diff --git a/.DS_Store b/.DS_Store index 965beae..d697bd1 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 997615c..514b288 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,4 +1,4 @@ -name: Build Documentation for Read the Docs +name: Build and Deploy Documentation on: push: @@ -7,47 +7,36 @@ on: branches: [ main ] jobs: - build-docs: + build-deploy-docs: runs-on: ubuntu-latest steps: - name: Checkout Repository uses: actions/checkout@v3 with: - fetch-depth: 0 + fetch-depth: 0 - - name: Set up Python + - name: Set up Python 3.10 uses: actions/setup-python@v4 with: - python-version: '3.8' + python-version: '3.10' check-latest: true - - name: List repository contents - run: ls -la - - - name: List docs directory contents - run: ls -la docs/ - - - name: Run setup-env.sh (Non-Interactive) - env: - INSTALL_TYPE: 1 # cpu only - INSTALL_DEV: y # dev dependencies - run: | - chmod +x scripts/setup-env.sh - ./scripts/setup-env.sh - - # Build and install the package - - name: Build and install package + - name: Install Dependencies and Set Up Environment run: | - source .venv/bin/activate - pip install -e . + python -m pip install --upgrade pip + python fast-install.py --cuda --cuda-version 12.1 --dev + shell: bash - name: Build Documentation run: | - source .venv/bin/activate + source ./bioneuralnet-env/bin/activate + mkdir -p docs/build/html sphinx-build -b html docs/source/ docs/build/html/ - - - name: Validate Documentation Build - run: | - echo "Documentation build completed successfully. Files are located in docs/build/html/" - ls -R docs/build/html/ + shell: bash + + - name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./docs/build/html diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index a761187..57edd32 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -10,8 +10,8 @@ jobs: build: strategy: matrix: - os: [ubuntu-latest] - python-version: ['3.8'] + os: [ubuntu-latest, macos-latest, windows-latest] + python-version: ['3.10', '3.11'] runs-on: ${{ matrix.os }} @@ -25,41 +25,55 @@ jobs: python-version: ${{ matrix.python-version }} check-latest: true - - name: Install R - uses: r-lib/actions/setup-r@v2 - - - name: List scripts directory contents - run: ls -la scripts/ + - name: Cache pip dependencies + uses: actions/cache@v3 + with: + path: | + ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt', '**/scripts/requirements-dev.txt', 'fast-install.py') }} + restore-keys: | + ${{ runner.os }}-pip- - - name: Install R and its dependencies + - name: Install dependencies using fast-install.py (Unix) + if: matrix.os != 'windows-latest' run: | - chmod +x scripts/setup-R.sh - ./scripts/setup-R.sh + chmod +x fast-install.py + ./fast-install.py --cuda --cuda-version 12.1 --dev + shell: bash - - name: Run setup-env.sh (Non-Interactive) - env: - INSTALL_TYPE: 1 #use cpu - INSTALL_DEV: y #install dev dependencies + - name: Install dependencies using fast-install.py (Windows) + if: matrix.os == 'windows-latest' run: | - chmod +x scripts/setup-env.sh - ./scripts/setup-env.sh - - - name: Verify installed Python packages + python fast-install.py --cuda --cuda-version 12.1 --dev + shell: powershell + + - name: Verify installed Python packages (Unix) + if: matrix.os != 'windows-latest' run: | - source .venv/bin/activate + source ./bioneuralnet-env/bin/activate pip list + shell: bash + - name: Verify installed Python packages (Windows) + if: matrix.os == 'windows-latest' + run: | + .\bioneuralnet-env\Scripts\Activate.ps1 + pip list + shell: powershell - - name: Verify R installation and WGCNA - shell: bash + - name: Run tests with pytest (Unix) + if: matrix.os != 'windows-latest' run: | - R --version - Rscript -e "library(WGCNA); cat('WGCNA loaded successfully')" + source ./bioneuralnet-env/bin/activate + pytest --cov=bioneuralnet --cov-report=xml tests/ + shell: bash - - name: Run tests with pytest + - name: Run tests with pytest (Windows) + if: matrix.os == 'windows-latest' run: | - source .venv/bin/activate + .\bioneuralnet-env\Scripts\Activate.ps1 pytest --cov=bioneuralnet --cov-report=xml tests/ + shell: powershell - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 diff --git a/.github/workflows/readthedocs.yml b/.github/workflows/readthedocs.yml new file mode 100644 index 0000000..b001401 --- /dev/null +++ b/.github/workflows/readthedocs.yml @@ -0,0 +1,18 @@ +version: 2 + +build: + os: ubuntu-20.04 + tools: + python: "3.10" + +python: + install: + - method: pip + path: . + - requirements: requirements.txt + - requirements: scripts/requirements-dev.txt + - path: . + command: python fast-install.py --dev + +sphinx: + configuration: docs/source/conf.py diff --git a/.gitignore b/.gitignore index 0f53ff9..f8ec485 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,8 @@ ENV/ env.bak/ venv.bak/ .pytest_cache +release.md +bioneuralnet.egg-info # Sphinx documentation build docs/build/ @@ -20,6 +22,7 @@ env/ env.bak/ venv.bak/ .venv/ +bioneuralnet-env/ # IDE and editor directories .vscode/ @@ -51,3 +54,7 @@ test_report/ # Other *.bak *.tmp +test_output/ +dpmon_output_* +lib/ +.DS_Store diff --git a/LICENSE b/LICENSE index 4d81188..847c0bf 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2024 Big Data Management and Mining Laboratory +Copyright (c) [2024] [Big Data Management and Mining Laboratory] Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index a0c0691..73c5c1d 100644 --- a/README.md +++ b/README.md @@ -3,188 +3,250 @@ ![License](https://img.shields.io/badge/license-MIT-blue.svg) ![PyPI](https://img.shields.io/pypi/v/bioneuralnet) ![Python Versions](https://img.shields.io/pypi/pyversions/bioneuralnet) - -## Table of Contents -- [Overview](#overview) -- [Framework Overview](#framework-overview) -- [Installation](#installation) -- [Documentation & Examples](#documentation--examples) -- [Acknowledgements](#acknowledgements) -- [Testing](#testing) -- [Contributing](#contributing) -- [License & Contact](#license--contact) - ---- +![GitHub Issues](https://img.shields.io/github/issues/UCD-BDLab/BioNeuralNet) +![GitHub Contributors](https://img.shields.io/github/contributors/UCD-BDLab/BioNeuralNet) ## Overview -**BioNeuralNet** is a Python-based framework designed to integrate and analyze multi-omics data through advanced neural network embeddings. It streamlines complex workflows, enabling researchers to transform high-dimensional biological data into meaningful insights for biomarker discovery and precision medicine. - ---- +**BioNeuralNet** is a Python-based framework designed to integrate and analyze multi-omics data through advanced neural network embeddings. It streamlines complex workflows, enabling researchers to transform high-dimensional biological data into meaningful insights for biomarker discovery, disease prediction, and more. -## Framework Overview +![BioNeuralNet Workflow](assets/BioNeuralNet.png) -![BioNeuralNet Workflow](assets/bioneuralnet1.png) +## Key Features BioNeuralNet encompasses five core components: -1. **Graph Construction**: Build multi-omics networks using WGCNA, SmCCNet, or import existing networks. -2. **Graph Clustering**: Apply hierarchical, PageRank, or Louvain clustering to identify functional modules. -3. **Graph Embedding**: Generate embeddings with Graph Neural Networks (GNNs) or Node2Vec. -4. **Subject Representation**: Integrate embeddings into omics data for enhanced subject-level features. -5. **Disease Prediction (DPMON)**: Utilize embeddings in predictive models for accurate disease classification. - -**Note:** BioNeuralNet also supports static and dynamic network visualizations for intuitive exploration of network structures and results. +1. **Graph Construction**: Build multi-omics networks using methods like Weighted Gene Co-expression Network Analysis (**WGCNA**), Sparse Multiple Canonical Correlation Network (**SmCCNet**), or import existing networks. +2. **Graph Clustering**: Identify functional modules and communities using hierarchical clustering, PageRank, or Louvain clustering algorithms. +3. **Network Embedding**: Generate embeddings with **Graph Neural Networks (GNNs)** or **Node2Vec**, simplifying high-dimensional data into lower-dimensional representations. +4. **Subject Representation**: Integrate embeddings into omics data to enrich subject-level features, enhancing the dataset for downstream analyses. +5. **Downstream Tasks**: Perform advanced analyses like disease prediction using network information. Seamlessly integrate your own downstream tasks by leveraging existing components. ---- +**Additional Features:** +- Supports static and dynamic network visualizations for intuitive exploration of network structures and results. +- CUDA-based GPU acceleration for enhanced computational performance. ## Installation -### Clone the Repository -Follow these steps to set up BioNeuralNet: +### Quick Installation via pip -```bash -git clone https://github.com/UCD-BDLab/BioNeuralNet.git -cd BioNeuralNet -``` +Ensure you have Python 3.10 or 3.11 installed. Then, install BioNeuralNet using pip: -### Fast Install Script -Run the installation script for guided setup (CPU or CUDA-enabled): ```bash -cd scripts -python3 fast-install.py +pip install bioneuralnet==0.1.0b1 ``` -### Alternative Pip Installation -Install directly using pip: -```bash -pip install bioneuralnet -``` +### Installation with Dependencies + +BioNeuralNet relies on various Python and R packages for data processing and graph generation. Use the provided `fast-install.py` script for an automated setup. + +1. **Clone the Repository:** + + ```bash + git clone https://github.com/UCD-BDLab/BioNeuralNet.git + cd BioNeuralNet + ``` + +2. **Run the Fast Install Script:** + + ```bash + python3 scripts/fast-install.py + ``` + + ![Installation](assets/terminal.png) + + **Installation Options:** + - **GPU-acceleration**: Install GPU-accelerated PyTorch by specifying the `--cuda` argument. To use a specific CUDA version (e.g., 12.1), include the `--cuda-version` argument: + + ```bash + python3 scripts/fast-install.py --cuda --cuda-version 12.1 + ``` + + - **Development Dependencies**: Install additional dependencies for testing, documentation, or contributing with the `--dev` argument: + + ```bash + python3 scripts/fast-install.py --dev + ``` + + - **Combined Installation**: Install both CUDA support and development dependencies: + + ```bash + python3 scripts/fast-install.py --cuda --cuda-version 11.8 --dev + ``` -### Optional R Dependencies -For graph construction using WGCNA or SmCCNet: -```r -install.packages(c("dplyr", "SmCCNet", "WGCNA")) + **Available Arguments:** + - `--cuda`: Enable GPU-accelerated PyTorch installation. + - `--cuda-version`: Specify a CUDA version (11.8, 12.1, or 12.4). + - `--dev`: Install development dependencies. + +### More Installation Methods + +For alternative installation methods and detailed step-by-step instructions (e.g., using .zip downloads instead of git clone), visit the[Installation Guide](https://bioneuralnet.readthedocs.io/en/latest/install.html). + +## Quick Example + +Here's a quick example demonstrating how to generate a network representation using **SmCCNet** and apply it to disease prediction using **DPMON**: + +```python +import pandas as pd +from bioneuralnet.graph_generation import SmCCNet +from bioneuralnet.downstream_task import DPMON + +# Step 1: Load Multi-Omics Dataset +omics_data = pd.read_csv('omics_data.csv', index_col=0) +phenotype_data = pd.read_csv('phenotype_data.csv', index_col=0) + +# Step 2: Generate a network using SmCCNet +smccnet = SmCCNet(phenotype_data=phenotype_data, omics_data=omics_data) +adjacency_matrix = smccnet.run() +print("Multi-Omics Network generated.") + +# Step 3: Enhanced disease prediction using network information with DPMON +dpmon = DPMON(adjacency_matrix=adjacency_matrix, omics_list=[omics_data], phenotype_data=phenotype_data) +predictions = dpmon.run() +print("Disease phenotype predictions:") +print(predictions) ``` ---- +**Output:** +- **Adjacency Matrix**: The network representation of the multi-omics data. +- **Predictions**: Disease phenotype predictions for each sample. + +![SmCCNet_DPMON](assets/Overview.png) ## Documentation & Examples -Comprehensive documentation, tutorials, and example workflows are available in the [`docs/`](./docs/) directory. To build and view the documentation locally: +Comprehensive documentation, tutorials, and example workflows are available at [BioNeuralNet - Read The Docs](https://bioneuralnet.readthedocs.io/en/latest/index.html). -```bash -cd docs -sphinx-build -b html source/ build/html -open build/html/index.html -``` +**What’s Included:** +- Detailed pipeline overviews +- Step-by-step tutorials +- API references +- End-to-end workflow examples -**What’s included:** -- Detailed pipeline overviews -- Step-by-step tutorials -- API references -- End-to-end workflow examples +Explore example scripts in the `turorials/` tab. -Explore example scripts in the `examples/` directory. +## Frequently Asked Questions (FAQ) ---- +For a comprehensive list of FAQs, visit the [FAQ](https://bioneuralnet.readthedocs.io/en/latest/faq.html) section in the documentation. -## Acknowledgements +### Highlights: -BioNeuralNet leverages several open-source libraries and tools: +- **What is BioNeuralNet?** +- **Key components of BioNeuralNet** +- **Installation instructions** +- **GPU acceleration** +- **Contribution guidelines** +- **Reporting issues and requesting features** +- **License information** +- **Acknowledgments** -- [SmCCNet on CRAN](https://cran.r-project.org/package=SmCCNet) -- [WGCNA on CRAN](https://cran.r-project.org/package=WGCNA) -- [Node2Vec on GitHub](https://github.com/aditya-grover/node2vec) -- [PyTorch](https://pytorch.org/) -- [PyTorch Geometric](https://github.com/pyg-team/pytorch_geometric) -- [dplyr on CRAN](https://cran.r-project.org/package=dplyr) -- [Pytest](https://pytest.org/) -- [Pre-commit](https://github.com/pre-commit/pre-commit) +## Acknowledgements -We extend our gratitude to all contributors and open-source communities that made BioNeuralNet possible. +BioNeuralNet leverages several open-source libraries and tools that are integral to its functionality: ---- +- [SmCCNet on CRAN](https://cran.r-project.org/package=SmCCNet) +- [WGCNA on CRAN](https://cran.r-project.org/package=WGCNA) +- [Node2Vec on GitHub](https://github.com/aditya-grover/node2vec) +- [PyTorch](https://pytorch.org/) +- [PyTorch Geometric](https://github.com/pyg-team/pytorch_geometric) +- [dplyr on CRAN](https://cran.r-project.org/package=dplyr) +- [Pytest](https://pytest.org/) +- [Pre-commit](https://github.com/pre-commit/pre-commit) +- [Sphinx](https://www.sphinx-doc.org/) +- [Black](https://black.readthedocs.io/) +- [Flake8](https://flake8.pycqa.org/) + +We extend our gratitude to all contributors and open-source communities that have made BioNeuralNet possible. ## Testing -BioNeuralNet ensures reliability through automated tests and CI workflows. +BioNeuralNet ensures reliability through automated tests and Continuous Integration (CI) workflows. -### Running Tests Locally +### Running Tests Locally + +1. **Install Development Dependencies:** -1. **Install Development Dependencies** ```bash pip install -r requirements-dev.txt ``` -2. **Run All Tests** +2. **Run All Tests:** + ```bash pytest ``` -3. **View Coverage Reports** +3. **View Coverage Reports:** + ```bash pytest --cov=bioneuralnet --cov-report=html tests/ - open htmlcov/index.html + open htmlcov/index.html ``` -### Continuous Integration -GitHub Actions ensure all commits and pull requests: -- Install dependencies -- Run the test suite -- Enforce code quality and generate coverage reports +### Continuous Integration ---- +GitHub Actions ensure that all commits and pull requests: +- Install dependencies +- Run the test suite +- Enforce code quality and generate coverage reports ## Contributing -We welcome contributions! To contribute: +We welcome contributions! To contribute: + +1. **Fork the Repository:** -1. **Fork the Repository** ```bash git clone https://github.com/UCD-BDLab/BioNeuralNet.git cd BioNeuralNet ``` -2. **Create a Feature Branch** +2. **Create a Feature Branch:** + ```bash git checkout -b feature/your-feature-name ``` -3. **Install Development Dependencies** +3. **Install Development Dependencies:** + ```bash ./setup.sh ``` -4. **Make Your Changes** - - Follow PEP 8 standards. - - Add or update tests. - - Update relevant documentation. +4. **Make Your Changes:** + - Implement new features. + - Add or update tests. + - Document your changes. + +5. **Run Tests:** -5. **Run Tests** ```bash pytest ``` -6. **Commit Changes** +6. **Commit Changes:** + ```bash git add . git commit -m "Add feature XYZ" ``` -7. **Push and Open a Pull Request** +7. **Push and Open a Pull Request:** + ```bash git push origin feature/your-feature-name ``` ---- +For detailed guidelines, refer to the [FAQ](https://bioneuralnet.readthedocs.io/en/latest/faq.html) section in the documentation. ## License & Contact -- **License**: [MIT License](LICENSE) -- **Contact**: +- **License:** [MIT License](https://github.com/UCD-BDLab/BioNeuralNet/blob/main/LICENSE) + +- **Contact:** For questions, issues, or feature requests, please open an issue on the [GitHub repository](https://github.com/UCD-BDLab/BioNeuralNet/issues) or contact the maintainer at **vicente.ramos@ucdenver.edu**. --- -For an in-depth look at BioNeuralNet, refer to the [Documentation](./docs/) and example workflows in the `examples/` directory. +For an in-depth look at BioNeuralNet, refer to the [Documentation](https://bioneuralnet.readthedocs.io/en/latest/index.html) and example workflows in the `turorial/` directory. diff --git a/assets/BioNeuralNet.png b/assets/BioNeuralNet.png new file mode 100644 index 0000000..a308430 Binary files /dev/null and b/assets/BioNeuralNet.png differ diff --git a/assets/BioNeuralNet1.png b/assets/BioNeuralNet1.png deleted file mode 100644 index d4c8e09..0000000 Binary files a/assets/BioNeuralNet1.png and /dev/null differ diff --git a/assets/DPMON.png b/assets/DPMON.png index 547bc7c..66be718 100644 Binary files a/assets/DPMON.png and b/assets/DPMON.png differ diff --git a/assets/Overview.png b/assets/Overview.png new file mode 100644 index 0000000..d4e920b Binary files /dev/null and b/assets/Overview.png differ diff --git a/assets/SubjectRepresentation1.png b/assets/SubjectRepresentation.png similarity index 100% rename from assets/SubjectRepresentation1.png rename to assets/SubjectRepresentation.png diff --git a/assets/repo.png b/assets/repo.png new file mode 100644 index 0000000..da7ba71 Binary files /dev/null and b/assets/repo.png differ diff --git a/assets/terminal.png b/assets/terminal.png new file mode 100644 index 0000000..4547c91 Binary files /dev/null and b/assets/terminal.png differ diff --git a/assets/terminal2.png b/assets/terminal2.png new file mode 100644 index 0000000..5471c86 Binary files /dev/null and b/assets/terminal2.png differ diff --git a/assets/tests.png b/assets/tests.png new file mode 100644 index 0000000..fe7d40f Binary files /dev/null and b/assets/tests.png differ diff --git a/bioneuralnet.egg-info/PKG-INFO b/bioneuralnet.egg-info/PKG-INFO deleted file mode 100644 index 76a46c3..0000000 --- a/bioneuralnet.egg-info/PKG-INFO +++ /dev/null @@ -1,213 +0,0 @@ -Metadata-Version: 2.1 -Name: bioneuralnet -Version: 0.1.0 -Summary: A framework designed to analyze biological data through a series of computational steps. Capable of taking a network to a lower dimensional space. Opening the door for further analysis. -Home-page: https://github.com/UCD-BDLab/BioNeuralNet -Author: Vicente Ramos -Author-email: vicente.ramos@ucdenver.edu -License: UNKNOWN -Project-URL: Bug Reports, https://github.com/UCD-BDLab/BioNeuralNet/issues -Project-URL: Source, https://github.com/UCD-BDLab/BioNeuralNet -Platform: UNKNOWN -Classifier: Programming Language :: Python :: 3 -Classifier: License :: OSI Approved :: MIT License -Classifier: Operating System :: OS Independent -Requires-Python: >=3.8 -Description-Content-Type: text/markdown -Provides-Extra: cpu -Provides-Extra: cuda117 -Provides-Extra: dev -License-File: LICENSE - -# BioNeuralNet: A Graph-Based Multi-Omics Integration and Embedding Framework for Advanced analysis - -![License](https://img.shields.io/badge/license-MIT-blue.svg) -![PyPI](https://img.shields.io/pypi/v/bioneuralnet) -![Python Versions](https://img.shields.io/pypi/pyversions/bioneuralnet) - -## Table of Contents -- [Overview](#overview) -- [Framework Overview](#framework-overview) -- [Installation](#installation) -- [Documentation & Examples](#documentation--examples) -- [Acknowledgements](#acknowledgements) -- [Testing](#testing) -- [Contributing](#contributing) -- [License & Contact](#license--contact) - ---- - -## Overview - -**BioNeuralNet** is a Python-based framework designed to integrate and analyze multi-omics data through advanced neural network embeddings. It streamlines complex workflows, enabling researchers to transform high-dimensional biological data into meaningful insights for biomarker discovery and precision medicine. - ---- - -## Framework Overview - -![BioNeuralNet Workflow](assets/bioneuralnet1.png) - -BioNeuralNet encompasses five core components: - -1. **Graph Construction**: Build multi-omics networks using WGCNA, SmCCNet, or import existing networks. -2. **Graph Clustering**: Apply hierarchical, PageRank, or Louvain clustering to identify functional modules. -3. **Graph Embedding**: Generate embeddings with Graph Neural Networks (GNNs) or Node2Vec. -4. **Subject Representation**: Integrate embeddings into omics data for enhanced subject-level features. -5. **Disease Prediction (DPMON)**: Utilize embeddings in predictive models for accurate disease classification. - -**Note:** BioNeuralNet also supports static and dynamic network visualizations for intuitive exploration of network structures and results. - ---- - -## Installation - -### Clone the Repository -Follow these steps to set up BioNeuralNet: - -```bash -git clone https://github.com/UCD-BDLab/BioNeuralNet.git -cd BioNeuralNet -``` - -### Fast Install Script -Run the installation script for guided setup (CPU or CUDA-enabled): -```bash -cd scripts -python3 fast-install.py -``` - -### Alternative Pip Installation -Install directly using pip: -```bash -pip install bioneuralnet -``` - -### Optional R Dependencies -For graph construction using WGCNA or SmCCNet: -```r -install.packages(c("dplyr", "SmCCNet", "WGCNA")) -``` - ---- - -## Documentation & Examples - -Comprehensive documentation, tutorials, and example workflows are available in the [`docs/`](./docs/) directory. To build and view the documentation locally: - -```bash -cd docs -sphinx-build -b html source/ build/html -open build/html/index.html -``` - -**What’s included:** -- Detailed pipeline overviews -- Step-by-step tutorials -- API references -- End-to-end workflow examples - -Explore example scripts in the `examples/` directory. - ---- - -## Acknowledgements - -BioNeuralNet leverages several open-source libraries and tools: - -- [SmCCNet on CRAN](https://cran.r-project.org/package=SmCCNet) -- [WGCNA on CRAN](https://cran.r-project.org/package=WGCNA) -- [Node2Vec on GitHub](https://github.com/aditya-grover/node2vec) -- [PyTorch](https://pytorch.org/) -- [PyTorch Geometric](https://github.com/pyg-team/pytorch_geometric) -- [dplyr on CRAN](https://cran.r-project.org/package=dplyr) -- [Pytest](https://pytest.org/) -- [Pre-commit](https://github.com/pre-commit/pre-commit) - -We extend our gratitude to all contributors and open-source communities that made BioNeuralNet possible. - ---- - -## Testing - -BioNeuralNet ensures reliability through automated tests and CI workflows. - -### Running Tests Locally - -1. **Install Development Dependencies** - ```bash - pip install -r requirements-dev.txt - ``` - -2. **Run All Tests** - ```bash - pytest - ``` - -3. **View Coverage Reports** - ```bash - pytest --cov=bioneuralnet --cov-report=html tests/ - open htmlcov/index.html - ``` - -### Continuous Integration -GitHub Actions ensure all commits and pull requests: -- Install dependencies -- Run the test suite -- Enforce code quality and generate coverage reports - ---- - -## Contributing - -We welcome contributions! To contribute: - -1. **Fork the Repository** - ```bash - git clone https://github.com/UCD-BDLab/BioNeuralNet.git - cd BioNeuralNet - ``` - -2. **Create a Feature Branch** - ```bash - git checkout -b feature/your-feature-name - ``` - -3. **Install Development Dependencies** - ```bash - ./setup.sh - ``` - -4. **Make Your Changes** - - Follow PEP 8 standards. - - Add or update tests. - - Update relevant documentation. - -5. **Run Tests** - ```bash - pytest - ``` - -6. **Commit Changes** - ```bash - git add . - git commit -m "Add feature XYZ" - ``` - -7. **Push and Open a Pull Request** - ```bash - git push origin feature/your-feature-name - ``` - ---- - -## License & Contact - -- **License**: [MIT License](LICENSE) -- **Contact**: - For questions, issues, or feature requests, please open an issue on the [GitHub repository](https://github.com/UCD-BDLab/BioNeuralNet/issues) or contact the maintainer at **vicente.ramos@ucdenver.edu**. - ---- - -For an in-depth look at BioNeuralNet, refer to the [Documentation](./docs/) and example workflows in the `examples/` directory. - - diff --git a/bioneuralnet.egg-info/SOURCES.txt b/bioneuralnet.egg-info/SOURCES.txt deleted file mode 100644 index 5b87409..0000000 --- a/bioneuralnet.egg-info/SOURCES.txt +++ /dev/null @@ -1,282 +0,0 @@ -LICENSE -MANIFEST.in -README.md -requirements.txt -setup.cfg -setup.py -assets/BioNeuralNet1.png -assets/DPMON.png -assets/SubjectRepresentation1.png -bioneuralnet/__init__.py -bioneuralnet.egg-info/PKG-INFO -bioneuralnet.egg-info/SOURCES.txt -bioneuralnet.egg-info/dependency_links.txt -bioneuralnet.egg-info/requires.txt -bioneuralnet.egg-info/top_level.txt -bioneuralnet/analysis/__init__.py -bioneuralnet/analysis/base_feature_selector.py -bioneuralnet/analysis/correlation_analysis.py -bioneuralnet/analysis/dynamic_visualization.py -bioneuralnet/analysis/feature_selector.py -bioneuralnet/analysis/static_visualization.py -bioneuralnet/clustering/__init__.py -bioneuralnet/clustering/hierarchical.py -bioneuralnet/clustering/pagerank.py -bioneuralnet/clustering/hybrid_clustering/Hybrid_Louvain.py -bioneuralnet/clustering/hybrid_clustering/Manual_Louvain.py -bioneuralnet/clustering/hybrid_clustering/__init__.py -bioneuralnet/clustering/hybrid_clustering/main.py -bioneuralnet/clustering/hybrid_clustering/pagerank.py -bioneuralnet/graph_generation/__init__.py -bioneuralnet/graph_generation/smccnet.py -bioneuralnet/graph_generation/wgcna.py -bioneuralnet/integrated_tasks/__init__.py -bioneuralnet/integrated_tasks/dpmon.py -bioneuralnet/network_embedding/__init__.py -bioneuralnet/network_embedding/gnn_embedding.py -bioneuralnet/network_embedding/gnn_models.py -bioneuralnet/network_embedding/node2vec.py -bioneuralnet/subject_representation/__init__.py -bioneuralnet/subject_representation/subject_representation.py -bioneuralnet/utils/__init__.py -bioneuralnet/utils/config.yml -bioneuralnet/utils/config_loader.py -bioneuralnet/utils/data_utils.py -bioneuralnet/utils/file_helpers.py -bioneuralnet/utils/logger.py -bioneuralnet/utils/path_utils.py -docs/.DS_Store -docs/README.md -docs/build/html/.buildinfo -docs/build/html/api_reference.html -docs/build/html/faq.html -docs/build/html/genindex.html -docs/build/html/hybrid_example_1.html -docs/build/html/hybrid_example_2.html -docs/build/html/hybrid_example_3.html -docs/build/html/index.html -docs/build/html/installation.html -docs/build/html/objects.inv -docs/build/html/py-modindex.html -docs/build/html/search.html -docs/build/html/searchindex.js -docs/build/html/tutorials.html -docs/build/html/usage.html -docs/build/html/.doctrees/api_reference.doctree -docs/build/html/.doctrees/environment.pickle -docs/build/html/.doctrees/faq.doctree -docs/build/html/.doctrees/hybrid_example_1.doctree -docs/build/html/.doctrees/hybrid_example_2.doctree -docs/build/html/.doctrees/hybrid_example_3.doctree -docs/build/html/.doctrees/index.doctree -docs/build/html/.doctrees/installation.doctree -docs/build/html/.doctrees/tutorials.doctree -docs/build/html/.doctrees/usage.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.analysis.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.analysis.dynamic_visualization.DynamicVisualizer.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.analysis.feature_selector.FeatureSelector.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.analysis.static_visualization.StaticVisualizer.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.clustering.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.clustering.hybrid_clustering.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.graph_generation.SmCCNet.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.graph_generation.WGCNA.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.graph_generation.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.integrated_tasks.DPMON.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.integrated_tasks.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.network_embedding.GNNEmbedding.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.network_embedding.Node2VecEmbedding.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.network_embedding.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.subject_representation.GraphEmbedding.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.subject_representation.SubjectRepresentationEmbedding.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.subject_representation.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.utils.data_utils.combine_omics_data.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.utils.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.utils.file_helpers.find_files.doctree -docs/build/html/.doctrees/_autosummary/bioneuralnet.utils.path_utils.validate_paths.doctree -docs/build/html/.doctrees/_autosummary/modules.doctree -docs/build/html/_autosummary/bioneuralnet.analysis.dynamic_visualization.DynamicVisualizer.html -docs/build/html/_autosummary/bioneuralnet.analysis.feature_selector.FeatureSelector.html -docs/build/html/_autosummary/bioneuralnet.analysis.html -docs/build/html/_autosummary/bioneuralnet.analysis.static_visualization.StaticVisualizer.html -docs/build/html/_autosummary/bioneuralnet.clustering.html -docs/build/html/_autosummary/bioneuralnet.clustering.hybrid_clustering.html -docs/build/html/_autosummary/bioneuralnet.graph_generation.SmCCNet.html -docs/build/html/_autosummary/bioneuralnet.graph_generation.WGCNA.html -docs/build/html/_autosummary/bioneuralnet.graph_generation.html -docs/build/html/_autosummary/bioneuralnet.html -docs/build/html/_autosummary/bioneuralnet.integrated_tasks.DPMON.html -docs/build/html/_autosummary/bioneuralnet.integrated_tasks.html -docs/build/html/_autosummary/bioneuralnet.network_embedding.GNNEmbedding.html -docs/build/html/_autosummary/bioneuralnet.network_embedding.Node2VecEmbedding.html -docs/build/html/_autosummary/bioneuralnet.network_embedding.html -docs/build/html/_autosummary/bioneuralnet.subject_representation.GraphEmbedding.html -docs/build/html/_autosummary/bioneuralnet.subject_representation.SubjectRepresentationEmbedding.html -docs/build/html/_autosummary/bioneuralnet.subject_representation.html -docs/build/html/_autosummary/bioneuralnet.utils.data_utils.combine_omics_data.html -docs/build/html/_autosummary/bioneuralnet.utils.file_helpers.find_files.html -docs/build/html/_autosummary/bioneuralnet.utils.html -docs/build/html/_autosummary/bioneuralnet.utils.path_utils.validate_paths.html -docs/build/html/_autosummary/modules.html -docs/build/html/_images/BioNeuralNet1.png -docs/build/html/_images/DPMON.png -docs/build/html/_images/SubjectRepresentation1.png -docs/build/html/_modules/index.html -docs/build/html/_modules/bioneuralnet/analysis/base_feature_selector.html -docs/build/html/_modules/bioneuralnet/analysis/dynamic_visualization.html -docs/build/html/_modules/bioneuralnet/analysis/feature_selector.html -docs/build/html/_modules/bioneuralnet/analysis/static_visualization.html -docs/build/html/_modules/bioneuralnet/clustering/hierarchical.html -docs/build/html/_modules/bioneuralnet/clustering/pagerank.html -docs/build/html/_modules/bioneuralnet/graph_generation/smccnet.html -docs/build/html/_modules/bioneuralnet/graph_generation/wgcna.html -docs/build/html/_modules/bioneuralnet/integrated_tasks/dpmon.html -docs/build/html/_modules/bioneuralnet/network_embedding/gnn_embedding.html -docs/build/html/_modules/bioneuralnet/network_embedding/gnn_models.html -docs/build/html/_modules/bioneuralnet/network_embedding/node2vec.html -docs/build/html/_modules/bioneuralnet/subject_representation/subject_representation.html -docs/build/html/_modules/bioneuralnet/utils/config_loader.html -docs/build/html/_modules/bioneuralnet/utils/data_utils.html -docs/build/html/_modules/bioneuralnet/utils/file_helpers.html -docs/build/html/_modules/bioneuralnet/utils/logger.html -docs/build/html/_modules/bioneuralnet/utils/path_utils.html -docs/build/html/_sources/api_reference.rst.txt -docs/build/html/_sources/faq.rst.txt -docs/build/html/_sources/hybrid_example_1.rst.txt -docs/build/html/_sources/hybrid_example_2.rst.txt -docs/build/html/_sources/hybrid_example_3.rst.txt -docs/build/html/_sources/index.rst.txt -docs/build/html/_sources/installation.rst.txt -docs/build/html/_sources/tutorials.rst.txt -docs/build/html/_sources/usage.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.analysis.dynamic_visualization.DynamicVisualizer.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.analysis.feature_selector.FeatureSelector.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.analysis.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.analysis.static_visualization.StaticVisualizer.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.clustering.hybrid_clustering.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.clustering.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.graph_generation.SmCCNet.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.graph_generation.WGCNA.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.graph_generation.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.integrated_tasks.DPMON.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.integrated_tasks.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.network_embedding.GNNEmbedding.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.network_embedding.Node2VecEmbedding.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.network_embedding.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.subject_representation.GraphEmbedding.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.subject_representation.SubjectRepresentationEmbedding.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.subject_representation.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.utils.data_utils.combine_omics_data.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.utils.file_helpers.find_files.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.utils.path_utils.validate_paths.rst.txt -docs/build/html/_sources/_autosummary/bioneuralnet.utils.rst.txt -docs/build/html/_sources/_autosummary/modules.rst.txt -docs/build/html/_static/BioNeuralNet1.png -docs/build/html/_static/DPMON.png -docs/build/html/_static/SubjectRepresentation1.png -docs/build/html/_static/_sphinx_javascript_frameworks_compat.js -docs/build/html/_static/basic.css -docs/build/html/_static/doctools.js -docs/build/html/_static/documentation_options.js -docs/build/html/_static/file.png -docs/build/html/_static/jquery.js -docs/build/html/_static/language_data.js -docs/build/html/_static/minus.png -docs/build/html/_static/plus.png -docs/build/html/_static/pygments.css -docs/build/html/_static/searchtools.js -docs/build/html/_static/sphinx_highlight.js -docs/build/html/_static/css/badge_only.css -docs/build/html/_static/css/theme.css -docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff -docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff2 -docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff -docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff2 -docs/build/html/_static/css/fonts/fontawesome-webfont.eot -docs/build/html/_static/css/fonts/fontawesome-webfont.svg -docs/build/html/_static/css/fonts/fontawesome-webfont.ttf -docs/build/html/_static/css/fonts/fontawesome-webfont.woff -docs/build/html/_static/css/fonts/fontawesome-webfont.woff2 -docs/build/html/_static/css/fonts/lato-bold-italic.woff -docs/build/html/_static/css/fonts/lato-bold-italic.woff2 -docs/build/html/_static/css/fonts/lato-bold.woff -docs/build/html/_static/css/fonts/lato-bold.woff2 -docs/build/html/_static/css/fonts/lato-normal-italic.woff -docs/build/html/_static/css/fonts/lato-normal-italic.woff2 -docs/build/html/_static/css/fonts/lato-normal.woff -docs/build/html/_static/css/fonts/lato-normal.woff2 -docs/build/html/_static/fonts/Lato/lato-bold.eot -docs/build/html/_static/fonts/Lato/lato-bold.ttf -docs/build/html/_static/fonts/Lato/lato-bold.woff -docs/build/html/_static/fonts/Lato/lato-bold.woff2 -docs/build/html/_static/fonts/Lato/lato-bolditalic.eot -docs/build/html/_static/fonts/Lato/lato-bolditalic.ttf -docs/build/html/_static/fonts/Lato/lato-bolditalic.woff -docs/build/html/_static/fonts/Lato/lato-bolditalic.woff2 -docs/build/html/_static/fonts/Lato/lato-italic.eot -docs/build/html/_static/fonts/Lato/lato-italic.ttf -docs/build/html/_static/fonts/Lato/lato-italic.woff -docs/build/html/_static/fonts/Lato/lato-italic.woff2 -docs/build/html/_static/fonts/Lato/lato-regular.eot -docs/build/html/_static/fonts/Lato/lato-regular.ttf -docs/build/html/_static/fonts/Lato/lato-regular.woff -docs/build/html/_static/fonts/Lato/lato-regular.woff2 -docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot -docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf -docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff -docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 -docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot -docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf -docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff -docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 -docs/build/html/_static/js/badge_only.js -docs/build/html/_static/js/theme.js -docs/build/html/_static/js/versions.js -docs/examples/hybrid_example_1.py -docs/examples/hybrid_example_2.py -docs/examples/hybrid_example_3.py -docs/source/api_reference.rst -docs/source/conf.py -docs/source/faq.rst -docs/source/hybrid_example_1.rst -docs/source/hybrid_example_2.rst -docs/source/hybrid_example_3.rst -docs/source/index.rst -docs/source/installation.rst -docs/source/tutorials.rst -docs/source/usage.rst -docs/source/_autosummary/bioneuralnet.analysis.rst -docs/source/_autosummary/bioneuralnet.clustering.hybrid_clustering.rst -docs/source/_autosummary/bioneuralnet.clustering.rst -docs/source/_autosummary/bioneuralnet.graph_generation.rst -docs/source/_autosummary/bioneuralnet.integrated_tasks.rst -docs/source/_autosummary/bioneuralnet.network_embedding.rst -docs/source/_autosummary/bioneuralnet.rst -docs/source/_autosummary/bioneuralnet.subject_representation.rst -docs/source/_autosummary/bioneuralnet.utils.rst -docs/source/_autosummary/modules.rst -docs/source/_static/BioNeuralNet1.png -docs/source/_static/DPMON.png -docs/source/_static/SubjectRepresentation1.png -examples/dpmon_example.py -examples/dynamic_visualization_example.py -examples/feature_selector_example.py -examples/gnn_embedding_example.py -examples/hierarchical_example.py -examples/hybrid_example_1.py -examples/hybrid_example_2.py -examples/hybrid_example_3.py -examples/node2vec_example.py -examples/pagerank_example.py -examples/smccnet_example.py -examples/static_visualization_example.py -examples/subject_representation_example.py -examples/wgcna_example.py -scripts/fast-install.py -scripts/requirements-cpu.txt -scripts/requirements-dev.txt -scripts/requirements-gpu.txt -scripts/setup-R.bat -scripts/setup-R.sh -scripts/setup-env.sh \ No newline at end of file diff --git a/bioneuralnet.egg-info/dependency_links.txt b/bioneuralnet.egg-info/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/bioneuralnet.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/bioneuralnet.egg-info/requires.txt b/bioneuralnet.egg-info/requires.txt deleted file mode 100644 index f929c29..0000000 --- a/bioneuralnet.egg-info/requires.txt +++ /dev/null @@ -1,36 +0,0 @@ -torch==2.0.0 -torch_geometric>=2.0.0 -PyYAML>=5.4 -pandas>=1.0 -numpy>=1.18 -scikit-learn>=0.24 -node2vec>=0.4.1 -matplotlib>=3.3 -ray[tune]>=2.0 -tensorboardX>=2.5 -networkx>=2.5 -pyvis>=0.2 - -[cpu] -torch-scatter@ https://data.pyg.org/whl/torch-2.0.0+cpu-cp310-cp310-win_amd64.whl -torch-sparse@ https://data.pyg.org/whl/torch-2.0.0+cpu-cp310-cp310-win_amd64.whl - -[cuda117] -torch-scatter@ https://data.pyg.org/whl/torch-2.0.0+cu117-cp310-cp310-win_amd64.whl -torch-sparse@ https://data.pyg.org/whl/torch-2.0.0+cu117-cp310-cp310-win_amd64.whl - -[dev] -pytest>=6.0 -pytest-cov -pytest-mock -sphinx -sphinx_rtd_theme -sphinx-autosummary-accessors -sphinxcontrib-napoleon -flake8 -black -mypy -pre-commit -tox -setuptools>=42 -twine diff --git a/bioneuralnet.egg-info/top_level.txt b/bioneuralnet.egg-info/top_level.txt deleted file mode 100644 index c42074e..0000000 --- a/bioneuralnet.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -bioneuralnet diff --git a/bioneuralnet/__init__.py b/bioneuralnet/__init__.py index 8597847..b4c16d4 100644 --- a/bioneuralnet/__init__.py +++ b/bioneuralnet/__init__.py @@ -23,10 +23,10 @@ __version__: str = '0.1.0' # Import key classes and functions for easy access -from .network_embedding import GnnEmbedding +from .network_embedding import GNNEmbedding from .network_embedding import Node2VecEmbedding from .subject_representation import GraphEmbedding -from .integrated_tasks import DPMON +from .downstream_task import DPMON from .analysis import FeatureSelector from .analysis import StaticVisualizer from .analysis import DynamicVisualizer @@ -38,7 +38,7 @@ 'subject_representation', 'utils', '__version__', - 'GnnEmbedding', + 'GNNEmbedding', 'Node2VecEmbedding', 'GraphEmbedding', 'DPMON', diff --git a/bioneuralnet/analysis/dynamic_visualization.py b/bioneuralnet/analysis/dynamic_visualization.py index 77ee26c..b217eee 100644 --- a/bioneuralnet/analysis/dynamic_visualization.py +++ b/bioneuralnet/analysis/dynamic_visualization.py @@ -44,14 +44,11 @@ def generate_graph(self) -> nx.Graph: def visualize(self, G: nx.Graph): self.logger.info(f"Generating interactive visualization with layout: {self.layout}") - # Load the default template from pyvis/templates templates_dir = os.path.join(os.path.dirname(pyvis.__file__), 'templates') env = Environment(loader=FileSystemLoader(templates_dir)) template = env.get_template('template.html') net = Network(height=self.height, width=self.width, bgcolor=self.bgcolor, font_color=self.font_color, notebook=False) - - # Assign the loaded template to net.template net.template = template if self.layout == 'hierarchical': diff --git a/bioneuralnet/analysis/feature_selector.py b/bioneuralnet/analysis/feature_selector.py index e109c27..d707a73 100644 --- a/bioneuralnet/analysis/feature_selector.py +++ b/bioneuralnet/analysis/feature_selector.py @@ -1,13 +1,9 @@ -import os - import pandas as pd from sklearn.linear_model import LassoCV from sklearn.ensemble import RandomForestClassifier from sklearn.feature_selection import SelectKBest, f_classif - from ..utils.logger import get_logger - class FeatureSelector: """ FeatureSelector Class for Selecting Relevant Multi-Omics Features. diff --git a/bioneuralnet/clustering/hierarchical.py b/bioneuralnet/clustering/hierarchical.py index b2baf7d..54cce07 100644 --- a/bioneuralnet/clustering/hierarchical.py +++ b/bioneuralnet/clustering/hierarchical.py @@ -1,12 +1,10 @@ from typing import Dict, Any - import pandas as pd from sklearn.cluster import AgglomerativeClustering from sklearn.metrics import silhouette_score from sklearn.preprocessing import StandardScaler from ..utils.logger import get_logger - class HierarchicalClustering: """ HierarchicalClustering Class for Performing Agglomerative Hierarchical Clustering. @@ -74,7 +72,6 @@ def preprocess_data(self) -> None: try: if self.scale_data and self.scaler is not None: scaled_array = self.scaler.fit_transform(self.adjacency_matrix.values) - # Convert back to DataFrame with original index and columns self.scaled_feature_matrix = pd.DataFrame( scaled_array, index=self.adjacency_matrix.index, @@ -82,7 +79,6 @@ def preprocess_data(self) -> None: ) self.logger.info("Data has been scaled using StandardScaler.") else: - # Retain the original DataFrame self.scaled_feature_matrix = self.adjacency_matrix.copy() self.logger.info("Data scaling skipped.") except Exception as e: @@ -95,7 +91,6 @@ def run_clustering(self) -> None: Executes the hierarchical clustering algorithm. """ try: - # Update: Replace 'affinity' with 'metric' and ensure compatibility with 'ward' linkage metric = 'euclidean' if self.linkage == 'ward' else self.affinity model = AgglomerativeClustering( n_clusters=self.n_clusters, @@ -106,7 +101,6 @@ def run_clustering(self) -> None: self.labels = model.fit_predict(self.scaled_feature_matrix) self.logger.info("Hierarchical clustering completed.") - # Compute silhouette score if applicable if metric in ['euclidean', 'l1', 'l2', 'manhattan', 'cosine']: try: self.silhouette_avg = silhouette_score(self.scaled_feature_matrix, self.labels, metric=metric) @@ -118,7 +112,6 @@ def run_clustering(self) -> None: self.logger.warning(f"Silhouette score not computed for metric '{metric}'.") self.silhouette_avg = None - # Create a DataFrame with cluster labels self.cluster_labels_df = pd.DataFrame({ 'node': self.adjacency_matrix.index, 'cluster': self.labels @@ -151,10 +144,51 @@ def run(self) -> Dict[str, Any]: """ Runs the entire hierarchical clustering pipeline. - Returns: - Dict[str, Any]: Clustering results. + **Steps:** + + 1. **Preprocessing Data**: + - Prepares and formats the input data to be compatible with hierarchical clustering. + + 2. **Running Clustering**: + - Executes the hierarchical clustering algorithm (e.g., agglomerative clustering) to identify groups or modules in the data. + + 3. **Extracting Results**: + - Processes and formats clustering outputs, such as cluster assignments and dendrogram structures. + + **Returns**: Dict[str, Any] + + - A dictionary containing clustering results, including: + - Cluster assignments for each data point. + - Dendrogram structure for visualization. + - Metrics or statistics related to cluster quality. + + **Raises**: + + - **ValueError**: If input data is invalid or preprocessing fails. + - **Exception**: For any unforeseen issues during the clustering pipeline. + + **Notes**: + + - Ensure that the input data is properly normalized and formatted before running the clustering pipeline. + - Adjust clustering parameters like the linkage method or distance metric to fit the analysis. + + **Example**: + + .. code-block:: python + + cluster_pipeline = HierarchicalClustering(data) + results = cluster_pipeline.run() + print(results['clusters']) """ - self.preprocess_data() - self.run_clustering() - self.logger.info("Hierarchical clustering pipeline completed successfully.") - return self.get_results() + self.logger.info("Running Hierarchical Clustering workflow.") + + try: + self.preprocess_data() + self.run_clustering() + self.logger.info("Hierarchical clustering pipeline completed successfully.") + return self.get_results() + + except Exception as e: + self.logger.error(f"Error in Hierarchical Clustering: {e}") + raise + diff --git a/bioneuralnet/clustering/hybrid_clustering/HybridVertexPartition.cpp b/bioneuralnet/clustering/hybrid_clustering/HybridVertexPartition.cpp deleted file mode 100644 index 68f97d6..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/HybridVertexPartition.cpp +++ /dev/null @@ -1,433 +0,0 @@ -// -// Created by Mohamed Abdel-Hafiz on 10/7/21. -// - -#include "HybridVertexPartition.h" -#include - -#ifdef DEBUG -#include -using std::cerr; -using std::endl; -#endif - -HybridVertexPartition::HybridVertexPartition(Graph* graph, - vector const& membership) : - MutableVertexPartition(graph, - membership) -{ } - -HybridVertexPartition::HybridVertexPartition(Graph* graph) : - MutableVertexPartition(graph) -{ } - -HybridVertexPartition::HybridVertexPartition(Graph* graph, std::vector< std::vector > input_dataset, std::vector target, - double k1, double k2, double k3, double k4) : - MutableVertexPartition(graph), dataset(input_dataset), target(target), k1(k1), k2(k2), k3(k3), k4(k4) -{ -// igraph_t* rawGraph = this->get_graph()->get_igraph(); -//// for (int i=0; iget_graph()->vcount(); i++) { -//// igraph_real_t nodeName = VAN(rawGraph, "name", i); -//// printf("%d\n", nodeName); -//// } -// for (int i=0; iget_graph()->ecount(); i++) { -// printf("1\n"); -// printf("Null check: %d\n", rawGraph == NULL? 1 : 0); -// igraph_real_t edgeWeight = EAN(rawGraph, "weight", i); -// printf("2\n"); -// printf("%d\n", edgeWeight); -// } -// printf("3\n"); -// for (int i=0; i < this->_membership.size(); i++) { -// printf("%d\n", this->_membership[i]); -// } -// printf("Here4\n"); -// printf("%d\n", raw_dataset.size()); -//// this->dataset.reserve(raw_dataset.size()); -// printf("%d\n", this->n_communities()); -// this->dataset = std::vector< std::vector< std::vector > >(this->n_communities()); -// printf("%d\n", input_dataset.size()); -// printf("%d\n", this->dataset.size()); -// printf("Here5\n"); -// for (int i=0; idataset[i].push_back(input_dataset[i]); -// printf("Here8\n"); -// } -// printf("Here7\n"); -} - -HybridVertexPartition::HybridVertexPartition(Graph* graph, vector const& membership, - std::vector< std::vector > input_dataset, std::vector target, - double k1, double k2, double k3, double k4) : - MutableVertexPartition(graph, membership), dataset(input_dataset), target(target), k1(k1), k2(k2), k3(k3), k4(k4) -{ -// printf("Here1\n"); -// printf("%d\n%d\n", raw_dataset.size(), membership.size()); -//// this->dataset.reserve(raw_dataset.size()); -// this->dataset = std::vector< std::vector< std::vector > >(this->n_communities()); -// printf("%d\n", this->dataset.size()); -// for (int i=0; idataset[membership[i]].push_back(input_dataset[membership[i]]); -// } -// printf("Here3\n"); -} - -HybridVertexPartition::~HybridVertexPartition() -{ } - -HybridVertexPartition* HybridVertexPartition::create(Graph* graph) -{ - printf("Creating1\n"); - return new HybridVertexPartition(graph, this->dataset, this->target, this->k1, this->k2, this->k3, this->k4); - printf("Created\n"); -} - -HybridVertexPartition* HybridVertexPartition::create(Graph* graph, vector const& membership) -{ - printf("Creating2\n"); - return new HybridVertexPartition(graph, membership, this->dataset, this->target, this->k1, this->k2, this->k3, this->k4); - printf("Created\n"); -} - -/***************************************************************************** - Returns the difference in modularity if we move a node to a new community -*****************************************************************************/ -double HybridVertexPartition::diff_move(size_t v, size_t new_comm) -{ -#ifdef DEBUG - cerr << "double ModularityVertexPartition::diff_move(" << v << ", " << new_comm << ")" << endl; -#endif - size_t old_comm = this->_membership[v]; - double diff = 0.0; - double total_weight = this->graph->total_weight()*(2.0 - this->graph->is_directed()); - if (total_weight == 0.0) - return 0.0; - if (new_comm != old_comm) - { -#ifdef DEBUG - cerr << "\t" << "old_comm: " << old_comm << endl; -#endif - double w_to_old = this->weight_to_comm(v, old_comm); -#ifdef DEBUG - cerr << "\t" << "w_to_old: " << w_to_old << endl; -#endif - double w_from_old = this->weight_from_comm(v, old_comm); -#ifdef DEBUG - cerr << "\t" << "w_from_old: " << w_from_old << endl; -#endif - double w_to_new = this->weight_to_comm(v, new_comm); -#ifdef DEBUG - cerr << "\t" << "w_to_new: " << w_to_new << endl; -#endif - double w_from_new = this->weight_from_comm(v, new_comm); -#ifdef DEBUG - cerr << "\t" << "w_from_new: " << w_from_new << endl; -#endif - double k_out = this->graph->strength(v, IGRAPH_OUT); -#ifdef DEBUG - cerr << "\t" << "k_out: " << k_out << endl; -#endif - double k_in = this->graph->strength(v, IGRAPH_IN); -#ifdef DEBUG - cerr << "\t" << "k_in: " << k_in << endl; -#endif - double self_weight = this->graph->node_self_weight(v); -#ifdef DEBUG - cerr << "\t" << "self_weight: " << self_weight << endl; -#endif - double K_out_old = this->total_weight_from_comm(old_comm); -#ifdef DEBUG - cerr << "\t" << "K_out_old: " << K_out_old << endl; -#endif - double K_in_old = this->total_weight_to_comm(old_comm); -#ifdef DEBUG - cerr << "\t" << "K_in_old: " << K_in_old << endl; -#endif - double K_out_new = this->total_weight_from_comm(new_comm) + k_out; -#ifdef DEBUG - cerr << "\t" << "K_out_new: " << K_out_new << endl; -#endif - double K_in_new = this->total_weight_to_comm(new_comm) + k_in; -#ifdef DEBUG - cerr << "\t" << "K_in_new: " << K_in_new << endl; - cerr << "\t" << "total_weight: " << total_weight << endl; -#endif - double diff_old = (w_to_old - k_out*K_in_old/total_weight) + \ - (w_from_old - k_in*K_out_old/total_weight); -#ifdef DEBUG - cerr << "\t" << "diff_old: " << diff_old << endl; -#endif - double diff_new = (w_to_new + self_weight - k_out*K_in_new/total_weight) + \ - (w_from_new + self_weight - k_in*K_out_new/total_weight); -#ifdef DEBUG - cerr << "\t" << "diff_new: " << diff_new << endl; -#endif - diff = diff_new - diff_old; -#ifdef DEBUG - cerr << "\t" << "diff: " << diff << endl; -#endif - } -#ifdef DEBUG - cerr << "exit double ModularityVertexPartition::diff_move((" << v << ", " << new_comm << ")" << endl; - cerr << "return " << diff << endl << endl; -#endif - double m; - if (this->graph->is_directed()) - m = this->graph->total_weight(); - else - m = 2*this->graph->total_weight(); - -// double k1 = 0.1, k2 = 0.9; // Weights for correlation portion of quality measure -// double k3 = 0.5, k4 = 0.5; // Weights for correlation (k3) vs modularity (k4) in overall quality measure - double pearson_diff = 0; - try { - pearson_diff = this->calculate_correlation_diff(v, new_comm); -// printf("%f\n", pearson_diff); - } catch (const alglib::ap_error& e) { - printf("alglib::error: "); -// printf(e.msg.c_str()); - printf("\n"); - throw; - } - printf("k3: %f\tk4: %f\n", this->k3, this->k4); - printf("diff: %f\t p_diff: %f\t total: %f\n v: %d\t new_comm: %d\tN_Comm: %d\tmembership.size: %d\n", diff, pearson_diff, (this->k3*(diff/m)) + (this->k4*pearson_diff), v, new_comm, this->n_communities(), this->_membership.size()); - return (this->k3*(diff/m)) + (this->k4*pearson_diff); -} - - -/***************************************************************************** - Give the modularity of the partition. - - We here use the unscaled version of modularity, in other words, we don"t - normalise by the number of edges. -******************************************************************************/ -double HybridVertexPartition::quality() -{ -#ifdef DEBUG - cerr << "double ModularityVertexPartition::quality()" << endl; -#endif - double mod = 0.0; - double corr = 0.0; -// double k1 = 0.1, k2 = 0.9; // Weights for correlation portion of quality measure -// double k3 = 0.5, k4 = 0.5; // Weights for correlation (k3) vs modularity (k4) in overall quality measure - - printf("Test4\n"); - std::vector membership = this->membership(); - printf("Membership:\n"); - for (unsigned long i=0; i < membership.size(); i++) { - printf("%d\n", membership[i]); - } - printf("\\Membership\n"); - - double m; - if (this->graph->is_directed()) - m = this->graph->total_weight(); - else - m = 2*this->graph->total_weight(); - - if (m == 0) - return 0.0; - - for (size_t c = 0; c < this->n_communities(); c++) - { - double w = this->total_weight_in_comm(c); - double w_out = this->total_weight_from_comm(c); - double w_in = this->total_weight_to_comm(c); -#ifdef DEBUG - size_t csize = this->csize(c); - cerr << "\t" << "Comm: " << c << ", size=" << csize << ", w=" << w << ", w_out=" << w_out << ", w_in=" << w_in << "." << endl; -#endif - mod += w - w_out*w_in/((this->graph->is_directed() ? 1.0 : 4.0)*this->graph->total_weight()); - - // Calculating pearson correlation - std::vector members; - for (int i=0; i<_membership.size(); i++) { - if (this->_membership[i] == c) { - members.push_back(i); - } - } - - alglib::real_2d_array subset, V; - alglib::real_1d_array s2, pc, alg_target; - - subset.setlength(this->target.size(), members.size()); - for (int i=0; i node_ids = this->get_graph()->get_features(members[i]); - for (int j=0; jdataset[node_ids[j]].size(); j++) { - subset[k][i] = this->dataset[node_ids[j]][k]; - } - } - - V.setlength(members.size(), 1); - s2.setlength(1); - alglib::pcatruncatedsubspace(subset, this->dataset[0].size(), members.size(), 1, 0.0006, 100000, s2, V); - - pc.setlength(this->dataset[0].size()); - alg_target.setlength(this->target.size()); - for (int i=0; itarget.size(); i++) { - alg_target[i] = this->target[i]; - } - for (int i=0; idataset[0].size(); i++) { - pc[0] = 0; - for (int j=0; jgraph->is_directed())*mod; -#ifdef DEBUG - cerr << "exit double ModularityVertexPartition::quality()" << endl; - cerr << "return " << q/m << endl << endl; -#endif - - return (this->k3*(q/m)) + (this->k4*corr); -} - -double HybridVertexPartition::calculate_correlation_diff(size_t v, size_t new_comm) { -// printf("In diff func.\n"); - printf("Num comms: %d\n", this->get_graph()->get_features().size()); - size_t old_comm = this->_membership[v]; - std::vector old_members = std::vector(); - std::vector new_members = std::vector(); - for (int i=0; i < this->_membership.size(); i++) { - if (this->_membership[i] == old_comm) { - old_members.push_back(i); - } - if (this->_membership[i] == new_comm || i == v) { - new_members.push_back(i); - } - } - alglib::real_2d_array old_including, old_excluding, new_including, new_excluding; -// printf("\n\nStart\n"); -// printf("Dataset Size: %d\nFeature Size: %d\n", this->dataset.size(), this->dataset[v].size()); -// printf("Node: %d\nOld Community: %d, Size: %d\nNew Community: %d, Size: %d\n", v, old_comm, old_members.size(), new_comm, new_members.size()); - old_including.setlength(this->dataset[v].size(), old_members.size()); -// printf("Done."); - if (old_members.size() > 1) - old_excluding.setlength(this->dataset[v].size(), old_members.size() - 1); - new_including.setlength(this->dataset[v].size(), new_members.size()); - if (new_members.size() > 1) - new_excluding.setlength(this->dataset[v].size(), new_members.size() - 1); - int old_offset = 0, new_offset = 0; - for (int i=0; i node_ids = this->get_graph()->get_features(old_members[i]); -// printf("2\n"); - for (int j=0; jdataset[node_ids[j]].size(); k++) { -// printf("4\n"); - old_including[k][i] = this->dataset[node_ids[j]][k]; - if (old_members.size() > 1) { - if (old_members[i] != v) { - old_excluding[k][i - old_offset] = this->dataset[node_ids[j]][k]; - } else { - old_offset = 1; - } - } - } - } - } -// printf("5\n"); - for (int i=0; i node_ids = this->get_graph()->get_features(new_members[i]); -// printf("7\n"); - for (int j=0; jdataset[node_ids[j]].size(); k++) { -// printf("9\n"); - new_including[k][i] = this->dataset[node_ids[j]][k]; - if (new_members.size() > 1) { - if (new_members[i] != v) { - new_excluding[k][i - new_offset] = this->dataset[node_ids[j]][k]; - } else { - new_offset = 1; - } - } - } - } - } -// printf("10\n"); - alglib::real_1d_array s2_old_i, s2_old_e, s2_new_i, s2_new_e; - alglib::real_2d_array V_old_i, V_old_e, V_new_i, V_new_e; - s2_old_i.setlength(1); - if (old_members.size() > 1) - s2_old_e.setlength(1); - s2_new_i.setlength(1); - if (new_members.size() > 1) - s2_new_e.setlength(1); - V_old_i.setlength(old_members.size(), 1); - if (old_members.size() > 1) - V_old_e.setlength(old_members.size() - 1, 1); - V_new_i.setlength(new_members.size(), 1); - if (new_members.size() > 1) - V_new_e.setlength(new_members.size() - 1, 1); - - alglib::pcatruncatedsubspace(old_including, this->dataset[v].size(), old_members.size(), 1, 0.0006, 100000, s2_old_i, V_old_i); - if (old_members.size() > 1) - alglib::pcatruncatedsubspace(old_excluding, this->dataset[v].size(), old_members.size() - 1, 1, 0.0006, 100000, s2_old_e, V_old_e); - alglib::pcatruncatedsubspace(new_including, this->dataset[v].size(), new_members.size(), 1, 0.0006, 100000, s2_new_i, V_new_i); - if (new_members.size() > 1) - alglib::pcatruncatedsubspace(new_excluding, this->dataset[v].size(), new_members.size() - 1, 1, 0.0006, 100000, s2_new_e, V_new_e); - - alglib::real_1d_array alg_target, pc_old_i, pc_old_e, pc_new_i, pc_new_e; - alg_target.setlength(this->target.size()); - pc_old_i.setlength(this->dataset[v].size()); - if (old_members.size() > 1) - pc_old_e.setlength(this->dataset[v].size()); - pc_new_i.setlength(this->dataset[v].size()); - if (new_members.size() > 1) - pc_new_e.setlength(this->dataset[v].size()); - - for (int i=0; itarget.size(); i++) { - alg_target[i] = this->target[i]; - } - - for (int i=0; idataset[v].size(); i++) { - pc_old_i[i] = 0; - for (int j=0; j 1) { - for (int i = 0; i < this->dataset[v].size(); i++) { - pc_old_e[i] = 0; - for (int j = 0; j < old_members.size() - 1; j++) { - pc_old_e[i] += V_old_e(j, 0) * old_excluding(i, j); - } - } - } - for (int i=0; idataset[v].size(); i++) { - pc_new_i[i] = 0; - for (int j=0; j 1) { - for (int i = 0; i < this->dataset[v].size(); i++) { - pc_new_e[i] = 0; - for (int j = 0; j < new_members.size() - 1; j++) { - pc_new_e[i] += V_new_e(j, 0) * new_excluding(i, j); - } - } - } - - double p_old_i, p_old_e, p_new_i, p_new_e; - p_old_i = alglib::pearsoncorr2(pc_old_i, alg_target); - p_old_e = old_members.size() > 1 ? alglib::pearsoncorr2(pc_old_e, alg_target) : 0; - p_new_i = alglib::pearsoncorr2(pc_new_i, alg_target); - p_new_e = new_members.size() > 1 ? alglib::pearsoncorr2(pc_new_e, alg_target) : 0; - - printf("poi: %f\tpoe: %f\tpni: %f\tpne: %f\n", p_old_i, p_old_e, p_new_i, p_new_e); - -// return (abs(p_old_e) - abs(p_old_i)) + (abs(p_new_i) - abs(p_new_e)); // delta_old + delta_new - return ((0.5*(1-p_old_e)) - (0.5*(1-p_old_i))) + ((0.5*(1-p_new_i)) - (0.5*(1-p_new_e))); -// return ((0.5*(1+abs(p_old_e))) - (0.5*(1+abs(p_old_i)))) + ((0.5*(1+abs(p_new_i))) - (0.5*(1+abs(p_new_e)))); -} \ No newline at end of file diff --git a/bioneuralnet/clustering/hybrid_clustering/Hybrid_Louvain.py b/bioneuralnet/clustering/hybrid_clustering/Hybrid_Louvain.py deleted file mode 100644 index eec0a18..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/Hybrid_Louvain.py +++ /dev/null @@ -1,384 +0,0 @@ -import copy -import getopt -import sys, os -from bioneuralnet.clustering.hybrid_clustering.Hybrid_Louvain import ManualLouvain - -sys.path.append(os.path.join(os.path.dirname(sys.path[0]), 'leidenalg-igraph', 'build', 'lib.linux-x86_64-3.8')) -# louvaun aka name -import leidenalg as leiden -import igraph as ig -# from OutputGrabber import * -import networkx as nx -import matplotlib.pyplot as plt -import pandas as pd -from sklearn.preprocessing import StandardScaler -from sklearn.decomposition import PCA -from scipy.stats import pearsonr -from time import time -from datetime import datetime - - -def ReadDataset(): - print('Reading dataset...') - read_time = time() - dataset = pd.read_excel('X.xlsx') - target = pd.read_excel('Y.xlsx') - # G = nx.read_edgelist('GFEV1ac110.edgelist', data=(('weight', float),)) - G = ig.Graph.Read_Ncol('GFEV1ac110.edgelist', directed=False) - for node in G.vs: - node['name'] = int(node['name']) - - target_list = target.iloc[:, 1].values.tolist() - dataset_list = dataset.iloc[:, 1:].T.values.tolist() - - scaler = StandardScaler() - dataset_list_scaled = scaler.fit_transform(dataset.iloc[:, 1:]).T.tolist() - read_time = time() - read_time - print('Dataset loaded.') - print('Read time: {}'.format(read_time)) - - return G, dataset_list, dataset_list_scaled, target_list, list(dataset.columns[1:]) - - -def RunAlgorithm(k3, k4): - print('Starting partitioning...') - partition_time = time() - - optimiser = leiden.Optimiser() - partitions = [] - partial_partition = leiden.HybridVertexParition(G, weights='weight', - dataset=dataset_list_scaled, target=target_list, k3=k3, k4=k4) - partition_agg = partial_partition.aggregate_partition() - while optimiser.move_nodes(partition_agg) > 0: - partial_partition.from_coarse_partition(partition_agg) - partitions += [copy.copy(partial_partition)] - partition_agg = partition_agg.aggregate_partition() - - partition_time = time() - partition_time - print('Partitioned.') - print('Partition time: {}'.format(partition_time)) - - return partitions - - -def GetStats(G, partition, dataset_list, dataset_list_scaled, target_list, name_list): - corr = [0 for _ in range(len(partition))] - pval = [0 for _ in range(len(partition))] - corr_scaled = [0 for _ in range(len(partition))] - pval_scaled = [0 for _ in range(len(partition))] - true_index = [0 for _ in range(len(partition))] - node_names = [0 for _ in range(len(partition))] - - for i, community in enumerate(partition): - subset = [] - subset_scaled = [] - true_comm = [] - names = [] - for node_index in community: - index = int(G.vs[int(node_index)]['name']) - subset += [dataset_list[index]] - subset_scaled += [dataset_list_scaled[index]] - true_comm += [index] - names += [name_list[index]] - - pca = PCA(n_components=1) - pc1 = pca.fit_transform(pd.DataFrame(subset).T) - pc1 = [j for j, in pc1] - - pca_scaled = PCA(n_components=1) - pc1_scaled = pca_scaled.fit_transform(pd.DataFrame(subset).T) - pc1_scaled = [j for j, in pc1_scaled] - - corr_val, pval_val = pearsonr(pc1, target_list) - corr[i] = corr_val - pval[i] = pval_val - - corr_val, pval_val = pearsonr(pc1_scaled, target_list) - corr_scaled[i] = corr_val - pval_scaled[i] = pval_val - - true_index[i] = true_comm - node_names[i] = names - - return corr, pval, corr_scaled, pval_scaled, true_index, node_names - - -def PrintAllStats(index, partition, corr, pval, corr_scaled, pval_scaled, true_index): - print(color.BOLD + color.BLUE + '------------------------------------------------------------------' + color.END) - print(color.BOLD + color.BLUE + 'Level {}'.format(index) + color.END) - for i in range(len(partition)): - print('Community {}'.format(i)) - print('Members: {}'.format(partition[i])) - print('Real Members: {}'.format(true_index[i])) - print('Correlation: {}\nP Value: {}'.format(corr[i], pval[i])) - print('Scaled Correlation: {}\nScaled P Value: {}'.format(corr_scaled[i], pval_scaled[i])) - print('\n\n\n') - - -def PrintTopKStats(k, partition, corr, pval, corr_scaled, pval_scaled, true_index): - print(color.BOLD + color.BLUE + '------------------------------------------------------------------' + color.END) - print(color.BOLD + color.BLUE + 'Top {}'.format(k) + color.END) - for cluster in sorted(list(zip(partition, list(range(len(partition))), corr, pval, corr_scaled, pval_scaled, true_index)), - key=lambda x: abs(x[2]), reverse=True)[:min(k, len(partition))]: - print('Community {}'.format(cluster[1])) - print('Members: {}'.format(cluster[0])) - print('Real Members: {}'.format(cluster[6])) - print('Correlation: {}\nP Value: {}'.format(cluster[2], cluster[3])) - print('Scaled Correlation: {}\nScaled P Value: {}'.format(cluster[4], cluster[5])) - print('\n\n\n') - - -def SaveStats(filename, partition, corr, pval, corr_scaled, pval_scaled, true_index, node_names, directory='Results'): - df = pd.DataFrame(columns=['Cluster Number', 'Partition Members', 'Real Members', 'Member Names', 'Correlation', - 'P Value', 'Scaled Correlation', 'Scaled P Value']) - for i, cluster in enumerate( - sorted(list(zip(partition, list(range(len(partition))), corr, pval, corr_scaled, pval_scaled, true_index, node_names)), - key=lambda x: abs(x[2]), reverse=True)): - entry = {'Cluster Number': cluster[1], - 'Partition Members': cluster[0], - 'Real Members': cluster[6], - 'Member Names': cluster[7], - 'Correlation': cluster[2], - 'P Value': cluster[3], - 'Scaled Correlation': cluster[4], - 'Scaled P Value': cluster[5]} - df = df.append(entry, ignore_index=True) - - if not os.path.isdir(directory): - os.mkdir(directory) - - df.to_csv('{}/{}'.format(directory, filename), index=False) - - -# sweep-cut fucntion for simultaneous PageRank method -def sweep_cut (p, G): - cond_res = [] - corr_res = [] - cond_corr_res = [] - - cluster = set() - min_cut , min_cond , len_clus, min_cond_corr = len(p), 1, 0, 2 - vec = sorted([(p[i]/G.degree(weight='weight')[str(i)] , i) for i in p.keys()], reverse=True) - - for i, (val, node) in enumerate(vec): # val is normalized PR score - if val == 0: break - else: - cluster.add(node) - - if len(G.nodes()) > len(cluster): - cluster_cond = nx.conductance(G, cluster , weight= 'weight') - cluster_cond = round (cluster_cond, 3) - cond_res.append(cluster_cond) - - - Nodes = [int(k) for k in cluster] - cluster_corr, corr_pvalue = Phen_omics_corr(Nodes) - corr_res.append (round(cluster_corr, 3)) - cluster_corr = (-1) * abs(round(cluster_corr,3)) - - # setting K value for composite correlation-coductance function - k =0.9 - cond_corr = round((1-k)*cluster_cond + k*cluster_corr, 3) - cond_corr_res.append(cond_corr) - - - if (cond_corr < min_cond_corr): - min_cond_corr , min_cut = cond_corr , i - len_clus = len(cluster) - cond = cluster_cond - corr = - cluster_corr - cor_pval = corr_pvalue - - - return ([vec[i][1] for i in range(min_cut+1)], len_clus, cond, corr, round (min_cond_corr,3), cor_pval) - -class color: - PURPLE = '\033[95m' - CYAN = '\033[96m' - DARKCYAN = '\033[36m' - BLUE = '\033[94m' - GREEN = '\033[92m' - YELLOW = '\033[93m' - RED = '\033[91m' - BOLD = '\033[1m' - UNDERLINE = '\033[4m' - END = '\033[0m' - -# Hybrid functions - -# Calculating omics-phyenotype Pearson correlation -# Nodes is a list of nodes indeces a vector[] -def Phen_omics_corr (Nodes): - - # Subsetting the Omics data from the PageRank subent - # B is the omics data - B_sub = B.iloc[:, Nodes ] - - # Scaling the sebset data - scaler = StandardScaler() - scaled = scaler.fit_transform(B_sub) - - # applying PCA to the subset data - pca = PCA(n_components = 1) - g1 = pca.fit_transform(scaled) - - g1 = [i for i, in g1] - - # Subsetting the phenotype data - g2 = Y.iloc[:,0] - - # obtaining the omics-phenotype correlation - corr, pvalue = pearsonr(g1, g2) - corr = round (corr,2) - p_value = format(pvalue,'.3g') - corr_pvalue = "(".join([str(corr),str(p_value)+')']) - return(corr, corr_pvalue) - -def generate_weighted_personalization(nodes, max_alpha): - total_corr = Phen_omics_corr(nodes)[0] - corr_contribution = [0 for _ in range(len(nodes))] - for i in range(len(nodes)): -# print('Total: {}, Excluding {}: {}'.format(total_corr, nodes[i], Phen_omics_corr(nodes[:i] + nodes[i+1:])[0])) - corr_contribution[i] = abs(Phen_omics_corr(nodes[:i] + nodes[i+1:])[0]) - abs(total_corr) - -# print('Contributions: {}'.format(corr_contribution)) - weighted_personalization = {} -# print('Max Correlation Contribution: {}'.format(max(corr_contribution, key=abs))) - for pair in zip(nodes, corr_contribution): -# print('Node {} contribution: {}'.format(pair[0], pair[1])) - weighted_personalization[str(pair[0])] = max_alpha * pair[1]/max(corr_contribution, key=abs) - -# print('Weighted personalization: {}'.format(weighted_personalization)) - return weighted_personalization -def calculate_conductance(G, subgraph): - S = [str(item) for item in subgraph] - T = [item for item in G.nodes if item not in S] - return nx.algorithms.cuts.conductance(G, S, T), nx.conductance(G, nx.Graph(nx.subgraph(G, S)), weight='weight') - - - -def ManualLouvain(G, dataset, target, k3, k4): - print('Starting partitioning...') - partition_time = time() - - #Hybredvertex - optimiser = leiden.Optimiser() - partitions = [] - partial_partition = leiden.HybridVertexParition(G, weights='weight', - dataset=dataset, target=target, k3=k3, k4=k4) - partition_agg = partial_partition.aggregate_partition() - while optimiser.move_nodes(partition_agg) > 0: - partial_partition.from_coarse_partition(partition_agg) - partitions += [copy.copy(partial_partition)] - partition_agg = partition_agg.aggregate_partition() - - partition_time = time() - partition_time - print('Partitioned.') - print('Partition time: {}'.format(partition_time)) - - -if __name__ == "__main__": - - # global variables. - # Reading dataset - print('Reading dataset...') - print(os.path.join(os.path.dirname(sys.path[0]),'leidenalg-igraph','build','lib.linux-x86_64-3.8')) - read_time = time() - dataset = pd.read_excel('X.xlsx') - target = pd.read_excel('Y.xlsx') - G = ig.Graph.Read_Ncol('GFEV1ac110.edgelist', directed=False) - for node in G.vs: - node['name'] = int(node['name']) - - target_list = target.iloc[:, 1].values.tolist() - dataset_list = dataset.iloc[:, 1:].T.values.tolist() - - scaler = StandardScaler() - dataset_list_scaled = scaler.fit_transform(dataset_list).tolist() - read_time = time() - read_time - print('Dataset loaded.') - print('Read time: {}'.format(read_time)) - - # Variables for pagerank - # apply PageRank to the graph - alpha = 0.9 - seeds = 94 - - # Loading data - B = pd.read_excel('X.xlsx') - B.drop(B.columns[0], axis =1, inplace = True) - - Y = pd.read_excel('Y.xlsx') - Y.drop(Y.columns[0], axis = 1, inplace = True) - - G2 = nx.read_edgelist('GFEV1ac110.edgelist', data=(('weight', float),)) - - - - # g is the graph, dataset_list is the list of omics data, dataset_list_scaled is the scaled omics data, target_list is the phenotype data, name_list is the list of node names - all_partitions = ManualLouvain(G, dataset_list_scaled, target_list, 0.2, 0.8) - partition = all_partitions[-1] - corr, pval, corr_scaled, pval_scaled, true_index, node_names = GetStats(G, partition, dataset_list, dataset_list_scaled, target_list, name_list) - candidates = sorted(zip(corr, true_index), key=lambda x: abs(x[0]), reverse=True) - - for candidate in candidates: - if len(candidate[1]) > 1: - top_candidate = candidate[1] - print('Top cluster: {}\nCorrelation: {}'.format(candidate[1], candidate[0])) - break - - p = nx.pagerank(G2, personalization=generate_weighted_personalization(candidates, alpha), max_iter=100000, tol=1e-06) - nodes, n, cond, corr, min_corr, pval = sweep_cut(p, G2) - - # Never generated an actual subgraph. - # Cluster is a list of node indexes - # Sweep return a list of indices. - -#################################################################### - k3 = float(sys.argv[1]) - k4 = float(sys.argv[2]) - - G, dataset_list, dataset_list_scaled, target_list, name_list = ReadDataset() - # This is a list of clusters. - partitions = RunAlgorithm(k3, k4) - - for i, partition in enumerate(partitions): - corr, pval, corr_scaled, pval_scaled, true_index, node_names = GetStats(G, partition, dataset_list, dataset_list_scaled, target_list, name_list) - PrintAllStats(i, partition, corr, pval, corr_scaled, pval_scaled, true_index) - PrintTopKStats(20, partition, corr, pval, corr_scaled, pval_scaled, true_index) - timestamp = datetime.now() - SaveStats('{}_{}_Level {}_Max {}_{}.csv'.format(k3, k4, i, max(corr, key=abs), timestamp.strftime('%m%d%y-%H%M%S')), - partition, corr, pval, corr_scaled, pval_scaled, true_index, node_names) - - -## Subset of nodes - - test_nodes = [11, 206, 303, 406, 1421, 1805] - edge_threshold = 0.09 - - # p = nx.pagerank(G, personalization=generate_weighted_personalization(test_nodes, alpha), max_iter=100000, tol=1e-06) - p = nx.pagerank(G, personalization=generate_weighted_personalization(test_nodes, alpha), max_iter=100000, tol=1e-06) - nodes, n, cond, corr, min_corr, pval = sweep_cut(p, G) - - print('Seed node {}:'.format(test_nodes)) - print('Number of nodes: {}'.format(n)) - print('Cond: {}'.format(cond)) - print('Correlation: {}'.format(corr)) - print('Minimum Correlation: {}'.format(min_corr)) - print('Corr/PVal: {}'.format(pval)) - print('\n\n\n') - - subgraph = nx.Graph(G.subgraph(nodes)) - edge_weights = nx.get_edge_attributes(subgraph, 'weight') - subgraph.remove_edges_from((e for e, w in edge_weights.items() if w < 0.09)) - subgraph.remove_nodes_from(list(nx.isolates(subgraph))) - corr, pval = Phen_omics_corr([int(node) for node in list(subgraph.nodes)]) - - print('After pruning:') - print('Number of nodes: {}'.format(len(list(subgraph.nodes)))) - print('Correlation: {}'.format(corr)) - - - ## READ METHODS from - - #hybrid approach pagerank -> louvain -> pagerank -> \ No newline at end of file diff --git a/bioneuralnet/clustering/hybrid_clustering/Manual_Louvain.py b/bioneuralnet/clustering/hybrid_clustering/Manual_Louvain.py deleted file mode 100644 index 16791f8..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/Manual_Louvain.py +++ /dev/null @@ -1,248 +0,0 @@ -import copy -import sys, os -base_path = os.path.join('home', 'mohamed', 'Documents') -sys.path.append(os.path.join(base_path,'leidenalg-igraph','build','lib.linux-x86_64-3.8')) -import leidenalg as leiden -import igraph as ig -import networkx as nx -# from OutputGrabber import * -import pandas as pd -from sklearn.preprocessing import StandardScaler -from sklearn.decomposition import PCA -from scipy.stats import pearsonr, spearmanr -from time import time, sleep -from datetime import datetime -import ipyparallel as ipp -import matplotlib.pyplot as plt -from bioneuralnet.clustering.hybrid_clustering.Hybrid_Louvain import SaveStats, GetStats, ReadDataset - -# Calculating omics-phyenotype Pearson correlation -def Phen_omics_corr (Nodes): - - # Subsetting the Omics data from the PageRank subent - B_sub = B.iloc[:, Nodes ] - - # Scaling the sebset data - scaler = StandardScaler() - scaled = scaler.fit_transform(B_sub) - - # applying PCA to the subset data - pca = PCA(n_components = 1) - g1 = pca.fit_transform(scaled) - - g1 = [i for i, in g1] - - g2 = Y.iloc[:,0] - - # obtaining the omics-phenotype correlation - corr, pvalue = pearsonr(g1, g2) - corr = round (corr,2) - p_value = format(pvalue,'.3g') - corr_pvalue = "(".join([str(corr),str(p_value)+')']) - return(corr, corr_pvalue) - -# sweep-cut fucntion for simultaneous PageRank method -def sweep_cut (p, G): - cond_res = [] - corr_res = [] - cond_corr_res = [] - - cluster = set() - min_cut , min_cond , len_clus, min_cond_corr = len(p), 1, 0, 2 - vec = sorted([(p[i]/G.degree(weight='weight')[str(i)] , i) for i in p.keys()], reverse=True) - - for i, (val, node) in enumerate(vec): # val is normalized PR score - if val == 0: break - else: - cluster.add(node) - - if len(G.nodes()) > len(cluster): - cluster_cond = nx.conductance(G, cluster , weight= 'weight') - cluster_cond = round (cluster_cond, 3) - cond_res.append(cluster_cond) - - - Nodes = [int(k) for k in cluster] - cluster_corr, corr_pvalue = Phen_omics_corr(Nodes) - corr_res.append (round(cluster_corr, 3)) - cluster_corr = (-1) * abs(round(cluster_corr,3)) - - # setting K value for composite correlation-coductance function - k =0.9 - cond_corr = round((1-k)*cluster_cond + k*cluster_corr, 3) - cond_corr_res.append(cond_corr) - - - if (cond_corr < min_cond_corr): - min_cond_corr , min_cut = cond_corr , i - len_clus = len(cluster) - cond = cluster_cond - corr = - cluster_corr - cor_pval = corr_pvalue - - - return ([vec[i][1] for i in range(min_cut+1)], len_clus, cond, corr, round (min_cond_corr,3), cor_pval) - -def generate_weighted_personalization(nodes, max_alpha): - total_corr = Phen_omics_corr(nodes)[0] - corr_contribution = [0 for _ in range(len(nodes))] - for i in range(len(nodes)): - print('Total: {}, Excluding {}: {}'.format(total_corr, nodes[i], Phen_omics_corr(nodes[:i] + nodes[i+1:])[0])) - corr_contribution[i] = abs(Phen_omics_corr(nodes[:i] + nodes[i+1:])[0]) - abs(total_corr) - - print('Contributions: {}'.format(corr_contribution)) - weighted_personalization = {} -# print('Max Correlation Contribution: {}'.format(max(corr_contribution, key=abs))) - for pair in zip(nodes, corr_contribution): - print('Node {} contribution: {}'.format(pair[0], pair[1])) - weighted_personalization[str(pair[0])] = max_alpha * (pair[1]/max(corr_contribution, key=abs)) if abs(max(corr_contribution, key=abs)) > 1e-6 else max_alpha - - print('Weighted personalization: {}'.format(weighted_personalization)) - return weighted_personalization - -def calculate_conductance(G, subgraph): - S = [str(item) for item in subgraph] - T = [item for item in G.nodes if item not in S] - return nx.algorithms.cuts.conductance(G, S, T), nx.conductance(G, nx.Graph(nx.subgraph(G, S)), weight='weight') - -def ManualLouvain(G, dataset, target, k3, k4): - print('Starting partitioning...') - partition_time = time() - - optimiser = leiden.Optimiser() - partitions = [] - partial_partition = leiden.HybridVertexParition(G, weights='weight', - dataset=dataset, target=target, k3=k3, k4=k4) - partition_agg = partial_partition.aggregate_partition() - while optimiser.move_nodes(partition_agg) > 0: - partial_partition.from_coarse_partition(partition_agg) - partitions += [copy.copy(partial_partition)] - partition_agg = partition_agg.aggregate_partition() - - partition_time = time() - partition_time - print('Partitioned.') - print('Partition time: {}'.format(partition_time)) - - return partitions - -if __name__ == '__main__': - ###### Reading dataset -# print('Reading dataset...') -# print(os.path.join(os.path.dirname(sys.path[0]),'leidenalg-igraph','build','lib.linux-x86_64-3.8')) -# read_time = time() -# dataset = pd.read_excel('X.xlsx') -# target = pd.read_excel('Y.xlsx') -# G = ig.Graph.Read_Ncol('GFEV1ac110.edgelist', directed=False) -# ig_subgraph = G -# for node in G.vs: -# node['name'] = int(node['name']) - -# target_list = target.iloc[:, 1].values.tolist() -# dataset_list = dataset.iloc[:, 1:].T.values.tolist() - -# scaler = StandardScaler() -# dataset_list_scaled = scaler.fit_transform(dataset_list).tolist() -# read_time = time() - read_time -# print('Dataset loaded.') -# print('Read time: {}'.format(read_time)) - G, dataset_list, dataset_list_scaled, target_list, name_list = ReadDataset() - ig_subgraph = G - k3 = float(sys.argv[1]) - k4 = float(sys.argv[2]) - - - ###### Variables for pagerank - # apply PageRank to the graph - alpha = 0.04 - - # Loading data - B = pd.read_excel('X.xlsx') - B.drop(B.columns[0], axis =1, inplace = True) - - Y = pd.read_excel('Y.xlsx') - Y.drop(Y.columns[0], axis = 1, inplace = True) - - G2 = nx.read_edgelist('GFEV1ac110.edgelist', data=(('weight', float),)) - subgraph = G2 - graph_size = len(list(G2.nodes)) - - ###### Other variables - directory = 'ResultsHybrid9_{}'.format(k4) - PRResults = pd.DataFrame(columns=['Seed Nodes', 'Cluster', 'Number of Nodes', 'Conductance', 'Correlation', 'Minimum Correlation', 'Corr/PVal']) - cont = True - run = 1 - keepSingletons = False - - - ###### Running initial louvain - # all_partitions = ManualLouvain(G, dataset_list_scaled, target_list, 0.2, 0.8) - # partition = all_partitions[-1] - # corr, pval, corr_scaled, pval_scaled, true_index, node_names = GetStats(G, partition, dataset_list, dataset_list_scaled, target_list, name_list) - # candidates = sorted(zip(corr, true_index), key=lambda x: abs(x[0]), reverse=True) - - - if not os.path.isdir(directory): - os.mkdir(directory) - - - ###### Main loop - while cont: - #### Louvain - all_partitions = ManualLouvain(ig_subgraph, dataset_list_scaled, target_list, k3, k4) - - for i, partition in enumerate(all_partitions): - corr, pval, corr_scaled, pval_scaled, true_index, node_names = GetStats(ig_subgraph, partition, dataset_list, dataset_list_scaled, target_list, name_list) - # PrintAllStats(i, partition, corr, pval, corr_scaled, pval_scaled, true_index) - # PrintTopKStats(20, partition, corr, pval, corr_scaled, pval_scaled, true_index) - timestamp = datetime.now() - SaveStats('Round {}_{}_{}_Level {}_Max {}_{}.csv'.format(run, k3, k4, i, max(corr, key=abs), timestamp.strftime('%m%d%y-%H%M%S')), - partition, corr, pval, corr_scaled, pval_scaled, true_index, node_names, directory) - - if not len(all_partitions) > 0: - break - - partition = all_partitions[-1] - corr, pval, corr_scaled, pval_scaled, true_index, node_names = GetStats(ig_subgraph, partition, dataset_list, dataset_list_scaled, target_list, name_list) - candidates = sorted(zip(corr, true_index), key=lambda x: abs(x[0]), reverse=True) - - top_candidate = None - for candidate in candidates: - if len(candidate[1]) > 1 or keepSingletons: - top_candidate = candidate[1] - print('Top cluster: {}\nCorrelation: {}'.format(candidate[1], candidate[0])) - break - - #### PageRank - if top_candidate is not None: - p = nx.pagerank(subgraph, personalization=generate_weighted_personalization(top_candidate, alpha), max_iter=100000, tol=1e-06) - for edge in subgraph.edges(data=True): - print(edge[2]['weight']) - print('Nodes: {}'.format(list(subgraph.nodes))) - print('Seed: {}'.format(top_candidate)) - # p = nx.pagerank(subgraph, personalization={str(node): alpha for node in top_candidate}, max_iter=100000, tol=1e-06) - nodes, n, cond, corr, min_corr, pval = sweep_cut(p, subgraph) - - entry = {'Seed Nodes': top_candidate, - 'Cluster': [int(node) for node in nodes], - 'Number of Nodes': n, - 'Conductance': cond, - 'Correlation': corr, - 'Minimum Correlation': min_corr, - 'Corr/PVal': pval} - PRResults = PRResults.append(entry, ignore_index=True) - PRResults.to_csv(os.path.join(directory, 'PRResults.csv')) - - - - if len(nodes) < graph_size and len(nodes) > 0: - graph_size = len(nodes) - subgraph = subgraph.subgraph(nodes) - ig_subgraph = ig_subgraph.subgraph(ig_subgraph.vs.select([i for i, v in enumerate(ig_subgraph.vs) if v['name'] in [int(node) for node in nodes]])) - run += 1 - else: - cont = False - -# if not os.path.isdir(directory): -# os.mkdir(directory) - -# PRResults.to_csv(os.path.join(directory, 'PRResults.csv')) \ No newline at end of file diff --git a/bioneuralnet/clustering/hybrid_clustering/__init__.py b/bioneuralnet/clustering/hybrid_clustering/__init__.py deleted file mode 100644 index 643601b..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# In progress \ No newline at end of file diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/.gitattributes b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/.gitattributes deleted file mode 100644 index 6aed1a5..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -* text=auto -src/_version.py export-subst diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/.gitignore b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/.gitignore deleted file mode 100644 index cc868d5..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/.gitignore +++ /dev/null @@ -1,39 +0,0 @@ -MANIFEST -build/ -dist/ -lib/ -nbproject/ -leidenalg.egg-info/ -wlib/ -bin/ -obj/ -Makefile -*.log -**/*.o -**/*.so -**/*.pyc -files.txt -files_py3.txt -callgrind* -main.cpp -leiden-dists.zip -leidenalg.cbp -leidenalg.depend -leidenalg.layout -leiden.log -igraphcore/ -**/*.swp -valgrind-python.supp -test/ -test_install.sh -massif* -.vscode/ -*.code-workspace -PACKAGE.txt -vendor/source/igraph -vendor/source/install -vendor/install -src/leidenalg/version.py -pip-wheel-metadata -.eggs/ -doc/source/_build diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/.gitmodules b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/.gitmodules deleted file mode 100644 index 7f45a2d..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/.gitmodules +++ /dev/null @@ -1,5 +0,0 @@ -[submodule "vendor/source/igraph"] - path = vendor/source/igraph - url = https://github.com/igraph/igraph.git - ignore = all - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/.readthedocs.yml b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/.readthedocs.yml deleted file mode 100644 index 16f0c1c..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/.readthedocs.yml +++ /dev/null @@ -1,27 +0,0 @@ -# .readthedocs.yml -# Read the Docs configuration file -# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details - -# Required -version: 2 - -conda: - environment: build-doc.yml - -# Optionally build your docs in additional formats such as PDF and ePub -formats: all - -# Optionally set the version of Python and requirements required to build your docs -python: - version: 3.7 - install: - - method: pip - path: . - -submodules: - include: all - recursive: true - -# Build documentation in the doc/source directory with Sphinx -sphinx: - configuration: doc/source/conf.py \ No newline at end of file diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/CHANGELOG b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/CHANGELOG deleted file mode 100644 index 4b7cc46..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/CHANGELOG +++ /dev/null @@ -1,75 +0,0 @@ -0.8.9 -- Fixed bug with renaming of python-igraph to igraph (issue #93) -- Removed irrelevant node_sizes argument for RBConfigurationVertexPartition and ModularityVertexPartition -- Improved documentation - -0.8.8 -- Corrected relabeling bug (PR #82) -- Improved error handling, avoiding some crashses (issue #81) - -0.8.7 -- Improved numerical stability - -0.8.6 -- Removed accidentally left DEBUG statement - -0.8.5 -- Corrected iterating over nodes (PR #70). -- Fixed segfault with move_nodes_constrained (issue #68) -- Fixed problem with initial_membership (issue #66) - -0.8.4 -- Update C core to 0.9.1 -- Fixed caching problem (issue #62) -- Fixed missing node_sizes for modularity (issue #60) - -0.8.3 -- Fixed missing parameter in find_partition_multiplex by @TomKellyGenetics (PR #50) - -0.8.2 -- New option to constrain community size by @orenbenkiki (PR #46) -- Great performance improvement by @ragibson (PR #40) -- Minor improvements and clarifications - -0.8.1 -- Fixed performance problem (issue #35) -- Improved documentation - -0.8.0 -- New option to keep some nodes "fixed" by @iosonofabio (PR #8, #9) -- Corrected bipartite clustering -- Corrected some documentation -- Several minor bugfixes - -0.6.1 -- Minor corrections to documentation -- Added doctest to examples in documentation -- Removed trailing semicolons throughout code -- Corrected some errors in CPMVertexPartition.Bipartite - -0.6.0 -- Major API changes, now exposing actual classes and optimisation routine. -- Improved algorithm, now runs faster and finds better solutions. -- Improved error handling, doing more type checking. -- Improved documentation throughout, now done using Sphinx and available from - readthedocs.org. -- Now includes testing module, available through python setup.py test. - -0.5.3 -- Fixed bug concerning weights (were rounded to integers). -- Improved documentation. -- Included an HOWTO on extending the current package. -- Fixed some minor bugs. - -0.5.2 -- Ensured that random neighbour selection works in O(1) rather than O(k), with - k the average number of neighbours. -- Optimized the calculation of weight from/to community. -- Included some missing references. - -0.5.1 -Corrected some mistakes which prevented it from being properly used on PyPi. -No serious changes were made. - -0.5 -Initial release diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/LICENSE b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/LICENSE deleted file mode 100644 index 9cecc1d..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - {one line to give the program's name and a brief idea of what it does.} - Copyright (C) {year} {name of author} - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - {project} Copyright (C) {year} {fullname} - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/MANIFEST.in b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/MANIFEST.in deleted file mode 100644 index 935d2d9..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/MANIFEST.in +++ /dev/null @@ -1,18 +0,0 @@ -include LICENSE -include CHANGELOG -include README.rst -include pyproject.toml -include include/ -include MANIFEST.in -include tests/*.py - -exclude .git* -exclude *.yml -exclude release* -prune .github - -graft vendor/source/igraph -prune vendor/source/igraph/etc/abstracts -prune vendor/source/igraph/etc/papers -prune vendor/source/igraph/etc/presentations -prune vendor/source/igraph/vendor/simpleraytracer diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/README.rst b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/README.rst deleted file mode 100644 index 361ec9b..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/README.rst +++ /dev/null @@ -1,200 +0,0 @@ -leidenalg -============== - -This package implements the Leiden algorithm in ``C++`` and exposes it to -``python``. It relies on ``(python-)igraph`` for it to function. Besides the -relative flexibility of the implementation, it also scales well, and can be run -on graphs of millions of nodes (as long as they can fit in memory). The core -function is ``find_partition`` which finds the optimal partition using the -Leiden algorithm [1]_, which is an extension of the Louvain algorithm [2]_ for a -number of different methods. The methods currently implemented are (1) -modularity [3]_, (2) Reichardt and Bornholdt's model using the configuration -null model and the Erdös-Rényi null model [4]_, (3) the Constant Potts model -(CPM) [5]_, (4) Significance [6]_, and finally (5) Surprise [7]_. In addition, -it supports multiplex partition optimisation allowing community detection on for -example negative links [8]_ or multiple time slices [9]_. There is the -possibility of only partially optimising a partition, so that some community -assignments remain fixed [10]_. It also provides some support for community -detection on bipartite graphs. See the `documentation -`_ for more information. - - -.. image:: https://readthedocs.org/projects/leidenalg/badge - :target: http://leidenalg.readthedocs.io/en/latest/ - :alt: Leiden documentation status - -.. image:: https://github.com/vtraag/leidenalg/actions/workflows/build.yml/badge.svg?branch=master - :target: https://github.com/vtraag/leidenalg/actions/workflows/build.yml - :alt: Leiden build status (GitHub Actions) - -.. image:: https://zenodo.org/badge/146722095.svg - :target: https://zenodo.org/badge/latestdoi/146722095 - :alt: DOI - -.. image:: https://anaconda.org/conda-forge/leidenalg/badges/version.svg - :target: https://anaconda.org/conda-forge/leidenalg - :alt: Anaconda (conda-forge) - -Installation ------------- - -In short: ``pip install leidenalg``. All major platforms are supported on -Python>=3.6, earlier versions of Python are no longer supported. Alternatively, -you can install from Anaconda (channel ``conda-forge``). - -For Unix like systems it is possible to install from source. For Windows this is -overly complicated, and you are recommended to use the binary wheels. The igraph -``C`` core library is provided within this package, and is automatically -compiled. If you encounter any issue with compilation, please see -http://igraph.org. - -Make sure you have all necessary tools for compilation. In Ubuntu this can be -installed using ``sudo apt-get install build-essential autoconf automake flex -bison``, please refer to the documentation for your specific system. Make sure -that not only ``gcc`` is installed, but also ``g++``, as the ``leidenalg`` -package is programmed in ``C++``. - -You can check if all went well by running a variety of tests using ``python -setup.py test``. - -There are basically two installation modes, similar to the python-igraph package -itself (from which most of the setup.py comes). - -1. No ``C`` core library is installed yet. The ``C`` core - library of igraph that is provided within the ``leidenalg`` package is - compiled. -2. A ``C`` core library is already installed. In this case, you may link - dynamically to the already installed version by specifying - ``--no-pkg-config``. This is probably also the version that is used by the - igraph package, but you may want to double check this. - -In case the ``python-igraph`` package is already installed before, make sure that -both use the **same versions** (at least the same minor version, which should be -API compatible). - -Troubleshooting ---------------- - -In case of any problems, best to start over with a clean environment. Make sure -you remove the ``python-igraph`` package completely, remove the ``C`` core -library and remove the ``leidenalg`` package. Then, do a complete reinstall -starting from ``pip install leidenalg``. In case you want a dynamic library be -sure to then install the ``C`` core library from source before. Make sure you -**install the same versions**. - -Usage ------ - -There is no standalone version of ``leidenalg``, and you will always need python -to access it. There are no plans at the moment for developing a standalone -version or R support. However, there have been various efforts to port the -package to R. These typically do not offer all available functionality or have -some other limitations, but nonetheless may be very useful. The available ports -are: - -- https://github.com/cole-trapnell-lab/leidenbase -- https://github.com/TomKellyGenetics/leiden -- https://github.com/kharchenkolab/leidenAlg - -Please refer to the documentation for more details -on function calls and parameters. - -This implementation is made for flexibility, but ``igraph`` nowadays also -includes an implementation of the Leiden algorithm internally. That -implementation is less flexible: the implementation only works on undirected -graphs, and only CPM and modularity are supported. It is likely to be -substantially faster though. - -Just to get you started, below the essential parts. -To start, make sure to import the packages: - ->>> import leidenalg ->>> import igraph as ig - -We'll create a random graph for testing purposes: - ->>> G = ig.Graph.Erdos_Renyi(100, 0.1); - -For simply finding a partition use: - ->>> part = leidenalg.find_partition(G, leidenalg.ModularityVertexPartition); - -Contribute ----------- - -Source code: https://github.com/vtraag/leidenalg - -Issue tracking: https://github.com/vtraag/leidenalg/issues - -See the documentation on `Implementation` for more details on how to -contribute new methods. - -References ----------- - -Please cite the references appropriately in case they are used. - -.. [1] Traag, V.A., Waltman. L., Van Eck, N.-J. (2018). From Louvain to - Leiden: guaranteeing well-connected communities. Scientific reports, 9(1), 5233. - `10.1038/s41598-019-41695-z `_ - -.. [2] Blondel, V. D., Guillaume, J.-L., Lambiotte, R., & Lefebvre, E. (2008). - Fast unfolding of communities in large networks. Journal of Statistical - Mechanics: Theory and Experiment, 10008(10), 6. - `10.1088/1742-5468/2008/10/P10008 `_ - -.. [3] Newman, M. E. J., & Girvan, M. (2004). Finding and evaluating community - structure in networks. Physical Review E, 69(2), 026113. - `10.1103/PhysRevE.69.026113 `_ - -.. [4] Reichardt, J., & Bornholdt, S. (2006). Statistical mechanics of - community detection. Physical Review E, 74(1), 016110. - `10.1103/PhysRevE.74.016110 `_ - -.. [5] Traag, V. A., Van Dooren, P., & Nesterov, Y. (2011). Narrow scope for - resolution-limit-free community detection. Physical Review E, 84(1), - 016114. `10.1103/PhysRevE.84.016114 - `_ - -.. [6] Traag, V. A., Krings, G., & Van Dooren, P. (2013). Significant scales in - community structure. Scientific Reports, 3, 2930. `10.1038/srep02930 - `_ - -.. [7] Traag, V. A., Aldecoa, R., & Delvenne, J.-C. (2015). Detecting - communities using asymptotical surprise. Physical Review E, 92(2), - 022816. `10.1103/PhysRevE.92.022816 - `_ - -.. [8] Traag, V. A., & Bruggeman, J. (2009). Community detection in networks - with positive and negative links. Physical Review E, 80(3), 036115. - `10.1103/PhysRevE.80.036115 - `_ - -.. [9] Mucha, P. J., Richardson, T., Macon, K., Porter, M. A., & Onnela, J.-P. - (2010). Community structure in time-dependent, multiscale, and multiplex - networks. Science, 328(5980), 876–8. `10.1126/science.1184819 - `_ - -.. [10] Zanini, F., Berghuis, B. A., Jones, R. C., Robilant, B. N. di, - Nong, R. Y., Norton, J., Clarke, Michael F., Quake, S. R. (2019). - northstar: leveraging cell atlases to identify healthy and neoplastic - cells in transcriptomes from human tumors. BioRxiv, 820928. - `10.1101/820928 `_ - -Licence -------- - -Copyright (C) 2020 V.A. Traag - -This program is free software: you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation, either version 3 of the License, or (at your option) any later -version. - -This program is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program. If not, see http://www.gnu.org/licenses/. - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/build-doc.yml b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/build-doc.yml deleted file mode 100644 index 9b36879..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/build-doc.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: build-doc -channels: - - conda-forge -dependencies: - - python=3.8 - - python-igraph>=0.8.0 - - ddt - - sphinx - - sphinx_rtd_theme - - autoconf - - automake - - flex - - bison - - libtool - - cmake \ No newline at end of file diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/advanced.rst b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/advanced.rst deleted file mode 100644 index 4df3b63..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/advanced.rst +++ /dev/null @@ -1,250 +0,0 @@ -Advanced -======== - -The basic interface explained in the :ref:`Introduction` should provide you -enough to start detecting communities. However, perhaps you want to improve the -partitions further or want to do some more advanced analysis. In this section, -we will explain this in more detail. - -Optimiser ---------- - -Although the package provides simple access to the function -:func:`~leidenalg.find_partition`, there is actually an underlying -:class:`~leidenalg.Optimiser` class that is doing the actual work. We can also -explicitly construct an :class:`~leidenalg.Optimiser` object: - ->>> optimiser = la.Optimiser() - -The function :func:`~leidenalg.find_partition` then does nothing else then -calling :func:`~leidenalg.Optimiser.optimise_partition` on the provided -partition. - -.. testsetup:: - - G = ig.Graph.Erdos_Renyi(100, p=5./100) - partition = la.CPMVertexPartition(G) - ->>> diff = optimiser.optimise_partition(partition) - -:func:`~leidenalg.Optimiser.optimise_partition` simply tries to improve any -provided partition. We can thus try to repeatedly call -:func:`~leidenalg.Optimiser.optimise_partition` to keep on improving the current -partition: - ->>> G = ig.Graph.Erdos_Renyi(100, p=5./100) ->>> partition = la.ModularityVertexPartition(G) ->>> diff = 1 ->>> while diff > 0: -... diff = optimiser.optimise_partition(partition) - -Even if a call to :func:`~leidenalg.Optimiser.optimise_partition` did not improve -the current partition, it is still possible that a next call will improve the -partition. Of course, if the current partition is already optimal, this will -never happen, but it is not possible to decide whether a partition is optimal. - -This functionality of repeating multiple iterations is actually already -built-in. You can simply call - ->>> diff = optimiser.optimise_partition(partition, n_iterations=10) - -If ``n_iterations < 0`` the optimiser continues iterating until it encounters -an iterations that did not improve the partition. - -The :func:`~leidenalg.Optimiser.optimise_partition` itself is built on two other -basic algorithms: :func:`~leidenalg.Optimiser.move_nodes` and -:func:`~leidenalg.Optimiser.merge_nodes`. You can also call these functions -yourself. For example: - ->>> diff = optimiser.move_nodes(partition) - -or - ->>> diff = optimiser.merge_nodes(partition) - -The simpler Louvain algorithm aggregates the partition and repeats the -:func:`~leidenalg.Optimiser.move_nodes` on the aggregated partition. We can easily -emulate that: - ->>> partition = la.ModularityVertexPartition(G) ->>> while optimiser.move_nodes(partition) > 0: -... partition = partition.aggregate_partition() - -This summarises the whole Louvain algorithm in just three lines of code. -Although this finds the final aggregate partition, it leaves unclear the actual -partition on the level of the individual nodes. In order to do that, we need to -update the membership based on the aggregate partition, for which we use the -function -:func:`~leidenalg.VertexPartition.MutableVertexPartition.from_coarse_partition`. - ->>> partition = la.ModularityVertexPartition(G) ->>> partition_agg = partition.aggregate_partition() ->>> while optimiser.move_nodes(partition_agg) > 0: -... partition.from_coarse_partition(partition_agg) -... partition_agg = partition_agg.aggregate_partition() - -Now ``partition_agg`` contains the aggregate partition and ``partition`` -contains the actual partition of the original graph ``G``. Of course, -``partition_agg.quality() == partition.quality()`` (save some rounding). - -Instead of :func:`~leidenalg.Optimiser.move_nodes`, you could also use -:func:`~leidenalg.Optimiser.merge_nodes`. These functions depend on choosing -particular alternative communities: the documentation of the functions provides -more detail. - -One possibility is that rather than aggregating the partition based on the -current partition, you can first refine the partition and then aggregate it. -This is what is done in the Leiden algorithm, and can be done using the functions -:func:`~leidenalg.Optimiser.move_nodes_constrained` and -:func:`~leidenalg.Optimiser.merge_nodes_constrained`. Implementing this, you -end up with the following high-level implementation of the Leiden algorithm: - ->>> # Set initial partition ->>> partition = la.ModularityVertexPartition(G) ->>> refined_partition = la.ModularityVertexPartition(G) ->>> partition_agg = refined_partition.aggregate_partition() ->>> ->>> while optimiser.move_nodes(partition_agg): -... -... # Get individual membership for partition -... partition.from_coarse_partition(partition_agg, refined_partition.membership) -... -... # Refine partition -... refined_partition = la.ModularityVertexPartition(G) -... optimiser.merge_nodes_constrained(refined_partition, partition) -... -... # Define aggregate partition on refined partition -... partition_agg = refined_partition.aggregate_partition() -... -... # But use membership of actual partition -... aggregate_membership = [None] * len(refined_partition) -... for i in range(G.vcount()): -... aggregate_membership[refined_partition.membership[i]] = partition.membership[i] -... partition_agg.set_membership(aggregate_membership) - -These functions in turn rely on two key functions of the partition: -:func:`~leidenalg.VertexPartition.MutableVertexPartition.diff_move` and -:func:`~leidenalg.VertexPartition.MutableVertexPartition.move_node`. The first -calculates the difference when moving a node, and the latter actually moves the -node, and updates all necessary internal administration. The -:func:`~leidenalg.Optimiser.move_nodes` then does something as follows - ->>> for v in G.vs: -... best_comm = max(range(len(partition)), -... key=lambda c: partition.diff_move(v.index, c)) -... partition.move_node(v.index, best_comm) - -The actual implementation is more complicated, but this gives the general idea. - -This package builds on a previous implementation of the Louvain algorithm in -`louvain-igraph `_. To illustrate -the difference between ``louvain-igraph`` and ``leidenalg``, we ran both -algorithms for 10 iterations on a `Youtube network -`_ of more than 1 million -nodes and almost 3 million edges. - -.. image:: figures/speed.png - -The results are quite clear: Leiden is able to achieve a higher modularity in -less time. It also points out that it is usually a good idea to run Leiden for -at least two iterations; this is also the default setting. - -Note that even if the Leiden algorithm did not find any improvement in this -iteration, it is always possible that it will find some improvement in the next -iteration. - -Resolution profile ------------------- - -Some methods accept so-called resolution parameters, such as -:class:`~leidenalg.CPMVertexPartition` or -:class:`~leidenalg.RBConfigurationVertexPartition`. Although some methods may seem -to have some 'natural' resolution, in reality this is often quite arbitrary. -However, the methods implemented here (which depend in a linear way on -resolution parameters) allow for an effective scanning of a full range for the -resolution parameter. In particular, these methods somehow can be formulated as -:math:`Q = E - \gamma N` where :math:`E` and :math:`N` are some other -quantities. In the case for :class:`~leidenalg.CPMVertexPartition` for example, -:math:`E = \sum_c m_c` is the number of internal edges and :math:`N = \sum_c -\binom{n_c}{2}` is the sum of the internal possible edges. The essential -insight for these formulations [1]_ is that if there is an optimal partition -for both :math:`\gamma_1` and :math:`\gamma_2` then the partition is also -optimal for all :math:`\gamma_1 \leq \gamma \leq \gamma_2`. - -Such a resolution profile can be constructed using the -:class:`~leidenalg.Optimiser` object. - ->>> G = ig.Graph.Famous('Zachary') ->>> optimiser = la.Optimiser() ->>> profile = optimiser.resolution_profile(G, la.CPMVertexPartition, -... resolution_range=(0,1)) - -Plotting the resolution parameter versus the total number of internal edges we -thus obtain something as follows: - -.. image:: figures/resolution_profile.png - -Now ``profile`` contains a list of partitions of the specified type -(:class:`~leidenalg.CPMVertexPartition` in this case) for -resolution parameters at which there was a change. In particular, -``profile[i]`` should be better until ``profile[i+1]``, or stated otherwise for -any resolution parameter between ``profile[i].resolution_parameter`` and -``profile[i+1].resolution_parameter`` the partition at position ``i`` should be -better. Of course, there will be some variations because -:func:`~leidenalg.Optimiser.optimise_partition` will find partitions of varying -quality. The change points can then also vary for different runs. - -This function repeatedly calls :func:`~leidenalg.Optimiser.optimise_partition` -and can therefore require a lot of time. Especially for resolution parameters -right around a change point there may be many possible partitions, thus -requiring a lot of runs. - -Fixed nodes ------------ - -For some purposes, it might be beneficial to only update part of a partition. -For example, perhaps we previously already ran the Leiden algorithm on some -dataset, and did some analysis on the resulting partition. If we then gather new -data, and in particular new nodes, it might be useful to keep the previous -community assignments fixed, while only updating the community assignments for -the new nodes. This can be done using the ``is_membership_fixed`` argument of -:func:`~leidenalg.Optimiser.find_partition`, see [2]_ for some details. - -For example, suppose we previously detected ``partition`` for graph ``G``, which -was extended to graph ``G2``. Assuming that the previously exiting nodes are -identical, we could create a new partition by doing - ->>> new_membership = list(range(G2.vcount())) -... new_membership[:G.vcount()] = partition.membership - -We can then only update the community assignments for the new nodes as follows - ->>> new_partition = la.CPMVertexPartition(G2, new_membership, -... resolution_parameter=partition.resolution_parameter) -... is_membership_fixed = [i < G.vcount() for i in range(G2.vcount())] ->>> diff = optimiser.optimise_partition(new_partition, is_membership_fixed=is_membership_fixed) - -In this example we used :class:`~leidenalg.CPMVertexPartition`. but any other -``VertexPartition`` would work as well. - -Maximum community size ----------------------- - -In some cases, you may want to restrict the community sizes. It is possible to indicate this -by setting the :attr:`~leidenalg.Optimiser.max_comm_size` parameter so that this constraint is -taken into account during optimisation. In addition, it is possible to pass this parameter -directly when using :func:`~leidenalg.find_partition`. For example - ->>> partition = la.find_partition(G, la.ModularityVertexPartition, max_comm_size=10) - -References ----------- -.. [1] Traag, V. A., Krings, G., & Van Dooren, P. (2013). Significant scales in - community structure. Scientific Reports, 3, 2930. `10.1038/srep02930 - `_ - -.. [2] Zanini, F., Berghuis, B. A., Jones, R. C., Robilant, B. N. di, - Nong, R. Y., Norton, J., Clarke, Michael F., Quake, S. R. (2019). - northstar: leveraging cell atlases to identify healthy and neoplastic - cells in transcriptomes from human tumors. BioRxiv, 820928. - `10.1101/820928 `_ diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/conf.py b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/conf.py deleted file mode 100644 index 4bad50d..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/conf.py +++ /dev/null @@ -1,365 +0,0 @@ -# -*- coding: utf-8 -*- -# -# leidenalg documentation build configuration file, created by -# sphinx-quickstart on Fri Oct 21 11:26:44 2016. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -import os -#import sys -# -#sys.path.insert(0, os.path.abspath('.')) - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -# -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.doctest', - 'sphinx.ext.coverage', - 'sphinx.ext.mathjax', - 'sphinx.ext.napoleon', - 'sphinx.ext.autosectionlabel' -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['.templates'] - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# -# source_suffix = ['.rst', '.md'] -source_suffix = '.rst' - -# The encoding of source files. -# -# source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'leidenalg' -copyright = u'2016, V.A. Traag' -author = u'V.A. Traag' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -from pkg_resources import get_distribution - -# The full version, including alpha/beta/rc tags. -release = get_distribution('leidenalg').version -del get_distribution - -# The short X.Y version. -version = '.'.join(release.split('.')[:2]) - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# -# today = '' -# -# Else, today_fmt is used as the format for a strftime call. -# -# today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This patterns also effect to html_static_path and html_extra_path -exclude_patterns = [] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -# -# default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -# -# add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# -# add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# -# show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -# keep_warnings = False - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = False - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -#html_theme = 'classic' -# on_rtd is whether we are on readthedocs.org, this line of code grabbed from docs.readthedocs.org -on_rtd = os.environ.get('READTHEDOCS', None) == 'True' - -if not on_rtd: # only import and set the theme if we're building docs locally - import sphinx_rtd_theme - html_theme = 'sphinx_rtd_theme' - html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] - -# otherwise, readthedocs.org uses their theme by default, so no need to specify it - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# -# html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. -# " v documentation" by default. -# -# html_title = u'leidenalg v0.7.0' - -# A shorter title for the navigation bar. Default is the same as html_title. -# -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# -# html_logo = None - -# The name of an image file (relative to this directory) to use as a favicon of -# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# -# html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['.static'] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -# -# html_extra_path = [] - -# If not None, a 'Last updated on:' timestamp is inserted at every page -# bottom, using the given strftime format. -# The empty string is equivalent to '%b %d, %Y'. -# -# html_last_updated_fmt = None - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# -# html_additional_pages = {} - -# If false, no module index is generated. -# -# html_domain_indices = True - -# If false, no index is generated. -# -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Language to be used for generating the HTML full-text search index. -# Sphinx supports the following languages: -# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' -# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh' -# -# html_search_language = 'en' - -# A dictionary with options for the search language support, empty by default. -# 'ja' uses this config value. -# 'zh' user can custom change `jieba` dictionary path. -# -# html_search_options = {'type': 'default'} - -# The name of a javascript file (relative to the configuration directory) that -# implements a search results scorer. If empty, the default will be used. -# -# html_search_scorer = 'scorer.js' - -# Output file base name for HTML help builder. -htmlhelp_basename = 'leidendoc' - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - (master_doc, 'leidenalg.tex', u'leidenalg Documentation', - u'V.A. Traag', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# -# latex_use_parts = False - -# If true, show page references after internal links. -# -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# -# latex_show_urls = False - -# Documents to append as an appendix to all manuals. -# -# latex_appendices = [] - -# It false, will not define \strong, \code, itleref, \crossref ... but only -# \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added -# packages. -# -# latex_keep_old_macro_names = True - -# If false, no module index is generated. -# -# latex_domain_indices = True - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'leidenalg', u'leidenalg Documentation', - [author], 1) -] - -# If true, show URL addresses after external links. -# -# man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - (master_doc, 'leidenalg', u'leidenalg Documentation', - author, 'leidenalg', 'One line description of project.', - 'Miscellaneous'), -] - -autoclass_content = 'both' - -# Documents to append as an appendix to all manuals. -# -# texinfo_appendices = [] - -# If false, no module index is generated. -# -# texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# -# texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -# -# texinfo_no_detailmenu = False - -doctest_global_setup = """ -import igraph as ig -import leidenalg as la -""" diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/karate_CPM.png b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/karate_CPM.png deleted file mode 100644 index 76d6048..0000000 Binary files a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/karate_CPM.png and /dev/null differ diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/karate_modularity.png b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/karate_modularity.png deleted file mode 100644 index ca58726..0000000 Binary files a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/karate_modularity.png and /dev/null differ diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/layers_separate.pdf b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/layers_separate.pdf deleted file mode 100644 index 9955386..0000000 Binary files a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/layers_separate.pdf and /dev/null differ diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/layers_separate.png b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/layers_separate.png deleted file mode 100644 index fdb6990..0000000 Binary files a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/layers_separate.png and /dev/null differ diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/layers_separate.synctex.gz b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/layers_separate.synctex.gz deleted file mode 100644 index c23ba65..0000000 Binary files a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/layers_separate.synctex.gz and /dev/null differ diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/layers_separate.tex b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/layers_separate.tex deleted file mode 100644 index 3e3c044..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/layers_separate.tex +++ /dev/null @@ -1,274 +0,0 @@ -\documentclass[tikz]{standalone} - -\renewcommand{\familydefault}{\sfdefault} -\usepackage{sansmath} -\sansmath - -\usepackage{tikz} %TikZ is required for this to work. Make sure this exists before the next line - -\usepackage{tikz-3dplot} %requires 3dplot.sty to be in same directory, or in your LaTeX installation -\usetikzlibrary{calc} - -\begin{document} - -\definecolor{c0}{RGB}{228,26,28} -\definecolor{c1}{RGB}{55,126,184} - -\begin{tikzpicture}[scale=0.7, - n/.style={circle,draw=black,outer sep=0pt,inner sep=0pt, minimum size=6pt}, - nc0/.style={n,fill=c0}, - nc1/.style={n,fill=c1}, - n2c0/.style={nc0,minimum size=3pt}, - n2c1/.style={nc1,minimum size=3pt}, - e/.style={}] - \begin{scope}[local bounding box=outer box] - - \coordinate (t1) at (2,-3); - \coordinate (t2) at (4,-6); - - %Network t=0 - \node[n2c0] (a0) at (-0,0) {}; - \node[n2c0] (b0) at (-1,0) {}; - \node[n2c0] (c0) at (-0,1) {}; - \node[n2c0] (d0) at (-1,1) {}; - \node[n2c1] (e0) at (-2,1) {}; - \node[n2c1] (f0) at (-1,2) {}; - \node[n2c1] (g0) at (-2,2) {}; - %\draw[-] (d0) -- (b0) -- (a0) -- (c0) -- (d0) -- - % (e0) -- (g0) -- (f0) -- (d0); - - %Network t=1 - \node[n2c0] (a1) at ($(t1) + (-0,0)$) {}; - \node[n2c0] (b1) at ($(t1) + (-1,0)$) {}; - \node[n2c0] (c1) at ($(t1) + (-0,1)$) {}; - \node[n2c0] (d1) at ($(t1) + (-1,1)$) {}; - \node[n2c0] (e1) at ($(t1) + (-2,1)$) {}; - \node[n2c1] (f1) at ($(t1) + (-1,2)$) {}; - \node[n2c1] (g1) at ($(t1) + (-2,2)$) {}; - %\draw[-] (d1) -- (b1) -- (a1) -- (c1) -- (d1) -- - % (e1) -- (g1) -- (f1) -- (d1) (b1) -- (e1); - - %Network t=2 - \node[n2c0] (a2) at ($(t2) + (-0,0)$) {}; - \node[n2c0] (b2) at ($(t2) + (-1,0)$) {}; - \node[n2c0] (c2) at ($(t2) + (-0,1)$) {}; - \node[n2c1] (d2) at ($(t2) + (-1,1)$) {}; - \node[n2c1] (e2) at ($(t2) + (-2,1)$) {}; - \node[n2c1] (f2) at ($(t2) + (-1,2)$) {}; - %\node[nc0] (g2) at (2,4,2) {g}; - %\draw[-] (d2) -- (b2) -- (a2) -- (c2) -- (d2) -- (e2) - % (f2) -- (d2); - - %interslice edge 0 - 1 - \draw[-,dashed] (a0) to[bend left =60] (a1) - (b0) to[bend right=45] (b1) - (c0) to[bend left =45] (c1) - (d0) .. controls ($(t1) + (-2.5,1.5)$) .. (d1) - (e0) to[bend right=45] (e1) - (f0) to[bend left =45] (f1) - (g0) to[bend right=60] (g1); - - %interslice edge 1 - 2 - \draw[-,dashed] (a1) to[bend left =60] (a2) - (b1) to[bend right=45] (b2) - (c1) to[bend left =45] (c2) - (d1) to[bend right=20] (d2) - (e1) to[bend right=45] (e2) - (f1) to[bend left =60] (f2); - - - %\draw[thick,->] (0,0,0) -- (1,0,0) node[anchor=north east]{$x$}; - %\draw[thick,->] (0,0,0) -- (0,1,0) node[anchor=north west]{$y$}; - %\draw[thick,->] (0,0,0) -- (0,0,1) node[anchor=south]{$z$}; - - \draw ($(outer box.north east)+(0,7pt)$) rectangle ($(outer box.south west)+(0,-5pt)$); - \node[anchor=south] at (outer box.north) {Layer 0 (Interslice)}; - \end{scope} - \begin{scope}[xshift=9cm,local bounding box=outer box] - \coordinate (t1) at (2,-3); - \coordinate (t2) at (4,-6); - - %Network t=0 - \node[nc0] (a0) at (-0,0) {}; - \node[nc0] (b0) at (-1,0) {}; - \node[nc0] (c0) at (-0,1) {}; - \node[nc0] (d0) at (-1,1) {}; - \node[nc1] (e0) at (-2,1) {}; - \node[nc1] (f0) at (-1,2) {}; - \node[nc1] (g0) at (-2,2) {}; - \draw[-] (d0) -- (b0) -- (a0) -- (c0) -- (d0) -- - (e0) -- (g0) -- (f0) -- (d0); - - %Network t=1 - \node[n2c0] (a1) at ($(t1) + (-0,0)$) {}; - \node[n2c0] (b1) at ($(t1) + (-1,0)$) {}; - \node[n2c0] (c1) at ($(t1) + (-0,1)$) {}; - \node[n2c0] (d1) at ($(t1) + (-1,1)$) {}; - \node[n2c0] (e1) at ($(t1) + (-2,1)$) {}; - \node[n2c1] (f1) at ($(t1) + (-1,2)$) {}; - \node[n2c1] (g1) at ($(t1) + (-2,2)$) {}; - %\draw[-] (d1) -- (b1) -- (a1) -- (c1) -- (d1) -- - % (e1) -- (g1) -- (f1) -- (d1) (b1) -- (e1); - - %Network t=2 - \node[n2c0] (a2) at ($(t2) + (-0,0)$) {}; - \node[n2c0] (b2) at ($(t2) + (-1,0)$) {}; - \node[n2c0] (c2) at ($(t2) + (-0,1)$) {}; - \node[n2c1] (d2) at ($(t2) + (-1,1)$) {}; - \node[n2c1] (e2) at ($(t2) + (-2,1)$) {}; - \node[n2c1] (f2) at ($(t2) + (-1,2)$) {}; - %\node[nc0] (g2) at (2,4,2) {g}; - %\draw[-] (d2) -- (b2) -- (a2) -- (c2) -- (d2) -- (e2) - % (f2) -- (d2); - - %%interslice edge 0 - 1 - \draw[-,red,opacity=0] (a0) to[bend left =60] (a1) - (b0) to[bend right=45] (b1) - (c0) to[bend left =45] (c1) - (d0) .. controls ($(t1) + (-2.5,1.5)$) .. (d1) - (e0) to[bend right=45] (e1) - (f0) to[bend left =45] (f1) - (g0) to[bend right=60] (g1); - - %%interslice edge 1 - 2 - \draw[-,red,opacity=0] (a1) to[bend left =60] (a2) - (b1) to[bend right=45] (b2) - (c1) to[bend left =45] (c2) - (d1) to[bend right=20] (d2) - (e1) to[bend right=45] (e2) - (f1) to[bend left =60] (f2); - - - %\draw[thick,->] (0,0,0) -- (1,0,0) node[anchor=north east]{$x$}; - %\draw[thick,->] (0,0,0) -- (0,1,0) node[anchor=north west]{$y$}; - %\draw[thick,->] (0,0,0) -- (0,0,1) node[anchor=south]{$z$}; - \draw ($(outer box.north east)+(0,7pt)$) rectangle ($(outer box.south west)+(0,-5pt)$); - \node[anchor=south] at (outer box.north) {Layer 1 ($t = 1$)}; - \end{scope} - \begin{scope}[yshift=-10cm,local bounding box=outer box] - \coordinate (t1) at (2,-3); - \coordinate (t2) at (4,-6); - - %Network t=0 - \node[n2c0] (a0) at (-0,0) {}; - \node[n2c0] (b0) at (-1,0) {}; - \node[n2c0] (c0) at (-0,1) {}; - \node[n2c0] (d0) at (-1,1) {}; - \node[n2c1] (e0) at (-2,1) {}; - \node[n2c1] (f0) at (-1,2) {}; - \node[n2c1] (g0) at (-2,2) {}; - %\draw[-] (d0) -- (b0) -- (a0) -- (c0) -- (d0) -- - % (e0) -- (g0) -- (f0) -- (d0); - - %Network t=1 - \node[nc0] (a1) at ($(t1) + (-0,0)$) {}; - \node[nc0] (b1) at ($(t1) + (-1,0)$) {}; - \node[nc0] (c1) at ($(t1) + (-0,1)$) {}; - \node[nc0] (d1) at ($(t1) + (-1,1)$) {}; - \node[nc0] (e1) at ($(t1) + (-2,1)$) {}; - \node[nc1] (f1) at ($(t1) + (-1,2)$) {}; - \node[nc1] (g1) at ($(t1) + (-2,2)$) {}; - \draw[-] (d1) -- (b1) -- (a1) -- (c1) -- (d1) -- - (e1) -- (g1) -- (f1) -- (d1) (b1) -- (e1); - - %Network t=2 - \node[n2c0] (a2) at ($(t2) + (-0,0)$) {}; - \node[n2c0] (b2) at ($(t2) + (-1,0)$) {}; - \node[n2c0] (c2) at ($(t2) + (-0,1)$) {}; - \node[n2c1] (d2) at ($(t2) + (-1,1)$) {}; - \node[n2c1] (e2) at ($(t2) + (-2,1)$) {}; - \node[n2c1] (f2) at ($(t2) + (-1,2)$) {}; - %\node[nc0] (g2) at (2,4,2) {g}; - %\draw[-] (d2) -- (b2) -- (a2) -- (c2) -- (d2) -- (e2) - % (f2) -- (d2); - - %interslice edge 0 - 1 - \draw[-,red,opacity=0] (a0) to[bend left =60] (a1) - (b0) to[bend right=45] (b1) - (c0) to[bend left =45] (c1) - (d0) .. controls ($(t1) + (-2.5,1.5)$) .. (d1) - (e0) to[bend right=45] (e1) - (f0) to[bend left =45] (f1) - (g0) to[bend right=60] (g1); - - %interslice edge 1 - 2 - \draw[-,red,opacity=0] (a1) to[bend left =60] (a2) - (b1) to[bend right=45] (b2) - (c1) to[bend left =45] (c2) - (d1) to[bend right=20] (d2) - (e1) to[bend right=45] (e2) - (f1) to[bend left =60] (f2); - - - %\draw[thick,->] (0,0,0) -- (1,0,0) node[anchor=north east]{$x$}; - %\draw[thick,->] (0,0,0) -- (0,1,0) node[anchor=north west]{$y$}; - %\draw[thick,->] (0,0,0) -- (0,0,1) node[anchor=south]{$z$}; - \draw ($(outer box.north east)+(0,7pt)$) rectangle ($(outer box.south west)+(0,-5pt)$); - \node[anchor=south] at (outer box.north) {Layer 2 ($t = 2$)}; - \end{scope} - \begin{scope}[xshift=9cm,yshift=-10cm,local bounding box=outer box] - - \coordinate (t1) at (2,-3); - \coordinate (t2) at (4,-6); - - %Network t=0 - \node[n2c0] (a0) at (-0,0) {}; - \node[n2c0] (b0) at (-1,0) {}; - \node[n2c0] (c0) at (-0,1) {}; - \node[n2c0] (d0) at (-1,1) {}; - \node[n2c1] (e0) at (-2,1) {}; - \node[n2c1] (f0) at (-1,2) {}; - \node[n2c1] (g0) at (-2,2) {}; - %\draw[-] (d0) -- (b0) -- (a0) -- (c0) -- (d0) -- - % (e0) -- (g0) -- (f0) -- (d0); - - %Network t=1 - \node[n2c0] (a1) at ($(t1) + (-0,0)$) {}; - \node[n2c0] (b1) at ($(t1) + (-1,0)$) {}; - \node[n2c0] (c1) at ($(t1) + (-0,1)$) {}; - \node[n2c0] (d1) at ($(t1) + (-1,1)$) {}; - \node[n2c0] (e1) at ($(t1) + (-2,1)$) {}; - \node[n2c1] (f1) at ($(t1) + (-1,2)$) {}; - \node[n2c1] (g1) at ($(t1) + (-2,2)$) {}; - %\draw[-] (d1) -- (b1) -- (a1) -- (c1) -- (d1) -- - % (e1) -- (g1) -- (f1) -- (d1) (b1) -- (e1); - - %Network t=2 - \node[nc0] (a2) at ($(t2) + (-0,0)$) {}; - \node[nc0] (b2) at ($(t2) + (-1,0)$) {}; - \node[nc0] (c2) at ($(t2) + (-0,1)$) {}; - \node[nc1] (d2) at ($(t2) + (-1,1)$) {}; - \node[nc1] (e2) at ($(t2) + (-2,1)$) {}; - \node[nc1] (f2) at ($(t2) + (-1,2)$) {}; - %\node[nc0] (g2) at (2,4,2) {g}; - \draw[-] (d2) -- (b2) -- (a2) -- (c2) -- (d2) -- (e2) - (f2) -- (d2); - - %interslice edge 0 - 1 - \draw[-,red,opacity=0] (a0) to[bend left =60] (a1) - (b0) to[bend right=45] (b1) - (c0) to[bend left =45] (c1) - (d0) .. controls ($(t1) + (-2.5,1.5)$) .. (d1) - (e0) to[bend right=45] (e1) - (f0) to[bend left =45] (f1) - (g0) to[bend right=60] (g1); - - %interslice edge 1 - 2 - \draw[-,red,opacity=0] (a1) to[bend left =60] (a2) - (b1) to[bend right=45] (b2) - (c1) to[bend left =45] (c2) - (d1) to[bend right=20] (d2) - (e1) to[bend right=45] (e2) - (f1) to[bend left =60] (f2); - - - %\draw[thick,->] (0,0,0) -- (1,0,0) node[anchor=north east]{$x$}; - %\draw[thick,->] (0,0,0) -- (0,1,0) node[anchor=north west]{$y$}; - %\draw[thick,->] (0,0,0) -- (0,0,1) node[anchor=south]{$z$}; - \draw ($(outer box.north east)+(0,7pt)$) rectangle ($(outer box.south west)+(0,-5pt)$); - \node[anchor=south] at (outer box.north) {Layer 3 ($t = 3$)}; - \end{scope} - -\end{tikzpicture} - -\end{document} diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/resolution_profile.png b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/resolution_profile.png deleted file mode 100644 index 54a9cb3..0000000 Binary files a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/resolution_profile.png and /dev/null differ diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/slices.pdf b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/slices.pdf deleted file mode 100644 index 4205ff4..0000000 Binary files a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/slices.pdf and /dev/null differ diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/slices.png b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/slices.png deleted file mode 100644 index c737062..0000000 Binary files a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/slices.png and /dev/null differ diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/slices.synctex.gz b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/slices.synctex.gz deleted file mode 100644 index ffae92a..0000000 Binary files a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/slices.synctex.gz and /dev/null differ diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/slices.tex b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/slices.tex deleted file mode 100644 index 03fd075..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/slices.tex +++ /dev/null @@ -1,102 +0,0 @@ -\documentclass[tikz]{standalone} - -\renewcommand{\familydefault}{\sfdefault} -\usepackage{sansmath} -\sansmath - -\usepackage{tikz} %TikZ is required for this to work. Make sure this exists before the next line - -\usepackage{tikz-3dplot} %requires 3dplot.sty to be in same directory, or in your LaTeX installation - -\begin{document} - -\tdplotsetmaincoords{70}{110} - -\definecolor{c0}{RGB}{228,26,28} -\definecolor{c1}{RGB}{55,126,184} - -\begin{tikzpicture}[tdplot_main_coords, - n/.style={circle,draw=black,shading=ball,outer sep=0pt,inner sep=0pt, minimum size=6pt}, - nc0/.style={n,ball color=c0}, - nc1/.style={n,ball color=c1}, - e/.style={}] - -%Network t=1 -\draw[fill=lightgray,opacity=0.9] (-1,0,-1) -- (3,0,-1) node[below] - {$\scriptstyle t=1$} -- (3,0,3) -- (-1,0,3) -- (-1,0,-1); -\node[nc0] (a0) at (0,0,0) {}; -\node[nc0] (b0) at (1,0,0) {}; -\node[nc0] (c0) at (0,0,1) {}; -\node[nc0] (d0) at (1,0,1) {}; -\node[nc1] (e0) at (2,0,1) {}; -\node[nc1] (f0) at (1,0,2) {}; -\node[nc1] (g0) at (2,0,2) {}; -\draw[-] (d0) -- (b0) -- (a0) -- (c0) -- (d0) -- (e0) -- (g0) -- (f0) -- (d0); - -%ghost nodes for interslice links -\node[e] (a1) at (0,2,0) {}; -\node[e] (b1) at (1,2,0) {}; -\node[e] (c1) at (0,2,1) {}; -\node[e] (d1) at (1,2,1) {}; -\node[e] (e1) at (2,2,1) {}; -\node[e] (f1) at (1,2,2) {}; -\node[e] (g1) at (2,2,2) {}; - -%interslice edge 0 - 1 -\draw[-,gray] (a0) -- (a1) - (b0) -- (b1) - (c0) -- (c1) - (d0) -- (d1) - (e0) -- (e1) - (f0) -- node[] (f01) {} (f1) - (g0) -- (g1); - -%Network t=2 -\draw[fill=lightgray,opacity=0.9] (-1,2,-1) -- (3,2,-1) node[below] - {$\scriptstyle t=2$} -- (3,2,3) -- (-1,2,3) -- (-1,2,-1); -\node[nc0] (a1) at (0,2,0) {}; -\node[nc0] (b1) at (1,2,0) {}; -\node[nc0] (c1) at (0,2,1) {}; -\node[nc0] (d1) at (1,2,1) {}; -\node[nc0] (e1) at (2,2,1) {}; -\node[nc1] (f1) at (1,2,2) {}; -\node[nc1] (g1) at (2,2,2) {}; -\draw[-] (d1) -- (b1) -- (a1) -- (c1) -- (d1) -- (e1) -- (g1) -- (f1) -- node (fd1) {}(d1) - (b1) -- (e1); - -%ghost nodes for interslice links -\node[e] (a2) at (0,4,0) {}; -\node[e] (b2) at (1,4,0) {}; -\node[e] (c2) at (0,4,1) {}; -\node[e] (d2) at (1,4,1) {}; -\node[e] (e2) at (2,4,1) {}; -\node[e] (f2) at (1,4,2) {}; - -%interslice edge 1 - 2 -\draw[-,gray] (a1) -- (a2) - (b1) -- (b2) - (c1) -- (c2) - (d1) -- (d2) - (e1) -- (e2) - (f1) -- (f2); -%Network t=3 -\draw[fill=lightgray,opacity=0.9] (-1,4,-1) -- (3,4,-1) node[below] - {$\scriptstyle t=3$} -- (3,4,3) -- (-1,4,3) -- (-1,4,-1); -\node[nc0] (a2) at (0,4,0) {}; -\node[nc0] (b2) at (1,4,0) {}; -\node[nc0] (c2) at (0,4,1) {}; -\node[nc1] (d2) at (1,4,1) {}; -\node[nc1] (e2) at (2,4,1) {}; -\node[nc1] (f2) at (1,4,2) {}; -\draw[-] (d2) -- (b2) -- (a2) -- (c2) -- (d2) -- (e2) - (f2) -- (d2); - -%Create equations -\node[anchor=base,align=left] (S_irs) at (0,1.2,3) {Interslice\\ coupling}; -\draw[->] (S_irs) .. controls (1,1,2.5) .. (f01); -\node[anchor=base,align=left] (A_ijs) at (0,3.2,3) {Intraslice\\ link}; -\draw[->] (A_ijs) .. controls (1.5,3,2) .. (fd1); - -\end{tikzpicture} - -\end{document} diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/speed.png b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/speed.png deleted file mode 100644 index 6d8c662..0000000 Binary files a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/figures/speed.png and /dev/null differ diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/implement.rst b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/implement.rst deleted file mode 100644 index 93f4fa4..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/implement.rst +++ /dev/null @@ -1,103 +0,0 @@ -Implementation -============== - -If you have a cool new idea for a better method, and you want to optimise it, -you can easily plug it in the current tool. This section explains how the -package is setup internally, and how you can extend it. Most of this concerns -``C++``, and ``python`` only comes in when exposing the resulting classes. - -Method ------- - -All methods in the end derive from :class:`MutableVertexPartition`, which -implements almost all necessary details, such as moving actual nodes while -maintaining the internal administration. Similarly, it provides all the -necessary functionality for initialising a partition. Additionally, there are -two abstract classes that derive from this base class: -:class:`ResolutionParameterVertexPartition` and -:class:`LinearResolutionParameterVertexPartition` (which in turn derives from -the former class). If you want a method with a resolution parameter, you should -derive from one of these two classes, otherwise, simply from the base class -:class:`MutableVertexPartition`. - -There are two functions that you need to implement yourself: :func:`diff_move` -and :func:`quality`. Note that they should always be consistent, so that we can -double check the internal consistency. You should also ensure that the -diff_move function can be correctly used on any aggregate graph (i.e. moving a -node in the aggregate graph indeed corresponds to moving a set of nodes in the -individual graph). - -That's it. In principle, you could now use and test the method in ``C++``. - -Python ------- - -Exposing the method to ``python`` takes a bit more effort. There are various -places in which you need to change/add things. In the following, we assume you -created a new class called ``CoolVertexPartition``. In order of dependencies, it -goes as follows: - -1. Your own new VertexPartition class should add some specific methods. In - particular, you need to ensure you create a method - - .. code-block:: c++ - - CoolVertexPartition* CoolVertexPartition::create(Graph* graph) - { - return new CoolVertexPartition(graph); - } - - - and - - .. code-block:: c++ - - CoolVertexPartition* CoolVertexPartition::create(Graph* graph, vector const& membership) - { - return new CoolVertexPartition(graph, membership); - } - - - These methods ensure that based on a current partition, we can create a new - partition (without knowing its type). - -2. In ``python_partition_interface.cpp`` some methods need to be added. In - particular - - .. code-block:: c++ - - PyObject* _new_CoolVertexPartition(PyObject *self, PyObject *args, PyObject *keywds) - - - You should be able to simply copy an existing method, and adapt it to your - own needs. - -3. These methods need to be exposed in ``pynterface.h``. In particular, you - need to add the method you created in step (2) to ``leiden_funcs[]``. - Again, you should be able to simply copy an existing line. - -4. You can then finally create the Python class in ``VertexPartition.py``. The - base class derives from the :class:`VertexClustering` from :mod:`igraph`, so - that it is compatible with all operations in :mod:`igraph`. You should add - the method as follows:: - - class CoolVertexPartition(MutableVertexPartition): - - def __init__(self, ... ): - ... - - Again, you should be able to copy the outline for another class and adapt it - to your own needs. Don't forget to change to ``docstring`` to update the - documentation so that everybody knows how your new cool method works. - -5. Expose your newly created ``python`` class directly in ``__init__.py`` by - importing it:: - - from .VertexPartition import CoolVertexPartition - -That's it! You're done and should now be able to find communities using your -new :class:`CoolVertexPartition`: - ->>> la.find_partition(G, la.CoolVertexPartition); # doctest: +SKIP - - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/index.rst b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/index.rst deleted file mode 100644 index e8e22fa..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/index.rst +++ /dev/null @@ -1,27 +0,0 @@ -.. la documentation master file, created by - sphinx-quickstart on Fri Oct 21 11:26:44 2016. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -leidenalg documentation -===================== - -.. toctree:: - :maxdepth: 2 - - install - intro - advanced - multiplex - implement - -Reference -========= - -.. toctree:: - :maxdepth: 2 - - reference - -* :ref:`genindex` -* :ref:`search` diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/install.rst b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/install.rst deleted file mode 100644 index 25c4821..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/install.rst +++ /dev/null @@ -1,36 +0,0 @@ -Installation -============ - -In short: ``pip install leidenalg``. -Alternatively, use `Anaconda `_ and get -the conda packages from the `conda-forge channel -`_, which supports both Unix, Mac OS and -Windows. - -For Unix like systems it is possible to install from source. For Windows this is -overly complicated, and you are recommended to use the binary wheels. There are -two things that are needed by this package: the igraph ``C`` core library and -the python-igraph python package. For both, please see http://igraph.org. - -Make sure you have all necessary tools for compilation. In Ubuntu this can be -installed using ``sudo apt-get install build-essential``, please refer to the -documentation for your specific system. Make sure that not only ``gcc`` is -installed, but also ``g++``, as the ``leidenalg`` package is programmed in ``C++``. - -You can check if all went well by running a variety of tests using ``python -setup.py test``. - -There are basically two installation modes, similar to the python-igraph package -itself (from which most of the ``setup.py`` comes). - -1. No ``C`` core library is installed yet. The ``C`` core - library of igraph that is provided within the ``leidenalg`` package is - compiled. -2. A ``C`` core library is already installed. In this case, you may link - dynamically to the already installed version by specifying - ``--no-pkg-config``. This is probably also the version that is used by the - igraph package, but you may want to double check this. - -In case the ``python-igraph`` package is already installed before, make sure that -both use the **same versions** (at least the same minor version, which should be -API compatible). \ No newline at end of file diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/intro.rst b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/intro.rst deleted file mode 100644 index fd4b059..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/intro.rst +++ /dev/null @@ -1,107 +0,0 @@ -Introduction -============ - -The :mod:`leidenalg` package facilitates community detection of networks and -builds on the package :mod:`igraph`. We abbreviate the :mod:`leidenalg` package as -``la`` and the ``igraph`` package as ``ig`` in all ``Python`` code throughout -this documentation. Although the options in the :mod:`leidenalg` community -detection package are extensive, most people are presumably simply interested -in detecting communities with a robust method that works well. This -introduction explains how to do that. - -For those without patience (and some prior experience), if you simply want to -detect communities given a graph ``G`` using modularity, you simply use - -.. testsetup:: - - G = ig.Graph.Erdos_Renyi(100, p=5./100); - ->>> partition = la.find_partition(G, la.ModularityVertexPartition); - -That's it. - -The result ``partition`` is in this case a -:class:`~leidenalg.ModularityVertexPartition` which is derived from the -:mod:`igraph` type :class:`ig.VertexClustering`, see the `documentation -`_ -for more details. - -Why then should you use this package rather than for example the Louvain -algorithm :func:`community_multilevel` built into :mod:`igraph`? If you want to -use modularity, and you work with a simple undirected, unweighted graph, then -indeed you may use the built-in method. For anything else, the functionality is -not built-in and this package is for you. Moreover, the Leiden algorithm is -typically faster than the Louvain algorithm and returns partitions of a higher -quality. - -For those less familiar with :mod:`igraph`, let us work out an example more -fully. First, we need to import the relevant packages: - ->>> import igraph as ig ->>> import leidenalg as la - -Let us then look at one of the most famous examples of network science: the -Zachary karate club (it even has a prize named after it): - ->>> G = ig.Graph.Famous('Zachary') - -Now detecting communities with modularity is straightforward, as demonstrated -earlier: - ->>> partition = la.find_partition(G, la.ModularityVertexPartition) - -You can simply plot the results as follows: - ->>> ig.plot(partition) # doctest: +SKIP - -.. image:: figures/karate_modularity.png - -In this case, the algorithm actually finds the optimal partition (for small -graphs like these you can check this using -:func:`~ig.Graph.community_optimal_modularity` in the :mod:`igraph` package), -but this is generally not the case (although the algorithm should do well). -Although this is the optimal partition, it does not correspond to the split in -two factions that was observed for this particular network. We can uncover that -split in two using a different method, :class:`~leidenalg.CPMVertexPartition`: - ->>> partition = la.find_partition(G, la.CPMVertexPartition, -... resolution_parameter = 0.05); ->>> ig.plot(partition) # doctest: +SKIP - -.. image:: figures/karate_CPM.png - -Note that any additional ``**kwargs`` passed to :func:`~leidenalg.find_partition` -is passed on to the constructor of the given ``partition_type``. In this case, -we can pass the ``resolution_parameter``, but we could also pass ``weights`` or -``node_sizes``. - -This is the real benefit of using this package: it provides implementations for -six different methods (see :ref:`Reference`), and works also on directed and -weighted graphs. In addition, it also provides flexible functionality for -customizing to some extent the optimisation routines (see :ref:`Advanced`). -Finally, it also allows to work with more complex multiplex graphs (see -:ref:`Multiplex`). - -The Leiden algorithm [1] extends the Louvain algorithm [2], which is widely -seen as one of the best algorithms for detecting communities. However, the -Louvain algorithm can lead to arbitrarily badly connected communities, whereas -the Leiden algorithm guarantees communities are well-connected. In fact, it -converges towards a partition in which all subsets of all communities are -locally optimally assigned. Finally, the Leiden algorithm is also much faster, -because it relies on a fast local move routine. The -`"canonical" `_ -Leiden algorithm is implemented -in ``Java`` and is faster than this implementation, but less extensive. - -References ----------- - -.. [1] Traag, V.A., Waltman. L., Van Eck, N.-J. (2018). From Louvain to - Leiden: guaranteeing well-connected communities. - `arXiv:1810.08473 `_ - -.. [2] Blondel, V. D., Guillaume, J.-L., Lambiotte, R., & Lefebvre, E. - (2008). Fast unfolding of communities in large networks. Journal of - Statistical Mechanics: Theory and Experiment, 10008(10), 6. - `10.1088/1742-5468/2008/10/P10008 `_ - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/multiplex.rst b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/multiplex.rst deleted file mode 100644 index a5ee16d..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/multiplex.rst +++ /dev/null @@ -1,378 +0,0 @@ -Multiplex -========= - -The implementation of multiplex community detection builds on ideas in [1]_. -The most basic form simply considers two or more graphs which are defined on -the same vertex set, but which have differing edge sets. In this context, each -node is identified with a single community, and cannot have different -communities for different graphs. We call this *layers* of graphs in this -context. This format is actually more flexible than it looks, but you have to -construct the layer graphs in a smart way. Instead of having layers of graphs -which are always identified on the same vertex set, you could define *slices* -of graphs which do not necessarily have the same vertex set. Using slices we -would like to assign a node to a community for each slice, so that the -community for a node can be different for different slices, rather than always -being the same for all layers. We can translate *slices* into *layers* but it -is not an easy transformation to grasp fully. But by doing so, we can again -rely on the same machinery we developed for dealing with layers. - -Throughout the remained of this section, we assume an optimiser has been -created: - ->>> optimiser = la.Optimiser() - -Layer multiplex ---------------- - -If we have two graphs which are identified on exactly the same vertex set, we -say we have two *layers*. For example, suppose graph ``G_telephone`` contains -the communication between friends over the telephone and that the graph -``G_email`` contains the communication between friends via mail. The exact same -vertex set then means that ``G_telephone.vs[i]`` is identical to the node -``G_email.vs[i]``. For each layer we can separately specify the type of -partition that we look for. In principle they could be different for each -layer, but for now we will assume the type of partition is the same for all -layers. The quality of all partitions combined is simply the sum of the -individual qualities for the various partitions, weighted by the -``layer_weight``. If we denote by :math:`q_k` the quality of layer :math:`k` -and the weight by :math:`w_k`, the overall quality is then - -.. math:: q = \sum_k w_k q_k. - -The optimisation algorithm is no different from the standard algorithm. We -simply calculate the overall difference of moving a node to another community -as the sum of the individual differences in all partitions. The rest -(aggregating and repeating on the aggregate partition) simple proceeds as -usual. - -The most straightforward way to use this is then to use -:func:`~leidenalg.find_partition_multiplex`: - -.. testsetup:: - - G_telephone = ig.Graph.Erdos_Renyi(100, 0.1); - G_email = ig.Graph.Erdos_Renyi(100, 0.1); - ->>> membership, improv = la.find_partition_multiplex( -... [G_telephone, G_email], -... la.ModularityVertexPartition); - -.. note:: You may need to carefully reflect how you want to weigh the importance - of an individual layer. Since the :class:`~leidenalg.ModularityVertexPartition` - is normalised by the number of links, you essentially weigh layers the same, - independent of the number of links. This may be undesirable, in which case it - may be better to use :class:`RBConfigurationVertexPartition`, which is - unnormalised. Alternatively, you may specify different ``layer_weights``. - -Similar to the simpler function :func:`~leidenalg.find_partition`, it is a simple -helper function. The function returns a membership vector, because the -membership for all layers is identical. You can also control the partitions and -optimisation in more detail. Perhaps it is better to use -:class:`~leidenalg.CPMVertexPartition` with different resolution parameter for -example for different layers of the graph. For example, using email creates a -more connected structure because multiple people can be involved in a single -mail, which may require a higher resolution parameter for the email graph. - ->>> part_telephone = la.CPMVertexPartition( -... G_telephone, resolution_parameter=0.01); ->>> part_email = la.CPMVertexPartition( -... G_email, resolution_parameter=0.3); ->>> diff = optimiser.optimise_partition_multiplex( -... [part_telephone, part_email]); - -Note that ``part_telephone`` and ``part_email`` contain exactly the same -partition, in the sense that ``part_telephone.membership == -part_email.membership``. The underlying graph is of course different, and hence -the individual quality will also be different. - -Some layers may have a more important role in the partition and this can be -indicated by the ``layer_weight``. Using half the weight for the email layer for -example would be possible as follows: - ->>> diff = optimiser.optimise_partition_multiplex( -... [part_telephone, part_email], -... layer_weights=[1,0.5]); - -Negative links -^^^^^^^^^^^^^^ - -The layer weights are especially useful when negative links are present, -representing for example conflict or animosity. Most methods (except CPM) only -accept positive weights. In order to deal with graphs that do have negative -links, a solution is to separate the graph into two layers: one layer with -positive links, the other with only negative links [2]_. In general, we would -like to have relatively many positive links within communities, while for -negative links the opposite holds: we want many negative links between -communities. We can easily do this within the multiplex layer framework by -passing in a negative layer weight. For example, suppose we have a graph ``G`` -with possibly negative weights. We can then separate it into a positive and -negative graph as follows: - -.. testsetup:: - - import numpy as np - G = ig.Graph.Erdos_Renyi(100, 0.1) - G.es['weight'] = np.random.randn(G.ecount()); - ->>> G_pos = G.subgraph_edges(G.es.select(weight_gt = 0), delete_vertices=False); ->>> G_neg = G.subgraph_edges(G.es.select(weight_lt = 0), delete_vertices=False); ->>> G_neg.es['weight'] = [-w for w in G_neg.es['weight']]; - -We can then simply detect communities using; - ->>> part_pos = la.ModularityVertexPartition(G_pos, weights='weight'); ->>> part_neg = la.ModularityVertexPartition(G_neg, weights='weight'); ->>> diff = optimiser.optimise_partition_multiplex( -... [part_pos, part_neg], -... layer_weights=[1,-1]); - -Bipartite -^^^^^^^^^ - -For some methods it may be possible to to community detection in bipartite -networks. Bipartite networks are special in the sense that they have only links -between the two different classes, and no links within a class are allowed. For -example, there might be products and customers, and there is a link between -:math:`i` and :math:`j` if a product :math:`i` is bought by a customer -:math:`j`. In this case, there are no links among products, nor among -customers. One possible approach is simply project this bipartite network into -the one or the other class and then detect communities. But then the -correspondence between the communities in the two different projections is -lost. Detecting communities in the bipartite network can therefore be useful. - -Setting this up requires a bit of a creative approach, which is why it is also -explicitly explained here. We will explain it for the CPM method, and then show -how this works the same for some related measures. In the case of CPM you would -like to be able to set three different resolution parameters: one for within -each class :math:`\gamma_0, \gamma_1`, and one for the links between classes, -:math:`\gamma_{01}`. Then the formulation would be - -.. math:: Q = \sum_{ij} - [A_{ij} - - (\gamma_0\delta(s_i,0) + \gamma_1\delta(s_i,1)) \delta(s_i,s_j) - - \gamma_{01}(1 - \delta(s_i, s_j)) - ]\delta(\sigma_i, \sigma_j) - -where :math:`s_i` denotes the bipartite class of a node and :math:`\sigma_i` -the community of the node as elsewhere in the documentation. Rewriting as a sum -over communities gives a bit more insight - -.. math:: Q = \sum_c (e_c - - \gamma_{01} 2 n_c(0) n_c(1) - - \gamma_0 n^2_c(0) - - \gamma_1 n^2_c(1)) - -where :math:`n_c(0)` is the number of nodes in community :math:`c` of class 0 -(and similarly for 1) and :math:`e_c` is the number of edges within community -:math:`c`. We denote by :math:`n_c = n_c(0) + n_c(1)` the total number of nodes -in community :math:`c`. Note that - -.. math:: n_c^2 &= (n_c(0) + n_c(1))^2 \\ - &= n_c(0)^2 + 2 n_c(0) n_c(1) + n_c(1)^2 - -We then create three different layers: (1) all nodes have ``node_size = 1`` and -all relevant links; (2) only nodes of class 0 have ``node_size = 1`` and no -links; (3) only nodes of class 1 have ``node_size = 1`` and no links. If we add -the first with resolution parameter :math:`\gamma_{01}`, and the others with -resolution parameters :math:`\gamma_{01} - \gamma_0` and :math:`\gamma_{01} -- \gamma_1`, but the latter two with a layer weight of -1 while the first -layer has layer weight 1, we obtain the following: - -.. math:: Q &= \sum_c (e_c - \gamma_{01} n_c^2) - -\sum_c (- (\gamma_{01} - \gamma_0) n_c(0)^2) - -\sum_c (- (\gamma_{01} - \gamma_1) n_c(0)^2) \\ - &= \sum_c [e_c - \gamma_{01} 2 n_c(0) n_c(1) - - \gamma_{01} n_c(0)^2 - - \gamma_{01} n_c(1)^2) - + ( \gamma_{01} - \gamma_0) n_c(0)^2 - + ( \gamma_{01} - \gamma_1) n_c(1)^2 - ] \\ - &= \sum_c (e_c - \gamma_{01} 2 n_c(0) n_c(1) - - \gamma_{0} n_c(0)^2 - - \gamma_{1} n_c(1)^2) \\ - -Hence detecting communities with these three layers corresponds to detecting -communities in bipartite networks. Although we worked out this example for -directed network including self-loops (since it is easiest), it works out -similarly for undirected networks (with or without self-loops). This only -corresponds to the CPM method. However, using a little additional trick, we can -also make this work for modularity. Essentially, modularity is nothing else -than CPM with the ``node_size`` set to the degree, and the resolution parameter -set to :math:`\gamma = \frac{1}{2m}`. In particular, in general (i.e. not -specifically for bipartite graph) if ``node_sizes=G.degree()`` we then obtain - -.. math:: Q = \sum_{ij} A_{ij} - \gamma k_i k_j - -In the case of bipartite graphs something similar is obtained, but then -correctly adapted (as long as the resolution parameter is also appropriately -rescaled). Note that this is only possible for modularity for undirected -graphs. Hence, we can also detect communities in bipartite networks using -modularity by using this little trick. The definition of modularity for -bipartite graphs is identical to the formulation of bipartite modularity -provided in [3]_. - -All of this has been implemented in the constructor -:func:`~leidenalg.CPMVertexPartition.Bipartite`. You can simply pass in a -bipartite network with the classes appropriately defined in ``G.vs['type']`` or -equivalent. This function assumes the two classes are coded by ``0`` and ``1``, -and if this is not the case it will try to convert it into such categories by -:func:`ig.UniqueIdGenerator`. - -An explicit example of this: - -.. testsetup:: - - import numpy as np - G.vs['type'] = np.random.randint(0, 2, G.vcount()) - ->>> p_01, p_0, p_1 = la.CPMVertexPartition.Bipartite(G, -... resolution_parameter_01=0.1); ->>> diff = optimiser.optimise_partition_multiplex([p_01, p_0, p_1], -... layer_weights=[1, -1, -1]); - -Slices to layers ----------------- - -The multiplex formulation as layers has two limitations: (1) each graph needs to -have an identical vertex set; (2) each node is only in a single community. -Ideally, one would like to relax both these requirements, so that you can work -with graphs that do not need to have identical nodes and where nodes can be in -different communities in different layers. For example, a person could be in one -community when looking at his professional relations, but in another community -looking at his personal relations. Perhaps more commonly: a person could be in -one community at time 1 and in another community at time 2. - -Fortunately, this is also possible with this package. We call the more general -formulation *slices* in contrast to the *layers* required by the earlier -functions. Slices are then just different graphs, which do not need to have the -same vertex set in any way. The idea is to build one big graph out of all the -slices and then decompose it again in layers that correspond with slices. The -key element is that some slices are coupled: for example two consecutive time -windows, or simply two different slices of types of relations. Because any two -slices can be coupled in theory, we represent the coupling itself again with a -graph. The nodes of this *coupling graph* thus are slices, and the (possibly -weighted) links in the coupling graph represent the (possibly weighted) -couplings between slices. Below an example with three different time slices, -where slice 1 is coupled to slice 2, which in turn is coupled to slice 3: - -.. image:: figures/slices.png - -The coupling graph thus consists of three nodes and a simple line structure: ``1 --- 2 -- 3``. We convert this into layers by putting all nodes of all slices in -one big network. Each node is thus represented by a tuple ``(node, slice)`` in a -certain sense. Out of this big network, we then only take those edges that are -defined between nodes of the same slice, which then constitutes a single layer. -Finally, we need one more layer for the couplings. In addition, for methods such -as :class:`~leidenalg.CPMVertexPartition`, so-called ``node_sizes`` are required, and for -them to properly function, they should be set to 0 (which is handled -appropriately by the package). We thus obtain equally many layers as we have -slices, and we need one more layer for representing the interslice couplings. -For the example provided above, we thus obtain the following: - -.. image:: figures/layers_separate.png - -To transform slices into layers using a coupling graph, this package provides -:func:`~leidenalg.layers_to_slices`. For the example above, this would function -as follows. First create the coupling graph assuming we have three slices -``G_1``, ``G_2`` and ``G_3``: - -.. testsetup:: - - G_1 = ig.Graph.Erdos_Renyi(100, 0.1) - G_2 = ig.Graph.Erdos_Renyi(100, 0.1) - G_3 = ig.Graph.Erdos_Renyi(100, 0.1) - - G_1.vs['id'] = range(100) - G_2.vs['id'] = range(100) - G_3.vs['id'] = range(100) - ->>> G_coupling = ig.Graph.Formula('1 -- 2 -- 3'); ->>> G_coupling.es['weight'] = 0.1; # Interslice coupling strength ->>> G_coupling.vs['slice'] = [G_1, G_2, G_3] - -Then we convert them to layers - ->>> layers, interslice_layer, G_full = la.slices_to_layers(G_coupling); - -Now we still have to create partitions for all the layers. We can freely choose -here to use the same partition types for all partitions, or to use different -types for different layers. - -.. warning:: The interslice layer should usually be of type - :class:`~leidenalg.CPMVertexPartition` with a ``resolution_parameter=0`` and - ``node_sizes`` set to 0. The ``G.vs[node_size]`` is automatically set to 0 - for all nodes in the interslice layer in :func:`~leidenalg.slices_to_layers`, - so you can simply pass in the attribute ``node_size``. Unless you know what - you are doing, simply use these settings. - -.. warning:: When using methods that accept a node_size argument, this should - always be used. This is the case for :class:`~leidenalg.CPMVertexPartition`, - :class:`~leidenalg.RBERVertexPartition`, :class:`~leidenalg.SurpriseVertexPartition` and - :class:`~leidenalg.SignificanceVertexPartition`. - -.. testsetup:: - - gamma = 0.5; - ->>> partitions = [la.CPMVertexPartition(H, node_sizes='node_size', -... weights='weight', resolution_parameter=gamma) -... for H in layers]; ->>> interslice_partition = la.CPMVertexPartition(interslice_layer, resolution_parameter=0, -... node_sizes='node_size', weights='weight'); - -You can then simply optimise these partitions as before using -:func:`~leidenalg.Optimiser.optimise_partition_multiplex`: - ->>> diff = optimiser.optimise_partition_multiplex(partitions + [interslice_partition]); - -Temporal community detection ----------------------------- - -One of the most common tasks for converting slices to layers is that we have -slices at different points in time. We call this temporal community detection. -Because it is such a common task, we provide several helper functions to -simplify the above process. Let us assume again that we have three slices -``G_1``, ``G_2`` and ``G_3`` as in the example above. The most straightforward -function is :func:`~leidenalg.find_partition_temporal`: - ->>> membership, improvement = la.find_partition_temporal( -... [G_1, G_2, G_3], -... la.CPMVertexPartition, -... interslice_weight=0.1, -... resolution_parameter=gamma) - -This function only returns the membership vectors for the different time slices, -rather than actual partitions. - -Rather than directly detecting communities, you can also obtain the actual -partitions in a slightly more convenient way using -:func:`~leidenalg.time_slices_to_layers`: - ->>> layers, interslice_layer, G_full = \ -... la.time_slices_to_layers([G_1, G_2, G_3], -... interslice_weight=0.1); ->>> partitions = [la.CPMVertexPartition(H, node_sizes='node_size', -... weights='weight', -... resolution_parameter=gamma) -... for H in layers]; ->>> interslice_partition = \ -... la.CPMVertexPartition(interslice_layer, resolution_parameter=0, -... node_sizes='node_size', weights='weight'); ->>> diff = optimiser.optimise_partition_multiplex(partitions + [interslice_partition]); - -Both these functions assume that the interslice coupling is always identical for -all slices. If you want more finegrained control, you will have to use the -earlier explained functions. - -References ----------- -.. [1] Mucha, P. J., Richardson, T., Macon, K., Porter, M. A., & Onnela, J.-P. - (2010). Community structure in time-dependent, multiscale, and multiplex - networks. Science, 328(5980), 876–8. `10.1126/science.1184819 - `_ -.. [2] Traag, V. A., & Bruggeman, J. (2009). Community detection in networks - with positive and negative links. Physical Review E, 80(3), 036115. - `10.1103/PhysRevE.80.036115 `_ -.. [3] Barber, M. J. (2007). Modularity and community detection in bipartite - networks. Physical Review E, 76(6), 066102. `10.1103/PhysRevE.76.066102 - `_ \ No newline at end of file diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/reference.rst b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/reference.rst deleted file mode 100644 index cc42acc..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/doc/source/reference.rst +++ /dev/null @@ -1,79 +0,0 @@ -Reference -=============== - -Module functions ----------------- - -.. automodule:: leidenalg - :members: find_partition, - find_partition_multiplex, - find_partition_temporal, - slices_to_layers, - time_slices_to_layers, - :undoc-members: - :show-inheritance: - -Optimiser ---------- - -.. autoclass:: Optimiser - :members: - :undoc-members: - :show-inheritance: - -MutableVertexPartition ----------------------- - -.. autoclass:: leidenalg.VertexPartition.MutableVertexPartition - :members: - :undoc-members: - :show-inheritance: - -ModularityVertexPartition -------------------------- - -.. autoclass:: ModularityVertexPartition - :members: - :undoc-members: - :show-inheritance: - -RBConfigurationVertexPartition ------------------------------- - -.. autoclass:: RBConfigurationVertexPartition - :members: resolution_parameter - :undoc-members: - :show-inheritance: - -RBERVertexPartition -------------------- - -.. autoclass:: RBERVertexPartition - :members: - :undoc-members: - :show-inheritance: - -CPMVertexPartition ------------------- - -.. autoclass:: CPMVertexPartition - :members: - :undoc-members: - :show-inheritance: - -SignificanceVertexPartition ---------------------------- - -.. autoclass:: SignificanceVertexPartition - :members: - :undoc-members: - :show-inheritance: - -SurpriseVertexPartition ------------------------ - -.. autoclass:: SurpriseVertexPartition - :members: - :undoc-members: - :show-inheritance: - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/CPMVertexPartition.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/CPMVertexPartition.h deleted file mode 100644 index 639d9ed..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/CPMVertexPartition.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef CPMVERTEXPARTITION_H -#define CPMVERTEXPARTITION_H - -#include - -class CPMVertexPartition : public LinearResolutionParameterVertexPartition -{ - public: - CPMVertexPartition(Graph* graph, - vector membership, double resolution_parameter); - CPMVertexPartition(Graph* graph, - vector membership); - CPMVertexPartition(Graph* graph, - double resolution_parameter); - CPMVertexPartition(Graph* graph); - virtual ~CPMVertexPartition(); - virtual CPMVertexPartition* create(Graph* graph); - virtual CPMVertexPartition* create(Graph* graph, vector const& membership); - - virtual double diff_move(size_t v, size_t new_comm); - virtual double quality(double resolution_parameter); - - protected: - private: -}; - -#endif // CPMVERTEXPARTITION_H diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/GraphHelper.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/GraphHelper.h deleted file mode 100644 index de578b8..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/GraphHelper.h +++ /dev/null @@ -1,226 +0,0 @@ -#ifndef GRAPHHELPER_INCLUDED -#define GRAPHHELPER_INCLUDED - -#include - -#include -#include -#include -#include - -//#ifdef DEBUG -#include - using std::cerr; - using std::endl; -//#endif - -class MutableVertexPartition; - -using std::vector; -using std::pair; -using std::set; -using std::deque; -using std::make_pair; - -vector range(size_t n); - -bool orderCSize(const size_t* A, const size_t* B); - -double KL(double q, double p); -double KLL(double q, double p); - -template T sum(vector vec) -{ - T sum_of_elems = T(); - for (T x : vec) - sum_of_elems += x; - return sum_of_elems; -}; - -class Exception : public std::exception -{ - public: - Exception(const char* str) - { - this->str = str; - } - - virtual const char* what() const throw() - { - return this->str; - } - - private: - const char* str; - -}; - -inline size_t get_random_int(size_t from, size_t to, igraph_rng_t* rng) -{ - return igraph_rng_get_integer(rng, from, to); -}; - -void shuffle(vector& v, igraph_rng_t* rng); - -class Graph -{ - public: - Graph(igraph_t* graph, - vector const& edge_weights, - vector const& node_sizes, - vector const& node_self_weights, int correct_self_loops); - Graph(igraph_t* graph, - vector const& edge_weights, - vector const& node_sizes, - vector const& node_self_weights); - Graph(igraph_t* graph, - vector const& edge_weights, - vector const& node_sizes, int correct_self_loops); - Graph(igraph_t* graph, - vector const& edge_weights, - vector const& node_sizes); - Graph(igraph_t* graph, vector const& edge_weights, int correct_self_loops); - Graph(igraph_t* graph, vector const& edge_weights); - Graph(igraph_t* graph, vector const& node_sizes, int correct_self_loops); - Graph(igraph_t* graph, vector const& node_sizes); - Graph(igraph_t* graph, int correct_self_loops); - Graph(igraph_t* graph); - Graph(); - ~Graph(); - - int has_self_loops(); - size_t possible_edges(); - size_t possible_edges(size_t n); - - Graph* collapse_graph(MutableVertexPartition* partition); - - vector const& get_neighbour_edges(size_t v, igraph_neimode_t mode); - vector const& get_neighbours(size_t v, igraph_neimode_t mode); - size_t get_random_neighbour(size_t v, igraph_neimode_t mode, igraph_rng_t* rng); - - inline size_t get_random_node(igraph_rng_t* rng) - { - return get_random_int(0, this->vcount() - 1, rng); - }; - - inline igraph_t* get_igraph() { return this->_graph; }; - - inline size_t vcount() { return igraph_vcount(this->_graph); }; - inline size_t ecount() { return igraph_ecount(this->_graph); }; - inline double total_weight() { return this->_total_weight; }; - inline size_t total_size() { return this->_total_size; }; - inline int is_directed() { return this->_is_directed; }; - inline double density() { return this->_density; }; - inline int correct_self_loops() { return this->_correct_self_loops; }; - inline int is_weighted() { return this->_is_weighted; }; - - // Get weight of edge based on attribute (or 1.0 if there is none). - inline double edge_weight(size_t e) - { - #ifdef DEBUG - if (e > this->_edge_weights.size()) - throw Exception("Edges outside of range of edge weights."); - #endif - return this->_edge_weights[e]; - }; - - inline void edge(size_t eid, size_t &from, size_t &to) { - from = IGRAPH_FROM(this->get_igraph(), eid); - to = IGRAPH_TO(this->get_igraph(), eid); - } - - inline vector edge(size_t e) - { - vector edge(2); - this->edge(e, edge[0], edge[1]); - return edge; - } - - // Get size of node based on attribute (or 1.0 if there is none). - inline size_t node_size(size_t v) - { return this->_node_sizes[v]; }; - - // Get self weight of node based on attribute (or set to 0.0 if there is none) - inline double node_self_weight(size_t v) - { return this->_node_self_weights[v]; }; - - inline size_t degree(size_t v, igraph_neimode_t mode) - { - if (mode == IGRAPH_IN || !this->is_directed()) - return this->_degree_in[v]; - else if (mode == IGRAPH_OUT) - return this->_degree_out[v]; - else if (mode == IGRAPH_ALL) - return this->_degree_all[v]; - else - throw Exception("Incorrect mode specified."); - }; - - inline double strength(size_t v, igraph_neimode_t mode) - { - if (mode == IGRAPH_IN || !this->is_directed()) - return this->_strength_in[v]; - else if (mode == IGRAPH_OUT) - return this->_strength_out[v]; - else - throw Exception("Incorrect mode specified."); - }; - - inline void set_features(std::vector< std::vector > names) { _names = names; }; - inline std::vector get_features(size_t node) { return _names[node]; }; - inline std::vector< std::vector > get_features() { return _names; }; - - protected: - - int _remove_graph; - - private: - igraph_t* _graph; - igraph_vector_t _temp_igraph_vector; - - // Utility variables to easily access the strength of each node - vector _strength_in; - vector _strength_out; - - vector _degree_in; - vector _degree_out; - vector _degree_all; - - vector _edge_weights; // Used for the weight of the edges. - vector _node_sizes; // Used for the size of the nodes. - vector _node_self_weights; // Used for the self weight of the nodes. - - void cache_neighbours(size_t v, igraph_neimode_t mode); - vector _cached_neighs_from; size_t _current_node_cache_neigh_from; - vector _cached_neighs_to; size_t _current_node_cache_neigh_to; - vector _cached_neighs_all; size_t _current_node_cache_neigh_all; - - void cache_neighbour_edges(size_t v, igraph_neimode_t mode); - vector _cached_neigh_edges_from; size_t _current_node_cache_neigh_edges_from; - vector _cached_neigh_edges_to; size_t _current_node_cache_neigh_edges_to; - vector _cached_neigh_edges_all; size_t _current_node_cache_neigh_edges_all; - - double _total_weight; - size_t _total_size; - int _is_weighted; - bool _is_directed; - - int _correct_self_loops; - double _density; - - std::vector< std::vector > _names; - - void init_admin(); - void set_defaults(); - void set_default_edge_weight(); - void set_default_node_size(); - void set_self_weights(); - -}; - -// We need this ugly way to include the MutableVertexPartition -// to overcome a circular linkage problem. -#include "MutableVertexPartition.h" - -#endif // GRAPHHELPER_INCLUDED - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/HybridVertexPartition.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/HybridVertexPartition.h deleted file mode 100644 index 047d43c..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/HybridVertexPartition.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// Created by Mohamed Abdel-Hafiz on 10/7/21. -// - -#ifndef LEIDENALG_IGRAPH_HYBRIDVERTEXPARTITION_H -#define LEIDENALG_IGRAPH_HYBRIDVERTEXPARTITION_H - -#include "MutableVertexPartition.h" -#include "vector" -#include "dataanalysis.h" -#include "statistics.h" -#include "ap.h" - -class HybridVertexPartition : public MutableVertexPartition -{ -public: - HybridVertexPartition(Graph* graph, - vector const& membership); - HybridVertexPartition(Graph* graph); - HybridVertexPartition(Graph* graph, std::vector< std::vector > input_dataset, std::vector target, - double k1, double k2, double k3, double k4); - HybridVertexPartition(Graph* graph, - vector const& membership, - std::vector< std::vector > input_dataset, std::vector target, - double k1, double k2, double k3, double k4); - virtual ~HybridVertexPartition(); - virtual HybridVertexPartition* create(Graph* graph); - virtual HybridVertexPartition* create(Graph* graph, vector const& membership); - - virtual double diff_move(size_t v, size_t new_comm); - virtual double quality(); - virtual double calculate_correlation_diff(size_t v, size_t new_comm); -// void move_node(size_t v,size_t new_comm); - -protected: - std::vector< std::vector > dataset; - std::vector target; - double k1, k2, k3, k4; -private: -}; - -#endif //LEIDENALG_IGRAPH_HYBRIDVERTEXPARTITION_H diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/LinearResolutionParameterVertexPartition.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/LinearResolutionParameterVertexPartition.h deleted file mode 100644 index 751cf5b..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/LinearResolutionParameterVertexPartition.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef LINEARRESOLUTIONPARAMETERVERTEXPARTITION_H -#define LINEARRESOLUTIONPARAMETERVERTEXPARTITION_H - -#include - -class LinearResolutionParameterVertexPartition : public ResolutionParameterVertexPartition -{ - public: - LinearResolutionParameterVertexPartition(Graph* graph, - vector membership, double resolution_parameter); - LinearResolutionParameterVertexPartition(Graph* graph, - vector membership); - LinearResolutionParameterVertexPartition(Graph* graph, double resolution_parameter); - LinearResolutionParameterVertexPartition(Graph* graph); - virtual ~LinearResolutionParameterVertexPartition(); - - private: - -}; - -#endif // RESOLUTIONPARAMETERVERTEXPARTITION_H diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/ModularityVertexPartition.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/ModularityVertexPartition.h deleted file mode 100644 index 0157536..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/ModularityVertexPartition.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef MODULARITYVERTEXPARTITION_H -#define MODULARITYVERTEXPARTITION_H - -#include - -class ModularityVertexPartition : public MutableVertexPartition -{ - public: - ModularityVertexPartition(Graph* graph, - vector const& membership); - ModularityVertexPartition(Graph* graph); - virtual ~ModularityVertexPartition(); - virtual ModularityVertexPartition* create(Graph* graph); - virtual ModularityVertexPartition* create(Graph* graph, vector const& membership); - - virtual double diff_move(size_t v, size_t new_comm); - virtual double quality(); - - protected: - private: -}; - -#endif // MODULARITYVERTEXPARTITION_H diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/MutableVertexPartition.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/MutableVertexPartition.h deleted file mode 100644 index 65df475..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/MutableVertexPartition.h +++ /dev/null @@ -1,183 +0,0 @@ -#ifndef MUTABLEVERTEXPARTITION_H -#define MUTABLEVERTEXPARTITION_H - -#include -#include "GraphHelper.h" -#include -#include -#include -#include - -using std::string; -using std::map; -using std::make_pair; -using std::pair; -using std::sort; -using std::reverse; -using std::priority_queue; - -/**************************************************************************** -Contains a partition of graph. - -This class contains the basic implementation for optimising a partition. -Specifically, it implements all the administration necessary to keep track of -the partition from various points of view. Internally, it keeps track of the -number of internal edges (or total weight), the size of the communities, the -total incoming degree (or weight) for a community, etc... When deriving from -this class, one can easily use this administration to provide their own -implementation. - -In order to keep the administration up-to-date, all changes in partition -should be done through move_node. This function moves a node from one -community to another, and updates all the administration. - -It is possible to manually update the membership vector, and then call -__init_admin() which completely refreshes all the administration. This is -only possible by updating the membership vector, not by changing some of the -other variables. - -The basic idea is that diff_move computes the difference in the quality -function if we call move_node for the same move. Using this framework, the -Leiden method in the optimisation class can call these general functions in -order to optimise the quality function. -*****************************************************************************/ - -class MutableVertexPartition -{ - public: - MutableVertexPartition(Graph* graph, - vector const& membership); - MutableVertexPartition(Graph* graph); - virtual MutableVertexPartition* create(Graph* graph); - virtual MutableVertexPartition* create(Graph* graph, vector const& membership); - - virtual ~MutableVertexPartition(); - - inline size_t membership(size_t v) { return this->_membership[v]; }; - inline vector const& membership() const { return this->_membership; }; - - size_t csize(size_t comm); - size_t cnodes(size_t comm); - vector get_community(size_t comm); - vector< vector > get_communities(); - size_t n_communities(); - - void move_node(size_t v,size_t new_comm); - virtual double diff_move(size_t v, size_t new_comm) - { - throw Exception("Function not implemented. This should be implented in a derived class, since the base class does not implement a specific method."); - }; - virtual double quality() - { - throw Exception("Function not implemented. This should be implented in a derived class, since the base class does not implement a specific method."); - }; - - inline Graph* get_graph() { return this->graph; }; - - void renumber_communities(); - void renumber_communities(vector const& fixed_nodes, vector const& fixed_membership); - void renumber_communities(vector const& new_membership); - void set_membership(vector const& new_membership); - void relabel_communities(vector const& new_comm_id); - vector static rank_order_communities(vector partitions); - size_t get_empty_community(); - size_t add_empty_community(); - void from_coarse_partition(vector const& coarse_partition_membership); - void from_coarse_partition(MutableVertexPartition* partition); - void from_coarse_partition(MutableVertexPartition* partition, vector const& coarser_membership); - void from_coarse_partition(vector const& coarse_partition_membership, vector const& coarse_node); - - void from_partition(MutableVertexPartition* partition); - - inline double total_weight_in_comm(size_t comm) { return comm < _n_communities ? this->_total_weight_in_comm[comm] : 0.0; }; - inline double total_weight_from_comm(size_t comm) { return comm < _n_communities ? this->_total_weight_from_comm[comm] : 0.0; }; - inline double total_weight_to_comm(size_t comm) { return comm < _n_communities ? this->_total_weight_to_comm[comm] : 0.0; }; - - inline double total_weight_in_all_comms() { return this->_total_weight_in_all_comms; }; - inline size_t total_possible_edges_in_all_comms() { return this->_total_possible_edges_in_all_comms; }; - - inline double weight_to_comm(size_t v, size_t comm) - { - if (this->_current_node_cache_community_to != v) - { - this->cache_neigh_communities(v, IGRAPH_OUT); - this->_current_node_cache_community_to = v; - } - - if (comm < this->_cached_weight_to_community.size()) - return this->_cached_weight_to_community[comm]; - else - return 0.0; - } - - inline double weight_from_comm(size_t v, size_t comm) - { - if (!this->graph->is_directed()) - return weight_to_comm(v, comm); - - if (this->_current_node_cache_community_from != v) - { - this->cache_neigh_communities(v, IGRAPH_IN); - this->_current_node_cache_community_from = v; - } - - if (comm < this->_cached_weight_from_community.size()) - return this->_cached_weight_from_community[comm]; - else - return 0.0; - } - - vector const& get_neigh_comms(size_t v, igraph_neimode_t); - vector get_neigh_comms(size_t v, igraph_neimode_t mode, vector const& constrained_membership); - - // By delegating the responsibility for deleting the graph to the partition, - // we no longer have to worry about deleting this graph. - int destructor_delete_graph; - - protected: - - void init_admin(); - - vector _membership; // Membership vector, i.e. \sigma_i = c means that node i is in community c - - Graph* graph; - - // Community size - vector< size_t > _csize; - - // Number of nodes in community - vector< size_t > _cnodes; - - double weight_vertex_tofrom_comm(size_t v, size_t comm, igraph_neimode_t mode); - - void set_default_attrs(); - - private: - - // Keep track of the internal weight of each community - vector _total_weight_in_comm; - // Keep track of the total weight to a community - vector _total_weight_to_comm; - // Keep track of the total weight from a community - vector _total_weight_from_comm; - // Keep track of the total internal weight - double _total_weight_in_all_comms; - size_t _total_possible_edges_in_all_comms; - size_t _n_communities; - - vector _empty_communities; - - void cache_neigh_communities(size_t v, igraph_neimode_t mode); - - size_t _current_node_cache_community_from; vector _cached_weight_from_community; vector _cached_neigh_comms_from; - size_t _current_node_cache_community_to; vector _cached_weight_to_community; vector _cached_neigh_comms_to; - size_t _current_node_cache_community_all; vector _cached_weight_all_community; vector _cached_neigh_comms_all; - - void clean_mem(); - void init_graph_admin(); - - void update_n_communities(); - -}; - -#endif // MUTABLEVERTEXPARTITION_H diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/Optimiser.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/Optimiser.h deleted file mode 100644 index fbd1fab..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/Optimiser.h +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef OPTIMISER_H -#define OPTIMISER_H -#include "GraphHelper.h" -#include "MutableVertexPartition.h" -#include -#include -#include - -#include -using std::cerr; -using std::endl; -using std::set; -using std::map; - -/**************************************************************************** -Class for doing community detection using the Leiden algorithm. - -Given a certain partition type is calls diff_move for trying to move a node -to another community. It moves the node to the community that *maximises* -this diff_move. If no further improvement is possible, the graph is -aggregated (collapse_graph) and the method is reiterated on that graph. -****************************************************************************/ - -class Optimiser -{ - public: - Optimiser(); - double optimise_partition(MutableVertexPartition* partition); - double optimise_partition(MutableVertexPartition* partition, vector const& is_membership_fixed); - double optimise_partition(MutableVertexPartition* partition, vector const& is_membership_fixed, size_t max_comm_size); - template T* find_partition(Graph* graph); - template T* find_partition(Graph* graph, double resolution_parameter); - - // The multiplex functions that simultaneously optimise multiple graphs and partitions (i.e. methods) - // Each node will be in the same community in all graphs, and the graphs are expected to have identical nodes - // Optionally we can loop over all possible communities instead of only the neighbours. In the case of negative - // layer weights this may be necessary. - double optimise_partition(vector partitions, vector layer_weights, vector const& is_membership_fixed); - double optimise_partition(vector partitions, vector layer_weights, vector const& is_membership_fixed, size_t max_comm_size); - - double move_nodes(MutableVertexPartition* partition); - double move_nodes(MutableVertexPartition* partition, int consider_comms); - double move_nodes(MutableVertexPartition* partition, vector const& is_membership_fixed, int consider_comms, bool renumber_fixed_nodes); - double move_nodes(MutableVertexPartition* partition, vector const& is_membership_fixed, int consider_comms, bool renumber_fixed_nodes, size_t max_comm_size); - double move_nodes(vector partitions, vector layer_weights, vector const& is_membership_fixed, bool renumber_fixed_nodes); - double move_nodes(vector partitions, vector layer_weights, vector const& is_membership_fixed, int consider_comms, int consider_empty_community); - double move_nodes(vector partitions, vector layer_weights, vector const& is_membership_fixed, int consider_comms, int consider_empty_community, bool renumber_fixed_nodes); - double move_nodes(vector partitions, vector layer_weights, vector const& is_membership_fixed, int consider_comms, int consider_empty_community, bool renumber_fixed_nodes, size_t max_comm_size); - - double merge_nodes(MutableVertexPartition* partition); - double merge_nodes(MutableVertexPartition* partition, int consider_comms); - double merge_nodes(MutableVertexPartition* partition, vector const& is_membership_fixed, int consider_comms, bool renumber_fixed_nodes); - double merge_nodes(MutableVertexPartition* partition, vector const& is_membership_fixed, int consider_comms, bool renumber_fixed_nodes, size_t max_comm_size); - double merge_nodes(vector partitions, vector layer_weights, vector const& is_membership_fixed, bool renumber_fixed_nodes); - double merge_nodes(vector partitions, vector layer_weights, vector const& is_membership_fixed, int consider_comms, bool renumber_fixed_nodes); - double merge_nodes(vector partitions, vector layer_weights, vector const& is_membership_fixed, int consider_comms, bool renumber_fixed_nodes, size_t max_comm_size); - - double move_nodes_constrained(MutableVertexPartition* partition, MutableVertexPartition* constrained_partition); - double move_nodes_constrained(MutableVertexPartition* partition, int consider_comms, MutableVertexPartition* constrained_partition); - double move_nodes_constrained(MutableVertexPartition* partition, int consider_comms, MutableVertexPartition* constrained_partition, size_t max_comm_size); - double move_nodes_constrained(vector partitions, vector layer_weights, MutableVertexPartition* constrained_partition); - double move_nodes_constrained(vector partitions, vector layer_weights, int consider_comms, MutableVertexPartition* constrained_partition); - double move_nodes_constrained(vector partitions, vector layer_weights, int consider_comms, MutableVertexPartition* constrained_partition, size_t max_comm_size); - - double merge_nodes_constrained(MutableVertexPartition* partition, MutableVertexPartition* constrained_partition); - double merge_nodes_constrained(MutableVertexPartition* partition, int consider_comms, MutableVertexPartition* constrained_partition); - double merge_nodes_constrained(MutableVertexPartition* partition, int consider_comms, MutableVertexPartition* constrained_partition, size_t max_comm_size); - double merge_nodes_constrained(vector partitions, vector layer_weights, MutableVertexPartition* constrained_partition); - double merge_nodes_constrained(vector partitions, vector layer_weights, int consider_comms, MutableVertexPartition* constrained_partition); - double merge_nodes_constrained(vector partitions, vector layer_weights, int consider_comms, MutableVertexPartition* constrained_partition, size_t max_comm_size); - - inline void set_rng_seed(size_t seed) { igraph_rng_seed(&rng, seed); }; - - virtual ~Optimiser(); - - int consider_comms; // Indicates how communities will be considered for improvement. Should be one of the parameters below - int refine_partition; // Refine partition before aggregating - int refine_consider_comms; // Indicates how communities will be considered for improvement within the refinement. Should be one of the parameters below - int optimise_routine; // What routine to use for optimisation - int refine_routine; // What routine to use for optimisation - int consider_empty_community; // Determine whether to consider moving nodes to an empty community - size_t max_comm_size; // Constrain the maximal community size. - - static const int ALL_COMMS = 1; // Consider all communities for improvement. - static const int ALL_NEIGH_COMMS = 2; // Consider all neighbour communities for improvement. - static const int RAND_COMM = 3; // Consider a random commmunity for improvement. - static const int RAND_NEIGH_COMM = 4; // Consider a random community among the neighbours for improvement. - - static const int MOVE_NODES = 10; // Use move node routine - static const int MERGE_NODES = 11; // Use merge node routine - - protected: - - private: - void print_settings(); - - igraph_rng_t rng; -}; - -template T* Optimiser::find_partition(Graph* graph) -{ - T* partition = new T(graph); - #ifdef DEBUG - cerr << "Use default partition (all nodes in own community)" << endl; - #endif - this->optimise_partition(partition); - return partition; -} - -template T* Optimiser::find_partition(Graph* graph, double resolution_parameter) -{ - T* partition = new T(graph, resolution_parameter); - #ifdef DEBUG - cerr << "Use default partition (all nodes in own community)" << endl; - #endif - this->optimise_partition(partition); - return partition; -} -#endif // OPTIMISER_H diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/RBConfigurationVertexPartition.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/RBConfigurationVertexPartition.h deleted file mode 100644 index 4220f54..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/RBConfigurationVertexPartition.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef RBCONFIGURATIONVERTEXPARTITION_H -#define RBCONFIGURATIONVERTEXPARTITION_H - -#include "LinearResolutionParameterVertexPartition.h" - -class RBConfigurationVertexPartition : public LinearResolutionParameterVertexPartition -{ - public: - RBConfigurationVertexPartition(Graph* graph, - vector const& membership, double resolution_parameter); - RBConfigurationVertexPartition(Graph* graph, - vector const& membership); - RBConfigurationVertexPartition(Graph* graph, - double resolution_parameter); - RBConfigurationVertexPartition(Graph* graph); - virtual ~RBConfigurationVertexPartition(); - virtual RBConfigurationVertexPartition* create(Graph* graph); - virtual RBConfigurationVertexPartition* create(Graph* graph, vector const& membership); - - virtual double diff_move(size_t v, size_t new_comm); - virtual double quality(double resolution_parameter); - - protected: - private: -}; - -#endif // RBCONFIGURATIONVERTEXPARTITION_H diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/RBERVertexPartition.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/RBERVertexPartition.h deleted file mode 100644 index e79c313..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/RBERVertexPartition.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef RBERVERTEXPARTITION_H -#define RBERVERTEXPARTITION_H - -#include - - -class RBERVertexPartition : public LinearResolutionParameterVertexPartition -{ - public: - RBERVertexPartition(Graph* graph, - vector const& membership, double resolution_parameter); - RBERVertexPartition(Graph* graph, - vector const& membership); - RBERVertexPartition(Graph* graph, - double resolution_parameter); - RBERVertexPartition(Graph* graph); - virtual ~RBERVertexPartition(); - virtual RBERVertexPartition* create(Graph* graph); - virtual RBERVertexPartition* create(Graph* graph, vector const& membership); - - virtual double diff_move(size_t v, size_t new_comm); - virtual double quality(double resolution_parameter); - - protected: - private: -}; - -#endif // RBERVERTEXPARTITION_H diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/ResolutionParameterVertexPartition.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/ResolutionParameterVertexPartition.h deleted file mode 100644 index df886c7..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/ResolutionParameterVertexPartition.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef RESOLUTIONPARAMETERVERTEXPARTITION_H -#define RESOLUTIONPARAMETERVERTEXPARTITION_H - -#include - -class ResolutionParameterVertexPartition : public MutableVertexPartition -{ - public: - ResolutionParameterVertexPartition(Graph* graph, - vector membership, double resolution_parameter); - ResolutionParameterVertexPartition(Graph* graph, - vector membership); - ResolutionParameterVertexPartition(Graph* graph, double resolution_parameter); - ResolutionParameterVertexPartition(Graph* graph); - virtual ~ResolutionParameterVertexPartition(); - - double resolution_parameter; - - virtual double quality() - { - return this->quality(this->resolution_parameter); - }; - - virtual double quality(double resolution_parameter) - { - throw Exception("Function not implemented. This should be implented in a derived class, since the base class does not implement a specific method."); - }; - - private: - -}; - -#endif // RESOLUTIONPARAMETERVERTEXPARTITION_H diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/SignificanceVertexPartition.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/SignificanceVertexPartition.h deleted file mode 100644 index dd93849..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/SignificanceVertexPartition.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SIGNIFICANCEVERTEXPARTITION_H -#define SIGNIFICANCEVERTEXPARTITION_H - -#include - - -class SignificanceVertexPartition : public MutableVertexPartition -{ - public: - SignificanceVertexPartition(Graph* graph, vector const& membership); - SignificanceVertexPartition(Graph* graph); - virtual ~SignificanceVertexPartition(); - virtual SignificanceVertexPartition* create(Graph* graph); - virtual SignificanceVertexPartition* create(Graph* graph, vector const& membership); - - virtual double diff_move(size_t v, size_t new_comm); - virtual double quality(); - protected: - private: -}; - -#endif // SIGNIFICANCEVERTEXPARTITION_H diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/SurpriseVertexPartition.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/SurpriseVertexPartition.h deleted file mode 100644 index 535caa4..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/SurpriseVertexPartition.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SURPRISEVERTEXPARTITION_H -#define SURPRISEVERTEXPARTITION_H - -#include "MutableVertexPartition.h" -#include - using std::cerr; - using std::endl; - -class SurpriseVertexPartition: public MutableVertexPartition -{ - public: - SurpriseVertexPartition(Graph* graph, vector const& membership); - SurpriseVertexPartition(Graph* graph, SurpriseVertexPartition* partition); - SurpriseVertexPartition(Graph* graph); - virtual ~SurpriseVertexPartition(); - virtual SurpriseVertexPartition* create(Graph* graph); - virtual SurpriseVertexPartition* create(Graph* graph, vector const& membership); - - virtual double diff_move(size_t v, size_t new_comm); - virtual double quality(); - protected: - private: -}; - -#endif // SURPRISEVERTEXPARTITION_H diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/pynterface.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/pynterface.h deleted file mode 100644 index d2e7873..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/pynterface.h +++ /dev/null @@ -1,144 +0,0 @@ -#ifndef PYNTERFACE_H_INCLUDED -#define PYNTERFACE_H_INCLUDED - -#include -#include -#include "GraphHelper.h" -#include "ModularityVertexPartition.h" -#include "SignificanceVertexPartition.h" -#include "SurpriseVertexPartition.h" -#include "RBConfigurationVertexPartition.h" -#include "RBERVertexPartition.h" -#include "CPMVertexPartition.h" -#include "Optimiser.h" - -#include "python_partition_interface.h" -#include "python_optimiser_interface.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - - PyObject* _set_rng_seed(PyObject *self, PyObject *args, PyObject *keywds); - - static PyMethodDef leiden_funcs[] = { - {"_new_HybridVertexPartition", (PyCFunction)_new_HybridVertexPartition, METH_VARARGS | METH_KEYWORDS, ""}, - {"_new_ModularityVertexPartition", (PyCFunction)_new_ModularityVertexPartition, METH_VARARGS | METH_KEYWORDS, ""}, - {"_new_SignificanceVertexPartition", (PyCFunction)_new_SignificanceVertexPartition, METH_VARARGS | METH_KEYWORDS, ""}, - {"_new_SurpriseVertexPartition", (PyCFunction)_new_SurpriseVertexPartition, METH_VARARGS | METH_KEYWORDS, ""}, - {"_new_CPMVertexPartition", (PyCFunction)_new_CPMVertexPartition, METH_VARARGS | METH_KEYWORDS, ""}, - {"_new_RBERVertexPartition", (PyCFunction)_new_RBERVertexPartition, METH_VARARGS | METH_KEYWORDS, ""}, - {"_new_RBConfigurationVertexPartition", (PyCFunction)_new_RBConfigurationVertexPartition, METH_VARARGS | METH_KEYWORDS, ""}, - - {"_MutableVertexPartition_diff_move", (PyCFunction)_MutableVertexPartition_diff_move, METH_VARARGS | METH_KEYWORDS, ""}, - {"_MutableVertexPartition_move_node", (PyCFunction)_MutableVertexPartition_move_node, METH_VARARGS | METH_KEYWORDS, ""}, - {"_MutableVertexPartition_get_py_igraph", (PyCFunction)_MutableVertexPartition_get_py_igraph, METH_VARARGS | METH_KEYWORDS, ""}, - {"_MutableVertexPartition_aggregate_partition", (PyCFunction)_MutableVertexPartition_aggregate_partition, METH_VARARGS | METH_KEYWORDS, ""}, - {"_MutableVertexPartition_from_coarse_partition", (PyCFunction)_MutableVertexPartition_from_coarse_partition, METH_VARARGS | METH_KEYWORDS, ""}, - {"_MutableVertexPartition_renumber_communities", (PyCFunction)_MutableVertexPartition_renumber_communities, METH_VARARGS | METH_KEYWORDS, ""}, - - {"_MutableVertexPartition_quality", (PyCFunction)_MutableVertexPartition_quality, METH_VARARGS | METH_KEYWORDS, ""}, - {"_MutableVertexPartition_total_weight_in_comm", (PyCFunction)_MutableVertexPartition_total_weight_in_comm, METH_VARARGS | METH_KEYWORDS, ""}, - {"_MutableVertexPartition_total_weight_from_comm", (PyCFunction)_MutableVertexPartition_total_weight_from_comm, METH_VARARGS | METH_KEYWORDS, ""}, - {"_MutableVertexPartition_total_weight_to_comm", (PyCFunction)_MutableVertexPartition_total_weight_to_comm, METH_VARARGS | METH_KEYWORDS, ""}, - {"_MutableVertexPartition_total_weight_in_all_comms", (PyCFunction)_MutableVertexPartition_total_weight_in_all_comms, METH_VARARGS | METH_KEYWORDS, ""}, - {"_MutableVertexPartition_total_possible_edges_in_all_comms", (PyCFunction)_MutableVertexPartition_total_possible_edges_in_all_comms, METH_VARARGS | METH_KEYWORDS, ""}, - {"_MutableVertexPartition_weight_to_comm", (PyCFunction)_MutableVertexPartition_weight_to_comm, METH_VARARGS | METH_KEYWORDS, ""}, - {"_MutableVertexPartition_weight_from_comm", (PyCFunction)_MutableVertexPartition_weight_from_comm, METH_VARARGS | METH_KEYWORDS, ""}, - {"_MutableVertexPartition_get_membership", (PyCFunction)_MutableVertexPartition_get_membership, METH_VARARGS | METH_KEYWORDS, ""}, - {"_MutableVertexPartition_set_membership", (PyCFunction)_MutableVertexPartition_set_membership, METH_VARARGS | METH_KEYWORDS, ""}, - {"_ResolutionParameterVertexPartition_get_resolution", (PyCFunction)_ResolutionParameterVertexPartition_get_resolution, METH_VARARGS | METH_KEYWORDS, ""}, - {"_ResolutionParameterVertexPartition_set_resolution", (PyCFunction)_ResolutionParameterVertexPartition_set_resolution, METH_VARARGS | METH_KEYWORDS, ""}, - {"_ResolutionParameterVertexPartition_quality", (PyCFunction)_ResolutionParameterVertexPartition_quality, METH_VARARGS | METH_KEYWORDS, ""}, - - - {"_new_Optimiser", (PyCFunction)_new_Optimiser, METH_NOARGS, ""}, - {"_Optimiser_optimise_partition", (PyCFunction)_Optimiser_optimise_partition, METH_VARARGS | METH_KEYWORDS, ""}, - {"_Optimiser_optimise_partition_multiplex", (PyCFunction)_Optimiser_optimise_partition_multiplex, METH_VARARGS | METH_KEYWORDS, ""}, - {"_Optimiser_move_nodes", (PyCFunction)_Optimiser_move_nodes, METH_VARARGS | METH_KEYWORDS, ""}, - {"_Optimiser_move_nodes_constrained", (PyCFunction)_Optimiser_move_nodes_constrained, METH_VARARGS | METH_KEYWORDS, ""}, - {"_Optimiser_merge_nodes", (PyCFunction)_Optimiser_merge_nodes, METH_VARARGS | METH_KEYWORDS, ""}, - {"_Optimiser_merge_nodes_constrained", (PyCFunction)_Optimiser_merge_nodes_constrained, METH_VARARGS | METH_KEYWORDS, ""}, - - {"_Optimiser_set_consider_comms", (PyCFunction)_Optimiser_set_consider_comms, METH_VARARGS | METH_KEYWORDS, ""}, - {"_Optimiser_set_refine_consider_comms", (PyCFunction)_Optimiser_set_refine_consider_comms, METH_VARARGS | METH_KEYWORDS, ""}, - {"_Optimiser_set_optimise_routine", (PyCFunction)_Optimiser_set_optimise_routine, METH_VARARGS | METH_KEYWORDS, ""}, - {"_Optimiser_set_refine_routine", (PyCFunction)_Optimiser_set_refine_routine, METH_VARARGS | METH_KEYWORDS, ""}, - {"_Optimiser_set_consider_empty_community", (PyCFunction)_Optimiser_set_consider_empty_community, METH_VARARGS | METH_KEYWORDS, ""}, - {"_Optimiser_set_refine_partition", (PyCFunction)_Optimiser_set_refine_partition, METH_VARARGS | METH_KEYWORDS, ""}, - {"_Optimiser_set_max_comm_size", (PyCFunction)_Optimiser_set_max_comm_size, METH_VARARGS | METH_KEYWORDS, ""}, - - {"_Optimiser_get_consider_comms", (PyCFunction)_Optimiser_get_consider_comms, METH_VARARGS | METH_KEYWORDS, ""}, - {"_Optimiser_get_refine_consider_comms", (PyCFunction)_Optimiser_get_refine_consider_comms, METH_VARARGS | METH_KEYWORDS, ""}, - {"_Optimiser_get_optimise_routine", (PyCFunction)_Optimiser_get_optimise_routine, METH_VARARGS | METH_KEYWORDS, ""}, - {"_Optimiser_get_refine_routine", (PyCFunction)_Optimiser_get_refine_routine, METH_VARARGS | METH_KEYWORDS, ""}, - {"_Optimiser_get_consider_empty_community", (PyCFunction)_Optimiser_get_consider_empty_community, METH_VARARGS | METH_KEYWORDS, ""}, - {"_Optimiser_get_refine_partition", (PyCFunction)_Optimiser_get_refine_partition, METH_VARARGS | METH_KEYWORDS, ""}, - {"_Optimiser_get_max_comm_size", (PyCFunction)_Optimiser_get_max_comm_size, METH_VARARGS | METH_KEYWORDS, ""}, - - {"_Optimiser_set_rng_seed", (PyCFunction)_Optimiser_set_rng_seed, METH_VARARGS | METH_KEYWORDS, ""}, - - {NULL} - }; - - struct module_state { - PyObject *error; - }; - - #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) - - static int leiden_traverse(PyObject *m, visitproc visit, void *arg) { - Py_VISIT(GETSTATE(m)->error); - return 0; - } - - static int leiden_clear(PyObject *m) { - Py_CLEAR(GETSTATE(m)->error); - return 0; - } - - static struct PyModuleDef leidendef = { - PyModuleDef_HEAD_INIT, - "_c_leiden", - NULL, - sizeof(struct module_state), - leiden_funcs, - NULL, - leiden_traverse, - leiden_clear, - NULL - }; - - #define INITERROR return NULL - - PyObject * - PyInit__c_leiden(void) - { - PyObject* module = PyModule_Create(&leidendef); - - PyModule_AddIntConstant(module, "ALL_COMMS", Optimiser::ALL_COMMS); - PyModule_AddIntConstant(module, "ALL_NEIGH_COMMS", Optimiser::ALL_NEIGH_COMMS); - PyModule_AddIntConstant(module, "RAND_COMM", Optimiser::RAND_COMM); - PyModule_AddIntConstant(module, "RAND_NEIGH_COMM", Optimiser::RAND_NEIGH_COMM); - - PyModule_AddIntConstant(module, "MOVE_NODES", Optimiser::MOVE_NODES); - PyModule_AddIntConstant(module, "MERGE_NODES", Optimiser::MERGE_NODES); - - if (module == NULL) - INITERROR; - struct module_state *st = GETSTATE(module); - - st->error = PyErr_NewException("leidenalg.Error", NULL, NULL); - if (st->error == NULL) { - Py_DECREF(module); - INITERROR; - } - - return module; - } - -#ifdef __cplusplus -} -#endif -#endif // PYNTERFACE_H_INCLUDED diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/python_optimiser_interface.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/python_optimiser_interface.h deleted file mode 100644 index 4194f45..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/python_optimiser_interface.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef PYNTERFACE_OPTIMISER_H_INCLUDED -#define PYNTERFACE_OPTIMISER_H_INCLUDED - -#include -#include -#include "GraphHelper.h" -#include "ModularityVertexPartition.h" -#include "SignificanceVertexPartition.h" -#include "SurpriseVertexPartition.h" -#include "RBConfigurationVertexPartition.h" -#include "RBERVertexPartition.h" -#include "CPMVertexPartition.h" -#include "Optimiser.h" -#include "python_partition_interface.h" - -#ifdef DEBUG -#include - using std::cerr; - using std::endl; -#endif - -PyObject* capsule_Optimiser(Optimiser* optimiser); -Optimiser* decapsule_Optimiser(PyObject* py_optimiser); -void del_Optimiser(PyObject* py_optimiser); - -#ifdef __cplusplus -extern "C" -{ -#endif - PyObject* _new_Optimiser(PyObject *self, PyObject *args); - PyObject* _Optimiser_optimise_partition(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _Optimiser_optimise_partition_multiplex(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _Optimiser_move_nodes(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _Optimiser_move_nodes_constrained(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _Optimiser_merge_nodes(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _Optimiser_merge_nodes_constrained(PyObject *self, PyObject *args, PyObject *keywds); - - PyObject* _Optimiser_set_consider_comms(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _Optimiser_set_refine_consider_comms(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _Optimiser_set_optimise_routine(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _Optimiser_set_refine_routine(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _Optimiser_set_consider_empty_community(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _Optimiser_set_refine_partition(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _Optimiser_set_max_comm_size(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _Optimiser_set_rng_seed(PyObject *self, PyObject *args, PyObject *keywds); - - PyObject* _Optimiser_get_consider_comms(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _Optimiser_get_refine_consider_comms(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _Optimiser_get_optimise_routine(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _Optimiser_get_refine_routine(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _Optimiser_get_consider_empty_community(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _Optimiser_get_refine_partition(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _Optimiser_get_max_comm_size(PyObject *self, PyObject *args, PyObject *keywds); - -#ifdef __cplusplus -} -#endif -#endif // PYNTERFACE_OPTIMISER_H_INCLUDED diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/python_partition_interface.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/python_partition_interface.h deleted file mode 100644 index 1ae247c..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/include/python_partition_interface.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef PYNTERFACE_PARTITION_H_INCLUDED -#define PYNTERFACE_PARTITION_H_INCLUDED - -#include -#include -#include "GraphHelper.h" -#include "HybridVertexPartition.h" -#include "ModularityVertexPartition.h" -#include "SignificanceVertexPartition.h" -#include "SurpriseVertexPartition.h" -#include "RBConfigurationVertexPartition.h" -#include "RBERVertexPartition.h" -#include "CPMVertexPartition.h" -#include "Optimiser.h" - -#include - -#ifdef DEBUG -#include - using std::cerr; - using std::endl; -#endif - -MutableVertexPartition* create_partition(Graph* graph, char* method, vector* initial_membership, double resolution_parameter); -MutableVertexPartition* create_partition_from_py(PyObject* py_obj_graph, char* method, PyObject* py_initial_membership, PyObject* py_weights, PyObject* py_node_sizes, double resolution_parameter); - -Graph* create_graph_from_py(PyObject* py_obj_graph, PyObject* py_node_sizes); -Graph* create_graph_from_py(PyObject* py_obj_graph, PyObject* py_node_sizes, PyObject* py_weights); -Graph* create_graph_from_py(PyObject* py_obj_graph, PyObject* py_node_sizes, PyObject* py_weights, int check_positive_weight); -//Graph* create_graph_from_py(PyObject* py_obj_graph, PyObject* py_node_sizes, PyObject* py_weights, PyObject* py_dataset, PyObject* py_names); - -vector create_size_t_vector(PyObject* py_list); - -PyObject* capsule_MutableVertexPartition(MutableVertexPartition* partition); -MutableVertexPartition* decapsule_MutableVertexPartition(PyObject* py_partition); - -void del_MutableVertexPartition(PyObject *self); - -#ifdef __cplusplus -extern "C" -{ -#endif - PyObject* _new_HybridVertexPartition(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _new_ModularityVertexPartition(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _new_SignificanceVertexPartition(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _new_SurpriseVertexPartition(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _new_CPMVertexPartition(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _new_RBERVertexPartition(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _new_RBConfigurationVertexPartition(PyObject *self, PyObject *args, PyObject *keywds); - - PyObject* _MutableVertexPartition_diff_move(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _MutableVertexPartition_move_node(PyObject *self, PyObject *args, PyObject *keywds); - - PyObject* _MutableVertexPartition_aggregate_partition(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _MutableVertexPartition_get_py_igraph(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _MutableVertexPartition_from_coarse_partition(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _MutableVertexPartition_renumber_communities(PyObject *self, PyObject *args, PyObject *keywds); - - PyObject* _MutableVertexPartition_quality(PyObject *self, PyObject *args, PyObject *keywds); - - PyObject* _MutableVertexPartition_total_weight_in_comm(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _MutableVertexPartition_total_weight_from_comm(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _MutableVertexPartition_total_weight_to_comm(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _MutableVertexPartition_total_weight_in_all_comms(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _MutableVertexPartition_total_possible_edges_in_all_comms(PyObject *self, PyObject *args, PyObject *keywds); - - PyObject* _MutableVertexPartition_weight_to_comm(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _MutableVertexPartition_weight_from_comm(PyObject *self, PyObject *args, PyObject *keywds); - - PyObject* _MutableVertexPartition_get_membership(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _MutableVertexPartition_set_membership(PyObject *self, PyObject *args, PyObject *keywds); - - PyObject* _ResolutionParameterVertexPartition_get_resolution(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _ResolutionParameterVertexPartition_set_resolution(PyObject *self, PyObject *args, PyObject *keywds); - PyObject* _ResolutionParameterVertexPartition_quality(PyObject *self, PyObject *args, PyObject *keywds); - -#ifdef __cplusplus -} -#endif -#endif // PYNTERFACE_PARTITION_H_INCLUDED diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/setup.cfg b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/setup.cfg deleted file mode 100644 index a0438ef..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/setup.cfg +++ /dev/null @@ -1,7 +0,0 @@ -[build_sphinx] -source-dir = doc/source -build-dir = doc/build -all_files = 1 - -[upload_sphinx] -upload-dir = doc/build/html diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/setup.py b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/setup.py deleted file mode 100644 index 0159ac4..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/setup.py +++ /dev/null @@ -1,814 +0,0 @@ -#!usr/bin/env python - -import os -import platform -import sys - -########################################################################### - -# Check Python's version info and exit early if it is too old -if sys.version_info < (3, 6): - print("This module requires Python >= 3.6") - sys.exit(0) - -# Check whether we are compiling for PyPy. Headers will not be installed -# for PyPy. -SKIP_HEADER_INSTALL = (platform.python_implementation() == "PyPy") or ( - "SKIP_HEADER_INSTALL" in os.environ -) - -########################################################################### - -from setuptools import setup, Command, Extension - -import glob -import shlex -import shutil -import subprocess -import sys -import sysconfig - -from pathlib import Path -from select import select -from shutil import which -from time import sleep - -########################################################################### - -is_windows = platform.system() == "windows" - - -def building_on_windows_msvc(): - """Returns True when using the non-MinGW CPython interpreter on Windows""" - return platform.system() == "Windows" and sysconfig.get_platform() != "mingw" - - -def exclude_from_list(items, items_to_exclude): - """Excludes certain items from a list, keeping the original order of - the remaining items.""" - itemset = set(items_to_exclude) - return [item for item in items if item not in itemset] - - -def find_static_library(library_name, library_path): - """Given the raw name of a library in `library_name`, tries to find a - static library with this name in the given `library_path`. `library_path` - is automatically extended with common library directories on Linux and Mac - OS X.""" - - variants = ["lib{0}.a", "{0}.a", "{0}.lib", "lib{0}.lib"] - if is_unix_like(): - extra_libdirs = [ - "/usr/local/lib64", - "/usr/local/lib", - "/usr/lib/x86_64-linux-gnu", - "/usr/lib64", - "/usr/lib", - "/lib64", - "/lib", - ] - else: - extra_libdirs = [] - - for path in extra_libdirs: - if path not in library_path and os.path.isdir(path): - library_path.append(path) - - for path in library_path: - for variant in variants: - full_path = os.path.join(path, variant.format(library_name)) - if os.path.isfile(full_path): - return full_path - - -def first(iterable): - """Returns the first element from the given iterable.""" - for item in iterable: - return item - raise ValueError("iterable is empty") - - -def get_output(args, encoding="utf-8"): - """Returns the output of a command returning a single line of output.""" - PIPE = subprocess.PIPE - try: - p = subprocess.Popen(args, shell=False, stdin=PIPE, stdout=PIPE, stderr=PIPE) - stdout, stderr = p.communicate() - returncode = p.returncode - except OSError: - stdout, stderr = None, None - returncode = 77 - if encoding and type(stdout).__name__ == "bytes": - stdout = str(stdout, encoding=encoding) - if encoding and type(stderr).__name__ == "bytes": - stderr = str(stderr, encoding=encoding) - return stdout, returncode - - -def get_output_single_line(args, encoding="utf-8"): - """Returns the output of a command returning a single line of output, - stripped from any trailing newlines.""" - stdout, returncode = get_output(args, encoding=encoding) - if stdout is not None: - line, _, _ = stdout.partition("\n") - else: - line = None - return line, returncode - - -def is_unix_like(platform=None): - """Returns whether the given platform is a Unix-like platform with the usual - Unix filesystem. When the parameter is omitted, it defaults to ``sys.platform`` - """ - platform = platform or sys.platform - platform = platform.lower() - return ( - platform.startswith("linux") - or platform.startswith("darwin") - or platform.startswith("cygwin") - ) - - -def wait_for_keypress(seconds): - """Wait for a keypress or until the given number of seconds have passed, - whichever happens first. - """ - global is_windows - - while seconds > 0: - if seconds > 1: - plural = "s" - else: - plural = "" - - sys.stdout.write( - "\rContinuing in %2d second%s; press Enter to continue " - "immediately. " % (seconds, plural) - ) - sys.stdout.flush() - - if is_windows: - from msvcrt import kbhit - - for i in range(10): - if kbhit(): - seconds = 0 - break - sleep(0.1) - else: - rlist, _, _ = select([sys.stdin], [], [], 1) - if rlist: - sys.stdin.readline() - seconds = 0 - break - - seconds -= 1 - - sys.stdout.write("\r" + " " * 65 + "\r") - - -########################################################################### - - -class IgraphCCoreBuilder(object): - """Superclass for classes responsible for downloading and building the - C core of igraph if it is not installed yet. - """ - - def create_build_config_file(self, install_folder, libraries): - with (install_folder / "build.cfg").open("w") as fp: - fp.write(repr(libraries)) - - def parse_pkgconfig_file(self, filename): - building_on_windows = building_on_windows_msvc() - - if building_on_windows: - libraries = ["igraph"] - else: - libraries = [] - with filename.open("r") as fp: - for line in fp: - if line.startswith("Libs: ") or line.startswith("Libs.private: "): - words = line.strip().split() - libraries.extend( - word[2:] for word in words if word.startswith("-l") - ) - - if not libraries: - # Educated guess - libraries = ["igraph"] - - return libraries - - -########################################################################### - - -class IgraphCCoreCMakeBuilder(IgraphCCoreBuilder): - """Class responsible for downloading and building the C core of igraph - if it is not installed yet, assuming that the C core uses CMake as the - build tool. This is the case from igraph 0.9. - - Returns: - False if the build failed or the list of libraries to link to when - linking the Python interface to igraph - """ - - def compile_in(self, source_folder, build_folder, install_folder): - """Compiles igraph from its source code in the given folder. - - source_folder is the name of the folder that contains igraph's source - files. build_folder is the name of the folder where the build should - be executed. Both must be absolute paths. - """ - global is_windows - - cmake = which("cmake") - if not cmake: - print( - "igraph uses CMake as the build system. You need to install CMake " - "before compiling igraph." - ) - return False - - build_to_source_folder = os.path.relpath(source_folder, build_folder) - os.chdir(build_folder) - - print("Configuring build...") - args = [cmake] - - # Build the Python interface with vendored libraries - for deps in "ARPACK BLAS CXSPARSE GLPK GMP LAPACK".split(): - args.append("-DIGRAPH_USE_INTERNAL_" + deps + "=ON") - - # -fPIC is needed on Linux so we can link to a static igraph lib from a - # Python shared library - args.append("-DCMAKE_POSITION_INDEPENDENT_CODE=ON") - - # Add any extra CMake args from environment variables - if "IGRAPH_CMAKE_EXTRA_ARGS" in os.environ: - args.extend(shlex.split(os.environ["IGRAPH_CMAKE_EXTRA_ARGS"])) - - # Finally, add the source folder path - args.append(str(build_to_source_folder)) - - retcode = subprocess.call(args) - if retcode: - return False - - print("Running build...") - retcode = subprocess.call( - [cmake, "--build", ".", "--config", "Release"] - ) - if retcode: - return False - - print("Installing build...") - retcode = subprocess.call([cmake, "--install", ".", "--prefix", str(install_folder), "--config", "Release"]) - if retcode: - return False - - pkgconfig_candidates = [ - install_folder / "lib" / "pkgconfig" / "igraph.pc", - install_folder / "lib64" / "pkgconfig" / "igraph.pc" - ] - for candidate in pkgconfig_candidates: - if candidate.exists(): - return self.parse_pkgconfig_file(candidate) - - raise RuntimeError("no igraph.pc was found in the installation folder of igraph") - - -########################################################################### - - -class BuildConfiguration(object): - def __init__(self): - self.include_dirs = [] - self.library_dirs = [] - self.runtime_library_dirs = [] - self.libraries = [] - self.extra_compile_args = [] - self.extra_link_args = [] - self.define_macros = [] - self.extra_objects = [] - self.static_extension = False - self.external = False - self.use_pkgconfig = False - self._has_pkgconfig = None - self.excluded_include_dirs = [] - self.excluded_library_dirs = [] - self.wait = platform.system() != "Windows" - - @property - def has_pkgconfig(self): - """Returns whether ``pkg-config`` is available on the current system - and it knows about igraph or not.""" - if self._has_pkgconfig is None: - if self.use_pkgconfig: - line, exit_code = get_output_single_line(["pkg-config", "igraph"]) - self._has_pkgconfig = exit_code == 0 - else: - self._has_pkgconfig = False - return self._has_pkgconfig - - @property - def build_c_core(self): - """Returns a class representing a custom setup.py command that builds - the C core of igraph. - - This is used in CI environments where we want to build the C core of - igraph once and then build the Python interface for various Python - versions without having to recompile the C core all the time. - - If is also used as a custom building block of `build_ext`. - """ - - buildcfg = self - - class build_c_core(Command): - description = "Compile the C core of igraph only" - user_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - buildcfg.c_core_built = buildcfg.compile_igraph_from_vendor_source() - - return build_c_core - - @property - def build_ext(self): - """Returns a class that can be used as a replacement for the - ``build_ext`` command in ``setuptools`` and that will compile the C core - of igraph before compiling the Python extension. - """ - from setuptools.command.build_ext import build_ext - from distutils.sysconfig import get_python_inc - - buildcfg = self - - class custom_build_ext(build_ext): - def run(self): - # Bail out if we don't have the Python include files - include_dir = get_python_inc() - if not os.path.isfile(os.path.join(include_dir, "Python.h")): - print("You will need the Python headers to compile this extension.") - sys.exit(1) - - # Check whether the user asked us to discover a pre-built igraph - # with pkg-config - detected = False - if buildcfg.external: - if buildcfg.use_pkgconfig: - detected = buildcfg.detect_from_pkgconfig() - if not detected: - print( - "Cannot find the C core of igraph on this system using pkg-config." - ) - sys.exit(1) - else: - buildcfg.use_educated_guess() - else: - # Build the C core from the vendored igraph source - self.run_command("build_c_core") - if not buildcfg.c_core_built: - # Fall back to an educated guess if everything else failed - if not detected: - buildcfg.use_educated_guess() - - # Add any extra include paths if needed; this is needed for the - # Appveyor CI build - if "IGRAPH_EXTRA_INCLUDE_PATH" in os.environ: - buildcfg.include_dirs = ( - list(os.environ["IGRAPH_EXTRA_INCLUDE_PATH"].split(os.pathsep)) - + buildcfg.include_dirs - ) - - # Add any extra library paths if needed; this is needed for the - # Appveyor CI build - if "IGRAPH_EXTRA_LIBRARY_PATH" in os.environ: - buildcfg.library_dirs = ( - list(os.environ["IGRAPH_EXTRA_LIBRARY_PATH"].split(os.pathsep)) - + buildcfg.library_dirs - ) - - # Add extra libraries that may have been specified - if "IGRAPH_EXTRA_LIBRARIES" in os.environ: - extra_libraries = os.environ["IGRAPH_EXTRA_LIBRARIES"].split(',') - buildcfg.libraries.extend(extra_libraries) - - # Override static specification based on environment variable - if "IGRAPH_STATIC_EXTENSION" in os.environ: - if os.environ["IGRAPH_STATIC_EXTENSION"].lower() in ['true', '1', 'on']: - buildcfg.static_extension = True - else: - buildcfg.static_extension = False - - # Replaces library names with full paths to static libraries - # where possible. libm.a is excluded because it caused problems - # on Sabayon Linux where libm.a is probably not compiled with - # -fPIC - if buildcfg.static_extension: - if buildcfg.static_extension == "only_igraph": - buildcfg.replace_static_libraries(only=["igraph"]) - else: - buildcfg.replace_static_libraries(exclusions=["m"]) - - # Add extra libraries that may have been specified - if "IGRAPH_EXTRA_DYNAMIC_LIBRARIES" in os.environ: - extra_libraries = os.environ["IGRAPH_EXTRA_DYNAMIC_LIBRARIES"].split(',') - buildcfg.libraries.extend(extra_libraries) - - # Prints basic build information - buildcfg.print_build_info() - - # Find the igraph extension and configure it with the settings - # of this build configuration - ext = first( - extension - for extension in self.extensions - if extension.name == "leidenalg._c_leiden" - ) - ext.include_dirs += buildcfg.include_dirs - buildcfg.configure(ext) - - # Run the original build_ext command - build_ext.run(self) - - return custom_build_ext - - @property - def sdist(self): - """Returns a class that can be used as a replacement for the - ``sdist`` command in ``setuptools`` and that will clean up - ``vendor/source/igraph`` before running the original ``sdist`` - command. - """ - from setuptools.command.sdist import sdist - - def is_git_repo(folder): - return os.path.exists(os.path.join(folder, ".git")) - - def cleanup_git_repo(folder): - folder = str(folder) - cwd = os.getcwd() - try: - os.chdir(folder) - if os.path.exists(".git"): - retcode = subprocess.call("git clean -dfx", shell=True) - if retcode: - raise RuntimeError(f"Failed to clean {folder} with git") - finally: - os.chdir(cwd) - - class custom_sdist(sdist): - def run(self): - igraph_source_repo = os.path.join("vendor", "source", "igraph") - igraph_build_dir = os.path.join("vendor", "build", "igraph") - version_file = os.path.join(igraph_source_repo, "IGRAPH_VERSION") - version = None - - # Check whether the source repo contains an IGRAPH_VERSION file, - # and extract the version number from that - if os.path.exists(version_file): - with open(version_file, "r") as fp: - version = fp.read().strip().split("\n")[0] - - # If no IGRAPH_VERSION file exists, but we have a git repo, try - # git describe - if not version and is_git_repo(igraph_source_repo): - cwd = os.getcwd() - try: - os.chdir(igraph_source_repo) - version = subprocess.check_output("git describe", shell=True).decode("utf-8").strip() - finally: - os.chdir(cwd) - - # If we still don't have a version number, try to parse it from - # include/igraph_version.h - if not version: - version_header = os.path.join(igraph_build_dir, "include", "igraph_version.h") - if not os.path.exists(version_header): - raise RuntimeError("You need to build the C core of igraph first before generating a source tarball of python-igraph") - - with open(version_header, "r") as fp: - lines = [line.strip() for line in fp if line.startswith("#define IGRAPH_VERSION ")] - if len(lines) == 1: - version = lines[0].split('"')[1] - - if not isinstance(version, str) or len(version) < 5: - raise RuntimeError(f"Cannot determine the version number of the C core in {igraph_source_repo}") - - if not is_git_repo(igraph_source_repo): - # python-igraph was extracted from an official tarball so - # there is no need to tweak anything - return sdist.run(self) - else: - # Clean up vendor/source/igraph with git - cleanup_git_repo(igraph_source_repo) - - # Copy the generated parser sources from the build folder - parser_dir = os.path.join(igraph_build_dir, "src", "io", "parsers") - if os.path.isdir(parser_dir): - shutil.copytree(parser_dir, os.path.join(igraph_source_repo, "src", "io", "parsers")) - else: - raise RuntimeError(f"You need to build the C core of igraph first before generating a source tarball of python-igraph") - - # Add a version file to the tarball - with open(version_file, "w") as fp: - fp.write(version) - - # Run the original sdist command - retval = sdist.run(self) - - # Clean up vendor/source/igraph with git again - cleanup_git_repo(igraph_source_repo) - - return retval - - return custom_sdist - - def compile_igraph_from_vendor_source(self): - """Compiles igraph from the vendored source code inside `vendor/source/igraph`. - This folder typically comes from a git submodule. - """ - vendor_folder = Path("vendor") - source_folder = vendor_folder / "source" / "igraph" - build_folder = vendor_folder / "build" / "igraph" - install_folder = vendor_folder / "install" / "igraph" - - if install_folder.exists(): - # Vendored igraph already compiled and installed, just use it - self.use_vendored_igraph() - return True - - if (source_folder / "CMakeLists.txt").exists(): - igraph_builder = IgraphCCoreCMakeBuilder() - else: - print("Cannot find vendored igraph source in {0}".format(source_folder)) - print("") - return False - - print("We are going to build the C core of igraph.") - print(" Source folder: {0}".format(source_folder)) - print(" Build folder: {0}".format(build_folder)) - print(" Install folder: {0}".format(install_folder)) - print("") - - source_folder = source_folder.resolve() - build_folder = build_folder.resolve() - install_folder = install_folder.resolve() - - Path(build_folder).mkdir(parents=True, exist_ok=True) - - cwd = os.getcwd() - try: - libraries = igraph_builder.compile_in( - source_folder=source_folder, - build_folder=build_folder, - install_folder=install_folder, - ) - finally: - os.chdir(cwd) - - igraph_builder.create_build_config_file(install_folder, libraries) - - self.use_vendored_igraph() - return True - - def configure(self, ext): - """Configures the given Extension object using this build configuration.""" - ext.include_dirs = exclude_from_list( - ext.include_dirs, self.excluded_include_dirs - ) - ext.library_dirs = exclude_from_list( - self.library_dirs, self.excluded_library_dirs - ) - ext.runtime_library_dirs = self.runtime_library_dirs - ext.libraries = self.libraries - ext.extra_compile_args = self.extra_compile_args - ext.extra_link_args = self.extra_link_args - ext.extra_objects = self.extra_objects - ext.define_macros = self.define_macros - - def detect_from_pkgconfig(self): - """Detects the igraph include directory, library directory and the - list of libraries to link to using ``pkg-config``.""" - if not buildcfg.has_pkgconfig: - return False - - cmd = ["pkg-config", "igraph", "--cflags", "--libs"] - if self.static_extension: - cmd += ["--static"] - line, exit_code = get_output_single_line(cmd) - if exit_code > 0 or len(line) == 0: - return False - - opts = line.strip().split() - self.libraries = [opt[2:] for opt in opts if opt.startswith("-l")] - self.library_dirs = [opt[2:] for opt in opts if opt.startswith("-L")] - self.include_dirs = [opt[2:] for opt in opts if opt.startswith("-I")] - return True - - def print_build_info(self): - """Prints the include and library path being used for debugging purposes.""" - if self.static_extension == "only_igraph": - build_type = "dynamic extension with vendored igraph source" - elif self.static_extension: - build_type = "static extension" - else: - build_type = "dynamic extension" - print("Build type: %s" % build_type) - print("Include path: %s" % " ".join(self.include_dirs)) - if self.excluded_include_dirs: - print(" - excluding: %s" % " ".join(self.excluded_include_dirs)) - print("Library path: %s" % " ".join(self.library_dirs)) - if self.excluded_library_dirs: - print(" - excluding: %s" % " ".join(self.excluded_library_dirs)) - print("Runtime library path: %s" % " ".join(self.runtime_library_dirs)) - print("Linked dynamic libraries: %s" % " ".join(self.libraries)) - print("Linked static libraries: %s" % " ".join(self.extra_objects)) - print("Extra compiler options: %s" % " ".join(self.extra_compile_args)) - print("Extra linker options: %s" % " ".join(self.extra_link_args)) - - def process_args_from_command_line(self): - """Preprocesses the command line options before they are passed to - setup.py and sets up the build configuration.""" - # Yes, this is ugly, but we don't want to interfere with setup.py's own - # option handling - opts_to_remove = [] - for idx, option in enumerate(sys.argv): - if not option.startswith("--"): - continue - if option == "--static": - opts_to_remove.append(idx) - self.static_extension = True - elif option == "--no-pkg-config": - opts_to_remove.append(idx) - self.use_pkgconfig = False - elif option == "--no-wait": - opts_to_remove.append(idx) - self.wait = False - elif option == "--external": - opts_to_remove.append(idx) - self.external = True - elif option == "--use-pkg-config": - opts_to_remove.append(idx) - self.use_pkgconfig = True - - for idx in reversed(opts_to_remove): - sys.argv[idx : (idx + 1)] = [] - - def replace_static_libraries(self, only=None, exclusions=None): - """Replaces references to libraries with full paths to their static - versions if the static version is to be found on the library path.""" - building_on_windows = building_on_windows_msvc() - - if not building_on_windows and "stdc++" not in self.libraries: - self.libraries.append("stdc++") - - if exclusions is None: - exclusions = [] - - print(f"Libraries: {self.libraries}") - print(f"Exclusions: {exclusions}") - for library_name in set(self.libraries) - set(exclusions): - if only is not None and library_name not in only: - continue - - static_lib = find_static_library(library_name, self.library_dirs) - if static_lib: - print(f"Found {library_name} as static library in {static_lib}.") - self.libraries.remove(library_name) - self.extra_objects.append(static_lib) - else: - print(f"Warning: could not find static library of {library_name}.") - - def use_vendored_igraph(self): - """Assumes that igraph is installed already in ``vendor/install/igraph`` and sets up - the include and library paths and the library names accordingly.""" - building_on_windows = building_on_windows_msvc() - - vendor_dir = Path("vendor") / "install" / "igraph" - - buildcfg.include_dirs = [str(vendor_dir / "include" / "igraph")] - buildcfg.library_dirs = [] - - for candidate in ("lib", "lib64"): - candidate = vendor_dir / candidate - if candidate.exists(): - buildcfg.library_dirs.append(str(candidate)) - break - else: - raise RuntimeError("cannot detect igraph library dir within " + str(vendor_dir)) - - if not buildcfg.static_extension: - buildcfg.static_extension = "only_igraph" - if building_on_windows: - buildcfg.define_macros.append(("IGRAPH_STATIC", "1")) - - buildcfg_file = vendor_dir / "build.cfg" - if buildcfg_file.exists(): - buildcfg.libraries = eval(buildcfg_file.open("r").read()) - - def use_educated_guess(self): - """Tries to guess the proper library names, include and library paths.""" - - print("""WARNING: You are trying to install with an external igraph library. -No include dirs or library dirs are specified, so they need to be set externally. -If compilation fails you may adjust the following environment variables to adjust -the required paths. -- IGRAPH_EXTRA_INCLUDE_PATH -- IGRAPH_EXTRA_LIBRARY_PATH -- IGRAPH_EXTRA_LIBRARIES -- IGRAPH_EXTRA_DYNAMIC_LIBRARIES - -If a static build extension is used, we try to statically link to igraph. The extra -libraries that are specified are then also assumed to be statically linked. If, in -addition, some libraries need to be explicitly dynamically linked, you can specify this. - """) - - self.libraries = ['igraph'] - self.include_dirs = [] - self.library_dirs = [] - - -########################################################################### - -# Process command line options -buildcfg = BuildConfiguration() -buildcfg.process_args_from_command_line() - - - -# Define the extension -leiden_ext = Extension('leidenalg._c_leiden', - sources = glob.glob(os.path.join('src', 'leidenalg', '*.cpp')) + glob.glob(os.path.join('vendor', 'source', 'alglib', 'src', '*.cpp')), - include_dirs=['include', 'vendor/source/alglib/src']); - -options = dict( - name = 'leidenalg', - description = 'Leiden is a general algorithm for methods of community detection in large networks. MODIFIED VERSION', - long_description= - """ - Leiden is a general algorithm for methods of community detection in large networks. - - Please refer to the `documentation `_ - for more details. - - The source code of this package is hosted at `GitHub `_. - Issues and bug reports are welcome at https://github.com/vtraag/leidenalg/issues. - """, - license = 'GPLv3+', - url = 'https://github.com/vtraag/leidenalg', - - use_scm_version={ - 'write_to': 'src/leidenalg/version.py', - }, - setup_requires=['setuptools_scm'], - - author = 'V.A. Traag', - author_email = 'vincent@traag.net', - test_suite = 'tests', - - provides = ['leidenalg'], - package_dir = {'leidenalg': os.path.join('src', 'leidenalg')}, - packages = ['leidenalg'], - ext_modules = [leiden_ext], - install_requires = ['igraph >= 0.9.0,< 0.10'], - platforms="ALL", - keywords=[ - 'graph', - 'network', - 'community detection', - 'clustering' - ], - classifiers=[ - 'Development Status :: 4 - Beta', - 'Environment :: Console', - 'Intended Audience :: End Users/Desktop', - 'Intended Audience :: Developers', - 'Intended Audience :: Science/Research', - 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Operating System :: POSIX', - 'Programming Language :: Python', - 'Programming Language :: C++', - 'Topic :: Scientific/Engineering :: Mathematics', - 'Topic :: Scientific/Engineering :: Information Analysis', - 'Topic :: Sociology' - ], - cmdclass={ - "build_c_core": buildcfg.build_c_core, # used by CI - "build_ext": buildcfg.build_ext, - "sdist": buildcfg.sdist - }, -) - -setup(**options) \ No newline at end of file diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/CPMVertexPartition.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/CPMVertexPartition.cpp deleted file mode 100644 index 57f08f7..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/CPMVertexPartition.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include "CPMVertexPartition.h" - -CPMVertexPartition::CPMVertexPartition(Graph* graph, - vector membership, double resolution_parameter) : - LinearResolutionParameterVertexPartition(graph, - membership, resolution_parameter) -{ } - -CPMVertexPartition::CPMVertexPartition(Graph* graph, - vector membership) : - LinearResolutionParameterVertexPartition(graph, - membership) -{ } - -CPMVertexPartition::CPMVertexPartition(Graph* graph, - double resolution_parameter) : - LinearResolutionParameterVertexPartition(graph, resolution_parameter) -{ } - -CPMVertexPartition::CPMVertexPartition(Graph* graph) : - LinearResolutionParameterVertexPartition(graph) -{ } - -CPMVertexPartition::~CPMVertexPartition() -{ } - -CPMVertexPartition* CPMVertexPartition::create(Graph* graph) -{ - return new CPMVertexPartition(graph, this->resolution_parameter); -} - -CPMVertexPartition* CPMVertexPartition::create(Graph* graph, vector const& membership) -{ - return new CPMVertexPartition(graph, membership, this->resolution_parameter); -} - -/******************************************************************************** - RBER implementation of a vertex partition - (which includes a resolution parameter). - ********************************************************************************/ -double CPMVertexPartition::diff_move(size_t v, size_t new_comm) -{ - #ifdef DEBUG - cerr << "double CPMVertexPartition::diff_move(" << v << ", " << new_comm << ")" << endl; - cerr << "Using resolution parameter: " << this->resolution_parameter << "." << endl; - #endif - size_t old_comm = this->membership(v); - double diff = 0.0; - if (new_comm != old_comm) - { - double w_to_old = this->weight_to_comm(v, old_comm); - #ifdef DEBUG - cerr << "\t" << "w_to_old: " << w_to_old << endl; - #endif - double w_to_new = this->weight_to_comm(v, new_comm); - #ifdef DEBUG - cerr << "\t" << "w_to_new: " << w_to_new << endl; - #endif - double w_from_old = this->weight_from_comm(v, old_comm); - #ifdef DEBUG - cerr << "\t" << "w_from_old: " << w_from_old << endl; - #endif - double w_from_new = this->weight_from_comm(v, new_comm); - #ifdef DEBUG - cerr << "\t" << "w_from_new: " << w_from_new << endl; - #endif - size_t nsize = this->graph->node_size(v); - #ifdef DEBUG - cerr << "\t" << "nsize: " << nsize << endl; - #endif - size_t csize_old = this->csize(old_comm); - #ifdef DEBUG - cerr << "\t" << "csize_old: " << csize_old << endl; - #endif - size_t csize_new = this->csize(new_comm); - #ifdef DEBUG - cerr << "\t" << "csize_new: " << csize_new << endl; - #endif - double self_weight = this->graph->node_self_weight(v); - #ifdef DEBUG - cerr << "\t" << "self_weight: " << self_weight << endl; - cerr << "\t" << "density: " << this->graph->density() << endl; - #endif - double possible_edge_difference_old = 0.0; - if (this->graph->correct_self_loops()) - possible_edge_difference_old = nsize*(2.0*csize_old - nsize); - else - possible_edge_difference_old = nsize*(2.0*csize_old - nsize - 1.0); - #ifdef DEBUG - cerr << "\t" << "possible_edge_difference_old: " << possible_edge_difference_old << endl; - #endif - double diff_old = w_to_old + w_from_old - - self_weight - this->resolution_parameter*possible_edge_difference_old; - #ifdef DEBUG - cerr << "\t" << "diff_old: " << diff_old << endl; - #endif - double possible_edge_difference_new = 0.0; - if (this->graph->correct_self_loops()) - possible_edge_difference_new = nsize*(2.0*csize_new + nsize); - else - possible_edge_difference_new = nsize*(2.0*csize_new + nsize - 1.0); - #ifdef DEBUG - cerr << "\t" << "possible_edge_difference_new: " << possible_edge_difference_new << endl; - #endif - double diff_new = w_to_new + w_from_new + self_weight - - this->resolution_parameter*possible_edge_difference_new; - #ifdef DEBUG - cerr << "\t" << "diff_new: " << diff_new << endl; - #endif - diff = diff_new - diff_old; - #ifdef DEBUG - cerr << "\t" << "diff: " << diff << endl;; - #endif - } - #ifdef DEBUG - cerr << "exit CPMVertexPartition::diff_move(" << v << ", " << new_comm << ")" << endl; - cerr << "return " << diff << endl << endl; - #endif - return diff; -} - -double CPMVertexPartition::quality(double resolution_parameter) -{ - #ifdef DEBUG - cerr << "double CPMVertexPartition::quality()" << endl; - #endif - double mod = 0.0; - for (size_t c = 0; c < this->n_communities(); c++) - { - size_t csize = this->csize(c); - double w = this->total_weight_in_comm(c); - size_t comm_possible_edges = this->graph->possible_edges(csize); - - #ifdef DEBUG - cerr << "\t" << "Comm: " << c << ", w_c=" << w << ", n_c=" << csize << ", comm_possible_edges=" << comm_possible_edges << ", p=" << this->graph->density() << "." << endl; - #endif - mod += w - resolution_parameter*comm_possible_edges; - } - #ifdef DEBUG - cerr << "exit double CPMVertexPartition::quality()" << endl; - cerr << "return " << mod << endl << endl; - #endif - return (2.0 - this->graph->is_directed())*mod; -} - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/GraphHelper.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/GraphHelper.cpp deleted file mode 100644 index ca9cef3..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/GraphHelper.cpp +++ /dev/null @@ -1,786 +0,0 @@ -#include "GraphHelper.h" - -#ifdef DEBUG - using std::cerr; - using std::endl; -#endif - -vector range(size_t n) -{ - vector range_vec(n); - for(size_t i = 0; i < n; i++) - range_vec[i] = i; - return range_vec; -} - -bool orderCSize(const size_t* A, const size_t* B) -{ - - if (A[1] == B[1]) - { - if (A[2] == B[2]) - return A[0] < B[0]; - else - return A[2] > B[2]; - } - else - return A[1] > B[1]; -} - -void shuffle(vector& v, igraph_rng_t* rng) -{ - size_t n = v.size(); - if (n > 0) - { - for (size_t idx = n - 1; idx > 0; idx--) - { - size_t rand_idx = get_random_int(0, idx, rng); - size_t tmp = v[idx]; - v[idx] = v[rand_idx]; - v[rand_idx] = tmp; - } - } -} - -/**************************************************************************** - The binary Kullback-Leibler divergence. -****************************************************************************/ -double KL(double q, double p) -{ - double KL = 0.0; - if (q > 0.0 && p > 0.0) - KL += q*log(q/p); - if (q < 1.0 && p < 1.0) - KL += (1.0-q)*log((1.0-q)/(1.0-p)); - return KL; -} - -double KLL(double q, double p) -{ - double KL = 0.0; - if (q > 0.0 && p > 0.0) - KL += q*log(q/p); - if (q < 1.0 && p < 1.0) - KL += (1.0-q)*log((1.0-q)/(1.0-p)); - if (q < p) - KL *= -1; - return KL; -} - -Graph::Graph(igraph_t* graph, - vector const& edge_weights, - vector const& node_sizes, - vector const& node_self_weights, int correct_self_loops) -{ - this->_graph = graph; - this->_remove_graph = false; - - if (edge_weights.size() != this->ecount()) - throw Exception("Edge weights vector inconsistent length with the edge count of the graph."); - this->_edge_weights = edge_weights; - this->_is_weighted = true; - - if (node_sizes.size() != this->vcount()) - throw Exception("Node size vector inconsistent length with the vertex count of the graph."); - this->_node_sizes = node_sizes; - - if (node_self_weights.size() != this->vcount()) - throw Exception("Node self weights vector inconsistent length with the vertex count of the graph."); - this->_node_self_weights = node_self_weights; - - this->_correct_self_loops = correct_self_loops; - igraph_vector_init(&this->_temp_igraph_vector, this->vcount()); - this->init_admin(); -} - -Graph::Graph(igraph_t* graph, - vector const& edge_weights, - vector const& node_sizes, - vector const& node_self_weights) -{ - this->_graph = graph; - this->_remove_graph = false; - - if (edge_weights.size() != this->ecount()) - throw Exception("Edge weights vector inconsistent length with the edge count of the graph."); - this->_edge_weights = edge_weights; - this->_is_weighted = true; - - if (node_sizes.size() != this->vcount()) - throw Exception("Node size vector inconsistent length with the vertex count of the graph."); - this->_node_sizes = node_sizes; - - this->_correct_self_loops = this->has_self_loops(); - - this->_node_self_weights = node_self_weights; - igraph_vector_init(&this->_temp_igraph_vector, this->vcount()); - this->init_admin(); -} - -Graph::Graph(igraph_t* graph, - vector const& edge_weights, - vector const& node_sizes, int correct_self_loops) -{ - this->_graph = graph; - this->_remove_graph = false; - - if (edge_weights.size() != this->ecount()) - throw Exception("Edge weights vector inconsistent length with the edge count of the graph."); - this->_edge_weights = edge_weights; - this->_is_weighted = true; - - if (node_sizes.size() != this->vcount()) - throw Exception("Node size vector inconsistent length with the vertex count of the graph."); - this->_node_sizes = node_sizes; - - this->_correct_self_loops = correct_self_loops; - igraph_vector_init(&this->_temp_igraph_vector, this->vcount()); - this->init_admin(); - this->set_self_weights(); -} - -Graph::Graph(igraph_t* graph, - vector const& edge_weights, - vector const& node_sizes) -{ - this->_graph = graph; - this->_remove_graph = false; - if (edge_weights.size() != this->ecount()) - throw Exception("Edge weights vector inconsistent length with the edge count of the graph."); - this->_edge_weights = edge_weights; - this->_is_weighted = true; - - if (node_sizes.size() != this->vcount()) - throw Exception("Node size vector inconsistent length with the vertex count of the graph."); - this->_node_sizes = node_sizes; - - this->_correct_self_loops = this->has_self_loops(); - - igraph_vector_init(&this->_temp_igraph_vector, this->vcount()); - this->init_admin(); - this->set_self_weights(); -} - -Graph::Graph(igraph_t* graph, vector const& edge_weights, int correct_self_loops) -{ - this->_graph = graph; - this->_remove_graph = false; - this->_correct_self_loops = correct_self_loops; - if (edge_weights.size() != this->ecount()) - throw Exception("Edge weights vector inconsistent length with the edge count of the graph."); - this->_edge_weights = edge_weights; - this->_is_weighted = true; - this->set_default_node_size(); - igraph_vector_init(&this->_temp_igraph_vector, this->vcount()); - this->init_admin(); - this->set_self_weights(); -} - -Graph::Graph(igraph_t* graph, vector const& edge_weights) -{ - this->_graph = graph; - this->_remove_graph = false; - if (edge_weights.size() != this->ecount()) - throw Exception("Edge weights vector inconsistent length with the edge count of the graph."); - this->_edge_weights = edge_weights; - this->_is_weighted = true; - - this->_correct_self_loops = this->has_self_loops(); - - this->set_default_node_size(); - igraph_vector_init(&this->_temp_igraph_vector, this->vcount()); - this->init_admin(); - this->set_self_weights(); -} - -Graph::Graph(igraph_t* graph, vector const& node_sizes, int correct_self_loops) -{ - this->_graph = graph; - this->_remove_graph = false; - this->_correct_self_loops = correct_self_loops; - - if (node_sizes.size() != this->vcount()) - throw Exception("Node size vector inconsistent length with the vertex count of the graph."); - this->_node_sizes = node_sizes; - - this->set_default_edge_weight(); - this->_is_weighted = false; - igraph_vector_init(&this->_temp_igraph_vector, this->vcount()); - this->init_admin(); - this->set_self_weights(); -} - -Graph::Graph(igraph_t* graph, vector const& node_sizes) -{ - this->_graph = graph; - this->_remove_graph = false; - this->set_defaults(); - this->_is_weighted = false; - - if (node_sizes.size() != this->vcount()) - throw Exception("Node size vector inconsistent length with the vertex count of the graph."); - - this->_node_sizes = node_sizes; - - this->_correct_self_loops = this->has_self_loops(); - - igraph_vector_init(&this->_temp_igraph_vector, this->vcount()); - this->init_admin(); - this->set_self_weights(); -} - -Graph::Graph(igraph_t* graph, int correct_self_loops) -{ - this->_graph = graph; - this->_remove_graph = false; - this->_correct_self_loops = correct_self_loops; - this->set_defaults(); - this->_is_weighted = false; - igraph_vector_init(&this->_temp_igraph_vector, this->vcount()); - this->init_admin(); - this->set_self_weights(); -} - -Graph::Graph(igraph_t* graph) -{ - this->_graph = graph; - this->_remove_graph = false; - this->set_defaults(); - this->_is_weighted = false; - - this->_correct_self_loops = this->has_self_loops(); - - igraph_vector_init(&this->_temp_igraph_vector, this->vcount()); - this->init_admin(); - this->set_self_weights(); -} - -Graph::Graph() -{ - this->_graph = new igraph_t(); - this->_remove_graph = true; - this->set_defaults(); - this->_is_weighted = false; - this->_correct_self_loops = false; - igraph_vector_init(&this->_temp_igraph_vector, this->vcount()); - this->init_admin(); - this->set_self_weights(); -} - -Graph::~Graph() -{ - if (this->_remove_graph) - { - igraph_destroy(this->_graph); - delete this->_graph; - } - igraph_vector_destroy(&this->_temp_igraph_vector); -} - -int Graph::has_self_loops() -{ - size_t m = this->ecount(); - igraph_vector_bool_t loop; - igraph_vector_bool_init(&loop, m); - igraph_is_loop(this->_graph, &loop, igraph_ess_all(IGRAPH_EDGEORDER_ID)); - - int has_self_loops = false; - for (size_t idx = 0; idx < m; idx++) - { - if (VECTOR(loop)[idx]) - { - has_self_loops = true; - break; - } - } - igraph_vector_bool_destroy(&loop); - return has_self_loops; -} - -size_t Graph::possible_edges() -{ - return this->possible_edges(this->vcount()); -} - -size_t Graph::possible_edges(size_t n) -{ - size_t possible_edges = n*(n-1); - if (!this->is_directed()) - possible_edges /= 2; - if (this->correct_self_loops()) - possible_edges += n; - - return possible_edges; -} - -void Graph::set_defaults() -{ - this->set_default_edge_weight(); - this->set_default_node_size(); -} - -void Graph::set_default_edge_weight() -{ - size_t m = this->ecount(); - - // Set default edge weight of 1.0 - this->_edge_weights.clear(); this->_edge_weights.resize(m); - fill(this->_edge_weights.begin(), this->_edge_weights.end(), 1.0); - this->_is_weighted = false; -} - -void Graph::set_default_node_size() -{ - size_t n = this->vcount(); - - // Set default node size of 1 - this->_node_sizes.clear(); this->_node_sizes.resize(n); - fill(this->_node_sizes.begin(), this->_node_sizes.end(), 1); -} - -void Graph::set_self_weights() -{ - size_t n = this->vcount(); - - // Set default self_weights of the total weight of any possible self-loops - this->_node_self_weights.clear(); this->_node_self_weights.resize(n); - for (size_t v = 0; v < n; v++) - { - #ifdef DEBUG - cerr << "\t" << "Size node " << v << ": " << this->node_size(v) << endl; - #endif - double self_weight = 0.0; - // There should be only one self loop - igraph_integer_t eid; - // Get edge id for self loop - igraph_get_eid(this->_graph, &eid, v, v, this->is_directed(), false); - if (eid >= 0) - self_weight = this->edge_weight(eid); - - this->_node_self_weights[v] = self_weight; - #ifdef DEBUG - cerr << "\t" << "Self weight node " << v << ": " << self_weight << endl; - #endif - } -} - -void Graph::init_admin() -{ - - size_t m = this->ecount(); - size_t n = this->vcount(); - this->_is_directed = igraph_is_directed(this->_graph); - - this->_strength_in.clear(); - this->_strength_in.resize(n, 0.0); - - this->_degree_in.clear(); - this->_degree_in.resize(n, 0.0); - - if (this->_is_directed) { - this->_strength_out.clear(); - this->_strength_out.resize(n, 0.0); - - this->_degree_out.clear(); - this->_degree_out.resize(n, 0); - - this->_degree_all.clear(); - this->_degree_all.resize(n, 0); - } - - // Determine total weight in the graph. - this->_total_weight = 0.0; - for (size_t e = 0; e < m; e++) { - double w = this->edge_weight(e); - this->_total_weight += w; - - size_t from, to; - this->edge(e, from, to); - - if (this->is_directed()) { - this->_strength_in[to] += w; - this->_strength_out[from] += w; - - this->_degree_in[to]++; - this->_degree_out[from]++; - this->_degree_all[to]++; - this->_degree_all[from]++; - } else { - // we only compute strength_in and degree_in for undirected graphs - this->_strength_in[to] += w; - this->_strength_in[from] += w; - - // recall that igraph ignores the mode for undirected graphs - this->_degree_in[to]++; - this->_degree_in[from]++; - } - } - - // Make sure to multiply by 2 for undirected graphs - //if (!this->is_directed()) - // this->_total_weight *= 2.0; - - this->_total_size = 0; - for (size_t v = 0; v < n; v++) - this->_total_size += this->node_size(v); - - // Calculate density; - double w = this->total_weight(); - size_t n_size = this->total_size(); - - // For now we default to not correcting self loops. - // this->_correct_self_loops = false; (remove this as this is set in the constructor) - - double normalise = 0.0; - if (this->_correct_self_loops) - normalise = n_size*n_size; - else - normalise = n_size*(n_size - 1); - - if (this->is_directed()) - this->_density = w/normalise; - else - this->_density = 2*w/normalise; - - this->_current_node_cache_neigh_edges_from = n + 1; - this->_current_node_cache_neigh_edges_to = n + 1; - this->_current_node_cache_neigh_edges_all = n + 1; - - this->_current_node_cache_neigh_from = n + 1; - this->_current_node_cache_neigh_to = n + 1; - this->_current_node_cache_neigh_all = n + 1; -} - -void Graph::cache_neighbour_edges(size_t v, igraph_neimode_t mode) -{ - #ifdef DEBUG - cerr << "void Graph::cache_neighbour_edges(" << v << ", " << mode << ");" << endl; - #endif - size_t degree = this->degree(v, mode); - #ifdef DEBUG - cerr << "Degree: " << degree << endl; - #endif - - igraph_vector_t *incident_edges = &this->_temp_igraph_vector; - igraph_incident(this->_graph, incident_edges, v, mode); - - vector* _cached_neigh_edges = NULL; - switch (mode) - { - case IGRAPH_IN: - this->_current_node_cache_neigh_edges_from = v; - _cached_neigh_edges = &(this->_cached_neigh_edges_from); - break; - case IGRAPH_OUT: - this->_current_node_cache_neigh_edges_to = v; - _cached_neigh_edges = &(this->_cached_neigh_edges_to); - break; - case IGRAPH_ALL: - this->_current_node_cache_neigh_edges_all = v; - _cached_neigh_edges = &(this->_cached_neigh_edges_all); - break; - } - _cached_neigh_edges->assign(igraph_vector_e_ptr(incident_edges, 0), - igraph_vector_e_ptr(incident_edges, degree)); - #ifdef DEBUG - cerr << "Number of edges: " << _cached_neigh_edges->size() << endl; - #endif - - #ifdef DEBUG - cerr << "exit void Graph::cache_neighbour_edges(" << v << ", " << mode << ");" << endl; - #endif -} - -vector const& Graph::get_neighbour_edges(size_t v, igraph_neimode_t mode) -{ - if (!this->is_directed()) - mode = IGRAPH_ALL; // igraph ignores mode for undirected graphs - - switch (mode) - { - case IGRAPH_IN: - if (this->_current_node_cache_neigh_edges_from != v) - { - cache_neighbour_edges(v, mode); - this->_current_node_cache_neigh_edges_from = v; - } - return this->_cached_neigh_edges_from; - case IGRAPH_OUT: - if (this->_current_node_cache_neigh_edges_to != v) - { - cache_neighbour_edges(v, mode); - this->_current_node_cache_neigh_edges_to = v; - } - return this->_cached_neigh_edges_to; - case IGRAPH_ALL: - if (this->_current_node_cache_neigh_edges_all != v) - { - cache_neighbour_edges(v, mode); - this->_current_node_cache_neigh_edges_all = v; - } - return this->_cached_neigh_edges_all; - } - throw Exception("Incorrect model for getting neighbour edges."); -} - -void Graph::cache_neighbours(size_t v, igraph_neimode_t mode) -{ - #ifdef DEBUG - cerr << "void Graph::cache_neighbours(" << v << ", " << mode << ");" << endl; - #endif - size_t degree = this->degree(v, mode); - #ifdef DEBUG - cerr << "Degree: " << degree << endl; - #endif - - igraph_vector_t *neighbours = &this->_temp_igraph_vector; - igraph_neighbors(this->_graph, neighbours, v, mode); - - vector* _cached_neighs = NULL; - switch (mode) - { - case IGRAPH_IN: - this->_current_node_cache_neigh_from = v; - _cached_neighs = &(this->_cached_neighs_from); - break; - case IGRAPH_OUT: - this->_current_node_cache_neigh_to = v; - _cached_neighs = &(this->_cached_neighs_to); - break; - case IGRAPH_ALL: - this->_current_node_cache_neigh_all = v; - _cached_neighs = &(this->_cached_neighs_all); - break; - } - _cached_neighs->assign(igraph_vector_e_ptr(neighbours, 0),igraph_vector_e_ptr(neighbours, degree)); - - #ifdef DEBUG - cerr << "Number of edges: " << _cached_neighs->size() << endl; - #endif - - #ifdef DEBUG - cerr << "exit void Graph::cache_neighbours(" << v << ", " << mode << ");" << endl; - #endif -} - -vector< size_t > const& Graph::get_neighbours(size_t v, igraph_neimode_t mode) -{ - if (!this->is_directed()) - mode = IGRAPH_ALL; // igraph ignores mode for undirected graphs - - switch (mode) - { - case IGRAPH_IN: - if (this->_current_node_cache_neigh_from != v) - { - cache_neighbours(v, mode); - this -> _current_node_cache_neigh_from = v; - } - #ifdef DEBUG - cerr << "Returning " << this->_cached_neighs_from.size() << " incoming neighbours" << endl; - #endif - return this->_cached_neighs_from; - case IGRAPH_OUT: - if (this->_current_node_cache_neigh_to != v) - { - cache_neighbours(v, mode); - this -> _current_node_cache_neigh_to = v; - } - #ifdef DEBUG - cerr << "Returning " << this->_cached_neighs_to.size() << " incoming neighbours" << endl; - #endif - return this->_cached_neighs_to; - case IGRAPH_ALL: - if (this->_current_node_cache_neigh_all != v) - { - cache_neighbours(v, mode); - this->_current_node_cache_neigh_all = v; - } - #ifdef DEBUG - cerr << "Returning " << this->_cached_neighs_all.size() << " incoming neighbours" << endl; - #endif - return this->_cached_neighs_all; - } - throw Exception("Invalid mode for getting neighbours."); -} - -/******************************************************************************** - * This should return a random neighbour in O(1) - ********************************************************************************/ -size_t Graph::get_random_neighbour(size_t v, igraph_neimode_t mode, igraph_rng_t* rng) -{ - size_t node=v; - size_t rand_neigh = -1; - - if (this->degree(v, mode) <= 0) - throw Exception("Cannot select a random neighbour for an isolated node."); - - if (this->is_directed() && mode != IGRAPH_ALL) - { - if (mode == IGRAPH_OUT) - { - // Get indices of where neighbours are - size_t cum_degree_this_node = (size_t) VECTOR(this->_graph->os)[node]; - size_t cum_degree_next_node = (size_t) VECTOR(this->_graph->os)[node+1]; - // Get a random index from them - size_t rand_neigh_idx = get_random_int(cum_degree_this_node, cum_degree_next_node - 1, rng); - // Return the neighbour at that index - #ifdef DEBUG - cerr << "Degree: " << this->degree(node, mode) << " diff in cumulative: " << cum_degree_next_node - cum_degree_this_node << endl; - #endif - rand_neigh = VECTOR(this->_graph->to)[ (size_t)VECTOR(this->_graph->oi)[rand_neigh_idx] ]; - } - else if (mode == IGRAPH_IN) - { - // Get indices of where neighbours are - size_t cum_degree_this_node = (size_t) VECTOR(this->_graph->is)[node]; - size_t cum_degree_next_node = (size_t) VECTOR(this->_graph->is)[node+1]; - // Get a random index from them - size_t rand_neigh_idx = get_random_int(cum_degree_this_node, cum_degree_next_node - 1, rng); - #ifdef DEBUG - cerr << "Degree: " << this->degree(node, mode) << " diff in cumulative: " << cum_degree_next_node - cum_degree_this_node << endl; - #endif - // Return the neighbour at that index - rand_neigh = VECTOR(this->_graph->from)[ (size_t)VECTOR(this->_graph->ii)[rand_neigh_idx] ]; - } - } - else - { - // both in- and out- neighbors in a directed graph. - size_t cum_outdegree_this_node = (size_t)VECTOR(this->_graph->os)[node]; - size_t cum_indegree_this_node = (size_t)VECTOR(this->_graph->is)[node]; - - size_t cum_outdegree_next_node = (size_t)VECTOR(this->_graph->os)[node+1]; - size_t cum_indegree_next_node = (size_t)VECTOR(this->_graph->is)[node+1]; - - size_t total_outdegree = cum_outdegree_next_node - cum_outdegree_this_node; - size_t total_indegree = cum_indegree_next_node - cum_indegree_this_node; - - size_t rand_idx = get_random_int(0, total_outdegree + total_indegree - 1, rng); - - #ifdef DEBUG - cerr << "Degree: " << this->degree(node, mode) << " diff in cumulative: " << total_outdegree + total_indegree << endl; - #endif - // From among in or out neighbours? - if (rand_idx < total_outdegree) - { // From among outgoing neighbours - size_t rand_neigh_idx = cum_outdegree_this_node + rand_idx; - rand_neigh = VECTOR(this->_graph->to)[ (size_t)VECTOR(this->_graph->oi)[rand_neigh_idx] ]; - } - else - { // From among incoming neighbours - size_t rand_neigh_idx = cum_indegree_this_node + rand_idx - total_outdegree; - rand_neigh = VECTOR(this->_graph->from)[ (size_t)VECTOR(this->_graph->ii)[rand_neigh_idx] ]; - } - } - - return rand_neigh; -} - -/**************************************************************************** - Creates a graph with communities as node and links as weights between - communities. - - The weight of the edges in the new graph is simply the sum of the weight - of the edges between the communities. The self weight of a node (i.e. the - weight of its self loop) is the internal weight of a community. The size - of a node in the new graph is simply the size of the community in the old - graph. -*****************************************************************************/ -Graph* Graph::collapse_graph(MutableVertexPartition* partition) -{ - #ifdef DEBUG - cerr << "Graph* Graph::collapse_graph(vector membership)" << endl; - #endif - - #ifdef DEBUG - cerr << "Current graph has " << this->vcount() << " nodes and " << this->ecount() << " edges." << endl; - cerr << "Collapsing to graph with " << partition->n_communities() << " nodes." << endl; - #endif - - size_t n_collapsed = partition->n_communities(); - vector > community_memberships = partition->get_communities(); - - vector collapsed_weights; - double total_collapsed_weight = 0.0; - - vector edge_weight_to_community(n_collapsed, 0.0); - vector neighbour_comm_added(n_collapsed, false); - - // collapsed edges for new graph - igraph_vector_t edges; - igraph_vector_init(&edges, 0); - - for (size_t v_comm = 0; v_comm < n_collapsed; v_comm++) { - vector neighbour_communities; - for (size_t v : community_memberships[v_comm]) { - for (size_t e : this->get_neighbour_edges(v, IGRAPH_OUT)) { - size_t from, to; - this->edge(e, from, to); - - if ((size_t) from != v) { - // need to skip because IGRAPH_OUT is ignored for undirected graphs - continue; - } - - size_t u_comm = partition->membership(to); - - double w = this->edge_weight(e); - // Self loops appear twice here if the graph is undirected, so divide by 2.0 in that case. - if (from == to && !this->is_directed()) - w /= 2.0; - - if (!neighbour_comm_added[u_comm]) { - neighbour_comm_added[u_comm] = true; - neighbour_communities.push_back(u_comm); - } - edge_weight_to_community[u_comm] += w; - } - } - - for (size_t u_comm : neighbour_communities) { - igraph_vector_push_back(&edges, v_comm); - igraph_vector_push_back(&edges, u_comm); - collapsed_weights.push_back(edge_weight_to_community[u_comm]); - total_collapsed_weight += edge_weight_to_community[u_comm]; - - // reset edge_weight_to_community to all 0.0 and neighbour_comm_added to all false - edge_weight_to_community[u_comm] = 0.0; - neighbour_comm_added[u_comm] = false; - } - } - - // Create graph based on edges - igraph_t* graph = new igraph_t(); - igraph_create(graph, &edges, n_collapsed, this->is_directed()); - igraph_vector_destroy(&edges); - - if ((size_t) igraph_vcount(graph) != partition->n_communities()) - throw Exception("Something went wrong with collapsing the graph."); - - // Calculate new node sizes - vector csizes(n_collapsed, 0); - for (size_t c = 0; c < partition->n_communities(); c++) - csizes[c] = partition->csize(c); - - Graph* G = new Graph(graph, collapsed_weights, csizes, this->_correct_self_loops); - - std::vector< std::vector > current_names = this->get_features(); - std::vector< std::vector > new_names; - - for (std::vector comm : community_memberships) { - std::vector cluster_members; - for (size_t i : comm) { - for (int member : current_names[i]) - cluster_members.push_back(member); - } - new_names.push_back(cluster_members); - } - G->set_features(new_names); - - G->_remove_graph = true; - #ifdef DEBUG - cerr << "exit Graph::collapse_graph(vector membership)" << endl << endl; - #endif - return G; -} diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/HybridVertexPartition.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/HybridVertexPartition.cpp deleted file mode 100644 index 68f97d6..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/HybridVertexPartition.cpp +++ /dev/null @@ -1,433 +0,0 @@ -// -// Created by Mohamed Abdel-Hafiz on 10/7/21. -// - -#include "HybridVertexPartition.h" -#include - -#ifdef DEBUG -#include -using std::cerr; -using std::endl; -#endif - -HybridVertexPartition::HybridVertexPartition(Graph* graph, - vector const& membership) : - MutableVertexPartition(graph, - membership) -{ } - -HybridVertexPartition::HybridVertexPartition(Graph* graph) : - MutableVertexPartition(graph) -{ } - -HybridVertexPartition::HybridVertexPartition(Graph* graph, std::vector< std::vector > input_dataset, std::vector target, - double k1, double k2, double k3, double k4) : - MutableVertexPartition(graph), dataset(input_dataset), target(target), k1(k1), k2(k2), k3(k3), k4(k4) -{ -// igraph_t* rawGraph = this->get_graph()->get_igraph(); -//// for (int i=0; iget_graph()->vcount(); i++) { -//// igraph_real_t nodeName = VAN(rawGraph, "name", i); -//// printf("%d\n", nodeName); -//// } -// for (int i=0; iget_graph()->ecount(); i++) { -// printf("1\n"); -// printf("Null check: %d\n", rawGraph == NULL? 1 : 0); -// igraph_real_t edgeWeight = EAN(rawGraph, "weight", i); -// printf("2\n"); -// printf("%d\n", edgeWeight); -// } -// printf("3\n"); -// for (int i=0; i < this->_membership.size(); i++) { -// printf("%d\n", this->_membership[i]); -// } -// printf("Here4\n"); -// printf("%d\n", raw_dataset.size()); -//// this->dataset.reserve(raw_dataset.size()); -// printf("%d\n", this->n_communities()); -// this->dataset = std::vector< std::vector< std::vector > >(this->n_communities()); -// printf("%d\n", input_dataset.size()); -// printf("%d\n", this->dataset.size()); -// printf("Here5\n"); -// for (int i=0; idataset[i].push_back(input_dataset[i]); -// printf("Here8\n"); -// } -// printf("Here7\n"); -} - -HybridVertexPartition::HybridVertexPartition(Graph* graph, vector const& membership, - std::vector< std::vector > input_dataset, std::vector target, - double k1, double k2, double k3, double k4) : - MutableVertexPartition(graph, membership), dataset(input_dataset), target(target), k1(k1), k2(k2), k3(k3), k4(k4) -{ -// printf("Here1\n"); -// printf("%d\n%d\n", raw_dataset.size(), membership.size()); -//// this->dataset.reserve(raw_dataset.size()); -// this->dataset = std::vector< std::vector< std::vector > >(this->n_communities()); -// printf("%d\n", this->dataset.size()); -// for (int i=0; idataset[membership[i]].push_back(input_dataset[membership[i]]); -// } -// printf("Here3\n"); -} - -HybridVertexPartition::~HybridVertexPartition() -{ } - -HybridVertexPartition* HybridVertexPartition::create(Graph* graph) -{ - printf("Creating1\n"); - return new HybridVertexPartition(graph, this->dataset, this->target, this->k1, this->k2, this->k3, this->k4); - printf("Created\n"); -} - -HybridVertexPartition* HybridVertexPartition::create(Graph* graph, vector const& membership) -{ - printf("Creating2\n"); - return new HybridVertexPartition(graph, membership, this->dataset, this->target, this->k1, this->k2, this->k3, this->k4); - printf("Created\n"); -} - -/***************************************************************************** - Returns the difference in modularity if we move a node to a new community -*****************************************************************************/ -double HybridVertexPartition::diff_move(size_t v, size_t new_comm) -{ -#ifdef DEBUG - cerr << "double ModularityVertexPartition::diff_move(" << v << ", " << new_comm << ")" << endl; -#endif - size_t old_comm = this->_membership[v]; - double diff = 0.0; - double total_weight = this->graph->total_weight()*(2.0 - this->graph->is_directed()); - if (total_weight == 0.0) - return 0.0; - if (new_comm != old_comm) - { -#ifdef DEBUG - cerr << "\t" << "old_comm: " << old_comm << endl; -#endif - double w_to_old = this->weight_to_comm(v, old_comm); -#ifdef DEBUG - cerr << "\t" << "w_to_old: " << w_to_old << endl; -#endif - double w_from_old = this->weight_from_comm(v, old_comm); -#ifdef DEBUG - cerr << "\t" << "w_from_old: " << w_from_old << endl; -#endif - double w_to_new = this->weight_to_comm(v, new_comm); -#ifdef DEBUG - cerr << "\t" << "w_to_new: " << w_to_new << endl; -#endif - double w_from_new = this->weight_from_comm(v, new_comm); -#ifdef DEBUG - cerr << "\t" << "w_from_new: " << w_from_new << endl; -#endif - double k_out = this->graph->strength(v, IGRAPH_OUT); -#ifdef DEBUG - cerr << "\t" << "k_out: " << k_out << endl; -#endif - double k_in = this->graph->strength(v, IGRAPH_IN); -#ifdef DEBUG - cerr << "\t" << "k_in: " << k_in << endl; -#endif - double self_weight = this->graph->node_self_weight(v); -#ifdef DEBUG - cerr << "\t" << "self_weight: " << self_weight << endl; -#endif - double K_out_old = this->total_weight_from_comm(old_comm); -#ifdef DEBUG - cerr << "\t" << "K_out_old: " << K_out_old << endl; -#endif - double K_in_old = this->total_weight_to_comm(old_comm); -#ifdef DEBUG - cerr << "\t" << "K_in_old: " << K_in_old << endl; -#endif - double K_out_new = this->total_weight_from_comm(new_comm) + k_out; -#ifdef DEBUG - cerr << "\t" << "K_out_new: " << K_out_new << endl; -#endif - double K_in_new = this->total_weight_to_comm(new_comm) + k_in; -#ifdef DEBUG - cerr << "\t" << "K_in_new: " << K_in_new << endl; - cerr << "\t" << "total_weight: " << total_weight << endl; -#endif - double diff_old = (w_to_old - k_out*K_in_old/total_weight) + \ - (w_from_old - k_in*K_out_old/total_weight); -#ifdef DEBUG - cerr << "\t" << "diff_old: " << diff_old << endl; -#endif - double diff_new = (w_to_new + self_weight - k_out*K_in_new/total_weight) + \ - (w_from_new + self_weight - k_in*K_out_new/total_weight); -#ifdef DEBUG - cerr << "\t" << "diff_new: " << diff_new << endl; -#endif - diff = diff_new - diff_old; -#ifdef DEBUG - cerr << "\t" << "diff: " << diff << endl; -#endif - } -#ifdef DEBUG - cerr << "exit double ModularityVertexPartition::diff_move((" << v << ", " << new_comm << ")" << endl; - cerr << "return " << diff << endl << endl; -#endif - double m; - if (this->graph->is_directed()) - m = this->graph->total_weight(); - else - m = 2*this->graph->total_weight(); - -// double k1 = 0.1, k2 = 0.9; // Weights for correlation portion of quality measure -// double k3 = 0.5, k4 = 0.5; // Weights for correlation (k3) vs modularity (k4) in overall quality measure - double pearson_diff = 0; - try { - pearson_diff = this->calculate_correlation_diff(v, new_comm); -// printf("%f\n", pearson_diff); - } catch (const alglib::ap_error& e) { - printf("alglib::error: "); -// printf(e.msg.c_str()); - printf("\n"); - throw; - } - printf("k3: %f\tk4: %f\n", this->k3, this->k4); - printf("diff: %f\t p_diff: %f\t total: %f\n v: %d\t new_comm: %d\tN_Comm: %d\tmembership.size: %d\n", diff, pearson_diff, (this->k3*(diff/m)) + (this->k4*pearson_diff), v, new_comm, this->n_communities(), this->_membership.size()); - return (this->k3*(diff/m)) + (this->k4*pearson_diff); -} - - -/***************************************************************************** - Give the modularity of the partition. - - We here use the unscaled version of modularity, in other words, we don"t - normalise by the number of edges. -******************************************************************************/ -double HybridVertexPartition::quality() -{ -#ifdef DEBUG - cerr << "double ModularityVertexPartition::quality()" << endl; -#endif - double mod = 0.0; - double corr = 0.0; -// double k1 = 0.1, k2 = 0.9; // Weights for correlation portion of quality measure -// double k3 = 0.5, k4 = 0.5; // Weights for correlation (k3) vs modularity (k4) in overall quality measure - - printf("Test4\n"); - std::vector membership = this->membership(); - printf("Membership:\n"); - for (unsigned long i=0; i < membership.size(); i++) { - printf("%d\n", membership[i]); - } - printf("\\Membership\n"); - - double m; - if (this->graph->is_directed()) - m = this->graph->total_weight(); - else - m = 2*this->graph->total_weight(); - - if (m == 0) - return 0.0; - - for (size_t c = 0; c < this->n_communities(); c++) - { - double w = this->total_weight_in_comm(c); - double w_out = this->total_weight_from_comm(c); - double w_in = this->total_weight_to_comm(c); -#ifdef DEBUG - size_t csize = this->csize(c); - cerr << "\t" << "Comm: " << c << ", size=" << csize << ", w=" << w << ", w_out=" << w_out << ", w_in=" << w_in << "." << endl; -#endif - mod += w - w_out*w_in/((this->graph->is_directed() ? 1.0 : 4.0)*this->graph->total_weight()); - - // Calculating pearson correlation - std::vector members; - for (int i=0; i<_membership.size(); i++) { - if (this->_membership[i] == c) { - members.push_back(i); - } - } - - alglib::real_2d_array subset, V; - alglib::real_1d_array s2, pc, alg_target; - - subset.setlength(this->target.size(), members.size()); - for (int i=0; i node_ids = this->get_graph()->get_features(members[i]); - for (int j=0; jdataset[node_ids[j]].size(); j++) { - subset[k][i] = this->dataset[node_ids[j]][k]; - } - } - - V.setlength(members.size(), 1); - s2.setlength(1); - alglib::pcatruncatedsubspace(subset, this->dataset[0].size(), members.size(), 1, 0.0006, 100000, s2, V); - - pc.setlength(this->dataset[0].size()); - alg_target.setlength(this->target.size()); - for (int i=0; itarget.size(); i++) { - alg_target[i] = this->target[i]; - } - for (int i=0; idataset[0].size(); i++) { - pc[0] = 0; - for (int j=0; jgraph->is_directed())*mod; -#ifdef DEBUG - cerr << "exit double ModularityVertexPartition::quality()" << endl; - cerr << "return " << q/m << endl << endl; -#endif - - return (this->k3*(q/m)) + (this->k4*corr); -} - -double HybridVertexPartition::calculate_correlation_diff(size_t v, size_t new_comm) { -// printf("In diff func.\n"); - printf("Num comms: %d\n", this->get_graph()->get_features().size()); - size_t old_comm = this->_membership[v]; - std::vector old_members = std::vector(); - std::vector new_members = std::vector(); - for (int i=0; i < this->_membership.size(); i++) { - if (this->_membership[i] == old_comm) { - old_members.push_back(i); - } - if (this->_membership[i] == new_comm || i == v) { - new_members.push_back(i); - } - } - alglib::real_2d_array old_including, old_excluding, new_including, new_excluding; -// printf("\n\nStart\n"); -// printf("Dataset Size: %d\nFeature Size: %d\n", this->dataset.size(), this->dataset[v].size()); -// printf("Node: %d\nOld Community: %d, Size: %d\nNew Community: %d, Size: %d\n", v, old_comm, old_members.size(), new_comm, new_members.size()); - old_including.setlength(this->dataset[v].size(), old_members.size()); -// printf("Done."); - if (old_members.size() > 1) - old_excluding.setlength(this->dataset[v].size(), old_members.size() - 1); - new_including.setlength(this->dataset[v].size(), new_members.size()); - if (new_members.size() > 1) - new_excluding.setlength(this->dataset[v].size(), new_members.size() - 1); - int old_offset = 0, new_offset = 0; - for (int i=0; i node_ids = this->get_graph()->get_features(old_members[i]); -// printf("2\n"); - for (int j=0; jdataset[node_ids[j]].size(); k++) { -// printf("4\n"); - old_including[k][i] = this->dataset[node_ids[j]][k]; - if (old_members.size() > 1) { - if (old_members[i] != v) { - old_excluding[k][i - old_offset] = this->dataset[node_ids[j]][k]; - } else { - old_offset = 1; - } - } - } - } - } -// printf("5\n"); - for (int i=0; i node_ids = this->get_graph()->get_features(new_members[i]); -// printf("7\n"); - for (int j=0; jdataset[node_ids[j]].size(); k++) { -// printf("9\n"); - new_including[k][i] = this->dataset[node_ids[j]][k]; - if (new_members.size() > 1) { - if (new_members[i] != v) { - new_excluding[k][i - new_offset] = this->dataset[node_ids[j]][k]; - } else { - new_offset = 1; - } - } - } - } - } -// printf("10\n"); - alglib::real_1d_array s2_old_i, s2_old_e, s2_new_i, s2_new_e; - alglib::real_2d_array V_old_i, V_old_e, V_new_i, V_new_e; - s2_old_i.setlength(1); - if (old_members.size() > 1) - s2_old_e.setlength(1); - s2_new_i.setlength(1); - if (new_members.size() > 1) - s2_new_e.setlength(1); - V_old_i.setlength(old_members.size(), 1); - if (old_members.size() > 1) - V_old_e.setlength(old_members.size() - 1, 1); - V_new_i.setlength(new_members.size(), 1); - if (new_members.size() > 1) - V_new_e.setlength(new_members.size() - 1, 1); - - alglib::pcatruncatedsubspace(old_including, this->dataset[v].size(), old_members.size(), 1, 0.0006, 100000, s2_old_i, V_old_i); - if (old_members.size() > 1) - alglib::pcatruncatedsubspace(old_excluding, this->dataset[v].size(), old_members.size() - 1, 1, 0.0006, 100000, s2_old_e, V_old_e); - alglib::pcatruncatedsubspace(new_including, this->dataset[v].size(), new_members.size(), 1, 0.0006, 100000, s2_new_i, V_new_i); - if (new_members.size() > 1) - alglib::pcatruncatedsubspace(new_excluding, this->dataset[v].size(), new_members.size() - 1, 1, 0.0006, 100000, s2_new_e, V_new_e); - - alglib::real_1d_array alg_target, pc_old_i, pc_old_e, pc_new_i, pc_new_e; - alg_target.setlength(this->target.size()); - pc_old_i.setlength(this->dataset[v].size()); - if (old_members.size() > 1) - pc_old_e.setlength(this->dataset[v].size()); - pc_new_i.setlength(this->dataset[v].size()); - if (new_members.size() > 1) - pc_new_e.setlength(this->dataset[v].size()); - - for (int i=0; itarget.size(); i++) { - alg_target[i] = this->target[i]; - } - - for (int i=0; idataset[v].size(); i++) { - pc_old_i[i] = 0; - for (int j=0; j 1) { - for (int i = 0; i < this->dataset[v].size(); i++) { - pc_old_e[i] = 0; - for (int j = 0; j < old_members.size() - 1; j++) { - pc_old_e[i] += V_old_e(j, 0) * old_excluding(i, j); - } - } - } - for (int i=0; idataset[v].size(); i++) { - pc_new_i[i] = 0; - for (int j=0; j 1) { - for (int i = 0; i < this->dataset[v].size(); i++) { - pc_new_e[i] = 0; - for (int j = 0; j < new_members.size() - 1; j++) { - pc_new_e[i] += V_new_e(j, 0) * new_excluding(i, j); - } - } - } - - double p_old_i, p_old_e, p_new_i, p_new_e; - p_old_i = alglib::pearsoncorr2(pc_old_i, alg_target); - p_old_e = old_members.size() > 1 ? alglib::pearsoncorr2(pc_old_e, alg_target) : 0; - p_new_i = alglib::pearsoncorr2(pc_new_i, alg_target); - p_new_e = new_members.size() > 1 ? alglib::pearsoncorr2(pc_new_e, alg_target) : 0; - - printf("poi: %f\tpoe: %f\tpni: %f\tpne: %f\n", p_old_i, p_old_e, p_new_i, p_new_e); - -// return (abs(p_old_e) - abs(p_old_i)) + (abs(p_new_i) - abs(p_new_e)); // delta_old + delta_new - return ((0.5*(1-p_old_e)) - (0.5*(1-p_old_i))) + ((0.5*(1-p_new_i)) - (0.5*(1-p_new_e))); -// return ((0.5*(1+abs(p_old_e))) - (0.5*(1+abs(p_old_i)))) + ((0.5*(1+abs(p_new_i))) - (0.5*(1+abs(p_new_e)))); -} \ No newline at end of file diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/LinearResolutionParameterVertexPartition.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/LinearResolutionParameterVertexPartition.cpp deleted file mode 100644 index 12d5925..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/LinearResolutionParameterVertexPartition.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "LinearResolutionParameterVertexPartition.h" - -LinearResolutionParameterVertexPartition::LinearResolutionParameterVertexPartition(Graph* graph, - vector membership, double resolution_parameter) : - ResolutionParameterVertexPartition(graph, - membership, resolution_parameter) -{ } - -LinearResolutionParameterVertexPartition::LinearResolutionParameterVertexPartition(Graph* graph, - vector membership) : - ResolutionParameterVertexPartition(graph, - membership) -{ } - -LinearResolutionParameterVertexPartition::LinearResolutionParameterVertexPartition(Graph* graph, - double resolution_parameter) : - ResolutionParameterVertexPartition(graph, resolution_parameter) -{ } - -LinearResolutionParameterVertexPartition::LinearResolutionParameterVertexPartition(Graph* graph) : - ResolutionParameterVertexPartition(graph) -{ } - -LinearResolutionParameterVertexPartition::~LinearResolutionParameterVertexPartition() -{ } diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/ModularityVertexPartition.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/ModularityVertexPartition.cpp deleted file mode 100644 index 5dd97ee..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/ModularityVertexPartition.cpp +++ /dev/null @@ -1,162 +0,0 @@ -#include "ModularityVertexPartition.h" - -#ifdef DEBUG -#include -using std::cerr; -using std::endl; -#endif - -ModularityVertexPartition::ModularityVertexPartition(Graph* graph, - vector const& membership) : - MutableVertexPartition(graph, - membership) -{ } - -ModularityVertexPartition::ModularityVertexPartition(Graph* graph) : - MutableVertexPartition(graph) -{ } - -ModularityVertexPartition::~ModularityVertexPartition() -{ } - -ModularityVertexPartition* ModularityVertexPartition::create(Graph* graph) -{ - return new ModularityVertexPartition(graph); -} - -ModularityVertexPartition* ModularityVertexPartition::create(Graph* graph, vector const& membership) -{ - return new ModularityVertexPartition(graph, membership); -} - -/***************************************************************************** - Returns the difference in modularity if we move a node to a new community -*****************************************************************************/ -double ModularityVertexPartition::diff_move(size_t v, size_t new_comm) -{ - #ifdef DEBUG - cerr << "double ModularityVertexPartition::diff_move(" << v << ", " << new_comm << ")" << endl; - #endif - size_t old_comm = this->_membership[v]; - double diff = 0.0; - double total_weight = this->graph->total_weight()*(2.0 - this->graph->is_directed()); - if (total_weight == 0.0) - return 0.0; - if (new_comm != old_comm) - { - #ifdef DEBUG - cerr << "\t" << "old_comm: " << old_comm << endl; - #endif - double w_to_old = this->weight_to_comm(v, old_comm); - #ifdef DEBUG - cerr << "\t" << "w_to_old: " << w_to_old << endl; - #endif - double w_from_old = this->weight_from_comm(v, old_comm); - #ifdef DEBUG - cerr << "\t" << "w_from_old: " << w_from_old << endl; - #endif - double w_to_new = this->weight_to_comm(v, new_comm); - #ifdef DEBUG - cerr << "\t" << "w_to_new: " << w_to_new << endl; - #endif - double w_from_new = this->weight_from_comm(v, new_comm); - #ifdef DEBUG - cerr << "\t" << "w_from_new: " << w_from_new << endl; - #endif - double k_out = this->graph->strength(v, IGRAPH_OUT); - #ifdef DEBUG - cerr << "\t" << "k_out: " << k_out << endl; - #endif - double k_in = this->graph->strength(v, IGRAPH_IN); - #ifdef DEBUG - cerr << "\t" << "k_in: " << k_in << endl; - #endif - double self_weight = this->graph->node_self_weight(v); - #ifdef DEBUG - cerr << "\t" << "self_weight: " << self_weight << endl; - #endif - double K_out_old = this->total_weight_from_comm(old_comm); - #ifdef DEBUG - cerr << "\t" << "K_out_old: " << K_out_old << endl; - #endif - double K_in_old = this->total_weight_to_comm(old_comm); - #ifdef DEBUG - cerr << "\t" << "K_in_old: " << K_in_old << endl; - #endif - double K_out_new = this->total_weight_from_comm(new_comm) + k_out; - #ifdef DEBUG - cerr << "\t" << "K_out_new: " << K_out_new << endl; - #endif - double K_in_new = this->total_weight_to_comm(new_comm) + k_in; - #ifdef DEBUG - cerr << "\t" << "K_in_new: " << K_in_new << endl; - cerr << "\t" << "total_weight: " << total_weight << endl; - #endif - double diff_old = (w_to_old - k_out*K_in_old/total_weight) + \ - (w_from_old - k_in*K_out_old/total_weight); - #ifdef DEBUG - cerr << "\t" << "diff_old: " << diff_old << endl; - #endif - double diff_new = (w_to_new + self_weight - k_out*K_in_new/total_weight) + \ - (w_from_new + self_weight - k_in*K_out_new/total_weight); - #ifdef DEBUG - cerr << "\t" << "diff_new: " << diff_new << endl; - #endif - diff = diff_new - diff_old; - #ifdef DEBUG - cerr << "\t" << "diff: " << diff << endl; - #endif - } - #ifdef DEBUG - cerr << "exit double ModularityVertexPartition::diff_move((" << v << ", " << new_comm << ")" << endl; - cerr << "return " << diff << endl << endl; - #endif - double m; - if (this->graph->is_directed()) - m = this->graph->total_weight(); - else - m = 2*this->graph->total_weight(); - return diff/m; -} - - -/***************************************************************************** - Give the modularity of the partition. - - We here use the unscaled version of modularity, in other words, we don"t - normalise by the number of edges. -******************************************************************************/ -double ModularityVertexPartition::quality() -{ - #ifdef DEBUG - cerr << "double ModularityVertexPartition::quality()" << endl; - #endif - double mod = 0.0; -printf("Test Modularity Quality"); - double m; - if (this->graph->is_directed()) - m = this->graph->total_weight(); - else - m = 2*this->graph->total_weight(); - - if (m == 0) - return 0.0; - - for (size_t c = 0; c < this->n_communities(); c++) - { - double w = this->total_weight_in_comm(c); - double w_out = this->total_weight_from_comm(c); - double w_in = this->total_weight_to_comm(c); - #ifdef DEBUG - size_t csize = this->csize(c); - cerr << "\t" << "Comm: " << c << ", size=" << csize << ", w=" << w << ", w_out=" << w_out << ", w_in=" << w_in << "." << endl; - #endif - mod += w - w_out*w_in/((this->graph->is_directed() ? 1.0 : 4.0)*this->graph->total_weight()); - } - double q = (2.0 - this->graph->is_directed())*mod; - #ifdef DEBUG - cerr << "exit double ModularityVertexPartition::quality()" << endl; - cerr << "return " << q/m << endl << endl; - #endif - return q/m; -} diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/MutableVertexPartition.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/MutableVertexPartition.cpp deleted file mode 100644 index 0edf74d..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/MutableVertexPartition.cpp +++ /dev/null @@ -1,918 +0,0 @@ -#include "MutableVertexPartition.h" - -#ifdef DEBUG - using std::cerr; - using std::endl; -#endif - -/**************************************************************************** - Create a new vertex partition. - - Parameters: - graph -- The igraph.Graph on which this partition is defined. - membership=None -- The membership vector of this partition, i.e. an - community number for each node. So membership[i] = c - implies that node i is in community c. If None, it is - initialised with each node in its own community. - weight_attr=None -- What edge attribute should be used as a weight for the - edges? If None, the weight defaults to 1. - size_attr=None -- What node attribute should be used for keeping track - of the size of the node? In some methods (e.g. CPM or - Significance), we need to keep track of the total - size of the community. So when we aggregate/collapse - the graph, we should know how many nodes were in a - community. If None, the size of a node defaults to 1. - self_weight_attr=None - -- What node attribute should be used for the self - weight? If None, the self_weight is - recalculated each time.""" -*****************************************************************************/ - -MutableVertexPartition::MutableVertexPartition(Graph* graph, - vector const& membership) -{ - this->destructor_delete_graph = false; - this->graph = graph; - if (membership.size() != graph->vcount()) - { - throw Exception("Membership vector has incorrect size."); - } - this->_membership = membership; - this->init_admin(); -} - -MutableVertexPartition::MutableVertexPartition(Graph* graph) -{ - this->destructor_delete_graph = false; - this->graph = graph; - this->_membership = range(graph->vcount()); - this->init_admin(); -} - -MutableVertexPartition* MutableVertexPartition::create(Graph* graph) -{ - return new MutableVertexPartition(graph); -} - -MutableVertexPartition* MutableVertexPartition::create(Graph* graph, vector const& membership) -{ - return new MutableVertexPartition(graph, membership); -} - - -MutableVertexPartition::~MutableVertexPartition() -{ - this->clean_mem(); - if (this->destructor_delete_graph) - delete this->graph; -} - -void MutableVertexPartition::clean_mem() -{ - -} - -size_t MutableVertexPartition::csize(size_t comm) -{ - if (comm < this->_csize.size()) - return this->_csize[comm]; - else - return 0; -} - -size_t MutableVertexPartition::cnodes(size_t comm) -{ - if (comm < this->_cnodes.size()) - return this->_cnodes[comm]; - else - return 0; -} - -vector MutableVertexPartition::get_community(size_t comm) -{ - vector community; - community.reserve(this->_cnodes[comm]); - for (size_t i = 0; i < this->graph->vcount(); i++) - if (this->_membership[i] == comm) - community.push_back(i); - return community; -} - -vector< vector > MutableVertexPartition::get_communities() -{ - vector< vector > communities(this->_n_communities); - - for (size_t c = 0; c < this->_n_communities; c++) - { - size_t cn = this->_cnodes[c]; - communities[c].reserve(cn); - } - - for (size_t i = 0; i < this->graph->vcount(); i++) - communities[this->_membership[i]].push_back(i); - - return communities; -} - -size_t MutableVertexPartition::n_communities() -{ - return this->_n_communities; -} - -/**************************************************************************** - Initialise all the administration based on the membership vector. -*****************************************************************************/ - -void MutableVertexPartition::init_admin() -{ - #ifdef DEBUG - cerr << "void MutableVertexPartition::init_admin()" << endl; - #endif - size_t n = this->graph->vcount(); - - // First determine number of communities (assuming they are consecutively numbered - this->update_n_communities(); - - // Reset administration - this->_total_weight_in_comm.clear(); - this->_total_weight_in_comm.resize(this->_n_communities); - this->_total_weight_from_comm.clear(); - this->_total_weight_from_comm.resize(this->_n_communities); - this->_total_weight_to_comm.clear(); - this->_total_weight_to_comm.resize(this->_n_communities); - this->_csize.clear(); - this->_csize.resize(this->_n_communities); - this->_cnodes.clear(); - this->_cnodes.resize(this->_n_communities); - - this->_current_node_cache_community_from = n + 1; this->_cached_weight_from_community.resize(this->_n_communities, 0); - this->_current_node_cache_community_to = n + 1; this->_cached_weight_to_community.resize(this->_n_communities, 0); - this->_current_node_cache_community_all = n + 1; this->_cached_weight_all_community.resize(this->_n_communities, 0); - this->_cached_neigh_comms_all.resize(n); - - if (this->get_graph()->is_directed()) { - this->_cached_neigh_comms_from.resize(n); - this->_cached_neigh_comms_to.resize(n); - } - - this->_empty_communities.clear(); - - this->_total_weight_in_all_comms = 0.0; - for (size_t v = 0; v < n; v++) - { - size_t v_comm = this->_membership[v]; - // Update the community size - this->_csize[v_comm] += this->graph->node_size(v); - // Update the community size - this->_cnodes[v_comm] += 1; - } - - size_t m = graph->ecount(); - for (size_t e = 0; e < m; e++) - { - size_t v, u; - this->graph->edge(e, v, u); - - size_t v_comm = this->_membership[v]; - size_t u_comm = this->_membership[u]; - - // Get the weight of the edge - double w = this->graph->edge_weight(e); - // Add weight to the outgoing weight of community of v - this->_total_weight_from_comm[v_comm] += w; - #ifdef DEBUG - cerr << "\t" << "Add (" << v << ", " << u << ") weight " << w << " to from_comm " << v_comm << "." << endl; - #endif - // Add weight to the incoming weight of community of u - this->_total_weight_to_comm[u_comm] += w; - #ifdef DEBUG - cerr << "\t" << "Add (" << v << ", " << u << ") weight " << w << " to to_comm " << u_comm << "." << endl; - #endif - if (!this->graph->is_directed()) - { - #ifdef DEBUG - cerr << "\t" << "Add (" << u << ", " << v << ") weight " << w << " to from_comm " << u_comm << "." << endl; - #endif - this->_total_weight_from_comm[u_comm] += w; - #ifdef DEBUG - cerr << "\t" << "Add (" << u << ", " << v << ") weight " << w << " to to_comm " << v_comm << "." << endl; - #endif - this->_total_weight_to_comm[v_comm] += w; - } - // If it is an edge within a community - if (v_comm == u_comm) - { - this->_total_weight_in_comm[v_comm] += w; - this->_total_weight_in_all_comms += w; - #ifdef DEBUG - cerr << "\t" << "Add (" << v << ", " << u << ") weight " << w << " to in_comm " << v_comm << "." << endl; - #endif - } - } - - this->_total_possible_edges_in_all_comms = 0; - for (size_t c = 0; c < this->_n_communities; c++) - { - size_t n_c = this->csize(c); - size_t possible_edges = this->graph->possible_edges(n_c); - - #ifdef DEBUG - cerr << "\t" << "c=" << c << ", n_c=" << n_c << ", possible_edges=" << possible_edges << endl; - #endif - - this->_total_possible_edges_in_all_comms += possible_edges; - - // It is possible that some community have a zero size (if the order - // is for example not consecutive. We add those communities to the empty - // communities vector for consistency. - if (this->_cnodes[c] == 0) - this->_empty_communities.push_back(c); - } - - #ifdef DEBUG - cerr << "exit MutableVertexPartition::init_admin()" << endl << endl; - #endif - -} - -void MutableVertexPartition::update_n_communities() -{ - this->_n_communities = 0; - for (size_t i = 0; i < this->graph->vcount(); i++) - if (this->_membership[i] >= this->_n_communities) - this->_n_communities = this->_membership[i] + 1; -} - -/**************************************************************************** - Renumber the communities so that they are numbered 0,...,q-1 where q is - the number of communities. This also removes any empty communities, as they - will not be given a new number. -*****************************************************************************/ -void MutableVertexPartition::renumber_communities() -{ - vector partitions(1); - partitions[0] = this; - vector new_comm_id = MutableVertexPartition::rank_order_communities(partitions); - this->relabel_communities(new_comm_id); -} - -/**************************************************************************** - Renumber the communities according to the new labels in new_comm_id. - - This adjusts the internal bookkeeping as required, avoiding the more costly - setup required in init_admin(). In particular, this avoids recomputation of - weights in/from/to each community by simply assigning the previously - computed values to the new, relabeled communities. - - For instance, a new_comm_id of <1, 2, 0> will change the labels such that - community 0 becomes 1, community 1 becomes 2, and community 2 becomes 0. -*****************************************************************************/ -void MutableVertexPartition::relabel_communities(vector const& new_comm_id) { - if (this->_n_communities != new_comm_id.size()) { - throw Exception("Problem swapping community labels. Mismatch between n_communities and new_comm_id vector."); - } - - size_t n = this->graph->vcount(); - - for (size_t i = 0; i < n; i++) - this->_membership[i] = new_comm_id[this->_membership[i]]; - - this->update_n_communities(); - size_t nbcomms = this->n_communities(); - - vector new_total_weight_in_comm(nbcomms, 0.0); - vector new_total_weight_from_comm(nbcomms, 0.0); - vector new_total_weight_to_comm(nbcomms, 0.0); - vector new_csize(nbcomms, 0); - vector new_cnodes(nbcomms, 0); - - // Relabel community admin - for (size_t c = 0; c < new_comm_id.size(); c++) { - size_t new_c = new_comm_id[c]; - if (this->_cnodes[c] > 0) { - new_total_weight_in_comm[new_c] = this->_total_weight_in_comm[c]; - new_total_weight_from_comm[new_c] = this->_total_weight_from_comm[c]; - new_total_weight_to_comm[new_c] = this->_total_weight_to_comm[c]; - new_csize[new_c] = this->_csize[c]; - new_cnodes[new_c] = this->_cnodes[c]; - } - } - - this->_total_weight_in_comm = new_total_weight_in_comm; - this->_total_weight_from_comm = new_total_weight_from_comm; - this->_total_weight_to_comm = new_total_weight_to_comm; - this->_csize = new_csize; - this->_cnodes = new_cnodes; - - this->_empty_communities.clear(); - for (size_t c = 0; c < nbcomms; c++) { - if (this->_cnodes[c] == 0) { - this->_empty_communities.push_back(c); - } - } - - // invalidate cached weight vectors - for (size_t c : this->_cached_neigh_comms_from) - this->_cached_weight_from_community[c] = 0; - this->_cached_neigh_comms_from.clear(); - this->_cached_weight_from_community.resize(nbcomms, 0); - this->_current_node_cache_community_from = n + 1; - - for (size_t c : this->_cached_neigh_comms_to) - this->_cached_weight_to_community[c] = 0; - this->_cached_neigh_comms_to.clear(); - this->_cached_weight_to_community.resize(nbcomms, 0); - this->_current_node_cache_community_to = n + 1; - - for (size_t c : this->_cached_neigh_comms_all) - this->_cached_weight_all_community[c] = 0; - this->_cached_neigh_comms_all.clear(); - this->_cached_weight_all_community.resize(nbcomms, 0); - this->_current_node_cache_community_all = n + 1; - - #ifdef DEBUG - if (this->_csize.size() < this->_n_communities || - this->_cnodes.size() < this->_n_communities || - this->_total_weight_in_comm.size() < this->_n_communities || - this->_total_weight_to_comm.size() < this->_n_communities || - this->_total_weight_from_comm.size() < this->_n_communities || - this->_cached_weight_from_community.size() < this->_n_communities || - this->_cached_weight_to_community.size() < this->_n_communities || - this->_cached_weight_all_community.size() < this->_n_communities) { - cerr << "ERROR: MutableVertexPartition bookkeeping is too small after rearrange_community_labels." << endl; - } - - this->init_admin(); - - for (size_t c = 0; c < this->_n_communities; c++) { - if (fabs(new_total_weight_in_comm[c] - this->_total_weight_in_comm[c]) > 1e-6 || - fabs(new_total_weight_from_comm[c] - this->_total_weight_from_comm[c]) > 1e-6 || - fabs(new_total_weight_to_comm[c] - this->_total_weight_to_comm[c]) > 1e-6 || - new_csize[c] != this->_csize[c] || - new_cnodes[c] != this->_cnodes[c]) { - cerr << "ERROR: MutableVertexPartition bookkeeping is incorrect after rearrange_community_labels." << endl; - cerr << "Community c has " << endl - << "total_weight_in_comm=" << new_total_weight_in_comm[c] - << " (should be " << this->_total_weight_in_comm[c] << ")" << endl - << "total_weight_from_comm=" << new_total_weight_from_comm[c] - << " (should be " << this->_total_weight_from_comm[c] << ")" << endl - << "total_weight_to_comm=" << new_total_weight_to_comm[c] - << " (should be " << this->_total_weight_to_comm[c] << ")" << endl - << "csize=" << new_csize[c] - << " (should be " << this->_csize[c] << ")" << endl - << "cnodes=" << new_cnodes[c] - << " (should be " << this->_cnodes[c] << ")" << endl; - } - } - #endif -} - -vector MutableVertexPartition::rank_order_communities(vector partitions) -{ - size_t nb_layers = partitions.size(); - size_t nb_comms = partitions[0]->n_communities(); - - #ifdef DEBUG - size_t n = partitions[0]->graph->vcount(); - for (size_t layer = 0; layer < nb_layers; layer++) - { - for (size_t v = 0; v < n; v++) - { - if (partitions[0]->membership(v) != partitions[layer]->membership(v)) - cerr << "Membership of all partitions are not equal"; - } - } - #endif - // First sort the communities by size - // Csizes - // first - community - // second - csize - // third - number of nodes (may be aggregate nodes), to account for communities with zero weight. - vector csizes; - for (size_t i = 0; i < nb_comms; i++) - { - size_t csize = 0; - for (size_t layer = 0; layer < nb_layers; layer++) - csize += partitions[layer]->csize(i); - - size_t* row = new size_t[3]; - row[0] = i; - row[1] = csize; - row[2] = partitions[0]->cnodes(i); - csizes.push_back(row); - } - sort(csizes.begin(), csizes.end(), orderCSize); - - // Then use the sort order to assign new communities, - // such that the largest community gets the lowest index. - vector new_comm_id(nb_comms, 0); - for (size_t i = 0; i < nb_comms; i++) - { - size_t comm = csizes[i][0]; - new_comm_id[comm] = i; - delete[] csizes[i]; - } - - return new_comm_id; -} - - -/**************************************************************************** - Renumber the communities using the original fixed membership vector. Notice - that this doesn't ensure any property of the community numbers. -*****************************************************************************/ -void MutableVertexPartition::renumber_communities(vector const& fixed_nodes, vector const& fixed_membership) -{ - - #ifdef DEBUG - cerr << "void MutableVertexPartition::renumber_communities(" << &fixed_nodes << ", " << &fixed_membership << ")" << endl; - #endif - - // Skip whole thing if there are no fixed nodes for efficiency - if (fixed_nodes.size() == 0) - return; - - // The number of communities does not depend on whether some are fixed - size_t nb_comms = n_communities(); - - // Fill the community map with the original communities - vector new_comm_id(nb_comms); - vector comm_assigned_bool(nb_comms); - priority_queue, std::greater > new_comm_assigned; - for (size_t v : fixed_nodes) { - if (!comm_assigned_bool[_membership[v]]) - { - size_t fixed_comm_v = fixed_membership[v]; - #ifdef DEBUG - cerr << "Setting map for fixed community " << fixed_comm_v << endl; - #endif - new_comm_id[_membership[v]] = fixed_comm_v; - comm_assigned_bool[_membership[v]] = true; - new_comm_assigned.push(fixed_comm_v); - } - } - - // Index of the most recently added community - size_t cc = 0; - for (size_t c = 0; c != nb_comms; c++) { - if(!comm_assigned_bool[c]) { - // Look for the first free integer - while (!new_comm_assigned.empty() && cc == new_comm_assigned.top()) - { - new_comm_assigned.pop(); - cc++; - } - // Assign the community - #ifdef DEBUG - cerr << "Setting map for free community " << cc << endl; - #endif - new_comm_id[c] = cc++; - } - } - - this->relabel_communities(new_comm_id); -} - -void MutableVertexPartition::renumber_communities(vector const& membership) -{ - cerr << "This function is deprecated, use MutableVertexPartition::set_membership(vector const& membership)" << endl; - this->set_membership(membership); -} - -size_t MutableVertexPartition::get_empty_community() -{ - if (this->_empty_communities.empty()) - { - // If there was no empty community yet, - // we will create a new one. - add_empty_community(); - } - - return this->_empty_communities.back(); -} - -void MutableVertexPartition::set_membership(vector const& membership) -{ - #ifdef DEBUG - cerr << "void MutableVertexPartition::set_membership(" << &membership << ")" << endl; - #endif - this->_membership = membership; - - this->clean_mem(); - this->init_admin(); - #ifdef DEBUG - cerr << "exit MutableVertexPartition::set_membership(" << &membership << ")" << endl; - #endif -} - -size_t MutableVertexPartition::add_empty_community() -{ - this->_n_communities = this->_n_communities + 1; - - if (this->_n_communities > this->graph->vcount()) - throw Exception("There cannot be more communities than nodes, so there must already be an empty community."); - - size_t new_comm = this->_n_communities - 1; - - this->_csize.resize(this->_n_communities); this->_csize[new_comm] = 0; - this->_cnodes.resize(this->_n_communities); this->_cnodes[new_comm] = 0; - this->_total_weight_in_comm.resize(this->_n_communities); this->_total_weight_in_comm[new_comm] = 0; - this->_total_weight_from_comm.resize(this->_n_communities); this->_total_weight_from_comm[new_comm] = 0; - this->_total_weight_to_comm.resize(this->_n_communities); this->_total_weight_to_comm[new_comm] = 0; - - this->_cached_weight_all_community.resize(this->_n_communities); - this->_cached_weight_from_community.resize(this->_n_communities); - this->_cached_weight_to_community.resize(this->_n_communities); - - this->_empty_communities.push_back(new_comm); - #ifdef DEBUG - cerr << "Added empty community " << new_comm << endl; - #endif - return new_comm; -} - -/**************************************************************************** - Move a node to a new community and update the administration. - Parameters: - v -- Node to move. - new_comm -- To which community should it move. -*****************************************************************************/ -void MutableVertexPartition::move_node(size_t v,size_t new_comm) -{ - #ifdef DEBUG - cerr << "void MutableVertexPartition::move_node(" << v << ", " << new_comm << ")" << endl; - if (new_comm >= this->n_communities()) - cerr << "ERROR: New community (" << new_comm << ") larger than total number of communities (" << this->n_communities() << ")." << endl; - #endif - // Move node and update internal administration - if (new_comm >= this->_n_communities) - { - if (new_comm < this->graph->vcount()) - { - while (new_comm >= this->_n_communities) - this->add_empty_community(); - } - else - { - throw Exception("Cannot add new communities beyond the number of nodes."); - } - } - - // Keep track of all possible edges in all communities; - size_t node_size = this->graph->node_size(v); - size_t old_comm = this->_membership[v]; - #ifdef DEBUG - cerr << "Node size: " << node_size << ", old comm: " << old_comm << ", new comm: " << new_comm << endl; - #endif - // Incidentally, this is independent of whether we take into account self-loops or not - // (i.e. whether we count as n_c^2 or as n_c(n_c - 1). Be careful to do this before the - // adaptation of the community sizes, otherwise the calculations are incorrect. - if (new_comm != old_comm) - { - double delta_possible_edges_in_comms = 2.0*node_size*(ptrdiff_t)(this->_csize[new_comm] - this->_csize[old_comm] + node_size)/(2.0 - this->graph->is_directed()); - _total_possible_edges_in_all_comms += delta_possible_edges_in_comms; - #ifdef DEBUG - cerr << "Change in possible edges in all comms: " << delta_possible_edges_in_comms << endl; - #endif - } - - // Remove from old community - #ifdef DEBUG - cerr << "Removing from old community " << old_comm << ", community size: " << this->_csize[old_comm] << endl; - #endif - this->_cnodes[old_comm] -= 1; - this->_csize[old_comm] -= node_size; - #ifdef DEBUG - cerr << "Removed from old community." << endl; - #endif - - // We have to use the size of the set of nodes rather than the csize - // to account for nodes that have a zero size (i.e. community may not be empty, but - // may have zero size). - if (this->_cnodes[old_comm] == 0) - { - #ifdef DEBUG - cerr << "Adding community " << old_comm << " to empty communities." << endl; - #endif - this->_empty_communities.push_back(old_comm); - #ifdef DEBUG - cerr << "Added community " << old_comm << " to empty communities." << endl; - #endif - } - - if (this->_cnodes[new_comm] == 0) - { - #ifdef DEBUG - cerr << "Removing from empty communities (number of empty communities is " << this->_empty_communities.size() << ")." << endl; - #endif - vector::reverse_iterator it_comm = this->_empty_communities.rbegin(); - while (it_comm != this->_empty_communities.rend() && *it_comm != new_comm) - { - #ifdef DEBUG - cerr << "Empty community " << *it_comm << " != new community " << new_comm << endl; - #endif - it_comm++; - } - #ifdef DEBUG - cerr << "Erasing empty community " << *it_comm << endl; - if (it_comm == this->_empty_communities.rend()) - cerr << "ERROR: empty community does not exist." << endl; - #endif - if (it_comm != this->_empty_communities.rend()) - this->_empty_communities.erase( (++it_comm).base() ); - } - - #ifdef DEBUG - cerr << "Adding to new community " << new_comm << ", community size: " << this->_csize[new_comm] << endl; - #endif - // Add to new community - this->_cnodes[new_comm] += 1; - this->_csize[new_comm] += this->graph->node_size(v); - - // Switch outgoing links - #ifdef DEBUG - cerr << "Added to new community." << endl; - #endif - - // Use set for incident edges, because self loop appears twice - igraph_neimode_t modes[2] = {IGRAPH_OUT, IGRAPH_IN}; - for (size_t mode_i = 0; mode_i < 2; mode_i++) - { - igraph_neimode_t mode = modes[mode_i]; - - // Loop over all incident edges - vector const& neighbours = this->graph->get_neighbours(v, mode); - vector const& neighbour_edges = this->graph->get_neighbour_edges(v, mode); - - size_t degree = neighbours.size(); - - #ifdef DEBUG - if (mode == IGRAPH_OUT) - cerr << "\t" << "Looping over outgoing links." << endl; - else if (mode == IGRAPH_IN) - cerr << "\t" << "Looping over incoming links." << endl; - else - cerr << "\t" << "Looping over unknown mode." << endl; - #endif - - for (size_t idx = 0; idx < degree; idx++) - { - size_t u = neighbours[idx]; - size_t e = neighbour_edges[idx]; - - size_t u_comm = this->_membership[u]; - // Get the weight of the edge - double w = this->graph->edge_weight(e); - if (mode == IGRAPH_OUT) - { - // Remove the weight from the outgoing weights of the old community - this->_total_weight_from_comm[old_comm] -= w; - // Add the weight to the outgoing weights of the new community - this->_total_weight_from_comm[new_comm] += w; - #ifdef DEBUG - cerr << "\t" << "Moving link (" << v << "-" << u << ") " - << "outgoing weight " << w - << " from " << old_comm << " to " << new_comm - << "." << endl; - #endif - } - else if (mode == IGRAPH_IN) - { - // Remove the weight from the outgoing weights of the old community - this->_total_weight_to_comm[old_comm] -= w; - // Add the weight to the outgoing weights of the new community - this->_total_weight_to_comm[new_comm] += w; - #ifdef DEBUG - cerr << "\t" << "Moving link (" << v << "-" << u << ") " - << "incoming weight " << w - << " from " << old_comm << " to " << new_comm - << "." << endl; - #endif - } - else - throw Exception("Incorrect mode for updating the admin."); - // Get internal weight (if it is an internal edge) - double int_weight = w/(this->graph->is_directed() ? 1.0 : 2.0)/( u == v ? 2.0 : 1.0); - // If it is an internal edge in the old community - if (old_comm == u_comm) - { - // Remove the internal weight - this->_total_weight_in_comm[old_comm] -= int_weight; - this->_total_weight_in_all_comms -= int_weight; - #ifdef DEBUG - cerr << "\t" << "From link (" << v << "-" << u << ") " - << "remove internal weight " << int_weight - << " from " << old_comm << "." << endl; - #endif - } - // If it is an internal edge in the new community - // i.e. if u is in the new community, or if it is a self loop - if ((new_comm == u_comm) || (u == v)) - { - // Add the internal weight - this->_total_weight_in_comm[new_comm] += int_weight; - this->_total_weight_in_all_comms += int_weight; - #ifdef DEBUG - cerr << "\t" << "From link (" << v << "-" << u << ") " - << "add internal weight " << int_weight - << " to " << new_comm << "." << endl; - #endif - } - } - } - #ifdef DEBUG - // Check this->_total_weight_in_all_comms - double check_total_weight_in_all_comms = 0.0; - for (size_t c = 0; c < this->n_communities(); c++) - check_total_weight_in_all_comms += this->total_weight_in_comm(c); - cerr << "Internal _total_weight_in_all_comms=" << this->_total_weight_in_all_comms - << ", calculated check_total_weight_in_all_comms=" << check_total_weight_in_all_comms << endl; - #endif - // Update the membership vector - this->_membership[v] = new_comm; - #ifdef DEBUG - cerr << "exit MutableVertexPartition::move_node(" << v << ", " << new_comm << ")" << endl << endl; - #endif -} - - -/**************************************************************************** - Read new communities from coarser partition assuming that the community - represents a node in the coarser partition (with the same index as the - community number). -****************************************************************************/ -void MutableVertexPartition::from_coarse_partition(vector const& coarse_partition_membership) -{ - this->from_coarse_partition(coarse_partition_membership, this->_membership); -} - -void MutableVertexPartition::from_coarse_partition(MutableVertexPartition* coarse_partition) -{ - this->from_coarse_partition(coarse_partition, this->_membership); -} - -void MutableVertexPartition::from_coarse_partition(MutableVertexPartition* coarse_partition, vector const& coarse_node) -{ - this->from_coarse_partition(coarse_partition->membership(), coarse_node); -} - -/**************************************************************************** - Set the current community of all nodes to the community specified in the partition - assuming that the coarser partition is created using the membership as specified - by coarser_membership. In other words node i becomes node coarse_node[i] in - the coarser partition and thus has community coarse_partition_membership[coarse_node[i]]. -****************************************************************************/ -void MutableVertexPartition::from_coarse_partition(vector const& coarse_partition_membership, vector const& coarse_node) -{ - // Read the coarser partition - for (size_t v = 0; v < this->graph->vcount(); v++) - { - // In the coarser partition, the node should have the community id - // as represented by the coarser_membership vector - size_t v_level2 = coarse_node[v]; - - // In the coarser partition, this node is represented by v_level2 - size_t v_comm_level2 = coarse_partition_membership[v_level2]; - - // Set local membership to community found for node at second level - this->_membership[v] = v_comm_level2; - } - - this->clean_mem(); - this->init_admin(); -} - - -/**************************************************************************** - Read new partition from another partition. -****************************************************************************/ -void MutableVertexPartition::from_partition(MutableVertexPartition* partition) -{ - // Assign the membership of every node in the supplied partition - // to the one in this partition - for (size_t v = 0; v < this->graph->vcount(); v++) - this->_membership[v] = partition->membership(v); - this->clean_mem(); - this->init_admin(); -} - -void MutableVertexPartition::cache_neigh_communities(size_t v, igraph_neimode_t mode) -{ - // TODO: We can probably calculate at once the IN, OUT and ALL - // rather than this being called multiple times. - - // Weight between vertex and community - #ifdef DEBUG - cerr << "double MutableVertexPartition::cache_neigh_communities(" << v << ", " << mode << ")." << endl; - #endif - vector* _cached_weight_tofrom_community = NULL; - vector* _cached_neighs_comms = NULL; - switch (mode) - { - case IGRAPH_IN: - _cached_weight_tofrom_community = &(this->_cached_weight_from_community); - _cached_neighs_comms = &(this->_cached_neigh_comms_from); - break; - case IGRAPH_OUT: - _cached_weight_tofrom_community = &(this->_cached_weight_to_community); - _cached_neighs_comms = &(this->_cached_neigh_comms_to); - break; - case IGRAPH_ALL: - _cached_weight_tofrom_community = &(this->_cached_weight_all_community); - _cached_neighs_comms = &(this->_cached_neigh_comms_all); - break; - } - - // Reset cached communities - for (size_t c : *_cached_neighs_comms) - (*_cached_weight_tofrom_community)[c] = 0; - - // Loop over all incident edges - vector const& neighbours = this->graph->get_neighbours(v, mode); - vector const& neighbour_edges = this->graph->get_neighbour_edges(v, mode); - - size_t degree = neighbours.size(); - - // Reset cached neighbours - _cached_neighs_comms->clear(); - for (size_t idx = 0; idx < degree; idx++) - { - size_t u = neighbours[idx]; - size_t e = neighbour_edges[idx]; - - // If it is an edge to the requested community - #ifdef DEBUG - size_t v_comm = this->_membership[v]; - #endif - size_t comm = this->_membership[u]; - // Get the weight of the edge - double w = this->graph->edge_weight(e); - // Self loops appear twice here if the graph is undirected, so divide by 2.0 in that case. - if (u == v && !this->graph->is_directed()) - w /= 2.0; - #ifdef DEBUG - cerr << "\t" << "Edge (" << v << "-" << u << "), Comm (" << v_comm << "-" << comm << ") weight: " << w << "." << endl; - #endif - (*_cached_weight_tofrom_community)[comm] += w; - // REMARK: Notice in the rare case of negative weights, being exactly equal - // for a certain community, that this community may then potentially be added multiple - // times to the _cached_neighs. However, I don' believe this causes any further issue, - // so that's why I leave this here as is. - if ((*_cached_weight_tofrom_community)[comm] != 0) - _cached_neighs_comms->push_back(comm); - } - #ifdef DEBUG - cerr << "exit Graph::cache_neigh_communities(" << v << ", " << mode << ")." << endl; - #endif -} - -vector const& MutableVertexPartition::get_neigh_comms(size_t v, igraph_neimode_t mode) -{ - if (!this->get_graph()->is_directed()) - mode = IGRAPH_ALL; // igraph ignores mode for undirected graphs - - switch (mode) - { - case IGRAPH_IN: - if (this->_current_node_cache_community_from != v) - { - cache_neigh_communities(v, mode); - this->_current_node_cache_community_from = v; - } - return this->_cached_neigh_comms_from; - case IGRAPH_OUT: - if (this->_current_node_cache_community_to != v) - { - cache_neigh_communities(v, mode); - this->_current_node_cache_community_to = v; - } - return this->_cached_neigh_comms_to; - case IGRAPH_ALL: - if (this->_current_node_cache_community_all != v) - { - cache_neigh_communities(v, mode); - this->_current_node_cache_community_all = v; - } - return this->_cached_neigh_comms_all; - } - throw Exception("Problem obtaining neighbour communities, invalid mode."); -} - -vector MutableVertexPartition::get_neigh_comms(size_t v, igraph_neimode_t mode, vector const& constrained_membership) -{ - vector neigh_comms; - vector comm_added(this->n_communities(), false); - for (size_t u : this->graph->get_neighbours(v, mode)) - { - if (constrained_membership[v] == constrained_membership[u]) - { - size_t comm = this->membership(u); - if (!comm_added[comm]) - { - neigh_comms.push_back(comm); - comm_added[comm]; - } - } - } - return neigh_comms; -} diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/Optimiser.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/Optimiser.cpp deleted file mode 100644 index 9ac1eb2..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/Optimiser.cpp +++ /dev/null @@ -1,1446 +0,0 @@ -#include "Optimiser.h" - -/**************************************************************************** - Create a new Optimiser object - - Be sure to call - - igraph_i_set_attribute_table(&igraph_cattribute_table); - - before using this package, otherwise the attribute handling - will not be dealt with correctly. - - Parameters: - consider_comms - -- Consider communities in a specific manner: - ALL_COMMS -- Consider all communities for improvement. - ALL_NEIGH_COMMS -- Consider all neighbour communities for - improvement. - RAND_COMM -- Consider a random commmunity for improvement. - RAND_NEIGH_COMM -- Consider a random community among the neighbours - for improvement. -****************************************************************************/ -Optimiser::Optimiser() -{ - this->consider_comms = Optimiser::ALL_NEIGH_COMMS; - this->optimise_routine = Optimiser::MOVE_NODES; - this->refine_consider_comms = Optimiser::ALL_NEIGH_COMMS; - this->refine_routine = Optimiser::MERGE_NODES; - this->refine_partition = true; - this->consider_empty_community = true; - this->max_comm_size = 0; - - igraph_rng_init(&rng, &igraph_rngtype_mt19937); - igraph_rng_seed(&rng, time(NULL)); - - igraph_set_attribute_table(&igraph_cattribute_table); -} - -Optimiser::~Optimiser() -{ - igraph_rng_destroy(&rng); -} - -void Optimiser::print_settings() -{ - cerr << "Consider communities method:\t" << this->consider_comms << endl; - cerr << "Refine partition:\t" << this->refine_partition << endl; -} - -/***************************************************************************** - optimise the provided partition. -*****************************************************************************/ -double Optimiser::optimise_partition(MutableVertexPartition* partition) -{ - size_t n = partition->get_graph()->vcount(); - vector is_membership_fixed(n, false); - return this->optimise_partition(partition, is_membership_fixed); -} - -double Optimiser::optimise_partition(MutableVertexPartition* partition, vector const& is_membership_fixed) -{ - return this->optimise_partition(partition, is_membership_fixed, this->max_comm_size); -} - -double Optimiser::optimise_partition(MutableVertexPartition* partition, vector const& is_membership_fixed, size_t max_comm_size) -{ - vector partitions(1); - partitions[0] = partition; - vector layer_weights(1, 1.0); - return this->optimise_partition(partitions, layer_weights, is_membership_fixed, max_comm_size); -} - -double Optimiser::optimise_partition(vector partitions, vector layer_weights, vector const& is_membership_fixed) -{ - return this->optimise_partition(partitions, layer_weights, is_membership_fixed, this->max_comm_size); -} - -/***************************************************************************** - optimise the providede partitions simultaneously. We here use the sum - of the difference of the moves as the overall quality function, each partition - weighted by the layer weight. -*****************************************************************************/ -/***************************************************************************** - optimise the provided partition. -*****************************************************************************/ -double Optimiser::optimise_partition(vector partitions, vector layer_weights, vector const& is_membership_fixed, size_t max_comm_size) -{ - #ifdef DEBUG - cerr << "void Optimiser::optimise_partition(vector partitions, vector layer_weights, vector const& is_membership_fixed, size_t max_comm_size)" << endl; - #endif - - double q = 0.0; - - // Number of multiplex layers - size_t nb_layers = partitions.size(); - if (nb_layers == 0) - throw Exception("No partitions provided."); - - // Get graphs for all layers - vector graphs(nb_layers); - for (size_t layer = 0; layer < nb_layers; layer++) - graphs[layer] = partitions[layer]->get_graph(); - - // Number of nodes in the graphs. Should be the same across - // all graphs, so we only take the first one. - size_t n = graphs[0]->vcount(); - - // Make sure that all graphs contain the exact same number of nodes. - // We assume the index of each vertex in the graph points to the - // same node (but then in a different layer). - for (Graph* graph : graphs) - if (graph->vcount() != n) - throw Exception("Number of nodes are not equal for all graphs."); - - // Get the fixed membership for fixed nodes - vector fixed_nodes; - vector fixed_membership(n); - for (size_t v = 0; v < n; v++) { - if (is_membership_fixed[v]) { - fixed_nodes.push_back(v); - fixed_membership[v] = partitions[0]->membership(v); - } - } - - // Initialize the vector of the collapsed graphs for all layers - vector collapsed_graphs(nb_layers); - vector collapsed_partitions(nb_layers); - - // Declare the collapsed_graph variable which will contain the graph - // collapsed by its communities. We will use this variables at each - // further iteration, so we don't keep a collapsed graph at each pass. - for (size_t layer = 0; layer < nb_layers; layer++) - { - collapsed_graphs[layer] = graphs[layer]; - collapsed_partitions[layer] = partitions[layer]; - } - - // Declare which nodes in the collapsed graph are fixed, which to start is - // simply equal to is_membership_fixed - vector is_collapsed_membership_fixed(is_membership_fixed); - - // This reflects the aggregate node, which to start with is simply equal to the graph. - vector aggregate_node_per_individual_node = range(n); - bool aggregate_further = true; - // As long as there remains improvement iterate - double improv = 0.0; - do - { - - // Optimise partition for collapsed graph - #ifdef DEBUG - q = 0.0; - for (size_t layer = 0; layer < nb_layers; layer++) - q += partitions[layer]->quality()*layer_weights[layer]; - cerr << "Quality before moving " << q << endl; - #endif - if (this->optimise_routine == Optimiser::MOVE_NODES) - improv += this->move_nodes(collapsed_partitions, layer_weights, is_collapsed_membership_fixed, this->consider_comms, this->consider_empty_community, false, max_comm_size); - - else if (this->optimise_routine == Optimiser::MERGE_NODES) - improv += this->merge_nodes(collapsed_partitions, layer_weights, is_collapsed_membership_fixed, this->consider_comms, false, max_comm_size); - - #ifdef DEBUG - cerr << "Found " << collapsed_partitions[0]->n_communities() << " communities, improved " << improv << endl; - q = 0.0; - for (size_t layer = 0; layer < nb_layers; layer++) - q += partitions[layer]->quality()*layer_weights[layer]; - cerr << "Quality after moving " << q << endl; - #endif // DEBUG - - // Make sure improvement on coarser scale is reflected on the - // scale of the graph as a whole. - for (size_t layer = 0; layer < nb_layers; layer++) - { - if (collapsed_partitions[layer] != partitions[layer]) - { - if (this->refine_partition) - partitions[layer]->from_coarse_partition(collapsed_partitions[layer], aggregate_node_per_individual_node); - else - partitions[layer]->from_coarse_partition(collapsed_partitions[layer]); - } - } - - #ifdef DEBUG - q = 0.0; - for (size_t layer = 0; layer < nb_layers; layer++) - q += partitions[layer]->quality()*layer_weights[layer]; - cerr << "Quality on finer partition " << q << endl; - #endif // DEBUG - - #ifdef DEBUG - cerr << "Number of communities: " << partitions[0]->n_communities() << endl; - #endif - - // Collapse graph (i.e. community graph) - // If we do refine the partition, we separate communities in slightly more - // fine-grained parts for which we collapse the graph. - vector sub_collapsed_partitions(nb_layers); - - vector new_collapsed_graphs(nb_layers); - vector new_collapsed_partitions(nb_layers); - - if (this->refine_partition) - { - // First create a new partition, which should be a sub partition - // of the collapsed partition, i.e. such that all clusters of - // the partition are strictly partitioned in the subpartition. - - #ifdef DEBUG - cerr << "\tBefore SLM " << collapsed_partitions[0]->n_communities() << " communities." << endl; - #endif - for (size_t layer = 0; layer < nb_layers; layer++) - { - sub_collapsed_partitions[layer] = collapsed_partitions[layer]->create(collapsed_graphs[layer]); - } - - // Then move around nodes but restrict movement to within original communities. - #ifdef DEBUG - cerr << "\tStarting refinement with " << sub_collapsed_partitions[0]->n_communities() << " communities." << endl; - #endif - if (this->refine_routine == Optimiser::MOVE_NODES) - this->move_nodes_constrained(sub_collapsed_partitions, layer_weights, refine_consider_comms, collapsed_partitions[0], max_comm_size); - else if (this->refine_routine == Optimiser::MERGE_NODES) - this->merge_nodes_constrained(sub_collapsed_partitions, layer_weights, refine_consider_comms, collapsed_partitions[0], max_comm_size); - #ifdef DEBUG - cerr << "\tAfter applying refinement found " << sub_collapsed_partitions[0]->n_communities() << " communities." << endl; - #endif - - // Determine new aggregate node per individual node - for (size_t v = 0; v < n; v++) - { - size_t aggregate_node = aggregate_node_per_individual_node[v]; - aggregate_node_per_individual_node[v] = sub_collapsed_partitions[0]->membership(aggregate_node); - } - - // Collapse graph based on sub collapsed partition - for (size_t layer = 0; layer < nb_layers; layer++) - { - new_collapsed_graphs[layer] = collapsed_graphs[layer]->collapse_graph(sub_collapsed_partitions[layer]); - } - - // Determine the membership for the collapsed graph - vector new_collapsed_membership(new_collapsed_graphs[0]->vcount()); - - // Every node within the collapsed graph should be assigned - // to the community of the original partition before the refinement. - // We thus check for each node what the community is in the refined partition - // and set the membership equal to the original partition (i.e. - // even though the aggregation may be slightly different, the - // membership of the aggregated nodes is as indicated by the original partition.) - #ifdef DEBUG - //cerr << "Refinement\tOrig" << endl; - #endif // DEBUG - for (size_t v = 0; v < collapsed_graphs[0]->vcount(); v++) - { - size_t new_aggregate_node = sub_collapsed_partitions[0]->membership(v); - new_collapsed_membership[new_aggregate_node] = collapsed_partitions[0]->membership(v); - #ifdef DEBUG - //cerr << sub_collapsed_partition->membership(v) << "\t" << sub_collapsed_partition->membership(v) << endl; - #endif // DEBUG - } - - // Determine which collapsed nodes are fixed - is_collapsed_membership_fixed.clear(); - is_collapsed_membership_fixed.resize(new_collapsed_graphs[0]->vcount(), false); - for (size_t v = 0; v < n; v++) - if (is_membership_fixed[v]) - is_collapsed_membership_fixed[aggregate_node_per_individual_node[v]] = true; - - // Create new collapsed partition - for (size_t layer = 0; layer < nb_layers; layer++) - { - delete sub_collapsed_partitions[layer]; - new_collapsed_partitions[layer] = collapsed_partitions[layer]->create(new_collapsed_graphs[layer], new_collapsed_membership); - } - } - else - { - for (size_t layer = 0; layer < nb_layers; layer++) - { - new_collapsed_graphs[layer] = collapsed_graphs[layer]->collapse_graph(collapsed_partitions[layer]); - // Create collapsed partition (i.e. default partition of each node in its own community). - new_collapsed_partitions[layer] = collapsed_partitions[layer]->create(new_collapsed_graphs[layer]); - #ifdef DEBUG - cerr << "Layer " << layer << endl; - cerr << "Old collapsed graph " << collapsed_graphs[layer] << ", vcount is " << collapsed_graphs[layer]->vcount() << endl; - cerr << "New collapsed graph " << new_collapsed_graphs[layer] << ", vcount is " << new_collapsed_graphs[layer]->vcount() << endl; - #endif - } - } - - // Determine whether to aggregate further - // If all is fixed, no need to aggregate - aggregate_further = false; - for (const bool& membership_fixed : is_collapsed_membership_fixed) - { - if(!membership_fixed) { - aggregate_further = true; - break; - } - } - // else, check whether anything has stirred since last time - aggregate_further &= (new_collapsed_graphs[0]->vcount() < collapsed_graphs[0]->vcount()) && - (collapsed_graphs[0]->vcount() > collapsed_partitions[0]->n_communities()); - - #ifdef DEBUG - cerr << "Aggregate further " << aggregate_further << endl; - #endif - - // Delete the previous collapsed partition and graph - for (size_t layer = 0; layer < nb_layers; layer++) - { - if (collapsed_partitions[layer] != partitions[layer]) - delete collapsed_partitions[layer]; - if (collapsed_graphs[layer] != graphs[layer]) - delete collapsed_graphs[layer]; - } - - // and set them to the new one. - collapsed_partitions = new_collapsed_partitions; - collapsed_graphs = new_collapsed_graphs; - - #ifdef DEBUG - for (size_t layer = 0; layer < nb_layers; layer++) - { - cerr << "Calculate partition " << layer << " quality." << endl; - q = partitions[layer]->quality()*layer_weights[layer]; - cerr << "Calculate collapsed partition quality." << endl; - double q_collapsed = 0.0; - q_collapsed += collapsed_partitions[layer]->quality()*layer_weights[layer]; - if (fabs(q - q_collapsed) > 1e-6) - { - cerr << "ERROR: Quality of original partition and collapsed partition are not equal." << endl; - } - cerr << "partition->quality()=" << q - << ", collapsed_partition->quality()=" << q_collapsed << endl; - cerr << "graph->total_weight()=" << graphs[layer]->total_weight() - << ", collapsed_graph->total_weight()=" << collapsed_graphs[layer]->total_weight() << endl; - cerr << "graph->vcount()=" << graphs[layer]->vcount() - << ", collapsed_graph->vcount()=" << collapsed_graphs[layer]->vcount() << endl; - cerr << "graph->ecount()=" << graphs[layer]->ecount() - << ", collapsed_graph->ecount()=" << collapsed_graphs[layer]->ecount() << endl; - cerr << "graph->is_directed()=" << graphs[layer]->is_directed() - << ", collapsed_graph->is_directed()=" << collapsed_graphs[layer]->is_directed() << endl; - cerr << "graph->correct_self_loops()=" << graphs[layer]->correct_self_loops() - << ", collapsed_graph->correct_self_loops()=" << collapsed_graphs[layer]->correct_self_loops() << endl << endl; - } - #endif // DEBUG - - } while (aggregate_further); - - // Clean up memory after use. - for (size_t layer = 0; layer < nb_layers; layer++) - { - if (collapsed_partitions[layer] != partitions[layer]) - delete collapsed_partitions[layer]; - - if (collapsed_graphs[layer] != graphs[layer]) - delete collapsed_graphs[layer]; - } - - // Make sure the resulting communities are called 0,...,r-1 - // where r is the number of communities. The exception is fixed - // nodes which should keep the numbers of the original communities - q = 0.0; - partitions[0]->renumber_communities(); - partitions[0]->renumber_communities(fixed_nodes, fixed_membership); - vector const& membership = partitions[0]->membership(); - // We only renumber the communities for the first graph, - // since the communities for the other graphs should just be equal - // to the membership of the first graph. - for (size_t layer = 1; layer < nb_layers; layer++) - { - partitions[layer]->set_membership(membership); - q += partitions[layer]->quality()*layer_weights[layer]; - } - return improv; -} - -/***************************************************************************** - Move nodes to other communities depending on how other communities are - considered, see consider_comms parameter of the class. - - Parameters: - partition -- The partition to optimise. -******************************************************************************/ -double Optimiser::move_nodes(MutableVertexPartition* partition) -{ - return this->move_nodes(partition, this->consider_comms); -} - -double Optimiser::move_nodes(MutableVertexPartition* partition, int consider_comms) -{ - vector is_membership_fixed(partition->get_graph()->vcount()); - return this->move_nodes(partition, is_membership_fixed, consider_comms, false); -} - -double Optimiser::move_nodes(MutableVertexPartition* partition, vector const& is_membership_fixed, int consider_comms, bool renumber_fixed_nodes) -{ - return this->move_nodes(partition, is_membership_fixed, consider_comms, renumber_fixed_nodes, this->max_comm_size); -} - -double Optimiser::move_nodes(MutableVertexPartition* partition, vector const& is_membership_fixed, int consider_comms, bool renumber_fixed_nodes, size_t max_comm_size) -{ - vector partitions(1); - partitions[0] = partition; - vector layer_weights(1, 1.0); - return this->move_nodes(partitions, layer_weights, is_membership_fixed, consider_comms, this->consider_empty_community, renumber_fixed_nodes, max_comm_size); -} - -double Optimiser::merge_nodes(MutableVertexPartition* partition) -{ - return this->merge_nodes(partition, this->consider_comms); -} - -double Optimiser::merge_nodes(MutableVertexPartition* partition, int consider_comms) -{ - vector is_membership_fixed(partition->get_graph()->vcount()); - return this->merge_nodes(partition, is_membership_fixed, consider_comms, false); -} - -double Optimiser::merge_nodes(MutableVertexPartition* partition, vector const& is_membership_fixed, int consider_comms, bool renumber_fixed_nodes) -{ - return this->merge_nodes(partition, is_membership_fixed, consider_comms, renumber_fixed_nodes, this->max_comm_size); -} - -double Optimiser::merge_nodes(MutableVertexPartition* partition, vector const& is_membership_fixed, int consider_comms, bool renumber_fixed_nodes, size_t max_comm_size) -{ - vector partitions(1); - partitions[0] = partition; - vector layer_weights(1, 1.0); - return this->merge_nodes(partitions, layer_weights, is_membership_fixed, consider_comms, renumber_fixed_nodes, max_comm_size); -} - -double Optimiser::move_nodes_constrained(MutableVertexPartition* partition, MutableVertexPartition* constrained_partition) -{ - return this->move_nodes_constrained(partition, this->refine_consider_comms, constrained_partition); -} - -double Optimiser::move_nodes_constrained(MutableVertexPartition* partition, int consider_comms, MutableVertexPartition* constrained_partition) -{ - return this->move_nodes_constrained(partition, consider_comms, constrained_partition, this->max_comm_size); -} - -double Optimiser::move_nodes_constrained(MutableVertexPartition* partition, int consider_comms, MutableVertexPartition* constrained_partition, size_t max_comm_size) -{ - vector partitions(1); - partitions[0] = partition; - vector layer_weights(1, 1.0); - return this->move_nodes_constrained(partitions, layer_weights, consider_comms, constrained_partition, max_comm_size); -} - -double Optimiser::merge_nodes_constrained(MutableVertexPartition* partition, MutableVertexPartition* constrained_partition) -{ - return this->merge_nodes_constrained(partition, this->refine_consider_comms, constrained_partition); -} - -double Optimiser::merge_nodes_constrained(MutableVertexPartition* partition, int consider_comms, MutableVertexPartition* constrained_partition) -{ - return this->merge_nodes_constrained(partition, consider_comms, constrained_partition, this->max_comm_size); -} - -double Optimiser::merge_nodes_constrained(MutableVertexPartition* partition, int consider_comms, MutableVertexPartition* constrained_partition, size_t max_comm_size) -{ - vector partitions(1); - partitions[0] = partition; - vector layer_weights(1, 1.0); - return this->merge_nodes_constrained(partitions, layer_weights, consider_comms, constrained_partition, max_comm_size); -} - -/***************************************************************************** - Move nodes to neighbouring communities such that each move improves the - given quality function maximally (i.e. greedily) for multiple layers, - i.e. for multiplex networks. Each node will be in the same community in - each layer, but the method may be different, or the weighting may be - different for different layers. Notably, this can be used in the case of - negative links, where you would like to weigh the negative links with a - negative weight. - - Parameters: - partitions -- The partitions to optimise. - layer_weights -- The weights used for the different layers. -******************************************************************************/ -double Optimiser::move_nodes(vector partitions, vector layer_weights, vector const& is_membership_fixed, bool renumber_fixed_nodes) -{ - return this->move_nodes(partitions, layer_weights, is_membership_fixed, this->consider_comms, this->consider_empty_community, renumber_fixed_nodes); -} - -double Optimiser::move_nodes(vector partitions, vector layer_weights, vector const& is_membership_fixed, int consider_comms, int consider_empty_community) -{ - return this->move_nodes(partitions, layer_weights, is_membership_fixed, consider_comms, consider_empty_community, true); -} - -double Optimiser::move_nodes(vector partitions, vector layer_weights, vector const& is_membership_fixed, int consider_comms, int consider_empty_community, bool renumber_fixed_nodes) -{ - return this->move_nodes(partitions, layer_weights, is_membership_fixed, consider_comms, consider_empty_community, renumber_fixed_nodes, this->max_comm_size); -} - -double Optimiser::move_nodes(vector partitions, vector layer_weights, vector const& is_membership_fixed, int consider_comms, int consider_empty_community, bool renumber_fixed_nodes, size_t max_comm_size) -{ - #ifdef DEBUG - cerr << "double Optimiser::move_nodes(vector partitions, vector layer_weights, vector const& is_membership_fixed, int consider_comms, int consider_empty_community, bool renumber_fixed_nodes, size_t max_comm_size)" << endl; - #endif - // Number of multiplex layers - size_t nb_layers = partitions.size(); - if (nb_layers == 0) - return -1.0; - // Get graphs - vector graphs(nb_layers); - for (size_t layer = 0; layer < nb_layers; layer++) - graphs[layer] = partitions[layer]->get_graph(); - // Number of nodes in the graph - size_t n = graphs[0]->vcount(); - - // Get the fixed membership for fixed nodes - vector fixed_nodes; - vector fixed_membership(n); - if (renumber_fixed_nodes) { - for (size_t v = 0; v < n; v++) { - if (is_membership_fixed[v]) { - fixed_nodes.push_back(v); - fixed_membership[v] = partitions[0]->membership(v); - } - } - } - - // Total improvement while moving nodes - double total_improv = 0.0; - - for (Graph* graph : graphs) - if (graph->vcount() != n) - throw Exception("Number of nodes are not equal for all graphs."); - // Number of moved nodes during one loop - size_t nb_moves = 0; - - // Fixed nodes are also stable nodes - vector is_node_stable(is_membership_fixed); - - // Establish vertex order - // We normally initialize the normal vertex order - // of considering node 0,1,... - // But if we use a random order, we shuffle this order. - // Also, we skip fixed nodes from the queue for efficiency reasons - vector nodes; - for (size_t v = 0; v != is_membership_fixed.size(); v++) { - if (!is_membership_fixed[v]) - nodes.push_back(v); - } - shuffle(nodes, &rng); - deque vertex_order(nodes.begin(), nodes.end()); - - // Initialize the degree vector - // If we want to debug the function, we will calculate some additional values. - // In particular, the following consistencies could be checked: - // (1) - The difference in the quality function after a move should match - // the reported difference when calling diff_move. - // (2) - The quality function should be exactly the same value after - // aggregating/collapsing the graph. - - vector comm_added(partitions[0]->n_communities(), false); - vector comms; - - // As long as the queue is not empty - while(!vertex_order.empty()) - { - size_t v = vertex_order.front(); vertex_order.pop_front(); - - // What is the current community of the node (this should be the same for all layers) - size_t v_comm = partitions[0]->membership(v); - - if (consider_comms == ALL_COMMS) - { - for(size_t comm = 0; comm < partitions[0]->n_communities(); comm++) - { - for (size_t layer = 0; layer < nb_layers; layer++) - { - if (partitions[layer]->cnodes(comm) > 0 && !comm_added[comm]) - { - comms.push_back(comm); - comm_added[comm] = true; - break; // Break from for loop in layer - } - } - - } - } - else if (consider_comms == ALL_NEIGH_COMMS) - { - /****************************ALL NEIGH COMMS*****************************/ - for (size_t layer = 0; layer < nb_layers; layer++) - { - for (size_t comm : partitions[layer]->get_neigh_comms(v, IGRAPH_ALL)) - { - if (!comm_added[comm]) - { - comms.push_back(comm); - comm_added[comm] = true; - } - } - } - } - else if (consider_comms == RAND_COMM) - { - /****************************RAND COMM***********************************/ - size_t rand_comm = partitions[0]->membership(graphs[0]->get_random_node(&rng)); - // No need to check if random_comm is already added, we only add one comm - comms.push_back(rand_comm); - comm_added[rand_comm] = true; - } - else if (consider_comms == RAND_NEIGH_COMM) - { - /****************************RAND NEIGH COMM*****************************/ - size_t rand_layer = get_random_int(0, nb_layers - 1, &rng); - if (graphs[rand_layer]->degree(v, IGRAPH_ALL) > 0) - { - size_t rand_comm = partitions[0]->membership(graphs[rand_layer]->get_random_neighbour(v, IGRAPH_ALL, &rng)); - // No need to check if random_comm is already added, we only add one comm - comms.push_back(rand_comm); - comm_added[rand_comm] = true; - } - } - - // Check if we should move to an empty community - if (consider_empty_community) - { - if ( partitions[0]->cnodes(v_comm) > 1 ) // We should not move a node when it is already in its own empty community (this may otherwise create more empty communities than nodes) - { - size_t n_comms = partitions[0]->n_communities(); - size_t comm = partitions[0]->get_empty_community(); - #ifdef DEBUG - cerr << "Checking empty community (" << comm << ") for partition " << partitions[0] << endl; - #endif - comms.push_back(comm); - if (partitions[0]->n_communities() > n_comms) - { - // If the empty community has just been added, we need to make sure - // that is has also been added to the other layers - for (size_t layer = 1; layer < nb_layers; layer++) - partitions[layer]->add_empty_community(); - comm_added.push_back(true); - } - } - } - - #ifdef DEBUG - cerr << "Consider " << comms.size() << " communities for moving." << endl; - #endif - - size_t max_comm = v_comm; - double max_improv = (0 < max_comm_size && max_comm_size < partitions[0]->csize(v_comm)) ? -INFINITY : 10*DBL_EPSILON; - size_t v_size = graphs[0]->node_size(v); - for (size_t comm : comms) - { - // reset comm_added to all false - comm_added[comm] = false; - - // Do not create too-large communities. - if (0 < max_comm_size && max_comm_size < partitions[0]->csize(comm) + v_size) { - continue; - } - - double possible_improv = 0.0; - - // Consider the improvement of moving to a community for all layers - for (size_t layer = 0; layer < nb_layers; layer++) - { - // Make sure to multiply it by the weight per layer - possible_improv += layer_weights[layer]*partitions[layer]->diff_move(v, comm); - } - - if (possible_improv > max_improv) - { - max_comm = comm; - max_improv = possible_improv; - } - } - - // Clear comms - comms.clear(); - - is_node_stable[v] = true; - - // If we actually plan to move the node - if (max_comm != v_comm) - { - // Keep track of improvement - total_improv += max_improv; - - #ifdef DEBUG - // If we are debugging, calculate quality function - double q_improv = 0; - #endif - - for (size_t layer = 0; layer < nb_layers; layer++) - { - MutableVertexPartition* partition = partitions[layer]; - - #ifdef DEBUG - // If we are debugging, calculate quality function - double q1 = partition->quality(); - #endif - - // Actually move the node - partition->move_node(v, max_comm); - #ifdef DEBUG - // If we are debugging, calculate quality function - // and report difference - double q2 = partition->quality(); - double q_delta = layer_weights[layer]*(q2 - q1); - q_improv += q_delta; - cerr << "Move node " << v - << " from " << v_comm << " to " << max_comm << " for layer " << layer - << " (diff_move=" << max_improv - << ", q2 - q1=" << q_delta << ")" << endl; - #endif - } - #ifdef DEBUG - if (fabs(q_improv - max_improv) > 1e-6) - { - cerr << "ERROR: Inconsistency while moving nodes, improvement as measured by quality function did not equal the improvement measured by the diff_move function." << endl - << " (diff_move=" << max_improv - << ", q2 - q1=" << q_improv << ")" << endl; - } - #endif - - // Mark neighbours as unstable (if not in new community and not fixed) - for (Graph* graph : graphs) - { - for (size_t u : graph->get_neighbours(v, IGRAPH_ALL)) - { - // If the neighbour was stable and is not in the new community, we - // should mark it as unstable, and add it to the queue, skipping - // fixed nodes - if (is_node_stable[u] && partitions[0]->membership(u) != max_comm && !is_membership_fixed[u]) - { - vertex_order.push_back(u); - is_node_stable[u] = false; - } - } - } - // Keep track of number of moves - nb_moves += 1; - } - } - - partitions[0]->renumber_communities(); - if (renumber_fixed_nodes) - partitions[0]->renumber_communities(fixed_nodes, fixed_membership); - vector const& membership = partitions[0]->membership(); - for (size_t layer = 1; layer < nb_layers; layer++) - { - partitions[layer]->set_membership(membership); - #ifdef DEBUG - cerr << "Renumbered communities for layer " << layer << " for " << partitions[layer]->n_communities() << " communities." << endl; - #endif //DEBUG - } - return total_improv; -} - -double Optimiser::merge_nodes(vector partitions, vector layer_weights, vector const& is_membership_fixed, bool renumber_fixed_nodes) -{ - return this->merge_nodes(partitions, layer_weights, is_membership_fixed, this->consider_comms, renumber_fixed_nodes); -} - -double Optimiser::merge_nodes(vector partitions, vector layer_weights, vector const& is_membership_fixed, int consider_comms, bool renumber_fixed_nodes) -{ - return this->merge_nodes(partitions, layer_weights, is_membership_fixed, consider_comms, renumber_fixed_nodes, this->max_comm_size); -} - -double Optimiser::merge_nodes(vector partitions, vector layer_weights, vector const& is_membership_fixed, int consider_comms, bool renumber_fixed_nodes, size_t max_comm_size) -{ - #ifdef DEBUG - cerr << "double Optimiser::merge_nodes(vector partitions, vector layer_weights, vector const& is_membership_fixed, int consider_comms, bool renumber_fixed_nodes, size_t max_comm)" << std::endl; - #endif - - // Number of multiplex layers - size_t nb_layers = partitions.size(); - if (nb_layers == 0) - return -1.0; - - // Get graphs - vector graphs(nb_layers); - for (size_t layer = 0; layer < nb_layers; layer++) - graphs[layer] = partitions[layer]->get_graph(); - // Number of nodes in the graph - size_t n = graphs[0]->vcount(); - - // Get the fixed membership for fixed nodes - vector fixed_nodes; - vector fixed_membership(n); - if (renumber_fixed_nodes) { - for (size_t v = 0; v < n; v++) { - if (is_membership_fixed[v]) { - fixed_nodes.push_back(v); - fixed_membership[v] = partitions[0]->membership(v); - } - } - } - - // Total improvement while merging nodes - double total_improv = 0.0; - - for (Graph* graph : graphs) - if (graph->vcount() != n) - throw Exception("Number of nodes are not equal for all graphs."); - - // Establish vertex order, skipping fixed nodes - // We normally initialize the normal vertex order - // of considering node 0,1,... - vector vertex_order; - for (size_t v = 0; v != n; v++) - if (!is_membership_fixed[v]) - vertex_order.push_back(v); - - // But if we use a random order, we shuffle this order. - shuffle(vertex_order, &rng); - - vector comm_added(partitions[0]->n_communities(), false); - vector comms; - - // Iterate over all nodes - for (size_t v : vertex_order) - { - // What is the current community of the node (this should be the same for all layers) - size_t v_comm = partitions[0]->membership(v); - // Clear comms - for (size_t comm : comms) - comm_added[comm] = false; - comms.clear(); - - #ifdef DEBUG - cerr << "Consider moving node " << v << " from " << v_comm << "." << endl; - #endif - - if (partitions[0]->cnodes(v_comm) == 1) - { - if (consider_comms == ALL_COMMS) - { - for(size_t comm = 0; comm < partitions[0]->n_communities(); comm++) - { - for (size_t layer = 0; layer < nb_layers; layer++) - { - if (partitions[layer]->cnodes(comm) > 0 && !comm_added[comm]) - { - comms.push_back(comm); - comm_added[comm] = true; - break; // Break from for loop in layer - } - } - - } - } - else if (consider_comms == ALL_NEIGH_COMMS) - { - /****************************ALL NEIGH COMMS*****************************/ - for (size_t layer = 0; layer < nb_layers; layer++) - { - for (size_t comm : partitions[layer]->get_neigh_comms(v, IGRAPH_ALL)) - { - if (!comm_added[comm]) - { - comms.push_back(comm); - comm_added[comm] = true; - } - } - } - } - else if (consider_comms == RAND_COMM) - { - /****************************RAND COMM***********************************/ - size_t rand_comm = partitions[0]->membership(graphs[0]->get_random_node(&rng)); - // No need to check if random_comm is already added, we only add one comm - comms.push_back(rand_comm); - comm_added[rand_comm] = true; - } - else if (consider_comms == RAND_NEIGH_COMM) - { - /****************************RAND NEIGH COMM*****************************/ - size_t rand_layer = get_random_int(0, nb_layers - 1, &rng); - size_t k = graphs[rand_layer]->degree(v, IGRAPH_ALL); - if (k > 0) - { - // Make sure there is also a probability not to move the node - if (get_random_int(0, k, &rng) > 0) - { - size_t rand_comm = partitions[0]->membership(graphs[rand_layer]->get_random_neighbour(v, IGRAPH_ALL, &rng)); - // No need to check if random_comm is already added, we only add one comm - comms.push_back(rand_comm); - comm_added[rand_comm] = true; - } - } - } - - #ifdef DEBUG - cerr << "Consider " << comms.size() << " communities for moving node " << v << "." << endl; - #endif - - size_t max_comm = v_comm; - double max_improv = (0 < max_comm_size && max_comm_size < partitions[0]->csize(v_comm)) ? -INFINITY : 0; - size_t v_size = graphs[0]->node_size(v); - for (size_t comm : comms) - { - // Do not create too-large communities. - if (0 < max_comm_size && max_comm_size < partitions[0]->csize(comm) + v_size) { - continue; - } - - double possible_improv = 0.0; - - // Consider the improvement of moving to a community for all layers - for (size_t layer = 0; layer < nb_layers; layer++) - { - // Make sure to multiply it by the weight per layer - possible_improv += layer_weights[layer]*partitions[layer]->diff_move(v, comm); - } - #ifdef DEBUG - cerr << "Improvement of " << possible_improv << " when move to " << comm << "." << endl; - #endif - - if (possible_improv >= max_improv) - { - max_comm = comm; - max_improv = possible_improv; - } - } - - // If we actually plan to move the node - if (max_comm != v_comm) - { - // Keep track of improvement - total_improv += max_improv; - - #ifdef DEBUG - // If we are debugging, calculate quality function - double q_improv = 0; - #endif - - for (size_t layer = 0; layer < nb_layers; layer++) - { - MutableVertexPartition* partition = partitions[layer]; - - #ifdef DEBUG - // If we are debugging, calculate quality function - double q1 = partition->quality(); - #endif - - // Actually move the node - partition->move_node(v, max_comm); - #ifdef DEBUG - // If we are debugging, calculate quality function - // and report difference - double q2 = partition->quality(); - double q_delta = layer_weights[layer]*(q2 - q1); - q_improv += q_delta; - cerr << "Move node " << v - << " from " << v_comm << " to " << max_comm << " for layer " << layer - << " (diff_move=" << max_improv - << ", q2 - q1=" << q_delta << ")" << endl; - #endif - } - #ifdef DEBUG - if (fabs(q_improv - max_improv) > 1e-6) - { - cerr << "ERROR: Inconsistency while moving nodes, improvement as measured by quality function did not equal the improvement measured by the diff_move function." << endl - << " (diff_move=" << max_improv - << ", q2 - q1=" << q_improv << ")" << endl; - } - #endif - } - } - } - - partitions[0]->renumber_communities(); - if (renumber_fixed_nodes) - partitions[0]->renumber_communities(fixed_nodes, fixed_membership); - vector const& membership = partitions[0]->membership(); - for (size_t layer = 1; layer < nb_layers; layer++) - { - partitions[layer]->set_membership(membership); - #ifdef DEBUG - cerr << "Renumbered communities for layer " << layer << " for " << partitions[layer]->n_communities() << " communities." << endl; - #endif //DEBUG - } - return total_improv; -} - -double Optimiser::move_nodes_constrained(vector partitions, vector layer_weights, MutableVertexPartition* constrained_partition) -{ - return this->move_nodes_constrained(partitions, layer_weights, this->refine_consider_comms, constrained_partition); -} - -double Optimiser::move_nodes_constrained(vector partitions, vector layer_weights, int consider_comms, MutableVertexPartition* constrained_partition) -{ - return this->move_nodes_constrained(partitions, layer_weights, refine_consider_comms, constrained_partition, this->max_comm_size); -} - -double Optimiser::move_nodes_constrained(vector partitions, vector layer_weights, int consider_comms, MutableVertexPartition* constrained_partition, size_t max_comm_size) -{ - #ifdef DEBUG - cerr << "double Optimiser::move_nodes_constrained(vector partitions, vector layer_weights, int consider_comms, MutableVertexPartition* constrained_partition, size_t max_comm_size)" << std::endl; - #endif - // Number of multiplex layers - size_t nb_layers = partitions.size(); - if (nb_layers == 0) - return -1.0; - // Get graphs - vector graphs(nb_layers); - for (size_t layer = 0; layer < nb_layers; layer++) - graphs[layer] = partitions[layer]->get_graph(); - // Number of nodes in the graph - size_t n = graphs[0]->vcount(); - - // Total improvement while moving nodes - double total_improv = 0.0; - - for (size_t layer = 0; layer < nb_layers; layer++) - if (graphs[layer]->vcount() != n) - throw Exception("Number of nodes are not equal for all graphs."); - // Number of moved nodes during one loop - size_t nb_moves = 0; - - // Establish vertex order - // We normally initialize the normal vertex order - // of considering node 0,1,... - vector is_node_stable(n, false); - // But if we use a random order, we shuffle this order. - vector nodes = range(n); - shuffle(nodes, &rng); - deque vertex_order(nodes.begin(), nodes.end()); - - vector< vector > constrained_comms = constrained_partition->get_communities(); - - // Initialize the degree vector - // If we want to debug the function, we will calculate some additional values. - // In particular, the following consistencies could be checked: - // (1) - The difference in the quality function after a move should match - // the reported difference when calling diff_move. - // (2) - The quality function should be exactly the same value after - // aggregating/collapsing the graph. - - vector comm_added(partitions[0]->n_communities(), false); - vector comms; - - // As long as the queue is not empty - while(!vertex_order.empty()) - { - size_t v = vertex_order.front(); vertex_order.pop_front(); - - // Clear comms - for (size_t comm : comms) - comm_added[comm] = false; - comms.clear(); - - // What is the current community of the node (this should be the same for all layers) - size_t v_comm = partitions[0]->membership(v); - - if (consider_comms == ALL_COMMS) - { - // Add all communities to the set comms that are within the constrained community. - size_t v_constrained_comm = constrained_partition->membership(v); - for (size_t u : constrained_comms[v_constrained_comm]) - { - size_t u_comm = partitions[0]->membership(u); - if (!comm_added[u_comm]) - { - comms.push_back(u_comm); - comm_added[u_comm] = true; - } - } - } - else if (consider_comms == ALL_NEIGH_COMMS) - { - /****************************ALL NEIGH COMMS*****************************/ - for (size_t layer = 0; layer < nb_layers; layer++) - { - for (size_t comm : partitions[layer]->get_neigh_comms(v, IGRAPH_ALL, constrained_partition->membership())) - { - if (!comm_added[comm]) - { - comms.push_back(comm); - comm_added[comm] = true; - } - } - } - } - else if (consider_comms == RAND_COMM) - { - /****************************RAND COMM***********************************/ - size_t v_constrained_comm = constrained_partition->membership(v); - size_t random_idx = get_random_int(0, constrained_comms[v_constrained_comm].size() - 1, &rng); - size_t rand_comm = constrained_comms[v_constrained_comm][random_idx]; - // No need to check if random_comm is already added, we only add one comm - comms.push_back(rand_comm); - comm_added[rand_comm] = true; - } - else if (consider_comms == RAND_NEIGH_COMM) - { - /****************************RAND NEIGH COMM*****************************/ - // Draw a random community among the neighbours, proportional to the - // frequency of the communities among the neighbours. Notice this is no - // longer - vector all_neigh_comms_incl_dupes; - for (size_t layer = 0; layer < nb_layers; layer++) - { - vector neigh_comm_layer = partitions[layer]->get_neigh_comms(v, IGRAPH_ALL, constrained_partition->membership()); - all_neigh_comms_incl_dupes.insert(all_neigh_comms_incl_dupes.end(), neigh_comm_layer.begin(), neigh_comm_layer.end()); - } - if (all_neigh_comms_incl_dupes.size() > 0) - { - size_t random_idx = get_random_int(0, all_neigh_comms_incl_dupes.size() - 1, &rng); - size_t rand_comm = all_neigh_comms_incl_dupes[random_idx]; - // No need to check if random_comm is already added, we only add one comm - comms.push_back(rand_comm); - comm_added[rand_comm] = true; - } - } - - #ifdef DEBUG - cerr << "Consider " << comms.size() << " communities for moving." << endl; - #endif - - size_t max_comm = v_comm; - double max_improv = (0 < max_comm_size && max_comm_size < partitions[0]->csize(v_comm)) ? -INFINITY : 10*DBL_EPSILON; - size_t v_size = graphs[0]->node_size(v); - for (size_t comm : comms) - { - // Do not create too-large communities. - if (0 < max_comm_size && max_comm_size < partitions[0]->csize(comm) + v_size) { - continue; - } - - double possible_improv = 0.0; - - // Consider the improvement of moving to a community for all layers - for (size_t layer = 0; layer < nb_layers; layer++) - { - // Make sure to multiply it by the weight per layer - possible_improv += layer_weights[layer]*partitions[layer]->diff_move(v, comm); - } - - // Check if improvement is best - if (possible_improv > max_improv) - { - max_comm = comm; - max_improv = possible_improv; - } - } - - is_node_stable[v] = true; - - // If we actually plan to move the nove - if (max_comm != v_comm) - { - // Keep track of improvement - total_improv += max_improv; - - #ifdef DEBUG - // If we are debugging, calculate quality function - double q_improv = 0; - #endif - - for (size_t layer = 0; layer < nb_layers; layer++) - { - MutableVertexPartition* partition = partitions[layer]; - - #ifdef DEBUG - // If we are debugging, calculate quality function - double q1 = partition->quality(); - #endif - - // Actually move the node - partition->move_node(v, max_comm); - #ifdef DEBUG - // If we are debugging, calculate quality function - // and report difference - double q2 = partition->quality(); - double q_delta = layer_weights[layer]*(q2 - q1); - q_improv += q_delta; - cerr << "Move node " << v - << " from " << v_comm << " to " << max_comm << " for layer " << layer - << " (diff_move=" << max_improv - << ", q2 - q1=" << q_delta << ")" << endl; - #endif - } - #ifdef DEBUG - if (fabs(q_improv - max_improv) > 1e-6) - { - cerr << "ERROR: Inconsistency while moving nodes, improvement as measured by quality function did not equal the improvement measured by the diff_move function." << endl - << " (diff_move=" << max_improv - << ", q2 - q1=" << q_improv << ")" << endl; - } - #endif - - // Mark neighbours as unstable (if not in new community and not fixed) - for (Graph* graph : graphs) - { - for (size_t u : graph->get_neighbours(v, IGRAPH_ALL)) - { - // If the neighbour was stable and is not in the new community, we - // should mark it as unstable, and add it to the queue, skipping - // fixed nodes - if (is_node_stable[u] && partitions[0]->membership(u) != max_comm && constrained_partition->membership(u) == constrained_partition->membership(v)) - { - vertex_order.push_back(u); - is_node_stable[u] = false; - } - } - } - - // Keep track of number of moves - nb_moves += 1; - } - #ifdef DEBUG - cerr << "Moved " << nb_moves << " nodes." << endl; - #endif - } - partitions[0]->renumber_communities(); - vector const& membership = partitions[0]->membership(); - for (size_t layer = 1; layer < nb_layers; layer++) - { - partitions[layer]->set_membership(membership); - #ifdef DEBUG - cerr << "Renumbered communities for layer " << layer << " for " << partitions[layer]->n_communities() << " communities." << endl; - #endif //DEBUG - } - return total_improv; -} - -double Optimiser::merge_nodes_constrained(vector partitions, vector layer_weights, MutableVertexPartition* constrained_partition) -{ - return this->merge_nodes_constrained(partitions, layer_weights, this->refine_consider_comms, constrained_partition); -} - -double Optimiser::merge_nodes_constrained(vector partitions, vector layer_weights, int consider_comms, MutableVertexPartition* constrained_partition) -{ - return this->merge_nodes_constrained(partitions, layer_weights, refine_consider_comms, constrained_partition, this->max_comm_size); -} - -double Optimiser::merge_nodes_constrained(vector partitions, vector layer_weights, int consider_comms, MutableVertexPartition* constrained_partition, size_t max_comm_size) -{ - #ifdef DEBUG - cerr << "double Optimiser::merge_nodes_constrained(vector partitions, vector layer_weights, int consider_comms, MutableVertexPartition* constrained_partition, size_t max_comm_size)" << std::endl; - #endif - - // Number of multiplex layers - size_t nb_layers = partitions.size(); - if (nb_layers == 0) - return -1.0; - - // Get graphs - vector graphs(nb_layers); - for (size_t layer = 0; layer < nb_layers; layer++) - graphs[layer] = partitions[layer]->get_graph(); - // Number of nodes in the graph - size_t n = graphs[0]->vcount(); - - // Total improvement while merging nodes - double total_improv = 0.0; - - for (size_t layer = 0; layer < nb_layers; layer++) - if (graphs[layer]->vcount() != n) - throw Exception("Number of nodes are not equal for all graphs."); - - // Establish vertex order - // We normally initialize the normal vertex order - // of considering node 0,1,... - vector vertex_order = range(n); - - - // But if we use a random order, we shuffle this order. - shuffle(vertex_order, &rng); - - vector< vector > constrained_comms = constrained_partition->get_communities(); - - vector comm_added(partitions[0]->n_communities(), false); - vector comms; - - // For each node - for (size_t v : vertex_order) - { - // What is the current community of the node (this should be the same for all layers) - size_t v_comm = partitions[0]->membership(v); - - if (partitions[0]->cnodes(v_comm) == 1) - { - // Clear comms - for (size_t comm : comms) - comm_added[comm] = false; - comms.clear(); - - if (consider_comms == ALL_COMMS) - { - // Add all communities to the set comms that are within the constrained community. - size_t v_constrained_comm = constrained_partition->membership(v); - for (size_t u : constrained_comms[v_constrained_comm]) - { - size_t u_comm = partitions[0]->membership(u); - if (!comm_added[u_comm]) { - comms.push_back(u_comm); - comm_added[u_comm] = true; - } - } - } - else if (consider_comms == ALL_NEIGH_COMMS) - { - /****************************ALL NEIGH COMMS*****************************/ - for (size_t layer = 0; layer < nb_layers; layer++) - { - for (size_t u : partitions[layer]->get_graph()->get_neighbours(v, IGRAPH_ALL)) { - if (constrained_partition->membership(v) == constrained_partition->membership(u)) { - size_t comm = partitions[layer]->membership(u); - if (!comm_added[comm]) { - comms.push_back(comm); - comm_added[comm] = true; - } - } - } - } - } - else if (consider_comms == RAND_COMM) - { - /****************************RAND COMM***********************************/ - size_t v_constrained_comm = constrained_partition->membership(v); - size_t random_idx = get_random_int(0, constrained_comms[v_constrained_comm].size() - 1, &rng); - size_t rand_comm = constrained_comms[v_constrained_comm][random_idx]; - // No need to check if random_comm is already added, we only add one comm - comms.push_back(rand_comm); - comm_added[rand_comm] = true; - } - else if (consider_comms == RAND_NEIGH_COMM) - { - /****************************RAND NEIGH COMM*****************************/ - // Draw a random community among the neighbours, proportional to the - // frequency of the communities among the neighbours. Notice this is no - // longer - vector all_neigh_comms_incl_dupes; - for (size_t layer = 0; layer < nb_layers; layer++) - { - vector neigh_comm_layer = partitions[layer]->get_neigh_comms(v, IGRAPH_ALL, constrained_partition->membership()); - all_neigh_comms_incl_dupes.insert(all_neigh_comms_incl_dupes.end(), neigh_comm_layer.begin(), neigh_comm_layer.end()); - } - size_t k = all_neigh_comms_incl_dupes.size(); - if (k > 0) - { - // Make sure there is also a probability not to move the node - if (get_random_int(0, k, &rng) > 0) - { - size_t random_idx = get_random_int(0, k - 1, &rng); - size_t rand_comm = all_neigh_comms_incl_dupes[random_idx]; - // No need to check if random_comm is already added, we only add one comm - comms.push_back(rand_comm); - comm_added[rand_comm] = true; - } - } - } - - #ifdef DEBUG - cerr << "Consider " << comms.size() << " communities for moving." << endl; - #endif - - size_t max_comm = v_comm; - double max_improv = (0 < max_comm_size && max_comm_size < partitions[0]->csize(v_comm)) ? -INFINITY : 0; - size_t v_size = graphs[0]->node_size(v); - for (size_t comm : comms) - { - // reset comm_added to all false - comm_added[comm] = false; - - // Do not create too-large communities. - if (0 < max_comm_size && max_comm_size < partitions[0]->csize(comm) + v_size) { - continue; - } - - double possible_improv = 0.0; - - // Consider the improvement of moving to a community for all layers - for (size_t layer = 0; layer < nb_layers; layer++) - { - // Make sure to multiply it by the weight per layer - possible_improv += layer_weights[layer]*partitions[layer]->diff_move(v, comm); - } - - if (possible_improv >= max_improv) - { - max_comm = comm; - max_improv = possible_improv; - } - } - - // If we actually plan to move the node - if (max_comm != v_comm) - { - // Keep track of improvement - total_improv += max_improv; - - #ifdef DEBUG - // If we are debugging, calculate quality function - double q_improv = 0; - #endif - - for (size_t layer = 0; layer < nb_layers; layer++) - { - MutableVertexPartition* partition = partitions[layer]; - - #ifdef DEBUG - // If we are debugging, calculate quality function - double q1 = partition->quality(); - #endif - - // Actually move the node - partition->move_node(v, max_comm); - #ifdef DEBUG - // If we are debugging, calculate quality function - // and report difference - double q2 = partition->quality(); - double q_delta = layer_weights[layer]*(q2 - q1); - q_improv += q_delta; - cerr << "Move node " << v - << " from " << v_comm << " to " << max_comm << " for layer " << layer - << " (diff_move=" << max_improv - << ", q2 - q1=" << q_delta << ")" << endl; - #endif - } - #ifdef DEBUG - if (fabs(q_improv - max_improv) > 1e-6) - { - cerr << "ERROR: Inconsistency while moving nodes, improvement as measured by quality function did not equal the improvement measured by the diff_move function." << endl - << " (diff_move=" << max_improv - << ", q2 - q1=" << q_improv << ")" << endl; - } - #endif - } - } - } - - partitions[0]->renumber_communities(); - vector const& membership = partitions[0]->membership(); - for (size_t layer = 1; layer < nb_layers; layer++) - { - partitions[layer]->set_membership(membership); - #ifdef DEBUG - cerr << "Renumbered communities for layer " << layer << " for " << partitions[layer]->n_communities() << " communities." << endl; - #endif //DEBUG - } - return total_improv; -} diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/Optimiser.py b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/Optimiser.py deleted file mode 100644 index 832431b..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/Optimiser.py +++ /dev/null @@ -1,808 +0,0 @@ -from . import _c_leiden -from .VertexPartition import LinearResolutionParameterVertexPartition -from collections import namedtuple -from math import log, sqrt - -class Optimiser(object): - """ Class for doing community detection using the Leiden algorithm. - - The Leiden algorithm [1] derives from the Louvain algorithm [2]. The Louvain - algorithm has an elegant formulation. It consists of two phases: (1) move - nodes between communities; (2) aggregate the graph. It then repeats these - phases on the aggregate graph. The Leiden algorithm consists of three phases: - (1) move nodes; (2) refine communities; (3) aggregate the graph based on the - refinement. The Louvain algorithm can lead to arbitrarily badly connected - communities, whereas the Leiden algorithm guarantees communities are - well-connected. In fact, it converges towards a partition in which all - subsets of all communities are locally optimally assigned. Finally, the - Leiden algorithm is also much faster, because it relies on a fast local move - routine. - - There is one, rather technical, difference with the original Leiden - algorithm. This implementation provides a general optimisation - routine for any quality function. There is one aspect of the original Leiden - algorithm that cannot be translated well in this framework: when merging - subcommunities in the refinement procedure, it does not consider whether they - are sufficiently well connected to the rest of the community. This - implementation therefore does not guarantee subpartition :math:`\gamma`-density. - However, all other guarantees still hold: - - After each iteration - 1. :math:`\gamma`-separation - 2. :math:`\gamma`-connectivity - - After a stable iteration - 3. Node optimality - 4. Some subsets are locally optimally assigned - - Asymptotically - 5. Uniform :math:`\gamma`-density - 6. Subset optimality - - The optimiser class provides a number of different methods for optimising a - given partition. The overall optimisation procedure - :func:`optimise_partition` calls either :func:`move_nodes` or - :func:`merge_nodes` (which is controlled by :attr:`optimise_routine`) then - aggregates the graph and repeats the same procedure. Possible, indicated by - :attr:`refine_partition` the partition is refined before aggregating, meaning - that subsets of communities are considered for moving around. Which routine - is used for the refinement is indicated by :attr:`refine_routine`. For - calculating the actual improvement of moving a node (corresponding a subset - of nodes in the aggregate graph), the code relies on - :func:`~VertexPartition.MutableVertexPartition.diff_move` which provides - different values for different methods (e.g. modularity or CPM). The default - settings are consistent with the Leiden algorithm. By not doing the - refinement, you essentially get the Louvain algorithm with a fast local move. - Finally, the Optimiser class provides a routine to construct a - :func:`resolution_profile` on a resolution parameter. - - References - ---------- - - .. [1] Traag, V.A., Waltman. L., Van Eck, N.-J. (2018). From Louvain to - Leiden: guaranteeing well-connected communities. - `arXiv:1810.08473 `_ - - .. [2] Blondel, V. D., Guillaume, J.-L., Lambiotte, R., & Lefebvre, E. - (2008). Fast unfolding of communities in large networks. Journal of - Statistical Mechanics: Theory and Experiment, 10008(10), 6. - `10.1088/1742-5468/2008/10/P10008 `_ - """ - def __init__(self): - """ Create a new Optimiser object """ - self._optimiser = _c_leiden._new_Optimiser() - - #########################################################3 - # consider_comms - @property - def consider_comms(self): - """ Determine how alternative communities are considered for moving - a node for *optimising* a partition. - - Nodes will only move to alternative communities that improve the given - quality function. - - Notes - ------- - This attribute should be set to one of the following values - - * :attr:`leidenalg.ALL_NEIGH_COMMS` - Consider all neighbouring communities for moving. - - * :attr:`leidenalg.ALL_COMMS` - Consider all communities for moving. This is especially useful in the - case of negative links, in which case it may be better to move a node to - a non-neighbouring community. - - * :attr:`leidenalg.RAND_NEIGH_COMM` - Consider a random neighbour community for moving. The probability to - choose a community is proportional to the number of neighbours a node has - in that community. - - * :attr:`leidenalg.RAND_COMM` - Consider a random community for moving. The probability to choose a - community is proportional to the number of nodes in that community. - """ - return _c_leiden._Optimiser_get_consider_comms(self._optimiser) - - @consider_comms.setter - def consider_comms(self, value): - _c_leiden._Optimiser_set_consider_comms(self._optimiser, value) - - #########################################################3 - # refine consider_comms - @property - def refine_consider_comms(self): - """ Determine how alternative communities are considered for moving - a node when *refining* a partition. - - Nodes will only move to alternative communities that improve the given - quality function. - - Notes - ------- - This attribute should be set to one of the following values - - * :attr:`leidenalg.ALL_NEIGH_COMMS` - Consider all neighbouring communities for moving. - - * :attr:`leidenalg.ALL_COMMS` - Consider all communities for moving. This is especially useful in the - case of negative links, in which case it may be better to move a node to - a non-neighbouring community. - - * :attr:`leidenalg.RAND_NEIGH_COMM` - Consider a random neighbour community for moving. The probability to - choose a community is proportional to the number of neighbours a node has - in that community. - - * :attr:`leidenalg.RAND_COMM` - Consider a random community for moving. The probability to choose a - community is proportional to the number of nodes in that community. - """ - return _c_leiden._Optimiser_get_refine_consider_comms(self._optimiser) - - @refine_consider_comms.setter - def refine_consider_comms(self, value): - _c_leiden._Optimiser_set_refine_consider_comms(self._optimiser, value) - - #########################################################3 - # optimise routine - @property - def optimise_routine(self): - """ Determine the routine to use for *optimising* a partition. - - Notes - ------- - This attribute should be set to one of the following values - - * :attr:`leidenalg.MOVE_NODES` - Use :func:`move_nodes`. - - * :attr:`leidenalg.MERGE_NODES` - Use :func:`merge_nodes`. - """ - return _c_leiden._Optimiser_get_optimise_routine(self._optimiser) - - @optimise_routine.setter - def optimise_routine(self, value): - _c_leiden._Optimiser_set_optimise_routine(self._optimiser, value) - - #########################################################3 - # optimise routine - @property - def refine_routine(self): - """ Determine the routine to use for *refining* a partition. - - Notes - ------- - This attribute should be set to one of the following values - - * :attr:`leidenalg.MOVE_NODES` - Use :func:`move_nodes`. - - * :attr:`leidenalg.MERGE_NODES` - Use :func:`merge_nodes`. - """ - return _c_leiden._Optimiser_get_refine_routine(self._optimiser) - - @refine_routine.setter - def refine_routine(self, value): - _c_leiden._Optimiser_set_refine_routine(self._optimiser, value) - - #########################################################3 - # refine_partition - @property - def refine_partition(self): - """ boolean: if ``True`` refine partition before aggregation. """ - return _c_leiden._Optimiser_get_refine_partition(self._optimiser) - - @refine_partition.setter - def refine_partition(self, value): - _c_leiden._Optimiser_set_refine_partition(self._optimiser, value) - - #########################################################3 - # consider_empty_community - @property - def consider_empty_community(self): - """ boolean: if ``True`` consider also moving nodes to an empty community - (default). """ - return _c_leiden._Optimiser_get_consider_empty_community(self._optimiser) - - @consider_empty_community.setter - def consider_empty_community(self, value): - _c_leiden._Optimiser_set_consider_empty_community(self._optimiser, value) - - #########################################################3 - # max_comm_size - @property - def max_comm_size(self): - """ Constrain the maximal community size. - - By default (zero), communities can be of any size. If this is set to a - positive integer value, then communities will be constrained to be at most - this total size. - """ - return _c_leiden._Optimiser_get_max_comm_size(self._optimiser) - - @max_comm_size.setter - def max_comm_size(self, value): - if value < 0: - raise ValueError("negative max_comm_size: %s" % value) - _c_leiden._Optimiser_set_max_comm_size(self._optimiser, value) - - ########################################################## - # Set rng seed - def set_rng_seed(self, value): - """ Set the random seed for the random number generator. - - Parameters - ---------- - value - The integer seed used in the random number generator - """ - _c_leiden._Optimiser_set_rng_seed(self._optimiser, value) - - def optimise_partition(self, partition, n_iterations=2, is_membership_fixed=None): - """ Optimise the given partition. - - Parameters - ---------- - partition - The :class:`~VertexPartition.MutableVertexPartition` to optimise. - - n_iterations : int - Number of iterations to run the Leiden algorithm. By default, 2 iterations - are run. If the number of iterations is negative, the Leiden algorithm is - run until an iteration in which there was no improvement. - - is_membership_fixed: list of bools or None - Boolean list of nodes that are not allowed to change community. The - length of this list must be equal to the number of nodes. By default - (None) all nodes can change community during the optimization. - - Returns - ------- - float - Improvement in quality function. - - Examples - -------- - - >>> G = ig.Graph.Famous('Zachary') - >>> optimiser = la.Optimiser() - >>> partition = la.ModularityVertexPartition(G) - >>> diff = optimiser.optimise_partition(partition) - - or, fixing the membership of some nodes: - - >>> is_membership_fixed = [False for v in G.vs] - >>> is_membership_fixed[4] = True - >>> is_membership_fixed[6] = True - >>> diff = optimiser.optimise_partition(partition, is_membership_fixed=is_membership_fixed) - """ - - itr = 0 - diff = 0 - continue_iteration = itr < n_iterations or n_iterations < 0 - while continue_iteration: - diff_inc = _c_leiden._Optimiser_optimise_partition( - self._optimiser, - partition._partition, - is_membership_fixed=is_membership_fixed, - ) - diff += diff_inc - itr += 1 - if n_iterations < 0: - continue_iteration = (diff_inc > 0) - else: - continue_iteration = itr < n_iterations - - partition._update_internal_membership() - return diff - - def optimise_partition_multiplex(self, partitions, layer_weights=None, n_iterations=2, is_membership_fixed=None): - """ Optimise the given partitions simultaneously. - - Parameters - ---------- - partitions - List of :class:`~VertexPartition.MutableVertexPartition` layers to optimise. - - layer_weights - List of weights of layers. - - is_membership_fixed: list of bools or None - Boolean list of nodes that are not allowed to change community. The - length of this list must be equal to the number of nodes. By default - (None) all nodes can change community during the optimization. - - n_iterations : int - Number of iterations to run the Leiden algorithm. By default, 2 iterations - are run. If the number of iterations is negative, the Leiden algorithm is - run until an iteration in which there was no improvement. - - Returns - ------- - float - Improvement in quality of combined partitions, see `Notes <#notes-multiplex>`_. - - - .. _notes-multiplex: - - Notes - ----- - - This method assumes that the partitions are defined for graphs with the - same vertices. The connections between the vertices may be different, but - the vertices themselves should be identical. In other words, all vertices - should have identical indices in all graphs (i.e. node `i` is assumed to be - the same node in all graphs). The quality of the overall partition is - simply the sum of the individual qualities for the various partitions, - weighted by the layer_weight. If we denote by :math:`Q_k` the quality of - layer :math:`k` and the weight by :math:`\\lambda_k`, the overall quality - is then - - .. math:: Q = \sum_k \\lambda_k Q_k. - - This is particularly useful for graphs containing negative links. When - separating the graph in two graphs, the one containing only the positive - links, and the other only the negative link, by supplying a negative weight - to the latter layer, we try to find relatively many positive links within a - community and relatively many negative links between communities. Note that - in this case it may be better to assign a node to a community to which it - is not connected so that :attr:`consider_comms` may be better set to - :attr:`leidenalg.ALL_COMMS`. - - Besides multiplex graphs where each node is assumed to have a single - community, it is also useful in the case of for example multiple time - slices, or in situations where nodes can have different communities in - different slices. The package includes some special helper functions for - using :func:`optimise_partition_multiplex` in such cases, where there is a - conversion required from (time) slices to layers suitable for use in this - function. - - See Also - -------- - :func:`slices_to_layers` - - :func:`time_slices_to_layers` - - :func:`find_partition_multiplex` - - :func:`find_partition_temporal` - - Examples - -------- - >>> G_pos = ig.Graph.SBM(100, pref_matrix=[[0.5, 0.1], [0.1, 0.5]], block_sizes=[50, 50]) - >>> G_neg = ig.Graph.SBM(100, pref_matrix=[[0.1, 0.5], [0.5, 0.1]], block_sizes=[50, 50]) - >>> optimiser = la.Optimiser() - >>> partition_pos = la.ModularityVertexPartition(G_pos) - >>> partition_neg = la.ModularityVertexPartition(G_neg) - >>> diff = optimiser.optimise_partition_multiplex( - ... partitions=[partition_pos, partition_neg], - ... layer_weights=[1,-1]) - - """ - if not layer_weights: - layer_weights = [1]*len(partitions) - - itr = 0 - diff = 0 - continue_iteration = itr < n_iterations or n_iterations < 0 - while continue_iteration: - diff_inc = _c_leiden._Optimiser_optimise_partition_multiplex( - self._optimiser, - [partition._partition for partition in partitions], - layer_weights, - is_membership_fixed) - diff += diff_inc - itr += 1 - if n_iterations < 0: - continue_iteration = (diff_inc > 0) - else: - continue_iteration = itr < n_iterations - - for partition in partitions: - partition._update_internal_membership() - return diff - - def move_nodes(self, partition, is_membership_fixed=None, consider_comms=None): - """ Move nodes to alternative communities for *optimising* the partition. - - Parameters - ---------- - partition - The partition for which to move nodes. - - is_membership_fixed: list of bools or None - Boolean list of nodes that are not allowed to change community. The - length of this list must be equal to the number of nodes. By default - (None) all nodes can change community during the optimization. - - consider_comms - If ``None`` uses :attr:`consider_comms`, but can be set to - something else. - - Returns - ------- - float - Improvement in quality function. - - Notes - ----- - When moving nodes, the function loops over nodes and considers moving the - node to an alternative community. Which community depends on - ``consider_comms``. The function terminates when no more nodes can be moved - to an alternative community. - - See Also - -------- - :func:`Optimiser.move_nodes_constrained` - - :func:`Optimiser.merge_nodes` - - Examples - -------- - >>> G = ig.Graph.Famous('Zachary') - >>> optimiser = la.Optimiser() - >>> partition = la.ModularityVertexPartition(G) - >>> diff = optimiser.move_nodes(partition) - - """ - if (consider_comms is None): - consider_comms = self.consider_comms - diff = _c_leiden._Optimiser_move_nodes( - self._optimiser, partition._partition, is_membership_fixed, consider_comms) - partition._update_internal_membership() - return diff - - def move_nodes_constrained(self, partition, constrained_partition, consider_comms=None): - """ Move nodes to alternative communities for *refining* the partition. - - Parameters - ---------- - partition - The partition for which to move nodes. - - constrained_partition - The partition within which we may move nodes. - - consider_comms - If ``None`` uses :attr:`refine_consider_comms`, but can be set - to something else. - - Returns - ------- - float - Improvement in quality function. - - Notes - ----- - The idea is constrain the movement of nodes to alternative communities to - another partition. In other words, if there is a partition ``P`` which we - want to refine, we can then initialize a new singleton partition, and move - nodes in that partition constrained to ``P``. - - See Also - -------- - :func:`Optimiser.move_nodes` - - :func:`Optimiser.merge_nodes_constrained` - - Examples - -------- - >>> G = ig.Graph.Famous('Zachary') - >>> optimiser = la.Optimiser() - >>> partition = la.ModularityVertexPartition(G) - >>> diff = optimiser.optimise_partition(partition) - >>> refine_partition = la.ModularityVertexPartition(G) - >>> diff = optimiser.move_nodes_constrained(refine_partition, partition) - - """ - if (consider_comms is None): - consider_comms = self.refine_consider_comms - diff = _c_leiden._Optimiser_move_nodes_constrained(self._optimiser, partition._partition, constrained_partition._partition, consider_comms) - partition._update_internal_membership() - return diff - - def merge_nodes(self, partition, is_membership_fixed=None, consider_comms=None): - """ Merge nodes for *optimising* the partition. - - Parameters - ---------- - partition - The partition for which to merge nodes. - - is_membership_fixed: list of bools or None - Boolean list of nodes that are not allowed to change community. The - length of this list must be equal to the number of nodes. By default - (None) all nodes can change community during the optimization. - - consider_comms - If ``None`` uses :attr:`consider_comms`, but can be set to - something else. - - Returns - ------- - float - Improvement in quality function. - - Notes - ----- - This function loop over all nodes once and tries to merge them with another - community. Merging in this case implies that a node will never be removed - from a community, only merged with other communities. - - See Also - -------- - :func:`Optimiser.move_nodes` - - :func:`Optimiser.merge_nodes_constrained` - - Examples - -------- - >>> G = ig.Graph.Famous('Zachary') - >>> optimiser = la.Optimiser() - >>> partition = la.ModularityVertexPartition(G) - >>> diff = optimiser.merge_nodes(partition) - - """ - if (consider_comms is None): - consider_comms = self.consider_comms - - diff = _c_leiden._Optimiser_merge_nodes( - self._optimiser, partition._partition, is_membership_fixed, consider_comms) - partition._update_internal_membership() - return diff - - def merge_nodes_constrained(self, partition, constrained_partition, consider_comms=None): - """ Merge nodes for *refining* the partition. - - Parameters - ---------- - partition - The partition for which to merge nodes. - - constrained_partition - The partition within which we may merge nodes. - - consider_comms - If ``None`` uses :attr:`refine_consider_comms`, but can be set - to something else. - - Returns - ------- - float - Improvement in quality function. - - Notes - ----- - The idea is constrain the merging of nodes to another partition. In other - words, if there is a partition ``P`` which we want to refine, we can then - initialize a new singleton partition, and move nodes in that partition - constrained to ``P``. - - See Also - -------- - :func:`Optimiser.move_nodes_constrained` - - :func:`Optimiser.merge_nodes` - - Examples - -------- - >>> G = ig.Graph.Famous('Zachary') - >>> optimiser = la.Optimiser() - >>> partition = la.ModularityVertexPartition(G) - >>> diff = optimiser.optimise_partition(partition) - >>> refine_partition = la.ModularityVertexPartition(G) - >>> diff = optimiser.move_nodes_constrained(refine_partition, partition) - - """ - if (consider_comms is None): - consider_comms = self.refine_consider_comms - diff = _c_leiden._Optimiser_merge_nodes_constrained(self._optimiser, partition._partition, constrained_partition._partition, consider_comms) - partition._update_internal_membership() - return diff - - def resolution_profile(self, - graph, - partition_type, - resolution_range, - weights=None, - bisect_func=lambda p: p.bisect_value(), - min_diff_bisect_value=1, - min_diff_resolution=1e-3, - linear_bisection=False, - number_iterations=1, - **kwargs - ): - """ Use bisectioning on the resolution parameter in order to construct a - resolution profile. - - Parameters - ---------- - graph - The graph for which to construct a resolution profile. - - partition_type - The type of :class:`~VertexPartition.MutableVertexPartition` used - to find a partition (must support resolution parameters obviously). - - resolution_range - The range of resolution values that we would like to scan. - - weights - If provided, indicates the edge attribute to use as a weight. - - Returns - ------- - list of :class:`~VertexPartition.MutableVertexPartition` - A list of partitions for different resolutions. - - Other Parameters - ---------------- - bisect_func - The function used for bisectioning. For the methods currently - implemented, this should usually not be altered. - - min_diff_bisect_value - The difference in the value returned by the bisect_func below which the - bisectioning stops (i.e. by default, a difference of a single edge does - not trigger further bisectioning). - - min_diff_resolution - The difference in resolution below which the bisectioning stops. For - positive differences, the logarithmic difference is used by default, i.e. - ``diff = log(res_1) - log(res_2) = log(res_1/res_2)``, for which ``diff > - min_diff_resolution`` to continue bisectioning. Set the linear_bisection - to true in order to use only linear bisectioning (in the case of negative - resolution parameters for example, which can happen with negative - weights). - - linear_bisection - Whether the bisectioning will be done on a linear or on a logarithmic - basis (if possible). - - number_iterations - Indicates the number of iterations of the algorithm to run. If negative - (or zero) the algorithm is run until a stable iteration. - - Examples - -------- - >>> G = ig.Graph.Famous('Zachary') - >>> optimiser = la.Optimiser() - >>> profile = optimiser.resolution_profile(G, la.CPMVertexPartition, - ... resolution_range=(0,1)) - """ - - # Helper function for cleaning values to be a stepwise function - def clean_stepwise(bisect_values): - # Check best partition for each resolution parameter - for res, bisect in bisect_values.items(): - best_bisect = bisect - best_quality = bisect.partition.quality(res) - for res2, bisect2 in bisect_values.items(): - if bisect2.partition.quality(res) > best_quality: - best_bisect = bisect2 - best_quality = bisect2.partition.quality(res) - if best_bisect != bisect: - bisect_values[res] = best_bisect - - # We only need to keep the changes in the bisection values - bisect_list = sorted([(res, part.bisect_value) for res, part in - bisect_values.items()], key=lambda x: x[0]) - for (res1, v1), (res2, v2) \ - in zip(bisect_list, - bisect_list[1:]): - # If two consecutive bisection values are the same, remove the second - # resolution parameter - if v1 == v2: - del bisect_values[res2] - - for res, bisect in bisect_values.items(): - bisect.partition.resolution_parameter = res - - # We assume here that the bisection values are - # monotonically decreasing with increasing resolution - # parameter values. - def ensure_monotonicity(bisect_values, new_res): - # First check if this partition improves on any other partition - for res, bisect_part in bisect_values.items(): - if bisect_values[new_res].partition.quality(res) > bisect_part.partition.quality(res): - bisect_values[res] = bisect_values[new_res] - # Then check what is best partition for the new_res - current_quality = bisect_values[new_res].partition.quality(new_res) - best_res = new_res - for res, bisect_part in bisect_values.items(): - if bisect_part.partition.quality(new_res) > current_quality: - best_res = new_res - bisect_values[new_res] = bisect_values[best_res] - - def find_partition(self, graph, partition_type, weights=None, **kwargs): - partition = partition_type(graph, - weights=weights, - **kwargs) - n_itr = 0 - while self.optimise_partition(partition) > 0 and \ - (n_itr < number_iterations or number_iterations <= 0): - n_itr += 1 - return partition - - assert issubclass(partition_type, LinearResolutionParameterVertexPartition), "Bisectioning only works on partitions with a linear resolution parameter." - # Start actual bisectioning - bisect_values = {} - stack_res_range = [] - # Push first range onto the stack - stack_res_range.append(resolution_range) - # Make sure the bisection values are calculated - # The namedtuple we will use in the bisection function - BisectPartition = namedtuple('BisectPartition', - ['partition', 'bisect_value']) - partition = find_partition(self, graph=graph, partition_type=partition_type, - weights=weights,resolution_parameter=resolution_range[0], - **kwargs) - bisect_values[resolution_range[0]] = BisectPartition(partition=partition, - bisect_value=bisect_func(partition)) - partition = find_partition(self, graph=graph, partition_type=partition_type, - weights=weights, resolution_parameter=resolution_range[1], **kwargs) - bisect_values[resolution_range[1]] = BisectPartition(partition=partition, - bisect_value=bisect_func(partition)) - # While stack of ranges not yet empty - try: - from tqdm import tqdm - progress = tqdm(total=float('inf')) - except: - progress = None - - while stack_res_range: - # Get the current range from the stack - current_range = stack_res_range.pop() - # Get the difference in bisection values - diff_bisect_value = abs(bisect_values[current_range[0]].bisect_value - - bisect_values[current_range[1]].bisect_value) - # Get the difference in resolution parameter (in log space if 0 is not in - # the interval (assuming only non-negative resolution parameters). - if current_range[0] > 0 and current_range[1] > 0 and not linear_bisection: - diff_resolution = log(current_range[1]/current_range[0]) - else: - diff_resolution = abs(current_range[1] - current_range[0]) - # Check if we still want to scan a smaller interval - # If we would like to bisect this interval - if diff_bisect_value > min_diff_bisect_value and \ - diff_resolution > min_diff_resolution: - # Determine new resolution value - if current_range[0] > 0 and current_range[1] > 0 and not linear_bisection: - new_res = sqrt(current_range[1]*current_range[0]) - else: - new_res = sum(current_range)/2.0 - # Bisect left (push on stack) - stack_res_range.append((current_range[0], new_res)) - # Bisect right (push on stack) - stack_res_range.append((new_res, current_range[1])) - # If we haven't scanned this resolution value yet, - # do so now - if not new_res in bisect_values: - partition = find_partition(self, graph, partition_type=partition_type, - weights=weights, resolution_parameter=new_res, **kwargs) - bisect_values[new_res] = BisectPartition(partition=partition, - bisect_value=bisect_func(partition)) - if progress is not None: - progress.update(1) - progress.set_postfix(resolution_parameter=new_res, refresh=False) - - # Because of stochastic differences in different runs, the monotonicity - # of the bisection values might be violated, so check for any - # inconsistencies - ensure_monotonicity(bisect_values, new_res) - - if progress is not None: - progress.close() - - # Ensure we only keep those resolution values for which - # the bisection values actually changed, instead of all of them - clean_stepwise(bisect_values) - # Use an ordered dict so that when iterating over it, the results appear in - # increasing order based on the resolution value. - return sorted((bisect.partition for res, bisect in - bisect_values.items()), key=lambda x: x.resolution_parameter) diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/RBConfigurationVertexPartition.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/RBConfigurationVertexPartition.cpp deleted file mode 100644 index e2d6f2d..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/RBConfigurationVertexPartition.cpp +++ /dev/null @@ -1,161 +0,0 @@ -#include "RBConfigurationVertexPartition.h" - -RBConfigurationVertexPartition::RBConfigurationVertexPartition(Graph* graph, - vector const& membership, double resolution_parameter) : - LinearResolutionParameterVertexPartition(graph, - membership, resolution_parameter) -{ } - -RBConfigurationVertexPartition::RBConfigurationVertexPartition(Graph* graph, - vector const& membership) : - LinearResolutionParameterVertexPartition(graph, - membership) -{ } - -RBConfigurationVertexPartition::RBConfigurationVertexPartition(Graph* graph, - double resolution_parameter) : - LinearResolutionParameterVertexPartition(graph, resolution_parameter) -{ } - -RBConfigurationVertexPartition::RBConfigurationVertexPartition(Graph* graph) : - LinearResolutionParameterVertexPartition(graph) -{ } - -RBConfigurationVertexPartition::~RBConfigurationVertexPartition() -{ } - -RBConfigurationVertexPartition* RBConfigurationVertexPartition::create(Graph* graph) -{ - return new RBConfigurationVertexPartition(graph, this->resolution_parameter); -} - -RBConfigurationVertexPartition* RBConfigurationVertexPartition::create(Graph* graph, vector const& membership) -{ - return new RBConfigurationVertexPartition(graph, membership, this->resolution_parameter); -} - -/***************************************************************************** - Returns the difference in modularity if we move a node to a new community -*****************************************************************************/ -double RBConfigurationVertexPartition::diff_move(size_t v, size_t new_comm) -{ - #ifdef DEBUG - cerr << "double RBConfigurationVertexPartition::diff_move(" << v << ", " << new_comm << ")" << endl; - #endif - size_t old_comm = this->_membership[v]; - double diff = 0.0; - double total_weight = this->graph->total_weight()*(2.0 - this->graph->is_directed()); - if (total_weight == 0.0) - return 0.0; - if (new_comm != old_comm) - { - #ifdef DEBUG - cerr << "\t" << "old_comm: " << old_comm << endl; - #endif - double w_to_old = this->weight_to_comm(v, old_comm); - #ifdef DEBUG - cerr << "\t" << "w_to_old: " << w_to_old << endl; - #endif - double w_from_old = this->weight_from_comm(v, old_comm); - #ifdef DEBUG - cerr << "\t" << "w_from_old: " << w_from_old << endl; - #endif - double w_to_new = this->weight_to_comm(v, new_comm); - #ifdef DEBUG - cerr << "\t" << "w_to_new: " << w_to_new << endl; - #endif - double w_from_new = this->weight_from_comm(v, new_comm); - #ifdef DEBUG - cerr << "\t" << "w_from_new: " << w_from_new << endl; - #endif - double k_out = this->graph->strength(v, IGRAPH_OUT); - #ifdef DEBUG - cerr << "\t" << "k_out: " << k_out << endl; - #endif - double k_in = this->graph->strength(v, IGRAPH_IN); - #ifdef DEBUG - cerr << "\t" << "k_in: " << k_in << endl; - #endif - double self_weight = this->graph->node_self_weight(v); - #ifdef DEBUG - cerr << "\t" << "self_weight: " << self_weight << endl; - #endif - double K_out_old = this->total_weight_from_comm(old_comm); - #ifdef DEBUG - cerr << "\t" << "K_out_old: " << K_out_old << endl; - #endif - double K_in_old = this->total_weight_to_comm(old_comm); - #ifdef DEBUG - cerr << "\t" << "K_in_old: " << K_in_old << endl; - #endif - double K_out_new = this->total_weight_from_comm(new_comm) + k_out; - #ifdef DEBUG - cerr << "\t" << "K_out_new: " << K_out_new << endl; - #endif - double K_in_new = this->total_weight_to_comm(new_comm) + k_in; - #ifdef DEBUG - cerr << "\t" << "K_in_new: " << K_in_new << endl; - cerr << "\t" << "total_weight: " << total_weight << endl; - #endif - double diff_old = (w_to_old - this->resolution_parameter*k_out*K_in_old/total_weight) + \ - (w_from_old - this->resolution_parameter*k_in*K_out_old/total_weight); - #ifdef DEBUG - cerr << "\t" << "diff_old: " << diff_old << endl; - #endif - double diff_new = (w_to_new + self_weight - this->resolution_parameter*k_out*K_in_new/total_weight) + \ - (w_from_new + self_weight - this->resolution_parameter*k_in*K_out_new/total_weight); - #ifdef DEBUG - cerr << "\t" << "diff_new: " << diff_new << endl; - #endif - diff = diff_new - diff_old; - #ifdef DEBUG - cerr << "\t" << "diff: " << diff << endl; - #endif - } - #ifdef DEBUG - cerr << "exit RBConfigurationVertexPartition::diff_move(" << v << ", " << new_comm << ")" << endl; - cerr << "return " << diff << endl << endl; - #endif - return diff; -} - -/***************************************************************************** - Give the modularity of the partition. - - We here use the unscaled version of modularity, in other words, we don"t - normalise by the number of edges. -******************************************************************************/ -double RBConfigurationVertexPartition::quality(double resolution_parameter) -{ - #ifdef DEBUG - cerr << "double ModularityVertexPartition::quality()" << endl; - #endif - double mod = 0.0; - - double m; - if (this->graph->is_directed()) - m = this->graph->total_weight(); - else - m = 2*this->graph->total_weight(); - - if (m == 0) - return 0.0; - - for (size_t c = 0; c < this->n_communities(); c++) - { - double w = this->total_weight_in_comm(c); - double w_out = this->total_weight_from_comm(c); - double w_in = this->total_weight_to_comm(c); - #ifdef DEBUG - size_t csize = this->csize(c); - cerr << "\t" << "Comm: " << c << ", size=" << csize << ", w=" << w << ", w_out=" << w_out << ", w_in=" << w_in << "." << endl; - #endif - mod += w - resolution_parameter*w_out*w_in/((this->graph->is_directed() ? 1.0 : 4.0)*this->graph->total_weight()); - } - double q = (2.0 - this->graph->is_directed())*mod; - #ifdef DEBUG - cerr << "exit double RBConfigurationVertexPartition::quality()" << endl; - cerr << "return " << q << endl << endl; - #endif - return q; -} diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/RBERVertexPartition.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/RBERVertexPartition.cpp deleted file mode 100644 index 9350a08..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/RBERVertexPartition.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#include "RBERVertexPartition.h" - -RBERVertexPartition::RBERVertexPartition(Graph* graph, - vector const& membership, double resolution_parameter) : - LinearResolutionParameterVertexPartition(graph, - membership, resolution_parameter) -{ } - -RBERVertexPartition::RBERVertexPartition(Graph* graph, - vector const& membership) : - LinearResolutionParameterVertexPartition(graph, - membership) -{ } - -RBERVertexPartition::RBERVertexPartition(Graph* graph, - double resolution_parameter) : - LinearResolutionParameterVertexPartition(graph, resolution_parameter) -{ } - -RBERVertexPartition::RBERVertexPartition(Graph* graph) : - LinearResolutionParameterVertexPartition(graph) -{ } - -RBERVertexPartition* RBERVertexPartition::create(Graph* graph) -{ - return new RBERVertexPartition(graph, this->resolution_parameter); -} - -RBERVertexPartition* RBERVertexPartition::create(Graph* graph, vector const& membership) -{ - return new RBERVertexPartition(graph, membership, this->resolution_parameter); -} - -RBERVertexPartition::~RBERVertexPartition() -{ } - -/******************************************************************************** - RBER implementation of a vertex partition - (which includes a resolution parameter). - ********************************************************************************/ -double RBERVertexPartition::diff_move(size_t v, size_t new_comm) -{ - #ifdef DEBUG - cerr << "double RBERVertexPartition::diff_move(" << v << ", " << new_comm << ")" << endl; - #endif - size_t old_comm = this->membership(v); - double diff = 0.0; - if (new_comm != old_comm) - { - double w_to_old = this->weight_to_comm(v, old_comm); - #ifdef DEBUG - cerr << "\t" << "w_to_old: " << w_to_old << endl; - #endif - double w_to_new = this->weight_to_comm(v, new_comm); - #ifdef DEBUG - cerr << "\t" << "w_to_new: " << w_to_new << endl; - #endif - double w_from_old = this->weight_from_comm(v, old_comm); - #ifdef DEBUG - cerr << "\t" << "w_from_old: " << w_from_old << endl; - #endif - double w_from_new = this->weight_from_comm(v, new_comm); - #ifdef DEBUG - cerr << "\t" << "w_from_new: " << w_from_new << endl; - #endif - size_t nsize = this->graph->node_size(v); - #ifdef DEBUG - cerr << "\t" << "nsize: " << nsize << endl; - #endif - size_t csize_old = this->csize(old_comm); - #ifdef DEBUG - cerr << "\t" << "csize_old: " << csize_old << endl; - #endif - size_t csize_new = this->csize(new_comm); - #ifdef DEBUG - cerr << "\t" << "csize_new: " << csize_new << endl; - #endif - double self_weight = this->graph->node_self_weight(v); - #ifdef DEBUG - cerr << "\t" << "self_weight: " << self_weight << endl; - cerr << "\t" << "density: " << this->graph->density() << endl; - #endif - double possible_edge_difference_old = 0.0; - if (this->graph->correct_self_loops()) - possible_edge_difference_old = nsize*(ptrdiff_t)(2.0*csize_old - nsize); - else - possible_edge_difference_old = nsize*(ptrdiff_t)(2.0*csize_old - nsize - 1.0); - #ifdef DEBUG - cerr << "\t" << "possible_edge_difference_old: " << possible_edge_difference_old << endl; - #endif - double diff_old = w_to_old + w_from_old - - self_weight - this->resolution_parameter*this->graph->density()*possible_edge_difference_old; - #ifdef DEBUG - cerr << "\t" << "diff_old: " << diff_old << endl; - #endif - double possible_edge_difference_new = 0.0; - if (this->graph->correct_self_loops()) - possible_edge_difference_new = nsize*(ptrdiff_t)(2.0*csize_new + nsize); - else - possible_edge_difference_new = nsize*(ptrdiff_t)(2.0*csize_new + nsize - 1.0); - #ifdef DEBUG - cerr << "\t" << "possible_edge_difference_new: " << possible_edge_difference_new << endl; - #endif - double diff_new = w_to_new + w_from_new + self_weight - - this->resolution_parameter*this->graph->density()*possible_edge_difference_new; - #ifdef DEBUG - cerr << "\t" << "diff_new: " << diff_new << endl; - #endif - diff = diff_new - diff_old; - #ifdef DEBUG - cerr << "\t" << "diff: " << diff << endl;; - #endif - } - #ifdef DEBUG - cerr << "exit RBERVertexPartition::diff_move(" << v << ", " << new_comm << ")" << endl; - cerr << "return " << diff << endl << endl; - #endif - return diff; -} - -double RBERVertexPartition::quality(double resolution_parameter) -{ - #ifdef DEBUG - cerr << "double RBERVertexPartition::quality()" << endl; - #endif - double mod = 0.0; - for (size_t c = 0; c < this->n_communities(); c++) - { - size_t csize = this->csize(c); - double w = this->total_weight_in_comm(c); - size_t comm_possible_edges = this->graph->possible_edges(csize); - - #ifdef DEBUG - cerr << "\t" << "Comm: " << c << ", w_c=" << w << ", n_c=" << csize << ", comm_possible_edges=" << comm_possible_edges << ", p=" << this->graph->density() << "." << endl; - #endif - mod += w - resolution_parameter*this->graph->density()*comm_possible_edges; - } - #ifdef DEBUG - cerr << "exit double RBERVertexPartition::quality()" << endl; - cerr << "return " << mod << endl << endl; - #endif - return (2.0 - this->graph->is_directed())*mod; -} diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/ResolutionParameterVertexPartition.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/ResolutionParameterVertexPartition.cpp deleted file mode 100644 index 56bb1e5..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/ResolutionParameterVertexPartition.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "ResolutionParameterVertexPartition.h" - -ResolutionParameterVertexPartition::ResolutionParameterVertexPartition(Graph* graph, - vector membership, double resolution_parameter) : - MutableVertexPartition(graph, - membership) -{ this->resolution_parameter = resolution_parameter; } - -ResolutionParameterVertexPartition::ResolutionParameterVertexPartition(Graph* graph, - vector membership) : - MutableVertexPartition(graph, - membership) -{ this->resolution_parameter = 1.0; } - -ResolutionParameterVertexPartition::ResolutionParameterVertexPartition(Graph* graph, - double resolution_parameter) : - MutableVertexPartition(graph) -{ this->resolution_parameter = resolution_parameter; } - -ResolutionParameterVertexPartition::ResolutionParameterVertexPartition(Graph* graph) : - MutableVertexPartition(graph) -{ this->resolution_parameter = 1.0; } - -ResolutionParameterVertexPartition::~ResolutionParameterVertexPartition() -{ } diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/SignificanceVertexPartition.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/SignificanceVertexPartition.cpp deleted file mode 100644 index dcdcb7b..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/SignificanceVertexPartition.cpp +++ /dev/null @@ -1,163 +0,0 @@ -#include "SignificanceVertexPartition.h" - -#ifdef DEBUG -#include -using std::cerr; -using std::endl; -#endif - -SignificanceVertexPartition::SignificanceVertexPartition(Graph* graph, - vector const& membership) : - MutableVertexPartition(graph, - membership) -{ } - -SignificanceVertexPartition::SignificanceVertexPartition(Graph* graph) : - MutableVertexPartition(graph) -{ } - -SignificanceVertexPartition* SignificanceVertexPartition::create(Graph* graph) -{ - return new SignificanceVertexPartition(graph); -} - -SignificanceVertexPartition* SignificanceVertexPartition::create(Graph* graph, vector const& membership) -{ - return new SignificanceVertexPartition(graph, membership); -} - -SignificanceVertexPartition::~SignificanceVertexPartition() -{ } - -double SignificanceVertexPartition::diff_move(size_t v, size_t new_comm) -{ - #ifdef DEBUG - cerr << "virtual double SignificanceVertexPartition::diff_move(" << v << ", " << new_comm << ")" << endl; - #endif - size_t old_comm = this->membership(v); - size_t nsize = this->graph->node_size(v); - double diff = 0.0; - if (new_comm != old_comm) - { - double normalise = (2.0 - this->graph->is_directed()); - double p = this->graph->density(); - #ifdef DEBUG - size_t n = this->graph->total_size(); - cerr << "\t" << "Community: " << old_comm << " => " << new_comm << "." << endl; - cerr << "\t" << "n: " << n << ", m: " << this->graph->total_weight() << ", p: " << p << "." << endl; - #endif - - //Old comm - size_t n_old = this->csize(old_comm); - size_t N_old = this->graph->possible_edges(n_old); - double m_old = this->total_weight_in_comm(old_comm); - double q_old = 0.0; - if (N_old > 0) - q_old = m_old/N_old; - #ifdef DEBUG - cerr << "\t" << "n_old: " << n_old << ", N_old: " << N_old << ", m_old: " << m_old << ", q_old: " << q_old - << ", KL: " << KL(q_old, p) << "." << endl; - #endif - // Old comm after move - size_t n_oldx = n_old - nsize; // It should not be possible that this becomes negative, so no need for ptrdiff_t here. - size_t N_oldx = this->graph->possible_edges(n_oldx); - double sw = this->graph->node_self_weight(v); - // Be careful to exclude the self weight here, because this is include in the weight_to_comm function. - double wtc = this->weight_to_comm(v, old_comm) - sw; - double wfc = this->weight_from_comm(v, old_comm) - sw; - #ifdef DEBUG - cerr << "\t" << "wtc: " << wtc << ", wfc: " << wfc << ", sw: " << sw << "." << endl; - #endif - double m_oldx = m_old - wtc/normalise - wfc/normalise - sw; - double q_oldx = 0.0; - if (N_oldx > 0) - q_oldx = m_oldx/N_oldx; - #ifdef DEBUG - cerr << "\t" << "n_oldx: " << n_oldx << ", N_oldx: " << N_oldx << ", m_oldx: " << m_oldx << ", q_oldx: " << q_oldx - << ", KL: " << KL(q_oldx, p) << "." << endl; - #endif - - // New comm - size_t n_new = this->csize(new_comm); - size_t N_new = this->graph->possible_edges(n_new); - double m_new = this->total_weight_in_comm(new_comm); - double q_new = 0.0; - if (N_new > 0) - q_new = m_new/N_new; - #ifdef DEBUG - cerr << "\t" << "n_new: " << n_new << ", N_new: " << N_new << ", m_new: " << m_new << ", q_new: " << q_new - << ", KL: " << KL(q_new, p) << "." << endl; - #endif - - // New comm after move - size_t n_newx = n_new + nsize; - size_t N_newx = this->graph->possible_edges(n_newx); - wtc = this->weight_to_comm(v, new_comm); - wfc = this->weight_from_comm(v, new_comm); - sw = this->graph->node_self_weight(v); - #ifdef DEBUG - cerr << "\t" << "wtc: " << wtc << ", wfc: " << wfc << ", sw: " << sw << "." << endl; - #endif - double m_newx = m_new + wtc/normalise + wfc/normalise + sw; - double q_newx = 0.0; - if (N_newx > 0) - q_newx = m_newx/N_newx; - #ifdef DEBUG - cerr << "\t" << "n_newx: " << n_newx << ", N_newx: " << N_newx << ", m_newx: " << m_newx - << ", q_newx: " << q_newx - << ", KL: " << KL(q_newx, p) << "." << endl; - #endif - - // Calculate actual diff - - if (N_oldx != N_new || q_oldx != q_new) - diff += (double)N_oldx*KLL(q_oldx, p) - (double)N_new*KLL(q_new, p); - - if (N_newx != N_old || q_newx != q_old) - diff += (double)N_newx*KLL(q_newx, p) - (double)N_old*KLL(q_old, p); - - #ifdef DEBUG - cerr << "\t" << "diff: " << diff << "." << endl; - #endif - } - #ifdef DEBUG - cerr << "exit double SignificanceVertexPartition::diff_move(" << v << ", " << new_comm << ")" << endl; - cerr << "return " << diff << endl << endl; - #endif - return diff; -} - -/******************************************************************************** - Calculate the significance of the partition. -*********************************************************************************/ -double SignificanceVertexPartition::quality() -{ - #ifdef DEBUG - cerr << "double SignificanceVertexPartition::quality()"; - size_t n = this->graph->total_size(); - #endif - double S = 0.0; - double p = this->graph->density(); - #ifdef DEBUG - cerr << "\t" << "n=" << n << ", m=" << this->graph->total_weight() << ", p=" << p << "." << endl; - #endif - for (size_t c = 0; c < this->n_communities(); c++) - { - size_t n_c = this->csize(c); - double m_c = this->total_weight_in_comm(c); - double p_c = 0.0; - size_t N_c = this->graph->possible_edges(n_c); - if (N_c > 0) - p_c = m_c/N_c; - #ifdef DEBUG - cerr << "\t" << "c=" << c << ", n_c=" << n_c << ", m_c=" << m_c << ", N_c=" << N_c - << ", p_c=" << p_c << ", p=" << p << ", KLL=" << KL(p_c, p) << "." << endl; - #endif - S += N_c*KLL(p_c, p); - } - #ifdef DEBUG - cerr << "exit SignificanceVertexPartition::quality()" << endl; - cerr << "return " << S << endl << endl; - #endif - return S; -} diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/SurpriseVertexPartition.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/SurpriseVertexPartition.cpp deleted file mode 100644 index 90a9ab8..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/SurpriseVertexPartition.cpp +++ /dev/null @@ -1,144 +0,0 @@ -#include "SurpriseVertexPartition.h" - -SurpriseVertexPartition::SurpriseVertexPartition(Graph* graph, - vector const& membership) : - MutableVertexPartition(graph, - membership) -{ } - -SurpriseVertexPartition::SurpriseVertexPartition(Graph* graph) : - MutableVertexPartition(graph) -{ } - -SurpriseVertexPartition* SurpriseVertexPartition::create(Graph* graph) -{ - return new SurpriseVertexPartition(graph); -} - - SurpriseVertexPartition* SurpriseVertexPartition::create(Graph* graph, vector const& membership) -{ - return new SurpriseVertexPartition(graph, membership); -} - -SurpriseVertexPartition::~SurpriseVertexPartition() -{ } - -double SurpriseVertexPartition::diff_move(size_t v, size_t new_comm) -{ - #ifdef DEBUG - cerr << "virtual double SurpriseVertexPartition::diff_move(" << v << ", " << new_comm << ")" << endl; - #endif - size_t old_comm = this->membership(v); - size_t nsize = this->graph->node_size(v); - #ifdef DEBUG - cerr << "\t" << "nsize: " << nsize << endl; - #endif - double diff = 0.0; - double m = this->graph->total_weight(); - - if (m == 0) - return 0.0; - - if (new_comm != old_comm) - { - double normalise = (2.0 - this->graph->is_directed()); - size_t n = this->graph->total_size(); - size_t n2 = this->graph->possible_edges(n); - - #ifdef DEBUG - cerr << "\t" << "Community: " << old_comm << " => " << new_comm << "." << endl; - cerr << "\t" << "m: " << m << ", n2: " << n2 << "." << endl; - #endif - - // Before move - double mc = this->total_weight_in_all_comms(); - size_t nc2 = this->total_possible_edges_in_all_comms(); - #ifdef DEBUG - cerr << "\t" << "mc: " << mc << ", nc2: " << nc2 << "." << endl; - #endif - - // To old comm - size_t n_old = this->csize(old_comm); - double sw = this->graph->node_self_weight(v); - double wtc = this->weight_to_comm(v, old_comm) - sw; - double wfc = this->weight_from_comm(v, old_comm) - sw; - #ifdef DEBUG - cerr << "\t" << "wtc: " << wtc << ", wfc: " << wfc << ", sw: " << sw << "." << endl; - #endif - double m_old = wtc/normalise + wfc/normalise + sw; - #ifdef DEBUG - cerr << "\t" << "m_old: " << m_old << ", n_old: " << n_old << "." << endl; - #endif - - // To new comm - size_t n_new = this->csize(new_comm); - wtc = this->weight_to_comm(v, new_comm); - wfc = this->weight_from_comm(v, new_comm); - sw = this->graph->node_self_weight(v); - #ifdef DEBUG - cerr << "\t" << "wtc: " << wtc << ", wfc: " << wfc << ", sw: " << sw << "." << endl; - #endif - double m_new = wtc/normalise + wfc/normalise + sw; - #ifdef DEBUG - cerr << "\t" << "m_new: " << m_new << ", n_new: " << n_new << "." << endl; - #endif - - double q = mc/m; - double s = (double)nc2/(double)n2; - double q_new = (mc - m_old + m_new)/m; - #ifdef DEBUG - cerr << "\t" << "mc - m_old + m_new=" << (mc - m_old + m_new) << endl; - #endif - double delta_nc2 = 2.0*nsize*(ptrdiff_t)(n_new - n_old + nsize)/normalise; - double s_new = (double)(nc2 + delta_nc2)/(double)n2; - #ifdef DEBUG - cerr << "\t" << "delta_nc2=" << delta_nc2 << endl; - #endif - #ifdef DEBUG - cerr << "\t" << "q:\t" << q << ", s:\t" << s << "." << endl; - cerr << "\t" << "q_new:\t" << q_new << ", s_new:\t" << s_new << "." << endl; - #endif - diff = m*(KLL(q_new, s_new) - KLL(q, s)); - - #ifdef DEBUG - cerr << "\t" << "diff: " << diff << "." << endl; - #endif - } - #ifdef DEBUG - cerr << "exit double SurpriseVertexPartition::diff_move(" << v << ", " << new_comm << ")" << endl; - cerr << "return " << diff << endl << endl; - #endif - return diff; -} - -double SurpriseVertexPartition::quality() -{ - #ifdef DEBUG - cerr << "double SurpriseVertexPartition::quality()" << endl; - #endif - - double mc = this->total_weight_in_all_comms(); - size_t nc2 = this->total_possible_edges_in_all_comms(); - double m = this->graph->total_weight(); - size_t n = this->graph->total_size(); - - if (m == 0) - return 0.0; - - size_t n2 = this->graph->possible_edges(n); - - #ifdef DEBUG - cerr << "\t" << "mc=" << mc << ", m=" << m << ", nc2=" << nc2 << ", n2=" << n2 << "." << endl; - #endif - double q = mc/m; - double s = (double)nc2/(double)n2; - #ifdef DEBUG - cerr << "\t" << "q:\t" << q << ", s:\t" << s << "." << endl; - #endif - double S = m*KLL(q,s); - #ifdef DEBUG - cerr << "exit SurpriseVertexPartition::quality()" << endl; - cerr << "return " << S << endl << endl; - #endif - return S; -} diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/VertexPartition.py b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/VertexPartition.py deleted file mode 100644 index 6f1a37d..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/VertexPartition.py +++ /dev/null @@ -1,1213 +0,0 @@ -import igraph as _ig -from . import _c_leiden -from .functions import _get_py_capsule - -class MutableVertexPartition(_ig.VertexClustering): - """ Contains a partition of a graph, derives from - :class:`ig.VertexClustering`. Please see the `documentation - `_ - of :class:`ig.VertexClustering` for more details about its functionality. - - This class contains the basic implementation for optimising a partition. - Specifically, it implements all the administration necessary to keep track of - the partition from various points of view. Internally, it keeps track of the - number of internal edges (or total weight), the size of the communities, the - total incoming degree (or weight) for a community, et cetera. - - In order to keep the administration up-to-date, all changes in a partition - should be done through - :func:`~VertexPartition.MutableVertexPartition.move_node` or - :func:`~VertexPartition.MutableVertexPartition.set_membership`. The first - moves a node from one community to another, and updates the administration. - The latter simply updates the membership vector and updates the - administration. - - The basic idea is that - :func:`~VertexPartition.MutableVertexPartition.diff_move` computes the - difference in the quality function if we would call - :func:`~VertexPartition.MutableVertexPartition.move_node` for the same move. - These functions are overridden in any derived classes to provide an actual - implementation. These functions are used by :class:`Optimiser` to optimise - the partition. - - .. warning:: This base class should never be used in practice, since only - derived classes provide an actual implementation. - - """ - - # Init - def __init__(self, graph, initial_membership=None): - """ - Parameters - ---------- - graph - The :class:`ig.Graph` on which this partition is defined. - - membership - The membership vector of this partition. ``Membership[i] = c`` implies that - node ``i`` is in community ``c``. If ``None``, it is initialised with a singleton - partition community, i.e. ``membership[i] = i``. - """ - if initial_membership is not None: - initial_membership = list(initial_membership) - - super(MutableVertexPartition, self).__init__(graph, initial_membership) - - @classmethod - def _FromCPartition(cls, partition): - n, directed, edges, weights, node_sizes = _c_leiden._MutableVertexPartition_get_py_igraph(partition) - graph = _ig.Graph(n=n, - directed=directed, - edges=edges, - edge_attrs={'weight': weights}, - vertex_attrs={'node_size': node_sizes}) - new_partition = cls(graph) - new_partition._partition = partition - new_partition._update_internal_membership() - return new_partition - - @classmethod - def FromPartition(cls, partition, **kwargs): - """ Create a new partition from an existing partition. - - Parameters - ---------- - partition - The :class:`~VertexPartition.MutableVertexPartition` to replicate. - - **kwargs - Any remaining keyword arguments will be passed on to the constructor of - the new partition. - - Notes - ----- - This may for example come in handy when determining the quality of a - partition using a different method. Suppose that we already have a - partition ``p`` and that we want to determine the Significance of that - partition. We can then simply use - - >>> p = la.find_partition(ig.Graph.Famous('Zachary'), - ... la.ModularityVertexPartition) - >>> sig = la.SignificanceVertexPartition.FromPartition(p).quality() - """ - new_partition = cls(partition.graph, partition.membership, **kwargs) - return new_partition - - def _update_internal_membership(self): - self._membership = _c_leiden._MutableVertexPartition_get_membership(self._partition) - # Reset the length of the object, i.e. the number of communities - if len(self._membership)>0: - self._len = max(m for m in self._membership if m is not None)+1 - else: - self._len = 0 - - def set_membership(self, membership): - """ Set membership. """ - _c_leiden._MutableVertexPartition_set_membership(self._partition, list(membership)) - self._update_internal_membership() - - # Calculate improvement *if* we move this node - def diff_move(self,v,new_comm): - """ Calculate the difference in the quality function if node ``v`` is - moved to community ``new_comm``. - - Parameters - ---------- - v - The node to move. - - new_comm - The community to move to. - - Returns - ------- - float - Difference in quality function. - - Notes - ----- - The difference returned by diff_move should be equivalent to first - determining the quality of the partition, then calling move_node, and then - determining again the quality of the partition and looking at the - difference. In other words - - >>> partition = la.find_partition(ig.Graph.Famous('Zachary'), - ... la.ModularityVertexPartition) - >>> diff = partition.diff_move(v=0, new_comm=0) - >>> q1 = partition.quality() - >>> partition.move_node(v=0, new_comm=0) - >>> q2 = partition.quality() - >>> round(diff, 10) == round(q2 - q1, 10) - True - - .. warning:: Only derived classes provide actual implementations, the base - class provides no implementation for this function. - - """ - return _c_leiden._MutableVertexPartition_diff_move(self._partition, v, new_comm) - - def aggregate_partition(self, membership_partition=None): - """ Aggregate the graph according to the current partition and provide a - default partition for it. - - The aggregated graph can then be found as a parameter of the partition - ``partition.graph``. - - Notes - ----- - This function contrasts to the function ``cluster_graph`` in igraph itself, - which also provides the aggregate graph, but we may require setting - the appropriate ``resolution_parameter``, ``weights`` and ``node_sizes``. - In particular, this function also ensures that the quality defined on the - aggregate partition is identical to the quality defined on the original - partition. - - Examples - -------- - >>> G = ig.Graph.Famous('Zachary') - >>> partition = la.find_partition(G, la.ModularityVertexPartition) - >>> aggregate_partition = partition.aggregate_partition(partition) - >>> aggregate_graph = aggregate_partition.graph - >>> aggregate_partition.quality() == partition.quality() - True - """ - partition_agg = self._FromCPartition(_c_leiden._MutableVertexPartition_aggregate_partition(self._partition)) - - if (not membership_partition is None): - membership = partition_agg.membership - for v in self.graph.vs: - membership[self.membership[v.index]] = membership_partition.membership[v.index] - partition_agg.set_membership(membership) - - return partition_agg - - def move_node(self,v,new_comm): - """ Move node ``v`` to community ``new_comm``. - - Parameters - ---------- - v - Node to move. - - new_comm - Community to move to. - - Examples - -------- - >>> G = ig.Graph.Famous('Zachary') - >>> partition = la.ModularityVertexPartition(G) - >>> partition.move_node(0, 1) - """ - _c_leiden._MutableVertexPartition_move_node(self._partition, v, new_comm) - # Make sure this move is also reflected in the membership vector of the python object - self._membership[v] = new_comm - self._modularity_dirty = True - - def from_coarse_partition(self, partition, coarse_node=None): - """ Update current partition according to coarser partition. - - Parameters - ---------- - partition : :class:`~VertexPartition.MutableVertexPartition` - The coarser partition used to update the current partition. - - coarse_node : list of int - The coarser node which represent the current node in the partition. - - Notes - ----- - This function is to be used to determine the correct partition for an - aggregated graph. In particular, suppose we move nodes and then get an - aggregate graph. - - >>> diff = optimiser.move_nodes(partition) - >>> aggregate_partition = partition.aggregate_partition() - - Now we also move nodes in the aggregate partition - - >>> diff = optimiser.move_nodes(aggregate_partition) - - Now we improved the quality function of ``aggregate_partition``, but this - is not yet reflected in the original ``partition``. We can thus call - - >>> partition.from_coarse_partition(aggregate_partition) - - so that ``partition`` now reflects the changes made to - ``aggregate_partition``. - - The ``coarse_node`` can be used it the ``aggregate_partition`` is not - defined based on the membership of this partition. In particular the - membership of this partition is defined as follows: - - >>> for v in G.vs: - ... partition.membership[v] = aggregate_partition.membership[coarse_node[v]] # doctest: +SKIP - - If ``coarse_node`` is :obj:`None` it is assumed the coarse node was defined - based on the membership of the current partition, so that - - >>> for v in G.vs: - ... partition.membership[v] = aggregate_partition.membership[partition.membership[v]] # doctest: +SKIP - - This can be useful when the aggregate partition is defined on a more - refined partition. - """ - # Read the coarser partition - _c_leiden._MutableVertexPartition_from_coarse_partition(self._partition, - partition.membership, coarse_node) - self._update_internal_membership() - - def renumber_communities(self): - """ Renumber the communities so that they are numbered in decreasing size. - - Notes - ----- - The sort is not necessarily stable. - """ - _c_leiden._MutableVertexPartition_renumber_communities(self._partition) - self._update_internal_membership() - - def quality(self): - """ The current quality of the partition. """ - return _c_leiden._MutableVertexPartition_quality(self._partition) - - def total_weight_in_comm(self, comm): - """ The total weight (i.e. number of edges) within a community. - - Parameters - ---------- - comm - Community - - See Also - -------- - :func:`~VertexPartition.MutableVertexPartition.total_weight_to_comm` - - :func:`~VertexPartition.MutableVertexPartition.total_weight_from_comm` - - :func:`~VertexPartition.MutableVertexPartition.total_weight_in_all_comms` - """ - return _c_leiden._MutableVertexPartition_total_weight_in_comm(self._partition, comm) - - def total_weight_from_comm(self, comm): - """ The total weight (i.e. number of edges) from a community. - - Parameters - ---------- - comm - Community - - Notes - ----- - This includes all edges, also the ones that are internal to a community. - Sometimes this is also referred to as the community (out)degree. - - See Also - -------- - :func:`~VertexPartition.MutableVertexPartition.total_weight_to_comm` - - :func:`~VertexPartition.MutableVertexPartition.total_weight_in_comm` - - :func:`~VertexPartition.MutableVertexPartition.total_weight_in_all_comms` - """ - return _c_leiden._MutableVertexPartition_total_weight_from_comm(self._partition, comm) - - def total_weight_to_comm(self, comm): - """ The total weight (i.e. number of edges) to a community. - - Parameters - ---------- - comm - Community - - Notes - ----- - This includes all edges, also the ones that are internal to a community. - Sometimes this is also referred to as the community (in)degree. - - See Also - -------- - :func:`~VertexPartition.MutableVertexPartition.total_weight_from_comm` - - :func:`~VertexPartition.MutableVertexPartition.total_weight_in_comm` - - :func:`~VertexPartition.MutableVertexPartition.total_weight_in_all_comms` - """ - return _c_leiden._MutableVertexPartition_total_weight_to_comm(self._partition, comm) - - def total_weight_in_all_comms(self): - """ The total weight (i.e. number of edges) within all communities. - - Notes - ----- - This should be equal to simply the sum of ``total_weight_in_comm`` for all communities. - - See Also - -------- - :func:`~VertexPartition.MutableVertexPartition.total_weight_to_comm` - - :func:`~VertexPartition.MutableVertexPartition.total_weight_from_comm` - - :func:`~VertexPartition.MutableVertexPartition.total_weight_in_comm` - """ - return _c_leiden._MutableVertexPartition_total_weight_in_all_comms(self._partition) - - def total_possible_edges_in_all_comms(self): - """ The total possible number of edges in all communities. - - Notes - ----- - If we denote by :math:`n_c` the number of nodes in community :math:`c`, - this is simply - - .. math :: \\sum_c \\binom{n_c}{2} - - """ - return _c_leiden._MutableVertexPartition_total_possible_edges_in_all_comms(self._partition) - - def weight_to_comm(self, v, comm): - """ The total number of edges (or sum of weights) from node ``v`` to - community ``comm``. - - See Also - -------- - :func:`~VertexPartition.MutableVertexPartition.weight_from_comm` - """ - return _c_leiden._MutableVertexPartition_weight_to_comm(self._partition, v, comm) - - def weight_from_comm(self, v, comm): - """ The total number of edges (or sum of weights) to node ``v`` from - community ``comm``. - - See Also - -------- - :func:`~VertexPartition.MutableVertexPartition.weight_to_comm` - """ - return _c_leiden._MutableVertexPartition_weight_from_comm(self._partition, v, comm) - -class HybridVertexParition(MutableVertexPartition): - """ Implements modularity. This quality function is well-defined only for positive edge weights. - - Notes - ----- - The quality function is - - .. math:: Q = \\frac{1}{2m} \\sum_{ij} \\left(A_{ij} - \\frac{k_i k_j}{2m} \\right)\\delta(\\sigma_i, \\sigma_j) - - where :math:`A` is the adjacency matrix, :math:`k_i` is the (weighted) degree - of node :math:`i`, :math:`m` is the total number of edges (or total edge - weight), :math:`\\sigma_i` denotes the community of node :math:`i` and - :math:`\\delta(\\sigma_i, \\sigma_j) = 1` if :math:`\\sigma_i = \\sigma_j` - and `0` otherwise. - - This can alternatively be formulated as a sum over communities: - - .. math:: Q = \\frac{1}{2m} \\sum_{c} \\left(m_c - \\frac{K_c^2}{4m} \\right) - - where :math:`m_c` is the number of internal edges (or total internal edge - weight) of community :math:`c` and :math:`K_c = \\sum_{i \\mid \\sigma_i = c} - k_i` is the total (weighted) degree of nodes in community :math:`c`. - - Note that for directed graphs a slightly different formulation is used, as - proposed by Leicht and Newman [2]: - - .. math:: Q = \\frac{1}{m} \\sum_{ij} \\left(A_{ij} - \\frac{k_i^\mathrm{out} k_j^\mathrm{in}}{m} \\right)\\delta(\\sigma_i, \\sigma_j), - - where :math:`k_i^\\mathrm{out}` and :math:`k_i^\\mathrm{in}` refers to - respectively the outdegree and indegree of node :math:`i`, and :math:`A_{ij}` - refers to an edge from :math:`i` to :math:`j`. - - References - ---------- - .. [1] Newman, M. E. J., & Girvan, M. (2004). Finding and evaluating - community structure in networks. Physical Review E, 69(2), 026113. - `10.1103/PhysRevE.69.026113 `_ - - .. [2] Leicht, E. A., & Newman, M. E. J. (2008). Community Structure - in Directed Networks. Physical Review Letters, 100(11), 118703. - `10.1103/PhysRevLett.100.118703 `_ - """ - def __init__(self, graph, initial_membership=None, weights=None, node_sizes=None, **kwargs): - """ - Parameters - ---------- - graph : :class:`ig.Graph` - Graph to define the partition on. - - initial_membership : list of int - Initial membership for the partition. If :obj:`None` then defaults to a - singleton partition. - - weights : list of double, or edge attribute - Weights of edges. Can be either an iterable or an edge attribute. - - node_sizes : list of int, or vertex attribute - Sizes of nodes are necessary to know the size of communities in aggregate - graphs. Usually this is set to 1 for all nodes, but in specific cases - this could be changed. - """ - if initial_membership is not None: - initial_membership = list(initial_membership) - - super(HybridVertexParition, self).__init__(graph, initial_membership) - pygraph_t = _get_py_capsule(graph) - - if weights is not None: - if isinstance(weights, str): - weights = graph.es[weights] - else: - # Make sure it is a list - weights = list(weights) - - if node_sizes is not None: - if isinstance(node_sizes, str): - node_sizes = graph.vs[node_sizes] - else: - # Make sure it is a list - node_sizes = list(node_sizes) - - if 'dataset' in kwargs and 'target' in kwargs: - if 'k1' in kwargs and 'k2' in kwargs: - k1 = kwargs.get('k1') - k2 = kwargs.get('k2') - else: - k1 = 0.1 - k2 = 0.9 - if 'k3' in kwargs and 'k4' in kwargs: - k3 = kwargs.get('k3') - k4 = kwargs.get('k4') - else: - k3 = 0.5 - k4 = 0.5 - - self._partition = _c_leiden._new_HybridVertexPartition(pygraph_t, - initial_membership, weights, node_sizes, - kwargs.get('dataset'), graph.vs['name'], - kwargs.get('target'), - k1, k2, k3, k4) - - else: - self._partition = _c_leiden._new_HybridVertexPartition(pygraph_t, - initial_membership, weights, node_sizes) - self._update_internal_membership() - - def __deepcopy__(self, memo): - n, directed, edges, weights, node_sizes = _c_leiden._HybridVertexPartition_get_py_igraph(self._partition) - new_partition = HybridVertexParition(self.graph, self.membership, weights, node_sizes) - return new_partition - -class ModularityVertexPartition(MutableVertexPartition): - """ Implements modularity. This quality function is well-defined only for positive edge weights. - - Notes - ----- - The quality function is - - .. math:: Q = \\frac{1}{2m} \\sum_{ij} \\left(A_{ij} - \\frac{k_i k_j}{2m} \\right)\\delta(\\sigma_i, \\sigma_j) - - where :math:`A` is the adjacency matrix, :math:`k_i` is the (weighted) degree - of node :math:`i`, :math:`m` is the total number of edges (or total edge - weight), :math:`\\sigma_i` denotes the community of node :math:`i` and - :math:`\\delta(\\sigma_i, \\sigma_j) = 1` if :math:`\\sigma_i = \\sigma_j` - and `0` otherwise. - - This can alternatively be formulated as a sum over communities: - - .. math:: Q = \\frac{1}{2m} \\sum_{c} \\left(m_c - \\frac{K_c^2}{4m} \\right) - - where :math:`m_c` is the number of internal edges (or total internal edge - weight) of community :math:`c` and :math:`K_c = \\sum_{i \\mid \\sigma_i = c} - k_i` is the total (weighted) degree of nodes in community :math:`c`. - - Note that for directed graphs a slightly different formulation is used, as - proposed by Leicht and Newman [2]: - - .. math:: Q = \\frac{1}{m} \\sum_{ij} \\left(A_{ij} - \\frac{k_i^\mathrm{out} k_j^\mathrm{in}}{m} \\right)\\delta(\\sigma_i, \\sigma_j), - - where :math:`k_i^\\mathrm{out}` and :math:`k_i^\\mathrm{in}` refers to - respectively the outdegree and indegree of node :math:`i`, and :math:`A_{ij}` - refers to an edge from :math:`i` to :math:`j`. - - References - ---------- - .. [1] Newman, M. E. J., & Girvan, M. (2004). Finding and evaluating - community structure in networks. Physical Review E, 69(2), 026113. - `10.1103/PhysRevE.69.026113 `_ - - .. [2] Leicht, E. A., & Newman, M. E. J. (2008). Community Structure - in Directed Networks. Physical Review Letters, 100(11), 118703. - `10.1103/PhysRevLett.100.118703 `_ - """ - def __init__(self, graph, initial_membership=None, weights=None): - """ - Parameters - ---------- - graph : :class:`ig.Graph` - Graph to define the partition on. - - initial_membership : list of int - Initial membership for the partition. If :obj:`None` then defaults to a - singleton partition. - - weights : list of double, or edge attribute - Weights of edges. Can be either an iterable or an edge attribute. - """ - if initial_membership is not None: - initial_membership = list(initial_membership) - - super(ModularityVertexPartition, self).__init__(graph, initial_membership) - pygraph_t = _get_py_capsule(graph) - - if weights is not None: - if isinstance(weights, str): - weights = graph.es[weights] - else: - # Make sure it is a list - weights = list(weights) - - self._partition = _c_leiden._new_ModularityVertexPartition(pygraph_t, - initial_membership, weights) - self._update_internal_membership() - - def __deepcopy__(self, memo): - n, directed, edges, weights, node_sizes = _c_leiden._MutableVertexPartition_get_py_igraph(self._partition) - new_partition = ModularityVertexPartition(self.graph, self.membership, weights) - return new_partition - -class SurpriseVertexPartition(MutableVertexPartition): - """ Implements (asymptotic) Surprise. This quality function is well-defined only for positive edge weights. - - Notes - ----- - The quality function is - - .. math:: Q = m D(q \\parallel \\langle q \\rangle) - - where :math:`m` is the number of edges, - - .. math:: q = \\frac{\\sum_c m_c}{m}, - - is the fraction of internal edges, - - .. math:: \\langle q \\rangle = \\frac{\\sum_c \\binom{n_c}{2}}{\\binom{n}{2}} - - is the expected fraction of internal edges, and finally - - .. math:: D(x \\parallel y) = x \\ln \\frac{x}{y} + (1 - x) \\ln \\frac{1 - x}{1 - y} - - is the binary Kullback-Leibler divergence. - - For directed graphs we can multiplying the binomials by 2, and this leaves - :math:`\\langle q \\rangle` unchanged, so that we can simply use the same - formulation. For weighted graphs we can simply count the total internal - weight instead of the total number of edges for :math:`q`, while - :math:`\\langle q \\rangle` remains unchanged. - - References - ---------- - .. [1] Traag, V. A., Aldecoa, R., & Delvenne, J.-C. (2015). Detecting - communities using asymptotical surprise. Physical Review E, 92(2), - 022816. - `10.1103/PhysRevE.92.022816 `_ - """ - - def __init__(self, graph, initial_membership=None, weights=None, node_sizes=None): - """ - Parameters - ---------- - graph : :class:`ig.Graph` - Graph to define the partition on. - - initial_membership : list of int - Initial membership for the partition. If :obj:`None` then defaults to a - singleton partition. - - weights : list of double, or edge attribute - Weights of edges. Can be either an iterable or an edge attribute. - - node_sizes : list of int, or vertex attribute - The quality function takes into account the size of a community, which - is defined as the sum over the sizes of each individual node. By default, - the node sizes are set to 1, meaning that the size of a community equals - the number of nodes of a community. If a node already represents an - aggregation, this could be reflect in its node size. - """ - if initial_membership is not None: - initial_membership = list(initial_membership) - - super(SurpriseVertexPartition, self).__init__(graph, initial_membership) - - pygraph_t = _get_py_capsule(graph) - - if weights is not None: - if isinstance(weights, str): - weights = graph.es[weights] - else: - # Make sure it is a list - weights = list(weights) - - if node_sizes is not None: - if isinstance(node_sizes, str): - node_sizes = graph.vs[node_sizes] - else: - # Make sure it is a list - node_sizes = list(node_sizes) - - self._partition = _c_leiden._new_SurpriseVertexPartition(pygraph_t, - initial_membership, weights, node_sizes) - self._update_internal_membership() - - def __deepcopy__(self, memo): - n, directed, edges, weights, node_sizes = _c_leiden._MutableVertexPartition_get_py_igraph(self._partition) - new_partition = SurpriseVertexPartition(self.graph, self.membership, weights, node_sizes) - return new_partition - -class SignificanceVertexPartition(MutableVertexPartition): - """ Implements Significance. This quality function is well-defined only for unweighted graphs. - - Notes - ----- - The quality function is - - .. math:: Q = \\sum_c \\binom{n_c}{2} D(p_c \\parallel p) - - where :math:`n_c` is the number of nodes in community :math:`c`, - - .. math:: p_c = \\frac{m_c}{\\binom{n_c}{2}}, - - is the density of community :math:`c`, - - .. math:: p = \\frac{m}{\\binom{n}{2}} - - is the overall density of the graph, and finally - - .. math:: D(x \\parallel y) = x \\ln \\frac{x}{y} + (1 - x) \\ln \\frac{1 - x}{1 - y} - - is the binary Kullback-Leibler divergence. - - For directed graphs simply multiply the binomials by 2. The expected - Significance in Erdos-Renyi graphs behaves roughly as :math:`\\frac{1}{2} n - \\ln n` for both directed and undirected graphs in this formulation. - - .. warning:: This method is not suitable for weighted graphs. - - References - ---------- - .. [1] Traag, V. A., Krings, G., & Van Dooren, P. (2013). Significant scales in community structure. - Scientific Reports, 3, 2930. `10.1038/srep02930 `_ - """ - def __init__(self, graph, initial_membership=None, node_sizes=None): - """ - Parameters - ---------- - graph : :class:`ig.Graph` - Graph to define the partition on. - - initial_membership : list of int - Initial membership for the partition. If :obj:`None` then defaults to a - singleton partition. - - node_sizes : list of int, or vertex attribute - The quality function takes into account the size of a community, which - is defined as the sum over the sizes of each individual node. By default, - the node sizes are set to 1, meaning that the size of a community equals - the number of nodes of a community. If a node already represents an - aggregation, this could be reflect in its node size. - """ - if initial_membership is not None: - initial_membership = list(initial_membership) - - super(SignificanceVertexPartition, self).__init__(graph, initial_membership) - - pygraph_t = _get_py_capsule(graph) - - if node_sizes is not None: - if isinstance(node_sizes, str): - node_sizes = graph.vs[node_sizes] - else: - # Make sure it is a list - node_sizes = list(node_sizes) - - self._partition = _c_leiden._new_SignificanceVertexPartition(pygraph_t, initial_membership, node_sizes) - self._update_internal_membership() - - def __deepcopy__(self, memo): - n, directed, edges, weights, node_sizes = _c_leiden._MutableVertexPartition_get_py_igraph(self._partition) - new_partition = SignificanceVertexPartition(self.graph, self.membership, node_sizes) - return new_partition - -class LinearResolutionParameterVertexPartition(MutableVertexPartition): - """ Some quality functions have a linear resolution parameter, for which the - basis is implemented here. - - With a linear resolution parameter, we mean that the objective function has - the form: - - .. math:: Q = E - \\gamma F - - where :math:`\\gamma` is some resolution parameter and :math:`E` and - :math:`F` arbitrary other functions of the partition. - - One thing that can be easily done on these type of quality functions, is - bisectioning on the gamma function (also assuming that :math:`E` is a - stepwise decreasing monotonic function, e.g. as for - :class:`CPMVertexPartition`). - """ - def __init__(self, graph, initial_membership=None): - if initial_membership is not None: - initial_membership = list(initial_membership) - - super(LinearResolutionParameterVertexPartition, self).__init__(graph, initial_membership) - - #########################################################3 - # resolution parameter - @property - def resolution_parameter(self): - """ Resolution parameter. """ - return _c_leiden._ResolutionParameterVertexPartition_get_resolution(self._partition) - - @resolution_parameter.setter - def resolution_parameter(self, value): - return _c_leiden._ResolutionParameterVertexPartition_set_resolution(self._partition, value) - - def bisect_value(self): - """ Give the value on which we can perform bisectioning. - - If p1 and p2 are two different optimal partitions for two different - resolution parameters g1 and g2, then if p1.bisect_value() == - p2.bisect_value() the two partitions should be optimal for both g1 and g2. - """ - return self.total_weight_in_all_comms() - - def quality(self, resolution_parameter=None): - return _c_leiden._ResolutionParameterVertexPartition_quality(self._partition, resolution_parameter) - -class RBERVertexPartition(LinearResolutionParameterVertexPartition): - """ Implements Reichardt and Bornholdt’s Potts model with an Erdős-Rényi null model. - This quality function is well-defined only for positive edge weights. - This quality function uses a linear resolution parameter. - - Notes - ----- - The quality function is - - .. math:: Q = \\sum_{ij} \\left(A_{ij} - \\gamma p \\right)\\delta(\\sigma_i, \\sigma_j) - - where :math:`A` is the adjacency matrix, - - .. math:: p = \\frac{m}{\\binom{n}{2}} - - is the overall density of the graph, :math:`\\sigma_i` denotes the community - of node :math:`i`, :math:`\\delta(\\sigma_i, \\sigma_j) = 1` if - :math:`\\sigma_i = \\sigma_j` and `0` otherwise, and, finally :math:`\\gamma` - is a resolution parameter. - - This can alternatively be formulated as a sum over communities: - - .. math:: Q = \\sum_{c} \\left[m_c - \\gamma p \\binom{n_c}{2} \\right] - - where :math:`m_c` is the number of internal edges of community :math:`c` and - :math:`n_c` the number of nodes in community :math:`c`. - - References - ---------- - .. [1] Reichardt, J., & Bornholdt, S. (2006). Statistical mechanics of - community detection. Physical Review E, 74(1), 016110. - `10.1103/PhysRevE.74.016110 `_ - """ - def __init__(self, graph, initial_membership=None, weights=None, node_sizes=None, resolution_parameter=1.0): - """ - Parameters - ---------- - graph : :class:`ig.Graph` - Graph to define the partition on. - - initial_membership : list of int - Initial membership for the partition. If :obj:`None` then defaults to a - singleton partition. - - weights : list of double, or edge attribute - Weights of edges. Can be either an iterable or an edge attribute. - - node_sizes : list of int, or vertex attribute - The quality function takes into account the size of a community, which - is defined as the sum over the sizes of each individual node. By default, - the node sizes are set to 1, meaning that the size of a community equals - the number of nodes of a community. If a node already represents an - aggregation, this could be reflect in its node size. - - resolution_parameter : double - Resolution parameter. - """ - if initial_membership is not None: - initial_membership = list(initial_membership) - - super(RBERVertexPartition, self).__init__(graph, initial_membership) - - pygraph_t = _get_py_capsule(graph) - - if weights is not None: - if isinstance(weights, str): - weights = graph.es[weights] - else: - # Make sure it is a list - weights = list(weights) - - if node_sizes is not None: - if isinstance(node_sizes, str): - node_sizes = graph.vs[node_sizes] - else: - # Make sure it is a list - node_sizes = list(node_sizes) - - self._partition = _c_leiden._new_RBERVertexPartition(pygraph_t, - initial_membership, weights, node_sizes, resolution_parameter) - self._update_internal_membership() - - def __deepcopy__(self, memo): - n, directed, edges, weights, node_sizes = _c_leiden._MutableVertexPartition_get_py_igraph(self._partition) - new_partition = RBERVertexPartition(self.graph, self.membership, weights, node_sizes, self.resolution_parameter) - return new_partition - -class RBConfigurationVertexPartition(LinearResolutionParameterVertexPartition): - """ Implements Reichardt and Bornholdt's Potts model with a configuration null model. - This quality function is well-defined only for positive edge weights. - This quality function uses a linear resolution parameter. - - Notes - ----- - The quality function is - - .. math:: Q = \\sum_{ij} \\left(A_{ij} - \\gamma \\frac{k_i k_j}{2m} \\right)\\delta(\\sigma_i, \\sigma_j) - - where :math:`A` is the adjacency matrix, :math:`k_i` is the (weighted) degree - of node :math:`i`, :math:`m` is the total number of edges (or total edge - weight), :math:`\\sigma_i` denotes the community of node :math:`i` and - :math:`\\delta(\\sigma_i, \\sigma_j) = 1` if :math:`\\sigma_i = \\sigma_j` - and `0` otherwise. - - This can alternatively be formulated as a sum over communities: - - .. math:: Q = \\sum_{c} \\left(m_c - \\gamma \\frac{K_c^2}{4m} \\right) - - where :math:`m_c` is the number of internal edges (or total internal edge - weight) of community :math:`c` and :math:`K_c = \\sum_{i \\mid \\sigma_i = c} - k_i` is the total (weighted) degree of nodes in community :math:`c`. - - Note that for directed graphs a slightly different formulation is used, as - proposed by Leicht and Newman [2]: - - .. math:: Q = \\sum_{ij} \\left(A_{ij} - \\gamma \\frac{k_i^\mathrm{out} k_j^\mathrm{in}}{m} \\right)\\delta(\\sigma_i, \\sigma_j), - - where :math:`k_i^\\mathrm{out}` and :math:`k_i^\\mathrm{in}` refers to - respectively the outdegree and indegree of node :math:`i`, and :math:`A_{ij}` - refers to an edge from :math:`i` to :math:`j`. - - Note that this is the same as :class:`ModularityVertexPartition` when setting - :math:`\\gamma=1` and normalising by :math:`2m`, or :math:`m` for directed - graphs. - - References - ---------- - .. [1] Reichardt, J., & Bornholdt, S. (2006). Statistical mechanics of - community detection. Physical Review E, 74(1), 016110. - `10.1103/PhysRevE.74.016110 `_ - - .. [2] Leicht, E. A., & Newman, M. E. J. (2008). Community Structure - in Directed Networks. Physical Review Letters, 100(11), 118703. - `10.1103/PhysRevLett.100.118703 `_ - - """ - def __init__(self, graph, initial_membership=None, weights=None, resolution_parameter=1.0): - """ - Parameters - ---------- - graph : :class:`ig.Graph` - Graph to define the partition on. - - initial_membership : list of int - Initial membership for the partition. If :obj:`None` then defaults to a - singleton partition. - - weights : list of double, or edge attribute - Weights of edges. Can be either an iterable or an edge attribute. - - resolution_parameter : double - Resolution parameter. - """ - if initial_membership is not None: - initial_membership = list(initial_membership) - - super(RBConfigurationVertexPartition, self).__init__(graph, initial_membership) - - pygraph_t = _get_py_capsule(graph) - - if weights is not None: - if isinstance(weights, str): - weights = graph.es[weights] - else: - # Make sure it is a list - weights = list(weights) - - self._partition = _c_leiden._new_RBConfigurationVertexPartition(pygraph_t, - initial_membership, weights, resolution_parameter) - self._update_internal_membership() - - def __deepcopy__(self, memo): - n, directed, edges, weights, node_sizes = _c_leiden._MutableVertexPartition_get_py_igraph(self._partition) - new_partition = RBConfigurationVertexPartition(self.graph, self.membership, weights, self.resolution_parameter) - return new_partition - -class CPMVertexPartition(LinearResolutionParameterVertexPartition): - """ Implements the Constant Potts Model (CPM). - This quality function is well-defined for both positive and negative edge weights. - This quality function uses a linear resolution parameter. - - Notes - ----- - The Constant Potts Model (CPM) quality function is - - .. math:: Q = \\sum_{ij} \\left(A_{ij} - \\gamma \\right)\\delta(\\sigma_i, \\sigma_j) - - where :math:`A` is the adjacency matrix, :math:`\\sigma_i` denotes the - community of node :math:`i`, :math:`\\delta(\\sigma_i, \\sigma_j) = 1` if - :math:`\\sigma_i = \\sigma_j` and `0` otherwise, and, finally :math:`\\gamma` - is a resolution parameter. - - This can alternatively be formulated as a sum over communities: - - .. math:: Q = \\sum_{c} \\left[m_c - \\gamma \\binom{n_c}{2} \\right] - - where :math:`m_c` is the number of internal edges of community :math:`c` and - :math:`n_c` the number of nodes in community :math:`c`. - - The resolution parameter :math:`\\gamma` for this functions has a - particularly simple interpretation. The internal density of communities - - .. math:: p_c = \\frac{m_c}{\\binom{n_c}{2}} \\geq \\gamma - - is higher than :math:`\\gamma`, while the external density - - .. math:: p_{cd} = \\frac{m_{cd}}{n_c n_d} \\leq \\gamma - - is lower than :math:`\\gamma`. In other words, choosing a particular - :math:`\\gamma` corresponds to choosing to find communities of a particular - density, and as such defines communities. Finally, the definition of a - community is in a sense independent of the actual graph, which is not the - case for any of the other methods (see the reference for more detail). - - References - ---------- - .. [1] Traag, V. A., Van Dooren, P., & Nesterov, Y. (2011). Narrow scope for - resolution-limit-free community detection. Physical Review E, 84(1), - 016114. `10.1103/PhysRevE.84.016114 `_ - """ - def __init__(self, graph, initial_membership=None, weights=None, node_sizes=None, resolution_parameter=1.0): - """ - Parameters - ---------- - graph : :class:`ig.Graph` - Graph to define the partition on. - - initial_membership : list of int - Initial membership for the partition. If :obj:`None` then defaults to a - singleton partition. - - weights : list of double, or edge attribute - Weights of edges. Can be either an iterable or an edge attribute. - - node_sizes : list of int, or vertex attribute - The quality function takes into account the size of a community, which - is defined as the sum over the sizes of each individual node. By default, - the node sizes are set to 1, meaning that the size of a community equals - the number of nodes of a community. If a node already represents an - aggregation, this could be reflect in its node size. - - resolution_parameter : double - Resolution parameter. - """ - if initial_membership is not None: - initial_membership = list(initial_membership) - - super(CPMVertexPartition, self).__init__(graph, initial_membership) - - pygraph_t = _get_py_capsule(graph) - - if weights is not None: - if isinstance(weights, str): - weights = graph.es[weights] - else: - # Make sure it is a list - weights = list(weights) - - if node_sizes is not None: - if isinstance(node_sizes, str): - node_sizes = graph.vs[node_sizes] - else: - # Make sure it is a list - node_sizes = list(node_sizes) - - self._partition = _c_leiden._new_CPMVertexPartition(pygraph_t, - initial_membership, weights, node_sizes, resolution_parameter) - self._update_internal_membership() - - def __deepcopy__(self, memo): - n, directed, edges, weights, node_sizes = _c_leiden._MutableVertexPartition_get_py_igraph(self._partition) - new_partition = CPMVertexPartition(self.graph, self.membership, weights, node_sizes, self.resolution_parameter) - return new_partition - - @classmethod - def Bipartite(cls, graph, resolution_parameter_01, - resolution_parameter_0 = 0, resolution_parameter_1 = 0, - degree_as_node_size=False, types='type', **kwargs): - """ Create three layers for bipartite partitions. - - This creates three layers for bipartite partition necessary for detecting - communities in bipartite networks. These three layers should be passed to - :func:`Optimiser.optimise_partition_multiplex` with - ``layer_weights=[1,-1,-1]``. See `Notes <#notes-bipartite>`_ for more details. - - Parameters - ---------- - graph : :class:`ig.Graph` - Graph to define the bipartite partitions on. - - resolution_parameter_01 : double - Resolution parameter for in between two classes. - - resolution_parameter_0 : double - Resolution parameter for class 0. - - resolution_parameter_1 : double - Resolution parameter for class 1. - - degree_as_node_size : boolean - If ``True`` use degree as node size instead of 1, to mimic modularity, - see `Notes <#notes-bipartite>`_. - - types : vertex attribute or list - Indicator of the class for each vertex. If not 0, 1, it is automatically - converted. - - **kwargs - Additional arguments passed on to default constructor of - :class:`CPMVertexPartition`. - - Returns - ------- - :class:`ig.CPMVertexPartition` - partition containing the bipartite graph and correct node sizes. - - :class:`ig.CPMVertexPartition` - partition for type 0, containing the correct node sizes for type 0. - - :class:`ig.CPMVertexPartition` - partition for type 1, containing the correct node sizes for type 1. - - - .. _notes-bipartite: - - Notes - ----- - - For bipartite networks, we would like to be able to set three different - resolution parameters: one for within each class :math:`\\gamma_0, - \\gamma_1`, and one for the links between classes, :math:`\\gamma_{01}`. - Then the formulation would be - - .. math:: Q = \\sum_{ij} - [A_{ij} - - (\\gamma_0\\delta(s_i,0) + \\gamma_1\\delta(s_i,1)) \\delta(s_i,s_j) - - \\gamma_{01}(1 - \\delta(s_i, s_j)) - ]\\delta(\\sigma_i, \\sigma_j) - - In terms of communities this is - - .. math:: Q = \\sum_c (e_c - - \\gamma_{01} 2 n_c(0) n_c(1) - - \\gamma_0 n^2_c(0) - - \\gamma_1 n^2_c(1)) - - where :math:`n_c(0)` is the number of nodes in community :math:`c` of class 0 - (and similarly for 1) and :math:`e_c` is the number of edges within community - :math:`c`. We denote by :math:`n_c = n_c(0) + n_c(1)` the total number of nodes - in community :math:`c`. - - We achieve this by creating three layers : (1) all nodes have ``node_size = - 1`` and all relevant links; (2) only nodes of class 0 have ``node_size = - 1`` and no links; (3) only nodes of class 1 have ``node_size = 1`` and no - links. If we add the first with resolution parameter :math:`\\gamma_{01}`, - and the others with resolution parameters :math:`\\gamma_{01} - \\gamma_0` - and :math:`\\gamma_{01} - \\gamma_1`, but the latter two with a layer - weight of -1 while the first layer has layer weight 1, we obtain the - following: - - .. math:: Q &= \\sum_c (e_c - \\gamma_{01} n_c^2) - -\\sum_c (- (\\gamma_{01} - \\gamma_0) n_c(0)^2) - -\\sum_c (- (\\gamma_{01} - \\gamma_1) n_c(1)^2) \\\\ - &= \\sum_c [e_c - \\gamma_{01} 2 n_c(0) n_c(1) - - \\gamma_{01} n_c(0)^2 - - \\gamma_{01} n_c(1)^2) - + ( \\gamma_{01} - \\gamma_0) n_c(0)^2 - + ( \\gamma_{01} - \\gamma_1) n_c(1)^2 - ] \\\\ - &= \\sum_c [e_c - \\gamma_{01} 2 n_c(0) n_c(1) - - \\gamma_{0} n_c(0)^2 - - \\gamma_{1} n_c(1)^2] - - Although the derivation above is using :math:`n_c^2`, implicitly assuming a - direct graph with self-loops, similar derivations can be made for - undirected graphs using :math:`\\binom{n_c}{2}`, but the notation is then - somewhat more convoluted. - - If we set node sizes equal to the degree, we get something similar to - modularity, except that the resolution parameter should still be divided by - :math:`2m`. In particular, in general (i.e. not specifically for bipartite - graph) if ``node_sizes=G.degree()`` we then obtain - - .. math:: Q = \\sum_{ij} A_{ij} - \\gamma k_i k_j - - In the case of bipartite graphs something similar is obtained, but then - correctly adapted (as long as the resolution parameter is also - appropriately rescaled). - - .. note:: This function is not suited for directed graphs in the case of - using the degree as node sizes. - """ - - if types is not None: - if isinstance(types, str): - types = graph.vs[types] - else: - # Make sure it is a list - types = list(types) - - if set(types) != set([0, 1]): - new_type = _ig.UniqueIdGenerator() - types = [new_type[t] for t in types] - - if set(types) != set([0, 1]): - raise ValueError("More than one type specified.") - - if degree_as_node_size: - if (graph.is_directed()): - raise ValueError("This method is not suitable for directed graphs " + - "when using degree as node sizes.") - node_sizes = graph.degree() - else: - node_sizes = [1]*graph.vcount() - - partition_01 = cls(graph, - node_sizes=node_sizes, - resolution_parameter=resolution_parameter_01, - **kwargs) - H_0 = graph.subgraph_edges([], delete_vertices=False) - partition_0 = cls(H_0, weights=None, - node_sizes=[s if t == 0 else 0 - for v, s, t in zip(graph.vs,node_sizes,types)], - resolution_parameter=resolution_parameter_01 - resolution_parameter_0) - H_1 = graph.subgraph_edges([], delete_vertices=False) - partition_1 = cls(H_1, weights=None, - node_sizes=[s if t == 1 else 0 - for v, s, t in zip(graph.vs,node_sizes,types)], - resolution_parameter=resolution_parameter_01 - resolution_parameter_1) - return partition_01, partition_0, partition_1 diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/__init__.py b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/__init__.py deleted file mode 100644 index 075160f..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/__init__.py +++ /dev/null @@ -1,58 +0,0 @@ -# -*- coding: utf-8 -*- -r""" This package implements the Leiden algorithm in ``C++`` and exposes it to -python. It relies on ``(python-)igraph`` for it to function. Besides the -relative flexibility of the implementation, it also scales well, and can be run -on graphs of millions of nodes (as long as they can fit in memory). Each method -is represented by a different class, all of whom derive from -:class:`~leidenalg.VertexPartition.MutableVertexPartition`. In addition, -multiplex graphs are supported as layers, which also supports multislice -representations. - -Examples --------- - -The simplest example just finds a partition using modularity - - >>> G = ig.Graph.Tree(100, 3) - >>> partition = la.find_partition(G, la.ModularityVertexPartition) - -Alternatively, one can access the different optimisation routines individually -and construct partitions oneself. These partitions can then be optimised by -constructing an :class:`Optimiser` object and running -:func:`~Optimiser.optimise_partition`. - - >>> G = ig.Graph.Tree(100, 3) - >>> partition = la.CPMVertexPartition(G, resolution_parameter = 0.1) - >>> optimiser = la.Optimiser() - >>> diff = optimiser.optimise_partition(partition) - -The :class:`Optimiser` class contains also the different subroutines that are -used internally by :func:`~Optimiser.optimise_partition`. In addition, through -the Optimiser class there are various options available for changing some of -the optimisation procedure which can affect both speed and quality, which are -not immediately available in :func:`leidenalg.find_partition`. -""" -from .functions import ALL_COMMS -from .functions import ALL_NEIGH_COMMS -from .functions import RAND_COMM -from .functions import RAND_NEIGH_COMM - -from .functions import MOVE_NODES -from .functions import MERGE_NODES - -from .functions import find_partition -from .functions import find_partition_multiplex -from .functions import find_partition_temporal -from .functions import slices_to_layers -from .functions import time_slices_to_layers - -from .Optimiser import Optimiser -from .VertexPartition import HybridVertexParition -from .VertexPartition import ModularityVertexPartition -from .VertexPartition import SurpriseVertexPartition -from .VertexPartition import SignificanceVertexPartition -from .VertexPartition import RBERVertexPartition -from .VertexPartition import RBConfigurationVertexPartition -from .VertexPartition import CPMVertexPartition - -from .version import * diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/functions.py b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/functions.py deleted file mode 100644 index ea3eb8d..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/functions.py +++ /dev/null @@ -1,522 +0,0 @@ -import sys -import igraph as _ig -from . import _c_leiden -from ._c_leiden import ALL_COMMS -from ._c_leiden import ALL_NEIGH_COMMS -from ._c_leiden import RAND_COMM -from ._c_leiden import RAND_NEIGH_COMM - -from ._c_leiden import MOVE_NODES -from ._c_leiden import MERGE_NODES - -from collections import Counter - - -def _get_py_capsule(graph): - return graph.__graph_as_capsule() - -from .VertexPartition import * -from .Optimiser import * - -def find_partition(graph, partition_type, initial_membership=None, weights=None, n_iterations=2, max_comm_size=0, seed=None, **kwargs): - """ Detect communities using the default settings. - - This function detects communities given the specified method in the - ``partition_type``. This should be type derived from - :class:`VertexPartition.MutableVertexPartition`, e.g. - :class:`ModularityVertexPartition` or :class:`CPMVertexPartition`. Optionally - an initial membership and edge weights can be provided. Remaining - ``**kwargs`` are passed on to the constructor of the ``partition_type``, - including for example a ``resolution_parameter``. - - Parameters - ---------- - graph : :class:`ig.Graph` - The graph for which to detect communities. - - partition_type : type of :class:` - The type of partition to use for optimisation. - - initial_membership : list of int - Initial membership for the partition. If :obj:`None` then defaults to a - singleton partition. - - weights : list of double, or edge attribute - Weights of edges. Can be either an iterable or an edge attribute. - - n_iterations : int - Number of iterations to run the Leiden algorithm. By default, 2 iterations - are run. If the number of iterations is negative, the Leiden algorithm is - run until an iteration in which there was no improvement. - - max_comm_size : non-negative int - Maximal total size of nodes in a community. If zero (the default), then - communities can be of any size. - - seed : int - Seed for the random number generator. By default uses a random seed - if nothing is specified. - - **kwargs - Remaining keyword arguments, passed on to constructor of - ``partition_type``. - - Returns - ------- - partition - The optimised partition. - - See Also - -------- - :func:`Optimiser.optimise_partition` - - Examples - -------- - >>> G = ig.Graph.Famous('Zachary') - >>> partition = la.find_partition(G, la.ModularityVertexPartition) - - """ - if not weights is None: - kwargs['weights'] = weights - partition = partition_type(graph, - initial_membership=initial_membership, - **kwargs) - optimiser = Optimiser() - - optimiser.max_comm_size = max_comm_size - - if (not seed is None): - optimiser.set_rng_seed(seed) - - optimiser.optimise_partition(partition, n_iterations) - - return partition - -def find_partition_multiplex(graphs, partition_type, n_iterations=2, max_comm_size=0, seed=None, **kwargs): - """ Detect communities for multiplex graphs. - - Each graph should be defined on the same set of vertices, only the edges may - differ for different graphs. See - :func:`Optimiser.optimise_partition_multiplex` for a more detailed - explanation. - - Parameters - ---------- - graphs : list of :class:`ig.Graph` - List of :class:`ig.Graph` graphs to optimise. - - partition_type : type of :class:`MutableVertexPartition` - The type of partition to use for optimisation (identical for all graphs). - - n_iterations : int - Number of iterations to run the Leiden algorithm. By default, 2 iterations - are run. If the number of iterations is negative, the Leiden algorithm is - run until an iteration in which there was no improvement. - - max_comm_size : non-negative int - Maximal total size of nodes in a community. If zero (the default), then - communities can be of any size. - - seed : int - Seed for the random number generator. By default uses a random seed - if nothing is specified. - - **kwargs - Remaining keyword arguments, passed on to constructor of ``partition_type``. - - Returns - ------- - list of int - membership of nodes. - - float - Improvement in quality of combined partitions, see - :func:`Optimiser.optimise_partition_multiplex`. - - Notes - ----- - We don't return a partition in this case because a partition is always - defined on a single graph. We therefore simply return the membership (which - is the same for all layers). - - See Also - -------- - :func:`Optimiser.optimise_partition_multiplex` - - :func:`slices_to_layers` - - Examples - -------- - >>> n = 100 - >>> G_1 = ig.Graph.Lattice([n], 1) - >>> G_2 = ig.Graph.Lattice([n], 1) - >>> membership, improvement = la.find_partition_multiplex([G_1, G_2], - ... la.ModularityVertexPartition) - """ - n_layers = len(graphs) - partitions = [] - layer_weights = [1]*n_layers - for graph in graphs: - partitions.append(partition_type(graph, **kwargs)) - optimiser = Optimiser() - - optimiser.max_comm_size = max_comm_size; - - if (not seed is None): - optimiser.set_rng_seed(seed) - - improvement = optimiser.optimise_partition_multiplex(partitions, layer_weights, n_iterations) - - return partitions[0].membership, improvement - -def find_partition_temporal(graphs, partition_type, - interslice_weight=1, - slice_attr='slice', vertex_id_attr='id', - edge_type_attr='type', weight_attr='weight', - n_iterations=2, max_comm_size=0, seed=None, - **kwargs): - """ Detect communities for temporal graphs. - - Each graph is considered to represent a time slice and does not necessarily - need to be defined on the same set of vertices. Nodes in two consecutive - slices are identified on the basis of the ``vertex_id_attr``, i.e. if two - nodes in two consecutive slices have an identical value of the - ``vertex_id_attr`` they are coupled. The ``vertex_id_attr`` should hence be - unique in each slice. The nodes are then coupled with a weight of - ``interslice_weight`` which is set in the edge attribute ``weight_attr``. No - weight is set if the ``interslice_weight`` is None (i.e. corresponding in - practice with a weight of 1). See :func:`time_slices_to_layers` for - a more detailed explanation. - - Parameters - ---------- - graphs : list of :class:`ig.Graph` - List of :class:`leidenalg.VertexPartition` layers to optimise. - - partition_type : type of :class:`VertexPartition.MutableVertexPartition` - The type of partition to use for optimisation (identical for all graphs). - - interslice_weight : float - The weight of the coupling between two consecutive time slices. - - slice_attr : string - The vertex attribute to use for indicating the slice of a node. - - vertex_id_attr : string - The vertex to use to identify nodes. - - edge_type_attr : string - The edge attribute to use for indicating the type of link (`interslice` or - `intraslice`). - - weight_attr : string - The edge attribute used to indicate the weight. - - n_iterations : int - Number of iterations to run the Leiden algorithm. By default, 2 iterations - are run. If the number of iterations is negative, the Leiden algorithm is - run until an iteration in which there was no improvement. - - max_comm_size : non-negative int - Maximal total size of nodes in a community. If zero (the default), then - communities can be of any size. - - seed : int - Seed for the random number generator. By default uses a random seed - if nothing is specified. - - **kwargs - Remaining keyword arguments, passed on to constructor of - ``partition_type``. - - Returns - ------- - list of membership - list containing for each slice the membership vector. - - float - Improvement in quality of combined partitions, see - :func:`Optimiser.optimise_partition_multiplex`. - - See Also - -------- - :func:`time_slices_to_layers` - - :func:`slices_to_layers` - - Examples - -------- - >>> n = 100 - >>> G_1 = ig.Graph.Lattice([n], 1) - >>> G_1.vs['id'] = range(n) - >>> G_2 = ig.Graph.Lattice([n], 1) - >>> G_2.vs['id'] = range(n) - >>> membership, improvement = la.find_partition_temporal([G_1, G_2], - ... la.ModularityVertexPartition, - ... interslice_weight=1) - """ - # Create layers - G_layers, G_interslice, G = time_slices_to_layers(graphs, - interslice_weight, - slice_attr=slice_attr, - vertex_id_attr=vertex_id_attr, - edge_type_attr=edge_type_attr, - weight_attr=weight_attr) - # Optimise partitions - arg_dict = {} - if 'node_sizes' in partition_type.__init__.__code__.co_varnames: - arg_dict['node_sizes'] = 'node_size' - - if 'weights' in partition_type.__init__.__code__.co_varnames: - arg_dict['weights'] = 'weight' - - arg_dict.update(kwargs) - - partitions = [] - for H in G_layers: - arg_dict['graph'] = H - partitions.append(partition_type(**arg_dict)) - - # We can always take the same interslice partition, as this should have no - # cost in the optimisation. - partition_interslice = CPMVertexPartition(G_interslice, resolution_parameter=0, - node_sizes='node_size', weights=weight_attr) - optimiser = Optimiser() - - optimiser.max_comm_size = max_comm_size - - if (not seed is None): - optimiser.set_rng_seed(seed) - - improvement = optimiser.optimise_partition_multiplex(partitions + [partition_interslice], n_iterations=n_iterations) - - # Transform results back into original form. - membership = {(v[slice_attr], v[vertex_id_attr]): m for v, m in zip(G.vs, partitions[0].membership)} - - membership_time_slices = [] - for slice_idx, H in enumerate(graphs): - membership_slice = [membership[(slice_idx, v[vertex_id_attr])] for v in H.vs] - membership_time_slices.append(list(membership_slice)) - return membership_time_slices, improvement - -#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -# These are helper functions to create a proper -# disjoint union in python. The igraph implementation -# currently does not keep the attributes when creating -# a disjoint_union. -def get_attrs_or_nones(seq, attr_name): - try: - return seq[attr_name] - except KeyError: - return [None] * len(seq) - -def disjoint_union_attrs(graphs): - G = _ig.Graph.disjoint_union(graphs[0], graphs[1:]) - - vertex_attributes = set(sum([H.vertex_attributes() for H in graphs], [])) - edge_attributes = set(sum([H.edge_attributes() for H in graphs], [])) - - for attr in vertex_attributes: - attr_value = sum([get_attrs_or_nones(H.vs, attr) for H in graphs], []) - G.vs[attr] = attr_value - for attr in edge_attributes: - attr_value = sum([get_attrs_or_nones(H.es, attr) for H in graphs], []) - G.es[attr] = attr_value - - return G - -#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -# Conversion to layer graphs - -def time_slices_to_layers(graphs, - interslice_weight=1, - slice_attr='slice', - vertex_id_attr='id', - edge_type_attr='type', - weight_attr='weight'): - """ Convert time slices to layer graphs. - - Each graph is considered to represent a time slice. This function simply - connects all the consecutive slices (i.e. the slice graph) with an - ``interslice_weight``. The further conversion is then delegated to - :func:`slices_to_layers`, which also provides further details. - - See Also - -------- - :func:`find_partition_temporal` - - :func:`slices_to_layers` - - """ - G_slices = _ig.Graph.Tree(len(graphs), 1, mode=_ig.TREE_UNDIRECTED) - G_slices.es[weight_attr] = interslice_weight - G_slices.vs[slice_attr] = graphs - return slices_to_layers(G_slices, - slice_attr, - vertex_id_attr, - edge_type_attr, - weight_attr) - -def slices_to_layers(G_coupling, - slice_attr='slice', - vertex_id_attr='id', - edge_type_attr='type', - weight_attr='weight'): - """ Convert a coupling graph of slices to layers of graphs. - - This function converts a graph of slices to layers so that they can be used - with this package. - - This function assumes that the slices are represented by - nodes in ``G_coupling``, and stored in the attribute ``slice_attr``. In other - words, ``G_coupling.vs[slice_attr]`` should contain :class:`ig.Graph` s . The - slices will be converted to layers, and nodes in different slices will be - coupled if the two slices are connected in ``G_coupling``. Nodes in two - connected slices are identified on the basis of the ``vertex_id_attr``, i.e. - if two nodes in two connected slices have an identical value of the - ``vertex_id_attr`` they will be coupled. The ``vertex_id_attr`` should hence - be unique in each slice. Each node in the resulting layer graphs will contain - two vertex attributes with the name of ``slice_attr`` and ``vertex_id_attr`` - that refer respectively to the slice and id of the node. - - The weight of the coupling is determined by the - weight of this link in ``G_coupling``, as determined by the ``weight_attr``. - - Parameters - ---------- - G_coupling : :class:`ig.Graph` - The graph connecting the different slices. - - slice_attr : string - The vertex attribute which contains the slices. - - vertex_id_attr : string - The vertex attribute which is used to identify whether two nodes in two - slices represent the same node, and hence, should be coupled. - - edge_type_attr : string - The edge attribute to use for indicating the type of link (``interslice`` - or ``intraslice``). - - weight_attr : string - The edge attribute used to indicate the (coupling) weight. - - Returns - ------- - G_layers : list of :class:`ig.Graph` - A list of slices converted to layers. - - G_interslice : :class:`ig.Graph` - The interslice coupling layer. - - G : :class:`ig.Graph` - The complete graph containing all layers and interslice couplings. - - Notes - ----- - The distinction between slices and layers is not easy to grasp. Slices in - this context refer to graphs that somehow represents different aspects of a - network. The simplest example is probably slices that represents time: there - are different snapshots network across time, and each snapshot is considered - a slice. Some nodes may drop out of the network over time, while others enter - the network. Edges may change over time, or the weight of the links may - change over time. This is just the simplest example of a slice, and there may - be different, more complex possibilities. Below an example with three time - slices: - - .. image:: figures/slices.png - - Now in order to optimise partitions across these different slices, we - represent them slightly differently, namely as layers. The idea of layers is - that all graphs always are defined on the same set of nodes, and that only the - links differ for different layers. We thus create new nodes as combinations of - original nodes and slices. For example, if node 1 existed in both slice 1 and - in slice 2, we will thus create two nodes to build the layers: a node 1-1 and - a node 1-2. Additionally, if the slices are connected in the slice graph, the - two nodes would also be connected, so there would be a linke between node 1-1 - and 1-2. Different slices will then correspond to different layers: each layer - only contains the link for that particular slice. In addition, for methods - such as :class:`CPMVertexPartition`, so-called ``node_sizes`` are required, - and for them to properly function, they should be set to 1 only for nodes of a - layer that represent nodes of the corresponding slice and 0 for the other - nodes (which is handled appropriately in this function, and stored in the - vertex attribute ``node_size``). Additionally, ``node_sizes`` should be set to - 0 for the interslice coupling layer. We thus obtain equally many layers as we - have slices, and we need one more layer for representing the interslice - couplings. For the example provided above, we thus obtain the following: - - .. image:: figures/layers_separate.png - - The idea of doing community detection with slices is further detailed in [1]. - - References - ---------- - .. [1] Mucha, P. J., Richardson, T., Macon, K., Porter, M. A., & Onnela, - J.-P. (2010). Community structure in time-dependent, multiscale, and - multiplex networks. Science, 328(5980), 876-8. - `10.1126/science.1184819 `_ - See Also - -------- - :func:`find_partition_temporal` - - :func:`time_slices_to_layers` - - """ - if not slice_attr in G_coupling.vertex_attributes(): - raise ValueError("Could not find the vertex attribute {0} in the coupling graph.".format(slice_attr)) - - if not weight_attr in G_coupling.edge_attributes(): - raise ValueError("Could not find the edge attribute {0} in the coupling graph.".format(weight_attr)) - - # Create disjoint union of the time graphs - for v_slice in G_coupling.vs: - H = v_slice[slice_attr] - H.vs[slice_attr] = v_slice.index - if not vertex_id_attr in H.vertex_attributes(): - raise ValueError("Could not find the vertex attribute {0} to identify nodes in different slices.".format(vertex_id_attr )) - if not weight_attr in H.edge_attributes(): - H.es[weight_attr] = 1 - - G = disjoint_union_attrs(G_coupling.vs[slice_attr]) - G.es[edge_type_attr] = 'intraslice' - - for v_slice in G_coupling.vs: - for u_slice in v_slice.neighbors(mode=_ig.OUT): - if v_slice.index < u_slice.index or G_coupling.is_directed(): - nodes_v = G.vs.select(lambda v: v[slice_attr]==v_slice.index)[vertex_id_attr] - if len(set(nodes_v)) != len(nodes_v): - err = '\n'.join( - ['\t{0} {1} times'.format(item, count) for item, count in Counter(nodes_v).items() if count > 1] - ) - raise ValueError('No unique IDs for slice {0}, require unique IDs:\n{1}'.format(v_slice.index, err)) - nodes_u = G.vs.select(lambda v: v[slice_attr]==u_slice.index)[vertex_id_attr] - if len(set(nodes_u)) != len(nodes_u): - err = '\n'.join( - ['\t{0} {1} times'.format(item, count) for item, count in Counter(nodes_u).items() if count > 1] - ) - raise ValueError('No unique IDs for slice {0}, require unique IDs:\n{1}'.format(u_slice.index, err)) - common_nodes = set(nodes_v).intersection(set(nodes_u)) - nodes_v = sorted([v for v in G.vs if v[slice_attr] == v_slice.index and v[vertex_id_attr] in common_nodes], key=lambda v: v[vertex_id_attr]) - nodes_u = sorted([v for v in G.vs if v[slice_attr] == u_slice.index and v[vertex_id_attr] in common_nodes], key=lambda v: v[vertex_id_attr]) - edges = zip(nodes_v, nodes_u) - e_start = G.ecount() - G.add_edges(edges) - e_end = G.ecount() - e_idx = range(e_start, e_end) - interslice_weight = G_coupling.es[G_coupling.get_eid(v_slice, u_slice)][weight_attr] - if not interslice_weight is None: - G.es[e_idx][weight_attr] = interslice_weight - G.es[e_idx][edge_type_attr] = 'interslice' - - # Convert aggregate graph to individual layers for each time slice. - G_layers = [None]*G_coupling.vcount() - for v_slice in G_coupling.vs: - H = G.subgraph_edges(G.es.select(_within=[v.index for v in G.vs if v[slice_attr] == v_slice.index]), delete_vertices=False) - H.vs['node_size'] = [1 if v[slice_attr] == v_slice.index else 0 for v in H.vs] - G_layers[v_slice.index] = H - - # Create one graph for the interslice links. - G_interslice = G.subgraph_edges(G.es.select(type_eq='interslice'), delete_vertices=False) - G_interslice.vs['node_size'] = 0 - - return G_layers, G_interslice, G diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/pynterface.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/pynterface.cpp deleted file mode 100644 index f754684..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/pynterface.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "pynterface.h" diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/python_optimiser_interface.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/python_optimiser_interface.cpp deleted file mode 100644 index 0b97d32..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/python_optimiser_interface.cpp +++ /dev/null @@ -1,961 +0,0 @@ -#include "python_optimiser_interface.h" - - PyObject* capsule_Optimiser(Optimiser* optimiser) - { - PyObject* py_optimiser = PyCapsule_New(optimiser, "leidenalg.Optimiser", del_Optimiser); - return py_optimiser; - } - - Optimiser* decapsule_Optimiser(PyObject* py_optimiser) - { - Optimiser* optimiser = (Optimiser*) PyCapsule_GetPointer(py_optimiser, "leidenalg.Optimiser"); - return optimiser; - } - - void del_Optimiser(PyObject* py_optimiser) - { - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - delete optimiser; - } -#ifdef __cplusplus -extern "C" -{ -#endif - - PyObject* _new_Optimiser(PyObject *self, PyObject *args) - { - if (args != NULL) - { - PyErr_BadArgument(); - return NULL; - } - - Optimiser* optimiser = new Optimiser(); - PyObject* py_optimiser = capsule_Optimiser(optimiser); - return py_optimiser; - } - - PyObject* _Optimiser_optimise_partition(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - PyObject* py_partition = NULL; - PyObject* py_is_membership_fixed = NULL; - - static const char* kwlist[] = {"optimiser", "partition", "is_membership_fixed", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "OO|O", (char**) kwlist, - &py_optimiser, &py_partition, - &py_is_membership_fixed)) - return NULL; - - #ifdef DEBUG - cerr << "optimise_partition(" << py_partition << ", is_membership_fixed=" << py_is_membership_fixed << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - size_t n = partition->get_graph()->vcount(); - vector is_membership_fixed(n, false); - if (py_is_membership_fixed != NULL && py_is_membership_fixed != Py_None) - { - #ifdef DEBUG - cerr << "Reading is_membership_fixed." << endl; - #endif - - size_t nb_is_membership_fixed = PyList_Size(py_is_membership_fixed); - if (nb_is_membership_fixed != n) - { - PyErr_SetString(PyExc_ValueError, "Node size vector not the same size as the number of nodes."); - return NULL; - } - - for (size_t v = 0; v < n; v++) - { - PyObject* py_item = PyList_GetItem(py_is_membership_fixed, v); - is_membership_fixed[v] = PyObject_IsTrue(py_item); - } - } - - double q = 0.0; - try - { - q = optimiser->optimise_partition(partition, is_membership_fixed); - } - catch (std::exception& e) - { - PyErr_SetString(PyExc_ValueError, e.what()); - return NULL; - } - return PyFloat_FromDouble(q); - } - - PyObject* _Optimiser_optimise_partition_multiplex(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - PyObject* py_partitions = NULL; - PyObject* py_layer_weights = NULL; - PyObject* py_is_membership_fixed = NULL; - - static const char* kwlist[] = {"optimiser", "partitions", "layer_weights", "is_membership_fixed", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "OOO|O", (char**) kwlist, - &py_optimiser, &py_partitions, - &py_layer_weights, &py_is_membership_fixed)) - return NULL; - - size_t nb_partitions = (size_t)PyList_Size(py_partitions); - if (nb_partitions != (size_t)PyList_Size(py_layer_weights)) - { - PyErr_SetString(PyExc_ValueError, "Number of layer weights does not equal the number of partitions"); - return NULL; - } - - #ifdef DEBUG - cerr << "Parsing " << nb_partitions << " partitions." << endl; - #endif - - // This is all done per layer. - - vector partitions(nb_partitions); - vector layer_weights(nb_partitions, 1.0); - - for (size_t layer = 0; layer < nb_partitions; layer++) - { - PyObject* py_partition = PyList_GetItem(py_partitions, layer); - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - PyObject* layer_weight = PyList_GetItem(py_layer_weights, layer); - - partitions[layer] = partition; - - - if (PyNumber_Check(layer_weight)) - { - layer_weights[layer] = PyFloat_AsDouble(layer_weight); - } - else - { - PyErr_SetString(PyExc_TypeError, "Expected floating value for layer weight."); - return NULL; - } - - if (isnan(layer_weights[layer])) - { - PyErr_SetString(PyExc_TypeError, "Cannot accept NaN weights."); - return NULL; - } - } - - if (nb_partitions == 0) - return NULL; - - size_t n = partitions[0]->get_graph()->vcount(); - vector is_membership_fixed(n, false); - if (py_is_membership_fixed != NULL && py_is_membership_fixed != Py_None) - { - #ifdef DEBUG - cerr << "Reading is_membership_fixed." << endl; - #endif - - size_t nb_is_membership_fixed = PyList_Size(py_is_membership_fixed); - if (nb_is_membership_fixed != n) - { - PyErr_SetString(PyExc_TypeError, "Node size vector not the same size as the number of nodes."); - return NULL; - } - - for (size_t v = 0; v < n; v++) - { - PyObject* py_item = PyList_GetItem(py_is_membership_fixed, v); - is_membership_fixed[v] = PyObject_IsTrue(py_item); - } - } - - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - #endif - - double q = 0.0; - try - { - q = optimiser->optimise_partition(partitions, layer_weights, is_membership_fixed); - } - catch (std::exception& e) - { - PyErr_SetString(PyExc_ValueError, e.what()); - return NULL; - } - return PyFloat_FromDouble(q); - } - - PyObject* _Optimiser_move_nodes(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - PyObject* py_partition = NULL; - PyObject* py_is_membership_fixed = NULL; - int consider_comms = -1; - - static const char* kwlist[] = {"optimiser", "partition", "is_membership_fixed", "consider_comms", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "OO|Oi", (char**) kwlist, - &py_optimiser, &py_partition, - &py_is_membership_fixed, &consider_comms)) - return NULL; - - #ifdef DEBUG - cerr << "optimise_partition(" << py_partition << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - size_t n = partition->get_graph()->vcount(); - vector is_membership_fixed(n, false); - if (py_is_membership_fixed != NULL && py_is_membership_fixed != Py_None) - { - #ifdef DEBUG - cerr << "Reading is_membership_fixed." << endl; - #endif - - size_t nb_is_membership_fixed = PyList_Size(py_is_membership_fixed); - if (nb_is_membership_fixed != n) - { - PyErr_SetString(PyExc_TypeError, "Node size vector not the same size as the number of nodes."); - return NULL; - } - - for (size_t v = 0; v < n; v++) - { - PyObject* py_item = PyList_GetItem(py_is_membership_fixed, v); - is_membership_fixed[v] = PyObject_IsTrue(py_item); - } - } - - if (consider_comms < 0) - consider_comms = optimiser->consider_comms; - - double q = 0.0; - try - { - q = optimiser->move_nodes(partition, is_membership_fixed, consider_comms, true); - } - catch (std::exception& e) - { - PyErr_SetString(PyExc_ValueError, e.what()); - return NULL; - } - return PyFloat_FromDouble(q); - } - - PyObject* _Optimiser_merge_nodes(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - PyObject* py_partition = NULL; - PyObject* py_is_membership_fixed = NULL; - int consider_comms = -1; - - static const char* kwlist[] = {"optimiser", "partition", "is_membership_fixed", "consider_comms", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "OO|Oi", (char**) kwlist, - &py_optimiser, &py_partition, - &py_is_membership_fixed, &consider_comms)) - return NULL; - - #ifdef DEBUG - cerr << "optimise_partition(" << py_partition << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - size_t n = partition->get_graph()->vcount(); - vector is_membership_fixed(n, false); - if (py_is_membership_fixed != NULL && py_is_membership_fixed != Py_None) - { - #ifdef DEBUG - cerr << "Reading is_membership_fixed." << endl; - #endif - - size_t nb_is_membership_fixed = PyList_Size(py_is_membership_fixed); - if (nb_is_membership_fixed != n) - { - PyErr_SetString(PyExc_TypeError, "Node size vector not the same size as the number of nodes."); - return NULL; - } - - for (size_t v = 0; v < n; v++) - { - PyObject* py_item = PyList_GetItem(py_is_membership_fixed, v); - is_membership_fixed[v] = PyObject_IsTrue(py_item); - } - } - - if (consider_comms < 0) - consider_comms = optimiser->consider_comms; - - double q = 0.0; - try - { - q = optimiser->merge_nodes(partition, is_membership_fixed, consider_comms, true); - } - catch (std::exception& e) - { - PyErr_SetString(PyExc_ValueError, e.what()); - return NULL; - } - return PyFloat_FromDouble(q); - } - - PyObject* _Optimiser_move_nodes_constrained(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - PyObject* py_partition = NULL; - PyObject* py_constrained_partition = NULL; - int consider_comms = -1; - - static const char* kwlist[] = {"optimiser", "partition", "constrained_partition", "consider_comms", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "OOO|i", (char**) kwlist, - &py_optimiser, &py_partition, &py_constrained_partition, &consider_comms)) - return NULL; - - #ifdef DEBUG - cerr << "optimise_partition(" << py_partition << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule constrained partition at address " << py_constrained_partition << endl; - #endif - MutableVertexPartition* constrained_partition = decapsule_MutableVertexPartition(py_constrained_partition); - #ifdef DEBUG - cerr << "Using constrained partition at address " << constrained_partition << endl; - #endif - - if (consider_comms < 0) - consider_comms = optimiser->refine_consider_comms; - - double q = 0.0; - try - { - q = optimiser->move_nodes_constrained(partition, consider_comms, constrained_partition); - } - catch (std::exception& e) - { - PyErr_SetString(PyExc_ValueError, e.what()); - return NULL; - } - return PyFloat_FromDouble(q); - } - - PyObject* _Optimiser_merge_nodes_constrained(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - PyObject* py_partition = NULL; - PyObject* py_constrained_partition = NULL; - int consider_comms = -1; - - static const char* kwlist[] = {"optimiser", "partition", "constrained_partition", "consider_comms", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "OOO|i", (char**) kwlist, - &py_optimiser, &py_partition, &py_constrained_partition, &consider_comms)) - return NULL; - - #ifdef DEBUG - cerr << "optimise_partition(" << py_partition << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule constrained partition at address " << py_partition << endl; - #endif - MutableVertexPartition* constrained_partition = decapsule_MutableVertexPartition(py_constrained_partition); - #ifdef DEBUG - cerr << "Using constrained partition at address " << partition << endl; - #endif - - if (consider_comms < 0) - consider_comms = optimiser->refine_consider_comms; - - double q = 0.0; - try - { - q = optimiser->merge_nodes_constrained(partition, consider_comms, constrained_partition); - } - catch (std::exception& e) - { - PyErr_SetString(PyExc_ValueError, e.what()); - return NULL; - } - return PyFloat_FromDouble(q); - } - - PyObject* _Optimiser_set_consider_comms(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - int consider_comms = Optimiser::ALL_NEIGH_COMMS; - static const char* kwlist[] = {"optimiser", "consider_comms", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "Oi", (char**) kwlist, - &py_optimiser, &consider_comms)) - return NULL; - - #ifdef DEBUG - cerr << "set_consider_comms(" << consider_comms << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - #endif - - optimiser->consider_comms = consider_comms; - - Py_INCREF(Py_None); - return Py_None; - } - - PyObject* _Optimiser_get_consider_comms(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - static const char* kwlist[] = {"optimiser", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O", (char**) kwlist, - &py_optimiser)) - return NULL; - - #ifdef DEBUG - cerr << "get_consider_comms();" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - #endif - - return PyLong_FromLong(optimiser->consider_comms); - } - - PyObject* _Optimiser_set_refine_consider_comms(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - int refine_consider_comms = Optimiser::ALL_NEIGH_COMMS; - static const char* kwlist[] = {"optimiser", "refine_consider_comms", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "Oi", (char**) kwlist, - &py_optimiser, &refine_consider_comms)) - return NULL; - - #ifdef DEBUG - cerr << "set_refine_consider_comms(" << refine_consider_comms << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - #endif - - optimiser->refine_consider_comms = refine_consider_comms; - - Py_INCREF(Py_None); - return Py_None; - } - - PyObject* _Optimiser_get_refine_consider_comms(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - static const char* kwlist[] = {"optimiser", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O", (char**) kwlist, - &py_optimiser)) - return NULL; - - #ifdef DEBUG - cerr << "get_refine_consider_comms();" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - #endif - - return PyLong_FromLong(optimiser->refine_consider_comms); - } - - PyObject* _Optimiser_set_optimise_routine(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - int optimise_routine = Optimiser::ALL_NEIGH_COMMS; - static const char* kwlist[] = {"optimiser", "optimise_routine", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "Oi", (char**) kwlist, - &py_optimiser, &optimise_routine)) - return NULL; - - #ifdef DEBUG - cerr << "set_optimise_routine(" << optimise_routine << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - #endif - - optimiser->optimise_routine = optimise_routine; - - Py_INCREF(Py_None); - return Py_None; - } - - PyObject* _Optimiser_get_optimise_routine(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - static const char* kwlist[] = {"optimiser", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O", (char**) kwlist, - &py_optimiser)) - return NULL; - - #ifdef DEBUG - cerr << "get_optimise_routine();" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - #endif - - return PyLong_FromLong(optimiser->optimise_routine); - } - - PyObject* _Optimiser_set_refine_routine(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - int refine_routine = Optimiser::ALL_NEIGH_COMMS; - static const char* kwlist[] = {"optimiser", "refine_routine", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "Oi", (char**) kwlist, - &py_optimiser, &refine_routine)) - return NULL; - - #ifdef DEBUG - cerr << "set_refine_routine(" << refine_routine << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - #endif - - optimiser->refine_routine = refine_routine; - - Py_INCREF(Py_None); - return Py_None; - } - - PyObject* _Optimiser_get_refine_routine(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - static const char* kwlist[] = {"optimiser", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O", (char**) kwlist, - &py_optimiser)) - return NULL; - - #ifdef DEBUG - cerr << "get_refine_routine();" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - #endif - - return PyLong_FromLong(optimiser->refine_routine); - } - - PyObject* _Optimiser_set_consider_empty_community(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - int consider_empty_community = true; - static const char* kwlist[] = {"optimiser", "consider_empty_community", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "Oi", (char**) kwlist, - &py_optimiser, &consider_empty_community)) - return NULL; - - #ifdef DEBUG - cerr << "set_consider_empty_community(" << consider_empty_community << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - #endif - - #ifdef DEBUG - cerr << "Setting consider_empty_community to " << consider_empty_community << endl; - #endif - optimiser->consider_empty_community = consider_empty_community; - #ifdef DEBUG - cerr << "Set consider_empty_community to " << optimiser->consider_empty_community << endl; - #endif - - Py_INCREF(Py_None); - return Py_None; - } - - PyObject* _Optimiser_get_consider_empty_community(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - static const char* kwlist[] = {"optimiser", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O", (char**) kwlist, - &py_optimiser)) - return NULL; - - #ifdef DEBUG - cerr << "get_consider_empty_community();" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - cerr << "Returning " << optimiser->consider_empty_community << endl; - #endif - - return PyBool_FromLong(optimiser->consider_empty_community); - } - - PyObject* _Optimiser_set_refine_partition(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - int refine_partition = false; - static const char* kwlist[] = {"optimiser", "refine_partition", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "Oi", (char**) kwlist, - &py_optimiser, &refine_partition)) - return NULL; - - #ifdef DEBUG - cerr << "set_refine_partition(" << refine_partition << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - #endif - - optimiser->refine_partition = refine_partition; - - Py_INCREF(Py_None); - return Py_None; - } - - PyObject* _Optimiser_get_refine_partition(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - static const char* kwlist[] = {"optimiser", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O", (char**) kwlist, - &py_optimiser)) - return NULL; - - #ifdef DEBUG - cerr << "get_refine_partition();" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - #endif - - return PyBool_FromLong(optimiser->refine_partition); - } - - PyObject* _Optimiser_set_max_comm_size(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - size_t max_comm_size = 0; - static const char* kwlist[] = {"optimiser", "max_comm_size", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "On", (char**) kwlist, - &py_optimiser, &max_comm_size)) - return NULL; - - #ifdef DEBUG - cerr << "set_max_comm_size(" << max_comm_size << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - #endif - - optimiser->max_comm_size = max_comm_size; - - Py_INCREF(Py_None); - return Py_None; - } - - PyObject* _Optimiser_get_max_comm_size(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - static const char* kwlist[] = {"optimiser", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O", (char**) kwlist, - &py_optimiser)) - return NULL; - - #ifdef DEBUG - cerr << "get_max_comm_size();" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - #endif - - return PyLong_FromSize_t(optimiser->max_comm_size); - } - - PyObject* _Optimiser_set_rng_seed(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_optimiser = NULL; - int seed = 0; - static const char* kwlist[] = {"optimiser", "seed", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "Oi", (char**) kwlist, - &py_optimiser, &seed)) - return NULL; - - #ifdef DEBUG - cerr << "set_rng_seed(" << seed << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule optimiser at address " << py_optimiser << endl; - #endif - Optimiser* optimiser = decapsule_Optimiser(py_optimiser); - #ifdef DEBUG - cerr << "Using optimiser at address " << optimiser << endl; - #endif - - #ifdef DEBUG - cerr << "Setting seed to " << seed << endl; - #endif - optimiser->set_rng_seed(seed); - - Py_INCREF(Py_None); - return Py_None; - } -#ifdef __cplusplus -} -#endif diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/python_partition_interface.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/python_partition_interface.cpp deleted file mode 100644 index 6b14f76..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/src/leidenalg/python_partition_interface.cpp +++ /dev/null @@ -1,1404 +0,0 @@ -#include "python_partition_interface.h" - -Graph* create_graph_from_py(PyObject* py_obj_graph, PyObject* py_node_sizes) -{ - return create_graph_from_py(py_obj_graph, py_node_sizes, NULL, true); -} - -Graph* create_graph_from_py(PyObject* py_obj_graph, PyObject* py_node_sizes, PyObject* py_weights) -{ - return create_graph_from_py(py_obj_graph, py_node_sizes, py_weights, true); -} - -Graph* create_graph_from_py(PyObject* py_obj_graph, PyObject* py_node_sizes, PyObject* py_weights, int check_positive_weight) -{ - #ifdef DEBUG - cerr << "create_graph_from_py" << endl; - #endif - - igraph_t* py_graph = (igraph_t*) PyCapsule_GetPointer(py_obj_graph, NULL); - #ifdef DEBUG - cerr << "Got igraph_t " << py_graph << endl; - #endif - - // If necessary create a weighted graph - Graph* graph = NULL; - #ifdef DEBUG - cerr << "Creating graph."<< endl; - #endif - - size_t n = igraph_vcount(py_graph); - size_t m = igraph_ecount(py_graph); - - vector node_sizes; - vector weights; - if (py_node_sizes != NULL && py_node_sizes != Py_None) - { - #ifdef DEBUG - cerr << "Reading node_sizes." << endl; - #endif - - size_t nb_node_size = PyList_Size(py_node_sizes); - if (nb_node_size != n) - { - throw Exception("Node size vector not the same size as the number of nodes."); - } - node_sizes.resize(n); - for (size_t v = 0; v < n; v++) - { - PyObject* py_item = PyList_GetItem(py_node_sizes, v); - if (PyNumber_Check(py_item) && PyIndex_Check(py_item)) - { - size_t e = PyLong_AsSize_t(PyNumber_Long(py_item)); - node_sizes[v] = e; - } - else - { - throw Exception("Expected integer value for node sizes vector."); - } - } - } - - if (py_weights != NULL && py_weights != Py_None) - { - #ifdef DEBUG - cerr << "Reading weights." << endl; - #endif - size_t nb_weights = PyList_Size(py_weights); - if (nb_weights != m) - throw Exception("Weight vector not the same size as the number of edges."); - weights.resize(m); - for (size_t e = 0; e < m; e++) - { - PyObject* py_item = PyList_GetItem(py_weights, e); - #ifdef DEBUG - //PyObject* py_item_repr = PyObject_Repr(py_item); - //const char* s = PyUnicode_AsUTF8(py_item_repr); - //cerr << "Got item " << e << ": " << s << endl; - #endif - if (PyNumber_Check(py_item)) - { - weights[e] = PyFloat_AsDouble(py_item); - } - else - { - throw Exception("Expected floating point value for weight vector."); - } - - if (check_positive_weight) - if (weights[e] < 0 ) - throw Exception("Cannot accept negative weights."); - - if (isnan(weights[e])) - throw Exception("Cannot accept NaN weights."); - - if (!isfinite(weights[e])) - throw Exception("Cannot accept infinite weights."); - } - } - - // TODO: Pass correct_for_self_loops as parameter - int correct_self_loops = false; - if (node_sizes.size() == n) - { - if (weights.size() == m) - graph = new Graph(py_graph, weights, node_sizes, correct_self_loops); - else - graph = new Graph(py_graph, node_sizes, correct_self_loops); - } - else - { - if (weights.size() == m) - graph = new Graph(py_graph, weights, correct_self_loops); - else - graph = new Graph(py_graph, correct_self_loops); - } - - #ifdef DEBUG - cerr << "Created graph " << graph << endl; - cerr << "Number of nodes " << graph->vcount() << endl; - cerr << "Number of edges " << graph->ecount() << endl; - cerr << "Total weight " << graph->total_weight() << endl; - #endif - - return graph; -} -// -//Graph* create_graph_from_py(PyObject* py_obj_graph, PyObject* py_node_sizes, PyObject* py_weights, PyObject* py_dataset, PyObject* py_names) { -// Graph* graph create_graph_from_py(py_obj_graph, py_node_sizes, py_weights, check_positive_weight); -// -//} - -vector create_size_t_vector(PyObject* py_list) -{ - size_t n = PyList_Size(py_list); - vector result(n); - for (size_t i = 0; i < n; i++) - { - PyObject* py_item = PyList_GetItem(py_list, i); - if (PyNumber_Check(py_item) && PyIndex_Check(py_item)) - { - size_t e = PyLong_AsSize_t(PyNumber_Long(py_item)); - if (e >= n) - throw Exception("Value cannot exceed length of list."); - else - result[i] = e; - } - else - throw Exception("Value cannot exceed length of list."); - } - return result; -} - -PyObject* capsule_MutableVertexPartition(MutableVertexPartition* partition) -{ - PyObject* py_partition = PyCapsule_New(partition, "leidenalg.VertexPartition.MutableVertexPartition", del_MutableVertexPartition); - return py_partition; -} - -MutableVertexPartition* decapsule_MutableVertexPartition(PyObject* py_partition) -{ - MutableVertexPartition* partition = (MutableVertexPartition*) PyCapsule_GetPointer(py_partition, "leidenalg.VertexPartition.MutableVertexPartition"); - return partition; -} - -void del_MutableVertexPartition(PyObject* py_partition) -{ - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - delete partition; -} - -#ifdef __cplusplus -extern "C" -{ -#endif - -PyObject* _new_HybridVertexPartition(PyObject *self, PyObject *args, PyObject *keywds) -{ - PyObject* py_obj_graph = NULL; - PyObject* py_initial_membership = NULL; - PyObject* py_weights = NULL; - PyObject* py_node_sizes = NULL; - PyObject* py_dataset = NULL; - PyObject* py_names = NULL; - PyObject* py_target = NULL; - PyObject* py_k1 = NULL; - PyObject* py_k2 = NULL; - PyObject* py_k3 = NULL; - PyObject* py_k4 = NULL; - - static const char* kwlist[] = {"graph", "initial_membership", "weights", "node_sizes", "dataset", "names", "target", "k1", "k2", "k3", "k4", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|OOOOOOOOOO", (char**) kwlist, - &py_obj_graph, &py_initial_membership, &py_weights, &py_node_sizes, - &py_dataset, &py_names, &py_target, &py_k1, &py_k2, &py_k3, &py_k4)) - return NULL; - - try - { - - Graph* graph = create_graph_from_py(py_obj_graph, py_node_sizes, py_weights); - - HybridVertexPartition* partition = NULL; - - // If necessary create an initial partition - if (py_initial_membership != NULL && py_initial_membership != Py_None) - { - vector initial_membership = create_size_t_vector(py_initial_membership); - partition = new HybridVertexPartition(graph, initial_membership); - } - else { - if (py_dataset != NULL && py_dataset != Py_None && - py_target != NULL && py_target != Py_None && - py_names != NULL && py_names != Py_None) { - std::vector< std::vector >dataset; - std::vector target; - std::vector< std::vector > names; - // getting dataset - for (int i=0; i < PyList_Size(py_dataset); i++) { - PyObject* py_inner_list = PyList_GetItem(py_dataset, i); - std::vector inner_list; - if (!PyList_Check(py_dataset)) { - PyErr_SetString(PyExc_TypeError, "Dataset passed in doesn't match expected format. Must be list of list of doubles."); - return NULL; - } - for (int j=0; j < PyList_Size(py_inner_list); j++) { - PyObject* py_data_point = PyList_GetItem(py_inner_list, j); - double val; - if (PyLong_Check(py_data_point)) { - val = (double) PyLong_AsLong(py_data_point); - } else if (PyFloat_Check(py_data_point)) { - val = PyFloat_AsDouble(py_data_point); - } else { - PyErr_SetString(PyExc_TypeError, "Must pass in list of list of number for dataset."); - return NULL; - } - inner_list.push_back(val); - } - dataset.push_back(inner_list); - } - - // getting target - for (int i=0; i < PyList_Size(py_target); i++) { - PyObject* py_data_point = PyList_GetItem(py_target, i); - double val; - if (PyLong_Check(py_data_point)) { - val = (double) PyLong_AsLong(py_data_point); - } else if (PyFloat_Check(py_data_point)) { - val = PyFloat_AsDouble(py_data_point); - } else { - PyErr_SetString(PyExc_TypeError, "Must pass in list of list of number for target."); - return NULL; - } - target.push_back(val); - } - - // getting names - for (int i=0; i < PyList_Size(py_names); i++) { - PyObject* py_data_point = PyList_GetItem(py_names, i); - std::vector data_point_list; - int data_point; - if (PyLong_Check(py_data_point)) { - data_point = (int) PyLong_AsLong(py_data_point); - data_point_list.push_back(data_point); - } else { - PyErr_SetString(PyExc_TypeError, "Must pass in list of ints for names."); - } - names.push_back(data_point_list); - } - - // getting weights - double k1, k2, k3, k4; - if (PyLong_Check(py_k1)) { - k1 = (double) PyLong_AsLong(py_k1); - } else if (PyFloat_Check(py_k1)) { - k1 = PyFloat_AsDouble(py_k1); - } else { - PyErr_SetString(PyExc_TypeError, "Must pass in float for k1."); - return NULL; - } - if (PyLong_Check(py_k2)) { - k2 = (double) PyLong_AsLong(py_k2); - } else if (PyFloat_Check(py_k2)) { - k2 = PyFloat_AsDouble(py_k2); - } else { - PyErr_SetString(PyExc_TypeError, "Must pass in float for k2."); - return NULL; - } - if (PyLong_Check(py_k3)) { - k3 = (double) PyLong_AsLong(py_k3); - } else if (PyFloat_Check(py_k3)) { - k3 = PyFloat_AsDouble(py_k3); - } else { - PyErr_SetString(PyExc_TypeError, "Must pass in float for k3."); - return NULL; - } - if (PyLong_Check(py_k4)) { - k4 = (double) PyLong_AsLong(py_k4); - } else if (PyFloat_Check(py_k4)) { - k4 = PyFloat_AsDouble(py_k4); - } else { - PyErr_SetString(PyExc_TypeError, "Must pass in float for k4."); - return NULL; - } - - graph->set_features(names); - - partition = new HybridVertexPartition(graph, dataset, target, k1, k2, k3, k4); - } else { - partition = new HybridVertexPartition(graph); - } - } - - // Do *NOT* forget to remove the graph upon deletion - partition->destructor_delete_graph = true; - - PyObject* py_partition = capsule_MutableVertexPartition(partition); -#ifdef DEBUG - cerr << "Created capsule partition at address " << py_partition << endl; -#endif - - return py_partition; - } - catch (std::exception& e ) - { - string s = "Could not construct partition: " + string(e.what()); - PyErr_SetString(PyExc_BaseException, s.c_str()); - return NULL; - } -} - PyObject* _new_ModularityVertexPartition(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_obj_graph = NULL; - PyObject* py_initial_membership = NULL; - PyObject* py_weights = NULL; - - static const char* kwlist[] = {"graph", "initial_membership", "weights", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|OO", (char**) kwlist, - &py_obj_graph, &py_initial_membership, &py_weights)) - return NULL; - - try - { - - Graph* graph = create_graph_from_py(py_obj_graph, NULL, py_weights); - - ModularityVertexPartition* partition = NULL; - - // If necessary create an initial partition - if (py_initial_membership != NULL && py_initial_membership != Py_None) - { - vector initial_membership = create_size_t_vector(py_initial_membership); - - partition = new ModularityVertexPartition(graph, initial_membership); - } - else - partition = new ModularityVertexPartition(graph); - - // Do *NOT* forget to remove the graph upon deletion - partition->destructor_delete_graph = true; - - PyObject* py_partition = capsule_MutableVertexPartition(partition); - #ifdef DEBUG - cerr << "Created capsule partition at address " << py_partition << endl; - #endif - - return py_partition; - } - catch (std::exception& e ) - { - string s = "Could not construct partition: " + string(e.what()); - PyErr_SetString(PyExc_BaseException, s.c_str()); - return NULL; - } - } - - - PyObject* _new_SignificanceVertexPartition(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_obj_graph = NULL; - PyObject* py_initial_membership = NULL; - PyObject* py_node_sizes = NULL; - - static const char* kwlist[] = {"graph", "initial_membership", "node_sizes", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|OO", (char**) kwlist, - &py_obj_graph, &py_initial_membership, &py_node_sizes)) - return NULL; - - try - { - - Graph* graph = create_graph_from_py(py_obj_graph, py_node_sizes); - - SignificanceVertexPartition* partition = NULL; - - // If necessary create an initial partition - if (py_initial_membership != NULL && py_initial_membership != Py_None) - { - vector initial_membership = create_size_t_vector(py_initial_membership); - - partition = new SignificanceVertexPartition(graph, initial_membership); - } - else - partition = new SignificanceVertexPartition(graph); - - // Do *NOT* forget to remove the graph upon deletion - partition->destructor_delete_graph = true; - - PyObject* py_partition = capsule_MutableVertexPartition(partition); - #ifdef DEBUG - cerr << "Created capsule partition at address " << py_partition << endl; - #endif - - return py_partition; - } - catch (std::exception const & e ) - { - string s = "Could not construct partition: " + string(e.what()); - PyErr_SetString(PyExc_BaseException, s.c_str()); - return NULL; - } - } - - PyObject* _new_SurpriseVertexPartition(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_obj_graph = NULL; - PyObject* py_initial_membership = NULL; - PyObject* py_weights = NULL; - PyObject* py_node_sizes = NULL; - - static const char* kwlist[] = {"graph", "initial_membership", "weights", "node_sizes", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|OOO", (char**) kwlist, - &py_obj_graph, &py_initial_membership, &py_weights, &py_node_sizes)) - return NULL; - - try - { - - Graph* graph = create_graph_from_py(py_obj_graph, py_node_sizes, py_weights); - - SurpriseVertexPartition* partition = NULL; - - // If necessary create an initial partition - if (py_initial_membership != NULL && py_initial_membership != Py_None) - { - vector initial_membership = create_size_t_vector(py_initial_membership); - - partition = new SurpriseVertexPartition(graph, initial_membership); - } - else - partition = new SurpriseVertexPartition(graph); - - // Do *NOT* forget to remove the graph upon deletion - partition->destructor_delete_graph = true; - - PyObject* py_partition = capsule_MutableVertexPartition(partition); - #ifdef DEBUG - cerr << "Created capsule partition at address " << py_partition << endl; - #endif - - return py_partition; - } - catch (std::exception const & e ) - { - string s = "Could not construct partition: " + string(e.what()); - PyErr_SetString(PyExc_BaseException, s.c_str()); - return NULL; - } - } - - PyObject* _new_CPMVertexPartition(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_obj_graph = NULL; - PyObject* py_initial_membership = NULL; - PyObject* py_weights = NULL; - PyObject* py_node_sizes = NULL; - double resolution_parameter = 1.0; - - static const char* kwlist[] = {"graph", "initial_membership", "weights", "node_sizes", "resolution_parameter", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|OOOd", (char**) kwlist, - &py_obj_graph, &py_initial_membership, &py_weights, &py_node_sizes, &resolution_parameter)) - return NULL; - - try - { - - Graph* graph = create_graph_from_py(py_obj_graph, py_node_sizes, py_weights, false); - - CPMVertexPartition* partition = NULL; - - // If necessary create an initial partition - if (py_initial_membership != NULL && py_initial_membership != Py_None) - { - vector initial_membership = create_size_t_vector(py_initial_membership); - - partition = new CPMVertexPartition(graph, initial_membership, resolution_parameter); - } - else - partition = new CPMVertexPartition(graph, resolution_parameter); - - // Do *NOT* forget to remove the graph upon deletion - partition->destructor_delete_graph = true; - - PyObject* py_partition = capsule_MutableVertexPartition(partition); - #ifdef DEBUG - cerr << "Created capsule partition at address " << py_partition << endl; - #endif - - return py_partition; - } - catch (std::exception const & e ) - { - string s = "Could not construct partition: " + string(e.what()); - PyErr_SetString(PyExc_BaseException, s.c_str()); - return NULL; - } - } - - PyObject* _new_RBERVertexPartition(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_obj_graph = NULL; - PyObject* py_initial_membership = NULL; - PyObject* py_weights = NULL; - PyObject* py_node_sizes = NULL; - double resolution_parameter = 1.0; - - static const char* kwlist[] = {"graph", "initial_membership", "weights", "node_sizes", "resolution_parameter", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|OOOd", (char**) kwlist, - &py_obj_graph, &py_initial_membership, &py_weights, &py_node_sizes, &resolution_parameter)) - return NULL; - - try - { - - Graph* graph = create_graph_from_py(py_obj_graph, py_node_sizes, py_weights); - - RBERVertexPartition* partition = NULL; - - // If necessary create an initial partition - if (py_initial_membership != NULL && py_initial_membership != Py_None) - { - vector initial_membership = create_size_t_vector(py_initial_membership); - - partition = new RBERVertexPartition(graph, initial_membership, resolution_parameter); - } - else - partition = new RBERVertexPartition(graph, resolution_parameter); - - // Do *NOT* forget to remove the graph upon deletion - partition->destructor_delete_graph = true; - - PyObject* py_partition = capsule_MutableVertexPartition(partition); - #ifdef DEBUG - cerr << "Created capsule partition at address " << py_partition << endl; - #endif - - return py_partition; - } - catch (std::exception const & e ) - { - string s = "Could not construct partition: " + string(e.what()); - PyErr_SetString(PyExc_BaseException, s.c_str()); - return NULL; - } - } - - PyObject* _new_RBConfigurationVertexPartition(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_obj_graph = NULL; - PyObject* py_initial_membership = NULL; - PyObject* py_weights = NULL; - double resolution_parameter = 1.0; - - static const char* kwlist[] = {"graph", "initial_membership", "weights", "resolution_parameter", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|OOd", (char**) kwlist, - &py_obj_graph, &py_initial_membership, &py_weights, &resolution_parameter)) - return NULL; - - try - { - - Graph* graph = create_graph_from_py(py_obj_graph, NULL, py_weights); - - RBConfigurationVertexPartition* partition = NULL; - - // If necessary create an initial partition - if (py_initial_membership != NULL && py_initial_membership != Py_None) - { - vector initial_membership = create_size_t_vector(py_initial_membership); - - partition = new RBConfigurationVertexPartition(graph, initial_membership, resolution_parameter); - } - else - partition = new RBConfigurationVertexPartition(graph, resolution_parameter); - - // Do *NOT* forget to remove the graph upon deletion - partition->destructor_delete_graph = true; - - PyObject* py_partition = capsule_MutableVertexPartition(partition); - #ifdef DEBUG - cerr << "Created capsule partition at address " << py_partition << endl; - #endif - - return py_partition; - } - catch (std::exception const & e ) - { - string s = "Could not construct partition: " + string(e.what()); - PyErr_SetString(PyExc_BaseException, s.c_str()); - return NULL; - } - } - - PyObject* _MutableVertexPartition_get_py_igraph(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_partition = NULL; - - static const char* kwlist[] = {"partition", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O", (char**) kwlist, - &py_partition)) - return NULL; - - #ifdef DEBUG - cerr << "get_py_igraph();" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - Graph* graph = partition->get_graph(); - - size_t n = graph->vcount(); - size_t m = graph->ecount(); - - PyObject* edges = PyList_New(m); - for (size_t e = 0; e < m; e++) - { - vector edge = graph->edge(e); - PyList_SetItem(edges, e, Py_BuildValue("(nn)", edge[0], edge[1])); - } - - PyObject* weights = PyList_New(m); - for (size_t e = 0; e < m; e++) - { - PyObject* item = PyFloat_FromDouble(graph->edge_weight(e)); - PyList_SetItem(weights, e, item); - } - - PyObject* node_sizes = PyList_New(n); - for (size_t v = 0; v < n; v++) - { - PyObject* item = PyLong_FromSize_t(graph->node_size(v)); - PyList_SetItem(node_sizes, v, item); - } - - return Py_BuildValue("lOOOO", n, graph->is_directed() ? Py_True : Py_False, edges, weights, node_sizes); - } - - PyObject* _MutableVertexPartition_from_coarse_partition(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_partition = NULL; - PyObject* py_membership = NULL; - PyObject* py_coarse_node = NULL; - - static const char* kwlist[] = {"partition", "membership", "coarse_node", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - // TODO : Instead of simply returning NULL, we should also set an error. - if (!PyArg_ParseTupleAndKeywords(args, keywds, "OO|O", (char**) kwlist, - &py_partition, &py_membership, &py_coarse_node)) - return NULL; - - #ifdef DEBUG - cerr << "from_coarse_partition();" << endl; - #endif - - vector membership; - try - { - membership = create_size_t_vector(py_membership); - } - catch (std::exception& e ) - { - string s = "Could not create membership vector: " + string(e.what()); - PyErr_SetString(PyExc_BaseException, s.c_str()); - return NULL; - } - - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - if (py_coarse_node != NULL && py_coarse_node != Py_None) - { - vector coarse_node; - try - { - coarse_node = create_size_t_vector(py_coarse_node); - } - catch (std::exception& e ) - { - string s = "Could not create coarse node vector: " + string(e.what()); - PyErr_SetString(PyExc_BaseException, s.c_str()); - return NULL; - } - - partition->from_coarse_partition(membership, coarse_node); - } - else - partition->from_coarse_partition(membership); - - Py_INCREF(Py_None); - return Py_None; - } - - PyObject* _MutableVertexPartition_renumber_communities(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_partition = NULL; - - static const char* kwlist[] = {"partition", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O", (char**) kwlist, - &py_partition)) - return NULL; - - #ifdef DEBUG - cerr << "renumber_communities();" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - partition->renumber_communities(); - - Py_INCREF(Py_None); - return Py_None; - } - - PyObject* _MutableVertexPartition_diff_move(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_partition = NULL; - size_t v; - size_t new_comm; - - static const char* kwlist[] = {"partition", "v", "new_comm", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "Onn", (char**) kwlist, - &py_partition, &v, &new_comm)) - return NULL; - - #ifdef DEBUG - cerr << "diff_move(" << v << ", " << new_comm << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - double diff = partition->diff_move(v, new_comm); - return PyFloat_FromDouble(diff); - } - - PyObject* _MutableVertexPartition_move_node(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_partition = NULL; - size_t v; - size_t new_comm; - - static const char* kwlist[] = {"partition", "v", "new_comm", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "Onn", (char**) kwlist, - &py_partition, &v, &new_comm)) - return NULL; - - #ifdef DEBUG - cerr << "move_node(" << v << ", " << new_comm << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - if (new_comm >= partition->get_graph()->vcount()) - { - PyErr_SetString(PyExc_TypeError, "Community membership cannot exceed number of nodes."); - return NULL; - } - else if (new_comm < 0) - { - PyErr_SetString(PyExc_TypeError, "Community membership cannot be negative"); - return NULL; - } - - partition->move_node(v, new_comm); - - Py_INCREF(Py_None); - return Py_None; - } - - PyObject* _MutableVertexPartition_quality(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_partition = NULL; - - static const char* kwlist[] = {"partition", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O", (char**) kwlist, - &py_partition)) - return NULL; - - #ifdef DEBUG - cerr << "quality();" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - double q = partition->quality(); - return PyFloat_FromDouble(q); - } - - PyObject* _MutableVertexPartition_aggregate_partition(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_partition = NULL; - - static const char* kwlist[] = {"partition", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O", (char**) kwlist, - &py_partition)) - return NULL; - - #ifdef DEBUG - cerr << "aggregate_partition();" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - // First collapse graph (i.e. community graph) - Graph* collapsed_graph = partition->get_graph()->collapse_graph(partition); - - // Create collapsed partition (i.e. default partition of each node in its own community). - MutableVertexPartition* collapsed_partition = partition->create(collapsed_graph); - collapsed_partition->destructor_delete_graph = true; - - PyObject* py_collapsed_partition = capsule_MutableVertexPartition(collapsed_partition); - return py_collapsed_partition; - } - - PyObject* _MutableVertexPartition_total_weight_in_comm(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_partition = NULL; - size_t comm; - - static const char* kwlist[] = {"partition", "comm", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "On", (char**) kwlist, - &py_partition, &comm)) - return NULL; - - #ifdef DEBUG - cerr << "total_weight_in_comm(" << comm << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - if (comm >= partition->n_communities()) - { - PyErr_SetString(PyExc_IndexError, "Try to index beyond the number of communities."); - return NULL; - } - - double w = partition->total_weight_in_comm(comm); - return PyFloat_FromDouble(w); - } - - PyObject* _MutableVertexPartition_total_weight_from_comm(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_partition = NULL; - size_t comm; - - static const char* kwlist[] = {"partition", "comm", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "On", (char**) kwlist, - &py_partition, &comm)) - return NULL; - - #ifdef DEBUG - cerr << "total_weight_from_comm(" << comm << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - - if (comm >= partition->n_communities()) - { - PyErr_SetString(PyExc_IndexError, "Try to index beyond the number of communities."); - return NULL; - } - - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - double w = partition->total_weight_from_comm(comm); - return PyFloat_FromDouble(w); - } - - PyObject* _MutableVertexPartition_total_weight_to_comm(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_partition = NULL; - size_t comm; - - static const char* kwlist[] = {"partition", "comm", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "On", (char**) kwlist, - &py_partition, &comm)) - return NULL; - - #ifdef DEBUG - cerr << "total_weight_to_comm(" << comm << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - - if (comm >= partition->n_communities()) - { - PyErr_SetString(PyExc_IndexError, "Try to index beyond the number of communities."); - return NULL; - } - - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - double w = partition->total_weight_to_comm(comm); - return PyFloat_FromDouble(w); - } - - PyObject* _MutableVertexPartition_total_weight_in_all_comms(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_partition = NULL; - - static const char* kwlist[] = {"partition", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O", (char**) kwlist, - &py_partition)) - return NULL; - - #ifdef DEBUG - cerr << "total_weight_in_all_comms();" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - double w = partition->total_weight_in_all_comms(); - return PyFloat_FromDouble(w); - } - - PyObject* _MutableVertexPartition_total_possible_edges_in_all_comms(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_partition = NULL; - - static const char* kwlist[] = {"partition", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O", (char**) kwlist, - &py_partition)) - return NULL; - - #ifdef DEBUG - cerr << "total_possible_edges_in_all_comms();" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - size_t e = partition->total_possible_edges_in_all_comms(); - return PyLong_FromSize_t(e); - } - - PyObject* _MutableVertexPartition_weight_to_comm(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_partition = NULL; - size_t v; - size_t comm; - - static const char* kwlist[] = {"partition", "v", "comm", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "Onn", (char**) kwlist, - &py_partition, &v, &comm)) - return NULL; - - #ifdef DEBUG - cerr << "weight_to_comm(" << v << ", " << comm << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - - if (comm >= partition->n_communities()) - { - PyErr_SetString(PyExc_IndexError, "Try to index beyond the number of communities."); - return NULL; - } - - if (v >= partition->get_graph()->vcount()) - { - PyErr_SetString(PyExc_IndexError, "Try to index beyond the number of nodes."); - return NULL; - } - - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - double diff = partition->weight_to_comm(v, comm); - return PyFloat_FromDouble(diff); - } - - PyObject* _MutableVertexPartition_weight_from_comm(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_partition = NULL; - size_t v; - size_t comm; - - static const char* kwlist[] = {"partition", "v", "comm", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "Onn", (char**) kwlist, - &py_partition, &v, &comm)) - return NULL; - - #ifdef DEBUG - cerr << "weight_to_comm(" << v << ", " << comm << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - - if (comm >= partition->n_communities()) - { - PyErr_SetString(PyExc_IndexError, "Try to index beyond the number of communities."); - return NULL; - } - - if (v >= partition->get_graph()->vcount()) - { - PyErr_SetString(PyExc_IndexError, "Try to index beyond the number of nodes."); - return NULL; - } - - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - double diff = partition->weight_to_comm(v, comm); - return PyFloat_FromDouble(diff); - } - - PyObject* _MutableVertexPartition_get_membership(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_partition = NULL; - static const char* kwlist[] = {"partition", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O", (char**) kwlist, - &py_partition)) - return NULL; - - #ifdef DEBUG - cerr << "get_membership();" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - size_t n = partition->get_graph()->vcount(); - PyObject* py_membership = PyList_New(n); - for (size_t v = 0; v < n; v++) - { - PyObject* item = PyLong_FromSize_t(partition->membership(v)); - PyList_SetItem(py_membership, v, item); - } - return py_membership; - } - - PyObject* _MutableVertexPartition_set_membership(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_partition = NULL; - PyObject* py_membership = NULL; - - static const char* kwlist[] = {"partition", "membership", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "OO", (char**) kwlist, - &py_partition, &py_membership)) - return NULL; - - #ifdef DEBUG - cerr << "set_membership();" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - - MutableVertexPartition* partition = decapsule_MutableVertexPartition(py_partition); - - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - try - { - partition->set_membership(create_size_t_vector(py_membership)); - } - catch (std::exception& e ) - { - string s = "Could not set membership: " + string(e.what()); - PyErr_SetString(PyExc_BaseException, s.c_str()); - return NULL; - } - - #ifdef DEBUG - cerr << "Exiting set_membership();" << endl; - #endif - - Py_INCREF(Py_None); - return Py_None; - } - - PyObject* _ResolutionParameterVertexPartition_get_resolution(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_partition = NULL; - static const char* kwlist[] = {"partition", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O", (char**) kwlist, - &py_partition)) - return NULL; - - #ifdef DEBUG - cerr << "get_resolution();" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule ResolutionParameterVertexPartition at address " << py_partition << endl; - #endif - ResolutionParameterVertexPartition* partition = (ResolutionParameterVertexPartition*)decapsule_MutableVertexPartition(py_partition); - #ifdef DEBUG - cerr << "Using ResolutionParameterVertexPartition at address " << partition << endl; - #endif - - return PyFloat_FromDouble(partition->resolution_parameter); - } - - PyObject* _ResolutionParameterVertexPartition_set_resolution(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_partition = NULL; - double resolution_parameter = 1.0; - static const char* kwlist[] = {"partition", "resolution_parameter", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "Od", (char**) kwlist, - &py_partition, &resolution_parameter)) - return NULL; - - #ifdef DEBUG - cerr << "set_resolution(" << resolution_parameter << ");" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule ResolutionParameterVertexPartition at address " << py_partition << endl; - #endif - ResolutionParameterVertexPartition* partition = (ResolutionParameterVertexPartition*)decapsule_MutableVertexPartition(py_partition); - #ifdef DEBUG - cerr << "Using ResolutionParameterVertexPartition at address " << partition << endl; - #endif - - partition->resolution_parameter = resolution_parameter; - - Py_INCREF(Py_None); - return Py_None; - } - - PyObject* _ResolutionParameterVertexPartition_quality(PyObject *self, PyObject *args, PyObject *keywds) - { - PyObject* py_partition = NULL; - PyObject* py_res = NULL; - double resolution_parameter = 0.0; - - static const char* kwlist[] = {"partition", "resolution_parameter", NULL}; - - #ifdef DEBUG - cerr << "Parsing arguments..." << endl; - #endif - - if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|O", (char**) kwlist, - &py_partition, &py_res)) - return NULL; - - #ifdef DEBUG - cerr << "quality();" << endl; - #endif - - #ifdef DEBUG - cerr << "Capsule partition at address " << py_partition << endl; - #endif - - ResolutionParameterVertexPartition* partition = (ResolutionParameterVertexPartition*)decapsule_MutableVertexPartition(py_partition); - - if (py_res != NULL && py_res != Py_None) - { - if (PyNumber_Check(py_res)) - { - resolution_parameter = PyFloat_AsDouble(py_res); - } - else - { - PyErr_SetString(PyExc_TypeError, "Expected floating point value for resolution parameter."); - return NULL; - } - - if (isnan(resolution_parameter)) - { - PyErr_SetString(PyExc_TypeError, "Cannot accept NaN resolution parameter."); - return NULL; - } - } - else - resolution_parameter = partition->resolution_parameter; - - #ifdef DEBUG - cerr << "Using partition at address " << partition << endl; - #endif - - double q = partition->quality(resolution_parameter); - return PyFloat_FromDouble(q); - } - -#ifdef __cplusplus -} -#endif diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/tests/__init__.py b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/tests/test_Optimiser.py b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/tests/test_Optimiser.py deleted file mode 100644 index dc2ca1d..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/tests/test_Optimiser.py +++ /dev/null @@ -1,171 +0,0 @@ -import unittest -import igraph as ig -import leidenalg - -from functools import reduce - -class OptimiserTest(unittest.TestCase): - - def setUp(self): - self.optimiser = leidenalg.Optimiser() - - def test_move_nodes(self): - G = ig.Graph.Full(100) - partition = leidenalg.CPMVertexPartition(G, resolution_parameter=0.5) - self.optimiser.move_nodes(partition, consider_comms=leidenalg.ALL_NEIGH_COMMS) - self.assertListEqual( - partition.sizes(), [100], - msg="CPMVertexPartition(resolution_parameter=0.5) of complete graph after move nodes incorrect.") - - def test_move_nodes_with_max_comm_size(self): - G = ig.Graph.Full(100) - partition = leidenalg.CPMVertexPartition(G, resolution_parameter=0.5) - self.optimiser.max_comm_size = 17 - self.optimiser.move_nodes(partition, consider_comms=leidenalg.ALL_NEIGH_COMMS) - self.assertListEqual( - partition.sizes(), [17, 17, 17, 17, 17, 15], - msg="CPMVertexPartition(resolution_parameter=0.5) of complete graph after move nodes (max_comm_size=17) incorrect.") - - def test_move_nodes_with_fixed(self): - # One edge plus singleton, but the two connected nodes are fixed - G = ig.Graph([(0, 2)]) - is_membership_fixed = [True, False, True] - partition = leidenalg.CPMVertexPartition( - G, - resolution_parameter=0.1) - self.optimiser.move_nodes(partition, is_membership_fixed=is_membership_fixed, consider_comms=leidenalg.ALL_NEIGH_COMMS) - self.assertListEqual( - partition.sizes(), [1, 1, 1], - msg="CPMVertexPartition(resolution_parameter=0.1) of one edge plus singleton after move nodes with fixed nodes is incorrect.") - - def test_merge_nodes(self): - G = ig.Graph.Full(100) - partition = leidenalg.CPMVertexPartition(G, resolution_parameter=0.5) - self.optimiser.merge_nodes(partition, consider_comms=leidenalg.ALL_NEIGH_COMMS) - self.assertListEqual( - partition.sizes(), [100], - msg="CPMVertexPartition(resolution_parameter=0.5) of complete graph after merge nodes incorrect.") - self.assertEqual( - partition.total_weight_in_all_comms(), - G.ecount(), - msg="total_weight_in_all_comms not equal to ecount of graph.") - - def test_merge_nodes_with_max_comm_size(self): - G = ig.Graph.Full(100) - partition = leidenalg.CPMVertexPartition(G, resolution_parameter=0.5) - self.optimiser.max_comm_size = 17 - self.optimiser.merge_nodes(partition, consider_comms=leidenalg.ALL_NEIGH_COMMS) - self.assertListEqual( - partition.sizes(), [17, 17, 17, 17, 17, 15], - msg="CPMVertexPartition(resolution_parameter=0.5) of complete graph after merge nodes (max_comm_size=17) incorrect.") - - def test_diff_move_node_optimality(self): - G = ig.Graph.Erdos_Renyi(100, p=5./100, directed=False, loops=False) - partition = leidenalg.CPMVertexPartition(G, resolution_parameter=0.1) - while 0 < self.optimiser.move_nodes(partition, consider_comms=leidenalg.ALL_NEIGH_COMMS): - pass - for v in G.vs: - neigh_comms = set(partition.membership[u.index] for u in v.neighbors()) - for c in neigh_comms: - self.assertLessEqual( - partition.diff_move(v.index, c), 1e-10, # Allow for a small difference up to rounding error. - msg="Was able to move a node to a better community, violating node optimality.") - - def test_optimiser(self): - G = reduce(ig.Graph.disjoint_union, (ig.Graph.Tree(10, 3, mode=ig.TREE_UNDIRECTED) for i in range(10))) - partition = leidenalg.CPMVertexPartition(G, resolution_parameter=0) - self.optimiser.consider_comms=leidenalg.ALL_NEIGH_COMMS - self.optimiser.optimise_partition(partition) - self.assertListEqual( - partition.sizes(), 10*[10], - msg="After optimising partition failed to find different components with CPMVertexPartition(resolution_parameter=0)") - - def test_optimiser_with_max_comm_size(self): - G = ig.Graph.Full(100) - partition = leidenalg.CPMVertexPartition(G, resolution_parameter=0) - self.optimiser.consider_comms=leidenalg.ALL_NEIGH_COMMS - self.optimiser.max_comm_size = 10 - self.optimiser.optimise_partition(partition) - self.assertListEqual( - partition.sizes(), 10*[10], - msg="After optimising partition (max_comm_size=10) failed to find different components with CPMVertexPartition(resolution_parameter=0)") - - def test_optimiser_split_with_max_comm_size(self): - G = ig.Graph.Full(100) - partition = leidenalg.CPMVertexPartition(G, resolution_parameter=0.5) - self.optimiser.merge_nodes(partition, consider_comms=leidenalg.ALL_NEIGH_COMMS) - self.assertListEqual( - partition.sizes(), [100], - msg="CPMVertexPartition(resolution_parameter=0.5) of complete graph after merge nodes incorrect.") - self.optimiser.max_comm_size = 10 - self.optimiser.optimise_partition(partition) - self.assertListEqual( - partition.sizes(), 10*[10], - msg="After optimising partition (max_comm_size=10) failed to find different components with CPMVertexPartition(resolution_parameter=0.5)") - - def test_optimiser_with_is_membership_fixed(self): - G = ig.Graph.Full(3) - partition = leidenalg.CPMVertexPartition( - G, - resolution_parameter=0.01, - initial_membership=[2, 1, 0]) - # Equivalent to setting initial membership - #partition.set_membership([2, 1, 2]) - is_membership_fixed = [True, False, False] - original_quality = partition.quality() - diff = self.optimiser.optimise_partition(partition, is_membership_fixed=is_membership_fixed) - self.assertAlmostEqual(partition.quality() - original_quality, diff, places=10, - msg="Optimisation with fixed nodes returns inconsistent quality") - self.assertListEqual( - partition.membership, [2, 2, 2], - msg="After optimising partition with fixed nodes failed to recover initial fixed memberships" - ) - - def test_optimiser_is_membership_fixed_large_labels(self): - G = ig.Graph.Erdos_Renyi(n=100, p=5./100, directed=True, loops=True) - - membership = list(range(G.vcount())) - partition = leidenalg.RBConfigurationVertexPartition(G, initial_membership=membership) - - # large enough to force nonconsecutive labels in the final partition - fixed_node_idx = 90 - is_membership_fixed = [False] * G.vcount() - is_membership_fixed[fixed_node_idx] = True - - original_quality = partition.quality() - diff = self.optimiser.optimise_partition(partition, is_membership_fixed=is_membership_fixed) - - self.assertLess(len(set(partition.membership)), len(partition), - msg="Optimisation with fixed nodes yielded too many communities") - self.assertAlmostEqual(partition.quality() - original_quality, diff, places=10, - msg="Optimisation with fixed nodes returned inconsistent quality") - self.assertEqual(partition.membership[fixed_node_idx], fixed_node_idx, - msg="Optimisation with fixed nodes failed to keep the associated community labels fixed") - - - def test_neg_weight_bipartite(self): - G = ig.Graph.Full_Bipartite(50, 50) - G.es['weight'] = -0.1 - partition = leidenalg.CPMVertexPartition(G, resolution_parameter=-0.1, weights='weight') - self.optimiser.consider_comms=leidenalg.ALL_COMMS - self.optimiser.optimise_partition(partition) - self.assertListEqual( - partition.sizes(), 2*[50], - msg="After optimising partition failed to find bipartite structure with CPMVertexPartition(resolution_parameter=-0.1)") - - def test_resolution_profile(self): - G = ig.Graph.Famous('Zachary') - profile = self.optimiser.resolution_profile(G, leidenalg.CPMVertexPartition, resolution_range=(0,1)) - self.assertListEqual( - profile[0].sizes(), [G.vcount()], - msg="Resolution profile incorrect: at resolution 0, not equal to a single community for CPM.") - self.assertListEqual( - profile[-1].sizes(), [1]*G.vcount(), - msg="Resolution profile incorrect: at resolution 1, not equal to a singleton partition for CPM.") - -#%% -if __name__ == '__main__': - #%% - unittest.main(verbosity=3) - suite = unittest.TestLoader().discover('.') - unittest.TextTestRunner(verbosity=1).run(suite) diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/tests/test_VertexPartition.py b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/tests/test_VertexPartition.py deleted file mode 100644 index 9d0a90d..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/tests/test_VertexPartition.py +++ /dev/null @@ -1,226 +0,0 @@ -import unittest -import igraph as ig -import leidenalg -import random -from copy import deepcopy - -from ddt import ddt, data, unpack - -#%% - -def name_object(obj, name): - obj.__name__ = name - return obj - -graphs = [ - ########################################################################### - # Zachary karate network - name_object(ig.Graph.Famous('Zachary'), - 'Zachary'), - - ########################################################################### - # ER Networks - # Undirected no loop - name_object(ig.Graph.Erdos_Renyi(100, p=1./100, directed=False, loops=False), - 'ER_k1_undirected_no_loops'), - name_object(ig.Graph.Erdos_Renyi(100, p=5./100, directed=False, loops=False), - 'ER_k5_undirected_no_loops'), - # Directed no loop - name_object(ig.Graph.Erdos_Renyi(100, p=1./100, directed=True, loops=False), - 'ER_k1_directed_no_loops'), - name_object(ig.Graph.Erdos_Renyi(100, p=5./100, directed=True, loops=False), - 'ER_k5_directed_no_loops'), - # Undirected loops - name_object(ig.Graph.Erdos_Renyi(100, p=1./100, directed=False, loops=True), - 'ER_k1_undirected_loops'), - name_object(ig.Graph.Erdos_Renyi(100, p=5./100, directed=False, loops=True), - 'ER_k5_undirected_loops'), - # Directed loops - name_object(ig.Graph.Erdos_Renyi(100, p=1./100, directed=True, loops=True), - 'ER_k1_directed_loops'), - name_object(ig.Graph.Erdos_Renyi(100, p=5./100, directed=True, loops=True), - 'ER_k5_directed_loops'), - - ########################################################################### - # Tree - name_object(ig.Graph.Tree(100, 3, type=ig.TREE_UNDIRECTED), - 'Tree_undirected'), - name_object(ig.Graph.Tree(100, 3, type=ig.TREE_OUT), - 'Tree_directed_out'), - name_object(ig.Graph.Tree(100, 3, type=ig.TREE_IN), - 'Tree_directed_in'), - - ########################################################################### - # Lattice - name_object(ig.Graph.Lattice([100], nei=3, directed=False, mutual=True, circular=True), - 'Lattice_undirected'), - name_object(ig.Graph.Lattice([100], nei=3, directed=True, mutual=False, circular=True), - 'Lattice_directed') - ] - -bipartite_graph = name_object( - ig.Graph.Bipartite([0, 0, 0, 0, 1, 1, 1, 1], - [[0, 4], - [0, 5], - [0, 6], - [1, 4], - [1, 5], - [2, 6], - [2, 7], - [3, 6], - [3, 7], - [3, 5]]), - 'bipartite_example') - -def make_weighted(G): - m = G.ecount() - G.es['weight'] = [random.random() for i in range(G.ecount())] - G.__name__ += '_weighted' - return G - -graphs += [make_weighted(H) for H in graphs] - -class BaseTest: - @ddt - class MutableVertexPartitionTest(unittest.TestCase): - - def setUp(self): - self.optimiser = leidenalg.Optimiser() - - @data(*graphs) - def test_move_nodes(self, graph): - if 'weight' in graph.es.attributes() and self.partition_type == leidenalg.SignificanceVertexPartition: - raise unittest.SkipTest('Significance doesn\'t handle weighted graphs') - - if 'weight' in graph.es.attributes(): - partition = self.partition_type(graph, weights='weight') - else: - partition = self.partition_type(graph) - for v in range(graph.vcount()): - if graph.degree(v) >= 1: - u = graph.neighbors(v)[0] - diff = partition.diff_move(v, partition.membership[u]) - q1 = partition.quality() - partition.move_node(v, partition.membership[u]) - q2 = partition.quality() - self.assertAlmostEqual( - q2 - q1, - diff, - places=5, - msg="Difference in quality ({0}) not equal to calculated difference ({1})".format( - q2 - q1, diff)) - - @data(*graphs) - def test_aggregate_partition(self, graph): - if 'weight' in graph.es.attributes() and self.partition_type != leidenalg.SignificanceVertexPartition: - partition = self.partition_type(graph, weights='weight') - else: - partition = self.partition_type(graph) - self.optimiser.move_nodes(partition) - aggregate_partition = partition.aggregate_partition() - self.assertAlmostEqual( - partition.quality(), - aggregate_partition.quality(), - places=5, - msg='Quality not equal for aggregate partition.') - self.optimiser.move_nodes(aggregate_partition) - partition.from_coarse_partition(aggregate_partition) - self.assertAlmostEqual( - partition.quality(), - aggregate_partition.quality(), - places=5, - msg='Quality not equal from coarser partition.') - - @data(*graphs) - def test_total_weight_in_all_comms(self, graph): - if 'weight' in graph.es.attributes() and self.partition_type != leidenalg.SignificanceVertexPartition: - partition = self.partition_type(graph, weights='weight') - else: - partition = self.partition_type(graph) - self.optimiser.optimise_partition(partition) - s = sum([partition.total_weight_in_comm(c) for c,_ in enumerate(partition)]) - self.assertAlmostEqual( - s, - partition.total_weight_in_all_comms(), - places=5, - msg='Total weight in all communities ({0}) not equal to the sum of the weight in all communities ({1}).'.format( - s, partition.total_weight_in_all_comms()) - ) - - @data(*graphs) - def test_copy(self, graph): - if 'weight' in graph.es.attributes() and self.partition_type != leidenalg.SignificanceVertexPartition: - partition = self.partition_type(graph, weights='weight') - else: - partition = self.partition_type(graph) - - self.optimiser.optimise_partition(partition) - - partition2 = deepcopy(partition) - - self.assertAlmostEqual( - partition.quality(), - partition2.quality(), - places=5, - msg='Quality of deepcopy ({0}) not equal to quality of original partition ({1}).'.format( - partition.quality(), partition2.quality()) - ) - - if (partition2.membership[0] == 0): - partition2.move_node(0, 1) - else: - partition2.move_node(0, 0) - - self.assertNotEqual( - partition.membership[0], - partition2.membership[0], - msg='Moving node 0 in the deepcopy to community {0} results in community membership {1} for node 0 also in original partition.'.format( - partition.membership[0], partition2.membership[0]) - ) - - -class ModularityVertexPartitionTest(BaseTest.MutableVertexPartitionTest): - def setUp(self): - super(ModularityVertexPartitionTest, self).setUp() - self.partition_type = leidenalg.ModularityVertexPartition - -class RBERVertexPartitionTest(BaseTest.MutableVertexPartitionTest): - def setUp(self): - super(RBERVertexPartitionTest, self).setUp() - self.partition_type = leidenalg.RBERVertexPartition - -class RBConfigurationVertexPartitionTest(BaseTest.MutableVertexPartitionTest): - def setUp(self): - super(RBConfigurationVertexPartitionTest, self).setUp() - self.partition_type = leidenalg.RBConfigurationVertexPartition - -class CPMVertexPartitionTest(BaseTest.MutableVertexPartitionTest): - def setUp(self): - super(CPMVertexPartitionTest, self).setUp() - self.partition_type = leidenalg.CPMVertexPartition - - def test_Bipartite(self): - graph = bipartite_graph - partition, partition_0, partition_1 = \ - leidenalg.CPMVertexPartition.Bipartite(graph, resolution_parameter_01=0.2) - self.optimiser.optimise_partition_multiplex( - [partition, partition_0, partition_1], - layer_weights=[1, -1, -1]) - self.assertEqual(len(partition), 1) - -class SurpriseVertexPartitionTest(BaseTest.MutableVertexPartitionTest): - def setUp(self): - super(SurpriseVertexPartitionTest, self).setUp() - self.partition_type = leidenalg.SurpriseVertexPartition - -class SignificanceVertexPartitionTest(BaseTest.MutableVertexPartitionTest): - def setUp(self): - super(SignificanceVertexPartitionTest, self).setUp() - self.partition_type = leidenalg.SignificanceVertexPartition - -#%% -if __name__ == '__main__': - #%% - unittest.main(verbosity=3) - suite = unittest.TestLoader().discover('.') - unittest.TextTestRunner(verbosity=1).run(suite) diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/gpl2.txt b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/gpl2.txt deleted file mode 100644 index d159169..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/gpl2.txt +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/gpl3.txt b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/gpl3.txt deleted file mode 100644 index 20d40b6..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/gpl3.txt +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/manual.cpp.html b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/manual.cpp.html deleted file mode 100644 index 313ced0..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/manual.cpp.html +++ /dev/null @@ -1,60049 +0,0 @@ - - - - - -
-1 Introduction
-    1.1 What is ALGLIB
-    1.2 ALGLIB license
-    1.3 Documentation license
-    1.4 Reference Manual and User Guide
-    1.5 Acknowledgements
-2 ALGLIB structure
-    2.1 Packages
-    2.2 Subpackages
-    2.3 Open Source and Commercial versions
-3 Compatibility
-    3.1 CPU
-    3.2 OS
-    3.3 Compiler
-    3.4 Optimization settings
-4 Compiling ALGLIB
-    4.1 Adding to your project
-    4.2 Configuring for your compiler
-    4.3 Improving performance (CPU-specific and OS-specific optimizations)
-    4.4 Examples (free and commercial editions)
-        4.4.1 Introduction
-        4.4.2 Compiling under Windows
-        4.4.3 Compiling under Linux
-5 Using ALGLIB
-    5.1 Thread-safety
-    5.2 Global definitions
-    5.3 Datatypes
-    5.4 Constants
-    5.5 Functions
-    5.6 Working with vectors and matrices
-    5.7 Using functions: 'expert' and 'friendly' interfaces
-    5.8 Handling errors
-    5.9 Working with Level 1 BLAS functions
-    5.10 Reading data from CSV files
-6 Working with commercial version
-    6.1 Benefits of commercial version
-    6.2 Working with SIMD support (Intel/AMD users)
-    6.3 Using multithreading
-        6.3.1 General information
-        6.3.2 SMT (CMT/hyper-threading) issues
-    6.4 Linking with Intel MKL
-        6.4.1 Using lightweight Intel MKL supplied by ALGLIB Project
-        6.4.2 Using your own installation of Intel MKL
-7 Advanced topics
-    7.1 Exception-free mode
-    7.2 Partial compilation
-    7.3 Testing ALGLIB
-8 ALGLIB packages and subpackages
-    8.1 AlglibMisc package
-    8.2 DataAnalysis package
-    8.3 DiffEquations package
-    8.4 FastTransforms package
-    8.5 Integration package
-    8.6 Interpolation package
-    8.7 LinAlg package
-    8.8 Optimization package
-    8.9 Solvers package
-    8.10 SpecialFunctions package
-    8.11 Statistics package
-
-
-
-

1 Introduction

- -

1.1 What is ALGLIB

- -

-ALGLIB is a cross-platform numerical analysis and data mining library. -It supports several programming languages (C++, C#, Delphi, VB.NET, Python) and several operating systems (Windows, *nix family). -

- -

-ALGLIB features include: -

- -
    -
  • Data analysis (classification/regression, including neural networks)
  • -
  • Optimization and nonlinear solvers
  • -
  • Interpolation and linear/nonlinear least-squares fitting
  • -
  • Linear algebra (direct algorithms, EVD/SVD), direct and iterative linear solvers, Fast Fourier Transform and many other algorithms (numerical integration, ODEs, statistics, special functions)
  • -
- -

-ALGLIB Project (the company behind ALGLIB) delivers to you several editions of ALGLIB: -

- -
    -
  • ALGLIB Free Edition - full functionality but limited performance and license
  • -
  • ALGLIB Commercial Edition - high-performance version of ALGLIB with business-friendly license
  • -
- -

-Free Edition is a serial version without multithreading support or extensive low-level optimizations (generic C or C# code). -Commercial Edition is a heavily optimized version of ALGLIB. -It supports multithreading, it was extensively optimized, and (on Intel platforms) - -our commercial users may enjoy precompiled version of ALGLIB which internally calls Intel MKL to accelerate low-level tasks. -We obtained license from Intel corp., which allows us to integrate Intel MKL into ALGLIB, so you don't have to buy separate license from Intel. -

- -

1.2 ALGLIB license

- -

-ALGLIB Free Edition is distributed under license which favors non-commmercial usage, -but is not well suited for commercial applications: -

- - - -

-ALGLIB Commercial Edition is distributed under license which is friendly to commericial users. -A copy of the commercial license can be found at http://www.alglib.net/commercial.php. -

- -

1.3 Documentation license

- -
-

-This reference manual is licensed under BSD-like documentation license: -

- -

-Copyright 1994-2017 Sergey Bochkanov, ALGLIB Project. All rights reserved. -

- -

-Redistribution and use of this document (ALGLIB Reference Manual) with or without modification, -are permitted provided that such redistributions will retain the above copyright notice, -this condition and the following disclaimer as the first (or last) lines of this file. -

- -

-THIS DOCUMENTATION IS PROVIDED BY THE ALGLIB PROJECT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ALGLIB PROJECT BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS DOCUMENTATION, EVEN IF ADVISED -OF THE POSSIBILITY OF SUCH DAMAGE. -

-
- -

1.4 Reference Manual and User Guide

- -

-ALGLIB Project provides two sources of information: ALGLIB Reference Manual (this document) and ALGLIB User Guide. -

- -

-ALGLIB Reference Manual contains full description of all publicly accessible ALGLIB units accompanied with examples. -Reference Manual is focused on the source code: it documents units, functions, structures and so on. -If you want to know what unit YYY can do or what subroutines unit ZZZ contains Reference Manual is a place to go. -Free software needs free documentation - that's why ALGLIB Reference Manual is licensed under BSD-like documentation license. -

- -

-Additionally to the Reference Manual we provide you User Guide. -User Guide is focused on more general questions: how fast ALGLIB is? how reliable it is? what are the strong and weak sides of the algorithms used? -We aim to make ALGLIB User Guide an important source of information both about ALGLIB and numerical analysis algorithms in general. -We want it to be a book about algorithms, not just software documentation. -And we want it to be unique - that's why ALGLIB User Guide is distributed under less-permissive personal-use-only license. -

- -

1.5 Acknowledgements

- -

-ALGLIB was not possible without contribution of the next open source projects: -

- - - -

-We also want to thank developers of the Intel's local development center (Nizhny Novgorod branch) -for their help during MKL integration. -

- - - - -

2 ALGLIB structure

- -

2.1 Packages

- -

-ALGLIB is a C++ interface to the computational core written in C. -Both C library and C++ wrapper are automatically generated by code generation tools developed within ALGLIB project. -Pre-3.0 versions of ALGLIB included more than 100 units, but it was difficult to work with such large number of files. -Since ALGLIB 3.0 all units are merged into 11 packages and two support units: -

- -
    -
  • alglibmisc.cpp - contains different algorithms which are hard to classify
  • -
  • dataanalysis.cpp - contains data mining algorithms
  • -
  • diffequations.cpp - contains differential equation solvers
  • -
  • fasttransforms.cpp - contains FFT and other related algorithms
  • -
  • integration.cpp - contains numerical integration algorithms
  • -
  • interpolation.cpp - contains interpolation algorithms
  • -
  • linalg.cpp - contains linear algebra algorithms
  • -
  • optimization.cpp - contains optimization algorithms
  • -
  • solvers.cpp - contains linear and nonlinear solvers
  • -
  • specialfunctions.cpp - contains special functions
  • -
  • statistics.cpp - statistics
  • -
  • alglibinternal.cpp - contains internal functions which are used by other packages, but not exposed to the external world
  • -
  • ap.cpp - contains publicly accessible vector/matrix classes, most important and general functions and other "basic" functionality
  • -
- -

-One package may rely on other ones, but we have tried to reduce number of dependencies. -Every package relies on ap.cpp and many packages rely on alglibinternal.cpp. -But many packages require only these two to work, and many other packages need significantly less than 13 packages. -For example, statistics.cpp requires two packages mentioned above and only one additional package - specialfunctions.cpp. -

- -

2.2 Subpackages

- -

-There is one more concept to learn - subpackages. -Every package was created from several source files. -For example (as of ALGLIB 3.0.0), linalg.cpp was created by merging together 14 .cpp files (C++ interface) and 14 .c files (computational core). -These files provide different functionality: one of them calculates triangular factorizations, another generates random matrices, and so on. -We've merged source code, but what to do with their documentation? -

- -

-Of course, we can merge their documentation (as we've merged units) in one big list of functions and data structures, but such list will be hard to read. -Instead, we have decided to merge source code, but leave documentation separate. -

- -

-If you look at the list of ALGLIB packages, you will see that each package includes several subpackages. -For example, linalg.cpp includes trfac, svd, evd and other subpackages. -These subpackages do no exist as separate files, namespaces or other entities. -They are just subsets of one large unit which provide significantly different functionality. -They have separate documentation sections, but if you want to use svd subpackage, you have to include linalg.h, not svd.h. -

- - -

2.3 Open Source and Commercial versions

- -

-ALGLIB comes in two versions - open source (GPL-licensed) and commercial (closed source) one. -Both versions have same functionality, i.e. may solve same set of problems. -However, commercial version differs from open source one in following aspects: -

- -
    -
  • -License. -Commercial ALGLIB is licensed under non-copyleft license which is friendly to commercial users. -
  • -
  • -Performance. -Many algorithms in commercial ALGLIB are multi-threaded and SIMD-optimized (when used on Intel systems). -Open source ALGLIB is single-threaded and can not efficiently use modern multicore CPU's.
    -You have to study comments on specific functions if you want to know whether they have multithreaded versions or not. -
  • -
- -

-This documentation applies to both versions of ALGLIB. -Detailed description of commercial version can be found below. -

- - -

3 Compatibility

- -

3.1 CPU

- -

-ALGLIB is compatible with any CPU which: -

- -
    -
  • supports double precision arithmetics
  • -
  • complies with IEEE 754 floating point standard (especially in its handling of IEEE special values)
  • -
  • either big-endian or little-endian (but not mixed-endian)
  • -
- -

-Most mainstream CPU's (in particular, x86, x86_64, ARM and SPARC) satisfy these requirements. -

- -

-As for Intel architecture, ALGLIB works with both FPU-based and SIMD-based implementations of floating point math. -80-bit internal representation used by Intel FPU is not a problem for ALGLIB. -

- -

3.2 OS

- -

-ALGLIB for C++ (both open source and commercial versions) can be compiled in OS-agnostic mode (no OS-specific preprocessor definitions), -when it is compatible with any OS which supports C++98 standard library. -In particular, it will work under any POSIX-compatible OS and under Windows. -

- -

-If you want to use multithreaded capabilities of commercial version of ALGLIB, -you should compile it in OS-specific mode by #defining either AE_OS=AE_WINDOWS -or AE_OS=AE_POSIX at compile time, depending on OS being used. -Former corresponds to any modern OS (32/64-bit Windows XP and later) from Windows family, -while latter means almost any POSIX-compatible OS. -It applies only to commercial version of ALGLIB. -Open source version is always OS-agnostic, even in the presence of OS-specific definitions. -

- -

3.3 Compiler

- -

-ALGLIB is compatible with any C++ compiler which: -

- -
    -
  • supports 32-bit and 64-bit signed integer datatypes
  • -
  • emits code which handles comparisons with IEEE special values without raising exception. -We don't require that x/0 will return INF. -But at least we must be able to compare double precision value with infinity or NAN without raising exception.
  • -
- -

-All modern compilers satisfy these requirements. -

- -

-However, some very old compilers (ten years old version of Borland C++ Builder, for example) may emit code which does not correctly work with IEEE special values. -If you use one of these old compilers, we recommend you to run ALGLIB test suite to ensure that library works. -

- -

3.4 Optimization settings

- -

-ALGLIB is compatible with any kind of optimizing compiler as long as: -

- -
    -
  • volatile modifier is correctly handled (i.e. compiler does not optimize volatile reads/writes)
  • -
  • optimized code correctly handles IEEE special values
  • -
- -

-Generally, all kinds of optimization that were marked by compiler vendor as "safe" are possible. For example, ALGLIB can be compiled: -

- -
    -
  • under MSVC: with /O1, /O2, /Og, /Os, /Ox, /Ot, /Oy, /fp:precise, /fp:except, /fp:strict
  • -
  • under GCC: with -O1, -O2, -O3, -Os
  • -
- -

-From the other side, following "unsafe" optimizations will break ALGLIB: -

- -
    -
  • under MSVC: /fp:fast
  • -
  • under GCC: -Ofast, -ffast-math
  • -
- -

4 Compiling ALGLIB

- -

4.1 Adding to your project

- -

-Adding ALGLIB to your project is easy - just pick packages you need and... add them to your project! -Under most used compilers (GCC, MSVC) it will work without any additional settings. -In other cases you will need to define several preprocessor definitions (this topic will be detailed below), but everything will still be simple. -

- -

-By "adding to your project" we mean that you should a) compile .cpp files with the rest of your project, and b) include .h files you need. -Do not include .cpp files - these files must be compiled separately, not as part of some larger source file. -The only files you should include are .h files, stored in the /src folder of the ALGLIB distribution. -

- -

-As you see, ALGLIB has no project files or makefiles. Why? There are several reasons: -

- -
    -
  • first, because many ALGLIB users don't need separate static library (which will be created by invoking makefile) - they prefer to integrate source code in their projects. -We have provided script-based build system before, but majority of our users prefer to build ALGLIB themselves. -
  • -
  • -second, because we want ALGLIB to be usable in any programming environment, whether it is Visual Studio, GNU build system or something else. -The best solution is to write package which doesn't depend on any particular programming environment. -
  • -
- -

-In any case, compiling ALGLIB is so simple that even without project file you can do it in several minutes. -

- -

4.2 Configuring for your compiler

- -

-If you use modern versions of MSVC or GCC, you don't need to configure ALGLIB at all. -But if you use outdated versions of these compilers (or something else), then you may need to tune definitions of several data types: -

- -
    -
  • alglib_impl::ae_int32_t - signed integer which is 32 bits wide
  • -
  • alglib_impl::ae_int64_t - signed integer which is 64 bits wide
  • -
  • alglib_impl::ae_uint64_t - unsigned integer which is 64 bits wide
  • -
  • alglib_impl::ae_int_t - signed integer which has same width as pointer
  • -
- -

-ALGLIB tries to autodetect your compiler and to define these types in compiler-specific manner: -

- -
    -
  • ae_int32_t is defined as int, because this type is 32 bits wide in all modern compilers.
  • -
  • ae_int64_t is defined as _int64 (MSVC) or as signed long long (GCC, Sun Studio).
  • -
  • ae_uint64_t is defined as unsigned _int64 (MSVC) or as unsigned long long (GCC, Sun Studio).
  • -
  • ae_int_t is defined as ptrdiff_t.
  • -
- -

-In most cases, it is enough. But if anything goes wrong, you have several options: -

- -
    -
  • if your compiler provides stdint.h, you can define AE_HAVE_STDINT conditional symbol
  • -
  • alternatively, you can manually define AE_INT32_T and/or AE_INT64_T and/or AE_UINT64_T and/or AE_INT_T symbols. -Just assign datatype name to them, and ALGLIB will automatically use your definition. -You may define all or just one/two types (those which are not detected automatically).
  • -
- - -

4.3 Improving performance (CPU-specific and OS-specific optimizations)

- -

-You can improve performance of ALGLIB in a several ways: -

- -
    -
  • by compiling with advanced optimization turned on
  • -
  • by telling ALGLIB about CPU it will run on
  • -
- -

-ALGLIB has two-layered structure: some set of basic performance-critical primitives is implemented using optimized code, -and the rest of the library is built on top of these primitives. -By default, ALGLIB uses generic C code to implement these primitives (matrix multiplication, decompositions, etc.). -This code works everywhere from Intel to SPARC. -However, you can tell ALGLIB that it will work under particular architecture by defining appropriate macro at the global level: -

- -
    -
  • defining AE_CPU=AE_INTEL - to tell ALGLIB that it will work under Intel
  • -
- -

-When AE_CPU macro is defined and equals to the AE_INTEL, it enables SIMD support. -ALGLIB will use cpuid instruction to determine SIMD presence at run-time and use SIMD-capable code. -ALGLIB uses SIMD intrinsics which are portable across different compilers and efficient enough for most practical purposes. -

- -

-If you want to use multithreaded capabilities of commercial version of ALGLIB, -you should compile it in OS-specific mode by #defining either AE_OS=AE_WINDOWS, -AE_OS=AE_POSIX or AE_OS=AE_LINUX (POSIX with Linux-specific extensions) at compile time, -depending on OS being used. -Former corresponds to any modern OS (32/64-bit Windows XP and later) from Windows family, -while latter means almost any POSIX-compatible OS (or any OS from the Linux family). -It applies only to commercial version of ALGLIB. -Open source version is always OS-agnostic, even in the presence of OS-specific definitions. -

- -

4.4 Examples (free and commercial editions)

- -

4.4.1 Introduction

- -

-In this section we'll consider different compilation scenarios for free and commercial versions of ALGLIB - -from simple platform-agnostic compilation to compiling/linking with MKL extensions. -

- -

-We assume that you unpacked ALGLIB distribution in the current directory and saved here demo.cpp file, -whose code is given below. Thus, in the current directory you should have exactly one file (demo.cpp) and -exactly one subdirectory (cpp folder with ALGLIB distribution). -

- -

4.4.2 Compiling under Windows

- -

-File listing below contains the very basic program which uses ALGLIB to perform matrix-matrix multiplication. -After that program evaluates performance of GEMM (function being called) and prints result to console. -We'll show how performance of this program continually increases as we add more and more sophisticated compiler options. -

- -
-demo.cpp (WINDOWS EXAMPLE)
-
-
-#include <stdio.h>
-#include <windows.h>
-#include "LinAlg.h"
-
-double counter()
-{
-    return 0.001*GetTickCount();
-}
-
-int main()
-{
-    alglib::real_2d_array a, b, c;
-    int n = 2000;
-    int i, j;
-    double timeneeded, flops;
-    
-    // Initialize arrays
-    a.setlength(n, n);
-    b.setlength(n, n);
-    c.setlength(n, n);
-    for(i=0; i<n; i++)
-        for(j=0; j<n; j++)
-        {
-            a[i][j] = alglib::randomreal()-0.5;
-            b[i][j] = alglib::randomreal()-0.5;
-            c[i][j] = 0.0;
-        }
-    
-    // Set global threading settings (applied to all ALGLIB functions);
-    // default is to perform serial computations, unless parallel execution
-    // is activated. Parallel execution tries to utilize all cores; this
-    // behavior can be changed with alglib::setnworkers() call.
-    alglib::setglobalthreading(alglib::parallel);
-    
-    // Perform matrix-matrix product.
-    flops = 2*pow((double)n, (double)3);
-    timeneeded = counter();
-    alglib::rmatrixgemm(
-        n, n, n,
-        1.0,
-        a, 0, 0, 0,
-        b, 0, 0, 1,
-        0.0,
-        c, 0, 0);
-    timeneeded = counter()-timeneeded;
-    
-    // Evaluate performance
-    printf("Performance is %.1f GFLOPS\n", (double)(1.0E-9*flops/timeneeded));
-    
-    return 0;
-}
-
-
- -

-Examples below cover Windows compilation from command line with MSVC. -It is very straightforward to adapt them to compilation from MSVC IDE - or to another compilers. -We assume that you already called %VCINSTALLDIR%\bin\amd64\vcvars64.bat batch file -which loads 64-bit build environment (or its 32-bit counterpart). -We also assume that current directory is clean before example is executed -(i.e. it has ONLY demo.cpp file and cpp folder). -We used 3.2 GHz 4-core CPU for this test. -

- -

-First example covers platform-agnostic compilation without optimization settings - the most simple way to compile ALGLIB. -This step is same in both open source and commercial editions. -However, in platform-agnostic mode ALGLIB is unable to use all performance related features present in commercial edition. -

- -

-We starts from copying all cpp and h files to current directory, -then we will compile them along with demo.cpp. -In this and following examples we will omit compiler output for the sake of simplicity. -

- -
-OS-agnostic mode, no compiler optimizations
-
-
-> copy cpp\src\*.* .
-> cl /I. /EHsc /Fedemo.exe *.cpp
-> demo.exe
-Performance is 0.7 GFLOPS
-
- -

-Well, 0.7 GFLOPS is not very impressing for a 3.2GHz CPU... Let's add /Ox to compiler parameters. -

- -
-OS-agnostic mode, /Ox optimization
-
-
-> cl /I. /EHsc /Fedemo.exe /Ox *.cpp
-> demo.exe
-Performance is 0.9 GFLOPS
-
- -

-Still not impressed. Let's turn on optimizations for x86 architecture: define AE_CPU=AE_INTEL. -This option provides some speed-up in both free and commercial editions of ALGLIB. -

- -
-OS-agnostic mode, ALGLIB knows it is x86/x64
-
-
-> cl /I. /EHsc /Fedemo.exe /Ox /DAE_CPU=AE_INTEL *.cpp
-> demo.exe
-Performance is 4.5 GFLOPS
-
- -

-It is good, but we have 4 cores - and only one of them was used. -Defining AE_OS=AE_WINDOWS allows ALGLIB to use Windows threads to parallelize execution of some functions. -Starting from this moment, our example applies only to Commercial Edition. -

- -
-ALGLIB knows it is Windows on x86/x64 CPU (COMMERCIAL EDITION)
-
-
-> cl /I. /EHsc /Fedemo.exe /Ox /DAE_CPU=AE_INTEL /DAE_OS=AE_WINDOWS *.cpp
-> demo.exe
-Performance is 16.0 GFLOPS
-
- -

-Not bad. -And now we are ready to the final test - linking with MKL extensions. -

- -

-Linking with MKL extensions differs a bit from standard way of linking with ALGLIB. -ALGLIB itself is compiled with one more preprocessor definition: we define AE_MKL symbol. -We also link ALGLIB with appropriate (32-bit or 64-bit) alglib???_??mkl.lib static library, -which is an import library for special lightweight MKL distribution, shipped with ALGLIB. -We also should copy to current directory appropriate alglib???_??mkl.dll binary file which contains Intel MKL. -

- -
-Linking with MKL extensions (COMMERCIAL EDITION)
-
-
-> copy cpp\addons-mkl\alglib*64mkl.lib .
-> copy cpp\addons-mkl\alglib*64mkl.dll .
-> cl /I. /EHsc /Fedemo.exe /Ox /DAE_CPU=AE_INTEL /DAE_OS=AE_WINDOWS /DAE_MKL *.cpp alglib*64mkl.lib
-> demo.exe
-Performance is 33.1 GFLOPS
-
- -

-From 0.7 GFLOPS to 33.1 GFLOPS - you may see that commercial version of ALGLIB is really worth it! -

- -

4.4.3 Compiling under Linux

- -

-File listing below contains the very basic program which uses ALGLIB to perform matrix-matrix multiplication. -After that program evaluates performance of GEMM (function being called) and prints result to console. -We'll show how performance of this program continually increases as we add more and more sophisticated compiler options. -

- -
-demo.cpp (LINUX EXAMPLE)
-
-
-#include <stdio.h>
-#include <sys/time.h>
-#include "LinAlg.h"
-
-double counter()
-{
-    struct timeval now;
-    alglib_impl::ae_int64_t r, v;
-    gettimeofday(&now, NULL);
-    v = now.tv_sec;
-    r = v*1000;
-    v = now.tv_usec/1000;
-    r = r+v;
-    return 0.001*r;
-}
-
-int main()
-{
-    alglib::real_2d_array a, b, c;
-    int n = 2000;
-    int i, j;
-    double timeneeded, flops;
-    
-    // Initialize arrays
-    a.setlength(n, n);
-    b.setlength(n, n);
-    c.setlength(n, n);
-    for(i=0; i<n; i++)
-        for(j=0; j<n; j++)
-        {
-            a[i][j] = alglib::randomreal()-0.5;
-            b[i][j] = alglib::randomreal()-0.5;
-            c[i][j] = 0.0;
-        }
-    
-    // Set global threading settings (applied to all ALGLIB functions);
-    // default is to perform serial computations, unless parallel execution
-    // is activated. Parallel execution tries to utilize all cores; this
-    // behavior can be changed with alglib::setnworkers() call.
-    alglib::setglobalthreading(alglib::parallel);
-    
-    // Perform matrix-matrix product.
-    flops = 2*pow((double)n, (double)3);
-    timeneeded = counter();
-    alglib::rmatrixgemm(
-        n, n, n,
-        1.0,
-        a, 0, 0, 0,
-        b, 0, 0, 1,
-        0.0,
-        c, 0, 0);
-    timeneeded = counter()-timeneeded;
-    
-    // Evaluate performance
-    printf("Performance is %.1f GFLOPS\n", (double)(1.0E-9*flops/timeneeded));
-    
-    return 0;
-}
-
-
- -

-Examples below cover x64 Linux compilation from command line with GCC. -We assume that current directory is clean before example is executed -(i.e. it has ONLY demo.cpp file and cpp folder). -We used 2.3 GHz 2-core Skylake CPU with 2x Hyperthreading enabled for this test. -

- -

-First example covers platform-agnostic compilation without optimization settings - the most simple way to compile ALGLIB. -This step is same in both open source and commercial editions. -However, in platform-agnostic mode ALGLIB is unable to use all performance related features present in commercial edition. -

- -

-We starts from copying all cpp and h files to current directory, -then we will compile them along with demo.cpp. -In this and following examples we will omit compiler output for the sake of simplicity. -

- -
-OS-agnostic mode, no compiler optimizations
-
-
-> cp cpp/src/* .
-> g++ -I. -o demo.out *.cpp
-> ./demo.out
-Performance is 0.9 GFLOPS
-
- -

-Let's add -O3 to compiler parameters. -

- -
-OS-agnostic mode, -O3 optimization
-
-
-> g++ -I. -o demo.out -O3 *.cpp
-> ./demo.out
-Performance is 2.8 GFLOPS
-
- -

-Better, but not impressed. Let's turn on optimizations for x86 architecture: define AE_CPU=AE_INTEL. -This option provides some speed-up in both free and commercial editions of ALGLIB. -

- -
-OS-agnostic mode, ALGLIB knows it is x86/x64
-
-
-> g++ -I. -o demo.out -O3 -DAE_CPU=AE_INTEL *.cpp
-> ./demo.out
-Performance is 5.0 GFLOPS
-
- -

-It is good, but we have 4 cores (in fact, 2 cores - it is 2-way hyperthreaded system) and only one of them was used. -Defining AE_OS=AE_POSIX allows ALGLIB to use POSIX threads to parallelize execution of some functions. -You should also specify -pthread flag to link with pthreads standard library. -Starting from this moment, our example applies only to Commercial Edition. -

- -
-ALGLIB knows it is POSIX OS on x86/x64 CPU (COMMERCIAL EDITION)
-
-
-> g++ -I. -o demo.out -O3 -DAE_CPU=AE_INTEL -DAE_OS=AE_POSIX -pthread *.cpp
-> ./demo.out
-Performance is 9.0 GFLOPS
-
- -

-Not bad. You may notice that performance growth was ~2x, not 4x. -The reason is that we tested ALGLIB on hyperthreaded system: although we have 4 logical cores, -they share computational resources of just 2 physical cores. -And now we are ready to the final test - linking with MKL extensions. -

- -

-Linking with MKL extensions differs a bit from standard way of linking with ALGLIB. -ALGLIB itself is compiled with one more preprocessor definition: we define AE_MKL symbol. -We also link ALGLIB with appropriate alglib???_??mkl.so shared library, -which contains special lightweight MKL distribution shipped with ALGLIB. -

- -

-We should note that on typical Linux system shared libraries are not loaded from current directory by default. -Either you install them into one of the system directories, -or use some way to tell linker/loader that you want to load shared library from some specific directory. -For our example we choose to update LD_LIBRARY_PATH environment variable. -

- -
-Linking with MKL extensions (COMMERCIAL EDITION, relevant for ALGLIB 3.13)
-
-
-> cp cpp/addons-mkl/libalglib*64mkl.so .
-> ls *.so
-libalglib313_64mkl.so
-> g++ -I. -o demo.out -O3 -DAE_CPU=AE_INTEL -DAE_OS=AE_POSIX -pthread -DAE_MKL -L. *.cpp -lalglib313_64mkl
-> LD_LIBRARY_PATH=.
-> export LD_LIBRARY_PATH
-> ./demo.out
-Performance is 33.8 GFLOPS
-
- -

-Final result: from 0.9 GFLOPS to 33.8 GFLOPS! -

- - -

5 Using ALGLIB

- -

5.1 Thread-safety

- -

-Both open source and commercial versions of ALGLIB are 100% thread-safe -as long as different user threads work with different instances of objects/arrays. -Thread-safety is guaranteed by having no global shared variables. -

- -

-However, any kind of sharing ALGLIB objects/arrays between different threads is potentially hazardous. -Even when this object is seemingly used in read-only mode! -

- -

-Say, you use ALGLIB neural network NET to process two input vectors X0 and X1, -and get two output vectors Y0 and Y1. -You may decide that neural network is used in read-only mode which does not change state of NET, -because output is written to distinct arrays Y. -Thus, you may want to process these vectors from parallel threads. -

-But it is not read-only operation, even if it looks like that! -Neural network object NET allocates internal temporary buffers, which are modified by neural processing functions. -Thus, sharing one instance of neural network between two threads is thread-unsafe! -

- -

5.2 Global definitions

- -

-ALGLIB defines several conditional symbols (all start with "AE_" which means "ALGLIB environment") and two namespaces: -alglib_impl (contains computational core) and alglib (contains C++ interface). -

- -

-Although this manual mentions both alglib_impl and alglib namespaces, -only alglib namespace should be used by you. -It contains user-friendly C++ interface with automatic memory management, exception handling and all other nice features. -alglib_impl is less user-friendly, is less documented, -and it is too easy to crash your system or cause memory leak if you use it directly. -

- -

5.3 Datatypes

- -

-ALGLIB (ap.h header) defines several "basic" datatypes (types which are used by all packages) and many package-specific datatypes. "Basic" datatypes are: -

- -
    -
  • alglib::ae_int_t - signed integer type used by library
  • -
  • alglib::complex - double precision complex datatype, safer replacement for std::complex
  • -
  • alglib::ap_error - exception which is thrown by library
  • -
  • boolean_1d_array - 1-dimensional boolean array
  • -
  • integer_1d_array - 1-dimensional integer array
  • -
  • real_1d_array - 1-dimensional real (double precision) array
  • -
  • complex_1d_array - 1-dimensional complex array
  • -
  • boolean_2d_array - 2-dimensional boolean array
  • -
  • integer_2d_array - 2-dimensional integer array
  • -
  • real_2d_array - 2-dimensional real (double precision) array
  • -
  • complex_2d_array - 2-dimensional complex array
  • -
- -

-Package-specific datatypes are classes which can be divided into two distinct groups: -

- -
    -
  • "struct-like" classes with public fields which you can access directly.
  • -
  • "object-like" classes which have no public fields. You should use ALGLIB functions to work with them.
  • -
- -

5.4 Constants

- -

-The most important constants (defined in the ap.h header) from ALGLIB namespace are: -

- -
    -
  • alglib::machineepsilon - small number which is close to the double precision &eps;, but is slightly larger
  • -
  • alglib::maxrealnumber - very large number which is close to the maximum real number, but is slightly smaller
  • -
  • alglib::minrealnumber - very small number which is close to the minimum nonzero real number, but is slightly larger
  • -
  • alglib::fp_nan - NAN (non-signalling under most platforms except for PA-RISC, where it is signalling; -but when PA-RISC CPU is in its default state, it is silently converted to the quiet NAN)
  • -
  • alglib::fp_posinf - positive infinity
  • -
  • alglib::fp_neginf - negative infinity
  • -
- -

5.5 Functions

- -

-The most important "basic" functions from ALGLIB namespace (ap.h header) are: -

- -
    -
  • alglib::randomreal() - returns random real number from [0,1)
  • -
  • alglib::randominteger(mx) - returns random integer number from [0,nx); mx must be less than RAND_MAX
  • -
  • alglib::fp_eq(v1,v2) - makes IEEE-compliant comparison of two double precision numbers. -If numbers are represented with greater precision than specified by IEEE 754 (as with Intel 80-bit FPU), this functions converts them to 64 bits before comparing.
  • -
  • alglib::fp_neq(v1,v2) - makes IEEE-compliant comparison of two double precision numbers.
  • -
  • alglib::fp_less(v1,v2) - makes IEEE-compliant comparison of two double precision numbers.
  • -
  • alglib::fp_less_eq(v1,v2) - makes IEEE-compliant comparison of two double precision numbers.
  • -
  • alglib::fp_greater(v1,v2) - makes IEEE-compliant comparison of two double precision numbers.
  • -
  • alglib::fp_greater_eq(v1,v2) - makes IEEE-compliant comparison of two double precision numbers.
  • -
  • alglib::fp_isnan - checks whether number is NAN
  • -
  • alglib::fp_isposinf - checks whether number is +INF
  • -
  • alglib::fp_isneginf - checks whether number is -INF
  • -
  • alglib::fp_isinf - checks whether number is +INF or -INF
  • -
  • alglib::fp_isfinite - checks whether number is finite value (possibly subnormalized)
  • -
- -

5.6 Working with vectors and matrices

- -

-ALGLIB (ap.h header) supports matrixes and vectors (one-dimensional and two-dimensional arrays) of variable size, with numeration starting from zero. -

- -

-Everything starts from array creation. -You should distinguish the creation of array class instance and the memory allocation for the array. -When creating the class instance, you can use constructor without any parameters, that creates an empty array without any elements. -An attempt to address them may cause the program failure. -

- -

-You can use copy and assignment constructors that copy one array into another. -If, during the copy operation, the source array has no memory allocated for the array elements, destination array will contain no elements either. -If the source array has memory allocated for its elements, destination array will allocate the same amount of memory and copy the elements there. -That is, the copy operation yields into two independent arrays with indentical contents. -

- -

-You can also create array from formatted string like - "[]", - "[true,FALSE,tRUe]", - "[[]]]" or - "[[1,2],[3.2,4],[5.2]]" (note: '.' is used as decimal point independently from locale settings). -

- -
-alglib::boolean_1d_array b1;
-b1 = "[true]";
-
-alglib::real_2d_array r2("[[2,3],[3,4]]");
-alglib::real_2d_array r2_1("[[]]");
-alglib::real_2d_array r2_2(r2);
-r2_1 = r2;
-
-alglib::complex_1d_array c2;
-c2 = "[]";
-c2 = "[0]";
-c2 = "[1,2i]";
-c2 = "[+1-2i,-1+5i]";
-c2 = "[ 4i-2,  8i+2]";
-c2 = "[+4i-2, +8i+2]";
-c2 = "[-4i-2, -8i+2]";
-
- -

-After an empty array has been created, you can allocate memory for its elements, using the setlength() method. -The content of the created array elements is not defined. -If the setlength method is called for the array with already allocated memory, then, after changing its parameters, -the newly allocated elements also become undefined and the old content is destroyed. -

- -
-alglib::boolean_1d_array b1;
-b1.setlength(2);
-
-alglib::integer_2d_array r2;
-r2.setlength(4,3);
-
- -

-Another way to initialize array is to call setcontent() method. -This method accepts pointer to data which are copied into newly allocated array. -Vectors are stored in contiguous order, matrices are stored row by row. -

- -
-alglib::real_1d_array r1;
-double _r1[] = {2, 3};
-r1.setcontent(2,_r1);
-
-alglib::real_2d_array r2;
-double _r2[] = {11, 12, 13, 21, 22, 23};
-r2.setcontent(2,3,_r2);
-
- -

-You can also attach real vector/matrix object to already allocated double precision array -(attaching to boolean/integer/complex arrays is not supported). -In this case, no actual data is copied, and attached vector/matrix object becomes a read/write proxy for external array. -

- -
-alglib::real_1d_array r1;
-double a1[] = {2, 3};
-r1.attach_to_ptr(2,a1);
-
-alglib::real_2d_array r2;
-double a2[] = {11, 12, 13, 21, 22, 23};
-r2.attach_to_ptr(2,3,_r2);
-
- -

-To access the array elements, an overloaded operator() or operator[] can used. -That is, the code addressing the element of array a with indexes [i,j] can look like -a(i,j) or a[i][j]. -

- -
-alglib::integer_1d_array a("[1,2,3]");
-alglib::integer_1d_array b("[3,9,27]");
-a[0] = b(0);
-
-alglib::integer_2d_array c("[[1,2,3],[9,9,9]]");
-alglib::integer_2d_array d("[[3,9,27],[8,8,8]]");
-d[1][1] = c(0,0);
-
- -

-You can access contents of 1-dimensional array by calling getcontent() method which returns pointer to the array memory. -For historical reasons 2-dimensional arrays do not provide getcontent() method, but you can use create reference to any element of array. -2-dimensional arrays store data in row-major order with aligned rows (i.e. generally distance between rows is not equal to number of columns). -You can get stride (distance between consequtive elements in different rows) with getstride() call. -

- -
-alglib::integer_1d_array a("[1,2]");
-alglib::real_2d_array b("[[0,1],[10,11]]");
-
-alglib::ae_int_t *a_row = a.getcontent();
-
-// all three pointers point to the same location
-double *b_row0 = &b[0][0];
-double *b_row0_2 = &b(0,0);
-double *b_row0_3 = b[0];
-
-// advancing to the next row of 2-dimensional array
-double *b_row1 = b_row0 + b.getstride();
-
- -

-Finally, you can get array size with length(), rows() or cols() methods: -

- -
-alglib::integer_1d_array a("[1,2]");
-alglib::real_2d_array b("[[0,1],[10,11]]");
-
-printf("%ld\n", (long)a.length());
-printf("%ld\n", (long)b.rows());
-printf("%ld\n", (long)b.cols());
-
- -

5.7 Using functions: 'expert' and 'friendly' interfaces

- -

-Most ALGLIB functions provide two interfaces: 'expert' and 'friendly'. What is the difference between two? When you use 'friendly' interface, ALGLIB: -

- -
    -
  • tries to automatically determine size of input arguments
  • -
  • throws an exception when arguments have inconsistent size (for example, square matrix is expected, but non-square is passed; -another example - two parameters must have same size, but have different size)
  • -
  • if semantics of input parameter assumes that it is symmetric/Hermitian matrix, -checks that lower triangle is equal to upper triangle (conjugate of upper triangle) and throws an exception otherwise
  • -
  • if semantics of output parameter assumes that it is symmetric/Hermitian matrix, -returns full matrix (both upper and lower triangles)
  • -
- -

-When you use 'expert' interface, ALGLIB: -

- -
    -
  • requires caller to explicitly specify size of input arguments. -If vector/matrix is larger than size being specified (say, N), only N leading elements are used
  • -
  • if semantics of input parameter assumes that it is symmetric/Hermitian matrix, -uses only upper or lower triangle of input matrix and requires caller to specify what triangle to use
  • -
  • if semantics of output parameter assumes that it is symmetric/Hermitian matrix, returns only upper or lower triangle -(when you look at specific function, it is clear what triangle is returned)
  • -
- -

-Here are several examples of 'friendly' and 'expert' interfaces: -

- -
-#include "interpolation.h"
-
-...
-
-alglib::real_1d_array    x("[0,1,2,3]");
-alglib::real_1d_array    y("[1,5,3,9]");
-alglib::real_1d_array   y2("[1,5,3,9,0]");
-alglib::spline1dinterpolant s;
-
-alglib::spline1dbuildlinear(x, y, 4, s);  // 'expert' interface is used
-alglib::spline1dbuildlinear(x, y, s);     // 'friendly' interface - input size is
-                                          // automatically determined
-
-alglib::spline1dbuildlinear(x, y2, 4, s); // y2.length() is 5, but it will work
-
-alglib::spline1dbuildlinear(x, y2, s);    // it won't work because sizes of x and y2
-                                          // are inconsistent
-
- -

-'Friendly' interface - matrix semantics: -

- -
-#include "linalg.h"
-
-...
-
-alglib::real_2d_array a;
-alglib::matinvreport  rep;
-alglib::ae_int_t      info;
-
-// 
-// 'Friendly' interface: spdmatrixinverse() accepts and returns symmetric matrix
-// 
-
-// symmetric positive definite matrix
-a = "[[2,1],[1,2]]";
-
-// after this line A will contain [[0.66,-0.33],[-0.33,0.66]]
-// which is symmetric too
-alglib::spdmatrixinverse(a, info, rep); 
-
-// you may try to pass nonsymmetric matrix
-a = "[[2,1],[0,2]]";
-
-// but exception will be thrown in such case
-alglib::spdmatrixinverse(a, info, rep); 
-
- -

-Same function but with 'expert' interface: -

- -
-#include "linalg.h"
-
-...
-
-alglib::real_2d_array a;
-alglib::matinvreport  rep;
-alglib::ae_int_t      info;
-
-// 
-// 'Expert' interface, spdmatrixinverse()
-// 
-
-// only upper triangle is used; a[1][0] is initialized by NAN,
-// but it can be arbitrary number
-a = "[[2,1],[NAN,2]]";
-
-// after this line A will contain [[0.66,-0.33],[NAN,0.66]]
-// only upper triangle is modified
-alglib::spdmatrixinverse(a, 2 /* N */, true /* upper triangle is used */, info, rep); 
-
- - -

5.8 Handling errors

- -

-ALGLIB uses two error handling strategies: -

- -
    -
  • returning error code
  • -
  • throwing exception
  • -
- -

-What is actually done depends on function being used and error being reported: -

- -
    -
  1. if function returns some error code and has corresponding value for this kind of error, ALLGIB returns error code
  2. -
  3. if function does not return error code (or returns error code, but there is no code for error being reported), ALGLIB throws alglib::ap_error exception. -Exception object has msg parameter which contains short description of error.
  4. -
- -

-To make things clear we consider several examples of error handling. -

- -

-Example 1. mincgreate function creates nonlinear CG optimizer. It accepts problem size N and initial point X. -Several things can go wrong - you may pass array which is too short, filled by NAN's, or otherwise pass incorrect data. -However, this function returns no error code - so it throws an exception in case something goes wrong. -There is no other way to tell caller that something went wrong. -

- -

-Example 2. rmatrixinverse function calculates inverse matrix. -It returns error code, which is set to +1 when problem is solved and is set to -3 if singular matrix was passed to the function. -However, there is no error code for matrix which is non-square or contains infinities. -Well, we could have created corresponding error codes - but we didn't. -So if you pass singular matrix to rmatrixinverse, you will get completion code -3. -But if you pass matrix which contains INF in one of its elements, alglib::ap_error will be thrown. -

- -

-First error handling strategy (error codes) is used to report "frequent" errors -which can occur during normal execution of user program. -Second error handling strategy (exceptions) is used to report "rare" errors -which are result of serious flaws in your program (or ALGLIB) - -infinities/NAN's in the inputs, inconsistent inputs, etc. -

- - -

5.9 Working with Level 1 BLAS functions

- -

-ALGLIB (ap.h header) includes following Level 1 BLAS functions: -

- -
    -
  • alglib::vdotproduct() family, which allows to calculate dot product of two real or complex vectors
  • -
  • alglib::vmove() family, which allows to copy real/complex vector to another location with optimal multiplication by real/complex value
  • -
  • alglib::vmoveneg() family, which allows to copy real/complex vector to another location with multiplication by -1
  • -
  • alglib::vadd() and alglib::vsub() families, which allows to add or subtract two real/complex vectors with optimal multiplication by real/complex value
  • -
  • alglib::vmul() family, which implements in-place multiplication of real/complex vector by real/complex value
  • -
- -

-Each Level 1 BLAS function accepts input stride and output stride, which are expected to be positive. -Input and output vectors should not overlap. -Functions operating with complex vectors accept additional parameter conj_src, which specifies whether input vector is conjugated or not. -

- -

-For each real/complex function there exists "simple" companion which accepts no stride or conjugation modifier. -"Simple" function assumes that input/output stride is +1, and no input conjugation is required. -

- -
-alglib::real_1d_array    rvec("[0,1,2,3]");
-alglib::real_2d_array    rmat("[[1,2],[3,4]]");
-alglib::complex_1d_array cvec("[0+1i,1+2i,2-1i,3-2i]");
-alglib::complex_2d_array cmat("[[3i,1],[9,2i]]");
-
-alglib::vmove(&rvec[0],  1, &rmat[0][0], rmat.getstride(), 2); // now rvec is [1,3,2,3]
-
-alglib::vmove(&cvec[0],  1, &cmat[0][0], rmat.getstride(), "No conj", 2); // now cvec is [3i, 9, 2-1i, 3-2i]
-alglib::vmove(&cvec[2],  1, &cmat[0][0], 1,                "Conj", 2);    // now cvec is [3i, 9, -3i,  1]
-
- -

-Here is full list of Level 1 BLAS functions implemented in ALGLIB: -

- -
-double vdotproduct(
-    const double *v0,
-     ae_int_t stride0,
-     const double *v1,
-     ae_int_t stride1,
-     ae_int_t n);
-double vdotproduct(
-    const double *v1,
-     const double *v2,
-     ae_int_t N);
-
-alglib::complex vdotproduct(
-    const alglib::complex *v0,
-     ae_int_t stride0,
-     const char *conj0,
-     const alglib::complex *v1,
-     ae_int_t stride1,
-     const char *conj1,
-     ae_int_t n);
-alglib::complex vdotproduct(
-    const alglib::complex *v1,
-     const alglib::complex *v2,
-     ae_int_t N);
-
-void vmove(
-    double *vdst,
-      ae_int_t stride_dst,
-     const double* vsrc,
-      ae_int_t stride_src,
-     ae_int_t n);
-void vmove(
-    double *vdst,
-     const double* vsrc,
-     ae_int_t N);
-
-void vmove(
-    alglib::complex *vdst,
-     ae_int_t stride_dst,
-     const alglib::complex* vsrc,
-     ae_int_t stride_src,
-     const char *conj_src,
-     ae_int_t n);
-void vmove(
-    alglib::complex *vdst,
-     const alglib::complex* vsrc,
-     ae_int_t N);
-
-void vmoveneg(
-    double *vdst,
-      ae_int_t stride_dst,
-     const double* vsrc,
-      ae_int_t stride_src,
-     ae_int_t n);
-void vmoveneg(
-    double *vdst,
-     const double *vsrc,
-     ae_int_t N);
-
-void vmoveneg(
-    alglib::complex *vdst,
-     ae_int_t stride_dst,
-     const alglib::complex* vsrc,
-     ae_int_t stride_src,
-     const char *conj_src,
-     ae_int_t n);
-void vmoveneg(
-    alglib::complex *vdst,
-     const alglib::complex *vsrc,
-     ae_int_t N);
-
-void vmove(
-    double *vdst,
-      ae_int_t stride_dst,
-     const double* vsrc,
-      ae_int_t stride_src,
-     ae_int_t n,
-     double alpha);
-void vmove(
-    double *vdst,
-     const double *vsrc,
-     ae_int_t N,
-     double alpha);
-
-void vmove(
-    alglib::complex *vdst,
-     ae_int_t stride_dst,
-     const alglib::complex* vsrc,
-     ae_int_t stride_src,
-     const char *conj_src,
-     ae_int_t n,
-     double alpha);
-void vmove(
-    alglib::complex *vdst,
-     const alglib::complex *vsrc,
-     ae_int_t N,
-     double alpha);
-
-void vmove(
-    alglib::complex *vdst,
-     ae_int_t stride_dst,
-     const alglib::complex* vsrc,
-     ae_int_t stride_src,
-     const char *conj_src,
-     ae_int_t n,
-     alglib::complex alpha);
-void vmove(
-    alglib::complex *vdst,
-     const alglib::complex *vsrc,
-     ae_int_t N,
-     alglib::complex alpha);
-
-void vadd(
-    double *vdst,
-      ae_int_t stride_dst,
-     const double *vsrc,
-      ae_int_t stride_src,
-     ae_int_t n);
-void vadd(
-    double *vdst,
-     const double *vsrc,
-     ae_int_t N);
-
-void vadd(
-    alglib::complex *vdst,
-     ae_int_t stride_dst,
-     const alglib::complex *vsrc,
-     ae_int_t stride_src,
-     const char *conj_src,
-     ae_int_t n);
-void vadd(
-    alglib::complex *vdst,
-     const alglib::complex *vsrc,
-     ae_int_t N);
-
-void vadd(
-    double *vdst,
-      ae_int_t stride_dst,
-     const double *vsrc,
-      ae_int_t stride_src,
-     ae_int_t n,
-     double alpha);
-void vadd(
-    double *vdst,
-     const double *vsrc,
-     ae_int_t N,
-     double alpha);
-
-void vadd(
-    alglib::complex *vdst,
-     ae_int_t stride_dst,
-     const alglib::complex *vsrc,
-     ae_int_t stride_src,
-     const char *conj_src,
-     ae_int_t n,
-     double alpha);
-void vadd(
-    alglib::complex *vdst,
-     const alglib::complex *vsrc,
-     ae_int_t N,
-     double alpha);
-
-void vadd(
-    alglib::complex *vdst,
-     ae_int_t stride_dst,
-     const alglib::complex *vsrc,
-     ae_int_t stride_src,
-     const char *conj_src,
-     ae_int_t n,
-     alglib::complex alpha);
-void vadd(
-    alglib::complex *vdst,
-     const alglib::complex *vsrc,
-     ae_int_t N,
-     alglib::complex alpha);
-
-void vsub(
-    double *vdst,
-      ae_int_t stride_dst,
-     const double *vsrc,
-      ae_int_t stride_src,
-     ae_int_t n);
-void vsub(
-    double *vdst,
-     const double *vsrc,
-     ae_int_t N);
-
-void vsub(
-    alglib::complex *vdst,
-     ae_int_t stride_dst,
-     const alglib::complex *vsrc,
-     ae_int_t stride_src,
-     const char *conj_src,
-     ae_int_t n);
-void vsub(
-    alglib::complex *vdst,
-     const alglib::complex *vsrc,
-     ae_int_t N);
-
-void vsub(
-    double *vdst,
-      ae_int_t stride_dst,
-     const double *vsrc,
-      ae_int_t stride_src,
-     ae_int_t n,
-     double alpha);
-void vsub(
-    double *vdst,
-     const double *vsrc,
-     ae_int_t N,
-     double alpha);
-
-void vsub(
-    alglib::complex *vdst,
-     ae_int_t stride_dst,
-     const alglib::complex *vsrc,
-     ae_int_t stride_src,
-     const char *conj_src,
-     ae_int_t n,
-     double alpha);
-void vsub(
-    alglib::complex *vdst,
-     const alglib::complex *vsrc,
-     ae_int_t N,
-     double alpha);
-
-void vsub(
-    alglib::complex *vdst,
-     ae_int_t stride_dst,
-     const alglib::complex *vsrc,
-     ae_int_t stride_src,
-     const char *conj_src,
-     ae_int_t n,
-     alglib::complex alpha);
-void vsub(
-    alglib::complex *vdst,
-     const alglib::complex *vsrc,
-     ae_int_t N,
-     alglib::complex alpha);
-
-void vmul(
-    double *vdst,
-      ae_int_t stride_dst,
-     ae_int_t n,
-     double alpha);
-void vmul(
-    double *vdst,
-     ae_int_t N,
-     double alpha);
-
-void vmul(
-    alglib::complex *vdst,
-     ae_int_t stride_dst,
-     ae_int_t n,
-     double alpha);
-void vmul(
-    alglib::complex *vdst,
-     ae_int_t N,
-     double alpha);
-
-void vmul(
-    alglib::complex *vdst,
-     ae_int_t stride_dst,
-     ae_int_t n,
-     alglib::complex alpha);
-void vmul(
-    alglib::complex *vdst,
-     ae_int_t N,
-     alglib::complex alpha);
-
- -

5.10 Reading data from CSV files

- -

-ALGLIB (ap.h header) has alglib::read_csv() function -which allows to read data from CSV file. -Entire file is loaded into memory as double precision 2D array (alglib::real_2d_array object). -This function provides following features: -

- -
    -
  • support for ASCI encoding and UTF-8 without BOM (in header names)
  • -
  • ability to use any character (comma/tab/space) as field separator -(as long as it is distinct from one used for decimal point)
  • -
  • ability to use both comma and full stop as decimal point -(as long is decimal point is distinct from field separator). -
  • support for Unix and Windows text files (CR vs CRLF)
  • -
- -

-See comments on alglib::read_csv() function for more information about its functionality. -

- - - -

6 Working with commercial version

- -

6.1 Benefits of commercial version

- -

-Commercial version of ALGLIB for C++ features four important improvements over open source one: -

- -
    -
  • -License. -Commercial license used by ALGLIB is friendly to closed source applications. -Unlike GPL, it does not require you to open source your application. -Thus, almost any commercial software developer is interested in obtaining commercial license. -
  • -
  • -Low-level optimizations. -Commercial version of ALGLIB includes SIMD-optimized versions of many computationally intensive functions. -It allows to increase performance on Intel/AMD platforms while still being able to use software under non-x86 CPU's. -
  • -
  • -Multithreading. -Commercial version of ALGLIB can utilize multicore capabilities of modern CPU's. -Large computational problems can be automatically split between different cores. -ALGLIB uses its own multithreading framework which does not depend on vendor/compiler support for technologies like OpenMP/MPI/... -It gives ALGLIB unprecedented portability across operating systems and compilers. -
  • -
  • -Integrated Intel MKL. -Commercial version of ALGLIB includes special MKL extensions - -special lightweight distribution of Intel MKL, high-performance numerical analysis library, accompanied by ALGLIB-MKL interface. -We obtained license from Intel which allows us to integrate MKL into ALGLIB distribution. -Linking with MKL accelerates many ALGLIB functions, -however due to license restrictions you can not use MKL directly (i.e. bypass ALGLIB interface between your program and MKL). -
  • -
- -

6.2 Working with SIMD support (Intel/AMD users)

- -

-ALGLIB for C++ can utilize SIMD instructions supported by Intel and AMD processors. -This feature is optional and must be explicitly turned on during compile-time. -If you do not activate it, ALGLIB will use generic C code, without any processor-specific assembly/intrinsics. -

- -

-Thus, if you turn on this feature, your code will run faster on x86_32 and x86_64 processors, -but will be unportable to non-x86 platforms (and Intel MIC platform, which is not exactly x86!). -From the other side, if you do not activate this feature, your code will be portable to almost any modern CPU (SPARC, ARM, ...). -

- -

-In order to turn on x86-specific optimizations, -you should define AE_CPU=AE_INTEL preprocessor definition at global level. -It will tell ALGLIB to use SIMD intrinsics supported by GCC, MSVC and Intel compilers. -Additionally you should tell compiler to generate SIMD-capable code. -It can be done in the project settings of your IDE or in the command line: -

- -
-
-GCC example:
-> g++ -msse2 -I. -DAE_CPU=AE_INTEL *.cpp -lm
-
-MSVC example:
-> cl /I. /EHsc /DAE_CPU=AE_INTEL *.cpp
-
-
- -

6.3 Using multithreading

- -

6.3.1 General information

- -

-Commercial version of ALGLIB includes out-of-the-box support for multithreading. -Many (not all) computationally intensive problems can be solved in multithreaded mode. -You should read comments on specific ALGLIB functions to determine what can be multithreaded and what can not. -

- -

-ALGLIB does not depend on vendor/compiler support for technologies like OpenMP/MPI/... -Under Windows ALGLIB uses OS threads and custom synchronization framework. -Under POSIX-compatible OS (Solaris, Linux, FreeBSD, NetBSD, OpenBSD, ...) ALGLIB uses POSIX Threads -(standard *nix library which is shipped with any POSIX system) -with its threading and synchronization primitives. -It gives ALGLIB unprecedented portability across operating systems and compilers. -ALGLIB does not depend on presence of any custom multithreading library -or compiler support for any multithreading technology. -

- -

-If you want to use multithreaded capabilities of ALGLIB, you should: -

- -
    -
  1. compile it in OS-specific mode (ALGLIB have to know what OS it is running on)
  2. -
  3. activate multithreading at global level with alglib::setglobalthreading function call -or enable it at per-function basis by passing alglib::parallel to the specific computational function
  4. -
  5. optionally, tell ALGLIB about number of worker threads to use (default is to utilize all cores)
  6. -
- -

-Let explain it in more details... -

- -

-1. -You should compile ALGLIB in OS-specific mode by #defining either -AE_OS=AE_WINDOWS or AE_OS=AE_POSIX -(or AE_OS=AE_LINUX, which means "POSIX with Linux extensions") at compile time, -depending on OS being used. -Former corresponds to any modern OS (32/64-bit Windows XP and later) from Windows family, -while latter two mean almost any POSIX-compatible OS or any OS from the Linux family. -When compiling on POSIX/Linux, do not forget to link ALGLIB with libpthread library. -

- -

-2. -By default, ALGLIB is configured to perform all calculations in serial manner. -Parallel execution can be manually enabled at either global or per-function level. -Former means that all ALGLIB functions will be able to parallelize themselves at their discretion. -Similarly, you can enable global parallelism, but selectively disable it for specific function calls. -

- -

-Global parallelism is enabled by alglib::setglobalthreading(alglib::parallel) and -disabled by alglib::setglobalthreading(alglib::serial) call. -Function-level parallelism can be enabled (or disabled, if global default is to parallelize) -by adding alglib::parallel (or alglib::serial) to the end of the parameters list -of specific ALGLIB function being called. -

- -

-Enabling parallelism does not guarantee that ALGLIB will parallelize its computations. -Small problems (say, products of 64x64 matrices) can not be efficiently parallelized. -ALGLIB will automatically decide whether your problem is large enough or not for efficient parallelization. -

- -

-3. -ALGLIB automatically determines number of cores on application startup. -On Windows it is done using GetSystemInfo() call. -On POSIX systems ALGLIB performs sysconf(_SC_NPROCESSORS_ONLN) system call. -This system call is supported by all modern POSIX-compatible systems: Solaris, Linux, FreeBSD, NetBSD, OpenBSD. -

- -

-By default, ALGLIB uses all available cores (when told to parallelize calculations). -Such behavior may be changed with setnworkers() call: -

- -
    -
  • alglib::setnworkers(0) = use all cores
  • -
  • alglib::setnworkers(-1) = leave one core unused
  • -
  • alglib::setnworkers(-2) = leave two cores unused
  • -
  • alglib::setnworkers(+2) = use 2 cores (even if you have more)
  • -
- -

-You may want to specify maximum number of worker threads during compile time -by means of preprocessor definition AE_NWORKERS=N. -You can add this definition to compiler command line or change corresponding project settings in your IDE. -Here N can be any positive number. -ALGLIB will use exactly N worker threads, unless being told to use less by setnworkers() call. -

- -

-Some old POSIX-compatible operating systems do not support sysconf(_SC_NPROCESSORS_ONLN) system call -which is required in order to automatically determine number of active cores. -On these systems you should specify number of cores manually at compile time. -Without it ALGLIB will run in single-threaded mode. -

- -

6.3.2 SMT (CMT/hyper-threading) issues

- -

-Simultaneous multithreading (SMT) also known as Hyper-threading (Intel) -and Cluster-based Multithreading (AMD) -is a CPU design where several (usually two) logical cores share resources of one physical core. -Say, on dual-core system with 2x HT scale factor you will see 4 logical cores. -Each pair of these 4 cores, however, share same hardware resources. -Thus, you may get only marginal speedup when running highly optimized software which fully utilizes CPU resources. -

- -

-Say, if one thread occupies floating-point unit, -another thread on the same physical core may work with integer numbers at the same time without any performance penalties. -In this case you may get some speedup due to having additional cores. -But if both threads keep FPU unit 100% busy, they won't get any multithreaded speedup. -

- -

-So, if 2 math-intensive threads are dispatched by OS scheduler to different physical cores, -you will get 2x speedup due to use of multithreading. -But if these threads are dispatched to different logical cores - but same physical core - you won't get any speedup at all! -One physical core will be 100% busy, and another one will be 100% idle. -From the other side, if you start four threads instead of two, your system will be 100% utilized independently of thread scheduling details. -

- -

-Let we stress it one more time - multithreading speedup on SMT systems is highly dependent on number of threads you are running and decisions made by OS scheduler. -It is not 100% deterministic! -With "true SMP" when you run 2 threads, you get 2x speedup (or 1.95, or 1.80 - it depends on algorithm, but this factor is always same). -With SMT when you run 2 threads you may get your 2x speedup - or no speedup at all. -Modern OS schedulers do a good job on single-socket hardware, -but even in this "simple" case they give no guarantees of fair distribution of hardware resources. -And things become a bit tricky when you work with multi-socket hardware. -On SMT systems the only guaranteed way to 100% utilize your CPU is to create as many worker threads as there are logical cores. -In this case OS scheduler has no chance to make its work in a wrong way. -

- -

6.4 Linking with Intel MKL

- -

6.4.1 Using lightweight Intel MKL supplied by ALGLIB Project

- -

-Commercial edition of ALGLIB includes MKL extensions - -special lightweight distribution of Intel MKL, highly optimized numerical library from Intel -- and precompiled ALGLIB-MKL interface libraries. -Linking your programs with MKL extensions allows you to run ALGLIB with maximum performance. -MKL binaries are delivered for x86/x64 Windows and x64 Linux platforms. -

- -

-Unlike the rest of the library, MKL extensions are distributed in binary-only form. -ALGLIB itself is still distributed in source code form, -but Intel MKL and ALGLIB-MKL interface are distributed as precompiled dynamic/static libraries. -We can not distribute them in source because of license restrictions associated with Intel MKL. -Also due to license restrictions we can not give you direct access to MKL functionality. -You may use MKL to accelerate ALGLIB - without paying for MKL license - but you may not call its functions directly. -It is technically possible, but strictly prohibited by both MKL's EULA and ALGLIB License Agreement. -If you want to work with MKL, you should obtain separate license from Intel (as of 2018, free licenses are available). -

- -

-MKL extensions are located in the /cpp/addons-mkl subdirectory of the ALGLIB distribution. -This directory includes following files: -

- -
    -
  • alglib???_32mkl.lib - x86 Windows import library (MSVC) for Intel MKL extensions
  • -
  • alglib???_64mkl.lib - x64 Windows import library (MSVC) for Intel MKL extensions
  • -
  • alglib???_32mkl.dll - x86 Windows binary with Intel MKL inside
  • -
  • alglib???_64mkl.dll - x64 Windows binary with Intel MKL inside
  • -
  • libalglib???_64mkl.so - x64 Linux binary with Intel MKL inside
  • -
- -

-Here ??? stands for specific ALGLIB version: 313 for ALGLIB 3.13, and so on. -Files above are just MKL extensions - ALGLIB itself is not included in these binaries, -and you still have to compile primary ALGLIB distribution. -

- -

-In order to activate MKL extensions you should: -

- -
    -
  • -#define globally AE_MKL to activate ALGLIB-MKL connection. -
  • -
  • -additionally, #define globally AE_OS=AE_WINDOWS or AE_OS=AE_POSIX to activate multithreading capabilities -
  • -
  • -additionally, #define globally AE_CPU=AE_INTEL to use SIMD instructions provided by x86/x64 CPU's in the rest of ALGLIB -
  • -
  • -Depending on your OS, perform one of the following:
    -    - Windows: choose 32-bit or 64-bit import library alglib???_32/64mkl.lib and link it with your application
    -    - Linux: choose 64-bit SO file alglib???_64mkl.so and link it with your application -
  • -
  • -place DLL/SO binary into directory where it can be found during application startup -(Windows: application dir; Linux: one of the system directories) -
  • -
- -

-Several examples of ALGLIB+MKL usage are given in the 'compiling ALGLIB: examples' section. -

- -

6.4.2 Using your own installation of Intel MKL

- -

-If you bought separate license for Intel MKL, and want to use your own -installation of MKL - and not our lightweight distribution - then you -should compile ALGLIB as it was told in the previous section, with all necessary preprocessor definitions -(AE_OS=AE_WINDOWS or AE_OS=AE_POSIX, AE_CPU=AE_INTEL and AE_MKL defined). -But instead of linking with MKL Extensions binary, -you should add to your project alglib2mkl.c file from addons-mkl directory -and compile it (as C file) along with the rest of ALGLIB. -

- -

-This C file implements interface between MKL and ALGLIB. -Having this file in your project and defining AE_MKL preprocessor definition -results in ALGLIB using MKL functions. -

- -

-However, this C file is just interface! -It is your responsibility to make sure that C/C++ compiler can find MKL headers, -and appropriate MKL static/dynamic libraries are linked to your application. -

- -

7 Advanced topics

- -

7.1 Exception-free mode

- -

-ALGLIB for C++ can be compiled in exception-free mode, with exceptions -(throw/try/catch constructs) being disabled at compiler level. -Such feature is sometimes used by developers of embedded software. -

- -

-ALGLIB uses two-level model of errors: -"expected" errors (like degeneracy of linear system or inconsistency of linear constraints) -are reported with dedicated completion codes, -and "critical" errors (like malloc failures, unexpected NANs/INFs in the input data and so on) -are reported with exceptions. -The idea is that it is hard to put (and handle) completion codes in every ALGLIB function, -so we use exceptions to signal errors which should never happen under normal circumstances. -

- -

-Internally ALGLIB for C++ is implemented as C++ wrapper around computational core written in pure C. -Thus, internals of ALGLIB core use C-specific methods of error handling - -completion codes and setjmp/longjmp functions. -These error handling strategies are combined with sophisticated machinery of C memory management -which makes sure that not even a byte of dynamic memory is lost when we make longjmp to the error handler. -So, the only point where C++ exceptions are actually used is a boundary between C core and C++ interface. -

- -

-If you choose to use exceptions (default mode), ALGLIB will throw an exception with short textual description of the situation. -And if you choose to work without exceptions, ALGLIB will set global error flag and silently return from the current -function/constructor/... instead of throwing an exception. -Due to portability issues this error flag is made to be a non-TLS variable, i.e. it is shared between different threads. -So, you can use exception-free error handling only in single-threaded programs - although multithreaded programs won't break, -there is no way to determine which thread caused an "exception without exceptions". -

- -

-Exception-free method of reporting critical errors can be activated by #defining two preprocessor symbols at global level: -

- -
    -
  • AE_NO_EXCEPTIONS - to switch from exception-based to exception-free code
  • -
  • AE_THREADING=AE_SERIAL_UNSAFE - to confirm that you are aware of limitations associated -with exception-free mode (it does not support multithreading)
  • -
- -

-We must also note that exception-free mode is incompatible with OS-aware compiling: -you can not have AE_OS=??? defined together with AE_NO_EXCEPTIONS. -

- -

-After you #define all the necessary preprocessor symbols, two functions will appear in alglib namespace: -

- -
    -
  • -bool alglib::get_error_flag(const char **p_msg = NULL), -which returns current error status (true is returned on error), -with optional char** parameter used to get human-readable error message. -
  • -
  • -void alglib::clear_error_flag(), which clears error flag -(ALGLIB functions set flag on failure, but do not clear it on successful calls) -
  • -
- -

-You must check error flag after EVERY operation with ALGLIB objects and functions. -In addition to calling computational ALGLIB functions, following kinds of operations may result in "exception": -

- -
    -
  • -calling default constructor for ALGLIB object -(simply instantiating object may result in "exception"). -Due to large size ALGLIB objects are allocated dynamically -(they look like value types, but internally everything is stored in the heap memory). -Thus every constructor, even default one, makes at least one malloc() call which may fail. -
  • -
  • -calling copy/assignment constructors for ALGLIB objects (same reason - malloc) -
  • -
  • -resizing arrays with setlength()/setcontents() -and attaching to external memory with attach_to_ptr() -
  • -
- -

7.2 Partial compilation

- -

-Due to ALGLIB modular structure it is possible to selectively enable/disable some of its subpackages along with their dependencies. -Deactivation of ALGLIB source code is performed at preprocessor level - compiler does not even see disabled code. -Partial compilation can be used for two purposes: -

- -
    -
  • -to reduce code size in cases when linker is unable to remove unused code -(happens with some compilers when ALGLIB is compiled as part of the shared library) -
  • -
  • -to reduce build time (disabled code is silently removed by preprocessor, -thus no time is spent in the compiler) -
  • -
- -

-You can activate partial compilation by #defining at global level following symbols: -

- -
    -
  • -AE_PARTIAL_BUILD - to disable everything not enabled by default -
  • -
  • -AE_COMPILE_SUBPACKAGE - to selectively enable subpackage SUBPACKAGE, -with its name given in upper case (case sensitive). -You may combine several definitions like this in order to enable several subpackages. -Subpackage names can be found in the list of ALGLIB packages and subpackages. -
  • -
- -

7.3 Testing ALGLIB

- -

-There are three test suites in ALGLIB: computational tests, interface tests, extended tests. -Computational tests are located in /tests/test_c.cpp. -They are focused on numerical properties of algorithms, stress testing and "deep" tests (large automatically generated problems). -They require significant amount of time to finish (tens of minutes). -

- -

-Interface tests are located in /tests/test_i.cpp. -These tests are focused on ability to correctly pass data between computational core and caller, ability to detect simple problems in inputs, -and on ability to at least compile ALGLIB with your compiler. -They are very fast (about a minute to finish including compilation time). -

- -

-Extended tests are located in /tests/test_x.cpp. -These tests are focused on testing some special properties -(say, testing that cloning object indeed results in 100% independent copy being created) -and performance of several chosen algorithms. -

- -

-Running test suite is easy - just -

- -
    -
  1. compile one of these files (test_c.cpp, test_i.cpp or test_x.cpp) -along with the rest of the library
  2. -
  3. launch executable you will get. It may take from several seconds (interface tests) to several minutes (computational tests) to get final results
  4. -
- -

-If you want to be sure that ALGLIB will work with some sophisticated optimization settings, set corresponding flags during compile time. -If your compiler/system are not in the list of supported ones, we recommend you to run both test suites. But if you are running out of time, run at least test_i.cpp. -

- - - -
-

8 ALGLIB packages and subpackages

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

8.1 AlglibMisc package

-
hqrnd High quality random numbers generator
nearestneighbor Nearest neighbor search: approximate and exact
xdebug Debug functions to test ALGLIB interface generator
 
-

8.2 DataAnalysis package

-
bdss Basic dataset functions
clustering Clustering functions (hierarchical, k-means, k-means++)
datacomp Backward compatibility functions
dforest Decision forest classifier (regression model)
filters Different filters used in data analysis
knn K Nearest Neighbors classification/regression
lda Linear discriminant analysis
linreg Linear models
logit Logit models
mcpd Markov Chains for Population/proportional Data
mlpbase Basic functions for neural networks
mlpe Basic functions for neural ensemble models
mlptrain Neural network training
pca Principal component analysis
ssa Singular Spectrum Analysis
 
-

8.3 DiffEquations package

-
odesolver Ordinary differential equation solver
 
-

8.4 FastTransforms package

-
conv Fast real/complex convolution
corr Fast real/complex cross-correlation
fft Real/complex FFT
fht Real Fast Hartley Transform
 
-

8.5 Integration package

-
autogk Adaptive 1-dimensional integration
gkq Gauss-Kronrod quadrature generator
gq Gaussian quadrature generator
 
-

8.6 Interpolation package

-
fitsphere Fitting circle/sphere to data (least squares, minimum circumscribed, maximum inscribed, minimum zone)
idw Inverse distance weighting: interpolation/fitting with improved Shepard-like algorithm
intcomp Backward compatibility functions
lsfit Fitting with least squates target function (linear and nonlinear least-squares)
parametric Parametric curves
polint Polynomial interpolation/fitting
ratint Rational interpolation/fitting
rbf Scattered N-dimensional interpolation with RBF models
spline1d 1D spline interpolation/fitting
spline2d 2D spline interpolation
spline3d 3D spline interpolation
 
-

8.7 LinAlg package

-
ablas Level 2 and Level 3 BLAS operations
bdsvd Bidiagonal SVD
evd Direct and iterative eigensolvers
inverseupdate Sherman-Morrison update of the inverse matrix
matdet Determinant calculation
matgen Random matrix generation
matinv Matrix inverse
normestimator Estimates norm of the sparse matrix (from below)
ortfac Real/complex QR/LQ, bi(tri)diagonal, Hessenberg decompositions
rcond Condition number estimate
schur Schur decomposition
sparse Sparse matrices
spdgevd Generalized symmetric eigensolver
svd Singular value decomposition
trfac LU and Cholesky decompositions (dense and sparse)
 
-

8.8 Optimization package

-
minbc Box constrained optimizer with fast activation of multiple constraints per step
minbleic Bound constrained optimizer with additional linear equality/inequality constraints
mincg Conjugate gradient optimizer
mincomp Backward compatibility functions
minlbfgs Limited memory BFGS optimizer
minlm Improved Levenberg-Marquardt optimizer
minlp Linear programming suite
minnlc Nonlinearly constrained optimizer
minns Nonsmooth constrained optimizer
minqp Quadratic programming with bound and linear equality/inequality constraints
optguardapi OptGuard integrity checking for nonlinear models
 
-

8.9 Solvers package

-
directdensesolvers Direct dense linear solvers
directsparsesolvers Direct sparse linear solvers
lincg Sparse linear CG solver
linlsqr Sparse linear LSQR solver
nleq Solvers for nonlinear equations
polynomialsolver Polynomial solver
 
-

8.10 SpecialFunctions package

-
airyf Airy functions
bessel Bessel functions
betaf Beta function
binomialdistr Binomial distribution
chebyshev Chebyshev polynomials
chisquaredistr Chi-Square distribution
dawson Dawson integral
elliptic Elliptic integrals
expintegrals Exponential integrals
fdistr F-distribution
fresnel Fresnel integrals
gammafunc Gamma function
hermite Hermite polynomials
ibetaf Incomplete beta function
igammaf Incomplete gamma function
jacobianelliptic Jacobian elliptic functions
laguerre Laguerre polynomials
legendre Legendre polynomials
normaldistr Univarite and bivariate normal distribution PDF and CDF
poissondistr Poisson distribution
psif Psi function
studenttdistr Student's t-distribution
trigintegrals Trigonometric integrals
 
-

8.11 Statistics package

-
basestat Mean, variance, covariance, correlation, etc.
correlationtests Hypothesis testing: correlation tests
jarquebera Hypothesis testing: Jarque-Bera test
mannwhitneyu Hypothesis testing: Mann-Whitney-U test
stest Hypothesis testing: sign test
studentttests Hypothesis testing: Student's t-test
variancetests Hypothesis testing: F-test and one-sample variance test
wsr Hypothesis testing: Wilcoxon signed rank test
 
- - - -
-
/************************************************************************* -Copy - -Input parameters: - M - number of rows - N - number of columns - A - source matrix, MxN submatrix is copied and transposed - IA - submatrix offset (row index) - JA - submatrix offset (column index) - B - destination matrix, must be large enough to store result - IB - submatrix offset (row index) - JB - submatrix offset (column index) -*************************************************************************/ -
void alglib::cmatrixcopy( - ae_int_t m, - ae_int_t n, - complex_2d_array a, - ae_int_t ia, - ae_int_t ja, - complex_2d_array& b, - ae_int_t ib, - ae_int_t jb, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine calculates C = alpha*op1(A)*op2(B) +beta*C where: -* C is MxN general matrix -* op1(A) is MxK matrix -* op2(B) is KxN matrix -* "op" may be identity transformation, transposition, conjugate transposition - -Additional info: -* cache-oblivious algorithm is used. -* multiplication result replaces C. If Beta=0, C elements are not used in - calculations (not multiplied by zero - just not referenced) -* if Alpha=0, A is not used (not multiplied by zero - just not referenced) -* if both Beta and Alpha are zero, C is filled by zeros. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -IMPORTANT: - -This function does NOT preallocate output matrix C, it MUST be preallocated -by caller prior to calling this function. In case C does not have enough -space to store result, exception will be generated. - -INPUT PARAMETERS - M - matrix size, M>0 - N - matrix size, N>0 - K - matrix size, K>0 - Alpha - coefficient - A - matrix - IA - submatrix offset - JA - submatrix offset - OpTypeA - transformation type: - * 0 - no transformation - * 1 - transposition - * 2 - conjugate transposition - B - matrix - IB - submatrix offset - JB - submatrix offset - OpTypeB - transformation type: - * 0 - no transformation - * 1 - transposition - * 2 - conjugate transposition - Beta - coefficient - C - matrix (PREALLOCATED, large enough to store result) - IC - submatrix offset - JC - submatrix offset - - -- ALGLIB routine -- - 2009-2019 - Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixgemm( - ae_int_t m, - ae_int_t n, - ae_int_t k, - alglib::complex alpha, - complex_2d_array a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - complex_2d_array b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - alglib::complex beta, - complex_2d_array& c, - ae_int_t ic, - ae_int_t jc, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This subroutine calculates C=alpha*A*A^H+beta*C or C=alpha*A^H*A+beta*C -where: -* C is NxN Hermitian matrix given by its upper/lower triangle -* A is NxK matrix when A*A^H is calculated, KxN matrix otherwise - -Additional info: -* multiplication result replaces C. If Beta=0, C elements are not used in - calculations (not multiplied by zero - just not referenced) -* if Alpha=0, A is not used (not multiplied by zero - just not referenced) -* if both Beta and Alpha are zero, C is filled by zeros. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - K - matrix size, K>=0 - Alpha - coefficient - A - matrix - IA - submatrix offset (row index) - JA - submatrix offset (column index) - OpTypeA - multiplication type: - * 0 - A*A^H is calculated - * 2 - A^H*A is calculated - Beta - coefficient - C - preallocated input/output matrix - IC - submatrix offset (row index) - JC - submatrix offset (column index) - IsUpper - whether upper or lower triangle of C is updated; - this function updates only one half of C, leaving - other half unchanged (not referenced at all). - - -- ALGLIB routine -- - 16.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixherk( - ae_int_t n, - ae_int_t k, - double alpha, - complex_2d_array a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - complex_2d_array& c, - ae_int_t ic, - ae_int_t jc, - bool isupper, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This subroutine calculates op(A^-1)*X where: -* X is MxN general matrix -* A is MxM upper/lower triangular/unitriangular matrix -* "op" may be identity transformation, transposition, conjugate transposition -Multiplication result replaces X. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - M - matrix size, N>=0 - A - matrix, actial matrix is stored in A[I1:I1+M-1,J1:J1+M-1] - I1 - submatrix offset - J1 - submatrix offset - IsUpper - whether matrix is upper triangular - IsUnit - whether matrix is unitriangular - OpType - transformation type: - * 0 - no transformation - * 1 - transposition - * 2 - conjugate transposition - X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1] - I2 - submatrix offset - J2 - submatrix offset - - -- ALGLIB routine -- - 15.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixlefttrsm( - ae_int_t m, - ae_int_t n, - complex_2d_array a, - ae_int_t i1, - ae_int_t j1, - bool isupper, - bool isunit, - ae_int_t optype, - complex_2d_array& x, - ae_int_t i2, - ae_int_t j2, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Matrix-vector product: y := op(A)*x - -INPUT PARAMETERS: - M - number of rows of op(A) - M>=0 - N - number of columns of op(A) - N>=0 - A - target matrix - IA - submatrix offset (row index) - JA - submatrix offset (column index) - OpA - operation type: - * OpA=0 => op(A) = A - * OpA=1 => op(A) = A^T - * OpA=2 => op(A) = A^H - X - input vector - IX - subvector offset - IY - subvector offset - Y - preallocated matrix, must be large enough to store result - -OUTPUT PARAMETERS: - Y - vector which stores result - -if M=0, then subroutine does nothing. -if N=0, Y is filled by zeros. - - - -- ALGLIB routine -- - - 28.01.2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixmv( - ae_int_t m, - ae_int_t n, - complex_2d_array a, - ae_int_t ia, - ae_int_t ja, - ae_int_t opa, - complex_1d_array x, - ae_int_t ix, - complex_1d_array& y, - ae_int_t iy, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Rank-1 correction: A := A + u*v' - -INPUT PARAMETERS: - M - number of rows - N - number of columns - A - target matrix, MxN submatrix is updated - IA - submatrix offset (row index) - JA - submatrix offset (column index) - U - vector #1 - IU - subvector offset - V - vector #2 - IV - subvector offset -*************************************************************************/ -
void alglib::cmatrixrank1( - ae_int_t m, - ae_int_t n, - complex_2d_array& a, - ae_int_t ia, - ae_int_t ja, - complex_1d_array& u, - ae_int_t iu, - complex_1d_array& v, - ae_int_t iv, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine calculates X*op(A^-1) where: -* X is MxN general matrix -* A is NxN upper/lower triangular/unitriangular matrix -* "op" may be identity transformation, transposition, conjugate transposition -Multiplication result replaces X. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - M - matrix size, N>=0 - A - matrix, actial matrix is stored in A[I1:I1+N-1,J1:J1+N-1] - I1 - submatrix offset - J1 - submatrix offset - IsUpper - whether matrix is upper triangular - IsUnit - whether matrix is unitriangular - OpType - transformation type: - * 0 - no transformation - * 1 - transposition - * 2 - conjugate transposition - X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1] - I2 - submatrix offset - J2 - submatrix offset - - -- ALGLIB routine -- - 20.01.2018 - Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixrighttrsm( - ae_int_t m, - ae_int_t n, - complex_2d_array a, - ae_int_t i1, - ae_int_t j1, - bool isupper, - bool isunit, - ae_int_t optype, - complex_2d_array& x, - ae_int_t i2, - ae_int_t j2, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine is an older version of CMatrixHERK(), one with wrong name -(it is HErmitian update, not SYmmetric). It is left here for backward -compatibility. - - -- ALGLIB routine -- - 16.12.2009 - Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixsyrk( - ae_int_t n, - ae_int_t k, - double alpha, - complex_2d_array a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - complex_2d_array& c, - ae_int_t ic, - ae_int_t jc, - bool isupper, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Cache-oblivous complex "copy-and-transpose" - -Input parameters: - M - number of rows - N - number of columns - A - source matrix, MxN submatrix is copied and transposed - IA - submatrix offset (row index) - JA - submatrix offset (column index) - B - destination matrix, must be large enough to store result - IB - submatrix offset (row index) - JB - submatrix offset (column index) -*************************************************************************/ -
void alglib::cmatrixtranspose( - ae_int_t m, - ae_int_t n, - complex_2d_array a, - ae_int_t ia, - ae_int_t ja, - complex_2d_array& b, - ae_int_t ib, - ae_int_t jb, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Copy - -Input parameters: - M - number of rows - N - number of columns - A - source matrix, MxN submatrix is copied and transposed - IA - submatrix offset (row index) - JA - submatrix offset (column index) - B - destination matrix, must be large enough to store result - IB - submatrix offset (row index) - JB - submatrix offset (column index) -*************************************************************************/ -
void alglib::rmatrixcopy( - ae_int_t m, - ae_int_t n, - real_2d_array a, - ae_int_t ia, - ae_int_t ja, - real_2d_array& b, - ae_int_t ib, - ae_int_t jb, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This code enforces symmetricy of the matrix by copying Upper part to lower -one (or vice versa). - -INPUT PARAMETERS: - A - matrix - N - number of rows/columns - IsUpper - whether we want to copy upper triangle to lower one (True) - or vice versa (False). -*************************************************************************/ -
void alglib::rmatrixenforcesymmetricity( - real_2d_array& a, - ae_int_t n, - bool isupper, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine calculates C = alpha*op1(A)*op2(B) +beta*C where: -* C is MxN general matrix -* op1(A) is MxK matrix -* op2(B) is KxN matrix -* "op" may be identity transformation, transposition - -Additional info: -* cache-oblivious algorithm is used. -* multiplication result replaces C. If Beta=0, C elements are not used in - calculations (not multiplied by zero - just not referenced) -* if Alpha=0, A is not used (not multiplied by zero - just not referenced) -* if both Beta and Alpha are zero, C is filled by zeros. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -IMPORTANT: - -This function does NOT preallocate output matrix C, it MUST be preallocated -by caller prior to calling this function. In case C does not have enough -space to store result, exception will be generated. - -INPUT PARAMETERS - M - matrix size, M>0 - N - matrix size, N>0 - K - matrix size, K>0 - Alpha - coefficient - A - matrix - IA - submatrix offset - JA - submatrix offset - OpTypeA - transformation type: - * 0 - no transformation - * 1 - transposition - B - matrix - IB - submatrix offset - JB - submatrix offset - OpTypeB - transformation type: - * 0 - no transformation - * 1 - transposition - Beta - coefficient - C - PREALLOCATED output matrix, large enough to store result - IC - submatrix offset - JC - submatrix offset - - -- ALGLIB routine -- - 2009-2019 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixgemm( - ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - real_2d_array a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - real_2d_array b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - double beta, - real_2d_array& c, - ae_int_t ic, - ae_int_t jc, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* - -*************************************************************************/ -
void alglib::rmatrixgemv( - ae_int_t m, - ae_int_t n, - double alpha, - real_2d_array a, - ae_int_t ia, - ae_int_t ja, - ae_int_t opa, - real_1d_array x, - ae_int_t ix, - double beta, - real_1d_array& y, - ae_int_t iy, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Performs generalized copy: B := Beta*B + Alpha*A. - -If Beta=0, then previous contents of B is simply ignored. If Alpha=0, then -A is ignored and not referenced. If both Alpha and Beta are zero, B is -filled by zeros. - -Input parameters: - M - number of rows - N - number of columns - Alpha- coefficient - A - source matrix, MxN submatrix is copied and transposed - IA - submatrix offset (row index) - JA - submatrix offset (column index) - Beta- coefficient - B - destination matrix, must be large enough to store result - IB - submatrix offset (row index) - JB - submatrix offset (column index) -*************************************************************************/ -
void alglib::rmatrixgencopy( - ae_int_t m, - ae_int_t n, - double alpha, - real_2d_array a, - ae_int_t ia, - ae_int_t ja, - double beta, - real_2d_array& b, - ae_int_t ib, - ae_int_t jb, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Rank-1 correction: A := A + alpha*u*v' - -NOTE: this function expects A to be large enough to store result. No - automatic preallocation happens for smaller arrays. No integrity - checks is performed for sizes of A, u, v. - -INPUT PARAMETERS: - M - number of rows - N - number of columns - A - target matrix, MxN submatrix is updated - IA - submatrix offset (row index) - JA - submatrix offset (column index) - Alpha- coefficient - U - vector #1 - IU - subvector offset - V - vector #2 - IV - subvector offset - - - -- ALGLIB routine -- - - 16.10.2017 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixger( - ae_int_t m, - ae_int_t n, - real_2d_array& a, - ae_int_t ia, - ae_int_t ja, - double alpha, - real_1d_array u, - ae_int_t iu, - real_1d_array v, - ae_int_t iv, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine calculates op(A^-1)*X where: -* X is MxN general matrix -* A is MxM upper/lower triangular/unitriangular matrix -* "op" may be identity transformation, transposition -Multiplication result replaces X. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - M - matrix size, N>=0 - A - matrix, actial matrix is stored in A[I1:I1+M-1,J1:J1+M-1] - I1 - submatrix offset - J1 - submatrix offset - IsUpper - whether matrix is upper triangular - IsUnit - whether matrix is unitriangular - OpType - transformation type: - * 0 - no transformation - * 1 - transposition - X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1] - I2 - submatrix offset - J2 - submatrix offset - - -- ALGLIB routine -- - 15.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixlefttrsm( - ae_int_t m, - ae_int_t n, - real_2d_array a, - ae_int_t i1, - ae_int_t j1, - bool isupper, - bool isunit, - ae_int_t optype, - real_2d_array& x, - ae_int_t i2, - ae_int_t j2, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -IMPORTANT: this function is deprecated since ALGLIB 3.13. Use RMatrixGEMV() - which is more generic version of this function. - -Matrix-vector product: y := op(A)*x - -INPUT PARAMETERS: - M - number of rows of op(A) - N - number of columns of op(A) - A - target matrix - IA - submatrix offset (row index) - JA - submatrix offset (column index) - OpA - operation type: - * OpA=0 => op(A) = A - * OpA=1 => op(A) = A^T - X - input vector - IX - subvector offset - IY - subvector offset - Y - preallocated matrix, must be large enough to store result - -OUTPUT PARAMETERS: - Y - vector which stores result - -if M=0, then subroutine does nothing. -if N=0, Y is filled by zeros. - - - -- ALGLIB routine -- - - 28.01.2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixmv( - ae_int_t m, - ae_int_t n, - real_2d_array a, - ae_int_t ia, - ae_int_t ja, - ae_int_t opa, - real_1d_array x, - ae_int_t ix, - real_1d_array& y, - ae_int_t iy, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -IMPORTANT: this function is deprecated since ALGLIB 3.13. Use RMatrixGER() - which is more generic version of this function. - -Rank-1 correction: A := A + u*v' - -INPUT PARAMETERS: - M - number of rows - N - number of columns - A - target matrix, MxN submatrix is updated - IA - submatrix offset (row index) - JA - submatrix offset (column index) - U - vector #1 - IU - subvector offset - V - vector #2 - IV - subvector offset -*************************************************************************/ -
void alglib::rmatrixrank1( - ae_int_t m, - ae_int_t n, - real_2d_array& a, - ae_int_t ia, - ae_int_t ja, - real_1d_array& u, - ae_int_t iu, - real_1d_array& v, - ae_int_t iv, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine calculates X*op(A^-1) where: -* X is MxN general matrix -* A is NxN upper/lower triangular/unitriangular matrix -* "op" may be identity transformation, transposition -Multiplication result replaces X. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - M - matrix size, N>=0 - A - matrix, actial matrix is stored in A[I1:I1+N-1,J1:J1+N-1] - I1 - submatrix offset - J1 - submatrix offset - IsUpper - whether matrix is upper triangular - IsUnit - whether matrix is unitriangular - OpType - transformation type: - * 0 - no transformation - * 1 - transposition - X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1] - I2 - submatrix offset - J2 - submatrix offset - - -- ALGLIB routine -- - 15.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixrighttrsm( - ae_int_t m, - ae_int_t n, - real_2d_array a, - ae_int_t i1, - ae_int_t j1, - bool isupper, - bool isunit, - ae_int_t optype, - real_2d_array& x, - ae_int_t i2, - ae_int_t j2, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* - -*************************************************************************/ -
void alglib::rmatrixsymv( - ae_int_t n, - double alpha, - real_2d_array a, - ae_int_t ia, - ae_int_t ja, - bool isupper, - real_1d_array x, - ae_int_t ix, - double beta, - real_1d_array& y, - ae_int_t iy, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine calculates C=alpha*A*A^T+beta*C or C=alpha*A^T*A+beta*C -where: -* C is NxN symmetric matrix given by its upper/lower triangle -* A is NxK matrix when A*A^T is calculated, KxN matrix otherwise - -Additional info: -* multiplication result replaces C. If Beta=0, C elements are not used in - calculations (not multiplied by zero - just not referenced) -* if Alpha=0, A is not used (not multiplied by zero - just not referenced) -* if both Beta and Alpha are zero, C is filled by zeros. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - K - matrix size, K>=0 - Alpha - coefficient - A - matrix - IA - submatrix offset (row index) - JA - submatrix offset (column index) - OpTypeA - multiplication type: - * 0 - A*A^T is calculated - * 2 - A^T*A is calculated - Beta - coefficient - C - preallocated input/output matrix - IC - submatrix offset (row index) - JC - submatrix offset (column index) - IsUpper - whether C is upper triangular or lower triangular - - -- ALGLIB routine -- - 16.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixsyrk( - ae_int_t n, - ae_int_t k, - double alpha, - real_2d_array a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - real_2d_array& c, - ae_int_t ic, - ae_int_t jc, - bool isupper, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* - -*************************************************************************/ -
double alglib::rmatrixsyvmv( - ae_int_t n, - real_2d_array a, - ae_int_t ia, - ae_int_t ja, - bool isupper, - real_1d_array x, - ae_int_t ix, - real_1d_array& tmp, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Cache-oblivous real "copy-and-transpose" - -Input parameters: - M - number of rows - N - number of columns - A - source matrix, MxN submatrix is copied and transposed - IA - submatrix offset (row index) - JA - submatrix offset (column index) - B - destination matrix, must be large enough to store result - IB - submatrix offset (row index) - JB - submatrix offset (column index) -*************************************************************************/ -
void alglib::rmatrixtranspose( - ae_int_t m, - ae_int_t n, - real_2d_array a, - ae_int_t ia, - ae_int_t ja, - real_2d_array& b, - ae_int_t ib, - ae_int_t jb, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine solves linear system op(A)*x=b where: -* A is NxN upper/lower triangular/unitriangular matrix -* X and B are Nx1 vectors -* "op" may be identity transformation, transposition, conjugate transposition - -Solution replaces X. - -IMPORTANT: * no overflow/underflow/denegeracy tests is performed. - * no integrity checks for operand sizes, out-of-bounds accesses - and so on is performed - -INPUT PARAMETERS - N - matrix size, N>=0 - A - matrix, actial matrix is stored in A[IA:IA+N-1,JA:JA+N-1] - IA - submatrix offset - JA - submatrix offset - IsUpper - whether matrix is upper triangular - IsUnit - whether matrix is unitriangular - OpType - transformation type: - * 0 - no transformation - * 1 - transposition - X - right part, actual vector is stored in X[IX:IX+N-1] - IX - offset - -OUTPUT PARAMETERS - X - solution replaces elements X[IX:IX+N-1] - - -- ALGLIB routine / remastering of LAPACK's DTRSV -- - (c) 2017 Bochkanov Sergey - converted to ALGLIB - (c) 2016 Reference BLAS level1 routine (LAPACK version 3.7.0) - Reference BLAS is a software package provided by Univ. of Tennessee, - Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd. -*************************************************************************/ -
void alglib::rmatrixtrsv( - ae_int_t n, - real_2d_array a, - ae_int_t ia, - ae_int_t ja, - bool isupper, - bool isunit, - ae_int_t optype, - real_1d_array& x, - ae_int_t ix, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Copy - -Input parameters: - N - subvector size - A - source vector, N elements are copied - IA - source offset (first element index) - B - destination vector, must be large enough to store result - IB - destination offset (first element index) -*************************************************************************/ -
void alglib::rvectorcopy( - ae_int_t n, - real_1d_array a, - ae_int_t ia, - real_1d_array& b, - ae_int_t ib, - const xparams _params = alglib::xdefault); - -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "linalg.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    real_2d_array a = "[[2,1],[1,3]]";
-    real_2d_array b = "[[2,1],[0,1]]";
-    real_2d_array c = "[[0,0],[0,0]]";
-
-    //
-    // rmatrixgemm() function allows us to calculate matrix product C:=A*B or
-    // to perform more general operation, C:=alpha*op1(A)*op2(B)+beta*C,
-    // where A, B, C are rectangular matrices, op(X) can be X or X^T,
-    // alpha and beta are scalars.
-    //
-    // This function:
-    // * can apply transposition and/or multiplication by scalar to operands
-    // * can use arbitrary part of matrices A/B (given by submatrix offset)
-    // * can store result into arbitrary part of C
-    // * for performance reasons requires C to be preallocated
-    //
-    // Parameters of this function are:
-    // * M, N, K            -   sizes of op1(A) (which is MxK), op2(B) (which
-    //                          is KxN) and C (which is MxN)
-    // * Alpha              -   coefficient before A*B
-    // * A, IA, JA          -   matrix A and offset of the submatrix
-    // * OpTypeA            -   transformation type:
-    //                          0 - no transformation
-    //                          1 - transposition
-    // * B, IB, JB          -   matrix B and offset of the submatrix
-    // * OpTypeB            -   transformation type:
-    //                          0 - no transformation
-    //                          1 - transposition
-    // * Beta               -   coefficient before C
-    // * C, IC, JC          -   preallocated matrix C and offset of the submatrix
-    //
-    // Below we perform simple product C:=A*B (alpha=1, beta=0)
-    //
-    // IMPORTANT: this function works with preallocated C, which must be large
-    //            enough to store multiplication result.
-    //
-    ae_int_t m = 2;
-    ae_int_t n = 2;
-    ae_int_t k = 2;
-    double alpha = 1.0;
-    ae_int_t ia = 0;
-    ae_int_t ja = 0;
-    ae_int_t optypea = 0;
-    ae_int_t ib = 0;
-    ae_int_t jb = 0;
-    ae_int_t optypeb = 0;
-    double beta = 0.0;
-    ae_int_t ic = 0;
-    ae_int_t jc = 0;
-    rmatrixgemm(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc);
-    printf("%s\n", c.tostring(3).c_str()); // EXPECTED: [[4,3],[2,4]]
-
-    //
-    // Now we try to apply some simple transformation to operands: C:=A*B^T
-    //
-    optypeb = 1;
-    rmatrixgemm(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc);
-    printf("%s\n", c.tostring(3).c_str()); // EXPECTED: [[5,1],[5,3]]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "linalg.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // rmatrixsyrk() function allows us to calculate symmetric rank-K update
-    // C := beta*C + alpha*A'*A, where C is square N*N matrix, A is square K*N
-    // matrix, alpha and beta are scalars. It is also possible to update by
-    // adding A*A' instead of A'*A.
-    //
-    // Parameters of this function are:
-    // * N, K       -   matrix size
-    // * Alpha      -   coefficient before A
-    // * A, IA, JA  -   matrix and submatrix offsets
-    // * OpTypeA    -   multiplication type:
-    //                  * 0 - A*A^T is calculated
-    //                  * 2 - A^T*A is calculated
-    // * Beta       -   coefficient before C
-    // * C, IC, JC  -   preallocated input/output matrix and submatrix offsets
-    // * IsUpper    -   whether upper or lower triangle of C is updated;
-    //                  this function updates only one half of C, leaving
-    //                  other half unchanged (not referenced at all).
-    //
-    // Below we will show how to calculate simple product C:=A'*A
-    //
-    // NOTE: beta=0 and we do not use previous value of C, but still it
-    //       MUST be preallocated.
-    //
-    ae_int_t n = 2;
-    ae_int_t k = 1;
-    double alpha = 1.0;
-    ae_int_t ia = 0;
-    ae_int_t ja = 0;
-    ae_int_t optypea = 2;
-    double beta = 0.0;
-    ae_int_t ic = 0;
-    ae_int_t jc = 0;
-    bool isupper = true;
-    real_2d_array a = "[[1,2]]";
-
-    // preallocate space to store result
-    real_2d_array c = "[[0,0],[0,0]]";
-
-    // calculate product, store result into upper part of c
-    rmatrixsyrk(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper);
-
-    // output result.
-    // IMPORTANT: lower triangle of C was NOT updated!
-    printf("%s\n", c.tostring(3).c_str()); // EXPECTED: [[1,2],[0,4]]
-    return 0;
-}
-
-
-
-
- -airy
- - -
- -
-
/************************************************************************* -Airy function - -Solution of the differential equation - -y"(x) = xy. - -The function returns the two independent solutions Ai, Bi -and their first derivatives Ai'(x), Bi'(x). - -Evaluation is by power series summation for small x, -by rational minimax approximations for large x. - - - -ACCURACY: -Error criterion is absolute when function <= 1, relative -when function > 1, except * denotes relative error criterion. -For large negative x, the absolute error increases as x^1.5. -For large positive x, the relative error increases as x^1.5. - -Arithmetic domain function # trials peak rms -IEEE -10, 0 Ai 10000 1.6e-15 2.7e-16 -IEEE 0, 10 Ai 10000 2.3e-14* 1.8e-15* -IEEE -10, 0 Ai' 10000 4.6e-15 7.6e-16 -IEEE 0, 10 Ai' 10000 1.8e-14* 1.5e-15* -IEEE -10, 10 Bi 30000 4.2e-15 5.3e-16 -IEEE -10, 10 Bi' 30000 4.9e-15 7.3e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -
void alglib::airy( - double x, - double& ai, - double& aip, - double& bi, - double& bip, - const xparams _params = alglib::xdefault); - -
- -
- -autogkreport
-autogkstate
- -autogkintegrate
-autogkresults
-autogksingular
-autogksmooth
-autogksmoothw
- - - -
autogk_d1 Integrating f=exp(x) by adaptive integrator
- -
-
/************************************************************************* -Integration report: -* TerminationType = completetion code: - * -5 non-convergence of Gauss-Kronrod nodes - calculation subroutine. - * -1 incorrect parameters were specified - * 1 OK -* Rep.NFEV countains number of function calculations -* Rep.NIntervals contains number of intervals [a,b] - was partitioned into. -*************************************************************************/ -
class autogkreport -{ - ae_int_t terminationtype; - ae_int_t nfev; - ae_int_t nintervals; -}; - -
- -
-
/************************************************************************* -This structure stores state of the integration algorithm. - -Although this class has public fields, they are not intended for external -use. You should use ALGLIB functions to work with this class: -* autogksmooth()/AutoGKSmoothW()/... to create objects -* autogkintegrate() to begin integration -* autogkresults() to get results -*************************************************************************/ -
class autogkstate -{ -}; - -
- -
-
/************************************************************************* -This function is used to launcn iterations of ODE solver - -It accepts following parameters: - diff - callback which calculates dy/dx for given y and x - obj - optional object which is passed to diff; can be NULL - - - -- ALGLIB -- - Copyright 07.05.2009 by Bochkanov Sergey -*************************************************************************/ -
void autogkintegrate(autogkstate &state, - void (*func)(double x, double xminusa, double bminusx, double &y, void *ptr), - void *ptr = NULL, const xparams _xparams = alglib::xdefault); -
-

Examples:   [1]  

- -
-
/************************************************************************* -Adaptive integration results - -Called after AutoGKIteration returned False. - -Input parameters: - State - algorithm state (used by AutoGKIteration). - -Output parameters: - V - integral(f(x)dx,a,b) - Rep - optimization report (see AutoGKReport description) - - -- ALGLIB -- - Copyright 14.11.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::autogkresults( - autogkstate state, - double& v, - autogkreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Integration on a finite interval [A,B]. -Integrand have integrable singularities at A/B. - -F(X) must diverge as "(x-A)^alpha" at A, as "(B-x)^beta" at B, with known -alpha/beta (alpha>-1, beta>-1). If alpha/beta are not known, estimates -from below can be used (but these estimates should be greater than -1 too). - -One of alpha/beta variables (or even both alpha/beta) may be equal to 0, -which means than function F(x) is non-singular at A/B. Anyway (singular at -bounds or not), function F(x) is supposed to be continuous on (A,B). - -Fast-convergent algorithm based on a Gauss-Kronrod formula is used. Result -is calculated with accuracy close to the machine precision. - -INPUT PARAMETERS: - A, B - interval boundaries (A<B, A=B or A>B) - Alpha - power-law coefficient of the F(x) at A, - Alpha>-1 - Beta - power-law coefficient of the F(x) at B, - Beta>-1 - -OUTPUT PARAMETERS - State - structure which stores algorithm state - -SEE ALSO - AutoGKSmooth, AutoGKSmoothW, AutoGKResults. - - - -- ALGLIB -- - Copyright 06.05.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::autogksingular( - double a, - double b, - double alpha, - double beta, - autogkstate& state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Integration of a smooth function F(x) on a finite interval [a,b]. - -Fast-convergent algorithm based on a Gauss-Kronrod formula is used. Result -is calculated with accuracy close to the machine precision. - -Algorithm works well only with smooth integrands. It may be used with -continuous non-smooth integrands, but with less performance. - -It should never be used with integrands which have integrable singularities -at lower or upper limits - algorithm may crash. Use AutoGKSingular in such -cases. - -INPUT PARAMETERS: - A, B - interval boundaries (A<B, A=B or A>B) - -OUTPUT PARAMETERS - State - structure which stores algorithm state - -SEE ALSO - AutoGKSmoothW, AutoGKSingular, AutoGKResults. - - - -- ALGLIB -- - Copyright 06.05.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::autogksmooth( - double a, - double b, - autogkstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Integration of a smooth function F(x) on a finite interval [a,b]. - -This subroutine is same as AutoGKSmooth(), but it guarantees that interval -[a,b] is partitioned into subintervals which have width at most XWidth. - -Subroutine can be used when integrating nearly-constant function with -narrow "bumps" (about XWidth wide). If "bumps" are too narrow, AutoGKSmooth -subroutine can overlook them. - -INPUT PARAMETERS: - A, B - interval boundaries (A<B, A=B or A>B) - -OUTPUT PARAMETERS - State - structure which stores algorithm state - -SEE ALSO - AutoGKSmooth, AutoGKSingular, AutoGKResults. - - - -- ALGLIB -- - Copyright 06.05.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::autogksmoothw( - double a, - double b, - double xwidth, - autogkstate& state, - const xparams _params = alglib::xdefault); - -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "integration.h"
-
-using namespace alglib;
-void int_function_1_func(double x, double xminusa, double bminusx, double &y, void *ptr) 
-{
-    // this callback calculates f(x)=exp(x)
-    y = exp(x);
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates integration of f=exp(x) on [0,1]:
-    // * first, autogkstate is initialized
-    // * then we call integration function
-    // * and finally we obtain results with autogkresults() call
-    //
-    double a = 0;
-    double b = 1;
-    autogkstate s;
-    double v;
-    autogkreport rep;
-
-    autogksmooth(a, b, s);
-    alglib::autogkintegrate(s, int_function_1_func);
-    autogkresults(s, v, rep);
-
-    printf("%.2f\n", double(v)); // EXPECTED: 1.7182
-    return 0;
-}
-
-
-
-
- -cov2
-covm
-covm2
-pearsoncorr2
-pearsoncorrelation
-pearsoncorrm
-pearsoncorrm2
-rankdata
-rankdatacentered
-sampleadev
-samplekurtosis
-samplemean
-samplemedian
-samplemoments
-samplepercentile
-sampleskewness
-samplevariance
-spearmancorr2
-spearmancorrm
-spearmancorrm2
-spearmanrankcorrelation
- - - - - - -
basestat_d_base Basic functionality (moments, adev, median, percentile)
basestat_d_c2 Correlation (covariance) between two random variables
basestat_d_cm Correlation (covariance) between components of random vector
basestat_d_cm2 Correlation (covariance) between two random vectors
- -
-
/************************************************************************* -2-sample covariance - -Input parameters: - X - sample 1 (array indexes: [0..N-1]) - Y - sample 2 (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only N leading elements of X/Y are processed - * if not given, automatically determined from input sizes - -Result: - covariance (zero for N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -
double alglib::cov2( - real_1d_array x, - real_1d_array y, - const xparams _params = alglib::xdefault); -double alglib::cov2( - real_1d_array x, - real_1d_array y, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Covariance matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X are used - * if not given, automatically determined from input size - M - M>0, number of variables: - * if given, only leading M columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M,M], covariance matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::covm( - real_2d_array x, - real_2d_array& c, - const xparams _params = alglib::xdefault); -void alglib::covm( - real_2d_array x, - ae_int_t n, - ae_int_t m, - real_2d_array& c, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Cross-covariance matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M1], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - Y - array[N,M2], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X/Y are used - * if not given, automatically determined from input sizes - M1 - M1>0, number of variables in X: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - M2 - M2>0, number of variables in Y: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M1,M2], cross-covariance matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::covm2( - real_2d_array x, - real_2d_array y, - real_2d_array& c, - const xparams _params = alglib::xdefault); -void alglib::covm2( - real_2d_array x, - real_2d_array y, - ae_int_t n, - ae_int_t m1, - ae_int_t m2, - real_2d_array& c, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Pearson product-moment correlation coefficient - -Input parameters: - X - sample 1 (array indexes: [0..N-1]) - Y - sample 2 (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only N leading elements of X/Y are processed - * if not given, automatically determined from input sizes - -Result: - Pearson product-moment correlation coefficient - (zero for N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -
double alglib::pearsoncorr2( - real_1d_array x, - real_1d_array y, - const xparams _params = alglib::xdefault); -double alglib::pearsoncorr2( - real_1d_array x, - real_1d_array y, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Obsolete function, we recommend to use PearsonCorr2(). - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -
double alglib::pearsoncorrelation( - real_1d_array x, - real_1d_array y, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Pearson product-moment correlation matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X are used - * if not given, automatically determined from input size - M - M>0, number of variables: - * if given, only leading M columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M,M], correlation matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::pearsoncorrm( - real_2d_array x, - real_2d_array& c, - const xparams _params = alglib::xdefault); -void alglib::pearsoncorrm( - real_2d_array x, - ae_int_t n, - ae_int_t m, - real_2d_array& c, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Pearson product-moment cross-correlation matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M1], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - Y - array[N,M2], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X/Y are used - * if not given, automatically determined from input sizes - M1 - M1>0, number of variables in X: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - M2 - M2>0, number of variables in Y: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M1,M2], cross-correlation matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::pearsoncorrm2( - real_2d_array x, - real_2d_array y, - real_2d_array& c, - const xparams _params = alglib::xdefault); -void alglib::pearsoncorrm2( - real_2d_array x, - real_2d_array y, - ae_int_t n, - ae_int_t m1, - ae_int_t m2, - real_2d_array& c, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function replaces data in XY by their ranks: -* XY is processed row-by-row -* rows are processed separately -* tied data are correctly handled (tied ranks are calculated) -* ranking starts from 0, ends at NFeatures-1 -* sum of within-row values is equal to (NFeatures-1)*NFeatures/2 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - array[NPoints,NFeatures], dataset - NPoints - number of points - NFeatures- number of features - -OUTPUT PARAMETERS: - XY - data are replaced by their within-row ranks; - ranking starts from 0, ends at NFeatures-1 - - -- ALGLIB -- - Copyright 18.04.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rankdata( - real_2d_array& xy, - const xparams _params = alglib::xdefault); -void alglib::rankdata( - real_2d_array& xy, - ae_int_t npoints, - ae_int_t nfeatures, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function replaces data in XY by their CENTERED ranks: -* XY is processed row-by-row -* rows are processed separately -* tied data are correctly handled (tied ranks are calculated) -* centered ranks are just usual ranks, but centered in such way that sum - of within-row values is equal to 0.0. -* centering is performed by subtracting mean from each row, i.e it changes - mean value, but does NOT change higher moments - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - array[NPoints,NFeatures], dataset - NPoints - number of points - NFeatures- number of features - -OUTPUT PARAMETERS: - XY - data are replaced by their within-row ranks; - ranking starts from 0, ends at NFeatures-1 - - -- ALGLIB -- - Copyright 18.04.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rankdatacentered( - real_2d_array& xy, - const xparams _params = alglib::xdefault); -void alglib::rankdatacentered( - real_2d_array& xy, - ae_int_t npoints, - ae_int_t nfeatures, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -ADev - -Input parameters: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -Output parameters: - ADev- ADev - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sampleadev( - real_1d_array x, - double& adev, - const xparams _params = alglib::xdefault); -void alglib::sampleadev( - real_1d_array x, - ae_int_t n, - double& adev, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Calculation of the kurtosis. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -NOTE: - -This function return result which calculated by 'SampleMoments' function -and stored at 'Kurtosis' variable. - - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -
double alglib::samplekurtosis( - real_1d_array x, - const xparams _params = alglib::xdefault); -double alglib::samplekurtosis( - real_1d_array x, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Calculation of the mean. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -NOTE: - -This function return result which calculated by 'SampleMoments' function -and stored at 'Mean' variable. - - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -
double alglib::samplemean( - real_1d_array x, - const xparams _params = alglib::xdefault); -double alglib::samplemean( - real_1d_array x, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Median calculation. - -Input parameters: - X - sample (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -Output parameters: - Median - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -
void alglib::samplemedian( - real_1d_array x, - double& median, - const xparams _params = alglib::xdefault); -void alglib::samplemedian( - real_1d_array x, - ae_int_t n, - double& median, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Calculation of the distribution moments: mean, variance, skewness, kurtosis. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -OUTPUT PARAMETERS - Mean - mean. - Variance- variance. - Skewness- skewness (if variance<>0; zero otherwise). - Kurtosis- kurtosis (if variance<>0; zero otherwise). - -NOTE: variance is calculated by dividing sum of squares by N-1, not N. - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -
void alglib::samplemoments( - real_1d_array x, - double& mean, - double& variance, - double& skewness, - double& kurtosis, - const xparams _params = alglib::xdefault); -void alglib::samplemoments( - real_1d_array x, - ae_int_t n, - double& mean, - double& variance, - double& skewness, - double& kurtosis, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Percentile calculation. - -Input parameters: - X - sample (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - P - percentile (0<=P<=1) - -Output parameters: - V - percentile - - -- ALGLIB -- - Copyright 01.03.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::samplepercentile( - real_1d_array x, - double p, - double& v, - const xparams _params = alglib::xdefault); -void alglib::samplepercentile( - real_1d_array x, - ae_int_t n, - double p, - double& v, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Calculation of the skewness. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -NOTE: - -This function return result which calculated by 'SampleMoments' function -and stored at 'Skewness' variable. - - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -
double alglib::sampleskewness( - real_1d_array x, - const xparams _params = alglib::xdefault); -double alglib::sampleskewness( - real_1d_array x, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Calculation of the variance. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -NOTE: - -This function return result which calculated by 'SampleMoments' function -and stored at 'Variance' variable. - - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -
double alglib::samplevariance( - real_1d_array x, - const xparams _params = alglib::xdefault); -double alglib::samplevariance( - real_1d_array x, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Spearman's rank correlation coefficient - -Input parameters: - X - sample 1 (array indexes: [0..N-1]) - Y - sample 2 (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only N leading elements of X/Y are processed - * if not given, automatically determined from input sizes - -Result: - Spearman's rank correlation coefficient - (zero for N=0 or N=1) - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -
double alglib::spearmancorr2( - real_1d_array x, - real_1d_array y, - const xparams _params = alglib::xdefault); -double alglib::spearmancorr2( - real_1d_array x, - real_1d_array y, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Spearman's rank correlation matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X are used - * if not given, automatically determined from input size - M - M>0, number of variables: - * if given, only leading M columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M,M], correlation matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spearmancorrm( - real_2d_array x, - real_2d_array& c, - const xparams _params = alglib::xdefault); -void alglib::spearmancorrm( - real_2d_array x, - ae_int_t n, - ae_int_t m, - real_2d_array& c, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Spearman's rank cross-correlation matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M1], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - Y - array[N,M2], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X/Y are used - * if not given, automatically determined from input sizes - M1 - M1>0, number of variables in X: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - M2 - M2>0, number of variables in Y: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M1,M2], cross-correlation matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spearmancorrm2( - real_2d_array x, - real_2d_array y, - real_2d_array& c, - const xparams _params = alglib::xdefault); -void alglib::spearmancorrm2( - real_2d_array x, - real_2d_array y, - ae_int_t n, - ae_int_t m1, - ae_int_t m2, - real_2d_array& c, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Obsolete function, we recommend to use SpearmanCorr2(). - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -
double alglib::spearmanrankcorrelation( - real_1d_array x, - real_1d_array y, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "statistics.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    real_1d_array x = "[0,1,4,9,16,25,36,49,64,81]";
-    double mean;
-    double variance;
-    double skewness;
-    double kurtosis;
-    double adev;
-    double p;
-    double v;
-
-    //
-    // Here we demonstrate calculation of sample moments
-    // (mean, variance, skewness, kurtosis)
-    //
-    samplemoments(x, mean, variance, skewness, kurtosis);
-    printf("%.1f\n", double(mean)); // EXPECTED: 28.5
-    printf("%.1f\n", double(variance)); // EXPECTED: 801.1667
-    printf("%.1f\n", double(skewness)); // EXPECTED: 0.5751
-    printf("%.1f\n", double(kurtosis)); // EXPECTED: -1.2666
-
-    //
-    // Average deviation
-    //
-    sampleadev(x, adev);
-    printf("%.1f\n", double(adev)); // EXPECTED: 23.2
-
-    //
-    // Median and percentile
-    //
-    samplemedian(x, v);
-    printf("%.1f\n", double(v)); // EXPECTED: 20.5
-    p = 0.5;
-    samplepercentile(x, p, v);
-    printf("%.1f\n", double(v)); // EXPECTED: 20.5
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "statistics.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // We have two samples - x and y, and want to measure dependency between them
-    //
-    real_1d_array x = "[0,1,4,9,16,25,36,49,64,81]";
-    real_1d_array y = "[0,1,2,3,4,5,6,7,8,9]";
-    double v;
-
-    //
-    // Three dependency measures are calculated:
-    // * covariation
-    // * Pearson correlation
-    // * Spearman rank correlation
-    //
-    v = cov2(x, y);
-    printf("%.2f\n", double(v)); // EXPECTED: 82.5
-    v = pearsoncorr2(x, y);
-    printf("%.2f\n", double(v)); // EXPECTED: 0.9627
-    v = spearmancorr2(x, y);
-    printf("%.2f\n", double(v)); // EXPECTED: 1.000
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "statistics.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // X is a sample matrix:
-    // * I-th row corresponds to I-th observation
-    // * J-th column corresponds to J-th variable
-    //
-    real_2d_array x = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]";
-    real_2d_array c;
-
-    //
-    // Three dependency measures are calculated:
-    // * covariation
-    // * Pearson correlation
-    // * Spearman rank correlation
-    //
-    // Result is stored into C, with C[i,j] equal to correlation
-    // (covariance) between I-th and J-th variables of X.
-    //
-    covm(x, c);
-    printf("%s\n", c.tostring(1).c_str()); // EXPECTED: [[1.80,0.60,-1.40],[0.60,0.70,-0.80],[-1.40,-0.80,14.70]]
-    pearsoncorrm(x, c);
-    printf("%s\n", c.tostring(1).c_str()); // EXPECTED: [[1.000,0.535,-0.272],[0.535,1.000,-0.249],[-0.272,-0.249,1.000]]
-    spearmancorrm(x, c);
-    printf("%s\n", c.tostring(1).c_str()); // EXPECTED: [[1.000,0.556,-0.306],[0.556,1.000,-0.750],[-0.306,-0.750,1.000]]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "statistics.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // X and Y are sample matrices:
-    // * I-th row corresponds to I-th observation
-    // * J-th column corresponds to J-th variable
-    //
-    real_2d_array x = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]";
-    real_2d_array y = "[[2,3],[2,1],[-1,6],[-9,9],[7,1]]";
-    real_2d_array c;
-
-    //
-    // Three dependency measures are calculated:
-    // * covariation
-    // * Pearson correlation
-    // * Spearman rank correlation
-    //
-    // Result is stored into C, with C[i,j] equal to correlation
-    // (covariance) between I-th variable of X and J-th variable of Y.
-    //
-    covm2(x, y, c);
-    printf("%s\n", c.tostring(1).c_str()); // EXPECTED: [[4.100,-3.250],[2.450,-1.500],[13.450,-5.750]]
-    pearsoncorrm2(x, y, c);
-    printf("%s\n", c.tostring(1).c_str()); // EXPECTED: [[0.519,-0.699],[0.497,-0.518],[0.596,-0.433]]
-    spearmancorrm2(x, y, c);
-    printf("%s\n", c.tostring(1).c_str()); // EXPECTED: [[0.541,-0.649],[0.216,-0.433],[0.433,-0.135]]
-    return 0;
-}
-
-
-
-
- -dsoptimalsplit2
-dsoptimalsplit2fast
- - -
- -
-
/************************************************************************* -Optimal binary classification - -Algorithms finds optimal (=with minimal cross-entropy) binary partition. -Internal subroutine. - -INPUT PARAMETERS: - A - array[0..N-1], variable - C - array[0..N-1], class numbers (0 or 1). - N - array size - -OUTPUT PARAMETERS: - Info - completetion code: - * -3, all values of A[] are same (partition is impossible) - * -2, one of C[] is incorrect (<0, >1) - * -1, incorrect pararemets were passed (N<=0). - * 1, OK - Threshold- partiton boundary. Left part contains values which are - strictly less than Threshold. Right part contains values - which are greater than or equal to Threshold. - PAL, PBL- probabilities P(0|v<Threshold) and P(1|v<Threshold) - PAR, PBR- probabilities P(0|v>=Threshold) and P(1|v>=Threshold) - CVE - cross-validation estimate of cross-entropy - - -- ALGLIB -- - Copyright 22.05.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dsoptimalsplit2( - real_1d_array a, - integer_1d_array c, - ae_int_t n, - ae_int_t& info, - double& threshold, - double& pal, - double& pbl, - double& par, - double& pbr, - double& cve, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Optimal partition, internal subroutine. Fast version. - -Accepts: - A array[0..N-1] array of attributes array[0..N-1] - C array[0..N-1] array of class labels - TiesBuf array[0..N] temporaries (ties) - CntBuf array[0..2*NC-1] temporaries (counts) - Alpha centering factor (0<=alpha<=1, recommended value - 0.05) - BufR array[0..N-1] temporaries - BufI array[0..N-1] temporaries - -Output: - Info error code (">0"=OK, "<0"=bad) - RMS training set RMS error - CVRMS leave-one-out RMS error - -Note: - content of all arrays is changed by subroutine; - it doesn't allocate temporaries. - - -- ALGLIB -- - Copyright 11.12.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dsoptimalsplit2fast( - real_1d_array& a, - integer_1d_array& c, - integer_1d_array& tiesbuf, - integer_1d_array& cntbuf, - real_1d_array& bufr, - integer_1d_array& bufi, - ae_int_t n, - ae_int_t nc, - double alpha, - ae_int_t& info, - double& threshold, - double& rms, - double& cvrms, - const xparams _params = alglib::xdefault); - -
- -
- -rmatrixbdsvd
- - -
- -
-
/************************************************************************* -Singular value decomposition of a bidiagonal matrix (extended algorithm) - -COMMERCIAL EDITION OF ALGLIB: - - ! Commercial version of ALGLIB includes one important improvement of - ! this function, which can be used from C++ and C#: - ! * Intel MKL support (lightweight Intel MKL is shipped with ALGLIB) - ! - ! Intel MKL gives approximately constant (with respect to number of - ! worker threads) acceleration factor which depends on CPU being used, - ! problem size and "baseline" ALGLIB edition which is used for - ! comparison. - ! - ! Generally, commercial ALGLIB is several times faster than open-source - ! generic C edition, and many times faster than open-source C# edition. - ! - ! Multithreaded acceleration is NOT supported for this function. - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -The algorithm performs the singular value decomposition of a bidiagonal -matrix B (upper or lower) representing it as B = Q*S*P^T, where Q and P - -orthogonal matrices, S - diagonal matrix with non-negative elements on the -main diagonal, in descending order. - -The algorithm finds singular values. In addition, the algorithm can -calculate matrices Q and P (more precisely, not the matrices, but their -product with given matrices U and VT - U*Q and (P^T)*VT)). Of course, -matrices U and VT can be of any type, including identity. Furthermore, the -algorithm can calculate Q'*C (this product is calculated more effectively -than U*Q, because this calculation operates with rows instead of matrix -columns). - -The feature of the algorithm is its ability to find all singular values -including those which are arbitrarily close to 0 with relative accuracy -close to machine precision. If the parameter IsFractionalAccuracyRequired -is set to True, all singular values will have high relative accuracy close -to machine precision. If the parameter is set to False, only the biggest -singular value will have relative accuracy close to machine precision. -The absolute error of other singular values is equal to the absolute error -of the biggest singular value. - -Input parameters: - D - main diagonal of matrix B. - Array whose index ranges within [0..N-1]. - E - superdiagonal (or subdiagonal) of matrix B. - Array whose index ranges within [0..N-2]. - N - size of matrix B. - IsUpper - True, if the matrix is upper bidiagonal. - IsFractionalAccuracyRequired - - THIS PARAMETER IS IGNORED SINCE ALGLIB 3.5.0 - SINGULAR VALUES ARE ALWAYS SEARCHED WITH HIGH ACCURACY. - U - matrix to be multiplied by Q. - Array whose indexes range within [0..NRU-1, 0..N-1]. - The matrix can be bigger, in that case only the submatrix - [0..NRU-1, 0..N-1] will be multiplied by Q. - NRU - number of rows in matrix U. - C - matrix to be multiplied by Q'. - Array whose indexes range within [0..N-1, 0..NCC-1]. - The matrix can be bigger, in that case only the submatrix - [0..N-1, 0..NCC-1] will be multiplied by Q'. - NCC - number of columns in matrix C. - VT - matrix to be multiplied by P^T. - Array whose indexes range within [0..N-1, 0..NCVT-1]. - The matrix can be bigger, in that case only the submatrix - [0..N-1, 0..NCVT-1] will be multiplied by P^T. - NCVT - number of columns in matrix VT. - -Output parameters: - D - singular values of matrix B in descending order. - U - if NRU>0, contains matrix U*Q. - VT - if NCVT>0, contains matrix (P^T)*VT. - C - if NCC>0, contains matrix Q'*C. - -Result: - True, if the algorithm has converged. - False, if the algorithm hasn't converged (rare case). - -NOTE: multiplication U*Q is performed by means of transposition to internal - buffer, multiplication and backward transposition. It helps to avoid - costly columnwise operations and speed-up algorithm. - -Additional information: - The type of convergence is controlled by the internal parameter TOL. - If the parameter is greater than 0, the singular values will have - relative accuracy TOL. If TOL<0, the singular values will have - absolute accuracy ABS(TOL)*norm(B). - By default, |TOL| falls within the range of 10*Epsilon and 100*Epsilon, - where Epsilon is the machine precision. It is not recommended to use - TOL less than 10*Epsilon since this will considerably slow down the - algorithm and may not lead to error decreasing. - -History: - * 31 March, 2007. - changed MAXITR from 6 to 12. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - October 31, 1999. -*************************************************************************/ -
bool alglib::rmatrixbdsvd( - real_1d_array& d, - real_1d_array e, - ae_int_t n, - bool isupper, - bool isfractionalaccuracyrequired, - real_2d_array& u, - ae_int_t nru, - real_2d_array& c, - ae_int_t ncc, - real_2d_array& vt, - ae_int_t ncvt, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -Modified Bessel function of order zero - -Returns modified Bessel function of order zero of the -argument. - -The function is defined as i0(x) = j0( ix ). - -The range is partitioned into the two intervals [0,8] and -(8, infinity). Chebyshev polynomial expansions are employed -in each interval. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,30 30000 5.8e-16 1.4e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::besseli0( - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Modified Bessel function of order one - -Returns modified Bessel function of order one of the -argument. - -The function is defined as i1(x) = -i j1( ix ). - -The range is partitioned into the two intervals [0,8] and -(8, infinity). Chebyshev polynomial expansions are employed -in each interval. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 1.9e-15 2.1e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1985, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::besseli1( - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Bessel function of order zero - -Returns Bessel function of order zero of the argument. - -The domain is divided into the intervals [0, 5] and -(5, infinity). In the first interval the following rational -approximation is used: - - - 2 2 -(w - r ) (w - r ) P (w) / Q (w) - 1 2 3 8 - - 2 -where w = x and the two r's are zeros of the function. - -In the second interval, the Hankel asymptotic expansion -is employed with two rational functions of degree 6/6 -and 7/7. - -ACCURACY: - - Absolute error: -arithmetic domain # trials peak rms - IEEE 0, 30 60000 4.2e-16 1.1e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::besselj0( - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Bessel function of order one - -Returns Bessel function of order one of the argument. - -The domain is divided into the intervals [0, 8] and -(8, infinity). In the first interval a 24 term Chebyshev -expansion is used. In the second, the asymptotic -trigonometric representation is employed using two -rational functions of degree 5/5. - -ACCURACY: - - Absolute error: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 2.6e-16 1.1e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::besselj1( - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Bessel function of integer order - -Returns Bessel function of order n, where n is a -(possibly negative) integer. - -The ratio of jn(x) to j0(x) is computed by backward -recurrence. First the ratio jn/jn-1 is found by a -continued fraction expansion. Then the recurrence -relating successive orders is applied until j0 or j1 is -reached. - -If n = 0 or 1 the routine for j0 or j1 is called -directly. - -ACCURACY: - - Absolute error: -arithmetic range # trials peak rms - IEEE 0, 30 5000 4.4e-16 7.9e-17 - - -Not suitable for large n or x. Use jv() (fractional order) instead. - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::besseljn( - ae_int_t n, - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Modified Bessel function, second kind, order zero - -Returns modified Bessel function of the second kind -of order zero of the argument. - -The range is partitioned into the two intervals [0,8] and -(8, infinity). Chebyshev polynomial expansions are employed -in each interval. - -ACCURACY: - -Tested at 2000 random points between 0 and 8. Peak absolute -error (relative when K0 > 1) was 1.46e-14; rms, 4.26e-15. - Relative error: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 1.2e-15 1.6e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::besselk0( - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Modified Bessel function, second kind, order one - -Computes the modified Bessel function of the second kind -of order one of the argument. - -The range is partitioned into the two intervals [0,2] and -(2, infinity). Chebyshev polynomial expansions are employed -in each interval. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 1.2e-15 1.6e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::besselk1( - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Modified Bessel function, second kind, integer order - -Returns modified Bessel function of the second kind -of order n of the argument. - -The range is partitioned into the two intervals [0,9.55] and -(9.55, infinity). An ascending power series is used in the -low range, and an asymptotic expansion in the high range. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,30 90000 1.8e-8 3.0e-10 - -Error is high only near the crossover point x = 9.55 -between the two expansions used. - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::besselkn( - ae_int_t nn, - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Bessel function of the second kind, order zero - -Returns Bessel function of the second kind, of order -zero, of the argument. - -The domain is divided into the intervals [0, 5] and -(5, infinity). In the first interval a rational approximation -R(x) is employed to compute - y0(x) = R(x) + 2 * log(x) * j0(x) / PI. -Thus a call to j0() is required. - -In the second interval, the Hankel asymptotic expansion -is employed with two rational functions of degree 6/6 -and 7/7. - - - -ACCURACY: - - Absolute error, when y0(x) < 1; else relative error: - -arithmetic domain # trials peak rms - IEEE 0, 30 30000 1.3e-15 1.6e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::bessely0( - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Bessel function of second kind of order one - -Returns Bessel function of the second kind of order one -of the argument. - -The domain is divided into the intervals [0, 8] and -(8, infinity). In the first interval a 25 term Chebyshev -expansion is used, and a call to j1() is required. -In the second, the asymptotic trigonometric representation -is employed using two rational functions of degree 5/5. - -ACCURACY: - - Absolute error: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 1.0e-15 1.3e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::bessely1( - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Bessel function of second kind of integer order - -Returns Bessel function of order n, where n is a -(possibly negative) integer. - -The function is evaluated by forward recurrence on -n, starting with values computed by the routines -y0() and y1(). - -If n = 0 or 1 the routine for y0 or y1 is called -directly. - -ACCURACY: - Absolute error, except relative - when y > 1: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 3.4e-15 4.3e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::besselyn( - ae_int_t n, - double x, - const xparams _params = alglib::xdefault); - -
- -
- -beta
- - -
- -
-
/************************************************************************* -Beta function - - - - - - | (a) | (b) -beta( a, b ) = -----------. - - - | (a+b) - -For large arguments the logarithm of the function is -evaluated using lgam(), then exponentiated. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,30 30000 8.1e-14 1.1e-14 - -Cephes Math Library Release 2.0: April, 1987 -Copyright 1984, 1987 by Stephen L. Moshier -*************************************************************************/ -
double alglib::beta( - double a, - double b, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -Complemented binomial distribution - -Returns the sum of the terms k+1 through n of the Binomial -probability density: - - n - -- ( n ) j n-j - > ( ) p (1-p) - -- ( j ) - j=k+1 - -The terms are not summed directly; instead the incomplete -beta integral is employed, according to the formula - -y = bdtrc( k, n, p ) = incbet( k+1, n-k, p ). - -The arguments must be positive, with p ranging from 0 to 1. - -ACCURACY: - -Tested at random points (a,b,p). - - a,b Relative error: -arithmetic domain # trials peak rms - For p between 0.001 and 1: - IEEE 0,100 100000 6.7e-15 8.2e-16 - For p between 0 and .001: - IEEE 0,100 100000 1.5e-13 2.7e-15 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::binomialcdistribution( - ae_int_t k, - ae_int_t n, - double p, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Binomial distribution - -Returns the sum of the terms 0 through k of the Binomial -probability density: - - k - -- ( n ) j n-j - > ( ) p (1-p) - -- ( j ) - j=0 - -The terms are not summed directly; instead the incomplete -beta integral is employed, according to the formula - -y = bdtr( k, n, p ) = incbet( n-k, k+1, 1-p ). - -The arguments must be positive, with p ranging from 0 to 1. - -ACCURACY: - -Tested at random points (a,b,p), with p between 0 and 1. - - a,b Relative error: -arithmetic domain # trials peak rms - For p between 0.001 and 1: - IEEE 0,100 100000 4.3e-15 2.6e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::binomialdistribution( - ae_int_t k, - ae_int_t n, - double p, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Inverse binomial distribution - -Finds the event probability p such that the sum of the -terms 0 through k of the Binomial probability density -is equal to the given cumulative probability y. - -This is accomplished using the inverse beta integral -function and the relation - -1 - p = incbi( n-k, k+1, y ). - -ACCURACY: - -Tested at random points (a,b,p). - - a,b Relative error: -arithmetic domain # trials peak rms - For p between 0.001 and 1: - IEEE 0,100 100000 2.3e-14 6.4e-16 - IEEE 0,10000 100000 6.6e-12 1.2e-13 - For p between 10^-6 and 0.001: - IEEE 0,100 100000 2.0e-12 1.3e-14 - IEEE 0,10000 100000 1.5e-12 3.2e-14 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::invbinomialdistribution( - ae_int_t k, - ae_int_t n, - double y, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -Calculation of the value of the Chebyshev polynomials of the -first and second kinds. - -Parameters: - r - polynomial kind, either 1 or 2. - n - degree, n>=0 - x - argument, -1 <= x <= 1 - -Result: - the value of the Chebyshev polynomial at x -*************************************************************************/ -
double alglib::chebyshevcalculate( - ae_int_t r, - ae_int_t n, - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Representation of Tn as C[0] + C[1]*X + ... + C[N]*X^N - -Input parameters: - N - polynomial degree, n>=0 - -Output parameters: - C - coefficients -*************************************************************************/ -
void alglib::chebyshevcoefficients( - ae_int_t n, - real_1d_array& c, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Summation of Chebyshev polynomials using Clenshaw's recurrence formula. - -This routine calculates - c[0]*T0(x) + c[1]*T1(x) + ... + c[N]*TN(x) -or - c[0]*U0(x) + c[1]*U1(x) + ... + c[N]*UN(x) -depending on the R. - -Parameters: - r - polynomial kind, either 1 or 2. - n - degree, n>=0 - x - argument - -Result: - the value of the Chebyshev polynomial at x -*************************************************************************/ -
double alglib::chebyshevsum( - real_1d_array c, - ae_int_t r, - ae_int_t n, - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Conversion of a series of Chebyshev polynomials to a power series. - -Represents A[0]*T0(x) + A[1]*T1(x) + ... + A[N]*Tn(x) as -B[0] + B[1]*X + ... + B[N]*X^N. - -Input parameters: - A - Chebyshev series coefficients - N - degree, N>=0 - -Output parameters - B - power series coefficients -*************************************************************************/ -
void alglib::fromchebyshev( - real_1d_array a, - ae_int_t n, - real_1d_array& b, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -Complemented Chi-square distribution - -Returns the area under the right hand tail (from x to -infinity) of the Chi square probability density function -with v degrees of freedom: - - inf. - - - 1 | | v/2-1 -t/2 - P( x | v ) = ----------- | t e dt - v/2 - | | - 2 | (v/2) - - x - -where x is the Chi-square variable. - -The incomplete gamma integral is used, according to the -formula - -y = chdtr( v, x ) = igamc( v/2.0, x/2.0 ). - -The arguments must both be positive. - -ACCURACY: - -See incomplete gamma function - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::chisquarecdistribution( - double v, - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Chi-square distribution - -Returns the area under the left hand tail (from 0 to x) -of the Chi square probability density function with -v degrees of freedom. - - - x - - - 1 | | v/2-1 -t/2 - P( x | v ) = ----------- | t e dt - v/2 - | | - 2 | (v/2) - - 0 - -where x is the Chi-square variable. - -The incomplete gamma integral is used, according to the -formula - -y = chdtr( v, x ) = igam( v/2.0, x/2.0 ). - -The arguments must both be positive. - -ACCURACY: - -See incomplete gamma function - - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::chisquaredistribution( - double v, - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Inverse of complemented Chi-square distribution - -Finds the Chi-square argument x such that the integral -from x to infinity of the Chi-square density is equal -to the given cumulative probability y. - -This is accomplished using the inverse gamma integral -function and the relation - - x/2 = igami( df/2, y ); - -ACCURACY: - -See inverse incomplete gamma function - - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::invchisquaredistribution( - double v, - double y, - const xparams _params = alglib::xdefault); - -
- -
- -ahcreport
-clusterizerstate
-kmeansreport
- -clusterizercreate
-clusterizergetdistances
-clusterizergetkclusters
-clusterizerrunahc
-clusterizerrunkmeans
-clusterizerseparatedbycorr
-clusterizerseparatedbydist
-clusterizersetahcalgo
-clusterizersetdistances
-clusterizersetkmeansinit
-clusterizersetkmeanslimits
-clusterizersetpoints
-clusterizersetseed
- - - - - - - -
clst_ahc Simple hierarchical clusterization with Euclidean distance function
clst_distance Clusterization with different metric types
clst_kclusters Obtaining K top clusters from clusterization tree
clst_kmeans Simple k-means clusterization
clst_linkage Clusterization with different linkage types
- -
-
/************************************************************************* -This structure is used to store results of the agglomerative hierarchical -clustering (AHC). - -Following information is returned: - -* TerminationType - completion code: - * 1 for successful completion of algorithm - * -5 inappropriate combination of clustering algorithm and distance - function was used. As for now, it is possible only when Ward's - method is called for dataset with non-Euclidean distance function. - In case negative completion code is returned, other fields of report - structure are invalid and should not be used. - -* NPoints contains number of points in the original dataset - -* Z contains information about merges performed (see below). Z contains - indexes from the original (unsorted) dataset and it can be used when you - need to know what points were merged. However, it is not convenient when - you want to build a dendrograd (see below). - -* if you want to build dendrogram, you can use Z, but it is not good - option, because Z contains indexes from unsorted dataset. Dendrogram - built from such dataset is likely to have intersections. So, you have to - reorder you points before building dendrogram. - Permutation which reorders point is returned in P. Another representation - of merges, which is more convenient for dendorgram construction, is - returned in PM. - -* more information on format of Z, P and PM can be found below and in the - examples from ALGLIB Reference Manual. - -FORMAL DESCRIPTION OF FIELDS: - NPoints number of points - Z array[NPoints-1,2], contains indexes of clusters - linked in pairs to form clustering tree. I-th row - corresponds to I-th merge: - * Z[I,0] - index of the first cluster to merge - * Z[I,1] - index of the second cluster to merge - * Z[I,0]<Z[I,1] - * clusters are numbered from 0 to 2*NPoints-2, with - indexes from 0 to NPoints-1 corresponding to points - of the original dataset, and indexes from NPoints to - 2*NPoints-2 correspond to clusters generated by - subsequent merges (I-th row of Z creates cluster - with index NPoints+I). - - IMPORTANT: indexes in Z[] are indexes in the ORIGINAL, - unsorted dataset. In addition to Z algorithm outputs - permutation which rearranges points in such way that - subsequent merges are performed on adjacent points - (such order is needed if you want to build dendrogram). - However, indexes in Z are related to original, - unrearranged sequence of points. - - P array[NPoints], permutation which reorders points for - dendrogram construction. P[i] contains index of the - position where we should move I-th point of the - original dataset in order to apply merges PZ/PM. - - PZ same as Z, but for permutation of points given by P. - The only thing which changed are indexes of the - original points; indexes of clusters remained same. - - MergeDist array[NPoints-1], contains distances between clusters - being merged (MergeDist[i] correspond to merge stored - in Z[i,...]): - * CLINK, SLINK and average linkage algorithms report - "raw", unmodified distance metric. - * Ward's method reports weighted intra-cluster - variance, which is equal to ||Ca-Cb||^2 * Sa*Sb/(Sa+Sb). - Here A and B are clusters being merged, Ca is a - center of A, Cb is a center of B, Sa is a size of A, - Sb is a size of B. - - PM array[NPoints-1,6], another representation of merges, - which is suited for dendrogram construction. It deals - with rearranged points (permutation P is applied) and - represents merges in a form which different from one - used by Z. - For each I from 0 to NPoints-2, I-th row of PM represents - merge performed on two clusters C0 and C1. Here: - * C0 contains points with indexes PM[I,0]...PM[I,1] - * C1 contains points with indexes PM[I,2]...PM[I,3] - * indexes stored in PM are given for dataset sorted - according to permutation P - * PM[I,1]=PM[I,2]-1 (only adjacent clusters are merged) - * PM[I,0]<=PM[I,1], PM[I,2]<=PM[I,3], i.e. both - clusters contain at least one point - * heights of "subdendrograms" corresponding to C0/C1 - are stored in PM[I,4] and PM[I,5]. Subdendrograms - corresponding to single-point clusters have - height=0. Dendrogram of the merge result has height - H=max(H0,H1)+1. - -NOTE: there is one-to-one correspondence between merges described by Z and - PM. I-th row of Z describes same merge of clusters as I-th row of PM, - with "left" cluster from Z corresponding to the "left" one from PM. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -
class ahcreport -{ - ae_int_t terminationtype; - ae_int_t npoints; - integer_1d_array p; - integer_2d_array z; - integer_2d_array pz; - integer_2d_array pm; - real_1d_array mergedist; -}; - -
- -
-
/************************************************************************* -This structure is a clusterization engine. - -You should not try to access its fields directly. -Use ALGLIB functions in order to work with this object. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -
class clusterizerstate -{ -}; - -
- -
-
/************************************************************************* -This structure is used to store results of the k-means clustering -algorithm. - -Following information is always returned: -* NPoints contains number of points in the original dataset -* TerminationType contains completion code, negative on failure, positive - on success -* K contains number of clusters - -For positive TerminationType we return: -* NFeatures contains number of variables in the original dataset -* C, which contains centers found by algorithm -* CIdx, which maps points of the original dataset to clusters - -FORMAL DESCRIPTION OF FIELDS: - NPoints number of points, >=0 - NFeatures number of variables, >=1 - TerminationType completion code: - * -5 if distance type is anything different from - Euclidean metric - * -3 for degenerate dataset: a) less than K distinct - points, b) K=0 for non-empty dataset. - * +1 for successful completion - K number of clusters - C array[K,NFeatures], rows of the array store centers - CIdx array[NPoints], which contains cluster indexes - IterationsCount actual number of iterations performed by clusterizer. - If algorithm performed more than one random restart, - total number of iterations is returned. - Energy merit function, "energy", sum of squared deviations - from cluster centers - - -- ALGLIB -- - Copyright 27.11.2012 by Bochkanov Sergey -*************************************************************************/ -
class kmeansreport -{ - ae_int_t npoints; - ae_int_t nfeatures; - ae_int_t terminationtype; - ae_int_t iterationscount; - double energy; - ae_int_t k; - real_2d_array c; - integer_1d_array cidx; -}; - -
- -
-
/************************************************************************* -This function initializes clusterizer object. Newly initialized object is -empty, i.e. it does not contain dataset. You should use it as follows: -1. creation -2. dataset is added with ClusterizerSetPoints() -3. additional parameters are set -3. clusterization is performed with one of the clustering functions - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::clusterizercreate( - clusterizerstate& s, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  [5]  

- -
-
/************************************************************************* -This function returns distance matrix for dataset - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - array[NPoints,NFeatures], dataset - NPoints - number of points, >=0 - NFeatures- number of features, >=1 - DistType- distance function: - * 0 Chebyshev distance (L-inf norm) - * 1 city block distance (L1 norm) - * 2 Euclidean distance (L2 norm, non-squared) - * 10 Pearson correlation: - dist(a,b) = 1-corr(a,b) - * 11 Absolute Pearson correlation: - dist(a,b) = 1-|corr(a,b)| - * 12 Uncentered Pearson correlation (cosine of the angle): - dist(a,b) = a'*b/(|a|*|b|) - * 13 Absolute uncentered Pearson correlation - dist(a,b) = |a'*b|/(|a|*|b|) - * 20 Spearman rank correlation: - dist(a,b) = 1-rankcorr(a,b) - * 21 Absolute Spearman rank correlation - dist(a,b) = 1-|rankcorr(a,b)| - -OUTPUT PARAMETERS: - D - array[NPoints,NPoints], distance matrix - (full matrix is returned, with lower and upper triangles) - -NOTE: different distance functions have different performance penalty: - * Euclidean or Pearson correlation distances are the fastest ones - * Spearman correlation distance function is a bit slower - * city block and Chebyshev distances are order of magnitude slower - - The reason behing difference in performance is that correlation-based - distance functions are computed using optimized linear algebra kernels, - while Chebyshev and city block distance functions are computed using - simple nested loops with two branches at each iteration. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::clusterizergetdistances( - real_2d_array xy, - ae_int_t npoints, - ae_int_t nfeatures, - ae_int_t disttype, - real_2d_array& d, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function takes as input clusterization report Rep, desired clusters -count K, and builds top K clusters from hierarchical clusterization tree. -It returns assignment of points to clusters (array of cluster indexes). - -INPUT PARAMETERS: - Rep - report from ClusterizerRunAHC() performed on XY - K - desired number of clusters, 1<=K<=NPoints. - K can be zero only when NPoints=0. - -OUTPUT PARAMETERS: - CIdx - array[NPoints], I-th element contains cluster index (from - 0 to K-1) for I-th point of the dataset. - CZ - array[K]. This array allows to convert cluster indexes - returned by this function to indexes used by Rep.Z. J-th - cluster returned by this function corresponds to CZ[J]-th - cluster stored in Rep.Z/PZ/PM. - It is guaranteed that CZ[I]<CZ[I+1]. - -NOTE: K clusters built by this subroutine are assumed to have no hierarchy. - Although they were obtained by manipulation with top K nodes of - dendrogram (i.e. hierarchical decomposition of dataset), this - function does not return information about hierarchy. Each of the - clusters stand on its own. - -NOTE: Cluster indexes returned by this function does not correspond to - indexes returned in Rep.Z/PZ/PM. Either you work with hierarchical - representation of the dataset (dendrogram), or you work with "flat" - representation returned by this function. Each of representations - has its own clusters indexing system (former uses [0, 2*NPoints-2]), - while latter uses [0..K-1]), although it is possible to perform - conversion from one system to another by means of CZ array, returned - by this function, which allows you to convert indexes stored in CIdx - to the numeration system used by Rep.Z. - -NOTE: this subroutine is optimized for moderate values of K. Say, for K=5 - it will perform many times faster than for K=100. Its worst-case - performance is O(N*K), although in average case it perform better - (up to O(N*log(K))). - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::clusterizergetkclusters( - ahcreport rep, - ae_int_t k, - integer_1d_array& cidx, - integer_1d_array& cz, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function performs agglomerative hierarchical clustering - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: Agglomerative hierarchical clustering algorithm has two phases: - distance matrix calculation and clustering itself. Only first phase - (distance matrix calculation) is accelerated by Intel MKL and - multithreading. Thus, acceleration is significant only for medium or - high-dimensional problems. - - Although activating multithreading gives some speedup over single- - threaded execution, you should not expect nearly-linear scaling - with respect to cores count. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - -OUTPUT PARAMETERS: - Rep - clustering results; see description of AHCReport - structure for more information. - -NOTE 1: hierarchical clustering algorithms require large amounts of memory. - In particular, this implementation needs sizeof(double)*NPoints^2 - bytes, which are used to store distance matrix. In case we work - with user-supplied matrix, this amount is multiplied by 2 (we have - to store original matrix and to work with its copy). - - For example, problem with 10000 points would require 800M of RAM, - even when working in a 1-dimensional space. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::clusterizerrunahc( - clusterizerstate s, - ahcreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  [5]  

- -
-
/************************************************************************* -This function performs clustering by k-means++ algorithm. - -You may change algorithm properties by calling: -* ClusterizerSetKMeansLimits() to change number of restarts or iterations -* ClusterizerSetKMeansInit() to change initialization algorithm - -By default, one restart and unlimited number of iterations are used. -Initialization algorithm is chosen automatically. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: k-means clustering algorithm has two phases: selection of initial - centers and clustering itself. ALGLIB parallelizes both phases. - Parallel version is optimized for the following scenario: medium or - high-dimensional problem (8 or more dimensions) with large number of - points and clusters. However, some speed-up can be obtained even - when assumptions above are violated. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - K - number of clusters, K>=0. - K can be zero only when algorithm is called for empty - dataset, in this case completion code is set to - success (+1). - If K=0 and dataset size is non-zero, we can not - meaningfully assign points to some center (there are no - centers because K=0) and return -3 as completion code - (failure). - -OUTPUT PARAMETERS: - Rep - clustering results; see description of KMeansReport - structure for more information. - -NOTE 1: k-means clustering can be performed only for datasets with - Euclidean distance function. Algorithm will return negative - completion code in Rep.TerminationType in case dataset was added - to clusterizer with DistType other than Euclidean (or dataset was - specified by distance matrix instead of explicitly given points). - -NOTE 2: by default, k-means uses non-deterministic seed to initialize RNG - which is used to select initial centers. As result, each run of - algorithm may return different values. If you need deterministic - behavior, use ClusterizerSetSeed() function. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::clusterizerrunkmeans( - clusterizerstate s, - ae_int_t k, - kmeansreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function accepts AHC report Rep, desired maximum intercluster -correlation and returns top clusters from hierarchical clusterization tree -which are separated by correlation R or LOWER. - -It returns assignment of points to clusters (array of cluster indexes). - -There is one more function with similar name - ClusterizerSeparatedByDist, -which returns clusters with intercluster distance equal to R or HIGHER -(note: higher for distance, lower for correlation). - -INPUT PARAMETERS: - Rep - report from ClusterizerRunAHC() performed on XY - R - desired maximum intercluster correlation, -1<=R<=+1 - -OUTPUT PARAMETERS: - K - number of clusters, 1<=K<=NPoints - CIdx - array[NPoints], I-th element contains cluster index (from - 0 to K-1) for I-th point of the dataset. - CZ - array[K]. This array allows to convert cluster indexes - returned by this function to indexes used by Rep.Z. J-th - cluster returned by this function corresponds to CZ[J]-th - cluster stored in Rep.Z/PZ/PM. - It is guaranteed that CZ[I]<CZ[I+1]. - -NOTE: K clusters built by this subroutine are assumed to have no hierarchy. - Although they were obtained by manipulation with top K nodes of - dendrogram (i.e. hierarchical decomposition of dataset), this - function does not return information about hierarchy. Each of the - clusters stand on its own. - -NOTE: Cluster indexes returned by this function does not correspond to - indexes returned in Rep.Z/PZ/PM. Either you work with hierarchical - representation of the dataset (dendrogram), or you work with "flat" - representation returned by this function. Each of representations - has its own clusters indexing system (former uses [0, 2*NPoints-2]), - while latter uses [0..K-1]), although it is possible to perform - conversion from one system to another by means of CZ array, returned - by this function, which allows you to convert indexes stored in CIdx - to the numeration system used by Rep.Z. - -NOTE: this subroutine is optimized for moderate values of K. Say, for K=5 - it will perform many times faster than for K=100. Its worst-case - performance is O(N*K), although in average case it perform better - (up to O(N*log(K))). - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::clusterizerseparatedbycorr( - ahcreport rep, - double r, - ae_int_t& k, - integer_1d_array& cidx, - integer_1d_array& cz, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function accepts AHC report Rep, desired minimum intercluster -distance and returns top clusters from hierarchical clusterization tree -which are separated by distance R or HIGHER. - -It returns assignment of points to clusters (array of cluster indexes). - -There is one more function with similar name - ClusterizerSeparatedByCorr, -which returns clusters with intercluster correlation equal to R or LOWER -(note: higher for distance, lower for correlation). - -INPUT PARAMETERS: - Rep - report from ClusterizerRunAHC() performed on XY - R - desired minimum intercluster distance, R>=0 - -OUTPUT PARAMETERS: - K - number of clusters, 1<=K<=NPoints - CIdx - array[NPoints], I-th element contains cluster index (from - 0 to K-1) for I-th point of the dataset. - CZ - array[K]. This array allows to convert cluster indexes - returned by this function to indexes used by Rep.Z. J-th - cluster returned by this function corresponds to CZ[J]-th - cluster stored in Rep.Z/PZ/PM. - It is guaranteed that CZ[I]<CZ[I+1]. - -NOTE: K clusters built by this subroutine are assumed to have no hierarchy. - Although they were obtained by manipulation with top K nodes of - dendrogram (i.e. hierarchical decomposition of dataset), this - function does not return information about hierarchy. Each of the - clusters stand on its own. - -NOTE: Cluster indexes returned by this function does not correspond to - indexes returned in Rep.Z/PZ/PM. Either you work with hierarchical - representation of the dataset (dendrogram), or you work with "flat" - representation returned by this function. Each of representations - has its own clusters indexing system (former uses [0, 2*NPoints-2]), - while latter uses [0..K-1]), although it is possible to perform - conversion from one system to another by means of CZ array, returned - by this function, which allows you to convert indexes stored in CIdx - to the numeration system used by Rep.Z. - -NOTE: this subroutine is optimized for moderate values of K. Say, for K=5 - it will perform many times faster than for K=100. Its worst-case - performance is O(N*K), although in average case it perform better - (up to O(N*log(K))). - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::clusterizerseparatedbydist( - ahcreport rep, - double r, - ae_int_t& k, - integer_1d_array& cidx, - integer_1d_array& cz, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets agglomerative hierarchical clustering algorithm - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - Algo - algorithm type: - * 0 complete linkage (default algorithm) - * 1 single linkage - * 2 unweighted average linkage - * 3 weighted average linkage - * 4 Ward's method - -NOTE: Ward's method works correctly only with Euclidean distance, that's - why algorithm will return negative termination code (failure) for - any other distance type. - - It is possible, however, to use this method with user-supplied - distance matrix. It is your responsibility to pass one which was - calculated with Euclidean distance function. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::clusterizersetahcalgo( - clusterizerstate s, - ae_int_t algo, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  [5]  

- -
-
/************************************************************************* -This function adds dataset given by distance matrix to the clusterizer -structure. It is important that dataset is not given explicitly - only -distance matrix is given. - -This function overrides all previous calls of ClusterizerSetPoints() or -ClusterizerSetDistances(). - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - D - array[NPoints,NPoints], distance matrix given by its upper - or lower triangle (main diagonal is ignored because its - entries are expected to be zero). - NPoints - number of points - IsUpper - whether upper or lower triangle of D is given. - -NOTE 1: different clustering algorithms have different limitations: - * agglomerative hierarchical clustering algorithms may be used with - any kind of distance metric, including one which is given by - distance matrix - * k-means++ clustering algorithm may be used only with Euclidean - distance function and explicitly given points - it can not be - used with dataset given by distance matrix - Thus, if you call this function, you will be unable to use k-means - clustering algorithm to process your problem. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::clusterizersetdistances( - clusterizerstate s, - real_2d_array d, - bool isupper, - const xparams _params = alglib::xdefault); -void alglib::clusterizersetdistances( - clusterizerstate s, - real_2d_array d, - ae_int_t npoints, - bool isupper, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function sets k-means initialization algorithm. Several different -algorithms can be chosen, including k-means++. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - InitAlgo- initialization algorithm: - * 0 automatic selection ( different versions of ALGLIB - may select different algorithms) - * 1 random initialization - * 2 k-means++ initialization (best quality of initial - centers, but long non-parallelizable initialization - phase with bad cache locality) - * 3 "fast-greedy" algorithm with efficient, easy to - parallelize initialization. Quality of initial centers - is somewhat worse than that of k-means++. This - algorithm is a default one in the current version of - ALGLIB. - *-1 "debug" algorithm which always selects first K rows - of dataset; this algorithm is used for debug purposes - only. Do not use it in the industrial code! - - -- ALGLIB -- - Copyright 21.01.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::clusterizersetkmeansinit( - clusterizerstate s, - ae_int_t initalgo, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets k-means properties: number of restarts and maximum -number of iterations per one run. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - Restarts- restarts count, >=1. - k-means++ algorithm performs several restarts and chooses - best set of centers (one with minimum squared distance). - MaxIts - maximum number of k-means iterations performed during one - run. >=0, zero value means that algorithm performs unlimited - number of iterations. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::clusterizersetkmeanslimits( - clusterizerstate s, - ae_int_t restarts, - ae_int_t maxits, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function adds dataset to the clusterizer structure. - -This function overrides all previous calls of ClusterizerSetPoints() or -ClusterizerSetDistances(). - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - XY - array[NPoints,NFeatures], dataset - NPoints - number of points, >=0 - NFeatures- number of features, >=1 - DistType- distance function: - * 0 Chebyshev distance (L-inf norm) - * 1 city block distance (L1 norm) - * 2 Euclidean distance (L2 norm), non-squared - * 10 Pearson correlation: - dist(a,b) = 1-corr(a,b) - * 11 Absolute Pearson correlation: - dist(a,b) = 1-|corr(a,b)| - * 12 Uncentered Pearson correlation (cosine of the angle): - dist(a,b) = a'*b/(|a|*|b|) - * 13 Absolute uncentered Pearson correlation - dist(a,b) = |a'*b|/(|a|*|b|) - * 20 Spearman rank correlation: - dist(a,b) = 1-rankcorr(a,b) - * 21 Absolute Spearman rank correlation - dist(a,b) = 1-|rankcorr(a,b)| - -NOTE 1: different distance functions have different performance penalty: - * Euclidean or Pearson correlation distances are the fastest ones - * Spearman correlation distance function is a bit slower - * city block and Chebyshev distances are order of magnitude slower - - The reason behing difference in performance is that correlation-based - distance functions are computed using optimized linear algebra kernels, - while Chebyshev and city block distance functions are computed using - simple nested loops with two branches at each iteration. - -NOTE 2: different clustering algorithms have different limitations: - * agglomerative hierarchical clustering algorithms may be used with - any kind of distance metric - * k-means++ clustering algorithm may be used only with Euclidean - distance function - Thus, list of specific clustering algorithms you may use depends - on distance function you specify when you set your dataset. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::clusterizersetpoints( - clusterizerstate s, - real_2d_array xy, - ae_int_t disttype, - const xparams _params = alglib::xdefault); -void alglib::clusterizersetpoints( - clusterizerstate s, - real_2d_array xy, - ae_int_t npoints, - ae_int_t nfeatures, - ae_int_t disttype, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  [5]  

- -
-
/************************************************************************* -This function sets seed which is used to initialize internal RNG. By -default, deterministic seed is used - same for each run of clusterizer. If -you specify non-deterministic seed value, then some algorithms which -depend on random initialization (in current version: k-means) may return -slightly different results after each run. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - Seed - seed: - * positive values = use deterministic seed for each run of - algorithms which depend on random initialization - * zero or negative values = use non-deterministic seed - - -- ALGLIB -- - Copyright 08.06.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::clusterizersetseed( - clusterizerstate s, - ae_int_t seed, - const xparams _params = alglib::xdefault); - -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // The very simple clusterization example
-    //
-    // We have a set of points in 2D space:
-    //     (P0,P1,P2,P3,P4) = ((1,1),(1,2),(4,1),(2,3),(4,1.5))
-    //
-    //  |
-    //  |     P3
-    //  |
-    //  | P1          
-    //  |             P4
-    //  | P0          P2
-    //  |-------------------------
-    //
-    // We want to perform Agglomerative Hierarchic Clusterization (AHC),
-    // using complete linkage (default algorithm) and Euclidean distance
-    // (default metric).
-    //
-    // In order to do that, we:
-    // * create clusterizer with clusterizercreate()
-    // * set points XY and metric (2=Euclidean) with clusterizersetpoints()
-    // * run AHC algorithm with clusterizerrunahc
-    //
-    // You may see that clusterization itself is a minor part of the example,
-    // most of which is dominated by comments :)
-    //
-    clusterizerstate s;
-    ahcreport rep;
-    real_2d_array xy = "[[1,1],[1,2],[4,1],[2,3],[4,1.5]]";
-
-    clusterizercreate(s);
-    clusterizersetpoints(s, xy, 2);
-    clusterizerrunahc(s, rep);
-
-    //
-    // Now we've built our clusterization tree. Rep.z contains information which
-    // is required to build dendrogram. I-th row of rep.z represents one merge
-    // operation, with first cluster to merge having index rep.z[I,0] and second
-    // one having index rep.z[I,1]. Merge result has index NPoints+I.
-    //
-    // Clusters with indexes less than NPoints are single-point initial clusters,
-    // while ones with indexes from NPoints to 2*NPoints-2 are multi-point
-    // clusters created during merges.
-    //
-    // In our example, Z=[[2,4], [0,1], [3,6], [5,7]]
-    //
-    // It means that:
-    // * first, we merge C2=(P2) and C4=(P4),    and create C5=(P2,P4)
-    // * then, we merge  C2=(P0) and C1=(P1),    and create C6=(P0,P1)
-    // * then, we merge  C3=(P3) and C6=(P0,P1), and create C7=(P0,P1,P3)
-    // * finally, we merge C5 and C7 and create C8=(P0,P1,P2,P3,P4)
-    //
-    // Thus, we have following dendrogram:
-    //  
-    //      ------8-----
-    //      |          |
-    //      |      ----7----
-    //      |      |       |
-    //   ---5---   |    ---6---
-    //   |     |   |    |     |
-    //   P2   P4   P3   P0   P1
-    //
-    printf("%s\n", rep.z.tostring().c_str()); // EXPECTED: [[2,4],[0,1],[3,6],[5,7]]
-
-    //
-    // We've built dendrogram above by reordering our dataset.
-    //
-    // Without such reordering it would be impossible to build dendrogram without
-    // intersections. Luckily, ahcreport structure contains two additional fields
-    // which help to build dendrogram from your data:
-    // * rep.p, which contains permutation applied to dataset
-    // * rep.pm, which contains another representation of merges 
-    //
-    // In our example we have:
-    // * P=[3,4,0,2,1]
-    // * PZ=[[0,0,1,1,0,0],[3,3,4,4,0,0],[2,2,3,4,0,1],[0,1,2,4,1,2]]
-    //
-    // Permutation array P tells us that P0 should be moved to position 3,
-    // P1 moved to position 4, P2 moved to position 0 and so on:
-    //
-    //   (P0 P1 P2 P3 P4) => (P2 P4 P3 P0 P1)
-    //
-    // Merges array PZ tells us how to perform merges on the sorted dataset.
-    // One row of PZ corresponds to one merge operations, with first pair of
-    // elements denoting first of the clusters to merge (start index, end
-    // index) and next pair of elements denoting second of the clusters to
-    // merge. Clusters being merged are always adjacent, with first one on
-    // the left and second one on the right.
-    //
-    // For example, first row of PZ tells us that clusters [0,0] and [1,1] are
-    // merged (single-point clusters, with first one containing P2 and second
-    // one containing P4). Third row of PZ tells us that we merge one single-
-    // point cluster [2,2] with one two-point cluster [3,4].
-    //
-    // There are two more elements in each row of PZ. These are the helper
-    // elements, which denote HEIGHT (not size) of left and right subdendrograms.
-    // For example, according to PZ, first two merges are performed on clusterization
-    // trees of height 0, while next two merges are performed on 0-1 and 1-2
-    // pairs of trees correspondingly.
-    //
-    printf("%s\n", rep.p.tostring().c_str()); // EXPECTED: [3,4,0,2,1]
-    printf("%s\n", rep.pm.tostring().c_str()); // EXPECTED: [[0,0,1,1,0,0],[3,3,4,4,0,0],[2,2,3,4,0,1],[0,1,2,4,1,2]]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // We have three points in 4D space:
-    //     (P0,P1,P2) = ((1, 2, 1, 2), (6, 7, 6, 7), (7, 6, 7, 6))
-    //
-    // We want to try clustering them with different distance functions.
-    // Distance function is chosen when we add dataset to the clusterizer.
-    // We can choose several distance types - Euclidean, city block, Chebyshev,
-    // several correlation measures or user-supplied distance matrix.
-    //
-    // Here we'll try three distances: Euclidean, Pearson correlation,
-    // user-supplied distance matrix. Different distance functions lead
-    // to different choices being made by algorithm during clustering.
-    //
-    clusterizerstate s;
-    ahcreport rep;
-    ae_int_t disttype;
-    real_2d_array xy = "[[1, 2, 1, 2], [6, 7, 6, 7], [7, 6, 7, 6]]";
-    clusterizercreate(s);
-
-    // With Euclidean distance function (disttype=2) two closest points
-    // are P1 and P2, thus:
-    // * first, we merge P1 and P2 to form C3=[P1,P2]
-    // * second, we merge P0 and C3 to form C4=[P0,P1,P2]
-    disttype = 2;
-    clusterizersetpoints(s, xy, disttype);
-    clusterizerrunahc(s, rep);
-    printf("%s\n", rep.z.tostring().c_str()); // EXPECTED: [[1,2],[0,3]]
-
-    // With Pearson correlation distance function (disttype=10) situation
-    // is different - distance between P0 and P1 is zero, thus:
-    // * first, we merge P0 and P1 to form C3=[P0,P1]
-    // * second, we merge P2 and C3 to form C4=[P0,P1,P2]
-    disttype = 10;
-    clusterizersetpoints(s, xy, disttype);
-    clusterizerrunahc(s, rep);
-    printf("%s\n", rep.z.tostring().c_str()); // EXPECTED: [[0,1],[2,3]]
-
-    // Finally, we try clustering with user-supplied distance matrix:
-    //     [ 0 3 1 ]
-    // P = [ 3 0 3 ], where P[i,j] = dist(Pi,Pj)
-    //     [ 1 3 0 ]
-    //
-    // * first, we merge P0 and P2 to form C3=[P0,P2]
-    // * second, we merge P1 and C3 to form C4=[P0,P1,P2]
-    real_2d_array d = "[[0,3,1],[3,0,3],[1,3,0]]";
-    clusterizersetdistances(s, d, true);
-    clusterizerrunahc(s, rep);
-    printf("%s\n", rep.z.tostring().c_str()); // EXPECTED: [[0,2],[1,3]]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // We have a set of points in 2D space:
-    //     (P0,P1,P2,P3,P4) = ((1,1),(1,2),(4,1),(2,3),(4,1.5))
-    //
-    //  |
-    //  |     P3
-    //  |
-    //  | P1          
-    //  |             P4
-    //  | P0          P2
-    //  |-------------------------
-    //
-    // We perform Agglomerative Hierarchic Clusterization (AHC) and we want
-    // to get top K clusters from clusterization tree for different K.
-    //
-    clusterizerstate s;
-    ahcreport rep;
-    real_2d_array xy = "[[1,1],[1,2],[4,1],[2,3],[4,1.5]]";
-    integer_1d_array cidx;
-    integer_1d_array cz;
-
-    clusterizercreate(s);
-    clusterizersetpoints(s, xy, 2);
-    clusterizerrunahc(s, rep);
-
-    // with K=5, every points is assigned to its own cluster:
-    // C0=P0, C1=P1 and so on...
-    clusterizergetkclusters(rep, 5, cidx, cz);
-    printf("%s\n", cidx.tostring().c_str()); // EXPECTED: [0,1,2,3,4]
-
-    // with K=1 we have one large cluster C0=[P0,P1,P2,P3,P4,P5]
-    clusterizergetkclusters(rep, 1, cidx, cz);
-    printf("%s\n", cidx.tostring().c_str()); // EXPECTED: [0,0,0,0,0]
-
-    // with K=3 we have three clusters C0=[P3], C1=[P2,P4], C2=[P0,P1]
-    clusterizergetkclusters(rep, 3, cidx, cz);
-    printf("%s\n", cidx.tostring().c_str()); // EXPECTED: [2,2,1,0,1]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // The very simple clusterization example
-    //
-    // We have a set of points in 2D space:
-    //     (P0,P1,P2,P3,P4) = ((1,1),(1,2),(4,1),(2,3),(4,1.5))
-    //
-    //  |
-    //  |     P3
-    //  |
-    //  | P1          
-    //  |             P4
-    //  | P0          P2
-    //  |-------------------------
-    //
-    // We want to perform k-means++ clustering with K=2.
-    //
-    // In order to do that, we:
-    // * create clusterizer with clusterizercreate()
-    // * set points XY and metric (must be Euclidean, distype=2) with clusterizersetpoints()
-    // * (optional) set number of restarts from random positions to 5
-    // * run k-means algorithm with clusterizerrunkmeans()
-    //
-    // You may see that clusterization itself is a minor part of the example,
-    // most of which is dominated by comments :)
-    //
-    clusterizerstate s;
-    kmeansreport rep;
-    real_2d_array xy = "[[1,1],[1,2],[4,1],[2,3],[4,1.5]]";
-
-    clusterizercreate(s);
-    clusterizersetpoints(s, xy, 2);
-    clusterizersetkmeanslimits(s, 5, 0);
-    clusterizerrunkmeans(s, 2, rep);
-
-    //
-    // We've performed clusterization, and it succeeded (completion code is +1).
-    //
-    // Now first center is stored in the first row of rep.c, second one is stored
-    // in the second row. rep.cidx can be used to determine which center is
-    // closest to some specific point of the dataset.
-    //
-    printf("%d\n", int(rep.terminationtype)); // EXPECTED: 1
-
-    // We called clusterizersetpoints() with disttype=2 because k-means++
-    // algorithm does NOT support metrics other than Euclidean. But what if we
-    // try to use some other metric?
-    //
-    // We change metric type by calling clusterizersetpoints() one more time,
-    // and try to run k-means algo again. It fails.
-    //
-    clusterizersetpoints(s, xy, 0);
-    clusterizerrunkmeans(s, 2, rep);
-    printf("%d\n", int(rep.terminationtype)); // EXPECTED: -5
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // We have a set of points in 1D space:
-    //     (P0,P1,P2,P3,P4) = (1, 3, 10, 16, 20)
-    //
-    // We want to perform Agglomerative Hierarchic Clusterization (AHC),
-    // using either complete or single linkage and Euclidean distance
-    // (default metric).
-    //
-    // First two steps merge P0/P1 and P3/P4 independently of the linkage type.
-    // However, third step depends on linkage type being used:
-    // * in case of complete linkage P2=10 is merged with [P0,P1]
-    // * in case of single linkage P2=10 is merged with [P3,P4]
-    //
-    clusterizerstate s;
-    ahcreport rep;
-    real_2d_array xy = "[[1],[3],[10],[16],[20]]";
-    integer_1d_array cidx;
-    integer_1d_array cz;
-
-    clusterizercreate(s);
-    clusterizersetpoints(s, xy, 2);
-
-    // use complete linkage, reduce set down to 2 clusters.
-    // print clusterization with clusterizergetkclusters(2).
-    // P2 must belong to [P0,P1]
-    clusterizersetahcalgo(s, 0);
-    clusterizerrunahc(s, rep);
-    clusterizergetkclusters(rep, 2, cidx, cz);
-    printf("%s\n", cidx.tostring().c_str()); // EXPECTED: [1,1,1,0,0]
-
-    // use single linkage, reduce set down to 2 clusters.
-    // print clusterization with clusterizergetkclusters(2).
-    // P2 must belong to [P2,P3]
-    clusterizersetahcalgo(s, 1);
-    clusterizerrunahc(s, rep);
-    clusterizergetkclusters(rep, 2, cidx, cz);
-    printf("%s\n", cidx.tostring().c_str()); // EXPECTED: [0,0,1,1,1]
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* -1-dimensional complex convolution. - -For given A/B returns conv(A,B) (non-circular). Subroutine can automatically -choose between three implementations: straightforward O(M*N) formula for -very small N (or M), overlap-add algorithm for cases where max(M,N) is -significantly larger than min(M,N), but O(M*N) algorithm is too slow, and -general FFT-based formula for cases where two previois algorithms are too -slow. - -Algorithm has max(M,N)*log(max(M,N)) complexity for any M/N. - -INPUT PARAMETERS - A - array[0..M-1] - complex function to be transformed - M - problem size - B - array[0..N-1] - complex function to be transformed - N - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..N+M-2]. - -NOTE: - It is assumed that A is zero at T<0, B is zero too. If one or both -functions have non-zero values at negative T's, you can still use this -subroutine - just shift its result correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::convc1d( - complex_1d_array a, - ae_int_t m, - complex_1d_array b, - ae_int_t n, - complex_1d_array& r, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -1-dimensional circular complex convolution. - -For given S/R returns conv(S,R) (circular). Algorithm has linearithmic -complexity for any M/N. - -IMPORTANT: normal convolution is commutative, i.e. it is symmetric - -conv(A,B)=conv(B,A). Cyclic convolution IS NOT. One function - S - is a -signal, periodic function, and another - R - is a response, non-periodic -function with limited length. - -INPUT PARAMETERS - S - array[0..M-1] - complex periodic signal - M - problem size - B - array[0..N-1] - complex non-periodic response - N - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..M-1]. - -NOTE: - It is assumed that B is zero at T<0. If it has non-zero values at -negative T's, you can still use this subroutine - just shift its result -correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::convc1dcircular( - complex_1d_array s, - ae_int_t m, - complex_1d_array r, - ae_int_t n, - complex_1d_array& c, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -1-dimensional circular complex deconvolution (inverse of ConvC1DCircular()). - -Algorithm has M*log(M)) complexity for any M (composite or prime). - -INPUT PARAMETERS - A - array[0..M-1] - convolved periodic signal, A = conv(R, B) - M - convolved signal length - B - array[0..N-1] - non-periodic response - N - response length - -OUTPUT PARAMETERS - R - deconvolved signal. array[0..M-1]. - -NOTE: - deconvolution is unstable process and may result in division by zero -(if your response function is degenerate, i.e. has zero Fourier coefficient). - -NOTE: - It is assumed that B is zero at T<0. If it has non-zero values at -negative T's, you can still use this subroutine - just shift its result -correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::convc1dcircularinv( - complex_1d_array a, - ae_int_t m, - complex_1d_array b, - ae_int_t n, - complex_1d_array& r, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -1-dimensional complex non-circular deconvolution (inverse of ConvC1D()). - -Algorithm has M*log(M)) complexity for any M (composite or prime). - -INPUT PARAMETERS - A - array[0..M-1] - convolved signal, A = conv(R, B) - M - convolved signal length - B - array[0..N-1] - response - N - response length, N<=M - -OUTPUT PARAMETERS - R - deconvolved signal. array[0..M-N]. - -NOTE: - deconvolution is unstable process and may result in division by zero -(if your response function is degenerate, i.e. has zero Fourier coefficient). - -NOTE: - It is assumed that A is zero at T<0, B is zero too. If one or both -functions have non-zero values at negative T's, you can still use this -subroutine - just shift its result correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::convc1dinv( - complex_1d_array a, - ae_int_t m, - complex_1d_array b, - ae_int_t n, - complex_1d_array& r, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -1-dimensional real convolution. - -Analogous to ConvC1D(), see ConvC1D() comments for more details. - -INPUT PARAMETERS - A - array[0..M-1] - real function to be transformed - M - problem size - B - array[0..N-1] - real function to be transformed - N - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..N+M-2]. - -NOTE: - It is assumed that A is zero at T<0, B is zero too. If one or both -functions have non-zero values at negative T's, you can still use this -subroutine - just shift its result correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::convr1d( - real_1d_array a, - ae_int_t m, - real_1d_array b, - ae_int_t n, - real_1d_array& r, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -1-dimensional circular real convolution. - -Analogous to ConvC1DCircular(), see ConvC1DCircular() comments for more details. - -INPUT PARAMETERS - S - array[0..M-1] - real signal - M - problem size - B - array[0..N-1] - real response - N - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..M-1]. - -NOTE: - It is assumed that B is zero at T<0. If it has non-zero values at -negative T's, you can still use this subroutine - just shift its result -correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::convr1dcircular( - real_1d_array s, - ae_int_t m, - real_1d_array r, - ae_int_t n, - real_1d_array& c, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -1-dimensional complex deconvolution (inverse of ConvC1D()). - -Algorithm has M*log(M)) complexity for any M (composite or prime). - -INPUT PARAMETERS - A - array[0..M-1] - convolved signal, A = conv(R, B) - M - convolved signal length - B - array[0..N-1] - response - N - response length - -OUTPUT PARAMETERS - R - deconvolved signal. array[0..M-N]. - -NOTE: - deconvolution is unstable process and may result in division by zero -(if your response function is degenerate, i.e. has zero Fourier coefficient). - -NOTE: - It is assumed that B is zero at T<0. If it has non-zero values at -negative T's, you can still use this subroutine - just shift its result -correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::convr1dcircularinv( - real_1d_array a, - ae_int_t m, - real_1d_array b, - ae_int_t n, - real_1d_array& r, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -1-dimensional real deconvolution (inverse of ConvC1D()). - -Algorithm has M*log(M)) complexity for any M (composite or prime). - -INPUT PARAMETERS - A - array[0..M-1] - convolved signal, A = conv(R, B) - M - convolved signal length - B - array[0..N-1] - response - N - response length, N<=M - -OUTPUT PARAMETERS - R - deconvolved signal. array[0..M-N]. - -NOTE: - deconvolution is unstable process and may result in division by zero -(if your response function is degenerate, i.e. has zero Fourier coefficient). - -NOTE: - It is assumed that A is zero at T<0, B is zero too. If one or both -functions have non-zero values at negative T's, you can still use this -subroutine - just shift its result correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::convr1dinv( - real_1d_array a, - ae_int_t m, - real_1d_array b, - ae_int_t n, - real_1d_array& r, - const xparams _params = alglib::xdefault); - -
- -
- -corrc1d
-corrc1dcircular
-corrr1d
-corrr1dcircular
- - -
- -
-
/************************************************************************* -1-dimensional complex cross-correlation. - -For given Pattern/Signal returns corr(Pattern,Signal) (non-circular). - -Correlation is calculated using reduction to convolution. Algorithm with -max(N,N)*log(max(N,N)) complexity is used (see ConvC1D() for more info -about performance). - -IMPORTANT: - for historical reasons subroutine accepts its parameters in reversed - order: CorrC1D(Signal, Pattern) = Pattern x Signal (using traditional - definition of cross-correlation, denoting cross-correlation as "x"). - -INPUT PARAMETERS - Signal - array[0..N-1] - complex function to be transformed, - signal containing pattern - N - problem size - Pattern - array[0..M-1] - complex function to be transformed, - pattern to search withing signal - M - problem size - -OUTPUT PARAMETERS - R - cross-correlation, array[0..N+M-2]: - * positive lags are stored in R[0..N-1], - R[i] = sum(conj(pattern[j])*signal[i+j] - * negative lags are stored in R[N..N+M-2], - R[N+M-1-i] = sum(conj(pattern[j])*signal[-i+j] - -NOTE: - It is assumed that pattern domain is [0..M-1]. If Pattern is non-zero -on [-K..M-1], you can still use this subroutine, just shift result by K. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::corrc1d( - complex_1d_array signal, - ae_int_t n, - complex_1d_array pattern, - ae_int_t m, - complex_1d_array& r, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -1-dimensional circular complex cross-correlation. - -For given Pattern/Signal returns corr(Pattern,Signal) (circular). -Algorithm has linearithmic complexity for any M/N. - -IMPORTANT: - for historical reasons subroutine accepts its parameters in reversed - order: CorrC1DCircular(Signal, Pattern) = Pattern x Signal (using - traditional definition of cross-correlation, denoting cross-correlation - as "x"). - -INPUT PARAMETERS - Signal - array[0..N-1] - complex function to be transformed, - periodic signal containing pattern - N - problem size - Pattern - array[0..M-1] - complex function to be transformed, - non-periodic pattern to search withing signal - M - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..M-1]. - - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::corrc1dcircular( - complex_1d_array signal, - ae_int_t m, - complex_1d_array pattern, - ae_int_t n, - complex_1d_array& c, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -1-dimensional real cross-correlation. - -For given Pattern/Signal returns corr(Pattern,Signal) (non-circular). - -Correlation is calculated using reduction to convolution. Algorithm with -max(N,N)*log(max(N,N)) complexity is used (see ConvC1D() for more info -about performance). - -IMPORTANT: - for historical reasons subroutine accepts its parameters in reversed - order: CorrR1D(Signal, Pattern) = Pattern x Signal (using traditional - definition of cross-correlation, denoting cross-correlation as "x"). - -INPUT PARAMETERS - Signal - array[0..N-1] - real function to be transformed, - signal containing pattern - N - problem size - Pattern - array[0..M-1] - real function to be transformed, - pattern to search withing signal - M - problem size - -OUTPUT PARAMETERS - R - cross-correlation, array[0..N+M-2]: - * positive lags are stored in R[0..N-1], - R[i] = sum(pattern[j]*signal[i+j] - * negative lags are stored in R[N..N+M-2], - R[N+M-1-i] = sum(pattern[j]*signal[-i+j] - -NOTE: - It is assumed that pattern domain is [0..M-1]. If Pattern is non-zero -on [-K..M-1], you can still use this subroutine, just shift result by K. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::corrr1d( - real_1d_array signal, - ae_int_t n, - real_1d_array pattern, - ae_int_t m, - real_1d_array& r, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -1-dimensional circular real cross-correlation. - -For given Pattern/Signal returns corr(Pattern,Signal) (circular). -Algorithm has linearithmic complexity for any M/N. - -IMPORTANT: - for historical reasons subroutine accepts its parameters in reversed - order: CorrR1DCircular(Signal, Pattern) = Pattern x Signal (using - traditional definition of cross-correlation, denoting cross-correlation - as "x"). - -INPUT PARAMETERS - Signal - array[0..N-1] - real function to be transformed, - periodic signal containing pattern - N - problem size - Pattern - array[0..M-1] - real function to be transformed, - non-periodic pattern to search withing signal - M - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..M-1]. - - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::corrr1dcircular( - real_1d_array signal, - ae_int_t m, - real_1d_array pattern, - ae_int_t n, - real_1d_array& c, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -Pearson's correlation coefficient significance test - -This test checks hypotheses about whether X and Y are samples of two -continuous distributions having zero correlation or whether their -correlation is non-zero. - -The following tests are performed: - * two-tailed test (null hypothesis - X and Y have zero correlation) - * left-tailed test (null hypothesis - the correlation coefficient is - greater than or equal to 0) - * right-tailed test (null hypothesis - the correlation coefficient is - less than or equal to 0). - -Requirements: - * the number of elements in each sample is not less than 5 - * normality of distributions of X and Y. - -Input parameters: - R - Pearson's correlation coefficient for X and Y - N - number of elements in samples, N>=5. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::pearsoncorrelationsignificance( - double r, - ae_int_t n, - double& bothtails, - double& lefttail, - double& righttail, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Spearman's rank correlation coefficient significance test - -This test checks hypotheses about whether X and Y are samples of two -continuous distributions having zero correlation or whether their -correlation is non-zero. - -The following tests are performed: - * two-tailed test (null hypothesis - X and Y have zero correlation) - * left-tailed test (null hypothesis - the correlation coefficient is - greater than or equal to 0) - * right-tailed test (null hypothesis - the correlation coefficient is - less than or equal to 0). - -Requirements: - * the number of elements in each sample is not less than 5. - -The test is non-parametric and doesn't require distributions X and Y to be -normal. - -Input parameters: - R - Spearman's rank correlation coefficient for X and Y - N - number of elements in samples, N>=5. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spearmanrankcorrelationsignificance( - double r, - ae_int_t n, - double& bothtails, - double& lefttail, - double& righttail, - const xparams _params = alglib::xdefault); - -
- -
- -kmeansgenerate
- - -
- -
-
/************************************************************************* -k-means++ clusterization. -Backward compatibility function, we recommend to use CLUSTERING subpackage -as better replacement. - - -- ALGLIB -- - Copyright 21.03.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::kmeansgenerate( - real_2d_array xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t k, - ae_int_t restarts, - ae_int_t& info, - real_2d_array& c, - integer_1d_array& xyc, - const xparams _params = alglib::xdefault); - -
- -
- -dawsonintegral
- - -
- -
-
/************************************************************************* -Dawson's Integral - -Approximates the integral - - x - - - 2 | | 2 - dawsn(x) = exp( -x ) | exp( t ) dt - | | - - - 0 - -Three different rational approximations are employed, for -the intervals 0 to 3.25; 3.25 to 6.25; and 6.25 up. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,10 10000 6.9e-16 1.0e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::dawsonintegral( - double x, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -Decision forest (random forest) model. -*************************************************************************/ -
class decisionforest -{ -}; - -
- -
-
/************************************************************************* -Buffer object which is used to perform various requests (usually model -inference) in the multithreaded mode (multiple threads working with same -DF object). - -This object should be created with DFCreateBuffer(). -*************************************************************************/ -
class decisionforestbuffer -{ -}; - -
- -
-
/************************************************************************* -A random forest (decision forest) builder object. - -Used to store dataset and specify decision forest training algorithm settings. -*************************************************************************/ -
class decisionforestbuilder -{ -}; - -
- -
-
/************************************************************************* -Decision forest training report. - -=== training/oob errors ================================================== - -Following fields store training set errors: -* relclserror - fraction of misclassified cases, [0,1] -* avgce - average cross-entropy in bits per symbol -* rmserror - root-mean-square error -* avgerror - average error -* avgrelerror - average relative error - -Out-of-bag estimates are stored in fields with same names, but "oob" prefix. - -For classification problems: -* RMS, AVG and AVGREL errors are calculated for posterior probabilities - -For regression problems: -* RELCLS and AVGCE errors are zero - -=== variable importance ================================================== - -Following fields are used to store variable importance information: - -* topvars - variables ordered from the most important to - less important ones (according to current - choice of importance raiting). - For example, topvars[0] contains index of the - most important variable, and topvars[0:2] are - indexes of 3 most important ones and so on. - -* varimportances - array[nvars], ratings (the larger, the more - important the variable is, always in [0,1] - range). - By default, filled by zeros (no importance - ratings are provided unless you explicitly - request them). - Zero rating means that variable is not important, - however you will rarely encounter such a thing, - in many cases unimportant variables produce - nearly-zero (but nonzero) ratings. - -Variable importance report must be EXPLICITLY requested by calling: -* dfbuildersetimportancegini() function, if you need out-of-bag Gini-based - importance rating also known as MDI (fast to calculate, resistant to - overfitting issues, but has some bias towards continuous and - high-cardinality categorical variables) -* dfbuildersetimportancetrngini() function, if you need training set Gini- - -based importance rating (what other packages typically report). -* dfbuildersetimportancepermutation() function, if you need permutation- - based importance rating also known as MDA (slower to calculate, but less - biased) -* dfbuildersetimportancenone() function, if you do not need importance - ratings - ratings will be zero, topvars[] will be [0,1,2,...] - -Different importance ratings (Gini or permutation) produce non-comparable -values. Although in all cases rating values lie in [0,1] range, there are -exist differences: -* informally speaking, Gini importance rating tends to divide "unit amount - of importance" between several important variables, i.e. it produces - estimates which roughly sum to 1.0 (or less than 1.0, if your task can - not be solved exactly). If all variables are equally important, they - will have same rating, roughly 1/NVars, even if every variable is - critically important. -* from the other side, permutation importance tells us what percentage of - the model predictive power will be ruined by permuting this specific - variable. It does not produce estimates which sum to one. Critically - important variable will have rating close to 1.0, and you may have - multiple variables with such a rating. - -More information on variable importance ratings can be found in comments -on the dfbuildersetimportancegini() and dfbuildersetimportancepermutation() -functions. -*************************************************************************/ -
class dfreport -{ - double relclserror; - double avgce; - double rmserror; - double avgerror; - double avgrelerror; - double oobrelclserror; - double oobavgce; - double oobrmserror; - double oobavgerror; - double oobavgrelerror; - integer_1d_array topvars; - real_1d_array varimportances; -}; - -
- -
-
/************************************************************************* -Average cross-entropy (in bits per element) on the test set - -INPUT PARAMETERS: - DF - decision forest model - XY - test set - NPoints - test set size - -RESULT: - CrossEntropy/(NPoints*LN(2)). - Zero if model solves regression task. - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -
double alglib::dfavgce( - decisionforest df, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Average error on the test set - -INPUT PARAMETERS: - DF - decision forest model - XY - test set - NPoints - test set size - -RESULT: - Its meaning for regression task is obvious. As for - classification task, it means average error when estimating posterior - probabilities. - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -
double alglib::dfavgerror( - decisionforest df, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Average relative error on the test set - -INPUT PARAMETERS: - DF - decision forest model - XY - test set - NPoints - test set size - -RESULT: - Its meaning for regression task is obvious. As for - classification task, it means average relative error when estimating - posterior probability of belonging to the correct class. - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -
double alglib::dfavgrelerror( - decisionforest df, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function performs binary compression of the decision forest. - -Original decision forest produced by the forest builder is stored using -64-bit representation for all numbers - offsets, variable indexes, split -points. - -It is possible to significantly reduce model size by means of: -* using compressed dynamic encoding for integers (offsets and variable - indexes), which uses just 1 byte to store small ints (less than 128), - just 2 bytes for larger values (less than 128^2) and so on -* storing floating point numbers using 8-bit exponent and 16-bit mantissa - -As result, model needs significantly less memory (compression factor -depends on variable and class counts). In particular: -* NVars<128 and NClasses<128 result in 4.4x-5.7x model size reduction -* NVars<16384 and NClasses<128 result in 3.7x-4.5x model size reduction - -Such storage format performs lossless compression of all integers, but -compression of floating point values (split values) is lossy, with roughly -0.01% relative error introduced during rounding. Thus, we recommend you to -re-evaluate model accuracy after compression. - -Another downside of compression is ~1.5x reduction in the inference -speed due to necessity of dynamic decompression of the compressed model. - -INPUT PARAMETERS: - DF - decision forest built by forest builder - -OUTPUT PARAMETERS: - DF - replaced by compressed forest - -RESULT: - compression factor (in-RAM size of the compressed model vs than of the - uncompressed one), positive number larger than 1.0 - - -- ALGLIB -- - Copyright 22.07.2019 by Bochkanov Sergey -*************************************************************************/ -
double alglib::dfbinarycompression( - decisionforest df, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine builds decision forest according to current settings using -dataset internally stored in the builder object. Dense algorithm is used. - -NOTE: this function uses dense algorithm for forest construction - independently from the dataset format (dense or sparse). - -NOTE: forest built with this function is stored in-memory using 64-bit - data structures for offsets/indexes/split values. It is possible to - convert forest into more memory-efficient compressed binary - representation. Depending on the problem properties, 3.7x-5.7x - compression factors are possible. - - The downsides of compression are (a) slight reduction in the model - accuracy and (b) ~1.5x reduction in the inference speed (due to - increased complexity of the storage format). - - See comments on dfbinarycompression() for more info. - -Default settings are used by the algorithm; you can tweak them with the -help of the following functions: -* dfbuildersetrfactor() - to control a fraction of the dataset used for - subsampling -* dfbuildersetrandomvars() - to control number of variables randomly chosen - for decision rule creation - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - decision forest builder object - NTrees - NTrees>=1, number of trees to train - -OUTPUT PARAMETERS: - DF - decision forest. You can compress this forest to more - compact 16-bit representation with dfbinarycompression() - Rep - report, see below for information on its fields. - -=== report information produced by forest construction function ========== - -Decision forest training report includes following information: -* training set errors -* out-of-bag estimates of errors -* variable importance ratings - -Following fields are used to store information: -* training set errors are stored in rep.relclserror, rep.avgce, rep.rmserror, - rep.avgerror and rep.avgrelerror -* out-of-bag estimates of errors are stored in rep.oobrelclserror, rep.oobavgce, - rep.oobrmserror, rep.oobavgerror and rep.oobavgrelerror - -Variable importance reports, if requested by dfbuildersetimportancegini(), -dfbuildersetimportancetrngini() or dfbuildersetimportancepermutation() -call, are stored in: -* rep.varimportances field stores importance ratings -* rep.topvars stores variable indexes ordered from the most important to - less important ones - -You can find more information about report fields in: -* comments on dfreport structure -* comments on dfbuildersetimportancegini function -* comments on dfbuildersetimportancetrngini function -* comments on dfbuildersetimportancepermutation function - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dfbuilderbuildrandomforest( - decisionforestbuilder s, - ae_int_t ntrees, - decisionforest& df, - dfreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This subroutine creates DecisionForestBuilder object which is used to -train decision forests. - -By default, new builder stores empty dataset and some reasonable default -settings. At the very least, you should specify dataset prior to building -decision forest. You can also tweak settings of the forest construction -algorithm (recommended, although default setting should work well). - -Following actions are mandatory: -* calling dfbuildersetdataset() to specify dataset -* calling dfbuilderbuildrandomforest() to build decision forest using - current dataset and default settings - -Additionally, you may call: -* dfbuildersetrndvars() or dfbuildersetrndvarsratio() to specify number of - variables randomly chosen for each split -* dfbuildersetsubsampleratio() to specify fraction of the dataset randomly - subsampled to build each tree -* dfbuildersetseed() to control random seed chosen for tree construction - -INPUT PARAMETERS: - none - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dfbuildercreate( - decisionforestbuilder& s, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function is an alias for dfbuilderpeekprogress(), left in ALGLIB for -backward compatibility reasons. - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -
double alglib::dfbuildergetprogress( - decisionforestbuilder s, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function is used to peek into decision forest construction process -from some other thread and get current progress indicator. - -It returns value in [0,1]. - -INPUT PARAMETERS: - S - decision forest builder object used to build forest - in some other thread - -RESULT: - progress value, in [0,1] - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -
double alglib::dfbuilderpeekprogress( - decisionforestbuilder s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine adds dense dataset to the internal storage of the builder -object. Specifying your dataset in the dense format means that the dense -version of the forest construction algorithm will be invoked. - -INPUT PARAMETERS: - S - decision forest builder object - XY - array[NPoints,NVars+1] (minimum size; actual size can - be larger, only leading part is used anyway), dataset: - * first NVars elements of each row store values of the - independent variables - * last column store class number (in 0...NClasses-1) - or real value of the dependent variable - NPoints - number of rows in the dataset, NPoints>=1 - NVars - number of independent variables, NVars>=1 - NClasses - indicates type of the problem being solved: - * NClasses>=2 means that classification problem is - solved (last column of the dataset stores class - number) - * NClasses=1 means that regression problem is solved - (last column of the dataset stores variable value) - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dfbuildersetdataset( - decisionforestbuilder s, - real_2d_array xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function tells decision forest construction algorithm to skip -variable importance estimation. - -INPUT PARAMETERS: - S - decision forest builder object - -OUTPUT PARAMETERS: - S - decision forest builder object. Next call to the forest - construction function will result in forest being built - without variable importance estimation. - - -- ALGLIB -- - Copyright 29.07.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dfbuildersetimportancenone( - decisionforestbuilder s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function tells decision forest construction algorithm to use -out-of-bag version of Gini variable importance estimation (also known as -OOB-MDI). - -This version of importance estimation algorithm analyzes mean decrease in -impurity (MDI) on out-of-bag sample during splits. The result is divided -by impurity at the root node in order to produce estimate in [0,1] range. - -Such estimates are fast to calculate and resistant to overfitting issues -(thanks to the out-of-bag estimates used). However, OOB Gini rating has -following downsides: -* there exist some bias towards continuous and high-cardinality categorical - variables -* Gini rating allows us to order variables by importance, but it is hard - to define importance of the variable by itself. - -NOTE: informally speaking, MDA (permutation importance) rating answers the - question "what part of the model predictive power is ruined by - permuting k-th variable?" while MDI tells us "what part of the model - predictive power was achieved due to usage of k-th variable". - - Thus, MDA rates each variable independently at "0 to 1" scale while - MDI (and OOB-MDI too) tends to divide "unit amount of importance" - between several important variables. - - If all variables are equally important, they will have same - MDI/OOB-MDI rating, equal (for OOB-MDI: roughly equal) to 1/NVars. - However, roughly same picture will be produced for the "all - variables provide information no one is critical" situation and for - the "all variables are critical, drop any one, everything is ruined" - situation. - - Contrary to that, MDA will rate critical variable as ~1.0 important, - and important but non-critical variable will have less than unit - rating. - -NOTE: quite an often MDA and MDI return same results. It generally happens - on problems with low test set error (a few percents at most) and - large enough training set to avoid overfitting. - - The difference between MDA, MDI and OOB-MDI becomes important only - on "hard" tasks with high test set error and/or small training set. - -INPUT PARAMETERS: - S - decision forest builder object - -OUTPUT PARAMETERS: - S - decision forest builder object. Next call to the forest - construction function will produce: - * importance estimates in rep.varimportances field - * variable ranks in rep.topvars field - - -- ALGLIB -- - Copyright 29.07.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dfbuildersetimportanceoobgini( - decisionforestbuilder s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function tells decision forest construction algorithm to use -permutation variable importance estimator (also known as MDA). - -This version of importance estimation algorithm analyzes mean increase in -out-of-bag sum of squared residuals after random permutation of J-th -variable. The result is divided by error computed with all variables being -perturbed in order to produce R-squared-like estimate in [0,1] range. - -Such estimate is slower to calculate than Gini-based rating because it -needs multiple inference runs for each of variables being studied. - -ALGLIB uses parallelized and highly optimized algorithm which analyzes -path through the decision tree and allows to handle most perturbations -in O(1) time; nevertheless, requesting MDA importances may increase forest -construction time from 10% to 200% (or more, if you have thousands of -variables). - -However, MDA rating has following benefits over Gini-based ones: -* no bias towards specific variable types -* ability to directly evaluate "absolute" importance of some variable at - "0 to 1" scale (contrary to Gini-based rating, which returns comparative - importances). - -NOTE: informally speaking, MDA (permutation importance) rating answers the - question "what part of the model predictive power is ruined by - permuting k-th variable?" while MDI tells us "what part of the model - predictive power was achieved due to usage of k-th variable". - - Thus, MDA rates each variable independently at "0 to 1" scale while - MDI (and OOB-MDI too) tends to divide "unit amount of importance" - between several important variables. - - If all variables are equally important, they will have same - MDI/OOB-MDI rating, equal (for OOB-MDI: roughly equal) to 1/NVars. - However, roughly same picture will be produced for the "all - variables provide information no one is critical" situation and for - the "all variables are critical, drop any one, everything is ruined" - situation. - - Contrary to that, MDA will rate critical variable as ~1.0 important, - and important but non-critical variable will have less than unit - rating. - -NOTE: quite an often MDA and MDI return same results. It generally happens - on problems with low test set error (a few percents at most) and - large enough training set to avoid overfitting. - - The difference between MDA, MDI and OOB-MDI becomes important only - on "hard" tasks with high test set error and/or small training set. - -INPUT PARAMETERS: - S - decision forest builder object - -OUTPUT PARAMETERS: - S - decision forest builder object. Next call to the forest - construction function will produce: - * importance estimates in rep.varimportances field - * variable ranks in rep.topvars field - - -- ALGLIB -- - Copyright 29.07.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dfbuildersetimportancepermutation( - decisionforestbuilder s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function tells decision forest construction algorithm to use -Gini impurity based variable importance estimation (also known as MDI). - -This version of importance estimation algorithm analyzes mean decrease in -impurity (MDI) on training sample during splits. The result is divided -by impurity at the root node in order to produce estimate in [0,1] range. - -Such estimates are fast to calculate and beautifully normalized (sum to -one) but have following downsides: -* They ALWAYS sum to 1.0, even if output is completely unpredictable. I.e. - MDI allows to order variables by importance, but does not tell us about - "absolute" importances of variables -* there exist some bias towards continuous and high-cardinality categorical - variables - -NOTE: informally speaking, MDA (permutation importance) rating answers the - question "what part of the model predictive power is ruined by - permuting k-th variable?" while MDI tells us "what part of the model - predictive power was achieved due to usage of k-th variable". - - Thus, MDA rates each variable independently at "0 to 1" scale while - MDI (and OOB-MDI too) tends to divide "unit amount of importance" - between several important variables. - - If all variables are equally important, they will have same - MDI/OOB-MDI rating, equal (for OOB-MDI: roughly equal) to 1/NVars. - However, roughly same picture will be produced for the "all - variables provide information no one is critical" situation and for - the "all variables are critical, drop any one, everything is ruined" - situation. - - Contrary to that, MDA will rate critical variable as ~1.0 important, - and important but non-critical variable will have less than unit - rating. - -NOTE: quite an often MDA and MDI return same results. It generally happens - on problems with low test set error (a few percents at most) and - large enough training set to avoid overfitting. - - The difference between MDA, MDI and OOB-MDI becomes important only - on "hard" tasks with high test set error and/or small training set. - -INPUT PARAMETERS: - S - decision forest builder object - -OUTPUT PARAMETERS: - S - decision forest builder object. Next call to the forest - construction function will produce: - * importance estimates in rep.varimportances field - * variable ranks in rep.topvars field - - -- ALGLIB -- - Copyright 29.07.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dfbuildersetimportancetrngini( - decisionforestbuilder s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets random decision forest construction algorithm. - -As for now, only one decision forest construction algorithm is supported - -a dense "baseline" RDF algorithm. - -INPUT PARAMETERS: - S - decision forest builder object - AlgoType - algorithm type: - * 0 = baseline dense RDF - -OUTPUT PARAMETERS: - S - decision forest builder, see - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dfbuildersetrdfalgo( - decisionforestbuilder s, - ae_int_t algotype, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets split selection algorithm used by decision forest -classifier. You may choose several algorithms, with different speed and -quality of the results. - -INPUT PARAMETERS: - S - decision forest builder object - SplitStrength- split type: - * 0 = split at the random position, fastest one - * 1 = split at the middle of the range - * 2 = strong split at the best point of the range (default) - -OUTPUT PARAMETERS: - S - decision forest builder, see - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dfbuildersetrdfsplitstrength( - decisionforestbuilder s, - ae_int_t splitstrength, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function sets number of variables (in [1,NVars] range) used by -decision forest construction algorithm. - -The default option is to use roughly sqrt(NVars) variables. - -INPUT PARAMETERS: - S - decision forest builder object - RndVars - number of randomly selected variables; values outside - of [1,NVars] range are silently clipped. - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dfbuildersetrndvars( - decisionforestbuilder s, - ae_int_t rndvars, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function tells decision forest builder to automatically choose number -of variables used by decision forest construction algorithm. Roughly -sqrt(NVars) variables will be used. - -INPUT PARAMETERS: - S - decision forest builder object - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dfbuildersetrndvarsauto( - decisionforestbuilder s, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function sets number of variables used by decision forest construction -algorithm as a fraction of total variable count (0,1) range. - -The default option is to use roughly sqrt(NVars) variables. - -INPUT PARAMETERS: - S - decision forest builder object - F - round(NVars*F) variables are selected - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dfbuildersetrndvarsratio( - decisionforestbuilder s, - double f, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function sets seed used by internal RNG for random subsampling and -random selection of variable subsets. - -By default random seed is used, i.e. every time you build decision forest, -we seed generator with new value obtained from system-wide RNG. Thus, -decision forest builder returns non-deterministic results. You can change -such behavior by specyfing fixed positive seed value. - -INPUT PARAMETERS: - S - decision forest builder object - SeedVal - seed value: - * positive values are used for seeding RNG with fixed - seed, i.e. subsequent runs on same data will return - same decision forests - * non-positive seed means that random seed is used - for every run of builder, i.e. subsequent runs on - same datasets will return slightly different - decision forests - -OUTPUT PARAMETERS: - S - decision forest builder, see - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dfbuildersetseed( - decisionforestbuilder s, - ae_int_t seedval, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function sets size of dataset subsample generated the decision forest -construction algorithm. Size is specified as a fraction of total dataset -size. - -The default option is to use 50% of the dataset for training, 50% for the -OOB estimates. You can decrease fraction F down to 10%, 1% or even below -in order to reduce overfitting. - -INPUT PARAMETERS: - S - decision forest builder object - F - fraction of the dataset to use, in (0,1] range. Values - outside of this range will be silently clipped. At - least one element is always selected for the training - set. - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dfbuildersetsubsampleratio( - decisionforestbuilder s, - double f, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This subroutine builds random decision forest. - ---------- DEPRECATED VERSION! USE DECISION FOREST BUILDER OBJECT --------- - - -- ALGLIB -- - Copyright 19.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dfbuildrandomdecisionforest( - real_2d_array xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - ae_int_t ntrees, - double r, - ae_int_t& info, - decisionforest& df, - dfreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine builds random decision forest. - ---------- DEPRECATED VERSION! USE DECISION FOREST BUILDER OBJECT --------- - - -- ALGLIB -- - Copyright 19.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dfbuildrandomdecisionforestx1( - real_2d_array xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - ae_int_t ntrees, - ae_int_t nrndvars, - double r, - ae_int_t& info, - decisionforest& df, - dfreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function returns most probable class number for an input X. It is -same as calling dfprocess(model,x,y), then determining i=argmax(y[i]) and -returning i. - -A class number in [0,NOut) range in returned for classification problems, --1 is returned when this function is called for regression problems. - -IMPORTANT: this function is thread-unsafe and modifies internal structures - of the model! You can not use same model object for parallel - evaluation from several threads. - - Use dftsprocess() with independent thread-local buffers, if - you need thread-safe evaluation. - -INPUT PARAMETERS: - Model - decision forest model - X - input vector, array[0..NVars-1]. - -RESULT: - class number, -1 for regression tasks - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::dfclassify( - decisionforest model, - real_1d_array x, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function creates buffer structure which can be used to perform -parallel inference requests. - -DF subpackage provides two sets of computing functions - ones which use -internal buffer of DF model (these functions are single-threaded because -they use same buffer, which can not shared between threads), and ones -which use external buffer. - -This function is used to initialize external buffer. - -INPUT PARAMETERS - Model - DF model which is associated with newly created buffer - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: buffer object should be used only with model which was used to - initialize buffer. Any attempt to use buffer with different - object is dangerous - you may get integrity check failure - (exception) because sizes of internal arrays do not fit to - dimensions of the model structure. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dfcreatebuffer( - decisionforest model, - decisionforestbuffer& buf, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Inference using decision forest - -IMPORTANT: this function is thread-unsafe and may modify internal - structures of the model! You can not use same model object for - parallel evaluation from several threads. - - Use dftsprocess() with independent thread-local buffers if - you need thread-safe evaluation. - -INPUT PARAMETERS: - DF - decision forest model - X - input vector, array[NVars] - Y - possibly preallocated buffer, reallocated if too small - -OUTPUT PARAMETERS: - Y - result. Regression estimate when solving regression task, - vector of posterior probabilities for classification task. - -See also DFProcessI. - - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dfprocess( - decisionforest df, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function returns first component of the inferred vector (i.e. one -with index #0). - -It is a convenience wrapper for dfprocess() intended for either: -* 1-dimensional regression problems -* 2-class classification problems - -In the former case this function returns inference result as scalar, which -is definitely more convenient that wrapping it as vector. In the latter -case it returns probability of object belonging to class #0. - -If you call it for anything different from two cases above, it will work -as defined, i.e. return y[0], although it is of less use in such cases. - -IMPORTANT: this function is thread-unsafe and modifies internal structures - of the model! You can not use same model object for parallel - evaluation from several threads. - - Use dftsprocess() with independent thread-local buffers, if - you need thread-safe evaluation. - -INPUT PARAMETERS: - Model - DF model - X - input vector, array[0..NVars-1]. - -RESULT: - Y[0] - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
double alglib::dfprocess0( - decisionforest model, - real_1d_array x, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -'interactive' variant of DFProcess for languages like Python which support -constructs like "Y = DFProcessI(DF,X)" and interactive mode of interpreter - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - -IMPORTANT: this function is thread-unsafe and may modify internal - structures of the model! You can not use same model object for - parallel evaluation from several threads. - - Use dftsprocess() with independent thread-local buffers if - you need thread-safe evaluation. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dfprocessi( - decisionforest df, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Relative classification error on the test set - -INPUT PARAMETERS: - DF - decision forest model - XY - test set - NPoints - test set size - -RESULT: - percent of incorrectly classified cases. - Zero if model solves regression task. - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -
double alglib::dfrelclserror( - decisionforest df, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -RMS error on the test set - -INPUT PARAMETERS: - DF - decision forest model - XY - test set - NPoints - test set size - -RESULT: - root mean square error. - Its meaning for regression task is obvious. As for - classification task, RMS error means error when estimating posterior - probabilities. - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -
double alglib::dfrmserror( - decisionforest df, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -
void dfserialize(decisionforest &obj, std::string &s_out); -void dfserialize(decisionforest &obj, std::ostream &s_out); -
- -
-
/************************************************************************* -Inference using decision forest - -Thread-safe procesing using external buffer for temporaries. - -This function is thread-safe (i.e . you can use same DF model from -multiple threads) as long as you use different buffer objects for different -threads. - -INPUT PARAMETERS: - DF - decision forest model - Buf - buffer object, must be allocated specifically for this - model with dfcreatebuffer(). - X - input vector, array[NVars] - Y - possibly preallocated buffer, reallocated if too small - -OUTPUT PARAMETERS: - Y - result. Regression estimate when solving regression task, - vector of posterior probabilities for classification task. - -See also DFProcessI. - - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::dftsprocess( - decisionforest df, - decisionforestbuffer buf, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -
void dfunserialize(const std::string &s_in, decisionforest &obj); -void dfunserialize(const std::istream &s_in, decisionforest &obj); -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // The very simple classification example: classify points (x,y) in 2D space
-    // as ones with x>=0 and ones with x<0 (y is ignored, but our classifier
-    // has to find out it).
-    //
-    // First, we have to create decision forest builder object, load dataset and
-    // specify training settings. Our dataset is specified as matrix, which has
-    // following format:
-    //
-    //     x0 y0 class0
-    //     x1 y1 class1
-    //     x2 y2 class2
-    //     ....
-    //
-    // Here xi and yi can be any values (and in fact you can have any number of
-    // independent variables), and classi MUST be integer number in [0,NClasses)
-    // range. In our example we denote points with x>=0 as class #0, and
-    // ones with negative xi as class #1.
-    //
-    // NOTE: if you want to solve regression problem, specify NClasses=1. In
-    //       this case last column of xy can be any numeric value.
-    //
-    // For the sake of simplicity, our example includes only 4-point dataset.
-    // However, random forests are able to cope with extremely large datasets
-    // having millions of examples.
-    //
-    decisionforestbuilder builder;
-    ae_int_t nvars = 2;
-    ae_int_t nclasses = 2;
-    ae_int_t npoints = 4;
-    real_2d_array xy = "[[1,1,0],[1,-1,0],[-1,1,1],[-1,-1,1]]";
-
-    dfbuildercreate(builder);
-    dfbuildersetdataset(builder, xy, npoints, nvars, nclasses);
-
-    // in our example we train decision forest using full sample - it allows us
-    // to get zero classification error. However, in practical applications smaller
-    // values are used: 50%, 25%, 5% or even less.
-    dfbuildersetsubsampleratio(builder, 1.0);
-
-    // we train random forest with just one tree; again, in real life situations
-    // you typically need from 50 to 500 trees.
-    ae_int_t ntrees = 1;
-    decisionforest forest;
-    dfreport rep;
-    dfbuilderbuildrandomforest(builder, ntrees, forest, rep);
-
-    // with such settings (100% of the training set is used) you can expect
-    // zero classification error. Beautiful results, but remember - in real life
-    // you do not need zero TRAINING SET error, you need good generalization.
-
-    printf("%.4f\n", double(rep.relclserror)); // EXPECTED: 0.0000
-
-    // now, let's perform some simple processing with dfprocess()
-    real_1d_array x = "[+1,0]";
-    real_1d_array y = "[]";
-    dfprocess(forest, x, y);
-    printf("%s\n", y.tostring(3).c_str()); // EXPECTED: [+1,0]
-
-    // another option is to use dfprocess0() which returns just first component
-    // of the output vector y. ideal for regression problems and binary classifiers.
-    double y0;
-    y0 = dfprocess0(forest, x);
-    printf("%.3f\n", double(y0)); // EXPECTED: 1.000
-
-    // finally, you can use dfclassify() which returns most probable class index (i.e. argmax y[i]).
-    ae_int_t i;
-    i = dfclassify(forest, x);
-    printf("%d\n", int(i)); // EXPECTED: 0
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // The very simple regression example: model f(x,y)=x+y
-    //
-    // First, we have to create DF builder object, load dataset and specify
-    // training settings. Our dataset is specified as matrix, which has following
-    // format:
-    //
-    //     x0 y0 f0
-    //     x1 y1 f1
-    //     x2 y2 f2
-    //     ....
-    //
-    // Here xi and yi can be any values, and fi is a dependent function value.
-    //
-    // NOTE: you can also solve classification problems with DF models, see
-    //       another example for this unit.
-    //
-    decisionforestbuilder builder;
-    ae_int_t nvars = 2;
-    ae_int_t nclasses = 1;
-    ae_int_t npoints = 4;
-    real_2d_array xy = "[[1,1,+2],[1,-1,0],[-1,1,0],[-1,-1,-2]]";
-
-    dfbuildercreate(builder);
-    dfbuildersetdataset(builder, xy, npoints, nvars, nclasses);
-
-    // in our example we train decision forest using full sample - it allows us
-    // to get zero classification error. However, in practical applications smaller
-    // values are used: 50%, 25%, 5% or even less.
-    dfbuildersetsubsampleratio(builder, 1.0);
-
-    // we train random forest with just one tree; again, in real life situations
-    // you typically need from 50 to 500 trees.
-    ae_int_t ntrees = 1;
-    decisionforest model;
-    dfreport rep;
-    dfbuilderbuildrandomforest(builder, ntrees, model, rep);
-
-    // with such settings (full sample is used) you can expect zero RMS error on the
-    // training set. Beautiful results, but remember - in real life you do not
-    // need zero TRAINING SET error, you need good generalization.
-
-    printf("%.4f\n", double(rep.rmserror)); // EXPECTED: 0.0000
-
-    // now, let's perform some simple processing with dfprocess()
-    real_1d_array x = "[+1,+1]";
-    real_1d_array y = "[]";
-    dfprocess(model, x, y);
-    printf("%s\n", y.tostring(3).c_str()); // EXPECTED: [+2]
-
-    // another option is to use dfprocess0() which returns just first component
-    // of the output vector y. ideal for regression problems and binary classifiers.
-    double y0;
-    y0 = dfprocess0(model, x);
-    printf("%.3f\n", double(y0)); // EXPECTED: 2.000
-
-    // there also exist another convenience function, dfclassify(),
-    // but it does not work for regression problems - it always returns -1.
-    ae_int_t i;
-    i = dfclassify(model, x);
-    printf("%d\n", int(i)); // EXPECTED: -1
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* - -*************************************************************************/ -
class densesolverlsreport -{ - double r2; - real_2d_array cx; - ae_int_t n; - ae_int_t k; -}; - -
- -
-
/************************************************************************* - -*************************************************************************/ -
class densesolverreport -{ - double r1; - double rinf; -}; - -
- -
-
/************************************************************************* -Complex dense linear solver for A*x=b with complex N*N A given by its LU -decomposition and N*1 vectors x and b. This is "slow-but-robust" version -of the complex linear solver with additional features which add -significant performance overhead. Faster version is CMatrixLUSolveFast() -function. - -Algorithm features: -* automatic detection of degenerate cases -* O(N^2) complexity -* condition number estimation - -No iterative refinement is provided because exact form of original matrix -is not known to subroutine. Use CMatrixSolve or CMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in 10-15x performance penalty when compared - ! with "fast" version which just calls triangular solver. - ! - ! This performance penalty is insignificant when compared with - ! cost of large LU decomposition. However, if you call this - ! function many times for the same left side, this overhead - ! BECOMES significant. It also becomes significant for small- - ! scale problems. - ! - ! In such cases we strongly recommend you to use faster solver, - ! CMatrixLUSolveFast() function. - -INPUT PARAMETERS - LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU result - P - array[0..N-1], pivots array, CMatrixLU result - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixlusolve( - complex_2d_array lua, - integer_1d_array p, - ae_int_t n, - complex_1d_array b, - ae_int_t& info, - densesolverreport& rep, - complex_1d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Complex dense linear solver for A*x=b with N*N complex A given by its LU -decomposition and N*1 vectors x and b. This is fast lightweight version -of solver, which is significantly faster than CMatrixLUSolve(), but does -not provide additional information (like condition numbers). - -Algorithm features: -* O(N^2) complexity -* no additional time-consuming features, just triangular solver - -INPUT PARAMETERS - LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU result - P - array[0..N-1], pivots array, CMatrixLU result - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - -NOTE: unlike CMatrixLUSolve(), this function does NOT check for - near-degeneracy of input matrix. It checks for EXACT degeneracy, - because this check is easy to do. However, very badly conditioned - matrices may went unnoticed. - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixlusolvefast( - complex_2d_array lua, - integer_1d_array p, - ae_int_t n, - complex_1d_array& b, - ae_int_t& info, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver for A*X=B with N*N complex A given by its LU decomposition, -and N*M matrices X and B (multiple right sides). "Slow-but-feature-rich" -version of the solver. - -Algorithm features: -* automatic detection of degenerate cases -* O(M*N^2) complexity -* condition number estimation - -No iterative refinement is provided because exact form of original matrix -is not known to subroutine. Use CMatrixSolve or CMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just calls triangular - ! solver. - ! - ! This performance penalty is especially apparent when you use - ! ALGLIB parallel capabilities (condition number estimation is - ! inherently sequential). It also becomes significant for - ! small-scale problems. - ! - ! In such cases we strongly recommend you to use faster solver, - ! CMatrixLUSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixlusolvem( - complex_2d_array lua, - integer_1d_array p, - ae_int_t n, - complex_2d_array b, - ae_int_t m, - ae_int_t& info, - densesolverreport& rep, - complex_2d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver for A*X=B with N*N complex A given by its LU decomposition, -and N*M matrices X and B (multiple right sides). "Fast-but-lightweight" -version of the solver. - -Algorithm features: -* O(M*N^2) complexity -* no additional time-consuming features - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N,M]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixlusolvemfast( - complex_2d_array lua, - integer_1d_array p, - ae_int_t n, - complex_2d_array& b, - ae_int_t m, - ae_int_t& info, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver. Same as RMatrixMixedSolve(), but for complex matrices. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(N^2) complexity - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU result - P - array[0..N-1], pivots array, CMatrixLU result - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixmixedsolve( - complex_2d_array a, - complex_2d_array lua, - integer_1d_array p, - ae_int_t n, - complex_1d_array b, - ae_int_t& info, - densesolverreport& rep, - complex_1d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver. Same as RMatrixMixedSolveM(), but for complex matrices. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(M*N^2) complexity - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU result - P - array[0..N-1], pivots array, CMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixmixedsolvem( - complex_2d_array a, - complex_2d_array lua, - integer_1d_array p, - ae_int_t n, - complex_2d_array b, - ae_int_t m, - ae_int_t& info, - densesolverreport& rep, - complex_2d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Complex dense solver for A*x=B with N*N complex matrix A and N*1 complex -vectors x and b. "Slow-but-feature-rich" version of the solver. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(N^3) complexity - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system - ! and performs iterative refinement, which results in - ! significant performance penalty when compared with "fast" - ! version which just performs LU decomposition and calls - ! triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, CMatrixSolveFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixsolve( - complex_2d_array a, - ae_int_t n, - complex_1d_array b, - ae_int_t& info, - densesolverreport& rep, - complex_1d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Complex dense solver for A*x=B with N*N complex matrix A and N*1 complex -vectors x and b. "Fast-but-lightweight" version of the solver. - -Algorithm features: -* O(N^3) complexity -* no additional time consuming features, just triangular solver - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS: - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixsolvefast( - complex_2d_array a, - ae_int_t n, - complex_1d_array& b, - ae_int_t& info, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Complex dense solver for A*X=B with N*N complex matrix A, N*M complex -matrices X and B. "Slow-but-feature-rich" version which provides -additional functions, at the cost of slower performance. Faster version -may be invoked with CMatrixSolveMFast() function. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(N^3+M*N^2) complexity - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system - ! and performs iterative refinement, which results in - ! significant performance penalty when compared with "fast" - ! version which just performs LU decomposition and calls - ! triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, CMatrixSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - RFS - iterative refinement switch: - * True - refinement is used. - Less performance, more precision. - * False - refinement is not used. - More performance, less precision. - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixsolvem( - complex_2d_array a, - ae_int_t n, - complex_2d_array b, - ae_int_t m, - bool rfs, - ae_int_t& info, - densesolverreport& rep, - complex_2d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Complex dense solver for A*X=B with N*N complex matrix A, N*M complex -matrices X and B. "Fast-but-lightweight" version which provides just -triangular solver - and no additional functions like iterative refinement -or condition number estimation. - -Algorithm features: -* O(N^3+M*N^2) complexity -* no additional time consuming functions - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS: - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N,M]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 16.03.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixsolvemfast( - complex_2d_array a, - ae_int_t n, - complex_2d_array& b, - ae_int_t m, - ae_int_t& info, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver for A*x=b with N*N Hermitian positive definite matrix A given -by its Cholesky decomposition, and N*1 complex vectors x and b. This is -"slow-but-feature-rich" version of the solver which estimates condition -number of the system. - -Algorithm features: -* automatic detection of degenerate cases -* O(N^2) complexity -* condition number estimation -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in 10-15x performance penalty when compared - ! with "fast" version which just calls triangular solver. - ! - ! This performance penalty is insignificant when compared with - ! cost of large LU decomposition. However, if you call this - ! function many times for the same left side, this overhead - ! BECOMES significant. It also becomes significant for small- - ! scale problems (N<50). - ! - ! In such cases we strongly recommend you to use faster solver, - ! HPDMatrixCholeskySolveFast() function. - -INPUT PARAMETERS - CHA - array[0..N-1,0..N-1], Cholesky decomposition, - SPDMatrixCholesky result - N - size of A - IsUpper - what half of CHA is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or ill conditioned - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N]: - * for info>0 - solution - * for info=-3 - filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::hpdmatrixcholeskysolve( - complex_2d_array cha, - ae_int_t n, - bool isupper, - complex_1d_array b, - ae_int_t& info, - densesolverreport& rep, - complex_1d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver for A*x=b with N*N Hermitian positive definite matrix A given -by its Cholesky decomposition, and N*1 complex vectors x and b. This is -"fast-but-lightweight" version of the solver. - -Algorithm features: -* O(N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional time-consuming features - -INPUT PARAMETERS - CHA - array[0..N-1,0..N-1], Cholesky decomposition, - SPDMatrixCholesky result - N - size of A - IsUpper - what half of CHA is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or ill conditioned - B is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * for info>0 - overwritten by solution - * for info=-3 - filled by zeros - - -- ALGLIB -- - Copyright 18.03.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::hpdmatrixcholeskysolvefast( - complex_2d_array cha, - ae_int_t n, - bool isupper, - complex_1d_array& b, - ae_int_t& info, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver for A*X=B with N*N Hermitian positive definite matrix A given -by its Cholesky decomposition and N*M complex matrices X and B. This is -"slow-but-feature-rich" version of the solver which, in addition to the -solution, estimates condition number of the system. - -Algorithm features: -* automatic detection of degenerate cases -* O(M*N^2) complexity -* condition number estimation -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just calls triangular - ! solver. Amount of overhead introduced depends on M (the - ! larger - the more efficient). - ! - ! This performance penalty is insignificant when compared with - ! cost of large Cholesky decomposition. However, if you call - ! this function many times for the same left side, this - ! overhead BECOMES significant. It also becomes significant - ! for small-scale problems (N<50). - ! - ! In such cases we strongly recommend you to use faster solver, - ! HPDMatrixCholeskySolveMFast() function. - - -INPUT PARAMETERS - CHA - array[N,N], Cholesky decomposition, - HPDMatrixCholesky result - N - size of CHA - IsUpper - what half of CHA is provided - B - array[N,M], right part - M - right part size - -OUTPUT PARAMETERS: - Info - return code: - * -3 A is singular, or VERY close to singular. - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task was solved - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N]: - * for info>0 contains solution - * for info=-3 filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::hpdmatrixcholeskysolvem( - complex_2d_array cha, - ae_int_t n, - bool isupper, - complex_2d_array b, - ae_int_t m, - ae_int_t& info, - densesolverreport& rep, - complex_2d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver for A*X=B with N*N Hermitian positive definite matrix A given -by its Cholesky decomposition and N*M complex matrices X and B. This is -"fast-but-lightweight" version of the solver. - -Algorithm features: -* O(M*N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional time-consuming features - -INPUT PARAMETERS - CHA - array[N,N], Cholesky decomposition, - HPDMatrixCholesky result - N - size of CHA - IsUpper - what half of CHA is provided - B - array[N,M], right part - M - right part size - -OUTPUT PARAMETERS: - Info - return code: - * -3 A is singular, or VERY close to singular. - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task was solved - B - array[N]: - * for info>0 overwritten by solution - * for info=-3 filled by zeros - - -- ALGLIB -- - Copyright 18.03.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::hpdmatrixcholeskysolvemfast( - complex_2d_array cha, - ae_int_t n, - bool isupper, - complex_2d_array& b, - ae_int_t m, - ae_int_t& info, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver for A*x=b, with N*N Hermitian positive definite matrix A, and -N*1 complex vectors x and b. "Slow-but-feature-rich" version of the -solver. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* O(N^3) complexity -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just performs Cholesky - ! decomposition and calls triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, HPDMatrixSolveFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - same as in RMatrixSolve - Returns -3 for non-HPD matrices. - Rep - same as in RMatrixSolve - X - same as in RMatrixSolve - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::hpdmatrixsolve( - complex_2d_array a, - ae_int_t n, - bool isupper, - complex_1d_array b, - ae_int_t& info, - densesolverreport& rep, - complex_1d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver for A*x=b, with N*N Hermitian positive definite matrix A, and -N*1 complex vectors x and b. "Fast-but-lightweight" version of the -solver without additional functions. - -Algorithm features: -* O(N^3) complexity -* matrix is represented by its upper or lower triangle -* no additional time consuming functions - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or not positive definite - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task was solved - B - array[0..N-1]: - * overwritten by solution - * zeros, if A is exactly singular (diagonal of its LU - decomposition has exact zeros). - - -- ALGLIB -- - Copyright 17.03.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::hpdmatrixsolvefast( - complex_2d_array a, - ae_int_t n, - bool isupper, - complex_1d_array& b, - ae_int_t& info, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver for A*X=B, with N*N Hermitian positive definite matrix A and -N*M complex matrices X and B. "Slow-but-feature-rich" version of the -solver. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* O(N^3+M*N^2) complexity -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just calls triangular - ! solver. - ! - ! This performance penalty is especially apparent when you use - ! ALGLIB parallel capabilities (condition number estimation is - ! inherently sequential). It also becomes significant for - ! small-scale problems (N<100). - ! - ! In such cases we strongly recommend you to use faster solver, - ! HPDMatrixSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - same as in RMatrixSolve. - Returns -3 for non-HPD matrices. - Rep - same as in RMatrixSolve - X - same as in RMatrixSolve - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::hpdmatrixsolvem( - complex_2d_array a, - ae_int_t n, - bool isupper, - complex_2d_array b, - ae_int_t m, - ae_int_t& info, - densesolverreport& rep, - complex_2d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver for A*X=B, with N*N Hermitian positive definite matrix A and -N*M complex matrices X and B. "Fast-but-lightweight" version of the solver. - -Algorithm features: -* O(N^3+M*N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional time consuming features like condition number estimation - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or is not positive definite. - B is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - B - array[0..N-1]: - * overwritten by solution - * zeros, if problem was not solved - - -- ALGLIB -- - Copyright 17.03.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::hpdmatrixsolvemfast( - complex_2d_array a, - ae_int_t n, - bool isupper, - complex_2d_array& b, - ae_int_t m, - ae_int_t& info, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver. - -This subroutine solves a system A*x=b, where A is NxN non-denegerate -real matrix given by its LU decomposition, x and b are real vectors. This -is "slow-but-robust" version of the linear LU-based solver. Faster version -is RMatrixLUSolveFast() function. - -Algorithm features: -* automatic detection of degenerate cases -* O(N^2) complexity -* condition number estimation - -No iterative refinement is provided because exact form of original matrix -is not known to subroutine. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in 10-15x performance penalty when compared - ! with "fast" version which just calls triangular solver. - ! - ! This performance penalty is insignificant when compared with - ! cost of large LU decomposition. However, if you call this - ! function many times for the same left side, this overhead - ! BECOMES significant. It also becomes significant for small- - ! scale problems. - ! - ! In such cases we strongly recommend you to use faster solver, - ! RMatrixLUSolveFast() function. - -INPUT PARAMETERS - LUA - array[N,N], LU decomposition, RMatrixLU result - P - array[N], pivots array, RMatrixLU result - N - size of A - B - array[N], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixlusolve( - real_2d_array lua, - integer_1d_array p, - ae_int_t n, - real_1d_array b, - ae_int_t& info, - densesolverreport& rep, - real_1d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver. - -This subroutine solves a system A*x=b, where A is NxN non-denegerate -real matrix given by its LU decomposition, x and b are real vectors. This -is "fast-without-any-checks" version of the linear LU-based solver. Slower -but more robust version is RMatrixLUSolve() function. - -Algorithm features: -* O(N^2) complexity -* fast algorithm without ANY additional checks, just triangular solver - -INPUT PARAMETERS - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 18.03.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixlusolvefast( - real_2d_array lua, - integer_1d_array p, - ae_int_t n, - real_1d_array& b, - ae_int_t& info, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver. - -Similar to RMatrixLUSolve() but solves task with multiple right parts -(where b and x are NxM matrices). This is "robust-but-slow" version of -LU-based solver which performs additional checks for non-degeneracy of -inputs (condition number estimation). If you need best performance, use -"fast-without-any-checks" version, RMatrixLUSolveMFast(). - -Algorithm features: -* automatic detection of degenerate cases -* O(M*N^2) complexity -* condition number estimation - -No iterative refinement is provided because exact form of original matrix -is not known to subroutine. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just calls triangular - ! solver. - ! - ! This performance penalty is especially apparent when you use - ! ALGLIB parallel capabilities (condition number estimation is - ! inherently sequential). It also becomes significant for - ! small-scale problems. - ! - ! In such cases we strongly recommend you to use faster solver, - ! RMatrixLUSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - LUA - array[N,N], LU decomposition, RMatrixLU result - P - array[N], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixlusolvem( - real_2d_array lua, - integer_1d_array p, - ae_int_t n, - real_2d_array b, - ae_int_t m, - ae_int_t& info, - densesolverreport& rep, - real_2d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver. - -Similar to RMatrixLUSolve() but solves task with multiple right parts, -where b and x are NxM matrices. This is "fast-without-any-checks" version -of LU-based solver. It does not estimate condition number of a system, -so it is extremely fast. If you need better detection of near-degenerate -cases, use RMatrixLUSolveM() function. - -Algorithm features: -* O(M*N^2) complexity -* fast algorithm without ANY additional checks, just triangular solver - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS: - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N,M]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 18.03.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixlusolvemfast( - real_2d_array lua, - integer_1d_array p, - ae_int_t n, - real_2d_array& b, - ae_int_t m, - ae_int_t& info, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver. - -This subroutine solves a system A*x=b, where BOTH ORIGINAL A AND ITS -LU DECOMPOSITION ARE KNOWN. You can use it if for some reasons you have -both A and its LU decomposition. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(N^2) complexity - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixmixedsolve( - real_2d_array a, - real_2d_array lua, - integer_1d_array p, - ae_int_t n, - real_1d_array b, - ae_int_t& info, - densesolverreport& rep, - real_1d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver. - -Similar to RMatrixMixedSolve() but solves task with multiple right parts -(where b and x are NxM matrices). - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(M*N^2) complexity - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixmixedsolvem( - real_2d_array a, - real_2d_array lua, - integer_1d_array p, - ae_int_t n, - real_2d_array b, - ae_int_t m, - ae_int_t& info, - densesolverreport& rep, - real_2d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver for A*x=b with N*N real matrix A and N*1 real vectorx x and -b. This is "slow-but-feature rich" version of the linear solver. Faster -version is RMatrixSolveFast() function. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(N^3) complexity - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system - ! and performs iterative refinement, which results in - ! significant performance penalty when compared with "fast" - ! version which just performs LU decomposition and calls - ! triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. It is also very significant on small matrices. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, RMatrixSolveFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixsolve( - real_2d_array a, - ae_int_t n, - real_1d_array b, - ae_int_t& info, - densesolverreport& rep, - real_1d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver. - -This subroutine solves a system A*x=b, where A is NxN non-denegerate -real matrix, x and b are vectors. This is a "fast" version of linear -solver which does NOT provide any additional functions like condition -number estimation or iterative refinement. - -Algorithm features: -* efficient algorithm O(N^3) complexity -* no performance overhead from additional functionality - -If you need condition number estimation or iterative refinement, use more -feature-rich version - RMatrixSolve(). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 16.03.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixsolvefast( - real_2d_array a, - ae_int_t n, - real_1d_array& b, - ae_int_t& info, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver. - -This subroutine finds solution of the linear system A*X=B with non-square, -possibly degenerate A. System is solved in the least squares sense, and -general least squares solution X = X0 + CX*y which minimizes |A*X-B| is -returned. If A is non-degenerate, solution in the usual sense is returned. - -Algorithm features: -* automatic detection (and correct handling!) of degenerate cases -* iterative refinement -* O(N^3) complexity - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..NRows-1,0..NCols-1], system matrix - NRows - vertical size of A - NCols - horizontal size of A - B - array[0..NCols-1], right part - Threshold- a number in [0,1]. Singular values beyond Threshold are - considered zero. Set it to 0.0, if you don't understand - what it means, so the solver will choose good value on its - own. - -OUTPUT PARAMETERS - Info - return code: - * -4 SVD subroutine failed - * -1 if NRows<=0 or NCols<=0 or Threshold<0 was passed - * 1 if task is solved - Rep - solver report, see below for more info - X - array[0..N-1,0..M-1], it contains: - * solution of A*X=B (even for singular A) - * zeros, if SVD subroutine failed - -SOLVER REPORT - -Subroutine sets following fields of the Rep structure: -* R2 reciprocal of condition number: 1/cond(A), 2-norm. -* N = NCols -* K dim(Null(A)) -* CX array[0..N-1,0..K-1], kernel of A. - Columns of CX store such vectors that A*CX[i]=0. - - -- ALGLIB -- - Copyright 24.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixsolvels( - real_2d_array a, - ae_int_t nrows, - ae_int_t ncols, - real_1d_array b, - double threshold, - ae_int_t& info, - densesolverlsreport& rep, - real_1d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver. - -Similar to RMatrixSolve() but solves task with multiple right parts (where -b and x are NxM matrices). This is "slow-but-robust" version of linear -solver with additional functionality like condition number estimation. -There also exists faster version - RMatrixSolveMFast(). - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* optional iterative refinement -* O(N^3+M*N^2) complexity - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system - ! and performs iterative refinement, which results in - ! significant performance penalty when compared with "fast" - ! version which just performs LU decomposition and calls - ! triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. It also very significant on small matrices. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, RMatrixSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - RFS - iterative refinement switch: - * True - refinement is used. - Less performance, more precision. - * False - refinement is not used. - More performance, less precision. - -OUTPUT PARAMETERS - Info - return code: - * -3 A is ill conditioned or singular. - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixsolvem( - real_2d_array a, - ae_int_t n, - real_2d_array b, - ae_int_t m, - bool rfs, - ae_int_t& info, - densesolverreport& rep, - real_2d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver. - -Similar to RMatrixSolve() but solves task with multiple right parts (where -b and x are NxM matrices). This is "fast" version of linear solver which -does NOT offer additional functions like condition number estimation or -iterative refinement. - -Algorithm features: -* O(N^3+M*N^2) complexity -* no additional functionality, highest performance - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - RFS - iterative refinement switch: - * True - refinement is used. - Less performance, more precision. - * False - refinement is not used. - More performance, less precision. - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - B - array[N]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixsolvemfast( - real_2d_array a, - ae_int_t n, - real_2d_array& b, - ae_int_t m, - ae_int_t& info, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver for A*x=b with N*N symmetric positive definite matrix A given -by its Cholesky decomposition, and N*1 real vectors x and b. This is "slow- -but-feature-rich" version of the solver which, in addition to the -solution, performs condition number estimation. - -Algorithm features: -* automatic detection of degenerate cases -* O(N^2) complexity -* condition number estimation -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in 10-15x performance penalty when compared - ! with "fast" version which just calls triangular solver. - ! - ! This performance penalty is insignificant when compared with - ! cost of large LU decomposition. However, if you call this - ! function many times for the same left side, this overhead - ! BECOMES significant. It also becomes significant for small- - ! scale problems (N<50). - ! - ! In such cases we strongly recommend you to use faster solver, - ! SPDMatrixCholeskySolveFast() function. - -INPUT PARAMETERS - CHA - array[N,N], Cholesky decomposition, - SPDMatrixCholesky result - N - size of A - IsUpper - what half of CHA is provided - B - array[N], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or ill conditioned - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N]: - * for info>0 - solution - * for info=-3 - filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spdmatrixcholeskysolve( - real_2d_array cha, - ae_int_t n, - bool isupper, - real_1d_array b, - ae_int_t& info, - densesolverreport& rep, - real_1d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver for A*x=b with N*N symmetric positive definite matrix A given -by its Cholesky decomposition, and N*1 real vectors x and b. This is "fast- -but-lightweight" version of the solver. - -Algorithm features: -* O(N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional features - -INPUT PARAMETERS - CHA - array[N,N], Cholesky decomposition, - SPDMatrixCholesky result - N - size of A - IsUpper - what half of CHA is provided - B - array[N], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or ill conditioned - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * for info>0 - overwritten by solution - * for info=-3 - filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spdmatrixcholeskysolvefast( - real_2d_array cha, - ae_int_t n, - bool isupper, - real_1d_array& b, - ae_int_t& info, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver for A*X=B with N*N symmetric positive definite matrix A given -by its Cholesky decomposition, and N*M vectors X and B. It is "slow-but- -feature-rich" version of the solver which estimates condition number of -the system. - -Algorithm features: -* automatic detection of degenerate cases -* O(M*N^2) complexity -* condition number estimation -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just calls triangular - ! solver. Amount of overhead introduced depends on M (the - ! larger - the more efficient). - ! - ! This performance penalty is insignificant when compared with - ! cost of large LU decomposition. However, if you call this - ! function many times for the same left side, this overhead - ! BECOMES significant. It also becomes significant for small- - ! scale problems (N<50). - ! - ! In such cases we strongly recommend you to use faster solver, - ! SPDMatrixCholeskySolveMFast() function. - -INPUT PARAMETERS - CHA - array[0..N-1,0..N-1], Cholesky decomposition, - SPDMatrixCholesky result - N - size of CHA - IsUpper - what half of CHA is provided - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or badly conditioned - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task was solved - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N]: - * for info>0 contains solution - * for info=-3 filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spdmatrixcholeskysolvem( - real_2d_array cha, - ae_int_t n, - bool isupper, - real_2d_array b, - ae_int_t m, - ae_int_t& info, - densesolverreport& rep, - real_2d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver for A*X=B with N*N symmetric positive definite matrix A given -by its Cholesky decomposition, and N*M vectors X and B. It is "fast-but- -lightweight" version of the solver which just solves linear system, -without any additional functions. - -Algorithm features: -* O(M*N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional functionality - -INPUT PARAMETERS - CHA - array[N,N], Cholesky decomposition, - SPDMatrixCholesky result - N - size of CHA - IsUpper - what half of CHA is provided - B - array[N,M], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or badly conditioned - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task was solved - B - array[N]: - * for info>0 overwritten by solution - * for info=-3 filled by zeros - - -- ALGLIB -- - Copyright 18.03.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spdmatrixcholeskysolvemfast( - real_2d_array cha, - ae_int_t n, - bool isupper, - real_2d_array& b, - ae_int_t m, - ae_int_t& info, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense linear solver for A*x=b with N*N real symmetric positive definite -matrix A, N*1 vectors x and b. "Slow-but-feature-rich" version of the -solver. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* O(N^3) complexity -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just performs Cholesky - ! decomposition and calls triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, SPDMatrixSolveFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or non-SPD. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spdmatrixsolve( - real_2d_array a, - ae_int_t n, - bool isupper, - real_1d_array b, - ae_int_t& info, - densesolverreport& rep, - real_1d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense linear solver for A*x=b with N*N real symmetric positive definite -matrix A, N*1 vectors x and b. "Fast-but-lightweight" version of the -solver. - -Algorithm features: -* O(N^3) complexity -* matrix is represented by its upper or lower triangle -* no additional time consuming features like condition number estimation - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or non-SPD - * -1 N<=0 was passed - * 1 task was solved - B - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 17.03.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spdmatrixsolvefast( - real_2d_array a, - ae_int_t n, - bool isupper, - real_1d_array& b, - ae_int_t& info, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver for A*X=B with N*N symmetric positive definite matrix A, and -N*M vectors X and B. It is "slow-but-feature-rich" version of the solver. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* O(N^3+M*N^2) complexity -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just performs Cholesky - ! decomposition and calls triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, SPDMatrixSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or non-SPD. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spdmatrixsolvem( - real_2d_array a, - ae_int_t n, - bool isupper, - real_2d_array b, - ae_int_t m, - ae_int_t& info, - densesolverreport& rep, - real_2d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Dense solver for A*X=B with N*N symmetric positive definite matrix A, and -N*M vectors X and B. It is "fast-but-lightweight" version of the solver. - -Algorithm features: -* O(N^3+M*N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional time consuming features - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular - * -1 N<=0 was passed - * 1 task was solved - B - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 17.03.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spdmatrixsolvemfast( - real_2d_array a, - ae_int_t n, - bool isupper, - real_2d_array& b, - ae_int_t m, - ae_int_t& info, - const xparams _params = alglib::xdefault); - -
- -
- -sparsesolverreport
- -sparselusolve
-sparsesolve
-sparsespdcholeskysolve
-sparsespdsolve
-sparsespdsolvesks
- - - -
solvesks_d_1 Solving positive definite sparse system using Skyline (SKS) solver
- -
-
/************************************************************************* -This structure is a sparse solver report. - -Following fields can be accessed by users: -*************************************************************************/ -
class sparsesolverreport -{ - ae_int_t terminationtype; -}; - -
- -
-
/************************************************************************* -Sparse linear solver for A*x=b with general (nonsymmetric) N*N sparse real -matrix A given by its LU factorization, N*1 vectors x and b. - -IMPORTANT: this solver requires input matrix to be in the CRS sparse - storage format. An exception will be generated if you pass - matrix in some other format (HASH or SKS). - -INPUT PARAMETERS - A - LU factorization of the sparse matrix, must be NxN exactly - in CRS storage format - P, Q - pivot indexes from LU factorization - N - size of A, N>0 - B - array[0..N-1], right part - -OUTPUT PARAMETERS - X - array[N], it contains: - * rep.terminationtype>0 => solution - * rep.terminationtype=-3 => filled by zeros - Rep - solver report, following fields are set: - * rep.terminationtype - solver status; >0 for success, - set to -3 on failure (degenerate system). - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparselusolve( - sparsematrix a, - integer_1d_array p, - integer_1d_array q, - real_1d_array b, - real_1d_array& x, - sparsesolverreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Sparse linear solver for A*x=b with general (nonsymmetric) N*N sparse real -matrix A, N*1 vectors x and b. - -This solver converts input matrix to CRS format, performs LU factorization -and uses sparse triangular solvers to get solution of the original system. - -INPUT PARAMETERS - A - sparse matrix, must be NxN exactly, any storage format - N - size of A, N>0 - B - array[0..N-1], right part - -OUTPUT PARAMETERS - X - array[N], it contains: - * rep.terminationtype>0 => solution - * rep.terminationtype=-3 => filled by zeros - Rep - solver report, following fields are set: - * rep.terminationtype - solver status; >0 for success, - set to -3 on failure (degenerate system). - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsesolve( - sparsematrix a, - real_1d_array b, - real_1d_array& x, - sparsesolverreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Sparse linear solver for A*x=b with N*N real symmetric positive definite -matrix A given by its Cholesky decomposition, and N*1 vectors x and b. - -IMPORTANT: this solver requires input matrix to be in the SKS (Skyline) - or CRS (compressed row storage) format. An exception will be - generated if you pass matrix in some other format. - -INPUT PARAMETERS - A - sparse NxN matrix stored in CRs or SKS format, must be NxN - exactly - IsUpper - which half of A is provided (another half is ignored) - B - array[N], right part - -OUTPUT PARAMETERS - X - array[N], it contains: - * rep.terminationtype>0 => solution - * rep.terminationtype=-3 => filled by zeros - Rep - solver report, following fields are set: - * rep.terminationtype - solver status; >0 for success, - set to -3 on failure (degenerate or non-SPD system). - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsespdcholeskysolve( - sparsematrix a, - bool isupper, - real_1d_array b, - real_1d_array& x, - sparsesolverreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Sparse linear solver for A*x=b with N*N sparse real symmetric positive -definite matrix A, N*1 vectors x and b. - -This solver converts input matrix to CRS format, performs Cholesky -factorization using supernodal Cholesky decomposition with permutation- -reducing ordering and uses sparse triangular solver to get solution of the -original system. - -INPUT PARAMETERS - A - sparse matrix, must be NxN exactly - IsUpper - which half of A is provided (another half is ignored) - B - array[N], right part - -OUTPUT PARAMETERS - X - array[N], it contains: - * rep.terminationtype>0 => solution - * rep.terminationtype=-3 => filled by zeros - Rep - solver report, following fields are set: - * rep.terminationtype - solver status; >0 for success, - set to -3 on failure (degenerate or non-SPD system). - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsespdsolve( - sparsematrix a, - bool isupper, - real_1d_array b, - real_1d_array& x, - sparsesolverreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Sparse linear solver for A*x=b with N*N sparse real symmetric positive -definite matrix A, N*1 vectors x and b. - -This solver converts input matrix to SKS format, performs Cholesky -factorization using SKS Cholesky subroutine (works well for limited -bandwidth matrices) and uses sparse triangular solvers to get solution of -the original system. - -INPUT PARAMETERS - A - sparse matrix, must be NxN exactly - IsUpper - which half of A is provided (another half is ignored) - B - array[0..N-1], right part - -OUTPUT PARAMETERS - X - array[N], it contains: - * rep.terminationtype>0 => solution - * rep.terminationtype=-3 => filled by zeros - Rep - solver report, following fields are set: - * rep.terminationtype - solver status; >0 for success, - set to -3 on failure (degenerate or non-SPD system). - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsespdsolvesks( - sparsematrix a, - bool isupper, - real_1d_array b, - real_1d_array& x, - sparsesolverreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "solvers.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates creation/initialization of the sparse matrix
-    // in the SKS (Skyline) storage format and solution using SKS-based direct
-    // solver.
-    //
-    // First, we have to create matrix and initialize it. Matrix is created
-    // in the SKS format, using fixed bandwidth initialization function.
-    // Several points should be noted:
-    //
-    // 1. SKS sparse storage format also allows variable bandwidth matrices;
-    //    we just do not want to overcomplicate this example.
-    //
-    // 2. SKS format requires you to specify matrix geometry prior to
-    //    initialization of its elements with sparseset(). If you specified
-    //    bandwidth=1, you can not change your mind afterwards and call
-    //    sparseset() for non-existent elements.
-    // 
-    // 3. Because SKS solver need just one triangle of SPD matrix, we can
-    //    omit initialization of the lower triangle of our matrix.
-    //
-    ae_int_t n = 4;
-    ae_int_t bandwidth = 1;
-    sparsematrix s;
-    sparsecreatesksband(n, n, bandwidth, s);
-    sparseset(s, 0, 0, 2.0);
-    sparseset(s, 0, 1, 1.0);
-    sparseset(s, 1, 1, 3.0);
-    sparseset(s, 1, 2, 1.0);
-    sparseset(s, 2, 2, 3.0);
-    sparseset(s, 2, 3, 1.0);
-    sparseset(s, 3, 3, 2.0);
-
-    //
-    // Now we have symmetric positive definite 4x4 system width bandwidth=1:
-    //
-    //     [ 2 1     ]   [ x0]]   [  4 ]
-    //     [ 1 3 1   ]   [ x1 ]   [ 10 ]
-    //     [   1 3 1 ] * [ x2 ] = [ 15 ]
-    //     [     1 2 ]   [ x3 ]   [ 11 ]
-    //
-    // After successful creation we can call SKS solver.
-    //
-    real_1d_array b = "[4,10,15,11]";
-    sparsesolverreport rep;
-    real_1d_array x;
-    bool isuppertriangle = true;
-    sparsespdsolvesks(s, isuppertriangle, b, x, rep);
-    printf("%s\n", x.tostring(4).c_str()); // EXPECTED: [1.0000, 2.0000, 3.0000, 4.0000]
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* -Complete elliptic integral of the second kind - -Approximates the integral - - - pi/2 - - - | | 2 -E(m) = | sqrt( 1 - m sin t ) dt - | | - - - 0 - -using the approximation - - P(x) - x log x Q(x). - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0, 1 10000 2.1e-16 7.3e-17 - -Cephes Math Library, Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::ellipticintegrale( - double m, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Complete elliptic integral of the first kind - -Approximates the integral - - - - pi/2 - - - | | - | dt -K(m) = | ------------------ - | 2 - | | sqrt( 1 - m sin t ) - - - 0 - -using the approximation - - P(x) - log x Q(x). - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,1 30000 2.5e-16 6.8e-17 - -Cephes Math Library, Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::ellipticintegralk( - double m, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Complete elliptic integral of the first kind - -Approximates the integral - - - - pi/2 - - - | | - | dt -K(m) = | ------------------ - | 2 - | | sqrt( 1 - m sin t ) - - - 0 - -where m = 1 - m1, using the approximation - - P(x) - log x Q(x). - -The argument m1 is used rather than m so that the logarithmic -singularity at m = 1 will be shifted to the origin; this -preserves maximum accuracy. - -K(0) = pi/2. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,1 30000 2.5e-16 6.8e-17 - -Cephes Math Library, Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::ellipticintegralkhighprecision( - double m1, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Incomplete elliptic integral of the second kind - -Approximates the integral - - - phi - - - | | - | 2 -E(phi_\m) = | sqrt( 1 - m sin t ) dt - | - | | - - - 0 - -of amplitude phi and modulus m, using the arithmetic - -geometric mean algorithm. - -ACCURACY: - -Tested at random arguments with phi in [-10, 10] and m in -[0, 1]. - Relative error: -arithmetic domain # trials peak rms - IEEE -10,10 150000 3.3e-15 1.4e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1993, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::incompleteellipticintegrale( - double phi, - double m, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Incomplete elliptic integral of the first kind F(phi|m) - -Approximates the integral - - - - phi - - - | | - | dt -F(phi_\m) = | ------------------ - | 2 - | | sqrt( 1 - m sin t ) - - - 0 - -of amplitude phi and modulus m, using the arithmetic - -geometric mean algorithm. - - - - -ACCURACY: - -Tested at random points with m in [0, 1] and phi as indicated. - - Relative error: -arithmetic domain # trials peak rms - IEEE -10,10 200000 7.4e-16 1.0e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::incompleteellipticintegralk( - double phi, - double m, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -This object stores state of the subspace iteration algorithm. - -You should use ALGLIB functions to work with this object. -*************************************************************************/ -
class eigsubspacereport -{ - ae_int_t iterationscount; -}; - -
- -
-
/************************************************************************* -This object stores state of the subspace iteration algorithm. - -You should use ALGLIB functions to work with this object. -*************************************************************************/ -
class eigsubspacestate -{ -}; - -
- -
-
/************************************************************************* -This function initializes subspace iteration solver. This solver is used -to solve symmetric real eigenproblems where just a few (top K) eigenvalues -and corresponding eigenvectors is required. - -This solver can be significantly faster than complete EVD decomposition -in the following case: -* when only just a small fraction of top eigenpairs of dense matrix is - required. When K approaches N, this solver is slower than complete dense - EVD -* when problem matrix is sparse (and/or is not known explicitly, i.e. only - matrix-matrix product can be performed) - -USAGE (explicit dense/sparse matrix): -1. User initializes algorithm state with eigsubspacecreate() call -2. [optional] User tunes solver parameters by calling eigsubspacesetcond() - or other functions -3. User calls eigsubspacesolvedense() or eigsubspacesolvesparse() methods, - which take algorithm state and 2D array or alglib.sparsematrix object. - -USAGE (out-of-core mode): -1. User initializes algorithm state with eigsubspacecreate() call -2. [optional] User tunes solver parameters by calling eigsubspacesetcond() - or other functions -3. User activates out-of-core mode of the solver and repeatedly calls - communication functions in a loop like below: - > alglib.eigsubspaceoocstart(state) - > while alglib.eigsubspaceooccontinue(state) do - > alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) - > alglib.eigsubspaceoocgetrequestdata(state, out X) - > [calculate Y=A*X, with X=R^NxM] - > alglib.eigsubspaceoocsendresult(state, in Y) - > alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - N - problem dimensionality, N>0 - K - number of top eigenvector to calculate, 0<K<=N. - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: if you solve many similar EVD problems you may find it useful to - reuse previous subspace as warm-start point for new EVD problem. It - can be done with eigsubspacesetwarmstart() function. - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::eigsubspacecreate( - ae_int_t n, - ae_int_t k, - eigsubspacestate& state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Buffered version of constructor which aims to reuse previously allocated -memory as much as possible. - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::eigsubspacecreatebuf( - ae_int_t n, - ae_int_t k, - eigsubspacestate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function performs subspace iteration in the out-of-core mode. It -should be used in conjunction with other out-of-core-related functions of -this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -
bool alglib::eigsubspaceooccontinue( - eigsubspacestate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function is used to retrieve information about out-of-core request -sent by solver to user code: matrix X (array[N,RequestSize) which have to -be multiplied by out-of-core matrix A in a product A*X. - -This function returns just request data; in order to get size of the data -prior to processing requestm, use eigsubspaceoocgetrequestinfo(). - -It should be used in conjunction with other out-of-core-related functions -of this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - State - solver running in out-of-core mode - X - possibly preallocated storage; reallocated if - needed, left unchanged, if large enough to store - request data. - -OUTPUT PARAMETERS: - X - array[N,RequestSize] or larger, leading rectangle - is filled with dense matrix X. - - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::eigsubspaceoocgetrequestdata( - eigsubspacestate state, - real_2d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function is used to retrieve information about out-of-core request -sent by solver to user code: request type (current version of the solver -sends only requests for matrix-matrix products) and request size (size of -the matrices being multiplied). - -This function returns just request metrics; in order to get contents of -the matrices being multiplied, use eigsubspaceoocgetrequestdata(). - -It should be used in conjunction with other out-of-core-related functions -of this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - State - solver running in out-of-core mode - -OUTPUT PARAMETERS: - RequestType - type of the request to process: - * 0 - for matrix-matrix product A*X, with A being - NxN matrix whose eigenvalues/vectors are needed, - and X being NxREQUESTSIZE one which is returned - by the eigsubspaceoocgetrequestdata(). - RequestSize - size of the X matrix (number of columns), usually - it is several times larger than number of vectors - K requested by user. - - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::eigsubspaceoocgetrequestinfo( - eigsubspacestate state, - ae_int_t& requesttype, - ae_int_t& requestsize, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function is used to send user reply to out-of-core request sent by -solver. Usually it is product A*X for returned by solver matrix X. - -It should be used in conjunction with other out-of-core-related functions -of this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - State - solver running in out-of-core mode - AX - array[N,RequestSize] or larger, leading rectangle - is filled with product A*X. - - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::eigsubspaceoocsendresult( - eigsubspacestate state, - real_2d_array ax, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function initiates out-of-core mode of subspace eigensolver. It -should be used in conjunction with other out-of-core-related functions of -this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - State - solver object - MType - matrix type: - * 0 for real symmetric matrix (solver assumes that - matrix being processed is symmetric; symmetric - direct eigensolver is used for smaller subproblems - arising during solution of larger "full" task) - Future versions of ALGLIB may introduce support for - other matrix types; for now, only symmetric - eigenproblems are supported. - - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::eigsubspaceoocstart( - eigsubspacestate state, - ae_int_t mtype, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function finalizes out-of-core mode of subspace eigensolver. It -should be used in conjunction with other out-of-core-related functions of -this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - State - solver state - -OUTPUT PARAMETERS: - W - array[K], depending on solver settings: - * top K eigenvalues ordered by descending - if - eigenvectors are returned in Z - * zeros - if invariant subspace is returned in Z - Z - array[N,K], depending on solver settings either: - * matrix of eigenvectors found - * orthogonal basis of K-dimensional invariant subspace - Rep - report with additional parameters - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::eigsubspaceoocstop( - eigsubspacestate state, - real_1d_array& w, - real_2d_array& z, - eigsubspacereport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets stopping critera for the solver: -* error in eigenvector/value allowed by solver -* maximum number of iterations to perform - -INPUT PARAMETERS: - State - solver structure - Eps - eps>=0, with non-zero value used to tell solver that - it can stop after all eigenvalues converged with - error roughly proportional to eps*MAX(LAMBDA_MAX), - where LAMBDA_MAX is a maximum eigenvalue. - Zero value means that no check for precision is - performed. - MaxIts - maxits>=0, with non-zero value used to tell solver - that it can stop after maxits steps (no matter how - precise current estimate is) - -NOTE: passing eps=0 and maxits=0 results in automatic selection of - moderate eps as stopping criteria (1.0E-6 in current implementation, - but it may change without notice). - -NOTE: very small values of eps are possible (say, 1.0E-12), although the - larger problem you solve (N and/or K), the harder it is to find - precise eigenvectors because rounding errors tend to accumulate. - -NOTE: passing non-zero eps results in some performance penalty, roughly - equal to 2N*(2K)^2 FLOPs per iteration. These additional computations - are required in order to estimate current error in eigenvalues via - Rayleigh-Ritz process. - Most of this additional time is spent in construction of ~2Kx2K - symmetric subproblem whose eigenvalues are checked with exact - eigensolver. - This additional time is negligible if you search for eigenvalues of - the large dense matrix, but may become noticeable on highly sparse - EVD problems, where cost of matrix-matrix product is low. - If you set eps to exactly zero, Rayleigh-Ritz phase is completely - turned off. - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::eigsubspacesetcond( - eigsubspacestate state, - double eps, - ae_int_t maxits, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets warm-start mode of the solver: next call to the solver -will reuse previous subspace as warm-start point. It can significantly -speed-up convergence when you solve many similar eigenproblems. - -INPUT PARAMETERS: - State - solver structure - UseWarmStart- either True or False - - -- ALGLIB -- - Copyright 12.11.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::eigsubspacesetwarmstart( - eigsubspacestate state, - bool usewarmstart, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function runs eigensolver for dense NxN symmetric matrix A, given by -upper or lower triangle. - -This function can not process nonsymmetric matrices. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - State - solver state - A - array[N,N], symmetric NxN matrix given by one of its - triangles - IsUpper - whether upper or lower triangle of A is given (the - other one is not referenced at all). - -OUTPUT PARAMETERS: - W - array[K], top K eigenvalues ordered by descending - of their absolute values - Z - array[N,K], matrix of eigenvectors found - Rep - report with additional parameters - -NOTE: internally this function allocates a copy of NxN dense A. You should - take it into account when working with very large matrices occupying - almost all RAM. - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::eigsubspacesolvedenses( - eigsubspacestate state, - real_2d_array a, - bool isupper, - real_1d_array& w, - real_2d_array& z, - eigsubspacereport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function runs eigensolver for dense NxN symmetric matrix A, given by -upper or lower triangle. - -This function can not process nonsymmetric matrices. - -INPUT PARAMETERS: - State - solver state - A - NxN symmetric matrix given by one of its triangles - IsUpper - whether upper or lower triangle of A is given (the - other one is not referenced at all). - -OUTPUT PARAMETERS: - W - array[K], top K eigenvalues ordered by descending - of their absolute values - Z - array[N,K], matrix of eigenvectors found - Rep - report with additional parameters - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::eigsubspacesolvesparses( - eigsubspacestate state, - sparsematrix a, - bool isupper, - real_1d_array& w, - real_2d_array& z, - eigsubspacereport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Finding the eigenvalues and eigenvectors of a Hermitian matrix - -The algorithm finds eigen pairs of a Hermitian matrix by reducing it to -real tridiagonal form and using the QL/QR algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - Hermitian matrix which is given by its upper or lower - triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - storage format. - ZNeeded - flag controlling whether the eigenvectors are needed or - not. If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - -Output parameters: - D - eigenvalues in ascending order. - Array whose index ranges within [0..N-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains the eigenvectors. - Array whose indexes range within [0..N-1, 0..N-1]. - The eigenvectors are stored in the matrix columns. - -Result: - True, if the algorithm has converged. - False, if the algorithm hasn't converged (rare case). - -Note: - eigenvectors of Hermitian matrix are defined up to multiplication by - a complex number L, such that |L|=1. - - -- ALGLIB -- - Copyright 2005, 23 March 2007 by Bochkanov Sergey -*************************************************************************/ -
bool alglib::hmatrixevd( - complex_2d_array a, - ae_int_t n, - ae_int_t zneeded, - bool isupper, - real_1d_array& d, - complex_2d_array& z, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Subroutine for finding the eigenvalues and eigenvectors of a Hermitian -matrix with given indexes by using bisection and inverse iteration methods - -Input parameters: - A - Hermitian matrix which is given by its upper or lower - triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or - not. If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - IsUpperA - storage format of matrix A. - I1, I2 - index interval for searching (from I1 to I2). - 0 <= I1 <= I2 <= N-1. - -Output parameters: - W - array of the eigenvalues found. - Array whose index ranges within [0..I2-I1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains eigenvectors. - Array whose indexes range within [0..N-1, 0..I2-I1]. - In that case, the eigenvectors are stored in the matrix - columns. - -Result: - True, if successful. W contains the eigenvalues, Z contains the - eigenvectors (if needed). - - False, if the bisection method subroutine wasn't able to find the - eigenvalues in the given interval or if the inverse iteration - subroutine wasn't able to find all the corresponding eigenvectors. - In that case, the eigenvalues and eigenvectors are not returned. - -Note: - eigen vectors of Hermitian matrix are defined up to multiplication by - a complex number L, such as |L|=1. - - -- ALGLIB -- - Copyright 07.01.2006, 24.03.2007 by Bochkanov Sergey. -*************************************************************************/ -
bool alglib::hmatrixevdi( - complex_2d_array a, - ae_int_t n, - ae_int_t zneeded, - bool isupper, - ae_int_t i1, - ae_int_t i2, - real_1d_array& w, - complex_2d_array& z, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Subroutine for finding the eigenvalues (and eigenvectors) of a Hermitian -matrix in a given half-interval (A, B] by using a bisection and inverse -iteration - -Input parameters: - A - Hermitian matrix which is given by its upper or lower - triangular part. Array whose indexes range within - [0..N-1, 0..N-1]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or - not. If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - IsUpperA - storage format of matrix A. - B1, B2 - half-interval (B1, B2] to search eigenvalues in. - -Output parameters: - M - number of eigenvalues found in a given half-interval, M>=0 - W - array of the eigenvalues found. - Array whose index ranges within [0..M-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains eigenvectors. - Array whose indexes range within [0..N-1, 0..M-1]. - The eigenvectors are stored in the matrix columns. - -Result: - True, if successful. M contains the number of eigenvalues in the given - half-interval (could be equal to 0), W contains the eigenvalues, - Z contains the eigenvectors (if needed). - - False, if the bisection method subroutine wasn't able to find the - eigenvalues in the given interval or if the inverse iteration - subroutine wasn't able to find all the corresponding eigenvectors. - In that case, the eigenvalues and eigenvectors are not returned, M is - equal to 0. - -Note: - eigen vectors of Hermitian matrix are defined up to multiplication by - a complex number L, such as |L|=1. - - -- ALGLIB -- - Copyright 07.01.2006, 24.03.2007 by Bochkanov Sergey. -*************************************************************************/ -
bool alglib::hmatrixevdr( - complex_2d_array a, - ae_int_t n, - ae_int_t zneeded, - bool isupper, - double b1, - double b2, - ae_int_t& m, - real_1d_array& w, - complex_2d_array& z, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Finding eigenvalues and eigenvectors of a general (unsymmetric) matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -The algorithm finds eigenvalues and eigenvectors of a general matrix by -using the QR algorithm with multiple shifts. The algorithm can find -eigenvalues and both left and right eigenvectors. - -The right eigenvector is a vector x such that A*x = w*x, and the left -eigenvector is a vector y such that y'*A = w*y' (here y' implies a complex -conjugate transposition of vector y). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - VNeeded - flag controlling whether eigenvectors are needed or not. - If VNeeded is equal to: - * 0, eigenvectors are not returned; - * 1, right eigenvectors are returned; - * 2, left eigenvectors are returned; - * 3, both left and right eigenvectors are returned. - -Output parameters: - WR - real parts of eigenvalues. - Array whose index ranges within [0..N-1]. - WR - imaginary parts of eigenvalues. - Array whose index ranges within [0..N-1]. - VL, VR - arrays of left and right eigenvectors (if they are needed). - If WI[i]=0, the respective eigenvalue is a real number, - and it corresponds to the column number I of matrices VL/VR. - If WI[i]>0, we have a pair of complex conjugate numbers with - positive and negative imaginary parts: - the first eigenvalue WR[i] + sqrt(-1)*WI[i]; - the second eigenvalue WR[i+1] + sqrt(-1)*WI[i+1]; - WI[i]>0 - WI[i+1] = -WI[i] < 0 - In that case, the eigenvector corresponding to the first - eigenvalue is located in i and i+1 columns of matrices - VL/VR (the column number i contains the real part, and the - column number i+1 contains the imaginary part), and the vector - corresponding to the second eigenvalue is a complex conjugate to - the first vector. - Arrays whose indexes range within [0..N-1, 0..N-1]. - -Result: - True, if the algorithm has converged. - False, if the algorithm has not converged. - -Note 1: - Some users may ask the following question: what if WI[N-1]>0? - WI[N] must contain an eigenvalue which is complex conjugate to the - N-th eigenvalue, but the array has only size N? - The answer is as follows: such a situation cannot occur because the - algorithm finds a pairs of eigenvalues, therefore, if WI[i]>0, I is - strictly less than N-1. - -Note 2: - The algorithm performance depends on the value of the internal parameter - NS of the InternalSchurDecomposition subroutine which defines the number - of shifts in the QR algorithm (similarly to the block width in block-matrix - algorithms of linear algebra). If you require maximum performance - on your machine, it is recommended to adjust this parameter manually. - - -See also the InternalTREVC subroutine. - -The algorithm is based on the LAPACK 3.0 library. -*************************************************************************/ -
bool alglib::rmatrixevd( - real_2d_array a, - ae_int_t n, - ae_int_t vneeded, - real_1d_array& wr, - real_1d_array& wi, - real_2d_array& vl, - real_2d_array& vr, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Finding the eigenvalues and eigenvectors of a symmetric matrix - -The algorithm finds eigen pairs of a symmetric matrix by reducing it to -tridiagonal form and using the QL/QR algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - symmetric matrix which is given by its upper or lower - triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - IsUpper - storage format. - -Output parameters: - D - eigenvalues in ascending order. - Array whose index ranges within [0..N-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains the eigenvectors. - Array whose indexes range within [0..N-1, 0..N-1]. - The eigenvectors are stored in the matrix columns. - -Result: - True, if the algorithm has converged. - False, if the algorithm hasn't converged (rare case). - - -- ALGLIB -- - Copyright 2005-2008 by Bochkanov Sergey -*************************************************************************/ -
bool alglib::smatrixevd( - real_2d_array a, - ae_int_t n, - ae_int_t zneeded, - bool isupper, - real_1d_array& d, - real_2d_array& z, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Subroutine for finding the eigenvalues and eigenvectors of a symmetric -matrix with given indexes by using bisection and inverse iteration methods. - -Input parameters: - A - symmetric matrix which is given by its upper or lower - triangular part. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - IsUpperA - storage format of matrix A. - I1, I2 - index interval for searching (from I1 to I2). - 0 <= I1 <= I2 <= N-1. - -Output parameters: - W - array of the eigenvalues found. - Array whose index ranges within [0..I2-I1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains eigenvectors. - Array whose indexes range within [0..N-1, 0..I2-I1]. - In that case, the eigenvectors are stored in the matrix columns. - -Result: - True, if successful. W contains the eigenvalues, Z contains the - eigenvectors (if needed). - - False, if the bisection method subroutine wasn't able to find the - eigenvalues in the given interval or if the inverse iteration subroutine - wasn't able to find all the corresponding eigenvectors. - In that case, the eigenvalues and eigenvectors are not returned. - - -- ALGLIB -- - Copyright 07.01.2006 by Bochkanov Sergey -*************************************************************************/ -
bool alglib::smatrixevdi( - real_2d_array a, - ae_int_t n, - ae_int_t zneeded, - bool isupper, - ae_int_t i1, - ae_int_t i2, - real_1d_array& w, - real_2d_array& z, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Subroutine for finding the eigenvalues (and eigenvectors) of a symmetric -matrix in a given half open interval (A, B] by using a bisection and -inverse iteration - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - symmetric matrix which is given by its upper or lower - triangular part. Array [0..N-1, 0..N-1]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - IsUpperA - storage format of matrix A. - B1, B2 - half open interval (B1, B2] to search eigenvalues in. - -Output parameters: - M - number of eigenvalues found in a given half-interval (M>=0). - W - array of the eigenvalues found. - Array whose index ranges within [0..M-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains eigenvectors. - Array whose indexes range within [0..N-1, 0..M-1]. - The eigenvectors are stored in the matrix columns. - -Result: - True, if successful. M contains the number of eigenvalues in the given - half-interval (could be equal to 0), W contains the eigenvalues, - Z contains the eigenvectors (if needed). - - False, if the bisection method subroutine wasn't able to find the - eigenvalues in the given interval or if the inverse iteration subroutine - wasn't able to find all the corresponding eigenvectors. - In that case, the eigenvalues and eigenvectors are not returned, - M is equal to 0. - - -- ALGLIB -- - Copyright 07.01.2006 by Bochkanov Sergey -*************************************************************************/ -
bool alglib::smatrixevdr( - real_2d_array a, - ae_int_t n, - ae_int_t zneeded, - bool isupper, - double b1, - double b2, - ae_int_t& m, - real_1d_array& w, - real_2d_array& z, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Finding the eigenvalues and eigenvectors of a tridiagonal symmetric matrix - -The algorithm finds the eigen pairs of a tridiagonal symmetric matrix by -using an QL/QR algorithm with implicit shifts. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - D - the main diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-1]. - E - the secondary diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-2]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not needed; - * 1, the eigenvectors of a tridiagonal matrix - are multiplied by the square matrix Z. It is used if the - tridiagonal matrix is obtained by the similarity - transformation of a symmetric matrix; - * 2, the eigenvectors of a tridiagonal matrix replace the - square matrix Z; - * 3, matrix Z contains the first row of the eigenvectors - matrix. - Z - if ZNeeded=1, Z contains the square matrix by which the - eigenvectors are multiplied. - Array whose indexes range within [0..N-1, 0..N-1]. - -Output parameters: - D - eigenvalues in ascending order. - Array whose index ranges within [0..N-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains the product of a given matrix (from the left) - and the eigenvectors matrix (from the right); - * 2, Z contains the eigenvectors. - * 3, Z contains the first row of the eigenvectors matrix. - If ZNeeded<3, Z is the array whose indexes range within [0..N-1, 0..N-1]. - In that case, the eigenvectors are stored in the matrix columns. - If ZNeeded=3, Z is the array whose indexes range within [0..0, 0..N-1]. - -Result: - True, if the algorithm has converged. - False, if the algorithm hasn't converged. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994 -*************************************************************************/ -
bool alglib::smatrixtdevd( - real_1d_array& d, - real_1d_array e, - ae_int_t n, - ae_int_t zneeded, - real_2d_array& z, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Subroutine for finding tridiagonal matrix eigenvalues/vectors with given -indexes (in ascending order) by using the bisection and inverse iteraion. - -Input parameters: - D - the main diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-1]. - E - the secondary diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-2]. - N - size of matrix. N>=0. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not needed; - * 1, the eigenvectors of a tridiagonal matrix are multiplied - by the square matrix Z. It is used if the - tridiagonal matrix is obtained by the similarity transformation - of a symmetric matrix. - * 2, the eigenvectors of a tridiagonal matrix replace - matrix Z. - I1, I2 - index interval for searching (from I1 to I2). - 0 <= I1 <= I2 <= N-1. - Z - if ZNeeded is equal to: - * 0, Z isn't used and remains unchanged; - * 1, Z contains the square matrix (array whose indexes range within [0..N-1, 0..N-1]) - which reduces the given symmetric matrix to tridiagonal form; - * 2, Z isn't used (but changed on the exit). - -Output parameters: - D - array of the eigenvalues found. - Array whose index ranges within [0..I2-I1]. - Z - if ZNeeded is equal to: - * 0, doesn't contain any information; - * 1, contains the product of a given NxN matrix Z (from the left) and - Nx(I2-I1) matrix of the eigenvectors found (from the right). - Array whose indexes range within [0..N-1, 0..I2-I1]. - * 2, contains the matrix of the eigenvalues found. - Array whose indexes range within [0..N-1, 0..I2-I1]. - - -Result: - - True, if successful. In that case, D contains the eigenvalues, - Z contains the eigenvectors (if needed). - It should be noted that the subroutine changes the size of arrays D and Z. - - False, if the bisection method subroutine wasn't able to find the eigenvalues - in the given interval or if the inverse iteration subroutine wasn't able - to find all the corresponding eigenvectors. In that case, the eigenvalues - and eigenvectors are not returned. - - -- ALGLIB -- - Copyright 25.12.2005 by Bochkanov Sergey -*************************************************************************/ -
bool alglib::smatrixtdevdi( - real_1d_array& d, - real_1d_array e, - ae_int_t n, - ae_int_t zneeded, - ae_int_t i1, - ae_int_t i2, - real_2d_array& z, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Subroutine for finding the tridiagonal matrix eigenvalues/vectors in a -given half-interval (A, B] by using bisection and inverse iteration. - -Input parameters: - D - the main diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-1]. - E - the secondary diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-2]. - N - size of matrix, N>=0. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not needed; - * 1, the eigenvectors of a tridiagonal matrix are multiplied - by the square matrix Z. It is used if the tridiagonal - matrix is obtained by the similarity transformation - of a symmetric matrix. - * 2, the eigenvectors of a tridiagonal matrix replace matrix Z. - A, B - half-interval (A, B] to search eigenvalues in. - Z - if ZNeeded is equal to: - * 0, Z isn't used and remains unchanged; - * 1, Z contains the square matrix (array whose indexes range - within [0..N-1, 0..N-1]) which reduces the given symmetric - matrix to tridiagonal form; - * 2, Z isn't used (but changed on the exit). - -Output parameters: - D - array of the eigenvalues found. - Array whose index ranges within [0..M-1]. - M - number of eigenvalues found in the given half-interval (M>=0). - Z - if ZNeeded is equal to: - * 0, doesn't contain any information; - * 1, contains the product of a given NxN matrix Z (from the - left) and NxM matrix of the eigenvectors found (from the - right). Array whose indexes range within [0..N-1, 0..M-1]. - * 2, contains the matrix of the eigenvectors found. - Array whose indexes range within [0..N-1, 0..M-1]. - -Result: - - True, if successful. In that case, M contains the number of eigenvalues - in the given half-interval (could be equal to 0), D contains the eigenvalues, - Z contains the eigenvectors (if needed). - It should be noted that the subroutine changes the size of arrays D and Z. - - False, if the bisection method subroutine wasn't able to find the - eigenvalues in the given interval or if the inverse iteration subroutine - wasn't able to find all the corresponding eigenvectors. In that case, - the eigenvalues and eigenvectors are not returned, M is equal to 0. - - -- ALGLIB -- - Copyright 31.03.2008 by Bochkanov Sergey -*************************************************************************/ -
bool alglib::smatrixtdevdr( - real_1d_array& d, - real_1d_array e, - ae_int_t n, - ae_int_t zneeded, - double a, - double b, - ae_int_t& m, - real_2d_array& z, - const xparams _params = alglib::xdefault); - -
- -
- -exponentialintegralei
-exponentialintegralen
- - -
- -
-
/************************************************************************* -Exponential integral Ei(x) - - x - - t - | | e - Ei(x) = -|- --- dt . - | | t - - - -inf - -Not defined for x <= 0. -See also expn.c. - - - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,100 50000 8.6e-16 1.3e-16 - -Cephes Math Library Release 2.8: May, 1999 -Copyright 1999 by Stephen L. Moshier -*************************************************************************/ -
double alglib::exponentialintegralei( - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Exponential integral En(x) - -Evaluates the exponential integral - - inf. - - - | | -xt - | e - E (x) = | ---- dt. - n | n - | | t - - - 1 - - -Both n and x must be nonnegative. - -The routine employs either a power series, a continued -fraction, or an asymptotic formula depending on the -relative values of n and x. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0, 30 10000 1.7e-15 3.6e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1985, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::exponentialintegralen( - double x, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
- -fcdistribution
-fdistribution
-invfdistribution
- - -
- -
-
/************************************************************************* -Complemented F distribution - -Returns the area from x to infinity under the F density -function (also known as Snedcor's density or the -variance ratio density). - - - inf. - - - 1 | | a-1 b-1 -1-P(x) = ------ | t (1-t) dt - B(a,b) | | - - - x - - -The incomplete beta integral is used, according to the -formula - -P(x) = incbet( df2/2, df1/2, (df2/(df2 + df1*x) ). - - -ACCURACY: - -Tested at random points (a,b,x) in the indicated intervals. - x a,b Relative error: -arithmetic domain domain # trials peak rms - IEEE 0,1 1,100 100000 3.7e-14 5.9e-16 - IEEE 1,5 1,100 100000 8.0e-15 1.6e-15 - IEEE 0,1 1,10000 100000 1.8e-11 3.5e-13 - IEEE 1,5 1,10000 100000 2.0e-11 3.0e-12 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::fcdistribution( - ae_int_t a, - ae_int_t b, - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -F distribution - -Returns the area from zero to x under the F density -function (also known as Snedcor's density or the -variance ratio density). This is the density -of x = (u1/df1)/(u2/df2), where u1 and u2 are random -variables having Chi square distributions with df1 -and df2 degrees of freedom, respectively. -The incomplete beta integral is used, according to the -formula - -P(x) = incbet( df1/2, df2/2, (df1*x/(df2 + df1*x) ). - - -The arguments a and b are greater than zero, and x is -nonnegative. - -ACCURACY: - -Tested at random points (a,b,x). - - x a,b Relative error: -arithmetic domain domain # trials peak rms - IEEE 0,1 0,100 100000 9.8e-15 1.7e-15 - IEEE 1,5 0,100 100000 6.5e-15 3.5e-16 - IEEE 0,1 1,10000 100000 2.2e-11 3.3e-12 - IEEE 1,5 1,10000 100000 1.1e-11 1.7e-13 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::fdistribution( - ae_int_t a, - ae_int_t b, - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Inverse of complemented F distribution - -Finds the F density argument x such that the integral -from x to infinity of the F density is equal to the -given probability p. - -This is accomplished using the inverse beta integral -function and the relations - - z = incbi( df2/2, df1/2, p ) - x = df2 (1-z) / (df1 z). - -Note: the following relations hold for the inverse of -the uncomplemented F distribution: - - z = incbi( df1/2, df2/2, p ) - x = df2 z / (df1 (1-z)). - -ACCURACY: - -Tested at random points (a,b,p). - - a,b Relative error: -arithmetic domain # trials peak rms - For p between .001 and 1: - IEEE 1,100 100000 8.3e-15 4.7e-16 - IEEE 1,10000 100000 2.1e-11 1.4e-13 - For p between 10^-6 and 10^-3: - IEEE 1,100 50000 1.3e-12 8.4e-15 - IEEE 1,10000 50000 3.0e-12 4.8e-14 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::invfdistribution( - ae_int_t a, - ae_int_t b, - double y, - const xparams _params = alglib::xdefault); - -
- -
- -fftc1d
-fftc1dinv
-fftr1d
-fftr1dinv
- - - - - - -
fft_complex_d1 Complex FFT: simple example
fft_complex_d2 Complex FFT: advanced example
fft_real_d1 Real FFT: simple example
fft_real_d2 Real FFT: advanced example
- -
-
/************************************************************************* -1-dimensional complex FFT. - -Array size N may be arbitrary number (composite or prime). Composite N's -are handled with cache-oblivious variation of a Cooley-Tukey algorithm. -Small prime-factors are transformed using hard coded codelets (similar to -FFTW codelets, but without low-level optimization), large prime-factors -are handled with Bluestein's algorithm. - -Fastests transforms are for smooth N's (prime factors are 2, 3, 5 only), -most fast for powers of 2. When N have prime factors larger than these, -but orders of magnitude smaller than N, computations will be about 4 times -slower than for nearby highly composite N's. When N itself is prime, speed -will be 6 times lower. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - A - array[0..N-1] - complex function to be transformed - N - problem size - -OUTPUT PARAMETERS - A - DFT of a input array, array[0..N-1] - A_out[j] = SUM(A_in[k]*exp(-2*pi*sqrt(-1)*j*k/N), k = 0..N-1) - - - -- ALGLIB -- - Copyright 29.05.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::fftc1d( - complex_1d_array& a, - const xparams _params = alglib::xdefault); -void alglib::fftc1d( - complex_1d_array& a, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -1-dimensional complex inverse FFT. - -Array size N may be arbitrary number (composite or prime). Algorithm has -O(N*logN) complexity for any N (composite or prime). - -See FFTC1D() description for more information about algorithm performance. - -INPUT PARAMETERS - A - array[0..N-1] - complex array to be transformed - N - problem size - -OUTPUT PARAMETERS - A - inverse DFT of a input array, array[0..N-1] - A_out[j] = SUM(A_in[k]/N*exp(+2*pi*sqrt(-1)*j*k/N), k = 0..N-1) - - - -- ALGLIB -- - Copyright 29.05.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::fftc1dinv( - complex_1d_array& a, - const xparams _params = alglib::xdefault); -void alglib::fftc1dinv( - complex_1d_array& a, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -1-dimensional real FFT. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - A - array[0..N-1] - real function to be transformed - N - problem size - -OUTPUT PARAMETERS - F - DFT of a input array, array[0..N-1] - F[j] = SUM(A[k]*exp(-2*pi*sqrt(-1)*j*k/N), k = 0..N-1) - -NOTE: - F[] satisfies symmetry property F[k] = conj(F[N-k]), so just one half -of array is usually needed. But for convinience subroutine returns full -complex array (with frequencies above N/2), so its result may be used by -other FFT-related subroutines. - - - -- ALGLIB -- - Copyright 01.06.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::fftr1d( - real_1d_array a, - complex_1d_array& f, - const xparams _params = alglib::xdefault); -void alglib::fftr1d( - real_1d_array a, - ae_int_t n, - complex_1d_array& f, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -1-dimensional real inverse FFT. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - F - array[0..floor(N/2)] - frequencies from forward real FFT - N - problem size - -OUTPUT PARAMETERS - A - inverse DFT of a input array, array[0..N-1] - -NOTE: - F[] should satisfy symmetry property F[k] = conj(F[N-k]), so just one -half of frequencies array is needed - elements from 0 to floor(N/2). F[0] -is ALWAYS real. If N is even F[floor(N/2)] is real too. If N is odd, then -F[floor(N/2)] has no special properties. - -Relying on properties noted above, FFTR1DInv subroutine uses only elements -from 0th to floor(N/2)-th. It ignores imaginary part of F[0], and in case -N is even it ignores imaginary part of F[floor(N/2)] too. - -When you call this function using full arguments list - "FFTR1DInv(F,N,A)" -- you can pass either either frequencies array with N elements or reduced -array with roughly N/2 elements - subroutine will successfully transform -both. - -If you call this function using reduced arguments list - "FFTR1DInv(F,A)" -- you must pass FULL array with N elements (although higher N/2 are still -not used) because array size is used to automatically determine FFT length - - - -- ALGLIB -- - Copyright 01.06.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::fftr1dinv( - complex_1d_array f, - real_1d_array& a, - const xparams _params = alglib::xdefault); -void alglib::fftr1dinv( - complex_1d_array f, - ae_int_t n, - real_1d_array& a, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "fasttransforms.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // first we demonstrate forward FFT:
-    // [1i,1i,1i,1i] is converted to [4i, 0, 0, 0]
-    //
-    complex_1d_array z = "[1i,1i,1i,1i]";
-    fftc1d(z);
-    printf("%s\n", z.tostring(3).c_str()); // EXPECTED: [4i,0,0,0]
-
-    //
-    // now we convert [4i, 0, 0, 0] back to [1i,1i,1i,1i]
-    // with backward FFT
-    //
-    fftc1dinv(z);
-    printf("%s\n", z.tostring(3).c_str()); // EXPECTED: [1i,1i,1i,1i]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "fasttransforms.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // first we demonstrate forward FFT:
-    // [0,1,0,1i] is converted to [1+1i, -1-1i, -1-1i, 1+1i]
-    //
-    complex_1d_array z = "[0,1,0,1i]";
-    fftc1d(z);
-    printf("%s\n", z.tostring(3).c_str()); // EXPECTED: [1+1i, -1-1i, -1-1i, 1+1i]
-
-    //
-    // now we convert result back with backward FFT
-    //
-    fftc1dinv(z);
-    printf("%s\n", z.tostring(3).c_str()); // EXPECTED: [0,1,0,1i]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "fasttransforms.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // first we demonstrate forward FFT:
-    // [1,1,1,1] is converted to [4, 0, 0, 0]
-    //
-    real_1d_array x = "[1,1,1,1]";
-    complex_1d_array f;
-    real_1d_array x2;
-    fftr1d(x, f);
-    printf("%s\n", f.tostring(3).c_str()); // EXPECTED: [4,0,0,0]
-
-    //
-    // now we convert [4, 0, 0, 0] back to [1,1,1,1]
-    // with backward FFT
-    //
-    fftr1dinv(f, x2);
-    printf("%s\n", x2.tostring(3).c_str()); // EXPECTED: [1,1,1,1]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "fasttransforms.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // first we demonstrate forward FFT:
-    // [1,2,3,4] is converted to [10, -2+2i, -2, -2-2i]
-    //
-    // note that output array is self-adjoint:
-    // * f[0] = conj(f[0])
-    // * f[1] = conj(f[3])
-    // * f[2] = conj(f[2])
-    //
-    real_1d_array x = "[1,2,3,4]";
-    complex_1d_array f;
-    real_1d_array x2;
-    fftr1d(x, f);
-    printf("%s\n", f.tostring(3).c_str()); // EXPECTED: [10, -2+2i, -2, -2-2i]
-
-    //
-    // now we convert [10, -2+2i, -2, -2-2i] back to [1,2,3,4]
-    //
-    fftr1dinv(f, x2);
-    printf("%s\n", x2.tostring(3).c_str()); // EXPECTED: [1,2,3,4]
-
-    //
-    // remember that F is self-adjoint? It means that we can pass just half
-    // (slightly larger than half) of F to inverse real FFT and still get our result.
-    //
-    // I.e. instead [10, -2+2i, -2, -2-2i] we pass just [10, -2+2i, -2] and everything works!
-    //
-    // NOTE: in this case we should explicitly pass array length (which is 4) to ALGLIB;
-    // if not, it will automatically use array length to determine FFT size and
-    // will erroneously make half-length FFT.
-    //
-    f = "[10, -2+2i, -2]";
-    fftr1dinv(f, 4, x2);
-    printf("%s\n", x2.tostring(3).c_str()); // EXPECTED: [1,2,3,4]
-    return 0;
-}
-
-
-
-
- -fhtr1d
-fhtr1dinv
- - -
- -
-
/************************************************************************* -1-dimensional Fast Hartley Transform. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - A - array[0..N-1] - real function to be transformed - N - problem size - -OUTPUT PARAMETERS - A - FHT of a input array, array[0..N-1], - A_out[k] = sum(A_in[j]*(cos(2*pi*j*k/N)+sin(2*pi*j*k/N)), j=0..N-1) - - - -- ALGLIB -- - Copyright 04.06.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::fhtr1d( - real_1d_array& a, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -1-dimensional inverse FHT. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - A - array[0..N-1] - complex array to be transformed - N - problem size - -OUTPUT PARAMETERS - A - inverse FHT of a input array, array[0..N-1] - - - -- ALGLIB -- - Copyright 29.05.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::fhtr1dinv( - real_1d_array& a, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
- -filterema
-filterlrma
-filtersma
- - - - - -
filters_d_ema EMA(alpha) filter
filters_d_lrma LRMA(k) filter
filters_d_sma SMA(k) filter
- -
-
/************************************************************************* -Filters: exponential moving averages. - -This filter replaces array by results of EMA(alpha) filter. EMA(alpha) is -defined as filter which replaces X[] by S[]: - S[0] = X[0] - S[t] = alpha*X[t] + (1-alpha)*S[t-1] - -INPUT PARAMETERS: - X - array[N], array to process. It can be larger than N, - in this case only first N points are processed. - N - points count, N>=0 - alpha - 0<alpha<=1, smoothing parameter. - -OUTPUT PARAMETERS: - X - array, whose first N elements were processed - with EMA(alpha) - -NOTE 1: this function uses efficient in-place algorithm which does not - allocate temporary arrays. - -NOTE 2: this algorithm uses BOTH previous points and current one, i.e. - new value of X[i] depends on BOTH previous point and X[i] itself. - -NOTE 3: technical analytis users quite often work with EMA coefficient - expressed in DAYS instead of fractions. If you want to calculate - EMA(N), where N is a number of days, you can use alpha=2/(N+1). - - -- ALGLIB -- - Copyright 25.10.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::filterema( - real_1d_array& x, - double alpha, - const xparams _params = alglib::xdefault); -void alglib::filterema( - real_1d_array& x, - ae_int_t n, - double alpha, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Filters: linear regression moving averages. - -This filter replaces array by results of LRMA(K) filter. - -LRMA(K) is defined as filter which, for each data point, builds linear -regression model using K prevous points (point itself is included in -these K points) and calculates value of this linear model at the point in -question. - -INPUT PARAMETERS: - X - array[N], array to process. It can be larger than N, - in this case only first N points are processed. - N - points count, N>=0 - K - K>=1 (K can be larger than N , such cases will be - correctly handled). Window width. K=1 corresponds to - identity transformation (nothing changes). - -OUTPUT PARAMETERS: - X - array, whose first N elements were processed with SMA(K) - -NOTE 1: this function uses efficient in-place algorithm which does not - allocate temporary arrays. - -NOTE 2: this algorithm makes only one pass through array and uses running - sum to speed-up calculation of the averages. Additional measures - are taken to ensure that running sum on a long sequence of zero - elements will be correctly reset to zero even in the presence of - round-off error. - -NOTE 3: this is unsymmetric version of the algorithm, which does NOT - averages points after the current one. Only X[i], X[i-1], ... are - used when calculating new value of X[i]. We should also note that - this algorithm uses BOTH previous points and current one, i.e. - new value of X[i] depends on BOTH previous point and X[i] itself. - - -- ALGLIB -- - Copyright 25.10.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::filterlrma( - real_1d_array& x, - ae_int_t k, - const xparams _params = alglib::xdefault); -void alglib::filterlrma( - real_1d_array& x, - ae_int_t n, - ae_int_t k, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Filters: simple moving averages (unsymmetric). - -This filter replaces array by results of SMA(K) filter. SMA(K) is defined -as filter which averages at most K previous points (previous - not points -AROUND central point) - or less, in case of the first K-1 points. - -INPUT PARAMETERS: - X - array[N], array to process. It can be larger than N, - in this case only first N points are processed. - N - points count, N>=0 - K - K>=1 (K can be larger than N , such cases will be - correctly handled). Window width. K=1 corresponds to - identity transformation (nothing changes). - -OUTPUT PARAMETERS: - X - array, whose first N elements were processed with SMA(K) - -NOTE 1: this function uses efficient in-place algorithm which does not - allocate temporary arrays. - -NOTE 2: this algorithm makes only one pass through array and uses running - sum to speed-up calculation of the averages. Additional measures - are taken to ensure that running sum on a long sequence of zero - elements will be correctly reset to zero even in the presence of - round-off error. - -NOTE 3: this is unsymmetric version of the algorithm, which does NOT - averages points after the current one. Only X[i], X[i-1], ... are - used when calculating new value of X[i]. We should also note that - this algorithm uses BOTH previous points and current one, i.e. - new value of X[i] depends on BOTH previous point and X[i] itself. - - -- ALGLIB -- - Copyright 25.10.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::filtersma( - real_1d_array& x, - ae_int_t k, - const xparams _params = alglib::xdefault); -void alglib::filtersma( - real_1d_array& x, - ae_int_t n, - ae_int_t k, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // Here we demonstrate EMA(0.5) filtering for time series.
-    //
-    real_1d_array x = "[5,6,7,8]";
-
-    //
-    // Apply filter.
-    // We should get [5, 5.5, 6.25, 7.125] as result
-    //
-    filterema(x, 0.5);
-    printf("%s\n", x.tostring(4).c_str()); // EXPECTED: [5,5.5,6.25,7.125]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // Here we demonstrate LRMA(3) filtering for time series.
-    //
-    real_1d_array x = "[7,8,8,9,12,12]";
-
-    //
-    // Apply filter.
-    // We should get [7.0000, 8.0000, 8.1667, 8.8333, 11.6667, 12.5000] as result
-    //    
-    filterlrma(x, 3);
-    printf("%s\n", x.tostring(4).c_str()); // EXPECTED: [7.0000,8.0000,8.1667,8.8333,11.6667,12.5000]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // Here we demonstrate SMA(k) filtering for time series.
-    //
-    real_1d_array x = "[5,6,7,8]";
-
-    //
-    // Apply filter.
-    // We should get [5, 5.5, 6.5, 7.5] as result
-    //
-    filtersma(x, 2);
-    printf("%s\n", x.tostring(4).c_str()); // EXPECTED: [5,5.5,6.5,7.5]
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* -Fits least squares (LS) circle (or NX-dimensional sphere) to data (a set -of points in NX-dimensional space). - -Least squares circle minimizes sum of squared deviations between distances -from points to the center and some "candidate" radius, which is also -fitted to the data. - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - -OUTPUT PARAMETERS: - CX - central point for a sphere - R - radius - - -- ALGLIB -- - Copyright 07.05.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::fitspherels( - real_2d_array xy, - ae_int_t npoints, - ae_int_t nx, - real_1d_array& cx, - double& r, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Fits minimum circumscribed (MC) circle (or NX-dimensional sphere) to data -(a set of points in NX-dimensional space). - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - -OUTPUT PARAMETERS: - CX - central point for a sphere - RHi - radius - -NOTE: this function is an easy-to-use wrapper around more powerful "expert" - function fitspherex(). - - This wrapper is optimized for ease of use and stability - at the - cost of somewhat lower performance (we have to use very tight - stopping criteria for inner optimizer because we want to make sure - that it will converge on any dataset). - - If you are ready to experiment with settings of "expert" function, - you can achieve ~2-4x speedup over standard "bulletproof" settings. - - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::fitspheremc( - real_2d_array xy, - ae_int_t npoints, - ae_int_t nx, - real_1d_array& cx, - double& rhi, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Fits maximum inscribed circle (or NX-dimensional sphere) to data (a set of -points in NX-dimensional space). - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - -OUTPUT PARAMETERS: - CX - central point for a sphere - RLo - radius - -NOTE: this function is an easy-to-use wrapper around more powerful "expert" - function fitspherex(). - - This wrapper is optimized for ease of use and stability - at the - cost of somewhat lower performance (we have to use very tight - stopping criteria for inner optimizer because we want to make sure - that it will converge on any dataset). - - If you are ready to experiment with settings of "expert" function, - you can achieve ~2-4x speedup over standard "bulletproof" settings. - - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::fitspheremi( - real_2d_array xy, - ae_int_t npoints, - ae_int_t nx, - real_1d_array& cx, - double& rlo, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Fits minimum zone circle (or NX-dimensional sphere) to data (a set of -points in NX-dimensional space). - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - -OUTPUT PARAMETERS: - CX - central point for a sphere - RLo - radius of inscribed circle - RHo - radius of circumscribed circle - -NOTE: this function is an easy-to-use wrapper around more powerful "expert" - function fitspherex(). - - This wrapper is optimized for ease of use and stability - at the - cost of somewhat lower performance (we have to use very tight - stopping criteria for inner optimizer because we want to make sure - that it will converge on any dataset). - - If you are ready to experiment with settings of "expert" function, - you can achieve ~2-4x speedup over standard "bulletproof" settings. - - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::fitspheremz( - real_2d_array xy, - ae_int_t npoints, - ae_int_t nx, - real_1d_array& cx, - double& rlo, - double& rhi, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Fitting minimum circumscribed, maximum inscribed or minimum zone circles -(or NX-dimensional spheres) to data (a set of points in NX-dimensional -space). - -This is expert function which allows to tweak many parameters of -underlying nonlinear solver: -* stopping criteria for inner iterations -* number of outer iterations -* penalty coefficient used to handle nonlinear constraints (we convert - unconstrained nonsmooth optimization problem ivolving max() and/or min() - operations to quadratically constrained smooth one). - -You may tweak all these parameters or only some of them, leaving other -ones at their default state - just specify zero value, and solver will -fill it with appropriate default one. - -These comments also include some discussion of approach used to handle -such unusual fitting problem, its stability, drawbacks of alternative -methods, and convergence properties. - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - ProblemType-used to encode problem type: - * 0 for least squares circle - * 1 for minimum circumscribed circle/sphere fitting (MC) - * 2 for maximum inscribed circle/sphere fitting (MI) - * 3 for minimum zone circle fitting (difference between - Rhi and Rlo is minimized), denoted as MZ - EpsX - stopping condition for NLC optimizer: - * must be non-negative - * use 0 to choose default value (1.0E-12 is used by default) - * you may specify larger values, up to 1.0E-6, if you want - to speed-up solver; NLC solver performs several - preconditioned outer iterations, so final result - typically has precision much better than EpsX. - AULIts - number of outer iterations performed by NLC optimizer: - * must be non-negative - * use 0 to choose default value (20 is used by default) - * you may specify values smaller than 20 if you want to - speed up solver; 10 often results in good combination of - precision and speed; sometimes you may get good results - with just 6 outer iterations. - Ignored for ProblemType=0. - Penalty - penalty coefficient for NLC optimizer: - * must be non-negative - * use 0 to choose default value (1.0E6 in current version) - * it should be really large, 1.0E6...1.0E7 is a good value - to start from; - * generally, default value is good enough - Ignored for ProblemType=0. - -OUTPUT PARAMETERS: - CX - central point for a sphere - RLo - radius: - * for ProblemType=2,3, radius of the inscribed sphere - * for ProblemType=0 - radius of the least squares sphere - * for ProblemType=1 - zero - RHo - radius: - * for ProblemType=1,3, radius of the circumscribed sphere - * for ProblemType=0 - radius of the least squares sphere - * for ProblemType=2 - zero - -NOTE: ON THE UNIQUENESS OF SOLUTIONS - -ALGLIB provides solution to several related circle fitting problems: MC -(minimum circumscribed), MI (maximum inscribed) and MZ (minimum zone) -fitting, LS (least squares) fitting. - -It is important to note that among these problems only MC and LS are -convex and have unique solution independently from starting point. - -As for MI, it may (or may not, depending on dataset properties) have -multiple solutions, and it always has one degenerate solution C=infinity -which corresponds to infinitely large radius. Thus, there are no guarantees -that solution to MI returned by this solver will be the best one (and no -one can provide you with such guarantee because problem is NP-hard). The -only guarantee you have is that this solution is locally optimal, i.e. it -can not be improved by infinitesimally small tweaks in the parameters. - -It is also possible to "run away" to infinity when started from bad -initial point located outside of point cloud (or when point cloud does not -span entire circumference/surface of the sphere). - -Finally, MZ (minimum zone circle) stands somewhere between MC and MI in -stability. It is somewhat regularized by "circumscribed" term of the merit -function; however, solutions to MZ may be non-unique, and in some unlucky -cases it is also possible to "run away to infinity". - - -NOTE: ON THE NONLINEARLY CONSTRAINED PROGRAMMING APPROACH - -The problem formulation for MC (minimum circumscribed circle; for the -sake of simplicity we omit MZ and MI here) is: - - [ [ ]2 ] - min [ max [ XY[i]-C ] ] - C [ i [ ] ] - -i.e. it is unconstrained nonsmooth optimization problem of finding "best" -central point, with radius R being unambiguously determined from C. In -order to move away from non-smoothness we use following reformulation: - - [ ] [ ]2 - min [ R ] subject to R>=0, [ XY[i]-C ] <= R^2 - C,R [ ] [ ] - -i.e. it becomes smooth quadratically constrained optimization problem with -linear target function. Such problem statement is 100% equivalent to the -original nonsmooth one, but much easier to approach. We solve it with -MinNLC solver provided by ALGLIB. - - -NOTE: ON INSTABILITY OF SEQUENTIAL LINEARIZATION APPROACH - -ALGLIB has nonlinearly constrained solver which proved to be stable on -such problems. However, some authors proposed to linearize constraints in -the vicinity of current approximation (Ci,Ri) and to get next approximate -solution (Ci+1,Ri+1) as solution to linear programming problem. Obviously, -LP problems are easier than nonlinearly constrained ones. - -Indeed, such approach to MC/MI/MZ resulted in ~10-20x increase in -performance (when compared with NLC solver). However, it turned out that -in some cases linearized model fails to predict correct direction for next -step and tells us that we converged to solution even when we are still 2-4 -digits of precision away from it. - -It is important that it is not failure of LP solver - it is failure of the -linear model; even when solved exactly, it fails to handle subtle -nonlinearities which arise near the solution. We validated it by comparing -results returned by ALGLIB linear solver with that of MATLAB. - -In our experiments with linearization: -* MC failed most often, at both realistic and synthetic datasets -* MI sometimes failed, but sometimes succeeded -* MZ often succeeded; our guess is that presence of two independent sets - of constraints (one set for Rlo and another one for Rhi) and two terms - in the target function (Rlo and Rhi) regularizes task, so when linear - model fails to handle nonlinearities from Rlo, it uses Rhi as a hint - (and vice versa). - -Because linearization approach failed to achieve stable results, we do not -include it in ALGLIB. - - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::fitspherex( - real_2d_array xy, - ae_int_t npoints, - ae_int_t nx, - ae_int_t problemtype, - double epsx, - ae_int_t aulits, - double penalty, - real_1d_array& cx, - double& rlo, - double& rhi, - const xparams _params = alglib::xdefault); - -
- -
- -fresnelintegral
- - -
- -
-
/************************************************************************* -Fresnel integral - -Evaluates the Fresnel integrals - - x - - - | | -C(x) = | cos(pi/2 t**2) dt, - | | - - - 0 - - x - - - | | -S(x) = | sin(pi/2 t**2) dt. - | | - - - 0 - - -The integrals are evaluated by a power series for x < 1. -For x >= 1 auxiliary functions f(x) and g(x) are employed -such that - -C(x) = 0.5 + f(x) sin( pi/2 x**2 ) - g(x) cos( pi/2 x**2 ) -S(x) = 0.5 - f(x) cos( pi/2 x**2 ) - g(x) sin( pi/2 x**2 ) - - - -ACCURACY: - - Relative error. - -Arithmetic function domain # trials peak rms - IEEE S(x) 0, 10 10000 2.0e-15 3.2e-16 - IEEE C(x) 0, 10 10000 1.8e-15 3.3e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -
void alglib::fresnelintegral( - double x, - double& c, - double& s, - const xparams _params = alglib::xdefault); - -
- -
- -gammafunction
-lngamma
- - -
- -
-
/************************************************************************* -Gamma function - -Input parameters: - X - argument - -Domain: - 0 < X < 171.6 - -170 < X < 0, X is not an integer. - -Relative error: - arithmetic domain # trials peak rms - IEEE -170,-33 20000 2.3e-15 3.3e-16 - IEEE -33, 33 20000 9.4e-16 2.2e-16 - IEEE 33, 171.6 20000 2.3e-15 3.2e-16 - -Cephes Math Library Release 2.8: June, 2000 -Original copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier -Translated to AlgoPascal by Bochkanov Sergey (2005, 2006, 2007). -*************************************************************************/ -
double alglib::gammafunction( - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Natural logarithm of gamma function - -Input parameters: - X - argument - -Result: - logarithm of the absolute value of the Gamma(X). - -Output parameters: - SgnGam - sign(Gamma(X)) - -Domain: - 0 < X < 2.55e305 - -2.55e305 < X < 0, X is not an integer. - -ACCURACY: -arithmetic domain # trials peak rms - IEEE 0, 3 28000 5.4e-16 1.1e-16 - IEEE 2.718, 2.556e305 40000 3.5e-16 8.3e-17 -The error criterion was relative when the function magnitude -was greater than one but absolute when it was less than one. - -The following test used the relative error criterion, though -at certain points the relative error could be much higher than -indicated. - IEEE -200, -4 10000 4.8e-16 1.3e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier -Translated to AlgoPascal by Bochkanov Sergey (2005, 2006, 2007). -*************************************************************************/ -
double alglib::lngamma( - double x, - double& sgngam, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -Returns Gauss and Gauss-Kronrod nodes/weights for Gauss-Jacobi -quadrature on [-1,1] with weight function - - W(x)=Power(1-x,Alpha)*Power(1+x,Beta). - -INPUT PARAMETERS: - N - number of Kronrod nodes, must be odd number, >=3. - Alpha - power-law coefficient, Alpha>-1 - Beta - power-law coefficient, Beta>-1 - -OUTPUT PARAMETERS: - Info - error code: - * -5 no real and positive Gauss-Kronrod formula can - be created for such a weight function with a - given number of nodes. - * -4 an error was detected when calculating - weights/nodes. Alpha or Beta are too close - to -1 to obtain weights/nodes with high enough - accuracy, or, may be, N is too large. Try to - use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N was passed - * +1 OK - * +2 OK, but quadrature rule have exterior nodes, - x[0]<-1 or x[n-1]>+1 - X - array[0..N-1] - array of quadrature nodes, ordered in - ascending order. - WKronrod - array[0..N-1] - Kronrod weights - WGauss - array[0..N-1] - Gauss weights (interleaved with zeros - corresponding to extended Kronrod nodes). - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::gkqgenerategaussjacobi( - ae_int_t n, - double alpha, - double beta, - ae_int_t& info, - real_1d_array& x, - real_1d_array& wkronrod, - real_1d_array& wgauss, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Returns Gauss and Gauss-Kronrod nodes/weights for Gauss-Legendre -quadrature with N points. - -GKQLegendreCalc (calculation) or GKQLegendreTbl (precomputed table) is -used depending on machine precision and number of nodes. - -INPUT PARAMETERS: - N - number of Kronrod nodes, must be odd number, >=3. - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. N is too large to obtain - weights/nodes with high enough accuracy. - Try to use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, ordered in - ascending order. - WKronrod - array[0..N-1] - Kronrod weights - WGauss - array[0..N-1] - Gauss weights (interleaved with zeros - corresponding to extended Kronrod nodes). - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::gkqgenerategausslegendre( - ae_int_t n, - ae_int_t& info, - real_1d_array& x, - real_1d_array& wkronrod, - real_1d_array& wgauss, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Computation of nodes and weights of a Gauss-Kronrod quadrature formula - -The algorithm generates the N-point Gauss-Kronrod quadrature formula with -weight function given by coefficients alpha and beta of a recurrence -relation which generates a system of orthogonal polynomials: - - P-1(x) = 0 - P0(x) = 1 - Pn+1(x) = (x-alpha(n))*Pn(x) - beta(n)*Pn-1(x) - -and zero moment Mu0 - - Mu0 = integral(W(x)dx,a,b) - - -INPUT PARAMETERS: - Alpha - alpha coefficients, array[0..floor(3*K/2)]. - Beta - beta coefficients, array[0..ceil(3*K/2)]. - Beta[0] is not used and may be arbitrary. - Beta[I]>0. - Mu0 - zeroth moment of the weight function. - N - number of nodes of the Gauss-Kronrod quadrature formula, - N >= 3, - N = 2*K+1. - -OUTPUT PARAMETERS: - Info - error code: - * -5 no real and positive Gauss-Kronrod formula can - be created for such a weight function with a - given number of nodes. - * -4 N is too large, task may be ill conditioned - - x[i]=x[i+1] found. - * -3 internal eigenproblem solver hasn't converged - * -2 Beta[i]<=0 - * -1 incorrect N was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - WKronrod - array[0..N-1] - Kronrod weights - WGauss - array[0..N-1] - Gauss weights (interleaved with zeros - corresponding to extended Kronrod nodes). - - -- ALGLIB -- - Copyright 08.05.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::gkqgeneraterec( - real_1d_array alpha, - real_1d_array beta, - double mu0, - ae_int_t n, - ae_int_t& info, - real_1d_array& x, - real_1d_array& wkronrod, - real_1d_array& wgauss, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Returns Gauss and Gauss-Kronrod nodes for quadrature with N points. - -Reduction to tridiagonal eigenproblem is used. - -INPUT PARAMETERS: - N - number of Kronrod nodes, must be odd number, >=3. - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. N is too large to obtain - weights/nodes with high enough accuracy. - Try to use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, ordered in - ascending order. - WKronrod - array[0..N-1] - Kronrod weights - WGauss - array[0..N-1] - Gauss weights (interleaved with zeros - corresponding to extended Kronrod nodes). - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::gkqlegendrecalc( - ae_int_t n, - ae_int_t& info, - real_1d_array& x, - real_1d_array& wkronrod, - real_1d_array& wgauss, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Returns Gauss and Gauss-Kronrod nodes for quadrature with N points using -pre-calculated table. Nodes/weights were computed with accuracy up to -1.0E-32 (if MPFR version of ALGLIB is used). In standard double precision -accuracy reduces to something about 2.0E-16 (depending on your compiler's -handling of long floating point constants). - -INPUT PARAMETERS: - N - number of Kronrod nodes. - N can be 15, 21, 31, 41, 51, 61. - -OUTPUT PARAMETERS: - X - array[0..N-1] - array of quadrature nodes, ordered in - ascending order. - WKronrod - array[0..N-1] - Kronrod weights - WGauss - array[0..N-1] - Gauss weights (interleaved with zeros - corresponding to extended Kronrod nodes). - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::gkqlegendretbl( - ae_int_t n, - real_1d_array& x, - real_1d_array& wkronrod, - real_1d_array& wgauss, - double& eps, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -Returns nodes/weights for Gauss-Hermite quadrature on (-inf,+inf) with -weight function W(x)=Exp(-x*x) - -INPUT PARAMETERS: - N - number of nodes, >=1 - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. May be, N is too large. Try to - use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N/Alpha was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::gqgenerategausshermite( - ae_int_t n, - ae_int_t& info, - real_1d_array& x, - real_1d_array& w, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Returns nodes/weights for Gauss-Jacobi quadrature on [-1,1] with weight -function W(x)=Power(1-x,Alpha)*Power(1+x,Beta). - -INPUT PARAMETERS: - N - number of nodes, >=1 - Alpha - power-law coefficient, Alpha>-1 - Beta - power-law coefficient, Beta>-1 - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. Alpha or Beta are too close - to -1 to obtain weights/nodes with high enough - accuracy, or, may be, N is too large. Try to - use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N/Alpha/Beta was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::gqgenerategaussjacobi( - ae_int_t n, - double alpha, - double beta, - ae_int_t& info, - real_1d_array& x, - real_1d_array& w, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Returns nodes/weights for Gauss-Laguerre quadrature on [0,+inf) with -weight function W(x)=Power(x,Alpha)*Exp(-x) - -INPUT PARAMETERS: - N - number of nodes, >=1 - Alpha - power-law coefficient, Alpha>-1 - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. Alpha is too close to -1 to - obtain weights/nodes with high enough accuracy - or, may be, N is too large. Try to use - multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N/Alpha was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::gqgenerategausslaguerre( - ae_int_t n, - double alpha, - ae_int_t& info, - real_1d_array& x, - real_1d_array& w, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Returns nodes/weights for Gauss-Legendre quadrature on [-1,1] with N -nodes. - -INPUT PARAMETERS: - N - number of nodes, >=1 - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. N is too large to obtain - weights/nodes with high enough accuracy. - Try to use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::gqgenerategausslegendre( - ae_int_t n, - ae_int_t& info, - real_1d_array& x, - real_1d_array& w, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Computation of nodes and weights for a Gauss-Lobatto quadrature formula - -The algorithm generates the N-point Gauss-Lobatto quadrature formula with -weight function given by coefficients alpha and beta of a recurrence which -generates a system of orthogonal polynomials. - -P-1(x) = 0 -P0(x) = 1 -Pn+1(x) = (x-alpha(n))*Pn(x) - beta(n)*Pn-1(x) - -and zeroth moment Mu0 - -Mu0 = integral(W(x)dx,a,b) - -INPUT PARAMETERS: - Alpha - array[0..N-2], alpha coefficients - Beta - array[0..N-2], beta coefficients. - Zero-indexed element is not used, may be arbitrary. - Beta[I]>0 - Mu0 - zeroth moment of the weighting function. - A - left boundary of the integration interval. - B - right boundary of the integration interval. - N - number of nodes of the quadrature formula, N>=3 - (including the left and right boundary nodes). - -OUTPUT PARAMETERS: - Info - error code: - * -3 internal eigenproblem solver hasn't converged - * -2 Beta[i]<=0 - * -1 incorrect N was passed - * 1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - -- ALGLIB -- - Copyright 2005-2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::gqgenerategausslobattorec( - real_1d_array alpha, - real_1d_array beta, - double mu0, - double a, - double b, - ae_int_t n, - ae_int_t& info, - real_1d_array& x, - real_1d_array& w, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Computation of nodes and weights for a Gauss-Radau quadrature formula - -The algorithm generates the N-point Gauss-Radau quadrature formula with -weight function given by the coefficients alpha and beta of a recurrence -which generates a system of orthogonal polynomials. - -P-1(x) = 0 -P0(x) = 1 -Pn+1(x) = (x-alpha(n))*Pn(x) - beta(n)*Pn-1(x) - -and zeroth moment Mu0 - -Mu0 = integral(W(x)dx,a,b) - -INPUT PARAMETERS: - Alpha - array[0..N-2], alpha coefficients. - Beta - array[0..N-1], beta coefficients - Zero-indexed element is not used. - Beta[I]>0 - Mu0 - zeroth moment of the weighting function. - A - left boundary of the integration interval. - N - number of nodes of the quadrature formula, N>=2 - (including the left boundary node). - -OUTPUT PARAMETERS: - Info - error code: - * -3 internal eigenproblem solver hasn't converged - * -2 Beta[i]<=0 - * -1 incorrect N was passed - * 1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - - -- ALGLIB -- - Copyright 2005-2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::gqgenerategaussradaurec( - real_1d_array alpha, - real_1d_array beta, - double mu0, - double a, - ae_int_t n, - ae_int_t& info, - real_1d_array& x, - real_1d_array& w, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Computation of nodes and weights for a Gauss quadrature formula - -The algorithm generates the N-point Gauss quadrature formula with weight -function given by coefficients alpha and beta of a recurrence relation -which generates a system of orthogonal polynomials: - -P-1(x) = 0 -P0(x) = 1 -Pn+1(x) = (x-alpha(n))*Pn(x) - beta(n)*Pn-1(x) - -and zeroth moment Mu0 - -Mu0 = integral(W(x)dx,a,b) - -INPUT PARAMETERS: - Alpha - array[0..N-1], alpha coefficients - Beta - array[0..N-1], beta coefficients - Zero-indexed element is not used and may be arbitrary. - Beta[I]>0. - Mu0 - zeroth moment of the weight function. - N - number of nodes of the quadrature formula, N>=1 - -OUTPUT PARAMETERS: - Info - error code: - * -3 internal eigenproblem solver hasn't converged - * -2 Beta[i]<=0 - * -1 incorrect N was passed - * 1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - -- ALGLIB -- - Copyright 2005-2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::gqgeneraterec( - real_1d_array alpha, - real_1d_array beta, - double mu0, - ae_int_t n, - ae_int_t& info, - real_1d_array& x, - real_1d_array& w, - const xparams _params = alglib::xdefault); - -
- -
- -hermitecalculate
-hermitecoefficients
-hermitesum
- - -
- -
-
/************************************************************************* -Calculation of the value of the Hermite polynomial. - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Hermite polynomial Hn at x -*************************************************************************/ -
double alglib::hermitecalculate( - ae_int_t n, - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Representation of Hn as C[0] + C[1]*X + ... + C[N]*X^N - -Input parameters: - N - polynomial degree, n>=0 - -Output parameters: - C - coefficients -*************************************************************************/ -
void alglib::hermitecoefficients( - ae_int_t n, - real_1d_array& c, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Summation of Hermite polynomials using Clenshaw's recurrence formula. - -This routine calculates - c[0]*H0(x) + c[1]*H1(x) + ... + c[N]*HN(x) - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Hermite polynomial at x -*************************************************************************/ -
double alglib::hermitesum( - real_1d_array c, - ae_int_t n, - double x, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -Portable high quality random number generator state. -Initialized with HQRNDRandomize() or HQRNDSeed(). - -Fields: - S1, S2 - seed values - V - precomputed value - MagicV - 'magic' value used to determine whether State structure - was correctly initialized. -*************************************************************************/ -
class hqrndstate -{ -}; - -
- -
-
/************************************************************************* -This function generates random number from continuous distribution given -by finite sample X. - -INPUT PARAMETERS - State - high quality random number generator, must be - initialized with HQRNDRandomize() or HQRNDSeed(). - X - finite sample, array[N] (can be larger, in this case only - leading N elements are used). THIS ARRAY MUST BE SORTED BY - ASCENDING. - N - number of elements to use, N>=1 - -RESULT - this function returns random number from continuous distribution which - tries to approximate X as mush as possible. min(X)<=Result<=max(X). - - -- ALGLIB -- - Copyright 08.11.2011 by Bochkanov Sergey -*************************************************************************/ -
double alglib::hqrndcontinuous( - hqrndstate state, - real_1d_array x, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function generates random number from discrete distribution given by -finite sample X. - -INPUT PARAMETERS - State - high quality random number generator, must be - initialized with HQRNDRandomize() or HQRNDSeed(). - X - finite sample - N - number of elements to use, N>=1 - -RESULT - this function returns one of the X[i] for random i=0..N-1 - - -- ALGLIB -- - Copyright 08.11.2011 by Bochkanov Sergey -*************************************************************************/ -
double alglib::hqrnddiscrete( - hqrndstate state, - real_1d_array x, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Random number generator: exponential distribution - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 11.08.2007 by Bochkanov Sergey -*************************************************************************/ -
double alglib::hqrndexponential( - hqrndstate state, - double lambdav, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Random number generator: normal numbers - -This function generates one random number from normal distribution. -Its performance is equal to that of HQRNDNormal2() - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -
double alglib::hqrndnormal( - hqrndstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Random number generator: normal numbers - -This function generates two independent random numbers from normal -distribution. Its performance is equal to that of HQRNDNormal() - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::hqrndnormal2( - hqrndstate state, - double& x1, - double& x2, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Random number generator: matrix with random entries (normal distribution) - -This function generates MxN random matrix. - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::hqrndnormalm( - hqrndstate state, - ae_int_t m, - ae_int_t n, - real_2d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Random number generator: vector with random entries (normal distribution) - -This function generates N random numbers from normal distribution. - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::hqrndnormalv( - hqrndstate state, - ae_int_t n, - real_1d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -HQRNDState initialization with random values which come from standard -RNG. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::hqrndrandomize( - hqrndstate& state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -HQRNDState initialization with seed values - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::hqrndseed( - ae_int_t s1, - ae_int_t s2, - hqrndstate& state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function generates random integer number in [0, N) - -1. State structure must be initialized with HQRNDRandomize() or HQRNDSeed() -2. N can be any positive number except for very large numbers: - * close to 2^31 on 32-bit systems - * close to 2^62 on 64-bit systems - An exception will be generated if N is too large. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::hqrnduniformi( - hqrndstate state, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function generates random real number in (0,1), -not including interval boundaries - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -
double alglib::hqrnduniformr( - hqrndstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Random number generator: random X and Y such that X^2+Y^2=1 - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::hqrndunit2( - hqrndstate state, - double& x, - double& y, - const xparams _params = alglib::xdefault); - -
- -
- -incompletebeta
-invincompletebeta
- - -
- -
-
/************************************************************************* -Incomplete beta integral - -Returns incomplete beta integral of the arguments, evaluated -from zero to x. The function is defined as - - x - - - - | (a+b) | | a-1 b-1 - ----------- | t (1-t) dt. - - - | | - | (a) | (b) - - 0 - -The domain of definition is 0 <= x <= 1. In this -implementation a and b are restricted to positive values. -The integral from x to 1 may be obtained by the symmetry -relation - - 1 - incbet( a, b, x ) = incbet( b, a, 1-x ). - -The integral is evaluated by a continued fraction expansion -or, when b*x is small, by a power series. - -ACCURACY: - -Tested at uniformly distributed random points (a,b,x) with a and b -in "domain" and x between 0 and 1. - Relative error -arithmetic domain # trials peak rms - IEEE 0,5 10000 6.9e-15 4.5e-16 - IEEE 0,85 250000 2.2e-13 1.7e-14 - IEEE 0,1000 30000 5.3e-12 6.3e-13 - IEEE 0,10000 250000 9.3e-11 7.1e-12 - IEEE 0,100000 10000 8.7e-10 4.8e-11 -Outputs smaller than the IEEE gradual underflow threshold -were excluded from these statistics. - -Cephes Math Library, Release 2.8: June, 2000 -Copyright 1984, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::incompletebeta( - double a, - double b, - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Inverse of imcomplete beta integral - -Given y, the function finds x such that - - incbet( a, b, x ) = y . - -The routine performs interval halving or Newton iterations to find the -root of incbet(a,b,x) - y = 0. - - -ACCURACY: - - Relative error: - x a,b -arithmetic domain domain # trials peak rms - IEEE 0,1 .5,10000 50000 5.8e-12 1.3e-13 - IEEE 0,1 .25,100 100000 1.8e-13 3.9e-15 - IEEE 0,1 0,5 50000 1.1e-12 5.5e-15 -With a and b constrained to half-integer or integer values: - IEEE 0,1 .5,10000 50000 5.8e-12 1.1e-13 - IEEE 0,1 .5,100 100000 1.7e-14 7.9e-16 -With a = .5, b constrained to half-integer or integer values: - IEEE 0,1 .5,10000 10000 8.3e-11 1.0e-11 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1996, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::invincompletebeta( - double a, - double b, - double y, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -Builder object used to generate IDW (Inverse Distance Weighting) model. -*************************************************************************/ -
class idwbuilder -{ -}; - -
- -
-
/************************************************************************* -Buffer object which is used to perform evaluation requests in the -multithreaded mode (multiple threads working with same IDW object). - -This object should be created with idwcreatecalcbuffer(). -*************************************************************************/ -
class idwcalcbuffer -{ -}; - -
- -
-
/************************************************************************* -IDW (Inverse Distance Weighting) model object. -*************************************************************************/ -
class idwmodel -{ -}; - -
- -
-
/************************************************************************* -IDW fitting report: - rmserror RMS error - avgerror average error - maxerror maximum error - r2 coefficient of determination, R-squared, 1-RSS/TSS -*************************************************************************/ -
class idwreport -{ - double rmserror; - double avgerror; - double maxerror; - double r2; -}; - -
- -
-
/************************************************************************* -This subroutine creates builder object used to generate IDW model from -irregularly sampled (scattered) dataset. Multidimensional scalar/vector- --valued are supported. - -Builder object is used to fit model to data as follows: -* builder object is created with idwbuildercreate() function -* dataset is added with idwbuildersetpoints() function -* one of the modern IDW algorithms is chosen with either: - * idwbuildersetalgomstab() - Multilayer STABilized algorithm (interpolation) - Alternatively, one of the textbook algorithms can be chosen (not recommended): - * idwbuildersetalgotextbookshepard() - textbook Shepard algorithm - * idwbuildersetalgotextbookmodshepard()-textbook modified Shepard algorithm -* finally, model construction is performed with idwfit() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - NX - dimensionality of the argument, NX>=1 - NY - dimensionality of the function being modeled, NY>=1; - NY=1 corresponds to classic scalar function, NY>=1 corresponds - to vector-valued function. - -OUTPUT PARAMETERS: - State- builder object - - -- ALGLIB PROJECT -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::idwbuildercreate( - ae_int_t nx, - ae_int_t ny, - idwbuilder& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function sets IDW model construction algorithm to the Multilayer -Stabilized IDW method (IDW-MSTAB), a latest incarnation of the inverse -distance weighting interpolation which fixes shortcomings of the original -and modified Shepard's variants. - -The distinctive features of IDW-MSTAB are: -1) exact interpolation is pursued (as opposed to fitting and noise - suppression) -2) improved robustness when compared with that of other algorithms: - * MSTAB shows almost no strange fitting artifacts like ripples and - sharp spikes (unlike N-dimensional splines and HRBFs) - * MSTAB does not return function values far from the interval spanned - by the dataset; say, if all your points have |f|<=1, you can be sure - that model value won't deviate too much from [-1,+1] -3) good model construction time competing with that of HRBFs and bicubic - splines -4) ability to work with any number of dimensions, starting from NX=1 - -The drawbacks of IDW-MSTAB (and all IDW algorithms in general) are: -1) dependence of the model evaluation time on the search radius -2) bad extrapolation properties, models built by this method are usually - conservative in their predictions - -Thus, IDW-MSTAB is a good "default" option if you want to perform -scattered multidimensional interpolation. Although it has its drawbacks, -it is easy to use and robust, which makes it a good first step. - - -INPUT PARAMETERS: - State - builder object - SRad - initial search radius, SRad>0 is required. A model value - is obtained by "smart" averaging of the dataset points - within search radius. - -NOTE 1: IDW interpolation can correctly handle ANY dataset, including - datasets with non-distinct points. In case non-distinct points are - found, an average value for this point will be calculated. - -NOTE 2: the memory requirements for model storage are O(NPoints*NLayers). - The model construction needs twice as much memory as model storage. - -NOTE 3: by default 16 IDW layers are built which is enough for most cases. - You can change this parameter with idwbuildersetnlayers() method. - Larger values may be necessary if you need to reproduce extrafine - details at distances smaller than SRad/65536. Smaller value may - be necessary if you have to save memory and computing time, and - ready to sacrifice some model quality. - - -ALGORITHM DESCRIPTION - -ALGLIB implementation of IDW is somewhat similar to the modified Shepard's -method (one with search radius R) but overcomes several of its drawbacks, -namely: -1) a tendency to show stepwise behavior for uniform datasets -2) a tendency to show terrible interpolation properties for highly - nonuniform datasets which often arise in geospatial tasks - (function values are densely sampled across multiple separated - "tracks") - -IDW-MSTAB method performs several passes over dataset and builds a sequence -of progressively refined IDW models (layers), which starts from one with -largest search radius SRad and continues to smaller search radii until -required number of layers is built. Highest layers reproduce global -behavior of the target function at larger distances whilst lower layers -reproduce fine details at smaller distances. - -Each layer is an IDW model built with following modifications: -* weights go to zero when distance approach to the current search radius -* an additional regularizing term is added to the distance: w=1/(d^2+lambda) -* an additional fictional term with unit weight and zero function value is - added in order to promote continuity properties at the isolated and - boundary points - -By default, 16 layers is built, which is enough for most cases. You can -change this parameter with idwbuildersetnlayers() method. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::idwbuildersetalgomstab( - idwbuilder state, - double srad, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function sets IDW model construction algorithm to the 'textbook' -modified Shepard's algorithm with user-specified search radius. - -IMPORTANT: we do NOT recommend using textbook IDW algorithms because they - have terrible interpolation properties. Use MSTAB in all cases. - -INPUT PARAMETERS: - State - builder object - R - search radius - -NOTE 1: IDW interpolation can correctly handle ANY dataset, including - datasets with non-distinct points. In case non-distinct points are - found, an average value for this point will be calculated. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::idwbuildersetalgotextbookmodshepard( - idwbuilder state, - double r, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets IDW model construction algorithm to the textbook -Shepard's algorithm with custom (user-specified) power parameter. - -IMPORTANT: we do NOT recommend using textbook IDW algorithms because they - have terrible interpolation properties. Use MSTAB in all cases. - -INPUT PARAMETERS: - State - builder object - P - power parameter, P>0; good value to start with is 2.0 - -NOTE 1: IDW interpolation can correctly handle ANY dataset, including - datasets with non-distinct points. In case non-distinct points are - found, an average value for this point will be calculated. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::idwbuildersetalgotextbookshepard( - idwbuilder state, - double p, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets constant prior term (model value at infinity). - -Constant prior term is determined as mean value over dataset. - -INPUT PARAMETERS: - S - spline builder - - -- ALGLIB -- - Copyright 29.10.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::idwbuildersetconstterm( - idwbuilder state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function changes number of layers used by IDW-MSTAB algorithm. - -The more layers you have, the finer details can be reproduced with IDW -model. The less layers you have, the less memory and CPU time is consumed -by the model. - -Memory consumption grows linearly with layers count, running time grows -sub-linearly. - -The default number of layers is 16, which allows you to reproduce details -at distance down to SRad/65536. You will rarely need to change it. - -INPUT PARAMETERS: - State - builder object - NLayers - NLayers>=1, the number of layers used by the model. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::idwbuildersetnlayers( - idwbuilder state, - ae_int_t nlayers, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function adds dataset to the builder object. - -This function overrides results of the previous calls, i.e. multiple calls -of this function will result in only the last set being added. - -INPUT PARAMETERS: - State - builder object - XY - points, array[N,NX+NY]. One row corresponds to one point - in the dataset. First NX elements are coordinates, next - NY elements are function values. Array may be larger than - specified, in this case only leading [N,NX+NY] elements - will be used. - N - number of points in the dataset, N>=0. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::idwbuildersetpoints( - idwbuilder state, - real_2d_array xy, - const xparams _params = alglib::xdefault); -void alglib::idwbuildersetpoints( - idwbuilder state, - real_2d_array xy, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function sets prior term (model value at infinity) as user-specified -value. - -INPUT PARAMETERS: - S - spline builder - V - value for user-defined prior - -NOTE: for vector-valued models all components of the prior are set to same - user-specified value - - -- ALGLIB -- - Copyright 29.10.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::idwbuildersetuserterm( - idwbuilder state, - double v, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets zero prior term (model value at infinity). - -INPUT PARAMETERS: - S - spline builder - - -- ALGLIB -- - Copyright 29.10.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::idwbuildersetzeroterm( - idwbuilder state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates values of the IDW model at the given point. - -This is general function which can be used for arbitrary NX (dimension of -the space of arguments) and NY (dimension of the function itself). However -when you have NY=1 you may find more convenient to use idwcalc1(), -idwcalc2() or idwcalc3(). - -NOTE: this function modifies internal temporaries of the IDW model, thus - IT IS NOT THREAD-SAFE! If you want to perform parallel model - evaluation from the multiple threads, use idwtscalcbuf() with per- - thread buffer object. - -INPUT PARAMETERS: - S - IDW model - X - coordinates, array[NX]. X may have more than NX elements, - in this case only leading NX will be used. - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is out-parameter and will be - reallocated after call to this function. In case you want - to reuse previously allocated Y, you may use idwcalcbuf(), - which reallocates Y only when it is too small. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::idwcalc( - idwmodel s, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -IDW interpolation: scalar target, 1-dimensional argument - -NOTE: this function modifies internal temporaries of the IDW model, thus - IT IS NOT THREAD-SAFE! If you want to perform parallel model - evaluation from the multiple threads, use idwtscalcbuf() with per- - thread buffer object. - -INPUT PARAMETERS: - S - IDW interpolant built with IDW builder - X0 - argument value - -Result: - IDW interpolant S(X0) - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -
double alglib::idwcalc1( - idwmodel s, - double x0, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -IDW interpolation: scalar target, 2-dimensional argument - -NOTE: this function modifies internal temporaries of the IDW model, thus - IT IS NOT THREAD-SAFE! If you want to perform parallel model - evaluation from the multiple threads, use idwtscalcbuf() with per- - thread buffer object. - -INPUT PARAMETERS: - S - IDW interpolant built with IDW builder - X0, X1 - argument value - -Result: - IDW interpolant S(X0,X1) - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -
double alglib::idwcalc2( - idwmodel s, - double x0, - double x1, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -IDW interpolation: scalar target, 3-dimensional argument - -NOTE: this function modifies internal temporaries of the IDW model, thus - IT IS NOT THREAD-SAFE! If you want to perform parallel model - evaluation from the multiple threads, use idwtscalcbuf() with per- - thread buffer object. - -INPUT PARAMETERS: - S - IDW interpolant built with IDW builder - X0,X1,X2- argument value - -Result: - IDW interpolant S(X0,X1,X2) - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -
double alglib::idwcalc3( - idwmodel s, - double x0, - double x1, - double x2, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function calculates values of the IDW model at the given point. - -Same as idwcalc(), but does not reallocate Y when in is large enough to -store function values. - -NOTE: this function modifies internal temporaries of the IDW model, thus - IT IS NOT THREAD-SAFE! If you want to perform parallel model - evaluation from the multiple threads, use idwtscalcbuf() with per- - thread buffer object. - -INPUT PARAMETERS: - S - IDW model - X - coordinates, array[NX]. X may have more than NX elements, - in this case only leading NX will be used. - Y - possibly preallocated array - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is not reallocated when it - is larger than NY. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::idwcalcbuf( - idwmodel s, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function creates buffer structure which can be used to perform -parallel IDW model evaluations (with one IDW model instance being -used from multiple threads, as long as different threads use different -instances of buffer). - -This buffer object can be used with idwtscalcbuf() function (here "ts" -stands for "thread-safe", "buf" is a suffix which denotes function which -reuses previously allocated output space). - -How to use it: -* create IDW model structure or load it from file -* call idwcreatecalcbuffer(), once per thread working with IDW model (you - should call this function only AFTER model initialization, see below for - more information) -* call idwtscalcbuf() from different threads, with each thread working - with its own copy of buffer object. - -INPUT PARAMETERS - S - IDW model - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: buffer object should be used only with IDW model object which - was used to initialize buffer. Any attempt to use buffer with - different object is dangerous - you may get memory violation - error because sizes of internal arrays do not fit to dimensions - of the IDW structure. - -IMPORTANT: you should call this function only for model which was built - with model builder (or unserialized from file). Sizes of some - internal structures are determined only after model is built, - so buffer object created before model construction stage will - be useless (and any attempt to use it will result in exception). - - -- ALGLIB -- - Copyright 22.10.2018 by Sergey Bochkanov -*************************************************************************/ -
void alglib::idwcreatecalcbuffer( - idwmodel s, - idwcalcbuffer& buf, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function fits IDW model to the dataset using current IDW construction -algorithm. A model being built and fitting report are returned. - -INPUT PARAMETERS: - State - builder object - -OUTPUT PARAMETERS: - Model - an IDW model built with current algorithm - Rep - model fitting report, fields of this structure contain - information about average fitting errors. - -NOTE: although IDW-MSTAB algorithm is an interpolation method, i.e. it - tries to fit the model exactly, it can handle datasets with non- - distinct points which can not be fit exactly; in such cases least- - squares fitting is performed. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::idwfit( - idwbuilder state, - idwmodel& model, - idwreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -
void idwserialize(idwmodel &obj, std::string &s_out); -void idwserialize(idwmodel &obj, std::ostream &s_out); -
- -
-
/************************************************************************* -This function calculates values of the IDW model at the given point, using -external buffer object (internal temporaries of IDW model are not -modified). - -This function allows to use same IDW model object in different threads, -assuming that different threads use different instances of the buffer -structure. - -INPUT PARAMETERS: - S - IDW model, may be shared between different threads - Buf - buffer object created for this particular instance of IDW - model with idwcreatecalcbuffer(). - X - coordinates, array[NX]. X may have more than NX elements, - in this case only leading NX will be used. - Y - possibly preallocated array - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is not reallocated when it - is larger than NY. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::idwtscalcbuf( - idwmodel s, - idwcalcbuffer buf, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -
void idwunserialize(const std::string &s_in, idwmodel &obj); -void idwunserialize(const std::istream &s_in, idwmodel &obj); -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example illustrates basic concepts of the IDW models:
-    // creation and evaluation.
-    // 
-    // Suppose that we have set of 2-dimensional points with associated
-    // scalar function values, and we want to build an IDW model using
-    // our data.
-    // 
-    // NOTE: we can work with N-dimensional models and vector-valued functions too :)
-    // 
-    // Typical sequence of steps is given below:
-    // 1. we create IDW builder object
-    // 2. we attach our dataset to the IDW builder and tune algorithm settings
-    // 3. we generate IDW model
-    // 4. we use IDW model instance (evaluate, serialize, etc.)
-    //
-    double v;
-
-    //
-    // Step 1: IDW builder creation.
-    //
-    // We have to specify dimensionality of the space (2 or 3) and
-    // dimensionality of the function (scalar or vector).
-    //
-    // New builder object is empty - it has not dataset and uses
-    // default model construction settings
-    //
-    idwbuilder builder;
-    idwbuildercreate(2, 1, builder);
-
-    //
-    // Step 2: dataset addition
-    //
-    // XY contains two points - x0=(-1,0) and x1=(+1,0) -
-    // and two function values f(x0)=2, f(x1)=3.
-    //
-    real_2d_array xy = "[[-1,0,2],[+1,0,3]]";
-    idwbuildersetpoints(builder, xy);
-
-    //
-    // Step 3: choose IDW algorithm and generate model
-    //
-    // We use modified stabilized IDW algorithm with following parameters:
-    // * SRad - set to 5.0 (search radius must be large enough)
-    //
-    // IDW-MSTAB algorithm is a state-of-the-art implementation of IDW which
-    // is competitive with RBFs and bicubic splines. See comments on the
-    // idwbuildersetalgomstab() function for more information.
-    //
-    idwmodel model;
-    idwreport rep;
-    idwbuildersetalgomstab(builder, 5.0);
-    idwfit(builder, model, rep);
-
-    //
-    // Step 4: model was built, evaluate its value
-    //
-    v = idwcalc2(model, 1.0, 0.0);
-    printf("%.2f\n", double(v)); // EXPECTED: 3.000
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example shows how to serialize and unserialize IDW model.
-    // 
-    // Suppose that we have set of 2-dimensional points with associated
-    // scalar function values, and we have built an IDW model using
-    // our data.
-    //
-    // This model can be serialized to string or stream. ALGLIB supports
-    // flexible (un)serialization, i.e. you can move serialized model
-    // representation between different machines (32-bit or 64-bit),
-    // different CPU architectures (x86/64, ARM) or even different
-    // programming languages supported by ALGLIB (C#, C++, ...).
-    //
-    // Our first step is to build model, evaluate it at point (1,0),
-    // and serialize it to string.
-    //
-    std::string s;
-    double v;
-    real_2d_array xy = "[[-1,0,2],[+1,0,3]]";
-    idwbuilder builder;
-    idwmodel model;
-    idwmodel model2;
-    idwreport rep;
-    idwbuildercreate(2, 1, builder);
-    idwbuildersetpoints(builder, xy);
-    idwbuildersetalgomstab(builder, 5.0);
-    idwfit(builder, model, rep);
-    v = idwcalc2(model, 1.0, 0.0);
-    printf("%.2f\n", double(v)); // EXPECTED: 3.000
-
-    //
-    // Serialization + unserialization to a different instance
-    // of the model class.
-    //
-    alglib::idwserialize(model, s);
-    alglib::idwunserialize(s, model2);
-
-    //
-    // Evaluate unserialized model at the same point
-    //
-    v = idwcalc2(model2, 1.0, 0.0);
-    printf("%.2f\n", double(v)); // EXPECTED: 3.000
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* -Incomplete gamma integral - -The function is defined by - - x - - - 1 | | -t a-1 - igam(a,x) = ----- | e t dt. - - | | - | (a) - - 0 - - -In this implementation both arguments must be positive. -The integral is evaluated by either a power series or -continued fraction expansion, depending on the relative -values of a and x. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,30 200000 3.6e-14 2.9e-15 - IEEE 0,100 300000 9.9e-14 1.5e-14 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1985, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::incompletegamma( - double a, - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Complemented incomplete gamma integral - -The function is defined by - - - igamc(a,x) = 1 - igam(a,x) - - inf. - - - 1 | | -t a-1 - = ----- | e t dt. - - | | - | (a) - - x - - -In this implementation both arguments must be positive. -The integral is evaluated by either a power series or -continued fraction expansion, depending on the relative -values of a and x. - -ACCURACY: - -Tested at random a, x. - a x Relative error: -arithmetic domain domain # trials peak rms - IEEE 0.5,100 0,100 200000 1.9e-14 1.7e-15 - IEEE 0.01,0.5 0,100 200000 1.4e-13 1.6e-15 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1985, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::incompletegammac( - double a, - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Inverse of complemented imcomplete gamma integral - -Given p, the function finds x such that - - igamc( a, x ) = p. - -Starting with the approximate value - - 3 - x = a t - - where - - t = 1 - d - ndtri(p) sqrt(d) - -and - - d = 1/9a, - -the routine performs up to 10 Newton iterations to find the -root of igamc(a,x) - p = 0. - -ACCURACY: - -Tested at random a, p in the intervals indicated. - - a p Relative error: -arithmetic domain domain # trials peak rms - IEEE 0.5,100 0,0.5 100000 1.0e-14 1.7e-15 - IEEE 0.01,0.5 0,0.5 100000 9.0e-14 3.4e-15 - IEEE 0.5,10000 0,0.5 20000 2.3e-13 3.8e-14 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::invincompletegammac( - double a, - double y0, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -This function is left for backward compatibility. -Use fitspheremc() instead. - - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::nsfitspheremcc( - real_2d_array xy, - ae_int_t npoints, - ae_int_t nx, - real_1d_array& cx, - double& rhi, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function is left for backward compatibility. -Use fitspheremi() instead. - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::nsfitspheremic( - real_2d_array xy, - ae_int_t npoints, - ae_int_t nx, - real_1d_array& cx, - double& rlo, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function is left for backward compatibility. -Use fitspheremz() instead. - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::nsfitspheremzc( - real_2d_array xy, - ae_int_t npoints, - ae_int_t nx, - real_1d_array& cx, - double& rlo, - double& rhi, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function is left for backward compatibility. -Use fitspherex() instead. - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::nsfitspherex( - real_2d_array xy, - ae_int_t npoints, - ae_int_t nx, - ae_int_t problemtype, - double epsx, - ae_int_t aulits, - double penalty, - real_1d_array& cx, - double& rlo, - double& rhi, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function is an obsolete and deprecated version of fitting by -penalized cubic spline. - -It was superseded by spline1dfit(), which is an orders of magnitude faster -and more memory-efficient implementation. - -Do NOT use this function in the new code! - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dfitpenalized( - real_1d_array x, - real_1d_array y, - ae_int_t m, - double rho, - ae_int_t& info, - spline1dinterpolant& s, - spline1dfitreport& rep, - const xparams _params = alglib::xdefault); -void alglib::spline1dfitpenalized( - real_1d_array x, - real_1d_array y, - ae_int_t n, - ae_int_t m, - double rho, - ae_int_t& info, - spline1dinterpolant& s, - spline1dfitreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function is an obsolete and deprecated version of fitting by -penalized cubic spline. - -It was superseded by spline1dfit(), which is an orders of magnitude faster -and more memory-efficient implementation. - -Do NOT use this function in the new code! - - -- ALGLIB PROJECT -- - Copyright 19.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dfitpenalizedw( - real_1d_array x, - real_1d_array y, - real_1d_array w, - ae_int_t m, - double rho, - ae_int_t& info, - spline1dinterpolant& s, - spline1dfitreport& rep, - const xparams _params = alglib::xdefault); -void alglib::spline1dfitpenalizedw( - real_1d_array x, - real_1d_array y, - real_1d_array w, - ae_int_t n, - ae_int_t m, - double rho, - ae_int_t& info, - spline1dinterpolant& s, - spline1dfitreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- - - -
-
/************************************************************************* -Inverse matrix update by the Sherman-Morrison formula - -The algorithm updates matrix A^-1 when adding a vector to a column -of matrix A. - -Input parameters: - InvA - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - UpdColumn - the column of A whose vector U was added. - 0 <= UpdColumn <= N-1 - U - the vector to be added to a column. - Array whose index ranges within [0..N-1]. - -Output parameters: - InvA - inverse of modified matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixinvupdatecolumn( - real_2d_array& inva, - ae_int_t n, - ae_int_t updcolumn, - real_1d_array u, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Inverse matrix update by the Sherman-Morrison formula - -The algorithm updates matrix A^-1 when adding a vector to a row -of matrix A. - -Input parameters: - InvA - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - UpdRow - the row of A whose vector V was added. - 0 <= Row <= N-1 - V - the vector to be added to a row. - Array whose index ranges within [0..N-1]. - -Output parameters: - InvA - inverse of modified matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixinvupdaterow( - real_2d_array& inva, - ae_int_t n, - ae_int_t updrow, - real_1d_array v, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Inverse matrix update by the Sherman-Morrison formula - -The algorithm updates matrix A^-1 when adding a number to an element -of matrix A. - -Input parameters: - InvA - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - UpdRow - row where the element to be updated is stored. - UpdColumn - column where the element to be updated is stored. - UpdVal - a number to be added to the element. - - -Output parameters: - InvA - inverse of modified matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixinvupdatesimple( - real_2d_array& inva, - ae_int_t n, - ae_int_t updrow, - ae_int_t updcolumn, - double updval, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Inverse matrix update by the Sherman-Morrison formula - -The algorithm computes the inverse of matrix A+u*v' by using the given matrix -A^-1 and the vectors u and v. - -Input parameters: - InvA - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - U - the vector modifying the matrix. - Array whose index ranges within [0..N-1]. - V - the vector modifying the matrix. - Array whose index ranges within [0..N-1]. - -Output parameters: - InvA - inverse of matrix A + u*v'. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixinvupdateuv( - real_2d_array& inva, - ae_int_t n, - real_1d_array u, - real_1d_array v, - const xparams _params = alglib::xdefault); - -
- -
- -jacobianellipticfunctions
- - -
- -
-
/************************************************************************* -Jacobian Elliptic Functions - -Evaluates the Jacobian elliptic functions sn(u|m), cn(u|m), -and dn(u|m) of parameter m between 0 and 1, and real -argument u. - -These functions are periodic, with quarter-period on the -real axis equal to the complete elliptic integral -ellpk(1.0-m). - -Relation to incomplete elliptic integral: -If u = ellik(phi,m), then sn(u|m) = sin(phi), -and cn(u|m) = cos(phi). Phi is called the amplitude of u. - -Computation is by means of the arithmetic-geometric mean -algorithm, except when m is within 1e-9 of 0 or 1. In the -latter case with m close to 1, the approximation applies -only for phi < pi/2. - -ACCURACY: - -Tested at random points with u between 0 and 10, m between -0 and 1. - - Absolute error (* = relative error): -arithmetic function # trials peak rms - IEEE phi 10000 9.2e-16* 1.4e-16* - IEEE sn 50000 4.1e-15 4.6e-16 - IEEE cn 40000 3.6e-15 4.4e-16 - IEEE dn 10000 1.3e-12 1.8e-14 - - Peak error observed in consistency check using addition -theorem for sn(u+v) was 4e-16 (absolute). Also tested by -the above relation to the incomplete elliptic integral. -Accuracy deteriorates when u is large. - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -
void alglib::jacobianellipticfunctions( - double u, - double m, - double& sn, - double& cn, - double& dn, - double& ph, - const xparams _params = alglib::xdefault); - -
- -
- -jarqueberatest
- - -
- -
-
/************************************************************************* -Jarque-Bera test - -This test checks hypotheses about the fact that a given sample X is a -sample of normal random variable. - -Requirements: - * the number of elements in the sample is not less than 5. - -Input parameters: - X - sample. Array whose index goes from 0 to N-1. - N - size of the sample. N>=5 - -Output parameters: - P - p-value for the test - -Accuracy of the approximation used (5<=N<=1951): - -p-value relative error (5<=N<=1951) -[1, 0.1] < 1% -[0.1, 0.01] < 2% -[0.01, 0.001] < 6% -[0.001, 0] wasn't measured - -For N>1951 accuracy wasn't measured but it shouldn't be sharply different -from table values. - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::jarqueberatest( - real_1d_array x, - ae_int_t n, - double& p, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -Buffer object which is used to perform various requests (usually model -inference) in the multithreaded mode (multiple threads working with same -KNN object). - -This object should be created with KNNCreateBuffer(). -*************************************************************************/ -
class knnbuffer -{ -}; - -
- -
-
/************************************************************************* -A KNN builder object; this object encapsulates dataset and all related -settings, it is used to create an actual instance of KNN model. -*************************************************************************/ -
class knnbuilder -{ -}; - -
- -
-
/************************************************************************* -KNN model, can be used for classification or regression -*************************************************************************/ -
class knnmodel -{ -}; - -
- -
-
/************************************************************************* -KNN training report. - -Following fields store training set errors: -* relclserror - fraction of misclassified cases, [0,1] -* avgce - average cross-entropy in bits per symbol -* rmserror - root-mean-square error -* avgerror - average error -* avgrelerror - average relative error - -For classification problems: -* RMS, AVG and AVGREL errors are calculated for posterior probabilities - -For regression problems: -* RELCLS and AVGCE errors are zero -*************************************************************************/ -
class knnreport -{ - double relclserror; - double avgce; - double rmserror; - double avgerror; - double avgrelerror; -}; - -
- -
-
/************************************************************************* -Calculates all kinds of errors for the model in one call. - -INPUT PARAMETERS: - Model - KNN model - XY - test set: - * one row per point - * first NVars columns store independent variables - * depending on problem type: - * next column stores class number in [0,NClasses) - for - classification problems - * next NOut columns store dependent variables - for - regression problems - NPoints - test set size, NPoints>=0 - -OUTPUT PARAMETERS: - Rep - following fields are loaded with errors for both regression - and classification models: - * rep.rmserror - RMS error for the output - * rep.avgerror - average error - * rep.avgrelerror - average relative error - following fields are set only for classification models, - zero for regression ones: - * relclserror - relative classification error, in [0,1] - * avgce - average cross-entropy in bits per dataset entry - -NOTE: the cross-entropy metric is too unstable when used to evaluate KNN - models (such models can report exactly zero probabilities), so we - do not recommend using it. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::knnallerrors( - knnmodel model, - real_2d_array xy, - ae_int_t npoints, - knnreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Average cross-entropy (in bits per element) on the test set - -INPUT PARAMETERS: - Model - KNN model - XY - test set - NPoints - test set size - -RESULT: - CrossEntropy/NPoints. - Zero if model solves regression task. - -NOTE: the cross-entropy metric is too unstable when used to evaluate KNN - models (such models can report exactly zero probabilities), so we - do not recommend using it. - -NOTE: if you need several different kinds of error metrics, it is better - to use knnallerrors() which computes all error metric with just one - pass over dataset. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
double alglib::knnavgce( - knnmodel model, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Average error on the test set - -Its meaning for regression task is obvious. As for classification problems, -average error means error when estimating posterior probabilities. - -INPUT PARAMETERS: - Model - KNN model - XY - test set - NPoints - test set size - -RESULT: - average error - -NOTE: if you need several different kinds of error metrics, it is better - to use knnallerrors() which computes all error metric with just one - pass over dataset. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
double alglib::knnavgerror( - knnmodel model, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Average relative error on the test set - -Its meaning for regression task is obvious. As for classification problems, -average relative error means error when estimating posterior probabilities. - -INPUT PARAMETERS: - Model - KNN model - XY - test set - NPoints - test set size - -RESULT: - average relative error - -NOTE: if you need several different kinds of error metrics, it is better - to use knnallerrors() which computes all error metric with just one - pass over dataset. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
double alglib::knnavgrelerror( - knnmodel model, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine builds KNN model according to current settings, using -dataset internally stored in the builder object. - -The model being built performs inference using Eps-approximate K nearest -neighbors search algorithm, with: -* K=1, Eps=0 corresponding to the "nearest neighbor algorithm" -* K>1, Eps=0 corresponding to the "K nearest neighbors algorithm" -* K>=1, Eps>0 corresponding to "approximate nearest neighbors algorithm" - -An approximate KNN is a good option for high-dimensional datasets (exact -KNN works slowly when dimensions count grows). - -An ALGLIB implementation of kd-trees is used to perform k-nn searches. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - KNN builder object - K - number of neighbors to search for, K>=1 - Eps - approximation factor: - * Eps=0 means that exact kNN search is performed - * Eps>0 means that (1+Eps)-approximate search is performed - -OUTPUT PARAMETERS: - Model - KNN model - Rep - report - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::knnbuilderbuildknnmodel( - knnbuilder s, - ae_int_t k, - double eps, - knnmodel& model, - knnreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This subroutine creates KNNBuilder object which is used to train KNN models. - -By default, new builder stores empty dataset and some reasonable default -settings. At the very least, you should specify dataset prior to building -KNN model. You can also tweak settings of the model construction algorithm -(recommended, although default settings should work well). - -Following actions are mandatory: -* calling knnbuildersetdataset() to specify dataset -* calling knnbuilderbuildknnmodel() to build KNN model using current - dataset and default settings - -Additionally, you may call: -* knnbuildersetnorm() to change norm being used - -INPUT PARAMETERS: - none - -OUTPUT PARAMETERS: - S - KNN builder - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::knnbuildercreate( - knnbuilder& s, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -Specifies classification problem (two or more classes are predicted). -There also exists "regression" version of this function. - -This subroutine adds dense dataset to the internal storage of the builder -object. Specifying your dataset in the dense format means that the dense -version of the KNN construction algorithm will be invoked. - -INPUT PARAMETERS: - S - KNN builder object - XY - array[NPoints,NVars+1] (note: actual size can be - larger, only leading part is used anyway), dataset: - * first NVars elements of each row store values of the - independent variables - * next element stores class index, in [0,NClasses) - NPoints - number of rows in the dataset, NPoints>=1 - NVars - number of independent variables, NVars>=1 - NClasses - number of classes, NClasses>=2 - -OUTPUT PARAMETERS: - S - KNN builder - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::knnbuildersetdatasetcls( - knnbuilder s, - real_2d_array xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Specifies regression problem (one or more continuous output variables are -predicted). There also exists "classification" version of this function. - -This subroutine adds dense dataset to the internal storage of the builder -object. Specifying your dataset in the dense format means that the dense -version of the KNN construction algorithm will be invoked. - -INPUT PARAMETERS: - S - KNN builder object - XY - array[NPoints,NVars+NOut] (note: actual size can be - larger, only leading part is used anyway), dataset: - * first NVars elements of each row store values of the - independent variables - * next NOut elements store values of the dependent - variables - NPoints - number of rows in the dataset, NPoints>=1 - NVars - number of independent variables, NVars>=1 - NOut - number of dependent variables, NOut>=1 - -OUTPUT PARAMETERS: - S - KNN builder - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::knnbuildersetdatasetreg( - knnbuilder s, - real_2d_array xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nout, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function sets norm type used for neighbor search. - -INPUT PARAMETERS: - S - decision forest builder object - NormType - norm type: - * 0 inf-norm - * 1 1-norm - * 2 Euclidean norm (default) - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::knnbuildersetnorm( - knnbuilder s, - ae_int_t nrmtype, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function returns most probable class number for an input X. It is -same as calling knnprocess(model,x,y), then determining i=argmax(y[i]) and -returning i. - -A class number in [0,NOut) range in returned for classification problems, --1 is returned when this function is called for regression problems. - -IMPORTANT: this function is thread-unsafe and modifies internal structures - of the model! You can not use same model object for parallel - evaluation from several threads. - - Use knntsprocess() with independent thread-local buffers, if - you need thread-safe evaluation. - -INPUT PARAMETERS: - Model - KNN model - X - input vector, array[0..NVars-1]. - -RESULT: - class number, -1 for regression tasks - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::knnclassify( - knnmodel model, - real_1d_array x, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function creates buffer structure which can be used to perform -parallel KNN requests. - -KNN subpackage provides two sets of computing functions - ones which use -internal buffer of KNN model (these functions are single-threaded because -they use same buffer, which can not shared between threads), and ones -which use external buffer. - -This function is used to initialize external buffer. - -INPUT PARAMETERS - Model - KNN model which is associated with newly created buffer - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: buffer object should be used only with model which was used to - initialize buffer. Any attempt to use buffer with different - object is dangerous - you may get integrity check failure - (exception) because sizes of internal arrays do not fit to - dimensions of the model structure. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::knncreatebuffer( - knnmodel model, - knnbuffer& buf, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Inference using KNN model. - -See also knnprocess0(), knnprocessi() and knnclassify() for options with a -bit more convenient interface. - -IMPORTANT: this function is thread-unsafe and modifies internal structures - of the model! You can not use same model object for parallel - evaluation from several threads. - - Use knntsprocess() with independent thread-local buffers, if - you need thread-safe evaluation. - -INPUT PARAMETERS: - Model - KNN model - X - input vector, array[0..NVars-1]. - Y - possible preallocated buffer. Reused if long enough. - -OUTPUT PARAMETERS: - Y - result. Regression estimate when solving regression task, - vector of posterior probabilities for classification task. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::knnprocess( - knnmodel model, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function returns first component of the inferred vector (i.e. one -with index #0). - -It is a convenience wrapper for knnprocess() intended for either: -* 1-dimensional regression problems -* 2-class classification problems - -In the former case this function returns inference result as scalar, which -is definitely more convenient that wrapping it as vector. In the latter -case it returns probability of object belonging to class #0. - -If you call it for anything different from two cases above, it will work -as defined, i.e. return y[0], although it is of less use in such cases. - -IMPORTANT: this function is thread-unsafe and modifies internal structures - of the model! You can not use same model object for parallel - evaluation from several threads. - - Use knntsprocess() with independent thread-local buffers, if - you need thread-safe evaluation. - -INPUT PARAMETERS: - Model - KNN model - X - input vector, array[0..NVars-1]. - -RESULT: - Y[0] - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
double alglib::knnprocess0( - knnmodel model, - real_1d_array x, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -'interactive' variant of knnprocess() for languages like Python which -support constructs like "y = knnprocessi(model,x)" and interactive mode of -the interpreter. - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - -IMPORTANT: this function is thread-unsafe and may modify internal - structures of the model! You can not use same model object for - parallel evaluation from several threads. - - Use knntsprocess() with independent thread-local buffers if - you need thread-safe evaluation. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::knnprocessi( - knnmodel model, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Relative classification error on the test set - -INPUT PARAMETERS: - Model - KNN model - XY - test set - NPoints - test set size - -RESULT: - percent of incorrectly classified cases. - Zero if model solves regression task. - -NOTE: if you need several different kinds of error metrics, it is better - to use knnallerrors() which computes all error metric with just one - pass over dataset. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
double alglib::knnrelclserror( - knnmodel model, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Changing search settings of KNN model. - -K and EPS parameters of KNN (AKNN) search are specified during model -construction. However, plain KNN algorithm with Euclidean distance allows -you to change them at any moment. - -NOTE: future versions of KNN model may support advanced versions of KNN, - such as NCA or LMNN. It is possible that such algorithms won't allow - you to change search settings on the fly. If you call this function - for an algorithm which does not support on-the-fly changes, it will - throw an exception. - -INPUT PARAMETERS: - Model - KNN model - K - K>=1, neighbors count - EPS - accuracy of the EPS-approximate NN search. Set to 0.0, if - you want to perform "classic" KNN search. Specify larger - values if you need to speed-up high-dimensional KNN - queries. - -OUTPUT PARAMETERS: - nothing on success, exception on failure - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::knnrewritekeps( - knnmodel model, - ae_int_t k, - double eps, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -RMS error on the test set. - -Its meaning for regression task is obvious. As for classification problems, -RMS error means error when estimating posterior probabilities. - -INPUT PARAMETERS: - Model - KNN model - XY - test set - NPoints - test set size - -RESULT: - root mean square error. - -NOTE: if you need several different kinds of error metrics, it is better - to use knnallerrors() which computes all error metric with just one - pass over dataset. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
double alglib::knnrmserror( - knnmodel model, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -
void knnserialize(knnmodel &obj, std::string &s_out); -void knnserialize(knnmodel &obj, std::ostream &s_out); -
- -
-
/************************************************************************* -Thread-safe procesing using external buffer for temporaries. - -This function is thread-safe (i.e . you can use same KNN model from -multiple threads) as long as you use different buffer objects for different -threads. - -INPUT PARAMETERS: - Model - KNN model - Buf - buffer object, must be allocated specifically for this - model with knncreatebuffer(). - X - input vector, array[NVars] - -OUTPUT PARAMETERS: - Y - result, array[NOut]. Regression estimate when solving - regression task, vector of posterior probabilities for - a classification task. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::knntsprocess( - knnmodel model, - knnbuffer buf, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -
void knnunserialize(const std::string &s_in, knnmodel &obj); -void knnunserialize(const std::istream &s_in, knnmodel &obj); -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // The very simple classification example: classify points (x,y) in 2D space
-    // as ones with x>=0 and ones with x<0 (y is ignored, but our classifier
-    // has to find out it).
-    //
-    // First, we have to create KNN builder object, load dataset and specify
-    // training settings. Our dataset is specified as matrix, which has following
-    // format:
-    //
-    //     x0 y0 class0
-    //     x1 y1 class1
-    //     x2 y2 class2
-    //     ....
-    //
-    // Here xi and yi can be any values (and in fact you can have any number of
-    // independent variables), and classi MUST be integer number in [0,NClasses)
-    // range. In our example we denote points with x>=0 as class #0, and
-    // ones with negative xi as class #1.
-    //
-    // NOTE: if you want to solve regression problem, specify dataset in similar
-    //       format, but with dependent variable(s) instead of class labels. You
-    //       can have dataset with multiple dependent variables, by the way!
-    //
-    // For the sake of simplicity, our example includes only 4-point dataset and
-    // really simple K=1 nearest neighbor search. Industrial problems typically
-    // need larger values of K.
-    //
-    knnbuilder builder;
-    ae_int_t nvars = 2;
-    ae_int_t nclasses = 2;
-    ae_int_t npoints = 4;
-    real_2d_array xy = "[[1,1,0],[1,-1,0],[-1,1,1],[-1,-1,1]]";
-
-    knnbuildercreate(builder);
-    knnbuildersetdatasetcls(builder, xy, npoints, nvars, nclasses);
-
-    // we build KNN model with k=1 and eps=0 (exact k-nn search is performed)
-    ae_int_t k = 1;
-    double eps = 0;
-    knnmodel model;
-    knnreport rep;
-    knnbuilderbuildknnmodel(builder, k, eps, model, rep);
-
-    // with such settings (k=1 is used) you can expect zero classification
-    // error on training set. Beautiful results, but remember - in real life
-    // you do not need zero TRAINING SET error, you need good generalization.
-
-    printf("%.4f\n", double(rep.relclserror)); // EXPECTED: 0.0000
-
-    // now, let's perform some simple processing with knnprocess()
-    real_1d_array x = "[+1,0]";
-    real_1d_array y = "[]";
-    knnprocess(model, x, y);
-    printf("%s\n", y.tostring(3).c_str()); // EXPECTED: [+1,0]
-
-    // another option is to use knnprocess0() which returns just first component
-    // of the output vector y. ideal for regression problems and binary classifiers.
-    double y0;
-    y0 = knnprocess0(model, x);
-    printf("%.3f\n", double(y0)); // EXPECTED: 1.000
-
-    // finally, you can use knnclassify() which returns most probable class index (i.e. argmax y[i]).
-    ae_int_t i;
-    i = knnclassify(model, x);
-    printf("%d\n", int(i)); // EXPECTED: 0
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // The very simple regression example: model f(x,y)=x+y
-    //
-    // First, we have to create KNN builder object, load dataset and specify
-    // training settings. Our dataset is specified as matrix, which has following
-    // format:
-    //
-    //     x0 y0 f0
-    //     x1 y1 f1
-    //     x2 y2 f2
-    //     ....
-    //
-    // Here xi and yi can be any values, and fi is a dependent function value.
-    // By the way, with KNN algorithm you can even model functions with multiple
-    // dependent variables!
-    //
-    // NOTE: you can also solve classification problems with KNN models, see
-    //       another example for this unit.
-    //
-    // For the sake of simplicity, our example includes only 4-point dataset and
-    // really simple K=1 nearest neighbor search. Industrial problems typically
-    // need larger values of K.
-    //
-    knnbuilder builder;
-    ae_int_t nvars = 2;
-    ae_int_t nout = 1;
-    ae_int_t npoints = 4;
-    real_2d_array xy = "[[1,1,+2],[1,-1,0],[-1,1,0],[-1,-1,-2]]";
-
-    knnbuildercreate(builder);
-    knnbuildersetdatasetreg(builder, xy, npoints, nvars, nout);
-
-    // we build KNN model with k=1 and eps=0 (exact k-nn search is performed)
-    ae_int_t k = 1;
-    double eps = 0;
-    knnmodel model;
-    knnreport rep;
-    knnbuilderbuildknnmodel(builder, k, eps, model, rep);
-
-    // with such settings (k=1 is used) you can expect zero RMS error on the
-    // training set. Beautiful results, but remember - in real life you do not
-    // need zero TRAINING SET error, you need good generalization.
-
-    printf("%.4f\n", double(rep.rmserror)); // EXPECTED: 0.0000
-
-    // now, let's perform some simple processing with knnprocess()
-    real_1d_array x = "[+1,+1]";
-    real_1d_array y = "[]";
-    knnprocess(model, x, y);
-    printf("%s\n", y.tostring(3).c_str()); // EXPECTED: [+2]
-
-    // another option is to use knnprocess0() which returns just first component
-    // of the output vector y. ideal for regression problems and binary classifiers.
-    double y0;
-    y0 = knnprocess0(model, x);
-    printf("%.3f\n", double(y0)); // EXPECTED: 2.000
-
-    // there also exist another convenience function, knnclassify(),
-    // but it does not work for regression problems - it always returns -1.
-    ae_int_t i;
-    i = knnclassify(model, x);
-    printf("%d\n", int(i)); // EXPECTED: -1
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* -Calculation of the value of the Laguerre polynomial. - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Laguerre polynomial Ln at x -*************************************************************************/ -
double alglib::laguerrecalculate( - ae_int_t n, - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Representation of Ln as C[0] + C[1]*X + ... + C[N]*X^N - -Input parameters: - N - polynomial degree, n>=0 - -Output parameters: - C - coefficients -*************************************************************************/ -
void alglib::laguerrecoefficients( - ae_int_t n, - real_1d_array& c, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Summation of Laguerre polynomials using Clenshaw's recurrence formula. - -This routine calculates c[0]*L0(x) + c[1]*L1(x) + ... + c[N]*LN(x) - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Laguerre polynomial at x -*************************************************************************/ -
double alglib::laguerresum( - real_1d_array c, - ae_int_t n, - double x, - const xparams _params = alglib::xdefault); - -
- -
- -fisherlda
-fisherldan
- - -
- -
-
/************************************************************************* -Multiclass Fisher LDA - -Subroutine finds coefficients of linear combination which optimally separates -training set on classes. - -COMMERCIAL EDITION OF ALGLIB: - - ! Commercial version of ALGLIB includes two important improvements of - ! this function, which can be used from C++ and C#: - ! * Intel MKL support (lightweight Intel MKL is shipped with ALGLIB) - ! * multithreading support - ! - ! Intel MKL gives approximately constant (with respect to number of - ! worker threads) acceleration factor which depends on CPU being used, - ! problem size and "baseline" ALGLIB edition which is used for - ! comparison. Best results are achieved for high-dimensional problems - ! (NVars is at least 256). - ! - ! Multithreading is used to accelerate initial phase of LDA, which - ! includes calculation of products of large matrices. Again, for best - ! efficiency problem must be high-dimensional. - ! - ! Generally, commercial ALGLIB is several times faster than open-source - ! generic C edition, and many times faster than open-source C# edition. - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - training set, array[0..NPoints-1,0..NVars]. - First NVars columns store values of independent - variables, next column stores number of class (from 0 - to NClasses-1) which dataset element belongs to. Fractional - values are rounded to nearest integer. - NPoints - training set size, NPoints>=0 - NVars - number of independent variables, NVars>=1 - NClasses - number of classes, NClasses>=2 - - -OUTPUT PARAMETERS: - Info - return code: - * -4, if internal EVD subroutine hasn't converged - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed (NPoints<0, - NVars<1, NClasses<2) - * 1, if task has been solved - * 2, if there was a multicollinearity in training set, - but task has been solved. - W - linear combination coefficients, array[0..NVars-1] - - -- ALGLIB -- - Copyright 31.05.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::fisherlda( - real_2d_array xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - ae_int_t& info, - real_1d_array& w, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -N-dimensional multiclass Fisher LDA - -Subroutine finds coefficients of linear combinations which optimally separates -training set on classes. It returns N-dimensional basis whose vector are sorted -by quality of training set separation (in descending order). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - training set, array[0..NPoints-1,0..NVars]. - First NVars columns store values of independent - variables, next column stores number of class (from 0 - to NClasses-1) which dataset element belongs to. Fractional - values are rounded to nearest integer. - NPoints - training set size, NPoints>=0 - NVars - number of independent variables, NVars>=1 - NClasses - number of classes, NClasses>=2 - - -OUTPUT PARAMETERS: - Info - return code: - * -4, if internal EVD subroutine hasn't converged - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed (NPoints<0, - NVars<1, NClasses<2) - * 1, if task has been solved - * 2, if there was a multicollinearity in training set, - but task has been solved. - W - basis, array[0..NVars-1,0..NVars-1] - columns of matrix stores basis vectors, sorted by - quality of training set separation (in descending order) - - -- ALGLIB -- - Copyright 31.05.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::fisherldan( - real_2d_array xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - ae_int_t& info, - real_2d_array& w, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -Calculation of the value of the Legendre polynomial Pn. - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Legendre polynomial Pn at x -*************************************************************************/ -
double alglib::legendrecalculate( - ae_int_t n, - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Representation of Pn as C[0] + C[1]*X + ... + C[N]*X^N - -Input parameters: - N - polynomial degree, n>=0 - -Output parameters: - C - coefficients -*************************************************************************/ -
void alglib::legendrecoefficients( - ae_int_t n, - real_1d_array& c, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Summation of Legendre polynomials using Clenshaw's recurrence formula. - -This routine calculates - c[0]*P0(x) + c[1]*P1(x) + ... + c[N]*PN(x) - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Legendre polynomial at x -*************************************************************************/ -
double alglib::legendresum( - real_1d_array c, - ae_int_t n, - double x, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* - -*************************************************************************/ -
class lincgreport -{ - ae_int_t iterationscount; - ae_int_t nmv; - ae_int_t terminationtype; - double r2; -}; - -
- -
-
/************************************************************************* -This object stores state of the linear CG method. - -You should use ALGLIB functions to work with this object. -Never try to access its fields directly! -*************************************************************************/ -
class lincgstate -{ -}; - -
- -
-
/************************************************************************* -This function initializes linear CG Solver. This solver is used to solve -symmetric positive definite problems. If you want to solve nonsymmetric -(or non-positive definite) problem you may use LinLSQR solver provided by -ALGLIB. - -USAGE: -1. User initializes algorithm state with LinCGCreate() call -2. User tunes solver parameters with LinCGSetCond() and other functions -3. Optionally, user sets starting point with LinCGSetStartingPoint() -4. User calls LinCGSolveSparse() function which takes algorithm state and - SparseMatrix object. -5. User calls LinCGResults() to get solution -6. Optionally, user may call LinCGSolveSparse() again to solve another - problem with different matrix and/or right part without reinitializing - LinCGState structure. - -INPUT PARAMETERS: - N - problem dimension, N>0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lincgcreate( - ae_int_t n, - lincgstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -CG-solver: results. - -This function must be called after LinCGSolve - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[N], solution - Rep - optimization report: - * Rep.TerminationType completetion code: - * -5 input matrix is either not positive definite, - too large or too small - * -4 overflow/underflow during solution - (ill conditioned problem) - * 1 ||residual||<=EpsF*||b|| - * 5 MaxIts steps was taken - * 7 rounding errors prevent further progress, - best point found is returned - * Rep.IterationsCount contains iterations count - * NMV countains number of matrix-vector calculations - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lincgresults( - lincgstate state, - real_1d_array& x, - lincgreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function sets stopping criteria. - -INPUT PARAMETERS: - EpsF - algorithm will be stopped if norm of residual is less than - EpsF*||b||. - MaxIts - algorithm will be stopped if number of iterations is more - than MaxIts. - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -If both EpsF and MaxIts are zero then small EpsF will be set to small -value. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lincgsetcond( - lincgstate state, - double epsf, - ae_int_t maxits, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function changes preconditioning settings of LinCGSolveSparse() -function. LinCGSolveSparse() will use diagonal of the system matrix as -preconditioner. This preconditioning mode is active by default. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 19.11.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lincgsetprecdiag( - lincgstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function changes preconditioning settings of LinCGSolveSparse() -function. By default, SolveSparse() uses diagonal preconditioner, but if -you want to use solver without preconditioning, you can call this function -which forces solver to use unit matrix for preconditioning. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 19.11.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lincgsetprecunit( - lincgstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets restart frequency. By default, algorithm is restarted -after N subsequent iterations. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lincgsetrestartfreq( - lincgstate state, - ae_int_t srf, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets frequency of residual recalculations. - -Algorithm updates residual r_k using iterative formula, but recalculates -it from scratch after each 10 iterations. It is done to avoid accumulation -of numerical errors and to stop algorithm when r_k starts to grow. - -Such low update frequence (1/10) gives very little overhead, but makes -algorithm a bit more robust against numerical errors. However, you may -change it - -INPUT PARAMETERS: - Freq - desired update frequency, Freq>=0. - Zero value means that no updates will be done. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lincgsetrupdatefreq( - lincgstate state, - ae_int_t freq, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets starting point. -By default, zero starting point is used. - -INPUT PARAMETERS: - X - starting point, array[N] - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lincgsetstartingpoint( - lincgstate state, - real_1d_array x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinCGOptimize(). - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lincgsetxrep( - lincgstate state, - bool needxrep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Procedure for solution of A*x=b with sparse A. - -INPUT PARAMETERS: - State - algorithm state - A - sparse matrix in the CRS format (you MUST contvert it to - CRS format by calling SparseConvertToCRS() function). - IsUpper - whether upper or lower triangle of A is used: - * IsUpper=True => only upper triangle is used and lower - triangle is not referenced at all - * IsUpper=False => only lower triangle is used and upper - triangle is not referenced at all - B - right part, array[N] - -RESULT: - This function returns no result. - You can get solution by calling LinCGResults() - -NOTE: this function uses lightweight preconditioning - multiplication by - inverse of diag(A). If you want, you can turn preconditioning off by - calling LinCGSetPrecUnit(). However, preconditioning cost is low and - preconditioner is very important for solution of badly scaled - problems. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lincgsolvesparse( - lincgstate state, - sparsematrix a, - bool isupper, - real_1d_array b, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "solvers.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example illustrates solution of sparse linear systems with
-    // conjugate gradient method.
-    // 
-    // Suppose that we have linear system A*x=b with sparse symmetric
-    // positive definite A (represented by sparsematrix object)
-    //         [ 5 1       ]
-    //         [ 1 7 2     ]
-    //     A = [   2 8 1   ]
-    //         [     1 4 1 ]
-    //         [       1 4 ]
-    // and right part b
-    //     [  7 ]
-    //     [ 17 ]
-    // b = [ 14 ]
-    //     [ 10 ]
-    //     [  6 ]
-    // and we want to solve this system using sparse linear CG. In order
-    // to do so, we have to create left part (sparsematrix object) and
-    // right part (dense array).
-    //
-    // Initially, sparse matrix is created in the Hash-Table format,
-    // which allows easy initialization, but do not allow matrix to be
-    // used in the linear solvers. So after construction you should convert
-    // sparse matrix to CRS format (one suited for linear operations).
-    //
-    // It is important to note that in our example we initialize full
-    // matrix A, both lower and upper triangles. However, it is symmetric
-    // and sparse solver needs just one half of the matrix. So you may
-    // save about half of the space by filling only one of the triangles.
-    //
-    sparsematrix a;
-    sparsecreate(5, 5, a);
-    sparseset(a, 0, 0, 5.0);
-    sparseset(a, 0, 1, 1.0);
-    sparseset(a, 1, 0, 1.0);
-    sparseset(a, 1, 1, 7.0);
-    sparseset(a, 1, 2, 2.0);
-    sparseset(a, 2, 1, 2.0);
-    sparseset(a, 2, 2, 8.0);
-    sparseset(a, 2, 3, 1.0);
-    sparseset(a, 3, 2, 1.0);
-    sparseset(a, 3, 3, 4.0);
-    sparseset(a, 3, 4, 1.0);
-    sparseset(a, 4, 3, 1.0);
-    sparseset(a, 4, 4, 4.0);
-
-    //
-    // Now our matrix is fully initialized, but we have to do one more
-    // step - convert it from Hash-Table format to CRS format (see
-    // documentation on sparse matrices for more information about these
-    // formats).
-    //
-    // If you omit this call, ALGLIB will generate exception on the first
-    // attempt to use A in linear operations. 
-    //
-    sparseconverttocrs(a);
-
-    //
-    // Initialization of the right part
-    //
-    real_1d_array b = "[7,17,14,10,6]";
-
-    //
-    // Now we have to create linear solver object and to use it for the
-    // solution of the linear system.
-    //
-    // NOTE: lincgsolvesparse() accepts additional parameter which tells
-    //       what triangle of the symmetric matrix should be used - upper
-    //       or lower. Because we've filled both parts of the matrix, we
-    //       can use any part - upper or lower.
-    //
-    lincgstate s;
-    lincgreport rep;
-    real_1d_array x;
-    lincgcreate(5, s);
-    lincgsolvesparse(s, a, true, b);
-    lincgresults(s, x, rep);
-
-    printf("%d\n", int(rep.terminationtype)); // EXPECTED: 1
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [1.000,2.000,1.000,2.000,1.000]
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* - -*************************************************************************/ -
class linlsqrreport -{ - ae_int_t iterationscount; - ae_int_t nmv; - ae_int_t terminationtype; -}; - -
- -
-
/************************************************************************* -This object stores state of the LinLSQR method. - -You should use ALGLIB functions to work with this object. -*************************************************************************/ -
class linlsqrstate -{ -}; - -
- -
-
/************************************************************************* -This function initializes linear LSQR Solver. This solver is used to solve -non-symmetric (and, possibly, non-square) problems. Least squares solution -is returned for non-compatible systems. - -USAGE: -1. User initializes algorithm state with LinLSQRCreate() call -2. User tunes solver parameters with LinLSQRSetCond() and other functions -3. User calls LinLSQRSolveSparse() function which takes algorithm state - and SparseMatrix object. -4. User calls LinLSQRResults() to get solution -5. Optionally, user may call LinLSQRSolveSparse() again to solve another - problem with different matrix and/or right part without reinitializing - LinLSQRState structure. - -INPUT PARAMETERS: - M - number of rows in A - N - number of variables, N>0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: see also linlsqrcreatebuf() for version which reuses previously - allocated place as much as possible. - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::linlsqrcreate( - ae_int_t m, - ae_int_t n, - linlsqrstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function initializes linear LSQR Solver. It provides exactly same -functionality as linlsqrcreate(), but reuses previously allocated space -as much as possible. - -INPUT PARAMETERS: - M - number of rows in A - N - number of variables, N>0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 14.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::linlsqrcreatebuf( - ae_int_t m, - ae_int_t n, - linlsqrstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function is used to peek into LSQR solver and get current iteration -counter. You can safely "peek" into the solver from another thread. - -INPUT PARAMETERS: - S - solver object - -RESULT: - iteration counter, in [0,INF) - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::linlsqrpeekiterationscount( - linlsqrstate s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine submits request for termination of the running solver. It -can be called from some other thread which wants LSQR solver to terminate -(obviously, the thread running LSQR solver can not request termination -because it is already busy working on LSQR). - -As result, solver stops at point which was "current accepted" when -termination request was submitted and returns error code 8 (successful -termination). Such termination is a smooth process which properly -deallocates all temporaries. - -INPUT PARAMETERS: - State - solver structure - -NOTE: calling this function on solver which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - -NOTE: solver clears termination flag on its start, it means that if some - other thread will request termination too soon, its request will went - unnoticed. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::linlsqrrequesttermination( - linlsqrstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -LSQR solver: results. - -This function must be called after LinLSQRSolve - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[N], solution - Rep - optimization report: - * Rep.TerminationType completetion code: - * 1 ||Rk||<=EpsB*||B|| - * 4 ||A^T*Rk||/(||A||*||Rk||)<=EpsA - * 5 MaxIts steps was taken - * 7 rounding errors prevent further progress, - X contains best point found so far. - (sometimes returned on singular systems) - * 8 user requested termination via calling - linlsqrrequesttermination() - * Rep.IterationsCount contains iterations count - * NMV countains number of matrix-vector calculations - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::linlsqrresults( - linlsqrstate state, - real_1d_array& x, - linlsqrreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function sets stopping criteria. - -INPUT PARAMETERS: - EpsA - algorithm will be stopped if ||A^T*Rk||/(||A||*||Rk||)<=EpsA. - EpsB - algorithm will be stopped if ||Rk||<=EpsB*||B|| - MaxIts - algorithm will be stopped if number of iterations - more than MaxIts. - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: if EpsA,EpsB,EpsC and MaxIts are zero then these variables will -be setted as default values. - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::linlsqrsetcond( - linlsqrstate state, - double epsa, - double epsb, - ae_int_t maxits, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets optional Tikhonov regularization coefficient. -It is zero by default. - -INPUT PARAMETERS: - LambdaI - regularization factor, LambdaI>=0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::linlsqrsetlambdai( - linlsqrstate state, - double lambdai, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function changes preconditioning settings of LinCGSolveSparse() -function. LinCGSolveSparse() will use diagonal of the system matrix as -preconditioner. This preconditioning mode is active by default. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 19.11.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::linlsqrsetprecdiag( - linlsqrstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function changes preconditioning settings of LinLSQQSolveSparse() -function. By default, SolveSparse() uses diagonal preconditioner, but if -you want to use solver without preconditioning, you can call this function -which forces solver to use unit matrix for preconditioning. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 19.11.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::linlsqrsetprecunit( - linlsqrstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinCGOptimize(). - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::linlsqrsetxrep( - linlsqrstate state, - bool needxrep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Procedure for solution of A*x=b with sparse A. - -INPUT PARAMETERS: - State - algorithm state - A - sparse M*N matrix in the CRS format (you MUST contvert it - to CRS format by calling SparseConvertToCRS() function - BEFORE you pass it to this function). - B - right part, array[M] - -RESULT: - This function returns no result. - You can get solution by calling LinCGResults() - -NOTE: this function uses lightweight preconditioning - multiplication by - inverse of diag(A). If you want, you can turn preconditioning off by - calling LinLSQRSetPrecUnit(). However, preconditioning cost is low - and preconditioner is very important for solution of badly scaled - problems. - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::linlsqrsolvesparse( - linlsqrstate state, - sparsematrix a, - real_1d_array b, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "solvers.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example illustrates solution of sparse linear least squares problem
-    // with LSQR algorithm.
-    // 
-    // Suppose that we have least squares problem min|A*x-b| with sparse A
-    // represented by sparsematrix object
-    //         [ 1 1 ]
-    //         [ 1 1 ]
-    //     A = [ 2 1 ]
-    //         [ 1   ]
-    //         [   1 ]
-    // and right part b
-    //     [ 4 ]
-    //     [ 2 ]
-    // b = [ 4 ]
-    //     [ 1 ]
-    //     [ 2 ]
-    // and we want to solve this system in the least squares sense using
-    // LSQR algorithm. In order to do so, we have to create left part
-    // (sparsematrix object) and right part (dense array).
-    //
-    // Initially, sparse matrix is created in the Hash-Table format,
-    // which allows easy initialization, but do not allow matrix to be
-    // used in the linear solvers. So after construction you should convert
-    // sparse matrix to CRS format (one suited for linear operations).
-    //
-    sparsematrix a;
-    sparsecreate(5, 2, a);
-    sparseset(a, 0, 0, 1.0);
-    sparseset(a, 0, 1, 1.0);
-    sparseset(a, 1, 0, 1.0);
-    sparseset(a, 1, 1, 1.0);
-    sparseset(a, 2, 0, 2.0);
-    sparseset(a, 2, 1, 1.0);
-    sparseset(a, 3, 0, 1.0);
-    sparseset(a, 4, 1, 1.0);
-
-    //
-    // Now our matrix is fully initialized, but we have to do one more
-    // step - convert it from Hash-Table format to CRS format (see
-    // documentation on sparse matrices for more information about these
-    // formats).
-    //
-    // If you omit this call, ALGLIB will generate exception on the first
-    // attempt to use A in linear operations. 
-    //
-    sparseconverttocrs(a);
-
-    //
-    // Initialization of the right part
-    //
-    real_1d_array b = "[4,2,4,1,2]";
-
-    //
-    // Now we have to create linear solver object and to use it for the
-    // solution of the linear system.
-    //
-    linlsqrstate s;
-    linlsqrreport rep;
-    real_1d_array x;
-    linlsqrcreate(5, 2, s);
-    linlsqrsolvesparse(s, a, b);
-    linlsqrresults(s, x, rep);
-
-    printf("%d\n", int(rep.terminationtype)); // EXPECTED: 4
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [1.000,2.000]
-    return 0;
-}
-
-
-
-
- -linearmodel
-lrreport
- -lravgerror
-lravgrelerror
-lrbuild
-lrbuilds
-lrbuildz
-lrbuildzs
-lrpack
-lrprocess
-lrrmserror
-lrunpack
- - - -
linreg_d_basic Linear regression used to build the very basic model and unpack coefficients
- -
-
/************************************************************************* - -*************************************************************************/ -
class linearmodel -{ -}; - -
- -
-
/************************************************************************* -LRReport structure contains additional information about linear model: -* C - covariation matrix, array[0..NVars,0..NVars]. - C[i,j] = Cov(A[i],A[j]) -* RMSError - root mean square error on a training set -* AvgError - average error on a training set -* AvgRelError - average relative error on a training set (excluding - observations with zero function value). -* CVRMSError - leave-one-out cross-validation estimate of - generalization error. Calculated using fast algorithm - with O(NVars*NPoints) complexity. -* CVAvgError - cross-validation estimate of average error -* CVAvgRelError - cross-validation estimate of average relative error - -All other fields of the structure are intended for internal use and should -not be used outside ALGLIB. -*************************************************************************/ -
class lrreport -{ - real_2d_array c; - double rmserror; - double avgerror; - double avgrelerror; - double cvrmserror; - double cvavgerror; - double cvavgrelerror; - ae_int_t ncvdefects; - integer_1d_array cvdefects; -}; - -
- -
-
/************************************************************************* -Average error on the test set - -INPUT PARAMETERS: - LM - linear model - XY - test set - NPoints - test set size - -RESULT: - average error. - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -
double alglib::lravgerror( - linearmodel lm, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -RMS error on the test set - -INPUT PARAMETERS: - LM - linear model - XY - test set - NPoints - test set size - -RESULT: - average relative error. - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -
double alglib::lravgrelerror( - linearmodel lm, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Linear regression - -Subroutine builds model: - - Y = A(0)*X[0] + ... + A(N-1)*X[N-1] + A(N) - -and model found in ALGLIB format, covariation matrix, training set errors -(rms, average, average relative) and leave-one-out cross-validation -estimate of the generalization error. CV estimate calculated using fast -algorithm with O(NPoints*NVars) complexity. - -When covariation matrix is calculated standard deviations of function -values are assumed to be equal to RMS error on the training set. - -INPUT PARAMETERS: - XY - training set, array [0..NPoints-1,0..NVars]: - * NVars columns - independent variables - * last column - dependent variable - NPoints - training set size, NPoints>NVars+1 - NVars - number of independent variables - -OUTPUT PARAMETERS: - Info - return code: - * -255, in case of unknown internal error - * -4, if internal SVD subroutine haven't converged - * -1, if incorrect parameters was passed (NPoints<NVars+2, NVars<1). - * 1, if subroutine successfully finished - LM - linear model in the ALGLIB format. Use subroutines of - this unit to work with the model. - AR - additional results - - - -- ALGLIB -- - Copyright 02.08.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lrbuild( - real_2d_array xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t& info, - linearmodel& lm, - lrreport& ar, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Linear regression - -Variant of LRBuild which uses vector of standatd deviations (errors in -function values). - -INPUT PARAMETERS: - XY - training set, array [0..NPoints-1,0..NVars]: - * NVars columns - independent variables - * last column - dependent variable - S - standard deviations (errors in function values) - array[0..NPoints-1], S[i]>0. - NPoints - training set size, NPoints>NVars+1 - NVars - number of independent variables - -OUTPUT PARAMETERS: - Info - return code: - * -255, in case of unknown internal error - * -4, if internal SVD subroutine haven't converged - * -1, if incorrect parameters was passed (NPoints<NVars+2, NVars<1). - * -2, if S[I]<=0 - * 1, if subroutine successfully finished - LM - linear model in the ALGLIB format. Use subroutines of - this unit to work with the model. - AR - additional results - - - -- ALGLIB -- - Copyright 02.08.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lrbuilds( - real_2d_array xy, - real_1d_array s, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t& info, - linearmodel& lm, - lrreport& ar, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Like LRBuild but builds model - - Y = A(0)*X[0] + ... + A(N-1)*X[N-1] - -i.e. with zero constant term. - - -- ALGLIB -- - Copyright 30.10.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lrbuildz( - real_2d_array xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t& info, - linearmodel& lm, - lrreport& ar, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Like LRBuildS, but builds model - - Y = A(0)*X[0] + ... + A(N-1)*X[N-1] - -i.e. with zero constant term. - - -- ALGLIB -- - Copyright 30.10.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lrbuildzs( - real_2d_array xy, - real_1d_array s, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t& info, - linearmodel& lm, - lrreport& ar, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -"Packs" coefficients and creates linear model in ALGLIB format (LRUnpack -reversed). - -INPUT PARAMETERS: - V - coefficients, array[0..NVars] - NVars - number of independent variables - -OUTPUT PAREMETERS: - LM - linear model. - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lrpack( - real_1d_array v, - ae_int_t nvars, - linearmodel& lm, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Procesing - -INPUT PARAMETERS: - LM - linear model - X - input vector, array[0..NVars-1]. - -Result: - value of linear model regression estimate - - -- ALGLIB -- - Copyright 03.09.2008 by Bochkanov Sergey -*************************************************************************/ -
double alglib::lrprocess( - linearmodel lm, - real_1d_array x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -RMS error on the test set - -INPUT PARAMETERS: - LM - linear model - XY - test set - NPoints - test set size - -RESULT: - root mean square error. - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -
double alglib::lrrmserror( - linearmodel lm, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Unpacks coefficients of linear model. - -INPUT PARAMETERS: - LM - linear model in ALGLIB format - -OUTPUT PARAMETERS: - V - coefficients, array[0..NVars] - constant term (intercept) is stored in the V[NVars]. - NVars - number of independent variables (one less than number - of coefficients) - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lrunpack( - linearmodel lm, - real_1d_array& v, - ae_int_t& nvars, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // In this example we demonstrate linear fitting by f(x|a) = a*exp(0.5*x).
-    //
-    // We have:
-    // * xy - matrix of basic function values (exp(0.5*x)) and expected values
-    //
-    real_2d_array xy = "[[0.606531,1.133719],[0.670320,1.306522],[0.740818,1.504604],[0.818731,1.554663],[0.904837,1.884638],[1.000000,2.072436],[1.105171,2.257285],[1.221403,2.534068],[1.349859,2.622017],[1.491825,2.897713],[1.648721,3.219371]]";
-    ae_int_t info;
-    ae_int_t nvars;
-    linearmodel model;
-    lrreport rep;
-    real_1d_array c;
-
-    lrbuildz(xy, 11, 1, info, model, rep);
-    printf("%d\n", int(info)); // EXPECTED: 1
-    lrunpack(model, c, nvars);
-    printf("%s\n", c.tostring(4).c_str()); // EXPECTED: [1.98650,0.00000]
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* - -*************************************************************************/ -
class logitmodel -{ -}; - -
- -
-
/************************************************************************* -MNLReport structure contains information about training process: -* NGrad - number of gradient calculations -* NHess - number of Hessian calculations -*************************************************************************/ -
class mnlreport -{ - ae_int_t ngrad; - ae_int_t nhess; -}; - -
- -
-
/************************************************************************* -Average cross-entropy (in bits per element) on the test set - -INPUT PARAMETERS: - LM - logit model - XY - test set - NPoints - test set size - -RESULT: - CrossEntropy/(NPoints*ln(2)). - - -- ALGLIB -- - Copyright 10.09.2008 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mnlavgce( - logitmodel lm, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Average error on the test set - -INPUT PARAMETERS: - LM - logit model - XY - test set - NPoints - test set size - -RESULT: - average error (error when estimating posterior probabilities). - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mnlavgerror( - logitmodel lm, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Average relative error on the test set - -INPUT PARAMETERS: - LM - logit model - XY - test set - NPoints - test set size - -RESULT: - average relative error (error when estimating posterior probabilities). - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mnlavgrelerror( - logitmodel lm, - real_2d_array xy, - ae_int_t ssize, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Classification error on test set = MNLRelClsError*NPoints - - -- ALGLIB -- - Copyright 10.09.2008 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::mnlclserror( - logitmodel lm, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -"Packs" coefficients and creates logit model in ALGLIB format (MNLUnpack -reversed). - -INPUT PARAMETERS: - A - model (see MNLUnpack) - NVars - number of independent variables - NClasses - number of classes - -OUTPUT PARAMETERS: - LM - logit model. - - -- ALGLIB -- - Copyright 10.09.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mnlpack( - real_2d_array a, - ae_int_t nvars, - ae_int_t nclasses, - logitmodel& lm, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Procesing - -INPUT PARAMETERS: - LM - logit model, passed by non-constant reference - (some fields of structure are used as temporaries - when calculating model output). - X - input vector, array[0..NVars-1]. - Y - (possibly) preallocated buffer; if size of Y is less than - NClasses, it will be reallocated.If it is large enough, it - is NOT reallocated, so we can save some time on reallocation. - -OUTPUT PARAMETERS: - Y - result, array[0..NClasses-1] - Vector of posterior probabilities for classification task. - - -- ALGLIB -- - Copyright 10.09.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mnlprocess( - logitmodel lm, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -'interactive' variant of MNLProcess for languages like Python which -support constructs like "Y = MNLProcess(LM,X)" and interactive mode of the -interpreter - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 10.09.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mnlprocessi( - logitmodel lm, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Relative classification error on the test set - -INPUT PARAMETERS: - LM - logit model - XY - test set - NPoints - test set size - -RESULT: - percent of incorrectly classified cases. - - -- ALGLIB -- - Copyright 10.09.2008 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mnlrelclserror( - logitmodel lm, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -RMS error on the test set - -INPUT PARAMETERS: - LM - logit model - XY - test set - NPoints - test set size - -RESULT: - root mean square error (error when estimating posterior probabilities). - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mnlrmserror( - logitmodel lm, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine trains logit model. - -INPUT PARAMETERS: - XY - training set, array[0..NPoints-1,0..NVars] - First NVars columns store values of independent - variables, next column stores number of class (from 0 - to NClasses-1) which dataset element belongs to. Fractional - values are rounded to nearest integer. - NPoints - training set size, NPoints>=1 - NVars - number of independent variables, NVars>=1 - NClasses - number of classes, NClasses>=2 - -OUTPUT PARAMETERS: - Info - return code: - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed - (NPoints<NVars+2, NVars<1, NClasses<2). - * 1, if task has been solved - LM - model built - Rep - training report - - -- ALGLIB -- - Copyright 10.09.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mnltrainh( - real_2d_array xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - ae_int_t& info, - logitmodel& lm, - mnlreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Unpacks coefficients of logit model. Logit model have form: - - P(class=i) = S(i) / (S(0) + S(1) + ... +S(M-1)) - S(i) = Exp(A[i,0]*X[0] + ... + A[i,N-1]*X[N-1] + A[i,N]), when i<M-1 - S(M-1) = 1 - -INPUT PARAMETERS: - LM - logit model in ALGLIB format - -OUTPUT PARAMETERS: - V - coefficients, array[0..NClasses-2,0..NVars] - NVars - number of independent variables - NClasses - number of classes - - -- ALGLIB -- - Copyright 10.09.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mnlunpack( - logitmodel lm, - real_2d_array& a, - ae_int_t& nvars, - ae_int_t& nclasses, - const xparams _params = alglib::xdefault); - -
- -
- -barycentricfitreport
-lsfitreport
-lsfitstate
-polynomialfitreport
- -barycentricfitfloaterhormann
-barycentricfitfloaterhormannwc
-logisticcalc4
-logisticcalc5
-logisticfit4
-logisticfit45x
-logisticfit4ec
-logisticfit5
-logisticfit5ec
-lsfitcreatef
-lsfitcreatefg
-lsfitcreatefgh
-lsfitcreatewf
-lsfitcreatewfg
-lsfitcreatewfgh
-lsfitfit
-lsfitlinear
-lsfitlinearc
-lsfitlinearw
-lsfitlinearwc
-lsfitresults
-lsfitsetbc
-lsfitsetcond
-lsfitsetgradientcheck
-lsfitsetlc
-lsfitsetscale
-lsfitsetstpmax
-lsfitsetxrep
-lstfitpiecewiselinearrdp
-lstfitpiecewiselinearrdpfixed
-polynomialfit
-polynomialfitwc
-spline1dfitcubic
-spline1dfitcubicwc
-spline1dfithermite
-spline1dfithermitewc
- - - - - - - - - - - - - - -
lsfit_d_lin Unconstrained (general) linear least squares fitting with and without weights
lsfit_d_linc Constrained (general) linear least squares fitting with and without weights
lsfit_d_nlf Nonlinear fitting using function value only
lsfit_d_nlfb Bound contstrained nonlinear fitting using function value only
lsfit_d_nlfg Nonlinear fitting using gradient
lsfit_d_nlfgh Nonlinear fitting using gradient and Hessian
lsfit_d_nlscale Nonlinear fitting with custom scaling and bound constraints
lsfit_d_pol Unconstrained polynomial fitting
lsfit_d_polc Constrained polynomial fitting
lsfit_d_spline Unconstrained fitting by penalized regression spline
lsfit_t_4pl 4-parameter logistic fitting
lsfit_t_5pl 5-parameter logistic fitting
- -
-
/************************************************************************* -Barycentric fitting report: - RMSError RMS error - AvgError average error - AvgRelError average relative error (for non-zero Y[I]) - MaxError maximum error - TaskRCond reciprocal of task's condition number -*************************************************************************/ -
class barycentricfitreport -{ - double taskrcond; - ae_int_t dbest; - double rmserror; - double avgerror; - double avgrelerror; - double maxerror; -}; - -
- -
-
/************************************************************************* -Least squares fitting report. This structure contains informational fields -which are set by fitting functions provided by this unit. - -Different functions initialize different sets of fields, so you should -read documentation on specific function you used in order to know which -fields are initialized. - - TaskRCond reciprocal of task's condition number - IterationsCount number of internal iterations - - VarIdx if user-supplied gradient contains errors which were - detected by nonlinear fitter, this field is set to - index of the first component of gradient which is - suspected to be spoiled by bugs. - - RMSError RMS error - AvgError average error - AvgRelError average relative error (for non-zero Y[I]) - MaxError maximum error - - WRMSError weighted RMS error - - CovPar covariance matrix for parameters, filled by some solvers - ErrPar vector of errors in parameters, filled by some solvers - ErrCurve vector of fit errors - variability of the best-fit - curve, filled by some solvers. - Noise vector of per-point noise estimates, filled by - some solvers. - R2 coefficient of determination (non-weighted, non-adjusted), - filled by some solvers. -*************************************************************************/ -
class lsfitreport -{ - double taskrcond; - ae_int_t iterationscount; - ae_int_t varidx; - double rmserror; - double avgerror; - double avgrelerror; - double maxerror; - double wrmserror; - real_2d_array covpar; - real_1d_array errpar; - real_1d_array errcurve; - real_1d_array noise; - double r2; -}; - -
- -
-
/************************************************************************* -Nonlinear fitter. - -You should use ALGLIB functions to work with fitter. -Never try to access its fields directly! -*************************************************************************/ -
class lsfitstate -{ -}; - -
- -
-
/************************************************************************* -Polynomial fitting report: - TaskRCond reciprocal of task's condition number - RMSError RMS error - AvgError average error - AvgRelError average relative error (for non-zero Y[I]) - MaxError maximum error -*************************************************************************/ -
class polynomialfitreport -{ - double taskrcond; - double rmserror; - double avgerror; - double avgrelerror; - double maxerror; -}; - -
- -
-
/************************************************************************* -Rational least squares fitting using Floater-Hormann rational functions -with optimal D chosen from [0,9]. - -Equidistant grid with M node on [min(x),max(x)] is used to build basis -functions. Different values of D are tried, optimal D (least root mean -square error) is chosen. Task is linear, so linear least squares solver -is used. Complexity of this computational scheme is O(N*M^2) (mostly -dominated by the least squares solver). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - N - number of points, N>0. - M - number of basis functions ( = number_of_nodes), M>=2. - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearWC() subroutine. - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - B - barycentric interpolant. - Rep - report, same format as in LSFitLinearWC() subroutine. - Following fields are set: - * DBest best value of the D parameter - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::barycentricfitfloaterhormann( - real_1d_array x, - real_1d_array y, - ae_int_t n, - ae_int_t m, - ae_int_t& info, - barycentricinterpolant& b, - barycentricfitreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Weghted rational least squares fitting using Floater-Hormann rational -functions with optimal D chosen from [0,9], with constraints and -individual weights. - -Equidistant grid with M node on [min(x),max(x)] is used to build basis -functions. Different values of D are tried, optimal D (least WEIGHTED root -mean square error) is chosen. Task is linear, so linear least squares -solver is used. Complexity of this computational scheme is O(N*M^2) -(mostly dominated by the least squares solver). - -SEE ALSO -* BarycentricFitFloaterHormann(), "lightweight" fitting without invididual - weights and constraints. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - W - weights, array[0..N-1] - Each summand in square sum of approximation deviations from - given values is multiplied by the square of corresponding - weight. Fill it by 1's if you don't want to solve weighted - task. - N - number of points, N>0. - XC - points where function values/derivatives are constrained, - array[0..K-1]. - YC - values of constraints, array[0..K-1] - DC - array[0..K-1], types of constraints: - * DC[i]=0 means that S(XC[i])=YC[i] - * DC[i]=1 means that S'(XC[i])=YC[i] - SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS - K - number of constraints, 0<=K<M. - K=0 means no constraints (XC/YC/DC are not used in such cases) - M - number of basis functions ( = number_of_nodes), M>=2. - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearWC() subroutine. - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - -1 means another errors in parameters passed - (N<=0, for example) - B - barycentric interpolant. - Rep - report, same format as in LSFitLinearWC() subroutine. - Following fields are set: - * DBest best value of the D parameter - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroutine doesn't calculate task's condition number for K<>0. - -SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: - -Setting constraints can lead to undesired results, like ill-conditioned -behavior, or inconsistency being detected. From the other side, it allows -us to improve quality of the fit. Here we summarize our experience with -constrained barycentric interpolants: -* excessive constraints can be inconsistent. Floater-Hormann basis - functions aren't as flexible as splines (although they are very smooth). -* the more evenly constraints are spread across [min(x),max(x)], the more - chances that they will be consistent -* the greater is M (given fixed constraints), the more chances that - constraints will be consistent -* in the general case, consistency of constraints IS NOT GUARANTEED. -* in the several special cases, however, we CAN guarantee consistency. -* one of this cases is constraints on the function VALUES at the interval - boundaries. Note that consustency of the constraints on the function - DERIVATIVES is NOT guaranteed (you can use in such cases cubic splines - which are more flexible). -* another special case is ONE constraint on the function value (OR, but - not AND, derivative) anywhere in the interval - -Our final recommendation is to use constraints WHEN AND ONLY WHEN you -can't solve your task without them. Anything beyond special cases given -above is not guaranteed and may result in inconsistency. - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::barycentricfitfloaterhormannwc( - real_1d_array x, - real_1d_array y, - real_1d_array w, - ae_int_t n, - real_1d_array xc, - real_1d_array yc, - integer_1d_array dc, - ae_int_t k, - ae_int_t m, - ae_int_t& info, - barycentricinterpolant& b, - barycentricfitreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates value of four-parameter logistic (4PL) model at -specified point X. 4PL model has following form: - - F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B)) - -INPUT PARAMETERS: - X - current point, X>=0: - * zero X is correctly handled even for B<=0 - * negative X results in exception. - A, B, C, D- parameters of 4PL model: - * A is unconstrained - * B is unconstrained; zero or negative values are handled - correctly. - * C>0, non-positive value results in exception - * D is unconstrained - -RESULT: - model value at X - -NOTE: if B=0, denominator is assumed to be equal to 2.0 even for zero X - (strictly speaking, 0^0 is undefined). - -NOTE: this function also throws exception if all input parameters are - correct, but overflow was detected during calculations. - -NOTE: this function performs a lot of checks; if you need really high - performance, consider evaluating model yourself, without checking - for degenerate cases. - - - -- ALGLIB PROJECT -- - Copyright 14.05.2014 by Bochkanov Sergey -*************************************************************************/ -
double alglib::logisticcalc4( - double x, - double a, - double b, - double c, - double d, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function calculates value of five-parameter logistic (5PL) model at -specified point X. 5PL model has following form: - - F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G) - -INPUT PARAMETERS: - X - current point, X>=0: - * zero X is correctly handled even for B<=0 - * negative X results in exception. - A, B, C, D, G- parameters of 5PL model: - * A is unconstrained - * B is unconstrained; zero or negative values are handled - correctly. - * C>0, non-positive value results in exception - * D is unconstrained - * G>0, non-positive value results in exception - -RESULT: - model value at X - -NOTE: if B=0, denominator is assumed to be equal to Power(2.0,G) even for - zero X (strictly speaking, 0^0 is undefined). - -NOTE: this function also throws exception if all input parameters are - correct, but overflow was detected during calculations. - -NOTE: this function performs a lot of checks; if you need really high - performance, consider evaluating model yourself, without checking - for degenerate cases. - - - -- ALGLIB PROJECT -- - Copyright 14.05.2014 by Bochkanov Sergey -*************************************************************************/ -
double alglib::logisticcalc5( - double x, - double a, - double b, - double c, - double d, - double g, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function fits four-parameter logistic (4PL) model to data provided -by user. 4PL model has following form: - - F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B)) - -Here: - * A, D - unconstrained (see LogisticFit4EC() for constrained 4PL) - * B>=0 - * C>0 - -IMPORTANT: output of this function is constrained in such way that B>0. - Because 4PL model is symmetric with respect to B, there is no - need to explore B<0. Constraining B makes algorithm easier - to stabilize and debug. - Users who for some reason prefer to work with negative B's - should transform output themselves (swap A and D, replace B by - -B). - -4PL fitting is implemented as follows: -* we perform small number of restarts from random locations which helps to - solve problem of bad local extrema. Locations are only partially random - - we use input data to determine good initial guess, but we include - controlled amount of randomness. -* we perform Levenberg-Marquardt fitting with very tight constraints on - parameters B and C - it allows us to find good initial guess for the - second stage without risk of running into "flat spot". -* second Levenberg-Marquardt round is performed without excessive - constraints. Results from the previous round are used as initial guess. -* after fitting is done, we compare results with best values found so far, - rewrite "best solution" if needed, and move to next random location. - -Overall algorithm is very stable and is not prone to bad local extrema. -Furthermore, it automatically scales when input data have very large or -very small range. - -INPUT PARAMETERS: - X - array[N], stores X-values. - MUST include only non-negative numbers (but may include - zero values). Can be unsorted. - Y - array[N], values to fit. - N - number of points. If N is less than length of X/Y, only - leading N elements are used. - -OUTPUT PARAMETERS: - A, B, C, D- parameters of 4PL model - Rep - fitting report. This structure has many fields, but ONLY - ONES LISTED BELOW ARE SET: - * Rep.IterationsCount - number of iterations performed - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average absolute error - * Rep.AvgRelError - average relative error (calculated for - non-zero Y-values) - * Rep.MaxError - maximum absolute error - * Rep.R2 - coefficient of determination, R-squared. This - coefficient is calculated as R2=1-RSS/TSS (in case - of nonlinear regression there are multiple ways to - define R2, each of them giving different results). - -NOTE: for stability reasons the B parameter is restricted by [1/1000,1000] - range. It prevents algorithm from making trial steps deep into the - area of bad parameters. - -NOTE: after you obtained coefficients, you can evaluate model with - LogisticCalc4() function. - -NOTE: if you need better control over fitting process than provided by this - function, you may use LogisticFit45X(). - -NOTE: step is automatically scaled according to scale of parameters being - fitted before we compare its length with EpsX. Thus, this function - can be used to fit data with very small or very large values without - changing EpsX. - - - -- ALGLIB PROJECT -- - Copyright 14.02.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::logisticfit4( - real_1d_array x, - real_1d_array y, - ae_int_t n, - double& a, - double& b, - double& c, - double& d, - lsfitreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This is "expert" 4PL/5PL fitting function, which can be used if you need -better control over fitting process than provided by LogisticFit4() or -LogisticFit5(). - -This function fits model of the form - - F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B)) (4PL model) - -or - - F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G) (5PL model) - -Here: - * A, D - unconstrained - * B>=0 for 4PL, unconstrained for 5PL - * C>0 - * G>0 (if present) - -INPUT PARAMETERS: - X - array[N], stores X-values. - MUST include only non-negative numbers (but may include - zero values). Can be unsorted. - Y - array[N], values to fit. - N - number of points. If N is less than length of X/Y, only - leading N elements are used. - CnstrLeft- optional equality constraint for model value at the left - boundary (at X=0). Specify NAN (Not-a-Number) if you do - not need constraint on the model value at X=0 (in C++ you - can pass alglib::fp_nan as parameter, in C# it will be - Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - CnstrRight- optional equality constraint for model value at X=infinity. - Specify NAN (Not-a-Number) if you do not need constraint - on the model value (in C++ you can pass alglib::fp_nan as - parameter, in C# it will be Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - Is4PL - whether 4PL or 5PL models are fitted - LambdaV - regularization coefficient, LambdaV>=0. - Set it to zero unless you know what you are doing. - EpsX - stopping condition (step size), EpsX>=0. - Zero value means that small step is automatically chosen. - See notes below for more information. - RsCnt - number of repeated restarts from random points. 4PL/5PL - models are prone to problem of bad local extrema. Utilizing - multiple random restarts allows us to improve algorithm - convergence. - RsCnt>=0. - Zero value means that function automatically choose small - amount of restarts (recommended). - -OUTPUT PARAMETERS: - A, B, C, D- parameters of 4PL model - G - parameter of 5PL model; for Is4PL=True, G=1 is returned. - Rep - fitting report. This structure has many fields, but ONLY - ONES LISTED BELOW ARE SET: - * Rep.IterationsCount - number of iterations performed - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average absolute error - * Rep.AvgRelError - average relative error (calculated for - non-zero Y-values) - * Rep.MaxError - maximum absolute error - * Rep.R2 - coefficient of determination, R-squared. This - coefficient is calculated as R2=1-RSS/TSS (in case - of nonlinear regression there are multiple ways to - define R2, each of them giving different results). - -NOTE: for better stability B parameter is restricted by [+-1/1000,+-1000] - range, and G is restricted by [1/10,10] range. It prevents algorithm - from making trial steps deep into the area of bad parameters. - -NOTE: after you obtained coefficients, you can evaluate model with - LogisticCalc5() function. - -NOTE: step is automatically scaled according to scale of parameters being - fitted before we compare its length with EpsX. Thus, this function - can be used to fit data with very small or very large values without - changing EpsX. - -EQUALITY CONSTRAINTS ON PARAMETERS - -4PL/5PL solver supports equality constraints on model values at the left -boundary (X=0) and right boundary (X=infinity). These constraints are -completely optional and you can specify both of them, only one - or no -constraints at all. - -Parameter CnstrLeft contains left constraint (or NAN for unconstrained -fitting), and CnstrRight contains right one. For 4PL, left constraint -ALWAYS corresponds to parameter A, and right one is ALWAYS constraint on -D. That's because 4PL model is normalized in such way that B>=0. - -For 5PL model things are different. Unlike 4PL one, 5PL model is NOT -symmetric with respect to change in sign of B. Thus, negative B's are -possible, and left constraint may constrain parameter A (for positive B's) -- or parameter D (for negative B's). Similarly changes meaning of right -constraint. - -You do not have to decide what parameter to constrain - algorithm will -automatically determine correct parameters as fitting progresses. However, -question highlighted above is important when you interpret fitting results. - - - -- ALGLIB PROJECT -- - Copyright 14.02.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::logisticfit45x( - real_1d_array x, - real_1d_array y, - ae_int_t n, - double cnstrleft, - double cnstrright, - bool is4pl, - double lambdav, - double epsx, - ae_int_t rscnt, - double& a, - double& b, - double& c, - double& d, - double& g, - lsfitreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function fits four-parameter logistic (4PL) model to data provided -by user, with optional constraints on parameters A and D. 4PL model has -following form: - - F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B)) - -Here: - * A, D - with optional equality constraints - * B>=0 - * C>0 - -IMPORTANT: output of this function is constrained in such way that B>0. - Because 4PL model is symmetric with respect to B, there is no - need to explore B<0. Constraining B makes algorithm easier - to stabilize and debug. - Users who for some reason prefer to work with negative B's - should transform output themselves (swap A and D, replace B by - -B). - -4PL fitting is implemented as follows: -* we perform small number of restarts from random locations which helps to - solve problem of bad local extrema. Locations are only partially random - - we use input data to determine good initial guess, but we include - controlled amount of randomness. -* we perform Levenberg-Marquardt fitting with very tight constraints on - parameters B and C - it allows us to find good initial guess for the - second stage without risk of running into "flat spot". -* second Levenberg-Marquardt round is performed without excessive - constraints. Results from the previous round are used as initial guess. -* after fitting is done, we compare results with best values found so far, - rewrite "best solution" if needed, and move to next random location. - -Overall algorithm is very stable and is not prone to bad local extrema. -Furthermore, it automatically scales when input data have very large or -very small range. - -INPUT PARAMETERS: - X - array[N], stores X-values. - MUST include only non-negative numbers (but may include - zero values). Can be unsorted. - Y - array[N], values to fit. - N - number of points. If N is less than length of X/Y, only - leading N elements are used. - CnstrLeft- optional equality constraint for model value at the left - boundary (at X=0). Specify NAN (Not-a-Number) if you do - not need constraint on the model value at X=0 (in C++ you - can pass alglib::fp_nan as parameter, in C# it will be - Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - CnstrRight- optional equality constraint for model value at X=infinity. - Specify NAN (Not-a-Number) if you do not need constraint - on the model value (in C++ you can pass alglib::fp_nan as - parameter, in C# it will be Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - -OUTPUT PARAMETERS: - A, B, C, D- parameters of 4PL model - Rep - fitting report. This structure has many fields, but ONLY - ONES LISTED BELOW ARE SET: - * Rep.IterationsCount - number of iterations performed - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average absolute error - * Rep.AvgRelError - average relative error (calculated for - non-zero Y-values) - * Rep.MaxError - maximum absolute error - * Rep.R2 - coefficient of determination, R-squared. This - coefficient is calculated as R2=1-RSS/TSS (in case - of nonlinear regression there are multiple ways to - define R2, each of them giving different results). - -NOTE: for stability reasons the B parameter is restricted by [1/1000,1000] - range. It prevents algorithm from making trial steps deep into the - area of bad parameters. - -NOTE: after you obtained coefficients, you can evaluate model with - LogisticCalc4() function. - -NOTE: if you need better control over fitting process than provided by this - function, you may use LogisticFit45X(). - -NOTE: step is automatically scaled according to scale of parameters being - fitted before we compare its length with EpsX. Thus, this function - can be used to fit data with very small or very large values without - changing EpsX. - -EQUALITY CONSTRAINTS ON PARAMETERS - -4PL/5PL solver supports equality constraints on model values at the left -boundary (X=0) and right boundary (X=infinity). These constraints are -completely optional and you can specify both of them, only one - or no -constraints at all. - -Parameter CnstrLeft contains left constraint (or NAN for unconstrained -fitting), and CnstrRight contains right one. For 4PL, left constraint -ALWAYS corresponds to parameter A, and right one is ALWAYS constraint on -D. That's because 4PL model is normalized in such way that B>=0. - - - -- ALGLIB PROJECT -- - Copyright 14.02.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::logisticfit4ec( - real_1d_array x, - real_1d_array y, - ae_int_t n, - double cnstrleft, - double cnstrright, - double& a, - double& b, - double& c, - double& d, - lsfitreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function fits five-parameter logistic (5PL) model to data provided -by user. 5PL model has following form: - - F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G) - -Here: - * A, D - unconstrained - * B - unconstrained - * C>0 - * G>0 - -IMPORTANT: unlike in 4PL fitting, output of this function is NOT - constrained in such way that B is guaranteed to be positive. - Furthermore, unlike 4PL, 5PL model is NOT symmetric with - respect to B, so you can NOT transform model to equivalent one, - with B having desired sign (>0 or <0). - -5PL fitting is implemented as follows: -* we perform small number of restarts from random locations which helps to - solve problem of bad local extrema. Locations are only partially random - - we use input data to determine good initial guess, but we include - controlled amount of randomness. -* we perform Levenberg-Marquardt fitting with very tight constraints on - parameters B and C - it allows us to find good initial guess for the - second stage without risk of running into "flat spot". Parameter G is - fixed at G=1. -* second Levenberg-Marquardt round is performed without excessive - constraints on B and C, but with G still equal to 1. Results from the - previous round are used as initial guess. -* third Levenberg-Marquardt round relaxes constraints on G and tries two - different models - one with B>0 and one with B<0. -* after fitting is done, we compare results with best values found so far, - rewrite "best solution" if needed, and move to next random location. - -Overall algorithm is very stable and is not prone to bad local extrema. -Furthermore, it automatically scales when input data have very large or -very small range. - -INPUT PARAMETERS: - X - array[N], stores X-values. - MUST include only non-negative numbers (but may include - zero values). Can be unsorted. - Y - array[N], values to fit. - N - number of points. If N is less than length of X/Y, only - leading N elements are used. - -OUTPUT PARAMETERS: - A,B,C,D,G- parameters of 5PL model - Rep - fitting report. This structure has many fields, but ONLY - ONES LISTED BELOW ARE SET: - * Rep.IterationsCount - number of iterations performed - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average absolute error - * Rep.AvgRelError - average relative error (calculated for - non-zero Y-values) - * Rep.MaxError - maximum absolute error - * Rep.R2 - coefficient of determination, R-squared. This - coefficient is calculated as R2=1-RSS/TSS (in case - of nonlinear regression there are multiple ways to - define R2, each of them giving different results). - -NOTE: for better stability B parameter is restricted by [+-1/1000,+-1000] - range, and G is restricted by [1/10,10] range. It prevents algorithm - from making trial steps deep into the area of bad parameters. - -NOTE: after you obtained coefficients, you can evaluate model with - LogisticCalc5() function. - -NOTE: if you need better control over fitting process than provided by this - function, you may use LogisticFit45X(). - -NOTE: step is automatically scaled according to scale of parameters being - fitted before we compare its length with EpsX. Thus, this function - can be used to fit data with very small or very large values without - changing EpsX. - - - -- ALGLIB PROJECT -- - Copyright 14.02.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::logisticfit5( - real_1d_array x, - real_1d_array y, - ae_int_t n, - double& a, - double& b, - double& c, - double& d, - double& g, - lsfitreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function fits five-parameter logistic (5PL) model to data provided -by user, subject to optional equality constraints on parameters A and D. -5PL model has following form: - - F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G) - -Here: - * A, D - with optional equality constraints - * B - unconstrained - * C>0 - * G>0 - -IMPORTANT: unlike in 4PL fitting, output of this function is NOT - constrained in such way that B is guaranteed to be positive. - Furthermore, unlike 4PL, 5PL model is NOT symmetric with - respect to B, so you can NOT transform model to equivalent one, - with B having desired sign (>0 or <0). - -5PL fitting is implemented as follows: -* we perform small number of restarts from random locations which helps to - solve problem of bad local extrema. Locations are only partially random - - we use input data to determine good initial guess, but we include - controlled amount of randomness. -* we perform Levenberg-Marquardt fitting with very tight constraints on - parameters B and C - it allows us to find good initial guess for the - second stage without risk of running into "flat spot". Parameter G is - fixed at G=1. -* second Levenberg-Marquardt round is performed without excessive - constraints on B and C, but with G still equal to 1. Results from the - previous round are used as initial guess. -* third Levenberg-Marquardt round relaxes constraints on G and tries two - different models - one with B>0 and one with B<0. -* after fitting is done, we compare results with best values found so far, - rewrite "best solution" if needed, and move to next random location. - -Overall algorithm is very stable and is not prone to bad local extrema. -Furthermore, it automatically scales when input data have very large or -very small range. - -INPUT PARAMETERS: - X - array[N], stores X-values. - MUST include only non-negative numbers (but may include - zero values). Can be unsorted. - Y - array[N], values to fit. - N - number of points. If N is less than length of X/Y, only - leading N elements are used. - CnstrLeft- optional equality constraint for model value at the left - boundary (at X=0). Specify NAN (Not-a-Number) if you do - not need constraint on the model value at X=0 (in C++ you - can pass alglib::fp_nan as parameter, in C# it will be - Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - CnstrRight- optional equality constraint for model value at X=infinity. - Specify NAN (Not-a-Number) if you do not need constraint - on the model value (in C++ you can pass alglib::fp_nan as - parameter, in C# it will be Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - -OUTPUT PARAMETERS: - A,B,C,D,G- parameters of 5PL model - Rep - fitting report. This structure has many fields, but ONLY - ONES LISTED BELOW ARE SET: - * Rep.IterationsCount - number of iterations performed - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average absolute error - * Rep.AvgRelError - average relative error (calculated for - non-zero Y-values) - * Rep.MaxError - maximum absolute error - * Rep.R2 - coefficient of determination, R-squared. This - coefficient is calculated as R2=1-RSS/TSS (in case - of nonlinear regression there are multiple ways to - define R2, each of them giving different results). - -NOTE: for better stability B parameter is restricted by [+-1/1000,+-1000] - range, and G is restricted by [1/10,10] range. It prevents algorithm - from making trial steps deep into the area of bad parameters. - -NOTE: after you obtained coefficients, you can evaluate model with - LogisticCalc5() function. - -NOTE: if you need better control over fitting process than provided by this - function, you may use LogisticFit45X(). - -NOTE: step is automatically scaled according to scale of parameters being - fitted before we compare its length with EpsX. Thus, this function - can be used to fit data with very small or very large values without - changing EpsX. - -EQUALITY CONSTRAINTS ON PARAMETERS - -5PL solver supports equality constraints on model values at the left -boundary (X=0) and right boundary (X=infinity). These constraints are -completely optional and you can specify both of them, only one - or no -constraints at all. - -Parameter CnstrLeft contains left constraint (or NAN for unconstrained -fitting), and CnstrRight contains right one. - -Unlike 4PL one, 5PL model is NOT symmetric with respect to change in sign -of B. Thus, negative B's are possible, and left constraint may constrain -parameter A (for positive B's) - or parameter D (for negative B's). -Similarly changes meaning of right constraint. - -You do not have to decide what parameter to constrain - algorithm will -automatically determine correct parameters as fitting progresses. However, -question highlighted above is important when you interpret fitting results. - - - -- ALGLIB PROJECT -- - Copyright 14.02.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::logisticfit5ec( - real_1d_array x, - real_1d_array y, - ae_int_t n, - double cnstrleft, - double cnstrright, - double& a, - double& b, - double& c, - double& d, - double& g, - lsfitreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Nonlinear least squares fitting using function values only. - -Combination of numerical differentiation and secant updates is used to -obtain function Jacobian. - -Nonlinear task min(F(c)) is solved, where - - F(c) = (f(c,x[0])-y[0])^2 + ... + (f(c,x[n-1])-y[n-1])^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * w is an N-dimensional vector of weight coefficients, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses only f(c,x[i]). - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - DiffStep- numerical differentiation step; - should not be very small or large; - large = loss of accuracy - small = growth of round-off errors - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 18.10.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lsfitcreatef( - real_2d_array x, - real_1d_array y, - real_1d_array c, - double diffstep, - lsfitstate& state, - const xparams _params = alglib::xdefault); -void alglib::lsfitcreatef( - real_2d_array x, - real_1d_array y, - real_1d_array c, - ae_int_t n, - ae_int_t m, - ae_int_t k, - double diffstep, - lsfitstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -Nonlinear least squares fitting using gradient only, without individual -weights. - -Nonlinear task min(F(c)) is solved, where - - F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses only f(c,x[i]) and its gradient. - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - CheapFG - boolean flag, which is: - * True if both function and gradient calculation complexity - are less than O(M^2). An improved algorithm can - be used which corresponds to FGJ scheme from - MINLM unit. - * False otherwise. - Standard Jacibian-bases Levenberg-Marquardt algo - will be used (FJ scheme). - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lsfitcreatefg( - real_2d_array x, - real_1d_array y, - real_1d_array c, - bool cheapfg, - lsfitstate& state, - const xparams _params = alglib::xdefault); -void alglib::lsfitcreatefg( - real_2d_array x, - real_1d_array y, - real_1d_array c, - ae_int_t n, - ae_int_t m, - ae_int_t k, - bool cheapfg, - lsfitstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Nonlinear least squares fitting using gradient/Hessian, without individial -weights. - -Nonlinear task min(F(c)) is solved, where - - F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses f(c,x[i]), its gradient and its Hessian. - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lsfitcreatefgh( - real_2d_array x, - real_1d_array y, - real_1d_array c, - lsfitstate& state, - const xparams _params = alglib::xdefault); -void alglib::lsfitcreatefgh( - real_2d_array x, - real_1d_array y, - real_1d_array c, - ae_int_t n, - ae_int_t m, - ae_int_t k, - lsfitstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Weighted nonlinear least squares fitting using function values only. - -Combination of numerical differentiation and secant updates is used to -obtain function Jacobian. - -Nonlinear task min(F(c)) is solved, where - - F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * w is an N-dimensional vector of weight coefficients, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses only f(c,x[i]). - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - W - weights, array[0..N-1] - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - DiffStep- numerical differentiation step; - should not be very small or large; - large = loss of accuracy - small = growth of round-off errors - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 18.10.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lsfitcreatewf( - real_2d_array x, - real_1d_array y, - real_1d_array w, - real_1d_array c, - double diffstep, - lsfitstate& state, - const xparams _params = alglib::xdefault); -void alglib::lsfitcreatewf( - real_2d_array x, - real_1d_array y, - real_1d_array w, - real_1d_array c, - ae_int_t n, - ae_int_t m, - ae_int_t k, - double diffstep, - lsfitstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -Weighted nonlinear least squares fitting using gradient only. - -Nonlinear task min(F(c)) is solved, where - - F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * w is an N-dimensional vector of weight coefficients, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses only f(c,x[i]) and its gradient. - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - W - weights, array[0..N-1] - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - CheapFG - boolean flag, which is: - * True if both function and gradient calculation complexity - are less than O(M^2). An improved algorithm can - be used which corresponds to FGJ scheme from - MINLM unit. - * False otherwise. - Standard Jacibian-bases Levenberg-Marquardt algo - will be used (FJ scheme). - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -See also: - LSFitResults - LSFitCreateFG (fitting without weights) - LSFitCreateWFGH (fitting using Hessian) - LSFitCreateFGH (fitting using Hessian, without weights) - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lsfitcreatewfg( - real_2d_array x, - real_1d_array y, - real_1d_array w, - real_1d_array c, - bool cheapfg, - lsfitstate& state, - const xparams _params = alglib::xdefault); -void alglib::lsfitcreatewfg( - real_2d_array x, - real_1d_array y, - real_1d_array w, - real_1d_array c, - ae_int_t n, - ae_int_t m, - ae_int_t k, - bool cheapfg, - lsfitstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Weighted nonlinear least squares fitting using gradient/Hessian. - -Nonlinear task min(F(c)) is solved, where - - F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * w is an N-dimensional vector of weight coefficients, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses f(c,x[i]), its gradient and its Hessian. - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - W - weights, array[0..N-1] - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lsfitcreatewfgh( - real_2d_array x, - real_1d_array y, - real_1d_array w, - real_1d_array c, - lsfitstate& state, - const xparams _params = alglib::xdefault); -void alglib::lsfitcreatewfgh( - real_2d_array x, - real_1d_array y, - real_1d_array w, - real_1d_array c, - ae_int_t n, - ae_int_t m, - ae_int_t k, - lsfitstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This family of functions is used to launcn iterations of nonlinear fitter - -These functions accept following parameters: - state - algorithm state - func - callback which calculates function (or merit function) - value func at given point x - grad - callback which calculates function (or merit function) - value func and gradient grad at given point x - hess - callback which calculates function (or merit function) - value func, gradient grad and Hessian hess at given point x - rep - optional callback which is called after each iteration - can be NULL - ptr - optional pointer which is passed to func/grad/hess/jac/rep - can be NULL - -NOTES: - -1. this algorithm is somewhat unusual because it works with parameterized - function f(C,X), where X is a function argument (we have many points - which are characterized by different argument values), and C is a - parameter to fit. - - For example, if we want to do linear fit by f(c0,c1,x) = c0*x+c1, then - x will be argument, and {c0,c1} will be parameters. - - It is important to understand that this algorithm finds minimum in the - space of function PARAMETERS (not arguments), so it needs derivatives - of f() with respect to C, not X. - - In the example above it will need f=c0*x+c1 and {df/dc0,df/dc1} = {x,1} - instead of {df/dx} = {c0}. - -2. Callback functions accept C as the first parameter, and X as the second - -3. If state was created with LSFitCreateFG(), algorithm needs just - function and its gradient, but if state was created with - LSFitCreateFGH(), algorithm will need function, gradient and Hessian. - - According to the said above, there ase several versions of this - function, which accept different sets of callbacks. - - This flexibility opens way to subtle errors - you may create state with - LSFitCreateFGH() (optimization using Hessian), but call function which - does not accept Hessian. So when algorithm will request Hessian, there - will be no callback to call. In this case exception will be thrown. - - Be careful to avoid such errors because there is no way to find them at - compile time - you can see them at runtime only. - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void lsfitfit(lsfitstate &state, - void (*func)(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr), - void (*rep)(const real_1d_array &c, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void lsfitfit(lsfitstate &state, - void (*func)(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr), - void (*grad)(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*rep)(const real_1d_array &c, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void lsfitfit(lsfitstate &state, - void (*func)(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr), - void (*grad)(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*hess)(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, real_2d_array &hess, void *ptr), - void (*rep)(const real_1d_array &c, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -
-

Examples:   [1]  [2]  [3]  [4]  [5]  

- -
-
/************************************************************************* -Linear least squares fitting. - -QR decomposition is used to reduce task to MxM, then triangular solver or -SVD-based solver is used depending on condition number of the system. It -allows to maximize speed and retain decent accuracy. - -IMPORTANT: if you want to perform polynomial fitting, it may be more - convenient to use PolynomialFit() function. This function gives - best results on polynomial problems and solves numerical - stability issues which arise when you fit high-degree - polynomials to your data. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Y - array[0..N-1] Function values in N points. - FMatrix - a table of basis functions values, array[0..N-1, 0..M-1]. - FMatrix[I, J] - value of J-th basis function in I-th point. - N - number of points used. N>=1. - M - number of basis functions, M>=1. - -OUTPUT PARAMETERS: - Info - error code: - * -4 internal SVD decomposition subroutine failed (very - rare and for degenerate systems only) - * 1 task is solved - C - decomposition coefficients, array[0..M-1] - Rep - fitting report. Following fields are set: - * Rep.TaskRCond reciprocal of condition number - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(F*CovPar*F')), - where F is functions matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lsfitlinear( - real_1d_array y, - real_2d_array fmatrix, - ae_int_t& info, - real_1d_array& c, - lsfitreport& rep, - const xparams _params = alglib::xdefault); -void alglib::lsfitlinear( - real_1d_array y, - real_2d_array fmatrix, - ae_int_t n, - ae_int_t m, - ae_int_t& info, - real_1d_array& c, - lsfitreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Constained linear least squares fitting. - -This is variation of LSFitLinear(), which searchs for min|A*x=b| given -that K additional constaints C*x=bc are satisfied. It reduces original -task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinear() -is called. - -IMPORTANT: if you want to perform polynomial fitting, it may be more - convenient to use PolynomialFit() function. This function gives - best results on polynomial problems and solves numerical - stability issues which arise when you fit high-degree - polynomials to your data. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Y - array[0..N-1] Function values in N points. - FMatrix - a table of basis functions values, array[0..N-1, 0..M-1]. - FMatrix[I,J] - value of J-th basis function in I-th point. - CMatrix - a table of constaints, array[0..K-1,0..M]. - I-th row of CMatrix corresponds to I-th linear constraint: - CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M] - N - number of points used. N>=1. - M - number of basis functions, M>=1. - K - number of constraints, 0 <= K < M - K=0 corresponds to absence of constraints. - -OUTPUT PARAMETERS: - Info - error code: - * -4 internal SVD decomposition subroutine failed (very - rare and for degenerate systems only) - * -3 either too many constraints (M or more), - degenerate constraints (some constraints are - repetead twice) or inconsistent constraints were - specified. - * 1 task is solved - C - decomposition coefficients, array[0..M-1] - Rep - fitting report. Following fields are set: - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(F*CovPar*F')), - where F is functions matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -IMPORTANT: errors in parameters are calculated without taking into - account boundary/linear constraints! Presence of constraints - changes distribution of errors, but there is no easy way to - account for constraints when you calculate covariance matrix. - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 07.09.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lsfitlinearc( - real_1d_array y, - real_2d_array fmatrix, - real_2d_array cmatrix, - ae_int_t& info, - real_1d_array& c, - lsfitreport& rep, - const xparams _params = alglib::xdefault); -void alglib::lsfitlinearc( - real_1d_array y, - real_2d_array fmatrix, - real_2d_array cmatrix, - ae_int_t n, - ae_int_t m, - ae_int_t k, - ae_int_t& info, - real_1d_array& c, - lsfitreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Weighted linear least squares fitting. - -QR decomposition is used to reduce task to MxM, then triangular solver or -SVD-based solver is used depending on condition number of the system. It -allows to maximize speed and retain decent accuracy. - -IMPORTANT: if you want to perform polynomial fitting, it may be more - convenient to use PolynomialFit() function. This function gives - best results on polynomial problems and solves numerical - stability issues which arise when you fit high-degree - polynomials to your data. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Y - array[0..N-1] Function values in N points. - W - array[0..N-1] Weights corresponding to function values. - Each summand in square sum of approximation deviations - from given values is multiplied by the square of - corresponding weight. - FMatrix - a table of basis functions values, array[0..N-1, 0..M-1]. - FMatrix[I, J] - value of J-th basis function in I-th point. - N - number of points used. N>=1. - M - number of basis functions, M>=1. - -OUTPUT PARAMETERS: - Info - error code: - * -4 internal SVD decomposition subroutine failed (very - rare and for degenerate systems only) - * -1 incorrect N/M were specified - * 1 task is solved - C - decomposition coefficients, array[0..M-1] - Rep - fitting report. Following fields are set: - * Rep.TaskRCond reciprocal of condition number - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(F*CovPar*F')), - where F is functions matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lsfitlinearw( - real_1d_array y, - real_1d_array w, - real_2d_array fmatrix, - ae_int_t& info, - real_1d_array& c, - lsfitreport& rep, - const xparams _params = alglib::xdefault); -void alglib::lsfitlinearw( - real_1d_array y, - real_1d_array w, - real_2d_array fmatrix, - ae_int_t n, - ae_int_t m, - ae_int_t& info, - real_1d_array& c, - lsfitreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Weighted constained linear least squares fitting. - -This is variation of LSFitLinearW(), which searchs for min|A*x=b| given -that K additional constaints C*x=bc are satisfied. It reduces original -task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinearW() -is called. - -IMPORTANT: if you want to perform polynomial fitting, it may be more - convenient to use PolynomialFit() function. This function gives - best results on polynomial problems and solves numerical - stability issues which arise when you fit high-degree - polynomials to your data. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Y - array[0..N-1] Function values in N points. - W - array[0..N-1] Weights corresponding to function values. - Each summand in square sum of approximation deviations - from given values is multiplied by the square of - corresponding weight. - FMatrix - a table of basis functions values, array[0..N-1, 0..M-1]. - FMatrix[I,J] - value of J-th basis function in I-th point. - CMatrix - a table of constaints, array[0..K-1,0..M]. - I-th row of CMatrix corresponds to I-th linear constraint: - CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M] - N - number of points used. N>=1. - M - number of basis functions, M>=1. - K - number of constraints, 0 <= K < M - K=0 corresponds to absence of constraints. - -OUTPUT PARAMETERS: - Info - error code: - * -4 internal SVD decomposition subroutine failed (very - rare and for degenerate systems only) - * -3 either too many constraints (M or more), - degenerate constraints (some constraints are - repetead twice) or inconsistent constraints were - specified. - * 1 task is solved - C - decomposition coefficients, array[0..M-1] - Rep - fitting report. Following fields are set: - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(F*CovPar*F')), - where F is functions matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -IMPORTANT: errors in parameters are calculated without taking into - account boundary/linear constraints! Presence of constraints - changes distribution of errors, but there is no easy way to - account for constraints when you calculate covariance matrix. - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 07.09.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lsfitlinearwc( - real_1d_array y, - real_1d_array w, - real_2d_array fmatrix, - real_2d_array cmatrix, - ae_int_t& info, - real_1d_array& c, - lsfitreport& rep, - const xparams _params = alglib::xdefault); -void alglib::lsfitlinearwc( - real_1d_array y, - real_1d_array w, - real_2d_array fmatrix, - real_2d_array cmatrix, - ae_int_t n, - ae_int_t m, - ae_int_t k, - ae_int_t& info, - real_1d_array& c, - lsfitreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Nonlinear least squares fitting results. - -Called after return from LSFitFit(). - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - Info - completion code: - * -8 optimizer detected NAN/INF in the target - function and/or gradient - * -7 gradient verification failed. - See LSFitSetGradientCheck() for more information. - * -3 inconsistent constraints - * 2 relative step is no more than EpsX. - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible - C - array[0..K-1], solution - Rep - optimization report. On success following fields are set: - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - * WRMSError weighted rms error on the (X,Y). - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(J*CovPar*J')), - where J is Jacobian matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -IMPORTANT: errors in parameters are calculated without taking into - account boundary/linear constraints! Presence of constraints - changes distribution of errors, but there is no easy way to - account for constraints when you calculate covariance matrix. - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lsfitresults( - lsfitstate state, - ae_int_t& info, - real_1d_array& c, - lsfitreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  [5]  

- -
-
/************************************************************************* -This function sets boundary constraints for underlying optimizer - -Boundary constraints are inactive by default (after initial creation). -They are preserved until explicitly turned off with another SetBC() call. - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[K]. - If some (all) variables are unbounded, you may specify - very small number or -INF (latter is recommended because - it will allow solver to use better algorithm). - BndU - upper bounds, array[K]. - If some (all) variables are unbounded, you may specify - very large number or +INF (latter is recommended because - it will allow solver to use better algorithm). - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - -NOTE 2: unlike other constrained optimization algorithms, this solver has -following useful properties: -* bound constraints are always satisfied exactly -* function is evaluated only INSIDE area specified by bound constraints - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lsfitsetbc( - lsfitstate state, - real_1d_array bndl, - real_1d_array bndu, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Stopping conditions for nonlinear least squares fitting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - ste pvector, dx=X(k+1)-X(k) - * s - scaling coefficients set by LSFitSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. Only Levenberg-Marquardt - iterations are counted (L-BFGS/CG iterations are NOT - counted because their cost is very low compared to that of - LM). - -NOTE - -Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic -stopping criterion selection (according to the scheme used by MINLM unit). - - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lsfitsetcond( - lsfitstate state, - double epsx, - ae_int_t maxits, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  [5]  

- -
-
/************************************************************************* -This subroutine turns on verification of the user-supplied analytic -gradient: -* user calls this subroutine before fitting begins -* LSFitFit() is called -* prior to actual fitting, for each point in data set X_i and each - component of parameters being fited C_j algorithm performs following - steps: - * two trial steps are made to C_j-TestStep*S[j] and C_j+TestStep*S[j], - where C_j is j-th parameter and S[j] is a scale of j-th parameter - * if needed, steps are bounded with respect to constraints on C[] - * F(X_i|C) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - * in case difference between prediction and actual value is higher than - some predetermined threshold, algorithm stops with completion code -7; - Rep.VarIdx is set to index of the parameter with incorrect derivative. -* after verification is over, algorithm proceeds to the actual optimization. - -NOTE 1: verification needs N*K (points count * parameters count) gradient - evaluations. It is very costly and you should use it only for low - dimensional problems, when you want to be sure that you've - correctly calculated analytic derivatives. You should not use it - in the production code (unless you want to check derivatives - provided by some third party). - -NOTE 2: you should carefully choose TestStep. Value which is too large - (so large that function behaviour is significantly non-cubic) will - lead to false alarms. You may use different step for different - parameters by means of setting scale with LSFitSetScale(). - -NOTE 3: this function may lead to false positives. In case it reports that - I-th derivative was calculated incorrectly, you may decrease test - step and try one more time - maybe your function changes too - sharply and your step is too large for such rapidly chanding - function. - -NOTE 4: this function works only for optimizers created with LSFitCreateWFG() - or LSFitCreateFG() constructors. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step: - * TestStep=0 turns verification off - * TestStep>0 activates verification - - -- ALGLIB -- - Copyright 15.06.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lsfitsetgradientcheck( - lsfitstate state, - double teststep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets linear constraints for underlying optimizer - -Linear constraints are inactive by default (after initial creation). -They are preserved until explicitly turned off with another SetLC() call. - -INPUT PARAMETERS: - State - structure stores algorithm state - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -IMPORTANT: if you have linear constraints, it is strongly recommended to - set scale of variables with lsfitsetscale(). QP solver which is - used to calculate linearly constrained steps heavily relies on - good scaling of input problems. - -NOTE: linear (non-box) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations. - -NOTE: general linear constraints add significant overhead to solution - process. Although solver performs roughly same amount of iterations - (when compared with similar box-only constrained problem), each - iteration now involves solution of linearly constrained QP - subproblem, which requires ~3-5 times more Cholesky decompositions. - Thus, if you can reformulate your problem in such way this it has - only box constraints, it may be beneficial to do so. - - -- ALGLIB -- - Copyright 29.04.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lsfitsetlc( - lsfitstate state, - real_2d_array c, - integer_1d_array ct, - const xparams _params = alglib::xdefault); -void alglib::lsfitsetlc( - lsfitstate state, - real_2d_array c, - integer_1d_array ct, - ae_int_t k, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets scaling coefficients for underlying optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Generally, scale is NOT considered to be a form of preconditioner. But LM -optimizer is unique in that it uses scaling matrix both in the stopping -condition tests and as Marquardt damping factor. - -Proper scaling is very important for the algorithm performance. It is less -important for the quality of results, but still has some influence (it is -easier to converge when variables are properly scaled, so premature -stopping is possible when very badly scalled variables are combined with -relaxed stopping conditions). - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lsfitsetscale( - lsfitstate state, - real_1d_array s, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which leads to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - -NOTE: non-zero StpMax leads to moderate performance degradation because -intermediate step of preconditioned L-BFGS optimization is incompatible -with limits on step size. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lsfitsetstpmax( - lsfitstate state, - double stpmax, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -When reports are needed, State.C (current parameters) and State.F (current -value of fitting function) are reported. - - - -- ALGLIB -- - Copyright 15.08.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lsfitsetxrep( - lsfitstate state, - bool needxrep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine fits piecewise linear curve to points with Ramer-Douglas- -Peucker algorithm, which stops after achieving desired precision. - -IMPORTANT: -* it performs non-least-squares fitting; it builds curve, but this curve - does not minimize some least squares metric. See description of RDP - algorithm (say, in Wikipedia) for more details on WHAT is performed. -* this function does NOT work with parametric curves (i.e. curves which - can be represented as {X(t),Y(t)}. It works with curves which can be - represented as Y(X). Thus, it is impossible to model figures like circles - with this functions. - If you want to work with parametric curves, you should use - ParametricRDPFixed() function provided by "Parametric" subpackage of - "Interpolation" package. - -INPUT PARAMETERS: - X - array of X-coordinates: - * at least N elements - * can be unordered (points are automatically sorted) - * this function may accept non-distinct X (see below for - more information on handling of such inputs) - Y - array of Y-coordinates: - * at least N elements - N - number of elements in X/Y - Eps - positive number, desired precision. - - -OUTPUT PARAMETERS: - X2 - X-values of corner points for piecewise approximation, - has length NSections+1 or zero (for NSections=0). - Y2 - Y-values of corner points, - has length NSections+1 or zero (for NSections=0). - NSections- number of sections found by algorithm, - NSections can be zero for degenerate datasets - (N<=1 or all X[] are non-distinct). - -NOTE: X2/Y2 are ordered arrays, i.e. (X2[0],Y2[0]) is a first point of - curve, (X2[NSection-1],Y2[NSection-1]) is the last point. - - -- ALGLIB -- - Copyright 02.10.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lstfitpiecewiselinearrdp( - real_1d_array x, - real_1d_array y, - ae_int_t n, - double eps, - real_1d_array& x2, - real_1d_array& y2, - ae_int_t& nsections, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine fits piecewise linear curve to points with Ramer-Douglas- -Peucker algorithm, which stops after generating specified number of linear -sections. - -IMPORTANT: -* it does NOT perform least-squares fitting; it builds curve, but this - curve does not minimize some least squares metric. See description of - RDP algorithm (say, in Wikipedia) for more details on WHAT is performed. -* this function does NOT work with parametric curves (i.e. curves which - can be represented as {X(t),Y(t)}. It works with curves which can be - represented as Y(X). Thus, it is impossible to model figures like - circles with this functions. - If you want to work with parametric curves, you should use - ParametricRDPFixed() function provided by "Parametric" subpackage of - "Interpolation" package. - -INPUT PARAMETERS: - X - array of X-coordinates: - * at least N elements - * can be unordered (points are automatically sorted) - * this function may accept non-distinct X (see below for - more information on handling of such inputs) - Y - array of Y-coordinates: - * at least N elements - N - number of elements in X/Y - M - desired number of sections: - * at most M sections are generated by this function - * less than M sections can be generated if we have N<M - (or some X are non-distinct). - -OUTPUT PARAMETERS: - X2 - X-values of corner points for piecewise approximation, - has length NSections+1 or zero (for NSections=0). - Y2 - Y-values of corner points, - has length NSections+1 or zero (for NSections=0). - NSections- number of sections found by algorithm, NSections<=M, - NSections can be zero for degenerate datasets - (N<=1 or all X[] are non-distinct). - -NOTE: X2/Y2 are ordered arrays, i.e. (X2[0],Y2[0]) is a first point of - curve, (X2[NSection-1],Y2[NSection-1]) is the last point. - - -- ALGLIB -- - Copyright 02.10.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::lstfitpiecewiselinearrdpfixed( - real_1d_array x, - real_1d_array y, - ae_int_t n, - ae_int_t m, - real_1d_array& x2, - real_1d_array& y2, - ae_int_t& nsections, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Fitting by polynomials in barycentric form. This function provides simple -unterface for unconstrained unweighted fitting. See PolynomialFitWC() if -you need constrained fitting. - -Task is linear, so linear least squares solver is used. Complexity of this -computational scheme is O(N*M^2), mostly dominated by least squares solver - -SEE ALSO: - PolynomialFitWC() - -NOTES: - you can convert P from barycentric form to the power or Chebyshev - basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions from - POLINT subpackage. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - N - number of points, N>0 - * if given, only leading N elements of X/Y are used - * if not given, automatically determined from sizes of X/Y - M - number of basis functions (= polynomial_degree + 1), M>=1 - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearW() subroutine: - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - P - interpolant in barycentric form. - Rep - report, same format as in LSFitLinearW() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - - -- ALGLIB PROJECT -- - Copyright 10.12.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::polynomialfit( - real_1d_array x, - real_1d_array y, - ae_int_t m, - ae_int_t& info, - barycentricinterpolant& p, - polynomialfitreport& rep, - const xparams _params = alglib::xdefault); -void alglib::polynomialfit( - real_1d_array x, - real_1d_array y, - ae_int_t n, - ae_int_t m, - ae_int_t& info, - barycentricinterpolant& p, - polynomialfitreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Weighted fitting by polynomials in barycentric form, with constraints on -function values or first derivatives. - -Small regularizing term is used when solving constrained tasks (to improve -stability). - -Task is linear, so linear least squares solver is used. Complexity of this -computational scheme is O(N*M^2), mostly dominated by least squares solver - -SEE ALSO: - PolynomialFit() - -NOTES: - you can convert P from barycentric form to the power or Chebyshev - basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions from - POLINT subpackage. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - W - weights, array[0..N-1] - Each summand in square sum of approximation deviations from - given values is multiplied by the square of corresponding - weight. Fill it by 1's if you don't want to solve weighted - task. - N - number of points, N>0. - * if given, only leading N elements of X/Y/W are used - * if not given, automatically determined from sizes of X/Y/W - XC - points where polynomial values/derivatives are constrained, - array[0..K-1]. - YC - values of constraints, array[0..K-1] - DC - array[0..K-1], types of constraints: - * DC[i]=0 means that P(XC[i])=YC[i] - * DC[i]=1 means that P'(XC[i])=YC[i] - SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS - K - number of constraints, 0<=K<M. - K=0 means no constraints (XC/YC/DC are not used in such cases) - M - number of basis functions (= polynomial_degree + 1), M>=1 - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearW() subroutine: - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - P - interpolant in barycentric form. - Rep - report, same format as in LSFitLinearW() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - -SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: - -Setting constraints can lead to undesired results, like ill-conditioned -behavior, or inconsistency being detected. From the other side, it allows -us to improve quality of the fit. Here we summarize our experience with -constrained regression splines: -* even simple constraints can be inconsistent, see Wikipedia article on - this subject: http://en.wikipedia.org/wiki/Birkhoff_interpolation -* the greater is M (given fixed constraints), the more chances that - constraints will be consistent -* in the general case, consistency of constraints is NOT GUARANTEED. -* in the one special cases, however, we can guarantee consistency. This - case is: M>1 and constraints on the function values (NOT DERIVATIVES) - -Our final recommendation is to use constraints WHEN AND ONLY when you -can't solve your task without them. Anything beyond special cases given -above is not guaranteed and may result in inconsistency. - - -- ALGLIB PROJECT -- - Copyright 10.12.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::polynomialfitwc( - real_1d_array x, - real_1d_array y, - real_1d_array w, - real_1d_array xc, - real_1d_array yc, - integer_1d_array dc, - ae_int_t m, - ae_int_t& info, - barycentricinterpolant& p, - polynomialfitreport& rep, - const xparams _params = alglib::xdefault); -void alglib::polynomialfitwc( - real_1d_array x, - real_1d_array y, - real_1d_array w, - ae_int_t n, - real_1d_array xc, - real_1d_array yc, - integer_1d_array dc, - ae_int_t k, - ae_int_t m, - ae_int_t& info, - barycentricinterpolant& p, - polynomialfitreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Least squares fitting by cubic spline. - -This subroutine is "lightweight" alternative for more complex and feature- -rich Spline1DFitCubicWC(). See Spline1DFitCubicWC() for more information -about subroutine parameters (we don't duplicate it here because of length) - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dfitcubic( - real_1d_array x, - real_1d_array y, - ae_int_t m, - ae_int_t& info, - spline1dinterpolant& s, - spline1dfitreport& rep, - const xparams _params = alglib::xdefault); -void alglib::spline1dfitcubic( - real_1d_array x, - real_1d_array y, - ae_int_t n, - ae_int_t m, - ae_int_t& info, - spline1dinterpolant& s, - spline1dfitreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Weighted fitting by cubic spline, with constraints on function values or -derivatives. - -Equidistant grid with M-2 nodes on [min(x,xc),max(x,xc)] is used to build -basis functions. Basis functions are cubic splines with continuous second -derivatives and non-fixed first derivatives at interval ends. Small -regularizing term is used when solving constrained tasks (to improve -stability). - -Task is linear, so linear least squares solver is used. Complexity of this -computational scheme is O(N*M^2), mostly dominated by least squares solver - -SEE ALSO - Spline1DFitHermiteWC() - fitting by Hermite splines (more flexible, - less smooth) - Spline1DFitCubic() - "lightweight" fitting by cubic splines, - without invididual weights and constraints - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - W - weights, array[0..N-1] - Each summand in square sum of approximation deviations from - given values is multiplied by the square of corresponding - weight. Fill it by 1's if you don't want to solve weighted - task. - N - number of points (optional): - * N>0 - * if given, only first N elements of X/Y/W are processed - * if not given, automatically determined from X/Y/W sizes - XC - points where spline values/derivatives are constrained, - array[0..K-1]. - YC - values of constraints, array[0..K-1] - DC - array[0..K-1], types of constraints: - * DC[i]=0 means that S(XC[i])=YC[i] - * DC[i]=1 means that S'(XC[i])=YC[i] - SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS - K - number of constraints (optional): - * 0<=K<M. - * K=0 means no constraints (XC/YC/DC are not used) - * if given, only first K elements of XC/YC/DC are used - * if not given, automatically determined from XC/YC/DC - M - number of basis functions ( = number_of_nodes+2), M>=4. - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearWC() subroutine. - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - S - spline interpolant. - Rep - report, same format as in LSFitLinearWC() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - -SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: - -Setting constraints can lead to undesired results, like ill-conditioned -behavior, or inconsistency being detected. From the other side, it allows -us to improve quality of the fit. Here we summarize our experience with -constrained regression splines: -* excessive constraints can be inconsistent. Splines are piecewise cubic - functions, and it is easy to create an example, where large number of - constraints concentrated in small area will result in inconsistency. - Just because spline is not flexible enough to satisfy all of them. And - same constraints spread across the [min(x),max(x)] will be perfectly - consistent. -* the more evenly constraints are spread across [min(x),max(x)], the more - chances that they will be consistent -* the greater is M (given fixed constraints), the more chances that - constraints will be consistent -* in the general case, consistency of constraints IS NOT GUARANTEED. -* in the several special cases, however, we CAN guarantee consistency. -* one of this cases is constraints on the function values AND/OR its - derivatives at the interval boundaries. -* another special case is ONE constraint on the function value (OR, but - not AND, derivative) anywhere in the interval - -Our final recommendation is to use constraints WHEN AND ONLY WHEN you -can't solve your task without them. Anything beyond special cases given -above is not guaranteed and may result in inconsistency. - - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dfitcubicwc( - real_1d_array x, - real_1d_array y, - real_1d_array w, - real_1d_array xc, - real_1d_array yc, - integer_1d_array dc, - ae_int_t m, - ae_int_t& info, - spline1dinterpolant& s, - spline1dfitreport& rep, - const xparams _params = alglib::xdefault); -void alglib::spline1dfitcubicwc( - real_1d_array x, - real_1d_array y, - real_1d_array w, - ae_int_t n, - real_1d_array xc, - real_1d_array yc, - integer_1d_array dc, - ae_int_t k, - ae_int_t m, - ae_int_t& info, - spline1dinterpolant& s, - spline1dfitreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Least squares fitting by Hermite spline. - -This subroutine is "lightweight" alternative for more complex and feature- -rich Spline1DFitHermiteWC(). See Spline1DFitHermiteWC() description for -more information about subroutine parameters (we don't duplicate it here -because of length). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dfithermite( - real_1d_array x, - real_1d_array y, - ae_int_t m, - ae_int_t& info, - spline1dinterpolant& s, - spline1dfitreport& rep, - const xparams _params = alglib::xdefault); -void alglib::spline1dfithermite( - real_1d_array x, - real_1d_array y, - ae_int_t n, - ae_int_t m, - ae_int_t& info, - spline1dinterpolant& s, - spline1dfitreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Weighted fitting by Hermite spline, with constraints on function values -or first derivatives. - -Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is used to build -basis functions. Basis functions are Hermite splines. Small regularizing -term is used when solving constrained tasks (to improve stability). - -Task is linear, so linear least squares solver is used. Complexity of this -computational scheme is O(N*M^2), mostly dominated by least squares solver - -SEE ALSO - Spline1DFitCubicWC() - fitting by Cubic splines (less flexible, - more smooth) - Spline1DFitHermite() - "lightweight" Hermite fitting, without - invididual weights and constraints - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - W - weights, array[0..N-1] - Each summand in square sum of approximation deviations from - given values is multiplied by the square of corresponding - weight. Fill it by 1's if you don't want to solve weighted - task. - N - number of points (optional): - * N>0 - * if given, only first N elements of X/Y/W are processed - * if not given, automatically determined from X/Y/W sizes - XC - points where spline values/derivatives are constrained, - array[0..K-1]. - YC - values of constraints, array[0..K-1] - DC - array[0..K-1], types of constraints: - * DC[i]=0 means that S(XC[i])=YC[i] - * DC[i]=1 means that S'(XC[i])=YC[i] - SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS - K - number of constraints (optional): - * 0<=K<M. - * K=0 means no constraints (XC/YC/DC are not used) - * if given, only first K elements of XC/YC/DC are used - * if not given, automatically determined from XC/YC/DC - M - number of basis functions (= 2 * number of nodes), - M>=4, - M IS EVEN! - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearW() subroutine: - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - -2 means odd M was passed (which is not supported) - -1 means another errors in parameters passed - (N<=0, for example) - S - spline interpolant. - Rep - report, same format as in LSFitLinearW() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - -IMPORTANT: - this subroitine supports only even M's - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - -SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: - -Setting constraints can lead to undesired results, like ill-conditioned -behavior, or inconsistency being detected. From the other side, it allows -us to improve quality of the fit. Here we summarize our experience with -constrained regression splines: -* excessive constraints can be inconsistent. Splines are piecewise cubic - functions, and it is easy to create an example, where large number of - constraints concentrated in small area will result in inconsistency. - Just because spline is not flexible enough to satisfy all of them. And - same constraints spread across the [min(x),max(x)] will be perfectly - consistent. -* the more evenly constraints are spread across [min(x),max(x)], the more - chances that they will be consistent -* the greater is M (given fixed constraints), the more chances that - constraints will be consistent -* in the general case, consistency of constraints is NOT GUARANTEED. -* in the several special cases, however, we can guarantee consistency. -* one of this cases is M>=4 and constraints on the function value - (AND/OR its derivative) at the interval boundaries. -* another special case is M>=4 and ONE constraint on the function value - (OR, BUT NOT AND, derivative) anywhere in [min(x),max(x)] - -Our final recommendation is to use constraints WHEN AND ONLY when you -can't solve your task without them. Anything beyond special cases given -above is not guaranteed and may result in inconsistency. - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dfithermitewc( - real_1d_array x, - real_1d_array y, - real_1d_array w, - real_1d_array xc, - real_1d_array yc, - integer_1d_array dc, - ae_int_t m, - ae_int_t& info, - spline1dinterpolant& s, - spline1dfitreport& rep, - const xparams _params = alglib::xdefault); -void alglib::spline1dfithermitewc( - real_1d_array x, - real_1d_array y, - real_1d_array w, - ae_int_t n, - real_1d_array xc, - real_1d_array yc, - integer_1d_array dc, - ae_int_t k, - ae_int_t m, - ae_int_t& info, - spline1dinterpolant& s, - spline1dfitreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // In this example we demonstrate linear fitting by f(x|a) = a*exp(0.5*x).
-    //
-    // We have:
-    // * y - vector of experimental data
-    // * fmatrix -  matrix of basis functions calculated at sample points
-    //              Actually, we have only one basis function F0 = exp(0.5*x).
-    //
-    real_2d_array fmatrix = "[[0.606531],[0.670320],[0.740818],[0.818731],[0.904837],[1.000000],[1.105171],[1.221403],[1.349859],[1.491825],[1.648721]]";
-    real_1d_array y = "[1.133719, 1.306522, 1.504604, 1.554663, 1.884638, 2.072436, 2.257285, 2.534068, 2.622017, 2.897713, 3.219371]";
-    ae_int_t info;
-    real_1d_array c;
-    lsfitreport rep;
-
-    //
-    // Linear fitting without weights
-    //
-    lsfitlinear(y, fmatrix, info, c, rep);
-    printf("%d\n", int(info)); // EXPECTED: 1
-    printf("%s\n", c.tostring(4).c_str()); // EXPECTED: [1.98650]
-
-    //
-    // Linear fitting with individual weights.
-    // Slightly different result is returned.
-    //
-    real_1d_array w = "[1.414213, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]";
-    lsfitlinearw(y, w, fmatrix, info, c, rep);
-    printf("%d\n", int(info)); // EXPECTED: 1
-    printf("%s\n", c.tostring(4).c_str()); // EXPECTED: [1.983354]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // In this example we demonstrate linear fitting by f(x|a,b) = a*x+b
-    // with simple constraint f(0)=0.
-    //
-    // We have:
-    // * y - vector of experimental data
-    // * fmatrix -  matrix of basis functions sampled at [0,1] with step 0.2:
-    //                  [ 1.0   0.0 ]
-    //                  [ 1.0   0.2 ]
-    //                  [ 1.0   0.4 ]
-    //                  [ 1.0   0.6 ]
-    //                  [ 1.0   0.8 ]
-    //                  [ 1.0   1.0 ]
-    //              first column contains value of first basis function (constant term)
-    //              second column contains second basis function (linear term)
-    // * cmatrix -  matrix of linear constraints:
-    //                  [ 1.0  0.0  0.0 ]
-    //              first two columns contain coefficients before basis functions,
-    //              last column contains desired value of their sum.
-    //              So [1,0,0] means "1*constant_term + 0*linear_term = 0" 
-    //
-    real_1d_array y = "[0.072436,0.246944,0.491263,0.522300,0.714064,0.921929]";
-    real_2d_array fmatrix = "[[1,0.0],[1,0.2],[1,0.4],[1,0.6],[1,0.8],[1,1.0]]";
-    real_2d_array cmatrix = "[[1,0,0]]";
-    ae_int_t info;
-    real_1d_array c;
-    lsfitreport rep;
-
-    //
-    // Constrained fitting without weights
-    //
-    lsfitlinearc(y, fmatrix, cmatrix, info, c, rep);
-    printf("%d\n", int(info)); // EXPECTED: 1
-    printf("%s\n", c.tostring(3).c_str()); // EXPECTED: [0,0.932933]
-
-    //
-    // Constrained fitting with individual weights
-    //
-    real_1d_array w = "[1, 1.414213, 1, 1, 1, 1]";
-    lsfitlinearwc(y, w, fmatrix, cmatrix, info, c, rep);
-    printf("%d\n", int(info)); // EXPECTED: 1
-    printf("%s\n", c.tostring(3).c_str()); // EXPECTED: [0,0.938322]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-void function_cx_1_func(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr) 
-{
-    // this callback calculates f(c,x)=exp(-c0*sqr(x0))
-    // where x is a position on X-axis and c is adjustable parameter
-    func = exp(-c[0]*pow(x[0],2));
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // In this example we demonstrate exponential fitting
-    // by f(x) = exp(-c*x^2)
-    // using function value only.
-    //
-    // Gradient is estimated using combination of numerical differences
-    // and secant updates. diffstep variable stores differentiation step 
-    // (we have to tell algorithm what step to use).
-    //
-    real_2d_array x = "[[-1],[-0.8],[-0.6],[-0.4],[-0.2],[0],[0.2],[0.4],[0.6],[0.8],[1.0]]";
-    real_1d_array y = "[0.223130, 0.382893, 0.582748, 0.786628, 0.941765, 1.000000, 0.941765, 0.786628, 0.582748, 0.382893, 0.223130]";
-    real_1d_array c = "[0.3]";
-    double epsx = 0.000001;
-    ae_int_t maxits = 0;
-    ae_int_t info;
-    lsfitstate state;
-    lsfitreport rep;
-    double diffstep = 0.0001;
-
-    //
-    // Fitting without weights
-    //
-    lsfitcreatef(x, y, c, diffstep, state);
-    lsfitsetcond(state, epsx, maxits);
-    alglib::lsfitfit(state, function_cx_1_func);
-    lsfitresults(state, info, c, rep);
-    printf("%d\n", int(info)); // EXPECTED: 2
-    printf("%s\n", c.tostring(1).c_str()); // EXPECTED: [1.5]
-
-    //
-    // Fitting with weights
-    // (you can change weights and see how it changes result)
-    //
-    real_1d_array w = "[1,1,1,1,1,1,1,1,1,1,1]";
-    lsfitcreatewf(x, y, w, c, diffstep, state);
-    lsfitsetcond(state, epsx, maxits);
-    alglib::lsfitfit(state, function_cx_1_func);
-    lsfitresults(state, info, c, rep);
-    printf("%d\n", int(info)); // EXPECTED: 2
-    printf("%s\n", c.tostring(1).c_str()); // EXPECTED: [1.5]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-void function_cx_1_func(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr) 
-{
-    // this callback calculates f(c,x)=exp(-c0*sqr(x0))
-    // where x is a position on X-axis and c is adjustable parameter
-    func = exp(-c[0]*pow(x[0],2));
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // In this example we demonstrate exponential fitting by
-    //     f(x) = exp(-c*x^2)
-    // subject to bound constraints
-    //     0.0 <= c <= 1.0
-    // using function value only.
-    //
-    // Gradient is estimated using combination of numerical differences
-    // and secant updates. diffstep variable stores differentiation step 
-    // (we have to tell algorithm what step to use).
-    //
-    // Unconstrained solution is c=1.5, but because of constraints we should
-    // get c=1.0 (at the boundary).
-    //
-    real_2d_array x = "[[-1],[-0.8],[-0.6],[-0.4],[-0.2],[0],[0.2],[0.4],[0.6],[0.8],[1.0]]";
-    real_1d_array y = "[0.223130, 0.382893, 0.582748, 0.786628, 0.941765, 1.000000, 0.941765, 0.786628, 0.582748, 0.382893, 0.223130]";
-    real_1d_array c = "[0.3]";
-    real_1d_array bndl = "[0.0]";
-    real_1d_array bndu = "[1.0]";
-    double epsx = 0.000001;
-    ae_int_t maxits = 0;
-    ae_int_t info;
-    lsfitstate state;
-    lsfitreport rep;
-    double diffstep = 0.0001;
-
-    lsfitcreatef(x, y, c, diffstep, state);
-    lsfitsetbc(state, bndl, bndu);
-    lsfitsetcond(state, epsx, maxits);
-    alglib::lsfitfit(state, function_cx_1_func);
-    lsfitresults(state, info, c, rep);
-    printf("%s\n", c.tostring(1).c_str()); // EXPECTED: [1.0]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-void function_cx_1_func(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr) 
-{
-    // this callback calculates f(c,x)=exp(-c0*sqr(x0))
-    // where x is a position on X-axis and c is adjustable parameter
-    func = exp(-c[0]*pow(x[0],2));
-}
-void function_cx_1_grad(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, void *ptr) 
-{
-    // this callback calculates f(c,x)=exp(-c0*sqr(x0)) and gradient G={df/dc[i]}
-    // where x is a position on X-axis and c is adjustable parameter.
-    // IMPORTANT: gradient is calculated with respect to C, not to X
-    func = exp(-c[0]*pow(x[0],2));
-    grad[0] = -pow(x[0],2)*func;
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // In this example we demonstrate exponential fitting
-    // by f(x) = exp(-c*x^2)
-    // using function value and gradient (with respect to c).
-    //
-    real_2d_array x = "[[-1],[-0.8],[-0.6],[-0.4],[-0.2],[0],[0.2],[0.4],[0.6],[0.8],[1.0]]";
-    real_1d_array y = "[0.223130, 0.382893, 0.582748, 0.786628, 0.941765, 1.000000, 0.941765, 0.786628, 0.582748, 0.382893, 0.223130]";
-    real_1d_array c = "[0.3]";
-    double epsx = 0.000001;
-    ae_int_t maxits = 0;
-    ae_int_t info;
-    lsfitstate state;
-    lsfitreport rep;
-
-    //
-    // Fitting without weights
-    //
-    lsfitcreatefg(x, y, c, true, state);
-    lsfitsetcond(state, epsx, maxits);
-    alglib::lsfitfit(state, function_cx_1_func, function_cx_1_grad);
-    lsfitresults(state, info, c, rep);
-    printf("%d\n", int(info)); // EXPECTED: 2
-    printf("%s\n", c.tostring(1).c_str()); // EXPECTED: [1.5]
-
-    //
-    // Fitting with weights
-    // (you can change weights and see how it changes result)
-    //
-    real_1d_array w = "[1,1,1,1,1,1,1,1,1,1,1]";
-    lsfitcreatewfg(x, y, w, c, true, state);
-    lsfitsetcond(state, epsx, maxits);
-    alglib::lsfitfit(state, function_cx_1_func, function_cx_1_grad);
-    lsfitresults(state, info, c, rep);
-    printf("%d\n", int(info)); // EXPECTED: 2
-    printf("%s\n", c.tostring(1).c_str()); // EXPECTED: [1.5]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-void function_cx_1_func(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr) 
-{
-    // this callback calculates f(c,x)=exp(-c0*sqr(x0))
-    // where x is a position on X-axis and c is adjustable parameter
-    func = exp(-c[0]*pow(x[0],2));
-}
-void function_cx_1_grad(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, void *ptr) 
-{
-    // this callback calculates f(c,x)=exp(-c0*sqr(x0)) and gradient G={df/dc[i]}
-    // where x is a position on X-axis and c is adjustable parameter.
-    // IMPORTANT: gradient is calculated with respect to C, not to X
-    func = exp(-c[0]*pow(x[0],2));
-    grad[0] = -pow(x[0],2)*func;
-}
-void function_cx_1_hess(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, real_2d_array &hess, void *ptr) 
-{
-    // this callback calculates f(c,x)=exp(-c0*sqr(x0)), gradient G={df/dc[i]} and Hessian H={d2f/(dc[i]*dc[j])}
-    // where x is a position on X-axis and c is adjustable parameter.
-    // IMPORTANT: gradient/Hessian are calculated with respect to C, not to X
-    func = exp(-c[0]*pow(x[0],2));
-    grad[0] = -pow(x[0],2)*func;
-    hess[0][0] = pow(x[0],4)*func;
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // In this example we demonstrate exponential fitting
-    // by f(x) = exp(-c*x^2)
-    // using function value, gradient and Hessian (with respect to c)
-    //
-    real_2d_array x = "[[-1],[-0.8],[-0.6],[-0.4],[-0.2],[0],[0.2],[0.4],[0.6],[0.8],[1.0]]";
-    real_1d_array y = "[0.223130, 0.382893, 0.582748, 0.786628, 0.941765, 1.000000, 0.941765, 0.786628, 0.582748, 0.382893, 0.223130]";
-    real_1d_array c = "[0.3]";
-    double epsx = 0.000001;
-    ae_int_t maxits = 0;
-    ae_int_t info;
-    lsfitstate state;
-    lsfitreport rep;
-
-    //
-    // Fitting without weights
-    //
-    lsfitcreatefgh(x, y, c, state);
-    lsfitsetcond(state, epsx, maxits);
-    alglib::lsfitfit(state, function_cx_1_func, function_cx_1_grad, function_cx_1_hess);
-    lsfitresults(state, info, c, rep);
-    printf("%d\n", int(info)); // EXPECTED: 2
-    printf("%s\n", c.tostring(1).c_str()); // EXPECTED: [1.5]
-
-    //
-    // Fitting with weights
-    // (you can change weights and see how it changes result)
-    //
-    real_1d_array w = "[1,1,1,1,1,1,1,1,1,1,1]";
-    lsfitcreatewfgh(x, y, w, c, state);
-    lsfitsetcond(state, epsx, maxits);
-    alglib::lsfitfit(state, function_cx_1_func, function_cx_1_grad, function_cx_1_hess);
-    lsfitresults(state, info, c, rep);
-    printf("%d\n", int(info)); // EXPECTED: 2
-    printf("%s\n", c.tostring(1).c_str()); // EXPECTED: [1.5]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-void function_debt_func(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr) 
-{
-    //
-    // this callback calculates f(c,x)=c[0]*(1+c[1]*(pow(x[0]-1999,c[2])-1))
-    //
-    func = c[0]*(1+c[1]*(pow(x[0]-1999,c[2])-1));
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // In this example we demonstrate fitting by
-    //     f(x) = c[0]*(1+c[1]*((x-1999)^c[2]-1))
-    // subject to bound constraints
-    //     -INF  < c[0] < +INF
-    //      -10 <= c[1] <= +10
-    //      0.1 <= c[2] <= 2.0
-    // Data we want to fit are time series of Japan national debt
-    // collected from 2000 to 2008 measured in USD (dollars, not
-    // millions of dollars).
-    //
-    // Our variables are:
-    //     c[0] - debt value at initial moment (2000),
-    //     c[1] - direction coefficient (growth or decrease),
-    //     c[2] - curvature coefficient.
-    // You may see that our variables are badly scaled - first one 
-    // is order of 10^12, and next two are somewhere about 1 in 
-    // magnitude. Such problem is difficult to solve without some
-    // kind of scaling.
-    // That is exactly where lsfitsetscale() function can be used.
-    // We set scale of our variables to [1.0E12, 1, 1], which allows
-    // us to easily solve this problem.
-    //
-    // You can try commenting out lsfitsetscale() call - and you will 
-    // see that algorithm will fail to converge.
-    //
-    real_2d_array x = "[[2000],[2001],[2002],[2003],[2004],[2005],[2006],[2007],[2008]]";
-    real_1d_array y = "[4323239600000.0, 4560913100000.0, 5564091500000.0, 6743189300000.0, 7284064600000.0, 7050129600000.0, 7092221500000.0, 8483907600000.0, 8625804400000.0]";
-    real_1d_array c = "[1.0e+13, 1, 1]";
-    double epsx = 1.0e-5;
-    real_1d_array bndl = "[-inf, -10, 0.1]";
-    real_1d_array bndu = "[+inf, +10, 2.0]";
-    real_1d_array s = "[1.0e+12, 1, 1]";
-    ae_int_t maxits = 0;
-    ae_int_t info;
-    lsfitstate state;
-    lsfitreport rep;
-    double diffstep = 1.0e-5;
-
-    lsfitcreatef(x, y, c, diffstep, state);
-    lsfitsetcond(state, epsx, maxits);
-    lsfitsetbc(state, bndl, bndu);
-    lsfitsetscale(state, s);
-    alglib::lsfitfit(state, function_debt_func);
-    lsfitresults(state, info, c, rep);
-    printf("%d\n", int(info)); // EXPECTED: 2
-    printf("%s\n", c.tostring(-2).c_str()); // EXPECTED: [4.142560E+12, 0.434240, 0.565376]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates polynomial fitting.
-    //
-    // Fitting is done by two (M=2) functions from polynomial basis:
-    //     f0 = 1
-    //     f1 = x
-    // Basically, it just a linear fit; more complex polynomials may be used
-    // (e.g. parabolas with M=3, cubic with M=4), but even such simple fit allows
-    // us to demonstrate polynomialfit() function in action.
-    //
-    // We have:
-    // * x      set of abscissas
-    // * y      experimental data
-    //
-    // Additionally we demonstrate weighted fitting, where second point has
-    // more weight than other ones.
-    //
-    real_1d_array x = "[0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]";
-    real_1d_array y = "[0.00,0.05,0.26,0.32,0.33,0.43,0.60,0.60,0.77,0.98,1.02]";
-    ae_int_t m = 2;
-    double t = 2;
-    ae_int_t info;
-    barycentricinterpolant p;
-    polynomialfitreport rep;
-    double v;
-
-    //
-    // Fitting without individual weights
-    //
-    // NOTE: result is returned as barycentricinterpolant structure.
-    //       if you want to get representation in the power basis,
-    //       you can use barycentricbar2pow() function to convert
-    //       from barycentric to power representation (see docs for 
-    //       POLINT subpackage for more info).
-    //
-    polynomialfit(x, y, m, info, p, rep);
-    v = barycentriccalc(p, t);
-    printf("%.2f\n", double(v)); // EXPECTED: 2.011
-
-    //
-    // Fitting with individual weights
-    //
-    // NOTE: slightly different result is returned
-    //
-    real_1d_array w = "[1,1.414213562,1,1,1,1,1,1,1,1,1]";
-    real_1d_array xc = "[]";
-    real_1d_array yc = "[]";
-    integer_1d_array dc = "[]";
-    polynomialfitwc(x, y, w, xc, yc, dc, m, info, p, rep);
-    v = barycentriccalc(p, t);
-    printf("%.2f\n", double(v)); // EXPECTED: 2.023
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates polynomial fitting.
-    //
-    // Fitting is done by two (M=2) functions from polynomial basis:
-    //     f0 = 1
-    //     f1 = x
-    // with simple constraint on function value
-    //     f(0) = 0
-    // Basically, it just a linear fit; more complex polynomials may be used
-    // (e.g. parabolas with M=3, cubic with M=4), but even such simple fit allows
-    // us to demonstrate polynomialfit() function in action.
-    //
-    // We have:
-    // * x      set of abscissas
-    // * y      experimental data
-    // * xc     points where constraints are placed
-    // * yc     constraints on derivatives
-    // * dc     derivative indices
-    //          (0 means function itself, 1 means first derivative)
-    //
-    real_1d_array x = "[1.0,1.0]";
-    real_1d_array y = "[0.9,1.1]";
-    real_1d_array w = "[1,1]";
-    real_1d_array xc = "[0]";
-    real_1d_array yc = "[0]";
-    integer_1d_array dc = "[0]";
-    double t = 2;
-    ae_int_t m = 2;
-    ae_int_t info;
-    barycentricinterpolant p;
-    polynomialfitreport rep;
-    double v;
-
-    polynomialfitwc(x, y, w, xc, yc, dc, m, info, p, rep);
-    v = barycentriccalc(p, t);
-    printf("%.2f\n", double(v)); // EXPECTED: 2.000
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // In this example we demonstrate penalized spline fitting of noisy data
-    //
-    // We have:
-    // * x - abscissas
-    // * y - vector of experimental data, straight line with small noise
-    //
-    real_1d_array x = "[0.00,0.10,0.20,0.30,0.40,0.50,0.60,0.70,0.80,0.90]";
-    real_1d_array y = "[0.10,0.00,0.30,0.40,0.30,0.40,0.62,0.68,0.75,0.95]";
-    ae_int_t info;
-    double v;
-    spline1dinterpolant s;
-    spline1dfitreport rep;
-    double rho;
-
-    //
-    // Fit with VERY small amount of smoothing (rho = -5.0)
-    // and large number of basis functions (M=50).
-    //
-    // With such small regularization penalized spline almost fully reproduces function values
-    //
-    rho = -5.0;
-    spline1dfitpenalized(x, y, 50, rho, info, s, rep);
-    printf("%d\n", int(info)); // EXPECTED: 1
-    v = spline1dcalc(s, 0.0);
-    printf("%.1f\n", double(v)); // EXPECTED: 0.10
-
-    //
-    // Fit with VERY large amount of smoothing (rho = 10.0)
-    // and large number of basis functions (M=50).
-    //
-    // With such regularization our spline should become close to the straight line fit.
-    // We will compare its value in x=1.0 with results obtained from such fit.
-    //
-    rho = +10.0;
-    spline1dfitpenalized(x, y, 50, rho, info, s, rep);
-    printf("%d\n", int(info)); // EXPECTED: 1
-    v = spline1dcalc(s, 1.0);
-    printf("%.2f\n", double(v)); // EXPECTED: 0.969
-
-    //
-    // In real life applications you may need some moderate degree of fitting,
-    // so we try to fit once more with rho=3.0.
-    //
-    rho = +3.0;
-    spline1dfitpenalized(x, y, 50, rho, info, s, rep);
-    printf("%d\n", int(info)); // EXPECTED: 1
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    real_1d_array x = "[1,2,3,4,5,6,7,8]";
-    real_1d_array y = "[0.06313223,0.44552624,0.61838364,0.71385108,0.77345838,0.81383140,0.84280033,0.86449822]";
-    ae_int_t n = 8;
-    double a;
-    double b;
-    double c;
-    double d;
-    lsfitreport rep;
-
-    //
-    // Test logisticfit4() on carefully designed data with a priori known answer.
-    //
-    logisticfit4(x, y, n, a, b, c, d, rep);
-    printf("%.1f\n", double(a)); // EXPECTED: -1.000
-    printf("%.1f\n", double(b)); // EXPECTED: 1.200
-    printf("%.1f\n", double(c)); // EXPECTED: 0.900
-    printf("%.1f\n", double(d)); // EXPECTED: 1.000
-
-    //
-    // Evaluate model at point x=0.5
-    //
-    double v;
-    v = logisticcalc4(0.5, a, b, c, d);
-    printf("%.2f\n", double(v)); // EXPECTED: -0.33874308
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    real_1d_array x = "[1,2,3,4,5,6,7,8]";
-    real_1d_array y = "[0.1949776139,0.5710060208,0.726002637,0.8060434158,0.8534547965,0.8842071579,0.9054773317,0.9209088299]";
-    ae_int_t n = 8;
-    double a;
-    double b;
-    double c;
-    double d;
-    double g;
-    lsfitreport rep;
-
-    //
-    // Test logisticfit5() on carefully designed data with a priori known answer.
-    //
-    logisticfit5(x, y, n, a, b, c, d, g, rep);
-    printf("%.1f\n", double(a)); // EXPECTED: -1.000
-    printf("%.1f\n", double(b)); // EXPECTED: 1.200
-    printf("%.1f\n", double(c)); // EXPECTED: 0.900
-    printf("%.1f\n", double(d)); // EXPECTED: 1.000
-    printf("%.1f\n", double(g)); // EXPECTED: 1.200
-
-    //
-    // Evaluate model at point x=0.5
-    //
-    double v;
-    v = logisticcalc5(0.5, a, b, c, d, g);
-    printf("%.2f\n", double(v)); // EXPECTED: -0.2354656824
-    return 0;
-}
-
-
-
-
- -mannwhitneyutest
- - -
- -
-
/************************************************************************* -Mann-Whitney U-test - -This test checks hypotheses about whether X and Y are samples of two -continuous distributions of the same shape and same median or whether -their medians are different. - -The following tests are performed: - * two-tailed test (null hypothesis - the medians are equal) - * left-tailed test (null hypothesis - the median of the first sample - is greater than or equal to the median of the second sample) - * right-tailed test (null hypothesis - the median of the first sample - is less than or equal to the median of the second sample). - -Requirements: - * the samples are independent - * X and Y are continuous distributions (or discrete distributions well- - approximating continuous distributions) - * distributions of X and Y have the same shape. The only possible - difference is their position (i.e. the value of the median) - * the number of elements in each sample is not less than 5 - * the scale of measurement should be ordinal, interval or ratio (i.e. - the test could not be applied to nominal variables). - -The test is non-parametric and doesn't require distributions to be normal. - -Input parameters: - X - sample 1. Array whose index goes from 0 to N-1. - N - size of the sample. N>=5 - Y - sample 2. Array whose index goes from 0 to M-1. - M - size of the sample. M>=5 - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -To calculate p-values, special approximation is used. This method lets us -calculate p-values with satisfactory accuracy in interval [0.0001, 1]. -There is no approximation outside the [0.0001, 1] interval. Therefore, if -the significance level outlies this interval, the test returns 0.0001. - -Relative precision of approximation of p-value: - -N M Max.err. Rms.err. -5..10 N..10 1.4e-02 6.0e-04 -5..10 N..100 2.2e-02 5.3e-06 -10..15 N..15 1.0e-02 3.2e-04 -10..15 N..100 1.0e-02 2.2e-05 -15..100 N..100 6.1e-03 2.7e-06 - -For N,M>100 accuracy checks weren't put into practice, but taking into -account characteristics of asymptotic approximation used, precision should -not be sharply different from the values for interval [5, 100]. - -NOTE: P-value approximation was optimized for 0.0001<=p<=0.2500. Thus, - P's outside of this interval are enforced to these bounds. Say, you - may quite often get P equal to exactly 0.25 or 0.0001. - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mannwhitneyutest( - real_1d_array x, - ae_int_t n, - real_1d_array y, - ae_int_t m, - double& bothtails, - double& lefttail, - double& righttail, - const xparams _params = alglib::xdefault); - -
- -
- -cmatrixdet
-cmatrixludet
-rmatrixdet
-rmatrixludet
-spdmatrixcholeskydet
-spdmatrixdet
- - - - - - - -
matdet_d_1 Determinant calculation, real matrix, short form
matdet_d_2 Determinant calculation, real matrix, full form
matdet_d_3 Determinant calculation, complex matrix, short form
matdet_d_4 Determinant calculation, complex matrix, full form
matdet_d_5 Determinant calculation, complex matrix with zero imaginary part, short form
- -
-
/************************************************************************* -Calculation of the determinant of a general matrix - -Input parameters: - A - matrix, array[0..N-1, 0..N-1] - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -Result: determinant of matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -
alglib::complex alglib::cmatrixdet( - complex_2d_array a, - const xparams _params = alglib::xdefault); -alglib::complex alglib::cmatrixdet( - complex_2d_array a, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -Determinant calculation of the matrix given by its LU decomposition. - -Input parameters: - A - LU decomposition of the matrix (output of - RMatrixLU subroutine). - Pivots - table of permutations which were made during - the LU decomposition. - Output of RMatrixLU subroutine. - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -Result: matrix determinant. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -
alglib::complex alglib::cmatrixludet( - complex_2d_array a, - integer_1d_array pivots, - const xparams _params = alglib::xdefault); -alglib::complex alglib::cmatrixludet( - complex_2d_array a, - integer_1d_array pivots, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Calculation of the determinant of a general matrix - -Input parameters: - A - matrix, array[0..N-1, 0..N-1] - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -Result: determinant of matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -
double alglib::rmatrixdet( - real_2d_array a, - const xparams _params = alglib::xdefault); -double alglib::rmatrixdet( - real_2d_array a, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -Determinant calculation of the matrix given by its LU decomposition. - -Input parameters: - A - LU decomposition of the matrix (output of - RMatrixLU subroutine). - Pivots - table of permutations which were made during - the LU decomposition. - Output of RMatrixLU subroutine. - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -Result: matrix determinant. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -
double alglib::rmatrixludet( - real_2d_array a, - integer_1d_array pivots, - const xparams _params = alglib::xdefault); -double alglib::rmatrixludet( - real_2d_array a, - integer_1d_array pivots, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Determinant calculation of the matrix given by the Cholesky decomposition. - -Input parameters: - A - Cholesky decomposition, - output of SMatrixCholesky subroutine. - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -As the determinant is equal to the product of squares of diagonal elements, -it's not necessary to specify which triangle - lower or upper - the matrix -is stored in. - -Result: - matrix determinant. - - -- ALGLIB -- - Copyright 2005-2008 by Bochkanov Sergey -*************************************************************************/ -
double alglib::spdmatrixcholeskydet( - real_2d_array a, - const xparams _params = alglib::xdefault); -double alglib::spdmatrixcholeskydet( - real_2d_array a, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Determinant calculation of the symmetric positive definite matrix. - -Input parameters: - A - matrix. Array with elements [0..N-1, 0..N-1]. - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - IsUpper - (optional) storage type: - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, both lower and upper triangles must be - filled. - -Result: - determinant of matrix A. - If matrix A is not positive definite, exception is thrown. - - -- ALGLIB -- - Copyright 2005-2008 by Bochkanov Sergey -*************************************************************************/ -
double alglib::spdmatrixdet( - real_2d_array a, - const xparams _params = alglib::xdefault); -double alglib::spdmatrixdet( - real_2d_array a, - ae_int_t n, - bool isupper, - const xparams _params = alglib::xdefault); - -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "linalg.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    real_2d_array b = "[[1,2],[2,1]]";
-    double a;
-    a = rmatrixdet(b);
-    printf("%.3f\n", double(a)); // EXPECTED: -3
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "linalg.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    real_2d_array b = "[[5,4],[4,5]]";
-    double a;
-    a = rmatrixdet(b, 2);
-    printf("%.3f\n", double(a)); // EXPECTED: 9
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "linalg.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    complex_2d_array b = "[[1+1i,2],[2,1-1i]]";
-    alglib::complex a;
-    a = cmatrixdet(b);
-    printf("%s\n", a.tostring(3).c_str()); // EXPECTED: -2
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "linalg.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    alglib::complex a;
-    complex_2d_array b = "[[5i,4],[4i,5]]";
-    a = cmatrixdet(b, 2);
-    printf("%s\n", a.tostring(3).c_str()); // EXPECTED: 9i
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "linalg.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    alglib::complex a;
-    complex_2d_array b = "[[9,1],[2,1]]";
-    a = cmatrixdet(b);
-    printf("%s\n", a.tostring(3).c_str()); // EXPECTED: 7
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* -Generation of random NxN complex matrix with given condition number C and -norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixrndcond( - ae_int_t n, - double c, - complex_2d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Generation of a random Haar distributed orthogonal complex matrix - -INPUT PARAMETERS: - N - matrix size, N>=1 - -OUTPUT PARAMETERS: - A - orthogonal NxN matrix, array[0..N-1,0..N-1] - -NOTE: this function uses algorithm described in Stewart, G. W. (1980), - "The Efficient Generation of Random Orthogonal Matrices with an - Application to Condition Estimators". - - Speaking short, to generate an (N+1)x(N+1) orthogonal matrix, it: - * takes an NxN one - * takes uniformly distributed unit vector of dimension N+1. - * constructs a Householder reflection from the vector, then applies - it to the smaller matrix (embedded in the larger size with a 1 at - the bottom right corner). - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixrndorthogonal( - ae_int_t n, - complex_2d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Multiplication of MxN complex matrix by MxM random Haar distributed -complex orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..M-1, 0..N-1] - M, N- matrix size - -OUTPUT PARAMETERS: - A - Q*A, where Q is random MxM orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixrndorthogonalfromtheleft( - complex_2d_array& a, - ae_int_t m, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Multiplication of MxN complex matrix by NxN random Haar distributed -complex orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..M-1, 0..N-1] - M, N- matrix size - -OUTPUT PARAMETERS: - A - A*Q, where Q is random NxN orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixrndorthogonalfromtheright( - complex_2d_array& a, - ae_int_t m, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Generation of random NxN Hermitian matrix with given condition number and -norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -
void alglib::hmatrixrndcond( - ae_int_t n, - double c, - complex_2d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Hermitian multiplication of NxN matrix by random Haar distributed -complex orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..N-1, 0..N-1] - N - matrix size - -OUTPUT PARAMETERS: - A - Q^H*A*Q, where Q is random NxN orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -
void alglib::hmatrixrndmultiply( - complex_2d_array& a, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Generation of random NxN Hermitian positive definite matrix with given -condition number and norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random HPD matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -
void alglib::hpdmatrixrndcond( - ae_int_t n, - double c, - complex_2d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Generation of random NxN matrix with given condition number and norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixrndcond( - ae_int_t n, - double c, - real_2d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Generation of a random uniformly distributed (Haar) orthogonal matrix - -INPUT PARAMETERS: - N - matrix size, N>=1 - -OUTPUT PARAMETERS: - A - orthogonal NxN matrix, array[0..N-1,0..N-1] - -NOTE: this function uses algorithm described in Stewart, G. W. (1980), - "The Efficient Generation of Random Orthogonal Matrices with an - Application to Condition Estimators". - - Speaking short, to generate an (N+1)x(N+1) orthogonal matrix, it: - * takes an NxN one - * takes uniformly distributed unit vector of dimension N+1. - * constructs a Householder reflection from the vector, then applies - it to the smaller matrix (embedded in the larger size with a 1 at - the bottom right corner). - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixrndorthogonal( - ae_int_t n, - real_2d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Multiplication of MxN matrix by MxM random Haar distributed orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..M-1, 0..N-1] - M, N- matrix size - -OUTPUT PARAMETERS: - A - Q*A, where Q is random MxM orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixrndorthogonalfromtheleft( - real_2d_array& a, - ae_int_t m, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Multiplication of MxN matrix by NxN random Haar distributed orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..M-1, 0..N-1] - M, N- matrix size - -OUTPUT PARAMETERS: - A - A*Q, where Q is random NxN orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixrndorthogonalfromtheright( - real_2d_array& a, - ae_int_t m, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Generation of random NxN symmetric matrix with given condition number and -norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -
void alglib::smatrixrndcond( - ae_int_t n, - double c, - real_2d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Symmetric multiplication of NxN matrix by random Haar distributed -orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..N-1, 0..N-1] - N - matrix size - -OUTPUT PARAMETERS: - A - Q'*A*Q, where Q is random NxN orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -
void alglib::smatrixrndmultiply( - real_2d_array& a, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Generation of random NxN symmetric positive definite matrix with given -condition number and norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random SPD matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -
void alglib::spdmatrixrndcond( - ae_int_t n, - double c, - real_2d_array& a, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -Matrix inverse report: -* R1 reciprocal of condition number in 1-norm -* RInf reciprocal of condition number in inf-norm -*************************************************************************/ -
class matinvreport -{ - double r1; - double rinf; -}; - -
- -
-
/************************************************************************* -Inversion of a general matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixinverse( - complex_2d_array& a, - ae_int_t& info, - matinvreport& rep, - const xparams _params = alglib::xdefault); -void alglib::cmatrixinverse( - complex_2d_array& a, - ae_int_t n, - ae_int_t& info, - matinvreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Inversion of a matrix given by its LU decomposition. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - LU decomposition of the matrix - (output of CMatrixLU subroutine). - Pivots - table of permutations - (the output of CMatrixLU subroutine). - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - -OUTPUT PARAMETERS: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 05.02.2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixluinverse( - complex_2d_array& a, - integer_1d_array pivots, - ae_int_t& info, - matinvreport& rep, - const xparams _params = alglib::xdefault); -void alglib::cmatrixluinverse( - complex_2d_array& a, - integer_1d_array pivots, - ae_int_t n, - ae_int_t& info, - matinvreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Triangular matrix inverse (complex) - -The subroutine inverts the following types of matrices: - * upper triangular - * upper triangular with unit diagonal - * lower triangular - * lower triangular with unit diagonal - -In case of an upper (lower) triangular matrix, the inverse matrix will -also be upper (lower) triangular, and after the end of the algorithm, the -inverse matrix replaces the source matrix. The elements below (above) the -main diagonal are not changed by the algorithm. - -If the matrix has a unit diagonal, the inverse matrix also has a unit -diagonal, and the diagonal elements are not passed to the algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix, array[0..N-1, 0..N-1]. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - True, if the matrix is upper triangular. - IsUnit - diagonal type (optional): - * if True, matrix has unit diagonal (a[i,i] are NOT used) - * if False, matrix diagonal is arbitrary - * if not given, False is assumed - -Output parameters: - Info - same as for RMatrixLUInverse - Rep - same as for RMatrixLUInverse - A - same as for RMatrixLUInverse. - - -- ALGLIB -- - Copyright 05.02.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixtrinverse( - complex_2d_array& a, - bool isupper, - ae_int_t& info, - matinvreport& rep, - const xparams _params = alglib::xdefault); -void alglib::cmatrixtrinverse( - complex_2d_array& a, - ae_int_t n, - bool isupper, - bool isunit, - ae_int_t& info, - matinvreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Inversion of a Hermitian positive definite matrix which is given -by Cholesky decomposition. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - Cholesky decomposition of the matrix to be inverted: - A=U'*U or A = L*L'. - Output of HPDMatrixCholesky subroutine. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - storage type (optional): - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, lower half is used. - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 10.02.2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::hpdmatrixcholeskyinverse( - complex_2d_array& a, - ae_int_t& info, - matinvreport& rep, - const xparams _params = alglib::xdefault); -void alglib::hpdmatrixcholeskyinverse( - complex_2d_array& a, - ae_int_t n, - bool isupper, - ae_int_t& info, - matinvreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Inversion of a Hermitian positive definite matrix. - -Given an upper or lower triangle of a Hermitian positive definite matrix, -the algorithm generates matrix A^-1 and saves the upper or lower triangle -depending on the input. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix to be inverted (upper or lower triangle). - Array with elements [0..N-1,0..N-1]. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - storage type (optional): - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, both lower and upper triangles must be - filled. - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 10.02.2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::hpdmatrixinverse( - complex_2d_array& a, - ae_int_t& info, - matinvreport& rep, - const xparams _params = alglib::xdefault); -void alglib::hpdmatrixinverse( - complex_2d_array& a, - ae_int_t n, - bool isupper, - ae_int_t& info, - matinvreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Inversion of a general matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - -Result: - True, if the matrix is not singular. - False, if the matrix is singular. - - -- ALGLIB -- - Copyright 2005-2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixinverse( - real_2d_array& a, - ae_int_t& info, - matinvreport& rep, - const xparams _params = alglib::xdefault); -void alglib::rmatrixinverse( - real_2d_array& a, - ae_int_t n, - ae_int_t& info, - matinvreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Inversion of a matrix given by its LU decomposition. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - LU decomposition of the matrix - (output of RMatrixLU subroutine). - Pivots - table of permutations - (the output of RMatrixLU subroutine). - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - -OUTPUT PARAMETERS: - Info - return code: - * -3 A is singular, or VERY close to singular. - it is filled by zeros in such cases. - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - solver report, see below for more info - A - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - -SOLVER REPORT - -Subroutine sets following fields of the Rep structure: -* R1 reciprocal of condition number: 1/cond(A), 1-norm. -* RInf reciprocal of condition number: 1/cond(A), inf-norm. - - -- ALGLIB routine -- - 05.02.2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixluinverse( - real_2d_array& a, - integer_1d_array pivots, - ae_int_t& info, - matinvreport& rep, - const xparams _params = alglib::xdefault); -void alglib::rmatrixluinverse( - real_2d_array& a, - integer_1d_array pivots, - ae_int_t n, - ae_int_t& info, - matinvreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Triangular matrix inverse (real) - -The subroutine inverts the following types of matrices: - * upper triangular - * upper triangular with unit diagonal - * lower triangular - * lower triangular with unit diagonal - -In case of an upper (lower) triangular matrix, the inverse matrix will -also be upper (lower) triangular, and after the end of the algorithm, the -inverse matrix replaces the source matrix. The elements below (above) the -main diagonal are not changed by the algorithm. - -If the matrix has a unit diagonal, the inverse matrix also has a unit -diagonal, and the diagonal elements are not passed to the algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix, array[0..N-1, 0..N-1]. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - True, if the matrix is upper triangular. - IsUnit - diagonal type (optional): - * if True, matrix has unit diagonal (a[i,i] are NOT used) - * if False, matrix diagonal is arbitrary - * if not given, False is assumed - -Output parameters: - Info - same as for RMatrixLUInverse - Rep - same as for RMatrixLUInverse - A - same as for RMatrixLUInverse. - - -- ALGLIB -- - Copyright 05.02.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixtrinverse( - real_2d_array& a, - bool isupper, - ae_int_t& info, - matinvreport& rep, - const xparams _params = alglib::xdefault); -void alglib::rmatrixtrinverse( - real_2d_array& a, - ae_int_t n, - bool isupper, - bool isunit, - ae_int_t& info, - matinvreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Inversion of a symmetric positive definite matrix which is given -by Cholesky decomposition. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - Cholesky decomposition of the matrix to be inverted: - A=U'*U or A = L*L'. - Output of SPDMatrixCholesky subroutine. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - storage type (optional): - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, lower half is used. - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 10.02.2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::spdmatrixcholeskyinverse( - real_2d_array& a, - ae_int_t& info, - matinvreport& rep, - const xparams _params = alglib::xdefault); -void alglib::spdmatrixcholeskyinverse( - real_2d_array& a, - ae_int_t n, - bool isupper, - ae_int_t& info, - matinvreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Inversion of a symmetric positive definite matrix. - -Given an upper or lower triangle of a symmetric positive definite matrix, -the algorithm generates matrix A^-1 and saves the upper or lower triangle -depending on the input. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix to be inverted (upper or lower triangle). - Array with elements [0..N-1,0..N-1]. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - storage type (optional): - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, both lower and upper triangles must be - filled. - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 10.02.2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::spdmatrixinverse( - real_2d_array& a, - ae_int_t& info, - matinvreport& rep, - const xparams _params = alglib::xdefault); -void alglib::spdmatrixinverse( - real_2d_array& a, - ae_int_t n, - bool isupper, - ae_int_t& info, - matinvreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "linalg.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    complex_2d_array a = "[[1i,-1],[1i,1]]";
-    ae_int_t info;
-    matinvreport rep;
-    cmatrixinverse(a, info, rep);
-    printf("%d\n", int(info)); // EXPECTED: 1
-    printf("%s\n", a.tostring(4).c_str()); // EXPECTED: [[-0.5i,-0.5i],[-0.5,0.5]]
-    printf("%.4f\n", double(rep.r1)); // EXPECTED: 0.5
-    printf("%.4f\n", double(rep.rinf)); // EXPECTED: 0.5
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "linalg.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    complex_2d_array a = "[[2,1],[1,2]]";
-    ae_int_t info;
-    matinvreport rep;
-    hpdmatrixinverse(a, info, rep);
-    printf("%d\n", int(info)); // EXPECTED: 1
-    printf("%s\n", a.tostring(4).c_str()); // EXPECTED: [[0.666666,-0.333333],[-0.333333,0.666666]]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "linalg.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    real_2d_array a = "[[1,-1],[1,1]]";
-    ae_int_t info;
-    matinvreport rep;
-    rmatrixinverse(a, info, rep);
-    printf("%d\n", int(info)); // EXPECTED: 1
-    printf("%s\n", a.tostring(4).c_str()); // EXPECTED: [[0.5,0.5],[-0.5,0.5]]
-    printf("%.4f\n", double(rep.r1)); // EXPECTED: 0.5
-    printf("%.4f\n", double(rep.rinf)); // EXPECTED: 0.5
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "linalg.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    real_2d_array a = "[[2,1],[1,2]]";
-    ae_int_t info;
-    matinvreport rep;
-    spdmatrixinverse(a, info, rep);
-    printf("%d\n", int(info)); // EXPECTED: 1
-    printf("%s\n", a.tostring(4).c_str()); // EXPECTED: [[0.666666,-0.333333],[-0.333333,0.666666]]
-    return 0;
-}
-
-
-
-
- -mcpdreport
-mcpdstate
- -mcpdaddbc
-mcpdaddec
-mcpdaddtrack
-mcpdcreate
-mcpdcreateentry
-mcpdcreateentryexit
-mcpdcreateexit
-mcpdresults
-mcpdsetbc
-mcpdsetec
-mcpdsetlc
-mcpdsetpredictionweights
-mcpdsetprior
-mcpdsettikhonovregularizer
-mcpdsolve
- - - - -
mcpd_simple1 Simple unconstrained MCPD model (no entry/exit states)
mcpd_simple2 Simple MCPD model (no entry/exit states) with equality constraints
- -
-
/************************************************************************* -This structure is a MCPD training report: - InnerIterationsCount - number of inner iterations of the - underlying optimization algorithm - OuterIterationsCount - number of outer iterations of the - underlying optimization algorithm - NFEV - number of merit function evaluations - TerminationType - termination type - (same as for MinBLEIC optimizer, positive - values denote success, negative ones - - failure) - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -
class mcpdreport -{ - ae_int_t inneriterationscount; - ae_int_t outeriterationscount; - ae_int_t nfev; - ae_int_t terminationtype; -}; - -
- -
-
/************************************************************************* -This structure is a MCPD (Markov Chains for Population Data) solver. - -You should use ALGLIB functions in order to work with this object. - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -
class mcpdstate -{ -}; - -
- -
-
/************************************************************************* -This function is used to add bound constraints on the elements of the -transition matrix P. - -MCPD solver has four types of constraints which can be placed on P: -* user-specified equality constraints (optional) -* user-specified bound constraints (optional) -* user-specified general linear constraints (optional) -* basic constraints (always present): - * non-negativity: P[i,j]>=0 - * consistency: every column of P sums to 1.0 - -Final constraints which are passed to the underlying optimizer are -calculated as intersection of all present constraints. For example, you -may specify boundary constraint on P[0,0] and equality one: - 0.1<=P[0,0]<=0.9 - P[0,0]=0.5 -Such combination of constraints will be silently reduced to their -intersection, which is P[0,0]=0.5. - -This function can be used to ADD bound constraint for one element of P -without changing constraints for other elements. - -You can also use MCPDSetBC() function which allows to place bound -constraints on arbitrary subset of elements of P. Set of constraints is -specified by BndL/BndU matrices, which may contain arbitrary combination -of finite numbers or infinities (like -INF<x<=0.5 or 0.1<=x<+INF). - -These functions (MCPDSetBC and MCPDAddBC) interact as follows: -* there is internal matrix of bound constraints which is stored in the - MCPD solver -* MCPDSetBC() replaces this matrix by another one (SET) -* MCPDAddBC() modifies one element of this matrix and leaves other ones - unchanged (ADD) -* thus MCPDAddBC() call preserves all modifications done by previous - calls, while MCPDSetBC() completely discards all changes done to the - equality constraints. - -INPUT PARAMETERS: - S - solver - I - row index of element being constrained - J - column index of element being constrained - BndL - lower bound - BndU - upper bound - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mcpdaddbc( - mcpdstate s, - ae_int_t i, - ae_int_t j, - double bndl, - double bndu, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function is used to add equality constraints on the elements of the -transition matrix P. - -MCPD solver has four types of constraints which can be placed on P: -* user-specified equality constraints (optional) -* user-specified bound constraints (optional) -* user-specified general linear constraints (optional) -* basic constraints (always present): - * non-negativity: P[i,j]>=0 - * consistency: every column of P sums to 1.0 - -Final constraints which are passed to the underlying optimizer are -calculated as intersection of all present constraints. For example, you -may specify boundary constraint on P[0,0] and equality one: - 0.1<=P[0,0]<=0.9 - P[0,0]=0.5 -Such combination of constraints will be silently reduced to their -intersection, which is P[0,0]=0.5. - -This function can be used to ADD equality constraint for one element of P -without changing constraints for other elements. - -You can also use MCPDSetEC() function which allows you to specify -arbitrary set of equality constraints in one call. - -These functions (MCPDSetEC and MCPDAddEC) interact as follows: -* there is internal matrix of equality constraints which is stored in the - MCPD solver -* MCPDSetEC() replaces this matrix by another one (SET) -* MCPDAddEC() modifies one element of this matrix and leaves other ones - unchanged (ADD) -* thus MCPDAddEC() call preserves all modifications done by previous - calls, while MCPDSetEC() completely discards all changes done to the - equality constraints. - -INPUT PARAMETERS: - S - solver - I - row index of element being constrained - J - column index of element being constrained - C - value (constraint for P[I,J]). Can be either NAN (no - constraint) or finite value from [0,1]. - -NOTES: - -1. infinite values of C will lead to exception being thrown. Values less -than 0.0 or greater than 1.0 will lead to error code being returned after -call to MCPDSolve(). - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mcpdaddec( - mcpdstate s, - ae_int_t i, - ae_int_t j, - double c, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function is used to add a track - sequence of system states at the -different moments of its evolution. - -You may add one or several tracks to the MCPD solver. In case you have -several tracks, they won't overwrite each other. For example, if you pass -two tracks, A1-A2-A3 (system at t=A+1, t=A+2 and t=A+3) and B1-B2-B3, then -solver will try to model transitions from t=A+1 to t=A+2, t=A+2 to t=A+3, -t=B+1 to t=B+2, t=B+2 to t=B+3. But it WONT mix these two tracks - i.e. it -wont try to model transition from t=A+3 to t=B+1. - -INPUT PARAMETERS: - S - solver - XY - track, array[K,N]: - * I-th row is a state at t=I - * elements of XY must be non-negative (exception will be - thrown on negative elements) - K - number of points in a track - * if given, only leading K rows of XY are used - * if not given, automatically determined from size of XY - -NOTES: - -1. Track may contain either proportional or population data: - * with proportional data all rows of XY must sum to 1.0, i.e. we have - proportions instead of absolute population values - * with population data rows of XY contain population counts and generally - do not sum to 1.0 (although they still must be non-negative) - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mcpdaddtrack( - mcpdstate s, - real_2d_array xy, - const xparams _params = alglib::xdefault); -void alglib::mcpdaddtrack( - mcpdstate s, - real_2d_array xy, - ae_int_t k, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -DESCRIPTION: - -This function creates MCPD (Markov Chains for Population Data) solver. - -This solver can be used to find transition matrix P for N-dimensional -prediction problem where transition from X[i] to X[i+1] is modelled as - X[i+1] = P*X[i] -where X[i] and X[i+1] are N-dimensional population vectors (components of -each X are non-negative), and P is a N*N transition matrix (elements of P -are non-negative, each column sums to 1.0). - -Such models arise when when: -* there is some population of individuals -* individuals can have different states -* individuals can transit from one state to another -* population size is constant, i.e. there is no new individuals and no one - leaves population -* you want to model transitions of individuals from one state into another - -USAGE: - -Here we give very brief outline of the MCPD. We strongly recommend you to -read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide -on data analysis which is available at http://www.alglib.net/dataanalysis/ - -1. User initializes algorithm state with MCPDCreate() call - -2. User adds one or more tracks - sequences of states which describe - evolution of a system being modelled from different starting conditions - -3. User may add optional boundary, equality and/or linear constraints on - the coefficients of P by calling one of the following functions: - * MCPDSetEC() to set equality constraints - * MCPDSetBC() to set bound constraints - * MCPDSetLC() to set linear constraints - -4. Optionally, user may set custom weights for prediction errors (by - default, algorithm assigns non-equal, automatically chosen weights for - errors in the prediction of different components of X). It can be done - with a call of MCPDSetPredictionWeights() function. - -5. User calls MCPDSolve() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. - -6. User calls MCPDResults() to get solution - -INPUT PARAMETERS: - N - problem dimension, N>=1 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mcpdcreate( - ae_int_t n, - mcpdstate& s, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -DESCRIPTION: - -This function is a specialized version of MCPDCreate() function, and we -recommend you to read comments for this function for general information -about MCPD solver. - -This function creates MCPD (Markov Chains for Population Data) solver -for "Entry-state" model, i.e. model where transition from X[i] to X[i+1] -is modelled as - X[i+1] = P*X[i] -where - X[i] and X[i+1] are N-dimensional state vectors - P is a N*N transition matrix -and one selected component of X[] is called "entry" state and is treated -in a special way: - system state always transits from "entry" state to some another state - system state can not transit from any state into "entry" state -Such conditions basically mean that row of P which corresponds to "entry" -state is zero. - -Such models arise when: -* there is some population of individuals -* individuals can have different states -* individuals can transit from one state to another -* population size is NOT constant - at every moment of time there is some - (unpredictable) amount of "new" individuals, which can transit into one - of the states at the next turn, but still no one leaves population -* you want to model transitions of individuals from one state into another -* but you do NOT want to predict amount of "new" individuals because it - does not depends on individuals already present (hence system can not - transit INTO entry state - it can only transit FROM it). - -This model is discussed in more details in the ALGLIB User Guide (see -http://www.alglib.net/dataanalysis/ for more data). - -INPUT PARAMETERS: - N - problem dimension, N>=2 - EntryState- index of entry state, in 0..N-1 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mcpdcreateentry( - ae_int_t n, - ae_int_t entrystate, - mcpdstate& s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -DESCRIPTION: - -This function is a specialized version of MCPDCreate() function, and we -recommend you to read comments for this function for general information -about MCPD solver. - -This function creates MCPD (Markov Chains for Population Data) solver -for "Entry-Exit-states" model, i.e. model where transition from X[i] to -X[i+1] is modelled as - X[i+1] = P*X[i] -where - X[i] and X[i+1] are N-dimensional state vectors - P is a N*N transition matrix -one selected component of X[] is called "entry" state and is treated in a -special way: - system state always transits from "entry" state to some another state - system state can not transit from any state into "entry" state -and another one component of X[] is called "exit" state and is treated in -a special way too: - system state can transit from any state into "exit" state - system state can not transit from "exit" state into any other state - transition operator discards "exit" state (makes it zero at each turn) -Such conditions basically mean that: - row of P which corresponds to "entry" state is zero - column of P which corresponds to "exit" state is zero -Multiplication by such P may decrease sum of vector components. - -Such models arise when: -* there is some population of individuals -* individuals can have different states -* individuals can transit from one state to another -* population size is NOT constant -* at every moment of time there is some (unpredictable) amount of "new" - individuals, which can transit into one of the states at the next turn -* some individuals can move (predictably) into "exit" state and leave - population at the next turn -* you want to model transitions of individuals from one state into another, - including transitions from the "entry" state and into the "exit" state. -* but you do NOT want to predict amount of "new" individuals because it - does not depends on individuals already present (hence system can not - transit INTO entry state - it can only transit FROM it). - -This model is discussed in more details in the ALGLIB User Guide (see -http://www.alglib.net/dataanalysis/ for more data). - -INPUT PARAMETERS: - N - problem dimension, N>=2 - EntryState- index of entry state, in 0..N-1 - ExitState- index of exit state, in 0..N-1 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mcpdcreateentryexit( - ae_int_t n, - ae_int_t entrystate, - ae_int_t exitstate, - mcpdstate& s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -DESCRIPTION: - -This function is a specialized version of MCPDCreate() function, and we -recommend you to read comments for this function for general information -about MCPD solver. - -This function creates MCPD (Markov Chains for Population Data) solver -for "Exit-state" model, i.e. model where transition from X[i] to X[i+1] -is modelled as - X[i+1] = P*X[i] -where - X[i] and X[i+1] are N-dimensional state vectors - P is a N*N transition matrix -and one selected component of X[] is called "exit" state and is treated -in a special way: - system state can transit from any state into "exit" state - system state can not transit from "exit" state into any other state - transition operator discards "exit" state (makes it zero at each turn) -Such conditions basically mean that column of P which corresponds to -"exit" state is zero. Multiplication by such P may decrease sum of vector -components. - -Such models arise when: -* there is some population of individuals -* individuals can have different states -* individuals can transit from one state to another -* population size is NOT constant - individuals can move into "exit" state - and leave population at the next turn, but there are no new individuals -* amount of individuals which leave population can be predicted -* you want to model transitions of individuals from one state into another - (including transitions into the "exit" state) - -This model is discussed in more details in the ALGLIB User Guide (see -http://www.alglib.net/dataanalysis/ for more data). - -INPUT PARAMETERS: - N - problem dimension, N>=2 - ExitState- index of exit state, in 0..N-1 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mcpdcreateexit( - ae_int_t n, - ae_int_t exitstate, - mcpdstate& s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -MCPD results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - P - array[N,N], transition matrix - Rep - optimization report. You should check Rep.TerminationType - in order to distinguish successful termination from - unsuccessful one. Speaking short, positive values denote - success, negative ones are failures. - More information about fields of this structure can be - found in the comments on MCPDReport datatype. - - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mcpdresults( - mcpdstate s, - real_2d_array& p, - mcpdreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function is used to add bound constraints on the elements of the -transition matrix P. - -MCPD solver has four types of constraints which can be placed on P: -* user-specified equality constraints (optional) -* user-specified bound constraints (optional) -* user-specified general linear constraints (optional) -* basic constraints (always present): - * non-negativity: P[i,j]>=0 - * consistency: every column of P sums to 1.0 - -Final constraints which are passed to the underlying optimizer are -calculated as intersection of all present constraints. For example, you -may specify boundary constraint on P[0,0] and equality one: - 0.1<=P[0,0]<=0.9 - P[0,0]=0.5 -Such combination of constraints will be silently reduced to their -intersection, which is P[0,0]=0.5. - -This function can be used to place bound constraints on arbitrary -subset of elements of P. Set of constraints is specified by BndL/BndU -matrices, which may contain arbitrary combination of finite numbers or -infinities (like -INF<x<=0.5 or 0.1<=x<+INF). - -You can also use MCPDAddBC() function which allows to ADD bound constraint -for one element of P without changing constraints for other elements. - -These functions (MCPDSetBC and MCPDAddBC) interact as follows: -* there is internal matrix of bound constraints which is stored in the - MCPD solver -* MCPDSetBC() replaces this matrix by another one (SET) -* MCPDAddBC() modifies one element of this matrix and leaves other ones - unchanged (ADD) -* thus MCPDAddBC() call preserves all modifications done by previous - calls, while MCPDSetBC() completely discards all changes done to the - equality constraints. - -INPUT PARAMETERS: - S - solver - BndL - lower bounds constraints, array[N,N]. Elements of BndL can - be finite numbers or -INF. - BndU - upper bounds constraints, array[N,N]. Elements of BndU can - be finite numbers or +INF. - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mcpdsetbc( - mcpdstate s, - real_2d_array bndl, - real_2d_array bndu, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function is used to add equality constraints on the elements of the -transition matrix P. - -MCPD solver has four types of constraints which can be placed on P: -* user-specified equality constraints (optional) -* user-specified bound constraints (optional) -* user-specified general linear constraints (optional) -* basic constraints (always present): - * non-negativity: P[i,j]>=0 - * consistency: every column of P sums to 1.0 - -Final constraints which are passed to the underlying optimizer are -calculated as intersection of all present constraints. For example, you -may specify boundary constraint on P[0,0] and equality one: - 0.1<=P[0,0]<=0.9 - P[0,0]=0.5 -Such combination of constraints will be silently reduced to their -intersection, which is P[0,0]=0.5. - -This function can be used to place equality constraints on arbitrary -subset of elements of P. Set of constraints is specified by EC, which may -contain either NAN's or finite numbers from [0,1]. NAN denotes absence of -constraint, finite number denotes equality constraint on specific element -of P. - -You can also use MCPDAddEC() function which allows to ADD equality -constraint for one element of P without changing constraints for other -elements. - -These functions (MCPDSetEC and MCPDAddEC) interact as follows: -* there is internal matrix of equality constraints which is stored in the - MCPD solver -* MCPDSetEC() replaces this matrix by another one (SET) -* MCPDAddEC() modifies one element of this matrix and leaves other ones - unchanged (ADD) -* thus MCPDAddEC() call preserves all modifications done by previous - calls, while MCPDSetEC() completely discards all changes done to the - equality constraints. - -INPUT PARAMETERS: - S - solver - EC - equality constraints, array[N,N]. Elements of EC can be - either NAN's or finite numbers from [0,1]. NAN denotes - absence of constraints, while finite value denotes - equality constraint on the corresponding element of P. - -NOTES: - -1. infinite values of EC will lead to exception being thrown. Values less -than 0.0 or greater than 1.0 will lead to error code being returned after -call to MCPDSolve(). - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mcpdsetec( - mcpdstate s, - real_2d_array ec, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function is used to set linear equality/inequality constraints on the -elements of the transition matrix P. - -This function can be used to set one or several general linear constraints -on the elements of P. Two types of constraints are supported: -* equality constraints -* inequality constraints (both less-or-equal and greater-or-equal) - -Coefficients of constraints are specified by matrix C (one of the -parameters). One row of C corresponds to one constraint. Because -transition matrix P has N*N elements, we need N*N columns to store all -coefficients (they are stored row by row), and one more column to store -right part - hence C has N*N+1 columns. Constraint kind is stored in the -CT array. - -Thus, I-th linear constraint is - P[0,0]*C[I,0] + P[0,1]*C[I,1] + .. + P[0,N-1]*C[I,N-1] + - + P[1,0]*C[I,N] + P[1,1]*C[I,N+1] + ... + - + P[N-1,N-1]*C[I,N*N-1] ?=? C[I,N*N] -where ?=? can be either "=" (CT[i]=0), "<=" (CT[i]<0) or ">=" (CT[i]>0). - -Your constraint may involve only some subset of P (less than N*N elements). -For example it can be something like - P[0,0] + P[0,1] = 0.5 -In this case you still should pass matrix with N*N+1 columns, but all its -elements (except for C[0,0], C[0,1] and C[0,N*N-1]) will be zero. - -INPUT PARAMETERS: - S - solver - C - array[K,N*N+1] - coefficients of constraints - (see above for complete description) - CT - array[K] - constraint types - (see above for complete description) - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mcpdsetlc( - mcpdstate s, - real_2d_array c, - integer_1d_array ct, - const xparams _params = alglib::xdefault); -void alglib::mcpdsetlc( - mcpdstate s, - real_2d_array c, - integer_1d_array ct, - ae_int_t k, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function is used to change prediction weights - -MCPD solver scales prediction errors as follows - Error(P) = ||W*(y-P*x)||^2 -where - x is a system state at time t - y is a system state at time t+1 - P is a transition matrix - W is a diagonal scaling matrix - -By default, weights are chosen in order to minimize relative prediction -error instead of absolute one. For example, if one component of state is -about 0.5 in magnitude and another one is about 0.05, then algorithm will -make corresponding weights equal to 2.0 and 20.0. - -INPUT PARAMETERS: - S - solver - PW - array[N], weights: - * must be non-negative values (exception will be thrown otherwise) - * zero values will be replaced by automatically chosen values - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mcpdsetpredictionweights( - mcpdstate s, - real_1d_array pw, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function allows to set prior values used for regularization of your -problem. - -By default, regularizing term is equal to r*||P-prior_P||^2, where r is a -small non-zero value, P is transition matrix, prior_P is identity matrix, -||X||^2 is a sum of squared elements of X. - -This function allows you to change prior values prior_P. You can also -change r with MCPDSetTikhonovRegularizer() function. - -INPUT PARAMETERS: - S - solver - PP - array[N,N], matrix of prior values: - 1. elements must be real numbers from [0,1] - 2. columns must sum to 1.0. - First property is checked (exception is thrown otherwise), - while second one is not checked/enforced. - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mcpdsetprior( - mcpdstate s, - real_2d_array pp, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function allows to tune amount of Tikhonov regularization being -applied to your problem. - -By default, regularizing term is equal to r*||P-prior_P||^2, where r is a -small non-zero value, P is transition matrix, prior_P is identity matrix, -||X||^2 is a sum of squared elements of X. - -This function allows you to change coefficient r. You can also change -prior values with MCPDSetPrior() function. - -INPUT PARAMETERS: - S - solver - V - regularization coefficient, finite non-negative value. It - is not recommended to specify zero value unless you are - pretty sure that you want it. - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mcpdsettikhonovregularizer( - mcpdstate s, - double v, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function is used to start solution of the MCPD problem. - -After return from this function, you can use MCPDResults() to get solution -and completion code. - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mcpdsolve( - mcpdstate s, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // The very simple MCPD example
-    //
-    // We have a loan portfolio. Our loans can be in one of two states:
-    // * normal loans ("good" ones)
-    // * past due loans ("bad" ones)
-    //
-    // We assume that:
-    // * loans can transition from any state to any other state. In 
-    //   particular, past due loan can become "good" one at any moment 
-    //   with same (fixed) probability. Not realistic, but it is toy example :)
-    // * portfolio size does not change over time
-    //
-    // Thus, we have following model
-    //     state_new = P*state_old
-    // where
-    //         ( p00  p01 )
-    //     P = (          )
-    //         ( p10  p11 )
-    //
-    // We want to model transitions between these two states using MCPD
-    // approach (Markov Chains for Proportional/Population Data), i.e.
-    // to restore hidden transition matrix P using actual portfolio data.
-    // We have:
-    // * poportional data, i.e. proportion of loans in the normal and past 
-    //   due states (not portfolio size measured in some currency, although 
-    //   it is possible to work with population data too)
-    // * two tracks, i.e. two sequences which describe portfolio
-    //   evolution from two different starting states: [1,0] (all loans 
-    //   are "good") and [0.8,0.2] (only 80% of portfolio is in the "good"
-    //   state)
-    //
-    mcpdstate s;
-    mcpdreport rep;
-    real_2d_array p;
-    real_2d_array track0 = "[[1.00000,0.00000],[0.95000,0.05000],[0.92750,0.07250],[0.91738,0.08263],[0.91282,0.08718]]";
-    real_2d_array track1 = "[[0.80000,0.20000],[0.86000,0.14000],[0.88700,0.11300],[0.89915,0.10085]]";
-
-    mcpdcreate(2, s);
-    mcpdaddtrack(s, track0);
-    mcpdaddtrack(s, track1);
-    mcpdsolve(s);
-    mcpdresults(s, p, rep);
-
-    //
-    // Hidden matrix P is equal to
-    //         ( 0.95  0.50 )
-    //         (            )
-    //         ( 0.05  0.50 )
-    // which means that "good" loans can become "bad" with 5% probability, 
-    // while "bad" loans will return to good state with 50% probability.
-    //
-    printf("%s\n", p.tostring(2).c_str()); // EXPECTED: [[0.95,0.50],[0.05,0.50]]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // Simple MCPD example
-    //
-    // We have a loan portfolio. Our loans can be in one of three states:
-    // * normal loans
-    // * past due loans
-    // * charged off loans
-    //
-    // We assume that:
-    // * normal loan can stay normal or become past due (but not charged off)
-    // * past due loan can stay past due, become normal or charged off
-    // * charged off loan will stay charged off for the rest of eternity
-    // * portfolio size does not change over time
-    // Not realistic, but it is toy example :)
-    //
-    // Thus, we have following model
-    //     state_new = P*state_old
-    // where
-    //         ( p00  p01    )
-    //     P = ( p10  p11    )
-    //         (      p21  1 )
-    // i.e. four elements of P are known a priori.
-    //
-    // Although it is possible (given enough data) to In order to enforce 
-    // this property we set equality constraints on these elements.
-    //
-    // We want to model transitions between these two states using MCPD
-    // approach (Markov Chains for Proportional/Population Data), i.e.
-    // to restore hidden transition matrix P using actual portfolio data.
-    // We have:
-    // * poportional data, i.e. proportion of loans in the current and past 
-    //   due states (not portfolio size measured in some currency, although 
-    //   it is possible to work with population data too)
-    // * two tracks, i.e. two sequences which describe portfolio
-    //   evolution from two different starting states: [1,0,0] (all loans 
-    //   are "good") and [0.8,0.2,0.0] (only 80% of portfolio is in the "good"
-    //   state)
-    //
-    mcpdstate s;
-    mcpdreport rep;
-    real_2d_array p;
-    real_2d_array track0 = "[[1.000000,0.000000,0.000000],[0.950000,0.050000,0.000000],[0.927500,0.060000,0.012500],[0.911125,0.061375,0.027500],[0.896256,0.060900,0.042844]]";
-    real_2d_array track1 = "[[0.800000,0.200000,0.000000],[0.860000,0.090000,0.050000],[0.862000,0.065500,0.072500],[0.851650,0.059475,0.088875],[0.838805,0.057451,0.103744]]";
-
-    mcpdcreate(3, s);
-    mcpdaddtrack(s, track0);
-    mcpdaddtrack(s, track1);
-    mcpdaddec(s, 0, 2, 0.0);
-    mcpdaddec(s, 1, 2, 0.0);
-    mcpdaddec(s, 2, 2, 1.0);
-    mcpdaddec(s, 2, 0, 0.0);
-    mcpdsolve(s);
-    mcpdresults(s, p, rep);
-
-    //
-    // Hidden matrix P is equal to
-    //         ( 0.95 0.50      )
-    //         ( 0.05 0.25      )
-    //         (      0.25 1.00 ) 
-    // which means that "good" loans can become past due with 5% probability, 
-    // while past due loans will become charged off with 25% probability or
-    // return back to normal state with 50% probability.
-    //
-    printf("%s\n", p.tostring(2).c_str()); // EXPECTED: [[0.95,0.50,0.00],[0.05,0.25,0.00],[0.00,0.25,1.00]]
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* -This structure stores optimization report: -* iterationscount number of iterations -* nfev number of gradient evaluations -* terminationtype termination type (see below) - -TERMINATION CODES - -terminationtype field contains completion code, which can be: - -8 internal integrity control detected infinite or NAN values in - function/gradient. Abnormal termination signalled. - -3 inconsistent constraints. - 1 relative function improvement is no more than EpsF. - 2 relative step is no more than EpsX. - 4 gradient norm is no more than EpsG - 5 MaxIts steps was taken - 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - 8 terminated by user who called minbcrequesttermination(). X contains - point which was "current accepted" when termination request was - submitted. -*************************************************************************/ -
class minbcreport -{ - ae_int_t iterationscount; - ae_int_t nfev; - ae_int_t varidx; - ae_int_t terminationtype; -}; - -
- -
-
/************************************************************************* -This object stores nonlinear optimizer state. -You should use functions provided by MinBC subpackage to work with this -object -*************************************************************************/ -
class minbcstate -{ -}; - -
- -
-
/************************************************************************* - BOX CONSTRAINED OPTIMIZATION - WITH FAST ACTIVATION OF MULTIPLE BOX CONSTRAINTS - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments subject to box -constraints (with some of box constraints actually being equality ones). - -This optimizer uses algorithm similar to that of MinBLEIC (optimizer with -general linear constraints), but presence of box-only constraints allows -us to use faster constraint activation strategies. On large-scale problems, -with multiple constraints active at the solution, this optimizer can be -several times faster than BLEIC. - -REQUIREMENTS: -* user must provide function value and gradient -* starting point X0 must be feasible or - not too far away from the feasible set -* grad(f) must be Lipschitz continuous on a level set: - L = { x : f(x)<=f(x0) } -* function must be defined everywhere on the feasible set F - -USAGE: - -Constrained optimization if far more complex than the unconstrained one. -Here we give very brief outline of the BC optimizer. We strongly recommend -you to read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide -on optimization, which is available at http://www.alglib.net/optimization/ - -1. User initializes algorithm state with MinBCCreate() call - -2. USer adds box constraints by calling MinBCSetBC() function. - -3. User sets stopping conditions with MinBCSetCond(). - -4. User calls MinBCOptimize() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. - -5. User calls MinBCResults() to get solution - -6. Optionally user may call MinBCRestartFrom() to solve another problem - with same N but another starting point. - MinBCRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size ofX - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbccreate( - real_1d_array x, - minbcstate& state, - const xparams _params = alglib::xdefault); -void alglib::minbccreate( - ae_int_t n, - real_1d_array x, - minbcstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -The subroutine is finite difference variant of MinBCCreate(). It uses -finite differences in order to differentiate target function. - -Description below contains information which is specific to this function -only. We recommend to read comments on MinBCCreate() in order to get -more information about creation of BC optimizer. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[0..N-1]. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinBCSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large truncation errors, while too small - step will result in too large numerical errors. 1.0E-6 can be good - value to start with. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. CG needs exact gradient values. Imprecise - gradient may slow down convergence, especially on highly nonlinear - problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbccreatef( - real_1d_array x, - double diffstep, - minbcstate& state, - const xparams _params = alglib::xdefault); -void alglib::minbccreatef( - ae_int_t n, - real_1d_array x, - double diffstep, - minbcstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic gradient. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function at the initial point -(note: future versions may also perform check at the final point) and -compares numerical gradient with analytic one provided by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both gradients and specific components highlighted as -suspicious by the OptGuard. - -The primary OptGuard report can be retrieved with minbcoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with minbcsetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbcoptguardgradient( - minbcstate state, - double teststep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #0 - -Nonsmoothness (non-C1) test #0 studies function values (not gradient!) -obtained during line searches and monitors behavior of the directional -derivative estimate. - -This test is less powerful than test #1, but it does not depend on the -gradient values and thus it is more robust against artifacts introduced by -numerical differentiation. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #0 "strong" report - lngrep - C1 test #0 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbcoptguardnonc1test0results( - minbcstate state, - optguardnonc1test0report& strrep, - optguardnonc1test0report& lngrep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #1 - -Nonsmoothness (non-C1) test #1 studies individual components of the -gradient computed during line search. - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #1 "strong" report - lngrep - C1 test #1 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbcoptguardnonc1test1results( - minbcstate state, - optguardnonc1test1report& strrep, - optguardnonc1test1report& lngrep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -=== PRIMARY REPORT ======================================================= - -OptGuard performs several checks which are intended to catch common errors -in the implementation of nonlinear function/gradient: -* incorrect analytic gradient -* discontinuous (non-C0) target functions (constraints) -* nonsmooth (non-C1) target functions (constraints) - -Each of these checks is activated with appropriate function: -* minbcoptguardgradient() for gradient verification -* minbcoptguardsmoothness() for C0/C1 checks - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradvidx for specific variable (gradient element) suspected - * rep.badgradxbase, a point where gradient is tested - * rep.badgraduser, user-provided gradient (stored as 2D matrix with - single row in order to make report structure compatible with more - complex optimizers like MinNLC or MinLM) - * rep.badgradnum, reference gradient obtained via numerical - differentiation (stored as 2D matrix with single row in order to make - report structure compatible with more complex optimizers like MinNLC - or MinLM) -* rep.nonc0suspected -* rep.nonc1suspected - -=== ADDITIONAL REPORTS/LOGS ============================================== - -Several different tests are performed to catch C0/C1 errors, you can find -out specific test signaled error by looking to: -* rep.nonc0test0positive, for non-C0 test #0 -* rep.nonc1test0positive, for non-C1 test #0 -* rep.nonc1test1positive, for non-C1 test #1 - -Additional information (including line search logs) can be obtained by -means of: -* minbcoptguardnonc1test0results() -* minbcoptguardnonc1test1results() -which return detailed error reports, specific points where discontinuities -were found, and so on. - -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - generic OptGuard report; more detailed reports can be - retrieved with other functions. - -NOTE: false negatives (nonsmooth problems are not identified as nonsmooth - ones) are possible although unlikely. - - The reason is that you need to make several evaluations around - nonsmoothness in order to accumulate enough information about - function curvature. Say, if you start right from the nonsmooth point, - optimizer simply won't get enough data to understand what is going - wrong before it terminates due to abrupt changes in the derivative. - It is also possible that "unlucky" step will move us to the - termination too quickly. - - Our current approach is to have less than 0.1% false negatives in - our test examples (measured with multiple restarts from random - points), and to have exactly 0% false positives. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbcoptguardresults( - minbcstate state, - optguardreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) -b) nonsmooth target function (non-C1) - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbcoptguardsmoothness( - minbcstate state, - const xparams _params = alglib::xdefault); -void alglib::minbcoptguardsmoothness( - minbcstate state, - ae_int_t level, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This family of functions is used to launcn iterations of nonlinear optimizer - -These functions accept following parameters: - state - algorithm state - func - callback which calculates function (or merit function) - value func at given point x - grad - callback which calculates function (or merit function) - value func and gradient grad at given point x - rep - optional callback which is called after each iteration - can be NULL - ptr - optional pointer which is passed to func/grad/hess/jac/rep - can be NULL - -NOTES: - -1. This function has two different implementations: one which uses exact - (analytical) user-supplied gradient, and one which uses function value - only and numerically differentiates function in order to obtain - gradient. - - Depending on the specific function used to create optimizer object - (either MinBCCreate() for analytical gradient or MinBCCreateF() - for numerical differentiation) you should choose appropriate variant of - MinBCOptimize() - one which accepts function AND gradient or one - which accepts function ONLY. - - Be careful to choose variant of MinBCOptimize() which corresponds to - your optimization scheme! Table below lists different combinations of - callback (function/gradient) passed to MinBCOptimize() and specific - function used to create optimizer. - - - | USER PASSED TO MinBCOptimize() - CREATED WITH | function only | function and gradient - ------------------------------------------------------------ - MinBCCreateF() | works FAILS - MinBCCreate() | FAILS works - - Here "FAIL" denotes inappropriate combinations of optimizer creation - function and MinBCOptimize() version. Attemps to use such - combination (for example, to create optimizer with MinBCCreateF() - and to pass gradient information to MinCGOptimize()) will lead to - exception being thrown. Either you did not pass gradient when it WAS - needed or you passed gradient when it was NOT needed. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void minbcoptimize(minbcstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void minbcoptimize(minbcstate &state, - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbcrequesttermination( - minbcstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine restarts algorithm from new point. -All optimization parameters (including constraints) are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure previously allocated with MinBCCreate call. - X - new starting point. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbcrestartfrom( - minbcstate state, - real_1d_array x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -BC results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report. You should check Rep.TerminationType - in order to distinguish successful termination from - unsuccessful one: - * -8 internal integrity control detected infinite or - NAN values in function/gradient. Abnormal - termination signalled. - * -3 inconsistent constraints. - * 1 relative function improvement is no more than EpsF. - * 2 scaled step is no more than EpsX. - * 4 scaled gradient norm is no more than EpsG. - * 5 MaxIts steps was taken - * 8 terminated by user who called minbcrequesttermination(). - X contains point which was "current accepted" when - termination request was submitted. - More information about fields of this structure can be - found in the comments on MinBCReport datatype. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbcresults( - minbcstate state, - real_1d_array& x, - minbcreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -BC results - -Buffered implementation of MinBCResults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbcresultsbuf( - minbcstate state, - real_1d_array& x, - minbcreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets boundary constraints for BC optimizer. - -Boundary constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with MinBCRestartFrom(). - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF. - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF. - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - -NOTE 2: this solver has following useful properties: -* bound constraints are always satisfied exactly -* function is evaluated only INSIDE area specified by bound constraints, - even when numerical differentiation is used (algorithm adjusts nodes - according to boundary constraints) - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbcsetbc( - minbcstate state, - real_1d_array bndl, - real_1d_array bndu, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function sets stopping conditions for the optimizer. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|<EpsG is satisfied, where: - * |.| means Euclidian norm - * v - scaled gradient vector, v[i]=g[i]*s[i] - * g - gradient - * s - scaling coefficients set by MinBCSetScale() - EpsF - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - is satisfied. - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - step vector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinBCSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead -to automatic stopping criterion selection. - -NOTE: when SetCond() called with non-zero MaxIts, BC solver may perform - slightly more than MaxIts iterations. I.e., MaxIts sets non-strict - limit on iterations count. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbcsetcond( - minbcstate state, - double epsg, - double epsf, - double epsx, - ae_int_t maxits, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -Modification of the preconditioner: preconditioning is turned off. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbcsetprecdefault( - minbcstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Modification of the preconditioner: diagonal of approximate Hessian is -used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - D - diagonal of the approximate Hessian, array[0..N-1], - (if larger, only leading N elements are used). - -NOTE 1: D[i] should be positive. Exception will be thrown otherwise. - -NOTE 2: you should pass diagonal of approximate Hessian - NOT ITS INVERSE. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbcsetprecdiag( - minbcstate state, - real_1d_array d, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Modification of the preconditioner: scale-based diagonal preconditioning. - -This preconditioning mode can be useful when you don't have approximate -diagonal of Hessian, but you know that your variables are badly scaled -(for example, one variable is in [1,10], and another in [1000,100000]), -and most part of the ill-conditioning comes from different scales of vars. - -In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2), -can greatly improve convergence. - -IMPRTANT: you should set scale of your variables with MinBCSetScale() -call (before or after MinBCSetPrecScale() call). Without knowledge of -the scale of your variables scale-based preconditioner will be just unit -matrix. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbcsetprecscale( - minbcstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets scaling coefficients for BC optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of the optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -In most optimizers (and in the BC too) scaling is NOT a form of -preconditioning. It just affects stopping conditions. You should set -preconditioner by separate call to one of the MinBCSetPrec...() -functions. - -There is a special preconditioning mode, however, which uses scaling -coefficients to form diagonal preconditioning matrix. You can turn this -mode on, if you want. But you should understand that scaling is not the -same thing as preconditioning - these are two different, although related -forms of tuning solver. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbcsetscale( - minbcstate state, - real_1d_array s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which lead to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbcsetstpmax( - minbcstate state, - double stpmax, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinBCOptimize(). - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbcsetxrep( - minbcstate state, - bool needxrep, - const xparams _params = alglib::xdefault); - -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void function1_grad(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr) 
-{
-    //
-    // this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4
-    // and its derivatives df/d0 and df/dx1
-    //
-    func = 100*pow(x[0]+3,4) + pow(x[1]-3,4);
-    grad[0] = 400*pow(x[0]+3,3);
-    grad[1] = 4*pow(x[1]-3,3);
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of
-    //
-    //     f(x,y) = 100*(x+3)^4+(y-3)^4
-    //
-    // subject to box constraints
-    //
-    //     -1<=x<=+1, -1<=y<=+1
-    //
-    // using MinBC optimizer with:
-    // * initial point x=[0,0]
-    // * unit scale being set for all variables (see minbcsetscale for more info)
-    // * stopping criteria set to "terminate after short enough step"
-    // * OptGuard integrity check being used to check problem statement
-    //   for some common errors like nonsmoothness or bad analytic gradient
-    //
-    // First, we create optimizer object and tune its properties:
-    // * set box constraints
-    // * set variable scales
-    // * set stopping criteria
-    //
-    real_1d_array x = "[0,0]";
-    real_1d_array s = "[1,1]";
-    real_1d_array bndl = "[-1,-1]";
-    real_1d_array bndu = "[+1,+1]";
-    minbcstate state;
-    double epsg = 0;
-    double epsf = 0;
-    double epsx = 0.000001;
-    ae_int_t maxits = 0;
-    minbccreate(x, state);
-    minbcsetbc(state, bndl, bndu);
-    minbcsetscale(state, s);
-    minbcsetcond(state, epsg, epsf, epsx, maxits);
-
-    //
-    // Then we activate OptGuard integrity checking.
-    //
-    // OptGuard monitor helps to catch common coding and problem statement
-    // issues, like:
-    // * discontinuity of the target function (C0 continuity violation)
-    // * nonsmoothness of the target function (C1 continuity violation)
-    // * erroneous analytic gradient, i.e. one inconsistent with actual
-    //   change in the target/constraints
-    //
-    // OptGuard is essential for early prototyping stages because such
-    // problems often result in premature termination of the optimizer
-    // which is really hard to distinguish from the correct termination.
-    //
-    // IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL
-    //            DIFFERENTIATION. DO NOT USE IT IN PRODUCTION CODE!!!!!!!
-    //
-    //            Other OptGuard checks add moderate overhead, but anyway
-    //            it is better to turn them off when they are not needed.
-    //
-    minbcoptguardsmoothness(state);
-    minbcoptguardgradient(state, 0.001);
-
-    //
-    // Optimize and evaluate results
-    //
-    minbcreport rep;
-    alglib::minbcoptimize(state, function1_grad);
-    minbcresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [-1,1]
-
-    //
-    // Check that OptGuard did not report errors
-    //
-    // NOTE: want to test OptGuard? Try breaking the gradient - say, add
-    //       1.0 to some of its components.
-    //
-    optguardreport ogrep;
-    minbcoptguardresults(state, ogrep);
-    printf("%s\n", ogrep.badgradsuspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc0suspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc1suspected ? "true" : "false"); // EXPECTED: false
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void function1_func(const real_1d_array &x, double &func, void *ptr)
-{
-    //
-    // this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4
-    //
-    func = 100*pow(x[0]+3,4) + pow(x[1]-3,4);
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of
-    //
-    //     f(x,y) = 100*(x+3)^4+(y-3)^4
-    //
-    // subject to box constraints
-    //
-    //    -1<=x<=+1, -1<=y<=+1
-    //
-    // using MinBC optimizer with:
-    // * numerical differentiation being used
-    // * initial point x=[0,0]
-    // * unit scale being set for all variables (see minbcsetscale for more info)
-    // * stopping criteria set to "terminate after short enough step"
-    // * OptGuard integrity check being used to check problem statement
-    //   for some common errors like nonsmoothness or bad analytic gradient
-    //
-    real_1d_array x = "[0,0]";
-    real_1d_array s = "[1,1]";
-    real_1d_array bndl = "[-1,-1]";
-    real_1d_array bndu = "[+1,+1]";
-    minbcstate state;
-    double epsg = 0;
-    double epsf = 0;
-    double epsx = 0.000001;
-    ae_int_t maxits = 0;
-    double diffstep = 1.0e-6;
-
-    //
-    // Now we are ready to actually optimize something:
-    // * first we create optimizer
-    // * we add boundary constraints
-    // * we tune stopping conditions
-    // * and, finally, optimize and obtain results...
-    //
-    minbccreatef(x, diffstep, state);
-    minbcsetbc(state, bndl, bndu);
-    minbcsetscale(state, s);
-    minbcsetcond(state, epsg, epsf, epsx, maxits);
-
-    //
-    // Then we activate OptGuard integrity checking.
-    //
-    // Numerical differentiation always produces "correct" gradient
-    // (with some truncation error, but unbiased). Thus, we just have
-    // to check smoothness properties of the target: C0 and C1 continuity.
-    //
-    // Sometimes user accidentally tries to solve nonsmooth problems
-    // with smooth optimizer. OptGuard helps to detect such situations
-    // early, at the prototyping stage.
-    //
-    minbcoptguardsmoothness(state);
-
-    //
-    // Optimize and evaluate results
-    //
-    minbcreport rep;
-    alglib::minbcoptimize(state, function1_func);
-    minbcresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [-1,1]
-
-    //
-    // Check that OptGuard did not report errors
-    //
-    // Want to challenge OptGuard? Try to make your problem
-    // nonsmooth by replacing 100*(x+3)^4 by 100*|x+3| and
-    // re-run optimizer.
-    //
-    optguardreport ogrep;
-    minbcoptguardresults(state, ogrep);
-    printf("%s\n", ogrep.nonc0suspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc1suspected ? "true" : "false"); // EXPECTED: false
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* -This structure stores optimization report: -* IterationsCount number of iterations -* NFEV number of gradient evaluations -* TerminationType termination type (see below) - -TERMINATION CODES - -TerminationType field contains completion code, which can be: - -8 internal integrity control detected infinite or NAN values in - function/gradient. Abnormal termination signalled. - -3 inconsistent constraints. Feasible point is - either nonexistent or too hard to find. Try to - restart optimizer with better initial approximation - 1 relative function improvement is no more than EpsF. - 2 relative step is no more than EpsX. - 4 gradient norm is no more than EpsG - 5 MaxIts steps was taken - 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - 8 terminated by user who called minbleicrequesttermination(). X contains - point which was "current accepted" when termination request was - submitted. - -ADDITIONAL FIELDS - -There are additional fields which can be used for debugging: -* DebugEqErr error in the equality constraints (2-norm) -* DebugFS f, calculated at projection of initial point - to the feasible set -* DebugFF f, calculated at the final point -* DebugDX |X_start-X_final| -*************************************************************************/ -
class minbleicreport -{ - ae_int_t iterationscount; - ae_int_t nfev; - ae_int_t varidx; - ae_int_t terminationtype; - double debugeqerr; - double debugfs; - double debugff; - double debugdx; - ae_int_t debugfeasqpits; - ae_int_t debugfeasgpaits; - ae_int_t inneriterationscount; - ae_int_t outeriterationscount; -}; - -
- -
-
/************************************************************************* -This object stores nonlinear optimizer state. -You should use functions provided by MinBLEIC subpackage to work with this -object -*************************************************************************/ -
class minbleicstate -{ -}; - -
- -
-
/************************************************************************* - BOUND CONSTRAINED OPTIMIZATION - WITH ADDITIONAL LINEAR EQUALITY AND INEQUALITY CONSTRAINTS - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments subject to any -combination of: -* bound constraints -* linear inequality constraints -* linear equality constraints - -REQUIREMENTS: -* user must provide function value and gradient -* starting point X0 must be feasible or - not too far away from the feasible set -* grad(f) must be Lipschitz continuous on a level set: - L = { x : f(x)<=f(x0) } -* function must be defined everywhere on the feasible set F - -USAGE: - -Constrained optimization if far more complex than the unconstrained one. -Here we give very brief outline of the BLEIC optimizer. We strongly recommend -you to read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide -on optimization, which is available at http://www.alglib.net/optimization/ - -1. User initializes algorithm state with MinBLEICCreate() call - -2. USer adds boundary and/or linear constraints by calling - MinBLEICSetBC() and MinBLEICSetLC() functions. - -3. User sets stopping conditions with MinBLEICSetCond(). - -4. User calls MinBLEICOptimize() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. - -5. User calls MinBLEICResults() to get solution - -6. Optionally user may call MinBLEICRestartFrom() to solve another problem - with same N but another starting point. - MinBLEICRestartFrom() allows to reuse already initialized structure. - -NOTE: if you have box-only constraints (no general linear constraints), - then MinBC optimizer can be better option. It uses special, faster - constraint activation method, which performs better on problems with - multiple constraints active at the solution. - - On small-scale problems performance of MinBC is similar to that of - MinBLEIC, but on large-scale ones (hundreds and thousands of active - constraints) it can be several times faster than MinBLEIC. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size ofX - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleiccreate( - real_1d_array x, - minbleicstate& state, - const xparams _params = alglib::xdefault); -void alglib::minbleiccreate( - ae_int_t n, - real_1d_array x, - minbleicstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -The subroutine is finite difference variant of MinBLEICCreate(). It uses -finite differences in order to differentiate target function. - -Description below contains information which is specific to this function -only. We recommend to read comments on MinBLEICCreate() in order to get -more information about creation of BLEIC optimizer. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[0..N-1]. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinBLEICSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large truncation errors, while too small - step will result in too large numerical errors. 1.0E-6 can be good - value to start with. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. CG needs exact gradient values. Imprecise - gradient may slow down convergence, especially on highly nonlinear - problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleiccreatef( - real_1d_array x, - double diffstep, - minbleicstate& state, - const xparams _params = alglib::xdefault); -void alglib::minbleiccreatef( - ae_int_t n, - real_1d_array x, - double diffstep, - minbleicstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic gradient. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function at the initial point -(note: future versions may also perform check at the final point) and -compares numerical gradient with analytic one provided by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both gradients and specific components highlighted as -suspicious by the OptGuard. - -The primary OptGuard report can be retrieved with minbleicoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with minbleicsetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleicoptguardgradient( - minbleicstate state, - double teststep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #0 - -Nonsmoothness (non-C1) test #0 studies function values (not gradient!) -obtained during line searches and monitors behavior of the directional -derivative estimate. - -This test is less powerful than test #1, but it does not depend on the -gradient values and thus it is more robust against artifacts introduced by -numerical differentiation. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #0 "strong" report - lngrep - C1 test #0 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleicoptguardnonc1test0results( - minbleicstate state, - optguardnonc1test0report& strrep, - optguardnonc1test0report& lngrep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #1 - -Nonsmoothness (non-C1) test #1 studies individual components of the -gradient computed during line search. - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #1 "strong" report - lngrep - C1 test #1 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleicoptguardnonc1test1results( - minbleicstate state, - optguardnonc1test1report& strrep, - optguardnonc1test1report& lngrep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -=== PRIMARY REPORT ======================================================= - -OptGuard performs several checks which are intended to catch common errors -in the implementation of nonlinear function/gradient: -* incorrect analytic gradient -* discontinuous (non-C0) target functions (constraints) -* nonsmooth (non-C1) target functions (constraints) - -Each of these checks is activated with appropriate function: -* minbleicoptguardgradient() for gradient verification -* minbleicoptguardsmoothness() for C0/C1 checks - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradvidx for specific variable (gradient element) suspected - * rep.badgradxbase, a point where gradient is tested - * rep.badgraduser, user-provided gradient (stored as 2D matrix with - single row in order to make report structure compatible with more - complex optimizers like MinNLC or MinLM) - * rep.badgradnum, reference gradient obtained via numerical - differentiation (stored as 2D matrix with single row in order to make - report structure compatible with more complex optimizers like MinNLC - or MinLM) -* rep.nonc0suspected -* rep.nonc1suspected - -=== ADDITIONAL REPORTS/LOGS ============================================== - -Several different tests are performed to catch C0/C1 errors, you can find -out specific test signaled error by looking to: -* rep.nonc0test0positive, for non-C0 test #0 -* rep.nonc1test0positive, for non-C1 test #0 -* rep.nonc1test1positive, for non-C1 test #1 - -Additional information (including line search logs) can be obtained by -means of: -* minbleicoptguardnonc1test0results() -* minbleicoptguardnonc1test1results() -which return detailed error reports, specific points where discontinuities -were found, and so on. - -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - generic OptGuard report; more detailed reports can be - retrieved with other functions. - -NOTE: false negatives (nonsmooth problems are not identified as nonsmooth - ones) are possible although unlikely. - - The reason is that you need to make several evaluations around - nonsmoothness in order to accumulate enough information about - function curvature. Say, if you start right from the nonsmooth point, - optimizer simply won't get enough data to understand what is going - wrong before it terminates due to abrupt changes in the derivative. - It is also possible that "unlucky" step will move us to the - termination too quickly. - - Our current approach is to have less than 0.1% false negatives in - our test examples (measured with multiple restarts from random - points), and to have exactly 0% false positives. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleicoptguardresults( - minbleicstate state, - optguardreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) -b) nonsmooth target function (non-C1) - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleicoptguardsmoothness( - minbleicstate state, - const xparams _params = alglib::xdefault); -void alglib::minbleicoptguardsmoothness( - minbleicstate state, - ae_int_t level, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This family of functions is used to launcn iterations of nonlinear optimizer - -These functions accept following parameters: - state - algorithm state - func - callback which calculates function (or merit function) - value func at given point x - grad - callback which calculates function (or merit function) - value func and gradient grad at given point x - rep - optional callback which is called after each iteration - can be NULL - ptr - optional pointer which is passed to func/grad/hess/jac/rep - can be NULL - -NOTES: - -1. This function has two different implementations: one which uses exact - (analytical) user-supplied gradient, and one which uses function value - only and numerically differentiates function in order to obtain - gradient. - - Depending on the specific function used to create optimizer object - (either MinBLEICCreate() for analytical gradient or MinBLEICCreateF() - for numerical differentiation) you should choose appropriate variant of - MinBLEICOptimize() - one which accepts function AND gradient or one - which accepts function ONLY. - - Be careful to choose variant of MinBLEICOptimize() which corresponds to - your optimization scheme! Table below lists different combinations of - callback (function/gradient) passed to MinBLEICOptimize() and specific - function used to create optimizer. - - - | USER PASSED TO MinBLEICOptimize() - CREATED WITH | function only | function and gradient - ------------------------------------------------------------ - MinBLEICCreateF() | work FAIL - MinBLEICCreate() | FAIL work - - Here "FAIL" denotes inappropriate combinations of optimizer creation - function and MinBLEICOptimize() version. Attemps to use such - combination (for example, to create optimizer with MinBLEICCreateF() - and to pass gradient information to MinBLEICOptimize()) will lead to - exception being thrown. Either you did not pass gradient when it WAS - needed or you passed gradient when it was NOT needed. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void minbleicoptimize(minbleicstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void minbleicoptimize(minbleicstate &state, - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleicrequesttermination( - minbleicstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine restarts algorithm from new point. -All optimization parameters (including constraints) are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure previously allocated with MinBLEICCreate call. - X - new starting point. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleicrestartfrom( - minbleicstate state, - real_1d_array x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -BLEIC results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report. You should check Rep.TerminationType - in order to distinguish successful termination from - unsuccessful one: - * -8 internal integrity control detected infinite or - NAN values in function/gradient. Abnormal - termination signalled. - * -3 inconsistent constraints. Feasible point is - either nonexistent or too hard to find. Try to - restart optimizer with better initial approximation - * 1 relative function improvement is no more than EpsF. - * 2 scaled step is no more than EpsX. - * 4 scaled gradient norm is no more than EpsG. - * 5 MaxIts steps was taken - * 8 terminated by user who called minbleicrequesttermination(). - X contains point which was "current accepted" when - termination request was submitted. - More information about fields of this structure can be - found in the comments on MinBLEICReport datatype. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleicresults( - minbleicstate state, - real_1d_array& x, - minbleicreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -BLEIC results - -Buffered implementation of MinBLEICResults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleicresultsbuf( - minbleicstate state, - real_1d_array& x, - minbleicreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets boundary constraints for BLEIC optimizer. - -Boundary constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with MinBLEICRestartFrom(). - -NOTE: if you have box-only constraints (no general linear constraints), - then MinBC optimizer can be better option. It uses special, faster - constraint activation method, which performs better on problems with - multiple constraints active at the solution. - - On small-scale problems performance of MinBC is similar to that of - MinBLEIC, but on large-scale ones (hundreds and thousands of active - constraints) it can be several times faster than MinBLEIC. - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF. - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF. - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - -NOTE 2: this solver has following useful properties: -* bound constraints are always satisfied exactly -* function is evaluated only INSIDE area specified by bound constraints, - even when numerical differentiation is used (algorithm adjusts nodes - according to boundary constraints) - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleicsetbc( - minbleicstate state, - real_1d_array bndl, - real_1d_array bndu, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function sets stopping conditions for the optimizer. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|<EpsG is satisfied, where: - * |.| means Euclidian norm - * v - scaled gradient vector, v[i]=g[i]*s[i] - * g - gradient - * s - scaling coefficients set by MinBLEICSetScale() - EpsF - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - is satisfied. - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - step vector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinBLEICSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead -to automatic stopping criterion selection. - -NOTE: when SetCond() called with non-zero MaxIts, BLEIC solver may perform - slightly more than MaxIts iterations. I.e., MaxIts sets non-strict - limit on iterations count. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleicsetcond( - minbleicstate state, - double epsg, - double epsf, - double epsx, - ae_int_t maxits, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -This function sets linear constraints for BLEIC optimizer. - -Linear constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with MinBLEICRestartFrom(). - -INPUT PARAMETERS: - State - structure previously allocated with MinBLEICCreate call. - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -NOTE 1: linear (non-bound) constraints are satisfied only approximately: -* there always exists some minor violation (about Epsilon in magnitude) - due to rounding errors -* numerical differentiation, if used, may lead to function evaluations - outside of the feasible area, because algorithm does NOT change - numerical differentiation formula according to linear constraints. -If you want constraints to be satisfied exactly, try to reformulate your -problem in such manner that all constraints will become boundary ones -(this kind of constraints is always satisfied exactly, both in the final -solution and in all intermediate points). - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleicsetlc( - minbleicstate state, - real_2d_array c, - integer_1d_array ct, - const xparams _params = alglib::xdefault); -void alglib::minbleicsetlc( - minbleicstate state, - real_2d_array c, - integer_1d_array ct, - ae_int_t k, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Modification of the preconditioner: preconditioning is turned off. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleicsetprecdefault( - minbleicstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Modification of the preconditioner: diagonal of approximate Hessian is -used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - D - diagonal of the approximate Hessian, array[0..N-1], - (if larger, only leading N elements are used). - -NOTE 1: D[i] should be positive. Exception will be thrown otherwise. - -NOTE 2: you should pass diagonal of approximate Hessian - NOT ITS INVERSE. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleicsetprecdiag( - minbleicstate state, - real_1d_array d, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Modification of the preconditioner: scale-based diagonal preconditioning. - -This preconditioning mode can be useful when you don't have approximate -diagonal of Hessian, but you know that your variables are badly scaled -(for example, one variable is in [1,10], and another in [1000,100000]), -and most part of the ill-conditioning comes from different scales of vars. - -In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2), -can greatly improve convergence. - -IMPRTANT: you should set scale of your variables with MinBLEICSetScale() -call (before or after MinBLEICSetPrecScale() call). Without knowledge of -the scale of your variables scale-based preconditioner will be just unit -matrix. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleicsetprecscale( - minbleicstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets scaling coefficients for BLEIC optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of the optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -In most optimizers (and in the BLEIC too) scaling is NOT a form of -preconditioning. It just affects stopping conditions. You should set -preconditioner by separate call to one of the MinBLEICSetPrec...() -functions. - -There is a special preconditioning mode, however, which uses scaling -coefficients to form diagonal preconditioning matrix. You can turn this -mode on, if you want. But you should understand that scaling is not the -same thing as preconditioning - these are two different, although related -forms of tuning solver. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleicsetscale( - minbleicstate state, - real_1d_array s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets maximum step length - -IMPORTANT: this feature is hard to combine with preconditioning. You can't -set upper limit on step length, when you solve optimization problem with -linear (non-boundary) constraints AND preconditioner turned on. - -When non-boundary constraints are present, you have to either a) use -preconditioner, or b) use upper limit on step length. YOU CAN'T USE BOTH! -In this case algorithm will terminate with appropriate error code. - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which lead to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleicsetstpmax( - minbleicstate state, - double stpmax, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinBLEICOptimize(). - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleicsetxrep( - minbleicstate state, - bool needxrep, - const xparams _params = alglib::xdefault); - -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void function1_grad(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr) 
-{
-    //
-    // this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4
-    // and its derivatives df/d0 and df/dx1
-    //
-    func = 100*pow(x[0]+3,4) + pow(x[1]-3,4);
-    grad[0] = 400*pow(x[0]+3,3);
-    grad[1] = 4*pow(x[1]-3,3);
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of
-    //
-    //     f(x,y) = 100*(x+3)^4+(y-3)^4
-    //
-    // subject to box constraints
-    //
-    //     -1<=x<=+1, -1<=y<=+1
-    //
-    // using BLEIC optimizer with:
-    // * initial point x=[0,0]
-    // * unit scale being set for all variables (see minbleicsetscale for more info)
-    // * stopping criteria set to "terminate after short enough step"
-    // * OptGuard integrity check being used to check problem statement
-    //   for some common errors like nonsmoothness or bad analytic gradient
-    //
-    // First, we create optimizer object and tune its properties:
-    // * set box constraints
-    // * set variable scales
-    // * set stopping criteria
-    //
-    real_1d_array x = "[0,0]";
-    real_1d_array s = "[1,1]";
-    real_1d_array bndl = "[-1,-1]";
-    real_1d_array bndu = "[+1,+1]";
-    double epsg = 0;
-    double epsf = 0;
-    double epsx = 0.000001;
-    ae_int_t maxits = 0;
-    minbleicstate state;
-    minbleiccreate(x, state);
-    minbleicsetbc(state, bndl, bndu);
-    minbleicsetscale(state, s);
-    minbleicsetcond(state, epsg, epsf, epsx, maxits);
-
-    //
-    // Then we activate OptGuard integrity checking.
-    //
-    // OptGuard monitor helps to catch common coding and problem statement
-    // issues, like:
-    // * discontinuity of the target function (C0 continuity violation)
-    // * nonsmoothness of the target function (C1 continuity violation)
-    // * erroneous analytic gradient, i.e. one inconsistent with actual
-    //   change in the target/constraints
-    //
-    // OptGuard is essential for early prototyping stages because such
-    // problems often result in premature termination of the optimizer
-    // which is really hard to distinguish from the correct termination.
-    //
-    // IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL
-    //            DIFFERENTIATION. DO NOT USE IT IN PRODUCTION CODE!!!!!!!
-    //
-    //            Other OptGuard checks add moderate overhead, but anyway
-    //            it is better to turn them off when they are not needed.
-    //
-    minbleicoptguardsmoothness(state);
-    minbleicoptguardgradient(state, 0.001);
-
-    //
-    // Optimize and evaluate results
-    //
-    minbleicreport rep;
-    alglib::minbleicoptimize(state, function1_grad);
-    minbleicresults(state, x, rep);
-    printf("%d\n", int(rep.terminationtype)); // EXPECTED: 4
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [-1,1]
-
-    //
-    // Check that OptGuard did not report errors
-    //
-    // NOTE: want to test OptGuard? Try breaking the gradient - say, add
-    //       1.0 to some of its components.
-    //
-    optguardreport ogrep;
-    minbleicoptguardresults(state, ogrep);
-    printf("%s\n", ogrep.badgradsuspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc0suspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc1suspected ? "true" : "false"); // EXPECTED: false
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void function1_grad(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr) 
-{
-    //
-    // this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4
-    // and its derivatives df/d0 and df/dx1
-    //
-    func = 100*pow(x[0]+3,4) + pow(x[1]-3,4);
-    grad[0] = 400*pow(x[0]+3,3);
-    grad[1] = 4*pow(x[1]-3,3);
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of
-    //
-    //     f(x,y) = 100*(x+3)^4+(y-3)^4
-    //
-    // subject to inequality constraints
-    //
-    // * x>=2 (posed as general linear constraint),
-    // * x+y>=6
-    //
-    // using BLEIC optimizer with
-    // * initial point x=[0,0]
-    // * unit scale being set for all variables (see minbleicsetscale for more info)
-    // * stopping criteria set to "terminate after short enough step"
-    // * OptGuard integrity check being used to check problem statement
-    //   for some common errors like nonsmoothness or bad analytic gradient
-    //
-    // First, we create optimizer object and tune its properties:
-    // * set linear constraints
-    // * set variable scales
-    // * set stopping criteria
-    //
-    real_1d_array x = "[5,5]";
-    real_1d_array s = "[1,1]";
-    real_2d_array c = "[[1,0,2],[1,1,6]]";
-    integer_1d_array ct = "[1,1]";
-    minbleicstate state;
-    double epsg = 0;
-    double epsf = 0;
-    double epsx = 0.000001;
-    ae_int_t maxits = 0;
-
-    minbleiccreate(x, state);
-    minbleicsetlc(state, c, ct);
-    minbleicsetscale(state, s);
-    minbleicsetcond(state, epsg, epsf, epsx, maxits);
-
-    //
-    // Then we activate OptGuard integrity checking.
-    //
-    // OptGuard monitor helps to catch common coding and problem statement
-    // issues, like:
-    // * discontinuity of the target function (C0 continuity violation)
-    // * nonsmoothness of the target function (C1 continuity violation)
-    // * erroneous analytic gradient, i.e. one inconsistent with actual
-    //   change in the target/constraints
-    //
-    // OptGuard is essential for early prototyping stages because such
-    // problems often result in premature termination of the optimizer
-    // which is really hard to distinguish from the correct termination.
-    //
-    // IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL
-    //            DIFFERENTIATION. DO NOT USE IT IN PRODUCTION CODE!!!!!!!
-    //
-    //            Other OptGuard checks add moderate overhead, but anyway
-    //            it is better to turn them off when they are not needed.
-    //
-    minbleicoptguardsmoothness(state);
-    minbleicoptguardgradient(state, 0.001);
-
-    //
-    // Optimize and evaluate results
-    //
-    minbleicreport rep;
-    alglib::minbleicoptimize(state, function1_grad);
-    minbleicresults(state, x, rep);
-    printf("%d\n", int(rep.terminationtype)); // EXPECTED: 4
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [2,4]
-
-    //
-    // Check that OptGuard did not report errors
-    //
-    // NOTE: want to test OptGuard? Try breaking the gradient - say, add
-    //       1.0 to some of its components.
-    //
-    optguardreport ogrep;
-    minbleicoptguardresults(state, ogrep);
-    printf("%s\n", ogrep.badgradsuspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc0suspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc1suspected ? "true" : "false"); // EXPECTED: false
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void function1_func(const real_1d_array &x, double &func, void *ptr)
-{
-    //
-    // this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4
-    //
-    func = 100*pow(x[0]+3,4) + pow(x[1]-3,4);
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of
-    //
-    //     f(x,y) = 100*(x+3)^4+(y-3)^4
-    //
-    // subject to box constraints
-    //
-    //     -1<=x<=+1, -1<=y<=+1
-    //
-    // using BLEIC optimizer with:
-    // * numerical differentiation being used
-    // * initial point x=[0,0]
-    // * unit scale being set for all variables (see minbleicsetscale for more info)
-    // * stopping criteria set to "terminate after short enough step"
-    // * OptGuard integrity check being used to check problem statement
-    //   for some common errors like nonsmoothness or bad analytic gradient
-    //
-    // First, we create optimizer object and tune its properties:
-    // * set box constraints
-    // * set variable scales
-    // * set stopping criteria
-    //
-    real_1d_array x = "[0,0]";
-    real_1d_array s = "[1,1]";
-    real_1d_array bndl = "[-1,-1]";
-    real_1d_array bndu = "[+1,+1]";
-    minbleicstate state;
-    double epsg = 0;
-    double epsf = 0;
-    double epsx = 0.000001;
-    ae_int_t maxits = 0;
-    double diffstep = 1.0e-6;
-
-    minbleiccreatef(x, diffstep, state);
-    minbleicsetbc(state, bndl, bndu);
-    minbleicsetscale(state, s);
-    minbleicsetcond(state, epsg, epsf, epsx, maxits);
-
-    //
-    // Then we activate OptGuard integrity checking.
-    //
-    // Numerical differentiation always produces "correct" gradient
-    // (with some truncation error, but unbiased). Thus, we just have
-    // to check smoothness properties of the target: C0 and C1 continuity.
-    //
-    // Sometimes user accidentally tries to solve nonsmooth problems
-    // with smooth optimizer. OptGuard helps to detect such situations
-    // early, at the prototyping stage.
-    //
-    minbleicoptguardsmoothness(state);
-
-    //
-    // Optimize and evaluate results
-    //
-    minbleicreport rep;
-    alglib::minbleicoptimize(state, function1_func);
-    minbleicresults(state, x, rep);
-    printf("%d\n", int(rep.terminationtype)); // EXPECTED: 4
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [-1,1]
-
-    //
-    // Check that OptGuard did not report errors
-    //
-    // Want to challenge OptGuard? Try to make your problem
-    // nonsmooth by replacing 100*(x+3)^4 by 100*|x+3| and
-    // re-run optimizer.
-    //
-    optguardreport ogrep;
-    minbleicoptguardresults(state, ogrep);
-    printf("%s\n", ogrep.nonc0suspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc1suspected ? "true" : "false"); // EXPECTED: false
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* -This structure stores optimization report: -* IterationsCount total number of inner iterations -* NFEV number of gradient evaluations -* TerminationType termination type (see below) - -TERMINATION CODES - -TerminationType field contains completion code, which can be: - -8 internal integrity control detected infinite or NAN values in - function/gradient. Abnormal termination signalled. - 1 relative function improvement is no more than EpsF. - 2 relative step is no more than EpsX. - 4 gradient norm is no more than EpsG - 5 MaxIts steps was taken - 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - 8 terminated by user who called mincgrequesttermination(). X contains - point which was "current accepted" when termination request was - submitted. - -Other fields of this structure are not documented and should not be used! -*************************************************************************/ -
class mincgreport -{ - ae_int_t iterationscount; - ae_int_t nfev; - ae_int_t terminationtype; -}; - -
- -
-
/************************************************************************* -This object stores state of the nonlinear CG optimizer. - -You should use ALGLIB functions to work with this object. -*************************************************************************/ -
class mincgstate -{ -}; - -
- -
-
/************************************************************************* - NONLINEAR CONJUGATE GRADIENT METHOD - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments by using one of the -nonlinear conjugate gradient methods. - -These CG methods are globally convergent (even on non-convex functions) as -long as grad(f) is Lipschitz continuous in a some neighborhood of the -L = { x : f(x)<=f(x0) }. - - -REQUIREMENTS: -Algorithm will request following information during its operation: -* function value F and its gradient G (simultaneously) at given point X - - -USAGE: -1. User initializes algorithm state with MinCGCreate() call -2. User tunes solver parameters with MinCGSetCond(), MinCGSetStpMax() and - other functions -3. User calls MinCGOptimize() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. -4. User calls MinCGResults() to get solution -5. Optionally, user may call MinCGRestartFrom() to solve another problem - with same N but another starting point and/or another function. - MinCGRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[0..N-1]. - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 25.03.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mincgcreate( - real_1d_array x, - mincgstate& state, - const xparams _params = alglib::xdefault); -void alglib::mincgcreate( - ae_int_t n, - real_1d_array x, - mincgstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -The subroutine is finite difference variant of MinCGCreate(). It uses -finite differences in order to differentiate target function. - -Description below contains information which is specific to this function -only. We recommend to read comments on MinCGCreate() in order to get more -information about creation of CG optimizer. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[0..N-1]. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinCGSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large truncation errors, while too small - step will result in too large numerical errors. 1.0E-6 can be good - value to start with. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. L-BFGS needs exact gradient values. - Imprecise gradient may slow down convergence, especially on highly - nonlinear problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mincgcreatef( - real_1d_array x, - double diffstep, - mincgstate& state, - const xparams _params = alglib::xdefault); -void alglib::mincgcreatef( - ae_int_t n, - real_1d_array x, - double diffstep, - mincgstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic gradient. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function at the initial point -(note: future versions may also perform check at the final point) and -compares numerical gradient with analytic one provided by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both gradients and specific components highlighted as -suspicious by the OptGuard. - -The primary OptGuard report can be retrieved with mincgoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with mincgsetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mincgoptguardgradient( - mincgstate state, - double teststep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #0 - -Nonsmoothness (non-C1) test #0 studies function values (not gradient!) -obtained during line searches and monitors behavior of the directional -derivative estimate. - -This test is less powerful than test #1, but it does not depend on the -gradient values and thus it is more robust against artifacts introduced by -numerical differentiation. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #0 "strong" report - lngrep - C1 test #0 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mincgoptguardnonc1test0results( - mincgstate state, - optguardnonc1test0report& strrep, - optguardnonc1test0report& lngrep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #1 - -Nonsmoothness (non-C1) test #1 studies individual components of the -gradient computed during line search. - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #1 "strong" report - lngrep - C1 test #1 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mincgoptguardnonc1test1results( - mincgstate state, - optguardnonc1test1report& strrep, - optguardnonc1test1report& lngrep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -=== PRIMARY REPORT ======================================================= - -OptGuard performs several checks which are intended to catch common errors -in the implementation of nonlinear function/gradient: -* incorrect analytic gradient -* discontinuous (non-C0) target functions (constraints) -* nonsmooth (non-C1) target functions (constraints) - -Each of these checks is activated with appropriate function: -* mincgoptguardgradient() for gradient verification -* mincgoptguardsmoothness() for C0/C1 checks - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradvidx for specific variable (gradient element) suspected - * rep.badgradxbase, a point where gradient is tested - * rep.badgraduser, user-provided gradient (stored as 2D matrix with - single row in order to make report structure compatible with more - complex optimizers like MinNLC or MinLM) - * rep.badgradnum, reference gradient obtained via numerical - differentiation (stored as 2D matrix with single row in order to make - report structure compatible with more complex optimizers like MinNLC - or MinLM) -* rep.nonc0suspected -* rep.nonc1suspected - -=== ADDITIONAL REPORTS/LOGS ============================================== - -Several different tests are performed to catch C0/C1 errors, you can find -out specific test signaled error by looking to: -* rep.nonc0test0positive, for non-C0 test #0 -* rep.nonc1test0positive, for non-C1 test #0 -* rep.nonc1test1positive, for non-C1 test #1 - -Additional information (including line search logs) can be obtained by -means of: -* mincgoptguardnonc1test0results() -* mincgoptguardnonc1test1results() -which return detailed error reports, specific points where discontinuities -were found, and so on. - -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - generic OptGuard report; more detailed reports can be - retrieved with other functions. - -NOTE: false negatives (nonsmooth problems are not identified as nonsmooth - ones) are possible although unlikely. - - The reason is that you need to make several evaluations around - nonsmoothness in order to accumulate enough information about - function curvature. Say, if you start right from the nonsmooth point, - optimizer simply won't get enough data to understand what is going - wrong before it terminates due to abrupt changes in the derivative. - It is also possible that "unlucky" step will move us to the - termination too quickly. - - Our current approach is to have less than 0.1% false negatives in - our test examples (measured with multiple restarts from random - points), and to have exactly 0% false positives. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mincgoptguardresults( - mincgstate state, - optguardreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) -b) nonsmooth target function (non-C1) - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mincgoptguardsmoothness( - mincgstate state, - const xparams _params = alglib::xdefault); -void alglib::mincgoptguardsmoothness( - mincgstate state, - ae_int_t level, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This family of functions is used to launcn iterations of nonlinear optimizer - -These functions accept following parameters: - state - algorithm state - func - callback which calculates function (or merit function) - value func at given point x - grad - callback which calculates function (or merit function) - value func and gradient grad at given point x - rep - optional callback which is called after each iteration - can be NULL - ptr - optional pointer which is passed to func/grad/hess/jac/rep - can be NULL - -NOTES: - -1. This function has two different implementations: one which uses exact - (analytical) user-supplied gradient, and one which uses function value - only and numerically differentiates function in order to obtain - gradient. - - Depending on the specific function used to create optimizer object - (either MinCGCreate() for analytical gradient or MinCGCreateF() for - numerical differentiation) you should choose appropriate variant of - MinCGOptimize() - one which accepts function AND gradient or one which - accepts function ONLY. - - Be careful to choose variant of MinCGOptimize() which corresponds to - your optimization scheme! Table below lists different combinations of - callback (function/gradient) passed to MinCGOptimize() and specific - function used to create optimizer. - - - | USER PASSED TO MinCGOptimize() - CREATED WITH | function only | function and gradient - ------------------------------------------------------------ - MinCGCreateF() | work FAIL - MinCGCreate() | FAIL work - - Here "FAIL" denotes inappropriate combinations of optimizer creation - function and MinCGOptimize() version. Attemps to use such combination - (for example, to create optimizer with MinCGCreateF() and to pass - gradient information to MinCGOptimize()) will lead to exception being - thrown. Either you did not pass gradient when it WAS needed or you - passed gradient when it was NOT needed. - - -- ALGLIB -- - Copyright 20.04.2009 by Bochkanov Sergey -*************************************************************************/ -
void mincgoptimize(mincgstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void mincgoptimize(mincgstate &state, - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mincgrequesttermination( - mincgstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine restarts CG algorithm from new point. All optimization -parameters are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure used to store algorithm state. - X - new starting point. - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mincgrestartfrom( - mincgstate state, - real_1d_array x, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Conjugate gradient results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report: - * Rep.TerminationType completetion code: - * -8 internal integrity control detected infinite - or NAN values in function/gradient. Abnormal - termination signalled. - * -7 gradient verification failed. - See MinCGSetGradientCheck() for more information. - * 1 relative function improvement is no more than - EpsF. - * 2 relative step is no more than EpsX. - * 4 gradient norm is no more than EpsG - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible, - we return best X found so far - * 8 terminated by user - * Rep.IterationsCount contains iterations count - * NFEV countains number of function calculations - - -- ALGLIB -- - Copyright 20.04.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mincgresults( - mincgstate state, - real_1d_array& x, - mincgreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -Conjugate gradient results - -Buffered implementation of MinCGResults(), which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 20.04.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mincgresultsbuf( - mincgstate state, - real_1d_array& x, - mincgreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets CG algorithm. - -INPUT PARAMETERS: - State - structure which stores algorithm state - CGType - algorithm type: - * -1 automatic selection of the best algorithm - * 0 DY (Dai and Yuan) algorithm - * 1 Hybrid DY-HS algorithm - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mincgsetcgtype( - mincgstate state, - ae_int_t cgtype, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets stopping conditions for CG optimization algorithm. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|<EpsG is satisfied, where: - * |.| means Euclidian norm - * v - scaled gradient vector, v[i]=g[i]*s[i] - * g - gradient - * s - scaling coefficients set by MinCGSetScale() - EpsF - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - is satisfied. - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - ste pvector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinCGSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to -automatic stopping criterion selection (small EpsX). - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mincgsetcond( - mincgstate state, - double epsg, - double epsf, - double epsx, - ae_int_t maxits, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -Modification of the preconditioner: preconditioning is turned off. - -INPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mincgsetprecdefault( - mincgstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Modification of the preconditioner: diagonal of approximate Hessian is -used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - D - diagonal of the approximate Hessian, array[0..N-1], - (if larger, only leading N elements are used). - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - -NOTE 2: D[i] should be positive. Exception will be thrown otherwise. - -NOTE 3: you should pass diagonal of approximate Hessian - NOT ITS INVERSE. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mincgsetprecdiag( - mincgstate state, - real_1d_array d, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Modification of the preconditioner: scale-based diagonal preconditioning. - -This preconditioning mode can be useful when you don't have approximate -diagonal of Hessian, but you know that your variables are badly scaled -(for example, one variable is in [1,10], and another in [1000,100000]), -and most part of the ill-conditioning comes from different scales of vars. - -In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2), -can greatly improve convergence. - -IMPRTANT: you should set scale of your variables with MinCGSetScale() call -(before or after MinCGSetPrecScale() call). Without knowledge of the scale -of your variables scale-based preconditioner will be just unit matrix. - -INPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mincgsetprecscale( - mincgstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets scaling coefficients for CG optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of CG optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -In most optimizers (and in the CG too) scaling is NOT a form of -preconditioning. It just affects stopping conditions. You should set -preconditioner by separate call to one of the MinCGSetPrec...() functions. - -There is special preconditioning mode, however, which uses scaling -coefficients to form diagonal preconditioning matrix. You can turn this -mode on, if you want. But you should understand that scaling is not the -same thing as preconditioning - these are two different, although related -forms of tuning solver. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mincgsetscale( - mincgstate state, - real_1d_array s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which leads to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mincgsetstpmax( - mincgstate state, - double stpmax, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinCGOptimize(). - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mincgsetxrep( - mincgstate state, - bool needxrep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function allows to suggest initial step length to the CG algorithm. - -Suggested step length is used as starting point for the line search. It -can be useful when you have badly scaled problem, i.e. when ||grad|| -(which is used as initial estimate for the first step) is many orders of -magnitude different from the desired step. - -Line search may fail on such problems without good estimate of initial -step length. Imagine, for example, problem with ||grad||=10^50 and desired -step equal to 0.1 Line search function will use 10^50 as initial step, -then it will decrease step length by 2 (up to 20 attempts) and will get -10^44, which is still too large. - -This function allows us to tell than line search should be started from -some moderate step length, like 1.0, so algorithm will be able to detect -desired step length in a several searches. - -Default behavior (when no step is suggested) is to use preconditioner, if -it is available, to generate initial estimate of step length. - -This function influences only first iteration of algorithm. It should be -called between MinCGCreate/MinCGRestartFrom() call and MinCGOptimize call. -Suggested step is ignored if you have preconditioner. - -INPUT PARAMETERS: - State - structure used to store algorithm state. - Stp - initial estimate of the step length. - Can be zero (no estimate). - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mincgsuggeststep( - mincgstate state, - double stp, - const xparams _params = alglib::xdefault); - -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void function1_grad(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr) 
-{
-    //
-    // this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4
-    // and its derivatives df/d0 and df/dx1
-    //
-    func = 100*pow(x[0]+3,4) + pow(x[1]-3,4);
-    grad[0] = 400*pow(x[0]+3,3);
-    grad[1] = 4*pow(x[1]-3,3);
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of
-    //
-    //     f(x,y) = 100*(x+3)^4+(y-3)^4
-    //
-    // using nonlinear conjugate gradient method with:
-    // * initial point x=[0,0]
-    // * unit scale being set for all variables (see mincgsetscale for more info)
-    // * stopping criteria set to "terminate after short enough step"
-    // * OptGuard integrity check being used to check problem statement
-    //   for some common errors like nonsmoothness or bad analytic gradient
-    //
-    // First, we create optimizer object and tune its properties
-    //
-    real_1d_array x = "[0,0]";
-    real_1d_array s = "[1,1]";
-    double epsg = 0;
-    double epsf = 0;
-    double epsx = 0.0000000001;
-    ae_int_t maxits = 0;
-    mincgstate state;
-    mincgcreate(x, state);
-    mincgsetcond(state, epsg, epsf, epsx, maxits);
-    mincgsetscale(state, s);
-
-    //
-    // Activate OptGuard integrity checking.
-    //
-    // OptGuard monitor helps to catch common coding and problem statement
-    // issues, like:
-    // * discontinuity of the target function (C0 continuity violation)
-    // * nonsmoothness of the target function (C1 continuity violation)
-    // * erroneous analytic gradient, i.e. one inconsistent with actual
-    //   change in the target/constraints
-    //
-    // OptGuard is essential for early prototyping stages because such
-    // problems often result in premature termination of the optimizer
-    // which is really hard to distinguish from the correct termination.
-    //
-    // IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL
-    //            DIFFERENTIATION. DO NOT USE IT IN PRODUCTION CODE!!!!!!!
-    //
-    //            Other OptGuard checks add moderate overhead, but anyway
-    //            it is better to turn them off when they are not needed.
-    //
-    mincgoptguardsmoothness(state);
-    mincgoptguardgradient(state, 0.001);
-
-    //
-    // Optimize and evaluate results
-    //
-    mincgreport rep;
-    alglib::mincgoptimize(state, function1_grad);
-    mincgresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [-3,3]
-
-    //
-    // Check that OptGuard did not report errors
-    //
-    // NOTE: want to test OptGuard? Try breaking the gradient - say, add
-    //       1.0 to some of its components.
-    //
-    optguardreport ogrep;
-    mincgoptguardresults(state, ogrep);
-    printf("%s\n", ogrep.badgradsuspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc0suspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc1suspected ? "true" : "false"); // EXPECTED: false
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void function1_grad(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr) 
-{
-    //
-    // this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4
-    // and its derivatives df/d0 and df/dx1
-    //
-    func = 100*pow(x[0]+3,4) + pow(x[1]-3,4);
-    grad[0] = 400*pow(x[0]+3,3);
-    grad[1] = 4*pow(x[1]-3,3);
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of f(x,y) = 100*(x+3)^4+(y-3)^4
-    // with nonlinear conjugate gradient method.
-    //
-    // Several advanced techniques are demonstrated:
-    // * upper limit on step size
-    // * restart from new point
-    //
-    real_1d_array x = "[0,0]";
-    real_1d_array s = "[1,1]";
-    double epsg = 0;
-    double epsf = 0;
-    double epsx = 0.0000000001;
-    double stpmax = 0.1;
-    ae_int_t maxits = 0;
-    mincgstate state;
-    mincgreport rep;
-
-    // create and tune optimizer
-    mincgcreate(x, state);
-    mincgsetscale(state, s);
-    mincgsetcond(state, epsg, epsf, epsx, maxits);
-    mincgsetstpmax(state, stpmax);
-
-    // Set up OptGuard integrity checker which catches errors
-    // like nonsmooth targets or errors in the analytic gradient.
-    //
-    // OptGuard is essential at the early prototyping stages.
-    //
-    // NOTE: gradient verification needs 3*N additional function
-    //       evaluations; DO NOT USE IT IN THE PRODUCTION CODE
-    //       because it leads to unnecessary slowdown of your app.
-    mincgoptguardsmoothness(state);
-    mincgoptguardgradient(state, 0.001);
-
-    // first run
-    alglib::mincgoptimize(state, function1_grad);
-    mincgresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [-3,3]
-
-    // second run - algorithm is restarted with mincgrestartfrom()
-    x = "[10,10]";
-    mincgrestartfrom(state, x);
-    alglib::mincgoptimize(state, function1_grad);
-    mincgresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [-3,3]
-
-    // check OptGuard integrity report. Why do we need it at all?
-    // Well, try breaking the gradient by adding 1.0 to some
-    // of its components - OptGuard should report it as error.
-    // And it may also catch unintended errors too :)
-    optguardreport ogrep;
-    mincgoptguardresults(state, ogrep);
-    printf("%s\n", ogrep.badgradsuspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc0suspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc1suspected ? "true" : "false"); // EXPECTED: false
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void function1_func(const real_1d_array &x, double &func, void *ptr)
-{
-    //
-    // this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4
-    //
-    func = 100*pow(x[0]+3,4) + pow(x[1]-3,4);
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of
-    //
-    //     f(x,y) = 100*(x+3)^4+(y-3)^4
-    //
-    // using numerical differentiation to calculate gradient.
-    //
-    // We also show how to use OptGuard integrity checker to catch common
-    // problem statement errors like accidentally specifying nonsmooth target
-    // function.
-    //
-    // First, we set up optimizer...
-    //
-    real_1d_array x = "[0,0]";
-    real_1d_array s = "[1,1]";
-    double epsg = 0;
-    double epsf = 0;
-    double epsx = 0.0000000001;
-    double diffstep = 1.0e-6;
-    ae_int_t maxits = 0;
-    mincgstate state;
-    mincgcreatef(x, diffstep, state);
-    mincgsetcond(state, epsg, epsf, epsx, maxits);
-    mincgsetscale(state, s);
-
-    //
-    // Then, we activate OptGuard integrity checking.
-    //
-    // Numerical differentiation always produces "correct" gradient
-    // (with some truncation error, but unbiased). Thus, we just have
-    // to check smoothness properties of the target: C0 and C1 continuity.
-    //
-    // Sometimes user accidentally tried to solve nonsmooth problems
-    // with smooth optimizer. OptGuard helps to detect such situations
-    // early, at the prototyping stage.
-    //
-    mincgoptguardsmoothness(state);
-
-    //
-    // Now we are ready to run the optimization
-    //
-    mincgreport rep;
-    alglib::mincgoptimize(state, function1_func);
-    mincgresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [-3,3]
-
-    //
-    // ...and to check OptGuard integrity report.
-    //
-    // Want to challenge OptGuard? Try to make your problem
-    // nonsmooth by replacing 100*(x+3)^4 by 100*|x+3| and
-    // re-run optimizer.
-    //
-    optguardreport ogrep;
-    mincgoptguardresults(state, ogrep);
-    printf("%s\n", ogrep.nonc0suspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc1suspected ? "true" : "false"); // EXPECTED: false
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* - -*************************************************************************/ -
class minasareport -{ - ae_int_t iterationscount; - ae_int_t nfev; - ae_int_t terminationtype; - ae_int_t activeconstraints; -}; - -
- -
-
/************************************************************************* - -*************************************************************************/ -
class minasastate -{ -}; - -
- -
-
/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 25.03.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minasacreate( - real_1d_array x, - real_1d_array bndl, - real_1d_array bndu, - minasastate& state, - const xparams _params = alglib::xdefault); -void alglib::minasacreate( - ae_int_t n, - real_1d_array x, - real_1d_array bndl, - real_1d_array bndu, - minasastate& state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This family of functions is used to launcn iterations of nonlinear optimizer - -These functions accept following parameters: - state - algorithm state - grad - callback which calculates function (or merit function) - value func and gradient grad at given point x - rep - optional callback which is called after each iteration - can be NULL - ptr - optional pointer which is passed to func/grad/hess/jac/rep - can be NULL - - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -
void minasaoptimize(minasastate &state, - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -
- -
-
/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minasarestartfrom( - minasastate state, - real_1d_array x, - real_1d_array bndl, - real_1d_array bndu, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minasaresults( - minasastate state, - real_1d_array& x, - minasareport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minasaresultsbuf( - minasastate state, - real_1d_array& x, - minasareport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minasasetalgorithm( - minasastate state, - ae_int_t algotype, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minasasetcond( - minasastate state, - double epsg, - double epsf, - double epsx, - ae_int_t maxits, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minasasetstpmax( - minasastate state, - double stpmax, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minasasetxrep( - minasastate state, - bool needxrep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is obsolete function which was used by previous version of the BLEIC -optimizer. It does nothing in the current version of BLEIC. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleicsetbarrierdecay( - minbleicstate state, - double mudecay, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is obsolete function which was used by previous version of the BLEIC -optimizer. It does nothing in the current version of BLEIC. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minbleicsetbarrierwidth( - minbleicstate state, - double mu, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Obsolete function, use MinLBFGSSetCholeskyPreconditioner() instead. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgssetcholeskypreconditioner( - minlbfgsstate state, - real_2d_array p, - bool isupper, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Obsolete function, use MinLBFGSSetPrecDefault() instead. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgssetdefaultpreconditioner( - minlbfgsstate state, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -This structure stores optimization report: -* IterationsCount total number of inner iterations -* NFEV number of gradient evaluations -* TerminationType termination type (see below) - -TERMINATION CODES - -TerminationType field contains completion code, which can be: - -8 internal integrity control detected infinite or NAN values in - function/gradient. Abnormal termination signalled. - 1 relative function improvement is no more than EpsF. - 2 relative step is no more than EpsX. - 4 gradient norm is no more than EpsG - 5 MaxIts steps was taken - 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - 8 terminated by user who called minlbfgsrequesttermination(). - X contains point which was "current accepted" when termination - request was submitted. - -Other fields of this structure are not documented and should not be used! -*************************************************************************/ -
class minlbfgsreport -{ - ae_int_t iterationscount; - ae_int_t nfev; - ae_int_t terminationtype; -}; - -
- -
-
/************************************************************************* - -*************************************************************************/ -
class minlbfgsstate -{ -}; - -
- -
-
/************************************************************************* - LIMITED MEMORY BFGS METHOD FOR LARGE SCALE OPTIMIZATION - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments by using a quasi- -Newton method (LBFGS scheme) which is optimized to use a minimum amount -of memory. -The subroutine generates the approximation of an inverse Hessian matrix by -using information about the last M steps of the algorithm (instead of N). -It lessens a required amount of memory from a value of order N^2 to a -value of order 2*N*M. - - -REQUIREMENTS: -Algorithm will request following information during its operation: -* function value F and its gradient G (simultaneously) at given point X - - -USAGE: -1. User initializes algorithm state with MinLBFGSCreate() call -2. User tunes solver parameters with MinLBFGSSetCond() MinLBFGSSetStpMax() - and other functions -3. User calls MinLBFGSOptimize() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. -4. User calls MinLBFGSResults() to get solution -5. Optionally user may call MinLBFGSRestartFrom() to solve another problem - with same N/M but another starting point and/or another function. - MinLBFGSRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension. N>0 - M - number of corrections in the BFGS scheme of Hessian - approximation update. Recommended value: 3<=M<=7. The smaller - value causes worse convergence, the bigger will not cause a - considerably better convergence, but will cause a fall in the - performance. M<=N. - X - initial solution approximation, array[0..N-1]. - - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -NOTES: -1. you may tune stopping conditions with MinLBFGSSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use MinLBFGSSetStpMax() function to bound algorithm's steps. However, - L-BFGS rarely needs such a tuning. - - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgscreate( - ae_int_t m, - real_1d_array x, - minlbfgsstate& state, - const xparams _params = alglib::xdefault); -void alglib::minlbfgscreate( - ae_int_t n, - ae_int_t m, - real_1d_array x, - minlbfgsstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -The subroutine is finite difference variant of MinLBFGSCreate(). It uses -finite differences in order to differentiate target function. - -Description below contains information which is specific to this function -only. We recommend to read comments on MinLBFGSCreate() in order to get -more information about creation of LBFGS optimizer. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - M - number of corrections in the BFGS scheme of Hessian - approximation update. Recommended value: 3<=M<=7. The smaller - value causes worse convergence, the bigger will not cause a - considerably better convergence, but will cause a fall in the - performance. M<=N. - X - starting point, array[0..N-1]. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinLBFGSSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large truncation errors, while too small - step will result in too large numerical errors. 1.0E-6 can be good - value to start with. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. LBFGS needs exact gradient values. - Imprecise gradient may slow down convergence, especially on highly - nonlinear problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgscreatef( - ae_int_t m, - real_1d_array x, - double diffstep, - minlbfgsstate& state, - const xparams _params = alglib::xdefault); -void alglib::minlbfgscreatef( - ae_int_t n, - ae_int_t m, - real_1d_array x, - double diffstep, - minlbfgsstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic gradient. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function at the initial point -(note: future versions may also perform check at the final point) and -compares numerical gradient with analytic one provided by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both gradients and specific components highlighted as -suspicious by the OptGuard. - -The primary OptGuard report can be retrieved with minlbfgsoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with minlbfgssetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgsoptguardgradient( - minlbfgsstate state, - double teststep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #0 - -Nonsmoothness (non-C1) test #0 studies function values (not gradient!) -obtained during line searches and monitors behavior of the directional -derivative estimate. - -This test is less powerful than test #1, but it does not depend on the -gradient values and thus it is more robust against artifacts introduced by -numerical differentiation. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #0 "strong" report - lngrep - C1 test #0 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgsoptguardnonc1test0results( - minlbfgsstate state, - optguardnonc1test0report& strrep, - optguardnonc1test0report& lngrep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #1 - -Nonsmoothness (non-C1) test #1 studies individual components of the -gradient computed during line search. - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #1 "strong" report - lngrep - C1 test #1 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgsoptguardnonc1test1results( - minlbfgsstate state, - optguardnonc1test1report& strrep, - optguardnonc1test1report& lngrep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -=== PRIMARY REPORT ======================================================= - -OptGuard performs several checks which are intended to catch common errors -in the implementation of nonlinear function/gradient: -* incorrect analytic gradient -* discontinuous (non-C0) target functions (constraints) -* nonsmooth (non-C1) target functions (constraints) - -Each of these checks is activated with appropriate function: -* minlbfgsoptguardgradient() for gradient verification -* minlbfgsoptguardsmoothness() for C0/C1 checks - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradvidx for specific variable (gradient element) suspected - * rep.badgradxbase, a point where gradient is tested - * rep.badgraduser, user-provided gradient (stored as 2D matrix with - single row in order to make report structure compatible with more - complex optimizers like MinNLC or MinLM) - * rep.badgradnum, reference gradient obtained via numerical - differentiation (stored as 2D matrix with single row in order to make - report structure compatible with more complex optimizers like MinNLC - or MinLM) -* rep.nonc0suspected -* rep.nonc1suspected - -=== ADDITIONAL REPORTS/LOGS ============================================== - -Several different tests are performed to catch C0/C1 errors, you can find -out specific test signaled error by looking to: -* rep.nonc0test0positive, for non-C0 test #0 -* rep.nonc1test0positive, for non-C1 test #0 -* rep.nonc1test1positive, for non-C1 test #1 - -Additional information (including line search logs) can be obtained by -means of: -* minlbfgsoptguardnonc1test0results() -* minlbfgsoptguardnonc1test1results() -which return detailed error reports, specific points where discontinuities -were found, and so on. - -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - generic OptGuard report; more detailed reports can be - retrieved with other functions. - -NOTE: false negatives (nonsmooth problems are not identified as nonsmooth - ones) are possible although unlikely. - - The reason is that you need to make several evaluations around - nonsmoothness in order to accumulate enough information about - function curvature. Say, if you start right from the nonsmooth point, - optimizer simply won't get enough data to understand what is going - wrong before it terminates due to abrupt changes in the derivative. - It is also possible that "unlucky" step will move us to the - termination too quickly. - - Our current approach is to have less than 0.1% false negatives in - our test examples (measured with multiple restarts from random - points), and to have exactly 0% false positives. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgsoptguardresults( - minlbfgsstate state, - optguardreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) -b) nonsmooth target function (non-C1) - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgsoptguardsmoothness( - minlbfgsstate state, - const xparams _params = alglib::xdefault); -void alglib::minlbfgsoptguardsmoothness( - minlbfgsstate state, - ae_int_t level, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This family of functions is used to launcn iterations of nonlinear optimizer - -These functions accept following parameters: - state - algorithm state - func - callback which calculates function (or merit function) - value func at given point x - grad - callback which calculates function (or merit function) - value func and gradient grad at given point x - rep - optional callback which is called after each iteration - can be NULL - ptr - optional pointer which is passed to func/grad/hess/jac/rep - can be NULL - -NOTES: - -1. This function has two different implementations: one which uses exact - (analytical) user-supplied gradient, and one which uses function value - only and numerically differentiates function in order to obtain - gradient. - - Depending on the specific function used to create optimizer object - (either MinLBFGSCreate() for analytical gradient or MinLBFGSCreateF() - for numerical differentiation) you should choose appropriate variant of - MinLBFGSOptimize() - one which accepts function AND gradient or one - which accepts function ONLY. - - Be careful to choose variant of MinLBFGSOptimize() which corresponds to - your optimization scheme! Table below lists different combinations of - callback (function/gradient) passed to MinLBFGSOptimize() and specific - function used to create optimizer. - - - | USER PASSED TO MinLBFGSOptimize() - CREATED WITH | function only | function and gradient - ------------------------------------------------------------ - MinLBFGSCreateF() | work FAIL - MinLBFGSCreate() | FAIL work - - Here "FAIL" denotes inappropriate combinations of optimizer creation - function and MinLBFGSOptimize() version. Attemps to use such - combination (for example, to create optimizer with MinLBFGSCreateF() and - to pass gradient information to MinCGOptimize()) will lead to exception - being thrown. Either you did not pass gradient when it WAS needed or - you passed gradient when it was NOT needed. - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -
void minlbfgsoptimize(minlbfgsstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void minlbfgsoptimize(minlbfgsstate &state, - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgsrequesttermination( - minlbfgsstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine restarts LBFGS algorithm from new point. All optimization -parameters are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure used to store algorithm state - X - new starting point. - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgsrestartfrom( - minlbfgsstate state, - real_1d_array x, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -L-BFGS algorithm results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report: - * Rep.TerminationType completetion code: - * -8 internal integrity control detected infinite - or NAN values in function/gradient. Abnormal - termination signalled. - * -2 rounding errors prevent further improvement. - X contains best point found. - * -1 incorrect parameters were specified - * 1 relative function improvement is no more than - EpsF. - * 2 relative step is no more than EpsX. - * 4 gradient norm is no more than EpsG - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible - * 8 terminated by user who called minlbfgsrequesttermination(). - X contains point which was "current accepted" when - termination request was submitted. - * Rep.IterationsCount contains iterations count - * NFEV countains number of function calculations - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgsresults( - minlbfgsstate state, - real_1d_array& x, - minlbfgsreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -L-BFGS algorithm results - -Buffered implementation of MinLBFGSResults which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 20.08.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgsresultsbuf( - minlbfgsstate state, - real_1d_array& x, - minlbfgsreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets stopping conditions for L-BFGS optimization algorithm. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|<EpsG is satisfied, where: - * |.| means Euclidian norm - * v - scaled gradient vector, v[i]=g[i]*s[i] - * g - gradient - * s - scaling coefficients set by MinLBFGSSetScale() - EpsF - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - is satisfied. - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - ste pvector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinLBFGSSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to -automatic stopping criterion selection (small EpsX). - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgssetcond( - minlbfgsstate state, - double epsg, - double epsf, - double epsx, - ae_int_t maxits, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -Modification of the preconditioner: Cholesky factorization of approximate -Hessian is used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - P - triangular preconditioner, Cholesky factorization of - the approximate Hessian. array[0..N-1,0..N-1], - (if larger, only leading N elements are used). - IsUpper - whether upper or lower triangle of P is given - (other triangle is not referenced) - -After call to this function preconditioner is changed to P (P is copied -into the internal buffer). - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - -NOTE 2: P should be nonsingular. Exception will be thrown otherwise. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgssetpreccholesky( - minlbfgsstate state, - real_2d_array p, - bool isupper, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Modification of the preconditioner: default preconditioner (simple -scaling, same for all elements of X) is used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgssetprecdefault( - minlbfgsstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Modification of the preconditioner: diagonal of approximate Hessian is -used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - D - diagonal of the approximate Hessian, array[0..N-1], - (if larger, only leading N elements are used). - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - -NOTE 2: D[i] should be positive. Exception will be thrown otherwise. - -NOTE 3: you should pass diagonal of approximate Hessian - NOT ITS INVERSE. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgssetprecdiag( - minlbfgsstate state, - real_1d_array d, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Modification of the preconditioner: scale-based diagonal preconditioning. - -This preconditioning mode can be useful when you don't have approximate -diagonal of Hessian, but you know that your variables are badly scaled -(for example, one variable is in [1,10], and another in [1000,100000]), -and most part of the ill-conditioning comes from different scales of vars. - -In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2), -can greatly improve convergence. - -IMPRTANT: you should set scale of your variables with MinLBFGSSetScale() -call (before or after MinLBFGSSetPrecScale() call). Without knowledge of -the scale of your variables scale-based preconditioner will be just unit -matrix. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgssetprecscale( - minlbfgsstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets scaling coefficients for LBFGS optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of the optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -In most optimizers (and in the LBFGS too) scaling is NOT a form of -preconditioning. It just affects stopping conditions. You should set -preconditioner by separate call to one of the MinLBFGSSetPrec...() -functions. - -There is special preconditioning mode, however, which uses scaling -coefficients to form diagonal preconditioning matrix. You can turn this -mode on, if you want. But you should understand that scaling is not the -same thing as preconditioning - these are two different, although related -forms of tuning solver. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgssetscale( - minlbfgsstate state, - real_1d_array s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0 (default), if - you don't want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which leads to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgssetstpmax( - minlbfgsstate state, - double stpmax, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinLBFGSOptimize(). - - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlbfgssetxrep( - minlbfgsstate state, - bool needxrep, - const xparams _params = alglib::xdefault); - -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void function1_grad(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr) 
-{
-    //
-    // this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4
-    // and its derivatives df/d0 and df/dx1
-    //
-    func = 100*pow(x[0]+3,4) + pow(x[1]-3,4);
-    grad[0] = 400*pow(x[0]+3,3);
-    grad[1] = 4*pow(x[1]-3,3);
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of
-    //
-    //     f(x,y) = 100*(x+3)^4+(y-3)^4
-    //
-    // using LBFGS method, with:
-    // * initial point x=[0,0]
-    // * unit scale being set for all variables (see minlbfgssetscale for more info)
-    // * stopping criteria set to "terminate after short enough step"
-    // * OptGuard integrity check being used to check problem statement
-    //   for some common errors like nonsmoothness or bad analytic gradient
-    //
-    // First, we create optimizer object and tune its properties
-    //
-    real_1d_array x = "[0,0]";
-    real_1d_array s = "[1,1]";
-    double epsg = 0;
-    double epsf = 0;
-    double epsx = 0.0000000001;
-    ae_int_t maxits = 0;
-    minlbfgsstate state;
-    minlbfgscreate(1, x, state);
-    minlbfgssetcond(state, epsg, epsf, epsx, maxits);
-    minlbfgssetscale(state, s);
-
-    //
-    // Activate OptGuard integrity checking.
-    //
-    // OptGuard monitor helps to catch common coding and problem statement
-    // issues, like:
-    // * discontinuity of the target function (C0 continuity violation)
-    // * nonsmoothness of the target function (C1 continuity violation)
-    // * erroneous analytic gradient, i.e. one inconsistent with actual
-    //   change in the target/constraints
-    //
-    // OptGuard is essential for early prototyping stages because such
-    // problems often result in premature termination of the optimizer
-    // which is really hard to distinguish from the correct termination.
-    //
-    // IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL
-    //            DIFFERENTIATION. DO NOT USE IT IN PRODUCTION CODE!!!!!!!
-    //
-    //            Other OptGuard checks add moderate overhead, but anyway
-    //            it is better to turn them off when they are not needed.
-    //
-    minlbfgsoptguardsmoothness(state);
-    minlbfgsoptguardgradient(state, 0.001);
-
-    //
-    // Optimize and examine results.
-    //
-    minlbfgsreport rep;
-    alglib::minlbfgsoptimize(state, function1_grad);
-    minlbfgsresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [-3,3]
-
-    //
-    // Check that OptGuard did not report errors
-    //
-    // NOTE: want to test OptGuard? Try breaking the gradient - say, add
-    //       1.0 to some of its components.
-    //
-    optguardreport ogrep;
-    minlbfgsoptguardresults(state, ogrep);
-    printf("%s\n", ogrep.badgradsuspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc0suspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc1suspected ? "true" : "false"); // EXPECTED: false
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void function1_grad(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr) 
-{
-    //
-    // this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4
-    // and its derivatives df/d0 and df/dx1
-    //
-    func = 100*pow(x[0]+3,4) + pow(x[1]-3,4);
-    grad[0] = 400*pow(x[0]+3,3);
-    grad[1] = 4*pow(x[1]-3,3);
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of f(x,y) = 100*(x+3)^4+(y-3)^4
-    // using LBFGS method.
-    //
-    // Several advanced techniques are demonstrated:
-    // * upper limit on step size
-    // * restart from new point
-    //
-    real_1d_array x = "[0,0]";
-    real_1d_array s = "[1,1]";
-    double epsg = 0;
-    double epsf = 0;
-    double epsx = 0.0000000001;
-    double stpmax = 0.1;
-    ae_int_t maxits = 0;
-    minlbfgsstate state;
-    minlbfgsreport rep;
-
-    // create and tune optimizer
-    minlbfgscreate(1, x, state);
-    minlbfgssetcond(state, epsg, epsf, epsx, maxits);
-    minlbfgssetstpmax(state, stpmax);
-    minlbfgssetscale(state, s);
-
-    // Set up OptGuard integrity checker which catches errors
-    // like nonsmooth targets or errors in the analytic gradient.
-    //
-    // OptGuard is essential at the early prototyping stages.
-    //
-    // NOTE: gradient verification needs 3*N additional function
-    //       evaluations; DO NOT USE IT IN THE PRODUCTION CODE
-    //       because it leads to unnecessary slowdown of your app.
-    minlbfgsoptguardsmoothness(state);
-    minlbfgsoptguardgradient(state, 0.001);
-
-    // first run
-    alglib::minlbfgsoptimize(state, function1_grad);
-    minlbfgsresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [-3,3]
-
-    // second run - algorithm is restarted
-    x = "[10,10]";
-    minlbfgsrestartfrom(state, x);
-    alglib::minlbfgsoptimize(state, function1_grad);
-    minlbfgsresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [-3,3]
-
-    // check OptGuard integrity report. Why do we need it at all?
-    // Well, try breaking the gradient by adding 1.0 to some
-    // of its components - OptGuard should report it as error.
-    // And it may also catch unintended errors too :)
-    optguardreport ogrep;
-    minlbfgsoptguardresults(state, ogrep);
-    printf("%s\n", ogrep.badgradsuspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc0suspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc1suspected ? "true" : "false"); // EXPECTED: false
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void function1_func(const real_1d_array &x, double &func, void *ptr)
-{
-    //
-    // this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4
-    //
-    func = 100*pow(x[0]+3,4) + pow(x[1]-3,4);
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of f(x,y) = 100*(x+3)^4+(y-3)^4
-    // using numerical differentiation to calculate gradient.
-    //
-    real_1d_array x = "[0,0]";
-    double epsg = 0.0000000001;
-    double epsf = 0;
-    double epsx = 0;
-    double diffstep = 1.0e-6;
-    ae_int_t maxits = 0;
-    minlbfgsstate state;
-    minlbfgsreport rep;
-
-    minlbfgscreatef(1, x, diffstep, state);
-    minlbfgssetcond(state, epsg, epsf, epsx, maxits);
-    alglib::minlbfgsoptimize(state, function1_func);
-    minlbfgsresults(state, x, rep);
-
-    printf("%d\n", int(rep.terminationtype)); // EXPECTED: 4
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [-3,3]
-    return 0;
-}
-
-
-
-
- -minlmreport
-minlmstate
- -minlmcreatefgh
-minlmcreatefgj
-minlmcreatefj
-minlmcreatev
-minlmcreatevgj
-minlmcreatevj
-minlmoptguardgradient
-minlmoptguardresults
-minlmoptimize
-minlmrequesttermination
-minlmrestartfrom
-minlmresults
-minlmresultsbuf
-minlmsetacctype
-minlmsetbc
-minlmsetcond
-minlmsetlc
-minlmsetscale
-minlmsetstpmax
-minlmsetxrep
- - - - - - - -
minlm_d_fgh Nonlinear Hessian-based optimization for general functions
minlm_d_restarts Efficient restarts of LM optimizer
minlm_d_v Nonlinear least squares optimization using function vector only
minlm_d_vb Bound constrained nonlinear least squares optimization
minlm_d_vj Nonlinear least squares optimization using function vector and Jacobian
- -
-
/************************************************************************* -Optimization report, filled by MinLMResults() function - -FIELDS: -* TerminationType, completetion code: - * -8 optimizer detected NAN/INF values either in the function itself, - or in its Jacobian - * -5 inappropriate solver was used: - * solver created with minlmcreatefgh() used on problem with - general linear constraints (set with minlmsetlc() call). - * -3 constraints are inconsistent - * 2 relative step is no more than EpsX. - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible - * 8 terminated by user who called MinLMRequestTermination(). - X contains point which was "current accepted" when termination - request was submitted. -* IterationsCount, contains iterations count -* NFunc, number of function calculations -* NJac, number of Jacobi matrix calculations -* NGrad, number of gradient calculations -* NHess, number of Hessian calculations -* NCholesky, number of Cholesky decomposition calculations -*************************************************************************/ -
class minlmreport -{ - ae_int_t iterationscount; - ae_int_t terminationtype; - ae_int_t nfunc; - ae_int_t njac; - ae_int_t ngrad; - ae_int_t nhess; - ae_int_t ncholesky; -}; - -
- -
-
/************************************************************************* -Levenberg-Marquardt optimizer. - -This structure should be created using one of the MinLMCreate???() -functions. You should not access its fields directly; use ALGLIB functions -to work with it. -*************************************************************************/ -
class minlmstate -{ -}; - -
- -
-
/************************************************************************* - LEVENBERG-MARQUARDT-LIKE METHOD FOR NON-LINEAR OPTIMIZATION - -DESCRIPTION: -This function is used to find minimum of general form (not "sum-of- --squares") function - F = F(x[0], ..., x[n-1]) -using its gradient and Hessian. Levenberg-Marquardt modification with -L-BFGS pre-optimization and internal pre-conditioned L-BFGS optimization -after each Levenberg-Marquardt step is used. - - -REQUIREMENTS: -This algorithm will request following information during its operation: - -* function value F at given point X -* F and gradient G (simultaneously) at given point X -* F, G and Hessian H (simultaneously) at given point X - -There are several overloaded versions of MinLMOptimize() function which -correspond to different LM-like optimization algorithms provided by this -unit. You should choose version which accepts func(), grad() and hess() -function pointers. First pointer is used to calculate F at given point, -second one calculates F(x) and grad F(x), third one calculates F(x), -grad F(x), hess F(x). - -You can try to initialize MinLMState structure with FGH-function and then -use incorrect version of MinLMOptimize() (for example, version which does -not provide Hessian matrix), but it will lead to exception being thrown -after first attempt to calculate Hessian. - - -USAGE: -1. User initializes algorithm state with MinLMCreateFGH() call -2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and - other functions -3. User calls MinLMOptimize() function which takes algorithm state and - pointers (delegates, etc.) to callback functions. -4. User calls MinLMResults() to get solution -5. Optionally, user may call MinLMRestartFrom() to solve another problem - with same N but another starting point and/or another function. - MinLMRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - dimension, N>1 - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - initial solution, array[0..N-1] - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. you may tune stopping conditions with MinLMSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use MinLMSetStpMax() function to bound algorithm's steps. - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlmcreatefgh( - real_1d_array x, - minlmstate& state, - const xparams _params = alglib::xdefault); -void alglib::minlmcreatefgh( - ae_int_t n, - real_1d_array x, - minlmstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This is obsolete function. - -Since ALGLIB 3.3 it is equivalent to MinLMCreateFJ(). - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlmcreatefgj( - ae_int_t m, - real_1d_array x, - minlmstate& state, - const xparams _params = alglib::xdefault); -void alglib::minlmcreatefgj( - ae_int_t n, - ae_int_t m, - real_1d_array x, - minlmstate& state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function is considered obsolete since ALGLIB 3.1.0 and is present for -backward compatibility only. We recommend to use MinLMCreateVJ, which -provides similar, but more consistent and feature-rich interface. - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlmcreatefj( - ae_int_t m, - real_1d_array x, - minlmstate& state, - const xparams _params = alglib::xdefault); -void alglib::minlmcreatefj( - ae_int_t n, - ae_int_t m, - real_1d_array x, - minlmstate& state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* - IMPROVED LEVENBERG-MARQUARDT METHOD FOR - NON-LINEAR LEAST SQUARES OPTIMIZATION - -DESCRIPTION: -This function is used to find minimum of function which is represented as -sum of squares: - F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1]) -using value of function vector f[] only. Finite differences are used to -calculate Jacobian. - - -REQUIREMENTS: -This algorithm will request following information during its operation: -* function vector f[] at given point X - -There are several overloaded versions of MinLMOptimize() function which -correspond to different LM-like optimization algorithms provided by this -unit. You should choose version which accepts fvec() callback. - -You can try to initialize MinLMState structure with VJ function and then -use incorrect version of MinLMOptimize() (for example, version which -works with general form function and does not accept function vector), but -it will lead to exception being thrown after first attempt to calculate -Jacobian. - - -USAGE: -1. User initializes algorithm state with MinLMCreateV() call -2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and - other functions -3. User calls MinLMOptimize() function which takes algorithm state and - callback functions. -4. User calls MinLMResults() to get solution -5. Optionally, user may call MinLMRestartFrom() to solve another problem - with same N/M but another starting point and/or another function. - MinLMRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - dimension, N>1 - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - M - number of functions f[i] - X - initial solution, array[0..N-1] - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -See also MinLMIteration, MinLMResults. - -NOTES: -1. you may tune stopping conditions with MinLMSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use MinLMSetStpMax() function to bound algorithm's steps. - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlmcreatev( - ae_int_t m, - real_1d_array x, - double diffstep, - minlmstate& state, - const xparams _params = alglib::xdefault); -void alglib::minlmcreatev( - ae_int_t n, - ae_int_t m, - real_1d_array x, - double diffstep, - minlmstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -This is obsolete function. - -Since ALGLIB 3.3 it is equivalent to MinLMCreateVJ(). - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlmcreatevgj( - ae_int_t m, - real_1d_array x, - minlmstate& state, - const xparams _params = alglib::xdefault); -void alglib::minlmcreatevgj( - ae_int_t n, - ae_int_t m, - real_1d_array x, - minlmstate& state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* - IMPROVED LEVENBERG-MARQUARDT METHOD FOR - NON-LINEAR LEAST SQUARES OPTIMIZATION - -DESCRIPTION: -This function is used to find minimum of function which is represented as -sum of squares: - F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1]) -using value of function vector f[] and Jacobian of f[]. - - -REQUIREMENTS: -This algorithm will request following information during its operation: - -* function vector f[] at given point X -* function vector f[] and Jacobian of f[] (simultaneously) at given point - -There are several overloaded versions of MinLMOptimize() function which -correspond to different LM-like optimization algorithms provided by this -unit. You should choose version which accepts fvec() and jac() callbacks. -First one is used to calculate f[] at given point, second one calculates -f[] and Jacobian df[i]/dx[j]. - -You can try to initialize MinLMState structure with VJ function and then -use incorrect version of MinLMOptimize() (for example, version which -works with general form function and does not provide Jacobian), but it -will lead to exception being thrown after first attempt to calculate -Jacobian. - - -USAGE: -1. User initializes algorithm state with MinLMCreateVJ() call -2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and - other functions -3. User calls MinLMOptimize() function which takes algorithm state and - callback functions. -4. User calls MinLMResults() to get solution -5. Optionally, user may call MinLMRestartFrom() to solve another problem - with same N/M but another starting point and/or another function. - MinLMRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - dimension, N>1 - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - M - number of functions f[i] - X - initial solution, array[0..N-1] - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. you may tune stopping conditions with MinLMSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use MinLMSetStpMax() function to bound algorithm's steps. - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlmcreatevj( - ae_int_t m, - real_1d_array x, - minlmstate& state, - const xparams _params = alglib::xdefault); -void alglib::minlmcreatevj( - ae_int_t n, - ae_int_t m, - real_1d_array x, - minlmstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic Jacobian. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function vector at the initial -point (note: future versions may also perform check at the final point) -and compares numerical Jacobian with analytic one provided by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both Jacobians, and specific components highlighted as -suspicious by the OptGuard. - -The OptGuard report can be retrieved with minlmoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with minlmsetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlmoptguardgradient( - minlmstate state, - double teststep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -OptGuard checks analytic Jacobian against reference value obtained by -numerical differentiation with user-specified step. - -NOTE: other optimizers perform additional OptGuard checks for things like - C0/C1-continuity violations. However, LM optimizer can check only - for incorrect Jacobian. - - The reason is that unlike line search methods LM optimizer does not - perform extensive evaluations along the line. Thus, we simply do not - have enough data to catch C0/C1-violations. - -This check is activated with minlmoptguardgradient() function. - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradfidx for specific function (Jacobian row) suspected - * rep.badgradvidx for specific variable (Jacobian column) suspected - * rep.badgradxbase, a point where gradient/Jacobian is tested - * rep.badgraduser, user-provided gradient/Jacobian - * rep.badgradnum, reference gradient/Jacobian obtained via numerical - differentiation - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - OptGuard report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlmoptguardresults( - minlmstate state, - optguardreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This family of functions is used to launcn iterations of nonlinear optimizer - -These functions accept following parameters: - state - algorithm state - func - callback which calculates function (or merit function) - value func at given point x - grad - callback which calculates function (or merit function) - value func and gradient grad at given point x - hess - callback which calculates function (or merit function) - value func, gradient grad and Hessian hess at given point x - fvec - callback which calculates function vector fi[] - at given point x - jac - callback which calculates function vector fi[] - and Jacobian jac at given point x - rep - optional callback which is called after each iteration - can be NULL - ptr - optional pointer which is passed to func/grad/hess/jac/rep - can be NULL - -NOTES: - -1. Depending on function used to create state structure, this algorithm - may accept Jacobian and/or Hessian and/or gradient. According to the - said above, there ase several versions of this function, which accept - different sets of callbacks. - - This flexibility opens way to subtle errors - you may create state with - MinLMCreateFGH() (optimization using Hessian), but call function which - does not accept Hessian. So when algorithm will request Hessian, there - will be no callback to call. In this case exception will be thrown. - - Be careful to avoid such errors because there is no way to find them at - compile time - you can see them at runtime only. - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -
void minlmoptimize(minlmstate &state, - void (*fvec)(const real_1d_array &x, real_1d_array &fi, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void minlmoptimize(minlmstate &state, - void (*fvec)(const real_1d_array &x, real_1d_array &fi, void *ptr), - void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void minlmoptimize(minlmstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*hess)(const real_1d_array &x, double &func, real_1d_array &grad, real_2d_array &hess, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void minlmoptimize(minlmstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void minlmoptimize(minlmstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -
-

Examples:   [1]  [2]  [3]  [4]  [5]  

- -
-
/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlmrequesttermination( - minlmstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine restarts LM algorithm from new point. All optimization -parameters are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure used for reverse communication previously - allocated with MinLMCreateXXX call. - X - new starting point. - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlmrestartfrom( - minlmstate state, - real_1d_array x, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Levenberg-Marquardt algorithm results - -NOTE: if you activated OptGuard integrity checking functionality and want - to get OptGuard report, it can be retrieved with the help of - minlmoptguardresults() function. - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report; includes termination codes and - additional information. Termination codes are listed below, - see comments for this structure for more info. - Termination code is stored in rep.terminationtype field: - * -8 optimizer detected NAN/INF values either in the - function itself, or in its Jacobian - * -3 constraints are inconsistent - * 2 relative step is no more than EpsX. - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible - * 8 terminated by user who called minlmrequesttermination(). - X contains point which was "current accepted" when - termination request was submitted. - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlmresults( - minlmstate state, - real_1d_array& x, - minlmreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  [5]  

- -
-
/************************************************************************* -Levenberg-Marquardt algorithm results - -Buffered implementation of MinLMResults(), which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlmresultsbuf( - minlmstate state, - real_1d_array& x, - minlmreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function is used to change acceleration settings - -You can choose between three acceleration strategies: -* AccType=0, no acceleration. -* AccType=1, secant updates are used to update quadratic model after each - iteration. After fixed number of iterations (or after model breakdown) - we recalculate quadratic model using analytic Jacobian or finite - differences. Number of secant-based iterations depends on optimization - settings: about 3 iterations - when we have analytic Jacobian, up to 2*N - iterations - when we use finite differences to calculate Jacobian. - -AccType=1 is recommended when Jacobian calculation cost is prohibitively -high (several Mx1 function vector calculations followed by several NxN -Cholesky factorizations are faster than calculation of one M*N Jacobian). -It should also be used when we have no Jacobian, because finite difference -approximation takes too much time to compute. - -Table below list optimization protocols (XYZ protocol corresponds to -MinLMCreateXYZ) and acceleration types they support (and use by default). - -ACCELERATION TYPES SUPPORTED BY OPTIMIZATION PROTOCOLS: - -protocol 0 1 comment -V + + -VJ + + -FGH + - -DEFAULT VALUES: - -protocol 0 1 comment -V x without acceleration it is so slooooooooow -VJ x -FGH x - -NOTE: this function should be called before optimization. Attempt to call -it during algorithm iterations may result in unexpected behavior. - -NOTE: attempt to call this function with unsupported protocol/acceleration -combination will result in exception being thrown. - - -- ALGLIB -- - Copyright 14.10.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlmsetacctype( - minlmstate state, - ae_int_t acctype, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets boundary constraints for LM optimizer - -Boundary constraints are inactive by default (after initial creation). -They are preserved until explicitly turned off with another SetBC() call. - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF (latter is recommended because - it will allow solver to use better algorithm). - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF (latter is recommended because - it will allow solver to use better algorithm). - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - -NOTE 2: this solver has following useful properties: -* bound constraints are always satisfied exactly -* function is evaluated only INSIDE area specified by bound constraints - or at its boundary - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlmsetbc( - minlmstate state, - real_1d_array bndl, - real_1d_array bndu, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets stopping conditions for Levenberg-Marquardt optimization -algorithm. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - ste pvector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinLMSetScale() - Recommended values: 1E-9 ... 1E-12. - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. Only Levenberg-Marquardt - iterations are counted (L-BFGS/CG iterations are NOT - counted because their cost is very low compared to that of - LM). - -Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic -stopping criterion selection (small EpsX). - -NOTE: it is not recommended to set large EpsX (say, 0.001). Because LM is - a second-order method, it performs very precise steps anyway. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlmsetcond( - minlmstate state, - double epsx, - ae_int_t maxits, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  [5]  

- -
-
/************************************************************************* -This function sets general linear constraints for LM optimizer - -Linear constraints are inactive by default (after initial creation). They -are preserved until explicitly turned off with another minlmsetlc() call. - -INPUT PARAMETERS: - State - structure stores algorithm state - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -IMPORTANT: if you have linear constraints, it is strongly recommended to - set scale of variables with minlmsetscale(). QP solver which is - used to calculate linearly constrained steps heavily relies on - good scaling of input problems. - -IMPORTANT: solvers created with minlmcreatefgh() do not support linear - constraints. - -NOTE: linear (non-bound) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations. - -NOTE: general linear constraints add significant overhead to solution - process. Although solver performs roughly same amount of iterations - (when compared with similar box-only constrained problem), each - iteration now involves solution of linearly constrained QP - subproblem, which requires ~3-5 times more Cholesky decompositions. - Thus, if you can reformulate your problem in such way this it has - only box constraints, it may be beneficial to do so. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlmsetlc( - minlmstate state, - real_2d_array c, - integer_1d_array ct, - const xparams _params = alglib::xdefault); -void alglib::minlmsetlc( - minlmstate state, - real_2d_array c, - integer_1d_array ct, - ae_int_t k, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets scaling coefficients for LM optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Generally, scale is NOT considered to be a form of preconditioner. But LM -optimizer is unique in that it uses scaling matrix both in the stopping -condition tests and as Marquardt damping factor. - -Proper scaling is very important for the algorithm performance. It is less -important for the quality of results, but still has some influence (it is -easier to converge when variables are properly scaled, so premature -stopping is possible when very badly scalled variables are combined with -relaxed stopping conditions). - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlmsetscale( - minlmstate state, - real_1d_array s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which leads to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - -NOTE: non-zero StpMax leads to moderate performance degradation because -intermediate step of preconditioned L-BFGS optimization is incompatible -with limits on step size. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlmsetstpmax( - minlmstate state, - double stpmax, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinLMOptimize(). Both Levenberg-Marquardt and internal L-BFGS -iterations are reported. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlmsetxrep( - minlmstate state, - bool needxrep, - const xparams _params = alglib::xdefault); - -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void function1_func(const real_1d_array &x, double &func, void *ptr)
-{
-    //
-    // this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4
-    //
-    func = 100*pow(x[0]+3,4) + pow(x[1]-3,4);
-}
-void function1_grad(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr) 
-{
-    //
-    // this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4
-    // and its derivatives df/d0 and df/dx1
-    //
-    func = 100*pow(x[0]+3,4) + pow(x[1]-3,4);
-    grad[0] = 400*pow(x[0]+3,3);
-    grad[1] = 4*pow(x[1]-3,3);
-}
-void function1_hess(const real_1d_array &x, double &func, real_1d_array &grad, real_2d_array &hess, void *ptr)
-{
-    //
-    // this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4
-    // its derivatives df/d0 and df/dx1
-    // and its Hessian.
-    //
-    func = 100*pow(x[0]+3,4) + pow(x[1]-3,4);
-    grad[0] = 400*pow(x[0]+3,3);
-    grad[1] = 4*pow(x[1]-3,3);
-    hess[0][0] = 1200*pow(x[0]+3,2);
-    hess[0][1] = 0;
-    hess[1][0] = 0;
-    hess[1][1] = 12*pow(x[1]-3,2);
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of F(x0,x1) = 100*(x0+3)^4+(x1-3)^4
-    // using "FGH" mode of the Levenberg-Marquardt optimizer.
-    //
-    // F is treated like a monolitic function without internal structure,
-    // i.e. we do NOT represent it as a sum of squares.
-    //
-    // Optimization algorithm uses:
-    // * function value F(x0,x1)
-    // * gradient G={dF/dxi}
-    // * Hessian H={d2F/(dxi*dxj)}
-    //
-    real_1d_array x = "[0,0]";
-    double epsx = 0.0000000001;
-    ae_int_t maxits = 0;
-    minlmstate state;
-    minlmreport rep;
-
-    minlmcreatefgh(x, state);
-    minlmsetcond(state, epsx, maxits);
-    alglib::minlmoptimize(state, function1_func, function1_grad, function1_hess);
-    minlmresults(state, x, rep);
-
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [-3,+3]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void  function1_fvec(const real_1d_array &x, real_1d_array &fi, void *ptr)
-{
-    //
-    // this callback calculates
-    // f0(x0,x1) = 100*(x0+3)^4,
-    // f1(x0,x1) = (x1-3)^4
-    //
-    fi[0] = 10*pow(x[0]+3,2);
-    fi[1] = pow(x[1]-3,2);
-}
-void  function2_fvec(const real_1d_array &x, real_1d_array &fi, void *ptr)
-{
-    //
-    // this callback calculates
-    // f0(x0,x1) = x0^2+1
-    // f1(x0,x1) = x1-1
-    //
-    fi[0] = x[0]*x[0]+1;
-    fi[1] = x[1]-1;
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of F(x0,x1) = f0^2+f1^2, where 
-    //
-    //     f0(x0,x1) = 10*(x0+3)^2
-    //     f1(x0,x1) = (x1-3)^2
-    //
-    // using several starting points and efficient restarts.
-    //
-    real_1d_array x;
-    double epsx = 0.0000000001;
-    ae_int_t maxits = 0;
-    minlmstate state;
-    minlmreport rep;
-
-    //
-    // create optimizer using minlmcreatev()
-    //
-    x = "[10,10]";
-    minlmcreatev(2, x, 0.0001, state);
-    minlmsetcond(state, epsx, maxits);
-    alglib::minlmoptimize(state, function1_fvec);
-    minlmresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [-3,+3]
-
-    //
-    // restart optimizer using minlmrestartfrom()
-    //
-    // we can use different starting point, different function,
-    // different stopping conditions, but problem size
-    // must remain unchanged.
-    //
-    x = "[4,4]";
-    minlmrestartfrom(state, x);
-    alglib::minlmoptimize(state, function2_fvec);
-    minlmresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [0,1]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void  function1_fvec(const real_1d_array &x, real_1d_array &fi, void *ptr)
-{
-    //
-    // this callback calculates
-    // f0(x0,x1) = 100*(x0+3)^4,
-    // f1(x0,x1) = (x1-3)^4
-    //
-    fi[0] = 10*pow(x[0]+3,2);
-    fi[1] = pow(x[1]-3,2);
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of F(x0,x1) = f0^2+f1^2, where 
-    //
-    //     f0(x0,x1) = 10*(x0+3)^2
-    //     f1(x0,x1) = (x1-3)^2
-    //
-    // using "V" mode of the Levenberg-Marquardt optimizer.
-    //
-    // Optimization algorithm uses:
-    // * function vector f[] = {f1,f2}
-    //
-    // No other information (Jacobian, gradient, etc.) is needed.
-    //
-    real_1d_array x = "[0,0]";
-    real_1d_array s = "[1,1]";
-    double epsx = 0.0000000001;
-    ae_int_t maxits = 0;
-    minlmstate state;
-    minlmreport rep;
-
-    //
-    // Create optimizer, tell it to:
-    // * use numerical differentiation with step equal to 0.0001
-    // * use unit scale for all variables (s is a unit vector)
-    // * stop after short enough step (less than epsx)
-    //
-    minlmcreatev(2, x, 0.0001, state);
-    minlmsetcond(state, epsx, maxits);
-    minlmsetscale(state, s);
-
-    //
-    // Optimize
-    //
-    alglib::minlmoptimize(state, function1_fvec);
-
-    //
-    // Test optimization results
-    //
-    // NOTE: because we use numerical differentiation, we do not
-    //       verify Jacobian correctness - it is always "correct".
-    //       However, if you switch to analytic gradient, consider
-    //       checking it with OptGuard (see other examples).
-    //
-    minlmresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [-3,+3]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void  function1_fvec(const real_1d_array &x, real_1d_array &fi, void *ptr)
-{
-    //
-    // this callback calculates
-    // f0(x0,x1) = 100*(x0+3)^4,
-    // f1(x0,x1) = (x1-3)^4
-    //
-    fi[0] = 10*pow(x[0]+3,2);
-    fi[1] = pow(x[1]-3,2);
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of F(x0,x1) = f0^2+f1^2, where 
-    //
-    //     f0(x0,x1) = 10*(x0+3)^2
-    //     f1(x0,x1) = (x1-3)^2
-    //
-    // with boundary constraints
-    //
-    //     -1 <= x0 <= +1
-    //     -1 <= x1 <= +1
-    //
-    // using "V" mode of the Levenberg-Marquardt optimizer.
-    //
-    // Optimization algorithm uses:
-    // * function vector f[] = {f1,f2}
-    //
-    // No other information (Jacobian, gradient, etc.) is needed.
-    //
-    real_1d_array x = "[0,0]";
-    real_1d_array s = "[1,1]";
-    real_1d_array bndl = "[-1,-1]";
-    real_1d_array bndu = "[+1,+1]";
-    double epsx = 0.0000000001;
-    ae_int_t maxits = 0;
-    minlmstate state;
-
-    //
-    // Create optimizer, tell it to:
-    // * use numerical differentiation with step equal to 1.0
-    // * use unit scale for all variables (s is a unit vector)
-    // * stop after short enough step (less than epsx)
-    // * set box constraints
-    //
-    minlmcreatev(2, x, 0.0001, state);
-    minlmsetbc(state, bndl, bndu);
-    minlmsetcond(state, epsx, maxits);
-    minlmsetscale(state, s);
-
-    //
-    // Optimize
-    //
-    alglib::minlmoptimize(state, function1_fvec);
-
-    //
-    // Test optimization results
-    //
-    // NOTE: because we use numerical differentiation, we do not
-    //       verify Jacobian correctness - it is always "correct".
-    //       However, if you switch to analytic gradient, consider
-    //       checking it with OptGuard (see other examples).
-    //
-    minlmreport rep;
-    minlmresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [-1,+1]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void  function1_fvec(const real_1d_array &x, real_1d_array &fi, void *ptr)
-{
-    //
-    // this callback calculates
-    // f0(x0,x1) = 100*(x0+3)^4,
-    // f1(x0,x1) = (x1-3)^4
-    //
-    fi[0] = 10*pow(x[0]+3,2);
-    fi[1] = pow(x[1]-3,2);
-}
-void  function1_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr)
-{
-    //
-    // this callback calculates
-    // f0(x0,x1) = 100*(x0+3)^4,
-    // f1(x0,x1) = (x1-3)^4
-    // and Jacobian matrix J = [dfi/dxj]
-    //
-    fi[0] = 10*pow(x[0]+3,2);
-    fi[1] = pow(x[1]-3,2);
-    jac[0][0] = 20*(x[0]+3);
-    jac[0][1] = 0;
-    jac[1][0] = 0;
-    jac[1][1] = 2*(x[1]-3);
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of F(x0,x1) = f0^2+f1^2, where 
-    //
-    //     f0(x0,x1) = 10*(x0+3)^2
-    //     f1(x0,x1) = (x1-3)^2
-    //
-    // using "VJ" mode of the Levenberg-Marquardt optimizer.
-    //
-    // Optimization algorithm uses:
-    // * function vector f[] = {f1,f2}
-    // * Jacobian matrix J = {dfi/dxj}.
-    //
-    real_1d_array x = "[0,0]";
-    real_1d_array s = "[1,1]";
-    double epsx = 0.0000000001;
-    ae_int_t maxits = 0;
-    minlmstate state;
-
-    //
-    // Create optimizer, tell it to:
-    // * use analytic gradient provided by user
-    // * use unit scale for all variables (s is a unit vector)
-    // * stop after short enough step (less than epsx)
-    //
-    minlmcreatevj(2, x, state);
-    minlmsetcond(state, epsx, maxits);
-    minlmsetscale(state, s);
-
-    //
-    // Activate OptGuard integrity checking.
-    //
-    // OptGuard monitor helps to detect erroneous analytic Jacobian,
-    // i.e. one inconsistent with actual change in the target function.
-    //
-    // OptGuard is essential for early prototyping stages because such
-    // problems often result in premature termination of the optimizer
-    // which is really hard to distinguish from the correct termination.
-    //
-    // IMPORTANT: JACOBIAN VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL
-    //            DIFFERENTIATION, THUS DO NOT USE IT IN PRODUCTION CODE!
-    //
-    minlmoptguardgradient(state, 0.001);
-
-    //
-    // Optimize
-    //
-    alglib::minlmoptimize(state, function1_fvec, function1_jac);
-
-    //
-    // Test optimization results
-    //
-    minlmreport rep;
-    minlmresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [-3,+3]
-
-    //
-    // Check that OptGuard did not report errors
-    //
-    // NOTE: want to test OptGuard? Try breaking the Jacobian - say, add
-    //       1.0 to some of its components.
-    //
-    // NOTE: unfortunately, specifics of LM optimization do not allow us
-    //       to detect errors like nonsmoothness (like we do with other
-    //       optimizers). So, only Jacobian correctness is verified.
-    //
-    optguardreport ogrep;
-    minlmoptguardresults(state, ogrep);
-    printf("%s\n", ogrep.badgradsuspected ? "true" : "false"); // EXPECTED: false
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* -This structure stores optimization report: -* f target function value -* lagbc Lagrange coefficients for box constraints -* laglc Lagrange coefficients for linear constraints -* y dual variables -* stats array[N+M], statuses of box (N) and linear (M) - constraints. This array is filled only by DSS - algorithm because IPM always stops at INTERIOR - point: - * stats[i]>0 => constraint at upper bound - (also used for free non-basic - variables set to zero) - * stats[i]<0 => constraint at lower bound - * stats[i]=0 => constraint is inactive, basic - variable -* primalerror primal feasibility error -* dualerror dual feasibility error -* slackerror complementary slackness error -* iterationscount iteration count -* terminationtype completion code (see below) - -COMPLETION CODES - -Completion codes: -* -4 LP problem is primal unbounded (dual infeasible) -* -3 LP problem is primal infeasible (dual unbounded) -* 1..4 successful completion -* 5 MaxIts steps was taken -* 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - -LAGRANGE COEFFICIENTS - -Positive Lagrange coefficient means that constraint is at its upper bound. -Negative coefficient means that constraint is at its lower bound. It is -expected that at solution the dual feasibility condition holds: - - C + SUM(Ei*LagBC[i],i=0..n-1) + SUM(Ai*LagLC[i],i=0..m-1) ~ 0 - -where -* C is a cost vector (linear term) -* Ei is a vector with 1.0 at position I and 0 in other positions -* Ai is an I-th row of linear constraint matrix -*************************************************************************/ -
class minlpreport -{ - double f; - real_1d_array lagbc; - real_1d_array laglc; - real_1d_array y; - integer_1d_array stats; - double primalerror; - double dualerror; - double slackerror; - ae_int_t iterationscount; - ae_int_t terminationtype; -}; - -
- -
-
/************************************************************************* -This object stores linear solver state. -You should use functions provided by MinLP subpackage to work with this -object -*************************************************************************/ -
class minlpstate -{ -}; - -
- -
-
/************************************************************************* -This function appends two-sided linear constraint AL <= A*x <= AU to the -list of currently present constraints. - -Constraint is passed in compressed format: as list of non-zero entries of -coefficient vector A. Such approach is more efficient than dense storage -for highly sparse constraint vectors. - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - IdxA - array[NNZ], indexes of non-zero elements of A: - * can be unsorted - * can include duplicate indexes (corresponding entries of - ValA[] will be summed) - ValA - array[NNZ], values of non-zero elements of A - NNZ - number of non-zero coefficients in A - AL, AU - lower and upper bounds; - * AL=AU => equality constraint A*x - * AL<AU => two-sided constraint AL<=A*x<=AU - * AL=-INF => one-sided constraint A*x<=AU - * AU=+INF => one-sided constraint AL<=A*x - * AL=-INF, AU=+INF => constraint is ignored - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlpaddlc2( - minlpstate state, - integer_1d_array idxa, - real_1d_array vala, - ae_int_t nnz, - double al, - double au, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function appends two-sided linear constraint AL <= A*x <= AU to the -list of currently present constraints. - -This version accepts dense constraint vector as input, but sparsifies it -for internal storage and processing. Thus, time to add one constraint in -is O(N) - we have to scan entire array of length N. Sparse version of this -function is order of magnitude faster for constraints with just a few -nonzeros per row. - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - A - linear constraint coefficient, array[N], right side is NOT - included. - AL, AU - lower and upper bounds; - * AL=AU => equality constraint Ai*x - * AL<AU => two-sided constraint AL<=A*x<=AU - * AL=-INF => one-sided constraint Ai*x<=AU - * AU=+INF => one-sided constraint AL<=Ai*x - * AL=-INF, AU=+INF => constraint is ignored - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlpaddlc2dense( - minlpstate state, - real_1d_array a, - double al, - double au, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* - LINEAR PROGRAMMING - -The subroutine creates LP solver. After initial creation it contains -default optimization problem with zero cost vector and all variables being -fixed to zero values and no constraints. - -In order to actually solve something you should: -* set cost vector with minlpsetcost() -* set variable bounds with minlpsetbc() or minlpsetbcall() -* specify constraint matrix with one of the following functions: - [*] minlpsetlc() for dense one-sided constraints - [*] minlpsetlc2dense() for dense two-sided constraints - [*] minlpsetlc2() for sparse two-sided constraints - [*] minlpaddlc2dense() to add one dense row to constraint matrix - [*] minlpaddlc2() to add one row to constraint matrix (compressed format) -* call minlpoptimize() to run the solver and minlpresults() to get the - solution vector and additional information. - -By default, LP solver uses best algorithm available. As of ALGLIB 3.17, -sparse interior point (barrier) solver is used. Future releases of ALGLIB -may introduce other solvers. - -User may choose specific LP algorithm by calling: -* minlpsetalgodss() for revised dual simplex method with DSE pricing and - bounds flipping ratio test (aka long dual step). Large-scale sparse LU - solverwith Forest-Tomlin update is used internally as linear algebra - driver. -* minlpsetalgoipm() for sparse interior point method - -INPUT PARAMETERS: - N - problem size - -OUTPUT PARAMETERS: - State - optimizer in the default state - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlpcreate( - ae_int_t n, - minlpstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function solves LP problem. - -INPUT PARAMETERS: - State - algorithm state - -You should use minlpresults() function to access results after calls to -this function. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey. -*************************************************************************/ -
void alglib::minlpoptimize( - minlpstate state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -LP solver results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[N], solution (on failure: last trial point) - Rep - optimization report. You should check Rep.TerminationType, - which contains completion code, and you may check another - fields which contain another information about algorithm - functioning. - - Failure codes returned by algorithm are: - * -4 LP problem is primal unbounded (dual infeasible) - * -3 LP problem is primal infeasible (dual unbounded) - * -2 IPM solver detected that problem is either - infeasible or unbounded - - Success codes: - * 1..4 successful completion - * 5 MaxIts steps was taken - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlpresults( - minlpstate state, - real_1d_array& x, - minlpreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -LP results - -Buffered implementation of MinLPResults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlpresultsbuf( - minlpstate state, - real_1d_array& x, - minlpreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets LP algorithm to revised dual simplex method. - -ALGLIB implementation of dual simplex method supports advanced performance -and stability improvements like DSE pricing , bounds flipping ratio test -(aka long dual step), Forest-Tomlin update, shifting. - -INPUT PARAMETERS: - State - optimizer - Eps - stopping condition, Eps>=0: - * should be small number about 1E-6 or 1E-7. - * zero value means that solver automatically selects good - value (can be different in different ALGLIB versions) - * default value is zero - Algorithm stops when relative error is less than Eps. - -===== TRACING DSS SOLVER ================================================= - -DSS solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'DSS' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. -* 'DSS.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'DSS'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("DSS,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 08.11.2020 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlpsetalgodss( - minlpstate state, - double eps, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets LP algorithm to sparse interior point method. - -ALGORITHM INFORMATION: - -* this algorithm is our implementation of interior point method as - formulated by R.J.Vanderbei, with minor modifications to the algorithm - (damped Newton directions are extensively used) -* like all interior point methods, this algorithm tends to converge in - roughly same number of iterations (between 15 and 50) independently from - the problem dimensionality - -INPUT PARAMETERS: - State - optimizer - Eps - stopping condition, Eps>=0: - * should be small number about 1E-7 or 1E-8. - * zero value means that solver automatically selects good - value (can be different in different ALGLIB versions) - * default value is zero - Algorithm stops when primal error AND dual error AND - duality gap are less than Eps. - -===== TRACING IPM SOLVER ================================================= - -IPM solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'IPM' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. -* 'IPM.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'IPM'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("IPM,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 08.11.2020 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlpsetalgoipm( - minlpstate state, - const xparams _params = alglib::xdefault); -void alglib::minlpsetalgoipm( - minlpstate state, - double eps, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets box constraints for LP solver (all variables at once, -different constraints for different variables). - -The default state of constraints is to have all variables fixed at zero. -You have to overwrite it by your own constraint vector. Constraint status -is preserved until constraints are explicitly overwritten with another -minlpsetbc() call, overwritten with minlpsetbcall(), or partially -overwritten with minlmsetbci() call. - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd[i] BndL[i]=BndU[i] - lower bound BndL[i]<=x[i] BndU[i]=+INF - upper bound x[i]<=BndU[i] BndL[i]=-INF - range BndL[i]<=x[i]<=BndU[i] ... - free variable - BndL[I]=-INF, BndU[I]+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - BndU - upper bounds, array[N]. - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: if constraints for all variables are same you may use minlpsetbcall() - which allows to specify constraints without using arrays. - -NOTE: BndL>BndU will result in LP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlpsetbc( - minlpstate state, - real_1d_array bndl, - real_1d_array bndu, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function sets box constraints for LP solver (all variables at once, -same constraints for all variables) - -The default state of constraints is to have all variables fixed at zero. -You have to overwrite it by your own constraint vector. Constraint status -is preserved until constraints are explicitly overwritten with another -minlpsetbc() call or partially overwritten with minlpsetbcall(). - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd[i] BndL[i]=BndU[i] - lower bound BndL[i]<=x[i] BndU[i]=+INF - upper bound x[i]<=BndU[i] BndL[i]=-INF - range BndL[i]<=x[i]<=BndU[i] ... - free variable - BndL[I]=-INF, BndU[I]+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bound, same for all variables - BndU - upper bound, same for all variables - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: minlpsetbc() can be used to specify different constraints for - different variables. - -NOTE: BndL>BndU will result in LP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlpsetbcall( - minlpstate state, - double bndl, - double bndu, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function sets box constraints for I-th variable (other variables are -not modified). - -The default state of constraints is to have all variables fixed at zero. -You have to overwrite it by your own constraint vector. - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd[i] BndL[i]=BndU[i] - lower bound BndL[i]<=x[i] BndU[i]=+INF - upper bound x[i]<=BndU[i] BndL[i]=-INF - range BndL[i]<=x[i]<=BndU[i] ... - free variable - BndL[I]=-INF, BndU[I]+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - I - variable index, in [0,N) - BndL - lower bound for I-th variable - BndU - upper bound for I-th variable - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: minlpsetbc() can be used to specify different constraints for - different variables. - -NOTE: BndL>BndU will result in LP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlpsetbci( - minlpstate state, - ae_int_t i, - double bndl, - double bndu, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function sets cost term for LP solver. - -By default, cost term is zero. - -INPUT PARAMETERS: - State - structure which stores algorithm state - C - cost term, array[N]. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlpsetcost( - minlpstate state, - real_1d_array c, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function sets one-sided linear constraints A*x ~ AU, where "~" can be -a mix of "<=", "=" and ">=". - -IMPORTANT: this function is provided here for compatibility with the rest - of ALGLIB optimizers which accept constraints in format like - this one. Many real-life problems feature two-sided constraints - like a0 <= a*x <= a1. It is really inefficient to add them as a - pair of one-sided constraints. - - Use minlpsetlc2dense(), minlpsetlc2(), minlpaddlc2() (or its - sparse version) wherever possible. - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - A - linear constraints, array[K,N+1]. Each row of A represents - one constraint, with first N elements being linear coefficients, - and last element being right side. - CT - constraint types, array[K]: - * if CT[i]>0, then I-th constraint is A[i,*]*x >= A[i,n] - * if CT[i]=0, then I-th constraint is A[i,*]*x = A[i,n] - * if CT[i]<0, then I-th constraint is A[i,*]*x <= A[i,n] - K - number of equality/inequality constraints, K>=0; if not - given, inferred from sizes of A and CT. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlpsetlc( - minlpstate state, - real_2d_array a, - integer_1d_array ct, - const xparams _params = alglib::xdefault); -void alglib::minlpsetlc( - minlpstate state, - real_2d_array a, - integer_1d_array ct, - ae_int_t k, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU with -sparse constraining matrix A. Recommended for large-scale problems. - -This function overwrites linear (non-box) constraints set by previous -calls (if such calls were made). - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - A - sparse matrix with size [K,N] (exactly!). - Each row of A represents one general linear constraint. - A can be stored in any sparse storage format. - AL, AU - lower and upper bounds, array[K]; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i]<AU[i] => two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0. If K=0 - is specified, A, AL, AU are ignored. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlpsetlc2( - minlpstate state, - sparsematrix a, - real_1d_array al, - real_1d_array au, - ae_int_t k, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU. - -This version accepts dense matrix as input; internally LP solver uses -sparse storage anyway (most LP problems are sparse), but for your -convenience it may accept dense inputs. This function overwrites linear -constraints set by previous calls (if such calls were made). - -We recommend you to use sparse version of this function unless you solve -small-scale LP problem (less than few hundreds of variables). - -NOTE: there also exist several versions of this function: - * one-sided dense version which accepts constraints in the same - format as one used by QP and NLP solvers - * two-sided sparse version which accepts sparse matrix - * two-sided dense version which allows you to add constraints row by row - * two-sided sparse version which allows you to add constraints row by row - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - A - linear constraints, array[K,N]. Each row of A represents - one constraint. One-sided inequality constraints, two- - sided inequality constraints, equality constraints are - supported (see below) - AL, AU - lower and upper bounds, array[K]; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i]<AU[i] => two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0; if not - given, inferred from sizes of A, AL, AU. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlpsetlc2dense( - minlpstate state, - real_2d_array a, - real_1d_array al, - real_1d_array au, - const xparams _params = alglib::xdefault); -void alglib::minlpsetlc2dense( - minlpstate state, - real_2d_array a, - real_1d_array al, - real_1d_array au, - ae_int_t k, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function sets scaling coefficients. - -ALGLIB optimizers use scaling matrices to test stopping conditions and as -preconditioner. - -Scale of the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the - function - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minlpsetscale( - minlpstate state, - real_1d_array s, - const xparams _params = alglib::xdefault); - -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates how to minimize
-    //
-    //     F(x0,x1) = -0.1*x0 - x1
-    //
-    // subject to box constraints
-    //
-    //     -1 <= x0,x1 <= +1 
-    //
-    // and general linear constraints
-    //
-    //     x0 - x1 >= -1
-    //     x0 + x1 <=  1
-    //
-    // We use dual simplex solver provided by ALGLIB for this task. Box
-    // constraints are specified by means of constraint vectors bndl and
-    // bndu (we have bndl<=x<=bndu). General linear constraints are
-    // specified as AL<=A*x<=AU, with AL/AU being 2x1 vectors and A being
-    // 2x2 matrix.
-    //
-    // NOTE: some/all components of AL/AU can be +-INF, same applies to
-    //       bndl/bndu. You can also have AL[I]=AU[i] (as well as
-    //       BndL[i]=BndU[i]).
-    //
-    real_2d_array a = "[[1,-1],[1,+1]]";
-    real_1d_array al = "[-1,-inf]";
-    real_1d_array au = "[+inf,+1]";
-    real_1d_array c = "[-0.1,-1]";
-    real_1d_array s = "[1,1]";
-    real_1d_array bndl = "[-1,-1]";
-    real_1d_array bndu = "[+1,+1]";
-    real_1d_array x;
-    minlpstate state;
-    minlpreport rep;
-
-    minlpcreate(2, state);
-
-    //
-    // Set cost vector, box constraints, general linear constraints.
-    //
-    // Box constraints can be set in one call to minlpsetbc() or minlpsetbcall()
-    // (latter sets same constraints for all variables and accepts two scalars
-    // instead of two vectors).
-    //
-    // General linear constraints can be specified in several ways:
-    // * minlpsetlc2dense() - accepts dense 2D array as input; sometimes this
-    //   approach is more convenient, although less memory-efficient.
-    // * minlpsetlc2() - accepts sparse matrix as input
-    // * minlpaddlc2dense() - appends one row to the current set of constraints;
-    //   row being appended is specified as dense vector
-    // * minlpaddlc2() - appends one row to the current set of constraints;
-    //   row being appended is specified as sparse set of elements
-    // Independently from specific function being used, LP solver uses sparse
-    // storage format for internal representation of constraints.
-    //
-    minlpsetcost(state, c);
-    minlpsetbc(state, bndl, bndu);
-    minlpsetlc2dense(state, a, al, au, 2);
-
-    //
-    // Set scale of the parameters.
-    //
-    // It is strongly recommended that you set scale of your variables.
-    // Knowing their scales is essential for evaluation of stopping criteria
-    // and for preconditioning of the algorithm steps.
-    // You can find more information on scaling at http://www.alglib.net/optimization/scaling.php
-    //
-    minlpsetscale(state, s);
-
-    // Solve
-    minlpoptimize(state);
-    minlpresults(state, x, rep);
-    printf("%s\n", x.tostring(3).c_str()); // EXPECTED: [0,1]
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* -These fields store optimization report: -* iterationscount total number of inner iterations -* nfev number of gradient evaluations -* terminationtype termination type (see below) - -Scaled constraint violations are reported: -* bcerr maximum violation of the box constraints -* bcidx index of the most violated box constraint (or - -1, if all box constraints are satisfied or - there is no box constraint) -* lcerr maximum violation of the linear constraints, - computed as maximum scaled distance between - final point and constraint boundary. -* lcidx index of the most violated linear constraint - (or -1, if all constraints are satisfied or - there is no general linear constraints) -* nlcerr maximum violation of the nonlinear constraints -* nlcidx index of the most violated nonlinear constraint - (or -1, if all constraints are satisfied or - there is no nonlinear constraints) - -Violations of box constraints are scaled on per-component basis according -to the scale vector s[] as specified by minnlcsetscale(). Violations of -the general linear constraints are also computed using user-supplied -variable scaling. Violations of nonlinear constraints are computed "as is" - -TERMINATION CODES - -TerminationType field contains completion code, which can be either: - -=== FAILURE CODE === - -8 internal integrity control detected infinite or NAN values in - function/gradient. Abnormal termination signaled. - -3 box constraints are infeasible. Note: infeasibility of non-box - constraints does NOT trigger emergency completion; you have to - examine bcerr/lcerr/nlcerr to detect possibly inconsistent - constraints. - -=== SUCCESS CODE === - 2 relative step is no more than EpsX. - 5 MaxIts steps was taken - 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - 8 user requested algorithm termination via minnlcrequesttermination(), - last accepted point is returned - -Other fields of this structure are not documented and should not be used! -*************************************************************************/ -
class minnlcreport -{ - ae_int_t iterationscount; - ae_int_t nfev; - ae_int_t terminationtype; - double bcerr; - ae_int_t bcidx; - double lcerr; - ae_int_t lcidx; - double nlcerr; - ae_int_t nlcidx; - ae_int_t dbgphase0its; -}; - -
- -
-
/************************************************************************* -This object stores nonlinear optimizer state. -You should use functions provided by MinNLC subpackage to work with this -object -*************************************************************************/ -
class minnlcstate -{ -}; - -
- -
-
/************************************************************************* - NONLINEARLY CONSTRAINED OPTIMIZATION - WITH PRECONDITIONED AUGMENTED LAGRANGIAN ALGORITHM - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments subject to any -combination of: -* bound constraints -* linear inequality constraints -* linear equality constraints -* nonlinear equality constraints Gi(x)=0 -* nonlinear inequality constraints Hi(x)<=0 - -REQUIREMENTS: -* user must provide function value and gradient for F(), H(), G() -* starting point X0 must be feasible or not too far away from the feasible - set -* F(), G(), H() are continuously differentiable on the feasible set and - its neighborhood -* nonlinear constraints G() and H() must have non-zero gradient at G(x)=0 - and at H(x)=0. Say, constraint like x^2>=1 is supported, but x^2>=0 is - NOT supported. - -USAGE: - -Constrained optimization if far more complex than the unconstrained one. -Nonlinearly constrained optimization is one of the most esoteric numerical -procedures. - -Here we give very brief outline of the MinNLC optimizer. We strongly -recommend you to study examples in the ALGLIB Reference Manual and to read -ALGLIB User Guide on optimization, which is available at -http://www.alglib.net/optimization/ - -1. User initializes algorithm state with MinNLCCreate() call and chooses - what NLC solver to use. There is some solver which is used by default, - with default settings, but you should NOT rely on default choice. It - may change in future releases of ALGLIB without notice, and no one can - guarantee that new solver will be able to solve your problem with - default settings. - - From the other side, if you choose solver explicitly, you can be pretty - sure that it will work with new ALGLIB releases. - - In the current release following solvers can be used: - * SQP solver, recommended for medium-scale problems (less than thousand - of variables) with hard-to-evaluate target functions. Requires less - function evaluations than other solvers but each step involves - solution of QP subproblem, so running time may be higher than that of - AUL (another recommended option). Activated with minnlcsetalgosqp() - function. - * AUL solver with dense preconditioner, recommended for large-scale - problems or for problems with cheap target function. Needs more - function evaluations that SQP (about 5x-10x times more), but its - iterations are much cheaper that that of SQP. Activated with - minnlcsetalgoaul() function. - * SLP solver, successive linear programming. The slowest one, requires - more target function evaluations that SQP and AUL. However, it is - somewhat more robust in tricky cases, so it can be used as a backup - plan. Activated with minnlcsetalgoslp() function. - -2. [optional] user activates OptGuard integrity checker which tries to - detect possible errors in the user-supplied callbacks: - * discontinuity/nonsmoothness of the target/nonlinear constraints - * errors in the analytic gradient provided by user - This feature is essential for early prototyping stages because it helps - to catch common coding and problem statement errors. - OptGuard can be activated with following functions (one per each check - performed): - * minnlcoptguardsmoothness() - * minnlcoptguardgradient() - -3. User adds boundary and/or linear and/or nonlinear constraints by means - of calling one of the following functions: - a) minnlcsetbc() for boundary constraints - b) minnlcsetlc() for linear constraints - c) minnlcsetnlc() for nonlinear constraints - You may combine (a), (b) and (c) in one optimization problem. - -4. User sets scale of the variables with minnlcsetscale() function. It is - VERY important to set scale of the variables, because nonlinearly - constrained problems are hard to solve when variables are badly scaled. - -5. User sets stopping conditions with minnlcsetcond(). If NLC solver - uses inner/outer iteration layout, this function sets stopping - conditions for INNER iterations. - -6. Finally, user calls minnlcoptimize() function which takes algorithm - state and pointer (delegate, etc.) to callback function which calculates - F/G/H. - -7. User calls minnlcresults() to get solution; additionally you can - retrieve OptGuard report with minnlcoptguardresults(), and get detailed - report about purported errors in the target function with: - * minnlcoptguardnonc1test0results() - * minnlcoptguardnonc1test1results() - -8. Optionally user may call minnlcrestartfrom() to solve another problem - with same N but another starting point. minnlcrestartfrom() allows to - reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size ofX - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlccreate( - real_1d_array x, - minnlcstate& state, - const xparams _params = alglib::xdefault); -void alglib::minnlccreate( - ae_int_t n, - real_1d_array x, - minnlcstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -This subroutine is a finite difference variant of MinNLCCreate(). It uses -finite differences in order to differentiate target function. - -Description below contains information which is specific to this function -only. We recommend to read comments on MinNLCCreate() in order to get more -information about creation of NLC optimizer. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size ofX - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinNLCSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large TRUNCATION errors, while too small - step will result in too large NUMERICAL errors. 1.0E-4 can be good - value to start from. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. Imprecise gradient may slow down - convergence, especially on highly nonlinear problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlccreatef( - real_1d_array x, - double diffstep, - minnlcstate& state, - const xparams _params = alglib::xdefault); -void alglib::minnlccreatef( - ae_int_t n, - real_1d_array x, - double diffstep, - minnlcstate& state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic gradient/Jacobian. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function (constraints) at the -initial point (note: future versions may also perform check at the final -point) and compares numerical gradient/Jacobian with analytic one provided -by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both gradients/Jacobians, and specific components highlighted -as suspicious by the OptGuard. - -The primary OptGuard report can be retrieved with minnlcoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with minnlcsetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcoptguardgradient( - minnlcstate state, - double teststep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #0 - -Nonsmoothness (non-C1) test #0 studies function values (not gradient!) -obtained during line searches and monitors behavior of the directional -derivative estimate. - -This test is less powerful than test #1, but it does not depend on the -gradient values and thus it is more robust against artifacts introduced by -numerical differentiation. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* fidx - is an index of the function (0 for target function, 1 or higher - for nonlinear constraints) which is suspected of being "non-C1" -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #0 "strong" report - lngrep - C1 test #0 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcoptguardnonc1test0results( - minnlcstate state, - optguardnonc1test0report& strrep, - optguardnonc1test0report& lngrep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #1 - -Nonsmoothness (non-C1) test #1 studies individual components of the -gradient computed during line search. - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* fidx - is an index of the function (0 for target function, 1 or higher - for nonlinear constraints) which is suspected of being "non-C1" -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #1 "strong" report - lngrep - C1 test #1 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcoptguardnonc1test1results( - minnlcstate state, - optguardnonc1test1report& strrep, - optguardnonc1test1report& lngrep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -=== PRIMARY REPORT ======================================================= - -OptGuard performs several checks which are intended to catch common errors -in the implementation of nonlinear function/gradient: -* incorrect analytic gradient -* discontinuous (non-C0) target functions (constraints) -* nonsmooth (non-C1) target functions (constraints) - -Each of these checks is activated with appropriate function: -* minnlcoptguardgradient() for gradient verification -* minnlcoptguardsmoothness() for C0/C1 checks - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradfidx for specific function (Jacobian row) suspected - * rep.badgradvidx for specific variable (Jacobian column) suspected - * rep.badgradxbase, a point where gradient/Jacobian is tested - * rep.badgraduser, user-provided gradient/Jacobian - * rep.badgradnum, reference gradient/Jacobian obtained via numerical - differentiation -* rep.nonc0suspected, and additionally: - * rep.nonc0fidx - an index of specific function violating C0 continuity -* rep.nonc1suspected, and additionally - * rep.nonc1fidx - an index of specific function violating C1 continuity -Here function index 0 means target function, index 1 or higher denotes -nonlinear constraints. - -=== ADDITIONAL REPORTS/LOGS ============================================== - -Several different tests are performed to catch C0/C1 errors, you can find -out specific test signaled error by looking to: -* rep.nonc0test0positive, for non-C0 test #0 -* rep.nonc1test0positive, for non-C1 test #0 -* rep.nonc1test1positive, for non-C1 test #1 - -Additional information (including line search logs) can be obtained by -means of: -* minnlcoptguardnonc1test0results() -* minnlcoptguardnonc1test1results() -which return detailed error reports, specific points where discontinuities -were found, and so on. - -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - generic OptGuard report; more detailed reports can be - retrieved with other functions. - -NOTE: false negatives (nonsmooth problems are not identified as nonsmooth - ones) are possible although unlikely. - - The reason is that you need to make several evaluations around - nonsmoothness in order to accumulate enough information about - function curvature. Say, if you start right from the nonsmooth point, - optimizer simply won't get enough data to understand what is going - wrong before it terminates due to abrupt changes in the derivative. - It is also possible that "unlucky" step will move us to the - termination too quickly. - - Our current approach is to have less than 0.1% false negatives in - our test examples (measured with multiple restarts from random - points), and to have exactly 0% false positives. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcoptguardresults( - minnlcstate state, - optguardreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) and/or constraints -b) nonsmooth target function (non-C1) and/or constraints - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - This kind of monitoring does not work well with SQP - because SQP solver needs just 1-2 function evaluations - per step, which is not enough for OptGuard to make - any conclusions. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcoptguardsmoothness( - minnlcstate state, - const xparams _params = alglib::xdefault); -void alglib::minnlcoptguardsmoothness( - minnlcstate state, - ae_int_t level, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This family of functions is used to launcn iterations of nonlinear optimizer - -These functions accept following parameters: - state - algorithm state - fvec - callback which calculates function vector fi[] - at given point x - jac - callback which calculates function vector fi[] - and Jacobian jac at given point x - rep - optional callback which is called after each iteration - can be NULL - ptr - optional pointer which is passed to func/grad/hess/jac/rep - can be NULL - - -NOTES: - -1. This function has two different implementations: one which uses exact - (analytical) user-supplied Jacobian, and one which uses only function - vector and numerically differentiates function in order to obtain - gradient. - - Depending on the specific function used to create optimizer object - you should choose appropriate variant of MinNLCOptimize() - one which - accepts function AND Jacobian or one which accepts ONLY function. - - Be careful to choose variant of MinNLCOptimize() which corresponds to - your optimization scheme! Table below lists different combinations of - callback (function/gradient) passed to MinNLCOptimize() and specific - function used to create optimizer. - - - | USER PASSED TO MinNLCOptimize() - CREATED WITH | function only | function and gradient - ------------------------------------------------------------ - MinNLCCreateF() | works FAILS - MinNLCCreate() | FAILS works - - Here "FAILS" denotes inappropriate combinations of optimizer creation - function and MinNLCOptimize() version. Attemps to use such - combination will lead to exception. Either you did not pass gradient - when it WAS needed or you passed gradient when it was NOT needed. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -
void minnlcoptimize(minnlcstate &state, - void (*fvec)(const real_1d_array &x, real_1d_array &fi, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void minnlcoptimize(minnlcstate &state, - void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcrequesttermination( - minnlcstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine restarts algorithm from new point. -All optimization parameters (including constraints) are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure previously allocated with MinNLCCreate call. - X - new starting point. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcrestartfrom( - minnlcstate state, - real_1d_array x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -MinNLC results: the solution found, completion codes and additional -information. - -If you activated OptGuard integrity checking functionality and want to get -OptGuard report, it can be retrieved with: -* minnlcoptguardresults() - for a primary report about (a) suspected C0/C1 - continuity violations and (b) errors in the analytic gradient. -* minnlcoptguardnonc1test0results() - for C1 continuity violation test #0, - detailed line search log -* minnlcoptguardnonc1test1results() - for C1 continuity violation test #1, - detailed line search log - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report, contains information about completion - code, constraint violation at the solution and so on. - - You should check rep.terminationtype in order to - distinguish successful termination from unsuccessful one: - - === FAILURE CODES === - * -8 internal integrity control detected infinite or - NAN values in function/gradient. Abnormal - termination signalled. - * -3 box constraints are infeasible. - Note: infeasibility of non-box constraints does - NOT trigger emergency completion; you have - to examine rep.bcerr/rep.lcerr/rep.nlcerr to - detect possibly inconsistent constraints. - - === SUCCESS CODES === - * 2 scaled step is no more than EpsX. - * 5 MaxIts steps were taken. - * 8 user requested algorithm termination via - minnlcrequesttermination(), last accepted point is - returned. - - More information about fields of this structure can be - found in the comments on minnlcreport datatype. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcresults( - minnlcstate state, - real_1d_array& x, - minnlcreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -NLC results - -Buffered implementation of MinNLCResults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcresultsbuf( - minnlcstate state, - real_1d_array& x, - minnlcreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function tells MinNLC unit to use Augmented Lagrangian algorithm -for nonlinearly constrained optimization. This algorithm is a slight -modification of one described in "A Modified Barrier-Augmented Lagrangian -Method for Constrained Minimization (1999)" by D.GOLDFARB, R.POLYAK, -K. SCHEINBERG, I.YUZEFOVICH. - -AUL solver can be significantly faster than SQP on easy problems due to -cheaper iterations, although it needs more function evaluations. - -Augmented Lagrangian algorithm works by converting problem of minimizing -F(x) subject to equality/inequality constraints to unconstrained problem -of the form - - min[ f(x) + - + Rho*PENALTY_EQ(x) + SHIFT_EQ(x,Nu1) + - + Rho*PENALTY_INEQ(x) + SHIFT_INEQ(x,Nu2) ] - -where: -* Rho is a fixed penalization coefficient -* PENALTY_EQ(x) is a penalty term, which is used to APPROXIMATELY enforce - equality constraints -* SHIFT_EQ(x) is a special "shift" term which is used to "fine-tune" - equality constraints, greatly increasing precision -* PENALTY_INEQ(x) is a penalty term which is used to approximately enforce - inequality constraints -* SHIFT_INEQ(x) is a special "shift" term which is used to "fine-tune" - inequality constraints, greatly increasing precision -* Nu1/Nu2 are vectors of Lagrange coefficients which are fine-tuned during - outer iterations of algorithm - -This version of AUL algorithm uses preconditioner, which greatly -accelerates convergence. Because this algorithm is similar to penalty -methods, it may perform steps into infeasible area. All kinds of -constraints (boundary, linear and nonlinear ones) may be violated in -intermediate points - and in the solution. However, properly configured -AUL method is significantly better at handling constraints than barrier -and/or penalty methods. - -The very basic outline of algorithm is given below: -1) first outer iteration is performed with "default" values of Lagrange - multipliers Nu1/Nu2. Solution quality is low (candidate point can be - too far away from true solution; large violation of constraints is - possible) and is comparable with that of penalty methods. -2) subsequent outer iterations refine Lagrange multipliers and improve - quality of the solution. - -INPUT PARAMETERS: - State - structure which stores algorithm state - Rho - penalty coefficient, Rho>0: - * large enough that algorithm converges with desired - precision. Minimum value is 10*max(S'*diag(H)*S), where - S is a scale matrix (set by MinNLCSetScale) and H is a - Hessian of the function being minimized. If you can not - easily estimate Hessian norm, see our recommendations - below. - * not TOO large to prevent ill-conditioning - * for unit-scale problems (variables and Hessian have unit - magnitude), Rho=100 or Rho=1000 can be used. - * it is important to note that Rho is internally multiplied - by scaling matrix, i.e. optimum value of Rho depends on - scale of variables specified by MinNLCSetScale(). - ItsCnt - number of outer iterations: - * ItsCnt=0 means that small number of outer iterations is - automatically chosen (10 iterations in current version). - * ItsCnt=1 means that AUL algorithm performs just as usual - barrier method. - * ItsCnt>1 means that AUL algorithm performs specified - number of outer iterations - -HOW TO CHOOSE PARAMETERS - -Nonlinear optimization is a tricky area and Augmented Lagrangian algorithm -is sometimes hard to tune. Good values of Rho and ItsCnt are problem- -specific. In order to help you we prepared following set of -recommendations: - -* for unit-scale problems (variables and Hessian have unit magnitude), - Rho=100 or Rho=1000 can be used. - -* start from some small value of Rho and solve problem with just one - outer iteration (ItcCnt=1). In this case algorithm behaves like penalty - method. Increase Rho in 2x or 10x steps until you see that one outer - iteration returns point which is "rough approximation to solution". - - It is very important to have Rho so large that penalty term becomes - constraining i.e. modified function becomes highly convex in constrained - directions. - - From the other side, too large Rho may prevent you from converging to - the solution. You can diagnose it by studying number of inner iterations - performed by algorithm: too few (5-10 on 1000-dimensional problem) or - too many (orders of magnitude more than dimensionality) usually means - that Rho is too large. - -* with just one outer iteration you usually have low-quality solution. - Some constraints can be violated with very large margin, while other - ones (which are NOT violated in the true solution) can push final point - too far in the inner area of the feasible set. - - For example, if you have constraint x0>=0 and true solution x0=1, then - merely a presence of "x0>=0" will introduce a bias towards larger values - of x0. Say, algorithm may stop at x0=1.5 instead of 1.0. - -* after you found good Rho, you may increase number of outer iterations. - ItsCnt=10 is a good value. Subsequent outer iteration will refine values - of Lagrange multipliers. Constraints which were violated will be - enforced, inactive constraints will be dropped (corresponding multipliers - will be decreased). Ideally, you should see 10-1000x improvement in - constraint handling (constraint violation is reduced). - -* if you see that algorithm converges to vicinity of solution, but - additional outer iterations do not refine solution, it may mean that - algorithm is unstable - it wanders around true solution, but can not - approach it. Sometimes algorithm may be stabilized by increasing Rho one - more time, making it 5x or 10x larger. - -SCALING OF CONSTRAINTS [IMPORTANT] - -AUL optimizer scales variables according to scale specified by -MinNLCSetScale() function, so it can handle problems with badly scaled -variables (as long as we KNOW their scales). However, because function -being optimized is a mix of original function and constraint-dependent -penalty functions, it is important to rescale both variables AND -constraints. - -Say, if you minimize f(x)=x^2 subject to 1000000*x>=0, then you have -constraint whose scale is different from that of target function (another -example is 0.000001*x>=0). It is also possible to have constraints whose -scales are misaligned: 1000000*x0>=0, 0.000001*x1<=0. Inappropriate -scaling may ruin convergence because minimizing x^2 subject to x>=0 is NOT -same as minimizing it subject to 1000000*x>=0. - -Because we know coefficients of boundary/linear constraints, we can -automatically rescale and normalize them. However, there is no way to -automatically rescale nonlinear constraints Gi(x) and Hi(x) - they are -black boxes. - -It means that YOU are the one who is responsible for correct scaling of -nonlinear constraints Gi(x) and Hi(x). We recommend you to rescale -nonlinear constraints in such way that I-th component of dG/dX (or dH/dx) -has magnitude approximately equal to 1/S[i] (where S is a scale set by -MinNLCSetScale() function). - -WHAT IF IT DOES NOT CONVERGE? - -It is possible that AUL algorithm fails to converge to precise values of -Lagrange multipliers. It stops somewhere around true solution, but candidate -point is still too far from solution, and some constraints are violated. -Such kind of failure is specific for Lagrangian algorithms - technically, -they stop at some point, but this point is not constrained solution. - -There are exist several reasons why algorithm may fail to converge: -a) too loose stopping criteria for inner iteration -b) degenerate, redundant constraints -c) target function has unconstrained extremum exactly at the boundary of - some constraint -d) numerical noise in the target function - -In all these cases algorithm is unstable - each outer iteration results in -large and almost random step which improves handling of some constraints, -but violates other ones (ideally outer iterations should form a sequence -of progressively decreasing steps towards solution). - -First reason possible is that too loose stopping criteria for inner -iteration were specified. Augmented Lagrangian algorithm solves a sequence -of intermediate problems, and requries each of them to be solved with high -precision. Insufficient precision results in incorrect update of Lagrange -multipliers. - -Another reason is that you may have specified degenerate constraints: say, -some constraint was repeated twice. In most cases AUL algorithm gracefully -handles such situations, but sometimes it may spend too much time figuring -out subtle degeneracies in constraint matrix. - -Third reason is tricky and hard to diagnose. Consider situation when you -minimize f=x^2 subject to constraint x>=0. Unconstrained extremum is -located exactly at the boundary of constrained area. In this case -algorithm will tend to oscillate between negative and positive x. Each -time it stops at x<0 it "reinforces" constraint x>=0, and each time it is -bounced to x>0 it "relaxes" constraint (and is attracted to x<0). - -Such situation sometimes happens in problems with hidden symetries. -Algorithm is got caught in a loop with Lagrange multipliers being -continuously increased/decreased. Luckily, such loop forms after at least -three iterations, so this problem can be solved by DECREASING number of -outer iterations down to 1-2 and increasing penalty coefficient Rho as -much as possible. - -Final reason is numerical noise. AUL algorithm is robust against moderate -noise (more robust than, say, active set methods), but large noise may -destabilize algorithm. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcsetalgoaul( - minnlcstate state, - double rho, - ae_int_t itscnt, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -This function tells MinNLC optimizer to use SLP (Successive Linear -Programming) algorithm for nonlinearly constrained optimization. This -algorithm is a slight modification of one described in "A Linear -programming-based optimization algorithm for solving nonlinear programming -problems" (2010) by Claus Still and Tapio Westerlund. - -This solver is the slowest one in ALGLIB, it requires more target function -evaluations that SQP and AUL. However it is somewhat more robust in tricky -cases, so it can be used as a backup plan. We recommend to use this algo -when SQP/AUL do not work (does not return the solution you expect). If -trying different approach gives same results, then MAYBE something is -wrong with your optimization problem. - -Despite its name ("linear" = "first order method") this algorithm performs -steps similar to that of conjugate gradients method; internally it uses -orthogonality/conjugacy requirement for subsequent steps which makes it -closer to second order methods in terms of convergence speed. - -Convergence is proved for the following case: -* function and constraints are continuously differentiable (C1 class) -* extended Mangasarian–Fromovitz constraint qualification (EMFCQ) holds; - in the context of this algorithm EMFCQ means that one can, for any - infeasible point, find a search direction such that the constraint - infeasibilities are reduced. - -This algorithm has following nice properties: -* no parameters to tune -* no convexity requirements for target function or constraints -* initial point can be infeasible -* algorithm respects box constraints in all intermediate points (it does - not even evaluate function outside of box constrained area) -* once linear constraints are enforced, algorithm will not violate them -* no such guarantees can be provided for nonlinear constraints, but once - nonlinear constraints are enforced, algorithm will try to respect them - as much as possible -* numerical differentiation does not violate box constraints (although - general linear and nonlinear ones can be violated during differentiation) -* from our experience, this algorithm is somewhat more robust in really - difficult cases - -INPUT PARAMETERS: - State - structure which stores algorithm state - -===== TRACING SLP SOLVER ================================================= - -SLP solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'SLP' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. - It also prints OptGuard integrity checker report when - nonsmoothness of target/constraints is suspected. -* 'SLP.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'SLP'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format -* 'SLP.PROBING' - to let algorithm insert additional function evaluations - before line search in order to build human-readable - chart of the raw Lagrangian (~40 additional function - evaluations is performed for each line search). This - symbol also implicitly defines 'SLP'. -* 'OPTGUARD' - for report of smoothness/continuity violations in target - and/or constraints. This kind of reporting is included - in 'SLP', but it comes with lots of additional info. If - you need just smoothness monitoring, specify this - setting. - - NOTE: this tag merely directs OptGuard output to log - file. Even if you specify it, you still have to - configure OptGuard by calling minnlcoptguard...() - family of functions. - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. Specifying 'SLP.PROBING' adds even larger -overhead due to additional function evaluations being performed. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("SLP,SLP.PROBING,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 02.04.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcsetalgoslp( - minnlcstate state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -This function tells MinNLC optimizer to use SQP (Successive Quadratic -Programming) algorithm for nonlinearly constrained optimization. - -This algorithm needs order of magnitude (5x-10x) less function evaluations -than AUL solver, but has higher overhead because each iteration involves -solution of quadratic programming problem. - -Convergence is proved for the following case: -* function and constraints are continuously differentiable (C1 class) - -This algorithm has following nice properties: -* no parameters to tune -* no convexity requirements for target function or constraints -* initial point can be infeasible -* algorithm respects box constraints in all intermediate points (it does - not even evaluate function outside of box constrained area) -* once linear constraints are enforced, algorithm will not violate them -* no such guarantees can be provided for nonlinear constraints, but once - nonlinear constraints are enforced, algorithm will try to respect them - as much as possible -* numerical differentiation does not violate box constraints (although - general linear and nonlinear ones can be violated during differentiation) - -We recommend this algorithm as a default option for medium-scale problems -(less than thousand of variables) or problems with target function being -hard to evaluate. - -For large-scale problems or ones with very cheap target function -AUL solver can be better option. - -INPUT PARAMETERS: - State - structure which stores algorithm state - -===== INTERACTION WITH OPTGUARD ========================================== - -OptGuard integrity checker allows us to catch problems like errors in -gradients and discontinuity/nonsmoothness of the target/constraints. -Latter kind of problems can be detected by looking upon line searches -performed during optimization and searching for signs of nonsmoothness. - -The problem with SQP is that it is too good for OptGuard to work - it does -not perform line searches. It typically needs 1-2 function evaluations -per step, and it is not enough for OptGuard to detect nonsmoothness. - -So, if you suspect that your problem is nonsmooth, we recommend you to use -AUL or SLP solvers. - -===== TRACING SQP SOLVER ================================================= - -SQP solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'SQP' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. - It also prints OptGuard integrity checker report when - nonsmoothness of target/constraints is suspected. -* 'SQP.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'SQP'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format -* 'SQP.PROBING' - to let algorithm insert additional function evaluations - before line search in order to build human-readable - chart of the raw Lagrangian (~40 additional function - evaluations is performed for each line search). This - symbol also implicitly defines 'SQP' and activates - OptGuard integrity checker which detects continuity and - smoothness violations. An OptGuard log is printed at the - end of the file. - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. Specifying 'SQP.PROBING' adds even larger -overhead due to additional function evaluations being performed. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("SQP,SQP.PROBING,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 02.12.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcsetalgosqp( - minnlcstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets boundary constraints for NLC optimizer. - -Boundary constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with MinNLCRestartFrom(). - -You may combine boundary constraints with general linear ones - and with -nonlinear ones! Boundary constraints are handled more efficiently than -other types. Thus, if your problem has mixed constraints, you may -explicitly specify some of them as boundary and save some time/space. - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF. - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF. - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - -NOTE 2: when you solve your problem with augmented Lagrangian solver, - boundary constraints are satisfied only approximately! It is - possible that algorithm will evaluate function outside of - feasible area! - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcsetbc( - minnlcstate state, - real_1d_array bndl, - real_1d_array bndu, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets stopping conditions for inner iterations of optimizer. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - step vector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinNLCSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic -selection of the stopping condition. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcsetcond( - minnlcstate state, - double epsx, - ae_int_t maxits, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -This function sets linear constraints for MinNLC optimizer. - -Linear constraints are inactive by default (after initial creation). They -are preserved after algorithm restart with MinNLCRestartFrom(). - -You may combine linear constraints with boundary ones - and with nonlinear -ones! If your problem has mixed constraints, you may explicitly specify -some of them as linear. It may help optimizer to handle them more -efficiently. - -INPUT PARAMETERS: - State - structure previously allocated with MinNLCCreate call. - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -NOTE 1: when you solve your problem with augmented Lagrangian solver, - linear constraints are satisfied only approximately! It is - possible that algorithm will evaluate function outside of - feasible area! - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcsetlc( - minnlcstate state, - real_2d_array c, - integer_1d_array ct, - const xparams _params = alglib::xdefault); -void alglib::minnlcsetlc( - minnlcstate state, - real_2d_array c, - integer_1d_array ct, - ae_int_t k, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets nonlinear constraints for MinNLC optimizer. - -In fact, this function sets NUMBER of nonlinear constraints. Constraints -itself (constraint functions) are passed to MinNLCOptimize() method. This -method requires user-defined vector function F[] and its Jacobian J[], -where: -* first component of F[] and first row of Jacobian J[] corresponds to - function being minimized -* next NLEC components of F[] (and rows of J) correspond to nonlinear - equality constraints G_i(x)=0 -* next NLIC components of F[] (and rows of J) correspond to nonlinear - inequality constraints H_i(x)<=0 - -NOTE: you may combine nonlinear constraints with linear/boundary ones. If - your problem has mixed constraints, you may explicitly specify some - of them as linear ones. It may help optimizer to handle them more - efficiently. - -INPUT PARAMETERS: - State - structure previously allocated with MinNLCCreate call. - NLEC - number of Non-Linear Equality Constraints (NLEC), >=0 - NLIC - number of Non-Linear Inquality Constraints (NLIC), >=0 - -NOTE 1: when you solve your problem with augmented Lagrangian solver, - nonlinear constraints are satisfied only approximately! It is - possible that algorithm will evaluate function outside of - feasible area! - -NOTE 2: algorithm scales variables according to scale specified by - MinNLCSetScale() function, so it can handle problems with badly - scaled variables (as long as we KNOW their scales). - - However, there is no way to automatically scale nonlinear - constraints Gi(x) and Hi(x). Inappropriate scaling of Gi/Hi may - ruin convergence. Solving problem with constraint "1000*G0(x)=0" - is NOT same as solving it with constraint "0.001*G0(x)=0". - - It means that YOU are the one who is responsible for correct - scaling of nonlinear constraints Gi(x) and Hi(x). We recommend you - to scale nonlinear constraints in such way that I-th component of - dG/dX (or dH/dx) has approximately unit magnitude (for problems - with unit scale) or has magnitude approximately equal to 1/S[i] - (where S is a scale set by MinNLCSetScale() function). - - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcsetnlc( - minnlcstate state, - ae_int_t nlec, - ae_int_t nlic, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -This function sets preconditioner to "exact low rank" mode. - -Preconditioning is very important for convergence of Augmented Lagrangian -algorithm because presence of penalty term makes problem ill-conditioned. -Difference between performance of preconditioned and unpreconditioned -methods can be as large as 100x! - -MinNLC optimizer may use following preconditioners, each with its own -benefits and drawbacks: - a) inexact LBFGS-based, with O(N*K) evaluation time - b) exact low rank one, with O(N*K^2) evaluation time - c) exact robust one, with O(N^3+K*N^2) evaluation time -where K is a total number of general linear and nonlinear constraints (box -ones are not counted). - -It also provides special unpreconditioned mode of operation which can be -used for test purposes. Comments below discuss low rank preconditioner. - -Exact low-rank preconditioner uses Woodbury matrix identity to build -quadratic model of the penalized function. It has following features: -* no special assumptions about orthogonality of constraints -* preconditioner evaluation is optimized for K<<N. Its cost is O(N*K^2), - so it may become prohibitively slow for K>=N. -* finally, stability of the process is guaranteed only for K<<N. Woodbury - update often fail for K>=N due to degeneracy of intermediate matrices. - That's why we recommend to use "exact robust" preconditioner for such - cases. - -RECOMMENDATIONS - -We recommend to choose between "exact low rank" and "exact robust" -preconditioners, with "low rank" version being chosen when you know in -advance that total count of non-box constraints won't exceed N, and "robust" -version being chosen when you need bulletproof solution. - -INPUT PARAMETERS: - State - structure stores algorithm state - UpdateFreq- update frequency. Preconditioner is rebuilt after every - UpdateFreq iterations. Recommended value: 10 or higher. - Zero value means that good default value will be used. - - -- ALGLIB -- - Copyright 26.09.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcsetprecexactlowrank( - minnlcstate state, - ae_int_t updatefreq, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -This function sets preconditioner to "exact robust" mode. - -Preconditioning is very important for convergence of Augmented Lagrangian -algorithm because presence of penalty term makes problem ill-conditioned. -Difference between performance of preconditioned and unpreconditioned -methods can be as large as 100x! - -MinNLC optimizer may use following preconditioners, each with its own -benefits and drawbacks: - a) inexact LBFGS-based, with O(N*K) evaluation time - b) exact low rank one, with O(N*K^2) evaluation time - c) exact robust one, with O(N^3+K*N^2) evaluation time -where K is a total number of general linear and nonlinear constraints (box -ones are not counted). - -It also provides special unpreconditioned mode of operation which can be -used for test purposes. Comments below discuss robust preconditioner. - -Exact robust preconditioner uses Cholesky decomposition to invert -approximate Hessian matrix H=D+W'*C*W (where D stands for diagonal terms -of Hessian, combined result of initial scaling matrix and penalty from box -constraints; W stands for general linear constraints and linearization of -nonlinear ones; C stands for diagonal matrix of penalty coefficients). - -This preconditioner has following features: -* no special assumptions about constraint structure -* preconditioner is optimized for stability; unlike "exact low rank" - version which fails for K>=N, this one works well for any value of K. -* the only drawback is that is takes O(N^3+K*N^2) time to build it. No - economical Woodbury update is applied even when it makes sense, thus - there are exist situations (K<<N) when "exact low rank" preconditioner - outperforms this one. - -RECOMMENDATIONS - -We recommend to choose between "exact low rank" and "exact robust" -preconditioners, with "low rank" version being chosen when you know in -advance that total count of non-box constraints won't exceed N, and "robust" -version being chosen when you need bulletproof solution. - -INPUT PARAMETERS: - State - structure stores algorithm state - UpdateFreq- update frequency. Preconditioner is rebuilt after every - UpdateFreq iterations. Recommended value: 10 or higher. - Zero value means that good default value will be used. - - -- ALGLIB -- - Copyright 26.09.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcsetprecexactrobust( - minnlcstate state, - ae_int_t updatefreq, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets preconditioner to "inexact LBFGS-based" mode. - -Preconditioning is very important for convergence of Augmented Lagrangian -algorithm because presence of penalty term makes problem ill-conditioned. -Difference between performance of preconditioned and unpreconditioned -methods can be as large as 100x! - -MinNLC optimizer may use following preconditioners, each with its own -benefits and drawbacks: - a) inexact LBFGS-based, with O(N*K) evaluation time - b) exact low rank one, with O(N*K^2) evaluation time - c) exact robust one, with O(N^3+K*N^2) evaluation time -where K is a total number of general linear and nonlinear constraints (box -ones are not counted). - -Inexact LBFGS-based preconditioner uses L-BFGS formula combined with -orthogonality assumption to perform very fast updates. For a N-dimensional -problem with K general linear or nonlinear constraints (boundary ones are -not counted) it has O(N*K) cost per iteration. This preconditioner has -best quality (less iterations) when general linear and nonlinear -constraints are orthogonal to each other (orthogonality with respect to -boundary constraints is not required). Number of iterations increases when -constraints are non-orthogonal, because algorithm assumes orthogonality, -but still it is better than no preconditioner at all. - -INPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 26.09.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcsetprecinexact( - minnlcstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets preconditioner to "turned off" mode. - -Preconditioning is very important for convergence of Augmented Lagrangian -algorithm because presence of penalty term makes problem ill-conditioned. -Difference between performance of preconditioned and unpreconditioned -methods can be as large as 100x! - -MinNLC optimizer may utilize two preconditioners, each with its own -benefits and drawbacks: a) inexact LBFGS-based, and b) exact low rank one. -It also provides special unpreconditioned mode of operation which can be -used for test purposes. - -This function activates this test mode. Do not use it in production code -to solve real-life problems. - -INPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 26.09.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcsetprecnone( - minnlcstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets scaling coefficients for NLC optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of the optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcsetscale( - minnlcstate state, - real_1d_array s, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -This function sets maximum step length (after scaling of step vector with -respect to variable scales specified by minnlcsetscale() call). - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0 (default), if - you don't want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which leads to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - -NOTE: different solvers employed by MinNLC optimizer use different norms - for step; AUL solver uses 2-norm, whilst SLP solver uses INF-norm. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcsetstpmax( - minnlcstate state, - double stpmax, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinNLCOptimize(). - -NOTE: algorithm passes two parameters to rep() callback - current point - and penalized function value at current point. Important - function - value which is returned is NOT function being minimized. It is sum - of the value of the function being minimized - and penalty term. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnlcsetxrep( - minnlcstate state, - bool needxrep, - const xparams _params = alglib::xdefault); - -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void  nlcfunc1_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr)
-{
-    //
-    // this callback calculates
-    //
-    //     f0(x0,x1) = -x0+x1
-    //     f1(x0,x1) = x0^2+x1^2-1
-    //
-    // and Jacobian matrix J = [dfi/dxj]
-    //
-    fi[0] = -x[0]+x[1];
-    fi[1] = x[0]*x[0] + x[1]*x[1] - 1.0;
-    jac[0][0] = -1.0;
-    jac[0][1] = +1.0;
-    jac[1][0] = 2*x[0];
-    jac[1][1] = 2*x[1];
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of
-    //
-    //     f(x0,x1) = -x0+x1
-    //
-    // subject to nonlinear equality constraint
-    //
-    //    x0^2 + x1^2 - 1 = 0
-    //
-    real_1d_array x0 = "[0,0]";
-    real_1d_array s = "[1,1]";
-    double epsx = 0.000001;
-    ae_int_t maxits = 0;
-    minnlcstate state;
-
-    //
-    // Create optimizer object and tune its settings:
-    // * epsx=0.000001  stopping condition for inner iterations
-    // * s=[1,1]        all variables have unit scale
-    //
-    minnlccreate(2, x0, state);
-    minnlcsetcond(state, epsx, maxits);
-    minnlcsetscale(state, s);
-
-    //
-    // Choose one of the nonlinear programming solvers supported by minnlc
-    // optimizer:
-    // * SLP - successive linear programming NLP solver
-    // * AUL - augmented Lagrangian NLP solver
-    //
-    // Different solvers have different properties:
-    // * SLP is the most robust solver provided by ALGLIB: it can solve both
-    //   convex and nonconvex optimization problems, it respects box and
-    //   linear constraints (after you find feasible point it won't move away
-    //   from the feasible area) and tries to respect nonlinear constraints
-    //   as much as possible. It also usually needs less function evaluations
-    //   to converge than AUL.
-    //   However, it solves LP subproblems at each iterations which adds
-    //   significant overhead to its running time. Sometimes it can be as much
-    //   as 7x times slower than AUL.
-    // * AUL solver is less robust than SLP - it can violate box and linear
-    //   constraints at any moment, and it is intended for convex optimization
-    //   problems (although in many cases it can deal with nonconvex ones too).
-    //   Also, unlike SLP it needs some tuning (penalty factor and number of
-    //   outer iterations).
-    //   However, it is often much faster than the current version of SLP.
-    //
-    // In the code below we set solver to be AUL but then override it with SLP,
-    // so the effective choice is to use SLP. We recommend you to use SLP at
-    // least for early prototyping stages.
-    //
-    // You can comment out line with SLP if you want to solve your problem with
-    // AUL solver.
-    //
-    double rho = 1000.0;
-    ae_int_t outerits = 5;
-    minnlcsetalgoaul(state, rho, outerits);
-    minnlcsetalgoslp(state);
-
-    //
-    // Set constraints:
-    //
-    // Nonlinear constraints are tricky - you can not "pack" general
-    // nonlinear function into double precision array. That's why
-    // minnlcsetnlc() does not accept constraints itself - only constraint
-    // counts are passed: first parameter is number of equality constraints,
-    // second one is number of inequality constraints.
-    //
-    // As for constraining functions - these functions are passed as part
-    // of problem Jacobian (see below).
-    //
-    // NOTE: MinNLC optimizer supports arbitrary combination of boundary, general
-    //       linear and general nonlinear constraints. This example does not
-    //       show how to work with general linear constraints, but you can
-    //       easily find it in documentation on minnlcsetbc() and
-    //       minnlcsetlc() functions.
-    //
-    minnlcsetnlc(state, 1, 0);
-
-    //
-    // Activate OptGuard integrity checking.
-    //
-    // OptGuard monitor helps to catch common coding and problem statement
-    // issues, like:
-    // * discontinuity of the target/constraints (C0 continuity violation)
-    // * nonsmoothness of the target/constraints (C1 continuity violation)
-    // * erroneous analytic Jacobian, i.e. one inconsistent with actual
-    //   change in the target/constraints
-    //
-    // OptGuard is essential for early prototyping stages because such
-    // problems often result in premature termination of the optimizer
-    // which is really hard to distinguish from the correct termination.
-    //
-    // IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL
-    //            DIFFERENTIATION, THUS DO NOT USE IT IN PRODUCTION CODE!
-    //
-    //            Other OptGuard checks add moderate overhead, but anyway
-    //            it is better to turn them off when they are not needed.
-    //
-    minnlcoptguardsmoothness(state);
-    minnlcoptguardgradient(state, 0.001);
-
-    //
-    // Optimize and test results.
-    //
-    // Optimizer object accepts vector function and its Jacobian, with first
-    // component (Jacobian row) being target function, and next components
-    // (Jacobian rows) being nonlinear equality and inequality constraints.
-    //
-    // So, our vector function has form
-    //
-    //     {f0,f1} = { -x0+x1 , x0^2+x1^2-1 }
-    //
-    // with Jacobian
-    //
-    //         [  -1    +1  ]
-    //     J = [            ]
-    //         [ 2*x0  2*x1 ]
-    //
-    // with f0 being target function, f1 being constraining function. Number
-    // of equality/inequality constraints is specified by minnlcsetnlc(),
-    // with equality ones always being first, inequality ones being last.
-    //
-    minnlcreport rep;
-    real_1d_array x1;
-    alglib::minnlcoptimize(state, nlcfunc1_jac);
-    minnlcresults(state, x1, rep);
-    printf("%s\n", x1.tostring(2).c_str()); // EXPECTED: [0.70710,-0.70710]
-
-    //
-    // Check that OptGuard did not report errors
-    //
-    // NOTE: want to test OptGuard? Try breaking the Jacobian - say, add
-    //       1.0 to some of its components.
-    //
-    optguardreport ogrep;
-    minnlcoptguardresults(state, ogrep);
-    printf("%s\n", ogrep.badgradsuspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc0suspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc1suspected ? "true" : "false"); // EXPECTED: false
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void  nlcfunc1_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr)
-{
-    //
-    // this callback calculates
-    //
-    //     f0(x0,x1) = -x0+x1
-    //     f1(x0,x1) = x0^2+x1^2-1
-    //
-    // and Jacobian matrix J = [dfi/dxj]
-    //
-    fi[0] = -x[0]+x[1];
-    fi[1] = x[0]*x[0] + x[1]*x[1] - 1.0;
-    jac[0][0] = -1.0;
-    jac[0][1] = +1.0;
-    jac[1][0] = 2*x[0];
-    jac[1][1] = 2*x[1];
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of
-    //
-    //     f(x0,x1) = -x0+x1
-    //
-    // subject to box constraints
-    //
-    //    x0>=0, x1>=0
-    //
-    // and nonlinear inequality constraint
-    //
-    //    x0^2 + x1^2 - 1 <= 0
-    //
-    real_1d_array x0 = "[0,0]";
-    real_1d_array s = "[1,1]";
-    double epsx = 0.000001;
-    ae_int_t maxits = 0;
-    real_1d_array bndl = "[0,0]";
-    real_1d_array bndu = "[+inf,+inf]";
-    minnlcstate state;
-
-    //
-    // Create optimizer object and tune its settings:
-    // * epsx=0.000001  stopping condition for inner iterations
-    // * s=[1,1]        all variables have unit scale; it is important to
-    //                  tell optimizer about scales of your variables - it
-    //                  greatly accelerates convergence and helps to perform
-    //                  some important integrity checks.
-    //
-    minnlccreate(2, x0, state);
-    minnlcsetcond(state, epsx, maxits);
-    minnlcsetscale(state, s);
-
-    //
-    // Choose one of the nonlinear programming solvers supported by minnlc
-    // optimizer:
-    // * SQP - sequential quadratic programming NLP solver
-    // * AUL - augmented Lagrangian NLP solver
-    // * SLP - successive linear programming NLP solver
-    //
-    // Different solvers have different properties:
-    // * SQP needs less function evaluations than any other solver, but it
-    //   has much higher iteration cost than other solvers (a QP subproblem
-    //   has to be solved during each step)
-    // * AUL solver has cheaper iterations, but needs more target function
-    //   evaluations
-    // * SLP is the most robust solver provided by ALGLIB, but it performs
-    //   order of magnitude more iterations than SQP.
-    //
-    // In the code below we set solver to be AUL but then override it with SLP,
-    // and then with SQP, so the effective choice is to use SLP. We recommend
-    // you to use SQP at least for early prototyping stages, and then switch
-    // to AUL if possible.
-    //
-    double rho = 1000.0;
-    ae_int_t outerits = 5;
-    minnlcsetalgoaul(state, rho, outerits);
-    minnlcsetalgoslp(state);
-    minnlcsetalgosqp(state);
-
-    //
-    // Set constraints:
-    //
-    // 1. boundary constraints are passed with minnlcsetbc() call
-    //
-    // 2. nonlinear constraints are more tricky - you can not "pack" general
-    //    nonlinear function into double precision array. That's why
-    //    minnlcsetnlc() does not accept constraints itself - only constraint
-    //    counts are passed: first parameter is number of equality constraints,
-    //    second one is number of inequality constraints.
-    //
-    //    As for constraining functions - these functions are passed as part
-    //    of problem Jacobian (see below).
-    //
-    // NOTE: MinNLC optimizer supports arbitrary combination of boundary, general
-    //       linear and general nonlinear constraints. This example does not
-    //       show how to work with general linear constraints, but you can
-    //       easily find it in documentation on minnlcsetlc() function.
-    //
-    minnlcsetbc(state, bndl, bndu);
-    minnlcsetnlc(state, 0, 1);
-
-    //
-    // Activate OptGuard integrity checking.
-    //
-    // OptGuard monitor helps to catch common coding and problem statement
-    // issues, like:
-    // * discontinuity of the target/constraints (C0 continuity violation)
-    // * nonsmoothness of the target/constraints (C1 continuity violation)
-    // * erroneous analytic Jacobian, i.e. one inconsistent with actual
-    //   change in the target/constraints
-    //
-    // OptGuard is essential for early prototyping stages because such
-    // problems often result in premature termination of the optimizer
-    // which is really hard to distinguish from the correct termination.
-    //
-    // IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL
-    //            DIFFERENTIATION, THUS DO NOT USE IT IN PRODUCTION CODE!
-    //
-    //            Other OptGuard checks add moderate overhead, but anyway
-    //            it is better to turn them off when they are not needed.
-    //
-    minnlcoptguardsmoothness(state);
-    minnlcoptguardgradient(state, 0.001);
-
-    //
-    // Optimize and test results.
-    //
-    // Optimizer object accepts vector function and its Jacobian, with first
-    // component (Jacobian row) being target function, and next components
-    // (Jacobian rows) being nonlinear equality and inequality constraints.
-    //
-    // So, our vector function has form
-    //
-    //     {f0,f1} = { -x0+x1 , x0^2+x1^2-1 }
-    //
-    // with Jacobian
-    //
-    //         [  -1    +1  ]
-    //     J = [            ]
-    //         [ 2*x0  2*x1 ]
-    //
-    // with f0 being target function, f1 being constraining function. Number
-    // of equality/inequality constraints is specified by minnlcsetnlc(),
-    // with equality ones always being first, inequality ones being last.
-    //
-    minnlcreport rep;
-    real_1d_array x1;
-    alglib::minnlcoptimize(state, nlcfunc1_jac);
-    minnlcresults(state, x1, rep);
-    printf("%s\n", x1.tostring(2).c_str()); // EXPECTED: [1.0000,0.0000]
-
-    //
-    // Check that OptGuard did not report errors
-    //
-    // NOTE: want to test OptGuard? Try breaking the Jacobian - say, add
-    //       1.0 to some of its components.
-    //
-    optguardreport ogrep;
-    minnlcoptguardresults(state, ogrep);
-    printf("%s\n", ogrep.badgradsuspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc0suspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc1suspected ? "true" : "false"); // EXPECTED: false
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void  nlcfunc2_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr)
-{
-    //
-    // this callback calculates
-    //
-    //     f0(x0,x1,x2) = x0+x1
-    //     f1(x0,x1,x2) = x2-exp(x0)
-    //     f2(x0,x1,x2) = x0^2+x1^2-1
-    //
-    // and Jacobian matrix J = [dfi/dxj]
-    //
-    fi[0] = x[0]+x[1];
-    fi[1] = x[2]-exp(x[0]);
-    fi[2] = x[0]*x[0] + x[1]*x[1] - 1.0;
-    jac[0][0] = 1.0;
-    jac[0][1] = 1.0;
-    jac[0][2] = 0.0;
-    jac[1][0] = -exp(x[0]);
-    jac[1][1] = 0.0;
-    jac[1][2] = 1.0;
-    jac[2][0] = 2*x[0];
-    jac[2][1] = 2*x[1];
-    jac[2][2] = 0.0;
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of
-    //
-    //     f(x0,x1) = x0+x1
-    //
-    // subject to nonlinear inequality constraint
-    //
-    //    x0^2 + x1^2 - 1 <= 0
-    //
-    // and nonlinear equality constraint
-    //
-    //    x2-exp(x0) = 0
-    //
-    real_1d_array x0 = "[0,0,0]";
-    real_1d_array s = "[1,1,1]";
-    double epsx = 0.000001;
-    ae_int_t maxits = 0;
-    minnlcstate state;
-    minnlcreport rep;
-    real_1d_array x1;
-
-    //
-    // Create optimizer object and tune its settings:
-    // * epsx=0.000001  stopping condition for inner iterations
-    // * s=[1,1]        all variables have unit scale
-    // * upper limit on step length is specified (to avoid probing locations where exp() is large)
-    //
-    minnlccreate(3, x0, state);
-    minnlcsetcond(state, epsx, maxits);
-    minnlcsetscale(state, s);
-    minnlcsetstpmax(state, 10.0);
-
-    //
-    // Choose one of the nonlinear programming solvers supported by minnlc
-    // optimizer:
-    // * SLP - successive linear programming NLP solver
-    // * AUL - augmented Lagrangian NLP solver
-    //
-    // Different solvers have different properties:
-    // * SLP is the most robust solver provided by ALGLIB: it can solve both
-    //   convex and nonconvex optimization problems, it respects box and
-    //   linear constraints (after you find feasible point it won't move away
-    //   from the feasible area) and tries to respect nonlinear constraints
-    //   as much as possible. It also usually needs less function evaluations
-    //   to converge than AUL.
-    //   However, it solves LP subproblems at each iterations which adds
-    //   significant overhead to its running time. Sometimes it can be as much
-    //   as 7x times slower than AUL.
-    // * AUL solver is less robust than SLP - it can violate box and linear
-    //   constraints at any moment, and it is intended for convex optimization
-    //   problems (although in many cases it can deal with nonconvex ones too).
-    //   Also, unlike SLP it needs some tuning (penalty factor and number of
-    //   outer iterations).
-    //   However, it is often much faster than the current version of SLP.
-    //
-    // In the code below we set solver to be AUL but then override it with SLP,
-    // so the effective choice is to use SLP. We recommend you to use SLP at
-    // least for early prototyping stages.
-    //
-    // You can comment out line with SLP if you want to solve your problem with
-    // AUL solver.
-    //
-    double rho = 1000.0;
-    ae_int_t outerits = 5;
-    minnlcsetalgoaul(state, rho, outerits);
-    minnlcsetalgoslp(state);
-
-    //
-    // Set constraints:
-    //
-    // Nonlinear constraints are tricky - you can not "pack" general
-    // nonlinear function into double precision array. That's why
-    // minnlcsetnlc() does not accept constraints itself - only constraint
-    // counts are passed: first parameter is number of equality constraints,
-    // second one is number of inequality constraints.
-    //
-    // As for constraining functions - these functions are passed as part
-    // of problem Jacobian (see below).
-    //
-    // NOTE: MinNLC optimizer supports arbitrary combination of boundary, general
-    //       linear and general nonlinear constraints. This example does not
-    //       show how to work with boundary or general linear constraints, but you
-    //       can easily find it in documentation on minnlcsetbc() and
-    //       minnlcsetlc() functions.
-    //
-    minnlcsetnlc(state, 1, 1);
-
-    //
-    // Activate OptGuard integrity checking.
-    //
-    // OptGuard monitor helps to catch common coding and problem statement
-    // issues, like:
-    // * discontinuity of the target/constraints (C0 continuity violation)
-    // * nonsmoothness of the target/constraints (C1 continuity violation)
-    // * erroneous analytic Jacobian, i.e. one inconsistent with actual
-    //   change in the target/constraints
-    //
-    // OptGuard is essential for early prototyping stages because such
-    // problems often result in premature termination of the optimizer
-    // which is really hard to distinguish from the correct termination.
-    //
-    // IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL
-    //            DIFFERENTIATION, THUS DO NOT USE IT IN PRODUCTION CODE!
-    //
-    //            Other OptGuard checks add moderate overhead, but anyway
-    //            it is better to turn them off when they are not needed.
-    //
-    minnlcoptguardsmoothness(state);
-    minnlcoptguardgradient(state, 0.001);
-
-    //
-    // Optimize and test results.
-    //
-    // Optimizer object accepts vector function and its Jacobian, with first
-    // component (Jacobian row) being target function, and next components
-    // (Jacobian rows) being nonlinear equality and inequality constraints.
-    //
-    // So, our vector function has form
-    //
-    //     {f0,f1,f2} = { x0+x1 , x2-exp(x0) , x0^2+x1^2-1 }
-    //
-    // with Jacobian
-    //
-    //         [  +1      +1       0 ]
-    //     J = [-exp(x0)  0        1 ]
-    //         [ 2*x0    2*x1      0 ]
-    //
-    // with f0 being target function, f1 being equality constraint "f1=0",
-    // f2 being inequality constraint "f2<=0". Number of equality/inequality
-    // constraints is specified by minnlcsetnlc(), with equality ones always
-    // being first, inequality ones being last.
-    //
-    alglib::minnlcoptimize(state, nlcfunc2_jac);
-    minnlcresults(state, x1, rep);
-    printf("%s\n", x1.tostring(2).c_str()); // EXPECTED: [-0.70710,-0.70710,0.49306]
-
-    //
-    // Check that OptGuard did not report errors
-    //
-    // NOTE: want to test OptGuard? Try breaking the Jacobian - say, add
-    //       1.0 to some of its components.
-    //
-    optguardreport ogrep;
-    minnlcoptguardresults(state, ogrep);
-    printf("%s\n", ogrep.badgradsuspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc0suspected ? "true" : "false"); // EXPECTED: false
-    printf("%s\n", ogrep.nonc1suspected ? "true" : "false"); // EXPECTED: false
-    return 0;
-}
-
-
-
-
- -minnsreport
-minnsstate
- -minnscreate
-minnscreatef
-minnsoptimize
-minnsrequesttermination
-minnsrestartfrom
-minnsresults
-minnsresultsbuf
-minnssetalgoags
-minnssetbc
-minnssetcond
-minnssetlc
-minnssetnlc
-minnssetscale
-minnssetxrep
- - - - - - -
minns_d_bc Nonsmooth box constrained optimization
minns_d_diff Nonsmooth unconstrained optimization with numerical differentiation
minns_d_nlc Nonsmooth nonlinearly constrained optimization
minns_d_unconstrained Nonsmooth unconstrained optimization
- -
-
/************************************************************************* -This structure stores optimization report: -* IterationsCount total number of inner iterations -* NFEV number of gradient evaluations -* TerminationType termination type (see below) -* CErr maximum violation of all types of constraints -* LCErr maximum violation of linear constraints -* NLCErr maximum violation of nonlinear constraints - -TERMINATION CODES - -TerminationType field contains completion code, which can be: - -8 internal integrity control detected infinite or NAN values in - function/gradient. Abnormal termination signalled. - -3 box constraints are inconsistent - -1 inconsistent parameters were passed: - * penalty parameter for minnssetalgoags() is zero, - but we have nonlinear constraints set by minnssetnlc() - 2 sampling radius decreased below epsx - 5 MaxIts steps was taken - 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - 8 User requested termination via MinNSRequestTermination() - -Other fields of this structure are not documented and should not be used! -*************************************************************************/ -
class minnsreport -{ - ae_int_t iterationscount; - ae_int_t nfev; - double cerr; - double lcerr; - double nlcerr; - ae_int_t terminationtype; - ae_int_t varidx; - ae_int_t funcidx; -}; - -
- -
-
/************************************************************************* -This object stores nonlinear optimizer state. -You should use functions provided by MinNS subpackage to work with this -object -*************************************************************************/ -
class minnsstate -{ -}; - -
- -
-
/************************************************************************* - NONSMOOTH NONCONVEX OPTIMIZATION - SUBJECT TO BOX/LINEAR/NONLINEAR-NONSMOOTH CONSTRAINTS - -DESCRIPTION: - -The subroutine minimizes function F(x) of N arguments subject to any -combination of: -* bound constraints -* linear inequality constraints -* linear equality constraints -* nonlinear equality constraints Gi(x)=0 -* nonlinear inequality constraints Hi(x)<=0 - -IMPORTANT: see MinNSSetAlgoAGS for important information on performance - restrictions of AGS solver. - -REQUIREMENTS: -* starting point X0 must be feasible or not too far away from the feasible - set -* F(), G(), H() are continuous, locally Lipschitz and continuously (but - not necessarily twice) differentiable in an open dense subset of R^N. - Functions F(), G() and H() may be nonsmooth and non-convex. - Informally speaking, it means that functions are composed of large - differentiable "patches" with nonsmoothness having place only at the - boundaries between these "patches". - Most real-life nonsmooth functions satisfy these requirements. Say, - anything which involves finite number of abs(), min() and max() is very - likely to pass the test. - Say, it is possible to optimize anything of the following: - * f=abs(x0)+2*abs(x1) - * f=max(x0,x1) - * f=sin(max(x0,x1)+abs(x2)) -* for nonlinearly constrained problems: F() must be bounded from below - without nonlinear constraints (this requirement is due to the fact that, - contrary to box and linear constraints, nonlinear ones require special - handling). -* user must provide function value and gradient for F(), H(), G() at all - points where function/gradient can be calculated. If optimizer requires - value exactly at the boundary between "patches" (say, at x=0 for f=abs(x)), - where gradient is not defined, user may resolve tie arbitrarily (in our - case - return +1 or -1 at its discretion). -* NS solver supports numerical differentiation, i.e. it may differentiate - your function for you, but it results in 2N increase of function - evaluations. Not recommended unless you solve really small problems. See - minnscreatef() for more information on this functionality. - -USAGE: - -1. User initializes algorithm state with MinNSCreate() call and chooses - what NLC solver to use. There is some solver which is used by default, - with default settings, but you should NOT rely on default choice. It - may change in future releases of ALGLIB without notice, and no one can - guarantee that new solver will be able to solve your problem with - default settings. - - From the other side, if you choose solver explicitly, you can be pretty - sure that it will work with new ALGLIB releases. - - In the current release following solvers can be used: - * AGS solver (activated with MinNSSetAlgoAGS() function) - -2. User adds boundary and/or linear and/or nonlinear constraints by means - of calling one of the following functions: - a) MinNSSetBC() for boundary constraints - b) MinNSSetLC() for linear constraints - c) MinNSSetNLC() for nonlinear constraints - You may combine (a), (b) and (c) in one optimization problem. - -3. User sets scale of the variables with MinNSSetScale() function. It is - VERY important to set scale of the variables, because nonlinearly - constrained problems are hard to solve when variables are badly scaled. - -4. User sets stopping conditions with MinNSSetCond(). - -5. Finally, user calls MinNSOptimize() function which takes algorithm - state and pointer (delegate, etc) to callback function which calculates - F/G/H. - -7. User calls MinNSResults() to get solution - -8. Optionally user may call MinNSRestartFrom() to solve another problem - with same N but another starting point. MinNSRestartFrom() allows to - reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - -NOTE: minnscreatef() function may be used if you do not have analytic - gradient. This function creates solver which uses numerical - differentiation with user-specified step. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnscreate( - real_1d_array x, - minnsstate& state, - const xparams _params = alglib::xdefault); -void alglib::minnscreate( - ae_int_t n, - real_1d_array x, - minnsstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -Version of minnscreatef() which uses numerical differentiation. I.e., you -do not have to calculate derivatives yourself. However, this version needs -2N times more function evaluations. - -2-point differentiation formula is used, because more precise 4-point -formula is unstable when used on non-smooth functions. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - DiffStep- differentiation step, DiffStep>0. Algorithm performs - numerical differentiation with step for I-th variable - being equal to DiffStep*S[I] (here S[] is a scale vector, - set by minnssetscale() function). - Do not use too small steps, because it may lead to - catastrophic cancellation during intermediate calculations. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnscreatef( - real_1d_array x, - double diffstep, - minnsstate& state, - const xparams _params = alglib::xdefault); -void alglib::minnscreatef( - ae_int_t n, - real_1d_array x, - double diffstep, - minnsstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This family of functions is used to launcn iterations of nonlinear optimizer - -These functions accept following parameters: - state - algorithm state - fvec - callback which calculates function vector fi[] - at given point x - jac - callback which calculates function vector fi[] - and Jacobian jac at given point x - rep - optional callback which is called after each iteration - can be NULL - ptr - optional pointer which is passed to func/grad/hess/jac/rep - can be NULL - - -NOTES: - -1. This function has two different implementations: one which uses exact - (analytical) user-supplied Jacobian, and one which uses only function - vector and numerically differentiates function in order to obtain - gradient. - - Depending on the specific function used to create optimizer object - you should choose appropriate variant of minnsoptimize() - one which - accepts function AND Jacobian or one which accepts ONLY function. - - Be careful to choose variant of minnsoptimize() which corresponds to - your optimization scheme! Table below lists different combinations of - callback (function/gradient) passed to minnsoptimize() and specific - function used to create optimizer. - - - | USER PASSED TO minnsoptimize() - CREATED WITH | function only | function and gradient - ------------------------------------------------------------ - minnscreatef() | works FAILS - minnscreate() | FAILS works - - Here "FAILS" denotes inappropriate combinations of optimizer creation - function and minnsoptimize() version. Attemps to use such - combination will lead to exception. Either you did not pass gradient - when it WAS needed or you passed gradient when it was NOT needed. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -
void minnsoptimize(minnsstate &state, - void (*fvec)(const real_1d_array &x, real_1d_array &fi, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void minnsoptimize(minnsstate &state, - void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -
-

Examples:   [1]  [2]  [3]  [4]  

- -
-
/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnsrequesttermination( - minnsstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine restarts algorithm from new point. -All optimization parameters (including constraints) are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure previously allocated with minnscreate() call. - X - new starting point. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnsrestartfrom( - minnsstate state, - real_1d_array x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -MinNS results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report. You should check Rep.TerminationType - in order to distinguish successful termination from - unsuccessful one: - * -8 internal integrity control detected infinite or - NAN values in function/gradient. Abnormal - termination signalled. - * -3 box constraints are inconsistent - * -1 inconsistent parameters were passed: - * penalty parameter for minnssetalgoags() is zero, - but we have nonlinear constraints set by minnssetnlc() - * 2 sampling radius decreased below epsx - * 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - * 8 User requested termination via minnsrequesttermination() - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnsresults( - minnsstate state, - real_1d_array& x, - minnsreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  

- -
-
/************************************************************************* - -Buffered implementation of minnsresults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnsresultsbuf( - minnsstate state, - real_1d_array& x, - minnsreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function tells MinNS unit to use AGS (adaptive gradient sampling) -algorithm for nonsmooth constrained optimization. This algorithm is a -slight modification of one described in "An Adaptive Gradient Sampling -Algorithm for Nonsmooth Optimization" by Frank E. Curtisy and Xiaocun Quez. - -This optimizer has following benefits and drawbacks: -+ robustness; it can be used with nonsmooth and nonconvex functions. -+ relatively easy tuning; most of the metaparameters are easy to select. -- it has convergence of steepest descent, slower than CG/LBFGS. -- each iteration involves evaluation of ~2N gradient values and solution - of 2Nx2N quadratic programming problem, which limits applicability of - algorithm by small-scale problems (up to 50-100). - -IMPORTANT: this algorithm has convergence guarantees, i.e. it will - steadily move towards some stationary point of the function. - - However, "stationary point" does not always mean "solution". - Nonsmooth problems often have "flat spots", i.e. areas where - function do not change at all. Such "flat spots" are stationary - points by definition, and algorithm may be caught here. - - Nonsmooth CONVEX tasks are not prone to this problem. Say, if - your function has form f()=MAX(f0,f1,...), and f_i are convex, - then f() is convex too and you have guaranteed convergence to - solution. - -INPUT PARAMETERS: - State - structure which stores algorithm state - Radius - initial sampling radius, >=0. - - Internally multiplied by vector of per-variable scales - specified by minnssetscale()). - - You should select relatively large sampling radius, roughly - proportional to scaled length of the first steps of the - algorithm. Something close to 0.1 in magnitude should be - good for most problems. - - AGS solver can automatically decrease radius, so too large - radius is not a problem (assuming that you won't choose - so large radius that algorithm will sample function in - too far away points, where gradient value is irrelevant). - - Too small radius won't cause algorithm to fail, but it may - slow down algorithm (it may have to perform too short - steps). - Penalty - penalty coefficient for nonlinear constraints: - * for problem with nonlinear constraints should be some - problem-specific positive value, large enough that - penalty term changes shape of the function. - Starting from some problem-specific value penalty - coefficient becomes large enough to exactly enforce - nonlinear constraints; larger values do not improve - precision. - Increasing it too much may slow down convergence, so you - should choose it carefully. - * can be zero for problems WITHOUT nonlinear constraints - (i.e. for unconstrained ones or ones with just box or - linear constraints) - * if you specify zero value for problem with at least one - nonlinear constraint, algorithm will terminate with - error code -1. - -ALGORITHM OUTLINE - -The very basic outline of unconstrained AGS algorithm is given below: - -0. If sampling radius is below EpsX or we performed more then MaxIts - iterations - STOP. -1. sample O(N) gradient values at random locations around current point; - informally speaking, this sample is an implicit piecewise linear model - of the function, although algorithm formulation does not mention that - explicitly -2. solve quadratic programming problem in order to find descent direction -3. if QP solver tells us that we are near solution, decrease sampling - radius and move to (0) -4. perform backtracking line search -5. after moving to new point, goto (0) - -As for the constraints: -* box constraints are handled exactly by modification of the function - being minimized -* linear/nonlinear constraints are handled by adding L1 penalty. Because - our solver can handle nonsmoothness, we can use L1 penalty function, - which is an exact one (i.e. exact solution is returned under such - penalty). -* penalty coefficient for linear constraints is chosen automatically; - however, penalty coefficient for nonlinear constraints must be specified - by user. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnssetalgoags( - minnsstate state, - double radius, - double penalty, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  

- -
-
/************************************************************************* -This function sets boundary constraints. - -Boundary constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with minnsrestartfrom(). - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF. - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF. - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - -NOTE 2: AGS solver has following useful properties: -* bound constraints are always satisfied exactly -* function is evaluated only INSIDE area specified by bound constraints, - even when numerical differentiation is used (algorithm adjusts nodes - according to boundary constraints) - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnssetbc( - minnsstate state, - real_1d_array bndl, - real_1d_array bndu, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function sets stopping conditions for iterations of optimizer. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsX - >=0 - The AGS solver finishes its work if on k+1-th iteration - sampling radius decreases below EpsX. - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic -stopping criterion selection. We do not recommend you to rely on default -choice in production code. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnssetcond( - minnsstate state, - double epsx, - ae_int_t maxits, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  

- -
-
/************************************************************************* -This function sets linear constraints. - -Linear constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with minnsrestartfrom(). - -INPUT PARAMETERS: - State - structure previously allocated with minnscreate() call. - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -NOTE: linear (non-bound) constraints are satisfied only approximately: - -* there always exists some minor violation (about current sampling radius - in magnitude during optimization, about EpsX in the solution) due to use - of penalty method to handle constraints. -* numerical differentiation, if used, may lead to function evaluations - outside of the feasible area, because algorithm does NOT change - numerical differentiation formula according to linear constraints. - -If you want constraints to be satisfied exactly, try to reformulate your -problem in such manner that all constraints will become boundary ones -(this kind of constraints is always satisfied exactly, both in the final -solution and in all intermediate points). - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnssetlc( - minnsstate state, - real_2d_array c, - integer_1d_array ct, - const xparams _params = alglib::xdefault); -void alglib::minnssetlc( - minnsstate state, - real_2d_array c, - integer_1d_array ct, - ae_int_t k, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets nonlinear constraints. - -In fact, this function sets NUMBER of nonlinear constraints. Constraints -itself (constraint functions) are passed to minnsoptimize() method. This -method requires user-defined vector function F[] and its Jacobian J[], -where: -* first component of F[] and first row of Jacobian J[] correspond to - function being minimized -* next NLEC components of F[] (and rows of J) correspond to nonlinear - equality constraints G_i(x)=0 -* next NLIC components of F[] (and rows of J) correspond to nonlinear - inequality constraints H_i(x)<=0 - -NOTE: you may combine nonlinear constraints with linear/boundary ones. If - your problem has mixed constraints, you may explicitly specify some - of them as linear ones. It may help optimizer to handle them more - efficiently. - -INPUT PARAMETERS: - State - structure previously allocated with minnscreate() call. - NLEC - number of Non-Linear Equality Constraints (NLEC), >=0 - NLIC - number of Non-Linear Inquality Constraints (NLIC), >=0 - -NOTE 1: nonlinear constraints are satisfied only approximately! It is - possible that algorithm will evaluate function outside of - the feasible area! - -NOTE 2: algorithm scales variables according to scale specified by - minnssetscale() function, so it can handle problems with badly - scaled variables (as long as we KNOW their scales). - - However, there is no way to automatically scale nonlinear - constraints Gi(x) and Hi(x). Inappropriate scaling of Gi/Hi may - ruin convergence. Solving problem with constraint "1000*G0(x)=0" - is NOT same as solving it with constraint "0.001*G0(x)=0". - - It means that YOU are the one who is responsible for correct - scaling of nonlinear constraints Gi(x) and Hi(x). We recommend you - to scale nonlinear constraints in such way that I-th component of - dG/dX (or dH/dx) has approximately unit magnitude (for problems - with unit scale) or has magnitude approximately equal to 1/S[i] - (where S is a scale set by minnssetscale() function). - -NOTE 3: nonlinear constraints are always hard to handle, no matter what - algorithm you try to use. Even basic box/linear constraints modify - function curvature by adding valleys and ridges. However, - nonlinear constraints add valleys which are very hard to follow - due to their "curved" nature. - - It means that optimization with single nonlinear constraint may be - significantly slower than optimization with multiple linear ones. - It is normal situation, and we recommend you to carefully choose - Rho parameter of minnssetalgoags(), because too large value may - slow down convergence. - - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnssetnlc( - minnsstate state, - ae_int_t nlec, - ae_int_t nlic, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function sets scaling coefficients for NLC optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of the optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnssetscale( - minnsstate state, - real_1d_array s, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  

- -
-
/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to minnsoptimize(). - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minnssetxrep( - minnsstate state, - bool needxrep, - const xparams _params = alglib::xdefault); - -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void  nsfunc1_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr)
-{
-    //
-    // this callback calculates
-    //
-    //     f0(x0,x1) = 2*|x0|+x1
-    //
-    // and Jacobian matrix J = [df0/dx0 df0/dx1]
-    //
-    fi[0] = 2*fabs(double(x[0]))+fabs(double(x[1]));
-    jac[0][0] = 2*alglib::sign(x[0]);
-    jac[0][1] = alglib::sign(x[1]);
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of
-    //
-    //     f(x0,x1) = 2*|x0|+|x1|
-    //
-    // subject to box constraints
-    //
-    //        1 <= x0 < +INF
-    //     -INF <= x1 < +INF
-    //
-    // using nonsmooth nonlinear optimizer.
-    //
-    real_1d_array x0 = "[1,1]";
-    real_1d_array s = "[1,1]";
-    real_1d_array bndl = "[1,-inf]";
-    real_1d_array bndu = "[+inf,+inf]";
-    double epsx = 0.00001;
-    double radius = 0.1;
-    double rho = 0.0;
-    ae_int_t maxits = 0;
-    minnsstate state;
-    minnsreport rep;
-    real_1d_array x1;
-
-    //
-    // Create optimizer object, choose AGS algorithm and tune its settings:
-    // * radius=0.1     good initial value; will be automatically decreased later.
-    // * rho=0.0        penalty coefficient for nonlinear constraints; can be zero
-    //                  because we do not have such constraints
-    // * epsx=0.000001  stopping conditions
-    // * s=[1,1]        all variables have unit scale
-    //
-    minnscreate(2, x0, state);
-    minnssetalgoags(state, radius, rho);
-    minnssetcond(state, epsx, maxits);
-    minnssetscale(state, s);
-
-    //
-    // Set box constraints.
-    //
-    // General linear constraints are set in similar way (see comments on
-    // minnssetlc() function for more information).
-    //
-    // You may combine box, linear and nonlinear constraints in one optimization
-    // problem.
-    //
-    minnssetbc(state, bndl, bndu);
-
-    //
-    // Optimize and test results.
-    //
-    // Optimizer object accepts vector function and its Jacobian, with first
-    // component (Jacobian row) being target function, and next components
-    // (Jacobian rows) being nonlinear equality and inequality constraints
-    // (box/linear ones are passed separately by means of minnssetbc() and
-    // minnssetlc() calls).
-    //
-    // If you do not have nonlinear constraints (exactly our situation), then
-    // you will have one-component function vector and 1xN Jacobian matrix.
-    //
-    // So, our vector function has form
-    //
-    //     {f0} = { 2*|x0|+|x1| }
-    //
-    // with Jacobian
-    //
-    //         [                       ]
-    //     J = [ 2*sign(x0)   sign(x1) ]
-    //         [                       ]
-    //
-    // NOTE: nonsmooth optimizer requires considerably more function
-    //       evaluations than smooth solver - about 2N times more. Using
-    //       numerical differentiation introduces additional (multiplicative)
-    //       2N speedup.
-    //
-    //       It means that if smooth optimizer WITH user-supplied gradient
-    //       needs 100 function evaluations to solve 50-dimensional problem,
-    //       then AGS solver with user-supplied gradient will need about 10.000
-    //       function evaluations, and with numerical gradient about 1.000.000
-    //       function evaluations will be performed.
-    //
-    // NOTE: AGS solver used by us can handle nonsmooth and nonconvex
-    //       optimization problems. It has convergence guarantees, i.e. it will
-    //       converge to stationary point of the function after running for some
-    //       time.
-    //
-    //       However, it is important to remember that "stationary point" is not
-    //       equal to "solution". If your problem is convex, everything is OK.
-    //       But nonconvex optimization problems may have "flat spots" - large
-    //       areas where gradient is exactly zero, but function value is far away
-    //       from optimal. Such areas are stationary points too, and optimizer
-    //       may be trapped here.
-    //
-    //       "Flat spots" are nonsmooth equivalent of the saddle points, but with
-    //       orders of magnitude worse properties - they may be quite large and
-    //       hard to avoid. All nonsmooth optimizers are prone to this kind of the
-    //       problem, because it is impossible to automatically distinguish "flat
-    //       spot" from true solution.
-    //
-    //       This note is here to warn you that you should be very careful when
-    //       you solve nonsmooth optimization problems. Visual inspection of
-    //       results is essential.
-    //
-    //
-    alglib::minnsoptimize(state, nsfunc1_jac);
-    minnsresults(state, x1, rep);
-    printf("%s\n", x1.tostring(2).c_str()); // EXPECTED: [1.0000,0.0000]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void  nsfunc1_fvec(const real_1d_array &x, real_1d_array &fi, void *ptr)
-{
-    //
-    // this callback calculates
-    //
-    //     f0(x0,x1) = 2*|x0|+x1
-    //
-    fi[0] = 2*fabs(double(x[0]))+fabs(double(x[1]));
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of
-    //
-    //     f(x0,x1) = 2*|x0|+|x1|
-    //
-    // using nonsmooth nonlinear optimizer with numerical
-    // differentiation provided by ALGLIB.
-    //
-    // NOTE: nonsmooth optimizer requires considerably more function
-    //       evaluations than smooth solver - about 2N times more. Using
-    //       numerical differentiation introduces additional (multiplicative)
-    //       2N speedup.
-    //
-    //       It means that if smooth optimizer WITH user-supplied gradient
-    //       needs 100 function evaluations to solve 50-dimensional problem,
-    //       then AGS solver with user-supplied gradient will need about 10.000
-    //       function evaluations, and with numerical gradient about 1.000.000
-    //       function evaluations will be performed.
-    //
-    real_1d_array x0 = "[1,1]";
-    real_1d_array s = "[1,1]";
-    double epsx = 0.00001;
-    double diffstep = 0.000001;
-    double radius = 0.1;
-    double rho = 0.0;
-    ae_int_t maxits = 0;
-    minnsstate state;
-    minnsreport rep;
-    real_1d_array x1;
-
-    //
-    // Create optimizer object, choose AGS algorithm and tune its settings:
-    // * radius=0.1     good initial value; will be automatically decreased later.
-    // * rho=0.0        penalty coefficient for nonlinear constraints; can be zero
-    //                  because we do not have such constraints
-    // * epsx=0.000001  stopping conditions
-    // * s=[1,1]        all variables have unit scale
-    //
-    minnscreatef(2, x0, diffstep, state);
-    minnssetalgoags(state, radius, rho);
-    minnssetcond(state, epsx, maxits);
-    minnssetscale(state, s);
-
-    //
-    // Optimize and test results.
-    //
-    // Optimizer object accepts vector function, with first component
-    // being target function, and next components being nonlinear equality
-    // and inequality constraints (box/linear ones are passed separately
-    // by means of minnssetbc() and minnssetlc() calls).
-    //
-    // If you do not have nonlinear constraints (exactly our situation), then
-    // you will have one-component function vector.
-    //
-    // So, our vector function has form
-    //
-    //     {f0} = { 2*|x0|+|x1| }
-    //
-    alglib::minnsoptimize(state, nsfunc1_fvec);
-    minnsresults(state, x1, rep);
-    printf("%s\n", x1.tostring(2).c_str()); // EXPECTED: [0.0000,0.0000]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void  nsfunc2_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr)
-{
-    //
-    // this callback calculates function vector
-    //
-    //     f0(x0,x1) = 2*|x0|+x1
-    //     f1(x0,x1) = x0-1
-    //     f2(x0,x1) = -x1-1
-    //
-    // and Jacobian matrix J
-    //
-    //         [ df0/dx0   df0/dx1 ]
-    //     J = [ df1/dx0   df1/dx1 ]
-    //         [ df2/dx0   df2/dx1 ]
-    //
-    fi[0] = 2*fabs(double(x[0]))+fabs(double(x[1]));
-    jac[0][0] = 2*alglib::sign(x[0]);
-    jac[0][1] = alglib::sign(x[1]);
-    fi[1] = x[0]-1;
-    jac[1][0] = 1;
-    jac[1][1] = 0;
-    fi[2] = -x[1]-1;
-    jac[2][0] = 0;
-    jac[2][1] = -1;
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of
-    //
-    //     f(x0,x1) = 2*|x0|+|x1|
-    //
-    // subject to combination of equality and inequality constraints
-    //
-    //      x0  =  1
-    //      x1 >= -1
-    //
-    // using nonsmooth nonlinear optimizer. Although these constraints
-    // are linear, we treat them as general nonlinear ones in order to
-    // demonstrate nonlinearly constrained optimization setup.
-    //
-    real_1d_array x0 = "[1,1]";
-    real_1d_array s = "[1,1]";
-    double epsx = 0.00001;
-    double radius = 0.1;
-    double rho = 50.0;
-    ae_int_t maxits = 0;
-    minnsstate state;
-    minnsreport rep;
-    real_1d_array x1;
-
-    //
-    // Create optimizer object, choose AGS algorithm and tune its settings:
-    // * radius=0.1     good initial value; will be automatically decreased later.
-    // * rho=50.0       penalty coefficient for nonlinear constraints. It is your
-    //                  responsibility to choose good one - large enough that it
-    //                  enforces constraints, but small enough in order to avoid
-    //                  extreme slowdown due to ill-conditioning.
-    // * epsx=0.000001  stopping conditions
-    // * s=[1,1]        all variables have unit scale
-    //
-    minnscreate(2, x0, state);
-    minnssetalgoags(state, radius, rho);
-    minnssetcond(state, epsx, maxits);
-    minnssetscale(state, s);
-
-    //
-    // Set general nonlinear constraints.
-    //
-    // This part is more tricky than working with box/linear constraints - you
-    // can not "pack" general nonlinear function into double precision array.
-    // That's why minnssetnlc() does not accept constraints itself - only
-    // constraint COUNTS are passed: first parameter is number of equality
-    // constraints, second one is number of inequality constraints.
-    //
-    // As for constraining functions - these functions are passed as part
-    // of problem Jacobian (see below).
-    //
-    // NOTE: MinNS optimizer supports arbitrary combination of boundary, general
-    //       linear and general nonlinear constraints. This example does not
-    //       show how to work with general linear constraints, but you can
-    //       easily find it in documentation on minnlcsetlc() function.
-    //
-    minnssetnlc(state, 1, 1);
-
-    //
-    // Optimize and test results.
-    //
-    // Optimizer object accepts vector function and its Jacobian, with first
-    // component (Jacobian row) being target function, and next components
-    // (Jacobian rows) being nonlinear equality and inequality constraints
-    // (box/linear ones are passed separately by means of minnssetbc() and
-    // minnssetlc() calls).
-    //
-    // Nonlinear equality constraints have form Gi(x)=0, inequality ones
-    // have form Hi(x)<=0, so we may have to "normalize" constraints prior
-    // to passing them to optimizer (right side is zero, constraints are
-    // sorted, multiplied by -1 when needed).
-    //
-    // So, our vector function has form
-    //
-    //     {f0,f1,f2} = { 2*|x0|+|x1|,  x0-1, -x1-1 }
-    //
-    // with Jacobian
-    //
-    //         [ 2*sign(x0)   sign(x1) ]
-    //     J = [     1           0     ]
-    //         [     0          -1     ]
-    //
-    // which means that we have optimization problem
-    //
-    //     min{f0} subject to f1=0, f2<=0
-    //
-    // which is essentially same as
-    //
-    //     min { 2*|x0|+|x1| } subject to x0=1, x1>=-1
-    //
-    // NOTE: AGS solver used by us can handle nonsmooth and nonconvex
-    //       optimization problems. It has convergence guarantees, i.e. it will
-    //       converge to stationary point of the function after running for some
-    //       time.
-    //
-    //       However, it is important to remember that "stationary point" is not
-    //       equal to "solution". If your problem is convex, everything is OK.
-    //       But nonconvex optimization problems may have "flat spots" - large
-    //       areas where gradient is exactly zero, but function value is far away
-    //       from optimal. Such areas are stationary points too, and optimizer
-    //       may be trapped here.
-    //
-    //       "Flat spots" are nonsmooth equivalent of the saddle points, but with
-    //       orders of magnitude worse properties - they may be quite large and
-    //       hard to avoid. All nonsmooth optimizers are prone to this kind of the
-    //       problem, because it is impossible to automatically distinguish "flat
-    //       spot" from true solution.
-    //
-    //       This note is here to warn you that you should be very careful when
-    //       you solve nonsmooth optimization problems. Visual inspection of
-    //       results is essential.
-    //
-    alglib::minnsoptimize(state, nsfunc2_jac);
-    minnsresults(state, x1, rep);
-    printf("%s\n", x1.tostring(2).c_str()); // EXPECTED: [1.0000,0.0000]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-void  nsfunc1_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr)
-{
-    //
-    // this callback calculates
-    //
-    //     f0(x0,x1) = 2*|x0|+x1
-    //
-    // and Jacobian matrix J = [df0/dx0 df0/dx1]
-    //
-    fi[0] = 2*fabs(double(x[0]))+fabs(double(x[1]));
-    jac[0][0] = 2*alglib::sign(x[0]);
-    jac[0][1] = alglib::sign(x[1]);
-}
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of
-    //
-    //     f(x0,x1) = 2*|x0|+|x1|
-    //
-    // using nonsmooth nonlinear optimizer.
-    //
-    real_1d_array x0 = "[1,1]";
-    real_1d_array s = "[1,1]";
-    double epsx = 0.00001;
-    double radius = 0.1;
-    double rho = 0.0;
-    ae_int_t maxits = 0;
-    minnsstate state;
-    minnsreport rep;
-    real_1d_array x1;
-
-    //
-    // Create optimizer object, choose AGS algorithm and tune its settings:
-    // * radius=0.1     good initial value; will be automatically decreased later.
-    // * rho=0.0        penalty coefficient for nonlinear constraints; can be zero
-    //                  because we do not have such constraints
-    // * epsx=0.000001  stopping conditions
-    // * s=[1,1]        all variables have unit scale
-    //
-    minnscreate(2, x0, state);
-    minnssetalgoags(state, radius, rho);
-    minnssetcond(state, epsx, maxits);
-    minnssetscale(state, s);
-
-    //
-    // Optimize and test results.
-    //
-    // Optimizer object accepts vector function and its Jacobian, with first
-    // component (Jacobian row) being target function, and next components
-    // (Jacobian rows) being nonlinear equality and inequality constraints
-    // (box/linear ones are passed separately by means of minnssetbc() and
-    // minnssetlc() calls).
-    //
-    // If you do not have nonlinear constraints (exactly our situation), then
-    // you will have one-component function vector and 1xN Jacobian matrix.
-    //
-    // So, our vector function has form
-    //
-    //     {f0} = { 2*|x0|+|x1| }
-    //
-    // with Jacobian
-    //
-    //         [                       ]
-    //     J = [ 2*sign(x0)   sign(x1) ]
-    //         [                       ]
-    //
-    // NOTE: nonsmooth optimizer requires considerably more function
-    //       evaluations than smooth solver - about 2N times more. Using
-    //       numerical differentiation introduces additional (multiplicative)
-    //       2N speedup.
-    //
-    //       It means that if smooth optimizer WITH user-supplied gradient
-    //       needs 100 function evaluations to solve 50-dimensional problem,
-    //       then AGS solver with user-supplied gradient will need about 10.000
-    //       function evaluations, and with numerical gradient about 1.000.000
-    //       function evaluations will be performed.
-    //
-    // NOTE: AGS solver used by us can handle nonsmooth and nonconvex
-    //       optimization problems. It has convergence guarantees, i.e. it will
-    //       converge to stationary point of the function after running for some
-    //       time.
-    //
-    //       However, it is important to remember that "stationary point" is not
-    //       equal to "solution". If your problem is convex, everything is OK.
-    //       But nonconvex optimization problems may have "flat spots" - large
-    //       areas where gradient is exactly zero, but function value is far away
-    //       from optimal. Such areas are stationary points too, and optimizer
-    //       may be trapped here.
-    //
-    //       "Flat spots" are nonsmooth equivalent of the saddle points, but with
-    //       orders of magnitude worse properties - they may be quite large and
-    //       hard to avoid. All nonsmooth optimizers are prone to this kind of the
-    //       problem, because it is impossible to automatically distinguish "flat
-    //       spot" from true solution.
-    //
-    //       This note is here to warn you that you should be very careful when
-    //       you solve nonsmooth optimization problems. Visual inspection of
-    //       results is essential.
-    //
-    alglib::minnsoptimize(state, nsfunc1_jac);
-    minnsresults(state, x1, rep);
-    printf("%s\n", x1.tostring(2).c_str()); // EXPECTED: [0.0000,0.0000]
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* -This structure stores optimization report: -* InnerIterationsCount number of inner iterations -* OuterIterationsCount number of outer iterations -* NCholesky number of Cholesky decomposition -* NMV number of matrix-vector products - (only products calculated as part of iterative - process are counted) -* TerminationType completion code (see below) -* LagBC Lagrange multipliers for box constraints, - array[N], not filled by QP-BLEIC solver -* LagLC Lagrange multipliers for linear constraints, - array[MSparse+MDense], ignored by QP-BLEIC solver - -=== COMPLETION CODES ===================================================== - -Completion codes: -* -9 failure of the automatic scale evaluation: one of the diagonal - elements of the quadratic term is non-positive. Specify variable - scales manually! -* -5 inappropriate solver was used: - * QuickQP solver for problem with general linear constraints (dense/sparse) -* -4 BLEIC-QP or QuickQP solver found unconstrained direction - of negative curvature (function is unbounded from - below even under constraints), no meaningful - minimum can be found. -* -3 inconsistent constraints (or, maybe, feasible point is - too hard to find). If you are sure that constraints are feasible, - try to restart optimizer with better initial approximation. -* -2 IPM solver has difficulty finding primal/dual feasible point. - It is likely that the problem is either infeasible or unbounded, - but it is difficult to determine exact reason for termination. - X contains best point found so far. -* 1..4 successful completion -* 5 MaxIts steps was taken -* 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - -=== LAGRANGE MULTIPLIERS ================================================= - -Some optimizers report values of Lagrange multipliers on successful -completion (positive completion code): -* DENSE-IPM-QP and SPARSE-IPM-QP return very precise Lagrange multipliers - as determined during solution process. -* DENSE-AUL-QP returns approximate Lagrange multipliers (which are very - close to "true" Lagrange multipliers except for overconstrained or - degenerate problems) - -Two arrays of multipliers are returned: -* LagBC is array[N] which is loaded with multipliers from box constraints; - LagBC[i]>0 means that I-th constraint is at the upper bound, LagBC[I]<0 - means that I-th constraint is at the lower bound, LagBC[I]=0 means that - I-th box constraint is inactive. -* LagLC is array[MSparse+MDense] which is loaded with multipliers from - general linear constraints (former MSparse elements corresponds to - sparse part of the constraint matrix, latter MDense are for the dense - constraints, as was specified by user). - LagLC[i]>0 means that I-th constraint at the upper bound, LagLC[i]<0 - means that I-th constraint is at the lower bound, LagLC[i]=0 means that - I-th linear constraint is inactive. - -On failure (or when optimizer does not support Lagrange multipliers) these -arrays are zero-filled. - -It is expected that at solution the dual feasibility condition holds: - - C+H*(Xs-X0) + SUM(Ei*LagBC[i],i=0..n-1) + SUM(Ai*LagLC[i],i=0..m-1) ~ 0 - -where -* C is a linear term -* H is a quadratic term -* Xs is a solution, and X0 is an origin term (zero by default) -* Ei is a vector with 1.0 at position I and 0 in other positions -* Ai is an I-th row of linear constraint matrix - -NOTE: methods from IPM family may also return meaningful Lagrange - multipliers on completion with code -2 (infeasibility or - unboundedness detected). -*************************************************************************/ -
class minqpreport -{ - ae_int_t inneriterationscount; - ae_int_t outeriterationscount; - ae_int_t nmv; - ae_int_t ncholesky; - ae_int_t terminationtype; - real_1d_array lagbc; - real_1d_array laglc; -}; - -
- -
-
/************************************************************************* -This object stores nonlinear optimizer state. -You should use functions provided by MinQP subpackage to work with this -object -*************************************************************************/ -
class minqpstate -{ -}; - -
- -
-
/************************************************************************* -This function appends two-sided linear constraint AL <= A*x <= AU to the -list of currently present sparse constraints. - -Constraint is passed in compressed format: as list of non-zero entries of -coefficient vector A. Such approach is more efficient than dense storage -for highly sparse constraint vectors. - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - IdxA - array[NNZ], indexes of non-zero elements of A: - * can be unsorted - * can include duplicate indexes (corresponding entries of - ValA[] will be summed) - ValA - array[NNZ], values of non-zero elements of A - NNZ - number of non-zero coefficients in A - AL, AU - lower and upper bounds; - * AL=AU => equality constraint A*x - * AL<AU => two-sided constraint AL<=A*x<=AU - * AL=-INF => one-sided constraint A*x<=AU - * AU=+INF => one-sided constraint AL<=A*x - * AL=-INF, AU=+INF => constraint is ignored - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpaddlc2( - minqpstate state, - integer_1d_array idxa, - real_1d_array vala, - ae_int_t nnz, - double al, - double au, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function appends two-sided linear constraint AL <= A*x <= AU to the -list of currently present dense constraints. - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - A - linear constraint coefficient, array[N], right side is NOT - included. - AL, AU - lower and upper bounds; - * AL=AU => equality constraint Ai*x - * AL<AU => two-sided constraint AL<=A*x<=AU - * AL=-INF => one-sided constraint Ai*x<=AU - * AU=+INF => one-sided constraint AL<=Ai*x - * AL=-INF, AU=+INF => constraint is ignored - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpaddlc2dense( - minqpstate state, - real_1d_array a, - double al, - double au, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* - CONSTRAINED QUADRATIC PROGRAMMING - -The subroutine creates QP optimizer. After initial creation, it contains -default optimization problem with zero quadratic and linear terms and no -constraints. - -In order to actually solve something you should: -* set cost vector with minqpsetlinearterm() -* set variable bounds with minqpsetbc() or minqpsetbcall() -* specify constraint matrix with one of the following functions: - * modern API: - * minqpsetlc2() for sparse two-sided constraints AL <= A*x <= AU - * minqpsetlc2dense() for dense two-sided constraints AL <= A*x <= AU - * minqpsetlc2mixed() for mixed two-sided constraints AL <= A*x <= AU - * minqpaddlc2dense() to add one dense row to dense constraint submatrix - * minqpaddlc2() to add one sparse row to sparse constraint submatrix - * legacy API: - * minqpsetlc() for dense one-sided equality/inequality constraints - * minqpsetlcsparse() for sparse one-sided equality/inequality constraints - * minqpsetlcmixed() for mixed dense/sparse one-sided equality/inequality constraints -* choose appropriate QP solver and set it and its stopping criteria by - means of minqpsetalgo??????() function -* call minqpoptimize() to run the solver and minqpresults() to get the - solution vector and additional information. - -Following solvers are recommended for convex and semidefinite problems: -* QuickQP for dense problems with box-only constraints (or no constraints - at all) -* DENSE-IPM-QP for convex or semidefinite problems with medium (up - to several thousands) variable count, dense/sparse quadratic term and - any number (up to many thousands) of dense/sparse general linear - constraints -* SPARSE-IPM-QP for convex or semidefinite problems with large (many - thousands) variable count, sparse quadratic term AND linear constraints. - -If your problem happens to be nonconvex, but either (a) is effectively -convexified under constraints, or (b) has unique solution even with -nonconvex target, then you can use: -* QuickQP for dense nonconvex problems with box-only constraints -* DENSE-AUL-QP for dense nonconvex problems which are effectively - convexified under constraints with up to several thousands of variables - and any (small or large) number of general linear constraints -* QP-BLEIC for dense/sparse problems with small (up to several hundreds) - number of general linear constraints and arbitrarily large variable - count. - -INPUT PARAMETERS: - N - problem size - -OUTPUT PARAMETERS: - State - optimizer with zero quadratic/linear terms - and no constraints - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpcreate( - ae_int_t n, - minqpstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  [5]  

- -
-
/************************************************************************* -This function solves quadratic programming problem. - -Prior to calling this function you should choose solver by means of one of -the following functions: - -* minqpsetalgoquickqp() - for QuickQP solver -* minqpsetalgobleic() - for BLEIC-QP solver -* minqpsetalgodenseaul() - for Dense-AUL-QP solver -* minqpsetalgodenseipm() - for Dense-IPM-QP solver - -These functions also allow you to control stopping criteria of the solver. -If you did not set solver, MinQP subpackage will automatically select -solver for your problem and will run it with default stopping criteria. - -However, it is better to set explicitly solver and its stopping criteria. - -INPUT PARAMETERS: - State - algorithm state - -You should use MinQPResults() function to access results after calls -to this function. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey. - Special thanks to Elvira Illarionova for important suggestions on - the linearly constrained QP algorithm. -*************************************************************************/ -
void alglib::minqpoptimize( - minqpstate state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  [5]  

- -
-
/************************************************************************* -QP solver results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution (on failure - the best point found - so far). - Rep - optimization report, contains: - * completion code in Rep.TerminationType (positive values - denote some kind of success, negative - failures) - * Lagrange multipliers - for QP solvers which support them - * other statistics - See comments on minqpreport structure for more information - -Following completion codes are returned in Rep.TerminationType: -* -9 failure of the automatic scale evaluation: one of the diagonal - elements of the quadratic term is non-positive. Specify variable - scales manually! -* -5 inappropriate solver was used: - * QuickQP solver for problem with general linear constraints -* -4 the function is unbounded from below even under constraints, - no meaningful minimum can be found. -* -3 inconsistent constraints (or, maybe, feasible point is too hard to - find). -* -2 IPM solver has difficulty finding primal/dual feasible point. - It is likely that the problem is either infeasible or unbounded, - but it is difficult to determine exact reason for termination. - X contains best point found so far. -* >0 success -* 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpresults( - minqpstate state, - real_1d_array& x, - minqpreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  [5]  

- -
-
/************************************************************************* -QP results - -Buffered implementation of MinQPResults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpresultsbuf( - minqpstate state, - real_1d_array& x, - minqpreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function tells solver to use BLEIC-based algorithm and sets stopping -criteria for the algorithm. - -This algorithm is intended for large-scale problems, possibly nonconvex, -with small number of general linear constraints. Feasible initial point is -essential for good performance. - -IMPORTANT: when DENSE-IPM (or DENSE-AUL for nonconvex problems) solvers - are applicable, their performance is much better than that of - BLEIC-QP. - We recommend you to use BLEIC only when other solvers can not - be used. - -ALGORITHM FEATURES: - -* supports dense and sparse QP problems -* supports box and general linear equality/inequality constraints -* can solve all types of problems (convex, semidefinite, nonconvex) as - long as they are bounded from below under constraints. - Say, it is possible to solve "min{-x^2} subject to -1<=x<=+1". - Of course, global minimum is found only for positive definite and - semidefinite problems. As for indefinite ones - only local minimum is - found. - -ALGORITHM OUTLINE: - -* BLEIC-QP solver is just a driver function for MinBLEIC solver; it solves - quadratic programming problem as general linearly constrained - optimization problem, which is solved by means of BLEIC solver (part of - ALGLIB, active set method). - -ALGORITHM LIMITATIONS: -* This algorithm is inefficient on problems with hundreds and thousands - of general inequality constraints and infeasible initial point. Initial - feasibility detection stage may take too long on such constraint sets. - Consider using DENSE-IPM or DENSE-AUL instead. -* unlike QuickQP solver, this algorithm does not perform Newton steps and - does not use Level 3 BLAS. Being general-purpose active set method, it - can activate constraints only one-by-one. Thus, its performance is lower - than that of QuickQP. -* its precision is also a bit inferior to that of QuickQP. BLEIC-QP - performs only LBFGS steps (no Newton steps), which are good at detecting - neighborhood of the solution, buy needs many iterations to find solution - with more than 6 digits of precision. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|<EpsG is satisfied, where: - * |.| means Euclidian norm - * v - scaled constrained gradient vector, v[i]=g[i]*s[i] - * g - gradient - * s - scaling coefficients set by MinQPSetScale() - EpsF - >=0 - The subroutine finishes its work if exploratory steepest - descent step on k+1-th iteration satisfies following - condition: |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - EpsX - >=0 - The subroutine finishes its work if exploratory steepest - descent step on k+1-th iteration satisfies following - condition: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - step vector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinQPSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. NOTE: this algorithm uses LBFGS - iterations, which are relatively cheap, but improve - function value only a bit. So you will need many iterations - to converge - from 0.1*N to 10*N, depending on problem's - condition number. - -IT IS VERY IMPORTANT TO CALL MinQPSetScale() WHEN YOU USE THIS ALGORITHM -BECAUSE ITS STOPPING CRITERIA ARE SCALE-DEPENDENT! - -Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead -to automatic stopping criterion selection (presently it is small step -length, but it may change in the future versions of ALGLIB). - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetalgobleic( - minqpstate state, - double epsg, - double epsf, - double epsx, - ae_int_t maxits, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function tells QP solver to use DENSE-AUL algorithm and sets stopping -criteria for the algorithm. - -This algorithm is intended for non-convex problems with moderate (up -to several thousands) variable count and arbitrary number of constraints -which are either (a) effectively convexified under constraints or (b) have -unique solution even with nonconvex target. - -IMPORTANT: when DENSE-IPM solver is applicable, its performance is usually - much better than that of DENSE-AUL. - We recommend you to use DENSE-AUL only when other solvers can - not be used. - -ALGORITHM FEATURES: - -* supports box and dense/sparse general linear equality/inequality - constraints -* convergence is theoretically proved for positive-definite (convex) QP - problems. Semidefinite and non-convex problems can be solved as long as - they are bounded from below under constraints, although without - theoretical guarantees. - -ALGORITHM OUTLINE: - -* this algorithm is an augmented Lagrangian method with dense - preconditioner (hence its name). -* it performs several outer iterations in order to refine values of the - Lagrange multipliers. Single outer iteration is a solution of some - unconstrained optimization problem: first it performs dense Cholesky - factorization of the Hessian in order to build preconditioner (adaptive - regularization is applied to enforce positive definiteness), and then - it uses L-BFGS optimizer to solve optimization problem. -* typically you need about 5-10 outer iterations to converge to solution - -ALGORITHM LIMITATIONS: - -* because dense Cholesky driver is used, this algorithm has O(N^2) memory - requirements and O(OuterIterations*N^3) minimum running time. From the - practical point of view, it limits its applicability by several - thousands of variables. - From the other side, variables count is the most limiting factor, - and dependence on constraint count is much more lower. Assuming that - constraint matrix is sparse, it may handle tens of thousands of general - linear constraints. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsX - >=0, stopping criteria for inner optimizer. - Inner iterations are stopped when step length (with - variable scaling being applied) is less than EpsX. - See minqpsetscale() for more information on variable - scaling. - Rho - penalty coefficient, Rho>0: - * large enough that algorithm converges with desired - precision. - * not TOO large to prevent ill-conditioning - * recommended values are 100, 1000 or 10000 - ItsCnt - number of outer iterations: - * recommended values: 10-15 (although in most cases it - converges within 5 iterations, you may need a few more - to be sure). - * ItsCnt=0 means that small number of outer iterations is - automatically chosen (10 iterations in current version). - * ItsCnt=1 means that AUL algorithm performs just as usual - penalty method. - * ItsCnt>1 means that AUL algorithm performs specified - number of outer iterations - -IT IS VERY IMPORTANT TO CALL minqpsetscale() WHEN YOU USE THIS ALGORITHM -BECAUSE ITS CONVERGENCE PROPERTIES AND STOPPING CRITERIA ARE SCALE-DEPENDENT! - -NOTE: Passing EpsX=0 will lead to automatic step length selection - (specific step length chosen may change in the future versions of - ALGLIB, so it is better to specify step length explicitly). - - -- ALGLIB -- - Copyright 20.08.2016 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetalgodenseaul( - minqpstate state, - double epsx, - double rho, - ae_int_t itscnt, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function tells QP solver to use DENSE-IPM QP algorithm and sets -stopping criteria for the algorithm. - -This algorithm is intended for convex and semidefinite problems with -moderate (up to several thousands) variable count and arbitrary number of -constraints. - -IMPORTANT: this algorithm won't work for nonconvex problems, use DENSE-AUL - or BLEIC-QP instead. If you try to run DENSE-IPM on problem - with indefinite matrix (matrix having at least one negative - eigenvalue) then depending on circumstances it may either (a) - stall at some arbitrary point, or (b) throw exception on - failure of Cholesky decomposition. - -ALGORITHM FEATURES: - -* supports box and dense/sparse general linear equality/inequality - constraints - -ALGORITHM OUTLINE: - -* this algorithm is our implementation of interior point method as - formulated by R.J.Vanderbei, with minor modifications to the algorithm - (damped Newton directions are extensively used) -* like all interior point methods, this algorithm tends to converge in - roughly same number of iterations (between 15 and 50) independently from - the problem dimensionality - -ALGORITHM LIMITATIONS: - -* because dense Cholesky driver is used, for N-dimensional problem with - M dense constaints this algorithm has O(N^2+N*M) memory requirements and - O(N^3+N*M^2) running time. - Having sparse constraints with Z nonzeros per row relaxes storage and - running time down to O(N^2+M*Z) and O(N^3+N*Z^2) - From the practical point of view, it limits its applicability by - several thousands of variables. - From the other side, variables count is the most limiting factor, - and dependence on constraint count is much more lower. Assuming that - constraint matrix is sparse, it may handle tens of thousands of general - linear constraints. - -INPUT PARAMETERS: - State - structure which stores algorithm state - Eps - >=0, stopping criteria. The algorithm stops when primal - and dual infeasiblities as well as complementarity gap are - less than Eps. - -IT IS VERY IMPORTANT TO CALL minqpsetscale() WHEN YOU USE THIS ALGORITHM -BECAUSE ITS CONVERGENCE PROPERTIES AND STOPPING CRITERIA ARE SCALE-DEPENDENT! - -NOTE: Passing EpsX=0 will lead to automatic selection of small epsilon. - -===== TRACING IPM SOLVER ================================================= - -IPM solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'IPM' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. -* 'IPM.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'IPM'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("IPM,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetalgodenseipm( - minqpstate state, - double eps, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function tells solver to use QuickQP algorithm: special extra-fast -algorithm for problems with box-only constrants. It may solve non-convex -problems as long as they are bounded from below under constraints. - -ALGORITHM FEATURES: -* several times faster than DENSE-IPM when running on box-only problem -* utilizes accelerated methods for activation of constraints. -* supports dense and sparse QP problems -* supports ONLY box constraints; general linear constraints are NOT - supported by this solver -* can solve all types of problems (convex, semidefinite, nonconvex) as - long as they are bounded from below under constraints. - Say, it is possible to solve "min{-x^2} subject to -1<=x<=+1". - In convex/semidefinite case global minimum is returned, in nonconvex - case - algorithm returns one of the local minimums. - -ALGORITHM OUTLINE: - -* algorithm performs two kinds of iterations: constrained CG iterations - and constrained Newton iterations -* initially it performs small number of constrained CG iterations, which - can efficiently activate/deactivate multiple constraints -* after CG phase algorithm tries to calculate Cholesky decomposition and - to perform several constrained Newton steps. If Cholesky decomposition - failed (matrix is indefinite even under constraints), we perform more - CG iterations until we converge to such set of constraints that system - matrix becomes positive definite. Constrained Newton steps greatly - increase convergence speed and precision. -* algorithm interleaves CG and Newton iterations which allows to handle - indefinite matrices (CG phase) and quickly converge after final set of - constraints is found (Newton phase). Combination of CG and Newton phases - is called "outer iteration". -* it is possible to turn off Newton phase (beneficial for semidefinite - problems - Cholesky decomposition will fail too often) - -ALGORITHM LIMITATIONS: - -* algorithm does not support general linear constraints; only box ones - are supported -* Cholesky decomposition for sparse problems is performed with Skyline - Cholesky solver, which is intended for low-profile matrices. No profile- - reducing reordering of variables is performed in this version of ALGLIB. -* problems with near-zero negative eigenvalues (or exacty zero ones) may - experience about 2-3x performance penalty. The reason is that Cholesky - decomposition can not be performed until we identify directions of zero - and negative curvature and activate corresponding boundary constraints - - but we need a lot of trial and errors because these directions are hard - to notice in the matrix spectrum. - In this case you may turn off Newton phase of algorithm. - Large negative eigenvalues are not an issue, so highly non-convex - problems can be solved very efficiently. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|<EpsG is satisfied, where: - * |.| means Euclidian norm - * v - scaled constrained gradient vector, v[i]=g[i]*s[i] - * g - gradient - * s - scaling coefficients set by MinQPSetScale() - EpsF - >=0 - The subroutine finishes its work if exploratory steepest - descent step on k+1-th iteration satisfies following - condition: |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - EpsX - >=0 - The subroutine finishes its work if exploratory steepest - descent step on k+1-th iteration satisfies following - condition: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - step vector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinQPSetScale() - MaxOuterIts-maximum number of OUTER iterations. One outer iteration - includes some amount of CG iterations (from 5 to ~N) and - one or several (usually small amount) Newton steps. Thus, - one outer iteration has high cost, but can greatly reduce - funcation value. - Use 0 if you do not want to limit number of outer iterations. - UseNewton- use Newton phase or not: - * Newton phase improves performance of positive definite - dense problems (about 2 times improvement can be observed) - * can result in some performance penalty on semidefinite - or slightly negative definite problems - each Newton - phase will bring no improvement (Cholesky failure), but - still will require computational time. - * if you doubt, you can turn off this phase - optimizer - will retain its most of its high speed. - -IT IS VERY IMPORTANT TO CALL MinQPSetScale() WHEN YOU USE THIS ALGORITHM -BECAUSE ITS STOPPING CRITERIA ARE SCALE-DEPENDENT! - -Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead -to automatic stopping criterion selection (presently it is small step -length, but it may change in the future versions of ALGLIB). - - -- ALGLIB -- - Copyright 22.05.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetalgoquickqp( - minqpstate state, - double epsg, - double epsf, - double epsx, - ae_int_t maxouterits, - bool usenewton, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function tells QP solver to use SPARSE-IPM QP algorithm and sets -stopping criteria for the algorithm. - -This algorithm is intended for convex and semidefinite problems with -large variable and constraint count and sparse quadratic term and -constraints. It is possible to have some limited set of dense linear -constraints - they will be handled separately by dense BLAS - but the more -dense constraints you have, the more time solver needs. - -IMPORTANT: internally this solver performs large and sparse (N+M)x(N+M) - triangular factorization. So it expects both quadratic term and - constraints to be highly sparse. However, its running time is - influenced by BOTH fill factor and sparsity pattern. - - Generally we expect that no more than few nonzero elements per - row are present. However different sparsity patterns may result - in completely different running times even given same fill - factor. - - In many cases this algorithm outperforms DENSE-IPM by order of - magnitude. However, in some cases you may get better results - with DENSE-IPM even when solving sparse task. - -IMPORTANT: this algorithm won't work for nonconvex problems, use DENSE-AUL - or BLEIC-QP instead. If you try to run DENSE-IPM on problem - with indefinite matrix (matrix having at least one negative - eigenvalue) then depending on circumstances it may either (a) - stall at some arbitrary point, or (b) throw exception on - failure of Cholesky decomposition. - -ALGORITHM FEATURES: - -* supports box and dense/sparse general linear equality/inequality - constraints -* specializes on large-scale sparse problems - -ALGORITHM OUTLINE: - -* this algorithm is our implementation of interior point method as - formulated by R.J.Vanderbei, with minor modifications to the algorithm - (damped Newton directions are extensively used) -* like all interior point methods, this algorithm tends to converge in - roughly same number of iterations (between 15 and 50) independently from - the problem dimensionality - -ALGORITHM LIMITATIONS: - -* this algorithm may handle moderate number of dense constraints, usually - no more than a thousand of dense ones without losing its efficiency. - -INPUT PARAMETERS: - State - structure which stores algorithm state - Eps - >=0, stopping criteria. The algorithm stops when primal - and dual infeasiblities as well as complementarity gap are - less than Eps. - -IT IS VERY IMPORTANT TO CALL minqpsetscale() WHEN YOU USE THIS ALGORITHM -BECAUSE ITS CONVERGENCE PROPERTIES AND STOPPING CRITERIA ARE SCALE-DEPENDENT! - -NOTE: Passing EpsX=0 will lead to automatic selection of small epsilon. - -===== TRACING IPM SOLVER ================================================= - -IPM solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'IPM' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. -* 'IPM.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'IPM'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("IPM,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetalgosparseipm( - minqpstate state, - double eps, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets box constraints for QP solver - -Box constraints are inactive by default (after initial creation). After -being set, they are preserved until explicitly overwritten with another -minqpsetbc() or minqpsetbcall() call, or partially overwritten with -minqpsetbci() call. - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd[i] BndL[i]=BndU[i] - lower bound BndL[i]<=x[i] BndU[i]=+INF - upper bound x[i]<=BndU[i] BndL[i]=-INF - range BndL[i]<=x[i]<=BndU[i] ... - free variable - BndL[I]=-INF, BndU[I]+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF (latter is recommended because - it will allow solver to use better algorithm). - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF (latter is recommended because - it will allow solver to use better algorithm). - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: if constraints for all variables are same you may use minqpsetbcall() - which allows to specify constraints without using arrays. - -NOTE: BndL>BndU will result in QP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetbc( - minqpstate state, - real_1d_array bndl, - real_1d_array bndu, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function sets box constraints for QP solver (all variables at once, -same constraints for all variables) - -Box constraints are inactive by default (after initial creation). After -being set, they are preserved until explicitly overwritten with another -minqpsetbc() or minqpsetbcall() call, or partially overwritten with -minqpsetbci() call. - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd BndL=BndU - lower bound BndL<=x[i] BndU=+INF - upper bound x[i]<=BndU BndL=-INF - range BndL<=x[i]<=BndU ... - free variable - BndL=-INF, BndU+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bound, same for all variables - BndU - upper bound, same for all variables - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: BndL>BndU will result in QP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetbcall( - minqpstate state, - double bndl, - double bndu, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets box constraints for I-th variable (other variables are -not modified). - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd BndL=BndU - lower bound BndL<=x[i] BndU=+INF - upper bound x[i]<=BndU BndL=-INF - range BndL<=x[i]<=BndU ... - free variable - BndL=-INF, BndU+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bound - BndU - upper bound - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: BndL>BndU will result in QP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetbci( - minqpstate state, - ae_int_t i, - double bndl, - double bndu, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets dense linear constraints for QP optimizer. - -This function overrides results of previous calls to minqpsetlc(), -minqpsetlcsparse() and minqpsetlcmixed(). After call to this function -all non-box constraints are dropped, and you have only those constraints -which were specified in the present call. - -If you want to specify mixed (with dense and sparse terms) linear -constraints, you should call minqpsetlcmixed(). - -INPUT PARAMETERS: - State - structure previously allocated with MinQPCreate call. - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -NOTE 1: linear (non-bound) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations (BLEIC-QP solver is most precise, AUL-QP - solver is less precise). - - -- ALGLIB -- - Copyright 19.06.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetlc( - minqpstate state, - real_2d_array c, - integer_1d_array ct, - const xparams _params = alglib::xdefault); -void alglib::minqpsetlc( - minqpstate state, - real_2d_array c, - integer_1d_array ct, - ae_int_t k, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU with -sparse constraining matrix A. Recommended for large-scale problems. - -This function overwrites linear (non-box) constraints set by previous -calls (if such calls were made). - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - A - sparse matrix with size [K,N] (exactly!). - Each row of A represents one general linear constraint. - A can be stored in any sparse storage format. - AL, AU - lower and upper bounds, array[K]; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i]<AU[i] => two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0. If K=0 - is specified, A, AL, AU are ignored. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetlc2( - minqpstate state, - sparsematrix a, - real_1d_array al, - real_1d_array au, - ae_int_t k, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU with dense -constraint matrix A. - -NOTE: knowing that constraint matrix is dense helps some QP solvers - (especially modern IPM method) to utilize efficient dense Level 3 - BLAS for dense parts of the problem. If your problem has both dense - and sparse constraints, you can use minqpsetlc2mixed() function, - which will result in dense algebra being applied to dense terms, and - sparse sparse linear algebra applied to sparse terms. - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - A - linear constraints, array[K,N]. Each row of A represents - one constraint. One-sided inequality constraints, two- - sided inequality constraints, equality constraints are - supported (see below) - AL, AU - lower and upper bounds, array[K]; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i]<AU[i] => two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0; if not - given, inferred from sizes of A, AL, AU. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetlc2dense( - minqpstate state, - real_2d_array a, - real_1d_array al, - real_1d_array au, - const xparams _params = alglib::xdefault); -void alglib::minqpsetlc2dense( - minqpstate state, - real_2d_array a, - real_1d_array al, - real_1d_array au, - ae_int_t k, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU with -mixed constraining matrix A including sparse part (first SparseK rows) and -dense part (last DenseK rows). Recommended for large-scale problems. - -This function overwrites linear (non-box) constraints set by previous -calls (if such calls were made). - -This function may be useful if constraint matrix includes large number of -both types of rows - dense and sparse. If you have just a few sparse rows, -you may represent them in dense format without losing performance. -Similarly, if you have just a few dense rows, you may store them in sparse -format with almost same performance. - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - SparseA - sparse matrix with size [K,N] (exactly!). - Each row of A represents one general linear constraint. - A can be stored in any sparse storage format. - SparseK - number of sparse constraints, SparseK>=0 - DenseA - linear constraints, array[K,N], set of dense constraints. - Each row of A represents one general linear constraint. - DenseK - number of dense constraints, DenseK>=0 - AL, AU - lower and upper bounds, array[SparseK+DenseK], with former - SparseK elements corresponding to sparse constraints, and - latter DenseK elements corresponding to dense constraints; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i]<AU[i] => two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0. If K=0 - is specified, A, AL, AU are ignored. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetlc2mixed( - minqpstate state, - sparsematrix sparsea, - ae_int_t ksparse, - real_2d_array densea, - ae_int_t kdense, - real_1d_array al, - real_1d_array au, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets mixed linear constraints, which include a set of dense -rows, and a set of sparse rows. - -This function overrides results of previous calls to minqpsetlc(), -minqpsetlcsparse() and minqpsetlcmixed(). - -This function may be useful if constraint matrix includes large number of -both types of rows - dense and sparse. If you have just a few sparse rows, -you may represent them in dense format without losing performance. -Similarly, if you have just a few dense rows, you may store them in sparse -format with almost same performance. - -INPUT PARAMETERS: - State - structure previously allocated with MinQPCreate call. - SparseC - linear constraints, sparse matrix with dimensions EXACTLY - EQUAL TO [SparseK,N+1]. Each row of C represents one - constraint, either equality or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - SparseCT- type of sparse constraints, array[K]: - * if SparseCT[i]>0, then I-th constraint is SparseC[i,*]*x >= SparseC[i,n+1] - * if SparseCT[i]=0, then I-th constraint is SparseC[i,*]*x = SparseC[i,n+1] - * if SparseCT[i]<0, then I-th constraint is SparseC[i,*]*x <= SparseC[i,n+1] - SparseK - number of sparse equality/inequality constraints, K>=0 - DenseC - dense linear constraints, array[K,N+1]. - Each row of DenseC represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of DenseC (including right part) must be finite. - DenseCT - type of constraints, array[K]: - * if DenseCT[i]>0, then I-th constraint is DenseC[i,*]*x >= DenseC[i,n+1] - * if DenseCT[i]=0, then I-th constraint is DenseC[i,*]*x = DenseC[i,n+1] - * if DenseCT[i]<0, then I-th constraint is DenseC[i,*]*x <= DenseC[i,n+1] - DenseK - number of equality/inequality constraints, DenseK>=0 - -NOTE 1: linear (non-box) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations (BLEIC-QP solver is most precise, AUL-QP - solver is less precise). - -NOTE 2: due to backward compatibility reasons SparseC can be larger than - [SparseK,N+1]. In this case only leading [SparseK,N+1] submatrix - will be used. However, the rest of ALGLIB has more strict - requirements on the input size, so we recommend you to pass sparse - term whose size exactly matches algorithm expectations. - - -- ALGLIB -- - Copyright 22.08.2016 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetlcmixed( - minqpstate state, - sparsematrix sparsec, - integer_1d_array sparsect, - ae_int_t sparsek, - real_2d_array densec, - integer_1d_array densect, - ae_int_t densek, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function provides legacy API for specification of mixed dense/sparse -linear constraints. - -New conventions used by ALGLIB since release 3.16.0 state that set of -sparse constraints comes first, followed by set of dense ones. This -convention is essential when you talk about things like order of Lagrange -multipliers. - -However, legacy API accepted mixed constraints in reverse order. This -function is here to simplify situation with code relying on legacy API. It -simply accepts constraints in one order (old) and passes them to new API, -now in correct order. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetlcmixedlegacy( - minqpstate state, - real_2d_array densec, - integer_1d_array densect, - ae_int_t densek, - sparsematrix sparsec, - integer_1d_array sparsect, - ae_int_t sparsek, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets sparse linear constraints for QP optimizer. - -This function overrides results of previous calls to minqpsetlc(), -minqpsetlcsparse() and minqpsetlcmixed(). After call to this function -all non-box constraints are dropped, and you have only those constraints -which were specified in the present call. - -If you want to specify mixed (with dense and sparse terms) linear -constraints, you should call minqpsetlcmixed(). - -INPUT PARAMETERS: - State - structure previously allocated with MinQPCreate call. - C - linear constraints, sparse matrix with dimensions at - least [K,N+1]. If matrix has larger size, only leading - Kx(N+1) rectangle is used. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0 - -NOTE 1: linear (non-bound) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations (BLEIC-QP solver is most precise, AUL-QP - solver is less precise). - - -- ALGLIB -- - Copyright 22.08.2016 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetlcsparse( - minqpstate state, - sparsematrix c, - integer_1d_array ct, - ae_int_t k, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets linear term for QP solver. - -By default, linear term is zero. - -INPUT PARAMETERS: - State - structure which stores algorithm state - B - linear term, array[N]. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetlinearterm( - minqpstate state, - real_1d_array b, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  [5]  

- -
-
/************************************************************************* -This function sets origin for QP solver. By default, following QP program -is solved: - - min(0.5*x'*A*x+b'*x) - -This function allows to solve different problem: - - min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin)) - -Specification of non-zero origin affects function being minimized, but not -constraints. Box and linear constraints are still calculated without -origin. - -INPUT PARAMETERS: - State - structure which stores algorithm state - XOrigin - origin, array[N]. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetorigin( - minqpstate state, - real_1d_array xorigin, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets dense quadratic term for QP solver. By default, -quadratic term is zero. - -IMPORTANT: - -This solver minimizes following function: - f(x) = 0.5*x'*A*x + b'*x. -Note that quadratic term has 0.5 before it. So if you want to minimize - f(x) = x^2 + x -you should rewrite your problem as follows: - f(x) = 0.5*(2*x^2) + x -and your matrix A will be equal to [[2.0]], not to [[1.0]] - -INPUT PARAMETERS: - State - structure which stores algorithm state - A - matrix, array[N,N] - IsUpper - (optional) storage type: - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used - * if not given, both lower and upper triangles must be - filled. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetquadraticterm( - minqpstate state, - real_2d_array a, - const xparams _params = alglib::xdefault); -void alglib::minqpsetquadraticterm( - minqpstate state, - real_2d_array a, - bool isupper, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  

- -
-
/************************************************************************* -This function sets sparse quadratic term for QP solver. By default, -quadratic term is zero. This function overrides previous calls to -minqpsetquadraticterm() or minqpsetquadratictermsparse(). - -NOTE: dense solvers like DENSE-AUL-QP or DENSE-IPM-QP will convert this - matrix to dense storage anyway. - -IMPORTANT: - -This solver minimizes following function: - f(x) = 0.5*x'*A*x + b'*x. -Note that quadratic term has 0.5 before it. So if you want to minimize - f(x) = x^2 + x -you should rewrite your problem as follows: - f(x) = 0.5*(2*x^2) + x -and your matrix A will be equal to [[2.0]], not to [[1.0]] - -INPUT PARAMETERS: - State - structure which stores algorithm state - A - matrix, array[N,N] - IsUpper - (optional) storage type: - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used - * if not given, both lower and upper triangles must be - filled. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetquadratictermsparse( - minqpstate state, - sparsematrix a, - bool isupper, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function sets scaling coefficients. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances) and as -preconditioner. - -Scale of the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the - function - -If you do not know how to choose scales of your variables, you can: -* read www.alglib.net/optimization/scaling.php article -* use minqpsetscaleautodiag(), which calculates scale using diagonal of - the quadratic term: S is set to 1/sqrt(diag(A)), which works well - sometimes. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetscale( - minqpstate state, - real_1d_array s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets automatic evaluation of variable scaling. - -IMPORTANT: this function works only for matrices with positive diagonal - elements! Zero or negative elements will result in -9 error - code being returned. Specify scale vector manually with - minqpsetscale() in such cases. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances) and as -preconditioner. - -The best way to set scaling is to manually specify variable scales. -However, sometimes you just need quick-and-dirty solution - either when -you perform fast prototyping, or when you know your problem well and you -are 100% sure that this quick solution is robust enough in your case. - -One such solution is to evaluate scale of I-th variable as 1/Sqrt(A[i,i]), -where A[i,i] is an I-th diagonal element of the quadratic term. - -Such approach works well sometimes, but you have to be careful here. - -INPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetscaleautodiag( - minqpstate state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets starting point for QP solver. It is useful to have good -initial approximation to the solution, because it will increase speed of -convergence and identification of active constraints. - -NOTE: interior point solvers ignore initial point provided by user. - -INPUT PARAMETERS: - State - structure which stores algorithm state - X - starting point, array[N]. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::minqpsetstartingpoint( - minqpstate state, - real_1d_array x, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  [5]  

- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of F(x0,x1) = x0^2 + x1^2 -6*x0 - 4*x1
-    // subject to bound constraints 0<=x0<=2.5, 0<=x1<=2.5
-    //
-    // Exact solution is [x0,x1] = [2.5,2]
-    //
-    // We provide algorithm with starting point. With such small problem good starting
-    // point is not really necessary, but with high-dimensional problem it can save us
-    // a lot of time.
-    //
-    // Several QP solvers are tried: QuickQP, BLEIC, DENSE-AUL.
-    //
-    // IMPORTANT: this solver minimizes  following  function:
-    //     f(x) = 0.5*x'*A*x + b'*x.
-    // Note that quadratic term has 0.5 before it. So if you want to minimize
-    // quadratic function, you should rewrite it in such way that quadratic term
-    // is multiplied by 0.5 too.
-    // For example, our function is f(x)=x0^2+x1^2+..., but we rewrite it as 
-    //     f(x) = 0.5*(2*x0^2+2*x1^2) + ....
-    // and pass diag(2,2) as quadratic term - NOT diag(1,1)!
-    //
-    real_2d_array a = "[[2,0],[0,2]]";
-    real_1d_array b = "[-6,-4]";
-    real_1d_array x0 = "[0,1]";
-    real_1d_array s = "[1,1]";
-    real_1d_array bndl = "[0.0,0.0]";
-    real_1d_array bndu = "[2.5,2.5]";
-    real_1d_array x;
-    minqpstate state;
-    minqpreport rep;
-
-    // create solver, set quadratic/linear terms
-    minqpcreate(2, state);
-    minqpsetquadraticterm(state, a);
-    minqpsetlinearterm(state, b);
-    minqpsetstartingpoint(state, x0);
-    minqpsetbc(state, bndl, bndu);
-
-    // Set scale of the parameters.
-    // It is strongly recommended that you set scale of your variables.
-    // Knowing their scales is essential for evaluation of stopping criteria
-    // and for preconditioning of the algorithm steps.
-    // You can find more information on scaling at http://www.alglib.net/optimization/scaling.php
-    //
-    // NOTE: for convex problems you may try using minqpsetscaleautodiag()
-    //       which automatically determines variable scales.
-    minqpsetscale(state, s);
-
-    //
-    // Solve problem with QuickQP solver.
-    //
-    // This solver is intended for medium and large-scale problems with box
-    // constraints (general linear constraints are not supported).
-    //
-    // Default stopping criteria are used, Newton phase is active.
-    //
-    minqpsetalgoquickqp(state, 0.0, 0.0, 0.0, 0, true);
-    minqpoptimize(state);
-    minqpresults(state, x, rep);
-    printf("%d\n", int(rep.terminationtype)); // EXPECTED: 4
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [2.5,2]
-
-    //
-    // Solve problem with BLEIC-based QP solver.
-    //
-    // This solver is intended for problems with moderate (up to 50) number
-    // of general linear constraints and unlimited number of box constraints.
-    //
-    // Default stopping criteria are used.
-    //
-    minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0);
-    minqpoptimize(state);
-    minqpresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [2.5,2]
-
-    //
-    // Solve problem with DENSE-AUL solver.
-    //
-    // This solver is optimized for problems with up to several thousands of
-    // variables and large amount of general linear constraints. Problems with
-    // less than 50 general linear constraints can be efficiently solved with
-    // BLEIC, problems with box-only constraints can be solved with QuickQP.
-    // However, DENSE-AUL will work in any (including unconstrained) case.
-    //
-    // Default stopping criteria are used.
-    //
-    minqpsetalgodenseaul(state, 1.0e-9, 1.0e+4, 5);
-    minqpoptimize(state);
-    minqpresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [2.5,2]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of F(x0,x1) = x0^2 + x1^2 -6*x0 - 4*x1
-    // subject to linear constraint x0+x1<=2
-    //
-    // Exact solution is [x0,x1] = [1.5,0.5]
-    //
-    // IMPORTANT: this solver minimizes  following  function:
-    //     f(x) = 0.5*x'*A*x + b'*x.
-    // Note that quadratic term has 0.5 before it. So if you want to minimize
-    // quadratic function, you should rewrite it in such way that quadratic term
-    // is multiplied by 0.5 too.
-    // For example, our function is f(x)=x0^2+x1^2+..., but we rewrite it as 
-    //     f(x) = 0.5*(2*x0^2+2*x1^2) + ....
-    // and pass diag(2,2) as quadratic term - NOT diag(1,1)!
-    //
-    real_2d_array a = "[[2,0],[0,2]]";
-    real_1d_array b = "[-6,-4]";
-    real_1d_array s = "[1,1]";
-    real_2d_array c = "[[1.0,1.0,2.0]]";
-    integer_1d_array ct = "[-1]";
-    real_1d_array x;
-    minqpstate state;
-    minqpreport rep;
-
-    // create solver, set quadratic/linear terms
-    minqpcreate(2, state);
-    minqpsetquadraticterm(state, a);
-    minqpsetlinearterm(state, b);
-    minqpsetlc(state, c, ct);
-
-    // Set scale of the parameters.
-    // It is strongly recommended that you set scale of your variables.
-    // Knowing their scales is essential for evaluation of stopping criteria
-    // and for preconditioning of the algorithm steps.
-    // You can find more information on scaling at http://www.alglib.net/optimization/scaling.php
-    //
-    // NOTE: for convex problems you may try using minqpsetscaleautodiag()
-    //       which automatically determines variable scales.
-    minqpsetscale(state, s);
-
-    //
-    // Solve problem with BLEIC-based QP solver.
-    //
-    // This solver is intended for problems with moderate (up to 50) number
-    // of general linear constraints and unlimited number of box constraints.
-    //
-    // Default stopping criteria are used.
-    //
-    minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0);
-    minqpoptimize(state);
-    minqpresults(state, x, rep);
-    printf("%s\n", x.tostring(1).c_str()); // EXPECTED: [1.500,0.500]
-
-    //
-    // Solve problem with DENSE-AUL solver.
-    //
-    // This solver is optimized for problems with up to several thousands of
-    // variables and large amount of general linear constraints. Problems with
-    // less than 50 general linear constraints can be efficiently solved with
-    // BLEIC, problems with box-only constraints can be solved with QuickQP.
-    // However, DENSE-AUL will work in any (including unconstrained) case.
-    //
-    // Default stopping criteria are used.
-    //
-    minqpsetalgodenseaul(state, 1.0e-9, 1.0e+4, 5);
-    minqpoptimize(state);
-    minqpresults(state, x, rep);
-    printf("%s\n", x.tostring(1).c_str()); // EXPECTED: [1.500,0.500]
-
-    //
-    // Solve problem with QuickQP solver.
-    //
-    // This solver is intended for medium and large-scale problems with box
-    // constraints, and...
-    //
-    // ...Oops! It does not support general linear constraints, -5 returned as completion code!
-    //
-    minqpsetalgoquickqp(state, 0.0, 0.0, 0.0, 0, true);
-    minqpoptimize(state);
-    minqpresults(state, x, rep);
-    printf("%d\n", int(rep.terminationtype)); // EXPECTED: -5
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of nonconvex function
-    //     F(x0,x1) = -(x0^2+x1^2)
-    // subject to constraints x0,x1 in [1.0,2.0]
-    // Exact solution is [x0,x1] = [2,2].
-    //
-    // Non-convex problems are harded to solve than convex ones, and they
-    // may have more than one local minimum. However, ALGLIB solves may deal
-    // with such problems (altough they do not guarantee convergence to
-    // global minimum).
-    //
-    // IMPORTANT: this solver minimizes  following  function:
-    //     f(x) = 0.5*x'*A*x + b'*x.
-    // Note that quadratic term has 0.5 before it. So if you want to minimize
-    // quadratic function, you should rewrite it in such way that quadratic term
-    // is multiplied by 0.5 too.
-    //
-    // For example, our function is f(x)=-(x0^2+x1^2), but we rewrite it as 
-    //     f(x) = 0.5*(-2*x0^2-2*x1^2)
-    // and pass diag(-2,-2) as quadratic term - NOT diag(-1,-1)!
-    //
-    real_2d_array a = "[[-2,0],[0,-2]]";
-    real_1d_array x0 = "[1,1]";
-    real_1d_array s = "[1,1]";
-    real_1d_array bndl = "[1.0,1.0]";
-    real_1d_array bndu = "[2.0,2.0]";
-    real_1d_array x;
-    minqpstate state;
-    minqpreport rep;
-
-    // create solver, set quadratic/linear terms, constraints
-    minqpcreate(2, state);
-    minqpsetquadraticterm(state, a);
-    minqpsetstartingpoint(state, x0);
-    minqpsetbc(state, bndl, bndu);
-
-    // Set scale of the parameters.
-    // It is strongly recommended that you set scale of your variables.
-    // Knowing their scales is essential for evaluation of stopping criteria
-    // and for preconditioning of the algorithm steps.
-    // You can find more information on scaling at http://www.alglib.net/optimization/scaling.php
-    //
-    // NOTE: there also exists minqpsetscaleautodiag() function
-    //       which automatically determines variable scales; however,
-    //       it does NOT work for non-convex problems.
-    minqpsetscale(state, s);
-
-    //
-    // Solve problem with BLEIC-based QP solver.
-    //
-    // This solver is intended for problems with moderate (up to 50) number
-    // of general linear constraints and unlimited number of box constraints.
-    //
-    // It may solve non-convex problems as long as they are bounded from
-    // below under constraints.
-    //
-    // Default stopping criteria are used.
-    //
-    minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0);
-    minqpoptimize(state);
-    minqpresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [2,2]
-
-    //
-    // Solve problem with DENSE-AUL solver.
-    //
-    // This solver is optimized for problems with up to several thousands of
-    // variables and large amount of general linear constraints. Problems with
-    // less than 50 general linear constraints can be efficiently solved with
-    // BLEIC, problems with box-only constraints can be solved with QuickQP.
-    // However, DENSE-AUL will work in any (including unconstrained) case.
-    //
-    // Algorithm convergence is guaranteed only for convex case, but you may
-    // expect that it will work for non-convex problems too (because near the
-    // solution they are locally convex).
-    //
-    // Default stopping criteria are used.
-    //
-    minqpsetalgodenseaul(state, 1.0e-9, 1.0e+4, 5);
-    minqpoptimize(state);
-    minqpresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [2,2]
-
-    // Hmm... this problem is bounded from below (has solution) only under constraints.
-    // What it we remove them?
-    //
-    // You may see that BLEIC algorithm detects unboundedness of the problem, 
-    // -4 is returned as completion code. However, DENSE-AUL is unable to detect
-    // such situation and it will cycle forever (we do not test it here).
-    real_1d_array nobndl = "[-inf,-inf]";
-    real_1d_array nobndu = "[+inf,+inf]";
-    minqpsetbc(state, nobndl, nobndu);
-    minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0);
-    minqpoptimize(state);
-    minqpresults(state, x, rep);
-    printf("%d\n", int(rep.terminationtype)); // EXPECTED: -4
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of F(x0,x1) = x0^2 + x1^2 -6*x0 - 4*x1
-    //
-    // Exact solution is [x0,x1] = [3,2]
-    //
-    // We provide algorithm with starting point, although in this case
-    // (dense matrix, no constraints) it can work without such information.
-    //
-    // Several QP solvers are tried: QuickQP, BLEIC, DENSE-AUL.
-    //
-    // IMPORTANT: this solver minimizes  following  function:
-    //     f(x) = 0.5*x'*A*x + b'*x.
-    // Note that quadratic term has 0.5 before it. So if you want to minimize
-    // quadratic function, you should rewrite it in such way that quadratic term
-    // is multiplied by 0.5 too.
-    //
-    // For example, our function is f(x)=x0^2+x1^2+..., but we rewrite it as 
-    //     f(x) = 0.5*(2*x0^2+2*x1^2) + .... 
-    // and pass diag(2,2) as quadratic term - NOT diag(1,1)!
-    //
-    real_2d_array a = "[[2,0],[0,2]]";
-    real_1d_array b = "[-6,-4]";
-    real_1d_array x0 = "[0,1]";
-    real_1d_array s = "[1,1]";
-    real_1d_array x;
-    minqpstate state;
-    minqpreport rep;
-
-    // create solver, set quadratic/linear terms
-    minqpcreate(2, state);
-    minqpsetquadraticterm(state, a);
-    minqpsetlinearterm(state, b);
-    minqpsetstartingpoint(state, x0);
-
-    // Set scale of the parameters.
-    // It is strongly recommended that you set scale of your variables.
-    // Knowing their scales is essential for evaluation of stopping criteria
-    // and for preconditioning of the algorithm steps.
-    // You can find more information on scaling at http://www.alglib.net/optimization/scaling.php
-    //
-    // NOTE: for convex problems you may try using minqpsetscaleautodiag()
-    //       which automatically determines variable scales.
-    minqpsetscale(state, s);
-
-    //
-    // Solve problem with QuickQP solver.
-    //
-    // This solver is intended for medium and large-scale problems with box
-    // constraints (general linear constraints are not supported), but it can
-    // also be efficiently used on unconstrained problems.
-    //
-    // Default stopping criteria are used, Newton phase is active.
-    //
-    minqpsetalgoquickqp(state, 0.0, 0.0, 0.0, 0, true);
-    minqpoptimize(state);
-    minqpresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [3,2]
-
-    //
-    // Solve problem with BLEIC-based QP solver.
-    //
-    // This solver is intended for problems with moderate (up to 50) number
-    // of general linear constraints and unlimited number of box constraints.
-    // Of course, unconstrained problems can be solved too.
-    //
-    // Default stopping criteria are used.
-    //
-    minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0);
-    minqpoptimize(state);
-    minqpresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [3,2]
-
-    //
-    // Solve problem with DENSE-AUL solver.
-    //
-    // This solver is optimized for problems with up to several thousands of
-    // variables and large amount of general linear constraints. Problems with
-    // less than 50 general linear constraints can be efficiently solved with
-    // BLEIC, problems with box-only constraints can be solved with QuickQP.
-    // However, DENSE-AUL will work in any (including unconstrained) case.
-    //
-    // Default stopping criteria are used.
-    //
-    minqpsetalgodenseaul(state, 1.0e-9, 1.0e+4, 5);
-    minqpoptimize(state);
-    minqpresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [3,2]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "optimization.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates minimization of F(x0,x1) = x0^2 + x1^2 -6*x0 - 4*x1,
-    // with quadratic term given by sparse matrix structure.
-    //
-    // Exact solution is [x0,x1] = [3,2]
-    //
-    // We provide algorithm with starting point, although in this case
-    // (dense matrix, no constraints) it can work without such information.
-    //
-    // IMPORTANT: this solver minimizes  following  function:
-    //     f(x) = 0.5*x'*A*x + b'*x.
-    // Note that quadratic term has 0.5 before it. So if you want to minimize
-    // quadratic function, you should rewrite it in such way that quadratic term
-    // is multiplied by 0.5 too.
-    //
-    // For example, our function is f(x)=x0^2+x1^2+..., but we rewrite it as 
-    //     f(x) = 0.5*(2*x0^2+2*x1^2) + ....
-    // and pass diag(2,2) as quadratic term - NOT diag(1,1)!
-    //
-    sparsematrix a;
-    real_1d_array b = "[-6,-4]";
-    real_1d_array x0 = "[0,1]";
-    real_1d_array s = "[1,1]";
-    real_1d_array x;
-    minqpstate state;
-    minqpreport rep;
-
-    // initialize sparsematrix structure
-    sparsecreate(2, 2, 0, a);
-    sparseset(a, 0, 0, 2.0);
-    sparseset(a, 1, 1, 2.0);
-
-    // create solver, set quadratic/linear terms
-    minqpcreate(2, state);
-    minqpsetquadratictermsparse(state, a, true);
-    minqpsetlinearterm(state, b);
-    minqpsetstartingpoint(state, x0);
-
-    // Set scale of the parameters.
-    // It is strongly recommended that you set scale of your variables.
-    // Knowing their scales is essential for evaluation of stopping criteria
-    // and for preconditioning of the algorithm steps.
-    // You can find more information on scaling at http://www.alglib.net/optimization/scaling.php
-    //
-    // NOTE: for convex problems you may try using minqpsetscaleautodiag()
-    //       which automatically determines variable scales.
-    minqpsetscale(state, s);
-
-    //
-    // Solve problem with BLEIC-based QP solver.
-    //
-    // This solver is intended for problems with moderate (up to 50) number
-    // of general linear constraints and unlimited number of box constraints.
-    // It also supports sparse problems.
-    //
-    // Default stopping criteria are used.
-    //
-    minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0);
-    minqpoptimize(state);
-    minqpresults(state, x, rep);
-    printf("%s\n", x.tostring(2).c_str()); // EXPECTED: [3,2]
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* -Model's errors: - * RelCLSError - fraction of misclassified cases. - * AvgCE - acerage cross-entropy - * RMSError - root-mean-square error - * AvgError - average error - * AvgRelError - average relative error - -NOTE 1: RelCLSError/AvgCE are zero on regression problems. - -NOTE 2: on classification problems RMSError/AvgError/AvgRelError contain - errors in prediction of posterior probabilities -*************************************************************************/ -
class modelerrors -{ - double relclserror; - double avgce; - double rmserror; - double avgerror; - double avgrelerror; -}; - -
- -
-
/************************************************************************* - -*************************************************************************/ -
class multilayerperceptron -{ -}; - -
- -
-
/************************************************************************* -Neural network activation function - -INPUT PARAMETERS: - NET - neuron input - K - function index (zero for linear function) - -OUTPUT PARAMETERS: - F - function - DF - its derivative - D2F - its second derivative - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpactivationfunction( - double net, - ae_int_t k, - double& f, - double& df, - double& d2f, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Calculation of all types of errors on subset of dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset given by sparse matrix; - one sample = one row; - first NIn columns contain inputs, - next NOut columns - desired outputs. - SetSize - real size of XY, SetSize>=0; - Subset - subset of SubsetSize elements, array[SubsetSize]; - SubsetSize- number of elements in Subset[] array: - * if SubsetSize>0, rows of XY with indices Subset[0]... - ...Subset[SubsetSize-1] are processed - * if SubsetSize=0, zeros are returned - * if SubsetSize<0, entire dataset is processed; Subset[] - array is ignored in this case. - -OUTPUT PARAMETERS: - Rep - it contains all type of errors. - - - -- ALGLIB -- - Copyright 04.09.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpallerrorssparsesubset( - multilayerperceptron network, - sparsematrix xy, - ae_int_t setsize, - integer_1d_array subset, - ae_int_t subsetsize, - modelerrors& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Calculation of all types of errors on subset of dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset; one sample = one row; - first NIn columns contain inputs, - next NOut columns - desired outputs. - SetSize - real size of XY, SetSize>=0; - Subset - subset of SubsetSize elements, array[SubsetSize]; - SubsetSize- number of elements in Subset[] array: - * if SubsetSize>0, rows of XY with indices Subset[0]... - ...Subset[SubsetSize-1] are processed - * if SubsetSize=0, zeros are returned - * if SubsetSize<0, entire dataset is processed; Subset[] - array is ignored in this case. - -OUTPUT PARAMETERS: - Rep - it contains all type of errors. - - -- ALGLIB -- - Copyright 04.09.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpallerrorssubset( - multilayerperceptron network, - real_2d_array xy, - ae_int_t setsize, - integer_1d_array subset, - ae_int_t subsetsize, - modelerrors& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Average cross-entropy (in bits per element) on the test set. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: -CrossEntropy/(NPoints*LN(2)). -Zero if network solves regression task. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 08.01.2009 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlpavgce( - multilayerperceptron network, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Average cross-entropy (in bits per element) on the test set given by -sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - NPoints - points count, >=0. - -RESULT: -CrossEntropy/(NPoints*LN(2)). -Zero if network solves regression task. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 9.08.2012 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlpavgcesparse( - multilayerperceptron network, - sparsematrix xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Average absolute error on the test set. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: -Its meaning for regression task is obvious. As for classification task, it -means average error when estimating posterior probabilities. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 11.03.2008 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlpavgerror( - multilayerperceptron network, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Average absolute error on the test set given by sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - NPoints - points count, >=0. - -RESULT: -Its meaning for regression task is obvious. As for classification task, it -means average error when estimating posterior probabilities. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 09.08.2012 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlpavgerrorsparse( - multilayerperceptron network, - sparsematrix xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Average relative error on the test set. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: -Its meaning for regression task is obvious. As for classification task, it -means average relative error when estimating posterior probability of -belonging to the correct class. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 11.03.2008 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlpavgrelerror( - multilayerperceptron network, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Average relative error on the test set given by sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - NPoints - points count, >=0. - -RESULT: -Its meaning for regression task is obvious. As for classification task, it -means average relative error when estimating posterior probability of -belonging to the correct class. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 09.08.2012 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlpavgrelerrorsparse( - multilayerperceptron network, - sparsematrix xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Classification error of the neural network on dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: - classification error (number of misclassified cases) - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::mlpclserror( - multilayerperceptron network, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Copying of neural network - -INPUT PARAMETERS: - Network1 - original - -OUTPUT PARAMETERS: - Network2 - copy - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpcopy( - multilayerperceptron network1, - multilayerperceptron& network2, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function copies tunable parameters (weights/means/sigmas) from one -network to another with same architecture. It performs some rudimentary -checks that architectures are same, and throws exception if check fails. - -It is intended for fast copying of states between two network which are -known to have same geometry. - -INPUT PARAMETERS: - Network1 - source, must be correctly initialized - Network2 - target, must have same architecture - -OUTPUT PARAMETERS: - Network2 - network state is copied from source to target - - -- ALGLIB -- - Copyright 20.06.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpcopytunableparameters( - multilayerperceptron network1, - multilayerperceptron network2, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Creates neural network with NIn inputs, NOut outputs, without hidden -layers, with linear output layer. Network weights are filled with small -random values. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpcreate0( - ae_int_t nin, - ae_int_t nout, - multilayerperceptron& network, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Same as MLPCreate0, but with one hidden layer (NHid neurons) with -non-linear activation function. Output layer is linear. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpcreate1( - ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - multilayerperceptron& network, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Same as MLPCreate0, but with two hidden layers (NHid1 and NHid2 neurons) -with non-linear activation function. Output layer is linear. - $ALL - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpcreate2( - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - multilayerperceptron& network, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Creates neural network with NIn inputs, NOut outputs, without hidden -layers with non-linear output layer. Network weights are filled with small -random values. - -Activation function of the output layer takes values: - - (B, +INF), if D>=0 - -or - - (-INF, B), if D<0. - - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpcreateb0( - ae_int_t nin, - ae_int_t nout, - double b, - double d, - multilayerperceptron& network, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Same as MLPCreateB0 but with non-linear hidden layer. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpcreateb1( - ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - double b, - double d, - multilayerperceptron& network, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Same as MLPCreateB0 but with two non-linear hidden layers. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpcreateb2( - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - double b, - double d, - multilayerperceptron& network, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Creates classifier network with NIn inputs and NOut possible classes. -Network contains no hidden layers and linear output layer with SOFTMAX- -normalization (so outputs sums up to 1.0 and converge to posterior -probabilities). - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpcreatec0( - ae_int_t nin, - ae_int_t nout, - multilayerperceptron& network, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Same as MLPCreateC0, but with one non-linear hidden layer. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpcreatec1( - ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - multilayerperceptron& network, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Same as MLPCreateC0, but with two non-linear hidden layers. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpcreatec2( - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - multilayerperceptron& network, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Creates neural network with NIn inputs, NOut outputs, without hidden -layers with non-linear output layer. Network weights are filled with small -random values. Activation function of the output layer takes values [A,B]. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpcreater0( - ae_int_t nin, - ae_int_t nout, - double a, - double b, - multilayerperceptron& network, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Same as MLPCreateR0, but with non-linear hidden layer. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpcreater1( - ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - double a, - double b, - multilayerperceptron& network, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Same as MLPCreateR0, but with two non-linear hidden layers. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpcreater2( - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - double a, - double b, - multilayerperceptron& network, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Error of the neural network on dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: - sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2) - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlperror( - multilayerperceptron network, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Natural error function for neural network, internal subroutine. - -NOTE: this function is single-threaded. Unlike other error function, it -receives no speed-up from being executed in SMP mode. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlperrorn( - multilayerperceptron network, - real_2d_array xy, - ae_int_t ssize, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Error of the neural network on dataset given by sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - NPoints - points count, >=0 - -RESULT: - sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2) - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlperrorsparse( - multilayerperceptron network, - sparsematrix xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Error of the neural network on subset of sparse dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - SetSize - real size of XY, SetSize>=0; - it is used when SubsetSize<0; - Subset - subset of SubsetSize elements, array[SubsetSize]; - SubsetSize- number of elements in Subset[] array: - * if SubsetSize>0, rows of XY with indices Subset[0]... - ...Subset[SubsetSize-1] are processed - * if SubsetSize=0, zeros are returned - * if SubsetSize<0, entire dataset is processed; Subset[] - array is ignored in this case. - -RESULT: - sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2) - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 04.09.2012 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlperrorsparsesubset( - multilayerperceptron network, - sparsematrix xy, - ae_int_t setsize, - integer_1d_array subset, - ae_int_t subsetsize, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Error of the neural network on subset of dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - SetSize - real size of XY, SetSize>=0; - Subset - subset of SubsetSize elements, array[SubsetSize]; - SubsetSize- number of elements in Subset[] array: - * if SubsetSize>0, rows of XY with indices Subset[0]... - ...Subset[SubsetSize-1] are processed - * if SubsetSize=0, zeros are returned - * if SubsetSize<0, entire dataset is processed; Subset[] - array is ignored in this case. - -RESULT: - sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2) - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 04.09.2012 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlperrorsubset( - multilayerperceptron network, - real_2d_array xy, - ae_int_t setsize, - integer_1d_array subset, - ae_int_t subsetsize, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function returns offset/scaling coefficients for I-th input of the -network. - -INPUT PARAMETERS: - Network - network - I - input index - -OUTPUT PARAMETERS: - Mean - mean term - Sigma - sigma term, guaranteed to be nonzero. - -I-th input is passed through linear transformation - IN[i] = (IN[i]-Mean)/Sigma -before feeding to the network - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpgetinputscaling( - multilayerperceptron network, - ae_int_t i, - double& mean, - double& sigma, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Returns number of inputs. - - -- ALGLIB -- - Copyright 19.10.2011 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::mlpgetinputscount( - multilayerperceptron network, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function returns total number of layers (including input, hidden and -output layers). - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::mlpgetlayerscount( - multilayerperceptron network, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function returns size of K-th layer. - -K=0 corresponds to input layer, K=CNT-1 corresponds to output layer. - -Size of the output layer is always equal to the number of outputs, although -when we have softmax-normalized network, last neuron doesn't have any -connections - it is just zero. - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::mlpgetlayersize( - multilayerperceptron network, - ae_int_t k, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function returns information about Ith neuron of Kth layer - -INPUT PARAMETERS: - Network - network - K - layer index - I - neuron index (within layer) - -OUTPUT PARAMETERS: - FKind - activation function type (used by MLPActivationFunction()) - this value is zero for input or linear neurons - Threshold - also called offset, bias - zero for input neurons - -NOTE: this function throws exception if layer or neuron with given index -do not exists. - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpgetneuroninfo( - multilayerperceptron network, - ae_int_t k, - ae_int_t i, - ae_int_t& fkind, - double& threshold, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function returns offset/scaling coefficients for I-th output of the -network. - -INPUT PARAMETERS: - Network - network - I - input index - -OUTPUT PARAMETERS: - Mean - mean term - Sigma - sigma term, guaranteed to be nonzero. - -I-th output is passed through linear transformation - OUT[i] = OUT[i]*Sigma+Mean -before returning it to user. In case we have SOFTMAX-normalized network, -we return (Mean,Sigma)=(0.0,1.0). - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpgetoutputscaling( - multilayerperceptron network, - ae_int_t i, - double& mean, - double& sigma, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Returns number of outputs. - - -- ALGLIB -- - Copyright 19.10.2011 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::mlpgetoutputscount( - multilayerperceptron network, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function returns information about connection from I0-th neuron of -K0-th layer to I1-th neuron of K1-th layer. - -INPUT PARAMETERS: - Network - network - K0 - layer index - I0 - neuron index (within layer) - K1 - layer index - I1 - neuron index (within layer) - -RESULT: - connection weight (zero for non-existent connections) - -This function: -1. throws exception if layer or neuron with given index do not exists. -2. returns zero if neurons exist, but there is no connection between them - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlpgetweight( - multilayerperceptron network, - ae_int_t k0, - ae_int_t i0, - ae_int_t k1, - ae_int_t i1, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Returns number of weights. - - -- ALGLIB -- - Copyright 19.10.2011 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::mlpgetweightscount( - multilayerperceptron network, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Gradient calculation - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - X - input vector, length of array must be at least NIn - DesiredY- desired outputs, length of array must be at least NOut - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) - Grad - gradient of E with respect to weights of network, array[WCount] - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpgrad( - multilayerperceptron network, - real_1d_array x, - real_1d_array desiredy, - double& e, - real_1d_array& grad, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Batch gradient calculation for a set of inputs/outputs - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset in dense format; one sample = one row: - * first NIn columns contain inputs, - * for regression problem, next NOut columns store - desired outputs. - * for classification problem, next column (just one!) - stores class number. - SSize - number of elements in XY - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) - Grad - gradient of E with respect to weights of network, array[WCount] - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpgradbatch( - multilayerperceptron network, - real_2d_array xy, - ae_int_t ssize, - double& e, - real_1d_array& grad, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Batch gradient calculation for a set of inputs/outputs given by sparse -matrices - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset in sparse format; one sample = one row: - * MATRIX MUST BE STORED IN CRS FORMAT - * first NIn columns contain inputs. - * for regression problem, next NOut columns store - desired outputs. - * for classification problem, next column (just one!) - stores class number. - SSize - number of elements in XY - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) - Grad - gradient of E with respect to weights of network, array[WCount] - - -- ALGLIB -- - Copyright 26.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpgradbatchsparse( - multilayerperceptron network, - sparsematrix xy, - ae_int_t ssize, - double& e, - real_1d_array& grad, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Batch gradient calculation for a set of inputs/outputs for a subset of -dataset given by set of indexes. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset in sparse format; one sample = one row: - * MATRIX MUST BE STORED IN CRS FORMAT - * first NIn columns contain inputs, - * for regression problem, next NOut columns store - desired outputs. - * for classification problem, next column (just one!) - stores class number. - SetSize - real size of XY, SetSize>=0; - Idx - subset of SubsetSize elements, array[SubsetSize]: - * Idx[I] stores row index in the original dataset which is - given by XY. Gradient is calculated with respect to rows - whose indexes are stored in Idx[]. - * Idx[] must store correct indexes; this function throws - an exception in case incorrect index (less than 0 or - larger than rows(XY)) is given - * Idx[] may store indexes in any order and even with - repetitions. - SubsetSize- number of elements in Idx[] array: - * positive value means that subset given by Idx[] is processed - * zero value results in zero gradient - * negative value means that full dataset is processed - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) - Grad - gradient of E with respect to weights of network, - array[WCount] - -NOTE: when SubsetSize<0 is used full dataset by call MLPGradBatchSparse - function. - - -- ALGLIB -- - Copyright 26.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpgradbatchsparsesubset( - multilayerperceptron network, - sparsematrix xy, - ae_int_t setsize, - integer_1d_array idx, - ae_int_t subsetsize, - double& e, - real_1d_array& grad, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Batch gradient calculation for a subset of dataset - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset in dense format; one sample = one row: - * first NIn columns contain inputs, - * for regression problem, next NOut columns store - desired outputs. - * for classification problem, next column (just one!) - stores class number. - SetSize - real size of XY, SetSize>=0; - Idx - subset of SubsetSize elements, array[SubsetSize]: - * Idx[I] stores row index in the original dataset which is - given by XY. Gradient is calculated with respect to rows - whose indexes are stored in Idx[]. - * Idx[] must store correct indexes; this function throws - an exception in case incorrect index (less than 0 or - larger than rows(XY)) is given - * Idx[] may store indexes in any order and even with - repetitions. - SubsetSize- number of elements in Idx[] array: - * positive value means that subset given by Idx[] is processed - * zero value results in zero gradient - * negative value means that full dataset is processed - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) - Grad - gradient of E with respect to weights of network, - array[WCount] - - -- ALGLIB -- - Copyright 26.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpgradbatchsubset( - multilayerperceptron network, - real_2d_array xy, - ae_int_t setsize, - integer_1d_array idx, - ae_int_t subsetsize, - double& e, - real_1d_array& grad, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Gradient calculation (natural error function is used) - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - X - input vector, length of array must be at least NIn - DesiredY- desired outputs, length of array must be at least NOut - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, sum-of-squares for regression networks, - cross-entropy for classification networks. - Grad - gradient of E with respect to weights of network, array[WCount] - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpgradn( - multilayerperceptron network, - real_1d_array x, - real_1d_array desiredy, - double& e, - real_1d_array& grad, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Batch gradient calculation for a set of inputs/outputs -(natural error function is used) - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - set of inputs/outputs; one sample = one row; - first NIn columns contain inputs, - next NOut columns - desired outputs. - SSize - number of elements in XY - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, sum-of-squares for regression networks, - cross-entropy for classification networks. - Grad - gradient of E with respect to weights of network, array[WCount] - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpgradnbatch( - multilayerperceptron network, - real_2d_array xy, - ae_int_t ssize, - double& e, - real_1d_array& grad, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Batch Hessian calculation using R-algorithm. -Internal subroutine. - - -- ALGLIB -- - Copyright 26.01.2008 by Bochkanov Sergey. - - Hessian calculation based on R-algorithm described in - "Fast Exact Multiplication by the Hessian", - B. A. Pearlmutter, - Neural Computation, 1994. -*************************************************************************/ -
void alglib::mlphessianbatch( - multilayerperceptron network, - real_2d_array xy, - ae_int_t ssize, - double& e, - real_1d_array& grad, - real_2d_array& h, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Batch Hessian calculation (natural error function) using R-algorithm. -Internal subroutine. - - -- ALGLIB -- - Copyright 26.01.2008 by Bochkanov Sergey. - - Hessian calculation based on R-algorithm described in - "Fast Exact Multiplication by the Hessian", - B. A. Pearlmutter, - Neural Computation, 1994. -*************************************************************************/ -
void alglib::mlphessiannbatch( - multilayerperceptron network, - real_2d_array xy, - ae_int_t ssize, - double& e, - real_1d_array& grad, - real_2d_array& h, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Internal subroutine. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpinitpreprocessor( - multilayerperceptron network, - real_2d_array xy, - ae_int_t ssize, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Tells whether network is SOFTMAX-normalized (i.e. classifier) or not. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -
bool alglib::mlpissoftmax( - multilayerperceptron network, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Procesing - -INPUT PARAMETERS: - Network - neural network - X - input vector, array[0..NIn-1]. - -OUTPUT PARAMETERS: - Y - result. Regression estimate when solving regression task, - vector of posterior probabilities for classification task. - -See also MLPProcessI - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpprocess( - multilayerperceptron network, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -'interactive' variant of MLPProcess for languages like Python which -support constructs like "Y = MLPProcess(NN,X)" and interactive mode of the -interpreter - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 21.09.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpprocessi( - multilayerperceptron network, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Returns information about initialized network: number of inputs, outputs, -weights. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpproperties( - multilayerperceptron network, - ae_int_t& nin, - ae_int_t& nout, - ae_int_t& wcount, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Randomization of neural network weights - - -- ALGLIB -- - Copyright 06.11.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlprandomize( - multilayerperceptron network, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Randomization of neural network weights and standartisator - - -- ALGLIB -- - Copyright 10.03.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlprandomizefull( - multilayerperceptron network, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Relative classification error on the test set. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: -Percent of incorrectly classified cases. Works both for classifier -networks and general purpose networks used as classifiers. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 25.12.2008 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlprelclserror( - multilayerperceptron network, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Relative classification error on the test set given by sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. Sparse matrix must use CRS format - for storage. - NPoints - points count, >=0. - -RESULT: -Percent of incorrectly classified cases. Works both for classifier -networks and general purpose networks used as classifiers. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 09.08.2012 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlprelclserrorsparse( - multilayerperceptron network, - sparsematrix xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -RMS error on the test set given. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: -Root mean square error. Its meaning for regression task is obvious. As for -classification task, RMS error means error when estimating posterior -probabilities. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlprmserror( - multilayerperceptron network, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -RMS error on the test set given by sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - NPoints - points count, >=0. - -RESULT: -Root mean square error. Its meaning for regression task is obvious. As for -classification task, RMS error means error when estimating posterior -probabilities. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 09.08.2012 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlprmserrorsparse( - multilayerperceptron network, - sparsematrix xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -
void mlpserialize(multilayerperceptron &obj, std::string &s_out); -void mlpserialize(multilayerperceptron &obj, std::ostream &s_out); -
- -
-
/************************************************************************* -This function sets offset/scaling coefficients for I-th input of the -network. - -INPUT PARAMETERS: - Network - network - I - input index - Mean - mean term - Sigma - sigma term (if zero, will be replaced by 1.0) - -NTE: I-th input is passed through linear transformation - IN[i] = (IN[i]-Mean)/Sigma -before feeding to the network. This function sets Mean and Sigma. - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpsetinputscaling( - multilayerperceptron network, - ae_int_t i, - double mean, - double sigma, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function modifies information about Ith neuron of Kth layer - -INPUT PARAMETERS: - Network - network - K - layer index - I - neuron index (within layer) - FKind - activation function type (used by MLPActivationFunction()) - this value must be zero for input neurons - (you can not set activation function for input neurons) - Threshold - also called offset, bias - this value must be zero for input neurons - (you can not set threshold for input neurons) - -NOTES: -1. this function throws exception if layer or neuron with given index do - not exists. -2. this function also throws exception when you try to set non-linear - activation function for input neurons (any kind of network) or for output - neurons of classifier network. -3. this function throws exception when you try to set non-zero threshold for - input neurons (any kind of network). - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpsetneuroninfo( - multilayerperceptron network, - ae_int_t k, - ae_int_t i, - ae_int_t fkind, - double threshold, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets offset/scaling coefficients for I-th output of the -network. - -INPUT PARAMETERS: - Network - network - I - input index - Mean - mean term - Sigma - sigma term (if zero, will be replaced by 1.0) - -OUTPUT PARAMETERS: - -NOTE: I-th output is passed through linear transformation - OUT[i] = OUT[i]*Sigma+Mean -before returning it to user. This function sets Sigma/Mean. In case we -have SOFTMAX-normalized network, you can not set (Sigma,Mean) to anything -other than(0.0,1.0) - this function will throw exception. - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpsetoutputscaling( - multilayerperceptron network, - ae_int_t i, - double mean, - double sigma, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function modifies information about connection from I0-th neuron of -K0-th layer to I1-th neuron of K1-th layer. - -INPUT PARAMETERS: - Network - network - K0 - layer index - I0 - neuron index (within layer) - K1 - layer index - I1 - neuron index (within layer) - W - connection weight (must be zero for non-existent - connections) - -This function: -1. throws exception if layer or neuron with given index do not exists. -2. throws exception if you try to set non-zero weight for non-existent - connection - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpsetweight( - multilayerperceptron network, - ae_int_t k0, - ae_int_t i0, - ae_int_t k1, - ae_int_t i1, - double w, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -
void mlpunserialize(const std::string &s_in, multilayerperceptron &obj); -void mlpunserialize(const std::istream &s_in, multilayerperceptron &obj); -
- - - -
-
/************************************************************************* -Neural networks ensemble -*************************************************************************/ -
class mlpensemble -{ -}; - -
- -
-
/************************************************************************* -Average cross-entropy (in bits per element) on the test set - -INPUT PARAMETERS: - Ensemble- ensemble - XY - test set - NPoints - test set size - -RESULT: - CrossEntropy/(NPoints*LN(2)). - Zero if ensemble solves regression task. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlpeavgce( - mlpensemble ensemble, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Average error on the test set - -INPUT PARAMETERS: - Ensemble- ensemble - XY - test set - NPoints - test set size - -RESULT: - Its meaning for regression task is obvious. As for classification task -it means average error when estimating posterior probabilities. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlpeavgerror( - mlpensemble ensemble, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Average relative error on the test set - -INPUT PARAMETERS: - Ensemble- ensemble - XY - test set - NPoints - test set size - -RESULT: - Its meaning for regression task is obvious. As for classification task -it means average relative error when estimating posterior probabilities. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlpeavgrelerror( - mlpensemble ensemble, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Like MLPCreate0, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpecreate0( - ae_int_t nin, - ae_int_t nout, - ae_int_t ensemblesize, - mlpensemble& ensemble, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Like MLPCreate1, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpecreate1( - ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - ae_int_t ensemblesize, - mlpensemble& ensemble, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Like MLPCreate2, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpecreate2( - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t ensemblesize, - mlpensemble& ensemble, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Like MLPCreateB0, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpecreateb0( - ae_int_t nin, - ae_int_t nout, - double b, - double d, - ae_int_t ensemblesize, - mlpensemble& ensemble, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Like MLPCreateB1, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpecreateb1( - ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - double b, - double d, - ae_int_t ensemblesize, - mlpensemble& ensemble, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Like MLPCreateB2, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpecreateb2( - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - double b, - double d, - ae_int_t ensemblesize, - mlpensemble& ensemble, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Like MLPCreateC0, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpecreatec0( - ae_int_t nin, - ae_int_t nout, - ae_int_t ensemblesize, - mlpensemble& ensemble, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Like MLPCreateC1, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpecreatec1( - ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - ae_int_t ensemblesize, - mlpensemble& ensemble, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Like MLPCreateC2, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpecreatec2( - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t ensemblesize, - mlpensemble& ensemble, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Creates ensemble from network. Only network geometry is copied. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpecreatefromnetwork( - multilayerperceptron network, - ae_int_t ensemblesize, - mlpensemble& ensemble, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Like MLPCreateR0, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpecreater0( - ae_int_t nin, - ae_int_t nout, - double a, - double b, - ae_int_t ensemblesize, - mlpensemble& ensemble, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Like MLPCreateR1, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpecreater1( - ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - double a, - double b, - ae_int_t ensemblesize, - mlpensemble& ensemble, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Like MLPCreateR2, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpecreater2( - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - double a, - double b, - ae_int_t ensemblesize, - mlpensemble& ensemble, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Return normalization type (whether ensemble is SOFTMAX-normalized or not). - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -
bool alglib::mlpeissoftmax( - mlpensemble ensemble, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Procesing - -INPUT PARAMETERS: - Ensemble- neural networks ensemble - X - input vector, array[0..NIn-1]. - Y - (possibly) preallocated buffer; if size of Y is less than - NOut, it will be reallocated. If it is large enough, it - is NOT reallocated, so we can save some time on reallocation. - - -OUTPUT PARAMETERS: - Y - result. Regression estimate when solving regression task, - vector of posterior probabilities for classification task. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpeprocess( - mlpensemble ensemble, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -'interactive' variant of MLPEProcess for languages like Python which -support constructs like "Y = MLPEProcess(LM,X)" and interactive mode of the -interpreter - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpeprocessi( - mlpensemble ensemble, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Return ensemble properties (number of inputs and outputs). - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpeproperties( - mlpensemble ensemble, - ae_int_t& nin, - ae_int_t& nout, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Randomization of MLP ensemble - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlperandomize( - mlpensemble ensemble, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Relative classification error on the test set - -INPUT PARAMETERS: - Ensemble- ensemble - XY - test set - NPoints - test set size - -RESULT: - percent of incorrectly classified cases. - Works both for classifier betwork and for regression networks which -are used as classifiers. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlperelclserror( - mlpensemble ensemble, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -RMS error on the test set - -INPUT PARAMETERS: - Ensemble- ensemble - XY - test set - NPoints - test set size - -RESULT: - root mean square error. - Its meaning for regression task is obvious. As for classification task -RMS error means error when estimating posterior probabilities. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -
double alglib::mlpermserror( - mlpensemble ensemble, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -
void mlpeserialize(mlpensemble &obj, std::string &s_out); -void mlpeserialize(mlpensemble &obj, std::ostream &s_out); -
- -
-
/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -
void mlpeunserialize(const std::string &s_in, mlpensemble &obj); -void mlpeunserialize(const std::istream &s_in, mlpensemble &obj); -
- -
- -mlpcvreport
-mlpreport
-mlptrainer
- -mlpcontinuetraining
-mlpcreatetrainer
-mlpcreatetrainercls
-mlpebagginglbfgs
-mlpebagginglm
-mlpetraines
-mlpkfoldcv
-mlpkfoldcvlbfgs
-mlpkfoldcvlm
-mlpsetalgobatch
-mlpsetcond
-mlpsetdataset
-mlpsetdecay
-mlpsetsparsedataset
-mlpstarttraining
-mlptrainensemblees
-mlptraines
-mlptrainlbfgs
-mlptrainlm
-mlptrainnetwork
- - - - - - - - - - -
nn_cls2 Binary classification problem
nn_cls3 Multiclass classification problem
nn_crossvalidation Cross-validation
nn_ensembles_es Early stopping ensembles
nn_parallel Parallel training
nn_regr Regression problem with one output (2=>1)
nn_regr_n Regression problem with multiple outputs (2=>2)
nn_trainerobject Advanced example on trainer object
- -
-
/************************************************************************* -Cross-validation estimates of generalization error -*************************************************************************/ -
class mlpcvreport -{ - double relclserror; - double avgce; - double rmserror; - double avgerror; - double avgrelerror; -}; - -
- -
-
/************************************************************************* -Training report: - * RelCLSError - fraction of misclassified cases. - * AvgCE - acerage cross-entropy - * RMSError - root-mean-square error - * AvgError - average error - * AvgRelError - average relative error - * NGrad - number of gradient calculations - * NHess - number of Hessian calculations - * NCholesky - number of Cholesky decompositions - -NOTE 1: RelCLSError/AvgCE are zero on regression problems. - -NOTE 2: on classification problems RMSError/AvgError/AvgRelError contain - errors in prediction of posterior probabilities -*************************************************************************/ -
class mlpreport -{ - double relclserror; - double avgce; - double rmserror; - double avgerror; - double avgrelerror; - ae_int_t ngrad; - ae_int_t nhess; - ae_int_t ncholesky; -}; - -
- -
-
/************************************************************************* -Trainer object for neural network. - -You should not try to access fields of this object directly - use ALGLIB -functions to work with this object. -*************************************************************************/ -
class mlptrainer -{ -}; - -
- -
-
/************************************************************************* -IMPORTANT: this is an "expert" version of the MLPTrain() function. We do - not recommend you to use it unless you are pretty sure that you - need ability to monitor training progress. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -This function performs step-by-step training of the neural network. Here -"step-by-step" means that training starts with MLPStartTraining() call, -and then user subsequently calls MLPContinueTraining() to perform one more -iteration of the training. - -This function performs one more iteration of the training and returns -either True (training continues) or False (training stopped). In case True -was returned, Network weights are updated according to the current state -of the optimization progress. In case False was returned, no additional -updates is performed (previous update of the network weights moved us to -the final point, and no additional updates is needed). - -EXAMPLE: - > - > [initialize network and trainer object] - > - > MLPStartTraining(Trainer, Network, True) - > while MLPContinueTraining(Trainer, Network) do - > [visualize training progress] - > - -INPUT PARAMETERS: - S - trainer object - Network - neural network structure, which is used to store - current state of the training process. - -OUTPUT PARAMETERS: - Network - weights of the neural network are rewritten by the - current approximation. - -NOTE: this method uses sum-of-squares error function for training. - -NOTE: it is expected that trainer object settings are NOT changed during - step-by-step training, i.e. no one changes stopping criteria or - training set during training. It is possible and there is no defense - against such actions, but algorithm behavior in such cases is - undefined and can be unpredictable. - -NOTE: It is expected that Network is the same one which was passed to - MLPStartTraining() function. However, THIS function checks only - following: - * that number of network inputs is consistent with trainer object - settings - * that number of network outputs/classes is consistent with trainer - object settings - * that number of network weights is the same as number of weights in - the network passed to MLPStartTraining() function - Exception is thrown when these conditions are violated. - - It is also expected that you do not change state of the network on - your own - the only party who has right to change network during its - training is a trainer object. Any attempt to interfere with trainer - may lead to unpredictable results. - - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -
bool alglib::mlpcontinuetraining( - mlptrainer s, - multilayerperceptron network, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Creation of the network trainer object for regression networks - -INPUT PARAMETERS: - NIn - number of inputs, NIn>=1 - NOut - number of outputs, NOut>=1 - -OUTPUT PARAMETERS: - S - neural network trainer object. - This structure can be used to train any regression - network with NIn inputs and NOut outputs. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpcreatetrainer( - ae_int_t nin, - ae_int_t nout, - mlptrainer& s, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  [5]  [6]  

- -
-
/************************************************************************* -Creation of the network trainer object for classification networks - -INPUT PARAMETERS: - NIn - number of inputs, NIn>=1 - NClasses - number of classes, NClasses>=2 - -OUTPUT PARAMETERS: - S - neural network trainer object. - This structure can be used to train any classification - network with NIn inputs and NOut outputs. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpcreatetrainercls( - ae_int_t nin, - ae_int_t nclasses, - mlptrainer& s, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -Training neural networks ensemble using bootstrap aggregating (bagging). -L-BFGS algorithm is used as base training method. - -INPUT PARAMETERS: - Ensemble - model with initialized geometry - XY - training set - NPoints - training set size - Decay - weight decay coefficient, >=0.001 - Restarts - restarts, >0. - WStep - stopping criterion, same as in MLPTrainLBFGS - MaxIts - stopping criterion, same as in MLPTrainLBFGS - -OUTPUT PARAMETERS: - Ensemble - trained model - Info - return code: - * -8, if both WStep=0 and MaxIts=0 - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed - (NPoints<0, Restarts<1). - * 2, if task has been solved. - Rep - training report. - OOBErrors - out-of-bag generalization error estimate - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpebagginglbfgs( - mlpensemble ensemble, - real_2d_array xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - double wstep, - ae_int_t maxits, - ae_int_t& info, - mlpreport& rep, - mlpcvreport& ooberrors, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Training neural networks ensemble using bootstrap aggregating (bagging). -Modified Levenberg-Marquardt algorithm is used as base training method. - -INPUT PARAMETERS: - Ensemble - model with initialized geometry - XY - training set - NPoints - training set size - Decay - weight decay coefficient, >=0.001 - Restarts - restarts, >0. - -OUTPUT PARAMETERS: - Ensemble - trained model - Info - return code: - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed - (NPoints<0, Restarts<1). - * 2, if task has been solved. - Rep - training report. - OOBErrors - out-of-bag generalization error estimate - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpebagginglm( - mlpensemble ensemble, - real_2d_array xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - ae_int_t& info, - mlpreport& rep, - mlpcvreport& ooberrors, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Training neural networks ensemble using early stopping. - -INPUT PARAMETERS: - Ensemble - model with initialized geometry - XY - training set - NPoints - training set size - Decay - weight decay coefficient, >=0.001 - Restarts - restarts, >0. - -OUTPUT PARAMETERS: - Ensemble - trained model - Info - return code: - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed - (NPoints<0, Restarts<1). - * 6, if task has been solved. - Rep - training report. - OOBErrors - out-of-bag generalization error estimate - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpetraines( - mlpensemble ensemble, - real_2d_array xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - ae_int_t& info, - mlpreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function estimates generalization error using cross-validation on the -current dataset with current training settings. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - trainer object - Network - neural network. It must have same number of inputs and - output/classes as was specified during creation of the - trainer object. Network is not changed during cross- - validation and is not trained - it is used only as - representative of its architecture. I.e., we estimate - generalization properties of ARCHITECTURE, not some - specific network. - NRestarts - number of restarts, >=0: - * NRestarts>0 means that for each cross-validation - round specified number of random restarts is - performed, with best network being chosen after - training. - * NRestarts=0 is same as NRestarts=1 - FoldsCount - number of folds in k-fold cross-validation: - * 2<=FoldsCount<=size of dataset - * recommended value: 10. - * values larger than dataset size will be silently - truncated down to dataset size - -OUTPUT PARAMETERS: - Rep - structure which contains cross-validation estimates: - * Rep.RelCLSError - fraction of misclassified cases. - * Rep.AvgCE - acerage cross-entropy - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average error - * Rep.AvgRelError - average relative error - -NOTE: when no dataset was specified with MLPSetDataset/SetSparseDataset(), - or subset with only one point was given, zeros are returned as - estimates. - -NOTE: this method performs FoldsCount cross-validation rounds, each one - with NRestarts random starts. Thus, FoldsCount*NRestarts networks - are trained in total. - -NOTE: Rep.RelCLSError/Rep.AvgCE are zero on regression problems. - -NOTE: on classification problems Rep.RMSError/Rep.AvgError/Rep.AvgRelError - contain errors in prediction of posterior probabilities. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpkfoldcv( - mlptrainer s, - multilayerperceptron network, - ae_int_t nrestarts, - ae_int_t foldscount, - mlpreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -Cross-validation estimate of generalization error. - -Base algorithm - L-BFGS. - -INPUT PARAMETERS: - Network - neural network with initialized geometry. Network is - not changed during cross-validation - it is used only - as a representative of its architecture. - XY - training set. - SSize - training set size - Decay - weight decay, same as in MLPTrainLBFGS - Restarts - number of restarts, >0. - restarts are counted for each partition separately, so - total number of restarts will be Restarts*FoldsCount. - WStep - stopping criterion, same as in MLPTrainLBFGS - MaxIts - stopping criterion, same as in MLPTrainLBFGS - FoldsCount - number of folds in k-fold cross-validation, - 2<=FoldsCount<=SSize. - recommended value: 10. - -OUTPUT PARAMETERS: - Info - return code, same as in MLPTrainLBFGS - Rep - report, same as in MLPTrainLM/MLPTrainLBFGS - CVRep - generalization error estimates - - -- ALGLIB -- - Copyright 09.12.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpkfoldcvlbfgs( - multilayerperceptron network, - real_2d_array xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - double wstep, - ae_int_t maxits, - ae_int_t foldscount, - ae_int_t& info, - mlpreport& rep, - mlpcvreport& cvrep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Cross-validation estimate of generalization error. - -Base algorithm - Levenberg-Marquardt. - -INPUT PARAMETERS: - Network - neural network with initialized geometry. Network is - not changed during cross-validation - it is used only - as a representative of its architecture. - XY - training set. - SSize - training set size - Decay - weight decay, same as in MLPTrainLBFGS - Restarts - number of restarts, >0. - restarts are counted for each partition separately, so - total number of restarts will be Restarts*FoldsCount. - FoldsCount - number of folds in k-fold cross-validation, - 2<=FoldsCount<=SSize. - recommended value: 10. - -OUTPUT PARAMETERS: - Info - return code, same as in MLPTrainLBFGS - Rep - report, same as in MLPTrainLM/MLPTrainLBFGS - CVRep - generalization error estimates - - -- ALGLIB -- - Copyright 09.12.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpkfoldcvlm( - multilayerperceptron network, - real_2d_array xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - ae_int_t foldscount, - ae_int_t& info, - mlpreport& rep, - mlpcvreport& cvrep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets training algorithm: batch training using L-BFGS will be -used. - -This algorithm: -* the most robust for small-scale problems, but may be too slow for large - scale ones. -* perfoms full pass through the dataset before performing step -* uses conditions specified by MLPSetCond() for stopping -* is default one used by trainer object - -INPUT PARAMETERS: - S - trainer object - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpsetalgobatch( - mlptrainer s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets stopping criteria for the optimizer. - -INPUT PARAMETERS: - S - trainer object - WStep - stopping criterion. Algorithm stops if step size is - less than WStep. Recommended value - 0.01. Zero step - size means stopping after MaxIts iterations. - WStep>=0. - MaxIts - stopping criterion. Algorithm stops after MaxIts - epochs (full passes over entire dataset). Zero MaxIts - means stopping when step is sufficiently small. - MaxIts>=0. - -NOTE: by default, WStep=0.005 and MaxIts=0 are used. These values are also - used when MLPSetCond() is called with WStep=0 and MaxIts=0. - -NOTE: these stopping criteria are used for all kinds of neural training - - from "conventional" networks to early stopping ensembles. When used - for "conventional" networks, they are used as the only stopping - criteria. When combined with early stopping, they used as ADDITIONAL - stopping criteria which can terminate early stopping algorithm. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpsetcond( - mlptrainer s, - double wstep, - ae_int_t maxits, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets "current dataset" of the trainer object to one passed -by user. - -INPUT PARAMETERS: - S - trainer object - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. - NPoints - points count, >=0. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -datasetformat is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpsetdataset( - mlptrainer s, - real_2d_array xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  [5]  [6]  [7]  [8]  

- -
-
/************************************************************************* -This function sets weight decay coefficient which is used for training. - -INPUT PARAMETERS: - S - trainer object - Decay - weight decay coefficient, >=0. Weight decay term - 'Decay*||Weights||^2' is added to error function. If - you don't know what Decay to choose, use 1.0E-3. - Weight decay can be set to zero, in this case network - is trained without weight decay. - -NOTE: by default network uses some small nonzero value for weight decay. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpsetdecay( - mlptrainer s, - double decay, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets "current dataset" of the trainer object to one passed -by user (sparse matrix is used to store dataset). - -INPUT PARAMETERS: - S - trainer object - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Any sparse storage format can be used: - Hash-table, CRS... - NPoints - points count, >=0 - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -datasetformat is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpsetsparsedataset( - mlptrainer s, - sparsematrix xy, - ae_int_t npoints, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -IMPORTANT: this is an "expert" version of the MLPTrain() function. We do - not recommend you to use it unless you are pretty sure that you - need ability to monitor training progress. - -This function performs step-by-step training of the neural network. Here -"step-by-step" means that training starts with MLPStartTraining() call, -and then user subsequently calls MLPContinueTraining() to perform one more -iteration of the training. - -After call to this function trainer object remembers network and is ready -to train it. However, no training is performed until first call to -MLPContinueTraining() function. Subsequent calls to MLPContinueTraining() -will advance training progress one iteration further. - -EXAMPLE: - > - > ...initialize network and trainer object.... - > - > MLPStartTraining(Trainer, Network, True) - > while MLPContinueTraining(Trainer, Network) do - > ...visualize training progress... - > - -INPUT PARAMETERS: - S - trainer object - Network - neural network. It must have same number of inputs and - output/classes as was specified during creation of the - trainer object. - RandomStart - randomize network before training or not: - * True means that network is randomized and its - initial state (one which was passed to the trainer - object) is lost. - * False means that training is started from the - current state of the network - -OUTPUT PARAMETERS: - Network - neural network which is ready to training (weights are - initialized, preprocessor is initialized using current - training set) - -NOTE: this method uses sum-of-squares error function for training. - -NOTE: it is expected that trainer object settings are NOT changed during - step-by-step training, i.e. no one changes stopping criteria or - training set during training. It is possible and there is no defense - against such actions, but algorithm behavior in such cases is - undefined and can be unpredictable. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlpstarttraining( - mlptrainer s, - multilayerperceptron network, - bool randomstart, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function trains neural network ensemble passed to this function using -current dataset and early stopping training algorithm. Each early stopping -round performs NRestarts random restarts (thus, EnsembleSize*NRestarts -training rounds is performed in total). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - trainer object; - Ensemble - neural network ensemble. It must have same number of - inputs and outputs/classes as was specified during - creation of the trainer object. - NRestarts - number of restarts, >=0: - * NRestarts>0 means that specified number of random - restarts are performed during each ES round; - * NRestarts=0 is silently replaced by 1. - -OUTPUT PARAMETERS: - Ensemble - trained ensemble; - Rep - it contains all type of errors. - -NOTE: this training method uses BOTH early stopping and weight decay! So, - you should select weight decay before starting training just as you - select it before training "conventional" networks. - -NOTE: when no dataset was specified with MLPSetDataset/SetSparseDataset(), - or single-point dataset was passed, ensemble is filled by zero - values. - -NOTE: this method uses sum-of-squares error function for training. - - -- ALGLIB -- - Copyright 22.08.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlptrainensemblees( - mlptrainer s, - mlpensemble ensemble, - ae_int_t nrestarts, - mlpreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -Neural network training using early stopping (base algorithm - L-BFGS with -regularization). - -INPUT PARAMETERS: - Network - neural network with initialized geometry - TrnXY - training set - TrnSize - training set size, TrnSize>0 - ValXY - validation set - ValSize - validation set size, ValSize>0 - Decay - weight decay constant, >=0.001 - Decay term 'Decay*||Weights||^2' is added to error - function. - If you don't know what Decay to choose, use 0.001. - Restarts - number of restarts, either: - * strictly positive number - algorithm make specified - number of restarts from random position. - * -1, in which case algorithm makes exactly one run - from the initial state of the network (no randomization). - If you don't know what Restarts to choose, choose one - one the following: - * -1 (deterministic start) - * +1 (one random restart) - * +5 (moderate amount of random restarts) - -OUTPUT PARAMETERS: - Network - trained neural network. - Info - return code: - * -2, if there is a point with class number - outside of [0..NOut-1]. - * -1, if wrong parameters specified - (NPoints<0, Restarts<1, ...). - * 2, task has been solved, stopping criterion met - - sufficiently small step size. Not expected (we - use EARLY stopping) but possible and not an - error. - * 6, task has been solved, stopping criterion met - - increasing of validation set error. - Rep - training report - -NOTE: - -Algorithm stops if validation set error increases for a long enough or -step size is small enought (there are task where validation set may -decrease for eternity). In any case solution returned corresponds to the -minimum of validation set error. - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlptraines( - multilayerperceptron network, - real_2d_array trnxy, - ae_int_t trnsize, - real_2d_array valxy, - ae_int_t valsize, - double decay, - ae_int_t restarts, - ae_int_t& info, - mlpreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Neural network training using L-BFGS algorithm with regularization. -Subroutine trains neural network with restarts from random positions. -Algorithm is well suited for problems of any dimensionality (memory -requirements and step complexity are linear by weights number). - -INPUT PARAMETERS: - Network - neural network with initialized geometry - XY - training set - NPoints - training set size - Decay - weight decay constant, >=0.001 - Decay term 'Decay*||Weights||^2' is added to error - function. - If you don't know what Decay to choose, use 0.001. - Restarts - number of restarts from random position, >0. - If you don't know what Restarts to choose, use 2. - WStep - stopping criterion. Algorithm stops if step size is - less than WStep. Recommended value - 0.01. Zero step - size means stopping after MaxIts iterations. - MaxIts - stopping criterion. Algorithm stops after MaxIts - iterations (NOT gradient calculations). Zero MaxIts - means stopping when step is sufficiently small. - -OUTPUT PARAMETERS: - Network - trained neural network. - Info - return code: - * -8, if both WStep=0 and MaxIts=0 - * -2, if there is a point with class number - outside of [0..NOut-1]. - * -1, if wrong parameters specified - (NPoints<0, Restarts<1). - * 2, if task has been solved. - Rep - training report - - -- ALGLIB -- - Copyright 09.12.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlptrainlbfgs( - multilayerperceptron network, - real_2d_array xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - double wstep, - ae_int_t maxits, - ae_int_t& info, - mlpreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Neural network training using modified Levenberg-Marquardt with exact -Hessian calculation and regularization. Subroutine trains neural network -with restarts from random positions. Algorithm is well suited for small -and medium scale problems (hundreds of weights). - -INPUT PARAMETERS: - Network - neural network with initialized geometry - XY - training set - NPoints - training set size - Decay - weight decay constant, >=0.001 - Decay term 'Decay*||Weights||^2' is added to error - function. - If you don't know what Decay to choose, use 0.001. - Restarts - number of restarts from random position, >0. - If you don't know what Restarts to choose, use 2. - -OUTPUT PARAMETERS: - Network - trained neural network. - Info - return code: - * -9, if internal matrix inverse subroutine failed - * -2, if there is a point with class number - outside of [0..NOut-1]. - * -1, if wrong parameters specified - (NPoints<0, Restarts<1). - * 2, if task has been solved. - Rep - training report - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlptrainlm( - multilayerperceptron network, - real_2d_array xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - ae_int_t& info, - mlpreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function trains neural network passed to this function, using current -dataset (one which was passed to MLPSetDataset() or MLPSetSparseDataset()) -and current training settings. Training from NRestarts random starting -positions is performed, best network is chosen. - -Training is performed using current training algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - trainer object - Network - neural network. It must have same number of inputs and - output/classes as was specified during creation of the - trainer object. - NRestarts - number of restarts, >=0: - * NRestarts>0 means that specified number of random - restarts are performed, best network is chosen after - training - * NRestarts=0 means that current state of the network - is used for training. - -OUTPUT PARAMETERS: - Network - trained network - -NOTE: when no dataset was specified with MLPSetDataset/SetSparseDataset(), - network is filled by zero values. Same behavior for functions - MLPStartTraining and MLPContinueTraining. - -NOTE: this method uses sum-of-squares error function for training. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::mlptrainnetwork( - mlptrainer s, - multilayerperceptron network, - ae_int_t nrestarts, - mlpreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  [5]  [6]  

- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // Suppose that we want to classify numbers as positive (class 0) and negative
-    // (class 1). We have training set which includes several strictly positive
-    // or negative numbers - and zero.
-    //
-    // The problem is that we are not sure how to classify zero, so from time to
-    // time we mark it as positive or negative (with equal probability). Other
-    // numbers are marked in pure deterministic setting. How will neural network
-    // cope with such classification task?
-    //
-    // NOTE: we use network with excessive amount of neurons, which guarantees
-    //       almost exact reproduction of the training set. Generalization ability
-    //       of such network is rather low, but we are not concerned with such
-    //       questions in this basic demo.
-    //
-    mlptrainer trn;
-    multilayerperceptron network;
-    mlpreport rep;
-    real_1d_array x = "[0]";
-    real_1d_array y = "[0,0]";
-
-    //
-    // Training set. One row corresponds to one record [A => class(A)].
-    //
-    // Classes are denoted by numbers from 0 to 1, where 0 corresponds to positive
-    // numbers and 1 to negative numbers.
-    //
-    // [ +1  0]
-    // [ +2  0]
-    // [ -1  1]
-    // [ -2  1]
-    // [  0  0]   !! sometimes we classify 0 as positive, sometimes as negative
-    // [  0  1]   !!
-    //
-    real_2d_array xy = "[[+1,0],[+2,0],[-1,1],[-2,1],[0,0],[0,1]]";
-
-    //
-    //
-    // When we solve classification problems, everything is slightly different from
-    // the regression ones:
-    //
-    // 1. Network is created. Because we solve classification problem, we use
-    //    mlpcreatec1() function instead of mlpcreate1(). This function creates
-    //    classifier network with SOFTMAX-normalized outputs. This network returns
-    //    vector of class membership probabilities which are normalized to be
-    //    non-negative and sum to 1.0
-    //
-    // 2. We use mlpcreatetrainercls() function instead of mlpcreatetrainer() to
-    //    create trainer object. Trainer object process dataset and neural network
-    //    slightly differently to account for specifics of the classification
-    //    problems.
-    //
-    // 3. Dataset is attached to trainer object. Note that dataset format is slightly
-    //    different from one used for regression.
-    //
-    mlpcreatetrainercls(1, 2, trn);
-    mlpcreatec1(1, 5, 2, network);
-    mlpsetdataset(trn, xy, 6);
-
-    //
-    // Network is trained with 5 restarts from random positions
-    //
-    mlptrainnetwork(trn, network, 5, rep);
-
-    //
-    // Test our neural network on strictly positive and strictly negative numbers.
-    //
-    // IMPORTANT! Classifier network returns class membership probabilities instead
-    // of class indexes. Network returns two values (probabilities) instead of one
-    // (class index).
-    //
-    // Thus, for +1 we expect to get [P0,P1] = [1,0], where P0 is probability that
-    // number is positive (belongs to class 0), and P1 is probability that number
-    // is negative (belongs to class 1).
-    //
-    // For -1 we expect to get [P0,P1] = [0,1]
-    //
-    // Following properties are guaranteed by network architecture:
-    // * P0>=0, P1>=0   non-negativity
-    // * P0+P1=1        normalization
-    //
-    x = "[1]";
-    mlpprocess(network, x, y);
-    printf("%s\n", y.tostring(1).c_str()); // EXPECTED: [1.000,0.000]
-    x = "[-1]";
-    mlpprocess(network, x, y);
-    printf("%s\n", y.tostring(1).c_str()); // EXPECTED: [0.000,1.000]
-
-    //
-    // But what our network will return for 0, which is between classes 0 and 1?
-    //
-    // In our dataset it has two different marks assigned (class 0 AND class 1).
-    // So network will return something average between class 0 and class 1:
-    //     0 => [0.5, 0.5]
-    //
-    x = "[0]";
-    mlpprocess(network, x, y);
-    printf("%s\n", y.tostring(1).c_str()); // EXPECTED: [0.500,0.500]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // Suppose that we want to classify numbers as positive (class 0) and negative
-    // (class 1). We also have one more class for zero (class 2).
-    //
-    // NOTE: we use network with excessive amount of neurons, which guarantees
-    //       almost exact reproduction of the training set. Generalization ability
-    //       of such network is rather low, but we are not concerned with such
-    //       questions in this basic demo.
-    //
-    mlptrainer trn;
-    multilayerperceptron network;
-    mlpreport rep;
-    real_1d_array x = "[0]";
-    real_1d_array y = "[0,0,0]";
-
-    //
-    // Training set. One row corresponds to one record [A => class(A)].
-    //
-    // Classes are denoted by numbers from 0 to 2, where 0 corresponds to positive
-    // numbers, 1 to negative numbers, 2 to zero
-    //
-    // [ +1  0]
-    // [ +2  0]
-    // [ -1  1]
-    // [ -2  1]
-    // [  0  2]
-    //
-    real_2d_array xy = "[[+1,0],[+2,0],[-1,1],[-2,1],[0,2]]";
-
-    //
-    //
-    // When we solve classification problems, everything is slightly different from
-    // the regression ones:
-    //
-    // 1. Network is created. Because we solve classification problem, we use
-    //    mlpcreatec1() function instead of mlpcreate1(). This function creates
-    //    classifier network with SOFTMAX-normalized outputs. This network returns
-    //    vector of class membership probabilities which are normalized to be
-    //    non-negative and sum to 1.0
-    //
-    // 2. We use mlpcreatetrainercls() function instead of mlpcreatetrainer() to
-    //    create trainer object. Trainer object process dataset and neural network
-    //    slightly differently to account for specifics of the classification
-    //    problems.
-    //
-    // 3. Dataset is attached to trainer object. Note that dataset format is slightly
-    //    different from one used for regression.
-    //
-    mlpcreatetrainercls(1, 3, trn);
-    mlpcreatec1(1, 5, 3, network);
-    mlpsetdataset(trn, xy, 5);
-
-    //
-    // Network is trained with 5 restarts from random positions
-    //
-    mlptrainnetwork(trn, network, 5, rep);
-
-    //
-    // Test our neural network on strictly positive and strictly negative numbers.
-    //
-    // IMPORTANT! Classifier network returns class membership probabilities instead
-    // of class indexes. Network returns three values (probabilities) instead of one
-    // (class index).
-    //
-    // Thus, for +1 we expect to get [P0,P1,P2] = [1,0,0],
-    // for -1 we expect to get [P0,P1,P2] = [0,1,0],
-    // and for 0 we will get [P0,P1,P2] = [0,0,1].
-    //
-    // Following properties are guaranteed by network architecture:
-    // * P0>=0, P1>=0, P2>=0    non-negativity
-    // * P0+P1+P2=1             normalization
-    //
-    x = "[1]";
-    mlpprocess(network, x, y);
-    printf("%s\n", y.tostring(1).c_str()); // EXPECTED: [1.000,0.000,0.000]
-    x = "[-1]";
-    mlpprocess(network, x, y);
-    printf("%s\n", y.tostring(1).c_str()); // EXPECTED: [0.000,1.000,0.000]
-    x = "[0]";
-    mlpprocess(network, x, y);
-    printf("%s\n", y.tostring(1).c_str()); // EXPECTED: [0.000,0.000,1.000]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example shows how to perform cross-validation with ALGLIB
-    //
-    mlptrainer trn;
-    multilayerperceptron network;
-    mlpreport rep;
-
-    //
-    // Training set: f(x)=1/(x^2+1)
-    // One row corresponds to one record [x,f(x)]
-    //
-    real_2d_array xy = "[[-2.0,0.2],[-1.6,0.3],[-1.3,0.4],[-1,0.5],[-0.6,0.7],[-0.3,0.9],[0,1],[2.0,0.2],[1.6,0.3],[1.3,0.4],[1,0.5],[0.6,0.7],[0.3,0.9]]";
-
-    //
-    // Trainer object is created.
-    // Dataset is attached to trainer object.
-    //
-    // NOTE: it is not good idea to perform cross-validation on sample
-    //       as small as ours (13 examples). It is done for demonstration
-    //       purposes only. Generalization error estimates won't be
-    //       precise enough for practical purposes.
-    //
-    mlpcreatetrainer(1, 1, trn);
-    mlpsetdataset(trn, xy, 13);
-
-    //
-    // The key property of the cross-validation is that it estimates
-    // generalization properties of neural ARCHITECTURE. It does NOT
-    // estimates generalization error of some specific network which
-    // is passed to the k-fold CV routine.
-    //
-    // In our example we create 1x4x1 neural network and pass it to
-    // CV routine without training it. Original state of the network
-    // is not used for cross-validation - each round is restarted from
-    // random initial state. Only geometry of network matters.
-    //
-    // We perform 5 restarts from different random positions for each
-    // of the 10 cross-validation rounds.
-    //
-    mlpcreate1(1, 4, 1, network);
-    mlpkfoldcv(trn, network, 5, 10, rep);
-
-    //
-    // Cross-validation routine stores estimates of the generalization
-    // error to MLP report structure. You may examine its fields and
-    // see estimates of different errors (RMS, CE, Avg).
-    //
-    // Because cross-validation is non-deterministic, in our manual we
-    // can not say what values will be stored to rep after call to
-    // mlpkfoldcv(). Every CV round will return slightly different
-    // estimates.
-    //
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example shows how to train early stopping ensebles.
-    //
-    mlptrainer trn;
-    mlpensemble ensemble;
-    mlpreport rep;
-
-    //
-    // Training set: f(x)=1/(x^2+1)
-    // One row corresponds to one record [x,f(x)]
-    //
-    real_2d_array xy = "[[-2.0,0.2],[-1.6,0.3],[-1.3,0.4],[-1,0.5],[-0.6,0.7],[-0.3,0.9],[0,1],[2.0,0.2],[1.6,0.3],[1.3,0.4],[1,0.5],[0.6,0.7],[0.3,0.9]]";
-
-    //
-    // Trainer object is created.
-    // Dataset is attached to trainer object.
-    //
-    // NOTE: it is not good idea to use early stopping ensemble on sample
-    //       as small as ours (13 examples). It is done for demonstration
-    //       purposes only. Ensemble training algorithm won't find good
-    //       solution on such small sample.
-    //
-    mlpcreatetrainer(1, 1, trn);
-    mlpsetdataset(trn, xy, 13);
-
-    //
-    // Ensemble is created and trained. Each of 50 network is trained
-    // with 5 restarts.
-    //
-    mlpecreate1(1, 4, 1, 50, ensemble);
-    mlptrainensemblees(trn, ensemble, 5, rep);
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example shows how to use parallel functionality of ALGLIB.
-    // We generate simple 1-dimensional regression problem and show how
-    // to use parallel training, parallel cross-validation, parallel
-    // training of neural ensembles.
-    //
-    // We assume that you already know how to use ALGLIB in serial mode
-    // and concentrate on its parallel capabilities.
-    //
-    // NOTE: it is not good idea to use parallel features on sample as small
-    //       as ours (13 examples). It is done only for demonstration purposes.
-    //
-    mlptrainer trn;
-    multilayerperceptron network;
-    mlpensemble ensemble;
-    mlpreport rep;
-    real_2d_array xy = "[[-2.0,0.2],[-1.6,0.3],[-1.3,0.4],[-1,0.5],[-0.6,0.7],[-0.3,0.9],[0,1],[2.0,0.2],[1.6,0.3],[1.3,0.4],[1,0.5],[0.6,0.7],[0.3,0.9]]";
-    mlpcreatetrainer(1, 1, trn);
-    mlpsetdataset(trn, xy, 13);
-    mlpcreate1(1, 4, 1, network);
-    mlpecreate1(1, 4, 1, 50, ensemble);
-
-    //
-    // Below we demonstrate how to perform:
-    // * parallel training of individual networks
-    // * parallel cross-validation
-    // * parallel training of neural ensembles
-    //
-    // In order to use multithreading, you have to:
-    // 1) Install SMP edition of ALGLIB.
-    // 2) This step is specific for C++ users: you should activate OS-specific
-    //    capabilities of ALGLIB by defining AE_OS=AE_POSIX (for *nix systems)
-    //    or AE_OS=AE_WINDOWS (for Windows systems).
-    //    C# users do not have to perform this step because C# programs are
-    //    portable across different systems without OS-specific tuning.
-    // 3) Tell ALGLIB that you want it to use multithreading by means of
-    //    setnworkers() call:
-    //          * alglib::setnworkers(0)  = use all cores
-    //          * alglib::setnworkers(-1) = leave one core unused
-    //          * alglib::setnworkers(-2) = leave two cores unused
-    //          * alglib::setnworkers(+2) = use 2 cores (even if you have more)
-    //    During runtime ALGLIB will automatically determine whether it is
-    //    feasible to start worker threads and split your task between cores.
-    //
-    alglib::setnworkers(+2);
-
-    //
-    // First, we perform parallel training of individual network with 5
-    // restarts from random positions. These 5 rounds of  training  are
-    // executed in parallel manner,  with  best  network  chosen  after
-    // training.
-    //
-    // ALGLIB can use additional way to speed up computations -  divide
-    // dataset   into   smaller   subsets   and   process these subsets
-    // simultaneously. It allows us  to  efficiently  parallelize  even
-    // single training round. This operation is performed automatically
-    // for large datasets, but our toy dataset is too small.
-    //
-    mlptrainnetwork(trn, network, 5, rep);
-
-    //
-    // Then, we perform parallel 10-fold cross-validation, with 5 random
-    // restarts per each CV round. I.e., 5*10=50  networks  are trained
-    // in total. All these operations can be parallelized.
-    //
-    // NOTE: again, ALGLIB can parallelize  calculation   of   gradient
-    //       over entire dataset - but our dataset is too small.
-    //
-    mlpkfoldcv(trn, network, 5, 10, rep);
-
-    //
-    // Finally, we train early stopping ensemble of 50 neural networks,
-    // each  of them is trained with 5 random restarts. I.e.,  5*50=250
-    // networks aretrained in total.
-    //
-    mlptrainensemblees(trn, ensemble, 5, rep);
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // The very simple example on neural network: network is trained to reproduce
-    // small 2x2 multiplication table.
-    //
-    // NOTE: we use network with excessive amount of neurons, which guarantees
-    //       almost exact reproduction of the training set. Generalization ability
-    //       of such network is rather low, but we are not concerned with such
-    //       questions in this basic demo.
-    //
-    mlptrainer trn;
-    multilayerperceptron network;
-    mlpreport rep;
-
-    //
-    // Training set:
-    // * one row corresponds to one record A*B=C in the multiplication table
-    // * first two columns store A and B, last column stores C
-    //
-    // [1 * 1 = 1]
-    // [1 * 2 = 2]
-    // [2 * 1 = 2]
-    // [2 * 2 = 4]
-    //
-    real_2d_array xy = "[[1,1,1],[1,2,2],[2,1,2],[2,2,4]]";
-
-    //
-    // Network is created.
-    // Trainer object is created.
-    // Dataset is attached to trainer object.
-    //
-    mlpcreatetrainer(2, 1, trn);
-    mlpcreate1(2, 5, 1, network);
-    mlpsetdataset(trn, xy, 4);
-
-    //
-    // Network is trained with 5 restarts from random positions
-    //
-    mlptrainnetwork(trn, network, 5, rep);
-
-    //
-    // 2*2=?
-    //
-    real_1d_array x = "[2,2]";
-    real_1d_array y = "[0]";
-    mlpprocess(network, x, y);
-    printf("%s\n", y.tostring(1).c_str()); // EXPECTED: [4.000]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // Network with 2 inputs and 2 outputs is trained to reproduce vector function:
-    //     (x0,x1) => (x0+x1, x0*x1)
-    //
-    // Informally speaking, we want neural network to simultaneously calculate
-    // both sum of two numbers and their product.
-    //
-    // NOTE: we use network with excessive amount of neurons, which guarantees
-    //       almost exact reproduction of the training set. Generalization ability
-    //       of such network is rather low, but we are not concerned with such
-    //       questions in this basic demo.
-    //
-    mlptrainer trn;
-    multilayerperceptron network;
-    mlpreport rep;
-
-    //
-    // Training set. One row corresponds to one record [A,B,A+B,A*B].
-    //
-    // [ 1   1  1+1  1*1 ]
-    // [ 1   2  1+2  1*2 ]
-    // [ 2   1  2+1  2*1 ]
-    // [ 2   2  2+2  2*2 ]
-    //
-    real_2d_array xy = "[[1,1,2,1],[1,2,3,2],[2,1,3,2],[2,2,4,4]]";
-
-    //
-    // Network is created.
-    // Trainer object is created.
-    // Dataset is attached to trainer object.
-    //
-    mlpcreatetrainer(2, 2, trn);
-    mlpcreate1(2, 5, 2, network);
-    mlpsetdataset(trn, xy, 4);
-
-    //
-    // Network is trained with 5 restarts from random positions
-    //
-    mlptrainnetwork(trn, network, 5, rep);
-
-    //
-    // 2+1=?
-    // 2*1=?
-    //
-    real_1d_array x = "[2,1]";
-    real_1d_array y = "[0,0]";
-    mlpprocess(network, x, y);
-    printf("%s\n", y.tostring(1).c_str()); // EXPECTED: [3.000,2.000]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // Trainer object is used to train network. It stores dataset, training settings,
-    // and other information which is NOT part of neural network. You should use
-    // trainer object as follows:
-    // (1) you create trainer object and specify task type (classification/regression)
-    //     and number of inputs/outputs
-    // (2) you add dataset to the trainer object
-    // (3) you may change training settings (stopping criteria or weight decay)
-    // (4) finally, you may train one or more networks
-    //
-    // You may interleave stages 2...4 and repeat them many times. Trainer object
-    // remembers its internal state and can be used several times after its creation
-    // and initialization.
-    //
-    mlptrainer trn;
-
-    //
-    // Stage 1: object creation.
-    //
-    // We have to specify number of inputs and outputs. Trainer object can be used
-    // only for problems with same number of inputs/outputs as was specified during
-    // its creation.
-    //
-    // In case you want to train SOFTMAX-normalized network which solves classification
-    // problems,  you  must  use  another  function  to  create  trainer  object:
-    // mlpcreatetrainercls().
-    //
-    // Below we create trainer object which can be used to train regression networks
-    // with 2 inputs and 1 output.
-    //
-    mlpcreatetrainer(2, 1, trn);
-
-    //
-    // Stage 2: specification of the training set
-    //
-    // By default trainer object stores empty dataset. So to solve your non-empty problem
-    // you have to set dataset by passing to trainer dense or sparse matrix.
-    //
-    // One row of the matrix corresponds to one record A*B=C in the multiplication table.
-    // First two columns store A and B, last column stores C
-    //
-    //     [1 * 1 = 1]   [ 1 1 1 ]
-    //     [1 * 2 = 2]   [ 1 2 2 ]
-    //     [2 * 1 = 2] = [ 2 1 2 ]
-    //     [2 * 2 = 4]   [ 2 2 4 ]
-    //
-    real_2d_array xy = "[[1,1,1],[1,2,2],[2,1,2],[2,2,4]]";
-    mlpsetdataset(trn, xy, 4);
-
-    //
-    // Stage 3: modification of the training parameters.
-    //
-    // You may modify parameters like weights decay or stopping criteria:
-    // * we set moderate weight decay
-    // * we choose iterations limit as stopping condition (another condition - step size -
-    //   is zero, which means than this condition is not active)
-    //
-    double wstep = 0.000;
-    ae_int_t maxits = 100;
-    mlpsetdecay(trn, 0.01);
-    mlpsetcond(trn, wstep, maxits);
-
-    //
-    // Stage 4: training.
-    //
-    // We will train several networks with different architecture using same trainer object.
-    // We may change training parameters or even dataset, so different networks are trained
-    // differently. But in this simple example we will train all networks with same settings.
-    //
-    // We create and train three networks:
-    // * network 1 has 2x1 architecture     (2 inputs, no hidden neurons, 1 output)
-    // * network 2 has 2x5x1 architecture   (2 inputs, 5 hidden neurons, 1 output)
-    // * network 3 has 2x5x5x1 architecture (2 inputs, two hidden layers, 1 output)
-    //
-    // NOTE: these networks solve regression problems. For classification problems you
-    //       should use mlpcreatec0/c1/c2 to create neural networks which have SOFTMAX-
-    //       normalized outputs.
-    //
-    multilayerperceptron net1;
-    multilayerperceptron net2;
-    multilayerperceptron net3;
-    mlpreport rep;
-
-    mlpcreate0(2, 1, net1);
-    mlpcreate1(2, 5, 1, net2);
-    mlpcreate2(2, 5, 5, 1, net3);
-
-    mlptrainnetwork(trn, net1, 5, rep);
-    mlptrainnetwork(trn, net2, 5, rep);
-    mlptrainnetwork(trn, net3, 5, rep);
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* -KD-tree object. -*************************************************************************/ -
class kdtree -{ -}; - -
- -
-
/************************************************************************* -Buffer object which is used to perform nearest neighbor requests in the -multithreaded mode (multiple threads working with same KD-tree object). - -This object should be created with KDTreeCreateRequestBuffer(). -*************************************************************************/ -
class kdtreerequestbuffer -{ -}; - -
- -
-
/************************************************************************* -KD-tree creation - -This subroutine creates KD-tree from set of X-values and optional Y-values - -INPUT PARAMETERS - XY - dataset, array[0..N-1,0..NX+NY-1]. - one row corresponds to one point. - first NX columns contain X-values, next NY (NY may be zero) - columns may contain associated Y-values - N - number of points, N>=0. - NX - space dimension, NX>=1. - NY - number of optional Y-values, NY>=0. - NormType- norm type: - * 0 denotes infinity-norm - * 1 denotes 1-norm - * 2 denotes 2-norm (Euclidean norm) - -OUTPUT PARAMETERS - KDT - KD-tree - - -NOTES - -1. KD-tree creation have O(N*logN) complexity and O(N*(2*NX+NY)) memory - requirements. -2. Although KD-trees may be used with any combination of N and NX, they - are more efficient than brute-force search only when N >> 4^NX. So they - are most useful in low-dimensional tasks (NX=2, NX=3). NX=1 is another - inefficient case, because simple binary search (without additional - structures) is much more efficient in such tasks than KD-trees. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::kdtreebuild( - real_2d_array xy, - ae_int_t nx, - ae_int_t ny, - ae_int_t normtype, - kdtree& kdt, - const xparams _params = alglib::xdefault); -void alglib::kdtreebuild( - real_2d_array xy, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - ae_int_t normtype, - kdtree& kdt, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -KD-tree creation - -This subroutine creates KD-tree from set of X-values, integer tags and -optional Y-values - -INPUT PARAMETERS - XY - dataset, array[0..N-1,0..NX+NY-1]. - one row corresponds to one point. - first NX columns contain X-values, next NY (NY may be zero) - columns may contain associated Y-values - Tags - tags, array[0..N-1], contains integer tags associated - with points. - N - number of points, N>=0 - NX - space dimension, NX>=1. - NY - number of optional Y-values, NY>=0. - NormType- norm type: - * 0 denotes infinity-norm - * 1 denotes 1-norm - * 2 denotes 2-norm (Euclidean norm) - -OUTPUT PARAMETERS - KDT - KD-tree - -NOTES - -1. KD-tree creation have O(N*logN) complexity and O(N*(2*NX+NY)) memory - requirements. -2. Although KD-trees may be used with any combination of N and NX, they - are more efficient than brute-force search only when N >> 4^NX. So they - are most useful in low-dimensional tasks (NX=2, NX=3). NX=1 is another - inefficient case, because simple binary search (without additional - structures) is much more efficient in such tasks than KD-trees. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::kdtreebuildtagged( - real_2d_array xy, - integer_1d_array tags, - ae_int_t nx, - ae_int_t ny, - ae_int_t normtype, - kdtree& kdt, - const xparams _params = alglib::xdefault); -void alglib::kdtreebuildtagged( - real_2d_array xy, - integer_1d_array tags, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - ae_int_t normtype, - kdtree& kdt, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function creates buffer structure which can be used to perform -parallel KD-tree requests. - -KD-tree subpackage provides two sets of request functions - ones which use -internal buffer of KD-tree object (these functions are single-threaded -because they use same buffer, which can not shared between threads), and -ones which use external buffer. - -This function is used to initialize external buffer. - -INPUT PARAMETERS - KDT - KD-tree which is associated with newly created buffer - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: KD-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use buffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -
void alglib::kdtreecreaterequestbuffer( - kdtree kdt, - kdtreerequestbuffer& buf, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -K-NN query: approximate K nearest neighbors - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: KDTreeTsQueryAKNN() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - X - point, array[0..NX-1]. - K - number of neighbors to return, K>=1 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - Eps - approximation factor, Eps>=0. eps-approximate nearest - neighbor is a neighbor whose distance from X is at - most (1+eps) times distance of true nearest neighbor. - -RESULT - number of actual neighbors found (either K or N, if K>N). - -NOTES - significant performance gain may be achieved only when Eps is is on - the order of magnitude of 1 or larger. - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -these results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() to get distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::kdtreequeryaknn( - kdtree kdt, - real_1d_array x, - ae_int_t k, - double eps, - const xparams _params = alglib::xdefault); -ae_int_t alglib::kdtreequeryaknn( - kdtree kdt, - real_1d_array x, - ae_int_t k, - bool selfmatch, - double eps, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Box query: all points within user-specified box. - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: KDTreeTsQueryBox() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - BoxMin - lower bounds, array[0..NX-1]. - BoxMax - upper bounds, array[0..NX-1]. - - -RESULT - number of actual neighbors found (in [0,N]). - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -these results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() returns zeros for this request - -NOTE: this particular query returns unordered results, because there is no - meaningful way of ordering points. Furthermore, no 'distance' is - associated with points - it is either INSIDE or OUTSIDE (so request - for distances will return zeros). - - -- ALGLIB -- - Copyright 14.05.2016 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::kdtreequerybox( - kdtree kdt, - real_1d_array boxmin, - real_1d_array boxmax, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -K-NN query: K nearest neighbors - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: KDTreeTsQueryKNN() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - X - point, array[0..NX-1]. - K - number of neighbors to return, K>=1 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of actual neighbors found (either K or N, if K>N). - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -these results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() to get distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::kdtreequeryknn( - kdtree kdt, - real_1d_array x, - ae_int_t k, - const xparams _params = alglib::xdefault); -ae_int_t alglib::kdtreequeryknn( - kdtree kdt, - real_1d_array x, - ae_int_t k, - bool selfmatch, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Distances from last query - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - kdtreetsqueryresultsdistances(). - -INPUT PARAMETERS - KDT - KD-tree - R - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - R - filled with distances (in corresponding norm) - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsTags() tag values - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::kdtreequeryresultsdistances( - kdtree kdt, - real_1d_array& r, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Distances from last query; 'interactive' variant for languages like Python -which support constructs like "R = KDTreeQueryResultsDistancesI(KDT)" -and interactive mode of interpreter. - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::kdtreequeryresultsdistancesi( - kdtree kdt, - real_1d_array& r, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Tags from last query - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - kdtreetsqueryresultstags(). - -INPUT PARAMETERS - KDT - KD-tree - Tags - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - Tags - filled with tags associated with points, - or, when no tags were supplied, with zeros - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::kdtreequeryresultstags( - kdtree kdt, - integer_1d_array& tags, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Tags from last query; 'interactive' variant for languages like Python -which support constructs like "Tags = KDTreeQueryResultsTagsI(KDT)" and -interactive mode of interpreter. - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::kdtreequeryresultstagsi( - kdtree kdt, - integer_1d_array& tags, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -X-values from last query. - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - kdtreetsqueryresultsx(). - -INPUT PARAMETERS - KDT - KD-tree - X - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - X - rows are filled with X-values - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsTags() tag values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::kdtreequeryresultsx( - kdtree kdt, - real_2d_array& x, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -X-values from last query; 'interactive' variant for languages like Python -which support constructs like "X = KDTreeQueryResultsXI(KDT)" and -interactive mode of interpreter. - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::kdtreequeryresultsxi( - kdtree kdt, - real_2d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -X- and Y-values from last query - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - kdtreetsqueryresultsxy(). - -INPUT PARAMETERS - KDT - KD-tree - XY - possibly pre-allocated buffer. If XY is too small to store - result, it is resized. If size(XY) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - XY - rows are filled with points: first NX columns with - X-values, next NY columns - with Y-values. - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsTags() tag values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::kdtreequeryresultsxy( - kdtree kdt, - real_2d_array& xy, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -XY-values from last query; 'interactive' variant for languages like Python -which support constructs like "XY = KDTreeQueryResultsXYI(KDT)" and -interactive mode of interpreter. - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::kdtreequeryresultsxyi( - kdtree kdt, - real_2d_array& xy, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -R-NN query: all points within R-sphere centered at X, ordered by distance -between point and X (by ascending). - -NOTE: it is also possible to perform undordered queries performed by means - of kdtreequeryrnnu() and kdtreetsqueryrnnu() functions. Such queries - are faster because we do not have to use heap structure for sorting. - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: kdtreetsqueryrnn() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -actual results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() to get distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::kdtreequeryrnn( - kdtree kdt, - real_1d_array x, - double r, - const xparams _params = alglib::xdefault); -ae_int_t alglib::kdtreequeryrnn( - kdtree kdt, - real_1d_array x, - double r, - bool selfmatch, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -R-NN query: all points within R-sphere centered at X, no ordering by -distance as undicated by "U" suffix (faster that ordered query, for large -queries - significantly faster). - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: kdtreetsqueryrnn() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -actual results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() to get distances - -As indicated by "U" suffix, this function returns unordered results. - - -- ALGLIB -- - Copyright 01.11.2018 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::kdtreequeryrnnu( - kdtree kdt, - real_1d_array x, - double r, - const xparams _params = alglib::xdefault); -ae_int_t alglib::kdtreequeryrnnu( - kdtree kdt, - real_1d_array x, - double r, - bool selfmatch, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -
void kdtreeserialize(kdtree &obj, std::string &s_out); -void kdtreeserialize(kdtree &obj, std::ostream &s_out); -
- -
-
/************************************************************************* -K-NN query: approximate K nearest neighbors, using thread-local buffer. - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - K - number of neighbors to return, K>=1 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - Eps - approximation factor, Eps>=0. eps-approximate nearest - neighbor is a neighbor whose distance from X is at - most (1+eps) times distance of true nearest neighbor. - -RESULT - number of actual neighbors found (either K or N, if K>N). - -NOTES - significant performance gain may be achieved only when Eps is is on - the order of magnitude of 1 or larger. - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::kdtreetsqueryaknn( - kdtree kdt, - kdtreerequestbuffer buf, - real_1d_array x, - ae_int_t k, - double eps, - const xparams _params = alglib::xdefault); -ae_int_t alglib::kdtreetsqueryaknn( - kdtree kdt, - kdtreerequestbuffer buf, - real_1d_array x, - ae_int_t k, - bool selfmatch, - double eps, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Box query: all points within user-specified box, using thread-local buffer. - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - BoxMin - lower bounds, array[0..NX-1]. - BoxMax - upper bounds, array[0..NX-1]. - -RESULT - number of actual neighbors found (in [0,N]). - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "ts" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() returns zeros for this query - -NOTE: this particular query returns unordered results, because there is no - meaningful way of ordering points. Furthermore, no 'distance' is - associated with points - it is either INSIDE or OUTSIDE (so request - for distances will return zeros). - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 14.05.2016 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::kdtreetsquerybox( - kdtree kdt, - kdtreerequestbuffer buf, - real_1d_array boxmin, - real_1d_array boxmax, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -K-NN query: K nearest neighbors, using external thread-local buffer. - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -INPUT PARAMETERS - KDT - kd-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - K - number of neighbors to return, K>=1 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of actual neighbors found (either K or N, if K>N). - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::kdtreetsqueryknn( - kdtree kdt, - kdtreerequestbuffer buf, - real_1d_array x, - ae_int_t k, - const xparams _params = alglib::xdefault); -ae_int_t alglib::kdtreetsqueryknn( - kdtree kdt, - kdtreerequestbuffer buf, - real_1d_array x, - ae_int_t k, - bool selfmatch, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Distances from last query associated with kdtreerequestbuffer object. - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - KDTreeTsqueryresultsdistances(). - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure. - R - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - R - filled with distances (in corresponding norm) - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsTags() tag values - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::kdtreetsqueryresultsdistances( - kdtree kdt, - kdtreerequestbuffer buf, - real_1d_array& r, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Tags from last query associated with kdtreerequestbuffer object. - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - KDTreeTsqueryresultstags(). - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure. - Tags - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - Tags - filled with tags associated with points, - or, when no tags were supplied, with zeros - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::kdtreetsqueryresultstags( - kdtree kdt, - kdtreerequestbuffer buf, - integer_1d_array& tags, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -X-values from last query associated with kdtreerequestbuffer object. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure. - X - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - X - rows are filled with X-values - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsTags() tag values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::kdtreetsqueryresultsx( - kdtree kdt, - kdtreerequestbuffer buf, - real_2d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -X- and Y-values from last query associated with kdtreerequestbuffer object. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure. - XY - possibly pre-allocated buffer. If XY is too small to store - result, it is resized. If size(XY) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - XY - rows are filled with points: first NX columns with - X-values, next NY columns - with Y-values. - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsTags() tag values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::kdtreetsqueryresultsxy( - kdtree kdt, - kdtreerequestbuffer buf, - real_2d_array& xy, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -R-NN query: all points within R-sphere centered at X, using external -thread-local buffer, sorted by distance between point and X (by ascending) - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -NOTE: it is also possible to perform undordered queries performed by means - of kdtreequeryrnnu() and kdtreetsqueryrnnu() functions. Such queries - are faster because we do not have to use heap structure for sorting. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::kdtreetsqueryrnn( - kdtree kdt, - kdtreerequestbuffer buf, - real_1d_array x, - double r, - const xparams _params = alglib::xdefault); -ae_int_t alglib::kdtreetsqueryrnn( - kdtree kdt, - kdtreerequestbuffer buf, - real_1d_array x, - double r, - bool selfmatch, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -R-NN query: all points within R-sphere centered at X, using external -thread-local buffer, no ordering by distance as undicated by "U" suffix -(faster that ordered query, for large queries - significantly faster). - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -As indicated by "U" suffix, this function returns unordered results. - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::kdtreetsqueryrnnu( - kdtree kdt, - kdtreerequestbuffer buf, - real_1d_array x, - double r, - const xparams _params = alglib::xdefault); -ae_int_t alglib::kdtreetsqueryrnnu( - kdtree kdt, - kdtreerequestbuffer buf, - real_1d_array x, - double r, - bool selfmatch, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -
void kdtreeunserialize(const std::string &s_in, kdtree &obj); -void kdtreeunserialize(const std::istream &s_in, kdtree &obj); -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "alglibmisc.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    real_2d_array a = "[[0,0],[0,1],[1,0],[1,1]]";
-    ae_int_t nx = 2;
-    ae_int_t ny = 0;
-    ae_int_t normtype = 2;
-    kdtree kdt;
-    real_1d_array x;
-    real_2d_array r = "[[]]";
-    ae_int_t k;
-    kdtreebuild(a, nx, ny, normtype, kdt);
-    x = "[-1,0]";
-    k = kdtreequeryknn(kdt, x, 1);
-    printf("%d\n", int(k)); // EXPECTED: 1
-    kdtreequeryresultsx(kdt, r);
-    printf("%s\n", r.tostring(1).c_str()); // EXPECTED: [[0,0]]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "alglibmisc.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    real_2d_array a = "[[0,0],[0,1],[1,0],[1,1]]";
-    ae_int_t nx = 2;
-    ae_int_t ny = 0;
-    ae_int_t normtype = 2;
-    kdtree kdt0;
-    kdtree kdt1;
-    std::string s;
-    real_1d_array x;
-    real_2d_array r0 = "[[]]";
-    real_2d_array r1 = "[[]]";
-
-    //
-    // Build tree and serialize it
-    //
-    kdtreebuild(a, nx, ny, normtype, kdt0);
-    alglib::kdtreeserialize(kdt0, s);
-    alglib::kdtreeunserialize(s, kdt1);
-
-    //
-    // Compare results from KNN queries
-    //
-    x = "[-1,0]";
-    kdtreequeryknn(kdt0, x, 1);
-    kdtreequeryresultsx(kdt0, r0);
-    kdtreequeryknn(kdt1, x, 1);
-    kdtreequeryresultsx(kdt1, r1);
-    printf("%s\n", r0.tostring(1).c_str()); // EXPECTED: [[0,0]]
-    printf("%s\n", r1.tostring(1).c_str()); // EXPECTED: [[0,0]]
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* - -*************************************************************************/ -
class nleqreport -{ - ae_int_t iterationscount; - ae_int_t nfunc; - ae_int_t njac; - ae_int_t terminationtype; -}; - -
- -
-
/************************************************************************* - -*************************************************************************/ -
class nleqstate -{ -}; - -
- -
-
/************************************************************************* - LEVENBERG-MARQUARDT-LIKE NONLINEAR SOLVER - -DESCRIPTION: -This algorithm solves system of nonlinear equations - F[0](x[0], ..., x[n-1]) = 0 - F[1](x[0], ..., x[n-1]) = 0 - ... - F[M-1](x[0], ..., x[n-1]) = 0 -with M/N do not necessarily coincide. Algorithm converges quadratically -under following conditions: - * the solution set XS is nonempty - * for some xs in XS there exist such neighbourhood N(xs) that: - * vector function F(x) and its Jacobian J(x) are continuously - differentiable on N - * ||F(x)|| provides local error bound on N, i.e. there exists such - c1, that ||F(x)||>c1*distance(x,XS) -Note that these conditions are much more weaker than usual non-singularity -conditions. For example, algorithm will converge for any affine function -F (whether its Jacobian singular or not). - - -REQUIREMENTS: -Algorithm will request following information during its operation: -* function vector F[] and Jacobian matrix at given point X -* value of merit function f(x)=F[0]^2(x)+...+F[M-1]^2(x) at given point X - - -USAGE: -1. User initializes algorithm state with NLEQCreateLM() call -2. User tunes solver parameters with NLEQSetCond(), NLEQSetStpMax() and - other functions -3. User calls NLEQSolve() function which takes algorithm state and - pointers (delegates, etc.) to callback functions which calculate merit - function value and Jacobian. -4. User calls NLEQResults() to get solution -5. Optionally, user may call NLEQRestartFrom() to solve another problem - with same parameters (N/M) but another starting point and/or another - function vector. NLEQRestartFrom() allows to reuse already initialized - structure. - - -INPUT PARAMETERS: - N - space dimension, N>1: - * if provided, only leading N elements of X are used - * if not provided, determined automatically from size of X - M - system size - X - starting point - - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -NOTES: -1. you may tune stopping conditions with NLEQSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use NLEQSetStpMax() function to bound algorithm's steps. -3. this algorithm is a slightly modified implementation of the method - described in 'Levenberg-Marquardt method for constrained nonlinear - equations with strong local convergence properties' by Christian Kanzow - Nobuo Yamashita and Masao Fukushima and further developed in 'On the - convergence of a New Levenberg-Marquardt Method' by Jin-yan Fan and - Ya-Xiang Yuan. - - - -- ALGLIB -- - Copyright 20.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::nleqcreatelm( - ae_int_t m, - real_1d_array x, - nleqstate& state, - const xparams _params = alglib::xdefault); -void alglib::nleqcreatelm( - ae_int_t n, - ae_int_t m, - real_1d_array x, - nleqstate& state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine restarts CG algorithm from new point. All optimization -parameters are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure used for reverse communication previously - allocated with MinCGCreate call. - X - new starting point. - BndL - new lower bounds - BndU - new upper bounds - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::nleqrestartfrom( - nleqstate state, - real_1d_array x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -NLEQ solver results - -INPUT PARAMETERS: - State - algorithm state. - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report: - * Rep.TerminationType completetion code: - * -4 ERROR: algorithm has converged to the - stationary point Xf which is local minimum of - f=F[0]^2+...+F[m-1]^2, but is not solution of - nonlinear system. - * 1 sqrt(f)<=EpsF. - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible - * Rep.IterationsCount contains iterations count - * NFEV countains number of function calculations - * ActiveConstraints contains number of active constraints - - -- ALGLIB -- - Copyright 20.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::nleqresults( - nleqstate state, - real_1d_array& x, - nleqreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -NLEQ solver results - -Buffered implementation of NLEQResults(), which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 20.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::nleqresultsbuf( - nleqstate state, - real_1d_array& x, - nleqreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets stopping conditions for the nonlinear solver - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsF - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition ||F||<=EpsF is satisfied - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsF=0 and MaxIts=0 simultaneously will lead to automatic -stopping criterion selection (small EpsF). - -NOTES: - - -- ALGLIB -- - Copyright 20.08.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::nleqsetcond( - nleqstate state, - double epsf, - ae_int_t maxits, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when target function contains exp() or other fast -growing functions, and algorithm makes too large steps which lead to -overflow. This function allows us to reject steps that are too large (and -therefore expose us to the possible overflow) without actually calculating -function value at the x+stp*d. - - -- ALGLIB -- - Copyright 20.08.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::nleqsetstpmax( - nleqstate state, - double stpmax, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to NLEQSolve(). - - -- ALGLIB -- - Copyright 20.08.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::nleqsetxrep( - nleqstate state, - bool needxrep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This family of functions is used to launcn iterations of nonlinear solver - -These functions accept following parameters: - state - algorithm state - func - callback which calculates function (or merit function) - value func at given point x - jac - callback which calculates function vector fi[] - and Jacobian jac at given point x - rep - optional callback which is called after each iteration - can be NULL - ptr - optional pointer which is passed to func/grad/hess/jac/rep - can be NULL - - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -
void nleqsolve(nleqstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -
- - - -
-
/************************************************************************* -Bivariate normal CDF - -Returns the area under the bivariate Gaussian PDF with correlation -parameter equal to Rho, integrated from minus infinity to (x,y): - - - x y - - - - 1 | | | | - bvn(x,y,rho) = ------------------- | | f(u,v,rho)*du*dv - 2pi*sqrt(1-rho^2) | | | | - - - - -INF -INF - - -where - - ( u^2 - 2*rho*u*v + v^2 ) - f(u,v,rho) = exp( - ----------------------- ) - ( 2*(1-rho^2) ) - - -with -1<rho<+1 and arbitrary x, y. - -This subroutine uses high-precision approximation scheme proposed by -Alan Genz in "Numerical Computation of Rectangular Bivariate and -Trivariate Normal and t probabilities", which computes CDF with -absolute error roughly equal to 1e-14. - -This function won't fail as long as Rho is in (-1,+1) range. - - -- ALGLIB -- - Copyright 15.11.2019 by Bochkanov Sergey -*************************************************************************/ -
double alglib::bivariatenormalcdf( - double x, - double y, - double rho, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Bivariate normal PDF - -Returns probability density function of the bivariate Gaussian with -correlation parameter equal to Rho: - - 1 ( x^2 - 2*rho*x*y + y^2 ) - f(x,y,rho) = ----------------- * exp( - ----------------------- ) - 2pi*sqrt(1-rho^2) ( 2*(1-rho^2) ) - - -with -1<rho<+1 and arbitrary x, y. - -This function won't fail as long as Rho is in (-1,+1) range. - - -- ALGLIB -- - Copyright 15.11.2019 by Bochkanov Sergey -*************************************************************************/ -
double alglib::bivariatenormalpdf( - double x, - double y, - double rho, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Error function - -The integral is - - x - - - 2 | | 2 - erf(x) = -------- | exp( - t ) dt. - sqrt(pi) | | - - - 0 - -For 0 <= |x| < 1, erf(x) = x * P4(x**2)/Q5(x**2); otherwise -erf(x) = 1 - erfc(x). - - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,1 30000 3.7e-16 1.0e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::errorfunction( - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Complementary error function - - 1 - erf(x) = - - inf. - - - 2 | | 2 - erfc(x) = -------- | exp( - t ) dt - sqrt(pi) | | - - - x - - -For small x, erfc(x) = 1 - erf(x); otherwise rational -approximations are computed. - - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,26.6417 30000 5.7e-14 1.5e-14 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::errorfunctionc( - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Inverse of the error function - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::inverf(double e, const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Inverse of Normal CDF - -Returns the argument, x, for which the area under the -Gaussian probability density function (integrated from -minus infinity to x) is equal to y. - - -For small arguments 0 < y < exp(-2), the program computes -z = sqrt( -2.0 * log(y) ); then the approximation is -x = z - log(z)/z - (1/z) P(1/z) / Q(1/z). -There are two rational functions P/Q, one for 0 < y < exp(-32) -and the other for y up to exp(-2). For larger arguments, -w = y - 0.5, and x/sqrt(2pi) = w + w**3 R(w**2)/S(w**2)). - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0.125, 1 20000 7.2e-16 1.3e-16 - IEEE 3e-308, 0.135 50000 4.6e-16 9.8e-17 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::invnormalcdf( - double y0, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Same as invnormalcdf(), deprecated name -*************************************************************************/ -
double alglib::invnormaldistribution( - double y0, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Normal distribution CDF - -Returns the area under the Gaussian probability density -function, integrated from minus infinity to x: - - x - - - 1 | | 2 - ndtr(x) = --------- | exp( - t /2 ) dt - sqrt(2pi) | | - - - -inf. - - = ( 1 + erf(z) ) / 2 - = erfc(z) / 2 - -where z = x/sqrt(2). Computation is via the functions -erf and erfc. - - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE -13,0 30000 3.4e-14 6.7e-15 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::normalcdf( - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Same as normalcdf(), obsolete name. -*************************************************************************/ -
double alglib::normaldistribution( - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Normal distribution PDF - -Returns Gaussian probability density function: - - 1 - f(x) = --------- * exp(-x^2/2) - sqrt(2pi) - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::normalpdf( - double x, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -This object stores state of the iterative norm estimation algorithm. - -You should use ALGLIB functions to work with this object. -*************************************************************************/ -
class normestimatorstate -{ -}; - -
- -
-
/************************************************************************* -This procedure initializes matrix norm estimator. - -USAGE: -1. User initializes algorithm state with NormEstimatorCreate() call -2. User calls NormEstimatorEstimateSparse() (or NormEstimatorIteration()) -3. User calls NormEstimatorResults() to get solution. - -INPUT PARAMETERS: - M - number of rows in the matrix being estimated, M>0 - N - number of columns in the matrix being estimated, N>0 - NStart - number of random starting vectors - recommended value - at least 5. - NIts - number of iterations to do with best starting vector - recommended value - at least 5. - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -NOTE: this algorithm is effectively deterministic, i.e. it always returns -same result when repeatedly called for the same matrix. In fact, algorithm -uses randomized starting vectors, but internal random numbers generator -always generates same sequence of the random values (it is a feature, not -bug). - -Algorithm can be made non-deterministic with NormEstimatorSetSeed(0) call. - - -- ALGLIB -- - Copyright 06.12.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::normestimatorcreate( - ae_int_t m, - ae_int_t n, - ae_int_t nstart, - ae_int_t nits, - normestimatorstate& state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function estimates norm of the sparse M*N matrix A. - -INPUT PARAMETERS: - State - norm estimator state, must be initialized with a call - to NormEstimatorCreate() - A - sparse M*N matrix, must be converted to CRS format - prior to calling this function. - -After this function is over you can call NormEstimatorResults() to get -estimate of the norm(A). - - -- ALGLIB -- - Copyright 06.12.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::normestimatorestimatesparse( - normestimatorstate state, - sparsematrix a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Matrix norm estimation results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - Nrm - estimate of the matrix norm, Nrm>=0 - - -- ALGLIB -- - Copyright 06.12.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::normestimatorresults( - normestimatorstate state, - double& nrm, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function changes seed value used by algorithm. In some cases we need -deterministic processing, i.e. subsequent calls must return equal results, -in other cases we need non-deterministic algorithm which returns different -results for the same matrix on every pass. - -Setting zero seed will lead to non-deterministic algorithm, while non-zero -value will make our algorithm deterministic. - -INPUT PARAMETERS: - State - norm estimator state, must be initialized with a call - to NormEstimatorCreate() - SeedVal - seed value, >=0. Zero value = non-deterministic algo. - - -- ALGLIB -- - Copyright 06.12.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::normestimatorsetseed( - normestimatorstate state, - ae_int_t seedval, - const xparams _params = alglib::xdefault); - -
- -
- -odesolverreport
-odesolverstate
- -odesolverresults
-odesolverrkck
-odesolversolve
- - - -
odesolver_d1 Solving y'=-y with ODE solver
- -
-
/************************************************************************* - -*************************************************************************/ -
class odesolverreport -{ - ae_int_t nfev; - ae_int_t terminationtype; -}; - -
- -
-
/************************************************************************* - -*************************************************************************/ -
class odesolverstate -{ -}; - -
- -
-
/************************************************************************* -ODE solver results - -Called after OdeSolverIteration returned False. - -INPUT PARAMETERS: - State - algorithm state (used by OdeSolverIteration). - -OUTPUT PARAMETERS: - M - number of tabulated values, M>=1 - XTbl - array[0..M-1], values of X - YTbl - array[0..M-1,0..N-1], values of Y in X[i] - Rep - solver report: - * Rep.TerminationType completetion code: - * -2 X is not ordered by ascending/descending or - there are non-distinct X[], i.e. X[i]=X[i+1] - * -1 incorrect parameters were specified - * 1 task has been solved - * Rep.NFEV contains number of function calculations - - -- ALGLIB -- - Copyright 01.09.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::odesolverresults( - odesolverstate state, - ae_int_t& m, - real_1d_array& xtbl, - real_2d_array& ytbl, - odesolverreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Cash-Karp adaptive ODE solver. - -This subroutine solves ODE Y'=f(Y,x) with initial conditions Y(xs)=Ys -(here Y may be single variable or vector of N variables). - -INPUT PARAMETERS: - Y - initial conditions, array[0..N-1]. - contains values of Y[] at X[0] - N - system size - X - points at which Y should be tabulated, array[0..M-1] - integrations starts at X[0], ends at X[M-1], intermediate - values at X[i] are returned too. - SHOULD BE ORDERED BY ASCENDING OR BY DESCENDING! - M - number of intermediate points + first point + last point: - * M>2 means that you need both Y(X[M-1]) and M-2 values at - intermediate points - * M=2 means that you want just to integrate from X[0] to - X[1] and don't interested in intermediate values. - * M=1 means that you don't want to integrate :) - it is degenerate case, but it will be handled correctly. - * M<1 means error - Eps - tolerance (absolute/relative error on each step will be - less than Eps). When passing: - * Eps>0, it means desired ABSOLUTE error - * Eps<0, it means desired RELATIVE error. Relative errors - are calculated with respect to maximum values of Y seen - so far. Be careful to use this criterion when starting - from Y[] that are close to zero. - H - initial step lenth, it will be adjusted automatically - after the first step. If H=0, step will be selected - automatically (usualy it will be equal to 0.001 of - min(x[i]-x[j])). - -OUTPUT PARAMETERS - State - structure which stores algorithm state between subsequent - calls of OdeSolverIteration. Used for reverse communication. - This structure should be passed to the OdeSolverIteration - subroutine. - -SEE ALSO - AutoGKSmoothW, AutoGKSingular, AutoGKIteration, AutoGKResults. - - - -- ALGLIB -- - Copyright 01.09.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::odesolverrkck( - real_1d_array y, - real_1d_array x, - double eps, - double h, - odesolverstate& state, - const xparams _params = alglib::xdefault); -void alglib::odesolverrkck( - real_1d_array y, - ae_int_t n, - real_1d_array x, - ae_int_t m, - double eps, - double h, - odesolverstate& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function is used to launcn iterations of ODE solver - -It accepts following parameters: - diff - callback which calculates dy/dx for given y and x - ptr - optional pointer which is passed to diff; can be NULL - - - -- ALGLIB -- - Copyright 01.09.2009 by Bochkanov Sergey -*************************************************************************/ -
void odesolversolve(odesolverstate &state, - void (*diff)(const real_1d_array &y, double x, real_1d_array &dy, void *ptr), - void *ptr = NULL, const xparams _xparams = alglib::xdefault); -
-

Examples:   [1]  

- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "diffequations.h"
-
-using namespace alglib;
-void ode_function_1_diff(const real_1d_array &y, double x, real_1d_array &dy, void *ptr) 
-{
-    // this callback calculates f(y[],x)=-y[0]
-    dy[0] = -y[0];
-}
-
-int main(int argc, char **argv)
-{
-    real_1d_array y = "[1]";
-    real_1d_array x = "[0, 1, 2, 3]";
-    double eps = 0.00001;
-    double h = 0;
-    odesolverstate s;
-    ae_int_t m;
-    real_1d_array xtbl;
-    real_2d_array ytbl;
-    odesolverreport rep;
-    odesolverrkck(y, x, eps, h, s);
-    alglib::odesolversolve(s, ode_function_1_diff);
-    odesolverresults(s, m, xtbl, ytbl, rep);
-    printf("%d\n", int(m)); // EXPECTED: 4
-    printf("%s\n", xtbl.tostring(2).c_str()); // EXPECTED: [0, 1, 2, 3]
-    printf("%s\n", ytbl.tostring(2).c_str()); // EXPECTED: [[1], [0.367], [0.135], [0.050]]
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* -This structure is used for detailed reporting about suspected C0 -continuity violation. - -=== WHAT IS TESTED ======================================================= - -C0 test studies function values (not gradient!) obtained during line -searches and monitors estimate of the Lipschitz constant. Sudden spikes -usually indicate that discontinuity was detected. - - -=== WHAT IS REPORTED ===================================================== - -Actually, report retrieval function returns TWO report structures: - -* one for most suspicious point found so far (one with highest change in - the function value), so called "strongest" report -* another one for most detailed line search (more function evaluations = - easier to understand what's going on) which triggered test #0 criteria, - so called "longest" report - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* fidx - is an index of the function (0 for target function, 1 or higher - for nonlinear constraints) which is suspected of being "non-C1" -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -You can plot function values stored in stp[] and f[] arrays and study -behavior of your function by your own eyes, just to be sure that test -correctly reported C1 violation. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -
class optguardnonc0report -{ - bool positive; - ae_int_t fidx; - real_1d_array x0; - real_1d_array d; - ae_int_t n; - real_1d_array stp; - real_1d_array f; - ae_int_t cnt; - ae_int_t stpidxa; - ae_int_t stpidxb; -}; - -
- -
-
/************************************************************************* -This structure is used for detailed reporting about suspected C1 -continuity violation as flagged by C1 test #0 (OptGuard has several tests -for C1 continuity, this report is used by #0). - -=== WHAT IS TESTED ======================================================= - -C1 test #0 studies function values (not gradient!) obtained during line -searches and monitors behavior of directional derivative estimate. This -test is less powerful than test #1, but it does not depend on gradient -values and thus it is more robust against artifacts introduced by -numerical differentiation. - - -=== WHAT IS REPORTED ===================================================== - -Actually, report retrieval function returns TWO report structures: - -* one for most suspicious point found so far (one with highest change in - the directional derivative), so called "strongest" report -* another one for most detailed line search (more function evaluations = - easier to understand what's going on) which triggered test #0 criteria, - so called "longest" report - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* fidx - is an index of the function (0 for target function, 1 or higher - for nonlinear constraints) which is suspected of being "non-C1" -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -You can plot function values stored in stp[] and f[] arrays and study -behavior of your function by your own eyes, just to be sure that test -correctly reported C1 violation. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -
class optguardnonc1test0report -{ - bool positive; - ae_int_t fidx; - real_1d_array x0; - real_1d_array d; - ae_int_t n; - real_1d_array stp; - real_1d_array f; - ae_int_t cnt; - ae_int_t stpidxa; - ae_int_t stpidxb; -}; - -
- -
-
/************************************************************************* -This structure is used for detailed reporting about suspected C1 -continuity violation as flagged by C1 test #1 (OptGuard has several tests -for C1 continuity, this report is used by #1). - -=== WHAT IS TESTED ======================================================= - -C1 test #1 studies individual components of the gradient as recorded -during line searches. Upon discovering discontinuity in the gradient this -test records specific component which was suspected (or one with highest -indication of discontinuity if multiple components are suspected). - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - - -=== WHAT IS REPORTED ===================================================== - -Actually, report retrieval function returns TWO report structures: - -* one for most suspicious point found so far (one with highest change in - the directional derivative), so called "strongest" report -* another one for most detailed line search (more function evaluations = - easier to understand what's going on) which triggered test #1 criteria, - so called "longest" report - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* fidx - is an index of the function (0 for target function, 1 or higher - for nonlinear constraints) which is suspected of being "non-C1" -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -You can plot function values stored in stp[] and g[] arrays and study -behavior of your function by your own eyes, just to be sure that test -correctly reported C1 violation. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -
class optguardnonc1test1report -{ - bool positive; - ae_int_t fidx; - ae_int_t vidx; - real_1d_array x0; - real_1d_array d; - ae_int_t n; - real_1d_array stp; - real_1d_array g; - ae_int_t cnt; - ae_int_t stpidxa; - ae_int_t stpidxb; -}; - -
- -
-
/************************************************************************* -This structure is used to store OptGuard report, i.e. report on the -properties of the nonlinear function being optimized with ALGLIB. - -After you tell your optimizer to activate OptGuard this technology starts -to silently monitor function values and gradients/Jacobians being passed -all around during your optimization session. Depending on specific set of -checks enabled OptGuard may perform additional function evaluations (say, -about 3*N evaluations if you want to check analytic gradient for errors). - -Upon discovering that something strange happens (function values and/or -gradient components change too sharply and/or unexpectedly) OptGuard sets -one of the "suspicion flags" (without interrupting optimization session). -After optimization is done, you can examine OptGuard report. - -Following report fields can be set: -* nonc0suspected -* nonc1suspected -* badgradsuspected - - -=== WHAT CAN BE DETECTED WITH OptGuard INTEGRITY CHECKER ================= - -Following types of errors in your target function (constraints) can be -caught: -a) discontinuous functions ("non-C0" part of the report) -b) functions with discontinuous derivative ("non-C1" part of the report) -c) errors in the analytic gradient provided by user - -These types of errors result in optimizer stopping well before reaching -solution (most often - right after encountering discontinuity). - -Type A errors are usually coding errors during implementation of the -target function. Most "normal" problems involve continuous functions, and -anyway you can't reliably optimize discontinuous function. - -Type B errors are either coding errors or (in case code itself is correct) -evidence of the fact that your problem is an "incorrect" one. Most -optimizers (except for ones provided by MINNS subpackage) do not support -nonsmooth problems. - -Type C errors are coding errors which often prevent optimizer from making -even one step or result in optimizing stopping too early, as soon as -actual descent direction becomes too different from one suggested by user- -supplied gradient. - - -=== WHAT IS REPORTED ===================================================== - -Following set of report fields deals with discontinuous target functions, -ones not belonging to C0 continuity class: - -* nonc0suspected - is a flag which is set upon discovering some indication - of the discontinuity. If this flag is false, the rest of "non-C0" fields - should be ignored -* nonc0fidx - is an index of the function (0 for target function, 1 or - higher for nonlinear constraints) which is suspected of being "non-C0" -* nonc0lipshitzc - a Lipchitz constant for a function which was suspected - of being non-continuous. -* nonc0test0positive - set to indicate specific test which detected - continuity violation (test #0) - -Following set of report fields deals with discontinuous gradient/Jacobian, -i.e. with functions violating C1 continuity: - -* nonc1suspected - is a flag which is set upon discovering some indication - of the discontinuity. If this flag is false, the rest of "non-C1" fields - should be ignored -* nonc1fidx - is an index of the function (0 for target function, 1 or - higher for nonlinear constraints) which is suspected of being "non-C1" -* nonc1lipshitzc - a Lipchitz constant for a function gradient which was - suspected of being non-smooth. -* nonc1test0positive - set to indicate specific test which detected - continuity violation (test #0) -* nonc1test1positive - set to indicate specific test which detected - continuity violation (test #1) - -Following set of report fields deals with errors in the gradient: -* badgradsuspected - is a flad which is set upon discovering an error in - the analytic gradient supplied by user -* badgradfidx - index of the function with bad gradient (0 for target - function, 1 or higher for nonlinear constraints) -* badgradvidx - index of the variable -* badgradxbase - location where Jacobian is tested -* following matrices store user-supplied Jacobian and its numerical - differentiation version (which is assumed to be free from the coding - errors), both of them computed near the initial point: - * badgraduser, an array[K,N], analytic Jacobian supplied by user - * badgradnum, an array[K,N], numeric Jacobian computed by ALGLIB - Here K is a total number of nonlinear functions (target + nonlinear - constraints), N is a variable number. - The element of badgraduser[] with index [badgradfidx,badgradvidx] is - assumed to be wrong. - -More detailed error log can be obtained from optimizer by explicitly -requesting reports for tests C0.0, C1.0, C1.1. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -
class optguardreport -{ - bool nonc0suspected; - bool nonc0test0positive; - ae_int_t nonc0fidx; - double nonc0lipschitzc; - bool nonc1suspected; - bool nonc1test0positive; - bool nonc1test1positive; - ae_int_t nonc1fidx; - double nonc1lipschitzc; - bool badgradsuspected; - ae_int_t badgradfidx; - ae_int_t badgradvidx; - real_1d_array badgradxbase; - real_2d_array badgraduser; - real_2d_array badgradnum; -}; - -
- - - -
-
/************************************************************************* -LQ decomposition of a rectangular complex matrix of size MxN - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix A whose indexes range within [0..M-1, 0..N-1] - M - number of rows in matrix A. - N - number of columns in matrix A. - -Output parameters: - A - matrices Q and L in compact form - Tau - array of scalar factors which are used to form matrix Q. Array - whose indexes range within [0.. Min(M,N)-1] - -Matrix A is represented as A = LQ, where Q is an orthogonal matrix of size -MxM, L - lower triangular (or lower trapezoid) matrix of size MxN. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994 -*************************************************************************/ -
void alglib::cmatrixlq( - complex_2d_array& a, - ae_int_t m, - ae_int_t n, - complex_1d_array& tau, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Unpacking of matrix L from the LQ decomposition of a matrix A - -Input parameters: - A - matrices Q and L in compact form. - Output of CMatrixLQ subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - -Output parameters: - L - matrix L, array[0..M-1, 0..N-1]. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixlqunpackl( - complex_2d_array a, - ae_int_t m, - ae_int_t n, - complex_2d_array& l, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Partial unpacking of matrix Q from LQ decomposition of a complex matrix A. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrices Q and R in compact form. - Output of CMatrixLQ subroutine . - M - number of rows in matrix A. M>=0. - N - number of columns in matrix A. N>=0. - Tau - scalar factors which are used to form Q. - Output of CMatrixLQ subroutine . - QRows - required number of rows in matrix Q. N>=QColumns>=0. - -Output parameters: - Q - first QRows rows of matrix Q. - Array whose index ranges within [0..QRows-1, 0..N-1]. - If QRows=0, array isn't changed. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixlqunpackq( - complex_2d_array a, - ae_int_t m, - ae_int_t n, - complex_1d_array tau, - ae_int_t qrows, - complex_2d_array& q, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -QR decomposition of a rectangular complex matrix of size MxN - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix A whose indexes range within [0..M-1, 0..N-1] - M - number of rows in matrix A. - N - number of columns in matrix A. - -Output parameters: - A - matrices Q and R in compact form - Tau - array of scalar factors which are used to form matrix Q. Array - whose indexes range within [0.. Min(M,N)-1] - -Matrix A is represented as A = QR, where Q is an orthogonal matrix of size -MxM, R - upper triangular (or upper trapezoid) matrix of size MxN. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994 -*************************************************************************/ -
void alglib::cmatrixqr( - complex_2d_array& a, - ae_int_t m, - ae_int_t n, - complex_1d_array& tau, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Partial unpacking of matrix Q from QR decomposition of a complex matrix A. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrices Q and R in compact form. - Output of CMatrixQR subroutine . - M - number of rows in matrix A. M>=0. - N - number of columns in matrix A. N>=0. - Tau - scalar factors which are used to form Q. - Output of CMatrixQR subroutine . - QColumns - required number of columns in matrix Q. M>=QColumns>=0. - -Output parameters: - Q - first QColumns columns of matrix Q. - Array whose index ranges within [0..M-1, 0..QColumns-1]. - If QColumns=0, array isn't changed. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixqrunpackq( - complex_2d_array a, - ae_int_t m, - ae_int_t n, - complex_1d_array tau, - ae_int_t qcolumns, - complex_2d_array& q, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Unpacking of matrix R from the QR decomposition of a matrix A - -Input parameters: - A - matrices Q and R in compact form. - Output of CMatrixQR subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - -Output parameters: - R - matrix R, array[0..M-1, 0..N-1]. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixqrunpackr( - complex_2d_array a, - ae_int_t m, - ae_int_t n, - complex_2d_array& r, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Reduction of a Hermitian matrix which is given by its higher or lower -triangular part to a real tridiagonal matrix using unitary similarity -transformation: Q'*A*Q = T. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix to be transformed - array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - storage format. If IsUpper = True, then matrix A is given - by its upper triangle, and the lower triangle is not used - and not modified by the algorithm, and vice versa - if IsUpper = False. - -Output parameters: - A - matrices T and Q in compact form (see lower) - Tau - array of factors which are forming matrices H(i) - array with elements [0..N-2]. - D - main diagonal of real symmetric matrix T. - array with elements [0..N-1]. - E - secondary diagonal of real symmetric matrix T. - array with elements [0..N-2]. - - - If IsUpper=True, the matrix Q is represented as a product of elementary - reflectors - - Q = H(n-2) . . . H(2) H(0). - - Each H(i) has the form - - H(i) = I - tau * v * v' - - where tau is a complex scalar, and v is a complex vector with - v(i+1:n-1) = 0, v(i) = 1, v(0:i-1) is stored on exit in - A(0:i-1,i+1), and tau in TAU(i). - - If IsUpper=False, the matrix Q is represented as a product of elementary - reflectors - - Q = H(0) H(2) . . . H(n-2). - - Each H(i) has the form - - H(i) = I - tau * v * v' - - where tau is a complex scalar, and v is a complex vector with - v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) is stored on exit in A(i+2:n-1,i), - and tau in TAU(i). - - The contents of A on exit are illustrated by the following examples - with n = 5: - - if UPLO = 'U': if UPLO = 'L': - - ( d e v1 v2 v3 ) ( d ) - ( d e v2 v3 ) ( e d ) - ( d e v3 ) ( v0 e d ) - ( d e ) ( v0 v1 e d ) - ( d ) ( v0 v1 v2 e d ) - -where d and e denote diagonal and off-diagonal elements of T, and vi -denotes an element of the vector defining H(i). - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - October 31, 1992 -*************************************************************************/ -
void alglib::hmatrixtd( - complex_2d_array& a, - ae_int_t n, - bool isupper, - complex_1d_array& tau, - real_1d_array& d, - real_1d_array& e, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Unpacking matrix Q which reduces a Hermitian matrix to a real tridiagonal -form. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - the result of a HMatrixTD subroutine - N - size of matrix A. - IsUpper - storage format (a parameter of HMatrixTD subroutine) - Tau - the result of a HMatrixTD subroutine - -Output parameters: - Q - transformation matrix. - array with elements [0..N-1, 0..N-1]. - - -- ALGLIB -- - Copyright 2005-2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::hmatrixtdunpackq( - complex_2d_array a, - ae_int_t n, - bool isupper, - complex_1d_array tau, - complex_2d_array& q, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Reduction of a rectangular matrix to bidiagonal form - -The algorithm reduces the rectangular matrix A to bidiagonal form by -orthogonal transformations P and Q: A = Q*B*(P^T). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - source matrix. array[0..M-1, 0..N-1] - M - number of rows in matrix A. - N - number of columns in matrix A. - -Output parameters: - A - matrices Q, B, P in compact form (see below). - TauQ - scalar factors which are used to form matrix Q. - TauP - scalar factors which are used to form matrix P. - -The main diagonal and one of the secondary diagonals of matrix A are -replaced with bidiagonal matrix B. Other elements contain elementary -reflections which form MxM matrix Q and NxN matrix P, respectively. - -If M>=N, B is the upper bidiagonal MxN matrix and is stored in the -corresponding elements of matrix A. Matrix Q is represented as a -product of elementary reflections Q = H(0)*H(1)*...*H(n-1), where -H(i) = 1-tau*v*v'. Here tau is a scalar which is stored in TauQ[i], and -vector v has the following structure: v(0:i-1)=0, v(i)=1, v(i+1:m-1) is -stored in elements A(i+1:m-1,i). Matrix P is as follows: P = -G(0)*G(1)*...*G(n-2), where G(i) = 1 - tau*u*u'. Tau is stored in TauP[i], -u(0:i)=0, u(i+1)=1, u(i+2:n-1) is stored in elements A(i,i+2:n-1). - -If M<N, B is the lower bidiagonal MxN matrix and is stored in the -corresponding elements of matrix A. Q = H(0)*H(1)*...*H(m-2), where -H(i) = 1 - tau*v*v', tau is stored in TauQ, v(0:i)=0, v(i+1)=1, v(i+2:m-1) -is stored in elements A(i+2:m-1,i). P = G(0)*G(1)*...*G(m-1), -G(i) = 1-tau*u*u', tau is stored in TauP, u(0:i-1)=0, u(i)=1, u(i+1:n-1) -is stored in A(i,i+1:n-1). - -EXAMPLE: - -m=6, n=5 (m > n): m=5, n=6 (m < n): - -( d e u1 u1 u1 ) ( d u1 u1 u1 u1 u1 ) -( v1 d e u2 u2 ) ( e d u2 u2 u2 u2 ) -( v1 v2 d e u3 ) ( v1 e d u3 u3 u3 ) -( v1 v2 v3 d e ) ( v1 v2 e d u4 u4 ) -( v1 v2 v3 v4 d ) ( v1 v2 v3 e d u5 ) -( v1 v2 v3 v4 v5 ) - -Here vi and ui are vectors which form H(i) and G(i), and d and e - -are the diagonal and off-diagonal elements of matrix B. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994. - Sergey Bochkanov, ALGLIB project, translation from FORTRAN to - pseudocode, 2007-2010. -*************************************************************************/ -
void alglib::rmatrixbd( - real_2d_array& a, - ae_int_t m, - ae_int_t n, - real_1d_array& tauq, - real_1d_array& taup, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Multiplication by matrix P which reduces matrix A to bidiagonal form. - -The algorithm allows pre- or post-multiply by P or P'. - -Input parameters: - QP - matrices Q and P in compact form. - Output of RMatrixBD subroutine. - M - number of rows in matrix A. - N - number of columns in matrix A. - TAUP - scalar factors which are used to form P. - Output of RMatrixBD subroutine. - Z - multiplied matrix. - Array whose indexes range within [0..ZRows-1,0..ZColumns-1]. - ZRows - number of rows in matrix Z. If FromTheRight=False, - ZRows=N, otherwise ZRows can be arbitrary. - ZColumns - number of columns in matrix Z. If FromTheRight=True, - ZColumns=N, otherwise ZColumns can be arbitrary. - FromTheRight - pre- or post-multiply. - DoTranspose - multiply by P or P'. - -Output parameters: - Z - product of Z and P. - Array whose indexes range within [0..ZRows-1,0..ZColumns-1]. - If ZRows=0 or ZColumns=0, the array is not modified. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixbdmultiplybyp( - real_2d_array qp, - ae_int_t m, - ae_int_t n, - real_1d_array taup, - real_2d_array& z, - ae_int_t zrows, - ae_int_t zcolumns, - bool fromtheright, - bool dotranspose, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Multiplication by matrix Q which reduces matrix A to bidiagonal form. - -The algorithm allows pre- or post-multiply by Q or Q'. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - QP - matrices Q and P in compact form. - Output of ToBidiagonal subroutine. - M - number of rows in matrix A. - N - number of columns in matrix A. - TAUQ - scalar factors which are used to form Q. - Output of ToBidiagonal subroutine. - Z - multiplied matrix. - array[0..ZRows-1,0..ZColumns-1] - ZRows - number of rows in matrix Z. If FromTheRight=False, - ZRows=M, otherwise ZRows can be arbitrary. - ZColumns - number of columns in matrix Z. If FromTheRight=True, - ZColumns=M, otherwise ZColumns can be arbitrary. - FromTheRight - pre- or post-multiply. - DoTranspose - multiply by Q or Q'. - -Output parameters: - Z - product of Z and Q. - Array[0..ZRows-1,0..ZColumns-1] - If ZRows=0 or ZColumns=0, the array is not modified. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixbdmultiplybyq( - real_2d_array qp, - ae_int_t m, - ae_int_t n, - real_1d_array tauq, - real_2d_array& z, - ae_int_t zrows, - ae_int_t zcolumns, - bool fromtheright, - bool dotranspose, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Unpacking of the main and secondary diagonals of bidiagonal decomposition -of matrix A. - -Input parameters: - B - output of RMatrixBD subroutine. - M - number of rows in matrix B. - N - number of columns in matrix B. - -Output parameters: - IsUpper - True, if the matrix is upper bidiagonal. - otherwise IsUpper is False. - D - the main diagonal. - Array whose index ranges within [0..Min(M,N)-1]. - E - the secondary diagonal (upper or lower, depending on - the value of IsUpper). - Array index ranges within [0..Min(M,N)-1], the last - element is not used. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixbdunpackdiagonals( - real_2d_array b, - ae_int_t m, - ae_int_t n, - bool& isupper, - real_1d_array& d, - real_1d_array& e, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Unpacking matrix P which reduces matrix A to bidiagonal form. -The subroutine returns transposed matrix P. - -Input parameters: - QP - matrices Q and P in compact form. - Output of ToBidiagonal subroutine. - M - number of rows in matrix A. - N - number of columns in matrix A. - TAUP - scalar factors which are used to form P. - Output of ToBidiagonal subroutine. - PTRows - required number of rows of matrix P^T. N >= PTRows >= 0. - -Output parameters: - PT - first PTRows columns of matrix P^T - Array[0..PTRows-1, 0..N-1] - If PTRows=0, the array is not modified. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixbdunpackpt( - real_2d_array qp, - ae_int_t m, - ae_int_t n, - real_1d_array taup, - ae_int_t ptrows, - real_2d_array& pt, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Unpacking matrix Q which reduces a matrix to bidiagonal form. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - QP - matrices Q and P in compact form. - Output of ToBidiagonal subroutine. - M - number of rows in matrix A. - N - number of columns in matrix A. - TAUQ - scalar factors which are used to form Q. - Output of ToBidiagonal subroutine. - QColumns - required number of columns in matrix Q. - M>=QColumns>=0. - -Output parameters: - Q - first QColumns columns of matrix Q. - Array[0..M-1, 0..QColumns-1] - If QColumns=0, the array is not modified. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixbdunpackq( - real_2d_array qp, - ae_int_t m, - ae_int_t n, - real_1d_array tauq, - ae_int_t qcolumns, - real_2d_array& q, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Reduction of a square matrix to upper Hessenberg form: Q'*A*Q = H, -where Q is an orthogonal matrix, H - Hessenberg matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix A with elements [0..N-1, 0..N-1] - N - size of matrix A. - -Output parameters: - A - matrices Q and P in compact form (see below). - Tau - array of scalar factors which are used to form matrix Q. - Array whose index ranges within [0..N-2] - -Matrix H is located on the main diagonal, on the lower secondary diagonal -and above the main diagonal of matrix A. The elements which are used to -form matrix Q are situated in array Tau and below the lower secondary -diagonal of matrix A as follows: - -Matrix Q is represented as a product of elementary reflections - -Q = H(0)*H(2)*...*H(n-2), - -where each H(i) is given by - -H(i) = 1 - tau * v * (v^T) - -where tau is a scalar stored in Tau[I]; v - is a real vector, -so that v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) stored in A(i+2:n-1,i). - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - October 31, 1992 -*************************************************************************/ -
void alglib::rmatrixhessenberg( - real_2d_array& a, - ae_int_t n, - real_1d_array& tau, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Unpacking matrix H (the result of matrix A reduction to upper Hessenberg form) - -Input parameters: - A - output of RMatrixHessenberg subroutine. - N - size of matrix A. - -Output parameters: - H - matrix H. Array whose indexes range within [0..N-1, 0..N-1]. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixhessenbergunpackh( - real_2d_array a, - ae_int_t n, - real_2d_array& h, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Unpacking matrix Q which reduces matrix A to upper Hessenberg form - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - output of RMatrixHessenberg subroutine. - N - size of matrix A. - Tau - scalar factors which are used to form Q. - Output of RMatrixHessenberg subroutine. - -Output parameters: - Q - matrix Q. - Array whose indexes range within [0..N-1, 0..N-1]. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixhessenbergunpackq( - real_2d_array a, - ae_int_t n, - real_1d_array tau, - real_2d_array& q, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -LQ decomposition of a rectangular matrix of size MxN - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix A whose indexes range within [0..M-1, 0..N-1]. - M - number of rows in matrix A. - N - number of columns in matrix A. - -Output parameters: - A - matrices L and Q in compact form (see below) - Tau - array of scalar factors which are used to form - matrix Q. Array whose index ranges within [0..Min(M,N)-1]. - -Matrix A is represented as A = LQ, where Q is an orthogonal matrix of size -MxM, L - lower triangular (or lower trapezoid) matrix of size M x N. - -The elements of matrix L are located on and below the main diagonal of -matrix A. The elements which are located in Tau array and above the main -diagonal of matrix A are used to form matrix Q as follows: - -Matrix Q is represented as a product of elementary reflections - -Q = H(k-1)*H(k-2)*...*H(1)*H(0), - -where k = min(m,n), and each H(i) is of the form - -H(i) = 1 - tau * v * (v^T) - -where tau is a scalar stored in Tau[I]; v - real vector, so that v(0:i-1)=0, -v(i) = 1, v(i+1:n-1) stored in A(i,i+1:n-1). - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixlq( - real_2d_array& a, - ae_int_t m, - ae_int_t n, - real_1d_array& tau, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Unpacking of matrix L from the LQ decomposition of a matrix A - -Input parameters: - A - matrices Q and L in compact form. - Output of RMatrixLQ subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - -Output parameters: - L - matrix L, array[0..M-1, 0..N-1]. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixlqunpackl( - real_2d_array a, - ae_int_t m, - ae_int_t n, - real_2d_array& l, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Partial unpacking of matrix Q from the LQ decomposition of a matrix A - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrices L and Q in compact form. - Output of RMatrixLQ subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - Tau - scalar factors which are used to form Q. - Output of the RMatrixLQ subroutine. - QRows - required number of rows in matrix Q. N>=QRows>=0. - -Output parameters: - Q - first QRows rows of matrix Q. Array whose indexes range - within [0..QRows-1, 0..N-1]. If QRows=0, the array remains - unchanged. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixlqunpackq( - real_2d_array a, - ae_int_t m, - ae_int_t n, - real_1d_array tau, - ae_int_t qrows, - real_2d_array& q, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -QR decomposition of a rectangular matrix of size MxN - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix A whose indexes range within [0..M-1, 0..N-1]. - M - number of rows in matrix A. - N - number of columns in matrix A. - -Output parameters: - A - matrices Q and R in compact form (see below). - Tau - array of scalar factors which are used to form - matrix Q. Array whose index ranges within [0.. Min(M-1,N-1)]. - -Matrix A is represented as A = QR, where Q is an orthogonal matrix of size -MxM, R - upper triangular (or upper trapezoid) matrix of size M x N. - -The elements of matrix R are located on and above the main diagonal of -matrix A. The elements which are located in Tau array and below the main -diagonal of matrix A are used to form matrix Q as follows: - -Matrix Q is represented as a product of elementary reflections - -Q = H(0)*H(2)*...*H(k-1), - -where k = min(m,n), and each H(i) is in the form - -H(i) = 1 - tau * v * (v^T) - -where tau is a scalar stored in Tau[I]; v - real vector, -so that v(0:i-1) = 0, v(i) = 1, v(i+1:m-1) stored in A(i+1:m-1,i). - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixqr( - real_2d_array& a, - ae_int_t m, - ae_int_t n, - real_1d_array& tau, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Partial unpacking of matrix Q from the QR decomposition of a matrix A - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrices Q and R in compact form. - Output of RMatrixQR subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - Tau - scalar factors which are used to form Q. - Output of the RMatrixQR subroutine. - QColumns - required number of columns of matrix Q. M>=QColumns>=0. - -Output parameters: - Q - first QColumns columns of matrix Q. - Array whose indexes range within [0..M-1, 0..QColumns-1]. - If QColumns=0, the array remains unchanged. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixqrunpackq( - real_2d_array a, - ae_int_t m, - ae_int_t n, - real_1d_array tau, - ae_int_t qcolumns, - real_2d_array& q, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Unpacking of matrix R from the QR decomposition of a matrix A - -Input parameters: - A - matrices Q and R in compact form. - Output of RMatrixQR subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - -Output parameters: - R - matrix R, array[0..M-1, 0..N-1]. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixqrunpackr( - real_2d_array a, - ae_int_t m, - ae_int_t n, - real_2d_array& r, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Reduction of a symmetric matrix which is given by its higher or lower -triangular part to a tridiagonal matrix using orthogonal similarity -transformation: Q'*A*Q=T. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix to be transformed - array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - storage format. If IsUpper = True, then matrix A is given - by its upper triangle, and the lower triangle is not used - and not modified by the algorithm, and vice versa - if IsUpper = False. - -Output parameters: - A - matrices T and Q in compact form (see lower) - Tau - array of factors which are forming matrices H(i) - array with elements [0..N-2]. - D - main diagonal of symmetric matrix T. - array with elements [0..N-1]. - E - secondary diagonal of symmetric matrix T. - array with elements [0..N-2]. - - - If IsUpper=True, the matrix Q is represented as a product of elementary - reflectors - - Q = H(n-2) . . . H(2) H(0). - - Each H(i) has the form - - H(i) = I - tau * v * v' - - where tau is a real scalar, and v is a real vector with - v(i+1:n-1) = 0, v(i) = 1, v(0:i-1) is stored on exit in - A(0:i-1,i+1), and tau in TAU(i). - - If IsUpper=False, the matrix Q is represented as a product of elementary - reflectors - - Q = H(0) H(2) . . . H(n-2). - - Each H(i) has the form - - H(i) = I - tau * v * v' - - where tau is a real scalar, and v is a real vector with - v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) is stored on exit in A(i+2:n-1,i), - and tau in TAU(i). - - The contents of A on exit are illustrated by the following examples - with n = 5: - - if UPLO = 'U': if UPLO = 'L': - - ( d e v1 v2 v3 ) ( d ) - ( d e v2 v3 ) ( e d ) - ( d e v3 ) ( v0 e d ) - ( d e ) ( v0 v1 e d ) - ( d ) ( v0 v1 v2 e d ) - - where d and e denote diagonal and off-diagonal elements of T, and vi - denotes an element of the vector defining H(i). - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - October 31, 1992 -*************************************************************************/ -
void alglib::smatrixtd( - real_2d_array& a, - ae_int_t n, - bool isupper, - real_1d_array& tau, - real_1d_array& d, - real_1d_array& e, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Unpacking matrix Q which reduces symmetric matrix to a tridiagonal -form. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - the result of a SMatrixTD subroutine - N - size of matrix A. - IsUpper - storage format (a parameter of SMatrixTD subroutine) - Tau - the result of a SMatrixTD subroutine - -Output parameters: - Q - transformation matrix. - array with elements [0..N-1, 0..N-1]. - - -- ALGLIB -- - Copyright 2005-2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::smatrixtdunpackq( - real_2d_array a, - ae_int_t n, - bool isupper, - real_1d_array tau, - real_2d_array& q, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -Parametric spline inteprolant: 2-dimensional curve. - -You should not try to access its members directly - use PSpline2XXXXXXXX() -functions instead. -*************************************************************************/ -
class pspline2interpolant -{ -}; - -
- -
-
/************************************************************************* -Parametric spline inteprolant: 3-dimensional curve. - -You should not try to access its members directly - use PSpline3XXXXXXXX() -functions instead. -*************************************************************************/ -
class pspline3interpolant -{ -}; - -
- -
-
/************************************************************************* -This subroutine fits piecewise linear curve to points with Ramer-Douglas- -Peucker algorithm. This function performs PARAMETRIC fit, i.e. it can be -used to fit curves like circles. - -On input it accepts dataset which describes parametric multidimensional -curve X(t), with X being vector, and t taking values in [0,N), where N is -a number of points in dataset. As result, it returns reduced dataset X2, -which can be used to build parametric curve X2(t), which approximates -X(t) with desired precision (or has specified number of sections). - - -INPUT PARAMETERS: - X - array of multidimensional points: - * at least N elements, leading N elements are used if more - than N elements were specified - * order of points is IMPORTANT because it is parametric - fit - * each row of array is one point which has D coordinates - N - number of elements in X - D - number of dimensions (elements per row of X) - StopM - stopping condition - desired number of sections: - * at most M sections are generated by this function - * less than M sections can be generated if we have N<M - (or some X are non-distinct). - * zero StopM means that algorithm does not stop after - achieving some pre-specified section count - StopEps - stopping condition - desired precision: - * algorithm stops after error in each section is at most Eps - * zero Eps means that algorithm does not stop after - achieving some pre-specified precision - -OUTPUT PARAMETERS: - X2 - array of corner points for piecewise approximation, - has length NSections+1 or zero (for NSections=0). - Idx2 - array of indexes (parameter values): - * has length NSections+1 or zero (for NSections=0). - * each element of Idx2 corresponds to same-numbered - element of X2 - * each element of Idx2 is index of corresponding element - of X2 at original array X, i.e. I-th row of X2 is - Idx2[I]-th row of X. - * elements of Idx2 can be treated as parameter values - which should be used when building new parametric curve - * Idx2[0]=0, Idx2[NSections]=N-1 - NSections- number of sections found by algorithm, NSections<=M, - NSections can be zero for degenerate datasets - (N<=1 or all X[] are non-distinct). - -NOTE: algorithm stops after: - a) dividing curve into StopM sections - b) achieving required precision StopEps - c) dividing curve into N-1 sections - If both StopM and StopEps are non-zero, algorithm is stopped by the - FIRST criterion which is satisfied. In case both StopM and StopEps - are zero, algorithm stops because of (c). - - -- ALGLIB -- - Copyright 02.10.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::parametricrdpfixed( - real_2d_array x, - ae_int_t n, - ae_int_t d, - ae_int_t stopm, - double stopeps, - real_2d_array& x2, - integer_1d_array& idx2, - ae_int_t& nsections, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function calculates arc length, i.e. length of curve between t=a -and t=b. - -INPUT PARAMETERS: - P - parametric spline interpolant - A,B - parameter values corresponding to arc ends: - * B>A will result in positive length returned - * B<A will result in negative length returned - -RESULT: - length of arc starting at T=A and ending at T=B. - - - -- ALGLIB PROJECT -- - Copyright 30.05.2010 by Bochkanov Sergey -*************************************************************************/ -
double alglib::pspline2arclength( - pspline2interpolant p, - double a, - double b, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function builds non-periodic 2-dimensional parametric spline which -starts at (X[0],Y[0]) and ends at (X[N-1],Y[N-1]). - -INPUT PARAMETERS: - XY - points, array[0..N-1,0..1]. - XY[I,0:1] corresponds to the Ith point. - Order of points is important! - N - points count, N>=5 for Akima splines, N>=2 for other types of - splines. - ST - spline type: - * 0 Akima spline - * 1 parabolically terminated Catmull-Rom spline (Tension=0) - * 2 parabolically terminated cubic spline - PT - parameterization type: - * 0 uniform - * 1 chord length - * 2 centripetal - -OUTPUT PARAMETERS: - P - parametric spline interpolant - - -NOTES: -* this function assumes that there all consequent points are distinct. - I.e. (x0,y0)<>(x1,y1), (x1,y1)<>(x2,y2), (x2,y2)<>(x3,y3) and so on. - However, non-consequent points may coincide, i.e. we can have (x0,y0)= - =(x2,y2). - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::pspline2build( - real_2d_array xy, - ae_int_t n, - ae_int_t st, - ae_int_t pt, - pspline2interpolant& p, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function builds periodic 2-dimensional parametric spline which -starts at (X[0],Y[0]), goes through all points to (X[N-1],Y[N-1]) and then -back to (X[0],Y[0]). - -INPUT PARAMETERS: - XY - points, array[0..N-1,0..1]. - XY[I,0:1] corresponds to the Ith point. - XY[N-1,0:1] must be different from XY[0,0:1]. - Order of points is important! - N - points count, N>=3 for other types of splines. - ST - spline type: - * 1 Catmull-Rom spline (Tension=0) with cyclic boundary conditions - * 2 cubic spline with cyclic boundary conditions - PT - parameterization type: - * 0 uniform - * 1 chord length - * 2 centripetal - -OUTPUT PARAMETERS: - P - parametric spline interpolant - - -NOTES: -* this function assumes that there all consequent points are distinct. - I.e. (x0,y0)<>(x1,y1), (x1,y1)<>(x2,y2), (x2,y2)<>(x3,y3) and so on. - However, non-consequent points may coincide, i.e. we can have (x0,y0)= - =(x2,y2). -* last point of sequence is NOT equal to the first point. You shouldn't - make curve "explicitly periodic" by making them equal. - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::pspline2buildperiodic( - real_2d_array xy, - ae_int_t n, - ae_int_t st, - ae_int_t pt, - pspline2interpolant& p, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates the value of the parametric spline for a given -value of parameter T - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-position - Y - Y-position - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::pspline2calc( - pspline2interpolant p, - double t, - double& x, - double& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates derivative, i.e. it returns (dX/dT,dY/dT). - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-value - DX - X-derivative - Y - Y-value - DY - Y-derivative - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::pspline2diff( - pspline2interpolant p, - double t, - double& x, - double& dx, - double& y, - double& dy, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates first and second derivative with respect to T. - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-value - DX - derivative - D2X - second derivative - Y - Y-value - DY - derivative - D2Y - second derivative - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::pspline2diff2( - pspline2interpolant p, - double t, - double& x, - double& dx, - double& d2x, - double& y, - double& dy, - double& d2y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function returns vector of parameter values correspoding to points. - -I.e. for P created from (X[0],Y[0])...(X[N-1],Y[N-1]) and U=TValues(P) we -have - (X[0],Y[0]) = PSpline2Calc(P,U[0]), - (X[1],Y[1]) = PSpline2Calc(P,U[1]), - (X[2],Y[2]) = PSpline2Calc(P,U[2]), - ... - -INPUT PARAMETERS: - P - parametric spline interpolant - -OUTPUT PARAMETERS: - N - array size - T - array[0..N-1] - - -NOTES: -* for non-periodic splines U[0]=0, U[0]<U[1]<...<U[N-1], U[N-1]=1 -* for periodic splines U[0]=0, U[0]<U[1]<...<U[N-1], U[N-1]<1 - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::pspline2parametervalues( - pspline2interpolant p, - ae_int_t& n, - real_1d_array& t, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates tangent vector for a given value of parameter T - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-component of tangent vector (normalized) - Y - Y-component of tangent vector (normalized) - -NOTE: - X^2+Y^2 is either 1 (for non-zero tangent vector) or 0. - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::pspline2tangent( - pspline2interpolant p, - double t, - double& x, - double& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates arc length, i.e. length of curve between t=a -and t=b. - -INPUT PARAMETERS: - P - parametric spline interpolant - A,B - parameter values corresponding to arc ends: - * B>A will result in positive length returned - * B<A will result in negative length returned - -RESULT: - length of arc starting at T=A and ending at T=B. - - - -- ALGLIB PROJECT -- - Copyright 30.05.2010 by Bochkanov Sergey -*************************************************************************/ -
double alglib::pspline3arclength( - pspline3interpolant p, - double a, - double b, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function builds non-periodic 3-dimensional parametric spline which -starts at (X[0],Y[0],Z[0]) and ends at (X[N-1],Y[N-1],Z[N-1]). - -Same as PSpline2Build() function, but for 3D, so we won't duplicate its -description here. - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::pspline3build( - real_2d_array xy, - ae_int_t n, - ae_int_t st, - ae_int_t pt, - pspline3interpolant& p, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function builds periodic 3-dimensional parametric spline which -starts at (X[0],Y[0],Z[0]), goes through all points to (X[N-1],Y[N-1],Z[N-1]) -and then back to (X[0],Y[0],Z[0]). - -Same as PSpline2Build() function, but for 3D, so we won't duplicate its -description here. - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::pspline3buildperiodic( - real_2d_array xy, - ae_int_t n, - ae_int_t st, - ae_int_t pt, - pspline3interpolant& p, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates the value of the parametric spline for a given -value of parameter T. - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-position - Y - Y-position - Z - Z-position - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::pspline3calc( - pspline3interpolant p, - double t, - double& x, - double& y, - double& z, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates derivative, i.e. it returns (dX/dT,dY/dT,dZ/dT). - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-value - DX - X-derivative - Y - Y-value - DY - Y-derivative - Z - Z-value - DZ - Z-derivative - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::pspline3diff( - pspline3interpolant p, - double t, - double& x, - double& dx, - double& y, - double& dy, - double& z, - double& dz, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates first and second derivative with respect to T. - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-value - DX - derivative - D2X - second derivative - Y - Y-value - DY - derivative - D2Y - second derivative - Z - Z-value - DZ - derivative - D2Z - second derivative - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::pspline3diff2( - pspline3interpolant p, - double t, - double& x, - double& dx, - double& d2x, - double& y, - double& dy, - double& d2y, - double& z, - double& dz, - double& d2z, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function returns vector of parameter values correspoding to points. - -Same as PSpline2ParameterValues(), but for 3D. - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::pspline3parametervalues( - pspline3interpolant p, - ae_int_t& n, - real_1d_array& t, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates tangent vector for a given value of parameter T - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-component of tangent vector (normalized) - Y - Y-component of tangent vector (normalized) - Z - Z-component of tangent vector (normalized) - -NOTE: - X^2+Y^2+Z^2 is either 1 (for non-zero tangent vector) or 0. - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::pspline3tangent( - pspline3interpolant p, - double t, - double& x, - double& y, - double& z, - const xparams _params = alglib::xdefault); - -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // We use RDP algorithm to approximate parametric 2D curve given by
-    // locations in t=0,1,2,3 (see below), which form piecewise linear
-    // trajectory through D-dimensional space (2-dimensional in our example).
-    // 
-    //     |
-    //     |
-    //     -     *     *     X2................X3
-    //     |                .
-    //     |               .
-    //     -     *     *  .  *     *     *     *
-    //     |             .
-    //     |            .
-    //     -     *     X1    *     *     *     *
-    //     |      .....
-    //     |  ....
-    //     X0----|-----|-----|-----|-----|-----|---
-    //
-    ae_int_t npoints = 4;
-    ae_int_t ndimensions = 2;
-    real_2d_array x = "[[0,0],[2,1],[3,3],[6,3]]";
-
-    //
-    // Approximation of parametric curve is performed by another parametric curve
-    // with lesser amount of points. It allows to work with "compressed"
-    // representation, which needs smaller amount of memory. Say, in our example
-    // (we allow points with error smaller than 0.8) approximation will have
-    // just two sequential sections connecting X0 with X2, and X2 with X3.
-    // 
-    //     |
-    //     |
-    //     -     *     *     X2................X3
-    //     |               . 
-    //     |             .  
-    //     -     *     .     *     *     *     *
-    //     |         .    
-    //     |       .     
-    //     -     .     X1    *     *     *     *
-    //     |   .       
-    //     | .    
-    //     X0----|-----|-----|-----|-----|-----|---
-    //
-    //
-    real_2d_array y;
-    integer_1d_array idxy;
-    ae_int_t nsections;
-    ae_int_t limitcnt = 0;
-    double limiteps = 0.8;
-    parametricrdpfixed(x, npoints, ndimensions, limitcnt, limiteps, y, idxy, nsections);
-    printf("%d\n", int(nsections)); // EXPECTED: 2
-    printf("%s\n", idxy.tostring().c_str()); // EXPECTED: [0,2,3]
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* -Principal components analysis - -This function builds orthogonal basis where first axis corresponds to -direction with maximum variance, second axis maximizes variance in the -subspace orthogonal to first axis and so on. - -This function builds FULL basis, i.e. returns N vectors corresponding to -ALL directions, no matter how informative. If you need just a few (say, -10 or 50) of the most important directions, you may find it faster to use -one of the reduced versions: -* pcatruncatedsubspace() - for subspace iteration based method - -It should be noted that, unlike LDA, PCA does not use class labels. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - dataset, array[0..NPoints-1,0..NVars-1]. - matrix contains ONLY INDEPENDENT VARIABLES. - NPoints - dataset size, NPoints>=0 - NVars - number of independent variables, NVars>=1 - -OUTPUT PARAMETERS: - Info - return code: - * -4, if SVD subroutine haven't converged - * -1, if wrong parameters has been passed (NPoints<0, - NVars<1) - * 1, if task is solved - S2 - array[0..NVars-1]. variance values corresponding - to basis vectors. - V - array[0..NVars-1,0..NVars-1] - matrix, whose columns store basis vectors. - - -- ALGLIB -- - Copyright 25.08.2008 by Bochkanov Sergey -*************************************************************************/ -
void alglib::pcabuildbasis( - real_2d_array x, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t& info, - real_1d_array& s2, - real_2d_array& v, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Principal components analysis - -This function performs truncated PCA, i.e. returns just a few most important -directions. - -Internally it uses iterative eigensolver which is very efficient when only -a minor fraction of full basis is required. Thus, if you need full basis, -it is better to use pcabuildbasis() function. - -It should be noted that, unlike LDA, PCA does not use class labels. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - dataset, array[0..NPoints-1,0..NVars-1]. - matrix contains ONLY INDEPENDENT VARIABLES. - NPoints - dataset size, NPoints>=0 - NVars - number of independent variables, NVars>=1 - NNeeded - number of requested components, in [1,NVars] range; - this function is efficient only for NNeeded<<NVars. - Eps - desired precision of vectors returned; underlying - solver will stop iterations as soon as absolute error - in corresponding singular values reduces to roughly - eps*MAX(lambda[]), with lambda[] being array of eigen - values. - Zero value means that algorithm performs number of - iterations specified by maxits parameter, without - paying attention to precision. - MaxIts - number of iterations performed by subspace iteration - method. Zero value means that no limit on iteration - count is placed (eps-based stopping condition is used). - - -OUTPUT PARAMETERS: - S2 - array[NNeeded]. Variance values corresponding - to basis vectors. - V - array[NVars,NNeeded] - matrix, whose columns store basis vectors. - -NOTE: passing eps=0 and maxits=0 results in small eps being selected as -stopping condition. Exact value of automatically selected eps is version- --dependent. - - -- ALGLIB -- - Copyright 10.01.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::pcatruncatedsubspace( - real_2d_array x, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nneeded, - double eps, - ae_int_t maxits, - real_1d_array& s2, - real_2d_array& v, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Sparse truncated principal components analysis - -This function performs sparse truncated PCA, i.e. returns just a few most -important principal components for a sparse input X. - -Internally it uses iterative eigensolver which is very efficient when only -a minor fraction of full basis is required. - -It should be noted that, unlike LDA, PCA does not use class labels. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - sparse dataset, sparse npoints*nvars matrix. It is - recommended to use CRS sparse storage format; non-CRS - input will be internally converted to CRS. - Matrix contains ONLY INDEPENDENT VARIABLES, and must - be EXACTLY npoints*nvars. - NPoints - dataset size, NPoints>=0 - NVars - number of independent variables, NVars>=1 - NNeeded - number of requested components, in [1,NVars] range; - this function is efficient only for NNeeded<<NVars. - Eps - desired precision of vectors returned; underlying - solver will stop iterations as soon as absolute error - in corresponding singular values reduces to roughly - eps*MAX(lambda[]), with lambda[] being array of eigen - values. - Zero value means that algorithm performs number of - iterations specified by maxits parameter, without - paying attention to precision. - MaxIts - number of iterations performed by subspace iteration - method. Zero value means that no limit on iteration - count is placed (eps-based stopping condition is used). - - -OUTPUT PARAMETERS: - S2 - array[NNeeded]. Variance values corresponding - to basis vectors. - V - array[NVars,NNeeded] - matrix, whose columns store basis vectors. - -NOTE: passing eps=0 and maxits=0 results in small eps being selected as - a stopping condition. Exact value of automatically selected eps is - version-dependent. - -NOTE: zero MaxIts is silently replaced by some reasonable value which - prevents eternal loops (possible when inputs are degenerate and too - stringent stopping criteria are specified). In current version it - is 50+2*NVars. - - -- ALGLIB -- - Copyright 10.01.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::pcatruncatedsubspacesparse( - sparsematrix x, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nneeded, - double eps, - ae_int_t maxits, - real_1d_array& s2, - real_2d_array& v, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -Inverse Poisson distribution - -Finds the Poisson variable x such that the integral -from 0 to x of the Poisson density is equal to the -given probability y. - -This is accomplished using the inverse gamma integral -function and the relation - - m = igami( k+1, y ). - -ACCURACY: - -See inverse incomplete gamma function - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::invpoissondistribution( - ae_int_t k, - double y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Complemented Poisson distribution - -Returns the sum of the terms k+1 to infinity of the Poisson -distribution: - - inf. j - -- -m m - > e -- - -- j! - j=k+1 - -The terms are not summed directly; instead the incomplete -gamma integral is employed, according to the formula - -y = pdtrc( k, m ) = igam( k+1, m ). - -The arguments must both be positive. - -ACCURACY: - -See incomplete gamma function - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::poissoncdistribution( - ae_int_t k, - double m, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Poisson distribution - -Returns the sum of the first k+1 terms of the Poisson -distribution: - - k j - -- -m m - > e -- - -- j! - j=0 - -The terms are not summed directly; instead the incomplete -gamma integral is employed, according to the relation - -y = pdtr( k, m ) = igamc( k+1, m ). - -The arguments must both be positive. -ACCURACY: - -See incomplete gamma function - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::poissondistribution( - ae_int_t k, - double m, - const xparams _params = alglib::xdefault); - -
- -
- -polynomialbar2cheb
-polynomialbar2pow
-polynomialbuild
-polynomialbuildcheb1
-polynomialbuildcheb2
-polynomialbuildeqdist
-polynomialcalccheb1
-polynomialcalccheb2
-polynomialcalceqdist
-polynomialcheb2bar
-polynomialpow2bar
- - - - - -
polint_d_calcdiff Interpolation and differentiation using barycentric representation
polint_d_conv Conversion between power basis and barycentric representation
polint_d_spec Polynomial interpolation on special grids (equidistant, Chebyshev I/II)
- -
-
/************************************************************************* -Conversion from barycentric representation to Chebyshev basis. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - P - polynomial in barycentric form - A,B - base interval for Chebyshev polynomials (see below) - A<>B - -OUTPUT PARAMETERS - T - coefficients of Chebyshev representation; - P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N-1 }, - where Ti - I-th Chebyshev polynomial. - -NOTES: - barycentric interpolant passed as P may be either polynomial obtained - from polynomial interpolation/ fitting or rational function which is - NOT polynomial. We can't distinguish between these two cases, and this - algorithm just tries to work assuming that P IS a polynomial. If not, - algorithm will return results, but they won't have any meaning. - - -- ALGLIB -- - Copyright 30.09.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::polynomialbar2cheb( - barycentricinterpolant p, - double a, - double b, - real_1d_array& t, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Conversion from barycentric representation to power basis. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - P - polynomial in barycentric form - C - offset (see below); 0.0 is used as default value. - S - scale (see below); 1.0 is used as default value. S<>0. - -OUTPUT PARAMETERS - A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 } - N - number of coefficients (polynomial degree plus 1) - -NOTES: -1. this function accepts offset and scale, which can be set to improve - numerical properties of polynomial. For example, if P was obtained as - result of interpolation on [-1,+1], you can set C=0 and S=1 and - represent P as sum of 1, x, x^2, x^3 and so on. In most cases you it - is exactly what you need. - - However, if your interpolation model was built on [999,1001], you will - see significant growth of numerical errors when using {1, x, x^2, x^3} - as basis. Representing P as sum of 1, (x-1000), (x-1000)^2, (x-1000)^3 - will be better option. Such representation can be obtained by using - 1000.0 as offset C and 1.0 as scale S. - -2. power basis is ill-conditioned and tricks described above can't solve - this problem completely. This function will return coefficients in - any case, but for N>8 they will become unreliable. However, N's - less than 5 are pretty safe. - -3. barycentric interpolant passed as P may be either polynomial obtained - from polynomial interpolation/ fitting or rational function which is - NOT polynomial. We can't distinguish between these two cases, and this - algorithm just tries to work assuming that P IS a polynomial. If not, - algorithm will return results, but they won't have any meaning. - - -- ALGLIB -- - Copyright 30.09.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::polynomialbar2pow( - barycentricinterpolant p, - real_1d_array& a, - const xparams _params = alglib::xdefault); -void alglib::polynomialbar2pow( - barycentricinterpolant p, - double c, - double s, - real_1d_array& a, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Lagrange intepolant: generation of the model on the general grid. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - X - abscissas, array[0..N-1] - Y - function values, array[0..N-1] - N - number of points, N>=1 - -OUTPUT PARAMETERS - P - barycentric model which represents Lagrange interpolant - (see ratint unit info and BarycentricCalc() description for - more information). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::polynomialbuild( - real_1d_array x, - real_1d_array y, - barycentricinterpolant& p, - const xparams _params = alglib::xdefault); -void alglib::polynomialbuild( - real_1d_array x, - real_1d_array y, - ae_int_t n, - barycentricinterpolant& p, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Lagrange intepolant on Chebyshev grid (first kind). -This function has O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - Y - function values at the nodes, array[0..N-1], - Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n))) - N - number of points, N>=1 - for N=1 a constant model is constructed. - -OUTPUT PARAMETERS - P - barycentric model which represents Lagrange interpolant - (see ratint unit info and BarycentricCalc() description for - more information). - - -- ALGLIB -- - Copyright 03.12.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::polynomialbuildcheb1( - double a, - double b, - real_1d_array y, - barycentricinterpolant& p, - const xparams _params = alglib::xdefault); -void alglib::polynomialbuildcheb1( - double a, - double b, - real_1d_array y, - ae_int_t n, - barycentricinterpolant& p, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Lagrange intepolant on Chebyshev grid (second kind). -This function has O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - Y - function values at the nodes, array[0..N-1], - Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1))) - N - number of points, N>=1 - for N=1 a constant model is constructed. - -OUTPUT PARAMETERS - P - barycentric model which represents Lagrange interpolant - (see ratint unit info and BarycentricCalc() description for - more information). - - -- ALGLIB -- - Copyright 03.12.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::polynomialbuildcheb2( - double a, - double b, - real_1d_array y, - barycentricinterpolant& p, - const xparams _params = alglib::xdefault); -void alglib::polynomialbuildcheb2( - double a, - double b, - real_1d_array y, - ae_int_t n, - barycentricinterpolant& p, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Lagrange intepolant: generation of the model on equidistant grid. -This function has O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - Y - function values at the nodes, array[0..N-1] - N - number of points, N>=1 - for N=1 a constant model is constructed. - -OUTPUT PARAMETERS - P - barycentric model which represents Lagrange interpolant - (see ratint unit info and BarycentricCalc() description for - more information). - - -- ALGLIB -- - Copyright 03.12.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::polynomialbuildeqdist( - double a, - double b, - real_1d_array y, - barycentricinterpolant& p, - const xparams _params = alglib::xdefault); -void alglib::polynomialbuildeqdist( - double a, - double b, - real_1d_array y, - ae_int_t n, - barycentricinterpolant& p, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Fast polynomial interpolation function on Chebyshev points (first kind) -with O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - F - function values, array[0..N-1] - N - number of points on Chebyshev grid (first kind), - X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n)) - for N=1 a constant model is constructed. - T - position where P(x) is calculated - -RESULT - value of the Lagrange interpolant at T - -IMPORTANT - this function provides fast interface which is not overflow-safe - nor it is very precise. - the best option is to use PolIntBuildCheb1()/BarycentricCalc() - subroutines unless you are pretty sure that your data will not result - in overflow. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -
double alglib::polynomialcalccheb1( - double a, - double b, - real_1d_array f, - double t, - const xparams _params = alglib::xdefault); -double alglib::polynomialcalccheb1( - double a, - double b, - real_1d_array f, - ae_int_t n, - double t, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Fast polynomial interpolation function on Chebyshev points (second kind) -with O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - F - function values, array[0..N-1] - N - number of points on Chebyshev grid (second kind), - X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1)) - for N=1 a constant model is constructed. - T - position where P(x) is calculated - -RESULT - value of the Lagrange interpolant at T - -IMPORTANT - this function provides fast interface which is not overflow-safe - nor it is very precise. - the best option is to use PolIntBuildCheb2()/BarycentricCalc() - subroutines unless you are pretty sure that your data will not result - in overflow. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -
double alglib::polynomialcalccheb2( - double a, - double b, - real_1d_array f, - double t, - const xparams _params = alglib::xdefault); -double alglib::polynomialcalccheb2( - double a, - double b, - real_1d_array f, - ae_int_t n, - double t, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Fast equidistant polynomial interpolation function with O(N) complexity - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - F - function values, array[0..N-1] - N - number of points on equidistant grid, N>=1 - for N=1 a constant model is constructed. - T - position where P(x) is calculated - -RESULT - value of the Lagrange interpolant at T - -IMPORTANT - this function provides fast interface which is not overflow-safe - nor it is very precise. - the best option is to use PolynomialBuildEqDist()/BarycentricCalc() - subroutines unless you are pretty sure that your data will not result - in overflow. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -
double alglib::polynomialcalceqdist( - double a, - double b, - real_1d_array f, - double t, - const xparams _params = alglib::xdefault); -double alglib::polynomialcalceqdist( - double a, - double b, - real_1d_array f, - ae_int_t n, - double t, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Conversion from Chebyshev basis to barycentric representation. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - T - coefficients of Chebyshev representation; - P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N }, - where Ti - I-th Chebyshev polynomial. - N - number of coefficients: - * if given, only leading N elements of T are used - * if not given, automatically determined from size of T - A,B - base interval for Chebyshev polynomials (see above) - A<B - -OUTPUT PARAMETERS - P - polynomial in barycentric form - - -- ALGLIB -- - Copyright 30.09.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::polynomialcheb2bar( - real_1d_array t, - double a, - double b, - barycentricinterpolant& p, - const xparams _params = alglib::xdefault); -void alglib::polynomialcheb2bar( - real_1d_array t, - ae_int_t n, - double a, - double b, - barycentricinterpolant& p, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Conversion from power basis to barycentric representation. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 } - N - number of coefficients (polynomial degree plus 1) - * if given, only leading N elements of A are used - * if not given, automatically determined from size of A - C - offset (see below); 0.0 is used as default value. - S - scale (see below); 1.0 is used as default value. S<>0. - -OUTPUT PARAMETERS - P - polynomial in barycentric form - - -NOTES: -1. this function accepts offset and scale, which can be set to improve - numerical properties of polynomial. For example, if you interpolate on - [-1,+1], you can set C=0 and S=1 and convert from sum of 1, x, x^2, - x^3 and so on. In most cases you it is exactly what you need. - - However, if your interpolation model was built on [999,1001], you will - see significant growth of numerical errors when using {1, x, x^2, x^3} - as input basis. Converting from sum of 1, (x-1000), (x-1000)^2, - (x-1000)^3 will be better option (you have to specify 1000.0 as offset - C and 1.0 as scale S). - -2. power basis is ill-conditioned and tricks described above can't solve - this problem completely. This function will return barycentric model - in any case, but for N>8 accuracy well degrade. However, N's less than - 5 are pretty safe. - - -- ALGLIB -- - Copyright 30.09.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::polynomialpow2bar( - real_1d_array a, - barycentricinterpolant& p, - const xparams _params = alglib::xdefault); -void alglib::polynomialpow2bar( - real_1d_array a, - ae_int_t n, - double c, - double s, - barycentricinterpolant& p, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // Here we demonstrate polynomial interpolation and differentiation
-    // of y=x^2-x sampled at [0,1,2]. Barycentric representation of polynomial is used.
-    //
-    real_1d_array x = "[0,1,2]";
-    real_1d_array y = "[0,0,2]";
-    double t = -1;
-    double v;
-    double dv;
-    double d2v;
-    barycentricinterpolant p;
-
-    // barycentric model is created
-    polynomialbuild(x, y, p);
-
-    // barycentric interpolation is demonstrated
-    v = barycentriccalc(p, t);
-    printf("%.4f\n", double(v)); // EXPECTED: 2.0
-
-    // barycentric differentation is demonstrated
-    barycentricdiff1(p, t, v, dv);
-    printf("%.4f\n", double(v)); // EXPECTED: 2.0
-    printf("%.4f\n", double(dv)); // EXPECTED: -3.0
-
-    // second derivatives with barycentric representation
-    barycentricdiff1(p, t, v, dv);
-    printf("%.4f\n", double(v)); // EXPECTED: 2.0
-    printf("%.4f\n", double(dv)); // EXPECTED: -3.0
-    barycentricdiff2(p, t, v, dv, d2v);
-    printf("%.4f\n", double(v)); // EXPECTED: 2.0
-    printf("%.4f\n", double(dv)); // EXPECTED: -3.0
-    printf("%.4f\n", double(d2v)); // EXPECTED: 2.0
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // Here we demonstrate conversion of y=x^2-x
-    // between power basis and barycentric representation.
-    //
-    real_1d_array a = "[0,-1,+1]";
-    double t = 2;
-    real_1d_array a2;
-    double v;
-    barycentricinterpolant p;
-
-    //
-    // a=[0,-1,+1] is decomposition of y=x^2-x in the power basis:
-    //
-    //     y = 0 - 1*x + 1*x^2
-    //
-    // We convert it to the barycentric form.
-    //
-    polynomialpow2bar(a, p);
-
-    // now we have barycentric interpolation; we can use it for interpolation
-    v = barycentriccalc(p, t);
-    printf("%.2f\n", double(v)); // EXPECTED: 2.0
-
-    // we can also convert back from barycentric representation to power basis
-    polynomialbar2pow(p, a2);
-    printf("%s\n", a2.tostring(2).c_str()); // EXPECTED: [0,-1,+1]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // Temporaries:
-    // * values of y=x^2-x sampled at three special grids:
-    //   * equdistant grid spanning [0,2],     x[i] = 2*i/(N-1), i=0..N-1
-    //   * Chebyshev-I grid spanning [-1,+1],  x[i] = 1 + Cos(PI*(2*i+1)/(2*n)), i=0..N-1
-    //   * Chebyshev-II grid spanning [-1,+1], x[i] = 1 + Cos(PI*i/(n-1)), i=0..N-1
-    // * barycentric interpolants for these three grids
-    // * vectors to store coefficients of quadratic representation
-    //
-    real_1d_array y_eqdist = "[0,0,2]";
-    real_1d_array y_cheb1 = "[-0.116025,0.000000,1.616025]";
-    real_1d_array y_cheb2 = "[0,0,2]";
-    barycentricinterpolant p_eqdist;
-    barycentricinterpolant p_cheb1;
-    barycentricinterpolant p_cheb2;
-    real_1d_array a_eqdist;
-    real_1d_array a_cheb1;
-    real_1d_array a_cheb2;
-
-    //
-    // First, we demonstrate construction of barycentric interpolants on
-    // special grids. We unpack power representation to ensure that
-    // interpolant was built correctly.
-    //
-    // In all three cases we should get same quadratic function.
-    //
-    polynomialbuildeqdist(0.0, 2.0, y_eqdist, p_eqdist);
-    polynomialbar2pow(p_eqdist, a_eqdist);
-    printf("%s\n", a_eqdist.tostring(4).c_str()); // EXPECTED: [0,-1,+1]
-
-    polynomialbuildcheb1(-1, +1, y_cheb1, p_cheb1);
-    polynomialbar2pow(p_cheb1, a_cheb1);
-    printf("%s\n", a_cheb1.tostring(4).c_str()); // EXPECTED: [0,-1,+1]
-
-    polynomialbuildcheb2(-1, +1, y_cheb2, p_cheb2);
-    polynomialbar2pow(p_cheb2, a_cheb2);
-    printf("%s\n", a_cheb2.tostring(4).c_str()); // EXPECTED: [0,-1,+1]
-
-    //
-    // Now we demonstrate polynomial interpolation without construction 
-    // of the barycentricinterpolant structure.
-    //
-    // We calculate interpolant value at x=-2.
-    // In all three cases we should get same f=6
-    //
-    double t = -2;
-    double v;
-    v = polynomialcalceqdist(0.0, 2.0, y_eqdist, t);
-    printf("%.4f\n", double(v)); // EXPECTED: 6.0
-
-    v = polynomialcalccheb1(-1, +1, y_cheb1, t);
-    printf("%.4f\n", double(v)); // EXPECTED: 6.0
-
-    v = polynomialcalccheb2(-1, +1, y_cheb2, t);
-    printf("%.4f\n", double(v)); // EXPECTED: 6.0
-    return 0;
-}
-
-
-
-
- -polynomialsolverreport
- -polynomialsolve
- - -
- -
-
/************************************************************************* - -*************************************************************************/ -
class polynomialsolverreport -{ - double maxerr; -}; - -
- -
-
/************************************************************************* -Polynomial root finding. - -This function returns all roots of the polynomial - P(x) = a0 + a1*x + a2*x^2 + ... + an*x^n -Both real and complex roots are returned (see below). - -INPUT PARAMETERS: - A - array[N+1], polynomial coefficients: - * A[0] is constant term - * A[N] is a coefficient of X^N - N - polynomial degree - -OUTPUT PARAMETERS: - X - array of complex roots: - * for isolated real root, X[I] is strictly real: IMAGE(X[I])=0 - * complex roots are always returned in pairs - roots occupy - positions I and I+1, with: - * X[I+1]=Conj(X[I]) - * IMAGE(X[I]) > 0 - * IMAGE(X[I+1]) = -IMAGE(X[I]) < 0 - * multiple real roots may have non-zero imaginary part due - to roundoff errors. There is no reliable way to distinguish - real root of multiplicity 2 from two complex roots in - the presence of roundoff errors. - Rep - report, additional information, following fields are set: - * Rep.MaxErr - max( |P(xi)| ) for i=0..N-1. This field - allows to quickly estimate "quality" of the roots being - returned. - -NOTE: this function uses companion matrix method to find roots. In case - internal EVD solver fails do find eigenvalues, exception is - generated. - -NOTE: roots are not "polished" and no matrix balancing is performed - for them. - - -- ALGLIB -- - Copyright 24.02.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::polynomialsolve( - real_1d_array a, - ae_int_t n, - complex_1d_array& x, - polynomialsolverreport& rep, - const xparams _params = alglib::xdefault); - -
- -
- -psi
- - -
- -
-
/************************************************************************* -Psi (digamma) function - - d - - psi(x) = -- ln | (x) - dx - -is the logarithmic derivative of the gamma function. -For integer x, - n-1 - - -psi(n) = -EUL + > 1/k. - - - k=1 - -This formula is used for 0 < n <= 10. If x is negative, it -is transformed to a positive argument by the reflection -formula psi(1-x) = psi(x) + pi cot(pi x). -For general positive x, the argument is made greater than 10 -using the recurrence psi(x+1) = psi(x) + 1/x. -Then the following asymptotic expansion is applied: - - inf. B - - 2k -psi(x) = log(x) - 1/2x - > ------- - - 2k - k=1 2k x - -where the B2k are Bernoulli numbers. - -ACCURACY: - Relative error (except absolute when |psi| < 1): -arithmetic domain # trials peak rms - IEEE 0,30 30000 1.3e-15 1.4e-16 - IEEE -30,0 40000 1.5e-15 2.2e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::psi(double x, const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -Barycentric interpolant. -*************************************************************************/ -
class barycentricinterpolant -{ -}; - -
- -
-
/************************************************************************* -Rational interpolant without poles - -The subroutine constructs the rational interpolating function without real -poles (see 'Barycentric rational interpolation with no poles and high -rates of approximation', Michael S. Floater. and Kai Hormann, for more -information on this subject). - -Input parameters: - X - interpolation nodes, array[0..N-1]. - Y - function values, array[0..N-1]. - N - number of nodes, N>0. - D - order of the interpolation scheme, 0 <= D <= N-1. - D<0 will cause an error. - D>=N it will be replaced with D=N-1. - if you don't know what D to choose, use small value about 3-5. - -Output parameters: - B - barycentric interpolant. - -Note: - this algorithm always succeeds and calculates the weights with close - to machine precision. - - -- ALGLIB PROJECT -- - Copyright 17.06.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::barycentricbuildfloaterhormann( - real_1d_array x, - real_1d_array y, - ae_int_t n, - ae_int_t d, - barycentricinterpolant& b, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Rational interpolant from X/Y/W arrays - -F(t) = SUM(i=0,n-1,w[i]*f[i]/(t-x[i])) / SUM(i=0,n-1,w[i]/(t-x[i])) - -INPUT PARAMETERS: - X - interpolation nodes, array[0..N-1] - F - function values, array[0..N-1] - W - barycentric weights, array[0..N-1] - N - nodes count, N>0 - -OUTPUT PARAMETERS: - B - barycentric interpolant built from (X, Y, W) - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::barycentricbuildxyw( - real_1d_array x, - real_1d_array y, - real_1d_array w, - ae_int_t n, - barycentricinterpolant& b, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Rational interpolation using barycentric formula - -F(t) = SUM(i=0,n-1,w[i]*f[i]/(t-x[i])) / SUM(i=0,n-1,w[i]/(t-x[i])) - -Input parameters: - B - barycentric interpolant built with one of model building - subroutines. - T - interpolation point - -Result: - barycentric interpolant F(t) - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -
double alglib::barycentriccalc( - barycentricinterpolant b, - double t, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Differentiation of barycentric interpolant: first derivative. - -Algorithm used in this subroutine is very robust and should not fail until -provided with values too close to MaxRealNumber (usually MaxRealNumber/N -or greater will overflow). - -INPUT PARAMETERS: - B - barycentric interpolant built with one of model building - subroutines. - T - interpolation point - -OUTPUT PARAMETERS: - F - barycentric interpolant at T - DF - first derivative - -NOTE - - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::barycentricdiff1( - barycentricinterpolant b, - double t, - double& f, - double& df, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Differentiation of barycentric interpolant: first/second derivatives. - -INPUT PARAMETERS: - B - barycentric interpolant built with one of model building - subroutines. - T - interpolation point - -OUTPUT PARAMETERS: - F - barycentric interpolant at T - DF - first derivative - D2F - second derivative - -NOTE: this algorithm may fail due to overflow/underflor if used on data -whose values are close to MaxRealNumber or MinRealNumber. Use more robust -BarycentricDiff1() subroutine in such cases. - - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::barycentricdiff2( - barycentricinterpolant b, - double t, - double& f, - double& df, - double& d2f, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine performs linear transformation of the argument. - -INPUT PARAMETERS: - B - rational interpolant in barycentric form - CA, CB - transformation coefficients: x = CA*t + CB - -OUTPUT PARAMETERS: - B - transformed interpolant with X replaced by T - - -- ALGLIB PROJECT -- - Copyright 19.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::barycentriclintransx( - barycentricinterpolant b, - double ca, - double cb, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine performs linear transformation of the barycentric -interpolant. - -INPUT PARAMETERS: - B - rational interpolant in barycentric form - CA, CB - transformation coefficients: B2(x) = CA*B(x) + CB - -OUTPUT PARAMETERS: - B - transformed interpolant - - -- ALGLIB PROJECT -- - Copyright 19.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::barycentriclintransy( - barycentricinterpolant b, - double ca, - double cb, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Extracts X/Y/W arrays from rational interpolant - -INPUT PARAMETERS: - B - barycentric interpolant - -OUTPUT PARAMETERS: - N - nodes count, N>0 - X - interpolation nodes, array[0..N-1] - F - function values, array[0..N-1] - W - barycentric weights, array[0..N-1] - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -
void alglib::barycentricunpack( - barycentricinterpolant b, - ae_int_t& n, - real_1d_array& x, - real_1d_array& y, - real_1d_array& w, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -Buffer object which is used to perform nearest neighbor requests in the -multithreaded mode (multiple threads working with same KD-tree object). - -This object should be created with KDTreeCreateBuffer(). -*************************************************************************/ -
class rbfcalcbuffer -{ -}; - -
- -
-
/************************************************************************* -RBF model. - -Never try to directly work with fields of this object - always use ALGLIB -functions to use this object. -*************************************************************************/ -
class rbfmodel -{ -}; - -
- -
-
/************************************************************************* -RBF solution report: -* TerminationType - termination type, positive values - success, - non-positive - failure. - -Fields which are set by modern RBF solvers (hierarchical): -* RMSError - root-mean-square error; NAN for old solvers (ML, QNN) -* MaxError - maximum error; NAN for old solvers (ML, QNN) -*************************************************************************/ -
class rbfreport -{ - double rmserror; - double maxerror; - ae_int_t arows; - ae_int_t acols; - ae_int_t annz; - ae_int_t iterationscount; - ae_int_t nmv; - ae_int_t terminationtype; -}; - -
- -
-
/************************************************************************* -This function builds RBF model and returns report (contains some -information which can be used for evaluation of the algorithm properties). - -Call to this function modifies RBF model by calculating its centers/radii/ -weights and saving them into RBFModel structure. Initially RBFModel -contain zero coefficients, but after call to this function we will have -coefficients which were calculated in order to fit our dataset. - -After you called this function you can call RBFCalc(), RBFGridCalc() and -other model calculation functions. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - Rep - report: - * Rep.TerminationType: - * -5 - non-distinct basis function centers were detected, - interpolation aborted; only QNN returns this - error code, other algorithms can handle non- - distinct nodes. - * -4 - nonconvergence of the internal SVD solver - * -3 incorrect model construction algorithm was chosen: - QNN or RBF-ML, combined with one of the incompatible - features - NX=1 or NX>3; points with per-dimension - scales. - * 1 - successful termination - * 8 - a termination request was submitted via - rbfrequesttermination() function. - - Fields which are set only by modern RBF solvers (hierarchical - or nonnegative; older solvers like QNN and ML initialize these - fields by NANs): - * rep.rmserror - root-mean-square error at nodes - * rep.maxerror - maximum error at nodes - - Fields are used for debugging purposes: - * Rep.IterationsCount - iterations count of the LSQR solver - * Rep.NMV - number of matrix-vector products - * Rep.ARows - rows count for the system matrix - * Rep.ACols - columns count for the system matrix - * Rep.ANNZ - number of significantly non-zero elements - (elements above some algorithm-determined threshold) - -NOTE: failure to build model will leave current state of the structure -unchanged. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfbuildmodel( - rbfmodel s, - rbfreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -This function calculates values of the RBF model at the given point. - -This is general function which can be used for arbitrary NX (dimension of -the space of arguments) and NY (dimension of the function itself). However -when you have NY=1 you may find more convenient to use rbfcalc2() or -rbfcalc3(). - -If you want to perform parallel model evaluation from multiple threads, -use rbftscalcbuf() with per-thread buffer object. - -This function returns 0.0 when model is not initialized. - -INPUT PARAMETERS: - S - RBF model - X - coordinates, array[NX]. - X may have more than NX elements, in this case only - leading NX will be used. - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is out-parameter and - reallocated after call to this function. In case you want - to reuse previously allocated Y, you may use RBFCalcBuf(), - which reallocates Y only when it is too small. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfcalc( - rbfmodel s, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function calculates values of the RBF model in the given point. - -IMPORTANT: this function works only with modern (hierarchical) RBFs. It - can not be used with legacy (version 1) RBFs because older RBF - code does not support 1-dimensional models. - -This function should be used when we have NY=1 (scalar function) and NX=1 -(1-dimensional space). If you have 3-dimensional space, use rbfcalc3(). If -you have 2-dimensional space, use rbfcalc3(). If you have general -situation (NX-dimensional space, NY-dimensional function) you should use -generic rbfcalc(). - -If you want to perform parallel model evaluation from multiple threads, -use rbftscalcbuf() with per-thread buffer object. - -This function returns 0.0 when: -* model is not initialized -* NX<>1 -* NY<>1 - -INPUT PARAMETERS: - S - RBF model - X0 - X-coordinate, finite number - -RESULT: - value of the model or 0.0 (as defined above) - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -
double alglib::rbfcalc1( - rbfmodel s, - double x0, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates values of the RBF model in the given point. - -This function should be used when we have NY=1 (scalar function) and NX=2 -(2-dimensional space). If you have 3-dimensional space, use rbfcalc3(). If -you have general situation (NX-dimensional space, NY-dimensional function) -you should use generic rbfcalc(). - -If you want to calculate function values many times, consider using -rbfgridcalc2v(), which is far more efficient than many subsequent calls to -rbfcalc2(). - -If you want to perform parallel model evaluation from multiple threads, -use rbftscalcbuf() with per-thread buffer object. - -This function returns 0.0 when: -* model is not initialized -* NX<>2 - *NY<>1 - -INPUT PARAMETERS: - S - RBF model - X0 - first coordinate, finite number - X1 - second coordinate, finite number - -RESULT: - value of the model or 0.0 (as defined above) - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -
double alglib::rbfcalc2( - rbfmodel s, - double x0, - double x1, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function calculates value of the RBF model in the given point. - -This function should be used when we have NY=1 (scalar function) and NX=3 -(3-dimensional space). If you have 2-dimensional space, use rbfcalc2(). If -you have general situation (NX-dimensional space, NY-dimensional function) -you should use generic rbfcalc(). - -If you want to calculate function values many times, consider using -rbfgridcalc3v(), which is far more efficient than many subsequent calls to -rbfcalc3(). - -If you want to perform parallel model evaluation from multiple threads, -use rbftscalcbuf() with per-thread buffer object. - -This function returns 0.0 when: -* model is not initialized -* NX<>3 - *NY<>1 - -INPUT PARAMETERS: - S - RBF model - X0 - first coordinate, finite number - X1 - second coordinate, finite number - X2 - third coordinate, finite number - -RESULT: - value of the model or 0.0 (as defined above) - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -
double alglib::rbfcalc3( - rbfmodel s, - double x0, - double x1, - double x2, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates values of the RBF model at the given point. - -Same as rbfcalc(), but does not reallocate Y when in is large enough to -store function values. - -If you want to perform parallel model evaluation from multiple threads, -use rbftscalcbuf() with per-thread buffer object. - -INPUT PARAMETERS: - S - RBF model - X - coordinates, array[NX]. - X may have more than NX elements, in this case only - leading NX will be used. - Y - possibly preallocated array - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is not reallocated when it - is larger than NY. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfcalcbuf( - rbfmodel s, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function creates RBF model for a scalar (NY=1) or vector (NY>1) -function in a NX-dimensional space (NX>=1). - -Newly created model is empty. It can be used for interpolation right after -creation, but it just returns zeros. You have to add points to the model, -tune interpolation settings, and then call model construction function -rbfbuildmodel() which will update model according to your specification. - -USAGE: -1. User creates model with rbfcreate() -2. User adds dataset with rbfsetpoints() (points do NOT have to be on a - regular grid) or rbfsetpointsandscales(). -3. (OPTIONAL) User chooses polynomial term by calling: - * rbflinterm() to set linear term - * rbfconstterm() to set constant term - * rbfzeroterm() to set zero term - By default, linear term is used. -4. User tweaks algorithm properties with rbfsetalgohierarchical() method - (or chooses one of the legacy algorithms - QNN (rbfsetalgoqnn) or ML - (rbfsetalgomultilayer)). -5. User calls rbfbuildmodel() function which rebuilds model according to - the specification -6. User may call rbfcalc() to calculate model value at the specified point, - rbfgridcalc() to calculate model values at the points of the regular - grid. User may extract model coefficients with rbfunpack() call. - -IMPORTANT: we recommend you to use latest model construction algorithm - - hierarchical RBFs, which is activated by rbfsetalgohierarchical() - function. This algorithm is the fastest one, and most memory- - efficient. - However, it is incompatible with older versions of ALGLIB - (pre-3.11). So, if you serialize hierarchical model, you will - be unable to load it in pre-3.11 ALGLIB. Other model types (QNN - and RBF-ML) are still backward-compatible. - -INPUT PARAMETERS: - NX - dimension of the space, NX>=1 - NY - function dimension, NY>=1 - -OUTPUT PARAMETERS: - S - RBF model (initially equals to zero) - -NOTE 1: memory requirements. RBF models require amount of memory which is - proportional to the number of data points. Some additional memory - is allocated during model construction, but most of this memory is - freed after model coefficients are calculated. Amount of this - additional memory depends on model construction algorithm being - used. - -NOTE 2: prior to ALGLIB version 3.11, RBF models supported only NX=2 or - NX=3. Any attempt to create single-dimensional or more than - 3-dimensional RBF model resulted in exception. - - ALGLIB 3.11 supports any NX>0, but models created with NX!=2 and - NX!=3 are incompatible with (a) older versions of ALGLIB, (b) old - model construction algorithms (QNN or RBF-ML). - - So, if you create a model with NX=2 or NX=3, then, depending on - specific model construction algorithm being chosen, you will (QNN - and RBF-ML) or will not (HierarchicalRBF) get backward compatibility - with older versions of ALGLIB. You have a choice here. - - However, if you create a model with NX neither 2 nor 3, you have - no backward compatibility from the start, and you are forced to - use hierarchical RBFs and ALGLIB 3.11 or later. - - -- ALGLIB -- - Copyright 13.12.2011, 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfcreate( - ae_int_t nx, - ae_int_t ny, - rbfmodel& s, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  [4]  

- -
-
/************************************************************************* -This function creates buffer structure which can be used to perform -parallel RBF model evaluations (with one RBF model instance being -used from multiple threads, as long as different threads use different -instances of buffer). - -This buffer object can be used with rbftscalcbuf() function (here "ts" -stands for "thread-safe", "buf" is a suffix which denotes function which -reuses previously allocated output space). - -How to use it: -* create RBF model structure with rbfcreate() -* load data, tune parameters -* call rbfbuildmodel() -* call rbfcreatecalcbuffer(), once per thread working with RBF model (you - should call this function only AFTER call to rbfbuildmodel(), see below - for more information) -* call rbftscalcbuf() from different threads, with each thread working - with its own copy of buffer object. - -INPUT PARAMETERS - S - RBF model - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: buffer object should be used only with RBF model object which - was used to initialize buffer. Any attempt to use buffer with - different object is dangerous - you may get memory violation - error because sizes of internal arrays do not fit to dimensions - of RBF structure. - -IMPORTANT: you should call this function only for model which was built - with rbfbuildmodel() function, after successful invocation of - rbfbuildmodel(). Sizes of some internal structures are - determined only after model is built, so buffer object created - before model construction stage will be useless (and any - attempt to use it will result in exception). - - -- ALGLIB -- - Copyright 02.04.2016 by Sergey Bochkanov -*************************************************************************/ -
void alglib::rbfcreatecalcbuffer( - rbfmodel s, - rbfcalcbuffer& buf, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function returns model version. - -INPUT PARAMETERS: - S - RBF model - -RESULT: - * 1 - for models created by QNN and RBF-ML algorithms, - compatible with ALGLIB 3.10 or earlier. - * 2 - for models created by HierarchicalRBF, requires - ALGLIB 3.11 or later - - -- ALGLIB -- - Copyright 06.07.2016 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::rbfgetmodelversion( - rbfmodel s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is legacy function for gridded calculation of RBF model. - -It is superseded by rbfgridcalc2v() and rbfgridcalc2vsubset() functions. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfgridcalc2( - rbfmodel s, - real_1d_array x0, - ae_int_t n0, - real_1d_array x1, - ae_int_t n1, - real_2d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates values of the RBF model at the regular grid, -which has N0*N1 points, with Point[I,J] = (X0[I], X1[J]). Vector-valued -RBF models are supported. - -This function returns 0.0 when: -* model is not initialized -* NX<>2 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: Parallel processing is implemented only for modern (hierarchical) - RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still - processed serially. - -INPUT PARAMETERS: - S - RBF model, used in read-only mode, can be shared between - multiple invocations of this function from multiple - threads. - - X0 - array of grid nodes, first coordinates, array[N0]. - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N0 - grid size (number of nodes) in the first dimension - - X1 - array of grid nodes, second coordinates, array[N1] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N1 - grid size (number of nodes) in the second dimension - -OUTPUT PARAMETERS: - Y - function values, array[NY*N0*N1], where NY is a number of - "output" vector values (this function supports vector- - valued RBF models). Y is out-variable and is reallocated - by this function. - Y[K+NY*(I0+I1*N0)]=F_k(X0[I0],X1[I1]), for: - * K=0...NY-1 - * I0=0...N0-1 - * I1=0...N1-1 - -NOTE: this function supports weakly ordered grid nodes, i.e. you may have - X[i]=X[i+1] for some i. It does not provide you any performance - benefits due to duplication of points, just convenience and - flexibility. - -NOTE: this function is re-entrant, i.e. you may use same rbfmodel - structure in multiple threads calling this function for different - grids. - -NOTE: if you need function values on some subset of regular grid, which - may be described as "several compact and dense islands", you may - use rbfgridcalc2vsubset(). - - -- ALGLIB -- - Copyright 27.01.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfgridcalc2v( - rbfmodel s, - real_1d_array x0, - ae_int_t n0, - real_1d_array x1, - ae_int_t n1, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates values of the RBF model at some subset of regular -grid: -* grid has N0*N1 points, with Point[I,J] = (X0[I], X1[J]) -* only values at some subset of this grid are required -Vector-valued RBF models are supported. - -This function returns 0.0 when: -* model is not initialized -* NX<>2 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: Parallel processing is implemented only for modern (hierarchical) - RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still - processed serially. - -INPUT PARAMETERS: - S - RBF model, used in read-only mode, can be shared between - multiple invocations of this function from multiple - threads. - - X0 - array of grid nodes, first coordinates, array[N0]. - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N0 - grid size (number of nodes) in the first dimension - - X1 - array of grid nodes, second coordinates, array[N1] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N1 - grid size (number of nodes) in the second dimension - - FlagY - array[N0*N1]: - * Y[I0+I1*N0] corresponds to node (X0[I0],X1[I1]) - * it is a "bitmap" array which contains False for nodes - which are NOT calculated, and True for nodes which are - required. - -OUTPUT PARAMETERS: - Y - function values, array[NY*N0*N1*N2], where NY is a number - of "output" vector values (this function supports vector- - valued RBF models): - * Y[K+NY*(I0+I1*N0)]=F_k(X0[I0],X1[I1]), - for K=0...NY-1, I0=0...N0-1, I1=0...N1-1. - * elements of Y[] which correspond to FlagY[]=True are - loaded by model values (which may be exactly zero for - some nodes). - * elements of Y[] which correspond to FlagY[]=False MAY be - initialized by zeros OR may be calculated. This function - processes grid as a hierarchy of nested blocks and - micro-rows. If just one element of micro-row is required, - entire micro-row (up to 8 nodes in the current version, - but no promises) is calculated. - -NOTE: this function supports weakly ordered grid nodes, i.e. you may have - X[i]=X[i+1] for some i. It does not provide you any performance - benefits due to duplication of points, just convenience and - flexibility. - -NOTE: this function is re-entrant, i.e. you may use same rbfmodel - structure in multiple threads calling this function for different - grids. - - -- ALGLIB -- - Copyright 04.03.2016 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfgridcalc2vsubset( - rbfmodel s, - real_1d_array x0, - ae_int_t n0, - real_1d_array x1, - ae_int_t n1, - boolean_1d_array flagy, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates values of the RBF model at the regular grid, -which has N0*N1*N2 points, with Point[I,J,K] = (X0[I], X1[J], X2[K]). -Vector-valued RBF models are supported. - -This function returns 0.0 when: -* model is not initialized -* NX<>3 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: Parallel processing is implemented only for modern (hierarchical) - RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still - processed serially. - -INPUT PARAMETERS: - S - RBF model, used in read-only mode, can be shared between - multiple invocations of this function from multiple - threads. - - X0 - array of grid nodes, first coordinates, array[N0]. - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N0 - grid size (number of nodes) in the first dimension - - X1 - array of grid nodes, second coordinates, array[N1] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N1 - grid size (number of nodes) in the second dimension - - X2 - array of grid nodes, third coordinates, array[N2] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N2 - grid size (number of nodes) in the third dimension - -OUTPUT PARAMETERS: - Y - function values, array[NY*N0*N1*N2], where NY is a number - of "output" vector values (this function supports vector- - valued RBF models). Y is out-variable and is reallocated - by this function. - Y[K+NY*(I0+I1*N0+I2*N0*N1)]=F_k(X0[I0],X1[I1],X2[I2]), for: - * K=0...NY-1 - * I0=0...N0-1 - * I1=0...N1-1 - * I2=0...N2-1 - -NOTE: this function supports weakly ordered grid nodes, i.e. you may have - X[i]=X[i+1] for some i. It does not provide you any performance - benefits due to duplication of points, just convenience and - flexibility. - -NOTE: this function is re-entrant, i.e. you may use same rbfmodel - structure in multiple threads calling this function for different - grids. - -NOTE: if you need function values on some subset of regular grid, which - may be described as "several compact and dense islands", you may - use rbfgridcalc3vsubset(). - - -- ALGLIB -- - Copyright 04.03.2016 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfgridcalc3v( - rbfmodel s, - real_1d_array x0, - ae_int_t n0, - real_1d_array x1, - ae_int_t n1, - real_1d_array x2, - ae_int_t n2, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates values of the RBF model at some subset of regular -grid: -* grid has N0*N1*N2 points, with Point[I,J,K] = (X0[I], X1[J], X2[K]) -* only values at some subset of this grid are required -Vector-valued RBF models are supported. - -This function returns 0.0 when: -* model is not initialized -* NX<>3 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: Parallel processing is implemented only for modern (hierarchical) - RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still - processed serially. - -INPUT PARAMETERS: - S - RBF model, used in read-only mode, can be shared between - multiple invocations of this function from multiple - threads. - - X0 - array of grid nodes, first coordinates, array[N0]. - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N0 - grid size (number of nodes) in the first dimension - - X1 - array of grid nodes, second coordinates, array[N1] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N1 - grid size (number of nodes) in the second dimension - - X2 - array of grid nodes, third coordinates, array[N2] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N2 - grid size (number of nodes) in the third dimension - - FlagY - array[N0*N1*N2]: - * Y[I0+I1*N0+I2*N0*N1] corresponds to node (X0[I0],X1[I1],X2[I2]) - * it is a "bitmap" array which contains False for nodes - which are NOT calculated, and True for nodes which are - required. - -OUTPUT PARAMETERS: - Y - function values, array[NY*N0*N1*N2], where NY is a number - of "output" vector values (this function supports vector- - valued RBF models): - * Y[K+NY*(I0+I1*N0+I2*N0*N1)]=F_k(X0[I0],X1[I1],X2[I2]), - for K=0...NY-1, I0=0...N0-1, I1=0...N1-1, I2=0...N2-1. - * elements of Y[] which correspond to FlagY[]=True are - loaded by model values (which may be exactly zero for - some nodes). - * elements of Y[] which correspond to FlagY[]=False MAY be - initialized by zeros OR may be calculated. This function - processes grid as a hierarchy of nested blocks and - micro-rows. If just one element of micro-row is required, - entire micro-row (up to 8 nodes in the current version, - but no promises) is calculated. - -NOTE: this function supports weakly ordered grid nodes, i.e. you may have - X[i]=X[i+1] for some i. It does not provide you any performance - benefits due to duplication of points, just convenience and - flexibility. - -NOTE: this function is re-entrant, i.e. you may use same rbfmodel - structure in multiple threads calling this function for different - grids. - - -- ALGLIB -- - Copyright 04.03.2016 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfgridcalc3vsubset( - rbfmodel s, - real_1d_array x0, - ae_int_t n0, - real_1d_array x1, - ae_int_t n1, - real_1d_array x2, - ae_int_t n2, - boolean_1d_array flagy, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function is used to peek into hierarchical RBF construction process -from some other thread and get current progress indicator. It returns -value in [0,1]. - -IMPORTANT: only HRBFs (hierarchical RBFs) support peeking into progress - indicator. Legacy RBF-ML and RBF-QNN do not support it. You - will always get 0 value. - -INPUT PARAMETERS: - S - RBF model object - -RESULT: - progress value, in [0,1] - - -- ALGLIB -- - Copyright 17.11.2018 by Bochkanov Sergey -*************************************************************************/ -
double alglib::rbfpeekprogress( - rbfmodel s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function is used to submit a request for termination of the -hierarchical RBF construction process from some other thread. As result, -RBF construction is terminated smoothly (with proper deallocation of all -necessary resources) and resultant model is filled by zeros. - -A rep.terminationtype=8 will be returned upon receiving such request. - -IMPORTANT: only HRBFs (hierarchical RBFs) support termination requests. - Legacy RBF-ML and RBF-QNN do not support it. An attempt to - terminate their construction will be ignored. - -IMPORTANT: termination request flag is cleared when the model construction - starts. Thus, any pre-construction termination requests will be - silently ignored - only ones submitted AFTER construction has - actually began will be handled. - -INPUT PARAMETERS: - S - RBF model object - - -- ALGLIB -- - Copyright 17.11.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfrequesttermination( - rbfmodel s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -
void rbfserialize(rbfmodel &obj, std::string &s_out); -void rbfserialize(rbfmodel &obj, std::ostream &s_out); -
- -
-
/************************************************************************* -This function sets RBF interpolation algorithm. ALGLIB supports several -RBF algorithms with different properties. - -This algorithm is called Hierarchical RBF. It similar to its previous -incarnation, RBF-ML, i.e. it also builds a sequence of models with -decreasing radii. However, it uses more economical way of building upper -layers (ones with large radii), which results in faster model construction -and evaluation, as well as smaller memory footprint during construction. - -This algorithm has following important features: -* ability to handle millions of points -* controllable smoothing via nonlinearity penalization -* support for NX-dimensional models with NX=1 or NX>3 (unlike QNN or RBF-ML) -* support for specification of per-dimensional radii via scale vector, - which is set by means of rbfsetpointsandscales() function. This feature - is useful if you solve spatio-temporal interpolation problems, where - different radii are required for spatial and temporal dimensions. - -Running times are roughly proportional to: -* N*log(N)*NLayers - for model construction -* N*NLayers - for model evaluation -You may see that running time does not depend on search radius or points -density, just on number of layers in the hierarchy. - -IMPORTANT: this model construction algorithm was introduced in ALGLIB 3.11 - and produces models which are INCOMPATIBLE with previous - versions of ALGLIB. You can not unserialize models produced - with this function in ALGLIB 3.10 or earlier. - -INPUT PARAMETERS: - S - RBF model, initialized by rbfcreate() call - RBase - RBase parameter, RBase>0 - NLayers - NLayers parameter, NLayers>0, recommended value to start - with - about 5. - LambdaNS- >=0, nonlinearity penalty coefficient, negative values are - not allowed. This parameter adds controllable smoothing to - the problem, which may reduce noise. Specification of non- - zero lambda means that in addition to fitting error solver - will also minimize LambdaNS*|S''(x)|^2 (appropriately - generalized to multiple dimensions. - - Specification of exactly zero value means that no penalty - is added (we do not even evaluate matrix of second - derivatives which is necessary for smoothing). - - Calculation of nonlinearity penalty is costly - it results - in several-fold increase of model construction time. - Evaluation time remains the same. - - Optimal lambda is problem-dependent and requires trial - and error. Good value to start from is 1e-5...1e-6, - which corresponds to slightly noticeable smoothing of the - function. Value 1e-2 usually means that quite heavy - smoothing is applied. - -TUNING ALGORITHM - -In order to use this algorithm you have to choose three parameters: -* initial radius RBase -* number of layers in the model NLayers -* penalty coefficient LambdaNS - -Initial radius is easy to choose - you can pick any number several times -larger than the average distance between points. Algorithm won't break -down if you choose radius which is too large (model construction time will -increase, but model will be built correctly). - -Choose such number of layers that RLast=RBase/2^(NLayers-1) (radius used -by the last layer) will be smaller than the typical distance between -points. In case model error is too large, you can increase number of -layers. Having more layers will make model construction and evaluation -proportionally slower, but it will allow you to have model which precisely -fits your data. From the other side, if you want to suppress noise, you -can DECREASE number of layers to make your model less flexible (or specify -non-zero LambdaNS). - -TYPICAL ERRORS - -1. Using too small number of layers - RBF models with large radius are not - flexible enough to reproduce small variations in the target function. - You need many layers with different radii, from large to small, in - order to have good model. - -2. Using initial radius which is too small. You will get model with - "holes" in the areas which are too far away from interpolation centers. - However, algorithm will work correctly (and quickly) in this case. - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfsetalgohierarchical( - rbfmodel s, - double rbase, - ae_int_t nlayers, - double lambdans, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -DEPRECATED:since version 3.11 ALGLIB includes new RBF model construction - algorithm, Hierarchical RBF. This algorithm is faster and - requires less memory than QNN and RBF-ML. It is especially good - for large-scale interpolation problems. So, we recommend you to - consider Hierarchical RBF as default option. - -========================================================================== - -This function sets RBF interpolation algorithm. ALGLIB supports several -RBF algorithms with different properties. - -This algorithm is called RBF-ML. It builds multilayer RBF model, i.e. -model with subsequently decreasing radii, which allows us to combine -smoothness (due to large radii of the first layers) with exactness (due -to small radii of the last layers) and fast convergence. - -Internally RBF-ML uses many different means of acceleration, from sparse -matrices to KD-trees, which results in algorithm whose working time is -roughly proportional to N*log(N)*Density*RBase^2*NLayers, where N is a -number of points, Density is an average density if points per unit of the -interpolation space, RBase is an initial radius, NLayers is a number of -layers. - -RBF-ML is good for following kinds of interpolation problems: -1. "exact" problems (perfect fit) with well separated points -2. least squares problems with arbitrary distribution of points (algorithm - gives perfect fit where it is possible, and resorts to least squares - fit in the hard areas). -3. noisy problems where we want to apply some controlled amount of - smoothing. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - RBase - RBase parameter, RBase>0 - NLayers - NLayers parameter, NLayers>0, recommended value to start - with - about 5. - LambdaV - regularization value, can be useful when solving problem - in the least squares sense. Optimal lambda is problem- - dependent and require trial and error. In our experience, - good lambda can be as large as 0.1, and you can use 0.001 - as initial guess. - Default value - 0.01, which is used when LambdaV is not - given. You can specify zero value, but it is not - recommended to do so. - -TUNING ALGORITHM - -In order to use this algorithm you have to choose three parameters: -* initial radius RBase -* number of layers in the model NLayers -* regularization coefficient LambdaV - -Initial radius is easy to choose - you can pick any number several times -larger than the average distance between points. Algorithm won't break -down if you choose radius which is too large (model construction time will -increase, but model will be built correctly). - -Choose such number of layers that RLast=RBase/2^(NLayers-1) (radius used -by the last layer) will be smaller than the typical distance between -points. In case model error is too large, you can increase number of -layers. Having more layers will make model construction and evaluation -proportionally slower, but it will allow you to have model which precisely -fits your data. From the other side, if you want to suppress noise, you -can DECREASE number of layers to make your model less flexible. - -Regularization coefficient LambdaV controls smoothness of the individual -models built for each layer. We recommend you to use default value in case -you don't want to tune this parameter, because having non-zero LambdaV -accelerates and stabilizes internal iterative algorithm. In case you want -to suppress noise you can use LambdaV as additional parameter (larger -value = more smoothness) to tune. - -TYPICAL ERRORS - -1. Using initial radius which is too large. Memory requirements of the - RBF-ML are roughly proportional to N*Density*RBase^2 (where Density is - an average density of points per unit of the interpolation space). In - the extreme case of the very large RBase we will need O(N^2) units of - memory - and many layers in order to decrease radius to some reasonably - small value. - -2. Using too small number of layers - RBF models with large radius are not - flexible enough to reproduce small variations in the target function. - You need many layers with different radii, from large to small, in - order to have good model. - -3. Using initial radius which is too small. You will get model with - "holes" in the areas which are too far away from interpolation centers. - However, algorithm will work correctly (and quickly) in this case. - -4. Using too many layers - you will get too large and too slow model. This - model will perfectly reproduce your function, but maybe you will be - able to achieve similar results with less layers (and less memory). - - -- ALGLIB -- - Copyright 02.03.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfsetalgomultilayer( - rbfmodel s, - double rbase, - ae_int_t nlayers, - const xparams _params = alglib::xdefault); -void alglib::rbfsetalgomultilayer( - rbfmodel s, - double rbase, - ae_int_t nlayers, - double lambdav, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -DEPRECATED:since version 3.11 ALGLIB includes new RBF model construction - algorithm, Hierarchical RBF. This algorithm is faster and - requires less memory than QNN and RBF-ML. It is especially good - for large-scale interpolation problems. So, we recommend you to - consider Hierarchical RBF as default option. - -========================================================================== - -This function sets RBF interpolation algorithm. ALGLIB supports several -RBF algorithms with different properties. - -This algorithm is called RBF-QNN and it is good for point sets with -following properties: -a) all points are distinct -b) all points are well separated. -c) points distribution is approximately uniform. There is no "contour - lines", clusters of points, or other small-scale structures. - -Algorithm description: -1) interpolation centers are allocated to data points -2) interpolation radii are calculated as distances to the nearest centers - times Q coefficient (where Q is a value from [0.75,1.50]). -3) after performing (2) radii are transformed in order to avoid situation - when single outlier has very large radius and influences many points - across all dataset. Transformation has following form: - new_r[i] = min(r[i],Z*median(r[])) - where r[i] is I-th radius, median() is a median radius across entire - dataset, Z is user-specified value which controls amount of deviation - from median radius. - -When (a) is violated, we will be unable to build RBF model. When (b) or -(c) are violated, model will be built, but interpolation quality will be -low. See http://www.alglib.net/interpolation/ for more information on this -subject. - -This algorithm is used by default. - -Additional Q parameter controls smoothness properties of the RBF basis: -* Q<0.75 will give perfectly conditioned basis, but terrible smoothness - properties (RBF interpolant will have sharp peaks around function values) -* Q around 1.0 gives good balance between smoothness and condition number -* Q>1.5 will lead to badly conditioned systems and slow convergence of the - underlying linear solver (although smoothness will be very good) -* Q>2.0 will effectively make optimizer useless because it won't converge - within reasonable amount of iterations. It is possible to set such large - Q, but it is advised not to do so. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - Q - Q parameter, Q>0, recommended value - 1.0 - Z - Z parameter, Z>0, recommended value - 5.0 - -NOTE: this function has some serialization-related subtleties. We - recommend you to study serialization examples from ALGLIB Reference - Manual if you want to perform serialization of your models. - - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfsetalgoqnn( - rbfmodel s, - const xparams _params = alglib::xdefault); -void alglib::rbfsetalgoqnn( - rbfmodel s, - double q, - double z, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets constant term (model is a sum of radial basis functions -plus constant). This function won't have effect until next call to -RBFBuildModel(). - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - -NOTE: this function has some serialization-related subtleties. We - recommend you to study serialization examples from ALGLIB Reference - Manual if you want to perform serialization of your models. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfsetconstterm( - rbfmodel s, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function sets linear term (model is a sum of radial basis functions -plus linear polynomial). This function won't have effect until next call -to RBFBuildModel(). - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - -NOTE: this function has some serialization-related subtleties. We - recommend you to study serialization examples from ALGLIB Reference - Manual if you want to perform serialization of your models. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfsetlinterm( - rbfmodel s, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function adds dataset. - -This function overrides results of the previous calls, i.e. multiple calls -of this function will result in only the last set being added. - -IMPORTANT: ALGLIB version 3.11 and later allows you to specify a set of - per-dimension scales. Interpolation radii are multiplied by the - scale vector. It may be useful if you have mixed spatio-temporal - data (say, a set of 3D slices recorded at different times). - You should call rbfsetpointsandscales() function to use this - feature. - -INPUT PARAMETERS: - S - RBF model, initialized by rbfcreate() call. - XY - points, array[N,NX+NY]. One row corresponds to one point - in the dataset. First NX elements are coordinates, next - NY elements are function values. Array may be larger than - specified, in this case only leading [N,NX+NY] elements - will be used. - N - number of points in the dataset - -After you've added dataset and (optionally) tuned algorithm settings you -should call rbfbuildmodel() in order to build a model for you. - -NOTE: dataset added by this function is not saved during model serialization. - MODEL ITSELF is serialized, but data used to build it are not. - - So, if you 1) add dataset to empty RBF model, 2) serialize and - unserialize it, then you will get an empty RBF model with no dataset - being attached. - - From the other side, if you call rbfbuildmodel() between (1) and (2), - then after (2) you will get your fully constructed RBF model - but - again with no dataset attached, so subsequent calls to rbfbuildmodel() - will produce empty model. - - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfsetpoints( - rbfmodel s, - real_2d_array xy, - const xparams _params = alglib::xdefault); -void alglib::rbfsetpoints( - rbfmodel s, - real_2d_array xy, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -This function adds dataset and a vector of per-dimension scales. - -It may be useful if you have mixed spatio-temporal data - say, a set of 3D -slices recorded at different times. Such data typically require different -RBF radii for spatial and temporal dimensions. ALGLIB solves this problem -by specifying single RBF radius, which is (optionally) multiplied by the -scale vector. - -This function overrides results of the previous calls, i.e. multiple calls -of this function will result in only the last set being added. - -IMPORTANT: only HierarchicalRBF algorithm can work with scaled points. So, - using this function results in RBF models which can be used in - ALGLIB 3.11 or later. Previous versions of the library will be - unable to unserialize models produced by HierarchicalRBF algo. - - Any attempt to use this function with RBF-ML or QNN algorithms - will result in -3 error code being returned (incorrect - algorithm). - -INPUT PARAMETERS: - R - RBF model, initialized by rbfcreate() call. - XY - points, array[N,NX+NY]. One row corresponds to one point - in the dataset. First NX elements are coordinates, next - NY elements are function values. Array may be larger than - specified, in this case only leading [N,NX+NY] elements - will be used. - N - number of points in the dataset - S - array[NX], scale vector, S[i]>0. - -After you've added dataset and (optionally) tuned algorithm settings you -should call rbfbuildmodel() in order to build a model for you. - -NOTE: dataset added by this function is not saved during model serialization. - MODEL ITSELF is serialized, but data used to build it are not. - - So, if you 1) add dataset to empty RBF model, 2) serialize and - unserialize it, then you will get an empty RBF model with no dataset - being attached. - - From the other side, if you call rbfbuildmodel() between (1) and (2), - then after (2) you will get your fully constructed RBF model - but - again with no dataset attached, so subsequent calls to rbfbuildmodel() - will produce empty model. - - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfsetpointsandscales( - rbfmodel r, - real_2d_array xy, - real_1d_array s, - const xparams _params = alglib::xdefault); -void alglib::rbfsetpointsandscales( - rbfmodel r, - real_2d_array xy, - ae_int_t n, - real_1d_array s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets basis function type, which can be: -* 0 for classic Gaussian -* 1 for fast and compact bell-like basis function, which becomes exactly - zero at distance equal to 3*R (default option). - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - BF - basis function type: - * 0 - classic Gaussian - * 1 - fast and compact one - - -- ALGLIB -- - Copyright 01.02.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfsetv2bf( - rbfmodel s, - ae_int_t bf, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets stopping criteria of the underlying linear solver for -hierarchical (version 2) RBF constructor. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - MaxIts - this criterion will stop algorithm after MaxIts iterations. - Typically a few hundreds iterations is required, with 400 - being a good default value to start experimentation. - Zero value means that default value will be selected. - - -- ALGLIB -- - Copyright 01.02.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfsetv2its( - rbfmodel s, - ae_int_t maxits, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets support radius parameter of hierarchical (version 2) -RBF constructor. - -Hierarchical RBF model achieves great speed-up by removing from the model -excessive (too dense) nodes. Say, if you have RBF radius equal to 1 meter, -and two nodes are just 1 millimeter apart, you may remove one of them -without reducing model quality. - -Support radius parameter is used to justify which points need removal, and -which do not. If two points are less than SUPPORT_R*CUR_RADIUS units of -distance apart, one of them is removed from the model. The larger support -radius is, the faster model construction AND evaluation are. However, -too large values result in "bumpy" models. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - R - support radius coefficient, >=0. - Recommended values are [0.1,0.4] range, with 0.1 being - default value. - - -- ALGLIB -- - Copyright 01.02.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfsetv2supportr( - rbfmodel s, - double r, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets zero term (model is a sum of radial basis functions -without polynomial term). This function won't have effect until next call -to RBFBuildModel(). - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - -NOTE: this function has some serialization-related subtleties. We - recommend you to study serialization examples from ALGLIB Reference - Manual if you want to perform serialization of your models. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfsetzeroterm( - rbfmodel s, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function calculates values of the RBF model at the given point, using -external buffer object (internal temporaries of RBF model are not -modified). - -This function allows to use same RBF model object in different threads, -assuming that different threads use different instances of buffer -structure. - -INPUT PARAMETERS: - S - RBF model, may be shared between different threads - Buf - buffer object created for this particular instance of RBF - model with rbfcreatecalcbuffer(). - X - coordinates, array[NX]. - X may have more than NX elements, in this case only - leading NX will be used. - Y - possibly preallocated array - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is not reallocated when it - is larger than NY. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbftscalcbuf( - rbfmodel s, - rbfcalcbuffer buf, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function "unpacks" RBF model by extracting its coefficients. - -INPUT PARAMETERS: - S - RBF model - -OUTPUT PARAMETERS: - NX - dimensionality of argument - NY - dimensionality of the target function - XWR - model information, array[NC,NX+NY+1]. - One row of the array corresponds to one basis function: - * first NX columns - coordinates of the center - * next NY columns - weights, one per dimension of the - function being modelled - For ModelVersion=1: - * last column - radius, same for all dimensions of - the function being modelled - For ModelVersion=2: - * last NX columns - radii, one per dimension - NC - number of the centers - V - polynomial term , array[NY,NX+1]. One row per one - dimension of the function being modelled. First NX - elements are linear coefficients, V[NX] is equal to the - constant part. - ModelVersion-version of the RBF model: - * 1 - for models created by QNN and RBF-ML algorithms, - compatible with ALGLIB 3.10 or earlier. - * 2 - for models created by HierarchicalRBF, requires - ALGLIB 3.11 or later - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::rbfunpack( - rbfmodel s, - ae_int_t& nx, - ae_int_t& ny, - real_2d_array& xwr, - ae_int_t& nc, - real_2d_array& v, - ae_int_t& modelversion, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -
void rbfunserialize(const std::string &s_in, rbfmodel &obj); -void rbfunserialize(const std::istream &s_in, rbfmodel &obj); -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example illustrates basic concepts of the RBF models: creation, modification,
-    // evaluation.
-    // 
-    // Suppose that we have set of 2-dimensional points with associated
-    // scalar function values, and we want to build a RBF model using
-    // our data.
-    // 
-    // NOTE: we can work with 3D models too :)
-    // 
-    // Typical sequence of steps is given below:
-    // 1. we create RBF model object
-    // 2. we attach our dataset to the RBF model and tune algorithm settings
-    // 3. we rebuild RBF model using QNN algorithm on new data
-    // 4. we use RBF model (evaluate, serialize, etc.)
-    //
-    double v;
-
-    //
-    // Step 1: RBF model creation.
-    //
-    // We have to specify dimensionality of the space (2 or 3) and
-    // dimensionality of the function (scalar or vector).
-    //
-    // New model is empty - it can be evaluated,
-    // but we just get zero value at any point.
-    //
-    rbfmodel model;
-    rbfcreate(2, 1, model);
-
-    v = rbfcalc2(model, 0.0, 0.0);
-    printf("%.2f\n", double(v)); // EXPECTED: 0.000
-
-    //
-    // Step 2: we add dataset.
-    //
-    // XY contains two points - x0=(-1,0) and x1=(+1,0) -
-    // and two function values f(x0)=2, f(x1)=3.
-    //
-    // We added points, but model was not rebuild yet.
-    // If we call rbfcalc2(), we still will get 0.0 as result.
-    //
-    real_2d_array xy = "[[-1,0,2],[+1,0,3]]";
-    rbfsetpoints(model, xy);
-
-    v = rbfcalc2(model, 0.0, 0.0);
-    printf("%.2f\n", double(v)); // EXPECTED: 0.000
-
-    //
-    // Step 3: rebuild model
-    //
-    // After we've configured model, we should rebuild it -
-    // it will change coefficients stored internally in the
-    // rbfmodel structure.
-    //
-    // We use hierarchical RBF algorithm with following parameters:
-    // * RBase - set to 1.0
-    // * NLayers - three layers are used (although such simple problem
-    //   does not need more than 1 layer)
-    // * LambdaReg - is set to zero value, no smoothing is required
-    //
-    rbfreport rep;
-    rbfsetalgohierarchical(model, 1.0, 3, 0.0);
-    rbfbuildmodel(model, rep);
-    printf("%d\n", int(rep.terminationtype)); // EXPECTED: 1
-
-    //
-    // Step 4: model was built
-    //
-    // After call of rbfbuildmodel(), rbfcalc2() will return
-    // value of the new model.
-    //
-    v = rbfcalc2(model, 0.0, 0.0);
-    printf("%.2f\n", double(v)); // EXPECTED: 2.500
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example show how to work with polynomial term
-    // 
-    // Suppose that we have set of 2-dimensional points with associated
-    // scalar function values, and we want to build a RBF model using
-    // our data.
-    //
-    // We use hierarchical RBF algorithm with following parameters:
-    // * RBase - set to 1.0
-    // * NLayers - three layers are used (although such simple problem
-    //   does not need more than 1 layer)
-    // * LambdaReg - is set to zero value, no smoothing is required
-    //
-    double v;
-    rbfmodel model;
-    real_2d_array xy = "[[-1,0,2],[+1,0,3]]";
-    rbfreport rep;
-
-    rbfcreate(2, 1, model);
-    rbfsetpoints(model, xy);
-    rbfsetalgohierarchical(model, 1.0, 3, 0.0);
-
-    //
-    // By default, RBF model uses linear term. It means that model
-    // looks like
-    //     f(x,y) = SUM(RBF[i]) + a*x + b*y + c
-    // where RBF[i] is I-th radial basis function and a*x+by+c is a
-    // linear term. Having linear terms in a model gives us:
-    // (1) improved extrapolation properties
-    // (2) linearity of the model when data can be perfectly fitted
-    //     by the linear function
-    // (3) linear asymptotic behavior
-    //
-    // Our simple dataset can be modelled by the linear function
-    //     f(x,y) = 0.5*x + 2.5
-    // and rbfbuildmodel() with default settings should preserve this
-    // linearity.
-    //
-    ae_int_t nx;
-    ae_int_t ny;
-    ae_int_t nc;
-    ae_int_t modelversion;
-    real_2d_array xwr;
-    real_2d_array c;
-    rbfbuildmodel(model, rep);
-    printf("%d\n", int(rep.terminationtype)); // EXPECTED: 1
-    rbfunpack(model, nx, ny, xwr, nc, c, modelversion);
-    printf("%s\n", c.tostring(2).c_str()); // EXPECTED: [[0.500,0.000,2.500]]
-
-    // asymptotic behavior of our function is linear
-    v = rbfcalc2(model, 1000.0, 0.0);
-    printf("%.1f\n", double(v)); // EXPECTED: 502.50
-
-    //
-    // Instead of linear term we can use constant term. In this case
-    // we will get model which has form
-    //     f(x,y) = SUM(RBF[i]) + c
-    // where RBF[i] is I-th radial basis function and c is a constant,
-    // which is equal to the average function value on the dataset.
-    //
-    // Because we've already attached dataset to the model the only
-    // thing we have to do is to call rbfsetconstterm() and then
-    // rebuild model with rbfbuildmodel().
-    //
-    rbfsetconstterm(model);
-    rbfbuildmodel(model, rep);
-    printf("%d\n", int(rep.terminationtype)); // EXPECTED: 1
-    rbfunpack(model, nx, ny, xwr, nc, c, modelversion);
-    printf("%s\n", c.tostring(2).c_str()); // EXPECTED: [[0.000,0.000,2.500]]
-
-    // asymptotic behavior of our function is constant
-    v = rbfcalc2(model, 1000.0, 0.0);
-    printf("%.2f\n", double(v)); // EXPECTED: 2.500
-
-    //
-    // Finally, we can use zero term. Just plain RBF without polynomial
-    // part:
-    //     f(x,y) = SUM(RBF[i])
-    // where RBF[i] is I-th radial basis function.
-    //
-    rbfsetzeroterm(model);
-    rbfbuildmodel(model, rep);
-    printf("%d\n", int(rep.terminationtype)); // EXPECTED: 1
-    rbfunpack(model, nx, ny, xwr, nc, c, modelversion);
-    printf("%s\n", c.tostring(2).c_str()); // EXPECTED: [[0.000,0.000,0.000]]
-
-    // asymptotic behavior of our function is just zero constant
-    v = rbfcalc2(model, 1000.0, 0.0);
-    printf("%.2f\n", double(v)); // EXPECTED: 0.000
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example show how to serialize and unserialize RBF model
-    // 
-    // Suppose that we have set of 2-dimensional points with associated
-    // scalar function values, and we want to build a RBF model using
-    // our data. Then we want to serialize it to string and to unserialize
-    // from string, loading to another instance of RBF model.
-    //
-    // Here we assume that you already know how to create RBF models.
-    //
-    std::string s;
-    double v;
-    rbfmodel model0;
-    rbfmodel model1;
-    real_2d_array xy = "[[-1,0,2],[+1,0,3]]";
-    rbfreport rep;
-
-    // model initialization
-    rbfcreate(2, 1, model0);
-    rbfsetpoints(model0, xy);
-    rbfsetalgohierarchical(model0, 1.0, 3, 0.0);
-    rbfbuildmodel(model0, rep);
-    printf("%d\n", int(rep.terminationtype)); // EXPECTED: 1
-
-    //
-    // Serialization - it looks easy,
-    // but you should carefully read next section.
-    //
-    alglib::rbfserialize(model0, s);
-    alglib::rbfunserialize(s, model1);
-
-    // both models return same value
-    v = rbfcalc2(model0, 0.0, 0.0);
-    printf("%.2f\n", double(v)); // EXPECTED: 2.500
-    v = rbfcalc2(model1, 0.0, 0.0);
-    printf("%.2f\n", double(v)); // EXPECTED: 2.500
-
-    //
-    // Previous section shows that model state is saved/restored during
-    // serialization. However, some properties are NOT serialized.
-    //
-    // Serialization saves/restores RBF model, but it does NOT saves/restores
-    // settings which were used to build current model. In particular, dataset
-    // which was used to build model, is not preserved.
-    //
-    // What does it mean in for us?
-    //
-    // Do you remember this sequence: rbfcreate-rbfsetpoints-rbfbuildmodel?
-    // First step creates model, second step adds dataset and tunes model
-    // settings, third step builds model using current dataset and model
-    // construction settings.
-    //
-    // If you call rbfbuildmodel() without calling rbfsetpoints() first, you
-    // will get empty (zero) RBF model. In our example, model0 contains
-    // dataset which was added by rbfsetpoints() call. However, model1 does
-    // NOT contain dataset - because dataset is NOT serialized.
-    //
-    // This, if we call rbfbuildmodel(model0,rep), we will get same model,
-    // which returns 2.5 at (x,y)=(0,0). However, after same call model1 will
-    // return zero - because it contains RBF model (coefficients), but does NOT
-    // contain dataset which was used to build this model.
-    //
-    // Basically, it means that:
-    // * serialization of the RBF model preserves anything related to the model
-    //   EVALUATION
-    // * but it does NOT creates perfect copy of the original object.
-    //
-    rbfbuildmodel(model0, rep);
-    v = rbfcalc2(model0, 0.0, 0.0);
-    printf("%.2f\n", double(v)); // EXPECTED: 2.500
-
-    rbfbuildmodel(model1, rep);
-    v = rbfcalc2(model1, 0.0, 0.0);
-    printf("%.2f\n", double(v)); // EXPECTED: 0.000
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // Suppose that we have set of 2-dimensional points with associated VECTOR
-    // function values, and we want to build a RBF model using our data.
-    // 
-    // Typical sequence of steps is given below:
-    // 1. we create RBF model object
-    // 2. we attach our dataset to the RBF model and tune algorithm settings
-    // 3. we rebuild RBF model using new data
-    // 4. we use RBF model (evaluate, serialize, etc.)
-    //
-    real_1d_array x;
-    real_1d_array y;
-
-    //
-    // Step 1: RBF model creation.
-    //
-    // We have to specify dimensionality of the space (equal to 2) and
-    // dimensionality of the function (2-dimensional vector function).
-    //
-    // New model is empty - it can be evaluated,
-    // but we just get zero value at any point.
-    //
-    rbfmodel model;
-    rbfcreate(2, 2, model);
-
-    x = "[+1,+1]";
-    rbfcalc(model, x, y);
-    printf("%s\n", y.tostring(2).c_str()); // EXPECTED: [0.000,0.000]
-
-    //
-    // Step 2: we add dataset.
-    //
-    // XY arrays containt four points:
-    // * (x0,y0) = (+1,+1), f(x0,y0)=(0,-1)
-    // * (x1,y1) = (+1,-1), f(x1,y1)=(-1,0)
-    // * (x2,y2) = (-1,-1), f(x2,y2)=(0,+1)
-    // * (x3,y3) = (-1,+1), f(x3,y3)=(+1,0)
-    //
-    real_2d_array xy = "[[+1,+1,0,-1],[+1,-1,-1,0],[-1,-1,0,+1],[-1,+1,+1,0]]";
-    rbfsetpoints(model, xy);
-
-    // We added points, but model was not rebuild yet.
-    // If we call rbfcalc(), we still will get 0.0 as result.
-    rbfcalc(model, x, y);
-    printf("%s\n", y.tostring(2).c_str()); // EXPECTED: [0.000,0.000]
-
-    //
-    // Step 3: rebuild model
-    //
-    // We use hierarchical RBF algorithm with following parameters:
-    // * RBase - set to 1.0
-    // * NLayers - three layers are used (although such simple problem
-    //   does not need more than 1 layer)
-    // * LambdaReg - is set to zero value, no smoothing is required
-    //
-    // After we've configured model, we should rebuild it -
-    // it will change coefficients stored internally in the
-    // rbfmodel structure.
-    //
-    rbfreport rep;
-    rbfsetalgohierarchical(model, 1.0, 3, 0.0);
-    rbfbuildmodel(model, rep);
-    printf("%d\n", int(rep.terminationtype)); // EXPECTED: 1
-
-    //
-    // Step 4: model was built
-    //
-    // After call of rbfbuildmodel(), rbfcalc() will return
-    // value of the new model.
-    //
-    rbfcalc(model, x, y);
-    printf("%s\n", y.tostring(2).c_str()); // EXPECTED: [0.000,-1.000]
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* -Estimate of the condition number of a matrix given by its LU decomposition (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - LUA - LU decomposition of a matrix in compact form. Output of - the CMatrixLU subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -
double alglib::cmatrixlurcond1( - complex_2d_array lua, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Estimate of the condition number of a matrix given by its LU decomposition -(infinity norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - LUA - LU decomposition of a matrix in compact form. Output of - the CMatrixLU subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -
double alglib::cmatrixlurcondinf( - complex_2d_array lua, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Estimate of a matrix condition number (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -
double alglib::cmatrixrcond1( - complex_2d_array a, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Estimate of a matrix condition number (infinity-norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -
double alglib::cmatrixrcondinf( - complex_2d_array a, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Triangular matrix: estimate of a condition number (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array[0..N-1, 0..N-1]. - N - size of A. - IsUpper - True, if the matrix is upper triangular. - IsUnit - True, if the matrix has a unit diagonal. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -
double alglib::cmatrixtrrcond1( - complex_2d_array a, - ae_int_t n, - bool isupper, - bool isunit, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Triangular matrix: estimate of a matrix condition number (infinity-norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - True, if the matrix is upper triangular. - IsUnit - True, if the matrix has a unit diagonal. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -
double alglib::cmatrixtrrcondinf( - complex_2d_array a, - ae_int_t n, - bool isupper, - bool isunit, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Condition number estimate of a Hermitian positive definite matrix given by -Cholesky decomposition. - -The algorithm calculates a lower bound of the condition number. In this -case, the algorithm does not return a lower bound of the condition number, -but an inverse number (to avoid an overflow in case of a singular matrix). - -It should be noted that 1-norm and inf-norm condition numbers of symmetric -matrices are equal, so the algorithm doesn't take into account the -differences between these types of norms. - -Input parameters: - CD - Cholesky decomposition of matrix A, - output of SMatrixCholesky subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -
double alglib::hpdmatrixcholeskyrcond( - complex_2d_array a, - ae_int_t n, - bool isupper, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Condition number estimate of a Hermitian positive definite matrix. - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -It should be noted that 1-norm and inf-norm of condition numbers of symmetric -matrices are equal, so the algorithm doesn't take into account the -differences between these types of norms. - -Input parameters: - A - Hermitian positive definite matrix which is given by its - upper or lower triangle depending on the value of - IsUpper. Array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - storage format. - -Result: - 1/LowerBound(cond(A)), if matrix A is positive definite, - -1, if matrix A is not positive definite, and its condition number - could not be found by this algorithm. - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -
double alglib::hpdmatrixrcond( - complex_2d_array a, - ae_int_t n, - bool isupper, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Estimate of the condition number of a matrix given by its LU decomposition (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - LUA - LU decomposition of a matrix in compact form. Output of - the RMatrixLU subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -
double alglib::rmatrixlurcond1( - real_2d_array lua, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Estimate of the condition number of a matrix given by its LU decomposition -(infinity norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - LUA - LU decomposition of a matrix in compact form. Output of - the RMatrixLU subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -
double alglib::rmatrixlurcondinf( - real_2d_array lua, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Estimate of a matrix condition number (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -
double alglib::rmatrixrcond1( - real_2d_array a, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Estimate of a matrix condition number (infinity-norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -
double alglib::rmatrixrcondinf( - real_2d_array a, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Triangular matrix: estimate of a condition number (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array[0..N-1, 0..N-1]. - N - size of A. - IsUpper - True, if the matrix is upper triangular. - IsUnit - True, if the matrix has a unit diagonal. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -
double alglib::rmatrixtrrcond1( - real_2d_array a, - ae_int_t n, - bool isupper, - bool isunit, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Triangular matrix: estimate of a matrix condition number (infinity-norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - True, if the matrix is upper triangular. - IsUnit - True, if the matrix has a unit diagonal. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -
double alglib::rmatrixtrrcondinf( - real_2d_array a, - ae_int_t n, - bool isupper, - bool isunit, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Condition number estimate of a symmetric positive definite matrix given by -Cholesky decomposition. - -The algorithm calculates a lower bound of the condition number. In this -case, the algorithm does not return a lower bound of the condition number, -but an inverse number (to avoid an overflow in case of a singular matrix). - -It should be noted that 1-norm and inf-norm condition numbers of symmetric -matrices are equal, so the algorithm doesn't take into account the -differences between these types of norms. - -Input parameters: - CD - Cholesky decomposition of matrix A, - output of SMatrixCholesky subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -
double alglib::spdmatrixcholeskyrcond( - real_2d_array a, - ae_int_t n, - bool isupper, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Condition number estimate of a symmetric positive definite matrix. - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -It should be noted that 1-norm and inf-norm of condition numbers of symmetric -matrices are equal, so the algorithm doesn't take into account the -differences between these types of norms. - -Input parameters: - A - symmetric positive definite matrix which is given by its - upper or lower triangle depending on the value of - IsUpper. Array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - storage format. - -Result: - 1/LowerBound(cond(A)), if matrix A is positive definite, - -1, if matrix A is not positive definite, and its condition number - could not be found by this algorithm. - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -
double alglib::spdmatrixrcond( - real_2d_array a, - ae_int_t n, - bool isupper, - const xparams _params = alglib::xdefault); - -
- -
- -rmatrixschur
- - -
- -
-
/************************************************************************* -Subroutine performing the Schur decomposition of a general matrix by using -the QR algorithm with multiple shifts. - -COMMERCIAL EDITION OF ALGLIB: - - ! Commercial version of ALGLIB includes one important improvement of - ! this function, which can be used from C++ and C#: - ! * Intel MKL support (lightweight Intel MKL is shipped with ALGLIB) - ! - ! Intel MKL gives approximately constant (with respect to number of - ! worker threads) acceleration factor which depends on CPU being used, - ! problem size and "baseline" ALGLIB edition which is used for - ! comparison. - ! - ! Multithreaded acceleration is NOT supported for this function. - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -The source matrix A is represented as S'*A*S = T, where S is an orthogonal -matrix (Schur vectors), T - upper quasi-triangular matrix (with blocks of -sizes 1x1 and 2x2 on the main diagonal). - -Input parameters: - A - matrix to be decomposed. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of A, N>=0. - - -Output parameters: - A - contains matrix T. - Array whose indexes range within [0..N-1, 0..N-1]. - S - contains Schur vectors. - Array whose indexes range within [0..N-1, 0..N-1]. - -Note 1: - The block structure of matrix T can be easily recognized: since all - the elements below the blocks are zeros, the elements a[i+1,i] which - are equal to 0 show the block border. - -Note 2: - The algorithm performance depends on the value of the internal parameter - NS of the InternalSchurDecomposition subroutine which defines the number - of shifts in the QR algorithm (similarly to the block width in block-matrix - algorithms in linear algebra). If you require maximum performance on - your machine, it is recommended to adjust this parameter manually. - -Result: - True, - if the algorithm has converged and parameters A and S contain the result. - False, - if the algorithm has not converged. - -Algorithm implemented on the basis of the DHSEQR subroutine (LAPACK 3.0 library). -*************************************************************************/ -
bool alglib::rmatrixschur( - real_2d_array& a, - ae_int_t n, - real_2d_array& s, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -Temporary buffers for sparse matrix operations. - -You should pass an instance of this structure to factorization functions. -It allows to reuse memory during repeated sparse factorizations. You do -not have to call some initialization function - simply passing an instance -to factorization function is enough. -*************************************************************************/ -
class sparsebuffers -{ -}; - -
- -
-
/************************************************************************* -Sparse matrix structure. - -You should use ALGLIB functions to work with sparse matrix. Never try to -access its fields directly! - -NOTES ON THE SPARSE STORAGE FORMATS - -Sparse matrices can be stored using several formats: -* Hash-Table representation -* Compressed Row Storage (CRS) -* Skyline matrix storage (SKS) - -Each of the formats has benefits and drawbacks: -* Hash-table is good for dynamic operations (insertion of new elements), - but does not support linear algebra operations -* CRS is good for operations like matrix-vector or matrix-matrix products, - but its initialization is less convenient - you have to tell row sizes - at the initialization, and you have to fill matrix only row by row, - from left to right. -* SKS is a special format which is used to store triangular factors from - Cholesky factorization. It does not support dynamic modification, and - support for linear algebra operations is very limited. - -Tables below outline information about these two formats: - - OPERATIONS WITH MATRIX HASH CRS SKS - creation + + + - SparseGet + + + - SparseExists + + + - SparseRewriteExisting + + + - SparseSet + + + - SparseAdd + - SparseGetRow + + - SparseGetCompressedRow + + - sparse-dense linear algebra + + -*************************************************************************/ -
class sparsematrix -{ -}; - -
- -
-
/************************************************************************* -This function adds value to S[i,j] - element of the sparse matrix. Matrix -must be in a Hash-Table mode. - -In case S[i,j] already exists in the table, V i added to its value. In -case S[i,j] is non-existent, it is inserted in the table. Table -automatically grows when necessary. - -INPUT PARAMETERS - S - sparse M*N matrix in Hash-Table representation. - Exception will be thrown for CRS matrix. - I - row index of the element to modify, 0<=I<M - J - column index of the element to modify, 0<=J<N - V - value to add, must be finite number - -OUTPUT PARAMETERS - S - modified matrix - -NOTE 1: when S[i,j] is exactly zero after modification, it is deleted -from the table. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparseadd( - sparsematrix s, - ae_int_t i, - ae_int_t j, - double v, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function performs in-place conversion to desired sparse storage -format. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - Fmt - desired storage format of the output, as returned by - SparseGetMatrixType() function: - * 0 for hash-based storage - * 1 for CRS - * 2 for SKS - -OUTPUT PARAMETERS - S0 - sparse matrix in requested format. - -NOTE: in-place conversion wastes a lot of memory which is used to store - temporaries. If you perform a lot of repeated conversions, we - recommend to use out-of-place buffered conversion functions, like - SparseCopyToBuf(), which can reuse already allocated memory. - - -- ALGLIB PROJECT -- - Copyright 16.01.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparseconvertto( - sparsematrix s0, - ae_int_t fmt, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function converts matrix to CRS format. - -Some algorithms (linear algebra ones, for example) require matrices in -CRS format. This function allows to perform in-place conversion. - -INPUT PARAMETERS - S - sparse M*N matrix in any format - -OUTPUT PARAMETERS - S - matrix in CRS format - -NOTE: this function has no effect when called with matrix which is - already in CRS mode. - -NOTE: this function allocates temporary memory to store a copy of the - matrix. If you perform a lot of repeated conversions, we recommend - you to use SparseCopyToCRSBuf() function, which can reuse - previously allocated memory. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparseconverttocrs( - sparsematrix s, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function performs in-place conversion to Hash table storage. - -INPUT PARAMETERS - S - sparse matrix in CRS format. - -OUTPUT PARAMETERS - S - sparse matrix in Hash table format. - -NOTE: this function has no effect when called with matrix which is - already in Hash table mode. - -NOTE: in-place conversion involves allocation of temporary arrays. If you - perform a lot of repeated in- place conversions, it may lead to - memory fragmentation. Consider using out-of-place SparseCopyToHashBuf() - function in this case. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparseconverttohash( - sparsematrix s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function performs in-place conversion to SKS format. - -INPUT PARAMETERS - S - sparse matrix in any format. - -OUTPUT PARAMETERS - S - sparse matrix in SKS format. - -NOTE: this function has no effect when called with matrix which is - already in SKS mode. - -NOTE: in-place conversion involves allocation of temporary arrays. If you - perform a lot of repeated in- place conversions, it may lead to - memory fragmentation. Consider using out-of-place SparseCopyToSKSBuf() - function in this case. - - -- ALGLIB PROJECT -- - Copyright 15.01.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparseconverttosks( - sparsematrix s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function copies S0 to S1. -This function completely deallocates memory owned by S1 before creating a -copy of S0. If you want to reuse memory, use SparseCopyBuf. - -NOTE: this function does not verify its arguments, it just copies all -fields of the structure. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsecopy( - sparsematrix s0, - sparsematrix& s1, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function copies S0 to S1. -Memory already allocated in S1 is reused as much as possible. - -NOTE: this function does not verify its arguments, it just copies all -fields of the structure. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsecopybuf( - sparsematrix s0, - sparsematrix s1, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function performs out-of-place conversion to desired sparse storage -format. S0 is copied to S1 and converted on-the-fly. Memory allocated in -S1 is reused to maximum extent possible. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - Fmt - desired storage format of the output, as returned by - SparseGetMatrixType() function: - * 0 for hash-based storage - * 1 for CRS - * 2 for SKS - -OUTPUT PARAMETERS - S1 - sparse matrix in requested format. - - -- ALGLIB PROJECT -- - Copyright 16.01.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsecopytobuf( - sparsematrix s0, - ae_int_t fmt, - sparsematrix s1, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function performs out-of-place conversion to CRS format. S0 is -copied to S1 and converted on-the-fly. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - -OUTPUT PARAMETERS - S1 - sparse matrix in CRS format. - -NOTE: if S0 is stored as CRS, it is just copied without conversion. - -NOTE: this function de-allocates memory occupied by S1 before starting CRS - conversion. If you perform a lot of repeated CRS conversions, it may - lead to memory fragmentation. In this case we recommend you to use - SparseCopyToCRSBuf() function which re-uses memory in S1 as much as - possible. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsecopytocrs( - sparsematrix s0, - sparsematrix& s1, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function performs out-of-place conversion to CRS format. S0 is -copied to S1 and converted on-the-fly. Memory allocated in S1 is reused to -maximum extent possible. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - S1 - matrix which may contain some pre-allocated memory, or - can be just uninitialized structure. - -OUTPUT PARAMETERS - S1 - sparse matrix in CRS format. - -NOTE: if S0 is stored as CRS, it is just copied without conversion. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsecopytocrsbuf( - sparsematrix s0, - sparsematrix s1, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function performs out-of-place conversion to Hash table storage -format. S0 is copied to S1 and converted on-the-fly. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - -OUTPUT PARAMETERS - S1 - sparse matrix in Hash table format. - -NOTE: if S0 is stored as Hash-table, it is just copied without conversion. - -NOTE: this function de-allocates memory occupied by S1 before starting - conversion. If you perform a lot of repeated conversions, it may - lead to memory fragmentation. In this case we recommend you to use - SparseCopyToHashBuf() function which re-uses memory in S1 as much as - possible. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsecopytohash( - sparsematrix s0, - sparsematrix& s1, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function performs out-of-place conversion to Hash table storage -format. S0 is copied to S1 and converted on-the-fly. Memory allocated in -S1 is reused to maximum extent possible. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - -OUTPUT PARAMETERS - S1 - sparse matrix in Hash table format. - -NOTE: if S0 is stored as Hash-table, it is just copied without conversion. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsecopytohashbuf( - sparsematrix s0, - sparsematrix s1, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function performs out-of-place conversion to SKS storage format. -S0 is copied to S1 and converted on-the-fly. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - -OUTPUT PARAMETERS - S1 - sparse matrix in SKS format. - -NOTE: if S0 is stored as SKS, it is just copied without conversion. - -NOTE: this function de-allocates memory occupied by S1 before starting - conversion. If you perform a lot of repeated conversions, it may - lead to memory fragmentation. In this case we recommend you to use - SparseCopyToSKSBuf() function which re-uses memory in S1 as much as - possible. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsecopytosks( - sparsematrix s0, - sparsematrix& s1, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function performs out-of-place conversion to SKS format. S0 is -copied to S1 and converted on-the-fly. Memory allocated in S1 is reused -to maximum extent possible. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - -OUTPUT PARAMETERS - S1 - sparse matrix in SKS format. - -NOTE: if S0 is stored as SKS, it is just copied without conversion. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsecopytosksbuf( - sparsematrix s0, - sparsematrix s1, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function performs copying with transposition of CRS matrix. - -INPUT PARAMETERS - S0 - sparse matrix in CRS format. - -OUTPUT PARAMETERS - S1 - sparse matrix, transposed - - -- ALGLIB PROJECT -- - Copyright 23.07.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsecopytransposecrs( - sparsematrix s0, - sparsematrix& s1, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function performs copying with transposition of CRS matrix (buffered -version which reuses memory already allocated by the target as much as -possible). - -INPUT PARAMETERS - S0 - sparse matrix in CRS format. - -OUTPUT PARAMETERS - S1 - sparse matrix, transposed; previously allocated memory is - reused if possible. - - -- ALGLIB PROJECT -- - Copyright 23.07.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsecopytransposecrsbuf( - sparsematrix s0, - sparsematrix s1, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function creates sparse matrix in a Hash-Table format. - -This function creates Hast-Table matrix, which can be converted to CRS -format after its initialization is over. Typical usage scenario for a -sparse matrix is: -1. creation in a Hash-Table format -2. insertion of the matrix elements -3. conversion to the CRS representation -4. matrix is passed to some linear algebra algorithm - -Some information about different matrix formats can be found below, in -the "NOTES" section. - -INPUT PARAMETERS - M - number of rows in a matrix, M>=1 - N - number of columns in a matrix, N>=1 - K - K>=0, expected number of non-zero elements in a matrix. - K can be inexact approximation, can be less than actual - number of elements (table will grow when needed) or - even zero). - It is important to understand that although hash-table - may grow automatically, it is better to provide good - estimate of data size. - -OUTPUT PARAMETERS - S - sparse M*N matrix in Hash-Table representation. - All elements of the matrix are zero. - -NOTE 1 - -Hash-tables use memory inefficiently, and they have to keep some amount -of the "spare memory" in order to have good performance. Hash table for -matrix with K non-zero elements will need C*K*(8+2*sizeof(int)) bytes, -where C is a small constant, about 1.5-2 in magnitude. - -CRS storage, from the other side, is more memory-efficient, and needs -just K*(8+sizeof(int))+M*sizeof(int) bytes, where M is a number of rows -in a matrix. - -When you convert from the Hash-Table to CRS representation, all unneeded -memory will be freed. - -NOTE 2 - -Comments of SparseMatrix structure outline information about different -sparse storage formats. We recommend you to read them before starting to -use ALGLIB sparse matrices. - -NOTE 3 - -This function completely overwrites S with new sparse matrix. Previously -allocated storage is NOT reused. If you want to reuse already allocated -memory, call SparseCreateBuf function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsecreate( - ae_int_t m, - ae_int_t n, - sparsematrix& s, - const xparams _params = alglib::xdefault); -void alglib::sparsecreate( - ae_int_t m, - ae_int_t n, - ae_int_t k, - sparsematrix& s, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This version of SparseCreate function creates sparse matrix in Hash-Table -format, reusing previously allocated storage as much as possible. Read -comments for SparseCreate() for more information. - -INPUT PARAMETERS - M - number of rows in a matrix, M>=1 - N - number of columns in a matrix, N>=1 - K - K>=0, expected number of non-zero elements in a matrix. - K can be inexact approximation, can be less than actual - number of elements (table will grow when needed) or - even zero). - It is important to understand that although hash-table - may grow automatically, it is better to provide good - estimate of data size. - S - SparseMatrix structure which MAY contain some already - allocated storage. - -OUTPUT PARAMETERS - S - sparse M*N matrix in Hash-Table representation. - All elements of the matrix are zero. - Previously allocated storage is reused, if its size - is compatible with expected number of non-zeros K. - - -- ALGLIB PROJECT -- - Copyright 14.01.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsecreatebuf( - ae_int_t m, - ae_int_t n, - sparsematrix s, - const xparams _params = alglib::xdefault); -void alglib::sparsecreatebuf( - ae_int_t m, - ae_int_t n, - ae_int_t k, - sparsematrix s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function creates sparse matrix in a CRS format (expert function for -situations when you are running out of memory). - -This function creates CRS matrix. Typical usage scenario for a CRS matrix -is: -1. creation (you have to tell number of non-zero elements at each row at - this moment) -2. insertion of the matrix elements (row by row, from left to right) -3. matrix is passed to some linear algebra algorithm - -This function is a memory-efficient alternative to SparseCreate(), but it -is more complex because it requires you to know in advance how large your -matrix is. Some information about different matrix formats can be found -in comments on SparseMatrix structure. We recommend you to read them -before starting to use ALGLIB sparse matrices.. - -INPUT PARAMETERS - M - number of rows in a matrix, M>=1 - N - number of columns in a matrix, N>=1 - NER - number of elements at each row, array[M], NER[I]>=0 - -OUTPUT PARAMETERS - S - sparse M*N matrix in CRS representation. - You have to fill ALL non-zero elements by calling - SparseSet() BEFORE you try to use this matrix. - -NOTE: this function completely overwrites S with new sparse matrix. - Previously allocated storage is NOT reused. If you want to reuse - already allocated memory, call SparseCreateCRSBuf function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsecreatecrs( - ae_int_t m, - ae_int_t n, - integer_1d_array ner, - sparsematrix& s, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function creates sparse matrix in a CRS format (expert function for -situations when you are running out of memory). This version of CRS -matrix creation function may reuse memory already allocated in S. - -This function creates CRS matrix. Typical usage scenario for a CRS matrix -is: -1. creation (you have to tell number of non-zero elements at each row at - this moment) -2. insertion of the matrix elements (row by row, from left to right) -3. matrix is passed to some linear algebra algorithm - -This function is a memory-efficient alternative to SparseCreate(), but it -is more complex because it requires you to know in advance how large your -matrix is. Some information about different matrix formats can be found -in comments on SparseMatrix structure. We recommend you to read them -before starting to use ALGLIB sparse matrices.. - -INPUT PARAMETERS - M - number of rows in a matrix, M>=1 - N - number of columns in a matrix, N>=1 - NER - number of elements at each row, array[M], NER[I]>=0 - S - sparse matrix structure with possibly preallocated - memory. - -OUTPUT PARAMETERS - S - sparse M*N matrix in CRS representation. - You have to fill ALL non-zero elements by calling - SparseSet() BEFORE you try to use this matrix. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsecreatecrsbuf( - ae_int_t m, - ae_int_t n, - integer_1d_array ner, - sparsematrix s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function creates sparse matrix in a SKS format (skyline storage -format). In most cases you do not need this function - CRS format better -suits most use cases. - -INPUT PARAMETERS - M, N - number of rows(M) and columns (N) in a matrix: - * M=N (as for now, ALGLIB supports only square SKS) - * N>=1 - * M>=1 - D - "bottom" bandwidths, array[M], D[I]>=0. - I-th element stores number of non-zeros at I-th row, - below the diagonal (diagonal itself is not included) - U - "top" bandwidths, array[N], U[I]>=0. - I-th element stores number of non-zeros at I-th row, - above the diagonal (diagonal itself is not included) - -OUTPUT PARAMETERS - S - sparse M*N matrix in SKS representation. - All elements are filled by zeros. - You may use sparseset() to change their values. - -NOTE: this function completely overwrites S with new sparse matrix. - Previously allocated storage is NOT reused. If you want to reuse - already allocated memory, call SparseCreateSKSBuf function. - - -- ALGLIB PROJECT -- - Copyright 13.01.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsecreatesks( - ae_int_t m, - ae_int_t n, - integer_1d_array d, - integer_1d_array u, - sparsematrix& s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function creates sparse matrix in a SKS format (skyline storage -format). Unlike more general sparsecreatesks(), this function creates -sparse matrix with constant bandwidth. - -You may want to use this function instead of sparsecreatesks() when your -matrix has constant or nearly-constant bandwidth, and you want to -simplify source code. - -INPUT PARAMETERS - M, N - number of rows(M) and columns (N) in a matrix: - * M=N (as for now, ALGLIB supports only square SKS) - * N>=1 - * M>=1 - BW - matrix bandwidth, BW>=0 - -OUTPUT PARAMETERS - S - sparse M*N matrix in SKS representation. - All elements are filled by zeros. - You may use sparseset() to change their values. - -NOTE: this function completely overwrites S with new sparse matrix. - Previously allocated storage is NOT reused. If you want to reuse - already allocated memory, call sparsecreatesksbandbuf function. - - -- ALGLIB PROJECT -- - Copyright 25.12.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsecreatesksband( - ae_int_t m, - ae_int_t n, - ae_int_t bw, - sparsematrix& s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is "buffered" version of sparsecreatesksband() which reuses memory -previously allocated in S (of course, memory is reallocated if needed). - -You may want to use this function instead of sparsecreatesksbuf() when -your matrix has constant or nearly-constant bandwidth, and you want to -simplify source code. - -INPUT PARAMETERS - M, N - number of rows(M) and columns (N) in a matrix: - * M=N (as for now, ALGLIB supports only square SKS) - * N>=1 - * M>=1 - BW - bandwidth, BW>=0 - -OUTPUT PARAMETERS - S - sparse M*N matrix in SKS representation. - All elements are filled by zeros. - You may use sparseset() to change their values. - - -- ALGLIB PROJECT -- - Copyright 13.01.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsecreatesksbandbuf( - ae_int_t m, - ae_int_t n, - ae_int_t bw, - sparsematrix s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is "buffered" version of SparseCreateSKS() which reuses memory -previously allocated in S (of course, memory is reallocated if needed). - -This function creates sparse matrix in a SKS format (skyline storage -format). In most cases you do not need this function - CRS format better -suits most use cases. - -INPUT PARAMETERS - M, N - number of rows(M) and columns (N) in a matrix: - * M=N (as for now, ALGLIB supports only square SKS) - * N>=1 - * M>=1 - D - "bottom" bandwidths, array[M], 0<=D[I]<=I. - I-th element stores number of non-zeros at I-th row, - below the diagonal (diagonal itself is not included) - U - "top" bandwidths, array[N], 0<=U[I]<=I. - I-th element stores number of non-zeros at I-th row, - above the diagonal (diagonal itself is not included) - -OUTPUT PARAMETERS - S - sparse M*N matrix in SKS representation. - All elements are filled by zeros. - You may use sparseset() to change their values. - - -- ALGLIB PROJECT -- - Copyright 13.01.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsecreatesksbuf( - ae_int_t m, - ae_int_t n, - integer_1d_array d, - integer_1d_array u, - sparsematrix s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function is used to enumerate all elements of the sparse matrix. -Before first call user initializes T0 and T1 counters by zero. These -counters are used to remember current position in a matrix; after each -call they are updated by the function. - -Subsequent calls to this function return non-zero elements of the sparse -matrix, one by one. If you enumerate CRS matrix, matrix is traversed from -left to right, from top to bottom. In case you enumerate matrix stored as -Hash table, elements are returned in random order. - -EXAMPLE - > T0=0 - > T1=0 - > while SparseEnumerate(S,T0,T1,I,J,V) do - > ....do something with I,J,V - -INPUT PARAMETERS - S - sparse M*N matrix in Hash-Table or CRS representation. - T0 - internal counter - T1 - internal counter - -OUTPUT PARAMETERS - T0 - new value of the internal counter - T1 - new value of the internal counter - I - row index of non-zero element, 0<=I<M. - J - column index of non-zero element, 0<=J<N - V - value of the T-th element - -RESULT - True in case of success (next non-zero element was retrieved) - False in case all non-zero elements were enumerated - -NOTE: you may call SparseRewriteExisting() during enumeration, but it is - THE ONLY matrix modification function you can call!!! Other - matrix modification functions should not be called during enumeration! - - -- ALGLIB PROJECT -- - Copyright 14.03.2012 by Bochkanov Sergey -*************************************************************************/ -
bool alglib::sparseenumerate( - sparsematrix s, - ae_int_t& t0, - ae_int_t& t1, - ae_int_t& i, - ae_int_t& j, - double& v, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function checks whether S[i,j] is present in the sparse matrix. It -returns True even for elements that are numerically zero (but still -have place allocated for them). - -The matrix can be in any mode (Hash-Table, CRS, SKS), but this function -is less efficient for CRS matrices. Hash-Table and SKS matrices can find -element in O(1) time, while CRS matrices need O(log(RS)) time, where RS -is an number of non-zero elements in a row. - -INPUT PARAMETERS - S - sparse M*N matrix - I - row index of the element to modify, 0<=I<M - J - column index of the element to modify, 0<=J<N - -RESULT - whether S[I,J] is present in the data structure or not - - -- ALGLIB PROJECT -- - Copyright 14.10.2020 by Bochkanov Sergey -*************************************************************************/ -
bool alglib::sparseexists( - sparsematrix s, - ae_int_t i, - ae_int_t j, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -The function frees all memory occupied by sparse matrix. Sparse matrix -structure becomes unusable after this call. - -OUTPUT PARAMETERS - S - sparse matrix to delete - - -- ALGLIB PROJECT -- - Copyright 24.07.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsefree( - sparsematrix& s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates generalized sparse matrix-vector product - - y := alpha*op(S)*x + beta*y - -Matrix S must be stored in CRS or SKS format (exception will be thrown -otherwise). op(S) can be either S or S^T. - -NOTE: this function expects Y to be large enough to store result. No - automatic preallocation happens for smaller arrays. - -INPUT PARAMETERS - S - sparse matrix in CRS or SKS format. - Alpha - source coefficient - OpS - operation type: - * OpS=0 => op(S) = S - * OpS=1 => op(S) = S^T - X - input vector, must have at least Cols(op(S))+IX elements - IX - subvector offset - Beta - destination coefficient - Y - preallocated output array, must have at least Rows(op(S))+IY elements - IY - subvector offset - -OUTPUT PARAMETERS - Y - elements [IY...IY+Rows(op(S))-1] are replaced by result, - other elements are not modified - -HANDLING OF SPECIAL CASES: -* below M=Rows(op(S)) and N=Cols(op(S)). Although current ALGLIB version - does not allow you to create zero-sized sparse matrices, internally - ALGLIB can deal with such matrices. So, comments for M or N equal to - zero are for internal use only. -* if M=0, then subroutine does nothing. It does not even touch arrays. -* if N=0 or Alpha=0.0, then: - * if Beta=0, then Y is filled by zeros. S and X are not referenced at - all. Initial values of Y are ignored (we do not multiply Y by zero, - we just rewrite it by zeros) - * if Beta<>0, then Y is replaced by Beta*Y -* if M>0, N>0, Alpha<>0, but Beta=0, then Y is replaced by alpha*op(S)*x - initial state of Y is ignored (rewritten without initial multiplication - by zeros). - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 10.12.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsegemv( - sparsematrix s, - double alpha, - ae_int_t ops, - real_1d_array x, - ae_int_t ix, - double beta, - real_1d_array& y, - ae_int_t iy, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function returns S[i,j] - element of the sparse matrix. Matrix can -be in any mode (Hash-Table, CRS, SKS), but this function is less efficient -for CRS matrices. Hash-Table and SKS matrices can find element in O(1) -time, while CRS matrices need O(log(RS)) time, where RS is an number of -non-zero elements in a row. - -INPUT PARAMETERS - S - sparse M*N matrix - I - row index of the element to modify, 0<=I<M - J - column index of the element to modify, 0<=J<N - -RESULT - value of S[I,J] or zero (in case no element with such index is found) - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -
double alglib::sparseget( - sparsematrix s, - ae_int_t i, - ae_int_t j, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function returns I-th row of the sparse matrix IN COMPRESSED FORMAT - -only non-zero elements are returned (with their indexes). Matrix must be -stored in CRS or SKS format. - -INPUT PARAMETERS: - S - sparse M*N matrix in CRS format - I - row index, 0<=I<M - ColIdx - output buffer for column indexes, can be preallocated. - In case buffer size is too small to store I-th row, it - is automatically reallocated. - Vals - output buffer for values, can be preallocated. In case - buffer size is too small to store I-th row, it is - automatically reallocated. - -OUTPUT PARAMETERS: - ColIdx - column indexes of non-zero elements, sorted by - ascending. Symbolically non-zero elements are counted - (i.e. if you allocated place for element, but it has - zero numerical value - it is counted). - Vals - values. Vals[K] stores value of matrix element with - indexes (I,ColIdx[K]). Symbolically non-zero elements - are counted (i.e. if you allocated place for element, - but it has zero numerical value - it is counted). - NZCnt - number of symbolically non-zero elements per row. - -NOTE: when incorrect I (outside of [0,M-1]) or matrix (non CRS/SKS) - is passed, this function throws exception. - -NOTE: this function may allocate additional, unnecessary place for ColIdx - and Vals arrays. It is dictated by performance reasons - on SKS - matrices it is faster to allocate space at the beginning with - some "extra"-space, than performing two passes over matrix - first - time to calculate exact space required for data, second time - to - store data itself. - - -- ALGLIB PROJECT -- - Copyright 10.12.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsegetcompressedrow( - sparsematrix s, - ae_int_t i, - integer_1d_array& colidx, - real_1d_array& vals, - ae_int_t& nzcnt, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function returns I-th diagonal element of the sparse matrix. - -Matrix can be in any mode (Hash-Table or CRS storage), but this function -is most efficient for CRS matrices - it requires less than 50 CPU cycles -to extract diagonal element. For Hash-Table matrices we still have O(1) -query time, but function is many times slower. - -INPUT PARAMETERS - S - sparse M*N matrix in Hash-Table representation. - Exception will be thrown for CRS matrix. - I - index of the element to modify, 0<=I<min(M,N) - -RESULT - value of S[I,I] or zero (in case no element with such index is found) - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -
double alglib::sparsegetdiagonal( - sparsematrix s, - ae_int_t i, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -The function returns number of strictly lower triangular non-zero elements -in the matrix. It counts SYMBOLICALLY non-zero elements, i.e. entries -in the sparse matrix data structure. If some element has zero numerical -value, it is still counted. - -This function has different cost for different types of matrices: -* for hash-based matrices it involves complete pass over entire hash-table - with O(NNZ) cost, where NNZ is number of non-zero elements -* for CRS and SKS matrix types cost of counting is O(N) (N - matrix size). - -RESULT: number of non-zero elements strictly below main diagonal - - -- ALGLIB PROJECT -- - Copyright 12.02.2014 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::sparsegetlowercount( - sparsematrix s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function returns type of the matrix storage format. - -INPUT PARAMETERS: - S - sparse matrix. - -RESULT: - sparse storage format used by matrix: - 0 - Hash-table - 1 - CRS (compressed row storage) - 2 - SKS (skyline) - -NOTE: future versions of ALGLIB may include additional sparse storage - formats. - - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::sparsegetmatrixtype( - sparsematrix s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -The function returns number of columns of a sparse matrix. - -RESULT: number of columns of a sparse matrix. - - -- ALGLIB PROJECT -- - Copyright 23.08.2012 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::sparsegetncols( - sparsematrix s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -The function returns number of rows of a sparse matrix. - -RESULT: number of rows of a sparse matrix. - - -- ALGLIB PROJECT -- - Copyright 23.08.2012 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::sparsegetnrows( - sparsematrix s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function returns I-th row of the sparse matrix. Matrix must be stored -in CRS or SKS format. - -INPUT PARAMETERS: - S - sparse M*N matrix in CRS format - I - row index, 0<=I<M - IRow - output buffer, can be preallocated. In case buffer - size is too small to store I-th row, it is - automatically reallocated. - -OUTPUT PARAMETERS: - IRow - array[M], I-th row. - -NOTE: this function has O(N) running time, where N is a column count. It - allocates and fills N-element array, even although most of its - elemets are zero. - -NOTE: If you have O(non-zeros-per-row) time and memory requirements, use - SparseGetCompressedRow() function. It returns data in compressed - format. - -NOTE: when incorrect I (outside of [0,M-1]) or matrix (non CRS/SKS) - is passed, this function throws exception. - - -- ALGLIB PROJECT -- - Copyright 10.12.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsegetrow( - sparsematrix s, - ae_int_t i, - real_1d_array& irow, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -The function returns number of strictly upper triangular non-zero elements -in the matrix. It counts SYMBOLICALLY non-zero elements, i.e. entries -in the sparse matrix data structure. If some element has zero numerical -value, it is still counted. - -This function has different cost for different types of matrices: -* for hash-based matrices it involves complete pass over entire hash-table - with O(NNZ) cost, where NNZ is number of non-zero elements -* for CRS and SKS matrix types cost of counting is O(N) (N - matrix size). - -RESULT: number of non-zero elements strictly above main diagonal - - -- ALGLIB PROJECT -- - Copyright 12.02.2014 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::sparsegetuppercount( - sparsematrix s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function checks matrix storage format and returns True when matrix is -stored using CRS representation. - -INPUT PARAMETERS: - S - sparse matrix. - -RESULT: - True if matrix type is CRS - False if matrix type is not CRS - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -
bool alglib::sparseiscrs( - sparsematrix s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function checks matrix storage format and returns True when matrix is -stored using Hash table representation. - -INPUT PARAMETERS: - S - sparse matrix. - -RESULT: - True if matrix type is Hash table - False if matrix type is not Hash table - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -
bool alglib::sparseishash( - sparsematrix s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function checks matrix storage format and returns True when matrix is -stored using SKS representation. - -INPUT PARAMETERS: - S - sparse matrix. - -RESULT: - True if matrix type is SKS - False if matrix type is not SKS - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -
bool alglib::sparseissks( - sparsematrix s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates matrix-matrix product S*A. Matrix S must be -stored in CRS or SKS format (exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse M*N matrix in CRS or SKS format. - A - array[N][K], input dense matrix. For performance reasons - we make only quick checks - we check that array size - is at least N, but we do not check for NAN's or INF's. - K - number of columns of matrix (A). - B - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - B - array[M][K], S*A - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsemm( - sparsematrix s, - real_2d_array a, - ae_int_t k, - real_2d_array& b, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function simultaneously calculates two matrix-matrix products: - S*A and S^T*A. -S must be square (non-rectangular) matrix stored in CRS or SKS format -(exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse N*N matrix in CRS or SKS format. - A - array[N][K], input dense matrix. For performance reasons - we make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - K - number of columns of matrix (A). - B0 - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - B1 - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - B0 - array[N][K], S*A - B1 - array[N][K], S^T*A - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsemm2( - sparsematrix s, - real_2d_array a, - ae_int_t k, - real_2d_array& b0, - real_2d_array& b1, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates matrix-matrix product S^T*A. Matrix S must be -stored in CRS or SKS format (exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse M*N matrix in CRS or SKS format. - A - array[M][K], input dense matrix. For performance reasons - we make only quick checks - we check that array size is - at least M, but we do not check for NAN's or INF's. - K - number of columns of matrix (A). - B - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - B - array[N][K], S^T*A - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsemtm( - sparsematrix s, - real_2d_array a, - ae_int_t k, - real_2d_array& b, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates matrix-vector product S^T*x. Matrix S must be -stored in CRS or SKS format (exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse M*N matrix in CRS or SKS format. - X - array[M], input vector. For performance reasons we - make only quick checks - we check that array size is - at least M, but we do not check for NAN's or INF's. - Y - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - Y - array[N], S^T*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsemtv( - sparsematrix s, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates matrix-vector product S*x. Matrix S must be -stored in CRS or SKS format (exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse M*N matrix in CRS or SKS format. - X - array[N], input vector. For performance reasons we - make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - Y - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - Y - array[M], S*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsemv( - sparsematrix s, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function simultaneously calculates two matrix-vector products: - S*x and S^T*x. -S must be square (non-rectangular) matrix stored in CRS or SKS format -(exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse N*N matrix in CRS or SKS format. - X - array[N], input vector. For performance reasons we - make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - Y0 - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - Y1 - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - Y0 - array[N], S*x - Y1 - array[N], S^T*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsemv2( - sparsematrix s, - real_1d_array x, - real_1d_array& y0, - real_1d_array& y1, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This procedure resizes Hash-Table matrix. It can be called when you have -deleted too many elements from the matrix, and you want to free unneeded -memory. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparseresizematrix( - sparsematrix s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function rewrites existing (non-zero) element. It returns True if -element exists or False, when it is called for non-existing (zero) -element. - -This function works with any kind of the matrix. - -The purpose of this function is to provide convenient thread-safe way to -modify sparse matrix. Such modification (already existing element is -rewritten) is guaranteed to be thread-safe without any synchronization, as -long as different threads modify different elements. - -INPUT PARAMETERS - S - sparse M*N matrix in any kind of representation - (Hash, SKS, CRS). - I - row index of non-zero element to modify, 0<=I<M - J - column index of non-zero element to modify, 0<=J<N - V - value to rewrite, must be finite number - -OUTPUT PARAMETERS - S - modified matrix -RESULT - True in case when element exists - False in case when element doesn't exist or it is zero - - -- ALGLIB PROJECT -- - Copyright 14.03.2012 by Bochkanov Sergey -*************************************************************************/ -
bool alglib::sparserewriteexisting( - sparsematrix s, - ae_int_t i, - ae_int_t j, - double v, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function modifies S[i,j] - element of the sparse matrix. - -For Hash-based storage format: -* this function can be called at any moment - during matrix initialization - or later -* new value can be zero or non-zero. In case new value of S[i,j] is zero, - this element is deleted from the table. -* this function has no effect when called with zero V for non-existent - element. - -For CRS-bases storage format: -* this function can be called ONLY DURING MATRIX INITIALIZATION -* zero values are stored in the matrix similarly to non-zero ones -* elements must be initialized in correct order - from top row to bottom, - within row - from left to right. - -For SKS storage: -* this function can be called at any moment - during matrix initialization - or later -* zero values are stored in the matrix similarly to non-zero ones -* this function CAN NOT be called for non-existent (outside of the band - specified during SKS matrix creation) elements. Say, if you created SKS - matrix with bandwidth=2 and tried to call sparseset(s,0,10,VAL), an - exception will be generated. - -INPUT PARAMETERS - S - sparse M*N matrix in Hash-Table, SKS or CRS format. - I - row index of the element to modify, 0<=I<M - J - column index of the element to modify, 0<=J<N - V - value to set, must be finite number, can be zero - -OUTPUT PARAMETERS - S - modified matrix - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparseset( - sparsematrix s, - ae_int_t i, - ae_int_t j, - double v, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function calculates matrix-matrix product S*A, when S is symmetric -matrix. Matrix S must be stored in CRS or SKS format (exception will be -thrown otherwise). - -INPUT PARAMETERS - S - sparse M*M matrix in CRS or SKS format. - IsUpper - whether upper or lower triangle of S is given: - * if upper triangle is given, only S[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only S[i,j] for j<=i - are used, and upper triangle is ignored. - A - array[N][K], input dense matrix. For performance reasons - we make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - K - number of columns of matrix (A). - B - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - B - array[M][K], S*A - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsesmm( - sparsematrix s, - bool isupper, - real_2d_array a, - ae_int_t k, - real_2d_array& b, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates matrix-vector product S*x, when S is symmetric -matrix. Matrix S must be stored in CRS or SKS format (exception will be -thrown otherwise). - -INPUT PARAMETERS - S - sparse M*M matrix in CRS or SKS format. - IsUpper - whether upper or lower triangle of S is given: - * if upper triangle is given, only S[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only S[i,j] for j<=i - are used, and upper triangle is ignored. - X - array[N], input vector. For performance reasons we - make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - Y - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - Y - array[M], S*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsesmv( - sparsematrix s, - bool isupper, - real_1d_array x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function efficiently swaps contents of S0 and S1. - - -- ALGLIB PROJECT -- - Copyright 16.01.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparseswap( - sparsematrix s0, - sparsematrix s1, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function applies permutation given by permutation table P (as opposed -to product form of permutation) to sparse symmetric matrix A, given by -either upper or lower triangle: B := P*A*P'. - -This function allocates completely new instance of B. Use buffered version -SparseSymmPermTblBuf() if you want to reuse already allocated structure. - -INPUT PARAMETERS - A - sparse square matrix in CRS format. - IsUpper - whether upper or lower triangle of A is used: - * if upper triangle is given, only A[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only A[i,j] for j<=i - are used, and upper triangle is ignored. - P - array[N] which stores permutation table; P[I]=J means - that I-th row/column of matrix A is moved to J-th - position. For performance reasons we do NOT check that - P[] is a correct permutation (that there is no - repetitions, just that all its elements are in [0,N) - range. - -OUTPUT PARAMETERS - B - permuted matrix. Permutation is applied to A from - the both sides, only upper or lower triangle (depending - on IsUpper) is stored. - -NOTE: this function throws exception when called for non-CRS matrix. You - must convert your matrix with SparseConvertToCRS() before using this - function. - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -
void alglib::sparsesymmpermtbl( - sparsematrix a, - bool isupper, - integer_1d_array p, - sparsematrix& b, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function is a buffered version of SparseSymmPermTbl() that reuses -previously allocated storage in B as much as possible. - -This function applies permutation given by permutation table P (as opposed -to product form of permutation) to sparse symmetric matrix A, given by -either upper or lower triangle: B := P*A*P'. - -INPUT PARAMETERS - A - sparse square matrix in CRS format. - IsUpper - whether upper or lower triangle of A is used: - * if upper triangle is given, only A[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only A[i,j] for j<=i - are used, and upper triangle is ignored. - P - array[N] which stores permutation table; P[I]=J means - that I-th row/column of matrix A is moved to J-th - position. For performance reasons we do NOT check that - P[] is a correct permutation (that there is no - repetitions, just that all its elements are in [0,N) - range. - B - sparse matrix object that will hold output. - Previously allocated memory will be reused as much as - possible. - -OUTPUT PARAMETERS - B - permuted matrix. Permutation is applied to A from - the both sides, only upper or lower triangle (depending - on IsUpper) is stored. - -NOTE: this function throws exception when called for non-CRS matrix. You - must convert your matrix with SparseConvertToCRS() before using this - function. - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -
void alglib::sparsesymmpermtblbuf( - sparsematrix a, - bool isupper, - integer_1d_array p, - sparsematrix b, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function performs transpose of CRS matrix. - -INPUT PARAMETERS - S - sparse matrix in CRS format. - -OUTPUT PARAMETERS - S - sparse matrix, transposed. - -NOTE: internal temporary copy is allocated for the purposes of - transposition. It is deallocated after transposition. - - -- ALGLIB PROJECT -- - Copyright 30.01.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsetransposecrs( - sparsematrix s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function performs efficient in-place transpose of SKS matrix. No -additional memory is allocated during transposition. - -This function supports only skyline storage format (SKS). - -INPUT PARAMETERS - S - sparse matrix in SKS format. - -OUTPUT PARAMETERS - S - sparse matrix, transposed. - - -- ALGLIB PROJECT -- - Copyright 16.01.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsetransposesks( - sparsematrix s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates matrix-vector product op(S)*x, when x is vector, -S is symmetric triangular matrix, op(S) is transposition or no operation. -Matrix S must be stored in CRS or SKS format (exception will be thrown -otherwise). - -INPUT PARAMETERS - S - sparse square matrix in CRS or SKS format. - IsUpper - whether upper or lower triangle of S is used: - * if upper triangle is given, only S[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only S[i,j] for j<=i - are used, and upper triangle is ignored. - IsUnit - unit or non-unit diagonal: - * if True, diagonal elements of triangular matrix are - considered equal to 1.0. Actual elements stored in - S are not referenced at all. - * if False, diagonal stored in S is used - OpType - operation type: - * if 0, S*x is calculated - * if 1, (S^T)*x is calculated (transposition) - X - array[N] which stores input vector. For performance - reasons we make only quick checks - we check that - array size is at least N, but we do not check for - NAN's or INF's. - Y - possibly preallocated input buffer. Automatically - resized if its size is too small. - -OUTPUT PARAMETERS - Y - array[N], op(S)*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 20.01.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsetrmv( - sparsematrix s, - bool isupper, - bool isunit, - ae_int_t optype, - real_1d_array& x, - real_1d_array& y, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function solves linear system op(S)*y=x where x is vector, S is -symmetric triangular matrix, op(S) is transposition or no operation. -Matrix S must be stored in CRS or SKS format (exception will be thrown -otherwise). - -INPUT PARAMETERS - S - sparse square matrix in CRS or SKS format. - IsUpper - whether upper or lower triangle of S is used: - * if upper triangle is given, only S[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only S[i,j] for j<=i - are used, and upper triangle is ignored. - IsUnit - unit or non-unit diagonal: - * if True, diagonal elements of triangular matrix are - considered equal to 1.0. Actual elements stored in - S are not referenced at all. - * if False, diagonal stored in S is used. It is your - responsibility to make sure that diagonal is - non-zero. - OpType - operation type: - * if 0, S*x is calculated - * if 1, (S^T)*x is calculated (transposition) - X - array[N] which stores input vector. For performance - reasons we make only quick checks - we check that - array size is at least N, but we do not check for - NAN's or INF's. - -OUTPUT PARAMETERS - X - array[N], inv(op(S))*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. - You must convert your matrix with SparseConvertToCRS/SKS() before - using this function. - -NOTE: no assertion or tests are done during algorithm operation. It is - your responsibility to provide invertible matrix to algorithm. - - -- ALGLIB PROJECT -- - Copyright 20.01.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsetrsv( - sparsematrix s, - bool isupper, - bool isunit, - ae_int_t optype, - real_1d_array& x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function calculates vector-matrix-vector product x'*S*x, where S is -symmetric matrix. Matrix S must be stored in CRS or SKS format (exception -will be thrown otherwise). - -INPUT PARAMETERS - S - sparse M*M matrix in CRS or SKS format. - IsUpper - whether upper or lower triangle of S is given: - * if upper triangle is given, only S[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only S[i,j] for j<=i - are used, and upper triangle is ignored. - X - array[N], input vector. For performance reasons we - make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - -RESULT - x'*S*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 27.01.2014 by Bochkanov Sergey -*************************************************************************/ -
double alglib::sparsevsmv( - sparsematrix s, - bool isupper, - real_1d_array x, - const xparams _params = alglib::xdefault); - -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "linalg.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates creation/initialization of the sparse matrix
-    // and matrix-vector multiplication.
-    //
-    // First, we have to create matrix and initialize it. Matrix is initially created
-    // in the Hash-Table format, which allows convenient initialization. We can modify
-    // Hash-Table matrix with sparseset() and sparseadd() functions.
-    //
-    // NOTE: Unlike CRS format, Hash-Table representation allows you to initialize
-    // elements in the arbitrary order. You may see that we initialize a[0][0] first,
-    // then move to the second row, and then move back to the first row.
-    //
-    sparsematrix s;
-    sparsecreate(2, 2, s);
-    sparseset(s, 0, 0, 2.0);
-    sparseset(s, 1, 1, 1.0);
-    sparseset(s, 0, 1, 1.0);
-
-    sparseadd(s, 1, 1, 4.0);
-
-    //
-    // Now S is equal to
-    //   [ 2 1 ]
-    //   [   5 ]
-    // Lets check it by reading matrix contents with sparseget().
-    // You may see that with sparseget() you may read both non-zero
-    // and zero elements.
-    //
-    double v;
-    v = sparseget(s, 0, 0);
-    printf("%.2f\n", double(v)); // EXPECTED: 2.0000
-    v = sparseget(s, 0, 1);
-    printf("%.2f\n", double(v)); // EXPECTED: 1.0000
-    v = sparseget(s, 1, 0);
-    printf("%.2f\n", double(v)); // EXPECTED: 0.0000
-    v = sparseget(s, 1, 1);
-    printf("%.2f\n", double(v)); // EXPECTED: 5.0000
-
-    //
-    // After successful creation we can use our matrix for linear operations.
-    //
-    // However, there is one more thing we MUST do before using S in linear
-    // operations: we have to convert it from HashTable representation (used for
-    // initialization and dynamic operations) to CRS format with sparseconverttocrs()
-    // call. If you omit this call, ALGLIB will generate exception on the first
-    // attempt to use S in linear operations. 
-    //
-    sparseconverttocrs(s);
-
-    //
-    // Now S is in the CRS format and we are ready to do linear operations.
-    // Lets calculate A*x for some x.
-    //
-    real_1d_array x = "[1,-1]";
-    real_1d_array y = "[]";
-    sparsemv(s, x, y);
-    printf("%s\n", y.tostring(2).c_str()); // EXPECTED: [1.000,-5.000]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "linalg.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // This example demonstrates creation/initialization of the sparse matrix in the
-    // CRS format.
-    //
-    // Hash-Table format used by default is very convenient (it allows easy
-    // insertion of elements, automatic memory reallocation), but has
-    // significant memory and performance overhead. Insertion of one element 
-    // costs hundreds of CPU cycles, and memory consumption is several times
-    // higher than that of CRS.
-    //
-    // When you work with really large matrices and when you can tell in 
-    // advance how many elements EXACTLY you need, it can be beneficial to 
-    // create matrix in the CRS format from the very beginning.
-    //
-    // If you want to create matrix in the CRS format, you should:
-    // * use sparsecreatecrs() function
-    // * know row sizes in advance (number of non-zero entries in the each row)
-    // * initialize matrix with sparseset() - another function, sparseadd(), is not allowed
-    // * initialize elements from left to right, from top to bottom, each
-    //   element is initialized only once.
-    //
-    sparsematrix s;
-    integer_1d_array row_sizes = "[2,2,2,1]";
-    sparsecreatecrs(4, 4, row_sizes, s);
-    sparseset(s, 0, 0, 2.0);
-    sparseset(s, 0, 1, 1.0);
-    sparseset(s, 1, 1, 4.0);
-    sparseset(s, 1, 2, 2.0);
-    sparseset(s, 2, 2, 3.0);
-    sparseset(s, 2, 3, 1.0);
-    sparseset(s, 3, 3, 9.0);
-
-    //
-    // Now S is equal to
-    //   [ 2 1     ]
-    //   [   4 2   ]
-    //   [     3 1 ]
-    //   [       9 ]
-    //
-    // We should point that we have initialized S elements from left to right,
-    // from top to bottom. CRS representation does NOT allow you to do so in
-    // the different order. Try to change order of the sparseset() calls above,
-    // and you will see that your program generates exception.
-    //
-    // We can check it by reading matrix contents with sparseget().
-    // However, you should remember that sparseget() is inefficient on
-    // CRS matrices (it may have to pass through all elements of the row 
-    // until it finds element you need).
-    //
-    double v;
-    v = sparseget(s, 0, 0);
-    printf("%.2f\n", double(v)); // EXPECTED: 2.0000
-    v = sparseget(s, 2, 3);
-    printf("%.2f\n", double(v)); // EXPECTED: 1.0000
-
-    // you may see that you can read zero elements (which are not stored) with sparseget()
-    v = sparseget(s, 3, 2);
-    printf("%.2f\n", double(v)); // EXPECTED: 0.0000
-
-    //
-    // After successful creation we can use our matrix for linear operations.
-    // Lets calculate A*x for some x.
-    //
-    real_1d_array x = "[1,-1,1,-1]";
-    real_1d_array y = "[]";
-    sparsemv(s, x, y);
-    printf("%s\n", y.tostring(2).c_str()); // EXPECTED: [1.000,-2.000,2.000,-9]
-    return 0;
-}
-
-
-
-
- -smatrixgevd
-smatrixgevdreduce
- - -
- -
-
/************************************************************************* -Algorithm for solving the following generalized symmetric positive-definite -eigenproblem: - A*x = lambda*B*x (1) or - A*B*x = lambda*x (2) or - B*A*x = lambda*x (3). -where A is a symmetric matrix, B - symmetric positive-definite matrix. -The problem is solved by reducing it to an ordinary symmetric eigenvalue -problem. - -Input parameters: - A - symmetric matrix which is given by its upper or lower - triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrices A and B. - IsUpperA - storage format of matrix A. - B - symmetric positive-definite matrix which is given by - its upper or lower triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - IsUpperB - storage format of matrix B. - ZNeeded - if ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - ProblemType - if ProblemType is equal to: - * 1, the following problem is solved: A*x = lambda*B*x; - * 2, the following problem is solved: A*B*x = lambda*x; - * 3, the following problem is solved: B*A*x = lambda*x. - -Output parameters: - D - eigenvalues in ascending order. - Array whose index ranges within [0..N-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains eigenvectors. - Array whose indexes range within [0..N-1, 0..N-1]. - The eigenvectors are stored in matrix columns. It should - be noted that the eigenvectors in such problems do not - form an orthogonal system. - -Result: - True, if the problem was solved successfully. - False, if the error occurred during the Cholesky decomposition of matrix - B (the matrix isn't positive-definite) or during the work of the iterative - algorithm for solving the symmetric eigenproblem. - -See also the GeneralizedSymmetricDefiniteEVDReduce subroutine. - - -- ALGLIB -- - Copyright 1.28.2006 by Bochkanov Sergey -*************************************************************************/ -
bool alglib::smatrixgevd( - real_2d_array a, - ae_int_t n, - bool isuppera, - real_2d_array b, - bool isupperb, - ae_int_t zneeded, - ae_int_t problemtype, - real_1d_array& d, - real_2d_array& z, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Algorithm for reduction of the following generalized symmetric positive- -definite eigenvalue problem: - A*x = lambda*B*x (1) or - A*B*x = lambda*x (2) or - B*A*x = lambda*x (3) -to the symmetric eigenvalues problem C*y = lambda*y (eigenvalues of this and -the given problems are the same, and the eigenvectors of the given problem -could be obtained by multiplying the obtained eigenvectors by the -transformation matrix x = R*y). - -Here A is a symmetric matrix, B - symmetric positive-definite matrix. - -Input parameters: - A - symmetric matrix which is given by its upper or lower - triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrices A and B. - IsUpperA - storage format of matrix A. - B - symmetric positive-definite matrix which is given by - its upper or lower triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - IsUpperB - storage format of matrix B. - ProblemType - if ProblemType is equal to: - * 1, the following problem is solved: A*x = lambda*B*x; - * 2, the following problem is solved: A*B*x = lambda*x; - * 3, the following problem is solved: B*A*x = lambda*x. - -Output parameters: - A - symmetric matrix which is given by its upper or lower - triangle depending on IsUpperA. Contains matrix C. - Array whose indexes range within [0..N-1, 0..N-1]. - R - upper triangular or low triangular transformation matrix - which is used to obtain the eigenvectors of a given problem - as the product of eigenvectors of C (from the right) and - matrix R (from the left). If the matrix is upper - triangular, the elements below the main diagonal - are equal to 0 (and vice versa). Thus, we can perform - the multiplication without taking into account the - internal structure (which is an easier though less - effective way). - Array whose indexes range within [0..N-1, 0..N-1]. - IsUpperR - type of matrix R (upper or lower triangular). - -Result: - True, if the problem was reduced successfully. - False, if the error occurred during the Cholesky decomposition of - matrix B (the matrix is not positive-definite). - - -- ALGLIB -- - Copyright 1.28.2006 by Bochkanov Sergey -*************************************************************************/ -
bool alglib::smatrixgevdreduce( - real_2d_array& a, - ae_int_t n, - bool isuppera, - real_2d_array b, - bool isupperb, - ae_int_t problemtype, - real_2d_array& r, - bool& isupperr, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -Spline fitting report: - RMSError RMS error - AvgError average error - AvgRelError average relative error (for non-zero Y[I]) - MaxError maximum error - -Fields below are filled by obsolete functions (Spline1DFitCubic, -Spline1DFitHermite). Modern fitting functions do NOT fill these fields: - TaskRCond reciprocal of task's condition number -*************************************************************************/ -
class spline1dfitreport -{ - double taskrcond; - double rmserror; - double avgerror; - double avgrelerror; - double maxerror; -}; - -
- -
-
/************************************************************************* -1-dimensional spline interpolant -*************************************************************************/ -
class spline1dinterpolant -{ -}; - -
- -
-
/************************************************************************* -This subroutine builds Akima spline interpolant - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1] - Y - function values, array[0..N-1] - N - points count (optional): - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - -OUTPUT PARAMETERS: - C - spline interpolant - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - - -- ALGLIB PROJECT -- - Copyright 24.06.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dbuildakima( - real_1d_array x, - real_1d_array y, - spline1dinterpolant& c, - const xparams _params = alglib::xdefault); -void alglib::spline1dbuildakima( - real_1d_array x, - real_1d_array y, - ae_int_t n, - spline1dinterpolant& c, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine builds Catmull-Rom spline interpolant. - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1]. - Y - function values, array[0..N-1]. - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundType - boundary condition type: - * -1 for periodic boundary condition - * 0 for parabolically terminated spline (default) - Tension - tension parameter: - * tension=0 corresponds to classic Catmull-Rom spline (default) - * 0<tension<1 corresponds to more general form - cardinal spline - -OUTPUT PARAMETERS: - C - spline interpolant - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 23.06.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dbuildcatmullrom( - real_1d_array x, - real_1d_array y, - spline1dinterpolant& c, - const xparams _params = alglib::xdefault); -void alglib::spline1dbuildcatmullrom( - real_1d_array x, - real_1d_array y, - ae_int_t n, - ae_int_t boundtype, - double tension, - spline1dinterpolant& c, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine builds cubic spline interpolant. - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1]. - Y - function values, array[0..N-1]. - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - -OUTPUT PARAMETERS: - C - spline interpolant - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 23.06.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dbuildcubic( - real_1d_array x, - real_1d_array y, - spline1dinterpolant& c, - const xparams _params = alglib::xdefault); -void alglib::spline1dbuildcubic( - real_1d_array x, - real_1d_array y, - ae_int_t n, - ae_int_t boundltype, - double boundl, - ae_int_t boundrtype, - double boundr, - spline1dinterpolant& c, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine builds Hermite spline interpolant. - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1] - Y - function values, array[0..N-1] - D - derivatives, array[0..N-1] - N - points count (optional): - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - -OUTPUT PARAMETERS: - C - spline interpolant. - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - - -- ALGLIB PROJECT -- - Copyright 23.06.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dbuildhermite( - real_1d_array x, - real_1d_array y, - real_1d_array d, - spline1dinterpolant& c, - const xparams _params = alglib::xdefault); -void alglib::spline1dbuildhermite( - real_1d_array x, - real_1d_array y, - real_1d_array d, - ae_int_t n, - spline1dinterpolant& c, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine builds linear spline interpolant - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1] - Y - function values, array[0..N-1] - N - points count (optional): - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - -OUTPUT PARAMETERS: - C - spline interpolant - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - - -- ALGLIB PROJECT -- - Copyright 24.06.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dbuildlinear( - real_1d_array x, - real_1d_array y, - spline1dinterpolant& c, - const xparams _params = alglib::xdefault); -void alglib::spline1dbuildlinear( - real_1d_array x, - real_1d_array y, - ae_int_t n, - spline1dinterpolant& c, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function builds monotone cubic Hermite interpolant. This interpolant -is monotonic in [x(0),x(n-1)] and is constant outside of this interval. - -In case y[] form non-monotonic sequence, interpolant is piecewise -monotonic. Say, for x=(0,1,2,3,4) and y=(0,1,2,1,0) interpolant will -monotonically grow at [0..2] and monotonically decrease at [2..4]. - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1]. Subroutine automatically - sorts points, so caller may pass unsorted array. - Y - function values, array[0..N-1] - N - the number of points(N>=2). - -OUTPUT PARAMETERS: - C - spline interpolant. - - -- ALGLIB PROJECT -- - Copyright 21.06.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dbuildmonotone( - real_1d_array x, - real_1d_array y, - spline1dinterpolant& c, - const xparams _params = alglib::xdefault); -void alglib::spline1dbuildmonotone( - real_1d_array x, - real_1d_array y, - ae_int_t n, - spline1dinterpolant& c, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This subroutine calculates the value of the spline at the given point X. - -INPUT PARAMETERS: - C - spline interpolant - X - point - -Result: - S(x) - - -- ALGLIB PROJECT -- - Copyright 23.06.2007 by Bochkanov Sergey -*************************************************************************/ -
double alglib::spline1dcalc( - spline1dinterpolant c, - double x, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -This function solves following problem: given table y[] of function values -at old nodes x[] and new nodes x2[], it calculates and returns table of -function values y2[] (calculated at x2[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - old spline nodes - Y - function values - X2 - new spline nodes - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points from X/Y are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - N2 - new points count: - * N2>=2 - * if given, only first N2 points from X2 are used - * if not given, automatically detected from X2 size - -OUTPUT PARAMETERS: - F2 - function values at X2[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Function values are correctly reordered on return, so F2[I] is always -equal to S(X2[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dconvcubic( - real_1d_array x, - real_1d_array y, - real_1d_array x2, - real_1d_array& y2, - const xparams _params = alglib::xdefault); -void alglib::spline1dconvcubic( - real_1d_array x, - real_1d_array y, - ae_int_t n, - ae_int_t boundltype, - double boundl, - ae_int_t boundrtype, - double boundr, - real_1d_array x2, - ae_int_t n2, - real_1d_array& y2, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function solves following problem: given table y[] of function values -at old nodes x[] and new nodes x2[], it calculates and returns table of -function values y2[], first and second derivatives d2[] and dd2[] -(calculated at x2[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - old spline nodes - Y - function values - X2 - new spline nodes - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points from X/Y are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - N2 - new points count: - * N2>=2 - * if given, only first N2 points from X2 are used - * if not given, automatically detected from X2 size - -OUTPUT PARAMETERS: - F2 - function values at X2[] - D2 - first derivatives at X2[] - DD2 - second derivatives at X2[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Function values are correctly reordered on return, so F2[I] is always -equal to S(X2[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dconvdiff2cubic( - real_1d_array x, - real_1d_array y, - real_1d_array x2, - real_1d_array& y2, - real_1d_array& d2, - real_1d_array& dd2, - const xparams _params = alglib::xdefault); -void alglib::spline1dconvdiff2cubic( - real_1d_array x, - real_1d_array y, - ae_int_t n, - ae_int_t boundltype, - double boundl, - ae_int_t boundrtype, - double boundr, - real_1d_array x2, - ae_int_t n2, - real_1d_array& y2, - real_1d_array& d2, - real_1d_array& dd2, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function solves following problem: given table y[] of function values -at old nodes x[] and new nodes x2[], it calculates and returns table of -function values y2[] and derivatives d2[] (calculated at x2[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - old spline nodes - Y - function values - X2 - new spline nodes - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points from X/Y are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - N2 - new points count: - * N2>=2 - * if given, only first N2 points from X2 are used - * if not given, automatically detected from X2 size - -OUTPUT PARAMETERS: - F2 - function values at X2[] - D2 - first derivatives at X2[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Function values are correctly reordered on return, so F2[I] is always -equal to S(X2[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dconvdiffcubic( - real_1d_array x, - real_1d_array y, - real_1d_array x2, - real_1d_array& y2, - real_1d_array& d2, - const xparams _params = alglib::xdefault); -void alglib::spline1dconvdiffcubic( - real_1d_array x, - real_1d_array y, - ae_int_t n, - ae_int_t boundltype, - double boundl, - ae_int_t boundrtype, - double boundr, - real_1d_array x2, - ae_int_t n2, - real_1d_array& y2, - real_1d_array& d2, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This subroutine differentiates the spline. - -INPUT PARAMETERS: - C - spline interpolant. - X - point - -Result: - S - S(x) - DS - S'(x) - D2S - S''(x) - - -- ALGLIB PROJECT -- - Copyright 24.06.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1ddiff( - spline1dinterpolant c, - double x, - double& s, - double& ds, - double& d2s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Fitting by smoothing (penalized) cubic spline. - -This function approximates N scattered points (some of X[] may be equal to -each other) by cubic spline with M nodes at equidistant grid spanning -interval [min(x,xc),max(x,xc)]. - -The problem is regularized by adding nonlinearity penalty to usual least -squares penalty function: - - MERIT_FUNC = F_LS + F_NL - -where F_LS is a least squares error term, and F_NL is a nonlinearity -penalty which is roughly proportional to LambdaNS*integral{ S''(x)^2*dx }. -Algorithm applies automatic renormalization of F_NL which makes penalty -term roughly invariant to scaling of X[] and changes in M. - -This function is a new edition of penalized regression spline fitting, -a fast and compact one which needs much less resources that its previous -version: just O(maxMN) memory and O(maxMN*log(maxMN)) time. - -NOTE: it is OK to run this function with both M<<N and M>>N; say, it is - possible to process 100 points with 1000-node spline. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - N - number of points (optional): - * N>0 - * if given, only first N elements of X/Y are processed - * if not given, automatically determined from lengths - M - number of basis functions ( = number_of_nodes), M>=4. - LambdaNS - LambdaNS>=0, regularization constant passed by user. - It penalizes nonlinearity in the regression spline. - Possible values to start from are 0.00001, 0.1, 1 - -OUTPUT PARAMETERS: - S - spline interpolant. - Rep - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - - -- ALGLIB PROJECT -- - Copyright 27.08.2019 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dfit( - real_1d_array x, - real_1d_array y, - ae_int_t m, - double lambdans, - spline1dinterpolant& s, - spline1dfitreport& rep, - const xparams _params = alglib::xdefault); -void alglib::spline1dfit( - real_1d_array x, - real_1d_array y, - ae_int_t n, - ae_int_t m, - double lambdans, - spline1dinterpolant& s, - spline1dfitreport& rep, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function solves following problem: given table y[] of function values -at nodes x[], it calculates and returns tables of first and second -function derivatives d1[] and d2[] (calculated at the same nodes x[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - spline nodes - Y - function values - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - -OUTPUT PARAMETERS: - D1 - S' values at X[] - D2 - S'' values at X[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Derivative values are correctly reordered on return, so D[I] is always -equal to S'(X[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dgriddiff2cubic( - real_1d_array x, - real_1d_array y, - real_1d_array& d1, - real_1d_array& d2, - const xparams _params = alglib::xdefault); -void alglib::spline1dgriddiff2cubic( - real_1d_array x, - real_1d_array y, - ae_int_t n, - ae_int_t boundltype, - double boundl, - ae_int_t boundrtype, - double boundr, - real_1d_array& d1, - real_1d_array& d2, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function solves following problem: given table y[] of function values -at nodes x[], it calculates and returns table of function derivatives d[] -(calculated at the same nodes x[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - spline nodes - Y - function values - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - -OUTPUT PARAMETERS: - D - derivative values at X[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Derivative values are correctly reordered on return, so D[I] is always -equal to S'(X[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dgriddiffcubic( - real_1d_array x, - real_1d_array y, - real_1d_array& d, - const xparams _params = alglib::xdefault); -void alglib::spline1dgriddiffcubic( - real_1d_array x, - real_1d_array y, - ae_int_t n, - ae_int_t boundltype, - double boundl, - ae_int_t boundrtype, - double boundr, - real_1d_array& d, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This subroutine integrates the spline. - -INPUT PARAMETERS: - C - spline interpolant. - X - right bound of the integration interval [a, x], - here 'a' denotes min(x[]) -Result: - integral(S(t)dt,a,x) - - -- ALGLIB PROJECT -- - Copyright 23.06.2007 by Bochkanov Sergey -*************************************************************************/ -
double alglib::spline1dintegrate( - spline1dinterpolant c, - double x, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine performs linear transformation of the spline argument. - -INPUT PARAMETERS: - C - spline interpolant. - A, B- transformation coefficients: x = A*t + B -Result: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 30.06.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dlintransx( - spline1dinterpolant c, - double a, - double b, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine performs linear transformation of the spline. - -INPUT PARAMETERS: - C - spline interpolant. - A, B- transformation coefficients: S2(x) = A*S(x) + B -Result: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 30.06.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dlintransy( - spline1dinterpolant c, - double a, - double b, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine unpacks the spline into the coefficients table. - -INPUT PARAMETERS: - C - spline interpolant. - X - point - -OUTPUT PARAMETERS: - Tbl - coefficients table, unpacked format, array[0..N-2, 0..5]. - For I = 0...N-2: - Tbl[I,0] = X[i] - Tbl[I,1] = X[i+1] - Tbl[I,2] = C0 - Tbl[I,3] = C1 - Tbl[I,4] = C2 - Tbl[I,5] = C3 - On [x[i], x[i+1]] spline is equals to: - S(x) = C0 + C1*t + C2*t^2 + C3*t^3 - t = x-x[i] - -NOTE: - You can rebuild spline with Spline1DBuildHermite() function, which - accepts as inputs function values and derivatives at nodes, which are - easy to calculate when you have coefficients. - - -- ALGLIB PROJECT -- - Copyright 29.06.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline1dunpack( - spline1dinterpolant c, - ae_int_t& n, - real_2d_array& tbl, - const xparams _params = alglib::xdefault); - -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // We use cubic spline to do resampling, i.e. having
-    // values of f(x)=x^2 sampled at 5 equidistant nodes on [-1,+1]
-    // we calculate values/derivatives of cubic spline on 
-    // another grid (equidistant with 9 nodes on [-1,+1])
-    // WITHOUT CONSTRUCTION OF SPLINE OBJECT.
-    //
-    // There are efficient functions spline1dconvcubic(),
-    // spline1dconvdiffcubic() and spline1dconvdiff2cubic() 
-    // for such calculations.
-    //
-    // We use default boundary conditions ("parabolically terminated
-    // spline") because cubic spline built with such boundary conditions 
-    // will exactly reproduce any quadratic f(x).
-    //
-    // Actually, we could use natural conditions, but we feel that 
-    // spline which exactly reproduces f() will show us more 
-    // understandable results.
-    //
-    real_1d_array x_old = "[-1.0,-0.5,0.0,+0.5,+1.0]";
-    real_1d_array y_old = "[+1.0,0.25,0.0,0.25,+1.0]";
-    real_1d_array x_new = "[-1.00,-0.75,-0.50,-0.25,0.00,+0.25,+0.50,+0.75,+1.00]";
-    real_1d_array y_new;
-    real_1d_array d1_new;
-    real_1d_array d2_new;
-
-    //
-    // First, conversion without differentiation.
-    //
-    //
-    spline1dconvcubic(x_old, y_old, x_new, y_new);
-    printf("%s\n", y_new.tostring(3).c_str()); // EXPECTED: [1.0000, 0.5625, 0.2500, 0.0625, 0.0000, 0.0625, 0.2500, 0.5625, 1.0000]
-
-    //
-    // Then, conversion with differentiation (first derivatives only)
-    //
-    //
-    spline1dconvdiffcubic(x_old, y_old, x_new, y_new, d1_new);
-    printf("%s\n", y_new.tostring(3).c_str()); // EXPECTED: [1.0000, 0.5625, 0.2500, 0.0625, 0.0000, 0.0625, 0.2500, 0.5625, 1.0000]
-    printf("%s\n", d1_new.tostring(3).c_str()); // EXPECTED: [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0]
-
-    //
-    // Finally, conversion with first and second derivatives
-    //
-    //
-    spline1dconvdiff2cubic(x_old, y_old, x_new, y_new, d1_new, d2_new);
-    printf("%s\n", y_new.tostring(3).c_str()); // EXPECTED: [1.0000, 0.5625, 0.2500, 0.0625, 0.0000, 0.0625, 0.2500, 0.5625, 1.0000]
-    printf("%s\n", d1_new.tostring(3).c_str()); // EXPECTED: [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0]
-    printf("%s\n", d2_new.tostring(3).c_str()); // EXPECTED: [2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // We use cubic spline to interpolate f(x)=x^2 sampled 
-    // at 5 equidistant nodes on [-1,+1].
-    //
-    // First, we use default boundary conditions ("parabolically terminated
-    // spline") because cubic spline built with such boundary conditions 
-    // will exactly reproduce any quadratic f(x).
-    //
-    // Then we try to use natural boundary conditions
-    //     d2S(-1)/dx^2 = 0.0
-    //     d2S(+1)/dx^2 = 0.0
-    // and see that such spline interpolated f(x) with small error.
-    //
-    real_1d_array x = "[-1.0,-0.5,0.0,+0.5,+1.0]";
-    real_1d_array y = "[+1.0,0.25,0.0,0.25,+1.0]";
-    double t = 0.25;
-    double v;
-    spline1dinterpolant s;
-    ae_int_t natural_bound_type = 2;
-    //
-    // Test exact boundary conditions: build S(x), calculare S(0.25)
-    // (almost same as original function)
-    //
-    spline1dbuildcubic(x, y, s);
-    v = spline1dcalc(s, t);
-    printf("%.4f\n", double(v)); // EXPECTED: 0.0625
-
-    //
-    // Test natural boundary conditions: build S(x), calculare S(0.25)
-    // (small interpolation error)
-    //
-    spline1dbuildcubic(x, y, 5, natural_bound_type, 0.0, natural_bound_type, 0.0, s);
-    v = spline1dcalc(s, t);
-    printf("%.3f\n", double(v)); // EXPECTED: 0.0580
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // We use cubic spline to do grid differentiation, i.e. having
-    // values of f(x)=x^2 sampled at 5 equidistant nodes on [-1,+1]
-    // we calculate derivatives of cubic spline at nodes WITHOUT
-    // CONSTRUCTION OF SPLINE OBJECT.
-    //
-    // There are efficient functions spline1dgriddiffcubic() and
-    // spline1dgriddiff2cubic() for such calculations.
-    //
-    // We use default boundary conditions ("parabolically terminated
-    // spline") because cubic spline built with such boundary conditions 
-    // will exactly reproduce any quadratic f(x).
-    //
-    // Actually, we could use natural conditions, but we feel that 
-    // spline which exactly reproduces f() will show us more 
-    // understandable results.
-    //
-    real_1d_array x = "[-1.0,-0.5,0.0,+0.5,+1.0]";
-    real_1d_array y = "[+1.0,0.25,0.0,0.25,+1.0]";
-    real_1d_array d1;
-    real_1d_array d2;
-
-    //
-    // We calculate first derivatives: they must be equal to 2*x
-    //
-    spline1dgriddiffcubic(x, y, d1);
-    printf("%s\n", d1.tostring(3).c_str()); // EXPECTED: [-2.0, -1.0, 0.0, +1.0, +2.0]
-
-    //
-    // Now test griddiff2, which returns first AND second derivatives.
-    // First derivative is 2*x, second is equal to 2.0
-    //
-    spline1dgriddiff2cubic(x, y, d1, d2);
-    printf("%s\n", d1.tostring(3).c_str()); // EXPECTED: [-2.0, -1.0, 0.0, +1.0, +2.0]
-    printf("%s\n", d2.tostring(3).c_str()); // EXPECTED: [ 2.0,  2.0, 2.0,  2.0,  2.0]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // We use piecewise linear spline to interpolate f(x)=x^2 sampled 
-    // at 5 equidistant nodes on [-1,+1].
-    //
-    real_1d_array x = "[-1.0,-0.5,0.0,+0.5,+1.0]";
-    real_1d_array y = "[+1.0,0.25,0.0,0.25,+1.0]";
-    double t = 0.25;
-    double v;
-    spline1dinterpolant s;
-
-    // build spline
-    spline1dbuildlinear(x, y, s);
-
-    // calculate S(0.25) - it is quite different from 0.25^2=0.0625
-    v = spline1dcalc(s, t);
-    printf("%.4f\n", double(v)); // EXPECTED: 0.125
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // Spline built witn spline1dbuildcubic() can be non-monotone even when
-    // Y-values form monotone sequence. Say, for x=[0,1,2] and y=[0,1,1]
-    // cubic spline will monotonically grow until x=1.5 and then start
-    // decreasing.
-    //
-    // That's why ALGLIB provides special spline construction function
-    // which builds spline which preserves monotonicity of the original
-    // dataset.
-    //
-    // NOTE: in case original dataset is non-monotonic, ALGLIB splits it
-    // into monotone subsequences and builds piecewise monotonic spline.
-    //
-    real_1d_array x = "[0,1,2]";
-    real_1d_array y = "[0,1,1]";
-    spline1dinterpolant s;
-
-    // build spline
-    spline1dbuildmonotone(x, y, s);
-
-    // calculate S at x = [-0.5, 0.0, 0.5, 1.0, 1.5, 2.0]
-    // you may see that spline is really monotonic
-    double v;
-    v = spline1dcalc(s, -0.5);
-    printf("%.4f\n", double(v)); // EXPECTED: 0.0000
-    v = spline1dcalc(s, 0.0);
-    printf("%.4f\n", double(v)); // EXPECTED: 0.0000
-    v = spline1dcalc(s, +0.5);
-    printf("%.4f\n", double(v)); // EXPECTED: 0.5000
-    v = spline1dcalc(s, 1.0);
-    printf("%.4f\n", double(v)); // EXPECTED: 1.0000
-    v = spline1dcalc(s, 1.5);
-    printf("%.4f\n", double(v)); // EXPECTED: 1.0000
-    v = spline1dcalc(s, 2.0);
-    printf("%.4f\n", double(v)); // EXPECTED: 1.0000
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* -Nonlinear least squares solver used to fit 2D splines to data -*************************************************************************/ -
class spline2dbuilder -{ -}; - -
- -
-
/************************************************************************* -Spline 2D fitting report: - rmserror RMS error - avgerror average error - maxerror maximum error - r2 coefficient of determination, R-squared, 1-RSS/TSS -*************************************************************************/ -
class spline2dfitreport -{ - double rmserror; - double avgerror; - double maxerror; - double r2; -}; - -
- -
-
/************************************************************************* -2-dimensional spline inteprolant -*************************************************************************/ -
class spline2dinterpolant -{ -}; - -
- -
-
/************************************************************************* -This subroutine was deprecated in ALGLIB 3.6.0 - -We recommend you to switch to Spline2DBuildBicubicV(), which is more -flexible and accepts its arguments in more convenient order. - - -- ALGLIB PROJECT -- - Copyright 05.07.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dbuildbicubic( - real_1d_array x, - real_1d_array y, - real_2d_array f, - ae_int_t m, - ae_int_t n, - spline2dinterpolant& c, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine builds bicubic vector-valued spline. - -Input parameters: - X - spline abscissas, array[0..N-1] - Y - spline ordinates, array[0..M-1] - F - function values, array[0..M*N*D-1]: - * first D elements store D values at (X[0],Y[0]) - * next D elements store D values at (X[1],Y[0]) - * general form - D function values at (X[i],Y[j]) are stored - at F[D*(J*N+I)...D*(J*N+I)+D-1]. - M,N - grid size, M>=2, N>=2 - D - vector dimension, D>=1 - -Output parameters: - C - spline interpolant - - -- ALGLIB PROJECT -- - Copyright 16.04.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dbuildbicubicv( - real_1d_array x, - ae_int_t n, - real_1d_array y, - ae_int_t m, - real_1d_array f, - ae_int_t d, - spline2dinterpolant& c, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This subroutine was deprecated in ALGLIB 3.6.0 - -We recommend you to switch to Spline2DBuildBilinearV(), which is more -flexible and accepts its arguments in more convenient order. - - -- ALGLIB PROJECT -- - Copyright 05.07.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dbuildbilinear( - real_1d_array x, - real_1d_array y, - real_2d_array f, - ae_int_t m, - ae_int_t n, - spline2dinterpolant& c, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine builds bilinear vector-valued spline. - -Input parameters: - X - spline abscissas, array[0..N-1] - Y - spline ordinates, array[0..M-1] - F - function values, array[0..M*N*D-1]: - * first D elements store D values at (X[0],Y[0]) - * next D elements store D values at (X[1],Y[0]) - * general form - D function values at (X[i],Y[j]) are stored - at F[D*(J*N+I)...D*(J*N+I)+D-1]. - M,N - grid size, M>=2, N>=2 - D - vector dimension, D>=1 - -Output parameters: - C - spline interpolant - - -- ALGLIB PROJECT -- - Copyright 16.04.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dbuildbilinearv( - real_1d_array x, - ae_int_t n, - real_1d_array y, - ae_int_t m, - real_1d_array f, - ae_int_t d, - spline2dinterpolant& c, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This subroutine creates least squares solver used to fit 2D splines to -irregularly sampled (scattered) data. - -Solver object is used to perform spline fits as follows: -* solver object is created with spline2dbuildercreate() function -* dataset is added with spline2dbuildersetpoints() function -* fit area is chosen: - * spline2dbuildersetarea() - for user-defined area - * spline2dbuildersetareaauto() - for automatically chosen area -* number of grid nodes is chosen with spline2dbuildersetgrid() -* prior term is chosen with one of the following functions: - * spline2dbuildersetlinterm() to set linear prior - * spline2dbuildersetconstterm() to set constant prior - * spline2dbuildersetzeroterm() to set zero prior - * spline2dbuildersetuserterm() to set user-defined constant prior -* solver algorithm is chosen with either: - * spline2dbuildersetalgoblocklls() - BlockLLS algorithm, medium-scale problems - * spline2dbuildersetalgofastddm() - FastDDM algorithm, large-scale problems -* finally, fitting itself is performed with spline2dfit() function. - -Most of the steps above can be omitted, solver is configured with good -defaults. The minimum is to call: -* spline2dbuildercreate() to create solver object -* spline2dbuildersetpoints() to specify dataset -* spline2dbuildersetgrid() to tell how many nodes you need -* spline2dfit() to perform fit - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - D - positive number, number of Y-components: D=1 for simple scalar - fit, D>1 for vector-valued spline fitting. - -OUTPUT PARAMETERS: - S - solver object - - -- ALGLIB PROJECT -- - Copyright 29.01.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dbuildercreate( - ae_int_t d, - spline2dbuilder& state, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function allows you to choose least squares solver used to perform -fitting. This function sets solver algorithm to "BlockLLS", which performs -least squares fitting with fast sparse direct solver, with optional -nonsmoothness penalty being applied. - -Nonlinearity penalty has the following form: - - [ ] - P() ~ Lambda* integral[ (d2S/dx2)^2 + 2*(d2S/dxdy)^2 + (d2S/dy2)^2 ]dxdy - [ ] - -here integral is calculated over entire grid, and "~" means "proportional" -because integral is normalized after calcilation. Extremely large values -of Lambda result in linear fit being performed. - -NOTE: this algorithm is the most robust and controllable one, but it is - limited by 512x512 grids and (say) up to 1.000.000 points. However, - ALGLIB has one more spline solver: FastDDM algorithm, which is - intended for really large-scale problems (in 10M-100M range). FastDDM - algorithm also has better parallelism properties. - -More information on BlockLLS solver: -* memory requirements: ~[32*K^3+256*NPoints] bytes for KxK grid with - NPoints-sized dataset -* serial running time: O(K^4+NPoints) -* parallelism potential: limited. You may get some sublinear gain when - working with large grids (K's in 256..512 range) - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - spline 2D builder object - LambdaNS- non-negative value: - * positive value means that some smoothing is applied - * zero value means that no smoothing is applied, and - corresponding entries of design matrix are numerically - zero and dropped from consideration. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dbuildersetalgoblocklls( - spline2dbuilder state, - double lambdans, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function allows you to choose least squares solver used to perform -fitting. This function sets solver algorithm to "FastDDM", which performs -fast parallel fitting by splitting problem into smaller chunks and merging -results together. - -This solver is optimized for large-scale problems, starting from 256x256 -grids, and up to 10000x10000 grids. Of course, it will work for smaller -grids too. - -More detailed description of the algorithm is given below: -* algorithm generates hierarchy of nested grids, ranging from ~16x16 - (topmost "layer" of the model) to ~KX*KY one (final layer). Upper layers - model global behavior of the function, lower layers are used to model - fine details. Moving from layer to layer doubles grid density. -* fitting is started from topmost layer, subsequent layers are fitted - using residuals from previous ones. -* user may choose to skip generation of upper layers and generate only a - few bottom ones, which will result in much better performance and - parallelization efficiency, at the cost of algorithm inability to "patch" - large holes in the dataset. -* every layer is regularized using progressively increasing regularization - coefficient; thus, increasing LambdaV penalizes fine details first, - leaving lower frequencies almost intact for a while. -* after fitting is done, all layers are merged together into one bicubic - spline - -IMPORTANT: regularization coefficient used by this solver is different - from the one used by BlockLLS. Latter utilizes nonlinearity - penalty, which is global in nature (large regularization - results in global linear trend being extracted); this solver - uses another, localized form of penalty, which is suitable for - parallel processing. - -Notes on memory and performance: -* memory requirements: most memory is consumed during modeling of the - higher layers; ~[512*NPoints] bytes is required for a model with full - hierarchy of grids being generated. However, if you skip a few topmost - layers, you will get nearly constant (wrt. points count and grid size) - memory consumption. -* serial running time: O(K*K)+O(NPoints) for a KxK grid -* parallelism potential: good. You may get nearly linear speed-up when - performing fitting with just a few layers. Adding more layers results in - model becoming more global, which somewhat reduces efficiency of the - parallel code. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - spline 2D builder object - NLayers - number of layers in the model: - * NLayers>=1 means that up to chosen number of bottom - layers is fitted - * NLayers=0 means that maximum number of layers is chosen - (according to current grid size) - * NLayers<=-1 means that up to |NLayers| topmost layers is - skipped - Recommendations: - * good "default" value is 2 layers - * you may need more layers, if your dataset is very - irregular and you want to "patch" large holes. For a - grid step H (equal to AreaWidth/GridSize) you may expect - that last layer reproduces variations at distance H (and - can patch holes that wide); that higher layers operate - at distances 2*H, 4*H, 8*H and so on. - * good value for "bullletproof" mode is NLayers=0, which - results in complete hierarchy of layers being generated. - LambdaV - regularization coefficient, chosen in such a way that it - penalizes bottom layers (fine details) first. - LambdaV>=0, zero value means that no penalty is applied. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dbuildersetalgofastddm( - spline2dbuilder state, - ae_int_t nlayers, - double lambdav, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function allows you to choose least squares solver used to perform -fitting. This function sets solver algorithm to "NaiveLLS". - -IMPORTANT: NaiveLLS is NOT intended to be used in real life code! This - algorithm solves problem by generated dense (K^2)x(K^2+NPoints) - matrix and solves linear least squares problem with dense - solver. - - It is here just to test BlockLLS against reference solver - (and maybe for someone trying to compare well optimized solver - against straightforward approach to the LLS problem). - -More information on naive LLS solver: -* memory requirements: ~[8*K^4+256*NPoints] bytes for KxK grid. -* serial running time: O(K^6+NPoints) for KxK grid -* when compared with BlockLLS, NaiveLLS has ~K larger memory demand and - ~K^2 larger running time. - -INPUT PARAMETERS: - S - spline 2D builder object - LambdaNS- nonsmoothness penalty - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dbuildersetalgonaivells( - spline2dbuilder state, - double lambdans, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets area where 2D spline interpolant is built to -user-defined one: [XA,XB]*[YA,YB] - -INPUT PARAMETERS: - S - spline 2D builder object - XA,XB - spatial extent in the first (X) dimension, XA<XB - YA,YB - spatial extent in the second (Y) dimension, YA<YB - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dbuildersetarea( - spline2dbuilder state, - double xa, - double xb, - double ya, - double yb, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets area where 2D spline interpolant is built. "Auto" means -that area extent is determined automatically from dataset extent. - -INPUT PARAMETERS: - S - spline 2D builder object - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dbuildersetareaauto( - spline2dbuilder state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets constant prior term (model is a sum of bicubic spline -and global prior, which can be linear, constant, user-defined constant or -zero). - -Constant prior term is determined by least squares fitting. - -INPUT PARAMETERS: - S - spline builder - - -- ALGLIB -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dbuildersetconstterm( - spline2dbuilder state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets nodes count for 2D spline interpolant. Fitting is -performed on area defined with one of the "setarea" functions; this one -sets number of nodes placed upon the fitting area. - -INPUT PARAMETERS: - S - spline 2D builder object - KX - nodes count for the first (X) dimension; fitting interval - [XA,XB] is separated into KX-1 subintervals, with KX nodes - created at the boundaries. - KY - nodes count for the first (Y) dimension; fitting interval - [YA,YB] is separated into KY-1 subintervals, with KY nodes - created at the boundaries. - -NOTE: at least 4 nodes is created in each dimension, so KX and KY are - silently increased if needed. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dbuildersetgrid( - spline2dbuilder state, - ae_int_t kx, - ae_int_t ky, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets linear prior term (model is a sum of bicubic spline and -global prior, which can be linear, constant, user-defined constant or -zero). - -Linear prior term is determined by least squares fitting. - -INPUT PARAMETERS: - S - spline builder - - -- ALGLIB -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dbuildersetlinterm( - spline2dbuilder state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function adds dataset to the builder object. - -This function overrides results of the previous calls, i.e. multiple calls -of this function will result in only the last set being added. - -INPUT PARAMETERS: - S - spline 2D builder object - XY - points, array[N,2+D]. One row corresponds to one point - in the dataset. First 2 elements are coordinates, next - D elements are function values. Array may be larger than - specified, in this case only leading [N,NX+NY] elements - will be used. - N - number of points in the dataset - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dbuildersetpoints( - spline2dbuilder state, - real_2d_array xy, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets constant prior term (model is a sum of bicubic spline -and global prior, which can be linear, constant, user-defined constant or -zero). - -Constant prior term is determined by least squares fitting. - -INPUT PARAMETERS: - S - spline builder - V - value for user-defined prior - - -- ALGLIB -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dbuildersetuserterm( - spline2dbuilder state, - double v, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets zero prior term (model is a sum of bicubic spline and -global prior, which can be linear, constant, user-defined constant or -zero). - -INPUT PARAMETERS: - S - spline builder - - -- ALGLIB -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dbuildersetzeroterm( - spline2dbuilder state, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine calculates the value of the bilinear or bicubic spline at -the given point X. - -Input parameters: - C - 2D spline object. - Built by spline2dbuildbilinearv or spline2dbuildbicubicv. - X, Y- point - -Result: - S(x,y) - - -- ALGLIB PROJECT -- - Copyright 05.07.2007 by Bochkanov Sergey -*************************************************************************/ -
double alglib::spline2dcalc( - spline2dinterpolant c, - double x, - double y, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This subroutine calculates bilinear or bicubic vector-valued spline at the -given point (X,Y). - -INPUT PARAMETERS: - C - spline interpolant. - X, Y- point - -OUTPUT PARAMETERS: - F - array[D] which stores function values. F is out-parameter and - it is reallocated after call to this function. In case you - want to reuse previously allocated F, you may use - Spline2DCalcVBuf(), which reallocates F only when it is too - small. - - -- ALGLIB PROJECT -- - Copyright 16.04.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dcalcv( - spline2dinterpolant c, - double x, - double y, - real_1d_array& f, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This subroutine calculates bilinear or bicubic vector-valued spline at the -given point (X,Y). - -If you need just some specific component of vector-valued spline, you can -use spline2dcalcvi() function. - -INPUT PARAMETERS: - C - spline interpolant. - X, Y- point - F - output buffer, possibly preallocated array. In case array size - is large enough to store result, it is not reallocated. Array - which is too short will be reallocated - -OUTPUT PARAMETERS: - F - array[D] (or larger) which stores function values - - -- ALGLIB PROJECT -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dcalcvbuf( - spline2dinterpolant c, - double x, - double y, - real_1d_array& f, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine calculates specific component of vector-valued bilinear or -bicubic spline at the given point (X,Y). - -INPUT PARAMETERS: - C - spline interpolant. - X, Y- point - I - component index, in [0,D). An exception is generated for out - of range values. - -RESULT: - value of I-th component - - -- ALGLIB PROJECT -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -
double alglib::spline2dcalcvi( - spline2dinterpolant c, - double x, - double y, - ae_int_t i, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine makes the copy of the spline model. - -Input parameters: - C - spline interpolant - -Output parameters: - CC - spline copy - - -- ALGLIB PROJECT -- - Copyright 29.06.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dcopy( - spline2dinterpolant c, - spline2dinterpolant& cc, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This subroutine calculates the value of the bilinear or bicubic spline at -the given point X and its derivatives. - -Input parameters: - C - spline interpolant. - X, Y- point - -Output parameters: - F - S(x,y) - FX - dS(x,y)/dX - FY - dS(x,y)/dY - FXY - d2S(x,y)/dXdY - - -- ALGLIB PROJECT -- - Copyright 05.07.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2ddiff( - spline2dinterpolant c, - double x, - double y, - double& f, - double& fx, - double& fy, - double& fxy, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine calculates value of specific component of bilinear or -bicubic vector-valued spline and its derivatives. - -Input parameters: - C - spline interpolant. - X, Y- point - I - component index, in [0,D) - -Output parameters: - F - S(x,y) - FX - dS(x,y)/dX - FY - dS(x,y)/dY - FXY - d2S(x,y)/dXdY - - -- ALGLIB PROJECT -- - Copyright 05.07.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2ddiffvi( - spline2dinterpolant c, - double x, - double y, - ae_int_t i, - double& f, - double& fx, - double& fy, - double& fxy, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function fits bicubic spline to current dataset, using current area/ -grid and current LLS solver. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - State - spline 2D builder object - -OUTPUT PARAMETERS: - S - 2D spline, fit result - Rep - fitting report, which provides some additional info about - errors, R2 coefficient and so on. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dfit( - spline2dbuilder state, - spline2dinterpolant& s, - spline2dfitreport& rep, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This subroutine performs linear transformation of the spline. - -Input parameters: - C - spline interpolant. - A, B- transformation coefficients: S2(x,y) = A*S(x,y) + B - -Output parameters: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 30.06.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dlintransf( - spline2dinterpolant c, - double a, - double b, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This subroutine performs linear transformation of the spline argument. - -Input parameters: - C - spline interpolant - AX, BX - transformation coefficients: x = A*t + B - AY, BY - transformation coefficients: y = A*u + B -Result: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 30.06.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dlintransxy( - spline2dinterpolant c, - double ax, - double bx, - double ay, - double by, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -Bicubic spline resampling - -Input parameters: - A - function values at the old grid, - array[0..OldHeight-1, 0..OldWidth-1] - OldHeight - old grid height, OldHeight>1 - OldWidth - old grid width, OldWidth>1 - NewHeight - new grid height, NewHeight>1 - NewWidth - new grid width, NewWidth>1 - -Output parameters: - B - function values at the new grid, - array[0..NewHeight-1, 0..NewWidth-1] - - -- ALGLIB routine -- - 15 May, 2007 - Copyright by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dresamplebicubic( - real_2d_array a, - ae_int_t oldheight, - ae_int_t oldwidth, - real_2d_array& b, - ae_int_t newheight, - ae_int_t newwidth, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Bilinear spline resampling - -Input parameters: - A - function values at the old grid, - array[0..OldHeight-1, 0..OldWidth-1] - OldHeight - old grid height, OldHeight>1 - OldWidth - old grid width, OldWidth>1 - NewHeight - new grid height, NewHeight>1 - NewWidth - new grid width, NewWidth>1 - -Output parameters: - B - function values at the new grid, - array[0..NewHeight-1, 0..NewWidth-1] - - -- ALGLIB routine -- - 09.07.2007 - Copyright by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dresamplebilinear( - real_2d_array a, - ae_int_t oldheight, - ae_int_t oldwidth, - real_2d_array& b, - ae_int_t newheight, - ae_int_t newwidth, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -
void spline2dserialize(spline2dinterpolant &obj, std::string &s_out); -void spline2dserialize(spline2dinterpolant &obj, std::ostream &s_out); -
- -
-
/************************************************************************* -This subroutine was deprecated in ALGLIB 3.6.0 - -We recommend you to switch to Spline2DUnpackV(), which is more flexible -and accepts its arguments in more convenient order. - - -- ALGLIB PROJECT -- - Copyright 29.06.2007 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dunpack( - spline2dinterpolant c, - ae_int_t& m, - ae_int_t& n, - real_2d_array& tbl, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine unpacks two-dimensional spline into the coefficients table - -Input parameters: - C - spline interpolant. - -Result: - M, N- grid size (x-axis and y-axis) - D - number of components - Tbl - coefficients table, unpacked format, - D - components: [0..(N-1)*(M-1)*D-1, 0..19]. - For T=0..D-1 (component index), I = 0...N-2 (x index), - J=0..M-2 (y index): - K := T + I*D + J*D*(N-1) - - K-th row stores decomposition for T-th component of the - vector-valued function - - Tbl[K,0] = X[i] - Tbl[K,1] = X[i+1] - Tbl[K,2] = Y[j] - Tbl[K,3] = Y[j+1] - Tbl[K,4] = C00 - Tbl[K,5] = C01 - Tbl[K,6] = C02 - Tbl[K,7] = C03 - Tbl[K,8] = C10 - Tbl[K,9] = C11 - ... - Tbl[K,19] = C33 - On each grid square spline is equals to: - S(x) = SUM(c[i,j]*(t^i)*(u^j), i=0..3, j=0..3) - t = x-x[j] - u = y-y[i] - - -- ALGLIB PROJECT -- - Copyright 16.04.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline2dunpackv( - spline2dinterpolant c, - ae_int_t& m, - ae_int_t& n, - ae_int_t& d, - real_2d_array& tbl, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -
void spline2dunserialize(const std::string &s_in, spline2dinterpolant &obj); -void spline2dunserialize(const std::istream &s_in, spline2dinterpolant &obj); -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // We use bilinear spline to interpolate f(x,y)=x^2+2*y^2 sampled 
-    // at (x,y) from [0.0, 0.5, 1.0] X [0.0, 1.0].
-    //
-    real_1d_array x = "[0.0, 0.5, 1.0]";
-    real_1d_array y = "[0.0, 1.0]";
-    real_1d_array f = "[0.00,0.25,1.00,2.00,2.25,3.00]";
-    double vx = 0.25;
-    double vy = 0.50;
-    double v;
-    double dx;
-    double dy;
-    double dxy;
-    spline2dinterpolant s;
-
-    // build spline
-    spline2dbuildbicubicv(x, 3, y, 2, f, 1, s);
-
-    // calculate S(0.25,0.50)
-    v = spline2dcalc(s, vx, vy);
-    printf("%.4f\n", double(v)); // EXPECTED: 1.0625
-
-    // calculate derivatives
-    spline2ddiff(s, vx, vy, v, dx, dy, dxy);
-    printf("%.4f\n", double(v)); // EXPECTED: 1.0625
-    printf("%.4f\n", double(dx)); // EXPECTED: 0.5000
-    printf("%.4f\n", double(dy)); // EXPECTED: 2.0000
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // We use bilinear spline to interpolate f(x,y)=x^2+2*y^2 sampled 
-    // at (x,y) from [0.0, 0.5, 1.0] X [0.0, 1.0].
-    //
-    real_1d_array x = "[0.0, 0.5, 1.0]";
-    real_1d_array y = "[0.0, 1.0]";
-    real_1d_array f = "[0.00,0.25,1.00,2.00,2.25,3.00]";
-    double vx = 0.25;
-    double vy = 0.50;
-    double v;
-    spline2dinterpolant s;
-
-    // build spline
-    spline2dbuildbilinearv(x, 3, y, 2, f, 1, s);
-
-    // calculate S(0.25,0.50)
-    v = spline2dcalc(s, vx, vy);
-    printf("%.4f\n", double(v)); // EXPECTED: 1.1250
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // We build bilinear spline for f(x,y)=x+2*y for (x,y) in [0,1].
-    // Then we apply several transformations to this spline.
-    //
-    real_1d_array x = "[0.0, 1.0]";
-    real_1d_array y = "[0.0, 1.0]";
-    real_1d_array f = "[0.00,1.00,2.00,3.00]";
-    spline2dinterpolant s;
-    spline2dinterpolant snew;
-    double v;
-    spline2dbuildbilinearv(x, 2, y, 2, f, 1, s);
-
-    // copy spline, apply transformation x:=2*xnew, y:=4*ynew
-    // evaluate at (xnew,ynew) = (0.25,0.25) - should be same as (x,y)=(0.5,1.0)
-    spline2dcopy(s, snew);
-    spline2dlintransxy(snew, 2.0, 0.0, 4.0, 0.0);
-    v = spline2dcalc(snew, 0.25, 0.25);
-    printf("%.4f\n", double(v)); // EXPECTED: 2.500
-
-    // copy spline, apply transformation SNew:=2*S+3
-    spline2dcopy(s, snew);
-    spline2dlintransf(snew, 2.0, 3.0);
-    v = spline2dcalc(snew, 0.5, 1.0);
-    printf("%.4f\n", double(v)); // EXPECTED: 8.000
-
-    //
-    // Same example, but for vector spline (f0,f1) = {x+2*y, 2*x+y}
-    //
-    real_1d_array f2 = "[0.00,0.00, 1.00,2.00, 2.00,1.00, 3.00,3.00]";
-    real_1d_array vr;
-    spline2dbuildbilinearv(x, 2, y, 2, f2, 2, s);
-
-    // copy spline, apply transformation x:=2*xnew, y:=4*ynew
-    spline2dcopy(s, snew);
-    spline2dlintransxy(snew, 2.0, 0.0, 4.0, 0.0);
-    spline2dcalcv(snew, 0.25, 0.25, vr);
-    printf("%s\n", vr.tostring(4).c_str()); // EXPECTED: [2.500,2.000]
-
-    // copy spline, apply transformation SNew:=2*S+3
-    spline2dcopy(s, snew);
-    spline2dlintransf(snew, 2.0, 3.0);
-    spline2dcalcv(snew, 0.5, 1.0, vr);
-    printf("%s\n", vr.tostring(4).c_str()); // EXPECTED: [8.000,7.000]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // We use bicubic spline to reproduce f(x,y)=1/(1+x^2+2*y^2) sampled
-    // at irregular points (x,y) from [-1,+1]*[-1,+1]
-    //
-    // We have 5 such points, located approximately at corners of the area
-    // and its center -  but not exactly at the grid. Thus, we have to FIT
-    // the spline, i.e. to solve least squares problem
-    //
-    real_2d_array xy = "[[-0.987,-0.902,0.359],[0.948,-0.992,0.347],[-1.000,1.000,0.333],[1.000,0.973,0.339],[0.017,0.180,0.968]]";
-
-    //
-    // First step is to create spline2dbuilder object and set its properties:
-    // * d=1 means that we create vector-valued spline with 1 component
-    // * we specify dataset xy
-    // * we rely on automatic selection of interpolation area
-    // * we tell builder that we want to use 5x5 grid for an underlying spline
-    // * we choose least squares solver named BlockLLS and configure it by
-    //   telling that we want to apply zero nonlinearity penalty.
-    //
-    // NOTE: you can specify non-zero lambdav if you want to make your spline
-    //       more "rigid", i.e. to penalize nonlinearity.
-    //
-    // NOTE: ALGLIB has two solvers which fit bicubic splines to irregular data,
-    //       one of them is BlockLLS and another one is FastDDM. Former is
-    //       intended for moderately sized grids (up to 512x512 nodes, although
-    //       it may take up to few minutes); it is the most easy to use and
-    //       control spline fitting function in the library. Latter, FastDDM,
-    //       is intended for efficient solution of large-scale problems
-    //       (up to 100.000.000 nodes). Both solvers can be parallelized, but
-    //       FastDDM is much more efficient. See comments for more information.
-    //
-    spline2dbuilder builder;
-    ae_int_t d = 1;
-    double lambdav = 0.000;
-    spline2dbuildercreate(d, builder);
-    spline2dbuildersetpoints(builder, xy, 5);
-    spline2dbuildersetgrid(builder, 5, 5);
-    spline2dbuildersetalgoblocklls(builder, lambdav);
-
-    //
-    // Now we are ready to fit and evaluate our results
-    //
-    spline2dinterpolant s;
-    spline2dfitreport rep;
-    spline2dfit(builder, s, rep);
-
-    // evaluate results - function value at the grid is reproduced exactly
-    double v;
-    v = spline2dcalc(s, -1, 1);
-    printf("%.2f\n", double(v)); // EXPECTED: 0.333000
-
-    // check maximum error - it must be nearly zero
-    printf("%.2f\n", double(rep.maxerror)); // EXPECTED: 0.000
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // We build bilinear spline for f(x,y)=x+2*y+3*xy for (x,y) in [0,1].
-    // Then we demonstrate how to unpack it.
-    //
-    real_1d_array x = "[0.0, 1.0]";
-    real_1d_array y = "[0.0, 1.0]";
-    real_1d_array f = "[0.00,1.00,2.00,6.00]";
-    real_2d_array c;
-    ae_int_t m;
-    ae_int_t n;
-    ae_int_t d;
-    spline2dinterpolant s;
-
-    // build spline
-    spline2dbuildbilinearv(x, 2, y, 2, f, 1, s);
-
-    // unpack and test
-    spline2dunpackv(s, m, n, d, c);
-    printf("%s\n", c.tostring(4).c_str()); // EXPECTED: [[0, 1, 0, 1, 0,2,0,0, 1,3,0,0, 0,0,0,0, 0,0,0,0 ]]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // We build bilinear vector-valued spline (f0,f1) = {x+2*y, 2*x+y}
-    // Spline is built using function values at 2x2 grid: (x,y)=[0,1]*[0,1]
-    // Then we perform evaluation at (x,y)=(0.1,0.3)
-    //
-    real_1d_array x = "[0.0, 1.0]";
-    real_1d_array y = "[0.0, 1.0]";
-    real_1d_array f = "[0.00,0.00, 1.00,2.00, 2.00,1.00, 3.00,3.00]";
-    spline2dinterpolant s;
-    real_1d_array vr;
-    spline2dbuildbilinearv(x, 2, y, 2, f, 2, s);
-    spline2dcalcv(s, 0.1, 0.3, vr);
-    printf("%s\n", vr.tostring(4).c_str()); // EXPECTED: [0.700,0.500]
-    return 0;
-}
-
-
-
-
- -spline3dinterpolant
- -spline3dbuildtrilinearv
-spline3dcalc
-spline3dcalcv
-spline3dcalcvbuf
-spline3dlintransf
-spline3dlintransxyz
-spline3dresampletrilinear
-spline3dunpackv
- - - - -
spline3d_trilinear Trilinear spline interpolation
spline3d_vector Vector-valued trilinear spline interpolation
- -
-
/************************************************************************* -3-dimensional spline inteprolant -*************************************************************************/ -
class spline3dinterpolant -{ -}; - -
- -
-
/************************************************************************* -This subroutine builds trilinear vector-valued spline. - -INPUT PARAMETERS: - X - spline abscissas, array[0..N-1] - Y - spline ordinates, array[0..M-1] - Z - spline applicates, array[0..L-1] - F - function values, array[0..M*N*L*D-1]: - * first D elements store D values at (X[0],Y[0],Z[0]) - * next D elements store D values at (X[1],Y[0],Z[0]) - * next D elements store D values at (X[2],Y[0],Z[0]) - * ... - * next D elements store D values at (X[0],Y[1],Z[0]) - * next D elements store D values at (X[1],Y[1],Z[0]) - * next D elements store D values at (X[2],Y[1],Z[0]) - * ... - * next D elements store D values at (X[0],Y[0],Z[1]) - * next D elements store D values at (X[1],Y[0],Z[1]) - * next D elements store D values at (X[2],Y[0],Z[1]) - * ... - * general form - D function values at (X[i],Y[j]) are stored - at F[D*(N*(M*K+J)+I)...D*(N*(M*K+J)+I)+D-1]. - M,N, - L - grid size, M>=2, N>=2, L>=2 - D - vector dimension, D>=1 - -OUTPUT PARAMETERS: - C - spline interpolant - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline3dbuildtrilinearv( - real_1d_array x, - ae_int_t n, - real_1d_array y, - ae_int_t m, - real_1d_array z, - ae_int_t l, - real_1d_array f, - ae_int_t d, - spline3dinterpolant& c, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This subroutine calculates the value of the trilinear or tricubic spline at -the given point (X,Y,Z). - -INPUT PARAMETERS: - C - coefficients table. - Built by BuildBilinearSpline or BuildBicubicSpline. - X, Y, - Z - point - -Result: - S(x,y,z) - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -
double alglib::spline3dcalc( - spline3dinterpolant c, - double x, - double y, - double z, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This subroutine calculates trilinear or tricubic vector-valued spline at the -given point (X,Y,Z). - -INPUT PARAMETERS: - C - spline interpolant. - X, Y, - Z - point - -OUTPUT PARAMETERS: - F - array[D] which stores function values. F is out-parameter and - it is reallocated after call to this function. In case you - want to reuse previously allocated F, you may use - Spline2DCalcVBuf(), which reallocates F only when it is too - small. - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline3dcalcv( - spline3dinterpolant c, - double x, - double y, - double z, - real_1d_array& f, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This subroutine calculates bilinear or bicubic vector-valued spline at the -given point (X,Y,Z). - -INPUT PARAMETERS: - C - spline interpolant. - X, Y, - Z - point - F - output buffer, possibly preallocated array. In case array size - is large enough to store result, it is not reallocated. Array - which is too short will be reallocated - -OUTPUT PARAMETERS: - F - array[D] (or larger) which stores function values - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline3dcalcvbuf( - spline3dinterpolant c, - double x, - double y, - double z, - real_1d_array& f, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine performs linear transformation of the spline. - -INPUT PARAMETERS: - C - spline interpolant. - A, B- transformation coefficients: S2(x,y) = A*S(x,y,z) + B - -OUTPUT PARAMETERS: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline3dlintransf( - spline3dinterpolant c, - double a, - double b, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine performs linear transformation of the spline argument. - -INPUT PARAMETERS: - C - spline interpolant - AX, BX - transformation coefficients: x = A*u + B - AY, BY - transformation coefficients: y = A*v + B - AZ, BZ - transformation coefficients: z = A*w + B - -OUTPUT PARAMETERS: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline3dlintransxyz( - spline3dinterpolant c, - double ax, - double bx, - double ay, - double by, - double az, - double bz, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Trilinear spline resampling - -INPUT PARAMETERS: - A - array[0..OldXCount*OldYCount*OldZCount-1], function - values at the old grid, : - A[0] x=0,y=0,z=0 - A[1] x=1,y=0,z=0 - A[..] ... - A[..] x=oldxcount-1,y=0,z=0 - A[..] x=0,y=1,z=0 - A[..] ... - ... - OldZCount - old Z-count, OldZCount>1 - OldYCount - old Y-count, OldYCount>1 - OldXCount - old X-count, OldXCount>1 - NewZCount - new Z-count, NewZCount>1 - NewYCount - new Y-count, NewYCount>1 - NewXCount - new X-count, NewXCount>1 - -OUTPUT PARAMETERS: - B - array[0..NewXCount*NewYCount*NewZCount-1], function - values at the new grid: - B[0] x=0,y=0,z=0 - B[1] x=1,y=0,z=0 - B[..] ... - B[..] x=newxcount-1,y=0,z=0 - B[..] x=0,y=1,z=0 - B[..] ... - ... - - -- ALGLIB routine -- - 26.04.2012 - Copyright by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline3dresampletrilinear( - real_1d_array a, - ae_int_t oldzcount, - ae_int_t oldycount, - ae_int_t oldxcount, - ae_int_t newzcount, - ae_int_t newycount, - ae_int_t newxcount, - real_1d_array& b, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This subroutine unpacks tri-dimensional spline into the coefficients table - -INPUT PARAMETERS: - C - spline interpolant. - -Result: - N - grid size (X) - M - grid size (Y) - L - grid size (Z) - D - number of components - SType- spline type. Currently, only one spline type is supported: - trilinear spline, as indicated by SType=1. - Tbl - spline coefficients: [0..(N-1)*(M-1)*(L-1)*D-1, 0..13]. - For T=0..D-1 (component index), I = 0...N-2 (x index), - J=0..M-2 (y index), K=0..L-2 (z index): - Q := T + I*D + J*D*(N-1) + K*D*(N-1)*(M-1), - - Q-th row stores decomposition for T-th component of the - vector-valued function - - Tbl[Q,0] = X[i] - Tbl[Q,1] = X[i+1] - Tbl[Q,2] = Y[j] - Tbl[Q,3] = Y[j+1] - Tbl[Q,4] = Z[k] - Tbl[Q,5] = Z[k+1] - - Tbl[Q,6] = C000 - Tbl[Q,7] = C100 - Tbl[Q,8] = C010 - Tbl[Q,9] = C110 - Tbl[Q,10]= C001 - Tbl[Q,11]= C101 - Tbl[Q,12]= C011 - Tbl[Q,13]= C111 - On each grid square spline is equals to: - S(x) = SUM(c[i,j,k]*(x^i)*(y^j)*(z^k), i=0..1, j=0..1, k=0..1) - t = x-x[j] - u = y-y[i] - v = z-z[k] - - NOTE: format of Tbl is given for SType=1. Future versions of - ALGLIB can use different formats for different values of - SType. - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -
void alglib::spline3dunpackv( - spline3dinterpolant c, - ae_int_t& n, - ae_int_t& m, - ae_int_t& l, - ae_int_t& d, - ae_int_t& stype, - real_2d_array& tbl, - const xparams _params = alglib::xdefault); - -
- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // We use trilinear spline to interpolate f(x,y,z)=x+xy+z sampled 
-    // at (x,y,z) from [0.0, 1.0] X [0.0, 1.0] X [0.0, 1.0].
-    //
-    // We store x, y and z-values at local arrays with same names.
-    // Function values are stored in the array F as follows:
-    //     f[0]     (x,y,z) = (0,0,0)
-    //     f[1]     (x,y,z) = (1,0,0)
-    //     f[2]     (x,y,z) = (0,1,0)
-    //     f[3]     (x,y,z) = (1,1,0)
-    //     f[4]     (x,y,z) = (0,0,1)
-    //     f[5]     (x,y,z) = (1,0,1)
-    //     f[6]     (x,y,z) = (0,1,1)
-    //     f[7]     (x,y,z) = (1,1,1)
-    //
-    real_1d_array x = "[0.0, 1.0]";
-    real_1d_array y = "[0.0, 1.0]";
-    real_1d_array z = "[0.0, 1.0]";
-    real_1d_array f = "[0,1,0,2,1,2,1,3]";
-    double vx = 0.50;
-    double vy = 0.50;
-    double vz = 0.50;
-    double v;
-    spline3dinterpolant s;
-
-    // build spline
-    spline3dbuildtrilinearv(x, 2, y, 2, z, 2, f, 1, s);
-
-    // calculate S(0.5,0.5,0.5)
-    v = spline3dcalc(s, vx, vy, vz);
-    printf("%.4f\n", double(v)); // EXPECTED: 1.2500
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "interpolation.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // We use trilinear vector-valued spline to interpolate {f0,f1}={x+xy+z,x+xy+yz+z}
-    // sampled at (x,y,z) from [0.0, 1.0] X [0.0, 1.0] X [0.0, 1.0].
-    //
-    // We store x, y and z-values at local arrays with same names.
-    // Function values are stored in the array F as follows:
-    //     f[0]     f0, (x,y,z) = (0,0,0)
-    //     f[1]     f1, (x,y,z) = (0,0,0)
-    //     f[2]     f0, (x,y,z) = (1,0,0)
-    //     f[3]     f1, (x,y,z) = (1,0,0)
-    //     f[4]     f0, (x,y,z) = (0,1,0)
-    //     f[5]     f1, (x,y,z) = (0,1,0)
-    //     f[6]     f0, (x,y,z) = (1,1,0)
-    //     f[7]     f1, (x,y,z) = (1,1,0)
-    //     f[8]     f0, (x,y,z) = (0,0,1)
-    //     f[9]     f1, (x,y,z) = (0,0,1)
-    //     f[10]    f0, (x,y,z) = (1,0,1)
-    //     f[11]    f1, (x,y,z) = (1,0,1)
-    //     f[12]    f0, (x,y,z) = (0,1,1)
-    //     f[13]    f1, (x,y,z) = (0,1,1)
-    //     f[14]    f0, (x,y,z) = (1,1,1)
-    //     f[15]    f1, (x,y,z) = (1,1,1)
-    //
-    real_1d_array x = "[0.0, 1.0]";
-    real_1d_array y = "[0.0, 1.0]";
-    real_1d_array z = "[0.0, 1.0]";
-    real_1d_array f = "[0,0, 1,1, 0,0, 2,2, 1,1, 2,2, 1,2, 3,4]";
-    double vx = 0.50;
-    double vy = 0.50;
-    double vz = 0.50;
-    spline3dinterpolant s;
-
-    // build spline
-    spline3dbuildtrilinearv(x, 2, y, 2, z, 2, f, 2, s);
-
-    // calculate S(0.5,0.5,0.5) - we have vector of values instead of single value
-    real_1d_array v;
-    spline3dcalcv(s, vx, vy, vz, v);
-    printf("%s\n", v.tostring(4).c_str()); // EXPECTED: [1.2500,1.5000]
-    return 0;
-}
-
-
-
- - -
-
/************************************************************************* -This object stores state of the SSA model. - -You should use ALGLIB functions to work with this object. -*************************************************************************/ -
class ssamodel -{ -}; - -
- -
-
/************************************************************************* -This function adds data sequence to SSA model. Only single-dimensional -sequences are supported. - -What is a sequences? Following definitions/requirements apply: -* a sequence is an array of values measured in subsequent, equally - separated time moments (ticks). -* you may have many sequences in your dataset; say, one sequence may - correspond to one trading session. -* sequence length should be larger than current window length (shorter - sequences will be ignored during analysis). -* analysis is performed within a sequence; different sequences are NOT - stacked together to produce one large contiguous stream of data. -* analysis is performed for all sequences at once, i.e. same set of basis - vectors is computed for all sequences - -INCREMENTAL ANALYSIS - -This function is non intended for incremental updates of previously found -SSA basis. Calling it invalidates all previous analysis results (basis is -reset and will be recalculated from zero during next analysis). - -If you want to perform incremental/real-time SSA, consider using -following functions: -* ssaappendpointandupdate() for appending one point -* ssaappendsequenceandupdate() for appending new sequence - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - X - array[N], data, can be larger (additional values - are ignored) - N - data length, can be automatically determined from - the array length. N>=0. - -OUTPUT PARAMETERS: - S - SSA model, updated - -NOTE: you can clear dataset with ssacleardata() - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssaaddsequence( - ssamodel s, - real_1d_array x, - const xparams _params = alglib::xdefault); -void alglib::ssaaddsequence( - ssamodel s, - real_1d_array x, - ae_int_t n, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -This function: -* builds SSA basis using internally stored (entire) dataset -* returns reconstruction for the last NTicks of the last sequence - -If you want to analyze some other sequence, use ssaanalyzesequence(). - -Reconstruction phase involves generation of NTicks-WindowWidth sliding -windows, their decomposition using empirical orthogonal functions found by -SSA, followed by averaging of each data point across several overlapping -windows. Thus, every point in the output trend is reconstructed using up -to WindowWidth overlapping windows (WindowWidth windows exactly in the -inner points, just one window at the extremal points). - -IMPORTANT: due to averaging this function returns different results for - different values of NTicks. It is expected and not a bug. - - For example: - * Trend[NTicks-1] is always same because it is not averaged in - any case (same applies to Trend[0]). - * Trend[NTicks-2] has different values for NTicks=WindowWidth - and NTicks=WindowWidth+1 because former case means that no - averaging is performed, and latter case means that averaging - using two sliding windows is performed. Larger values of - NTicks produce same results as NTicks=WindowWidth+1. - * ...and so on... - -PERFORMANCE: this function has O((NTicks-WindowWidth)*WindowWidth*NBasis) - running time. If you work in time-constrained setting and - have to analyze just a few last ticks, choosing NTicks equal - to WindowWidth+SmoothingLen, with SmoothingLen=1...WindowWidth - will result in good compromise between noise cancellation and - analysis speed. - -INPUT PARAMETERS: - S - SSA model - NTicks - number of ticks to analyze, Nticks>=1. - * special case of NTicks<=WindowWidth is handled - by analyzing last window and returning NTicks - last ticks. - * special case NTicks>LastSequenceLen is handled - by prepending result with NTicks-LastSequenceLen - zeros. - -OUTPUT PARAMETERS: - Trend - array[NTicks], reconstructed trend line - Noise - array[NTicks], the rest of the signal; - it holds that ActualData = Trend+Noise. - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - -In any case, only basis is reused. Reconstruction is performed from -scratch every time you call this function. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* last sequence is shorter than the window length (analysis can be done, - but we can not perform reconstruction on the last sequence) - -Calling this function in degenerate cases returns following result: -* in any case, NTicks ticks is returned -* trend is assumed to be zero -* noise is initialized by the last sequence; if last sequence is shorter - than the window size, it is moved to the end of the array, and the - beginning of the noise array is filled by zeros - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssaanalyzelast( - ssamodel s, - ae_int_t nticks, - real_1d_array& trend, - real_1d_array& noise, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function executes SSA on internally stored dataset and returns -analysis for the last window of the last sequence. Such analysis is -an lightweight alternative for full scale reconstruction (see below). - -Typical use case for this function is real-time setting, when you are -interested in quick-and-dirty (very quick and very dirty) processing of -just a few last ticks of the trend. - -IMPORTANT: full scale SSA involves analysis of the ENTIRE dataset, - with reconstruction being done for all positions of sliding - window with subsequent hankelization (diagonal averaging) of - the resulting matrix. - - Such analysis requires O((DataLen-Window)*Window*NBasis) FLOPs - and can be quite costly. However, it has nice noise-canceling - effects due to averaging. - - This function performs REDUCED analysis of the last window. It - is much faster - just O(Window*NBasis), but its results are - DIFFERENT from that of ssaanalyzelast(). In particular, first - few points of the trend are much more prone to noise. - -INPUT PARAMETERS: - S - SSA model - -OUTPUT PARAMETERS: - Trend - array[WindowSize], reconstructed trend line - Noise - array[WindowSize], the rest of the signal; - it holds that ActualData = Trend+Noise. - NTicks - current WindowSize - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - -In any case, only basis is reused. Reconstruction is performed from -scratch every time you call this function. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* last sequence is shorter than the window length (analysis can be done, - but we can not perform reconstruction on the last sequence) - -Calling this function in degenerate cases returns following result: -* in any case, WindowWidth ticks is returned -* trend is assumed to be zero -* noise is initialized by the last sequence; if last sequence is shorter - than the window size, it is moved to the end of the array, and the - beginning of the noise array is filled by zeros - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssaanalyzelastwindow( - ssamodel s, - real_1d_array& trend, - real_1d_array& noise, - ae_int_t& nticks, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function: -* builds SSA basis using internally stored (entire) dataset -* returns reconstruction for the sequence being passed to this function - -If you want to analyze last sequence stored in the model, use -ssaanalyzelast(). - -Reconstruction phase involves generation of NTicks-WindowWidth sliding -windows, their decomposition using empirical orthogonal functions found by -SSA, followed by averaging of each data point across several overlapping -windows. Thus, every point in the output trend is reconstructed using up -to WindowWidth overlapping windows (WindowWidth windows exactly in the -inner points, just one window at the extremal points). - -PERFORMANCE: this function has O((NTicks-WindowWidth)*WindowWidth*NBasis) - running time. If you work in time-constrained setting and - have to analyze just a few last ticks, choosing NTicks equal - to WindowWidth+SmoothingLen, with SmoothingLen=1...WindowWidth - will result in good compromise between noise cancellation and - analysis speed. - -INPUT PARAMETERS: - S - SSA model - Data - array[NTicks], can be larger (only NTicks leading - elements will be used) - NTicks - number of ticks to analyze, Nticks>=1. - * special case of NTicks<WindowWidth is handled - by returning zeros as trend, and signal as noise - -OUTPUT PARAMETERS: - Trend - array[NTicks], reconstructed trend line - Noise - array[NTicks], the rest of the signal; - it holds that ActualData = Trend+Noise. - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - -In any case, only basis is reused. Reconstruction is performed from -scratch every time you call this function. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* sequence being passed is shorter than the window length - -Calling this function in degenerate cases returns following result: -* in any case, NTicks ticks is returned -* trend is assumed to be zero -* noise is initialized by the sequence. - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssaanalyzesequence( - ssamodel s, - real_1d_array data, - real_1d_array& trend, - real_1d_array& noise, - const xparams _params = alglib::xdefault); -void alglib::ssaanalyzesequence( - ssamodel s, - real_1d_array data, - ae_int_t nticks, - real_1d_array& trend, - real_1d_array& noise, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -This function appends single point to last data sequence stored in the SSA -model and tries to update model in the incremental manner (if possible -with current algorithm). - -If you want to add more than one point at once: -* if you want to add M points to the same sequence, perform M-1 calls with - UpdateIts parameter set to 0.0, and last call with non-zero UpdateIts. -* if you want to add new sequence, use ssaappendsequenceandupdate() - -Running time of this function does NOT depend on dataset size, only on -window width and number of singular vectors. Depending on algorithm being -used, incremental update has complexity: -* for top-K real time - O(UpdateIts*K*Width^2), with fractional UpdateIts -* for top-K direct - O(Width^3) for any non-zero UpdateIts -* for precomputed basis - O(1), no update is performed - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - X - new point - UpdateIts - >=0, floating point (!) value, desired update - frequency: - * zero value means that point is stored, but no - update is performed - * integer part of the value means that specified - number of iterations is always performed - * fractional part of the value means that one - iteration is performed with this probability. - - Recommended value: 0<UpdateIts<=1. Values larger - than 1 are VERY seldom needed. If your dataset - changes slowly, you can set it to 0.1 and skip - 90% of updates. - - In any case, no information is lost even with zero - value of UpdateIts! It will be incorporated into - model, sooner or later. - -OUTPUT PARAMETERS: - S - SSA model, updated - -NOTE: this function uses internal RNG to handle fractional values of - UpdateIts. By default it is initialized with fixed seed during - initial calculation of basis. Thus subsequent calls to this function - will result in the same sequence of pseudorandom decisions. - - However, if you have several SSA models which are calculated - simultaneously, and if you want to reduce computational bottlenecks - by performing random updates at random moments, then fixed seed is - not an option - all updates will fire at same moments. - - You may change it with ssasetseed() function. - -NOTE: this function throws an exception if called for empty dataset (there - is no "last" sequence to modify). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssaappendpointandupdate( - ssamodel s, - double x, - double updateits, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function appends new sequence to dataset stored in the SSA model and -tries to update model in the incremental manner (if possible with current -algorithm). - -Notes: -* if you want to add M sequences at once, perform M-1 calls with UpdateIts - parameter set to 0.0, and last call with non-zero UpdateIts. -* if you want to add just one point, use ssaappendpointandupdate() - -Running time of this function does NOT depend on dataset size, only on -sequence length, window width and number of singular vectors. Depending on -algorithm being used, incremental update has complexity: -* for top-K real time - O(UpdateIts*K*Width^2+(NTicks-Width)*Width^2) -* for top-K direct - O(Width^3+(NTicks-Width)*Width^2) -* for precomputed basis - O(1), no update is performed - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - X - new sequence, array[NTicks] or larget - NTicks - >=1, number of ticks in the sequence - UpdateIts - >=0, floating point (!) value, desired update - frequency: - * zero value means that point is stored, but no - update is performed - * integer part of the value means that specified - number of iterations is always performed - * fractional part of the value means that one - iteration is performed with this probability. - - Recommended value: 0<UpdateIts<=1. Values larger - than 1 are VERY seldom needed. If your dataset - changes slowly, you can set it to 0.1 and skip - 90% of updates. - - In any case, no information is lost even with zero - value of UpdateIts! It will be incorporated into - model, sooner or later. - -OUTPUT PARAMETERS: - S - SSA model, updated - -NOTE: this function uses internal RNG to handle fractional values of - UpdateIts. By default it is initialized with fixed seed during - initial calculation of basis. Thus subsequent calls to this function - will result in the same sequence of pseudorandom decisions. - - However, if you have several SSA models which are calculated - simultaneously, and if you want to reduce computational bottlenecks - by performing random updates at random moments, then fixed seed is - not an option - all updates will fire at same moments. - - You may change it with ssasetseed() function. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssaappendsequenceandupdate( - ssamodel s, - real_1d_array x, - double updateits, - const xparams _params = alglib::xdefault); -void alglib::ssaappendsequenceandupdate( - ssamodel s, - real_1d_array x, - ae_int_t nticks, - double updateits, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function clears all data stored in the model and invalidates all -basis components found so far. - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - -OUTPUT PARAMETERS: - S - SSA model, updated - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssacleardata( - ssamodel s, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function creates SSA model object. Right after creation model is in -"dummy" mode - you can add data, but analyzing/prediction will return -just zeros (it assumes that basis is empty). - -HOW TO USE SSA MODEL: - -1. create model with ssacreate() -2. add data with one/many ssaaddsequence() calls -3. choose SSA algorithm with one of ssasetalgo...() functions: - * ssasetalgotopkdirect() for direct one-run analysis - * ssasetalgotopkrealtime() for algorithm optimized for many subsequent - runs with warm-start capabilities - * ssasetalgoprecomputed() for user-supplied basis -4. set window width with ssasetwindow() -5. perform one of the analysis-related activities: - a) call ssagetbasis() to get basis - b) call ssaanalyzelast() ssaanalyzesequence() or ssaanalyzelastwindow() - to perform analysis (trend/noise separation) - c) call one of the forecasting functions (ssaforecastlast() or - ssaforecastsequence()) to perform prediction; alternatively, you can - extract linear recurrence coefficients with ssagetlrr(). - SSA analysis will be performed during first call to analysis-related - function. SSA model is smart enough to track all changes in the dataset - and model settings, to cache previously computed basis and to - re-evaluate basis only when necessary. - -Additionally, if your setting involves constant stream of incoming data, -you can perform quick update already calculated model with one of the -incremental append-and-update functions: ssaappendpointandupdate() or -ssaappendsequenceandupdate(). - -NOTE: steps (2), (3), (4) can be performed in arbitrary order. - -INPUT PARAMETERS: - none - -OUTPUT PARAMETERS: - S - structure which stores model state - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssacreate( - ssamodel& s, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-
/************************************************************************* -This function builds SSA basis and performs forecasting for a specified -number of ticks, returning value of trend. - -Forecast is performed as follows: -* SSA trend extraction is applied to last M sliding windows of the - internally stored dataset -* for each of M sliding windows, M predictions are built -* average value of M predictions is returned - -This function has following running time: -* O(NBasis*WindowWidth*M) for trend extraction phase (always performed) -* O(WindowWidth*NTicks*M) for forecast phase - -NOTE: noise reduction is ALWAYS applied by this algorithm; if you want to - apply recurrence relation to raw unprocessed data, use another - function - ssaforecastsequence() which allows to turn on and off - noise reduction phase. - -NOTE: combination of several predictions results in lesser sensitivity to - noise, but it may produce undesirable discontinuities between last - point of the trend and first point of the prediction. The reason is - that last point of the trend is usually corrupted by noise, but - average value of several predictions is less sensitive to noise, - thus discontinuity appears. It is not a bug. - -INPUT PARAMETERS: - S - SSA model - M - number of sliding windows to combine, M>=1. If - your dataset has less than M sliding windows, this - parameter will be silently reduced. - NTicks - number of ticks to forecast, NTicks>=1 - -OUTPUT PARAMETERS: - Trend - array[NTicks], predicted trend line - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* last sequence is shorter than the WindowWidth (analysis can be done, - but we can not perform forecasting on the last sequence) -* window lentgh is 1 (impossible to use for forecasting) -* SSA analysis algorithm is configured to extract basis whose size is - equal to window length (impossible to use for forecasting; only basis - whose size is less than window length can be used). - -Calling this function in degenerate cases returns following result: -* NTicks copies of the last value is returned for non-empty task with - large enough dataset, but with overcomplete basis (window width=1 or - basis size is equal to window width) -* zero trend with length=NTicks is returned for empty task - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is ever constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssaforecastavglast( - ssamodel s, - ae_int_t m, - ae_int_t nticks, - real_1d_array& trend, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function builds SSA basis and performs forecasting for a user- -specified sequence, returning value of trend. - -Forecasting is done in two stages: -* first, we extract trend from M last sliding windows of the sequence. - This stage is optional, you can turn it off if you pass data which - are already processed with SSA. Of course, you can turn it off even - for raw data, but it is not recommended - noise suppression is very - important for correct prediction. -* then, we apply LRR independently for M sliding windows -* average of M predictions is returned - -This function has following running time: -* O(NBasis*WindowWidth*M) for trend extraction phase -* O(WindowWidth*NTicks*M) for forecast phase - -NOTE: combination of several predictions results in lesser sensitivity to - noise, but it may produce undesirable discontinuities between last - point of the trend and first point of the prediction. The reason is - that last point of the trend is usually corrupted by noise, but - average value of several predictions is less sensitive to noise, - thus discontinuity appears. It is not a bug. - -INPUT PARAMETERS: - S - SSA model - Data - array[NTicks], data to forecast - DataLen - number of ticks in the data, DataLen>=1 - M - number of sliding windows to combine, M>=1. If - your dataset has less than M sliding windows, this - parameter will be silently reduced. - ForecastLen - number of ticks to predict, ForecastLen>=1 - ApplySmoothing - whether to apply smoothing trend extraction or not. - if you do not know what to specify, pass true. - -OUTPUT PARAMETERS: - Trend - array[ForecastLen], forecasted trend - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* data sequence is shorter than the WindowWidth (analysis can be done, - but we can not perform forecasting on the last sequence) -* window lentgh is 1 (impossible to use for forecasting) -* SSA analysis algorithm is configured to extract basis whose size is - equal to window length (impossible to use for forecasting; only basis - whose size is less than window length can be used). - -Calling this function in degenerate cases returns following result: -* ForecastLen copies of the last value is returned for non-empty task with - large enough dataset, but with overcomplete basis (window width=1 or - basis size is equal to window width) -* zero trend with length=ForecastLen is returned for empty task - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is ever constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssaforecastavgsequence( - ssamodel s, - real_1d_array data, - ae_int_t m, - ae_int_t forecastlen, - real_1d_array& trend, - const xparams _params = alglib::xdefault); -void alglib::ssaforecastavgsequence( - ssamodel s, - real_1d_array data, - ae_int_t datalen, - ae_int_t m, - ae_int_t forecastlen, - bool applysmoothing, - real_1d_array& trend, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function builds SSA basis and performs forecasting for a specified -number of ticks, returning value of trend. - -Forecast is performed as follows: -* SSA trend extraction is applied to last WindowWidth elements of the - internally stored dataset; this step is basically a noise reduction. -* linear recurrence relation is applied to extracted trend - -This function has following running time: -* O(NBasis*WindowWidth) for trend extraction phase (always performed) -* O(WindowWidth*NTicks) for forecast phase - -NOTE: noise reduction is ALWAYS applied by this algorithm; if you want to - apply recurrence relation to raw unprocessed data, use another - function - ssaforecastsequence() which allows to turn on and off - noise reduction phase. - -NOTE: this algorithm performs prediction using only one - last - sliding - window. Predictions produced by such approach are smooth - continuations of the reconstructed trend line, but they can be - easily corrupted by noise. If you need noise-resistant prediction, - use ssaforecastavglast() function, which averages predictions built - using several sliding windows. - -INPUT PARAMETERS: - S - SSA model - NTicks - number of ticks to forecast, NTicks>=1 - -OUTPUT PARAMETERS: - Trend - array[NTicks], predicted trend line - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* last sequence is shorter than the WindowWidth (analysis can be done, - but we can not perform forecasting on the last sequence) -* window lentgh is 1 (impossible to use for forecasting) -* SSA analysis algorithm is configured to extract basis whose size is - equal to window length (impossible to use for forecasting; only basis - whose size is less than window length can be used). - -Calling this function in degenerate cases returns following result: -* NTicks copies of the last value is returned for non-empty task with - large enough dataset, but with overcomplete basis (window width=1 or - basis size is equal to window width) -* zero trend with length=NTicks is returned for empty task - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is ever constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssaforecastlast( - ssamodel s, - ae_int_t nticks, - real_1d_array& trend, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function builds SSA basis and performs forecasting for a user- -specified sequence, returning value of trend. - -Forecasting is done in two stages: -* first, we extract trend from the WindowWidth last elements of the - sequence. This stage is optional, you can turn it off if you pass - data which are already processed with SSA. Of course, you can turn it - off even for raw data, but it is not recommended - noise suppression is - very important for correct prediction. -* then, we apply LRR for last WindowWidth-1 elements of the extracted - trend. - -This function has following running time: -* O(NBasis*WindowWidth) for trend extraction phase -* O(WindowWidth*NTicks) for forecast phase - -NOTE: this algorithm performs prediction using only one - last - sliding - window. Predictions produced by such approach are smooth - continuations of the reconstructed trend line, but they can be - easily corrupted by noise. If you need noise-resistant prediction, - use ssaforecastavgsequence() function, which averages predictions - built using several sliding windows. - -INPUT PARAMETERS: - S - SSA model - Data - array[NTicks], data to forecast - DataLen - number of ticks in the data, DataLen>=1 - ForecastLen - number of ticks to predict, ForecastLen>=1 - ApplySmoothing - whether to apply smoothing trend extraction or not; - if you do not know what to specify, pass True. - -OUTPUT PARAMETERS: - Trend - array[ForecastLen], forecasted trend - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* data sequence is shorter than the WindowWidth (analysis can be done, - but we can not perform forecasting on the last sequence) -* window lentgh is 1 (impossible to use for forecasting) -* SSA analysis algorithm is configured to extract basis whose size is - equal to window length (impossible to use for forecasting; only basis - whose size is less than window length can be used). - -Calling this function in degenerate cases returns following result: -* ForecastLen copies of the last value is returned for non-empty task with - large enough dataset, but with overcomplete basis (window width=1 or - basis size is equal to window width) -* zero trend with length=ForecastLen is returned for empty task - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is ever constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssaforecastsequence( - ssamodel s, - real_1d_array data, - ae_int_t forecastlen, - real_1d_array& trend, - const xparams _params = alglib::xdefault); -void alglib::ssaforecastsequence( - ssamodel s, - real_1d_array data, - ae_int_t datalen, - ae_int_t forecastlen, - bool applysmoothing, - real_1d_array& trend, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function executes SSA on internally stored dataset and returns basis -found by current method. - -INPUT PARAMETERS: - S - SSA model - -OUTPUT PARAMETERS: - A - array[WindowWidth,NBasis], basis; vectors are - stored in matrix columns, by descreasing variance - SV - array[NBasis]: - * zeros - for model initialized with SSASetAlgoPrecomputed() - * singular values - for other algorithms - WindowWidth - current window - NBasis - basis size - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Calling this function in degenerate cases (no data or all data are -shorter than window size; no algorithm is specified) returns basis with -just one zero vector. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssagetbasis( - ssamodel s, - real_2d_array& a, - real_1d_array& sv, - ae_int_t& windowwidth, - ae_int_t& nbasis, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function returns linear recurrence relation (LRR) coefficients found -by current SSA algorithm. - -INPUT PARAMETERS: - S - SSA model - -OUTPUT PARAMETERS: - A - array[WindowWidth-1]. Coefficients of the - linear recurrence of the form: - X[W-1] = X[W-2]*A[W-2] + X[W-3]*A[W-3] + ... + X[0]*A[0]. - Empty array for WindowWidth=1. - WindowWidth - current window width - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Calling this function in degenerate cases (no data or all data are -shorter than window size; no algorithm is specified) returns zeros. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssagetlrr( - ssamodel s, - real_1d_array& a, - ae_int_t& windowwidth, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets SSA algorithm to "precomputed vectors" algorithm. - -This algorithm uses precomputed set of orthonormal (orthogonal AND -normalized) basis vectors supplied by user. Thus, basis calculation phase -is not performed - we already have our basis - and only analysis/ -forecasting phase requires actual calculations. - -This algorithm may handle "append" requests which add just one/few ticks -to the end of the last sequence in O(1) time. - -NOTE: this algorithm accepts both basis and window width, because these - two parameters are naturally aligned. Calling this function sets - window width; if you call ssasetwindow() with other window width, - then during analysis stage algorithm will detect conflict and reset - to zero basis. - -INPUT PARAMETERS: - S - SSA model - A - array[WindowWidth,NBasis], orthonormalized basis; - this function does NOT control orthogonality and - does NOT perform any kind of renormalization. It - is your responsibility to provide it with correct - basis. - WindowWidth - window width, >=1 - NBasis - number of basis vectors, 1<=NBasis<=WindowWidth - -OUTPUT PARAMETERS: - S - updated model - -NOTE: calling this function invalidates basis in all cases. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssasetalgoprecomputed( - ssamodel s, - real_2d_array a, - const xparams _params = alglib::xdefault); -void alglib::ssasetalgoprecomputed( - ssamodel s, - real_2d_array a, - ae_int_t windowwidth, - ae_int_t nbasis, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets SSA algorithm to "direct top-K" algorithm. - -"Direct top-K" algorithm performs full SVD of the N*WINDOW trajectory -matrix (hence its name - direct solver is used), then extracts top K -components. Overall running time is O(N*WINDOW^2), where N is a number of -ticks in the dataset, WINDOW is window width. - -This algorithm may handle "append" requests which add just one/few ticks -to the end of the last sequence in O(WINDOW^3) time, which is ~N/WINDOW -times faster than re-computing everything from scratch. - -INPUT PARAMETERS: - S - SSA model - TopK - number of components to analyze; TopK>=1. - -OUTPUT PARAMETERS: - S - updated model - - -NOTE: TopK>WindowWidth is silently decreased to WindowWidth during analysis - phase - -NOTE: calling this function invalidates basis, except for the situation - when this algorithm was already set with same parameters. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssasetalgotopkdirect( - ssamodel s, - ae_int_t topk, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  

- -
-
/************************************************************************* -This function sets SSA algorithm to "top-K real time algorithm". This algo -extracts K components with largest singular values. - -It is real-time version of top-K algorithm which is optimized for -incremental processing and fast start-up. Internally it uses subspace -eigensolver for truncated SVD. It results in ability to perform quick -updates of the basis when only a few points/sequences is added to dataset. - -Performance profile of the algorithm is given below: -* O(K*WindowWidth^2) running time for incremental update of the dataset - with one of the "append-and-update" functions (ssaappendpointandupdate() - or ssaappendsequenceandupdate()). -* O(N*WindowWidth^2) running time for initial basis evaluation (N=size of - dataset) -* ability to split costly initialization across several incremental - updates of the basis (so called "Power-Up" functionality, activated by - ssasetpoweruplength() function) - -INPUT PARAMETERS: - S - SSA model - TopK - number of components to analyze; TopK>=1. - -OUTPUT PARAMETERS: - S - updated model - -NOTE: this algorithm is optimized for large-scale tasks with large - datasets. On toy problems with just 5-10 points it can return basis - which is slightly different from that returned by direct algorithm - (ssasetalgotopkdirect() function). However, the difference becomes - negligible as dataset grows. - -NOTE: TopK>WindowWidth is silently decreased to WindowWidth during analysis - phase - -NOTE: calling this function invalidates basis, except for the situation - when this algorithm was already set with same parameters. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssasetalgotopkrealtime( - ssamodel s, - ae_int_t topk, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function sets memory limit of SSA analysis. - -Straightforward SSA with sequence length T and window width W needs O(T*W) -memory. It is possible to reduce memory consumption by splitting task into -smaller chunks. - -Thus function allows you to specify approximate memory limit (measured in -double precision numbers used for buffers). Actual memory consumption will -be comparable to the number specified by you. - -Default memory limit is 50.000.000 (400Mbytes) in current version. - -INPUT PARAMETERS: - S - SSA model - MemLimit- memory limit, >=0. Zero value means no limit. - - -- ALGLIB -- - Copyright 20.12.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssasetmemorylimit( - ssamodel s, - ae_int_t memlimit, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets length of power-up cycle for real-time algorithm. - -By default, this algorithm performs costly O(N*WindowWidth^2) init phase -followed by full run of truncated EVD. However, if you are ready to -live with a bit lower-quality basis during first few iterations, you can -split this O(N*WindowWidth^2) initialization between several subsequent -append-and-update rounds. It results in better latency of the algorithm. - -This function invalidates basis/solver, next analysis call will result in -full recalculation of everything. - -INPUT PARAMETERS: - S - SSA model - PWLen - length of the power-up stage: - * 0 means that no power-up is requested - * 1 is the same as 0 - * >1 means that delayed power-up is performed - - -- ALGLIB -- - Copyright 03.11.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssasetpoweruplength( - ssamodel s, - ae_int_t pwlen, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  

- -
-
/************************************************************************* -This function sets seed which is used to initialize internal RNG when -we make pseudorandom decisions on model updates. - -By default, deterministic seed is used - which results in same sequence of -pseudorandom decisions every time you run SSA model. If you specify non- -deterministic seed value, then SSA model may return slightly different -results after each run. - -This function can be useful when you have several SSA models updated with -sseappendpointandupdate() called with 0<UpdateIts<1 (fractional value) and -due to performance limitations want them to perform updates at different -moments. - -INPUT PARAMETERS: - S - SSA model - Seed - seed: - * positive values = use deterministic seed for each run of - algorithms which depend on random initialization - * zero or negative values = use non-deterministic seed - - -- ALGLIB -- - Copyright 03.11.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssasetseed( - ssamodel s, - ae_int_t seed, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This function sets window width for SSA model. You should call it before -analysis phase. Default window width is 1 (not for real use). - -Special notes: -* this function call can be performed at any moment before first call to - analysis-related functions -* changing window width invalidates internally stored basis; if you change - window width AFTER you call analysis-related function, next analysis - phase will require re-calculation of the basis according to current - algorithm. -* calling this function with exactly same window width as current one has - no effect -* if you specify window width larger than any data sequence stored in the - model, analysis will return zero basis. - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - WindowWidth - >=1, new window width - -OUTPUT PARAMETERS: - S - SSA model, updated - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ssasetwindow( - ssamodel s, - ae_int_t windowwidth, - const xparams _params = alglib::xdefault); - -
-

Examples:   [1]  [2]  [3]  

- -
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // Here we demonstrate SSA trend/noise separation for some toy problem:
-    // small monotonically growing series X are analyzed with 3-tick window
-    // and "top-K" version of SSA, which selects K largest singular vectors
-    // for analysis, with K=1.
-    //
-    ssamodel s;
-    real_1d_array x = "[0,0.5,1,1,1.5,2]";
-
-    //
-    // First, we create SSA model, set its properties and add dataset.
-    //
-    // We use window with width=3 and configure model to use direct SSA
-    // algorithm - one which runs exact O(N*W^2) analysis - to extract
-    // one top singular vector. Well, it is toy problem :)
-    //
-    // NOTE: SSA model may store and analyze more than one sequence
-    //       (say, different sequences may correspond to data collected
-    //       from different devices)
-    //
-    ssacreate(s);
-    ssasetwindow(s, 3);
-    ssaaddsequence(s, x);
-    ssasetalgotopkdirect(s, 1);
-
-    //
-    // Now we begin analysis. Internally SSA model stores everything it needs:
-    // data, settings, solvers and so on. Right after first call to analysis-
-    // related function it will analyze dataset, build basis and perform analysis.
-    //
-    // Subsequent calls to analysis functions will reuse previously computed
-    // basis, unless you invalidate it by changing model settings (or dataset).
-    //
-    real_1d_array trend;
-    real_1d_array noise;
-    ssaanalyzesequence(s, x, trend, noise);
-    printf("%s\n", trend.tostring(2).c_str()); // EXPECTED: [0.3815,0.5582,0.7810,1.0794,1.5041,2.0105]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // Here we demonstrate SSA forecasting on some toy problem with clearly
-    // visible linear trend and small amount of noise.
-    //
-    ssamodel s;
-    real_1d_array x = "[0.05,0.96,2.04,3.11,3.97,5.03,5.98,7.02,8.02]";
-
-    //
-    // First, we create SSA model, set its properties and add dataset.
-    //
-    // We use window with width=3 and configure model to use direct SSA
-    // algorithm - one which runs exact O(N*W^2) analysis - to extract
-    // two top singular vectors. Well, it is toy problem :)
-    //
-    // NOTE: SSA model may store and analyze more than one sequence
-    //       (say, different sequences may correspond to data collected
-    //       from different devices)
-    //
-    ssacreate(s);
-    ssasetwindow(s, 3);
-    ssaaddsequence(s, x);
-    ssasetalgotopkdirect(s, 2);
-
-    //
-    // Now we begin analysis. Internally SSA model stores everything it needs:
-    // data, settings, solvers and so on. Right after first call to analysis-
-    // related function it will analyze dataset, build basis and perform analysis.
-    //
-    // Subsequent calls to analysis functions will reuse previously computed
-    // basis, unless you invalidate it by changing model settings (or dataset).
-    //
-    // In this example we show how to use ssaforecastlast() function, which
-    // predicts changed in the last sequence of the dataset. If you want to
-    // perform prediction for some other sequence, use ssaforecastsequence().
-    //
-    real_1d_array trend;
-    ssaforecastlast(s, 3, trend);
-
-    //
-    // Well, we expected it to be [9,10,11]. There exists some difference,
-    // which can be explained by the artificial noise in the dataset.
-    //
-    printf("%s\n", trend.tostring(2).c_str()); // EXPECTED: [9.0005,9.9322,10.8051]
-    return 0;
-}
-
-
-
-
-#include "stdafx.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include "dataanalysis.h"
-
-using namespace alglib;
-
-
-int main(int argc, char **argv)
-{
-    //
-    // Suppose that you have a constant stream of incoming data, and you want
-    // to regularly perform singular spectral analysis of this stream.
-    //
-    // One full run of direct algorithm costs O(N*Width^2) operations, so
-    // the more points you have, the more it costs to rebuild basis from
-    // scratch.
-    // 
-    // Luckily we have incremental SSA algorithm which can perform quick
-    // updates of already computed basis in O(K*Width^2) ops, where K
-    // is a number of singular vectors extracted. Usually it is orders of
-    // magnitude faster than full update of the basis.
-    //
-    // In this example we start from some initial dataset x0. Then we
-    // start appending elements one by one to the end of the last sequence.
-    //
-    // NOTE: direct algorithm also supports incremental updates, but
-    //       with O(Width^3) cost. Typically K<<Width, so specialized
-    //       incremental algorithm is still faster.
-    //
-    ssamodel s1;
-    real_2d_array a1;
-    real_1d_array sv1;
-    ae_int_t w;
-    ae_int_t k;
-    real_1d_array x0 = "[0.009,0.976,1.999,2.984,3.977,5.002]";
-    ssacreate(s1);
-    ssasetwindow(s1, 3);
-    ssaaddsequence(s1, x0);
-
-    // set algorithm to the real-time version of top-K, K=2
-    ssasetalgotopkrealtime(s1, 2);
-
-    // one more interesting feature of the incremental algorithm is "power-up" cycle.
-    // even with incremental algorithm initial basis calculation costs O(N*Width^2) ops.
-    // if such startup cost is too high for your real-time app, then you may divide
-    // initial basis calculation across several model updates. It results in better
-    // latency at the price of somewhat lesser precision during first few updates.
-    ssasetpoweruplength(s1, 3);
-
-    // now, after we prepared everything, start to add incoming points one by one;
-    // in the real life, of course, we will perform some work between subsequent update
-    // (analyze something, predict, and so on).
-    //
-    // After each append we perform one iteration of the real-time solver. Usually
-    // one iteration is more than enough to update basis. If you have REALLY tight
-    // performance constraints, you may specify fractional amount of iterations,
-    // which means that iteration is performed with required probability.
-    double updateits = 1.0;
-    ssaappendpointandupdate(s1, 5.951, updateits);
-    ssagetbasis(s1, a1, sv1, w, k);
-
-    ssaappendpointandupdate(s1, 7.074, updateits);
-    ssagetbasis(s1, a1, sv1, w, k);
-
-    ssaappendpointandupdate(s1, 7.925, updateits);
-    ssagetbasis(s1, a1, sv1, w, k);
-
-    ssaappendpointandupdate(s1, 8.992, updateits);
-    ssagetbasis(s1, a1, sv1, w, k);
-
-    ssaappendpointandupdate(s1, 9.942, updateits);
-    ssagetbasis(s1, a1, sv1, w, k);
-
-    ssaappendpointandupdate(s1, 11.051, updateits);
-    ssagetbasis(s1, a1, sv1, w, k);
-
-    ssaappendpointandupdate(s1, 11.965, updateits);
-    ssagetbasis(s1, a1, sv1, w, k);
-
-    ssaappendpointandupdate(s1, 13.047, updateits);
-    ssagetbasis(s1, a1, sv1, w, k);
-
-    ssaappendpointandupdate(s1, 13.970, updateits);
-    ssagetbasis(s1, a1, sv1, w, k);
-
-    // Ok, we have our basis in a1[] and singular values at sv1[].
-    // But is it good enough? Let's print it.
-    printf("%s\n", a1.tostring(3).c_str()); // EXPECTED: [[0.510607,0.753611],[0.575201,0.058445],[0.639081,-0.654717]]
-
-    // Ok, two vectors with 3 components each.
-    // But how to understand that is it really good basis?
-    // Let's compare it with direct SSA algorithm on the entire sequence.
-    ssamodel s2;
-    real_2d_array a2;
-    real_1d_array sv2;
-    real_1d_array x2 = "[0.009,0.976,1.999,2.984,3.977,5.002,5.951,7.074,7.925,8.992,9.942,11.051,11.965,13.047,13.970]";
-    ssacreate(s2);
-    ssasetwindow(s2, 3);
-    ssaaddsequence(s2, x2);
-    ssasetalgotopkdirect(s2, 2);
-    ssagetbasis(s2, a2, sv2, w, k);
-
-    // it is exactly the same as one calculated with incremental approach!
-    printf("%s\n", a2.tostring(3).c_str()); // EXPECTED: [[0.510607,0.753611],[0.575201,0.058445],[0.639081,-0.654717]]
-    return 0;
-}
-
-
-
-
- -onesamplesigntest
- - -
- -
-
/************************************************************************* -Sign test - -This test checks three hypotheses about the median of the given sample. -The following tests are performed: - * two-tailed test (null hypothesis - the median is equal to the given - value) - * left-tailed test (null hypothesis - the median is greater than or - equal to the given value) - * right-tailed test (null hypothesis - the median is less than or - equal to the given value) - -Requirements: - * the scale of measurement should be ordinal, interval or ratio (i.e. - the test could not be applied to nominal variables). - -The test is non-parametric and doesn't require distribution X to be normal - -Input parameters: - X - sample. Array whose index goes from 0 to N-1. - N - size of the sample. - Median - assumed median value. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -While calculating p-values high-precision binomial distribution -approximation is used, so significance levels have about 15 exact digits. - - -- ALGLIB -- - Copyright 08.09.2006 by Bochkanov Sergey -*************************************************************************/ -
void alglib::onesamplesigntest( - real_1d_array x, - ae_int_t n, - double median, - double& bothtails, - double& lefttail, - double& righttail, - const xparams _params = alglib::xdefault); - -
- -
- -invstudenttdistribution
-studenttdistribution
- - -
- -
-
/************************************************************************* -Functional inverse of Student's t distribution - -Given probability p, finds the argument t such that stdtr(k,t) -is equal to p. - -ACCURACY: - -Tested at random 1 <= k <= 100. The "domain" refers to p: - Relative error: -arithmetic domain # trials peak rms - IEEE .001,.999 25000 5.7e-15 8.0e-16 - IEEE 10^-6,.001 25000 2.0e-12 2.9e-14 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::invstudenttdistribution( - ae_int_t k, - double p, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Student's t distribution - -Computes the integral from minus infinity to t of the Student -t distribution with integer k > 0 degrees of freedom: - - t - - - | | - - | 2 -(k+1)/2 - | ( (k+1)/2 ) | ( x ) - ---------------------- | ( 1 + --- ) dx - - | ( k ) - sqrt( k pi ) | ( k/2 ) | - | | - - - -inf. - -Relation to incomplete beta integral: - - 1 - stdtr(k,t) = 0.5 * incbet( k/2, 1/2, z ) -where - z = k/(k + t**2). - -For t < -2, this is the method of computation. For higher t, -a direct method is derived from integration by parts. -Since the function is symmetric about t=0, the area under the -right tail of the density is found by calling the function -with -t instead of t. - -ACCURACY: - -Tested at random 1 <= k <= 25. The "domain" refers to t. - Relative error: -arithmetic domain # trials peak rms - IEEE -100,-2 50000 5.9e-15 1.4e-15 - IEEE -2,100 500000 2.7e-15 4.9e-17 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -
double alglib::studenttdistribution( - ae_int_t k, - double t, - const xparams _params = alglib::xdefault); - -
- -
- -studentttest1
-studentttest2
-unequalvariancettest
- - -
- -
-
/************************************************************************* -One-sample t-test - -This test checks three hypotheses about the mean of the given sample. The -following tests are performed: - * two-tailed test (null hypothesis - the mean is equal to the given - value) - * left-tailed test (null hypothesis - the mean is greater than or - equal to the given value) - * right-tailed test (null hypothesis - the mean is less than or equal - to the given value). - -The test is based on the assumption that a given sample has a normal -distribution and an unknown dispersion. If the distribution sharply -differs from normal, the test will work incorrectly. - -INPUT PARAMETERS: - X - sample. Array whose index goes from 0 to N-1. - N - size of sample, N>=0 - Mean - assumed value of the mean. - -OUTPUT PARAMETERS: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -NOTE: this function correctly handles degenerate cases: - * when N=0, all p-values are set to 1.0 - * when variance of X[] is exactly zero, p-values are set - to 1.0 or 0.0, depending on difference between sample mean and - value of mean being tested. - - - -- ALGLIB -- - Copyright 08.09.2006 by Bochkanov Sergey -*************************************************************************/ -
void alglib::studentttest1( - real_1d_array x, - ae_int_t n, - double mean, - double& bothtails, - double& lefttail, - double& righttail, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Two-sample pooled test - -This test checks three hypotheses about the mean of the given samples. The -following tests are performed: - * two-tailed test (null hypothesis - the means are equal) - * left-tailed test (null hypothesis - the mean of the first sample is - greater than or equal to the mean of the second sample) - * right-tailed test (null hypothesis - the mean of the first sample is - less than or equal to the mean of the second sample). - -Test is based on the following assumptions: - * given samples have normal distributions - * dispersions are equal - * samples are independent. - -Input parameters: - X - sample 1. Array whose index goes from 0 to N-1. - N - size of sample. - Y - sample 2. Array whose index goes from 0 to M-1. - M - size of sample. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -NOTE: this function correctly handles degenerate cases: - * when N=0 or M=0, all p-values are set to 1.0 - * when both samples has exactly zero variance, p-values are set - to 1.0 or 0.0, depending on difference between means. - - -- ALGLIB -- - Copyright 18.09.2006 by Bochkanov Sergey -*************************************************************************/ -
void alglib::studentttest2( - real_1d_array x, - ae_int_t n, - real_1d_array y, - ae_int_t m, - double& bothtails, - double& lefttail, - double& righttail, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Two-sample unpooled test - -This test checks three hypotheses about the mean of the given samples. The -following tests are performed: - * two-tailed test (null hypothesis - the means are equal) - * left-tailed test (null hypothesis - the mean of the first sample is - greater than or equal to the mean of the second sample) - * right-tailed test (null hypothesis - the mean of the first sample is - less than or equal to the mean of the second sample). - -Test is based on the following assumptions: - * given samples have normal distributions - * samples are independent. -Equality of variances is NOT required. - -Input parameters: - X - sample 1. Array whose index goes from 0 to N-1. - N - size of the sample. - Y - sample 2. Array whose index goes from 0 to M-1. - M - size of the sample. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -NOTE: this function correctly handles degenerate cases: - * when N=0 or M=0, all p-values are set to 1.0 - * when both samples has zero variance, p-values are set - to 1.0 or 0.0, depending on difference between means. - * when only one sample has zero variance, test reduces to 1-sample - version. - - -- ALGLIB -- - Copyright 18.09.2006 by Bochkanov Sergey -*************************************************************************/ -
void alglib::unequalvariancettest( - real_1d_array x, - ae_int_t n, - real_1d_array y, - ae_int_t m, - double& bothtails, - double& lefttail, - double& righttail, - const xparams _params = alglib::xdefault); - -
- -
- -rmatrixsvd
- - -
- -
-
/************************************************************************* -Singular value decomposition of a rectangular matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -The algorithm calculates the singular value decomposition of a matrix of -size MxN: A = U * S * V^T - -The algorithm finds the singular values and, optionally, matrices U and V^T. -The algorithm can find both first min(M,N) columns of matrix U and rows of -matrix V^T (singular vectors), and matrices U and V^T wholly (of sizes MxM -and NxN respectively). - -Take into account that the subroutine does not return matrix V but V^T. - -Input parameters: - A - matrix to be decomposed. - Array whose indexes range within [0..M-1, 0..N-1]. - M - number of rows in matrix A. - N - number of columns in matrix A. - UNeeded - 0, 1 or 2. See the description of the parameter U. - VTNeeded - 0, 1 or 2. See the description of the parameter VT. - AdditionalMemory - - If the parameter: - * equals 0, the algorithm doesn't use additional - memory (lower requirements, lower performance). - * equals 1, the algorithm uses additional - memory of size min(M,N)*min(M,N) of real numbers. - It often speeds up the algorithm. - * equals 2, the algorithm uses additional - memory of size M*min(M,N) of real numbers. - It allows to get a maximum performance. - The recommended value of the parameter is 2. - -Output parameters: - W - contains singular values in descending order. - U - if UNeeded=0, U isn't changed, the left singular vectors - are not calculated. - if Uneeded=1, U contains left singular vectors (first - min(M,N) columns of matrix U). Array whose indexes range - within [0..M-1, 0..Min(M,N)-1]. - if UNeeded=2, U contains matrix U wholly. Array whose - indexes range within [0..M-1, 0..M-1]. - VT - if VTNeeded=0, VT isn't changed, the right singular vectors - are not calculated. - if VTNeeded=1, VT contains right singular vectors (first - min(M,N) rows of matrix V^T). Array whose indexes range - within [0..min(M,N)-1, 0..N-1]. - if VTNeeded=2, VT contains matrix V^T wholly. Array whose - indexes range within [0..N-1, 0..N-1]. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -
bool alglib::rmatrixsvd( - real_2d_array a, - ae_int_t m, - ae_int_t n, - ae_int_t uneeded, - ae_int_t vtneeded, - ae_int_t additionalmemory, - real_1d_array& w, - real_2d_array& u, - real_2d_array& vt, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -An analysis of the sparse matrix decomposition, performed prior to actual -numerical factorization. You should not directly access fields of this -object - use appropriate ALGLIB functions to work with this object. -*************************************************************************/ -
class sparsedecompositionanalysis -{ -}; - -
- -
-
/************************************************************************* -LU decomposition of a general complex matrix with row pivoting - -A is represented as A = P*L*U, where: -* L is lower unitriangular matrix -* U is upper triangular matrix -* P = P0*P1*...*PK, K=min(M,N)-1, - Pi - permutation matrix for I and Pivots[I] - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - array[0..M-1, 0..N-1]. - M - number of rows in matrix A. - N - number of columns in matrix A. - - -OUTPUT PARAMETERS: - A - matrices L and U in compact form: - * L is stored under main diagonal - * U is stored on and above main diagonal - Pivots - permutation matrix in compact form. - array[0..Min(M-1,N-1)]. - - -- ALGLIB routine -- - 10.01.2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::cmatrixlu( - complex_2d_array& a, - ae_int_t m, - ae_int_t n, - integer_1d_array& pivots, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Cache-oblivious Cholesky decomposition - -The algorithm computes Cholesky decomposition of a Hermitian positive- -definite matrix. The result of an algorithm is a representation of A as -A=U'*U or A=L*L' (here X' denotes conj(X^T)). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - upper or lower triangle of a factorized matrix. - array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - if IsUpper=True, then A contains an upper triangle of - a symmetric matrix, otherwise A contains a lower one. - -OUTPUT PARAMETERS: - A - the result of factorization. If IsUpper=True, then - the upper triangle contains matrix U, so that A = U'*U, - and the elements below the main diagonal are not modified. - Similarly, if IsUpper = False. - -RESULT: - If the matrix is positive-definite, the function returns True. - Otherwise, the function returns False. Contents of A is not determined - in such case. - - -- ALGLIB routine -- - 15.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -
bool alglib::hpdmatrixcholesky( - complex_2d_array& a, - ae_int_t n, - bool isupper, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -LU decomposition of a general real matrix with row pivoting - -A is represented as A = P*L*U, where: -* L is lower unitriangular matrix -* U is upper triangular matrix -* P = P0*P1*...*PK, K=min(M,N)-1, - Pi - permutation matrix for I and Pivots[I] - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - array[0..M-1, 0..N-1]. - M - number of rows in matrix A. - N - number of columns in matrix A. - - -OUTPUT PARAMETERS: - A - matrices L and U in compact form: - * L is stored under main diagonal - * U is stored on and above main diagonal - Pivots - permutation matrix in compact form. - array[0..Min(M-1,N-1)]. - - -- ALGLIB routine -- - 10.01.2010 - Bochkanov Sergey -*************************************************************************/ -
void alglib::rmatrixlu( - real_2d_array& a, - ae_int_t m, - ae_int_t n, - integer_1d_array& pivots, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Sparse Cholesky decomposition for a matrix stored in any sparse storage, -without rows/cols permutation. - -This function is the most convenient (less parameters to specify), although -less efficient, version of sparse Cholesky. - -Internally it: -* calls SparseCholeskyAnalyze() function to perform symbolic analysis - phase with no permutation being configured. -* calls SparseCholeskyFactorize() function to perform numerical phase of - the factorization - -Following alternatives may result in better performance: -* using SparseCholeskyP(), which selects best pivoting available, which - almost always results in improved sparsity and cache locality -* using SparseCholeskyAnalyze() and SparseCholeskyFactorize() functions - directly, which may improve performance of repetitive factorizations - with same sparsity patterns. - -The latter also allows one to perform LDLT factorization of indefinite -matrix (one with strictly diagonal D, which is known to be stable only -in few special cases, like quasi-definite matrices). - -INPUT PARAMETERS: - A - a square NxN sparse matrix, stored in any storage format. - IsUpper - if IsUpper=True, then factorization is performed on upper - triangle. Another triangle is ignored on input, dropped - on output. Similarly, if IsUpper=False, the lower triangle - is processed. - -OUTPUT PARAMETERS: - A - the result of factorization, stored in CRS format: - * if IsUpper=True, then the upper triangle contains matrix - U such that A = U^T*U and the lower triangle is empty. - * similarly, if IsUpper=False, then lower triangular L is - returned and we have A = L*(L^T). - Note that THIS function does not perform permutation of - the rows to reduce fill-in. - -RESULT: - If the matrix is positive-definite, the function returns True. - Otherwise, the function returns False. Contents of A is undefined - in such case. - -NOTE: for performance reasons this function does NOT check that input - matrix includes only finite values. It is your responsibility to - make sure that there are no infinite or NAN values in the matrix. - - -- ALGLIB routine -- - 16.09.2020 - Bochkanov Sergey -*************************************************************************/ -
bool alglib::sparsecholesky( - sparsematrix a, - bool isupper, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Sparse Cholesky/LDLT decomposition: symbolic analysis phase. - -This function is a part of the 'expert' sparse Cholesky API: -* SparseCholeskyAnalyze(), that performs symbolic analysis phase and loads - matrix to be factorized into internal storage -* SparseCholeskySetModType(), that allows to use modified Cholesky/LDLT - with lower bounds on pivot magnitudes and additional overflow safeguards -* SparseCholeskyFactorize(), that performs numeric factorization using - precomputed symbolic analysis and internally stored matrix - and outputs - result -* SparseCholeskyReload(), that reloads one more matrix with same sparsity - pattern into internal storage so one may reuse previously allocated - temporaries and previously performed symbolic analysis - -This specific function performs preliminary analysis of the Cholesky/LDLT -factorization. It allows to choose different permutation types and to -choose between classic Cholesky and indefinite LDLT factorization (the -latter is computed with strictly diagonal D, i.e. without Bunch-Kauffman -pivoting). - -NOTE: L*D*LT family of factorization may be used to factorize indefinite - matrices. However, numerical stability is guaranteed ONLY for a class - of quasi-definite matrices. - -NOTE: all internal processing is performed with lower triangular matrices - stored in CRS format. Any other storage formats and/or upper - triangular storage means that one format conversion and/or one - transposition will be performed internally for the analysis and - factorization phases. Thus, highest performance is achieved when - input is a lower triangular CRS matrix. - -INPUT PARAMETERS: - A - sparse square matrix in any sparse storage format. - IsUpper - whether upper or lower triangle is decomposed (the - other one is ignored). - FactType - factorization type: - * 0 for traditional Cholesky of SPD matrix - * 1 for LDLT decomposition with strictly diagonal D, - which may have non-positive entries. - PermType - permutation type: - *-1 for absence of permutation - * 0 for best fill-in reducing permutation available - * 1 for supernodal ordering (improves locality and - performance, does NOT change fill-in factor) - * 2 for AMD (approximate minimum degree) ordering - -OUTPUT PARAMETERS: - Analysis - contains: - * symbolic analysis of the matrix structure which will - be used later to guide numerical factorization. - * specific numeric values loaded into internal memory - waiting for the factorization to be performed - -This function fails if and only if the matrix A is symbolically degenerate -i.e. has diagonal element which is exactly zero. In such case False is -returned, contents of Analysis object is undefined. - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -
bool alglib::sparsecholeskyanalyze( - sparsematrix a, - bool isupper, - ae_int_t facttype, - ae_int_t permtype, - sparsedecompositionanalysis& analysis, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Sparse Cholesky decomposition: numerical analysis phase. - -This function is a part of the 'expert' sparse Cholesky API: -* SparseCholeskyAnalyze(), that performs symbolic analysis phase and loads - matrix to be factorized into internal storage -* SparseCholeskySetModType(), that allows to use modified Cholesky/LDLT - with lower bounds on pivot magnitudes and additional overflow safeguards -* SparseCholeskyFactorize(), that performs numeric factorization using - precomputed symbolic analysis and internally stored matrix - and outputs - result -* SparseCholeskyReload(), that reloads one more matrix with same sparsity - pattern into internal storage so one may reuse previously allocated - temporaries and previously performed symbolic analysis - -Depending on settings specified during SparseCholeskyAnalyze() call it may -produce classic Cholesky or L*D*LT decomposition (with strictly diagonal -D), without permutation or with performance-enhancing permutation P. - -NOTE: all internal processing is performed with lower triangular matrices - stored in CRS format. Any other storage formats and/or upper - triangular storage means that one format conversion and/or one - transposition will be performed internally for the analysis and - factorization phases. Thus, highest performance is achieved when - input is a lower triangular CRS matrix, and lower triangular output - is requested. - -NOTE: L*D*LT family of factorization may be used to factorize indefinite - matrices. However, numerical stability is guaranteed ONLY for a class - of quasi-definite matrices. - -INPUT PARAMETERS: - Analysis - prior analysis with internally stored matrix which will - be factorized - NeedUpper - whether upper triangular or lower triangular output is - needed - -OUTPUT PARAMETERS: - A - Cholesky decomposition of A stored in lower triangular - CRS format, i.e. A=L*L' (or upper triangular CRS, with - A=U'*U, depending on NeedUpper parameter). - D - array[N], diagonal factor. If no diagonal factor was - required during analysis phase, still returned but - filled with 1's - P - array[N], pivots. Permutation matrix P is a product of - P(0)*P(1)*...*P(N-1), where P(i) is a permutation of - row/col I and P[I] (with P[I]>=I). - If no permutation was requested during analysis phase, - still returned but filled with identity permutation. - -The function returns True when factorization resulted in nondegenerate -matrix. False is returned when factorization fails (Cholesky factorization -of indefinite matrix) or LDLT factorization has exactly zero elements at -the diagonal. In the latter case contents of A, D and P is undefined. - -The analysis object is not changed during the factorization. Subsequent -calls to SparseCholeskyFactorize() will result in same factorization being -performed one more time. - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -
bool alglib::sparsecholeskyfactorize( - sparsedecompositionanalysis analysis, - bool needupper, - sparsematrix& a, - real_1d_array& d, - integer_1d_array& p, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Sparse Cholesky decomposition for a matrix stored in any sparse storage -format, with performance-enhancing permutation of rows/cols. - -Present version is configured to perform supernodal permutation which -sparsity reducing ordering. - -This function is a wrapper around generic sparse decomposition functions -that internally: -* calls SparseCholeskyAnalyze() function to perform symbolic analysis - phase with best available permutation being configured. -* calls SparseCholeskyFactorize() function to perform numerical phase of - the factorization. - -NOTE: using SparseCholeskyAnalyze() and SparseCholeskyFactorize() directly - may improve performance of repetitive factorizations with same - sparsity patterns. It also allows one to perform LDLT factorization - of indefinite matrix - a factorization with strictly diagonal D, - which is known to be stable only in few special cases, like quasi- - definite matrices. - -INPUT PARAMETERS: - A - a square NxN sparse matrix, stored in any storage format. - IsUpper - if IsUpper=True, then factorization is performed on upper - triangle. Another triangle is ignored on input, dropped - on output. Similarly, if IsUpper=False, the lower triangle - is processed. - -OUTPUT PARAMETERS: - A - the result of factorization, stored in CRS format: - * if IsUpper=True, then the upper triangle contains matrix - U such that A = U^T*U and the lower triangle is empty. - * similarly, if IsUpper=False, then lower triangular L is - returned and we have A = L*(L^T). - P - a row/column permutation, a product of P0*P1*...*Pk, k=N-1, - with Pi being permutation of rows/cols I and P[I] - -RESULT: - If the matrix is positive-definite, the function returns True. - Otherwise, the function returns False. Contents of A is undefined - in such case. - -NOTE: for performance reasons this function does NOT check that input - matrix includes only finite values. It is your responsibility to - make sure that there are no infinite or NAN values in the matrix. - - -- ALGLIB routine -- - 16.09.2020 - Bochkanov Sergey -*************************************************************************/ -
bool alglib::sparsecholeskyp( - sparsematrix a, - bool isupper, - integer_1d_array& p, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Sparse Cholesky decomposition: update internally stored matrix with -another one with exactly same sparsity pattern. - -This function is a part of the 'expert' sparse Cholesky API: -* SparseCholeskyAnalyze(), that performs symbolic analysis phase and loads - matrix to be factorized into internal storage -* SparseCholeskySetModType(), that allows to use modified Cholesky/LDLT - with lower bounds on pivot magnitudes and additional overflow safeguards -* SparseCholeskyFactorize(), that performs numeric factorization using - precomputed symbolic analysis and internally stored matrix - and outputs - result -* SparseCholeskyReload(), that reloads one more matrix with same sparsity - pattern into internal storage so one may reuse previously allocated - temporaries and previously performed symbolic analysis - -This specific function replaces internally stored numerical values with -ones from another sparse matrix (but having exactly same sparsity pattern -as one that was used for initial SparseCholeskyAnalyze() call). - -NOTE: all internal processing is performed with lower triangular matrices - stored in CRS format. Any other storage formats and/or upper - triangular storage means that one format conversion and/or one - transposition will be performed internally for the analysis and - factorization phases. Thus, highest performance is achieved when - input is a lower triangular CRS matrix. - -INPUT PARAMETERS: - Analysis - analysis object - A - sparse square matrix in any sparse storage format. It - MUST have exactly same sparsity pattern as that of the - matrix that was passed to SparseCholeskyAnalyze(). - Any difference (missing elements or additional elements) - may result in unpredictable and undefined behavior - - an algorithm may fail due to memory access violation. - IsUpper - whether upper or lower triangle is decomposed (the - other one is ignored). - -OUTPUT PARAMETERS: - Analysis - contains: - * symbolic analysis of the matrix structure which will - be used later to guide numerical factorization. - * specific numeric values loaded into internal memory - waiting for the factorization to be performed - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -
void alglib::sparsecholeskyreload( - sparsedecompositionanalysis analysis, - sparsematrix a, - bool isupper, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Sparse Cholesky decomposition for skyline matrixm using in-place algorithm -without allocating additional storage. - -The algorithm computes Cholesky decomposition of a symmetric positive- -definite sparse matrix. The result of an algorithm is a representation of -A as A=U^T*U or A=L*L^T - -This function allows to perform very efficient decomposition of low-profile -matrices (average bandwidth is ~5-10 elements). For larger matrices it is -recommended to use supernodal Cholesky decomposition: SparseCholeskyP() or -SparseCholeskyAnalyze()/SparseCholeskyFactorize(). - -INPUT PARAMETERS: - A - sparse matrix in skyline storage (SKS) format. - N - size of matrix A (can be smaller than actual size of A) - IsUpper - if IsUpper=True, then factorization is performed on upper - triangle. Another triangle is ignored (it may contant some - data, but it is not changed). - - -OUTPUT PARAMETERS: - A - the result of factorization, stored in SKS. If IsUpper=True, - then the upper triangle contains matrix U, such that - A = U^T*U. Lower triangle is not changed. - Similarly, if IsUpper = False. In this case L is returned, - and we have A = L*(L^T). - Note that THIS function does not perform permutation of - rows to reduce bandwidth. - -RESULT: - If the matrix is positive-definite, the function returns True. - Otherwise, the function returns False. Contents of A is not determined - in such case. - -NOTE: for performance reasons this function does NOT check that input - matrix includes only finite values. It is your responsibility to - make sure that there are no infinite or NAN values in the matrix. - - -- ALGLIB routine -- - 16.01.2014 - Bochkanov Sergey -*************************************************************************/ -
bool alglib::sparsecholeskyskyline( - sparsematrix a, - ae_int_t n, - bool isupper, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Sparse LU decomposition with column pivoting for sparsity and row pivoting -for stability. Input must be square sparse matrix stored in CRS format. - -The algorithm computes LU decomposition of a general square matrix -(rectangular ones are not supported). The result of an algorithm is a -representation of A as A = P*L*U*Q, where: -* L is lower unitriangular matrix -* U is upper triangular matrix -* P = P0*P1*...*PK, K=N-1, Pi - permutation matrix for I and P[I] -* Q = QK*...*Q1*Q0, K=N-1, Qi - permutation matrix for I and Q[I] - -This function pivots columns for higher sparsity, and then pivots rows for -stability (larger element at the diagonal). - -INPUT PARAMETERS: - A - sparse NxN matrix in CRS format. An exception is generated - if matrix is non-CRS or non-square. - PivotType- pivoting strategy: - * 0 for best pivoting available (2 in current version) - * 1 for row-only pivoting (NOT RECOMMENDED) - * 2 for complete pivoting which produces most sparse outputs - -OUTPUT PARAMETERS: - A - the result of factorization, matrices L and U stored in - compact form using CRS sparse storage format: - * lower unitriangular L is stored strictly under main diagonal - * upper triangilar U is stored ON and ABOVE main diagonal - P - row permutation matrix in compact form, array[N] - Q - col permutation matrix in compact form, array[N] - -This function always succeeds, i.e. it ALWAYS returns valid factorization, -but for your convenience it also returns boolean value which helps to -detect symbolically degenerate matrices: -* function returns TRUE, if the matrix was factorized AND symbolically - non-degenerate -* function returns FALSE, if the matrix was factorized but U has strictly - zero elements at the diagonal (the factorization is returned anyway). - - - -- ALGLIB routine -- - 03.09.2018 - Bochkanov Sergey -*************************************************************************/ -
bool alglib::sparselu( - sparsematrix a, - ae_int_t pivottype, - integer_1d_array& p, - integer_1d_array& q, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Cache-oblivious Cholesky decomposition - -The algorithm computes Cholesky decomposition of a symmetric positive- -definite matrix. The result of an algorithm is a representation of A as -A=U^T*U or A=L*L^T - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - upper or lower triangle of a factorized matrix. - array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - if IsUpper=True, then A contains an upper triangle of - a symmetric matrix, otherwise A contains a lower one. - -OUTPUT PARAMETERS: - A - the result of factorization. If IsUpper=True, then - the upper triangle contains matrix U, so that A = U^T*U, - and the elements below the main diagonal are not modified. - Similarly, if IsUpper = False. - -RESULT: - If the matrix is positive-definite, the function returns True. - Otherwise, the function returns False. Contents of A is not determined - in such case. - - -- ALGLIB routine -- - 15.12.2009 - Bochkanov Sergey -*************************************************************************/ -
bool alglib::spdmatrixcholesky( - real_2d_array& a, - ae_int_t n, - bool isupper, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Update of Cholesky decomposition: rank-1 update to original A. "Buffered" -version which uses preallocated buffer which is saved between subsequent -function calls. - -This function uses internally allocated buffer which is not saved between -subsequent calls. So, if you perform a lot of subsequent updates, -we recommend you to use "buffered" version of this function: -SPDMatrixCholeskyUpdateAdd1Buf(). - -INPUT PARAMETERS: - A - upper or lower Cholesky factor. - array with elements [0..N-1, 0..N-1]. - Exception is thrown if array size is too small. - N - size of matrix A, N>0 - IsUpper - if IsUpper=True, then A contains upper Cholesky factor; - otherwise A contains a lower one. - U - array[N], rank-1 update to A: A_mod = A + u*u' - Exception is thrown if array size is too small. - BufR - possibly preallocated buffer; automatically resized if - needed. It is recommended to reuse this buffer if you - perform a lot of subsequent decompositions. - -OUTPUT PARAMETERS: - A - updated factorization. If IsUpper=True, then the upper - triangle contains matrix U, and the elements below the main - diagonal are not modified. Similarly, if IsUpper = False. - -NOTE: this function always succeeds, so it does not return completion code - -NOTE: this function checks sizes of input arrays, but it does NOT checks - for presence of infinities or NAN's. - - -- ALGLIB -- - 03.02.2014 - Sergey Bochkanov -*************************************************************************/ -
void alglib::spdmatrixcholeskyupdateadd1( - real_2d_array& a, - ae_int_t n, - bool isupper, - real_1d_array u, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Update of Cholesky decomposition: rank-1 update to original A. "Buffered" -version which uses preallocated buffer which is saved between subsequent -function calls. - -See comments for SPDMatrixCholeskyUpdateAdd1() for more information. - -INPUT PARAMETERS: - A - upper or lower Cholesky factor. - array with elements [0..N-1, 0..N-1]. - Exception is thrown if array size is too small. - N - size of matrix A, N>0 - IsUpper - if IsUpper=True, then A contains upper Cholesky factor; - otherwise A contains a lower one. - U - array[N], rank-1 update to A: A_mod = A + u*u' - Exception is thrown if array size is too small. - BufR - possibly preallocated buffer; automatically resized if - needed. It is recommended to reuse this buffer if you - perform a lot of subsequent decompositions. - -OUTPUT PARAMETERS: - A - updated factorization. If IsUpper=True, then the upper - triangle contains matrix U, and the elements below the main - diagonal are not modified. Similarly, if IsUpper = False. - - -- ALGLIB -- - 03.02.2014 - Sergey Bochkanov -*************************************************************************/ -
void alglib::spdmatrixcholeskyupdateadd1buf( - real_2d_array& a, - ae_int_t n, - bool isupper, - real_1d_array u, - real_1d_array& bufr, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Update of Cholesky decomposition: "fixing" some variables. - -This function uses internally allocated buffer which is not saved between -subsequent calls. So, if you perform a lot of subsequent updates, -we recommend you to use "buffered" version of this function: -SPDMatrixCholeskyUpdateFixBuf(). - -"FIXING" EXPLAINED: - - Suppose we have N*N positive definite matrix A. "Fixing" some variable - means filling corresponding row/column of A by zeros, and setting - diagonal element to 1. - - For example, if we fix 2nd variable in 4*4 matrix A, it becomes Af: - - ( A00 A01 A02 A03 ) ( Af00 0 Af02 Af03 ) - ( A10 A11 A12 A13 ) ( 0 1 0 0 ) - ( A20 A21 A22 A23 ) => ( Af20 0 Af22 Af23 ) - ( A30 A31 A32 A33 ) ( Af30 0 Af32 Af33 ) - - If we have Cholesky decomposition of A, it must be recalculated after - variables were fixed. However, it is possible to use efficient - algorithm, which needs O(K*N^2) time to "fix" K variables, given - Cholesky decomposition of original, "unfixed" A. - -INPUT PARAMETERS: - A - upper or lower Cholesky factor. - array with elements [0..N-1, 0..N-1]. - Exception is thrown if array size is too small. - N - size of matrix A, N>0 - IsUpper - if IsUpper=True, then A contains upper Cholesky factor; - otherwise A contains a lower one. - Fix - array[N], I-th element is True if I-th variable must be - fixed. Exception is thrown if array size is too small. - BufR - possibly preallocated buffer; automatically resized if - needed. It is recommended to reuse this buffer if you - perform a lot of subsequent decompositions. - -OUTPUT PARAMETERS: - A - updated factorization. If IsUpper=True, then the upper - triangle contains matrix U, and the elements below the main - diagonal are not modified. Similarly, if IsUpper = False. - -NOTE: this function always succeeds, so it does not return completion code - -NOTE: this function checks sizes of input arrays, but it does NOT checks - for presence of infinities or NAN's. - -NOTE: this function is efficient only for moderate amount of updated - variables - say, 0.1*N or 0.3*N. For larger amount of variables it - will still work, but you may get better performance with - straightforward Cholesky. - - -- ALGLIB -- - 03.02.2014 - Sergey Bochkanov -*************************************************************************/ -
void alglib::spdmatrixcholeskyupdatefix( - real_2d_array& a, - ae_int_t n, - bool isupper, - boolean_1d_array fix, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Update of Cholesky decomposition: "fixing" some variables. "Buffered" -version which uses preallocated buffer which is saved between subsequent -function calls. - -See comments for SPDMatrixCholeskyUpdateFix() for more information. - -INPUT PARAMETERS: - A - upper or lower Cholesky factor. - array with elements [0..N-1, 0..N-1]. - Exception is thrown if array size is too small. - N - size of matrix A, N>0 - IsUpper - if IsUpper=True, then A contains upper Cholesky factor; - otherwise A contains a lower one. - Fix - array[N], I-th element is True if I-th variable must be - fixed. Exception is thrown if array size is too small. - BufR - possibly preallocated buffer; automatically resized if - needed. It is recommended to reuse this buffer if you - perform a lot of subsequent decompositions. - -OUTPUT PARAMETERS: - A - updated factorization. If IsUpper=True, then the upper - triangle contains matrix U, and the elements below the main - diagonal are not modified. Similarly, if IsUpper = False. - - -- ALGLIB -- - 03.02.2014 - Sergey Bochkanov -*************************************************************************/ -
void alglib::spdmatrixcholeskyupdatefixbuf( - real_2d_array& a, - ae_int_t n, - bool isupper, - boolean_1d_array fix, - real_1d_array& bufr, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* -Hyperbolic sine and cosine integrals - -Approximates the integrals - - x - - - | | cosh t - 1 - Chi(x) = eul + ln x + | ----------- dt, - | | t - - - 0 - - x - - - | | sinh t - Shi(x) = | ------ dt - | | t - - - 0 - -where eul = 0.57721566490153286061 is Euler's constant. -The integrals are evaluated by power series for x < 8 -and by Chebyshev expansions for x between 8 and 88. -For large x, both functions approach exp(x)/2x. -Arguments greater than 88 in magnitude return MAXNUM. - - -ACCURACY: - -Test interval 0 to 88. - Relative error: -arithmetic function # trials peak rms - IEEE Shi 30000 6.9e-16 1.6e-16 - Absolute error, except relative when |Chi| > 1: - IEEE Chi 30000 8.4e-16 1.4e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -
void alglib::hyperbolicsinecosineintegrals( - double x, - double& shi, - double& chi, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -Sine and cosine integrals - -Evaluates the integrals - - x - - - | cos t - 1 - Ci(x) = eul + ln x + | --------- dt, - | t - - - 0 - x - - - | sin t - Si(x) = | ----- dt - | t - - - 0 - -where eul = 0.57721566490153286061 is Euler's constant. -The integrals are approximated by rational functions. -For x > 8 auxiliary functions f(x) and g(x) are employed -such that - -Ci(x) = f(x) sin(x) - g(x) cos(x) -Si(x) = pi/2 - f(x) cos(x) - g(x) sin(x) - - -ACCURACY: - Test interval = [0,50]. -Absolute error, except relative when > 1: -arithmetic function # trials peak rms - IEEE Si 30000 4.4e-16 7.3e-17 - IEEE Ci 30000 6.9e-16 5.1e-17 - -Cephes Math Library Release 2.1: January, 1989 -Copyright 1984, 1987, 1989 by Stephen L. Moshier -*************************************************************************/ -
void alglib::sinecosineintegrals( - double x, - double& si, - double& ci, - const xparams _params = alglib::xdefault); - -
- -
- -ftest
-onesamplevariancetest
- - -
- -
-
/************************************************************************* -Two-sample F-test - -This test checks three hypotheses about dispersions of the given samples. -The following tests are performed: - * two-tailed test (null hypothesis - the dispersions are equal) - * left-tailed test (null hypothesis - the dispersion of the first - sample is greater than or equal to the dispersion of the second - sample). - * right-tailed test (null hypothesis - the dispersion of the first - sample is less than or equal to the dispersion of the second sample) - -The test is based on the following assumptions: - * the given samples have normal distributions - * the samples are independent. - -Input parameters: - X - sample 1. Array whose index goes from 0 to N-1. - N - sample size. - Y - sample 2. Array whose index goes from 0 to M-1. - M - sample size. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - - -- ALGLIB -- - Copyright 19.09.2006 by Bochkanov Sergey -*************************************************************************/ -
void alglib::ftest( - real_1d_array x, - ae_int_t n, - real_1d_array y, - ae_int_t m, - double& bothtails, - double& lefttail, - double& righttail, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -One-sample chi-square test - -This test checks three hypotheses about the dispersion of the given sample -The following tests are performed: - * two-tailed test (null hypothesis - the dispersion equals the given - number) - * left-tailed test (null hypothesis - the dispersion is greater than - or equal to the given number) - * right-tailed test (null hypothesis - dispersion is less than or - equal to the given number). - -Test is based on the following assumptions: - * the given sample has a normal distribution. - -Input parameters: - X - sample 1. Array whose index goes from 0 to N-1. - N - size of the sample. - Variance - dispersion value to compare with. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - - -- ALGLIB -- - Copyright 19.09.2006 by Bochkanov Sergey -*************************************************************************/ -
void alglib::onesamplevariancetest( - real_1d_array x, - ae_int_t n, - double variance, - double& bothtails, - double& lefttail, - double& righttail, - const xparams _params = alglib::xdefault); - -
- -
- -wilcoxonsignedranktest
- - -
- -
-
/************************************************************************* -Wilcoxon signed-rank test - -This test checks three hypotheses about the median of the given sample. -The following tests are performed: - * two-tailed test (null hypothesis - the median is equal to the given - value) - * left-tailed test (null hypothesis - the median is greater than or - equal to the given value) - * right-tailed test (null hypothesis - the median is less than or - equal to the given value) - -Requirements: - * the scale of measurement should be ordinal, interval or ratio (i.e. - the test could not be applied to nominal variables). - * the distribution should be continuous and symmetric relative to its - median. - * number of distinct values in the X array should be greater than 4 - -The test is non-parametric and doesn't require distribution X to be normal - -Input parameters: - X - sample. Array whose index goes from 0 to N-1. - N - size of the sample. - Median - assumed median value. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -To calculate p-values, special approximation is used. This method lets us -calculate p-values with two decimal places in interval [0.0001, 1]. - -"Two decimal places" does not sound very impressive, but in practice the -relative error of less than 1% is enough to make a decision. - -There is no approximation outside the [0.0001, 1] interval. Therefore, if -the significance level outlies this interval, the test returns 0.0001. - - -- ALGLIB -- - Copyright 08.09.2006 by Bochkanov Sergey -*************************************************************************/ -
void alglib::wilcoxonsignedranktest( - real_1d_array x, - ae_int_t n, - double e, - double& bothtails, - double& lefttail, - double& righttail, - const xparams _params = alglib::xdefault); - -
- - - -
-
/************************************************************************* - -*************************************************************************/ -
class xdebugrecord1 -{ - ae_int_t i; - alglib::complex c; - real_1d_array a; -}; - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Appends copy of array to itself. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugb1appendcopy( - boolean_1d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Counts number of True values in the boolean 1D array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::xdebugb1count( - boolean_1d_array a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by NOT(a[i]). -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugb1not( - boolean_1d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate N-element array with even-numbered elements set to True. -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugb1outeven( - ae_int_t n, - boolean_1d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Counts number of True values in the boolean 2D array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::xdebugb2count( - boolean_2d_array a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by NOT(a[i]). -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugb2not( - boolean_2d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate MxN matrix with elements set to "Sin(3*I+5*J)>0" -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugb2outsin( - ae_int_t m, - ae_int_t n, - boolean_2d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Transposes array. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugb2transpose( - boolean_2d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Appends copy of array to itself. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugc1appendcopy( - complex_1d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -A[I] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugc1neg( - complex_1d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate N-element array with even-numbered A[K] set to (x,y) = (K*0.25, K*0.125) -and odd-numbered ones are set to 0. - -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugc1outeven( - ae_int_t n, - complex_1d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
alglib::complex alglib::xdebugc1sum( - complex_1d_array a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -a[i,j] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugc2neg( - complex_2d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate MxN matrix with elements set to "Sin(3*I+5*J),Cos(3*I+5*J)" -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugc2outsincos( - ae_int_t m, - ae_int_t n, - complex_2d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
alglib::complex alglib::xdebugc2sum( - complex_2d_array a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Transposes array. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugc2transpose( - complex_2d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Appends copy of array to itself. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugi1appendcopy( - integer_1d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -A[I] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugi1neg( - integer_1d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate N-element array with even-numbered A[I] set to I, and odd-numbered -ones set to 0. - -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugi1outeven( - ae_int_t n, - integer_1d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::xdebugi1sum( - integer_1d_array a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -a[i,j] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugi2neg( - integer_2d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate MxN matrix with elements set to "Sign(Sin(3*I+5*J))" -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugi2outsin( - ae_int_t m, - ae_int_t n, - integer_2d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
ae_int_t alglib::xdebugi2sum( - integer_2d_array a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Transposes array. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugi2transpose( - integer_2d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Creates and returns XDebugRecord1 structure: -* integer and complex fields of Rec1 are set to 1 and 1+i correspondingly -* array field of Rec1 is set to [2,3] - - -- ALGLIB -- - Copyright 27.05.2014 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebuginitrecord1( - xdebugrecord1& rec1, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of a[i,j]*(1+b[i,j]) such that c[i,j] is True - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
double alglib::xdebugmaskedbiasedproductsum( - ae_int_t m, - ae_int_t n, - real_2d_array a, - real_2d_array b, - boolean_2d_array c, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Appends copy of array to itself. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugr1appendcopy( - real_1d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -A[I] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugr1neg( - real_1d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate N-element array with even-numbered A[I] set to I*0.25, -and odd-numbered ones are set to 0. - -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugr1outeven( - ae_int_t n, - real_1d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
double alglib::xdebugr1sum( - real_1d_array a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -a[i,j] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugr2neg( - real_2d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate MxN matrix with elements set to "Sin(3*I+5*J)" -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugr2outsin( - ae_int_t m, - ae_int_t n, - real_2d_array& a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
double alglib::xdebugr2sum( - real_2d_array a, - const xparams _params = alglib::xdefault); - -
- -
-
/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Transposes array. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -
void alglib::xdebugr2transpose( - real_2d_array& a, - const xparams _params = alglib::xdefault); - -
- - - \ No newline at end of file diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/alglibinternal.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/alglibinternal.cpp deleted file mode 100644 index b3301f1..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/alglibinternal.cpp +++ /dev/null @@ -1,18597 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifdef _MSC_VER -#define _CRT_SECURE_NO_WARNINGS -#endif -#include "stdafx.h" -#include "alglibinternal.h" - -// disable some irrelevant warnings -#if (AE_COMPILER==AE_MSVC) && !defined(AE_ALL_WARNINGS) -#pragma warning(disable:4100) -#pragma warning(disable:4127) -#pragma warning(disable:4611) -#pragma warning(disable:4702) -#pragma warning(disable:4996) -#endif - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - - -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF COMPUTATIONAL CORE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_SCODES) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_APSERV) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_TSORT) || !defined(AE_PARTIAL_BUILD) -static void tsort_tagsortfastirec(/* Real */ ae_vector* a, - /* Integer */ ae_vector* b, - /* Real */ ae_vector* bufa, - /* Integer */ ae_vector* bufb, - ae_int_t i1, - ae_int_t i2, - ae_state *_state); -static void tsort_tagsortfastrrec(/* Real */ ae_vector* a, - /* Real */ ae_vector* b, - /* Real */ ae_vector* bufa, - /* Real */ ae_vector* bufb, - ae_int_t i1, - ae_int_t i2, - ae_state *_state); -static void tsort_tagsortfastrec(/* Real */ ae_vector* a, - /* Real */ ae_vector* bufa, - ae_int_t i1, - ae_int_t i2, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_ABLASF) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_ABLASMKL) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_CREFLECTIONS) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_ROTATIONS) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_TRLINSOLVE) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_SAFESOLVE) || !defined(AE_PARTIAL_BUILD) -static ae_bool safesolve_cbasicsolveandupdate(ae_complex alpha, - ae_complex beta, - double lnmax, - double bnorm, - double maxgrowth, - double* xnorm, - ae_complex* x, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_HBLAS) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_SBLAS) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_BLAS) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_LINMIN) || !defined(AE_PARTIAL_BUILD) -static double linmin_ftol = 0.001; -static double linmin_xtol = 100*ae_machineepsilon; -static ae_int_t linmin_maxfev = 20; -static double linmin_stpmin = 1.0E-50; -static double linmin_defstpmax = 1.0E+50; -static double linmin_armijofactor = 1.3; -static void linmin_mcstep(double* stx, - double* fx, - double* dx, - double* sty, - double* fy, - double* dy, - double* stp, - double fp, - double dp, - ae_bool* brackt, - double stmin, - double stmax, - ae_int_t* info, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_XBLAS) || !defined(AE_PARTIAL_BUILD) -static void xblas_xsum(/* Real */ ae_vector* w, - double mx, - ae_int_t n, - double* r, - double* rerr, - ae_state *_state); -static double xblas_xfastpow(double r, ae_int_t n, ae_state *_state); - - -#endif -#if defined(AE_COMPILE_BASICSTATOPS) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_HPCCORES) || !defined(AE_PARTIAL_BUILD) -static ae_bool hpccores_hpcpreparechunkedgradientx(/* Real */ ae_vector* weights, - ae_int_t wcount, - /* Real */ ae_vector* hpcbuf, - ae_state *_state); -static ae_bool hpccores_hpcfinalizechunkedgradientx(/* Real */ ae_vector* buf, - ae_int_t wcount, - /* Real */ ae_vector* grad, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_NTHEORY) || !defined(AE_PARTIAL_BUILD) -static ae_bool ntheory_isprime(ae_int_t n, ae_state *_state); -static ae_int_t ntheory_modmul(ae_int_t a, - ae_int_t b, - ae_int_t n, - ae_state *_state); -static ae_int_t ntheory_modexp(ae_int_t a, - ae_int_t b, - ae_int_t n, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_FTBASE) || !defined(AE_PARTIAL_BUILD) -static ae_int_t ftbase_coltype = 0; -static ae_int_t ftbase_coloperandscnt = 1; -static ae_int_t ftbase_coloperandsize = 2; -static ae_int_t ftbase_colmicrovectorsize = 3; -static ae_int_t ftbase_colparam0 = 4; -static ae_int_t ftbase_colparam1 = 5; -static ae_int_t ftbase_colparam2 = 6; -static ae_int_t ftbase_colparam3 = 7; -static ae_int_t ftbase_colscnt = 8; -static ae_int_t ftbase_opend = 0; -static ae_int_t ftbase_opcomplexreffft = 1; -static ae_int_t ftbase_opbluesteinsfft = 2; -static ae_int_t ftbase_opcomplexcodeletfft = 3; -static ae_int_t ftbase_opcomplexcodelettwfft = 4; -static ae_int_t ftbase_opradersfft = 5; -static ae_int_t ftbase_opcomplextranspose = -1; -static ae_int_t ftbase_opcomplexfftfactors = -2; -static ae_int_t ftbase_opstart = -3; -static ae_int_t ftbase_opjmp = -4; -static ae_int_t ftbase_opparallelcall = -5; -static ae_int_t ftbase_maxradix = 6; -static ae_int_t ftbase_updatetw = 16; -static ae_int_t ftbase_recursivethreshold = 1024; -static ae_int_t ftbase_raderthreshold = 19; -static ae_int_t ftbase_ftbasecodeletrecommended = 5; -static double ftbase_ftbaseinefficiencyfactor = 1.3; -static ae_int_t ftbase_ftbasemaxsmoothfactor = 5; -static void ftbase_ftdeterminespacerequirements(ae_int_t n, - ae_int_t* precrsize, - ae_int_t* precisize, - ae_state *_state); -static void ftbase_ftcomplexfftplanrec(ae_int_t n, - ae_int_t k, - ae_bool childplan, - ae_bool topmostplan, - ae_int_t* rowptr, - ae_int_t* bluesteinsize, - ae_int_t* precrptr, - ae_int_t* preciptr, - fasttransformplan* plan, - ae_state *_state); -static void ftbase_ftpushentry(fasttransformplan* plan, - ae_int_t* rowptr, - ae_int_t etype, - ae_int_t eopcnt, - ae_int_t eopsize, - ae_int_t emcvsize, - ae_int_t eparam0, - ae_state *_state); -static void ftbase_ftpushentry2(fasttransformplan* plan, - ae_int_t* rowptr, - ae_int_t etype, - ae_int_t eopcnt, - ae_int_t eopsize, - ae_int_t emcvsize, - ae_int_t eparam0, - ae_int_t eparam1, - ae_state *_state); -static void ftbase_ftpushentry4(fasttransformplan* plan, - ae_int_t* rowptr, - ae_int_t etype, - ae_int_t eopcnt, - ae_int_t eopsize, - ae_int_t emcvsize, - ae_int_t eparam0, - ae_int_t eparam1, - ae_int_t eparam2, - ae_int_t eparam3, - ae_state *_state); -static void ftbase_ftapplysubplan(fasttransformplan* plan, - ae_int_t subplan, - /* Real */ ae_vector* a, - ae_int_t abase, - ae_int_t aoffset, - /* Real */ ae_vector* buf, - ae_int_t repcnt, - ae_state *_state); -static void ftbase_ftapplycomplexreffft(/* Real */ ae_vector* a, - ae_int_t offs, - ae_int_t operandscnt, - ae_int_t operandsize, - ae_int_t microvectorsize, - /* Real */ ae_vector* buf, - ae_state *_state); -static void ftbase_ftapplycomplexcodeletfft(/* Real */ ae_vector* a, - ae_int_t offs, - ae_int_t operandscnt, - ae_int_t operandsize, - ae_int_t microvectorsize, - ae_state *_state); -static void ftbase_ftapplycomplexcodelettwfft(/* Real */ ae_vector* a, - ae_int_t offs, - ae_int_t operandscnt, - ae_int_t operandsize, - ae_int_t microvectorsize, - ae_state *_state); -static void ftbase_ftprecomputebluesteinsfft(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* precr, - ae_int_t offs, - ae_state *_state); -static void ftbase_ftbluesteinsfft(fasttransformplan* plan, - /* Real */ ae_vector* a, - ae_int_t abase, - ae_int_t aoffset, - ae_int_t operandscnt, - ae_int_t n, - ae_int_t m, - ae_int_t precoffs, - ae_int_t subplan, - /* Real */ ae_vector* bufa, - /* Real */ ae_vector* bufb, - /* Real */ ae_vector* bufc, - /* Real */ ae_vector* bufd, - ae_state *_state); -static void ftbase_ftprecomputeradersfft(ae_int_t n, - ae_int_t rq, - ae_int_t riq, - /* Real */ ae_vector* precr, - ae_int_t offs, - ae_state *_state); -static void ftbase_ftradersfft(fasttransformplan* plan, - /* Real */ ae_vector* a, - ae_int_t abase, - ae_int_t aoffset, - ae_int_t operandscnt, - ae_int_t n, - ae_int_t subplan, - ae_int_t rq, - ae_int_t riq, - ae_int_t precoffs, - /* Real */ ae_vector* buf, - ae_state *_state); -static void ftbase_ftfactorize(ae_int_t n, - ae_bool isroot, - ae_int_t* n1, - ae_int_t* n2, - ae_state *_state); -static ae_int_t ftbase_ftoptimisticestimate(ae_int_t n, ae_state *_state); -static void ftbase_ffttwcalc(/* Real */ ae_vector* a, - ae_int_t aoffset, - ae_int_t n1, - ae_int_t n2, - ae_state *_state); -static void ftbase_internalcomplexlintranspose(/* Real */ ae_vector* a, - ae_int_t m, - ae_int_t n, - ae_int_t astart, - /* Real */ ae_vector* buf, - ae_state *_state); -static void ftbase_ffticltrec(/* Real */ ae_vector* a, - ae_int_t astart, - ae_int_t astride, - /* Real */ ae_vector* b, - ae_int_t bstart, - ae_int_t bstride, - ae_int_t m, - ae_int_t n, - ae_state *_state); -static void ftbase_fftirltrec(/* Real */ ae_vector* a, - ae_int_t astart, - ae_int_t astride, - /* Real */ ae_vector* b, - ae_int_t bstart, - ae_int_t bstride, - ae_int_t m, - ae_int_t n, - ae_state *_state); -static void ftbase_ftbasefindsmoothrec(ae_int_t n, - ae_int_t seed, - ae_int_t leastfactor, - ae_int_t* best, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_NEARUNITYUNIT) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_ALGLIBBASICS) || !defined(AE_PARTIAL_BUILD) - - -#endif - -#if defined(AE_COMPILE_SCODES) || !defined(AE_PARTIAL_BUILD) - - -ae_int_t getrdfserializationcode(ae_state *_state) -{ - ae_int_t result; - - - result = 1; - return result; -} - - -ae_int_t getkdtreeserializationcode(ae_state *_state) -{ - ae_int_t result; - - - result = 2; - return result; -} - - -ae_int_t getmlpserializationcode(ae_state *_state) -{ - ae_int_t result; - - - result = 3; - return result; -} - - -ae_int_t getmlpeserializationcode(ae_state *_state) -{ - ae_int_t result; - - - result = 4; - return result; -} - - -ae_int_t getrbfserializationcode(ae_state *_state) -{ - ae_int_t result; - - - result = 5; - return result; -} - - -ae_int_t getspline2dserializationcode(ae_state *_state) -{ - ae_int_t result; - - - result = 6; - return result; -} - - -ae_int_t getidwserializationcode(ae_state *_state) -{ - ae_int_t result; - - - result = 7; - return result; -} - - -ae_int_t getknnserializationcode(ae_state *_state) -{ - ae_int_t result; - - - result = 108; - return result; -} - - -#endif -#if defined(AE_COMPILE_APSERV) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Internally calls SetErrorFlag() with condition: - - Abs(Val-RefVal)>Tol*Max(Abs(RefVal),S) - -This function is used to test relative error in Val against RefVal, with -relative error being replaced by absolute when scale of RefVal is less -than S. - -This function returns value of COND. -*************************************************************************/ -void seterrorflagdiff(ae_bool* flag, - double val, - double refval, - double tol, - double s, - ae_state *_state) -{ - - - ae_set_error_flag(flag, ae_fp_greater(ae_fabs(val-refval, _state),tol*ae_maxreal(ae_fabs(refval, _state), s, _state)), __FILE__, __LINE__, "apserv.ap:162"); -} - - -/************************************************************************* -The function always returns False. -It may be used sometimes to prevent spurious warnings. - - -- ALGLIB -- - Copyright 17.09.2012 by Bochkanov Sergey -*************************************************************************/ -ae_bool alwaysfalse(ae_state *_state) -{ - ae_bool result; - - - result = ae_false; - return result; -} - - -/************************************************************************* -The function "touches" integer - it is used to avoid compiler messages -about unused variables (in rare cases when we do NOT want to remove these -variables). - - -- ALGLIB -- - Copyright 17.09.2012 by Bochkanov Sergey -*************************************************************************/ -void touchint(ae_int_t* a, ae_state *_state) -{ - - -} - - -/************************************************************************* -The function "touches" real - it is used to avoid compiler messages -about unused variables (in rare cases when we do NOT want to remove these -variables). - - -- ALGLIB -- - Copyright 17.09.2012 by Bochkanov Sergey -*************************************************************************/ -void touchreal(double* a, ae_state *_state) -{ - - -} - - -/************************************************************************* -The function performs zero-coalescing on real value. - -NOTE: no check is performed for B<>0 - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -double coalesce(double a, double b, ae_state *_state) -{ - double result; - - - result = a; - if( ae_fp_eq(a,0.0) ) - { - result = b; - } - return result; -} - - -/************************************************************************* -The function performs zero-coalescing on integer value. - -NOTE: no check is performed for B<>0 - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -ae_int_t coalescei(ae_int_t a, ae_int_t b, ae_state *_state) -{ - ae_int_t result; - - - result = a; - if( a==0 ) - { - result = b; - } - return result; -} - - -/************************************************************************* -The function convert integer value to real value. - - -- ALGLIB -- - Copyright 17.09.2012 by Bochkanov Sergey -*************************************************************************/ -double inttoreal(ae_int_t a, ae_state *_state) -{ - double result; - - - result = (double)(a); - return result; -} - - -/************************************************************************* -The function calculates binary logarithm. - -NOTE: it costs twice as much as Ln(x) - - -- ALGLIB -- - Copyright 17.09.2012 by Bochkanov Sergey -*************************************************************************/ -double logbase2(double x, ae_state *_state) -{ - double result; - - - result = ae_log(x, _state)/ae_log((double)(2), _state); - return result; -} - - -/************************************************************************* -This function compares two numbers for approximate equality, with tolerance -to errors as large as tol. - - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -ae_bool approxequal(double a, double b, double tol, ae_state *_state) -{ - ae_bool result; - - - result = ae_fp_less_eq(ae_fabs(a-b, _state),tol); - return result; -} - - -/************************************************************************* -This function compares two numbers for approximate equality, with tolerance -to errors as large as max(|a|,|b|)*tol. - - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -ae_bool approxequalrel(double a, double b, double tol, ae_state *_state) -{ - ae_bool result; - - - result = ae_fp_less_eq(ae_fabs(a-b, _state),ae_maxreal(ae_fabs(a, _state), ae_fabs(b, _state), _state)*tol); - return result; -} - - -/************************************************************************* -This function generates 1-dimensional general interpolation task with -moderate Lipshitz constant (close to 1.0) - -If N=1 then suborutine generates only one point at the middle of [A,B] - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void taskgenint1d(double a, - double b, - ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - double h; - - ae_vector_clear(x); - ae_vector_clear(y); - - ae_assert(n>=1, "TaskGenInterpolationEqdist1D: N<1!", _state); - ae_vector_set_length(x, n, _state); - ae_vector_set_length(y, n, _state); - if( n>1 ) - { - x->ptr.p_double[0] = a; - y->ptr.p_double[0] = 2*ae_randomreal(_state)-1; - h = (b-a)/(n-1); - for(i=1; i<=n-1; i++) - { - if( i!=n-1 ) - { - x->ptr.p_double[i] = a+(i+0.2*(2*ae_randomreal(_state)-1))*h; - } - else - { - x->ptr.p_double[i] = b; - } - y->ptr.p_double[i] = y->ptr.p_double[i-1]+(2*ae_randomreal(_state)-1)*(x->ptr.p_double[i]-x->ptr.p_double[i-1]); - } - } - else - { - x->ptr.p_double[0] = 0.5*(a+b); - y->ptr.p_double[0] = 2*ae_randomreal(_state)-1; - } -} - - -/************************************************************************* -This function generates 1-dimensional equidistant interpolation task with -moderate Lipshitz constant (close to 1.0) - -If N=1 then suborutine generates only one point at the middle of [A,B] - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void taskgenint1dequidist(double a, - double b, - ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - double h; - - ae_vector_clear(x); - ae_vector_clear(y); - - ae_assert(n>=1, "TaskGenInterpolationEqdist1D: N<1!", _state); - ae_vector_set_length(x, n, _state); - ae_vector_set_length(y, n, _state); - if( n>1 ) - { - x->ptr.p_double[0] = a; - y->ptr.p_double[0] = 2*ae_randomreal(_state)-1; - h = (b-a)/(n-1); - for(i=1; i<=n-1; i++) - { - x->ptr.p_double[i] = a+i*h; - y->ptr.p_double[i] = y->ptr.p_double[i-1]+(2*ae_randomreal(_state)-1)*h; - } - } - else - { - x->ptr.p_double[0] = 0.5*(a+b); - y->ptr.p_double[0] = 2*ae_randomreal(_state)-1; - } -} - - -/************************************************************************* -This function generates 1-dimensional Chebyshev-1 interpolation task with -moderate Lipshitz constant (close to 1.0) - -If N=1 then suborutine generates only one point at the middle of [A,B] - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void taskgenint1dcheb1(double a, - double b, - ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - - ae_vector_clear(x); - ae_vector_clear(y); - - ae_assert(n>=1, "TaskGenInterpolation1DCheb1: N<1!", _state); - ae_vector_set_length(x, n, _state); - ae_vector_set_length(y, n, _state); - if( n>1 ) - { - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = 0.5*(b+a)+0.5*(b-a)*ae_cos(ae_pi*(2*i+1)/(2*n), _state); - if( i==0 ) - { - y->ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - else - { - y->ptr.p_double[i] = y->ptr.p_double[i-1]+(2*ae_randomreal(_state)-1)*(x->ptr.p_double[i]-x->ptr.p_double[i-1]); - } - } - } - else - { - x->ptr.p_double[0] = 0.5*(a+b); - y->ptr.p_double[0] = 2*ae_randomreal(_state)-1; - } -} - - -/************************************************************************* -This function generates 1-dimensional Chebyshev-2 interpolation task with -moderate Lipshitz constant (close to 1.0) - -If N=1 then suborutine generates only one point at the middle of [A,B] - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void taskgenint1dcheb2(double a, - double b, - ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - - ae_vector_clear(x); - ae_vector_clear(y); - - ae_assert(n>=1, "TaskGenInterpolation1DCheb2: N<1!", _state); - ae_vector_set_length(x, n, _state); - ae_vector_set_length(y, n, _state); - if( n>1 ) - { - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = 0.5*(b+a)+0.5*(b-a)*ae_cos(ae_pi*i/(n-1), _state); - if( i==0 ) - { - y->ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - else - { - y->ptr.p_double[i] = y->ptr.p_double[i-1]+(2*ae_randomreal(_state)-1)*(x->ptr.p_double[i]-x->ptr.p_double[i-1]); - } - } - } - else - { - x->ptr.p_double[0] = 0.5*(a+b); - y->ptr.p_double[0] = 2*ae_randomreal(_state)-1; - } -} - - -/************************************************************************* -This function checks that all values from X[] are distinct. It does more -than just usual floating point comparison: -* first, it calculates max(X) and min(X) -* second, it maps X[] from [min,max] to [1,2] -* only at this stage actual comparison is done - -The meaning of such check is to ensure that all values are "distinct enough" -and will not cause interpolation subroutine to fail. - -NOTE: - X[] must be sorted by ascending (subroutine ASSERT's it) - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -ae_bool aredistinct(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state) -{ - double a; - double b; - ae_int_t i; - ae_bool nonsorted; - ae_bool result; - - - ae_assert(n>=1, "APSERVAreDistinct: internal error (N<1)", _state); - if( n==1 ) - { - - /* - * everything is alright, it is up to caller to decide whether it - * can interpolate something with just one point - */ - result = ae_true; - return result; - } - a = x->ptr.p_double[0]; - b = x->ptr.p_double[0]; - nonsorted = ae_false; - for(i=1; i<=n-1; i++) - { - a = ae_minreal(a, x->ptr.p_double[i], _state); - b = ae_maxreal(b, x->ptr.p_double[i], _state); - nonsorted = nonsorted||ae_fp_greater_eq(x->ptr.p_double[i-1],x->ptr.p_double[i]); - } - ae_assert(!nonsorted, "APSERVAreDistinct: internal error (not sorted)", _state); - for(i=1; i<=n-1; i++) - { - if( ae_fp_eq((x->ptr.p_double[i]-a)/(b-a)+1,(x->ptr.p_double[i-1]-a)/(b-a)+1) ) - { - result = ae_false; - return result; - } - } - result = ae_true; - return result; -} - - -/************************************************************************* -This function checks that two boolean values are the same (both are True -or both are False). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -ae_bool aresameboolean(ae_bool v1, ae_bool v2, ae_state *_state) -{ - ae_bool result; - - - result = (v1&&v2)||(!v1&&!v2); - return result; -} - - -/************************************************************************* -Resizes X and fills by zeros - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -void setlengthzero(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(n>=0, "SetLengthZero: N<0", _state); - ae_vector_set_length(x, n, _state); - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = (double)(0); - } -} - - -/************************************************************************* -If Length(X)cntcntcnt0&&n>0 ) - { - if( x->rowscols0&&n>0 ) - { - if( x->rowscolscnt>=n ) - { - ae_frame_leave(_state); - return; - } - - /* - * Choose new size - */ - n = ae_maxint(n, ae_round(1.8*x->cnt+1, _state), _state); - - /* - * Grow - */ - n2 = x->cnt; - ae_swap_vectors(x, &oldx); - ae_vector_set_length(x, n, _state); - for(i=0; i<=n-1; i++) - { - if( iptr.p_bool[i] = oldx.ptr.p_bool[i]; - } - else - { - x->ptr.p_bool[i] = ae_false; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Grows X, i.e. changes its size in such a way that: -a) contents is preserved -b) new size is at least N -c) new size can be larger than N, so subsequent grow() calls can return - without reallocation - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -void ivectorgrowto(/* Integer */ ae_vector* x, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector oldx; - ae_int_t i; - ae_int_t n2; - - ae_frame_make(_state, &_frame_block); - memset(&oldx, 0, sizeof(oldx)); - ae_vector_init(&oldx, 0, DT_INT, _state, ae_true); - - - /* - * Enough place - */ - if( x->cnt>=n ) - { - ae_frame_leave(_state); - return; - } - - /* - * Choose new size - */ - n = ae_maxint(n, ae_round(1.8*x->cnt+1, _state), _state); - - /* - * Grow - */ - n2 = x->cnt; - ae_swap_vectors(x, &oldx); - ae_vector_set_length(x, n, _state); - for(i=0; i<=n-1; i++) - { - if( iptr.p_int[i] = oldx.ptr.p_int[i]; - } - else - { - x->ptr.p_int[i] = 0; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Grows X, i.e. appends rows in such a way that: -a) contents is preserved -b) new row count is at least N -c) new row count can be larger than N, so subsequent grow() calls can return - without reallocation -d) new matrix has at least MinCols columns (if less than specified amount - of columns is present, new columns are added with undefined contents); - MinCols can be 0 or negative value = ignored - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -void rmatrixgrowrowsto(/* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t mincols, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix olda; - ae_int_t i; - ae_int_t j; - ae_int_t n2; - ae_int_t m; - - ae_frame_make(_state, &_frame_block); - memset(&olda, 0, sizeof(olda)); - ae_matrix_init(&olda, 0, 0, DT_REAL, _state, ae_true); - - - /* - * Enough place? - */ - if( a->rows>=n&&a->cols>=mincols ) - { - ae_frame_leave(_state); - return; - } - - /* - * Sizes and metrics - */ - if( a->rowsrows+1, _state), _state); - } - n2 = ae_minint(a->rows, n, _state); - m = a->cols; - - /* - * Grow - */ - ae_swap_matrices(a, &olda); - ae_matrix_set_length(a, n, ae_maxint(m, mincols, _state), _state); - for(i=0; i<=n2-1; i++) - { - for(j=0; j<=m-1; j++) - { - a->ptr.pp_double[i][j] = olda.ptr.pp_double[i][j]; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Grows X, i.e. appends cols in such a way that: -a) contents is preserved -b) new col count is at least N -c) new col count can be larger than N, so subsequent grow() calls can return - without reallocation -d) new matrix has at least MinRows row (if less than specified amount - of rows is present, new rows are added with undefined contents); - MinRows can be 0 or negative value = ignored - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -void rmatrixgrowcolsto(/* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t minrows, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix olda; - ae_int_t i; - ae_int_t j; - ae_int_t n2; - ae_int_t m; - - ae_frame_make(_state, &_frame_block); - memset(&olda, 0, sizeof(olda)); - ae_matrix_init(&olda, 0, 0, DT_REAL, _state, ae_true); - - - /* - * Enough place? - */ - if( a->cols>=n&&a->rows>=minrows ) - { - ae_frame_leave(_state); - return; - } - - /* - * Sizes and metrics - */ - if( a->colscols+1, _state), _state); - } - n2 = ae_minint(a->cols, n, _state); - m = a->rows; - - /* - * Grow - */ - ae_swap_matrices(a, &olda); - ae_matrix_set_length(a, ae_maxint(m, minrows, _state), n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n2-1; j++) - { - a->ptr.pp_double[i][j] = olda.ptr.pp_double[i][j]; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Grows X, i.e. changes its size in such a way that: -a) contents is preserved -b) new size is at least N -c) new size can be larger than N, so subsequent grow() calls can return - without reallocation - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -void rvectorgrowto(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector oldx; - ae_int_t i; - ae_int_t n2; - - ae_frame_make(_state, &_frame_block); - memset(&oldx, 0, sizeof(oldx)); - ae_vector_init(&oldx, 0, DT_REAL, _state, ae_true); - - - /* - * Enough place - */ - if( x->cnt>=n ) - { - ae_frame_leave(_state); - return; - } - - /* - * Choose new size - */ - n = ae_maxint(n, ae_round(1.8*x->cnt+1, _state), _state); - - /* - * Grow - */ - n2 = x->cnt; - ae_swap_vectors(x, &oldx); - ae_vector_set_length(x, n, _state); - for(i=0; i<=n-1; i++) - { - if( iptr.p_double[i] = oldx.ptr.p_double[i]; - } - else - { - x->ptr.p_double[i] = (double)(0); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Resizes X and: -* preserves old contents of X -* fills new elements by zeros - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -void ivectorresize(/* Integer */ ae_vector* x, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector oldx; - ae_int_t i; - ae_int_t n2; - - ae_frame_make(_state, &_frame_block); - memset(&oldx, 0, sizeof(oldx)); - ae_vector_init(&oldx, 0, DT_INT, _state, ae_true); - - n2 = x->cnt; - ae_swap_vectors(x, &oldx); - ae_vector_set_length(x, n, _state); - for(i=0; i<=n-1; i++) - { - if( iptr.p_int[i] = oldx.ptr.p_int[i]; - } - else - { - x->ptr.p_int[i] = 0; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Resizes X and: -* preserves old contents of X -* fills new elements by zeros - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -void rvectorresize(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector oldx; - ae_int_t i; - ae_int_t n2; - - ae_frame_make(_state, &_frame_block); - memset(&oldx, 0, sizeof(oldx)); - ae_vector_init(&oldx, 0, DT_REAL, _state, ae_true); - - n2 = x->cnt; - ae_swap_vectors(x, &oldx); - ae_vector_set_length(x, n, _state); - for(i=0; i<=n-1; i++) - { - if( iptr.p_double[i] = oldx.ptr.p_double[i]; - } - else - { - x->ptr.p_double[i] = (double)(0); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Resizes X and: -* preserves old contents of X -* fills new elements by zeros - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -void rmatrixresize(/* Real */ ae_matrix* x, - ae_int_t m, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix oldx; - ae_int_t i; - ae_int_t j; - ae_int_t m2; - ae_int_t n2; - - ae_frame_make(_state, &_frame_block); - memset(&oldx, 0, sizeof(oldx)); - ae_matrix_init(&oldx, 0, 0, DT_REAL, _state, ae_true); - - m2 = x->rows; - n2 = x->cols; - ae_swap_matrices(x, &oldx); - ae_matrix_set_length(x, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( iptr.pp_double[i][j] = oldx.ptr.pp_double[i][j]; - } - else - { - x->ptr.pp_double[i][j] = 0.0; - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Resizes X and: -* preserves old contents of X -* fills new elements by zeros - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -void imatrixresize(/* Integer */ ae_matrix* x, - ae_int_t m, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix oldx; - ae_int_t i; - ae_int_t j; - ae_int_t m2; - ae_int_t n2; - - ae_frame_make(_state, &_frame_block); - memset(&oldx, 0, sizeof(oldx)); - ae_matrix_init(&oldx, 0, 0, DT_INT, _state, ae_true); - - m2 = x->rows; - n2 = x->cols; - ae_swap_matrices(x, &oldx); - ae_matrix_set_length(x, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( iptr.pp_int[i][j] = oldx.ptr.pp_int[i][j]; - } - else - { - x->ptr.pp_int[i][j] = 0; - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -appends element to X - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -void ivectorappend(/* Integer */ ae_vector* x, - ae_int_t v, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector oldx; - ae_int_t i; - ae_int_t n; - - ae_frame_make(_state, &_frame_block); - memset(&oldx, 0, sizeof(oldx)); - ae_vector_init(&oldx, 0, DT_INT, _state, ae_true); - - n = x->cnt; - ae_swap_vectors(x, &oldx); - ae_vector_set_length(x, n+1, _state); - for(i=0; i<=n-1; i++) - { - x->ptr.p_int[i] = oldx.ptr.p_int[i]; - } - x->ptr.p_int[n] = v; - ae_frame_leave(_state); -} - - -/************************************************************************* -This function checks that length(X) is at least N and first N values from -X[] are finite - - -- ALGLIB -- - Copyright 18.06.2010 by Bochkanov Sergey -*************************************************************************/ -ae_bool isfinitevector(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - double v; - ae_bool result; - - - ae_assert(n>=0, "APSERVIsFiniteVector: internal error (N<0)", _state); - if( n==0 ) - { - result = ae_true; - return result; - } - if( x->cntptr.p_double[i]; - } - result = ae_isfinite(v, _state); - return result; -} - - -/************************************************************************* -This function checks that first N values from X[] are finite - - -- ALGLIB -- - Copyright 18.06.2010 by Bochkanov Sergey -*************************************************************************/ -ae_bool isfinitecvector(/* Complex */ ae_vector* z, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_bool result; - - - ae_assert(n>=0, "APSERVIsFiniteCVector: internal error (N<0)", _state); - for(i=0; i<=n-1; i++) - { - if( !ae_isfinite(z->ptr.p_complex[i].x, _state)||!ae_isfinite(z->ptr.p_complex[i].y, _state) ) - { - result = ae_false; - return result; - } - } - result = ae_true; - return result; -} - - -/************************************************************************* -This function checks that size of X is at least MxN and values from -X[0..M-1,0..N-1] are finite. - - -- ALGLIB -- - Copyright 18.06.2010 by Bochkanov Sergey -*************************************************************************/ -ae_bool apservisfinitematrix(/* Real */ ae_matrix* x, - ae_int_t m, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_bool result; - - - ae_assert(n>=0, "APSERVIsFiniteMatrix: internal error (N<0)", _state); - ae_assert(m>=0, "APSERVIsFiniteMatrix: internal error (M<0)", _state); - if( m==0||n==0 ) - { - result = ae_true; - return result; - } - if( x->rowscolsptr.pp_double[i][j], _state) ) - { - result = ae_false; - return result; - } - } - } - result = ae_true; - return result; -} - - -/************************************************************************* -This function checks that all values from X[0..M-1,0..N-1] are finite - - -- ALGLIB -- - Copyright 18.06.2010 by Bochkanov Sergey -*************************************************************************/ -ae_bool apservisfinitecmatrix(/* Complex */ ae_matrix* x, - ae_int_t m, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_bool result; - - - ae_assert(n>=0, "APSERVIsFiniteCMatrix: internal error (N<0)", _state); - ae_assert(m>=0, "APSERVIsFiniteCMatrix: internal error (M<0)", _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( !ae_isfinite(x->ptr.pp_complex[i][j].x, _state)||!ae_isfinite(x->ptr.pp_complex[i][j].y, _state) ) - { - result = ae_false; - return result; - } - } - } - result = ae_true; - return result; -} - - -/************************************************************************* -This function checks that size of X is at least NxN and all values from -upper/lower triangle of X[0..N-1,0..N-1] are finite - - -- ALGLIB -- - Copyright 18.06.2010 by Bochkanov Sergey -*************************************************************************/ -ae_bool isfinitertrmatrix(/* Real */ ae_matrix* x, - ae_int_t n, - ae_bool isupper, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j1; - ae_int_t j2; - ae_int_t j; - ae_bool result; - - - ae_assert(n>=0, "APSERVIsFiniteRTRMatrix: internal error (N<0)", _state); - if( n==0 ) - { - result = ae_true; - return result; - } - if( x->rowscolsptr.pp_double[i][j], _state) ) - { - result = ae_false; - return result; - } - } - } - result = ae_true; - return result; -} - - -/************************************************************************* -This function checks that all values from upper/lower triangle of -X[0..N-1,0..N-1] are finite - - -- ALGLIB -- - Copyright 18.06.2010 by Bochkanov Sergey -*************************************************************************/ -ae_bool apservisfinitectrmatrix(/* Complex */ ae_matrix* x, - ae_int_t n, - ae_bool isupper, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j1; - ae_int_t j2; - ae_int_t j; - ae_bool result; - - - ae_assert(n>=0, "APSERVIsFiniteCTRMatrix: internal error (N<0)", _state); - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j1 = i; - j2 = n-1; - } - else - { - j1 = 0; - j2 = i; - } - for(j=j1; j<=j2; j++) - { - if( !ae_isfinite(x->ptr.pp_complex[i][j].x, _state)||!ae_isfinite(x->ptr.pp_complex[i][j].y, _state) ) - { - result = ae_false; - return result; - } - } - } - result = ae_true; - return result; -} - - -/************************************************************************* -This function checks that all values from X[0..M-1,0..N-1] are finite or -NaN's. - - -- ALGLIB -- - Copyright 18.06.2010 by Bochkanov Sergey -*************************************************************************/ -ae_bool apservisfiniteornanmatrix(/* Real */ ae_matrix* x, - ae_int_t m, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_bool result; - - - ae_assert(n>=0, "APSERVIsFiniteOrNaNMatrix: internal error (N<0)", _state); - ae_assert(m>=0, "APSERVIsFiniteOrNaNMatrix: internal error (M<0)", _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( !(ae_isfinite(x->ptr.pp_double[i][j], _state)||ae_isnan(x->ptr.pp_double[i][j], _state)) ) - { - result = ae_false; - return result; - } - } - } - result = ae_true; - return result; -} - - -/************************************************************************* -Safe sqrt(x^2+y^2) - - -- ALGLIB -- - Copyright by Bochkanov Sergey -*************************************************************************/ -double safepythag2(double x, double y, ae_state *_state) -{ - double w; - double xabs; - double yabs; - double z; - double result; - - - xabs = ae_fabs(x, _state); - yabs = ae_fabs(y, _state); - w = ae_maxreal(xabs, yabs, _state); - z = ae_minreal(xabs, yabs, _state); - if( ae_fp_eq(z,(double)(0)) ) - { - result = w; - } - else - { - result = w*ae_sqrt(1+ae_sqr(z/w, _state), _state); - } - return result; -} - - -/************************************************************************* -Safe sqrt(x^2+y^2) - - -- ALGLIB -- - Copyright by Bochkanov Sergey -*************************************************************************/ -double safepythag3(double x, double y, double z, ae_state *_state) -{ - double w; - double result; - - - w = ae_maxreal(ae_fabs(x, _state), ae_maxreal(ae_fabs(y, _state), ae_fabs(z, _state), _state), _state); - if( ae_fp_eq(w,(double)(0)) ) - { - result = (double)(0); - return result; - } - x = x/w; - y = y/w; - z = z/w; - result = w*ae_sqrt(ae_sqr(x, _state)+ae_sqr(y, _state)+ae_sqr(z, _state), _state); - return result; -} - - -/************************************************************************* -Safe division. - -This function attempts to calculate R=X/Y without overflow. - -It returns: -* +1, if abs(X/Y)>=MaxRealNumber or undefined - overflow-like situation - (no overlfow is generated, R is either NAN, PosINF, NegINF) -* 0, if MinRealNumber0 - (R contains result, may be zero) -* -1, if 00 - */ - if( ae_fp_eq(y,(double)(0)) ) - { - result = 1; - if( ae_fp_eq(x,(double)(0)) ) - { - *r = _state->v_nan; - } - if( ae_fp_greater(x,(double)(0)) ) - { - *r = _state->v_posinf; - } - if( ae_fp_less(x,(double)(0)) ) - { - *r = _state->v_neginf; - } - return result; - } - if( ae_fp_eq(x,(double)(0)) ) - { - *r = (double)(0); - result = 0; - return result; - } - - /* - * make Y>0 - */ - if( ae_fp_less(y,(double)(0)) ) - { - x = -x; - y = -y; - } - - /* - * - */ - if( ae_fp_greater_eq(y,(double)(1)) ) - { - *r = x/y; - if( ae_fp_less_eq(ae_fabs(*r, _state),ae_minrealnumber) ) - { - result = -1; - *r = (double)(0); - } - else - { - result = 0; - } - } - else - { - if( ae_fp_greater_eq(ae_fabs(x, _state),ae_maxrealnumber*y) ) - { - if( ae_fp_greater(x,(double)(0)) ) - { - *r = _state->v_posinf; - } - else - { - *r = _state->v_neginf; - } - result = 1; - } - else - { - *r = x/y; - result = 0; - } - } - return result; -} - - -/************************************************************************* -This function calculates "safe" min(X/Y,V) for positive finite X, Y, V. -No overflow is generated in any case. - - -- ALGLIB -- - Copyright by Bochkanov Sergey -*************************************************************************/ -double safeminposrv(double x, double y, double v, ae_state *_state) -{ - double r; - double result; - - - if( ae_fp_greater_eq(y,(double)(1)) ) - { - - /* - * Y>=1, we can safely divide by Y - */ - r = x/y; - result = v; - if( ae_fp_greater(v,r) ) - { - result = r; - } - else - { - result = v; - } - } - else - { - - /* - * Y<1, we can safely multiply by Y - */ - if( ae_fp_less(x,v*y) ) - { - result = x/y; - } - else - { - result = v; - } - } - return result; -} - - -/************************************************************************* -This function makes periodic mapping of X to [A,B]. - -It accepts X, A, B (A>B). It returns T which lies in [A,B] and integer K, -such that X = T + K*(B-A). - -NOTES: -* K is represented as real value, although actually it is integer -* T is guaranteed to be in [A,B] -* T replaces X - - -- ALGLIB -- - Copyright by Bochkanov Sergey -*************************************************************************/ -void apperiodicmap(double* x, - double a, - double b, - double* k, - ae_state *_state) -{ - - *k = 0; - - ae_assert(ae_fp_less(a,b), "APPeriodicMap: internal error!", _state); - *k = (double)(ae_ifloor((*x-a)/(b-a), _state)); - *x = *x-*k*(b-a); - while(ae_fp_less(*x,a)) - { - *x = *x+(b-a); - *k = *k-1; - } - while(ae_fp_greater(*x,b)) - { - *x = *x-(b-a); - *k = *k+1; - } - *x = ae_maxreal(*x, a, _state); - *x = ae_minreal(*x, b, _state); -} - - -/************************************************************************* -Returns random normal number using low-quality system-provided generator - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -double randomnormal(ae_state *_state) -{ - double u; - double v; - double s; - double result; - - - for(;;) - { - u = 2*ae_randomreal(_state)-1; - v = 2*ae_randomreal(_state)-1; - s = ae_sqr(u, _state)+ae_sqr(v, _state); - if( ae_fp_greater(s,(double)(0))&&ae_fp_less(s,(double)(1)) ) - { - - /* - * two Sqrt's instead of one to - * avoid overflow when S is too small - */ - s = ae_sqrt(-2*ae_log(s, _state), _state)/ae_sqrt(s, _state); - result = u*s; - break; - } - } - return result; -} - - -/************************************************************************* -Generates random unit vector using low-quality system-provided generator. -Reallocates array if its size is too short. - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -void randomunit(ae_int_t n, /* Real */ ae_vector* x, ae_state *_state) -{ - ae_int_t i; - double v; - double vv; - - - ae_assert(n>0, "RandomUnit: N<=0", _state); - if( x->cntptr.p_double[i] = vv; - v = v+vv*vv; - } - } - while(ae_fp_less_eq(v,(double)(0))); - v = 1/ae_sqrt(v, _state); - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = x->ptr.p_double[i]*v; - } -} - - -/************************************************************************* -This function is used to swap two integer values -*************************************************************************/ -void swapi(ae_int_t* v0, ae_int_t* v1, ae_state *_state) -{ - ae_int_t v; - - - v = *v0; - *v0 = *v1; - *v1 = v; -} - - -/************************************************************************* -This function is used to swap two real values -*************************************************************************/ -void swapr(double* v0, double* v1, ae_state *_state) -{ - double v; - - - v = *v0; - *v0 = *v1; - *v1 = v; -} - - -/************************************************************************* -This function is used to swap two rows of the matrix; if NCols<0, automatically -determined from the matrix size. -*************************************************************************/ -void swaprows(/* Real */ ae_matrix* a, - ae_int_t i0, - ae_int_t i1, - ae_int_t ncols, - ae_state *_state) -{ - ae_int_t j; - double v; - - - if( i0==i1 ) - { - return; - } - if( ncols<0 ) - { - ncols = a->cols; - } - for(j=0; j<=ncols-1; j++) - { - v = a->ptr.pp_double[i0][j]; - a->ptr.pp_double[i0][j] = a->ptr.pp_double[i1][j]; - a->ptr.pp_double[i1][j] = v; - } -} - - -/************************************************************************* -This function is used to swap two cols of the matrix; if NRows<0, automatically -determined from the matrix size. -*************************************************************************/ -void swapcols(/* Real */ ae_matrix* a, - ae_int_t j0, - ae_int_t j1, - ae_int_t nrows, - ae_state *_state) -{ - ae_int_t i; - double v; - - - if( j0==j1 ) - { - return; - } - if( nrows<0 ) - { - nrows = a->rows; - } - for(i=0; i<=nrows-1; i++) - { - v = a->ptr.pp_double[i][j0]; - a->ptr.pp_double[i][j0] = a->ptr.pp_double[i][j1]; - a->ptr.pp_double[i][j1] = v; - } -} - - -/************************************************************************* -This function is used to swap two "entries" in 1-dimensional array composed -from D-element entries -*************************************************************************/ -void swapentries(/* Real */ ae_vector* a, - ae_int_t i0, - ae_int_t i1, - ae_int_t entrywidth, - ae_state *_state) -{ - ae_int_t offs0; - ae_int_t offs1; - ae_int_t j; - double v; - - - if( i0==i1 ) - { - return; - } - offs0 = i0*entrywidth; - offs1 = i1*entrywidth; - for(j=0; j<=entrywidth-1; j++) - { - v = a->ptr.p_double[offs0+j]; - a->ptr.p_double[offs0+j] = a->ptr.p_double[offs1+j]; - a->ptr.p_double[offs1+j] = v; - } -} - - -/************************************************************************* -This function is used to swap two elements of the vector -*************************************************************************/ -void swapelements(/* Real */ ae_vector* a, - ae_int_t i0, - ae_int_t i1, - ae_state *_state) -{ - double v; - - - if( i0==i1 ) - { - return; - } - v = a->ptr.p_double[i0]; - a->ptr.p_double[i0] = a->ptr.p_double[i1]; - a->ptr.p_double[i1] = v; -} - - -/************************************************************************* -This function is used to swap two elements of the vector -*************************************************************************/ -void swapelementsi(/* Integer */ ae_vector* a, - ae_int_t i0, - ae_int_t i1, - ae_state *_state) -{ - ae_int_t v; - - - if( i0==i1 ) - { - return; - } - v = a->ptr.p_int[i0]; - a->ptr.p_int[i0] = a->ptr.p_int[i1]; - a->ptr.p_int[i1] = v; -} - - -/************************************************************************* -This function is used to return maximum of three real values -*************************************************************************/ -double maxreal3(double v0, double v1, double v2, ae_state *_state) -{ - double result; - - - result = v0; - if( ae_fp_less(result,v1) ) - { - result = v1; - } - if( ae_fp_less(result,v2) ) - { - result = v2; - } - return result; -} - - -/************************************************************************* -This function is used to increment value of integer variable -*************************************************************************/ -void inc(ae_int_t* v, ae_state *_state) -{ - - - *v = *v+1; -} - - -/************************************************************************* -This function is used to decrement value of integer variable -*************************************************************************/ -void dec(ae_int_t* v, ae_state *_state) -{ - - - *v = *v-1; -} - - -/************************************************************************* -This function is used to increment value of integer variable; name of the -function suggests that increment is done in multithreaded setting in the -thread-unsafe manner (optional progress reports which do not need guaranteed -correctness) -*************************************************************************/ -void threadunsafeinc(ae_int_t* v, ae_state *_state) -{ - - - *v = *v+1; -} - - -/************************************************************************* -This function is used to increment value of integer variable; name of the -function suggests that increment is done in multithreaded setting in the -thread-unsafe manner (optional progress reports which do not need guaranteed -correctness) -*************************************************************************/ -void threadunsafeincby(ae_int_t* v, ae_int_t k, ae_state *_state) -{ - - - *v = *v+k; -} - - -/************************************************************************* -This function performs two operations: -1. decrements value of integer variable, if it is positive -2. explicitly sets variable to zero if it is non-positive -It is used by some algorithms to decrease value of internal counters. -*************************************************************************/ -void countdown(ae_int_t* v, ae_state *_state) -{ - - - if( *v>0 ) - { - *v = *v-1; - } - else - { - *v = 0; - } -} - - -/************************************************************************* -This function returns +1 or -1 depending on sign of X. -x=0 results in +1 being returned. -*************************************************************************/ -double possign(double x, ae_state *_state) -{ - double result; - - - if( ae_fp_greater_eq(x,(double)(0)) ) - { - result = (double)(1); - } - else - { - result = (double)(-1); - } - return result; -} - - -/************************************************************************* -This function returns product of two real numbers. It is convenient when -you have to perform typecast-and-product of two INTEGERS. -*************************************************************************/ -double rmul2(double v0, double v1, ae_state *_state) -{ - double result; - - - result = v0*v1; - return result; -} - - -/************************************************************************* -This function returns product of three real numbers. It is convenient when -you have to perform typecast-and-product of two INTEGERS. -*************************************************************************/ -double rmul3(double v0, double v1, double v2, ae_state *_state) -{ - double result; - - - result = v0*v1*v2; - return result; -} - - -/************************************************************************* -This function returns (A div B) rounded up; it expects that A>0, B>0, but -does not check it. -*************************************************************************/ -ae_int_t idivup(ae_int_t a, ae_int_t b, ae_state *_state) -{ - ae_int_t result; - - - result = a/b; - if( a%b>0 ) - { - result = result+1; - } - return result; -} - - -/************************************************************************* -This function returns min(i0,i1) -*************************************************************************/ -ae_int_t imin2(ae_int_t i0, ae_int_t i1, ae_state *_state) -{ - ae_int_t result; - - - result = i0; - if( i1result ) - { - result = i1; - } - return result; -} - - -/************************************************************************* -This function returns max(i0,i1,i2) -*************************************************************************/ -ae_int_t imax3(ae_int_t i0, ae_int_t i1, ae_int_t i2, ae_state *_state) -{ - ae_int_t result; - - - result = i0; - if( i1>result ) - { - result = i1; - } - if( i2>result ) - { - result = i2; - } - return result; -} - - -/************************************************************************* -This function returns max(r0,r1,r2) -*************************************************************************/ -double rmax3(double r0, double r1, double r2, ae_state *_state) -{ - double result; - - - result = r0; - if( ae_fp_greater(r1,result) ) - { - result = r1; - } - if( ae_fp_greater(r2,result) ) - { - result = r2; - } - return result; -} - - -/************************************************************************* -This function returns max(|r0|,|r1|,|r2|) -*************************************************************************/ -double rmaxabs3(double r0, double r1, double r2, ae_state *_state) -{ - double result; - - - r0 = ae_fabs(r0, _state); - r1 = ae_fabs(r1, _state); - r2 = ae_fabs(r2, _state); - result = r0; - if( ae_fp_greater(r1,result) ) - { - result = r1; - } - if( ae_fp_greater(r2,result) ) - { - result = r2; - } - return result; -} - - -/************************************************************************* -'bounds' value: maps X to [B1,B2] - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -double boundval(double x, double b1, double b2, ae_state *_state) -{ - double result; - - - if( ae_fp_less_eq(x,b1) ) - { - result = b1; - return result; - } - if( ae_fp_greater_eq(x,b2) ) - { - result = b2; - return result; - } - result = x; - return result; -} - - -/************************************************************************* -'bounds' value: maps X to [B1,B2] - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -ae_int_t iboundval(ae_int_t x, ae_int_t b1, ae_int_t b2, ae_state *_state) -{ - ae_int_t result; - - - if( x<=b1 ) - { - result = b1; - return result; - } - if( x>=b2 ) - { - result = b2; - return result; - } - result = x; - return result; -} - - -/************************************************************************* -'bounds' value: maps X to [B1,B2] - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -double rboundval(double x, double b1, double b2, ae_state *_state) -{ - double result; - - - if( ae_fp_less_eq(x,b1) ) - { - result = b1; - return result; - } - if( ae_fp_greater_eq(x,b2) ) - { - result = b2; - return result; - } - result = x; - return result; -} - - -/************************************************************************* -Returns number of non-zeros -*************************************************************************/ -ae_int_t countnz1(/* Real */ ae_vector* v, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t result; - - - result = 0; - for(i=0; i<=n-1; i++) - { - if( !(v->ptr.p_double[i]==0) ) - { - result = result+1; - } - } - return result; -} - - -/************************************************************************* -Returns number of non-zeros -*************************************************************************/ -ae_int_t countnz2(/* Real */ ae_matrix* v, - ae_int_t m, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t result; - - - result = 0; - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( !(v->ptr.pp_double[i][j]==0) ) - { - result = result+1; - } - } - } - return result; -} - - -/************************************************************************* -Allocation of serializer: complex value -*************************************************************************/ -void alloccomplex(ae_serializer* s, ae_complex v, ae_state *_state) -{ - - - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); -} - - -/************************************************************************* -Serialization: complex value -*************************************************************************/ -void serializecomplex(ae_serializer* s, ae_complex v, ae_state *_state) -{ - - - ae_serializer_serialize_double(s, v.x, _state); - ae_serializer_serialize_double(s, v.y, _state); -} - - -/************************************************************************* -Unserialization: complex value -*************************************************************************/ -ae_complex unserializecomplex(ae_serializer* s, ae_state *_state) -{ - ae_complex result; - - - ae_serializer_unserialize_double(s, &result.x, _state); - ae_serializer_unserialize_double(s, &result.y, _state); - return result; -} - - -/************************************************************************* -Allocation of serializer: real array -*************************************************************************/ -void allocrealarray(ae_serializer* s, - /* Real */ ae_vector* v, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - - - if( n<0 ) - { - n = v->cnt; - } - ae_serializer_alloc_entry(s); - for(i=0; i<=n-1; i++) - { - ae_serializer_alloc_entry(s); - } -} - - -/************************************************************************* -Serialization: complex value -*************************************************************************/ -void serializerealarray(ae_serializer* s, - /* Real */ ae_vector* v, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - - - if( n<0 ) - { - n = v->cnt; - } - ae_serializer_serialize_int(s, n, _state); - for(i=0; i<=n-1; i++) - { - ae_serializer_serialize_double(s, v->ptr.p_double[i], _state); - } -} - - -/************************************************************************* -Unserialization: complex value -*************************************************************************/ -void unserializerealarray(ae_serializer* s, - /* Real */ ae_vector* v, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - double t; - - ae_vector_clear(v); - - ae_serializer_unserialize_int(s, &n, _state); - if( n==0 ) - { - return; - } - ae_vector_set_length(v, n, _state); - for(i=0; i<=n-1; i++) - { - ae_serializer_unserialize_double(s, &t, _state); - v->ptr.p_double[i] = t; - } -} - - -/************************************************************************* -Allocation of serializer: Integer array -*************************************************************************/ -void allocintegerarray(ae_serializer* s, - /* Integer */ ae_vector* v, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - - - if( n<0 ) - { - n = v->cnt; - } - ae_serializer_alloc_entry(s); - for(i=0; i<=n-1; i++) - { - ae_serializer_alloc_entry(s); - } -} - - -/************************************************************************* -Serialization: Integer array -*************************************************************************/ -void serializeintegerarray(ae_serializer* s, - /* Integer */ ae_vector* v, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - - - if( n<0 ) - { - n = v->cnt; - } - ae_serializer_serialize_int(s, n, _state); - for(i=0; i<=n-1; i++) - { - ae_serializer_serialize_int(s, v->ptr.p_int[i], _state); - } -} - - -/************************************************************************* -Unserialization: complex value -*************************************************************************/ -void unserializeintegerarray(ae_serializer* s, - /* Integer */ ae_vector* v, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_int_t t; - - ae_vector_clear(v); - - ae_serializer_unserialize_int(s, &n, _state); - if( n==0 ) - { - return; - } - ae_vector_set_length(v, n, _state); - for(i=0; i<=n-1; i++) - { - ae_serializer_unserialize_int(s, &t, _state); - v->ptr.p_int[i] = t; - } -} - - -/************************************************************************* -Allocation of serializer: real matrix -*************************************************************************/ -void allocrealmatrix(ae_serializer* s, - /* Real */ ae_matrix* v, - ae_int_t n0, - ae_int_t n1, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - if( n0<0 ) - { - n0 = v->rows; - } - if( n1<0 ) - { - n1 = v->cols; - } - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - for(i=0; i<=n0-1; i++) - { - for(j=0; j<=n1-1; j++) - { - ae_serializer_alloc_entry(s); - } - } -} - - -/************************************************************************* -Serialization: complex value -*************************************************************************/ -void serializerealmatrix(ae_serializer* s, - /* Real */ ae_matrix* v, - ae_int_t n0, - ae_int_t n1, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - if( n0<0 ) - { - n0 = v->rows; - } - if( n1<0 ) - { - n1 = v->cols; - } - ae_serializer_serialize_int(s, n0, _state); - ae_serializer_serialize_int(s, n1, _state); - for(i=0; i<=n0-1; i++) - { - for(j=0; j<=n1-1; j++) - { - ae_serializer_serialize_double(s, v->ptr.pp_double[i][j], _state); - } - } -} - - -/************************************************************************* -Unserialization: complex value -*************************************************************************/ -void unserializerealmatrix(ae_serializer* s, - /* Real */ ae_matrix* v, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t n0; - ae_int_t n1; - double t; - - ae_matrix_clear(v); - - ae_serializer_unserialize_int(s, &n0, _state); - ae_serializer_unserialize_int(s, &n1, _state); - if( n0==0||n1==0 ) - { - return; - } - ae_matrix_set_length(v, n0, n1, _state); - for(i=0; i<=n0-1; i++) - { - for(j=0; j<=n1-1; j++) - { - ae_serializer_unserialize_double(s, &t, _state); - v->ptr.pp_double[i][j] = t; - } - } -} - - -/************************************************************************* -Copy boolean array -*************************************************************************/ -void copybooleanarray(/* Boolean */ ae_vector* src, - /* Boolean */ ae_vector* dst, - ae_state *_state) -{ - ae_int_t i; - - ae_vector_clear(dst); - - if( src->cnt>0 ) - { - ae_vector_set_length(dst, src->cnt, _state); - for(i=0; i<=src->cnt-1; i++) - { - dst->ptr.p_bool[i] = src->ptr.p_bool[i]; - } - } -} - - -/************************************************************************* -Copy integer array -*************************************************************************/ -void copyintegerarray(/* Integer */ ae_vector* src, - /* Integer */ ae_vector* dst, - ae_state *_state) -{ - ae_int_t i; - - ae_vector_clear(dst); - - if( src->cnt>0 ) - { - ae_vector_set_length(dst, src->cnt, _state); - for(i=0; i<=src->cnt-1; i++) - { - dst->ptr.p_int[i] = src->ptr.p_int[i]; - } - } -} - - -/************************************************************************* -Copy real array -*************************************************************************/ -void copyrealarray(/* Real */ ae_vector* src, - /* Real */ ae_vector* dst, - ae_state *_state) -{ - ae_int_t i; - - ae_vector_clear(dst); - - if( src->cnt>0 ) - { - ae_vector_set_length(dst, src->cnt, _state); - for(i=0; i<=src->cnt-1; i++) - { - dst->ptr.p_double[i] = src->ptr.p_double[i]; - } - } -} - - -/************************************************************************* -Copy real matrix -*************************************************************************/ -void copyrealmatrix(/* Real */ ae_matrix* src, - /* Real */ ae_matrix* dst, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(dst); - - if( src->rows>0&&src->cols>0 ) - { - ae_matrix_set_length(dst, src->rows, src->cols, _state); - for(i=0; i<=src->rows-1; i++) - { - for(j=0; j<=src->cols-1; j++) - { - dst->ptr.pp_double[i][j] = src->ptr.pp_double[i][j]; - } - } - } -} - - -/************************************************************************* -Clears integer array -*************************************************************************/ -void unsetintegerarray(/* Integer */ ae_vector* a, ae_state *_state) -{ - - ae_vector_clear(a); - -} - - -/************************************************************************* -Clears real array -*************************************************************************/ -void unsetrealarray(/* Real */ ae_vector* a, ae_state *_state) -{ - - ae_vector_clear(a); - -} - - -/************************************************************************* -Clears real matrix -*************************************************************************/ -void unsetrealmatrix(/* Real */ ae_matrix* a, ae_state *_state) -{ - - ae_matrix_clear(a); - -} - - -/************************************************************************* -This function is used in parallel functions for recurrent division of large -task into two smaller tasks. - -It has following properties: -* it works only for TaskSize>=2 and TaskSize>TileSize (assertion is thrown otherwise) -* Task0+Task1=TaskSize, Task0>0, Task1>0 -* Task0 and Task1 are close to each other -* Task0>=Task1 -* Task0 is always divisible by TileSize - - -- ALGLIB -- - Copyright 07.04.2013 by Bochkanov Sergey -*************************************************************************/ -void tiledsplit(ae_int_t tasksize, - ae_int_t tilesize, - ae_int_t* task0, - ae_int_t* task1, - ae_state *_state) -{ - ae_int_t cc; - - *task0 = 0; - *task1 = 0; - - ae_assert(tasksize>=2, "TiledSplit: TaskSize<2", _state); - ae_assert(tasksize>tilesize, "TiledSplit: TaskSize<=TileSize", _state); - cc = chunkscount(tasksize, tilesize, _state); - ae_assert(cc>=2, "TiledSplit: integrity check failed", _state); - *task0 = idivup(cc, 2, _state)*tilesize; - *task1 = tasksize-(*task0); - ae_assert(*task0>=1, "TiledSplit: internal error", _state); - ae_assert(*task1>=1, "TiledSplit: internal error", _state); - ae_assert(*task0%tilesize==0, "TiledSplit: internal error", _state); - ae_assert(*task0>=(*task1), "TiledSplit: internal error", _state); -} - - -/************************************************************************* -This function searches integer array. Elements in this array are actually -records, each NRec elements wide. Each record has unique header - NHeader -integer values, which identify it. Records are lexicographically sorted by -header. - -Records are identified by their index, not offset (offset = NRec*index). - -This function searches A (records with indices [I0,I1)) for a record with -header B. It returns index of this record (not offset!), or -1 on failure. - - -- ALGLIB -- - Copyright 28.03.2011 by Bochkanov Sergey -*************************************************************************/ -ae_int_t recsearch(/* Integer */ ae_vector* a, - ae_int_t nrec, - ae_int_t nheader, - ae_int_t i0, - ae_int_t i1, - /* Integer */ ae_vector* b, - ae_state *_state) -{ - ae_int_t mididx; - ae_int_t cflag; - ae_int_t k; - ae_int_t offs; - ae_int_t result; - - - result = -1; - for(;;) - { - if( i0>=i1 ) - { - break; - } - mididx = (i0+i1)/2; - offs = nrec*mididx; - cflag = 0; - for(k=0; k<=nheader-1; k++) - { - if( a->ptr.p_int[offs+k]ptr.p_int[k] ) - { - cflag = -1; - break; - } - if( a->ptr.p_int[offs+k]>b->ptr.p_int[k] ) - { - cflag = 1; - break; - } - } - if( cflag==0 ) - { - result = mididx; - return result; - } - if( cflag<0 ) - { - i0 = mididx+1; - } - else - { - i1 = mididx; - } - } - return result; -} - - -/************************************************************************* -This function is used in parallel functions for recurrent division of large -task into two smaller tasks. - -It has following properties: -* it works only for TaskSize>=2 (assertion is thrown otherwise) -* for TaskSize=2, it returns Task0=1, Task1=1 -* in case TaskSize is odd, Task0=TaskSize-1, Task1=1 -* in case TaskSize is even, Task0 and Task1 are approximately TaskSize/2 - and both Task0 and Task1 are even, Task0>=Task1 - - -- ALGLIB -- - Copyright 07.04.2013 by Bochkanov Sergey -*************************************************************************/ -void splitlengtheven(ae_int_t tasksize, - ae_int_t* task0, - ae_int_t* task1, - ae_state *_state) -{ - - *task0 = 0; - *task1 = 0; - - ae_assert(tasksize>=2, "SplitLengthEven: TaskSize<2", _state); - if( tasksize==2 ) - { - *task0 = 1; - *task1 = 1; - return; - } - if( tasksize%2==0 ) - { - - /* - * Even division - */ - *task0 = tasksize/2; - *task1 = tasksize/2; - if( *task0%2!=0 ) - { - *task0 = *task0+1; - *task1 = *task1-1; - } - } - else - { - - /* - * Odd task size, split trailing odd part from it. - */ - *task0 = tasksize-1; - *task1 = 1; - } - ae_assert(*task0>=1, "SplitLengthEven: internal error", _state); - ae_assert(*task1>=1, "SplitLengthEven: internal error", _state); -} - - -/************************************************************************* -This function is used to calculate number of chunks (including partial, -non-complete chunks) in some set. It expects that ChunkSize>=1, TaskSize>=0. -Assertion is thrown otherwise. - -Function result is equivalent to Ceil(TaskSize/ChunkSize), but with guarantees -that rounding errors won't ruin results. - - -- ALGLIB -- - Copyright 21.01.2015 by Bochkanov Sergey -*************************************************************************/ -ae_int_t chunkscount(ae_int_t tasksize, - ae_int_t chunksize, - ae_state *_state) -{ - ae_int_t result; - - - ae_assert(tasksize>=0, "ChunksCount: TaskSize<0", _state); - ae_assert(chunksize>=1, "ChunksCount: ChunkSize<1", _state); - result = tasksize/chunksize; - if( tasksize%chunksize!=0 ) - { - result = result+1; - } - return result; -} - - -/************************************************************************* -Returns maximum density for level 2 sparse/dense functions. Density values -below one returned by this function are better to handle via sparse Level 2 -functionality. - - -- ALGLIB routine -- - 10.01.2019 - Bochkanov Sergey -*************************************************************************/ -double sparselevel2density(ae_state *_state) -{ - double result; - - - result = 0.1; - return result; -} - - -/************************************************************************* -Returns A-tile size for a matrix. - -A-tiles are smallest tiles (32x32), suitable for processing by ALGLIB own -implementation of Level 3 linear algebra. - - -- ALGLIB routine -- - 10.01.2019 - Bochkanov Sergey -*************************************************************************/ -ae_int_t matrixtilesizea(ae_state *_state) -{ - ae_int_t result; - - - result = 32; - return result; -} - - -/************************************************************************* -Returns B-tile size for a matrix. - -B-tiles are larger tiles (64x64), suitable for parallel execution or for -processing by vendor's implementation of Level 3 linear algebra. - - -- ALGLIB routine -- - 10.01.2019 - Bochkanov Sergey -*************************************************************************/ -ae_int_t matrixtilesizeb(ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_int_t result; - - - result = 64; - return result; -#else - return _ialglib_i_matrixtilesizeb(); -#endif -} - - -/************************************************************************* -This function returns minimum cost of task which is feasible for -multithreaded processing. It returns real number in order to avoid overflow -problems. - - -- ALGLIB -- - Copyright 10.01.2018 by Bochkanov Sergey -*************************************************************************/ -double smpactivationlevel(ae_state *_state) -{ - double nn; - double result; - - - nn = (double)(2*matrixtilesizeb(_state)); - result = ae_maxreal(0.95*2*nn*nn*nn, 1.0E7, _state); - return result; -} - - -/************************************************************************* -This function returns minimum cost of task which is feasible for -spawn (given that multithreading is active). - -It returns real number in order to avoid overflow problems. - - -- ALGLIB -- - Copyright 10.01.2018 by Bochkanov Sergey -*************************************************************************/ -double spawnlevel(ae_state *_state) -{ - double nn; - double result; - - - nn = (double)(2*matrixtilesizea(_state)); - result = 0.95*2*nn*nn*nn; - return result; -} - - -/************************************************************************* ---- OBSOLETE FUNCTION, USE TILED SPLIT INSTEAD --- - -This function is used in parallel functions for recurrent division of large -task into two smaller tasks. - -It has following properties: -* it works only for TaskSize>=2 and ChunkSize>=2 - (assertion is thrown otherwise) -* Task0+Task1=TaskSize, Task0>0, Task1>0 -* Task0 and Task1 are close to each other -* in case TaskSize>ChunkSize, Task0 is always divisible by ChunkSize - - -- ALGLIB -- - Copyright 07.04.2013 by Bochkanov Sergey -*************************************************************************/ -void splitlength(ae_int_t tasksize, - ae_int_t chunksize, - ae_int_t* task0, - ae_int_t* task1, - ae_state *_state) -{ - - *task0 = 0; - *task1 = 0; - - ae_assert(chunksize>=2, "SplitLength: ChunkSize<2", _state); - ae_assert(tasksize>=2, "SplitLength: TaskSize<2", _state); - *task0 = tasksize/2; - if( *task0>chunksize&&*task0%chunksize!=0 ) - { - *task0 = *task0-*task0%chunksize; - } - *task1 = tasksize-(*task0); - ae_assert(*task0>=1, "SplitLength: internal error", _state); - ae_assert(*task1>=1, "SplitLength: internal error", _state); -} - - -/************************************************************************* -Outputs vector A[I0,I1-1] to trace log using either: -a) 6-digit exponential format (no trace flags is set) -b) 15-ditit exponential format ('PREC.E15' trace flag is set) -b) 6-ditit fixed-point format ('PREC.F6' trace flag is set) - -This function checks trace flags every time it is called. -*************************************************************************/ -void tracevectorautoprec(/* Real */ ae_vector* a, - ae_int_t i0, - ae_int_t i1, - ae_state *_state) -{ - ae_int_t i; - ae_int_t prectouse; - - - - /* - * Determine precision to use - */ - prectouse = 0; - if( ae_is_trace_enabled("PREC.E15") ) - { - prectouse = 1; - } - if( ae_is_trace_enabled("PREC.F6") ) - { - prectouse = 2; - } - - /* - * Output - */ - ae_trace("[ "); - for(i=i0; i<=i1-1; i++) - { - if( prectouse==0 ) - { - ae_trace("%14.6e", - (double)(a->ptr.p_double[i])); - } - if( prectouse==1 ) - { - ae_trace("%23.15e", - (double)(a->ptr.p_double[i])); - } - if( prectouse==2 ) - { - ae_trace("%13.6f", - (double)(a->ptr.p_double[i])); - } - if( iptr.p_double[i]; - if( applyscl ) - { - v = v*scl->ptr.p_double[i]; - } - if( applysft ) - { - v = v+sft->ptr.p_double[i]; - } - if( prectouse==0 ) - { - ae_trace("%14.6e", - (double)(v)); - } - if( prectouse==1 ) - { - ae_trace("%23.15e", - (double)(v)); - } - if( prectouse==2 ) - { - ae_trace("%13.6f", - (double)(v)); - } - if( iptr.pp_double[i][j], _state), _state); - } - if( prectouse==0 ) - { - ae_trace("%14.6e", - (double)(v)); - } - if( prectouse==1 ) - { - ae_trace("%23.15e", - (double)(v)); - } - if( prectouse==2 ) - { - ae_trace("%13.6f", - (double)(v)); - } - if( iptr.p_double[i])); - if( iptr.p_double[i])); - } - else - { - ae_trace("%14.6e", - (double)(a->ptr.p_double[i])); - } - if( iptr.pp_double[i][j], _state), _state); - } - ae_trace("%14.6e", - (double)(v)); - if( iba0, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->ia0, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->ia1, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->ia2, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->ia3, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->ra0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ra1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ra2, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ra3, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->rm0, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->rm1, 0, 0, DT_REAL, _state, make_automatic); -} - - -void _apbuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - apbuffers *dst = (apbuffers*)_dst; - apbuffers *src = (apbuffers*)_src; - ae_vector_init_copy(&dst->ba0, &src->ba0, _state, make_automatic); - ae_vector_init_copy(&dst->ia0, &src->ia0, _state, make_automatic); - ae_vector_init_copy(&dst->ia1, &src->ia1, _state, make_automatic); - ae_vector_init_copy(&dst->ia2, &src->ia2, _state, make_automatic); - ae_vector_init_copy(&dst->ia3, &src->ia3, _state, make_automatic); - ae_vector_init_copy(&dst->ra0, &src->ra0, _state, make_automatic); - ae_vector_init_copy(&dst->ra1, &src->ra1, _state, make_automatic); - ae_vector_init_copy(&dst->ra2, &src->ra2, _state, make_automatic); - ae_vector_init_copy(&dst->ra3, &src->ra3, _state, make_automatic); - ae_matrix_init_copy(&dst->rm0, &src->rm0, _state, make_automatic); - ae_matrix_init_copy(&dst->rm1, &src->rm1, _state, make_automatic); -} - - -void _apbuffers_clear(void* _p) -{ - apbuffers *p = (apbuffers*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->ba0); - ae_vector_clear(&p->ia0); - ae_vector_clear(&p->ia1); - ae_vector_clear(&p->ia2); - ae_vector_clear(&p->ia3); - ae_vector_clear(&p->ra0); - ae_vector_clear(&p->ra1); - ae_vector_clear(&p->ra2); - ae_vector_clear(&p->ra3); - ae_matrix_clear(&p->rm0); - ae_matrix_clear(&p->rm1); -} - - -void _apbuffers_destroy(void* _p) -{ - apbuffers *p = (apbuffers*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->ba0); - ae_vector_destroy(&p->ia0); - ae_vector_destroy(&p->ia1); - ae_vector_destroy(&p->ia2); - ae_vector_destroy(&p->ia3); - ae_vector_destroy(&p->ra0); - ae_vector_destroy(&p->ra1); - ae_vector_destroy(&p->ra2); - ae_vector_destroy(&p->ra3); - ae_matrix_destroy(&p->rm0); - ae_matrix_destroy(&p->rm1); -} - - -void _sboolean_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - sboolean *p = (sboolean*)_p; - ae_touch_ptr((void*)p); -} - - -void _sboolean_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - sboolean *dst = (sboolean*)_dst; - sboolean *src = (sboolean*)_src; - dst->val = src->val; -} - - -void _sboolean_clear(void* _p) -{ - sboolean *p = (sboolean*)_p; - ae_touch_ptr((void*)p); -} - - -void _sboolean_destroy(void* _p) -{ - sboolean *p = (sboolean*)_p; - ae_touch_ptr((void*)p); -} - - -void _sbooleanarray_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - sbooleanarray *p = (sbooleanarray*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->val, 0, DT_BOOL, _state, make_automatic); -} - - -void _sbooleanarray_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - sbooleanarray *dst = (sbooleanarray*)_dst; - sbooleanarray *src = (sbooleanarray*)_src; - ae_vector_init_copy(&dst->val, &src->val, _state, make_automatic); -} - - -void _sbooleanarray_clear(void* _p) -{ - sbooleanarray *p = (sbooleanarray*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->val); -} - - -void _sbooleanarray_destroy(void* _p) -{ - sbooleanarray *p = (sbooleanarray*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->val); -} - - -void _sinteger_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - sinteger *p = (sinteger*)_p; - ae_touch_ptr((void*)p); -} - - -void _sinteger_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - sinteger *dst = (sinteger*)_dst; - sinteger *src = (sinteger*)_src; - dst->val = src->val; -} - - -void _sinteger_clear(void* _p) -{ - sinteger *p = (sinteger*)_p; - ae_touch_ptr((void*)p); -} - - -void _sinteger_destroy(void* _p) -{ - sinteger *p = (sinteger*)_p; - ae_touch_ptr((void*)p); -} - - -void _sintegerarray_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - sintegerarray *p = (sintegerarray*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->val, 0, DT_INT, _state, make_automatic); -} - - -void _sintegerarray_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - sintegerarray *dst = (sintegerarray*)_dst; - sintegerarray *src = (sintegerarray*)_src; - ae_vector_init_copy(&dst->val, &src->val, _state, make_automatic); -} - - -void _sintegerarray_clear(void* _p) -{ - sintegerarray *p = (sintegerarray*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->val); -} - - -void _sintegerarray_destroy(void* _p) -{ - sintegerarray *p = (sintegerarray*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->val); -} - - -void _sreal_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - sreal *p = (sreal*)_p; - ae_touch_ptr((void*)p); -} - - -void _sreal_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - sreal *dst = (sreal*)_dst; - sreal *src = (sreal*)_src; - dst->val = src->val; -} - - -void _sreal_clear(void* _p) -{ - sreal *p = (sreal*)_p; - ae_touch_ptr((void*)p); -} - - -void _sreal_destroy(void* _p) -{ - sreal *p = (sreal*)_p; - ae_touch_ptr((void*)p); -} - - -void _srealarray_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - srealarray *p = (srealarray*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->val, 0, DT_REAL, _state, make_automatic); -} - - -void _srealarray_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - srealarray *dst = (srealarray*)_dst; - srealarray *src = (srealarray*)_src; - ae_vector_init_copy(&dst->val, &src->val, _state, make_automatic); -} - - -void _srealarray_clear(void* _p) -{ - srealarray *p = (srealarray*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->val); -} - - -void _srealarray_destroy(void* _p) -{ - srealarray *p = (srealarray*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->val); -} - - -void _scomplex_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - scomplex *p = (scomplex*)_p; - ae_touch_ptr((void*)p); -} - - -void _scomplex_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - scomplex *dst = (scomplex*)_dst; - scomplex *src = (scomplex*)_src; - dst->val = src->val; -} - - -void _scomplex_clear(void* _p) -{ - scomplex *p = (scomplex*)_p; - ae_touch_ptr((void*)p); -} - - -void _scomplex_destroy(void* _p) -{ - scomplex *p = (scomplex*)_p; - ae_touch_ptr((void*)p); -} - - -void _scomplexarray_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - scomplexarray *p = (scomplexarray*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->val, 0, DT_COMPLEX, _state, make_automatic); -} - - -void _scomplexarray_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - scomplexarray *dst = (scomplexarray*)_dst; - scomplexarray *src = (scomplexarray*)_src; - ae_vector_init_copy(&dst->val, &src->val, _state, make_automatic); -} - - -void _scomplexarray_clear(void* _p) -{ - scomplexarray *p = (scomplexarray*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->val); -} - - -void _scomplexarray_destroy(void* _p) -{ - scomplexarray *p = (scomplexarray*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->val); -} - - -#endif -#if defined(AE_COMPILE_TSORT) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function sorts array of real keys by ascending. - -Its results are: -* sorted array A -* permutation tables P1, P2 - -Algorithm outputs permutation tables using two formats: -* as usual permutation of [0..N-1]. If P1[i]=j, then sorted A[i] contains - value which was moved there from J-th position. -* as a sequence of pairwise permutations. Sorted A[] may be obtained by - swaping A[i] and A[P2[i]] for all i from 0 to N-1. - -INPUT PARAMETERS: - A - unsorted array - N - array size - -OUPUT PARAMETERS: - A - sorted array - P1, P2 - permutation tables, array[N] - -NOTES: - this function assumes that A[] is finite; it doesn't checks that - condition. All other conditions (size of input arrays, etc.) are not - checked too. - - -- ALGLIB -- - Copyright 14.05.2008 by Bochkanov Sergey -*************************************************************************/ -void tagsort(/* Real */ ae_vector* a, - ae_int_t n, - /* Integer */ ae_vector* p1, - /* Integer */ ae_vector* p2, - ae_state *_state) -{ - ae_frame _frame_block; - apbuffers buf; - - ae_frame_make(_state, &_frame_block); - memset(&buf, 0, sizeof(buf)); - ae_vector_clear(p1); - ae_vector_clear(p2); - _apbuffers_init(&buf, _state, ae_true); - - tagsortbuf(a, n, p1, p2, &buf, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Buffered variant of TagSort, which accepts preallocated output arrays as -well as special structure for buffered allocations. If arrays are too -short, they are reallocated. If they are large enough, no memory -allocation is done. - -It is intended to be used in the performance-critical parts of code, where -additional allocations can lead to severe performance degradation - - -- ALGLIB -- - Copyright 14.05.2008 by Bochkanov Sergey -*************************************************************************/ -void tagsortbuf(/* Real */ ae_vector* a, - ae_int_t n, - /* Integer */ ae_vector* p1, - /* Integer */ ae_vector* p2, - apbuffers* buf, - ae_state *_state) -{ - ae_int_t i; - ae_int_t lv; - ae_int_t lp; - ae_int_t rv; - ae_int_t rp; - - - - /* - * Special cases - */ - if( n<=0 ) - { - return; - } - if( n==1 ) - { - ivectorsetlengthatleast(p1, 1, _state); - ivectorsetlengthatleast(p2, 1, _state); - p1->ptr.p_int[0] = 0; - p2->ptr.p_int[0] = 0; - return; - } - - /* - * General case, N>1: prepare permutations table P1 - */ - ivectorsetlengthatleast(p1, n, _state); - for(i=0; i<=n-1; i++) - { - p1->ptr.p_int[i] = i; - } - - /* - * General case, N>1: sort, update P1 - */ - rvectorsetlengthatleast(&buf->ra0, n, _state); - ivectorsetlengthatleast(&buf->ia0, n, _state); - tagsortfasti(a, p1, &buf->ra0, &buf->ia0, n, _state); - - /* - * General case, N>1: fill permutations table P2 - * - * To fill P2 we maintain two arrays: - * * PV (Buf.IA0), Position(Value). PV[i] contains position of I-th key at the moment - * * VP (Buf.IA1), Value(Position). VP[i] contains key which has position I at the moment - * - * At each step we making permutation of two items: - * Left, which is given by position/value pair LP/LV - * and Right, which is given by RP/RV - * and updating PV[] and VP[] correspondingly. - */ - ivectorsetlengthatleast(&buf->ia0, n, _state); - ivectorsetlengthatleast(&buf->ia1, n, _state); - ivectorsetlengthatleast(p2, n, _state); - for(i=0; i<=n-1; i++) - { - buf->ia0.ptr.p_int[i] = i; - buf->ia1.ptr.p_int[i] = i; - } - for(i=0; i<=n-1; i++) - { - - /* - * calculate LP, LV, RP, RV - */ - lp = i; - lv = buf->ia1.ptr.p_int[lp]; - rv = p1->ptr.p_int[i]; - rp = buf->ia0.ptr.p_int[rv]; - - /* - * Fill P2 - */ - p2->ptr.p_int[i] = rp; - - /* - * update PV and VP - */ - buf->ia1.ptr.p_int[lp] = rv; - buf->ia1.ptr.p_int[rp] = lv; - buf->ia0.ptr.p_int[lv] = rp; - buf->ia0.ptr.p_int[rv] = lp; - } -} - - -/************************************************************************* -Same as TagSort, but optimized for real keys and integer labels. - -A is sorted, and same permutations are applied to B. - -NOTES: -1. this function assumes that A[] is finite; it doesn't checks that - condition. All other conditions (size of input arrays, etc.) are not - checked too. -2. this function uses two buffers, BufA and BufB, each is N elements large. - They may be preallocated (which will save some time) or not, in which - case function will automatically allocate memory. - - -- ALGLIB -- - Copyright 11.12.2008 by Bochkanov Sergey -*************************************************************************/ -void tagsortfasti(/* Real */ ae_vector* a, - /* Integer */ ae_vector* b, - /* Real */ ae_vector* bufa, - /* Integer */ ae_vector* bufb, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_bool isascending; - ae_bool isdescending; - double tmpr; - ae_int_t tmpi; - - - - /* - * Special case - */ - if( n<=1 ) - { - return; - } - - /* - * Test for already sorted set - */ - isascending = ae_true; - isdescending = ae_true; - for(i=1; i<=n-1; i++) - { - isascending = isascending&&a->ptr.p_double[i]>=a->ptr.p_double[i-1]; - isdescending = isdescending&&a->ptr.p_double[i]<=a->ptr.p_double[i-1]; - } - if( isascending ) - { - return; - } - if( isdescending ) - { - for(i=0; i<=n-1; i++) - { - j = n-1-i; - if( j<=i ) - { - break; - } - tmpr = a->ptr.p_double[i]; - a->ptr.p_double[i] = a->ptr.p_double[j]; - a->ptr.p_double[j] = tmpr; - tmpi = b->ptr.p_int[i]; - b->ptr.p_int[i] = b->ptr.p_int[j]; - b->ptr.p_int[j] = tmpi; - } - return; - } - - /* - * General case - */ - if( bufa->cntcntptr.p_double[i]>=a->ptr.p_double[i-1]; - isdescending = isdescending&&a->ptr.p_double[i]<=a->ptr.p_double[i-1]; - } - if( isascending ) - { - return; - } - if( isdescending ) - { - for(i=0; i<=n-1; i++) - { - j = n-1-i; - if( j<=i ) - { - break; - } - tmpr = a->ptr.p_double[i]; - a->ptr.p_double[i] = a->ptr.p_double[j]; - a->ptr.p_double[j] = tmpr; - tmpr = b->ptr.p_double[i]; - b->ptr.p_double[i] = b->ptr.p_double[j]; - b->ptr.p_double[j] = tmpr; - } - return; - } - - /* - * General case - */ - if( bufa->cntcntptr.p_double[i]>=a->ptr.p_double[i-1]; - isdescending = isdescending&&a->ptr.p_double[i]<=a->ptr.p_double[i-1]; - } - if( isascending ) - { - return; - } - if( isdescending ) - { - for(i=0; i<=n-1; i++) - { - j = n-1-i; - if( j<=i ) - { - break; - } - tmpr = a->ptr.p_double[i]; - a->ptr.p_double[i] = a->ptr.p_double[j]; - a->ptr.p_double[j] = tmpr; - } - return; - } - - /* - * General case - */ - if( bufa->cnt1: sort, update B - */ - for(i=2; i<=n; i++) - { - t = i; - while(t!=1) - { - k = t/2; - p0 = offset+k-1; - p1 = offset+t-1; - ak = a->ptr.p_int[p0]; - at = a->ptr.p_int[p1]; - if( ak>=at ) - { - break; - } - a->ptr.p_int[p0] = at; - a->ptr.p_int[p1] = ak; - tmpr = b->ptr.p_double[p0]; - b->ptr.p_double[p0] = b->ptr.p_double[p1]; - b->ptr.p_double[p1] = tmpr; - t = k; - } - } - for(i=n-1; i>=1; i--) - { - p0 = offset+0; - p1 = offset+i; - tmp = a->ptr.p_int[p1]; - a->ptr.p_int[p1] = a->ptr.p_int[p0]; - a->ptr.p_int[p0] = tmp; - at = tmp; - tmpr = b->ptr.p_double[p1]; - b->ptr.p_double[p1] = b->ptr.p_double[p0]; - b->ptr.p_double[p0] = tmpr; - bt = tmpr; - t = 0; - for(;;) - { - k = 2*t+1; - if( k+1>i ) - { - break; - } - p0 = offset+t; - p1 = offset+k; - ak = a->ptr.p_int[p1]; - if( k+1ptr.p_int[p1+1]; - if( ak1>ak ) - { - ak = ak1; - p1 = p1+1; - k = k+1; - } - } - if( at>=ak ) - { - break; - } - a->ptr.p_int[p1] = at; - a->ptr.p_int[p0] = ak; - b->ptr.p_double[p0] = b->ptr.p_double[p1]; - b->ptr.p_double[p1] = bt; - t = k; - } - } -} - - -/************************************************************************* -Sorting function optimized for integer keys and real labels, can be used -to sort middle of the array - -A is sorted, and same permutations are applied to B. - -NOTES: - this function assumes that A[] is finite; it doesn't checks that - condition. All other conditions (size of input arrays, etc.) are not - checked too. - - -- ALGLIB -- - Copyright 11.12.2008 by Bochkanov Sergey -*************************************************************************/ -void tagsortmiddlei(/* Integer */ ae_vector* a, - ae_int_t offset, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - ae_int_t t; - ae_int_t tmp; - ae_int_t p0; - ae_int_t p1; - ae_int_t at; - ae_int_t ak; - ae_int_t ak1; - - - - /* - * Special cases - */ - if( n<=1 ) - { - return; - } - - /* - * General case, N>1: sort, update B - */ - for(i=2; i<=n; i++) - { - t = i; - while(t!=1) - { - k = t/2; - p0 = offset+k-1; - p1 = offset+t-1; - ak = a->ptr.p_int[p0]; - at = a->ptr.p_int[p1]; - if( ak>=at ) - { - break; - } - a->ptr.p_int[p0] = at; - a->ptr.p_int[p1] = ak; - t = k; - } - } - for(i=n-1; i>=1; i--) - { - p0 = offset+0; - p1 = offset+i; - tmp = a->ptr.p_int[p1]; - a->ptr.p_int[p1] = a->ptr.p_int[p0]; - a->ptr.p_int[p0] = tmp; - at = tmp; - t = 0; - for(;;) - { - k = 2*t+1; - if( k+1>i ) - { - break; - } - p0 = offset+t; - p1 = offset+k; - ak = a->ptr.p_int[p1]; - if( k+1ptr.p_int[p1+1]; - if( ak1>ak ) - { - ak = ak1; - p1 = p1+1; - k = k+1; - } - } - if( at>=ak ) - { - break; - } - a->ptr.p_int[p1] = at; - a->ptr.p_int[p0] = ak; - t = k; - } - } -} - - -/************************************************************************* -Sorting function optimized for integer values (only keys, no labels), can -be used to sort middle of the array - - -- ALGLIB -- - Copyright 11.12.2008 by Bochkanov Sergey -*************************************************************************/ -void sortmiddlei(/* Integer */ ae_vector* a, - ae_int_t offset, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - ae_int_t t; - ae_int_t tmp; - ae_int_t p0; - ae_int_t p1; - ae_int_t at; - ae_int_t ak; - ae_int_t ak1; - - - - /* - * Special cases - */ - if( n<=1 ) - { - return; - } - - /* - * General case, N>1: sort, update B - */ - for(i=2; i<=n; i++) - { - t = i; - while(t!=1) - { - k = t/2; - p0 = offset+k-1; - p1 = offset+t-1; - ak = a->ptr.p_int[p0]; - at = a->ptr.p_int[p1]; - if( ak>=at ) - { - break; - } - a->ptr.p_int[p0] = at; - a->ptr.p_int[p1] = ak; - t = k; - } - } - for(i=n-1; i>=1; i--) - { - p0 = offset+0; - p1 = offset+i; - tmp = a->ptr.p_int[p1]; - a->ptr.p_int[p1] = a->ptr.p_int[p0]; - a->ptr.p_int[p0] = tmp; - at = tmp; - t = 0; - for(;;) - { - k = 2*t+1; - if( k+1>i ) - { - break; - } - p0 = offset+t; - p1 = offset+k; - ak = a->ptr.p_int[p1]; - if( k+1ptr.p_int[p1+1]; - if( ak1>ak ) - { - ak = ak1; - p1 = p1+1; - k = k+1; - } - } - if( at>=ak ) - { - break; - } - a->ptr.p_int[p1] = at; - a->ptr.p_int[p0] = ak; - t = k; - } - } -} - - -/************************************************************************* -Heap operations: adds element to the heap - -PARAMETERS: - A - heap itself, must be at least array[0..N] - B - array of integer tags, which are updated according to - permutations in the heap - N - size of the heap (without new element). - updated on output - VA - value of the element being added - VB - value of the tag - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void tagheappushi(/* Real */ ae_vector* a, - /* Integer */ ae_vector* b, - ae_int_t* n, - double va, - ae_int_t vb, - ae_state *_state) -{ - ae_int_t j; - ae_int_t k; - double v; - - - if( *n<0 ) - { - return; - } - - /* - * N=0 is a special case - */ - if( *n==0 ) - { - a->ptr.p_double[0] = va; - b->ptr.p_int[0] = vb; - *n = *n+1; - return; - } - - /* - * add current point to the heap - * (add to the bottom, then move up) - * - * we don't write point to the heap - * until its final position is determined - * (it allow us to reduce number of array access operations) - */ - j = *n; - *n = *n+1; - while(j>0) - { - k = (j-1)/2; - v = a->ptr.p_double[k]; - if( vptr.p_double[j] = v; - b->ptr.p_int[j] = b->ptr.p_int[k]; - j = k; - } - else - { - - /* - * element in its place. terminate. - */ - break; - } - } - a->ptr.p_double[j] = va; - b->ptr.p_int[j] = vb; -} - - -/************************************************************************* -Heap operations: replaces top element with new element -(which is moved down) - -PARAMETERS: - A - heap itself, must be at least array[0..N-1] - B - array of integer tags, which are updated according to - permutations in the heap - N - size of the heap - VA - value of the element which replaces top element - VB - value of the tag - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void tagheapreplacetopi(/* Real */ ae_vector* a, - /* Integer */ ae_vector* b, - ae_int_t n, - double va, - ae_int_t vb, - ae_state *_state) -{ - ae_int_t j; - ae_int_t k1; - ae_int_t k2; - double v; - double v1; - double v2; - - - if( n<1 ) - { - return; - } - - /* - * N=1 is a special case - */ - if( n==1 ) - { - a->ptr.p_double[0] = va; - b->ptr.p_int[0] = vb; - return; - } - - /* - * move down through heap: - * * J - current element - * * K1 - first child (always exists) - * * K2 - second child (may not exists) - * - * we don't write point to the heap - * until its final position is determined - * (it allow us to reduce number of array access operations) - */ - j = 0; - k1 = 1; - k2 = 2; - while(k1=n ) - { - - /* - * only one child. - * - * swap and terminate (because this child - * have no siblings due to heap structure) - */ - v = a->ptr.p_double[k1]; - if( v>va ) - { - a->ptr.p_double[j] = v; - b->ptr.p_int[j] = b->ptr.p_int[k1]; - j = k1; - } - break; - } - else - { - - /* - * two childs - */ - v1 = a->ptr.p_double[k1]; - v2 = a->ptr.p_double[k2]; - if( v1>v2 ) - { - if( vaptr.p_double[j] = v1; - b->ptr.p_int[j] = b->ptr.p_int[k1]; - j = k1; - } - else - { - break; - } - } - else - { - if( vaptr.p_double[j] = v2; - b->ptr.p_int[j] = b->ptr.p_int[k2]; - j = k2; - } - else - { - break; - } - } - k1 = 2*j+1; - k2 = 2*j+2; - } - } - a->ptr.p_double[j] = va; - b->ptr.p_int[j] = vb; -} - - -/************************************************************************* -Heap operations: pops top element from the heap - -PARAMETERS: - A - heap itself, must be at least array[0..N-1] - B - array of integer tags, which are updated according to - permutations in the heap - N - size of the heap, N>=1 - -On output top element is moved to A[N-1], B[N-1], heap is reordered, N is -decreased by 1. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void tagheappopi(/* Real */ ae_vector* a, - /* Integer */ ae_vector* b, - ae_int_t* n, - ae_state *_state) -{ - double va; - ae_int_t vb; - - - if( *n<1 ) - { - return; - } - - /* - * N=1 is a special case - */ - if( *n==1 ) - { - *n = 0; - return; - } - - /* - * swap top element and last element, - * then reorder heap - */ - va = a->ptr.p_double[*n-1]; - vb = b->ptr.p_int[*n-1]; - a->ptr.p_double[*n-1] = a->ptr.p_double[0]; - b->ptr.p_int[*n-1] = b->ptr.p_int[0]; - *n = *n-1; - tagheapreplacetopi(a, b, *n, va, vb, _state); -} - - -/************************************************************************* -Search first element less than T in sorted array. - -PARAMETERS: - A - sorted array by ascending from 0 to N-1 - N - number of elements in array - T - the desired element - -RESULT: - The very first element's index, which isn't less than T. -In the case when there aren't such elements, returns N. -*************************************************************************/ -ae_int_t lowerbound(/* Real */ ae_vector* a, - ae_int_t n, - double t, - ae_state *_state) -{ - ae_int_t l; - ae_int_t half; - ae_int_t first; - ae_int_t middle; - ae_int_t result; - - - l = n; - first = 0; - while(l>0) - { - half = l/2; - middle = first+half; - if( ae_fp_less(a->ptr.p_double[middle],t) ) - { - first = middle+1; - l = l-half-1; - } - else - { - l = half; - } - } - result = first; - return result; -} - - -/************************************************************************* -Search first element more than T in sorted array. - -PARAMETERS: - A - sorted array by ascending from 0 to N-1 - N - number of elements in array - T - the desired element - - RESULT: - The very first element's index, which more than T. -In the case when there aren't such elements, returns N. -*************************************************************************/ -ae_int_t upperbound(/* Real */ ae_vector* a, - ae_int_t n, - double t, - ae_state *_state) -{ - ae_int_t l; - ae_int_t half; - ae_int_t first; - ae_int_t middle; - ae_int_t result; - - - l = n; - first = 0; - while(l>0) - { - half = l/2; - middle = first+half; - if( ae_fp_less(t,a->ptr.p_double[middle]) ) - { - l = half; - } - else - { - first = middle+1; - l = l-half-1; - } - } - result = first; - return result; -} - - -/************************************************************************* -Internal TagSortFastI: sorts A[I1...I2] (both bounds are included), -applies same permutations to B. - - -- ALGLIB -- - Copyright 06.09.2010 by Bochkanov Sergey -*************************************************************************/ -static void tsort_tagsortfastirec(/* Real */ ae_vector* a, - /* Integer */ ae_vector* b, - /* Real */ ae_vector* bufa, - /* Integer */ ae_vector* bufb, - ae_int_t i1, - ae_int_t i2, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t cntless; - ae_int_t cnteq; - ae_int_t cntgreater; - double tmpr; - ae_int_t tmpi; - double v0; - double v1; - double v2; - double vp; - - - - /* - * Fast exit - */ - if( i2<=i1 ) - { - return; - } - - /* - * Non-recursive sort for small arrays - */ - if( i2-i1<=16 ) - { - for(j=i1+1; j<=i2; j++) - { - - /* - * Search elements [I1..J-1] for place to insert Jth element. - * - * This code stops immediately if we can leave A[J] at J-th position - * (all elements have same value of A[J] larger than any of them) - */ - tmpr = a->ptr.p_double[j]; - tmpi = j; - for(k=j-1; k>=i1; k--) - { - if( a->ptr.p_double[k]<=tmpr ) - { - break; - } - tmpi = k; - } - k = tmpi; - - /* - * Insert Jth element into Kth position - */ - if( k!=j ) - { - tmpr = a->ptr.p_double[j]; - tmpi = b->ptr.p_int[j]; - for(i=j-1; i>=k; i--) - { - a->ptr.p_double[i+1] = a->ptr.p_double[i]; - b->ptr.p_int[i+1] = b->ptr.p_int[i]; - } - a->ptr.p_double[k] = tmpr; - b->ptr.p_int[k] = tmpi; - } - } - return; - } - - /* - * Quicksort: choose pivot - * Here we assume that I2-I1>=2 - */ - v0 = a->ptr.p_double[i1]; - v1 = a->ptr.p_double[i1+(i2-i1)/2]; - v2 = a->ptr.p_double[i2]; - if( v0>v1 ) - { - tmpr = v1; - v1 = v0; - v0 = tmpr; - } - if( v1>v2 ) - { - tmpr = v2; - v2 = v1; - v1 = tmpr; - } - if( v0>v1 ) - { - tmpr = v1; - v1 = v0; - v0 = tmpr; - } - vp = v1; - - /* - * now pass through A/B and: - * * move elements that are LESS than VP to the left of A/B - * * move elements that are EQUAL to VP to the right of BufA/BufB (in the reverse order) - * * move elements that are GREATER than VP to the left of BufA/BufB (in the normal order - * * move elements from the tail of BufA/BufB to the middle of A/B (restoring normal order) - * * move elements from the left of BufA/BufB to the end of A/B - */ - cntless = 0; - cnteq = 0; - cntgreater = 0; - for(i=i1; i<=i2; i++) - { - v0 = a->ptr.p_double[i]; - if( v0ptr.p_double[k] = v0; - b->ptr.p_int[k] = b->ptr.p_int[i]; - } - cntless = cntless+1; - continue; - } - if( v0==vp ) - { - - /* - * EQUAL - */ - k = i2-cnteq; - bufa->ptr.p_double[k] = v0; - bufb->ptr.p_int[k] = b->ptr.p_int[i]; - cnteq = cnteq+1; - continue; - } - - /* - * GREATER - */ - k = i1+cntgreater; - bufa->ptr.p_double[k] = v0; - bufb->ptr.p_int[k] = b->ptr.p_int[i]; - cntgreater = cntgreater+1; - } - for(i=0; i<=cnteq-1; i++) - { - j = i1+cntless+cnteq-1-i; - k = i2+i-(cnteq-1); - a->ptr.p_double[j] = bufa->ptr.p_double[k]; - b->ptr.p_int[j] = bufb->ptr.p_int[k]; - } - for(i=0; i<=cntgreater-1; i++) - { - j = i1+cntless+cnteq+i; - k = i1+i; - a->ptr.p_double[j] = bufa->ptr.p_double[k]; - b->ptr.p_int[j] = bufb->ptr.p_int[k]; - } - - /* - * Sort left and right parts of the array (ignoring middle part) - */ - tsort_tagsortfastirec(a, b, bufa, bufb, i1, i1+cntless-1, _state); - tsort_tagsortfastirec(a, b, bufa, bufb, i1+cntless+cnteq, i2, _state); -} - - -/************************************************************************* -Internal TagSortFastR: sorts A[I1...I2] (both bounds are included), -applies same permutations to B. - - -- ALGLIB -- - Copyright 06.09.2010 by Bochkanov Sergey -*************************************************************************/ -static void tsort_tagsortfastrrec(/* Real */ ae_vector* a, - /* Real */ ae_vector* b, - /* Real */ ae_vector* bufa, - /* Real */ ae_vector* bufb, - ae_int_t i1, - ae_int_t i2, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double tmpr; - double tmpr2; - ae_int_t tmpi; - ae_int_t cntless; - ae_int_t cnteq; - ae_int_t cntgreater; - double v0; - double v1; - double v2; - double vp; - - - - /* - * Fast exit - */ - if( i2<=i1 ) - { - return; - } - - /* - * Non-recursive sort for small arrays - */ - if( i2-i1<=16 ) - { - for(j=i1+1; j<=i2; j++) - { - - /* - * Search elements [I1..J-1] for place to insert Jth element. - * - * This code stops immediatly if we can leave A[J] at J-th position - * (all elements have same value of A[J] larger than any of them) - */ - tmpr = a->ptr.p_double[j]; - tmpi = j; - for(k=j-1; k>=i1; k--) - { - if( a->ptr.p_double[k]<=tmpr ) - { - break; - } - tmpi = k; - } - k = tmpi; - - /* - * Insert Jth element into Kth position - */ - if( k!=j ) - { - tmpr = a->ptr.p_double[j]; - tmpr2 = b->ptr.p_double[j]; - for(i=j-1; i>=k; i--) - { - a->ptr.p_double[i+1] = a->ptr.p_double[i]; - b->ptr.p_double[i+1] = b->ptr.p_double[i]; - } - a->ptr.p_double[k] = tmpr; - b->ptr.p_double[k] = tmpr2; - } - } - return; - } - - /* - * Quicksort: choose pivot - * Here we assume that I2-I1>=16 - */ - v0 = a->ptr.p_double[i1]; - v1 = a->ptr.p_double[i1+(i2-i1)/2]; - v2 = a->ptr.p_double[i2]; - if( v0>v1 ) - { - tmpr = v1; - v1 = v0; - v0 = tmpr; - } - if( v1>v2 ) - { - tmpr = v2; - v2 = v1; - v1 = tmpr; - } - if( v0>v1 ) - { - tmpr = v1; - v1 = v0; - v0 = tmpr; - } - vp = v1; - - /* - * now pass through A/B and: - * * move elements that are LESS than VP to the left of A/B - * * move elements that are EQUAL to VP to the right of BufA/BufB (in the reverse order) - * * move elements that are GREATER than VP to the left of BufA/BufB (in the normal order - * * move elements from the tail of BufA/BufB to the middle of A/B (restoring normal order) - * * move elements from the left of BufA/BufB to the end of A/B - */ - cntless = 0; - cnteq = 0; - cntgreater = 0; - for(i=i1; i<=i2; i++) - { - v0 = a->ptr.p_double[i]; - if( v0ptr.p_double[k] = v0; - b->ptr.p_double[k] = b->ptr.p_double[i]; - } - cntless = cntless+1; - continue; - } - if( v0==vp ) - { - - /* - * EQUAL - */ - k = i2-cnteq; - bufa->ptr.p_double[k] = v0; - bufb->ptr.p_double[k] = b->ptr.p_double[i]; - cnteq = cnteq+1; - continue; - } - - /* - * GREATER - */ - k = i1+cntgreater; - bufa->ptr.p_double[k] = v0; - bufb->ptr.p_double[k] = b->ptr.p_double[i]; - cntgreater = cntgreater+1; - } - for(i=0; i<=cnteq-1; i++) - { - j = i1+cntless+cnteq-1-i; - k = i2+i-(cnteq-1); - a->ptr.p_double[j] = bufa->ptr.p_double[k]; - b->ptr.p_double[j] = bufb->ptr.p_double[k]; - } - for(i=0; i<=cntgreater-1; i++) - { - j = i1+cntless+cnteq+i; - k = i1+i; - a->ptr.p_double[j] = bufa->ptr.p_double[k]; - b->ptr.p_double[j] = bufb->ptr.p_double[k]; - } - - /* - * Sort left and right parts of the array (ignoring middle part) - */ - tsort_tagsortfastrrec(a, b, bufa, bufb, i1, i1+cntless-1, _state); - tsort_tagsortfastrrec(a, b, bufa, bufb, i1+cntless+cnteq, i2, _state); -} - - -/************************************************************************* -Internal TagSortFastI: sorts A[I1...I2] (both bounds are included), -applies same permutations to B. - - -- ALGLIB -- - Copyright 06.09.2010 by Bochkanov Sergey -*************************************************************************/ -static void tsort_tagsortfastrec(/* Real */ ae_vector* a, - /* Real */ ae_vector* bufa, - ae_int_t i1, - ae_int_t i2, - ae_state *_state) -{ - ae_int_t cntless; - ae_int_t cnteq; - ae_int_t cntgreater; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double tmpr; - ae_int_t tmpi; - double v0; - double v1; - double v2; - double vp; - - - - /* - * Fast exit - */ - if( i2<=i1 ) - { - return; - } - - /* - * Non-recursive sort for small arrays - */ - if( i2-i1<=16 ) - { - for(j=i1+1; j<=i2; j++) - { - - /* - * Search elements [I1..J-1] for place to insert Jth element. - * - * This code stops immediatly if we can leave A[J] at J-th position - * (all elements have same value of A[J] larger than any of them) - */ - tmpr = a->ptr.p_double[j]; - tmpi = j; - for(k=j-1; k>=i1; k--) - { - if( a->ptr.p_double[k]<=tmpr ) - { - break; - } - tmpi = k; - } - k = tmpi; - - /* - * Insert Jth element into Kth position - */ - if( k!=j ) - { - tmpr = a->ptr.p_double[j]; - for(i=j-1; i>=k; i--) - { - a->ptr.p_double[i+1] = a->ptr.p_double[i]; - } - a->ptr.p_double[k] = tmpr; - } - } - return; - } - - /* - * Quicksort: choose pivot - * Here we assume that I2-I1>=16 - */ - v0 = a->ptr.p_double[i1]; - v1 = a->ptr.p_double[i1+(i2-i1)/2]; - v2 = a->ptr.p_double[i2]; - if( v0>v1 ) - { - tmpr = v1; - v1 = v0; - v0 = tmpr; - } - if( v1>v2 ) - { - tmpr = v2; - v2 = v1; - v1 = tmpr; - } - if( v0>v1 ) - { - tmpr = v1; - v1 = v0; - v0 = tmpr; - } - vp = v1; - - /* - * now pass through A/B and: - * * move elements that are LESS than VP to the left of A/B - * * move elements that are EQUAL to VP to the right of BufA/BufB (in the reverse order) - * * move elements that are GREATER than VP to the left of BufA/BufB (in the normal order - * * move elements from the tail of BufA/BufB to the middle of A/B (restoring normal order) - * * move elements from the left of BufA/BufB to the end of A/B - */ - cntless = 0; - cnteq = 0; - cntgreater = 0; - for(i=i1; i<=i2; i++) - { - v0 = a->ptr.p_double[i]; - if( v0ptr.p_double[k] = v0; - } - cntless = cntless+1; - continue; - } - if( v0==vp ) - { - - /* - * EQUAL - */ - k = i2-cnteq; - bufa->ptr.p_double[k] = v0; - cnteq = cnteq+1; - continue; - } - - /* - * GREATER - */ - k = i1+cntgreater; - bufa->ptr.p_double[k] = v0; - cntgreater = cntgreater+1; - } - for(i=0; i<=cnteq-1; i++) - { - j = i1+cntless+cnteq-1-i; - k = i2+i-(cnteq-1); - a->ptr.p_double[j] = bufa->ptr.p_double[k]; - } - for(i=0; i<=cntgreater-1; i++) - { - j = i1+cntless+cnteq+i; - k = i1+i; - a->ptr.p_double[j] = bufa->ptr.p_double[k]; - } - - /* - * Sort left and right parts of the array (ignoring middle part) - */ - tsort_tagsortfastrec(a, bufa, i1, i1+cntless-1, _state); - tsort_tagsortfastrec(a, bufa, i1+cntless+cnteq, i2, _state); -} - - -#endif -#if defined(AE_COMPILE_ABLASF) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Computes dot product (X,Y) for elements [0,N) of X[] and Y[] - -INPUT PARAMETERS: - N - vector length - X - array[N], vector to process - Y - array[N], vector to process - -RESULT: - (X,Y) - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -double rdotv(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - double result; - - - result = (double)(0); - for(i=0; i<=n-1; i++) - { - result = result+x->ptr.p_double[i]*y->ptr.p_double[i]; - } - return result; -} - - -/************************************************************************* -Computes dot product (X,A[i]) for elements [0,N) of vector X[] and row A[i,*] - -INPUT PARAMETERS: - N - vector length - X - array[N], vector to process - A - array[?,N], matrix to process - I - row index - -RESULT: - (X,Ai) - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -double rdotvr(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_matrix* a, - ae_int_t i, - ae_state *_state) -{ - ae_int_t j; - double result; - - - result = (double)(0); - for(j=0; j<=n-1; j++) - { - result = result+x->ptr.p_double[j]*a->ptr.pp_double[i][j]; - } - return result; -} - - -/************************************************************************* -Computes dot product (X,A[i]) for rows A[ia,*] and B[ib,*] - -INPUT PARAMETERS: - N - vector length - X - array[N], vector to process - A - array[?,N], matrix to process - I - row index - -RESULT: - (X,Ai) - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -double rdotrr(ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_state *_state) -{ - ae_int_t j; - double result; - - - result = (double)(0); - for(j=0; j<=n-1; j++) - { - result = result+a->ptr.pp_double[ia][j]*b->ptr.pp_double[ib][j]; - } - return result; -} - - -/************************************************************************* -Computes dot product (X,X) for elements [0,N) of X[] - -INPUT PARAMETERS: - N - vector length - X - array[N], vector to process - -RESULT: - (X,X) - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -double rdotv2(ae_int_t n, /* Real */ ae_vector* x, ae_state *_state) -{ - ae_int_t i; - double v; - double result; - - - result = (double)(0); - for(i=0; i<=n-1; i++) - { - v = x->ptr.p_double[i]; - result = result+v*v; - } - return result; -} - - -/************************************************************************* -Performs inplace addition of Y[] to X[] - -INPUT PARAMETERS: - N - vector length - Alpha - multiplier - Y - array[N], vector to process - X - array[N], vector to process - -RESULT: - X := X + alpha*Y - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void raddv(ae_int_t n, - double alpha, - /* Real */ ae_vector* y, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = x->ptr.p_double[i]+alpha*y->ptr.p_double[i]; - } -} - - -/************************************************************************* -Performs inplace addition of Y[] to X[] - -INPUT PARAMETERS: - N - vector length - Alpha - multiplier - Y - source vector - OffsY - source offset - X - destination vector - OffsX - destination offset - -RESULT: - X := X + alpha*Y - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void raddvx(ae_int_t n, - double alpha, - /* Real */ ae_vector* y, - ae_int_t offsy, - /* Real */ ae_vector* x, - ae_int_t offsx, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[offsx+i] = x->ptr.p_double[offsx+i]+alpha*y->ptr.p_double[offsy+i]; - } -} - - -/************************************************************************* -Performs inplace addition of vector Y[] to column X[] - -INPUT PARAMETERS: - N - vector length - Alpha - multiplier - Y - vector to add - X - target column ColIdx - -RESULT: - X := X + alpha*Y - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void raddvc(ae_int_t n, - double alpha, - /* Real */ ae_vector* y, - /* Real */ ae_matrix* x, - ae_int_t colidx, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=n-1; i++) - { - x->ptr.pp_double[i][colidx] = x->ptr.pp_double[i][colidx]+alpha*y->ptr.p_double[i]; - } -} - - -/************************************************************************* -Performs inplace addition of vector Y[] to row X[] - -INPUT PARAMETERS: - N - vector length - Alpha - multiplier - Y - vector to add - X - target row RowIdx - -RESULT: - X := X + alpha*Y - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void raddvr(ae_int_t n, - double alpha, - /* Real */ ae_vector* y, - /* Real */ ae_matrix* x, - ae_int_t rowidx, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=n-1; i++) - { - x->ptr.pp_double[rowidx][i] = x->ptr.pp_double[rowidx][i]+alpha*y->ptr.p_double[i]; - } -} - - -/************************************************************************* -Performs componentwise multiplication of row X[] by vector Y[] - -INPUT PARAMETERS: - N - vector length - Y - vector to multiply by - X - target row RowIdx - -RESULT: - X := componentwise(X*Y) - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rmergemulvr(ae_int_t n, - /* Real */ ae_vector* y, - /* Real */ ae_matrix* x, - ae_int_t rowidx, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=n-1; i++) - { - x->ptr.pp_double[rowidx][i] = x->ptr.pp_double[rowidx][i]*y->ptr.p_double[i]; - } -} - - -/************************************************************************* -Performs componentwise max of row X[I] and vector Y[] - -INPUT PARAMETERS: - N - vector length - X - matrix, I-th row is source - X - target row RowIdx - -RESULT: - X := componentwise(X*Y) - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rmergemaxrv(ae_int_t n, - /* Real */ ae_matrix* x, - ae_int_t rowidx, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=n-1; i++) - { - y->ptr.p_double[i] = ae_maxreal(y->ptr.p_double[i], x->ptr.pp_double[rowidx][i], _state); - } -} - - -/************************************************************************* -Performs inplace addition of Y[RIdx,...] to X[] - -INPUT PARAMETERS: - N - vector length - Alpha - multiplier - Y - array[?,N], matrix whose RIdx-th row is added - RIdx - row index - X - array[N], vector to process - -RESULT: - X := X + alpha*Y - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void raddrv(ae_int_t n, - double alpha, - /* Real */ ae_matrix* y, - ae_int_t ridx, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = x->ptr.p_double[i]+alpha*y->ptr.pp_double[ridx][i]; - } -} - - -/************************************************************************* -Performs inplace multiplication of X[] by V - -INPUT PARAMETERS: - N - vector length - X - array[N], vector to process - V - multiplier - -OUTPUT PARAMETERS: - X - elements 0...N-1 multiplied by V - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rmulv(ae_int_t n, - double v, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = x->ptr.p_double[i]*v; - } -} - - -/************************************************************************* -Performs inplace multiplication of X[] by V - -INPUT PARAMETERS: - N - row length - X - array[?,N], row to process - V - multiplier - -OUTPUT PARAMETERS: - X - elements 0...N-1 of row RowIdx are multiplied by V - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rmulr(ae_int_t n, - double v, - /* Real */ ae_matrix* x, - ae_int_t rowidx, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=n-1; i++) - { - x->ptr.pp_double[rowidx][i] = x->ptr.pp_double[rowidx][i]*v; - } -} - - -/************************************************************************* -Performs inplace multiplication of X[OffsX:OffsX+N-1] by V - -INPUT PARAMETERS: - N - subvector length - X - vector to process - V - multiplier - -OUTPUT PARAMETERS: - X - elements OffsX:OffsX+N-1 multiplied by V - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rmulvx(ae_int_t n, - double v, - /* Real */ ae_vector* x, - ae_int_t offsx, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[offsx+i] = x->ptr.p_double[offsx+i]*v; - } -} - - -/************************************************************************* -Returns maximum |X| - -INPUT PARAMETERS: - N - vector length - X - array[N], vector to process - -OUTPUT PARAMETERS: - max(|X[i]|) - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -double rmaxabsv(ae_int_t n, /* Real */ ae_vector* x, ae_state *_state) -{ - ae_int_t i; - double v; - double result; - - - result = (double)(0); - for(i=0; i<=n-1; i++) - { - v = ae_fabs(x->ptr.p_double[i], _state); - if( ae_fp_greater(v,result) ) - { - result = v; - } - } - return result; -} - - -/************************************************************************* -Sets vector X[] to V - -INPUT PARAMETERS: - N - vector length - V - value to set - X - array[N] - -OUTPUT PARAMETERS: - X - leading N elements are replaced by V - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rsetv(ae_int_t n, - double v, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t j; - - - for(j=0; j<=n-1; j++) - { - x->ptr.p_double[j] = v; - } -} - - -/************************************************************************* -Sets X[OffsX:OffsX+N-1] to V - -INPUT PARAMETERS: - N - subvector length - V - value to set - X - array[N] - -OUTPUT PARAMETERS: - X - X[OffsX:OffsX+N-1] is replaced by V - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rsetvx(ae_int_t n, - double v, - /* Real */ ae_vector* x, - ae_int_t offsx, - ae_state *_state) -{ - ae_int_t j; - - - for(j=0; j<=n-1; j++) - { - x->ptr.p_double[offsx+j] = v; - } -} - - -/************************************************************************* -Sets vector X[] to V - -INPUT PARAMETERS: - N - vector length - V - value to set - X - array[N] - -OUTPUT PARAMETERS: - X - leading N elements are replaced by V - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void isetv(ae_int_t n, - ae_int_t v, - /* Integer */ ae_vector* x, - ae_state *_state) -{ - ae_int_t j; - - - for(j=0; j<=n-1; j++) - { - x->ptr.p_int[j] = v; - } -} - - -/************************************************************************* -Sets vector X[] to V - -INPUT PARAMETERS: - N - vector length - V - value to set - X - array[N] - -OUTPUT PARAMETERS: - X - leading N elements are replaced by V - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void bsetv(ae_int_t n, - ae_bool v, - /* Boolean */ ae_vector* x, - ae_state *_state) -{ - ae_int_t j; - - - for(j=0; j<=n-1; j++) - { - x->ptr.p_bool[j] = v; - } -} - - -/************************************************************************* -Sets matrix A[] to V - -INPUT PARAMETERS: - M, N - rows/cols count - V - value to set - A - array[M,N] - -OUTPUT PARAMETERS: - A - leading M rows, N cols are replaced by V - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rsetm(ae_int_t m, - ae_int_t n, - double v, - /* Real */ ae_matrix* a, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - a->ptr.pp_double[i][j] = v; - } - } -} - - -/************************************************************************* -Sets vector X[] to V, reallocating X[] if too small - -INPUT PARAMETERS: - N - vector length - V - value to set - X - possibly preallocated array - -OUTPUT PARAMETERS: - X - leading N elements are replaced by V; array is reallocated - if its length is less than N. - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rsetallocv(ae_int_t n, - double v, - /* Real */ ae_vector* x, - ae_state *_state) -{ - - - if( x->cntrowscols=N - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rallocv(ae_int_t n, /* Real */ ae_vector* x, ae_state *_state) -{ - - - if( x->cnt=N - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void ballocv(ae_int_t n, /* Boolean */ ae_vector* x, ae_state *_state) -{ - - - if( x->cntrowscolscntcntptr.pp_double[i][j] = v; - } -} - - -/************************************************************************* -Sets col J of A[,] to V - -INPUT PARAMETERS: - N - vector length - V - value to set - A - array[N,N] or larger - J - col index - -OUTPUT PARAMETERS: - A - leading N elements of I-th col are replaced by V - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rsetc(ae_int_t n, - double v, - /* Real */ ae_matrix* a, - ae_int_t j, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=n-1; i++) - { - a->ptr.pp_double[i][j] = v; - } -} - - -/************************************************************************* -Copies vector X[] to Y[] - -INPUT PARAMETERS: - N - vector length - X - array[N], source - Y - preallocated array[N] - -OUTPUT PARAMETERS: - Y - leading N elements are replaced by X - - -NOTE: destination and source should NOT overlap - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rcopyv(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t j; - - - for(j=0; j<=n-1; j++) - { - y->ptr.p_double[j] = x->ptr.p_double[j]; - } -} - - -/************************************************************************* -Copies vector X[] to Y[] - -INPUT PARAMETERS: - N - vector length - X - array[N], source - Y - preallocated array[N] - -OUTPUT PARAMETERS: - Y - leading N elements are replaced by X - - -NOTE: destination and source should NOT overlap - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void bcopyv(ae_int_t n, - /* Boolean */ ae_vector* x, - /* Boolean */ ae_vector* y, - ae_state *_state) -{ - ae_int_t j; - - - for(j=0; j<=n-1; j++) - { - y->ptr.p_bool[j] = x->ptr.p_bool[j]; - } -} - - -/************************************************************************* -Copies vector X[] to Y[], extended version - -INPUT PARAMETERS: - N - vector length - X - source array - OffsX - source offset - Y - preallocated array[N] - OffsY - destination offset - -OUTPUT PARAMETERS: - Y - N elements starting from OffsY are replaced by X[OffsX:OffsX+N-1] - -NOTE: destination and source should NOT overlap - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rcopyvx(ae_int_t n, - /* Real */ ae_vector* x, - ae_int_t offsx, - /* Real */ ae_vector* y, - ae_int_t offsy, - ae_state *_state) -{ - ae_int_t j; - - - for(j=0; j<=n-1; j++) - { - y->ptr.p_double[offsy+j] = x->ptr.p_double[offsx+j]; - } -} - - -/************************************************************************* -Copies vector X[] to Y[], resizing Y[] if needed. - -INPUT PARAMETERS: - N - vector length - X - array[N], source - Y - possibly preallocated array[N] (resized if needed) - -OUTPUT PARAMETERS: - Y - leading N elements are replaced by X - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rcopyallocv(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t j; - - - if( y->cntptr.p_double[j] = x->ptr.p_double[j]; - } -} - - -/************************************************************************* -Copies matrix X[] to Y[], resizing Y[] if needed. On resize, dimensions of -Y[] are increased - but not decreased. - -INPUT PARAMETERS: - M - rows count - N - cols count - X - array[M,N], source - Y - possibly preallocated array[M,N] (resized if needed) - -OUTPUT PARAMETERS: - Y - leading [M,N] elements are replaced by X - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rcopyallocm(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* x, - /* Real */ ae_matrix* y, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - if( m==0||n==0 ) - { - return; - } - if( y->rowscolsrows, _state), ae_maxint(n, y->cols, _state), _state); - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - y->ptr.pp_double[i][j] = x->ptr.pp_double[i][j]; - } - } -} - - -/************************************************************************* -Copies vector X[] to Y[], resizing Y[] if needed. - -INPUT PARAMETERS: - N - vector length - X - array[N], source - Y - possibly preallocated array[N] (resized if needed) - -OUTPUT PARAMETERS: - Y - leading N elements are replaced by X - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void icopyallocv(ae_int_t n, - /* Integer */ ae_vector* x, - /* Integer */ ae_vector* y, - ae_state *_state) -{ - ae_int_t j; - - - if( y->cntptr.p_int[j] = x->ptr.p_int[j]; - } -} - - -/************************************************************************* -Copies vector X[] to Y[], resizing Y[] if needed. - -INPUT PARAMETERS: - N - vector length - X - array[N], source - Y - possibly preallocated array[N] (resized if needed) - -OUTPUT PARAMETERS: - Y - leading N elements are replaced by X - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void bcopyallocv(ae_int_t n, - /* Boolean */ ae_vector* x, - /* Boolean */ ae_vector* y, - ae_state *_state) -{ - ae_int_t j; - - - if( y->cntptr.p_bool[j] = x->ptr.p_bool[j]; - } -} - - -/************************************************************************* -Copies vector X[] to Y[] - -INPUT PARAMETERS: - N - vector length - X - source array - Y - preallocated array[N] - -OUTPUT PARAMETERS: - Y - X copied to Y - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void icopyv(ae_int_t n, - /* Integer */ ae_vector* x, - /* Integer */ ae_vector* y, - ae_state *_state) -{ - ae_int_t j; - - - for(j=0; j<=n-1; j++) - { - y->ptr.p_int[j] = x->ptr.p_int[j]; - } -} - - -/************************************************************************* -Copies vector X[] to Y[], extended version - -INPUT PARAMETERS: - N - vector length - X - source array - OffsX - source offset - Y - preallocated array[N] - OffsY - destination offset - -OUTPUT PARAMETERS: - Y - N elements starting from OffsY are replaced by X[OffsX:OffsX+N-1] - -NOTE: destination and source should NOT overlap - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void icopyvx(ae_int_t n, - /* Integer */ ae_vector* x, - ae_int_t offsx, - /* Integer */ ae_vector* y, - ae_int_t offsy, - ae_state *_state) -{ - ae_int_t j; - - - for(j=0; j<=n-1; j++) - { - y->ptr.p_int[offsy+j] = x->ptr.p_int[offsx+j]; - } -} - - -/************************************************************************* -Grows X, i.e. changes its size in such a way that: -a) contents is preserved -b) new size is at least N -c) actual size can be larger than N, so subsequent grow() calls can return - without reallocation - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -void igrowv(ae_int_t newn, /* Integer */ ae_vector* x, ae_state *_state) -{ - ae_frame _frame_block; - ae_vector oldx; - ae_int_t oldn; - - ae_frame_make(_state, &_frame_block); - memset(&oldx, 0, sizeof(oldx)); - ae_vector_init(&oldx, 0, DT_INT, _state, ae_true); - - if( x->cnt>=newn ) - { - ae_frame_leave(_state); - return; - } - oldn = x->cnt; - newn = ae_maxint(newn, ae_round(1.8*oldn+1, _state), _state); - ae_swap_vectors(x, &oldx); - ae_vector_set_length(x, newn, _state); - icopyv(oldn, &oldx, x, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Performs copying with multiplication of V*X[] to Y[] - -INPUT PARAMETERS: - N - vector length - V - multiplier - X - array[N], source - Y - preallocated array[N] - -OUTPUT PARAMETERS: - Y - array[N], Y = V*X - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rcopymulv(ae_int_t n, - double v, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=n-1; i++) - { - y->ptr.p_double[i] = v*x->ptr.p_double[i]; - } -} - - -/************************************************************************* -Performs copying with multiplication of V*X[] to Y[I,*] - -INPUT PARAMETERS: - N - vector length - V - multiplier - X - array[N], source - Y - preallocated array[?,N] - RIdx - destination row index - -OUTPUT PARAMETERS: - Y - Y[RIdx,...] = V*X - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rcopymulvr(ae_int_t n, - double v, - /* Real */ ae_vector* x, - /* Real */ ae_matrix* y, - ae_int_t ridx, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=n-1; i++) - { - y->ptr.pp_double[ridx][i] = v*x->ptr.p_double[i]; - } -} - - -/************************************************************************* -Copies vector X[] to row I of A[,] - -INPUT PARAMETERS: - N - vector length - X - array[N], source - A - preallocated 2D array large enough to store result - I - destination row index - -OUTPUT PARAMETERS: - A - leading N elements of I-th row are replaced by X - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rcopyvr(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_matrix* a, - ae_int_t i, - ae_state *_state) -{ - ae_int_t j; - - - for(j=0; j<=n-1; j++) - { - a->ptr.pp_double[i][j] = x->ptr.p_double[j]; - } -} - - -/************************************************************************* -Copies row I of A[,] to vector X[] - -INPUT PARAMETERS: - N - vector length - A - 2D array, source - I - source row index - X - preallocated destination - -OUTPUT PARAMETERS: - X - array[N], destination - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rcopyrv(ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t j; - - - for(j=0; j<=n-1; j++) - { - x->ptr.p_double[j] = a->ptr.pp_double[i][j]; - } -} - - -/************************************************************************* -Copies row I of A[,] to row K of B[,]. - -A[i,...] and B[k,...] may overlap. - -INPUT PARAMETERS: - N - vector length - A - 2D array, source - I - source row index - B - preallocated destination - K - destination row index - -OUTPUT PARAMETERS: - B - row K overwritten - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rcopyrr(ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i, - /* Real */ ae_matrix* b, - ae_int_t k, - ae_state *_state) -{ - ae_int_t j; - - - for(j=0; j<=n-1; j++) - { - b->ptr.pp_double[k][j] = a->ptr.pp_double[i][j]; - } -} - - -/************************************************************************* -Copies vector X[] to column J of A[,] - -INPUT PARAMETERS: - N - vector length - X - array[N], source - A - preallocated 2D array large enough to store result - J - destination col index - -OUTPUT PARAMETERS: - A - leading N elements of J-th column are replaced by X - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rcopyvc(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_matrix* a, - ae_int_t j, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=n-1; i++) - { - a->ptr.pp_double[i][j] = x->ptr.p_double[i]; - } -} - - -/************************************************************************* -Copies column J of A[,] to vector X[] - -INPUT PARAMETERS: - N - vector length - A - source 2D array - J - source col index - -OUTPUT PARAMETERS: - X - preallocated array[N], destination - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rcopycv(ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t j, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = a->ptr.pp_double[i][j]; - } -} - - -/************************************************************************* -Fast kernel - - -- ALGLIB routine -- - 19.01.2010 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixgerf(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - double ralpha, - /* Real */ ae_vector* u, - ae_int_t iu, - /* Real */ ae_vector* v, - ae_int_t iv, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_ABLAS - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixgerf(m, n, a, ia, ja, ralpha, u, iu, v, iv); -#endif -} - - -/************************************************************************* -Fast kernel - - -- ALGLIB routine -- - 19.01.2010 - Bochkanov Sergey -*************************************************************************/ -ae_bool cmatrixrank1f(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Complex */ ae_vector* u, - ae_int_t iu, - /* Complex */ ae_vector* v, - ae_int_t iv, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_ABLAS - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_cmatrixrank1f(m, n, a, ia, ja, u, iu, v, iv); -#endif -} - - -/************************************************************************* -Fast kernel - - -- ALGLIB routine -- - 19.01.2010 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixrank1f(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Real */ ae_vector* u, - ae_int_t iu, - /* Real */ ae_vector* v, - ae_int_t iv, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_ABLAS - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixrank1f(m, n, a, ia, ja, u, iu, v, iv); -#endif -} - - -/************************************************************************* -Fast kernel - - -- ALGLIB routine -- - 19.01.2010 - Bochkanov Sergey -*************************************************************************/ -ae_bool cmatrixrighttrsmf(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_ABLAS - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_cmatrixrighttrsmf(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2); -#endif -} - - -/************************************************************************* -Fast kernel - - -- ALGLIB routine -- - 19.01.2010 - Bochkanov Sergey -*************************************************************************/ -ae_bool cmatrixlefttrsmf(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_ABLAS - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_cmatrixlefttrsmf(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2); -#endif -} - - -/************************************************************************* -Fast kernel - - -- ALGLIB routine -- - 19.01.2010 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixrighttrsmf(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_ABLAS - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixrighttrsmf(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2); -#endif -} - - -/************************************************************************* -Fast kernel - - -- ALGLIB routine -- - 19.01.2010 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixlefttrsmf(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_ABLAS - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixlefttrsmf(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2); -#endif -} - - -/************************************************************************* -Fast kernel - - -- ALGLIB routine -- - 19.01.2010 - Bochkanov Sergey -*************************************************************************/ -ae_bool cmatrixherkf(ae_int_t n, - ae_int_t k, - double alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_ABLAS - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_cmatrixherkf(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper); -#endif -} - - -/************************************************************************* -Fast kernel - - -- ALGLIB routine -- - 19.01.2010 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixsyrkf(ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_ABLAS - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixsyrkf(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper); -#endif -} - - -/************************************************************************* -Fast kernel - - -- ALGLIB routine -- - 19.01.2010 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixgemmf(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_ABLAS - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixgemmf(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc); -#endif -} - - -/************************************************************************* -Fast kernel - - -- ALGLIB routine -- - 19.01.2010 - Bochkanov Sergey -*************************************************************************/ -ae_bool cmatrixgemmf(ae_int_t m, - ae_int_t n, - ae_int_t k, - ae_complex alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Complex */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - ae_complex beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_ABLAS - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_cmatrixgemmf(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc); -#endif -} - - -/************************************************************************* -CMatrixGEMM kernel, basecase code for CMatrixGEMM. - -This subroutine calculates C = alpha*op1(A)*op2(B) +beta*C where: -* C is MxN general matrix -* op1(A) is MxK matrix -* op2(B) is KxN matrix -* "op" may be identity transformation, transposition, conjugate transposition - -Additional info: -* multiplication result replaces C. If Beta=0, C elements are not used in - calculations (not multiplied by zero - just not referenced) -* if Alpha=0, A is not used (not multiplied by zero - just not referenced) -* if both Beta and Alpha are zero, C is filled by zeros. - -IMPORTANT: - -This function does NOT preallocate output matrix C, it MUST be preallocated -by caller prior to calling this function. In case C does not have enough -space to store result, exception will be generated. - -INPUT PARAMETERS - M - matrix size, M>0 - N - matrix size, N>0 - K - matrix size, K>0 - Alpha - coefficient - A - matrix - IA - submatrix offset - JA - submatrix offset - OpTypeA - transformation type: - * 0 - no transformation - * 1 - transposition - * 2 - conjugate transposition - B - matrix - IB - submatrix offset - JB - submatrix offset - OpTypeB - transformation type: - * 0 - no transformation - * 1 - transposition - * 2 - conjugate transposition - Beta - coefficient - C - PREALLOCATED output matrix - IC - submatrix offset - JC - submatrix offset - - -- ALGLIB routine -- - 27.03.2013 - Bochkanov Sergey -*************************************************************************/ -void cmatrixgemmk(ae_int_t m, - ae_int_t n, - ae_int_t k, - ae_complex alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Complex */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - ae_complex beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_complex v; - ae_complex v00; - ae_complex v01; - ae_complex v10; - ae_complex v11; - double v00x; - double v00y; - double v01x; - double v01y; - double v10x; - double v10y; - double v11x; - double v11y; - double a0x; - double a0y; - double a1x; - double a1y; - double b0x; - double b0y; - double b1x; - double b1y; - ae_int_t idxa0; - ae_int_t idxa1; - ae_int_t idxb0; - ae_int_t idxb1; - ae_int_t i0; - ae_int_t i1; - ae_int_t ik; - ae_int_t j0; - ae_int_t j1; - ae_int_t jk; - ae_int_t t; - ae_int_t offsa; - ae_int_t offsb; - - - - /* - * if matrix size is zero - */ - if( m==0||n==0 ) - { - return; - } - - /* - * Try optimized code - */ - if( cmatrixgemmf(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state) ) - { - return; - } - - /* - * if K=0 or Alpha=0, then C=Beta*C - */ - if( k==0||ae_c_eq_d(alpha,(double)(0)) ) - { - if( ae_c_neq_d(beta,(double)(1)) ) - { - if( ae_c_neq_d(beta,(double)(0)) ) - { - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - c->ptr.pp_complex[ic+i][jc+j] = ae_c_mul(beta,c->ptr.pp_complex[ic+i][jc+j]); - } - } - } - else - { - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - c->ptr.pp_complex[ic+i][jc+j] = ae_complex_from_i(0); - } - } - } - } - return; - } - - /* - * This phase is not really necessary, but compiler complains - * about "possibly uninitialized variables" - */ - a0x = (double)(0); - a0y = (double)(0); - a1x = (double)(0); - a1y = (double)(0); - b0x = (double)(0); - b0y = (double)(0); - b1x = (double)(0); - b1y = (double)(0); - - /* - * General case - */ - i = 0; - while(iptr.pp_complex[idxa0][offsa].x; - a0y = a->ptr.pp_complex[idxa0][offsa].y; - a1x = a->ptr.pp_complex[idxa1][offsa].x; - a1y = a->ptr.pp_complex[idxa1][offsa].y; - } - if( optypea==1 ) - { - a0x = a->ptr.pp_complex[offsa][idxa0].x; - a0y = a->ptr.pp_complex[offsa][idxa0].y; - a1x = a->ptr.pp_complex[offsa][idxa1].x; - a1y = a->ptr.pp_complex[offsa][idxa1].y; - } - if( optypea==2 ) - { - a0x = a->ptr.pp_complex[offsa][idxa0].x; - a0y = -a->ptr.pp_complex[offsa][idxa0].y; - a1x = a->ptr.pp_complex[offsa][idxa1].x; - a1y = -a->ptr.pp_complex[offsa][idxa1].y; - } - if( optypeb==0 ) - { - b0x = b->ptr.pp_complex[offsb][idxb0].x; - b0y = b->ptr.pp_complex[offsb][idxb0].y; - b1x = b->ptr.pp_complex[offsb][idxb1].x; - b1y = b->ptr.pp_complex[offsb][idxb1].y; - } - if( optypeb==1 ) - { - b0x = b->ptr.pp_complex[idxb0][offsb].x; - b0y = b->ptr.pp_complex[idxb0][offsb].y; - b1x = b->ptr.pp_complex[idxb1][offsb].x; - b1y = b->ptr.pp_complex[idxb1][offsb].y; - } - if( optypeb==2 ) - { - b0x = b->ptr.pp_complex[idxb0][offsb].x; - b0y = -b->ptr.pp_complex[idxb0][offsb].y; - b1x = b->ptr.pp_complex[idxb1][offsb].x; - b1y = -b->ptr.pp_complex[idxb1][offsb].y; - } - v00x = v00x+a0x*b0x-a0y*b0y; - v00y = v00y+a0x*b0y+a0y*b0x; - v01x = v01x+a0x*b1x-a0y*b1y; - v01y = v01y+a0x*b1y+a0y*b1x; - v10x = v10x+a1x*b0x-a1y*b0y; - v10y = v10y+a1x*b0y+a1y*b0x; - v11x = v11x+a1x*b1x-a1y*b1y; - v11y = v11y+a1x*b1y+a1y*b1x; - offsa = offsa+1; - offsb = offsb+1; - } - v00.x = v00x; - v00.y = v00y; - v10.x = v10x; - v10.y = v10y; - v01.x = v01x; - v01.y = v01y; - v11.x = v11x; - v11.y = v11y; - if( ae_c_eq_d(beta,(double)(0)) ) - { - c->ptr.pp_complex[ic+i+0][jc+j+0] = ae_c_mul(alpha,v00); - c->ptr.pp_complex[ic+i+0][jc+j+1] = ae_c_mul(alpha,v01); - c->ptr.pp_complex[ic+i+1][jc+j+0] = ae_c_mul(alpha,v10); - c->ptr.pp_complex[ic+i+1][jc+j+1] = ae_c_mul(alpha,v11); - } - else - { - c->ptr.pp_complex[ic+i+0][jc+j+0] = ae_c_add(ae_c_mul(beta,c->ptr.pp_complex[ic+i+0][jc+j+0]),ae_c_mul(alpha,v00)); - c->ptr.pp_complex[ic+i+0][jc+j+1] = ae_c_add(ae_c_mul(beta,c->ptr.pp_complex[ic+i+0][jc+j+1]),ae_c_mul(alpha,v01)); - c->ptr.pp_complex[ic+i+1][jc+j+0] = ae_c_add(ae_c_mul(beta,c->ptr.pp_complex[ic+i+1][jc+j+0]),ae_c_mul(alpha,v10)); - c->ptr.pp_complex[ic+i+1][jc+j+1] = ae_c_add(ae_c_mul(beta,c->ptr.pp_complex[ic+i+1][jc+j+1]),ae_c_mul(alpha,v11)); - } - } - else - { - - /* - * Determine submatrix [I0..I1]x[J0..J1] to process - */ - i0 = i; - i1 = ae_minint(i+1, m-1, _state); - j0 = j; - j1 = ae_minint(j+1, n-1, _state); - - /* - * Process submatrix - */ - for(ik=i0; ik<=i1; ik++) - { - for(jk=j0; jk<=j1; jk++) - { - if( k==0||ae_c_eq_d(alpha,(double)(0)) ) - { - v = ae_complex_from_i(0); - } - else - { - v = ae_complex_from_d(0.0); - if( optypea==0&&optypeb==0 ) - { - v = ae_v_cdotproduct(&a->ptr.pp_complex[ia+ik][ja], 1, "N", &b->ptr.pp_complex[ib][jb+jk], b->stride, "N", ae_v_len(ja,ja+k-1)); - } - if( optypea==0&&optypeb==1 ) - { - v = ae_v_cdotproduct(&a->ptr.pp_complex[ia+ik][ja], 1, "N", &b->ptr.pp_complex[ib+jk][jb], 1, "N", ae_v_len(ja,ja+k-1)); - } - if( optypea==0&&optypeb==2 ) - { - v = ae_v_cdotproduct(&a->ptr.pp_complex[ia+ik][ja], 1, "N", &b->ptr.pp_complex[ib+jk][jb], 1, "Conj", ae_v_len(ja,ja+k-1)); - } - if( optypea==1&&optypeb==0 ) - { - v = ae_v_cdotproduct(&a->ptr.pp_complex[ia][ja+ik], a->stride, "N", &b->ptr.pp_complex[ib][jb+jk], b->stride, "N", ae_v_len(ia,ia+k-1)); - } - if( optypea==1&&optypeb==1 ) - { - v = ae_v_cdotproduct(&a->ptr.pp_complex[ia][ja+ik], a->stride, "N", &b->ptr.pp_complex[ib+jk][jb], 1, "N", ae_v_len(ia,ia+k-1)); - } - if( optypea==1&&optypeb==2 ) - { - v = ae_v_cdotproduct(&a->ptr.pp_complex[ia][ja+ik], a->stride, "N", &b->ptr.pp_complex[ib+jk][jb], 1, "Conj", ae_v_len(ia,ia+k-1)); - } - if( optypea==2&&optypeb==0 ) - { - v = ae_v_cdotproduct(&a->ptr.pp_complex[ia][ja+ik], a->stride, "Conj", &b->ptr.pp_complex[ib][jb+jk], b->stride, "N", ae_v_len(ia,ia+k-1)); - } - if( optypea==2&&optypeb==1 ) - { - v = ae_v_cdotproduct(&a->ptr.pp_complex[ia][ja+ik], a->stride, "Conj", &b->ptr.pp_complex[ib+jk][jb], 1, "N", ae_v_len(ia,ia+k-1)); - } - if( optypea==2&&optypeb==2 ) - { - v = ae_v_cdotproduct(&a->ptr.pp_complex[ia][ja+ik], a->stride, "Conj", &b->ptr.pp_complex[ib+jk][jb], 1, "Conj", ae_v_len(ia,ia+k-1)); - } - } - if( ae_c_eq_d(beta,(double)(0)) ) - { - c->ptr.pp_complex[ic+ik][jc+jk] = ae_c_mul(alpha,v); - } - else - { - c->ptr.pp_complex[ic+ik][jc+jk] = ae_c_add(ae_c_mul(beta,c->ptr.pp_complex[ic+ik][jc+jk]),ae_c_mul(alpha,v)); - } - } - } - } - j = j+2; - } - i = i+2; - } -} - - -/************************************************************************* -RMatrixGEMM kernel, basecase code for RMatrixGEMM. - -This subroutine calculates C = alpha*op1(A)*op2(B) +beta*C where: -* C is MxN general matrix -* op1(A) is MxK matrix -* op2(B) is KxN matrix -* "op" may be identity transformation, transposition - -Additional info: -* multiplication result replaces C. If Beta=0, C elements are not used in - calculations (not multiplied by zero - just not referenced) -* if Alpha=0, A is not used (not multiplied by zero - just not referenced) -* if both Beta and Alpha are zero, C is filled by zeros. - -IMPORTANT: - -This function does NOT preallocate output matrix C, it MUST be preallocated -by caller prior to calling this function. In case C does not have enough -space to store result, exception will be generated. - -INPUT PARAMETERS - M - matrix size, M>0 - N - matrix size, N>0 - K - matrix size, K>0 - Alpha - coefficient - A - matrix - IA - submatrix offset - JA - submatrix offset - OpTypeA - transformation type: - * 0 - no transformation - * 1 - transposition - B - matrix - IB - submatrix offset - JB - submatrix offset - OpTypeB - transformation type: - * 0 - no transformation - * 1 - transposition - Beta - coefficient - C - PREALLOCATED output matrix - IC - submatrix offset - JC - submatrix offset - - -- ALGLIB routine -- - 27.03.2013 - Bochkanov Sergey -*************************************************************************/ -void rmatrixgemmk(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - - /* - * if matrix size is zero - */ - if( m==0||n==0 ) - { - return; - } - - /* - * Try optimized code - */ - if( rmatrixgemmf(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state) ) - { - return; - } - - /* - * if K=0 or Alpha=0, then C=Beta*C - */ - if( k==0||ae_fp_eq(alpha,(double)(0)) ) - { - if( ae_fp_neq(beta,(double)(1)) ) - { - if( ae_fp_neq(beta,(double)(0)) ) - { - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - c->ptr.pp_double[ic+i][jc+j] = beta*c->ptr.pp_double[ic+i][jc+j]; - } - } - } - else - { - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - c->ptr.pp_double[ic+i][jc+j] = (double)(0); - } - } - } - } - return; - } - - /* - * Call specialized code. - * - * NOTE: specialized code was moved to separate function because of strange - * issues with instructions cache on some systems; Having too long - * functions significantly slows down internal loop of the algorithm. - */ - if( optypea==0&&optypeb==0 ) - { - rmatrixgemmk44v00(m, n, k, alpha, a, ia, ja, b, ib, jb, beta, c, ic, jc, _state); - } - if( optypea==0&&optypeb!=0 ) - { - rmatrixgemmk44v01(m, n, k, alpha, a, ia, ja, b, ib, jb, beta, c, ic, jc, _state); - } - if( optypea!=0&&optypeb==0 ) - { - rmatrixgemmk44v10(m, n, k, alpha, a, ia, ja, b, ib, jb, beta, c, ic, jc, _state); - } - if( optypea!=0&&optypeb!=0 ) - { - rmatrixgemmk44v11(m, n, k, alpha, a, ia, ja, b, ib, jb, beta, c, ic, jc, _state); - } -} - - -/************************************************************************* -RMatrixGEMM kernel, basecase code for RMatrixGEMM, specialized for sitation -with OpTypeA=0 and OpTypeB=0. - -Additional info: -* this function requires that Alpha<>0 (assertion is thrown otherwise) - -INPUT PARAMETERS - M - matrix size, M>0 - N - matrix size, N>0 - K - matrix size, K>0 - Alpha - coefficient - A - matrix - IA - submatrix offset - JA - submatrix offset - B - matrix - IB - submatrix offset - JB - submatrix offset - Beta - coefficient - C - PREALLOCATED output matrix - IC - submatrix offset - JC - submatrix offset - - -- ALGLIB routine -- - 27.03.2013 - Bochkanov Sergey -*************************************************************************/ -void rmatrixgemmk44v00(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - double v00; - double v01; - double v02; - double v03; - double v10; - double v11; - double v12; - double v13; - double v20; - double v21; - double v22; - double v23; - double v30; - double v31; - double v32; - double v33; - double a0; - double a1; - double a2; - double a3; - double b0; - double b1; - double b2; - double b3; - ae_int_t idxa0; - ae_int_t idxa1; - ae_int_t idxa2; - ae_int_t idxa3; - ae_int_t idxb0; - ae_int_t idxb1; - ae_int_t idxb2; - ae_int_t idxb3; - ae_int_t i0; - ae_int_t i1; - ae_int_t ik; - ae_int_t j0; - ae_int_t j1; - ae_int_t jk; - ae_int_t t; - ae_int_t offsa; - ae_int_t offsb; - - - ae_assert(ae_fp_neq(alpha,(double)(0)), "RMatrixGEMMK44V00: internal error (Alpha=0)", _state); - - /* - * if matrix size is zero - */ - if( m==0||n==0 ) - { - return; - } - - /* - * A*B - */ - i = 0; - while(iptr.pp_double[idxa0][offsa]; - a1 = a->ptr.pp_double[idxa1][offsa]; - b0 = b->ptr.pp_double[offsb][idxb0]; - b1 = b->ptr.pp_double[offsb][idxb1]; - v00 = v00+a0*b0; - v01 = v01+a0*b1; - v10 = v10+a1*b0; - v11 = v11+a1*b1; - a2 = a->ptr.pp_double[idxa2][offsa]; - a3 = a->ptr.pp_double[idxa3][offsa]; - v20 = v20+a2*b0; - v21 = v21+a2*b1; - v30 = v30+a3*b0; - v31 = v31+a3*b1; - b2 = b->ptr.pp_double[offsb][idxb2]; - b3 = b->ptr.pp_double[offsb][idxb3]; - v22 = v22+a2*b2; - v23 = v23+a2*b3; - v32 = v32+a3*b2; - v33 = v33+a3*b3; - v02 = v02+a0*b2; - v03 = v03+a0*b3; - v12 = v12+a1*b2; - v13 = v13+a1*b3; - offsa = offsa+1; - offsb = offsb+1; - } - if( ae_fp_eq(beta,(double)(0)) ) - { - c->ptr.pp_double[ic+i+0][jc+j+0] = alpha*v00; - c->ptr.pp_double[ic+i+0][jc+j+1] = alpha*v01; - c->ptr.pp_double[ic+i+0][jc+j+2] = alpha*v02; - c->ptr.pp_double[ic+i+0][jc+j+3] = alpha*v03; - c->ptr.pp_double[ic+i+1][jc+j+0] = alpha*v10; - c->ptr.pp_double[ic+i+1][jc+j+1] = alpha*v11; - c->ptr.pp_double[ic+i+1][jc+j+2] = alpha*v12; - c->ptr.pp_double[ic+i+1][jc+j+3] = alpha*v13; - c->ptr.pp_double[ic+i+2][jc+j+0] = alpha*v20; - c->ptr.pp_double[ic+i+2][jc+j+1] = alpha*v21; - c->ptr.pp_double[ic+i+2][jc+j+2] = alpha*v22; - c->ptr.pp_double[ic+i+2][jc+j+3] = alpha*v23; - c->ptr.pp_double[ic+i+3][jc+j+0] = alpha*v30; - c->ptr.pp_double[ic+i+3][jc+j+1] = alpha*v31; - c->ptr.pp_double[ic+i+3][jc+j+2] = alpha*v32; - c->ptr.pp_double[ic+i+3][jc+j+3] = alpha*v33; - } - else - { - c->ptr.pp_double[ic+i+0][jc+j+0] = beta*c->ptr.pp_double[ic+i+0][jc+j+0]+alpha*v00; - c->ptr.pp_double[ic+i+0][jc+j+1] = beta*c->ptr.pp_double[ic+i+0][jc+j+1]+alpha*v01; - c->ptr.pp_double[ic+i+0][jc+j+2] = beta*c->ptr.pp_double[ic+i+0][jc+j+2]+alpha*v02; - c->ptr.pp_double[ic+i+0][jc+j+3] = beta*c->ptr.pp_double[ic+i+0][jc+j+3]+alpha*v03; - c->ptr.pp_double[ic+i+1][jc+j+0] = beta*c->ptr.pp_double[ic+i+1][jc+j+0]+alpha*v10; - c->ptr.pp_double[ic+i+1][jc+j+1] = beta*c->ptr.pp_double[ic+i+1][jc+j+1]+alpha*v11; - c->ptr.pp_double[ic+i+1][jc+j+2] = beta*c->ptr.pp_double[ic+i+1][jc+j+2]+alpha*v12; - c->ptr.pp_double[ic+i+1][jc+j+3] = beta*c->ptr.pp_double[ic+i+1][jc+j+3]+alpha*v13; - c->ptr.pp_double[ic+i+2][jc+j+0] = beta*c->ptr.pp_double[ic+i+2][jc+j+0]+alpha*v20; - c->ptr.pp_double[ic+i+2][jc+j+1] = beta*c->ptr.pp_double[ic+i+2][jc+j+1]+alpha*v21; - c->ptr.pp_double[ic+i+2][jc+j+2] = beta*c->ptr.pp_double[ic+i+2][jc+j+2]+alpha*v22; - c->ptr.pp_double[ic+i+2][jc+j+3] = beta*c->ptr.pp_double[ic+i+2][jc+j+3]+alpha*v23; - c->ptr.pp_double[ic+i+3][jc+j+0] = beta*c->ptr.pp_double[ic+i+3][jc+j+0]+alpha*v30; - c->ptr.pp_double[ic+i+3][jc+j+1] = beta*c->ptr.pp_double[ic+i+3][jc+j+1]+alpha*v31; - c->ptr.pp_double[ic+i+3][jc+j+2] = beta*c->ptr.pp_double[ic+i+3][jc+j+2]+alpha*v32; - c->ptr.pp_double[ic+i+3][jc+j+3] = beta*c->ptr.pp_double[ic+i+3][jc+j+3]+alpha*v33; - } - } - else - { - - /* - * Determine submatrix [I0..I1]x[J0..J1] to process - */ - i0 = i; - i1 = ae_minint(i+3, m-1, _state); - j0 = j; - j1 = ae_minint(j+3, n-1, _state); - - /* - * Process submatrix - */ - for(ik=i0; ik<=i1; ik++) - { - for(jk=j0; jk<=j1; jk++) - { - if( k==0||ae_fp_eq(alpha,(double)(0)) ) - { - v = (double)(0); - } - else - { - v = ae_v_dotproduct(&a->ptr.pp_double[ia+ik][ja], 1, &b->ptr.pp_double[ib][jb+jk], b->stride, ae_v_len(ja,ja+k-1)); - } - if( ae_fp_eq(beta,(double)(0)) ) - { - c->ptr.pp_double[ic+ik][jc+jk] = alpha*v; - } - else - { - c->ptr.pp_double[ic+ik][jc+jk] = beta*c->ptr.pp_double[ic+ik][jc+jk]+alpha*v; - } - } - } - } - j = j+4; - } - i = i+4; - } -} - - -/************************************************************************* -RMatrixGEMM kernel, basecase code for RMatrixGEMM, specialized for sitation -with OpTypeA=0 and OpTypeB=1. - -Additional info: -* this function requires that Alpha<>0 (assertion is thrown otherwise) - -INPUT PARAMETERS - M - matrix size, M>0 - N - matrix size, N>0 - K - matrix size, K>0 - Alpha - coefficient - A - matrix - IA - submatrix offset - JA - submatrix offset - B - matrix - IB - submatrix offset - JB - submatrix offset - Beta - coefficient - C - PREALLOCATED output matrix - IC - submatrix offset - JC - submatrix offset - - -- ALGLIB routine -- - 27.03.2013 - Bochkanov Sergey -*************************************************************************/ -void rmatrixgemmk44v01(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - double v00; - double v01; - double v02; - double v03; - double v10; - double v11; - double v12; - double v13; - double v20; - double v21; - double v22; - double v23; - double v30; - double v31; - double v32; - double v33; - double a0; - double a1; - double a2; - double a3; - double b0; - double b1; - double b2; - double b3; - ae_int_t idxa0; - ae_int_t idxa1; - ae_int_t idxa2; - ae_int_t idxa3; - ae_int_t idxb0; - ae_int_t idxb1; - ae_int_t idxb2; - ae_int_t idxb3; - ae_int_t i0; - ae_int_t i1; - ae_int_t ik; - ae_int_t j0; - ae_int_t j1; - ae_int_t jk; - ae_int_t t; - ae_int_t offsa; - ae_int_t offsb; - - - ae_assert(ae_fp_neq(alpha,(double)(0)), "RMatrixGEMMK44V00: internal error (Alpha=0)", _state); - - /* - * if matrix size is zero - */ - if( m==0||n==0 ) - { - return; - } - - /* - * A*B' - */ - i = 0; - while(iptr.pp_double[idxa0][offsa]; - a1 = a->ptr.pp_double[idxa1][offsa]; - b0 = b->ptr.pp_double[idxb0][offsb]; - b1 = b->ptr.pp_double[idxb1][offsb]; - v00 = v00+a0*b0; - v01 = v01+a0*b1; - v10 = v10+a1*b0; - v11 = v11+a1*b1; - a2 = a->ptr.pp_double[idxa2][offsa]; - a3 = a->ptr.pp_double[idxa3][offsa]; - v20 = v20+a2*b0; - v21 = v21+a2*b1; - v30 = v30+a3*b0; - v31 = v31+a3*b1; - b2 = b->ptr.pp_double[idxb2][offsb]; - b3 = b->ptr.pp_double[idxb3][offsb]; - v22 = v22+a2*b2; - v23 = v23+a2*b3; - v32 = v32+a3*b2; - v33 = v33+a3*b3; - v02 = v02+a0*b2; - v03 = v03+a0*b3; - v12 = v12+a1*b2; - v13 = v13+a1*b3; - offsa = offsa+1; - offsb = offsb+1; - } - if( ae_fp_eq(beta,(double)(0)) ) - { - c->ptr.pp_double[ic+i+0][jc+j+0] = alpha*v00; - c->ptr.pp_double[ic+i+0][jc+j+1] = alpha*v01; - c->ptr.pp_double[ic+i+0][jc+j+2] = alpha*v02; - c->ptr.pp_double[ic+i+0][jc+j+3] = alpha*v03; - c->ptr.pp_double[ic+i+1][jc+j+0] = alpha*v10; - c->ptr.pp_double[ic+i+1][jc+j+1] = alpha*v11; - c->ptr.pp_double[ic+i+1][jc+j+2] = alpha*v12; - c->ptr.pp_double[ic+i+1][jc+j+3] = alpha*v13; - c->ptr.pp_double[ic+i+2][jc+j+0] = alpha*v20; - c->ptr.pp_double[ic+i+2][jc+j+1] = alpha*v21; - c->ptr.pp_double[ic+i+2][jc+j+2] = alpha*v22; - c->ptr.pp_double[ic+i+2][jc+j+3] = alpha*v23; - c->ptr.pp_double[ic+i+3][jc+j+0] = alpha*v30; - c->ptr.pp_double[ic+i+3][jc+j+1] = alpha*v31; - c->ptr.pp_double[ic+i+3][jc+j+2] = alpha*v32; - c->ptr.pp_double[ic+i+3][jc+j+3] = alpha*v33; - } - else - { - c->ptr.pp_double[ic+i+0][jc+j+0] = beta*c->ptr.pp_double[ic+i+0][jc+j+0]+alpha*v00; - c->ptr.pp_double[ic+i+0][jc+j+1] = beta*c->ptr.pp_double[ic+i+0][jc+j+1]+alpha*v01; - c->ptr.pp_double[ic+i+0][jc+j+2] = beta*c->ptr.pp_double[ic+i+0][jc+j+2]+alpha*v02; - c->ptr.pp_double[ic+i+0][jc+j+3] = beta*c->ptr.pp_double[ic+i+0][jc+j+3]+alpha*v03; - c->ptr.pp_double[ic+i+1][jc+j+0] = beta*c->ptr.pp_double[ic+i+1][jc+j+0]+alpha*v10; - c->ptr.pp_double[ic+i+1][jc+j+1] = beta*c->ptr.pp_double[ic+i+1][jc+j+1]+alpha*v11; - c->ptr.pp_double[ic+i+1][jc+j+2] = beta*c->ptr.pp_double[ic+i+1][jc+j+2]+alpha*v12; - c->ptr.pp_double[ic+i+1][jc+j+3] = beta*c->ptr.pp_double[ic+i+1][jc+j+3]+alpha*v13; - c->ptr.pp_double[ic+i+2][jc+j+0] = beta*c->ptr.pp_double[ic+i+2][jc+j+0]+alpha*v20; - c->ptr.pp_double[ic+i+2][jc+j+1] = beta*c->ptr.pp_double[ic+i+2][jc+j+1]+alpha*v21; - c->ptr.pp_double[ic+i+2][jc+j+2] = beta*c->ptr.pp_double[ic+i+2][jc+j+2]+alpha*v22; - c->ptr.pp_double[ic+i+2][jc+j+3] = beta*c->ptr.pp_double[ic+i+2][jc+j+3]+alpha*v23; - c->ptr.pp_double[ic+i+3][jc+j+0] = beta*c->ptr.pp_double[ic+i+3][jc+j+0]+alpha*v30; - c->ptr.pp_double[ic+i+3][jc+j+1] = beta*c->ptr.pp_double[ic+i+3][jc+j+1]+alpha*v31; - c->ptr.pp_double[ic+i+3][jc+j+2] = beta*c->ptr.pp_double[ic+i+3][jc+j+2]+alpha*v32; - c->ptr.pp_double[ic+i+3][jc+j+3] = beta*c->ptr.pp_double[ic+i+3][jc+j+3]+alpha*v33; - } - } - else - { - - /* - * Determine submatrix [I0..I1]x[J0..J1] to process - */ - i0 = i; - i1 = ae_minint(i+3, m-1, _state); - j0 = j; - j1 = ae_minint(j+3, n-1, _state); - - /* - * Process submatrix - */ - for(ik=i0; ik<=i1; ik++) - { - for(jk=j0; jk<=j1; jk++) - { - if( k==0||ae_fp_eq(alpha,(double)(0)) ) - { - v = (double)(0); - } - else - { - v = ae_v_dotproduct(&a->ptr.pp_double[ia+ik][ja], 1, &b->ptr.pp_double[ib+jk][jb], 1, ae_v_len(ja,ja+k-1)); - } - if( ae_fp_eq(beta,(double)(0)) ) - { - c->ptr.pp_double[ic+ik][jc+jk] = alpha*v; - } - else - { - c->ptr.pp_double[ic+ik][jc+jk] = beta*c->ptr.pp_double[ic+ik][jc+jk]+alpha*v; - } - } - } - } - j = j+4; - } - i = i+4; - } -} - - -/************************************************************************* -RMatrixGEMM kernel, basecase code for RMatrixGEMM, specialized for sitation -with OpTypeA=1 and OpTypeB=0. - -Additional info: -* this function requires that Alpha<>0 (assertion is thrown otherwise) - -INPUT PARAMETERS - M - matrix size, M>0 - N - matrix size, N>0 - K - matrix size, K>0 - Alpha - coefficient - A - matrix - IA - submatrix offset - JA - submatrix offset - B - matrix - IB - submatrix offset - JB - submatrix offset - Beta - coefficient - C - PREALLOCATED output matrix - IC - submatrix offset - JC - submatrix offset - - -- ALGLIB routine -- - 27.03.2013 - Bochkanov Sergey -*************************************************************************/ -void rmatrixgemmk44v10(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - double v00; - double v01; - double v02; - double v03; - double v10; - double v11; - double v12; - double v13; - double v20; - double v21; - double v22; - double v23; - double v30; - double v31; - double v32; - double v33; - double a0; - double a1; - double a2; - double a3; - double b0; - double b1; - double b2; - double b3; - ae_int_t idxa0; - ae_int_t idxa1; - ae_int_t idxa2; - ae_int_t idxa3; - ae_int_t idxb0; - ae_int_t idxb1; - ae_int_t idxb2; - ae_int_t idxb3; - ae_int_t i0; - ae_int_t i1; - ae_int_t ik; - ae_int_t j0; - ae_int_t j1; - ae_int_t jk; - ae_int_t t; - ae_int_t offsa; - ae_int_t offsb; - - - ae_assert(ae_fp_neq(alpha,(double)(0)), "RMatrixGEMMK44V00: internal error (Alpha=0)", _state); - - /* - * if matrix size is zero - */ - if( m==0||n==0 ) - { - return; - } - - /* - * A'*B - */ - i = 0; - while(iptr.pp_double[offsa][idxa0]; - a1 = a->ptr.pp_double[offsa][idxa1]; - b0 = b->ptr.pp_double[offsb][idxb0]; - b1 = b->ptr.pp_double[offsb][idxb1]; - v00 = v00+a0*b0; - v01 = v01+a0*b1; - v10 = v10+a1*b0; - v11 = v11+a1*b1; - a2 = a->ptr.pp_double[offsa][idxa2]; - a3 = a->ptr.pp_double[offsa][idxa3]; - v20 = v20+a2*b0; - v21 = v21+a2*b1; - v30 = v30+a3*b0; - v31 = v31+a3*b1; - b2 = b->ptr.pp_double[offsb][idxb2]; - b3 = b->ptr.pp_double[offsb][idxb3]; - v22 = v22+a2*b2; - v23 = v23+a2*b3; - v32 = v32+a3*b2; - v33 = v33+a3*b3; - v02 = v02+a0*b2; - v03 = v03+a0*b3; - v12 = v12+a1*b2; - v13 = v13+a1*b3; - offsa = offsa+1; - offsb = offsb+1; - } - if( ae_fp_eq(beta,(double)(0)) ) - { - c->ptr.pp_double[ic+i+0][jc+j+0] = alpha*v00; - c->ptr.pp_double[ic+i+0][jc+j+1] = alpha*v01; - c->ptr.pp_double[ic+i+0][jc+j+2] = alpha*v02; - c->ptr.pp_double[ic+i+0][jc+j+3] = alpha*v03; - c->ptr.pp_double[ic+i+1][jc+j+0] = alpha*v10; - c->ptr.pp_double[ic+i+1][jc+j+1] = alpha*v11; - c->ptr.pp_double[ic+i+1][jc+j+2] = alpha*v12; - c->ptr.pp_double[ic+i+1][jc+j+3] = alpha*v13; - c->ptr.pp_double[ic+i+2][jc+j+0] = alpha*v20; - c->ptr.pp_double[ic+i+2][jc+j+1] = alpha*v21; - c->ptr.pp_double[ic+i+2][jc+j+2] = alpha*v22; - c->ptr.pp_double[ic+i+2][jc+j+3] = alpha*v23; - c->ptr.pp_double[ic+i+3][jc+j+0] = alpha*v30; - c->ptr.pp_double[ic+i+3][jc+j+1] = alpha*v31; - c->ptr.pp_double[ic+i+3][jc+j+2] = alpha*v32; - c->ptr.pp_double[ic+i+3][jc+j+3] = alpha*v33; - } - else - { - c->ptr.pp_double[ic+i+0][jc+j+0] = beta*c->ptr.pp_double[ic+i+0][jc+j+0]+alpha*v00; - c->ptr.pp_double[ic+i+0][jc+j+1] = beta*c->ptr.pp_double[ic+i+0][jc+j+1]+alpha*v01; - c->ptr.pp_double[ic+i+0][jc+j+2] = beta*c->ptr.pp_double[ic+i+0][jc+j+2]+alpha*v02; - c->ptr.pp_double[ic+i+0][jc+j+3] = beta*c->ptr.pp_double[ic+i+0][jc+j+3]+alpha*v03; - c->ptr.pp_double[ic+i+1][jc+j+0] = beta*c->ptr.pp_double[ic+i+1][jc+j+0]+alpha*v10; - c->ptr.pp_double[ic+i+1][jc+j+1] = beta*c->ptr.pp_double[ic+i+1][jc+j+1]+alpha*v11; - c->ptr.pp_double[ic+i+1][jc+j+2] = beta*c->ptr.pp_double[ic+i+1][jc+j+2]+alpha*v12; - c->ptr.pp_double[ic+i+1][jc+j+3] = beta*c->ptr.pp_double[ic+i+1][jc+j+3]+alpha*v13; - c->ptr.pp_double[ic+i+2][jc+j+0] = beta*c->ptr.pp_double[ic+i+2][jc+j+0]+alpha*v20; - c->ptr.pp_double[ic+i+2][jc+j+1] = beta*c->ptr.pp_double[ic+i+2][jc+j+1]+alpha*v21; - c->ptr.pp_double[ic+i+2][jc+j+2] = beta*c->ptr.pp_double[ic+i+2][jc+j+2]+alpha*v22; - c->ptr.pp_double[ic+i+2][jc+j+3] = beta*c->ptr.pp_double[ic+i+2][jc+j+3]+alpha*v23; - c->ptr.pp_double[ic+i+3][jc+j+0] = beta*c->ptr.pp_double[ic+i+3][jc+j+0]+alpha*v30; - c->ptr.pp_double[ic+i+3][jc+j+1] = beta*c->ptr.pp_double[ic+i+3][jc+j+1]+alpha*v31; - c->ptr.pp_double[ic+i+3][jc+j+2] = beta*c->ptr.pp_double[ic+i+3][jc+j+2]+alpha*v32; - c->ptr.pp_double[ic+i+3][jc+j+3] = beta*c->ptr.pp_double[ic+i+3][jc+j+3]+alpha*v33; - } - } - else - { - - /* - * Determine submatrix [I0..I1]x[J0..J1] to process - */ - i0 = i; - i1 = ae_minint(i+3, m-1, _state); - j0 = j; - j1 = ae_minint(j+3, n-1, _state); - - /* - * Process submatrix - */ - for(ik=i0; ik<=i1; ik++) - { - for(jk=j0; jk<=j1; jk++) - { - if( k==0||ae_fp_eq(alpha,(double)(0)) ) - { - v = (double)(0); - } - else - { - v = 0.0; - v = ae_v_dotproduct(&a->ptr.pp_double[ia][ja+ik], a->stride, &b->ptr.pp_double[ib][jb+jk], b->stride, ae_v_len(ia,ia+k-1)); - } - if( ae_fp_eq(beta,(double)(0)) ) - { - c->ptr.pp_double[ic+ik][jc+jk] = alpha*v; - } - else - { - c->ptr.pp_double[ic+ik][jc+jk] = beta*c->ptr.pp_double[ic+ik][jc+jk]+alpha*v; - } - } - } - } - j = j+4; - } - i = i+4; - } -} - - -/************************************************************************* -RMatrixGEMM kernel, basecase code for RMatrixGEMM, specialized for sitation -with OpTypeA=1 and OpTypeB=1. - -Additional info: -* this function requires that Alpha<>0 (assertion is thrown otherwise) - -INPUT PARAMETERS - M - matrix size, M>0 - N - matrix size, N>0 - K - matrix size, K>0 - Alpha - coefficient - A - matrix - IA - submatrix offset - JA - submatrix offset - B - matrix - IB - submatrix offset - JB - submatrix offset - Beta - coefficient - C - PREALLOCATED output matrix - IC - submatrix offset - JC - submatrix offset - - -- ALGLIB routine -- - 27.03.2013 - Bochkanov Sergey -*************************************************************************/ -void rmatrixgemmk44v11(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - double v00; - double v01; - double v02; - double v03; - double v10; - double v11; - double v12; - double v13; - double v20; - double v21; - double v22; - double v23; - double v30; - double v31; - double v32; - double v33; - double a0; - double a1; - double a2; - double a3; - double b0; - double b1; - double b2; - double b3; - ae_int_t idxa0; - ae_int_t idxa1; - ae_int_t idxa2; - ae_int_t idxa3; - ae_int_t idxb0; - ae_int_t idxb1; - ae_int_t idxb2; - ae_int_t idxb3; - ae_int_t i0; - ae_int_t i1; - ae_int_t ik; - ae_int_t j0; - ae_int_t j1; - ae_int_t jk; - ae_int_t t; - ae_int_t offsa; - ae_int_t offsb; - - - ae_assert(ae_fp_neq(alpha,(double)(0)), "RMatrixGEMMK44V00: internal error (Alpha=0)", _state); - - /* - * if matrix size is zero - */ - if( m==0||n==0 ) - { - return; - } - - /* - * A'*B' - */ - i = 0; - while(iptr.pp_double[offsa][idxa0]; - a1 = a->ptr.pp_double[offsa][idxa1]; - b0 = b->ptr.pp_double[idxb0][offsb]; - b1 = b->ptr.pp_double[idxb1][offsb]; - v00 = v00+a0*b0; - v01 = v01+a0*b1; - v10 = v10+a1*b0; - v11 = v11+a1*b1; - a2 = a->ptr.pp_double[offsa][idxa2]; - a3 = a->ptr.pp_double[offsa][idxa3]; - v20 = v20+a2*b0; - v21 = v21+a2*b1; - v30 = v30+a3*b0; - v31 = v31+a3*b1; - b2 = b->ptr.pp_double[idxb2][offsb]; - b3 = b->ptr.pp_double[idxb3][offsb]; - v22 = v22+a2*b2; - v23 = v23+a2*b3; - v32 = v32+a3*b2; - v33 = v33+a3*b3; - v02 = v02+a0*b2; - v03 = v03+a0*b3; - v12 = v12+a1*b2; - v13 = v13+a1*b3; - offsa = offsa+1; - offsb = offsb+1; - } - if( ae_fp_eq(beta,(double)(0)) ) - { - c->ptr.pp_double[ic+i+0][jc+j+0] = alpha*v00; - c->ptr.pp_double[ic+i+0][jc+j+1] = alpha*v01; - c->ptr.pp_double[ic+i+0][jc+j+2] = alpha*v02; - c->ptr.pp_double[ic+i+0][jc+j+3] = alpha*v03; - c->ptr.pp_double[ic+i+1][jc+j+0] = alpha*v10; - c->ptr.pp_double[ic+i+1][jc+j+1] = alpha*v11; - c->ptr.pp_double[ic+i+1][jc+j+2] = alpha*v12; - c->ptr.pp_double[ic+i+1][jc+j+3] = alpha*v13; - c->ptr.pp_double[ic+i+2][jc+j+0] = alpha*v20; - c->ptr.pp_double[ic+i+2][jc+j+1] = alpha*v21; - c->ptr.pp_double[ic+i+2][jc+j+2] = alpha*v22; - c->ptr.pp_double[ic+i+2][jc+j+3] = alpha*v23; - c->ptr.pp_double[ic+i+3][jc+j+0] = alpha*v30; - c->ptr.pp_double[ic+i+3][jc+j+1] = alpha*v31; - c->ptr.pp_double[ic+i+3][jc+j+2] = alpha*v32; - c->ptr.pp_double[ic+i+3][jc+j+3] = alpha*v33; - } - else - { - c->ptr.pp_double[ic+i+0][jc+j+0] = beta*c->ptr.pp_double[ic+i+0][jc+j+0]+alpha*v00; - c->ptr.pp_double[ic+i+0][jc+j+1] = beta*c->ptr.pp_double[ic+i+0][jc+j+1]+alpha*v01; - c->ptr.pp_double[ic+i+0][jc+j+2] = beta*c->ptr.pp_double[ic+i+0][jc+j+2]+alpha*v02; - c->ptr.pp_double[ic+i+0][jc+j+3] = beta*c->ptr.pp_double[ic+i+0][jc+j+3]+alpha*v03; - c->ptr.pp_double[ic+i+1][jc+j+0] = beta*c->ptr.pp_double[ic+i+1][jc+j+0]+alpha*v10; - c->ptr.pp_double[ic+i+1][jc+j+1] = beta*c->ptr.pp_double[ic+i+1][jc+j+1]+alpha*v11; - c->ptr.pp_double[ic+i+1][jc+j+2] = beta*c->ptr.pp_double[ic+i+1][jc+j+2]+alpha*v12; - c->ptr.pp_double[ic+i+1][jc+j+3] = beta*c->ptr.pp_double[ic+i+1][jc+j+3]+alpha*v13; - c->ptr.pp_double[ic+i+2][jc+j+0] = beta*c->ptr.pp_double[ic+i+2][jc+j+0]+alpha*v20; - c->ptr.pp_double[ic+i+2][jc+j+1] = beta*c->ptr.pp_double[ic+i+2][jc+j+1]+alpha*v21; - c->ptr.pp_double[ic+i+2][jc+j+2] = beta*c->ptr.pp_double[ic+i+2][jc+j+2]+alpha*v22; - c->ptr.pp_double[ic+i+2][jc+j+3] = beta*c->ptr.pp_double[ic+i+2][jc+j+3]+alpha*v23; - c->ptr.pp_double[ic+i+3][jc+j+0] = beta*c->ptr.pp_double[ic+i+3][jc+j+0]+alpha*v30; - c->ptr.pp_double[ic+i+3][jc+j+1] = beta*c->ptr.pp_double[ic+i+3][jc+j+1]+alpha*v31; - c->ptr.pp_double[ic+i+3][jc+j+2] = beta*c->ptr.pp_double[ic+i+3][jc+j+2]+alpha*v32; - c->ptr.pp_double[ic+i+3][jc+j+3] = beta*c->ptr.pp_double[ic+i+3][jc+j+3]+alpha*v33; - } - } - else - { - - /* - * Determine submatrix [I0..I1]x[J0..J1] to process - */ - i0 = i; - i1 = ae_minint(i+3, m-1, _state); - j0 = j; - j1 = ae_minint(j+3, n-1, _state); - - /* - * Process submatrix - */ - for(ik=i0; ik<=i1; ik++) - { - for(jk=j0; jk<=j1; jk++) - { - if( k==0||ae_fp_eq(alpha,(double)(0)) ) - { - v = (double)(0); - } - else - { - v = 0.0; - v = ae_v_dotproduct(&a->ptr.pp_double[ia][ja+ik], a->stride, &b->ptr.pp_double[ib+jk][jb], 1, ae_v_len(ia,ia+k-1)); - } - if( ae_fp_eq(beta,(double)(0)) ) - { - c->ptr.pp_double[ic+ik][jc+jk] = alpha*v; - } - else - { - c->ptr.pp_double[ic+ik][jc+jk] = beta*c->ptr.pp_double[ic+ik][jc+jk]+alpha*v; - } - } - } - } - j = j+4; - } - i = i+4; - } -} - - -#endif -#if defined(AE_COMPILE_ABLASMKL) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -MKL-based kernel - - -- ALGLIB routine -- - 12.10.2017 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixgermkl(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - double alpha, - /* Real */ ae_vector* u, - ae_int_t iu, - /* Real */ ae_vector* v, - ae_int_t iv, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixgermkl(m, n, a, ia, ja, alpha, u, iu, v, iv); -#endif -} - - -/************************************************************************* -MKL-based kernel - - -- ALGLIB routine -- - 12.10.2017 - Bochkanov Sergey -*************************************************************************/ -ae_bool cmatrixrank1mkl(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Complex */ ae_vector* u, - ae_int_t iu, - /* Complex */ ae_vector* v, - ae_int_t iv, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_cmatrixrank1mkl(m, n, a, ia, ja, u, iu, v, iv); -#endif -} - - -/************************************************************************* -MKL-based kernel - - -- ALGLIB routine -- - 12.10.2017 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixrank1mkl(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Real */ ae_vector* u, - ae_int_t iu, - /* Real */ ae_vector* v, - ae_int_t iv, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixrank1mkl(m, n, a, ia, ja, u, iu, v, iv); -#endif -} - - -/************************************************************************* -MKL-based kernel - - -- ALGLIB routine -- - 12.10.2017 - Bochkanov Sergey -*************************************************************************/ -ae_bool cmatrixmvmkl(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t opa, - /* Complex */ ae_vector* x, - ae_int_t ix, - /* Complex */ ae_vector* y, - ae_int_t iy, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_cmatrixmvmkl(m, n, a, ia, ja, opa, x, ix, y, iy); -#endif -} - - -/************************************************************************* -MKL-based kernel - - -- ALGLIB routine -- - 12.10.2017 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixmvmkl(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t opa, - /* Real */ ae_vector* x, - ae_int_t ix, - /* Real */ ae_vector* y, - ae_int_t iy, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixmvmkl(m, n, a, ia, ja, opa, x, ix, y, iy); -#endif -} - - -/************************************************************************* -MKL-based kernel - - -- ALGLIB routine -- - 12.10.2017 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixgemvmkl(ae_int_t m, - ae_int_t n, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t opa, - /* Real */ ae_vector* x, - ae_int_t ix, - double beta, - /* Real */ ae_vector* y, - ae_int_t iy, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixgemvmkl(m, n, alpha, a, ia, ja, opa, x, ix, beta, y, iy); -#endif -} - - -/************************************************************************* -MKL-based kernel - - -- ALGLIB routine -- - 12.10.2017 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixtrsvmkl(ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_vector* x, - ae_int_t ix, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixtrsvmkl(n, a, ia, ja, isupper, isunit, optype, x, ix); -#endif -} - - -/************************************************************************* -MKL-based kernel - - -- ALGLIB routine -- - 01.10.2013 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixsyrkmkl(ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixsyrkmkl(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper); -#endif -} - - -/************************************************************************* -MKL-based kernel - - -- ALGLIB routine -- - 01.10.2013 - Bochkanov Sergey -*************************************************************************/ -ae_bool cmatrixherkmkl(ae_int_t n, - ae_int_t k, - double alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_cmatrixherkmkl(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper); -#endif -} - - -/************************************************************************* -MKL-based kernel - - -- ALGLIB routine -- - 01.10.2013 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixgemmmkl(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixgemmmkl(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc); -#endif -} - - -/************************************************************************* -MKL-based kernel - - -- ALGLIB routine -- - 01.10.2017 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixsymvmkl(ae_int_t n, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_bool isupper, - /* Real */ ae_vector* x, - ae_int_t ix, - double beta, - /* Real */ ae_vector* y, - ae_int_t iy, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixsymvmkl(n, alpha, a, ia, ja, isupper, x, ix, beta, y, iy); -#endif -} - - -/************************************************************************* -MKL-based kernel - - -- ALGLIB routine -- - 16.10.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool cmatrixgemmmkl(ae_int_t m, - ae_int_t n, - ae_int_t k, - ae_complex alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Complex */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - ae_complex beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_cmatrixgemmmkl(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc); -#endif -} - - -/************************************************************************* -MKL-based kernel - - -- ALGLIB routine -- - 16.10.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool cmatrixlefttrsmmkl(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_cmatrixlefttrsmmkl(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2); -#endif -} - - -/************************************************************************* -MKL-based kernel - - -- ALGLIB routine -- - 16.10.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool cmatrixrighttrsmmkl(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_cmatrixrighttrsmmkl(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2); -#endif -} - - -/************************************************************************* -MKL-based kernel - - -- ALGLIB routine -- - 16.10.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixlefttrsmmkl(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixlefttrsmmkl(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2); -#endif -} - - -/************************************************************************* -MKL-based kernel - - -- ALGLIB routine -- - 16.10.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixrighttrsmmkl(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixrighttrsmmkl(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2); -#endif -} - - -/************************************************************************* -MKL-based kernel. - -NOTE: - -if function returned False, CholResult is NOT modified. Not ever referenced! -if function returned True, CholResult is set to status of Cholesky decomposition -(True on succeess). - - -- ALGLIB routine -- - 16.10.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool spdmatrixcholeskymkl(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - ae_bool* cholresult, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_spdmatrixcholeskymkl(a, offs, n, isupper, cholresult); -#endif -} - - -/************************************************************************* -MKL-based kernel. - - -- ALGLIB routine -- - 20.10.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixplumkl(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixplumkl(a, offs, m, n, pivots); -#endif -} - - -/************************************************************************* -MKL-based kernel. - -NOTE: this function needs preallocated output/temporary arrays. - D and E must be at least max(M,N)-wide. - - -- ALGLIB routine -- - 20.10.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixbdmkl(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* d, - /* Real */ ae_vector* e, - /* Real */ ae_vector* tauq, - /* Real */ ae_vector* taup, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixbdmkl(a, m, n, d, e, tauq, taup); -#endif -} - - -/************************************************************************* -MKL-based kernel. - -If ByQ is True, TauP is not used (can be empty array). -If ByQ is False, TauQ is not used (can be empty array). - - -- ALGLIB routine -- - 20.10.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixbdmultiplybymkl(/* Real */ ae_matrix* qp, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* tauq, - /* Real */ ae_vector* taup, - /* Real */ ae_matrix* z, - ae_int_t zrows, - ae_int_t zcolumns, - ae_bool byq, - ae_bool fromtheright, - ae_bool dotranspose, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixbdmultiplybymkl(qp, m, n, tauq, taup, z, zrows, zcolumns, byq, fromtheright, dotranspose); -#endif -} - - -/************************************************************************* -MKL-based kernel. - -NOTE: Tau must be preallocated array with at least N-1 elements. - - -- ALGLIB routine -- - 20.10.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixhessenbergmkl(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_vector* tau, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixhessenbergmkl(a, n, tau); -#endif -} - - -/************************************************************************* -MKL-based kernel. - -NOTE: Q must be preallocated N*N array - - -- ALGLIB routine -- - 20.10.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixhessenbergunpackqmkl(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_vector* tau, - /* Real */ ae_matrix* q, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixhessenbergunpackqmkl(a, n, tau, q); -#endif -} - - -/************************************************************************* -MKL-based kernel. - -NOTE: Tau, D, E must be preallocated arrays; - length(E)=length(Tau)=N-1 (or larger) - length(D)=N (or larger) - - -- ALGLIB routine -- - 20.10.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool smatrixtdmkl(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* tau, - /* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_smatrixtdmkl(a, n, isupper, tau, d, e); -#endif -} - - -/************************************************************************* -MKL-based kernel. - -NOTE: Q must be preallocated N*N array - - -- ALGLIB routine -- - 20.10.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool smatrixtdunpackqmkl(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* tau, - /* Real */ ae_matrix* q, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_smatrixtdunpackqmkl(a, n, isupper, tau, q); -#endif -} - - -/************************************************************************* -MKL-based kernel. - -NOTE: Tau, D, E must be preallocated arrays; - length(E)=length(Tau)=N-1 (or larger) - length(D)=N (or larger) - - -- ALGLIB routine -- - 20.10.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool hmatrixtdmkl(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* tau, - /* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_hmatrixtdmkl(a, n, isupper, tau, d, e); -#endif -} - - -/************************************************************************* -MKL-based kernel. - -NOTE: Q must be preallocated N*N array - - -- ALGLIB routine -- - 20.10.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool hmatrixtdunpackqmkl(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* tau, - /* Complex */ ae_matrix* q, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_hmatrixtdunpackqmkl(a, n, isupper, tau, q); -#endif -} - - -/************************************************************************* -MKL-based kernel. - -Returns True if MKL was present and handled request (MKL completion code -is returned as separate output parameter). - -D and E are pre-allocated arrays with length N (both of them!). On output, -D constraints singular values, and E is destroyed. - -SVDResult is modified if and only if MKL is present. - - -- ALGLIB routine -- - 20.10.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixbdsvdmkl(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_matrix* u, - ae_int_t nru, - /* Real */ ae_matrix* c, - ae_int_t ncc, - /* Real */ ae_matrix* vt, - ae_int_t ncvt, - ae_bool* svdresult, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixbdsvdmkl(d, e, n, isupper, u, nru, c, ncc, vt, ncvt, svdresult); -#endif -} - - -/************************************************************************* -MKL-based DHSEQR kernel. - -Returns True if MKL was present and handled request. - -WR and WI are pre-allocated arrays with length N. -Z is pre-allocated array[N,N]. - - -- ALGLIB routine -- - 20.10.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixinternalschurdecompositionmkl(/* Real */ ae_matrix* h, - ae_int_t n, - ae_int_t tneeded, - ae_int_t zneeded, - /* Real */ ae_vector* wr, - /* Real */ ae_vector* wi, - /* Real */ ae_matrix* z, - ae_int_t* info, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixinternalschurdecompositionmkl(h, n, tneeded, zneeded, wr, wi, z, info); -#endif -} - - -/************************************************************************* -MKL-based DTREVC kernel. - -Returns True if MKL was present and handled request. - -NOTE: this function does NOT support HOWMNY=3!!!! - -VL and VR are pre-allocated arrays with length N*N, if required. If particalar -variables is not required, it can be dummy (empty) array. - - -- ALGLIB routine -- - 20.10.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixinternaltrevcmkl(/* Real */ ae_matrix* t, - ae_int_t n, - ae_int_t side, - ae_int_t howmny, - /* Real */ ae_matrix* vl, - /* Real */ ae_matrix* vr, - ae_int_t* m, - ae_int_t* info, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_rmatrixinternaltrevcmkl(t, n, side, howmny, vl, vr, m, info); -#endif -} - - -/************************************************************************* -MKL-based kernel. - -Returns True if MKL was present and handled request (MKL completion code -is returned as separate output parameter). - -D and E are pre-allocated arrays with length N (both of them!). On output, -D constraints eigenvalues, and E is destroyed. - -Z is preallocated array[N,N] for ZNeeded<>0; ignored for ZNeeded=0. - -EVDResult is modified if and only if MKL is present. - - -- ALGLIB routine -- - 20.10.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool smatrixtdevdmkl(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_int_t zneeded, - /* Real */ ae_matrix* z, - ae_bool* evdresult, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_smatrixtdevdmkl(d, e, n, zneeded, z, evdresult); -#endif -} - - -/************************************************************************* -MKL-based kernel. - -Returns True if MKL was present and handled request (MKL completion code -is returned as separate output parameter). - -D and E are pre-allocated arrays with length N (both of them!). On output, -D constraints eigenvalues, and E is destroyed. - -Z is preallocated array[N,N] for ZNeeded<>0; ignored for ZNeeded=0. - -EVDResult is modified if and only if MKL is present. - - -- ALGLIB routine -- - 20.10.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool sparsegemvcrsmkl(ae_int_t opa, - ae_int_t arows, - ae_int_t acols, - double alpha, - /* Real */ ae_vector* vals, - /* Integer */ ae_vector* cidx, - /* Integer */ ae_vector* ridx, - /* Real */ ae_vector* x, - ae_int_t ix, - double beta, - /* Real */ ae_vector* y, - ae_int_t iy, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_MKL - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_sparsegemvcrsmkl(opa, arows, acols, alpha, vals, cidx, ridx, x, ix, beta, y, iy); -#endif -} - - -#endif -#if defined(AE_COMPILE_CREFLECTIONS) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Generation of an elementary complex reflection transformation - -The subroutine generates elementary complex reflection H of order N, so -that, for a given X, the following equality holds true: - - ( X(1) ) ( Beta ) -H' * ( .. ) = ( 0 ), H'*H = I, Beta is a real number - ( X(n) ) ( 0 ) - -where - - ( V(1) ) -H = 1 - Tau * ( .. ) * ( conj(V(1)), ..., conj(V(n)) ) - ( V(n) ) - -where the first component of vector V equals 1. - -Input parameters: - X - vector. Array with elements [1..N]. - N - reflection order. - -Output parameters: - X - components from 2 to N are replaced by vector V. - The first component is replaced with parameter Beta. - Tau - scalar value Tau. - -This subroutine is the modification of CLARFG subroutines from the LAPACK -library. It has similar functionality except for the fact that it doesn't -handle errors when intermediate results cause an overflow. - - -- LAPACK auxiliary routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994 -*************************************************************************/ -void complexgeneratereflection(/* Complex */ ae_vector* x, - ae_int_t n, - ae_complex* tau, - ae_state *_state) -{ - ae_int_t j; - ae_complex alpha; - double alphi; - double alphr; - double beta; - double xnorm; - double mx; - ae_complex t; - double s; - ae_complex v; - - tau->x = 0; - tau->y = 0; - - if( n<=0 ) - { - *tau = ae_complex_from_i(0); - return; - } - - /* - * Scale if needed (to avoid overflow/underflow during intermediate - * calculations). - */ - mx = (double)(0); - for(j=1; j<=n; j++) - { - mx = ae_maxreal(ae_c_abs(x->ptr.p_complex[j], _state), mx, _state); - } - s = (double)(1); - if( ae_fp_neq(mx,(double)(0)) ) - { - if( ae_fp_less(mx,(double)(1)) ) - { - s = ae_sqrt(ae_minrealnumber, _state); - v = ae_complex_from_d(1/s); - ae_v_cmulc(&x->ptr.p_complex[1], 1, ae_v_len(1,n), v); - } - else - { - s = ae_sqrt(ae_maxrealnumber, _state); - v = ae_complex_from_d(1/s); - ae_v_cmulc(&x->ptr.p_complex[1], 1, ae_v_len(1,n), v); - } - } - - /* - * calculate - */ - alpha = x->ptr.p_complex[1]; - mx = (double)(0); - for(j=2; j<=n; j++) - { - mx = ae_maxreal(ae_c_abs(x->ptr.p_complex[j], _state), mx, _state); - } - xnorm = (double)(0); - if( ae_fp_neq(mx,(double)(0)) ) - { - for(j=2; j<=n; j++) - { - t = ae_c_div_d(x->ptr.p_complex[j],mx); - xnorm = xnorm+ae_c_mul(t,ae_c_conj(t, _state)).x; - } - xnorm = ae_sqrt(xnorm, _state)*mx; - } - alphr = alpha.x; - alphi = alpha.y; - if( ae_fp_eq(xnorm,(double)(0))&&ae_fp_eq(alphi,(double)(0)) ) - { - *tau = ae_complex_from_i(0); - x->ptr.p_complex[1] = ae_c_mul_d(x->ptr.p_complex[1],s); - return; - } - mx = ae_maxreal(ae_fabs(alphr, _state), ae_fabs(alphi, _state), _state); - mx = ae_maxreal(mx, ae_fabs(xnorm, _state), _state); - beta = -mx*ae_sqrt(ae_sqr(alphr/mx, _state)+ae_sqr(alphi/mx, _state)+ae_sqr(xnorm/mx, _state), _state); - if( ae_fp_less(alphr,(double)(0)) ) - { - beta = -beta; - } - tau->x = (beta-alphr)/beta; - tau->y = -alphi/beta; - alpha = ae_c_d_div(1,ae_c_sub_d(alpha,beta)); - if( n>1 ) - { - ae_v_cmulc(&x->ptr.p_complex[2], 1, ae_v_len(2,n), alpha); - } - alpha = ae_complex_from_d(beta); - x->ptr.p_complex[1] = alpha; - - /* - * Scale back - */ - x->ptr.p_complex[1] = ae_c_mul_d(x->ptr.p_complex[1],s); -} - - -/************************************************************************* -Application of an elementary reflection to a rectangular matrix of size MxN - -The algorithm pre-multiplies the matrix by an elementary reflection -transformation which is given by column V and scalar Tau (see the -description of the GenerateReflection). Not the whole matrix but only a -part of it is transformed (rows from M1 to M2, columns from N1 to N2). Only -the elements of this submatrix are changed. - -Note: the matrix is multiplied by H, not by H'. If it is required to -multiply the matrix by H', it is necessary to pass Conj(Tau) instead of Tau. - -Input parameters: - C - matrix to be transformed. - Tau - scalar defining transformation. - V - column defining transformation. - Array whose index ranges within [1..M2-M1+1] - M1, M2 - range of rows to be transformed. - N1, N2 - range of columns to be transformed. - WORK - working array whose index goes from N1 to N2. - -Output parameters: - C - the result of multiplying the input matrix C by the - transformation matrix which is given by Tau and V. - If N1>N2 or M1>M2, C is not modified. - - -- LAPACK auxiliary routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994 -*************************************************************************/ -void complexapplyreflectionfromtheleft(/* Complex */ ae_matrix* c, - ae_complex tau, - /* Complex */ ae_vector* v, - ae_int_t m1, - ae_int_t m2, - ae_int_t n1, - ae_int_t n2, - /* Complex */ ae_vector* work, - ae_state *_state) -{ - ae_complex t; - ae_int_t i; - - - if( (ae_c_eq_d(tau,(double)(0))||n1>n2)||m1>m2 ) - { - return; - } - - /* - * w := C^T * conj(v) - */ - for(i=n1; i<=n2; i++) - { - work->ptr.p_complex[i] = ae_complex_from_i(0); - } - for(i=m1; i<=m2; i++) - { - t = ae_c_conj(v->ptr.p_complex[i+1-m1], _state); - ae_v_caddc(&work->ptr.p_complex[n1], 1, &c->ptr.pp_complex[i][n1], 1, "N", ae_v_len(n1,n2), t); - } - - /* - * C := C - tau * v * w^T - */ - for(i=m1; i<=m2; i++) - { - t = ae_c_mul(v->ptr.p_complex[i-m1+1],tau); - ae_v_csubc(&c->ptr.pp_complex[i][n1], 1, &work->ptr.p_complex[n1], 1, "N", ae_v_len(n1,n2), t); - } -} - - -/************************************************************************* -Application of an elementary reflection to a rectangular matrix of size MxN - -The algorithm post-multiplies the matrix by an elementary reflection -transformation which is given by column V and scalar Tau (see the -description of the GenerateReflection). Not the whole matrix but only a -part of it is transformed (rows from M1 to M2, columns from N1 to N2). -Only the elements of this submatrix are changed. - -Input parameters: - C - matrix to be transformed. - Tau - scalar defining transformation. - V - column defining transformation. - Array whose index ranges within [1..N2-N1+1] - M1, M2 - range of rows to be transformed. - N1, N2 - range of columns to be transformed. - WORK - working array whose index goes from M1 to M2. - -Output parameters: - C - the result of multiplying the input matrix C by the - transformation matrix which is given by Tau and V. - If N1>N2 or M1>M2, C is not modified. - - -- LAPACK auxiliary routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994 -*************************************************************************/ -void complexapplyreflectionfromtheright(/* Complex */ ae_matrix* c, - ae_complex tau, - /* Complex */ ae_vector* v, - ae_int_t m1, - ae_int_t m2, - ae_int_t n1, - ae_int_t n2, - /* Complex */ ae_vector* work, - ae_state *_state) -{ - ae_complex t; - ae_int_t i; - ae_int_t vm; - - - if( (ae_c_eq_d(tau,(double)(0))||n1>n2)||m1>m2 ) - { - return; - } - - /* - * w := C * v - */ - vm = n2-n1+1; - for(i=m1; i<=m2; i++) - { - t = ae_v_cdotproduct(&c->ptr.pp_complex[i][n1], 1, "N", &v->ptr.p_complex[1], 1, "N", ae_v_len(n1,n2)); - work->ptr.p_complex[i] = t; - } - - /* - * C := C - w * conj(v^T) - */ - ae_v_cmove(&v->ptr.p_complex[1], 1, &v->ptr.p_complex[1], 1, "Conj", ae_v_len(1,vm)); - for(i=m1; i<=m2; i++) - { - t = ae_c_mul(work->ptr.p_complex[i],tau); - ae_v_csubc(&c->ptr.pp_complex[i][n1], 1, &v->ptr.p_complex[1], 1, "N", ae_v_len(n1,n2), t); - } - ae_v_cmove(&v->ptr.p_complex[1], 1, &v->ptr.p_complex[1], 1, "Conj", ae_v_len(1,vm)); -} - - -#endif -#if defined(AE_COMPILE_ROTATIONS) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Application of a sequence of elementary rotations to a matrix - -The algorithm pre-multiplies the matrix by a sequence of rotation -transformations which is given by arrays C and S. Depending on the value -of the IsForward parameter either 1 and 2, 3 and 4 and so on (if IsForward=true) -rows are rotated, or the rows N and N-1, N-2 and N-3 and so on, are rotated. - -Not the whole matrix but only a part of it is transformed (rows from M1 to -M2, columns from N1 to N2). Only the elements of this submatrix are changed. - -Input parameters: - IsForward - the sequence of the rotation application. - M1,M2 - the range of rows to be transformed. - N1, N2 - the range of columns to be transformed. - C,S - transformation coefficients. - Array whose index ranges within [1..M2-M1]. - A - processed matrix. - WORK - working array whose index ranges within [N1..N2]. - -Output parameters: - A - transformed matrix. - -Utility subroutine. -*************************************************************************/ -void applyrotationsfromtheleft(ae_bool isforward, - ae_int_t m1, - ae_int_t m2, - ae_int_t n1, - ae_int_t n2, - /* Real */ ae_vector* c, - /* Real */ ae_vector* s, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* work, - ae_state *_state) -{ - ae_int_t j; - ae_int_t jp1; - double ctemp; - double stemp; - double temp; - - - if( m1>m2||n1>n2 ) - { - return; - } - - /* - * Form P * A - */ - if( isforward ) - { - if( n1!=n2 ) - { - - /* - * Common case: N1<>N2 - */ - for(j=m1; j<=m2-1; j++) - { - ctemp = c->ptr.p_double[j-m1+1]; - stemp = s->ptr.p_double[j-m1+1]; - if( ae_fp_neq(ctemp,(double)(1))||ae_fp_neq(stemp,(double)(0)) ) - { - jp1 = j+1; - ae_v_moved(&work->ptr.p_double[n1], 1, &a->ptr.pp_double[jp1][n1], 1, ae_v_len(n1,n2), ctemp); - ae_v_subd(&work->ptr.p_double[n1], 1, &a->ptr.pp_double[j][n1], 1, ae_v_len(n1,n2), stemp); - ae_v_muld(&a->ptr.pp_double[j][n1], 1, ae_v_len(n1,n2), ctemp); - ae_v_addd(&a->ptr.pp_double[j][n1], 1, &a->ptr.pp_double[jp1][n1], 1, ae_v_len(n1,n2), stemp); - ae_v_move(&a->ptr.pp_double[jp1][n1], 1, &work->ptr.p_double[n1], 1, ae_v_len(n1,n2)); - } - } - } - else - { - - /* - * Special case: N1=N2 - */ - for(j=m1; j<=m2-1; j++) - { - ctemp = c->ptr.p_double[j-m1+1]; - stemp = s->ptr.p_double[j-m1+1]; - if( ae_fp_neq(ctemp,(double)(1))||ae_fp_neq(stemp,(double)(0)) ) - { - temp = a->ptr.pp_double[j+1][n1]; - a->ptr.pp_double[j+1][n1] = ctemp*temp-stemp*a->ptr.pp_double[j][n1]; - a->ptr.pp_double[j][n1] = stemp*temp+ctemp*a->ptr.pp_double[j][n1]; - } - } - } - } - else - { - if( n1!=n2 ) - { - - /* - * Common case: N1<>N2 - */ - for(j=m2-1; j>=m1; j--) - { - ctemp = c->ptr.p_double[j-m1+1]; - stemp = s->ptr.p_double[j-m1+1]; - if( ae_fp_neq(ctemp,(double)(1))||ae_fp_neq(stemp,(double)(0)) ) - { - jp1 = j+1; - ae_v_moved(&work->ptr.p_double[n1], 1, &a->ptr.pp_double[jp1][n1], 1, ae_v_len(n1,n2), ctemp); - ae_v_subd(&work->ptr.p_double[n1], 1, &a->ptr.pp_double[j][n1], 1, ae_v_len(n1,n2), stemp); - ae_v_muld(&a->ptr.pp_double[j][n1], 1, ae_v_len(n1,n2), ctemp); - ae_v_addd(&a->ptr.pp_double[j][n1], 1, &a->ptr.pp_double[jp1][n1], 1, ae_v_len(n1,n2), stemp); - ae_v_move(&a->ptr.pp_double[jp1][n1], 1, &work->ptr.p_double[n1], 1, ae_v_len(n1,n2)); - } - } - } - else - { - - /* - * Special case: N1=N2 - */ - for(j=m2-1; j>=m1; j--) - { - ctemp = c->ptr.p_double[j-m1+1]; - stemp = s->ptr.p_double[j-m1+1]; - if( ae_fp_neq(ctemp,(double)(1))||ae_fp_neq(stemp,(double)(0)) ) - { - temp = a->ptr.pp_double[j+1][n1]; - a->ptr.pp_double[j+1][n1] = ctemp*temp-stemp*a->ptr.pp_double[j][n1]; - a->ptr.pp_double[j][n1] = stemp*temp+ctemp*a->ptr.pp_double[j][n1]; - } - } - } - } -} - - -/************************************************************************* -Application of a sequence of elementary rotations to a matrix - -The algorithm post-multiplies the matrix by a sequence of rotation -transformations which is given by arrays C and S. Depending on the value -of the IsForward parameter either 1 and 2, 3 and 4 and so on (if IsForward=true) -rows are rotated, or the rows N and N-1, N-2 and N-3 and so on are rotated. - -Not the whole matrix but only a part of it is transformed (rows from M1 -to M2, columns from N1 to N2). Only the elements of this submatrix are changed. - -Input parameters: - IsForward - the sequence of the rotation application. - M1,M2 - the range of rows to be transformed. - N1, N2 - the range of columns to be transformed. - C,S - transformation coefficients. - Array whose index ranges within [1..N2-N1]. - A - processed matrix. - WORK - working array whose index ranges within [M1..M2]. - -Output parameters: - A - transformed matrix. - -Utility subroutine. -*************************************************************************/ -void applyrotationsfromtheright(ae_bool isforward, - ae_int_t m1, - ae_int_t m2, - ae_int_t n1, - ae_int_t n2, - /* Real */ ae_vector* c, - /* Real */ ae_vector* s, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* work, - ae_state *_state) -{ - ae_int_t j; - ae_int_t jp1; - double ctemp; - double stemp; - double temp; - - - - /* - * Form A * P' - */ - if( isforward ) - { - if( m1!=m2 ) - { - - /* - * Common case: M1<>M2 - */ - for(j=n1; j<=n2-1; j++) - { - ctemp = c->ptr.p_double[j-n1+1]; - stemp = s->ptr.p_double[j-n1+1]; - if( ae_fp_neq(ctemp,(double)(1))||ae_fp_neq(stemp,(double)(0)) ) - { - jp1 = j+1; - ae_v_moved(&work->ptr.p_double[m1], 1, &a->ptr.pp_double[m1][jp1], a->stride, ae_v_len(m1,m2), ctemp); - ae_v_subd(&work->ptr.p_double[m1], 1, &a->ptr.pp_double[m1][j], a->stride, ae_v_len(m1,m2), stemp); - ae_v_muld(&a->ptr.pp_double[m1][j], a->stride, ae_v_len(m1,m2), ctemp); - ae_v_addd(&a->ptr.pp_double[m1][j], a->stride, &a->ptr.pp_double[m1][jp1], a->stride, ae_v_len(m1,m2), stemp); - ae_v_move(&a->ptr.pp_double[m1][jp1], a->stride, &work->ptr.p_double[m1], 1, ae_v_len(m1,m2)); - } - } - } - else - { - - /* - * Special case: M1=M2 - */ - for(j=n1; j<=n2-1; j++) - { - ctemp = c->ptr.p_double[j-n1+1]; - stemp = s->ptr.p_double[j-n1+1]; - if( ae_fp_neq(ctemp,(double)(1))||ae_fp_neq(stemp,(double)(0)) ) - { - temp = a->ptr.pp_double[m1][j+1]; - a->ptr.pp_double[m1][j+1] = ctemp*temp-stemp*a->ptr.pp_double[m1][j]; - a->ptr.pp_double[m1][j] = stemp*temp+ctemp*a->ptr.pp_double[m1][j]; - } - } - } - } - else - { - if( m1!=m2 ) - { - - /* - * Common case: M1<>M2 - */ - for(j=n2-1; j>=n1; j--) - { - ctemp = c->ptr.p_double[j-n1+1]; - stemp = s->ptr.p_double[j-n1+1]; - if( ae_fp_neq(ctemp,(double)(1))||ae_fp_neq(stemp,(double)(0)) ) - { - jp1 = j+1; - ae_v_moved(&work->ptr.p_double[m1], 1, &a->ptr.pp_double[m1][jp1], a->stride, ae_v_len(m1,m2), ctemp); - ae_v_subd(&work->ptr.p_double[m1], 1, &a->ptr.pp_double[m1][j], a->stride, ae_v_len(m1,m2), stemp); - ae_v_muld(&a->ptr.pp_double[m1][j], a->stride, ae_v_len(m1,m2), ctemp); - ae_v_addd(&a->ptr.pp_double[m1][j], a->stride, &a->ptr.pp_double[m1][jp1], a->stride, ae_v_len(m1,m2), stemp); - ae_v_move(&a->ptr.pp_double[m1][jp1], a->stride, &work->ptr.p_double[m1], 1, ae_v_len(m1,m2)); - } - } - } - else - { - - /* - * Special case: M1=M2 - */ - for(j=n2-1; j>=n1; j--) - { - ctemp = c->ptr.p_double[j-n1+1]; - stemp = s->ptr.p_double[j-n1+1]; - if( ae_fp_neq(ctemp,(double)(1))||ae_fp_neq(stemp,(double)(0)) ) - { - temp = a->ptr.pp_double[m1][j+1]; - a->ptr.pp_double[m1][j+1] = ctemp*temp-stemp*a->ptr.pp_double[m1][j]; - a->ptr.pp_double[m1][j] = stemp*temp+ctemp*a->ptr.pp_double[m1][j]; - } - } - } - } -} - - -/************************************************************************* -The subroutine generates the elementary rotation, so that: - -[ CS SN ] . [ F ] = [ R ] -[ -SN CS ] [ G ] [ 0 ] - -CS**2 + SN**2 = 1 -*************************************************************************/ -void generaterotation(double f, - double g, - double* cs, - double* sn, - double* r, - ae_state *_state) -{ - double f1; - double g1; - - *cs = 0; - *sn = 0; - *r = 0; - - if( ae_fp_eq(g,(double)(0)) ) - { - *cs = (double)(1); - *sn = (double)(0); - *r = f; - } - else - { - if( ae_fp_eq(f,(double)(0)) ) - { - *cs = (double)(0); - *sn = (double)(1); - *r = g; - } - else - { - f1 = f; - g1 = g; - if( ae_fp_greater(ae_fabs(f1, _state),ae_fabs(g1, _state)) ) - { - *r = ae_fabs(f1, _state)*ae_sqrt(1+ae_sqr(g1/f1, _state), _state); - } - else - { - *r = ae_fabs(g1, _state)*ae_sqrt(1+ae_sqr(f1/g1, _state), _state); - } - *cs = f1/(*r); - *sn = g1/(*r); - if( ae_fp_greater(ae_fabs(f, _state),ae_fabs(g, _state))&&ae_fp_less(*cs,(double)(0)) ) - { - *cs = -*cs; - *sn = -*sn; - *r = -*r; - } - } - } -} - - -#endif -#if defined(AE_COMPILE_TRLINSOLVE) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Utility subroutine performing the "safe" solution of system of linear -equations with triangular coefficient matrices. - -The subroutine uses scaling and solves the scaled system A*x=s*b (where s -is a scalar value) instead of A*x=b, choosing s so that x can be -represented by a floating-point number. The closer the system gets to a -singular, the less s is. If the system is singular, s=0 and x contains the -non-trivial solution of equation A*x=0. - -The feature of an algorithm is that it could not cause an overflow or a -division by zero regardless of the matrix used as the input. - -The algorithm can solve systems of equations with upper/lower triangular -matrices, with/without unit diagonal, and systems of type A*x=b or A'*x=b -(where A' is a transposed matrix A). - -Input parameters: - A - system matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - X - right-hand member of a system. - Array whose index ranges within [0..N-1]. - IsUpper - matrix type. If it is True, the system matrix is the upper - triangular and is located in the corresponding part of - matrix A. - Trans - problem type. If it is True, the problem to be solved is - A'*x=b, otherwise it is A*x=b. - Isunit - matrix type. If it is True, the system matrix has a unit - diagonal (the elements on the main diagonal are not used - in the calculation process), otherwise the matrix is considered - to be a general triangular matrix. - -Output parameters: - X - solution. Array whose index ranges within [0..N-1]. - S - scaling factor. - - -- LAPACK auxiliary routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - June 30, 1992 -*************************************************************************/ -void rmatrixtrsafesolve(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_vector* x, - double* s, - ae_bool isupper, - ae_bool istrans, - ae_bool isunit, - ae_state *_state) -{ - ae_frame _frame_block; - ae_bool normin; - ae_vector cnorm; - ae_matrix a1; - ae_vector x1; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&cnorm, 0, sizeof(cnorm)); - memset(&a1, 0, sizeof(a1)); - memset(&x1, 0, sizeof(x1)); - *s = 0; - ae_vector_init(&cnorm, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - - - /* - * From 0-based to 1-based - */ - normin = ae_false; - ae_matrix_set_length(&a1, n+1, n+1, _state); - ae_vector_set_length(&x1, n+1, _state); - for(i=1; i<=n; i++) - { - ae_v_move(&a1.ptr.pp_double[i][1], 1, &a->ptr.pp_double[i-1][0], 1, ae_v_len(1,n)); - } - ae_v_move(&x1.ptr.p_double[1], 1, &x->ptr.p_double[0], 1, ae_v_len(1,n)); - - /* - * Solve 1-based - */ - safesolvetriangular(&a1, n, &x1, s, isupper, istrans, isunit, normin, &cnorm, _state); - - /* - * From 1-based to 0-based - */ - ae_v_move(&x->ptr.p_double[0], 1, &x1.ptr.p_double[1], 1, ae_v_len(0,n-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -Obsolete 1-based subroutine. -See RMatrixTRSafeSolve for 0-based replacement. -*************************************************************************/ -void safesolvetriangular(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_vector* x, - double* s, - ae_bool isupper, - ae_bool istrans, - ae_bool isunit, - ae_bool normin, - /* Real */ ae_vector* cnorm, - ae_state *_state) -{ - ae_int_t i; - ae_int_t imax; - ae_int_t j; - ae_int_t jfirst; - ae_int_t jinc; - ae_int_t jlast; - ae_int_t jm1; - ae_int_t jp1; - ae_int_t ip1; - ae_int_t im1; - ae_int_t k; - ae_int_t flg; - double v; - double vd; - double bignum; - double grow; - double rec; - double smlnum; - double sumj; - double tjj; - double tjjs; - double tmax; - double tscal; - double uscal; - double xbnd; - double xj; - double xmax; - ae_bool notran; - ae_bool upper; - ae_bool nounit; - - *s = 0; - - upper = isupper; - notran = !istrans; - nounit = !isunit; - - /* - * these initializers are not really necessary, - * but without them compiler complains about uninitialized locals - */ - tjjs = (double)(0); - - /* - * Quick return if possible - */ - if( n==0 ) - { - return; - } - - /* - * Determine machine dependent parameters to control overflow. - */ - smlnum = ae_minrealnumber/(ae_machineepsilon*2); - bignum = 1/smlnum; - *s = (double)(1); - if( !normin ) - { - ae_vector_set_length(cnorm, n+1, _state); - - /* - * Compute the 1-norm of each column, not including the diagonal. - */ - if( upper ) - { - - /* - * A is upper triangular. - */ - for(j=1; j<=n; j++) - { - v = (double)(0); - for(k=1; k<=j-1; k++) - { - v = v+ae_fabs(a->ptr.pp_double[k][j], _state); - } - cnorm->ptr.p_double[j] = v; - } - } - else - { - - /* - * A is lower triangular. - */ - for(j=1; j<=n-1; j++) - { - v = (double)(0); - for(k=j+1; k<=n; k++) - { - v = v+ae_fabs(a->ptr.pp_double[k][j], _state); - } - cnorm->ptr.p_double[j] = v; - } - cnorm->ptr.p_double[n] = (double)(0); - } - } - - /* - * Scale the column norms by TSCAL if the maximum element in CNORM is - * greater than BIGNUM. - */ - imax = 1; - for(k=2; k<=n; k++) - { - if( ae_fp_greater(cnorm->ptr.p_double[k],cnorm->ptr.p_double[imax]) ) - { - imax = k; - } - } - tmax = cnorm->ptr.p_double[imax]; - if( ae_fp_less_eq(tmax,bignum) ) - { - tscal = (double)(1); - } - else - { - tscal = 1/(smlnum*tmax); - ae_v_muld(&cnorm->ptr.p_double[1], 1, ae_v_len(1,n), tscal); - } - - /* - * Compute a bound on the computed solution vector to see if the - * Level 2 BLAS routine DTRSV can be used. - */ - j = 1; - for(k=2; k<=n; k++) - { - if( ae_fp_greater(ae_fabs(x->ptr.p_double[k], _state),ae_fabs(x->ptr.p_double[j], _state)) ) - { - j = k; - } - } - xmax = ae_fabs(x->ptr.p_double[j], _state); - xbnd = xmax; - if( notran ) - { - - /* - * Compute the growth in A * x = b. - */ - if( upper ) - { - jfirst = n; - jlast = 1; - jinc = -1; - } - else - { - jfirst = 1; - jlast = n; - jinc = 1; - } - if( ae_fp_neq(tscal,(double)(1)) ) - { - grow = (double)(0); - } - else - { - if( nounit ) - { - - /* - * A is non-unit triangular. - * - * Compute GROW = 1/G(j) and XBND = 1/M(j). - * Initially, G(0) = max{x(i), i=1,...,n}. - */ - grow = 1/ae_maxreal(xbnd, smlnum, _state); - xbnd = grow; - j = jfirst; - while((jinc>0&&j<=jlast)||(jinc<0&&j>=jlast)) - { - - /* - * Exit the loop if the growth factor is too small. - */ - if( ae_fp_less_eq(grow,smlnum) ) - { - break; - } - - /* - * M(j) = G(j-1) / abs(A(j,j)) - */ - tjj = ae_fabs(a->ptr.pp_double[j][j], _state); - xbnd = ae_minreal(xbnd, ae_minreal((double)(1), tjj, _state)*grow, _state); - if( ae_fp_greater_eq(tjj+cnorm->ptr.p_double[j],smlnum) ) - { - - /* - * G(j) = G(j-1)*( 1 + CNORM(j) / abs(A(j,j)) ) - */ - grow = grow*(tjj/(tjj+cnorm->ptr.p_double[j])); - } - else - { - - /* - * G(j) could overflow, set GROW to 0. - */ - grow = (double)(0); - } - if( j==jlast ) - { - grow = xbnd; - } - j = j+jinc; - } - } - else - { - - /* - * A is unit triangular. - * - * Compute GROW = 1/G(j), where G(0) = max{x(i), i=1,...,n}. - */ - grow = ae_minreal((double)(1), 1/ae_maxreal(xbnd, smlnum, _state), _state); - j = jfirst; - while((jinc>0&&j<=jlast)||(jinc<0&&j>=jlast)) - { - - /* - * Exit the loop if the growth factor is too small. - */ - if( ae_fp_less_eq(grow,smlnum) ) - { - break; - } - - /* - * G(j) = G(j-1)*( 1 + CNORM(j) ) - */ - grow = grow*(1/(1+cnorm->ptr.p_double[j])); - j = j+jinc; - } - } - } - } - else - { - - /* - * Compute the growth in A' * x = b. - */ - if( upper ) - { - jfirst = 1; - jlast = n; - jinc = 1; - } - else - { - jfirst = n; - jlast = 1; - jinc = -1; - } - if( ae_fp_neq(tscal,(double)(1)) ) - { - grow = (double)(0); - } - else - { - if( nounit ) - { - - /* - * A is non-unit triangular. - * - * Compute GROW = 1/G(j) and XBND = 1/M(j). - * Initially, M(0) = max{x(i), i=1,...,n}. - */ - grow = 1/ae_maxreal(xbnd, smlnum, _state); - xbnd = grow; - j = jfirst; - while((jinc>0&&j<=jlast)||(jinc<0&&j>=jlast)) - { - - /* - * Exit the loop if the growth factor is too small. - */ - if( ae_fp_less_eq(grow,smlnum) ) - { - break; - } - - /* - * G(j) = max( G(j-1), M(j-1)*( 1 + CNORM(j) ) ) - */ - xj = 1+cnorm->ptr.p_double[j]; - grow = ae_minreal(grow, xbnd/xj, _state); - - /* - * M(j) = M(j-1)*( 1 + CNORM(j) ) / abs(A(j,j)) - */ - tjj = ae_fabs(a->ptr.pp_double[j][j], _state); - if( ae_fp_greater(xj,tjj) ) - { - xbnd = xbnd*(tjj/xj); - } - if( j==jlast ) - { - grow = ae_minreal(grow, xbnd, _state); - } - j = j+jinc; - } - } - else - { - - /* - * A is unit triangular. - * - * Compute GROW = 1/G(j), where G(0) = max{x(i), i=1,...,n}. - */ - grow = ae_minreal((double)(1), 1/ae_maxreal(xbnd, smlnum, _state), _state); - j = jfirst; - while((jinc>0&&j<=jlast)||(jinc<0&&j>=jlast)) - { - - /* - * Exit the loop if the growth factor is too small. - */ - if( ae_fp_less_eq(grow,smlnum) ) - { - break; - } - - /* - * G(j) = ( 1 + CNORM(j) )*G(j-1) - */ - xj = 1+cnorm->ptr.p_double[j]; - grow = grow/xj; - j = j+jinc; - } - } - } - } - if( ae_fp_greater(grow*tscal,smlnum) ) - { - - /* - * Use the Level 2 BLAS solve if the reciprocal of the bound on - * elements of X is not too small. - */ - if( (upper&¬ran)||(!upper&&!notran) ) - { - if( nounit ) - { - vd = a->ptr.pp_double[n][n]; - } - else - { - vd = (double)(1); - } - x->ptr.p_double[n] = x->ptr.p_double[n]/vd; - for(i=n-1; i>=1; i--) - { - ip1 = i+1; - if( upper ) - { - v = ae_v_dotproduct(&a->ptr.pp_double[i][ip1], 1, &x->ptr.p_double[ip1], 1, ae_v_len(ip1,n)); - } - else - { - v = ae_v_dotproduct(&a->ptr.pp_double[ip1][i], a->stride, &x->ptr.p_double[ip1], 1, ae_v_len(ip1,n)); - } - if( nounit ) - { - vd = a->ptr.pp_double[i][i]; - } - else - { - vd = (double)(1); - } - x->ptr.p_double[i] = (x->ptr.p_double[i]-v)/vd; - } - } - else - { - if( nounit ) - { - vd = a->ptr.pp_double[1][1]; - } - else - { - vd = (double)(1); - } - x->ptr.p_double[1] = x->ptr.p_double[1]/vd; - for(i=2; i<=n; i++) - { - im1 = i-1; - if( upper ) - { - v = ae_v_dotproduct(&a->ptr.pp_double[1][i], a->stride, &x->ptr.p_double[1], 1, ae_v_len(1,im1)); - } - else - { - v = ae_v_dotproduct(&a->ptr.pp_double[i][1], 1, &x->ptr.p_double[1], 1, ae_v_len(1,im1)); - } - if( nounit ) - { - vd = a->ptr.pp_double[i][i]; - } - else - { - vd = (double)(1); - } - x->ptr.p_double[i] = (x->ptr.p_double[i]-v)/vd; - } - } - } - else - { - - /* - * Use a Level 1 BLAS solve, scaling intermediate results. - */ - if( ae_fp_greater(xmax,bignum) ) - { - - /* - * Scale X so that its components are less than or equal to - * BIGNUM in absolute value. - */ - *s = bignum/xmax; - ae_v_muld(&x->ptr.p_double[1], 1, ae_v_len(1,n), *s); - xmax = bignum; - } - if( notran ) - { - - /* - * Solve A * x = b - */ - j = jfirst; - while((jinc>0&&j<=jlast)||(jinc<0&&j>=jlast)) - { - - /* - * Compute x(j) = b(j) / A(j,j), scaling x if necessary. - */ - xj = ae_fabs(x->ptr.p_double[j], _state); - flg = 0; - if( nounit ) - { - tjjs = a->ptr.pp_double[j][j]*tscal; - } - else - { - tjjs = tscal; - if( ae_fp_eq(tscal,(double)(1)) ) - { - flg = 100; - } - } - if( flg!=100 ) - { - tjj = ae_fabs(tjjs, _state); - if( ae_fp_greater(tjj,smlnum) ) - { - - /* - * abs(A(j,j)) > SMLNUM: - */ - if( ae_fp_less(tjj,(double)(1)) ) - { - if( ae_fp_greater(xj,tjj*bignum) ) - { - - /* - * Scale x by 1/b(j). - */ - rec = 1/xj; - ae_v_muld(&x->ptr.p_double[1], 1, ae_v_len(1,n), rec); - *s = *s*rec; - xmax = xmax*rec; - } - } - x->ptr.p_double[j] = x->ptr.p_double[j]/tjjs; - xj = ae_fabs(x->ptr.p_double[j], _state); - } - else - { - if( ae_fp_greater(tjj,(double)(0)) ) - { - - /* - * 0 < abs(A(j,j)) <= SMLNUM: - */ - if( ae_fp_greater(xj,tjj*bignum) ) - { - - /* - * Scale x by (1/abs(x(j)))*abs(A(j,j))*BIGNUM - * to avoid overflow when dividing by A(j,j). - */ - rec = tjj*bignum/xj; - if( ae_fp_greater(cnorm->ptr.p_double[j],(double)(1)) ) - { - - /* - * Scale by 1/CNORM(j) to avoid overflow when - * multiplying x(j) times column j. - */ - rec = rec/cnorm->ptr.p_double[j]; - } - ae_v_muld(&x->ptr.p_double[1], 1, ae_v_len(1,n), rec); - *s = *s*rec; - xmax = xmax*rec; - } - x->ptr.p_double[j] = x->ptr.p_double[j]/tjjs; - xj = ae_fabs(x->ptr.p_double[j], _state); - } - else - { - - /* - * A(j,j) = 0: Set x(1:n) = 0, x(j) = 1, and - * scale = 0, and compute a solution to A*x = 0. - */ - for(i=1; i<=n; i++) - { - x->ptr.p_double[i] = (double)(0); - } - x->ptr.p_double[j] = (double)(1); - xj = (double)(1); - *s = (double)(0); - xmax = (double)(0); - } - } - } - - /* - * Scale x if necessary to avoid overflow when adding a - * multiple of column j of A. - */ - if( ae_fp_greater(xj,(double)(1)) ) - { - rec = 1/xj; - if( ae_fp_greater(cnorm->ptr.p_double[j],(bignum-xmax)*rec) ) - { - - /* - * Scale x by 1/(2*abs(x(j))). - */ - rec = rec*0.5; - ae_v_muld(&x->ptr.p_double[1], 1, ae_v_len(1,n), rec); - *s = *s*rec; - } - } - else - { - if( ae_fp_greater(xj*cnorm->ptr.p_double[j],bignum-xmax) ) - { - - /* - * Scale x by 1/2. - */ - ae_v_muld(&x->ptr.p_double[1], 1, ae_v_len(1,n), 0.5); - *s = *s*0.5; - } - } - if( upper ) - { - if( j>1 ) - { - - /* - * Compute the update - * x(1:j-1) := x(1:j-1) - x(j) * A(1:j-1,j) - */ - v = x->ptr.p_double[j]*tscal; - jm1 = j-1; - ae_v_subd(&x->ptr.p_double[1], 1, &a->ptr.pp_double[1][j], a->stride, ae_v_len(1,jm1), v); - i = 1; - for(k=2; k<=j-1; k++) - { - if( ae_fp_greater(ae_fabs(x->ptr.p_double[k], _state),ae_fabs(x->ptr.p_double[i], _state)) ) - { - i = k; - } - } - xmax = ae_fabs(x->ptr.p_double[i], _state); - } - } - else - { - if( jptr.p_double[j]*tscal; - ae_v_subd(&x->ptr.p_double[jp1], 1, &a->ptr.pp_double[jp1][j], a->stride, ae_v_len(jp1,n), v); - i = j+1; - for(k=j+2; k<=n; k++) - { - if( ae_fp_greater(ae_fabs(x->ptr.p_double[k], _state),ae_fabs(x->ptr.p_double[i], _state)) ) - { - i = k; - } - } - xmax = ae_fabs(x->ptr.p_double[i], _state); - } - } - j = j+jinc; - } - } - else - { - - /* - * Solve A' * x = b - */ - j = jfirst; - while((jinc>0&&j<=jlast)||(jinc<0&&j>=jlast)) - { - - /* - * Compute x(j) = b(j) - sum A(k,j)*x(k). - * k<>j - */ - xj = ae_fabs(x->ptr.p_double[j], _state); - uscal = tscal; - rec = 1/ae_maxreal(xmax, (double)(1), _state); - if( ae_fp_greater(cnorm->ptr.p_double[j],(bignum-xj)*rec) ) - { - - /* - * If x(j) could overflow, scale x by 1/(2*XMAX). - */ - rec = rec*0.5; - if( nounit ) - { - tjjs = a->ptr.pp_double[j][j]*tscal; - } - else - { - tjjs = tscal; - } - tjj = ae_fabs(tjjs, _state); - if( ae_fp_greater(tjj,(double)(1)) ) - { - - /* - * Divide by A(j,j) when scaling x if A(j,j) > 1. - */ - rec = ae_minreal((double)(1), rec*tjj, _state); - uscal = uscal/tjjs; - } - if( ae_fp_less(rec,(double)(1)) ) - { - ae_v_muld(&x->ptr.p_double[1], 1, ae_v_len(1,n), rec); - *s = *s*rec; - xmax = xmax*rec; - } - } - sumj = (double)(0); - if( ae_fp_eq(uscal,(double)(1)) ) - { - - /* - * If the scaling needed for A in the dot product is 1, - * call DDOT to perform the dot product. - */ - if( upper ) - { - if( j>1 ) - { - jm1 = j-1; - sumj = ae_v_dotproduct(&a->ptr.pp_double[1][j], a->stride, &x->ptr.p_double[1], 1, ae_v_len(1,jm1)); - } - else - { - sumj = (double)(0); - } - } - else - { - if( jptr.pp_double[jp1][j], a->stride, &x->ptr.p_double[jp1], 1, ae_v_len(jp1,n)); - } - } - } - else - { - - /* - * Otherwise, use in-line code for the dot product. - */ - if( upper ) - { - for(i=1; i<=j-1; i++) - { - v = a->ptr.pp_double[i][j]*uscal; - sumj = sumj+v*x->ptr.p_double[i]; - } - } - else - { - if( jptr.pp_double[i][j]*uscal; - sumj = sumj+v*x->ptr.p_double[i]; - } - } - } - } - if( ae_fp_eq(uscal,tscal) ) - { - - /* - * Compute x(j) := ( x(j) - sumj ) / A(j,j) if 1/A(j,j) - * was not used to scale the dotproduct. - */ - x->ptr.p_double[j] = x->ptr.p_double[j]-sumj; - xj = ae_fabs(x->ptr.p_double[j], _state); - flg = 0; - if( nounit ) - { - tjjs = a->ptr.pp_double[j][j]*tscal; - } - else - { - tjjs = tscal; - if( ae_fp_eq(tscal,(double)(1)) ) - { - flg = 150; - } - } - - /* - * Compute x(j) = x(j) / A(j,j), scaling if necessary. - */ - if( flg!=150 ) - { - tjj = ae_fabs(tjjs, _state); - if( ae_fp_greater(tjj,smlnum) ) - { - - /* - * abs(A(j,j)) > SMLNUM: - */ - if( ae_fp_less(tjj,(double)(1)) ) - { - if( ae_fp_greater(xj,tjj*bignum) ) - { - - /* - * Scale X by 1/abs(x(j)). - */ - rec = 1/xj; - ae_v_muld(&x->ptr.p_double[1], 1, ae_v_len(1,n), rec); - *s = *s*rec; - xmax = xmax*rec; - } - } - x->ptr.p_double[j] = x->ptr.p_double[j]/tjjs; - } - else - { - if( ae_fp_greater(tjj,(double)(0)) ) - { - - /* - * 0 < abs(A(j,j)) <= SMLNUM: - */ - if( ae_fp_greater(xj,tjj*bignum) ) - { - - /* - * Scale x by (1/abs(x(j)))*abs(A(j,j))*BIGNUM. - */ - rec = tjj*bignum/xj; - ae_v_muld(&x->ptr.p_double[1], 1, ae_v_len(1,n), rec); - *s = *s*rec; - xmax = xmax*rec; - } - x->ptr.p_double[j] = x->ptr.p_double[j]/tjjs; - } - else - { - - /* - * A(j,j) = 0: Set x(1:n) = 0, x(j) = 1, and - * scale = 0, and compute a solution to A'*x = 0. - */ - for(i=1; i<=n; i++) - { - x->ptr.p_double[i] = (double)(0); - } - x->ptr.p_double[j] = (double)(1); - *s = (double)(0); - xmax = (double)(0); - } - } - } - } - else - { - - /* - * Compute x(j) := x(j) / A(j,j) - sumj if the dot - * product has already been divided by 1/A(j,j). - */ - x->ptr.p_double[j] = x->ptr.p_double[j]/tjjs-sumj; - } - xmax = ae_maxreal(xmax, ae_fabs(x->ptr.p_double[j], _state), _state); - j = j+jinc; - } - } - *s = *s/tscal; - } - - /* - * Scale the column norms by 1/TSCAL for return. - */ - if( ae_fp_neq(tscal,(double)(1)) ) - { - v = 1/tscal; - ae_v_muld(&cnorm->ptr.p_double[1], 1, ae_v_len(1,n), v); - } -} - - -#endif -#if defined(AE_COMPILE_SAFESOLVE) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Real implementation of CMatrixScaledTRSafeSolve - - -- ALGLIB routine -- - 21.01.2010 - Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixscaledtrsafesolve(/* Real */ ae_matrix* a, - double sa, - ae_int_t n, - /* Real */ ae_vector* x, - ae_bool isupper, - ae_int_t trans, - ae_bool isunit, - double maxgrowth, - ae_state *_state) -{ - ae_frame _frame_block; - double lnmax; - double nrmb; - double nrmx; - ae_int_t i; - ae_complex alpha; - ae_complex beta; - double vr; - ae_complex cx; - ae_vector tmp; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&tmp, 0, sizeof(tmp)); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - - ae_assert(n>0, "RMatrixTRSafeSolve: incorrect N!", _state); - ae_assert(trans==0||trans==1, "RMatrixTRSafeSolve: incorrect Trans!", _state); - result = ae_true; - lnmax = ae_log(ae_maxrealnumber, _state); - - /* - * Quick return if possible - */ - if( n<=0 ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Load norms: right part and X - */ - nrmb = (double)(0); - for(i=0; i<=n-1; i++) - { - nrmb = ae_maxreal(nrmb, ae_fabs(x->ptr.p_double[i], _state), _state); - } - nrmx = (double)(0); - - /* - * Solve - */ - ae_vector_set_length(&tmp, n, _state); - result = ae_true; - if( isupper&&trans==0 ) - { - - /* - * U*x = b - */ - for(i=n-1; i>=0; i--) - { - - /* - * Task is reduced to alpha*x[i] = beta - */ - if( isunit ) - { - alpha = ae_complex_from_d(sa); - } - else - { - alpha = ae_complex_from_d(a->ptr.pp_double[i][i]*sa); - } - if( iptr.pp_double[i][i+1], 1, ae_v_len(i+1,n-1), sa); - vr = ae_v_dotproduct(&tmp.ptr.p_double[i+1], 1, &x->ptr.p_double[i+1], 1, ae_v_len(i+1,n-1)); - beta = ae_complex_from_d(x->ptr.p_double[i]-vr); - } - else - { - beta = ae_complex_from_d(x->ptr.p_double[i]); - } - - /* - * solve alpha*x[i] = beta - */ - result = safesolve_cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, &nrmx, &cx, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - x->ptr.p_double[i] = cx.x; - } - ae_frame_leave(_state); - return result; - } - if( !isupper&&trans==0 ) - { - - /* - * L*x = b - */ - for(i=0; i<=n-1; i++) - { - - /* - * Task is reduced to alpha*x[i] = beta - */ - if( isunit ) - { - alpha = ae_complex_from_d(sa); - } - else - { - alpha = ae_complex_from_d(a->ptr.pp_double[i][i]*sa); - } - if( i>0 ) - { - ae_v_moved(&tmp.ptr.p_double[0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,i-1), sa); - vr = ae_v_dotproduct(&tmp.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,i-1)); - beta = ae_complex_from_d(x->ptr.p_double[i]-vr); - } - else - { - beta = ae_complex_from_d(x->ptr.p_double[i]); - } - - /* - * solve alpha*x[i] = beta - */ - result = safesolve_cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, &nrmx, &cx, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - x->ptr.p_double[i] = cx.x; - } - ae_frame_leave(_state); - return result; - } - if( isupper&&trans==1 ) - { - - /* - * U^T*x = b - */ - for(i=0; i<=n-1; i++) - { - - /* - * Task is reduced to alpha*x[i] = beta - */ - if( isunit ) - { - alpha = ae_complex_from_d(sa); - } - else - { - alpha = ae_complex_from_d(a->ptr.pp_double[i][i]*sa); - } - beta = ae_complex_from_d(x->ptr.p_double[i]); - - /* - * solve alpha*x[i] = beta - */ - result = safesolve_cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, &nrmx, &cx, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - x->ptr.p_double[i] = cx.x; - - /* - * update the rest of right part - */ - if( iptr.pp_double[i][i+1], 1, ae_v_len(i+1,n-1), sa); - ae_v_subd(&x->ptr.p_double[i+1], 1, &tmp.ptr.p_double[i+1], 1, ae_v_len(i+1,n-1), vr); - } - } - ae_frame_leave(_state); - return result; - } - if( !isupper&&trans==1 ) - { - - /* - * L^T*x = b - */ - for(i=n-1; i>=0; i--) - { - - /* - * Task is reduced to alpha*x[i] = beta - */ - if( isunit ) - { - alpha = ae_complex_from_d(sa); - } - else - { - alpha = ae_complex_from_d(a->ptr.pp_double[i][i]*sa); - } - beta = ae_complex_from_d(x->ptr.p_double[i]); - - /* - * solve alpha*x[i] = beta - */ - result = safesolve_cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, &nrmx, &cx, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - x->ptr.p_double[i] = cx.x; - - /* - * update the rest of right part - */ - if( i>0 ) - { - vr = cx.x; - ae_v_moved(&tmp.ptr.p_double[0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,i-1), sa); - ae_v_subd(&x->ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,i-1), vr); - } - } - ae_frame_leave(_state); - return result; - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Internal subroutine for safe solution of - - SA*op(A)=b - -where A is NxN upper/lower triangular/unitriangular matrix, op(A) is -either identity transform, transposition or Hermitian transposition, SA is -a scaling factor such that max(|SA*A[i,j]|) is close to 1.0 in magnutude. - -This subroutine limits relative growth of solution (in inf-norm) by -MaxGrowth, returning False if growth exceeds MaxGrowth. Degenerate or -near-degenerate matrices are handled correctly (False is returned) as long -as MaxGrowth is significantly less than MaxRealNumber/norm(b). - - -- ALGLIB routine -- - 21.01.2010 - Bochkanov Sergey -*************************************************************************/ -ae_bool cmatrixscaledtrsafesolve(/* Complex */ ae_matrix* a, - double sa, - ae_int_t n, - /* Complex */ ae_vector* x, - ae_bool isupper, - ae_int_t trans, - ae_bool isunit, - double maxgrowth, - ae_state *_state) -{ - ae_frame _frame_block; - double lnmax; - double nrmb; - double nrmx; - ae_int_t i; - ae_complex alpha; - ae_complex beta; - ae_complex vc; - ae_vector tmp; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&tmp, 0, sizeof(tmp)); - ae_vector_init(&tmp, 0, DT_COMPLEX, _state, ae_true); - - ae_assert(n>0, "CMatrixTRSafeSolve: incorrect N!", _state); - ae_assert((trans==0||trans==1)||trans==2, "CMatrixTRSafeSolve: incorrect Trans!", _state); - result = ae_true; - lnmax = ae_log(ae_maxrealnumber, _state); - - /* - * Quick return if possible - */ - if( n<=0 ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Load norms: right part and X - */ - nrmb = (double)(0); - for(i=0; i<=n-1; i++) - { - nrmb = ae_maxreal(nrmb, ae_c_abs(x->ptr.p_complex[i], _state), _state); - } - nrmx = (double)(0); - - /* - * Solve - */ - ae_vector_set_length(&tmp, n, _state); - result = ae_true; - if( isupper&&trans==0 ) - { - - /* - * U*x = b - */ - for(i=n-1; i>=0; i--) - { - - /* - * Task is reduced to alpha*x[i] = beta - */ - if( isunit ) - { - alpha = ae_complex_from_d(sa); - } - else - { - alpha = ae_c_mul_d(a->ptr.pp_complex[i][i],sa); - } - if( iptr.pp_complex[i][i+1], 1, "N", ae_v_len(i+1,n-1), sa); - vc = ae_v_cdotproduct(&tmp.ptr.p_complex[i+1], 1, "N", &x->ptr.p_complex[i+1], 1, "N", ae_v_len(i+1,n-1)); - beta = ae_c_sub(x->ptr.p_complex[i],vc); - } - else - { - beta = x->ptr.p_complex[i]; - } - - /* - * solve alpha*x[i] = beta - */ - result = safesolve_cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, &nrmx, &vc, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - x->ptr.p_complex[i] = vc; - } - ae_frame_leave(_state); - return result; - } - if( !isupper&&trans==0 ) - { - - /* - * L*x = b - */ - for(i=0; i<=n-1; i++) - { - - /* - * Task is reduced to alpha*x[i] = beta - */ - if( isunit ) - { - alpha = ae_complex_from_d(sa); - } - else - { - alpha = ae_c_mul_d(a->ptr.pp_complex[i][i],sa); - } - if( i>0 ) - { - ae_v_cmoved(&tmp.ptr.p_complex[0], 1, &a->ptr.pp_complex[i][0], 1, "N", ae_v_len(0,i-1), sa); - vc = ae_v_cdotproduct(&tmp.ptr.p_complex[0], 1, "N", &x->ptr.p_complex[0], 1, "N", ae_v_len(0,i-1)); - beta = ae_c_sub(x->ptr.p_complex[i],vc); - } - else - { - beta = x->ptr.p_complex[i]; - } - - /* - * solve alpha*x[i] = beta - */ - result = safesolve_cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, &nrmx, &vc, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - x->ptr.p_complex[i] = vc; - } - ae_frame_leave(_state); - return result; - } - if( isupper&&trans==1 ) - { - - /* - * U^T*x = b - */ - for(i=0; i<=n-1; i++) - { - - /* - * Task is reduced to alpha*x[i] = beta - */ - if( isunit ) - { - alpha = ae_complex_from_d(sa); - } - else - { - alpha = ae_c_mul_d(a->ptr.pp_complex[i][i],sa); - } - beta = x->ptr.p_complex[i]; - - /* - * solve alpha*x[i] = beta - */ - result = safesolve_cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, &nrmx, &vc, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - x->ptr.p_complex[i] = vc; - - /* - * update the rest of right part - */ - if( iptr.pp_complex[i][i+1], 1, "N", ae_v_len(i+1,n-1), sa); - ae_v_csubc(&x->ptr.p_complex[i+1], 1, &tmp.ptr.p_complex[i+1], 1, "N", ae_v_len(i+1,n-1), vc); - } - } - ae_frame_leave(_state); - return result; - } - if( !isupper&&trans==1 ) - { - - /* - * L^T*x = b - */ - for(i=n-1; i>=0; i--) - { - - /* - * Task is reduced to alpha*x[i] = beta - */ - if( isunit ) - { - alpha = ae_complex_from_d(sa); - } - else - { - alpha = ae_c_mul_d(a->ptr.pp_complex[i][i],sa); - } - beta = x->ptr.p_complex[i]; - - /* - * solve alpha*x[i] = beta - */ - result = safesolve_cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, &nrmx, &vc, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - x->ptr.p_complex[i] = vc; - - /* - * update the rest of right part - */ - if( i>0 ) - { - ae_v_cmoved(&tmp.ptr.p_complex[0], 1, &a->ptr.pp_complex[i][0], 1, "N", ae_v_len(0,i-1), sa); - ae_v_csubc(&x->ptr.p_complex[0], 1, &tmp.ptr.p_complex[0], 1, "N", ae_v_len(0,i-1), vc); - } - } - ae_frame_leave(_state); - return result; - } - if( isupper&&trans==2 ) - { - - /* - * U^H*x = b - */ - for(i=0; i<=n-1; i++) - { - - /* - * Task is reduced to alpha*x[i] = beta - */ - if( isunit ) - { - alpha = ae_complex_from_d(sa); - } - else - { - alpha = ae_c_mul_d(ae_c_conj(a->ptr.pp_complex[i][i], _state),sa); - } - beta = x->ptr.p_complex[i]; - - /* - * solve alpha*x[i] = beta - */ - result = safesolve_cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, &nrmx, &vc, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - x->ptr.p_complex[i] = vc; - - /* - * update the rest of right part - */ - if( iptr.pp_complex[i][i+1], 1, "Conj", ae_v_len(i+1,n-1), sa); - ae_v_csubc(&x->ptr.p_complex[i+1], 1, &tmp.ptr.p_complex[i+1], 1, "N", ae_v_len(i+1,n-1), vc); - } - } - ae_frame_leave(_state); - return result; - } - if( !isupper&&trans==2 ) - { - - /* - * L^T*x = b - */ - for(i=n-1; i>=0; i--) - { - - /* - * Task is reduced to alpha*x[i] = beta - */ - if( isunit ) - { - alpha = ae_complex_from_d(sa); - } - else - { - alpha = ae_c_mul_d(ae_c_conj(a->ptr.pp_complex[i][i], _state),sa); - } - beta = x->ptr.p_complex[i]; - - /* - * solve alpha*x[i] = beta - */ - result = safesolve_cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, &nrmx, &vc, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - x->ptr.p_complex[i] = vc; - - /* - * update the rest of right part - */ - if( i>0 ) - { - ae_v_cmoved(&tmp.ptr.p_complex[0], 1, &a->ptr.pp_complex[i][0], 1, "Conj", ae_v_len(0,i-1), sa); - ae_v_csubc(&x->ptr.p_complex[0], 1, &tmp.ptr.p_complex[0], 1, "N", ae_v_len(0,i-1), vc); - } - } - ae_frame_leave(_state); - return result; - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -complex basic solver-updater for reduced linear system - - alpha*x[i] = beta - -solves this equation and updates it in overlfow-safe manner (keeping track -of relative growth of solution). - -Parameters: - Alpha - alpha - Beta - beta - LnMax - precomputed Ln(MaxRealNumber) - BNorm - inf-norm of b (right part of original system) - MaxGrowth- maximum growth of norm(x) relative to norm(b) - XNorm - inf-norm of other components of X (which are already processed) - it is updated by CBasicSolveAndUpdate. - X - solution - - -- ALGLIB routine -- - 26.01.2009 - Bochkanov Sergey -*************************************************************************/ -static ae_bool safesolve_cbasicsolveandupdate(ae_complex alpha, - ae_complex beta, - double lnmax, - double bnorm, - double maxgrowth, - double* xnorm, - ae_complex* x, - ae_state *_state) -{ - double v; - ae_bool result; - - x->x = 0; - x->y = 0; - - result = ae_false; - if( ae_c_eq_d(alpha,(double)(0)) ) - { - return result; - } - if( ae_c_neq_d(beta,(double)(0)) ) - { - - /* - * alpha*x[i]=beta - */ - v = ae_log(ae_c_abs(beta, _state), _state)-ae_log(ae_c_abs(alpha, _state), _state); - if( ae_fp_greater(v,lnmax) ) - { - return result; - } - *x = ae_c_div(beta,alpha); - } - else - { - - /* - * alpha*x[i]=0 - */ - *x = ae_complex_from_i(0); - } - - /* - * update NrmX, test growth limit - */ - *xnorm = ae_maxreal(*xnorm, ae_c_abs(*x, _state), _state); - if( ae_fp_greater(*xnorm,maxgrowth*bnorm) ) - { - return result; - } - result = ae_true; - return result; -} - - -#endif -#if defined(AE_COMPILE_HBLAS) || !defined(AE_PARTIAL_BUILD) - - -void hermitianmatrixvectormultiply(/* Complex */ ae_matrix* a, - ae_bool isupper, - ae_int_t i1, - ae_int_t i2, - /* Complex */ ae_vector* x, - ae_complex alpha, - /* Complex */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - ae_int_t ba1; - ae_int_t by1; - ae_int_t by2; - ae_int_t bx1; - ae_int_t bx2; - ae_int_t n; - ae_complex v; - - - n = i2-i1+1; - if( n<=0 ) - { - return; - } - - /* - * Let A = L + D + U, where - * L is strictly lower triangular (main diagonal is zero) - * D is diagonal - * U is strictly upper triangular (main diagonal is zero) - * - * A*x = L*x + D*x + U*x - * - * Calculate D*x first - */ - for(i=i1; i<=i2; i++) - { - y->ptr.p_complex[i-i1+1] = ae_c_mul(a->ptr.pp_complex[i][i],x->ptr.p_complex[i-i1+1]); - } - - /* - * Add L*x + U*x - */ - if( isupper ) - { - for(i=i1; i<=i2-1; i++) - { - - /* - * Add L*x to the result - */ - v = x->ptr.p_complex[i-i1+1]; - by1 = i-i1+2; - by2 = n; - ba1 = i+1; - ae_v_caddc(&y->ptr.p_complex[by1], 1, &a->ptr.pp_complex[i][ba1], 1, "Conj", ae_v_len(by1,by2), v); - - /* - * Add U*x to the result - */ - bx1 = i-i1+2; - bx2 = n; - ba1 = i+1; - v = ae_v_cdotproduct(&x->ptr.p_complex[bx1], 1, "N", &a->ptr.pp_complex[i][ba1], 1, "N", ae_v_len(bx1,bx2)); - y->ptr.p_complex[i-i1+1] = ae_c_add(y->ptr.p_complex[i-i1+1],v); - } - } - else - { - for(i=i1+1; i<=i2; i++) - { - - /* - * Add L*x to the result - */ - bx1 = 1; - bx2 = i-i1; - ba1 = i1; - v = ae_v_cdotproduct(&x->ptr.p_complex[bx1], 1, "N", &a->ptr.pp_complex[i][ba1], 1, "N", ae_v_len(bx1,bx2)); - y->ptr.p_complex[i-i1+1] = ae_c_add(y->ptr.p_complex[i-i1+1],v); - - /* - * Add U*x to the result - */ - v = x->ptr.p_complex[i-i1+1]; - by1 = 1; - by2 = i-i1; - ba1 = i1; - ae_v_caddc(&y->ptr.p_complex[by1], 1, &a->ptr.pp_complex[i][ba1], 1, "Conj", ae_v_len(by1,by2), v); - } - } - ae_v_cmulc(&y->ptr.p_complex[1], 1, ae_v_len(1,n), alpha); -} - - -void hermitianrank2update(/* Complex */ ae_matrix* a, - ae_bool isupper, - ae_int_t i1, - ae_int_t i2, - /* Complex */ ae_vector* x, - /* Complex */ ae_vector* y, - /* Complex */ ae_vector* t, - ae_complex alpha, - ae_state *_state) -{ - ae_int_t i; - ae_int_t tp1; - ae_int_t tp2; - ae_complex v; - - - if( isupper ) - { - for(i=i1; i<=i2; i++) - { - tp1 = i+1-i1; - tp2 = i2-i1+1; - v = ae_c_mul(alpha,x->ptr.p_complex[i+1-i1]); - ae_v_cmovec(&t->ptr.p_complex[tp1], 1, &y->ptr.p_complex[tp1], 1, "Conj", ae_v_len(tp1,tp2), v); - v = ae_c_mul(ae_c_conj(alpha, _state),y->ptr.p_complex[i+1-i1]); - ae_v_caddc(&t->ptr.p_complex[tp1], 1, &x->ptr.p_complex[tp1], 1, "Conj", ae_v_len(tp1,tp2), v); - ae_v_cadd(&a->ptr.pp_complex[i][i], 1, &t->ptr.p_complex[tp1], 1, "N", ae_v_len(i,i2)); - } - } - else - { - for(i=i1; i<=i2; i++) - { - tp1 = 1; - tp2 = i+1-i1; - v = ae_c_mul(alpha,x->ptr.p_complex[i+1-i1]); - ae_v_cmovec(&t->ptr.p_complex[tp1], 1, &y->ptr.p_complex[tp1], 1, "Conj", ae_v_len(tp1,tp2), v); - v = ae_c_mul(ae_c_conj(alpha, _state),y->ptr.p_complex[i+1-i1]); - ae_v_caddc(&t->ptr.p_complex[tp1], 1, &x->ptr.p_complex[tp1], 1, "Conj", ae_v_len(tp1,tp2), v); - ae_v_cadd(&a->ptr.pp_complex[i][i1], 1, &t->ptr.p_complex[tp1], 1, "N", ae_v_len(i1,i)); - } - } -} - - -#endif -#if defined(AE_COMPILE_SBLAS) || !defined(AE_PARTIAL_BUILD) - - -void symmetricmatrixvectormultiply(/* Real */ ae_matrix* a, - ae_bool isupper, - ae_int_t i1, - ae_int_t i2, - /* Real */ ae_vector* x, - double alpha, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - ae_int_t ba1; - ae_int_t ba2; - ae_int_t by1; - ae_int_t by2; - ae_int_t bx1; - ae_int_t bx2; - ae_int_t n; - double v; - - - n = i2-i1+1; - if( n<=0 ) - { - return; - } - - /* - * Let A = L + D + U, where - * L is strictly lower triangular (main diagonal is zero) - * D is diagonal - * U is strictly upper triangular (main diagonal is zero) - * - * A*x = L*x + D*x + U*x - * - * Calculate D*x first - */ - for(i=i1; i<=i2; i++) - { - y->ptr.p_double[i-i1+1] = a->ptr.pp_double[i][i]*x->ptr.p_double[i-i1+1]; - } - - /* - * Add L*x + U*x - */ - if( isupper ) - { - for(i=i1; i<=i2-1; i++) - { - - /* - * Add L*x to the result - */ - v = x->ptr.p_double[i-i1+1]; - by1 = i-i1+2; - by2 = n; - ba1 = i+1; - ba2 = i2; - ae_v_addd(&y->ptr.p_double[by1], 1, &a->ptr.pp_double[i][ba1], 1, ae_v_len(by1,by2), v); - - /* - * Add U*x to the result - */ - bx1 = i-i1+2; - bx2 = n; - ba1 = i+1; - ba2 = i2; - v = ae_v_dotproduct(&x->ptr.p_double[bx1], 1, &a->ptr.pp_double[i][ba1], 1, ae_v_len(bx1,bx2)); - y->ptr.p_double[i-i1+1] = y->ptr.p_double[i-i1+1]+v; - } - } - else - { - for(i=i1+1; i<=i2; i++) - { - - /* - * Add L*x to the result - */ - bx1 = 1; - bx2 = i-i1; - ba1 = i1; - ba2 = i-1; - v = ae_v_dotproduct(&x->ptr.p_double[bx1], 1, &a->ptr.pp_double[i][ba1], 1, ae_v_len(bx1,bx2)); - y->ptr.p_double[i-i1+1] = y->ptr.p_double[i-i1+1]+v; - - /* - * Add U*x to the result - */ - v = x->ptr.p_double[i-i1+1]; - by1 = 1; - by2 = i-i1; - ba1 = i1; - ba2 = i-1; - ae_v_addd(&y->ptr.p_double[by1], 1, &a->ptr.pp_double[i][ba1], 1, ae_v_len(by1,by2), v); - } - } - ae_v_muld(&y->ptr.p_double[1], 1, ae_v_len(1,n), alpha); - touchint(&ba2, _state); -} - - -void symmetricrank2update(/* Real */ ae_matrix* a, - ae_bool isupper, - ae_int_t i1, - ae_int_t i2, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* t, - double alpha, - ae_state *_state) -{ - ae_int_t i; - ae_int_t tp1; - ae_int_t tp2; - double v; - - - if( isupper ) - { - for(i=i1; i<=i2; i++) - { - tp1 = i+1-i1; - tp2 = i2-i1+1; - v = x->ptr.p_double[i+1-i1]; - ae_v_moved(&t->ptr.p_double[tp1], 1, &y->ptr.p_double[tp1], 1, ae_v_len(tp1,tp2), v); - v = y->ptr.p_double[i+1-i1]; - ae_v_addd(&t->ptr.p_double[tp1], 1, &x->ptr.p_double[tp1], 1, ae_v_len(tp1,tp2), v); - ae_v_muld(&t->ptr.p_double[tp1], 1, ae_v_len(tp1,tp2), alpha); - ae_v_add(&a->ptr.pp_double[i][i], 1, &t->ptr.p_double[tp1], 1, ae_v_len(i,i2)); - } - } - else - { - for(i=i1; i<=i2; i++) - { - tp1 = 1; - tp2 = i+1-i1; - v = x->ptr.p_double[i+1-i1]; - ae_v_moved(&t->ptr.p_double[tp1], 1, &y->ptr.p_double[tp1], 1, ae_v_len(tp1,tp2), v); - v = y->ptr.p_double[i+1-i1]; - ae_v_addd(&t->ptr.p_double[tp1], 1, &x->ptr.p_double[tp1], 1, ae_v_len(tp1,tp2), v); - ae_v_muld(&t->ptr.p_double[tp1], 1, ae_v_len(tp1,tp2), alpha); - ae_v_add(&a->ptr.pp_double[i][i1], 1, &t->ptr.p_double[tp1], 1, ae_v_len(i1,i)); - } - } -} - - -#endif -#if defined(AE_COMPILE_BLAS) || !defined(AE_PARTIAL_BUILD) - - -double vectornorm2(/* Real */ ae_vector* x, - ae_int_t i1, - ae_int_t i2, - ae_state *_state) -{ - ae_int_t n; - ae_int_t ix; - double absxi; - double scl; - double ssq; - double result; - - - n = i2-i1+1; - if( n<1 ) - { - result = (double)(0); - return result; - } - if( n==1 ) - { - result = ae_fabs(x->ptr.p_double[i1], _state); - return result; - } - scl = (double)(0); - ssq = (double)(1); - for(ix=i1; ix<=i2; ix++) - { - if( ae_fp_neq(x->ptr.p_double[ix],(double)(0)) ) - { - absxi = ae_fabs(x->ptr.p_double[ix], _state); - if( ae_fp_less(scl,absxi) ) - { - ssq = 1+ssq*ae_sqr(scl/absxi, _state); - scl = absxi; - } - else - { - ssq = ssq+ae_sqr(absxi/scl, _state); - } - } - } - result = scl*ae_sqrt(ssq, _state); - return result; -} - - -ae_int_t vectoridxabsmax(/* Real */ ae_vector* x, - ae_int_t i1, - ae_int_t i2, - ae_state *_state) -{ - ae_int_t i; - ae_int_t result; - - - result = i1; - for(i=i1+1; i<=i2; i++) - { - if( ae_fp_greater(ae_fabs(x->ptr.p_double[i], _state),ae_fabs(x->ptr.p_double[result], _state)) ) - { - result = i; - } - } - return result; -} - - -ae_int_t columnidxabsmax(/* Real */ ae_matrix* x, - ae_int_t i1, - ae_int_t i2, - ae_int_t j, - ae_state *_state) -{ - ae_int_t i; - ae_int_t result; - - - result = i1; - for(i=i1+1; i<=i2; i++) - { - if( ae_fp_greater(ae_fabs(x->ptr.pp_double[i][j], _state),ae_fabs(x->ptr.pp_double[result][j], _state)) ) - { - result = i; - } - } - return result; -} - - -ae_int_t rowidxabsmax(/* Real */ ae_matrix* x, - ae_int_t j1, - ae_int_t j2, - ae_int_t i, - ae_state *_state) -{ - ae_int_t j; - ae_int_t result; - - - result = j1; - for(j=j1+1; j<=j2; j++) - { - if( ae_fp_greater(ae_fabs(x->ptr.pp_double[i][j], _state),ae_fabs(x->ptr.pp_double[i][result], _state)) ) - { - result = j; - } - } - return result; -} - - -double upperhessenberg1norm(/* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t i2, - ae_int_t j1, - ae_int_t j2, - /* Real */ ae_vector* work, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double result; - - - ae_assert(i2-i1==j2-j1, "UpperHessenberg1Norm: I2-I1<>J2-J1!", _state); - for(j=j1; j<=j2; j++) - { - work->ptr.p_double[j] = (double)(0); - } - for(i=i1; i<=i2; i++) - { - for(j=ae_maxint(j1, j1+i-i1-1, _state); j<=j2; j++) - { - work->ptr.p_double[j] = work->ptr.p_double[j]+ae_fabs(a->ptr.pp_double[i][j], _state); - } - } - result = (double)(0); - for(j=j1; j<=j2; j++) - { - result = ae_maxreal(result, work->ptr.p_double[j], _state); - } - return result; -} - - -void copymatrix(/* Real */ ae_matrix* a, - ae_int_t is1, - ae_int_t is2, - ae_int_t js1, - ae_int_t js2, - /* Real */ ae_matrix* b, - ae_int_t id1, - ae_int_t id2, - ae_int_t jd1, - ae_int_t jd2, - ae_state *_state) -{ - ae_int_t isrc; - ae_int_t idst; - - - if( is1>is2||js1>js2 ) - { - return; - } - ae_assert(is2-is1==id2-id1, "CopyMatrix: different sizes!", _state); - ae_assert(js2-js1==jd2-jd1, "CopyMatrix: different sizes!", _state); - for(isrc=is1; isrc<=is2; isrc++) - { - idst = isrc-is1+id1; - ae_v_move(&b->ptr.pp_double[idst][jd1], 1, &a->ptr.pp_double[isrc][js1], 1, ae_v_len(jd1,jd2)); - } -} - - -void inplacetranspose(/* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t i2, - ae_int_t j1, - ae_int_t j2, - /* Real */ ae_vector* work, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t ips; - ae_int_t jps; - ae_int_t l; - - - if( i1>i2||j1>j2 ) - { - return; - } - ae_assert(i1-i2==j1-j2, "InplaceTranspose error: incorrect array size!", _state); - for(i=i1; i<=i2-1; i++) - { - j = j1+i-i1; - ips = i+1; - jps = j1+ips-i1; - l = i2-i; - ae_v_move(&work->ptr.p_double[1], 1, &a->ptr.pp_double[ips][j], a->stride, ae_v_len(1,l)); - ae_v_move(&a->ptr.pp_double[ips][j], a->stride, &a->ptr.pp_double[i][jps], 1, ae_v_len(ips,i2)); - ae_v_move(&a->ptr.pp_double[i][jps], 1, &work->ptr.p_double[1], 1, ae_v_len(jps,j2)); - } -} - - -void copyandtranspose(/* Real */ ae_matrix* a, - ae_int_t is1, - ae_int_t is2, - ae_int_t js1, - ae_int_t js2, - /* Real */ ae_matrix* b, - ae_int_t id1, - ae_int_t id2, - ae_int_t jd1, - ae_int_t jd2, - ae_state *_state) -{ - ae_int_t isrc; - ae_int_t jdst; - - - if( is1>is2||js1>js2 ) - { - return; - } - ae_assert(is2-is1==jd2-jd1, "CopyAndTranspose: different sizes!", _state); - ae_assert(js2-js1==id2-id1, "CopyAndTranspose: different sizes!", _state); - for(isrc=is1; isrc<=is2; isrc++) - { - jdst = isrc-is1+jd1; - ae_v_move(&b->ptr.pp_double[id1][jdst], b->stride, &a->ptr.pp_double[isrc][js1], 1, ae_v_len(id1,id2)); - } -} - - -void matrixvectormultiply(/* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t i2, - ae_int_t j1, - ae_int_t j2, - ae_bool trans, - /* Real */ ae_vector* x, - ae_int_t ix1, - ae_int_t ix2, - double alpha, - /* Real */ ae_vector* y, - ae_int_t iy1, - ae_int_t iy2, - double beta, - ae_state *_state) -{ - ae_int_t i; - double v; - - - if( !trans ) - { - - /* - * y := alpha*A*x + beta*y; - */ - if( i1>i2||j1>j2 ) - { - return; - } - ae_assert(j2-j1==ix2-ix1, "MatrixVectorMultiply: A and X dont match!", _state); - ae_assert(i2-i1==iy2-iy1, "MatrixVectorMultiply: A and Y dont match!", _state); - - /* - * beta*y - */ - if( ae_fp_eq(beta,(double)(0)) ) - { - for(i=iy1; i<=iy2; i++) - { - y->ptr.p_double[i] = (double)(0); - } - } - else - { - ae_v_muld(&y->ptr.p_double[iy1], 1, ae_v_len(iy1,iy2), beta); - } - - /* - * alpha*A*x - */ - for(i=i1; i<=i2; i++) - { - v = ae_v_dotproduct(&a->ptr.pp_double[i][j1], 1, &x->ptr.p_double[ix1], 1, ae_v_len(j1,j2)); - y->ptr.p_double[iy1+i-i1] = y->ptr.p_double[iy1+i-i1]+alpha*v; - } - } - else - { - - /* - * y := alpha*A'*x + beta*y; - */ - if( i1>i2||j1>j2 ) - { - return; - } - ae_assert(i2-i1==ix2-ix1, "MatrixVectorMultiply: A and X dont match!", _state); - ae_assert(j2-j1==iy2-iy1, "MatrixVectorMultiply: A and Y dont match!", _state); - - /* - * beta*y - */ - if( ae_fp_eq(beta,(double)(0)) ) - { - for(i=iy1; i<=iy2; i++) - { - y->ptr.p_double[i] = (double)(0); - } - } - else - { - ae_v_muld(&y->ptr.p_double[iy1], 1, ae_v_len(iy1,iy2), beta); - } - - /* - * alpha*A'*x - */ - for(i=i1; i<=i2; i++) - { - v = alpha*x->ptr.p_double[ix1+i-i1]; - ae_v_addd(&y->ptr.p_double[iy1], 1, &a->ptr.pp_double[i][j1], 1, ae_v_len(iy1,iy2), v); - } - } -} - - -double pythag2(double x, double y, ae_state *_state) -{ - double w; - double xabs; - double yabs; - double z; - double result; - - - xabs = ae_fabs(x, _state); - yabs = ae_fabs(y, _state); - w = ae_maxreal(xabs, yabs, _state); - z = ae_minreal(xabs, yabs, _state); - if( ae_fp_eq(z,(double)(0)) ) - { - result = w; - } - else - { - result = w*ae_sqrt(1+ae_sqr(z/w, _state), _state); - } - return result; -} - - -void matrixmatrixmultiply(/* Real */ ae_matrix* a, - ae_int_t ai1, - ae_int_t ai2, - ae_int_t aj1, - ae_int_t aj2, - ae_bool transa, - /* Real */ ae_matrix* b, - ae_int_t bi1, - ae_int_t bi2, - ae_int_t bj1, - ae_int_t bj2, - ae_bool transb, - double alpha, - /* Real */ ae_matrix* c, - ae_int_t ci1, - ae_int_t ci2, - ae_int_t cj1, - ae_int_t cj2, - double beta, - /* Real */ ae_vector* work, - ae_state *_state) -{ - ae_int_t arows; - ae_int_t acols; - ae_int_t brows; - ae_int_t bcols; - ae_int_t crows; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t l; - ae_int_t r; - double v; - - - - /* - * Setup - */ - if( !transa ) - { - arows = ai2-ai1+1; - acols = aj2-aj1+1; - } - else - { - arows = aj2-aj1+1; - acols = ai2-ai1+1; - } - if( !transb ) - { - brows = bi2-bi1+1; - bcols = bj2-bj1+1; - } - else - { - brows = bj2-bj1+1; - bcols = bi2-bi1+1; - } - ae_assert(acols==brows, "MatrixMatrixMultiply: incorrect matrix sizes!", _state); - if( ((arows<=0||acols<=0)||brows<=0)||bcols<=0 ) - { - return; - } - crows = arows; - - /* - * Test WORK - */ - i = ae_maxint(arows, acols, _state); - i = ae_maxint(brows, i, _state); - i = ae_maxint(i, bcols, _state); - work->ptr.p_double[1] = (double)(0); - work->ptr.p_double[i] = (double)(0); - - /* - * Prepare C - */ - if( ae_fp_eq(beta,(double)(0)) ) - { - for(i=ci1; i<=ci2; i++) - { - for(j=cj1; j<=cj2; j++) - { - c->ptr.pp_double[i][j] = (double)(0); - } - } - } - else - { - for(i=ci1; i<=ci2; i++) - { - ae_v_muld(&c->ptr.pp_double[i][cj1], 1, ae_v_len(cj1,cj2), beta); - } - } - - /* - * A*B - */ - if( !transa&&!transb ) - { - for(l=ai1; l<=ai2; l++) - { - for(r=bi1; r<=bi2; r++) - { - v = alpha*a->ptr.pp_double[l][aj1+r-bi1]; - k = ci1+l-ai1; - ae_v_addd(&c->ptr.pp_double[k][cj1], 1, &b->ptr.pp_double[r][bj1], 1, ae_v_len(cj1,cj2), v); - } - } - return; - } - - /* - * A*B' - */ - if( !transa&&transb ) - { - if( arows*acolsptr.pp_double[l][aj1], 1, &b->ptr.pp_double[r][bj1], 1, ae_v_len(aj1,aj2)); - c->ptr.pp_double[ci1+l-ai1][cj1+r-bi1] = c->ptr.pp_double[ci1+l-ai1][cj1+r-bi1]+alpha*v; - } - } - return; - } - else - { - for(l=ai1; l<=ai2; l++) - { - for(r=bi1; r<=bi2; r++) - { - v = ae_v_dotproduct(&a->ptr.pp_double[l][aj1], 1, &b->ptr.pp_double[r][bj1], 1, ae_v_len(aj1,aj2)); - c->ptr.pp_double[ci1+l-ai1][cj1+r-bi1] = c->ptr.pp_double[ci1+l-ai1][cj1+r-bi1]+alpha*v; - } - } - return; - } - } - - /* - * A'*B - */ - if( transa&&!transb ) - { - for(l=aj1; l<=aj2; l++) - { - for(r=bi1; r<=bi2; r++) - { - v = alpha*a->ptr.pp_double[ai1+r-bi1][l]; - k = ci1+l-aj1; - ae_v_addd(&c->ptr.pp_double[k][cj1], 1, &b->ptr.pp_double[r][bj1], 1, ae_v_len(cj1,cj2), v); - } - } - return; - } - - /* - * A'*B' - */ - if( transa&&transb ) - { - if( arows*acolsptr.p_double[i] = 0.0; - } - for(l=ai1; l<=ai2; l++) - { - v = alpha*b->ptr.pp_double[r][bj1+l-ai1]; - ae_v_addd(&work->ptr.p_double[1], 1, &a->ptr.pp_double[l][aj1], 1, ae_v_len(1,crows), v); - } - ae_v_add(&c->ptr.pp_double[ci1][k], c->stride, &work->ptr.p_double[1], 1, ae_v_len(ci1,ci2)); - } - return; - } - else - { - for(l=aj1; l<=aj2; l++) - { - k = ai2-ai1+1; - ae_v_move(&work->ptr.p_double[1], 1, &a->ptr.pp_double[ai1][l], a->stride, ae_v_len(1,k)); - for(r=bi1; r<=bi2; r++) - { - v = ae_v_dotproduct(&work->ptr.p_double[1], 1, &b->ptr.pp_double[r][bj1], 1, ae_v_len(1,k)); - c->ptr.pp_double[ci1+l-aj1][cj1+r-bi1] = c->ptr.pp_double[ci1+l-aj1][cj1+r-bi1]+alpha*v; - } - } - return; - } - } -} - - -#endif -#if defined(AE_COMPILE_LINMIN) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Normalizes direction/step pair: makes |D|=1, scales Stp. -If |D|=0, it returns, leavind D/Stp unchanged. - - -- ALGLIB -- - Copyright 01.04.2010 by Bochkanov Sergey -*************************************************************************/ -void linminnormalized(/* Real */ ae_vector* d, - double* stp, - ae_int_t n, - ae_state *_state) -{ - double mx; - double s; - ae_int_t i; - - - - /* - * first, scale D to avoid underflow/overflow durng squaring - */ - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - mx = ae_maxreal(mx, ae_fabs(d->ptr.p_double[i], _state), _state); - } - if( ae_fp_eq(mx,(double)(0)) ) - { - return; - } - s = 1/mx; - ae_v_muld(&d->ptr.p_double[0], 1, ae_v_len(0,n-1), s); - *stp = *stp/s; - - /* - * normalize D - */ - s = ae_v_dotproduct(&d->ptr.p_double[0], 1, &d->ptr.p_double[0], 1, ae_v_len(0,n-1)); - s = 1/ae_sqrt(s, _state); - ae_v_muld(&d->ptr.p_double[0], 1, ae_v_len(0,n-1), s); - *stp = *stp/s; -} - - -/************************************************************************* -THE PURPOSE OF MCSRCH IS TO FIND A STEP WHICH SATISFIES A SUFFICIENT -DECREASE CONDITION AND A CURVATURE CONDITION. - -AT EACH STAGE THE SUBROUTINE UPDATES AN INTERVAL OF UNCERTAINTY WITH -ENDPOINTS STX AND STY. THE INTERVAL OF UNCERTAINTY IS INITIALLY CHOSEN -SO THAT IT CONTAINS A MINIMIZER OF THE MODIFIED FUNCTION - - F(X+STP*S) - F(X) - FTOL*STP*(GRADF(X)'S). - -IF A STEP IS OBTAINED FOR WHICH THE MODIFIED FUNCTION HAS A NONPOSITIVE -FUNCTION VALUE AND NONNEGATIVE DERIVATIVE, THEN THE INTERVAL OF -UNCERTAINTY IS CHOSEN SO THAT IT CONTAINS A MINIMIZER OF F(X+STP*S). - -THE ALGORITHM IS DESIGNED TO FIND A STEP WHICH SATISFIES THE SUFFICIENT -DECREASE CONDITION - - F(X+STP*S) .LE. F(X) + FTOL*STP*(GRADF(X)'S), - -AND THE CURVATURE CONDITION - - ABS(GRADF(X+STP*S)'S)) .LE. GTOL*ABS(GRADF(X)'S). - -IF FTOL IS LESS THAN GTOL AND IF, FOR EXAMPLE, THE FUNCTION IS BOUNDED -BELOW, THEN THERE IS ALWAYS A STEP WHICH SATISFIES BOTH CONDITIONS. -IF NO STEP CAN BE FOUND WHICH SATISFIES BOTH CONDITIONS, THEN THE -ALGORITHM USUALLY STOPS WHEN ROUNDING ERRORS PREVENT FURTHER PROGRESS. -IN THIS CASE STP ONLY SATISFIES THE SUFFICIENT DECREASE CONDITION. - - -:::::::::::::IMPORTANT NOTES::::::::::::: - -NOTE 1: - -This routine guarantees that it will stop at the last point where function -value was calculated. It won't make several additional function evaluations -after finding good point. So if you store function evaluations requested by -this routine, you can be sure that last one is the point where we've stopped. - -NOTE 2: - -when 0initial_point - after rounding to machine precision - -NOTE 4: - -when non-descent direction is specified, algorithm stops with MCINFO=0, -Stp=0 and initial point at X[]. -::::::::::::::::::::::::::::::::::::::::: - - -PARAMETERS DESCRIPRION - -STAGE IS ZERO ON FIRST CALL, ZERO ON FINAL EXIT - -N IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER OF VARIABLES. - -X IS AN ARRAY OF LENGTH N. ON INPUT IT MUST CONTAIN THE BASE POINT FOR -THE LINE SEARCH. ON OUTPUT IT CONTAINS X+STP*S. - -F IS A VARIABLE. ON INPUT IT MUST CONTAIN THE VALUE OF F AT X. ON OUTPUT -IT CONTAINS THE VALUE OF F AT X + STP*S. - -G IS AN ARRAY OF LENGTH N. ON INPUT IT MUST CONTAIN THE GRADIENT OF F AT X. -ON OUTPUT IT CONTAINS THE GRADIENT OF F AT X + STP*S. - -S IS AN INPUT ARRAY OF LENGTH N WHICH SPECIFIES THE SEARCH DIRECTION. - -STP IS A NONNEGATIVE VARIABLE. ON INPUT STP CONTAINS AN INITIAL ESTIMATE -OF A SATISFACTORY STEP. ON OUTPUT STP CONTAINS THE FINAL ESTIMATE. - -FTOL AND GTOL ARE NONNEGATIVE INPUT VARIABLES. TERMINATION OCCURS WHEN THE -SUFFICIENT DECREASE CONDITION AND THE DIRECTIONAL DERIVATIVE CONDITION ARE -SATISFIED. - -XTOL IS A NONNEGATIVE INPUT VARIABLE. TERMINATION OCCURS WHEN THE RELATIVE -WIDTH OF THE INTERVAL OF UNCERTAINTY IS AT MOST XTOL. - -STPMIN AND STPMAX ARE NONNEGATIVE INPUT VARIABLES WHICH SPECIFY LOWER AND -UPPER BOUNDS FOR THE STEP. - -MAXFEV IS A POSITIVE INTEGER INPUT VARIABLE. TERMINATION OCCURS WHEN THE -NUMBER OF CALLS TO FCN IS AT LEAST MAXFEV BY THE END OF AN ITERATION. - -INFO IS AN INTEGER OUTPUT VARIABLE SET AS FOLLOWS: - INFO = 0 IMPROPER INPUT PARAMETERS. - - INFO = 1 THE SUFFICIENT DECREASE CONDITION AND THE - DIRECTIONAL DERIVATIVE CONDITION HOLD. - - INFO = 2 RELATIVE WIDTH OF THE INTERVAL OF UNCERTAINTY - IS AT MOST XTOL. - - INFO = 3 NUMBER OF CALLS TO FCN HAS REACHED MAXFEV. - - INFO = 4 THE STEP IS AT THE LOWER BOUND STPMIN. - - INFO = 5 THE STEP IS AT THE UPPER BOUND STPMAX. - - INFO = 6 ROUNDING ERRORS PREVENT FURTHER PROGRESS. - THERE MAY NOT BE A STEP WHICH SATISFIES THE - SUFFICIENT DECREASE AND CURVATURE CONDITIONS. - TOLERANCES MAY BE TOO SMALL. - -NFEV IS AN INTEGER OUTPUT VARIABLE SET TO THE NUMBER OF CALLS TO FCN. - -WA IS A WORK ARRAY OF LENGTH N. - -ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JUNE 1983 -JORGE J. MORE', DAVID J. THUENTE -*************************************************************************/ -void mcsrch(ae_int_t n, - /* Real */ ae_vector* x, - double* f, - /* Real */ ae_vector* g, - /* Real */ ae_vector* s, - double* stp, - double stpmax, - double gtol, - ae_int_t* info, - ae_int_t* nfev, - /* Real */ ae_vector* wa, - linminstate* state, - ae_int_t* stage, - ae_state *_state) -{ - ae_int_t i; - double v; - double p5; - double p66; - double zero; - - - - /* - * init - */ - p5 = 0.5; - p66 = 0.66; - state->xtrapf = 4.0; - zero = (double)(0); - if( ae_fp_eq(stpmax,(double)(0)) ) - { - stpmax = linmin_defstpmax; - } - if( ae_fp_less(*stp,linmin_stpmin) ) - { - *stp = linmin_stpmin; - } - if( ae_fp_greater(*stp,stpmax) ) - { - *stp = stpmax; - } - - /* - * Main cycle - */ - for(;;) - { - if( *stage==0 ) - { - - /* - * NEXT - */ - *stage = 2; - continue; - } - if( *stage==2 ) - { - state->infoc = 1; - *info = 0; - - /* - * CHECK THE INPUT PARAMETERS FOR ERRORS. - */ - if( ae_fp_less(stpmax,linmin_stpmin)&&ae_fp_greater(stpmax,(double)(0)) ) - { - *info = 5; - *stp = stpmax; - *stage = 0; - return; - } - if( ((((((n<=0||ae_fp_less_eq(*stp,(double)(0)))||ae_fp_less(linmin_ftol,(double)(0)))||ae_fp_less(gtol,zero))||ae_fp_less(linmin_xtol,zero))||ae_fp_less(linmin_stpmin,zero))||ae_fp_less(stpmax,linmin_stpmin))||linmin_maxfev<=0 ) - { - *stage = 0; - return; - } - - /* - * COMPUTE THE INITIAL GRADIENT IN THE SEARCH DIRECTION - * AND CHECK THAT S IS A DESCENT DIRECTION. - */ - v = ae_v_dotproduct(&g->ptr.p_double[0], 1, &s->ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->dginit = v; - if( ae_fp_greater_eq(state->dginit,(double)(0)) ) - { - *stage = 0; - *stp = (double)(0); - return; - } - - /* - * INITIALIZE LOCAL VARIABLES. - */ - state->brackt = ae_false; - state->stage1 = ae_true; - *nfev = 0; - state->finit = *f; - state->dgtest = linmin_ftol*state->dginit; - state->width = stpmax-linmin_stpmin; - state->width1 = state->width/p5; - ae_v_move(&wa->ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - - /* - * THE VARIABLES STX, FX, DGX CONTAIN THE VALUES OF THE STEP, - * FUNCTION, AND DIRECTIONAL DERIVATIVE AT THE BEST STEP. - * THE VARIABLES STY, FY, DGY CONTAIN THE VALUE OF THE STEP, - * FUNCTION, AND DERIVATIVE AT THE OTHER ENDPOINT OF - * THE INTERVAL OF UNCERTAINTY. - * THE VARIABLES STP, F, DG CONTAIN THE VALUES OF THE STEP, - * FUNCTION, AND DERIVATIVE AT THE CURRENT STEP. - */ - state->stx = (double)(0); - state->fx = state->finit; - state->dgx = state->dginit; - state->sty = (double)(0); - state->fy = state->finit; - state->dgy = state->dginit; - - /* - * NEXT - */ - *stage = 3; - continue; - } - if( *stage==3 ) - { - - /* - * START OF ITERATION. - * - * SET THE MINIMUM AND MAXIMUM STEPS TO CORRESPOND - * TO THE PRESENT INTERVAL OF UNCERTAINTY. - */ - if( state->brackt ) - { - if( ae_fp_less(state->stx,state->sty) ) - { - state->stmin = state->stx; - state->stmax = state->sty; - } - else - { - state->stmin = state->sty; - state->stmax = state->stx; - } - } - else - { - state->stmin = state->stx; - state->stmax = *stp+state->xtrapf*(*stp-state->stx); - } - - /* - * FORCE THE STEP TO BE WITHIN THE BOUNDS STPMAX AND STPMIN. - */ - if( ae_fp_greater(*stp,stpmax) ) - { - *stp = stpmax; - } - if( ae_fp_less(*stp,linmin_stpmin) ) - { - *stp = linmin_stpmin; - } - - /* - * IF AN UNUSUAL TERMINATION IS TO OCCUR THEN LET - * STP BE THE LOWEST POINT OBTAINED SO FAR. - */ - if( (((state->brackt&&(ae_fp_less_eq(*stp,state->stmin)||ae_fp_greater_eq(*stp,state->stmax)))||*nfev>=linmin_maxfev-1)||state->infoc==0)||(state->brackt&&ae_fp_less_eq(state->stmax-state->stmin,linmin_xtol*state->stmax)) ) - { - *stp = state->stx; - } - - /* - * EVALUATE THE FUNCTION AND GRADIENT AT STP - * AND COMPUTE THE DIRECTIONAL DERIVATIVE. - */ - ae_v_move(&x->ptr.p_double[0], 1, &wa->ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_addd(&x->ptr.p_double[0], 1, &s->ptr.p_double[0], 1, ae_v_len(0,n-1), *stp); - - /* - * NEXT - */ - *stage = 4; - return; - } - if( *stage==4 ) - { - *info = 0; - *nfev = *nfev+1; - v = ae_v_dotproduct(&g->ptr.p_double[0], 1, &s->ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->dg = v; - state->ftest1 = state->finit+*stp*state->dgtest; - - /* - * TEST FOR CONVERGENCE. - */ - if( (state->brackt&&(ae_fp_less_eq(*stp,state->stmin)||ae_fp_greater_eq(*stp,state->stmax)))||state->infoc==0 ) - { - *info = 6; - } - if( ((ae_fp_eq(*stp,stpmax)&&ae_fp_less(*f,state->finit))&&ae_fp_less_eq(*f,state->ftest1))&&ae_fp_less_eq(state->dg,state->dgtest) ) - { - *info = 5; - } - if( ae_fp_eq(*stp,linmin_stpmin)&&((ae_fp_greater_eq(*f,state->finit)||ae_fp_greater(*f,state->ftest1))||ae_fp_greater_eq(state->dg,state->dgtest)) ) - { - *info = 4; - } - if( *nfev>=linmin_maxfev ) - { - *info = 3; - } - if( state->brackt&&ae_fp_less_eq(state->stmax-state->stmin,linmin_xtol*state->stmax) ) - { - *info = 2; - } - if( (ae_fp_less(*f,state->finit)&&ae_fp_less_eq(*f,state->ftest1))&&ae_fp_less_eq(ae_fabs(state->dg, _state),-gtol*state->dginit) ) - { - *info = 1; - } - - /* - * CHECK FOR TERMINATION. - */ - if( *info!=0 ) - { - - /* - * Check guarantees provided by the function for INFO=1 or INFO=5 - */ - if( *info==1||*info==5 ) - { - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+(wa->ptr.p_double[i]-x->ptr.p_double[i])*(wa->ptr.p_double[i]-x->ptr.p_double[i]); - } - if( ae_fp_greater_eq(*f,state->finit)||ae_fp_eq(v,0.0) ) - { - *info = 6; - } - } - *stage = 0; - return; - } - - /* - * IN THE FIRST STAGE WE SEEK A STEP FOR WHICH THE MODIFIED - * FUNCTION HAS A NONPOSITIVE VALUE AND NONNEGATIVE DERIVATIVE. - */ - if( (state->stage1&&ae_fp_less_eq(*f,state->ftest1))&&ae_fp_greater_eq(state->dg,ae_minreal(linmin_ftol, gtol, _state)*state->dginit) ) - { - state->stage1 = ae_false; - } - - /* - * A MODIFIED FUNCTION IS USED TO PREDICT THE STEP ONLY IF - * WE HAVE NOT OBTAINED A STEP FOR WHICH THE MODIFIED - * FUNCTION HAS A NONPOSITIVE FUNCTION VALUE AND NONNEGATIVE - * DERIVATIVE, AND IF A LOWER FUNCTION VALUE HAS BEEN - * OBTAINED BUT THE DECREASE IS NOT SUFFICIENT. - */ - if( (state->stage1&&ae_fp_less_eq(*f,state->fx))&&ae_fp_greater(*f,state->ftest1) ) - { - - /* - * DEFINE THE MODIFIED FUNCTION AND DERIVATIVE VALUES. - */ - state->fm = *f-*stp*state->dgtest; - state->fxm = state->fx-state->stx*state->dgtest; - state->fym = state->fy-state->sty*state->dgtest; - state->dgm = state->dg-state->dgtest; - state->dgxm = state->dgx-state->dgtest; - state->dgym = state->dgy-state->dgtest; - - /* - * CALL CSTEP TO UPDATE THE INTERVAL OF UNCERTAINTY - * AND TO COMPUTE THE NEW STEP. - */ - linmin_mcstep(&state->stx, &state->fxm, &state->dgxm, &state->sty, &state->fym, &state->dgym, stp, state->fm, state->dgm, &state->brackt, state->stmin, state->stmax, &state->infoc, _state); - - /* - * RESET THE FUNCTION AND GRADIENT VALUES FOR F. - */ - state->fx = state->fxm+state->stx*state->dgtest; - state->fy = state->fym+state->sty*state->dgtest; - state->dgx = state->dgxm+state->dgtest; - state->dgy = state->dgym+state->dgtest; - } - else - { - - /* - * CALL MCSTEP TO UPDATE THE INTERVAL OF UNCERTAINTY - * AND TO COMPUTE THE NEW STEP. - */ - linmin_mcstep(&state->stx, &state->fx, &state->dgx, &state->sty, &state->fy, &state->dgy, stp, *f, state->dg, &state->brackt, state->stmin, state->stmax, &state->infoc, _state); - } - - /* - * FORCE A SUFFICIENT DECREASE IN THE SIZE OF THE - * INTERVAL OF UNCERTAINTY. - */ - if( state->brackt ) - { - if( ae_fp_greater_eq(ae_fabs(state->sty-state->stx, _state),p66*state->width1) ) - { - *stp = state->stx+p5*(state->sty-state->stx); - } - state->width1 = state->width; - state->width = ae_fabs(state->sty-state->stx, _state); - } - - /* - * NEXT. - */ - *stage = 3; - continue; - } - } -} - - -/************************************************************************* -These functions perform Armijo line search using at most FMAX function -evaluations. It doesn't enforce some kind of " sufficient decrease" -criterion - it just tries different Armijo steps and returns optimum found -so far. - -Optimization is done using F-rcomm interface: -* ArmijoCreate initializes State structure - (reusing previously allocated buffers) -* ArmijoIteration is subsequently called -* ArmijoResults returns results - -INPUT PARAMETERS: - N - problem size - X - array[N], starting point - F - F(X+S*STP) - S - step direction, S>0 - STP - step length - STPMAX - maximum value for STP or zero (if no limit is imposed) - FMAX - maximum number of function evaluations - State - optimization state - - -- ALGLIB -- - Copyright 05.10.2010 by Bochkanov Sergey -*************************************************************************/ -void armijocreate(ae_int_t n, - /* Real */ ae_vector* x, - double f, - /* Real */ ae_vector* s, - double stp, - double stpmax, - ae_int_t fmax, - armijostate* state, - ae_state *_state) -{ - - - if( state->x.cntx, n, _state); - } - if( state->xbase.cntxbase, n, _state); - } - if( state->s.cnts, n, _state); - } - state->stpmax = stpmax; - state->fmax = fmax; - state->stplen = stp; - state->fcur = f; - state->n = n; - ae_v_move(&state->xbase.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->s.ptr.p_double[0], 1, &s->ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_vector_set_length(&state->rstate.ia, 0+1, _state); - ae_vector_set_length(&state->rstate.ra, 0+1, _state); - state->rstate.stage = -1; -} - - -/************************************************************************* -This is rcomm-based search function - - -- ALGLIB -- - Copyright 05.10.2010 by Bochkanov Sergey -*************************************************************************/ -ae_bool armijoiteration(armijostate* state, ae_state *_state) -{ - double v; - ae_int_t n; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - n = state->rstate.ia.ptr.p_int[0]; - v = state->rstate.ra.ptr.p_double[0]; - } - else - { - n = 359; - v = -58; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - if( state->rstate.stage==1 ) - { - goto lbl_1; - } - if( state->rstate.stage==2 ) - { - goto lbl_2; - } - if( state->rstate.stage==3 ) - { - goto lbl_3; - } - - /* - * Routine body - */ - if( (ae_fp_less_eq(state->stplen,(double)(0))||ae_fp_less(state->stpmax,(double)(0)))||state->fmax<2 ) - { - state->info = 0; - result = ae_false; - return result; - } - if( ae_fp_less_eq(state->stplen,linmin_stpmin) ) - { - state->info = 4; - result = ae_false; - return result; - } - n = state->n; - state->nfev = 0; - - /* - * We always need F - */ - state->needf = ae_true; - - /* - * Bound StpLen - */ - if( ae_fp_greater(state->stplen,state->stpmax)&&ae_fp_neq(state->stpmax,(double)(0)) ) - { - state->stplen = state->stpmax; - } - - /* - * Increase length - */ - v = state->stplen*linmin_armijofactor; - if( ae_fp_greater(v,state->stpmax)&&ae_fp_neq(state->stpmax,(double)(0)) ) - { - v = state->stpmax; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_addd(&state->x.ptr.p_double[0], 1, &state->s.ptr.p_double[0], 1, ae_v_len(0,n-1), v); - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - state->nfev = state->nfev+1; - if( ae_fp_greater_eq(state->f,state->fcur) ) - { - goto lbl_4; - } - state->stplen = v; - state->fcur = state->f; -lbl_6: - if( ae_false ) - { - goto lbl_7; - } - - /* - * test stopping conditions - */ - if( state->nfev>=state->fmax ) - { - state->info = 3; - result = ae_false; - return result; - } - if( ae_fp_greater_eq(state->stplen,state->stpmax) ) - { - state->info = 5; - result = ae_false; - return result; - } - - /* - * evaluate F - */ - v = state->stplen*linmin_armijofactor; - if( ae_fp_greater(v,state->stpmax)&&ae_fp_neq(state->stpmax,(double)(0)) ) - { - v = state->stpmax; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_addd(&state->x.ptr.p_double[0], 1, &state->s.ptr.p_double[0], 1, ae_v_len(0,n-1), v); - state->rstate.stage = 1; - goto lbl_rcomm; -lbl_1: - state->nfev = state->nfev+1; - - /* - * make decision - */ - if( ae_fp_less(state->f,state->fcur) ) - { - state->stplen = v; - state->fcur = state->f; - } - else - { - state->info = 1; - result = ae_false; - return result; - } - goto lbl_6; -lbl_7: -lbl_4: - - /* - * Decrease length - */ - v = state->stplen/linmin_armijofactor; - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_addd(&state->x.ptr.p_double[0], 1, &state->s.ptr.p_double[0], 1, ae_v_len(0,n-1), v); - state->rstate.stage = 2; - goto lbl_rcomm; -lbl_2: - state->nfev = state->nfev+1; - if( ae_fp_greater_eq(state->f,state->fcur) ) - { - goto lbl_8; - } - state->stplen = state->stplen/linmin_armijofactor; - state->fcur = state->f; -lbl_10: - if( ae_false ) - { - goto lbl_11; - } - - /* - * test stopping conditions - */ - if( state->nfev>=state->fmax ) - { - state->info = 3; - result = ae_false; - return result; - } - if( ae_fp_less_eq(state->stplen,linmin_stpmin) ) - { - state->info = 4; - result = ae_false; - return result; - } - - /* - * evaluate F - */ - v = state->stplen/linmin_armijofactor; - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_addd(&state->x.ptr.p_double[0], 1, &state->s.ptr.p_double[0], 1, ae_v_len(0,n-1), v); - state->rstate.stage = 3; - goto lbl_rcomm; -lbl_3: - state->nfev = state->nfev+1; - - /* - * make decision - */ - if( ae_fp_less(state->f,state->fcur) ) - { - state->stplen = state->stplen/linmin_armijofactor; - state->fcur = state->f; - } - else - { - state->info = 1; - result = ae_false; - return result; - } - goto lbl_10; -lbl_11: -lbl_8: - - /* - * Nothing to be done - */ - state->info = 1; - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = n; - state->rstate.ra.ptr.p_double[0] = v; - return result; -} - - -/************************************************************************* -Results of Armijo search - -OUTPUT PARAMETERS: - INFO - on output it is set to one of the return codes: - * 0 improper input params - * 1 optimum step is found with at most FMAX evaluations - * 3 FMAX evaluations were used, - X contains optimum found so far - * 4 step is at lower bound STPMIN - * 5 step is at upper bound - STP - step length (in case of failure it is still returned) - F - function value (in case of failure it is still returned) - - -- ALGLIB -- - Copyright 05.10.2010 by Bochkanov Sergey -*************************************************************************/ -void armijoresults(armijostate* state, - ae_int_t* info, - double* stp, - double* f, - ae_state *_state) -{ - - - *info = state->info; - *stp = state->stplen; - *f = state->fcur; -} - - -static void linmin_mcstep(double* stx, - double* fx, - double* dx, - double* sty, - double* fy, - double* dy, - double* stp, - double fp, - double dp, - ae_bool* brackt, - double stmin, - double stmax, - ae_int_t* info, - ae_state *_state) -{ - ae_bool bound; - double gamma; - double p; - double q; - double r; - double s; - double sgnd; - double stpc; - double stpf; - double stpq; - double theta; - - - *info = 0; - - /* - * CHECK THE INPUT PARAMETERS FOR ERRORS. - */ - if( ((*brackt&&(ae_fp_less_eq(*stp,ae_minreal(*stx, *sty, _state))||ae_fp_greater_eq(*stp,ae_maxreal(*stx, *sty, _state))))||ae_fp_greater_eq(*dx*(*stp-(*stx)),(double)(0)))||ae_fp_less(stmax,stmin) ) - { - return; - } - - /* - * DETERMINE IF THE DERIVATIVES HAVE OPPOSITE SIGN. - */ - sgnd = dp*(*dx/ae_fabs(*dx, _state)); - - /* - * FIRST CASE. A HIGHER FUNCTION VALUE. - * THE MINIMUM IS BRACKETED. IF THE CUBIC STEP IS CLOSER - * TO STX THAN THE QUADRATIC STEP, THE CUBIC STEP IS TAKEN, - * ELSE THE AVERAGE OF THE CUBIC AND QUADRATIC STEPS IS TAKEN. - */ - if( ae_fp_greater(fp,*fx) ) - { - *info = 1; - bound = ae_true; - theta = 3*(*fx-fp)/(*stp-(*stx))+(*dx)+dp; - s = ae_maxreal(ae_fabs(theta, _state), ae_maxreal(ae_fabs(*dx, _state), ae_fabs(dp, _state), _state), _state); - gamma = s*ae_sqrt(ae_sqr(theta/s, _state)-*dx/s*(dp/s), _state); - if( ae_fp_less(*stp,*stx) ) - { - gamma = -gamma; - } - p = gamma-(*dx)+theta; - q = gamma-(*dx)+gamma+dp; - r = p/q; - stpc = *stx+r*(*stp-(*stx)); - stpq = *stx+*dx/((*fx-fp)/(*stp-(*stx))+(*dx))/2*(*stp-(*stx)); - if( ae_fp_less(ae_fabs(stpc-(*stx), _state),ae_fabs(stpq-(*stx), _state)) ) - { - stpf = stpc; - } - else - { - stpf = stpc+(stpq-stpc)/2; - } - *brackt = ae_true; - } - else - { - if( ae_fp_less(sgnd,(double)(0)) ) - { - - /* - * SECOND CASE. A LOWER FUNCTION VALUE AND DERIVATIVES OF - * OPPOSITE SIGN. THE MINIMUM IS BRACKETED. IF THE CUBIC - * STEP IS CLOSER TO STX THAN THE QUADRATIC (SECANT) STEP, - * THE CUBIC STEP IS TAKEN, ELSE THE QUADRATIC STEP IS TAKEN. - */ - *info = 2; - bound = ae_false; - theta = 3*(*fx-fp)/(*stp-(*stx))+(*dx)+dp; - s = ae_maxreal(ae_fabs(theta, _state), ae_maxreal(ae_fabs(*dx, _state), ae_fabs(dp, _state), _state), _state); - gamma = s*ae_sqrt(ae_sqr(theta/s, _state)-*dx/s*(dp/s), _state); - if( ae_fp_greater(*stp,*stx) ) - { - gamma = -gamma; - } - p = gamma-dp+theta; - q = gamma-dp+gamma+(*dx); - r = p/q; - stpc = *stp+r*(*stx-(*stp)); - stpq = *stp+dp/(dp-(*dx))*(*stx-(*stp)); - if( ae_fp_greater(ae_fabs(stpc-(*stp), _state),ae_fabs(stpq-(*stp), _state)) ) - { - stpf = stpc; - } - else - { - stpf = stpq; - } - *brackt = ae_true; - } - else - { - if( ae_fp_less(ae_fabs(dp, _state),ae_fabs(*dx, _state)) ) - { - - /* - * THIRD CASE. A LOWER FUNCTION VALUE, DERIVATIVES OF THE - * SAME SIGN, AND THE MAGNITUDE OF THE DERIVATIVE DECREASES. - * THE CUBIC STEP IS ONLY USED IF THE CUBIC TENDS TO INFINITY - * IN THE DIRECTION OF THE STEP OR IF THE MINIMUM OF THE CUBIC - * IS BEYOND STP. OTHERWISE THE CUBIC STEP IS DEFINED TO BE - * EITHER STPMIN OR STPMAX. THE QUADRATIC (SECANT) STEP IS ALSO - * COMPUTED AND IF THE MINIMUM IS BRACKETED THEN THE THE STEP - * CLOSEST TO STX IS TAKEN, ELSE THE STEP FARTHEST AWAY IS TAKEN. - */ - *info = 3; - bound = ae_true; - theta = 3*(*fx-fp)/(*stp-(*stx))+(*dx)+dp; - s = ae_maxreal(ae_fabs(theta, _state), ae_maxreal(ae_fabs(*dx, _state), ae_fabs(dp, _state), _state), _state); - - /* - * THE CASE GAMMA = 0 ONLY ARISES IF THE CUBIC DOES NOT TEND - * TO INFINITY IN THE DIRECTION OF THE STEP. - */ - gamma = s*ae_sqrt(ae_maxreal((double)(0), ae_sqr(theta/s, _state)-*dx/s*(dp/s), _state), _state); - if( ae_fp_greater(*stp,*stx) ) - { - gamma = -gamma; - } - p = gamma-dp+theta; - q = gamma+(*dx-dp)+gamma; - r = p/q; - if( ae_fp_less(r,(double)(0))&&ae_fp_neq(gamma,(double)(0)) ) - { - stpc = *stp+r*(*stx-(*stp)); - } - else - { - if( ae_fp_greater(*stp,*stx) ) - { - stpc = stmax; - } - else - { - stpc = stmin; - } - } - stpq = *stp+dp/(dp-(*dx))*(*stx-(*stp)); - if( *brackt ) - { - if( ae_fp_less(ae_fabs(*stp-stpc, _state),ae_fabs(*stp-stpq, _state)) ) - { - stpf = stpc; - } - else - { - stpf = stpq; - } - } - else - { - if( ae_fp_greater(ae_fabs(*stp-stpc, _state),ae_fabs(*stp-stpq, _state)) ) - { - stpf = stpc; - } - else - { - stpf = stpq; - } - } - } - else - { - - /* - * FOURTH CASE. A LOWER FUNCTION VALUE, DERIVATIVES OF THE - * SAME SIGN, AND THE MAGNITUDE OF THE DERIVATIVE DOES - * NOT DECREASE. IF THE MINIMUM IS NOT BRACKETED, THE STEP - * IS EITHER STPMIN OR STPMAX, ELSE THE CUBIC STEP IS TAKEN. - */ - *info = 4; - bound = ae_false; - if( *brackt ) - { - theta = 3*(fp-(*fy))/(*sty-(*stp))+(*dy)+dp; - s = ae_maxreal(ae_fabs(theta, _state), ae_maxreal(ae_fabs(*dy, _state), ae_fabs(dp, _state), _state), _state); - gamma = s*ae_sqrt(ae_sqr(theta/s, _state)-*dy/s*(dp/s), _state); - if( ae_fp_greater(*stp,*sty) ) - { - gamma = -gamma; - } - p = gamma-dp+theta; - q = gamma-dp+gamma+(*dy); - r = p/q; - stpc = *stp+r*(*sty-(*stp)); - stpf = stpc; - } - else - { - if( ae_fp_greater(*stp,*stx) ) - { - stpf = stmax; - } - else - { - stpf = stmin; - } - } - } - } - } - - /* - * UPDATE THE INTERVAL OF UNCERTAINTY. THIS UPDATE DOES NOT - * DEPEND ON THE NEW STEP OR THE CASE ANALYSIS ABOVE. - */ - if( ae_fp_greater(fp,*fx) ) - { - *sty = *stp; - *fy = fp; - *dy = dp; - } - else - { - if( ae_fp_less(sgnd,0.0) ) - { - *sty = *stx; - *fy = *fx; - *dy = *dx; - } - *stx = *stp; - *fx = fp; - *dx = dp; - } - - /* - * COMPUTE THE NEW STEP AND SAFEGUARD IT. - */ - stpf = ae_minreal(stmax, stpf, _state); - stpf = ae_maxreal(stmin, stpf, _state); - *stp = stpf; - if( *brackt&&bound ) - { - if( ae_fp_greater(*sty,*stx) ) - { - *stp = ae_minreal(*stx+0.66*(*sty-(*stx)), *stp, _state); - } - else - { - *stp = ae_maxreal(*stx+0.66*(*sty-(*stx)), *stp, _state); - } - } -} - - -void _linminstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - linminstate *p = (linminstate*)_p; - ae_touch_ptr((void*)p); -} - - -void _linminstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - linminstate *dst = (linminstate*)_dst; - linminstate *src = (linminstate*)_src; - dst->brackt = src->brackt; - dst->stage1 = src->stage1; - dst->infoc = src->infoc; - dst->dg = src->dg; - dst->dgm = src->dgm; - dst->dginit = src->dginit; - dst->dgtest = src->dgtest; - dst->dgx = src->dgx; - dst->dgxm = src->dgxm; - dst->dgy = src->dgy; - dst->dgym = src->dgym; - dst->finit = src->finit; - dst->ftest1 = src->ftest1; - dst->fm = src->fm; - dst->fx = src->fx; - dst->fxm = src->fxm; - dst->fy = src->fy; - dst->fym = src->fym; - dst->stx = src->stx; - dst->sty = src->sty; - dst->stmin = src->stmin; - dst->stmax = src->stmax; - dst->width = src->width; - dst->width1 = src->width1; - dst->xtrapf = src->xtrapf; -} - - -void _linminstate_clear(void* _p) -{ - linminstate *p = (linminstate*)_p; - ae_touch_ptr((void*)p); -} - - -void _linminstate_destroy(void* _p) -{ - linminstate *p = (linminstate*)_p; - ae_touch_ptr((void*)p); -} - - -void _armijostate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - armijostate *p = (armijostate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xbase, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); -} - - -void _armijostate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - armijostate *dst = (armijostate*)_dst; - armijostate *src = (armijostate*)_src; - dst->needf = src->needf; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - dst->f = src->f; - dst->n = src->n; - ae_vector_init_copy(&dst->xbase, &src->xbase, _state, make_automatic); - ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic); - dst->stplen = src->stplen; - dst->fcur = src->fcur; - dst->stpmax = src->stpmax; - dst->fmax = src->fmax; - dst->nfev = src->nfev; - dst->info = src->info; - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); -} - - -void _armijostate_clear(void* _p) -{ - armijostate *p = (armijostate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->x); - ae_vector_clear(&p->xbase); - ae_vector_clear(&p->s); - _rcommstate_clear(&p->rstate); -} - - -void _armijostate_destroy(void* _p) -{ - armijostate *p = (armijostate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->xbase); - ae_vector_destroy(&p->s); - _rcommstate_destroy(&p->rstate); -} - - -#endif -#if defined(AE_COMPILE_XBLAS) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -More precise dot-product. Absolute error of subroutine result is about -1 ulp of max(MX,V), where: - MX = max( |a[i]*b[i]| ) - V = |(a,b)| - -INPUT PARAMETERS - A - array[0..N-1], vector 1 - B - array[0..N-1], vector 2 - N - vectors length, N<2^29. - Temp - array[0..N-1], pre-allocated temporary storage - -OUTPUT PARAMETERS - R - (A,B) - RErr - estimate of error. This estimate accounts for both errors - during calculation of (A,B) and errors introduced by - rounding of A and B to fit in double (about 1 ulp). - - -- ALGLIB -- - Copyright 24.08.2009 by Bochkanov Sergey -*************************************************************************/ -void xdot(/* Real */ ae_vector* a, - /* Real */ ae_vector* b, - ae_int_t n, - /* Real */ ae_vector* temp, - double* r, - double* rerr, - ae_state *_state) -{ - ae_int_t i; - double mx; - double v; - - *r = 0; - *rerr = 0; - - - /* - * special cases: - * * N=0 - */ - if( n==0 ) - { - *r = (double)(0); - *rerr = (double)(0); - return; - } - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - v = a->ptr.p_double[i]*b->ptr.p_double[i]; - temp->ptr.p_double[i] = v; - mx = ae_maxreal(mx, ae_fabs(v, _state), _state); - } - if( ae_fp_eq(mx,(double)(0)) ) - { - *r = (double)(0); - *rerr = (double)(0); - return; - } - xblas_xsum(temp, mx, n, r, rerr, _state); -} - - -/************************************************************************* -More precise complex dot-product. Absolute error of subroutine result is -about 1 ulp of max(MX,V), where: - MX = max( |a[i]*b[i]| ) - V = |(a,b)| - -INPUT PARAMETERS - A - array[0..N-1], vector 1 - B - array[0..N-1], vector 2 - N - vectors length, N<2^29. - Temp - array[0..2*N-1], pre-allocated temporary storage - -OUTPUT PARAMETERS - R - (A,B) - RErr - estimate of error. This estimate accounts for both errors - during calculation of (A,B) and errors introduced by - rounding of A and B to fit in double (about 1 ulp). - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void xcdot(/* Complex */ ae_vector* a, - /* Complex */ ae_vector* b, - ae_int_t n, - /* Real */ ae_vector* temp, - ae_complex* r, - double* rerr, - ae_state *_state) -{ - ae_int_t i; - double mx; - double v; - double rerrx; - double rerry; - - r->x = 0; - r->y = 0; - *rerr = 0; - - - /* - * special cases: - * * N=0 - */ - if( n==0 ) - { - *r = ae_complex_from_i(0); - *rerr = (double)(0); - return; - } - - /* - * calculate real part - */ - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - v = a->ptr.p_complex[i].x*b->ptr.p_complex[i].x; - temp->ptr.p_double[2*i+0] = v; - mx = ae_maxreal(mx, ae_fabs(v, _state), _state); - v = -a->ptr.p_complex[i].y*b->ptr.p_complex[i].y; - temp->ptr.p_double[2*i+1] = v; - mx = ae_maxreal(mx, ae_fabs(v, _state), _state); - } - if( ae_fp_eq(mx,(double)(0)) ) - { - r->x = (double)(0); - rerrx = (double)(0); - } - else - { - xblas_xsum(temp, mx, 2*n, &r->x, &rerrx, _state); - } - - /* - * calculate imaginary part - */ - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - v = a->ptr.p_complex[i].x*b->ptr.p_complex[i].y; - temp->ptr.p_double[2*i+0] = v; - mx = ae_maxreal(mx, ae_fabs(v, _state), _state); - v = a->ptr.p_complex[i].y*b->ptr.p_complex[i].x; - temp->ptr.p_double[2*i+1] = v; - mx = ae_maxreal(mx, ae_fabs(v, _state), _state); - } - if( ae_fp_eq(mx,(double)(0)) ) - { - r->y = (double)(0); - rerry = (double)(0); - } - else - { - xblas_xsum(temp, mx, 2*n, &r->y, &rerry, _state); - } - - /* - * total error - */ - if( ae_fp_eq(rerrx,(double)(0))&&ae_fp_eq(rerry,(double)(0)) ) - { - *rerr = (double)(0); - } - else - { - *rerr = ae_maxreal(rerrx, rerry, _state)*ae_sqrt(1+ae_sqr(ae_minreal(rerrx, rerry, _state)/ae_maxreal(rerrx, rerry, _state), _state), _state); - } -} - - -/************************************************************************* -Internal subroutine for extra-precise calculation of SUM(w[i]). - -INPUT PARAMETERS: - W - array[0..N-1], values to be added - W is modified during calculations. - MX - max(W[i]) - N - array size - -OUTPUT PARAMETERS: - R - SUM(w[i]) - RErr- error estimate for R - - -- ALGLIB -- - Copyright 24.08.2009 by Bochkanov Sergey -*************************************************************************/ -static void xblas_xsum(/* Real */ ae_vector* w, - double mx, - ae_int_t n, - double* r, - double* rerr, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - ae_int_t ks; - double v; - double s; - double ln2; - double chunk; - double invchunk; - ae_bool allzeros; - - *r = 0; - *rerr = 0; - - - /* - * special cases: - * * N=0 - * * N is too large to use integer arithmetics - */ - if( n==0 ) - { - *r = (double)(0); - *rerr = (double)(0); - return; - } - if( ae_fp_eq(mx,(double)(0)) ) - { - *r = (double)(0); - *rerr = (double)(0); - return; - } - ae_assert(n<536870912, "XDot: N is too large!", _state); - - /* - * Prepare - */ - ln2 = ae_log((double)(2), _state); - *rerr = mx*ae_machineepsilon; - - /* - * 1. find S such that 0.5<=S*MX<1 - * 2. multiply W by S, so task is normalized in some sense - * 3. S:=1/S so we can obtain original vector multiplying by S - */ - k = ae_round(ae_log(mx, _state)/ln2, _state); - s = xblas_xfastpow((double)(2), -k, _state); - if( !ae_isfinite(s, _state) ) - { - - /* - * Overflow or underflow during evaluation of S; fallback low-precision code - */ - *r = (double)(0); - *rerr = mx*ae_machineepsilon; - for(i=0; i<=n-1; i++) - { - *r = *r+w->ptr.p_double[i]; - } - return; - } - while(ae_fp_greater_eq(s*mx,(double)(1))) - { - s = 0.5*s; - } - while(ae_fp_less(s*mx,0.5)) - { - s = 2*s; - } - ae_v_muld(&w->ptr.p_double[0], 1, ae_v_len(0,n-1), s); - s = 1/s; - - /* - * find Chunk=2^M such that N*Chunk<2^29 - * - * we have chosen upper limit (2^29) with enough space left - * to tolerate possible problems with rounding and N's close - * to the limit, so we don't want to be very strict here. - */ - k = ae_trunc(ae_log((double)536870912/(double)n, _state)/ln2, _state); - chunk = xblas_xfastpow((double)(2), k, _state); - if( ae_fp_less(chunk,(double)(2)) ) - { - chunk = (double)(2); - } - invchunk = 1/chunk; - - /* - * calculate result - */ - *r = (double)(0); - ae_v_muld(&w->ptr.p_double[0], 1, ae_v_len(0,n-1), chunk); - for(;;) - { - s = s*invchunk; - allzeros = ae_true; - ks = 0; - for(i=0; i<=n-1; i++) - { - v = w->ptr.p_double[i]; - k = ae_trunc(v, _state); - if( ae_fp_neq(v,(double)(k)) ) - { - allzeros = ae_false; - } - w->ptr.p_double[i] = chunk*(v-k); - ks = ks+k; - } - *r = *r+s*ks; - v = ae_fabs(*r, _state); - if( allzeros||ae_fp_eq(s*n+mx,mx) ) - { - break; - } - } - - /* - * correct error - */ - *rerr = ae_maxreal(*rerr, ae_fabs(*r, _state)*ae_machineepsilon, _state); -} - - -/************************************************************************* -Fast Pow - - -- ALGLIB -- - Copyright 24.08.2009 by Bochkanov Sergey -*************************************************************************/ -static double xblas_xfastpow(double r, ae_int_t n, ae_state *_state) -{ - double result; - - - result = (double)(0); - if( n>0 ) - { - if( n%2==0 ) - { - result = ae_sqr(xblas_xfastpow(r, n/2, _state), _state); - } - else - { - result = r*xblas_xfastpow(r, n-1, _state); - } - return result; - } - if( n==0 ) - { - result = (double)(1); - } - if( n<0 ) - { - result = xblas_xfastpow(1/r, -n, _state); - } - return result; -} - - -#endif -#if defined(AE_COMPILE_BASICSTATOPS) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Internal tied ranking subroutine. - -INPUT PARAMETERS: - X - array to rank - N - array size - IsCentered- whether ranks are centered or not: - * True - ranks are centered in such way that their - sum is zero - * False - ranks are not centered - Buf - temporary buffers - -NOTE: when IsCentered is True and all X[] are equal, this function fills - X by zeros (exact zeros are used, not sum which is only approximately - equal to zero). -*************************************************************************/ -void rankx(/* Real */ ae_vector* x, - ae_int_t n, - ae_bool iscentered, - apbuffers* buf, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double tmp; - double voffs; - - - - /* - * Prepare - */ - if( n<1 ) - { - return; - } - if( n==1 ) - { - x->ptr.p_double[0] = (double)(0); - return; - } - if( buf->ra1.cntra1, n, _state); - } - if( buf->ia1.cntia1, n, _state); - } - for(i=0; i<=n-1; i++) - { - buf->ra1.ptr.p_double[i] = x->ptr.p_double[i]; - buf->ia1.ptr.p_int[i] = i; - } - tagsortfasti(&buf->ra1, &buf->ia1, &buf->ra2, &buf->ia2, n, _state); - - /* - * Special test for all values being equal - */ - if( ae_fp_eq(buf->ra1.ptr.p_double[0],buf->ra1.ptr.p_double[n-1]) ) - { - if( iscentered ) - { - tmp = 0.0; - } - else - { - tmp = (double)(n-1)/(double)2; - } - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = tmp; - } - return; - } - - /* - * compute tied ranks - */ - i = 0; - while(i<=n-1) - { - j = i+1; - while(j<=n-1) - { - if( ae_fp_neq(buf->ra1.ptr.p_double[j],buf->ra1.ptr.p_double[i]) ) - { - break; - } - j = j+1; - } - for(k=i; k<=j-1; k++) - { - buf->ra1.ptr.p_double[k] = (double)(i+j-1)/(double)2; - } - i = j; - } - - /* - * back to x - */ - if( iscentered ) - { - voffs = (double)(n-1)/(double)2; - } - else - { - voffs = 0.0; - } - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[buf->ia1.ptr.p_int[i]] = buf->ra1.ptr.p_double[i]-voffs; - } -} - - -/************************************************************************* -Internal untied ranking subroutine. - -INPUT PARAMETERS: - X - array to rank - N - array size - Buf - temporary buffers - -Returns untied ranks (in case of a tie ranks are resolved arbitrarily). -*************************************************************************/ -void rankxuntied(/* Real */ ae_vector* x, - ae_int_t n, - apbuffers* buf, - ae_state *_state) -{ - ae_int_t i; - - - - /* - * Prepare - */ - if( n<1 ) - { - return; - } - if( n==1 ) - { - x->ptr.p_double[0] = (double)(0); - return; - } - if( buf->ra1.cntra1, n, _state); - } - if( buf->ia1.cntia1, n, _state); - } - for(i=0; i<=n-1; i++) - { - buf->ra1.ptr.p_double[i] = x->ptr.p_double[i]; - buf->ia1.ptr.p_int[i] = i; - } - tagsortfasti(&buf->ra1, &buf->ia1, &buf->ra2, &buf->ia2, n, _state); - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[buf->ia1.ptr.p_int[i]] = (double)(i); - } -} - - -#endif -#if defined(AE_COMPILE_HPCCORES) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Prepares HPC compuations of chunked gradient with HPCChunkedGradient(). -You have to call this function before calling HPCChunkedGradient() for -a new set of weights. You have to call it only once, see example below: - -HOW TO PROCESS DATASET WITH THIS FUNCTION: - Grad:=0 - HPCPrepareChunkedGradient(Weights, WCount, NTotal, NOut, Buf) - foreach chunk-of-dataset do - HPCChunkedGradient(...) - HPCFinalizeChunkedGradient(Buf, Grad) - -*************************************************************************/ -void hpcpreparechunkedgradient(/* Real */ ae_vector* weights, - ae_int_t wcount, - ae_int_t ntotal, - ae_int_t nin, - ae_int_t nout, - mlpbuffers* buf, - ae_state *_state) -{ - ae_int_t i; - ae_int_t batch4size; - ae_int_t chunksize; - - - chunksize = 4; - batch4size = 3*chunksize*ntotal+chunksize*(2*nout+1); - if( buf->xy.rowsxy.colsxy, chunksize, nin+nout, _state); - } - if( buf->xy2.rowsxy2.colsxy2, chunksize, nin+nout, _state); - } - if( buf->xyrow.cntxyrow, nin+nout, _state); - } - if( buf->x.cntx, nin, _state); - } - if( buf->y.cnty, nout, _state); - } - if( buf->desiredy.cntdesiredy, nout, _state); - } - if( buf->batch4buf.cntbatch4buf, batch4size, _state); - } - if( buf->hpcbuf.cnthpcbuf, wcount, _state); - } - if( buf->g.cntg, wcount, _state); - } - if( !hpccores_hpcpreparechunkedgradientx(weights, wcount, &buf->hpcbuf, _state) ) - { - for(i=0; i<=wcount-1; i++) - { - buf->hpcbuf.ptr.p_double[i] = 0.0; - } - } - buf->wcount = wcount; - buf->ntotal = ntotal; - buf->nin = nin; - buf->nout = nout; - buf->chunksize = chunksize; -} - - -/************************************************************************* -Finalizes HPC compuations of chunked gradient with HPCChunkedGradient(). -You have to call this function after calling HPCChunkedGradient() for -a new set of weights. You have to call it only once, see example below: - -HOW TO PROCESS DATASET WITH THIS FUNCTION: - Grad:=0 - HPCPrepareChunkedGradient(Weights, WCount, NTotal, NOut, Buf) - foreach chunk-of-dataset do - HPCChunkedGradient(...) - HPCFinalizeChunkedGradient(Buf, Grad) - -*************************************************************************/ -void hpcfinalizechunkedgradient(mlpbuffers* buf, - /* Real */ ae_vector* grad, - ae_state *_state) -{ - ae_int_t i; - - - if( !hpccores_hpcfinalizechunkedgradientx(&buf->hpcbuf, buf->wcount, grad, _state) ) - { - for(i=0; i<=buf->wcount-1; i++) - { - grad->ptr.p_double[i] = grad->ptr.p_double[i]+buf->hpcbuf.ptr.p_double[i]; - } - } -} - - -/************************************************************************* -Fast kernel for chunked gradient. - -*************************************************************************/ -ae_bool hpcchunkedgradient(/* Real */ ae_vector* weights, - /* Integer */ ae_vector* structinfo, - /* Real */ ae_vector* columnmeans, - /* Real */ ae_vector* columnsigmas, - /* Real */ ae_matrix* xy, - ae_int_t cstart, - ae_int_t csize, - /* Real */ ae_vector* batch4buf, - /* Real */ ae_vector* hpcbuf, - double* e, - ae_bool naturalerrorfunc, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_SSE2 - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_hpcchunkedgradient(weights, structinfo, columnmeans, columnsigmas, xy, cstart, csize, batch4buf, hpcbuf, e, naturalerrorfunc); -#endif -} - - -/************************************************************************* -Fast kernel for chunked processing. - -*************************************************************************/ -ae_bool hpcchunkedprocess(/* Real */ ae_vector* weights, - /* Integer */ ae_vector* structinfo, - /* Real */ ae_vector* columnmeans, - /* Real */ ae_vector* columnsigmas, - /* Real */ ae_matrix* xy, - ae_int_t cstart, - ae_int_t csize, - /* Real */ ae_vector* batch4buf, - /* Real */ ae_vector* hpcbuf, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_SSE2 - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_hpcchunkedprocess(weights, structinfo, columnmeans, columnsigmas, xy, cstart, csize, batch4buf, hpcbuf); -#endif -} - - -/************************************************************************* -Stub function. - - -- ALGLIB routine -- - 14.06.2013 - Bochkanov Sergey -*************************************************************************/ -static ae_bool hpccores_hpcpreparechunkedgradientx(/* Real */ ae_vector* weights, - ae_int_t wcount, - /* Real */ ae_vector* hpcbuf, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_SSE2 - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_hpcpreparechunkedgradientx(weights, wcount, hpcbuf); -#endif -} - - -/************************************************************************* -Stub function. - - -- ALGLIB routine -- - 14.06.2013 - Bochkanov Sergey -*************************************************************************/ -static ae_bool hpccores_hpcfinalizechunkedgradientx(/* Real */ ae_vector* buf, - ae_int_t wcount, - /* Real */ ae_vector* grad, - ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_SSE2 - ae_bool result; - - - result = ae_false; - return result; -#else - return _ialglib_i_hpcfinalizechunkedgradientx(buf, wcount, grad); -#endif -} - - -void _mlpbuffers_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - mlpbuffers *p = (mlpbuffers*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->batch4buf, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->hpcbuf, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->xy, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->xy2, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xyrow, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->desiredy, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); -} - - -void _mlpbuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - mlpbuffers *dst = (mlpbuffers*)_dst; - mlpbuffers *src = (mlpbuffers*)_src; - dst->chunksize = src->chunksize; - dst->ntotal = src->ntotal; - dst->nin = src->nin; - dst->nout = src->nout; - dst->wcount = src->wcount; - ae_vector_init_copy(&dst->batch4buf, &src->batch4buf, _state, make_automatic); - ae_vector_init_copy(&dst->hpcbuf, &src->hpcbuf, _state, make_automatic); - ae_matrix_init_copy(&dst->xy, &src->xy, _state, make_automatic); - ae_matrix_init_copy(&dst->xy2, &src->xy2, _state, make_automatic); - ae_vector_init_copy(&dst->xyrow, &src->xyrow, _state, make_automatic); - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic); - ae_vector_init_copy(&dst->desiredy, &src->desiredy, _state, make_automatic); - dst->e = src->e; - ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); -} - - -void _mlpbuffers_clear(void* _p) -{ - mlpbuffers *p = (mlpbuffers*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->batch4buf); - ae_vector_clear(&p->hpcbuf); - ae_matrix_clear(&p->xy); - ae_matrix_clear(&p->xy2); - ae_vector_clear(&p->xyrow); - ae_vector_clear(&p->x); - ae_vector_clear(&p->y); - ae_vector_clear(&p->desiredy); - ae_vector_clear(&p->g); - ae_vector_clear(&p->tmp0); -} - - -void _mlpbuffers_destroy(void* _p) -{ - mlpbuffers *p = (mlpbuffers*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->batch4buf); - ae_vector_destroy(&p->hpcbuf); - ae_matrix_destroy(&p->xy); - ae_matrix_destroy(&p->xy2); - ae_vector_destroy(&p->xyrow); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->y); - ae_vector_destroy(&p->desiredy); - ae_vector_destroy(&p->g); - ae_vector_destroy(&p->tmp0); -} - - -#endif -#if defined(AE_COMPILE_NTHEORY) || !defined(AE_PARTIAL_BUILD) - - -void findprimitiverootandinverse(ae_int_t n, - ae_int_t* proot, - ae_int_t* invproot, - ae_state *_state) -{ - ae_int_t candroot; - ae_int_t phin; - ae_int_t q; - ae_int_t f; - ae_bool allnonone; - ae_int_t x; - ae_int_t lastx; - ae_int_t y; - ae_int_t lasty; - ae_int_t a; - ae_int_t b; - ae_int_t t; - ae_int_t n2; - - *proot = 0; - *invproot = 0; - - ae_assert(n>=3, "FindPrimitiveRootAndInverse: N<3", _state); - *proot = 0; - *invproot = 0; - - /* - * check that N is prime - */ - ae_assert(ntheory_isprime(n, _state), "FindPrimitiveRoot: N is not prime", _state); - - /* - * Because N is prime, Euler totient function is equal to N-1 - */ - phin = n-1; - - /* - * Test different values of PRoot - from 2 to N-1. - * One of these values MUST be primitive root. - * - * For testing we use algorithm from Wiki (Primitive root modulo n): - * * compute phi(N) - * * determine the different prime factors of phi(N), say p1, ..., pk - * * for every element m of Zn*, compute m^(phi(N)/pi) mod N for i=1..k - * using a fast algorithm for modular exponentiation. - * * a number m for which these k results are all different from 1 is a - * primitive root. - */ - for(candroot=2; candroot<=n-1; candroot++) - { - - /* - * We have current candidate root in CandRoot. - * - * Scan different prime factors of PhiN. Here: - * * F is a current candidate factor - * * Q is a current quotient - amount which was left after dividing PhiN - * by all previous factors - * - * For each factor, perform test mentioned above. - */ - q = phin; - f = 2; - allnonone = ae_true; - while(q>1) - { - if( q%f==0 ) - { - t = ntheory_modexp(candroot, phin/f, n, _state); - if( t==1 ) - { - allnonone = ae_false; - break; - } - while(q%f==0) - { - q = q/f; - } - } - f = f+1; - } - if( allnonone ) - { - *proot = candroot; - break; - } - } - ae_assert(*proot>=2, "FindPrimitiveRoot: internal error (root not found)", _state); - - /* - * Use extended Euclidean algorithm to find multiplicative inverse of primitive root - */ - x = 0; - lastx = 1; - y = 1; - lasty = 0; - a = *proot; - b = n; - while(b!=0) - { - q = a/b; - t = a%b; - a = b; - b = t; - t = lastx-q*x; - lastx = x; - x = t; - t = lasty-q*y; - lasty = y; - y = t; - } - while(lastx<0) - { - lastx = lastx+n; - } - *invproot = lastx; - - /* - * Check that it is safe to perform multiplication modulo N. - * Check results for consistency. - */ - n2 = (n-1)*(n-1); - ae_assert(n2/(n-1)==n-1, "FindPrimitiveRoot: internal error", _state); - ae_assert(*proot*(*invproot)/(*proot)==(*invproot), "FindPrimitiveRoot: internal error", _state); - ae_assert(*proot*(*invproot)/(*invproot)==(*proot), "FindPrimitiveRoot: internal error", _state); - ae_assert(*proot*(*invproot)%n==1, "FindPrimitiveRoot: internal error", _state); -} - - -static ae_bool ntheory_isprime(ae_int_t n, ae_state *_state) -{ - ae_int_t p; - ae_bool result; - - - result = ae_false; - p = 2; - while(p*p<=n) - { - if( n%p==0 ) - { - return result; - } - p = p+1; - } - result = ae_true; - return result; -} - - -static ae_int_t ntheory_modmul(ae_int_t a, - ae_int_t b, - ae_int_t n, - ae_state *_state) -{ - ae_int_t t; - double ra; - double rb; - ae_int_t result; - - - ae_assert(a>=0&&a=N", _state); - ae_assert(b>=0&&b=N", _state); - - /* - * Base cases - */ - ra = (double)(a); - rb = (double)(b); - if( b==0||a==0 ) - { - result = 0; - return result; - } - if( b==1||a==1 ) - { - result = a*b; - return result; - } - if( ae_fp_eq(ra*rb,(double)(a*b)) ) - { - result = a*b%n; - return result; - } - - /* - * Non-base cases - */ - if( b%2==0 ) - { - - /* - * A*B = (A*(B/2)) * 2 - * - * Product T=A*(B/2) is calculated recursively, product T*2 is - * calculated as follows: - * * result:=T-N - * * result:=result+T - * * if result<0 then result:=result+N - * - * In case integer result overflows, we generate exception - */ - t = ntheory_modmul(a, b/2, n, _state); - result = t-n; - result = result+t; - if( result<0 ) - { - result = result+n; - } - } - else - { - - /* - * A*B = (A*(B div 2)) * 2 + A - * - * Product T=A*(B/2) is calculated recursively, product T*2 is - * calculated as follows: - * * result:=T-N - * * result:=result+T - * * if result<0 then result:=result+N - * - * In case integer result overflows, we generate exception - */ - t = ntheory_modmul(a, b/2, n, _state); - result = t-n; - result = result+t; - if( result<0 ) - { - result = result+n; - } - result = result-n; - result = result+a; - if( result<0 ) - { - result = result+n; - } - } - return result; -} - - -static ae_int_t ntheory_modexp(ae_int_t a, - ae_int_t b, - ae_int_t n, - ae_state *_state) -{ - ae_int_t t; - ae_int_t result; - - - ae_assert(a>=0&&a=N", _state); - ae_assert(b>=0, "ModExp: B<0", _state); - - /* - * Base cases - */ - if( b==0 ) - { - result = 1; - return result; - } - if( b==1 ) - { - result = a; - return result; - } - - /* - * Non-base cases - */ - if( b%2==0 ) - { - t = ntheory_modmul(a, a, n, _state); - result = ntheory_modexp(t, b/2, n, _state); - } - else - { - t = ntheory_modmul(a, a, n, _state); - result = ntheory_modexp(t, b/2, n, _state); - result = ntheory_modmul(result, a, n, _state); - } - return result; -} - - -#endif -#if defined(AE_COMPILE_FTBASE) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This subroutine generates FFT plan for K complex FFT's with length N each. - -INPUT PARAMETERS: - N - FFT length (in complex numbers), N>=1 - K - number of repetitions, K>=1 - -OUTPUT PARAMETERS: - Plan - plan - - -- ALGLIB -- - Copyright 05.04.2013 by Bochkanov Sergey -*************************************************************************/ -void ftcomplexfftplan(ae_int_t n, - ae_int_t k, - fasttransformplan* plan, - ae_state *_state) -{ - ae_frame _frame_block; - srealarray bluesteinbuf; - ae_int_t rowptr; - ae_int_t bluesteinsize; - ae_int_t precrptr; - ae_int_t preciptr; - ae_int_t precrsize; - ae_int_t precisize; - - ae_frame_make(_state, &_frame_block); - memset(&bluesteinbuf, 0, sizeof(bluesteinbuf)); - _fasttransformplan_clear(plan); - _srealarray_init(&bluesteinbuf, _state, ae_true); - - - /* - * Initial check for parameters - */ - ae_assert(n>0, "FTComplexFFTPlan: N<=0", _state); - ae_assert(k>0, "FTComplexFFTPlan: K<=0", _state); - - /* - * Determine required sizes of precomputed real and integer - * buffers. This stage of code is highly dependent on internals - * of FTComplexFFTPlanRec() and must be kept synchronized with - * possible changes in internals of plan generation function. - * - * Buffer size is determined as follows: - * * N is factorized - * * we factor out anything which is less or equal to MaxRadix - * * prime factor F>RaderThreshold requires 4*FTBaseFindSmooth(2*F-1) - * real entries to store precomputed Quantities for Bluestein's - * transformation - * * prime factor F<=RaderThreshold does NOT require - * precomputed storage - */ - precrsize = 0; - precisize = 0; - ftbase_ftdeterminespacerequirements(n, &precrsize, &precisize, _state); - if( precrsize>0 ) - { - ae_vector_set_length(&plan->precr, precrsize, _state); - } - if( precisize>0 ) - { - ae_vector_set_length(&plan->preci, precisize, _state); - } - - /* - * Generate plan - */ - rowptr = 0; - precrptr = 0; - preciptr = 0; - bluesteinsize = 1; - ae_vector_set_length(&plan->buffer, 2*n*k, _state); - ftbase_ftcomplexfftplanrec(n, k, ae_true, ae_true, &rowptr, &bluesteinsize, &precrptr, &preciptr, plan, _state); - ae_vector_set_length(&bluesteinbuf.val, bluesteinsize, _state); - ae_shared_pool_set_seed(&plan->bluesteinpool, &bluesteinbuf, sizeof(bluesteinbuf), _srealarray_init, _srealarray_init_copy, _srealarray_destroy, _state); - - /* - * Check that actual amount of precomputed space used by transformation - * plan is EXACTLY equal to amount of space allocated by us. - */ - ae_assert(precrptr==precrsize, "FTComplexFFTPlan: internal error (PrecRPtr<>PrecRSize)", _state); - ae_assert(preciptr==precisize, "FTComplexFFTPlan: internal error (PrecRPtr<>PrecRSize)", _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This subroutine applies transformation plan to input/output array A. - -INPUT PARAMETERS: - Plan - transformation plan - A - array, must be large enough for plan to work - OffsA - offset of the subarray to process - RepCnt - repetition count (transformation is repeatedly applied - to subsequent subarrays) - -OUTPUT PARAMETERS: - Plan - plan (temporary buffers can be modified, plan itself - is unchanged and can be reused) - A - transformed array - - -- ALGLIB -- - Copyright 05.04.2013 by Bochkanov Sergey -*************************************************************************/ -void ftapplyplan(fasttransformplan* plan, - /* Real */ ae_vector* a, - ae_int_t offsa, - ae_int_t repcnt, - ae_state *_state) -{ - ae_int_t plansize; - ae_int_t i; - - - plansize = plan->entries.ptr.pp_int[0][ftbase_coloperandscnt]*plan->entries.ptr.pp_int[0][ftbase_coloperandsize]*plan->entries.ptr.pp_int[0][ftbase_colmicrovectorsize]; - for(i=0; i<=repcnt-1; i++) - { - ftbase_ftapplysubplan(plan, 0, a, offsa+plansize*i, 0, &plan->buffer, 1, _state); - } -} - - -/************************************************************************* -Returns good factorization N=N1*N2. - -Usually N1<=N2 (but not always - small N's may be exception). -if N1<>1 then N2<>1. - -Factorization is chosen depending on task type and codelets we have. - - -- ALGLIB -- - Copyright 01.05.2009 by Bochkanov Sergey -*************************************************************************/ -void ftbasefactorize(ae_int_t n, - ae_int_t tasktype, - ae_int_t* n1, - ae_int_t* n2, - ae_state *_state) -{ - ae_int_t j; - - *n1 = 0; - *n2 = 0; - - *n1 = 0; - *n2 = 0; - - /* - * try to find good codelet - */ - if( *n1*(*n2)!=n ) - { - for(j=ftbase_ftbasecodeletrecommended; j>=2; j--) - { - if( n%j==0 ) - { - *n1 = j; - *n2 = n/j; - break; - } - } - } - - /* - * try to factorize N - */ - if( *n1*(*n2)!=n ) - { - for(j=ftbase_ftbasecodeletrecommended+1; j<=n-1; j++) - { - if( n%j==0 ) - { - *n1 = j; - *n2 = n/j; - break; - } - } - } - - /* - * looks like N is prime :( - */ - if( *n1*(*n2)!=n ) - { - *n1 = 1; - *n2 = n; - } - - /* - * normalize - */ - if( *n2==1&&*n1!=1 ) - { - *n2 = *n1; - *n1 = 1; - } -} - - -/************************************************************************* -Is number smooth? - - -- ALGLIB -- - Copyright 01.05.2009 by Bochkanov Sergey -*************************************************************************/ -ae_bool ftbaseissmooth(ae_int_t n, ae_state *_state) -{ - ae_int_t i; - ae_bool result; - - - for(i=2; i<=ftbase_ftbasemaxsmoothfactor; i++) - { - while(n%i==0) - { - n = n/i; - } - } - result = n==1; - return result; -} - - -/************************************************************************* -Returns smallest smooth (divisible only by 2, 3, 5) number that is greater -than or equal to max(N,2) - - -- ALGLIB -- - Copyright 01.05.2009 by Bochkanov Sergey -*************************************************************************/ -ae_int_t ftbasefindsmooth(ae_int_t n, ae_state *_state) -{ - ae_int_t best; - ae_int_t result; - - - best = 2; - while(bestRaderThreshold requires 4*FTBaseFindSmooth(2*F-1) - * real entries to store precomputed Quantities for Bluestein's - * transformation - * * prime factor F<=RaderThreshold requires 2*(F-1)+ESTIMATE(F-1) - * precomputed storage - */ - ncur = n; - for(i=2; i<=ftbase_maxradix; i++) - { - while(ncur%i==0) - { - ncur = ncur/i; - } - } - f = 2; - while(f<=ncur) - { - while(ncur%f==0) - { - if( f>ftbase_raderthreshold ) - { - *precrsize = *precrsize+4*ftbasefindsmooth(2*f-1, _state); - } - else - { - *precrsize = *precrsize+2*(f-1); - ftbase_ftdeterminespacerequirements(f-1, precrsize, precisize, _state); - } - ncur = ncur/f; - } - f = f+1; - } -} - - -/************************************************************************* -Recurrent function called by FTComplexFFTPlan() and other functions. It -recursively builds transformation plan - -INPUT PARAMETERS: - N - FFT length (in complex numbers), N>=1 - K - number of repetitions, K>=1 - ChildPlan - if True, plan generator inserts OpStart/opEnd in the - plan header/footer. - TopmostPlan - if True, plan generator assumes that it is topmost plan: - * it may use global buffer for transpositions - and there is no other plan which executes in parallel - RowPtr - index which points to past-the-last entry generated so far - BluesteinSize- amount of storage (in real numbers) required for Bluestein buffer - PrecRPtr - pointer to unused part of precomputed real buffer (Plan.PrecR): - * when this function stores some data to precomputed buffer, - it advances pointer. - * it is responsibility of the function to assert that - Plan.PrecR has enough space to store data before actually - writing to buffer. - * it is responsibility of the caller to allocate enough - space before calling this function - PrecIPtr - pointer to unused part of precomputed integer buffer (Plan.PrecI): - * when this function stores some data to precomputed buffer, - it advances pointer. - * it is responsibility of the function to assert that - Plan.PrecR has enough space to store data before actually - writing to buffer. - * it is responsibility of the caller to allocate enough - space before calling this function - Plan - plan (generated so far) - -OUTPUT PARAMETERS: - RowPtr - updated pointer (advanced by number of entries generated - by function) - BluesteinSize- updated amount - (may be increased, but may never be decreased) - -NOTE: in case TopmostPlan is True, ChildPlan is also must be True. - - -- ALGLIB -- - Copyright 05.04.2013 by Bochkanov Sergey -*************************************************************************/ -static void ftbase_ftcomplexfftplanrec(ae_int_t n, - ae_int_t k, - ae_bool childplan, - ae_bool topmostplan, - ae_int_t* rowptr, - ae_int_t* bluesteinsize, - ae_int_t* precrptr, - ae_int_t* preciptr, - fasttransformplan* plan, - ae_state *_state) -{ - ae_frame _frame_block; - srealarray localbuf; - ae_int_t m; - ae_int_t n1; - ae_int_t n2; - ae_int_t gq; - ae_int_t giq; - ae_int_t row0; - ae_int_t row1; - ae_int_t row2; - ae_int_t row3; - - ae_frame_make(_state, &_frame_block); - memset(&localbuf, 0, sizeof(localbuf)); - _srealarray_init(&localbuf, _state, ae_true); - - ae_assert(n>0, "FTComplexFFTPlan: N<=0", _state); - ae_assert(k>0, "FTComplexFFTPlan: K<=0", _state); - ae_assert(!topmostplan||childplan, "FTComplexFFTPlan: ChildPlan is inconsistent with TopmostPlan", _state); - - /* - * Try to generate "topmost" plan - */ - if( topmostplan&&n>ftbase_recursivethreshold ) - { - ftbase_ftfactorize(n, ae_false, &n1, &n2, _state); - if( n1*n2==0 ) - { - - /* - * Handle prime-factor FFT with Bluestein's FFT. - * Determine size of Bluestein's buffer. - */ - m = ftbasefindsmooth(2*n-1, _state); - *bluesteinsize = ae_maxint(2*m, *bluesteinsize, _state); - - /* - * Generate plan - */ - ftbase_ftpushentry2(plan, rowptr, ftbase_opstart, k, n, 2, -1, ftbase_ftoptimisticestimate(n, _state), _state); - ftbase_ftpushentry4(plan, rowptr, ftbase_opbluesteinsfft, k, n, 2, m, 2, *precrptr, 0, _state); - row0 = *rowptr; - ftbase_ftpushentry(plan, rowptr, ftbase_opjmp, 0, 0, 0, 0, _state); - ftbase_ftcomplexfftplanrec(m, 1, ae_true, ae_true, rowptr, bluesteinsize, precrptr, preciptr, plan, _state); - row1 = *rowptr; - plan->entries.ptr.pp_int[row0][ftbase_colparam0] = row1-row0; - ftbase_ftpushentry(plan, rowptr, ftbase_opend, k, n, 2, 0, _state); - - /* - * Fill precomputed buffer - */ - ftbase_ftprecomputebluesteinsfft(n, m, &plan->precr, *precrptr, _state); - - /* - * Update pointer to the precomputed area - */ - *precrptr = *precrptr+4*m; - } - else - { - - /* - * Handle composite FFT with recursive Cooley-Tukey which - * uses global buffer instead of local one. - */ - ftbase_ftpushentry2(plan, rowptr, ftbase_opstart, k, n, 2, -1, ftbase_ftoptimisticestimate(n, _state), _state); - ftbase_ftpushentry(plan, rowptr, ftbase_opcomplextranspose, k, n, 2, n1, _state); - row0 = *rowptr; - ftbase_ftpushentry2(plan, rowptr, ftbase_opparallelcall, k*n2, n1, 2, 0, ftbase_ftoptimisticestimate(n, _state), _state); - ftbase_ftpushentry(plan, rowptr, ftbase_opcomplexfftfactors, k, n, 2, n1, _state); - ftbase_ftpushentry(plan, rowptr, ftbase_opcomplextranspose, k, n, 2, n2, _state); - row2 = *rowptr; - ftbase_ftpushentry2(plan, rowptr, ftbase_opparallelcall, k*n1, n2, 2, 0, ftbase_ftoptimisticestimate(n, _state), _state); - ftbase_ftpushentry(plan, rowptr, ftbase_opcomplextranspose, k, n, 2, n1, _state); - ftbase_ftpushentry(plan, rowptr, ftbase_opend, k, n, 2, 0, _state); - row1 = *rowptr; - ftbase_ftcomplexfftplanrec(n1, 1, ae_true, ae_false, rowptr, bluesteinsize, precrptr, preciptr, plan, _state); - plan->entries.ptr.pp_int[row0][ftbase_colparam0] = row1-row0; - row3 = *rowptr; - ftbase_ftcomplexfftplanrec(n2, 1, ae_true, ae_false, rowptr, bluesteinsize, precrptr, preciptr, plan, _state); - plan->entries.ptr.pp_int[row2][ftbase_colparam0] = row3-row2; - } - ae_frame_leave(_state); - return; - } - - /* - * Prepare "non-topmost" plan: - * * calculate factorization - * * use local (shared) buffer - * * update buffer size - ANY plan will need at least - * 2*N temporaries, additional requirements can be - * applied later - */ - ftbase_ftfactorize(n, ae_false, &n1, &n2, _state); - - /* - * Handle FFT's with N1*N2=0: either small-N or prime-factor - */ - if( n1*n2==0 ) - { - if( n<=ftbase_maxradix ) - { - - /* - * Small-N FFT - */ - if( childplan ) - { - ftbase_ftpushentry2(plan, rowptr, ftbase_opstart, k, n, 2, -1, ftbase_ftoptimisticestimate(n, _state), _state); - } - ftbase_ftpushentry(plan, rowptr, ftbase_opcomplexcodeletfft, k, n, 2, 0, _state); - if( childplan ) - { - ftbase_ftpushentry(plan, rowptr, ftbase_opend, k, n, 2, 0, _state); - } - ae_frame_leave(_state); - return; - } - if( n<=ftbase_raderthreshold ) - { - - /* - * Handle prime-factor FFT's with Rader's FFT - */ - m = n-1; - if( childplan ) - { - ftbase_ftpushentry2(plan, rowptr, ftbase_opstart, k, n, 2, -1, ftbase_ftoptimisticestimate(n, _state), _state); - } - findprimitiverootandinverse(n, &gq, &giq, _state); - ftbase_ftpushentry4(plan, rowptr, ftbase_opradersfft, k, n, 2, 2, gq, giq, *precrptr, _state); - ftbase_ftprecomputeradersfft(n, gq, giq, &plan->precr, *precrptr, _state); - *precrptr = *precrptr+2*(n-1); - row0 = *rowptr; - ftbase_ftpushentry(plan, rowptr, ftbase_opjmp, 0, 0, 0, 0, _state); - ftbase_ftcomplexfftplanrec(m, 1, ae_true, ae_false, rowptr, bluesteinsize, precrptr, preciptr, plan, _state); - row1 = *rowptr; - plan->entries.ptr.pp_int[row0][ftbase_colparam0] = row1-row0; - if( childplan ) - { - ftbase_ftpushentry(plan, rowptr, ftbase_opend, k, n, 2, 0, _state); - } - } - else - { - - /* - * Handle prime-factor FFT's with Bluestein's FFT - */ - m = ftbasefindsmooth(2*n-1, _state); - *bluesteinsize = ae_maxint(2*m, *bluesteinsize, _state); - if( childplan ) - { - ftbase_ftpushentry2(plan, rowptr, ftbase_opstart, k, n, 2, -1, ftbase_ftoptimisticestimate(n, _state), _state); - } - ftbase_ftpushentry4(plan, rowptr, ftbase_opbluesteinsfft, k, n, 2, m, 2, *precrptr, 0, _state); - ftbase_ftprecomputebluesteinsfft(n, m, &plan->precr, *precrptr, _state); - *precrptr = *precrptr+4*m; - row0 = *rowptr; - ftbase_ftpushentry(plan, rowptr, ftbase_opjmp, 0, 0, 0, 0, _state); - ftbase_ftcomplexfftplanrec(m, 1, ae_true, ae_false, rowptr, bluesteinsize, precrptr, preciptr, plan, _state); - row1 = *rowptr; - plan->entries.ptr.pp_int[row0][ftbase_colparam0] = row1-row0; - if( childplan ) - { - ftbase_ftpushentry(plan, rowptr, ftbase_opend, k, n, 2, 0, _state); - } - } - ae_frame_leave(_state); - return; - } - - /* - * Handle Cooley-Tukey FFT with small N1 - */ - if( n1<=ftbase_maxradix ) - { - - /* - * Specialized transformation for small N1: - * * N2 short inplace FFT's, each N1-point, with integrated twiddle factors - * * N1 long FFT's - * * final transposition - */ - if( childplan ) - { - ftbase_ftpushentry2(plan, rowptr, ftbase_opstart, k, n, 2, -1, ftbase_ftoptimisticestimate(n, _state), _state); - } - ftbase_ftpushentry(plan, rowptr, ftbase_opcomplexcodelettwfft, k, n1, 2*n2, 0, _state); - ftbase_ftcomplexfftplanrec(n2, k*n1, ae_false, ae_false, rowptr, bluesteinsize, precrptr, preciptr, plan, _state); - ftbase_ftpushentry(plan, rowptr, ftbase_opcomplextranspose, k, n, 2, n1, _state); - if( childplan ) - { - ftbase_ftpushentry(plan, rowptr, ftbase_opend, k, n, 2, 0, _state); - } - ae_frame_leave(_state); - return; - } - - /* - * Handle general Cooley-Tukey FFT, either "flat" or "recursive" - */ - if( n<=ftbase_recursivethreshold ) - { - - /* - * General code for large N1/N2, "flat" version without explicit recurrence - * (nested subplans are inserted directly into the body of the plan) - */ - if( childplan ) - { - ftbase_ftpushentry2(plan, rowptr, ftbase_opstart, k, n, 2, -1, ftbase_ftoptimisticestimate(n, _state), _state); - } - ftbase_ftpushentry(plan, rowptr, ftbase_opcomplextranspose, k, n, 2, n1, _state); - ftbase_ftcomplexfftplanrec(n1, k*n2, ae_false, ae_false, rowptr, bluesteinsize, precrptr, preciptr, plan, _state); - ftbase_ftpushentry(plan, rowptr, ftbase_opcomplexfftfactors, k, n, 2, n1, _state); - ftbase_ftpushentry(plan, rowptr, ftbase_opcomplextranspose, k, n, 2, n2, _state); - ftbase_ftcomplexfftplanrec(n2, k*n1, ae_false, ae_false, rowptr, bluesteinsize, precrptr, preciptr, plan, _state); - ftbase_ftpushentry(plan, rowptr, ftbase_opcomplextranspose, k, n, 2, n1, _state); - if( childplan ) - { - ftbase_ftpushentry(plan, rowptr, ftbase_opend, k, n, 2, 0, _state); - } - } - else - { - - /* - * General code for large N1/N2, "recursive" version - nested subplans - * are separated from the plan body. - * - * Generate parent plan. - */ - if( childplan ) - { - ftbase_ftpushentry2(plan, rowptr, ftbase_opstart, k, n, 2, -1, ftbase_ftoptimisticestimate(n, _state), _state); - } - ftbase_ftpushentry(plan, rowptr, ftbase_opcomplextranspose, k, n, 2, n1, _state); - row0 = *rowptr; - ftbase_ftpushentry2(plan, rowptr, ftbase_opparallelcall, k*n2, n1, 2, 0, ftbase_ftoptimisticestimate(n, _state), _state); - ftbase_ftpushentry(plan, rowptr, ftbase_opcomplexfftfactors, k, n, 2, n1, _state); - ftbase_ftpushentry(plan, rowptr, ftbase_opcomplextranspose, k, n, 2, n2, _state); - row2 = *rowptr; - ftbase_ftpushentry2(plan, rowptr, ftbase_opparallelcall, k*n1, n2, 2, 0, ftbase_ftoptimisticestimate(n, _state), _state); - ftbase_ftpushentry(plan, rowptr, ftbase_opcomplextranspose, k, n, 2, n1, _state); - if( childplan ) - { - ftbase_ftpushentry(plan, rowptr, ftbase_opend, k, n, 2, 0, _state); - } - - /* - * Generate child subplans, insert refence to parent plans - */ - row1 = *rowptr; - ftbase_ftcomplexfftplanrec(n1, 1, ae_true, ae_false, rowptr, bluesteinsize, precrptr, preciptr, plan, _state); - plan->entries.ptr.pp_int[row0][ftbase_colparam0] = row1-row0; - row3 = *rowptr; - ftbase_ftcomplexfftplanrec(n2, 1, ae_true, ae_false, rowptr, bluesteinsize, precrptr, preciptr, plan, _state); - plan->entries.ptr.pp_int[row2][ftbase_colparam0] = row3-row2; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function pushes one more entry to the plan. It resizes Entries matrix -if needed. - -INPUT PARAMETERS: - Plan - plan (generated so far) - RowPtr - index which points to past-the-last entry generated so far - EType - entry type - EOpCnt - operands count - EOpSize - operand size - EMcvSize - microvector size - EParam0 - parameter 0 - -OUTPUT PARAMETERS: - Plan - updated plan - RowPtr - updated pointer - -NOTE: Param1 is set to -1. - - -- ALGLIB -- - Copyright 05.04.2013 by Bochkanov Sergey -*************************************************************************/ -static void ftbase_ftpushentry(fasttransformplan* plan, - ae_int_t* rowptr, - ae_int_t etype, - ae_int_t eopcnt, - ae_int_t eopsize, - ae_int_t emcvsize, - ae_int_t eparam0, - ae_state *_state) -{ - - - ftbase_ftpushentry2(plan, rowptr, etype, eopcnt, eopsize, emcvsize, eparam0, -1, _state); -} - - -/************************************************************************* -Same as FTPushEntry(), but sets Param0 AND Param1. -This function pushes one more entry to the plan. It resized Entries matrix -if needed. - -INPUT PARAMETERS: - Plan - plan (generated so far) - RowPtr - index which points to past-the-last entry generated so far - EType - entry type - EOpCnt - operands count - EOpSize - operand size - EMcvSize - microvector size - EParam0 - parameter 0 - EParam1 - parameter 1 - -OUTPUT PARAMETERS: - Plan - updated plan - RowPtr - updated pointer - - -- ALGLIB -- - Copyright 05.04.2013 by Bochkanov Sergey -*************************************************************************/ -static void ftbase_ftpushentry2(fasttransformplan* plan, - ae_int_t* rowptr, - ae_int_t etype, - ae_int_t eopcnt, - ae_int_t eopsize, - ae_int_t emcvsize, - ae_int_t eparam0, - ae_int_t eparam1, - ae_state *_state) -{ - - - if( *rowptr>=plan->entries.rows ) - { - imatrixresize(&plan->entries, ae_maxint(2*plan->entries.rows, 1, _state), ftbase_colscnt, _state); - } - plan->entries.ptr.pp_int[*rowptr][ftbase_coltype] = etype; - plan->entries.ptr.pp_int[*rowptr][ftbase_coloperandscnt] = eopcnt; - plan->entries.ptr.pp_int[*rowptr][ftbase_coloperandsize] = eopsize; - plan->entries.ptr.pp_int[*rowptr][ftbase_colmicrovectorsize] = emcvsize; - plan->entries.ptr.pp_int[*rowptr][ftbase_colparam0] = eparam0; - plan->entries.ptr.pp_int[*rowptr][ftbase_colparam1] = eparam1; - plan->entries.ptr.pp_int[*rowptr][ftbase_colparam2] = 0; - plan->entries.ptr.pp_int[*rowptr][ftbase_colparam3] = 0; - *rowptr = *rowptr+1; -} - - -/************************************************************************* -Same as FTPushEntry(), but sets Param0, Param1, Param2 and Param3. -This function pushes one more entry to the plan. It resized Entries matrix -if needed. - -INPUT PARAMETERS: - Plan - plan (generated so far) - RowPtr - index which points to past-the-last entry generated so far - EType - entry type - EOpCnt - operands count - EOpSize - operand size - EMcvSize - microvector size - EParam0 - parameter 0 - EParam1 - parameter 1 - EParam2 - parameter 2 - EParam3 - parameter 3 - -OUTPUT PARAMETERS: - Plan - updated plan - RowPtr - updated pointer - - -- ALGLIB -- - Copyright 05.04.2013 by Bochkanov Sergey -*************************************************************************/ -static void ftbase_ftpushentry4(fasttransformplan* plan, - ae_int_t* rowptr, - ae_int_t etype, - ae_int_t eopcnt, - ae_int_t eopsize, - ae_int_t emcvsize, - ae_int_t eparam0, - ae_int_t eparam1, - ae_int_t eparam2, - ae_int_t eparam3, - ae_state *_state) -{ - - - if( *rowptr>=plan->entries.rows ) - { - imatrixresize(&plan->entries, ae_maxint(2*plan->entries.rows, 1, _state), ftbase_colscnt, _state); - } - plan->entries.ptr.pp_int[*rowptr][ftbase_coltype] = etype; - plan->entries.ptr.pp_int[*rowptr][ftbase_coloperandscnt] = eopcnt; - plan->entries.ptr.pp_int[*rowptr][ftbase_coloperandsize] = eopsize; - plan->entries.ptr.pp_int[*rowptr][ftbase_colmicrovectorsize] = emcvsize; - plan->entries.ptr.pp_int[*rowptr][ftbase_colparam0] = eparam0; - plan->entries.ptr.pp_int[*rowptr][ftbase_colparam1] = eparam1; - plan->entries.ptr.pp_int[*rowptr][ftbase_colparam2] = eparam2; - plan->entries.ptr.pp_int[*rowptr][ftbase_colparam3] = eparam3; - *rowptr = *rowptr+1; -} - - -/************************************************************************* -This subroutine applies subplan to input/output array A. - -INPUT PARAMETERS: - Plan - transformation plan - SubPlan - subplan index - A - array, must be large enough for plan to work - ABase - base offset in array A, this value points to start of - subarray whose length is equal to length of the plan - AOffset - offset with respect to ABase, 0<=AOffsetentries.ptr.pp_int[subplan][ftbase_coltype]==ftbase_opstart, "FTApplySubPlan: incorrect subplan header", _state); - rowidx = subplan+1; - while(plan->entries.ptr.pp_int[rowidx][ftbase_coltype]!=ftbase_opend) - { - operation = plan->entries.ptr.pp_int[rowidx][ftbase_coltype]; - operandscnt = repcnt*plan->entries.ptr.pp_int[rowidx][ftbase_coloperandscnt]; - operandsize = plan->entries.ptr.pp_int[rowidx][ftbase_coloperandsize]; - microvectorsize = plan->entries.ptr.pp_int[rowidx][ftbase_colmicrovectorsize]; - param0 = plan->entries.ptr.pp_int[rowidx][ftbase_colparam0]; - param1 = plan->entries.ptr.pp_int[rowidx][ftbase_colparam1]; - touchint(¶m1, _state); - - /* - * Process "jump" operation - */ - if( operation==ftbase_opjmp ) - { - rowidx = rowidx+plan->entries.ptr.pp_int[rowidx][ftbase_colparam0]; - continue; - } - - /* - * Process "parallel call" operation: - * * we perform initial check for consistency between parent and child plans - * * we call FTSplitAndApplyParallelPlan(), which splits parallel plan into - * several parallel tasks - */ - if( operation==ftbase_opparallelcall ) - { - parentsize = operandsize*microvectorsize; - childsize = plan->entries.ptr.pp_int[rowidx+param0][ftbase_coloperandscnt]*plan->entries.ptr.pp_int[rowidx+param0][ftbase_coloperandsize]*plan->entries.ptr.pp_int[rowidx+param0][ftbase_colmicrovectorsize]; - ae_assert(plan->entries.ptr.pp_int[rowidx+param0][ftbase_coltype]==ftbase_opstart, "FTApplySubPlan: incorrect child subplan header", _state); - ae_assert(parentsize==childsize, "FTApplySubPlan: incorrect child subplan header", _state); - chunksize = ae_maxint(ftbase_recursivethreshold/childsize, 1, _state); - lastchunksize = operandscnt%chunksize; - if( lastchunksize==0 ) - { - lastchunksize = chunksize; - } - i = 0; - while(ibluesteinpool, &_bufa, _state); - ae_shared_pool_retrieve(&plan->bluesteinpool, &_bufb, _state); - ae_shared_pool_retrieve(&plan->bluesteinpool, &_bufc, _state); - ae_shared_pool_retrieve(&plan->bluesteinpool, &_bufd, _state); - ftbase_ftbluesteinsfft(plan, a, abase, aoffset, operandscnt, operandsize, plan->entries.ptr.pp_int[rowidx][ftbase_colparam0], plan->entries.ptr.pp_int[rowidx][ftbase_colparam2], rowidx+plan->entries.ptr.pp_int[rowidx][ftbase_colparam1], &bufa->val, &bufb->val, &bufc->val, &bufd->val, _state); - ae_shared_pool_recycle(&plan->bluesteinpool, &_bufa, _state); - ae_shared_pool_recycle(&plan->bluesteinpool, &_bufb, _state); - ae_shared_pool_recycle(&plan->bluesteinpool, &_bufc, _state); - ae_shared_pool_recycle(&plan->bluesteinpool, &_bufd, _state); - rowidx = rowidx+1; - continue; - } - - /* - * Process Rader's FFT - */ - if( operation==ftbase_opradersfft ) - { - ftbase_ftradersfft(plan, a, abase, aoffset, operandscnt, operandsize, rowidx+plan->entries.ptr.pp_int[rowidx][ftbase_colparam0], plan->entries.ptr.pp_int[rowidx][ftbase_colparam1], plan->entries.ptr.pp_int[rowidx][ftbase_colparam2], plan->entries.ptr.pp_int[rowidx][ftbase_colparam3], buf, _state); - rowidx = rowidx+1; - continue; - } - - /* - * Process "complex twiddle factors" operation - */ - if( operation==ftbase_opcomplexfftfactors ) - { - ae_assert(microvectorsize==2, "FTApplySubPlan: MicrovectorSize<>1", _state); - n1 = plan->entries.ptr.pp_int[rowidx][ftbase_colparam0]; - n2 = operandsize/n1; - for(i=0; i<=operandscnt-1; i++) - { - ftbase_ffttwcalc(a, abase+aoffset+i*operandsize*2, n1, n2, _state); - } - rowidx = rowidx+1; - continue; - } - - /* - * Process "complex transposition" operation - */ - if( operation==ftbase_opcomplextranspose ) - { - ae_assert(microvectorsize==2, "FTApplySubPlan: MicrovectorSize<>1", _state); - n1 = plan->entries.ptr.pp_int[rowidx][ftbase_colparam0]; - n2 = operandsize/n1; - for(i=0; i<=operandscnt-1; i++) - { - ftbase_internalcomplexlintranspose(a, n1, n2, abase+aoffset+i*operandsize*2, buf, _state); - } - rowidx = rowidx+1; - continue; - } - - /* - * Error - */ - ae_assert(ae_false, "FTApplySubPlan: unexpected plan type", _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This subroutine applies complex reference FFT to input/output array A. - -VERY SLOW OPERATION, do not use it in real life plans :) - -INPUT PARAMETERS: - A - array, must be large enough for plan to work - Offs - offset of the subarray to process - OperandsCnt - operands count (see description of FastTransformPlan) - OperandSize - operand size (see description of FastTransformPlan) - MicrovectorSize-microvector size (see description of FastTransformPlan) - Buf - temporary array, must be at least OperandsCnt*OperandSize*MicrovectorSize - -OUTPUT PARAMETERS: - A - transformed array - - -- ALGLIB -- - Copyright 05.04.2013 by Bochkanov Sergey -*************************************************************************/ -static void ftbase_ftapplycomplexreffft(/* Real */ ae_vector* a, - ae_int_t offs, - ae_int_t operandscnt, - ae_int_t operandsize, - ae_int_t microvectorsize, - /* Real */ ae_vector* buf, - ae_state *_state) -{ - ae_int_t opidx; - ae_int_t i; - ae_int_t k; - double hre; - double him; - double c; - double s; - double re; - double im; - ae_int_t n; - - - ae_assert(operandscnt>=1, "FTApplyComplexRefFFT: OperandsCnt<1", _state); - ae_assert(operandsize>=1, "FTApplyComplexRefFFT: OperandSize<1", _state); - ae_assert(microvectorsize==2, "FTApplyComplexRefFFT: MicrovectorSize<>2", _state); - n = operandsize; - for(opidx=0; opidx<=operandscnt-1; opidx++) - { - for(i=0; i<=n-1; i++) - { - hre = (double)(0); - him = (double)(0); - for(k=0; k<=n-1; k++) - { - re = a->ptr.p_double[offs+opidx*operandsize*2+2*k+0]; - im = a->ptr.p_double[offs+opidx*operandsize*2+2*k+1]; - c = ae_cos(-2*ae_pi*k*i/n, _state); - s = ae_sin(-2*ae_pi*k*i/n, _state); - hre = hre+c*re-s*im; - him = him+c*im+s*re; - } - buf->ptr.p_double[2*i+0] = hre; - buf->ptr.p_double[2*i+1] = him; - } - for(i=0; i<=operandsize*2-1; i++) - { - a->ptr.p_double[offs+opidx*operandsize*2+i] = buf->ptr.p_double[i]; - } - } -} - - -/************************************************************************* -This subroutine applies complex codelet FFT to input/output array A. - -INPUT PARAMETERS: - A - array, must be large enough for plan to work - Offs - offset of the subarray to process - OperandsCnt - operands count (see description of FastTransformPlan) - OperandSize - operand size (see description of FastTransformPlan) - MicrovectorSize-microvector size, must be 2 - -OUTPUT PARAMETERS: - A - transformed array - - -- ALGLIB -- - Copyright 05.04.2013 by Bochkanov Sergey -*************************************************************************/ -static void ftbase_ftapplycomplexcodeletfft(/* Real */ ae_vector* a, - ae_int_t offs, - ae_int_t operandscnt, - ae_int_t operandsize, - ae_int_t microvectorsize, - ae_state *_state) -{ - ae_int_t opidx; - ae_int_t n; - ae_int_t aoffset; - double a0x; - double a0y; - double a1x; - double a1y; - double a2x; - double a2y; - double a3x; - double a3y; - double a4x; - double a4y; - double a5x; - double a5y; - double v0; - double v1; - double v2; - double v3; - double t1x; - double t1y; - double t2x; - double t2y; - double t3x; - double t3y; - double t4x; - double t4y; - double t5x; - double t5y; - double m1x; - double m1y; - double m2x; - double m2y; - double m3x; - double m3y; - double m4x; - double m4y; - double m5x; - double m5y; - double s1x; - double s1y; - double s2x; - double s2y; - double s3x; - double s3y; - double s4x; - double s4y; - double s5x; - double s5y; - double c1; - double c2; - double c3; - double c4; - double c5; - double v; - - - ae_assert(operandscnt>=1, "FTApplyComplexCodeletFFT: OperandsCnt<1", _state); - ae_assert(operandsize>=1, "FTApplyComplexCodeletFFT: OperandSize<1", _state); - ae_assert(microvectorsize==2, "FTApplyComplexCodeletFFT: MicrovectorSize<>2", _state); - n = operandsize; - - /* - * Hard-coded transforms for different N's - */ - ae_assert(n<=ftbase_maxradix, "FTApplyComplexCodeletFFT: N>MaxRadix", _state); - if( n==2 ) - { - for(opidx=0; opidx<=operandscnt-1; opidx++) - { - aoffset = offs+opidx*operandsize*2; - a0x = a->ptr.p_double[aoffset+0]; - a0y = a->ptr.p_double[aoffset+1]; - a1x = a->ptr.p_double[aoffset+2]; - a1y = a->ptr.p_double[aoffset+3]; - v0 = a0x+a1x; - v1 = a0y+a1y; - v2 = a0x-a1x; - v3 = a0y-a1y; - a->ptr.p_double[aoffset+0] = v0; - a->ptr.p_double[aoffset+1] = v1; - a->ptr.p_double[aoffset+2] = v2; - a->ptr.p_double[aoffset+3] = v3; - } - return; - } - if( n==3 ) - { - c1 = ae_cos(2*ae_pi/3, _state)-1; - c2 = ae_sin(2*ae_pi/3, _state); - for(opidx=0; opidx<=operandscnt-1; opidx++) - { - aoffset = offs+opidx*operandsize*2; - a0x = a->ptr.p_double[aoffset+0]; - a0y = a->ptr.p_double[aoffset+1]; - a1x = a->ptr.p_double[aoffset+2]; - a1y = a->ptr.p_double[aoffset+3]; - a2x = a->ptr.p_double[aoffset+4]; - a2y = a->ptr.p_double[aoffset+5]; - t1x = a1x+a2x; - t1y = a1y+a2y; - a0x = a0x+t1x; - a0y = a0y+t1y; - m1x = c1*t1x; - m1y = c1*t1y; - m2x = c2*(a1y-a2y); - m2y = c2*(a2x-a1x); - s1x = a0x+m1x; - s1y = a0y+m1y; - a1x = s1x+m2x; - a1y = s1y+m2y; - a2x = s1x-m2x; - a2y = s1y-m2y; - a->ptr.p_double[aoffset+0] = a0x; - a->ptr.p_double[aoffset+1] = a0y; - a->ptr.p_double[aoffset+2] = a1x; - a->ptr.p_double[aoffset+3] = a1y; - a->ptr.p_double[aoffset+4] = a2x; - a->ptr.p_double[aoffset+5] = a2y; - } - return; - } - if( n==4 ) - { - for(opidx=0; opidx<=operandscnt-1; opidx++) - { - aoffset = offs+opidx*operandsize*2; - a0x = a->ptr.p_double[aoffset+0]; - a0y = a->ptr.p_double[aoffset+1]; - a1x = a->ptr.p_double[aoffset+2]; - a1y = a->ptr.p_double[aoffset+3]; - a2x = a->ptr.p_double[aoffset+4]; - a2y = a->ptr.p_double[aoffset+5]; - a3x = a->ptr.p_double[aoffset+6]; - a3y = a->ptr.p_double[aoffset+7]; - t1x = a0x+a2x; - t1y = a0y+a2y; - t2x = a1x+a3x; - t2y = a1y+a3y; - m2x = a0x-a2x; - m2y = a0y-a2y; - m3x = a1y-a3y; - m3y = a3x-a1x; - a->ptr.p_double[aoffset+0] = t1x+t2x; - a->ptr.p_double[aoffset+1] = t1y+t2y; - a->ptr.p_double[aoffset+4] = t1x-t2x; - a->ptr.p_double[aoffset+5] = t1y-t2y; - a->ptr.p_double[aoffset+2] = m2x+m3x; - a->ptr.p_double[aoffset+3] = m2y+m3y; - a->ptr.p_double[aoffset+6] = m2x-m3x; - a->ptr.p_double[aoffset+7] = m2y-m3y; - } - return; - } - if( n==5 ) - { - v = 2*ae_pi/5; - c1 = (ae_cos(v, _state)+ae_cos(2*v, _state))/2-1; - c2 = (ae_cos(v, _state)-ae_cos(2*v, _state))/2; - c3 = -ae_sin(v, _state); - c4 = -(ae_sin(v, _state)+ae_sin(2*v, _state)); - c5 = ae_sin(v, _state)-ae_sin(2*v, _state); - for(opidx=0; opidx<=operandscnt-1; opidx++) - { - aoffset = offs+opidx*operandsize*2; - t1x = a->ptr.p_double[aoffset+2]+a->ptr.p_double[aoffset+8]; - t1y = a->ptr.p_double[aoffset+3]+a->ptr.p_double[aoffset+9]; - t2x = a->ptr.p_double[aoffset+4]+a->ptr.p_double[aoffset+6]; - t2y = a->ptr.p_double[aoffset+5]+a->ptr.p_double[aoffset+7]; - t3x = a->ptr.p_double[aoffset+2]-a->ptr.p_double[aoffset+8]; - t3y = a->ptr.p_double[aoffset+3]-a->ptr.p_double[aoffset+9]; - t4x = a->ptr.p_double[aoffset+6]-a->ptr.p_double[aoffset+4]; - t4y = a->ptr.p_double[aoffset+7]-a->ptr.p_double[aoffset+5]; - t5x = t1x+t2x; - t5y = t1y+t2y; - a->ptr.p_double[aoffset+0] = a->ptr.p_double[aoffset+0]+t5x; - a->ptr.p_double[aoffset+1] = a->ptr.p_double[aoffset+1]+t5y; - m1x = c1*t5x; - m1y = c1*t5y; - m2x = c2*(t1x-t2x); - m2y = c2*(t1y-t2y); - m3x = -c3*(t3y+t4y); - m3y = c3*(t3x+t4x); - m4x = -c4*t4y; - m4y = c4*t4x; - m5x = -c5*t3y; - m5y = c5*t3x; - s3x = m3x-m4x; - s3y = m3y-m4y; - s5x = m3x+m5x; - s5y = m3y+m5y; - s1x = a->ptr.p_double[aoffset+0]+m1x; - s1y = a->ptr.p_double[aoffset+1]+m1y; - s2x = s1x+m2x; - s2y = s1y+m2y; - s4x = s1x-m2x; - s4y = s1y-m2y; - a->ptr.p_double[aoffset+2] = s2x+s3x; - a->ptr.p_double[aoffset+3] = s2y+s3y; - a->ptr.p_double[aoffset+4] = s4x+s5x; - a->ptr.p_double[aoffset+5] = s4y+s5y; - a->ptr.p_double[aoffset+6] = s4x-s5x; - a->ptr.p_double[aoffset+7] = s4y-s5y; - a->ptr.p_double[aoffset+8] = s2x-s3x; - a->ptr.p_double[aoffset+9] = s2y-s3y; - } - return; - } - if( n==6 ) - { - c1 = ae_cos(2*ae_pi/3, _state)-1; - c2 = ae_sin(2*ae_pi/3, _state); - c3 = ae_cos(-ae_pi/3, _state); - c4 = ae_sin(-ae_pi/3, _state); - for(opidx=0; opidx<=operandscnt-1; opidx++) - { - aoffset = offs+opidx*operandsize*2; - a0x = a->ptr.p_double[aoffset+0]; - a0y = a->ptr.p_double[aoffset+1]; - a1x = a->ptr.p_double[aoffset+2]; - a1y = a->ptr.p_double[aoffset+3]; - a2x = a->ptr.p_double[aoffset+4]; - a2y = a->ptr.p_double[aoffset+5]; - a3x = a->ptr.p_double[aoffset+6]; - a3y = a->ptr.p_double[aoffset+7]; - a4x = a->ptr.p_double[aoffset+8]; - a4y = a->ptr.p_double[aoffset+9]; - a5x = a->ptr.p_double[aoffset+10]; - a5y = a->ptr.p_double[aoffset+11]; - v0 = a0x; - v1 = a0y; - a0x = a0x+a3x; - a0y = a0y+a3y; - a3x = v0-a3x; - a3y = v1-a3y; - v0 = a1x; - v1 = a1y; - a1x = a1x+a4x; - a1y = a1y+a4y; - a4x = v0-a4x; - a4y = v1-a4y; - v0 = a2x; - v1 = a2y; - a2x = a2x+a5x; - a2y = a2y+a5y; - a5x = v0-a5x; - a5y = v1-a5y; - t4x = a4x*c3-a4y*c4; - t4y = a4x*c4+a4y*c3; - a4x = t4x; - a4y = t4y; - t5x = -a5x*c3-a5y*c4; - t5y = a5x*c4-a5y*c3; - a5x = t5x; - a5y = t5y; - t1x = a1x+a2x; - t1y = a1y+a2y; - a0x = a0x+t1x; - a0y = a0y+t1y; - m1x = c1*t1x; - m1y = c1*t1y; - m2x = c2*(a1y-a2y); - m2y = c2*(a2x-a1x); - s1x = a0x+m1x; - s1y = a0y+m1y; - a1x = s1x+m2x; - a1y = s1y+m2y; - a2x = s1x-m2x; - a2y = s1y-m2y; - t1x = a4x+a5x; - t1y = a4y+a5y; - a3x = a3x+t1x; - a3y = a3y+t1y; - m1x = c1*t1x; - m1y = c1*t1y; - m2x = c2*(a4y-a5y); - m2y = c2*(a5x-a4x); - s1x = a3x+m1x; - s1y = a3y+m1y; - a4x = s1x+m2x; - a4y = s1y+m2y; - a5x = s1x-m2x; - a5y = s1y-m2y; - a->ptr.p_double[aoffset+0] = a0x; - a->ptr.p_double[aoffset+1] = a0y; - a->ptr.p_double[aoffset+2] = a3x; - a->ptr.p_double[aoffset+3] = a3y; - a->ptr.p_double[aoffset+4] = a1x; - a->ptr.p_double[aoffset+5] = a1y; - a->ptr.p_double[aoffset+6] = a4x; - a->ptr.p_double[aoffset+7] = a4y; - a->ptr.p_double[aoffset+8] = a2x; - a->ptr.p_double[aoffset+9] = a2y; - a->ptr.p_double[aoffset+10] = a5x; - a->ptr.p_double[aoffset+11] = a5y; - } - return; - } -} - - -/************************************************************************* -This subroutine applies complex "integrated" codelet FFT to input/output -array A. "Integrated" codelet differs from "normal" one in following ways: -* it can work with MicrovectorSize>1 -* hence, it can be used in Cooley-Tukey FFT without transpositions -* it performs inlined multiplication by twiddle factors of Cooley-Tukey - FFT with N2=MicrovectorSize/2. - -INPUT PARAMETERS: - A - array, must be large enough for plan to work - Offs - offset of the subarray to process - OperandsCnt - operands count (see description of FastTransformPlan) - OperandSize - operand size (see description of FastTransformPlan) - MicrovectorSize-microvector size, must be 1 - -OUTPUT PARAMETERS: - A - transformed array - - -- ALGLIB -- - Copyright 05.04.2013 by Bochkanov Sergey -*************************************************************************/ -static void ftbase_ftapplycomplexcodelettwfft(/* Real */ ae_vector* a, - ae_int_t offs, - ae_int_t operandscnt, - ae_int_t operandsize, - ae_int_t microvectorsize, - ae_state *_state) -{ - ae_int_t opidx; - ae_int_t mvidx; - ae_int_t n; - ae_int_t m; - ae_int_t aoffset0; - ae_int_t aoffset2; - ae_int_t aoffset4; - ae_int_t aoffset6; - ae_int_t aoffset8; - ae_int_t aoffset10; - double a0x; - double a0y; - double a1x; - double a1y; - double a2x; - double a2y; - double a3x; - double a3y; - double a4x; - double a4y; - double a5x; - double a5y; - double v0; - double v1; - double v2; - double v3; - double q0x; - double q0y; - double t1x; - double t1y; - double t2x; - double t2y; - double t3x; - double t3y; - double t4x; - double t4y; - double t5x; - double t5y; - double m1x; - double m1y; - double m2x; - double m2y; - double m3x; - double m3y; - double m4x; - double m4y; - double m5x; - double m5y; - double s1x; - double s1y; - double s2x; - double s2y; - double s3x; - double s3y; - double s4x; - double s4y; - double s5x; - double s5y; - double c1; - double c2; - double c3; - double c4; - double c5; - double v; - double tw0; - double tw1; - double twx; - double twxm1; - double twy; - double tw2x; - double tw2y; - double tw3x; - double tw3y; - double tw4x; - double tw4y; - double tw5x; - double tw5y; - - - ae_assert(operandscnt>=1, "FTApplyComplexCodeletFFT: OperandsCnt<1", _state); - ae_assert(operandsize>=1, "FTApplyComplexCodeletFFT: OperandSize<1", _state); - ae_assert(microvectorsize>=1, "FTApplyComplexCodeletFFT: MicrovectorSize<>1", _state); - ae_assert(microvectorsize%2==0, "FTApplyComplexCodeletFFT: MicrovectorSize is not even", _state); - n = operandsize; - m = microvectorsize/2; - - /* - * Hard-coded transforms for different N's - */ - ae_assert(n<=ftbase_maxradix, "FTApplyComplexCodeletTwFFT: N>MaxRadix", _state); - if( n==2 ) - { - v = -2*ae_pi/(n*m); - tw0 = -2*ae_sqr(ae_sin(0.5*v, _state), _state); - tw1 = ae_sin(v, _state); - for(opidx=0; opidx<=operandscnt-1; opidx++) - { - aoffset0 = offs+opidx*operandsize*microvectorsize; - aoffset2 = aoffset0+microvectorsize; - twxm1 = 0.0; - twy = 0.0; - for(mvidx=0; mvidx<=m-1; mvidx++) - { - a0x = a->ptr.p_double[aoffset0]; - a0y = a->ptr.p_double[aoffset0+1]; - a1x = a->ptr.p_double[aoffset2]; - a1y = a->ptr.p_double[aoffset2+1]; - v0 = a0x+a1x; - v1 = a0y+a1y; - v2 = a0x-a1x; - v3 = a0y-a1y; - a->ptr.p_double[aoffset0] = v0; - a->ptr.p_double[aoffset0+1] = v1; - a->ptr.p_double[aoffset2] = v2*(1+twxm1)-v3*twy; - a->ptr.p_double[aoffset2+1] = v3*(1+twxm1)+v2*twy; - aoffset0 = aoffset0+2; - aoffset2 = aoffset2+2; - if( (mvidx+1)%ftbase_updatetw==0 ) - { - v = -2*ae_pi*(mvidx+1)/(n*m); - twxm1 = ae_sin(0.5*v, _state); - twxm1 = -2*twxm1*twxm1; - twy = ae_sin(v, _state); - } - else - { - v = twxm1+tw0+twxm1*tw0-twy*tw1; - twy = twy+tw1+twxm1*tw1+twy*tw0; - twxm1 = v; - } - } - } - return; - } - if( n==3 ) - { - v = -2*ae_pi/(n*m); - tw0 = -2*ae_sqr(ae_sin(0.5*v, _state), _state); - tw1 = ae_sin(v, _state); - c1 = ae_cos(2*ae_pi/3, _state)-1; - c2 = ae_sin(2*ae_pi/3, _state); - for(opidx=0; opidx<=operandscnt-1; opidx++) - { - aoffset0 = offs+opidx*operandsize*microvectorsize; - aoffset2 = aoffset0+microvectorsize; - aoffset4 = aoffset2+microvectorsize; - twx = 1.0; - twxm1 = 0.0; - twy = 0.0; - for(mvidx=0; mvidx<=m-1; mvidx++) - { - a0x = a->ptr.p_double[aoffset0]; - a0y = a->ptr.p_double[aoffset0+1]; - a1x = a->ptr.p_double[aoffset2]; - a1y = a->ptr.p_double[aoffset2+1]; - a2x = a->ptr.p_double[aoffset4]; - a2y = a->ptr.p_double[aoffset4+1]; - t1x = a1x+a2x; - t1y = a1y+a2y; - a0x = a0x+t1x; - a0y = a0y+t1y; - m1x = c1*t1x; - m1y = c1*t1y; - m2x = c2*(a1y-a2y); - m2y = c2*(a2x-a1x); - s1x = a0x+m1x; - s1y = a0y+m1y; - a1x = s1x+m2x; - a1y = s1y+m2y; - a2x = s1x-m2x; - a2y = s1y-m2y; - tw2x = twx*twx-twy*twy; - tw2y = 2*twx*twy; - a->ptr.p_double[aoffset0] = a0x; - a->ptr.p_double[aoffset0+1] = a0y; - a->ptr.p_double[aoffset2] = a1x*twx-a1y*twy; - a->ptr.p_double[aoffset2+1] = a1y*twx+a1x*twy; - a->ptr.p_double[aoffset4] = a2x*tw2x-a2y*tw2y; - a->ptr.p_double[aoffset4+1] = a2y*tw2x+a2x*tw2y; - aoffset0 = aoffset0+2; - aoffset2 = aoffset2+2; - aoffset4 = aoffset4+2; - if( (mvidx+1)%ftbase_updatetw==0 ) - { - v = -2*ae_pi*(mvidx+1)/(n*m); - twxm1 = ae_sin(0.5*v, _state); - twxm1 = -2*twxm1*twxm1; - twy = ae_sin(v, _state); - twx = twxm1+1; - } - else - { - v = twxm1+tw0+twxm1*tw0-twy*tw1; - twy = twy+tw1+twxm1*tw1+twy*tw0; - twxm1 = v; - twx = v+1; - } - } - } - return; - } - if( n==4 ) - { - v = -2*ae_pi/(n*m); - tw0 = -2*ae_sqr(ae_sin(0.5*v, _state), _state); - tw1 = ae_sin(v, _state); - for(opidx=0; opidx<=operandscnt-1; opidx++) - { - aoffset0 = offs+opidx*operandsize*microvectorsize; - aoffset2 = aoffset0+microvectorsize; - aoffset4 = aoffset2+microvectorsize; - aoffset6 = aoffset4+microvectorsize; - twx = 1.0; - twxm1 = 0.0; - twy = 0.0; - for(mvidx=0; mvidx<=m-1; mvidx++) - { - a0x = a->ptr.p_double[aoffset0]; - a0y = a->ptr.p_double[aoffset0+1]; - a1x = a->ptr.p_double[aoffset2]; - a1y = a->ptr.p_double[aoffset2+1]; - a2x = a->ptr.p_double[aoffset4]; - a2y = a->ptr.p_double[aoffset4+1]; - a3x = a->ptr.p_double[aoffset6]; - a3y = a->ptr.p_double[aoffset6+1]; - t1x = a0x+a2x; - t1y = a0y+a2y; - t2x = a1x+a3x; - t2y = a1y+a3y; - m2x = a0x-a2x; - m2y = a0y-a2y; - m3x = a1y-a3y; - m3y = a3x-a1x; - tw2x = twx*twx-twy*twy; - tw2y = 2*twx*twy; - tw3x = twx*tw2x-twy*tw2y; - tw3y = twx*tw2y+twy*tw2x; - a1x = m2x+m3x; - a1y = m2y+m3y; - a2x = t1x-t2x; - a2y = t1y-t2y; - a3x = m2x-m3x; - a3y = m2y-m3y; - a->ptr.p_double[aoffset0] = t1x+t2x; - a->ptr.p_double[aoffset0+1] = t1y+t2y; - a->ptr.p_double[aoffset2] = a1x*twx-a1y*twy; - a->ptr.p_double[aoffset2+1] = a1y*twx+a1x*twy; - a->ptr.p_double[aoffset4] = a2x*tw2x-a2y*tw2y; - a->ptr.p_double[aoffset4+1] = a2y*tw2x+a2x*tw2y; - a->ptr.p_double[aoffset6] = a3x*tw3x-a3y*tw3y; - a->ptr.p_double[aoffset6+1] = a3y*tw3x+a3x*tw3y; - aoffset0 = aoffset0+2; - aoffset2 = aoffset2+2; - aoffset4 = aoffset4+2; - aoffset6 = aoffset6+2; - if( (mvidx+1)%ftbase_updatetw==0 ) - { - v = -2*ae_pi*(mvidx+1)/(n*m); - twxm1 = ae_sin(0.5*v, _state); - twxm1 = -2*twxm1*twxm1; - twy = ae_sin(v, _state); - twx = twxm1+1; - } - else - { - v = twxm1+tw0+twxm1*tw0-twy*tw1; - twy = twy+tw1+twxm1*tw1+twy*tw0; - twxm1 = v; - twx = v+1; - } - } - } - return; - } - if( n==5 ) - { - v = -2*ae_pi/(n*m); - tw0 = -2*ae_sqr(ae_sin(0.5*v, _state), _state); - tw1 = ae_sin(v, _state); - v = 2*ae_pi/5; - c1 = (ae_cos(v, _state)+ae_cos(2*v, _state))/2-1; - c2 = (ae_cos(v, _state)-ae_cos(2*v, _state))/2; - c3 = -ae_sin(v, _state); - c4 = -(ae_sin(v, _state)+ae_sin(2*v, _state)); - c5 = ae_sin(v, _state)-ae_sin(2*v, _state); - for(opidx=0; opidx<=operandscnt-1; opidx++) - { - aoffset0 = offs+opidx*operandsize*microvectorsize; - aoffset2 = aoffset0+microvectorsize; - aoffset4 = aoffset2+microvectorsize; - aoffset6 = aoffset4+microvectorsize; - aoffset8 = aoffset6+microvectorsize; - twx = 1.0; - twxm1 = 0.0; - twy = 0.0; - for(mvidx=0; mvidx<=m-1; mvidx++) - { - a0x = a->ptr.p_double[aoffset0]; - a0y = a->ptr.p_double[aoffset0+1]; - a1x = a->ptr.p_double[aoffset2]; - a1y = a->ptr.p_double[aoffset2+1]; - a2x = a->ptr.p_double[aoffset4]; - a2y = a->ptr.p_double[aoffset4+1]; - a3x = a->ptr.p_double[aoffset6]; - a3y = a->ptr.p_double[aoffset6+1]; - a4x = a->ptr.p_double[aoffset8]; - a4y = a->ptr.p_double[aoffset8+1]; - t1x = a1x+a4x; - t1y = a1y+a4y; - t2x = a2x+a3x; - t2y = a2y+a3y; - t3x = a1x-a4x; - t3y = a1y-a4y; - t4x = a3x-a2x; - t4y = a3y-a2y; - t5x = t1x+t2x; - t5y = t1y+t2y; - q0x = a0x+t5x; - q0y = a0y+t5y; - m1x = c1*t5x; - m1y = c1*t5y; - m2x = c2*(t1x-t2x); - m2y = c2*(t1y-t2y); - m3x = -c3*(t3y+t4y); - m3y = c3*(t3x+t4x); - m4x = -c4*t4y; - m4y = c4*t4x; - m5x = -c5*t3y; - m5y = c5*t3x; - s3x = m3x-m4x; - s3y = m3y-m4y; - s5x = m3x+m5x; - s5y = m3y+m5y; - s1x = q0x+m1x; - s1y = q0y+m1y; - s2x = s1x+m2x; - s2y = s1y+m2y; - s4x = s1x-m2x; - s4y = s1y-m2y; - tw2x = twx*twx-twy*twy; - tw2y = 2*twx*twy; - tw3x = twx*tw2x-twy*tw2y; - tw3y = twx*tw2y+twy*tw2x; - tw4x = tw2x*tw2x-tw2y*tw2y; - tw4y = tw2x*tw2y+tw2y*tw2x; - a1x = s2x+s3x; - a1y = s2y+s3y; - a2x = s4x+s5x; - a2y = s4y+s5y; - a3x = s4x-s5x; - a3y = s4y-s5y; - a4x = s2x-s3x; - a4y = s2y-s3y; - a->ptr.p_double[aoffset0] = q0x; - a->ptr.p_double[aoffset0+1] = q0y; - a->ptr.p_double[aoffset2] = a1x*twx-a1y*twy; - a->ptr.p_double[aoffset2+1] = a1x*twy+a1y*twx; - a->ptr.p_double[aoffset4] = a2x*tw2x-a2y*tw2y; - a->ptr.p_double[aoffset4+1] = a2x*tw2y+a2y*tw2x; - a->ptr.p_double[aoffset6] = a3x*tw3x-a3y*tw3y; - a->ptr.p_double[aoffset6+1] = a3x*tw3y+a3y*tw3x; - a->ptr.p_double[aoffset8] = a4x*tw4x-a4y*tw4y; - a->ptr.p_double[aoffset8+1] = a4x*tw4y+a4y*tw4x; - aoffset0 = aoffset0+2; - aoffset2 = aoffset2+2; - aoffset4 = aoffset4+2; - aoffset6 = aoffset6+2; - aoffset8 = aoffset8+2; - if( (mvidx+1)%ftbase_updatetw==0 ) - { - v = -2*ae_pi*(mvidx+1)/(n*m); - twxm1 = ae_sin(0.5*v, _state); - twxm1 = -2*twxm1*twxm1; - twy = ae_sin(v, _state); - twx = twxm1+1; - } - else - { - v = twxm1+tw0+twxm1*tw0-twy*tw1; - twy = twy+tw1+twxm1*tw1+twy*tw0; - twxm1 = v; - twx = v+1; - } - } - } - return; - } - if( n==6 ) - { - c1 = ae_cos(2*ae_pi/3, _state)-1; - c2 = ae_sin(2*ae_pi/3, _state); - c3 = ae_cos(-ae_pi/3, _state); - c4 = ae_sin(-ae_pi/3, _state); - v = -2*ae_pi/(n*m); - tw0 = -2*ae_sqr(ae_sin(0.5*v, _state), _state); - tw1 = ae_sin(v, _state); - for(opidx=0; opidx<=operandscnt-1; opidx++) - { - aoffset0 = offs+opidx*operandsize*microvectorsize; - aoffset2 = aoffset0+microvectorsize; - aoffset4 = aoffset2+microvectorsize; - aoffset6 = aoffset4+microvectorsize; - aoffset8 = aoffset6+microvectorsize; - aoffset10 = aoffset8+microvectorsize; - twx = 1.0; - twxm1 = 0.0; - twy = 0.0; - for(mvidx=0; mvidx<=m-1; mvidx++) - { - a0x = a->ptr.p_double[aoffset0+0]; - a0y = a->ptr.p_double[aoffset0+1]; - a1x = a->ptr.p_double[aoffset2+0]; - a1y = a->ptr.p_double[aoffset2+1]; - a2x = a->ptr.p_double[aoffset4+0]; - a2y = a->ptr.p_double[aoffset4+1]; - a3x = a->ptr.p_double[aoffset6+0]; - a3y = a->ptr.p_double[aoffset6+1]; - a4x = a->ptr.p_double[aoffset8+0]; - a4y = a->ptr.p_double[aoffset8+1]; - a5x = a->ptr.p_double[aoffset10+0]; - a5y = a->ptr.p_double[aoffset10+1]; - v0 = a0x; - v1 = a0y; - a0x = a0x+a3x; - a0y = a0y+a3y; - a3x = v0-a3x; - a3y = v1-a3y; - v0 = a1x; - v1 = a1y; - a1x = a1x+a4x; - a1y = a1y+a4y; - a4x = v0-a4x; - a4y = v1-a4y; - v0 = a2x; - v1 = a2y; - a2x = a2x+a5x; - a2y = a2y+a5y; - a5x = v0-a5x; - a5y = v1-a5y; - t4x = a4x*c3-a4y*c4; - t4y = a4x*c4+a4y*c3; - a4x = t4x; - a4y = t4y; - t5x = -a5x*c3-a5y*c4; - t5y = a5x*c4-a5y*c3; - a5x = t5x; - a5y = t5y; - t1x = a1x+a2x; - t1y = a1y+a2y; - a0x = a0x+t1x; - a0y = a0y+t1y; - m1x = c1*t1x; - m1y = c1*t1y; - m2x = c2*(a1y-a2y); - m2y = c2*(a2x-a1x); - s1x = a0x+m1x; - s1y = a0y+m1y; - a1x = s1x+m2x; - a1y = s1y+m2y; - a2x = s1x-m2x; - a2y = s1y-m2y; - t1x = a4x+a5x; - t1y = a4y+a5y; - a3x = a3x+t1x; - a3y = a3y+t1y; - m1x = c1*t1x; - m1y = c1*t1y; - m2x = c2*(a4y-a5y); - m2y = c2*(a5x-a4x); - s1x = a3x+m1x; - s1y = a3y+m1y; - a4x = s1x+m2x; - a4y = s1y+m2y; - a5x = s1x-m2x; - a5y = s1y-m2y; - tw2x = twx*twx-twy*twy; - tw2y = 2*twx*twy; - tw3x = twx*tw2x-twy*tw2y; - tw3y = twx*tw2y+twy*tw2x; - tw4x = tw2x*tw2x-tw2y*tw2y; - tw4y = 2*tw2x*tw2y; - tw5x = tw3x*tw2x-tw3y*tw2y; - tw5y = tw3x*tw2y+tw3y*tw2x; - a->ptr.p_double[aoffset0+0] = a0x; - a->ptr.p_double[aoffset0+1] = a0y; - a->ptr.p_double[aoffset2+0] = a3x*twx-a3y*twy; - a->ptr.p_double[aoffset2+1] = a3y*twx+a3x*twy; - a->ptr.p_double[aoffset4+0] = a1x*tw2x-a1y*tw2y; - a->ptr.p_double[aoffset4+1] = a1y*tw2x+a1x*tw2y; - a->ptr.p_double[aoffset6+0] = a4x*tw3x-a4y*tw3y; - a->ptr.p_double[aoffset6+1] = a4y*tw3x+a4x*tw3y; - a->ptr.p_double[aoffset8+0] = a2x*tw4x-a2y*tw4y; - a->ptr.p_double[aoffset8+1] = a2y*tw4x+a2x*tw4y; - a->ptr.p_double[aoffset10+0] = a5x*tw5x-a5y*tw5y; - a->ptr.p_double[aoffset10+1] = a5y*tw5x+a5x*tw5y; - aoffset0 = aoffset0+2; - aoffset2 = aoffset2+2; - aoffset4 = aoffset4+2; - aoffset6 = aoffset6+2; - aoffset8 = aoffset8+2; - aoffset10 = aoffset10+2; - if( (mvidx+1)%ftbase_updatetw==0 ) - { - v = -2*ae_pi*(mvidx+1)/(n*m); - twxm1 = ae_sin(0.5*v, _state); - twxm1 = -2*twxm1*twxm1; - twy = ae_sin(v, _state); - twx = twxm1+1; - } - else - { - v = twxm1+tw0+twxm1*tw0-twy*tw1; - twy = twy+tw1+twxm1*tw1+twy*tw0; - twxm1 = v; - twx = v+1; - } - } - } - return; - } -} - - -/************************************************************************* -This subroutine precomputes data for complex Bluestein's FFT and writes -them to array PrecR[] at specified offset. It is responsibility of the -caller to make sure that PrecR[] is large enough. - -INPUT PARAMETERS: - N - original size of the transform - M - size of the "padded" Bluestein's transform - PrecR - preallocated array - Offs - offset - -OUTPUT PARAMETERS: - PrecR - data at Offs:Offs+4*M-1 are modified: - * PrecR[Offs:Offs+2*M-1] stores Z[k]=exp(i*pi*k^2/N) - * PrecR[Offs+2*M:Offs+4*M-1] stores FFT of the Z - Other parts of PrecR are unchanged. - -NOTE: this function performs internal M-point FFT. It allocates temporary - plan which is destroyed after leaving this function. - - -- ALGLIB -- - Copyright 08.05.2013 by Bochkanov Sergey -*************************************************************************/ -static void ftbase_ftprecomputebluesteinsfft(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* precr, - ae_int_t offs, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - double bx; - double by; - fasttransformplan plan; - - ae_frame_make(_state, &_frame_block); - memset(&plan, 0, sizeof(plan)); - _fasttransformplan_init(&plan, _state, ae_true); - - - /* - * Fill first half of PrecR with b[k] = exp(i*pi*k^2/N) - */ - for(i=0; i<=2*m-1; i++) - { - precr->ptr.p_double[offs+i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - bx = ae_cos(ae_pi/n*i*i, _state); - by = ae_sin(ae_pi/n*i*i, _state); - precr->ptr.p_double[offs+2*i+0] = bx; - precr->ptr.p_double[offs+2*i+1] = by; - precr->ptr.p_double[offs+2*((m-i)%m)+0] = bx; - precr->ptr.p_double[offs+2*((m-i)%m)+1] = by; - } - - /* - * Precomputed FFT - */ - ftcomplexfftplan(m, 1, &plan, _state); - for(i=0; i<=2*m-1; i++) - { - precr->ptr.p_double[offs+2*m+i] = precr->ptr.p_double[offs+i]; - } - ftbase_ftapplysubplan(&plan, 0, precr, offs+2*m, 0, &plan.buffer, 1, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This subroutine applies complex Bluestein's FFT to input/output array A. - -INPUT PARAMETERS: - Plan - transformation plan - A - array, must be large enough for plan to work - ABase - base offset in array A, this value points to start of - subarray whose length is equal to length of the plan - AOffset - offset with respect to ABase, 0<=AOffsetptr.p_double[p0+0]; - y = a->ptr.p_double[p0+1]; - bx = plan->precr.ptr.p_double[p1+0]; - by = -plan->precr.ptr.p_double[p1+1]; - bufa->ptr.p_double[2*i+0] = x*bx-y*by; - bufa->ptr.p_double[2*i+1] = x*by+y*bx; - p0 = p0+2; - p1 = p1+2; - } - for(i=2*n; i<=2*m-1; i++) - { - bufa->ptr.p_double[i] = (double)(0); - } - - /* - * Perform convolution of A and Z (using precomputed - * FFT of Z stored in Plan structure). - */ - ftbase_ftapplysubplan(plan, subplan, bufa, 0, 0, bufc, 1, _state); - p0 = 0; - p1 = precoffs+2*m; - for(i=0; i<=m-1; i++) - { - ax = bufa->ptr.p_double[p0+0]; - ay = bufa->ptr.p_double[p0+1]; - bx = plan->precr.ptr.p_double[p1+0]; - by = plan->precr.ptr.p_double[p1+1]; - bufa->ptr.p_double[p0+0] = ax*bx-ay*by; - bufa->ptr.p_double[p0+1] = -(ax*by+ay*bx); - p0 = p0+2; - p1 = p1+2; - } - ftbase_ftapplysubplan(plan, subplan, bufa, 0, 0, bufc, 1, _state); - - /* - * Post processing: - * A:=conj(Z)*conj(A)/M - * Here conj(A)/M corresponds to last stage of inverse DFT, - * and conj(Z) comes from Bluestein's FFT algorithm. - */ - p0 = precoffs; - p1 = 0; - p2 = abase+aoffset+op*2*n; - for(i=0; i<=n-1; i++) - { - bx = plan->precr.ptr.p_double[p0+0]; - by = plan->precr.ptr.p_double[p0+1]; - rx = bufa->ptr.p_double[p1+0]/m; - ry = -bufa->ptr.p_double[p1+1]/m; - a->ptr.p_double[p2+0] = rx*bx-ry*(-by); - a->ptr.p_double[p2+1] = rx*(-by)+ry*bx; - p0 = p0+2; - p1 = p1+2; - p2 = p2+2; - } - } -} - - -/************************************************************************* -This subroutine precomputes data for complex Rader's FFT and writes them -to array PrecR[] at specified offset. It is responsibility of the caller -to make sure that PrecR[] is large enough. - -INPUT PARAMETERS: - N - original size of the transform (before reduction to N-1) - RQ - primitive root modulo N - RIQ - inverse of primitive root modulo N - PrecR - preallocated array - Offs - offset - -OUTPUT PARAMETERS: - PrecR - data at Offs:Offs+2*(N-1)-1 store FFT of Rader's factors, - other parts of PrecR are unchanged. - -NOTE: this function performs internal (N-1)-point FFT. It allocates temporary - plan which is destroyed after leaving this function. - - -- ALGLIB -- - Copyright 08.05.2013 by Bochkanov Sergey -*************************************************************************/ -static void ftbase_ftprecomputeradersfft(ae_int_t n, - ae_int_t rq, - ae_int_t riq, - /* Real */ ae_vector* precr, - ae_int_t offs, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t q; - fasttransformplan plan; - ae_int_t kiq; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&plan, 0, sizeof(plan)); - _fasttransformplan_init(&plan, _state, ae_true); - - - /* - * Fill PrecR with Rader factors, perform FFT - */ - kiq = 1; - for(q=0; q<=n-2; q++) - { - v = -2*ae_pi*kiq/n; - precr->ptr.p_double[offs+2*q+0] = ae_cos(v, _state); - precr->ptr.p_double[offs+2*q+1] = ae_sin(v, _state); - kiq = kiq*riq%n; - } - ftcomplexfftplan(n-1, 1, &plan, _state); - ftbase_ftapplysubplan(&plan, 0, precr, offs, 0, &plan.buffer, 1, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This subroutine applies complex Rader's FFT to input/output array A. - -INPUT PARAMETERS: - A - array, must be large enough for plan to work - ABase - base offset in array A, this value points to start of - subarray whose length is equal to length of the plan - AOffset - offset with respect to ABase, 0<=AOffset=1, "FTApplyComplexRefFFT: OperandsCnt<1", _state); - - /* - * Process operands - */ - for(opidx=0; opidx<=operandscnt-1; opidx++) - { - - /* - * fill QA - */ - kq = 1; - p0 = abase+aoffset+opidx*n*2; - p1 = aoffset+opidx*n*2; - rx = a->ptr.p_double[p0+0]; - ry = a->ptr.p_double[p0+1]; - x0 = rx; - y0 = ry; - for(q=0; q<=n-2; q++) - { - ax = a->ptr.p_double[p0+2*kq+0]; - ay = a->ptr.p_double[p0+2*kq+1]; - buf->ptr.p_double[p1+0] = ax; - buf->ptr.p_double[p1+1] = ay; - rx = rx+ax; - ry = ry+ay; - kq = kq*rq%n; - p1 = p1+2; - } - p0 = abase+aoffset+opidx*n*2; - p1 = aoffset+opidx*n*2; - for(q=0; q<=n-2; q++) - { - a->ptr.p_double[p0] = buf->ptr.p_double[p1]; - a->ptr.p_double[p0+1] = buf->ptr.p_double[p1+1]; - p0 = p0+2; - p1 = p1+2; - } - - /* - * Convolution - */ - ftbase_ftapplysubplan(plan, subplan, a, abase, aoffset+opidx*n*2, buf, 1, _state); - p0 = abase+aoffset+opidx*n*2; - p1 = precoffs; - for(i=0; i<=n-2; i++) - { - ax = a->ptr.p_double[p0+0]; - ay = a->ptr.p_double[p0+1]; - bx = plan->precr.ptr.p_double[p1+0]; - by = plan->precr.ptr.p_double[p1+1]; - a->ptr.p_double[p0+0] = ax*bx-ay*by; - a->ptr.p_double[p0+1] = -(ax*by+ay*bx); - p0 = p0+2; - p1 = p1+2; - } - ftbase_ftapplysubplan(plan, subplan, a, abase, aoffset+opidx*n*2, buf, 1, _state); - p0 = abase+aoffset+opidx*n*2; - for(i=0; i<=n-2; i++) - { - a->ptr.p_double[p0+0] = a->ptr.p_double[p0+0]/(n-1); - a->ptr.p_double[p0+1] = -a->ptr.p_double[p0+1]/(n-1); - p0 = p0+2; - } - - /* - * Result - */ - buf->ptr.p_double[aoffset+opidx*n*2+0] = rx; - buf->ptr.p_double[aoffset+opidx*n*2+1] = ry; - kiq = 1; - p0 = aoffset+opidx*n*2; - p1 = abase+aoffset+opidx*n*2; - for(q=0; q<=n-2; q++) - { - buf->ptr.p_double[p0+2*kiq+0] = x0+a->ptr.p_double[p1+0]; - buf->ptr.p_double[p0+2*kiq+1] = y0+a->ptr.p_double[p1+1]; - kiq = kiq*riq%n; - p1 = p1+2; - } - p0 = abase+aoffset+opidx*n*2; - p1 = aoffset+opidx*n*2; - for(q=0; q<=n-1; q++) - { - a->ptr.p_double[p0] = buf->ptr.p_double[p1]; - a->ptr.p_double[p0+1] = buf->ptr.p_double[p1+1]; - p0 = p0+2; - p1 = p1+2; - } - } -} - - -/************************************************************************* -Factorizes task size N into product of two smaller sizes N1 and N2 - -INPUT PARAMETERS: - N - task size, N>0 - IsRoot - whether taks is root task (first one in a sequence) - -OUTPUT PARAMETERS: - N1, N2 - such numbers that: - * for prime N: N1=N2=0 - * for composite N<=MaxRadix: N1=N2=0 - * for composite N>MaxRadix: 1<=N1<=N2, N1*N2=N - - -- ALGLIB -- - Copyright 08.04.2013 by Bochkanov Sergey -*************************************************************************/ -static void ftbase_ftfactorize(ae_int_t n, - ae_bool isroot, - ae_int_t* n1, - ae_int_t* n2, - ae_state *_state) -{ - ae_int_t j; - ae_int_t k; - - *n1 = 0; - *n2 = 0; - - ae_assert(n>0, "FTFactorize: N<=0", _state); - *n1 = 0; - *n2 = 0; - - /* - * Small N - */ - if( n<=ftbase_maxradix ) - { - return; - } - - /* - * Large N, recursive split - */ - if( n>ftbase_recursivethreshold ) - { - k = ae_iceil(ae_sqrt((double)(n), _state), _state)+1; - ae_assert(k*k>=n, "FTFactorize: internal error during recursive factorization", _state); - for(j=k; j>=2; j--) - { - if( n%j==0 ) - { - *n1 = ae_minint(n/j, j, _state); - *n2 = ae_maxint(n/j, j, _state); - return; - } - } - } - - /* - * N>MaxRadix, try to find good codelet - */ - for(j=ftbase_maxradix; j>=2; j--) - { - if( n%j==0 ) - { - *n1 = j; - *n2 = n/j; - break; - } - } - - /* - * In case no good codelet was found, - * try to factorize N into product of ANY primes. - */ - if( *n1*(*n2)!=n ) - { - for(j=2; j<=n-1; j++) - { - if( n%j==0 ) - { - *n1 = j; - *n2 = n/j; - break; - } - if( j*j>n ) - { - break; - } - } - } - - /* - * normalize - */ - if( *n1>(*n2) ) - { - j = *n1; - *n1 = *n2; - *n2 = j; - } -} - - -/************************************************************************* -Returns optimistic estimate of the FFT cost, in UNITs (1 UNIT = 100 KFLOPs) - -INPUT PARAMETERS: - N - task size, N>0 - -RESULU: - cost in UNITs, rounded down to nearest integer - -NOTE: If FFT cost is less than 1 UNIT, it will return 0 as result. - - -- ALGLIB -- - Copyright 08.04.2013 by Bochkanov Sergey -*************************************************************************/ -static ae_int_t ftbase_ftoptimisticestimate(ae_int_t n, ae_state *_state) -{ - ae_int_t result; - - - ae_assert(n>0, "FTOptimisticEstimate: N<=0", _state); - result = ae_ifloor(1.0E-5*5*n*ae_log((double)(n), _state)/ae_log((double)(2), _state), _state); - return result; -} - - -/************************************************************************* -Twiddle factors calculation - - -- ALGLIB -- - Copyright 01.05.2009 by Bochkanov Sergey -*************************************************************************/ -static void ftbase_ffttwcalc(/* Real */ ae_vector* a, - ae_int_t aoffset, - ae_int_t n1, - ae_int_t n2, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j2; - ae_int_t n; - ae_int_t halfn1; - ae_int_t offs; - double x; - double y; - double twxm1; - double twy; - double twbasexm1; - double twbasey; - double twrowxm1; - double twrowy; - double tmpx; - double tmpy; - double v; - ae_int_t updatetw2; - - - - /* - * Multiplication by twiddle factors for complex Cooley-Tukey FFT - * with N factorized as N1*N2. - * - * Naive solution to this problem is given below: - * - * > for K:=1 to N2-1 do - * > for J:=1 to N1-1 do - * > begin - * > Idx:=K*N1+J; - * > X:=A[AOffset+2*Idx+0]; - * > Y:=A[AOffset+2*Idx+1]; - * > TwX:=Cos(-2*Pi()*K*J/(N1*N2)); - * > TwY:=Sin(-2*Pi()*K*J/(N1*N2)); - * > A[AOffset+2*Idx+0]:=X*TwX-Y*TwY; - * > A[AOffset+2*Idx+1]:=X*TwY+Y*TwX; - * > end; - * - * However, there are exist more efficient solutions. - * - * Each pass of the inner cycle corresponds to multiplication of one - * entry of A by W[k,j]=exp(-I*2*pi*k*j/N). This factor can be rewritten - * as exp(-I*2*pi*k/N)^j. So we can replace costly exponentiation by - * repeated multiplication: W[k,j+1]=W[k,j]*exp(-I*2*pi*k/N), with - * second factor being computed once in the beginning of the iteration. - * - * Also, exp(-I*2*pi*k/N) can be represented as exp(-I*2*pi/N)^k, i.e. - * we have W[K+1,1]=W[K,1]*W[1,1]. - * - * In our loop we use following variables: - * * [TwBaseXM1,TwBaseY] = [cos(2*pi/N)-1, sin(2*pi/N)] - * * [TwRowXM1, TwRowY] = [cos(2*pi*I/N)-1, sin(2*pi*I/N)] - * * [TwXM1, TwY] = [cos(2*pi*I*J/N)-1, sin(2*pi*I*J/N)] - * - * Meaning of the variables: - * * [TwXM1,TwY] is current twiddle factor W[I,J] - * * [TwRowXM1, TwRowY] is W[I,1] - * * [TwBaseXM1,TwBaseY] is W[1,1] - * - * During inner loop we multiply current twiddle factor by W[I,1], - * during outer loop we update W[I,1]. - * - */ - ae_assert(ftbase_updatetw>=2, "FFTTwCalc: internal error - UpdateTw<2", _state); - updatetw2 = ftbase_updatetw/2; - halfn1 = n1/2; - n = n1*n2; - v = -2*ae_pi/n; - twbasexm1 = -2*ae_sqr(ae_sin(0.5*v, _state), _state); - twbasey = ae_sin(v, _state); - twrowxm1 = (double)(0); - twrowy = (double)(0); - offs = aoffset; - for(i=0; i<=n2-1; i++) - { - - /* - * Initialize twiddle factor for current row - */ - twxm1 = (double)(0); - twy = (double)(0); - - /* - * N1-point block is separated into 2-point chunks and residual 1-point chunk - * (in case N1 is odd). Unrolled loop is several times faster. - */ - for(j2=0; j2<=halfn1-1; j2++) - { - - /* - * Processing: - * * process first element in a chunk. - * * update twiddle factor (unconditional update) - * * process second element - * * conditional update of the twiddle factor - */ - x = a->ptr.p_double[offs+0]; - y = a->ptr.p_double[offs+1]; - tmpx = x*(1+twxm1)-y*twy; - tmpy = x*twy+y*(1+twxm1); - a->ptr.p_double[offs+0] = tmpx; - a->ptr.p_double[offs+1] = tmpy; - tmpx = (1+twxm1)*twrowxm1-twy*twrowy; - twy = twy+(1+twxm1)*twrowy+twy*twrowxm1; - twxm1 = twxm1+tmpx; - x = a->ptr.p_double[offs+2]; - y = a->ptr.p_double[offs+3]; - tmpx = x*(1+twxm1)-y*twy; - tmpy = x*twy+y*(1+twxm1); - a->ptr.p_double[offs+2] = tmpx; - a->ptr.p_double[offs+3] = tmpy; - offs = offs+4; - if( (j2+1)%updatetw2==0&&j2ptr.p_double[offs+0]; - y = a->ptr.p_double[offs+1]; - tmpx = x*(1+twxm1)-y*twy; - tmpy = x*twy+y*(1+twxm1); - a->ptr.p_double[offs+0] = tmpx; - a->ptr.p_double[offs+1] = tmpy; - offs = offs+2; - } - - /* - * update TwRow: TwRow(new) = TwRow(old)*TwBase - */ - if( iptr.p_double[astart], 1, &buf->ptr.p_double[0], 1, ae_v_len(astart,astart+2*m*n-1)); -} - - -/************************************************************************* -Recurrent subroutine for a InternalComplexLinTranspose - -Write A^T to B, where: -* A is m*n complex matrix stored in array A as pairs of real/image values, - beginning from AStart position, with AStride stride -* B is n*m complex matrix stored in array B as pairs of real/image values, - beginning from BStart position, with BStride stride -stride is measured in complex numbers, i.e. in real/image pairs. - - -- ALGLIB -- - Copyright 01.05.2009 by Bochkanov Sergey -*************************************************************************/ -static void ftbase_ffticltrec(/* Real */ ae_vector* a, - ae_int_t astart, - ae_int_t astride, - /* Real */ ae_vector* b, - ae_int_t bstart, - ae_int_t bstride, - ae_int_t m, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t idx1; - ae_int_t idx2; - ae_int_t m2; - ae_int_t m1; - ae_int_t n1; - - - if( m==0||n==0 ) - { - return; - } - if( ae_maxint(m, n, _state)<=8 ) - { - m2 = 2*bstride; - for(i=0; i<=m-1; i++) - { - idx1 = bstart+2*i; - idx2 = astart+2*i*astride; - for(j=0; j<=n-1; j++) - { - b->ptr.p_double[idx1+0] = a->ptr.p_double[idx2+0]; - b->ptr.p_double[idx1+1] = a->ptr.p_double[idx2+1]; - idx1 = idx1+m2; - idx2 = idx2+2; - } - } - return; - } - if( n>m ) - { - - /* - * New partition: - * - * "A^T -> B" becomes "(A1 A2)^T -> ( B1 ) - * ( B2 ) - */ - n1 = n/2; - if( n-n1>=8&&n1%8!=0 ) - { - n1 = n1+(8-n1%8); - } - ae_assert(n-n1>0, "Assertion failed", _state); - ftbase_ffticltrec(a, astart, astride, b, bstart, bstride, m, n1, _state); - ftbase_ffticltrec(a, astart+2*n1, astride, b, bstart+2*n1*bstride, bstride, m, n-n1, _state); - } - else - { - - /* - * New partition: - * - * "A^T -> B" becomes "( A1 )^T -> ( B1 B2 ) - * ( A2 ) - */ - m1 = m/2; - if( m-m1>=8&&m1%8!=0 ) - { - m1 = m1+(8-m1%8); - } - ae_assert(m-m1>0, "Assertion failed", _state); - ftbase_ffticltrec(a, astart, astride, b, bstart, bstride, m1, n, _state); - ftbase_ffticltrec(a, astart+2*m1*astride, astride, b, bstart+2*m1, bstride, m-m1, n, _state); - } -} - - -/************************************************************************* -Recurrent subroutine for a InternalRealLinTranspose - - - -- ALGLIB -- - Copyright 01.05.2009 by Bochkanov Sergey -*************************************************************************/ -static void ftbase_fftirltrec(/* Real */ ae_vector* a, - ae_int_t astart, - ae_int_t astride, - /* Real */ ae_vector* b, - ae_int_t bstart, - ae_int_t bstride, - ae_int_t m, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t idx1; - ae_int_t idx2; - ae_int_t m1; - ae_int_t n1; - - - if( m==0||n==0 ) - { - return; - } - if( ae_maxint(m, n, _state)<=8 ) - { - for(i=0; i<=m-1; i++) - { - idx1 = bstart+i; - idx2 = astart+i*astride; - for(j=0; j<=n-1; j++) - { - b->ptr.p_double[idx1] = a->ptr.p_double[idx2]; - idx1 = idx1+bstride; - idx2 = idx2+1; - } - } - return; - } - if( n>m ) - { - - /* - * New partition: - * - * "A^T -> B" becomes "(A1 A2)^T -> ( B1 ) - * ( B2 ) - */ - n1 = n/2; - if( n-n1>=8&&n1%8!=0 ) - { - n1 = n1+(8-n1%8); - } - ae_assert(n-n1>0, "Assertion failed", _state); - ftbase_fftirltrec(a, astart, astride, b, bstart, bstride, m, n1, _state); - ftbase_fftirltrec(a, astart+n1, astride, b, bstart+n1*bstride, bstride, m, n-n1, _state); - } - else - { - - /* - * New partition: - * - * "A^T -> B" becomes "( A1 )^T -> ( B1 B2 ) - * ( A2 ) - */ - m1 = m/2; - if( m-m1>=8&&m1%8!=0 ) - { - m1 = m1+(8-m1%8); - } - ae_assert(m-m1>0, "Assertion failed", _state); - ftbase_fftirltrec(a, astart, astride, b, bstart, bstride, m1, n, _state); - ftbase_fftirltrec(a, astart+m1*astride, astride, b, bstart+m1, bstride, m-m1, n, _state); - } -} - - -/************************************************************************* -recurrent subroutine for FFTFindSmoothRec - - -- ALGLIB -- - Copyright 01.05.2009 by Bochkanov Sergey -*************************************************************************/ -static void ftbase_ftbasefindsmoothrec(ae_int_t n, - ae_int_t seed, - ae_int_t leastfactor, - ae_int_t* best, - ae_state *_state) -{ - - - ae_assert(ftbase_ftbasemaxsmoothfactor<=5, "FTBaseFindSmoothRec: internal error!", _state); - if( seed>=n ) - { - *best = ae_minint(*best, seed, _state); - return; - } - if( leastfactor<=2 ) - { - ftbase_ftbasefindsmoothrec(n, seed*2, 2, best, _state); - } - if( leastfactor<=3 ) - { - ftbase_ftbasefindsmoothrec(n, seed*3, 3, best, _state); - } - if( leastfactor<=5 ) - { - ftbase_ftbasefindsmoothrec(n, seed*5, 5, best, _state); - } -} - - -void _fasttransformplan_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - fasttransformplan *p = (fasttransformplan*)_p; - ae_touch_ptr((void*)p); - ae_matrix_init(&p->entries, 0, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->buffer, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->precr, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->preci, 0, DT_REAL, _state, make_automatic); - ae_shared_pool_init(&p->bluesteinpool, _state, make_automatic); -} - - -void _fasttransformplan_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - fasttransformplan *dst = (fasttransformplan*)_dst; - fasttransformplan *src = (fasttransformplan*)_src; - ae_matrix_init_copy(&dst->entries, &src->entries, _state, make_automatic); - ae_vector_init_copy(&dst->buffer, &src->buffer, _state, make_automatic); - ae_vector_init_copy(&dst->precr, &src->precr, _state, make_automatic); - ae_vector_init_copy(&dst->preci, &src->preci, _state, make_automatic); - ae_shared_pool_init_copy(&dst->bluesteinpool, &src->bluesteinpool, _state, make_automatic); -} - - -void _fasttransformplan_clear(void* _p) -{ - fasttransformplan *p = (fasttransformplan*)_p; - ae_touch_ptr((void*)p); - ae_matrix_clear(&p->entries); - ae_vector_clear(&p->buffer); - ae_vector_clear(&p->precr); - ae_vector_clear(&p->preci); - ae_shared_pool_clear(&p->bluesteinpool); -} - - -void _fasttransformplan_destroy(void* _p) -{ - fasttransformplan *p = (fasttransformplan*)_p; - ae_touch_ptr((void*)p); - ae_matrix_destroy(&p->entries); - ae_vector_destroy(&p->buffer); - ae_vector_destroy(&p->precr); - ae_vector_destroy(&p->preci); - ae_shared_pool_destroy(&p->bluesteinpool); -} - - -#endif -#if defined(AE_COMPILE_NEARUNITYUNIT) || !defined(AE_PARTIAL_BUILD) - - -double nulog1p(double x, ae_state *_state) -{ - double z; - double lp; - double lq; - double result; - - - z = 1.0+x; - if( ae_fp_less(z,0.70710678118654752440)||ae_fp_greater(z,1.41421356237309504880) ) - { - result = ae_log(z, _state); - return result; - } - z = x*x; - lp = 4.5270000862445199635215E-5; - lp = lp*x+4.9854102823193375972212E-1; - lp = lp*x+6.5787325942061044846969E0; - lp = lp*x+2.9911919328553073277375E1; - lp = lp*x+6.0949667980987787057556E1; - lp = lp*x+5.7112963590585538103336E1; - lp = lp*x+2.0039553499201281259648E1; - lq = 1.0000000000000000000000E0; - lq = lq*x+1.5062909083469192043167E1; - lq = lq*x+8.3047565967967209469434E1; - lq = lq*x+2.2176239823732856465394E2; - lq = lq*x+3.0909872225312059774938E2; - lq = lq*x+2.1642788614495947685003E2; - lq = lq*x+6.0118660497603843919306E1; - z = -0.5*z+x*(z*lp/lq); - result = x+z; - return result; -} - - -double nuexpm1(double x, ae_state *_state) -{ - double r; - double xx; - double ep; - double eq; - double result; - - - if( ae_fp_less(x,-0.5)||ae_fp_greater(x,0.5) ) - { - result = ae_exp(x, _state)-1.0; - return result; - } - xx = x*x; - ep = 1.2617719307481059087798E-4; - ep = ep*xx+3.0299440770744196129956E-2; - ep = ep*xx+9.9999999999999999991025E-1; - eq = 3.0019850513866445504159E-6; - eq = eq*xx+2.5244834034968410419224E-3; - eq = eq*xx+2.2726554820815502876593E-1; - eq = eq*xx+2.0000000000000000000897E0; - r = x*ep; - r = r/(eq-r); - result = r+r; - return result; -} - - -double nucosm1(double x, ae_state *_state) -{ - double xx; - double c; - double result; - - - if( ae_fp_less(x,-0.25*ae_pi)||ae_fp_greater(x,0.25*ae_pi) ) - { - result = ae_cos(x, _state)-1; - return result; - } - xx = x*x; - c = 4.7377507964246204691685E-14; - c = c*xx-1.1470284843425359765671E-11; - c = c*xx+2.0876754287081521758361E-9; - c = c*xx-2.7557319214999787979814E-7; - c = c*xx+2.4801587301570552304991E-5; - c = c*xx-1.3888888888888872993737E-3; - c = c*xx+4.1666666666666666609054E-2; - result = -0.5*xx+xx*xx*c; - return result; -} - - -#endif -#if defined(AE_COMPILE_ALGLIBBASICS) || !defined(AE_PARTIAL_BUILD) - - -#endif - -} - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/alglibinternal.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/alglibinternal.h deleted file mode 100644 index c305402..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/alglibinternal.h +++ /dev/null @@ -1,1749 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifndef _alglibinternal_pkg_h -#define _alglibinternal_pkg_h -#include "ap.h" - - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (DATATYPES) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_SCODES) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_APSERV) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_vector ba0; - ae_vector ia0; - ae_vector ia1; - ae_vector ia2; - ae_vector ia3; - ae_vector ra0; - ae_vector ra1; - ae_vector ra2; - ae_vector ra3; - ae_matrix rm0; - ae_matrix rm1; -} apbuffers; -typedef struct -{ - ae_bool val; -} sboolean; -typedef struct -{ - ae_vector val; -} sbooleanarray; -typedef struct -{ - ae_int_t val; -} sinteger; -typedef struct -{ - ae_vector val; -} sintegerarray; -typedef struct -{ - double val; -} sreal; -typedef struct -{ - ae_vector val; -} srealarray; -typedef struct -{ - ae_complex val; -} scomplex; -typedef struct -{ - ae_vector val; -} scomplexarray; -#endif -#if defined(AE_COMPILE_TSORT) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_ABLASF) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_ABLASMKL) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_CREFLECTIONS) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_ROTATIONS) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_TRLINSOLVE) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_SAFESOLVE) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_HBLAS) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_SBLAS) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_BLAS) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_LINMIN) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_bool brackt; - ae_bool stage1; - ae_int_t infoc; - double dg; - double dgm; - double dginit; - double dgtest; - double dgx; - double dgxm; - double dgy; - double dgym; - double finit; - double ftest1; - double fm; - double fx; - double fxm; - double fy; - double fym; - double stx; - double sty; - double stmin; - double stmax; - double width; - double width1; - double xtrapf; -} linminstate; -typedef struct -{ - ae_bool needf; - ae_vector x; - double f; - ae_int_t n; - ae_vector xbase; - ae_vector s; - double stplen; - double fcur; - double stpmax; - ae_int_t fmax; - ae_int_t nfev; - ae_int_t info; - rcommstate rstate; -} armijostate; -#endif -#if defined(AE_COMPILE_XBLAS) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_BASICSTATOPS) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_HPCCORES) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t chunksize; - ae_int_t ntotal; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_vector batch4buf; - ae_vector hpcbuf; - ae_matrix xy; - ae_matrix xy2; - ae_vector xyrow; - ae_vector x; - ae_vector y; - ae_vector desiredy; - double e; - ae_vector g; - ae_vector tmp0; -} mlpbuffers; -#endif -#if defined(AE_COMPILE_NTHEORY) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_FTBASE) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_matrix entries; - ae_vector buffer; - ae_vector precr; - ae_vector preci; - ae_shared_pool bluesteinpool; -} fasttransformplan; -#endif -#if defined(AE_COMPILE_NEARUNITYUNIT) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_ALGLIBBASICS) || !defined(AE_PARTIAL_BUILD) -#endif - -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - - -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (FUNCTIONS) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_SCODES) || !defined(AE_PARTIAL_BUILD) -ae_int_t getrdfserializationcode(ae_state *_state); -ae_int_t getkdtreeserializationcode(ae_state *_state); -ae_int_t getmlpserializationcode(ae_state *_state); -ae_int_t getmlpeserializationcode(ae_state *_state); -ae_int_t getrbfserializationcode(ae_state *_state); -ae_int_t getspline2dserializationcode(ae_state *_state); -ae_int_t getidwserializationcode(ae_state *_state); -ae_int_t getknnserializationcode(ae_state *_state); -#endif -#if defined(AE_COMPILE_APSERV) || !defined(AE_PARTIAL_BUILD) -void seterrorflagdiff(ae_bool* flag, - double val, - double refval, - double tol, - double s, - ae_state *_state); -ae_bool alwaysfalse(ae_state *_state); -void touchint(ae_int_t* a, ae_state *_state); -void touchreal(double* a, ae_state *_state); -double coalesce(double a, double b, ae_state *_state); -ae_int_t coalescei(ae_int_t a, ae_int_t b, ae_state *_state); -double inttoreal(ae_int_t a, ae_state *_state); -double logbase2(double x, ae_state *_state); -ae_bool approxequal(double a, double b, double tol, ae_state *_state); -ae_bool approxequalrel(double a, double b, double tol, ae_state *_state); -void taskgenint1d(double a, - double b, - ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void taskgenint1dequidist(double a, - double b, - ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void taskgenint1dcheb1(double a, - double b, - ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void taskgenint1dcheb2(double a, - double b, - ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -ae_bool aredistinct(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state); -ae_bool aresameboolean(ae_bool v1, ae_bool v2, ae_state *_state); -void setlengthzero(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state); -void bvectorsetlengthatleast(/* Boolean */ ae_vector* x, - ae_int_t n, - ae_state *_state); -void ivectorsetlengthatleast(/* Integer */ ae_vector* x, - ae_int_t n, - ae_state *_state); -void rvectorsetlengthatleast(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state); -void rmatrixsetlengthatleast(/* Real */ ae_matrix* x, - ae_int_t m, - ae_int_t n, - ae_state *_state); -void bmatrixsetlengthatleast(/* Boolean */ ae_matrix* x, - ae_int_t m, - ae_int_t n, - ae_state *_state); -void bvectorgrowto(/* Boolean */ ae_vector* x, - ae_int_t n, - ae_state *_state); -void ivectorgrowto(/* Integer */ ae_vector* x, - ae_int_t n, - ae_state *_state); -void rmatrixgrowrowsto(/* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t mincols, - ae_state *_state); -void rmatrixgrowcolsto(/* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t minrows, - ae_state *_state); -void rvectorgrowto(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state); -void ivectorresize(/* Integer */ ae_vector* x, - ae_int_t n, - ae_state *_state); -void rvectorresize(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state); -void rmatrixresize(/* Real */ ae_matrix* x, - ae_int_t m, - ae_int_t n, - ae_state *_state); -void imatrixresize(/* Integer */ ae_matrix* x, - ae_int_t m, - ae_int_t n, - ae_state *_state); -void ivectorappend(/* Integer */ ae_vector* x, - ae_int_t v, - ae_state *_state); -ae_bool isfinitevector(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state); -ae_bool isfinitecvector(/* Complex */ ae_vector* z, - ae_int_t n, - ae_state *_state); -ae_bool apservisfinitematrix(/* Real */ ae_matrix* x, - ae_int_t m, - ae_int_t n, - ae_state *_state); -ae_bool apservisfinitecmatrix(/* Complex */ ae_matrix* x, - ae_int_t m, - ae_int_t n, - ae_state *_state); -ae_bool isfinitertrmatrix(/* Real */ ae_matrix* x, - ae_int_t n, - ae_bool isupper, - ae_state *_state); -ae_bool apservisfinitectrmatrix(/* Complex */ ae_matrix* x, - ae_int_t n, - ae_bool isupper, - ae_state *_state); -ae_bool apservisfiniteornanmatrix(/* Real */ ae_matrix* x, - ae_int_t m, - ae_int_t n, - ae_state *_state); -double safepythag2(double x, double y, ae_state *_state); -double safepythag3(double x, double y, double z, ae_state *_state); -ae_int_t saferdiv(double x, double y, double* r, ae_state *_state); -double safeminposrv(double x, double y, double v, ae_state *_state); -void apperiodicmap(double* x, - double a, - double b, - double* k, - ae_state *_state); -double randomnormal(ae_state *_state); -void randomunit(ae_int_t n, /* Real */ ae_vector* x, ae_state *_state); -void swapi(ae_int_t* v0, ae_int_t* v1, ae_state *_state); -void swapr(double* v0, double* v1, ae_state *_state); -void swaprows(/* Real */ ae_matrix* a, - ae_int_t i0, - ae_int_t i1, - ae_int_t ncols, - ae_state *_state); -void swapcols(/* Real */ ae_matrix* a, - ae_int_t j0, - ae_int_t j1, - ae_int_t nrows, - ae_state *_state); -void swapentries(/* Real */ ae_vector* a, - ae_int_t i0, - ae_int_t i1, - ae_int_t entrywidth, - ae_state *_state); -void swapelements(/* Real */ ae_vector* a, - ae_int_t i0, - ae_int_t i1, - ae_state *_state); -void swapelementsi(/* Integer */ ae_vector* a, - ae_int_t i0, - ae_int_t i1, - ae_state *_state); -double maxreal3(double v0, double v1, double v2, ae_state *_state); -void inc(ae_int_t* v, ae_state *_state); -void dec(ae_int_t* v, ae_state *_state); -void threadunsafeinc(ae_int_t* v, ae_state *_state); -void threadunsafeincby(ae_int_t* v, ae_int_t k, ae_state *_state); -void countdown(ae_int_t* v, ae_state *_state); -double possign(double x, ae_state *_state); -double rmul2(double v0, double v1, ae_state *_state); -double rmul3(double v0, double v1, double v2, ae_state *_state); -ae_int_t idivup(ae_int_t a, ae_int_t b, ae_state *_state); -ae_int_t imin2(ae_int_t i0, ae_int_t i1, ae_state *_state); -ae_int_t imin3(ae_int_t i0, ae_int_t i1, ae_int_t i2, ae_state *_state); -ae_int_t imax2(ae_int_t i0, ae_int_t i1, ae_state *_state); -ae_int_t imax3(ae_int_t i0, ae_int_t i1, ae_int_t i2, ae_state *_state); -double rmax3(double r0, double r1, double r2, ae_state *_state); -double rmaxabs3(double r0, double r1, double r2, ae_state *_state); -double boundval(double x, double b1, double b2, ae_state *_state); -ae_int_t iboundval(ae_int_t x, ae_int_t b1, ae_int_t b2, ae_state *_state); -double rboundval(double x, double b1, double b2, ae_state *_state); -ae_int_t countnz1(/* Real */ ae_vector* v, - ae_int_t n, - ae_state *_state); -ae_int_t countnz2(/* Real */ ae_matrix* v, - ae_int_t m, - ae_int_t n, - ae_state *_state); -void alloccomplex(ae_serializer* s, ae_complex v, ae_state *_state); -void serializecomplex(ae_serializer* s, ae_complex v, ae_state *_state); -ae_complex unserializecomplex(ae_serializer* s, ae_state *_state); -void allocrealarray(ae_serializer* s, - /* Real */ ae_vector* v, - ae_int_t n, - ae_state *_state); -void serializerealarray(ae_serializer* s, - /* Real */ ae_vector* v, - ae_int_t n, - ae_state *_state); -void unserializerealarray(ae_serializer* s, - /* Real */ ae_vector* v, - ae_state *_state); -void allocintegerarray(ae_serializer* s, - /* Integer */ ae_vector* v, - ae_int_t n, - ae_state *_state); -void serializeintegerarray(ae_serializer* s, - /* Integer */ ae_vector* v, - ae_int_t n, - ae_state *_state); -void unserializeintegerarray(ae_serializer* s, - /* Integer */ ae_vector* v, - ae_state *_state); -void allocrealmatrix(ae_serializer* s, - /* Real */ ae_matrix* v, - ae_int_t n0, - ae_int_t n1, - ae_state *_state); -void serializerealmatrix(ae_serializer* s, - /* Real */ ae_matrix* v, - ae_int_t n0, - ae_int_t n1, - ae_state *_state); -void unserializerealmatrix(ae_serializer* s, - /* Real */ ae_matrix* v, - ae_state *_state); -void copybooleanarray(/* Boolean */ ae_vector* src, - /* Boolean */ ae_vector* dst, - ae_state *_state); -void copyintegerarray(/* Integer */ ae_vector* src, - /* Integer */ ae_vector* dst, - ae_state *_state); -void copyrealarray(/* Real */ ae_vector* src, - /* Real */ ae_vector* dst, - ae_state *_state); -void copyrealmatrix(/* Real */ ae_matrix* src, - /* Real */ ae_matrix* dst, - ae_state *_state); -void unsetintegerarray(/* Integer */ ae_vector* a, ae_state *_state); -void unsetrealarray(/* Real */ ae_vector* a, ae_state *_state); -void unsetrealmatrix(/* Real */ ae_matrix* a, ae_state *_state); -void tiledsplit(ae_int_t tasksize, - ae_int_t tilesize, - ae_int_t* task0, - ae_int_t* task1, - ae_state *_state); -ae_int_t recsearch(/* Integer */ ae_vector* a, - ae_int_t nrec, - ae_int_t nheader, - ae_int_t i0, - ae_int_t i1, - /* Integer */ ae_vector* b, - ae_state *_state); -void splitlengtheven(ae_int_t tasksize, - ae_int_t* task0, - ae_int_t* task1, - ae_state *_state); -ae_int_t chunkscount(ae_int_t tasksize, - ae_int_t chunksize, - ae_state *_state); -double sparselevel2density(ae_state *_state); -ae_int_t matrixtilesizea(ae_state *_state); -ae_int_t matrixtilesizeb(ae_state *_state); -double smpactivationlevel(ae_state *_state); -double spawnlevel(ae_state *_state); -void splitlength(ae_int_t tasksize, - ae_int_t chunksize, - ae_int_t* task0, - ae_int_t* task1, - ae_state *_state); -void tracevectorautoprec(/* Real */ ae_vector* a, - ae_int_t i0, - ae_int_t i1, - ae_state *_state); -void tracevectorunscaledunshiftedautoprec(/* Real */ ae_vector* x, - ae_int_t n, - /* Real */ ae_vector* scl, - ae_bool applyscl, - /* Real */ ae_vector* sft, - ae_bool applysft, - ae_state *_state); -void tracerownrm1autoprec(/* Real */ ae_matrix* a, - ae_int_t i0, - ae_int_t i1, - ae_int_t j0, - ae_int_t j1, - ae_state *_state); -void tracevectore6(/* Real */ ae_vector* a, - ae_int_t i0, - ae_int_t i1, - ae_state *_state); -void tracevectore615(/* Real */ ae_vector* a, - ae_int_t i0, - ae_int_t i1, - ae_bool usee15, - ae_state *_state); -void tracerownrm1e6(/* Real */ ae_matrix* a, - ae_int_t i0, - ae_int_t i1, - ae_int_t j0, - ae_int_t j1, - ae_state *_state); -void _apbuffers_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _apbuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _apbuffers_clear(void* _p); -void _apbuffers_destroy(void* _p); -void _sboolean_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _sboolean_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _sboolean_clear(void* _p); -void _sboolean_destroy(void* _p); -void _sbooleanarray_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _sbooleanarray_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _sbooleanarray_clear(void* _p); -void _sbooleanarray_destroy(void* _p); -void _sinteger_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _sinteger_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _sinteger_clear(void* _p); -void _sinteger_destroy(void* _p); -void _sintegerarray_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _sintegerarray_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _sintegerarray_clear(void* _p); -void _sintegerarray_destroy(void* _p); -void _sreal_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _sreal_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _sreal_clear(void* _p); -void _sreal_destroy(void* _p); -void _srealarray_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _srealarray_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _srealarray_clear(void* _p); -void _srealarray_destroy(void* _p); -void _scomplex_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _scomplex_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _scomplex_clear(void* _p); -void _scomplex_destroy(void* _p); -void _scomplexarray_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _scomplexarray_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _scomplexarray_clear(void* _p); -void _scomplexarray_destroy(void* _p); -#endif -#if defined(AE_COMPILE_TSORT) || !defined(AE_PARTIAL_BUILD) -void tagsort(/* Real */ ae_vector* a, - ae_int_t n, - /* Integer */ ae_vector* p1, - /* Integer */ ae_vector* p2, - ae_state *_state); -void tagsortbuf(/* Real */ ae_vector* a, - ae_int_t n, - /* Integer */ ae_vector* p1, - /* Integer */ ae_vector* p2, - apbuffers* buf, - ae_state *_state); -void tagsortfasti(/* Real */ ae_vector* a, - /* Integer */ ae_vector* b, - /* Real */ ae_vector* bufa, - /* Integer */ ae_vector* bufb, - ae_int_t n, - ae_state *_state); -void tagsortfastr(/* Real */ ae_vector* a, - /* Real */ ae_vector* b, - /* Real */ ae_vector* bufa, - /* Real */ ae_vector* bufb, - ae_int_t n, - ae_state *_state); -void tagsortfast(/* Real */ ae_vector* a, - /* Real */ ae_vector* bufa, - ae_int_t n, - ae_state *_state); -void tagsortmiddleir(/* Integer */ ae_vector* a, - /* Real */ ae_vector* b, - ae_int_t offset, - ae_int_t n, - ae_state *_state); -void tagsortmiddlei(/* Integer */ ae_vector* a, - ae_int_t offset, - ae_int_t n, - ae_state *_state); -void sortmiddlei(/* Integer */ ae_vector* a, - ae_int_t offset, - ae_int_t n, - ae_state *_state); -void tagheappushi(/* Real */ ae_vector* a, - /* Integer */ ae_vector* b, - ae_int_t* n, - double va, - ae_int_t vb, - ae_state *_state); -void tagheapreplacetopi(/* Real */ ae_vector* a, - /* Integer */ ae_vector* b, - ae_int_t n, - double va, - ae_int_t vb, - ae_state *_state); -void tagheappopi(/* Real */ ae_vector* a, - /* Integer */ ae_vector* b, - ae_int_t* n, - ae_state *_state); -ae_int_t lowerbound(/* Real */ ae_vector* a, - ae_int_t n, - double t, - ae_state *_state); -ae_int_t upperbound(/* Real */ ae_vector* a, - ae_int_t n, - double t, - ae_state *_state); -#endif -#if defined(AE_COMPILE_ABLASF) || !defined(AE_PARTIAL_BUILD) -double rdotv(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -double rdotvr(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_matrix* a, - ae_int_t i, - ae_state *_state); -double rdotrr(ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_state *_state); -double rdotv2(ae_int_t n, /* Real */ ae_vector* x, ae_state *_state); -void raddv(ae_int_t n, - double alpha, - /* Real */ ae_vector* y, - /* Real */ ae_vector* x, - ae_state *_state); -void raddvx(ae_int_t n, - double alpha, - /* Real */ ae_vector* y, - ae_int_t offsy, - /* Real */ ae_vector* x, - ae_int_t offsx, - ae_state *_state); -void raddvc(ae_int_t n, - double alpha, - /* Real */ ae_vector* y, - /* Real */ ae_matrix* x, - ae_int_t colidx, - ae_state *_state); -void raddvr(ae_int_t n, - double alpha, - /* Real */ ae_vector* y, - /* Real */ ae_matrix* x, - ae_int_t rowidx, - ae_state *_state); -void rmergemulvr(ae_int_t n, - /* Real */ ae_vector* y, - /* Real */ ae_matrix* x, - ae_int_t rowidx, - ae_state *_state); -void rmergemaxrv(ae_int_t n, - /* Real */ ae_matrix* x, - ae_int_t rowidx, - /* Real */ ae_vector* y, - ae_state *_state); -void raddrv(ae_int_t n, - double alpha, - /* Real */ ae_matrix* y, - ae_int_t ridx, - /* Real */ ae_vector* x, - ae_state *_state); -void rmulv(ae_int_t n, - double v, - /* Real */ ae_vector* x, - ae_state *_state); -void rmulr(ae_int_t n, - double v, - /* Real */ ae_matrix* x, - ae_int_t rowidx, - ae_state *_state); -void rmulvx(ae_int_t n, - double v, - /* Real */ ae_vector* x, - ae_int_t offsx, - ae_state *_state); -double rmaxabsv(ae_int_t n, /* Real */ ae_vector* x, ae_state *_state); -void rsetv(ae_int_t n, - double v, - /* Real */ ae_vector* x, - ae_state *_state); -void rsetvx(ae_int_t n, - double v, - /* Real */ ae_vector* x, - ae_int_t offsx, - ae_state *_state); -void isetv(ae_int_t n, - ae_int_t v, - /* Integer */ ae_vector* x, - ae_state *_state); -void bsetv(ae_int_t n, - ae_bool v, - /* Boolean */ ae_vector* x, - ae_state *_state); -void rsetm(ae_int_t m, - ae_int_t n, - double v, - /* Real */ ae_matrix* a, - ae_state *_state); -void rsetallocv(ae_int_t n, - double v, - /* Real */ ae_vector* x, - ae_state *_state); -void rsetallocm(ae_int_t m, - ae_int_t n, - double v, - /* Real */ ae_matrix* a, - ae_state *_state); -void rallocv(ae_int_t n, /* Real */ ae_vector* x, ae_state *_state); -void ballocv(ae_int_t n, /* Boolean */ ae_vector* x, ae_state *_state); -void rallocm(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_state *_state); -void isetallocv(ae_int_t n, - ae_int_t v, - /* Integer */ ae_vector* x, - ae_state *_state); -void bsetallocv(ae_int_t n, - ae_bool v, - /* Boolean */ ae_vector* x, - ae_state *_state); -void rsetr(ae_int_t n, - double v, - /* Real */ ae_matrix* a, - ae_int_t i, - ae_state *_state); -void rsetc(ae_int_t n, - double v, - /* Real */ ae_matrix* a, - ae_int_t j, - ae_state *_state); -void rcopyv(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void bcopyv(ae_int_t n, - /* Boolean */ ae_vector* x, - /* Boolean */ ae_vector* y, - ae_state *_state); -void rcopyvx(ae_int_t n, - /* Real */ ae_vector* x, - ae_int_t offsx, - /* Real */ ae_vector* y, - ae_int_t offsy, - ae_state *_state); -void rcopyallocv(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void rcopyallocm(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* x, - /* Real */ ae_matrix* y, - ae_state *_state); -void icopyallocv(ae_int_t n, - /* Integer */ ae_vector* x, - /* Integer */ ae_vector* y, - ae_state *_state); -void bcopyallocv(ae_int_t n, - /* Boolean */ ae_vector* x, - /* Boolean */ ae_vector* y, - ae_state *_state); -void icopyv(ae_int_t n, - /* Integer */ ae_vector* x, - /* Integer */ ae_vector* y, - ae_state *_state); -void icopyvx(ae_int_t n, - /* Integer */ ae_vector* x, - ae_int_t offsx, - /* Integer */ ae_vector* y, - ae_int_t offsy, - ae_state *_state); -void igrowv(ae_int_t newn, /* Integer */ ae_vector* x, ae_state *_state); -void rcopymulv(ae_int_t n, - double v, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void rcopymulvr(ae_int_t n, - double v, - /* Real */ ae_vector* x, - /* Real */ ae_matrix* y, - ae_int_t ridx, - ae_state *_state); -void rcopyvr(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_matrix* a, - ae_int_t i, - ae_state *_state); -void rcopyrv(ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i, - /* Real */ ae_vector* x, - ae_state *_state); -void rcopyrr(ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i, - /* Real */ ae_matrix* b, - ae_int_t k, - ae_state *_state); -void rcopyvc(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_matrix* a, - ae_int_t j, - ae_state *_state); -void rcopycv(ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t j, - /* Real */ ae_vector* x, - ae_state *_state); -ae_bool rmatrixgerf(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - double ralpha, - /* Real */ ae_vector* u, - ae_int_t iu, - /* Real */ ae_vector* v, - ae_int_t iv, - ae_state *_state); -ae_bool cmatrixrank1f(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Complex */ ae_vector* u, - ae_int_t iu, - /* Complex */ ae_vector* v, - ae_int_t iv, - ae_state *_state); -ae_bool rmatrixrank1f(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Real */ ae_vector* u, - ae_int_t iu, - /* Real */ ae_vector* v, - ae_int_t iv, - ae_state *_state); -ae_bool cmatrixrighttrsmf(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state); -ae_bool cmatrixlefttrsmf(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state); -ae_bool rmatrixrighttrsmf(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state); -ae_bool rmatrixlefttrsmf(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state); -ae_bool cmatrixherkf(ae_int_t n, - ae_int_t k, - double alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state); -ae_bool rmatrixsyrkf(ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state); -ae_bool rmatrixgemmf(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state); -ae_bool cmatrixgemmf(ae_int_t m, - ae_int_t n, - ae_int_t k, - ae_complex alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Complex */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - ae_complex beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state); -void cmatrixgemmk(ae_int_t m, - ae_int_t n, - ae_int_t k, - ae_complex alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Complex */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - ae_complex beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state); -void rmatrixgemmk(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state); -void rmatrixgemmk44v00(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state); -void rmatrixgemmk44v01(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state); -void rmatrixgemmk44v10(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state); -void rmatrixgemmk44v11(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state); -#endif -#if defined(AE_COMPILE_ABLASMKL) || !defined(AE_PARTIAL_BUILD) -ae_bool rmatrixgermkl(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - double alpha, - /* Real */ ae_vector* u, - ae_int_t iu, - /* Real */ ae_vector* v, - ae_int_t iv, - ae_state *_state); -ae_bool cmatrixrank1mkl(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Complex */ ae_vector* u, - ae_int_t iu, - /* Complex */ ae_vector* v, - ae_int_t iv, - ae_state *_state); -ae_bool rmatrixrank1mkl(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Real */ ae_vector* u, - ae_int_t iu, - /* Real */ ae_vector* v, - ae_int_t iv, - ae_state *_state); -ae_bool cmatrixmvmkl(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t opa, - /* Complex */ ae_vector* x, - ae_int_t ix, - /* Complex */ ae_vector* y, - ae_int_t iy, - ae_state *_state); -ae_bool rmatrixmvmkl(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t opa, - /* Real */ ae_vector* x, - ae_int_t ix, - /* Real */ ae_vector* y, - ae_int_t iy, - ae_state *_state); -ae_bool rmatrixgemvmkl(ae_int_t m, - ae_int_t n, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t opa, - /* Real */ ae_vector* x, - ae_int_t ix, - double beta, - /* Real */ ae_vector* y, - ae_int_t iy, - ae_state *_state); -ae_bool rmatrixtrsvmkl(ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_vector* x, - ae_int_t ix, - ae_state *_state); -ae_bool rmatrixsyrkmkl(ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state); -ae_bool cmatrixherkmkl(ae_int_t n, - ae_int_t k, - double alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state); -ae_bool rmatrixgemmmkl(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state); -ae_bool rmatrixsymvmkl(ae_int_t n, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_bool isupper, - /* Real */ ae_vector* x, - ae_int_t ix, - double beta, - /* Real */ ae_vector* y, - ae_int_t iy, - ae_state *_state); -ae_bool cmatrixgemmmkl(ae_int_t m, - ae_int_t n, - ae_int_t k, - ae_complex alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Complex */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - ae_complex beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state); -ae_bool cmatrixlefttrsmmkl(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state); -ae_bool cmatrixrighttrsmmkl(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state); -ae_bool rmatrixlefttrsmmkl(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state); -ae_bool rmatrixrighttrsmmkl(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state); -ae_bool spdmatrixcholeskymkl(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - ae_bool* cholresult, - ae_state *_state); -ae_bool rmatrixplumkl(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - ae_state *_state); -ae_bool rmatrixbdmkl(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* d, - /* Real */ ae_vector* e, - /* Real */ ae_vector* tauq, - /* Real */ ae_vector* taup, - ae_state *_state); -ae_bool rmatrixbdmultiplybymkl(/* Real */ ae_matrix* qp, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* tauq, - /* Real */ ae_vector* taup, - /* Real */ ae_matrix* z, - ae_int_t zrows, - ae_int_t zcolumns, - ae_bool byq, - ae_bool fromtheright, - ae_bool dotranspose, - ae_state *_state); -ae_bool rmatrixhessenbergmkl(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_vector* tau, - ae_state *_state); -ae_bool rmatrixhessenbergunpackqmkl(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_vector* tau, - /* Real */ ae_matrix* q, - ae_state *_state); -ae_bool smatrixtdmkl(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* tau, - /* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_state *_state); -ae_bool smatrixtdunpackqmkl(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* tau, - /* Real */ ae_matrix* q, - ae_state *_state); -ae_bool hmatrixtdmkl(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* tau, - /* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_state *_state); -ae_bool hmatrixtdunpackqmkl(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* tau, - /* Complex */ ae_matrix* q, - ae_state *_state); -ae_bool rmatrixbdsvdmkl(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_matrix* u, - ae_int_t nru, - /* Real */ ae_matrix* c, - ae_int_t ncc, - /* Real */ ae_matrix* vt, - ae_int_t ncvt, - ae_bool* svdresult, - ae_state *_state); -ae_bool rmatrixinternalschurdecompositionmkl(/* Real */ ae_matrix* h, - ae_int_t n, - ae_int_t tneeded, - ae_int_t zneeded, - /* Real */ ae_vector* wr, - /* Real */ ae_vector* wi, - /* Real */ ae_matrix* z, - ae_int_t* info, - ae_state *_state); -ae_bool rmatrixinternaltrevcmkl(/* Real */ ae_matrix* t, - ae_int_t n, - ae_int_t side, - ae_int_t howmny, - /* Real */ ae_matrix* vl, - /* Real */ ae_matrix* vr, - ae_int_t* m, - ae_int_t* info, - ae_state *_state); -ae_bool smatrixtdevdmkl(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_int_t zneeded, - /* Real */ ae_matrix* z, - ae_bool* evdresult, - ae_state *_state); -ae_bool sparsegemvcrsmkl(ae_int_t opa, - ae_int_t arows, - ae_int_t acols, - double alpha, - /* Real */ ae_vector* vals, - /* Integer */ ae_vector* cidx, - /* Integer */ ae_vector* ridx, - /* Real */ ae_vector* x, - ae_int_t ix, - double beta, - /* Real */ ae_vector* y, - ae_int_t iy, - ae_state *_state); -#endif -#if defined(AE_COMPILE_CREFLECTIONS) || !defined(AE_PARTIAL_BUILD) -void complexgeneratereflection(/* Complex */ ae_vector* x, - ae_int_t n, - ae_complex* tau, - ae_state *_state); -void complexapplyreflectionfromtheleft(/* Complex */ ae_matrix* c, - ae_complex tau, - /* Complex */ ae_vector* v, - ae_int_t m1, - ae_int_t m2, - ae_int_t n1, - ae_int_t n2, - /* Complex */ ae_vector* work, - ae_state *_state); -void complexapplyreflectionfromtheright(/* Complex */ ae_matrix* c, - ae_complex tau, - /* Complex */ ae_vector* v, - ae_int_t m1, - ae_int_t m2, - ae_int_t n1, - ae_int_t n2, - /* Complex */ ae_vector* work, - ae_state *_state); -#endif -#if defined(AE_COMPILE_ROTATIONS) || !defined(AE_PARTIAL_BUILD) -void applyrotationsfromtheleft(ae_bool isforward, - ae_int_t m1, - ae_int_t m2, - ae_int_t n1, - ae_int_t n2, - /* Real */ ae_vector* c, - /* Real */ ae_vector* s, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* work, - ae_state *_state); -void applyrotationsfromtheright(ae_bool isforward, - ae_int_t m1, - ae_int_t m2, - ae_int_t n1, - ae_int_t n2, - /* Real */ ae_vector* c, - /* Real */ ae_vector* s, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* work, - ae_state *_state); -void generaterotation(double f, - double g, - double* cs, - double* sn, - double* r, - ae_state *_state); -#endif -#if defined(AE_COMPILE_TRLINSOLVE) || !defined(AE_PARTIAL_BUILD) -void rmatrixtrsafesolve(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_vector* x, - double* s, - ae_bool isupper, - ae_bool istrans, - ae_bool isunit, - ae_state *_state); -void safesolvetriangular(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_vector* x, - double* s, - ae_bool isupper, - ae_bool istrans, - ae_bool isunit, - ae_bool normin, - /* Real */ ae_vector* cnorm, - ae_state *_state); -#endif -#if defined(AE_COMPILE_SAFESOLVE) || !defined(AE_PARTIAL_BUILD) -ae_bool rmatrixscaledtrsafesolve(/* Real */ ae_matrix* a, - double sa, - ae_int_t n, - /* Real */ ae_vector* x, - ae_bool isupper, - ae_int_t trans, - ae_bool isunit, - double maxgrowth, - ae_state *_state); -ae_bool cmatrixscaledtrsafesolve(/* Complex */ ae_matrix* a, - double sa, - ae_int_t n, - /* Complex */ ae_vector* x, - ae_bool isupper, - ae_int_t trans, - ae_bool isunit, - double maxgrowth, - ae_state *_state); -#endif -#if defined(AE_COMPILE_HBLAS) || !defined(AE_PARTIAL_BUILD) -void hermitianmatrixvectormultiply(/* Complex */ ae_matrix* a, - ae_bool isupper, - ae_int_t i1, - ae_int_t i2, - /* Complex */ ae_vector* x, - ae_complex alpha, - /* Complex */ ae_vector* y, - ae_state *_state); -void hermitianrank2update(/* Complex */ ae_matrix* a, - ae_bool isupper, - ae_int_t i1, - ae_int_t i2, - /* Complex */ ae_vector* x, - /* Complex */ ae_vector* y, - /* Complex */ ae_vector* t, - ae_complex alpha, - ae_state *_state); -#endif -#if defined(AE_COMPILE_SBLAS) || !defined(AE_PARTIAL_BUILD) -void symmetricmatrixvectormultiply(/* Real */ ae_matrix* a, - ae_bool isupper, - ae_int_t i1, - ae_int_t i2, - /* Real */ ae_vector* x, - double alpha, - /* Real */ ae_vector* y, - ae_state *_state); -void symmetricrank2update(/* Real */ ae_matrix* a, - ae_bool isupper, - ae_int_t i1, - ae_int_t i2, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* t, - double alpha, - ae_state *_state); -#endif -#if defined(AE_COMPILE_BLAS) || !defined(AE_PARTIAL_BUILD) -double vectornorm2(/* Real */ ae_vector* x, - ae_int_t i1, - ae_int_t i2, - ae_state *_state); -ae_int_t vectoridxabsmax(/* Real */ ae_vector* x, - ae_int_t i1, - ae_int_t i2, - ae_state *_state); -ae_int_t columnidxabsmax(/* Real */ ae_matrix* x, - ae_int_t i1, - ae_int_t i2, - ae_int_t j, - ae_state *_state); -ae_int_t rowidxabsmax(/* Real */ ae_matrix* x, - ae_int_t j1, - ae_int_t j2, - ae_int_t i, - ae_state *_state); -double upperhessenberg1norm(/* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t i2, - ae_int_t j1, - ae_int_t j2, - /* Real */ ae_vector* work, - ae_state *_state); -void copymatrix(/* Real */ ae_matrix* a, - ae_int_t is1, - ae_int_t is2, - ae_int_t js1, - ae_int_t js2, - /* Real */ ae_matrix* b, - ae_int_t id1, - ae_int_t id2, - ae_int_t jd1, - ae_int_t jd2, - ae_state *_state); -void inplacetranspose(/* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t i2, - ae_int_t j1, - ae_int_t j2, - /* Real */ ae_vector* work, - ae_state *_state); -void copyandtranspose(/* Real */ ae_matrix* a, - ae_int_t is1, - ae_int_t is2, - ae_int_t js1, - ae_int_t js2, - /* Real */ ae_matrix* b, - ae_int_t id1, - ae_int_t id2, - ae_int_t jd1, - ae_int_t jd2, - ae_state *_state); -void matrixvectormultiply(/* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t i2, - ae_int_t j1, - ae_int_t j2, - ae_bool trans, - /* Real */ ae_vector* x, - ae_int_t ix1, - ae_int_t ix2, - double alpha, - /* Real */ ae_vector* y, - ae_int_t iy1, - ae_int_t iy2, - double beta, - ae_state *_state); -double pythag2(double x, double y, ae_state *_state); -void matrixmatrixmultiply(/* Real */ ae_matrix* a, - ae_int_t ai1, - ae_int_t ai2, - ae_int_t aj1, - ae_int_t aj2, - ae_bool transa, - /* Real */ ae_matrix* b, - ae_int_t bi1, - ae_int_t bi2, - ae_int_t bj1, - ae_int_t bj2, - ae_bool transb, - double alpha, - /* Real */ ae_matrix* c, - ae_int_t ci1, - ae_int_t ci2, - ae_int_t cj1, - ae_int_t cj2, - double beta, - /* Real */ ae_vector* work, - ae_state *_state); -#endif -#if defined(AE_COMPILE_LINMIN) || !defined(AE_PARTIAL_BUILD) -void linminnormalized(/* Real */ ae_vector* d, - double* stp, - ae_int_t n, - ae_state *_state); -void mcsrch(ae_int_t n, - /* Real */ ae_vector* x, - double* f, - /* Real */ ae_vector* g, - /* Real */ ae_vector* s, - double* stp, - double stpmax, - double gtol, - ae_int_t* info, - ae_int_t* nfev, - /* Real */ ae_vector* wa, - linminstate* state, - ae_int_t* stage, - ae_state *_state); -void armijocreate(ae_int_t n, - /* Real */ ae_vector* x, - double f, - /* Real */ ae_vector* s, - double stp, - double stpmax, - ae_int_t fmax, - armijostate* state, - ae_state *_state); -ae_bool armijoiteration(armijostate* state, ae_state *_state); -void armijoresults(armijostate* state, - ae_int_t* info, - double* stp, - double* f, - ae_state *_state); -void _linminstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _linminstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _linminstate_clear(void* _p); -void _linminstate_destroy(void* _p); -void _armijostate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _armijostate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _armijostate_clear(void* _p); -void _armijostate_destroy(void* _p); -#endif -#if defined(AE_COMPILE_XBLAS) || !defined(AE_PARTIAL_BUILD) -void xdot(/* Real */ ae_vector* a, - /* Real */ ae_vector* b, - ae_int_t n, - /* Real */ ae_vector* temp, - double* r, - double* rerr, - ae_state *_state); -void xcdot(/* Complex */ ae_vector* a, - /* Complex */ ae_vector* b, - ae_int_t n, - /* Real */ ae_vector* temp, - ae_complex* r, - double* rerr, - ae_state *_state); -#endif -#if defined(AE_COMPILE_BASICSTATOPS) || !defined(AE_PARTIAL_BUILD) -void rankx(/* Real */ ae_vector* x, - ae_int_t n, - ae_bool iscentered, - apbuffers* buf, - ae_state *_state); -void rankxuntied(/* Real */ ae_vector* x, - ae_int_t n, - apbuffers* buf, - ae_state *_state); -#endif -#if defined(AE_COMPILE_HPCCORES) || !defined(AE_PARTIAL_BUILD) -void hpcpreparechunkedgradient(/* Real */ ae_vector* weights, - ae_int_t wcount, - ae_int_t ntotal, - ae_int_t nin, - ae_int_t nout, - mlpbuffers* buf, - ae_state *_state); -void hpcfinalizechunkedgradient(mlpbuffers* buf, - /* Real */ ae_vector* grad, - ae_state *_state); -ae_bool hpcchunkedgradient(/* Real */ ae_vector* weights, - /* Integer */ ae_vector* structinfo, - /* Real */ ae_vector* columnmeans, - /* Real */ ae_vector* columnsigmas, - /* Real */ ae_matrix* xy, - ae_int_t cstart, - ae_int_t csize, - /* Real */ ae_vector* batch4buf, - /* Real */ ae_vector* hpcbuf, - double* e, - ae_bool naturalerrorfunc, - ae_state *_state); -ae_bool hpcchunkedprocess(/* Real */ ae_vector* weights, - /* Integer */ ae_vector* structinfo, - /* Real */ ae_vector* columnmeans, - /* Real */ ae_vector* columnsigmas, - /* Real */ ae_matrix* xy, - ae_int_t cstart, - ae_int_t csize, - /* Real */ ae_vector* batch4buf, - /* Real */ ae_vector* hpcbuf, - ae_state *_state); -void _mlpbuffers_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _mlpbuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _mlpbuffers_clear(void* _p); -void _mlpbuffers_destroy(void* _p); -#endif -#if defined(AE_COMPILE_NTHEORY) || !defined(AE_PARTIAL_BUILD) -void findprimitiverootandinverse(ae_int_t n, - ae_int_t* proot, - ae_int_t* invproot, - ae_state *_state); -#endif -#if defined(AE_COMPILE_FTBASE) || !defined(AE_PARTIAL_BUILD) -void ftcomplexfftplan(ae_int_t n, - ae_int_t k, - fasttransformplan* plan, - ae_state *_state); -void ftapplyplan(fasttransformplan* plan, - /* Real */ ae_vector* a, - ae_int_t offsa, - ae_int_t repcnt, - ae_state *_state); -void ftbasefactorize(ae_int_t n, - ae_int_t tasktype, - ae_int_t* n1, - ae_int_t* n2, - ae_state *_state); -ae_bool ftbaseissmooth(ae_int_t n, ae_state *_state); -ae_int_t ftbasefindsmooth(ae_int_t n, ae_state *_state); -ae_int_t ftbasefindsmootheven(ae_int_t n, ae_state *_state); -double ftbasegetflopestimate(ae_int_t n, ae_state *_state); -void _fasttransformplan_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _fasttransformplan_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _fasttransformplan_clear(void* _p); -void _fasttransformplan_destroy(void* _p); -#endif -#if defined(AE_COMPILE_NEARUNITYUNIT) || !defined(AE_PARTIAL_BUILD) -double nulog1p(double x, ae_state *_state); -double nuexpm1(double x, ae_state *_state); -double nucosm1(double x, ae_state *_state); -#endif -#if defined(AE_COMPILE_ALGLIBBASICS) || !defined(AE_PARTIAL_BUILD) -#endif - -} -#endif - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/alglibmisc.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/alglibmisc.cpp deleted file mode 100644 index ca6097d..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/alglibmisc.cpp +++ /dev/null @@ -1,8754 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifdef _MSC_VER -#define _CRT_SECURE_NO_WARNINGS -#endif -#include "stdafx.h" -#include "alglibmisc.h" - -// disable some irrelevant warnings -#if (AE_COMPILER==AE_MSVC) && !defined(AE_ALL_WARNINGS) -#pragma warning(disable:4100) -#pragma warning(disable:4127) -#pragma warning(disable:4611) -#pragma warning(disable:4702) -#pragma warning(disable:4996) -#endif - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_NEARESTNEIGHBOR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_HQRND) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_XDEBUG) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_NEARESTNEIGHBOR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Buffer object which is used to perform nearest neighbor requests in the -multithreaded mode (multiple threads working with same KD-tree object). - -This object should be created with KDTreeCreateRequestBuffer(). -*************************************************************************/ -_kdtreerequestbuffer_owner::_kdtreerequestbuffer_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_kdtreerequestbuffer_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::kdtreerequestbuffer*)alglib_impl::ae_malloc(sizeof(alglib_impl::kdtreerequestbuffer), &_state); - memset(p_struct, 0, sizeof(alglib_impl::kdtreerequestbuffer)); - alglib_impl::_kdtreerequestbuffer_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_kdtreerequestbuffer_owner::_kdtreerequestbuffer_owner(const _kdtreerequestbuffer_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_kdtreerequestbuffer_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: kdtreerequestbuffer copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::kdtreerequestbuffer*)alglib_impl::ae_malloc(sizeof(alglib_impl::kdtreerequestbuffer), &_state); - memset(p_struct, 0, sizeof(alglib_impl::kdtreerequestbuffer)); - alglib_impl::_kdtreerequestbuffer_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_kdtreerequestbuffer_owner& _kdtreerequestbuffer_owner::operator=(const _kdtreerequestbuffer_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: kdtreerequestbuffer assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: kdtreerequestbuffer assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_kdtreerequestbuffer_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::kdtreerequestbuffer)); - alglib_impl::_kdtreerequestbuffer_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_kdtreerequestbuffer_owner::~_kdtreerequestbuffer_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_kdtreerequestbuffer_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::kdtreerequestbuffer* _kdtreerequestbuffer_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::kdtreerequestbuffer* _kdtreerequestbuffer_owner::c_ptr() const -{ - return const_cast(p_struct); -} -kdtreerequestbuffer::kdtreerequestbuffer() : _kdtreerequestbuffer_owner() -{ -} - -kdtreerequestbuffer::kdtreerequestbuffer(const kdtreerequestbuffer &rhs):_kdtreerequestbuffer_owner(rhs) -{ -} - -kdtreerequestbuffer& kdtreerequestbuffer::operator=(const kdtreerequestbuffer &rhs) -{ - if( this==&rhs ) - return *this; - _kdtreerequestbuffer_owner::operator=(rhs); - return *this; -} - -kdtreerequestbuffer::~kdtreerequestbuffer() -{ -} - - -/************************************************************************* -KD-tree object. -*************************************************************************/ -_kdtree_owner::_kdtree_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_kdtree_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::kdtree*)alglib_impl::ae_malloc(sizeof(alglib_impl::kdtree), &_state); - memset(p_struct, 0, sizeof(alglib_impl::kdtree)); - alglib_impl::_kdtree_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_kdtree_owner::_kdtree_owner(const _kdtree_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_kdtree_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: kdtree copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::kdtree*)alglib_impl::ae_malloc(sizeof(alglib_impl::kdtree), &_state); - memset(p_struct, 0, sizeof(alglib_impl::kdtree)); - alglib_impl::_kdtree_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_kdtree_owner& _kdtree_owner::operator=(const _kdtree_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: kdtree assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: kdtree assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_kdtree_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::kdtree)); - alglib_impl::_kdtree_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_kdtree_owner::~_kdtree_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_kdtree_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::kdtree* _kdtree_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::kdtree* _kdtree_owner::c_ptr() const -{ - return const_cast(p_struct); -} -kdtree::kdtree() : _kdtree_owner() -{ -} - -kdtree::kdtree(const kdtree &rhs):_kdtree_owner(rhs) -{ -} - -kdtree& kdtree::operator=(const kdtree &rhs) -{ - if( this==&rhs ) - return *this; - _kdtree_owner::operator=(rhs); - return *this; -} - -kdtree::~kdtree() -{ -} - - -/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -void kdtreeserialize(kdtree &obj, std::string &s_out) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - alglib_impl::ae_int_t ssize; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_alloc_start(&serializer); - alglib_impl::kdtreealloc(&serializer, obj.c_ptr(), &state); - ssize = alglib_impl::ae_serializer_get_alloc_size(&serializer); - s_out.clear(); - s_out.reserve((size_t)(ssize+1)); - alglib_impl::ae_serializer_sstart_str(&serializer, &s_out); - alglib_impl::kdtreeserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_assert( s_out.length()<=(size_t)ssize, "ALGLIB: serialization integrity error", &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} -/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -void kdtreeunserialize(const std::string &s_in, kdtree &obj) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_ustart_str(&serializer, &s_in); - alglib_impl::kdtreeunserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} - - -/************************************************************************* -This function serializes data structure to C++ stream. - -Data stream generated by this function is same as string representation -generated by string version of serializer - alphanumeric characters, -dots, underscores, minus signs, which are grouped into words separated by -spaces and CR+LF. - -We recommend you to read comments on string version of serializer to find -out more about serialization of AlGLIB objects. -*************************************************************************/ -void kdtreeserialize(kdtree &obj, std::ostream &s_out) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_alloc_start(&serializer); - alglib_impl::kdtreealloc(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_get_alloc_size(&serializer); // not actually needed, but we have to ask - alglib_impl::ae_serializer_sstart_stream(&serializer, &s_out); - alglib_impl::kdtreeserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} -/************************************************************************* -This function unserializes data structure from stream. -*************************************************************************/ -void kdtreeunserialize(const std::istream &s_in, kdtree &obj) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_ustart_stream(&serializer, &s_in); - alglib_impl::kdtreeunserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} - -/************************************************************************* -KD-tree creation - -This subroutine creates KD-tree from set of X-values and optional Y-values - -INPUT PARAMETERS - XY - dataset, array[0..N-1,0..NX+NY-1]. - one row corresponds to one point. - first NX columns contain X-values, next NY (NY may be zero) - columns may contain associated Y-values - N - number of points, N>=0. - NX - space dimension, NX>=1. - NY - number of optional Y-values, NY>=0. - NormType- norm type: - * 0 denotes infinity-norm - * 1 denotes 1-norm - * 2 denotes 2-norm (Euclidean norm) - -OUTPUT PARAMETERS - KDT - KD-tree - - -NOTES - -1. KD-tree creation have O(N*logN) complexity and O(N*(2*NX+NY)) memory - requirements. -2. Although KD-trees may be used with any combination of N and NX, they - are more efficient than brute-force search only when N >> 4^NX. So they - are most useful in low-dimensional tasks (NX=2, NX=3). NX=1 is another - inefficient case, because simple binary search (without additional - structures) is much more efficient in such tasks than KD-trees. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreebuild(const real_2d_array &xy, const ae_int_t n, const ae_int_t nx, const ae_int_t ny, const ae_int_t normtype, kdtree &kdt, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::kdtreebuild(const_cast(xy.c_ptr()), n, nx, ny, normtype, const_cast(kdt.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -KD-tree creation - -This subroutine creates KD-tree from set of X-values and optional Y-values - -INPUT PARAMETERS - XY - dataset, array[0..N-1,0..NX+NY-1]. - one row corresponds to one point. - first NX columns contain X-values, next NY (NY may be zero) - columns may contain associated Y-values - N - number of points, N>=0. - NX - space dimension, NX>=1. - NY - number of optional Y-values, NY>=0. - NormType- norm type: - * 0 denotes infinity-norm - * 1 denotes 1-norm - * 2 denotes 2-norm (Euclidean norm) - -OUTPUT PARAMETERS - KDT - KD-tree - - -NOTES - -1. KD-tree creation have O(N*logN) complexity and O(N*(2*NX+NY)) memory - requirements. -2. Although KD-trees may be used with any combination of N and NX, they - are more efficient than brute-force search only when N >> 4^NX. So they - are most useful in low-dimensional tasks (NX=2, NX=3). NX=1 is another - inefficient case, because simple binary search (without additional - structures) is much more efficient in such tasks than KD-trees. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void kdtreebuild(const real_2d_array &xy, const ae_int_t nx, const ae_int_t ny, const ae_int_t normtype, kdtree &kdt, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = xy.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::kdtreebuild(const_cast(xy.c_ptr()), n, nx, ny, normtype, const_cast(kdt.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -KD-tree creation - -This subroutine creates KD-tree from set of X-values, integer tags and -optional Y-values - -INPUT PARAMETERS - XY - dataset, array[0..N-1,0..NX+NY-1]. - one row corresponds to one point. - first NX columns contain X-values, next NY (NY may be zero) - columns may contain associated Y-values - Tags - tags, array[0..N-1], contains integer tags associated - with points. - N - number of points, N>=0 - NX - space dimension, NX>=1. - NY - number of optional Y-values, NY>=0. - NormType- norm type: - * 0 denotes infinity-norm - * 1 denotes 1-norm - * 2 denotes 2-norm (Euclidean norm) - -OUTPUT PARAMETERS - KDT - KD-tree - -NOTES - -1. KD-tree creation have O(N*logN) complexity and O(N*(2*NX+NY)) memory - requirements. -2. Although KD-trees may be used with any combination of N and NX, they - are more efficient than brute-force search only when N >> 4^NX. So they - are most useful in low-dimensional tasks (NX=2, NX=3). NX=1 is another - inefficient case, because simple binary search (without additional - structures) is much more efficient in such tasks than KD-trees. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreebuildtagged(const real_2d_array &xy, const integer_1d_array &tags, const ae_int_t n, const ae_int_t nx, const ae_int_t ny, const ae_int_t normtype, kdtree &kdt, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::kdtreebuildtagged(const_cast(xy.c_ptr()), const_cast(tags.c_ptr()), n, nx, ny, normtype, const_cast(kdt.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -KD-tree creation - -This subroutine creates KD-tree from set of X-values, integer tags and -optional Y-values - -INPUT PARAMETERS - XY - dataset, array[0..N-1,0..NX+NY-1]. - one row corresponds to one point. - first NX columns contain X-values, next NY (NY may be zero) - columns may contain associated Y-values - Tags - tags, array[0..N-1], contains integer tags associated - with points. - N - number of points, N>=0 - NX - space dimension, NX>=1. - NY - number of optional Y-values, NY>=0. - NormType- norm type: - * 0 denotes infinity-norm - * 1 denotes 1-norm - * 2 denotes 2-norm (Euclidean norm) - -OUTPUT PARAMETERS - KDT - KD-tree - -NOTES - -1. KD-tree creation have O(N*logN) complexity and O(N*(2*NX+NY)) memory - requirements. -2. Although KD-trees may be used with any combination of N and NX, they - are more efficient than brute-force search only when N >> 4^NX. So they - are most useful in low-dimensional tasks (NX=2, NX=3). NX=1 is another - inefficient case, because simple binary search (without additional - structures) is much more efficient in such tasks than KD-trees. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void kdtreebuildtagged(const real_2d_array &xy, const integer_1d_array &tags, const ae_int_t nx, const ae_int_t ny, const ae_int_t normtype, kdtree &kdt, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (xy.rows()!=tags.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'kdtreebuildtagged': looks like one of arguments has wrong size"); - n = xy.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::kdtreebuildtagged(const_cast(xy.c_ptr()), const_cast(tags.c_ptr()), n, nx, ny, normtype, const_cast(kdt.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function creates buffer structure which can be used to perform -parallel KD-tree requests. - -KD-tree subpackage provides two sets of request functions - ones which use -internal buffer of KD-tree object (these functions are single-threaded -because they use same buffer, which can not shared between threads), and -ones which use external buffer. - -This function is used to initialize external buffer. - -INPUT PARAMETERS - KDT - KD-tree which is associated with newly created buffer - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: KD-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use buffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -void kdtreecreaterequestbuffer(const kdtree &kdt, kdtreerequestbuffer &buf, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::kdtreecreaterequestbuffer(const_cast(kdt.c_ptr()), const_cast(buf.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -K-NN query: K nearest neighbors - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: KDTreeTsQueryKNN() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - X - point, array[0..NX-1]. - K - number of neighbors to return, K>=1 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of actual neighbors found (either K or N, if K>N). - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -these results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() to get distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreequeryknn(const kdtree &kdt, const real_1d_array &x, const ae_int_t k, const bool selfmatch, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::kdtreequeryknn(const_cast(kdt.c_ptr()), const_cast(x.c_ptr()), k, selfmatch, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -K-NN query: K nearest neighbors - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: KDTreeTsQueryKNN() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - X - point, array[0..NX-1]. - K - number of neighbors to return, K>=1 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of actual neighbors found (either K or N, if K>N). - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -these results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() to get distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -ae_int_t kdtreequeryknn(const kdtree &kdt, const real_1d_array &x, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - bool selfmatch; - - selfmatch = true; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::kdtreequeryknn(const_cast(kdt.c_ptr()), const_cast(x.c_ptr()), k, selfmatch, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -K-NN query: K nearest neighbors, using external thread-local buffer. - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -INPUT PARAMETERS - KDT - kd-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - K - number of neighbors to return, K>=1 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of actual neighbors found (either K or N, if K>N). - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreetsqueryknn(const kdtree &kdt, const kdtreerequestbuffer &buf, const real_1d_array &x, const ae_int_t k, const bool selfmatch, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::kdtreetsqueryknn(const_cast(kdt.c_ptr()), const_cast(buf.c_ptr()), const_cast(x.c_ptr()), k, selfmatch, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -K-NN query: K nearest neighbors, using external thread-local buffer. - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -INPUT PARAMETERS - KDT - kd-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - K - number of neighbors to return, K>=1 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of actual neighbors found (either K or N, if K>N). - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -ae_int_t kdtreetsqueryknn(const kdtree &kdt, const kdtreerequestbuffer &buf, const real_1d_array &x, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - bool selfmatch; - - selfmatch = true; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::kdtreetsqueryknn(const_cast(kdt.c_ptr()), const_cast(buf.c_ptr()), const_cast(x.c_ptr()), k, selfmatch, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -R-NN query: all points within R-sphere centered at X, ordered by distance -between point and X (by ascending). - -NOTE: it is also possible to perform undordered queries performed by means - of kdtreequeryrnnu() and kdtreetsqueryrnnu() functions. Such queries - are faster because we do not have to use heap structure for sorting. - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: kdtreetsqueryrnn() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -actual results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() to get distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreequeryrnn(const kdtree &kdt, const real_1d_array &x, const double r, const bool selfmatch, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::kdtreequeryrnn(const_cast(kdt.c_ptr()), const_cast(x.c_ptr()), r, selfmatch, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -R-NN query: all points within R-sphere centered at X, ordered by distance -between point and X (by ascending). - -NOTE: it is also possible to perform undordered queries performed by means - of kdtreequeryrnnu() and kdtreetsqueryrnnu() functions. Such queries - are faster because we do not have to use heap structure for sorting. - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: kdtreetsqueryrnn() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -actual results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() to get distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -ae_int_t kdtreequeryrnn(const kdtree &kdt, const real_1d_array &x, const double r, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - bool selfmatch; - - selfmatch = true; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::kdtreequeryrnn(const_cast(kdt.c_ptr()), const_cast(x.c_ptr()), r, selfmatch, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -R-NN query: all points within R-sphere centered at X, no ordering by -distance as undicated by "U" suffix (faster that ordered query, for large -queries - significantly faster). - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: kdtreetsqueryrnn() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -actual results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() to get distances - -As indicated by "U" suffix, this function returns unordered results. - - -- ALGLIB -- - Copyright 01.11.2018 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreequeryrnnu(const kdtree &kdt, const real_1d_array &x, const double r, const bool selfmatch, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::kdtreequeryrnnu(const_cast(kdt.c_ptr()), const_cast(x.c_ptr()), r, selfmatch, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -R-NN query: all points within R-sphere centered at X, no ordering by -distance as undicated by "U" suffix (faster that ordered query, for large -queries - significantly faster). - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: kdtreetsqueryrnn() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -actual results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() to get distances - -As indicated by "U" suffix, this function returns unordered results. - - -- ALGLIB -- - Copyright 01.11.2018 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -ae_int_t kdtreequeryrnnu(const kdtree &kdt, const real_1d_array &x, const double r, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - bool selfmatch; - - selfmatch = true; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::kdtreequeryrnnu(const_cast(kdt.c_ptr()), const_cast(x.c_ptr()), r, selfmatch, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -R-NN query: all points within R-sphere centered at X, using external -thread-local buffer, sorted by distance between point and X (by ascending) - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -NOTE: it is also possible to perform undordered queries performed by means - of kdtreequeryrnnu() and kdtreetsqueryrnnu() functions. Such queries - are faster because we do not have to use heap structure for sorting. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreetsqueryrnn(const kdtree &kdt, const kdtreerequestbuffer &buf, const real_1d_array &x, const double r, const bool selfmatch, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::kdtreetsqueryrnn(const_cast(kdt.c_ptr()), const_cast(buf.c_ptr()), const_cast(x.c_ptr()), r, selfmatch, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -R-NN query: all points within R-sphere centered at X, using external -thread-local buffer, sorted by distance between point and X (by ascending) - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -NOTE: it is also possible to perform undordered queries performed by means - of kdtreequeryrnnu() and kdtreetsqueryrnnu() functions. Such queries - are faster because we do not have to use heap structure for sorting. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -ae_int_t kdtreetsqueryrnn(const kdtree &kdt, const kdtreerequestbuffer &buf, const real_1d_array &x, const double r, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - bool selfmatch; - - selfmatch = true; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::kdtreetsqueryrnn(const_cast(kdt.c_ptr()), const_cast(buf.c_ptr()), const_cast(x.c_ptr()), r, selfmatch, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -R-NN query: all points within R-sphere centered at X, using external -thread-local buffer, no ordering by distance as undicated by "U" suffix -(faster that ordered query, for large queries - significantly faster). - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -As indicated by "U" suffix, this function returns unordered results. - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreetsqueryrnnu(const kdtree &kdt, const kdtreerequestbuffer &buf, const real_1d_array &x, const double r, const bool selfmatch, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::kdtreetsqueryrnnu(const_cast(kdt.c_ptr()), const_cast(buf.c_ptr()), const_cast(x.c_ptr()), r, selfmatch, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -R-NN query: all points within R-sphere centered at X, using external -thread-local buffer, no ordering by distance as undicated by "U" suffix -(faster that ordered query, for large queries - significantly faster). - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -As indicated by "U" suffix, this function returns unordered results. - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -ae_int_t kdtreetsqueryrnnu(const kdtree &kdt, const kdtreerequestbuffer &buf, const real_1d_array &x, const double r, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - bool selfmatch; - - selfmatch = true; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::kdtreetsqueryrnnu(const_cast(kdt.c_ptr()), const_cast(buf.c_ptr()), const_cast(x.c_ptr()), r, selfmatch, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -K-NN query: approximate K nearest neighbors - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: KDTreeTsQueryAKNN() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - X - point, array[0..NX-1]. - K - number of neighbors to return, K>=1 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - Eps - approximation factor, Eps>=0. eps-approximate nearest - neighbor is a neighbor whose distance from X is at - most (1+eps) times distance of true nearest neighbor. - -RESULT - number of actual neighbors found (either K or N, if K>N). - -NOTES - significant performance gain may be achieved only when Eps is is on - the order of magnitude of 1 or larger. - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -these results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() to get distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreequeryaknn(const kdtree &kdt, const real_1d_array &x, const ae_int_t k, const bool selfmatch, const double eps, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::kdtreequeryaknn(const_cast(kdt.c_ptr()), const_cast(x.c_ptr()), k, selfmatch, eps, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -K-NN query: approximate K nearest neighbors - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: KDTreeTsQueryAKNN() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - X - point, array[0..NX-1]. - K - number of neighbors to return, K>=1 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - Eps - approximation factor, Eps>=0. eps-approximate nearest - neighbor is a neighbor whose distance from X is at - most (1+eps) times distance of true nearest neighbor. - -RESULT - number of actual neighbors found (either K or N, if K>N). - -NOTES - significant performance gain may be achieved only when Eps is is on - the order of magnitude of 1 or larger. - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -these results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() to get distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -ae_int_t kdtreequeryaknn(const kdtree &kdt, const real_1d_array &x, const ae_int_t k, const double eps, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - bool selfmatch; - - selfmatch = true; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::kdtreequeryaknn(const_cast(kdt.c_ptr()), const_cast(x.c_ptr()), k, selfmatch, eps, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -K-NN query: approximate K nearest neighbors, using thread-local buffer. - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - K - number of neighbors to return, K>=1 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - Eps - approximation factor, Eps>=0. eps-approximate nearest - neighbor is a neighbor whose distance from X is at - most (1+eps) times distance of true nearest neighbor. - -RESULT - number of actual neighbors found (either K or N, if K>N). - -NOTES - significant performance gain may be achieved only when Eps is is on - the order of magnitude of 1 or larger. - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreetsqueryaknn(const kdtree &kdt, const kdtreerequestbuffer &buf, const real_1d_array &x, const ae_int_t k, const bool selfmatch, const double eps, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::kdtreetsqueryaknn(const_cast(kdt.c_ptr()), const_cast(buf.c_ptr()), const_cast(x.c_ptr()), k, selfmatch, eps, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -K-NN query: approximate K nearest neighbors, using thread-local buffer. - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - K - number of neighbors to return, K>=1 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - Eps - approximation factor, Eps>=0. eps-approximate nearest - neighbor is a neighbor whose distance from X is at - most (1+eps) times distance of true nearest neighbor. - -RESULT - number of actual neighbors found (either K or N, if K>N). - -NOTES - significant performance gain may be achieved only when Eps is is on - the order of magnitude of 1 or larger. - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -ae_int_t kdtreetsqueryaknn(const kdtree &kdt, const kdtreerequestbuffer &buf, const real_1d_array &x, const ae_int_t k, const double eps, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - bool selfmatch; - - selfmatch = true; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::kdtreetsqueryaknn(const_cast(kdt.c_ptr()), const_cast(buf.c_ptr()), const_cast(x.c_ptr()), k, selfmatch, eps, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -Box query: all points within user-specified box. - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: KDTreeTsQueryBox() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - BoxMin - lower bounds, array[0..NX-1]. - BoxMax - upper bounds, array[0..NX-1]. - - -RESULT - number of actual neighbors found (in [0,N]). - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -these results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() returns zeros for this request - -NOTE: this particular query returns unordered results, because there is no - meaningful way of ordering points. Furthermore, no 'distance' is - associated with points - it is either INSIDE or OUTSIDE (so request - for distances will return zeros). - - -- ALGLIB -- - Copyright 14.05.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreequerybox(const kdtree &kdt, const real_1d_array &boxmin, const real_1d_array &boxmax, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::kdtreequerybox(const_cast(kdt.c_ptr()), const_cast(boxmin.c_ptr()), const_cast(boxmax.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Box query: all points within user-specified box, using thread-local buffer. - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - BoxMin - lower bounds, array[0..NX-1]. - BoxMax - upper bounds, array[0..NX-1]. - -RESULT - number of actual neighbors found (in [0,N]). - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "ts" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() returns zeros for this query - -NOTE: this particular query returns unordered results, because there is no - meaningful way of ordering points. Furthermore, no 'distance' is - associated with points - it is either INSIDE or OUTSIDE (so request - for distances will return zeros). - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 14.05.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreetsquerybox(const kdtree &kdt, const kdtreerequestbuffer &buf, const real_1d_array &boxmin, const real_1d_array &boxmax, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::kdtreetsquerybox(const_cast(kdt.c_ptr()), const_cast(buf.c_ptr()), const_cast(boxmin.c_ptr()), const_cast(boxmax.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -X-values from last query. - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - kdtreetsqueryresultsx(). - -INPUT PARAMETERS - KDT - KD-tree - X - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - X - rows are filled with X-values - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsTags() tag values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultsx(const kdtree &kdt, real_2d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::kdtreequeryresultsx(const_cast(kdt.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -X- and Y-values from last query - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - kdtreetsqueryresultsxy(). - -INPUT PARAMETERS - KDT - KD-tree - XY - possibly pre-allocated buffer. If XY is too small to store - result, it is resized. If size(XY) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - XY - rows are filled with points: first NX columns with - X-values, next NY columns - with Y-values. - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsTags() tag values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultsxy(const kdtree &kdt, real_2d_array &xy, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::kdtreequeryresultsxy(const_cast(kdt.c_ptr()), const_cast(xy.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Tags from last query - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - kdtreetsqueryresultstags(). - -INPUT PARAMETERS - KDT - KD-tree - Tags - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - Tags - filled with tags associated with points, - or, when no tags were supplied, with zeros - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultstags(const kdtree &kdt, integer_1d_array &tags, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::kdtreequeryresultstags(const_cast(kdt.c_ptr()), const_cast(tags.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Distances from last query - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - kdtreetsqueryresultsdistances(). - -INPUT PARAMETERS - KDT - KD-tree - R - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - R - filled with distances (in corresponding norm) - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsTags() tag values - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultsdistances(const kdtree &kdt, real_1d_array &r, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::kdtreequeryresultsdistances(const_cast(kdt.c_ptr()), const_cast(r.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -X-values from last query associated with kdtreerequestbuffer object. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure. - X - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - X - rows are filled with X-values - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsTags() tag values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreetsqueryresultsx(const kdtree &kdt, const kdtreerequestbuffer &buf, real_2d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::kdtreetsqueryresultsx(const_cast(kdt.c_ptr()), const_cast(buf.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -X- and Y-values from last query associated with kdtreerequestbuffer object. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure. - XY - possibly pre-allocated buffer. If XY is too small to store - result, it is resized. If size(XY) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - XY - rows are filled with points: first NX columns with - X-values, next NY columns - with Y-values. - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsTags() tag values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreetsqueryresultsxy(const kdtree &kdt, const kdtreerequestbuffer &buf, real_2d_array &xy, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::kdtreetsqueryresultsxy(const_cast(kdt.c_ptr()), const_cast(buf.c_ptr()), const_cast(xy.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Tags from last query associated with kdtreerequestbuffer object. - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - KDTreeTsqueryresultstags(). - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure. - Tags - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - Tags - filled with tags associated with points, - or, when no tags were supplied, with zeros - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreetsqueryresultstags(const kdtree &kdt, const kdtreerequestbuffer &buf, integer_1d_array &tags, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::kdtreetsqueryresultstags(const_cast(kdt.c_ptr()), const_cast(buf.c_ptr()), const_cast(tags.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Distances from last query associated with kdtreerequestbuffer object. - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - KDTreeTsqueryresultsdistances(). - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure. - R - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - R - filled with distances (in corresponding norm) - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsTags() tag values - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreetsqueryresultsdistances(const kdtree &kdt, const kdtreerequestbuffer &buf, real_1d_array &r, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::kdtreetsqueryresultsdistances(const_cast(kdt.c_ptr()), const_cast(buf.c_ptr()), const_cast(r.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -X-values from last query; 'interactive' variant for languages like Python -which support constructs like "X = KDTreeQueryResultsXI(KDT)" and -interactive mode of interpreter. - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultsxi(const kdtree &kdt, real_2d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::kdtreequeryresultsxi(const_cast(kdt.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -XY-values from last query; 'interactive' variant for languages like Python -which support constructs like "XY = KDTreeQueryResultsXYI(KDT)" and -interactive mode of interpreter. - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultsxyi(const kdtree &kdt, real_2d_array &xy, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::kdtreequeryresultsxyi(const_cast(kdt.c_ptr()), const_cast(xy.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Tags from last query; 'interactive' variant for languages like Python -which support constructs like "Tags = KDTreeQueryResultsTagsI(KDT)" and -interactive mode of interpreter. - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultstagsi(const kdtree &kdt, integer_1d_array &tags, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::kdtreequeryresultstagsi(const_cast(kdt.c_ptr()), const_cast(tags.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Distances from last query; 'interactive' variant for languages like Python -which support constructs like "R = KDTreeQueryResultsDistancesI(KDT)" -and interactive mode of interpreter. - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultsdistancesi(const kdtree &kdt, real_1d_array &r, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::kdtreequeryresultsdistancesi(const_cast(kdt.c_ptr()), const_cast(r.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_HQRND) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Portable high quality random number generator state. -Initialized with HQRNDRandomize() or HQRNDSeed(). - -Fields: - S1, S2 - seed values - V - precomputed value - MagicV - 'magic' value used to determine whether State structure - was correctly initialized. -*************************************************************************/ -_hqrndstate_owner::_hqrndstate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_hqrndstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::hqrndstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::hqrndstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::hqrndstate)); - alglib_impl::_hqrndstate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_hqrndstate_owner::_hqrndstate_owner(const _hqrndstate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_hqrndstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: hqrndstate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::hqrndstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::hqrndstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::hqrndstate)); - alglib_impl::_hqrndstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_hqrndstate_owner& _hqrndstate_owner::operator=(const _hqrndstate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: hqrndstate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: hqrndstate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_hqrndstate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::hqrndstate)); - alglib_impl::_hqrndstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_hqrndstate_owner::~_hqrndstate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_hqrndstate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::hqrndstate* _hqrndstate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::hqrndstate* _hqrndstate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -hqrndstate::hqrndstate() : _hqrndstate_owner() -{ -} - -hqrndstate::hqrndstate(const hqrndstate &rhs):_hqrndstate_owner(rhs) -{ -} - -hqrndstate& hqrndstate::operator=(const hqrndstate &rhs) -{ - if( this==&rhs ) - return *this; - _hqrndstate_owner::operator=(rhs); - return *this; -} - -hqrndstate::~hqrndstate() -{ -} - -/************************************************************************* -HQRNDState initialization with random values which come from standard -RNG. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void hqrndrandomize(hqrndstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hqrndrandomize(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -HQRNDState initialization with seed values - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void hqrndseed(const ae_int_t s1, const ae_int_t s2, hqrndstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hqrndseed(s1, s2, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function generates random real number in (0,1), -not including interval boundaries - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -double hqrnduniformr(const hqrndstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::hqrnduniformr(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function generates random integer number in [0, N) - -1. State structure must be initialized with HQRNDRandomize() or HQRNDSeed() -2. N can be any positive number except for very large numbers: - * close to 2^31 on 32-bit systems - * close to 2^62 on 64-bit systems - An exception will be generated if N is too large. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -ae_int_t hqrnduniformi(const hqrndstate &state, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::hqrnduniformi(const_cast(state.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Random number generator: normal numbers - -This function generates one random number from normal distribution. -Its performance is equal to that of HQRNDNormal2() - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -double hqrndnormal(const hqrndstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::hqrndnormal(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Random number generator: vector with random entries (normal distribution) - -This function generates N random numbers from normal distribution. - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void hqrndnormalv(const hqrndstate &state, const ae_int_t n, real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hqrndnormalv(const_cast(state.c_ptr()), n, const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Random number generator: matrix with random entries (normal distribution) - -This function generates MxN random matrix. - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void hqrndnormalm(const hqrndstate &state, const ae_int_t m, const ae_int_t n, real_2d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hqrndnormalm(const_cast(state.c_ptr()), m, n, const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Random number generator: random X and Y such that X^2+Y^2=1 - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void hqrndunit2(const hqrndstate &state, double &x, double &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hqrndunit2(const_cast(state.c_ptr()), &x, &y, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Random number generator: normal numbers - -This function generates two independent random numbers from normal -distribution. Its performance is equal to that of HQRNDNormal() - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void hqrndnormal2(const hqrndstate &state, double &x1, double &x2, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hqrndnormal2(const_cast(state.c_ptr()), &x1, &x2, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Random number generator: exponential distribution - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 11.08.2007 by Bochkanov Sergey -*************************************************************************/ -double hqrndexponential(const hqrndstate &state, const double lambdav, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::hqrndexponential(const_cast(state.c_ptr()), lambdav, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function generates random number from discrete distribution given by -finite sample X. - -INPUT PARAMETERS - State - high quality random number generator, must be - initialized with HQRNDRandomize() or HQRNDSeed(). - X - finite sample - N - number of elements to use, N>=1 - -RESULT - this function returns one of the X[i] for random i=0..N-1 - - -- ALGLIB -- - Copyright 08.11.2011 by Bochkanov Sergey -*************************************************************************/ -double hqrnddiscrete(const hqrndstate &state, const real_1d_array &x, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::hqrnddiscrete(const_cast(state.c_ptr()), const_cast(x.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function generates random number from continuous distribution given -by finite sample X. - -INPUT PARAMETERS - State - high quality random number generator, must be - initialized with HQRNDRandomize() or HQRNDSeed(). - X - finite sample, array[N] (can be larger, in this case only - leading N elements are used). THIS ARRAY MUST BE SORTED BY - ASCENDING. - N - number of elements to use, N>=1 - -RESULT - this function returns random number from continuous distribution which - tries to approximate X as mush as possible. min(X)<=Result<=max(X). - - -- ALGLIB -- - Copyright 08.11.2011 by Bochkanov Sergey -*************************************************************************/ -double hqrndcontinuous(const hqrndstate &state, const real_1d_array &x, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::hqrndcontinuous(const_cast(state.c_ptr()), const_cast(x.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_XDEBUG) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - -*************************************************************************/ -_xdebugrecord1_owner::_xdebugrecord1_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_xdebugrecord1_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::xdebugrecord1*)alglib_impl::ae_malloc(sizeof(alglib_impl::xdebugrecord1), &_state); - memset(p_struct, 0, sizeof(alglib_impl::xdebugrecord1)); - alglib_impl::_xdebugrecord1_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_xdebugrecord1_owner::_xdebugrecord1_owner(const _xdebugrecord1_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_xdebugrecord1_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: xdebugrecord1 copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::xdebugrecord1*)alglib_impl::ae_malloc(sizeof(alglib_impl::xdebugrecord1), &_state); - memset(p_struct, 0, sizeof(alglib_impl::xdebugrecord1)); - alglib_impl::_xdebugrecord1_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_xdebugrecord1_owner& _xdebugrecord1_owner::operator=(const _xdebugrecord1_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: xdebugrecord1 assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: xdebugrecord1 assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_xdebugrecord1_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::xdebugrecord1)); - alglib_impl::_xdebugrecord1_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_xdebugrecord1_owner::~_xdebugrecord1_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_xdebugrecord1_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::xdebugrecord1* _xdebugrecord1_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::xdebugrecord1* _xdebugrecord1_owner::c_ptr() const -{ - return const_cast(p_struct); -} -xdebugrecord1::xdebugrecord1() : _xdebugrecord1_owner() ,i(p_struct->i),c(*((alglib::complex*)(&p_struct->c))),a(&p_struct->a) -{ -} - -xdebugrecord1::xdebugrecord1(const xdebugrecord1 &rhs):_xdebugrecord1_owner(rhs) ,i(p_struct->i),c(*((alglib::complex*)(&p_struct->c))),a(&p_struct->a) -{ -} - -xdebugrecord1& xdebugrecord1::operator=(const xdebugrecord1 &rhs) -{ - if( this==&rhs ) - return *this; - _xdebugrecord1_owner::operator=(rhs); - return *this; -} - -xdebugrecord1::~xdebugrecord1() -{ -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Creates and returns XDebugRecord1 structure: -* integer and complex fields of Rec1 are set to 1 and 1+i correspondingly -* array field of Rec1 is set to [2,3] - - -- ALGLIB -- - Copyright 27.05.2014 by Bochkanov Sergey -*************************************************************************/ -void xdebuginitrecord1(xdebugrecord1 &rec1, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebuginitrecord1(const_cast(rec1.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Counts number of True values in the boolean 1D array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -ae_int_t xdebugb1count(const boolean_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::xdebugb1count(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by NOT(a[i]). -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugb1not(const boolean_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugb1not(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Appends copy of array to itself. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugb1appendcopy(boolean_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugb1appendcopy(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate N-element array with even-numbered elements set to True. -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugb1outeven(const ae_int_t n, boolean_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugb1outeven(n, const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -ae_int_t xdebugi1sum(const integer_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::xdebugi1sum(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -A[I] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugi1neg(const integer_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugi1neg(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Appends copy of array to itself. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugi1appendcopy(integer_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugi1appendcopy(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate N-element array with even-numbered A[I] set to I, and odd-numbered -ones set to 0. - -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugi1outeven(const ae_int_t n, integer_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugi1outeven(n, const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -double xdebugr1sum(const real_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::xdebugr1sum(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -A[I] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugr1neg(const real_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugr1neg(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Appends copy of array to itself. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugr1appendcopy(real_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugr1appendcopy(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate N-element array with even-numbered A[I] set to I*0.25, -and odd-numbered ones are set to 0. - -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugr1outeven(const ae_int_t n, real_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugr1outeven(n, const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -alglib::complex xdebugc1sum(const complex_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_complex result = alglib_impl::xdebugc1sum(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -A[I] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugc1neg(const complex_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugc1neg(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Appends copy of array to itself. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugc1appendcopy(complex_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugc1appendcopy(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate N-element array with even-numbered A[K] set to (x,y) = (K*0.25, K*0.125) -and odd-numbered ones are set to 0. - -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugc1outeven(const ae_int_t n, complex_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugc1outeven(n, const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Counts number of True values in the boolean 2D array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -ae_int_t xdebugb2count(const boolean_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::xdebugb2count(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by NOT(a[i]). -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugb2not(const boolean_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugb2not(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Transposes array. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugb2transpose(boolean_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugb2transpose(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate MxN matrix with elements set to "Sin(3*I+5*J)>0" -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugb2outsin(const ae_int_t m, const ae_int_t n, boolean_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugb2outsin(m, n, const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -ae_int_t xdebugi2sum(const integer_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::xdebugi2sum(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -a[i,j] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugi2neg(const integer_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugi2neg(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Transposes array. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugi2transpose(integer_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugi2transpose(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate MxN matrix with elements set to "Sign(Sin(3*I+5*J))" -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugi2outsin(const ae_int_t m, const ae_int_t n, integer_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugi2outsin(m, n, const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -double xdebugr2sum(const real_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::xdebugr2sum(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -a[i,j] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugr2neg(const real_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugr2neg(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Transposes array. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugr2transpose(real_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugr2transpose(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate MxN matrix with elements set to "Sin(3*I+5*J)" -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugr2outsin(const ae_int_t m, const ae_int_t n, real_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugr2outsin(m, n, const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -alglib::complex xdebugc2sum(const complex_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_complex result = alglib_impl::xdebugc2sum(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -a[i,j] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugc2neg(const complex_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugc2neg(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Transposes array. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugc2transpose(complex_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugc2transpose(const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate MxN matrix with elements set to "Sin(3*I+5*J),Cos(3*I+5*J)" -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugc2outsincos(const ae_int_t m, const ae_int_t n, complex_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::xdebugc2outsincos(m, n, const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of a[i,j]*(1+b[i,j]) such that c[i,j] is True - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -double xdebugmaskedbiasedproductsum(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const real_2d_array &b, const boolean_2d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::xdebugmaskedbiasedproductsum(m, n, const_cast(a.c_ptr()), const_cast(b.c_ptr()), const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF COMPUTATIONAL CORE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_NEARESTNEIGHBOR) || !defined(AE_PARTIAL_BUILD) -static ae_int_t nearestneighbor_splitnodesize = 6; -static ae_int_t nearestneighbor_kdtreefirstversion = 0; -static ae_int_t nearestneighbor_tsqueryrnn(kdtree* kdt, - kdtreerequestbuffer* buf, - /* Real */ ae_vector* x, - double r, - ae_bool selfmatch, - ae_bool orderedbydist, - ae_state *_state); -static void nearestneighbor_kdtreesplit(kdtree* kdt, - ae_int_t i1, - ae_int_t i2, - ae_int_t d, - double s, - ae_int_t* i3, - ae_state *_state); -static void nearestneighbor_kdtreegeneratetreerec(kdtree* kdt, - ae_int_t* nodesoffs, - ae_int_t* splitsoffs, - ae_int_t i1, - ae_int_t i2, - ae_int_t maxleafsize, - ae_state *_state); -static void nearestneighbor_kdtreequerynnrec(kdtree* kdt, - kdtreerequestbuffer* buf, - ae_int_t offs, - ae_state *_state); -static void nearestneighbor_kdtreequeryboxrec(kdtree* kdt, - kdtreerequestbuffer* buf, - ae_int_t offs, - ae_state *_state); -static void nearestneighbor_kdtreeinitbox(kdtree* kdt, - /* Real */ ae_vector* x, - kdtreerequestbuffer* buf, - ae_state *_state); -static void nearestneighbor_kdtreeallocdatasetindependent(kdtree* kdt, - ae_int_t nx, - ae_int_t ny, - ae_state *_state); -static void nearestneighbor_kdtreeallocdatasetdependent(kdtree* kdt, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - ae_state *_state); -static void nearestneighbor_checkrequestbufferconsistency(kdtree* kdt, - kdtreerequestbuffer* buf, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_HQRND) || !defined(AE_PARTIAL_BUILD) -static ae_int_t hqrnd_hqrndmax = 2147483561; -static ae_int_t hqrnd_hqrndm1 = 2147483563; -static ae_int_t hqrnd_hqrndm2 = 2147483399; -static ae_int_t hqrnd_hqrndmagic = 1634357784; -static ae_int_t hqrnd_hqrndintegerbase(hqrndstate* state, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_XDEBUG) || !defined(AE_PARTIAL_BUILD) - - -#endif - -#if defined(AE_COMPILE_NEARESTNEIGHBOR) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -KD-tree creation - -This subroutine creates KD-tree from set of X-values and optional Y-values - -INPUT PARAMETERS - XY - dataset, array[0..N-1,0..NX+NY-1]. - one row corresponds to one point. - first NX columns contain X-values, next NY (NY may be zero) - columns may contain associated Y-values - N - number of points, N>=0. - NX - space dimension, NX>=1. - NY - number of optional Y-values, NY>=0. - NormType- norm type: - * 0 denotes infinity-norm - * 1 denotes 1-norm - * 2 denotes 2-norm (Euclidean norm) - -OUTPUT PARAMETERS - KDT - KD-tree - - -NOTES - -1. KD-tree creation have O(N*logN) complexity and O(N*(2*NX+NY)) memory - requirements. -2. Although KD-trees may be used with any combination of N and NX, they - are more efficient than brute-force search only when N >> 4^NX. So they - are most useful in low-dimensional tasks (NX=2, NX=3). NX=1 is another - inefficient case, because simple binary search (without additional - structures) is much more efficient in such tasks than KD-trees. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreebuild(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - ae_int_t normtype, - kdtree* kdt, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector tags; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&tags, 0, sizeof(tags)); - _kdtree_clear(kdt); - ae_vector_init(&tags, 0, DT_INT, _state, ae_true); - - ae_assert(n>=0, "KDTreeBuild: N<0", _state); - ae_assert(nx>=1, "KDTreeBuild: NX<1", _state); - ae_assert(ny>=0, "KDTreeBuild: NY<0", _state); - ae_assert(normtype>=0&&normtype<=2, "KDTreeBuild: incorrect NormType", _state); - ae_assert(xy->rows>=n, "KDTreeBuild: rows(X)cols>=nx+ny||n==0, "KDTreeBuild: cols(X)0 ) - { - ae_vector_set_length(&tags, n, _state); - for(i=0; i<=n-1; i++) - { - tags.ptr.p_int[i] = 0; - } - } - kdtreebuildtagged(xy, &tags, n, nx, ny, normtype, kdt, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -KD-tree creation - -This subroutine creates KD-tree from set of X-values, integer tags and -optional Y-values - -INPUT PARAMETERS - XY - dataset, array[0..N-1,0..NX+NY-1]. - one row corresponds to one point. - first NX columns contain X-values, next NY (NY may be zero) - columns may contain associated Y-values - Tags - tags, array[0..N-1], contains integer tags associated - with points. - N - number of points, N>=0 - NX - space dimension, NX>=1. - NY - number of optional Y-values, NY>=0. - NormType- norm type: - * 0 denotes infinity-norm - * 1 denotes 1-norm - * 2 denotes 2-norm (Euclidean norm) - -OUTPUT PARAMETERS - KDT - KD-tree - -NOTES - -1. KD-tree creation have O(N*logN) complexity and O(N*(2*NX+NY)) memory - requirements. -2. Although KD-trees may be used with any combination of N and NX, they - are more efficient than brute-force search only when N >> 4^NX. So they - are most useful in low-dimensional tasks (NX=2, NX=3). NX=1 is another - inefficient case, because simple binary search (without additional - structures) is much more efficient in such tasks than KD-trees. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreebuildtagged(/* Real */ ae_matrix* xy, - /* Integer */ ae_vector* tags, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - ae_int_t normtype, - kdtree* kdt, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t nodesoffs; - ae_int_t splitsoffs; - - _kdtree_clear(kdt); - - ae_assert(n>=0, "KDTreeBuildTagged: N<0", _state); - ae_assert(nx>=1, "KDTreeBuildTagged: NX<1", _state); - ae_assert(ny>=0, "KDTreeBuildTagged: NY<0", _state); - ae_assert(normtype>=0&&normtype<=2, "KDTreeBuildTagged: incorrect NormType", _state); - ae_assert(xy->rows>=n, "KDTreeBuildTagged: rows(X)cols>=nx+ny||n==0, "KDTreeBuildTagged: cols(X)n = n; - kdt->nx = nx; - kdt->ny = ny; - kdt->normtype = normtype; - kdt->innerbuf.kcur = 0; - - /* - * N=0 => quick exit - */ - if( n==0 ) - { - return; - } - - /* - * Allocate - */ - nearestneighbor_kdtreeallocdatasetindependent(kdt, nx, ny, _state); - nearestneighbor_kdtreeallocdatasetdependent(kdt, n, nx, ny, _state); - kdtreecreaterequestbuffer(kdt, &kdt->innerbuf, _state); - - /* - * Initial fill - */ - for(i=0; i<=n-1; i++) - { - ae_v_move(&kdt->xy.ptr.pp_double[i][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1)); - ae_v_move(&kdt->xy.ptr.pp_double[i][nx], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(nx,2*nx+ny-1)); - kdt->tags.ptr.p_int[i] = tags->ptr.p_int[i]; - } - - /* - * Determine bounding box - */ - ae_v_move(&kdt->boxmin.ptr.p_double[0], 1, &kdt->xy.ptr.pp_double[0][0], 1, ae_v_len(0,nx-1)); - ae_v_move(&kdt->boxmax.ptr.p_double[0], 1, &kdt->xy.ptr.pp_double[0][0], 1, ae_v_len(0,nx-1)); - for(i=1; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - kdt->boxmin.ptr.p_double[j] = ae_minreal(kdt->boxmin.ptr.p_double[j], kdt->xy.ptr.pp_double[i][j], _state); - kdt->boxmax.ptr.p_double[j] = ae_maxreal(kdt->boxmax.ptr.p_double[j], kdt->xy.ptr.pp_double[i][j], _state); - } - } - - /* - * Generate tree - */ - nodesoffs = 0; - splitsoffs = 0; - ae_v_move(&kdt->innerbuf.curboxmin.ptr.p_double[0], 1, &kdt->boxmin.ptr.p_double[0], 1, ae_v_len(0,nx-1)); - ae_v_move(&kdt->innerbuf.curboxmax.ptr.p_double[0], 1, &kdt->boxmax.ptr.p_double[0], 1, ae_v_len(0,nx-1)); - nearestneighbor_kdtreegeneratetreerec(kdt, &nodesoffs, &splitsoffs, 0, n, 8, _state); - ivectorresize(&kdt->nodes, nodesoffs, _state); - rvectorresize(&kdt->splits, splitsoffs, _state); -} - - -/************************************************************************* -This function creates buffer structure which can be used to perform -parallel KD-tree requests. - -KD-tree subpackage provides two sets of request functions - ones which use -internal buffer of KD-tree object (these functions are single-threaded -because they use same buffer, which can not shared between threads), and -ones which use external buffer. - -This function is used to initialize external buffer. - -INPUT PARAMETERS - KDT - KD-tree which is associated with newly created buffer - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: KD-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use buffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -void kdtreecreaterequestbuffer(kdtree* kdt, - kdtreerequestbuffer* buf, - ae_state *_state) -{ - - _kdtreerequestbuffer_clear(buf); - - ae_vector_set_length(&buf->x, kdt->nx, _state); - ae_vector_set_length(&buf->boxmin, kdt->nx, _state); - ae_vector_set_length(&buf->boxmax, kdt->nx, _state); - ae_vector_set_length(&buf->idx, kdt->n, _state); - ae_vector_set_length(&buf->r, kdt->n, _state); - ae_vector_set_length(&buf->buf, ae_maxint(kdt->n, kdt->nx, _state), _state); - ae_vector_set_length(&buf->curboxmin, kdt->nx, _state); - ae_vector_set_length(&buf->curboxmax, kdt->nx, _state); - buf->kcur = 0; -} - - -/************************************************************************* -K-NN query: K nearest neighbors - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: KDTreeTsQueryKNN() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - X - point, array[0..NX-1]. - K - number of neighbors to return, K>=1 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of actual neighbors found (either K or N, if K>N). - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -these results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() to get distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreequeryknn(kdtree* kdt, - /* Real */ ae_vector* x, - ae_int_t k, - ae_bool selfmatch, - ae_state *_state) -{ - ae_int_t result; - - - ae_assert(k>=1, "KDTreeQueryKNN: K<1!", _state); - ae_assert(x->cnt>=kdt->nx, "KDTreeQueryKNN: Length(X)nx, _state), "KDTreeQueryKNN: X contains infinite or NaN values!", _state); - result = kdtreetsqueryaknn(kdt, &kdt->innerbuf, x, k, selfmatch, 0.0, _state); - return result; -} - - -/************************************************************************* -K-NN query: K nearest neighbors, using external thread-local buffer. - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -INPUT PARAMETERS - KDT - kd-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - K - number of neighbors to return, K>=1 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of actual neighbors found (either K or N, if K>N). - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreetsqueryknn(kdtree* kdt, - kdtreerequestbuffer* buf, - /* Real */ ae_vector* x, - ae_int_t k, - ae_bool selfmatch, - ae_state *_state) -{ - ae_int_t result; - - - ae_assert(k>=1, "KDTreeTsQueryKNN: K<1!", _state); - ae_assert(x->cnt>=kdt->nx, "KDTreeTsQueryKNN: Length(X)nx, _state), "KDTreeTsQueryKNN: X contains infinite or NaN values!", _state); - result = kdtreetsqueryaknn(kdt, buf, x, k, selfmatch, 0.0, _state); - return result; -} - - -/************************************************************************* -R-NN query: all points within R-sphere centered at X, ordered by distance -between point and X (by ascending). - -NOTE: it is also possible to perform undordered queries performed by means - of kdtreequeryrnnu() and kdtreetsqueryrnnu() functions. Such queries - are faster because we do not have to use heap structure for sorting. - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: kdtreetsqueryrnn() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -actual results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() to get distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreequeryrnn(kdtree* kdt, - /* Real */ ae_vector* x, - double r, - ae_bool selfmatch, - ae_state *_state) -{ - ae_int_t result; - - - ae_assert(ae_fp_greater(r,(double)(0)), "KDTreeQueryRNN: incorrect R!", _state); - ae_assert(x->cnt>=kdt->nx, "KDTreeQueryRNN: Length(X)nx, _state), "KDTreeQueryRNN: X contains infinite or NaN values!", _state); - result = kdtreetsqueryrnn(kdt, &kdt->innerbuf, x, r, selfmatch, _state); - return result; -} - - -/************************************************************************* -R-NN query: all points within R-sphere centered at X, no ordering by -distance as undicated by "U" suffix (faster that ordered query, for large -queries - significantly faster). - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: kdtreetsqueryrnn() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -actual results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() to get distances - -As indicated by "U" suffix, this function returns unordered results. - - -- ALGLIB -- - Copyright 01.11.2018 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreequeryrnnu(kdtree* kdt, - /* Real */ ae_vector* x, - double r, - ae_bool selfmatch, - ae_state *_state) -{ - ae_int_t result; - - - ae_assert(ae_fp_greater(r,(double)(0)), "KDTreeQueryRNNU: incorrect R!", _state); - ae_assert(x->cnt>=kdt->nx, "KDTreeQueryRNNU: Length(X)nx, _state), "KDTreeQueryRNNU: X contains infinite or NaN values!", _state); - result = kdtreetsqueryrnnu(kdt, &kdt->innerbuf, x, r, selfmatch, _state); - return result; -} - - -/************************************************************************* -R-NN query: all points within R-sphere centered at X, using external -thread-local buffer, sorted by distance between point and X (by ascending) - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -NOTE: it is also possible to perform undordered queries performed by means - of kdtreequeryrnnu() and kdtreetsqueryrnnu() functions. Such queries - are faster because we do not have to use heap structure for sorting. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreetsqueryrnn(kdtree* kdt, - kdtreerequestbuffer* buf, - /* Real */ ae_vector* x, - double r, - ae_bool selfmatch, - ae_state *_state) -{ - ae_int_t result; - - - ae_assert(ae_isfinite(r, _state)&&ae_fp_greater(r,(double)(0)), "KDTreeTsQueryRNN: incorrect R!", _state); - ae_assert(x->cnt>=kdt->nx, "KDTreeTsQueryRNN: Length(X)nx, _state), "KDTreeTsQueryRNN: X contains infinite or NaN values!", _state); - result = nearestneighbor_tsqueryrnn(kdt, buf, x, r, selfmatch, ae_true, _state); - return result; -} - - -/************************************************************************* -R-NN query: all points within R-sphere centered at X, using external -thread-local buffer, no ordering by distance as undicated by "U" suffix -(faster that ordered query, for large queries - significantly faster). - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -As indicated by "U" suffix, this function returns unordered results. - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreetsqueryrnnu(kdtree* kdt, - kdtreerequestbuffer* buf, - /* Real */ ae_vector* x, - double r, - ae_bool selfmatch, - ae_state *_state) -{ - ae_int_t result; - - - ae_assert(ae_isfinite(r, _state)&&ae_fp_greater(r,(double)(0)), "KDTreeTsQueryRNNU: incorrect R!", _state); - ae_assert(x->cnt>=kdt->nx, "KDTreeTsQueryRNNU: Length(X)nx, _state), "KDTreeTsQueryRNNU: X contains infinite or NaN values!", _state); - result = nearestneighbor_tsqueryrnn(kdt, buf, x, r, selfmatch, ae_false, _state); - return result; -} - - -/************************************************************************* -K-NN query: approximate K nearest neighbors - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: KDTreeTsQueryAKNN() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - X - point, array[0..NX-1]. - K - number of neighbors to return, K>=1 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - Eps - approximation factor, Eps>=0. eps-approximate nearest - neighbor is a neighbor whose distance from X is at - most (1+eps) times distance of true nearest neighbor. - -RESULT - number of actual neighbors found (either K or N, if K>N). - -NOTES - significant performance gain may be achieved only when Eps is is on - the order of magnitude of 1 or larger. - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -these results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() to get distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreequeryaknn(kdtree* kdt, - /* Real */ ae_vector* x, - ae_int_t k, - ae_bool selfmatch, - double eps, - ae_state *_state) -{ - ae_int_t result; - - - result = kdtreetsqueryaknn(kdt, &kdt->innerbuf, x, k, selfmatch, eps, _state); - return result; -} - - -/************************************************************************* -K-NN query: approximate K nearest neighbors, using thread-local buffer. - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - K - number of neighbors to return, K>=1 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - Eps - approximation factor, Eps>=0. eps-approximate nearest - neighbor is a neighbor whose distance from X is at - most (1+eps) times distance of true nearest neighbor. - -RESULT - number of actual neighbors found (either K or N, if K>N). - -NOTES - significant performance gain may be achieved only when Eps is is on - the order of magnitude of 1 or larger. - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreetsqueryaknn(kdtree* kdt, - kdtreerequestbuffer* buf, - /* Real */ ae_vector* x, - ae_int_t k, - ae_bool selfmatch, - double eps, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t result; - - - ae_assert(k>0, "KDTreeTsQueryAKNN: incorrect K!", _state); - ae_assert(ae_fp_greater_eq(eps,(double)(0)), "KDTreeTsQueryAKNN: incorrect Eps!", _state); - ae_assert(x->cnt>=kdt->nx, "KDTreeTsQueryAKNN: Length(X)nx, _state), "KDTreeTsQueryAKNN: X contains infinite or NaN values!", _state); - - /* - * Handle special case: KDT.N=0 - */ - if( kdt->n==0 ) - { - buf->kcur = 0; - result = 0; - return result; - } - - /* - * Check consistency of request buffer - */ - nearestneighbor_checkrequestbufferconsistency(kdt, buf, _state); - - /* - * Prepare parameters - */ - k = ae_minint(k, kdt->n, _state); - buf->kneeded = k; - buf->rneeded = (double)(0); - buf->selfmatch = selfmatch; - if( kdt->normtype==2 ) - { - buf->approxf = 1/ae_sqr(1+eps, _state); - } - else - { - buf->approxf = 1/(1+eps); - } - buf->kcur = 0; - - /* - * calculate distance from point to current bounding box - */ - nearestneighbor_kdtreeinitbox(kdt, x, buf, _state); - - /* - * call recursive search - * results are returned as heap - */ - nearestneighbor_kdtreequerynnrec(kdt, buf, 0, _state); - - /* - * pop from heap to generate ordered representation - * - * last element is non pop'ed because it is already in - * its place - */ - result = buf->kcur; - j = buf->kcur; - for(i=buf->kcur; i>=2; i--) - { - tagheappopi(&buf->r, &buf->idx, &j, _state); - } - return result; -} - - -/************************************************************************* -Box query: all points within user-specified box. - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: KDTreeTsQueryBox() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - BoxMin - lower bounds, array[0..NX-1]. - BoxMax - upper bounds, array[0..NX-1]. - - -RESULT - number of actual neighbors found (in [0,N]). - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -these results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() returns zeros for this request - -NOTE: this particular query returns unordered results, because there is no - meaningful way of ordering points. Furthermore, no 'distance' is - associated with points - it is either INSIDE or OUTSIDE (so request - for distances will return zeros). - - -- ALGLIB -- - Copyright 14.05.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreequerybox(kdtree* kdt, - /* Real */ ae_vector* boxmin, - /* Real */ ae_vector* boxmax, - ae_state *_state) -{ - ae_int_t result; - - - result = kdtreetsquerybox(kdt, &kdt->innerbuf, boxmin, boxmax, _state); - return result; -} - - -/************************************************************************* -Box query: all points within user-specified box, using thread-local buffer. - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - BoxMin - lower bounds, array[0..NX-1]. - BoxMax - upper bounds, array[0..NX-1]. - -RESULT - number of actual neighbors found (in [0,N]). - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "ts" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() returns zeros for this query - -NOTE: this particular query returns unordered results, because there is no - meaningful way of ordering points. Furthermore, no 'distance' is - associated with points - it is either INSIDE or OUTSIDE (so request - for distances will return zeros). - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 14.05.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreetsquerybox(kdtree* kdt, - kdtreerequestbuffer* buf, - /* Real */ ae_vector* boxmin, - /* Real */ ae_vector* boxmax, - ae_state *_state) -{ - ae_int_t j; - ae_int_t result; - - - ae_assert(boxmin->cnt>=kdt->nx, "KDTreeTsQueryBox: Length(BoxMin)cnt>=kdt->nx, "KDTreeTsQueryBox: Length(BoxMax)nx, _state), "KDTreeTsQueryBox: BoxMin contains infinite or NaN values!", _state); - ae_assert(isfinitevector(boxmax, kdt->nx, _state), "KDTreeTsQueryBox: BoxMax contains infinite or NaN values!", _state); - - /* - * Check consistency of request buffer - */ - nearestneighbor_checkrequestbufferconsistency(kdt, buf, _state); - - /* - * Quick exit for degenerate boxes - */ - for(j=0; j<=kdt->nx-1; j++) - { - if( ae_fp_greater(boxmin->ptr.p_double[j],boxmax->ptr.p_double[j]) ) - { - buf->kcur = 0; - result = 0; - return result; - } - } - - /* - * Prepare parameters - */ - for(j=0; j<=kdt->nx-1; j++) - { - buf->boxmin.ptr.p_double[j] = boxmin->ptr.p_double[j]; - buf->boxmax.ptr.p_double[j] = boxmax->ptr.p_double[j]; - buf->curboxmin.ptr.p_double[j] = boxmin->ptr.p_double[j]; - buf->curboxmax.ptr.p_double[j] = boxmax->ptr.p_double[j]; - } - buf->kcur = 0; - - /* - * call recursive search - */ - nearestneighbor_kdtreequeryboxrec(kdt, buf, 0, _state); - result = buf->kcur; - return result; -} - - -/************************************************************************* -X-values from last query. - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - kdtreetsqueryresultsx(). - -INPUT PARAMETERS - KDT - KD-tree - X - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - X - rows are filled with X-values - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsTags() tag values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultsx(kdtree* kdt, - /* Real */ ae_matrix* x, - ae_state *_state) -{ - - - kdtreetsqueryresultsx(kdt, &kdt->innerbuf, x, _state); -} - - -/************************************************************************* -X- and Y-values from last query - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - kdtreetsqueryresultsxy(). - -INPUT PARAMETERS - KDT - KD-tree - XY - possibly pre-allocated buffer. If XY is too small to store - result, it is resized. If size(XY) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - XY - rows are filled with points: first NX columns with - X-values, next NY columns - with Y-values. - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsTags() tag values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultsxy(kdtree* kdt, - /* Real */ ae_matrix* xy, - ae_state *_state) -{ - - - kdtreetsqueryresultsxy(kdt, &kdt->innerbuf, xy, _state); -} - - -/************************************************************************* -Tags from last query - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - kdtreetsqueryresultstags(). - -INPUT PARAMETERS - KDT - KD-tree - Tags - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - Tags - filled with tags associated with points, - or, when no tags were supplied, with zeros - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultstags(kdtree* kdt, - /* Integer */ ae_vector* tags, - ae_state *_state) -{ - - - kdtreetsqueryresultstags(kdt, &kdt->innerbuf, tags, _state); -} - - -/************************************************************************* -Distances from last query - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - kdtreetsqueryresultsdistances(). - -INPUT PARAMETERS - KDT - KD-tree - R - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - R - filled with distances (in corresponding norm) - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsTags() tag values - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultsdistances(kdtree* kdt, - /* Real */ ae_vector* r, - ae_state *_state) -{ - - - kdtreetsqueryresultsdistances(kdt, &kdt->innerbuf, r, _state); -} - - -/************************************************************************* -X-values from last query associated with kdtreerequestbuffer object. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure. - X - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - X - rows are filled with X-values - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsTags() tag values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreetsqueryresultsx(kdtree* kdt, - kdtreerequestbuffer* buf, - /* Real */ ae_matrix* x, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - - - if( buf->kcur==0 ) - { - return; - } - if( x->rowskcur||x->colsnx ) - { - ae_matrix_set_length(x, buf->kcur, kdt->nx, _state); - } - k = buf->kcur; - for(i=0; i<=k-1; i++) - { - ae_v_move(&x->ptr.pp_double[i][0], 1, &kdt->xy.ptr.pp_double[buf->idx.ptr.p_int[i]][kdt->nx], 1, ae_v_len(0,kdt->nx-1)); - } -} - - -/************************************************************************* -X- and Y-values from last query associated with kdtreerequestbuffer object. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure. - XY - possibly pre-allocated buffer. If XY is too small to store - result, it is resized. If size(XY) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - XY - rows are filled with points: first NX columns with - X-values, next NY columns - with Y-values. - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsTags() tag values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreetsqueryresultsxy(kdtree* kdt, - kdtreerequestbuffer* buf, - /* Real */ ae_matrix* xy, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - - - if( buf->kcur==0 ) - { - return; - } - if( xy->rowskcur||xy->colsnx+kdt->ny ) - { - ae_matrix_set_length(xy, buf->kcur, kdt->nx+kdt->ny, _state); - } - k = buf->kcur; - for(i=0; i<=k-1; i++) - { - ae_v_move(&xy->ptr.pp_double[i][0], 1, &kdt->xy.ptr.pp_double[buf->idx.ptr.p_int[i]][kdt->nx], 1, ae_v_len(0,kdt->nx+kdt->ny-1)); - } -} - - -/************************************************************************* -Tags from last query associated with kdtreerequestbuffer object. - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - KDTreeTsqueryresultstags(). - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure. - Tags - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - Tags - filled with tags associated with points, - or, when no tags were supplied, with zeros - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreetsqueryresultstags(kdtree* kdt, - kdtreerequestbuffer* buf, - /* Integer */ ae_vector* tags, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - - - if( buf->kcur==0 ) - { - return; - } - if( tags->cntkcur ) - { - ae_vector_set_length(tags, buf->kcur, _state); - } - k = buf->kcur; - for(i=0; i<=k-1; i++) - { - tags->ptr.p_int[i] = kdt->tags.ptr.p_int[buf->idx.ptr.p_int[i]]; - } -} - - -/************************************************************************* -Distances from last query associated with kdtreerequestbuffer object. - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - KDTreeTsqueryresultsdistances(). - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure. - R - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - R - filled with distances (in corresponding norm) - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsTags() tag values - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreetsqueryresultsdistances(kdtree* kdt, - kdtreerequestbuffer* buf, - /* Real */ ae_vector* r, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - - - if( buf->kcur==0 ) - { - return; - } - if( r->cntkcur ) - { - ae_vector_set_length(r, buf->kcur, _state); - } - k = buf->kcur; - - /* - * unload norms - * - * Abs() call is used to handle cases with negative norms - * (generated during KFN requests) - */ - if( kdt->normtype==0 ) - { - for(i=0; i<=k-1; i++) - { - r->ptr.p_double[i] = ae_fabs(buf->r.ptr.p_double[i], _state); - } - } - if( kdt->normtype==1 ) - { - for(i=0; i<=k-1; i++) - { - r->ptr.p_double[i] = ae_fabs(buf->r.ptr.p_double[i], _state); - } - } - if( kdt->normtype==2 ) - { - for(i=0; i<=k-1; i++) - { - r->ptr.p_double[i] = ae_sqrt(ae_fabs(buf->r.ptr.p_double[i], _state), _state); - } - } -} - - -/************************************************************************* -X-values from last query; 'interactive' variant for languages like Python -which support constructs like "X = KDTreeQueryResultsXI(KDT)" and -interactive mode of interpreter. - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultsxi(kdtree* kdt, - /* Real */ ae_matrix* x, - ae_state *_state) -{ - - ae_matrix_clear(x); - - kdtreequeryresultsx(kdt, x, _state); -} - - -/************************************************************************* -XY-values from last query; 'interactive' variant for languages like Python -which support constructs like "XY = KDTreeQueryResultsXYI(KDT)" and -interactive mode of interpreter. - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultsxyi(kdtree* kdt, - /* Real */ ae_matrix* xy, - ae_state *_state) -{ - - ae_matrix_clear(xy); - - kdtreequeryresultsxy(kdt, xy, _state); -} - - -/************************************************************************* -Tags from last query; 'interactive' variant for languages like Python -which support constructs like "Tags = KDTreeQueryResultsTagsI(KDT)" and -interactive mode of interpreter. - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultstagsi(kdtree* kdt, - /* Integer */ ae_vector* tags, - ae_state *_state) -{ - - ae_vector_clear(tags); - - kdtreequeryresultstags(kdt, tags, _state); -} - - -/************************************************************************* -Distances from last query; 'interactive' variant for languages like Python -which support constructs like "R = KDTreeQueryResultsDistancesI(KDT)" -and interactive mode of interpreter. - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultsdistancesi(kdtree* kdt, - /* Real */ ae_vector* r, - ae_state *_state) -{ - - ae_vector_clear(r); - - kdtreequeryresultsdistances(kdt, r, _state); -} - - -/************************************************************************* -It is informational function which returns bounding box for entire dataset. -This function is not visible to ALGLIB users, only ALGLIB itself may use -it. - -This function assumes that output buffers are preallocated by caller. - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -void kdtreeexplorebox(kdtree* kdt, - /* Real */ ae_vector* boxmin, - /* Real */ ae_vector* boxmax, - ae_state *_state) -{ - ae_int_t i; - - - rvectorsetlengthatleast(boxmin, kdt->nx, _state); - rvectorsetlengthatleast(boxmax, kdt->nx, _state); - for(i=0; i<=kdt->nx-1; i++) - { - boxmin->ptr.p_double[i] = kdt->boxmin.ptr.p_double[i]; - boxmax->ptr.p_double[i] = kdt->boxmax.ptr.p_double[i]; - } -} - - -/************************************************************************* -It is informational function which allows to get information about node -type. Node index is given by integer value, with 0 corresponding to root -node and other node indexes obtained via exploration. - -You should not expect that serialization/unserialization will retain node -indexes. You should keep in mind that future versions of ALGLIB may -introduce new node types. - -OUTPUT VALUES: - NodeType - node type: - * 0 corresponds to leaf node, which can be explored by - kdtreeexploreleaf() function - * 1 corresponds to split node, which can be explored - by kdtreeexploresplit() function - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -void kdtreeexplorenodetype(kdtree* kdt, - ae_int_t node, - ae_int_t* nodetype, - ae_state *_state) -{ - - *nodetype = 0; - - ae_assert(node>=0, "KDTreeExploreNodeType: incorrect node", _state); - ae_assert(nodenodes.cnt, "KDTreeExploreNodeType: incorrect node", _state); - if( kdt->nodes.ptr.p_int[node]>0 ) - { - - /* - * Leaf node - */ - *nodetype = 0; - return; - } - if( kdt->nodes.ptr.p_int[node]==0 ) - { - - /* - * Split node - */ - *nodetype = 1; - return; - } - ae_assert(ae_false, "KDTreeExploreNodeType: integrity check failure", _state); -} - - -/************************************************************************* -It is informational function which allows to get information about leaf -node. Node index is given by integer value, with 0 corresponding to root -node and other node indexes obtained via exploration. - -You should not expect that serialization/unserialization will retain node -indexes. You should keep in mind that future versions of ALGLIB may -introduce new node types. - -OUTPUT VALUES: - XT - output buffer is reallocated (if too small) and filled by - XY values - K - number of rows in XY - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -void kdtreeexploreleaf(kdtree* kdt, - ae_int_t node, - /* Real */ ae_matrix* xy, - ae_int_t* k, - ae_state *_state) -{ - ae_int_t offs; - ae_int_t i; - ae_int_t j; - - *k = 0; - - ae_assert(node>=0, "KDTreeExploreLeaf: incorrect node index", _state); - ae_assert(node+1nodes.cnt, "KDTreeExploreLeaf: incorrect node index", _state); - ae_assert(kdt->nodes.ptr.p_int[node]>0, "KDTreeExploreLeaf: incorrect node index", _state); - *k = kdt->nodes.ptr.p_int[node]; - offs = kdt->nodes.ptr.p_int[node+1]; - ae_assert(offs>=0, "KDTreeExploreLeaf: integrity error", _state); - ae_assert(offs+(*k)-1xy.rows, "KDTreeExploreLeaf: integrity error", _state); - rmatrixsetlengthatleast(xy, *k, kdt->nx+kdt->ny, _state); - for(i=0; i<=*k-1; i++) - { - for(j=0; j<=kdt->nx+kdt->ny-1; j++) - { - xy->ptr.pp_double[i][j] = kdt->xy.ptr.pp_double[offs+i][kdt->nx+j]; - } - } -} - - -/************************************************************************* -It is informational function which allows to get information about split -node. Node index is given by integer value, with 0 corresponding to root -node and other node indexes obtained via exploration. - -You should not expect that serialization/unserialization will retain node -indexes. You should keep in mind that future versions of ALGLIB may -introduce new node types. - -OUTPUT VALUES: - XT - output buffer is reallocated (if too small) and filled by - XY values - K - number of rows in XY - - // Nodes[idx+1]=dim dimension to split - // Nodes[idx+2]=offs offset of splitting point in Splits[] - // Nodes[idx+3]=left position of left child in Nodes[] - // Nodes[idx+4]=right position of right child in Nodes[] - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -void kdtreeexploresplit(kdtree* kdt, - ae_int_t node, - ae_int_t* d, - double* s, - ae_int_t* nodele, - ae_int_t* nodege, - ae_state *_state) -{ - - *d = 0; - *s = 0; - *nodele = 0; - *nodege = 0; - - ae_assert(node>=0, "KDTreeExploreSplit: incorrect node index", _state); - ae_assert(node+4nodes.cnt, "KDTreeExploreSplit: incorrect node index", _state); - ae_assert(kdt->nodes.ptr.p_int[node]==0, "KDTreeExploreSplit: incorrect node index", _state); - *d = kdt->nodes.ptr.p_int[node+1]; - *s = kdt->splits.ptr.p_double[kdt->nodes.ptr.p_int[node+2]]; - *nodele = kdt->nodes.ptr.p_int[node+3]; - *nodege = kdt->nodes.ptr.p_int[node+4]; - ae_assert(*d>=0, "KDTreeExploreSplit: integrity failure", _state); - ae_assert(*dnx, "KDTreeExploreSplit: integrity failure", _state); - ae_assert(ae_isfinite(*s, _state), "KDTreeExploreSplit: integrity failure", _state); - ae_assert(*nodele>=0, "KDTreeExploreSplit: integrity failure", _state); - ae_assert(*nodelenodes.cnt, "KDTreeExploreSplit: integrity failure", _state); - ae_assert(*nodege>=0, "KDTreeExploreSplit: integrity failure", _state); - ae_assert(*nodegenodes.cnt, "KDTreeExploreSplit: integrity failure", _state); -} - - -/************************************************************************* -Serializer: allocation - - -- ALGLIB -- - Copyright 14.03.2011 by Bochkanov Sergey -*************************************************************************/ -void kdtreealloc(ae_serializer* s, kdtree* tree, ae_state *_state) -{ - - - - /* - * Header - */ - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - - /* - * Data - */ - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - allocrealmatrix(s, &tree->xy, -1, -1, _state); - allocintegerarray(s, &tree->tags, -1, _state); - allocrealarray(s, &tree->boxmin, -1, _state); - allocrealarray(s, &tree->boxmax, -1, _state); - allocintegerarray(s, &tree->nodes, -1, _state); - allocrealarray(s, &tree->splits, -1, _state); -} - - -/************************************************************************* -Serializer: serialization - - -- ALGLIB -- - Copyright 14.03.2011 by Bochkanov Sergey -*************************************************************************/ -void kdtreeserialize(ae_serializer* s, kdtree* tree, ae_state *_state) -{ - - - - /* - * Header - */ - ae_serializer_serialize_int(s, getkdtreeserializationcode(_state), _state); - ae_serializer_serialize_int(s, nearestneighbor_kdtreefirstversion, _state); - - /* - * Data - */ - ae_serializer_serialize_int(s, tree->n, _state); - ae_serializer_serialize_int(s, tree->nx, _state); - ae_serializer_serialize_int(s, tree->ny, _state); - ae_serializer_serialize_int(s, tree->normtype, _state); - serializerealmatrix(s, &tree->xy, -1, -1, _state); - serializeintegerarray(s, &tree->tags, -1, _state); - serializerealarray(s, &tree->boxmin, -1, _state); - serializerealarray(s, &tree->boxmax, -1, _state); - serializeintegerarray(s, &tree->nodes, -1, _state); - serializerealarray(s, &tree->splits, -1, _state); -} - - -/************************************************************************* -Serializer: unserialization - - -- ALGLIB -- - Copyright 14.03.2011 by Bochkanov Sergey -*************************************************************************/ -void kdtreeunserialize(ae_serializer* s, kdtree* tree, ae_state *_state) -{ - ae_int_t i0; - ae_int_t i1; - - _kdtree_clear(tree); - - - /* - * check correctness of header - */ - ae_serializer_unserialize_int(s, &i0, _state); - ae_assert(i0==getkdtreeserializationcode(_state), "KDTreeUnserialize: stream header corrupted", _state); - ae_serializer_unserialize_int(s, &i1, _state); - ae_assert(i1==nearestneighbor_kdtreefirstversion, "KDTreeUnserialize: stream header corrupted", _state); - - /* - * Unserialize data - */ - ae_serializer_unserialize_int(s, &tree->n, _state); - ae_serializer_unserialize_int(s, &tree->nx, _state); - ae_serializer_unserialize_int(s, &tree->ny, _state); - ae_serializer_unserialize_int(s, &tree->normtype, _state); - unserializerealmatrix(s, &tree->xy, _state); - unserializeintegerarray(s, &tree->tags, _state); - unserializerealarray(s, &tree->boxmin, _state); - unserializerealarray(s, &tree->boxmax, _state); - unserializeintegerarray(s, &tree->nodes, _state); - unserializerealarray(s, &tree->splits, _state); - kdtreecreaterequestbuffer(tree, &tree->innerbuf, _state); -} - - -/************************************************************************* -R-NN query: all points within R-sphere centered at X, using external -thread-local buffer, sorted by distance between point and X (by ascending) - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -NOTE: it is also possible to perform undordered queries performed by means - of kdtreequeryrnnu() and kdtreetsqueryrnnu() functions. Such queries - are faster because we do not have to use heap structure for sorting. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -static ae_int_t nearestneighbor_tsqueryrnn(kdtree* kdt, - kdtreerequestbuffer* buf, - /* Real */ ae_vector* x, - double r, - ae_bool selfmatch, - ae_bool orderedbydist, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t result; - - - - /* - * Handle special case: KDT.N=0 - */ - if( kdt->n==0 ) - { - buf->kcur = 0; - result = 0; - return result; - } - - /* - * Check consistency of request buffer - */ - nearestneighbor_checkrequestbufferconsistency(kdt, buf, _state); - - /* - * Prepare parameters - */ - buf->kneeded = 0; - if( kdt->normtype!=2 ) - { - buf->rneeded = r; - } - else - { - buf->rneeded = ae_sqr(r, _state); - } - buf->selfmatch = selfmatch; - buf->approxf = (double)(1); - buf->kcur = 0; - - /* - * calculate distance from point to current bounding box - */ - nearestneighbor_kdtreeinitbox(kdt, x, buf, _state); - - /* - * call recursive search - * results are returned as heap - */ - nearestneighbor_kdtreequerynnrec(kdt, buf, 0, _state); - result = buf->kcur; - - /* - * pop from heap to generate ordered representation - * - * last element is not pop'ed because it is already in - * its place - */ - if( orderedbydist ) - { - j = buf->kcur; - for(i=buf->kcur; i>=2; i--) - { - tagheappopi(&buf->r, &buf->idx, &j, _state); - } - } - return result; -} - - -/************************************************************************* -Rearranges nodes [I1,I2) using partition in D-th dimension with S as threshold. -Returns split position I3: [I1,I3) and [I3,I2) are created as result. - -This subroutine doesn't create tree structures, just rearranges nodes. -*************************************************************************/ -static void nearestneighbor_kdtreesplit(kdtree* kdt, - ae_int_t i1, - ae_int_t i2, - ae_int_t d, - double s, - ae_int_t* i3, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t ileft; - ae_int_t iright; - double v; - - *i3 = 0; - - ae_assert(kdt->n>0, "KDTreeSplit: internal error", _state); - - /* - * split XY/Tags in two parts: - * * [ILeft,IRight] is non-processed part of XY/Tags - * - * After cycle is done, we have Ileft=IRight. We deal with - * this element separately. - * - * After this, [I1,ILeft) contains left part, and [ILeft,I2) - * contains right part. - */ - ileft = i1; - iright = i2-1; - while(ileftxy.ptr.pp_double[ileft][d]<=s ) - { - - /* - * XY[ILeft] is on its place. - * Advance ILeft. - */ - ileft = ileft+1; - } - else - { - - /* - * XY[ILeft,..] must be at IRight. - * Swap and advance IRight. - */ - for(i=0; i<=2*kdt->nx+kdt->ny-1; i++) - { - v = kdt->xy.ptr.pp_double[ileft][i]; - kdt->xy.ptr.pp_double[ileft][i] = kdt->xy.ptr.pp_double[iright][i]; - kdt->xy.ptr.pp_double[iright][i] = v; - } - j = kdt->tags.ptr.p_int[ileft]; - kdt->tags.ptr.p_int[ileft] = kdt->tags.ptr.p_int[iright]; - kdt->tags.ptr.p_int[iright] = j; - iright = iright-1; - } - } - if( kdt->xy.ptr.pp_double[ileft][d]<=s ) - { - ileft = ileft+1; - } - else - { - iright = iright-1; - } - *i3 = ileft; -} - - -/************************************************************************* -Recursive kd-tree generation subroutine. - -PARAMETERS - KDT tree - NodesOffs unused part of Nodes[] which must be filled by tree - SplitsOffs unused part of Splits[] - I1, I2 points from [I1,I2) are processed - -NodesOffs[] and SplitsOffs[] must be large enough. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -static void nearestneighbor_kdtreegeneratetreerec(kdtree* kdt, - ae_int_t* nodesoffs, - ae_int_t* splitsoffs, - ae_int_t i1, - ae_int_t i2, - ae_int_t maxleafsize, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nx; - ae_int_t ny; - ae_int_t i; - ae_int_t j; - ae_int_t oldoffs; - ae_int_t i3; - ae_int_t cntless; - ae_int_t cntgreater; - double minv; - double maxv; - ae_int_t minidx; - ae_int_t maxidx; - ae_int_t d; - double ds; - double s; - double v; - double v0; - double v1; - - - ae_assert(kdt->n>0, "KDTreeGenerateTreeRec: internal error", _state); - ae_assert(i2>i1, "KDTreeGenerateTreeRec: internal error", _state); - - /* - * Generate leaf if needed - */ - if( i2-i1<=maxleafsize ) - { - kdt->nodes.ptr.p_int[*nodesoffs+0] = i2-i1; - kdt->nodes.ptr.p_int[*nodesoffs+1] = i1; - *nodesoffs = *nodesoffs+2; - return; - } - - /* - * Load values for easier access - */ - nx = kdt->nx; - ny = kdt->ny; - - /* - * Select dimension to split: - * * D is a dimension number - * In case bounding box has zero size, we enforce creation of the leaf node. - */ - d = 0; - ds = kdt->innerbuf.curboxmax.ptr.p_double[0]-kdt->innerbuf.curboxmin.ptr.p_double[0]; - for(i=1; i<=nx-1; i++) - { - v = kdt->innerbuf.curboxmax.ptr.p_double[i]-kdt->innerbuf.curboxmin.ptr.p_double[i]; - if( v>ds ) - { - ds = v; - d = i; - } - } - if( ae_fp_eq(ds,(double)(0)) ) - { - kdt->nodes.ptr.p_int[*nodesoffs+0] = i2-i1; - kdt->nodes.ptr.p_int[*nodesoffs+1] = i1; - *nodesoffs = *nodesoffs+2; - return; - } - - /* - * Select split position S using sliding midpoint rule, - * rearrange points into [I1,I3) and [I3,I2). - * - * In case all points has same value of D-th component - * (MinV=MaxV) we enforce D-th dimension of bounding - * box to become exactly zero and repeat tree construction. - */ - s = kdt->innerbuf.curboxmin.ptr.p_double[d]+0.5*ds; - ae_v_move(&kdt->innerbuf.buf.ptr.p_double[0], 1, &kdt->xy.ptr.pp_double[i1][d], kdt->xy.stride, ae_v_len(0,i2-i1-1)); - n = i2-i1; - cntless = 0; - cntgreater = 0; - minv = kdt->innerbuf.buf.ptr.p_double[0]; - maxv = kdt->innerbuf.buf.ptr.p_double[0]; - minidx = i1; - maxidx = i1; - for(i=0; i<=n-1; i++) - { - v = kdt->innerbuf.buf.ptr.p_double[i]; - if( vmaxv ) - { - maxv = v; - maxidx = i1+i; - } - if( vs ) - { - cntgreater = cntgreater+1; - } - } - if( minv==maxv ) - { - - /* - * In case all points has same value of D-th component - * (MinV=MaxV) we enforce D-th dimension of bounding - * box to become exactly zero and repeat tree construction. - */ - v0 = kdt->innerbuf.curboxmin.ptr.p_double[d]; - v1 = kdt->innerbuf.curboxmax.ptr.p_double[d]; - kdt->innerbuf.curboxmin.ptr.p_double[d] = minv; - kdt->innerbuf.curboxmax.ptr.p_double[d] = maxv; - nearestneighbor_kdtreegeneratetreerec(kdt, nodesoffs, splitsoffs, i1, i2, maxleafsize, _state); - kdt->innerbuf.curboxmin.ptr.p_double[d] = v0; - kdt->innerbuf.curboxmax.ptr.p_double[d] = v1; - return; - } - if( cntless>0&&cntgreater>0 ) - { - - /* - * normal midpoint split - */ - nearestneighbor_kdtreesplit(kdt, i1, i2, d, s, &i3, _state); - } - else - { - - /* - * sliding midpoint - */ - if( cntless==0 ) - { - - /* - * 1. move split to MinV, - * 2. place one point to the left bin (move to I1), - * others - to the right bin - */ - s = minv; - if( minidx!=i1 ) - { - for(i=0; i<=2*nx+ny-1; i++) - { - v = kdt->xy.ptr.pp_double[minidx][i]; - kdt->xy.ptr.pp_double[minidx][i] = kdt->xy.ptr.pp_double[i1][i]; - kdt->xy.ptr.pp_double[i1][i] = v; - } - j = kdt->tags.ptr.p_int[minidx]; - kdt->tags.ptr.p_int[minidx] = kdt->tags.ptr.p_int[i1]; - kdt->tags.ptr.p_int[i1] = j; - } - i3 = i1+1; - } - else - { - - /* - * 1. move split to MaxV, - * 2. place one point to the right bin (move to I2-1), - * others - to the left bin - */ - s = maxv; - if( maxidx!=i2-1 ) - { - for(i=0; i<=2*nx+ny-1; i++) - { - v = kdt->xy.ptr.pp_double[maxidx][i]; - kdt->xy.ptr.pp_double[maxidx][i] = kdt->xy.ptr.pp_double[i2-1][i]; - kdt->xy.ptr.pp_double[i2-1][i] = v; - } - j = kdt->tags.ptr.p_int[maxidx]; - kdt->tags.ptr.p_int[maxidx] = kdt->tags.ptr.p_int[i2-1]; - kdt->tags.ptr.p_int[i2-1] = j; - } - i3 = i2-1; - } - } - - /* - * Generate 'split' node - */ - kdt->nodes.ptr.p_int[*nodesoffs+0] = 0; - kdt->nodes.ptr.p_int[*nodesoffs+1] = d; - kdt->nodes.ptr.p_int[*nodesoffs+2] = *splitsoffs; - kdt->splits.ptr.p_double[*splitsoffs+0] = s; - oldoffs = *nodesoffs; - *nodesoffs = *nodesoffs+nearestneighbor_splitnodesize; - *splitsoffs = *splitsoffs+1; - - /* - * Recursive generation: - * * update CurBox - * * call subroutine - * * restore CurBox - */ - kdt->nodes.ptr.p_int[oldoffs+3] = *nodesoffs; - v = kdt->innerbuf.curboxmax.ptr.p_double[d]; - kdt->innerbuf.curboxmax.ptr.p_double[d] = s; - nearestneighbor_kdtreegeneratetreerec(kdt, nodesoffs, splitsoffs, i1, i3, maxleafsize, _state); - kdt->innerbuf.curboxmax.ptr.p_double[d] = v; - kdt->nodes.ptr.p_int[oldoffs+4] = *nodesoffs; - v = kdt->innerbuf.curboxmin.ptr.p_double[d]; - kdt->innerbuf.curboxmin.ptr.p_double[d] = s; - nearestneighbor_kdtreegeneratetreerec(kdt, nodesoffs, splitsoffs, i3, i2, maxleafsize, _state); - kdt->innerbuf.curboxmin.ptr.p_double[d] = v; - - /* - * Zero-fill unused portions of the node (avoid false warnings by Valgrind - * about attempt to serialize uninitialized values) - */ - ae_assert(nearestneighbor_splitnodesize==6, "KDTreeGenerateTreeRec: node size has unexpectedly changed", _state); - kdt->nodes.ptr.p_int[oldoffs+5] = 0; -} - - -/************************************************************************* -Recursive subroutine for NN queries. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -static void nearestneighbor_kdtreequerynnrec(kdtree* kdt, - kdtreerequestbuffer* buf, - ae_int_t offs, - ae_state *_state) -{ - double ptdist; - ae_int_t i; - ae_int_t j; - ae_int_t nx; - ae_int_t i1; - ae_int_t i2; - ae_int_t d; - double s; - double v; - double t1; - ae_int_t childbestoffs; - ae_int_t childworstoffs; - ae_int_t childoffs; - double prevdist; - ae_bool todive; - ae_bool bestisleft; - ae_bool updatemin; - - - ae_assert(kdt->n>0, "KDTreeQueryNNRec: internal error", _state); - - /* - * Leaf node. - * Process points. - */ - if( kdt->nodes.ptr.p_int[offs]>0 ) - { - i1 = kdt->nodes.ptr.p_int[offs+1]; - i2 = i1+kdt->nodes.ptr.p_int[offs]; - for(i=i1; i<=i2-1; i++) - { - - /* - * Calculate distance - */ - ptdist = (double)(0); - nx = kdt->nx; - if( kdt->normtype==0 ) - { - for(j=0; j<=nx-1; j++) - { - ptdist = ae_maxreal(ptdist, ae_fabs(kdt->xy.ptr.pp_double[i][j]-buf->x.ptr.p_double[j], _state), _state); - } - } - if( kdt->normtype==1 ) - { - for(j=0; j<=nx-1; j++) - { - ptdist = ptdist+ae_fabs(kdt->xy.ptr.pp_double[i][j]-buf->x.ptr.p_double[j], _state); - } - } - if( kdt->normtype==2 ) - { - for(j=0; j<=nx-1; j++) - { - ptdist = ptdist+ae_sqr(kdt->xy.ptr.pp_double[i][j]-buf->x.ptr.p_double[j], _state); - } - } - - /* - * Skip points with zero distance if self-matches are turned off - */ - if( ptdist==0&&!buf->selfmatch ) - { - continue; - } - - /* - * We CAN'T process point if R-criterion isn't satisfied, - * i.e. (RNeeded<>0) AND (PtDist>R). - */ - if( buf->rneeded==0||ptdist<=buf->rneeded ) - { - - /* - * R-criterion is satisfied, we must either: - * * replace worst point, if (KNeeded<>0) AND (KCur=KNeeded) - * (or skip, if worst point is better) - * * add point without replacement otherwise - */ - if( buf->kcurkneeded||buf->kneeded==0 ) - { - - /* - * add current point to heap without replacement - */ - tagheappushi(&buf->r, &buf->idx, &buf->kcur, ptdist, i, _state); - } - else - { - - /* - * New points are added or not, depending on their distance. - * If added, they replace element at the top of the heap - */ - if( ptdistr.ptr.p_double[0] ) - { - if( buf->kneeded==1 ) - { - buf->idx.ptr.p_int[0] = i; - buf->r.ptr.p_double[0] = ptdist; - } - else - { - tagheapreplacetopi(&buf->r, &buf->idx, buf->kneeded, ptdist, i, _state); - } - } - } - } - } - return; - } - - /* - * Simple split - */ - if( kdt->nodes.ptr.p_int[offs]==0 ) - { - - /* - * Load: - * * D dimension to split - * * S split position - */ - d = kdt->nodes.ptr.p_int[offs+1]; - s = kdt->splits.ptr.p_double[kdt->nodes.ptr.p_int[offs+2]]; - - /* - * Calculate: - * * ChildBestOffs child box with best chances - * * ChildWorstOffs child box with worst chances - */ - if( buf->x.ptr.p_double[d]<=s ) - { - childbestoffs = kdt->nodes.ptr.p_int[offs+3]; - childworstoffs = kdt->nodes.ptr.p_int[offs+4]; - bestisleft = ae_true; - } - else - { - childbestoffs = kdt->nodes.ptr.p_int[offs+4]; - childworstoffs = kdt->nodes.ptr.p_int[offs+3]; - bestisleft = ae_false; - } - - /* - * Navigate through childs - */ - for(i=0; i<=1; i++) - { - - /* - * Select child to process: - * * ChildOffs current child offset in Nodes[] - * * UpdateMin whether minimum or maximum value - * of bounding box is changed on update - */ - if( i==0 ) - { - childoffs = childbestoffs; - updatemin = !bestisleft; - } - else - { - updatemin = bestisleft; - childoffs = childworstoffs; - } - - /* - * Update bounding box and current distance - */ - if( updatemin ) - { - prevdist = buf->curdist; - t1 = buf->x.ptr.p_double[d]; - v = buf->curboxmin.ptr.p_double[d]; - if( t1<=s ) - { - if( kdt->normtype==0 ) - { - buf->curdist = ae_maxreal(buf->curdist, s-t1, _state); - } - if( kdt->normtype==1 ) - { - buf->curdist = buf->curdist-ae_maxreal(v-t1, (double)(0), _state)+s-t1; - } - if( kdt->normtype==2 ) - { - buf->curdist = buf->curdist-ae_sqr(ae_maxreal(v-t1, (double)(0), _state), _state)+ae_sqr(s-t1, _state); - } - } - buf->curboxmin.ptr.p_double[d] = s; - } - else - { - prevdist = buf->curdist; - t1 = buf->x.ptr.p_double[d]; - v = buf->curboxmax.ptr.p_double[d]; - if( t1>=s ) - { - if( kdt->normtype==0 ) - { - buf->curdist = ae_maxreal(buf->curdist, t1-s, _state); - } - if( kdt->normtype==1 ) - { - buf->curdist = buf->curdist-ae_maxreal(t1-v, (double)(0), _state)+t1-s; - } - if( kdt->normtype==2 ) - { - buf->curdist = buf->curdist-ae_sqr(ae_maxreal(t1-v, (double)(0), _state), _state)+ae_sqr(t1-s, _state); - } - } - buf->curboxmax.ptr.p_double[d] = s; - } - - /* - * Decide: to dive into cell or not to dive - */ - if( buf->rneeded!=0&&buf->curdist>buf->rneeded ) - { - todive = ae_false; - } - else - { - if( buf->kcurkneeded||buf->kneeded==0 ) - { - - /* - * KCurcurdist<=buf->r.ptr.p_double[0]*buf->approxf; - } - } - if( todive ) - { - nearestneighbor_kdtreequerynnrec(kdt, buf, childoffs, _state); - } - - /* - * Restore bounding box and distance - */ - if( updatemin ) - { - buf->curboxmin.ptr.p_double[d] = v; - } - else - { - buf->curboxmax.ptr.p_double[d] = v; - } - buf->curdist = prevdist; - } - return; - } -} - - -/************************************************************************* -Recursive subroutine for box queries. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -static void nearestneighbor_kdtreequeryboxrec(kdtree* kdt, - kdtreerequestbuffer* buf, - ae_int_t offs, - ae_state *_state) -{ - ae_bool inbox; - ae_int_t nx; - ae_int_t i1; - ae_int_t i2; - ae_int_t i; - ae_int_t j; - ae_int_t d; - double s; - double v; - - - ae_assert(kdt->n>0, "KDTreeQueryBoxRec: internal error", _state); - nx = kdt->nx; - - /* - * Check that intersection of query box with bounding box is non-empty. - * This check is performed once for Offs=0 (tree root). - */ - if( offs==0 ) - { - for(j=0; j<=nx-1; j++) - { - if( buf->boxmin.ptr.p_double[j]>buf->curboxmax.ptr.p_double[j] ) - { - return; - } - if( buf->boxmax.ptr.p_double[j]curboxmin.ptr.p_double[j] ) - { - return; - } - } - } - - /* - * Leaf node. - * Process points. - */ - if( kdt->nodes.ptr.p_int[offs]>0 ) - { - i1 = kdt->nodes.ptr.p_int[offs+1]; - i2 = i1+kdt->nodes.ptr.p_int[offs]; - for(i=i1; i<=i2-1; i++) - { - - /* - * Check whether point is in box or not - */ - inbox = ae_true; - for(j=0; j<=nx-1; j++) - { - inbox = inbox&&kdt->xy.ptr.pp_double[i][j]>=buf->boxmin.ptr.p_double[j]; - inbox = inbox&&kdt->xy.ptr.pp_double[i][j]<=buf->boxmax.ptr.p_double[j]; - } - if( !inbox ) - { - continue; - } - - /* - * Add point to unordered list - */ - buf->r.ptr.p_double[buf->kcur] = 0.0; - buf->idx.ptr.p_int[buf->kcur] = i; - buf->kcur = buf->kcur+1; - } - return; - } - - /* - * Simple split - */ - if( kdt->nodes.ptr.p_int[offs]==0 ) - { - - /* - * Load: - * * D dimension to split - * * S split position - */ - d = kdt->nodes.ptr.p_int[offs+1]; - s = kdt->splits.ptr.p_double[kdt->nodes.ptr.p_int[offs+2]]; - - /* - * Check lower split (S is upper bound of new bounding box) - */ - if( s>=buf->boxmin.ptr.p_double[d] ) - { - v = buf->curboxmax.ptr.p_double[d]; - buf->curboxmax.ptr.p_double[d] = s; - nearestneighbor_kdtreequeryboxrec(kdt, buf, kdt->nodes.ptr.p_int[offs+3], _state); - buf->curboxmax.ptr.p_double[d] = v; - } - - /* - * Check upper split (S is lower bound of new bounding box) - */ - if( s<=buf->boxmax.ptr.p_double[d] ) - { - v = buf->curboxmin.ptr.p_double[d]; - buf->curboxmin.ptr.p_double[d] = s; - nearestneighbor_kdtreequeryboxrec(kdt, buf, kdt->nodes.ptr.p_int[offs+4], _state); - buf->curboxmin.ptr.p_double[d] = v; - } - return; - } -} - - -/************************************************************************* -Copies X[] to Buf.X[] -Loads distance from X[] to bounding box. -Initializes Buf.CurBox[]. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -static void nearestneighbor_kdtreeinitbox(kdtree* kdt, - /* Real */ ae_vector* x, - kdtreerequestbuffer* buf, - ae_state *_state) -{ - ae_int_t i; - double vx; - double vmin; - double vmax; - - - ae_assert(kdt->n>0, "KDTreeInitBox: internal error", _state); - - /* - * calculate distance from point to current bounding box - */ - buf->curdist = (double)(0); - if( kdt->normtype==0 ) - { - for(i=0; i<=kdt->nx-1; i++) - { - vx = x->ptr.p_double[i]; - vmin = kdt->boxmin.ptr.p_double[i]; - vmax = kdt->boxmax.ptr.p_double[i]; - buf->x.ptr.p_double[i] = vx; - buf->curboxmin.ptr.p_double[i] = vmin; - buf->curboxmax.ptr.p_double[i] = vmax; - if( vxcurdist = ae_maxreal(buf->curdist, vmin-vx, _state); - } - else - { - if( vx>vmax ) - { - buf->curdist = ae_maxreal(buf->curdist, vx-vmax, _state); - } - } - } - } - if( kdt->normtype==1 ) - { - for(i=0; i<=kdt->nx-1; i++) - { - vx = x->ptr.p_double[i]; - vmin = kdt->boxmin.ptr.p_double[i]; - vmax = kdt->boxmax.ptr.p_double[i]; - buf->x.ptr.p_double[i] = vx; - buf->curboxmin.ptr.p_double[i] = vmin; - buf->curboxmax.ptr.p_double[i] = vmax; - if( vxcurdist = buf->curdist+vmin-vx; - } - else - { - if( vx>vmax ) - { - buf->curdist = buf->curdist+vx-vmax; - } - } - } - } - if( kdt->normtype==2 ) - { - for(i=0; i<=kdt->nx-1; i++) - { - vx = x->ptr.p_double[i]; - vmin = kdt->boxmin.ptr.p_double[i]; - vmax = kdt->boxmax.ptr.p_double[i]; - buf->x.ptr.p_double[i] = vx; - buf->curboxmin.ptr.p_double[i] = vmin; - buf->curboxmax.ptr.p_double[i] = vmax; - if( vxcurdist = buf->curdist+ae_sqr(vmin-vx, _state); - } - else - { - if( vx>vmax ) - { - buf->curdist = buf->curdist+ae_sqr(vx-vmax, _state); - } - } - } - } -} - - -/************************************************************************* -This function allocates all dataset-independend array fields of KDTree, -i.e. such array fields that their dimensions do not depend on dataset -size. - -This function do not sets KDT.NX or KDT.NY - it just allocates arrays - - -- ALGLIB -- - Copyright 14.03.2011 by Bochkanov Sergey -*************************************************************************/ -static void nearestneighbor_kdtreeallocdatasetindependent(kdtree* kdt, - ae_int_t nx, - ae_int_t ny, - ae_state *_state) -{ - - - ae_assert(kdt->n>0, "KDTreeAllocDatasetIndependent: internal error", _state); - ae_vector_set_length(&kdt->boxmin, nx, _state); - ae_vector_set_length(&kdt->boxmax, nx, _state); -} - - -/************************************************************************* -This function allocates all dataset-dependent array fields of KDTree, i.e. -such array fields that their dimensions depend on dataset size. - -This function do not sets KDT.N, KDT.NX or KDT.NY - -it just allocates arrays. - - -- ALGLIB -- - Copyright 14.03.2011 by Bochkanov Sergey -*************************************************************************/ -static void nearestneighbor_kdtreeallocdatasetdependent(kdtree* kdt, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - ae_state *_state) -{ - - - ae_assert(n>0, "KDTreeAllocDatasetDependent: internal error", _state); - ae_matrix_set_length(&kdt->xy, n, 2*nx+ny, _state); - ae_vector_set_length(&kdt->tags, n, _state); - ae_vector_set_length(&kdt->nodes, nearestneighbor_splitnodesize*2*n, _state); - ae_vector_set_length(&kdt->splits, 2*n, _state); -} - - -/************************************************************************* -This function checks consistency of request buffer structure with -dimensions of kd-tree object. - - -- ALGLIB -- - Copyright 02.04.2016 by Bochkanov Sergey -*************************************************************************/ -static void nearestneighbor_checkrequestbufferconsistency(kdtree* kdt, - kdtreerequestbuffer* buf, - ae_state *_state) -{ - - - ae_assert(buf->x.cnt>=kdt->nx, "KDTree: dimensions of kdtreerequestbuffer are inconsistent with kdtree structure", _state); - ae_assert(buf->idx.cnt>=kdt->n, "KDTree: dimensions of kdtreerequestbuffer are inconsistent with kdtree structure", _state); - ae_assert(buf->r.cnt>=kdt->n, "KDTree: dimensions of kdtreerequestbuffer are inconsistent with kdtree structure", _state); - ae_assert(buf->buf.cnt>=ae_maxint(kdt->n, kdt->nx, _state), "KDTree: dimensions of kdtreerequestbuffer are inconsistent with kdtree structure", _state); - ae_assert(buf->curboxmin.cnt>=kdt->nx, "KDTree: dimensions of kdtreerequestbuffer are inconsistent with kdtree structure", _state); - ae_assert(buf->curboxmax.cnt>=kdt->nx, "KDTree: dimensions of kdtreerequestbuffer are inconsistent with kdtree structure", _state); -} - - -void _kdtreerequestbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - kdtreerequestbuffer *p = (kdtreerequestbuffer*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->boxmin, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->boxmax, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->idx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->r, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->buf, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->curboxmin, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->curboxmax, 0, DT_REAL, _state, make_automatic); -} - - -void _kdtreerequestbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - kdtreerequestbuffer *dst = (kdtreerequestbuffer*)_dst; - kdtreerequestbuffer *src = (kdtreerequestbuffer*)_src; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->boxmin, &src->boxmin, _state, make_automatic); - ae_vector_init_copy(&dst->boxmax, &src->boxmax, _state, make_automatic); - dst->kneeded = src->kneeded; - dst->rneeded = src->rneeded; - dst->selfmatch = src->selfmatch; - dst->approxf = src->approxf; - dst->kcur = src->kcur; - ae_vector_init_copy(&dst->idx, &src->idx, _state, make_automatic); - ae_vector_init_copy(&dst->r, &src->r, _state, make_automatic); - ae_vector_init_copy(&dst->buf, &src->buf, _state, make_automatic); - ae_vector_init_copy(&dst->curboxmin, &src->curboxmin, _state, make_automatic); - ae_vector_init_copy(&dst->curboxmax, &src->curboxmax, _state, make_automatic); - dst->curdist = src->curdist; -} - - -void _kdtreerequestbuffer_clear(void* _p) -{ - kdtreerequestbuffer *p = (kdtreerequestbuffer*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->x); - ae_vector_clear(&p->boxmin); - ae_vector_clear(&p->boxmax); - ae_vector_clear(&p->idx); - ae_vector_clear(&p->r); - ae_vector_clear(&p->buf); - ae_vector_clear(&p->curboxmin); - ae_vector_clear(&p->curboxmax); -} - - -void _kdtreerequestbuffer_destroy(void* _p) -{ - kdtreerequestbuffer *p = (kdtreerequestbuffer*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->boxmin); - ae_vector_destroy(&p->boxmax); - ae_vector_destroy(&p->idx); - ae_vector_destroy(&p->r); - ae_vector_destroy(&p->buf); - ae_vector_destroy(&p->curboxmin); - ae_vector_destroy(&p->curboxmax); -} - - -void _kdtree_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - kdtree *p = (kdtree*)_p; - ae_touch_ptr((void*)p); - ae_matrix_init(&p->xy, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tags, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->boxmin, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->boxmax, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->nodes, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->splits, 0, DT_REAL, _state, make_automatic); - _kdtreerequestbuffer_init(&p->innerbuf, _state, make_automatic); -} - - -void _kdtree_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - kdtree *dst = (kdtree*)_dst; - kdtree *src = (kdtree*)_src; - dst->n = src->n; - dst->nx = src->nx; - dst->ny = src->ny; - dst->normtype = src->normtype; - ae_matrix_init_copy(&dst->xy, &src->xy, _state, make_automatic); - ae_vector_init_copy(&dst->tags, &src->tags, _state, make_automatic); - ae_vector_init_copy(&dst->boxmin, &src->boxmin, _state, make_automatic); - ae_vector_init_copy(&dst->boxmax, &src->boxmax, _state, make_automatic); - ae_vector_init_copy(&dst->nodes, &src->nodes, _state, make_automatic); - ae_vector_init_copy(&dst->splits, &src->splits, _state, make_automatic); - _kdtreerequestbuffer_init_copy(&dst->innerbuf, &src->innerbuf, _state, make_automatic); - dst->debugcounter = src->debugcounter; -} - - -void _kdtree_clear(void* _p) -{ - kdtree *p = (kdtree*)_p; - ae_touch_ptr((void*)p); - ae_matrix_clear(&p->xy); - ae_vector_clear(&p->tags); - ae_vector_clear(&p->boxmin); - ae_vector_clear(&p->boxmax); - ae_vector_clear(&p->nodes); - ae_vector_clear(&p->splits); - _kdtreerequestbuffer_clear(&p->innerbuf); -} - - -void _kdtree_destroy(void* _p) -{ - kdtree *p = (kdtree*)_p; - ae_touch_ptr((void*)p); - ae_matrix_destroy(&p->xy); - ae_vector_destroy(&p->tags); - ae_vector_destroy(&p->boxmin); - ae_vector_destroy(&p->boxmax); - ae_vector_destroy(&p->nodes); - ae_vector_destroy(&p->splits); - _kdtreerequestbuffer_destroy(&p->innerbuf); -} - - -#endif -#if defined(AE_COMPILE_HQRND) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -HQRNDState initialization with random values which come from standard -RNG. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void hqrndrandomize(hqrndstate* state, ae_state *_state) -{ - ae_int_t s0; - ae_int_t s1; - - _hqrndstate_clear(state); - - s0 = ae_randominteger(hqrnd_hqrndm1, _state); - s1 = ae_randominteger(hqrnd_hqrndm2, _state); - hqrndseed(s0, s1, state, _state); -} - - -/************************************************************************* -HQRNDState initialization with seed values - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void hqrndseed(ae_int_t s1, - ae_int_t s2, - hqrndstate* state, - ae_state *_state) -{ - - _hqrndstate_clear(state); - - - /* - * Protection against negative seeds: - * - * SEED := -(SEED+1) - * - * We can use just "-SEED" because there exists such integer number N - * that N<0, -N=N<0 too. (This number is equal to 0x800...000). Need - * to handle such seed correctly forces us to use a bit complicated - * formula. - */ - if( s1<0 ) - { - s1 = -(s1+1); - } - if( s2<0 ) - { - s2 = -(s2+1); - } - state->s1 = s1%(hqrnd_hqrndm1-1)+1; - state->s2 = s2%(hqrnd_hqrndm2-1)+1; - state->magicv = hqrnd_hqrndmagic; -} - - -/************************************************************************* -This function generates random real number in (0,1), -not including interval boundaries - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -double hqrnduniformr(hqrndstate* state, ae_state *_state) -{ - double result; - - - result = (double)(hqrnd_hqrndintegerbase(state, _state)+1)/(double)(hqrnd_hqrndmax+2); - return result; -} - - -/************************************************************************* -This function generates random integer number in [0, N) - -1. State structure must be initialized with HQRNDRandomize() or HQRNDSeed() -2. N can be any positive number except for very large numbers: - * close to 2^31 on 32-bit systems - * close to 2^62 on 64-bit systems - An exception will be generated if N is too large. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -ae_int_t hqrnduniformi(hqrndstate* state, ae_int_t n, ae_state *_state) -{ - ae_int_t maxcnt; - ae_int_t mx; - ae_int_t a; - ae_int_t b; - ae_int_t result; - - - ae_assert(n>0, "HQRNDUniformI: N<=0!", _state); - maxcnt = hqrnd_hqrndmax+1; - - /* - * Two branches: one for N<=MaxCnt, another for N>MaxCnt. - */ - if( n>maxcnt ) - { - - /* - * N>=MaxCnt. - * - * We have two options here: - * a) N is exactly divisible by MaxCnt - * b) N is not divisible by MaxCnt - * - * In both cases we reduce problem on interval spanning [0,N) - * to several subproblems on intervals spanning [0,MaxCnt). - */ - if( n%maxcnt==0 ) - { - - /* - * N is exactly divisible by MaxCnt. - * - * [0,N) range is dividided into N/MaxCnt bins, - * each of them having length equal to MaxCnt. - * - * We generate: - * * random bin number B - * * random offset within bin A - * Both random numbers are generated by recursively - * calling HQRNDUniformI(). - * - * Result is equal to A+MaxCnt*B. - */ - ae_assert(n/maxcnt<=maxcnt, "HQRNDUniformI: N is too large", _state); - a = hqrnduniformi(state, maxcnt, _state); - b = hqrnduniformi(state, n/maxcnt, _state); - result = a+maxcnt*b; - } - else - { - - /* - * N is NOT exactly divisible by MaxCnt. - * - * [0,N) range is dividided into Ceil(N/MaxCnt) bins, - * each of them having length equal to MaxCnt. - * - * We generate: - * * random bin number B in [0, Ceil(N/MaxCnt)-1] - * * random offset within bin A - * * if both of what is below is true - * 1) bin number B is that of the last bin - * 2) A >= N mod MaxCnt - * then we repeat generation of A/B. - * This stage is essential in order to avoid bias in the result. - * * otherwise, we return A*MaxCnt+N - */ - ae_assert(n/maxcnt+1<=maxcnt, "HQRNDUniformI: N is too large", _state); - result = -1; - do - { - a = hqrnduniformi(state, maxcnt, _state); - b = hqrnduniformi(state, n/maxcnt+1, _state); - if( b==n/maxcnt&&a>=n%maxcnt ) - { - continue; - } - result = a+maxcnt*b; - } - while(result<0); - } - } - else - { - - /* - * N<=MaxCnt - * - * Code below is a bit complicated because we can not simply - * return "HQRNDIntegerBase() mod N" - it will be skewed for - * large N's in [0.1*HQRNDMax...HQRNDMax]. - */ - mx = maxcnt-maxcnt%n; - do - { - result = hqrnd_hqrndintegerbase(state, _state); - } - while(result>=mx); - result = result%n; - } - return result; -} - - -/************************************************************************* -Random number generator: normal numbers - -This function generates one random number from normal distribution. -Its performance is equal to that of HQRNDNormal2() - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -double hqrndnormal(hqrndstate* state, ae_state *_state) -{ - double v1; - double v2; - double result; - - - hqrndnormal2(state, &v1, &v2, _state); - result = v1; - return result; -} - - -/************************************************************************* -Random number generator: vector with random entries (normal distribution) - -This function generates N random numbers from normal distribution. - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void hqrndnormalv(hqrndstate* state, - ae_int_t n, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n2; - double v1; - double v2; - - ae_vector_clear(x); - - n2 = n/2; - rallocv(n, x, _state); - for(i=0; i<=n2-1; i++) - { - hqrndnormal2(state, &v1, &v2, _state); - x->ptr.p_double[2*i+0] = v1; - x->ptr.p_double[2*i+1] = v2; - } - if( n%2!=0 ) - { - hqrndnormal2(state, &v1, &v2, _state); - x->ptr.p_double[n-1] = v1; - } -} - - -/************************************************************************* -Random number generator: matrix with random entries (normal distribution) - -This function generates MxN random matrix. - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void hqrndnormalm(hqrndstate* state, - ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* x, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t n2; - double v1; - double v2; - - ae_matrix_clear(x); - - n2 = n/2; - ae_matrix_set_length(x, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n2-1; j++) - { - hqrndnormal2(state, &v1, &v2, _state); - x->ptr.pp_double[i][2*j+0] = v1; - x->ptr.pp_double[i][2*j+1] = v2; - } - if( n%2!=0 ) - { - hqrndnormal2(state, &v1, &v2, _state); - x->ptr.pp_double[i][n-1] = v1; - } - } -} - - -/************************************************************************* -Random number generator: random X and Y such that X^2+Y^2=1 - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void hqrndunit2(hqrndstate* state, double* x, double* y, ae_state *_state) -{ - double v; - double mx; - double mn; - - *x = 0; - *y = 0; - - do - { - hqrndnormal2(state, x, y, _state); - } - while(!(ae_fp_neq(*x,(double)(0))||ae_fp_neq(*y,(double)(0)))); - mx = ae_maxreal(ae_fabs(*x, _state), ae_fabs(*y, _state), _state); - mn = ae_minreal(ae_fabs(*x, _state), ae_fabs(*y, _state), _state); - v = mx*ae_sqrt(1+ae_sqr(mn/mx, _state), _state); - *x = *x/v; - *y = *y/v; -} - - -/************************************************************************* -Random number generator: normal numbers - -This function generates two independent random numbers from normal -distribution. Its performance is equal to that of HQRNDNormal() - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void hqrndnormal2(hqrndstate* state, - double* x1, - double* x2, - ae_state *_state) -{ - double u; - double v; - double s; - - *x1 = 0; - *x2 = 0; - - for(;;) - { - u = 2*hqrnduniformr(state, _state)-1; - v = 2*hqrnduniformr(state, _state)-1; - s = ae_sqr(u, _state)+ae_sqr(v, _state); - if( ae_fp_greater(s,(double)(0))&&ae_fp_less(s,(double)(1)) ) - { - - /* - * two Sqrt's instead of one to - * avoid overflow when S is too small - */ - s = ae_sqrt(-2*ae_log(s, _state), _state)/ae_sqrt(s, _state); - *x1 = u*s; - *x2 = v*s; - return; - } - } -} - - -/************************************************************************* -Random number generator: exponential distribution - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 11.08.2007 by Bochkanov Sergey -*************************************************************************/ -double hqrndexponential(hqrndstate* state, - double lambdav, - ae_state *_state) -{ - double result; - - - ae_assert(ae_fp_greater(lambdav,(double)(0)), "HQRNDExponential: LambdaV<=0!", _state); - result = -ae_log(hqrnduniformr(state, _state), _state)/lambdav; - return result; -} - - -/************************************************************************* -This function generates random number from discrete distribution given by -finite sample X. - -INPUT PARAMETERS - State - high quality random number generator, must be - initialized with HQRNDRandomize() or HQRNDSeed(). - X - finite sample - N - number of elements to use, N>=1 - -RESULT - this function returns one of the X[i] for random i=0..N-1 - - -- ALGLIB -- - Copyright 08.11.2011 by Bochkanov Sergey -*************************************************************************/ -double hqrnddiscrete(hqrndstate* state, - /* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state) -{ - double result; - - - ae_assert(n>0, "HQRNDDiscrete: N<=0", _state); - ae_assert(n<=x->cnt, "HQRNDDiscrete: Length(X)ptr.p_double[hqrnduniformi(state, n, _state)]; - return result; -} - - -/************************************************************************* -This function generates random number from continuous distribution given -by finite sample X. - -INPUT PARAMETERS - State - high quality random number generator, must be - initialized with HQRNDRandomize() or HQRNDSeed(). - X - finite sample, array[N] (can be larger, in this case only - leading N elements are used). THIS ARRAY MUST BE SORTED BY - ASCENDING. - N - number of elements to use, N>=1 - -RESULT - this function returns random number from continuous distribution which - tries to approximate X as mush as possible. min(X)<=Result<=max(X). - - -- ALGLIB -- - Copyright 08.11.2011 by Bochkanov Sergey -*************************************************************************/ -double hqrndcontinuous(hqrndstate* state, - /* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state) -{ - double mx; - double mn; - ae_int_t i; - double result; - - - ae_assert(n>0, "HQRNDContinuous: N<=0", _state); - ae_assert(n<=x->cnt, "HQRNDContinuous: Length(X)ptr.p_double[0]; - return result; - } - i = hqrnduniformi(state, n-1, _state); - mn = x->ptr.p_double[i]; - mx = x->ptr.p_double[i+1]; - ae_assert(ae_fp_greater_eq(mx,mn), "HQRNDDiscrete: X is not sorted by ascending", _state); - if( ae_fp_neq(mx,mn) ) - { - result = (mx-mn)*hqrnduniformr(state, _state)+mn; - } - else - { - result = mn; - } - return result; -} - - -/************************************************************************* -This function returns random integer in [0,HQRNDMax] - -L'Ecuyer, Efficient and portable combined random number generators -*************************************************************************/ -static ae_int_t hqrnd_hqrndintegerbase(hqrndstate* state, - ae_state *_state) -{ - ae_int_t k; - ae_int_t result; - - - ae_assert(state->magicv==hqrnd_hqrndmagic, "HQRNDIntegerBase: State is not correctly initialized!", _state); - k = state->s1/53668; - state->s1 = 40014*(state->s1-k*53668)-k*12211; - if( state->s1<0 ) - { - state->s1 = state->s1+2147483563; - } - k = state->s2/52774; - state->s2 = 40692*(state->s2-k*52774)-k*3791; - if( state->s2<0 ) - { - state->s2 = state->s2+2147483399; - } - - /* - * Result - */ - result = state->s1-state->s2; - if( result<1 ) - { - result = result+2147483562; - } - result = result-1; - return result; -} - - -void _hqrndstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - hqrndstate *p = (hqrndstate*)_p; - ae_touch_ptr((void*)p); -} - - -void _hqrndstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - hqrndstate *dst = (hqrndstate*)_dst; - hqrndstate *src = (hqrndstate*)_src; - dst->s1 = src->s1; - dst->s2 = src->s2; - dst->magicv = src->magicv; -} - - -void _hqrndstate_clear(void* _p) -{ - hqrndstate *p = (hqrndstate*)_p; - ae_touch_ptr((void*)p); -} - - -void _hqrndstate_destroy(void* _p) -{ - hqrndstate *p = (hqrndstate*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_XDEBUG) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Creates and returns XDebugRecord1 structure: -* integer and complex fields of Rec1 are set to 1 and 1+i correspondingly -* array field of Rec1 is set to [2,3] - - -- ALGLIB -- - Copyright 27.05.2014 by Bochkanov Sergey -*************************************************************************/ -void xdebuginitrecord1(xdebugrecord1* rec1, ae_state *_state) -{ - - _xdebugrecord1_clear(rec1); - - rec1->i = 1; - rec1->c.x = (double)(1); - rec1->c.y = (double)(1); - ae_vector_set_length(&rec1->a, 2, _state); - rec1->a.ptr.p_double[0] = (double)(2); - rec1->a.ptr.p_double[1] = (double)(3); -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Counts number of True values in the boolean 1D array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -ae_int_t xdebugb1count(/* Boolean */ ae_vector* a, ae_state *_state) -{ - ae_int_t i; - ae_int_t result; - - - result = 0; - for(i=0; i<=a->cnt-1; i++) - { - if( a->ptr.p_bool[i] ) - { - result = result+1; - } - } - return result; -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by NOT(a[i]). -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugb1not(/* Boolean */ ae_vector* a, ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=a->cnt-1; i++) - { - a->ptr.p_bool[i] = !a->ptr.p_bool[i]; - } -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Appends copy of array to itself. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugb1appendcopy(/* Boolean */ ae_vector* a, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_vector b; - - ae_frame_make(_state, &_frame_block); - memset(&b, 0, sizeof(b)); - ae_vector_init(&b, 0, DT_BOOL, _state, ae_true); - - ae_vector_set_length(&b, a->cnt, _state); - for(i=0; i<=b.cnt-1; i++) - { - b.ptr.p_bool[i] = a->ptr.p_bool[i]; - } - ae_vector_set_length(a, 2*b.cnt, _state); - for(i=0; i<=a->cnt-1; i++) - { - a->ptr.p_bool[i] = b.ptr.p_bool[i%b.cnt]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate N-element array with even-numbered elements set to True. -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugb1outeven(ae_int_t n, - /* Boolean */ ae_vector* a, - ae_state *_state) -{ - ae_int_t i; - - ae_vector_clear(a); - - ae_vector_set_length(a, n, _state); - for(i=0; i<=a->cnt-1; i++) - { - a->ptr.p_bool[i] = i%2==0; - } -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -ae_int_t xdebugi1sum(/* Integer */ ae_vector* a, ae_state *_state) -{ - ae_int_t i; - ae_int_t result; - - - result = 0; - for(i=0; i<=a->cnt-1; i++) - { - result = result+a->ptr.p_int[i]; - } - return result; -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -A[I] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugi1neg(/* Integer */ ae_vector* a, ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=a->cnt-1; i++) - { - a->ptr.p_int[i] = -a->ptr.p_int[i]; - } -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Appends copy of array to itself. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugi1appendcopy(/* Integer */ ae_vector* a, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_vector b; - - ae_frame_make(_state, &_frame_block); - memset(&b, 0, sizeof(b)); - ae_vector_init(&b, 0, DT_INT, _state, ae_true); - - ae_vector_set_length(&b, a->cnt, _state); - for(i=0; i<=b.cnt-1; i++) - { - b.ptr.p_int[i] = a->ptr.p_int[i]; - } - ae_vector_set_length(a, 2*b.cnt, _state); - for(i=0; i<=a->cnt-1; i++) - { - a->ptr.p_int[i] = b.ptr.p_int[i%b.cnt]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate N-element array with even-numbered A[I] set to I, and odd-numbered -ones set to 0. - -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugi1outeven(ae_int_t n, - /* Integer */ ae_vector* a, - ae_state *_state) -{ - ae_int_t i; - - ae_vector_clear(a); - - ae_vector_set_length(a, n, _state); - for(i=0; i<=a->cnt-1; i++) - { - if( i%2==0 ) - { - a->ptr.p_int[i] = i; - } - else - { - a->ptr.p_int[i] = 0; - } - } -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -double xdebugr1sum(/* Real */ ae_vector* a, ae_state *_state) -{ - ae_int_t i; - double result; - - - result = (double)(0); - for(i=0; i<=a->cnt-1; i++) - { - result = result+a->ptr.p_double[i]; - } - return result; -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -A[I] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugr1neg(/* Real */ ae_vector* a, ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=a->cnt-1; i++) - { - a->ptr.p_double[i] = -a->ptr.p_double[i]; - } -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Appends copy of array to itself. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugr1appendcopy(/* Real */ ae_vector* a, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_vector b; - - ae_frame_make(_state, &_frame_block); - memset(&b, 0, sizeof(b)); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&b, a->cnt, _state); - for(i=0; i<=b.cnt-1; i++) - { - b.ptr.p_double[i] = a->ptr.p_double[i]; - } - ae_vector_set_length(a, 2*b.cnt, _state); - for(i=0; i<=a->cnt-1; i++) - { - a->ptr.p_double[i] = b.ptr.p_double[i%b.cnt]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate N-element array with even-numbered A[I] set to I*0.25, -and odd-numbered ones are set to 0. - -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugr1outeven(ae_int_t n, - /* Real */ ae_vector* a, - ae_state *_state) -{ - ae_int_t i; - - ae_vector_clear(a); - - ae_vector_set_length(a, n, _state); - for(i=0; i<=a->cnt-1; i++) - { - if( i%2==0 ) - { - a->ptr.p_double[i] = i*0.25; - } - else - { - a->ptr.p_double[i] = (double)(0); - } - } -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -ae_complex xdebugc1sum(/* Complex */ ae_vector* a, ae_state *_state) -{ - ae_int_t i; - ae_complex result; - - - result = ae_complex_from_i(0); - for(i=0; i<=a->cnt-1; i++) - { - result = ae_c_add(result,a->ptr.p_complex[i]); - } - return result; -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -A[I] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugc1neg(/* Complex */ ae_vector* a, ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=a->cnt-1; i++) - { - a->ptr.p_complex[i] = ae_c_neg(a->ptr.p_complex[i]); - } -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Appends copy of array to itself. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugc1appendcopy(/* Complex */ ae_vector* a, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_vector b; - - ae_frame_make(_state, &_frame_block); - memset(&b, 0, sizeof(b)); - ae_vector_init(&b, 0, DT_COMPLEX, _state, ae_true); - - ae_vector_set_length(&b, a->cnt, _state); - for(i=0; i<=b.cnt-1; i++) - { - b.ptr.p_complex[i] = a->ptr.p_complex[i]; - } - ae_vector_set_length(a, 2*b.cnt, _state); - for(i=0; i<=a->cnt-1; i++) - { - a->ptr.p_complex[i] = b.ptr.p_complex[i%b.cnt]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate N-element array with even-numbered A[K] set to (x,y) = (K*0.25, K*0.125) -and odd-numbered ones are set to 0. - -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugc1outeven(ae_int_t n, - /* Complex */ ae_vector* a, - ae_state *_state) -{ - ae_int_t i; - - ae_vector_clear(a); - - ae_vector_set_length(a, n, _state); - for(i=0; i<=a->cnt-1; i++) - { - if( i%2==0 ) - { - a->ptr.p_complex[i].x = i*0.250; - a->ptr.p_complex[i].y = i*0.125; - } - else - { - a->ptr.p_complex[i] = ae_complex_from_i(0); - } - } -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Counts number of True values in the boolean 2D array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -ae_int_t xdebugb2count(/* Boolean */ ae_matrix* a, ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t result; - - - result = 0; - for(i=0; i<=a->rows-1; i++) - { - for(j=0; j<=a->cols-1; j++) - { - if( a->ptr.pp_bool[i][j] ) - { - result = result+1; - } - } - } - return result; -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by NOT(a[i]). -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugb2not(/* Boolean */ ae_matrix* a, ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - for(i=0; i<=a->rows-1; i++) - { - for(j=0; j<=a->cols-1; j++) - { - a->ptr.pp_bool[i][j] = !a->ptr.pp_bool[i][j]; - } - } -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Transposes array. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugb2transpose(/* Boolean */ ae_matrix* a, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_matrix b; - - ae_frame_make(_state, &_frame_block); - memset(&b, 0, sizeof(b)); - ae_matrix_init(&b, 0, 0, DT_BOOL, _state, ae_true); - - ae_matrix_set_length(&b, a->rows, a->cols, _state); - for(i=0; i<=b.rows-1; i++) - { - for(j=0; j<=b.cols-1; j++) - { - b.ptr.pp_bool[i][j] = a->ptr.pp_bool[i][j]; - } - } - ae_matrix_set_length(a, b.cols, b.rows, _state); - for(i=0; i<=b.rows-1; i++) - { - for(j=0; j<=b.cols-1; j++) - { - a->ptr.pp_bool[j][i] = b.ptr.pp_bool[i][j]; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate MxN matrix with elements set to "Sin(3*I+5*J)>0" -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugb2outsin(ae_int_t m, - ae_int_t n, - /* Boolean */ ae_matrix* a, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(a); - - ae_matrix_set_length(a, m, n, _state); - for(i=0; i<=a->rows-1; i++) - { - for(j=0; j<=a->cols-1; j++) - { - a->ptr.pp_bool[i][j] = ae_fp_greater(ae_sin((double)(3*i+5*j), _state),(double)(0)); - } - } -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -ae_int_t xdebugi2sum(/* Integer */ ae_matrix* a, ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t result; - - - result = 0; - for(i=0; i<=a->rows-1; i++) - { - for(j=0; j<=a->cols-1; j++) - { - result = result+a->ptr.pp_int[i][j]; - } - } - return result; -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -a[i,j] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugi2neg(/* Integer */ ae_matrix* a, ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - for(i=0; i<=a->rows-1; i++) - { - for(j=0; j<=a->cols-1; j++) - { - a->ptr.pp_int[i][j] = -a->ptr.pp_int[i][j]; - } - } -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Transposes array. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugi2transpose(/* Integer */ ae_matrix* a, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_matrix b; - - ae_frame_make(_state, &_frame_block); - memset(&b, 0, sizeof(b)); - ae_matrix_init(&b, 0, 0, DT_INT, _state, ae_true); - - ae_matrix_set_length(&b, a->rows, a->cols, _state); - for(i=0; i<=b.rows-1; i++) - { - for(j=0; j<=b.cols-1; j++) - { - b.ptr.pp_int[i][j] = a->ptr.pp_int[i][j]; - } - } - ae_matrix_set_length(a, b.cols, b.rows, _state); - for(i=0; i<=b.rows-1; i++) - { - for(j=0; j<=b.cols-1; j++) - { - a->ptr.pp_int[j][i] = b.ptr.pp_int[i][j]; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate MxN matrix with elements set to "Sign(Sin(3*I+5*J))" -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugi2outsin(ae_int_t m, - ae_int_t n, - /* Integer */ ae_matrix* a, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(a); - - ae_matrix_set_length(a, m, n, _state); - for(i=0; i<=a->rows-1; i++) - { - for(j=0; j<=a->cols-1; j++) - { - a->ptr.pp_int[i][j] = ae_sign(ae_sin((double)(3*i+5*j), _state), _state); - } - } -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -double xdebugr2sum(/* Real */ ae_matrix* a, ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double result; - - - result = (double)(0); - for(i=0; i<=a->rows-1; i++) - { - for(j=0; j<=a->cols-1; j++) - { - result = result+a->ptr.pp_double[i][j]; - } - } - return result; -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -a[i,j] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugr2neg(/* Real */ ae_matrix* a, ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - for(i=0; i<=a->rows-1; i++) - { - for(j=0; j<=a->cols-1; j++) - { - a->ptr.pp_double[i][j] = -a->ptr.pp_double[i][j]; - } - } -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Transposes array. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugr2transpose(/* Real */ ae_matrix* a, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_matrix b; - - ae_frame_make(_state, &_frame_block); - memset(&b, 0, sizeof(b)); - ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true); - - ae_matrix_set_length(&b, a->rows, a->cols, _state); - for(i=0; i<=b.rows-1; i++) - { - for(j=0; j<=b.cols-1; j++) - { - b.ptr.pp_double[i][j] = a->ptr.pp_double[i][j]; - } - } - ae_matrix_set_length(a, b.cols, b.rows, _state); - for(i=0; i<=b.rows-1; i++) - { - for(j=0; j<=b.cols-1; j++) - { - a->ptr.pp_double[j][i] = b.ptr.pp_double[i][j]; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate MxN matrix with elements set to "Sin(3*I+5*J)" -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugr2outsin(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(a); - - ae_matrix_set_length(a, m, n, _state); - for(i=0; i<=a->rows-1; i++) - { - for(j=0; j<=a->cols-1; j++) - { - a->ptr.pp_double[i][j] = ae_sin((double)(3*i+5*j), _state); - } - } -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -ae_complex xdebugc2sum(/* Complex */ ae_matrix* a, ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_complex result; - - - result = ae_complex_from_i(0); - for(i=0; i<=a->rows-1; i++) - { - for(j=0; j<=a->cols-1; j++) - { - result = ae_c_add(result,a->ptr.pp_complex[i][j]); - } - } - return result; -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -a[i,j] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugc2neg(/* Complex */ ae_matrix* a, ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - for(i=0; i<=a->rows-1; i++) - { - for(j=0; j<=a->cols-1; j++) - { - a->ptr.pp_complex[i][j] = ae_c_neg(a->ptr.pp_complex[i][j]); - } - } -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Transposes array. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugc2transpose(/* Complex */ ae_matrix* a, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_matrix b; - - ae_frame_make(_state, &_frame_block); - memset(&b, 0, sizeof(b)); - ae_matrix_init(&b, 0, 0, DT_COMPLEX, _state, ae_true); - - ae_matrix_set_length(&b, a->rows, a->cols, _state); - for(i=0; i<=b.rows-1; i++) - { - for(j=0; j<=b.cols-1; j++) - { - b.ptr.pp_complex[i][j] = a->ptr.pp_complex[i][j]; - } - } - ae_matrix_set_length(a, b.cols, b.rows, _state); - for(i=0; i<=b.rows-1; i++) - { - for(j=0; j<=b.cols-1; j++) - { - a->ptr.pp_complex[j][i] = b.ptr.pp_complex[i][j]; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate MxN matrix with elements set to "Sin(3*I+5*J),Cos(3*I+5*J)" -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugc2outsincos(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(a); - - ae_matrix_set_length(a, m, n, _state); - for(i=0; i<=a->rows-1; i++) - { - for(j=0; j<=a->cols-1; j++) - { - a->ptr.pp_complex[i][j].x = ae_sin((double)(3*i+5*j), _state); - a->ptr.pp_complex[i][j].y = ae_cos((double)(3*i+5*j), _state); - } - } -} - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of a[i,j]*(1+b[i,j]) such that c[i,j] is True - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -double xdebugmaskedbiasedproductsum(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - /* Real */ ae_matrix* b, - /* Boolean */ ae_matrix* c, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double result; - - - ae_assert(m>=a->rows, "Assertion failed", _state); - ae_assert(m>=b->rows, "Assertion failed", _state); - ae_assert(m>=c->rows, "Assertion failed", _state); - ae_assert(n>=a->cols, "Assertion failed", _state); - ae_assert(n>=b->cols, "Assertion failed", _state); - ae_assert(n>=c->cols, "Assertion failed", _state); - result = 0.0; - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( c->ptr.pp_bool[i][j] ) - { - result = result+a->ptr.pp_double[i][j]*(1+b->ptr.pp_double[i][j]); - } - } - } - return result; -} - - -void _xdebugrecord1_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - xdebugrecord1 *p = (xdebugrecord1*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->a, 0, DT_REAL, _state, make_automatic); -} - - -void _xdebugrecord1_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - xdebugrecord1 *dst = (xdebugrecord1*)_dst; - xdebugrecord1 *src = (xdebugrecord1*)_src; - dst->i = src->i; - dst->c = src->c; - ae_vector_init_copy(&dst->a, &src->a, _state, make_automatic); -} - - -void _xdebugrecord1_clear(void* _p) -{ - xdebugrecord1 *p = (xdebugrecord1*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->a); -} - - -void _xdebugrecord1_destroy(void* _p) -{ - xdebugrecord1 *p = (xdebugrecord1*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->a); -} - - -#endif - -} - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/alglibmisc.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/alglibmisc.h deleted file mode 100644 index aaad920..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/alglibmisc.h +++ /dev/null @@ -1,2043 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifndef _alglibmisc_pkg_h -#define _alglibmisc_pkg_h -#include "ap.h" -#include "alglibinternal.h" - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (DATATYPES) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_NEARESTNEIGHBOR) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_vector x; - ae_vector boxmin; - ae_vector boxmax; - ae_int_t kneeded; - double rneeded; - ae_bool selfmatch; - double approxf; - ae_int_t kcur; - ae_vector idx; - ae_vector r; - ae_vector buf; - ae_vector curboxmin; - ae_vector curboxmax; - double curdist; -} kdtreerequestbuffer; -typedef struct -{ - ae_int_t n; - ae_int_t nx; - ae_int_t ny; - ae_int_t normtype; - ae_matrix xy; - ae_vector tags; - ae_vector boxmin; - ae_vector boxmax; - ae_vector nodes; - ae_vector splits; - kdtreerequestbuffer innerbuf; - ae_int_t debugcounter; -} kdtree; -#endif -#if defined(AE_COMPILE_HQRND) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t s1; - ae_int_t s2; - ae_int_t magicv; -} hqrndstate; -#endif -#if defined(AE_COMPILE_XDEBUG) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t i; - ae_complex c; - ae_vector a; -} xdebugrecord1; -#endif - -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_NEARESTNEIGHBOR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Buffer object which is used to perform nearest neighbor requests in the -multithreaded mode (multiple threads working with same KD-tree object). - -This object should be created with KDTreeCreateRequestBuffer(). -*************************************************************************/ -class _kdtreerequestbuffer_owner -{ -public: - _kdtreerequestbuffer_owner(); - _kdtreerequestbuffer_owner(const _kdtreerequestbuffer_owner &rhs); - _kdtreerequestbuffer_owner& operator=(const _kdtreerequestbuffer_owner &rhs); - virtual ~_kdtreerequestbuffer_owner(); - alglib_impl::kdtreerequestbuffer* c_ptr(); - alglib_impl::kdtreerequestbuffer* c_ptr() const; -protected: - alglib_impl::kdtreerequestbuffer *p_struct; -}; -class kdtreerequestbuffer : public _kdtreerequestbuffer_owner -{ -public: - kdtreerequestbuffer(); - kdtreerequestbuffer(const kdtreerequestbuffer &rhs); - kdtreerequestbuffer& operator=(const kdtreerequestbuffer &rhs); - virtual ~kdtreerequestbuffer(); - -}; - - -/************************************************************************* -KD-tree object. -*************************************************************************/ -class _kdtree_owner -{ -public: - _kdtree_owner(); - _kdtree_owner(const _kdtree_owner &rhs); - _kdtree_owner& operator=(const _kdtree_owner &rhs); - virtual ~_kdtree_owner(); - alglib_impl::kdtree* c_ptr(); - alglib_impl::kdtree* c_ptr() const; -protected: - alglib_impl::kdtree *p_struct; -}; -class kdtree : public _kdtree_owner -{ -public: - kdtree(); - kdtree(const kdtree &rhs); - kdtree& operator=(const kdtree &rhs); - virtual ~kdtree(); - -}; -#endif - -#if defined(AE_COMPILE_HQRND) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Portable high quality random number generator state. -Initialized with HQRNDRandomize() or HQRNDSeed(). - -Fields: - S1, S2 - seed values - V - precomputed value - MagicV - 'magic' value used to determine whether State structure - was correctly initialized. -*************************************************************************/ -class _hqrndstate_owner -{ -public: - _hqrndstate_owner(); - _hqrndstate_owner(const _hqrndstate_owner &rhs); - _hqrndstate_owner& operator=(const _hqrndstate_owner &rhs); - virtual ~_hqrndstate_owner(); - alglib_impl::hqrndstate* c_ptr(); - alglib_impl::hqrndstate* c_ptr() const; -protected: - alglib_impl::hqrndstate *p_struct; -}; -class hqrndstate : public _hqrndstate_owner -{ -public: - hqrndstate(); - hqrndstate(const hqrndstate &rhs); - hqrndstate& operator=(const hqrndstate &rhs); - virtual ~hqrndstate(); - -}; -#endif - -#if defined(AE_COMPILE_XDEBUG) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - -*************************************************************************/ -class _xdebugrecord1_owner -{ -public: - _xdebugrecord1_owner(); - _xdebugrecord1_owner(const _xdebugrecord1_owner &rhs); - _xdebugrecord1_owner& operator=(const _xdebugrecord1_owner &rhs); - virtual ~_xdebugrecord1_owner(); - alglib_impl::xdebugrecord1* c_ptr(); - alglib_impl::xdebugrecord1* c_ptr() const; -protected: - alglib_impl::xdebugrecord1 *p_struct; -}; -class xdebugrecord1 : public _xdebugrecord1_owner -{ -public: - xdebugrecord1(); - xdebugrecord1(const xdebugrecord1 &rhs); - xdebugrecord1& operator=(const xdebugrecord1 &rhs); - virtual ~xdebugrecord1(); - ae_int_t &i; - alglib::complex &c; - real_1d_array a; - -}; -#endif - -#if defined(AE_COMPILE_NEARESTNEIGHBOR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -void kdtreeserialize(kdtree &obj, std::string &s_out); - - -/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -void kdtreeunserialize(const std::string &s_in, kdtree &obj); - - - - -/************************************************************************* -This function serializes data structure to C++ stream. - -Data stream generated by this function is same as string representation -generated by string version of serializer - alphanumeric characters, -dots, underscores, minus signs, which are grouped into words separated by -spaces and CR+LF. - -We recommend you to read comments on string version of serializer to find -out more about serialization of AlGLIB objects. -*************************************************************************/ -void kdtreeserialize(kdtree &obj, std::ostream &s_out); - - -/************************************************************************* -This function unserializes data structure from stream. -*************************************************************************/ -void kdtreeunserialize(const std::istream &s_in, kdtree &obj); - - -/************************************************************************* -KD-tree creation - -This subroutine creates KD-tree from set of X-values and optional Y-values - -INPUT PARAMETERS - XY - dataset, array[0..N-1,0..NX+NY-1]. - one row corresponds to one point. - first NX columns contain X-values, next NY (NY may be zero) - columns may contain associated Y-values - N - number of points, N>=0. - NX - space dimension, NX>=1. - NY - number of optional Y-values, NY>=0. - NormType- norm type: - * 0 denotes infinity-norm - * 1 denotes 1-norm - * 2 denotes 2-norm (Euclidean norm) - -OUTPUT PARAMETERS - KDT - KD-tree - - -NOTES - -1. KD-tree creation have O(N*logN) complexity and O(N*(2*NX+NY)) memory - requirements. -2. Although KD-trees may be used with any combination of N and NX, they - are more efficient than brute-force search only when N >> 4^NX. So they - are most useful in low-dimensional tasks (NX=2, NX=3). NX=1 is another - inefficient case, because simple binary search (without additional - structures) is much more efficient in such tasks than KD-trees. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreebuild(const real_2d_array &xy, const ae_int_t n, const ae_int_t nx, const ae_int_t ny, const ae_int_t normtype, kdtree &kdt, const xparams _xparams = alglib::xdefault); -void kdtreebuild(const real_2d_array &xy, const ae_int_t nx, const ae_int_t ny, const ae_int_t normtype, kdtree &kdt, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -KD-tree creation - -This subroutine creates KD-tree from set of X-values, integer tags and -optional Y-values - -INPUT PARAMETERS - XY - dataset, array[0..N-1,0..NX+NY-1]. - one row corresponds to one point. - first NX columns contain X-values, next NY (NY may be zero) - columns may contain associated Y-values - Tags - tags, array[0..N-1], contains integer tags associated - with points. - N - number of points, N>=0 - NX - space dimension, NX>=1. - NY - number of optional Y-values, NY>=0. - NormType- norm type: - * 0 denotes infinity-norm - * 1 denotes 1-norm - * 2 denotes 2-norm (Euclidean norm) - -OUTPUT PARAMETERS - KDT - KD-tree - -NOTES - -1. KD-tree creation have O(N*logN) complexity and O(N*(2*NX+NY)) memory - requirements. -2. Although KD-trees may be used with any combination of N and NX, they - are more efficient than brute-force search only when N >> 4^NX. So they - are most useful in low-dimensional tasks (NX=2, NX=3). NX=1 is another - inefficient case, because simple binary search (without additional - structures) is much more efficient in such tasks than KD-trees. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreebuildtagged(const real_2d_array &xy, const integer_1d_array &tags, const ae_int_t n, const ae_int_t nx, const ae_int_t ny, const ae_int_t normtype, kdtree &kdt, const xparams _xparams = alglib::xdefault); -void kdtreebuildtagged(const real_2d_array &xy, const integer_1d_array &tags, const ae_int_t nx, const ae_int_t ny, const ae_int_t normtype, kdtree &kdt, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function creates buffer structure which can be used to perform -parallel KD-tree requests. - -KD-tree subpackage provides two sets of request functions - ones which use -internal buffer of KD-tree object (these functions are single-threaded -because they use same buffer, which can not shared between threads), and -ones which use external buffer. - -This function is used to initialize external buffer. - -INPUT PARAMETERS - KDT - KD-tree which is associated with newly created buffer - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: KD-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use buffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -void kdtreecreaterequestbuffer(const kdtree &kdt, kdtreerequestbuffer &buf, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -K-NN query: K nearest neighbors - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: KDTreeTsQueryKNN() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - X - point, array[0..NX-1]. - K - number of neighbors to return, K>=1 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of actual neighbors found (either K or N, if K>N). - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -these results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() to get distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreequeryknn(const kdtree &kdt, const real_1d_array &x, const ae_int_t k, const bool selfmatch, const xparams _xparams = alglib::xdefault); -ae_int_t kdtreequeryknn(const kdtree &kdt, const real_1d_array &x, const ae_int_t k, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -K-NN query: K nearest neighbors, using external thread-local buffer. - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -INPUT PARAMETERS - KDT - kd-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - K - number of neighbors to return, K>=1 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of actual neighbors found (either K or N, if K>N). - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreetsqueryknn(const kdtree &kdt, const kdtreerequestbuffer &buf, const real_1d_array &x, const ae_int_t k, const bool selfmatch, const xparams _xparams = alglib::xdefault); -ae_int_t kdtreetsqueryknn(const kdtree &kdt, const kdtreerequestbuffer &buf, const real_1d_array &x, const ae_int_t k, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -R-NN query: all points within R-sphere centered at X, ordered by distance -between point and X (by ascending). - -NOTE: it is also possible to perform undordered queries performed by means - of kdtreequeryrnnu() and kdtreetsqueryrnnu() functions. Such queries - are faster because we do not have to use heap structure for sorting. - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: kdtreetsqueryrnn() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -actual results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() to get distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreequeryrnn(const kdtree &kdt, const real_1d_array &x, const double r, const bool selfmatch, const xparams _xparams = alglib::xdefault); -ae_int_t kdtreequeryrnn(const kdtree &kdt, const real_1d_array &x, const double r, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -R-NN query: all points within R-sphere centered at X, no ordering by -distance as undicated by "U" suffix (faster that ordered query, for large -queries - significantly faster). - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: kdtreetsqueryrnn() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -actual results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() to get distances - -As indicated by "U" suffix, this function returns unordered results. - - -- ALGLIB -- - Copyright 01.11.2018 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreequeryrnnu(const kdtree &kdt, const real_1d_array &x, const double r, const bool selfmatch, const xparams _xparams = alglib::xdefault); -ae_int_t kdtreequeryrnnu(const kdtree &kdt, const real_1d_array &x, const double r, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -R-NN query: all points within R-sphere centered at X, using external -thread-local buffer, sorted by distance between point and X (by ascending) - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -NOTE: it is also possible to perform undordered queries performed by means - of kdtreequeryrnnu() and kdtreetsqueryrnnu() functions. Such queries - are faster because we do not have to use heap structure for sorting. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreetsqueryrnn(const kdtree &kdt, const kdtreerequestbuffer &buf, const real_1d_array &x, const double r, const bool selfmatch, const xparams _xparams = alglib::xdefault); -ae_int_t kdtreetsqueryrnn(const kdtree &kdt, const kdtreerequestbuffer &buf, const real_1d_array &x, const double r, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -R-NN query: all points within R-sphere centered at X, using external -thread-local buffer, no ordering by distance as undicated by "U" suffix -(faster that ordered query, for large queries - significantly faster). - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - R - radius of sphere (in corresponding norm), R>0 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - -RESULT - number of neighbors found, >=0 - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -As indicated by "U" suffix, this function returns unordered results. - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreetsqueryrnnu(const kdtree &kdt, const kdtreerequestbuffer &buf, const real_1d_array &x, const double r, const bool selfmatch, const xparams _xparams = alglib::xdefault); -ae_int_t kdtreetsqueryrnnu(const kdtree &kdt, const kdtreerequestbuffer &buf, const real_1d_array &x, const double r, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -K-NN query: approximate K nearest neighbors - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: KDTreeTsQueryAKNN() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - X - point, array[0..NX-1]. - K - number of neighbors to return, K>=1 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - Eps - approximation factor, Eps>=0. eps-approximate nearest - neighbor is a neighbor whose distance from X is at - most (1+eps) times distance of true nearest neighbor. - -RESULT - number of actual neighbors found (either K or N, if K>N). - -NOTES - significant performance gain may be achieved only when Eps is is on - the order of magnitude of 1 or larger. - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -these results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() to get distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreequeryaknn(const kdtree &kdt, const real_1d_array &x, const ae_int_t k, const bool selfmatch, const double eps, const xparams _xparams = alglib::xdefault); -ae_int_t kdtreequeryaknn(const kdtree &kdt, const real_1d_array &x, const ae_int_t k, const double eps, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -K-NN query: approximate K nearest neighbors, using thread-local buffer. - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - X - point, array[0..NX-1]. - K - number of neighbors to return, K>=1 - SelfMatch - whether self-matches are allowed: - * if True, nearest neighbor may be the point itself - (if it exists in original dataset) - * if False, then only points with non-zero distance - are returned - * if not given, considered True - Eps - approximation factor, Eps>=0. eps-approximate nearest - neighbor is a neighbor whose distance from X is at - most (1+eps) times distance of true nearest neighbor. - -RESULT - number of actual neighbors found (either K or N, if K>N). - -NOTES - significant performance gain may be achieved only when Eps is is on - the order of magnitude of 1 or larger. - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "buf" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() to get distances - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 18.03.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreetsqueryaknn(const kdtree &kdt, const kdtreerequestbuffer &buf, const real_1d_array &x, const ae_int_t k, const bool selfmatch, const double eps, const xparams _xparams = alglib::xdefault); -ae_int_t kdtreetsqueryaknn(const kdtree &kdt, const kdtreerequestbuffer &buf, const real_1d_array &x, const ae_int_t k, const double eps, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Box query: all points within user-specified box. - -IMPORTANT: this function can not be used in multithreaded code because it - uses internal temporary buffer of kd-tree object, which can not - be shared between multiple threads. If you want to perform - parallel requests, use function which uses external request - buffer: KDTreeTsQueryBox() ("Ts" stands for "thread-safe"). - -INPUT PARAMETERS - KDT - KD-tree - BoxMin - lower bounds, array[0..NX-1]. - BoxMax - upper bounds, array[0..NX-1]. - - -RESULT - number of actual neighbors found (in [0,N]). - -This subroutine performs query and stores its result in the internal -structures of the KD-tree. You can use following subroutines to obtain -these results: -* KDTreeQueryResultsX() to get X-values -* KDTreeQueryResultsXY() to get X- and Y-values -* KDTreeQueryResultsTags() to get tag values -* KDTreeQueryResultsDistances() returns zeros for this request - -NOTE: this particular query returns unordered results, because there is no - meaningful way of ordering points. Furthermore, no 'distance' is - associated with points - it is either INSIDE or OUTSIDE (so request - for distances will return zeros). - - -- ALGLIB -- - Copyright 14.05.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreequerybox(const kdtree &kdt, const real_1d_array &boxmin, const real_1d_array &boxmax, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Box query: all points within user-specified box, using thread-local buffer. - -You can call this function from multiple threads for same kd-tree instance, -assuming that different instances of buffer object are passed to different -threads. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure with kdtreecreaterequestbuffer() - function. - BoxMin - lower bounds, array[0..NX-1]. - BoxMax - upper bounds, array[0..NX-1]. - -RESULT - number of actual neighbors found (in [0,N]). - -This subroutine performs query and stores its result in the internal -structures of the buffer object. You can use following subroutines to -obtain these results (pay attention to "ts" in their names): -* KDTreeTsQueryResultsX() to get X-values -* KDTreeTsQueryResultsXY() to get X- and Y-values -* KDTreeTsQueryResultsTags() to get tag values -* KDTreeTsQueryResultsDistances() returns zeros for this query - -NOTE: this particular query returns unordered results, because there is no - meaningful way of ordering points. Furthermore, no 'distance' is - associated with points - it is either INSIDE or OUTSIDE (so request - for distances will return zeros). - -IMPORTANT: kd-tree buffer should be used only with KD-tree object which - was used to initialize buffer. Any attempt to use biffer with - different object is dangerous - you may get integrity check - failure (exception) because sizes of internal arrays do not fit - to dimensions of KD-tree structure. - - -- ALGLIB -- - Copyright 14.05.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t kdtreetsquerybox(const kdtree &kdt, const kdtreerequestbuffer &buf, const real_1d_array &boxmin, const real_1d_array &boxmax, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -X-values from last query. - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - kdtreetsqueryresultsx(). - -INPUT PARAMETERS - KDT - KD-tree - X - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - X - rows are filled with X-values - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsTags() tag values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultsx(const kdtree &kdt, real_2d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -X- and Y-values from last query - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - kdtreetsqueryresultsxy(). - -INPUT PARAMETERS - KDT - KD-tree - XY - possibly pre-allocated buffer. If XY is too small to store - result, it is resized. If size(XY) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - XY - rows are filled with points: first NX columns with - X-values, next NY columns - with Y-values. - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsTags() tag values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultsxy(const kdtree &kdt, real_2d_array &xy, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Tags from last query - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - kdtreetsqueryresultstags(). - -INPUT PARAMETERS - KDT - KD-tree - Tags - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - Tags - filled with tags associated with points, - or, when no tags were supplied, with zeros - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultstags(const kdtree &kdt, integer_1d_array &tags, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Distances from last query - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - kdtreetsqueryresultsdistances(). - -INPUT PARAMETERS - KDT - KD-tree - R - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - R - filled with distances (in corresponding norm) - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsTags() tag values - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultsdistances(const kdtree &kdt, real_1d_array &r, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -X-values from last query associated with kdtreerequestbuffer object. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure. - X - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - X - rows are filled with X-values - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsTags() tag values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreetsqueryresultsx(const kdtree &kdt, const kdtreerequestbuffer &buf, real_2d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -X- and Y-values from last query associated with kdtreerequestbuffer object. - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure. - XY - possibly pre-allocated buffer. If XY is too small to store - result, it is resized. If size(XY) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - XY - rows are filled with points: first NX columns with - X-values, next NY columns - with Y-values. - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsTags() tag values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreetsqueryresultsxy(const kdtree &kdt, const kdtreerequestbuffer &buf, real_2d_array &xy, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Tags from last query associated with kdtreerequestbuffer object. - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - KDTreeTsqueryresultstags(). - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure. - Tags - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - Tags - filled with tags associated with points, - or, when no tags were supplied, with zeros - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsDistances() distances - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreetsqueryresultstags(const kdtree &kdt, const kdtreerequestbuffer &buf, integer_1d_array &tags, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Distances from last query associated with kdtreerequestbuffer object. - -This function retuns results stored in the internal buffer of kd-tree -object. If you performed buffered requests (ones which use instances of -kdtreerequestbuffer class), you should call buffered version of this -function - KDTreeTsqueryresultsdistances(). - -INPUT PARAMETERS - KDT - KD-tree - Buf - request buffer object created for this particular - instance of kd-tree structure. - R - possibly pre-allocated buffer. If X is too small to store - result, it is resized. If size(X) is enough to store - result, it is left unchanged. - -OUTPUT PARAMETERS - R - filled with distances (in corresponding norm) - -NOTES -1. points are ordered by distance from the query point (first = closest) -2. if XY is larger than required to store result, only leading part will - be overwritten; trailing part will be left unchanged. So if on input - XY = [[A,B],[C,D]], and result is [1,2], then on exit we will get - XY = [[1,2],[C,D]]. This is done purposely to increase performance; if - you want function to resize array according to result size, use - function with same name and suffix 'I'. - -SEE ALSO -* KDTreeQueryResultsX() X-values -* KDTreeQueryResultsXY() X- and Y-values -* KDTreeQueryResultsTags() tag values - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreetsqueryresultsdistances(const kdtree &kdt, const kdtreerequestbuffer &buf, real_1d_array &r, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -X-values from last query; 'interactive' variant for languages like Python -which support constructs like "X = KDTreeQueryResultsXI(KDT)" and -interactive mode of interpreter. - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultsxi(const kdtree &kdt, real_2d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -XY-values from last query; 'interactive' variant for languages like Python -which support constructs like "XY = KDTreeQueryResultsXYI(KDT)" and -interactive mode of interpreter. - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultsxyi(const kdtree &kdt, real_2d_array &xy, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Tags from last query; 'interactive' variant for languages like Python -which support constructs like "Tags = KDTreeQueryResultsTagsI(KDT)" and -interactive mode of interpreter. - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultstagsi(const kdtree &kdt, integer_1d_array &tags, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Distances from last query; 'interactive' variant for languages like Python -which support constructs like "R = KDTreeQueryResultsDistancesI(KDT)" -and interactive mode of interpreter. - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void kdtreequeryresultsdistancesi(const kdtree &kdt, real_1d_array &r, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_HQRND) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -HQRNDState initialization with random values which come from standard -RNG. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void hqrndrandomize(hqrndstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -HQRNDState initialization with seed values - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void hqrndseed(const ae_int_t s1, const ae_int_t s2, hqrndstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function generates random real number in (0,1), -not including interval boundaries - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -double hqrnduniformr(const hqrndstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function generates random integer number in [0, N) - -1. State structure must be initialized with HQRNDRandomize() or HQRNDSeed() -2. N can be any positive number except for very large numbers: - * close to 2^31 on 32-bit systems - * close to 2^62 on 64-bit systems - An exception will be generated if N is too large. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -ae_int_t hqrnduniformi(const hqrndstate &state, const ae_int_t n, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Random number generator: normal numbers - -This function generates one random number from normal distribution. -Its performance is equal to that of HQRNDNormal2() - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -double hqrndnormal(const hqrndstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Random number generator: vector with random entries (normal distribution) - -This function generates N random numbers from normal distribution. - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void hqrndnormalv(const hqrndstate &state, const ae_int_t n, real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Random number generator: matrix with random entries (normal distribution) - -This function generates MxN random matrix. - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void hqrndnormalm(const hqrndstate &state, const ae_int_t m, const ae_int_t n, real_2d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Random number generator: random X and Y such that X^2+Y^2=1 - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void hqrndunit2(const hqrndstate &state, double &x, double &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Random number generator: normal numbers - -This function generates two independent random numbers from normal -distribution. Its performance is equal to that of HQRNDNormal() - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void hqrndnormal2(const hqrndstate &state, double &x1, double &x2, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Random number generator: exponential distribution - -State structure must be initialized with HQRNDRandomize() or HQRNDSeed(). - - -- ALGLIB -- - Copyright 11.08.2007 by Bochkanov Sergey -*************************************************************************/ -double hqrndexponential(const hqrndstate &state, const double lambdav, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function generates random number from discrete distribution given by -finite sample X. - -INPUT PARAMETERS - State - high quality random number generator, must be - initialized with HQRNDRandomize() or HQRNDSeed(). - X - finite sample - N - number of elements to use, N>=1 - -RESULT - this function returns one of the X[i] for random i=0..N-1 - - -- ALGLIB -- - Copyright 08.11.2011 by Bochkanov Sergey -*************************************************************************/ -double hqrnddiscrete(const hqrndstate &state, const real_1d_array &x, const ae_int_t n, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function generates random number from continuous distribution given -by finite sample X. - -INPUT PARAMETERS - State - high quality random number generator, must be - initialized with HQRNDRandomize() or HQRNDSeed(). - X - finite sample, array[N] (can be larger, in this case only - leading N elements are used). THIS ARRAY MUST BE SORTED BY - ASCENDING. - N - number of elements to use, N>=1 - -RESULT - this function returns random number from continuous distribution which - tries to approximate X as mush as possible. min(X)<=Result<=max(X). - - -- ALGLIB -- - Copyright 08.11.2011 by Bochkanov Sergey -*************************************************************************/ -double hqrndcontinuous(const hqrndstate &state, const real_1d_array &x, const ae_int_t n, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_XDEBUG) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Creates and returns XDebugRecord1 structure: -* integer and complex fields of Rec1 are set to 1 and 1+i correspondingly -* array field of Rec1 is set to [2,3] - - -- ALGLIB -- - Copyright 27.05.2014 by Bochkanov Sergey -*************************************************************************/ -void xdebuginitrecord1(xdebugrecord1 &rec1, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Counts number of True values in the boolean 1D array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -ae_int_t xdebugb1count(const boolean_1d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by NOT(a[i]). -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugb1not(const boolean_1d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Appends copy of array to itself. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugb1appendcopy(boolean_1d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate N-element array with even-numbered elements set to True. -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugb1outeven(const ae_int_t n, boolean_1d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -ae_int_t xdebugi1sum(const integer_1d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -A[I] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugi1neg(const integer_1d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Appends copy of array to itself. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugi1appendcopy(integer_1d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate N-element array with even-numbered A[I] set to I, and odd-numbered -ones set to 0. - -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugi1outeven(const ae_int_t n, integer_1d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -double xdebugr1sum(const real_1d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -A[I] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugr1neg(const real_1d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Appends copy of array to itself. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugr1appendcopy(real_1d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate N-element array with even-numbered A[I] set to I*0.25, -and odd-numbered ones are set to 0. - -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugr1outeven(const ae_int_t n, real_1d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -alglib::complex xdebugc1sum(const complex_1d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -A[I] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugc1neg(const complex_1d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Appends copy of array to itself. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugc1appendcopy(complex_1d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate N-element array with even-numbered A[K] set to (x,y) = (K*0.25, K*0.125) -and odd-numbered ones are set to 0. - -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugc1outeven(const ae_int_t n, complex_1d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Counts number of True values in the boolean 2D array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -ae_int_t xdebugb2count(const boolean_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by NOT(a[i]). -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugb2not(const boolean_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Transposes array. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugb2transpose(boolean_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate MxN matrix with elements set to "Sin(3*I+5*J)>0" -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugb2outsin(const ae_int_t m, const ae_int_t n, boolean_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -ae_int_t xdebugi2sum(const integer_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -a[i,j] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugi2neg(const integer_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Transposes array. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugi2transpose(integer_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate MxN matrix with elements set to "Sign(Sin(3*I+5*J))" -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugi2outsin(const ae_int_t m, const ae_int_t n, integer_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -double xdebugr2sum(const real_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -a[i,j] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugr2neg(const real_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Transposes array. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugr2transpose(real_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate MxN matrix with elements set to "Sin(3*I+5*J)" -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugr2outsin(const ae_int_t m, const ae_int_t n, real_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of elements in the array. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -alglib::complex xdebugc2sum(const complex_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Replace all values in array by -a[i,j] -Array is passed using "shared" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugc2neg(const complex_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Transposes array. -Array is passed using "var" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugc2transpose(complex_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Generate MxN matrix with elements set to "Sin(3*I+5*J),Cos(3*I+5*J)" -Array is passed using "out" convention. - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -void xdebugc2outsincos(const ae_int_t m, const ae_int_t n, complex_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is debug function intended for testing ALGLIB interface generator. -Never use it in any real life project. - -Returns sum of a[i,j]*(1+b[i,j]) such that c[i,j] is True - - -- ALGLIB -- - Copyright 11.10.2013 by Bochkanov Sergey -*************************************************************************/ -double xdebugmaskedbiasedproductsum(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const real_2d_array &b, const boolean_2d_array &c, const xparams _xparams = alglib::xdefault); -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (FUNCTIONS) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_NEARESTNEIGHBOR) || !defined(AE_PARTIAL_BUILD) -void kdtreebuild(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - ae_int_t normtype, - kdtree* kdt, - ae_state *_state); -void kdtreebuildtagged(/* Real */ ae_matrix* xy, - /* Integer */ ae_vector* tags, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - ae_int_t normtype, - kdtree* kdt, - ae_state *_state); -void kdtreecreaterequestbuffer(kdtree* kdt, - kdtreerequestbuffer* buf, - ae_state *_state); -ae_int_t kdtreequeryknn(kdtree* kdt, - /* Real */ ae_vector* x, - ae_int_t k, - ae_bool selfmatch, - ae_state *_state); -ae_int_t kdtreetsqueryknn(kdtree* kdt, - kdtreerequestbuffer* buf, - /* Real */ ae_vector* x, - ae_int_t k, - ae_bool selfmatch, - ae_state *_state); -ae_int_t kdtreequeryrnn(kdtree* kdt, - /* Real */ ae_vector* x, - double r, - ae_bool selfmatch, - ae_state *_state); -ae_int_t kdtreequeryrnnu(kdtree* kdt, - /* Real */ ae_vector* x, - double r, - ae_bool selfmatch, - ae_state *_state); -ae_int_t kdtreetsqueryrnn(kdtree* kdt, - kdtreerequestbuffer* buf, - /* Real */ ae_vector* x, - double r, - ae_bool selfmatch, - ae_state *_state); -ae_int_t kdtreetsqueryrnnu(kdtree* kdt, - kdtreerequestbuffer* buf, - /* Real */ ae_vector* x, - double r, - ae_bool selfmatch, - ae_state *_state); -ae_int_t kdtreequeryaknn(kdtree* kdt, - /* Real */ ae_vector* x, - ae_int_t k, - ae_bool selfmatch, - double eps, - ae_state *_state); -ae_int_t kdtreetsqueryaknn(kdtree* kdt, - kdtreerequestbuffer* buf, - /* Real */ ae_vector* x, - ae_int_t k, - ae_bool selfmatch, - double eps, - ae_state *_state); -ae_int_t kdtreequerybox(kdtree* kdt, - /* Real */ ae_vector* boxmin, - /* Real */ ae_vector* boxmax, - ae_state *_state); -ae_int_t kdtreetsquerybox(kdtree* kdt, - kdtreerequestbuffer* buf, - /* Real */ ae_vector* boxmin, - /* Real */ ae_vector* boxmax, - ae_state *_state); -void kdtreequeryresultsx(kdtree* kdt, - /* Real */ ae_matrix* x, - ae_state *_state); -void kdtreequeryresultsxy(kdtree* kdt, - /* Real */ ae_matrix* xy, - ae_state *_state); -void kdtreequeryresultstags(kdtree* kdt, - /* Integer */ ae_vector* tags, - ae_state *_state); -void kdtreequeryresultsdistances(kdtree* kdt, - /* Real */ ae_vector* r, - ae_state *_state); -void kdtreetsqueryresultsx(kdtree* kdt, - kdtreerequestbuffer* buf, - /* Real */ ae_matrix* x, - ae_state *_state); -void kdtreetsqueryresultsxy(kdtree* kdt, - kdtreerequestbuffer* buf, - /* Real */ ae_matrix* xy, - ae_state *_state); -void kdtreetsqueryresultstags(kdtree* kdt, - kdtreerequestbuffer* buf, - /* Integer */ ae_vector* tags, - ae_state *_state); -void kdtreetsqueryresultsdistances(kdtree* kdt, - kdtreerequestbuffer* buf, - /* Real */ ae_vector* r, - ae_state *_state); -void kdtreequeryresultsxi(kdtree* kdt, - /* Real */ ae_matrix* x, - ae_state *_state); -void kdtreequeryresultsxyi(kdtree* kdt, - /* Real */ ae_matrix* xy, - ae_state *_state); -void kdtreequeryresultstagsi(kdtree* kdt, - /* Integer */ ae_vector* tags, - ae_state *_state); -void kdtreequeryresultsdistancesi(kdtree* kdt, - /* Real */ ae_vector* r, - ae_state *_state); -void kdtreeexplorebox(kdtree* kdt, - /* Real */ ae_vector* boxmin, - /* Real */ ae_vector* boxmax, - ae_state *_state); -void kdtreeexplorenodetype(kdtree* kdt, - ae_int_t node, - ae_int_t* nodetype, - ae_state *_state); -void kdtreeexploreleaf(kdtree* kdt, - ae_int_t node, - /* Real */ ae_matrix* xy, - ae_int_t* k, - ae_state *_state); -void kdtreeexploresplit(kdtree* kdt, - ae_int_t node, - ae_int_t* d, - double* s, - ae_int_t* nodele, - ae_int_t* nodege, - ae_state *_state); -void kdtreealloc(ae_serializer* s, kdtree* tree, ae_state *_state); -void kdtreeserialize(ae_serializer* s, kdtree* tree, ae_state *_state); -void kdtreeunserialize(ae_serializer* s, kdtree* tree, ae_state *_state); -void _kdtreerequestbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _kdtreerequestbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _kdtreerequestbuffer_clear(void* _p); -void _kdtreerequestbuffer_destroy(void* _p); -void _kdtree_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _kdtree_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _kdtree_clear(void* _p); -void _kdtree_destroy(void* _p); -#endif -#if defined(AE_COMPILE_HQRND) || !defined(AE_PARTIAL_BUILD) -void hqrndrandomize(hqrndstate* state, ae_state *_state); -void hqrndseed(ae_int_t s1, - ae_int_t s2, - hqrndstate* state, - ae_state *_state); -double hqrnduniformr(hqrndstate* state, ae_state *_state); -ae_int_t hqrnduniformi(hqrndstate* state, ae_int_t n, ae_state *_state); -double hqrndnormal(hqrndstate* state, ae_state *_state); -void hqrndnormalv(hqrndstate* state, - ae_int_t n, - /* Real */ ae_vector* x, - ae_state *_state); -void hqrndnormalm(hqrndstate* state, - ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* x, - ae_state *_state); -void hqrndunit2(hqrndstate* state, double* x, double* y, ae_state *_state); -void hqrndnormal2(hqrndstate* state, - double* x1, - double* x2, - ae_state *_state); -double hqrndexponential(hqrndstate* state, - double lambdav, - ae_state *_state); -double hqrnddiscrete(hqrndstate* state, - /* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state); -double hqrndcontinuous(hqrndstate* state, - /* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state); -void _hqrndstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _hqrndstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _hqrndstate_clear(void* _p); -void _hqrndstate_destroy(void* _p); -#endif -#if defined(AE_COMPILE_XDEBUG) || !defined(AE_PARTIAL_BUILD) -void xdebuginitrecord1(xdebugrecord1* rec1, ae_state *_state); -ae_int_t xdebugb1count(/* Boolean */ ae_vector* a, ae_state *_state); -void xdebugb1not(/* Boolean */ ae_vector* a, ae_state *_state); -void xdebugb1appendcopy(/* Boolean */ ae_vector* a, ae_state *_state); -void xdebugb1outeven(ae_int_t n, - /* Boolean */ ae_vector* a, - ae_state *_state); -ae_int_t xdebugi1sum(/* Integer */ ae_vector* a, ae_state *_state); -void xdebugi1neg(/* Integer */ ae_vector* a, ae_state *_state); -void xdebugi1appendcopy(/* Integer */ ae_vector* a, ae_state *_state); -void xdebugi1outeven(ae_int_t n, - /* Integer */ ae_vector* a, - ae_state *_state); -double xdebugr1sum(/* Real */ ae_vector* a, ae_state *_state); -void xdebugr1neg(/* Real */ ae_vector* a, ae_state *_state); -void xdebugr1appendcopy(/* Real */ ae_vector* a, ae_state *_state); -void xdebugr1outeven(ae_int_t n, - /* Real */ ae_vector* a, - ae_state *_state); -ae_complex xdebugc1sum(/* Complex */ ae_vector* a, ae_state *_state); -void xdebugc1neg(/* Complex */ ae_vector* a, ae_state *_state); -void xdebugc1appendcopy(/* Complex */ ae_vector* a, ae_state *_state); -void xdebugc1outeven(ae_int_t n, - /* Complex */ ae_vector* a, - ae_state *_state); -ae_int_t xdebugb2count(/* Boolean */ ae_matrix* a, ae_state *_state); -void xdebugb2not(/* Boolean */ ae_matrix* a, ae_state *_state); -void xdebugb2transpose(/* Boolean */ ae_matrix* a, ae_state *_state); -void xdebugb2outsin(ae_int_t m, - ae_int_t n, - /* Boolean */ ae_matrix* a, - ae_state *_state); -ae_int_t xdebugi2sum(/* Integer */ ae_matrix* a, ae_state *_state); -void xdebugi2neg(/* Integer */ ae_matrix* a, ae_state *_state); -void xdebugi2transpose(/* Integer */ ae_matrix* a, ae_state *_state); -void xdebugi2outsin(ae_int_t m, - ae_int_t n, - /* Integer */ ae_matrix* a, - ae_state *_state); -double xdebugr2sum(/* Real */ ae_matrix* a, ae_state *_state); -void xdebugr2neg(/* Real */ ae_matrix* a, ae_state *_state); -void xdebugr2transpose(/* Real */ ae_matrix* a, ae_state *_state); -void xdebugr2outsin(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_state *_state); -ae_complex xdebugc2sum(/* Complex */ ae_matrix* a, ae_state *_state); -void xdebugc2neg(/* Complex */ ae_matrix* a, ae_state *_state); -void xdebugc2transpose(/* Complex */ ae_matrix* a, ae_state *_state); -void xdebugc2outsincos(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_state *_state); -double xdebugmaskedbiasedproductsum(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - /* Real */ ae_matrix* b, - /* Boolean */ ae_matrix* c, - ae_state *_state); -void _xdebugrecord1_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _xdebugrecord1_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _xdebugrecord1_clear(void* _p); -void _xdebugrecord1_destroy(void* _p); -#endif - -} -#endif - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/ap.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/ap.cpp deleted file mode 100644 index f4e1cb5..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/ap.cpp +++ /dev/null @@ -1,12421 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifdef _MSC_VER -#define _CRT_SECURE_NO_WARNINGS -#endif - -// -// if AE_OS==AE_LINUX (will be redefined to AE_POSIX in ap.h), -// set _GNU_SOURCE flag BEFORE any #includes to get affinity -// management functions -// -#if (AE_OS==AE_LINUX) && !defined(_GNU_SOURCE) -#define _GNU_SOURCE -#endif - -#include "stdafx.h" -#include "ap.h" -#include -#include -#include - -#if defined(AE_CPU) -#if (AE_CPU==AE_INTEL) - -#if AE_COMPILER==AE_MSVC -#include -#endif - -#endif -#endif - -// disable some irrelevant warnings -#if (AE_COMPILER==AE_MSVC) && !defined(AE_ALL_WARNINGS) -#pragma warning(disable:4100) -#pragma warning(disable:4127) -#pragma warning(disable:4611) -#pragma warning(disable:4702) -#pragma warning(disable:4996) -#endif - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION IMPLEMENTS BASIC FUNCTIONALITY LIKE -// MEMORY MANAGEMENT FOR VECTORS/MATRICES WHICH IS -// SHARED BETWEEN C++ AND PURE C LIBRARIES -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -/* - * OS-specific includes - */ -#ifdef AE_USE_CPP -} -#endif -#if AE_OS==AE_WINDOWS || defined(AE_DEBUG4WINDOWS) -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#endif -#include -#include -#elif AE_OS==AE_POSIX || defined(AE_DEBUG4POSIX) -#include -#include -#include -#include -#include -#endif -/* Debugging helpers for Windows */ -#ifdef AE_DEBUG4WINDOWS -#include -#include -#endif -#ifdef AE_USE_CPP -namespace alglib_impl -{ -#endif - -/* - * local definitions - */ -#define x_nb 16 -#define AE_DATA_ALIGN 64 -#define AE_PTR_ALIGN sizeof(void*) -#define DYN_BOTTOM ((void*)1) -#define DYN_FRAME ((void*)2) -#define AE_LITTLE_ENDIAN 1 -#define AE_BIG_ENDIAN 2 -#define AE_MIXED_ENDIAN 3 -#define AE_SER_ENTRY_LENGTH 11 -#define AE_SER_ENTRIES_PER_ROW 5 - -#define AE_SM_DEFAULT 0 -#define AE_SM_ALLOC 1 -#define AE_SM_READY2S 2 -#define AE_SM_TO_STRING 10 -#define AE_SM_TO_CPPSTRING 11 -#define AE_SM_TO_STREAM 12 -#define AE_SM_FROM_STRING 20 -#define AE_SM_FROM_STREAM 22 - -#define AE_LOCK_CYCLES 512 -#define AE_LOCK_TESTS_BEFORE_YIELD 16 -#define AE_CRITICAL_ASSERT(x) if( !(x) ) abort() - -/* IDs for set_dbg_value */ -#define _ALGLIB_USE_ALLOC_COUNTER 0 -#define _ALGLIB_USE_DBG_COUNTERS 1 -#define _ALGLIB_USE_VENDOR_KERNELS 100 -#define _ALGLIB_VENDOR_MEMSTAT 101 - -#define _ALGLIB_DEBUG_WORKSTEALING 200 -#define _ALGLIB_WSDBG_NCORES 201 -#define _ALGLIB_WSDBG_PUSHROOT_OK 202 -#define _ALGLIB_WSDBG_PUSHROOT_FAILED 203 - -#define _ALGLIB_SET_GLOBAL_THREADING 1001 -#define _ALGLIB_SET_NWORKERS 1002 - -/* IDs for get_dbg_value */ -#define _ALGLIB_GET_ALLOC_COUNTER 0 -#define _ALGLIB_GET_CUMULATIVE_ALLOC_SIZE 1 -#define _ALGLIB_GET_CUMULATIVE_ALLOC_COUNT 2 - -#define _ALGLIB_GET_CORES_COUNT 1000 -#define _ALGLIB_GET_GLOBAL_THREADING 1001 -#define _ALGLIB_GET_NWORKERS 1002 - -/************************************************************************* -Lock. - -This is internal structure which implements lock functionality. -*************************************************************************/ -typedef struct -{ -#if AE_OS==AE_WINDOWS - volatile ae_int_t * volatile p_lock; - char buf[sizeof(ae_int_t)+AE_LOCK_ALIGNMENT]; -#elif AE_OS==AE_POSIX - pthread_mutex_t mutex; -#else - ae_bool is_locked; -#endif -} _lock; - - - - -/* - * Error tracking facilities; this fields are modified every time ae_set_error_flag() - * is called with non-zero cond. Thread unsafe access, but it does not matter actually. - */ -static const char * sef_file = ""; -static int sef_line = 0; -static const char * sef_xdesc = ""; - -/* - * Global flags, split into several char-sized variables in order - * to avoid problem with non-atomic reads/writes (single-byte ops - * are atomic on all modern architectures); - * - * Following variables are included: - * * threading-related settings - */ -unsigned char _alglib_global_threading_flags = _ALGLIB_FLG_THREADING_SERIAL>>_ALGLIB_FLG_THREADING_SHIFT; - -/* - * DESCRIPTION: recommended number of active workers: - * * positive value >=1 is used to specify exact number of active workers - * * 0 means that ALL available cores are used - * * negative value means that all cores EXCEPT for cores_to_use will be used - * (say, -1 means that all cores except for one will be used). At least one - * core will be used in this case, even if you assign -9999999 to this field. - * - * Default value = 0 (fully parallel execution) when AE_NWORKERS is not defined - * = 0 for manually defined number of cores (AE_NWORKERS is defined) - * PROTECTION: not needed; runtime modification is possible, but we do not need exact - * synchronization. - */ -#if defined(AE_NWORKERS) && (AE_NWORKERS<=0) -#error AE_NWORKERS must be positive number or not defined at all. -#endif -#if defined(AE_NWORKERS) -ae_int_t _alglib_cores_to_use = 0; -#else -ae_int_t _alglib_cores_to_use = 0; -#endif - -/* - * Debug counters - */ -ae_int_t _alloc_counter = 0; -ae_int_t _alloc_counter_total = 0; -ae_bool _use_alloc_counter = ae_false; - -ae_int_t _dbg_alloc_total = 0; -ae_bool _use_dbg_counters = ae_false; - -ae_bool _use_vendor_kernels = ae_true; - -ae_bool debug_workstealing = ae_false; /* debug workstealing environment? False by default */ -ae_int_t dbgws_pushroot_ok = 0; -ae_int_t dbgws_pushroot_failed = 0; - -#ifdef AE_SMP_DEBUGCOUNTERS -__declspec(align(AE_LOCK_ALIGNMENT)) volatile ae_int64_t _ae_dbg_lock_acquisitions = 0; -__declspec(align(AE_LOCK_ALIGNMENT)) volatile ae_int64_t _ae_dbg_lock_spinwaits = 0; -__declspec(align(AE_LOCK_ALIGNMENT)) volatile ae_int64_t _ae_dbg_lock_yields = 0; -#endif - -/* - * Allocation debugging - */ -ae_bool _force_malloc_failure = ae_false; -ae_int_t _malloc_failure_after = 0; - - -/* - * Trace-related declarations: - * alglib_trace_type - trace output type - * alglib_trace_file - file descriptor (to be used by ALGLIB code which - * sends messages to trace log - * alglib_fclose_trace - whether we have to call fclose() when disabling or - * changing trace output - * alglib_trace_tags - string buffer used to store tags + two additional - * characters (leading and trailing commas) + null - * terminator - */ -#define ALGLIB_TRACE_NONE 0 -#define ALGLIB_TRACE_FILE 1 -#define ALGLIB_TRACE_TAGS_LEN 2048 -#define ALGLIB_TRACE_BUFFER_LEN (ALGLIB_TRACE_TAGS_LEN+2+1) -static ae_int_t alglib_trace_type = ALGLIB_TRACE_NONE; -FILE *alglib_trace_file = NULL; -static ae_bool alglib_fclose_trace = ae_false; -static char alglib_trace_tags[ALGLIB_TRACE_BUFFER_LEN]; - -/* - * Fields for memory allocation over static array - */ -#if AE_MALLOC==AE_BASIC_STATIC_MALLOC -#if AE_THREADING!=AE_SERIAL_UNSAFE -#error Basis static malloc is thread-unsafe; define AE_THREADING=AE_SERIAL_UNSAFE to prove that you know it -#endif -static ae_int_t sm_page_size = 0; -static ae_int_t sm_page_cnt = 0; -static ae_int_t *sm_page_tbl = NULL; -static unsigned char *sm_mem = NULL; -#endif - -/* - * These declarations are used to ensure that - * sizeof(ae_bool)=1, sizeof(ae_int32_t)==4, sizeof(ae_int64_t)==8, sizeof(ae_int_t)==sizeof(void*). - * they will lead to syntax error otherwise (array size will be negative). - * - * you can remove them, if you want - they are not used anywhere. - * - */ -static char _ae_bool_must_be_8_bits_wide [1-2*((int)(sizeof(ae_bool))-1)*((int)(sizeof(ae_bool))-1)]; -static char _ae_int32_t_must_be_32_bits_wide[1-2*((int)(sizeof(ae_int32_t))-4)*((int)(sizeof(ae_int32_t))-4)]; -static char _ae_int64_t_must_be_64_bits_wide[1-2*((int)(sizeof(ae_int64_t))-8)*((int)(sizeof(ae_int64_t))-8)]; -static char _ae_uint64_t_must_be_64_bits_wide[1-2*((int)(sizeof(ae_uint64_t))-8)*((int)(sizeof(ae_uint64_t))-8)]; -static char _ae_int_t_must_be_pointer_sized [1-2*((int)(sizeof(ae_int_t))-(int)sizeof(void*))*((int)(sizeof(ae_int_t))-(int)(sizeof(void*)))]; - -/* - * This variable is used to prevent some tricky optimizations which may degrade multithreaded performance. - * It is touched once in the ae_init_pool() function from smp.c in order to prevent optimizations. - * - */ -static volatile ae_int_t ae_never_change_it = 1; - -/************************************************************************* -This function should never be called. It is here to prevent spurious -compiler warnings about unused variables (in fact: used). -*************************************************************************/ -void ae_never_call_it() -{ - ae_touch_ptr((void*)_ae_bool_must_be_8_bits_wide); - ae_touch_ptr((void*)_ae_int32_t_must_be_32_bits_wide); - ae_touch_ptr((void*)_ae_int64_t_must_be_64_bits_wide); - ae_touch_ptr((void*)_ae_uint64_t_must_be_64_bits_wide); - ae_touch_ptr((void*)_ae_int_t_must_be_pointer_sized); -} - -void ae_set_dbg_flag(ae_int64_t flag_id, ae_int64_t flag_val) -{ - if( flag_id==_ALGLIB_USE_ALLOC_COUNTER ) - { - _use_alloc_counter = flag_val!=0; - return; - } - if( flag_id==_ALGLIB_USE_DBG_COUNTERS ) - { - _use_dbg_counters = flag_val!=0; - return; - } - if( flag_id==_ALGLIB_USE_VENDOR_KERNELS ) - { - _use_vendor_kernels = flag_val!=0; - return; - } - if( flag_id==_ALGLIB_DEBUG_WORKSTEALING ) - { - debug_workstealing = flag_val!=0; - return; - } - if( flag_id==_ALGLIB_SET_GLOBAL_THREADING ) - { - ae_set_global_threading((ae_uint64_t)flag_val); - return; - } - if( flag_id==_ALGLIB_SET_NWORKERS ) - { - _alglib_cores_to_use = (ae_int_t)flag_val; - return; - } -} - -ae_int64_t ae_get_dbg_value(ae_int64_t id) -{ - if( id==_ALGLIB_GET_ALLOC_COUNTER ) - return _alloc_counter; - if( id==_ALGLIB_GET_CUMULATIVE_ALLOC_SIZE ) - return _dbg_alloc_total; - if( id==_ALGLIB_GET_CUMULATIVE_ALLOC_COUNT ) - return _alloc_counter_total; - - if( id==_ALGLIB_VENDOR_MEMSTAT ) - { -#if defined(AE_MKL) - return ae_mkl_memstat(); -#else - return 0; -#endif - } - - /* workstealing counters */ - if( id==_ALGLIB_WSDBG_NCORES ) -#if defined(AE_SMP) - return ae_cores_count(); -#else - return 0; -#endif - if( id==_ALGLIB_WSDBG_PUSHROOT_OK ) - return dbgws_pushroot_ok; - if( id==_ALGLIB_WSDBG_PUSHROOT_FAILED ) - return dbgws_pushroot_failed; - - if( id==_ALGLIB_GET_CORES_COUNT ) -#if defined(AE_SMP) - return ae_cores_count(); -#else - return 0; -#endif - if( id==_ALGLIB_GET_GLOBAL_THREADING ) - return (ae_int64_t)ae_get_global_threading(); - if( id==_ALGLIB_GET_NWORKERS ) - return (ae_int64_t)_alglib_cores_to_use; - - /* unknown value */ - return 0; -} - -/************************************************************************ -This function sets default (global) threading model: -* serial execution -* multithreading, if cores_to_use allows it - -************************************************************************/ -void ae_set_global_threading(ae_uint64_t flg_value) -{ - flg_value = flg_value&_ALGLIB_FLG_THREADING_MASK; - AE_CRITICAL_ASSERT(flg_value==_ALGLIB_FLG_THREADING_SERIAL || flg_value==_ALGLIB_FLG_THREADING_PARALLEL); - _alglib_global_threading_flags = (unsigned char)(flg_value>>_ALGLIB_FLG_THREADING_SHIFT); -} - -/************************************************************************ -This function gets default (global) threading model: -* serial execution -* multithreading, if cores_to_use allows it - -************************************************************************/ -ae_uint64_t ae_get_global_threading() -{ - return ((ae_uint64_t)_alglib_global_threading_flags)<<_ALGLIB_FLG_THREADING_SHIFT; -} - -void ae_set_error_flag(ae_bool *p_flag, ae_bool cond, const char *filename, int lineno, const char *xdesc) -{ - if( cond ) - { - *p_flag = ae_true; - sef_file = filename; - sef_line = lineno; - sef_xdesc= xdesc; -#ifdef ALGLIB_ABORT_ON_ERROR_FLAG - printf("[ALGLIB] aborting on ae_set_error_flag(cond=true)\n"); - printf("[ALGLIB] %s:%d\n", filename, lineno); - printf("[ALGLIB] %s\n", xdesc); - fflush(stdout); - if( alglib_trace_file!=NULL ) fflush(alglib_trace_file); - abort(); -#endif - } -} - -/************************************************************************ -This function returns file name for the last call of ae_set_error_flag() -with non-zero cond parameter. -************************************************************************/ -const char * ae_get_last_error_file() -{ - return sef_file; -} - -/************************************************************************ -This function returns line number for the last call of ae_set_error_flag() -with non-zero cond parameter. -************************************************************************/ -int ae_get_last_error_line() -{ - return sef_line; -} - -/************************************************************************ -This function returns extra description for the last call of ae_set_error_flag() -with non-zero cond parameter. -************************************************************************/ -const char * ae_get_last_error_xdesc() -{ - return sef_xdesc; -} - -ae_int_t ae_misalignment(const void *ptr, size_t alignment) -{ - union _u - { - const void *ptr; - ae_int_t iptr; - } u; - u.ptr = ptr; - return (ae_int_t)(u.iptr%alignment); -} - -void* ae_align(void *ptr, size_t alignment) -{ - char *result = (char*)ptr; - if( (result-(char*)0)%alignment!=0 ) - result += alignment - (result-(char*)0)%alignment; - return result; -} - -/************************************************************************ -This function maps nworkers number (which can be positive, zero or -negative with 0 meaning "all cores", -1 meaning "all cores -1" and so on) -to "effective", strictly positive workers count. - -This function is intended to be used by debugging/testing code which -tests different number of worker threads. It is NOT aligned in any way -with ALGLIB multithreading framework (i.e. it can return non-zero worker -count even for single-threaded GPLed ALGLIB). -************************************************************************/ -ae_int_t ae_get_effective_workers(ae_int_t nworkers) -{ - ae_int_t ncores; - - /* determine cores count */ -#if defined(AE_NWORKERS) - ncores = AE_NWORKERS; -#elif AE_OS==AE_WINDOWS - SYSTEM_INFO sysInfo; - GetSystemInfo(&sysInfo); - ncores = (ae_int_t)(sysInfo.dwNumberOfProcessors); -#elif AE_OS==AE_POSIX - { - long r = sysconf(_SC_NPROCESSORS_ONLN); - ncores = r<=0 ? 1 : r; - } -#else - ncores = 1; -#endif - AE_CRITICAL_ASSERT(ncores>=1); - - /* map nworkers to its effective value */ - if( nworkers>=1 ) - return nworkers>ncores ? ncores : nworkers; - return ncores+nworkers>=1 ? ncores+nworkers : 1; -} - -/************************************************************************* -This function belongs to the family of "optional atomics", i.e. atomic -functions which either perform atomic changes - or do nothing at all, if -current compiler settings do not allow us to generate atomic code. - -All "optional atomics" are synchronized, i.e. either all of them work - or -no one of the works. - -This particular function performs atomic addition on pointer-sized value, -which must be pointer-size aligned. - -NOTE: this function is not intended to be extremely high performance one, - so use it only when necessary. -*************************************************************************/ -void ae_optional_atomic_add_i(ae_int_t *p, ae_int_t v) -{ - AE_CRITICAL_ASSERT(ae_misalignment(p,sizeof(void*))==0); -#if AE_OS==AE_WINDOWS - for(;;) - { - /* perform conversion between ae_int_t* and void** - without compiler warnings about indirection levels */ - union _u - { - PVOID volatile * volatile ptr; - volatile ae_int_t * volatile iptr; - } u; - u.iptr = p; - - /* atomic read for initial value */ - PVOID v0 = InterlockedCompareExchangePointer(u.ptr, NULL, NULL); - - /* increment cached value and store */ - if( InterlockedCompareExchangePointer(u.ptr, (PVOID)(((char*)v0)+v), v0)==v0 ) - break; - } -#elif (AE_COMPILER==AE_GNUC) && (AE_CPU==AE_INTEL) && (__GNUC__*100+__GNUC__>=470) - __atomic_add_fetch(p, v, __ATOMIC_RELAXED); -#else -#endif -} - -/************************************************************************* -This function belongs to the family of "optional atomics", i.e. atomic -functions which either perform atomic changes - or do nothing at all, if -current compiler settings do not allow us to generate atomic code. - -All "optional atomics" are synchronized, i.e. either all of them work - or -no one of the works. - -This particular function performs atomic subtraction on pointer-sized -value, which must be pointer-size aligned. - -NOTE: this function is not intended to be extremely high performance one, - so use it only when necessary. -*************************************************************************/ -void ae_optional_atomic_sub_i(ae_int_t *p, ae_int_t v) -{ - AE_CRITICAL_ASSERT(ae_misalignment(p,sizeof(void*))==0); -#if AE_OS==AE_WINDOWS - for(;;) - { - /* perform conversion between ae_int_t* and void** - without compiler warnings about indirection levels */ - union _u - { - PVOID volatile * volatile ptr; - volatile ae_int_t * volatile iptr; - } u; - u.iptr = p; - - /* atomic read for initial value, convert it to 1-byte pointer */ - PVOID v0 = InterlockedCompareExchangePointer(u.ptr, NULL, NULL); - - /* increment cached value and store */ - if( InterlockedCompareExchangePointer(u.ptr, (PVOID)(((char*)v0)-v), v0)==v0 ) - break; - } -#elif (AE_COMPILER==AE_GNUC) && (AE_CPU==AE_INTEL) && (__GNUC__*100+__GNUC__>=470) - __atomic_sub_fetch(p, v, __ATOMIC_RELAXED); -#else -#endif -} - - -/************************************************************************* -This function cleans up automatically managed memory before caller terminates -ALGLIB executing by ae_break() or by simply stopping calling callback. - -For state!=NULL it calls thread_exception_handler() and the ae_state_clear(). -For state==NULL it does nothing. -*************************************************************************/ -void ae_clean_up_before_breaking(ae_state *state) -{ - if( state!=NULL ) - { - if( state->thread_exception_handler!=NULL ) - state->thread_exception_handler(state); - ae_state_clear(state); - } -} - -/************************************************************************* -This function abnormally aborts program, using one of several ways: - -* for state!=NULL and state->break_jump being initialized with call to - ae_state_set_break_jump() - it performs longjmp() to return site. -* otherwise, abort() is called - -In all cases, for state!=NULL function sets state->last_error and -state->error_msg fields. It also clears state with ae_state_clear(). - -If state is not NULL and state->thread_exception_handler is set, it is -called prior to handling error and clearing state. -*************************************************************************/ -void ae_break(ae_state *state, ae_error_type error_type, const char *msg) -{ - if( state!=NULL ) - { - if( alglib_trace_type!=ALGLIB_TRACE_NONE ) - ae_trace("---!!! CRITICAL ERROR !!!--- exception with message '%s' was generated\n", msg!=NULL ? msg : ""); - ae_clean_up_before_breaking(state); - state->last_error = error_type; - state->error_msg = msg; - if( state->break_jump!=NULL ) - longjmp(*(state->break_jump), 1); - else - abort(); - } - else - abort(); -} - -#if AE_MALLOC==AE_BASIC_STATIC_MALLOC -void set_memory_pool(void *ptr, size_t size) -{ - /* - * Integrity checks - */ - AE_CRITICAL_ASSERT(sm_page_size==0); - AE_CRITICAL_ASSERT(sm_page_cnt==0); - AE_CRITICAL_ASSERT(sm_page_tbl==NULL); - AE_CRITICAL_ASSERT(sm_mem==NULL); - AE_CRITICAL_ASSERT(size>0); - - /* - * Align pointer - */ - size -= ae_misalignment(ptr, sizeof(ae_int_t)); - ptr = ae_align(ptr, sizeof(ae_int_t)); - - /* - * Calculate page size and page count, prepare pointers to page table and memory - */ - sm_page_size = 256; - AE_CRITICAL_ASSERT(size>=(sm_page_size+sizeof(ae_int_t))+sm_page_size); /* we expect to have memory for at least one page + table entry + alignment */ - sm_page_cnt = (size-sm_page_size)/(sm_page_size+sizeof(ae_int_t)); - AE_CRITICAL_ASSERT(sm_page_cnt>0); - sm_page_tbl = (ae_int_t*)ptr; - sm_mem = (unsigned char*)ae_align(sm_page_tbl+sm_page_cnt, sm_page_size); - - /* - * Mark all pages as free - */ - memset(sm_page_tbl, 0, sm_page_cnt*sizeof(ae_int_t)); -} - -void* ae_static_malloc(size_t size, size_t alignment) -{ - int rq_pages, i, j, cur_len; - - AE_CRITICAL_ASSERT(size>=0); - AE_CRITICAL_ASSERT(sm_page_size>0); - AE_CRITICAL_ASSERT(sm_page_cnt>0); - AE_CRITICAL_ASSERT(sm_page_tbl!=NULL); - AE_CRITICAL_ASSERT(sm_mem!=NULL); - - if( size==0 ) - return NULL; - if( _force_malloc_failure ) - return NULL; - - /* check that page alignment and requested alignment match each other */ - AE_CRITICAL_ASSERT(alignment<=sm_page_size); - AE_CRITICAL_ASSERT((sm_page_size%alignment)==0); - - /* search long enough sequence of pages */ - rq_pages = size/sm_page_size; - if( size%sm_page_size ) - rq_pages++; - cur_len = 0; - for(i=0; i0); - cur_len=0; - i += sm_page_tbl[i]; - continue; - } - - /* found it? */ - if( cur_len>=rq_pages ) - { - /* update counters (if flag is set) */ - if( _use_alloc_counter ) - { - ae_optional_atomic_add_i(&_alloc_counter, 1); - ae_optional_atomic_add_i(&_alloc_counter_total, 1); - } - if( _use_dbg_counters ) - ae_optional_atomic_add_i(&_dbg_alloc_total, size); - - /* mark pages and return */ - for(j=0; j=0); - AE_CRITICAL_ASSERT((page_idx%sm_page_size)==0); - page_idx = page_idx/sm_page_size; - AE_CRITICAL_ASSERT(page_idx=1); - for(i=0; i0); - AE_CRITICAL_ASSERT(sm_page_cnt>0); - AE_CRITICAL_ASSERT(sm_page_tbl!=NULL); - AE_CRITICAL_ASSERT(sm_mem!=NULL); - - /* scan page table */ - *bytes_used = 0; - *bytes_free = 0; - for(i=0; i0); - *bytes_used += sm_page_tbl[i]; - i += sm_page_tbl[i]; - } - } - *bytes_used *= sm_page_size; - *bytes_free *= sm_page_size; -} -#endif - -void* aligned_malloc(size_t size, size_t alignment) -{ -#if AE_MALLOC==AE_BASIC_STATIC_MALLOC - return ae_static_malloc(size, alignment); -#else - char *result = NULL; - - if( size==0 ) - return NULL; - if( _force_malloc_failure ) - return NULL; - if( _malloc_failure_after>0 && _alloc_counter_total>=_malloc_failure_after ) - return NULL; - - /* allocate */ - if( alignment<=1 ) - { - /* no alignment, just call alloc */ - void *block; - void **p; ; - block = malloc(sizeof(void*)+size); - if( block==NULL ) - return NULL; - p = (void**)block; - *p = block; - result = (char*)((char*)block+sizeof(void*)); - } - else - { - /* align */ - void *block; - block = malloc(alignment-1+sizeof(void*)+size); - if( block==NULL ) - return NULL; - result = (char*)block+sizeof(void*); - /*if( (result-(char*)0)%alignment!=0 ) - result += alignment - (result-(char*)0)%alignment;*/ - result = (char*)ae_align(result, alignment); - *((void**)(result-sizeof(void*))) = block; - } - - /* update counters (if flag is set) */ - if( _use_alloc_counter ) - { - ae_optional_atomic_add_i(&_alloc_counter, 1); - ae_optional_atomic_add_i(&_alloc_counter_total, 1); - } - if( _use_dbg_counters ) - ae_optional_atomic_add_i(&_dbg_alloc_total, (ae_int64_t)size); - - /* return */ - return (void*)result; -#endif -} - -void* aligned_extract_ptr(void *block) -{ -#if AE_MALLOC==AE_BASIC_STATIC_MALLOC - return NULL; -#else - if( block==NULL ) - return NULL; - return *((void**)((char*)block-sizeof(void*))); -#endif -} - -void aligned_free(void *block) -{ -#if AE_MALLOC==AE_BASIC_STATIC_MALLOC - ae_static_free(block); -#else - void *p; - if( block==NULL ) - return; - p = aligned_extract_ptr(block); - free(p); - if( _use_alloc_counter ) - ae_optional_atomic_sub_i(&_alloc_counter, 1); -#endif -} - -void* eternal_malloc(size_t size) -{ - if( size==0 ) - return NULL; - if( _force_malloc_failure ) - return NULL; - return malloc(size); -} - -/************************************************************************ -Allocate memory with automatic alignment. - -Returns NULL when zero size is specified. - -Error handling: -* if state is NULL, returns NULL on allocation error -* if state is not NULL, calls ae_break() on allocation error -************************************************************************/ -void* ae_malloc(size_t size, ae_state *state) -{ - void *result; - if( size==0 ) - return NULL; - result = aligned_malloc(size,AE_DATA_ALIGN); - if( result==NULL && state!=NULL) - ae_break(state, ERR_OUT_OF_MEMORY, "ae_malloc(): out of memory"); - return result; -} - -void ae_free(void *p) -{ - if( p!=NULL ) - aligned_free(p); -} - -/************************************************************************ -Sets pointers to the matrix rows. - -* dst must be correctly initialized matrix -* dst->data.ptr points to the beginning of memory block allocated for - row pointers. -* dst->ptr - undefined (initialized during algorithm processing) -* storage parameter points to the beginning of actual storage -************************************************************************/ -void ae_matrix_update_row_pointers(ae_matrix *dst, void *storage) -{ - char *p_base; - void **pp_ptr; - ae_int_t i; - if( dst->rows>0 && dst->cols>0 ) - { - p_base = (char*)storage; - pp_ptr = (void**)dst->data.ptr; - dst->ptr.pp_void = pp_ptr; - for(i=0; irows; i++, p_base+=dst->stride*ae_sizeof(dst->datatype)) - pp_ptr[i] = p_base; - } - else - dst->ptr.pp_void = NULL; -} - -/************************************************************************ -Returns size of datatype. -Zero for dynamic types like strings or multiple precision types. -************************************************************************/ -ae_int_t ae_sizeof(ae_datatype datatype) -{ - switch(datatype) - { - case DT_BOOL: return (ae_int_t)sizeof(ae_bool); - case DT_INT: return (ae_int_t)sizeof(ae_int_t); - case DT_REAL: return (ae_int_t)sizeof(double); - case DT_COMPLEX: return 2*(ae_int_t)sizeof(double); - default: return 0; - } -} - -/************************************************************************ -Checks that n bytes pointed by ptr are zero. - -This function is used in the constructors to check that instance fields -on entry are correctly initialized by zeros. -************************************************************************/ -ae_bool ae_check_zeros(const void *ptr, ae_int_t n) -{ - ae_int_t nu, nr, i; - unsigned long long c = 0x0; - - /* - * determine leading and trailing lengths - */ - nu = n/sizeof(unsigned long long); - nr = n%sizeof(unsigned long long); - - /* - * handle leading nu long long elements - */ - if( nu>0 ) - { - const unsigned long long *p_ull; - p_ull = (const unsigned long long *)ptr; - for(i=0; i0 ) - { - const unsigned char *p_uc; - p_uc = ((const unsigned char *)ptr)+nu*sizeof(unsigned long long); - for(i=0; iflags = 0x0; - - /* - * p_next points to itself because: - * * correct program should be able to detect end of the list - * by looking at the ptr field. - * * NULL p_next may be used to distinguish automatic blocks - * (in the list) from non-automatic (not in the list) - */ - state->last_block.p_next = &(state->last_block); - state->last_block.deallocator = NULL; - state->last_block.ptr = DYN_BOTTOM; - state->p_top_block = &(state->last_block); - state->break_jump = NULL; - state->error_msg = ""; - - /* - * determine endianness and initialize precomputed IEEE special quantities. - */ - state->endianness = ae_get_endianness(); - if( state->endianness==AE_LITTLE_ENDIAN ) - { - vp = (ae_int32_t*)(&state->v_nan); - vp[0] = 0; - vp[1] = (ae_int32_t)0x7FF80000; - vp = (ae_int32_t*)(&state->v_posinf); - vp[0] = 0; - vp[1] = (ae_int32_t)0x7FF00000; - vp = (ae_int32_t*)(&state->v_neginf); - vp[0] = 0; - vp[1] = (ae_int32_t)0xFFF00000; - } - else if( state->endianness==AE_BIG_ENDIAN ) - { - vp = (ae_int32_t*)(&state->v_nan); - vp[1] = 0; - vp[0] = (ae_int32_t)0x7FF80000; - vp = (ae_int32_t*)(&state->v_posinf); - vp[1] = 0; - vp[0] = (ae_int32_t)0x7FF00000; - vp = (ae_int32_t*)(&state->v_neginf); - vp[1] = 0; - vp[0] = (ae_int32_t)0xFFF00000; - } - else - abort(); - - /* - * set threading information - */ - state->worker_thread = NULL; - state->parent_task = NULL; - state->thread_exception_handler = NULL; -} - - -/************************************************************************ -This function clears ALGLIB environment state. -All dynamic data controlled by state are freed. -************************************************************************/ -void ae_state_clear(ae_state *state) -{ - while( state->p_top_block->ptr!=DYN_BOTTOM ) - ae_frame_leave(state); -} - - -/************************************************************************ -This function sets jump buffer for error handling. - -buf may be NULL. -************************************************************************/ -void ae_state_set_break_jump(ae_state *state, jmp_buf *buf) -{ - state->break_jump = buf; -} - - -/************************************************************************ -This function sets flags member of the ae_state structure - -buf may be NULL. -************************************************************************/ -void ae_state_set_flags(ae_state *state, ae_uint64_t flags) -{ - state->flags = flags; -} - - -/************************************************************************ -This function makes new stack frame. - -This function takes two parameters: environment state and pointer to the -dynamic block which will be used as indicator of the frame beginning. -This dynamic block must be initialized by caller and mustn't be changed/ -deallocated/reused till ae_leave_frame called. It may be global or local -variable (local is even better). -************************************************************************/ -void ae_frame_make(ae_state *state, ae_frame *tmp) -{ - tmp->db_marker.p_next = state->p_top_block; - tmp->db_marker.deallocator = NULL; - tmp->db_marker.ptr = DYN_FRAME; - state->p_top_block = &tmp->db_marker; -} - - -/************************************************************************ -This function leaves current stack frame and deallocates all automatic -dynamic blocks which were attached to this frame. -************************************************************************/ -void ae_frame_leave(ae_state *state) -{ - while( state->p_top_block->ptr!=DYN_FRAME && state->p_top_block->ptr!=DYN_BOTTOM) - { - if( state->p_top_block->ptr!=NULL && state->p_top_block->deallocator!=NULL) - ((ae_deallocator)(state->p_top_block->deallocator))(state->p_top_block->ptr); - state->p_top_block = state->p_top_block->p_next; - } - state->p_top_block = state->p_top_block->p_next; -} - - -/************************************************************************ -This function attaches block to the dynamic block list - -block block -state ALGLIB environment state - -This function does NOT generate exceptions. - -NOTES: -* never call it for special blocks which marks frame boundaries! -************************************************************************/ -void ae_db_attach(ae_dyn_block *block, ae_state *state) -{ - block->p_next = state->p_top_block; - state->p_top_block = block; -} - - -/************************************************************************ -This function initializes dynamic block: - -block destination block, MUST be zero-filled on entry -size size (in bytes), >=0. -state ALGLIB environment state, non-NULL -make_automatic if true, vector is added to the dynamic block list - -block is assumed to be uninitialized, its fields are ignored. You may -call this function with zero size in order to register block in the -dynamic list. - -Error handling: calls ae_break() on allocation error. Block is left in -valid state (empty, but valid). - -NOTES: -* never call it for blocks which are already in the list; use ae_db_realloc - for already allocated blocks. - -NOTE: no memory allocation is performed for initialization with size=0 -************************************************************************/ -void ae_db_init(ae_dyn_block *block, ae_int_t size, ae_state *state, ae_bool make_automatic) -{ - AE_CRITICAL_ASSERT(state!=NULL); - AE_CRITICAL_ASSERT(ae_check_zeros(block,sizeof(*block))); - - /* - * NOTE: these strange dances around block->ptr are necessary - * in order to correctly handle possible exceptions during - * memory allocation. - */ - ae_assert(size>=0, "ae_db_init(): negative size", state); - block->ptr = NULL; - block->valgrind_hint = NULL; - ae_touch_ptr(block->ptr); - ae_touch_ptr(block->valgrind_hint); - if( make_automatic ) - ae_db_attach(block, state); - else - block->p_next = NULL; - if( size!=0 ) - { - block->ptr = ae_malloc((size_t)size, state); - block->valgrind_hint = aligned_extract_ptr(block->ptr); - } - block->deallocator = ae_free; -} - - -/************************************************************************ -This function realloc's dynamic block: - -block destination block (initialized) -size new size (in bytes) -state ALGLIB environment state - -block is assumed to be initialized. - -This function: -* deletes old contents -* preserves automatic state - -Error handling: calls ae_break() on allocation error. Block is left in -valid state - empty, but valid. - -NOTES: -* never call it for special blocks which mark frame boundaries! -************************************************************************/ -void ae_db_realloc(ae_dyn_block *block, ae_int_t size, ae_state *state) -{ - AE_CRITICAL_ASSERT(state!=NULL); - - /* - * NOTE: these strange dances around block->ptr are necessary - * in order to correctly handle possible exceptions during - * memory allocation. - */ - ae_assert(size>=0, "ae_db_realloc(): negative size", state); - if( block->ptr!=NULL ) - { - ((ae_deallocator)block->deallocator)(block->ptr); - block->ptr = NULL; - block->valgrind_hint = NULL; - } - block->ptr = ae_malloc((size_t)size, state); - block->valgrind_hint = aligned_extract_ptr(block->ptr); - block->deallocator = ae_free; -} - - -/************************************************************************ -This function clears dynamic block (releases all dynamically allocated -memory). Dynamic block may be in automatic management list - in this case -it will NOT be removed from list. - -block destination block (initialized) - -NOTES: -* never call it for special blocks which marks frame boundaries! -************************************************************************/ -void ae_db_free(ae_dyn_block *block) -{ - if( block->ptr!=NULL ) - ((ae_deallocator)block->deallocator)(block->ptr); - block->ptr = NULL; - block->valgrind_hint = NULL; - block->deallocator = ae_free; -} - -/************************************************************************ -This function swaps contents of two dynamic blocks (pointers and -deallocators) leaving other parameters (automatic management settings, -etc.) unchanged. - -NOTES: -* never call it for special blocks which marks frame boundaries! -************************************************************************/ -void ae_db_swap(ae_dyn_block *block1, ae_dyn_block *block2) -{ - void (*deallocator)(void*) = NULL; - void * volatile ptr; - void * valgrind_hint; - - ptr = block1->ptr; - valgrind_hint = block1->valgrind_hint; - deallocator = block1->deallocator; - - block1->ptr = block2->ptr; - block1->valgrind_hint = block2->valgrind_hint; - block1->deallocator = block2->deallocator; - - block2->ptr = ptr; - block2->valgrind_hint = valgrind_hint; - block2->deallocator = deallocator; -} - -/************************************************************************* -This function creates ae_vector. -Vector size may be zero. Vector contents is uninitialized. - -dst destination vector, MUST be zero-filled (we check it - and call abort() if *dst is non-zero; the rationale is - that we can not correctly handle errors in constructors - without zero-filling). -size vector size, may be zero -datatype guess what... -state pointer to current state structure. Can not be NULL. - used for exception handling (say, allocation error results - in longjmp call). -make_automatic if true, vector will be registered in the current frame - of the state structure; - -NOTE: no memory allocation is performed for initialization with size=0 -*************************************************************************/ -void ae_vector_init(ae_vector *dst, ae_int_t size, ae_datatype datatype, ae_state *state, ae_bool make_automatic) -{ - /* - * Integrity checks - */ - AE_CRITICAL_ASSERT(state!=NULL); - AE_CRITICAL_ASSERT(ae_check_zeros(dst,sizeof(*dst))); - ae_assert(size>=0, "ae_vector_init(): negative size", state); - - /* prepare for possible errors during allocation */ - dst->cnt = 0; - dst->ptr.p_ptr = NULL; - - /* init */ - ae_db_init(&dst->data, size*ae_sizeof(datatype), state, make_automatic); - dst->cnt = size; - dst->datatype = datatype; - dst->ptr.p_ptr = dst->data.ptr; - dst->is_attached = ae_false; -} - - -/************************************************************************ -This function creates copy of ae_vector. New copy of the data is created, -which is managed and owned by newly initialized vector. - -dst destination vector, MUST be zero-filled (we check it - and call abort() if *dst is non-zero; the rationale is - that we can not correctly handle errors in constructors - without zero-filling). -src well, it is source -state pointer to current state structure. Can not be NULL. - used for exception handling (say, allocation error results - in longjmp call). -make_automatic if true, vector will be registered in the current frame - of the state structure; - -dst is assumed to be uninitialized, its fields are ignored. -************************************************************************/ -void ae_vector_init_copy(ae_vector *dst, ae_vector *src, ae_state *state, ae_bool make_automatic) -{ - AE_CRITICAL_ASSERT(state!=NULL); - - ae_vector_init(dst, src->cnt, src->datatype, state, make_automatic); - if( src->cnt!=0 ) - memmove(dst->ptr.p_ptr, src->ptr.p_ptr, (size_t)(src->cnt*ae_sizeof(src->datatype))); -} - -/************************************************************************ -This function initializes ae_vector using X-structure as source. New copy -of data is created, which is owned/managed by ae_vector structure. Both -structures (source and destination) remain completely independent after -this call. - -dst destination vector, MUST be zero-filled (we check it - and call abort() if *dst is non-zero; the rationale is - that we can not correctly handle errors in constructors - without zero-filling). -src well, it is source -state pointer to current state structure. Can not be NULL. - used for exception handling (say, allocation error results - in longjmp call). -make_automatic if true, vector will be registered in the current frame - of the state structure; - -dst is assumed to be uninitialized, its fields are ignored. -************************************************************************/ -void ae_vector_init_from_x(ae_vector *dst, x_vector *src, ae_state *state, ae_bool make_automatic) -{ - AE_CRITICAL_ASSERT(state!=NULL); - - ae_vector_init(dst, (ae_int_t)src->cnt, (ae_datatype)src->datatype, state, make_automatic); - if( src->cnt>0 ) - memmove(dst->ptr.p_ptr, src->x_ptr.p_ptr, (size_t)(((ae_int_t)src->cnt)*ae_sizeof((ae_datatype)src->datatype))); -} - -/************************************************************************ -This function initializes ae_vector using X-structure as source. - -New vector is attached to source: -* DST shares memory with SRC -* both DST and SRC are writable - all writes to DST change elements of - SRC and vice versa. -* DST can be reallocated with ae_vector_set_length(), in this case SRC - remains untouched -* SRC, however, CAN NOT BE REALLOCATED AS LONG AS DST EXISTS - -NOTE: is_attached field is set to ae_true in order to indicate that - vector does not own its memory. - -dst destination vector -src well, it is source -state pointer to current state structure. Can not be NULL. - used for exception handling (say, allocation error results - in longjmp call). -make_automatic if true, vector will be registered in the current frame - of the state structure; - -dst is assumed to be uninitialized, its fields are ignored. -************************************************************************/ -void ae_vector_init_attach_to_x(ae_vector *dst, x_vector *src, ae_state *state, ae_bool make_automatic) -{ - volatile ae_int_t cnt; - - AE_CRITICAL_ASSERT(state!=NULL); - AE_CRITICAL_ASSERT(ae_check_zeros(dst,sizeof(*dst))); - - cnt = (ae_int_t)src->cnt; - - /* ensure that size is correct */ - ae_assert(cnt==src->cnt, "ae_vector_init_attach_to_x(): 32/64 overflow", state); - ae_assert(cnt>=0, "ae_vector_init_attach_to_x(): negative length", state); - - /* prepare for possible errors during allocation */ - dst->cnt = 0; - dst->ptr.p_ptr = NULL; - dst->datatype = (ae_datatype)src->datatype; - - /* zero-size init in order to correctly register in the frame */ - ae_db_init(&dst->data, 0, state, make_automatic); - - /* init */ - dst->cnt = cnt; - dst->ptr.p_ptr = src->x_ptr.p_ptr; - dst->is_attached = ae_true; -} - -/************************************************************************ -This function changes length of ae_vector. - -dst destination vector -newsize vector size, may be zero -state ALGLIB environment state, can not be NULL - -Error handling: calls ae_break() on allocation error - -NOTES: -* vector must be initialized -* all contents is destroyed during setlength() call -* new size may be zero. -************************************************************************/ -void ae_vector_set_length(ae_vector *dst, ae_int_t newsize, ae_state *state) -{ - AE_CRITICAL_ASSERT(state!=NULL); - ae_assert(newsize>=0, "ae_vector_set_length(): negative size", state); - if( dst->cnt==newsize ) - return; - - /* realloc, being ready for exception during reallocation (cnt=ptr=0 on entry) */ - dst->cnt = 0; - dst->ptr.p_ptr = NULL; - ae_db_realloc(&dst->data, newsize*ae_sizeof(dst->datatype), state); - dst->cnt = newsize; - dst->ptr.p_ptr = dst->data.ptr; -} - -/************************************************************************ -This function resized ae_vector, preserving previously existing elements. -Values of elements added during vector growth is undefined. - -dst destination vector -newsize vector size, may be zero -state ALGLIB environment state, can not be NULL - -Error handling: calls ae_break() on allocation error - -NOTES: -* vector must be initialized -* new size may be zero. -************************************************************************/ -void ae_vector_resize(ae_vector *dst, ae_int_t newsize, ae_state *state) -{ - ae_vector tmp; - ae_int_t bytes_total; - - memset(&tmp, 0, sizeof(tmp)); - ae_vector_init(&tmp, newsize, dst->datatype, state, ae_false); - bytes_total = (dst->cntcnt : newsize)*ae_sizeof(dst->datatype); - if( bytes_total>0 ) - memmove(tmp.ptr.p_ptr, dst->ptr.p_ptr, bytes_total); - ae_swap_vectors(dst, &tmp); - ae_vector_clear(&tmp); -} - - -/************************************************************************ -This function provides "CLEAR" functionality for vector (contents is -cleared, but structure still left in valid state). - -The function clears vector contents (releases all dynamically allocated -memory). Vector may be in automatic management list - in this case it -will NOT be removed from list. - -IMPORTANT: this function does NOT invalidates dst; it just releases all -dynamically allocated storage, but dst still may be used after call to -ae_vector_set_length(). - -dst destination vector -************************************************************************/ -void ae_vector_clear(ae_vector *dst) -{ - dst->cnt = 0; - ae_db_free(&dst->data); - dst->ptr.p_ptr = 0; - dst->is_attached = ae_false; -} - - -/************************************************************************ -This function provides "DESTROY" functionality for vector (contents is -cleared, all internal structures are destroyed). For vectors it is same -as CLEAR. - -dst destination vector -************************************************************************/ -void ae_vector_destroy(ae_vector *dst) -{ - ae_vector_clear(dst); -} - - -/************************************************************************ -This function efficiently swaps contents of two vectors, leaving other -pararemeters (automatic management, etc.) unchanged. -************************************************************************/ -void ae_swap_vectors(ae_vector *vec1, ae_vector *vec2) -{ - ae_int_t cnt; - ae_datatype datatype; - void *p_ptr; - - ae_assert(!vec1->is_attached, "ALGLIB: internal error, attempt to swap vectors attached to X-object", NULL); - ae_assert(!vec2->is_attached, "ALGLIB: internal error, attempt to swap vectors attached to X-object", NULL); - - ae_db_swap(&vec1->data, &vec2->data); - - cnt = vec1->cnt; - datatype = vec1->datatype; - p_ptr = vec1->ptr.p_ptr; - vec1->cnt = vec2->cnt; - vec1->datatype = vec2->datatype; - vec1->ptr.p_ptr = vec2->ptr.p_ptr; - vec2->cnt = cnt; - vec2->datatype = datatype; - vec2->ptr.p_ptr = p_ptr; -} - -/************************************************************************ -This function creates ae_matrix. - -Matrix size may be zero, in such cases both rows and cols are zero. -Matrix contents is uninitialized. - -dst destination matrix, must be zero-filled -rows rows count -cols cols count -datatype element type -state pointer to current state structure. Can not be NULL. - used for exception handling (say, allocation error results - in longjmp call). -make_automatic if true, matrix will be registered in the current frame - of the state structure; - -dst is assumed to be uninitialized, its fields are ignored. - -NOTE: no memory allocation is performed for initialization with rows=cols=0 -************************************************************************/ -void ae_matrix_init(ae_matrix *dst, ae_int_t rows, ae_int_t cols, ae_datatype datatype, ae_state *state, ae_bool make_automatic) -{ - AE_CRITICAL_ASSERT(state!=NULL); - AE_CRITICAL_ASSERT(ae_check_zeros(dst,sizeof(*dst))); - - ae_assert(rows>=0 && cols>=0, "ae_matrix_init(): negative length", state); - - /* if one of rows/cols is zero, another MUST be too; perform quick exit */ - if( rows==0 || cols==0 ) - { - dst->rows = 0; - dst->cols = 0; - dst->is_attached = ae_false; - dst->ptr.pp_void = NULL; - dst->stride = 0; - dst->datatype = datatype; - ae_db_init(&dst->data, 0, state, make_automatic); - return; - } - - /* init, being ready for exception during allocation (rows=cols=ptr=NULL on entry) */ - dst->is_attached = ae_false; - dst->rows = 0; - dst->cols = 0; - dst->ptr.pp_void = NULL; - dst->stride = cols; - while( dst->stride*ae_sizeof(datatype)%AE_DATA_ALIGN!=0 ) - dst->stride++; - dst->datatype = datatype; - ae_db_init(&dst->data, rows*((ae_int_t)sizeof(void*)+dst->stride*ae_sizeof(datatype))+AE_DATA_ALIGN-1, state, make_automatic); - dst->rows = rows; - dst->cols = cols; - ae_matrix_update_row_pointers(dst, ae_align((char*)dst->data.ptr+rows*sizeof(void*),AE_DATA_ALIGN)); -} - - -/************************************************************************ -This function creates copy of ae_matrix. A new copy of the data is created. - -dst destination matrix, must be zero-filled -src well, it is source -state pointer to current state structure. Can not be NULL. - used for exception handling (say, allocation error results - in longjmp call). -make_automatic if true, matrix will be registered in the current frame - of the state structure; - -dst is assumed to be uninitialized, its fields are ignored. -************************************************************************/ -void ae_matrix_init_copy(ae_matrix *dst, ae_matrix *src, ae_state *state, ae_bool make_automatic) -{ - ae_int_t i; - ae_matrix_init(dst, src->rows, src->cols, src->datatype, state, make_automatic); - if( src->rows!=0 && src->cols!=0 ) - { - if( dst->stride==src->stride ) - memmove(dst->ptr.pp_void[0], src->ptr.pp_void[0], (size_t)(src->rows*src->stride*ae_sizeof(src->datatype))); - else - for(i=0; irows; i++) - memmove(dst->ptr.pp_void[i], src->ptr.pp_void[i], (size_t)(dst->cols*ae_sizeof(dst->datatype))); - } -} - - -/************************************************************************ -This function initializes ae_matrix using X-structure as source. New copy -of data is created, which is owned/managed by ae_matrix structure. Both -structures (source and destination) remain completely independent after -this call. - -dst destination matrix, must be zero-filled -src well, it is source -state pointer to current state structure. Can not be NULL. - used for exception handling (say, allocation error results - in longjmp call). -make_automatic if true, matrix will be registered in the current frame - of the state structure; - -dst is assumed to be uninitialized, its fields are ignored. -************************************************************************/ -void ae_matrix_init_from_x(ae_matrix *dst, x_matrix *src, ae_state *state, ae_bool make_automatic) -{ - char *p_src_row; - char *p_dst_row; - ae_int_t row_size; - ae_int_t i; - AE_CRITICAL_ASSERT(state!=NULL); - ae_matrix_init(dst, (ae_int_t)src->rows, (ae_int_t)src->cols, (ae_datatype)src->datatype, state, make_automatic); - if( src->rows!=0 && src->cols!=0 ) - { - p_src_row = (char*)src->x_ptr.p_ptr; - p_dst_row = (char*)(dst->ptr.pp_void[0]); - row_size = ae_sizeof((ae_datatype)src->datatype)*(ae_int_t)src->cols; - for(i=0; irows; i++, p_src_row+=src->stride*ae_sizeof((ae_datatype)src->datatype), p_dst_row+=dst->stride*ae_sizeof((ae_datatype)src->datatype)) - memmove(p_dst_row, p_src_row, (size_t)(row_size)); - } -} - - -/************************************************************************ -This function initializes ae_matrix using X-structure as source. - -New matrix is attached to source: -* DST shares memory with SRC -* both DST and SRC are writable - all writes to DST change elements of - SRC and vice versa. -* DST can be reallocated with ae_matrix_set_length(), in this case SRC - remains untouched -* SRC, however, CAN NOT BE REALLOCATED AS LONG AS DST EXISTS - -dst destination matrix, must be zero-filled -src well, it is source -state pointer to current state structure. Can not be NULL. - used for exception handling (say, allocation error results - in longjmp call). -make_automatic if true, matrix will be registered in the current frame - of the state structure; - -dst is assumed to be uninitialized, its fields are ignored. -************************************************************************/ -void ae_matrix_init_attach_to_x(ae_matrix *dst, x_matrix *src, ae_state *state, ae_bool make_automatic) -{ - ae_int_t rows, cols; - - AE_CRITICAL_ASSERT(state!=NULL); - AE_CRITICAL_ASSERT(ae_check_zeros(dst,sizeof(*dst))); - - rows = (ae_int_t)src->rows; - cols = (ae_int_t)src->cols; - - /* check that X-source is densely packed */ - ae_assert(src->cols==src->stride, "ae_matrix_init_attach_to_x(): unsupported stride", state); - - /* ensure that size is correct */ - ae_assert(rows==src->rows, "ae_matrix_init_attach_to_x(): 32/64 overflow", state); - ae_assert(cols==src->cols, "ae_matrix_init_attach_to_x(): 32/64 overflow", state); - ae_assert(rows>=0 && cols>=0, "ae_matrix_init_attach_to_x(): negative length", state); - - /* if one of rows/cols is zero, another MUST be too */ - if( rows==0 || cols==0 ) - { - rows = 0; - cols = 0; - } - - /* init, being ready for allocation error */ - dst->is_attached = ae_true; - dst->rows = 0; - dst->cols = 0; - dst->stride = cols; - dst->datatype = (ae_datatype)src->datatype; - dst->ptr.pp_void = NULL; - ae_db_init(&dst->data, rows*(ae_int_t)sizeof(void*), state, make_automatic); - dst->rows = rows; - dst->cols = cols; - if( dst->rows>0 && dst->cols>0 ) - { - ae_int_t i, rowsize; - char *p_row; - void **pp_ptr; - - p_row = (char*)src->x_ptr.p_ptr; - rowsize = dst->stride*ae_sizeof(dst->datatype); - pp_ptr = (void**)dst->data.ptr; - dst->ptr.pp_void = pp_ptr; - for(i=0; irows; i++, p_row+=rowsize) - pp_ptr[i] = p_row; - } -} - - -/************************************************************************ -This function changes length of ae_matrix. - -dst destination matrix -rows size, may be zero -cols size, may be zero -state ALGLIB environment state - -Error handling: -* if state is NULL, returns ae_false on allocation error -* if state is not NULL, calls ae_break() on allocation error -* returns ae_true on success - -NOTES: -* matrix must be initialized -* all contents is destroyed during setlength() call -* new size may be zero. -************************************************************************/ -void ae_matrix_set_length(ae_matrix *dst, ae_int_t rows, ae_int_t cols, ae_state *state) -{ - AE_CRITICAL_ASSERT(state!=NULL); - ae_assert(rows>=0 && cols>=0, "ae_matrix_set_length(): negative length", state); - if( dst->rows==rows && dst->cols==cols ) - return; - - /* prepare stride */ - dst->stride = cols; - while( dst->stride*ae_sizeof(dst->datatype)%AE_DATA_ALIGN!=0 ) - dst->stride++; - - /* realloc, being ready for an exception during reallocation (rows=cols=0 on entry) */ - dst->rows = 0; - dst->cols = 0; - dst->ptr.pp_void = NULL; - ae_db_realloc(&dst->data, rows*((ae_int_t)sizeof(void*)+dst->stride*ae_sizeof(dst->datatype))+AE_DATA_ALIGN-1, state); - dst->rows = rows; - dst->cols = cols; - - /* update pointers to rows */ - ae_matrix_update_row_pointers(dst, ae_align((char*)dst->data.ptr+dst->rows*sizeof(void*),AE_DATA_ALIGN)); -} - - -/************************************************************************ -This function provides "CLEAR" functionality for vector (contents is -cleared, but structure still left in valid state). - -The function clears matrix contents (releases all dynamically allocated -memory). Matrix may be in automatic management list - in this case it -will NOT be removed from list. - -IMPORTANT: this function does NOT invalidates dst; it just releases all -dynamically allocated storage, but dst still may be used after call to -ae_matrix_set_length(). - -dst destination matrix -************************************************************************/ -void ae_matrix_clear(ae_matrix *dst) -{ - dst->rows = 0; - dst->cols = 0; - dst->stride = 0; - ae_db_free(&dst->data); - dst->ptr.p_ptr = 0; - dst->is_attached = ae_false; -} - - -/************************************************************************ -This function provides "DESTROY" functionality for matrix (contents is -cleared, but structure still left in valid state). - -For matrices it is same as CLEAR. - -dst destination matrix -************************************************************************/ -void ae_matrix_destroy(ae_matrix *dst) -{ - ae_matrix_clear(dst); -} - - -/************************************************************************ -This function efficiently swaps contents of two vectors, leaving other -pararemeters (automatic management, etc.) unchanged. -************************************************************************/ -void ae_swap_matrices(ae_matrix *mat1, ae_matrix *mat2) -{ - ae_int_t rows; - ae_int_t cols; - ae_int_t stride; - ae_datatype datatype; - void *p_ptr; - - ae_assert(!mat1->is_attached, "ALGLIB: internal error, attempt to swap matrices attached to X-object", NULL); - ae_assert(!mat2->is_attached, "ALGLIB: internal error, attempt to swap matrices attached to X-object", NULL); - - ae_db_swap(&mat1->data, &mat2->data); - - rows = mat1->rows; - cols = mat1->cols; - stride = mat1->stride; - datatype = mat1->datatype; - p_ptr = mat1->ptr.p_ptr; - - mat1->rows = mat2->rows; - mat1->cols = mat2->cols; - mat1->stride = mat2->stride; - mat1->datatype = mat2->datatype; - mat1->ptr.p_ptr = mat2->ptr.p_ptr; - - mat2->rows = rows; - mat2->cols = cols; - mat2->stride = stride; - mat2->datatype = datatype; - mat2->ptr.p_ptr = p_ptr; -} - - -/************************************************************************ -This function creates smart pointer structure. - -dst destination smart pointer, must be zero-filled -subscriber pointer to pointer which receives updates in the - internal object stored in ae_smart_ptr. Any update to - dst->ptr is translated to subscriber. Can be NULL. -state pointer to current state structure. Can not be NULL. - used for exception handling (say, allocation error results - in longjmp call). -make_automatic if true, pointer will be registered in the current frame - of the state structure; - -Error handling: -* on failure calls ae_break() with NULL state pointer. Usually it results - in abort() call. - -After initialization, smart pointer stores NULL pointer. -************************************************************************/ -void ae_smart_ptr_init(ae_smart_ptr *dst, void **subscriber, ae_state *state, ae_bool make_automatic) -{ - AE_CRITICAL_ASSERT(state!=NULL); - AE_CRITICAL_ASSERT(ae_check_zeros(dst,sizeof(*dst))); - dst->subscriber = subscriber; - dst->ptr = NULL; - if( dst->subscriber!=NULL ) - *(dst->subscriber) = dst->ptr; - dst->is_owner = ae_false; - dst->is_dynamic = ae_false; - dst->frame_entry.deallocator = ae_smart_ptr_destroy; - dst->frame_entry.ptr = dst; - if( make_automatic ) - ae_db_attach(&dst->frame_entry, state); -} - - -/************************************************************************ -This function clears smart pointer structure. - -dst destination smart pointer. - -After call to this function smart pointer contains NULL reference, which -is propagated to its subscriber (in cases non-NULL subscruber was -specified during pointer creation). -************************************************************************/ -void ae_smart_ptr_clear(void *_dst) -{ - ae_smart_ptr *dst = (ae_smart_ptr*)_dst; - if( dst->is_owner && dst->ptr!=NULL ) - { - dst->destroy(dst->ptr); - if( dst->is_dynamic ) - ae_free(dst->ptr); - } - dst->is_owner = ae_false; - dst->is_dynamic = ae_false; - dst->ptr = NULL; - dst->destroy = NULL; - if( dst->subscriber!=NULL ) - *(dst->subscriber) = NULL; -} - - -/************************************************************************ -This function dstroys smart pointer structure (same as clearing it). - -dst destination smart pointer. -************************************************************************/ -void ae_smart_ptr_destroy(void *_dst) -{ - ae_smart_ptr_clear(_dst); -} - - -/************************************************************************ -This function assigns pointer to ae_smart_ptr structure. - -dst destination smart pointer. -new_ptr new pointer to assign -is_owner whether smart pointer owns new_ptr -is_dynamic whether object is dynamic - clearing such object - requires BOTH calling destructor function AND calling - ae_free() for memory occupied by object. -destroy destructor function - -In case smart pointer already contains non-NULL value and owns this value, -it is freed before assigning new pointer. - -Changes in pointer are propagated to its subscriber (in case non-NULL -subscriber was specified during pointer creation). - -You can specify NULL new_ptr, in which case is_owner/destroy are ignored. -************************************************************************/ -void ae_smart_ptr_assign(ae_smart_ptr *dst, void *new_ptr, ae_bool is_owner, ae_bool is_dynamic, void (*destroy)(void*)) -{ - if( dst->is_owner && dst->ptr!=NULL ) - { - dst->destroy(dst->ptr); - if( dst->is_dynamic ) - ae_free(dst->ptr); - } - if( new_ptr!=NULL ) - { - dst->ptr = new_ptr; - dst->is_owner = is_owner; - dst->is_dynamic = is_dynamic; - dst->destroy = destroy; - } - else - { - dst->ptr = NULL; - dst->is_owner = ae_false; - dst->is_dynamic = ae_false; - dst->destroy = NULL; - } - if( dst->subscriber!=NULL ) - *(dst->subscriber) = dst->ptr; -} - - -/************************************************************************ -This function releases pointer owned by ae_smart_ptr structure: -* all internal fields are set to NULL -* destructor function for internal pointer is NOT called even when we own - this pointer. After this call ae_smart_ptr releases ownership of its - pointer and passes it to caller. -* changes in pointer are propagated to its subscriber (in case non-NULL - subscriber was specified during pointer creation). - -dst destination smart pointer. -************************************************************************/ -void ae_smart_ptr_release(ae_smart_ptr *dst) -{ - dst->is_owner = ae_false; - dst->is_dynamic = ae_false; - dst->ptr = NULL; - dst->destroy = NULL; - if( dst->subscriber!=NULL ) - *(dst->subscriber) = NULL; -} - -/************************************************************************ -This function copies contents of ae_vector (SRC) to x_vector (DST). - -This function should not be called for DST which is attached to SRC -(opposite situation, when SRC is attached to DST, is possible). - -Depending on situation, following actions are performed -* for SRC attached to DST, this function performs no actions (no need to - do anything) -* for independent vectors of different sizes it allocates storage in DST - and copy contents of SRC to DST. DST->last_action field is set to - ACT_NEW_LOCATION, and DST->owner is set to OWN_AE. -* for independent vectors of same sizes it does not perform memory - (re)allocation. It just copies SRC to already existing place. - DST->last_action is set to ACT_SAME_LOCATION (unless it was - ACT_NEW_LOCATION), DST->owner is unmodified. - -dst destination vector -src source, vector in x-format -state ALGLIB environment state - -NOTES: -* dst is assumed to be initialized. Its contents is freed before copying - data from src (if size / type are different) or overwritten (if - possible given destination size). -************************************************************************/ -void ae_x_set_vector(x_vector *dst, ae_vector *src, ae_state *state) -{ - if( src->ptr.p_ptr == dst->x_ptr.p_ptr ) - { - /* src->ptr points to the beginning of dst, attached matrices, no need to copy */ - return; - } - if( dst->cnt!=src->cnt || dst->datatype!=src->datatype ) - { - if( dst->owner==OWN_AE ) - ae_free(dst->x_ptr.p_ptr); - dst->x_ptr.p_ptr = ae_malloc((size_t)(src->cnt*ae_sizeof(src->datatype)), state); - if( src->cnt!=0 && dst->x_ptr.p_ptr==NULL ) - ae_break(state, ERR_OUT_OF_MEMORY, "ae_malloc(): out of memory"); - dst->last_action = ACT_NEW_LOCATION; - dst->cnt = src->cnt; - dst->datatype = src->datatype; - dst->owner = OWN_AE; - } - else - { - if( dst->last_action==ACT_UNCHANGED ) - dst->last_action = ACT_SAME_LOCATION; - else if( dst->last_action==ACT_SAME_LOCATION ) - dst->last_action = ACT_SAME_LOCATION; - else if( dst->last_action==ACT_NEW_LOCATION ) - dst->last_action = ACT_NEW_LOCATION; - else - ae_assert(ae_false, "ALGLIB: internal error in ae_x_set_vector()", state); - } - if( src->cnt ) - memmove(dst->x_ptr.p_ptr, src->ptr.p_ptr, (size_t)(src->cnt*ae_sizeof(src->datatype))); -} - -/************************************************************************ -This function copies contents of ae_matrix to x_matrix. - -This function should not be called for DST which is attached to SRC -(opposite situation, when SRC is attached to DST, is possible). - -Depending on situation, following actions are performed -* for SRC attached to DST, this function performs no actions (no need to - do anything) -* for independent matrices of different sizes it allocates storage in DST - and copy contents of SRC to DST. DST->last_action field is set to - ACT_NEW_LOCATION, and DST->owner is set to OWN_AE. -* for independent matrices of same sizes it does not perform memory - (re)allocation. It just copies SRC to already existing place. - DST->last_action is set to ACT_SAME_LOCATION (unless it was - ACT_NEW_LOCATION), DST->owner is unmodified. - -dst destination vector -src source, matrix in x-format -state ALGLIB environment state - -NOTES: -* dst is assumed to be initialized. Its contents is freed before copying - data from src (if size / type are different) or overwritten (if - possible given destination size). -************************************************************************/ -void ae_x_set_matrix(x_matrix *dst, ae_matrix *src, ae_state *state) -{ - char *p_src_row; - char *p_dst_row; - ae_int_t i; - ae_int_t row_size; - if( src->ptr.pp_void!=NULL && src->ptr.pp_void[0] == dst->x_ptr.p_ptr ) - { - /* src->ptr points to the beginning of dst, attached matrices, no need to copy */ - return; - } - if( dst->rows!=src->rows || dst->cols!=src->cols || dst->datatype!=src->datatype ) - { - if( dst->owner==OWN_AE ) - ae_free(dst->x_ptr.p_ptr); - dst->rows = src->rows; - dst->cols = src->cols; - dst->stride = src->cols; - dst->datatype = src->datatype; - dst->x_ptr.p_ptr = ae_malloc((size_t)(dst->rows*((ae_int_t)dst->stride)*ae_sizeof(src->datatype)), state); - if( dst->rows!=0 && dst->stride!=0 && dst->x_ptr.p_ptr==NULL ) - ae_break(state, ERR_OUT_OF_MEMORY, "ae_malloc(): out of memory"); - dst->last_action = ACT_NEW_LOCATION; - dst->owner = OWN_AE; - } - else - { - if( dst->last_action==ACT_UNCHANGED ) - dst->last_action = ACT_SAME_LOCATION; - else if( dst->last_action==ACT_SAME_LOCATION ) - dst->last_action = ACT_SAME_LOCATION; - else if( dst->last_action==ACT_NEW_LOCATION ) - dst->last_action = ACT_NEW_LOCATION; - else - ae_assert(ae_false, "ALGLIB: internal error in ae_x_set_vector()", state); - } - if( src->rows!=0 && src->cols!=0 ) - { - p_src_row = (char*)(src->ptr.pp_void[0]); - p_dst_row = (char*)dst->x_ptr.p_ptr; - row_size = ae_sizeof(src->datatype)*src->cols; - for(i=0; irows; i++, p_src_row+=src->stride*ae_sizeof(src->datatype), p_dst_row+=dst->stride*ae_sizeof(src->datatype)) - memmove(p_dst_row, p_src_row, (size_t)(row_size)); - } -} - -/************************************************************************ -This function attaches x_vector to ae_vector's contents. -Ownership of memory allocated is not changed (it is still managed by -ae_matrix). - -dst destination vector -src source, vector in x-format -state ALGLIB environment state - -NOTES: -* dst is assumed to be initialized. Its contents is freed before - attaching to src. -* this function doesn't need ae_state parameter because it can't fail - (assuming correctly initialized src) -************************************************************************/ -void ae_x_attach_to_vector(x_vector *dst, ae_vector *src) -{ - if( dst->owner==OWN_AE ) - ae_free(dst->x_ptr.p_ptr); - dst->x_ptr.p_ptr = src->ptr.p_ptr; - dst->last_action = ACT_NEW_LOCATION; - dst->cnt = src->cnt; - dst->datatype = src->datatype; - dst->owner = OWN_CALLER; -} - -/************************************************************************ -This function attaches x_matrix to ae_matrix's contents. -Ownership of memory allocated is not changed (it is still managed by -ae_matrix). - -dst destination vector -src source, matrix in x-format -state ALGLIB environment state - -NOTES: -* dst is assumed to be initialized. Its contents is freed before - attaching to src. -* this function doesn't need ae_state parameter because it can't fail - (assuming correctly initialized src) -************************************************************************/ -void ae_x_attach_to_matrix(x_matrix *dst, ae_matrix *src) -{ - if( dst->owner==OWN_AE ) - ae_free(dst->x_ptr.p_ptr); - dst->rows = src->rows; - dst->cols = src->cols; - dst->stride = src->stride; - dst->datatype = src->datatype; - dst->x_ptr.p_ptr = &(src->ptr.pp_double[0][0]); - dst->last_action = ACT_NEW_LOCATION; - dst->owner = OWN_CALLER; -} - -/************************************************************************ -This function clears x_vector. It does nothing if vector is not owned by -ALGLIB environment. - -dst vector -************************************************************************/ -void x_vector_clear(x_vector *dst) -{ - if( dst->owner==OWN_AE ) - aligned_free(dst->x_ptr.p_ptr); - dst->x_ptr.p_ptr = NULL; - dst->cnt = 0; -} - -/************************************************************************ -Assertion - -For non-NULL state it allows to gracefully leave ALGLIB session, -removing all frames and deallocating registered dynamic data structure. - -For NULL state it just abort()'s program. - -IMPORTANT: this function ALWAYS evaluates its argument. It can not be - replaced by macro which does nothing. So, you may place actual - function calls at cond, and these will always be performed. -************************************************************************/ -void ae_assert(ae_bool cond, const char *msg, ae_state *state) -{ - if( !cond ) - ae_break(state, ERR_ASSERTION_FAILED, msg); -} - -/************************************************************************ -CPUID - -Returns information about features CPU and compiler support. - -You must tell ALGLIB what CPU family is used by defining AE_CPU symbol -(without this hint zero will be returned). - -Note: results of this function depend on both CPU and compiler; -if compiler doesn't support SSE intrinsics, function won't set -corresponding flag. -************************************************************************/ -static volatile ae_bool _ae_cpuid_initialized = ae_false; -static volatile ae_bool _ae_cpuid_has_sse2 = ae_false; -ae_int_t ae_cpuid() -{ - /* - * to speed up CPU detection we cache results from previous attempts - * there is no synchronization, but it is still thread safe. - * - * thread safety is guaranteed on all modern architectures which - * have following property: simultaneous writes by different cores - * to the same location will be executed in serial manner. - * - */ - ae_int_t result; - - /* - * if not initialized, determine system properties - */ - if( !_ae_cpuid_initialized ) - { - /* - * SSE2 - */ -#if defined(AE_CPU) -#if (AE_CPU==AE_INTEL) && defined(AE_HAS_SSE2_INTRINSICS) -#if AE_COMPILER==AE_MSVC - { - int CPUInfo[4]; - __cpuid(CPUInfo, 1); - if( (CPUInfo[3]&0x04000000)!=0 ) - _ae_cpuid_has_sse2 = ae_true; - } -#elif AE_COMPILER==AE_GNUC - { - ae_int_t a,b,c,d; - __asm__ __volatile__ ("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (1)); - if( (d&0x04000000)!=0 ) - _ae_cpuid_has_sse2 = ae_true; - } -#elif AE_COMPILER==AE_SUNC - { - ae_int_t a,b,c,d; - __asm__ __volatile__ ("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (1)); - if( (d&0x04000000)!=0 ) - _ae_cpuid_has_sse2 = ae_true; - } -#else -#endif -#endif -#endif - /* - * Perform one more CPUID call to generate memory fence - */ -#if AE_CPU==AE_INTEL -#if AE_COMPILER==AE_MSVC - { int CPUInfo[4]; __cpuid(CPUInfo, 1); } -#elif AE_COMPILER==AE_GNUC - { ae_int_t a,b,c,d; __asm__ __volatile__ ("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (1)); } -#elif AE_COMPILER==AE_SUNC - { ae_int_t a,b,c,d; __asm__ __volatile__ ("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (1)); } -#else -#endif -#endif - - /* - * set initialization flag - */ - _ae_cpuid_initialized = ae_true; - } - - /* - * return - */ - result = 0; - if( _ae_cpuid_has_sse2 ) - result = result|CPU_SSE2; - return result; -} - -/************************************************************************ -Activates tracing to file - -IMPORTANT: this function is NOT thread-safe! Calling it from multiple - threads will result in undefined behavior. Calling it when - some thread calls ALGLIB functions may result in undefined - behavior. -************************************************************************/ -void ae_trace_file(const char *tags, const char *filename) -{ - /* - * clean up previous call - */ - if( alglib_fclose_trace ) - { - if( alglib_trace_file!=NULL ) - fclose(alglib_trace_file); - alglib_trace_file = NULL; - alglib_fclose_trace = ae_false; - } - - /* - * store ",tags," to buffer. Leading and trailing commas allow us - * to perform checks for various tags by simply calling strstr(). - */ - memset(alglib_trace_tags, 0, ALGLIB_TRACE_BUFFER_LEN); - strcat(alglib_trace_tags, ","); - strncat(alglib_trace_tags, tags, ALGLIB_TRACE_TAGS_LEN); - strcat(alglib_trace_tags, ","); - for(int i=0; alglib_trace_tags[i]!=0; i++) - alglib_trace_tags[i] = tolower(alglib_trace_tags[i]); - - /* - * set up trace - */ - alglib_trace_type = ALGLIB_TRACE_FILE; - alglib_trace_file = fopen(filename, "ab"); - alglib_fclose_trace = ae_true; -} - -/************************************************************************ -Disables tracing -************************************************************************/ -void ae_trace_disable() -{ - alglib_trace_type = ALGLIB_TRACE_NONE; - if( alglib_fclose_trace ) - fclose(alglib_trace_file); - alglib_trace_file = NULL; - alglib_fclose_trace = ae_false; -} - -/************************************************************************ -Checks whether specific kind of tracing is enabled -************************************************************************/ -ae_bool ae_is_trace_enabled(const char *tag) -{ - char buf[ALGLIB_TRACE_BUFFER_LEN]; - - /* check global trace status */ - if( alglib_trace_type==ALGLIB_TRACE_NONE || alglib_trace_file==NULL ) - return ae_false; - - /* copy tag to buffer, lowercase it */ - memset(buf, 0, ALGLIB_TRACE_BUFFER_LEN); - strcat(buf, ","); - strncat(buf, tag, ALGLIB_TRACE_TAGS_LEN); - strcat(buf, "?"); - for(int i=0; buf[i]!=0; i++) - buf[i] = tolower(buf[i]); - - /* contains tag (followed by comma, which means exact match) */ - buf[strlen(buf)-1] = ','; - if( strstr(alglib_trace_tags,buf)!=NULL ) - return ae_true; - - /* contains tag (followed by dot, which means match with child) */ - buf[strlen(buf)-1] = '.'; - if( strstr(alglib_trace_tags,buf)!=NULL ) - return ae_true; - - /* nothing */ - return ae_false; -} - -void ae_trace(const char * printf_fmt, ...) -{ - /* check global trace status */ - if( alglib_trace_type==ALGLIB_TRACE_FILE && alglib_trace_file!=NULL ) - { - va_list args; - - /* fprintf() */ - va_start(args, printf_fmt); - vfprintf(alglib_trace_file, printf_fmt, args); - va_end(args); - - /* flush output */ - fflush(alglib_trace_file); - } -} - -int ae_tickcount() -{ -#if AE_OS==AE_WINDOWS || defined(AE_DEBUG4WINDOWS) - return (int)GetTickCount(); -#elif AE_OS==AE_POSIX || defined(AE_DEBUG4POSIX) - struct timeval now; - ae_int64_t r, v; - gettimeofday(&now, NULL); - v = now.tv_sec; - r = v*1000; - v = now.tv_usec/1000; - r = r+v; - return r; - /*struct timespec now; - if (clock_gettime(CLOCK_MONOTONIC, &now) ) - return 0; - return now.tv_sec * 1000.0 + now.tv_nsec / 1000000.0;*/ -#else - return 0; -#endif -} - - -/************************************************************************ -Real math functions -************************************************************************/ -ae_bool ae_fp_eq(double v1, double v2) -{ - /* IEEE-strict floating point comparison */ - volatile double x = v1; - volatile double y = v2; - return x==y; -} - -ae_bool ae_fp_neq(double v1, double v2) -{ - /* IEEE-strict floating point comparison */ - return !ae_fp_eq(v1,v2); -} - -ae_bool ae_fp_less(double v1, double v2) -{ - /* IEEE-strict floating point comparison */ - volatile double x = v1; - volatile double y = v2; - return xy; -} - -ae_bool ae_fp_greater_eq(double v1, double v2) -{ - /* IEEE-strict floating point comparison */ - volatile double x = v1; - volatile double y = v2; - return x>=y; -} - -ae_bool ae_isfinite_stateless(double x, ae_int_t endianness) -{ - union _u - { - double a; - ae_int32_t p[2]; - } u; - ae_int32_t high; - u.a = x; - if( endianness==AE_LITTLE_ENDIAN ) - high = u.p[1]; - else - high = u.p[0]; - return (high & (ae_int32_t)0x7FF00000)!=(ae_int32_t)0x7FF00000; -} - -ae_bool ae_isnan_stateless(double x, ae_int_t endianness) -{ - union _u - { - double a; - ae_int32_t p[2]; - } u; - ae_int32_t high, low; - u.a = x; - if( endianness==AE_LITTLE_ENDIAN ) - { - high = u.p[1]; - low = u.p[0]; - } - else - { - high = u.p[0]; - low = u.p[1]; - } - return ((high &0x7FF00000)==0x7FF00000) && (((high &0x000FFFFF)!=0) || (low!=0)); -} - -ae_bool ae_isinf_stateless(double x, ae_int_t endianness) -{ - union _u - { - double a; - ae_int32_t p[2]; - } u; - ae_int32_t high, low; - u.a = x; - if( endianness==AE_LITTLE_ENDIAN ) - { - high = u.p[1]; - low = u.p[0]; - } - else - { - high = u.p[0]; - low = u.p[1]; - } - - /* 31 least significant bits of high are compared */ - return ((high&0x7FFFFFFF)==0x7FF00000) && (low==0); -} - -ae_bool ae_isposinf_stateless(double x, ae_int_t endianness) -{ - union _u - { - double a; - ae_int32_t p[2]; - } u; - ae_int32_t high, low; - u.a = x; - if( endianness==AE_LITTLE_ENDIAN ) - { - high = u.p[1]; - low = u.p[0]; - } - else - { - high = u.p[0]; - low = u.p[1]; - } - - /* all 32 bits of high are compared */ - return (high==(ae_int32_t)0x7FF00000) && (low==0); -} - -ae_bool ae_isneginf_stateless(double x, ae_int_t endianness) -{ - union _u - { - double a; - ae_int32_t p[2]; - } u; - ae_int32_t high, low; - u.a = x; - if( endianness==AE_LITTLE_ENDIAN ) - { - high = u.p[1]; - low = u.p[0]; - } - else - { - high = u.p[0]; - low = u.p[1]; - } - - /* this code is a bit tricky to avoid comparison of high with 0xFFF00000, which may be unsafe with some buggy compilers */ - return ((high&0x7FFFFFFF)==0x7FF00000) && (high!=(ae_int32_t)0x7FF00000) && (low==0); -} - -ae_int_t ae_get_endianness() -{ - union - { - double a; - ae_int32_t p[2]; - } u; - - /* - * determine endianness - * two types are supported: big-endian and little-endian. - * mixed-endian hardware is NOT supported. - * - * 1983 is used as magic number because its non-periodic double - * representation allow us to easily distinguish between upper - * and lower halfs and to detect mixed endian hardware. - * - */ - u.a = 1.0/1983.0; - if( u.p[1]==(ae_int32_t)0x3f408642 ) - return AE_LITTLE_ENDIAN; - if( u.p[0]==(ae_int32_t)0x3f408642 ) - return AE_BIG_ENDIAN; - return AE_MIXED_ENDIAN; -} - -ae_bool ae_isfinite(double x,ae_state *state) -{ - return ae_isfinite_stateless(x, state->endianness); -} - -ae_bool ae_isnan(double x, ae_state *state) -{ - return ae_isnan_stateless(x, state->endianness); -} - -ae_bool ae_isinf(double x, ae_state *state) -{ - return ae_isinf_stateless(x, state->endianness); -} - -ae_bool ae_isposinf(double x,ae_state *state) -{ - return ae_isposinf_stateless(x, state->endianness); -} - -ae_bool ae_isneginf(double x,ae_state *state) -{ - return ae_isneginf_stateless(x, state->endianness); -} - -double ae_fabs(double x, ae_state *state) -{ - return fabs(x); -} - -ae_int_t ae_iabs(ae_int_t x, ae_state *state) -{ - return x>=0 ? x : -x; -} - -double ae_sqr(double x, ae_state *state) -{ - return x*x; -} - -double ae_sqrt(double x, ae_state *state) -{ - return sqrt(x); -} - -ae_int_t ae_sign(double x, ae_state *state) -{ - if( x>0 ) return 1; - if( x<0 ) return -1; - return 0; -} - -ae_int_t ae_round(double x, ae_state *state) -{ - return (ae_int_t)(ae_ifloor(x+0.5,state)); -} - -ae_int_t ae_trunc(double x, ae_state *state) -{ - return (ae_int_t)(x>0 ? ae_ifloor(x,state) : ae_iceil(x,state)); -} - -ae_int_t ae_ifloor(double x, ae_state *state) -{ - return (ae_int_t)(floor(x)); -} - -ae_int_t ae_iceil(double x, ae_state *state) -{ - return (ae_int_t)(ceil(x)); -} - -ae_int_t ae_maxint(ae_int_t m1, ae_int_t m2, ae_state *state) -{ - return m1>m2 ? m1 : m2; -} - -ae_int_t ae_minint(ae_int_t m1, ae_int_t m2, ae_state *state) -{ - return m1>m2 ? m2 : m1; -} - -double ae_maxreal(double m1, double m2, ae_state *state) -{ - return m1>m2 ? m1 : m2; -} - -double ae_minreal(double m1, double m2, ae_state *state) -{ - return m1>m2 ? m2 : m1; -} - -double ae_randomreal(ae_state *state) -{ - int i1 = rand(); - int i2 = rand(); - double mx = (double)(RAND_MAX)+1.0; - volatile double tmp0 = i2/mx; - volatile double tmp1 = i1+tmp0; - return tmp1/mx; -} - -ae_int_t ae_randominteger(ae_int_t maxv, ae_state *state) -{ - return rand()%maxv; -} - -double ae_sin(double x, ae_state *state) -{ - return sin(x); -} - -double ae_cos(double x, ae_state *state) -{ - return cos(x); -} - -double ae_tan(double x, ae_state *state) -{ - return tan(x); -} - -double ae_sinh(double x, ae_state *state) -{ - return sinh(x); -} - -double ae_cosh(double x, ae_state *state) -{ - return cosh(x); -} -double ae_tanh(double x, ae_state *state) -{ - return tanh(x); -} - -double ae_asin(double x, ae_state *state) -{ - return asin(x); -} - -double ae_acos(double x, ae_state *state) -{ - return acos(x); -} - -double ae_atan(double x, ae_state *state) -{ - return atan(x); -} - -double ae_atan2(double y, double x, ae_state *state) -{ - return atan2(y,x); -} - -double ae_log(double x, ae_state *state) -{ - return log(x); -} - -double ae_pow(double x, double y, ae_state *state) -{ - return pow(x,y); -} - -double ae_exp(double x, ae_state *state) -{ - return exp(x); -} - -/************************************************************************ -Symmetric/Hermitian properties: check and force -************************************************************************/ -static void x_split_length(ae_int_t n, ae_int_t nb, ae_int_t* n1, ae_int_t* n2) -{ - ae_int_t r; - if( n<=nb ) - { - *n1 = n; - *n2 = 0; - } - else - { - if( n%nb!=0 ) - { - *n2 = n%nb; - *n1 = n-(*n2); - } - else - { - *n2 = n/2; - *n1 = n-(*n2); - if( *n1%nb==0 ) - { - return; - } - r = nb-*n1%nb; - *n1 = *n1+r; - *n2 = *n2-r; - } - } -} -static double x_safepythag2(double x, double y) -{ - double w; - double xabs; - double yabs; - double z; - xabs = fabs(x); - yabs = fabs(y); - w = xabs>yabs ? xabs : yabs; - z = xabsx_nb || len1>x_nb ) - { - ae_int_t n1, n2; - if( len0>len1 ) - { - x_split_length(len0, x_nb, &n1, &n2); - is_symmetric_rec_off_stat(a, offset0, offset1, n1, len1, nonfinite, mx, err, _state); - is_symmetric_rec_off_stat(a, offset0+n1, offset1, n2, len1, nonfinite, mx, err, _state); - } - else - { - x_split_length(len1, x_nb, &n1, &n2); - is_symmetric_rec_off_stat(a, offset0, offset1, len0, n1, nonfinite, mx, err, _state); - is_symmetric_rec_off_stat(a, offset0, offset1+n1, len0, n2, nonfinite, mx, err, _state); - } - return; - } - else - { - /* base case */ - double *p1, *p2, *prow, *pcol; - double v; - ae_int_t i, j; - - p1 = (double*)(a->x_ptr.p_ptr)+offset0*a->stride+offset1; - p2 = (double*)(a->x_ptr.p_ptr)+offset1*a->stride+offset0; - for(i=0; istride; - for(j=0; jv ? *mx : v; - v = fabs(*prow); - *mx = *mx>v ? *mx : v; - v = fabs(*pcol-*prow); - *err = *err>v ? *err : v; - } - pcol += a->stride; - prow++; - } - } - } -} -/* - * this function checks that diagonal block A0 is symmetric. - * Block A0 is specified by its offset and size. - * - * [ . ] - * [ A0 ] - * A = [ . ] - * [ . ] - * - * this subroutine updates current values of: - * a) mx maximum value of A[i,j] found so far - * b) err componentwise difference between A0 and A0^T - * - */ -static void is_symmetric_rec_diag_stat(x_matrix *a, ae_int_t offset, ae_int_t len, ae_bool *nonfinite, double *mx, double *err, ae_state *_state) -{ - double *p, *prow, *pcol; - double v; - ae_int_t i, j; - - /* try to split problem into two smaller ones */ - if( len>x_nb ) - { - ae_int_t n1, n2; - x_split_length(len, x_nb, &n1, &n2); - is_symmetric_rec_diag_stat(a, offset, n1, nonfinite, mx, err, _state); - is_symmetric_rec_diag_stat(a, offset+n1, n2, nonfinite, mx, err, _state); - is_symmetric_rec_off_stat(a, offset+n1, offset, n2, n1, nonfinite, mx, err, _state); - return; - } - - /* base case */ - p = (double*)(a->x_ptr.p_ptr)+offset*a->stride+offset; - for(i=0; istride; - for(j=0; jstride,prow++) - { - if( !ae_isfinite(*pcol,_state) || !ae_isfinite(*prow,_state) ) - { - *nonfinite = ae_true; - } - else - { - v = fabs(*pcol); - *mx = *mx>v ? *mx : v; - v = fabs(*prow); - *mx = *mx>v ? *mx : v; - v = fabs(*pcol-*prow); - *err = *err>v ? *err : v; - } - } - v = fabs(p[i+i*a->stride]); - *mx = *mx>v ? *mx : v; - } -} -/* - * this function checks difference between offdiagonal blocks BL and BU - * (see below). Block BL is specified by offsets (offset0,offset1) and - * sizes (len0,len1). - * - * [ . ] - * [ A0 BU ] - * A = [ BL A1 ] - * [ . ] - * - * this subroutine updates current values of: - * a) mx maximum value of A[i,j] found so far - * b) err componentwise difference between elements of BL and BU^H - * - */ -static void is_hermitian_rec_off_stat(x_matrix *a, ae_int_t offset0, ae_int_t offset1, ae_int_t len0, ae_int_t len1, ae_bool *nonfinite, double *mx, double *err, ae_state *_state) -{ - /* try to split problem into two smaller ones */ - if( len0>x_nb || len1>x_nb ) - { - ae_int_t n1, n2; - if( len0>len1 ) - { - x_split_length(len0, x_nb, &n1, &n2); - is_hermitian_rec_off_stat(a, offset0, offset1, n1, len1, nonfinite, mx, err, _state); - is_hermitian_rec_off_stat(a, offset0+n1, offset1, n2, len1, nonfinite, mx, err, _state); - } - else - { - x_split_length(len1, x_nb, &n1, &n2); - is_hermitian_rec_off_stat(a, offset0, offset1, len0, n1, nonfinite, mx, err, _state); - is_hermitian_rec_off_stat(a, offset0, offset1+n1, len0, n2, nonfinite, mx, err, _state); - } - return; - } - else - { - /* base case */ - ae_complex *p1, *p2, *prow, *pcol; - double v; - ae_int_t i, j; - - p1 = (ae_complex*)(a->x_ptr.p_ptr)+offset0*a->stride+offset1; - p2 = (ae_complex*)(a->x_ptr.p_ptr)+offset1*a->stride+offset0; - for(i=0; istride; - for(j=0; jx, _state) || !ae_isfinite(pcol->y, _state) || !ae_isfinite(prow->x, _state) || !ae_isfinite(prow->y, _state) ) - { - *nonfinite = ae_true; - } - else - { - v = x_safepythag2(pcol->x, pcol->y); - *mx = *mx>v ? *mx : v; - v = x_safepythag2(prow->x, prow->y); - *mx = *mx>v ? *mx : v; - v = x_safepythag2(pcol->x-prow->x, pcol->y+prow->y); - *err = *err>v ? *err : v; - } - pcol += a->stride; - prow++; - } - } - } -} -/* - * this function checks that diagonal block A0 is Hermitian. - * Block A0 is specified by its offset and size. - * - * [ . ] - * [ A0 ] - * A = [ . ] - * [ . ] - * - * this subroutine updates current values of: - * a) mx maximum value of A[i,j] found so far - * b) err componentwise difference between A0 and A0^H - * - */ -static void is_hermitian_rec_diag_stat(x_matrix *a, ae_int_t offset, ae_int_t len, ae_bool *nonfinite, double *mx, double *err, ae_state *_state) -{ - ae_complex *p, *prow, *pcol; - double v; - ae_int_t i, j; - - /* try to split problem into two smaller ones */ - if( len>x_nb ) - { - ae_int_t n1, n2; - x_split_length(len, x_nb, &n1, &n2); - is_hermitian_rec_diag_stat(a, offset, n1, nonfinite, mx, err, _state); - is_hermitian_rec_diag_stat(a, offset+n1, n2, nonfinite, mx, err, _state); - is_hermitian_rec_off_stat(a, offset+n1, offset, n2, n1, nonfinite, mx, err, _state); - return; - } - - /* base case */ - p = (ae_complex*)(a->x_ptr.p_ptr)+offset*a->stride+offset; - for(i=0; istride; - for(j=0; jstride,prow++) - { - if( !ae_isfinite(pcol->x, _state) || !ae_isfinite(pcol->y, _state) || !ae_isfinite(prow->x, _state) || !ae_isfinite(prow->y, _state) ) - { - *nonfinite = ae_true; - } - else - { - v = x_safepythag2(pcol->x, pcol->y); - *mx = *mx>v ? *mx : v; - v = x_safepythag2(prow->x, prow->y); - *mx = *mx>v ? *mx : v; - v = x_safepythag2(pcol->x-prow->x, pcol->y+prow->y); - *err = *err>v ? *err : v; - } - } - if( !ae_isfinite(p[i+i*a->stride].x, _state) || !ae_isfinite(p[i+i*a->stride].y, _state) ) - { - *nonfinite = ae_true; - } - else - { - v = fabs(p[i+i*a->stride].x); - *mx = *mx>v ? *mx : v; - v = fabs(p[i+i*a->stride].y); - *err = *err>v ? *err : v; - } - } -} -/* - * this function copies offdiagonal block BL to its symmetric counterpart - * BU (see below). Block BL is specified by offsets (offset0,offset1) - * and sizes (len0,len1). - * - * [ . ] - * [ A0 BU ] - * A = [ BL A1 ] - * [ . ] - * - */ -static void force_symmetric_rec_off_stat(x_matrix *a, ae_int_t offset0, ae_int_t offset1, ae_int_t len0, ae_int_t len1) -{ - /* try to split problem into two smaller ones */ - if( len0>x_nb || len1>x_nb ) - { - ae_int_t n1, n2; - if( len0>len1 ) - { - x_split_length(len0, x_nb, &n1, &n2); - force_symmetric_rec_off_stat(a, offset0, offset1, n1, len1); - force_symmetric_rec_off_stat(a, offset0+n1, offset1, n2, len1); - } - else - { - x_split_length(len1, x_nb, &n1, &n2); - force_symmetric_rec_off_stat(a, offset0, offset1, len0, n1); - force_symmetric_rec_off_stat(a, offset0, offset1+n1, len0, n2); - } - return; - } - else - { - /* base case */ - double *p1, *p2, *prow, *pcol; - ae_int_t i, j; - - p1 = (double*)(a->x_ptr.p_ptr)+offset0*a->stride+offset1; - p2 = (double*)(a->x_ptr.p_ptr)+offset1*a->stride+offset0; - for(i=0; istride; - for(j=0; jstride; - prow++; - } - } - } -} -/* - * this function copies lower part of diagonal block A0 to its upper part - * Block is specified by offset and size. - * - * [ . ] - * [ A0 ] - * A = [ . ] - * [ . ] - * - */ -static void force_symmetric_rec_diag_stat(x_matrix *a, ae_int_t offset, ae_int_t len) -{ - double *p, *prow, *pcol; - ae_int_t i, j; - - /* try to split problem into two smaller ones */ - if( len>x_nb ) - { - ae_int_t n1, n2; - x_split_length(len, x_nb, &n1, &n2); - force_symmetric_rec_diag_stat(a, offset, n1); - force_symmetric_rec_diag_stat(a, offset+n1, n2); - force_symmetric_rec_off_stat(a, offset+n1, offset, n2, n1); - return; - } - - /* base case */ - p = (double*)(a->x_ptr.p_ptr)+offset*a->stride+offset; - for(i=0; istride; - for(j=0; jstride,prow++) - *pcol = *prow; - } -} -/* - * this function copies Hermitian transpose of offdiagonal block BL to - * its symmetric counterpart BU (see below). Block BL is specified by - * offsets (offset0,offset1) and sizes (len0,len1). - * - * [ . ] - * [ A0 BU ] - * A = [ BL A1 ] - * [ . ] - */ -static void force_hermitian_rec_off_stat(x_matrix *a, ae_int_t offset0, ae_int_t offset1, ae_int_t len0, ae_int_t len1) -{ - /* try to split problem into two smaller ones */ - if( len0>x_nb || len1>x_nb ) - { - ae_int_t n1, n2; - if( len0>len1 ) - { - x_split_length(len0, x_nb, &n1, &n2); - force_hermitian_rec_off_stat(a, offset0, offset1, n1, len1); - force_hermitian_rec_off_stat(a, offset0+n1, offset1, n2, len1); - } - else - { - x_split_length(len1, x_nb, &n1, &n2); - force_hermitian_rec_off_stat(a, offset0, offset1, len0, n1); - force_hermitian_rec_off_stat(a, offset0, offset1+n1, len0, n2); - } - return; - } - else - { - /* base case */ - ae_complex *p1, *p2, *prow, *pcol; - ae_int_t i, j; - - p1 = (ae_complex*)(a->x_ptr.p_ptr)+offset0*a->stride+offset1; - p2 = (ae_complex*)(a->x_ptr.p_ptr)+offset1*a->stride+offset0; - for(i=0; istride; - for(j=0; jstride; - prow++; - } - } - } -} -/* - * this function copies Hermitian transpose of lower part of - * diagonal block A0 to its upper part Block is specified by offset and size. - * - * [ . ] - * [ A0 ] - * A = [ . ] - * [ . ] - * - */ -static void force_hermitian_rec_diag_stat(x_matrix *a, ae_int_t offset, ae_int_t len) -{ - ae_complex *p, *prow, *pcol; - ae_int_t i, j; - - /* try to split problem into two smaller ones */ - if( len>x_nb ) - { - ae_int_t n1, n2; - x_split_length(len, x_nb, &n1, &n2); - force_hermitian_rec_diag_stat(a, offset, n1); - force_hermitian_rec_diag_stat(a, offset+n1, n2); - force_hermitian_rec_off_stat(a, offset+n1, offset, n2, n1); - return; - } - - /* base case */ - p = (ae_complex*)(a->x_ptr.p_ptr)+offset*a->stride+offset; - for(i=0; istride; - for(j=0; jstride,prow++) - *pcol = *prow; - } -} -ae_bool x_is_symmetric(x_matrix *a) -{ - double mx, err; - ae_bool nonfinite; - ae_state _alglib_env_state; - if( a->datatype!=DT_REAL ) - return ae_false; - if( a->cols!=a->rows ) - return ae_false; - if( a->cols==0 || a->rows==0 ) - return ae_true; - ae_state_init(&_alglib_env_state); - mx = 0; - err = 0; - nonfinite = ae_false; - is_symmetric_rec_diag_stat(a, 0, (ae_int_t)a->rows, &nonfinite, &mx, &err, &_alglib_env_state); - if( nonfinite ) - return ae_false; - if( mx==0 ) - return ae_true; - return err/mx<=1.0E-14; -} -ae_bool x_is_hermitian(x_matrix *a) -{ - double mx, err; - ae_bool nonfinite; - ae_state _alglib_env_state; - if( a->datatype!=DT_COMPLEX ) - return ae_false; - if( a->cols!=a->rows ) - return ae_false; - if( a->cols==0 || a->rows==0 ) - return ae_true; - ae_state_init(&_alglib_env_state); - mx = 0; - err = 0; - nonfinite = ae_false; - is_hermitian_rec_diag_stat(a, 0, (ae_int_t)a->rows, &nonfinite, &mx, &err, &_alglib_env_state); - if( nonfinite ) - return ae_false; - if( mx==0 ) - return ae_true; - return err/mx<=1.0E-14; -} -ae_bool x_force_symmetric(x_matrix *a) -{ - if( a->datatype!=DT_REAL ) - return ae_false; - if( a->cols!=a->rows ) - return ae_false; - if( a->cols==0 || a->rows==0 ) - return ae_true; - force_symmetric_rec_diag_stat(a, 0, (ae_int_t)a->rows); - return ae_true; -} -ae_bool x_force_hermitian(x_matrix *a) -{ - if( a->datatype!=DT_COMPLEX ) - return ae_false; - if( a->cols!=a->rows ) - return ae_false; - if( a->cols==0 || a->rows==0 ) - return ae_true; - force_hermitian_rec_diag_stat(a, 0, (ae_int_t)a->rows); - return ae_true; -} - -ae_bool ae_is_symmetric(ae_matrix *a) -{ - x_matrix x; - x.owner = OWN_CALLER; - ae_x_attach_to_matrix(&x, a); - return x_is_symmetric(&x); -} - -ae_bool ae_is_hermitian(ae_matrix *a) -{ - x_matrix x; - x.owner = OWN_CALLER; - ae_x_attach_to_matrix(&x, a); - return x_is_hermitian(&x); -} - -ae_bool ae_force_symmetric(ae_matrix *a) -{ - x_matrix x; - x.owner = OWN_CALLER; - ae_x_attach_to_matrix(&x, a); - return x_force_symmetric(&x); -} - -ae_bool ae_force_hermitian(ae_matrix *a) -{ - x_matrix x; - x.owner = OWN_CALLER; - ae_x_attach_to_matrix(&x, a); - return x_force_hermitian(&x); -} - -/************************************************************************ -This function converts six-bit value (from 0 to 63) to character (only -digits, lowercase and uppercase letters, minus and underscore are used). - -If v is negative or greater than 63, this function returns '?'. -************************************************************************/ -static char _sixbits2char_tbl[64] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', - 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', - 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', - 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', - 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', - 'u', 'v', 'w', 'x', 'y', 'z', '-', '_' }; - -char ae_sixbits2char(ae_int_t v) -{ - - if( v<0 || v>63 ) - return '?'; - return _sixbits2char_tbl[v]; - - /* v is correct, process it */ - /*if( v<10 ) - return '0'+v; - v -= 10; - if( v<26 ) - return 'A'+v; - v -= 26; - if( v<26 ) - return 'a'+v; - v -= 26; - return v==0 ? '-' : '_';*/ -} - -/************************************************************************ -This function converts character to six-bit value (from 0 to 63). - -This function is inverse of ae_sixbits2char() -If c is not correct character, this function returns -1. -************************************************************************/ -static ae_int_t _ae_char2sixbits_tbl[] = { - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 62, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, -1, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, -1, -1, -1, -1, 63, - -1, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, -1, -1, -1, -1, -1 }; -ae_int_t ae_char2sixbits(char c) -{ - return (c>=0 && c<127) ? _ae_char2sixbits_tbl[(int)c] : -1; -} - -/************************************************************************ -This function converts three bytes (24 bits) to four six-bit values -(24 bits again). - -src pointer to three bytes -dst pointer to four ints -************************************************************************/ -void ae_threebytes2foursixbits(const unsigned char *src, ae_int_t *dst) -{ - dst[0] = src[0] & 0x3F; - dst[1] = (src[0]>>6) | ((src[1]&0x0F)<<2); - dst[2] = (src[1]>>4) | ((src[2]&0x03)<<4); - dst[3] = src[2]>>2; -} - -/************************************************************************ -This function converts four six-bit values (24 bits) to three bytes -(24 bits again). - -src pointer to four ints -dst pointer to three bytes -************************************************************************/ -void ae_foursixbits2threebytes(const ae_int_t *src, unsigned char *dst) -{ - dst[0] = (unsigned char)( src[0] | ((src[1]&0x03)<<6)); - dst[1] = (unsigned char)((src[1]>>2) | ((src[2]&0x0F)<<4)); - dst[2] = (unsigned char)((src[2]>>4) | (src[3]<<2)); -} - -/************************************************************************ -This function serializes boolean value into buffer - -v boolean value to be serialized -buf buffer, at least 12 characters wide - (11 chars for value, one for trailing zero) -state ALGLIB environment state -************************************************************************/ -void ae_bool2str(ae_bool v, char *buf, ae_state *state) -{ - char c = v ? '1' : '0'; - ae_int_t i; - for(i=0; iendianness==AE_BIG_ENDIAN ) - { - for(i=0; i<(ae_int_t)(sizeof(ae_int_t)/2); i++) - { - unsigned char tc; - tc = u.bytes[i]; - u.bytes[i] = u.bytes[sizeof(ae_int_t)-1-i]; - u.bytes[sizeof(ae_int_t)-1-i] = tc; - } - } - - /* - * convert to six-bit representation, output - * - * NOTE: last 12th element of sixbits is always zero, we do not output it - */ - ae_threebytes2foursixbits(u.bytes+0, sixbits+0); - ae_threebytes2foursixbits(u.bytes+3, sixbits+4); - ae_threebytes2foursixbits(u.bytes+6, sixbits+8); - for(i=0; iendianness==AE_BIG_ENDIAN ) - { - for(i=0; i<(ae_int_t)(sizeof(ae_int_t)/2); i++) - { - unsigned char tc; - tc = bytes[i]; - bytes[i] = bytes[sizeof(ae_int_t)-1-i]; - bytes[sizeof(ae_int_t)-1-i] = tc; - } - } - - /* - * convert to six-bit representation, output - * - * NOTE: last 12th element of sixbits is always zero, we do not output it - */ - ae_threebytes2foursixbits(bytes+0, sixbits+0); - ae_threebytes2foursixbits(bytes+3, sixbits+4); - ae_threebytes2foursixbits(bytes+6, sixbits+8); - for(i=0; i=AE_SER_ENTRY_LENGTH ) - ae_break(state, ERR_ASSERTION_FAILED, emsg); - sixbits[sixbitsread] = d; - sixbitsread++; - buf++; - } - *pasttheend = buf; - if( sixbitsread==0 ) - ae_break(state, ERR_ASSERTION_FAILED, emsg); - for(i=sixbitsread; i<12; i++) - sixbits[i] = 0; - ae_foursixbits2threebytes(sixbits+0, u.bytes+0); - ae_foursixbits2threebytes(sixbits+4, u.bytes+3); - ae_foursixbits2threebytes(sixbits+8, u.bytes+6); - if( state->endianness==AE_BIG_ENDIAN ) - { - for(i=0; i<(ae_int_t)(sizeof(ae_int_t)/2); i++) - { - unsigned char tc; - tc = u.bytes[i]; - u.bytes[i] = u.bytes[sizeof(ae_int_t)-1-i]; - u.bytes[sizeof(ae_int_t)-1-i] = tc; - } - } - return u.ival; -} - -/************************************************************************ -This function unserializes 64-bit integer value from string - -buf buffer which contains value; leading spaces/tabs/newlines are - ignored, traling spaces/tabs/newlines are treated as end of - the boolean value. -state ALGLIB environment state - -This function raises an error in case unexpected symbol is found -************************************************************************/ -ae_int64_t ae_str2int64(const char *buf, ae_state *state, const char **pasttheend) -{ - const char *emsg = "ALGLIB: unable to read integer value from stream"; - ae_int_t sixbits[12]; - ae_int_t sixbitsread, i; - unsigned char bytes[9]; - ae_int64_t result; - - /* - * 1. skip leading spaces - * 2. read and decode six-bit digits - * 3. set trailing digits to zeros - * 4. convert to little endian 64-bit integer representation - * 5. convert to big endian representation, if needed - */ - while( *buf==' ' || *buf=='\t' || *buf=='\n' || *buf=='\r' ) - buf++; - sixbitsread = 0; - while( *buf!=' ' && *buf!='\t' && *buf!='\n' && *buf!='\r' && *buf!=0 ) - { - ae_int_t d; - d = ae_char2sixbits(*buf); - if( d<0 || sixbitsread>=AE_SER_ENTRY_LENGTH ) - ae_break(state, ERR_ASSERTION_FAILED, emsg); - sixbits[sixbitsread] = d; - sixbitsread++; - buf++; - } - *pasttheend = buf; - if( sixbitsread==0 ) - ae_break(state, ERR_ASSERTION_FAILED, emsg); - for(i=sixbitsread; i<12; i++) - sixbits[i] = 0; - ae_foursixbits2threebytes(sixbits+0, bytes+0); - ae_foursixbits2threebytes(sixbits+4, bytes+3); - ae_foursixbits2threebytes(sixbits+8, bytes+6); - if( state->endianness==AE_BIG_ENDIAN ) - { - for(i=0; i<(ae_int_t)(sizeof(ae_int_t)/2); i++) - { - unsigned char tc; - tc = bytes[i]; - bytes[i] = bytes[sizeof(ae_int_t)-1-i]; - bytes[sizeof(ae_int_t)-1-i] = tc; - } - } - memmove(&result, bytes, sizeof(result)); - return result; -} - - -/************************************************************************ -This function serializes double value into buffer - -v double value to be serialized -buf buffer, at least 12 characters wide - (11 chars for value, one for trailing zero) -state ALGLIB environment state -************************************************************************/ -void ae_double2str(double v, char *buf, ae_state *state) -{ - union _u - { - double dval; - unsigned char bytes[9]; - } u; - ae_int_t i; - ae_int_t sixbits[12]; - - /* - * handle special quantities - */ - if( ae_isnan(v, state) ) - { - const char *s = ".nan_______"; - memmove(buf, s, strlen(s)+1); - return; - } - if( ae_isposinf(v, state) ) - { - const char *s = ".posinf____"; - memmove(buf, s, strlen(s)+1); - return; - } - if( ae_isneginf(v, state) ) - { - const char *s = ".neginf____"; - memmove(buf, s, strlen(s)+1); - return; - } - - /* - * process general case: - * 1. copy v to array of chars - * 2. set 9th byte of u.bytes to zero in order to - * simplify conversion to six-bit representation - * 3. convert to little endian (if needed) - * 4. convert to six-bit representation - * (last 12th element of sixbits is always zero, we do not output it) - */ - u.dval = v; - u.bytes[8] = 0; - if( state->endianness==AE_BIG_ENDIAN ) - { - for(i=0; i<(ae_int_t)(sizeof(double)/2); i++) - { - unsigned char tc; - tc = u.bytes[i]; - u.bytes[i] = u.bytes[sizeof(double)-1-i]; - u.bytes[sizeof(double)-1-i] = tc; - } - } - ae_threebytes2foursixbits(u.bytes+0, sixbits+0); - ae_threebytes2foursixbits(u.bytes+3, sixbits+4); - ae_threebytes2foursixbits(u.bytes+6, sixbits+8); - for(i=0; iv_nan; - } - if( strncmp(buf, s_posinf, strlen(s_posinf))==0 ) - { - *pasttheend = buf+strlen(s_posinf); - return state->v_posinf; - } - if( strncmp(buf, s_neginf, strlen(s_neginf))==0 ) - { - *pasttheend = buf+strlen(s_neginf); - return state->v_neginf; - } - ae_break(state, ERR_ASSERTION_FAILED, emsg); - } - - /* - * General case: - * 1. read and decode six-bit digits - * 2. check that all 11 digits were read - * 3. set last 12th digit to zero (needed for simplicity of conversion) - * 4. convert to 8 bytes - * 5. convert to big endian representation, if needed - */ - sixbitsread = 0; - while( *buf!=' ' && *buf!='\t' && *buf!='\n' && *buf!='\r' && *buf!=0 ) - { - ae_int_t d; - d = ae_char2sixbits(*buf); - if( d<0 || sixbitsread>=AE_SER_ENTRY_LENGTH ) - ae_break(state, ERR_ASSERTION_FAILED, emsg); - sixbits[sixbitsread] = d; - sixbitsread++; - buf++; - } - *pasttheend = buf; - if( sixbitsread!=AE_SER_ENTRY_LENGTH ) - ae_break(state, ERR_ASSERTION_FAILED, emsg); - sixbits[AE_SER_ENTRY_LENGTH] = 0; - ae_foursixbits2threebytes(sixbits+0, u.bytes+0); - ae_foursixbits2threebytes(sixbits+4, u.bytes+3); - ae_foursixbits2threebytes(sixbits+8, u.bytes+6); - if( state->endianness==AE_BIG_ENDIAN ) - { - for(i=0; i<(ae_int_t)(sizeof(double)/2); i++) - { - unsigned char tc; - tc = u.bytes[i]; - u.bytes[i] = u.bytes[sizeof(double)-1-i]; - u.bytes[sizeof(double)-1-i] = tc; - } - } - return u.dval; -} - - -/************************************************************************ -This function performs given number of spin-wait iterations -************************************************************************/ -void ae_spin_wait(ae_int_t cnt) -{ - /* - * these strange operations with ae_never_change_it are necessary to - * prevent compiler optimization of the loop. - */ - volatile ae_int_t i; - - /* very unlikely because no one will wait for such amount of cycles */ - if( cnt>0x12345678 ) - ae_never_change_it = cnt%10; - - /* spin wait, test condition which will never be true */ - for(i=0; i0 ) - ae_never_change_it--; -} - - -/************************************************************************ -This function causes the calling thread to relinquish the CPU. The thread -is moved to the end of the queue and some other thread gets to run. - -NOTE: this function should NOT be called when AE_OS is AE_UNKNOWN - the - whole program will be abnormally terminated. -************************************************************************/ -void ae_yield() -{ -#if AE_OS==AE_WINDOWS - if( !SwitchToThread() ) - Sleep(0); -#elif AE_OS==AE_POSIX - sched_yield(); -#else - abort(); -#endif -} - -/************************************************************************ -This function initializes _lock structure which is internally used by -ae_lock high-level structure. - -_lock structure is statically allocated, no malloc() calls is performed -during its allocation. However, you have to call _ae_free_lock_raw() in -order to deallocate this lock properly. -************************************************************************/ -void _ae_init_lock_raw(_lock *p) -{ -#if AE_OS==AE_WINDOWS - p->p_lock = (ae_int_t*)ae_align((void*)(&p->buf),AE_LOCK_ALIGNMENT); - p->p_lock[0] = 0; -#elif AE_OS==AE_POSIX - pthread_mutex_init(&p->mutex, NULL); -#else - p->is_locked = ae_false; -#endif -} - - -/************************************************************************ -This function acquires _lock structure. - -It is low-level workhorse utilized by ae_acquire_lock(). -************************************************************************/ -void _ae_acquire_lock_raw(_lock *p) -{ -#if AE_OS==AE_WINDOWS - ae_int_t cnt = 0; -#ifdef AE_SMP_DEBUGCOUNTERS - InterlockedIncrement((LONG volatile *)&_ae_dbg_lock_acquisitions); -#endif - for(;;) - { - if( InterlockedCompareExchange((LONG volatile *)p->p_lock, 1, 0)==0 ) - return; - ae_spin_wait(AE_LOCK_CYCLES); -#ifdef AE_SMP_DEBUGCOUNTERS - InterlockedIncrement((LONG volatile *)&_ae_dbg_lock_spinwaits); -#endif - cnt++; - if( cnt%AE_LOCK_TESTS_BEFORE_YIELD==0 ) - { -#ifdef AE_SMP_DEBUGCOUNTERS - InterlockedIncrement((LONG volatile *)&_ae_dbg_lock_yields); -#endif - ae_yield(); - } - } -#elif AE_OS==AE_POSIX - ae_int_t cnt = 0; - for(;;) - { - if( pthread_mutex_trylock(&p->mutex)==0 ) - return; - ae_spin_wait(AE_LOCK_CYCLES); - cnt++; - if( cnt%AE_LOCK_TESTS_BEFORE_YIELD==0 ) - ae_yield(); - } - ; -#else - AE_CRITICAL_ASSERT(!p->is_locked); - p->is_locked = ae_true; -#endif -} - - -/************************************************************************ -This function releases _lock structure. - -It is low-level lock function which is used by ae_release_lock. -************************************************************************/ -void _ae_release_lock_raw(_lock *p) -{ -#if AE_OS==AE_WINDOWS - InterlockedExchange((LONG volatile *)p->p_lock, 0); -#elif AE_OS==AE_POSIX - pthread_mutex_unlock(&p->mutex); -#else - p->is_locked = ae_false; -#endif -} - - -/************************************************************************ -This function frees _lock structure. -************************************************************************/ -void _ae_free_lock_raw(_lock *p) -{ -#if AE_OS==AE_POSIX - pthread_mutex_destroy(&p->mutex); -#endif -} - - -/************************************************************************ -This function initializes ae_lock structure. - -INPUT PARAMETERS: - lock - pointer to lock structure, must be zero-filled - state - pointer to state structure, used for exception - handling and management of automatic objects. - make_automatic - if true, lock object is added to automatic - memory management list. - -NOTE: as a special exception, this function allows you to specify NULL - state pointer. In this case all exception arising during construction - are handled as critical failures, with abort() being called. - make_automatic must be false on such calls. -************************************************************************/ -void ae_init_lock(ae_lock *lock, ae_state *state, ae_bool make_automatic) -{ - _lock *p; - AE_CRITICAL_ASSERT(ae_check_zeros(lock,sizeof(*lock))); - if(state==NULL) - { - ae_state _tmp_state; - AE_CRITICAL_ASSERT(!make_automatic); - ae_state_init(&_tmp_state); - ae_init_lock(lock, &_tmp_state, ae_false); - ae_state_clear(&_tmp_state); - return; - } - lock->eternal = ae_false; - ae_db_init(&lock->db, sizeof(_lock), state, make_automatic); - lock->lock_ptr = lock->db.ptr; - p = (_lock*)lock->lock_ptr; - _ae_init_lock_raw(p); -} - -/************************************************************************ -This function initializes "eternal" ae_lock structure which is expected -to persist until the end of the execution of the program. Eternal locks -can not be deallocated (cleared) and do not increase debug allocation -counters. Errors during allocation of eternal locks are considered -critical exceptions and handled by calling abort(). - -INPUT PARAMETERS: - lock - pointer to lock structure, must be zero-filled - state - pointer to state structure, used for exception - handling and management of automatic objects; - non-NULL. - make_automatic - if true, lock object is added to automatic - memory management list. -************************************************************************/ -void ae_init_lock_eternal(ae_lock *lock) -{ - _lock *p; - AE_CRITICAL_ASSERT(ae_check_zeros(lock,sizeof(*lock))); - lock->eternal = ae_true; - lock->lock_ptr = eternal_malloc(sizeof(_lock)); - p = (_lock*)lock->lock_ptr; - _ae_init_lock_raw(p); -} - - -/************************************************************************ -This function acquires lock. In case lock is busy, we perform several -iterations inside tight loop before trying again. -************************************************************************/ -void ae_acquire_lock(ae_lock *lock) -{ - _lock *p; - p = (_lock*)lock->lock_ptr; - _ae_acquire_lock_raw(p); -} - - -/************************************************************************ -This function releases lock. -************************************************************************/ -void ae_release_lock(ae_lock *lock) -{ - _lock *p; - p = (_lock*)lock->lock_ptr; - _ae_release_lock_raw(p); -} - - -/************************************************************************ -This function frees ae_lock structure. -************************************************************************/ -void ae_free_lock(ae_lock *lock) -{ - _lock *p; - AE_CRITICAL_ASSERT(!lock->eternal); - p = (_lock*)lock->lock_ptr; - if( p!=NULL ) - _ae_free_lock_raw(p); - ae_db_free(&lock->db); -} - - -/************************************************************************ -This function creates ae_shared_pool structure. - -dst destination shared pool, must be zero-filled - already allocated, but not initialized. -state pointer to current state structure. Can not be NULL. - used for exception handling (say, allocation error results - in longjmp call). -make_automatic if true, vector will be registered in the current frame - of the state structure; - -Error handling: -* on failure calls ae_break() with NULL state pointer. Usually it results - in abort() call. - -dst is assumed to be uninitialized, its fields are ignored. -************************************************************************/ -void ae_shared_pool_init(void *_dst, ae_state *state, ae_bool make_automatic) -{ - ae_shared_pool *dst; - - AE_CRITICAL_ASSERT(state!=NULL); - dst = (ae_shared_pool*)_dst; - AE_CRITICAL_ASSERT(ae_check_zeros(dst,sizeof(*dst))); - - /* init */ - dst->seed_object = NULL; - dst->recycled_objects = NULL; - dst->recycled_entries = NULL; - dst->enumeration_counter = NULL; - dst->size_of_object = 0; - dst->init = NULL; - dst->init_copy = NULL; - dst->destroy = NULL; - dst->frame_entry.deallocator = ae_shared_pool_destroy; - dst->frame_entry.ptr = dst; - if( make_automatic ) - ae_db_attach(&dst->frame_entry, state); - ae_init_lock(&dst->pool_lock, state, ae_false); -} - - -/************************************************************************ -This function clears all dynamically allocated fields of the pool except -for the lock. It does NOT try to acquire pool_lock. - -NOTE: this function is NOT thread-safe, it is not protected by lock. -************************************************************************/ -static void ae_shared_pool_internalclear(ae_shared_pool *dst) -{ - ae_shared_pool_entry *ptr, *tmp; - - /* destroy seed */ - if( dst->seed_object!=NULL ) - { - dst->destroy((void*)dst->seed_object); - ae_free((void*)dst->seed_object); - dst->seed_object = NULL; - } - - /* destroy recycled objects */ - for(ptr=dst->recycled_objects; ptr!=NULL;) - { - tmp = (ae_shared_pool_entry*)ptr->next_entry; - dst->destroy(ptr->obj); - ae_free(ptr->obj); - ae_free(ptr); - ptr = tmp; - } - dst->recycled_objects = NULL; - - /* destroy recycled entries */ - for(ptr=dst->recycled_entries; ptr!=NULL;) - { - tmp = (ae_shared_pool_entry*)ptr->next_entry; - ae_free(ptr); - ptr = tmp; - } - dst->recycled_entries = NULL; -} - - -/************************************************************************ -This function creates copy of ae_shared_pool. - -dst destination pool, must be zero-filled -src source pool -state pointer to current state structure. Can not be NULL. - used for exception handling (say, allocation error results - in longjmp call). -make_automatic if true, vector will be registered in the current frame - of the state structure; - -dst is assumed to be uninitialized, its fields are ignored. - -NOTE: this function is NOT thread-safe. It does not acquire pool lock, so - you should NOT call it when lock can be used by another thread. -************************************************************************/ -void ae_shared_pool_init_copy(void *_dst, void *_src, ae_state *state, ae_bool make_automatic) -{ - ae_shared_pool *dst, *src; - ae_shared_pool_entry *ptr; - - /* state!=NULL, allocation errors result in exception */ - /* AE_CRITICAL_ASSERT(state!=NULL); */ - - dst = (ae_shared_pool*)_dst; - src = (ae_shared_pool*)_src; - ae_shared_pool_init(dst, state, make_automatic); - - /* copy non-pointer fields */ - dst->size_of_object = src->size_of_object; - dst->init = src->init; - dst->init_copy = src->init_copy; - dst->destroy = src->destroy; - - /* copy seed object */ - if( src->seed_object!=NULL ) - { - dst->seed_object = ae_malloc(dst->size_of_object, state); - memset(dst->seed_object, 0, dst->size_of_object); - dst->init_copy(dst->seed_object, src->seed_object, state, ae_false); - } - - /* copy recycled objects */ - dst->recycled_objects = NULL; - for(ptr=src->recycled_objects; ptr!=NULL; ptr=(ae_shared_pool_entry*)ptr->next_entry) - { - ae_shared_pool_entry *tmp; - - /* allocate entry, immediately add to the recycled list - (we do not want to lose it in case of future malloc failures) */ - tmp = (ae_shared_pool_entry*)ae_malloc(sizeof(ae_shared_pool_entry), state); - memset(tmp, 0, sizeof(*tmp)); - tmp->next_entry = dst->recycled_objects; - dst->recycled_objects = tmp; - - /* prepare place for object, init_copy() it */ - tmp->obj = ae_malloc(dst->size_of_object, state); - memset(tmp->obj, 0, dst->size_of_object); - dst->init_copy(tmp->obj, ptr->obj, state, ae_false); - } - - /* recycled entries are not copied because they do not store any information */ - dst->recycled_entries = NULL; - - /* enumeration counter is reset on copying */ - dst->enumeration_counter = NULL; - - /* initialize frame record */ - dst->frame_entry.deallocator = ae_shared_pool_destroy; - dst->frame_entry.ptr = dst; -} - - -/************************************************************************ -This function performs destruction of the pool object. - -NOTE: this function is NOT thread-safe. It does not acquire pool lock, so - you should NOT call it when pool can be used by another thread. -************************************************************************/ -void ae_shared_pool_clear(void *_dst) -{ - ae_shared_pool *dst = (ae_shared_pool*)_dst; - - /* clear seed and lists */ - ae_shared_pool_internalclear(dst); - - /* clear fields */ - dst->seed_object = NULL; - dst->recycled_objects = NULL; - dst->recycled_entries = NULL; - dst->enumeration_counter = NULL; - dst->size_of_object = 0; - dst->init = NULL; - dst->init_copy = NULL; - dst->destroy = NULL; -} - -void ae_shared_pool_destroy(void *_dst) -{ - ae_shared_pool *dst = (ae_shared_pool*)_dst; - ae_shared_pool_clear(_dst); - ae_free_lock(&dst->pool_lock); -} - - -/************************************************************************ -This function returns True, if internal seed object was set. It returns -False for un-seeded pool. - -dst destination pool (initialized by constructor function) - -NOTE: this function is NOT thread-safe. It does not acquire pool lock, so - you should NOT call it when lock can be used by another thread. -************************************************************************/ -ae_bool ae_shared_pool_is_initialized(void *_dst) -{ - ae_shared_pool *dst = (ae_shared_pool*)_dst; - return dst->seed_object!=NULL; -} - - -/************************************************************************ -This function sets internal seed object. All objects owned by the pool -(current seed object, recycled objects) are automatically freed. - -dst destination pool (initialized by constructor function) -seed_object new seed object -size_of_object sizeof(), used to allocate memory -init constructor function -init_copy copy constructor -clear destructor function -state ALGLIB environment state - -NOTE: this function is NOT thread-safe. It does not acquire pool lock, so - you should NOT call it when lock can be used by another thread. -************************************************************************/ -void ae_shared_pool_set_seed( - ae_shared_pool *dst, - void *seed_object, - ae_int_t size_of_object, - void (*init)(void* dst, ae_state* state, ae_bool make_automatic), - void (*init_copy)(void* dst, void* src, ae_state* state, ae_bool make_automatic), - void (*destroy)(void* ptr), - ae_state *state) -{ - /* state!=NULL, allocation errors result in exception */ - AE_CRITICAL_ASSERT(state!=NULL); - - /* destroy internal objects */ - ae_shared_pool_internalclear(dst); - - /* set non-pointer fields */ - dst->size_of_object = size_of_object; - dst->init = init; - dst->init_copy = init_copy; - dst->destroy = destroy; - - /* set seed object */ - dst->seed_object = ae_malloc(size_of_object, state); - memset(dst->seed_object, 0, size_of_object); - init_copy(dst->seed_object, seed_object, state, ae_false); -} - - -/************************************************************************ -This function retrieves a copy of the seed object from the pool and -stores it to target smart pointer ptr. - -In case target pointer owns non-NULL value, it is deallocated before -storing value retrieved from pool. Target pointer becomes owner of the -value which was retrieved from pool. - -pool pool -pptr pointer to ae_smart_ptr structure -state ALGLIB environment state - -NOTE: this function IS thread-safe. It acquires pool lock during its - operation and can be used simultaneously from several threads. -************************************************************************/ -void ae_shared_pool_retrieve( - ae_shared_pool *pool, - ae_smart_ptr *pptr, - ae_state *state) -{ - void *new_obj; - - /* state!=NULL, allocation errors are handled by throwing exception from ae_malloc() */ - AE_CRITICAL_ASSERT(state!=NULL); - - /* assert that pool was seeded */ - ae_assert( - pool->seed_object!=NULL, - "ALGLIB: shared pool is not seeded, PoolRetrieve() failed", - state); - - /* acquire lock */ - ae_acquire_lock(&pool->pool_lock); - - /* try to reuse recycled objects */ - if( pool->recycled_objects!=NULL ) - { - ae_shared_pool_entry *result; - - /* retrieve entry/object from list of recycled objects */ - result = pool->recycled_objects; - pool->recycled_objects = (ae_shared_pool_entry*)pool->recycled_objects->next_entry; - new_obj = result->obj; - result->obj = NULL; - - /* move entry to list of recycled entries */ - result->next_entry = pool->recycled_entries; - pool->recycled_entries = result; - - /* release lock */ - ae_release_lock(&pool->pool_lock); - - /* assign object to smart pointer */ - ae_smart_ptr_assign(pptr, new_obj, ae_true, ae_true, pool->destroy); - return; - } - - /* release lock; we do not need it anymore because copy constructor does not modify source variable */ - ae_release_lock(&pool->pool_lock); - - /* create new object from seed, immediately assign object to smart pointer - (do not want to lose it in case of future failures) */ - new_obj = ae_malloc(pool->size_of_object, state); - memset(new_obj, 0, pool->size_of_object); - ae_smart_ptr_assign(pptr, new_obj, ae_true, ae_true, pool->destroy); - - /* perform actual copying; before this line smartptr points to zero-filled instance */ - pool->init_copy(new_obj, pool->seed_object, state, ae_false); -} - - -/************************************************************************ -This function recycles object owned by smart pointer by moving it to -internal storage of the shared pool. - -Source pointer must own the object. After function is over, it owns NULL -pointer. - -pool pool -pptr pointer to ae_smart_ptr structure -state ALGLIB environment state - -NOTE: this function IS thread-safe. It acquires pool lock during its - operation and can be used simultaneously from several threads. -************************************************************************/ -void ae_shared_pool_recycle( - ae_shared_pool *pool, - ae_smart_ptr *pptr, - ae_state *state) -{ - ae_shared_pool_entry *new_entry; - - /* state!=NULL, allocation errors are handled by throwing exception from ae_malloc() */ - AE_CRITICAL_ASSERT(state!=NULL); - - /* assert that pool was seeded */ - ae_assert( - pool->seed_object!=NULL, - "ALGLIB: shared pool is not seeded, PoolRecycle() failed", - state); - - /* assert that pointer non-null and owns the object */ - ae_assert(pptr->is_owner, "ALGLIB: pptr in ae_shared_pool_recycle() does not own its pointer", state); - ae_assert(pptr->ptr!=NULL, "ALGLIB: pptr in ae_shared_pool_recycle() is NULL", state); - - /* acquire lock */ - ae_acquire_lock(&pool->pool_lock); - - /* acquire shared pool entry (reuse one from recycled_entries or allocate new one) */ - if( pool->recycled_entries!=NULL ) - { - /* reuse previously allocated entry */ - new_entry = pool->recycled_entries; - pool->recycled_entries = (ae_shared_pool_entry*)new_entry->next_entry; - } - else - { - /* - * Allocate memory for new entry. - * - * NOTE: we release pool lock during allocation because ae_malloc() may raise - * exception and we do not want our pool to be left in the locked state. - */ - ae_release_lock(&pool->pool_lock); - new_entry = (ae_shared_pool_entry*)ae_malloc(sizeof(ae_shared_pool_entry), state); - ae_acquire_lock(&pool->pool_lock); - } - - /* add object to the list of recycled objects */ - new_entry->obj = pptr->ptr; - new_entry->next_entry = pool->recycled_objects; - pool->recycled_objects = new_entry; - - /* release lock object */ - ae_release_lock(&pool->pool_lock); - - /* release source pointer */ - ae_smart_ptr_release(pptr); -} - - -/************************************************************************ -This function clears internal list of recycled objects, but does not -change seed object managed by the pool. - -pool pool -state ALGLIB environment state - -NOTE: this function is NOT thread-safe. It does not acquire pool lock, so - you should NOT call it when lock can be used by another thread. -************************************************************************/ -void ae_shared_pool_clear_recycled( - ae_shared_pool *pool, - ae_state *state) -{ - ae_shared_pool_entry *ptr, *tmp; - - /* clear recycled objects */ - for(ptr=pool->recycled_objects; ptr!=NULL;) - { - tmp = (ae_shared_pool_entry*)ptr->next_entry; - pool->destroy(ptr->obj); - ae_free(ptr->obj); - ae_free(ptr); - ptr = tmp; - } - pool->recycled_objects = NULL; -} - - -/************************************************************************ -This function allows to enumerate recycled elements of the shared pool. -It stores pointer to the first recycled object in the smart pointer. - -IMPORTANT: -* in case target pointer owns non-NULL value, it is deallocated before - storing value retrieved from pool. -* recycled object IS NOT removed from pool -* target pointer DOES NOT become owner of the new value -* this function IS NOT thread-safe -* you SHOULD NOT modify shared pool during enumeration (although you can - modify state of the objects retrieved from pool) -* in case there is no recycled objects in the pool, NULL is stored to pptr -* in case pool is not seeded, NULL is stored to pptr - -pool pool -pptr pointer to ae_smart_ptr structure -state ALGLIB environment state -************************************************************************/ -void ae_shared_pool_first_recycled( - ae_shared_pool *pool, - ae_smart_ptr *pptr, - ae_state *state) -{ - /* modify internal enumeration counter */ - pool->enumeration_counter = pool->recycled_objects; - - /* exit on empty list */ - if( pool->enumeration_counter==NULL ) - { - ae_smart_ptr_assign(pptr, NULL, ae_false, ae_false, NULL); - return; - } - - /* assign object to smart pointer */ - ae_smart_ptr_assign(pptr, pool->enumeration_counter->obj, ae_false, ae_false, pool->destroy); -} - - -/************************************************************************ -This function allows to enumerate recycled elements of the shared pool. -It stores pointer to the next recycled object in the smart pointer. - -IMPORTANT: -* in case target pointer owns non-NULL value, it is deallocated before - storing value retrieved from pool. -* recycled object IS NOT removed from pool -* target pointer DOES NOT become owner of the new value -* this function IS NOT thread-safe -* you SHOULD NOT modify shared pool during enumeration (although you can - modify state of the objects retrieved from pool) -* in case there is no recycled objects left in the pool, NULL is stored. -* in case pool is not seeded, NULL is stored. - -pool pool -pptr pointer to ae_smart_ptr structure -state ALGLIB environment state -************************************************************************/ -void ae_shared_pool_next_recycled( - ae_shared_pool *pool, - ae_smart_ptr *pptr, - ae_state *state) -{ - /* exit on end of list */ - if( pool->enumeration_counter==NULL ) - { - ae_smart_ptr_assign(pptr, NULL, ae_false, ae_false, NULL); - return; - } - - /* modify internal enumeration counter */ - pool->enumeration_counter = (ae_shared_pool_entry*)pool->enumeration_counter->next_entry; - - /* exit on empty list */ - if( pool->enumeration_counter==NULL ) - { - ae_smart_ptr_assign(pptr, NULL, ae_false, ae_false, NULL); - return; - } - - /* assign object to smart pointer */ - ae_smart_ptr_assign(pptr, pool->enumeration_counter->obj, ae_false, ae_false, pool->destroy); -} - - - -/************************************************************************ -This function clears internal list of recycled objects and seed object. -However, pool still can be used (after initialization with another seed). - -pool pool -state ALGLIB environment state - -NOTE: this function is NOT thread-safe. It does not acquire pool lock, so - you should NOT call it when lock can be used by another thread. -************************************************************************/ -void ae_shared_pool_reset( - ae_shared_pool *pool, - ae_state *state) -{ - /* clear seed and lists */ - ae_shared_pool_internalclear(pool); - - /* clear fields */ - pool->seed_object = NULL; - pool->recycled_objects = NULL; - pool->recycled_entries = NULL; - pool->enumeration_counter = NULL; - pool->size_of_object = 0; - pool->init = NULL; - pool->init_copy = NULL; - pool->destroy = NULL; -} - - -/************************************************************************ -This function initializes serializer -************************************************************************/ -void ae_serializer_init(ae_serializer *serializer) -{ - serializer->mode = AE_SM_DEFAULT; - serializer->entries_needed = 0; - serializer->bytes_asked = 0; -} - -void ae_serializer_clear(ae_serializer *serializer) -{ -} - -void ae_serializer_alloc_start(ae_serializer *serializer) -{ - serializer->entries_needed = 0; - serializer->bytes_asked = 0; - serializer->mode = AE_SM_ALLOC; -} - -void ae_serializer_alloc_entry(ae_serializer *serializer) -{ - serializer->entries_needed++; -} - -void ae_serializer_alloc_byte_array(ae_serializer *serializer, ae_vector *bytes) -{ - ae_int_t n; - n = bytes->cnt; - n = n/8 + (n%8>0 ? 1 : 0); - serializer->entries_needed += 1+n; -} - -/************************************************************************ -After allocation phase is done, this function returns required size of -the output string buffer (including trailing zero symbol). Actual size of -the data being stored can be a few characters smaller than requested. -************************************************************************/ -ae_int_t ae_serializer_get_alloc_size(ae_serializer *serializer) -{ - ae_int_t rows, lastrowsize, result; - - serializer->mode = AE_SM_READY2S; - - /* if no entries needes (degenerate case) */ - if( serializer->entries_needed==0 ) - { - serializer->bytes_asked = 4; /* a pair of chars for \r\n, one for dot, one for trailing zero */ - return serializer->bytes_asked; - } - - /* non-degenerate case */ - rows = serializer->entries_needed/AE_SER_ENTRIES_PER_ROW; - lastrowsize = AE_SER_ENTRIES_PER_ROW; - if( serializer->entries_needed%AE_SER_ENTRIES_PER_ROW ) - { - lastrowsize = serializer->entries_needed%AE_SER_ENTRIES_PER_ROW; - rows++; - } - - /* calculate result size */ - result = ((rows-1)*AE_SER_ENTRIES_PER_ROW+lastrowsize)*AE_SER_ENTRY_LENGTH; /* data size */ - result += (rows-1)*(AE_SER_ENTRIES_PER_ROW-1)+(lastrowsize-1); /* space symbols */ - result += rows*2; /* newline symbols */ - result += 1; /* trailing dot */ - result += 1; /* trailing zero */ - serializer->bytes_asked = result; - return result; -} - -#ifdef AE_USE_CPP_SERIALIZATION -void ae_serializer_sstart_str(ae_serializer *serializer, std::string *buf) -{ - serializer->mode = AE_SM_TO_CPPSTRING; - serializer->out_cppstr = buf; - serializer->entries_saved = 0; - serializer->bytes_written = 0; -} - -void ae_serializer_ustart_str(ae_serializer *serializer, const std::string *buf) -{ - serializer->mode = AE_SM_FROM_STRING; - serializer->in_str = buf->c_str(); -} - -static char cpp_writer(const char *p_string, ae_int_t aux) -{ - std::ostream *stream = reinterpret_cast(aux); - stream->write(p_string, strlen(p_string)); - return stream->bad() ? 1 : 0; -} - -static char cpp_reader(ae_int_t aux, ae_int_t cnt, char *p_buf) -{ - std::istream *stream = reinterpret_cast(aux); - int c; - if( cnt<=0 ) - return 1; /* unexpected cnt */ - for(;;) - { - c = stream->get(); - if( c<0 || c>255 ) - return 1; /* failure! */ - if( c!=' ' && c!='\t' && c!='\n' && c!='\r' ) - break; - } - p_buf[0] = (char)c; - for(int k=1; kget(); - if( c<0 || c>255 || c==' ' || c=='\t' || c=='\n' || c=='\r' ) - return 1; /* failure! */ - p_buf[k] = (char)c; - } - p_buf[cnt] = 0; - return 0; /* success */ -} - -void ae_serializer_sstart_stream(ae_serializer *serializer, std::ostream *stream) -{ - serializer->mode = AE_SM_TO_STREAM; - serializer->stream_writer = cpp_writer; - serializer->stream_aux = reinterpret_cast(stream); - serializer->entries_saved = 0; - serializer->bytes_written = 0; -} - -void ae_serializer_ustart_stream(ae_serializer *serializer, const std::istream *stream) -{ - serializer->mode = AE_SM_FROM_STREAM; - serializer->stream_reader = cpp_reader; - serializer->stream_aux = reinterpret_cast(stream); -} -#endif - -void ae_serializer_sstart_str(ae_serializer *serializer, char *buf) -{ - serializer->mode = AE_SM_TO_STRING; - serializer->out_str = buf; - serializer->out_str[0] = 0; - serializer->entries_saved = 0; - serializer->bytes_written = 0; -} - -void ae_serializer_ustart_str(ae_serializer *serializer, const char *buf) -{ - serializer->mode = AE_SM_FROM_STRING; - serializer->in_str = buf; -} - -void ae_serializer_sstart_stream(ae_serializer *serializer, ae_stream_writer writer, ae_int_t aux) -{ - serializer->mode = AE_SM_TO_STREAM; - serializer->stream_writer = writer; - serializer->stream_aux = aux; - serializer->entries_saved = 0; - serializer->bytes_written = 0; -} - -void ae_serializer_ustart_stream(ae_serializer *serializer, ae_stream_reader reader, ae_int_t aux) -{ - serializer->mode = AE_SM_FROM_STREAM; - serializer->stream_reader = reader; - serializer->stream_aux = aux; -} - -void ae_serializer_serialize_bool(ae_serializer *serializer, ae_bool v, ae_state *state) -{ - char buf[AE_SER_ENTRY_LENGTH+2+1]; - const char *emsg = "ALGLIB: serialization integrity error"; - ae_int_t bytes_appended; - - /* prepare serialization, check consistency */ - ae_bool2str(v, buf, state); - serializer->entries_saved++; - if( serializer->entries_saved%AE_SER_ENTRIES_PER_ROW ) - strcat(buf, " "); - else - strcat(buf, "\r\n"); - bytes_appended = (ae_int_t)strlen(buf); - ae_assert(serializer->bytes_written+bytes_appendedbytes_asked, emsg, state); /* strict "less" because we need space for trailing zero */ - serializer->bytes_written += bytes_appended; - - /* append to buffer */ -#ifdef AE_USE_CPP_SERIALIZATION - if( serializer->mode==AE_SM_TO_CPPSTRING ) - { - *(serializer->out_cppstr) += buf; - return; - } -#endif - if( serializer->mode==AE_SM_TO_STRING ) - { - strcat(serializer->out_str, buf); - serializer->out_str += bytes_appended; - return; - } - if( serializer->mode==AE_SM_TO_STREAM ) - { - ae_assert(serializer->stream_writer(buf, serializer->stream_aux)==0, "serializer: error writing to stream", state); - return; - } - ae_break(state, ERR_ASSERTION_FAILED, emsg); -} - -void ae_serializer_serialize_int(ae_serializer *serializer, ae_int_t v, ae_state *state) -{ - char buf[AE_SER_ENTRY_LENGTH+2+1]; - const char *emsg = "ALGLIB: serialization integrity error"; - ae_int_t bytes_appended; - - /* prepare serialization, check consistency */ - ae_int2str(v, buf, state); - serializer->entries_saved++; - if( serializer->entries_saved%AE_SER_ENTRIES_PER_ROW ) - strcat(buf, " "); - else - strcat(buf, "\r\n"); - bytes_appended = (ae_int_t)strlen(buf); - ae_assert(serializer->bytes_written+bytes_appendedbytes_asked, emsg, state); /* strict "less" because we need space for trailing zero */ - serializer->bytes_written += bytes_appended; - - /* append to buffer */ -#ifdef AE_USE_CPP_SERIALIZATION - if( serializer->mode==AE_SM_TO_CPPSTRING ) - { - *(serializer->out_cppstr) += buf; - return; - } -#endif - if( serializer->mode==AE_SM_TO_STRING ) - { - strcat(serializer->out_str, buf); - serializer->out_str += bytes_appended; - return; - } - if( serializer->mode==AE_SM_TO_STREAM ) - { - ae_assert(serializer->stream_writer(buf, serializer->stream_aux)==0, "serializer: error writing to stream", state); - return; - } - ae_break(state, ERR_ASSERTION_FAILED, emsg); -} - -void ae_serializer_serialize_int64(ae_serializer *serializer, ae_int64_t v, ae_state *state) -{ - char buf[AE_SER_ENTRY_LENGTH+2+1]; - const char *emsg = "ALGLIB: serialization integrity error"; - ae_int_t bytes_appended; - - /* prepare serialization, check consistency */ - ae_int642str(v, buf, state); - serializer->entries_saved++; - if( serializer->entries_saved%AE_SER_ENTRIES_PER_ROW ) - strcat(buf, " "); - else - strcat(buf, "\r\n"); - bytes_appended = (ae_int_t)strlen(buf); - ae_assert(serializer->bytes_written+bytes_appendedbytes_asked, emsg, state); /* strict "less" because we need space for trailing zero */ - serializer->bytes_written += bytes_appended; - - /* append to buffer */ -#ifdef AE_USE_CPP_SERIALIZATION - if( serializer->mode==AE_SM_TO_CPPSTRING ) - { - *(serializer->out_cppstr) += buf; - return; - } -#endif - if( serializer->mode==AE_SM_TO_STRING ) - { - strcat(serializer->out_str, buf); - serializer->out_str += bytes_appended; - return; - } - if( serializer->mode==AE_SM_TO_STREAM ) - { - ae_assert(serializer->stream_writer(buf, serializer->stream_aux)==0, "serializer: error writing to stream", state); - return; - } - ae_break(state, ERR_ASSERTION_FAILED, emsg); -} - -void ae_serializer_serialize_double(ae_serializer *serializer, double v, ae_state *state) -{ - char buf[AE_SER_ENTRY_LENGTH+2+1]; - const char *emsg = "ALGLIB: serialization integrity error"; - ae_int_t bytes_appended; - - /* prepare serialization, check consistency */ - ae_double2str(v, buf, state); - serializer->entries_saved++; - if( serializer->entries_saved%AE_SER_ENTRIES_PER_ROW ) - strcat(buf, " "); - else - strcat(buf, "\r\n"); - bytes_appended = (ae_int_t)strlen(buf); - ae_assert(serializer->bytes_written+bytes_appendedbytes_asked, emsg, state); /* strict "less" because we need space for trailing zero */ - serializer->bytes_written += bytes_appended; - - /* append to buffer */ -#ifdef AE_USE_CPP_SERIALIZATION - if( serializer->mode==AE_SM_TO_CPPSTRING ) - { - *(serializer->out_cppstr) += buf; - return; - } -#endif - if( serializer->mode==AE_SM_TO_STRING ) - { - strcat(serializer->out_str, buf); - serializer->out_str += bytes_appended; - return; - } - if( serializer->mode==AE_SM_TO_STREAM ) - { - ae_assert(serializer->stream_writer(buf, serializer->stream_aux)==0, "serializer: error writing to stream", state); - return; - } - ae_break(state, ERR_ASSERTION_FAILED, emsg); -} - -void ae_serializer_serialize_byte_array(ae_serializer *serializer, ae_vector *bytes, ae_state *state) -{ - ae_int_t chunk_size, entries_count; - - chunk_size = 8; - - /* save array length */ - ae_serializer_serialize_int(serializer, bytes->cnt, state); - - /* determine entries count */ - entries_count = bytes->cnt/chunk_size + (bytes->cnt%chunk_size>0 ? 1 : 0); - for(ae_int_t eidx=0; eidxcnt - eidx*chunk_size; - elen = elen>chunk_size ? chunk_size : elen; - memset(&tmpi, 0, sizeof(tmpi)); - memmove(&tmpi, bytes->ptr.p_ubyte + eidx*chunk_size, elen); - ae_serializer_serialize_int64(serializer, tmpi, state); - } -} - -void ae_serializer_unserialize_bool(ae_serializer *serializer, ae_bool *v, ae_state *state) -{ - if( serializer->mode==AE_SM_FROM_STRING ) - { - *v = ae_str2bool(serializer->in_str, state, &serializer->in_str); - return; - } - if( serializer->mode==AE_SM_FROM_STREAM ) - { - char buf[AE_SER_ENTRY_LENGTH+2+1]; - const char *p = buf; - ae_assert(serializer->stream_reader(serializer->stream_aux, AE_SER_ENTRY_LENGTH, buf)==0, "serializer: error reading from stream", state); - *v = ae_str2bool(buf, state, &p); - return; - } - ae_break(state, ERR_ASSERTION_FAILED, "ae_serializer: integrity check failed"); -} - -void ae_serializer_unserialize_int(ae_serializer *serializer, ae_int_t *v, ae_state *state) -{ - if( serializer->mode==AE_SM_FROM_STRING ) - { - *v = ae_str2int(serializer->in_str, state, &serializer->in_str); - return; - } - if( serializer->mode==AE_SM_FROM_STREAM ) - { - char buf[AE_SER_ENTRY_LENGTH+2+1]; - const char *p = buf; - ae_assert(serializer->stream_reader(serializer->stream_aux, AE_SER_ENTRY_LENGTH, buf)==0, "serializer: error reading from stream", state); - *v = ae_str2int(buf, state, &p); - return; - } - ae_break(state, ERR_ASSERTION_FAILED, "ae_serializer: integrity check failed"); -} - -void ae_serializer_unserialize_int64(ae_serializer *serializer, ae_int64_t *v, ae_state *state) -{ - if( serializer->mode==AE_SM_FROM_STRING ) - { - *v = ae_str2int64(serializer->in_str, state, &serializer->in_str); - return; - } - if( serializer->mode==AE_SM_FROM_STREAM ) - { - char buf[AE_SER_ENTRY_LENGTH+2+1]; - const char *p = buf; - ae_assert(serializer->stream_reader(serializer->stream_aux, AE_SER_ENTRY_LENGTH, buf)==0, "serializer: error reading from stream", state); - *v = ae_str2int64(buf, state, &p); - return; - } - ae_break(state, ERR_ASSERTION_FAILED, "ae_serializer: integrity check failed"); -} - -void ae_serializer_unserialize_double(ae_serializer *serializer, double *v, ae_state *state) -{ - if( serializer->mode==AE_SM_FROM_STRING ) - { - *v = ae_str2double(serializer->in_str, state, &serializer->in_str); - return; - } - if( serializer->mode==AE_SM_FROM_STREAM ) - { - char buf[AE_SER_ENTRY_LENGTH+2+1]; - const char *p = buf; - ae_assert(serializer->stream_reader(serializer->stream_aux, AE_SER_ENTRY_LENGTH, buf)==0, "serializer: error reading from stream", state); - *v = ae_str2double(buf, state, &p); - return; - } - ae_break(state, ERR_ASSERTION_FAILED, "ae_serializer: integrity check failed"); -} - -void ae_serializer_unserialize_byte_array(ae_serializer *serializer, ae_vector *bytes, ae_state *state) -{ - ae_int_t chunk_size, n, entries_count; - - chunk_size = 8; - - /* read array length, allocate output */ - ae_serializer_unserialize_int(serializer, &n, state); - ae_vector_set_length(bytes, n, state); - - /* determine entries count, read entries */ - entries_count = n/chunk_size + (n%chunk_size>0 ? 1 : 0); - for(ae_int_t eidx=0; eidxchunk_size ? chunk_size : elen; - ae_serializer_unserialize_int64(serializer, &tmp64, state); - memmove(bytes->ptr.p_ubyte+eidx*chunk_size, &tmp64, elen); - } -} - -void ae_serializer_stop(ae_serializer *serializer, ae_state *state) -{ -#ifdef AE_USE_CPP_SERIALIZATION - if( serializer->mode==AE_SM_TO_CPPSTRING ) - { - ae_assert(serializer->bytes_written+1bytes_asked, "ae_serializer: integrity check failed", state);/* strict "less" because we need space for trailing zero */ - serializer->bytes_written++; - *(serializer->out_cppstr) += "."; - return; - } -#endif - if( serializer->mode==AE_SM_TO_STRING ) - { - ae_assert(serializer->bytes_written+1bytes_asked, "ae_serializer: integrity check failed", state); /* strict "less" because we need space for trailing zero */ - serializer->bytes_written++; - strcat(serializer->out_str, "."); - serializer->out_str += 1; - return; - } - if( serializer->mode==AE_SM_TO_STREAM ) - { - ae_assert(serializer->bytes_written+1bytes_asked, "ae_serializer: integrity check failed", state); /* strict "less" because we need space for trailing zero */ - serializer->bytes_written++; - ae_assert(serializer->stream_writer(".", serializer->stream_aux)==0, "ae_serializer: error writing to stream", state); - return; - } - if( serializer->mode==AE_SM_FROM_STRING ) - { - /* - * because input string may be from pre-3.11 serializer, - * which does not include trailing dot, we do not test - * string for presence of "." symbol. Anyway, because string - * is not stream, we do not have to read ALL trailing symbols. - */ - return; - } - if( serializer->mode==AE_SM_FROM_STREAM ) - { - /* - * Read trailing dot, perform integrity check - */ - char buf[2]; - ae_assert(serializer->stream_reader(serializer->stream_aux, 1, buf)==0, "ae_serializer: error reading from stream", state); - ae_assert(buf[0]=='.', "ae_serializer: trailing . is not found in the stream", state); - return; - } - ae_break(state, ERR_ASSERTION_FAILED, "ae_serializer: integrity check failed"); -} - - -/************************************************************************ -Complex math functions -************************************************************************/ -ae_complex ae_complex_from_i(ae_int_t v) -{ - ae_complex r; - r.x = (double)v; - r.y = 0.0; - return r; -} - -ae_complex ae_complex_from_d(double v) -{ - ae_complex r; - r.x = v; - r.y = 0.0; - return r; -} - -ae_complex ae_c_neg(ae_complex lhs) -{ - ae_complex result; - result.x = -lhs.x; - result.y = -lhs.y; - return result; -} - -ae_complex ae_c_conj(ae_complex lhs, ae_state *state) -{ - ae_complex result; - result.x = +lhs.x; - result.y = -lhs.y; - return result; -} - -ae_complex ae_c_sqr(ae_complex lhs, ae_state *state) -{ - ae_complex result; - result.x = lhs.x*lhs.x-lhs.y*lhs.y; - result.y = 2*lhs.x*lhs.y; - return result; -} - -double ae_c_abs(ae_complex z, ae_state *state) -{ - double w; - double xabs; - double yabs; - double v; - - xabs = fabs(z.x); - yabs = fabs(z.y); - w = xabs>yabs ? xabs : yabs; - v = xabsx; - v0y = -v0->y; - v1x = v1->x; - v1y = -v1->y; - rx += v0x*v1x-v0y*v1y; - ry += v0x*v1y+v0y*v1x; - } - } - if( !bconj0 && bconj1 ) - { - double v0x, v0y, v1x, v1y; - for(i=0; ix; - v0y = v0->y; - v1x = v1->x; - v1y = -v1->y; - rx += v0x*v1x-v0y*v1y; - ry += v0x*v1y+v0y*v1x; - } - } - if( bconj0 && !bconj1 ) - { - double v0x, v0y, v1x, v1y; - for(i=0; ix; - v0y = -v0->y; - v1x = v1->x; - v1y = v1->y; - rx += v0x*v1x-v0y*v1y; - ry += v0x*v1y+v0y*v1x; - } - } - if( !bconj0 && !bconj1 ) - { - double v0x, v0y, v1x, v1y; - for(i=0; ix; - v0y = v0->y; - v1x = v1->x; - v1y = v1->y; - rx += v0x*v1x-v0y*v1y; - ry += v0x*v1y+v0y*v1x; - } - } - result.x = rx; - result.y = ry; - return result; -} - -void ae_v_cmove(ae_complex *vdst, ae_int_t stride_dst, const ae_complex* vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n) -{ - ae_bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n')); - ae_int_t i; - if( stride_dst!=1 || stride_src!=1 ) - { - /* - * general unoptimized case - */ - if( bconj ) - { - for(i=0; ix = vsrc->x; - vdst->y = -vsrc->y; - } - } - else - { - for(i=0; ix = vsrc->x; - vdst->y = -vsrc->y; - } - } - else - { - for(i=0; ix = -vsrc->x; - vdst->y = vsrc->y; - } - } - else - { - for(i=0; ix = -vsrc->x; - vdst->y = -vsrc->y; - } - } - } - else - { - /* - * optimized case - */ - if( bconj ) - { - for(i=0; ix = -vsrc->x; - vdst->y = vsrc->y; - } - } - else - { - for(i=0; ix = -vsrc->x; - vdst->y = -vsrc->y; - } - } - } -} - -void ae_v_cmoved(ae_complex *vdst, ae_int_t stride_dst, const ae_complex* vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, double alpha) -{ - ae_bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n')); - ae_int_t i; - if( stride_dst!=1 || stride_src!=1 ) - { - /* - * general unoptimized case - */ - if( bconj ) - { - for(i=0; ix = alpha*vsrc->x; - vdst->y = -alpha*vsrc->y; - } - } - else - { - for(i=0; ix = alpha*vsrc->x; - vdst->y = alpha*vsrc->y; - } - } - } - else - { - /* - * optimized case - */ - if( bconj ) - { - for(i=0; ix = alpha*vsrc->x; - vdst->y = -alpha*vsrc->y; - } - } - else - { - for(i=0; ix = alpha*vsrc->x; - vdst->y = alpha*vsrc->y; - } - } - } -} - -void ae_v_cmovec(ae_complex *vdst, ae_int_t stride_dst, const ae_complex* vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, ae_complex alpha) -{ - ae_bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n')); - ae_int_t i; - if( stride_dst!=1 || stride_src!=1 ) - { - /* - * general unoptimized case - */ - if( bconj ) - { - double ax = alpha.x, ay = alpha.y; - for(i=0; ix = ax*vsrc->x+ay*vsrc->y; - vdst->y = -ax*vsrc->y+ay*vsrc->x; - } - } - else - { - double ax = alpha.x, ay = alpha.y; - for(i=0; ix = ax*vsrc->x-ay*vsrc->y; - vdst->y = ax*vsrc->y+ay*vsrc->x; - } - } - } - else - { - /* - * highly optimized case - */ - if( bconj ) - { - double ax = alpha.x, ay = alpha.y; - for(i=0; ix = ax*vsrc->x+ay*vsrc->y; - vdst->y = -ax*vsrc->y+ay*vsrc->x; - } - } - else - { - double ax = alpha.x, ay = alpha.y; - for(i=0; ix = ax*vsrc->x-ay*vsrc->y; - vdst->y = ax*vsrc->y+ay*vsrc->x; - } - } - } -} - -void ae_v_cadd(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n) -{ - ae_bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n')); - ae_int_t i; - if( stride_dst!=1 || stride_src!=1 ) - { - /* - * general unoptimized case - */ - if( bconj ) - { - for(i=0; ix += vsrc->x; - vdst->y -= vsrc->y; - } - } - else - { - for(i=0; ix += vsrc->x; - vdst->y += vsrc->y; - } - } - } - else - { - /* - * optimized case - */ - if( bconj ) - { - for(i=0; ix += vsrc->x; - vdst->y -= vsrc->y; - } - } - else - { - for(i=0; ix += vsrc->x; - vdst->y += vsrc->y; - } - } - } -} - -void ae_v_caddd(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, double alpha) -{ - ae_bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n')); - ae_int_t i; - if( stride_dst!=1 || stride_src!=1 ) - { - /* - * general unoptimized case - */ - if( bconj ) - { - for(i=0; ix += alpha*vsrc->x; - vdst->y -= alpha*vsrc->y; - } - } - else - { - for(i=0; ix += alpha*vsrc->x; - vdst->y += alpha*vsrc->y; - } - } - } - else - { - /* - * optimized case - */ - if( bconj ) - { - for(i=0; ix += alpha*vsrc->x; - vdst->y -= alpha*vsrc->y; - } - } - else - { - for(i=0; ix += alpha*vsrc->x; - vdst->y += alpha*vsrc->y; - } - } - } -} - -void ae_v_caddc(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, ae_complex alpha) -{ - ae_bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n')); - ae_int_t i; - if( stride_dst!=1 || stride_src!=1 ) - { - /* - * general unoptimized case - */ - double ax = alpha.x, ay = alpha.y; - if( bconj ) - { - for(i=0; ix += ax*vsrc->x+ay*vsrc->y; - vdst->y -= ax*vsrc->y-ay*vsrc->x; - } - } - else - { - for(i=0; ix += ax*vsrc->x-ay*vsrc->y; - vdst->y += ax*vsrc->y+ay*vsrc->x; - } - } - } - else - { - /* - * highly optimized case - */ - double ax = alpha.x, ay = alpha.y; - if( bconj ) - { - for(i=0; ix += ax*vsrc->x+ay*vsrc->y; - vdst->y -= ax*vsrc->y-ay*vsrc->x; - } - } - else - { - for(i=0; ix += ax*vsrc->x-ay*vsrc->y; - vdst->y += ax*vsrc->y+ay*vsrc->x; - } - } - } -} - -void ae_v_csub(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n) -{ - ae_bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n')); - ae_int_t i; - if( stride_dst!=1 || stride_src!=1 ) - { - /* - * general unoptimized case - */ - if( bconj ) - { - for(i=0; ix -= vsrc->x; - vdst->y += vsrc->y; - } - } - else - { - for(i=0; ix -= vsrc->x; - vdst->y -= vsrc->y; - } - } - } - else - { - /* - * highly optimized case - */ - if( bconj ) - { - for(i=0; ix -= vsrc->x; - vdst->y += vsrc->y; - } - } - else - { - for(i=0; ix -= vsrc->x; - vdst->y -= vsrc->y; - } - } - } -} - -void ae_v_csubd(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, double alpha) -{ - ae_v_caddd(vdst, stride_dst, vsrc, stride_src, conj_src, n, -alpha); -} - -void ae_v_csubc(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, ae_complex alpha) -{ - alpha.x = -alpha.x; - alpha.y = -alpha.y; - ae_v_caddc(vdst, stride_dst, vsrc, stride_src, conj_src, n, alpha); -} - -void ae_v_cmuld(ae_complex *vdst, ae_int_t stride_dst, ae_int_t n, double alpha) -{ - ae_int_t i; - if( stride_dst!=1 ) - { - /* - * general unoptimized case - */ - for(i=0; ix *= alpha; - vdst->y *= alpha; - } - } - else - { - /* - * optimized case - */ - for(i=0; ix *= alpha; - vdst->y *= alpha; - } - } -} - -void ae_v_cmulc(ae_complex *vdst, ae_int_t stride_dst, ae_int_t n, ae_complex alpha) -{ - ae_int_t i; - if( stride_dst!=1 ) - { - /* - * general unoptimized case - */ - double ax = alpha.x, ay = alpha.y; - for(i=0; ix, dsty = vdst->y; - vdst->x = ax*dstx-ay*dsty; - vdst->y = ax*dsty+ay*dstx; - } - } - else - { - /* - * highly optimized case - */ - double ax = alpha.x, ay = alpha.y; - for(i=0; ix, dsty = vdst->y; - vdst->x = ax*dstx-ay*dsty; - vdst->y = ax*dsty+ay*dstx; - } - } -} - -/************************************************************************ -Real BLAS operations -************************************************************************/ -double ae_v_dotproduct(const double *v0, ae_int_t stride0, const double *v1, ae_int_t stride1, ae_int_t n) -{ - double result = 0; - ae_int_t i; - if( stride0!=1 || stride1!=1 ) - { - /* - * slow general code - */ - for(i=0; iba, 0, sizeof(p->ba)); - memset(&p->ia, 0, sizeof(p->ia)); - memset(&p->ra, 0, sizeof(p->ra)); - memset(&p->ca, 0, sizeof(p->ca)); - - /* initialization */ - ae_vector_init(&p->ba, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->ia, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->ra, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ca, 0, DT_COMPLEX, _state, make_automatic); -} - -void _rcommstate_init_copy(rcommstate* dst, rcommstate* src, ae_state *_state, ae_bool make_automatic) -{ - /* initial zero-filling */ - memset(&dst->ba, 0, sizeof(dst->ba)); - memset(&dst->ia, 0, sizeof(dst->ia)); - memset(&dst->ra, 0, sizeof(dst->ra)); - memset(&dst->ca, 0, sizeof(dst->ca)); - - /* initialization */ - ae_vector_init_copy(&dst->ba, &src->ba, _state, make_automatic); - ae_vector_init_copy(&dst->ia, &src->ia, _state, make_automatic); - ae_vector_init_copy(&dst->ra, &src->ra, _state, make_automatic); - ae_vector_init_copy(&dst->ca, &src->ca, _state, make_automatic); - dst->stage = src->stage; -} - -void _rcommstate_clear(rcommstate* p) -{ - ae_vector_clear(&p->ba); - ae_vector_clear(&p->ia); - ae_vector_clear(&p->ra); - ae_vector_clear(&p->ca); -} - -void _rcommstate_destroy(rcommstate* p) -{ - _rcommstate_clear(p); -} - - -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS C++ RELATED FUNCTIONALITY -// -///////////////////////////////////////////////////////////////////////// -/******************************************************************** -Internal forwards -********************************************************************/ -namespace alglib -{ - double get_aenv_nan(); - double get_aenv_posinf(); - double get_aenv_neginf(); - ae_int_t my_stricmp(const char *s1, const char *s2); - char* filter_spaces(const char *s); - void str_vector_create(const char *src, bool match_head_only, std::vector *p_vec); - void str_matrix_create(const char *src, std::vector< std::vector > *p_mat); - - ae_bool parse_bool_delim(const char *s, const char *delim); - ae_int_t parse_int_delim(const char *s, const char *delim); - bool _parse_real_delim(const char *s, const char *delim, double *result, const char **new_s); - double parse_real_delim(const char *s, const char *delim); - alglib::complex parse_complex_delim(const char *s, const char *delim); - - std::string arraytostring(const bool *ptr, ae_int_t n); - std::string arraytostring(const ae_int_t *ptr, ae_int_t n); - std::string arraytostring(const double *ptr, ae_int_t n, int dps); - std::string arraytostring(const alglib::complex *ptr, ae_int_t n, int dps); -} - -/******************************************************************** -Global and local constants/variables -********************************************************************/ -const double alglib::machineepsilon = 5E-16; -const double alglib::maxrealnumber = 1E300; -const double alglib::minrealnumber = 1E-300; -const alglib::ae_int_t alglib::endianness = alglib_impl::ae_get_endianness(); -const double alglib::fp_nan = alglib::get_aenv_nan(); -const double alglib::fp_posinf = alglib::get_aenv_posinf(); -const double alglib::fp_neginf = alglib::get_aenv_neginf(); -#if defined(AE_NO_EXCEPTIONS) -static const char *_alglib_last_error = NULL; -#endif -static const alglib_impl::ae_uint64_t _i64_xdefault = 0x0; -static const alglib_impl::ae_uint64_t _i64_xserial = _ALGLIB_FLG_THREADING_SERIAL; -static const alglib_impl::ae_uint64_t _i64_xparallel = _ALGLIB_FLG_THREADING_PARALLEL; -const alglib::xparams &alglib::xdefault = *((const alglib::xparams *)(&_i64_xdefault)); -const alglib::xparams &alglib::serial = *((const alglib::xparams *)(&_i64_xserial)); -const alglib::xparams &alglib::parallel = *((const alglib::xparams *)(&_i64_xparallel)); - - - -/******************************************************************** -Exception handling -********************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -alglib::ap_error::ap_error() -{ -} - -alglib::ap_error::ap_error(const char *s) -{ - msg = s; -} - -void alglib::ap_error::make_assertion(bool bClause) -{ - if(!bClause) - _ALGLIB_CPP_EXCEPTION(""); -} - -void alglib::ap_error::make_assertion(bool bClause, const char *p_msg) -{ - if(!bClause) - _ALGLIB_CPP_EXCEPTION(p_msg); -} -#else -void alglib::set_error_flag(const char *s) -{ - if( s==NULL ) - s = "ALGLIB: unknown error"; - _alglib_last_error = s; -} - -bool alglib::get_error_flag(const char **p_msg) -{ - if( _alglib_last_error==NULL ) - return false; - if( p_msg!=NULL ) - *p_msg = _alglib_last_error; - return true; -} - -void alglib::clear_error_flag() -{ - _alglib_last_error = NULL; -} -#endif - -/******************************************************************** -Complex number with double precision. -********************************************************************/ -alglib::complex::complex():x(0.0),y(0.0) -{ -} - -alglib::complex::complex(const double &_x):x(_x),y(0.0) -{ -} - -alglib::complex::complex(const double &_x, const double &_y):x(_x),y(_y) -{ -} - -alglib::complex::complex(const alglib::complex &z):x(z.x),y(z.y) -{ -} - -alglib::complex& alglib::complex::operator= (const double& v) -{ - x = v; - y = 0.0; - return *this; -} - -alglib::complex& alglib::complex::operator+=(const double& v) -{ - x += v; - return *this; -} - -alglib::complex& alglib::complex::operator-=(const double& v) -{ - x -= v; - return *this; -} - -alglib::complex& alglib::complex::operator*=(const double& v) -{ - x *= v; - y *= v; - return *this; -} - -alglib::complex& alglib::complex::operator/=(const double& v) -{ - x /= v; - y /= v; - return *this; -} - -alglib::complex& alglib::complex::operator= (const alglib::complex& z) -{ - x = z.x; - y = z.y; - return *this; -} - -alglib::complex& alglib::complex::operator+=(const alglib::complex& z) -{ - x += z.x; - y += z.y; - return *this; -} - -alglib::complex& alglib::complex::operator-=(const alglib::complex& z) -{ - x -= z.x; - y -= z.y; - return *this; -} - -alglib::complex& alglib::complex::operator*=(const alglib::complex& z) -{ - double t = x*z.x-y*z.y; - y = x*z.y+y*z.x; - x = t; - return *this; -} - -alglib::complex& alglib::complex::operator/=(const alglib::complex& z) -{ - alglib::complex result; - double e; - double f; - if( fabs(z.y)=0 ? _dps : -_dps; - if( dps<=0 || dps>=20 ) - _ALGLIB_CPP_EXCEPTION("complex::tostring(): incorrect dps"); - - // handle IEEE special quantities - if( fp_isnan(x) || fp_isnan(y) ) - return "NAN"; - if( fp_isinf(x) || fp_isinf(y) ) - return "INF"; - - // generate mask - if( sprintf(mask, "%%.%d%s", dps, _dps>=0 ? "f" : "e")>=(int)sizeof(mask) ) - _ALGLIB_CPP_EXCEPTION("complex::tostring(): buffer overflow"); - - // print |x|, |y| and zero with same mask and compare - if( sprintf(buf_x, mask, (double)(fabs(x)))>=(int)sizeof(buf_x) ) - _ALGLIB_CPP_EXCEPTION("complex::tostring(): buffer overflow"); - if( sprintf(buf_y, mask, (double)(fabs(y)))>=(int)sizeof(buf_y) ) - _ALGLIB_CPP_EXCEPTION("complex::tostring(): buffer overflow"); - if( sprintf(buf_zero, mask, (double)0)>=(int)sizeof(buf_zero) ) - _ALGLIB_CPP_EXCEPTION("complex::tostring(): buffer overflow"); - - // different zero/nonzero patterns - if( strcmp(buf_x,buf_zero)!=0 && strcmp(buf_y,buf_zero)!=0 ) - return std::string(x>0 ? "" : "-")+buf_x+(y>0 ? "+" : "-")+buf_y+"i"; - if( strcmp(buf_x,buf_zero)!=0 && strcmp(buf_y,buf_zero)==0 ) - return std::string(x>0 ? "" : "-")+buf_x; - if( strcmp(buf_x,buf_zero)==0 && strcmp(buf_y,buf_zero)!=0 ) - return std::string(y>0 ? "" : "-")+buf_y+"i"; - return std::string("0"); -} -#endif - -bool alglib::operator==(const alglib::complex& lhs, const alglib::complex& rhs) -{ - volatile double x1 = lhs.x; - volatile double x2 = rhs.x; - volatile double y1 = lhs.y; - volatile double y2 = rhs.y; - return x1==x2 && y1==y2; -} - -bool alglib::operator!=(const alglib::complex& lhs, const alglib::complex& rhs) -{ return !(lhs==rhs); } - -const alglib::complex alglib::operator+(const alglib::complex& lhs) -{ return lhs; } - -const alglib::complex alglib::operator-(const alglib::complex& lhs) -{ return alglib::complex(-lhs.x, -lhs.y); } - -const alglib::complex alglib::operator+(const alglib::complex& lhs, const alglib::complex& rhs) -{ alglib::complex r = lhs; r += rhs; return r; } - -const alglib::complex alglib::operator+(const alglib::complex& lhs, const double& rhs) -{ alglib::complex r = lhs; r += rhs; return r; } - -const alglib::complex alglib::operator+(const double& lhs, const alglib::complex& rhs) -{ alglib::complex r = rhs; r += lhs; return r; } - -const alglib::complex alglib::operator-(const alglib::complex& lhs, const alglib::complex& rhs) -{ alglib::complex r = lhs; r -= rhs; return r; } - -const alglib::complex alglib::operator-(const alglib::complex& lhs, const double& rhs) -{ alglib::complex r = lhs; r -= rhs; return r; } - -const alglib::complex alglib::operator-(const double& lhs, const alglib::complex& rhs) -{ alglib::complex r = lhs; r -= rhs; return r; } - -const alglib::complex alglib::operator*(const alglib::complex& lhs, const alglib::complex& rhs) -{ return alglib::complex(lhs.x*rhs.x - lhs.y*rhs.y, lhs.x*rhs.y + lhs.y*rhs.x); } - -const alglib::complex alglib::operator*(const alglib::complex& lhs, const double& rhs) -{ return alglib::complex(lhs.x*rhs, lhs.y*rhs); } - -const alglib::complex alglib::operator*(const double& lhs, const alglib::complex& rhs) -{ return alglib::complex(lhs*rhs.x, lhs*rhs.y); } - -const alglib::complex alglib::operator/(const alglib::complex& lhs, const alglib::complex& rhs) -{ - alglib::complex result; - double e; - double f; - if( fabs(rhs.y)yabs ? xabs : yabs; - v = xabsx; - v0y = -v0->y; - v1x = v1->x; - v1y = -v1->y; - rx += v0x*v1x-v0y*v1y; - ry += v0x*v1y+v0y*v1x; - } - } - if( !bconj0 && bconj1 ) - { - double v0x, v0y, v1x, v1y; - for(i=0; ix; - v0y = v0->y; - v1x = v1->x; - v1y = -v1->y; - rx += v0x*v1x-v0y*v1y; - ry += v0x*v1y+v0y*v1x; - } - } - if( bconj0 && !bconj1 ) - { - double v0x, v0y, v1x, v1y; - for(i=0; ix; - v0y = -v0->y; - v1x = v1->x; - v1y = v1->y; - rx += v0x*v1x-v0y*v1y; - ry += v0x*v1y+v0y*v1x; - } - } - if( !bconj0 && !bconj1 ) - { - double v0x, v0y, v1x, v1y; - for(i=0; ix; - v0y = v0->y; - v1x = v1->x; - v1y = v1->y; - rx += v0x*v1x-v0y*v1y; - ry += v0x*v1y+v0y*v1x; - } - } - return alglib::complex(rx,ry); -} - -alglib::complex alglib::vdotproduct(const alglib::complex *v1, const alglib::complex *v2, ae_int_t N) -{ - return vdotproduct(v1, 1, "N", v2, 1, "N", N); -} - -void alglib::vmove(double *vdst, ae_int_t stride_dst, const double* vsrc, ae_int_t stride_src, ae_int_t n) -{ - ae_int_t i; - if( stride_dst!=1 || stride_src!=1 ) - { - // - // general unoptimized case - // - for(i=0; ix = vsrc->x; - vdst->y = -vsrc->y; - } - } - else - { - for(i=0; ix = vsrc->x; - vdst->y = -vsrc->y; - } - } - else - { - for(i=0; ix = -vsrc->x; - vdst->y = vsrc->y; - } - } - else - { - for(i=0; ix = -vsrc->x; - vdst->y = -vsrc->y; - } - } - } - else - { - // - // optimized case - // - if( bconj ) - { - for(i=0; ix = -vsrc->x; - vdst->y = vsrc->y; - } - } - else - { - for(i=0; ix = -vsrc->x; - vdst->y = -vsrc->y; - } - } - } -} - -void alglib::vmoveneg(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t N) -{ - vmoveneg(vdst, 1, vsrc, 1, "N", N); -} - -void alglib::vmove(double *vdst, ae_int_t stride_dst, const double* vsrc, ae_int_t stride_src, ae_int_t n, double alpha) -{ - ae_int_t i; - if( stride_dst!=1 || stride_src!=1 ) - { - // - // general unoptimized case - // - for(i=0; ix = alpha*vsrc->x; - vdst->y = -alpha*vsrc->y; - } - } - else - { - for(i=0; ix = alpha*vsrc->x; - vdst->y = alpha*vsrc->y; - } - } - } - else - { - // - // optimized case - // - if( bconj ) - { - for(i=0; ix = alpha*vsrc->x; - vdst->y = -alpha*vsrc->y; - } - } - else - { - for(i=0; ix = alpha*vsrc->x; - vdst->y = alpha*vsrc->y; - } - } - } -} - -void alglib::vmove(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t N, double alpha) -{ - vmove(vdst, 1, vsrc, 1, "N", N, alpha); -} - -void alglib::vmove(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex* vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, alglib::complex alpha) -{ - bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n')); - ae_int_t i; - if( stride_dst!=1 || stride_src!=1 ) - { - // - // general unoptimized case - // - if( bconj ) - { - double ax = alpha.x, ay = alpha.y; - for(i=0; ix = ax*vsrc->x+ay*vsrc->y; - vdst->y = -ax*vsrc->y+ay*vsrc->x; - } - } - else - { - double ax = alpha.x, ay = alpha.y; - for(i=0; ix = ax*vsrc->x-ay*vsrc->y; - vdst->y = ax*vsrc->y+ay*vsrc->x; - } - } - } - else - { - // - // optimized case - // - if( bconj ) - { - double ax = alpha.x, ay = alpha.y; - for(i=0; ix = ax*vsrc->x+ay*vsrc->y; - vdst->y = -ax*vsrc->y+ay*vsrc->x; - } - } - else - { - double ax = alpha.x, ay = alpha.y; - for(i=0; ix = ax*vsrc->x-ay*vsrc->y; - vdst->y = ax*vsrc->y+ay*vsrc->x; - } - } - } -} - -void alglib::vmove(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t N, alglib::complex alpha) -{ - vmove(vdst, 1, vsrc, 1, "N", N, alpha); -} - -void alglib::vadd(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n) -{ - ae_int_t i; - if( stride_dst!=1 || stride_src!=1 ) - { - // - // general unoptimized case - // - for(i=0; ix += vsrc->x; - vdst->y -= vsrc->y; - } - } - else - { - for(i=0; ix += vsrc->x; - vdst->y += vsrc->y; - } - } - } - else - { - // - // optimized case - // - if( bconj ) - { - for(i=0; ix += vsrc->x; - vdst->y -= vsrc->y; - } - } - else - { - for(i=0; ix += vsrc->x; - vdst->y += vsrc->y; - } - } - } -} - -void alglib::vadd(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t N) -{ - vadd(vdst, 1, vsrc, 1, "N", N); -} - -void alglib::vadd(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n, double alpha) -{ - ae_int_t i; - if( stride_dst!=1 || stride_src!=1 ) - { - // - // general unoptimized case - // - for(i=0; ix += alpha*vsrc->x; - vdst->y -= alpha*vsrc->y; - } - } - else - { - for(i=0; ix += alpha*vsrc->x; - vdst->y += alpha*vsrc->y; - } - } - } - else - { - // - // optimized case - // - if( bconj ) - { - for(i=0; ix += alpha*vsrc->x; - vdst->y -= alpha*vsrc->y; - } - } - else - { - for(i=0; ix += alpha*vsrc->x; - vdst->y += alpha*vsrc->y; - } - } - } -} - -void alglib::vadd(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t N, double alpha) -{ - vadd(vdst, 1, vsrc, 1, "N", N, alpha); -} - -void alglib::vadd(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, alglib::complex alpha) -{ - bool bconj = !((conj_src[0]=='N') || (conj_src[0]=='n')); - ae_int_t i; - if( stride_dst!=1 || stride_src!=1 ) - { - // - // general unoptimized case - // - double ax = alpha.x, ay = alpha.y; - if( bconj ) - { - for(i=0; ix += ax*vsrc->x+ay*vsrc->y; - vdst->y -= ax*vsrc->y-ay*vsrc->x; - } - } - else - { - for(i=0; ix += ax*vsrc->x-ay*vsrc->y; - vdst->y += ax*vsrc->y+ay*vsrc->x; - } - } - } - else - { - // - // optimized case - // - double ax = alpha.x, ay = alpha.y; - if( bconj ) - { - for(i=0; ix += ax*vsrc->x+ay*vsrc->y; - vdst->y -= ax*vsrc->y-ay*vsrc->x; - } - } - else - { - for(i=0; ix += ax*vsrc->x-ay*vsrc->y; - vdst->y += ax*vsrc->y+ay*vsrc->x; - } - } - } -} - -void alglib::vadd(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t N, alglib::complex alpha) -{ - vadd(vdst, 1, vsrc, 1, "N", N, alpha); -} - -void alglib::vsub(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n) -{ - ae_int_t i; - if( stride_dst!=1 || stride_src!=1 ) - { - // - // general unoptimized case - // - for(i=0; ix -= vsrc->x; - vdst->y += vsrc->y; - } - } - else - { - for(i=0; ix -= vsrc->x; - vdst->y -= vsrc->y; - } - } - } - else - { - // - // optimized case - // - if( bconj ) - { - for(i=0; ix -= vsrc->x; - vdst->y += vsrc->y; - } - } - else - { - for(i=0; ix -= vsrc->x; - vdst->y -= vsrc->y; - } - } - } -} - -void alglib::vsub(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t N) -{ - vsub(vdst, 1, vsrc, 1, "N", N); -} - -void alglib::vsub(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n, double alpha) -{ - vadd(vdst, stride_dst, vsrc, stride_src, n, -alpha); -} - -void alglib::vsub(double *vdst, const double *vsrc, ae_int_t N, double alpha) -{ - vadd(vdst, 1, vsrc, 1, N, -alpha); -} - -void alglib::vsub(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, double alpha) -{ - vadd(vdst, stride_dst, vsrc, stride_src, conj_src, n, -alpha); -} - -void alglib::vsub(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t n, double alpha) -{ - vadd(vdst, 1, vsrc, 1, "N", n, -alpha); -} - -void alglib::vsub(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, alglib::complex alpha) -{ - vadd(vdst, stride_dst, vsrc, stride_src, conj_src, n, -alpha); -} - -void alglib::vsub(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t n, alglib::complex alpha) -{ - vadd(vdst, 1, vsrc, 1, "N", n, -alpha); -} -void alglib::vmul(double *vdst, ae_int_t stride_dst, ae_int_t n, double alpha) -{ - ae_int_t i; - if( stride_dst!=1 ) - { - // - // general unoptimized case - // - for(i=0; ix *= alpha; - vdst->y *= alpha; - } - } - else - { - // - // optimized case - // - for(i=0; ix *= alpha; - vdst->y *= alpha; - } - } -} - -void alglib::vmul(alglib::complex *vdst, ae_int_t N, double alpha) -{ - vmul(vdst, 1, N, alpha); -} - -void alglib::vmul(alglib::complex *vdst, ae_int_t stride_dst, ae_int_t n, alglib::complex alpha) -{ - ae_int_t i; - if( stride_dst!=1 ) - { - // - // general unoptimized case - // - double ax = alpha.x, ay = alpha.y; - for(i=0; ix, dsty = vdst->y; - vdst->x = ax*dstx-ay*dsty; - vdst->y = ax*dsty+ay*dstx; - } - } - else - { - // - // optimized case - // - double ax = alpha.x, ay = alpha.y; - for(i=0; ix, dsty = vdst->y; - vdst->x = ax*dstx-ay*dsty; - vdst->y = ax*dsty+ay*dstx; - } - } -} - -void alglib::vmul(alglib::complex *vdst, ae_int_t N, alglib::complex alpha) -{ - vmul(vdst, 1, N, alpha); -} - -alglib::ae_int_t alglib::vlen(ae_int_t n1, ae_int_t n2) -{ - return n2-n1+1; -} - - -/******************************************************************** -Matrices and vectors -********************************************************************/ -alglib::ae_vector_wrapper::ae_vector_wrapper(alglib_impl::ae_vector *e_ptr, alglib_impl::ae_datatype datatype) -{ - if( e_ptr==NULL || e_ptr->datatype!=datatype ) - { - const char *msg = "ALGLIB: ae_vector_wrapper datatype check failed"; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(msg); -#else - ptr = NULL; - is_frozen_proxy = false; - _ALGLIB_SET_ERROR_FLAG(msg); - return; -#endif - } - ptr = e_ptr; - is_frozen_proxy = true; -} - -alglib::ae_vector_wrapper::ae_vector_wrapper(alglib_impl::ae_datatype datatype) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - ptr = NULL; - is_frozen_proxy = false; - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - ptr = &inner_vec; - is_frozen_proxy = false; - memset(ptr, 0, sizeof(*ptr)); - ae_vector_init(ptr, 0, datatype, &_state, ae_false); - ae_state_clear(&_state); -} - -alglib::ae_vector_wrapper::ae_vector_wrapper(const ae_vector_wrapper &rhs, alglib_impl::ae_datatype datatype) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - ptr = NULL; - is_frozen_proxy = false; - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(rhs.ptr!=NULL, "ALGLIB: ae_vector_wrapper source is not initialized", &_state); - alglib_impl::ae_assert(rhs.ptr->datatype==datatype, "ALGLIB: ae_vector_wrapper datatype check failed", &_state); - ptr = &inner_vec; - is_frozen_proxy = false; - memset(ptr, 0, sizeof(*ptr)); - ae_vector_init_copy(ptr, rhs.ptr, &_state, ae_false); - ae_state_clear(&_state); -} - -alglib::ae_vector_wrapper::~ae_vector_wrapper() -{ - if( ptr==&inner_vec ) - ae_vector_clear(ptr); -} - -void alglib::ae_vector_wrapper::setlength(ae_int_t iLen) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(ptr!=NULL, "ALGLIB: setlength() error, ptr==NULL (array was not correctly initialized)", &_state); - alglib_impl::ae_assert(!is_frozen_proxy, "ALGLIB: setlength() error, ptr is frozen proxy array", &_state); - alglib_impl::ae_vector_set_length(ptr, iLen, &_state); - alglib_impl::ae_state_clear(&_state); -} - -alglib::ae_int_t alglib::ae_vector_wrapper::length() const -{ - if( ptr==NULL ) - return 0; - return ptr->cnt; -} - -void alglib::ae_vector_wrapper::attach_to(alglib_impl::x_vector *new_ptr, alglib_impl::ae_state *_state) -{ - if( ptr==&inner_vec ) - ae_vector_clear(ptr); - ptr = &inner_vec; - memset(ptr, 0, sizeof(*ptr)); - ae_vector_init_attach_to_x(ptr, new_ptr, _state, ae_false); - is_frozen_proxy = true; -} - -const alglib::ae_vector_wrapper& alglib::ae_vector_wrapper::assign(const alglib::ae_vector_wrapper &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - if( this==&rhs ) - return *this; - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - ae_assert(ptr!=NULL, "ALGLIB: incorrect assignment (uninitialized destination)", &_state); - ae_assert(rhs.ptr!=NULL, "ALGLIB: incorrect assignment (uninitialized source)", &_state); - ae_assert(rhs.ptr->datatype==ptr->datatype, "ALGLIB: incorrect assignment to array (types do not match)", &_state); - if( is_frozen_proxy ) - ae_assert(rhs.ptr->cnt==ptr->cnt, "ALGLIB: incorrect assignment to proxy array (sizes do not match)", &_state); - if( rhs.ptr->cnt!=ptr->cnt ) - ae_vector_set_length(ptr, rhs.ptr->cnt, &_state); - memcpy(ptr->ptr.p_ptr, rhs.ptr->ptr.p_ptr, ptr->cnt*alglib_impl::ae_sizeof(ptr->datatype)); - alglib_impl::ae_state_clear(&_state); - return *this; -} - -const alglib_impl::ae_vector* alglib::ae_vector_wrapper::c_ptr() const -{ - return ptr; -} - -alglib_impl::ae_vector* alglib::ae_vector_wrapper::c_ptr() -{ - return ptr; -} - -#if !defined(AE_NO_EXCEPTIONS) -alglib::ae_vector_wrapper::ae_vector_wrapper(const char *s, alglib_impl::ae_datatype datatype) -{ - std::vector svec; - size_t i; - char *p = filter_spaces(s); - if( p==NULL ) - _ALGLIB_CPP_EXCEPTION("ALGLIB: allocation error"); - try - { - str_vector_create(p, true, &svec); - { - jmp_buf _break_jump; - alglib_impl::ae_state _state; - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - ptr = &inner_vec; - is_frozen_proxy = false; - memset(ptr, 0, sizeof(*ptr)); - ae_vector_init(ptr, (ae_int_t)(svec.size()), datatype, &_state, ae_false); - ae_state_clear(&_state); - } - for(i=0; iptr.p_bool[i] = parse_bool_delim(svec[i],",]"); - if( datatype==alglib_impl::DT_INT ) - ptr->ptr.p_int[i] = parse_int_delim(svec[i],",]"); - if( datatype==alglib_impl::DT_REAL ) - ptr->ptr.p_double[i] = parse_real_delim(svec[i],",]"); - if( datatype==alglib_impl::DT_COMPLEX ) - { - alglib::complex t = parse_complex_delim(svec[i],",]"); - ptr->ptr.p_complex[i].x = t.x; - ptr->ptr.p_complex[i].y = t.y; - } - } - alglib_impl::ae_free(p); - } - catch(...) - { - alglib_impl::ae_free(p); - throw; - } -} -#endif - -alglib::boolean_1d_array::boolean_1d_array():ae_vector_wrapper(alglib_impl::DT_BOOL) -{ -} - -alglib::boolean_1d_array::boolean_1d_array(const alglib::boolean_1d_array &rhs):ae_vector_wrapper(rhs,alglib_impl::DT_BOOL) -{ -} - -alglib::boolean_1d_array::boolean_1d_array(alglib_impl::ae_vector *p):ae_vector_wrapper(p,alglib_impl::DT_BOOL) -{ -} - -const alglib::boolean_1d_array& alglib::boolean_1d_array::operator=(const alglib::boolean_1d_array &rhs) -{ - return static_cast(assign(rhs)); -} - -alglib::boolean_1d_array::~boolean_1d_array() -{ -} - -const ae_bool& alglib::boolean_1d_array::operator()(ae_int_t i) const -{ - return ptr->ptr.p_bool[i]; -} - -ae_bool& alglib::boolean_1d_array::operator()(ae_int_t i) -{ - return ptr->ptr.p_bool[i]; -} - -const ae_bool& alglib::boolean_1d_array::operator[](ae_int_t i) const -{ - return ptr->ptr.p_bool[i]; -} - -ae_bool& alglib::boolean_1d_array::operator[](ae_int_t i) -{ - return ptr->ptr.p_bool[i]; -} - -void alglib::boolean_1d_array::setcontent(ae_int_t iLen, const bool *pContent ) -{ - ae_int_t i; - - // setlength, with exception-free error handling fallback code - setlength(iLen); - if( ptr==NULL || ptr->cnt!=iLen ) - return; - - // copy - for(i=0; iptr.p_bool[i] = pContent[i]; -} - -ae_bool* alglib::boolean_1d_array::getcontent() -{ - return ptr->ptr.p_bool; -} - -const ae_bool* alglib::boolean_1d_array::getcontent() const -{ - return ptr->ptr.p_bool; -} - -#if !defined(AE_NO_EXCEPTIONS) -alglib::boolean_1d_array::boolean_1d_array(const char *s):ae_vector_wrapper(s, alglib_impl::DT_BOOL) -{ -} - -std::string alglib::boolean_1d_array::tostring() const -{ - if( length()==0 ) - return "[]"; - return arraytostring(&(operator()(0)), length()); -} -#endif - -alglib::integer_1d_array::integer_1d_array():ae_vector_wrapper(alglib_impl::DT_INT) -{ -} - -alglib::integer_1d_array::integer_1d_array(alglib_impl::ae_vector *p):ae_vector_wrapper(p,alglib_impl::DT_INT) -{ -} - -alglib::integer_1d_array::integer_1d_array(const alglib::integer_1d_array &rhs):ae_vector_wrapper(rhs,alglib_impl::DT_INT) -{ -} - -const alglib::integer_1d_array& alglib::integer_1d_array::operator=(const alglib::integer_1d_array &rhs) -{ - return static_cast(assign(rhs)); -} - -alglib::integer_1d_array::~integer_1d_array() -{ -} - -const alglib::ae_int_t& alglib::integer_1d_array::operator()(ae_int_t i) const -{ - return ptr->ptr.p_int[i]; -} - -alglib::ae_int_t& alglib::integer_1d_array::operator()(ae_int_t i) -{ - return ptr->ptr.p_int[i]; -} - -const alglib::ae_int_t& alglib::integer_1d_array::operator[](ae_int_t i) const -{ - return ptr->ptr.p_int[i]; -} - -alglib::ae_int_t& alglib::integer_1d_array::operator[](ae_int_t i) -{ - return ptr->ptr.p_int[i]; -} - -void alglib::integer_1d_array::setcontent(ae_int_t iLen, const ae_int_t *pContent ) -{ - ae_int_t i; - - // setlength(), handle possible exception-free errors - setlength(iLen); - if( ptr==NULL || ptr->cnt!=iLen ) - return; - - // copy - for(i=0; iptr.p_int[i] = pContent[i]; -} - -alglib::ae_int_t* alglib::integer_1d_array::getcontent() -{ - return ptr->ptr.p_int; -} - -const alglib::ae_int_t* alglib::integer_1d_array::getcontent() const -{ - return ptr->ptr.p_int; -} - -#if !defined(AE_NO_EXCEPTIONS) -alglib::integer_1d_array::integer_1d_array(const char *s):ae_vector_wrapper(s, alglib_impl::DT_INT) -{ -} - -std::string alglib::integer_1d_array::tostring() const -{ - if( length()==0 ) - return "[]"; - return arraytostring(&operator()(0), length()); -} -#endif - -alglib::real_1d_array::real_1d_array():ae_vector_wrapper(alglib_impl::DT_REAL) -{ -} - -alglib::real_1d_array::real_1d_array(alglib_impl::ae_vector *p):ae_vector_wrapper(p,alglib_impl::DT_REAL) -{ -} - -alglib::real_1d_array::real_1d_array(const alglib::real_1d_array &rhs):ae_vector_wrapper(rhs,alglib_impl::DT_REAL) -{ -} - -const alglib::real_1d_array& alglib::real_1d_array::operator=(const alglib::real_1d_array &rhs) -{ - return static_cast(assign(rhs)); -} - -alglib::real_1d_array::~real_1d_array() -{ -} - -const double& alglib::real_1d_array::operator()(ae_int_t i) const -{ - return ptr->ptr.p_double[i]; -} - -double& alglib::real_1d_array::operator()(ae_int_t i) -{ - return ptr->ptr.p_double[i]; -} - -const double& alglib::real_1d_array::operator[](ae_int_t i) const -{ - return ptr->ptr.p_double[i]; -} - -double& alglib::real_1d_array::operator[](ae_int_t i) -{ - return ptr->ptr.p_double[i]; -} - -void alglib::real_1d_array::setcontent(ae_int_t iLen, const double *pContent ) -{ - ae_int_t i; - - // setlength(), handle possible exception-free errors - setlength(iLen); - if( ptr==NULL || ptr->cnt!=iLen ) - return; - - // copy - for(i=0; iptr.p_double[i] = pContent[i]; -} - -void alglib::real_1d_array::attach_to_ptr(ae_int_t iLen, double *pContent ) // TODO: convert to constructor!!!!!!! -{ - alglib_impl::x_vector x; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - ptr = NULL; - is_frozen_proxy = false; - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(!is_frozen_proxy, "ALGLIB: unable to attach proxy object to something else", &_state); - alglib_impl::ae_assert(iLen>0, "ALGLIB: non-positive length for attach_to_ptr()", &_state); - x.cnt = iLen; - x.datatype = alglib_impl::DT_REAL; - x.owner = alglib_impl::OWN_CALLER; - x.last_action = alglib_impl::ACT_UNCHANGED; - x.x_ptr.p_ptr = pContent; - attach_to(&x, &_state); - ae_state_clear(&_state); -} - -double* alglib::real_1d_array::getcontent() -{ - return ptr->ptr.p_double; -} - -const double* alglib::real_1d_array::getcontent() const -{ - return ptr->ptr.p_double; -} - -#if !defined(AE_NO_EXCEPTIONS) -alglib::real_1d_array::real_1d_array(const char *s):ae_vector_wrapper(s, alglib_impl::DT_REAL) -{ -} - -std::string alglib::real_1d_array::tostring(int dps) const -{ - if( length()==0 ) - return "[]"; - return arraytostring(&operator()(0), length(), dps); -} -#endif - -alglib::complex_1d_array::complex_1d_array():ae_vector_wrapper(alglib_impl::DT_COMPLEX) -{ -} - -alglib::complex_1d_array::complex_1d_array(alglib_impl::ae_vector *p):ae_vector_wrapper(p,alglib_impl::DT_COMPLEX) -{ -} - -alglib::complex_1d_array::complex_1d_array(const alglib::complex_1d_array &rhs):ae_vector_wrapper(rhs,alglib_impl::DT_COMPLEX) -{ -} - -const alglib::complex_1d_array& alglib::complex_1d_array::operator=(const alglib::complex_1d_array &rhs) -{ - return static_cast(assign(rhs)); -} - -alglib::complex_1d_array::~complex_1d_array() -{ -} - -const alglib::complex& alglib::complex_1d_array::operator()(ae_int_t i) const -{ - return *((const alglib::complex*)(ptr->ptr.p_complex+i)); -} - -alglib::complex& alglib::complex_1d_array::operator()(ae_int_t i) -{ - return *((alglib::complex*)(ptr->ptr.p_complex+i)); -} - -const alglib::complex& alglib::complex_1d_array::operator[](ae_int_t i) const -{ - return *((const alglib::complex*)(ptr->ptr.p_complex+i)); -} - -alglib::complex& alglib::complex_1d_array::operator[](ae_int_t i) -{ - return *((alglib::complex*)(ptr->ptr.p_complex+i)); -} - -void alglib::complex_1d_array::setcontent(ae_int_t iLen, const alglib::complex *pContent ) -{ - ae_int_t i; - - // setlength(), handle possible exception-free errors - setlength(iLen); - if( ptr==NULL || ptr->cnt!=iLen ) - return; - - // copy - for(i=0; iptr.p_complex[i].x = pContent[i].x; - ptr->ptr.p_complex[i].y = pContent[i].y; - } -} - - alglib::complex* alglib::complex_1d_array::getcontent() -{ - return (alglib::complex*)ptr->ptr.p_complex; -} - -const alglib::complex* alglib::complex_1d_array::getcontent() const -{ - return (const alglib::complex*)ptr->ptr.p_complex; -} - -#if !defined(AE_NO_EXCEPTIONS) -alglib::complex_1d_array::complex_1d_array(const char *s):ae_vector_wrapper(s, alglib_impl::DT_COMPLEX) -{ -} - -std::string alglib::complex_1d_array::tostring(int dps) const -{ - if( length()==0 ) - return "[]"; - return arraytostring(&operator()(0), length(), dps); -} -#endif - -alglib::ae_matrix_wrapper::ae_matrix_wrapper(alglib_impl::ae_matrix *e_ptr, alglib_impl::ae_datatype datatype) -{ - if( e_ptr->datatype!=datatype ) - { - const char *msg = "ALGLIB: ae_vector_wrapper datatype check failed"; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(msg); -#else - ptr = NULL; - is_frozen_proxy = false; - _ALGLIB_SET_ERROR_FLAG(msg); - return; -#endif - } - ptr = e_ptr; - is_frozen_proxy = true; -} - -alglib::ae_matrix_wrapper::ae_matrix_wrapper(alglib_impl::ae_datatype datatype) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - ptr = NULL; - is_frozen_proxy = false; - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - ptr = &inner_mat; - is_frozen_proxy = false; - memset(ptr, 0, sizeof(*ptr)); - ae_matrix_init(ptr, 0, 0, datatype, &_state, ae_false); - ae_state_clear(&_state); - -} - -alglib::ae_matrix_wrapper::ae_matrix_wrapper(const ae_matrix_wrapper &rhs, alglib_impl::ae_datatype datatype) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - ptr = NULL; - is_frozen_proxy = false; - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - is_frozen_proxy = false; - ptr = NULL; - alglib_impl::ae_assert(rhs.ptr->datatype==datatype, "ALGLIB: ae_matrix_wrapper datatype check failed", &_state); - if( rhs.ptr!=NULL ) - { - ptr = &inner_mat; - memset(ptr, 0, sizeof(*ptr)); - ae_matrix_init_copy(ptr, rhs.ptr, &_state, ae_false); - } - ae_state_clear(&_state); -} - -alglib::ae_matrix_wrapper::~ae_matrix_wrapper() -{ - if( ptr==&inner_mat ) - ae_matrix_clear(ptr); -} - -#if !defined(AE_NO_EXCEPTIONS) -alglib::ae_matrix_wrapper::ae_matrix_wrapper(const char *s, alglib_impl::ae_datatype datatype) -{ - std::vector< std::vector > smat; - size_t i, j; - char *p = filter_spaces(s); - if( p==NULL ) - _ALGLIB_CPP_EXCEPTION("ALGLIB: allocation error"); - try - { - str_matrix_create(p, &smat); - { - jmp_buf _break_jump; - alglib_impl::ae_state _state; - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - ptr = &inner_mat; - is_frozen_proxy = false; - memset(ptr, 0, sizeof(*ptr)); - if( smat.size()!=0 ) - ae_matrix_init(ptr, (ae_int_t)(smat.size()), (ae_int_t)(smat[0].size()), datatype, &_state, ae_false); - else - ae_matrix_init(ptr, 0, 0, datatype, &_state, ae_false); - ae_state_clear(&_state); - } - for(i=0; iptr.pp_bool[i][j] = parse_bool_delim(smat[i][j],",]"); - if( datatype==alglib_impl::DT_INT ) - ptr->ptr.pp_int[i][j] = parse_int_delim(smat[i][j],",]"); - if( datatype==alglib_impl::DT_REAL ) - ptr->ptr.pp_double[i][j] = parse_real_delim(smat[i][j],",]"); - if( datatype==alglib_impl::DT_COMPLEX ) - { - alglib::complex t = parse_complex_delim(smat[i][j],",]"); - ptr->ptr.pp_complex[i][j].x = t.x; - ptr->ptr.pp_complex[i][j].y = t.y; - } - } - alglib_impl::ae_free(p); - } - catch(...) - { - alglib_impl::ae_free(p); - throw; - } -} -#endif - -void alglib::ae_matrix_wrapper::setlength(ae_int_t rows, ae_int_t cols) // TODO: automatic allocation of NULL ptr!!!!! -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(ptr!=NULL, "ALGLIB: setlength() error, p_mat==NULL (array was not correctly initialized)", &_state); - alglib_impl::ae_assert(!is_frozen_proxy, "ALGLIB: setlength() error, attempt to resize proxy array", &_state); - alglib_impl::ae_matrix_set_length(ptr, rows, cols, &_state); - alglib_impl::ae_state_clear(&_state); -} - -alglib::ae_int_t alglib::ae_matrix_wrapper::rows() const -{ - if( ptr==NULL ) - return 0; - return ptr->rows; -} - -alglib::ae_int_t alglib::ae_matrix_wrapper::cols() const -{ - if( ptr==NULL ) - return 0; - return ptr->cols; -} - -bool alglib::ae_matrix_wrapper::isempty() const -{ - return rows()==0 || cols()==0; -} - -alglib::ae_int_t alglib::ae_matrix_wrapper::getstride() const -{ - if( ptr==NULL ) - return 0; - return ptr->stride; -} - -void alglib::ae_matrix_wrapper::attach_to(alglib_impl::x_matrix *new_ptr, alglib_impl::ae_state *_state) -{ - if( ptr==&inner_mat ) - ae_matrix_clear(ptr); - ptr = &inner_mat; - memset(ptr, 0, sizeof(*ptr)); - ae_matrix_init_attach_to_x(ptr, new_ptr, _state, ae_false); - is_frozen_proxy = true; -} - -const alglib::ae_matrix_wrapper& alglib::ae_matrix_wrapper::assign(const alglib::ae_matrix_wrapper &rhs) -{ - ae_int_t i; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - if( this==&rhs ) - return *this; - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - ae_assert(ptr!=NULL, "ALGLIB: incorrect assignment to matrix (uninitialized destination)", &_state); - ae_assert(rhs.ptr!=NULL, "ALGLIB: incorrect assignment to array (uninitialized source)", &_state); - ae_assert(rhs.ptr->datatype==ptr->datatype, "ALGLIB: incorrect assignment to array (types dont match)", &_state); - if( is_frozen_proxy ) - { - ae_assert(rhs.ptr->rows==ptr->rows, "ALGLIB: incorrect assignment to proxy array (sizes dont match)", &_state); - ae_assert(rhs.ptr->cols==ptr->cols, "ALGLIB: incorrect assignment to proxy array (sizes dont match)", &_state); - } - if( (rhs.ptr->rows!=ptr->rows) || (rhs.ptr->cols!=ptr->cols) ) - ae_matrix_set_length(ptr, rhs.ptr->rows, rhs.ptr->cols, &_state); - for(i=0; irows; i++) - memcpy(ptr->ptr.pp_void[i], rhs.ptr->ptr.pp_void[i], ptr->cols*alglib_impl::ae_sizeof(ptr->datatype)); - alglib_impl::ae_state_clear(&_state); - return *this; -} - -const alglib_impl::ae_matrix* alglib::ae_matrix_wrapper::c_ptr() const -{ - return ptr; -} - -alglib_impl::ae_matrix* alglib::ae_matrix_wrapper::c_ptr() -{ - return ptr; -} - -alglib::boolean_2d_array::boolean_2d_array():ae_matrix_wrapper(alglib_impl::DT_BOOL) -{ -} - -alglib::boolean_2d_array::boolean_2d_array(const alglib::boolean_2d_array &rhs):ae_matrix_wrapper(rhs,alglib_impl::DT_BOOL) -{ -} - -alglib::boolean_2d_array::boolean_2d_array(alglib_impl::ae_matrix *p):ae_matrix_wrapper(p,alglib_impl::DT_BOOL) -{ -} - -alglib::boolean_2d_array::~boolean_2d_array() -{ -} - -const alglib::boolean_2d_array& alglib::boolean_2d_array::operator=(const alglib::boolean_2d_array &rhs) -{ - return static_cast(assign(rhs)); -} - -const ae_bool& alglib::boolean_2d_array::operator()(ae_int_t i, ae_int_t j) const -{ - return ptr->ptr.pp_bool[i][j]; -} - -ae_bool& alglib::boolean_2d_array::operator()(ae_int_t i, ae_int_t j) -{ - return ptr->ptr.pp_bool[i][j]; -} - -const ae_bool* alglib::boolean_2d_array::operator[](ae_int_t i) const -{ - return ptr->ptr.pp_bool[i]; -} - -ae_bool* alglib::boolean_2d_array::operator[](ae_int_t i) -{ - return ptr->ptr.pp_bool[i]; -} - -void alglib::boolean_2d_array::setcontent(ae_int_t irows, ae_int_t icols, const bool *pContent ) -{ - ae_int_t i, j; - - // setlength(), handle possible exception-free errors - setlength(irows, icols); - if( ptr==NULL || ptr->rows!=irows || ptr->cols!=icols ) - return; - - // copy - for(i=0; iptr.pp_bool[i][j] = pContent[i*icols+j]; -} - -#if !defined(AE_NO_EXCEPTIONS) -alglib::boolean_2d_array::boolean_2d_array(const char *s):ae_matrix_wrapper(s, alglib_impl::DT_BOOL) -{ -} - -std::string alglib::boolean_2d_array::tostring() const -{ - std::string result; - ae_int_t i; - if( isempty() ) - return "[[]]"; - result = "["; - for(i=0; i(assign(rhs)); -} - -const alglib::ae_int_t& alglib::integer_2d_array::operator()(ae_int_t i, ae_int_t j) const -{ - return ptr->ptr.pp_int[i][j]; -} - -alglib::ae_int_t& alglib::integer_2d_array::operator()(ae_int_t i, ae_int_t j) -{ - return ptr->ptr.pp_int[i][j]; -} - -const alglib::ae_int_t* alglib::integer_2d_array::operator[](ae_int_t i) const -{ - return ptr->ptr.pp_int[i]; -} - -alglib::ae_int_t* alglib::integer_2d_array::operator[](ae_int_t i) -{ - return ptr->ptr.pp_int[i]; -} - -void alglib::integer_2d_array::setcontent(ae_int_t irows, ae_int_t icols, const ae_int_t *pContent ) -{ - ae_int_t i, j; - - // setlength(), handle possible exception-free errors - setlength(irows, icols); - if( ptr==NULL || ptr->rows!=irows || ptr->cols!=icols ) - return; - - // copy - for(i=0; iptr.pp_int[i][j] = pContent[i*icols+j]; -} - -#if !defined(AE_NO_EXCEPTIONS) -alglib::integer_2d_array::integer_2d_array(const char *s):ae_matrix_wrapper(s, alglib_impl::DT_INT) -{ -} - -std::string alglib::integer_2d_array::tostring() const -{ - std::string result; - ae_int_t i; - if( isempty() ) - return "[[]]"; - result = "["; - for(i=0; i(assign(rhs)); -} - -const double& alglib::real_2d_array::operator()(ae_int_t i, ae_int_t j) const -{ - return ptr->ptr.pp_double[i][j]; -} - -double& alglib::real_2d_array::operator()(ae_int_t i, ae_int_t j) -{ - return ptr->ptr.pp_double[i][j]; -} - -const double* alglib::real_2d_array::operator[](ae_int_t i) const -{ - return ptr->ptr.pp_double[i]; -} - -double* alglib::real_2d_array::operator[](ae_int_t i) -{ - return ptr->ptr.pp_double[i]; -} - -void alglib::real_2d_array::setcontent(ae_int_t irows, ae_int_t icols, const double *pContent ) -{ - ae_int_t i, j; - - // setlength(), handle possible exception-free errors - setlength(irows, icols); - if( ptr==NULL || ptr->rows!=irows || ptr->cols!=icols ) - return; - - // copy - for(i=0; iptr.pp_double[i][j] = pContent[i*icols+j]; -} - -void alglib::real_2d_array::attach_to_ptr(ae_int_t irows, ae_int_t icols, double *pContent ) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - alglib_impl::x_matrix x; - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - ptr = NULL; - is_frozen_proxy = false; - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(!is_frozen_proxy, "ALGLIB: unable to attach proxy object to something else", &_state); - alglib_impl::ae_assert(irows>0&&icols>0, "ALGLIB: non-positive length for attach_to_ptr()", &_state); - x.rows = irows; - x.cols = icols; - x.stride = icols; - x.datatype = alglib_impl::DT_REAL; - x.owner = alglib_impl::OWN_CALLER; - x.last_action = alglib_impl::ACT_UNCHANGED; - x.x_ptr.p_ptr = pContent; - attach_to(&x, &_state); - ae_state_clear(&_state); -} - -#if !defined(AE_NO_EXCEPTIONS) -alglib::real_2d_array::real_2d_array(const char *s):ae_matrix_wrapper(s, alglib_impl::DT_REAL) -{ -} - -std::string alglib::real_2d_array::tostring(int dps) const -{ - std::string result; - ae_int_t i; - if( isempty() ) - return "[[]]"; - result = "["; - for(i=0; i(assign(rhs)); -} - -const alglib::complex& alglib::complex_2d_array::operator()(ae_int_t i, ae_int_t j) const -{ - return *((const alglib::complex*)(ptr->ptr.pp_complex[i]+j)); -} - -alglib::complex& alglib::complex_2d_array::operator()(ae_int_t i, ae_int_t j) -{ - return *((alglib::complex*)(ptr->ptr.pp_complex[i]+j)); -} - -const alglib::complex* alglib::complex_2d_array::operator[](ae_int_t i) const -{ - return (const alglib::complex*)(ptr->ptr.pp_complex[i]); -} - -alglib::complex* alglib::complex_2d_array::operator[](ae_int_t i) -{ - return (alglib::complex*)(ptr->ptr.pp_complex[i]); -} - -void alglib::complex_2d_array::setcontent(ae_int_t irows, ae_int_t icols, const alglib::complex *pContent ) -{ - ae_int_t i, j; - - // setlength(), handle possible exception-free errors - setlength(irows, icols); - if( ptr==NULL || ptr->rows!=irows || ptr->cols!=icols ) - return; - - // copy - for(i=0; iptr.pp_complex[i][j].x = pContent[i*icols+j].x; - ptr->ptr.pp_complex[i][j].y = pContent[i*icols+j].y; - } -} - -#if !defined(AE_NO_EXCEPTIONS) -alglib::complex_2d_array::complex_2d_array(const char *s):ae_matrix_wrapper(s, alglib_impl::DT_COMPLEX) -{ -} - -std::string alglib::complex_2d_array::tostring(int dps) const -{ - std::string result; - ae_int_t i; - if( isempty() ) - return "[[]]"; - result = "["; - for(i=0; ic2 ) - return +1; - } -} - -#if !defined(AE_NO_EXCEPTIONS) -// -// This function filters out all spaces from the string. -// It returns string allocated with ae_malloc(). -// On allocaction failure returns NULL. -// -char* alglib::filter_spaces(const char *s) -{ - size_t i, n; - char *r; - char *r0; - n = strlen(s); - r = (char*)alglib_impl::ae_malloc(n+1,NULL); - if( r==NULL ) - return r; - for(i=0,r0=r; i<=n; i++,s++) - if( !isspace(*s) ) - { - *r0 = *s; - r0++; - } - return r; -} - -void alglib::str_vector_create(const char *src, bool match_head_only, std::vector *p_vec) -{ - // - // parse beginning of the string. - // try to handle "[]" string - // - p_vec->clear(); - if( *src!='[' ) - _ALGLIB_CPP_EXCEPTION("Incorrect initializer for vector"); - src++; - if( *src==']' ) - return; - p_vec->push_back(src); - for(;;) - { - if( *src==0 ) - _ALGLIB_CPP_EXCEPTION("Incorrect initializer for vector"); - if( *src==']' ) - { - if( src[1]==0 || !match_head_only) - return; - _ALGLIB_CPP_EXCEPTION("Incorrect initializer for vector"); - } - if( *src==',' ) - { - p_vec->push_back(src+1); - src++; - continue; - } - src++; - } -} - -void alglib::str_matrix_create(const char *src, std::vector< std::vector > *p_mat) -{ - p_mat->clear(); - - // - // Try to handle "[[]]" string - // - if( strcmp(src, "[[]]")==0 ) - return; - - // - // Parse non-empty string - // - if( *src!='[' ) - _ALGLIB_CPP_EXCEPTION("Incorrect initializer for matrix"); - src++; - for(;;) - { - p_mat->push_back(std::vector()); - str_vector_create(src, false, &p_mat->back()); - if( p_mat->back().size()==0 || p_mat->back().size()!=(*p_mat)[0].size() ) - _ALGLIB_CPP_EXCEPTION("Incorrect initializer for matrix"); - src = strchr(src, ']'); - if( src==NULL ) - _ALGLIB_CPP_EXCEPTION("Incorrect initializer for matrix"); - src++; - if( *src==',' ) - { - src++; - continue; - } - if( *src==']' ) - break; - _ALGLIB_CPP_EXCEPTION("Incorrect initializer for matrix"); - } - src++; - if( *src!=0 ) - _ALGLIB_CPP_EXCEPTION("Incorrect initializer for matrix"); -} - -ae_bool alglib::parse_bool_delim(const char *s, const char *delim) -{ - const char *p; - char buf[8]; - - // try to parse false - p = "false"; - memset(buf, 0, sizeof(buf)); - strncpy(buf, s, strlen(p)); - if( my_stricmp(buf, p)==0 ) - { - if( s[strlen(p)]==0 || strchr(delim,s[strlen(p)])==NULL ) - _ALGLIB_CPP_EXCEPTION("Cannot parse value"); - return ae_false; - } - - // try to parse true - p = "true"; - memset(buf, 0, sizeof(buf)); - strncpy(buf, s, strlen(p)); - if( my_stricmp(buf, p)==0 ) - { - if( s[strlen(p)]==0 || strchr(delim,s[strlen(p)])==NULL ) - _ALGLIB_CPP_EXCEPTION("Cannot parse value"); - return ae_true; - } - - // error - _ALGLIB_CPP_EXCEPTION("Cannot parse value"); -} - -alglib::ae_int_t alglib::parse_int_delim(const char *s, const char *delim) -{ - const char *p; - long long_val; - volatile ae_int_t ae_val; - - p = s; - - // - // check string structure: - // * leading sign - // * at least one digit - // * delimiter - // - if( *s=='-' || *s=='+' ) - s++; - if( *s==0 || strchr("1234567890",*s)==NULL) - _ALGLIB_CPP_EXCEPTION("Cannot parse value"); - while( *s!=0 && strchr("1234567890",*s)!=NULL ) - s++; - if( *s==0 || strchr(delim,*s)==NULL ) - _ALGLIB_CPP_EXCEPTION("Cannot parse value"); - - // convert and ensure that value fits into ae_int_t - s = p; - long_val = atol(s); - ae_val = long_val; - if( ae_val!=long_val ) - _ALGLIB_CPP_EXCEPTION("Cannot parse value"); - return ae_val; -} - -bool alglib::_parse_real_delim(const char *s, const char *delim, double *result, const char **new_s) -{ - const char *p; - char *t; - bool has_digits; - char buf[64]; - int isign; - lconv *loc; - - p = s; - - // - // check string structure and decide what to do - // - isign = 1; - if( *s=='-' || *s=='+' ) - { - isign = *s=='-' ? -1 : +1; - s++; - } - memset(buf, 0, sizeof(buf)); - strncpy(buf, s, 3); - if( my_stricmp(buf,"nan")!=0 && my_stricmp(buf,"inf")!=0 ) - { - // - // [sign] [ddd] [.] [ddd] [e|E[sign]ddd] - // - has_digits = false; - if( *s!=0 && strchr("1234567890",*s)!=NULL ) - { - has_digits = true; - while( *s!=0 && strchr("1234567890",*s)!=NULL ) - s++; - } - if( *s=='.' ) - s++; - if( *s!=0 && strchr("1234567890",*s)!=NULL ) - { - has_digits = true; - while( *s!=0 && strchr("1234567890",*s)!=NULL ) - s++; - } - if (!has_digits ) - return false; - if( *s=='e' || *s=='E' ) - { - s++; - if( *s=='-' || *s=='+' ) - s++; - if( *s==0 || strchr("1234567890",*s)==NULL ) - return false; - while( *s!=0 && strchr("1234567890",*s)!=NULL ) - s++; - } - if( *s==0 || strchr(delim,*s)==NULL ) - return false; - *new_s = s; - - // - // finite value conversion - // - if( *new_s-p>=(int)sizeof(buf) ) - return false; - strncpy(buf, p, (size_t)(*new_s-p)); - buf[*new_s-p] = 0; - loc = localeconv(); - t = strchr(buf,'.'); - if( t!=NULL ) - *t = *loc->decimal_point; - *result = atof(buf); - return true; - } - else - { - // - // check delimiter and update *new_s - // - s += 3; - if( *s==0 || strchr(delim,*s)==NULL ) - return false; - *new_s = s; - - // - // NAN, INF conversion - // - if( my_stricmp(buf,"nan")==0 ) - *result = fp_nan; - if( my_stricmp(buf,"inf")==0 ) - *result = isign>0 ? fp_posinf : fp_neginf; - return true; - } -} - -double alglib::parse_real_delim(const char *s, const char *delim) -{ - double result; - const char *new_s; - if( !_parse_real_delim(s, delim, &result, &new_s) ) - _ALGLIB_CPP_EXCEPTION("Cannot parse value"); - return result; -} - -alglib::complex alglib::parse_complex_delim(const char *s, const char *delim) -{ - double d_result; - const char *new_s; - alglib::complex c_result; - - // parse as real value - if( _parse_real_delim(s, delim, &d_result, &new_s) ) - return d_result; - - // parse as "a+bi" or "a-bi" - if( _parse_real_delim(s, "+-", &c_result.x, &new_s) ) - { - s = new_s; - if( !_parse_real_delim(s, "i", &c_result.y, &new_s) ) - _ALGLIB_CPP_EXCEPTION("Cannot parse value"); - s = new_s+1; - if( *s==0 || strchr(delim,*s)==NULL ) - _ALGLIB_CPP_EXCEPTION("Cannot parse value"); - return c_result; - } - - // parse as complex value "bi+a" or "bi-a" - if( _parse_real_delim(s, "i", &c_result.y, &new_s) ) - { - s = new_s+1; - if( *s==0 ) - _ALGLIB_CPP_EXCEPTION("Cannot parse value"); - if( strchr(delim,*s)!=NULL ) - { - c_result.x = 0; - return c_result; - } - if( strchr("+-",*s)!=NULL ) - { - if( !_parse_real_delim(s, delim, &c_result.x, &new_s) ) - _ALGLIB_CPP_EXCEPTION("Cannot parse value"); - return c_result; - } - _ALGLIB_CPP_EXCEPTION("Cannot parse value"); - } - - // error - _ALGLIB_CPP_EXCEPTION("Cannot parse value"); -} - -std::string alglib::arraytostring(const bool *ptr, ae_int_t n) -{ - std::string result; - ae_int_t i; - result = "["; - for(i=0; i=(int)sizeof(buf) ) - _ALGLIB_CPP_EXCEPTION("arraytostring(): buffer overflow"); - result += buf; - } - result += "]"; - return result; -} - -std::string alglib::arraytostring(const double *ptr, ae_int_t n, int _dps) -{ - std::string result; - ae_int_t i; - char buf[64]; - char mask1[64]; - char mask2[64]; - int dps = _dps>=0 ? _dps : -_dps; - result = "["; - if( sprintf(mask1, "%%.%d%s", dps, _dps>=0 ? "f" : "e")>=(int)sizeof(mask1) ) - _ALGLIB_CPP_EXCEPTION("arraytostring(): buffer overflow"); - if( sprintf(mask2, ",%s", mask1)>=(int)sizeof(mask2) ) - _ALGLIB_CPP_EXCEPTION("arraytostring(): buffer overflow"); - for(i=0; i=(int)sizeof(buf) ) - _ALGLIB_CPP_EXCEPTION("arraytostring(): buffer overflow"); - } - else if( fp_isnan(ptr[i]) ) - strcpy(buf, i==0 ? "NAN" : ",NAN"); - else if( fp_isposinf(ptr[i]) ) - strcpy(buf, i==0 ? "+INF" : ",+INF"); - else if( fp_isneginf(ptr[i]) ) - strcpy(buf, i==0 ? "-INF" : ",-INF"); - result += buf; - } - result += "]"; - return result; -} - -std::string alglib::arraytostring(const alglib::complex *ptr, ae_int_t n, int dps) -{ - std::string result; - ae_int_t i; - result = "["; - for(i=0; i0 ) return 1; - if( x<0 ) return -1; - return 0; -} - -double alglib::randomreal() -{ - int i1 = rand(); - int i2 = rand(); - double mx = (double)(RAND_MAX)+1.0; - volatile double tmp0 = i2/mx; - volatile double tmp1 = i1+tmp0; - return tmp1/mx; -} - -alglib::ae_int_t alglib::randominteger(alglib::ae_int_t maxv) -{ - return ((alglib::ae_int_t)rand())%maxv; -} - -int alglib::round(double x) -{ return int(floor(x+0.5)); } - -int alglib::trunc(double x) -{ return int(x>0 ? floor(x) : ceil(x)); } - -int alglib::ifloor(double x) -{ return int(floor(x)); } - -int alglib::iceil(double x) -{ return int(ceil(x)); } - -double alglib::pi() -{ return 3.14159265358979323846; } - -double alglib::sqr(double x) -{ return x*x; } - -int alglib::maxint(int m1, int m2) -{ - return m1>m2 ? m1 : m2; -} - -int alglib::minint(int m1, int m2) -{ - return m1>m2 ? m2 : m1; -} - -double alglib::maxreal(double m1, double m2) -{ - return m1>m2 ? m1 : m2; -} - -double alglib::minreal(double m1, double m2) -{ - return m1>m2 ? m2 : m1; -} - -bool alglib::fp_eq(double v1, double v2) -{ - // IEEE-strict floating point comparison - volatile double x = v1; - volatile double y = v2; - return x==y; -} - -bool alglib::fp_neq(double v1, double v2) -{ - // IEEE-strict floating point comparison - return !fp_eq(v1,v2); -} - -bool alglib::fp_less(double v1, double v2) -{ - // IEEE-strict floating point comparison - volatile double x = v1; - volatile double y = v2; - return xy; -} - -bool alglib::fp_greater_eq(double v1, double v2) -{ - // IEEE-strict floating point comparison - volatile double x = v1; - volatile double y = v2; - return x>=y; -} - -bool alglib::fp_isnan(double x) -{ - return alglib_impl::ae_isnan_stateless(x,endianness); -} - -bool alglib::fp_isposinf(double x) -{ - return alglib_impl::ae_isposinf_stateless(x,endianness); -} - -bool alglib::fp_isneginf(double x) -{ - return alglib_impl::ae_isneginf_stateless(x,endianness); -} - -bool alglib::fp_isinf(double x) -{ - return alglib_impl::ae_isinf_stateless(x,endianness); -} - -bool alglib::fp_isfinite(double x) -{ - return alglib_impl::ae_isfinite_stateless(x,endianness); -} - -/******************************************************************** -CSV functions -********************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void alglib::read_csv(const char *filename, char separator, int flags, alglib::real_2d_array &out) -{ - int flag; - - // - // Parameters - // - bool skip_first_row = (flags&CSV_SKIP_HEADERS)!=0; - - // - // Prepare empty output array - // - out.setlength(0,0); - - // - // Open file, determine size, read contents - // - FILE *f_in = fopen(filename, "rb"); - if( f_in==NULL ) - _ALGLIB_CPP_EXCEPTION("read_csv: unable to open input file"); - flag = fseek(f_in, 0, SEEK_END); - AE_CRITICAL_ASSERT(flag==0); - long int _filesize = ftell(f_in); - AE_CRITICAL_ASSERT(_filesize>=0); - if( _filesize==0 ) - { - // empty file, return empty array, success - fclose(f_in); - return; - } - size_t filesize = _filesize; - std::vector v_buf; - v_buf.resize(filesize+2, 0); - char *p_buf = &v_buf[0]; - flag = fseek(f_in, 0, SEEK_SET); - AE_CRITICAL_ASSERT(flag==0); - size_t bytes_read = fread ((void*)p_buf, 1, filesize, f_in); - AE_CRITICAL_ASSERT(bytes_read==filesize); - fclose(f_in); - - // - // Normalize file contents: - // * replace 0x0 by spaces - // * remove trailing spaces and newlines - // * append trailing '\n' and '\0' characters - // Return if file contains only spaces/newlines. - // - for(size_t i=0; i0; ) - { - char c = p_buf[filesize-1]; - if( c==' ' || c=='\t' || c=='\n' || c=='\r' ) - { - filesize--; - continue; - } - break; - } - if( filesize==0 ) - return; - p_buf[filesize+0] = '\n'; - p_buf[filesize+1] = '\0'; - filesize+=2; - - // - // Scan dataset. - // - size_t rows_count = 0, cols_count = 0, max_length = 0; - std::vector offsets, lengths; - for(size_t row_start=0; p_buf[row_start]!=0x0; ) - { - // determine row length - size_t row_length; - for(row_length=0; p_buf[row_start+row_length]!='\n'; row_length++); - - // determine cols count, perform integrity check - size_t cur_cols_cnt=1; - for(size_t idx=0; idx0 && cols_count!=cur_cols_cnt ) - _ALGLIB_CPP_EXCEPTION("read_csv: non-rectangular contents, rows have different sizes"); - cols_count = cur_cols_cnt; - - // store offsets and lengths of the fields - size_t cur_offs = 0; - for(size_t idx=0; idxmax_length ? idx-cur_offs : max_length; - cur_offs = idx+1; - } - - // advance row start - rows_count++; - row_start = row_start+row_length+1; - } - AE_CRITICAL_ASSERT(rows_count>=1); - AE_CRITICAL_ASSERT(cols_count>=1); - AE_CRITICAL_ASSERT(cols_count*rows_count==offsets.size()); - AE_CRITICAL_ASSERT(cols_count*rows_count==lengths.size()); - if( rows_count==1 && skip_first_row ) // empty output, return - return; - - // - // Convert - // - size_t row0 = skip_first_row ? 1 : 0; - size_t row1 = rows_count; - lconv *loc = localeconv(); - out.setlength(row1-row0, cols_count); - for(size_t ridx=row0; ridxdecimal_point; - out[ridx-row0][cidx] = atof(p_field); - } -} -#endif - - - -/******************************************************************** -Trace functions -********************************************************************/ -void alglib::trace_file(std::string tags, std::string filename) -{ - alglib_impl::ae_trace_file(tags.c_str(), filename.c_str()); -} - -void alglib::trace_disable() -{ - alglib_impl::ae_trace_disable(); -} - - - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTIONS CONTAINS OPTIMIZED LINEAR ALGEBRA CODE -// IT IS SHARED BETWEEN C++ AND PURE C LIBRARIES -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#define alglib_simd_alignment 16 - -#define alglib_r_block 32 -#define alglib_half_r_block 16 -#define alglib_twice_r_block 64 - -#define alglib_c_block 16 -#define alglib_half_c_block 8 -#define alglib_twice_c_block 32 - - -/******************************************************************** -This subroutine calculates fast 32x32 real matrix-vector product: - - y := beta*y + alpha*A*x - -using either generic C code or native optimizations (if available) - -IMPORTANT: -* A must be stored in row-major order, - stride is alglib_r_block, - aligned on alglib_simd_alignment boundary -* X must be aligned on alglib_simd_alignment boundary -* Y may be non-aligned -********************************************************************/ -void _ialglib_mv_32(const double *a, const double *x, double *y, ae_int_t stride, double alpha, double beta) -{ - ae_int_t i, k; - const double *pa0, *pa1, *pb; - - pa0 = a; - pa1 = a+alglib_r_block; - pb = x; - for(i=0; i<16; i++) - { - double v0 = 0, v1 = 0; - for(k=0; k<4; k++) - { - v0 += pa0[0]*pb[0]; - v1 += pa1[0]*pb[0]; - v0 += pa0[1]*pb[1]; - v1 += pa1[1]*pb[1]; - v0 += pa0[2]*pb[2]; - v1 += pa1[2]*pb[2]; - v0 += pa0[3]*pb[3]; - v1 += pa1[3]*pb[3]; - v0 += pa0[4]*pb[4]; - v1 += pa1[4]*pb[4]; - v0 += pa0[5]*pb[5]; - v1 += pa1[5]*pb[5]; - v0 += pa0[6]*pb[6]; - v1 += pa1[6]*pb[6]; - v0 += pa0[7]*pb[7]; - v1 += pa1[7]*pb[7]; - pa0 += 8; - pa1 += 8; - pb += 8; - } - y[0] = beta*y[0]+alpha*v0; - y[stride] = beta*y[stride]+alpha*v1; - - /* - * now we've processed rows I and I+1, - * pa0 and pa1 are pointing to rows I+1 and I+2. - * move to I+2 and I+3. - */ - pa0 += alglib_r_block; - pa1 += alglib_r_block; - pb = x; - y+=2*stride; - } -} - - -/************************************************************************* -This function calculates MxN real matrix-vector product: - - y := beta*y + alpha*A*x - -using generic C code. It calls _ialglib_mv_32 if both M=32 and N=32. - -If beta is zero, we do not use previous values of y (they are overwritten -by alpha*A*x without ever being read). If alpha is zero, no matrix-vector -product is calculated (only beta is updated); however, this update is not -efficient and this function should NOT be used for multiplication of -vector and scalar. - -IMPORTANT: -* 0<=M<=alglib_r_block, 0<=N<=alglib_r_block -* A must be stored in row-major order with stride equal to alglib_r_block -*************************************************************************/ -void _ialglib_rmv(ae_int_t m, ae_int_t n, const double *a, const double *x, double *y, ae_int_t stride, double alpha, double beta) -{ - /* - * Handle special cases: - * - alpha is zero or n is zero - * - m is zero - */ - if( m==0 ) - return; - if( alpha==0.0 || n==0 ) - { - ae_int_t i; - if( beta==0.0 ) - { - for(i=0; ix-beta.y*cy->y)+(alpha.x*v0-alpha.y*v1); - double ty = (beta.x*cy->y+beta.y*cy->x)+(alpha.x*v1+alpha.y*v0); - cy->x = tx; - cy->y = ty; - cy+=stride; - } - else - { - double tx = (beta.x*dy[0]-beta.y*dy[1])+(alpha.x*v0-alpha.y*v1); - double ty = (beta.x*dy[1]+beta.y*dy[0])+(alpha.x*v1+alpha.y*v0); - dy[0] = tx; - dy[1] = ty; - dy += 2*stride; - } - parow += 2*alglib_c_block; - } -} - - -/************************************************************************* -This subroutine calculates fast MxN complex matrix-vector product: - - y := beta*y + alpha*A*x - -using generic C code, where A, x, y, alpha and beta are complex. - -If beta is zero, we do not use previous values of y (they are overwritten -by alpha*A*x without ever being read). However, when alpha is zero, we -still calculate A*x and multiply it by alpha (this distinction can be -important when A or x contain infinities/NANs). - -IMPORTANT: -* 0<=M<=alglib_c_block, 0<=N<=alglib_c_block -* A must be stored in row-major order, as sequence of double precision - pairs. Stride is alglib_c_block (it is measured in pairs of doubles, not - in doubles). -* Y may be referenced by cy (pointer to ae_complex) or - dy (pointer to array of double precision pair) depending on what type of - output you wish. Pass pointer to Y as one of these parameters, - AND SET OTHER PARAMETER TO NULL. -* both A and x must be aligned; y may be non-aligned. - -This function supports SSE2; it can be used when: -1. AE_HAS_SSE2_INTRINSICS was defined (checked at compile-time) -2. ae_cpuid() result contains CPU_SSE2 (checked at run-time) - -If (1) is failed, this function will be undefined. If (2) is failed, call -to this function will probably crash your system. - -If you want to know whether it is safe to call it, you should check -results of ae_cpuid(). If CPU_SSE2 bit is set, this function is callable -and will do its work. -*************************************************************************/ -#if defined(AE_HAS_SSE2_INTRINSICS) -void _ialglib_cmv_sse2(ae_int_t m, ae_int_t n, const double *a, const double *x, ae_complex *cy, double *dy, ae_int_t stride, ae_complex alpha, ae_complex beta) -{ - ae_int_t i, j, m2; - const double *pa0, *pa1, *parow, *pb; - __m128d vbeta, vbetax, vbetay; - __m128d valpha, valphax, valphay; - - m2 = m/2; - parow = a; - if( cy!=NULL ) - { - dy = (double*)cy; - cy = NULL; - } - vbeta = _mm_loadh_pd(_mm_load_sd(&beta.x),&beta.y); - vbetax = _mm_unpacklo_pd(vbeta,vbeta); - vbetay = _mm_unpackhi_pd(vbeta,vbeta); - valpha = _mm_loadh_pd(_mm_load_sd(&alpha.x),&alpha.y); - valphax = _mm_unpacklo_pd(valpha,valpha); - valphay = _mm_unpackhi_pd(valpha,valpha); - for(i=0; ix = 0.0; - p->y = 0.0; - } - } - else - { - for(i=0; ix = 0.0; - p->y = 0.0; - } - } -} - - -/******************************************************************** -This subroutine copies unaligned real vector -********************************************************************/ -void _ialglib_vcopy(ae_int_t n, const double *a, ae_int_t stridea, double *b, ae_int_t strideb) -{ - ae_int_t i, n2; - if( stridea==1 && strideb==1 ) - { - n2 = n/2; - for(i=n2; i!=0; i--, a+=2, b+=2) - { - b[0] = a[0]; - b[1] = a[1]; - } - if( n%2!=0 ) - b[0] = a[0]; - } - else - { - for(i=0; ix; - b[1] = a->y; - } - } - else - { - for(i=0; ix; - b[1] = -a->y; - } - } -} - - -/******************************************************************** -This subroutine copies unaligned complex vector (passed as double*) - -1. strideb is stride measured in complex numbers, not doubles -2. conj may be "N" (no conj.) or "C" (conj.) -********************************************************************/ -void _ialglib_vcopy_dcomplex(ae_int_t n, const double *a, ae_int_t stridea, double *b, ae_int_t strideb, const char *conj) -{ - ae_int_t i; - - /* - * more general case - */ - if( conj[0]=='N' || conj[0]=='n' ) - { - for(i=0; ix; - pdst[1] = psrc->y; - } - } - if( op==1 ) - { - for(i=0,psrc=a; ix; - pdst[1] = psrc->y; - } - } - if( op==2 ) - { - for(i=0,psrc=a; ix; - pdst[1] = -psrc->y; - } - } - if( op==3 ) - { - for(i=0,psrc=a; ix; - pdst[1] = -psrc->y; - } - } -} - - -/******************************************************************** -This subroutine copies matrix from aligned contigous storage to -non-aligned non-contigous storage - -A: -* 2*alglib_c_block*alglib_c_block doubles (only MxN submatrix is used) -* aligned -* stride is alglib_c_block -* pointer to double is passed -* may be transformed during copying (as prescribed by op) - -B: -* MxN -* non-aligned -* non-contigous -* pointer to ae_complex is passed - -Transformation types: -* 0 - no transform -* 1 - transposition -* 2 - conjugate transposition -* 3 - conjugate, but no transposition -********************************************************************/ -void _ialglib_mcopyunblock_complex(ae_int_t m, ae_int_t n, const double *a, ae_int_t op, ae_complex* b, ae_int_t stride) -{ - ae_int_t i, j; - const double *psrc; - ae_complex *pdst; - if( op==0 ) - { - for(i=0,psrc=a; ix = psrc[0]; - pdst->y = psrc[1]; - } - } - if( op==1 ) - { - for(i=0,psrc=a; ix = psrc[0]; - pdst->y = psrc[1]; - } - } - if( op==2 ) - { - for(i=0,psrc=a; ix = psrc[0]; - pdst->y = -psrc[1]; - } - } - if( op==3 ) - { - for(i=0,psrc=a; ix = psrc[0]; - pdst->y = -psrc[1]; - } - } -} - - -/******************************************************************** -Real GEMM kernel -********************************************************************/ -ae_bool _ialglib_rmatrixgemm(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - double *_a, - ae_int_t _a_stride, - ae_int_t optypea, - double *_b, - ae_int_t _b_stride, - ae_int_t optypeb, - double beta, - double *_c, - ae_int_t _c_stride) -{ - int i; - double *crow; - double _abuf[alglib_r_block+alglib_simd_alignment]; - double _bbuf[alglib_r_block*alglib_r_block+alglib_simd_alignment]; - double * const abuf = (double * ) ae_align(_abuf,alglib_simd_alignment); - double * const b = (double * ) ae_align(_bbuf,alglib_simd_alignment); - void (*rmv)(ae_int_t, ae_int_t, const double *, const double *, double *, ae_int_t, double, double) = &_ialglib_rmv; - void (*mcopyblock)(ae_int_t, ae_int_t, const double *, ae_int_t, ae_int_t, double *) = &_ialglib_mcopyblock; - - if( m>alglib_r_block || n>alglib_r_block || k>alglib_r_block || m<=0 || n<=0 || k<=0 || alpha==0.0 ) - return ae_false; - - /* - * Check for SSE2 support - */ -#ifdef AE_HAS_SSE2_INTRINSICS - if( ae_cpuid() & CPU_SSE2 ) - { - rmv = &_ialglib_rmv_sse2; - mcopyblock = &_ialglib_mcopyblock_sse2; - } -#endif - - /* - * copy b - */ - if( optypeb==0 ) - mcopyblock(k, n, _b, 1, _b_stride, b); - else - mcopyblock(n, k, _b, 0, _b_stride, b); - - /* - * multiply B by A (from the right, by rows) - * and store result in C - */ - crow = _c; - if( optypea==0 ) - { - const double *arow = _a; - for(i=0; ialglib_c_block || n>alglib_c_block || k>alglib_c_block ) - return ae_false; - - /* - * Check for SSE2 support - */ -#ifdef AE_HAS_SSE2_INTRINSICS - if( ae_cpuid() & CPU_SSE2 ) - { - cmv = &_ialglib_cmv_sse2; - } -#endif - - /* - * copy b - */ - brows = optypeb==0 ? k : n; - bcols = optypeb==0 ? n : k; - if( optypeb==0 ) - _ialglib_mcopyblock_complex(brows, bcols, _b, 1, _b_stride, b); - if( optypeb==1 ) - _ialglib_mcopyblock_complex(brows, bcols, _b, 0, _b_stride, b); - if( optypeb==2 ) - _ialglib_mcopyblock_complex(brows, bcols, _b, 3, _b_stride, b); - - /* - * multiply B by A (from the right, by rows) - * and store result in C - */ - arow = _a; - crow = _c; - for(i=0; ialglib_c_block || n>alglib_c_block ) - return ae_false; - - /* - * Check for SSE2 support - */ -#ifdef AE_HAS_SSE2_INTRINSICS - if( ae_cpuid() & CPU_SSE2 ) - { - cmv = &_ialglib_cmv_sse2; - } -#endif - - /* - * Prepare - */ - _ialglib_mcopyblock_complex(n, n, _a, optype, _a_stride, abuf); - _ialglib_mcopyblock_complex(m, n, _x, 0, _x_stride, xbuf); - if( isunit ) - for(i=0,pdiag=abuf; i=0; i--,pdiag-=2*(alglib_c_block+1)) - { - ae_complex tmp_c; - ae_complex beta; - ae_complex alpha; - tmp_c.x = pdiag[0]; - tmp_c.y = pdiag[1]; - beta = ae_c_d_div(1.0, tmp_c); - alpha.x = -beta.x; - alpha.y = -beta.y; - _ialglib_vcopy_dcomplex(n-1-i, pdiag+2*alglib_c_block, alglib_c_block, tmpbuf, 1, "No conj"); - cmv(m, n-1-i, xbuf+2*(i+1), tmpbuf, NULL, xbuf+2*i, alglib_c_block, alpha, beta); - } - _ialglib_mcopyunblock_complex(m, n, xbuf, 0, _x, _x_stride); - } - return ae_true; -} - - -/******************************************************************** -real TRSM kernel -********************************************************************/ -ae_bool _ialglib_rmatrixrighttrsm(ae_int_t m, - ae_int_t n, - double *_a, - ae_int_t _a_stride, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - double *_x, - ae_int_t _x_stride) -{ - /* - * local buffers - */ - double *pdiag; - ae_int_t i; - double _loc_abuf[alglib_r_block*alglib_r_block+alglib_simd_alignment]; - double _loc_xbuf[alglib_r_block*alglib_r_block+alglib_simd_alignment]; - double _loc_tmpbuf[alglib_r_block+alglib_simd_alignment]; - double * const abuf = (double *) ae_align(_loc_abuf, alglib_simd_alignment); - double * const xbuf = (double *) ae_align(_loc_xbuf, alglib_simd_alignment); - double * const tmpbuf = (double *) ae_align(_loc_tmpbuf,alglib_simd_alignment); - ae_bool uppera; - void (*rmv)(ae_int_t, ae_int_t, const double *, const double *, double *, ae_int_t, double, double) = &_ialglib_rmv; - void (*mcopyblock)(ae_int_t, ae_int_t, const double *, ae_int_t, ae_int_t, double *) = &_ialglib_mcopyblock; - - if( m>alglib_r_block || n>alglib_r_block ) - return ae_false; - - /* - * Check for SSE2 support - */ -#ifdef AE_HAS_SSE2_INTRINSICS - if( ae_cpuid() & CPU_SSE2 ) - { - rmv = &_ialglib_rmv_sse2; - mcopyblock = &_ialglib_mcopyblock_sse2; - } -#endif - - /* - * Prepare - */ - mcopyblock(n, n, _a, optype, _a_stride, abuf); - mcopyblock(m, n, _x, 0, _x_stride, xbuf); - if( isunit ) - for(i=0,pdiag=abuf; i=0; i--,pdiag-=alglib_r_block+1) - { - double beta = 1.0/(*pdiag); - double alpha = -beta; - _ialglib_vcopy(n-1-i, pdiag+alglib_r_block, alglib_r_block, tmpbuf+i+1, 1); - rmv(m, n-1-i, xbuf+i+1, tmpbuf+i+1, xbuf+i, alglib_r_block, alpha, beta); - } - _ialglib_mcopyunblock(m, n, xbuf, 0, _x, _x_stride); - } - return ae_true; -} - - -/******************************************************************** -complex TRSM kernel -********************************************************************/ -ae_bool _ialglib_cmatrixlefttrsm(ae_int_t m, - ae_int_t n, - ae_complex *_a, - ae_int_t _a_stride, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - ae_complex *_x, - ae_int_t _x_stride) -{ - /* - * local buffers - */ - double *pdiag, *arow; - ae_int_t i; - double _loc_abuf[2*alglib_c_block*alglib_c_block+alglib_simd_alignment]; - double _loc_xbuf[2*alglib_c_block*alglib_c_block+alglib_simd_alignment]; - double _loc_tmpbuf[2*alglib_c_block+alglib_simd_alignment]; - double * const abuf = (double *) ae_align(_loc_abuf, alglib_simd_alignment); - double * const xbuf = (double *) ae_align(_loc_xbuf, alglib_simd_alignment); - double * const tmpbuf = (double *) ae_align(_loc_tmpbuf,alglib_simd_alignment); - ae_bool uppera; - void (*cmv)(ae_int_t, ae_int_t, const double *, const double *, ae_complex *, double *, ae_int_t, ae_complex, ae_complex) = &_ialglib_cmv; - - if( m>alglib_c_block || n>alglib_c_block ) - return ae_false; - - /* - * Check for SSE2 support - */ -#ifdef AE_HAS_SSE2_INTRINSICS - if( ae_cpuid() & CPU_SSE2 ) - { - cmv = &_ialglib_cmv_sse2; - } -#endif - - /* - * Prepare - * Transpose X (so we may use mv, which calculates A*x, but not x*A) - */ - _ialglib_mcopyblock_complex(m, m, _a, optype, _a_stride, abuf); - _ialglib_mcopyblock_complex(m, n, _x, 1, _x_stride, xbuf); - if( isunit ) - for(i=0,pdiag=abuf; i=0; i--,pdiag-=2*(alglib_c_block+1)) - { - ae_complex tmp_c; - ae_complex beta; - ae_complex alpha; - tmp_c.x = pdiag[0]; - tmp_c.y = pdiag[1]; - beta = ae_c_d_div(1.0, tmp_c); - alpha.x = -beta.x; - alpha.y = -beta.y; - _ialglib_vcopy_dcomplex(m-1-i, pdiag+2, 1, tmpbuf, 1, "No conj"); - cmv(n, m-1-i, xbuf+2*(i+1), tmpbuf, NULL, xbuf+2*i, alglib_c_block, alpha, beta); - } - _ialglib_mcopyunblock_complex(m, n, xbuf, 1, _x, _x_stride); - } - else - { for(i=0,pdiag=abuf,arow=abuf; ialglib_r_block || n>alglib_r_block ) - return ae_false; - - /* - * Check for SSE2 support - */ -#ifdef AE_HAS_SSE2_INTRINSICS - if( ae_cpuid() & CPU_SSE2 ) - { - rmv = &_ialglib_rmv_sse2; - mcopyblock = &_ialglib_mcopyblock_sse2; - } -#endif - - /* - * Prepare - * Transpose X (so we may use mv, which calculates A*x, but not x*A) - */ - mcopyblock(m, m, _a, optype, _a_stride, abuf); - mcopyblock(m, n, _x, 1, _x_stride, xbuf); - if( isunit ) - for(i=0,pdiag=abuf; i=0; i--,pdiag-=alglib_r_block+1) - { - double beta = 1.0/(*pdiag); - double alpha = -beta; - _ialglib_vcopy(m-1-i, pdiag+1, 1, tmpbuf+i+1, 1); - rmv(n, m-1-i, xbuf+i+1, tmpbuf+i+1, xbuf+i, alglib_r_block, alpha, beta); - } - _ialglib_mcopyunblock(m, n, xbuf, 1, _x, _x_stride); - } - else - { for(i=0,pdiag=abuf,arow=abuf; ialglib_c_block || k>alglib_c_block ) - return ae_false; - if( n==0 ) - return ae_true; - - /* - * copy A and C, task is transformed to "A*A^H"-form. - * if beta==0, then C is filled by zeros (and not referenced) - * - * alpha==0 or k==0 are correctly processed (A is not referenced) - */ - c_alpha.x = alpha; - c_alpha.y = 0; - c_beta.x = beta; - c_beta.y = 0; - if( alpha==0 ) - k = 0; - if( k>0 ) - { - if( optypea==0 ) - _ialglib_mcopyblock_complex(n, k, _a, 3, _a_stride, abuf); - else - _ialglib_mcopyblock_complex(k, n, _a, 1, _a_stride, abuf); - } - _ialglib_mcopyblock_complex(n, n, _c, 0, _c_stride, cbuf); - if( beta==0 ) - { - for(i=0,crow=cbuf; ialglib_r_block || k>alglib_r_block ) - return ae_false; - if( n==0 ) - return ae_true; - - /* - * copy A and C, task is transformed to "A*A^T"-form. - * if beta==0, then C is filled by zeros (and not referenced) - * - * alpha==0 or k==0 are correctly processed (A is not referenced) - */ - if( alpha==0 ) - k = 0; - if( k>0 ) - { - if( optypea==0 ) - _ialglib_mcopyblock(n, k, _a, 0, _a_stride, abuf); - else - _ialglib_mcopyblock(k, n, _a, 1, _a_stride, abuf); - } - _ialglib_mcopyblock(n, n, _c, 0, _c_stride, cbuf); - if( beta==0 ) - { - for(i=0,crow=cbuf; iptr.pp_double[ia]+ja, _a->stride, optypea, _b->ptr.pp_double[ib]+jb, _b->stride, optypeb, beta, _c->ptr.pp_double[ic]+jc, _c->stride); -} - -ae_bool _ialglib_i_cmatrixgemmf(ae_int_t m, - ae_int_t n, - ae_int_t k, - ae_complex alpha, - ae_matrix *_a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - ae_matrix *_b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - ae_complex beta, - ae_matrix *_c, - ae_int_t ic, - ae_int_t jc) -{ - /* handle degenerate cases like zero matrices by ALGLIB - greatly simplifies passing data to ALGLIB kernel */ - if( (alpha.x==0.0 && alpha.y==0) || k==0 || n==0 || m==0 ) - return ae_false; - - /* handle with optimized ALGLIB kernel */ - return _ialglib_cmatrixgemm(m, n, k, alpha, _a->ptr.pp_complex[ia]+ja, _a->stride, optypea, _b->ptr.pp_complex[ib]+jb, _b->stride, optypeb, beta, _c->ptr.pp_complex[ic]+jc, _c->stride); -} - -ae_bool _ialglib_i_cmatrixrighttrsmf(ae_int_t m, - ae_int_t n, - ae_matrix *a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - ae_matrix *x, - ae_int_t i2, - ae_int_t j2) -{ - /* handle degenerate cases like zero matrices by ALGLIB - greatly simplifies passing data to ALGLIB kernel */ - if( m==0 || n==0) - return ae_false; - - /* handle with optimized ALGLIB kernel */ - return _ialglib_cmatrixrighttrsm(m, n, &a->ptr.pp_complex[i1][j1], a->stride, isupper, isunit, optype, &x->ptr.pp_complex[i2][j2], x->stride); -} - -ae_bool _ialglib_i_rmatrixrighttrsmf(ae_int_t m, - ae_int_t n, - ae_matrix *a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - ae_matrix *x, - ae_int_t i2, - ae_int_t j2) -{ - /* handle degenerate cases like zero matrices by ALGLIB - greatly simplifies passing data to ALGLIB kernel */ - if( m==0 || n==0) - return ae_false; - - /* handle with optimized ALGLIB kernel */ - return _ialglib_rmatrixrighttrsm(m, n, &a->ptr.pp_double[i1][j1], a->stride, isupper, isunit, optype, &x->ptr.pp_double[i2][j2], x->stride); -} - -ae_bool _ialglib_i_cmatrixlefttrsmf(ae_int_t m, - ae_int_t n, - ae_matrix *a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - ae_matrix *x, - ae_int_t i2, - ae_int_t j2) -{ - /* handle degenerate cases like zero matrices by ALGLIB - greatly simplifies passing data to ALGLIB kernel */ - if( m==0 || n==0) - return ae_false; - - /* handle with optimized ALGLIB kernel */ - return _ialglib_cmatrixlefttrsm(m, n, &a->ptr.pp_complex[i1][j1], a->stride, isupper, isunit, optype, &x->ptr.pp_complex[i2][j2], x->stride); -} - -ae_bool _ialglib_i_rmatrixlefttrsmf(ae_int_t m, - ae_int_t n, - ae_matrix *a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - ae_matrix *x, - ae_int_t i2, - ae_int_t j2) -{ - /* handle degenerate cases like zero matrices by ALGLIB - greatly simplifies passing data to ALGLIB kernel */ - if( m==0 || n==0) - return ae_false; - - /* handle with optimized ALGLIB kernel */ - return _ialglib_rmatrixlefttrsm(m, n, &a->ptr.pp_double[i1][j1], a->stride, isupper, isunit, optype, &x->ptr.pp_double[i2][j2], x->stride); -} - -ae_bool _ialglib_i_cmatrixherkf(ae_int_t n, - ae_int_t k, - double alpha, - ae_matrix *a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - ae_matrix *c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper) -{ - /* handle degenerate cases like zero matrices by ALGLIB - greatly simplifies passing data to ALGLIB kernel */ - if( alpha==0.0 || k==0 || n==0) - return ae_false; - - /* ALGLIB kernel */ - return _ialglib_cmatrixherk(n, k, alpha, &a->ptr.pp_complex[ia][ja], a->stride, optypea, beta, &c->ptr.pp_complex[ic][jc], c->stride, isupper); -} - -ae_bool _ialglib_i_rmatrixsyrkf(ae_int_t n, - ae_int_t k, - double alpha, - ae_matrix *a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - ae_matrix *c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper) -{ - /* handle degenerate cases like zero matrices by ALGLIB - greatly simplifies passing data to ALGLIB kernel */ - if( alpha==0.0 || k==0 || n==0) - return ae_false; - - /* ALGLIB kernel */ - return _ialglib_rmatrixsyrk(n, k, alpha, &a->ptr.pp_double[ia][ja], a->stride, optypea, beta, &c->ptr.pp_double[ic][jc], c->stride, isupper); -} - -ae_bool _ialglib_i_cmatrixrank1f(ae_int_t m, - ae_int_t n, - ae_matrix *a, - ae_int_t ia, - ae_int_t ja, - ae_vector *u, - ae_int_t uoffs, - ae_vector *v, - ae_int_t voffs) -{ - return _ialglib_cmatrixrank1(m, n, &a->ptr.pp_complex[ia][ja], a->stride, &u->ptr.p_complex[uoffs], &v->ptr.p_complex[voffs]); -} - -ae_bool _ialglib_i_rmatrixrank1f(ae_int_t m, - ae_int_t n, - ae_matrix *a, - ae_int_t ia, - ae_int_t ja, - ae_vector *u, - ae_int_t uoffs, - ae_vector *v, - ae_int_t voffs) -{ - return _ialglib_rmatrixrank1(m, n, &a->ptr.pp_double[ia][ja], a->stride, &u->ptr.p_double[uoffs], &v->ptr.p_double[voffs]); -} - -ae_bool _ialglib_i_rmatrixgerf(ae_int_t m, - ae_int_t n, - ae_matrix *a, - ae_int_t ia, - ae_int_t ja, - double alpha, - ae_vector *u, - ae_int_t uoffs, - ae_vector *v, - ae_int_t voffs) -{ - return _ialglib_rmatrixger(m, n, &a->ptr.pp_double[ia][ja], a->stride, alpha, &u->ptr.p_double[uoffs], &v->ptr.p_double[voffs]); -} - - - - -/******************************************************************** -This function reads rectangular matrix A given by two column pointers -col0 and col1 and stride src_stride and moves it into contiguous row- -by-row storage given by dst. - -It can handle following special cases: -* col1==NULL in this case second column of A is filled by zeros -********************************************************************/ -void _ialglib_pack_n2( - double *col0, - double *col1, - ae_int_t n, - ae_int_t src_stride, - double *dst) -{ - ae_int_t n2, j, stride2; - - /* - * handle special case - */ - if( col1==NULL ) - { - for(j=0; j>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifndef _ap_h -#define _ap_h - -#include -#include -#include -#include -#include -#include -#include - -#if defined(__CODEGEARC__) -#include -#include -#elif defined(__BORLANDC__) -#include -#include -#else -#include -#include -#endif - -#define AE_USE_CPP -/* Definitions */ -#define AE_UNKNOWN 0 -#define AE_INTEL 1 -#define AE_SPARC 2 - -/* OS definitions */ -#define AE_WINDOWS 1 -#define AE_POSIX 2 -#define AE_LINUX 304 -#if !defined(AE_OS) -#define AE_OS AE_UNKNOWN -#endif -#if AE_OS==AE_LINUX -#undef AE_OS -#define AE_OS AE_POSIX -#define _ALGLIB_USE_LINUX_EXTENSIONS -#endif - -/* threading models for AE_THREADING */ -#define AE_PARALLEL 100 -#define AE_SERIAL 101 -#define AE_SERIAL_UNSAFE 102 -#if !defined(AE_THREADING) -#define AE_THREADING AE_PARALLEL -#endif - -/* malloc types for AE_MALLOC */ -#define AE_STDLIB_MALLOC 200 -#define AE_BASIC_STATIC_MALLOC 201 -#if !defined(AE_MALLOC) -#define AE_MALLOC AE_STDLIB_MALLOC -#endif - -#define AE_LOCK_ALIGNMENT 16 - -/* automatically determine compiler */ -#define AE_MSVC 1 -#define AE_GNUC 2 -#define AE_SUNC 3 -#define AE_COMPILER AE_UNKNOWN -#ifdef __GNUC__ -#undef AE_COMPILER -#define AE_COMPILER AE_GNUC -#endif -#if defined(__SUNPRO_C)||defined(__SUNPRO_CC) -#undef AE_COMPILER -#define AE_COMPILER AE_SUNC -#endif -#ifdef _MSC_VER -#undef AE_COMPILER -#define AE_COMPILER AE_MSVC -#endif - -/* compiler-specific definitions */ -#if AE_COMPILER==AE_MSVC -#define ALIGNED __declspec(align(8)) -#elif AE_COMPILER==AE_GNUC -#define ALIGNED __attribute__((aligned(8))) -#else -#define ALIGNED -#endif - -/* state flags */ -#define _ALGLIB_FLG_THREADING_MASK 0x7 -#define _ALGLIB_FLG_THREADING_SHIFT 0 -#define _ALGLIB_FLG_THREADING_USE_GLOBAL 0x0 -#define _ALGLIB_FLG_THREADING_SERIAL 0x1 -#define _ALGLIB_FLG_THREADING_PARALLEL 0x2 - - -/* now we are ready to include headers */ -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(AE_HAVE_STDINT) -#include -#endif - -/* - * SSE2 intrinsics - * - * Preprocessor directives below: - * - include headers for SSE2 intrinsics - * - define AE_HAS_SSE2_INTRINSICS definition - * - * These actions are performed when we have: - * - x86 architecture definition (AE_CPU==AE_INTEL) - * - compiler which supports intrinsics - * - * Presence of AE_HAS_SSE2_INTRINSICS does NOT mean that our CPU - * actually supports SSE2 - such things should be determined at runtime - * with ae_cpuid() call. It means that we are working under Intel and - * out compiler can issue SSE2-capable code. - * - */ -#if defined(AE_CPU) -#if AE_CPU==AE_INTEL -#if AE_COMPILER==AE_MSVC -#include -#define AE_HAS_SSE2_INTRINSICS -#endif -#if AE_COMPILER==AE_GNUC -#include -#define AE_HAS_SSE2_INTRINSICS -#endif -#if AE_COMPILER==AE_SUNC -#include -#include -#define AE_HAS_SSE2_INTRINSICS -#endif -#endif -#endif - - - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS DECLARATIONS FOR BASIC FUNCTIONALITY -// LIKE MEMORY MANAGEMENT FOR VECTORS/MATRICES WHICH IS SHARED -// BETWEEN C++ AND PURE C LIBRARIES -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ - -/* if we work under C++ environment, define several conditions */ -#ifdef AE_USE_CPP -#define AE_USE_CPP_BOOL -#define AE_USE_CPP_SERIALIZATION -#include -#endif - -/* - * define ae_int32_t, ae_int64_t, ae_int_t, ae_bool, ae_complex, ae_error_type and ae_datatype - */ - -#if defined(AE_INT32_T) -typedef AE_INT32_T ae_int32_t; -#endif -#if defined(AE_HAVE_STDINT) && !defined(AE_INT32_T) -typedef int32_t ae_int32_t; -#endif -#if !defined(AE_HAVE_STDINT) && !defined(AE_INT32_T) -#if AE_COMPILER==AE_MSVC -typedef __int32 ae_int32_t; -#endif -#if (AE_COMPILER==AE_GNUC) || (AE_COMPILER==AE_SUNC) || (AE_COMPILER==AE_UNKNOWN) -typedef int ae_int32_t; -#endif -#endif - -#if defined(AE_INT64_T) -typedef AE_INT64_T ae_int64_t; -#endif -#if defined(AE_HAVE_STDINT) && !defined(AE_INT64_T) -typedef int64_t ae_int64_t; -#endif -#if !defined(AE_HAVE_STDINT) && !defined(AE_INT64_T) -#if AE_COMPILER==AE_MSVC -typedef __int64 ae_int64_t; -#endif -#if (AE_COMPILER==AE_GNUC) || (AE_COMPILER==AE_SUNC) || (AE_COMPILER==AE_UNKNOWN) -typedef signed long long ae_int64_t; -#endif -#endif - -#if defined(AE_UINT64_T) -typedef AE_UINT64_T ae_uint64_t; -#endif -#if defined(AE_HAVE_STDINT) && !defined(AE_UINT64_T) -typedef uint64_t ae_uint64_t; -#endif -#if !defined(AE_HAVE_STDINT) && !defined(AE_UINT64_T) -#if AE_COMPILER==AE_MSVC -typedef unsigned __int64 ae_uint64_t; -#endif -#if (AE_COMPILER==AE_GNUC) || (AE_COMPILER==AE_SUNC) || (AE_COMPILER==AE_UNKNOWN) -typedef unsigned long long ae_uint64_t; -#endif -#endif - -#if !defined(AE_INT_T) -typedef ptrdiff_t ae_int_t; -#endif - -#if !defined(AE_USE_CPP_BOOL) -#define ae_bool char -#define ae_true 1 -#define ae_false 0 -#else -#define ae_bool bool -#define ae_true true -#define ae_false false -#endif - -typedef struct { double x, y; } ae_complex; - -typedef enum -{ - ERR_OK = 0, - ERR_OUT_OF_MEMORY = 1, - ERR_XARRAY_TOO_LARGE = 2, - ERR_ASSERTION_FAILED = 3 -} ae_error_type; - -typedef ae_int_t ae_datatype; - -/* - * other definitions - */ -enum { OWN_CALLER=1, OWN_AE=2 }; -enum { ACT_UNCHANGED=1, ACT_SAME_LOCATION=2, ACT_NEW_LOCATION=3 }; -enum { DT_BOOL=1, DT_BYTE=1, DT_INT=2, DT_REAL=3, DT_COMPLEX=4 }; -enum { CPU_SSE2=1 }; - -/************************************************************************ -x-string (zero-terminated): - owner OWN_CALLER or OWN_AE. Determines what to do on realloc(). - If vector is owned by caller, X-interface will just set - ptr to NULL before realloc(). If it is owned by X, it - will call ae_free/x_free/aligned_free family functions. - - last_action ACT_UNCHANGED, ACT_SAME_LOCATION, ACT_NEW_LOCATION - contents is either: unchanged, stored at the same location, - stored at the new location. - this field is set on return from X. - - ptr pointer to the actual data - -Members of this structure are ae_int64_t to avoid alignment problems. -************************************************************************/ -typedef struct -{ - ALIGNED ae_int64_t owner; - ALIGNED ae_int64_t last_action; - ALIGNED char *ptr; -} x_string; - -/************************************************************************ -x-vector: - cnt number of elements - - datatype one of the DT_XXXX values - - owner OWN_CALLER or OWN_AE. Determines what to do on realloc(). - If vector is owned by caller, X-interface will just set - ptr to NULL before realloc(). If it is owned by X, it - will call ae_free/x_free/aligned_free family functions. - - last_action ACT_UNCHANGED, ACT_SAME_LOCATION, ACT_NEW_LOCATION - contents is either: unchanged, stored at the same location, - stored at the new location. - this field is set on return from X interface and may be - used by caller as hint when deciding what to do with data - (if it was ACT_UNCHANGED or ACT_SAME_LOCATION, no array - reallocation or copying is required). - - ptr pointer to the actual data - -Members of this structure are ae_int64_t to avoid alignment problems. -************************************************************************/ -typedef struct -{ - ae_int64_t cnt; - ae_int64_t datatype; - ae_int64_t owner; - ae_int64_t last_action; - union - { - void *p_ptr; - ae_int64_t portable_alignment_enforcer; - } x_ptr; -} x_vector; - - -/************************************************************************ -x-matrix: - rows number of rows. may be zero only when cols is zero too. - - cols number of columns. may be zero only when rows is zero too. - - stride stride, i.e. distance between first elements of rows (in bytes) - - datatype one of the DT_XXXX values - - owner OWN_CALLER or OWN_AE. Determines what to do on realloc(). - If vector is owned by caller, X-interface will just set - ptr to NULL before realloc(). If it is owned by X, it - will call ae_free/x_free/aligned_free family functions. - - last_action ACT_UNCHANGED, ACT_SAME_LOCATION, ACT_NEW_LOCATION - contents is either: unchanged, stored at the same location, - stored at the new location. - this field is set on return from X interface and may be - used by caller as hint when deciding what to do with data - (if it was ACT_UNCHANGED or ACT_SAME_LOCATION, no array - reallocation or copying is required). - - ptr pointer to the actual data, stored rowwise - -Members of this structure are ae_int64_t to avoid alignment problems. -************************************************************************/ -typedef struct -{ - ae_int64_t rows; - ae_int64_t cols; - ae_int64_t stride; - ae_int64_t datatype; - ae_int64_t owner; - ae_int64_t last_action; - union - { - void *p_ptr; - ae_int64_t portable_alignment_enforcer; - } x_ptr; -} x_matrix; - - -/************************************************************************ -dynamic block which may be automatically deallocated during stack unwinding - -p_next next block in the stack unwinding list. - NULL means that this block is not in the list -deallocator deallocator function which should be used to deallocate block. - NULL for "special" blocks (frame/stack boundaries) -ptr pointer which should be passed to the deallocator. - may be null (for zero-size block), DYN_BOTTOM or DYN_FRAME - for "special" blocks (frame/stack boundaries). - -valgrind_hint is a special field which stores a special hint pointer for - Valgrind and other similar memory checking tools. ALGLIB - manually aligns pointers obtained via malloc, so ptr usually - points to location past the beginning of the actuallly - allocated memory. In such cases memory testing tools may - report "(possibly) lost" memory. - - This "hint" field stores pointer actually returned by - malloc (or NULL, if for some reason we do not support - this feature). This field is used merely as a hint for - Valgrind - it should NOT be used for anything else. - -************************************************************************/ -typedef struct ae_dyn_block -{ - struct ae_dyn_block * volatile p_next; - /* void *deallocator; */ - void (*deallocator)(void*); - void * volatile ptr; - void* valgrind_hint; -} ae_dyn_block; - -typedef void(*ae_deallocator)(void*); - -/************************************************************************ -frame marker -************************************************************************/ -typedef struct ae_frame -{ - ae_dyn_block db_marker; -} ae_frame; - -/************************************************************************ -ALGLIB environment state -************************************************************************/ -typedef struct ae_state -{ - /* - * endianness type: AE_LITTLE_ENDIAN or AE_BIG_ENDIAN - */ - ae_int_t endianness; - - /* - * double value for NAN - */ - double v_nan; - - /* - * double value for +INF - */ - double v_posinf; - - /* - * double value for -INF - */ - double v_neginf; - - /* - * pointer to the top block in a stack of frames - * which hold dynamically allocated objects - */ - ae_dyn_block * volatile p_top_block; - ae_dyn_block last_block; - - /* - * jmp_buf pointer for internal C-style exception handling - */ - jmp_buf * volatile break_jump; - - /* - * ae_error_type of the last error (filled when exception is thrown) - */ - ae_error_type volatile last_error; - - /* - * human-readable message (filled when exception is thrown) - */ - const char* volatile error_msg; - - /* - * Flags: call-local settings for ALGLIB - */ - ae_uint64_t flags; - - /* - * threading information: - * a) current thread pool - * b) current worker thread - * c) parent task (one we are solving right now) - * d) thread exception handler (function which must be called - * by ae_assert before raising exception). - * - * NOTE: we use void* to store pointers in order to avoid explicit dependency on smp.h - */ - void *worker_thread; - void *parent_task; - void (*thread_exception_handler)(void*); - -} ae_state; - -/************************************************************************ -Serializer: - -* ae_stream_writer type is a function pointer for stream writer method; - this pointer is used by X-core for out-of-core serialization (say, to - serialize ALGLIB structure directly to managed C# stream). - - This function accepts two parameters: pointer to ANSI (7-bit) string - and pointer-sized integer passed to serializer during initialization. - String being passed is a part of the data stream; aux paramerer may be - arbitrary value intended to be used by actual implementation of stream - writer. String parameter may include spaces and linefeed symbols, it - should be written to stream as is. - - Return value must be zero for success or non-zero for failure. - -* ae_stream_reader type is a function pointer for stream reader method; - this pointer is used by X-core for out-of-core unserialization (say, to - unserialize ALGLIB structure directly from managed C# stream). - - This function accepts three parameters: pointer-sized integer passed to - serializer during initialization; number of symbols to read from - stream; pointer to buffer used to store next token read from stream - (ANSI encoding is used, buffer is large enough to store all symbols and - trailing zero symbol). - - Number of symbols to read is always positive. - - After being called by X-core, this function must: - * skip all space and linefeed characters from the current position at - the stream and until first non-space non-linefeed character is found - * read exactly cnt symbols from stream to buffer; check that all - symbols being read are non-space non-linefeed ones - * append trailing zero symbol to buffer - * return value must be zero on success, non-zero if even one of the - conditions above fails. When reader returns non-zero value, contents - of buf is not used. -************************************************************************/ -typedef char(*ae_stream_writer)(const char *p_string, ae_int_t aux); -typedef char(*ae_stream_reader)(ae_int_t aux, ae_int_t cnt, char *p_buf); - -typedef struct -{ - ae_int_t mode; - ae_int_t entries_needed; - ae_int_t entries_saved; - ae_int_t bytes_asked; - ae_int_t bytes_written; - -#ifdef AE_USE_CPP_SERIALIZATION - std::string *out_cppstr; -#endif - char *out_str; /* pointer to the current position at the output buffer; advanced with each write operation */ - const char *in_str; /* pointer to the current position at the input buffer; advanced with each read operation */ - ae_int_t stream_aux; - ae_stream_writer stream_writer; - ae_stream_reader stream_reader; -} ae_serializer; - - -typedef struct ae_vector -{ - /* - * Number of elements in array, cnt>=0 - */ - ae_int_t cnt; - - /* - * Either DT_BOOL/DT_BYTE, DT_INT, DT_REAL or DT_COMPLEX - */ - ae_datatype datatype; - - /* - * If ptr points to memory owned and managed by ae_vector itself, - * this field is ae_false. If vector was attached to x_vector structure - * with ae_vector_init_attach_to_x(), this field is ae_true. - */ - ae_bool is_attached; - - /* - * ae_dyn_block structure which manages data in ptr. This structure - * is responsible for automatic deletion of object when its frame - * is destroyed. - */ - ae_dyn_block data; - - /* - * Pointer to data. - * User usually works with this field. - */ - union - { - void *p_ptr; - ae_bool *p_bool; - unsigned char *p_ubyte; - ae_int_t *p_int; - double *p_double; - ae_complex *p_complex; - } ptr; -} ae_vector; - -typedef struct ae_matrix -{ - ae_int_t rows; - ae_int_t cols; - ae_int_t stride; - ae_datatype datatype; - - /* - * If ptr points to memory owned and managed by ae_vector itself, - * this field is ae_false. If vector was attached to x_vector structure - * with ae_vector_init_attach_to_x(), this field is ae_true. - */ - ae_bool is_attached; - - ae_dyn_block data; - union - { - void *p_ptr; - void **pp_void; - ae_bool **pp_bool; - ae_int_t **pp_int; - double **pp_double; - ae_complex **pp_complex; - } ptr; -} ae_matrix; - -typedef struct ae_smart_ptr -{ - /* pointer to subscriber; all changes in ptr are translated to subscriber */ - void **subscriber; - - /* pointer to object */ - void *ptr; - - /* whether smart pointer owns ptr */ - ae_bool is_owner; - - /* whether object pointed by ptr is dynamic - clearing such object requires BOTH - calling destructor function AND calling ae_free for memory occupied by object. */ - ae_bool is_dynamic; - - /* destructor function for pointer; clears all dynamically allocated memory */ - void (*destroy)(void*); - - /* frame entry; used to ensure automatic deallocation of smart pointer in case of exception/exit */ - ae_dyn_block frame_entry; -} ae_smart_ptr; - - -/************************************************************************* -Lock. - -This structure provides OS-independent non-reentrant lock: -* under Windows/Posix systems it uses system-provided locks -* under Boost it uses OS-independent lock provided by Boost package -* when no OS is defined, it uses "fake lock" (just stub which is not thread-safe): - a) "fake lock" can be in locked or free mode - b) "fake lock" can be used only from one thread - one which created lock - c) when thread acquires free lock, it immediately returns - d) when thread acquires busy lock, program is terminated - (because lock is already acquired and no one else can free it) -*************************************************************************/ -typedef struct -{ - /* - * Pointer to _lock structure. This pointer has type void* in order to - * make header file OS-independent (lock declaration depends on OS). - */ - void *lock_ptr; - - /* - * For eternal=false this field manages pointer to _lock structure. - * - * ae_dyn_block structure is responsible for automatic deletion of - * the memory allocated for the pointer when its frame is destroyed. - */ - ae_dyn_block db; - - /* - * Whether we have eternal lock object (used by thread pool) or - * transient lock. Eternal locks are allocated without using ae_dyn_block - * structure and do not allow deallocation. - */ - ae_bool eternal; -} ae_lock; - - -/************************************************************************* -Shared pool: data structure used to provide thread-safe access to pool of -temporary variables. -*************************************************************************/ -typedef struct ae_shared_pool_entry -{ - void * volatile obj; - void * volatile next_entry; -} ae_shared_pool_entry; - -typedef struct ae_shared_pool -{ - /* lock object which protects pool */ - ae_lock pool_lock; - - /* seed object (used to create new instances of temporaries) */ - void * volatile seed_object; - - /* - * list of recycled OBJECTS: - * 1. entries in this list store pointers to recycled objects - * 2. every time we retrieve object, we retrieve first entry from this list, - * move it to recycled_entries and return its obj field to caller/ - */ - ae_shared_pool_entry * volatile recycled_objects; - - /* - * list of recycled ENTRIES: - * 1. this list holds entries which are not used to store recycled objects; - * every time recycled object is retrieved, its entry is moved to this list. - * 2. every time object is recycled, we try to fetch entry for him from this list - * before allocating it with malloc() - */ - ae_shared_pool_entry * volatile recycled_entries; - - /* enumeration pointer, points to current recycled object*/ - ae_shared_pool_entry * volatile enumeration_counter; - - /* size of object; this field is used when we call malloc() for new objects */ - ae_int_t size_of_object; - - /* initializer function; accepts pointer to malloc'ed object, initializes its fields */ - void (*init)(void* dst, ae_state* state, ae_bool make_automatic); - - /* copy constructor; accepts pointer to malloc'ed, but not initialized object */ - void (*init_copy)(void* dst, void* src, ae_state* state, ae_bool make_automatic); - - /* destructor function; */ - void (*destroy)(void* ptr); - - /* frame entry; contains pointer to the pool object itself */ - ae_dyn_block frame_entry; -} ae_shared_pool; - -void ae_never_call_it(); -void ae_set_dbg_flag(ae_int64_t flag_id, ae_int64_t flag_val); -ae_int64_t ae_get_dbg_value(ae_int64_t id); -void ae_set_global_threading(ae_uint64_t flg_value); -ae_uint64_t ae_get_global_threading(); - -/************************************************************************ -Debugging and tracing functions -************************************************************************/ -void ae_set_error_flag(ae_bool *p_flag, ae_bool cond, const char *filename, int lineno, const char *xdesc); -const char * ae_get_last_error_file(); -int ae_get_last_error_line(); -const char * ae_get_last_error_xdesc(); - -void ae_trace_file(const char *tags, const char *filename); -void ae_trace_disable(); -ae_bool ae_is_trace_enabled(const char *tag); -void ae_trace(const char * printf_fmt, ...); - -int ae_tickcount(); - - -/************************************************************************ -... -************************************************************************/ -ae_int_t ae_misalignment(const void *ptr, size_t alignment); -void* ae_align(void *ptr, size_t alignment); -ae_int_t ae_get_effective_workers(ae_int_t nworkers); -void ae_optional_atomic_add_i(ae_int_t *p, ae_int_t v); -void ae_optional_atomic_sub_i(ae_int_t *p, ae_int_t v); - -void* aligned_malloc(size_t size, size_t alignment); -void* aligned_extract_ptr(void *block); -void aligned_free(void *block); -void* eternal_malloc(size_t size); -#if AE_MALLOC==AE_BASIC_STATIC_MALLOC -void set_memory_pool(void *ptr, size_t size); -void memory_pool_stats(ae_int_t *bytes_used, ae_int_t *bytes_free); -#endif - -void* ae_malloc(size_t size, ae_state *state); -void ae_free(void *p); -ae_int_t ae_sizeof(ae_datatype datatype); -ae_bool ae_check_zeros(const void *ptr, ae_int_t n); -void ae_touch_ptr(void *p); - -void ae_state_init(ae_state *state); -void ae_state_clear(ae_state *state); -void ae_state_set_break_jump(ae_state *state, jmp_buf *buf); -void ae_state_set_flags(ae_state *state, ae_uint64_t flags); -void ae_clean_up_before_breaking(ae_state *state); -void ae_break(ae_state *state, ae_error_type error_type, const char *msg); - -void ae_frame_make(ae_state *state, ae_frame *tmp); -void ae_frame_leave(ae_state *state); - -void ae_db_attach(ae_dyn_block *block, ae_state *state); -void ae_db_init(ae_dyn_block *block, ae_int_t size, ae_state *state, ae_bool make_automatic); -void ae_db_realloc(ae_dyn_block *block, ae_int_t size, ae_state *state); -void ae_db_free(ae_dyn_block *block); -void ae_db_swap(ae_dyn_block *block1, ae_dyn_block *block2); - -void ae_vector_init(ae_vector *dst, ae_int_t size, ae_datatype datatype, ae_state *state, ae_bool make_automatic); -void ae_vector_init_copy(ae_vector *dst, ae_vector *src, ae_state *state, ae_bool make_automatic); -void ae_vector_init_from_x(ae_vector *dst, x_vector *src, ae_state *state, ae_bool make_automatic); -void ae_vector_init_attach_to_x(ae_vector *dst, x_vector *src, ae_state *state, ae_bool make_automatic); -void ae_vector_set_length(ae_vector *dst, ae_int_t newsize, ae_state *state); -void ae_vector_resize(ae_vector *dst, ae_int_t newsize, ae_state *state); -void ae_vector_clear(ae_vector *dst); -void ae_vector_destroy(ae_vector *dst); -void ae_swap_vectors(ae_vector *vec1, ae_vector *vec2); - -void ae_matrix_init(ae_matrix *dst, ae_int_t rows, ae_int_t cols, ae_datatype datatype, ae_state *state, ae_bool make_automatic); -void ae_matrix_init_copy(ae_matrix *dst, ae_matrix *src, ae_state *state, ae_bool make_automatic); -void ae_matrix_init_from_x(ae_matrix *dst, x_matrix *src, ae_state *state, ae_bool make_automatic); -void ae_matrix_init_attach_to_x(ae_matrix *dst, x_matrix *src, ae_state *state, ae_bool make_automatic); -void ae_matrix_set_length(ae_matrix *dst, ae_int_t rows, ae_int_t cols, ae_state *state); -void ae_matrix_clear(ae_matrix *dst); -void ae_matrix_destroy(ae_matrix *dst); -void ae_swap_matrices(ae_matrix *mat1, ae_matrix *mat2); - -void ae_smart_ptr_init(ae_smart_ptr *dst, void **subscriber, ae_state *state, ae_bool make_automatic); -void ae_smart_ptr_clear(void *_dst); /* accepts ae_smart_ptr* */ -void ae_smart_ptr_destroy(void *_dst); -void ae_smart_ptr_assign(ae_smart_ptr *dst, void *new_ptr, ae_bool is_owner, ae_bool is_dynamic, void (*destroy)(void*)); -void ae_smart_ptr_release(ae_smart_ptr *dst); - -void ae_yield(); -void ae_init_lock(ae_lock *lock, ae_state *state, ae_bool make_automatic); -void ae_init_lock_eternal(ae_lock *lock); -void ae_acquire_lock(ae_lock *lock); -void ae_release_lock(ae_lock *lock); -void ae_free_lock(ae_lock *lock); - -void ae_shared_pool_init(void *_dst, ae_state *state, ae_bool make_automatic); -void ae_shared_pool_init_copy(void *_dst, void *_src, ae_state *state, ae_bool make_automatic); -void ae_shared_pool_clear(void *dst); -void ae_shared_pool_destroy(void *dst); -ae_bool ae_shared_pool_is_initialized(void *_dst); -void ae_shared_pool_set_seed( - ae_shared_pool *dst, - void *seed_object, - ae_int_t size_of_object, - void (*init)(void* dst, ae_state* state, ae_bool make_automatic), - void (*init_copy)(void* dst, void* src, ae_state* state, ae_bool make_automatic), - void (*destroy)(void* ptr), - ae_state *state); -void ae_shared_pool_retrieve( - ae_shared_pool *pool, - ae_smart_ptr *pptr, - ae_state *state); -void ae_shared_pool_recycle( - ae_shared_pool *pool, - ae_smart_ptr *pptr, - ae_state *state); -void ae_shared_pool_clear_recycled( - ae_shared_pool *pool, - ae_state *state); -void ae_shared_pool_first_recycled( - ae_shared_pool *pool, - ae_smart_ptr *pptr, - ae_state *state); -void ae_shared_pool_next_recycled( - ae_shared_pool *pool, - ae_smart_ptr *pptr, - ae_state *state); -void ae_shared_pool_reset( - ae_shared_pool *pool, - ae_state *state); - -void ae_x_set_vector(x_vector *dst, ae_vector *src, ae_state *state); -void ae_x_set_matrix(x_matrix *dst, ae_matrix *src, ae_state *state); -void ae_x_attach_to_vector(x_vector *dst, ae_vector *src); -void ae_x_attach_to_matrix(x_matrix *dst, ae_matrix *src); - -void x_vector_clear(x_vector *dst); - -ae_bool x_is_symmetric(x_matrix *a); -ae_bool x_is_hermitian(x_matrix *a); -ae_bool x_force_symmetric(x_matrix *a); -ae_bool x_force_hermitian(x_matrix *a); -ae_bool ae_is_symmetric(ae_matrix *a); -ae_bool ae_is_hermitian(ae_matrix *a); -ae_bool ae_force_symmetric(ae_matrix *a); -ae_bool ae_force_hermitian(ae_matrix *a); - -void ae_serializer_init(ae_serializer *serializer); -void ae_serializer_clear(ae_serializer *serializer); - -void ae_serializer_alloc_start(ae_serializer *serializer); -void ae_serializer_alloc_entry(ae_serializer *serializer); -void ae_serializer_alloc_byte_array(ae_serializer *serializer, ae_vector *bytes); -ae_int_t ae_serializer_get_alloc_size(ae_serializer *serializer); - -#ifdef AE_USE_CPP_SERIALIZATION -void ae_serializer_sstart_str(ae_serializer *serializer, std::string *buf); -void ae_serializer_ustart_str(ae_serializer *serializer, const std::string *buf); -void ae_serializer_sstart_stream(ae_serializer *serializer, std::ostream *stream); -void ae_serializer_ustart_stream(ae_serializer *serializer, const std::istream *stream); -#endif -void ae_serializer_sstart_str(ae_serializer *serializer, char *buf); -void ae_serializer_ustart_str(ae_serializer *serializer, const char *buf); -void ae_serializer_sstart_stream(ae_serializer *serializer, ae_stream_writer writer, ae_int_t aux); -void ae_serializer_ustart_stream(ae_serializer *serializer, ae_stream_reader reader, ae_int_t aux); - -void ae_serializer_serialize_bool(ae_serializer *serializer, ae_bool v, ae_state *state); -void ae_serializer_serialize_int(ae_serializer *serializer, ae_int_t v, ae_state *state); -void ae_serializer_serialize_int64(ae_serializer *serializer, ae_int64_t v, ae_state *state); -void ae_serializer_serialize_double(ae_serializer *serializer, double v, ae_state *state); -void ae_serializer_serialize_byte_array(ae_serializer *serializer, ae_vector *bytes, ae_state *state); -void ae_serializer_unserialize_bool(ae_serializer *serializer, ae_bool *v, ae_state *state); -void ae_serializer_unserialize_int(ae_serializer *serializer, ae_int_t *v, ae_state *state); -void ae_serializer_unserialize_int64(ae_serializer *serializer, ae_int64_t *v, ae_state *state); -void ae_serializer_unserialize_double(ae_serializer *serializer, double *v, ae_state *state); -void ae_serializer_unserialize_byte_array(ae_serializer *serializer, ae_vector *bytes, ae_state *state); - -void ae_serializer_stop(ae_serializer *serializer, ae_state *state); - -/************************************************************************ -Service functions -************************************************************************/ -void ae_assert(ae_bool cond, const char *msg, ae_state *state); -ae_int_t ae_cpuid(); - -/************************************************************************ -Real math functions: -* IEEE-compliant floating point comparisons -* standard functions -************************************************************************/ -ae_bool ae_fp_eq(double v1, double v2); -ae_bool ae_fp_neq(double v1, double v2); -ae_bool ae_fp_less(double v1, double v2); -ae_bool ae_fp_less_eq(double v1, double v2); -ae_bool ae_fp_greater(double v1, double v2); -ae_bool ae_fp_greater_eq(double v1, double v2); - -ae_bool ae_isfinite_stateless(double x, ae_int_t endianness); -ae_bool ae_isnan_stateless(double x, ae_int_t endianness); -ae_bool ae_isinf_stateless(double x, ae_int_t endianness); -ae_bool ae_isposinf_stateless(double x, ae_int_t endianness); -ae_bool ae_isneginf_stateless(double x, ae_int_t endianness); - -ae_int_t ae_get_endianness(); - -ae_bool ae_isfinite(double x,ae_state *state); -ae_bool ae_isnan(double x, ae_state *state); -ae_bool ae_isinf(double x, ae_state *state); -ae_bool ae_isposinf(double x,ae_state *state); -ae_bool ae_isneginf(double x,ae_state *state); - -double ae_fabs(double x, ae_state *state); -ae_int_t ae_iabs(ae_int_t x, ae_state *state); -double ae_sqr(double x, ae_state *state); -double ae_sqrt(double x, ae_state *state); - -ae_int_t ae_sign(double x, ae_state *state); -ae_int_t ae_round(double x, ae_state *state); -ae_int_t ae_trunc(double x, ae_state *state); -ae_int_t ae_ifloor(double x, ae_state *state); -ae_int_t ae_iceil(double x, ae_state *state); - -ae_int_t ae_maxint(ae_int_t m1, ae_int_t m2, ae_state *state); -ae_int_t ae_minint(ae_int_t m1, ae_int_t m2, ae_state *state); -double ae_maxreal(double m1, double m2, ae_state *state); -double ae_minreal(double m1, double m2, ae_state *state); -double ae_randomreal(ae_state *state); -ae_int_t ae_randominteger(ae_int_t maxv, ae_state *state); - -double ae_sin(double x, ae_state *state); -double ae_cos(double x, ae_state *state); -double ae_tan(double x, ae_state *state); -double ae_sinh(double x, ae_state *state); -double ae_cosh(double x, ae_state *state); -double ae_tanh(double x, ae_state *state); -double ae_asin(double x, ae_state *state); -double ae_acos(double x, ae_state *state); -double ae_atan(double x, ae_state *state); -double ae_atan2(double y, double x, ae_state *state); - -double ae_log(double x, ae_state *state); -double ae_pow(double x, double y, ae_state *state); -double ae_exp(double x, ae_state *state); - -/************************************************************************ -Complex math functions: -* basic arithmetic operations -* standard functions -************************************************************************/ -ae_complex ae_complex_from_i(ae_int_t v); -ae_complex ae_complex_from_d(double v); - -ae_complex ae_c_neg(ae_complex lhs); -ae_bool ae_c_eq(ae_complex lhs, ae_complex rhs); -ae_bool ae_c_neq(ae_complex lhs, ae_complex rhs); -ae_complex ae_c_add(ae_complex lhs, ae_complex rhs); -ae_complex ae_c_mul(ae_complex lhs, ae_complex rhs); -ae_complex ae_c_sub(ae_complex lhs, ae_complex rhs); -ae_complex ae_c_div(ae_complex lhs, ae_complex rhs); -ae_bool ae_c_eq_d(ae_complex lhs, double rhs); -ae_bool ae_c_neq_d(ae_complex lhs, double rhs); -ae_complex ae_c_add_d(ae_complex lhs, double rhs); -ae_complex ae_c_mul_d(ae_complex lhs, double rhs); -ae_complex ae_c_sub_d(ae_complex lhs, double rhs); -ae_complex ae_c_d_sub(double lhs, ae_complex rhs); -ae_complex ae_c_div_d(ae_complex lhs, double rhs); -ae_complex ae_c_d_div(double lhs, ae_complex rhs); - -ae_complex ae_c_conj(ae_complex lhs, ae_state *state); -ae_complex ae_c_sqr(ae_complex lhs, ae_state *state); -double ae_c_abs(ae_complex z, ae_state *state); - -/************************************************************************ -Complex BLAS operations -************************************************************************/ -ae_complex ae_v_cdotproduct(const ae_complex *v0, ae_int_t stride0, const char *conj0, const ae_complex *v1, ae_int_t stride1, const char *conj1, ae_int_t n); -void ae_v_cmove(ae_complex *vdst, ae_int_t stride_dst, const ae_complex* vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n); -void ae_v_cmoveneg(ae_complex *vdst, ae_int_t stride_dst, const ae_complex* vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n); -void ae_v_cmoved(ae_complex *vdst, ae_int_t stride_dst, const ae_complex* vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, double alpha); -void ae_v_cmovec(ae_complex *vdst, ae_int_t stride_dst, const ae_complex* vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, ae_complex alpha); -void ae_v_cadd(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n); -void ae_v_caddd(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, double alpha); -void ae_v_caddc(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, ae_complex alpha); -void ae_v_csub(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n); -void ae_v_csubd(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, double alpha); -void ae_v_csubc(ae_complex *vdst, ae_int_t stride_dst, const ae_complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, ae_complex alpha); -void ae_v_cmuld(ae_complex *vdst, ae_int_t stride_dst, ae_int_t n, double alpha); -void ae_v_cmulc(ae_complex *vdst, ae_int_t stride_dst, ae_int_t n, ae_complex alpha); - -/************************************************************************ -Real BLAS operations -************************************************************************/ -double ae_v_dotproduct(const double *v0, ae_int_t stride0, const double *v1, ae_int_t stride1, ae_int_t n); -void ae_v_move(double *vdst, ae_int_t stride_dst, const double* vsrc, ae_int_t stride_src, ae_int_t n); -void ae_v_moveneg(double *vdst, ae_int_t stride_dst, const double* vsrc, ae_int_t stride_src, ae_int_t n); -void ae_v_moved(double *vdst, ae_int_t stride_dst, const double* vsrc, ae_int_t stride_src, ae_int_t n, double alpha); -void ae_v_add(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n); -void ae_v_addd(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n, double alpha); -void ae_v_sub(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n); -void ae_v_subd(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n, double alpha); -void ae_v_muld(double *vdst, ae_int_t stride_dst, ae_int_t n, double alpha); - -/************************************************************************ -Other functions -************************************************************************/ -ae_int_t ae_v_len(ae_int_t a, ae_int_t b); - -/* -extern const double ae_machineepsilon; -extern const double ae_maxrealnumber; -extern const double ae_minrealnumber; -extern const double ae_pi; -*/ -#define ae_machineepsilon 5E-16 -#define ae_maxrealnumber 1E300 -#define ae_minrealnumber 1E-300 -#define ae_pi 3.1415926535897932384626433832795 - - -/************************************************************************ -RComm functions -************************************************************************/ -typedef struct rcommstate -{ - int stage; - ae_vector ia; - ae_vector ba; - ae_vector ra; - ae_vector ca; -} rcommstate; -void _rcommstate_init(rcommstate* p, ae_state *_state, ae_bool make_automatic); -void _rcommstate_init_copy(rcommstate* dst, rcommstate* src, ae_state *_state, ae_bool make_automatic); -void _rcommstate_clear(rcommstate* p); -void _rcommstate_destroy(rcommstate* p); - - -/************************************************************************ -Allocation counters, inactive by default. -Turned on when needed for debugging purposes. - -_alloc_counter is incremented by 1 on malloc(), decremented on free(). -_alloc_counter_total is only incremented by 1. -************************************************************************/ -extern ae_int_t _alloc_counter; -extern ae_int_t _alloc_counter_total; -extern ae_bool _use_alloc_counter; - - -/************************************************************************ -Malloc debugging: - -* _force_malloc_failure - set this flag to ae_true in order to enforce - failure of ALGLIB malloc(). Useful to debug handling of errors during - memory allocation. As long as this flag is set, ALGLIB malloc will fail. -* _malloc_failure_after - set it to non-zero value in order to enforce - malloc failure as soon as _alloc_counter_total increases above value of - this variable. This value has no effect if _use_alloc_counter is not - set. -************************************************************************/ -extern ae_bool _force_malloc_failure; -extern ae_int_t _malloc_failure_after; - - -/************************************************************************ -Trace file descriptor (to be used by ALGLIB code which sends messages to -trace log) -************************************************************************/ -extern FILE *alglib_trace_file; - - -/************************************************************************ -debug functions (must be turned on by preprocessor definitions): -* flushconsole(), fluches console -* ae_debugrng(), returns random number generated with high-quality random numbers generator -* ae_set_seed(), sets seed of the debug RNG (NON-THREAD-SAFE!!!) -* ae_get_seed(), returns two seed values of the debug RNG (NON-THREAD-SAFE!!!) -************************************************************************/ -#ifdef AE_DEBUG4WINDOWS -#define flushconsole(s) fflush(stdout) -#endif -#ifdef AE_DEBUG4POSIX -#define flushconsole(s) fflush(stdout) -#endif - - -} - - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS DECLARATIONS FOR C++ RELATED FUNCTIONALITY -// -///////////////////////////////////////////////////////////////////////// - -namespace alglib -{ - -typedef alglib_impl::ae_int_t ae_int_t; - -/******************************************************************** -Class forwards -********************************************************************/ -class complex; - -ae_int_t vlen(ae_int_t n1, ae_int_t n2); - -/******************************************************************** -Exception class. -********************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -class ap_error -{ -public: - std::string msg; - - ap_error(); - ap_error(const char *s); - static void make_assertion(bool bClause); - static void make_assertion(bool bClause, const char *p_msg); -private: -}; -#endif - -/******************************************************************** -Complex number with double precision. -********************************************************************/ -class complex -{ -public: - complex(); - complex(const double &_x); - complex(const double &_x, const double &_y); - complex(const complex &z); - - complex& operator= (const double& v); - complex& operator+=(const double& v); - complex& operator-=(const double& v); - complex& operator*=(const double& v); - complex& operator/=(const double& v); - - complex& operator= (const complex& z); - complex& operator+=(const complex& z); - complex& operator-=(const complex& z); - complex& operator*=(const complex& z); - complex& operator/=(const complex& z); - - alglib_impl::ae_complex* c_ptr(); - const alglib_impl::ae_complex* c_ptr() const; - -#if !defined(AE_NO_EXCEPTIONS) - std::string tostring(int dps) const; -#endif - - double x, y; -}; - -const alglib::complex operator/(const alglib::complex& lhs, const alglib::complex& rhs); -bool operator==(const alglib::complex& lhs, const alglib::complex& rhs); -bool operator!=(const alglib::complex& lhs, const alglib::complex& rhs); -const alglib::complex operator+(const alglib::complex& lhs); -const alglib::complex operator-(const alglib::complex& lhs); -const alglib::complex operator+(const alglib::complex& lhs, const alglib::complex& rhs); -const alglib::complex operator+(const alglib::complex& lhs, const double& rhs); -const alglib::complex operator+(const double& lhs, const alglib::complex& rhs); -const alglib::complex operator-(const alglib::complex& lhs, const alglib::complex& rhs); -const alglib::complex operator-(const alglib::complex& lhs, const double& rhs); -const alglib::complex operator-(const double& lhs, const alglib::complex& rhs); -const alglib::complex operator*(const alglib::complex& lhs, const alglib::complex& rhs); -const alglib::complex operator*(const alglib::complex& lhs, const double& rhs); -const alglib::complex operator*(const double& lhs, const alglib::complex& rhs); -const alglib::complex operator/(const alglib::complex& lhs, const alglib::complex& rhs); -const alglib::complex operator/(const double& lhs, const alglib::complex& rhs); -const alglib::complex operator/(const alglib::complex& lhs, const double& rhs); -double abscomplex(const alglib::complex &z); -alglib::complex conj(const alglib::complex &z); -alglib::complex csqr(const alglib::complex &z); - -/******************************************************************** -Level 1 BLAS functions - -NOTES: -* destination and source should NOT overlap -* stride is assumed to be positive, but it is not - assert'ed within function -* conj_src parameter specifies whether complex source is conjugated - before processing or not. Pass string which starts with 'N' or 'n' - ("No conj", for example) to use unmodified parameter. All other - values will result in conjugation of input, but it is recommended - to use "Conj" in such cases. -********************************************************************/ -double vdotproduct(const double *v0, ae_int_t stride0, const double *v1, ae_int_t stride1, ae_int_t n); -double vdotproduct(const double *v1, const double *v2, ae_int_t N); - -alglib::complex vdotproduct(const alglib::complex *v0, ae_int_t stride0, const char *conj0, const alglib::complex *v1, ae_int_t stride1, const char *conj1, ae_int_t n); -alglib::complex vdotproduct(const alglib::complex *v1, const alglib::complex *v2, ae_int_t N); - -void vmove(double *vdst, ae_int_t stride_dst, const double* vsrc, ae_int_t stride_src, ae_int_t n); -void vmove(double *vdst, const double* vsrc, ae_int_t N); - -void vmove(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex* vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n); -void vmove(alglib::complex *vdst, const alglib::complex* vsrc, ae_int_t N); - -void vmoveneg(double *vdst, ae_int_t stride_dst, const double* vsrc, ae_int_t stride_src, ae_int_t n); -void vmoveneg(double *vdst, const double *vsrc, ae_int_t N); - -void vmoveneg(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex* vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n); -void vmoveneg(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t N); - -void vmove(double *vdst, ae_int_t stride_dst, const double* vsrc, ae_int_t stride_src, ae_int_t n, double alpha); -void vmove(double *vdst, const double *vsrc, ae_int_t N, double alpha); - -void vmove(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex* vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, double alpha); -void vmove(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t N, double alpha); - -void vmove(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex* vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, alglib::complex alpha); -void vmove(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t N, alglib::complex alpha); - -void vadd(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n); -void vadd(double *vdst, const double *vsrc, ae_int_t N); - -void vadd(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n); -void vadd(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t N); - -void vadd(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n, double alpha); -void vadd(double *vdst, const double *vsrc, ae_int_t N, double alpha); - -void vadd(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, double alpha); -void vadd(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t N, double alpha); - -void vadd(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, alglib::complex alpha); -void vadd(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t N, alglib::complex alpha); - -void vsub(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n); -void vsub(double *vdst, const double *vsrc, ae_int_t N); - -void vsub(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n); -void vsub(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t N); - -void vsub(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n, double alpha); -void vsub(double *vdst, const double *vsrc, ae_int_t N, double alpha); - -void vsub(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, double alpha); -void vsub(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t N, double alpha); - -void vsub(alglib::complex *vdst, ae_int_t stride_dst, const alglib::complex *vsrc, ae_int_t stride_src, const char *conj_src, ae_int_t n, alglib::complex alpha); -void vsub(alglib::complex *vdst, const alglib::complex *vsrc, ae_int_t N, alglib::complex alpha); - -void vmul(double *vdst, ae_int_t stride_dst, ae_int_t n, double alpha); -void vmul(double *vdst, ae_int_t N, double alpha); - -void vmul(alglib::complex *vdst, ae_int_t stride_dst, ae_int_t n, double alpha); -void vmul(alglib::complex *vdst, ae_int_t N, double alpha); - -void vmul(alglib::complex *vdst, ae_int_t stride_dst, ae_int_t n, alglib::complex alpha); -void vmul(alglib::complex *vdst, ae_int_t N, alglib::complex alpha); - - -/******************************************************************** -xparams type and several predefined constants -********************************************************************/ -struct xparams -{ - alglib_impl::ae_uint64_t flags; -}; - -extern const xparams &xdefault; -extern const xparams &serial; -extern const xparams ∥ - -/******************************************************************** -Threading functions -********************************************************************/ -// nworkers can be 1, 2, ... ; or 0 for auto; or -1/-2/... for all except for one/two/... -void setnworkers(alglib::ae_int_t nworkers); - -// sets global threading settings to alglib::serial or alglib::parallel -void setglobalthreading(const xparams settings); - -// nworkers can be 1, 2, ... ; or 0 for auto; or -1/-2/... for all except for one/two/... -alglib::ae_int_t getnworkers(); - -/******************************************************************** -internal functions used by test_x.cpp, interfaces for functions present -in commercial ALGLIB but lacking in free edition. -********************************************************************/ -ae_int_t _ae_cores_count(); -void _ae_set_global_threading(alglib_impl::ae_uint64_t flg_value); -alglib_impl::ae_uint64_t _ae_get_global_threading(); - -/******************************************************************** -1- and 2-dimensional arrays -********************************************************************/ -class ae_vector_wrapper -{ -public: - // - // Creates object attached to external ae_vector structure. - // - // NOTE: this function also checks that source ae_vector* has - // required datatype. An exception is generated otherwise. - // - ae_vector_wrapper(alglib_impl::ae_vector *e_ptr, alglib_impl::ae_datatype datatype); - - // - // Creates zero-size vector of specific datatype - // - ae_vector_wrapper(alglib_impl::ae_datatype datatype); - - // - // Creates a copy of another vector (can be reference to one of the derived classes) - // - // NOTE: this function also checks that source ae_vector* has - // required datatype. An exception is generated otherwise. - // - ae_vector_wrapper(const ae_vector_wrapper &rhs, alglib_impl::ae_datatype datatype); - - // - // Well, it is destructor... - // - virtual ~ae_vector_wrapper(); - - // - // For wrapper object allocated with allocate_own() this function - // changes length, completely dropping previous contents. - // - // It does not work (throws exception) for frozen proxy objects. - // - void setlength(ae_int_t iLen); - - // - // Element count - // - ae_int_t length() const; - - // - // Access to internal C-structure used by C-core. - // Not intended for external use. - // - const alglib_impl::ae_vector* c_ptr() const; - alglib_impl::ae_vector* c_ptr(); -private: - ae_vector_wrapper(); - ae_vector_wrapper(const ae_vector_wrapper &rhs); - const ae_vector_wrapper& operator=(const ae_vector_wrapper &rhs); -protected: -#if !defined(AE_NO_EXCEPTIONS) - // - // Copies array given by string into current object. Additional - // parameter DATATYPE contains information about type of the data - // in S and type of the array to create. - // - // NOTE: this function is not supported in exception-free mode. - // - ae_vector_wrapper(const char *s, alglib_impl::ae_datatype datatype); -#endif - - // - // This function attaches wrapper object to external x_vector structure; - // "frozen proxy" mode is activated (you can read/write, but can not reallocate - // and do not own memory of the vector). - // - // NOTE: initial state of wrapper object is assumed to be initialized; - // all previously allocated memory is properly deallocated. - // - // NOTE: x_vector structure pointed by new_ptr is used only once; after - // we fetch pointer to memory and its size, this structure is ignored - // and not referenced anymore. So, you can pass pointers to temporary - // x-structures which are deallocated immediately after you call attach_to() - // - // NOTE: state structure is used for error reporting purposes (longjmp on errors). - // - void attach_to(alglib_impl::x_vector *new_ptr, alglib_impl::ae_state *_state); - - // - // Assigns RHS to current object. Returns *this. - // - // It has several branches depending on target object status: - // * in case it is proxy object, data are copied into memory pointed by - // proxy. Function checks that source has exactly same size as target - // (exception is thrown on failure). - // * in case it is non-proxy object, data allocated by object are cleared - // and a copy of RHS is created in target. - // - // NOTE: this function correctly handles assignments of the object to itself. - // - const ae_vector_wrapper& assign(const ae_vector_wrapper &rhs); - - // - // Pointer to ae_vector structure: - // * ptr==&inner_vec means that wrapper object owns ae_vector structure and - // is responsible for proper deallocation of its memory - // * ptr!=&inner_vec means that wrapper object works with someone's other - // ae_vector record and is not responsible for its memory; in this case - // inner_vec is assumed to be uninitialized. - // - alglib_impl::ae_vector *ptr; - - // - // Inner ae_vector record. - // Ignored for ptr!=&inner_rec. - // - alglib_impl::ae_vector inner_vec; - - // - // Whether this wrapper object is frozen proxy (you may read array, may - // modify its value, but can not deallocate its memory or resize it) or not. - // - // If is_frozen_proxy==true and if: - // * ptr==&inner_vec, it means that wrapper works with its own ae_vector - // structure, but this structure points to externally allocated memory. - // This memory is NOT owned by ae_vector object. - // * ptr!=&inner_vec, it means that wrapper works with externally allocated - // and managed ae_vector structure. Both memory pointed by ae_vector and - // ae_vector structure itself are not owned by wrapper object. - // - bool is_frozen_proxy; -}; - -class boolean_1d_array : public ae_vector_wrapper -{ -public: - boolean_1d_array(); - boolean_1d_array(const boolean_1d_array &rhs); - boolean_1d_array(alglib_impl::ae_vector *p); - const boolean_1d_array& operator=(const boolean_1d_array &rhs); - virtual ~boolean_1d_array() ; - - const ae_bool& operator()(ae_int_t i) const; - ae_bool& operator()(ae_int_t i); - - const ae_bool& operator[](ae_int_t i) const; - ae_bool& operator[](ae_int_t i); - - // - // This function allocates array[iLen] and copies data - // pointed by pContent to its memory. Completely independent - // copy of data is created. - // - void setcontent(ae_int_t iLen, const bool *pContent ); - - // - // This function returns pointer to internal memory - // - ae_bool* getcontent(); - const ae_bool* getcontent() const; - -#if !defined(AE_NO_EXCEPTIONS) - boolean_1d_array(const char *s); - std::string tostring() const; -#endif -}; - -class integer_1d_array : public ae_vector_wrapper -{ -public: - integer_1d_array(); - integer_1d_array(const integer_1d_array &rhs); - integer_1d_array(alglib_impl::ae_vector *p); - const integer_1d_array& operator=(const integer_1d_array &rhs); - virtual ~integer_1d_array(); - - const ae_int_t& operator()(ae_int_t i) const; - ae_int_t& operator()(ae_int_t i); - - const ae_int_t& operator[](ae_int_t i) const; - ae_int_t& operator[](ae_int_t i); - - // - // This function allocates array[iLen] and copies data - // pointed by pContent to its memory. Completely independent - // copy of data is created. - // - void setcontent(ae_int_t iLen, const ae_int_t *pContent ); - - // - // This function returns pointer to internal memory - // - ae_int_t* getcontent(); - const ae_int_t* getcontent() const; - -#if !defined(AE_NO_EXCEPTIONS) - integer_1d_array(const char *s); - std::string tostring() const; -#endif -}; - -class real_1d_array : public ae_vector_wrapper -{ -public: - real_1d_array(); - real_1d_array(const real_1d_array &rhs); - real_1d_array(alglib_impl::ae_vector *p); - const real_1d_array& operator=(const real_1d_array &rhs); - virtual ~real_1d_array(); - - const double& operator()(ae_int_t i) const; - double& operator()(ae_int_t i); - - const double& operator[](ae_int_t i) const; - double& operator[](ae_int_t i); - - // - // This function allocates array[iLen] and copies data - // pointed by pContent to its memory. Completely independent - // copy of data is created. - // - void setcontent(ae_int_t iLen, const double *pContent); - - // - // This function attaches array to memory pointed by pContent. - // No own memory is allocated, no copying of data is performed, - // so pContent pointer should be valid as long as we work with - // array. - // - // After you attach array object to external memory, it becomes - // "frozen": it is possible to read/write array elements, but - // it is not allowed to resize it (no setlength() calls). - // - void attach_to_ptr(ae_int_t iLen, double *pContent); - - // - // This function returns pointer to internal memory - // - double* getcontent(); - const double* getcontent() const; - -#if !defined(AE_NO_EXCEPTIONS) - real_1d_array(const char *s); - std::string tostring(int dps) const; -#endif -}; - -class complex_1d_array : public ae_vector_wrapper -{ -public: - complex_1d_array(); - complex_1d_array(const complex_1d_array &rhs); - complex_1d_array(alglib_impl::ae_vector *p); - const complex_1d_array& operator=(const complex_1d_array &rhs); - virtual ~complex_1d_array(); - - const alglib::complex& operator()(ae_int_t i) const; - alglib::complex& operator()(ae_int_t i); - - const alglib::complex& operator[](ae_int_t i) const; - alglib::complex& operator[](ae_int_t i); - - // - // This function allocates array[iLen] and copies data - // pointed by pContent to its memory. Completely independent - // copy of data is created. - // - void setcontent(ae_int_t iLen, const alglib::complex *pContent ); - alglib::complex* getcontent(); - const alglib::complex* getcontent() const; - -#if !defined(AE_NO_EXCEPTIONS) - complex_1d_array(const char *s); - std::string tostring(int dps) const; -#endif -}; - -class ae_matrix_wrapper -{ -public: - // - // Creates object attached to external ae_vector structure, with additional - // check for matching datatypes (e_ptr->datatype==datatype is required). - // - ae_matrix_wrapper(alglib_impl::ae_matrix *e_ptr, alglib_impl::ae_datatype datatype); - - // - // Creates zero-sized matrix of specified datatype. - // - ae_matrix_wrapper(alglib_impl::ae_datatype datatype); - - // - // Creates copy of rhs, with additional check for matching datatypes - // (rhs.datatype==datatype is required). - // - ae_matrix_wrapper(const ae_matrix_wrapper &rhs, alglib_impl::ae_datatype datatype); - - // - // Destructor - // - virtual ~ae_matrix_wrapper(); - - - void setlength(ae_int_t rows, ae_int_t cols); - ae_int_t rows() const; - ae_int_t cols() const; - bool isempty() const; - ae_int_t getstride() const; - - const alglib_impl::ae_matrix* c_ptr() const; - alglib_impl::ae_matrix* c_ptr(); -private: - ae_matrix_wrapper(); - ae_matrix_wrapper(const ae_matrix_wrapper &rhs); - const ae_matrix_wrapper& operator=(const ae_matrix_wrapper &rhs); -protected: -#if !defined(AE_NO_EXCEPTIONS) - // - // Copies array given by string into current object. Additional - // parameter DATATYPE contains information about type of the data - // in S and type of the array to create. - // - // Current object is considered empty (this function should be - // called from copy constructor). - // - ae_matrix_wrapper(const char *s, alglib_impl::ae_datatype datatype); -#endif - - // - // This function attaches wrapper object to external x_vector structure; - // "frozen proxy" mode is activated (you can read/write, but can not reallocate - // and do not own memory of the vector). - // - // NOTE: initial state of wrapper object is assumed to be initialized; - // all previously allocated memory is properly deallocated. - // - // NOTE: x_vector structure pointed by new_ptr is used only once; after - // we fetch pointer to memory and its size, this structure is ignored - // and not referenced anymore. So, you can pass pointers to temporary - // x-structures which are deallocated immediately after you call attach_to() - // - // NOTE: state structure is used for error-handling (a longjmp is performed - // on allocation error). All previously allocated memory is correctly - // freed on error. - // - void attach_to(alglib_impl::x_matrix *new_ptr, alglib_impl::ae_state *_state); - - // - // This function initializes matrix and allocates own memory storage. - // - // NOTE: initial state of wrapper object is assumed to be uninitialized; - // if ptr!=NULL on entry, it is considered critical error (abort is called). - // - void init(ae_int_t rows, ae_int_t cols, alglib_impl::ae_datatype datatype, alglib_impl::ae_state *_state); - - // - // Assigns RHS to current object. - // - // It has several branches depending on target object status: - // * in case it is proxy object, data are copied into memory pointed by - // proxy. Function checks that source has exactly same size as target - // (exception is thrown on failure). - // * in case it is non-proxy object, data allocated by object are cleared - // and a copy of RHS is created in target. - // - // NOTE: this function correctly handles assignments of the object to itself. - // - const ae_matrix_wrapper & assign(const ae_matrix_wrapper &rhs); - - - // - // Pointer to ae_matrix structure: - // * ptr==&inner_mat means that wrapper object owns ae_matrix structure and - // is responsible for proper deallocation of its memory - // * ptr!=&inner_mat means that wrapper object works with someone's other - // ae_matrix record and is not responsible for its memory; in this case - // inner_mat is assumed to be uninitialized. - // - alglib_impl::ae_matrix *ptr; - - // - // Inner ae_matrix record. - // Ignored for ptr!=&inner_mat. - // - alglib_impl::ae_matrix inner_mat; - - // - // Whether this wrapper object is frozen proxy (you may read array, may - // modify its value, but can not deallocate its memory or resize it) or not. - // - // If is_frozen_proxy==true and if: - // * ptr==&inner_vec, it means that wrapper works with its own ae_vector - // structure, but this structure points to externally allocated memory. - // This memory is NOT owned by ae_vector object. - // * ptr!=&inner_vec, it means that wrapper works with externally allocated - // and managed ae_vector structure. Both memory pointed by ae_vector and - // ae_vector structure itself are not owned by wrapper object. - // - bool is_frozen_proxy; -}; - -class boolean_2d_array : public ae_matrix_wrapper -{ -public: - boolean_2d_array(); - boolean_2d_array(const boolean_2d_array &rhs); - boolean_2d_array(alglib_impl::ae_matrix *p); - virtual ~boolean_2d_array(); - - const boolean_2d_array& operator=(const boolean_2d_array &rhs); - - const ae_bool& operator()(ae_int_t i, ae_int_t j) const; - ae_bool& operator()(ae_int_t i, ae_int_t j); - - const ae_bool* operator[](ae_int_t i) const; - ae_bool* operator[](ae_int_t i); - - // - // This function allocates array[irows,icols] and copies data - // pointed by pContent to its memory. Completely independent - // copy of data is created. - // - void setcontent(ae_int_t irows, ae_int_t icols, const bool *pContent ); - -#if !defined(AE_NO_EXCEPTIONS) - boolean_2d_array(const char *s); - std::string tostring() const ; -#endif -}; - -class integer_2d_array : public ae_matrix_wrapper -{ -public: - integer_2d_array(); - integer_2d_array(const integer_2d_array &rhs); - integer_2d_array(alglib_impl::ae_matrix *p); - virtual ~integer_2d_array(); - - const integer_2d_array& operator=(const integer_2d_array &rhs); - - const ae_int_t& operator()(ae_int_t i, ae_int_t j) const; - ae_int_t& operator()(ae_int_t i, ae_int_t j); - - const ae_int_t* operator[](ae_int_t i) const; - ae_int_t* operator[](ae_int_t i); - - // - // This function allocates array[irows,icols] and copies data - // pointed by pContent to its memory. Completely independent - // copy of data is created. - // - void setcontent(ae_int_t irows, ae_int_t icols, const ae_int_t *pContent ); - - -#if !defined(AE_NO_EXCEPTIONS) - integer_2d_array(const char *s); - std::string tostring() const; -#endif -}; - -class real_2d_array : public ae_matrix_wrapper -{ -public: - real_2d_array(); - real_2d_array(const real_2d_array &rhs); - real_2d_array(alglib_impl::ae_matrix *p); - virtual ~real_2d_array(); - - const real_2d_array& operator=(const real_2d_array &rhs); - - const double& operator()(ae_int_t i, ae_int_t j) const; - double& operator()(ae_int_t i, ae_int_t j); - - const double* operator[](ae_int_t i) const; - double* operator[](ae_int_t i); - - // - // This function allocates array[irows,icols] and copies data - // pointed by pContent to its memory. Completely independent - // copy of data is created. - // - void setcontent(ae_int_t irows, ae_int_t icols, const double *pContent); - - // - // This function attaches array to memory pointed by pContent: - // * only minor amount of own memory is allocated - O(irows) bytes to - // store precomputed pointers; but no costly copying of O(rows*cols) - // data is performed. - // * pContent pointer should be valid as long as we work with array - // - // After you attach array object to external memory, it becomes - // "frozen": it is possible to read/write array elements, but - // it is not allowed to resize it (no setlength() calls). - // - void attach_to_ptr(ae_int_t irows, ae_int_t icols, double *pContent); - -#if !defined(AE_NO_EXCEPTIONS) - real_2d_array(const char *s); - std::string tostring(int dps) const; -#endif -}; - -class complex_2d_array : public ae_matrix_wrapper -{ -public: - complex_2d_array(); - complex_2d_array(const complex_2d_array &rhs); - complex_2d_array(alglib_impl::ae_matrix *p); - virtual ~complex_2d_array(); - - const complex_2d_array& operator=(const complex_2d_array &rhs); - - const alglib::complex& operator()(ae_int_t i, ae_int_t j) const; - alglib::complex& operator()(ae_int_t i, ae_int_t j); - - const alglib::complex* operator[](ae_int_t i) const; - alglib::complex* operator[](ae_int_t i); - - // - // This function allocates array[irows,icols] and copies data - // pointed by pContent to its memory. Completely independent - // copy of data is created. - // - void setcontent(ae_int_t irows, ae_int_t icols, const alglib::complex *pContent ); - -#if !defined(AE_NO_EXCEPTIONS) - complex_2d_array(const char *s); - std::string tostring(int dps) const; -#endif -}; - -/******************************************************************** -CSV operations: reading CSV file to real matrix. - -This function reads CSV file and stores its contents to double -precision 2D array. Format of the data file must conform to RFC 4180 -specification, with additional notes: -* file size should be less than 2GB -* ASCI encoding, UTF-8 without BOM (in header names) are supported -* any character (comma/tab/space) may be used as field separator, as - long as it is distinct from one used for decimal point -* multiple subsequent field separators (say, two spaces) are treated - as MULTIPLE separators, not one big separator -* both comma and full stop may be used as decimal point. Parser will - automatically determine specific character being used. Both fixed - and exponential number formats are allowed. Thousand separators - are NOT allowed. -* line may end with \n (Unix style) or \r\n (Windows style), parser - will automatically adapt to chosen convention -* escaped fields (ones in double quotes) are not supported - -INPUT PARAMETERS: - filename relative/absolute path - separator character used to separate fields. May be ' ', - ',', '\t'. Other separators are possible too. - flags several values combined with bitwise OR: - * alglib::CSV_SKIP_HEADERS - if present, first row - contains headers and will be skipped. Its - contents is used to determine fields count, and - that's all. - If no flags are specified, default value 0x0 (or - alglib::CSV_DEFAULT, which is same) should be used. - -OUTPUT PARAMETERS: - out 2D matrix, CSV file parsed with atof() - -HANDLING OF SPECIAL CASES: -* file does not exist - alglib::ap_error exception is thrown -* empty file - empty array is returned (no exception) -* skip_first_row=true, only one row in file - empty array is returned -* field contents is not recognized by atof() - field value is replaced - by 0.0 -********************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void read_csv(const char *filename, char separator, int flags, alglib::real_2d_array &out); -#endif - - -/******************************************************************** -This function activates trace output, with trace log being saved to -file (appended to the end). - -Tracing allows us to study behavior of ALGLIB solvers and to debug -their failures: -* tracing is limited by one/several ALGLIB parts specified by means - of trace tags, like "SLP" (for SLP solver) or "OPTGUARD" (OptGuard - integrity checker). -* some ALGLIB solvers support hierarchies of trace tags which activate - different kinds of tracing. Say, "SLP" defines some basic tracing, - but "SLP.PROBING" defines more detailed and costly tracing. -* generally, "TRACETAG.SUBTAG" also implicitly activates logging - which is activated by "TRACETAG" -* you may define multiple trace tags by separating them with commas, - like "SLP,OPTGUARD,SLP.PROBING" -* trace tags are case-insensitive -* spaces/tabs are NOT allowed in the tags string - -Trace log is saved to file "filename", which is opened in the append -mode. If no file with such name can be opened, tracing won't be -performed (but no exception will be generated). -********************************************************************/ -void trace_file(std::string tags, std::string filename); - - -/******************************************************************** -This function disables tracing. -********************************************************************/ -void trace_disable(); - - -/******************************************************************** -Constants and functions introduced for compatibility with AlgoPascal -********************************************************************/ -extern const double machineepsilon; -extern const double maxrealnumber; -extern const double minrealnumber; -extern const double fp_nan; -extern const double fp_posinf; -extern const double fp_neginf; -extern const ae_int_t endianness; -static const int CSV_DEFAULT = 0x0; -static const int CSV_SKIP_HEADERS = 0x1; - -int sign(double x); -double randomreal(); -ae_int_t randominteger(ae_int_t maxv); -int round(double x); -int trunc(double x); -int ifloor(double x); -int iceil(double x); -double pi(); -double sqr(double x); -int maxint(int m1, int m2); -int minint(int m1, int m2); -double maxreal(double m1, double m2); -double minreal(double m1, double m2); - -bool fp_eq(double v1, double v2); -bool fp_neq(double v1, double v2); -bool fp_less(double v1, double v2); -bool fp_less_eq(double v1, double v2); -bool fp_greater(double v1, double v2); -bool fp_greater_eq(double v1, double v2); - -bool fp_isnan(double x); -bool fp_isposinf(double x); -bool fp_isneginf(double x); -bool fp_isinf(double x); -bool fp_isfinite(double x); - -/******************************************************************** -Exception handling macros -********************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -/////////////////////////////////////// -// exception-based code -////////////////////////////// -#define _ALGLIB_CPP_EXCEPTION(msg) throw alglib::ap_error(msg) -#define _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN try{ -#define _ALGLIB_CALLBACK_EXCEPTION_GUARD_END }catch(...){ ae_clean_up_before_breaking(&_alglib_env_state); throw; } - -#else - -/////////////////////////////////////// -// Exception-free version -////////////////////////////// -#if AE_OS!=AE_UNKNOWN -#error Exception-free mode can not be combined with AE_OS definition -#endif -#if AE_THREADING!=AE_SERIAL_UNSAFE -#error Exception-free mode is thread-unsafe; define AE_THREADING=AE_SERIAL_UNSAFE to prove that you know it -#endif -#define _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN -#define _ALGLIB_CALLBACK_EXCEPTION_GUARD_END -#define _ALGLIB_SET_ERROR_FLAG(s) set_error_flag(s) - -// sets eror flag and (optionally) sets error message -void set_error_flag(const char *s = NULL); - -// returns error flag and optionally returns error message (loaded to *p_msg); -// if error flag is not set (or p_msg is NULL) *p_msg is not changed. -bool get_error_flag(const char **p_msg = NULL); - -// clears error flag (it is not cleared until explicit call to this function) -void clear_error_flag(); -#endif - -}//namespace alglib - - - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTIONS CONTAINS DECLARATIONS FOR OPTIMIZED LINEAR ALGEBRA CODES -// IT IS SHARED BETWEEN C++ AND PURE C LIBRARIES -// -///////////////////////////////////////////////////////////////////////// - -namespace alglib_impl -{ -#define ALGLIB_INTERCEPTS_ABLAS -void _ialglib_vzero(ae_int_t n, double *p, ae_int_t stride); -void _ialglib_vzero_complex(ae_int_t n, ae_complex *p, ae_int_t stride); -void _ialglib_vcopy(ae_int_t n, const double *a, ae_int_t stridea, double *b, ae_int_t strideb); -void _ialglib_vcopy_complex(ae_int_t n, const ae_complex *a, ae_int_t stridea, double *b, ae_int_t strideb, const char *conj); -void _ialglib_vcopy_dcomplex(ae_int_t n, const double *a, ae_int_t stridea, double *b, ae_int_t strideb, const char *conj); -void _ialglib_mcopyblock(ae_int_t m, ae_int_t n, const double *a, ae_int_t op, ae_int_t stride, double *b); -void _ialglib_mcopyunblock(ae_int_t m, ae_int_t n, const double *a, ae_int_t op, double *b, ae_int_t stride); -void _ialglib_mcopyblock_complex(ae_int_t m, ae_int_t n, const ae_complex *a, ae_int_t op, ae_int_t stride, double *b); -void _ialglib_mcopyunblock_complex(ae_int_t m, ae_int_t n, const double *a, ae_int_t op, ae_complex* b, ae_int_t stride); - -ae_bool _ialglib_i_rmatrixgemmf(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - ae_matrix *a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - ae_matrix *b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - double beta, - ae_matrix *c, - ae_int_t ic, - ae_int_t jc); -ae_bool _ialglib_i_cmatrixgemmf(ae_int_t m, - ae_int_t n, - ae_int_t k, - ae_complex alpha, - ae_matrix *a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - ae_matrix *b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - ae_complex beta, - ae_matrix *c, - ae_int_t ic, - ae_int_t jc); -ae_bool _ialglib_i_cmatrixrighttrsmf(ae_int_t m, - ae_int_t n, - ae_matrix *a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - ae_matrix *x, - ae_int_t i2, - ae_int_t j2); -ae_bool _ialglib_i_rmatrixrighttrsmf(ae_int_t m, - ae_int_t n, - ae_matrix *a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - ae_matrix *x, - ae_int_t i2, - ae_int_t j2); -ae_bool _ialglib_i_cmatrixlefttrsmf(ae_int_t m, - ae_int_t n, - ae_matrix *a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - ae_matrix *x, - ae_int_t i2, - ae_int_t j2); -ae_bool _ialglib_i_rmatrixlefttrsmf(ae_int_t m, - ae_int_t n, - ae_matrix *a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - ae_matrix *x, - ae_int_t i2, - ae_int_t j2); -ae_bool _ialglib_i_cmatrixherkf(ae_int_t n, - ae_int_t k, - double alpha, - ae_matrix *a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - ae_matrix *c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper); -ae_bool _ialglib_i_rmatrixsyrkf(ae_int_t n, - ae_int_t k, - double alpha, - ae_matrix *a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - ae_matrix *c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper); -ae_bool _ialglib_i_cmatrixrank1f(ae_int_t m, - ae_int_t n, - ae_matrix *a, - ae_int_t ia, - ae_int_t ja, - ae_vector *u, - ae_int_t uoffs, - ae_vector *v, - ae_int_t voffs); -ae_bool _ialglib_i_rmatrixrank1f(ae_int_t m, - ae_int_t n, - ae_matrix *a, - ae_int_t ia, - ae_int_t ja, - ae_vector *u, - ae_int_t uoffs, - ae_vector *v, - ae_int_t voffs); -ae_bool _ialglib_i_rmatrixgerf(ae_int_t m, - ae_int_t n, - ae_matrix *a, - ae_int_t ia, - ae_int_t ja, - double alpha, - ae_vector *u, - ae_int_t uoffs, - ae_vector *v, - ae_int_t voffs); - - - -} - - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS PARALLEL SUBROUTINES -// -///////////////////////////////////////////////////////////////////////// - -namespace alglib_impl -{ - -} - - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS DEFINITIONS FOR PARTIAL COMPILATION -// -///////////////////////////////////////////////////////////////////////// -#ifdef AE_COMPILE_SCODES -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_APSERV -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_TSORT -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#endif - -#ifdef AE_COMPILE_NEARESTNEIGHBOR -#define AE_PARTIAL_BUILD -#define AE_COMPILE_SCODES -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#endif - -#ifdef AE_COMPILE_ABLASF -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_HQRND -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#endif - -#ifdef AE_COMPILE_XDEBUG -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_ODESOLVER -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#endif - -#ifdef AE_COMPILE_ABLASMKL -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_SPARSE -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#endif - -#ifdef AE_COMPILE_ABLAS -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#endif - -#ifdef AE_COMPILE_DLU -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#endif - -#ifdef AE_COMPILE_SPTRF -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#endif - -#ifdef AE_COMPILE_AMDORDERING -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#endif - -#ifdef AE_COMPILE_SPCHOL -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_AMDORDERING -#endif - -#ifdef AE_COMPILE_CREFLECTIONS -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_MATGEN -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_HQRND -#endif - -#ifdef AE_COMPILE_ROTATIONS -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_TRFAC -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#endif - -#ifdef AE_COMPILE_TRLINSOLVE -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_SAFESOLVE -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_RCOND -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#endif - -#ifdef AE_COMPILE_MATINV -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#endif - -#ifdef AE_COMPILE_HBLAS -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_SBLAS -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#endif - -#ifdef AE_COMPILE_ORTFAC -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_HBLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#endif - -#ifdef AE_COMPILE_FBLS -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_HQRND -#define AE_COMPILE_HBLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#endif - -#ifdef AE_COMPILE_CQMODELS -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_FBLS -#endif - -#ifdef AE_COMPILE_OPTGUARDAPI -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#endif - -#ifdef AE_COMPILE_BLAS -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_BDSVD -#define AE_PARTIAL_BUILD -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#endif - -#ifdef AE_COMPILE_SVD -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_HBLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_BDSVD -#endif - -#ifdef AE_COMPILE_OPTSERV -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_HQRND -#define AE_COMPILE_MATGEN -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#endif - -#ifdef AE_COMPILE_SNNLS -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_FBLS -#endif - -#ifdef AE_COMPILE_SACTIVESETS -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_FBLS -#define AE_COMPILE_SNNLS -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_OPTSERV -#endif - -#ifdef AE_COMPILE_QQPSOLVER -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_ABLAS -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_FBLS -#define AE_COMPILE_CQMODELS -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_SNNLS -#define AE_COMPILE_SACTIVESETS -#endif - -#ifdef AE_COMPILE_LINMIN -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_XBLAS -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_DIRECTDENSESOLVERS -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_HBLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_MATGEN -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_XBLAS -#endif - -#ifdef AE_COMPILE_MINLBFGS -#define AE_PARTIAL_BUILD -#define AE_COMPILE_LINMIN -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_HQRND -#define AE_COMPILE_MATGEN -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_FBLS -#endif - -#ifdef AE_COMPILE_LPQPSERV -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#endif - -#ifdef AE_COMPILE_VIPMSOLVER -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_HBLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ABLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_MATGEN -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_XBLAS -#define AE_COMPILE_DIRECTDENSESOLVERS -#define AE_COMPILE_LINMIN -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_MATINV -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_FBLS -#define AE_COMPILE_MINLBFGS -#define AE_COMPILE_CQMODELS -#define AE_COMPILE_LPQPSERV -#endif - -#ifdef AE_COMPILE_NLCSQP -#define AE_PARTIAL_BUILD -#define AE_COMPILE_LINMIN -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_TSORT -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_HQRND -#define AE_COMPILE_MATGEN -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_XBLAS -#define AE_COMPILE_DIRECTDENSESOLVERS -#define AE_COMPILE_FBLS -#define AE_COMPILE_MINLBFGS -#define AE_COMPILE_CQMODELS -#define AE_COMPILE_LPQPSERV -#define AE_COMPILE_VIPMSOLVER -#endif - -#ifdef AE_COMPILE_NORMESTIMATOR -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_ABLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#endif - -#ifdef AE_COMPILE_LINLSQR -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_HQRND -#define AE_COMPILE_MATGEN -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_NORMESTIMATOR -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#endif - -#ifdef AE_COMPILE_QPDENSEAULSOLVER -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_ABLAS -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_XBLAS -#define AE_COMPILE_DIRECTDENSESOLVERS -#define AE_COMPILE_NORMESTIMATOR -#define AE_COMPILE_LINLSQR -#define AE_COMPILE_LINMIN -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_FBLS -#define AE_COMPILE_MINLBFGS -#define AE_COMPILE_CQMODELS -#define AE_COMPILE_LPQPSERV -#define AE_COMPILE_SNNLS -#define AE_COMPILE_SACTIVESETS -#define AE_COMPILE_QQPSOLVER -#endif - -#ifdef AE_COMPILE_MINBLEIC -#define AE_PARTIAL_BUILD -#define AE_COMPILE_LINMIN -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_HQRND -#define AE_COMPILE_MATGEN -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_FBLS -#define AE_COMPILE_CQMODELS -#define AE_COMPILE_SNNLS -#define AE_COMPILE_SACTIVESETS -#endif - -#ifdef AE_COMPILE_QPBLEICSOLVER -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_ABLAS -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_LINMIN -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_FBLS -#define AE_COMPILE_CQMODELS -#define AE_COMPILE_SNNLS -#define AE_COMPILE_SACTIVESETS -#define AE_COMPILE_MINBLEIC -#endif - -#ifdef AE_COMPILE_MINQP -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_ABLAS -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_XBLAS -#define AE_COMPILE_DIRECTDENSESOLVERS -#define AE_COMPILE_NORMESTIMATOR -#define AE_COMPILE_LINLSQR -#define AE_COMPILE_LINMIN -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_FBLS -#define AE_COMPILE_MINLBFGS -#define AE_COMPILE_CQMODELS -#define AE_COMPILE_LPQPSERV -#define AE_COMPILE_SNNLS -#define AE_COMPILE_SACTIVESETS -#define AE_COMPILE_QQPSOLVER -#define AE_COMPILE_QPDENSEAULSOLVER -#define AE_COMPILE_MINBLEIC -#define AE_COMPILE_QPBLEICSOLVER -#define AE_COMPILE_VIPMSOLVER -#endif - -#ifdef AE_COMPILE_LPQPPRESOLVE -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#endif - -#ifdef AE_COMPILE_REVISEDDUALSIMPLEX -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_LPQPPRESOLVE -#endif - -#ifdef AE_COMPILE_MINLP -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_ABLAS -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_LPQPPRESOLVE -#define AE_COMPILE_REVISEDDUALSIMPLEX -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_XBLAS -#define AE_COMPILE_DIRECTDENSESOLVERS -#define AE_COMPILE_LINMIN -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_MATINV -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_FBLS -#define AE_COMPILE_MINLBFGS -#define AE_COMPILE_CQMODELS -#define AE_COMPILE_LPQPSERV -#define AE_COMPILE_VIPMSOLVER -#endif - -#ifdef AE_COMPILE_NLCSLP -#define AE_PARTIAL_BUILD -#define AE_COMPILE_LINMIN -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_HQRND -#define AE_COMPILE_MATGEN -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_LPQPPRESOLVE -#define AE_COMPILE_REVISEDDUALSIMPLEX -#endif - -#ifdef AE_COMPILE_MINNLC -#define AE_PARTIAL_BUILD -#define AE_COMPILE_LINMIN -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_HQRND -#define AE_COMPILE_MATGEN -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_FBLS -#define AE_COMPILE_SNNLS -#define AE_COMPILE_MINLBFGS -#define AE_COMPILE_CQMODELS -#define AE_COMPILE_SACTIVESETS -#define AE_COMPILE_MINBLEIC -#define AE_COMPILE_LPQPPRESOLVE -#define AE_COMPILE_REVISEDDUALSIMPLEX -#define AE_COMPILE_NLCSLP -#define AE_COMPILE_XBLAS -#define AE_COMPILE_DIRECTDENSESOLVERS -#define AE_COMPILE_LPQPSERV -#define AE_COMPILE_VIPMSOLVER -#define AE_COMPILE_NLCSQP -#endif - -#ifdef AE_COMPILE_MINBC -#define AE_PARTIAL_BUILD -#define AE_COMPILE_LINMIN -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_HQRND -#define AE_COMPILE_MATGEN -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_OPTSERV -#endif - -#ifdef AE_COMPILE_MINNS -#define AE_PARTIAL_BUILD -#define AE_COMPILE_LINMIN -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_HQRND -#define AE_COMPILE_MATGEN -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_FBLS -#define AE_COMPILE_SNNLS -#define AE_COMPILE_CQMODELS -#define AE_COMPILE_SACTIVESETS -#define AE_COMPILE_MINBLEIC -#endif - -#ifdef AE_COMPILE_MINCOMP -#define AE_PARTIAL_BUILD -#define AE_COMPILE_LINMIN -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_HQRND -#define AE_COMPILE_MATGEN -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_FBLS -#define AE_COMPILE_MINLBFGS -#define AE_COMPILE_CQMODELS -#define AE_COMPILE_SNNLS -#define AE_COMPILE_SACTIVESETS -#define AE_COMPILE_MINBLEIC -#endif - -#ifdef AE_COMPILE_MINCG -#define AE_PARTIAL_BUILD -#define AE_COMPILE_LINMIN -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_HQRND -#define AE_COMPILE_MATGEN -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_OPTSERV -#endif - -#ifdef AE_COMPILE_MINLM -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_HQRND -#define AE_COMPILE_MATGEN -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_XBLAS -#define AE_COMPILE_DIRECTDENSESOLVERS -#define AE_COMPILE_NORMESTIMATOR -#define AE_COMPILE_LINLSQR -#define AE_COMPILE_LINMIN -#define AE_COMPILE_FBLS -#define AE_COMPILE_MINLBFGS -#define AE_COMPILE_CQMODELS -#define AE_COMPILE_LPQPSERV -#define AE_COMPILE_SNNLS -#define AE_COMPILE_SACTIVESETS -#define AE_COMPILE_QQPSOLVER -#define AE_COMPILE_QPDENSEAULSOLVER -#define AE_COMPILE_MINBLEIC -#define AE_COMPILE_QPBLEICSOLVER -#define AE_COMPILE_VIPMSOLVER -#define AE_COMPILE_MINQP -#endif - -#ifdef AE_COMPILE_HSSCHUR -#define AE_PARTIAL_BUILD -#define AE_COMPILE_BLAS -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLAS -#endif - -#ifdef AE_COMPILE_BASICSTATOPS -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#endif - -#ifdef AE_COMPILE_EVD -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_HBLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_MATGEN -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_BLAS -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_HSSCHUR -#define AE_COMPILE_BASICSTATOPS -#endif - -#ifdef AE_COMPILE_BASESTAT -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#endif - -#ifdef AE_COMPILE_PCA -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_HBLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_MATGEN -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_HSSCHUR -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_EVD -#define AE_COMPILE_BASESTAT -#endif - -#ifdef AE_COMPILE_BDSS -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_BASESTAT -#endif - -#ifdef AE_COMPILE_HPCCORES -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_MLPBASE -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_BASESTAT -#define AE_COMPILE_BDSS -#define AE_COMPILE_HPCCORES -#define AE_COMPILE_SCODES -#define AE_COMPILE_HQRND -#define AE_COMPILE_SPARSE -#endif - -#ifdef AE_COMPILE_LDA -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_HBLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_MATGEN -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_BLAS -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_HSSCHUR -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_EVD -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#endif - -#ifdef AE_COMPILE_SSA -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_HBLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_MATGEN -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_HSSCHUR -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_EVD -#endif - -#ifdef AE_COMPILE_GAMMAFUNC -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_NORMALDISTR -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#endif - -#ifdef AE_COMPILE_IGAMMAF -#define AE_PARTIAL_BUILD -#define AE_COMPILE_GAMMAFUNC -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_NORMALDISTR -#endif - -#ifdef AE_COMPILE_LINREG -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_BASESTAT -#define AE_COMPILE_GAMMAFUNC -#define AE_COMPILE_HQRND -#define AE_COMPILE_NORMALDISTR -#define AE_COMPILE_IGAMMAF -#define AE_COMPILE_HBLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#endif - -#ifdef AE_COMPILE_FILTERS -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_BASESTAT -#define AE_COMPILE_GAMMAFUNC -#define AE_COMPILE_HQRND -#define AE_COMPILE_NORMALDISTR -#define AE_COMPILE_IGAMMAF -#define AE_COMPILE_HBLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_LINREG -#endif - -#ifdef AE_COMPILE_LOGIT -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_BASESTAT -#define AE_COMPILE_BDSS -#define AE_COMPILE_HPCCORES -#define AE_COMPILE_SCODES -#define AE_COMPILE_HQRND -#define AE_COMPILE_SPARSE -#define AE_COMPILE_MLPBASE -#define AE_COMPILE_HBLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_MATGEN -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_XBLAS -#define AE_COMPILE_DIRECTDENSESOLVERS -#endif - -#ifdef AE_COMPILE_MCPD -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_LINMIN -#define AE_COMPILE_TSORT -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_HQRND -#define AE_COMPILE_MATGEN -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_FBLS -#define AE_COMPILE_CQMODELS -#define AE_COMPILE_SNNLS -#define AE_COMPILE_SACTIVESETS -#define AE_COMPILE_MINBLEIC -#endif - -#ifdef AE_COMPILE_MLPE -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_BASESTAT -#define AE_COMPILE_BDSS -#define AE_COMPILE_HPCCORES -#define AE_COMPILE_SCODES -#define AE_COMPILE_HQRND -#define AE_COMPILE_SPARSE -#define AE_COMPILE_MLPBASE -#endif - -#ifdef AE_COMPILE_MLPTRAIN -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_BASESTAT -#define AE_COMPILE_BDSS -#define AE_COMPILE_HPCCORES -#define AE_COMPILE_SCODES -#define AE_COMPILE_HQRND -#define AE_COMPILE_SPARSE -#define AE_COMPILE_MLPBASE -#define AE_COMPILE_MLPE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_LINMIN -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_FBLS -#define AE_COMPILE_MINLBFGS -#define AE_COMPILE_XBLAS -#define AE_COMPILE_DIRECTDENSESOLVERS -#endif - -#ifdef AE_COMPILE_CLUSTERING -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_BLAS -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_BASESTAT -#endif - -#ifdef AE_COMPILE_DFOREST -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_SCODES -#define AE_COMPILE_TSORT -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_BASESTAT -#define AE_COMPILE_BDSS -#endif - -#ifdef AE_COMPILE_KNN -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_SCODES -#define AE_COMPILE_TSORT -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_NEARESTNEIGHBOR -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_BASESTAT -#define AE_COMPILE_BDSS -#endif - -#ifdef AE_COMPILE_DATACOMP -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_BLAS -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_BASESTAT -#define AE_COMPILE_CLUSTERING -#endif - -#ifdef AE_COMPILE_GQ -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_HBLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_MATGEN -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_BLAS -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_HSSCHUR -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_EVD -#define AE_COMPILE_GAMMAFUNC -#endif - -#ifdef AE_COMPILE_GKQ -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_HBLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_MATGEN -#define AE_COMPILE_SPARSE -#define AE_COMPILE_BLAS -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_HSSCHUR -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_EVD -#define AE_COMPILE_GAMMAFUNC -#define AE_COMPILE_GQ -#endif - -#ifdef AE_COMPILE_AUTOGK -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_HBLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_MATGEN -#define AE_COMPILE_SPARSE -#define AE_COMPILE_BLAS -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_HSSCHUR -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_EVD -#define AE_COMPILE_GAMMAFUNC -#define AE_COMPILE_GQ -#define AE_COMPILE_GKQ -#endif - -#ifdef AE_COMPILE_NTHEORY -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_FTBASE -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_NTHEORY -#endif - -#ifdef AE_COMPILE_FFT -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_NTHEORY -#define AE_COMPILE_FTBASE -#endif - -#ifdef AE_COMPILE_FHT -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_NTHEORY -#define AE_COMPILE_FTBASE -#define AE_COMPILE_FFT -#endif - -#ifdef AE_COMPILE_CONV -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_NTHEORY -#define AE_COMPILE_FTBASE -#define AE_COMPILE_FFT -#endif - -#ifdef AE_COMPILE_CORR -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_NTHEORY -#define AE_COMPILE_FTBASE -#define AE_COMPILE_FFT -#define AE_COMPILE_CONV -#endif - -#ifdef AE_COMPILE_IDW -#define AE_PARTIAL_BUILD -#define AE_COMPILE_SCODES -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_NEARESTNEIGHBOR -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#endif - -#ifdef AE_COMPILE_RATINT -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#endif - -#ifdef AE_COMPILE_FITSPHERE -#define AE_PARTIAL_BUILD -#define AE_COMPILE_LINMIN -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_HQRND -#define AE_COMPILE_MATGEN -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_FBLS -#define AE_COMPILE_CQMODELS -#define AE_COMPILE_SNNLS -#define AE_COMPILE_SACTIVESETS -#define AE_COMPILE_MINBLEIC -#define AE_COMPILE_XBLAS -#define AE_COMPILE_DIRECTDENSESOLVERS -#define AE_COMPILE_NORMESTIMATOR -#define AE_COMPILE_LINLSQR -#define AE_COMPILE_MINLBFGS -#define AE_COMPILE_LPQPSERV -#define AE_COMPILE_QQPSOLVER -#define AE_COMPILE_QPDENSEAULSOLVER -#define AE_COMPILE_QPBLEICSOLVER -#define AE_COMPILE_VIPMSOLVER -#define AE_COMPILE_MINQP -#define AE_COMPILE_MINLM -#define AE_COMPILE_LPQPPRESOLVE -#define AE_COMPILE_REVISEDDUALSIMPLEX -#define AE_COMPILE_NLCSLP -#define AE_COMPILE_NLCSQP -#define AE_COMPILE_MINNLC -#endif - -#ifdef AE_COMPILE_INTFITSERV -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#endif - -#ifdef AE_COMPILE_SPLINE1D -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_INTFITSERV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_FBLS -#define AE_COMPILE_NORMESTIMATOR -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_LINLSQR -#endif - -#ifdef AE_COMPILE_PARAMETRIC -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_INTFITSERV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_FBLS -#define AE_COMPILE_NORMESTIMATOR -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_LINLSQR -#define AE_COMPILE_SPLINE1D -#define AE_COMPILE_HSSCHUR -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_EVD -#define AE_COMPILE_GAMMAFUNC -#define AE_COMPILE_GQ -#define AE_COMPILE_GKQ -#define AE_COMPILE_AUTOGK -#endif - -#ifdef AE_COMPILE_SPLINE3D -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_INTFITSERV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_FBLS -#define AE_COMPILE_NORMESTIMATOR -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_LINLSQR -#define AE_COMPILE_SPLINE1D -#endif - -#ifdef AE_COMPILE_POLINT -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_RATINT -#endif - -#ifdef AE_COMPILE_LSFIT -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_INTFITSERV -#define AE_COMPILE_RATINT -#define AE_COMPILE_POLINT -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_FBLS -#define AE_COMPILE_NORMESTIMATOR -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_LINLSQR -#define AE_COMPILE_SPLINE1D -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_XBLAS -#define AE_COMPILE_DIRECTDENSESOLVERS -#define AE_COMPILE_LINMIN -#define AE_COMPILE_MINLBFGS -#define AE_COMPILE_CQMODELS -#define AE_COMPILE_LPQPSERV -#define AE_COMPILE_SNNLS -#define AE_COMPILE_SACTIVESETS -#define AE_COMPILE_QQPSOLVER -#define AE_COMPILE_QPDENSEAULSOLVER -#define AE_COMPILE_MINBLEIC -#define AE_COMPILE_QPBLEICSOLVER -#define AE_COMPILE_VIPMSOLVER -#define AE_COMPILE_MINQP -#define AE_COMPILE_MINLM -#endif - -#ifdef AE_COMPILE_RBFV2 -#define AE_PARTIAL_BUILD -#define AE_COMPILE_SCODES -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_NEARESTNEIGHBOR -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_INTFITSERV -#define AE_COMPILE_RATINT -#define AE_COMPILE_POLINT -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_FBLS -#define AE_COMPILE_NORMESTIMATOR -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_LINLSQR -#define AE_COMPILE_SPLINE1D -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_XBLAS -#define AE_COMPILE_DIRECTDENSESOLVERS -#define AE_COMPILE_LINMIN -#define AE_COMPILE_MINLBFGS -#define AE_COMPILE_CQMODELS -#define AE_COMPILE_LPQPSERV -#define AE_COMPILE_SNNLS -#define AE_COMPILE_SACTIVESETS -#define AE_COMPILE_QQPSOLVER -#define AE_COMPILE_QPDENSEAULSOLVER -#define AE_COMPILE_MINBLEIC -#define AE_COMPILE_QPBLEICSOLVER -#define AE_COMPILE_VIPMSOLVER -#define AE_COMPILE_MINQP -#define AE_COMPILE_MINLM -#define AE_COMPILE_LSFIT -#endif - -#ifdef AE_COMPILE_SPLINE2D -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_SCODES -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_INTFITSERV -#define AE_COMPILE_NORMESTIMATOR -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_LINLSQR -#define AE_COMPILE_FBLS -#define AE_COMPILE_SPLINE1D -#endif - -#ifdef AE_COMPILE_RBFV1 -#define AE_PARTIAL_BUILD -#define AE_COMPILE_SCODES -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_NEARESTNEIGHBOR -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_INTFITSERV -#define AE_COMPILE_RATINT -#define AE_COMPILE_POLINT -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_FBLS -#define AE_COMPILE_NORMESTIMATOR -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_LINLSQR -#define AE_COMPILE_SPLINE1D -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_XBLAS -#define AE_COMPILE_DIRECTDENSESOLVERS -#define AE_COMPILE_LINMIN -#define AE_COMPILE_MINLBFGS -#define AE_COMPILE_CQMODELS -#define AE_COMPILE_LPQPSERV -#define AE_COMPILE_SNNLS -#define AE_COMPILE_SACTIVESETS -#define AE_COMPILE_QQPSOLVER -#define AE_COMPILE_QPDENSEAULSOLVER -#define AE_COMPILE_MINBLEIC -#define AE_COMPILE_QPBLEICSOLVER -#define AE_COMPILE_VIPMSOLVER -#define AE_COMPILE_MINQP -#define AE_COMPILE_MINLM -#define AE_COMPILE_LSFIT -#endif - -#ifdef AE_COMPILE_RBF -#define AE_PARTIAL_BUILD -#define AE_COMPILE_SCODES -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_NEARESTNEIGHBOR -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_INTFITSERV -#define AE_COMPILE_RATINT -#define AE_COMPILE_POLINT -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_FBLS -#define AE_COMPILE_NORMESTIMATOR -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_LINLSQR -#define AE_COMPILE_SPLINE1D -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_XBLAS -#define AE_COMPILE_DIRECTDENSESOLVERS -#define AE_COMPILE_LINMIN -#define AE_COMPILE_MINLBFGS -#define AE_COMPILE_CQMODELS -#define AE_COMPILE_LPQPSERV -#define AE_COMPILE_SNNLS -#define AE_COMPILE_SACTIVESETS -#define AE_COMPILE_QQPSOLVER -#define AE_COMPILE_QPDENSEAULSOLVER -#define AE_COMPILE_MINBLEIC -#define AE_COMPILE_QPBLEICSOLVER -#define AE_COMPILE_VIPMSOLVER -#define AE_COMPILE_MINQP -#define AE_COMPILE_MINLM -#define AE_COMPILE_LSFIT -#define AE_COMPILE_RBFV1 -#define AE_COMPILE_RBFV2 -#endif - -#ifdef AE_COMPILE_INTCOMP -#define AE_PARTIAL_BUILD -#define AE_COMPILE_LINMIN -#define AE_COMPILE_APSERV -#define AE_COMPILE_TSORT -#define AE_COMPILE_OPTGUARDAPI -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_HQRND -#define AE_COMPILE_MATGEN -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_BDSVD -#define AE_COMPILE_SVD -#define AE_COMPILE_OPTSERV -#define AE_COMPILE_FBLS -#define AE_COMPILE_CQMODELS -#define AE_COMPILE_SNNLS -#define AE_COMPILE_SACTIVESETS -#define AE_COMPILE_MINBLEIC -#define AE_COMPILE_XBLAS -#define AE_COMPILE_DIRECTDENSESOLVERS -#define AE_COMPILE_NORMESTIMATOR -#define AE_COMPILE_LINLSQR -#define AE_COMPILE_MINLBFGS -#define AE_COMPILE_LPQPSERV -#define AE_COMPILE_QQPSOLVER -#define AE_COMPILE_QPDENSEAULSOLVER -#define AE_COMPILE_QPBLEICSOLVER -#define AE_COMPILE_VIPMSOLVER -#define AE_COMPILE_MINQP -#define AE_COMPILE_MINLM -#define AE_COMPILE_LPQPPRESOLVE -#define AE_COMPILE_REVISEDDUALSIMPLEX -#define AE_COMPILE_NLCSLP -#define AE_COMPILE_NLCSQP -#define AE_COMPILE_MINNLC -#define AE_COMPILE_FITSPHERE -#define AE_COMPILE_INTFITSERV -#define AE_COMPILE_SPLINE1D -#endif - -#ifdef AE_COMPILE_ELLIPTIC -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_HERMITE -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_DAWSON -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_TRIGINTEGRALS -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_POISSONDISTR -#define AE_PARTIAL_BUILD -#define AE_COMPILE_GAMMAFUNC -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_NORMALDISTR -#define AE_COMPILE_IGAMMAF -#endif - -#ifdef AE_COMPILE_BESSEL -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_IBETAF -#define AE_PARTIAL_BUILD -#define AE_COMPILE_GAMMAFUNC -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_NORMALDISTR -#endif - -#ifdef AE_COMPILE_FDISTR -#define AE_PARTIAL_BUILD -#define AE_COMPILE_GAMMAFUNC -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_NORMALDISTR -#define AE_COMPILE_IBETAF -#endif - -#ifdef AE_COMPILE_FRESNEL -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_JACOBIANELLIPTIC -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_PSIF -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_EXPINTEGRALS -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_LAGUERRE -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_CHISQUAREDISTR -#define AE_PARTIAL_BUILD -#define AE_COMPILE_GAMMAFUNC -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_NORMALDISTR -#define AE_COMPILE_IGAMMAF -#endif - -#ifdef AE_COMPILE_LEGENDRE -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_BETAF -#define AE_PARTIAL_BUILD -#define AE_COMPILE_GAMMAFUNC -#endif - -#ifdef AE_COMPILE_CHEBYSHEV -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_STUDENTTDISTR -#define AE_PARTIAL_BUILD -#define AE_COMPILE_GAMMAFUNC -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_NORMALDISTR -#define AE_COMPILE_IBETAF -#endif - -#ifdef AE_COMPILE_NEARUNITYUNIT -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_BINOMIALDISTR -#define AE_PARTIAL_BUILD -#define AE_COMPILE_GAMMAFUNC -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_NORMALDISTR -#define AE_COMPILE_IBETAF -#define AE_COMPILE_NEARUNITYUNIT -#endif - -#ifdef AE_COMPILE_AIRYF -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_WSR -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#endif - -#ifdef AE_COMPILE_STEST -#define AE_PARTIAL_BUILD -#define AE_COMPILE_GAMMAFUNC -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_NORMALDISTR -#define AE_COMPILE_IBETAF -#define AE_COMPILE_NEARUNITYUNIT -#define AE_COMPILE_BINOMIALDISTR -#endif - -#ifdef AE_COMPILE_CORRELATIONTESTS -#define AE_PARTIAL_BUILD -#define AE_COMPILE_GAMMAFUNC -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_NORMALDISTR -#define AE_COMPILE_IBETAF -#define AE_COMPILE_STUDENTTDISTR -#define AE_COMPILE_TSORT -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_BASESTAT -#endif - -#ifdef AE_COMPILE_STUDENTTTESTS -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_GAMMAFUNC -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_NORMALDISTR -#define AE_COMPILE_IBETAF -#define AE_COMPILE_STUDENTTDISTR -#endif - -#ifdef AE_COMPILE_MANNWHITNEYU -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#endif - -#ifdef AE_COMPILE_JARQUEBERA -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_VARIANCETESTS -#define AE_PARTIAL_BUILD -#define AE_COMPILE_GAMMAFUNC -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_NORMALDISTR -#define AE_COMPILE_IBETAF -#define AE_COMPILE_FDISTR -#define AE_COMPILE_IGAMMAF -#define AE_COMPILE_CHISQUAREDISTR -#endif - -#ifdef AE_COMPILE_SCHUR -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_HBLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_BLAS -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_HSSCHUR -#endif - -#ifdef AE_COMPILE_SPDGEVD -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#define AE_COMPILE_SBLAS -#define AE_COMPILE_BLAS -#define AE_COMPILE_TRLINSOLVE -#define AE_COMPILE_SAFESOLVE -#define AE_COMPILE_RCOND -#define AE_COMPILE_MATINV -#define AE_COMPILE_HBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_HSSCHUR -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_EVD -#endif - -#ifdef AE_COMPILE_INVERSEUPDATE -#define AE_PARTIAL_BUILD -#endif - -#ifdef AE_COMPILE_MATDET -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#endif - -#ifdef AE_COMPILE_POLYNOMIALSOLVER -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_HBLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_MATGEN -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_BLAS -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_HSSCHUR -#define AE_COMPILE_BASICSTATOPS -#define AE_COMPILE_EVD -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_TRFAC -#endif - -#ifdef AE_COMPILE_NLEQ -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_LINMIN -#define AE_COMPILE_ABLASF -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLAS -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_HQRND -#define AE_COMPILE_HBLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_SBLAS -#define AE_COMPILE_ORTFAC -#define AE_COMPILE_FBLS -#endif - -#ifdef AE_COMPILE_DIRECTSPARSESOLVERS -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_ABLAS -#define AE_COMPILE_DLU -#define AE_COMPILE_SPTRF -#define AE_COMPILE_AMDORDERING -#define AE_COMPILE_SPCHOL -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#define AE_COMPILE_ROTATIONS -#define AE_COMPILE_TRFAC -#endif - -#ifdef AE_COMPILE_LINCG -#define AE_PARTIAL_BUILD -#define AE_COMPILE_APSERV -#define AE_COMPILE_ABLASMKL -#define AE_COMPILE_ABLASF -#define AE_COMPILE_HQRND -#define AE_COMPILE_TSORT -#define AE_COMPILE_SPARSE -#define AE_COMPILE_ABLAS -#define AE_COMPILE_CREFLECTIONS -#define AE_COMPILE_MATGEN -#endif - -#ifdef AE_COMPILE_ALGLIBBASICS -#define AE_PARTIAL_BUILD -#endif - - - -#endif - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/dataanalysis.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/dataanalysis.cpp deleted file mode 100644 index 2a18f9d..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/dataanalysis.cpp +++ /dev/null @@ -1,51727 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifdef _MSC_VER -#define _CRT_SECURE_NO_WARNINGS -#endif -#include "stdafx.h" -#include "dataanalysis.h" - -// disable some irrelevant warnings -#if (AE_COMPILER==AE_MSVC) && !defined(AE_ALL_WARNINGS) -#pragma warning(disable:4100) -#pragma warning(disable:4127) -#pragma warning(disable:4611) -#pragma warning(disable:4702) -#pragma warning(disable:4996) -#endif - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_PCA) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_BDSS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MLPBASE) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_LDA) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SSA) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_LINREG) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_FILTERS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_LOGIT) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MCPD) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MLPE) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MLPTRAIN) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_CLUSTERING) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_DFOREST) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_KNN) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_DATACOMP) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_PCA) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Principal components analysis - -This function builds orthogonal basis where first axis corresponds to -direction with maximum variance, second axis maximizes variance in the -subspace orthogonal to first axis and so on. - -This function builds FULL basis, i.e. returns N vectors corresponding to -ALL directions, no matter how informative. If you need just a few (say, -10 or 50) of the most important directions, you may find it faster to use -one of the reduced versions: -* pcatruncatedsubspace() - for subspace iteration based method - -It should be noted that, unlike LDA, PCA does not use class labels. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - dataset, array[0..NPoints-1,0..NVars-1]. - matrix contains ONLY INDEPENDENT VARIABLES. - NPoints - dataset size, NPoints>=0 - NVars - number of independent variables, NVars>=1 - -OUTPUT PARAMETERS: - Info - return code: - * -4, if SVD subroutine haven't converged - * -1, if wrong parameters has been passed (NPoints<0, - NVars<1) - * 1, if task is solved - S2 - array[0..NVars-1]. variance values corresponding - to basis vectors. - V - array[0..NVars-1,0..NVars-1] - matrix, whose columns store basis vectors. - - -- ALGLIB -- - Copyright 25.08.2008 by Bochkanov Sergey -*************************************************************************/ -void pcabuildbasis(const real_2d_array &x, const ae_int_t npoints, const ae_int_t nvars, ae_int_t &info, real_1d_array &s2, real_2d_array &v, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::pcabuildbasis(const_cast(x.c_ptr()), npoints, nvars, &info, const_cast(s2.c_ptr()), const_cast(v.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Principal components analysis - -This function performs truncated PCA, i.e. returns just a few most important -directions. - -Internally it uses iterative eigensolver which is very efficient when only -a minor fraction of full basis is required. Thus, if you need full basis, -it is better to use pcabuildbasis() function. - -It should be noted that, unlike LDA, PCA does not use class labels. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - dataset, array[0..NPoints-1,0..NVars-1]. - matrix contains ONLY INDEPENDENT VARIABLES. - NPoints - dataset size, NPoints>=0 - NVars - number of independent variables, NVars>=1 - NNeeded - number of requested components, in [1,NVars] range; - this function is efficient only for NNeeded<(x.c_ptr()), npoints, nvars, nneeded, eps, maxits, const_cast(s2.c_ptr()), const_cast(v.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Sparse truncated principal components analysis - -This function performs sparse truncated PCA, i.e. returns just a few most -important principal components for a sparse input X. - -Internally it uses iterative eigensolver which is very efficient when only -a minor fraction of full basis is required. - -It should be noted that, unlike LDA, PCA does not use class labels. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - sparse dataset, sparse npoints*nvars matrix. It is - recommended to use CRS sparse storage format; non-CRS - input will be internally converted to CRS. - Matrix contains ONLY INDEPENDENT VARIABLES, and must - be EXACTLY npoints*nvars. - NPoints - dataset size, NPoints>=0 - NVars - number of independent variables, NVars>=1 - NNeeded - number of requested components, in [1,NVars] range; - this function is efficient only for NNeeded<(x.c_ptr()), npoints, nvars, nneeded, eps, maxits, const_cast(s2.c_ptr()), const_cast(v.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_BDSS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Optimal binary classification - -Algorithms finds optimal (=with minimal cross-entropy) binary partition. -Internal subroutine. - -INPUT PARAMETERS: - A - array[0..N-1], variable - C - array[0..N-1], class numbers (0 or 1). - N - array size - -OUTPUT PARAMETERS: - Info - completetion code: - * -3, all values of A[] are same (partition is impossible) - * -2, one of C[] is incorrect (<0, >1) - * -1, incorrect pararemets were passed (N<=0). - * 1, OK - Threshold- partiton boundary. Left part contains values which are - strictly less than Threshold. Right part contains values - which are greater than or equal to Threshold. - PAL, PBL- probabilities P(0|v=Threshold) and P(1|v>=Threshold) - CVE - cross-validation estimate of cross-entropy - - -- ALGLIB -- - Copyright 22.05.2008 by Bochkanov Sergey -*************************************************************************/ -void dsoptimalsplit2(const real_1d_array &a, const integer_1d_array &c, const ae_int_t n, ae_int_t &info, double &threshold, double &pal, double &pbl, double &par, double &pbr, double &cve, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dsoptimalsplit2(const_cast(a.c_ptr()), const_cast(c.c_ptr()), n, &info, &threshold, &pal, &pbl, &par, &pbr, &cve, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Optimal partition, internal subroutine. Fast version. - -Accepts: - A array[0..N-1] array of attributes array[0..N-1] - C array[0..N-1] array of class labels - TiesBuf array[0..N] temporaries (ties) - CntBuf array[0..2*NC-1] temporaries (counts) - Alpha centering factor (0<=alpha<=1, recommended value - 0.05) - BufR array[0..N-1] temporaries - BufI array[0..N-1] temporaries - -Output: - Info error code (">0"=OK, "<0"=bad) - RMS training set RMS error - CVRMS leave-one-out RMS error - -Note: - content of all arrays is changed by subroutine; - it doesn't allocate temporaries. - - -- ALGLIB -- - Copyright 11.12.2008 by Bochkanov Sergey -*************************************************************************/ -void dsoptimalsplit2fast(real_1d_array &a, integer_1d_array &c, integer_1d_array &tiesbuf, integer_1d_array &cntbuf, real_1d_array &bufr, integer_1d_array &bufi, const ae_int_t n, const ae_int_t nc, const double alpha, ae_int_t &info, double &threshold, double &rms, double &cvrms, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dsoptimalsplit2fast(const_cast(a.c_ptr()), const_cast(c.c_ptr()), const_cast(tiesbuf.c_ptr()), const_cast(cntbuf.c_ptr()), const_cast(bufr.c_ptr()), const_cast(bufi.c_ptr()), n, nc, alpha, &info, &threshold, &rms, &cvrms, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_MLPBASE) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Model's errors: - * RelCLSError - fraction of misclassified cases. - * AvgCE - acerage cross-entropy - * RMSError - root-mean-square error - * AvgError - average error - * AvgRelError - average relative error - -NOTE 1: RelCLSError/AvgCE are zero on regression problems. - -NOTE 2: on classification problems RMSError/AvgError/AvgRelError contain - errors in prediction of posterior probabilities -*************************************************************************/ -_modelerrors_owner::_modelerrors_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_modelerrors_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::modelerrors*)alglib_impl::ae_malloc(sizeof(alglib_impl::modelerrors), &_state); - memset(p_struct, 0, sizeof(alglib_impl::modelerrors)); - alglib_impl::_modelerrors_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_modelerrors_owner::_modelerrors_owner(const _modelerrors_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_modelerrors_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: modelerrors copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::modelerrors*)alglib_impl::ae_malloc(sizeof(alglib_impl::modelerrors), &_state); - memset(p_struct, 0, sizeof(alglib_impl::modelerrors)); - alglib_impl::_modelerrors_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_modelerrors_owner& _modelerrors_owner::operator=(const _modelerrors_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: modelerrors assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: modelerrors assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_modelerrors_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::modelerrors)); - alglib_impl::_modelerrors_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_modelerrors_owner::~_modelerrors_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_modelerrors_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::modelerrors* _modelerrors_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::modelerrors* _modelerrors_owner::c_ptr() const -{ - return const_cast(p_struct); -} -modelerrors::modelerrors() : _modelerrors_owner() ,relclserror(p_struct->relclserror),avgce(p_struct->avgce),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror) -{ -} - -modelerrors::modelerrors(const modelerrors &rhs):_modelerrors_owner(rhs) ,relclserror(p_struct->relclserror),avgce(p_struct->avgce),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror) -{ -} - -modelerrors& modelerrors::operator=(const modelerrors &rhs) -{ - if( this==&rhs ) - return *this; - _modelerrors_owner::operator=(rhs); - return *this; -} - -modelerrors::~modelerrors() -{ -} - - -/************************************************************************* - -*************************************************************************/ -_multilayerperceptron_owner::_multilayerperceptron_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_multilayerperceptron_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::multilayerperceptron*)alglib_impl::ae_malloc(sizeof(alglib_impl::multilayerperceptron), &_state); - memset(p_struct, 0, sizeof(alglib_impl::multilayerperceptron)); - alglib_impl::_multilayerperceptron_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_multilayerperceptron_owner::_multilayerperceptron_owner(const _multilayerperceptron_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_multilayerperceptron_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: multilayerperceptron copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::multilayerperceptron*)alglib_impl::ae_malloc(sizeof(alglib_impl::multilayerperceptron), &_state); - memset(p_struct, 0, sizeof(alglib_impl::multilayerperceptron)); - alglib_impl::_multilayerperceptron_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_multilayerperceptron_owner& _multilayerperceptron_owner::operator=(const _multilayerperceptron_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: multilayerperceptron assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: multilayerperceptron assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_multilayerperceptron_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::multilayerperceptron)); - alglib_impl::_multilayerperceptron_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_multilayerperceptron_owner::~_multilayerperceptron_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_multilayerperceptron_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::multilayerperceptron* _multilayerperceptron_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::multilayerperceptron* _multilayerperceptron_owner::c_ptr() const -{ - return const_cast(p_struct); -} -multilayerperceptron::multilayerperceptron() : _multilayerperceptron_owner() -{ -} - -multilayerperceptron::multilayerperceptron(const multilayerperceptron &rhs):_multilayerperceptron_owner(rhs) -{ -} - -multilayerperceptron& multilayerperceptron::operator=(const multilayerperceptron &rhs) -{ - if( this==&rhs ) - return *this; - _multilayerperceptron_owner::operator=(rhs); - return *this; -} - -multilayerperceptron::~multilayerperceptron() -{ -} - - -/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -void mlpserialize(multilayerperceptron &obj, std::string &s_out) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - alglib_impl::ae_int_t ssize; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_alloc_start(&serializer); - alglib_impl::mlpalloc(&serializer, obj.c_ptr(), &state); - ssize = alglib_impl::ae_serializer_get_alloc_size(&serializer); - s_out.clear(); - s_out.reserve((size_t)(ssize+1)); - alglib_impl::ae_serializer_sstart_str(&serializer, &s_out); - alglib_impl::mlpserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_assert( s_out.length()<=(size_t)ssize, "ALGLIB: serialization integrity error", &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} -/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -void mlpunserialize(const std::string &s_in, multilayerperceptron &obj) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_ustart_str(&serializer, &s_in); - alglib_impl::mlpunserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} - - -/************************************************************************* -This function serializes data structure to C++ stream. - -Data stream generated by this function is same as string representation -generated by string version of serializer - alphanumeric characters, -dots, underscores, minus signs, which are grouped into words separated by -spaces and CR+LF. - -We recommend you to read comments on string version of serializer to find -out more about serialization of AlGLIB objects. -*************************************************************************/ -void mlpserialize(multilayerperceptron &obj, std::ostream &s_out) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_alloc_start(&serializer); - alglib_impl::mlpalloc(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_get_alloc_size(&serializer); // not actually needed, but we have to ask - alglib_impl::ae_serializer_sstart_stream(&serializer, &s_out); - alglib_impl::mlpserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} -/************************************************************************* -This function unserializes data structure from stream. -*************************************************************************/ -void mlpunserialize(const std::istream &s_in, multilayerperceptron &obj) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_ustart_stream(&serializer, &s_in); - alglib_impl::mlpunserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} - -/************************************************************************* -Creates neural network with NIn inputs, NOut outputs, without hidden -layers, with linear output layer. Network weights are filled with small -random values. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcreate0(const ae_int_t nin, const ae_int_t nout, multilayerperceptron &network, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpcreate0(nin, nout, const_cast(network.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Same as MLPCreate0, but with one hidden layer (NHid neurons) with -non-linear activation function. Output layer is linear. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcreate1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, multilayerperceptron &network, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpcreate1(nin, nhid, nout, const_cast(network.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Same as MLPCreate0, but with two hidden layers (NHid1 and NHid2 neurons) -with non-linear activation function. Output layer is linear. - $ALL - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcreate2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, multilayerperceptron &network, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpcreate2(nin, nhid1, nhid2, nout, const_cast(network.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Creates neural network with NIn inputs, NOut outputs, without hidden -layers with non-linear output layer. Network weights are filled with small -random values. - -Activation function of the output layer takes values: - - (B, +INF), if D>=0 - -or - - (-INF, B), if D<0. - - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpcreateb0(const ae_int_t nin, const ae_int_t nout, const double b, const double d, multilayerperceptron &network, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpcreateb0(nin, nout, b, d, const_cast(network.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Same as MLPCreateB0 but with non-linear hidden layer. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpcreateb1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const double b, const double d, multilayerperceptron &network, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpcreateb1(nin, nhid, nout, b, d, const_cast(network.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Same as MLPCreateB0 but with two non-linear hidden layers. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpcreateb2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const double b, const double d, multilayerperceptron &network, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpcreateb2(nin, nhid1, nhid2, nout, b, d, const_cast(network.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Creates neural network with NIn inputs, NOut outputs, without hidden -layers with non-linear output layer. Network weights are filled with small -random values. Activation function of the output layer takes values [A,B]. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpcreater0(const ae_int_t nin, const ae_int_t nout, const double a, const double b, multilayerperceptron &network, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpcreater0(nin, nout, a, b, const_cast(network.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Same as MLPCreateR0, but with non-linear hidden layer. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpcreater1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const double a, const double b, multilayerperceptron &network, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpcreater1(nin, nhid, nout, a, b, const_cast(network.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Same as MLPCreateR0, but with two non-linear hidden layers. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpcreater2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const double a, const double b, multilayerperceptron &network, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpcreater2(nin, nhid1, nhid2, nout, a, b, const_cast(network.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Creates classifier network with NIn inputs and NOut possible classes. -Network contains no hidden layers and linear output layer with SOFTMAX- -normalization (so outputs sums up to 1.0 and converge to posterior -probabilities). - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcreatec0(const ae_int_t nin, const ae_int_t nout, multilayerperceptron &network, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpcreatec0(nin, nout, const_cast(network.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Same as MLPCreateC0, but with one non-linear hidden layer. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcreatec1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, multilayerperceptron &network, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpcreatec1(nin, nhid, nout, const_cast(network.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Same as MLPCreateC0, but with two non-linear hidden layers. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcreatec2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, multilayerperceptron &network, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpcreatec2(nin, nhid1, nhid2, nout, const_cast(network.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Copying of neural network - -INPUT PARAMETERS: - Network1 - original - -OUTPUT PARAMETERS: - Network2 - copy - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcopy(const multilayerperceptron &network1, multilayerperceptron &network2, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpcopy(const_cast(network1.c_ptr()), const_cast(network2.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function copies tunable parameters (weights/means/sigmas) from one -network to another with same architecture. It performs some rudimentary -checks that architectures are same, and throws exception if check fails. - -It is intended for fast copying of states between two network which are -known to have same geometry. - -INPUT PARAMETERS: - Network1 - source, must be correctly initialized - Network2 - target, must have same architecture - -OUTPUT PARAMETERS: - Network2 - network state is copied from source to target - - -- ALGLIB -- - Copyright 20.06.2013 by Bochkanov Sergey -*************************************************************************/ -void mlpcopytunableparameters(const multilayerperceptron &network1, const multilayerperceptron &network2, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpcopytunableparameters(const_cast(network1.c_ptr()), const_cast(network2.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Randomization of neural network weights - - -- ALGLIB -- - Copyright 06.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlprandomize(const multilayerperceptron &network, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlprandomize(const_cast(network.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Randomization of neural network weights and standartisator - - -- ALGLIB -- - Copyright 10.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlprandomizefull(const multilayerperceptron &network, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlprandomizefull(const_cast(network.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Internal subroutine. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpinitpreprocessor(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpinitpreprocessor(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), ssize, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Returns information about initialized network: number of inputs, outputs, -weights. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpproperties(const multilayerperceptron &network, ae_int_t &nin, ae_int_t &nout, ae_int_t &wcount, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpproperties(const_cast(network.c_ptr()), &nin, &nout, &wcount, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Returns number of inputs. - - -- ALGLIB -- - Copyright 19.10.2011 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mlpgetinputscount(const multilayerperceptron &network, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::mlpgetinputscount(const_cast(network.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Returns number of outputs. - - -- ALGLIB -- - Copyright 19.10.2011 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mlpgetoutputscount(const multilayerperceptron &network, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::mlpgetoutputscount(const_cast(network.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Returns number of weights. - - -- ALGLIB -- - Copyright 19.10.2011 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mlpgetweightscount(const multilayerperceptron &network, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::mlpgetweightscount(const_cast(network.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Tells whether network is SOFTMAX-normalized (i.e. classifier) or not. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -bool mlpissoftmax(const multilayerperceptron &network, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::mlpissoftmax(const_cast(network.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function returns total number of layers (including input, hidden and -output layers). - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mlpgetlayerscount(const multilayerperceptron &network, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::mlpgetlayerscount(const_cast(network.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function returns size of K-th layer. - -K=0 corresponds to input layer, K=CNT-1 corresponds to output layer. - -Size of the output layer is always equal to the number of outputs, although -when we have softmax-normalized network, last neuron doesn't have any -connections - it is just zero. - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mlpgetlayersize(const multilayerperceptron &network, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::mlpgetlayersize(const_cast(network.c_ptr()), k, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function returns offset/scaling coefficients for I-th input of the -network. - -INPUT PARAMETERS: - Network - network - I - input index - -OUTPUT PARAMETERS: - Mean - mean term - Sigma - sigma term, guaranteed to be nonzero. - -I-th input is passed through linear transformation - IN[i] = (IN[i]-Mean)/Sigma -before feeding to the network - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpgetinputscaling(const multilayerperceptron &network, const ae_int_t i, double &mean, double &sigma, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpgetinputscaling(const_cast(network.c_ptr()), i, &mean, &sigma, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function returns offset/scaling coefficients for I-th output of the -network. - -INPUT PARAMETERS: - Network - network - I - input index - -OUTPUT PARAMETERS: - Mean - mean term - Sigma - sigma term, guaranteed to be nonzero. - -I-th output is passed through linear transformation - OUT[i] = OUT[i]*Sigma+Mean -before returning it to user. In case we have SOFTMAX-normalized network, -we return (Mean,Sigma)=(0.0,1.0). - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpgetoutputscaling(const multilayerperceptron &network, const ae_int_t i, double &mean, double &sigma, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpgetoutputscaling(const_cast(network.c_ptr()), i, &mean, &sigma, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function returns information about Ith neuron of Kth layer - -INPUT PARAMETERS: - Network - network - K - layer index - I - neuron index (within layer) - -OUTPUT PARAMETERS: - FKind - activation function type (used by MLPActivationFunction()) - this value is zero for input or linear neurons - Threshold - also called offset, bias - zero for input neurons - -NOTE: this function throws exception if layer or neuron with given index -do not exists. - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpgetneuroninfo(const multilayerperceptron &network, const ae_int_t k, const ae_int_t i, ae_int_t &fkind, double &threshold, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpgetneuroninfo(const_cast(network.c_ptr()), k, i, &fkind, &threshold, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function returns information about connection from I0-th neuron of -K0-th layer to I1-th neuron of K1-th layer. - -INPUT PARAMETERS: - Network - network - K0 - layer index - I0 - neuron index (within layer) - K1 - layer index - I1 - neuron index (within layer) - -RESULT: - connection weight (zero for non-existent connections) - -This function: -1. throws exception if layer or neuron with given index do not exists. -2. returns zero if neurons exist, but there is no connection between them - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -double mlpgetweight(const multilayerperceptron &network, const ae_int_t k0, const ae_int_t i0, const ae_int_t k1, const ae_int_t i1, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlpgetweight(const_cast(network.c_ptr()), k0, i0, k1, i1, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function sets offset/scaling coefficients for I-th input of the -network. - -INPUT PARAMETERS: - Network - network - I - input index - Mean - mean term - Sigma - sigma term (if zero, will be replaced by 1.0) - -NTE: I-th input is passed through linear transformation - IN[i] = (IN[i]-Mean)/Sigma -before feeding to the network. This function sets Mean and Sigma. - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpsetinputscaling(const multilayerperceptron &network, const ae_int_t i, const double mean, const double sigma, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpsetinputscaling(const_cast(network.c_ptr()), i, mean, sigma, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets offset/scaling coefficients for I-th output of the -network. - -INPUT PARAMETERS: - Network - network - I - input index - Mean - mean term - Sigma - sigma term (if zero, will be replaced by 1.0) - -OUTPUT PARAMETERS: - -NOTE: I-th output is passed through linear transformation - OUT[i] = OUT[i]*Sigma+Mean -before returning it to user. This function sets Sigma/Mean. In case we -have SOFTMAX-normalized network, you can not set (Sigma,Mean) to anything -other than(0.0,1.0) - this function will throw exception. - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpsetoutputscaling(const multilayerperceptron &network, const ae_int_t i, const double mean, const double sigma, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpsetoutputscaling(const_cast(network.c_ptr()), i, mean, sigma, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function modifies information about Ith neuron of Kth layer - -INPUT PARAMETERS: - Network - network - K - layer index - I - neuron index (within layer) - FKind - activation function type (used by MLPActivationFunction()) - this value must be zero for input neurons - (you can not set activation function for input neurons) - Threshold - also called offset, bias - this value must be zero for input neurons - (you can not set threshold for input neurons) - -NOTES: -1. this function throws exception if layer or neuron with given index do - not exists. -2. this function also throws exception when you try to set non-linear - activation function for input neurons (any kind of network) or for output - neurons of classifier network. -3. this function throws exception when you try to set non-zero threshold for - input neurons (any kind of network). - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpsetneuroninfo(const multilayerperceptron &network, const ae_int_t k, const ae_int_t i, const ae_int_t fkind, const double threshold, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpsetneuroninfo(const_cast(network.c_ptr()), k, i, fkind, threshold, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function modifies information about connection from I0-th neuron of -K0-th layer to I1-th neuron of K1-th layer. - -INPUT PARAMETERS: - Network - network - K0 - layer index - I0 - neuron index (within layer) - K1 - layer index - I1 - neuron index (within layer) - W - connection weight (must be zero for non-existent - connections) - -This function: -1. throws exception if layer or neuron with given index do not exists. -2. throws exception if you try to set non-zero weight for non-existent - connection - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpsetweight(const multilayerperceptron &network, const ae_int_t k0, const ae_int_t i0, const ae_int_t k1, const ae_int_t i1, const double w, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpsetweight(const_cast(network.c_ptr()), k0, i0, k1, i1, w, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Neural network activation function - -INPUT PARAMETERS: - NET - neuron input - K - function index (zero for linear function) - -OUTPUT PARAMETERS: - F - function - DF - its derivative - D2F - its second derivative - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpactivationfunction(const double net, const ae_int_t k, double &f, double &df, double &d2f, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpactivationfunction(net, k, &f, &df, &d2f, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Procesing - -INPUT PARAMETERS: - Network - neural network - X - input vector, array[0..NIn-1]. - -OUTPUT PARAMETERS: - Y - result. Regression estimate when solving regression task, - vector of posterior probabilities for classification task. - -See also MLPProcessI - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpprocess(const multilayerperceptron &network, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpprocess(const_cast(network.c_ptr()), const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -'interactive' variant of MLPProcess for languages like Python which -support constructs like "Y = MLPProcess(NN,X)" and interactive mode of the -interpreter - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 21.09.2010 by Bochkanov Sergey -*************************************************************************/ -void mlpprocessi(const multilayerperceptron &network, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpprocessi(const_cast(network.c_ptr()), const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Error of the neural network on dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: - sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2) - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -double mlperror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlperror(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Error of the neural network on dataset given by sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - NPoints - points count, >=0 - -RESULT: - sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2) - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -double mlperrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlperrorsparse(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Natural error function for neural network, internal subroutine. - -NOTE: this function is single-threaded. Unlike other error function, it -receives no speed-up from being executed in SMP mode. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -double mlperrorn(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlperrorn(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), ssize, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Classification error of the neural network on dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: - classification error (number of misclassified cases) - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mlpclserror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::mlpclserror(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Relative classification error on the test set. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: -Percent of incorrectly classified cases. Works both for classifier -networks and general purpose networks used as classifiers. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 25.12.2008 by Bochkanov Sergey -*************************************************************************/ -double mlprelclserror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlprelclserror(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Relative classification error on the test set given by sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. Sparse matrix must use CRS format - for storage. - NPoints - points count, >=0. - -RESULT: -Percent of incorrectly classified cases. Works both for classifier -networks and general purpose networks used as classifiers. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 09.08.2012 by Bochkanov Sergey -*************************************************************************/ -double mlprelclserrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlprelclserrorsparse(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Average cross-entropy (in bits per element) on the test set. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: -CrossEntropy/(NPoints*LN(2)). -Zero if network solves regression task. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 08.01.2009 by Bochkanov Sergey -*************************************************************************/ -double mlpavgce(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlpavgce(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Average cross-entropy (in bits per element) on the test set given by -sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - NPoints - points count, >=0. - -RESULT: -CrossEntropy/(NPoints*LN(2)). -Zero if network solves regression task. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 9.08.2012 by Bochkanov Sergey -*************************************************************************/ -double mlpavgcesparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlpavgcesparse(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -RMS error on the test set given. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: -Root mean square error. Its meaning for regression task is obvious. As for -classification task, RMS error means error when estimating posterior -probabilities. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -double mlprmserror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlprmserror(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -RMS error on the test set given by sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - NPoints - points count, >=0. - -RESULT: -Root mean square error. Its meaning for regression task is obvious. As for -classification task, RMS error means error when estimating posterior -probabilities. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 09.08.2012 by Bochkanov Sergey -*************************************************************************/ -double mlprmserrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlprmserrorsparse(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Average absolute error on the test set. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: -Its meaning for regression task is obvious. As for classification task, it -means average error when estimating posterior probabilities. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 11.03.2008 by Bochkanov Sergey -*************************************************************************/ -double mlpavgerror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlpavgerror(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Average absolute error on the test set given by sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - NPoints - points count, >=0. - -RESULT: -Its meaning for regression task is obvious. As for classification task, it -means average error when estimating posterior probabilities. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 09.08.2012 by Bochkanov Sergey -*************************************************************************/ -double mlpavgerrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlpavgerrorsparse(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Average relative error on the test set. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: -Its meaning for regression task is obvious. As for classification task, it -means average relative error when estimating posterior probability of -belonging to the correct class. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 11.03.2008 by Bochkanov Sergey -*************************************************************************/ -double mlpavgrelerror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlpavgrelerror(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Average relative error on the test set given by sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - NPoints - points count, >=0. - -RESULT: -Its meaning for regression task is obvious. As for classification task, it -means average relative error when estimating posterior probability of -belonging to the correct class. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 09.08.2012 by Bochkanov Sergey -*************************************************************************/ -double mlpavgrelerrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlpavgrelerrorsparse(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Gradient calculation - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - X - input vector, length of array must be at least NIn - DesiredY- desired outputs, length of array must be at least NOut - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) - Grad - gradient of E with respect to weights of network, array[WCount] - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpgrad(const multilayerperceptron &network, const real_1d_array &x, const real_1d_array &desiredy, double &e, real_1d_array &grad, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpgrad(const_cast(network.c_ptr()), const_cast(x.c_ptr()), const_cast(desiredy.c_ptr()), &e, const_cast(grad.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Gradient calculation (natural error function is used) - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - X - input vector, length of array must be at least NIn - DesiredY- desired outputs, length of array must be at least NOut - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, sum-of-squares for regression networks, - cross-entropy for classification networks. - Grad - gradient of E with respect to weights of network, array[WCount] - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpgradn(const multilayerperceptron &network, const real_1d_array &x, const real_1d_array &desiredy, double &e, real_1d_array &grad, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpgradn(const_cast(network.c_ptr()), const_cast(x.c_ptr()), const_cast(desiredy.c_ptr()), &e, const_cast(grad.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Batch gradient calculation for a set of inputs/outputs - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset in dense format; one sample = one row: - * first NIn columns contain inputs, - * for regression problem, next NOut columns store - desired outputs. - * for classification problem, next column (just one!) - stores class number. - SSize - number of elements in XY - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) - Grad - gradient of E with respect to weights of network, array[WCount] - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpgradbatch(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, double &e, real_1d_array &grad, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpgradbatch(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), ssize, &e, const_cast(grad.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Batch gradient calculation for a set of inputs/outputs given by sparse -matrices - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset in sparse format; one sample = one row: - * MATRIX MUST BE STORED IN CRS FORMAT - * first NIn columns contain inputs. - * for regression problem, next NOut columns store - desired outputs. - * for classification problem, next column (just one!) - stores class number. - SSize - number of elements in XY - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) - Grad - gradient of E with respect to weights of network, array[WCount] - - -- ALGLIB -- - Copyright 26.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpgradbatchsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t ssize, double &e, real_1d_array &grad, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpgradbatchsparse(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), ssize, &e, const_cast(grad.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Batch gradient calculation for a subset of dataset - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset in dense format; one sample = one row: - * first NIn columns contain inputs, - * for regression problem, next NOut columns store - desired outputs. - * for classification problem, next column (just one!) - stores class number. - SetSize - real size of XY, SetSize>=0; - Idx - subset of SubsetSize elements, array[SubsetSize]: - * Idx[I] stores row index in the original dataset which is - given by XY. Gradient is calculated with respect to rows - whose indexes are stored in Idx[]. - * Idx[] must store correct indexes; this function throws - an exception in case incorrect index (less than 0 or - larger than rows(XY)) is given - * Idx[] may store indexes in any order and even with - repetitions. - SubsetSize- number of elements in Idx[] array: - * positive value means that subset given by Idx[] is processed - * zero value results in zero gradient - * negative value means that full dataset is processed - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) - Grad - gradient of E with respect to weights of network, - array[WCount] - - -- ALGLIB -- - Copyright 26.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpgradbatchsubset(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t setsize, const integer_1d_array &idx, const ae_int_t subsetsize, double &e, real_1d_array &grad, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpgradbatchsubset(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), setsize, const_cast(idx.c_ptr()), subsetsize, &e, const_cast(grad.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Batch gradient calculation for a set of inputs/outputs for a subset of -dataset given by set of indexes. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset in sparse format; one sample = one row: - * MATRIX MUST BE STORED IN CRS FORMAT - * first NIn columns contain inputs, - * for regression problem, next NOut columns store - desired outputs. - * for classification problem, next column (just one!) - stores class number. - SetSize - real size of XY, SetSize>=0; - Idx - subset of SubsetSize elements, array[SubsetSize]: - * Idx[I] stores row index in the original dataset which is - given by XY. Gradient is calculated with respect to rows - whose indexes are stored in Idx[]. - * Idx[] must store correct indexes; this function throws - an exception in case incorrect index (less than 0 or - larger than rows(XY)) is given - * Idx[] may store indexes in any order and even with - repetitions. - SubsetSize- number of elements in Idx[] array: - * positive value means that subset given by Idx[] is processed - * zero value results in zero gradient - * negative value means that full dataset is processed - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) - Grad - gradient of E with respect to weights of network, - array[WCount] - -NOTE: when SubsetSize<0 is used full dataset by call MLPGradBatchSparse - function. - - -- ALGLIB -- - Copyright 26.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpgradbatchsparsesubset(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t setsize, const integer_1d_array &idx, const ae_int_t subsetsize, double &e, real_1d_array &grad, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpgradbatchsparsesubset(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), setsize, const_cast(idx.c_ptr()), subsetsize, &e, const_cast(grad.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Batch gradient calculation for a set of inputs/outputs -(natural error function is used) - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - set of inputs/outputs; one sample = one row; - first NIn columns contain inputs, - next NOut columns - desired outputs. - SSize - number of elements in XY - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, sum-of-squares for regression networks, - cross-entropy for classification networks. - Grad - gradient of E with respect to weights of network, array[WCount] - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpgradnbatch(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, double &e, real_1d_array &grad, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpgradnbatch(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), ssize, &e, const_cast(grad.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Batch Hessian calculation (natural error function) using R-algorithm. -Internal subroutine. - - -- ALGLIB -- - Copyright 26.01.2008 by Bochkanov Sergey. - - Hessian calculation based on R-algorithm described in - "Fast Exact Multiplication by the Hessian", - B. A. Pearlmutter, - Neural Computation, 1994. -*************************************************************************/ -void mlphessiannbatch(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, double &e, real_1d_array &grad, real_2d_array &h, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlphessiannbatch(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), ssize, &e, const_cast(grad.c_ptr()), const_cast(h.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Batch Hessian calculation using R-algorithm. -Internal subroutine. - - -- ALGLIB -- - Copyright 26.01.2008 by Bochkanov Sergey. - - Hessian calculation based on R-algorithm described in - "Fast Exact Multiplication by the Hessian", - B. A. Pearlmutter, - Neural Computation, 1994. -*************************************************************************/ -void mlphessianbatch(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, double &e, real_1d_array &grad, real_2d_array &h, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlphessianbatch(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), ssize, &e, const_cast(grad.c_ptr()), const_cast(h.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Calculation of all types of errors on subset of dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset; one sample = one row; - first NIn columns contain inputs, - next NOut columns - desired outputs. - SetSize - real size of XY, SetSize>=0; - Subset - subset of SubsetSize elements, array[SubsetSize]; - SubsetSize- number of elements in Subset[] array: - * if SubsetSize>0, rows of XY with indices Subset[0]... - ...Subset[SubsetSize-1] are processed - * if SubsetSize=0, zeros are returned - * if SubsetSize<0, entire dataset is processed; Subset[] - array is ignored in this case. - -OUTPUT PARAMETERS: - Rep - it contains all type of errors. - - -- ALGLIB -- - Copyright 04.09.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpallerrorssubset(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize, modelerrors &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpallerrorssubset(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), setsize, const_cast(subset.c_ptr()), subsetsize, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Calculation of all types of errors on subset of dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset given by sparse matrix; - one sample = one row; - first NIn columns contain inputs, - next NOut columns - desired outputs. - SetSize - real size of XY, SetSize>=0; - Subset - subset of SubsetSize elements, array[SubsetSize]; - SubsetSize- number of elements in Subset[] array: - * if SubsetSize>0, rows of XY with indices Subset[0]... - ...Subset[SubsetSize-1] are processed - * if SubsetSize=0, zeros are returned - * if SubsetSize<0, entire dataset is processed; Subset[] - array is ignored in this case. - -OUTPUT PARAMETERS: - Rep - it contains all type of errors. - - - -- ALGLIB -- - Copyright 04.09.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpallerrorssparsesubset(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize, modelerrors &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpallerrorssparsesubset(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), setsize, const_cast(subset.c_ptr()), subsetsize, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Error of the neural network on subset of dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - SetSize - real size of XY, SetSize>=0; - Subset - subset of SubsetSize elements, array[SubsetSize]; - SubsetSize- number of elements in Subset[] array: - * if SubsetSize>0, rows of XY with indices Subset[0]... - ...Subset[SubsetSize-1] are processed - * if SubsetSize=0, zeros are returned - * if SubsetSize<0, entire dataset is processed; Subset[] - array is ignored in this case. - -RESULT: - sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2) - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 04.09.2012 by Bochkanov Sergey -*************************************************************************/ -double mlperrorsubset(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlperrorsubset(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), setsize, const_cast(subset.c_ptr()), subsetsize, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Error of the neural network on subset of sparse dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - SetSize - real size of XY, SetSize>=0; - it is used when SubsetSize<0; - Subset - subset of SubsetSize elements, array[SubsetSize]; - SubsetSize- number of elements in Subset[] array: - * if SubsetSize>0, rows of XY with indices Subset[0]... - ...Subset[SubsetSize-1] are processed - * if SubsetSize=0, zeros are returned - * if SubsetSize<0, entire dataset is processed; Subset[] - array is ignored in this case. - -RESULT: - sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2) - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 04.09.2012 by Bochkanov Sergey -*************************************************************************/ -double mlperrorsparsesubset(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlperrorsparsesubset(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), setsize, const_cast(subset.c_ptr()), subsetsize, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_LDA) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Multiclass Fisher LDA - -Subroutine finds coefficients of linear combination which optimally separates -training set on classes. - -COMMERCIAL EDITION OF ALGLIB: - - ! Commercial version of ALGLIB includes two important improvements of - ! this function, which can be used from C++ and C#: - ! * Intel MKL support (lightweight Intel MKL is shipped with ALGLIB) - ! * multithreading support - ! - ! Intel MKL gives approximately constant (with respect to number of - ! worker threads) acceleration factor which depends on CPU being used, - ! problem size and "baseline" ALGLIB edition which is used for - ! comparison. Best results are achieved for high-dimensional problems - ! (NVars is at least 256). - ! - ! Multithreading is used to accelerate initial phase of LDA, which - ! includes calculation of products of large matrices. Again, for best - ! efficiency problem must be high-dimensional. - ! - ! Generally, commercial ALGLIB is several times faster than open-source - ! generic C edition, and many times faster than open-source C# edition. - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - training set, array[0..NPoints-1,0..NVars]. - First NVars columns store values of independent - variables, next column stores number of class (from 0 - to NClasses-1) which dataset element belongs to. Fractional - values are rounded to nearest integer. - NPoints - training set size, NPoints>=0 - NVars - number of independent variables, NVars>=1 - NClasses - number of classes, NClasses>=2 - - -OUTPUT PARAMETERS: - Info - return code: - * -4, if internal EVD subroutine hasn't converged - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed (NPoints<0, - NVars<1, NClasses<2) - * 1, if task has been solved - * 2, if there was a multicollinearity in training set, - but task has been solved. - W - linear combination coefficients, array[0..NVars-1] - - -- ALGLIB -- - Copyright 31.05.2008 by Bochkanov Sergey -*************************************************************************/ -void fisherlda(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, ae_int_t &info, real_1d_array &w, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::fisherlda(const_cast(xy.c_ptr()), npoints, nvars, nclasses, &info, const_cast(w.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -N-dimensional multiclass Fisher LDA - -Subroutine finds coefficients of linear combinations which optimally separates -training set on classes. It returns N-dimensional basis whose vector are sorted -by quality of training set separation (in descending order). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - training set, array[0..NPoints-1,0..NVars]. - First NVars columns store values of independent - variables, next column stores number of class (from 0 - to NClasses-1) which dataset element belongs to. Fractional - values are rounded to nearest integer. - NPoints - training set size, NPoints>=0 - NVars - number of independent variables, NVars>=1 - NClasses - number of classes, NClasses>=2 - - -OUTPUT PARAMETERS: - Info - return code: - * -4, if internal EVD subroutine hasn't converged - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed (NPoints<0, - NVars<1, NClasses<2) - * 1, if task has been solved - * 2, if there was a multicollinearity in training set, - but task has been solved. - W - basis, array[0..NVars-1,0..NVars-1] - columns of matrix stores basis vectors, sorted by - quality of training set separation (in descending order) - - -- ALGLIB -- - Copyright 31.05.2008 by Bochkanov Sergey -*************************************************************************/ -void fisherldan(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, ae_int_t &info, real_2d_array &w, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::fisherldan(const_cast(xy.c_ptr()), npoints, nvars, nclasses, &info, const_cast(w.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_SSA) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores state of the SSA model. - -You should use ALGLIB functions to work with this object. -*************************************************************************/ -_ssamodel_owner::_ssamodel_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_ssamodel_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::ssamodel*)alglib_impl::ae_malloc(sizeof(alglib_impl::ssamodel), &_state); - memset(p_struct, 0, sizeof(alglib_impl::ssamodel)); - alglib_impl::_ssamodel_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_ssamodel_owner::_ssamodel_owner(const _ssamodel_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_ssamodel_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: ssamodel copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::ssamodel*)alglib_impl::ae_malloc(sizeof(alglib_impl::ssamodel), &_state); - memset(p_struct, 0, sizeof(alglib_impl::ssamodel)); - alglib_impl::_ssamodel_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_ssamodel_owner& _ssamodel_owner::operator=(const _ssamodel_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: ssamodel assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: ssamodel assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_ssamodel_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::ssamodel)); - alglib_impl::_ssamodel_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_ssamodel_owner::~_ssamodel_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_ssamodel_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::ssamodel* _ssamodel_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::ssamodel* _ssamodel_owner::c_ptr() const -{ - return const_cast(p_struct); -} -ssamodel::ssamodel() : _ssamodel_owner() -{ -} - -ssamodel::ssamodel(const ssamodel &rhs):_ssamodel_owner(rhs) -{ -} - -ssamodel& ssamodel::operator=(const ssamodel &rhs) -{ - if( this==&rhs ) - return *this; - _ssamodel_owner::operator=(rhs); - return *this; -} - -ssamodel::~ssamodel() -{ -} - -/************************************************************************* -This function creates SSA model object. Right after creation model is in -"dummy" mode - you can add data, but analyzing/prediction will return -just zeros (it assumes that basis is empty). - -HOW TO USE SSA MODEL: - -1. create model with ssacreate() -2. add data with one/many ssaaddsequence() calls -3. choose SSA algorithm with one of ssasetalgo...() functions: - * ssasetalgotopkdirect() for direct one-run analysis - * ssasetalgotopkrealtime() for algorithm optimized for many subsequent - runs with warm-start capabilities - * ssasetalgoprecomputed() for user-supplied basis -4. set window width with ssasetwindow() -5. perform one of the analysis-related activities: - a) call ssagetbasis() to get basis - b) call ssaanalyzelast() ssaanalyzesequence() or ssaanalyzelastwindow() - to perform analysis (trend/noise separation) - c) call one of the forecasting functions (ssaforecastlast() or - ssaforecastsequence()) to perform prediction; alternatively, you can - extract linear recurrence coefficients with ssagetlrr(). - SSA analysis will be performed during first call to analysis-related - function. SSA model is smart enough to track all changes in the dataset - and model settings, to cache previously computed basis and to - re-evaluate basis only when necessary. - -Additionally, if your setting involves constant stream of incoming data, -you can perform quick update already calculated model with one of the -incremental append-and-update functions: ssaappendpointandupdate() or -ssaappendsequenceandupdate(). - -NOTE: steps (2), (3), (4) can be performed in arbitrary order. - -INPUT PARAMETERS: - none - -OUTPUT PARAMETERS: - S - structure which stores model state - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssacreate(ssamodel &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssacreate(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets window width for SSA model. You should call it before -analysis phase. Default window width is 1 (not for real use). - -Special notes: -* this function call can be performed at any moment before first call to - analysis-related functions -* changing window width invalidates internally stored basis; if you change - window width AFTER you call analysis-related function, next analysis - phase will require re-calculation of the basis according to current - algorithm. -* calling this function with exactly same window width as current one has - no effect -* if you specify window width larger than any data sequence stored in the - model, analysis will return zero basis. - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - WindowWidth - >=1, new window width - -OUTPUT PARAMETERS: - S - SSA model, updated - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssasetwindow(const ssamodel &s, const ae_int_t windowwidth, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssasetwindow(const_cast(s.c_ptr()), windowwidth, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets seed which is used to initialize internal RNG when -we make pseudorandom decisions on model updates. - -By default, deterministic seed is used - which results in same sequence of -pseudorandom decisions every time you run SSA model. If you specify non- -deterministic seed value, then SSA model may return slightly different -results after each run. - -This function can be useful when you have several SSA models updated with -sseappendpointandupdate() called with 0(s.c_ptr()), seed, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets length of power-up cycle for real-time algorithm. - -By default, this algorithm performs costly O(N*WindowWidth^2) init phase -followed by full run of truncated EVD. However, if you are ready to -live with a bit lower-quality basis during first few iterations, you can -split this O(N*WindowWidth^2) initialization between several subsequent -append-and-update rounds. It results in better latency of the algorithm. - -This function invalidates basis/solver, next analysis call will result in -full recalculation of everything. - -INPUT PARAMETERS: - S - SSA model - PWLen - length of the power-up stage: - * 0 means that no power-up is requested - * 1 is the same as 0 - * >1 means that delayed power-up is performed - - -- ALGLIB -- - Copyright 03.11.2017 by Bochkanov Sergey -*************************************************************************/ -void ssasetpoweruplength(const ssamodel &s, const ae_int_t pwlen, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssasetpoweruplength(const_cast(s.c_ptr()), pwlen, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets memory limit of SSA analysis. - -Straightforward SSA with sequence length T and window width W needs O(T*W) -memory. It is possible to reduce memory consumption by splitting task into -smaller chunks. - -Thus function allows you to specify approximate memory limit (measured in -double precision numbers used for buffers). Actual memory consumption will -be comparable to the number specified by you. - -Default memory limit is 50.000.000 (400Mbytes) in current version. - -INPUT PARAMETERS: - S - SSA model - MemLimit- memory limit, >=0. Zero value means no limit. - - -- ALGLIB -- - Copyright 20.12.2017 by Bochkanov Sergey -*************************************************************************/ -void ssasetmemorylimit(const ssamodel &s, const ae_int_t memlimit, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssasetmemorylimit(const_cast(s.c_ptr()), memlimit, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function adds data sequence to SSA model. Only single-dimensional -sequences are supported. - -What is a sequences? Following definitions/requirements apply: -* a sequence is an array of values measured in subsequent, equally - separated time moments (ticks). -* you may have many sequences in your dataset; say, one sequence may - correspond to one trading session. -* sequence length should be larger than current window length (shorter - sequences will be ignored during analysis). -* analysis is performed within a sequence; different sequences are NOT - stacked together to produce one large contiguous stream of data. -* analysis is performed for all sequences at once, i.e. same set of basis - vectors is computed for all sequences - -INCREMENTAL ANALYSIS - -This function is non intended for incremental updates of previously found -SSA basis. Calling it invalidates all previous analysis results (basis is -reset and will be recalculated from zero during next analysis). - -If you want to perform incremental/real-time SSA, consider using -following functions: -* ssaappendpointandupdate() for appending one point -* ssaappendsequenceandupdate() for appending new sequence - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - X - array[N], data, can be larger (additional values - are ignored) - N - data length, can be automatically determined from - the array length. N>=0. - -OUTPUT PARAMETERS: - S - SSA model, updated - -NOTE: you can clear dataset with ssacleardata() - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaaddsequence(const ssamodel &s, const real_1d_array &x, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssaaddsequence(const_cast(s.c_ptr()), const_cast(x.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function adds data sequence to SSA model. Only single-dimensional -sequences are supported. - -What is a sequences? Following definitions/requirements apply: -* a sequence is an array of values measured in subsequent, equally - separated time moments (ticks). -* you may have many sequences in your dataset; say, one sequence may - correspond to one trading session. -* sequence length should be larger than current window length (shorter - sequences will be ignored during analysis). -* analysis is performed within a sequence; different sequences are NOT - stacked together to produce one large contiguous stream of data. -* analysis is performed for all sequences at once, i.e. same set of basis - vectors is computed for all sequences - -INCREMENTAL ANALYSIS - -This function is non intended for incremental updates of previously found -SSA basis. Calling it invalidates all previous analysis results (basis is -reset and will be recalculated from zero during next analysis). - -If you want to perform incremental/real-time SSA, consider using -following functions: -* ssaappendpointandupdate() for appending one point -* ssaappendsequenceandupdate() for appending new sequence - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - X - array[N], data, can be larger (additional values - are ignored) - N - data length, can be automatically determined from - the array length. N>=0. - -OUTPUT PARAMETERS: - S - SSA model, updated - -NOTE: you can clear dataset with ssacleardata() - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void ssaaddsequence(const ssamodel &s, const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssaaddsequence(const_cast(s.c_ptr()), const_cast(x.c_ptr()), n, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function appends single point to last data sequence stored in the SSA -model and tries to update model in the incremental manner (if possible -with current algorithm). - -If you want to add more than one point at once: -* if you want to add M points to the same sequence, perform M-1 calls with - UpdateIts parameter set to 0.0, and last call with non-zero UpdateIts. -* if you want to add new sequence, use ssaappendsequenceandupdate() - -Running time of this function does NOT depend on dataset size, only on -window width and number of singular vectors. Depending on algorithm being -used, incremental update has complexity: -* for top-K real time - O(UpdateIts*K*Width^2), with fractional UpdateIts -* for top-K direct - O(Width^3) for any non-zero UpdateIts -* for precomputed basis - O(1), no update is performed - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - X - new point - UpdateIts - >=0, floating point (!) value, desired update - frequency: - * zero value means that point is stored, but no - update is performed - * integer part of the value means that specified - number of iterations is always performed - * fractional part of the value means that one - iteration is performed with this probability. - - Recommended value: 0(s.c_ptr()), x, updateits, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function appends new sequence to dataset stored in the SSA model and -tries to update model in the incremental manner (if possible with current -algorithm). - -Notes: -* if you want to add M sequences at once, perform M-1 calls with UpdateIts - parameter set to 0.0, and last call with non-zero UpdateIts. -* if you want to add just one point, use ssaappendpointandupdate() - -Running time of this function does NOT depend on dataset size, only on -sequence length, window width and number of singular vectors. Depending on -algorithm being used, incremental update has complexity: -* for top-K real time - O(UpdateIts*K*Width^2+(NTicks-Width)*Width^2) -* for top-K direct - O(Width^3+(NTicks-Width)*Width^2) -* for precomputed basis - O(1), no update is performed - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - X - new sequence, array[NTicks] or larget - NTicks - >=1, number of ticks in the sequence - UpdateIts - >=0, floating point (!) value, desired update - frequency: - * zero value means that point is stored, but no - update is performed - * integer part of the value means that specified - number of iterations is always performed - * fractional part of the value means that one - iteration is performed with this probability. - - Recommended value: 0(s.c_ptr()), const_cast(x.c_ptr()), nticks, updateits, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function appends new sequence to dataset stored in the SSA model and -tries to update model in the incremental manner (if possible with current -algorithm). - -Notes: -* if you want to add M sequences at once, perform M-1 calls with UpdateIts - parameter set to 0.0, and last call with non-zero UpdateIts. -* if you want to add just one point, use ssaappendpointandupdate() - -Running time of this function does NOT depend on dataset size, only on -sequence length, window width and number of singular vectors. Depending on -algorithm being used, incremental update has complexity: -* for top-K real time - O(UpdateIts*K*Width^2+(NTicks-Width)*Width^2) -* for top-K direct - O(Width^3+(NTicks-Width)*Width^2) -* for precomputed basis - O(1), no update is performed - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - X - new sequence, array[NTicks] or larget - NTicks - >=1, number of ticks in the sequence - UpdateIts - >=0, floating point (!) value, desired update - frequency: - * zero value means that point is stored, but no - update is performed - * integer part of the value means that specified - number of iterations is always performed - * fractional part of the value means that one - iteration is performed with this probability. - - Recommended value: 0(s.c_ptr()), const_cast(x.c_ptr()), nticks, updateits, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets SSA algorithm to "precomputed vectors" algorithm. - -This algorithm uses precomputed set of orthonormal (orthogonal AND -normalized) basis vectors supplied by user. Thus, basis calculation phase -is not performed - we already have our basis - and only analysis/ -forecasting phase requires actual calculations. - -This algorithm may handle "append" requests which add just one/few ticks -to the end of the last sequence in O(1) time. - -NOTE: this algorithm accepts both basis and window width, because these - two parameters are naturally aligned. Calling this function sets - window width; if you call ssasetwindow() with other window width, - then during analysis stage algorithm will detect conflict and reset - to zero basis. - -INPUT PARAMETERS: - S - SSA model - A - array[WindowWidth,NBasis], orthonormalized basis; - this function does NOT control orthogonality and - does NOT perform any kind of renormalization. It - is your responsibility to provide it with correct - basis. - WindowWidth - window width, >=1 - NBasis - number of basis vectors, 1<=NBasis<=WindowWidth - -OUTPUT PARAMETERS: - S - updated model - -NOTE: calling this function invalidates basis in all cases. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssasetalgoprecomputed(const ssamodel &s, const real_2d_array &a, const ae_int_t windowwidth, const ae_int_t nbasis, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssasetalgoprecomputed(const_cast(s.c_ptr()), const_cast(a.c_ptr()), windowwidth, nbasis, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets SSA algorithm to "precomputed vectors" algorithm. - -This algorithm uses precomputed set of orthonormal (orthogonal AND -normalized) basis vectors supplied by user. Thus, basis calculation phase -is not performed - we already have our basis - and only analysis/ -forecasting phase requires actual calculations. - -This algorithm may handle "append" requests which add just one/few ticks -to the end of the last sequence in O(1) time. - -NOTE: this algorithm accepts both basis and window width, because these - two parameters are naturally aligned. Calling this function sets - window width; if you call ssasetwindow() with other window width, - then during analysis stage algorithm will detect conflict and reset - to zero basis. - -INPUT PARAMETERS: - S - SSA model - A - array[WindowWidth,NBasis], orthonormalized basis; - this function does NOT control orthogonality and - does NOT perform any kind of renormalization. It - is your responsibility to provide it with correct - basis. - WindowWidth - window width, >=1 - NBasis - number of basis vectors, 1<=NBasis<=WindowWidth - -OUTPUT PARAMETERS: - S - updated model - -NOTE: calling this function invalidates basis in all cases. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void ssasetalgoprecomputed(const ssamodel &s, const real_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t windowwidth; - ae_int_t nbasis; - - windowwidth = a.rows(); - nbasis = a.cols(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssasetalgoprecomputed(const_cast(s.c_ptr()), const_cast(a.c_ptr()), windowwidth, nbasis, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets SSA algorithm to "direct top-K" algorithm. - -"Direct top-K" algorithm performs full SVD of the N*WINDOW trajectory -matrix (hence its name - direct solver is used), then extracts top K -components. Overall running time is O(N*WINDOW^2), where N is a number of -ticks in the dataset, WINDOW is window width. - -This algorithm may handle "append" requests which add just one/few ticks -to the end of the last sequence in O(WINDOW^3) time, which is ~N/WINDOW -times faster than re-computing everything from scratch. - -INPUT PARAMETERS: - S - SSA model - TopK - number of components to analyze; TopK>=1. - -OUTPUT PARAMETERS: - S - updated model - - -NOTE: TopK>WindowWidth is silently decreased to WindowWidth during analysis - phase - -NOTE: calling this function invalidates basis, except for the situation - when this algorithm was already set with same parameters. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssasetalgotopkdirect(const ssamodel &s, const ae_int_t topk, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssasetalgotopkdirect(const_cast(s.c_ptr()), topk, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets SSA algorithm to "top-K real time algorithm". This algo -extracts K components with largest singular values. - -It is real-time version of top-K algorithm which is optimized for -incremental processing and fast start-up. Internally it uses subspace -eigensolver for truncated SVD. It results in ability to perform quick -updates of the basis when only a few points/sequences is added to dataset. - -Performance profile of the algorithm is given below: -* O(K*WindowWidth^2) running time for incremental update of the dataset - with one of the "append-and-update" functions (ssaappendpointandupdate() - or ssaappendsequenceandupdate()). -* O(N*WindowWidth^2) running time for initial basis evaluation (N=size of - dataset) -* ability to split costly initialization across several incremental - updates of the basis (so called "Power-Up" functionality, activated by - ssasetpoweruplength() function) - -INPUT PARAMETERS: - S - SSA model - TopK - number of components to analyze; TopK>=1. - -OUTPUT PARAMETERS: - S - updated model - -NOTE: this algorithm is optimized for large-scale tasks with large - datasets. On toy problems with just 5-10 points it can return basis - which is slightly different from that returned by direct algorithm - (ssasetalgotopkdirect() function). However, the difference becomes - negligible as dataset grows. - -NOTE: TopK>WindowWidth is silently decreased to WindowWidth during analysis - phase - -NOTE: calling this function invalidates basis, except for the situation - when this algorithm was already set with same parameters. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssasetalgotopkrealtime(const ssamodel &s, const ae_int_t topk, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssasetalgotopkrealtime(const_cast(s.c_ptr()), topk, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function clears all data stored in the model and invalidates all -basis components found so far. - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - -OUTPUT PARAMETERS: - S - SSA model, updated - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssacleardata(const ssamodel &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssacleardata(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function executes SSA on internally stored dataset and returns basis -found by current method. - -INPUT PARAMETERS: - S - SSA model - -OUTPUT PARAMETERS: - A - array[WindowWidth,NBasis], basis; vectors are - stored in matrix columns, by descreasing variance - SV - array[NBasis]: - * zeros - for model initialized with SSASetAlgoPrecomputed() - * singular values - for other algorithms - WindowWidth - current window - NBasis - basis size - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Calling this function in degenerate cases (no data or all data are -shorter than window size; no algorithm is specified) returns basis with -just one zero vector. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssagetbasis(const ssamodel &s, real_2d_array &a, real_1d_array &sv, ae_int_t &windowwidth, ae_int_t &nbasis, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssagetbasis(const_cast(s.c_ptr()), const_cast(a.c_ptr()), const_cast(sv.c_ptr()), &windowwidth, &nbasis, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function returns linear recurrence relation (LRR) coefficients found -by current SSA algorithm. - -INPUT PARAMETERS: - S - SSA model - -OUTPUT PARAMETERS: - A - array[WindowWidth-1]. Coefficients of the - linear recurrence of the form: - X[W-1] = X[W-2]*A[W-2] + X[W-3]*A[W-3] + ... + X[0]*A[0]. - Empty array for WindowWidth=1. - WindowWidth - current window width - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Calling this function in degenerate cases (no data or all data are -shorter than window size; no algorithm is specified) returns zeros. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssagetlrr(const ssamodel &s, real_1d_array &a, ae_int_t &windowwidth, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssagetlrr(const_cast(s.c_ptr()), const_cast(a.c_ptr()), &windowwidth, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function executes SSA on internally stored dataset and returns -analysis for the last window of the last sequence. Such analysis is -an lightweight alternative for full scale reconstruction (see below). - -Typical use case for this function is real-time setting, when you are -interested in quick-and-dirty (very quick and very dirty) processing of -just a few last ticks of the trend. - -IMPORTANT: full scale SSA involves analysis of the ENTIRE dataset, - with reconstruction being done for all positions of sliding - window with subsequent hankelization (diagonal averaging) of - the resulting matrix. - - Such analysis requires O((DataLen-Window)*Window*NBasis) FLOPs - and can be quite costly. However, it has nice noise-canceling - effects due to averaging. - - This function performs REDUCED analysis of the last window. It - is much faster - just O(Window*NBasis), but its results are - DIFFERENT from that of ssaanalyzelast(). In particular, first - few points of the trend are much more prone to noise. - -INPUT PARAMETERS: - S - SSA model - -OUTPUT PARAMETERS: - Trend - array[WindowSize], reconstructed trend line - Noise - array[WindowSize], the rest of the signal; - it holds that ActualData = Trend+Noise. - NTicks - current WindowSize - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - -In any case, only basis is reused. Reconstruction is performed from -scratch every time you call this function. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* last sequence is shorter than the window length (analysis can be done, - but we can not perform reconstruction on the last sequence) - -Calling this function in degenerate cases returns following result: -* in any case, WindowWidth ticks is returned -* trend is assumed to be zero -* noise is initialized by the last sequence; if last sequence is shorter - than the window size, it is moved to the end of the array, and the - beginning of the noise array is filled by zeros - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaanalyzelastwindow(const ssamodel &s, real_1d_array &trend, real_1d_array &noise, ae_int_t &nticks, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssaanalyzelastwindow(const_cast(s.c_ptr()), const_cast(trend.c_ptr()), const_cast(noise.c_ptr()), &nticks, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function: -* builds SSA basis using internally stored (entire) dataset -* returns reconstruction for the last NTicks of the last sequence - -If you want to analyze some other sequence, use ssaanalyzesequence(). - -Reconstruction phase involves generation of NTicks-WindowWidth sliding -windows, their decomposition using empirical orthogonal functions found by -SSA, followed by averaging of each data point across several overlapping -windows. Thus, every point in the output trend is reconstructed using up -to WindowWidth overlapping windows (WindowWidth windows exactly in the -inner points, just one window at the extremal points). - -IMPORTANT: due to averaging this function returns different results for - different values of NTicks. It is expected and not a bug. - - For example: - * Trend[NTicks-1] is always same because it is not averaged in - any case (same applies to Trend[0]). - * Trend[NTicks-2] has different values for NTicks=WindowWidth - and NTicks=WindowWidth+1 because former case means that no - averaging is performed, and latter case means that averaging - using two sliding windows is performed. Larger values of - NTicks produce same results as NTicks=WindowWidth+1. - * ...and so on... - -PERFORMANCE: this function has O((NTicks-WindowWidth)*WindowWidth*NBasis) - running time. If you work in time-constrained setting and - have to analyze just a few last ticks, choosing NTicks equal - to WindowWidth+SmoothingLen, with SmoothingLen=1...WindowWidth - will result in good compromise between noise cancellation and - analysis speed. - -INPUT PARAMETERS: - S - SSA model - NTicks - number of ticks to analyze, Nticks>=1. - * special case of NTicks<=WindowWidth is handled - by analyzing last window and returning NTicks - last ticks. - * special case NTicks>LastSequenceLen is handled - by prepending result with NTicks-LastSequenceLen - zeros. - -OUTPUT PARAMETERS: - Trend - array[NTicks], reconstructed trend line - Noise - array[NTicks], the rest of the signal; - it holds that ActualData = Trend+Noise. - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - -In any case, only basis is reused. Reconstruction is performed from -scratch every time you call this function. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* last sequence is shorter than the window length (analysis can be done, - but we can not perform reconstruction on the last sequence) - -Calling this function in degenerate cases returns following result: -* in any case, NTicks ticks is returned -* trend is assumed to be zero -* noise is initialized by the last sequence; if last sequence is shorter - than the window size, it is moved to the end of the array, and the - beginning of the noise array is filled by zeros - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaanalyzelast(const ssamodel &s, const ae_int_t nticks, real_1d_array &trend, real_1d_array &noise, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssaanalyzelast(const_cast(s.c_ptr()), nticks, const_cast(trend.c_ptr()), const_cast(noise.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function: -* builds SSA basis using internally stored (entire) dataset -* returns reconstruction for the sequence being passed to this function - -If you want to analyze last sequence stored in the model, use -ssaanalyzelast(). - -Reconstruction phase involves generation of NTicks-WindowWidth sliding -windows, their decomposition using empirical orthogonal functions found by -SSA, followed by averaging of each data point across several overlapping -windows. Thus, every point in the output trend is reconstructed using up -to WindowWidth overlapping windows (WindowWidth windows exactly in the -inner points, just one window at the extremal points). - -PERFORMANCE: this function has O((NTicks-WindowWidth)*WindowWidth*NBasis) - running time. If you work in time-constrained setting and - have to analyze just a few last ticks, choosing NTicks equal - to WindowWidth+SmoothingLen, with SmoothingLen=1...WindowWidth - will result in good compromise between noise cancellation and - analysis speed. - -INPUT PARAMETERS: - S - SSA model - Data - array[NTicks], can be larger (only NTicks leading - elements will be used) - NTicks - number of ticks to analyze, Nticks>=1. - * special case of NTicks(s.c_ptr()), const_cast(data.c_ptr()), nticks, const_cast(trend.c_ptr()), const_cast(noise.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function: -* builds SSA basis using internally stored (entire) dataset -* returns reconstruction for the sequence being passed to this function - -If you want to analyze last sequence stored in the model, use -ssaanalyzelast(). - -Reconstruction phase involves generation of NTicks-WindowWidth sliding -windows, their decomposition using empirical orthogonal functions found by -SSA, followed by averaging of each data point across several overlapping -windows. Thus, every point in the output trend is reconstructed using up -to WindowWidth overlapping windows (WindowWidth windows exactly in the -inner points, just one window at the extremal points). - -PERFORMANCE: this function has O((NTicks-WindowWidth)*WindowWidth*NBasis) - running time. If you work in time-constrained setting and - have to analyze just a few last ticks, choosing NTicks equal - to WindowWidth+SmoothingLen, with SmoothingLen=1...WindowWidth - will result in good compromise between noise cancellation and - analysis speed. - -INPUT PARAMETERS: - S - SSA model - Data - array[NTicks], can be larger (only NTicks leading - elements will be used) - NTicks - number of ticks to analyze, Nticks>=1. - * special case of NTicks(s.c_ptr()), const_cast(data.c_ptr()), nticks, const_cast(trend.c_ptr()), const_cast(noise.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function builds SSA basis and performs forecasting for a specified -number of ticks, returning value of trend. - -Forecast is performed as follows: -* SSA trend extraction is applied to last WindowWidth elements of the - internally stored dataset; this step is basically a noise reduction. -* linear recurrence relation is applied to extracted trend - -This function has following running time: -* O(NBasis*WindowWidth) for trend extraction phase (always performed) -* O(WindowWidth*NTicks) for forecast phase - -NOTE: noise reduction is ALWAYS applied by this algorithm; if you want to - apply recurrence relation to raw unprocessed data, use another - function - ssaforecastsequence() which allows to turn on and off - noise reduction phase. - -NOTE: this algorithm performs prediction using only one - last - sliding - window. Predictions produced by such approach are smooth - continuations of the reconstructed trend line, but they can be - easily corrupted by noise. If you need noise-resistant prediction, - use ssaforecastavglast() function, which averages predictions built - using several sliding windows. - -INPUT PARAMETERS: - S - SSA model - NTicks - number of ticks to forecast, NTicks>=1 - -OUTPUT PARAMETERS: - Trend - array[NTicks], predicted trend line - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* last sequence is shorter than the WindowWidth (analysis can be done, - but we can not perform forecasting on the last sequence) -* window lentgh is 1 (impossible to use for forecasting) -* SSA analysis algorithm is configured to extract basis whose size is - equal to window length (impossible to use for forecasting; only basis - whose size is less than window length can be used). - -Calling this function in degenerate cases returns following result: -* NTicks copies of the last value is returned for non-empty task with - large enough dataset, but with overcomplete basis (window width=1 or - basis size is equal to window width) -* zero trend with length=NTicks is returned for empty task - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is ever constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaforecastlast(const ssamodel &s, const ae_int_t nticks, real_1d_array &trend, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssaforecastlast(const_cast(s.c_ptr()), nticks, const_cast(trend.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function builds SSA basis and performs forecasting for a user- -specified sequence, returning value of trend. - -Forecasting is done in two stages: -* first, we extract trend from the WindowWidth last elements of the - sequence. This stage is optional, you can turn it off if you pass - data which are already processed with SSA. Of course, you can turn it - off even for raw data, but it is not recommended - noise suppression is - very important for correct prediction. -* then, we apply LRR for last WindowWidth-1 elements of the extracted - trend. - -This function has following running time: -* O(NBasis*WindowWidth) for trend extraction phase -* O(WindowWidth*NTicks) for forecast phase - -NOTE: this algorithm performs prediction using only one - last - sliding - window. Predictions produced by such approach are smooth - continuations of the reconstructed trend line, but they can be - easily corrupted by noise. If you need noise-resistant prediction, - use ssaforecastavgsequence() function, which averages predictions - built using several sliding windows. - -INPUT PARAMETERS: - S - SSA model - Data - array[NTicks], data to forecast - DataLen - number of ticks in the data, DataLen>=1 - ForecastLen - number of ticks to predict, ForecastLen>=1 - ApplySmoothing - whether to apply smoothing trend extraction or not; - if you do not know what to specify, pass True. - -OUTPUT PARAMETERS: - Trend - array[ForecastLen], forecasted trend - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* data sequence is shorter than the WindowWidth (analysis can be done, - but we can not perform forecasting on the last sequence) -* window lentgh is 1 (impossible to use for forecasting) -* SSA analysis algorithm is configured to extract basis whose size is - equal to window length (impossible to use for forecasting; only basis - whose size is less than window length can be used). - -Calling this function in degenerate cases returns following result: -* ForecastLen copies of the last value is returned for non-empty task with - large enough dataset, but with overcomplete basis (window width=1 or - basis size is equal to window width) -* zero trend with length=ForecastLen is returned for empty task - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is ever constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaforecastsequence(const ssamodel &s, const real_1d_array &data, const ae_int_t datalen, const ae_int_t forecastlen, const bool applysmoothing, real_1d_array &trend, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssaforecastsequence(const_cast(s.c_ptr()), const_cast(data.c_ptr()), datalen, forecastlen, applysmoothing, const_cast(trend.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function builds SSA basis and performs forecasting for a user- -specified sequence, returning value of trend. - -Forecasting is done in two stages: -* first, we extract trend from the WindowWidth last elements of the - sequence. This stage is optional, you can turn it off if you pass - data which are already processed with SSA. Of course, you can turn it - off even for raw data, but it is not recommended - noise suppression is - very important for correct prediction. -* then, we apply LRR for last WindowWidth-1 elements of the extracted - trend. - -This function has following running time: -* O(NBasis*WindowWidth) for trend extraction phase -* O(WindowWidth*NTicks) for forecast phase - -NOTE: this algorithm performs prediction using only one - last - sliding - window. Predictions produced by such approach are smooth - continuations of the reconstructed trend line, but they can be - easily corrupted by noise. If you need noise-resistant prediction, - use ssaforecastavgsequence() function, which averages predictions - built using several sliding windows. - -INPUT PARAMETERS: - S - SSA model - Data - array[NTicks], data to forecast - DataLen - number of ticks in the data, DataLen>=1 - ForecastLen - number of ticks to predict, ForecastLen>=1 - ApplySmoothing - whether to apply smoothing trend extraction or not; - if you do not know what to specify, pass True. - -OUTPUT PARAMETERS: - Trend - array[ForecastLen], forecasted trend - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* data sequence is shorter than the WindowWidth (analysis can be done, - but we can not perform forecasting on the last sequence) -* window lentgh is 1 (impossible to use for forecasting) -* SSA analysis algorithm is configured to extract basis whose size is - equal to window length (impossible to use for forecasting; only basis - whose size is less than window length can be used). - -Calling this function in degenerate cases returns following result: -* ForecastLen copies of the last value is returned for non-empty task with - large enough dataset, but with overcomplete basis (window width=1 or - basis size is equal to window width) -* zero trend with length=ForecastLen is returned for empty task - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is ever constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void ssaforecastsequence(const ssamodel &s, const real_1d_array &data, const ae_int_t forecastlen, real_1d_array &trend, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t datalen; - bool applysmoothing; - - datalen = data.length(); - applysmoothing = true; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssaforecastsequence(const_cast(s.c_ptr()), const_cast(data.c_ptr()), datalen, forecastlen, applysmoothing, const_cast(trend.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function builds SSA basis and performs forecasting for a specified -number of ticks, returning value of trend. - -Forecast is performed as follows: -* SSA trend extraction is applied to last M sliding windows of the - internally stored dataset -* for each of M sliding windows, M predictions are built -* average value of M predictions is returned - -This function has following running time: -* O(NBasis*WindowWidth*M) for trend extraction phase (always performed) -* O(WindowWidth*NTicks*M) for forecast phase - -NOTE: noise reduction is ALWAYS applied by this algorithm; if you want to - apply recurrence relation to raw unprocessed data, use another - function - ssaforecastsequence() which allows to turn on and off - noise reduction phase. - -NOTE: combination of several predictions results in lesser sensitivity to - noise, but it may produce undesirable discontinuities between last - point of the trend and first point of the prediction. The reason is - that last point of the trend is usually corrupted by noise, but - average value of several predictions is less sensitive to noise, - thus discontinuity appears. It is not a bug. - -INPUT PARAMETERS: - S - SSA model - M - number of sliding windows to combine, M>=1. If - your dataset has less than M sliding windows, this - parameter will be silently reduced. - NTicks - number of ticks to forecast, NTicks>=1 - -OUTPUT PARAMETERS: - Trend - array[NTicks], predicted trend line - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* last sequence is shorter than the WindowWidth (analysis can be done, - but we can not perform forecasting on the last sequence) -* window lentgh is 1 (impossible to use for forecasting) -* SSA analysis algorithm is configured to extract basis whose size is - equal to window length (impossible to use for forecasting; only basis - whose size is less than window length can be used). - -Calling this function in degenerate cases returns following result: -* NTicks copies of the last value is returned for non-empty task with - large enough dataset, but with overcomplete basis (window width=1 or - basis size is equal to window width) -* zero trend with length=NTicks is returned for empty task - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is ever constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaforecastavglast(const ssamodel &s, const ae_int_t m, const ae_int_t nticks, real_1d_array &trend, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssaforecastavglast(const_cast(s.c_ptr()), m, nticks, const_cast(trend.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function builds SSA basis and performs forecasting for a user- -specified sequence, returning value of trend. - -Forecasting is done in two stages: -* first, we extract trend from M last sliding windows of the sequence. - This stage is optional, you can turn it off if you pass data which - are already processed with SSA. Of course, you can turn it off even - for raw data, but it is not recommended - noise suppression is very - important for correct prediction. -* then, we apply LRR independently for M sliding windows -* average of M predictions is returned - -This function has following running time: -* O(NBasis*WindowWidth*M) for trend extraction phase -* O(WindowWidth*NTicks*M) for forecast phase - -NOTE: combination of several predictions results in lesser sensitivity to - noise, but it may produce undesirable discontinuities between last - point of the trend and first point of the prediction. The reason is - that last point of the trend is usually corrupted by noise, but - average value of several predictions is less sensitive to noise, - thus discontinuity appears. It is not a bug. - -INPUT PARAMETERS: - S - SSA model - Data - array[NTicks], data to forecast - DataLen - number of ticks in the data, DataLen>=1 - M - number of sliding windows to combine, M>=1. If - your dataset has less than M sliding windows, this - parameter will be silently reduced. - ForecastLen - number of ticks to predict, ForecastLen>=1 - ApplySmoothing - whether to apply smoothing trend extraction or not. - if you do not know what to specify, pass true. - -OUTPUT PARAMETERS: - Trend - array[ForecastLen], forecasted trend - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* data sequence is shorter than the WindowWidth (analysis can be done, - but we can not perform forecasting on the last sequence) -* window lentgh is 1 (impossible to use for forecasting) -* SSA analysis algorithm is configured to extract basis whose size is - equal to window length (impossible to use for forecasting; only basis - whose size is less than window length can be used). - -Calling this function in degenerate cases returns following result: -* ForecastLen copies of the last value is returned for non-empty task with - large enough dataset, but with overcomplete basis (window width=1 or - basis size is equal to window width) -* zero trend with length=ForecastLen is returned for empty task - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is ever constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaforecastavgsequence(const ssamodel &s, const real_1d_array &data, const ae_int_t datalen, const ae_int_t m, const ae_int_t forecastlen, const bool applysmoothing, real_1d_array &trend, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssaforecastavgsequence(const_cast(s.c_ptr()), const_cast(data.c_ptr()), datalen, m, forecastlen, applysmoothing, const_cast(trend.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function builds SSA basis and performs forecasting for a user- -specified sequence, returning value of trend. - -Forecasting is done in two stages: -* first, we extract trend from M last sliding windows of the sequence. - This stage is optional, you can turn it off if you pass data which - are already processed with SSA. Of course, you can turn it off even - for raw data, but it is not recommended - noise suppression is very - important for correct prediction. -* then, we apply LRR independently for M sliding windows -* average of M predictions is returned - -This function has following running time: -* O(NBasis*WindowWidth*M) for trend extraction phase -* O(WindowWidth*NTicks*M) for forecast phase - -NOTE: combination of several predictions results in lesser sensitivity to - noise, but it may produce undesirable discontinuities between last - point of the trend and first point of the prediction. The reason is - that last point of the trend is usually corrupted by noise, but - average value of several predictions is less sensitive to noise, - thus discontinuity appears. It is not a bug. - -INPUT PARAMETERS: - S - SSA model - Data - array[NTicks], data to forecast - DataLen - number of ticks in the data, DataLen>=1 - M - number of sliding windows to combine, M>=1. If - your dataset has less than M sliding windows, this - parameter will be silently reduced. - ForecastLen - number of ticks to predict, ForecastLen>=1 - ApplySmoothing - whether to apply smoothing trend extraction or not. - if you do not know what to specify, pass true. - -OUTPUT PARAMETERS: - Trend - array[ForecastLen], forecasted trend - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* data sequence is shorter than the WindowWidth (analysis can be done, - but we can not perform forecasting on the last sequence) -* window lentgh is 1 (impossible to use for forecasting) -* SSA analysis algorithm is configured to extract basis whose size is - equal to window length (impossible to use for forecasting; only basis - whose size is less than window length can be used). - -Calling this function in degenerate cases returns following result: -* ForecastLen copies of the last value is returned for non-empty task with - large enough dataset, but with overcomplete basis (window width=1 or - basis size is equal to window width) -* zero trend with length=ForecastLen is returned for empty task - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is ever constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void ssaforecastavgsequence(const ssamodel &s, const real_1d_array &data, const ae_int_t m, const ae_int_t forecastlen, real_1d_array &trend, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t datalen; - bool applysmoothing; - - datalen = data.length(); - applysmoothing = true; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ssaforecastavgsequence(const_cast(s.c_ptr()), const_cast(data.c_ptr()), datalen, m, forecastlen, applysmoothing, const_cast(trend.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif -#endif - -#if defined(AE_COMPILE_LINREG) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - -*************************************************************************/ -_linearmodel_owner::_linearmodel_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_linearmodel_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::linearmodel*)alglib_impl::ae_malloc(sizeof(alglib_impl::linearmodel), &_state); - memset(p_struct, 0, sizeof(alglib_impl::linearmodel)); - alglib_impl::_linearmodel_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_linearmodel_owner::_linearmodel_owner(const _linearmodel_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_linearmodel_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: linearmodel copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::linearmodel*)alglib_impl::ae_malloc(sizeof(alglib_impl::linearmodel), &_state); - memset(p_struct, 0, sizeof(alglib_impl::linearmodel)); - alglib_impl::_linearmodel_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_linearmodel_owner& _linearmodel_owner::operator=(const _linearmodel_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: linearmodel assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: linearmodel assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_linearmodel_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::linearmodel)); - alglib_impl::_linearmodel_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_linearmodel_owner::~_linearmodel_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_linearmodel_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::linearmodel* _linearmodel_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::linearmodel* _linearmodel_owner::c_ptr() const -{ - return const_cast(p_struct); -} -linearmodel::linearmodel() : _linearmodel_owner() -{ -} - -linearmodel::linearmodel(const linearmodel &rhs):_linearmodel_owner(rhs) -{ -} - -linearmodel& linearmodel::operator=(const linearmodel &rhs) -{ - if( this==&rhs ) - return *this; - _linearmodel_owner::operator=(rhs); - return *this; -} - -linearmodel::~linearmodel() -{ -} - - -/************************************************************************* -LRReport structure contains additional information about linear model: -* C - covariation matrix, array[0..NVars,0..NVars]. - C[i,j] = Cov(A[i],A[j]) -* RMSError - root mean square error on a training set -* AvgError - average error on a training set -* AvgRelError - average relative error on a training set (excluding - observations with zero function value). -* CVRMSError - leave-one-out cross-validation estimate of - generalization error. Calculated using fast algorithm - with O(NVars*NPoints) complexity. -* CVAvgError - cross-validation estimate of average error -* CVAvgRelError - cross-validation estimate of average relative error - -All other fields of the structure are intended for internal use and should -not be used outside ALGLIB. -*************************************************************************/ -_lrreport_owner::_lrreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_lrreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::lrreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::lrreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::lrreport)); - alglib_impl::_lrreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_lrreport_owner::_lrreport_owner(const _lrreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_lrreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: lrreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::lrreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::lrreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::lrreport)); - alglib_impl::_lrreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_lrreport_owner& _lrreport_owner::operator=(const _lrreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: lrreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: lrreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_lrreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::lrreport)); - alglib_impl::_lrreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_lrreport_owner::~_lrreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_lrreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::lrreport* _lrreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::lrreport* _lrreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -lrreport::lrreport() : _lrreport_owner() ,c(&p_struct->c),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),cvrmserror(p_struct->cvrmserror),cvavgerror(p_struct->cvavgerror),cvavgrelerror(p_struct->cvavgrelerror),ncvdefects(p_struct->ncvdefects),cvdefects(&p_struct->cvdefects) -{ -} - -lrreport::lrreport(const lrreport &rhs):_lrreport_owner(rhs) ,c(&p_struct->c),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),cvrmserror(p_struct->cvrmserror),cvavgerror(p_struct->cvavgerror),cvavgrelerror(p_struct->cvavgrelerror),ncvdefects(p_struct->ncvdefects),cvdefects(&p_struct->cvdefects) -{ -} - -lrreport& lrreport::operator=(const lrreport &rhs) -{ - if( this==&rhs ) - return *this; - _lrreport_owner::operator=(rhs); - return *this; -} - -lrreport::~lrreport() -{ -} - -/************************************************************************* -Linear regression - -Subroutine builds model: - - Y = A(0)*X[0] + ... + A(N-1)*X[N-1] + A(N) - -and model found in ALGLIB format, covariation matrix, training set errors -(rms, average, average relative) and leave-one-out cross-validation -estimate of the generalization error. CV estimate calculated using fast -algorithm with O(NPoints*NVars) complexity. - -When covariation matrix is calculated standard deviations of function -values are assumed to be equal to RMS error on the training set. - -INPUT PARAMETERS: - XY - training set, array [0..NPoints-1,0..NVars]: - * NVars columns - independent variables - * last column - dependent variable - NPoints - training set size, NPoints>NVars+1 - NVars - number of independent variables - -OUTPUT PARAMETERS: - Info - return code: - * -255, in case of unknown internal error - * -4, if internal SVD subroutine haven't converged - * -1, if incorrect parameters was passed (NPoints(xy.c_ptr()), npoints, nvars, &info, const_cast(lm.c_ptr()), const_cast(ar.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Linear regression - -Variant of LRBuild which uses vector of standatd deviations (errors in -function values). - -INPUT PARAMETERS: - XY - training set, array [0..NPoints-1,0..NVars]: - * NVars columns - independent variables - * last column - dependent variable - S - standard deviations (errors in function values) - array[0..NPoints-1], S[i]>0. - NPoints - training set size, NPoints>NVars+1 - NVars - number of independent variables - -OUTPUT PARAMETERS: - Info - return code: - * -255, in case of unknown internal error - * -4, if internal SVD subroutine haven't converged - * -1, if incorrect parameters was passed (NPoints(xy.c_ptr()), const_cast(s.c_ptr()), npoints, nvars, &info, const_cast(lm.c_ptr()), const_cast(ar.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Like LRBuildS, but builds model - - Y = A(0)*X[0] + ... + A(N-1)*X[N-1] - -i.e. with zero constant term. - - -- ALGLIB -- - Copyright 30.10.2008 by Bochkanov Sergey -*************************************************************************/ -void lrbuildzs(const real_2d_array &xy, const real_1d_array &s, const ae_int_t npoints, const ae_int_t nvars, ae_int_t &info, linearmodel &lm, lrreport &ar, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lrbuildzs(const_cast(xy.c_ptr()), const_cast(s.c_ptr()), npoints, nvars, &info, const_cast(lm.c_ptr()), const_cast(ar.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Like LRBuild but builds model - - Y = A(0)*X[0] + ... + A(N-1)*X[N-1] - -i.e. with zero constant term. - - -- ALGLIB -- - Copyright 30.10.2008 by Bochkanov Sergey -*************************************************************************/ -void lrbuildz(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, ae_int_t &info, linearmodel &lm, lrreport &ar, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lrbuildz(const_cast(xy.c_ptr()), npoints, nvars, &info, const_cast(lm.c_ptr()), const_cast(ar.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Unpacks coefficients of linear model. - -INPUT PARAMETERS: - LM - linear model in ALGLIB format - -OUTPUT PARAMETERS: - V - coefficients, array[0..NVars] - constant term (intercept) is stored in the V[NVars]. - NVars - number of independent variables (one less than number - of coefficients) - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -void lrunpack(const linearmodel &lm, real_1d_array &v, ae_int_t &nvars, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lrunpack(const_cast(lm.c_ptr()), const_cast(v.c_ptr()), &nvars, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -"Packs" coefficients and creates linear model in ALGLIB format (LRUnpack -reversed). - -INPUT PARAMETERS: - V - coefficients, array[0..NVars] - NVars - number of independent variables - -OUTPUT PAREMETERS: - LM - linear model. - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -void lrpack(const real_1d_array &v, const ae_int_t nvars, linearmodel &lm, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lrpack(const_cast(v.c_ptr()), nvars, const_cast(lm.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Procesing - -INPUT PARAMETERS: - LM - linear model - X - input vector, array[0..NVars-1]. - -Result: - value of linear model regression estimate - - -- ALGLIB -- - Copyright 03.09.2008 by Bochkanov Sergey -*************************************************************************/ -double lrprocess(const linearmodel &lm, const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::lrprocess(const_cast(lm.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -RMS error on the test set - -INPUT PARAMETERS: - LM - linear model - XY - test set - NPoints - test set size - -RESULT: - root mean square error. - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -double lrrmserror(const linearmodel &lm, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::lrrmserror(const_cast(lm.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Average error on the test set - -INPUT PARAMETERS: - LM - linear model - XY - test set - NPoints - test set size - -RESULT: - average error. - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -double lravgerror(const linearmodel &lm, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::lravgerror(const_cast(lm.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -RMS error on the test set - -INPUT PARAMETERS: - LM - linear model - XY - test set - NPoints - test set size - -RESULT: - average relative error. - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -double lravgrelerror(const linearmodel &lm, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::lravgrelerror(const_cast(lm.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_FILTERS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Filters: simple moving averages (unsymmetric). - -This filter replaces array by results of SMA(K) filter. SMA(K) is defined -as filter which averages at most K previous points (previous - not points -AROUND central point) - or less, in case of the first K-1 points. - -INPUT PARAMETERS: - X - array[N], array to process. It can be larger than N, - in this case only first N points are processed. - N - points count, N>=0 - K - K>=1 (K can be larger than N , such cases will be - correctly handled). Window width. K=1 corresponds to - identity transformation (nothing changes). - -OUTPUT PARAMETERS: - X - array, whose first N elements were processed with SMA(K) - -NOTE 1: this function uses efficient in-place algorithm which does not - allocate temporary arrays. - -NOTE 2: this algorithm makes only one pass through array and uses running - sum to speed-up calculation of the averages. Additional measures - are taken to ensure that running sum on a long sequence of zero - elements will be correctly reset to zero even in the presence of - round-off error. - -NOTE 3: this is unsymmetric version of the algorithm, which does NOT - averages points after the current one. Only X[i], X[i-1], ... are - used when calculating new value of X[i]. We should also note that - this algorithm uses BOTH previous points and current one, i.e. - new value of X[i] depends on BOTH previous point and X[i] itself. - - -- ALGLIB -- - Copyright 25.10.2011 by Bochkanov Sergey -*************************************************************************/ -void filtersma(real_1d_array &x, const ae_int_t n, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::filtersma(const_cast(x.c_ptr()), n, k, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Filters: simple moving averages (unsymmetric). - -This filter replaces array by results of SMA(K) filter. SMA(K) is defined -as filter which averages at most K previous points (previous - not points -AROUND central point) - or less, in case of the first K-1 points. - -INPUT PARAMETERS: - X - array[N], array to process. It can be larger than N, - in this case only first N points are processed. - N - points count, N>=0 - K - K>=1 (K can be larger than N , such cases will be - correctly handled). Window width. K=1 corresponds to - identity transformation (nothing changes). - -OUTPUT PARAMETERS: - X - array, whose first N elements were processed with SMA(K) - -NOTE 1: this function uses efficient in-place algorithm which does not - allocate temporary arrays. - -NOTE 2: this algorithm makes only one pass through array and uses running - sum to speed-up calculation of the averages. Additional measures - are taken to ensure that running sum on a long sequence of zero - elements will be correctly reset to zero even in the presence of - round-off error. - -NOTE 3: this is unsymmetric version of the algorithm, which does NOT - averages points after the current one. Only X[i], X[i-1], ... are - used when calculating new value of X[i]. We should also note that - this algorithm uses BOTH previous points and current one, i.e. - new value of X[i] depends on BOTH previous point and X[i] itself. - - -- ALGLIB -- - Copyright 25.10.2011 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void filtersma(real_1d_array &x, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::filtersma(const_cast(x.c_ptr()), n, k, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Filters: exponential moving averages. - -This filter replaces array by results of EMA(alpha) filter. EMA(alpha) is -defined as filter which replaces X[] by S[]: - S[0] = X[0] - S[t] = alpha*X[t] + (1-alpha)*S[t-1] - -INPUT PARAMETERS: - X - array[N], array to process. It can be larger than N, - in this case only first N points are processed. - N - points count, N>=0 - alpha - 0(x.c_ptr()), n, alpha, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Filters: exponential moving averages. - -This filter replaces array by results of EMA(alpha) filter. EMA(alpha) is -defined as filter which replaces X[] by S[]: - S[0] = X[0] - S[t] = alpha*X[t] + (1-alpha)*S[t-1] - -INPUT PARAMETERS: - X - array[N], array to process. It can be larger than N, - in this case only first N points are processed. - N - points count, N>=0 - alpha - 0(x.c_ptr()), n, alpha, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Filters: linear regression moving averages. - -This filter replaces array by results of LRMA(K) filter. - -LRMA(K) is defined as filter which, for each data point, builds linear -regression model using K prevous points (point itself is included in -these K points) and calculates value of this linear model at the point in -question. - -INPUT PARAMETERS: - X - array[N], array to process. It can be larger than N, - in this case only first N points are processed. - N - points count, N>=0 - K - K>=1 (K can be larger than N , such cases will be - correctly handled). Window width. K=1 corresponds to - identity transformation (nothing changes). - -OUTPUT PARAMETERS: - X - array, whose first N elements were processed with SMA(K) - -NOTE 1: this function uses efficient in-place algorithm which does not - allocate temporary arrays. - -NOTE 2: this algorithm makes only one pass through array and uses running - sum to speed-up calculation of the averages. Additional measures - are taken to ensure that running sum on a long sequence of zero - elements will be correctly reset to zero even in the presence of - round-off error. - -NOTE 3: this is unsymmetric version of the algorithm, which does NOT - averages points after the current one. Only X[i], X[i-1], ... are - used when calculating new value of X[i]. We should also note that - this algorithm uses BOTH previous points and current one, i.e. - new value of X[i] depends on BOTH previous point and X[i] itself. - - -- ALGLIB -- - Copyright 25.10.2011 by Bochkanov Sergey -*************************************************************************/ -void filterlrma(real_1d_array &x, const ae_int_t n, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::filterlrma(const_cast(x.c_ptr()), n, k, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Filters: linear regression moving averages. - -This filter replaces array by results of LRMA(K) filter. - -LRMA(K) is defined as filter which, for each data point, builds linear -regression model using K prevous points (point itself is included in -these K points) and calculates value of this linear model at the point in -question. - -INPUT PARAMETERS: - X - array[N], array to process. It can be larger than N, - in this case only first N points are processed. - N - points count, N>=0 - K - K>=1 (K can be larger than N , such cases will be - correctly handled). Window width. K=1 corresponds to - identity transformation (nothing changes). - -OUTPUT PARAMETERS: - X - array, whose first N elements were processed with SMA(K) - -NOTE 1: this function uses efficient in-place algorithm which does not - allocate temporary arrays. - -NOTE 2: this algorithm makes only one pass through array and uses running - sum to speed-up calculation of the averages. Additional measures - are taken to ensure that running sum on a long sequence of zero - elements will be correctly reset to zero even in the presence of - round-off error. - -NOTE 3: this is unsymmetric version of the algorithm, which does NOT - averages points after the current one. Only X[i], X[i-1], ... are - used when calculating new value of X[i]. We should also note that - this algorithm uses BOTH previous points and current one, i.e. - new value of X[i] depends on BOTH previous point and X[i] itself. - - -- ALGLIB -- - Copyright 25.10.2011 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void filterlrma(real_1d_array &x, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::filterlrma(const_cast(x.c_ptr()), n, k, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif -#endif - -#if defined(AE_COMPILE_LOGIT) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - -*************************************************************************/ -_logitmodel_owner::_logitmodel_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_logitmodel_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::logitmodel*)alglib_impl::ae_malloc(sizeof(alglib_impl::logitmodel), &_state); - memset(p_struct, 0, sizeof(alglib_impl::logitmodel)); - alglib_impl::_logitmodel_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_logitmodel_owner::_logitmodel_owner(const _logitmodel_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_logitmodel_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: logitmodel copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::logitmodel*)alglib_impl::ae_malloc(sizeof(alglib_impl::logitmodel), &_state); - memset(p_struct, 0, sizeof(alglib_impl::logitmodel)); - alglib_impl::_logitmodel_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_logitmodel_owner& _logitmodel_owner::operator=(const _logitmodel_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: logitmodel assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: logitmodel assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_logitmodel_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::logitmodel)); - alglib_impl::_logitmodel_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_logitmodel_owner::~_logitmodel_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_logitmodel_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::logitmodel* _logitmodel_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::logitmodel* _logitmodel_owner::c_ptr() const -{ - return const_cast(p_struct); -} -logitmodel::logitmodel() : _logitmodel_owner() -{ -} - -logitmodel::logitmodel(const logitmodel &rhs):_logitmodel_owner(rhs) -{ -} - -logitmodel& logitmodel::operator=(const logitmodel &rhs) -{ - if( this==&rhs ) - return *this; - _logitmodel_owner::operator=(rhs); - return *this; -} - -logitmodel::~logitmodel() -{ -} - - -/************************************************************************* -MNLReport structure contains information about training process: -* NGrad - number of gradient calculations -* NHess - number of Hessian calculations -*************************************************************************/ -_mnlreport_owner::_mnlreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_mnlreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::mnlreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::mnlreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::mnlreport)); - alglib_impl::_mnlreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_mnlreport_owner::_mnlreport_owner(const _mnlreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_mnlreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mnlreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::mnlreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::mnlreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::mnlreport)); - alglib_impl::_mnlreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_mnlreport_owner& _mnlreport_owner::operator=(const _mnlreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: mnlreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mnlreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_mnlreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::mnlreport)); - alglib_impl::_mnlreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_mnlreport_owner::~_mnlreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_mnlreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::mnlreport* _mnlreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::mnlreport* _mnlreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -mnlreport::mnlreport() : _mnlreport_owner() ,ngrad(p_struct->ngrad),nhess(p_struct->nhess) -{ -} - -mnlreport::mnlreport(const mnlreport &rhs):_mnlreport_owner(rhs) ,ngrad(p_struct->ngrad),nhess(p_struct->nhess) -{ -} - -mnlreport& mnlreport::operator=(const mnlreport &rhs) -{ - if( this==&rhs ) - return *this; - _mnlreport_owner::operator=(rhs); - return *this; -} - -mnlreport::~mnlreport() -{ -} - -/************************************************************************* -This subroutine trains logit model. - -INPUT PARAMETERS: - XY - training set, array[0..NPoints-1,0..NVars] - First NVars columns store values of independent - variables, next column stores number of class (from 0 - to NClasses-1) which dataset element belongs to. Fractional - values are rounded to nearest integer. - NPoints - training set size, NPoints>=1 - NVars - number of independent variables, NVars>=1 - NClasses - number of classes, NClasses>=2 - -OUTPUT PARAMETERS: - Info - return code: - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed - (NPoints(xy.c_ptr()), npoints, nvars, nclasses, &info, const_cast(lm.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Procesing - -INPUT PARAMETERS: - LM - logit model, passed by non-constant reference - (some fields of structure are used as temporaries - when calculating model output). - X - input vector, array[0..NVars-1]. - Y - (possibly) preallocated buffer; if size of Y is less than - NClasses, it will be reallocated.If it is large enough, it - is NOT reallocated, so we can save some time on reallocation. - -OUTPUT PARAMETERS: - Y - result, array[0..NClasses-1] - Vector of posterior probabilities for classification task. - - -- ALGLIB -- - Copyright 10.09.2008 by Bochkanov Sergey -*************************************************************************/ -void mnlprocess(const logitmodel &lm, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mnlprocess(const_cast(lm.c_ptr()), const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -'interactive' variant of MNLProcess for languages like Python which -support constructs like "Y = MNLProcess(LM,X)" and interactive mode of the -interpreter - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 10.09.2008 by Bochkanov Sergey -*************************************************************************/ -void mnlprocessi(const logitmodel &lm, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mnlprocessi(const_cast(lm.c_ptr()), const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Unpacks coefficients of logit model. Logit model have form: - - P(class=i) = S(i) / (S(0) + S(1) + ... +S(M-1)) - S(i) = Exp(A[i,0]*X[0] + ... + A[i,N-1]*X[N-1] + A[i,N]), when i(lm.c_ptr()), const_cast(a.c_ptr()), &nvars, &nclasses, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -"Packs" coefficients and creates logit model in ALGLIB format (MNLUnpack -reversed). - -INPUT PARAMETERS: - A - model (see MNLUnpack) - NVars - number of independent variables - NClasses - number of classes - -OUTPUT PARAMETERS: - LM - logit model. - - -- ALGLIB -- - Copyright 10.09.2008 by Bochkanov Sergey -*************************************************************************/ -void mnlpack(const real_2d_array &a, const ae_int_t nvars, const ae_int_t nclasses, logitmodel &lm, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mnlpack(const_cast(a.c_ptr()), nvars, nclasses, const_cast(lm.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Average cross-entropy (in bits per element) on the test set - -INPUT PARAMETERS: - LM - logit model - XY - test set - NPoints - test set size - -RESULT: - CrossEntropy/(NPoints*ln(2)). - - -- ALGLIB -- - Copyright 10.09.2008 by Bochkanov Sergey -*************************************************************************/ -double mnlavgce(const logitmodel &lm, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mnlavgce(const_cast(lm.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Relative classification error on the test set - -INPUT PARAMETERS: - LM - logit model - XY - test set - NPoints - test set size - -RESULT: - percent of incorrectly classified cases. - - -- ALGLIB -- - Copyright 10.09.2008 by Bochkanov Sergey -*************************************************************************/ -double mnlrelclserror(const logitmodel &lm, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mnlrelclserror(const_cast(lm.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -RMS error on the test set - -INPUT PARAMETERS: - LM - logit model - XY - test set - NPoints - test set size - -RESULT: - root mean square error (error when estimating posterior probabilities). - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -double mnlrmserror(const logitmodel &lm, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mnlrmserror(const_cast(lm.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Average error on the test set - -INPUT PARAMETERS: - LM - logit model - XY - test set - NPoints - test set size - -RESULT: - average error (error when estimating posterior probabilities). - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -double mnlavgerror(const logitmodel &lm, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mnlavgerror(const_cast(lm.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Average relative error on the test set - -INPUT PARAMETERS: - LM - logit model - XY - test set - NPoints - test set size - -RESULT: - average relative error (error when estimating posterior probabilities). - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -double mnlavgrelerror(const logitmodel &lm, const real_2d_array &xy, const ae_int_t ssize, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mnlavgrelerror(const_cast(lm.c_ptr()), const_cast(xy.c_ptr()), ssize, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Classification error on test set = MNLRelClsError*NPoints - - -- ALGLIB -- - Copyright 10.09.2008 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mnlclserror(const logitmodel &lm, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::mnlclserror(const_cast(lm.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_MCPD) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This structure is a MCPD (Markov Chains for Population Data) solver. - -You should use ALGLIB functions in order to work with this object. - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -_mcpdstate_owner::_mcpdstate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_mcpdstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::mcpdstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::mcpdstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::mcpdstate)); - alglib_impl::_mcpdstate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_mcpdstate_owner::_mcpdstate_owner(const _mcpdstate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_mcpdstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mcpdstate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::mcpdstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::mcpdstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::mcpdstate)); - alglib_impl::_mcpdstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_mcpdstate_owner& _mcpdstate_owner::operator=(const _mcpdstate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: mcpdstate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mcpdstate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_mcpdstate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::mcpdstate)); - alglib_impl::_mcpdstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_mcpdstate_owner::~_mcpdstate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_mcpdstate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::mcpdstate* _mcpdstate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::mcpdstate* _mcpdstate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -mcpdstate::mcpdstate() : _mcpdstate_owner() -{ -} - -mcpdstate::mcpdstate(const mcpdstate &rhs):_mcpdstate_owner(rhs) -{ -} - -mcpdstate& mcpdstate::operator=(const mcpdstate &rhs) -{ - if( this==&rhs ) - return *this; - _mcpdstate_owner::operator=(rhs); - return *this; -} - -mcpdstate::~mcpdstate() -{ -} - - -/************************************************************************* -This structure is a MCPD training report: - InnerIterationsCount - number of inner iterations of the - underlying optimization algorithm - OuterIterationsCount - number of outer iterations of the - underlying optimization algorithm - NFEV - number of merit function evaluations - TerminationType - termination type - (same as for MinBLEIC optimizer, positive - values denote success, negative ones - - failure) - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -_mcpdreport_owner::_mcpdreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_mcpdreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::mcpdreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::mcpdreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::mcpdreport)); - alglib_impl::_mcpdreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_mcpdreport_owner::_mcpdreport_owner(const _mcpdreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_mcpdreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mcpdreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::mcpdreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::mcpdreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::mcpdreport)); - alglib_impl::_mcpdreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_mcpdreport_owner& _mcpdreport_owner::operator=(const _mcpdreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: mcpdreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mcpdreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_mcpdreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::mcpdreport)); - alglib_impl::_mcpdreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_mcpdreport_owner::~_mcpdreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_mcpdreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::mcpdreport* _mcpdreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::mcpdreport* _mcpdreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -mcpdreport::mcpdreport() : _mcpdreport_owner() ,inneriterationscount(p_struct->inneriterationscount),outeriterationscount(p_struct->outeriterationscount),nfev(p_struct->nfev),terminationtype(p_struct->terminationtype) -{ -} - -mcpdreport::mcpdreport(const mcpdreport &rhs):_mcpdreport_owner(rhs) ,inneriterationscount(p_struct->inneriterationscount),outeriterationscount(p_struct->outeriterationscount),nfev(p_struct->nfev),terminationtype(p_struct->terminationtype) -{ -} - -mcpdreport& mcpdreport::operator=(const mcpdreport &rhs) -{ - if( this==&rhs ) - return *this; - _mcpdreport_owner::operator=(rhs); - return *this; -} - -mcpdreport::~mcpdreport() -{ -} - -/************************************************************************* -DESCRIPTION: - -This function creates MCPD (Markov Chains for Population Data) solver. - -This solver can be used to find transition matrix P for N-dimensional -prediction problem where transition from X[i] to X[i+1] is modelled as - X[i+1] = P*X[i] -where X[i] and X[i+1] are N-dimensional population vectors (components of -each X are non-negative), and P is a N*N transition matrix (elements of P -are non-negative, each column sums to 1.0). - -Such models arise when when: -* there is some population of individuals -* individuals can have different states -* individuals can transit from one state to another -* population size is constant, i.e. there is no new individuals and no one - leaves population -* you want to model transitions of individuals from one state into another - -USAGE: - -Here we give very brief outline of the MCPD. We strongly recommend you to -read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide -on data analysis which is available at http://www.alglib.net/dataanalysis/ - -1. User initializes algorithm state with MCPDCreate() call - -2. User adds one or more tracks - sequences of states which describe - evolution of a system being modelled from different starting conditions - -3. User may add optional boundary, equality and/or linear constraints on - the coefficients of P by calling one of the following functions: - * MCPDSetEC() to set equality constraints - * MCPDSetBC() to set bound constraints - * MCPDSetLC() to set linear constraints - -4. Optionally, user may set custom weights for prediction errors (by - default, algorithm assigns non-equal, automatically chosen weights for - errors in the prediction of different components of X). It can be done - with a call of MCPDSetPredictionWeights() function. - -5. User calls MCPDSolve() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. - -6. User calls MCPDResults() to get solution - -INPUT PARAMETERS: - N - problem dimension, N>=1 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdcreate(const ae_int_t n, mcpdstate &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mcpdcreate(n, const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -DESCRIPTION: - -This function is a specialized version of MCPDCreate() function, and we -recommend you to read comments for this function for general information -about MCPD solver. - -This function creates MCPD (Markov Chains for Population Data) solver -for "Entry-state" model, i.e. model where transition from X[i] to X[i+1] -is modelled as - X[i+1] = P*X[i] -where - X[i] and X[i+1] are N-dimensional state vectors - P is a N*N transition matrix -and one selected component of X[] is called "entry" state and is treated -in a special way: - system state always transits from "entry" state to some another state - system state can not transit from any state into "entry" state -Such conditions basically mean that row of P which corresponds to "entry" -state is zero. - -Such models arise when: -* there is some population of individuals -* individuals can have different states -* individuals can transit from one state to another -* population size is NOT constant - at every moment of time there is some - (unpredictable) amount of "new" individuals, which can transit into one - of the states at the next turn, but still no one leaves population -* you want to model transitions of individuals from one state into another -* but you do NOT want to predict amount of "new" individuals because it - does not depends on individuals already present (hence system can not - transit INTO entry state - it can only transit FROM it). - -This model is discussed in more details in the ALGLIB User Guide (see -http://www.alglib.net/dataanalysis/ for more data). - -INPUT PARAMETERS: - N - problem dimension, N>=2 - EntryState- index of entry state, in 0..N-1 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdcreateentry(const ae_int_t n, const ae_int_t entrystate, mcpdstate &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mcpdcreateentry(n, entrystate, const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -DESCRIPTION: - -This function is a specialized version of MCPDCreate() function, and we -recommend you to read comments for this function for general information -about MCPD solver. - -This function creates MCPD (Markov Chains for Population Data) solver -for "Exit-state" model, i.e. model where transition from X[i] to X[i+1] -is modelled as - X[i+1] = P*X[i] -where - X[i] and X[i+1] are N-dimensional state vectors - P is a N*N transition matrix -and one selected component of X[] is called "exit" state and is treated -in a special way: - system state can transit from any state into "exit" state - system state can not transit from "exit" state into any other state - transition operator discards "exit" state (makes it zero at each turn) -Such conditions basically mean that column of P which corresponds to -"exit" state is zero. Multiplication by such P may decrease sum of vector -components. - -Such models arise when: -* there is some population of individuals -* individuals can have different states -* individuals can transit from one state to another -* population size is NOT constant - individuals can move into "exit" state - and leave population at the next turn, but there are no new individuals -* amount of individuals which leave population can be predicted -* you want to model transitions of individuals from one state into another - (including transitions into the "exit" state) - -This model is discussed in more details in the ALGLIB User Guide (see -http://www.alglib.net/dataanalysis/ for more data). - -INPUT PARAMETERS: - N - problem dimension, N>=2 - ExitState- index of exit state, in 0..N-1 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdcreateexit(const ae_int_t n, const ae_int_t exitstate, mcpdstate &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mcpdcreateexit(n, exitstate, const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -DESCRIPTION: - -This function is a specialized version of MCPDCreate() function, and we -recommend you to read comments for this function for general information -about MCPD solver. - -This function creates MCPD (Markov Chains for Population Data) solver -for "Entry-Exit-states" model, i.e. model where transition from X[i] to -X[i+1] is modelled as - X[i+1] = P*X[i] -where - X[i] and X[i+1] are N-dimensional state vectors - P is a N*N transition matrix -one selected component of X[] is called "entry" state and is treated in a -special way: - system state always transits from "entry" state to some another state - system state can not transit from any state into "entry" state -and another one component of X[] is called "exit" state and is treated in -a special way too: - system state can transit from any state into "exit" state - system state can not transit from "exit" state into any other state - transition operator discards "exit" state (makes it zero at each turn) -Such conditions basically mean that: - row of P which corresponds to "entry" state is zero - column of P which corresponds to "exit" state is zero -Multiplication by such P may decrease sum of vector components. - -Such models arise when: -* there is some population of individuals -* individuals can have different states -* individuals can transit from one state to another -* population size is NOT constant -* at every moment of time there is some (unpredictable) amount of "new" - individuals, which can transit into one of the states at the next turn -* some individuals can move (predictably) into "exit" state and leave - population at the next turn -* you want to model transitions of individuals from one state into another, - including transitions from the "entry" state and into the "exit" state. -* but you do NOT want to predict amount of "new" individuals because it - does not depends on individuals already present (hence system can not - transit INTO entry state - it can only transit FROM it). - -This model is discussed in more details in the ALGLIB User Guide (see -http://www.alglib.net/dataanalysis/ for more data). - -INPUT PARAMETERS: - N - problem dimension, N>=2 - EntryState- index of entry state, in 0..N-1 - ExitState- index of exit state, in 0..N-1 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdcreateentryexit(const ae_int_t n, const ae_int_t entrystate, const ae_int_t exitstate, mcpdstate &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mcpdcreateentryexit(n, entrystate, exitstate, const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is used to add a track - sequence of system states at the -different moments of its evolution. - -You may add one or several tracks to the MCPD solver. In case you have -several tracks, they won't overwrite each other. For example, if you pass -two tracks, A1-A2-A3 (system at t=A+1, t=A+2 and t=A+3) and B1-B2-B3, then -solver will try to model transitions from t=A+1 to t=A+2, t=A+2 to t=A+3, -t=B+1 to t=B+2, t=B+2 to t=B+3. But it WONT mix these two tracks - i.e. it -wont try to model transition from t=A+3 to t=B+1. - -INPUT PARAMETERS: - S - solver - XY - track, array[K,N]: - * I-th row is a state at t=I - * elements of XY must be non-negative (exception will be - thrown on negative elements) - K - number of points in a track - * if given, only leading K rows of XY are used - * if not given, automatically determined from size of XY - -NOTES: - -1. Track may contain either proportional or population data: - * with proportional data all rows of XY must sum to 1.0, i.e. we have - proportions instead of absolute population values - * with population data rows of XY contain population counts and generally - do not sum to 1.0 (although they still must be non-negative) - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdaddtrack(const mcpdstate &s, const real_2d_array &xy, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mcpdaddtrack(const_cast(s.c_ptr()), const_cast(xy.c_ptr()), k, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is used to add a track - sequence of system states at the -different moments of its evolution. - -You may add one or several tracks to the MCPD solver. In case you have -several tracks, they won't overwrite each other. For example, if you pass -two tracks, A1-A2-A3 (system at t=A+1, t=A+2 and t=A+3) and B1-B2-B3, then -solver will try to model transitions from t=A+1 to t=A+2, t=A+2 to t=A+3, -t=B+1 to t=B+2, t=B+2 to t=B+3. But it WONT mix these two tracks - i.e. it -wont try to model transition from t=A+3 to t=B+1. - -INPUT PARAMETERS: - S - solver - XY - track, array[K,N]: - * I-th row is a state at t=I - * elements of XY must be non-negative (exception will be - thrown on negative elements) - K - number of points in a track - * if given, only leading K rows of XY are used - * if not given, automatically determined from size of XY - -NOTES: - -1. Track may contain either proportional or population data: - * with proportional data all rows of XY must sum to 1.0, i.e. we have - proportions instead of absolute population values - * with population data rows of XY contain population counts and generally - do not sum to 1.0 (although they still must be non-negative) - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void mcpdaddtrack(const mcpdstate &s, const real_2d_array &xy, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t k; - - k = xy.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mcpdaddtrack(const_cast(s.c_ptr()), const_cast(xy.c_ptr()), k, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function is used to add equality constraints on the elements of the -transition matrix P. - -MCPD solver has four types of constraints which can be placed on P: -* user-specified equality constraints (optional) -* user-specified bound constraints (optional) -* user-specified general linear constraints (optional) -* basic constraints (always present): - * non-negativity: P[i,j]>=0 - * consistency: every column of P sums to 1.0 - -Final constraints which are passed to the underlying optimizer are -calculated as intersection of all present constraints. For example, you -may specify boundary constraint on P[0,0] and equality one: - 0.1<=P[0,0]<=0.9 - P[0,0]=0.5 -Such combination of constraints will be silently reduced to their -intersection, which is P[0,0]=0.5. - -This function can be used to place equality constraints on arbitrary -subset of elements of P. Set of constraints is specified by EC, which may -contain either NAN's or finite numbers from [0,1]. NAN denotes absence of -constraint, finite number denotes equality constraint on specific element -of P. - -You can also use MCPDAddEC() function which allows to ADD equality -constraint for one element of P without changing constraints for other -elements. - -These functions (MCPDSetEC and MCPDAddEC) interact as follows: -* there is internal matrix of equality constraints which is stored in the - MCPD solver -* MCPDSetEC() replaces this matrix by another one (SET) -* MCPDAddEC() modifies one element of this matrix and leaves other ones - unchanged (ADD) -* thus MCPDAddEC() call preserves all modifications done by previous - calls, while MCPDSetEC() completely discards all changes done to the - equality constraints. - -INPUT PARAMETERS: - S - solver - EC - equality constraints, array[N,N]. Elements of EC can be - either NAN's or finite numbers from [0,1]. NAN denotes - absence of constraints, while finite value denotes - equality constraint on the corresponding element of P. - -NOTES: - -1. infinite values of EC will lead to exception being thrown. Values less -than 0.0 or greater than 1.0 will lead to error code being returned after -call to MCPDSolve(). - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdsetec(const mcpdstate &s, const real_2d_array &ec, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mcpdsetec(const_cast(s.c_ptr()), const_cast(ec.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is used to add equality constraints on the elements of the -transition matrix P. - -MCPD solver has four types of constraints which can be placed on P: -* user-specified equality constraints (optional) -* user-specified bound constraints (optional) -* user-specified general linear constraints (optional) -* basic constraints (always present): - * non-negativity: P[i,j]>=0 - * consistency: every column of P sums to 1.0 - -Final constraints which are passed to the underlying optimizer are -calculated as intersection of all present constraints. For example, you -may specify boundary constraint on P[0,0] and equality one: - 0.1<=P[0,0]<=0.9 - P[0,0]=0.5 -Such combination of constraints will be silently reduced to their -intersection, which is P[0,0]=0.5. - -This function can be used to ADD equality constraint for one element of P -without changing constraints for other elements. - -You can also use MCPDSetEC() function which allows you to specify -arbitrary set of equality constraints in one call. - -These functions (MCPDSetEC and MCPDAddEC) interact as follows: -* there is internal matrix of equality constraints which is stored in the - MCPD solver -* MCPDSetEC() replaces this matrix by another one (SET) -* MCPDAddEC() modifies one element of this matrix and leaves other ones - unchanged (ADD) -* thus MCPDAddEC() call preserves all modifications done by previous - calls, while MCPDSetEC() completely discards all changes done to the - equality constraints. - -INPUT PARAMETERS: - S - solver - I - row index of element being constrained - J - column index of element being constrained - C - value (constraint for P[I,J]). Can be either NAN (no - constraint) or finite value from [0,1]. - -NOTES: - -1. infinite values of C will lead to exception being thrown. Values less -than 0.0 or greater than 1.0 will lead to error code being returned after -call to MCPDSolve(). - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdaddec(const mcpdstate &s, const ae_int_t i, const ae_int_t j, const double c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mcpdaddec(const_cast(s.c_ptr()), i, j, c, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is used to add bound constraints on the elements of the -transition matrix P. - -MCPD solver has four types of constraints which can be placed on P: -* user-specified equality constraints (optional) -* user-specified bound constraints (optional) -* user-specified general linear constraints (optional) -* basic constraints (always present): - * non-negativity: P[i,j]>=0 - * consistency: every column of P sums to 1.0 - -Final constraints which are passed to the underlying optimizer are -calculated as intersection of all present constraints. For example, you -may specify boundary constraint on P[0,0] and equality one: - 0.1<=P[0,0]<=0.9 - P[0,0]=0.5 -Such combination of constraints will be silently reduced to their -intersection, which is P[0,0]=0.5. - -This function can be used to place bound constraints on arbitrary -subset of elements of P. Set of constraints is specified by BndL/BndU -matrices, which may contain arbitrary combination of finite numbers or -infinities (like -INF(s.c_ptr()), const_cast(bndl.c_ptr()), const_cast(bndu.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is used to add bound constraints on the elements of the -transition matrix P. - -MCPD solver has four types of constraints which can be placed on P: -* user-specified equality constraints (optional) -* user-specified bound constraints (optional) -* user-specified general linear constraints (optional) -* basic constraints (always present): - * non-negativity: P[i,j]>=0 - * consistency: every column of P sums to 1.0 - -Final constraints which are passed to the underlying optimizer are -calculated as intersection of all present constraints. For example, you -may specify boundary constraint on P[0,0] and equality one: - 0.1<=P[0,0]<=0.9 - P[0,0]=0.5 -Such combination of constraints will be silently reduced to their -intersection, which is P[0,0]=0.5. - -This function can be used to ADD bound constraint for one element of P -without changing constraints for other elements. - -You can also use MCPDSetBC() function which allows to place bound -constraints on arbitrary subset of elements of P. Set of constraints is -specified by BndL/BndU matrices, which may contain arbitrary combination -of finite numbers or infinities (like -INF(s.c_ptr()), i, j, bndl, bndu, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is used to set linear equality/inequality constraints on the -elements of the transition matrix P. - -This function can be used to set one or several general linear constraints -on the elements of P. Two types of constraints are supported: -* equality constraints -* inequality constraints (both less-or-equal and greater-or-equal) - -Coefficients of constraints are specified by matrix C (one of the -parameters). One row of C corresponds to one constraint. Because -transition matrix P has N*N elements, we need N*N columns to store all -coefficients (they are stored row by row), and one more column to store -right part - hence C has N*N+1 columns. Constraint kind is stored in the -CT array. - -Thus, I-th linear constraint is - P[0,0]*C[I,0] + P[0,1]*C[I,1] + .. + P[0,N-1]*C[I,N-1] + - + P[1,0]*C[I,N] + P[1,1]*C[I,N+1] + ... + - + P[N-1,N-1]*C[I,N*N-1] ?=? C[I,N*N] -where ?=? can be either "=" (CT[i]=0), "<=" (CT[i]<0) or ">=" (CT[i]>0). - -Your constraint may involve only some subset of P (less than N*N elements). -For example it can be something like - P[0,0] + P[0,1] = 0.5 -In this case you still should pass matrix with N*N+1 columns, but all its -elements (except for C[0,0], C[0,1] and C[0,N*N-1]) will be zero. - -INPUT PARAMETERS: - S - solver - C - array[K,N*N+1] - coefficients of constraints - (see above for complete description) - CT - array[K] - constraint types - (see above for complete description) - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdsetlc(const mcpdstate &s, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mcpdsetlc(const_cast(s.c_ptr()), const_cast(c.c_ptr()), const_cast(ct.c_ptr()), k, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is used to set linear equality/inequality constraints on the -elements of the transition matrix P. - -This function can be used to set one or several general linear constraints -on the elements of P. Two types of constraints are supported: -* equality constraints -* inequality constraints (both less-or-equal and greater-or-equal) - -Coefficients of constraints are specified by matrix C (one of the -parameters). One row of C corresponds to one constraint. Because -transition matrix P has N*N elements, we need N*N columns to store all -coefficients (they are stored row by row), and one more column to store -right part - hence C has N*N+1 columns. Constraint kind is stored in the -CT array. - -Thus, I-th linear constraint is - P[0,0]*C[I,0] + P[0,1]*C[I,1] + .. + P[0,N-1]*C[I,N-1] + - + P[1,0]*C[I,N] + P[1,1]*C[I,N+1] + ... + - + P[N-1,N-1]*C[I,N*N-1] ?=? C[I,N*N] -where ?=? can be either "=" (CT[i]=0), "<=" (CT[i]<0) or ">=" (CT[i]>0). - -Your constraint may involve only some subset of P (less than N*N elements). -For example it can be something like - P[0,0] + P[0,1] = 0.5 -In this case you still should pass matrix with N*N+1 columns, but all its -elements (except for C[0,0], C[0,1] and C[0,N*N-1]) will be zero. - -INPUT PARAMETERS: - S - solver - C - array[K,N*N+1] - coefficients of constraints - (see above for complete description) - CT - array[K] - constraint types - (see above for complete description) - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void mcpdsetlc(const mcpdstate &s, const real_2d_array &c, const integer_1d_array &ct, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t k; - if( (c.rows()!=ct.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'mcpdsetlc': looks like one of arguments has wrong size"); - k = c.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mcpdsetlc(const_cast(s.c_ptr()), const_cast(c.c_ptr()), const_cast(ct.c_ptr()), k, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function allows to tune amount of Tikhonov regularization being -applied to your problem. - -By default, regularizing term is equal to r*||P-prior_P||^2, where r is a -small non-zero value, P is transition matrix, prior_P is identity matrix, -||X||^2 is a sum of squared elements of X. - -This function allows you to change coefficient r. You can also change -prior values with MCPDSetPrior() function. - -INPUT PARAMETERS: - S - solver - V - regularization coefficient, finite non-negative value. It - is not recommended to specify zero value unless you are - pretty sure that you want it. - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdsettikhonovregularizer(const mcpdstate &s, const double v, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mcpdsettikhonovregularizer(const_cast(s.c_ptr()), v, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function allows to set prior values used for regularization of your -problem. - -By default, regularizing term is equal to r*||P-prior_P||^2, where r is a -small non-zero value, P is transition matrix, prior_P is identity matrix, -||X||^2 is a sum of squared elements of X. - -This function allows you to change prior values prior_P. You can also -change r with MCPDSetTikhonovRegularizer() function. - -INPUT PARAMETERS: - S - solver - PP - array[N,N], matrix of prior values: - 1. elements must be real numbers from [0,1] - 2. columns must sum to 1.0. - First property is checked (exception is thrown otherwise), - while second one is not checked/enforced. - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdsetprior(const mcpdstate &s, const real_2d_array &pp, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mcpdsetprior(const_cast(s.c_ptr()), const_cast(pp.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is used to change prediction weights - -MCPD solver scales prediction errors as follows - Error(P) = ||W*(y-P*x)||^2 -where - x is a system state at time t - y is a system state at time t+1 - P is a transition matrix - W is a diagonal scaling matrix - -By default, weights are chosen in order to minimize relative prediction -error instead of absolute one. For example, if one component of state is -about 0.5 in magnitude and another one is about 0.05, then algorithm will -make corresponding weights equal to 2.0 and 20.0. - -INPUT PARAMETERS: - S - solver - PW - array[N], weights: - * must be non-negative values (exception will be thrown otherwise) - * zero values will be replaced by automatically chosen values - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdsetpredictionweights(const mcpdstate &s, const real_1d_array &pw, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mcpdsetpredictionweights(const_cast(s.c_ptr()), const_cast(pw.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is used to start solution of the MCPD problem. - -After return from this function, you can use MCPDResults() to get solution -and completion code. - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdsolve(const mcpdstate &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mcpdsolve(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -MCPD results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - P - array[N,N], transition matrix - Rep - optimization report. You should check Rep.TerminationType - in order to distinguish successful termination from - unsuccessful one. Speaking short, positive values denote - success, negative ones are failures. - More information about fields of this structure can be - found in the comments on MCPDReport datatype. - - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdresults(const mcpdstate &s, real_2d_array &p, mcpdreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mcpdresults(const_cast(s.c_ptr()), const_cast(p.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_MLPE) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Neural networks ensemble -*************************************************************************/ -_mlpensemble_owner::_mlpensemble_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_mlpensemble_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::mlpensemble*)alglib_impl::ae_malloc(sizeof(alglib_impl::mlpensemble), &_state); - memset(p_struct, 0, sizeof(alglib_impl::mlpensemble)); - alglib_impl::_mlpensemble_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_mlpensemble_owner::_mlpensemble_owner(const _mlpensemble_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_mlpensemble_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mlpensemble copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::mlpensemble*)alglib_impl::ae_malloc(sizeof(alglib_impl::mlpensemble), &_state); - memset(p_struct, 0, sizeof(alglib_impl::mlpensemble)); - alglib_impl::_mlpensemble_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_mlpensemble_owner& _mlpensemble_owner::operator=(const _mlpensemble_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: mlpensemble assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mlpensemble assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_mlpensemble_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::mlpensemble)); - alglib_impl::_mlpensemble_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_mlpensemble_owner::~_mlpensemble_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_mlpensemble_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::mlpensemble* _mlpensemble_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::mlpensemble* _mlpensemble_owner::c_ptr() const -{ - return const_cast(p_struct); -} -mlpensemble::mlpensemble() : _mlpensemble_owner() -{ -} - -mlpensemble::mlpensemble(const mlpensemble &rhs):_mlpensemble_owner(rhs) -{ -} - -mlpensemble& mlpensemble::operator=(const mlpensemble &rhs) -{ - if( this==&rhs ) - return *this; - _mlpensemble_owner::operator=(rhs); - return *this; -} - -mlpensemble::~mlpensemble() -{ -} - - -/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -void mlpeserialize(mlpensemble &obj, std::string &s_out) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - alglib_impl::ae_int_t ssize; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_alloc_start(&serializer); - alglib_impl::mlpealloc(&serializer, obj.c_ptr(), &state); - ssize = alglib_impl::ae_serializer_get_alloc_size(&serializer); - s_out.clear(); - s_out.reserve((size_t)(ssize+1)); - alglib_impl::ae_serializer_sstart_str(&serializer, &s_out); - alglib_impl::mlpeserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_assert( s_out.length()<=(size_t)ssize, "ALGLIB: serialization integrity error", &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} -/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -void mlpeunserialize(const std::string &s_in, mlpensemble &obj) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_ustart_str(&serializer, &s_in); - alglib_impl::mlpeunserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} - - -/************************************************************************* -This function serializes data structure to C++ stream. - -Data stream generated by this function is same as string representation -generated by string version of serializer - alphanumeric characters, -dots, underscores, minus signs, which are grouped into words separated by -spaces and CR+LF. - -We recommend you to read comments on string version of serializer to find -out more about serialization of AlGLIB objects. -*************************************************************************/ -void mlpeserialize(mlpensemble &obj, std::ostream &s_out) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_alloc_start(&serializer); - alglib_impl::mlpealloc(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_get_alloc_size(&serializer); // not actually needed, but we have to ask - alglib_impl::ae_serializer_sstart_stream(&serializer, &s_out); - alglib_impl::mlpeserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} -/************************************************************************* -This function unserializes data structure from stream. -*************************************************************************/ -void mlpeunserialize(const std::istream &s_in, mlpensemble &obj) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_ustart_stream(&serializer, &s_in); - alglib_impl::mlpeunserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} - -/************************************************************************* -Like MLPCreate0, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreate0(const ae_int_t nin, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpecreate0(nin, nout, ensemblesize, const_cast(ensemble.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Like MLPCreate1, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreate1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpecreate1(nin, nhid, nout, ensemblesize, const_cast(ensemble.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Like MLPCreate2, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreate2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpecreate2(nin, nhid1, nhid2, nout, ensemblesize, const_cast(ensemble.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Like MLPCreateB0, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreateb0(const ae_int_t nin, const ae_int_t nout, const double b, const double d, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpecreateb0(nin, nout, b, d, ensemblesize, const_cast(ensemble.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Like MLPCreateB1, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreateb1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const double b, const double d, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpecreateb1(nin, nhid, nout, b, d, ensemblesize, const_cast(ensemble.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Like MLPCreateB2, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreateb2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const double b, const double d, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpecreateb2(nin, nhid1, nhid2, nout, b, d, ensemblesize, const_cast(ensemble.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Like MLPCreateR0, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreater0(const ae_int_t nin, const ae_int_t nout, const double a, const double b, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpecreater0(nin, nout, a, b, ensemblesize, const_cast(ensemble.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Like MLPCreateR1, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreater1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const double a, const double b, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpecreater1(nin, nhid, nout, a, b, ensemblesize, const_cast(ensemble.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Like MLPCreateR2, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreater2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const double a, const double b, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpecreater2(nin, nhid1, nhid2, nout, a, b, ensemblesize, const_cast(ensemble.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Like MLPCreateC0, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreatec0(const ae_int_t nin, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpecreatec0(nin, nout, ensemblesize, const_cast(ensemble.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Like MLPCreateC1, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreatec1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpecreatec1(nin, nhid, nout, ensemblesize, const_cast(ensemble.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Like MLPCreateC2, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreatec2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpecreatec2(nin, nhid1, nhid2, nout, ensemblesize, const_cast(ensemble.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Creates ensemble from network. Only network geometry is copied. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreatefromnetwork(const multilayerperceptron &network, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpecreatefromnetwork(const_cast(network.c_ptr()), ensemblesize, const_cast(ensemble.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Randomization of MLP ensemble - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlperandomize(const mlpensemble &ensemble, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlperandomize(const_cast(ensemble.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Return ensemble properties (number of inputs and outputs). - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpeproperties(const mlpensemble &ensemble, ae_int_t &nin, ae_int_t &nout, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpeproperties(const_cast(ensemble.c_ptr()), &nin, &nout, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Return normalization type (whether ensemble is SOFTMAX-normalized or not). - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -bool mlpeissoftmax(const mlpensemble &ensemble, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::mlpeissoftmax(const_cast(ensemble.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Procesing - -INPUT PARAMETERS: - Ensemble- neural networks ensemble - X - input vector, array[0..NIn-1]. - Y - (possibly) preallocated buffer; if size of Y is less than - NOut, it will be reallocated. If it is large enough, it - is NOT reallocated, so we can save some time on reallocation. - - -OUTPUT PARAMETERS: - Y - result. Regression estimate when solving regression task, - vector of posterior probabilities for classification task. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpeprocess(const mlpensemble &ensemble, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpeprocess(const_cast(ensemble.c_ptr()), const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -'interactive' variant of MLPEProcess for languages like Python which -support constructs like "Y = MLPEProcess(LM,X)" and interactive mode of the -interpreter - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpeprocessi(const mlpensemble &ensemble, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpeprocessi(const_cast(ensemble.c_ptr()), const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Relative classification error on the test set - -INPUT PARAMETERS: - Ensemble- ensemble - XY - test set - NPoints - test set size - -RESULT: - percent of incorrectly classified cases. - Works both for classifier betwork and for regression networks which -are used as classifiers. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -double mlperelclserror(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlperelclserror(const_cast(ensemble.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Average cross-entropy (in bits per element) on the test set - -INPUT PARAMETERS: - Ensemble- ensemble - XY - test set - NPoints - test set size - -RESULT: - CrossEntropy/(NPoints*LN(2)). - Zero if ensemble solves regression task. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -double mlpeavgce(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlpeavgce(const_cast(ensemble.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -RMS error on the test set - -INPUT PARAMETERS: - Ensemble- ensemble - XY - test set - NPoints - test set size - -RESULT: - root mean square error. - Its meaning for regression task is obvious. As for classification task -RMS error means error when estimating posterior probabilities. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -double mlpermserror(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlpermserror(const_cast(ensemble.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Average error on the test set - -INPUT PARAMETERS: - Ensemble- ensemble - XY - test set - NPoints - test set size - -RESULT: - Its meaning for regression task is obvious. As for classification task -it means average error when estimating posterior probabilities. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -double mlpeavgerror(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlpeavgerror(const_cast(ensemble.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Average relative error on the test set - -INPUT PARAMETERS: - Ensemble- ensemble - XY - test set - NPoints - test set size - -RESULT: - Its meaning for regression task is obvious. As for classification task -it means average relative error when estimating posterior probabilities. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -double mlpeavgrelerror(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::mlpeavgrelerror(const_cast(ensemble.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_MLPTRAIN) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Training report: - * RelCLSError - fraction of misclassified cases. - * AvgCE - acerage cross-entropy - * RMSError - root-mean-square error - * AvgError - average error - * AvgRelError - average relative error - * NGrad - number of gradient calculations - * NHess - number of Hessian calculations - * NCholesky - number of Cholesky decompositions - -NOTE 1: RelCLSError/AvgCE are zero on regression problems. - -NOTE 2: on classification problems RMSError/AvgError/AvgRelError contain - errors in prediction of posterior probabilities -*************************************************************************/ -_mlpreport_owner::_mlpreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_mlpreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::mlpreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::mlpreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::mlpreport)); - alglib_impl::_mlpreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_mlpreport_owner::_mlpreport_owner(const _mlpreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_mlpreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mlpreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::mlpreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::mlpreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::mlpreport)); - alglib_impl::_mlpreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_mlpreport_owner& _mlpreport_owner::operator=(const _mlpreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: mlpreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mlpreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_mlpreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::mlpreport)); - alglib_impl::_mlpreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_mlpreport_owner::~_mlpreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_mlpreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::mlpreport* _mlpreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::mlpreport* _mlpreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -mlpreport::mlpreport() : _mlpreport_owner() ,relclserror(p_struct->relclserror),avgce(p_struct->avgce),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),ngrad(p_struct->ngrad),nhess(p_struct->nhess),ncholesky(p_struct->ncholesky) -{ -} - -mlpreport::mlpreport(const mlpreport &rhs):_mlpreport_owner(rhs) ,relclserror(p_struct->relclserror),avgce(p_struct->avgce),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),ngrad(p_struct->ngrad),nhess(p_struct->nhess),ncholesky(p_struct->ncholesky) -{ -} - -mlpreport& mlpreport::operator=(const mlpreport &rhs) -{ - if( this==&rhs ) - return *this; - _mlpreport_owner::operator=(rhs); - return *this; -} - -mlpreport::~mlpreport() -{ -} - - -/************************************************************************* -Cross-validation estimates of generalization error -*************************************************************************/ -_mlpcvreport_owner::_mlpcvreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_mlpcvreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::mlpcvreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::mlpcvreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::mlpcvreport)); - alglib_impl::_mlpcvreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_mlpcvreport_owner::_mlpcvreport_owner(const _mlpcvreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_mlpcvreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mlpcvreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::mlpcvreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::mlpcvreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::mlpcvreport)); - alglib_impl::_mlpcvreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_mlpcvreport_owner& _mlpcvreport_owner::operator=(const _mlpcvreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: mlpcvreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mlpcvreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_mlpcvreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::mlpcvreport)); - alglib_impl::_mlpcvreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_mlpcvreport_owner::~_mlpcvreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_mlpcvreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::mlpcvreport* _mlpcvreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::mlpcvreport* _mlpcvreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -mlpcvreport::mlpcvreport() : _mlpcvreport_owner() ,relclserror(p_struct->relclserror),avgce(p_struct->avgce),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror) -{ -} - -mlpcvreport::mlpcvreport(const mlpcvreport &rhs):_mlpcvreport_owner(rhs) ,relclserror(p_struct->relclserror),avgce(p_struct->avgce),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror) -{ -} - -mlpcvreport& mlpcvreport::operator=(const mlpcvreport &rhs) -{ - if( this==&rhs ) - return *this; - _mlpcvreport_owner::operator=(rhs); - return *this; -} - -mlpcvreport::~mlpcvreport() -{ -} - - -/************************************************************************* -Trainer object for neural network. - -You should not try to access fields of this object directly - use ALGLIB -functions to work with this object. -*************************************************************************/ -_mlptrainer_owner::_mlptrainer_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_mlptrainer_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::mlptrainer*)alglib_impl::ae_malloc(sizeof(alglib_impl::mlptrainer), &_state); - memset(p_struct, 0, sizeof(alglib_impl::mlptrainer)); - alglib_impl::_mlptrainer_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_mlptrainer_owner::_mlptrainer_owner(const _mlptrainer_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_mlptrainer_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mlptrainer copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::mlptrainer*)alglib_impl::ae_malloc(sizeof(alglib_impl::mlptrainer), &_state); - memset(p_struct, 0, sizeof(alglib_impl::mlptrainer)); - alglib_impl::_mlptrainer_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_mlptrainer_owner& _mlptrainer_owner::operator=(const _mlptrainer_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: mlptrainer assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mlptrainer assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_mlptrainer_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::mlptrainer)); - alglib_impl::_mlptrainer_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_mlptrainer_owner::~_mlptrainer_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_mlptrainer_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::mlptrainer* _mlptrainer_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::mlptrainer* _mlptrainer_owner::c_ptr() const -{ - return const_cast(p_struct); -} -mlptrainer::mlptrainer() : _mlptrainer_owner() -{ -} - -mlptrainer::mlptrainer(const mlptrainer &rhs):_mlptrainer_owner(rhs) -{ -} - -mlptrainer& mlptrainer::operator=(const mlptrainer &rhs) -{ - if( this==&rhs ) - return *this; - _mlptrainer_owner::operator=(rhs); - return *this; -} - -mlptrainer::~mlptrainer() -{ -} - -/************************************************************************* -Neural network training using modified Levenberg-Marquardt with exact -Hessian calculation and regularization. Subroutine trains neural network -with restarts from random positions. Algorithm is well suited for small -and medium scale problems (hundreds of weights). - -INPUT PARAMETERS: - Network - neural network with initialized geometry - XY - training set - NPoints - training set size - Decay - weight decay constant, >=0.001 - Decay term 'Decay*||Weights||^2' is added to error - function. - If you don't know what Decay to choose, use 0.001. - Restarts - number of restarts from random position, >0. - If you don't know what Restarts to choose, use 2. - -OUTPUT PARAMETERS: - Network - trained neural network. - Info - return code: - * -9, if internal matrix inverse subroutine failed - * -2, if there is a point with class number - outside of [0..NOut-1]. - * -1, if wrong parameters specified - (NPoints<0, Restarts<1). - * 2, if task has been solved. - Rep - training report - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -void mlptrainlm(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, ae_int_t &info, mlpreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlptrainlm(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), npoints, decay, restarts, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Neural network training using L-BFGS algorithm with regularization. -Subroutine trains neural network with restarts from random positions. -Algorithm is well suited for problems of any dimensionality (memory -requirements and step complexity are linear by weights number). - -INPUT PARAMETERS: - Network - neural network with initialized geometry - XY - training set - NPoints - training set size - Decay - weight decay constant, >=0.001 - Decay term 'Decay*||Weights||^2' is added to error - function. - If you don't know what Decay to choose, use 0.001. - Restarts - number of restarts from random position, >0. - If you don't know what Restarts to choose, use 2. - WStep - stopping criterion. Algorithm stops if step size is - less than WStep. Recommended value - 0.01. Zero step - size means stopping after MaxIts iterations. - MaxIts - stopping criterion. Algorithm stops after MaxIts - iterations (NOT gradient calculations). Zero MaxIts - means stopping when step is sufficiently small. - -OUTPUT PARAMETERS: - Network - trained neural network. - Info - return code: - * -8, if both WStep=0 and MaxIts=0 - * -2, if there is a point with class number - outside of [0..NOut-1]. - * -1, if wrong parameters specified - (NPoints<0, Restarts<1). - * 2, if task has been solved. - Rep - training report - - -- ALGLIB -- - Copyright 09.12.2007 by Bochkanov Sergey -*************************************************************************/ -void mlptrainlbfgs(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, const double wstep, const ae_int_t maxits, ae_int_t &info, mlpreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlptrainlbfgs(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), npoints, decay, restarts, wstep, maxits, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Neural network training using early stopping (base algorithm - L-BFGS with -regularization). - -INPUT PARAMETERS: - Network - neural network with initialized geometry - TrnXY - training set - TrnSize - training set size, TrnSize>0 - ValXY - validation set - ValSize - validation set size, ValSize>0 - Decay - weight decay constant, >=0.001 - Decay term 'Decay*||Weights||^2' is added to error - function. - If you don't know what Decay to choose, use 0.001. - Restarts - number of restarts, either: - * strictly positive number - algorithm make specified - number of restarts from random position. - * -1, in which case algorithm makes exactly one run - from the initial state of the network (no randomization). - If you don't know what Restarts to choose, choose one - one the following: - * -1 (deterministic start) - * +1 (one random restart) - * +5 (moderate amount of random restarts) - -OUTPUT PARAMETERS: - Network - trained neural network. - Info - return code: - * -2, if there is a point with class number - outside of [0..NOut-1]. - * -1, if wrong parameters specified - (NPoints<0, Restarts<1, ...). - * 2, task has been solved, stopping criterion met - - sufficiently small step size. Not expected (we - use EARLY stopping) but possible and not an - error. - * 6, task has been solved, stopping criterion met - - increasing of validation set error. - Rep - training report - -NOTE: - -Algorithm stops if validation set error increases for a long enough or -step size is small enought (there are task where validation set may -decrease for eternity). In any case solution returned corresponds to the -minimum of validation set error. - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -void mlptraines(const multilayerperceptron &network, const real_2d_array &trnxy, const ae_int_t trnsize, const real_2d_array &valxy, const ae_int_t valsize, const double decay, const ae_int_t restarts, ae_int_t &info, mlpreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlptraines(const_cast(network.c_ptr()), const_cast(trnxy.c_ptr()), trnsize, const_cast(valxy.c_ptr()), valsize, decay, restarts, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Cross-validation estimate of generalization error. - -Base algorithm - L-BFGS. - -INPUT PARAMETERS: - Network - neural network with initialized geometry. Network is - not changed during cross-validation - it is used only - as a representative of its architecture. - XY - training set. - SSize - training set size - Decay - weight decay, same as in MLPTrainLBFGS - Restarts - number of restarts, >0. - restarts are counted for each partition separately, so - total number of restarts will be Restarts*FoldsCount. - WStep - stopping criterion, same as in MLPTrainLBFGS - MaxIts - stopping criterion, same as in MLPTrainLBFGS - FoldsCount - number of folds in k-fold cross-validation, - 2<=FoldsCount<=SSize. - recommended value: 10. - -OUTPUT PARAMETERS: - Info - return code, same as in MLPTrainLBFGS - Rep - report, same as in MLPTrainLM/MLPTrainLBFGS - CVRep - generalization error estimates - - -- ALGLIB -- - Copyright 09.12.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpkfoldcvlbfgs(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, const double wstep, const ae_int_t maxits, const ae_int_t foldscount, ae_int_t &info, mlpreport &rep, mlpcvreport &cvrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpkfoldcvlbfgs(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), npoints, decay, restarts, wstep, maxits, foldscount, &info, const_cast(rep.c_ptr()), const_cast(cvrep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Cross-validation estimate of generalization error. - -Base algorithm - Levenberg-Marquardt. - -INPUT PARAMETERS: - Network - neural network with initialized geometry. Network is - not changed during cross-validation - it is used only - as a representative of its architecture. - XY - training set. - SSize - training set size - Decay - weight decay, same as in MLPTrainLBFGS - Restarts - number of restarts, >0. - restarts are counted for each partition separately, so - total number of restarts will be Restarts*FoldsCount. - FoldsCount - number of folds in k-fold cross-validation, - 2<=FoldsCount<=SSize. - recommended value: 10. - -OUTPUT PARAMETERS: - Info - return code, same as in MLPTrainLBFGS - Rep - report, same as in MLPTrainLM/MLPTrainLBFGS - CVRep - generalization error estimates - - -- ALGLIB -- - Copyright 09.12.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpkfoldcvlm(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, const ae_int_t foldscount, ae_int_t &info, mlpreport &rep, mlpcvreport &cvrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpkfoldcvlm(const_cast(network.c_ptr()), const_cast(xy.c_ptr()), npoints, decay, restarts, foldscount, &info, const_cast(rep.c_ptr()), const_cast(cvrep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function estimates generalization error using cross-validation on the -current dataset with current training settings. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - trainer object - Network - neural network. It must have same number of inputs and - output/classes as was specified during creation of the - trainer object. Network is not changed during cross- - validation and is not trained - it is used only as - representative of its architecture. I.e., we estimate - generalization properties of ARCHITECTURE, not some - specific network. - NRestarts - number of restarts, >=0: - * NRestarts>0 means that for each cross-validation - round specified number of random restarts is - performed, with best network being chosen after - training. - * NRestarts=0 is same as NRestarts=1 - FoldsCount - number of folds in k-fold cross-validation: - * 2<=FoldsCount<=size of dataset - * recommended value: 10. - * values larger than dataset size will be silently - truncated down to dataset size - -OUTPUT PARAMETERS: - Rep - structure which contains cross-validation estimates: - * Rep.RelCLSError - fraction of misclassified cases. - * Rep.AvgCE - acerage cross-entropy - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average error - * Rep.AvgRelError - average relative error - -NOTE: when no dataset was specified with MLPSetDataset/SetSparseDataset(), - or subset with only one point was given, zeros are returned as - estimates. - -NOTE: this method performs FoldsCount cross-validation rounds, each one - with NRestarts random starts. Thus, FoldsCount*NRestarts networks - are trained in total. - -NOTE: Rep.RelCLSError/Rep.AvgCE are zero on regression problems. - -NOTE: on classification problems Rep.RMSError/Rep.AvgError/Rep.AvgRelError - contain errors in prediction of posterior probabilities. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpkfoldcv(const mlptrainer &s, const multilayerperceptron &network, const ae_int_t nrestarts, const ae_int_t foldscount, mlpreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpkfoldcv(const_cast(s.c_ptr()), const_cast(network.c_ptr()), nrestarts, foldscount, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Creation of the network trainer object for regression networks - -INPUT PARAMETERS: - NIn - number of inputs, NIn>=1 - NOut - number of outputs, NOut>=1 - -OUTPUT PARAMETERS: - S - neural network trainer object. - This structure can be used to train any regression - network with NIn inputs and NOut outputs. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpcreatetrainer(const ae_int_t nin, const ae_int_t nout, mlptrainer &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpcreatetrainer(nin, nout, const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Creation of the network trainer object for classification networks - -INPUT PARAMETERS: - NIn - number of inputs, NIn>=1 - NClasses - number of classes, NClasses>=2 - -OUTPUT PARAMETERS: - S - neural network trainer object. - This structure can be used to train any classification - network with NIn inputs and NOut outputs. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpcreatetrainercls(const ae_int_t nin, const ae_int_t nclasses, mlptrainer &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpcreatetrainercls(nin, nclasses, const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets "current dataset" of the trainer object to one passed -by user. - -INPUT PARAMETERS: - S - trainer object - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. - NPoints - points count, >=0. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -datasetformat is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpsetdataset(const mlptrainer &s, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpsetdataset(const_cast(s.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets "current dataset" of the trainer object to one passed -by user (sparse matrix is used to store dataset). - -INPUT PARAMETERS: - S - trainer object - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Any sparse storage format can be used: - Hash-table, CRS... - NPoints - points count, >=0 - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -datasetformat is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpsetsparsedataset(const mlptrainer &s, const sparsematrix &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpsetsparsedataset(const_cast(s.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets weight decay coefficient which is used for training. - -INPUT PARAMETERS: - S - trainer object - Decay - weight decay coefficient, >=0. Weight decay term - 'Decay*||Weights||^2' is added to error function. If - you don't know what Decay to choose, use 1.0E-3. - Weight decay can be set to zero, in this case network - is trained without weight decay. - -NOTE: by default network uses some small nonzero value for weight decay. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpsetdecay(const mlptrainer &s, const double decay, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpsetdecay(const_cast(s.c_ptr()), decay, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets stopping criteria for the optimizer. - -INPUT PARAMETERS: - S - trainer object - WStep - stopping criterion. Algorithm stops if step size is - less than WStep. Recommended value - 0.01. Zero step - size means stopping after MaxIts iterations. - WStep>=0. - MaxIts - stopping criterion. Algorithm stops after MaxIts - epochs (full passes over entire dataset). Zero MaxIts - means stopping when step is sufficiently small. - MaxIts>=0. - -NOTE: by default, WStep=0.005 and MaxIts=0 are used. These values are also - used when MLPSetCond() is called with WStep=0 and MaxIts=0. - -NOTE: these stopping criteria are used for all kinds of neural training - - from "conventional" networks to early stopping ensembles. When used - for "conventional" networks, they are used as the only stopping - criteria. When combined with early stopping, they used as ADDITIONAL - stopping criteria which can terminate early stopping algorithm. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpsetcond(const mlptrainer &s, const double wstep, const ae_int_t maxits, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpsetcond(const_cast(s.c_ptr()), wstep, maxits, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets training algorithm: batch training using L-BFGS will be -used. - -This algorithm: -* the most robust for small-scale problems, but may be too slow for large - scale ones. -* perfoms full pass through the dataset before performing step -* uses conditions specified by MLPSetCond() for stopping -* is default one used by trainer object - -INPUT PARAMETERS: - S - trainer object - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpsetalgobatch(const mlptrainer &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpsetalgobatch(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function trains neural network passed to this function, using current -dataset (one which was passed to MLPSetDataset() or MLPSetSparseDataset()) -and current training settings. Training from NRestarts random starting -positions is performed, best network is chosen. - -Training is performed using current training algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - trainer object - Network - neural network. It must have same number of inputs and - output/classes as was specified during creation of the - trainer object. - NRestarts - number of restarts, >=0: - * NRestarts>0 means that specified number of random - restarts are performed, best network is chosen after - training - * NRestarts=0 means that current state of the network - is used for training. - -OUTPUT PARAMETERS: - Network - trained network - -NOTE: when no dataset was specified with MLPSetDataset/SetSparseDataset(), - network is filled by zero values. Same behavior for functions - MLPStartTraining and MLPContinueTraining. - -NOTE: this method uses sum-of-squares error function for training. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlptrainnetwork(const mlptrainer &s, const multilayerperceptron &network, const ae_int_t nrestarts, mlpreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlptrainnetwork(const_cast(s.c_ptr()), const_cast(network.c_ptr()), nrestarts, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -IMPORTANT: this is an "expert" version of the MLPTrain() function. We do - not recommend you to use it unless you are pretty sure that you - need ability to monitor training progress. - -This function performs step-by-step training of the neural network. Here -"step-by-step" means that training starts with MLPStartTraining() call, -and then user subsequently calls MLPContinueTraining() to perform one more -iteration of the training. - -After call to this function trainer object remembers network and is ready -to train it. However, no training is performed until first call to -MLPContinueTraining() function. Subsequent calls to MLPContinueTraining() -will advance training progress one iteration further. - -EXAMPLE: - > - > ...initialize network and trainer object.... - > - > MLPStartTraining(Trainer, Network, True) - > while MLPContinueTraining(Trainer, Network) do - > ...visualize training progress... - > - -INPUT PARAMETERS: - S - trainer object - Network - neural network. It must have same number of inputs and - output/classes as was specified during creation of the - trainer object. - RandomStart - randomize network before training or not: - * True means that network is randomized and its - initial state (one which was passed to the trainer - object) is lost. - * False means that training is started from the - current state of the network - -OUTPUT PARAMETERS: - Network - neural network which is ready to training (weights are - initialized, preprocessor is initialized using current - training set) - -NOTE: this method uses sum-of-squares error function for training. - -NOTE: it is expected that trainer object settings are NOT changed during - step-by-step training, i.e. no one changes stopping criteria or - training set during training. It is possible and there is no defense - against such actions, but algorithm behavior in such cases is - undefined and can be unpredictable. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpstarttraining(const mlptrainer &s, const multilayerperceptron &network, const bool randomstart, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpstarttraining(const_cast(s.c_ptr()), const_cast(network.c_ptr()), randomstart, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -IMPORTANT: this is an "expert" version of the MLPTrain() function. We do - not recommend you to use it unless you are pretty sure that you - need ability to monitor training progress. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -This function performs step-by-step training of the neural network. Here -"step-by-step" means that training starts with MLPStartTraining() call, -and then user subsequently calls MLPContinueTraining() to perform one more -iteration of the training. - -This function performs one more iteration of the training and returns -either True (training continues) or False (training stopped). In case True -was returned, Network weights are updated according to the current state -of the optimization progress. In case False was returned, no additional -updates is performed (previous update of the network weights moved us to -the final point, and no additional updates is needed). - -EXAMPLE: - > - > [initialize network and trainer object] - > - > MLPStartTraining(Trainer, Network, True) - > while MLPContinueTraining(Trainer, Network) do - > [visualize training progress] - > - -INPUT PARAMETERS: - S - trainer object - Network - neural network structure, which is used to store - current state of the training process. - -OUTPUT PARAMETERS: - Network - weights of the neural network are rewritten by the - current approximation. - -NOTE: this method uses sum-of-squares error function for training. - -NOTE: it is expected that trainer object settings are NOT changed during - step-by-step training, i.e. no one changes stopping criteria or - training set during training. It is possible and there is no defense - against such actions, but algorithm behavior in such cases is - undefined and can be unpredictable. - -NOTE: It is expected that Network is the same one which was passed to - MLPStartTraining() function. However, THIS function checks only - following: - * that number of network inputs is consistent with trainer object - settings - * that number of network outputs/classes is consistent with trainer - object settings - * that number of network weights is the same as number of weights in - the network passed to MLPStartTraining() function - Exception is thrown when these conditions are violated. - - It is also expected that you do not change state of the network on - your own - the only party who has right to change network during its - training is a trainer object. Any attempt to interfere with trainer - may lead to unpredictable results. - - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -bool mlpcontinuetraining(const mlptrainer &s, const multilayerperceptron &network, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::mlpcontinuetraining(const_cast(s.c_ptr()), const_cast(network.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Training neural networks ensemble using bootstrap aggregating (bagging). -Modified Levenberg-Marquardt algorithm is used as base training method. - -INPUT PARAMETERS: - Ensemble - model with initialized geometry - XY - training set - NPoints - training set size - Decay - weight decay coefficient, >=0.001 - Restarts - restarts, >0. - -OUTPUT PARAMETERS: - Ensemble - trained model - Info - return code: - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed - (NPoints<0, Restarts<1). - * 2, if task has been solved. - Rep - training report. - OOBErrors - out-of-bag generalization error estimate - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpebagginglm(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, ae_int_t &info, mlpreport &rep, mlpcvreport &ooberrors, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpebagginglm(const_cast(ensemble.c_ptr()), const_cast(xy.c_ptr()), npoints, decay, restarts, &info, const_cast(rep.c_ptr()), const_cast(ooberrors.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Training neural networks ensemble using bootstrap aggregating (bagging). -L-BFGS algorithm is used as base training method. - -INPUT PARAMETERS: - Ensemble - model with initialized geometry - XY - training set - NPoints - training set size - Decay - weight decay coefficient, >=0.001 - Restarts - restarts, >0. - WStep - stopping criterion, same as in MLPTrainLBFGS - MaxIts - stopping criterion, same as in MLPTrainLBFGS - -OUTPUT PARAMETERS: - Ensemble - trained model - Info - return code: - * -8, if both WStep=0 and MaxIts=0 - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed - (NPoints<0, Restarts<1). - * 2, if task has been solved. - Rep - training report. - OOBErrors - out-of-bag generalization error estimate - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpebagginglbfgs(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, const double wstep, const ae_int_t maxits, ae_int_t &info, mlpreport &rep, mlpcvreport &ooberrors, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpebagginglbfgs(const_cast(ensemble.c_ptr()), const_cast(xy.c_ptr()), npoints, decay, restarts, wstep, maxits, &info, const_cast(rep.c_ptr()), const_cast(ooberrors.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Training neural networks ensemble using early stopping. - -INPUT PARAMETERS: - Ensemble - model with initialized geometry - XY - training set - NPoints - training set size - Decay - weight decay coefficient, >=0.001 - Restarts - restarts, >0. - -OUTPUT PARAMETERS: - Ensemble - trained model - Info - return code: - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed - (NPoints<0, Restarts<1). - * 6, if task has been solved. - Rep - training report. - OOBErrors - out-of-bag generalization error estimate - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpetraines(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, ae_int_t &info, mlpreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlpetraines(const_cast(ensemble.c_ptr()), const_cast(xy.c_ptr()), npoints, decay, restarts, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function trains neural network ensemble passed to this function using -current dataset and early stopping training algorithm. Each early stopping -round performs NRestarts random restarts (thus, EnsembleSize*NRestarts -training rounds is performed in total). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - trainer object; - Ensemble - neural network ensemble. It must have same number of - inputs and outputs/classes as was specified during - creation of the trainer object. - NRestarts - number of restarts, >=0: - * NRestarts>0 means that specified number of random - restarts are performed during each ES round; - * NRestarts=0 is silently replaced by 1. - -OUTPUT PARAMETERS: - Ensemble - trained ensemble; - Rep - it contains all type of errors. - -NOTE: this training method uses BOTH early stopping and weight decay! So, - you should select weight decay before starting training just as you - select it before training "conventional" networks. - -NOTE: when no dataset was specified with MLPSetDataset/SetSparseDataset(), - or single-point dataset was passed, ensemble is filled by zero - values. - -NOTE: this method uses sum-of-squares error function for training. - - -- ALGLIB -- - Copyright 22.08.2012 by Bochkanov Sergey -*************************************************************************/ -void mlptrainensemblees(const mlptrainer &s, const mlpensemble &ensemble, const ae_int_t nrestarts, mlpreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mlptrainensemblees(const_cast(s.c_ptr()), const_cast(ensemble.c_ptr()), nrestarts, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_CLUSTERING) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This structure is a clusterization engine. - -You should not try to access its fields directly. -Use ALGLIB functions in order to work with this object. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -_clusterizerstate_owner::_clusterizerstate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_clusterizerstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::clusterizerstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::clusterizerstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::clusterizerstate)); - alglib_impl::_clusterizerstate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_clusterizerstate_owner::_clusterizerstate_owner(const _clusterizerstate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_clusterizerstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: clusterizerstate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::clusterizerstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::clusterizerstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::clusterizerstate)); - alglib_impl::_clusterizerstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_clusterizerstate_owner& _clusterizerstate_owner::operator=(const _clusterizerstate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: clusterizerstate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: clusterizerstate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_clusterizerstate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::clusterizerstate)); - alglib_impl::_clusterizerstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_clusterizerstate_owner::~_clusterizerstate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_clusterizerstate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::clusterizerstate* _clusterizerstate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::clusterizerstate* _clusterizerstate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -clusterizerstate::clusterizerstate() : _clusterizerstate_owner() -{ -} - -clusterizerstate::clusterizerstate(const clusterizerstate &rhs):_clusterizerstate_owner(rhs) -{ -} - -clusterizerstate& clusterizerstate::operator=(const clusterizerstate &rhs) -{ - if( this==&rhs ) - return *this; - _clusterizerstate_owner::operator=(rhs); - return *this; -} - -clusterizerstate::~clusterizerstate() -{ -} - - -/************************************************************************* -This structure is used to store results of the agglomerative hierarchical -clustering (AHC). - -Following information is returned: - -* TerminationType - completion code: - * 1 for successful completion of algorithm - * -5 inappropriate combination of clustering algorithm and distance - function was used. As for now, it is possible only when Ward's - method is called for dataset with non-Euclidean distance function. - In case negative completion code is returned, other fields of report - structure are invalid and should not be used. - -* NPoints contains number of points in the original dataset - -* Z contains information about merges performed (see below). Z contains - indexes from the original (unsorted) dataset and it can be used when you - need to know what points were merged. However, it is not convenient when - you want to build a dendrograd (see below). - -* if you want to build dendrogram, you can use Z, but it is not good - option, because Z contains indexes from unsorted dataset. Dendrogram - built from such dataset is likely to have intersections. So, you have to - reorder you points before building dendrogram. - Permutation which reorders point is returned in P. Another representation - of merges, which is more convenient for dendorgram construction, is - returned in PM. - -* more information on format of Z, P and PM can be found below and in the - examples from ALGLIB Reference Manual. - -FORMAL DESCRIPTION OF FIELDS: - NPoints number of points - Z array[NPoints-1,2], contains indexes of clusters - linked in pairs to form clustering tree. I-th row - corresponds to I-th merge: - * Z[I,0] - index of the first cluster to merge - * Z[I,1] - index of the second cluster to merge - * Z[I,0](rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_ahcreport_owner& _ahcreport_owner::operator=(const _ahcreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: ahcreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: ahcreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_ahcreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::ahcreport)); - alglib_impl::_ahcreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_ahcreport_owner::~_ahcreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_ahcreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::ahcreport* _ahcreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::ahcreport* _ahcreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -ahcreport::ahcreport() : _ahcreport_owner() ,terminationtype(p_struct->terminationtype),npoints(p_struct->npoints),p(&p_struct->p),z(&p_struct->z),pz(&p_struct->pz),pm(&p_struct->pm),mergedist(&p_struct->mergedist) -{ -} - -ahcreport::ahcreport(const ahcreport &rhs):_ahcreport_owner(rhs) ,terminationtype(p_struct->terminationtype),npoints(p_struct->npoints),p(&p_struct->p),z(&p_struct->z),pz(&p_struct->pz),pm(&p_struct->pm),mergedist(&p_struct->mergedist) -{ -} - -ahcreport& ahcreport::operator=(const ahcreport &rhs) -{ - if( this==&rhs ) - return *this; - _ahcreport_owner::operator=(rhs); - return *this; -} - -ahcreport::~ahcreport() -{ -} - - -/************************************************************************* -This structure is used to store results of the k-means clustering -algorithm. - -Following information is always returned: -* NPoints contains number of points in the original dataset -* TerminationType contains completion code, negative on failure, positive - on success -* K contains number of clusters - -For positive TerminationType we return: -* NFeatures contains number of variables in the original dataset -* C, which contains centers found by algorithm -* CIdx, which maps points of the original dataset to clusters - -FORMAL DESCRIPTION OF FIELDS: - NPoints number of points, >=0 - NFeatures number of variables, >=1 - TerminationType completion code: - * -5 if distance type is anything different from - Euclidean metric - * -3 for degenerate dataset: a) less than K distinct - points, b) K=0 for non-empty dataset. - * +1 for successful completion - K number of clusters - C array[K,NFeatures], rows of the array store centers - CIdx array[NPoints], which contains cluster indexes - IterationsCount actual number of iterations performed by clusterizer. - If algorithm performed more than one random restart, - total number of iterations is returned. - Energy merit function, "energy", sum of squared deviations - from cluster centers - - -- ALGLIB -- - Copyright 27.11.2012 by Bochkanov Sergey -*************************************************************************/ -_kmeansreport_owner::_kmeansreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_kmeansreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::kmeansreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::kmeansreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::kmeansreport)); - alglib_impl::_kmeansreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_kmeansreport_owner::_kmeansreport_owner(const _kmeansreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_kmeansreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: kmeansreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::kmeansreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::kmeansreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::kmeansreport)); - alglib_impl::_kmeansreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_kmeansreport_owner& _kmeansreport_owner::operator=(const _kmeansreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: kmeansreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: kmeansreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_kmeansreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::kmeansreport)); - alglib_impl::_kmeansreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_kmeansreport_owner::~_kmeansreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_kmeansreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::kmeansreport* _kmeansreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::kmeansreport* _kmeansreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -kmeansreport::kmeansreport() : _kmeansreport_owner() ,npoints(p_struct->npoints),nfeatures(p_struct->nfeatures),terminationtype(p_struct->terminationtype),iterationscount(p_struct->iterationscount),energy(p_struct->energy),k(p_struct->k),c(&p_struct->c),cidx(&p_struct->cidx) -{ -} - -kmeansreport::kmeansreport(const kmeansreport &rhs):_kmeansreport_owner(rhs) ,npoints(p_struct->npoints),nfeatures(p_struct->nfeatures),terminationtype(p_struct->terminationtype),iterationscount(p_struct->iterationscount),energy(p_struct->energy),k(p_struct->k),c(&p_struct->c),cidx(&p_struct->cidx) -{ -} - -kmeansreport& kmeansreport::operator=(const kmeansreport &rhs) -{ - if( this==&rhs ) - return *this; - _kmeansreport_owner::operator=(rhs); - return *this; -} - -kmeansreport::~kmeansreport() -{ -} - -/************************************************************************* -This function initializes clusterizer object. Newly initialized object is -empty, i.e. it does not contain dataset. You should use it as follows: -1. creation -2. dataset is added with ClusterizerSetPoints() -3. additional parameters are set -3. clusterization is performed with one of the clustering functions - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizercreate(clusterizerstate &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::clusterizercreate(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function adds dataset to the clusterizer structure. - -This function overrides all previous calls of ClusterizerSetPoints() or -ClusterizerSetDistances(). - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - XY - array[NPoints,NFeatures], dataset - NPoints - number of points, >=0 - NFeatures- number of features, >=1 - DistType- distance function: - * 0 Chebyshev distance (L-inf norm) - * 1 city block distance (L1 norm) - * 2 Euclidean distance (L2 norm), non-squared - * 10 Pearson correlation: - dist(a,b) = 1-corr(a,b) - * 11 Absolute Pearson correlation: - dist(a,b) = 1-|corr(a,b)| - * 12 Uncentered Pearson correlation (cosine of the angle): - dist(a,b) = a'*b/(|a|*|b|) - * 13 Absolute uncentered Pearson correlation - dist(a,b) = |a'*b|/(|a|*|b|) - * 20 Spearman rank correlation: - dist(a,b) = 1-rankcorr(a,b) - * 21 Absolute Spearman rank correlation - dist(a,b) = 1-|rankcorr(a,b)| - -NOTE 1: different distance functions have different performance penalty: - * Euclidean or Pearson correlation distances are the fastest ones - * Spearman correlation distance function is a bit slower - * city block and Chebyshev distances are order of magnitude slower - - The reason behing difference in performance is that correlation-based - distance functions are computed using optimized linear algebra kernels, - while Chebyshev and city block distance functions are computed using - simple nested loops with two branches at each iteration. - -NOTE 2: different clustering algorithms have different limitations: - * agglomerative hierarchical clustering algorithms may be used with - any kind of distance metric - * k-means++ clustering algorithm may be used only with Euclidean - distance function - Thus, list of specific clustering algorithms you may use depends - on distance function you specify when you set your dataset. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizersetpoints(const clusterizerstate &s, const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nfeatures, const ae_int_t disttype, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::clusterizersetpoints(const_cast(s.c_ptr()), const_cast(xy.c_ptr()), npoints, nfeatures, disttype, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function adds dataset to the clusterizer structure. - -This function overrides all previous calls of ClusterizerSetPoints() or -ClusterizerSetDistances(). - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - XY - array[NPoints,NFeatures], dataset - NPoints - number of points, >=0 - NFeatures- number of features, >=1 - DistType- distance function: - * 0 Chebyshev distance (L-inf norm) - * 1 city block distance (L1 norm) - * 2 Euclidean distance (L2 norm), non-squared - * 10 Pearson correlation: - dist(a,b) = 1-corr(a,b) - * 11 Absolute Pearson correlation: - dist(a,b) = 1-|corr(a,b)| - * 12 Uncentered Pearson correlation (cosine of the angle): - dist(a,b) = a'*b/(|a|*|b|) - * 13 Absolute uncentered Pearson correlation - dist(a,b) = |a'*b|/(|a|*|b|) - * 20 Spearman rank correlation: - dist(a,b) = 1-rankcorr(a,b) - * 21 Absolute Spearman rank correlation - dist(a,b) = 1-|rankcorr(a,b)| - -NOTE 1: different distance functions have different performance penalty: - * Euclidean or Pearson correlation distances are the fastest ones - * Spearman correlation distance function is a bit slower - * city block and Chebyshev distances are order of magnitude slower - - The reason behing difference in performance is that correlation-based - distance functions are computed using optimized linear algebra kernels, - while Chebyshev and city block distance functions are computed using - simple nested loops with two branches at each iteration. - -NOTE 2: different clustering algorithms have different limitations: - * agglomerative hierarchical clustering algorithms may be used with - any kind of distance metric - * k-means++ clustering algorithm may be used only with Euclidean - distance function - Thus, list of specific clustering algorithms you may use depends - on distance function you specify when you set your dataset. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void clusterizersetpoints(const clusterizerstate &s, const real_2d_array &xy, const ae_int_t disttype, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t npoints; - ae_int_t nfeatures; - - npoints = xy.rows(); - nfeatures = xy.cols(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::clusterizersetpoints(const_cast(s.c_ptr()), const_cast(xy.c_ptr()), npoints, nfeatures, disttype, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function adds dataset given by distance matrix to the clusterizer -structure. It is important that dataset is not given explicitly - only -distance matrix is given. - -This function overrides all previous calls of ClusterizerSetPoints() or -ClusterizerSetDistances(). - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - D - array[NPoints,NPoints], distance matrix given by its upper - or lower triangle (main diagonal is ignored because its - entries are expected to be zero). - NPoints - number of points - IsUpper - whether upper or lower triangle of D is given. - -NOTE 1: different clustering algorithms have different limitations: - * agglomerative hierarchical clustering algorithms may be used with - any kind of distance metric, including one which is given by - distance matrix - * k-means++ clustering algorithm may be used only with Euclidean - distance function and explicitly given points - it can not be - used with dataset given by distance matrix - Thus, if you call this function, you will be unable to use k-means - clustering algorithm to process your problem. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizersetdistances(const clusterizerstate &s, const real_2d_array &d, const ae_int_t npoints, const bool isupper, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::clusterizersetdistances(const_cast(s.c_ptr()), const_cast(d.c_ptr()), npoints, isupper, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function adds dataset given by distance matrix to the clusterizer -structure. It is important that dataset is not given explicitly - only -distance matrix is given. - -This function overrides all previous calls of ClusterizerSetPoints() or -ClusterizerSetDistances(). - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - D - array[NPoints,NPoints], distance matrix given by its upper - or lower triangle (main diagonal is ignored because its - entries are expected to be zero). - NPoints - number of points - IsUpper - whether upper or lower triangle of D is given. - -NOTE 1: different clustering algorithms have different limitations: - * agglomerative hierarchical clustering algorithms may be used with - any kind of distance metric, including one which is given by - distance matrix - * k-means++ clustering algorithm may be used only with Euclidean - distance function and explicitly given points - it can not be - used with dataset given by distance matrix - Thus, if you call this function, you will be unable to use k-means - clustering algorithm to process your problem. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void clusterizersetdistances(const clusterizerstate &s, const real_2d_array &d, const bool isupper, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t npoints; - if( (d.rows()!=d.cols())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'clusterizersetdistances': looks like one of arguments has wrong size"); - npoints = d.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::clusterizersetdistances(const_cast(s.c_ptr()), const_cast(d.c_ptr()), npoints, isupper, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets agglomerative hierarchical clustering algorithm - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - Algo - algorithm type: - * 0 complete linkage (default algorithm) - * 1 single linkage - * 2 unweighted average linkage - * 3 weighted average linkage - * 4 Ward's method - -NOTE: Ward's method works correctly only with Euclidean distance, that's - why algorithm will return negative termination code (failure) for - any other distance type. - - It is possible, however, to use this method with user-supplied - distance matrix. It is your responsibility to pass one which was - calculated with Euclidean distance function. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizersetahcalgo(const clusterizerstate &s, const ae_int_t algo, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::clusterizersetahcalgo(const_cast(s.c_ptr()), algo, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets k-means properties: number of restarts and maximum -number of iterations per one run. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - Restarts- restarts count, >=1. - k-means++ algorithm performs several restarts and chooses - best set of centers (one with minimum squared distance). - MaxIts - maximum number of k-means iterations performed during one - run. >=0, zero value means that algorithm performs unlimited - number of iterations. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizersetkmeanslimits(const clusterizerstate &s, const ae_int_t restarts, const ae_int_t maxits, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::clusterizersetkmeanslimits(const_cast(s.c_ptr()), restarts, maxits, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets k-means initialization algorithm. Several different -algorithms can be chosen, including k-means++. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - InitAlgo- initialization algorithm: - * 0 automatic selection ( different versions of ALGLIB - may select different algorithms) - * 1 random initialization - * 2 k-means++ initialization (best quality of initial - centers, but long non-parallelizable initialization - phase with bad cache locality) - * 3 "fast-greedy" algorithm with efficient, easy to - parallelize initialization. Quality of initial centers - is somewhat worse than that of k-means++. This - algorithm is a default one in the current version of - ALGLIB. - *-1 "debug" algorithm which always selects first K rows - of dataset; this algorithm is used for debug purposes - only. Do not use it in the industrial code! - - -- ALGLIB -- - Copyright 21.01.2015 by Bochkanov Sergey -*************************************************************************/ -void clusterizersetkmeansinit(const clusterizerstate &s, const ae_int_t initalgo, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::clusterizersetkmeansinit(const_cast(s.c_ptr()), initalgo, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets seed which is used to initialize internal RNG. By -default, deterministic seed is used - same for each run of clusterizer. If -you specify non-deterministic seed value, then some algorithms which -depend on random initialization (in current version: k-means) may return -slightly different results after each run. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - Seed - seed: - * positive values = use deterministic seed for each run of - algorithms which depend on random initialization - * zero or negative values = use non-deterministic seed - - -- ALGLIB -- - Copyright 08.06.2017 by Bochkanov Sergey -*************************************************************************/ -void clusterizersetseed(const clusterizerstate &s, const ae_int_t seed, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::clusterizersetseed(const_cast(s.c_ptr()), seed, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function performs agglomerative hierarchical clustering - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: Agglomerative hierarchical clustering algorithm has two phases: - distance matrix calculation and clustering itself. Only first phase - (distance matrix calculation) is accelerated by Intel MKL and - multithreading. Thus, acceleration is significant only for medium or - high-dimensional problems. - - Although activating multithreading gives some speedup over single- - threaded execution, you should not expect nearly-linear scaling - with respect to cores count. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - -OUTPUT PARAMETERS: - Rep - clustering results; see description of AHCReport - structure for more information. - -NOTE 1: hierarchical clustering algorithms require large amounts of memory. - In particular, this implementation needs sizeof(double)*NPoints^2 - bytes, which are used to store distance matrix. In case we work - with user-supplied matrix, this amount is multiplied by 2 (we have - to store original matrix and to work with its copy). - - For example, problem with 10000 points would require 800M of RAM, - even when working in a 1-dimensional space. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizerrunahc(const clusterizerstate &s, ahcreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::clusterizerrunahc(const_cast(s.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function performs clustering by k-means++ algorithm. - -You may change algorithm properties by calling: -* ClusterizerSetKMeansLimits() to change number of restarts or iterations -* ClusterizerSetKMeansInit() to change initialization algorithm - -By default, one restart and unlimited number of iterations are used. -Initialization algorithm is chosen automatically. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: k-means clustering algorithm has two phases: selection of initial - centers and clustering itself. ALGLIB parallelizes both phases. - Parallel version is optimized for the following scenario: medium or - high-dimensional problem (8 or more dimensions) with large number of - points and clusters. However, some speed-up can be obtained even - when assumptions above are violated. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - K - number of clusters, K>=0. - K can be zero only when algorithm is called for empty - dataset, in this case completion code is set to - success (+1). - If K=0 and dataset size is non-zero, we can not - meaningfully assign points to some center (there are no - centers because K=0) and return -3 as completion code - (failure). - -OUTPUT PARAMETERS: - Rep - clustering results; see description of KMeansReport - structure for more information. - -NOTE 1: k-means clustering can be performed only for datasets with - Euclidean distance function. Algorithm will return negative - completion code in Rep.TerminationType in case dataset was added - to clusterizer with DistType other than Euclidean (or dataset was - specified by distance matrix instead of explicitly given points). - -NOTE 2: by default, k-means uses non-deterministic seed to initialize RNG - which is used to select initial centers. As result, each run of - algorithm may return different values. If you need deterministic - behavior, use ClusterizerSetSeed() function. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizerrunkmeans(const clusterizerstate &s, const ae_int_t k, kmeansreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::clusterizerrunkmeans(const_cast(s.c_ptr()), k, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function returns distance matrix for dataset - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - array[NPoints,NFeatures], dataset - NPoints - number of points, >=0 - NFeatures- number of features, >=1 - DistType- distance function: - * 0 Chebyshev distance (L-inf norm) - * 1 city block distance (L1 norm) - * 2 Euclidean distance (L2 norm, non-squared) - * 10 Pearson correlation: - dist(a,b) = 1-corr(a,b) - * 11 Absolute Pearson correlation: - dist(a,b) = 1-|corr(a,b)| - * 12 Uncentered Pearson correlation (cosine of the angle): - dist(a,b) = a'*b/(|a|*|b|) - * 13 Absolute uncentered Pearson correlation - dist(a,b) = |a'*b|/(|a|*|b|) - * 20 Spearman rank correlation: - dist(a,b) = 1-rankcorr(a,b) - * 21 Absolute Spearman rank correlation - dist(a,b) = 1-|rankcorr(a,b)| - -OUTPUT PARAMETERS: - D - array[NPoints,NPoints], distance matrix - (full matrix is returned, with lower and upper triangles) - -NOTE: different distance functions have different performance penalty: - * Euclidean or Pearson correlation distances are the fastest ones - * Spearman correlation distance function is a bit slower - * city block and Chebyshev distances are order of magnitude slower - - The reason behing difference in performance is that correlation-based - distance functions are computed using optimized linear algebra kernels, - while Chebyshev and city block distance functions are computed using - simple nested loops with two branches at each iteration. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizergetdistances(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nfeatures, const ae_int_t disttype, real_2d_array &d, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::clusterizergetdistances(const_cast(xy.c_ptr()), npoints, nfeatures, disttype, const_cast(d.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function takes as input clusterization report Rep, desired clusters -count K, and builds top K clusters from hierarchical clusterization tree. -It returns assignment of points to clusters (array of cluster indexes). - -INPUT PARAMETERS: - Rep - report from ClusterizerRunAHC() performed on XY - K - desired number of clusters, 1<=K<=NPoints. - K can be zero only when NPoints=0. - -OUTPUT PARAMETERS: - CIdx - array[NPoints], I-th element contains cluster index (from - 0 to K-1) for I-th point of the dataset. - CZ - array[K]. This array allows to convert cluster indexes - returned by this function to indexes used by Rep.Z. J-th - cluster returned by this function corresponds to CZ[J]-th - cluster stored in Rep.Z/PZ/PM. - It is guaranteed that CZ[I](rep.c_ptr()), k, const_cast(cidx.c_ptr()), const_cast(cz.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function accepts AHC report Rep, desired minimum intercluster -distance and returns top clusters from hierarchical clusterization tree -which are separated by distance R or HIGHER. - -It returns assignment of points to clusters (array of cluster indexes). - -There is one more function with similar name - ClusterizerSeparatedByCorr, -which returns clusters with intercluster correlation equal to R or LOWER -(note: higher for distance, lower for correlation). - -INPUT PARAMETERS: - Rep - report from ClusterizerRunAHC() performed on XY - R - desired minimum intercluster distance, R>=0 - -OUTPUT PARAMETERS: - K - number of clusters, 1<=K<=NPoints - CIdx - array[NPoints], I-th element contains cluster index (from - 0 to K-1) for I-th point of the dataset. - CZ - array[K]. This array allows to convert cluster indexes - returned by this function to indexes used by Rep.Z. J-th - cluster returned by this function corresponds to CZ[J]-th - cluster stored in Rep.Z/PZ/PM. - It is guaranteed that CZ[I](rep.c_ptr()), r, &k, const_cast(cidx.c_ptr()), const_cast(cz.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function accepts AHC report Rep, desired maximum intercluster -correlation and returns top clusters from hierarchical clusterization tree -which are separated by correlation R or LOWER. - -It returns assignment of points to clusters (array of cluster indexes). - -There is one more function with similar name - ClusterizerSeparatedByDist, -which returns clusters with intercluster distance equal to R or HIGHER -(note: higher for distance, lower for correlation). - -INPUT PARAMETERS: - Rep - report from ClusterizerRunAHC() performed on XY - R - desired maximum intercluster correlation, -1<=R<=+1 - -OUTPUT PARAMETERS: - K - number of clusters, 1<=K<=NPoints - CIdx - array[NPoints], I-th element contains cluster index (from - 0 to K-1) for I-th point of the dataset. - CZ - array[K]. This array allows to convert cluster indexes - returned by this function to indexes used by Rep.Z. J-th - cluster returned by this function corresponds to CZ[J]-th - cluster stored in Rep.Z/PZ/PM. - It is guaranteed that CZ[I](rep.c_ptr()), r, &k, const_cast(cidx.c_ptr()), const_cast(cz.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_DFOREST) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -A random forest (decision forest) builder object. - -Used to store dataset and specify decision forest training algorithm settings. -*************************************************************************/ -_decisionforestbuilder_owner::_decisionforestbuilder_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_decisionforestbuilder_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::decisionforestbuilder*)alglib_impl::ae_malloc(sizeof(alglib_impl::decisionforestbuilder), &_state); - memset(p_struct, 0, sizeof(alglib_impl::decisionforestbuilder)); - alglib_impl::_decisionforestbuilder_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_decisionforestbuilder_owner::_decisionforestbuilder_owner(const _decisionforestbuilder_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_decisionforestbuilder_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: decisionforestbuilder copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::decisionforestbuilder*)alglib_impl::ae_malloc(sizeof(alglib_impl::decisionforestbuilder), &_state); - memset(p_struct, 0, sizeof(alglib_impl::decisionforestbuilder)); - alglib_impl::_decisionforestbuilder_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_decisionforestbuilder_owner& _decisionforestbuilder_owner::operator=(const _decisionforestbuilder_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: decisionforestbuilder assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: decisionforestbuilder assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_decisionforestbuilder_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::decisionforestbuilder)); - alglib_impl::_decisionforestbuilder_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_decisionforestbuilder_owner::~_decisionforestbuilder_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_decisionforestbuilder_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::decisionforestbuilder* _decisionforestbuilder_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::decisionforestbuilder* _decisionforestbuilder_owner::c_ptr() const -{ - return const_cast(p_struct); -} -decisionforestbuilder::decisionforestbuilder() : _decisionforestbuilder_owner() -{ -} - -decisionforestbuilder::decisionforestbuilder(const decisionforestbuilder &rhs):_decisionforestbuilder_owner(rhs) -{ -} - -decisionforestbuilder& decisionforestbuilder::operator=(const decisionforestbuilder &rhs) -{ - if( this==&rhs ) - return *this; - _decisionforestbuilder_owner::operator=(rhs); - return *this; -} - -decisionforestbuilder::~decisionforestbuilder() -{ -} - - -/************************************************************************* -Buffer object which is used to perform various requests (usually model -inference) in the multithreaded mode (multiple threads working with same -DF object). - -This object should be created with DFCreateBuffer(). -*************************************************************************/ -_decisionforestbuffer_owner::_decisionforestbuffer_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_decisionforestbuffer_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::decisionforestbuffer*)alglib_impl::ae_malloc(sizeof(alglib_impl::decisionforestbuffer), &_state); - memset(p_struct, 0, sizeof(alglib_impl::decisionforestbuffer)); - alglib_impl::_decisionforestbuffer_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_decisionforestbuffer_owner::_decisionforestbuffer_owner(const _decisionforestbuffer_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_decisionforestbuffer_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: decisionforestbuffer copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::decisionforestbuffer*)alglib_impl::ae_malloc(sizeof(alglib_impl::decisionforestbuffer), &_state); - memset(p_struct, 0, sizeof(alglib_impl::decisionforestbuffer)); - alglib_impl::_decisionforestbuffer_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_decisionforestbuffer_owner& _decisionforestbuffer_owner::operator=(const _decisionforestbuffer_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: decisionforestbuffer assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: decisionforestbuffer assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_decisionforestbuffer_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::decisionforestbuffer)); - alglib_impl::_decisionforestbuffer_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_decisionforestbuffer_owner::~_decisionforestbuffer_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_decisionforestbuffer_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::decisionforestbuffer* _decisionforestbuffer_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::decisionforestbuffer* _decisionforestbuffer_owner::c_ptr() const -{ - return const_cast(p_struct); -} -decisionforestbuffer::decisionforestbuffer() : _decisionforestbuffer_owner() -{ -} - -decisionforestbuffer::decisionforestbuffer(const decisionforestbuffer &rhs):_decisionforestbuffer_owner(rhs) -{ -} - -decisionforestbuffer& decisionforestbuffer::operator=(const decisionforestbuffer &rhs) -{ - if( this==&rhs ) - return *this; - _decisionforestbuffer_owner::operator=(rhs); - return *this; -} - -decisionforestbuffer::~decisionforestbuffer() -{ -} - - -/************************************************************************* -Decision forest (random forest) model. -*************************************************************************/ -_decisionforest_owner::_decisionforest_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_decisionforest_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::decisionforest*)alglib_impl::ae_malloc(sizeof(alglib_impl::decisionforest), &_state); - memset(p_struct, 0, sizeof(alglib_impl::decisionforest)); - alglib_impl::_decisionforest_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_decisionforest_owner::_decisionforest_owner(const _decisionforest_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_decisionforest_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: decisionforest copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::decisionforest*)alglib_impl::ae_malloc(sizeof(alglib_impl::decisionforest), &_state); - memset(p_struct, 0, sizeof(alglib_impl::decisionforest)); - alglib_impl::_decisionforest_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_decisionforest_owner& _decisionforest_owner::operator=(const _decisionforest_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: decisionforest assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: decisionforest assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_decisionforest_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::decisionforest)); - alglib_impl::_decisionforest_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_decisionforest_owner::~_decisionforest_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_decisionforest_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::decisionforest* _decisionforest_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::decisionforest* _decisionforest_owner::c_ptr() const -{ - return const_cast(p_struct); -} -decisionforest::decisionforest() : _decisionforest_owner() -{ -} - -decisionforest::decisionforest(const decisionforest &rhs):_decisionforest_owner(rhs) -{ -} - -decisionforest& decisionforest::operator=(const decisionforest &rhs) -{ - if( this==&rhs ) - return *this; - _decisionforest_owner::operator=(rhs); - return *this; -} - -decisionforest::~decisionforest() -{ -} - - -/************************************************************************* -Decision forest training report. - -=== training/oob errors ================================================== - -Following fields store training set errors: -* relclserror - fraction of misclassified cases, [0,1] -* avgce - average cross-entropy in bits per symbol -* rmserror - root-mean-square error -* avgerror - average error -* avgrelerror - average relative error - -Out-of-bag estimates are stored in fields with same names, but "oob" prefix. - -For classification problems: -* RMS, AVG and AVGREL errors are calculated for posterior probabilities - -For regression problems: -* RELCLS and AVGCE errors are zero - -=== variable importance ================================================== - -Following fields are used to store variable importance information: - -* topvars - variables ordered from the most important to - less important ones (according to current - choice of importance raiting). - For example, topvars[0] contains index of the - most important variable, and topvars[0:2] are - indexes of 3 most important ones and so on. - -* varimportances - array[nvars], ratings (the larger, the more - important the variable is, always in [0,1] - range). - By default, filled by zeros (no importance - ratings are provided unless you explicitly - request them). - Zero rating means that variable is not important, - however you will rarely encounter such a thing, - in many cases unimportant variables produce - nearly-zero (but nonzero) ratings. - -Variable importance report must be EXPLICITLY requested by calling: -* dfbuildersetimportancegini() function, if you need out-of-bag Gini-based - importance rating also known as MDI (fast to calculate, resistant to - overfitting issues, but has some bias towards continuous and - high-cardinality categorical variables) -* dfbuildersetimportancetrngini() function, if you need training set Gini- - -based importance rating (what other packages typically report). -* dfbuildersetimportancepermutation() function, if you need permutation- - based importance rating also known as MDA (slower to calculate, but less - biased) -* dfbuildersetimportancenone() function, if you do not need importance - ratings - ratings will be zero, topvars[] will be [0,1,2,...] - -Different importance ratings (Gini or permutation) produce non-comparable -values. Although in all cases rating values lie in [0,1] range, there are -exist differences: -* informally speaking, Gini importance rating tends to divide "unit amount - of importance" between several important variables, i.e. it produces - estimates which roughly sum to 1.0 (or less than 1.0, if your task can - not be solved exactly). If all variables are equally important, they - will have same rating, roughly 1/NVars, even if every variable is - critically important. -* from the other side, permutation importance tells us what percentage of - the model predictive power will be ruined by permuting this specific - variable. It does not produce estimates which sum to one. Critically - important variable will have rating close to 1.0, and you may have - multiple variables with such a rating. - -More information on variable importance ratings can be found in comments -on the dfbuildersetimportancegini() and dfbuildersetimportancepermutation() -functions. -*************************************************************************/ -_dfreport_owner::_dfreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_dfreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::dfreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::dfreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::dfreport)); - alglib_impl::_dfreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_dfreport_owner::_dfreport_owner(const _dfreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_dfreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: dfreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::dfreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::dfreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::dfreport)); - alglib_impl::_dfreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_dfreport_owner& _dfreport_owner::operator=(const _dfreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: dfreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: dfreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_dfreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::dfreport)); - alglib_impl::_dfreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_dfreport_owner::~_dfreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_dfreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::dfreport* _dfreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::dfreport* _dfreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -dfreport::dfreport() : _dfreport_owner() ,relclserror(p_struct->relclserror),avgce(p_struct->avgce),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),oobrelclserror(p_struct->oobrelclserror),oobavgce(p_struct->oobavgce),oobrmserror(p_struct->oobrmserror),oobavgerror(p_struct->oobavgerror),oobavgrelerror(p_struct->oobavgrelerror),topvars(&p_struct->topvars),varimportances(&p_struct->varimportances) -{ -} - -dfreport::dfreport(const dfreport &rhs):_dfreport_owner(rhs) ,relclserror(p_struct->relclserror),avgce(p_struct->avgce),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),oobrelclserror(p_struct->oobrelclserror),oobavgce(p_struct->oobavgce),oobrmserror(p_struct->oobrmserror),oobavgerror(p_struct->oobavgerror),oobavgrelerror(p_struct->oobavgrelerror),topvars(&p_struct->topvars),varimportances(&p_struct->varimportances) -{ -} - -dfreport& dfreport::operator=(const dfreport &rhs) -{ - if( this==&rhs ) - return *this; - _dfreport_owner::operator=(rhs); - return *this; -} - -dfreport::~dfreport() -{ -} - - -/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -void dfserialize(decisionforest &obj, std::string &s_out) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - alglib_impl::ae_int_t ssize; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_alloc_start(&serializer); - alglib_impl::dfalloc(&serializer, obj.c_ptr(), &state); - ssize = alglib_impl::ae_serializer_get_alloc_size(&serializer); - s_out.clear(); - s_out.reserve((size_t)(ssize+1)); - alglib_impl::ae_serializer_sstart_str(&serializer, &s_out); - alglib_impl::dfserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_assert( s_out.length()<=(size_t)ssize, "ALGLIB: serialization integrity error", &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} -/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -void dfunserialize(const std::string &s_in, decisionforest &obj) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_ustart_str(&serializer, &s_in); - alglib_impl::dfunserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} - - -/************************************************************************* -This function serializes data structure to C++ stream. - -Data stream generated by this function is same as string representation -generated by string version of serializer - alphanumeric characters, -dots, underscores, minus signs, which are grouped into words separated by -spaces and CR+LF. - -We recommend you to read comments on string version of serializer to find -out more about serialization of AlGLIB objects. -*************************************************************************/ -void dfserialize(decisionforest &obj, std::ostream &s_out) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_alloc_start(&serializer); - alglib_impl::dfalloc(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_get_alloc_size(&serializer); // not actually needed, but we have to ask - alglib_impl::ae_serializer_sstart_stream(&serializer, &s_out); - alglib_impl::dfserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} -/************************************************************************* -This function unserializes data structure from stream. -*************************************************************************/ -void dfunserialize(const std::istream &s_in, decisionforest &obj) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_ustart_stream(&serializer, &s_in); - alglib_impl::dfunserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} - -/************************************************************************* -This function creates buffer structure which can be used to perform -parallel inference requests. - -DF subpackage provides two sets of computing functions - ones which use -internal buffer of DF model (these functions are single-threaded because -they use same buffer, which can not shared between threads), and ones -which use external buffer. - -This function is used to initialize external buffer. - -INPUT PARAMETERS - Model - DF model which is associated with newly created buffer - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: buffer object should be used only with model which was used to - initialize buffer. Any attempt to use buffer with different - object is dangerous - you may get integrity check failure - (exception) because sizes of internal arrays do not fit to - dimensions of the model structure. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void dfcreatebuffer(const decisionforest &model, decisionforestbuffer &buf, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dfcreatebuffer(const_cast(model.c_ptr()), const_cast(buf.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine creates DecisionForestBuilder object which is used to -train decision forests. - -By default, new builder stores empty dataset and some reasonable default -settings. At the very least, you should specify dataset prior to building -decision forest. You can also tweak settings of the forest construction -algorithm (recommended, although default setting should work well). - -Following actions are mandatory: -* calling dfbuildersetdataset() to specify dataset -* calling dfbuilderbuildrandomforest() to build decision forest using - current dataset and default settings - -Additionally, you may call: -* dfbuildersetrndvars() or dfbuildersetrndvarsratio() to specify number of - variables randomly chosen for each split -* dfbuildersetsubsampleratio() to specify fraction of the dataset randomly - subsampled to build each tree -* dfbuildersetseed() to control random seed chosen for tree construction - -INPUT PARAMETERS: - none - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildercreate(decisionforestbuilder &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dfbuildercreate(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine adds dense dataset to the internal storage of the builder -object. Specifying your dataset in the dense format means that the dense -version of the forest construction algorithm will be invoked. - -INPUT PARAMETERS: - S - decision forest builder object - XY - array[NPoints,NVars+1] (minimum size; actual size can - be larger, only leading part is used anyway), dataset: - * first NVars elements of each row store values of the - independent variables - * last column store class number (in 0...NClasses-1) - or real value of the dependent variable - NPoints - number of rows in the dataset, NPoints>=1 - NVars - number of independent variables, NVars>=1 - NClasses - indicates type of the problem being solved: - * NClasses>=2 means that classification problem is - solved (last column of the dataset stores class - number) - * NClasses=1 means that regression problem is solved - (last column of the dataset stores variable value) - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetdataset(const decisionforestbuilder &s, const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dfbuildersetdataset(const_cast(s.c_ptr()), const_cast(xy.c_ptr()), npoints, nvars, nclasses, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets number of variables (in [1,NVars] range) used by -decision forest construction algorithm. - -The default option is to use roughly sqrt(NVars) variables. - -INPUT PARAMETERS: - S - decision forest builder object - RndVars - number of randomly selected variables; values outside - of [1,NVars] range are silently clipped. - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetrndvars(const decisionforestbuilder &s, const ae_int_t rndvars, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dfbuildersetrndvars(const_cast(s.c_ptr()), rndvars, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets number of variables used by decision forest construction -algorithm as a fraction of total variable count (0,1) range. - -The default option is to use roughly sqrt(NVars) variables. - -INPUT PARAMETERS: - S - decision forest builder object - F - round(NVars*F) variables are selected - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetrndvarsratio(const decisionforestbuilder &s, const double f, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dfbuildersetrndvarsratio(const_cast(s.c_ptr()), f, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function tells decision forest builder to automatically choose number -of variables used by decision forest construction algorithm. Roughly -sqrt(NVars) variables will be used. - -INPUT PARAMETERS: - S - decision forest builder object - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetrndvarsauto(const decisionforestbuilder &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dfbuildersetrndvarsauto(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets size of dataset subsample generated the decision forest -construction algorithm. Size is specified as a fraction of total dataset -size. - -The default option is to use 50% of the dataset for training, 50% for the -OOB estimates. You can decrease fraction F down to 10%, 1% or even below -in order to reduce overfitting. - -INPUT PARAMETERS: - S - decision forest builder object - F - fraction of the dataset to use, in (0,1] range. Values - outside of this range will be silently clipped. At - least one element is always selected for the training - set. - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetsubsampleratio(const decisionforestbuilder &s, const double f, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dfbuildersetsubsampleratio(const_cast(s.c_ptr()), f, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets seed used by internal RNG for random subsampling and -random selection of variable subsets. - -By default random seed is used, i.e. every time you build decision forest, -we seed generator with new value obtained from system-wide RNG. Thus, -decision forest builder returns non-deterministic results. You can change -such behavior by specyfing fixed positive seed value. - -INPUT PARAMETERS: - S - decision forest builder object - SeedVal - seed value: - * positive values are used for seeding RNG with fixed - seed, i.e. subsequent runs on same data will return - same decision forests - * non-positive seed means that random seed is used - for every run of builder, i.e. subsequent runs on - same datasets will return slightly different - decision forests - -OUTPUT PARAMETERS: - S - decision forest builder, see - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetseed(const decisionforestbuilder &s, const ae_int_t seedval, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dfbuildersetseed(const_cast(s.c_ptr()), seedval, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets random decision forest construction algorithm. - -As for now, only one decision forest construction algorithm is supported - -a dense "baseline" RDF algorithm. - -INPUT PARAMETERS: - S - decision forest builder object - AlgoType - algorithm type: - * 0 = baseline dense RDF - -OUTPUT PARAMETERS: - S - decision forest builder, see - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetrdfalgo(const decisionforestbuilder &s, const ae_int_t algotype, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dfbuildersetrdfalgo(const_cast(s.c_ptr()), algotype, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets split selection algorithm used by decision forest -classifier. You may choose several algorithms, with different speed and -quality of the results. - -INPUT PARAMETERS: - S - decision forest builder object - SplitStrength- split type: - * 0 = split at the random position, fastest one - * 1 = split at the middle of the range - * 2 = strong split at the best point of the range (default) - -OUTPUT PARAMETERS: - S - decision forest builder, see - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetrdfsplitstrength(const decisionforestbuilder &s, const ae_int_t splitstrength, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dfbuildersetrdfsplitstrength(const_cast(s.c_ptr()), splitstrength, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function tells decision forest construction algorithm to use -Gini impurity based variable importance estimation (also known as MDI). - -This version of importance estimation algorithm analyzes mean decrease in -impurity (MDI) on training sample during splits. The result is divided -by impurity at the root node in order to produce estimate in [0,1] range. - -Such estimates are fast to calculate and beautifully normalized (sum to -one) but have following downsides: -* They ALWAYS sum to 1.0, even if output is completely unpredictable. I.e. - MDI allows to order variables by importance, but does not tell us about - "absolute" importances of variables -* there exist some bias towards continuous and high-cardinality categorical - variables - -NOTE: informally speaking, MDA (permutation importance) rating answers the - question "what part of the model predictive power is ruined by - permuting k-th variable?" while MDI tells us "what part of the model - predictive power was achieved due to usage of k-th variable". - - Thus, MDA rates each variable independently at "0 to 1" scale while - MDI (and OOB-MDI too) tends to divide "unit amount of importance" - between several important variables. - - If all variables are equally important, they will have same - MDI/OOB-MDI rating, equal (for OOB-MDI: roughly equal) to 1/NVars. - However, roughly same picture will be produced for the "all - variables provide information no one is critical" situation and for - the "all variables are critical, drop any one, everything is ruined" - situation. - - Contrary to that, MDA will rate critical variable as ~1.0 important, - and important but non-critical variable will have less than unit - rating. - -NOTE: quite an often MDA and MDI return same results. It generally happens - on problems with low test set error (a few percents at most) and - large enough training set to avoid overfitting. - - The difference between MDA, MDI and OOB-MDI becomes important only - on "hard" tasks with high test set error and/or small training set. - -INPUT PARAMETERS: - S - decision forest builder object - -OUTPUT PARAMETERS: - S - decision forest builder object. Next call to the forest - construction function will produce: - * importance estimates in rep.varimportances field - * variable ranks in rep.topvars field - - -- ALGLIB -- - Copyright 29.07.2019 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetimportancetrngini(const decisionforestbuilder &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dfbuildersetimportancetrngini(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function tells decision forest construction algorithm to use -out-of-bag version of Gini variable importance estimation (also known as -OOB-MDI). - -This version of importance estimation algorithm analyzes mean decrease in -impurity (MDI) on out-of-bag sample during splits. The result is divided -by impurity at the root node in order to produce estimate in [0,1] range. - -Such estimates are fast to calculate and resistant to overfitting issues -(thanks to the out-of-bag estimates used). However, OOB Gini rating has -following downsides: -* there exist some bias towards continuous and high-cardinality categorical - variables -* Gini rating allows us to order variables by importance, but it is hard - to define importance of the variable by itself. - -NOTE: informally speaking, MDA (permutation importance) rating answers the - question "what part of the model predictive power is ruined by - permuting k-th variable?" while MDI tells us "what part of the model - predictive power was achieved due to usage of k-th variable". - - Thus, MDA rates each variable independently at "0 to 1" scale while - MDI (and OOB-MDI too) tends to divide "unit amount of importance" - between several important variables. - - If all variables are equally important, they will have same - MDI/OOB-MDI rating, equal (for OOB-MDI: roughly equal) to 1/NVars. - However, roughly same picture will be produced for the "all - variables provide information no one is critical" situation and for - the "all variables are critical, drop any one, everything is ruined" - situation. - - Contrary to that, MDA will rate critical variable as ~1.0 important, - and important but non-critical variable will have less than unit - rating. - -NOTE: quite an often MDA and MDI return same results. It generally happens - on problems with low test set error (a few percents at most) and - large enough training set to avoid overfitting. - - The difference between MDA, MDI and OOB-MDI becomes important only - on "hard" tasks with high test set error and/or small training set. - -INPUT PARAMETERS: - S - decision forest builder object - -OUTPUT PARAMETERS: - S - decision forest builder object. Next call to the forest - construction function will produce: - * importance estimates in rep.varimportances field - * variable ranks in rep.topvars field - - -- ALGLIB -- - Copyright 29.07.2019 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetimportanceoobgini(const decisionforestbuilder &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dfbuildersetimportanceoobgini(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function tells decision forest construction algorithm to use -permutation variable importance estimator (also known as MDA). - -This version of importance estimation algorithm analyzes mean increase in -out-of-bag sum of squared residuals after random permutation of J-th -variable. The result is divided by error computed with all variables being -perturbed in order to produce R-squared-like estimate in [0,1] range. - -Such estimate is slower to calculate than Gini-based rating because it -needs multiple inference runs for each of variables being studied. - -ALGLIB uses parallelized and highly optimized algorithm which analyzes -path through the decision tree and allows to handle most perturbations -in O(1) time; nevertheless, requesting MDA importances may increase forest -construction time from 10% to 200% (or more, if you have thousands of -variables). - -However, MDA rating has following benefits over Gini-based ones: -* no bias towards specific variable types -* ability to directly evaluate "absolute" importance of some variable at - "0 to 1" scale (contrary to Gini-based rating, which returns comparative - importances). - -NOTE: informally speaking, MDA (permutation importance) rating answers the - question "what part of the model predictive power is ruined by - permuting k-th variable?" while MDI tells us "what part of the model - predictive power was achieved due to usage of k-th variable". - - Thus, MDA rates each variable independently at "0 to 1" scale while - MDI (and OOB-MDI too) tends to divide "unit amount of importance" - between several important variables. - - If all variables are equally important, they will have same - MDI/OOB-MDI rating, equal (for OOB-MDI: roughly equal) to 1/NVars. - However, roughly same picture will be produced for the "all - variables provide information no one is critical" situation and for - the "all variables are critical, drop any one, everything is ruined" - situation. - - Contrary to that, MDA will rate critical variable as ~1.0 important, - and important but non-critical variable will have less than unit - rating. - -NOTE: quite an often MDA and MDI return same results. It generally happens - on problems with low test set error (a few percents at most) and - large enough training set to avoid overfitting. - - The difference between MDA, MDI and OOB-MDI becomes important only - on "hard" tasks with high test set error and/or small training set. - -INPUT PARAMETERS: - S - decision forest builder object - -OUTPUT PARAMETERS: - S - decision forest builder object. Next call to the forest - construction function will produce: - * importance estimates in rep.varimportances field - * variable ranks in rep.topvars field - - -- ALGLIB -- - Copyright 29.07.2019 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetimportancepermutation(const decisionforestbuilder &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dfbuildersetimportancepermutation(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function tells decision forest construction algorithm to skip -variable importance estimation. - -INPUT PARAMETERS: - S - decision forest builder object - -OUTPUT PARAMETERS: - S - decision forest builder object. Next call to the forest - construction function will result in forest being built - without variable importance estimation. - - -- ALGLIB -- - Copyright 29.07.2019 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetimportancenone(const decisionforestbuilder &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dfbuildersetimportancenone(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is an alias for dfbuilderpeekprogress(), left in ALGLIB for -backward compatibility reasons. - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -double dfbuildergetprogress(const decisionforestbuilder &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::dfbuildergetprogress(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function is used to peek into decision forest construction process -from some other thread and get current progress indicator. - -It returns value in [0,1]. - -INPUT PARAMETERS: - S - decision forest builder object used to build forest - in some other thread - -RESULT: - progress value, in [0,1] - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -double dfbuilderpeekprogress(const decisionforestbuilder &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::dfbuilderpeekprogress(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This subroutine builds decision forest according to current settings using -dataset internally stored in the builder object. Dense algorithm is used. - -NOTE: this function uses dense algorithm for forest construction - independently from the dataset format (dense or sparse). - -NOTE: forest built with this function is stored in-memory using 64-bit - data structures for offsets/indexes/split values. It is possible to - convert forest into more memory-efficient compressed binary - representation. Depending on the problem properties, 3.7x-5.7x - compression factors are possible. - - The downsides of compression are (a) slight reduction in the model - accuracy and (b) ~1.5x reduction in the inference speed (due to - increased complexity of the storage format). - - See comments on dfbinarycompression() for more info. - -Default settings are used by the algorithm; you can tweak them with the -help of the following functions: -* dfbuildersetrfactor() - to control a fraction of the dataset used for - subsampling -* dfbuildersetrandomvars() - to control number of variables randomly chosen - for decision rule creation - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - decision forest builder object - NTrees - NTrees>=1, number of trees to train - -OUTPUT PARAMETERS: - DF - decision forest. You can compress this forest to more - compact 16-bit representation with dfbinarycompression() - Rep - report, see below for information on its fields. - -=== report information produced by forest construction function ========== - -Decision forest training report includes following information: -* training set errors -* out-of-bag estimates of errors -* variable importance ratings - -Following fields are used to store information: -* training set errors are stored in rep.relclserror, rep.avgce, rep.rmserror, - rep.avgerror and rep.avgrelerror -* out-of-bag estimates of errors are stored in rep.oobrelclserror, rep.oobavgce, - rep.oobrmserror, rep.oobavgerror and rep.oobavgrelerror - -Variable importance reports, if requested by dfbuildersetimportancegini(), -dfbuildersetimportancetrngini() or dfbuildersetimportancepermutation() -call, are stored in: -* rep.varimportances field stores importance ratings -* rep.topvars stores variable indexes ordered from the most important to - less important ones - -You can find more information about report fields in: -* comments on dfreport structure -* comments on dfbuildersetimportancegini function -* comments on dfbuildersetimportancetrngini function -* comments on dfbuildersetimportancepermutation function - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuilderbuildrandomforest(const decisionforestbuilder &s, const ae_int_t ntrees, decisionforest &df, dfreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dfbuilderbuildrandomforest(const_cast(s.c_ptr()), ntrees, const_cast(df.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function performs binary compression of the decision forest. - -Original decision forest produced by the forest builder is stored using -64-bit representation for all numbers - offsets, variable indexes, split -points. - -It is possible to significantly reduce model size by means of: -* using compressed dynamic encoding for integers (offsets and variable - indexes), which uses just 1 byte to store small ints (less than 128), - just 2 bytes for larger values (less than 128^2) and so on -* storing floating point numbers using 8-bit exponent and 16-bit mantissa - -As result, model needs significantly less memory (compression factor -depends on variable and class counts). In particular: -* NVars<128 and NClasses<128 result in 4.4x-5.7x model size reduction -* NVars<16384 and NClasses<128 result in 3.7x-4.5x model size reduction - -Such storage format performs lossless compression of all integers, but -compression of floating point values (split values) is lossy, with roughly -0.01% relative error introduced during rounding. Thus, we recommend you to -re-evaluate model accuracy after compression. - -Another downside of compression is ~1.5x reduction in the inference -speed due to necessity of dynamic decompression of the compressed model. - -INPUT PARAMETERS: - DF - decision forest built by forest builder - -OUTPUT PARAMETERS: - DF - replaced by compressed forest - -RESULT: - compression factor (in-RAM size of the compressed model vs than of the - uncompressed one), positive number larger than 1.0 - - -- ALGLIB -- - Copyright 22.07.2019 by Bochkanov Sergey -*************************************************************************/ -double dfbinarycompression(const decisionforest &df, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::dfbinarycompression(const_cast(df.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Inference using decision forest - -IMPORTANT: this function is thread-unsafe and may modify internal - structures of the model! You can not use same model object for - parallel evaluation from several threads. - - Use dftsprocess() with independent thread-local buffers if - you need thread-safe evaluation. - -INPUT PARAMETERS: - DF - decision forest model - X - input vector, array[NVars] - Y - possibly preallocated buffer, reallocated if too small - -OUTPUT PARAMETERS: - Y - result. Regression estimate when solving regression task, - vector of posterior probabilities for classification task. - -See also DFProcessI. - - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -void dfprocess(const decisionforest &df, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dfprocess(const_cast(df.c_ptr()), const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -'interactive' variant of DFProcess for languages like Python which support -constructs like "Y = DFProcessI(DF,X)" and interactive mode of interpreter - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - -IMPORTANT: this function is thread-unsafe and may modify internal - structures of the model! You can not use same model object for - parallel evaluation from several threads. - - Use dftsprocess() with independent thread-local buffers if - you need thread-safe evaluation. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void dfprocessi(const decisionforest &df, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dfprocessi(const_cast(df.c_ptr()), const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function returns first component of the inferred vector (i.e. one -with index #0). - -It is a convenience wrapper for dfprocess() intended for either: -* 1-dimensional regression problems -* 2-class classification problems - -In the former case this function returns inference result as scalar, which -is definitely more convenient that wrapping it as vector. In the latter -case it returns probability of object belonging to class #0. - -If you call it for anything different from two cases above, it will work -as defined, i.e. return y[0], although it is of less use in such cases. - -IMPORTANT: this function is thread-unsafe and modifies internal structures - of the model! You can not use same model object for parallel - evaluation from several threads. - - Use dftsprocess() with independent thread-local buffers, if - you need thread-safe evaluation. - -INPUT PARAMETERS: - Model - DF model - X - input vector, array[0..NVars-1]. - -RESULT: - Y[0] - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double dfprocess0(const decisionforest &model, const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::dfprocess0(const_cast(model.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function returns most probable class number for an input X. It is -same as calling dfprocess(model,x,y), then determining i=argmax(y[i]) and -returning i. - -A class number in [0,NOut) range in returned for classification problems, --1 is returned when this function is called for regression problems. - -IMPORTANT: this function is thread-unsafe and modifies internal structures - of the model! You can not use same model object for parallel - evaluation from several threads. - - Use dftsprocess() with independent thread-local buffers, if - you need thread-safe evaluation. - -INPUT PARAMETERS: - Model - decision forest model - X - input vector, array[0..NVars-1]. - -RESULT: - class number, -1 for regression tasks - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -ae_int_t dfclassify(const decisionforest &model, const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::dfclassify(const_cast(model.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Inference using decision forest - -Thread-safe procesing using external buffer for temporaries. - -This function is thread-safe (i.e . you can use same DF model from -multiple threads) as long as you use different buffer objects for different -threads. - -INPUT PARAMETERS: - DF - decision forest model - Buf - buffer object, must be allocated specifically for this - model with dfcreatebuffer(). - X - input vector, array[NVars] - Y - possibly preallocated buffer, reallocated if too small - -OUTPUT PARAMETERS: - Y - result. Regression estimate when solving regression task, - vector of posterior probabilities for classification task. - -See also DFProcessI. - - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -void dftsprocess(const decisionforest &df, const decisionforestbuffer &buf, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dftsprocess(const_cast(df.c_ptr()), const_cast(buf.c_ptr()), const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Relative classification error on the test set - -INPUT PARAMETERS: - DF - decision forest model - XY - test set - NPoints - test set size - -RESULT: - percent of incorrectly classified cases. - Zero if model solves regression task. - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -double dfrelclserror(const decisionforest &df, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::dfrelclserror(const_cast(df.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Average cross-entropy (in bits per element) on the test set - -INPUT PARAMETERS: - DF - decision forest model - XY - test set - NPoints - test set size - -RESULT: - CrossEntropy/(NPoints*LN(2)). - Zero if model solves regression task. - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -double dfavgce(const decisionforest &df, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::dfavgce(const_cast(df.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -RMS error on the test set - -INPUT PARAMETERS: - DF - decision forest model - XY - test set - NPoints - test set size - -RESULT: - root mean square error. - Its meaning for regression task is obvious. As for - classification task, RMS error means error when estimating posterior - probabilities. - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -double dfrmserror(const decisionforest &df, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::dfrmserror(const_cast(df.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Average error on the test set - -INPUT PARAMETERS: - DF - decision forest model - XY - test set - NPoints - test set size - -RESULT: - Its meaning for regression task is obvious. As for - classification task, it means average error when estimating posterior - probabilities. - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -double dfavgerror(const decisionforest &df, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::dfavgerror(const_cast(df.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Average relative error on the test set - -INPUT PARAMETERS: - DF - decision forest model - XY - test set - NPoints - test set size - -RESULT: - Its meaning for regression task is obvious. As for - classification task, it means average relative error when estimating - posterior probability of belonging to the correct class. - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -double dfavgrelerror(const decisionforest &df, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::dfavgrelerror(const_cast(df.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This subroutine builds random decision forest. - ---------- DEPRECATED VERSION! USE DECISION FOREST BUILDER OBJECT --------- - - -- ALGLIB -- - Copyright 19.02.2009 by Bochkanov Sergey -*************************************************************************/ -void dfbuildrandomdecisionforest(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, const ae_int_t ntrees, const double r, ae_int_t &info, decisionforest &df, dfreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dfbuildrandomdecisionforest(const_cast(xy.c_ptr()), npoints, nvars, nclasses, ntrees, r, &info, const_cast(df.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine builds random decision forest. - ---------- DEPRECATED VERSION! USE DECISION FOREST BUILDER OBJECT --------- - - -- ALGLIB -- - Copyright 19.02.2009 by Bochkanov Sergey -*************************************************************************/ -void dfbuildrandomdecisionforestx1(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, const ae_int_t ntrees, const ae_int_t nrndvars, const double r, ae_int_t &info, decisionforest &df, dfreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::dfbuildrandomdecisionforestx1(const_cast(xy.c_ptr()), npoints, nvars, nclasses, ntrees, nrndvars, r, &info, const_cast(df.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_KNN) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Buffer object which is used to perform various requests (usually model -inference) in the multithreaded mode (multiple threads working with same -KNN object). - -This object should be created with KNNCreateBuffer(). -*************************************************************************/ -_knnbuffer_owner::_knnbuffer_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_knnbuffer_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::knnbuffer*)alglib_impl::ae_malloc(sizeof(alglib_impl::knnbuffer), &_state); - memset(p_struct, 0, sizeof(alglib_impl::knnbuffer)); - alglib_impl::_knnbuffer_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_knnbuffer_owner::_knnbuffer_owner(const _knnbuffer_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_knnbuffer_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: knnbuffer copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::knnbuffer*)alglib_impl::ae_malloc(sizeof(alglib_impl::knnbuffer), &_state); - memset(p_struct, 0, sizeof(alglib_impl::knnbuffer)); - alglib_impl::_knnbuffer_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_knnbuffer_owner& _knnbuffer_owner::operator=(const _knnbuffer_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: knnbuffer assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: knnbuffer assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_knnbuffer_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::knnbuffer)); - alglib_impl::_knnbuffer_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_knnbuffer_owner::~_knnbuffer_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_knnbuffer_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::knnbuffer* _knnbuffer_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::knnbuffer* _knnbuffer_owner::c_ptr() const -{ - return const_cast(p_struct); -} -knnbuffer::knnbuffer() : _knnbuffer_owner() -{ -} - -knnbuffer::knnbuffer(const knnbuffer &rhs):_knnbuffer_owner(rhs) -{ -} - -knnbuffer& knnbuffer::operator=(const knnbuffer &rhs) -{ - if( this==&rhs ) - return *this; - _knnbuffer_owner::operator=(rhs); - return *this; -} - -knnbuffer::~knnbuffer() -{ -} - - -/************************************************************************* -A KNN builder object; this object encapsulates dataset and all related -settings, it is used to create an actual instance of KNN model. -*************************************************************************/ -_knnbuilder_owner::_knnbuilder_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_knnbuilder_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::knnbuilder*)alglib_impl::ae_malloc(sizeof(alglib_impl::knnbuilder), &_state); - memset(p_struct, 0, sizeof(alglib_impl::knnbuilder)); - alglib_impl::_knnbuilder_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_knnbuilder_owner::_knnbuilder_owner(const _knnbuilder_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_knnbuilder_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: knnbuilder copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::knnbuilder*)alglib_impl::ae_malloc(sizeof(alglib_impl::knnbuilder), &_state); - memset(p_struct, 0, sizeof(alglib_impl::knnbuilder)); - alglib_impl::_knnbuilder_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_knnbuilder_owner& _knnbuilder_owner::operator=(const _knnbuilder_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: knnbuilder assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: knnbuilder assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_knnbuilder_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::knnbuilder)); - alglib_impl::_knnbuilder_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_knnbuilder_owner::~_knnbuilder_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_knnbuilder_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::knnbuilder* _knnbuilder_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::knnbuilder* _knnbuilder_owner::c_ptr() const -{ - return const_cast(p_struct); -} -knnbuilder::knnbuilder() : _knnbuilder_owner() -{ -} - -knnbuilder::knnbuilder(const knnbuilder &rhs):_knnbuilder_owner(rhs) -{ -} - -knnbuilder& knnbuilder::operator=(const knnbuilder &rhs) -{ - if( this==&rhs ) - return *this; - _knnbuilder_owner::operator=(rhs); - return *this; -} - -knnbuilder::~knnbuilder() -{ -} - - -/************************************************************************* -KNN model, can be used for classification or regression -*************************************************************************/ -_knnmodel_owner::_knnmodel_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_knnmodel_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::knnmodel*)alglib_impl::ae_malloc(sizeof(alglib_impl::knnmodel), &_state); - memset(p_struct, 0, sizeof(alglib_impl::knnmodel)); - alglib_impl::_knnmodel_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_knnmodel_owner::_knnmodel_owner(const _knnmodel_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_knnmodel_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: knnmodel copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::knnmodel*)alglib_impl::ae_malloc(sizeof(alglib_impl::knnmodel), &_state); - memset(p_struct, 0, sizeof(alglib_impl::knnmodel)); - alglib_impl::_knnmodel_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_knnmodel_owner& _knnmodel_owner::operator=(const _knnmodel_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: knnmodel assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: knnmodel assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_knnmodel_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::knnmodel)); - alglib_impl::_knnmodel_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_knnmodel_owner::~_knnmodel_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_knnmodel_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::knnmodel* _knnmodel_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::knnmodel* _knnmodel_owner::c_ptr() const -{ - return const_cast(p_struct); -} -knnmodel::knnmodel() : _knnmodel_owner() -{ -} - -knnmodel::knnmodel(const knnmodel &rhs):_knnmodel_owner(rhs) -{ -} - -knnmodel& knnmodel::operator=(const knnmodel &rhs) -{ - if( this==&rhs ) - return *this; - _knnmodel_owner::operator=(rhs); - return *this; -} - -knnmodel::~knnmodel() -{ -} - - -/************************************************************************* -KNN training report. - -Following fields store training set errors: -* relclserror - fraction of misclassified cases, [0,1] -* avgce - average cross-entropy in bits per symbol -* rmserror - root-mean-square error -* avgerror - average error -* avgrelerror - average relative error - -For classification problems: -* RMS, AVG and AVGREL errors are calculated for posterior probabilities - -For regression problems: -* RELCLS and AVGCE errors are zero -*************************************************************************/ -_knnreport_owner::_knnreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_knnreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::knnreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::knnreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::knnreport)); - alglib_impl::_knnreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_knnreport_owner::_knnreport_owner(const _knnreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_knnreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: knnreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::knnreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::knnreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::knnreport)); - alglib_impl::_knnreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_knnreport_owner& _knnreport_owner::operator=(const _knnreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: knnreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: knnreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_knnreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::knnreport)); - alglib_impl::_knnreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_knnreport_owner::~_knnreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_knnreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::knnreport* _knnreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::knnreport* _knnreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -knnreport::knnreport() : _knnreport_owner() ,relclserror(p_struct->relclserror),avgce(p_struct->avgce),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror) -{ -} - -knnreport::knnreport(const knnreport &rhs):_knnreport_owner(rhs) ,relclserror(p_struct->relclserror),avgce(p_struct->avgce),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror) -{ -} - -knnreport& knnreport::operator=(const knnreport &rhs) -{ - if( this==&rhs ) - return *this; - _knnreport_owner::operator=(rhs); - return *this; -} - -knnreport::~knnreport() -{ -} - - -/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -void knnserialize(knnmodel &obj, std::string &s_out) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - alglib_impl::ae_int_t ssize; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_alloc_start(&serializer); - alglib_impl::knnalloc(&serializer, obj.c_ptr(), &state); - ssize = alglib_impl::ae_serializer_get_alloc_size(&serializer); - s_out.clear(); - s_out.reserve((size_t)(ssize+1)); - alglib_impl::ae_serializer_sstart_str(&serializer, &s_out); - alglib_impl::knnserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_assert( s_out.length()<=(size_t)ssize, "ALGLIB: serialization integrity error", &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} -/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -void knnunserialize(const std::string &s_in, knnmodel &obj) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_ustart_str(&serializer, &s_in); - alglib_impl::knnunserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} - - -/************************************************************************* -This function serializes data structure to C++ stream. - -Data stream generated by this function is same as string representation -generated by string version of serializer - alphanumeric characters, -dots, underscores, minus signs, which are grouped into words separated by -spaces and CR+LF. - -We recommend you to read comments on string version of serializer to find -out more about serialization of AlGLIB objects. -*************************************************************************/ -void knnserialize(knnmodel &obj, std::ostream &s_out) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_alloc_start(&serializer); - alglib_impl::knnalloc(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_get_alloc_size(&serializer); // not actually needed, but we have to ask - alglib_impl::ae_serializer_sstart_stream(&serializer, &s_out); - alglib_impl::knnserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} -/************************************************************************* -This function unserializes data structure from stream. -*************************************************************************/ -void knnunserialize(const std::istream &s_in, knnmodel &obj) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_ustart_stream(&serializer, &s_in); - alglib_impl::knnunserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} - -/************************************************************************* -This function creates buffer structure which can be used to perform -parallel KNN requests. - -KNN subpackage provides two sets of computing functions - ones which use -internal buffer of KNN model (these functions are single-threaded because -they use same buffer, which can not shared between threads), and ones -which use external buffer. - -This function is used to initialize external buffer. - -INPUT PARAMETERS - Model - KNN model which is associated with newly created buffer - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: buffer object should be used only with model which was used to - initialize buffer. Any attempt to use buffer with different - object is dangerous - you may get integrity check failure - (exception) because sizes of internal arrays do not fit to - dimensions of the model structure. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knncreatebuffer(const knnmodel &model, knnbuffer &buf, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::knncreatebuffer(const_cast(model.c_ptr()), const_cast(buf.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine creates KNNBuilder object which is used to train KNN models. - -By default, new builder stores empty dataset and some reasonable default -settings. At the very least, you should specify dataset prior to building -KNN model. You can also tweak settings of the model construction algorithm -(recommended, although default settings should work well). - -Following actions are mandatory: -* calling knnbuildersetdataset() to specify dataset -* calling knnbuilderbuildknnmodel() to build KNN model using current - dataset and default settings - -Additionally, you may call: -* knnbuildersetnorm() to change norm being used - -INPUT PARAMETERS: - none - -OUTPUT PARAMETERS: - S - KNN builder - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnbuildercreate(knnbuilder &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::knnbuildercreate(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Specifies regression problem (one or more continuous output variables are -predicted). There also exists "classification" version of this function. - -This subroutine adds dense dataset to the internal storage of the builder -object. Specifying your dataset in the dense format means that the dense -version of the KNN construction algorithm will be invoked. - -INPUT PARAMETERS: - S - KNN builder object - XY - array[NPoints,NVars+NOut] (note: actual size can be - larger, only leading part is used anyway), dataset: - * first NVars elements of each row store values of the - independent variables - * next NOut elements store values of the dependent - variables - NPoints - number of rows in the dataset, NPoints>=1 - NVars - number of independent variables, NVars>=1 - NOut - number of dependent variables, NOut>=1 - -OUTPUT PARAMETERS: - S - KNN builder - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnbuildersetdatasetreg(const knnbuilder &s, const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nout, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::knnbuildersetdatasetreg(const_cast(s.c_ptr()), const_cast(xy.c_ptr()), npoints, nvars, nout, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Specifies classification problem (two or more classes are predicted). -There also exists "regression" version of this function. - -This subroutine adds dense dataset to the internal storage of the builder -object. Specifying your dataset in the dense format means that the dense -version of the KNN construction algorithm will be invoked. - -INPUT PARAMETERS: - S - KNN builder object - XY - array[NPoints,NVars+1] (note: actual size can be - larger, only leading part is used anyway), dataset: - * first NVars elements of each row store values of the - independent variables - * next element stores class index, in [0,NClasses) - NPoints - number of rows in the dataset, NPoints>=1 - NVars - number of independent variables, NVars>=1 - NClasses - number of classes, NClasses>=2 - -OUTPUT PARAMETERS: - S - KNN builder - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnbuildersetdatasetcls(const knnbuilder &s, const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::knnbuildersetdatasetcls(const_cast(s.c_ptr()), const_cast(xy.c_ptr()), npoints, nvars, nclasses, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets norm type used for neighbor search. - -INPUT PARAMETERS: - S - decision forest builder object - NormType - norm type: - * 0 inf-norm - * 1 1-norm - * 2 Euclidean norm (default) - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnbuildersetnorm(const knnbuilder &s, const ae_int_t nrmtype, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::knnbuildersetnorm(const_cast(s.c_ptr()), nrmtype, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine builds KNN model according to current settings, using -dataset internally stored in the builder object. - -The model being built performs inference using Eps-approximate K nearest -neighbors search algorithm, with: -* K=1, Eps=0 corresponding to the "nearest neighbor algorithm" -* K>1, Eps=0 corresponding to the "K nearest neighbors algorithm" -* K>=1, Eps>0 corresponding to "approximate nearest neighbors algorithm" - -An approximate KNN is a good option for high-dimensional datasets (exact -KNN works slowly when dimensions count grows). - -An ALGLIB implementation of kd-trees is used to perform k-nn searches. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - KNN builder object - K - number of neighbors to search for, K>=1 - Eps - approximation factor: - * Eps=0 means that exact kNN search is performed - * Eps>0 means that (1+Eps)-approximate search is performed - -OUTPUT PARAMETERS: - Model - KNN model - Rep - report - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnbuilderbuildknnmodel(const knnbuilder &s, const ae_int_t k, const double eps, knnmodel &model, knnreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::knnbuilderbuildknnmodel(const_cast(s.c_ptr()), k, eps, const_cast(model.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Changing search settings of KNN model. - -K and EPS parameters of KNN (AKNN) search are specified during model -construction. However, plain KNN algorithm with Euclidean distance allows -you to change them at any moment. - -NOTE: future versions of KNN model may support advanced versions of KNN, - such as NCA or LMNN. It is possible that such algorithms won't allow - you to change search settings on the fly. If you call this function - for an algorithm which does not support on-the-fly changes, it will - throw an exception. - -INPUT PARAMETERS: - Model - KNN model - K - K>=1, neighbors count - EPS - accuracy of the EPS-approximate NN search. Set to 0.0, if - you want to perform "classic" KNN search. Specify larger - values if you need to speed-up high-dimensional KNN - queries. - -OUTPUT PARAMETERS: - nothing on success, exception on failure - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnrewritekeps(const knnmodel &model, const ae_int_t k, const double eps, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::knnrewritekeps(const_cast(model.c_ptr()), k, eps, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Inference using KNN model. - -See also knnprocess0(), knnprocessi() and knnclassify() for options with a -bit more convenient interface. - -IMPORTANT: this function is thread-unsafe and modifies internal structures - of the model! You can not use same model object for parallel - evaluation from several threads. - - Use knntsprocess() with independent thread-local buffers, if - you need thread-safe evaluation. - -INPUT PARAMETERS: - Model - KNN model - X - input vector, array[0..NVars-1]. - Y - possible preallocated buffer. Reused if long enough. - -OUTPUT PARAMETERS: - Y - result. Regression estimate when solving regression task, - vector of posterior probabilities for classification task. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnprocess(const knnmodel &model, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::knnprocess(const_cast(model.c_ptr()), const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function returns first component of the inferred vector (i.e. one -with index #0). - -It is a convenience wrapper for knnprocess() intended for either: -* 1-dimensional regression problems -* 2-class classification problems - -In the former case this function returns inference result as scalar, which -is definitely more convenient that wrapping it as vector. In the latter -case it returns probability of object belonging to class #0. - -If you call it for anything different from two cases above, it will work -as defined, i.e. return y[0], although it is of less use in such cases. - -IMPORTANT: this function is thread-unsafe and modifies internal structures - of the model! You can not use same model object for parallel - evaluation from several threads. - - Use knntsprocess() with independent thread-local buffers, if - you need thread-safe evaluation. - -INPUT PARAMETERS: - Model - KNN model - X - input vector, array[0..NVars-1]. - -RESULT: - Y[0] - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double knnprocess0(const knnmodel &model, const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::knnprocess0(const_cast(model.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function returns most probable class number for an input X. It is -same as calling knnprocess(model,x,y), then determining i=argmax(y[i]) and -returning i. - -A class number in [0,NOut) range in returned for classification problems, --1 is returned when this function is called for regression problems. - -IMPORTANT: this function is thread-unsafe and modifies internal structures - of the model! You can not use same model object for parallel - evaluation from several threads. - - Use knntsprocess() with independent thread-local buffers, if - you need thread-safe evaluation. - -INPUT PARAMETERS: - Model - KNN model - X - input vector, array[0..NVars-1]. - -RESULT: - class number, -1 for regression tasks - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -ae_int_t knnclassify(const knnmodel &model, const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::knnclassify(const_cast(model.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -'interactive' variant of knnprocess() for languages like Python which -support constructs like "y = knnprocessi(model,x)" and interactive mode of -the interpreter. - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - -IMPORTANT: this function is thread-unsafe and may modify internal - structures of the model! You can not use same model object for - parallel evaluation from several threads. - - Use knntsprocess() with independent thread-local buffers if - you need thread-safe evaluation. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnprocessi(const knnmodel &model, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::knnprocessi(const_cast(model.c_ptr()), const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Thread-safe procesing using external buffer for temporaries. - -This function is thread-safe (i.e . you can use same KNN model from -multiple threads) as long as you use different buffer objects for different -threads. - -INPUT PARAMETERS: - Model - KNN model - Buf - buffer object, must be allocated specifically for this - model with knncreatebuffer(). - X - input vector, array[NVars] - -OUTPUT PARAMETERS: - Y - result, array[NOut]. Regression estimate when solving - regression task, vector of posterior probabilities for - a classification task. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knntsprocess(const knnmodel &model, const knnbuffer &buf, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::knntsprocess(const_cast(model.c_ptr()), const_cast(buf.c_ptr()), const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Relative classification error on the test set - -INPUT PARAMETERS: - Model - KNN model - XY - test set - NPoints - test set size - -RESULT: - percent of incorrectly classified cases. - Zero if model solves regression task. - -NOTE: if you need several different kinds of error metrics, it is better - to use knnallerrors() which computes all error metric with just one - pass over dataset. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double knnrelclserror(const knnmodel &model, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::knnrelclserror(const_cast(model.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Average cross-entropy (in bits per element) on the test set - -INPUT PARAMETERS: - Model - KNN model - XY - test set - NPoints - test set size - -RESULT: - CrossEntropy/NPoints. - Zero if model solves regression task. - -NOTE: the cross-entropy metric is too unstable when used to evaluate KNN - models (such models can report exactly zero probabilities), so we - do not recommend using it. - -NOTE: if you need several different kinds of error metrics, it is better - to use knnallerrors() which computes all error metric with just one - pass over dataset. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double knnavgce(const knnmodel &model, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::knnavgce(const_cast(model.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -RMS error on the test set. - -Its meaning for regression task is obvious. As for classification problems, -RMS error means error when estimating posterior probabilities. - -INPUT PARAMETERS: - Model - KNN model - XY - test set - NPoints - test set size - -RESULT: - root mean square error. - -NOTE: if you need several different kinds of error metrics, it is better - to use knnallerrors() which computes all error metric with just one - pass over dataset. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double knnrmserror(const knnmodel &model, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::knnrmserror(const_cast(model.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Average error on the test set - -Its meaning for regression task is obvious. As for classification problems, -average error means error when estimating posterior probabilities. - -INPUT PARAMETERS: - Model - KNN model - XY - test set - NPoints - test set size - -RESULT: - average error - -NOTE: if you need several different kinds of error metrics, it is better - to use knnallerrors() which computes all error metric with just one - pass over dataset. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double knnavgerror(const knnmodel &model, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::knnavgerror(const_cast(model.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Average relative error on the test set - -Its meaning for regression task is obvious. As for classification problems, -average relative error means error when estimating posterior probabilities. - -INPUT PARAMETERS: - Model - KNN model - XY - test set - NPoints - test set size - -RESULT: - average relative error - -NOTE: if you need several different kinds of error metrics, it is better - to use knnallerrors() which computes all error metric with just one - pass over dataset. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double knnavgrelerror(const knnmodel &model, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::knnavgrelerror(const_cast(model.c_ptr()), const_cast(xy.c_ptr()), npoints, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Calculates all kinds of errors for the model in one call. - -INPUT PARAMETERS: - Model - KNN model - XY - test set: - * one row per point - * first NVars columns store independent variables - * depending on problem type: - * next column stores class number in [0,NClasses) - for - classification problems - * next NOut columns store dependent variables - for - regression problems - NPoints - test set size, NPoints>=0 - -OUTPUT PARAMETERS: - Rep - following fields are loaded with errors for both regression - and classification models: - * rep.rmserror - RMS error for the output - * rep.avgerror - average error - * rep.avgrelerror - average relative error - following fields are set only for classification models, - zero for regression ones: - * relclserror - relative classification error, in [0,1] - * avgce - average cross-entropy in bits per dataset entry - -NOTE: the cross-entropy metric is too unstable when used to evaluate KNN - models (such models can report exactly zero probabilities), so we - do not recommend using it. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnallerrors(const knnmodel &model, const real_2d_array &xy, const ae_int_t npoints, knnreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::knnallerrors(const_cast(model.c_ptr()), const_cast(xy.c_ptr()), npoints, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_DATACOMP) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -k-means++ clusterization. -Backward compatibility function, we recommend to use CLUSTERING subpackage -as better replacement. - - -- ALGLIB -- - Copyright 21.03.2009 by Bochkanov Sergey -*************************************************************************/ -void kmeansgenerate(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t k, const ae_int_t restarts, ae_int_t &info, real_2d_array &c, integer_1d_array &xyc, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::kmeansgenerate(const_cast(xy.c_ptr()), npoints, nvars, k, restarts, &info, const_cast(c.c_ptr()), const_cast(xyc.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF COMPUTATIONAL CORE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_PCA) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_BDSS) || !defined(AE_PARTIAL_BUILD) -static double bdss_xlny(double x, double y, ae_state *_state); -static double bdss_getcv(/* Integer */ ae_vector* cnt, - ae_int_t nc, - ae_state *_state); -static void bdss_tieaddc(/* Integer */ ae_vector* c, - /* Integer */ ae_vector* ties, - ae_int_t ntie, - ae_int_t nc, - /* Integer */ ae_vector* cnt, - ae_state *_state); -static void bdss_tiesubc(/* Integer */ ae_vector* c, - /* Integer */ ae_vector* ties, - ae_int_t ntie, - ae_int_t nc, - /* Integer */ ae_vector* cnt, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_MLPBASE) || !defined(AE_PARTIAL_BUILD) -static ae_int_t mlpbase_mlpvnum = 7; -static ae_int_t mlpbase_mlpfirstversion = 0; -static ae_int_t mlpbase_nfieldwidth = 4; -static ae_int_t mlpbase_hlconnfieldwidth = 5; -static ae_int_t mlpbase_hlnfieldwidth = 4; -static ae_int_t mlpbase_gradbasecasecost = 50000; -static ae_int_t mlpbase_microbatchsize = 64; -static void mlpbase_addinputlayer(ae_int_t ncount, - /* Integer */ ae_vector* lsizes, - /* Integer */ ae_vector* ltypes, - /* Integer */ ae_vector* lconnfirst, - /* Integer */ ae_vector* lconnlast, - ae_int_t* lastproc, - ae_state *_state); -static void mlpbase_addbiasedsummatorlayer(ae_int_t ncount, - /* Integer */ ae_vector* lsizes, - /* Integer */ ae_vector* ltypes, - /* Integer */ ae_vector* lconnfirst, - /* Integer */ ae_vector* lconnlast, - ae_int_t* lastproc, - ae_state *_state); -static void mlpbase_addactivationlayer(ae_int_t functype, - /* Integer */ ae_vector* lsizes, - /* Integer */ ae_vector* ltypes, - /* Integer */ ae_vector* lconnfirst, - /* Integer */ ae_vector* lconnlast, - ae_int_t* lastproc, - ae_state *_state); -static void mlpbase_addzerolayer(/* Integer */ ae_vector* lsizes, - /* Integer */ ae_vector* ltypes, - /* Integer */ ae_vector* lconnfirst, - /* Integer */ ae_vector* lconnlast, - ae_int_t* lastproc, - ae_state *_state); -static void mlpbase_hladdinputlayer(multilayerperceptron* network, - ae_int_t* connidx, - ae_int_t* neuroidx, - ae_int_t* structinfoidx, - ae_int_t nin, - ae_state *_state); -static void mlpbase_hladdoutputlayer(multilayerperceptron* network, - ae_int_t* connidx, - ae_int_t* neuroidx, - ae_int_t* structinfoidx, - ae_int_t* weightsidx, - ae_int_t k, - ae_int_t nprev, - ae_int_t nout, - ae_bool iscls, - ae_bool islinearout, - ae_state *_state); -static void mlpbase_hladdhiddenlayer(multilayerperceptron* network, - ae_int_t* connidx, - ae_int_t* neuroidx, - ae_int_t* structinfoidx, - ae_int_t* weightsidx, - ae_int_t k, - ae_int_t nprev, - ae_int_t ncur, - ae_state *_state); -static void mlpbase_fillhighlevelinformation(multilayerperceptron* network, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_bool iscls, - ae_bool islinearout, - ae_state *_state); -static void mlpbase_mlpcreate(ae_int_t nin, - ae_int_t nout, - /* Integer */ ae_vector* lsizes, - /* Integer */ ae_vector* ltypes, - /* Integer */ ae_vector* lconnfirst, - /* Integer */ ae_vector* lconnlast, - ae_int_t layerscount, - ae_bool isclsnet, - multilayerperceptron* network, - ae_state *_state); -static void mlpbase_mlphessianbatchinternal(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t ssize, - ae_bool naturalerr, - double* e, - /* Real */ ae_vector* grad, - /* Real */ ae_matrix* h, - ae_state *_state); -static void mlpbase_mlpinternalcalculategradient(multilayerperceptron* network, - /* Real */ ae_vector* neurons, - /* Real */ ae_vector* weights, - /* Real */ ae_vector* derror, - /* Real */ ae_vector* grad, - ae_bool naturalerrorfunc, - ae_state *_state); -static void mlpbase_mlpchunkedgradient(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t cstart, - ae_int_t csize, - /* Real */ ae_vector* batch4buf, - /* Real */ ae_vector* hpcbuf, - double* e, - ae_bool naturalerrorfunc, - ae_state *_state); -static void mlpbase_mlpchunkedprocess(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t cstart, - ae_int_t csize, - /* Real */ ae_vector* batch4buf, - /* Real */ ae_vector* hpcbuf, - ae_state *_state); -static double mlpbase_safecrossentropy(double t, - double z, - ae_state *_state); -static void mlpbase_randomizebackwardpass(multilayerperceptron* network, - ae_int_t neuronidx, - double v, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_LDA) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_SSA) || !defined(AE_PARTIAL_BUILD) -static ae_bool ssa_hassomethingtoanalyze(ssamodel* s, ae_state *_state); -static ae_bool ssa_issequencebigenough(ssamodel* s, - ae_int_t i, - ae_state *_state); -static void ssa_updatebasis(ssamodel* s, - ae_int_t appendlen, - double updateits, - ae_state *_state); -static void ssa_analyzesequence(ssamodel* s, - /* Real */ ae_vector* data, - ae_int_t i0, - ae_int_t i1, - /* Real */ ae_vector* trend, - /* Real */ ae_vector* noise, - ae_int_t offs, - ae_state *_state); -static void ssa_forecastavgsequence(ssamodel* s, - /* Real */ ae_vector* data, - ae_int_t i0, - ae_int_t i1, - ae_int_t m, - ae_int_t forecastlen, - ae_bool smooth, - /* Real */ ae_vector* trend, - ae_int_t offs, - ae_state *_state); -static void ssa_realtimedequeue(ssamodel* s, - double beta, - ae_int_t cnt, - ae_state *_state); -static void ssa_updatexxtprepare(ssamodel* s, - ae_int_t updatesize, - ae_int_t windowwidth, - ae_int_t memorylimit, - ae_state *_state); -static void ssa_updatexxtsend(ssamodel* s, - /* Real */ ae_vector* u, - ae_int_t i0, - /* Real */ ae_matrix* xxt, - ae_state *_state); -static void ssa_updatexxtfinalize(ssamodel* s, - /* Real */ ae_matrix* xxt, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_LINREG) || !defined(AE_PARTIAL_BUILD) -static ae_int_t linreg_lrvnum = 5; -static void linreg_lrinternal(/* Real */ ae_matrix* xy, - /* Real */ ae_vector* s, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t* info, - linearmodel* lm, - lrreport* ar, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_FILTERS) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_LOGIT) || !defined(AE_PARTIAL_BUILD) -static double logit_xtol = 100*ae_machineepsilon; -static double logit_ftol = 0.0001; -static double logit_gtol = 0.3; -static ae_int_t logit_maxfev = 20; -static double logit_stpmin = 1.0E-2; -static double logit_stpmax = 1.0E5; -static ae_int_t logit_logitvnum = 6; -static void logit_mnliexp(/* Real */ ae_vector* w, - /* Real */ ae_vector* x, - ae_state *_state); -static void logit_mnlallerrors(logitmodel* lm, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double* relcls, - double* avgce, - double* rms, - double* avg, - double* avgrel, - ae_state *_state); -static void logit_mnlmcsrch(ae_int_t n, - /* Real */ ae_vector* x, - double* f, - /* Real */ ae_vector* g, - /* Real */ ae_vector* s, - double* stp, - ae_int_t* info, - ae_int_t* nfev, - /* Real */ ae_vector* wa, - logitmcstate* state, - ae_int_t* stage, - ae_state *_state); -static void logit_mnlmcstep(double* stx, - double* fx, - double* dx, - double* sty, - double* fy, - double* dy, - double* stp, - double fp, - double dp, - ae_bool* brackt, - double stmin, - double stmax, - ae_int_t* info, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_MCPD) || !defined(AE_PARTIAL_BUILD) -static double mcpd_xtol = 1.0E-8; -static void mcpd_mcpdinit(ae_int_t n, - ae_int_t entrystate, - ae_int_t exitstate, - mcpdstate* s, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_MLPE) || !defined(AE_PARTIAL_BUILD) -static ae_int_t mlpe_mlpefirstversion = 1; - - -#endif -#if defined(AE_COMPILE_MLPTRAIN) || !defined(AE_PARTIAL_BUILD) -static double mlptrain_mindecay = 0.001; -static ae_int_t mlptrain_defaultlbfgsfactor = 6; -static void mlptrain_mlpkfoldcvgeneral(multilayerperceptron* n, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - ae_int_t foldscount, - ae_bool lmalgorithm, - double wstep, - ae_int_t maxits, - ae_int_t* info, - mlpreport* rep, - mlpcvreport* cvrep, - ae_state *_state); -static void mlptrain_mlpkfoldsplit(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nclasses, - ae_int_t foldscount, - ae_bool stratifiedsplits, - /* Integer */ ae_vector* folds, - ae_state *_state); -static void mlptrain_mthreadcv(mlptrainer* s, - ae_int_t rowsize, - ae_int_t nrestarts, - /* Integer */ ae_vector* folds, - ae_int_t fold, - ae_int_t dfold, - /* Real */ ae_matrix* cvy, - ae_shared_pool* pooldatacv, - ae_int_t wcount, - ae_state *_state); -ae_bool _trypexec_mlptrain_mthreadcv(mlptrainer* s, - ae_int_t rowsize, - ae_int_t nrestarts, - /* Integer */ ae_vector* folds, - ae_int_t fold, - ae_int_t dfold, - /* Real */ ae_matrix* cvy, - ae_shared_pool* pooldatacv, - ae_int_t wcount, ae_state *_state); -static void mlptrain_mlptrainnetworkx(mlptrainer* s, - ae_int_t nrestarts, - ae_int_t algokind, - /* Integer */ ae_vector* trnsubset, - ae_int_t trnsubsetsize, - /* Integer */ ae_vector* valsubset, - ae_int_t valsubsetsize, - multilayerperceptron* network, - mlpreport* rep, - ae_bool isrootcall, - ae_shared_pool* sessions, - ae_state *_state); -ae_bool _trypexec_mlptrain_mlptrainnetworkx(mlptrainer* s, - ae_int_t nrestarts, - ae_int_t algokind, - /* Integer */ ae_vector* trnsubset, - ae_int_t trnsubsetsize, - /* Integer */ ae_vector* valsubset, - ae_int_t valsubsetsize, - multilayerperceptron* network, - mlpreport* rep, - ae_bool isrootcall, - ae_shared_pool* sessions, ae_state *_state); -static void mlptrain_mlptrainensemblex(mlptrainer* s, - mlpensemble* ensemble, - ae_int_t idx0, - ae_int_t idx1, - ae_int_t nrestarts, - ae_int_t trainingmethod, - sinteger* ngrad, - ae_bool isrootcall, - ae_shared_pool* esessions, - ae_state *_state); -ae_bool _trypexec_mlptrain_mlptrainensemblex(mlptrainer* s, - mlpensemble* ensemble, - ae_int_t idx0, - ae_int_t idx1, - ae_int_t nrestarts, - ae_int_t trainingmethod, - sinteger* ngrad, - ae_bool isrootcall, - ae_shared_pool* esessions, ae_state *_state); -static void mlptrain_mlpstarttrainingx(mlptrainer* s, - ae_bool randomstart, - ae_int_t algokind, - /* Integer */ ae_vector* subset, - ae_int_t subsetsize, - smlptrnsession* session, - ae_state *_state); -static ae_bool mlptrain_mlpcontinuetrainingx(mlptrainer* s, - /* Integer */ ae_vector* subset, - ae_int_t subsetsize, - ae_int_t* ngradbatch, - smlptrnsession* session, - ae_state *_state); -static void mlptrain_mlpebagginginternal(mlpensemble* ensemble, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - double wstep, - ae_int_t maxits, - ae_bool lmalgorithm, - ae_int_t* info, - mlpreport* rep, - mlpcvreport* ooberrors, - ae_state *_state); -static void mlptrain_initmlptrnsession(multilayerperceptron* networktrained, - ae_bool randomizenetwork, - mlptrainer* trainer, - smlptrnsession* session, - ae_state *_state); -static void mlptrain_initmlptrnsessions(multilayerperceptron* networktrained, - ae_bool randomizenetwork, - mlptrainer* trainer, - ae_shared_pool* sessions, - ae_state *_state); -static void mlptrain_initmlpetrnsession(multilayerperceptron* individualnetwork, - mlptrainer* trainer, - mlpetrnsession* session, - ae_state *_state); -static void mlptrain_initmlpetrnsessions(multilayerperceptron* individualnetwork, - mlptrainer* trainer, - ae_shared_pool* sessions, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_CLUSTERING) || !defined(AE_PARTIAL_BUILD) -static ae_int_t clustering_kmeansblocksize = 32; -static ae_int_t clustering_kmeansparalleldim = 8; -static ae_int_t clustering_kmeansparallelk = 4; -static double clustering_complexitymultiplier = 1.0; -static void clustering_selectinitialcenters(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t initalgo, - hqrndstate* rs, - ae_int_t k, - /* Real */ ae_matrix* ct, - apbuffers* initbuf, - ae_shared_pool* updatepool, - ae_state *_state); -static ae_bool clustering_fixcenters(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - /* Real */ ae_matrix* ct, - ae_int_t k, - apbuffers* initbuf, - ae_shared_pool* updatepool, - ae_state *_state); -static void clustering_clusterizerrunahcinternal(clusterizerstate* s, - /* Real */ ae_matrix* d, - ahcreport* rep, - ae_state *_state); -static void clustering_evaluatedistancematrixrec(/* Real */ ae_matrix* xy, - ae_int_t nfeatures, - ae_int_t disttype, - /* Real */ ae_matrix* d, - ae_int_t i0, - ae_int_t i1, - ae_int_t j0, - ae_int_t j1, - ae_state *_state); -ae_bool _trypexec_clustering_evaluatedistancematrixrec(/* Real */ ae_matrix* xy, - ae_int_t nfeatures, - ae_int_t disttype, - /* Real */ ae_matrix* d, - ae_int_t i0, - ae_int_t i1, - ae_int_t j0, - ae_int_t j1, ae_state *_state); - - -#endif -#if defined(AE_COMPILE_DFOREST) || !defined(AE_PARTIAL_BUILD) -static ae_int_t dforest_innernodewidth = 3; -static ae_int_t dforest_leafnodewidth = 2; -static ae_int_t dforest_dfusestrongsplits = 1; -static ae_int_t dforest_dfuseevs = 2; -static ae_int_t dforest_dfuncompressedv0 = 0; -static ae_int_t dforest_dfcompressedv0 = 1; -static ae_int_t dforest_needtrngini = 1; -static ae_int_t dforest_needoobgini = 2; -static ae_int_t dforest_needpermutation = 3; -static ae_int_t dforest_permutationimportancebatchsize = 512; -static void dforest_buildrandomtree(decisionforestbuilder* s, - ae_int_t treeidx0, - ae_int_t treeidx1, - ae_state *_state); -ae_bool _trypexec_dforest_buildrandomtree(decisionforestbuilder* s, - ae_int_t treeidx0, - ae_int_t treeidx1, ae_state *_state); -static void dforest_buildrandomtreerec(decisionforestbuilder* s, - dfworkbuf* workbuf, - ae_int_t workingset, - ae_int_t varstoselect, - /* Real */ ae_vector* treebuf, - dfvotebuf* votebuf, - hqrndstate* rs, - ae_int_t idx0, - ae_int_t idx1, - ae_int_t oobidx0, - ae_int_t oobidx1, - double meanloss, - double topmostmeanloss, - ae_int_t* treesize, - ae_state *_state); -static void dforest_estimatevariableimportance(decisionforestbuilder* s, - ae_int_t sessionseed, - decisionforest* df, - ae_int_t ntrees, - dfreport* rep, - ae_state *_state); -ae_bool _trypexec_dforest_estimatevariableimportance(decisionforestbuilder* s, - ae_int_t sessionseed, - decisionforest* df, - ae_int_t ntrees, - dfreport* rep, ae_state *_state); -static void dforest_estimatepermutationimportances(decisionforestbuilder* s, - decisionforest* df, - ae_int_t ntrees, - ae_shared_pool* permpool, - ae_int_t idx0, - ae_int_t idx1, - ae_state *_state); -ae_bool _trypexec_dforest_estimatepermutationimportances(decisionforestbuilder* s, - decisionforest* df, - ae_int_t ntrees, - ae_shared_pool* permpool, - ae_int_t idx0, - ae_int_t idx1, ae_state *_state); -static void dforest_cleanreport(decisionforestbuilder* s, - dfreport* rep, - ae_state *_state); -static double dforest_meannrms2(ae_int_t nclasses, - /* Integer */ ae_vector* trnlabelsi, - /* Real */ ae_vector* trnlabelsr, - ae_int_t trnidx0, - ae_int_t trnidx1, - /* Integer */ ae_vector* tstlabelsi, - /* Real */ ae_vector* tstlabelsr, - ae_int_t tstidx0, - ae_int_t tstidx1, - /* Integer */ ae_vector* tmpi, - ae_state *_state); -static void dforest_choosecurrentsplitdense(decisionforestbuilder* s, - dfworkbuf* workbuf, - ae_int_t* varsinpool, - ae_int_t varstoselect, - hqrndstate* rs, - ae_int_t idx0, - ae_int_t idx1, - ae_int_t* varbest, - double* splitbest, - ae_state *_state); -static void dforest_evaluatedensesplit(decisionforestbuilder* s, - dfworkbuf* workbuf, - hqrndstate* rs, - ae_int_t splitvar, - ae_int_t idx0, - ae_int_t idx1, - ae_int_t* info, - double* split, - double* rms, - ae_state *_state); -static void dforest_classifiersplit(decisionforestbuilder* s, - dfworkbuf* workbuf, - /* Real */ ae_vector* x, - /* Integer */ ae_vector* c, - ae_int_t n, - hqrndstate* rs, - ae_int_t* info, - double* threshold, - double* e, - /* Real */ ae_vector* sortrbuf, - /* Integer */ ae_vector* sortibuf, - ae_state *_state); -static void dforest_regressionsplit(decisionforestbuilder* s, - dfworkbuf* workbuf, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t* info, - double* threshold, - double* e, - /* Real */ ae_vector* sortrbuf, - /* Real */ ae_vector* sortrbuf2, - ae_state *_state); -static double dforest_getsplit(decisionforestbuilder* s, - double a, - double b, - hqrndstate* rs, - ae_state *_state); -static void dforest_outputleaf(decisionforestbuilder* s, - dfworkbuf* workbuf, - /* Real */ ae_vector* treebuf, - dfvotebuf* votebuf, - ae_int_t idx0, - ae_int_t idx1, - ae_int_t oobidx0, - ae_int_t oobidx1, - ae_int_t* treesize, - double leafval, - ae_state *_state); -static void dforest_analyzeandpreprocessdataset(decisionforestbuilder* s, - ae_state *_state); -static void dforest_mergetrees(decisionforestbuilder* s, - decisionforest* df, - ae_state *_state); -static void dforest_processvotingresults(decisionforestbuilder* s, - ae_int_t ntrees, - dfvotebuf* buf, - dfreport* rep, - ae_state *_state); -static double dforest_binarycompression(decisionforest* df, - ae_bool usemantissa8, - ae_state *_state); -static ae_int_t dforest_computecompressedsizerec(decisionforest* df, - ae_bool usemantissa8, - ae_int_t treeroot, - ae_int_t treepos, - /* Integer */ ae_vector* compressedsizes, - ae_bool savecompressedsizes, - ae_state *_state); -static void dforest_compressrec(decisionforest* df, - ae_bool usemantissa8, - ae_int_t treeroot, - ae_int_t treepos, - /* Integer */ ae_vector* compressedsizes, - ae_vector* buf, - ae_int_t* dstoffs, - ae_state *_state); -static ae_int_t dforest_computecompresseduintsize(ae_int_t v, - ae_state *_state); -static void dforest_streamuint(ae_vector* buf, - ae_int_t* offs, - ae_int_t v, - ae_state *_state); -static ae_int_t dforest_unstreamuint(ae_vector* buf, - ae_int_t* offs, - ae_state *_state); -static void dforest_streamfloat(ae_vector* buf, - ae_bool usemantissa8, - ae_int_t* offs, - double v, - ae_state *_state); -static double dforest_unstreamfloat(ae_vector* buf, - ae_bool usemantissa8, - ae_int_t* offs, - ae_state *_state); -static ae_int_t dforest_dfclserror(decisionforest* df, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -static void dforest_dfprocessinternaluncompressed(decisionforest* df, - ae_int_t subtreeroot, - ae_int_t nodeoffs, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -static void dforest_dfprocessinternalcompressed(decisionforest* df, - ae_int_t offs, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -static double dforest_xfastpow(double r, ae_int_t n, ae_state *_state); - - -#endif -#if defined(AE_COMPILE_KNN) || !defined(AE_PARTIAL_BUILD) -static ae_int_t knn_knnfirstversion = 0; -static void knn_clearreport(knnreport* rep, ae_state *_state); -static void knn_processinternal(knnmodel* model, - knnbuffer* buf, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_DATACOMP) || !defined(AE_PARTIAL_BUILD) - - -#endif - -#if defined(AE_COMPILE_PCA) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Principal components analysis - -This function builds orthogonal basis where first axis corresponds to -direction with maximum variance, second axis maximizes variance in the -subspace orthogonal to first axis and so on. - -This function builds FULL basis, i.e. returns N vectors corresponding to -ALL directions, no matter how informative. If you need just a few (say, -10 or 50) of the most important directions, you may find it faster to use -one of the reduced versions: -* pcatruncatedsubspace() - for subspace iteration based method - -It should be noted that, unlike LDA, PCA does not use class labels. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - dataset, array[0..NPoints-1,0..NVars-1]. - matrix contains ONLY INDEPENDENT VARIABLES. - NPoints - dataset size, NPoints>=0 - NVars - number of independent variables, NVars>=1 - -OUTPUT PARAMETERS: - Info - return code: - * -4, if SVD subroutine haven't converged - * -1, if wrong parameters has been passed (NPoints<0, - NVars<1) - * 1, if task is solved - S2 - array[0..NVars-1]. variance values corresponding - to basis vectors. - V - array[0..NVars-1,0..NVars-1] - matrix, whose columns store basis vectors. - - -- ALGLIB -- - Copyright 25.08.2008 by Bochkanov Sergey -*************************************************************************/ -void pcabuildbasis(/* Real */ ae_matrix* x, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t* info, - /* Real */ ae_vector* s2, - /* Real */ ae_matrix* v, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix u; - ae_matrix vt; - ae_vector m; - ae_vector t; - ae_int_t i; - ae_int_t j; - double mean; - double variance; - double skewness; - double kurtosis; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&u, 0, sizeof(u)); - memset(&vt, 0, sizeof(vt)); - memset(&m, 0, sizeof(m)); - memset(&t, 0, sizeof(t)); - *info = 0; - ae_vector_clear(s2); - ae_matrix_clear(v); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vt, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&m, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - - - /* - * Check input data - */ - if( npoints<0||nvars<1 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - *info = 1; - - /* - * Special case: NPoints=0 - */ - if( npoints==0 ) - { - ae_vector_set_length(s2, nvars, _state); - ae_matrix_set_length(v, nvars, nvars, _state); - for(i=0; i<=nvars-1; i++) - { - s2->ptr.p_double[i] = (double)(0); - } - for(i=0; i<=nvars-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - if( i==j ) - { - v->ptr.pp_double[i][j] = (double)(1); - } - else - { - v->ptr.pp_double[i][j] = (double)(0); - } - } - } - ae_frame_leave(_state); - return; - } - - /* - * Calculate means - */ - ae_vector_set_length(&m, nvars, _state); - ae_vector_set_length(&t, npoints, _state); - for(j=0; j<=nvars-1; j++) - { - ae_v_move(&t.ptr.p_double[0], 1, &x->ptr.pp_double[0][j], x->stride, ae_v_len(0,npoints-1)); - samplemoments(&t, npoints, &mean, &variance, &skewness, &kurtosis, _state); - m.ptr.p_double[j] = mean; - } - - /* - * Center, apply SVD, prepare output - */ - ae_matrix_set_length(&a, ae_maxint(npoints, nvars, _state), nvars, _state); - for(i=0; i<=npoints-1; i++) - { - ae_v_move(&a.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - ae_v_sub(&a.ptr.pp_double[i][0], 1, &m.ptr.p_double[0], 1, ae_v_len(0,nvars-1)); - } - for(i=npoints; i<=nvars-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - if( !rmatrixsvd(&a, ae_maxint(npoints, nvars, _state), nvars, 0, 1, 2, s2, &u, &vt, _state) ) - { - *info = -4; - ae_frame_leave(_state); - return; - } - if( npoints!=1 ) - { - for(i=0; i<=nvars-1; i++) - { - s2->ptr.p_double[i] = ae_sqr(s2->ptr.p_double[i], _state)/(npoints-1); - } - } - ae_matrix_set_length(v, nvars, nvars, _state); - copyandtranspose(&vt, 0, nvars-1, 0, nvars-1, v, 0, nvars-1, 0, nvars-1, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Principal components analysis - -This function performs truncated PCA, i.e. returns just a few most important -directions. - -Internally it uses iterative eigensolver which is very efficient when only -a minor fraction of full basis is required. Thus, if you need full basis, -it is better to use pcabuildbasis() function. - -It should be noted that, unlike LDA, PCA does not use class labels. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - dataset, array[0..NPoints-1,0..NVars-1]. - matrix contains ONLY INDEPENDENT VARIABLES. - NPoints - dataset size, NPoints>=0 - NVars - number of independent variables, NVars>=1 - NNeeded - number of requested components, in [1,NVars] range; - this function is efficient only for NNeeded<=0, "PCATruncatedSubspace: npoints<0", _state); - ae_assert(nvars>=1, "PCATruncatedSubspace: nvars<1", _state); - ae_assert(nneeded>0, "PCATruncatedSubspace: nneeded<1", _state); - ae_assert(nneeded<=nvars, "PCATruncatedSubspace: nneeded>nvars", _state); - ae_assert(maxits>=0, "PCATruncatedSubspace: maxits<0", _state); - ae_assert(ae_isfinite(eps, _state)&&ae_fp_greater_eq(eps,(double)(0)), "PCATruncatedSubspace: eps<0 or is not finite", _state); - ae_assert(x->rows>=npoints, "PCATruncatedSubspace: rows(x)cols>=nvars||npoints==0, "PCATruncatedSubspace: cols(x)ptr.p_double[i] = (double)(0); - } - for(i=0; i<=nvars-1; i++) - { - for(j=0; j<=nneeded-1; j++) - { - if( i==j ) - { - v->ptr.pp_double[i][j] = (double)(1); - } - else - { - v->ptr.pp_double[i][j] = (double)(0); - } - } - } - ae_frame_leave(_state); - return; - } - - /* - * Center matrix - */ - ae_vector_set_length(&means, nvars, _state); - for(i=0; i<=nvars-1; i++) - { - means.ptr.p_double[i] = (double)(0); - } - vv = (double)1/(double)npoints; - for(i=0; i<=npoints-1; i++) - { - ae_v_addd(&means.ptr.p_double[0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1), vv); - } - ae_matrix_set_length(&a, npoints, nvars, _state); - for(i=0; i<=npoints-1; i++) - { - ae_v_move(&a.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - ae_v_sub(&a.ptr.pp_double[i][0], 1, &means.ptr.p_double[0], 1, ae_v_len(0,nvars-1)); - } - - /* - * Find eigenvalues with subspace iteration solver - */ - eigsubspacecreate(nvars, nneeded, &solver, _state); - eigsubspacesetcond(&solver, eps, maxits, _state); - eigsubspaceoocstart(&solver, 0, _state); - while(eigsubspaceooccontinue(&solver, _state)) - { - ae_assert(solver.requesttype==0, "PCATruncatedSubspace: integrity check failed", _state); - k = solver.requestsize; - rmatrixsetlengthatleast(&b, npoints, k, _state); - rmatrixgemm(npoints, k, nvars, 1.0, &a, 0, 0, 0, &solver.x, 0, 0, 0, 0.0, &b, 0, 0, _state); - rmatrixgemm(nvars, k, npoints, 1.0, &a, 0, 0, 1, &b, 0, 0, 0, 0.0, &solver.ax, 0, 0, _state); - } - eigsubspaceoocstop(&solver, s2, v, &rep, _state); - if( npoints!=1 ) - { - for(i=0; i<=nneeded-1; i++) - { - s2->ptr.p_double[i] = s2->ptr.p_double[i]/(npoints-1); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Sparse truncated principal components analysis - -This function performs sparse truncated PCA, i.e. returns just a few most -important principal components for a sparse input X. - -Internally it uses iterative eigensolver which is very efficient when only -a minor fraction of full basis is required. - -It should be noted that, unlike LDA, PCA does not use class labels. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - sparse dataset, sparse npoints*nvars matrix. It is - recommended to use CRS sparse storage format; non-CRS - input will be internally converted to CRS. - Matrix contains ONLY INDEPENDENT VARIABLES, and must - be EXACTLY npoints*nvars. - NPoints - dataset size, NPoints>=0 - NVars - number of independent variables, NVars>=1 - NNeeded - number of requested components, in [1,NVars] range; - this function is efficient only for NNeeded<=0, "PCATruncatedSubspaceSparse: npoints<0", _state); - ae_assert(nvars>=1, "PCATruncatedSubspaceSparse: nvars<1", _state); - ae_assert(nneeded>0, "PCATruncatedSubspaceSparse: nneeded<1", _state); - ae_assert(nneeded<=nvars, "PCATruncatedSubspaceSparse: nneeded>nvars", _state); - ae_assert(maxits>=0, "PCATruncatedSubspaceSparse: maxits<0", _state); - ae_assert(ae_isfinite(eps, _state)&&ae_fp_greater_eq(eps,(double)(0)), "PCATruncatedSubspaceSparse: eps<0 or is not finite", _state); - if( npoints>0 ) - { - ae_assert(sparsegetnrows(x, _state)==npoints, "PCATruncatedSubspaceSparse: rows(x)!=npoints", _state); - ae_assert(sparsegetncols(x, _state)==nvars, "PCATruncatedSubspaceSparse: cols(x)!=nvars", _state); - } - - /* - * Special case: NPoints=0 - */ - if( npoints==0 ) - { - ae_vector_set_length(s2, nneeded, _state); - ae_matrix_set_length(v, nvars, nneeded, _state); - for(i=0; i<=nvars-1; i++) - { - s2->ptr.p_double[i] = (double)(0); - } - for(i=0; i<=nvars-1; i++) - { - for(j=0; j<=nneeded-1; j++) - { - if( i==j ) - { - v->ptr.pp_double[i][j] = (double)(1); - } - else - { - v->ptr.pp_double[i][j] = (double)(0); - } - } - } - ae_frame_leave(_state); - return; - } - - /* - * If input data are not in CRS format, perform conversion to CRS - */ - if( !sparseiscrs(x, _state) ) - { - sparsecopytocrs(x, &xcrs, _state); - pcatruncatedsubspacesparse(&xcrs, npoints, nvars, nneeded, eps, maxits, s2, v, _state); - ae_frame_leave(_state); - return; - } - - /* - * Initialize parameters, prepare buffers - */ - ae_vector_set_length(&b1, npoints, _state); - ae_vector_set_length(&z1, nvars, _state); - if( ae_fp_eq(eps,(double)(0))&&maxits==0 ) - { - eps = 1.0E-6; - } - if( maxits==0 ) - { - maxits = 50+2*nvars; - } - - /* - * Calculate mean values - */ - vv = (double)1/(double)npoints; - for(i=0; i<=npoints-1; i++) - { - b1.ptr.p_double[i] = vv; - } - sparsemtv(x, &b1, &means, _state); - - /* - * Find eigenvalues with subspace iteration solver - */ - eigsubspacecreate(nvars, nneeded, &solver, _state); - eigsubspacesetcond(&solver, eps, maxits, _state); - eigsubspaceoocstart(&solver, 0, _state); - while(eigsubspaceooccontinue(&solver, _state)) - { - ae_assert(solver.requesttype==0, "PCATruncatedSubspace: integrity check failed", _state); - for(k=0; k<=solver.requestsize-1; k++) - { - - /* - * Calculate B1=(X-meansX)*Zk - */ - ae_v_move(&z1.ptr.p_double[0], 1, &solver.x.ptr.pp_double[0][k], solver.x.stride, ae_v_len(0,nvars-1)); - sparsemv(x, &z1, &b1, _state); - vv = ae_v_dotproduct(&solver.x.ptr.pp_double[0][k], solver.x.stride, &means.ptr.p_double[0], 1, ae_v_len(0,nvars-1)); - for(i=0; i<=npoints-1; i++) - { - b1.ptr.p_double[i] = b1.ptr.p_double[i]-vv; - } - - /* - * Calculate (X-meansX)^T*B1 - */ - sparsemtv(x, &b1, &c1, _state); - vv = (double)(0); - for(i=0; i<=npoints-1; i++) - { - vv = vv+b1.ptr.p_double[i]; - } - for(j=0; j<=nvars-1; j++) - { - solver.ax.ptr.pp_double[j][k] = c1.ptr.p_double[j]-vv*means.ptr.p_double[j]; - } - } - } - eigsubspaceoocstop(&solver, s2, v, &rep, _state); - if( npoints!=1 ) - { - for(i=0; i<=nneeded-1; i++) - { - s2->ptr.p_double[i] = s2->ptr.p_double[i]/(npoints-1); - } - } - ae_frame_leave(_state); -} - - -#endif -#if defined(AE_COMPILE_BDSS) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This set of routines (DSErrAllocate, DSErrAccumulate, DSErrFinish) -calculates different error functions (classification error, cross-entropy, -rms, avg, avg.rel errors). - -1. DSErrAllocate prepares buffer. -2. DSErrAccumulate accumulates individual errors: - * Y contains predicted output (posterior probabilities for classification) - * DesiredY contains desired output (class number for classification) -3. DSErrFinish outputs results: - * Buf[0] contains relative classification error (zero for regression tasks) - * Buf[1] contains avg. cross-entropy (zero for regression tasks) - * Buf[2] contains rms error (regression, classification) - * Buf[3] contains average error (regression, classification) - * Buf[4] contains average relative error (regression, classification) - -NOTES(1): - "NClasses>0" means that we have classification task. - "NClasses<0" means regression task with -NClasses real outputs. - -NOTES(2): - rms. avg, avg.rel errors for classification tasks are interpreted as - errors in posterior probabilities with respect to probabilities given - by training/test set. - - -- ALGLIB -- - Copyright 11.01.2009 by Bochkanov Sergey -*************************************************************************/ -void dserrallocate(ae_int_t nclasses, - /* Real */ ae_vector* buf, - ae_state *_state) -{ - - ae_vector_clear(buf); - - ae_vector_set_length(buf, 7+1, _state); - buf->ptr.p_double[0] = (double)(0); - buf->ptr.p_double[1] = (double)(0); - buf->ptr.p_double[2] = (double)(0); - buf->ptr.p_double[3] = (double)(0); - buf->ptr.p_double[4] = (double)(0); - buf->ptr.p_double[5] = (double)(nclasses); - buf->ptr.p_double[6] = (double)(0); - buf->ptr.p_double[7] = (double)(0); -} - - -/************************************************************************* -See DSErrAllocate for comments on this routine. - - -- ALGLIB -- - Copyright 11.01.2009 by Bochkanov Sergey -*************************************************************************/ -void dserraccumulate(/* Real */ ae_vector* buf, - /* Real */ ae_vector* y, - /* Real */ ae_vector* desiredy, - ae_state *_state) -{ - ae_int_t nclasses; - ae_int_t nout; - ae_int_t offs; - ae_int_t mmax; - ae_int_t rmax; - ae_int_t j; - double v; - double ev; - - - offs = 5; - nclasses = ae_round(buf->ptr.p_double[offs], _state); - if( nclasses>0 ) - { - - /* - * Classification - */ - rmax = ae_round(desiredy->ptr.p_double[0], _state); - mmax = 0; - for(j=1; j<=nclasses-1; j++) - { - if( ae_fp_greater(y->ptr.p_double[j],y->ptr.p_double[mmax]) ) - { - mmax = j; - } - } - if( mmax!=rmax ) - { - buf->ptr.p_double[0] = buf->ptr.p_double[0]+1; - } - if( ae_fp_greater(y->ptr.p_double[rmax],(double)(0)) ) - { - buf->ptr.p_double[1] = buf->ptr.p_double[1]-ae_log(y->ptr.p_double[rmax], _state); - } - else - { - buf->ptr.p_double[1] = buf->ptr.p_double[1]+ae_log(ae_maxrealnumber, _state); - } - for(j=0; j<=nclasses-1; j++) - { - v = y->ptr.p_double[j]; - if( j==rmax ) - { - ev = (double)(1); - } - else - { - ev = (double)(0); - } - buf->ptr.p_double[2] = buf->ptr.p_double[2]+ae_sqr(v-ev, _state); - buf->ptr.p_double[3] = buf->ptr.p_double[3]+ae_fabs(v-ev, _state); - if( ae_fp_neq(ev,(double)(0)) ) - { - buf->ptr.p_double[4] = buf->ptr.p_double[4]+ae_fabs((v-ev)/ev, _state); - buf->ptr.p_double[offs+2] = buf->ptr.p_double[offs+2]+1; - } - } - buf->ptr.p_double[offs+1] = buf->ptr.p_double[offs+1]+1; - } - else - { - - /* - * Regression - */ - nout = -nclasses; - rmax = 0; - for(j=1; j<=nout-1; j++) - { - if( ae_fp_greater(desiredy->ptr.p_double[j],desiredy->ptr.p_double[rmax]) ) - { - rmax = j; - } - } - mmax = 0; - for(j=1; j<=nout-1; j++) - { - if( ae_fp_greater(y->ptr.p_double[j],y->ptr.p_double[mmax]) ) - { - mmax = j; - } - } - if( mmax!=rmax ) - { - buf->ptr.p_double[0] = buf->ptr.p_double[0]+1; - } - for(j=0; j<=nout-1; j++) - { - v = y->ptr.p_double[j]; - ev = desiredy->ptr.p_double[j]; - buf->ptr.p_double[2] = buf->ptr.p_double[2]+ae_sqr(v-ev, _state); - buf->ptr.p_double[3] = buf->ptr.p_double[3]+ae_fabs(v-ev, _state); - if( ae_fp_neq(ev,(double)(0)) ) - { - buf->ptr.p_double[4] = buf->ptr.p_double[4]+ae_fabs((v-ev)/ev, _state); - buf->ptr.p_double[offs+2] = buf->ptr.p_double[offs+2]+1; - } - } - buf->ptr.p_double[offs+1] = buf->ptr.p_double[offs+1]+1; - } -} - - -/************************************************************************* -See DSErrAllocate for comments on this routine. - - -- ALGLIB -- - Copyright 11.01.2009 by Bochkanov Sergey -*************************************************************************/ -void dserrfinish(/* Real */ ae_vector* buf, ae_state *_state) -{ - ae_int_t nout; - ae_int_t offs; - - - offs = 5; - nout = ae_iabs(ae_round(buf->ptr.p_double[offs], _state), _state); - if( ae_fp_neq(buf->ptr.p_double[offs+1],(double)(0)) ) - { - buf->ptr.p_double[0] = buf->ptr.p_double[0]/buf->ptr.p_double[offs+1]; - buf->ptr.p_double[1] = buf->ptr.p_double[1]/buf->ptr.p_double[offs+1]; - buf->ptr.p_double[2] = ae_sqrt(buf->ptr.p_double[2]/(nout*buf->ptr.p_double[offs+1]), _state); - buf->ptr.p_double[3] = buf->ptr.p_double[3]/(nout*buf->ptr.p_double[offs+1]); - } - if( ae_fp_neq(buf->ptr.p_double[offs+2],(double)(0)) ) - { - buf->ptr.p_double[4] = buf->ptr.p_double[4]/buf->ptr.p_double[offs+2]; - } -} - - -/************************************************************************* - - -- ALGLIB -- - Copyright 19.05.2008 by Bochkanov Sergey -*************************************************************************/ -void dsnormalize(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t* info, - /* Real */ ae_vector* means, - /* Real */ ae_vector* sigmas, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_vector tmp; - double mean; - double variance; - double skewness; - double kurtosis; - - ae_frame_make(_state, &_frame_block); - memset(&tmp, 0, sizeof(tmp)); - *info = 0; - ae_vector_clear(means); - ae_vector_clear(sigmas); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - - - /* - * Test parameters - */ - if( npoints<=0||nvars<1 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - *info = 1; - - /* - * Standartization - */ - ae_vector_set_length(means, nvars-1+1, _state); - ae_vector_set_length(sigmas, nvars-1+1, _state); - ae_vector_set_length(&tmp, npoints-1+1, _state); - for(j=0; j<=nvars-1; j++) - { - ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][j], xy->stride, ae_v_len(0,npoints-1)); - samplemoments(&tmp, npoints, &mean, &variance, &skewness, &kurtosis, _state); - means->ptr.p_double[j] = mean; - sigmas->ptr.p_double[j] = ae_sqrt(variance, _state); - if( ae_fp_eq(sigmas->ptr.p_double[j],(double)(0)) ) - { - sigmas->ptr.p_double[j] = (double)(1); - } - for(i=0; i<=npoints-1; i++) - { - xy->ptr.pp_double[i][j] = (xy->ptr.pp_double[i][j]-means->ptr.p_double[j])/sigmas->ptr.p_double[j]; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* - - -- ALGLIB -- - Copyright 19.05.2008 by Bochkanov Sergey -*************************************************************************/ -void dsnormalizec(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t* info, - /* Real */ ae_vector* means, - /* Real */ ae_vector* sigmas, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t j; - ae_vector tmp; - double mean; - double variance; - double skewness; - double kurtosis; - - ae_frame_make(_state, &_frame_block); - memset(&tmp, 0, sizeof(tmp)); - *info = 0; - ae_vector_clear(means); - ae_vector_clear(sigmas); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - - - /* - * Test parameters - */ - if( npoints<=0||nvars<1 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - *info = 1; - - /* - * Standartization - */ - ae_vector_set_length(means, nvars-1+1, _state); - ae_vector_set_length(sigmas, nvars-1+1, _state); - ae_vector_set_length(&tmp, npoints-1+1, _state); - for(j=0; j<=nvars-1; j++) - { - ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][j], xy->stride, ae_v_len(0,npoints-1)); - samplemoments(&tmp, npoints, &mean, &variance, &skewness, &kurtosis, _state); - means->ptr.p_double[j] = mean; - sigmas->ptr.p_double[j] = ae_sqrt(variance, _state); - if( ae_fp_eq(sigmas->ptr.p_double[j],(double)(0)) ) - { - sigmas->ptr.p_double[j] = (double)(1); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* - - -- ALGLIB -- - Copyright 19.05.2008 by Bochkanov Sergey -*************************************************************************/ -double dsgetmeanmindistance(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_vector tmp; - ae_vector tmp2; - double v; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&tmp, 0, sizeof(tmp)); - memset(&tmp2, 0, sizeof(tmp2)); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp2, 0, DT_REAL, _state, ae_true); - - - /* - * Test parameters - */ - if( npoints<=0||nvars<1 ) - { - result = (double)(0); - ae_frame_leave(_state); - return result; - } - - /* - * Process - */ - ae_vector_set_length(&tmp, npoints-1+1, _state); - for(i=0; i<=npoints-1; i++) - { - tmp.ptr.p_double[i] = ae_maxrealnumber; - } - ae_vector_set_length(&tmp2, nvars-1+1, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=i+1; j<=npoints-1; j++) - { - ae_v_move(&tmp2.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - ae_v_sub(&tmp2.ptr.p_double[0], 1, &xy->ptr.pp_double[j][0], 1, ae_v_len(0,nvars-1)); - v = ae_v_dotproduct(&tmp2.ptr.p_double[0], 1, &tmp2.ptr.p_double[0], 1, ae_v_len(0,nvars-1)); - v = ae_sqrt(v, _state); - tmp.ptr.p_double[i] = ae_minreal(tmp.ptr.p_double[i], v, _state); - tmp.ptr.p_double[j] = ae_minreal(tmp.ptr.p_double[j], v, _state); - } - } - result = (double)(0); - for(i=0; i<=npoints-1; i++) - { - result = result+tmp.ptr.p_double[i]/npoints; - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* - - -- ALGLIB -- - Copyright 19.05.2008 by Bochkanov Sergey -*************************************************************************/ -void dstie(/* Real */ ae_vector* a, - ae_int_t n, - /* Integer */ ae_vector* ties, - ae_int_t* tiecount, - /* Integer */ ae_vector* p1, - /* Integer */ ae_vector* p2, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t k; - ae_vector tmp; - - ae_frame_make(_state, &_frame_block); - memset(&tmp, 0, sizeof(tmp)); - ae_vector_clear(ties); - *tiecount = 0; - ae_vector_clear(p1); - ae_vector_clear(p2); - ae_vector_init(&tmp, 0, DT_INT, _state, ae_true); - - - /* - * Special case - */ - if( n<=0 ) - { - *tiecount = 0; - ae_frame_leave(_state); - return; - } - - /* - * Sort A - */ - tagsort(a, n, p1, p2, _state); - - /* - * Process ties - */ - *tiecount = 1; - for(i=1; i<=n-1; i++) - { - if( ae_fp_neq(a->ptr.p_double[i],a->ptr.p_double[i-1]) ) - { - *tiecount = *tiecount+1; - } - } - ae_vector_set_length(ties, *tiecount+1, _state); - ties->ptr.p_int[0] = 0; - k = 1; - for(i=1; i<=n-1; i++) - { - if( ae_fp_neq(a->ptr.p_double[i],a->ptr.p_double[i-1]) ) - { - ties->ptr.p_int[k] = i; - k = k+1; - } - } - ties->ptr.p_int[*tiecount] = n; - ae_frame_leave(_state); -} - - -/************************************************************************* - - -- ALGLIB -- - Copyright 11.12.2008 by Bochkanov Sergey -*************************************************************************/ -void dstiefasti(/* Real */ ae_vector* a, - /* Integer */ ae_vector* b, - ae_int_t n, - /* Integer */ ae_vector* ties, - ae_int_t* tiecount, - /* Real */ ae_vector* bufr, - /* Integer */ ae_vector* bufi, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t k; - ae_vector tmp; - - ae_frame_make(_state, &_frame_block); - memset(&tmp, 0, sizeof(tmp)); - *tiecount = 0; - ae_vector_init(&tmp, 0, DT_INT, _state, ae_true); - - - /* - * Special case - */ - if( n<=0 ) - { - *tiecount = 0; - ae_frame_leave(_state); - return; - } - - /* - * Sort A - */ - tagsortfasti(a, b, bufr, bufi, n, _state); - - /* - * Process ties - */ - ties->ptr.p_int[0] = 0; - k = 1; - for(i=1; i<=n-1; i++) - { - if( ae_fp_neq(a->ptr.p_double[i],a->ptr.p_double[i-1]) ) - { - ties->ptr.p_int[k] = i; - k = k+1; - } - } - ties->ptr.p_int[k] = n; - *tiecount = k; - ae_frame_leave(_state); -} - - -/************************************************************************* -Optimal binary classification - -Algorithms finds optimal (=with minimal cross-entropy) binary partition. -Internal subroutine. - -INPUT PARAMETERS: - A - array[0..N-1], variable - C - array[0..N-1], class numbers (0 or 1). - N - array size - -OUTPUT PARAMETERS: - Info - completetion code: - * -3, all values of A[] are same (partition is impossible) - * -2, one of C[] is incorrect (<0, >1) - * -1, incorrect pararemets were passed (N<=0). - * 1, OK - Threshold- partiton boundary. Left part contains values which are - strictly less than Threshold. Right part contains values - which are greater than or equal to Threshold. - PAL, PBL- probabilities P(0|v=Threshold) and P(1|v>=Threshold) - CVE - cross-validation estimate of cross-entropy - - -- ALGLIB -- - Copyright 22.05.2008 by Bochkanov Sergey -*************************************************************************/ -void dsoptimalsplit2(/* Real */ ae_vector* a, - /* Integer */ ae_vector* c, - ae_int_t n, - ae_int_t* info, - double* threshold, - double* pal, - double* pbl, - double* par, - double* pbr, - double* cve, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _a; - ae_vector _c; - ae_int_t i; - ae_int_t t; - double s; - ae_vector ties; - ae_int_t tiecount; - ae_vector p1; - ae_vector p2; - ae_int_t k; - ae_int_t koptimal; - double pak; - double pbk; - double cvoptimal; - double cv; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&_c, 0, sizeof(_c)); - memset(&ties, 0, sizeof(ties)); - memset(&p1, 0, sizeof(p1)); - memset(&p2, 0, sizeof(p2)); - ae_vector_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_vector_init_copy(&_c, c, _state, ae_true); - c = &_c; - *info = 0; - *threshold = 0; - *pal = 0; - *pbl = 0; - *par = 0; - *pbr = 0; - *cve = 0; - ae_vector_init(&ties, 0, DT_INT, _state, ae_true); - ae_vector_init(&p1, 0, DT_INT, _state, ae_true); - ae_vector_init(&p2, 0, DT_INT, _state, ae_true); - - - /* - * Test for errors in inputs - */ - if( n<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - if( c->ptr.p_int[i]!=0&&c->ptr.p_int[i]!=1 ) - { - *info = -2; - ae_frame_leave(_state); - return; - } - } - *info = 1; - - /* - * Tie - */ - dstie(a, n, &ties, &tiecount, &p1, &p2, _state); - for(i=0; i<=n-1; i++) - { - if( p2.ptr.p_int[i]!=i ) - { - t = c->ptr.p_int[i]; - c->ptr.p_int[i] = c->ptr.p_int[p2.ptr.p_int[i]]; - c->ptr.p_int[p2.ptr.p_int[i]] = t; - } - } - - /* - * Special case: number of ties is 1. - * - * NOTE: we assume that P[i,j] equals to 0 or 1, - * intermediate values are not allowed. - */ - if( tiecount==1 ) - { - *info = -3; - ae_frame_leave(_state); - return; - } - - /* - * General case, number of ties > 1 - * - * NOTE: we assume that P[i,j] equals to 0 or 1, - * intermediate values are not allowed. - */ - *pal = (double)(0); - *pbl = (double)(0); - *par = (double)(0); - *pbr = (double)(0); - for(i=0; i<=n-1; i++) - { - if( c->ptr.p_int[i]==0 ) - { - *par = *par+1; - } - if( c->ptr.p_int[i]==1 ) - { - *pbr = *pbr+1; - } - } - koptimal = -1; - cvoptimal = ae_maxrealnumber; - for(k=0; k<=tiecount-2; k++) - { - - /* - * first, obtain information about K-th tie which is - * moved from R-part to L-part - */ - pak = (double)(0); - pbk = (double)(0); - for(i=ties.ptr.p_int[k]; i<=ties.ptr.p_int[k+1]-1; i++) - { - if( c->ptr.p_int[i]==0 ) - { - pak = pak+1; - } - if( c->ptr.p_int[i]==1 ) - { - pbk = pbk+1; - } - } - - /* - * Calculate cross-validation CE - */ - cv = (double)(0); - cv = cv-bdss_xlny(*pal+pak, (*pal+pak)/(*pal+pak+(*pbl)+pbk+1), _state); - cv = cv-bdss_xlny(*pbl+pbk, (*pbl+pbk)/(*pal+pak+1+(*pbl)+pbk), _state); - cv = cv-bdss_xlny(*par-pak, (*par-pak)/(*par-pak+(*pbr)-pbk+1), _state); - cv = cv-bdss_xlny(*pbr-pbk, (*pbr-pbk)/(*par-pak+1+(*pbr)-pbk), _state); - - /* - * Compare with best - */ - if( ae_fp_less(cv,cvoptimal) ) - { - cvoptimal = cv; - koptimal = k; - } - - /* - * update - */ - *pal = *pal+pak; - *pbl = *pbl+pbk; - *par = *par-pak; - *pbr = *pbr-pbk; - } - *cve = cvoptimal; - *threshold = 0.5*(a->ptr.p_double[ties.ptr.p_int[koptimal]]+a->ptr.p_double[ties.ptr.p_int[koptimal+1]]); - *pal = (double)(0); - *pbl = (double)(0); - *par = (double)(0); - *pbr = (double)(0); - for(i=0; i<=n-1; i++) - { - if( ae_fp_less(a->ptr.p_double[i],*threshold) ) - { - if( c->ptr.p_int[i]==0 ) - { - *pal = *pal+1; - } - else - { - *pbl = *pbl+1; - } - } - else - { - if( c->ptr.p_int[i]==0 ) - { - *par = *par+1; - } - else - { - *pbr = *pbr+1; - } - } - } - s = *pal+(*pbl); - *pal = *pal/s; - *pbl = *pbl/s; - s = *par+(*pbr); - *par = *par/s; - *pbr = *pbr/s; - ae_frame_leave(_state); -} - - -/************************************************************************* -Optimal partition, internal subroutine. Fast version. - -Accepts: - A array[0..N-1] array of attributes array[0..N-1] - C array[0..N-1] array of class labels - TiesBuf array[0..N] temporaries (ties) - CntBuf array[0..2*NC-1] temporaries (counts) - Alpha centering factor (0<=alpha<=1, recommended value - 0.05) - BufR array[0..N-1] temporaries - BufI array[0..N-1] temporaries - -Output: - Info error code (">0"=OK, "<0"=bad) - RMS training set RMS error - CVRMS leave-one-out RMS error - -Note: - content of all arrays is changed by subroutine; - it doesn't allocate temporaries. - - -- ALGLIB -- - Copyright 11.12.2008 by Bochkanov Sergey -*************************************************************************/ -void dsoptimalsplit2fast(/* Real */ ae_vector* a, - /* Integer */ ae_vector* c, - /* Integer */ ae_vector* tiesbuf, - /* Integer */ ae_vector* cntbuf, - /* Real */ ae_vector* bufr, - /* Integer */ ae_vector* bufi, - ae_int_t n, - ae_int_t nc, - double alpha, - ae_int_t* info, - double* threshold, - double* rms, - double* cvrms, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - ae_int_t cl; - ae_int_t tiecount; - double cbest; - double cc; - ae_int_t koptimal; - ae_int_t sl; - ae_int_t sr; - double v; - double w; - double x; - - *info = 0; - *threshold = 0; - *rms = 0; - *cvrms = 0; - - - /* - * Test for errors in inputs - */ - if( n<=0||nc<2 ) - { - *info = -1; - return; - } - for(i=0; i<=n-1; i++) - { - if( c->ptr.p_int[i]<0||c->ptr.p_int[i]>=nc ) - { - *info = -2; - return; - } - } - *info = 1; - - /* - * Tie - */ - dstiefasti(a, c, n, tiesbuf, &tiecount, bufr, bufi, _state); - - /* - * Special case: number of ties is 1. - */ - if( tiecount==1 ) - { - *info = -3; - return; - } - - /* - * General case, number of ties > 1 - */ - for(i=0; i<=2*nc-1; i++) - { - cntbuf->ptr.p_int[i] = 0; - } - for(i=0; i<=n-1; i++) - { - cntbuf->ptr.p_int[nc+c->ptr.p_int[i]] = cntbuf->ptr.p_int[nc+c->ptr.p_int[i]]+1; - } - koptimal = -1; - *threshold = a->ptr.p_double[n-1]; - cbest = ae_maxrealnumber; - sl = 0; - sr = n; - for(k=0; k<=tiecount-2; k++) - { - - /* - * first, move Kth tie from right to left - */ - for(i=tiesbuf->ptr.p_int[k]; i<=tiesbuf->ptr.p_int[k+1]-1; i++) - { - cl = c->ptr.p_int[i]; - cntbuf->ptr.p_int[cl] = cntbuf->ptr.p_int[cl]+1; - cntbuf->ptr.p_int[nc+cl] = cntbuf->ptr.p_int[nc+cl]-1; - } - sl = sl+(tiesbuf->ptr.p_int[k+1]-tiesbuf->ptr.p_int[k]); - sr = sr-(tiesbuf->ptr.p_int[k+1]-tiesbuf->ptr.p_int[k]); - - /* - * Calculate RMS error - */ - v = (double)(0); - for(i=0; i<=nc-1; i++) - { - w = (double)(cntbuf->ptr.p_int[i]); - v = v+w*ae_sqr(w/sl-1, _state); - v = v+(sl-w)*ae_sqr(w/sl, _state); - w = (double)(cntbuf->ptr.p_int[nc+i]); - v = v+w*ae_sqr(w/sr-1, _state); - v = v+(sr-w)*ae_sqr(w/sr, _state); - } - v = ae_sqrt(v/(nc*n), _state); - - /* - * Compare with best - */ - x = (double)(2*sl)/(double)(sl+sr)-1; - cc = v*(1-alpha+alpha*ae_sqr(x, _state)); - if( ae_fp_less(cc,cbest) ) - { - - /* - * store split - */ - *rms = v; - koptimal = k; - cbest = cc; - - /* - * calculate CVRMS error - */ - *cvrms = (double)(0); - for(i=0; i<=nc-1; i++) - { - if( sl>1 ) - { - w = (double)(cntbuf->ptr.p_int[i]); - *cvrms = *cvrms+w*ae_sqr((w-1)/(sl-1)-1, _state); - *cvrms = *cvrms+(sl-w)*ae_sqr(w/(sl-1), _state); - } - else - { - w = (double)(cntbuf->ptr.p_int[i]); - *cvrms = *cvrms+w*ae_sqr((double)1/(double)nc-1, _state); - *cvrms = *cvrms+(sl-w)*ae_sqr((double)1/(double)nc, _state); - } - if( sr>1 ) - { - w = (double)(cntbuf->ptr.p_int[nc+i]); - *cvrms = *cvrms+w*ae_sqr((w-1)/(sr-1)-1, _state); - *cvrms = *cvrms+(sr-w)*ae_sqr(w/(sr-1), _state); - } - else - { - w = (double)(cntbuf->ptr.p_int[nc+i]); - *cvrms = *cvrms+w*ae_sqr((double)1/(double)nc-1, _state); - *cvrms = *cvrms+(sr-w)*ae_sqr((double)1/(double)nc, _state); - } - } - *cvrms = ae_sqrt(*cvrms/(nc*n), _state); - } - } - - /* - * Calculate threshold. - * Code is a bit complicated because there can be such - * numbers that 0.5(A+B) equals to A or B (if A-B=epsilon) - */ - *threshold = 0.5*(a->ptr.p_double[tiesbuf->ptr.p_int[koptimal]]+a->ptr.p_double[tiesbuf->ptr.p_int[koptimal+1]]); - if( ae_fp_less_eq(*threshold,a->ptr.p_double[tiesbuf->ptr.p_int[koptimal]]) ) - { - *threshold = a->ptr.p_double[tiesbuf->ptr.p_int[koptimal+1]]; - } -} - - -/************************************************************************* -Automatic non-optimal discretization, internal subroutine. - - -- ALGLIB -- - Copyright 22.05.2008 by Bochkanov Sergey -*************************************************************************/ -void dssplitk(/* Real */ ae_vector* a, - /* Integer */ ae_vector* c, - ae_int_t n, - ae_int_t nc, - ae_int_t kmax, - ae_int_t* info, - /* Real */ ae_vector* thresholds, - ae_int_t* ni, - double* cve, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _a; - ae_vector _c; - ae_int_t i; - ae_int_t j; - ae_int_t j1; - ae_int_t k; - ae_vector ties; - ae_int_t tiecount; - ae_vector p1; - ae_vector p2; - ae_vector cnt; - double v2; - ae_int_t bestk; - double bestcve; - ae_vector bestsizes; - double curcve; - ae_vector cursizes; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&_c, 0, sizeof(_c)); - memset(&ties, 0, sizeof(ties)); - memset(&p1, 0, sizeof(p1)); - memset(&p2, 0, sizeof(p2)); - memset(&cnt, 0, sizeof(cnt)); - memset(&bestsizes, 0, sizeof(bestsizes)); - memset(&cursizes, 0, sizeof(cursizes)); - ae_vector_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_vector_init_copy(&_c, c, _state, ae_true); - c = &_c; - *info = 0; - ae_vector_clear(thresholds); - *ni = 0; - *cve = 0; - ae_vector_init(&ties, 0, DT_INT, _state, ae_true); - ae_vector_init(&p1, 0, DT_INT, _state, ae_true); - ae_vector_init(&p2, 0, DT_INT, _state, ae_true); - ae_vector_init(&cnt, 0, DT_INT, _state, ae_true); - ae_vector_init(&bestsizes, 0, DT_INT, _state, ae_true); - ae_vector_init(&cursizes, 0, DT_INT, _state, ae_true); - - - /* - * Test for errors in inputs - */ - if( (n<=0||nc<2)||kmax<2 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - if( c->ptr.p_int[i]<0||c->ptr.p_int[i]>=nc ) - { - *info = -2; - ae_frame_leave(_state); - return; - } - } - *info = 1; - - /* - * Tie - */ - dstie(a, n, &ties, &tiecount, &p1, &p2, _state); - for(i=0; i<=n-1; i++) - { - if( p2.ptr.p_int[i]!=i ) - { - k = c->ptr.p_int[i]; - c->ptr.p_int[i] = c->ptr.p_int[p2.ptr.p_int[i]]; - c->ptr.p_int[p2.ptr.p_int[i]] = k; - } - } - - /* - * Special cases - */ - if( tiecount==1 ) - { - *info = -3; - ae_frame_leave(_state); - return; - } - - /* - * General case: - * 0. allocate arrays - */ - kmax = ae_minint(kmax, tiecount, _state); - ae_vector_set_length(&bestsizes, kmax-1+1, _state); - ae_vector_set_length(&cursizes, kmax-1+1, _state); - ae_vector_set_length(&cnt, nc-1+1, _state); - - /* - * General case: - * 1. prepare "weak" solution (two subintervals, divided at median) - */ - v2 = ae_maxrealnumber; - j = -1; - for(i=1; i<=tiecount-1; i++) - { - if( ae_fp_less(ae_fabs(ties.ptr.p_int[i]-0.5*(n-1), _state),v2) ) - { - v2 = ae_fabs(ties.ptr.p_int[i]-0.5*n, _state); - j = i; - } - } - ae_assert(j>0, "DSSplitK: internal error #1!", _state); - bestk = 2; - bestsizes.ptr.p_int[0] = ties.ptr.p_int[j]; - bestsizes.ptr.p_int[1] = n-j; - bestcve = (double)(0); - for(i=0; i<=nc-1; i++) - { - cnt.ptr.p_int[i] = 0; - } - for(i=0; i<=j-1; i++) - { - bdss_tieaddc(c, &ties, i, nc, &cnt, _state); - } - bestcve = bestcve+bdss_getcv(&cnt, nc, _state); - for(i=0; i<=nc-1; i++) - { - cnt.ptr.p_int[i] = 0; - } - for(i=j; i<=tiecount-1; i++) - { - bdss_tieaddc(c, &ties, i, nc, &cnt, _state); - } - bestcve = bestcve+bdss_getcv(&cnt, nc, _state); - - /* - * General case: - * 2. Use greedy algorithm to find sub-optimal split in O(KMax*N) time - */ - for(k=2; k<=kmax; k++) - { - - /* - * Prepare greedy K-interval split - */ - for(i=0; i<=k-1; i++) - { - cursizes.ptr.p_int[i] = 0; - } - i = 0; - j = 0; - while(j<=tiecount-1&&i<=k-1) - { - - /* - * Rule: I-th bin is empty, fill it - */ - if( cursizes.ptr.p_int[i]==0 ) - { - cursizes.ptr.p_int[i] = ties.ptr.p_int[j+1]-ties.ptr.p_int[j]; - j = j+1; - continue; - } - - /* - * Rule: (K-1-I) bins left, (K-1-I) ties left (1 tie per bin); next bin - */ - if( tiecount-j==k-1-i ) - { - i = i+1; - continue; - } - - /* - * Rule: last bin, always place in current - */ - if( i==k-1 ) - { - cursizes.ptr.p_int[i] = cursizes.ptr.p_int[i]+ties.ptr.p_int[j+1]-ties.ptr.p_int[j]; - j = j+1; - continue; - } - - /* - * Place J-th tie in I-th bin, or leave for I+1-th bin. - */ - if( ae_fp_less(ae_fabs(cursizes.ptr.p_int[i]+ties.ptr.p_int[j+1]-ties.ptr.p_int[j]-(double)n/(double)k, _state),ae_fabs(cursizes.ptr.p_int[i]-(double)n/(double)k, _state)) ) - { - cursizes.ptr.p_int[i] = cursizes.ptr.p_int[i]+ties.ptr.p_int[j+1]-ties.ptr.p_int[j]; - j = j+1; - } - else - { - i = i+1; - } - } - ae_assert(cursizes.ptr.p_int[k-1]!=0&&j==tiecount, "DSSplitK: internal error #1", _state); - - /* - * Calculate CVE - */ - curcve = (double)(0); - j = 0; - for(i=0; i<=k-1; i++) - { - for(j1=0; j1<=nc-1; j1++) - { - cnt.ptr.p_int[j1] = 0; - } - for(j1=j; j1<=j+cursizes.ptr.p_int[i]-1; j1++) - { - cnt.ptr.p_int[c->ptr.p_int[j1]] = cnt.ptr.p_int[c->ptr.p_int[j1]]+1; - } - curcve = curcve+bdss_getcv(&cnt, nc, _state); - j = j+cursizes.ptr.p_int[i]; - } - - /* - * Choose best variant - */ - if( ae_fp_less(curcve,bestcve) ) - { - for(i=0; i<=k-1; i++) - { - bestsizes.ptr.p_int[i] = cursizes.ptr.p_int[i]; - } - bestcve = curcve; - bestk = k; - } - } - - /* - * Transform from sizes to thresholds - */ - *cve = bestcve; - *ni = bestk; - ae_vector_set_length(thresholds, *ni-2+1, _state); - j = bestsizes.ptr.p_int[0]; - for(i=1; i<=bestk-1; i++) - { - thresholds->ptr.p_double[i-1] = 0.5*(a->ptr.p_double[j-1]+a->ptr.p_double[j]); - j = j+bestsizes.ptr.p_int[i]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Automatic optimal discretization, internal subroutine. - - -- ALGLIB -- - Copyright 22.05.2008 by Bochkanov Sergey -*************************************************************************/ -void dsoptimalsplitk(/* Real */ ae_vector* a, - /* Integer */ ae_vector* c, - ae_int_t n, - ae_int_t nc, - ae_int_t kmax, - ae_int_t* info, - /* Real */ ae_vector* thresholds, - ae_int_t* ni, - double* cve, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _a; - ae_vector _c; - ae_int_t i; - ae_int_t j; - ae_int_t s; - ae_int_t jl; - ae_int_t jr; - double v2; - ae_vector ties; - ae_int_t tiecount; - ae_vector p1; - ae_vector p2; - double cvtemp; - ae_vector cnt; - ae_vector cnt2; - ae_matrix cv; - ae_matrix splits; - ae_int_t k; - ae_int_t koptimal; - double cvoptimal; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&_c, 0, sizeof(_c)); - memset(&ties, 0, sizeof(ties)); - memset(&p1, 0, sizeof(p1)); - memset(&p2, 0, sizeof(p2)); - memset(&cnt, 0, sizeof(cnt)); - memset(&cnt2, 0, sizeof(cnt2)); - memset(&cv, 0, sizeof(cv)); - memset(&splits, 0, sizeof(splits)); - ae_vector_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_vector_init_copy(&_c, c, _state, ae_true); - c = &_c; - *info = 0; - ae_vector_clear(thresholds); - *ni = 0; - *cve = 0; - ae_vector_init(&ties, 0, DT_INT, _state, ae_true); - ae_vector_init(&p1, 0, DT_INT, _state, ae_true); - ae_vector_init(&p2, 0, DT_INT, _state, ae_true); - ae_vector_init(&cnt, 0, DT_INT, _state, ae_true); - ae_vector_init(&cnt2, 0, DT_INT, _state, ae_true); - ae_matrix_init(&cv, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&splits, 0, 0, DT_INT, _state, ae_true); - - - /* - * Test for errors in inputs - */ - if( (n<=0||nc<2)||kmax<2 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - if( c->ptr.p_int[i]<0||c->ptr.p_int[i]>=nc ) - { - *info = -2; - ae_frame_leave(_state); - return; - } - } - *info = 1; - - /* - * Tie - */ - dstie(a, n, &ties, &tiecount, &p1, &p2, _state); - for(i=0; i<=n-1; i++) - { - if( p2.ptr.p_int[i]!=i ) - { - k = c->ptr.p_int[i]; - c->ptr.p_int[i] = c->ptr.p_int[p2.ptr.p_int[i]]; - c->ptr.p_int[p2.ptr.p_int[i]] = k; - } - } - - /* - * Special cases - */ - if( tiecount==1 ) - { - *info = -3; - ae_frame_leave(_state); - return; - } - - /* - * General case - * Use dynamic programming to find best split in O(KMax*NC*TieCount^2) time - */ - kmax = ae_minint(kmax, tiecount, _state); - ae_matrix_set_length(&cv, kmax-1+1, tiecount-1+1, _state); - ae_matrix_set_length(&splits, kmax-1+1, tiecount-1+1, _state); - ae_vector_set_length(&cnt, nc-1+1, _state); - ae_vector_set_length(&cnt2, nc-1+1, _state); - for(j=0; j<=nc-1; j++) - { - cnt.ptr.p_int[j] = 0; - } - for(j=0; j<=tiecount-1; j++) - { - bdss_tieaddc(c, &ties, j, nc, &cnt, _state); - splits.ptr.pp_int[0][j] = 0; - cv.ptr.pp_double[0][j] = bdss_getcv(&cnt, nc, _state); - } - for(k=1; k<=kmax-1; k++) - { - for(j=0; j<=nc-1; j++) - { - cnt.ptr.p_int[j] = 0; - } - - /* - * Subtask size J in [K..TieCount-1]: - * optimal K-splitting on ties from 0-th to J-th. - */ - for(j=k; j<=tiecount-1; j++) - { - - /* - * Update Cnt - let it contain classes of ties from K-th to J-th - */ - bdss_tieaddc(c, &ties, j, nc, &cnt, _state); - - /* - * Search for optimal split point S in [K..J] - */ - for(i=0; i<=nc-1; i++) - { - cnt2.ptr.p_int[i] = cnt.ptr.p_int[i]; - } - cv.ptr.pp_double[k][j] = cv.ptr.pp_double[k-1][j-1]+bdss_getcv(&cnt2, nc, _state); - splits.ptr.pp_int[k][j] = j; - for(s=k+1; s<=j; s++) - { - - /* - * Update Cnt2 - let it contain classes of ties from S-th to J-th - */ - bdss_tiesubc(c, &ties, s-1, nc, &cnt2, _state); - - /* - * Calculate CVE - */ - cvtemp = cv.ptr.pp_double[k-1][s-1]+bdss_getcv(&cnt2, nc, _state); - if( ae_fp_less(cvtemp,cv.ptr.pp_double[k][j]) ) - { - cv.ptr.pp_double[k][j] = cvtemp; - splits.ptr.pp_int[k][j] = s; - } - } - } - } - - /* - * Choose best partition, output result - */ - koptimal = -1; - cvoptimal = ae_maxrealnumber; - for(k=0; k<=kmax-1; k++) - { - if( ae_fp_less(cv.ptr.pp_double[k][tiecount-1],cvoptimal) ) - { - cvoptimal = cv.ptr.pp_double[k][tiecount-1]; - koptimal = k; - } - } - ae_assert(koptimal>=0, "DSOptimalSplitK: internal error #1!", _state); - if( koptimal==0 ) - { - - /* - * Special case: best partition is one big interval. - * Even 2-partition is not better. - * This is possible when dealing with "weak" predictor variables. - * - * Make binary split as close to the median as possible. - */ - v2 = ae_maxrealnumber; - j = -1; - for(i=1; i<=tiecount-1; i++) - { - if( ae_fp_less(ae_fabs(ties.ptr.p_int[i]-0.5*(n-1), _state),v2) ) - { - v2 = ae_fabs(ties.ptr.p_int[i]-0.5*(n-1), _state); - j = i; - } - } - ae_assert(j>0, "DSOptimalSplitK: internal error #2!", _state); - ae_vector_set_length(thresholds, 0+1, _state); - thresholds->ptr.p_double[0] = 0.5*(a->ptr.p_double[ties.ptr.p_int[j-1]]+a->ptr.p_double[ties.ptr.p_int[j]]); - *ni = 2; - *cve = (double)(0); - for(i=0; i<=nc-1; i++) - { - cnt.ptr.p_int[i] = 0; - } - for(i=0; i<=j-1; i++) - { - bdss_tieaddc(c, &ties, i, nc, &cnt, _state); - } - *cve = *cve+bdss_getcv(&cnt, nc, _state); - for(i=0; i<=nc-1; i++) - { - cnt.ptr.p_int[i] = 0; - } - for(i=j; i<=tiecount-1; i++) - { - bdss_tieaddc(c, &ties, i, nc, &cnt, _state); - } - *cve = *cve+bdss_getcv(&cnt, nc, _state); - } - else - { - - /* - * General case: 2 or more intervals - * - * NOTE: we initialize both JL and JR (left and right bounds), - * altough algorithm needs only JL. - */ - ae_vector_set_length(thresholds, koptimal-1+1, _state); - *ni = koptimal+1; - *cve = cv.ptr.pp_double[koptimal][tiecount-1]; - jl = splits.ptr.pp_int[koptimal][tiecount-1]; - jr = tiecount-1; - for(k=koptimal; k>=1; k--) - { - thresholds->ptr.p_double[k-1] = 0.5*(a->ptr.p_double[ties.ptr.p_int[jl-1]]+a->ptr.p_double[ties.ptr.p_int[jl]]); - jr = jl-1; - jl = splits.ptr.pp_int[k-1][jl-1]; - } - touchint(&jr, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal function -*************************************************************************/ -static double bdss_xlny(double x, double y, ae_state *_state) -{ - double result; - - - if( ae_fp_eq(x,(double)(0)) ) - { - result = (double)(0); - } - else - { - result = x*ae_log(y, _state); - } - return result; -} - - -/************************************************************************* -Internal function, -returns number of samples of class I in Cnt[I] -*************************************************************************/ -static double bdss_getcv(/* Integer */ ae_vector* cnt, - ae_int_t nc, - ae_state *_state) -{ - ae_int_t i; - double s; - double result; - - - s = (double)(0); - for(i=0; i<=nc-1; i++) - { - s = s+cnt->ptr.p_int[i]; - } - result = (double)(0); - for(i=0; i<=nc-1; i++) - { - result = result-bdss_xlny((double)(cnt->ptr.p_int[i]), cnt->ptr.p_int[i]/(s+nc-1), _state); - } - return result; -} - - -/************************************************************************* -Internal function, adds number of samples of class I in tie NTie to Cnt[I] -*************************************************************************/ -static void bdss_tieaddc(/* Integer */ ae_vector* c, - /* Integer */ ae_vector* ties, - ae_int_t ntie, - ae_int_t nc, - /* Integer */ ae_vector* cnt, - ae_state *_state) -{ - ae_int_t i; - - - for(i=ties->ptr.p_int[ntie]; i<=ties->ptr.p_int[ntie+1]-1; i++) - { - cnt->ptr.p_int[c->ptr.p_int[i]] = cnt->ptr.p_int[c->ptr.p_int[i]]+1; - } -} - - -/************************************************************************* -Internal function, subtracts number of samples of class I in tie NTie to Cnt[I] -*************************************************************************/ -static void bdss_tiesubc(/* Integer */ ae_vector* c, - /* Integer */ ae_vector* ties, - ae_int_t ntie, - ae_int_t nc, - /* Integer */ ae_vector* cnt, - ae_state *_state) -{ - ae_int_t i; - - - for(i=ties->ptr.p_int[ntie]; i<=ties->ptr.p_int[ntie+1]-1; i++) - { - cnt->ptr.p_int[c->ptr.p_int[i]] = cnt->ptr.p_int[c->ptr.p_int[i]]-1; - } -} - - -void _cvreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - cvreport *p = (cvreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _cvreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - cvreport *dst = (cvreport*)_dst; - cvreport *src = (cvreport*)_src; - dst->relclserror = src->relclserror; - dst->avgce = src->avgce; - dst->rmserror = src->rmserror; - dst->avgerror = src->avgerror; - dst->avgrelerror = src->avgrelerror; -} - - -void _cvreport_clear(void* _p) -{ - cvreport *p = (cvreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _cvreport_destroy(void* _p) -{ - cvreport *p = (cvreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_MLPBASE) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function returns number of weights updates which is required for -gradient calculation problem to be splitted. -*************************************************************************/ -ae_int_t mlpgradsplitcost(ae_state *_state) -{ - ae_int_t result; - - - result = mlpbase_gradbasecasecost; - return result; -} - - -/************************************************************************* -This function returns number of elements in subset of dataset which is -required for gradient calculation problem to be splitted. -*************************************************************************/ -ae_int_t mlpgradsplitsize(ae_state *_state) -{ - ae_int_t result; - - - result = mlpbase_microbatchsize; - return result; -} - - -/************************************************************************* -Creates neural network with NIn inputs, NOut outputs, without hidden -layers, with linear output layer. Network weights are filled with small -random values. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcreate0(ae_int_t nin, - ae_int_t nout, - multilayerperceptron* network, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector lsizes; - ae_vector ltypes; - ae_vector lconnfirst; - ae_vector lconnlast; - ae_int_t layerscount; - ae_int_t lastproc; - - ae_frame_make(_state, &_frame_block); - memset(&lsizes, 0, sizeof(lsizes)); - memset(<ypes, 0, sizeof(ltypes)); - memset(&lconnfirst, 0, sizeof(lconnfirst)); - memset(&lconnlast, 0, sizeof(lconnlast)); - _multilayerperceptron_clear(network); - ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true); - ae_vector_init(<ypes, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true); - - layerscount = 1+3; - - /* - * Allocate arrays - */ - ae_vector_set_length(&lsizes, layerscount-1+1, _state); - ae_vector_set_length(<ypes, layerscount-1+1, _state); - ae_vector_set_length(&lconnfirst, layerscount-1+1, _state); - ae_vector_set_length(&lconnlast, layerscount-1+1, _state); - - /* - * Layers - */ - mlpbase_addinputlayer(nin, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nout, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(-5, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - - /* - * Create - */ - mlpbase_mlpcreate(nin, nout, &lsizes, <ypes, &lconnfirst, &lconnlast, layerscount, ae_false, network, _state); - mlpbase_fillhighlevelinformation(network, nin, 0, 0, nout, ae_false, ae_true, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Same as MLPCreate0, but with one hidden layer (NHid neurons) with -non-linear activation function. Output layer is linear. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcreate1(ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - multilayerperceptron* network, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector lsizes; - ae_vector ltypes; - ae_vector lconnfirst; - ae_vector lconnlast; - ae_int_t layerscount; - ae_int_t lastproc; - - ae_frame_make(_state, &_frame_block); - memset(&lsizes, 0, sizeof(lsizes)); - memset(<ypes, 0, sizeof(ltypes)); - memset(&lconnfirst, 0, sizeof(lconnfirst)); - memset(&lconnlast, 0, sizeof(lconnlast)); - _multilayerperceptron_clear(network); - ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true); - ae_vector_init(<ypes, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true); - - layerscount = 1+3+3; - - /* - * Allocate arrays - */ - ae_vector_set_length(&lsizes, layerscount-1+1, _state); - ae_vector_set_length(<ypes, layerscount-1+1, _state); - ae_vector_set_length(&lconnfirst, layerscount-1+1, _state); - ae_vector_set_length(&lconnlast, layerscount-1+1, _state); - - /* - * Layers - */ - mlpbase_addinputlayer(nin, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nhid, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nout, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(-5, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - - /* - * Create - */ - mlpbase_mlpcreate(nin, nout, &lsizes, <ypes, &lconnfirst, &lconnlast, layerscount, ae_false, network, _state); - mlpbase_fillhighlevelinformation(network, nin, nhid, 0, nout, ae_false, ae_true, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Same as MLPCreate0, but with two hidden layers (NHid1 and NHid2 neurons) -with non-linear activation function. Output layer is linear. - $ALL - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcreate2(ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - multilayerperceptron* network, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector lsizes; - ae_vector ltypes; - ae_vector lconnfirst; - ae_vector lconnlast; - ae_int_t layerscount; - ae_int_t lastproc; - - ae_frame_make(_state, &_frame_block); - memset(&lsizes, 0, sizeof(lsizes)); - memset(<ypes, 0, sizeof(ltypes)); - memset(&lconnfirst, 0, sizeof(lconnfirst)); - memset(&lconnlast, 0, sizeof(lconnlast)); - _multilayerperceptron_clear(network); - ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true); - ae_vector_init(<ypes, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true); - - layerscount = 1+3+3+3; - - /* - * Allocate arrays - */ - ae_vector_set_length(&lsizes, layerscount-1+1, _state); - ae_vector_set_length(<ypes, layerscount-1+1, _state); - ae_vector_set_length(&lconnfirst, layerscount-1+1, _state); - ae_vector_set_length(&lconnlast, layerscount-1+1, _state); - - /* - * Layers - */ - mlpbase_addinputlayer(nin, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nhid1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nhid2, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nout, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(-5, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - - /* - * Create - */ - mlpbase_mlpcreate(nin, nout, &lsizes, <ypes, &lconnfirst, &lconnlast, layerscount, ae_false, network, _state); - mlpbase_fillhighlevelinformation(network, nin, nhid1, nhid2, nout, ae_false, ae_true, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Creates neural network with NIn inputs, NOut outputs, without hidden -layers with non-linear output layer. Network weights are filled with small -random values. - -Activation function of the output layer takes values: - - (B, +INF), if D>=0 - -or - - (-INF, B), if D<0. - - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpcreateb0(ae_int_t nin, - ae_int_t nout, - double b, - double d, - multilayerperceptron* network, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector lsizes; - ae_vector ltypes; - ae_vector lconnfirst; - ae_vector lconnlast; - ae_int_t layerscount; - ae_int_t lastproc; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&lsizes, 0, sizeof(lsizes)); - memset(<ypes, 0, sizeof(ltypes)); - memset(&lconnfirst, 0, sizeof(lconnfirst)); - memset(&lconnlast, 0, sizeof(lconnlast)); - _multilayerperceptron_clear(network); - ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true); - ae_vector_init(<ypes, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true); - - layerscount = 1+3; - if( ae_fp_greater_eq(d,(double)(0)) ) - { - d = (double)(1); - } - else - { - d = (double)(-1); - } - - /* - * Allocate arrays - */ - ae_vector_set_length(&lsizes, layerscount-1+1, _state); - ae_vector_set_length(<ypes, layerscount-1+1, _state); - ae_vector_set_length(&lconnfirst, layerscount-1+1, _state); - ae_vector_set_length(&lconnlast, layerscount-1+1, _state); - - /* - * Layers - */ - mlpbase_addinputlayer(nin, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nout, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(3, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - - /* - * Create - */ - mlpbase_mlpcreate(nin, nout, &lsizes, <ypes, &lconnfirst, &lconnlast, layerscount, ae_false, network, _state); - mlpbase_fillhighlevelinformation(network, nin, 0, 0, nout, ae_false, ae_false, _state); - - /* - * Turn on ouputs shift/scaling. - */ - for(i=nin; i<=nin+nout-1; i++) - { - network->columnmeans.ptr.p_double[i] = b; - network->columnsigmas.ptr.p_double[i] = d; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Same as MLPCreateB0 but with non-linear hidden layer. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpcreateb1(ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - double b, - double d, - multilayerperceptron* network, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector lsizes; - ae_vector ltypes; - ae_vector lconnfirst; - ae_vector lconnlast; - ae_int_t layerscount; - ae_int_t lastproc; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&lsizes, 0, sizeof(lsizes)); - memset(<ypes, 0, sizeof(ltypes)); - memset(&lconnfirst, 0, sizeof(lconnfirst)); - memset(&lconnlast, 0, sizeof(lconnlast)); - _multilayerperceptron_clear(network); - ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true); - ae_vector_init(<ypes, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true); - - layerscount = 1+3+3; - if( ae_fp_greater_eq(d,(double)(0)) ) - { - d = (double)(1); - } - else - { - d = (double)(-1); - } - - /* - * Allocate arrays - */ - ae_vector_set_length(&lsizes, layerscount-1+1, _state); - ae_vector_set_length(<ypes, layerscount-1+1, _state); - ae_vector_set_length(&lconnfirst, layerscount-1+1, _state); - ae_vector_set_length(&lconnlast, layerscount-1+1, _state); - - /* - * Layers - */ - mlpbase_addinputlayer(nin, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nhid, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nout, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(3, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - - /* - * Create - */ - mlpbase_mlpcreate(nin, nout, &lsizes, <ypes, &lconnfirst, &lconnlast, layerscount, ae_false, network, _state); - mlpbase_fillhighlevelinformation(network, nin, nhid, 0, nout, ae_false, ae_false, _state); - - /* - * Turn on ouputs shift/scaling. - */ - for(i=nin; i<=nin+nout-1; i++) - { - network->columnmeans.ptr.p_double[i] = b; - network->columnsigmas.ptr.p_double[i] = d; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Same as MLPCreateB0 but with two non-linear hidden layers. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpcreateb2(ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - double b, - double d, - multilayerperceptron* network, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector lsizes; - ae_vector ltypes; - ae_vector lconnfirst; - ae_vector lconnlast; - ae_int_t layerscount; - ae_int_t lastproc; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&lsizes, 0, sizeof(lsizes)); - memset(<ypes, 0, sizeof(ltypes)); - memset(&lconnfirst, 0, sizeof(lconnfirst)); - memset(&lconnlast, 0, sizeof(lconnlast)); - _multilayerperceptron_clear(network); - ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true); - ae_vector_init(<ypes, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true); - - layerscount = 1+3+3+3; - if( ae_fp_greater_eq(d,(double)(0)) ) - { - d = (double)(1); - } - else - { - d = (double)(-1); - } - - /* - * Allocate arrays - */ - ae_vector_set_length(&lsizes, layerscount-1+1, _state); - ae_vector_set_length(<ypes, layerscount-1+1, _state); - ae_vector_set_length(&lconnfirst, layerscount-1+1, _state); - ae_vector_set_length(&lconnlast, layerscount-1+1, _state); - - /* - * Layers - */ - mlpbase_addinputlayer(nin, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nhid1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nhid2, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nout, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(3, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - - /* - * Create - */ - mlpbase_mlpcreate(nin, nout, &lsizes, <ypes, &lconnfirst, &lconnlast, layerscount, ae_false, network, _state); - mlpbase_fillhighlevelinformation(network, nin, nhid1, nhid2, nout, ae_false, ae_false, _state); - - /* - * Turn on ouputs shift/scaling. - */ - for(i=nin; i<=nin+nout-1; i++) - { - network->columnmeans.ptr.p_double[i] = b; - network->columnsigmas.ptr.p_double[i] = d; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Creates neural network with NIn inputs, NOut outputs, without hidden -layers with non-linear output layer. Network weights are filled with small -random values. Activation function of the output layer takes values [A,B]. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpcreater0(ae_int_t nin, - ae_int_t nout, - double a, - double b, - multilayerperceptron* network, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector lsizes; - ae_vector ltypes; - ae_vector lconnfirst; - ae_vector lconnlast; - ae_int_t layerscount; - ae_int_t lastproc; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&lsizes, 0, sizeof(lsizes)); - memset(<ypes, 0, sizeof(ltypes)); - memset(&lconnfirst, 0, sizeof(lconnfirst)); - memset(&lconnlast, 0, sizeof(lconnlast)); - _multilayerperceptron_clear(network); - ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true); - ae_vector_init(<ypes, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true); - - layerscount = 1+3; - - /* - * Allocate arrays - */ - ae_vector_set_length(&lsizes, layerscount-1+1, _state); - ae_vector_set_length(<ypes, layerscount-1+1, _state); - ae_vector_set_length(&lconnfirst, layerscount-1+1, _state); - ae_vector_set_length(&lconnlast, layerscount-1+1, _state); - - /* - * Layers - */ - mlpbase_addinputlayer(nin, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nout, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - - /* - * Create - */ - mlpbase_mlpcreate(nin, nout, &lsizes, <ypes, &lconnfirst, &lconnlast, layerscount, ae_false, network, _state); - mlpbase_fillhighlevelinformation(network, nin, 0, 0, nout, ae_false, ae_false, _state); - - /* - * Turn on outputs shift/scaling. - */ - for(i=nin; i<=nin+nout-1; i++) - { - network->columnmeans.ptr.p_double[i] = 0.5*(a+b); - network->columnsigmas.ptr.p_double[i] = 0.5*(a-b); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Same as MLPCreateR0, but with non-linear hidden layer. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpcreater1(ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - double a, - double b, - multilayerperceptron* network, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector lsizes; - ae_vector ltypes; - ae_vector lconnfirst; - ae_vector lconnlast; - ae_int_t layerscount; - ae_int_t lastproc; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&lsizes, 0, sizeof(lsizes)); - memset(<ypes, 0, sizeof(ltypes)); - memset(&lconnfirst, 0, sizeof(lconnfirst)); - memset(&lconnlast, 0, sizeof(lconnlast)); - _multilayerperceptron_clear(network); - ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true); - ae_vector_init(<ypes, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true); - - layerscount = 1+3+3; - - /* - * Allocate arrays - */ - ae_vector_set_length(&lsizes, layerscount-1+1, _state); - ae_vector_set_length(<ypes, layerscount-1+1, _state); - ae_vector_set_length(&lconnfirst, layerscount-1+1, _state); - ae_vector_set_length(&lconnlast, layerscount-1+1, _state); - - /* - * Layers - */ - mlpbase_addinputlayer(nin, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nhid, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nout, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - - /* - * Create - */ - mlpbase_mlpcreate(nin, nout, &lsizes, <ypes, &lconnfirst, &lconnlast, layerscount, ae_false, network, _state); - mlpbase_fillhighlevelinformation(network, nin, nhid, 0, nout, ae_false, ae_false, _state); - - /* - * Turn on outputs shift/scaling. - */ - for(i=nin; i<=nin+nout-1; i++) - { - network->columnmeans.ptr.p_double[i] = 0.5*(a+b); - network->columnsigmas.ptr.p_double[i] = 0.5*(a-b); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Same as MLPCreateR0, but with two non-linear hidden layers. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpcreater2(ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - double a, - double b, - multilayerperceptron* network, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector lsizes; - ae_vector ltypes; - ae_vector lconnfirst; - ae_vector lconnlast; - ae_int_t layerscount; - ae_int_t lastproc; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&lsizes, 0, sizeof(lsizes)); - memset(<ypes, 0, sizeof(ltypes)); - memset(&lconnfirst, 0, sizeof(lconnfirst)); - memset(&lconnlast, 0, sizeof(lconnlast)); - _multilayerperceptron_clear(network); - ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true); - ae_vector_init(<ypes, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true); - - layerscount = 1+3+3+3; - - /* - * Allocate arrays - */ - ae_vector_set_length(&lsizes, layerscount-1+1, _state); - ae_vector_set_length(<ypes, layerscount-1+1, _state); - ae_vector_set_length(&lconnfirst, layerscount-1+1, _state); - ae_vector_set_length(&lconnlast, layerscount-1+1, _state); - - /* - * Layers - */ - mlpbase_addinputlayer(nin, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nhid1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nhid2, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nout, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - - /* - * Create - */ - mlpbase_mlpcreate(nin, nout, &lsizes, <ypes, &lconnfirst, &lconnlast, layerscount, ae_false, network, _state); - mlpbase_fillhighlevelinformation(network, nin, nhid1, nhid2, nout, ae_false, ae_false, _state); - - /* - * Turn on outputs shift/scaling. - */ - for(i=nin; i<=nin+nout-1; i++) - { - network->columnmeans.ptr.p_double[i] = 0.5*(a+b); - network->columnsigmas.ptr.p_double[i] = 0.5*(a-b); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Creates classifier network with NIn inputs and NOut possible classes. -Network contains no hidden layers and linear output layer with SOFTMAX- -normalization (so outputs sums up to 1.0 and converge to posterior -probabilities). - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcreatec0(ae_int_t nin, - ae_int_t nout, - multilayerperceptron* network, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector lsizes; - ae_vector ltypes; - ae_vector lconnfirst; - ae_vector lconnlast; - ae_int_t layerscount; - ae_int_t lastproc; - - ae_frame_make(_state, &_frame_block); - memset(&lsizes, 0, sizeof(lsizes)); - memset(<ypes, 0, sizeof(ltypes)); - memset(&lconnfirst, 0, sizeof(lconnfirst)); - memset(&lconnlast, 0, sizeof(lconnlast)); - _multilayerperceptron_clear(network); - ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true); - ae_vector_init(<ypes, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true); - - ae_assert(nout>=2, "MLPCreateC0: NOut<2!", _state); - layerscount = 1+2+1; - - /* - * Allocate arrays - */ - ae_vector_set_length(&lsizes, layerscount-1+1, _state); - ae_vector_set_length(<ypes, layerscount-1+1, _state); - ae_vector_set_length(&lconnfirst, layerscount-1+1, _state); - ae_vector_set_length(&lconnlast, layerscount-1+1, _state); - - /* - * Layers - */ - mlpbase_addinputlayer(nin, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nout-1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addzerolayer(&lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - - /* - * Create - */ - mlpbase_mlpcreate(nin, nout, &lsizes, <ypes, &lconnfirst, &lconnlast, layerscount, ae_true, network, _state); - mlpbase_fillhighlevelinformation(network, nin, 0, 0, nout, ae_true, ae_true, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Same as MLPCreateC0, but with one non-linear hidden layer. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcreatec1(ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - multilayerperceptron* network, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector lsizes; - ae_vector ltypes; - ae_vector lconnfirst; - ae_vector lconnlast; - ae_int_t layerscount; - ae_int_t lastproc; - - ae_frame_make(_state, &_frame_block); - memset(&lsizes, 0, sizeof(lsizes)); - memset(<ypes, 0, sizeof(ltypes)); - memset(&lconnfirst, 0, sizeof(lconnfirst)); - memset(&lconnlast, 0, sizeof(lconnlast)); - _multilayerperceptron_clear(network); - ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true); - ae_vector_init(<ypes, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true); - - ae_assert(nout>=2, "MLPCreateC1: NOut<2!", _state); - layerscount = 1+3+2+1; - - /* - * Allocate arrays - */ - ae_vector_set_length(&lsizes, layerscount-1+1, _state); - ae_vector_set_length(<ypes, layerscount-1+1, _state); - ae_vector_set_length(&lconnfirst, layerscount-1+1, _state); - ae_vector_set_length(&lconnlast, layerscount-1+1, _state); - - /* - * Layers - */ - mlpbase_addinputlayer(nin, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nhid, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nout-1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addzerolayer(&lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - - /* - * Create - */ - mlpbase_mlpcreate(nin, nout, &lsizes, <ypes, &lconnfirst, &lconnlast, layerscount, ae_true, network, _state); - mlpbase_fillhighlevelinformation(network, nin, nhid, 0, nout, ae_true, ae_true, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Same as MLPCreateC0, but with two non-linear hidden layers. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcreatec2(ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - multilayerperceptron* network, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector lsizes; - ae_vector ltypes; - ae_vector lconnfirst; - ae_vector lconnlast; - ae_int_t layerscount; - ae_int_t lastproc; - - ae_frame_make(_state, &_frame_block); - memset(&lsizes, 0, sizeof(lsizes)); - memset(<ypes, 0, sizeof(ltypes)); - memset(&lconnfirst, 0, sizeof(lconnfirst)); - memset(&lconnlast, 0, sizeof(lconnlast)); - _multilayerperceptron_clear(network); - ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true); - ae_vector_init(<ypes, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true); - ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true); - - ae_assert(nout>=2, "MLPCreateC2: NOut<2!", _state); - layerscount = 1+3+3+2+1; - - /* - * Allocate arrays - */ - ae_vector_set_length(&lsizes, layerscount-1+1, _state); - ae_vector_set_length(<ypes, layerscount-1+1, _state); - ae_vector_set_length(&lconnfirst, layerscount-1+1, _state); - ae_vector_set_length(&lconnlast, layerscount-1+1, _state); - - /* - * Layers - */ - mlpbase_addinputlayer(nin, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nhid1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nhid2, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addactivationlayer(1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addbiasedsummatorlayer(nout-1, &lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - mlpbase_addzerolayer(&lsizes, <ypes, &lconnfirst, &lconnlast, &lastproc, _state); - - /* - * Create - */ - mlpbase_mlpcreate(nin, nout, &lsizes, <ypes, &lconnfirst, &lconnlast, layerscount, ae_true, network, _state); - mlpbase_fillhighlevelinformation(network, nin, nhid1, nhid2, nout, ae_true, ae_true, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Copying of neural network - -INPUT PARAMETERS: - Network1 - original - -OUTPUT PARAMETERS: - Network2 - copy - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcopy(multilayerperceptron* network1, - multilayerperceptron* network2, - ae_state *_state) -{ - - _multilayerperceptron_clear(network2); - - mlpcopyshared(network1, network2, _state); -} - - -/************************************************************************* -Copying of neural network (second parameter is passed as shared object). - -INPUT PARAMETERS: - Network1 - original - -OUTPUT PARAMETERS: - Network2 - copy - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcopyshared(multilayerperceptron* network1, - multilayerperceptron* network2, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t wcount; - ae_int_t i; - mlpbuffers buf; - smlpgrad sgrad; - - ae_frame_make(_state, &_frame_block); - memset(&buf, 0, sizeof(buf)); - memset(&sgrad, 0, sizeof(sgrad)); - _mlpbuffers_init(&buf, _state, ae_true); - _smlpgrad_init(&sgrad, _state, ae_true); - - - /* - * Copy scalar and array fields - */ - network2->hlnetworktype = network1->hlnetworktype; - network2->hlnormtype = network1->hlnormtype; - copyintegerarray(&network1->hllayersizes, &network2->hllayersizes, _state); - copyintegerarray(&network1->hlconnections, &network2->hlconnections, _state); - copyintegerarray(&network1->hlneurons, &network2->hlneurons, _state); - copyintegerarray(&network1->structinfo, &network2->structinfo, _state); - copyrealarray(&network1->weights, &network2->weights, _state); - copyrealarray(&network1->columnmeans, &network2->columnmeans, _state); - copyrealarray(&network1->columnsigmas, &network2->columnsigmas, _state); - copyrealarray(&network1->neurons, &network2->neurons, _state); - copyrealarray(&network1->dfdnet, &network2->dfdnet, _state); - copyrealarray(&network1->derror, &network2->derror, _state); - copyrealarray(&network1->x, &network2->x, _state); - copyrealarray(&network1->y, &network2->y, _state); - copyrealarray(&network1->nwbuf, &network2->nwbuf, _state); - copyintegerarray(&network1->integerbuf, &network2->integerbuf, _state); - - /* - * copy buffers - */ - wcount = mlpgetweightscount(network1, _state); - ae_shared_pool_set_seed(&network2->buf, &buf, sizeof(buf), _mlpbuffers_init, _mlpbuffers_init_copy, _mlpbuffers_destroy, _state); - ae_vector_set_length(&sgrad.g, wcount, _state); - sgrad.f = 0.0; - for(i=0; i<=wcount-1; i++) - { - sgrad.g.ptr.p_double[i] = 0.0; - } - ae_shared_pool_set_seed(&network2->gradbuf, &sgrad, sizeof(sgrad), _smlpgrad_init, _smlpgrad_init_copy, _smlpgrad_destroy, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function compares architectures of neural networks. Only geometries -are compared, weights and other parameters are not tested. - - -- ALGLIB -- - Copyright 20.06.2013 by Bochkanov Sergey -*************************************************************************/ -ae_bool mlpsamearchitecture(multilayerperceptron* network1, - multilayerperceptron* network2, - ae_state *_state) -{ - ae_int_t i; - ae_int_t ninfo; - ae_bool result; - - - ae_assert(network1->structinfo.cnt>0&&network1->structinfo.cnt>=network1->structinfo.ptr.p_int[0], "MLPSameArchitecture: Network1 is uninitialized", _state); - ae_assert(network2->structinfo.cnt>0&&network2->structinfo.cnt>=network2->structinfo.ptr.p_int[0], "MLPSameArchitecture: Network2 is uninitialized", _state); - result = ae_false; - if( network1->structinfo.ptr.p_int[0]!=network2->structinfo.ptr.p_int[0] ) - { - return result; - } - ninfo = network1->structinfo.ptr.p_int[0]; - for(i=0; i<=ninfo-1; i++) - { - if( network1->structinfo.ptr.p_int[i]!=network2->structinfo.ptr.p_int[i] ) - { - return result; - } - } - result = ae_true; - return result; -} - - -/************************************************************************* -This function copies tunable parameters (weights/means/sigmas) from one -network to another with same architecture. It performs some rudimentary -checks that architectures are same, and throws exception if check fails. - -It is intended for fast copying of states between two network which are -known to have same geometry. - -INPUT PARAMETERS: - Network1 - source, must be correctly initialized - Network2 - target, must have same architecture - -OUTPUT PARAMETERS: - Network2 - network state is copied from source to target - - -- ALGLIB -- - Copyright 20.06.2013 by Bochkanov Sergey -*************************************************************************/ -void mlpcopytunableparameters(multilayerperceptron* network1, - multilayerperceptron* network2, - ae_state *_state) -{ - ae_int_t i; - ae_int_t ninfo; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - - - ae_assert(network1->structinfo.cnt>0&&network1->structinfo.cnt>=network1->structinfo.ptr.p_int[0], "MLPCopyTunableParameters: Network1 is uninitialized", _state); - ae_assert(network2->structinfo.cnt>0&&network2->structinfo.cnt>=network2->structinfo.ptr.p_int[0], "MLPCopyTunableParameters: Network2 is uninitialized", _state); - ae_assert(network1->structinfo.ptr.p_int[0]==network2->structinfo.ptr.p_int[0], "MLPCopyTunableParameters: Network1 geometry differs from that of Network2", _state); - ninfo = network1->structinfo.ptr.p_int[0]; - for(i=0; i<=ninfo-1; i++) - { - ae_assert(network1->structinfo.ptr.p_int[i]==network2->structinfo.ptr.p_int[i], "MLPCopyTunableParameters: Network1 geometry differs from that of Network2", _state); - } - mlpproperties(network1, &nin, &nout, &wcount, _state); - for(i=0; i<=wcount-1; i++) - { - network2->weights.ptr.p_double[i] = network1->weights.ptr.p_double[i]; - } - if( mlpissoftmax(network1, _state) ) - { - for(i=0; i<=nin-1; i++) - { - network2->columnmeans.ptr.p_double[i] = network1->columnmeans.ptr.p_double[i]; - network2->columnsigmas.ptr.p_double[i] = network1->columnsigmas.ptr.p_double[i]; - } - } - else - { - for(i=0; i<=nin+nout-1; i++) - { - network2->columnmeans.ptr.p_double[i] = network1->columnmeans.ptr.p_double[i]; - network2->columnsigmas.ptr.p_double[i] = network1->columnsigmas.ptr.p_double[i]; - } - } -} - - -/************************************************************************* -This function exports tunable parameters (weights/means/sigmas) from -network to contiguous array. Nothing is guaranteed about array format, the -only thing you can count for is that MLPImportTunableParameters() will be -able to parse it. - -It is intended for fast copying of states between network and backup array - -INPUT PARAMETERS: - Network - source, must be correctly initialized - P - array to use. If its size is enough to store data, it - is reused. - -OUTPUT PARAMETERS: - P - array which stores network parameters, resized if needed - PCount - number of parameters stored in array. - - -- ALGLIB -- - Copyright 20.06.2013 by Bochkanov Sergey -*************************************************************************/ -void mlpexporttunableparameters(multilayerperceptron* network, - /* Real */ ae_vector* p, - ae_int_t* pcount, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - - *pcount = 0; - - ae_assert(network->structinfo.cnt>0&&network->structinfo.cnt>=network->structinfo.ptr.p_int[0], "MLPExportTunableParameters: Network is uninitialized", _state); - mlpproperties(network, &nin, &nout, &wcount, _state); - if( mlpissoftmax(network, _state) ) - { - *pcount = wcount+2*nin; - rvectorsetlengthatleast(p, *pcount, _state); - k = 0; - for(i=0; i<=wcount-1; i++) - { - p->ptr.p_double[k] = network->weights.ptr.p_double[i]; - k = k+1; - } - for(i=0; i<=nin-1; i++) - { - p->ptr.p_double[k] = network->columnmeans.ptr.p_double[i]; - k = k+1; - p->ptr.p_double[k] = network->columnsigmas.ptr.p_double[i]; - k = k+1; - } - } - else - { - *pcount = wcount+2*(nin+nout); - rvectorsetlengthatleast(p, *pcount, _state); - k = 0; - for(i=0; i<=wcount-1; i++) - { - p->ptr.p_double[k] = network->weights.ptr.p_double[i]; - k = k+1; - } - for(i=0; i<=nin+nout-1; i++) - { - p->ptr.p_double[k] = network->columnmeans.ptr.p_double[i]; - k = k+1; - p->ptr.p_double[k] = network->columnsigmas.ptr.p_double[i]; - k = k+1; - } - } -} - - -/************************************************************************* -This function imports tunable parameters (weights/means/sigmas) which -were exported by MLPExportTunableParameters(). - -It is intended for fast copying of states between network and backup array - -INPUT PARAMETERS: - Network - target: - * must be correctly initialized - * must have same geometry as network used to export params - P - array with parameters - - -- ALGLIB -- - Copyright 20.06.2013 by Bochkanov Sergey -*************************************************************************/ -void mlpimporttunableparameters(multilayerperceptron* network, - /* Real */ ae_vector* p, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - - - ae_assert(network->structinfo.cnt>0&&network->structinfo.cnt>=network->structinfo.ptr.p_int[0], "MLPImportTunableParameters: Network is uninitialized", _state); - mlpproperties(network, &nin, &nout, &wcount, _state); - if( mlpissoftmax(network, _state) ) - { - k = 0; - for(i=0; i<=wcount-1; i++) - { - network->weights.ptr.p_double[i] = p->ptr.p_double[k]; - k = k+1; - } - for(i=0; i<=nin-1; i++) - { - network->columnmeans.ptr.p_double[i] = p->ptr.p_double[k]; - k = k+1; - network->columnsigmas.ptr.p_double[i] = p->ptr.p_double[k]; - k = k+1; - } - } - else - { - k = 0; - for(i=0; i<=wcount-1; i++) - { - network->weights.ptr.p_double[i] = p->ptr.p_double[k]; - k = k+1; - } - for(i=0; i<=nin+nout-1; i++) - { - network->columnmeans.ptr.p_double[i] = p->ptr.p_double[k]; - k = k+1; - network->columnsigmas.ptr.p_double[i] = p->ptr.p_double[k]; - k = k+1; - } - } -} - - -/************************************************************************* -Serialization of MultiLayerPerceptron strucure - -INPUT PARAMETERS: - Network - original - -OUTPUT PARAMETERS: - RA - array of real numbers which stores network, - array[0..RLen-1] - RLen - RA lenght - - -- ALGLIB -- - Copyright 29.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpserializeold(multilayerperceptron* network, - /* Real */ ae_vector* ra, - ae_int_t* rlen, - ae_state *_state) -{ - ae_int_t i; - ae_int_t ssize; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t sigmalen; - ae_int_t offs; - - ae_vector_clear(ra); - *rlen = 0; - - - /* - * Unload info - */ - ssize = network->structinfo.ptr.p_int[0]; - nin = network->structinfo.ptr.p_int[1]; - nout = network->structinfo.ptr.p_int[2]; - wcount = network->structinfo.ptr.p_int[4]; - if( mlpissoftmax(network, _state) ) - { - sigmalen = nin; - } - else - { - sigmalen = nin+nout; - } - - /* - * RA format: - * LEN DESRC. - * 1 RLen - * 1 version (MLPVNum) - * 1 StructInfo size - * SSize StructInfo - * WCount Weights - * SigmaLen ColumnMeans - * SigmaLen ColumnSigmas - */ - *rlen = 3+ssize+wcount+2*sigmalen; - ae_vector_set_length(ra, *rlen-1+1, _state); - ra->ptr.p_double[0] = (double)(*rlen); - ra->ptr.p_double[1] = (double)(mlpbase_mlpvnum); - ra->ptr.p_double[2] = (double)(ssize); - offs = 3; - for(i=0; i<=ssize-1; i++) - { - ra->ptr.p_double[offs+i] = (double)(network->structinfo.ptr.p_int[i]); - } - offs = offs+ssize; - ae_v_move(&ra->ptr.p_double[offs], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(offs,offs+wcount-1)); - offs = offs+wcount; - ae_v_move(&ra->ptr.p_double[offs], 1, &network->columnmeans.ptr.p_double[0], 1, ae_v_len(offs,offs+sigmalen-1)); - offs = offs+sigmalen; - ae_v_move(&ra->ptr.p_double[offs], 1, &network->columnsigmas.ptr.p_double[0], 1, ae_v_len(offs,offs+sigmalen-1)); - offs = offs+sigmalen; -} - - -/************************************************************************* -Unserialization of MultiLayerPerceptron strucure - -INPUT PARAMETERS: - RA - real array which stores network - -OUTPUT PARAMETERS: - Network - restored network - - -- ALGLIB -- - Copyright 29.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpunserializeold(/* Real */ ae_vector* ra, - multilayerperceptron* network, - ae_state *_state) -{ - ae_int_t i; - ae_int_t ssize; - ae_int_t ntotal; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t sigmalen; - ae_int_t offs; - - _multilayerperceptron_clear(network); - - ae_assert(ae_round(ra->ptr.p_double[1], _state)==mlpbase_mlpvnum, "MLPUnserialize: incorrect array!", _state); - - /* - * Unload StructInfo from IA - */ - offs = 3; - ssize = ae_round(ra->ptr.p_double[2], _state); - ae_vector_set_length(&network->structinfo, ssize-1+1, _state); - for(i=0; i<=ssize-1; i++) - { - network->structinfo.ptr.p_int[i] = ae_round(ra->ptr.p_double[offs+i], _state); - } - offs = offs+ssize; - - /* - * Unload info from StructInfo - */ - ssize = network->structinfo.ptr.p_int[0]; - nin = network->structinfo.ptr.p_int[1]; - nout = network->structinfo.ptr.p_int[2]; - ntotal = network->structinfo.ptr.p_int[3]; - wcount = network->structinfo.ptr.p_int[4]; - if( network->structinfo.ptr.p_int[6]==0 ) - { - sigmalen = nin+nout; - } - else - { - sigmalen = nin; - } - - /* - * Allocate space for other fields - */ - ae_vector_set_length(&network->weights, wcount-1+1, _state); - ae_vector_set_length(&network->columnmeans, sigmalen-1+1, _state); - ae_vector_set_length(&network->columnsigmas, sigmalen-1+1, _state); - ae_vector_set_length(&network->neurons, ntotal-1+1, _state); - ae_vector_set_length(&network->nwbuf, ae_maxint(wcount, 2*nout, _state)-1+1, _state); - ae_vector_set_length(&network->dfdnet, ntotal-1+1, _state); - ae_vector_set_length(&network->x, nin-1+1, _state); - ae_vector_set_length(&network->y, nout-1+1, _state); - ae_vector_set_length(&network->derror, ntotal-1+1, _state); - - /* - * Copy parameters from RA - */ - ae_v_move(&network->weights.ptr.p_double[0], 1, &ra->ptr.p_double[offs], 1, ae_v_len(0,wcount-1)); - offs = offs+wcount; - ae_v_move(&network->columnmeans.ptr.p_double[0], 1, &ra->ptr.p_double[offs], 1, ae_v_len(0,sigmalen-1)); - offs = offs+sigmalen; - ae_v_move(&network->columnsigmas.ptr.p_double[0], 1, &ra->ptr.p_double[offs], 1, ae_v_len(0,sigmalen-1)); - offs = offs+sigmalen; -} - - -/************************************************************************* -Randomization of neural network weights - - -- ALGLIB -- - Copyright 06.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlprandomize(multilayerperceptron* network, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t ntotal; - ae_int_t istart; - hqrndstate r; - ae_int_t entrysize; - ae_int_t entryoffs; - ae_int_t neuronidx; - ae_int_t neurontype; - double vmean; - double vvar; - ae_int_t i; - ae_int_t n1; - ae_int_t n2; - double desiredsigma; - ae_int_t montecarlocnt; - double ef; - double ef2; - double v; - double wscale; - - ae_frame_make(_state, &_frame_block); - memset(&r, 0, sizeof(r)); - _hqrndstate_init(&r, _state, ae_true); - - hqrndrandomize(&r, _state); - mlpproperties(network, &nin, &nout, &wcount, _state); - ntotal = network->structinfo.ptr.p_int[3]; - istart = network->structinfo.ptr.p_int[5]; - desiredsigma = 0.5; - montecarlocnt = 20; - - /* - * Stage 1: - * * Network.Weights is filled by standard deviation of weights - * * default values: sigma=1 - */ - for(i=0; i<=wcount-1; i++) - { - network->weights.ptr.p_double[i] = 1.0; - } - - /* - * Stage 2: - * * assume that input neurons have zero mean and unit standard deviation - * * assume that constant neurons have zero standard deviation - * * perform forward pass along neurons - * * for each non-input non-constant neuron: - * * calculate mean and standard deviation of neuron's output - * assuming that we know means/deviations of neurons which feed it - * and assuming that weights has unit variance and zero mean. - * * for each nonlinear neuron additionally we perform backward pass: - * * scale variances of weights which feed it in such way that neuron's - * input has unit standard deviation - * - * NOTE: this algorithm assumes that each connection feeds at most one - * non-linear neuron. This assumption can be incorrect in upcoming - * architectures with strong neurons. However, algorithm should - * work smoothly even in this case. - * - * During this stage we use Network.RndBuf, which is grouped into NTotal - * entries, each of them having following format: - * - * Buf[Offset+0] mean value of neuron's output - * Buf[Offset+1] standard deviation of neuron's output - * - * - */ - entrysize = 2; - rvectorsetlengthatleast(&network->rndbuf, entrysize*ntotal, _state); - for(neuronidx=0; neuronidx<=ntotal-1; neuronidx++) - { - neurontype = network->structinfo.ptr.p_int[istart+neuronidx*mlpbase_nfieldwidth+0]; - entryoffs = entrysize*neuronidx; - if( neurontype==-2 ) - { - - /* - * Input neuron: zero mean, unit variance. - */ - network->rndbuf.ptr.p_double[entryoffs+0] = 0.0; - network->rndbuf.ptr.p_double[entryoffs+1] = 1.0; - continue; - } - if( neurontype==-3 ) - { - - /* - * "-1" neuron: mean=-1, zero variance. - */ - network->rndbuf.ptr.p_double[entryoffs+0] = -1.0; - network->rndbuf.ptr.p_double[entryoffs+1] = 0.0; - continue; - } - if( neurontype==-4 ) - { - - /* - * "0" neuron: mean=0, zero variance. - */ - network->rndbuf.ptr.p_double[entryoffs+0] = 0.0; - network->rndbuf.ptr.p_double[entryoffs+1] = 0.0; - continue; - } - if( neurontype==0 ) - { - - /* - * Adaptive summator neuron: - * * calculate its mean and variance. - * * we assume that weights of this neuron have unit variance and zero mean. - * * thus, neuron's output is always have zero mean - * * as for variance, it is a bit more interesting: - * * let n[i] is i-th input neuron - * * let w[i] is i-th weight - * * we assume that n[i] and w[i] are independently distributed - * * Var(n0*w0+n1*w1+...) = Var(n0*w0)+Var(n1*w1)+... - * * Var(X*Y) = mean(X)^2*Var(Y) + mean(Y)^2*Var(X) + Var(X)*Var(Y) - * * mean(w[i])=0, var(w[i])=1 - * * Var(n[i]*w[i]) = mean(n[i])^2 + Var(n[i]) - */ - n1 = network->structinfo.ptr.p_int[istart+neuronidx*mlpbase_nfieldwidth+2]; - n2 = n1+network->structinfo.ptr.p_int[istart+neuronidx*mlpbase_nfieldwidth+1]-1; - vmean = 0.0; - vvar = 0.0; - for(i=n1; i<=n2; i++) - { - vvar = vvar+ae_sqr(network->rndbuf.ptr.p_double[entrysize*i+0], _state)+ae_sqr(network->rndbuf.ptr.p_double[entrysize*i+1], _state); - } - network->rndbuf.ptr.p_double[entryoffs+0] = vmean; - network->rndbuf.ptr.p_double[entryoffs+1] = ae_sqrt(vvar, _state); - continue; - } - if( neurontype==-5 ) - { - - /* - * Linear activation function - */ - i = network->structinfo.ptr.p_int[istart+neuronidx*mlpbase_nfieldwidth+2]; - vmean = network->rndbuf.ptr.p_double[entrysize*i+0]; - vvar = ae_sqr(network->rndbuf.ptr.p_double[entrysize*i+1], _state); - if( ae_fp_greater(vvar,(double)(0)) ) - { - wscale = desiredsigma/ae_sqrt(vvar, _state); - } - else - { - wscale = 1.0; - } - mlpbase_randomizebackwardpass(network, i, wscale, _state); - network->rndbuf.ptr.p_double[entryoffs+0] = vmean*wscale; - network->rndbuf.ptr.p_double[entryoffs+1] = desiredsigma; - continue; - } - if( neurontype>0 ) - { - - /* - * Nonlinear activation function: - * * scale its inputs - * * estimate mean/sigma of its output using Monte-Carlo method - * (we simulate different inputs with unit deviation and - * sample activation function output on such inputs) - */ - i = network->structinfo.ptr.p_int[istart+neuronidx*mlpbase_nfieldwidth+2]; - vmean = network->rndbuf.ptr.p_double[entrysize*i+0]; - vvar = ae_sqr(network->rndbuf.ptr.p_double[entrysize*i+1], _state); - if( ae_fp_greater(vvar,(double)(0)) ) - { - wscale = desiredsigma/ae_sqrt(vvar, _state); - } - else - { - wscale = 1.0; - } - mlpbase_randomizebackwardpass(network, i, wscale, _state); - ef = 0.0; - ef2 = 0.0; - vmean = vmean*wscale; - for(i=0; i<=montecarlocnt-1; i++) - { - v = vmean+desiredsigma*hqrndnormal(&r, _state); - ef = ef+v; - ef2 = ef2+v*v; - } - ef = ef/montecarlocnt; - ef2 = ef2/montecarlocnt; - network->rndbuf.ptr.p_double[entryoffs+0] = ef; - network->rndbuf.ptr.p_double[entryoffs+1] = ae_maxreal(ef2-ef*ef, 0.0, _state); - continue; - } - ae_assert(ae_false, "MLPRandomize: unexpected neuron type", _state); - } - - /* - * Stage 3: generate weights. - */ - for(i=0; i<=wcount-1; i++) - { - network->weights.ptr.p_double[i] = network->weights.ptr.p_double[i]*hqrndnormal(&r, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Randomization of neural network weights and standartisator - - -- ALGLIB -- - Copyright 10.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlprandomizefull(multilayerperceptron* network, ae_state *_state) -{ - ae_int_t i; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t ntotal; - ae_int_t istart; - ae_int_t offs; - ae_int_t ntype; - - - mlpproperties(network, &nin, &nout, &wcount, _state); - ntotal = network->structinfo.ptr.p_int[3]; - istart = network->structinfo.ptr.p_int[5]; - - /* - * Process network - */ - mlprandomize(network, _state); - for(i=0; i<=nin-1; i++) - { - network->columnmeans.ptr.p_double[i] = ae_randomreal(_state)-0.5; - network->columnsigmas.ptr.p_double[i] = ae_randomreal(_state)+0.5; - } - if( !mlpissoftmax(network, _state) ) - { - for(i=0; i<=nout-1; i++) - { - offs = istart+(ntotal-nout+i)*mlpbase_nfieldwidth; - ntype = network->structinfo.ptr.p_int[offs+0]; - if( ntype==0 ) - { - - /* - * Shifts are changed only for linear outputs neurons - */ - network->columnmeans.ptr.p_double[nin+i] = 2*ae_randomreal(_state)-1; - } - if( ntype==0||ntype==3 ) - { - - /* - * Scales are changed only for linear or bounded outputs neurons. - * Note that scale randomization preserves sign. - */ - network->columnsigmas.ptr.p_double[nin+i] = ae_sign(network->columnsigmas.ptr.p_double[nin+i], _state)*(1.5*ae_randomreal(_state)+0.5); - } - } - } -} - - -/************************************************************************* -Internal subroutine. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpinitpreprocessor(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t ssize, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t jmax; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t ntotal; - ae_int_t istart; - ae_int_t offs; - ae_int_t ntype; - ae_vector means; - ae_vector sigmas; - double s; - - ae_frame_make(_state, &_frame_block); - memset(&means, 0, sizeof(means)); - memset(&sigmas, 0, sizeof(sigmas)); - ae_vector_init(&means, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sigmas, 0, DT_REAL, _state, ae_true); - - mlpproperties(network, &nin, &nout, &wcount, _state); - ntotal = network->structinfo.ptr.p_int[3]; - istart = network->structinfo.ptr.p_int[5]; - - /* - * Means/Sigmas - */ - if( mlpissoftmax(network, _state) ) - { - jmax = nin-1; - } - else - { - jmax = nin+nout-1; - } - ae_vector_set_length(&means, jmax+1, _state); - ae_vector_set_length(&sigmas, jmax+1, _state); - for(i=0; i<=jmax; i++) - { - means.ptr.p_double[i] = (double)(0); - sigmas.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=ssize-1; i++) - { - for(j=0; j<=jmax; j++) - { - means.ptr.p_double[j] = means.ptr.p_double[j]+xy->ptr.pp_double[i][j]; - } - } - for(i=0; i<=jmax; i++) - { - means.ptr.p_double[i] = means.ptr.p_double[i]/ssize; - } - for(i=0; i<=ssize-1; i++) - { - for(j=0; j<=jmax; j++) - { - sigmas.ptr.p_double[j] = sigmas.ptr.p_double[j]+ae_sqr(xy->ptr.pp_double[i][j]-means.ptr.p_double[j], _state); - } - } - for(i=0; i<=jmax; i++) - { - sigmas.ptr.p_double[i] = ae_sqrt(sigmas.ptr.p_double[i]/ssize, _state); - } - - /* - * Inputs - */ - for(i=0; i<=nin-1; i++) - { - network->columnmeans.ptr.p_double[i] = means.ptr.p_double[i]; - network->columnsigmas.ptr.p_double[i] = sigmas.ptr.p_double[i]; - if( ae_fp_eq(network->columnsigmas.ptr.p_double[i],(double)(0)) ) - { - network->columnsigmas.ptr.p_double[i] = (double)(1); - } - } - - /* - * Outputs - */ - if( !mlpissoftmax(network, _state) ) - { - for(i=0; i<=nout-1; i++) - { - offs = istart+(ntotal-nout+i)*mlpbase_nfieldwidth; - ntype = network->structinfo.ptr.p_int[offs+0]; - - /* - * Linear outputs - */ - if( ntype==0 ) - { - network->columnmeans.ptr.p_double[nin+i] = means.ptr.p_double[nin+i]; - network->columnsigmas.ptr.p_double[nin+i] = sigmas.ptr.p_double[nin+i]; - if( ae_fp_eq(network->columnsigmas.ptr.p_double[nin+i],(double)(0)) ) - { - network->columnsigmas.ptr.p_double[nin+i] = (double)(1); - } - } - - /* - * Bounded outputs (half-interval) - */ - if( ntype==3 ) - { - s = means.ptr.p_double[nin+i]-network->columnmeans.ptr.p_double[nin+i]; - if( ae_fp_eq(s,(double)(0)) ) - { - s = (double)(ae_sign(network->columnsigmas.ptr.p_double[nin+i], _state)); - } - if( ae_fp_eq(s,(double)(0)) ) - { - s = 1.0; - } - network->columnsigmas.ptr.p_double[nin+i] = ae_sign(network->columnsigmas.ptr.p_double[nin+i], _state)*ae_fabs(s, _state); - if( ae_fp_eq(network->columnsigmas.ptr.p_double[nin+i],(double)(0)) ) - { - network->columnsigmas.ptr.p_double[nin+i] = (double)(1); - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal subroutine. -Initialization for preprocessor based on a sample. - -INPUT - Network - initialized neural network; - XY - sample, given by sparse matrix; - SSize - sample size. - -OUTPUT - Network - neural network with initialised preprocessor. - - -- ALGLIB -- - Copyright 26.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpinitpreprocessorsparse(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t ssize, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t jmax; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t ntotal; - ae_int_t istart; - ae_int_t offs; - ae_int_t ntype; - ae_vector means; - ae_vector sigmas; - double s; - ae_int_t i; - ae_int_t j; - - ae_frame_make(_state, &_frame_block); - memset(&means, 0, sizeof(means)); - memset(&sigmas, 0, sizeof(sigmas)); - ae_vector_init(&means, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sigmas, 0, DT_REAL, _state, ae_true); - - mlpproperties(network, &nin, &nout, &wcount, _state); - ntotal = network->structinfo.ptr.p_int[3]; - istart = network->structinfo.ptr.p_int[5]; - - /* - * Means/Sigmas - */ - if( mlpissoftmax(network, _state) ) - { - jmax = nin-1; - } - else - { - jmax = nin+nout-1; - } - ae_vector_set_length(&means, jmax+1, _state); - ae_vector_set_length(&sigmas, jmax+1, _state); - for(i=0; i<=jmax; i++) - { - means.ptr.p_double[i] = (double)(0); - sigmas.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=ssize-1; i++) - { - sparsegetrow(xy, i, &network->xyrow, _state); - for(j=0; j<=jmax; j++) - { - means.ptr.p_double[j] = means.ptr.p_double[j]+network->xyrow.ptr.p_double[j]; - } - } - for(i=0; i<=jmax; i++) - { - means.ptr.p_double[i] = means.ptr.p_double[i]/ssize; - } - for(i=0; i<=ssize-1; i++) - { - sparsegetrow(xy, i, &network->xyrow, _state); - for(j=0; j<=jmax; j++) - { - sigmas.ptr.p_double[j] = sigmas.ptr.p_double[j]+ae_sqr(network->xyrow.ptr.p_double[j]-means.ptr.p_double[j], _state); - } - } - for(i=0; i<=jmax; i++) - { - sigmas.ptr.p_double[i] = ae_sqrt(sigmas.ptr.p_double[i]/ssize, _state); - } - - /* - * Inputs - */ - for(i=0; i<=nin-1; i++) - { - network->columnmeans.ptr.p_double[i] = means.ptr.p_double[i]; - network->columnsigmas.ptr.p_double[i] = sigmas.ptr.p_double[i]; - if( ae_fp_eq(network->columnsigmas.ptr.p_double[i],(double)(0)) ) - { - network->columnsigmas.ptr.p_double[i] = (double)(1); - } - } - - /* - * Outputs - */ - if( !mlpissoftmax(network, _state) ) - { - for(i=0; i<=nout-1; i++) - { - offs = istart+(ntotal-nout+i)*mlpbase_nfieldwidth; - ntype = network->structinfo.ptr.p_int[offs+0]; - - /* - * Linear outputs - */ - if( ntype==0 ) - { - network->columnmeans.ptr.p_double[nin+i] = means.ptr.p_double[nin+i]; - network->columnsigmas.ptr.p_double[nin+i] = sigmas.ptr.p_double[nin+i]; - if( ae_fp_eq(network->columnsigmas.ptr.p_double[nin+i],(double)(0)) ) - { - network->columnsigmas.ptr.p_double[nin+i] = (double)(1); - } - } - - /* - * Bounded outputs (half-interval) - */ - if( ntype==3 ) - { - s = means.ptr.p_double[nin+i]-network->columnmeans.ptr.p_double[nin+i]; - if( ae_fp_eq(s,(double)(0)) ) - { - s = (double)(ae_sign(network->columnsigmas.ptr.p_double[nin+i], _state)); - } - if( ae_fp_eq(s,(double)(0)) ) - { - s = 1.0; - } - network->columnsigmas.ptr.p_double[nin+i] = ae_sign(network->columnsigmas.ptr.p_double[nin+i], _state)*ae_fabs(s, _state); - if( ae_fp_eq(network->columnsigmas.ptr.p_double[nin+i],(double)(0)) ) - { - network->columnsigmas.ptr.p_double[nin+i] = (double)(1); - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal subroutine. -Initialization for preprocessor based on a subsample. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset; one sample = one row; - first NIn columns contain inputs, - next NOut columns - desired outputs. - SetSize - real size of XY, SetSize>=0; - Idx - subset of SubsetSize elements, array[SubsetSize]: - * Idx[I] stores row index in the original dataset which is - given by XY. Gradient is calculated with respect to rows - whose indexes are stored in Idx[]. - * Idx[] must store correct indexes; this function throws - an exception in case incorrect index (less than 0 or - larger than rows(XY)) is given - * Idx[] may store indexes in any order and even with - repetitions. - SubsetSize- number of elements in Idx[] array. - -OUTPUT: - Network - neural network with initialised preprocessor. - -NOTE: when SubsetSize<0 is used full dataset by call MLPInitPreprocessor - function. - - -- ALGLIB -- - Copyright 23.08.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpinitpreprocessorsubset(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t setsize, - /* Integer */ ae_vector* idx, - ae_int_t subsetsize, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t jmax; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t ntotal; - ae_int_t istart; - ae_int_t offs; - ae_int_t ntype; - ae_vector means; - ae_vector sigmas; - double s; - ae_int_t npoints; - ae_int_t i; - ae_int_t j; - - ae_frame_make(_state, &_frame_block); - memset(&means, 0, sizeof(means)); - memset(&sigmas, 0, sizeof(sigmas)); - ae_vector_init(&means, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sigmas, 0, DT_REAL, _state, ae_true); - - ae_assert(setsize>=0, "MLPInitPreprocessorSubset: SetSize<0", _state); - if( subsetsize<0 ) - { - mlpinitpreprocessor(network, xy, setsize, _state); - ae_frame_leave(_state); - return; - } - ae_assert(subsetsize<=idx->cnt, "MLPInitPreprocessorSubset: SubsetSize>Length(Idx)", _state); - npoints = setsize; - for(i=0; i<=subsetsize-1; i++) - { - ae_assert(idx->ptr.p_int[i]>=0, "MLPInitPreprocessorSubset: incorrect index of XY row(Idx[I]<0)", _state); - ae_assert(idx->ptr.p_int[i]<=npoints-1, "MLPInitPreprocessorSubset: incorrect index of XY row(Idx[I]>Rows(XY)-1)", _state); - } - mlpproperties(network, &nin, &nout, &wcount, _state); - ntotal = network->structinfo.ptr.p_int[3]; - istart = network->structinfo.ptr.p_int[5]; - - /* - * Means/Sigmas - */ - if( mlpissoftmax(network, _state) ) - { - jmax = nin-1; - } - else - { - jmax = nin+nout-1; - } - ae_vector_set_length(&means, jmax+1, _state); - ae_vector_set_length(&sigmas, jmax+1, _state); - for(i=0; i<=jmax; i++) - { - means.ptr.p_double[i] = (double)(0); - sigmas.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=subsetsize-1; i++) - { - for(j=0; j<=jmax; j++) - { - means.ptr.p_double[j] = means.ptr.p_double[j]+xy->ptr.pp_double[idx->ptr.p_int[i]][j]; - } - } - for(i=0; i<=jmax; i++) - { - means.ptr.p_double[i] = means.ptr.p_double[i]/subsetsize; - } - for(i=0; i<=subsetsize-1; i++) - { - for(j=0; j<=jmax; j++) - { - sigmas.ptr.p_double[j] = sigmas.ptr.p_double[j]+ae_sqr(xy->ptr.pp_double[idx->ptr.p_int[i]][j]-means.ptr.p_double[j], _state); - } - } - for(i=0; i<=jmax; i++) - { - sigmas.ptr.p_double[i] = ae_sqrt(sigmas.ptr.p_double[i]/subsetsize, _state); - } - - /* - * Inputs - */ - for(i=0; i<=nin-1; i++) - { - network->columnmeans.ptr.p_double[i] = means.ptr.p_double[i]; - network->columnsigmas.ptr.p_double[i] = sigmas.ptr.p_double[i]; - if( ae_fp_eq(network->columnsigmas.ptr.p_double[i],(double)(0)) ) - { - network->columnsigmas.ptr.p_double[i] = (double)(1); - } - } - - /* - * Outputs - */ - if( !mlpissoftmax(network, _state) ) - { - for(i=0; i<=nout-1; i++) - { - offs = istart+(ntotal-nout+i)*mlpbase_nfieldwidth; - ntype = network->structinfo.ptr.p_int[offs+0]; - - /* - * Linear outputs - */ - if( ntype==0 ) - { - network->columnmeans.ptr.p_double[nin+i] = means.ptr.p_double[nin+i]; - network->columnsigmas.ptr.p_double[nin+i] = sigmas.ptr.p_double[nin+i]; - if( ae_fp_eq(network->columnsigmas.ptr.p_double[nin+i],(double)(0)) ) - { - network->columnsigmas.ptr.p_double[nin+i] = (double)(1); - } - } - - /* - * Bounded outputs (half-interval) - */ - if( ntype==3 ) - { - s = means.ptr.p_double[nin+i]-network->columnmeans.ptr.p_double[nin+i]; - if( ae_fp_eq(s,(double)(0)) ) - { - s = (double)(ae_sign(network->columnsigmas.ptr.p_double[nin+i], _state)); - } - if( ae_fp_eq(s,(double)(0)) ) - { - s = 1.0; - } - network->columnsigmas.ptr.p_double[nin+i] = ae_sign(network->columnsigmas.ptr.p_double[nin+i], _state)*ae_fabs(s, _state); - if( ae_fp_eq(network->columnsigmas.ptr.p_double[nin+i],(double)(0)) ) - { - network->columnsigmas.ptr.p_double[nin+i] = (double)(1); - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal subroutine. -Initialization for preprocessor based on a subsample. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset, given by sparse matrix; - one sample = one row; - first NIn columns contain inputs, - next NOut columns - desired outputs. - SetSize - real size of XY, SetSize>=0; - Idx - subset of SubsetSize elements, array[SubsetSize]: - * Idx[I] stores row index in the original dataset which is - given by XY. Gradient is calculated with respect to rows - whose indexes are stored in Idx[]. - * Idx[] must store correct indexes; this function throws - an exception in case incorrect index (less than 0 or - larger than rows(XY)) is given - * Idx[] may store indexes in any order and even with - repetitions. - SubsetSize- number of elements in Idx[] array. - -OUTPUT: - Network - neural network with initialised preprocessor. - -NOTE: when SubsetSize<0 is used full dataset by call - MLPInitPreprocessorSparse function. - - -- ALGLIB -- - Copyright 26.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpinitpreprocessorsparsesubset(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t setsize, - /* Integer */ ae_vector* idx, - ae_int_t subsetsize, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t jmax; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t ntotal; - ae_int_t istart; - ae_int_t offs; - ae_int_t ntype; - ae_vector means; - ae_vector sigmas; - double s; - ae_int_t npoints; - ae_int_t i; - ae_int_t j; - - ae_frame_make(_state, &_frame_block); - memset(&means, 0, sizeof(means)); - memset(&sigmas, 0, sizeof(sigmas)); - ae_vector_init(&means, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sigmas, 0, DT_REAL, _state, ae_true); - - ae_assert(setsize>=0, "MLPInitPreprocessorSparseSubset: SetSize<0", _state); - if( subsetsize<0 ) - { - mlpinitpreprocessorsparse(network, xy, setsize, _state); - ae_frame_leave(_state); - return; - } - ae_assert(subsetsize<=idx->cnt, "MLPInitPreprocessorSparseSubset: SubsetSize>Length(Idx)", _state); - npoints = setsize; - for(i=0; i<=subsetsize-1; i++) - { - ae_assert(idx->ptr.p_int[i]>=0, "MLPInitPreprocessorSparseSubset: incorrect index of XY row(Idx[I]<0)", _state); - ae_assert(idx->ptr.p_int[i]<=npoints-1, "MLPInitPreprocessorSparseSubset: incorrect index of XY row(Idx[I]>Rows(XY)-1)", _state); - } - mlpproperties(network, &nin, &nout, &wcount, _state); - ntotal = network->structinfo.ptr.p_int[3]; - istart = network->structinfo.ptr.p_int[5]; - - /* - * Means/Sigmas - */ - if( mlpissoftmax(network, _state) ) - { - jmax = nin-1; - } - else - { - jmax = nin+nout-1; - } - ae_vector_set_length(&means, jmax+1, _state); - ae_vector_set_length(&sigmas, jmax+1, _state); - for(i=0; i<=jmax; i++) - { - means.ptr.p_double[i] = (double)(0); - sigmas.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=subsetsize-1; i++) - { - sparsegetrow(xy, idx->ptr.p_int[i], &network->xyrow, _state); - for(j=0; j<=jmax; j++) - { - means.ptr.p_double[j] = means.ptr.p_double[j]+network->xyrow.ptr.p_double[j]; - } - } - for(i=0; i<=jmax; i++) - { - means.ptr.p_double[i] = means.ptr.p_double[i]/subsetsize; - } - for(i=0; i<=subsetsize-1; i++) - { - sparsegetrow(xy, idx->ptr.p_int[i], &network->xyrow, _state); - for(j=0; j<=jmax; j++) - { - sigmas.ptr.p_double[j] = sigmas.ptr.p_double[j]+ae_sqr(network->xyrow.ptr.p_double[j]-means.ptr.p_double[j], _state); - } - } - for(i=0; i<=jmax; i++) - { - sigmas.ptr.p_double[i] = ae_sqrt(sigmas.ptr.p_double[i]/subsetsize, _state); - } - - /* - * Inputs - */ - for(i=0; i<=nin-1; i++) - { - network->columnmeans.ptr.p_double[i] = means.ptr.p_double[i]; - network->columnsigmas.ptr.p_double[i] = sigmas.ptr.p_double[i]; - if( ae_fp_eq(network->columnsigmas.ptr.p_double[i],(double)(0)) ) - { - network->columnsigmas.ptr.p_double[i] = (double)(1); - } - } - - /* - * Outputs - */ - if( !mlpissoftmax(network, _state) ) - { - for(i=0; i<=nout-1; i++) - { - offs = istart+(ntotal-nout+i)*mlpbase_nfieldwidth; - ntype = network->structinfo.ptr.p_int[offs+0]; - - /* - * Linear outputs - */ - if( ntype==0 ) - { - network->columnmeans.ptr.p_double[nin+i] = means.ptr.p_double[nin+i]; - network->columnsigmas.ptr.p_double[nin+i] = sigmas.ptr.p_double[nin+i]; - if( ae_fp_eq(network->columnsigmas.ptr.p_double[nin+i],(double)(0)) ) - { - network->columnsigmas.ptr.p_double[nin+i] = (double)(1); - } - } - - /* - * Bounded outputs (half-interval) - */ - if( ntype==3 ) - { - s = means.ptr.p_double[nin+i]-network->columnmeans.ptr.p_double[nin+i]; - if( ae_fp_eq(s,(double)(0)) ) - { - s = (double)(ae_sign(network->columnsigmas.ptr.p_double[nin+i], _state)); - } - if( ae_fp_eq(s,(double)(0)) ) - { - s = 1.0; - } - network->columnsigmas.ptr.p_double[nin+i] = ae_sign(network->columnsigmas.ptr.p_double[nin+i], _state)*ae_fabs(s, _state); - if( ae_fp_eq(network->columnsigmas.ptr.p_double[nin+i],(double)(0)) ) - { - network->columnsigmas.ptr.p_double[nin+i] = (double)(1); - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Returns information about initialized network: number of inputs, outputs, -weights. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpproperties(multilayerperceptron* network, - ae_int_t* nin, - ae_int_t* nout, - ae_int_t* wcount, - ae_state *_state) -{ - - *nin = 0; - *nout = 0; - *wcount = 0; - - *nin = network->structinfo.ptr.p_int[1]; - *nout = network->structinfo.ptr.p_int[2]; - *wcount = network->structinfo.ptr.p_int[4]; -} - - -/************************************************************************* -Returns number of "internal", low-level neurons in the network (one which -is stored in StructInfo). - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mlpntotal(multilayerperceptron* network, ae_state *_state) -{ - ae_int_t result; - - - result = network->structinfo.ptr.p_int[3]; - return result; -} - - -/************************************************************************* -Returns number of inputs. - - -- ALGLIB -- - Copyright 19.10.2011 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mlpgetinputscount(multilayerperceptron* network, - ae_state *_state) -{ - ae_int_t result; - - - result = network->structinfo.ptr.p_int[1]; - return result; -} - - -/************************************************************************* -Returns number of outputs. - - -- ALGLIB -- - Copyright 19.10.2011 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mlpgetoutputscount(multilayerperceptron* network, - ae_state *_state) -{ - ae_int_t result; - - - result = network->structinfo.ptr.p_int[2]; - return result; -} - - -/************************************************************************* -Returns number of weights. - - -- ALGLIB -- - Copyright 19.10.2011 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mlpgetweightscount(multilayerperceptron* network, - ae_state *_state) -{ - ae_int_t result; - - - result = network->structinfo.ptr.p_int[4]; - return result; -} - - -/************************************************************************* -Tells whether network is SOFTMAX-normalized (i.e. classifier) or not. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -ae_bool mlpissoftmax(multilayerperceptron* network, ae_state *_state) -{ - ae_bool result; - - - result = network->structinfo.ptr.p_int[6]==1; - return result; -} - - -/************************************************************************* -This function returns total number of layers (including input, hidden and -output layers). - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mlpgetlayerscount(multilayerperceptron* network, - ae_state *_state) -{ - ae_int_t result; - - - result = network->hllayersizes.cnt; - return result; -} - - -/************************************************************************* -This function returns size of K-th layer. - -K=0 corresponds to input layer, K=CNT-1 corresponds to output layer. - -Size of the output layer is always equal to the number of outputs, although -when we have softmax-normalized network, last neuron doesn't have any -connections - it is just zero. - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mlpgetlayersize(multilayerperceptron* network, - ae_int_t k, - ae_state *_state) -{ - ae_int_t result; - - - ae_assert(k>=0&&khllayersizes.cnt, "MLPGetLayerSize: incorrect layer index", _state); - result = network->hllayersizes.ptr.p_int[k]; - return result; -} - - -/************************************************************************* -This function returns offset/scaling coefficients for I-th input of the -network. - -INPUT PARAMETERS: - Network - network - I - input index - -OUTPUT PARAMETERS: - Mean - mean term - Sigma - sigma term, guaranteed to be nonzero. - -I-th input is passed through linear transformation - IN[i] = (IN[i]-Mean)/Sigma -before feeding to the network - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpgetinputscaling(multilayerperceptron* network, - ae_int_t i, - double* mean, - double* sigma, - ae_state *_state) -{ - - *mean = 0; - *sigma = 0; - - ae_assert(i>=0&&ihllayersizes.ptr.p_int[0], "MLPGetInputScaling: incorrect (nonexistent) I", _state); - *mean = network->columnmeans.ptr.p_double[i]; - *sigma = network->columnsigmas.ptr.p_double[i]; - if( ae_fp_eq(*sigma,(double)(0)) ) - { - *sigma = (double)(1); - } -} - - -/************************************************************************* -This function returns offset/scaling coefficients for I-th output of the -network. - -INPUT PARAMETERS: - Network - network - I - input index - -OUTPUT PARAMETERS: - Mean - mean term - Sigma - sigma term, guaranteed to be nonzero. - -I-th output is passed through linear transformation - OUT[i] = OUT[i]*Sigma+Mean -before returning it to user. In case we have SOFTMAX-normalized network, -we return (Mean,Sigma)=(0.0,1.0). - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpgetoutputscaling(multilayerperceptron* network, - ae_int_t i, - double* mean, - double* sigma, - ae_state *_state) -{ - - *mean = 0; - *sigma = 0; - - ae_assert(i>=0&&ihllayersizes.ptr.p_int[network->hllayersizes.cnt-1], "MLPGetOutputScaling: incorrect (nonexistent) I", _state); - if( network->structinfo.ptr.p_int[6]==1 ) - { - *mean = (double)(0); - *sigma = (double)(1); - } - else - { - *mean = network->columnmeans.ptr.p_double[network->hllayersizes.ptr.p_int[0]+i]; - *sigma = network->columnsigmas.ptr.p_double[network->hllayersizes.ptr.p_int[0]+i]; - } -} - - -/************************************************************************* -This function returns information about Ith neuron of Kth layer - -INPUT PARAMETERS: - Network - network - K - layer index - I - neuron index (within layer) - -OUTPUT PARAMETERS: - FKind - activation function type (used by MLPActivationFunction()) - this value is zero for input or linear neurons - Threshold - also called offset, bias - zero for input neurons - -NOTE: this function throws exception if layer or neuron with given index -do not exists. - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpgetneuroninfo(multilayerperceptron* network, - ae_int_t k, - ae_int_t i, - ae_int_t* fkind, - double* threshold, - ae_state *_state) -{ - ae_int_t ncnt; - ae_int_t istart; - ae_int_t highlevelidx; - ae_int_t activationoffset; - - *fkind = 0; - *threshold = 0; - - ncnt = network->hlneurons.cnt/mlpbase_hlnfieldwidth; - istart = network->structinfo.ptr.p_int[5]; - - /* - * search - */ - network->integerbuf.ptr.p_int[0] = k; - network->integerbuf.ptr.p_int[1] = i; - highlevelidx = recsearch(&network->hlneurons, mlpbase_hlnfieldwidth, 2, 0, ncnt, &network->integerbuf, _state); - ae_assert(highlevelidx>=0, "MLPGetNeuronInfo: incorrect (nonexistent) layer or neuron index", _state); - - /* - * 1. find offset of the activation function record in the - */ - if( network->hlneurons.ptr.p_int[highlevelidx*mlpbase_hlnfieldwidth+2]>=0 ) - { - activationoffset = istart+network->hlneurons.ptr.p_int[highlevelidx*mlpbase_hlnfieldwidth+2]*mlpbase_nfieldwidth; - *fkind = network->structinfo.ptr.p_int[activationoffset+0]; - } - else - { - *fkind = 0; - } - if( network->hlneurons.ptr.p_int[highlevelidx*mlpbase_hlnfieldwidth+3]>=0 ) - { - *threshold = network->weights.ptr.p_double[network->hlneurons.ptr.p_int[highlevelidx*mlpbase_hlnfieldwidth+3]]; - } - else - { - *threshold = (double)(0); - } -} - - -/************************************************************************* -This function returns information about connection from I0-th neuron of -K0-th layer to I1-th neuron of K1-th layer. - -INPUT PARAMETERS: - Network - network - K0 - layer index - I0 - neuron index (within layer) - K1 - layer index - I1 - neuron index (within layer) - -RESULT: - connection weight (zero for non-existent connections) - -This function: -1. throws exception if layer or neuron with given index do not exists. -2. returns zero if neurons exist, but there is no connection between them - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -double mlpgetweight(multilayerperceptron* network, - ae_int_t k0, - ae_int_t i0, - ae_int_t k1, - ae_int_t i1, - ae_state *_state) -{ - ae_int_t ccnt; - ae_int_t highlevelidx; - double result; - - - ccnt = network->hlconnections.cnt/mlpbase_hlconnfieldwidth; - - /* - * check params - */ - ae_assert(k0>=0&&k0hllayersizes.cnt, "MLPGetWeight: incorrect (nonexistent) K0", _state); - ae_assert(i0>=0&&i0hllayersizes.ptr.p_int[k0], "MLPGetWeight: incorrect (nonexistent) I0", _state); - ae_assert(k1>=0&&k1hllayersizes.cnt, "MLPGetWeight: incorrect (nonexistent) K1", _state); - ae_assert(i1>=0&&i1hllayersizes.ptr.p_int[k1], "MLPGetWeight: incorrect (nonexistent) I1", _state); - - /* - * search - */ - network->integerbuf.ptr.p_int[0] = k0; - network->integerbuf.ptr.p_int[1] = i0; - network->integerbuf.ptr.p_int[2] = k1; - network->integerbuf.ptr.p_int[3] = i1; - highlevelidx = recsearch(&network->hlconnections, mlpbase_hlconnfieldwidth, 4, 0, ccnt, &network->integerbuf, _state); - if( highlevelidx>=0 ) - { - result = network->weights.ptr.p_double[network->hlconnections.ptr.p_int[highlevelidx*mlpbase_hlconnfieldwidth+4]]; - } - else - { - result = (double)(0); - } - return result; -} - - -/************************************************************************* -This function sets offset/scaling coefficients for I-th input of the -network. - -INPUT PARAMETERS: - Network - network - I - input index - Mean - mean term - Sigma - sigma term (if zero, will be replaced by 1.0) - -NTE: I-th input is passed through linear transformation - IN[i] = (IN[i]-Mean)/Sigma -before feeding to the network. This function sets Mean and Sigma. - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpsetinputscaling(multilayerperceptron* network, - ae_int_t i, - double mean, - double sigma, - ae_state *_state) -{ - - - ae_assert(i>=0&&ihllayersizes.ptr.p_int[0], "MLPSetInputScaling: incorrect (nonexistent) I", _state); - ae_assert(ae_isfinite(mean, _state), "MLPSetInputScaling: infinite or NAN Mean", _state); - ae_assert(ae_isfinite(sigma, _state), "MLPSetInputScaling: infinite or NAN Sigma", _state); - if( ae_fp_eq(sigma,(double)(0)) ) - { - sigma = (double)(1); - } - network->columnmeans.ptr.p_double[i] = mean; - network->columnsigmas.ptr.p_double[i] = sigma; -} - - -/************************************************************************* -This function sets offset/scaling coefficients for I-th output of the -network. - -INPUT PARAMETERS: - Network - network - I - input index - Mean - mean term - Sigma - sigma term (if zero, will be replaced by 1.0) - -OUTPUT PARAMETERS: - -NOTE: I-th output is passed through linear transformation - OUT[i] = OUT[i]*Sigma+Mean -before returning it to user. This function sets Sigma/Mean. In case we -have SOFTMAX-normalized network, you can not set (Sigma,Mean) to anything -other than(0.0,1.0) - this function will throw exception. - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpsetoutputscaling(multilayerperceptron* network, - ae_int_t i, - double mean, - double sigma, - ae_state *_state) -{ - - - ae_assert(i>=0&&ihllayersizes.ptr.p_int[network->hllayersizes.cnt-1], "MLPSetOutputScaling: incorrect (nonexistent) I", _state); - ae_assert(ae_isfinite(mean, _state), "MLPSetOutputScaling: infinite or NAN Mean", _state); - ae_assert(ae_isfinite(sigma, _state), "MLPSetOutputScaling: infinite or NAN Sigma", _state); - if( network->structinfo.ptr.p_int[6]==1 ) - { - ae_assert(ae_fp_eq(mean,(double)(0)), "MLPSetOutputScaling: you can not set non-zero Mean term for classifier network", _state); - ae_assert(ae_fp_eq(sigma,(double)(1)), "MLPSetOutputScaling: you can not set non-unit Sigma term for classifier network", _state); - } - else - { - if( ae_fp_eq(sigma,(double)(0)) ) - { - sigma = (double)(1); - } - network->columnmeans.ptr.p_double[network->hllayersizes.ptr.p_int[0]+i] = mean; - network->columnsigmas.ptr.p_double[network->hllayersizes.ptr.p_int[0]+i] = sigma; - } -} - - -/************************************************************************* -This function modifies information about Ith neuron of Kth layer - -INPUT PARAMETERS: - Network - network - K - layer index - I - neuron index (within layer) - FKind - activation function type (used by MLPActivationFunction()) - this value must be zero for input neurons - (you can not set activation function for input neurons) - Threshold - also called offset, bias - this value must be zero for input neurons - (you can not set threshold for input neurons) - -NOTES: -1. this function throws exception if layer or neuron with given index do - not exists. -2. this function also throws exception when you try to set non-linear - activation function for input neurons (any kind of network) or for output - neurons of classifier network. -3. this function throws exception when you try to set non-zero threshold for - input neurons (any kind of network). - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpsetneuroninfo(multilayerperceptron* network, - ae_int_t k, - ae_int_t i, - ae_int_t fkind, - double threshold, - ae_state *_state) -{ - ae_int_t ncnt; - ae_int_t istart; - ae_int_t highlevelidx; - ae_int_t activationoffset; - - - ae_assert(ae_isfinite(threshold, _state), "MLPSetNeuronInfo: infinite or NAN Threshold", _state); - - /* - * convenience vars - */ - ncnt = network->hlneurons.cnt/mlpbase_hlnfieldwidth; - istart = network->structinfo.ptr.p_int[5]; - - /* - * search - */ - network->integerbuf.ptr.p_int[0] = k; - network->integerbuf.ptr.p_int[1] = i; - highlevelidx = recsearch(&network->hlneurons, mlpbase_hlnfieldwidth, 2, 0, ncnt, &network->integerbuf, _state); - ae_assert(highlevelidx>=0, "MLPSetNeuronInfo: incorrect (nonexistent) layer or neuron index", _state); - - /* - * activation function - */ - if( network->hlneurons.ptr.p_int[highlevelidx*mlpbase_hlnfieldwidth+2]>=0 ) - { - activationoffset = istart+network->hlneurons.ptr.p_int[highlevelidx*mlpbase_hlnfieldwidth+2]*mlpbase_nfieldwidth; - network->structinfo.ptr.p_int[activationoffset+0] = fkind; - } - else - { - ae_assert(fkind==0, "MLPSetNeuronInfo: you try to set activation function for neuron which can not have one", _state); - } - - /* - * Threshold - */ - if( network->hlneurons.ptr.p_int[highlevelidx*mlpbase_hlnfieldwidth+3]>=0 ) - { - network->weights.ptr.p_double[network->hlneurons.ptr.p_int[highlevelidx*mlpbase_hlnfieldwidth+3]] = threshold; - } - else - { - ae_assert(ae_fp_eq(threshold,(double)(0)), "MLPSetNeuronInfo: you try to set non-zero threshold for neuron which can not have one", _state); - } -} - - -/************************************************************************* -This function modifies information about connection from I0-th neuron of -K0-th layer to I1-th neuron of K1-th layer. - -INPUT PARAMETERS: - Network - network - K0 - layer index - I0 - neuron index (within layer) - K1 - layer index - I1 - neuron index (within layer) - W - connection weight (must be zero for non-existent - connections) - -This function: -1. throws exception if layer or neuron with given index do not exists. -2. throws exception if you try to set non-zero weight for non-existent - connection - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpsetweight(multilayerperceptron* network, - ae_int_t k0, - ae_int_t i0, - ae_int_t k1, - ae_int_t i1, - double w, - ae_state *_state) -{ - ae_int_t ccnt; - ae_int_t highlevelidx; - - - ccnt = network->hlconnections.cnt/mlpbase_hlconnfieldwidth; - - /* - * check params - */ - ae_assert(k0>=0&&k0hllayersizes.cnt, "MLPSetWeight: incorrect (nonexistent) K0", _state); - ae_assert(i0>=0&&i0hllayersizes.ptr.p_int[k0], "MLPSetWeight: incorrect (nonexistent) I0", _state); - ae_assert(k1>=0&&k1hllayersizes.cnt, "MLPSetWeight: incorrect (nonexistent) K1", _state); - ae_assert(i1>=0&&i1hllayersizes.ptr.p_int[k1], "MLPSetWeight: incorrect (nonexistent) I1", _state); - ae_assert(ae_isfinite(w, _state), "MLPSetWeight: infinite or NAN weight", _state); - - /* - * search - */ - network->integerbuf.ptr.p_int[0] = k0; - network->integerbuf.ptr.p_int[1] = i0; - network->integerbuf.ptr.p_int[2] = k1; - network->integerbuf.ptr.p_int[3] = i1; - highlevelidx = recsearch(&network->hlconnections, mlpbase_hlconnfieldwidth, 4, 0, ccnt, &network->integerbuf, _state); - if( highlevelidx>=0 ) - { - network->weights.ptr.p_double[network->hlconnections.ptr.p_int[highlevelidx*mlpbase_hlconnfieldwidth+4]] = w; - } - else - { - ae_assert(ae_fp_eq(w,(double)(0)), "MLPSetWeight: you try to set non-zero weight for non-existent connection", _state); - } -} - - -/************************************************************************* -Neural network activation function - -INPUT PARAMETERS: - NET - neuron input - K - function index (zero for linear function) - -OUTPUT PARAMETERS: - F - function - DF - its derivative - D2F - its second derivative - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpactivationfunction(double net, - ae_int_t k, - double* f, - double* df, - double* d2f, - ae_state *_state) -{ - double net2; - double arg; - double root; - double r; - - *f = 0; - *df = 0; - *d2f = 0; - - if( k==0||k==-5 ) - { - *f = net; - *df = (double)(1); - *d2f = (double)(0); - return; - } - if( k==1 ) - { - - /* - * TanH activation function - */ - if( ae_fp_less(ae_fabs(net, _state),(double)(100)) ) - { - *f = ae_tanh(net, _state); - } - else - { - *f = (double)(ae_sign(net, _state)); - } - *df = 1-*f*(*f); - *d2f = -2*(*f)*(*df); - return; - } - if( k==3 ) - { - - /* - * EX activation function - */ - if( ae_fp_greater_eq(net,(double)(0)) ) - { - net2 = net*net; - arg = net2+1; - root = ae_sqrt(arg, _state); - *f = net+root; - r = net/root; - *df = 1+r; - *d2f = (root-net*r)/arg; - } - else - { - *f = ae_exp(net, _state); - *df = *f; - *d2f = *f; - } - return; - } - if( k==2 ) - { - *f = ae_exp(-ae_sqr(net, _state), _state); - *df = -2*net*(*f); - *d2f = -2*(*f+*df*net); - return; - } - *f = (double)(0); - *df = (double)(0); - *d2f = (double)(0); -} - - -/************************************************************************* -Procesing - -INPUT PARAMETERS: - Network - neural network - X - input vector, array[0..NIn-1]. - -OUTPUT PARAMETERS: - Y - result. Regression estimate when solving regression task, - vector of posterior probabilities for classification task. - -See also MLPProcessI - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpprocess(multilayerperceptron* network, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - - - if( y->cntstructinfo.ptr.p_int[2] ) - { - ae_vector_set_length(y, network->structinfo.ptr.p_int[2], _state); - } - mlpinternalprocessvector(&network->structinfo, &network->weights, &network->columnmeans, &network->columnsigmas, &network->neurons, &network->dfdnet, x, y, _state); -} - - -/************************************************************************* -'interactive' variant of MLPProcess for languages like Python which -support constructs like "Y = MLPProcess(NN,X)" and interactive mode of the -interpreter - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 21.09.2010 by Bochkanov Sergey -*************************************************************************/ -void mlpprocessi(multilayerperceptron* network, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - - ae_vector_clear(y); - - mlpprocess(network, x, y, _state); -} - - -/************************************************************************* -Error of the neural network on dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: - sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2) - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -double mlperror(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - double result; - - - ae_assert(xy->rows>=npoints, "MLPError: XY has less than NPoints rows", _state); - if( npoints>0 ) - { - if( mlpissoftmax(network, _state) ) - { - ae_assert(xy->cols>=mlpgetinputscount(network, _state)+1, "MLPError: XY has less than NIn+1 columns", _state); - } - else - { - ae_assert(xy->cols>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPError: XY has less than NIn+NOut columns", _state); - } - } - mlpallerrorsx(network, xy, &network->dummysxy, npoints, 0, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state); - result = ae_sqr(network->err.rmserror, _state)*npoints*mlpgetoutputscount(network, _state)/2; - return result; -} - - -/************************************************************************* -Error of the neural network on dataset given by sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - NPoints - points count, >=0 - -RESULT: - sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2) - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -double mlperrorsparse(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - double result; - - - ae_assert(sparseiscrs(xy, _state), "MLPErrorSparse: XY is not in CRS format.", _state); - ae_assert(sparsegetnrows(xy, _state)>=npoints, "MLPErrorSparse: XY has less than NPoints rows", _state); - if( npoints>0 ) - { - if( mlpissoftmax(network, _state) ) - { - ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+1, "MLPErrorSparse: XY has less than NIn+1 columns", _state); - } - else - { - ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPErrorSparse: XY has less than NIn+NOut columns", _state); - } - } - mlpallerrorsx(network, &network->dummydxy, xy, npoints, 1, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state); - result = ae_sqr(network->err.rmserror, _state)*npoints*mlpgetoutputscount(network, _state)/2; - return result; -} - - -/************************************************************************* -Natural error function for neural network, internal subroutine. - -NOTE: this function is single-threaded. Unlike other error function, it -receives no speed-up from being executed in SMP mode. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -double mlperrorn(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t ssize, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - double e; - double result; - - - mlpproperties(network, &nin, &nout, &wcount, _state); - result = (double)(0); - for(i=0; i<=ssize-1; i++) - { - - /* - * Process vector - */ - ae_v_move(&network->x.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nin-1)); - mlpprocess(network, &network->x, &network->y, _state); - - /* - * Update error function - */ - if( network->structinfo.ptr.p_int[6]==0 ) - { - - /* - * Least squares error function - */ - ae_v_sub(&network->y.ptr.p_double[0], 1, &xy->ptr.pp_double[i][nin], 1, ae_v_len(0,nout-1)); - e = ae_v_dotproduct(&network->y.ptr.p_double[0], 1, &network->y.ptr.p_double[0], 1, ae_v_len(0,nout-1)); - result = result+e/2; - } - else - { - - /* - * Cross-entropy error function - */ - k = ae_round(xy->ptr.pp_double[i][nin], _state); - if( k>=0&&ky.ptr.p_double[k], _state); - } - } - } - return result; -} - - -/************************************************************************* -Classification error of the neural network on dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: - classification error (number of misclassified cases) - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mlpclserror(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_int_t result; - - - ae_assert(xy->rows>=npoints, "MLPClsError: XY has less than NPoints rows", _state); - if( npoints>0 ) - { - if( mlpissoftmax(network, _state) ) - { - ae_assert(xy->cols>=mlpgetinputscount(network, _state)+1, "MLPClsError: XY has less than NIn+1 columns", _state); - } - else - { - ae_assert(xy->cols>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPClsError: XY has less than NIn+NOut columns", _state); - } - } - mlpallerrorsx(network, xy, &network->dummysxy, npoints, 0, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state); - result = ae_round(npoints*network->err.relclserror, _state); - return result; -} - - -/************************************************************************* -Relative classification error on the test set. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: -Percent of incorrectly classified cases. Works both for classifier -networks and general purpose networks used as classifiers. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 25.12.2008 by Bochkanov Sergey -*************************************************************************/ -double mlprelclserror(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - double result; - - - ae_assert(xy->rows>=npoints, "MLPRelClsError: XY has less than NPoints rows", _state); - if( npoints>0 ) - { - if( mlpissoftmax(network, _state) ) - { - ae_assert(xy->cols>=mlpgetinputscount(network, _state)+1, "MLPRelClsError: XY has less than NIn+1 columns", _state); - } - else - { - ae_assert(xy->cols>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPRelClsError: XY has less than NIn+NOut columns", _state); - } - } - if( npoints>0 ) - { - result = (double)mlpclserror(network, xy, npoints, _state)/(double)npoints; - } - else - { - result = 0.0; - } - return result; -} - - -/************************************************************************* -Relative classification error on the test set given by sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. Sparse matrix must use CRS format - for storage. - NPoints - points count, >=0. - -RESULT: -Percent of incorrectly classified cases. Works both for classifier -networks and general purpose networks used as classifiers. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 09.08.2012 by Bochkanov Sergey -*************************************************************************/ -double mlprelclserrorsparse(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - double result; - - - ae_assert(sparseiscrs(xy, _state), "MLPRelClsErrorSparse: sparse matrix XY is not in CRS format.", _state); - ae_assert(sparsegetnrows(xy, _state)>=npoints, "MLPRelClsErrorSparse: sparse matrix XY has less than NPoints rows", _state); - if( npoints>0 ) - { - if( mlpissoftmax(network, _state) ) - { - ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+1, "MLPRelClsErrorSparse: sparse matrix XY has less than NIn+1 columns", _state); - } - else - { - ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPRelClsErrorSparse: sparse matrix XY has less than NIn+NOut columns", _state); - } - } - mlpallerrorsx(network, &network->dummydxy, xy, npoints, 1, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state); - result = network->err.relclserror; - return result; -} - - -/************************************************************************* -Average cross-entropy (in bits per element) on the test set. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: -CrossEntropy/(NPoints*LN(2)). -Zero if network solves regression task. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 08.01.2009 by Bochkanov Sergey -*************************************************************************/ -double mlpavgce(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - double result; - - - ae_assert(xy->rows>=npoints, "MLPAvgCE: XY has less than NPoints rows", _state); - if( npoints>0 ) - { - if( mlpissoftmax(network, _state) ) - { - ae_assert(xy->cols>=mlpgetinputscount(network, _state)+1, "MLPAvgCE: XY has less than NIn+1 columns", _state); - } - else - { - ae_assert(xy->cols>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPAvgCE: XY has less than NIn+NOut columns", _state); - } - } - mlpallerrorsx(network, xy, &network->dummysxy, npoints, 0, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state); - result = network->err.avgce; - return result; -} - - -/************************************************************************* -Average cross-entropy (in bits per element) on the test set given by -sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - NPoints - points count, >=0. - -RESULT: -CrossEntropy/(NPoints*LN(2)). -Zero if network solves regression task. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 9.08.2012 by Bochkanov Sergey -*************************************************************************/ -double mlpavgcesparse(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - double result; - - - ae_assert(sparseiscrs(xy, _state), "MLPAvgCESparse: sparse matrix XY is not in CRS format.", _state); - ae_assert(sparsegetnrows(xy, _state)>=npoints, "MLPAvgCESparse: sparse matrix XY has less than NPoints rows", _state); - if( npoints>0 ) - { - if( mlpissoftmax(network, _state) ) - { - ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+1, "MLPAvgCESparse: sparse matrix XY has less than NIn+1 columns", _state); - } - else - { - ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPAvgCESparse: sparse matrix XY has less than NIn+NOut columns", _state); - } - } - mlpallerrorsx(network, &network->dummydxy, xy, npoints, 1, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state); - result = network->err.avgce; - return result; -} - - -/************************************************************************* -RMS error on the test set given. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: -Root mean square error. Its meaning for regression task is obvious. As for -classification task, RMS error means error when estimating posterior -probabilities. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -double mlprmserror(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - double result; - - - ae_assert(xy->rows>=npoints, "MLPRMSError: XY has less than NPoints rows", _state); - if( npoints>0 ) - { - if( mlpissoftmax(network, _state) ) - { - ae_assert(xy->cols>=mlpgetinputscount(network, _state)+1, "MLPRMSError: XY has less than NIn+1 columns", _state); - } - else - { - ae_assert(xy->cols>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPRMSError: XY has less than NIn+NOut columns", _state); - } - } - mlpallerrorsx(network, xy, &network->dummysxy, npoints, 0, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state); - result = network->err.rmserror; - return result; -} - - -/************************************************************************* -RMS error on the test set given by sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - NPoints - points count, >=0. - -RESULT: -Root mean square error. Its meaning for regression task is obvious. As for -classification task, RMS error means error when estimating posterior -probabilities. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 09.08.2012 by Bochkanov Sergey -*************************************************************************/ -double mlprmserrorsparse(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - double result; - - - ae_assert(sparseiscrs(xy, _state), "MLPRMSErrorSparse: sparse matrix XY is not in CRS format.", _state); - ae_assert(sparsegetnrows(xy, _state)>=npoints, "MLPRMSErrorSparse: sparse matrix XY has less than NPoints rows", _state); - if( npoints>0 ) - { - if( mlpissoftmax(network, _state) ) - { - ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+1, "MLPRMSErrorSparse: sparse matrix XY has less than NIn+1 columns", _state); - } - else - { - ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPRMSErrorSparse: sparse matrix XY has less than NIn+NOut columns", _state); - } - } - mlpallerrorsx(network, &network->dummydxy, xy, npoints, 1, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state); - result = network->err.rmserror; - return result; -} - - -/************************************************************************* -Average absolute error on the test set. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: -Its meaning for regression task is obvious. As for classification task, it -means average error when estimating posterior probabilities. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 11.03.2008 by Bochkanov Sergey -*************************************************************************/ -double mlpavgerror(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - double result; - - - ae_assert(xy->rows>=npoints, "MLPAvgError: XY has less than NPoints rows", _state); - if( npoints>0 ) - { - if( mlpissoftmax(network, _state) ) - { - ae_assert(xy->cols>=mlpgetinputscount(network, _state)+1, "MLPAvgError: XY has less than NIn+1 columns", _state); - } - else - { - ae_assert(xy->cols>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPAvgError: XY has less than NIn+NOut columns", _state); - } - } - mlpallerrorsx(network, xy, &network->dummysxy, npoints, 0, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state); - result = network->err.avgerror; - return result; -} - - -/************************************************************************* -Average absolute error on the test set given by sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - NPoints - points count, >=0. - -RESULT: -Its meaning for regression task is obvious. As for classification task, it -means average error when estimating posterior probabilities. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 09.08.2012 by Bochkanov Sergey -*************************************************************************/ -double mlpavgerrorsparse(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - double result; - - - ae_assert(sparseiscrs(xy, _state), "MLPAvgErrorSparse: XY is not in CRS format.", _state); - ae_assert(sparsegetnrows(xy, _state)>=npoints, "MLPAvgErrorSparse: XY has less than NPoints rows", _state); - if( npoints>0 ) - { - if( mlpissoftmax(network, _state) ) - { - ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+1, "MLPAvgErrorSparse: XY has less than NIn+1 columns", _state); - } - else - { - ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPAvgErrorSparse: XY has less than NIn+NOut columns", _state); - } - } - mlpallerrorsx(network, &network->dummydxy, xy, npoints, 1, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state); - result = network->err.avgerror; - return result; -} - - -/************************************************************************* -Average relative error on the test set. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: -Its meaning for regression task is obvious. As for classification task, it -means average relative error when estimating posterior probability of -belonging to the correct class. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 11.03.2008 by Bochkanov Sergey -*************************************************************************/ -double mlpavgrelerror(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - double result; - - - ae_assert(xy->rows>=npoints, "MLPAvgRelError: XY has less than NPoints rows", _state); - if( npoints>0 ) - { - if( mlpissoftmax(network, _state) ) - { - ae_assert(xy->cols>=mlpgetinputscount(network, _state)+1, "MLPAvgRelError: XY has less than NIn+1 columns", _state); - } - else - { - ae_assert(xy->cols>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPAvgRelError: XY has less than NIn+NOut columns", _state); - } - } - mlpallerrorsx(network, xy, &network->dummysxy, npoints, 0, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state); - result = network->err.avgrelerror; - return result; -} - - -/************************************************************************* -Average relative error on the test set given by sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - NPoints - points count, >=0. - -RESULT: -Its meaning for regression task is obvious. As for classification task, it -means average relative error when estimating posterior probability of -belonging to the correct class. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 09.08.2012 by Bochkanov Sergey -*************************************************************************/ -double mlpavgrelerrorsparse(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - double result; - - - ae_assert(sparseiscrs(xy, _state), "MLPAvgRelErrorSparse: XY is not in CRS format.", _state); - ae_assert(sparsegetnrows(xy, _state)>=npoints, "MLPAvgRelErrorSparse: XY has less than NPoints rows", _state); - if( npoints>0 ) - { - if( mlpissoftmax(network, _state) ) - { - ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+1, "MLPAvgRelErrorSparse: XY has less than NIn+1 columns", _state); - } - else - { - ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPAvgRelErrorSparse: XY has less than NIn+NOut columns", _state); - } - } - mlpallerrorsx(network, &network->dummydxy, xy, npoints, 1, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state); - result = network->err.avgrelerror; - return result; -} - - -/************************************************************************* -Gradient calculation - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - X - input vector, length of array must be at least NIn - DesiredY- desired outputs, length of array must be at least NOut - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) - Grad - gradient of E with respect to weights of network, array[WCount] - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpgrad(multilayerperceptron* network, - /* Real */ ae_vector* x, - /* Real */ ae_vector* desiredy, - double* e, - /* Real */ ae_vector* grad, - ae_state *_state) -{ - ae_int_t i; - ae_int_t nout; - ae_int_t ntotal; - - *e = 0; - - - /* - * Alloc - */ - rvectorsetlengthatleast(grad, network->structinfo.ptr.p_int[4], _state); - - /* - * Prepare dError/dOut, internal structures - */ - mlpprocess(network, x, &network->y, _state); - nout = network->structinfo.ptr.p_int[2]; - ntotal = network->structinfo.ptr.p_int[3]; - *e = (double)(0); - for(i=0; i<=ntotal-1; i++) - { - network->derror.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=nout-1; i++) - { - network->derror.ptr.p_double[ntotal-nout+i] = network->y.ptr.p_double[i]-desiredy->ptr.p_double[i]; - *e = *e+ae_sqr(network->y.ptr.p_double[i]-desiredy->ptr.p_double[i], _state)/2; - } - - /* - * gradient - */ - mlpbase_mlpinternalcalculategradient(network, &network->neurons, &network->weights, &network->derror, grad, ae_false, _state); -} - - -/************************************************************************* -Gradient calculation (natural error function is used) - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - X - input vector, length of array must be at least NIn - DesiredY- desired outputs, length of array must be at least NOut - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, sum-of-squares for regression networks, - cross-entropy for classification networks. - Grad - gradient of E with respect to weights of network, array[WCount] - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpgradn(multilayerperceptron* network, - /* Real */ ae_vector* x, - /* Real */ ae_vector* desiredy, - double* e, - /* Real */ ae_vector* grad, - ae_state *_state) -{ - double s; - ae_int_t i; - ae_int_t nout; - ae_int_t ntotal; - - *e = 0; - - - /* - * Alloc - */ - rvectorsetlengthatleast(grad, network->structinfo.ptr.p_int[4], _state); - - /* - * Prepare dError/dOut, internal structures - */ - mlpprocess(network, x, &network->y, _state); - nout = network->structinfo.ptr.p_int[2]; - ntotal = network->structinfo.ptr.p_int[3]; - for(i=0; i<=ntotal-1; i++) - { - network->derror.ptr.p_double[i] = (double)(0); - } - *e = (double)(0); - if( network->structinfo.ptr.p_int[6]==0 ) - { - - /* - * Regression network, least squares - */ - for(i=0; i<=nout-1; i++) - { - network->derror.ptr.p_double[ntotal-nout+i] = network->y.ptr.p_double[i]-desiredy->ptr.p_double[i]; - *e = *e+ae_sqr(network->y.ptr.p_double[i]-desiredy->ptr.p_double[i], _state)/2; - } - } - else - { - - /* - * Classification network, cross-entropy - */ - s = (double)(0); - for(i=0; i<=nout-1; i++) - { - s = s+desiredy->ptr.p_double[i]; - } - for(i=0; i<=nout-1; i++) - { - network->derror.ptr.p_double[ntotal-nout+i] = s*network->y.ptr.p_double[i]-desiredy->ptr.p_double[i]; - *e = *e+mlpbase_safecrossentropy(desiredy->ptr.p_double[i], network->y.ptr.p_double[i], _state); - } - } - - /* - * gradient - */ - mlpbase_mlpinternalcalculategradient(network, &network->neurons, &network->weights, &network->derror, grad, ae_true, _state); -} - - -/************************************************************************* -Batch gradient calculation for a set of inputs/outputs - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset in dense format; one sample = one row: - * first NIn columns contain inputs, - * for regression problem, next NOut columns store - desired outputs. - * for classification problem, next column (just one!) - stores class number. - SSize - number of elements in XY - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) - Grad - gradient of E with respect to weights of network, array[WCount] - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpgradbatch(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t ssize, - double* e, - /* Real */ ae_vector* grad, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t subset0; - ae_int_t subset1; - ae_int_t subsettype; - smlpgrad *sgrad; - ae_smart_ptr _sgrad; - - ae_frame_make(_state, &_frame_block); - memset(&_sgrad, 0, sizeof(_sgrad)); - *e = 0; - ae_smart_ptr_init(&_sgrad, (void**)&sgrad, _state, ae_true); - - ae_assert(ssize>=0, "MLPGradBatchSparse: SSize<0", _state); - subset0 = 0; - subset1 = ssize; - subsettype = 0; - mlpproperties(network, &nin, &nout, &wcount, _state); - rvectorsetlengthatleast(grad, wcount, _state); - ae_shared_pool_first_recycled(&network->gradbuf, &_sgrad, _state); - while(sgrad!=NULL) - { - sgrad->f = 0.0; - for(i=0; i<=wcount-1; i++) - { - sgrad->g.ptr.p_double[i] = 0.0; - } - ae_shared_pool_next_recycled(&network->gradbuf, &_sgrad, _state); - } - mlpgradbatchx(network, xy, &network->dummysxy, ssize, 0, &network->dummyidx, subset0, subset1, subsettype, &network->buf, &network->gradbuf, _state); - *e = 0.0; - for(i=0; i<=wcount-1; i++) - { - grad->ptr.p_double[i] = 0.0; - } - ae_shared_pool_first_recycled(&network->gradbuf, &_sgrad, _state); - while(sgrad!=NULL) - { - *e = *e+sgrad->f; - for(i=0; i<=wcount-1; i++) - { - grad->ptr.p_double[i] = grad->ptr.p_double[i]+sgrad->g.ptr.p_double[i]; - } - ae_shared_pool_next_recycled(&network->gradbuf, &_sgrad, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Batch gradient calculation for a set of inputs/outputs given by sparse -matrices - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset in sparse format; one sample = one row: - * MATRIX MUST BE STORED IN CRS FORMAT - * first NIn columns contain inputs. - * for regression problem, next NOut columns store - desired outputs. - * for classification problem, next column (just one!) - stores class number. - SSize - number of elements in XY - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) - Grad - gradient of E with respect to weights of network, array[WCount] - - -- ALGLIB -- - Copyright 26.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpgradbatchsparse(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t ssize, - double* e, - /* Real */ ae_vector* grad, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t subset0; - ae_int_t subset1; - ae_int_t subsettype; - smlpgrad *sgrad; - ae_smart_ptr _sgrad; - - ae_frame_make(_state, &_frame_block); - memset(&_sgrad, 0, sizeof(_sgrad)); - *e = 0; - ae_smart_ptr_init(&_sgrad, (void**)&sgrad, _state, ae_true); - - ae_assert(ssize>=0, "MLPGradBatchSparse: SSize<0", _state); - ae_assert(sparseiscrs(xy, _state), "MLPGradBatchSparse: sparse matrix XY must be in CRS format.", _state); - subset0 = 0; - subset1 = ssize; - subsettype = 0; - mlpproperties(network, &nin, &nout, &wcount, _state); - rvectorsetlengthatleast(grad, wcount, _state); - ae_shared_pool_first_recycled(&network->gradbuf, &_sgrad, _state); - while(sgrad!=NULL) - { - sgrad->f = 0.0; - for(i=0; i<=wcount-1; i++) - { - sgrad->g.ptr.p_double[i] = 0.0; - } - ae_shared_pool_next_recycled(&network->gradbuf, &_sgrad, _state); - } - mlpgradbatchx(network, &network->dummydxy, xy, ssize, 1, &network->dummyidx, subset0, subset1, subsettype, &network->buf, &network->gradbuf, _state); - *e = 0.0; - for(i=0; i<=wcount-1; i++) - { - grad->ptr.p_double[i] = 0.0; - } - ae_shared_pool_first_recycled(&network->gradbuf, &_sgrad, _state); - while(sgrad!=NULL) - { - *e = *e+sgrad->f; - for(i=0; i<=wcount-1; i++) - { - grad->ptr.p_double[i] = grad->ptr.p_double[i]+sgrad->g.ptr.p_double[i]; - } - ae_shared_pool_next_recycled(&network->gradbuf, &_sgrad, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Batch gradient calculation for a subset of dataset - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset in dense format; one sample = one row: - * first NIn columns contain inputs, - * for regression problem, next NOut columns store - desired outputs. - * for classification problem, next column (just one!) - stores class number. - SetSize - real size of XY, SetSize>=0; - Idx - subset of SubsetSize elements, array[SubsetSize]: - * Idx[I] stores row index in the original dataset which is - given by XY. Gradient is calculated with respect to rows - whose indexes are stored in Idx[]. - * Idx[] must store correct indexes; this function throws - an exception in case incorrect index (less than 0 or - larger than rows(XY)) is given - * Idx[] may store indexes in any order and even with - repetitions. - SubsetSize- number of elements in Idx[] array: - * positive value means that subset given by Idx[] is processed - * zero value results in zero gradient - * negative value means that full dataset is processed - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) - Grad - gradient of E with respect to weights of network, - array[WCount] - - -- ALGLIB -- - Copyright 26.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpgradbatchsubset(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t setsize, - /* Integer */ ae_vector* idx, - ae_int_t subsetsize, - double* e, - /* Real */ ae_vector* grad, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t npoints; - ae_int_t subset0; - ae_int_t subset1; - ae_int_t subsettype; - smlpgrad *sgrad; - ae_smart_ptr _sgrad; - - ae_frame_make(_state, &_frame_block); - memset(&_sgrad, 0, sizeof(_sgrad)); - *e = 0; - ae_smart_ptr_init(&_sgrad, (void**)&sgrad, _state, ae_true); - - ae_assert(setsize>=0, "MLPGradBatchSubset: SetSize<0", _state); - ae_assert(subsetsize<=idx->cnt, "MLPGradBatchSubset: SubsetSize>Length(Idx)", _state); - npoints = setsize; - if( subsetsize<0 ) - { - subset0 = 0; - subset1 = setsize; - subsettype = 0; - } - else - { - subset0 = 0; - subset1 = subsetsize; - subsettype = 1; - for(i=0; i<=subsetsize-1; i++) - { - ae_assert(idx->ptr.p_int[i]>=0, "MLPGradBatchSubset: incorrect index of XY row(Idx[I]<0)", _state); - ae_assert(idx->ptr.p_int[i]<=npoints-1, "MLPGradBatchSubset: incorrect index of XY row(Idx[I]>Rows(XY)-1)", _state); - } - } - mlpproperties(network, &nin, &nout, &wcount, _state); - rvectorsetlengthatleast(grad, wcount, _state); - ae_shared_pool_first_recycled(&network->gradbuf, &_sgrad, _state); - while(sgrad!=NULL) - { - sgrad->f = 0.0; - for(i=0; i<=wcount-1; i++) - { - sgrad->g.ptr.p_double[i] = 0.0; - } - ae_shared_pool_next_recycled(&network->gradbuf, &_sgrad, _state); - } - mlpgradbatchx(network, xy, &network->dummysxy, setsize, 0, idx, subset0, subset1, subsettype, &network->buf, &network->gradbuf, _state); - *e = 0.0; - for(i=0; i<=wcount-1; i++) - { - grad->ptr.p_double[i] = 0.0; - } - ae_shared_pool_first_recycled(&network->gradbuf, &_sgrad, _state); - while(sgrad!=NULL) - { - *e = *e+sgrad->f; - for(i=0; i<=wcount-1; i++) - { - grad->ptr.p_double[i] = grad->ptr.p_double[i]+sgrad->g.ptr.p_double[i]; - } - ae_shared_pool_next_recycled(&network->gradbuf, &_sgrad, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Batch gradient calculation for a set of inputs/outputs for a subset of -dataset given by set of indexes. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset in sparse format; one sample = one row: - * MATRIX MUST BE STORED IN CRS FORMAT - * first NIn columns contain inputs, - * for regression problem, next NOut columns store - desired outputs. - * for classification problem, next column (just one!) - stores class number. - SetSize - real size of XY, SetSize>=0; - Idx - subset of SubsetSize elements, array[SubsetSize]: - * Idx[I] stores row index in the original dataset which is - given by XY. Gradient is calculated with respect to rows - whose indexes are stored in Idx[]. - * Idx[] must store correct indexes; this function throws - an exception in case incorrect index (less than 0 or - larger than rows(XY)) is given - * Idx[] may store indexes in any order and even with - repetitions. - SubsetSize- number of elements in Idx[] array: - * positive value means that subset given by Idx[] is processed - * zero value results in zero gradient - * negative value means that full dataset is processed - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) - Grad - gradient of E with respect to weights of network, - array[WCount] - -NOTE: when SubsetSize<0 is used full dataset by call MLPGradBatchSparse - function. - - -- ALGLIB -- - Copyright 26.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpgradbatchsparsesubset(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t setsize, - /* Integer */ ae_vector* idx, - ae_int_t subsetsize, - double* e, - /* Real */ ae_vector* grad, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t npoints; - ae_int_t subset0; - ae_int_t subset1; - ae_int_t subsettype; - smlpgrad *sgrad; - ae_smart_ptr _sgrad; - - ae_frame_make(_state, &_frame_block); - memset(&_sgrad, 0, sizeof(_sgrad)); - *e = 0; - ae_smart_ptr_init(&_sgrad, (void**)&sgrad, _state, ae_true); - - ae_assert(setsize>=0, "MLPGradBatchSparseSubset: SetSize<0", _state); - ae_assert(subsetsize<=idx->cnt, "MLPGradBatchSparseSubset: SubsetSize>Length(Idx)", _state); - ae_assert(sparseiscrs(xy, _state), "MLPGradBatchSparseSubset: sparse matrix XY must be in CRS format.", _state); - npoints = setsize; - if( subsetsize<0 ) - { - subset0 = 0; - subset1 = setsize; - subsettype = 0; - } - else - { - subset0 = 0; - subset1 = subsetsize; - subsettype = 1; - for(i=0; i<=subsetsize-1; i++) - { - ae_assert(idx->ptr.p_int[i]>=0, "MLPGradBatchSparseSubset: incorrect index of XY row(Idx[I]<0)", _state); - ae_assert(idx->ptr.p_int[i]<=npoints-1, "MLPGradBatchSparseSubset: incorrect index of XY row(Idx[I]>Rows(XY)-1)", _state); - } - } - mlpproperties(network, &nin, &nout, &wcount, _state); - rvectorsetlengthatleast(grad, wcount, _state); - ae_shared_pool_first_recycled(&network->gradbuf, &_sgrad, _state); - while(sgrad!=NULL) - { - sgrad->f = 0.0; - for(i=0; i<=wcount-1; i++) - { - sgrad->g.ptr.p_double[i] = 0.0; - } - ae_shared_pool_next_recycled(&network->gradbuf, &_sgrad, _state); - } - mlpgradbatchx(network, &network->dummydxy, xy, setsize, 1, idx, subset0, subset1, subsettype, &network->buf, &network->gradbuf, _state); - *e = 0.0; - for(i=0; i<=wcount-1; i++) - { - grad->ptr.p_double[i] = 0.0; - } - ae_shared_pool_first_recycled(&network->gradbuf, &_sgrad, _state); - while(sgrad!=NULL) - { - *e = *e+sgrad->f; - for(i=0; i<=wcount-1; i++) - { - grad->ptr.p_double[i] = grad->ptr.p_double[i]+sgrad->g.ptr.p_double[i]; - } - ae_shared_pool_next_recycled(&network->gradbuf, &_sgrad, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal function which actually calculates batch gradient for a subset or -full dataset, which can be represented in different formats. - -THIS FUNCTION IS NOT INTENDED TO BE USED BY ALGLIB USERS! - - -- ALGLIB -- - Copyright 26.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpgradbatchx(multilayerperceptron* network, - /* Real */ ae_matrix* densexy, - sparsematrix* sparsexy, - ae_int_t datasetsize, - ae_int_t datasettype, - /* Integer */ ae_vector* idx, - ae_int_t subset0, - ae_int_t subset1, - ae_int_t subsettype, - ae_shared_pool* buf, - ae_shared_pool* gradbuf, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t rowsize; - ae_int_t srcidx; - ae_int_t cstart; - ae_int_t csize; - ae_int_t j; - double problemcost; - mlpbuffers *buf2; - ae_smart_ptr _buf2; - ae_int_t len0; - ae_int_t len1; - mlpbuffers *pbuf; - ae_smart_ptr _pbuf; - smlpgrad *sgrad; - ae_smart_ptr _sgrad; - - ae_frame_make(_state, &_frame_block); - memset(&_buf2, 0, sizeof(_buf2)); - memset(&_pbuf, 0, sizeof(_pbuf)); - memset(&_sgrad, 0, sizeof(_sgrad)); - ae_smart_ptr_init(&_buf2, (void**)&buf2, _state, ae_true); - ae_smart_ptr_init(&_pbuf, (void**)&pbuf, _state, ae_true); - ae_smart_ptr_init(&_sgrad, (void**)&sgrad, _state, ae_true); - - ae_assert(datasetsize>=0, "MLPGradBatchX: SetSize<0", _state); - ae_assert(datasettype==0||datasettype==1, "MLPGradBatchX: DatasetType is incorrect", _state); - ae_assert(subsettype==0||subsettype==1, "MLPGradBatchX: SubsetType is incorrect", _state); - - /* - * Determine network and dataset properties - */ - mlpproperties(network, &nin, &nout, &wcount, _state); - if( mlpissoftmax(network, _state) ) - { - rowsize = nin+1; - } - else - { - rowsize = nin+nout; - } - - /* - * Split problem. - * - * Splitting problem allows us to reduce effect of single-precision - * arithmetics (SSE-optimized version of MLPChunkedGradient uses single - * precision internally, but converts them to double precision after - * results are exported from HPC buffer to network). Small batches are - * calculated in single precision, results are aggregated in double - * precision, and it allows us to avoid accumulation of errors when - * we process very large batches (tens of thousands of items). - * - * NOTE: it is important to use real arithmetics for ProblemCost - * because ProblemCost may be larger than MAXINT. - */ - problemcost = (double)(subset1-subset0); - problemcost = problemcost*wcount*2; - if( ae_fp_greater_eq(problemcost,smpactivationlevel(_state))&&subset1-subset0>=2*mlpbase_microbatchsize ) - { - if( _trypexec_mlpgradbatchx(network,densexy,sparsexy,datasetsize,datasettype,idx,subset0,subset1,subsettype,buf,gradbuf, _state) ) - { - ae_frame_leave(_state); - return; - } - } - if( subset1-subset0>=2*mlpbase_microbatchsize&&ae_fp_greater(problemcost,spawnlevel(_state)) ) - { - splitlength(subset1-subset0, mlpbase_microbatchsize, &len0, &len1, _state); - mlpgradbatchx(network, densexy, sparsexy, datasetsize, datasettype, idx, subset0, subset0+len0, subsettype, buf, gradbuf, _state); - mlpgradbatchx(network, densexy, sparsexy, datasetsize, datasettype, idx, subset0+len0, subset1, subsettype, buf, gradbuf, _state); - ae_frame_leave(_state); - return; - } - - /* - * Chunked processing - */ - ae_shared_pool_retrieve(gradbuf, &_sgrad, _state); - ae_shared_pool_retrieve(buf, &_pbuf, _state); - hpcpreparechunkedgradient(&network->weights, wcount, mlpntotal(network, _state), nin, nout, pbuf, _state); - cstart = subset0; - while(cstartchunksize, _state)-cstart; - for(j=0; j<=csize-1; j++) - { - srcidx = -1; - if( subsettype==0 ) - { - srcidx = cstart+j; - } - if( subsettype==1 ) - { - srcidx = idx->ptr.p_int[cstart+j]; - } - ae_assert(srcidx>=0, "MLPGradBatchX: internal error", _state); - if( datasettype==0 ) - { - ae_v_move(&pbuf->xy.ptr.pp_double[j][0], 1, &densexy->ptr.pp_double[srcidx][0], 1, ae_v_len(0,rowsize-1)); - } - if( datasettype==1 ) - { - sparsegetrow(sparsexy, srcidx, &pbuf->xyrow, _state); - ae_v_move(&pbuf->xy.ptr.pp_double[j][0], 1, &pbuf->xyrow.ptr.p_double[0], 1, ae_v_len(0,rowsize-1)); - } - } - - /* - * Process chunk and advance line pointer - */ - mlpbase_mlpchunkedgradient(network, &pbuf->xy, 0, csize, &pbuf->batch4buf, &pbuf->hpcbuf, &sgrad->f, ae_false, _state); - cstart = cstart+pbuf->chunksize; - } - hpcfinalizechunkedgradient(pbuf, &sgrad->g, _state); - ae_shared_pool_recycle(buf, &_pbuf, _state); - ae_shared_pool_recycle(gradbuf, &_sgrad, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_mlpgradbatchx(multilayerperceptron* network, - /* Real */ ae_matrix* densexy, - sparsematrix* sparsexy, - ae_int_t datasetsize, - ae_int_t datasettype, - /* Integer */ ae_vector* idx, - ae_int_t subset0, - ae_int_t subset1, - ae_int_t subsettype, - ae_shared_pool* buf, - ae_shared_pool* gradbuf, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -Batch gradient calculation for a set of inputs/outputs -(natural error function is used) - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - set of inputs/outputs; one sample = one row; - first NIn columns contain inputs, - next NOut columns - desired outputs. - SSize - number of elements in XY - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, sum-of-squares for regression networks, - cross-entropy for classification networks. - Grad - gradient of E with respect to weights of network, array[WCount] - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpgradnbatch(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t ssize, - double* e, - /* Real */ ae_vector* grad, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - mlpbuffers *pbuf; - ae_smart_ptr _pbuf; - - ae_frame_make(_state, &_frame_block); - memset(&_pbuf, 0, sizeof(_pbuf)); - *e = 0; - ae_smart_ptr_init(&_pbuf, (void**)&pbuf, _state, ae_true); - - - /* - * Alloc - */ - mlpproperties(network, &nin, &nout, &wcount, _state); - ae_shared_pool_retrieve(&network->buf, &_pbuf, _state); - hpcpreparechunkedgradient(&network->weights, wcount, mlpntotal(network, _state), nin, nout, pbuf, _state); - rvectorsetlengthatleast(grad, wcount, _state); - for(i=0; i<=wcount-1; i++) - { - grad->ptr.p_double[i] = (double)(0); - } - *e = (double)(0); - i = 0; - while(i<=ssize-1) - { - mlpbase_mlpchunkedgradient(network, xy, i, ae_minint(ssize, i+pbuf->chunksize, _state)-i, &pbuf->batch4buf, &pbuf->hpcbuf, e, ae_true, _state); - i = i+pbuf->chunksize; - } - hpcfinalizechunkedgradient(pbuf, grad, _state); - ae_shared_pool_recycle(&network->buf, &_pbuf, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Batch Hessian calculation (natural error function) using R-algorithm. -Internal subroutine. - - -- ALGLIB -- - Copyright 26.01.2008 by Bochkanov Sergey. - - Hessian calculation based on R-algorithm described in - "Fast Exact Multiplication by the Hessian", - B. A. Pearlmutter, - Neural Computation, 1994. -*************************************************************************/ -void mlphessiannbatch(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t ssize, - double* e, - /* Real */ ae_vector* grad, - /* Real */ ae_matrix* h, - ae_state *_state) -{ - - *e = 0; - - mlpbase_mlphessianbatchinternal(network, xy, ssize, ae_true, e, grad, h, _state); -} - - -/************************************************************************* -Batch Hessian calculation using R-algorithm. -Internal subroutine. - - -- ALGLIB -- - Copyright 26.01.2008 by Bochkanov Sergey. - - Hessian calculation based on R-algorithm described in - "Fast Exact Multiplication by the Hessian", - B. A. Pearlmutter, - Neural Computation, 1994. -*************************************************************************/ -void mlphessianbatch(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t ssize, - double* e, - /* Real */ ae_vector* grad, - /* Real */ ae_matrix* h, - ae_state *_state) -{ - - *e = 0; - - mlpbase_mlphessianbatchinternal(network, xy, ssize, ae_false, e, grad, h, _state); -} - - -/************************************************************************* -Internal subroutine, shouldn't be called by user. -*************************************************************************/ -void mlpinternalprocessvector(/* Integer */ ae_vector* structinfo, - /* Real */ ae_vector* weights, - /* Real */ ae_vector* columnmeans, - /* Real */ ae_vector* columnsigmas, - /* Real */ ae_vector* neurons, - /* Real */ ae_vector* dfdnet, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n1; - ae_int_t n2; - ae_int_t w1; - ae_int_t w2; - ae_int_t ntotal; - ae_int_t nin; - ae_int_t nout; - ae_int_t istart; - ae_int_t offs; - double net; - double f; - double df; - double d2f; - double mx; - ae_bool perr; - - - - /* - * Read network geometry - */ - nin = structinfo->ptr.p_int[1]; - nout = structinfo->ptr.p_int[2]; - ntotal = structinfo->ptr.p_int[3]; - istart = structinfo->ptr.p_int[5]; - - /* - * Inputs standartisation and putting in the network - */ - for(i=0; i<=nin-1; i++) - { - if( ae_fp_neq(columnsigmas->ptr.p_double[i],(double)(0)) ) - { - neurons->ptr.p_double[i] = (x->ptr.p_double[i]-columnmeans->ptr.p_double[i])/columnsigmas->ptr.p_double[i]; - } - else - { - neurons->ptr.p_double[i] = x->ptr.p_double[i]-columnmeans->ptr.p_double[i]; - } - } - - /* - * Process network - */ - for(i=0; i<=ntotal-1; i++) - { - offs = istart+i*mlpbase_nfieldwidth; - if( structinfo->ptr.p_int[offs+0]>0||structinfo->ptr.p_int[offs+0]==-5 ) - { - - /* - * Activation function - */ - mlpactivationfunction(neurons->ptr.p_double[structinfo->ptr.p_int[offs+2]], structinfo->ptr.p_int[offs+0], &f, &df, &d2f, _state); - neurons->ptr.p_double[i] = f; - dfdnet->ptr.p_double[i] = df; - continue; - } - if( structinfo->ptr.p_int[offs+0]==0 ) - { - - /* - * Adaptive summator - */ - n1 = structinfo->ptr.p_int[offs+2]; - n2 = n1+structinfo->ptr.p_int[offs+1]-1; - w1 = structinfo->ptr.p_int[offs+3]; - w2 = w1+structinfo->ptr.p_int[offs+1]-1; - net = ae_v_dotproduct(&weights->ptr.p_double[w1], 1, &neurons->ptr.p_double[n1], 1, ae_v_len(w1,w2)); - neurons->ptr.p_double[i] = net; - dfdnet->ptr.p_double[i] = 1.0; - touchint(&n2, _state); - continue; - } - if( structinfo->ptr.p_int[offs+0]<0 ) - { - perr = ae_true; - if( structinfo->ptr.p_int[offs+0]==-2 ) - { - - /* - * input neuron, left unchanged - */ - perr = ae_false; - } - if( structinfo->ptr.p_int[offs+0]==-3 ) - { - - /* - * "-1" neuron - */ - neurons->ptr.p_double[i] = (double)(-1); - perr = ae_false; - } - if( structinfo->ptr.p_int[offs+0]==-4 ) - { - - /* - * "0" neuron - */ - neurons->ptr.p_double[i] = (double)(0); - perr = ae_false; - } - ae_assert(!perr, "MLPInternalProcessVector: internal error - unknown neuron type!", _state); - continue; - } - } - - /* - * Extract result - */ - ae_v_move(&y->ptr.p_double[0], 1, &neurons->ptr.p_double[ntotal-nout], 1, ae_v_len(0,nout-1)); - - /* - * Softmax post-processing or standardisation if needed - */ - ae_assert(structinfo->ptr.p_int[6]==0||structinfo->ptr.p_int[6]==1, "MLPInternalProcessVector: unknown normalization type!", _state); - if( structinfo->ptr.p_int[6]==1 ) - { - - /* - * Softmax - */ - mx = y->ptr.p_double[0]; - for(i=1; i<=nout-1; i++) - { - mx = ae_maxreal(mx, y->ptr.p_double[i], _state); - } - net = (double)(0); - for(i=0; i<=nout-1; i++) - { - y->ptr.p_double[i] = ae_exp(y->ptr.p_double[i]-mx, _state); - net = net+y->ptr.p_double[i]; - } - for(i=0; i<=nout-1; i++) - { - y->ptr.p_double[i] = y->ptr.p_double[i]/net; - } - } - else - { - - /* - * Standardisation - */ - for(i=0; i<=nout-1; i++) - { - y->ptr.p_double[i] = y->ptr.p_double[i]*columnsigmas->ptr.p_double[nin+i]+columnmeans->ptr.p_double[nin+i]; - } - } -} - - -/************************************************************************* -Serializer: allocation - - -- ALGLIB -- - Copyright 14.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpalloc(ae_serializer* s, - multilayerperceptron* network, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t fkind; - double threshold; - double v0; - double v1; - ae_int_t nin; - ae_int_t nout; - - - nin = network->hllayersizes.ptr.p_int[0]; - nout = network->hllayersizes.ptr.p_int[network->hllayersizes.cnt-1]; - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - allocintegerarray(s, &network->hllayersizes, -1, _state); - for(i=1; i<=network->hllayersizes.cnt-1; i++) - { - for(j=0; j<=network->hllayersizes.ptr.p_int[i]-1; j++) - { - mlpgetneuroninfo(network, i, j, &fkind, &threshold, _state); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - for(k=0; k<=network->hllayersizes.ptr.p_int[i-1]-1; k++) - { - ae_serializer_alloc_entry(s); - } - } - } - for(j=0; j<=nin-1; j++) - { - mlpgetinputscaling(network, j, &v0, &v1, _state); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - } - for(j=0; j<=nout-1; j++) - { - mlpgetoutputscaling(network, j, &v0, &v1, _state); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - } -} - - -/************************************************************************* -Serializer: serialization - - -- ALGLIB -- - Copyright 14.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpserialize(ae_serializer* s, - multilayerperceptron* network, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t fkind; - double threshold; - double v0; - double v1; - ae_int_t nin; - ae_int_t nout; - - - nin = network->hllayersizes.ptr.p_int[0]; - nout = network->hllayersizes.ptr.p_int[network->hllayersizes.cnt-1]; - ae_serializer_serialize_int(s, getmlpserializationcode(_state), _state); - ae_serializer_serialize_int(s, mlpbase_mlpfirstversion, _state); - ae_serializer_serialize_bool(s, mlpissoftmax(network, _state), _state); - serializeintegerarray(s, &network->hllayersizes, -1, _state); - for(i=1; i<=network->hllayersizes.cnt-1; i++) - { - for(j=0; j<=network->hllayersizes.ptr.p_int[i]-1; j++) - { - mlpgetneuroninfo(network, i, j, &fkind, &threshold, _state); - ae_serializer_serialize_int(s, fkind, _state); - ae_serializer_serialize_double(s, threshold, _state); - for(k=0; k<=network->hllayersizes.ptr.p_int[i-1]-1; k++) - { - ae_serializer_serialize_double(s, mlpgetweight(network, i-1, k, i, j, _state), _state); - } - } - } - for(j=0; j<=nin-1; j++) - { - mlpgetinputscaling(network, j, &v0, &v1, _state); - ae_serializer_serialize_double(s, v0, _state); - ae_serializer_serialize_double(s, v1, _state); - } - for(j=0; j<=nout-1; j++) - { - mlpgetoutputscaling(network, j, &v0, &v1, _state); - ae_serializer_serialize_double(s, v0, _state); - ae_serializer_serialize_double(s, v1, _state); - } -} - - -/************************************************************************* -Serializer: unserialization - - -- ALGLIB -- - Copyright 14.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpunserialize(ae_serializer* s, - multilayerperceptron* network, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i0; - ae_int_t i1; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t fkind; - double threshold; - double v0; - double v1; - ae_int_t nin; - ae_int_t nout; - ae_bool issoftmax; - ae_vector layersizes; - - ae_frame_make(_state, &_frame_block); - memset(&layersizes, 0, sizeof(layersizes)); - _multilayerperceptron_clear(network); - ae_vector_init(&layersizes, 0, DT_INT, _state, ae_true); - - - /* - * check correctness of header - */ - ae_serializer_unserialize_int(s, &i0, _state); - ae_assert(i0==getmlpserializationcode(_state), "MLPUnserialize: stream header corrupted", _state); - ae_serializer_unserialize_int(s, &i1, _state); - ae_assert(i1==mlpbase_mlpfirstversion, "MLPUnserialize: stream header corrupted", _state); - - /* - * Create network - */ - ae_serializer_unserialize_bool(s, &issoftmax, _state); - unserializeintegerarray(s, &layersizes, _state); - ae_assert((layersizes.cnt==2||layersizes.cnt==3)||layersizes.cnt==4, "MLPUnserialize: too many hidden layers!", _state); - nin = layersizes.ptr.p_int[0]; - nout = layersizes.ptr.p_int[layersizes.cnt-1]; - if( layersizes.cnt==2 ) - { - if( issoftmax ) - { - mlpcreatec0(layersizes.ptr.p_int[0], layersizes.ptr.p_int[1], network, _state); - } - else - { - mlpcreate0(layersizes.ptr.p_int[0], layersizes.ptr.p_int[1], network, _state); - } - } - if( layersizes.cnt==3 ) - { - if( issoftmax ) - { - mlpcreatec1(layersizes.ptr.p_int[0], layersizes.ptr.p_int[1], layersizes.ptr.p_int[2], network, _state); - } - else - { - mlpcreate1(layersizes.ptr.p_int[0], layersizes.ptr.p_int[1], layersizes.ptr.p_int[2], network, _state); - } - } - if( layersizes.cnt==4 ) - { - if( issoftmax ) - { - mlpcreatec2(layersizes.ptr.p_int[0], layersizes.ptr.p_int[1], layersizes.ptr.p_int[2], layersizes.ptr.p_int[3], network, _state); - } - else - { - mlpcreate2(layersizes.ptr.p_int[0], layersizes.ptr.p_int[1], layersizes.ptr.p_int[2], layersizes.ptr.p_int[3], network, _state); - } - } - - /* - * Load neurons and weights - */ - for(i=1; i<=layersizes.cnt-1; i++) - { - for(j=0; j<=layersizes.ptr.p_int[i]-1; j++) - { - ae_serializer_unserialize_int(s, &fkind, _state); - ae_serializer_unserialize_double(s, &threshold, _state); - mlpsetneuroninfo(network, i, j, fkind, threshold, _state); - for(k=0; k<=layersizes.ptr.p_int[i-1]-1; k++) - { - ae_serializer_unserialize_double(s, &v0, _state); - mlpsetweight(network, i-1, k, i, j, v0, _state); - } - } - } - - /* - * Load standartizator - */ - for(j=0; j<=nin-1; j++) - { - ae_serializer_unserialize_double(s, &v0, _state); - ae_serializer_unserialize_double(s, &v1, _state); - mlpsetinputscaling(network, j, v0, v1, _state); - } - for(j=0; j<=nout-1; j++) - { - ae_serializer_unserialize_double(s, &v0, _state); - ae_serializer_unserialize_double(s, &v1, _state); - mlpsetoutputscaling(network, j, v0, v1, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Calculation of all types of errors on subset of dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset; one sample = one row; - first NIn columns contain inputs, - next NOut columns - desired outputs. - SetSize - real size of XY, SetSize>=0; - Subset - subset of SubsetSize elements, array[SubsetSize]; - SubsetSize- number of elements in Subset[] array: - * if SubsetSize>0, rows of XY with indices Subset[0]... - ...Subset[SubsetSize-1] are processed - * if SubsetSize=0, zeros are returned - * if SubsetSize<0, entire dataset is processed; Subset[] - array is ignored in this case. - -OUTPUT PARAMETERS: - Rep - it contains all type of errors. - - -- ALGLIB -- - Copyright 04.09.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpallerrorssubset(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t setsize, - /* Integer */ ae_vector* subset, - ae_int_t subsetsize, - modelerrors* rep, - ae_state *_state) -{ - ae_int_t idx0; - ae_int_t idx1; - ae_int_t idxtype; - - _modelerrors_clear(rep); - - ae_assert(xy->rows>=setsize, "MLPAllErrorsSubset: XY has less than SetSize rows", _state); - if( setsize>0 ) - { - if( mlpissoftmax(network, _state) ) - { - ae_assert(xy->cols>=mlpgetinputscount(network, _state)+1, "MLPAllErrorsSubset: XY has less than NIn+1 columns", _state); - } - else - { - ae_assert(xy->cols>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPAllErrorsSubset: XY has less than NIn+NOut columns", _state); - } - } - if( subsetsize>=0 ) - { - idx0 = 0; - idx1 = subsetsize; - idxtype = 1; - } - else - { - idx0 = 0; - idx1 = setsize; - idxtype = 0; - } - mlpallerrorsx(network, xy, &network->dummysxy, setsize, 0, subset, idx0, idx1, idxtype, &network->buf, rep, _state); -} - - -/************************************************************************* -Calculation of all types of errors on subset of dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset given by sparse matrix; - one sample = one row; - first NIn columns contain inputs, - next NOut columns - desired outputs. - SetSize - real size of XY, SetSize>=0; - Subset - subset of SubsetSize elements, array[SubsetSize]; - SubsetSize- number of elements in Subset[] array: - * if SubsetSize>0, rows of XY with indices Subset[0]... - ...Subset[SubsetSize-1] are processed - * if SubsetSize=0, zeros are returned - * if SubsetSize<0, entire dataset is processed; Subset[] - array is ignored in this case. - -OUTPUT PARAMETERS: - Rep - it contains all type of errors. - - - -- ALGLIB -- - Copyright 04.09.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpallerrorssparsesubset(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t setsize, - /* Integer */ ae_vector* subset, - ae_int_t subsetsize, - modelerrors* rep, - ae_state *_state) -{ - ae_int_t idx0; - ae_int_t idx1; - ae_int_t idxtype; - - _modelerrors_clear(rep); - - ae_assert(sparseiscrs(xy, _state), "MLPAllErrorsSparseSubset: XY is not in CRS format.", _state); - ae_assert(sparsegetnrows(xy, _state)>=setsize, "MLPAllErrorsSparseSubset: XY has less than SetSize rows", _state); - if( setsize>0 ) - { - if( mlpissoftmax(network, _state) ) - { - ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+1, "MLPAllErrorsSparseSubset: XY has less than NIn+1 columns", _state); - } - else - { - ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPAllErrorsSparseSubset: XY has less than NIn+NOut columns", _state); - } - } - if( subsetsize>=0 ) - { - idx0 = 0; - idx1 = subsetsize; - idxtype = 1; - } - else - { - idx0 = 0; - idx1 = setsize; - idxtype = 0; - } - mlpallerrorsx(network, &network->dummydxy, xy, setsize, 1, subset, idx0, idx1, idxtype, &network->buf, rep, _state); -} - - -/************************************************************************* -Error of the neural network on subset of dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - SetSize - real size of XY, SetSize>=0; - Subset - subset of SubsetSize elements, array[SubsetSize]; - SubsetSize- number of elements in Subset[] array: - * if SubsetSize>0, rows of XY with indices Subset[0]... - ...Subset[SubsetSize-1] are processed - * if SubsetSize=0, zeros are returned - * if SubsetSize<0, entire dataset is processed; Subset[] - array is ignored in this case. - -RESULT: - sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2) - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 04.09.2012 by Bochkanov Sergey -*************************************************************************/ -double mlperrorsubset(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t setsize, - /* Integer */ ae_vector* subset, - ae_int_t subsetsize, - ae_state *_state) -{ - ae_int_t idx0; - ae_int_t idx1; - ae_int_t idxtype; - double result; - - - ae_assert(xy->rows>=setsize, "MLPErrorSubset: XY has less than SetSize rows", _state); - if( setsize>0 ) - { - if( mlpissoftmax(network, _state) ) - { - ae_assert(xy->cols>=mlpgetinputscount(network, _state)+1, "MLPErrorSubset: XY has less than NIn+1 columns", _state); - } - else - { - ae_assert(xy->cols>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPErrorSubset: XY has less than NIn+NOut columns", _state); - } - } - if( subsetsize>=0 ) - { - idx0 = 0; - idx1 = subsetsize; - idxtype = 1; - } - else - { - idx0 = 0; - idx1 = setsize; - idxtype = 0; - } - mlpallerrorsx(network, xy, &network->dummysxy, setsize, 0, subset, idx0, idx1, idxtype, &network->buf, &network->err, _state); - result = ae_sqr(network->err.rmserror, _state)*(idx1-idx0)*mlpgetoutputscount(network, _state)/2; - return result; -} - - -/************************************************************************* -Error of the neural network on subset of sparse dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - SetSize - real size of XY, SetSize>=0; - it is used when SubsetSize<0; - Subset - subset of SubsetSize elements, array[SubsetSize]; - SubsetSize- number of elements in Subset[] array: - * if SubsetSize>0, rows of XY with indices Subset[0]... - ...Subset[SubsetSize-1] are processed - * if SubsetSize=0, zeros are returned - * if SubsetSize<0, entire dataset is processed; Subset[] - array is ignored in this case. - -RESULT: - sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2) - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 04.09.2012 by Bochkanov Sergey -*************************************************************************/ -double mlperrorsparsesubset(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t setsize, - /* Integer */ ae_vector* subset, - ae_int_t subsetsize, - ae_state *_state) -{ - ae_int_t idx0; - ae_int_t idx1; - ae_int_t idxtype; - double result; - - - ae_assert(sparseiscrs(xy, _state), "MLPErrorSparseSubset: XY is not in CRS format.", _state); - ae_assert(sparsegetnrows(xy, _state)>=setsize, "MLPErrorSparseSubset: XY has less than SetSize rows", _state); - if( setsize>0 ) - { - if( mlpissoftmax(network, _state) ) - { - ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+1, "MLPErrorSparseSubset: XY has less than NIn+1 columns", _state); - } - else - { - ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPErrorSparseSubset: XY has less than NIn+NOut columns", _state); - } - } - if( subsetsize>=0 ) - { - idx0 = 0; - idx1 = subsetsize; - idxtype = 1; - } - else - { - idx0 = 0; - idx1 = setsize; - idxtype = 0; - } - mlpallerrorsx(network, &network->dummydxy, xy, setsize, 1, subset, idx0, idx1, idxtype, &network->buf, &network->err, _state); - result = ae_sqr(network->err.rmserror, _state)*(idx1-idx0)*mlpgetoutputscount(network, _state)/2; - return result; -} - - -/************************************************************************* -Calculation of all types of errors at once for a subset or full dataset, -which can be represented in different formats. - -THIS INTERNAL FUNCTION IS NOT INTENDED TO BE USED BY ALGLIB USERS! - - -- ALGLIB -- - Copyright 26.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpallerrorsx(multilayerperceptron* network, - /* Real */ ae_matrix* densexy, - sparsematrix* sparsexy, - ae_int_t datasetsize, - ae_int_t datasettype, - /* Integer */ ae_vector* idx, - ae_int_t subset0, - ae_int_t subset1, - ae_int_t subsettype, - ae_shared_pool* buf, - modelerrors* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t rowsize; - ae_bool iscls; - ae_int_t srcidx; - ae_int_t cstart; - ae_int_t csize; - ae_int_t j; - mlpbuffers *pbuf; - ae_smart_ptr _pbuf; - ae_int_t len0; - ae_int_t len1; - modelerrors rep0; - modelerrors rep1; - double problemcost; - - ae_frame_make(_state, &_frame_block); - memset(&_pbuf, 0, sizeof(_pbuf)); - memset(&rep0, 0, sizeof(rep0)); - memset(&rep1, 0, sizeof(rep1)); - ae_smart_ptr_init(&_pbuf, (void**)&pbuf, _state, ae_true); - _modelerrors_init(&rep0, _state, ae_true); - _modelerrors_init(&rep1, _state, ae_true); - - ae_assert(datasetsize>=0, "MLPAllErrorsX: SetSize<0", _state); - ae_assert(datasettype==0||datasettype==1, "MLPAllErrorsX: DatasetType is incorrect", _state); - ae_assert(subsettype==0||subsettype==1, "MLPAllErrorsX: SubsetType is incorrect", _state); - - /* - * Determine network properties - */ - mlpproperties(network, &nin, &nout, &wcount, _state); - iscls = mlpissoftmax(network, _state); - - /* - * Split problem. - * - * Splitting problem allows us to reduce effect of single-precision - * arithmetics (SSE-optimized version of MLPChunkedProcess uses single - * precision internally, but converts them to double precision after - * results are exported from HPC buffer to network). Small batches are - * calculated in single precision, results are aggregated in double - * precision, and it allows us to avoid accumulation of errors when - * we process very large batches (tens of thousands of items). - * - * NOTE: it is important to use real arithmetics for ProblemCost - * because ProblemCost may be larger than MAXINT. - */ - problemcost = (double)(subset1-subset0); - problemcost = problemcost*wcount*2; - if( ae_fp_greater_eq(problemcost,smpactivationlevel(_state))&&subset1-subset0>=2*mlpbase_microbatchsize ) - { - if( _trypexec_mlpallerrorsx(network,densexy,sparsexy,datasetsize,datasettype,idx,subset0,subset1,subsettype,buf,rep, _state) ) - { - ae_frame_leave(_state); - return; - } - } - if( subset1-subset0>=2*mlpbase_microbatchsize&&ae_fp_greater(problemcost,spawnlevel(_state)) ) - { - splitlength(subset1-subset0, mlpbase_microbatchsize, &len0, &len1, _state); - mlpallerrorsx(network, densexy, sparsexy, datasetsize, datasettype, idx, subset0, subset0+len0, subsettype, buf, &rep0, _state); - mlpallerrorsx(network, densexy, sparsexy, datasetsize, datasettype, idx, subset0+len0, subset1, subsettype, buf, &rep1, _state); - rep->relclserror = (len0*rep0.relclserror+len1*rep1.relclserror)/(len0+len1); - rep->avgce = (len0*rep0.avgce+len1*rep1.avgce)/(len0+len1); - rep->rmserror = ae_sqrt((len0*ae_sqr(rep0.rmserror, _state)+len1*ae_sqr(rep1.rmserror, _state))/(len0+len1), _state); - rep->avgerror = (len0*rep0.avgerror+len1*rep1.avgerror)/(len0+len1); - rep->avgrelerror = (len0*rep0.avgrelerror+len1*rep1.avgrelerror)/(len0+len1); - ae_frame_leave(_state); - return; - } - - /* - * Retrieve and prepare - */ - ae_shared_pool_retrieve(buf, &_pbuf, _state); - if( iscls ) - { - rowsize = nin+1; - dserrallocate(nout, &pbuf->tmp0, _state); - } - else - { - rowsize = nin+nout; - dserrallocate(-nout, &pbuf->tmp0, _state); - } - - /* - * Processing - */ - hpcpreparechunkedgradient(&network->weights, wcount, mlpntotal(network, _state), nin, nout, pbuf, _state); - cstart = subset0; - while(cstartchunksize, _state)-cstart; - for(j=0; j<=csize-1; j++) - { - srcidx = -1; - if( subsettype==0 ) - { - srcidx = cstart+j; - } - if( subsettype==1 ) - { - srcidx = idx->ptr.p_int[cstart+j]; - } - ae_assert(srcidx>=0, "MLPAllErrorsX: internal error", _state); - if( datasettype==0 ) - { - ae_v_move(&pbuf->xy.ptr.pp_double[j][0], 1, &densexy->ptr.pp_double[srcidx][0], 1, ae_v_len(0,rowsize-1)); - } - if( datasettype==1 ) - { - sparsegetrow(sparsexy, srcidx, &pbuf->xyrow, _state); - ae_v_move(&pbuf->xy.ptr.pp_double[j][0], 1, &pbuf->xyrow.ptr.p_double[0], 1, ae_v_len(0,rowsize-1)); - } - } - - /* - * Unpack XY and process (temporary code, to be replaced by chunked processing) - */ - for(j=0; j<=csize-1; j++) - { - ae_v_move(&pbuf->xy2.ptr.pp_double[j][0], 1, &pbuf->xy.ptr.pp_double[j][0], 1, ae_v_len(0,rowsize-1)); - } - mlpbase_mlpchunkedprocess(network, &pbuf->xy2, 0, csize, &pbuf->batch4buf, &pbuf->hpcbuf, _state); - for(j=0; j<=csize-1; j++) - { - ae_v_move(&pbuf->x.ptr.p_double[0], 1, &pbuf->xy2.ptr.pp_double[j][0], 1, ae_v_len(0,nin-1)); - ae_v_move(&pbuf->y.ptr.p_double[0], 1, &pbuf->xy2.ptr.pp_double[j][nin], 1, ae_v_len(0,nout-1)); - if( iscls ) - { - pbuf->desiredy.ptr.p_double[0] = pbuf->xy.ptr.pp_double[j][nin]; - } - else - { - ae_v_move(&pbuf->desiredy.ptr.p_double[0], 1, &pbuf->xy.ptr.pp_double[j][nin], 1, ae_v_len(0,nout-1)); - } - dserraccumulate(&pbuf->tmp0, &pbuf->y, &pbuf->desiredy, _state); - } - - /* - * Process chunk and advance line pointer - */ - cstart = cstart+pbuf->chunksize; - } - dserrfinish(&pbuf->tmp0, _state); - rep->relclserror = pbuf->tmp0.ptr.p_double[0]; - rep->avgce = pbuf->tmp0.ptr.p_double[1]/ae_log((double)(2), _state); - rep->rmserror = pbuf->tmp0.ptr.p_double[2]; - rep->avgerror = pbuf->tmp0.ptr.p_double[3]; - rep->avgrelerror = pbuf->tmp0.ptr.p_double[4]; - - /* - * Recycle - */ - ae_shared_pool_recycle(buf, &_pbuf, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_mlpallerrorsx(multilayerperceptron* network, - /* Real */ ae_matrix* densexy, - sparsematrix* sparsexy, - ae_int_t datasetsize, - ae_int_t datasettype, - /* Integer */ ae_vector* idx, - ae_int_t subset0, - ae_int_t subset1, - ae_int_t subsettype, - ae_shared_pool* buf, - modelerrors* rep, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -Internal subroutine: adding new input layer to network -*************************************************************************/ -static void mlpbase_addinputlayer(ae_int_t ncount, - /* Integer */ ae_vector* lsizes, - /* Integer */ ae_vector* ltypes, - /* Integer */ ae_vector* lconnfirst, - /* Integer */ ae_vector* lconnlast, - ae_int_t* lastproc, - ae_state *_state) -{ - - - lsizes->ptr.p_int[0] = ncount; - ltypes->ptr.p_int[0] = -2; - lconnfirst->ptr.p_int[0] = 0; - lconnlast->ptr.p_int[0] = 0; - *lastproc = 0; -} - - -/************************************************************************* -Internal subroutine: adding new summator layer to network -*************************************************************************/ -static void mlpbase_addbiasedsummatorlayer(ae_int_t ncount, - /* Integer */ ae_vector* lsizes, - /* Integer */ ae_vector* ltypes, - /* Integer */ ae_vector* lconnfirst, - /* Integer */ ae_vector* lconnlast, - ae_int_t* lastproc, - ae_state *_state) -{ - - - lsizes->ptr.p_int[*lastproc+1] = 1; - ltypes->ptr.p_int[*lastproc+1] = -3; - lconnfirst->ptr.p_int[*lastproc+1] = 0; - lconnlast->ptr.p_int[*lastproc+1] = 0; - lsizes->ptr.p_int[*lastproc+2] = ncount; - ltypes->ptr.p_int[*lastproc+2] = 0; - lconnfirst->ptr.p_int[*lastproc+2] = *lastproc; - lconnlast->ptr.p_int[*lastproc+2] = *lastproc+1; - *lastproc = *lastproc+2; -} - - -/************************************************************************* -Internal subroutine: adding new summator layer to network -*************************************************************************/ -static void mlpbase_addactivationlayer(ae_int_t functype, - /* Integer */ ae_vector* lsizes, - /* Integer */ ae_vector* ltypes, - /* Integer */ ae_vector* lconnfirst, - /* Integer */ ae_vector* lconnlast, - ae_int_t* lastproc, - ae_state *_state) -{ - - - ae_assert(functype>0||functype==-5, "AddActivationLayer: incorrect function type", _state); - lsizes->ptr.p_int[*lastproc+1] = lsizes->ptr.p_int[*lastproc]; - ltypes->ptr.p_int[*lastproc+1] = functype; - lconnfirst->ptr.p_int[*lastproc+1] = *lastproc; - lconnlast->ptr.p_int[*lastproc+1] = *lastproc; - *lastproc = *lastproc+1; -} - - -/************************************************************************* -Internal subroutine: adding new zero layer to network -*************************************************************************/ -static void mlpbase_addzerolayer(/* Integer */ ae_vector* lsizes, - /* Integer */ ae_vector* ltypes, - /* Integer */ ae_vector* lconnfirst, - /* Integer */ ae_vector* lconnlast, - ae_int_t* lastproc, - ae_state *_state) -{ - - - lsizes->ptr.p_int[*lastproc+1] = 1; - ltypes->ptr.p_int[*lastproc+1] = -4; - lconnfirst->ptr.p_int[*lastproc+1] = 0; - lconnlast->ptr.p_int[*lastproc+1] = 0; - *lastproc = *lastproc+1; -} - - -/************************************************************************* -This routine adds input layer to the high-level description of the network. - -It modifies Network.HLConnections and Network.HLNeurons and assumes that -these arrays have enough place to store data. It accepts following -parameters: - Network - network - ConnIdx - index of the first free entry in the HLConnections - NeuroIdx - index of the first free entry in the HLNeurons - StructInfoIdx- index of the first entry in the low level description - of the current layer (in the StructInfo array) - NIn - number of inputs - -It modified Network and indices. -*************************************************************************/ -static void mlpbase_hladdinputlayer(multilayerperceptron* network, - ae_int_t* connidx, - ae_int_t* neuroidx, - ae_int_t* structinfoidx, - ae_int_t nin, - ae_state *_state) -{ - ae_int_t i; - ae_int_t offs; - - - offs = mlpbase_hlnfieldwidth*(*neuroidx); - for(i=0; i<=nin-1; i++) - { - network->hlneurons.ptr.p_int[offs+0] = 0; - network->hlneurons.ptr.p_int[offs+1] = i; - network->hlneurons.ptr.p_int[offs+2] = -1; - network->hlneurons.ptr.p_int[offs+3] = -1; - offs = offs+mlpbase_hlnfieldwidth; - } - *neuroidx = *neuroidx+nin; - *structinfoidx = *structinfoidx+nin; -} - - -/************************************************************************* -This routine adds output layer to the high-level description of -the network. - -It modifies Network.HLConnections and Network.HLNeurons and assumes that -these arrays have enough place to store data. It accepts following -parameters: - Network - network - ConnIdx - index of the first free entry in the HLConnections - NeuroIdx - index of the first free entry in the HLNeurons - StructInfoIdx- index of the first entry in the low level description - of the current layer (in the StructInfo array) - WeightsIdx - index of the first entry in the Weights array which - corresponds to the current layer - K - current layer index - NPrev - number of neurons in the previous layer - NOut - number of outputs - IsCls - is it classifier network? - IsLinear - is it network with linear output? - -It modified Network and ConnIdx/NeuroIdx/StructInfoIdx/WeightsIdx. -*************************************************************************/ -static void mlpbase_hladdoutputlayer(multilayerperceptron* network, - ae_int_t* connidx, - ae_int_t* neuroidx, - ae_int_t* structinfoidx, - ae_int_t* weightsidx, - ae_int_t k, - ae_int_t nprev, - ae_int_t nout, - ae_bool iscls, - ae_bool islinearout, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t neurooffs; - ae_int_t connoffs; - - - ae_assert((iscls&&islinearout)||!iscls, "HLAddOutputLayer: internal error", _state); - neurooffs = mlpbase_hlnfieldwidth*(*neuroidx); - connoffs = mlpbase_hlconnfieldwidth*(*connidx); - if( !iscls ) - { - - /* - * Regression network - */ - for(i=0; i<=nout-1; i++) - { - network->hlneurons.ptr.p_int[neurooffs+0] = k; - network->hlneurons.ptr.p_int[neurooffs+1] = i; - network->hlneurons.ptr.p_int[neurooffs+2] = *structinfoidx+1+nout+i; - network->hlneurons.ptr.p_int[neurooffs+3] = *weightsidx+nprev+(nprev+1)*i; - neurooffs = neurooffs+mlpbase_hlnfieldwidth; - } - for(i=0; i<=nprev-1; i++) - { - for(j=0; j<=nout-1; j++) - { - network->hlconnections.ptr.p_int[connoffs+0] = k-1; - network->hlconnections.ptr.p_int[connoffs+1] = i; - network->hlconnections.ptr.p_int[connoffs+2] = k; - network->hlconnections.ptr.p_int[connoffs+3] = j; - network->hlconnections.ptr.p_int[connoffs+4] = *weightsidx+i+j*(nprev+1); - connoffs = connoffs+mlpbase_hlconnfieldwidth; - } - } - *connidx = *connidx+nprev*nout; - *neuroidx = *neuroidx+nout; - *structinfoidx = *structinfoidx+2*nout+1; - *weightsidx = *weightsidx+nout*(nprev+1); - } - else - { - - /* - * Classification network - */ - for(i=0; i<=nout-2; i++) - { - network->hlneurons.ptr.p_int[neurooffs+0] = k; - network->hlneurons.ptr.p_int[neurooffs+1] = i; - network->hlneurons.ptr.p_int[neurooffs+2] = -1; - network->hlneurons.ptr.p_int[neurooffs+3] = *weightsidx+nprev+(nprev+1)*i; - neurooffs = neurooffs+mlpbase_hlnfieldwidth; - } - network->hlneurons.ptr.p_int[neurooffs+0] = k; - network->hlneurons.ptr.p_int[neurooffs+1] = i; - network->hlneurons.ptr.p_int[neurooffs+2] = -1; - network->hlneurons.ptr.p_int[neurooffs+3] = -1; - for(i=0; i<=nprev-1; i++) - { - for(j=0; j<=nout-2; j++) - { - network->hlconnections.ptr.p_int[connoffs+0] = k-1; - network->hlconnections.ptr.p_int[connoffs+1] = i; - network->hlconnections.ptr.p_int[connoffs+2] = k; - network->hlconnections.ptr.p_int[connoffs+3] = j; - network->hlconnections.ptr.p_int[connoffs+4] = *weightsidx+i+j*(nprev+1); - connoffs = connoffs+mlpbase_hlconnfieldwidth; - } - } - *connidx = *connidx+nprev*(nout-1); - *neuroidx = *neuroidx+nout; - *structinfoidx = *structinfoidx+nout+2; - *weightsidx = *weightsidx+(nout-1)*(nprev+1); - } -} - - -/************************************************************************* -This routine adds hidden layer to the high-level description of -the network. - -It modifies Network.HLConnections and Network.HLNeurons and assumes that -these arrays have enough place to store data. It accepts following -parameters: - Network - network - ConnIdx - index of the first free entry in the HLConnections - NeuroIdx - index of the first free entry in the HLNeurons - StructInfoIdx- index of the first entry in the low level description - of the current layer (in the StructInfo array) - WeightsIdx - index of the first entry in the Weights array which - corresponds to the current layer - K - current layer index - NPrev - number of neurons in the previous layer - NCur - number of neurons in the current layer - -It modified Network and ConnIdx/NeuroIdx/StructInfoIdx/WeightsIdx. -*************************************************************************/ -static void mlpbase_hladdhiddenlayer(multilayerperceptron* network, - ae_int_t* connidx, - ae_int_t* neuroidx, - ae_int_t* structinfoidx, - ae_int_t* weightsidx, - ae_int_t k, - ae_int_t nprev, - ae_int_t ncur, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t neurooffs; - ae_int_t connoffs; - - - neurooffs = mlpbase_hlnfieldwidth*(*neuroidx); - connoffs = mlpbase_hlconnfieldwidth*(*connidx); - for(i=0; i<=ncur-1; i++) - { - network->hlneurons.ptr.p_int[neurooffs+0] = k; - network->hlneurons.ptr.p_int[neurooffs+1] = i; - network->hlneurons.ptr.p_int[neurooffs+2] = *structinfoidx+1+ncur+i; - network->hlneurons.ptr.p_int[neurooffs+3] = *weightsidx+nprev+(nprev+1)*i; - neurooffs = neurooffs+mlpbase_hlnfieldwidth; - } - for(i=0; i<=nprev-1; i++) - { - for(j=0; j<=ncur-1; j++) - { - network->hlconnections.ptr.p_int[connoffs+0] = k-1; - network->hlconnections.ptr.p_int[connoffs+1] = i; - network->hlconnections.ptr.p_int[connoffs+2] = k; - network->hlconnections.ptr.p_int[connoffs+3] = j; - network->hlconnections.ptr.p_int[connoffs+4] = *weightsidx+i+j*(nprev+1); - connoffs = connoffs+mlpbase_hlconnfieldwidth; - } - } - *connidx = *connidx+nprev*ncur; - *neuroidx = *neuroidx+ncur; - *structinfoidx = *structinfoidx+2*ncur+1; - *weightsidx = *weightsidx+ncur*(nprev+1); -} - - -/************************************************************************* -This function fills high level information about network created using -internal MLPCreate() function. - -This function does NOT examine StructInfo for low level information, it -just expects that network has following structure: - - input neuron \ - ... | input layer - input neuron / - - "-1" neuron \ - biased summator | - ... | - biased summator | hidden layer(s), if there are exists any - activation function | - ... | - activation function / - - "-1" neuron \ - biased summator | output layer: - ... | - biased summator | * we have NOut summators/activators for regression networks - activation function | * we have only NOut-1 summators and no activators for classifiers - ... | * we have "0" neuron only when we have classifier - activation function | - "0" neuron / - - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -static void mlpbase_fillhighlevelinformation(multilayerperceptron* network, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_bool iscls, - ae_bool islinearout, - ae_state *_state) -{ - ae_int_t idxweights; - ae_int_t idxstruct; - ae_int_t idxneuro; - ae_int_t idxconn; - - - ae_assert((iscls&&islinearout)||!iscls, "FillHighLevelInformation: internal error", _state); - - /* - * Preparations common to all types of networks - */ - idxweights = 0; - idxneuro = 0; - idxstruct = 0; - idxconn = 0; - network->hlnetworktype = 0; - - /* - * network without hidden layers - */ - if( nhid1==0 ) - { - ae_vector_set_length(&network->hllayersizes, 2, _state); - network->hllayersizes.ptr.p_int[0] = nin; - network->hllayersizes.ptr.p_int[1] = nout; - if( !iscls ) - { - ae_vector_set_length(&network->hlconnections, mlpbase_hlconnfieldwidth*nin*nout, _state); - ae_vector_set_length(&network->hlneurons, mlpbase_hlnfieldwidth*(nin+nout), _state); - network->hlnormtype = 0; - } - else - { - ae_vector_set_length(&network->hlconnections, mlpbase_hlconnfieldwidth*nin*(nout-1), _state); - ae_vector_set_length(&network->hlneurons, mlpbase_hlnfieldwidth*(nin+nout), _state); - network->hlnormtype = 1; - } - mlpbase_hladdinputlayer(network, &idxconn, &idxneuro, &idxstruct, nin, _state); - mlpbase_hladdoutputlayer(network, &idxconn, &idxneuro, &idxstruct, &idxweights, 1, nin, nout, iscls, islinearout, _state); - return; - } - - /* - * network with one hidden layers - */ - if( nhid2==0 ) - { - ae_vector_set_length(&network->hllayersizes, 3, _state); - network->hllayersizes.ptr.p_int[0] = nin; - network->hllayersizes.ptr.p_int[1] = nhid1; - network->hllayersizes.ptr.p_int[2] = nout; - if( !iscls ) - { - ae_vector_set_length(&network->hlconnections, mlpbase_hlconnfieldwidth*(nin*nhid1+nhid1*nout), _state); - ae_vector_set_length(&network->hlneurons, mlpbase_hlnfieldwidth*(nin+nhid1+nout), _state); - network->hlnormtype = 0; - } - else - { - ae_vector_set_length(&network->hlconnections, mlpbase_hlconnfieldwidth*(nin*nhid1+nhid1*(nout-1)), _state); - ae_vector_set_length(&network->hlneurons, mlpbase_hlnfieldwidth*(nin+nhid1+nout), _state); - network->hlnormtype = 1; - } - mlpbase_hladdinputlayer(network, &idxconn, &idxneuro, &idxstruct, nin, _state); - mlpbase_hladdhiddenlayer(network, &idxconn, &idxneuro, &idxstruct, &idxweights, 1, nin, nhid1, _state); - mlpbase_hladdoutputlayer(network, &idxconn, &idxneuro, &idxstruct, &idxweights, 2, nhid1, nout, iscls, islinearout, _state); - return; - } - - /* - * Two hidden layers - */ - ae_vector_set_length(&network->hllayersizes, 4, _state); - network->hllayersizes.ptr.p_int[0] = nin; - network->hllayersizes.ptr.p_int[1] = nhid1; - network->hllayersizes.ptr.p_int[2] = nhid2; - network->hllayersizes.ptr.p_int[3] = nout; - if( !iscls ) - { - ae_vector_set_length(&network->hlconnections, mlpbase_hlconnfieldwidth*(nin*nhid1+nhid1*nhid2+nhid2*nout), _state); - ae_vector_set_length(&network->hlneurons, mlpbase_hlnfieldwidth*(nin+nhid1+nhid2+nout), _state); - network->hlnormtype = 0; - } - else - { - ae_vector_set_length(&network->hlconnections, mlpbase_hlconnfieldwidth*(nin*nhid1+nhid1*nhid2+nhid2*(nout-1)), _state); - ae_vector_set_length(&network->hlneurons, mlpbase_hlnfieldwidth*(nin+nhid1+nhid2+nout), _state); - network->hlnormtype = 1; - } - mlpbase_hladdinputlayer(network, &idxconn, &idxneuro, &idxstruct, nin, _state); - mlpbase_hladdhiddenlayer(network, &idxconn, &idxneuro, &idxstruct, &idxweights, 1, nin, nhid1, _state); - mlpbase_hladdhiddenlayer(network, &idxconn, &idxneuro, &idxstruct, &idxweights, 2, nhid1, nhid2, _state); - mlpbase_hladdoutputlayer(network, &idxconn, &idxneuro, &idxstruct, &idxweights, 3, nhid2, nout, iscls, islinearout, _state); -} - - -/************************************************************************* -Internal subroutine. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -static void mlpbase_mlpcreate(ae_int_t nin, - ae_int_t nout, - /* Integer */ ae_vector* lsizes, - /* Integer */ ae_vector* ltypes, - /* Integer */ ae_vector* lconnfirst, - /* Integer */ ae_vector* lconnlast, - ae_int_t layerscount, - ae_bool isclsnet, - multilayerperceptron* network, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t ssize; - ae_int_t ntotal; - ae_int_t wcount; - ae_int_t offs; - ae_int_t nprocessed; - ae_int_t wallocated; - ae_vector localtemp; - ae_vector lnfirst; - ae_vector lnsyn; - mlpbuffers buf; - smlpgrad sgrad; - - ae_frame_make(_state, &_frame_block); - memset(&localtemp, 0, sizeof(localtemp)); - memset(&lnfirst, 0, sizeof(lnfirst)); - memset(&lnsyn, 0, sizeof(lnsyn)); - memset(&buf, 0, sizeof(buf)); - memset(&sgrad, 0, sizeof(sgrad)); - _multilayerperceptron_clear(network); - ae_vector_init(&localtemp, 0, DT_INT, _state, ae_true); - ae_vector_init(&lnfirst, 0, DT_INT, _state, ae_true); - ae_vector_init(&lnsyn, 0, DT_INT, _state, ae_true); - _mlpbuffers_init(&buf, _state, ae_true); - _smlpgrad_init(&sgrad, _state, ae_true); - - - /* - * Check - */ - ae_assert(layerscount>0, "MLPCreate: wrong parameters!", _state); - ae_assert(ltypes->ptr.p_int[0]==-2, "MLPCreate: wrong LTypes[0] (must be -2)!", _state); - for(i=0; i<=layerscount-1; i++) - { - ae_assert(lsizes->ptr.p_int[i]>0, "MLPCreate: wrong LSizes!", _state); - ae_assert(lconnfirst->ptr.p_int[i]>=0&&(lconnfirst->ptr.p_int[i]ptr.p_int[i]>=lconnfirst->ptr.p_int[i]&&(lconnlast->ptr.p_int[i]ptr.p_int[i]>=0||ltypes->ptr.p_int[i]==-5 ) - { - lnsyn.ptr.p_int[i] = 0; - for(j=lconnfirst->ptr.p_int[i]; j<=lconnlast->ptr.p_int[i]; j++) - { - lnsyn.ptr.p_int[i] = lnsyn.ptr.p_int[i]+lsizes->ptr.p_int[j]; - } - } - else - { - if( (ltypes->ptr.p_int[i]==-2||ltypes->ptr.p_int[i]==-3)||ltypes->ptr.p_int[i]==-4 ) - { - lnsyn.ptr.p_int[i] = 0; - } - } - ae_assert(lnsyn.ptr.p_int[i]>=0, "MLPCreate: internal error #0!", _state); - - /* - * Other info - */ - lnfirst.ptr.p_int[i] = ntotal; - ntotal = ntotal+lsizes->ptr.p_int[i]; - if( ltypes->ptr.p_int[i]==0 ) - { - wcount = wcount+lnsyn.ptr.p_int[i]*lsizes->ptr.p_int[i]; - } - } - ssize = 7+ntotal*mlpbase_nfieldwidth; - - /* - * Allocate - */ - ae_vector_set_length(&network->structinfo, ssize-1+1, _state); - ae_vector_set_length(&network->weights, wcount-1+1, _state); - if( isclsnet ) - { - ae_vector_set_length(&network->columnmeans, nin-1+1, _state); - ae_vector_set_length(&network->columnsigmas, nin-1+1, _state); - } - else - { - ae_vector_set_length(&network->columnmeans, nin+nout-1+1, _state); - ae_vector_set_length(&network->columnsigmas, nin+nout-1+1, _state); - } - ae_vector_set_length(&network->neurons, ntotal-1+1, _state); - ae_vector_set_length(&network->nwbuf, ae_maxint(wcount, 2*nout, _state)-1+1, _state); - ae_vector_set_length(&network->integerbuf, 3+1, _state); - ae_vector_set_length(&network->dfdnet, ntotal-1+1, _state); - ae_vector_set_length(&network->x, nin-1+1, _state); - ae_vector_set_length(&network->y, nout-1+1, _state); - ae_vector_set_length(&network->derror, ntotal-1+1, _state); - - /* - * Fill structure: - * * first, fill by dummy values to avoid spurious reports by Valgrind - * * then fill global info header - */ - for(i=0; i<=ssize-1; i++) - { - network->structinfo.ptr.p_int[i] = -999999; - } - network->structinfo.ptr.p_int[0] = ssize; - network->structinfo.ptr.p_int[1] = nin; - network->structinfo.ptr.p_int[2] = nout; - network->structinfo.ptr.p_int[3] = ntotal; - network->structinfo.ptr.p_int[4] = wcount; - network->structinfo.ptr.p_int[5] = 7; - if( isclsnet ) - { - network->structinfo.ptr.p_int[6] = 1; - } - else - { - network->structinfo.ptr.p_int[6] = 0; - } - - /* - * Fill structure: neuron connections - */ - nprocessed = 0; - wallocated = 0; - for(i=0; i<=layerscount-1; i++) - { - for(j=0; j<=lsizes->ptr.p_int[i]-1; j++) - { - offs = network->structinfo.ptr.p_int[5]+nprocessed*mlpbase_nfieldwidth; - network->structinfo.ptr.p_int[offs+0] = ltypes->ptr.p_int[i]; - if( ltypes->ptr.p_int[i]==0 ) - { - - /* - * Adaptive summator: - * * connections with weights to previous neurons - */ - network->structinfo.ptr.p_int[offs+1] = lnsyn.ptr.p_int[i]; - network->structinfo.ptr.p_int[offs+2] = lnfirst.ptr.p_int[lconnfirst->ptr.p_int[i]]; - network->structinfo.ptr.p_int[offs+3] = wallocated; - wallocated = wallocated+lnsyn.ptr.p_int[i]; - nprocessed = nprocessed+1; - } - if( ltypes->ptr.p_int[i]>0||ltypes->ptr.p_int[i]==-5 ) - { - - /* - * Activation layer: - * * each neuron connected to one (only one) of previous neurons. - * * no weights - */ - network->structinfo.ptr.p_int[offs+1] = 1; - network->structinfo.ptr.p_int[offs+2] = lnfirst.ptr.p_int[lconnfirst->ptr.p_int[i]]+j; - network->structinfo.ptr.p_int[offs+3] = -1; - nprocessed = nprocessed+1; - } - if( (ltypes->ptr.p_int[i]==-2||ltypes->ptr.p_int[i]==-3)||ltypes->ptr.p_int[i]==-4 ) - { - nprocessed = nprocessed+1; - } - } - } - ae_assert(wallocated==wcount, "MLPCreate: internal error #1!", _state); - ae_assert(nprocessed==ntotal, "MLPCreate: internal error #2!", _state); - - /* - * Fill weights by small random values - * Initialize means and sigmas - */ - for(i=0; i<=nin-1; i++) - { - network->columnmeans.ptr.p_double[i] = (double)(0); - network->columnsigmas.ptr.p_double[i] = (double)(1); - } - if( !isclsnet ) - { - for(i=0; i<=nout-1; i++) - { - network->columnmeans.ptr.p_double[nin+i] = (double)(0); - network->columnsigmas.ptr.p_double[nin+i] = (double)(1); - } - } - mlprandomize(network, _state); - - /* - * Seed buffers - */ - ae_shared_pool_set_seed(&network->buf, &buf, sizeof(buf), _mlpbuffers_init, _mlpbuffers_init_copy, _mlpbuffers_destroy, _state); - ae_vector_set_length(&sgrad.g, wcount, _state); - sgrad.f = 0.0; - for(i=0; i<=wcount-1; i++) - { - sgrad.g.ptr.p_double[i] = 0.0; - } - ae_shared_pool_set_seed(&network->gradbuf, &sgrad, sizeof(sgrad), _smlpgrad_init, _smlpgrad_init_copy, _smlpgrad_destroy, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal subroutine for Hessian calculation. - -WARNING! Unspeakable math far beyong human capabilities :) -*************************************************************************/ -static void mlpbase_mlphessianbatchinternal(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t ssize, - ae_bool naturalerr, - double* e, - /* Real */ ae_vector* grad, - /* Real */ ae_matrix* h, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t ntotal; - ae_int_t istart; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t kl; - ae_int_t offs; - ae_int_t n1; - ae_int_t n2; - ae_int_t w1; - ae_int_t w2; - double s; - double t; - double v; - double et; - ae_bool bflag; - double f; - double df; - double d2f; - double deidyj; - double mx; - double q; - double z; - double s2; - double expi; - double expj; - ae_vector x; - ae_vector desiredy; - ae_vector gt; - ae_vector zeros; - ae_matrix rx; - ae_matrix ry; - ae_matrix rdx; - ae_matrix rdy; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&desiredy, 0, sizeof(desiredy)); - memset(>, 0, sizeof(gt)); - memset(&zeros, 0, sizeof(zeros)); - memset(&rx, 0, sizeof(rx)); - memset(&ry, 0, sizeof(ry)); - memset(&rdx, 0, sizeof(rdx)); - memset(&rdy, 0, sizeof(rdy)); - *e = 0; - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&desiredy, 0, DT_REAL, _state, ae_true); - ae_vector_init(>, 0, DT_REAL, _state, ae_true); - ae_vector_init(&zeros, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&rx, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ry, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&rdx, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&rdy, 0, 0, DT_REAL, _state, ae_true); - - mlpproperties(network, &nin, &nout, &wcount, _state); - ntotal = network->structinfo.ptr.p_int[3]; - istart = network->structinfo.ptr.p_int[5]; - - /* - * Prepare - */ - ae_vector_set_length(&x, nin-1+1, _state); - ae_vector_set_length(&desiredy, nout-1+1, _state); - ae_vector_set_length(&zeros, wcount-1+1, _state); - ae_vector_set_length(>, wcount-1+1, _state); - ae_matrix_set_length(&rx, ntotal+nout-1+1, wcount-1+1, _state); - ae_matrix_set_length(&ry, ntotal+nout-1+1, wcount-1+1, _state); - ae_matrix_set_length(&rdx, ntotal+nout-1+1, wcount-1+1, _state); - ae_matrix_set_length(&rdy, ntotal+nout-1+1, wcount-1+1, _state); - *e = (double)(0); - for(i=0; i<=wcount-1; i++) - { - zeros.ptr.p_double[i] = (double)(0); - } - ae_v_move(&grad->ptr.p_double[0], 1, &zeros.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - for(i=0; i<=wcount-1; i++) - { - ae_v_move(&h->ptr.pp_double[i][0], 1, &zeros.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - } - - /* - * Process - */ - for(k=0; k<=ssize-1; k++) - { - - /* - * Process vector with MLPGradN. - * Now Neurons, DFDNET and DError contains results of the last run. - */ - ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[k][0], 1, ae_v_len(0,nin-1)); - if( mlpissoftmax(network, _state) ) - { - - /* - * class labels outputs - */ - kl = ae_round(xy->ptr.pp_double[k][nin], _state); - for(i=0; i<=nout-1; i++) - { - if( i==kl ) - { - desiredy.ptr.p_double[i] = (double)(1); - } - else - { - desiredy.ptr.p_double[i] = (double)(0); - } - } - } - else - { - - /* - * real outputs - */ - ae_v_move(&desiredy.ptr.p_double[0], 1, &xy->ptr.pp_double[k][nin], 1, ae_v_len(0,nout-1)); - } - if( naturalerr ) - { - mlpgradn(network, &x, &desiredy, &et, >, _state); - } - else - { - mlpgrad(network, &x, &desiredy, &et, >, _state); - } - - /* - * grad, error - */ - *e = *e+et; - ae_v_add(&grad->ptr.p_double[0], 1, >.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - - /* - * Hessian. - * Forward pass of the R-algorithm - */ - for(i=0; i<=ntotal-1; i++) - { - offs = istart+i*mlpbase_nfieldwidth; - ae_v_move(&rx.ptr.pp_double[i][0], 1, &zeros.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - ae_v_move(&ry.ptr.pp_double[i][0], 1, &zeros.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - if( network->structinfo.ptr.p_int[offs+0]>0||network->structinfo.ptr.p_int[offs+0]==-5 ) - { - - /* - * Activation function - */ - n1 = network->structinfo.ptr.p_int[offs+2]; - ae_v_move(&rx.ptr.pp_double[i][0], 1, &ry.ptr.pp_double[n1][0], 1, ae_v_len(0,wcount-1)); - v = network->dfdnet.ptr.p_double[i]; - ae_v_moved(&ry.ptr.pp_double[i][0], 1, &rx.ptr.pp_double[i][0], 1, ae_v_len(0,wcount-1), v); - continue; - } - if( network->structinfo.ptr.p_int[offs+0]==0 ) - { - - /* - * Adaptive summator - */ - n1 = network->structinfo.ptr.p_int[offs+2]; - n2 = n1+network->structinfo.ptr.p_int[offs+1]-1; - w1 = network->structinfo.ptr.p_int[offs+3]; - w2 = w1+network->structinfo.ptr.p_int[offs+1]-1; - for(j=n1; j<=n2; j++) - { - v = network->weights.ptr.p_double[w1+j-n1]; - ae_v_addd(&rx.ptr.pp_double[i][0], 1, &ry.ptr.pp_double[j][0], 1, ae_v_len(0,wcount-1), v); - rx.ptr.pp_double[i][w1+j-n1] = rx.ptr.pp_double[i][w1+j-n1]+network->neurons.ptr.p_double[j]; - } - ae_v_move(&ry.ptr.pp_double[i][0], 1, &rx.ptr.pp_double[i][0], 1, ae_v_len(0,wcount-1)); - continue; - } - if( network->structinfo.ptr.p_int[offs+0]<0 ) - { - bflag = ae_true; - if( network->structinfo.ptr.p_int[offs+0]==-2 ) - { - - /* - * input neuron, left unchanged - */ - bflag = ae_false; - } - if( network->structinfo.ptr.p_int[offs+0]==-3 ) - { - - /* - * "-1" neuron, left unchanged - */ - bflag = ae_false; - } - if( network->structinfo.ptr.p_int[offs+0]==-4 ) - { - - /* - * "0" neuron, left unchanged - */ - bflag = ae_false; - } - ae_assert(!bflag, "MLPHessianNBatch: internal error - unknown neuron type!", _state); - continue; - } - } - - /* - * Hessian. Backward pass of the R-algorithm. - * - * Stage 1. Initialize RDY - */ - for(i=0; i<=ntotal+nout-1; i++) - { - ae_v_move(&rdy.ptr.pp_double[i][0], 1, &zeros.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - } - if( network->structinfo.ptr.p_int[6]==0 ) - { - - /* - * Standardisation. - * - * In context of the Hessian calculation standardisation - * is considered as additional layer with weightless - * activation function: - * - * F(NET) := Sigma*NET - * - * So we add one more layer to forward pass, and - * make forward/backward pass through this layer. - */ - for(i=0; i<=nout-1; i++) - { - n1 = ntotal-nout+i; - n2 = ntotal+i; - - /* - * Forward pass from N1 to N2 - */ - ae_v_move(&rx.ptr.pp_double[n2][0], 1, &ry.ptr.pp_double[n1][0], 1, ae_v_len(0,wcount-1)); - v = network->columnsigmas.ptr.p_double[nin+i]; - ae_v_moved(&ry.ptr.pp_double[n2][0], 1, &rx.ptr.pp_double[n2][0], 1, ae_v_len(0,wcount-1), v); - - /* - * Initialization of RDY - */ - ae_v_move(&rdy.ptr.pp_double[n2][0], 1, &ry.ptr.pp_double[n2][0], 1, ae_v_len(0,wcount-1)); - - /* - * Backward pass from N2 to N1: - * 1. Calculate R(dE/dX). - * 2. No R(dE/dWij) is needed since weight of activation neuron - * is fixed to 1. So we can update R(dE/dY) for - * the connected neuron (note that Vij=0, Wij=1) - */ - df = network->columnsigmas.ptr.p_double[nin+i]; - ae_v_moved(&rdx.ptr.pp_double[n2][0], 1, &rdy.ptr.pp_double[n2][0], 1, ae_v_len(0,wcount-1), df); - ae_v_add(&rdy.ptr.pp_double[n1][0], 1, &rdx.ptr.pp_double[n2][0], 1, ae_v_len(0,wcount-1)); - } - } - else - { - - /* - * Softmax. - * - * Initialize RDY using generalized expression for ei'(yi) - * (see expression (9) from p. 5 of "Fast Exact Multiplication by the Hessian"). - * - * When we are working with softmax network, generalized - * expression for ei'(yi) is used because softmax - * normalization leads to ei, which depends on all y's - */ - if( naturalerr ) - { - - /* - * softmax + cross-entropy. - * We have: - * - * S = sum(exp(yk)), - * ei = sum(trn)*exp(yi)/S-trn_i - * - * j=i: d(ei)/d(yj) = T*exp(yi)*(S-exp(yi))/S^2 - * j<>i: d(ei)/d(yj) = -T*exp(yi)*exp(yj)/S^2 - */ - t = (double)(0); - for(i=0; i<=nout-1; i++) - { - t = t+desiredy.ptr.p_double[i]; - } - mx = network->neurons.ptr.p_double[ntotal-nout]; - for(i=0; i<=nout-1; i++) - { - mx = ae_maxreal(mx, network->neurons.ptr.p_double[ntotal-nout+i], _state); - } - s = (double)(0); - for(i=0; i<=nout-1; i++) - { - network->nwbuf.ptr.p_double[i] = ae_exp(network->neurons.ptr.p_double[ntotal-nout+i]-mx, _state); - s = s+network->nwbuf.ptr.p_double[i]; - } - for(i=0; i<=nout-1; i++) - { - for(j=0; j<=nout-1; j++) - { - if( j==i ) - { - deidyj = t*network->nwbuf.ptr.p_double[i]*(s-network->nwbuf.ptr.p_double[i])/ae_sqr(s, _state); - ae_v_addd(&rdy.ptr.pp_double[ntotal-nout+i][0], 1, &ry.ptr.pp_double[ntotal-nout+i][0], 1, ae_v_len(0,wcount-1), deidyj); - } - else - { - deidyj = -t*network->nwbuf.ptr.p_double[i]*network->nwbuf.ptr.p_double[j]/ae_sqr(s, _state); - ae_v_addd(&rdy.ptr.pp_double[ntotal-nout+i][0], 1, &ry.ptr.pp_double[ntotal-nout+j][0], 1, ae_v_len(0,wcount-1), deidyj); - } - } - } - } - else - { - - /* - * For a softmax + squared error we have expression - * far beyond human imagination so we dont even try - * to comment on it. Just enjoy the code... - * - * P.S. That's why "natural error" is called "natural" - - * compact beatiful expressions, fast code.... - */ - mx = network->neurons.ptr.p_double[ntotal-nout]; - for(i=0; i<=nout-1; i++) - { - mx = ae_maxreal(mx, network->neurons.ptr.p_double[ntotal-nout+i], _state); - } - s = (double)(0); - s2 = (double)(0); - for(i=0; i<=nout-1; i++) - { - network->nwbuf.ptr.p_double[i] = ae_exp(network->neurons.ptr.p_double[ntotal-nout+i]-mx, _state); - s = s+network->nwbuf.ptr.p_double[i]; - s2 = s2+ae_sqr(network->nwbuf.ptr.p_double[i], _state); - } - q = (double)(0); - for(i=0; i<=nout-1; i++) - { - q = q+(network->y.ptr.p_double[i]-desiredy.ptr.p_double[i])*network->nwbuf.ptr.p_double[i]; - } - for(i=0; i<=nout-1; i++) - { - z = -q+(network->y.ptr.p_double[i]-desiredy.ptr.p_double[i])*s; - expi = network->nwbuf.ptr.p_double[i]; - for(j=0; j<=nout-1; j++) - { - expj = network->nwbuf.ptr.p_double[j]; - if( j==i ) - { - deidyj = expi/ae_sqr(s, _state)*((z+expi)*(s-2*expi)/s+expi*s2/ae_sqr(s, _state)); - } - else - { - deidyj = expi*expj/ae_sqr(s, _state)*(s2/ae_sqr(s, _state)-2*z/s-(expi+expj)/s+(network->y.ptr.p_double[i]-desiredy.ptr.p_double[i])-(network->y.ptr.p_double[j]-desiredy.ptr.p_double[j])); - } - ae_v_addd(&rdy.ptr.pp_double[ntotal-nout+i][0], 1, &ry.ptr.pp_double[ntotal-nout+j][0], 1, ae_v_len(0,wcount-1), deidyj); - } - } - } - } - - /* - * Hessian. Backward pass of the R-algorithm - * - * Stage 2. Process. - */ - for(i=ntotal-1; i>=0; i--) - { - - /* - * Possible variants: - * 1. Activation function - * 2. Adaptive summator - * 3. Special neuron - */ - offs = istart+i*mlpbase_nfieldwidth; - if( network->structinfo.ptr.p_int[offs+0]>0||network->structinfo.ptr.p_int[offs+0]==-5 ) - { - n1 = network->structinfo.ptr.p_int[offs+2]; - - /* - * First, calculate R(dE/dX). - */ - mlpactivationfunction(network->neurons.ptr.p_double[n1], network->structinfo.ptr.p_int[offs+0], &f, &df, &d2f, _state); - v = d2f*network->derror.ptr.p_double[i]; - ae_v_moved(&rdx.ptr.pp_double[i][0], 1, &rdy.ptr.pp_double[i][0], 1, ae_v_len(0,wcount-1), df); - ae_v_addd(&rdx.ptr.pp_double[i][0], 1, &rx.ptr.pp_double[i][0], 1, ae_v_len(0,wcount-1), v); - - /* - * No R(dE/dWij) is needed since weight of activation neuron - * is fixed to 1. - * - * So we can update R(dE/dY) for the connected neuron. - * (note that Vij=0, Wij=1) - */ - ae_v_add(&rdy.ptr.pp_double[n1][0], 1, &rdx.ptr.pp_double[i][0], 1, ae_v_len(0,wcount-1)); - continue; - } - if( network->structinfo.ptr.p_int[offs+0]==0 ) - { - - /* - * Adaptive summator - */ - n1 = network->structinfo.ptr.p_int[offs+2]; - n2 = n1+network->structinfo.ptr.p_int[offs+1]-1; - w1 = network->structinfo.ptr.p_int[offs+3]; - w2 = w1+network->structinfo.ptr.p_int[offs+1]-1; - - /* - * First, calculate R(dE/dX). - */ - ae_v_move(&rdx.ptr.pp_double[i][0], 1, &rdy.ptr.pp_double[i][0], 1, ae_v_len(0,wcount-1)); - - /* - * Then, calculate R(dE/dWij) - */ - for(j=w1; j<=w2; j++) - { - v = network->neurons.ptr.p_double[n1+j-w1]; - ae_v_addd(&h->ptr.pp_double[j][0], 1, &rdx.ptr.pp_double[i][0], 1, ae_v_len(0,wcount-1), v); - v = network->derror.ptr.p_double[i]; - ae_v_addd(&h->ptr.pp_double[j][0], 1, &ry.ptr.pp_double[n1+j-w1][0], 1, ae_v_len(0,wcount-1), v); - } - - /* - * And finally, update R(dE/dY) for connected neurons. - */ - for(j=w1; j<=w2; j++) - { - v = network->weights.ptr.p_double[j]; - ae_v_addd(&rdy.ptr.pp_double[n1+j-w1][0], 1, &rdx.ptr.pp_double[i][0], 1, ae_v_len(0,wcount-1), v); - rdy.ptr.pp_double[n1+j-w1][j] = rdy.ptr.pp_double[n1+j-w1][j]+network->derror.ptr.p_double[i]; - } - continue; - } - if( network->structinfo.ptr.p_int[offs+0]<0 ) - { - bflag = ae_false; - if( (network->structinfo.ptr.p_int[offs+0]==-2||network->structinfo.ptr.p_int[offs+0]==-3)||network->structinfo.ptr.p_int[offs+0]==-4 ) - { - - /* - * Special neuron type, no back-propagation required - */ - bflag = ae_true; - } - ae_assert(bflag, "MLPHessianNBatch: unknown neuron type!", _state); - continue; - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal subroutine - -Network must be processed by MLPProcess on X -*************************************************************************/ -static void mlpbase_mlpinternalcalculategradient(multilayerperceptron* network, - /* Real */ ae_vector* neurons, - /* Real */ ae_vector* weights, - /* Real */ ae_vector* derror, - /* Real */ ae_vector* grad, - ae_bool naturalerrorfunc, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n1; - ae_int_t n2; - ae_int_t w1; - ae_int_t w2; - ae_int_t ntotal; - ae_int_t istart; - ae_int_t nin; - ae_int_t nout; - ae_int_t offs; - double dedf; - double dfdnet; - double v; - double fown; - double deown; - double net; - double mx; - ae_bool bflag; - - - - /* - * Read network geometry - */ - nin = network->structinfo.ptr.p_int[1]; - nout = network->structinfo.ptr.p_int[2]; - ntotal = network->structinfo.ptr.p_int[3]; - istart = network->structinfo.ptr.p_int[5]; - - /* - * Pre-processing of dError/dOut: - * from dError/dOut(normalized) to dError/dOut(non-normalized) - */ - ae_assert(network->structinfo.ptr.p_int[6]==0||network->structinfo.ptr.p_int[6]==1, "MLPInternalCalculateGradient: unknown normalization type!", _state); - if( network->structinfo.ptr.p_int[6]==1 ) - { - - /* - * Softmax - */ - if( !naturalerrorfunc ) - { - mx = network->neurons.ptr.p_double[ntotal-nout]; - for(i=0; i<=nout-1; i++) - { - mx = ae_maxreal(mx, network->neurons.ptr.p_double[ntotal-nout+i], _state); - } - net = (double)(0); - for(i=0; i<=nout-1; i++) - { - network->nwbuf.ptr.p_double[i] = ae_exp(network->neurons.ptr.p_double[ntotal-nout+i]-mx, _state); - net = net+network->nwbuf.ptr.p_double[i]; - } - v = ae_v_dotproduct(&network->derror.ptr.p_double[ntotal-nout], 1, &network->nwbuf.ptr.p_double[0], 1, ae_v_len(ntotal-nout,ntotal-1)); - for(i=0; i<=nout-1; i++) - { - fown = network->nwbuf.ptr.p_double[i]; - deown = network->derror.ptr.p_double[ntotal-nout+i]; - network->nwbuf.ptr.p_double[nout+i] = (-v+deown*fown+deown*(net-fown))*fown/ae_sqr(net, _state); - } - for(i=0; i<=nout-1; i++) - { - network->derror.ptr.p_double[ntotal-nout+i] = network->nwbuf.ptr.p_double[nout+i]; - } - } - } - else - { - - /* - * Un-standardisation - */ - for(i=0; i<=nout-1; i++) - { - network->derror.ptr.p_double[ntotal-nout+i] = network->derror.ptr.p_double[ntotal-nout+i]*network->columnsigmas.ptr.p_double[nin+i]; - } - } - - /* - * Backpropagation - */ - for(i=ntotal-1; i>=0; i--) - { - - /* - * Extract info - */ - offs = istart+i*mlpbase_nfieldwidth; - if( network->structinfo.ptr.p_int[offs+0]>0||network->structinfo.ptr.p_int[offs+0]==-5 ) - { - - /* - * Activation function - */ - dedf = network->derror.ptr.p_double[i]; - dfdnet = network->dfdnet.ptr.p_double[i]; - derror->ptr.p_double[network->structinfo.ptr.p_int[offs+2]] = derror->ptr.p_double[network->structinfo.ptr.p_int[offs+2]]+dedf*dfdnet; - continue; - } - if( network->structinfo.ptr.p_int[offs+0]==0 ) - { - - /* - * Adaptive summator - */ - n1 = network->structinfo.ptr.p_int[offs+2]; - n2 = n1+network->structinfo.ptr.p_int[offs+1]-1; - w1 = network->structinfo.ptr.p_int[offs+3]; - w2 = w1+network->structinfo.ptr.p_int[offs+1]-1; - dedf = network->derror.ptr.p_double[i]; - dfdnet = 1.0; - v = dedf*dfdnet; - ae_v_moved(&grad->ptr.p_double[w1], 1, &neurons->ptr.p_double[n1], 1, ae_v_len(w1,w2), v); - ae_v_addd(&derror->ptr.p_double[n1], 1, &weights->ptr.p_double[w1], 1, ae_v_len(n1,n2), v); - continue; - } - if( network->structinfo.ptr.p_int[offs+0]<0 ) - { - bflag = ae_false; - if( (network->structinfo.ptr.p_int[offs+0]==-2||network->structinfo.ptr.p_int[offs+0]==-3)||network->structinfo.ptr.p_int[offs+0]==-4 ) - { - - /* - * Special neuron type, no back-propagation required - */ - bflag = ae_true; - } - ae_assert(bflag, "MLPInternalCalculateGradient: unknown neuron type!", _state); - continue; - } - } -} - - -static void mlpbase_mlpchunkedgradient(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t cstart, - ae_int_t csize, - /* Real */ ae_vector* batch4buf, - /* Real */ ae_vector* hpcbuf, - double* e, - ae_bool naturalerrorfunc, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t kl; - ae_int_t ntotal; - ae_int_t nin; - ae_int_t nout; - ae_int_t offs; - double f; - double df; - double d2f; - double v; - double vv; - double s; - double fown; - double deown; - ae_bool bflag; - ae_int_t istart; - ae_int_t entrysize; - ae_int_t dfoffs; - ae_int_t derroroffs; - ae_int_t entryoffs; - ae_int_t neuronidx; - ae_int_t srcentryoffs; - ae_int_t srcneuronidx; - ae_int_t srcweightidx; - ae_int_t neurontype; - ae_int_t nweights; - ae_int_t offs0; - ae_int_t offs1; - ae_int_t offs2; - double v0; - double v1; - double v2; - double v3; - double s0; - double s1; - double s2; - double s3; - ae_int_t chunksize; - - - chunksize = 4; - ae_assert(csize<=chunksize, "MLPChunkedGradient: internal error (CSize>ChunkSize)", _state); - - /* - * Try to use HPC core, if possible - */ - if( hpcchunkedgradient(&network->weights, &network->structinfo, &network->columnmeans, &network->columnsigmas, xy, cstart, csize, batch4buf, hpcbuf, e, naturalerrorfunc, _state) ) - { - return; - } - - /* - * Read network geometry, prepare data - */ - nin = network->structinfo.ptr.p_int[1]; - nout = network->structinfo.ptr.p_int[2]; - ntotal = network->structinfo.ptr.p_int[3]; - istart = network->structinfo.ptr.p_int[5]; - entrysize = 12; - dfoffs = 4; - derroroffs = 8; - - /* - * Fill Batch4Buf by zeros. - * - * THIS STAGE IS VERY IMPORTANT! - * - * We fill all components of entry - neuron values, dF/dNET, dError/dF. - * It allows us to easily handle situations when CSizeptr.p_double[i] = (double)(0); - } - - /* - * Forward pass: - * 1. Load data into Batch4Buf. If CSizecolumnsigmas.ptr.p_double[i],(double)(0)) ) - { - batch4buf->ptr.p_double[entryoffs+j] = (xy->ptr.pp_double[cstart+j][i]-network->columnmeans.ptr.p_double[i])/network->columnsigmas.ptr.p_double[i]; - } - else - { - batch4buf->ptr.p_double[entryoffs+j] = xy->ptr.pp_double[cstart+j][i]-network->columnmeans.ptr.p_double[i]; - } - } - } - for(neuronidx=0; neuronidx<=ntotal-1; neuronidx++) - { - entryoffs = entrysize*neuronidx; - offs = istart+neuronidx*mlpbase_nfieldwidth; - neurontype = network->structinfo.ptr.p_int[offs+0]; - if( neurontype>0||neurontype==-5 ) - { - - /* - * "activation function" neuron, which takes value of neuron SrcNeuronIdx - * and applies activation function to it. - * - * This neuron has no weights and no tunable parameters. - */ - srcneuronidx = network->structinfo.ptr.p_int[offs+2]; - srcentryoffs = entrysize*srcneuronidx; - mlpactivationfunction(batch4buf->ptr.p_double[srcentryoffs+0], neurontype, &f, &df, &d2f, _state); - batch4buf->ptr.p_double[entryoffs+0] = f; - batch4buf->ptr.p_double[entryoffs+0+dfoffs] = df; - mlpactivationfunction(batch4buf->ptr.p_double[srcentryoffs+1], neurontype, &f, &df, &d2f, _state); - batch4buf->ptr.p_double[entryoffs+1] = f; - batch4buf->ptr.p_double[entryoffs+1+dfoffs] = df; - mlpactivationfunction(batch4buf->ptr.p_double[srcentryoffs+2], neurontype, &f, &df, &d2f, _state); - batch4buf->ptr.p_double[entryoffs+2] = f; - batch4buf->ptr.p_double[entryoffs+2+dfoffs] = df; - mlpactivationfunction(batch4buf->ptr.p_double[srcentryoffs+3], neurontype, &f, &df, &d2f, _state); - batch4buf->ptr.p_double[entryoffs+3] = f; - batch4buf->ptr.p_double[entryoffs+3+dfoffs] = df; - continue; - } - if( neurontype==0 ) - { - - /* - * "adaptive summator" neuron, whose output is a weighted sum of inputs. - * It has weights, but has no activation function. - */ - nweights = network->structinfo.ptr.p_int[offs+1]; - srcneuronidx = network->structinfo.ptr.p_int[offs+2]; - srcentryoffs = entrysize*srcneuronidx; - srcweightidx = network->structinfo.ptr.p_int[offs+3]; - v0 = (double)(0); - v1 = (double)(0); - v2 = (double)(0); - v3 = (double)(0); - for(j=0; j<=nweights-1; j++) - { - v = network->weights.ptr.p_double[srcweightidx]; - srcweightidx = srcweightidx+1; - v0 = v0+v*batch4buf->ptr.p_double[srcentryoffs+0]; - v1 = v1+v*batch4buf->ptr.p_double[srcentryoffs+1]; - v2 = v2+v*batch4buf->ptr.p_double[srcentryoffs+2]; - v3 = v3+v*batch4buf->ptr.p_double[srcentryoffs+3]; - srcentryoffs = srcentryoffs+entrysize; - } - batch4buf->ptr.p_double[entryoffs+0] = v0; - batch4buf->ptr.p_double[entryoffs+1] = v1; - batch4buf->ptr.p_double[entryoffs+2] = v2; - batch4buf->ptr.p_double[entryoffs+3] = v3; - batch4buf->ptr.p_double[entryoffs+0+dfoffs] = (double)(1); - batch4buf->ptr.p_double[entryoffs+1+dfoffs] = (double)(1); - batch4buf->ptr.p_double[entryoffs+2+dfoffs] = (double)(1); - batch4buf->ptr.p_double[entryoffs+3+dfoffs] = (double)(1); - continue; - } - if( neurontype<0 ) - { - bflag = ae_false; - if( neurontype==-2 ) - { - - /* - * Input neuron, left unchanged - */ - bflag = ae_true; - } - if( neurontype==-3 ) - { - - /* - * "-1" neuron - */ - batch4buf->ptr.p_double[entryoffs+0] = (double)(-1); - batch4buf->ptr.p_double[entryoffs+1] = (double)(-1); - batch4buf->ptr.p_double[entryoffs+2] = (double)(-1); - batch4buf->ptr.p_double[entryoffs+3] = (double)(-1); - batch4buf->ptr.p_double[entryoffs+0+dfoffs] = (double)(0); - batch4buf->ptr.p_double[entryoffs+1+dfoffs] = (double)(0); - batch4buf->ptr.p_double[entryoffs+2+dfoffs] = (double)(0); - batch4buf->ptr.p_double[entryoffs+3+dfoffs] = (double)(0); - bflag = ae_true; - } - if( neurontype==-4 ) - { - - /* - * "0" neuron - */ - batch4buf->ptr.p_double[entryoffs+0] = (double)(0); - batch4buf->ptr.p_double[entryoffs+1] = (double)(0); - batch4buf->ptr.p_double[entryoffs+2] = (double)(0); - batch4buf->ptr.p_double[entryoffs+3] = (double)(0); - batch4buf->ptr.p_double[entryoffs+0+dfoffs] = (double)(0); - batch4buf->ptr.p_double[entryoffs+1+dfoffs] = (double)(0); - batch4buf->ptr.p_double[entryoffs+2+dfoffs] = (double)(0); - batch4buf->ptr.p_double[entryoffs+3+dfoffs] = (double)(0); - bflag = ae_true; - } - ae_assert(bflag, "MLPChunkedGradient: internal error - unknown neuron type!", _state); - continue; - } - } - - /* - * Intermediate phase between forward and backward passes. - * - * For regression networks: - * * forward pass is completely done (no additional post-processing is - * needed). - * * before starting backward pass, we have to calculate dError/dOut - * for output neurons. We also update error at this phase. - * - * For classification networks: - * * in addition to forward pass we apply SOFTMAX normalization to - * output neurons. - * * after applying normalization, we have to calculate dError/dOut, - * which is calculated in two steps: - * * first, we calculate derivative of error with respect to SOFTMAX - * normalized outputs (normalized dError) - * * then, we calculate derivative of error with respect to values - * of outputs BEFORE normalization was applied to them - */ - ae_assert(network->structinfo.ptr.p_int[6]==0||network->structinfo.ptr.p_int[6]==1, "MLPChunkedGradient: unknown normalization type!", _state); - if( network->structinfo.ptr.p_int[6]==1 ) - { - - /* - * SOFTMAX-normalized network. - * - * First, calculate (V0,V1,V2,V3) - component-wise maximum - * of output neurons. This vector of maximum values will be - * used for normalization of outputs prior to calculating - * exponentials. - * - * NOTE: the only purpose of this stage is to prevent overflow - * during calculation of exponentials. With this stage - * we make sure that all exponentials are calculated - * with non-positive argument. If you load (0,0,0,0) to - * (V0,V1,V2,V3), your program will continue working - - * although with less robustness. - */ - entryoffs = entrysize*(ntotal-nout); - v0 = batch4buf->ptr.p_double[entryoffs+0]; - v1 = batch4buf->ptr.p_double[entryoffs+1]; - v2 = batch4buf->ptr.p_double[entryoffs+2]; - v3 = batch4buf->ptr.p_double[entryoffs+3]; - entryoffs = entryoffs+entrysize; - for(i=1; i<=nout-1; i++) - { - v = batch4buf->ptr.p_double[entryoffs+0]; - if( v>v0 ) - { - v0 = v; - } - v = batch4buf->ptr.p_double[entryoffs+1]; - if( v>v1 ) - { - v1 = v; - } - v = batch4buf->ptr.p_double[entryoffs+2]; - if( v>v2 ) - { - v2 = v; - } - v = batch4buf->ptr.p_double[entryoffs+3]; - if( v>v3 ) - { - v3 = v; - } - entryoffs = entryoffs+entrysize; - } - - /* - * Then, calculate exponentials and place them to part of the - * array which is located past the last entry. We also - * calculate sum of exponentials which will be stored past the - * exponentials. - */ - entryoffs = entrysize*(ntotal-nout); - offs0 = entrysize*ntotal; - s0 = (double)(0); - s1 = (double)(0); - s2 = (double)(0); - s3 = (double)(0); - for(i=0; i<=nout-1; i++) - { - v = ae_exp(batch4buf->ptr.p_double[entryoffs+0]-v0, _state); - s0 = s0+v; - batch4buf->ptr.p_double[offs0+0] = v; - v = ae_exp(batch4buf->ptr.p_double[entryoffs+1]-v1, _state); - s1 = s1+v; - batch4buf->ptr.p_double[offs0+1] = v; - v = ae_exp(batch4buf->ptr.p_double[entryoffs+2]-v2, _state); - s2 = s2+v; - batch4buf->ptr.p_double[offs0+2] = v; - v = ae_exp(batch4buf->ptr.p_double[entryoffs+3]-v3, _state); - s3 = s3+v; - batch4buf->ptr.p_double[offs0+3] = v; - entryoffs = entryoffs+entrysize; - offs0 = offs0+chunksize; - } - offs0 = entrysize*ntotal+2*nout*chunksize; - batch4buf->ptr.p_double[offs0+0] = s0; - batch4buf->ptr.p_double[offs0+1] = s1; - batch4buf->ptr.p_double[offs0+2] = s2; - batch4buf->ptr.p_double[offs0+3] = s3; - - /* - * Now we have: - * * Batch4Buf[0...EntrySize*NTotal-1] stores: - * * NTotal*ChunkSize neuron output values (SOFTMAX normalization - * was not applied to these values), - * * NTotal*ChunkSize values of dF/dNET (derivative of neuron - * output with respect to its input) - * * NTotal*ChunkSize zeros in the elements which correspond to - * dError/dOut (derivative of error with respect to neuron output). - * * Batch4Buf[EntrySize*NTotal...EntrySize*NTotal+ChunkSize*NOut-1] - - * stores exponentials of last NOut neurons. - * * Batch4Buf[EntrySize*NTotal+ChunkSize*NOut-1...EntrySize*NTotal+ChunkSize*2*NOut-1] - * - can be used for temporary calculations - * * Batch4Buf[EntrySize*NTotal+ChunkSize*2*NOut...EntrySize*NTotal+ChunkSize*2*NOut+ChunkSize-1] - * - stores sum-of-exponentials - * - * Block below calculates derivatives of error function with respect - * to non-SOFTMAX-normalized output values of last NOut neurons. - * - * It is quite complicated; we do not describe algebra behind it, - * but if you want you may check it yourself :) - */ - if( naturalerrorfunc ) - { - - /* - * Calculate derivative of error with respect to values of - * output neurons PRIOR TO SOFTMAX NORMALIZATION. Because we - * use natural error function (cross-entropy), we can do so - * very easy. - */ - offs0 = entrysize*ntotal+2*nout*chunksize; - for(k=0; k<=csize-1; k++) - { - s = batch4buf->ptr.p_double[offs0+k]; - kl = ae_round(xy->ptr.pp_double[cstart+k][nin], _state); - offs1 = (ntotal-nout)*entrysize+derroroffs+k; - offs2 = entrysize*ntotal+k; - for(i=0; i<=nout-1; i++) - { - if( i==kl ) - { - v = (double)(1); - } - else - { - v = (double)(0); - } - vv = batch4buf->ptr.p_double[offs2]; - batch4buf->ptr.p_double[offs1] = vv/s-v; - *e = *e+mlpbase_safecrossentropy(v, vv/s, _state); - offs1 = offs1+entrysize; - offs2 = offs2+chunksize; - } - } - } - else - { - - /* - * SOFTMAX normalization makes things very difficult. - * Sorry, we do not dare to describe this esoteric math - * in details. - */ - offs0 = entrysize*ntotal+chunksize*2*nout; - for(k=0; k<=csize-1; k++) - { - s = batch4buf->ptr.p_double[offs0+k]; - kl = ae_round(xy->ptr.pp_double[cstart+k][nin], _state); - vv = (double)(0); - offs1 = entrysize*ntotal+k; - offs2 = entrysize*ntotal+nout*chunksize+k; - for(i=0; i<=nout-1; i++) - { - fown = batch4buf->ptr.p_double[offs1]; - if( i==kl ) - { - deown = fown/s-1; - } - else - { - deown = fown/s; - } - batch4buf->ptr.p_double[offs2] = deown; - vv = vv+deown*fown; - *e = *e+deown*deown/2; - offs1 = offs1+chunksize; - offs2 = offs2+chunksize; - } - offs1 = entrysize*ntotal+k; - offs2 = entrysize*ntotal+nout*chunksize+k; - for(i=0; i<=nout-1; i++) - { - fown = batch4buf->ptr.p_double[offs1]; - deown = batch4buf->ptr.p_double[offs2]; - batch4buf->ptr.p_double[(ntotal-nout+i)*entrysize+derroroffs+k] = (-vv+deown*fown+deown*(s-fown))*fown/ae_sqr(s, _state); - offs1 = offs1+chunksize; - offs2 = offs2+chunksize; - } - } - } - } - else - { - - /* - * Regression network with sum-of-squares function. - * - * For each NOut of last neurons: - * * calculate difference between actual and desired output - * * calculate dError/dOut for this neuron (proportional to difference) - * * store in in last 4 components of entry (these values are used - * to start backpropagation) - * * update error - */ - for(i=0; i<=nout-1; i++) - { - v0 = network->columnsigmas.ptr.p_double[nin+i]; - v1 = network->columnmeans.ptr.p_double[nin+i]; - entryoffs = entrysize*(ntotal-nout+i); - offs0 = entryoffs; - offs1 = entryoffs+derroroffs; - for(j=0; j<=csize-1; j++) - { - v = batch4buf->ptr.p_double[offs0+j]*v0+v1-xy->ptr.pp_double[cstart+j][nin+i]; - batch4buf->ptr.p_double[offs1+j] = v*v0; - *e = *e+v*v/2; - } - } - } - - /* - * Backpropagation - */ - for(neuronidx=ntotal-1; neuronidx>=0; neuronidx--) - { - entryoffs = entrysize*neuronidx; - offs = istart+neuronidx*mlpbase_nfieldwidth; - neurontype = network->structinfo.ptr.p_int[offs+0]; - if( neurontype>0||neurontype==-5 ) - { - - /* - * Activation function - */ - srcneuronidx = network->structinfo.ptr.p_int[offs+2]; - srcentryoffs = entrysize*srcneuronidx; - offs0 = srcentryoffs+derroroffs; - offs1 = entryoffs+derroroffs; - offs2 = entryoffs+dfoffs; - batch4buf->ptr.p_double[offs0+0] = batch4buf->ptr.p_double[offs0+0]+batch4buf->ptr.p_double[offs1+0]*batch4buf->ptr.p_double[offs2+0]; - batch4buf->ptr.p_double[offs0+1] = batch4buf->ptr.p_double[offs0+1]+batch4buf->ptr.p_double[offs1+1]*batch4buf->ptr.p_double[offs2+1]; - batch4buf->ptr.p_double[offs0+2] = batch4buf->ptr.p_double[offs0+2]+batch4buf->ptr.p_double[offs1+2]*batch4buf->ptr.p_double[offs2+2]; - batch4buf->ptr.p_double[offs0+3] = batch4buf->ptr.p_double[offs0+3]+batch4buf->ptr.p_double[offs1+3]*batch4buf->ptr.p_double[offs2+3]; - continue; - } - if( neurontype==0 ) - { - - /* - * Adaptive summator - */ - nweights = network->structinfo.ptr.p_int[offs+1]; - srcneuronidx = network->structinfo.ptr.p_int[offs+2]; - srcentryoffs = entrysize*srcneuronidx; - srcweightidx = network->structinfo.ptr.p_int[offs+3]; - v0 = batch4buf->ptr.p_double[entryoffs+derroroffs+0]; - v1 = batch4buf->ptr.p_double[entryoffs+derroroffs+1]; - v2 = batch4buf->ptr.p_double[entryoffs+derroroffs+2]; - v3 = batch4buf->ptr.p_double[entryoffs+derroroffs+3]; - for(j=0; j<=nweights-1; j++) - { - offs0 = srcentryoffs; - offs1 = srcentryoffs+derroroffs; - v = network->weights.ptr.p_double[srcweightidx]; - hpcbuf->ptr.p_double[srcweightidx] = hpcbuf->ptr.p_double[srcweightidx]+batch4buf->ptr.p_double[offs0+0]*v0+batch4buf->ptr.p_double[offs0+1]*v1+batch4buf->ptr.p_double[offs0+2]*v2+batch4buf->ptr.p_double[offs0+3]*v3; - batch4buf->ptr.p_double[offs1+0] = batch4buf->ptr.p_double[offs1+0]+v*v0; - batch4buf->ptr.p_double[offs1+1] = batch4buf->ptr.p_double[offs1+1]+v*v1; - batch4buf->ptr.p_double[offs1+2] = batch4buf->ptr.p_double[offs1+2]+v*v2; - batch4buf->ptr.p_double[offs1+3] = batch4buf->ptr.p_double[offs1+3]+v*v3; - srcentryoffs = srcentryoffs+entrysize; - srcweightidx = srcweightidx+1; - } - continue; - } - if( neurontype<0 ) - { - bflag = ae_false; - if( (neurontype==-2||neurontype==-3)||neurontype==-4 ) - { - - /* - * Special neuron type, no back-propagation required - */ - bflag = ae_true; - } - ae_assert(bflag, "MLPInternalCalculateGradient: unknown neuron type!", _state); - continue; - } - } -} - - -static void mlpbase_mlpchunkedprocess(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t cstart, - ae_int_t csize, - /* Real */ ae_vector* batch4buf, - /* Real */ ae_vector* hpcbuf, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t ntotal; - ae_int_t nin; - ae_int_t nout; - ae_int_t offs; - double f; - double df; - double d2f; - double v; - ae_bool bflag; - ae_int_t istart; - ae_int_t entrysize; - ae_int_t entryoffs; - ae_int_t neuronidx; - ae_int_t srcentryoffs; - ae_int_t srcneuronidx; - ae_int_t srcweightidx; - ae_int_t neurontype; - ae_int_t nweights; - ae_int_t offs0; - double v0; - double v1; - double v2; - double v3; - double s0; - double s1; - double s2; - double s3; - ae_int_t chunksize; - - - chunksize = 4; - ae_assert(csize<=chunksize, "MLPChunkedProcess: internal error (CSize>ChunkSize)", _state); - - /* - * Try to use HPC core, if possible - */ - if( hpcchunkedprocess(&network->weights, &network->structinfo, &network->columnmeans, &network->columnsigmas, xy, cstart, csize, batch4buf, hpcbuf, _state) ) - { - return; - } - - /* - * Read network geometry, prepare data - */ - nin = network->structinfo.ptr.p_int[1]; - nout = network->structinfo.ptr.p_int[2]; - ntotal = network->structinfo.ptr.p_int[3]; - istart = network->structinfo.ptr.p_int[5]; - entrysize = 4; - - /* - * Fill Batch4Buf by zeros. - * - * THIS STAGE IS VERY IMPORTANT! - * - * We fill all components of entry - neuron values, dF/dNET, dError/dF. - * It allows us to easily handle situations when CSizeptr.p_double[i] = (double)(0); - } - - /* - * Forward pass: - * 1. Load data into Batch4Buf. If CSizecolumnsigmas.ptr.p_double[i],(double)(0)) ) - { - batch4buf->ptr.p_double[entryoffs+j] = (xy->ptr.pp_double[cstart+j][i]-network->columnmeans.ptr.p_double[i])/network->columnsigmas.ptr.p_double[i]; - } - else - { - batch4buf->ptr.p_double[entryoffs+j] = xy->ptr.pp_double[cstart+j][i]-network->columnmeans.ptr.p_double[i]; - } - } - } - for(neuronidx=0; neuronidx<=ntotal-1; neuronidx++) - { - entryoffs = entrysize*neuronidx; - offs = istart+neuronidx*mlpbase_nfieldwidth; - neurontype = network->structinfo.ptr.p_int[offs+0]; - if( neurontype>0||neurontype==-5 ) - { - - /* - * "activation function" neuron, which takes value of neuron SrcNeuronIdx - * and applies activation function to it. - * - * This neuron has no weights and no tunable parameters. - */ - srcneuronidx = network->structinfo.ptr.p_int[offs+2]; - srcentryoffs = entrysize*srcneuronidx; - mlpactivationfunction(batch4buf->ptr.p_double[srcentryoffs+0], neurontype, &f, &df, &d2f, _state); - batch4buf->ptr.p_double[entryoffs+0] = f; - mlpactivationfunction(batch4buf->ptr.p_double[srcentryoffs+1], neurontype, &f, &df, &d2f, _state); - batch4buf->ptr.p_double[entryoffs+1] = f; - mlpactivationfunction(batch4buf->ptr.p_double[srcentryoffs+2], neurontype, &f, &df, &d2f, _state); - batch4buf->ptr.p_double[entryoffs+2] = f; - mlpactivationfunction(batch4buf->ptr.p_double[srcentryoffs+3], neurontype, &f, &df, &d2f, _state); - batch4buf->ptr.p_double[entryoffs+3] = f; - continue; - } - if( neurontype==0 ) - { - - /* - * "adaptive summator" neuron, whose output is a weighted sum of inputs. - * It has weights, but has no activation function. - */ - nweights = network->structinfo.ptr.p_int[offs+1]; - srcneuronidx = network->structinfo.ptr.p_int[offs+2]; - srcentryoffs = entrysize*srcneuronidx; - srcweightidx = network->structinfo.ptr.p_int[offs+3]; - v0 = (double)(0); - v1 = (double)(0); - v2 = (double)(0); - v3 = (double)(0); - for(j=0; j<=nweights-1; j++) - { - v = network->weights.ptr.p_double[srcweightidx]; - srcweightidx = srcweightidx+1; - v0 = v0+v*batch4buf->ptr.p_double[srcentryoffs+0]; - v1 = v1+v*batch4buf->ptr.p_double[srcentryoffs+1]; - v2 = v2+v*batch4buf->ptr.p_double[srcentryoffs+2]; - v3 = v3+v*batch4buf->ptr.p_double[srcentryoffs+3]; - srcentryoffs = srcentryoffs+entrysize; - } - batch4buf->ptr.p_double[entryoffs+0] = v0; - batch4buf->ptr.p_double[entryoffs+1] = v1; - batch4buf->ptr.p_double[entryoffs+2] = v2; - batch4buf->ptr.p_double[entryoffs+3] = v3; - continue; - } - if( neurontype<0 ) - { - bflag = ae_false; - if( neurontype==-2 ) - { - - /* - * Input neuron, left unchanged - */ - bflag = ae_true; - } - if( neurontype==-3 ) - { - - /* - * "-1" neuron - */ - batch4buf->ptr.p_double[entryoffs+0] = (double)(-1); - batch4buf->ptr.p_double[entryoffs+1] = (double)(-1); - batch4buf->ptr.p_double[entryoffs+2] = (double)(-1); - batch4buf->ptr.p_double[entryoffs+3] = (double)(-1); - bflag = ae_true; - } - if( neurontype==-4 ) - { - - /* - * "0" neuron - */ - batch4buf->ptr.p_double[entryoffs+0] = (double)(0); - batch4buf->ptr.p_double[entryoffs+1] = (double)(0); - batch4buf->ptr.p_double[entryoffs+2] = (double)(0); - batch4buf->ptr.p_double[entryoffs+3] = (double)(0); - bflag = ae_true; - } - ae_assert(bflag, "MLPChunkedProcess: internal error - unknown neuron type!", _state); - continue; - } - } - - /* - * SOFTMAX normalization or scaling. - */ - ae_assert(network->structinfo.ptr.p_int[6]==0||network->structinfo.ptr.p_int[6]==1, "MLPChunkedProcess: unknown normalization type!", _state); - if( network->structinfo.ptr.p_int[6]==1 ) - { - - /* - * SOFTMAX-normalized network. - * - * First, calculate (V0,V1,V2,V3) - component-wise maximum - * of output neurons. This vector of maximum values will be - * used for normalization of outputs prior to calculating - * exponentials. - * - * NOTE: the only purpose of this stage is to prevent overflow - * during calculation of exponentials. With this stage - * we make sure that all exponentials are calculated - * with non-positive argument. If you load (0,0,0,0) to - * (V0,V1,V2,V3), your program will continue working - - * although with less robustness. - */ - entryoffs = entrysize*(ntotal-nout); - v0 = batch4buf->ptr.p_double[entryoffs+0]; - v1 = batch4buf->ptr.p_double[entryoffs+1]; - v2 = batch4buf->ptr.p_double[entryoffs+2]; - v3 = batch4buf->ptr.p_double[entryoffs+3]; - entryoffs = entryoffs+entrysize; - for(i=1; i<=nout-1; i++) - { - v = batch4buf->ptr.p_double[entryoffs+0]; - if( v>v0 ) - { - v0 = v; - } - v = batch4buf->ptr.p_double[entryoffs+1]; - if( v>v1 ) - { - v1 = v; - } - v = batch4buf->ptr.p_double[entryoffs+2]; - if( v>v2 ) - { - v2 = v; - } - v = batch4buf->ptr.p_double[entryoffs+3]; - if( v>v3 ) - { - v3 = v; - } - entryoffs = entryoffs+entrysize; - } - - /* - * Then, calculate exponentials and place them to part of the - * array which is located past the last entry. We also - * calculate sum of exponentials. - */ - entryoffs = entrysize*(ntotal-nout); - offs0 = entrysize*ntotal; - s0 = (double)(0); - s1 = (double)(0); - s2 = (double)(0); - s3 = (double)(0); - for(i=0; i<=nout-1; i++) - { - v = ae_exp(batch4buf->ptr.p_double[entryoffs+0]-v0, _state); - s0 = s0+v; - batch4buf->ptr.p_double[offs0+0] = v; - v = ae_exp(batch4buf->ptr.p_double[entryoffs+1]-v1, _state); - s1 = s1+v; - batch4buf->ptr.p_double[offs0+1] = v; - v = ae_exp(batch4buf->ptr.p_double[entryoffs+2]-v2, _state); - s2 = s2+v; - batch4buf->ptr.p_double[offs0+2] = v; - v = ae_exp(batch4buf->ptr.p_double[entryoffs+3]-v3, _state); - s3 = s3+v; - batch4buf->ptr.p_double[offs0+3] = v; - entryoffs = entryoffs+entrysize; - offs0 = offs0+chunksize; - } - - /* - * Write SOFTMAX-normalized values to the output array. - */ - offs0 = entrysize*ntotal; - for(i=0; i<=nout-1; i++) - { - if( csize>0 ) - { - xy->ptr.pp_double[cstart+0][nin+i] = batch4buf->ptr.p_double[offs0+0]/s0; - } - if( csize>1 ) - { - xy->ptr.pp_double[cstart+1][nin+i] = batch4buf->ptr.p_double[offs0+1]/s1; - } - if( csize>2 ) - { - xy->ptr.pp_double[cstart+2][nin+i] = batch4buf->ptr.p_double[offs0+2]/s2; - } - if( csize>3 ) - { - xy->ptr.pp_double[cstart+3][nin+i] = batch4buf->ptr.p_double[offs0+3]/s3; - } - offs0 = offs0+chunksize; - } - } - else - { - - /* - * Regression network with sum-of-squares function. - * - * For each NOut of last neurons: - * * calculate difference between actual and desired output - * * calculate dError/dOut for this neuron (proportional to difference) - * * store in in last 4 components of entry (these values are used - * to start backpropagation) - * * update error - */ - for(i=0; i<=nout-1; i++) - { - v0 = network->columnsigmas.ptr.p_double[nin+i]; - v1 = network->columnmeans.ptr.p_double[nin+i]; - entryoffs = entrysize*(ntotal-nout+i); - for(j=0; j<=csize-1; j++) - { - xy->ptr.pp_double[cstart+j][nin+i] = batch4buf->ptr.p_double[entryoffs+j]*v0+v1; - } - } - } -} - - -/************************************************************************* -Returns T*Ln(T/Z), guarded against overflow/underflow. -Internal subroutine. -*************************************************************************/ -static double mlpbase_safecrossentropy(double t, - double z, - ae_state *_state) -{ - double r; - double result; - - - if( ae_fp_eq(t,(double)(0)) ) - { - result = (double)(0); - } - else - { - if( ae_fp_greater(ae_fabs(z, _state),(double)(1)) ) - { - - /* - * Shouldn't be the case with softmax, - * but we just want to be sure. - */ - if( ae_fp_eq(t/z,(double)(0)) ) - { - r = ae_minrealnumber; - } - else - { - r = t/z; - } - } - else - { - - /* - * Normal case - */ - if( ae_fp_eq(z,(double)(0))||ae_fp_greater_eq(ae_fabs(t, _state),ae_maxrealnumber*ae_fabs(z, _state)) ) - { - r = ae_maxrealnumber; - } - else - { - r = t/z; - } - } - result = t*ae_log(r, _state); - } - return result; -} - - -/************************************************************************* -This function performs backward pass of neural network randimization: -* it assumes that Network.Weights stores standard deviation of weights - (weights are not generated yet, only their deviations are present) -* it sets deviations of weights which feed NeuronIdx-th neuron to specified value -* it recursively passes to deeper neuron and modifies their weights -* it stops after encountering nonlinear neurons, linear activation function, - input neurons, "0" and "-1" neurons - - -- ALGLIB -- - Copyright 27.06.2013 by Bochkanov Sergey -*************************************************************************/ -static void mlpbase_randomizebackwardpass(multilayerperceptron* network, - ae_int_t neuronidx, - double v, - ae_state *_state) -{ - ae_int_t istart; - ae_int_t neurontype; - ae_int_t n1; - ae_int_t n2; - ae_int_t w1; - ae_int_t w2; - ae_int_t offs; - ae_int_t i; - - - istart = network->structinfo.ptr.p_int[5]; - neurontype = network->structinfo.ptr.p_int[istart+neuronidx*mlpbase_nfieldwidth+0]; - if( neurontype==-2 ) - { - - /* - * Input neuron - stop - */ - return; - } - if( neurontype==-3 ) - { - - /* - * "-1" neuron: stop - */ - return; - } - if( neurontype==-4 ) - { - - /* - * "0" neuron: stop - */ - return; - } - if( neurontype==0 ) - { - - /* - * Adaptive summator neuron: - * * modify deviations of its weights - * * recursively call this function for its inputs - */ - offs = istart+neuronidx*mlpbase_nfieldwidth; - n1 = network->structinfo.ptr.p_int[offs+2]; - n2 = n1+network->structinfo.ptr.p_int[offs+1]-1; - w1 = network->structinfo.ptr.p_int[offs+3]; - w2 = w1+network->structinfo.ptr.p_int[offs+1]-1; - for(i=w1; i<=w2; i++) - { - network->weights.ptr.p_double[i] = v; - } - for(i=n1; i<=n2; i++) - { - mlpbase_randomizebackwardpass(network, i, v, _state); - } - return; - } - if( neurontype==-5 ) - { - - /* - * Linear activation function: stop - */ - return; - } - if( neurontype>0 ) - { - - /* - * Nonlinear activation function: stop - */ - return; - } - ae_assert(ae_false, "RandomizeBackwardPass: unexpected neuron type", _state); -} - - -void _modelerrors_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - modelerrors *p = (modelerrors*)_p; - ae_touch_ptr((void*)p); -} - - -void _modelerrors_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - modelerrors *dst = (modelerrors*)_dst; - modelerrors *src = (modelerrors*)_src; - dst->relclserror = src->relclserror; - dst->avgce = src->avgce; - dst->rmserror = src->rmserror; - dst->avgerror = src->avgerror; - dst->avgrelerror = src->avgrelerror; -} - - -void _modelerrors_clear(void* _p) -{ - modelerrors *p = (modelerrors*)_p; - ae_touch_ptr((void*)p); -} - - -void _modelerrors_destroy(void* _p) -{ - modelerrors *p = (modelerrors*)_p; - ae_touch_ptr((void*)p); -} - - -void _smlpgrad_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - smlpgrad *p = (smlpgrad*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic); -} - - -void _smlpgrad_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - smlpgrad *dst = (smlpgrad*)_dst; - smlpgrad *src = (smlpgrad*)_src; - dst->f = src->f; - ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic); -} - - -void _smlpgrad_clear(void* _p) -{ - smlpgrad *p = (smlpgrad*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->g); -} - - -void _smlpgrad_destroy(void* _p) -{ - smlpgrad *p = (smlpgrad*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->g); -} - - -void _multilayerperceptron_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - multilayerperceptron *p = (multilayerperceptron*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->hllayersizes, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->hlconnections, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->hlneurons, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->structinfo, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->weights, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->columnmeans, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->columnsigmas, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->neurons, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dfdnet, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->derror, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->xy, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xyrow, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->nwbuf, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->integerbuf, 0, DT_INT, _state, make_automatic); - _modelerrors_init(&p->err, _state, make_automatic); - ae_vector_init(&p->rndbuf, 0, DT_REAL, _state, make_automatic); - ae_shared_pool_init(&p->buf, _state, make_automatic); - ae_shared_pool_init(&p->gradbuf, _state, make_automatic); - ae_matrix_init(&p->dummydxy, 0, 0, DT_REAL, _state, make_automatic); - _sparsematrix_init(&p->dummysxy, _state, make_automatic); - ae_vector_init(&p->dummyidx, 0, DT_INT, _state, make_automatic); - ae_shared_pool_init(&p->dummypool, _state, make_automatic); -} - - -void _multilayerperceptron_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - multilayerperceptron *dst = (multilayerperceptron*)_dst; - multilayerperceptron *src = (multilayerperceptron*)_src; - dst->hlnetworktype = src->hlnetworktype; - dst->hlnormtype = src->hlnormtype; - ae_vector_init_copy(&dst->hllayersizes, &src->hllayersizes, _state, make_automatic); - ae_vector_init_copy(&dst->hlconnections, &src->hlconnections, _state, make_automatic); - ae_vector_init_copy(&dst->hlneurons, &src->hlneurons, _state, make_automatic); - ae_vector_init_copy(&dst->structinfo, &src->structinfo, _state, make_automatic); - ae_vector_init_copy(&dst->weights, &src->weights, _state, make_automatic); - ae_vector_init_copy(&dst->columnmeans, &src->columnmeans, _state, make_automatic); - ae_vector_init_copy(&dst->columnsigmas, &src->columnsigmas, _state, make_automatic); - ae_vector_init_copy(&dst->neurons, &src->neurons, _state, make_automatic); - ae_vector_init_copy(&dst->dfdnet, &src->dfdnet, _state, make_automatic); - ae_vector_init_copy(&dst->derror, &src->derror, _state, make_automatic); - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic); - ae_matrix_init_copy(&dst->xy, &src->xy, _state, make_automatic); - ae_vector_init_copy(&dst->xyrow, &src->xyrow, _state, make_automatic); - ae_vector_init_copy(&dst->nwbuf, &src->nwbuf, _state, make_automatic); - ae_vector_init_copy(&dst->integerbuf, &src->integerbuf, _state, make_automatic); - _modelerrors_init_copy(&dst->err, &src->err, _state, make_automatic); - ae_vector_init_copy(&dst->rndbuf, &src->rndbuf, _state, make_automatic); - ae_shared_pool_init_copy(&dst->buf, &src->buf, _state, make_automatic); - ae_shared_pool_init_copy(&dst->gradbuf, &src->gradbuf, _state, make_automatic); - ae_matrix_init_copy(&dst->dummydxy, &src->dummydxy, _state, make_automatic); - _sparsematrix_init_copy(&dst->dummysxy, &src->dummysxy, _state, make_automatic); - ae_vector_init_copy(&dst->dummyidx, &src->dummyidx, _state, make_automatic); - ae_shared_pool_init_copy(&dst->dummypool, &src->dummypool, _state, make_automatic); -} - - -void _multilayerperceptron_clear(void* _p) -{ - multilayerperceptron *p = (multilayerperceptron*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->hllayersizes); - ae_vector_clear(&p->hlconnections); - ae_vector_clear(&p->hlneurons); - ae_vector_clear(&p->structinfo); - ae_vector_clear(&p->weights); - ae_vector_clear(&p->columnmeans); - ae_vector_clear(&p->columnsigmas); - ae_vector_clear(&p->neurons); - ae_vector_clear(&p->dfdnet); - ae_vector_clear(&p->derror); - ae_vector_clear(&p->x); - ae_vector_clear(&p->y); - ae_matrix_clear(&p->xy); - ae_vector_clear(&p->xyrow); - ae_vector_clear(&p->nwbuf); - ae_vector_clear(&p->integerbuf); - _modelerrors_clear(&p->err); - ae_vector_clear(&p->rndbuf); - ae_shared_pool_clear(&p->buf); - ae_shared_pool_clear(&p->gradbuf); - ae_matrix_clear(&p->dummydxy); - _sparsematrix_clear(&p->dummysxy); - ae_vector_clear(&p->dummyidx); - ae_shared_pool_clear(&p->dummypool); -} - - -void _multilayerperceptron_destroy(void* _p) -{ - multilayerperceptron *p = (multilayerperceptron*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->hllayersizes); - ae_vector_destroy(&p->hlconnections); - ae_vector_destroy(&p->hlneurons); - ae_vector_destroy(&p->structinfo); - ae_vector_destroy(&p->weights); - ae_vector_destroy(&p->columnmeans); - ae_vector_destroy(&p->columnsigmas); - ae_vector_destroy(&p->neurons); - ae_vector_destroy(&p->dfdnet); - ae_vector_destroy(&p->derror); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->y); - ae_matrix_destroy(&p->xy); - ae_vector_destroy(&p->xyrow); - ae_vector_destroy(&p->nwbuf); - ae_vector_destroy(&p->integerbuf); - _modelerrors_destroy(&p->err); - ae_vector_destroy(&p->rndbuf); - ae_shared_pool_destroy(&p->buf); - ae_shared_pool_destroy(&p->gradbuf); - ae_matrix_destroy(&p->dummydxy); - _sparsematrix_destroy(&p->dummysxy); - ae_vector_destroy(&p->dummyidx); - ae_shared_pool_destroy(&p->dummypool); -} - - -#endif -#if defined(AE_COMPILE_LDA) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Multiclass Fisher LDA - -Subroutine finds coefficients of linear combination which optimally separates -training set on classes. - -COMMERCIAL EDITION OF ALGLIB: - - ! Commercial version of ALGLIB includes two important improvements of - ! this function, which can be used from C++ and C#: - ! * Intel MKL support (lightweight Intel MKL is shipped with ALGLIB) - ! * multithreading support - ! - ! Intel MKL gives approximately constant (with respect to number of - ! worker threads) acceleration factor which depends on CPU being used, - ! problem size and "baseline" ALGLIB edition which is used for - ! comparison. Best results are achieved for high-dimensional problems - ! (NVars is at least 256). - ! - ! Multithreading is used to accelerate initial phase of LDA, which - ! includes calculation of products of large matrices. Again, for best - ! efficiency problem must be high-dimensional. - ! - ! Generally, commercial ALGLIB is several times faster than open-source - ! generic C edition, and many times faster than open-source C# edition. - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - training set, array[0..NPoints-1,0..NVars]. - First NVars columns store values of independent - variables, next column stores number of class (from 0 - to NClasses-1) which dataset element belongs to. Fractional - values are rounded to nearest integer. - NPoints - training set size, NPoints>=0 - NVars - number of independent variables, NVars>=1 - NClasses - number of classes, NClasses>=2 - - -OUTPUT PARAMETERS: - Info - return code: - * -4, if internal EVD subroutine hasn't converged - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed (NPoints<0, - NVars<1, NClasses<2) - * 1, if task has been solved - * 2, if there was a multicollinearity in training set, - but task has been solved. - W - linear combination coefficients, array[0..NVars-1] - - -- ALGLIB -- - Copyright 31.05.2008 by Bochkanov Sergey -*************************************************************************/ -void fisherlda(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - ae_int_t* info, - /* Real */ ae_vector* w, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix w2; - - ae_frame_make(_state, &_frame_block); - memset(&w2, 0, sizeof(w2)); - *info = 0; - ae_vector_clear(w); - ae_matrix_init(&w2, 0, 0, DT_REAL, _state, ae_true); - - fisherldan(xy, npoints, nvars, nclasses, info, &w2, _state); - if( *info>0 ) - { - ae_vector_set_length(w, nvars, _state); - ae_v_move(&w->ptr.p_double[0], 1, &w2.ptr.pp_double[0][0], w2.stride, ae_v_len(0,nvars-1)); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -N-dimensional multiclass Fisher LDA - -Subroutine finds coefficients of linear combinations which optimally separates -training set on classes. It returns N-dimensional basis whose vector are sorted -by quality of training set separation (in descending order). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - training set, array[0..NPoints-1,0..NVars]. - First NVars columns store values of independent - variables, next column stores number of class (from 0 - to NClasses-1) which dataset element belongs to. Fractional - values are rounded to nearest integer. - NPoints - training set size, NPoints>=0 - NVars - number of independent variables, NVars>=1 - NClasses - number of classes, NClasses>=2 - - -OUTPUT PARAMETERS: - Info - return code: - * -4, if internal EVD subroutine hasn't converged - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed (NPoints<0, - NVars<1, NClasses<2) - * 1, if task has been solved - * 2, if there was a multicollinearity in training set, - but task has been solved. - W - basis, array[0..NVars-1,0..NVars-1] - columns of matrix stores basis vectors, sorted by - quality of training set separation (in descending order) - - -- ALGLIB -- - Copyright 31.05.2008 by Bochkanov Sergey -*************************************************************************/ -void fisherldan(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - ae_int_t* info, - /* Real */ ae_matrix* w, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t m; - double v; - ae_vector c; - ae_vector mu; - ae_matrix muc; - ae_vector nc; - ae_matrix sw; - ae_matrix st; - ae_matrix z; - ae_matrix z2; - ae_matrix tm; - ae_matrix sbroot; - ae_matrix a; - ae_matrix xyc; - ae_matrix xyproj; - ae_matrix wproj; - ae_vector tf; - ae_vector d; - ae_vector d2; - ae_vector work; - - ae_frame_make(_state, &_frame_block); - memset(&c, 0, sizeof(c)); - memset(&mu, 0, sizeof(mu)); - memset(&muc, 0, sizeof(muc)); - memset(&nc, 0, sizeof(nc)); - memset(&sw, 0, sizeof(sw)); - memset(&st, 0, sizeof(st)); - memset(&z, 0, sizeof(z)); - memset(&z2, 0, sizeof(z2)); - memset(&tm, 0, sizeof(tm)); - memset(&sbroot, 0, sizeof(sbroot)); - memset(&a, 0, sizeof(a)); - memset(&xyc, 0, sizeof(xyc)); - memset(&xyproj, 0, sizeof(xyproj)); - memset(&wproj, 0, sizeof(wproj)); - memset(&tf, 0, sizeof(tf)); - memset(&d, 0, sizeof(d)); - memset(&d2, 0, sizeof(d2)); - memset(&work, 0, sizeof(work)); - *info = 0; - ae_matrix_clear(w); - ae_vector_init(&c, 0, DT_INT, _state, ae_true); - ae_vector_init(&mu, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&muc, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&nc, 0, DT_INT, _state, ae_true); - ae_matrix_init(&sw, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&st, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&tm, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&sbroot, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xyc, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xyproj, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&wproj, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - - - /* - * Test data - */ - if( (npoints<0||nvars<1)||nclasses<2 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - for(i=0; i<=npoints-1; i++) - { - if( ae_round(xy->ptr.pp_double[i][nvars], _state)<0||ae_round(xy->ptr.pp_double[i][nvars], _state)>=nclasses ) - { - *info = -2; - ae_frame_leave(_state); - return; - } - } - *info = 1; - - /* - * Special case: NPoints<=1 - * Degenerate task. - */ - if( npoints<=1 ) - { - *info = 2; - ae_matrix_set_length(w, nvars, nvars, _state); - for(i=0; i<=nvars-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - if( i==j ) - { - w->ptr.pp_double[i][j] = (double)(1); - } - else - { - w->ptr.pp_double[i][j] = (double)(0); - } - } - } - ae_frame_leave(_state); - return; - } - - /* - * Prepare temporaries - */ - ae_vector_set_length(&tf, nvars, _state); - ae_vector_set_length(&work, ae_maxint(nvars, npoints, _state)+1, _state); - ae_matrix_set_length(&xyc, npoints, nvars, _state); - - /* - * Convert class labels from reals to integers (just for convenience) - */ - ae_vector_set_length(&c, npoints, _state); - for(i=0; i<=npoints-1; i++) - { - c.ptr.p_int[i] = ae_round(xy->ptr.pp_double[i][nvars], _state); - } - - /* - * Calculate class sizes, class means - */ - ae_vector_set_length(&mu, nvars, _state); - ae_matrix_set_length(&muc, nclasses, nvars, _state); - ae_vector_set_length(&nc, nclasses, _state); - for(j=0; j<=nvars-1; j++) - { - mu.ptr.p_double[j] = (double)(0); - } - for(i=0; i<=nclasses-1; i++) - { - nc.ptr.p_int[i] = 0; - for(j=0; j<=nvars-1; j++) - { - muc.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=npoints-1; i++) - { - ae_v_add(&mu.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - ae_v_add(&muc.ptr.pp_double[c.ptr.p_int[i]][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - nc.ptr.p_int[c.ptr.p_int[i]] = nc.ptr.p_int[c.ptr.p_int[i]]+1; - } - for(i=0; i<=nclasses-1; i++) - { - v = (double)1/(double)nc.ptr.p_int[i]; - ae_v_muld(&muc.ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1), v); - } - v = (double)1/(double)npoints; - ae_v_muld(&mu.ptr.p_double[0], 1, ae_v_len(0,nvars-1), v); - - /* - * Create ST matrix - */ - ae_matrix_set_length(&st, nvars, nvars, _state); - for(i=0; i<=nvars-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - st.ptr.pp_double[i][j] = (double)(0); - } - } - for(k=0; k<=npoints-1; k++) - { - ae_v_move(&xyc.ptr.pp_double[k][0], 1, &xy->ptr.pp_double[k][0], 1, ae_v_len(0,nvars-1)); - ae_v_sub(&xyc.ptr.pp_double[k][0], 1, &mu.ptr.p_double[0], 1, ae_v_len(0,nvars-1)); - } - rmatrixgemm(nvars, nvars, npoints, 1.0, &xyc, 0, 0, 1, &xyc, 0, 0, 0, 0.0, &st, 0, 0, _state); - - /* - * Create SW matrix - */ - ae_matrix_set_length(&sw, nvars, nvars, _state); - for(i=0; i<=nvars-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - sw.ptr.pp_double[i][j] = (double)(0); - } - } - for(k=0; k<=npoints-1; k++) - { - ae_v_move(&xyc.ptr.pp_double[k][0], 1, &xy->ptr.pp_double[k][0], 1, ae_v_len(0,nvars-1)); - ae_v_sub(&xyc.ptr.pp_double[k][0], 1, &muc.ptr.pp_double[c.ptr.p_int[k]][0], 1, ae_v_len(0,nvars-1)); - } - rmatrixgemm(nvars, nvars, npoints, 1.0, &xyc, 0, 0, 1, &xyc, 0, 0, 0, 0.0, &sw, 0, 0, _state); - - /* - * Maximize ratio J=(w'*ST*w)/(w'*SW*w). - * - * First, make transition from w to v such that w'*ST*w becomes v'*v: - * v = root(ST)*w = R*w - * R = root(D)*Z' - * w = (root(ST)^-1)*v = RI*v - * RI = Z*inv(root(D)) - * J = (v'*v)/(v'*(RI'*SW*RI)*v) - * ST = Z*D*Z' - * - * so we have - * - * J = (v'*v) / (v'*(inv(root(D))*Z'*SW*Z*inv(root(D)))*v) = - * = (v'*v) / (v'*A*v) - */ - if( !smatrixevd(&st, nvars, 1, ae_true, &d, &z, _state) ) - { - *info = -4; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(w, nvars, nvars, _state); - if( ae_fp_less_eq(d.ptr.p_double[nvars-1],(double)(0))||ae_fp_less_eq(d.ptr.p_double[0],1000*ae_machineepsilon*d.ptr.p_double[nvars-1]) ) - { - - /* - * Special case: D[NVars-1]<=0 - * Degenerate task (all variables takes the same value). - */ - if( ae_fp_less_eq(d.ptr.p_double[nvars-1],(double)(0)) ) - { - *info = 2; - for(i=0; i<=nvars-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - if( i==j ) - { - w->ptr.pp_double[i][j] = (double)(1); - } - else - { - w->ptr.pp_double[i][j] = (double)(0); - } - } - } - ae_frame_leave(_state); - return; - } - - /* - * Special case: degenerate ST matrix, multicollinearity found. - * Since we know ST eigenvalues/vectors we can translate task to - * non-degenerate form. - * - * Let WG is orthogonal basis of the non zero variance subspace - * of the ST and let WZ is orthogonal basis of the zero variance - * subspace. - * - * Projection on WG allows us to use LDA on reduced M-dimensional - * subspace, N-M vectors of WZ allows us to update reduced LDA - * factors to full N-dimensional subspace. - */ - m = 0; - for(k=0; k<=nvars-1; k++) - { - if( ae_fp_less_eq(d.ptr.p_double[k],1000*ae_machineepsilon*d.ptr.p_double[nvars-1]) ) - { - m = k+1; - } - } - ae_assert(m!=0, "FisherLDAN: internal error #1", _state); - ae_matrix_set_length(&xyproj, npoints, nvars-m+1, _state); - rmatrixgemm(npoints, nvars-m, nvars, 1.0, xy, 0, 0, 0, &z, 0, m, 0, 0.0, &xyproj, 0, 0, _state); - for(i=0; i<=npoints-1; i++) - { - xyproj.ptr.pp_double[i][nvars-m] = xy->ptr.pp_double[i][nvars]; - } - fisherldan(&xyproj, npoints, nvars-m, nclasses, info, &wproj, _state); - if( *info<0 ) - { - ae_frame_leave(_state); - return; - } - rmatrixgemm(nvars, nvars-m, nvars-m, 1.0, &z, 0, m, 0, &wproj, 0, 0, 0, 0.0, w, 0, 0, _state); - for(k=nvars-m; k<=nvars-1; k++) - { - ae_v_move(&w->ptr.pp_double[0][k], w->stride, &z.ptr.pp_double[0][k-(nvars-m)], z.stride, ae_v_len(0,nvars-1)); - } - *info = 2; - } - else - { - - /* - * General case: no multicollinearity - */ - ae_matrix_set_length(&tm, nvars, nvars, _state); - ae_matrix_set_length(&a, nvars, nvars, _state); - rmatrixgemm(nvars, nvars, nvars, 1.0, &sw, 0, 0, 0, &z, 0, 0, 0, 0.0, &tm, 0, 0, _state); - rmatrixgemm(nvars, nvars, nvars, 1.0, &z, 0, 0, 1, &tm, 0, 0, 0, 0.0, &a, 0, 0, _state); - for(i=0; i<=nvars-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]/ae_sqrt(d.ptr.p_double[i]*d.ptr.p_double[j], _state); - } - } - if( !smatrixevd(&a, nvars, 1, ae_true, &d2, &z2, _state) ) - { - *info = -4; - ae_frame_leave(_state); - return; - } - for(i=0; i<=nvars-1; i++) - { - for(k=0; k<=nvars-1; k++) - { - z2.ptr.pp_double[i][k] = z2.ptr.pp_double[i][k]/ae_sqrt(d.ptr.p_double[i], _state); - } - } - rmatrixgemm(nvars, nvars, nvars, 1.0, &z, 0, 0, 0, &z2, 0, 0, 0, 0.0, w, 0, 0, _state); - } - - /* - * Post-processing: - * * normalization - * * converting to non-negative form, if possible - */ - for(k=0; k<=nvars-1; k++) - { - v = ae_v_dotproduct(&w->ptr.pp_double[0][k], w->stride, &w->ptr.pp_double[0][k], w->stride, ae_v_len(0,nvars-1)); - v = 1/ae_sqrt(v, _state); - ae_v_muld(&w->ptr.pp_double[0][k], w->stride, ae_v_len(0,nvars-1), v); - v = (double)(0); - for(i=0; i<=nvars-1; i++) - { - v = v+w->ptr.pp_double[i][k]; - } - if( ae_fp_less(v,(double)(0)) ) - { - ae_v_muld(&w->ptr.pp_double[0][k], w->stride, ae_v_len(0,nvars-1), -1); - } - } - ae_frame_leave(_state); -} - - -#endif -#if defined(AE_COMPILE_SSA) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function creates SSA model object. Right after creation model is in -"dummy" mode - you can add data, but analyzing/prediction will return -just zeros (it assumes that basis is empty). - -HOW TO USE SSA MODEL: - -1. create model with ssacreate() -2. add data with one/many ssaaddsequence() calls -3. choose SSA algorithm with one of ssasetalgo...() functions: - * ssasetalgotopkdirect() for direct one-run analysis - * ssasetalgotopkrealtime() for algorithm optimized for many subsequent - runs with warm-start capabilities - * ssasetalgoprecomputed() for user-supplied basis -4. set window width with ssasetwindow() -5. perform one of the analysis-related activities: - a) call ssagetbasis() to get basis - b) call ssaanalyzelast() ssaanalyzesequence() or ssaanalyzelastwindow() - to perform analysis (trend/noise separation) - c) call one of the forecasting functions (ssaforecastlast() or - ssaforecastsequence()) to perform prediction; alternatively, you can - extract linear recurrence coefficients with ssagetlrr(). - SSA analysis will be performed during first call to analysis-related - function. SSA model is smart enough to track all changes in the dataset - and model settings, to cache previously computed basis and to - re-evaluate basis only when necessary. - -Additionally, if your setting involves constant stream of incoming data, -you can perform quick update already calculated model with one of the -incremental append-and-update functions: ssaappendpointandupdate() or -ssaappendsequenceandupdate(). - -NOTE: steps (2), (3), (4) can be performed in arbitrary order. - -INPUT PARAMETERS: - none - -OUTPUT PARAMETERS: - S - structure which stores model state - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssacreate(ssamodel* s, ae_state *_state) -{ - - _ssamodel_clear(s); - - - /* - * Model data, algorithms and settings - */ - s->nsequences = 0; - ae_vector_set_length(&s->sequenceidx, 1, _state); - s->sequenceidx.ptr.p_int[0] = 0; - s->algotype = 0; - s->windowwidth = 1; - s->rtpowerup = 1; - s->arebasisandsolvervalid = ae_false; - s->rngseed = 1; - s->defaultsubspaceits = 10; - s->memorylimit = 50000000; - - /* - * Debug counters - */ - s->dbgcntevd = 0; -} - - -/************************************************************************* -This function sets window width for SSA model. You should call it before -analysis phase. Default window width is 1 (not for real use). - -Special notes: -* this function call can be performed at any moment before first call to - analysis-related functions -* changing window width invalidates internally stored basis; if you change - window width AFTER you call analysis-related function, next analysis - phase will require re-calculation of the basis according to current - algorithm. -* calling this function with exactly same window width as current one has - no effect -* if you specify window width larger than any data sequence stored in the - model, analysis will return zero basis. - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - WindowWidth - >=1, new window width - -OUTPUT PARAMETERS: - S - SSA model, updated - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssasetwindow(ssamodel* s, ae_int_t windowwidth, ae_state *_state) -{ - - - ae_assert(windowwidth>=1, "SSASetWindow: WindowWidth<1", _state); - if( windowwidth==s->windowwidth ) - { - return; - } - s->windowwidth = windowwidth; - s->arebasisandsolvervalid = ae_false; -} - - -/************************************************************************* -This function sets seed which is used to initialize internal RNG when -we make pseudorandom decisions on model updates. - -By default, deterministic seed is used - which results in same sequence of -pseudorandom decisions every time you run SSA model. If you specify non- -deterministic seed value, then SSA model may return slightly different -results after each run. - -This function can be useful when you have several SSA models updated with -sseappendpointandupdate() called with 0rngseed = seed; -} - - -/************************************************************************* -This function sets length of power-up cycle for real-time algorithm. - -By default, this algorithm performs costly O(N*WindowWidth^2) init phase -followed by full run of truncated EVD. However, if you are ready to -live with a bit lower-quality basis during first few iterations, you can -split this O(N*WindowWidth^2) initialization between several subsequent -append-and-update rounds. It results in better latency of the algorithm. - -This function invalidates basis/solver, next analysis call will result in -full recalculation of everything. - -INPUT PARAMETERS: - S - SSA model - PWLen - length of the power-up stage: - * 0 means that no power-up is requested - * 1 is the same as 0 - * >1 means that delayed power-up is performed - - -- ALGLIB -- - Copyright 03.11.2017 by Bochkanov Sergey -*************************************************************************/ -void ssasetpoweruplength(ssamodel* s, ae_int_t pwlen, ae_state *_state) -{ - - - ae_assert(pwlen>=0, "SSASetPowerUpLength: PWLen<0", _state); - s->rtpowerup = ae_maxint(pwlen, 1, _state); - s->arebasisandsolvervalid = ae_false; -} - - -/************************************************************************* -This function sets memory limit of SSA analysis. - -Straightforward SSA with sequence length T and window width W needs O(T*W) -memory. It is possible to reduce memory consumption by splitting task into -smaller chunks. - -Thus function allows you to specify approximate memory limit (measured in -double precision numbers used for buffers). Actual memory consumption will -be comparable to the number specified by you. - -Default memory limit is 50.000.000 (400Mbytes) in current version. - -INPUT PARAMETERS: - S - SSA model - MemLimit- memory limit, >=0. Zero value means no limit. - - -- ALGLIB -- - Copyright 20.12.2017 by Bochkanov Sergey -*************************************************************************/ -void ssasetmemorylimit(ssamodel* s, ae_int_t memlimit, ae_state *_state) -{ - - - if( memlimit<0 ) - { - memlimit = 0; - } - s->memorylimit = memlimit; -} - - -/************************************************************************* -This function adds data sequence to SSA model. Only single-dimensional -sequences are supported. - -What is a sequences? Following definitions/requirements apply: -* a sequence is an array of values measured in subsequent, equally - separated time moments (ticks). -* you may have many sequences in your dataset; say, one sequence may - correspond to one trading session. -* sequence length should be larger than current window length (shorter - sequences will be ignored during analysis). -* analysis is performed within a sequence; different sequences are NOT - stacked together to produce one large contiguous stream of data. -* analysis is performed for all sequences at once, i.e. same set of basis - vectors is computed for all sequences - -INCREMENTAL ANALYSIS - -This function is non intended for incremental updates of previously found -SSA basis. Calling it invalidates all previous analysis results (basis is -reset and will be recalculated from zero during next analysis). - -If you want to perform incremental/real-time SSA, consider using -following functions: -* ssaappendpointandupdate() for appending one point -* ssaappendsequenceandupdate() for appending new sequence - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - X - array[N], data, can be larger (additional values - are ignored) - N - data length, can be automatically determined from - the array length. N>=0. - -OUTPUT PARAMETERS: - S - SSA model, updated - -NOTE: you can clear dataset with ssacleardata() - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaaddsequence(ssamodel* s, - /* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t offs; - - - ae_assert(n>=0, "SSAAddSequence: N<0", _state); - ae_assert(x->cnt>=n, "SSAAddSequence: X is too short", _state); - ae_assert(isfinitevector(x, n, _state), "SSAAddSequence: X contains infinities NANs", _state); - - /* - * Invalidate model - */ - s->arebasisandsolvervalid = ae_false; - - /* - * Add sequence - */ - ivectorgrowto(&s->sequenceidx, s->nsequences+2, _state); - s->sequenceidx.ptr.p_int[s->nsequences+1] = s->sequenceidx.ptr.p_int[s->nsequences]+n; - rvectorgrowto(&s->sequencedata, s->sequenceidx.ptr.p_int[s->nsequences+1], _state); - offs = s->sequenceidx.ptr.p_int[s->nsequences]; - for(i=0; i<=n-1; i++) - { - s->sequencedata.ptr.p_double[offs+i] = x->ptr.p_double[i]; - } - inc(&s->nsequences, _state); -} - - -/************************************************************************* -This function appends single point to last data sequence stored in the SSA -model and tries to update model in the incremental manner (if possible -with current algorithm). - -If you want to add more than one point at once: -* if you want to add M points to the same sequence, perform M-1 calls with - UpdateIts parameter set to 0.0, and last call with non-zero UpdateIts. -* if you want to add new sequence, use ssaappendsequenceandupdate() - -Running time of this function does NOT depend on dataset size, only on -window width and number of singular vectors. Depending on algorithm being -used, incremental update has complexity: -* for top-K real time - O(UpdateIts*K*Width^2), with fractional UpdateIts -* for top-K direct - O(Width^3) for any non-zero UpdateIts -* for precomputed basis - O(1), no update is performed - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - X - new point - UpdateIts - >=0, floating point (!) value, desired update - frequency: - * zero value means that point is stored, but no - update is performed - * integer part of the value means that specified - number of iterations is always performed - * fractional part of the value means that one - iteration is performed with this probability. - - Recommended value: 0nsequences>0, "SSAAppendPointAndUpdate: dataset is empty, no sequence to modify", _state); - - /* - * Append point to dataset - */ - rvectorgrowto(&s->sequencedata, s->sequenceidx.ptr.p_int[s->nsequences]+1, _state); - s->sequencedata.ptr.p_double[s->sequenceidx.ptr.p_int[s->nsequences]] = x; - s->sequenceidx.ptr.p_int[s->nsequences] = s->sequenceidx.ptr.p_int[s->nsequences]+1; - - /* - * Do we have something to analyze? If no, invalidate basis - * (just to be sure) and exit. - */ - if( !ssa_hassomethingtoanalyze(s, _state) ) - { - s->arebasisandsolvervalid = ae_false; - return; - } - - /* - * Well, we have data to analyze and algorithm set, but basis is - * invalid. Let's calculate it from scratch and exit. - */ - if( !s->arebasisandsolvervalid ) - { - ssa_updatebasis(s, 0, 0.0, _state); - return; - } - - /* - * Update already computed basis - */ - ssa_updatebasis(s, 1, updateits, _state); -} - - -/************************************************************************* -This function appends new sequence to dataset stored in the SSA model and -tries to update model in the incremental manner (if possible with current -algorithm). - -Notes: -* if you want to add M sequences at once, perform M-1 calls with UpdateIts - parameter set to 0.0, and last call with non-zero UpdateIts. -* if you want to add just one point, use ssaappendpointandupdate() - -Running time of this function does NOT depend on dataset size, only on -sequence length, window width and number of singular vectors. Depending on -algorithm being used, incremental update has complexity: -* for top-K real time - O(UpdateIts*K*Width^2+(NTicks-Width)*Width^2) -* for top-K direct - O(Width^3+(NTicks-Width)*Width^2) -* for precomputed basis - O(1), no update is performed - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - X - new sequence, array[NTicks] or larget - NTicks - >=1, number of ticks in the sequence - UpdateIts - >=0, floating point (!) value, desired update - frequency: - * zero value means that point is stored, but no - update is performed - * integer part of the value means that specified - number of iterations is always performed - * fractional part of the value means that one - iteration is performed with this probability. - - Recommended value: 0=0, "SSAAppendSequenceAndUpdate: NTicks<0", _state); - ae_assert(x->cnt>=nticks, "SSAAppendSequenceAndUpdate: X is too short", _state); - ae_assert(isfinitevector(x, nticks, _state), "SSAAppendSequenceAndUpdate: X contains infinities NANs", _state); - - /* - * Add sequence - */ - ivectorgrowto(&s->sequenceidx, s->nsequences+2, _state); - s->sequenceidx.ptr.p_int[s->nsequences+1] = s->sequenceidx.ptr.p_int[s->nsequences]+nticks; - rvectorgrowto(&s->sequencedata, s->sequenceidx.ptr.p_int[s->nsequences+1], _state); - offs = s->sequenceidx.ptr.p_int[s->nsequences]; - for(i=0; i<=nticks-1; i++) - { - s->sequencedata.ptr.p_double[offs+i] = x->ptr.p_double[i]; - } - inc(&s->nsequences, _state); - - /* - * Do we have something to analyze? If no, invalidate basis - * (just to be sure) and exit. - */ - if( !ssa_hassomethingtoanalyze(s, _state) ) - { - s->arebasisandsolvervalid = ae_false; - return; - } - - /* - * Well, we have data to analyze and algorithm set, but basis is - * invalid. Let's calculate it from scratch and exit. - */ - if( !s->arebasisandsolvervalid ) - { - ssa_updatebasis(s, 0, 0.0, _state); - return; - } - - /* - * Update already computed basis - */ - if( nticks>=s->windowwidth ) - { - ssa_updatebasis(s, nticks-s->windowwidth+1, updateits, _state); - } -} - - -/************************************************************************* -This function sets SSA algorithm to "precomputed vectors" algorithm. - -This algorithm uses precomputed set of orthonormal (orthogonal AND -normalized) basis vectors supplied by user. Thus, basis calculation phase -is not performed - we already have our basis - and only analysis/ -forecasting phase requires actual calculations. - -This algorithm may handle "append" requests which add just one/few ticks -to the end of the last sequence in O(1) time. - -NOTE: this algorithm accepts both basis and window width, because these - two parameters are naturally aligned. Calling this function sets - window width; if you call ssasetwindow() with other window width, - then during analysis stage algorithm will detect conflict and reset - to zero basis. - -INPUT PARAMETERS: - S - SSA model - A - array[WindowWidth,NBasis], orthonormalized basis; - this function does NOT control orthogonality and - does NOT perform any kind of renormalization. It - is your responsibility to provide it with correct - basis. - WindowWidth - window width, >=1 - NBasis - number of basis vectors, 1<=NBasis<=WindowWidth - -OUTPUT PARAMETERS: - S - updated model - -NOTE: calling this function invalidates basis in all cases. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssasetalgoprecomputed(ssamodel* s, - /* Real */ ae_matrix* a, - ae_int_t windowwidth, - ae_int_t nbasis, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - ae_assert(windowwidth>=1, "SSASetAlgoPrecomputed: WindowWidth<1", _state); - ae_assert(nbasis>=1, "SSASetAlgoPrecomputed: NBasis<1", _state); - ae_assert(nbasis<=windowwidth, "SSASetAlgoPrecomputed: NBasis>WindowWidth", _state); - ae_assert(a->rows>=windowwidth, "SSASetAlgoPrecomputed: Rows(A)cols>=nbasis, "SSASetAlgoPrecomputed: Rows(A)algotype = 1; - s->precomputedwidth = windowwidth; - s->precomputednbasis = nbasis; - s->windowwidth = windowwidth; - rmatrixsetlengthatleast(&s->precomputedbasis, windowwidth, nbasis, _state); - for(i=0; i<=windowwidth-1; i++) - { - for(j=0; j<=nbasis-1; j++) - { - s->precomputedbasis.ptr.pp_double[i][j] = a->ptr.pp_double[i][j]; - } - } - s->arebasisandsolvervalid = ae_false; -} - - -/************************************************************************* -This function sets SSA algorithm to "direct top-K" algorithm. - -"Direct top-K" algorithm performs full SVD of the N*WINDOW trajectory -matrix (hence its name - direct solver is used), then extracts top K -components. Overall running time is O(N*WINDOW^2), where N is a number of -ticks in the dataset, WINDOW is window width. - -This algorithm may handle "append" requests which add just one/few ticks -to the end of the last sequence in O(WINDOW^3) time, which is ~N/WINDOW -times faster than re-computing everything from scratch. - -INPUT PARAMETERS: - S - SSA model - TopK - number of components to analyze; TopK>=1. - -OUTPUT PARAMETERS: - S - updated model - - -NOTE: TopK>WindowWidth is silently decreased to WindowWidth during analysis - phase - -NOTE: calling this function invalidates basis, except for the situation - when this algorithm was already set with same parameters. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssasetalgotopkdirect(ssamodel* s, ae_int_t topk, ae_state *_state) -{ - - - ae_assert(topk>=1, "SSASetAlgoTopKDirect: TopK<1", _state); - - /* - * Ignore calls which change nothing - */ - if( s->algotype==2&&s->topk==topk ) - { - return; - } - - /* - * Update settings, invalidate model - */ - s->algotype = 2; - s->topk = topk; - s->arebasisandsolvervalid = ae_false; -} - - -/************************************************************************* -This function sets SSA algorithm to "top-K real time algorithm". This algo -extracts K components with largest singular values. - -It is real-time version of top-K algorithm which is optimized for -incremental processing and fast start-up. Internally it uses subspace -eigensolver for truncated SVD. It results in ability to perform quick -updates of the basis when only a few points/sequences is added to dataset. - -Performance profile of the algorithm is given below: -* O(K*WindowWidth^2) running time for incremental update of the dataset - with one of the "append-and-update" functions (ssaappendpointandupdate() - or ssaappendsequenceandupdate()). -* O(N*WindowWidth^2) running time for initial basis evaluation (N=size of - dataset) -* ability to split costly initialization across several incremental - updates of the basis (so called "Power-Up" functionality, activated by - ssasetpoweruplength() function) - -INPUT PARAMETERS: - S - SSA model - TopK - number of components to analyze; TopK>=1. - -OUTPUT PARAMETERS: - S - updated model - -NOTE: this algorithm is optimized for large-scale tasks with large - datasets. On toy problems with just 5-10 points it can return basis - which is slightly different from that returned by direct algorithm - (ssasetalgotopkdirect() function). However, the difference becomes - negligible as dataset grows. - -NOTE: TopK>WindowWidth is silently decreased to WindowWidth during analysis - phase - -NOTE: calling this function invalidates basis, except for the situation - when this algorithm was already set with same parameters. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssasetalgotopkrealtime(ssamodel* s, ae_int_t topk, ae_state *_state) -{ - - - ae_assert(topk>=1, "SSASetAlgoTopKRealTime: TopK<1", _state); - - /* - * Ignore calls which change nothing - */ - if( s->algotype==3&&s->topk==topk ) - { - return; - } - - /* - * Update settings, invalidate model - */ - s->algotype = 3; - s->topk = topk; - s->arebasisandsolvervalid = ae_false; -} - - -/************************************************************************* -This function clears all data stored in the model and invalidates all -basis components found so far. - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - -OUTPUT PARAMETERS: - S - SSA model, updated - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssacleardata(ssamodel* s, ae_state *_state) -{ - - - s->nsequences = 0; - s->arebasisandsolvervalid = ae_false; -} - - -/************************************************************************* -This function executes SSA on internally stored dataset and returns basis -found by current method. - -INPUT PARAMETERS: - S - SSA model - -OUTPUT PARAMETERS: - A - array[WindowWidth,NBasis], basis; vectors are - stored in matrix columns, by descreasing variance - SV - array[NBasis]: - * zeros - for model initialized with SSASetAlgoPrecomputed() - * singular values - for other algorithms - WindowWidth - current window - NBasis - basis size - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Calling this function in degenerate cases (no data or all data are -shorter than window size; no algorithm is specified) returns basis with -just one zero vector. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssagetbasis(ssamodel* s, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* sv, - ae_int_t* windowwidth, - ae_int_t* nbasis, - ae_state *_state) -{ - ae_int_t i; - - ae_matrix_clear(a); - ae_vector_clear(sv); - *windowwidth = 0; - *nbasis = 0; - - - /* - * Is it degenerate case? - */ - if( !ssa_hassomethingtoanalyze(s, _state) ) - { - *windowwidth = s->windowwidth; - *nbasis = 1; - ae_matrix_set_length(a, *windowwidth, 1, _state); - for(i=0; i<=*windowwidth-1; i++) - { - a->ptr.pp_double[i][0] = 0.0; - } - ae_vector_set_length(sv, 1, _state); - sv->ptr.p_double[0] = 0.0; - return; - } - - /* - * Update basis. - * - * It will take care of basis validity flags. AppendLen=0 which means - * that we perform initial basis evaluation. - */ - ssa_updatebasis(s, 0, 0.0, _state); - - /* - * Output - */ - ae_assert(s->nbasis>0, "SSAGetBasis: integrity check failed", _state); - ae_assert(s->windowwidth>0, "SSAGetBasis: integrity check failed", _state); - *nbasis = s->nbasis; - *windowwidth = s->windowwidth; - ae_matrix_set_length(a, *windowwidth, *nbasis, _state); - rmatrixcopy(*windowwidth, *nbasis, &s->basis, 0, 0, a, 0, 0, _state); - ae_vector_set_length(sv, *nbasis, _state); - for(i=0; i<=*nbasis-1; i++) - { - sv->ptr.p_double[i] = s->sv.ptr.p_double[i]; - } -} - - -/************************************************************************* -This function returns linear recurrence relation (LRR) coefficients found -by current SSA algorithm. - -INPUT PARAMETERS: - S - SSA model - -OUTPUT PARAMETERS: - A - array[WindowWidth-1]. Coefficients of the - linear recurrence of the form: - X[W-1] = X[W-2]*A[W-2] + X[W-3]*A[W-3] + ... + X[0]*A[0]. - Empty array for WindowWidth=1. - WindowWidth - current window width - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Calling this function in degenerate cases (no data or all data are -shorter than window size; no algorithm is specified) returns zeros. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssagetlrr(ssamodel* s, - /* Real */ ae_vector* a, - ae_int_t* windowwidth, - ae_state *_state) -{ - ae_int_t i; - - ae_vector_clear(a); - *windowwidth = 0; - - ae_assert(s->windowwidth>0, "SSAGetLRR: integrity check failed", _state); - - /* - * Is it degenerate case? - */ - if( !ssa_hassomethingtoanalyze(s, _state) ) - { - *windowwidth = s->windowwidth; - ae_vector_set_length(a, *windowwidth-1, _state); - for(i=0; i<=*windowwidth-2; i++) - { - a->ptr.p_double[i] = 0.0; - } - return; - } - - /* - * Update basis. - * - * It will take care of basis validity flags. AppendLen=0 which means - * that we perform initial basis evaluation. - */ - ssa_updatebasis(s, 0, 0.0, _state); - - /* - * Output - */ - *windowwidth = s->windowwidth; - ae_vector_set_length(a, *windowwidth-1, _state); - for(i=0; i<=*windowwidth-2; i++) - { - a->ptr.p_double[i] = s->forecasta.ptr.p_double[i]; - } -} - - -/************************************************************************* -This function executes SSA on internally stored dataset and returns -analysis for the last window of the last sequence. Such analysis is -an lightweight alternative for full scale reconstruction (see below). - -Typical use case for this function is real-time setting, when you are -interested in quick-and-dirty (very quick and very dirty) processing of -just a few last ticks of the trend. - -IMPORTANT: full scale SSA involves analysis of the ENTIRE dataset, - with reconstruction being done for all positions of sliding - window with subsequent hankelization (diagonal averaging) of - the resulting matrix. - - Such analysis requires O((DataLen-Window)*Window*NBasis) FLOPs - and can be quite costly. However, it has nice noise-canceling - effects due to averaging. - - This function performs REDUCED analysis of the last window. It - is much faster - just O(Window*NBasis), but its results are - DIFFERENT from that of ssaanalyzelast(). In particular, first - few points of the trend are much more prone to noise. - -INPUT PARAMETERS: - S - SSA model - -OUTPUT PARAMETERS: - Trend - array[WindowSize], reconstructed trend line - Noise - array[WindowSize], the rest of the signal; - it holds that ActualData = Trend+Noise. - NTicks - current WindowSize - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - -In any case, only basis is reused. Reconstruction is performed from -scratch every time you call this function. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* last sequence is shorter than the window length (analysis can be done, - but we can not perform reconstruction on the last sequence) - -Calling this function in degenerate cases returns following result: -* in any case, WindowWidth ticks is returned -* trend is assumed to be zero -* noise is initialized by the last sequence; if last sequence is shorter - than the window size, it is moved to the end of the array, and the - beginning of the noise array is filled by zeros - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaanalyzelastwindow(ssamodel* s, - /* Real */ ae_vector* trend, - /* Real */ ae_vector* noise, - ae_int_t* nticks, - ae_state *_state) -{ - ae_int_t i; - ae_int_t offs; - ae_int_t cnt; - - ae_vector_clear(trend); - ae_vector_clear(noise); - *nticks = 0; - - - /* - * Init - */ - *nticks = s->windowwidth; - ae_vector_set_length(trend, s->windowwidth, _state); - ae_vector_set_length(noise, s->windowwidth, _state); - - /* - * Is it degenerate case? - */ - if( !ssa_hassomethingtoanalyze(s, _state)||!ssa_issequencebigenough(s, -1, _state) ) - { - for(i=0; i<=*nticks-1; i++) - { - trend->ptr.p_double[i] = (double)(0); - noise->ptr.p_double[i] = (double)(0); - } - if( s->nsequences>=1 ) - { - cnt = ae_minint(s->sequenceidx.ptr.p_int[s->nsequences]-s->sequenceidx.ptr.p_int[s->nsequences-1], *nticks, _state); - offs = s->sequenceidx.ptr.p_int[s->nsequences]-cnt; - for(i=0; i<=cnt-1; i++) - { - noise->ptr.p_double[*nticks-cnt+i] = s->sequencedata.ptr.p_double[offs+i]; - } - } - return; - } - - /* - * Update basis. - * - * It will take care of basis validity flags. AppendLen=0 which means - * that we perform initial basis evaluation. - */ - ssa_updatebasis(s, 0, 0.0, _state); - - /* - * Perform analysis of the last window - */ - ae_assert(s->sequenceidx.ptr.p_int[s->nsequences]-s->windowwidth>=0, "SSAAnalyzeLastWindow: integrity check failed", _state); - rvectorsetlengthatleast(&s->tmp0, s->nbasis, _state); - rmatrixgemv(s->nbasis, s->windowwidth, 1.0, &s->basist, 0, 0, 0, &s->sequencedata, s->sequenceidx.ptr.p_int[s->nsequences]-s->windowwidth, 0.0, &s->tmp0, 0, _state); - rmatrixgemv(s->windowwidth, s->nbasis, 1.0, &s->basis, 0, 0, 0, &s->tmp0, 0, 0.0, trend, 0, _state); - offs = s->sequenceidx.ptr.p_int[s->nsequences]-s->windowwidth; - cnt = s->windowwidth; - for(i=0; i<=cnt-1; i++) - { - noise->ptr.p_double[i] = s->sequencedata.ptr.p_double[offs+i]-trend->ptr.p_double[i]; - } -} - - -/************************************************************************* -This function: -* builds SSA basis using internally stored (entire) dataset -* returns reconstruction for the last NTicks of the last sequence - -If you want to analyze some other sequence, use ssaanalyzesequence(). - -Reconstruction phase involves generation of NTicks-WindowWidth sliding -windows, their decomposition using empirical orthogonal functions found by -SSA, followed by averaging of each data point across several overlapping -windows. Thus, every point in the output trend is reconstructed using up -to WindowWidth overlapping windows (WindowWidth windows exactly in the -inner points, just one window at the extremal points). - -IMPORTANT: due to averaging this function returns different results for - different values of NTicks. It is expected and not a bug. - - For example: - * Trend[NTicks-1] is always same because it is not averaged in - any case (same applies to Trend[0]). - * Trend[NTicks-2] has different values for NTicks=WindowWidth - and NTicks=WindowWidth+1 because former case means that no - averaging is performed, and latter case means that averaging - using two sliding windows is performed. Larger values of - NTicks produce same results as NTicks=WindowWidth+1. - * ...and so on... - -PERFORMANCE: this function has O((NTicks-WindowWidth)*WindowWidth*NBasis) - running time. If you work in time-constrained setting and - have to analyze just a few last ticks, choosing NTicks equal - to WindowWidth+SmoothingLen, with SmoothingLen=1...WindowWidth - will result in good compromise between noise cancellation and - analysis speed. - -INPUT PARAMETERS: - S - SSA model - NTicks - number of ticks to analyze, Nticks>=1. - * special case of NTicks<=WindowWidth is handled - by analyzing last window and returning NTicks - last ticks. - * special case NTicks>LastSequenceLen is handled - by prepending result with NTicks-LastSequenceLen - zeros. - -OUTPUT PARAMETERS: - Trend - array[NTicks], reconstructed trend line - Noise - array[NTicks], the rest of the signal; - it holds that ActualData = Trend+Noise. - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - -In any case, only basis is reused. Reconstruction is performed from -scratch every time you call this function. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* last sequence is shorter than the window length (analysis can be done, - but we can not perform reconstruction on the last sequence) - -Calling this function in degenerate cases returns following result: -* in any case, NTicks ticks is returned -* trend is assumed to be zero -* noise is initialized by the last sequence; if last sequence is shorter - than the window size, it is moved to the end of the array, and the - beginning of the noise array is filled by zeros - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaanalyzelast(ssamodel* s, - ae_int_t nticks, - /* Real */ ae_vector* trend, - /* Real */ ae_vector* noise, - ae_state *_state) -{ - ae_int_t i; - ae_int_t offs; - ae_int_t cnt; - ae_int_t cntzeros; - - ae_vector_clear(trend); - ae_vector_clear(noise); - - ae_assert(nticks>=1, "SSAAnalyzeLast: NTicks<1", _state); - - /* - * Init - */ - ae_vector_set_length(trend, nticks, _state); - ae_vector_set_length(noise, nticks, _state); - - /* - * Is it degenerate case? - */ - if( !ssa_hassomethingtoanalyze(s, _state)||!ssa_issequencebigenough(s, -1, _state) ) - { - for(i=0; i<=nticks-1; i++) - { - trend->ptr.p_double[i] = (double)(0); - noise->ptr.p_double[i] = (double)(0); - } - if( s->nsequences>=1 ) - { - cnt = ae_minint(s->sequenceidx.ptr.p_int[s->nsequences]-s->sequenceidx.ptr.p_int[s->nsequences-1], nticks, _state); - offs = s->sequenceidx.ptr.p_int[s->nsequences]-cnt; - for(i=0; i<=cnt-1; i++) - { - noise->ptr.p_double[nticks-cnt+i] = s->sequencedata.ptr.p_double[offs+i]; - } - } - return; - } - - /* - * Fast exit: NTicks<=WindowWidth, just last window is analyzed - */ - if( nticks<=s->windowwidth ) - { - ssaanalyzelastwindow(s, &s->alongtrend, &s->alongnoise, &cnt, _state); - offs = s->windowwidth-nticks; - for(i=0; i<=nticks-1; i++) - { - trend->ptr.p_double[i] = s->alongtrend.ptr.p_double[offs+i]; - noise->ptr.p_double[i] = s->alongnoise.ptr.p_double[offs+i]; - } - return; - } - - /* - * Update basis. - * - * It will take care of basis validity flags. AppendLen=0 which means - * that we perform initial basis evaluation. - */ - ssa_updatebasis(s, 0, 0.0, _state); - - /* - * Perform analysis: - * * prepend max(NTicks-LastSequenceLength,0) zeros to the beginning - * of array - * * analyze the rest with AnalyzeSequence() which assumes that we - * already have basis - */ - ae_assert(s->sequenceidx.ptr.p_int[s->nsequences]-s->sequenceidx.ptr.p_int[s->nsequences-1]>=s->windowwidth, "SSAAnalyzeLast: integrity check failed / 23vd4", _state); - cntzeros = ae_maxint(nticks-(s->sequenceidx.ptr.p_int[s->nsequences]-s->sequenceidx.ptr.p_int[s->nsequences-1]), 0, _state); - for(i=0; i<=cntzeros-1; i++) - { - trend->ptr.p_double[i] = 0.0; - noise->ptr.p_double[i] = 0.0; - } - cnt = ae_minint(nticks, s->sequenceidx.ptr.p_int[s->nsequences]-s->sequenceidx.ptr.p_int[s->nsequences-1], _state); - ssa_analyzesequence(s, &s->sequencedata, s->sequenceidx.ptr.p_int[s->nsequences]-cnt, s->sequenceidx.ptr.p_int[s->nsequences], trend, noise, cntzeros, _state); -} - - -/************************************************************************* -This function: -* builds SSA basis using internally stored (entire) dataset -* returns reconstruction for the sequence being passed to this function - -If you want to analyze last sequence stored in the model, use -ssaanalyzelast(). - -Reconstruction phase involves generation of NTicks-WindowWidth sliding -windows, their decomposition using empirical orthogonal functions found by -SSA, followed by averaging of each data point across several overlapping -windows. Thus, every point in the output trend is reconstructed using up -to WindowWidth overlapping windows (WindowWidth windows exactly in the -inner points, just one window at the extremal points). - -PERFORMANCE: this function has O((NTicks-WindowWidth)*WindowWidth*NBasis) - running time. If you work in time-constrained setting and - have to analyze just a few last ticks, choosing NTicks equal - to WindowWidth+SmoothingLen, with SmoothingLen=1...WindowWidth - will result in good compromise between noise cancellation and - analysis speed. - -INPUT PARAMETERS: - S - SSA model - Data - array[NTicks], can be larger (only NTicks leading - elements will be used) - NTicks - number of ticks to analyze, Nticks>=1. - * special case of NTicks=1, "SSAAnalyzeSequence: NTicks<1", _state); - ae_assert(data->cnt>=nticks, "SSAAnalyzeSequence: Data is too short", _state); - ae_assert(isfinitevector(data, nticks, _state), "SSAAnalyzeSequence: Data contains infinities NANs", _state); - - /* - * Init - */ - ae_vector_set_length(trend, nticks, _state); - ae_vector_set_length(noise, nticks, _state); - - /* - * Is it degenerate case? - */ - if( !ssa_hassomethingtoanalyze(s, _state)||ntickswindowwidth ) - { - for(i=0; i<=nticks-1; i++) - { - trend->ptr.p_double[i] = (double)(0); - noise->ptr.p_double[i] = data->ptr.p_double[i]; - } - return; - } - - /* - * Update basis. - * - * It will take care of basis validity flags. AppendLen=0 which means - * that we perform initial basis evaluation. - */ - ssa_updatebasis(s, 0, 0.0, _state); - - /* - * Perform analysis - */ - ssa_analyzesequence(s, data, 0, nticks, trend, noise, 0, _state); -} - - -/************************************************************************* -This function builds SSA basis and performs forecasting for a specified -number of ticks, returning value of trend. - -Forecast is performed as follows: -* SSA trend extraction is applied to last WindowWidth elements of the - internally stored dataset; this step is basically a noise reduction. -* linear recurrence relation is applied to extracted trend - -This function has following running time: -* O(NBasis*WindowWidth) for trend extraction phase (always performed) -* O(WindowWidth*NTicks) for forecast phase - -NOTE: noise reduction is ALWAYS applied by this algorithm; if you want to - apply recurrence relation to raw unprocessed data, use another - function - ssaforecastsequence() which allows to turn on and off - noise reduction phase. - -NOTE: this algorithm performs prediction using only one - last - sliding - window. Predictions produced by such approach are smooth - continuations of the reconstructed trend line, but they can be - easily corrupted by noise. If you need noise-resistant prediction, - use ssaforecastavglast() function, which averages predictions built - using several sliding windows. - -INPUT PARAMETERS: - S - SSA model - NTicks - number of ticks to forecast, NTicks>=1 - -OUTPUT PARAMETERS: - Trend - array[NTicks], predicted trend line - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* last sequence is shorter than the WindowWidth (analysis can be done, - but we can not perform forecasting on the last sequence) -* window lentgh is 1 (impossible to use for forecasting) -* SSA analysis algorithm is configured to extract basis whose size is - equal to window length (impossible to use for forecasting; only basis - whose size is less than window length can be used). - -Calling this function in degenerate cases returns following result: -* NTicks copies of the last value is returned for non-empty task with - large enough dataset, but with overcomplete basis (window width=1 or - basis size is equal to window width) -* zero trend with length=NTicks is returned for empty task - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is ever constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaforecastlast(ssamodel* s, - ae_int_t nticks, - /* Real */ ae_vector* trend, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - ae_int_t winw; - - ae_vector_clear(trend); - - ae_assert(nticks>=1, "SSAForecast: NTicks<1", _state); - - /* - * Init - */ - winw = s->windowwidth; - ae_vector_set_length(trend, nticks, _state); - - /* - * Is it degenerate case? - */ - if( !ssa_hassomethingtoanalyze(s, _state) ) - { - for(i=0; i<=nticks-1; i++) - { - trend->ptr.p_double[i] = (double)(0); - } - return; - } - ae_assert(s->nsequences>0, "SSAForecastLast: integrity check failed", _state); - if( s->sequenceidx.ptr.p_int[s->nsequences]-s->sequenceidx.ptr.p_int[s->nsequences-1]ptr.p_double[i] = (double)(0); - } - return; - } - if( winw==1 ) - { - ae_assert(s->nsequences>0, "SSAForecast: integrity check failed / 2355", _state); - ae_assert(s->sequenceidx.ptr.p_int[s->nsequences]-s->sequenceidx.ptr.p_int[s->nsequences-1]>0, "SSAForecast: integrity check failed", _state); - for(i=0; i<=nticks-1; i++) - { - trend->ptr.p_double[i] = s->sequencedata.ptr.p_double[s->sequenceidx.ptr.p_int[s->nsequences]-1]; - } - return; - } - - /* - * Update basis and recurrent relation. - * - * It will take care of basis validity flags. AppendLen=0 which means - * that we perform initial basis evaluation. - */ - ssa_updatebasis(s, 0, 0.0, _state); - ae_assert(s->nbasis<=winw&&s->nbasis>0, "SSAForecast: integrity check failed / 4f5et", _state); - if( s->nbasis==winw ) - { - - /* - * Handle degenerate situation with basis whose size - * is equal to window length. - */ - ae_assert(s->nsequences>0, "SSAForecast: integrity check failed / 2355", _state); - ae_assert(s->sequenceidx.ptr.p_int[s->nsequences]-s->sequenceidx.ptr.p_int[s->nsequences-1]>0, "SSAForecast: integrity check failed", _state); - for(i=0; i<=nticks-1; i++) - { - trend->ptr.p_double[i] = s->sequencedata.ptr.p_double[s->sequenceidx.ptr.p_int[s->nsequences]-1]; - } - return; - } - - /* - * Apply recurrent formula for SSA forecasting: - * * first, perform smoothing of the last window - * * second, perform analysis phase - */ - ae_assert(s->nsequences>0, "SSAForecastLast: integrity check failed", _state); - ae_assert(s->sequenceidx.ptr.p_int[s->nsequences]-s->sequenceidx.ptr.p_int[s->nsequences-1]>=s->windowwidth, "SSAForecastLast: integrity check failed", _state); - rvectorsetlengthatleast(&s->tmp0, s->nbasis, _state); - rvectorsetlengthatleast(&s->fctrend, s->windowwidth, _state); - rmatrixgemv(s->nbasis, s->windowwidth, 1.0, &s->basist, 0, 0, 0, &s->sequencedata, s->sequenceidx.ptr.p_int[s->nsequences]-s->windowwidth, 0.0, &s->tmp0, 0, _state); - rmatrixgemv(s->windowwidth, s->nbasis, 1.0, &s->basis, 0, 0, 0, &s->tmp0, 0, 0.0, &s->fctrend, 0, _state); - rvectorsetlengthatleast(&s->tmp1, winw-1, _state); - for(i=1; i<=winw-1; i++) - { - s->tmp1.ptr.p_double[i-1] = s->fctrend.ptr.p_double[i]; - } - for(i=0; i<=nticks-1; i++) - { - v = s->forecasta.ptr.p_double[0]*s->tmp1.ptr.p_double[0]; - for(j=1; j<=winw-2; j++) - { - v = v+s->forecasta.ptr.p_double[j]*s->tmp1.ptr.p_double[j]; - s->tmp1.ptr.p_double[j-1] = s->tmp1.ptr.p_double[j]; - } - trend->ptr.p_double[i] = v; - s->tmp1.ptr.p_double[winw-2] = v; - } -} - - -/************************************************************************* -This function builds SSA basis and performs forecasting for a user- -specified sequence, returning value of trend. - -Forecasting is done in two stages: -* first, we extract trend from the WindowWidth last elements of the - sequence. This stage is optional, you can turn it off if you pass - data which are already processed with SSA. Of course, you can turn it - off even for raw data, but it is not recommended - noise suppression is - very important for correct prediction. -* then, we apply LRR for last WindowWidth-1 elements of the extracted - trend. - -This function has following running time: -* O(NBasis*WindowWidth) for trend extraction phase -* O(WindowWidth*NTicks) for forecast phase - -NOTE: this algorithm performs prediction using only one - last - sliding - window. Predictions produced by such approach are smooth - continuations of the reconstructed trend line, but they can be - easily corrupted by noise. If you need noise-resistant prediction, - use ssaforecastavgsequence() function, which averages predictions - built using several sliding windows. - -INPUT PARAMETERS: - S - SSA model - Data - array[NTicks], data to forecast - DataLen - number of ticks in the data, DataLen>=1 - ForecastLen - number of ticks to predict, ForecastLen>=1 - ApplySmoothing - whether to apply smoothing trend extraction or not; - if you do not know what to specify, pass True. - -OUTPUT PARAMETERS: - Trend - array[ForecastLen], forecasted trend - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* data sequence is shorter than the WindowWidth (analysis can be done, - but we can not perform forecasting on the last sequence) -* window lentgh is 1 (impossible to use for forecasting) -* SSA analysis algorithm is configured to extract basis whose size is - equal to window length (impossible to use for forecasting; only basis - whose size is less than window length can be used). - -Calling this function in degenerate cases returns following result: -* ForecastLen copies of the last value is returned for non-empty task with - large enough dataset, but with overcomplete basis (window width=1 or - basis size is equal to window width) -* zero trend with length=ForecastLen is returned for empty task - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is ever constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaforecastsequence(ssamodel* s, - /* Real */ ae_vector* data, - ae_int_t datalen, - ae_int_t forecastlen, - ae_bool applysmoothing, - /* Real */ ae_vector* trend, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - ae_int_t winw; - - ae_vector_clear(trend); - - ae_assert(datalen>=1, "SSAForecastSequence: DataLen<1", _state); - ae_assert(data->cnt>=datalen, "SSAForecastSequence: Data is too short", _state); - ae_assert(isfinitevector(data, datalen, _state), "SSAForecastSequence: Data contains infinities NANs", _state); - ae_assert(forecastlen>=1, "SSAForecastSequence: ForecastLen<1", _state); - - /* - * Init - */ - winw = s->windowwidth; - ae_vector_set_length(trend, forecastlen, _state); - - /* - * Is it degenerate case? - */ - if( !ssa_hassomethingtoanalyze(s, _state)||datalenptr.p_double[i] = (double)(0); - } - return; - } - if( winw==1 ) - { - for(i=0; i<=forecastlen-1; i++) - { - trend->ptr.p_double[i] = data->ptr.p_double[datalen-1]; - } - return; - } - - /* - * Update basis. - * - * It will take care of basis validity flags. AppendLen=0 which means - * that we perform initial basis evaluation. - */ - ssa_updatebasis(s, 0, 0.0, _state); - ae_assert(s->nbasis<=winw&&s->nbasis>0, "SSAForecast: integrity check failed / 4f5et", _state); - if( s->nbasis==winw ) - { - - /* - * Handle degenerate situation with basis whose size - * is equal to window length. - */ - for(i=0; i<=forecastlen-1; i++) - { - trend->ptr.p_double[i] = data->ptr.p_double[datalen-1]; - } - return; - } - - /* - * Perform trend extraction - */ - rvectorsetlengthatleast(&s->fctrend, s->windowwidth, _state); - if( applysmoothing ) - { - ae_assert(datalen>=winw, "SSAForecastSequence: integrity check failed", _state); - rvectorsetlengthatleast(&s->tmp0, s->nbasis, _state); - rmatrixgemv(s->nbasis, winw, 1.0, &s->basist, 0, 0, 0, data, datalen-winw, 0.0, &s->tmp0, 0, _state); - rmatrixgemv(winw, s->nbasis, 1.0, &s->basis, 0, 0, 0, &s->tmp0, 0, 0.0, &s->fctrend, 0, _state); - } - else - { - for(i=0; i<=winw-1; i++) - { - s->fctrend.ptr.p_double[i] = data->ptr.p_double[datalen+i-winw]; - } - } - - /* - * Apply recurrent formula for SSA forecasting - */ - rvectorsetlengthatleast(&s->tmp1, winw-1, _state); - for(i=1; i<=winw-1; i++) - { - s->tmp1.ptr.p_double[i-1] = s->fctrend.ptr.p_double[i]; - } - for(i=0; i<=forecastlen-1; i++) - { - v = s->forecasta.ptr.p_double[0]*s->tmp1.ptr.p_double[0]; - for(j=1; j<=winw-2; j++) - { - v = v+s->forecasta.ptr.p_double[j]*s->tmp1.ptr.p_double[j]; - s->tmp1.ptr.p_double[j-1] = s->tmp1.ptr.p_double[j]; - } - trend->ptr.p_double[i] = v; - s->tmp1.ptr.p_double[winw-2] = v; - } -} - - -/************************************************************************* -This function builds SSA basis and performs forecasting for a specified -number of ticks, returning value of trend. - -Forecast is performed as follows: -* SSA trend extraction is applied to last M sliding windows of the - internally stored dataset -* for each of M sliding windows, M predictions are built -* average value of M predictions is returned - -This function has following running time: -* O(NBasis*WindowWidth*M) for trend extraction phase (always performed) -* O(WindowWidth*NTicks*M) for forecast phase - -NOTE: noise reduction is ALWAYS applied by this algorithm; if you want to - apply recurrence relation to raw unprocessed data, use another - function - ssaforecastsequence() which allows to turn on and off - noise reduction phase. - -NOTE: combination of several predictions results in lesser sensitivity to - noise, but it may produce undesirable discontinuities between last - point of the trend and first point of the prediction. The reason is - that last point of the trend is usually corrupted by noise, but - average value of several predictions is less sensitive to noise, - thus discontinuity appears. It is not a bug. - -INPUT PARAMETERS: - S - SSA model - M - number of sliding windows to combine, M>=1. If - your dataset has less than M sliding windows, this - parameter will be silently reduced. - NTicks - number of ticks to forecast, NTicks>=1 - -OUTPUT PARAMETERS: - Trend - array[NTicks], predicted trend line - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* last sequence is shorter than the WindowWidth (analysis can be done, - but we can not perform forecasting on the last sequence) -* window lentgh is 1 (impossible to use for forecasting) -* SSA analysis algorithm is configured to extract basis whose size is - equal to window length (impossible to use for forecasting; only basis - whose size is less than window length can be used). - -Calling this function in degenerate cases returns following result: -* NTicks copies of the last value is returned for non-empty task with - large enough dataset, but with overcomplete basis (window width=1 or - basis size is equal to window width) -* zero trend with length=NTicks is returned for empty task - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is ever constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaforecastavglast(ssamodel* s, - ae_int_t m, - ae_int_t nticks, - /* Real */ ae_vector* trend, - ae_state *_state) -{ - ae_int_t i; - ae_int_t winw; - - ae_vector_clear(trend); - - ae_assert(nticks>=1, "SSAForecastAvgLast: NTicks<1", _state); - ae_assert(m>=1, "SSAForecastAvgLast: M<1", _state); - - /* - * Init - */ - winw = s->windowwidth; - ae_vector_set_length(trend, nticks, _state); - - /* - * Is it degenerate case? - */ - if( !ssa_hassomethingtoanalyze(s, _state) ) - { - for(i=0; i<=nticks-1; i++) - { - trend->ptr.p_double[i] = (double)(0); - } - return; - } - ae_assert(s->nsequences>0, "SSAForecastAvgLast: integrity check failed", _state); - if( s->sequenceidx.ptr.p_int[s->nsequences]-s->sequenceidx.ptr.p_int[s->nsequences-1]ptr.p_double[i] = (double)(0); - } - return; - } - if( winw==1 ) - { - ae_assert(s->nsequences>0, "SSAForecastAvgLast: integrity check failed / 2355", _state); - ae_assert(s->sequenceidx.ptr.p_int[s->nsequences]-s->sequenceidx.ptr.p_int[s->nsequences-1]>0, "SSAForecastAvgLast: integrity check failed", _state); - for(i=0; i<=nticks-1; i++) - { - trend->ptr.p_double[i] = s->sequencedata.ptr.p_double[s->sequenceidx.ptr.p_int[s->nsequences]-1]; - } - return; - } - - /* - * Update basis and recurrent relation. - * - * It will take care of basis validity flags. AppendLen=0 which means - * that we perform initial basis evaluation. - */ - ssa_updatebasis(s, 0, 0.0, _state); - ae_assert(s->nbasis<=winw&&s->nbasis>0, "SSAForecastAvgLast: integrity check failed / 4f5et", _state); - if( s->nbasis==winw ) - { - - /* - * Handle degenerate situation with basis whose size - * is equal to window length. - */ - ae_assert(s->nsequences>0, "SSAForecastAvgLast: integrity check failed / 2355", _state); - ae_assert(s->sequenceidx.ptr.p_int[s->nsequences]-s->sequenceidx.ptr.p_int[s->nsequences-1]>0, "SSAForecastAvgLast: integrity check failed", _state); - for(i=0; i<=nticks-1; i++) - { - trend->ptr.p_double[i] = s->sequencedata.ptr.p_double[s->sequenceidx.ptr.p_int[s->nsequences]-1]; - } - return; - } - - /* - * Decrease M if we have less than M sliding windows. - * Forecast. - */ - m = ae_minint(m, s->sequenceidx.ptr.p_int[s->nsequences]-s->sequenceidx.ptr.p_int[s->nsequences-1]-winw+1, _state); - ae_assert(m>=1, "SSAForecastAvgLast: integrity check failed", _state); - ssa_forecastavgsequence(s, &s->sequencedata, s->sequenceidx.ptr.p_int[s->nsequences-1], s->sequenceidx.ptr.p_int[s->nsequences], m, nticks, ae_true, trend, 0, _state); -} - - -/************************************************************************* -This function builds SSA basis and performs forecasting for a user- -specified sequence, returning value of trend. - -Forecasting is done in two stages: -* first, we extract trend from M last sliding windows of the sequence. - This stage is optional, you can turn it off if you pass data which - are already processed with SSA. Of course, you can turn it off even - for raw data, but it is not recommended - noise suppression is very - important for correct prediction. -* then, we apply LRR independently for M sliding windows -* average of M predictions is returned - -This function has following running time: -* O(NBasis*WindowWidth*M) for trend extraction phase -* O(WindowWidth*NTicks*M) for forecast phase - -NOTE: combination of several predictions results in lesser sensitivity to - noise, but it may produce undesirable discontinuities between last - point of the trend and first point of the prediction. The reason is - that last point of the trend is usually corrupted by noise, but - average value of several predictions is less sensitive to noise, - thus discontinuity appears. It is not a bug. - -INPUT PARAMETERS: - S - SSA model - Data - array[NTicks], data to forecast - DataLen - number of ticks in the data, DataLen>=1 - M - number of sliding windows to combine, M>=1. If - your dataset has less than M sliding windows, this - parameter will be silently reduced. - ForecastLen - number of ticks to predict, ForecastLen>=1 - ApplySmoothing - whether to apply smoothing trend extraction or not. - if you do not know what to specify, pass true. - -OUTPUT PARAMETERS: - Trend - array[ForecastLen], forecasted trend - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* data sequence is shorter than the WindowWidth (analysis can be done, - but we can not perform forecasting on the last sequence) -* window lentgh is 1 (impossible to use for forecasting) -* SSA analysis algorithm is configured to extract basis whose size is - equal to window length (impossible to use for forecasting; only basis - whose size is less than window length can be used). - -Calling this function in degenerate cases returns following result: -* ForecastLen copies of the last value is returned for non-empty task with - large enough dataset, but with overcomplete basis (window width=1 or - basis size is equal to window width) -* zero trend with length=ForecastLen is returned for empty task - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is ever constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaforecastavgsequence(ssamodel* s, - /* Real */ ae_vector* data, - ae_int_t datalen, - ae_int_t m, - ae_int_t forecastlen, - ae_bool applysmoothing, - /* Real */ ae_vector* trend, - ae_state *_state) -{ - ae_int_t i; - ae_int_t winw; - - ae_vector_clear(trend); - - ae_assert(datalen>=1, "SSAForecastAvgSequence: DataLen<1", _state); - ae_assert(m>=1, "SSAForecastAvgSequence: M<1", _state); - ae_assert(data->cnt>=datalen, "SSAForecastAvgSequence: Data is too short", _state); - ae_assert(isfinitevector(data, datalen, _state), "SSAForecastAvgSequence: Data contains infinities NANs", _state); - ae_assert(forecastlen>=1, "SSAForecastAvgSequence: ForecastLen<1", _state); - - /* - * Init - */ - winw = s->windowwidth; - ae_vector_set_length(trend, forecastlen, _state); - - /* - * Is it degenerate case? - */ - if( !ssa_hassomethingtoanalyze(s, _state)||datalenptr.p_double[i] = (double)(0); - } - return; - } - if( winw==1 ) - { - for(i=0; i<=forecastlen-1; i++) - { - trend->ptr.p_double[i] = data->ptr.p_double[datalen-1]; - } - return; - } - - /* - * Update basis. - * - * It will take care of basis validity flags. AppendLen=0 which means - * that we perform initial basis evaluation. - */ - ssa_updatebasis(s, 0, 0.0, _state); - ae_assert(s->nbasis<=winw&&s->nbasis>0, "SSAForecast: integrity check failed / 4f5et", _state); - if( s->nbasis==winw ) - { - - /* - * Handle degenerate situation with basis whose size - * is equal to window length. - */ - for(i=0; i<=forecastlen-1; i++) - { - trend->ptr.p_double[i] = data->ptr.p_double[datalen-1]; - } - return; - } - - /* - * Decrease M if we have less than M sliding windows. - * Forecast. - */ - m = ae_minint(m, datalen-winw+1, _state); - ae_assert(m>=1, "SSAForecastAvgLast: integrity check failed", _state); - ssa_forecastavgsequence(s, data, 0, datalen, m, forecastlen, applysmoothing, trend, 0, _state); -} - - -/************************************************************************* -This function evaluates current model and tells whether we have some data -which can be analyzed by current algorithm, or not. - -No analysis can be done in the following degenerate cases: -* dataset is empty -* all sequences are shorter than the window length -* no algorithm is specified - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -static ae_bool ssa_hassomethingtoanalyze(ssamodel* s, ae_state *_state) -{ - ae_int_t i; - ae_bool allsmaller; - ae_bool isdegenerate; - ae_bool result; - - - isdegenerate = ae_false; - isdegenerate = isdegenerate||s->algotype==0; - isdegenerate = isdegenerate||s->nsequences==0; - allsmaller = ae_true; - for(i=0; i<=s->nsequences-1; i++) - { - allsmaller = allsmaller&&s->sequenceidx.ptr.p_int[i+1]-s->sequenceidx.ptr.p_int[i]windowwidth; - } - isdegenerate = isdegenerate||allsmaller; - result = !isdegenerate; - return result; -} - - -/************************************************************************* -This function checks whether I-th sequence is big enough for analysis or not. - -I=-1 is used to denote last sequence (for NSequences=0) - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -static ae_bool ssa_issequencebigenough(ssamodel* s, - ae_int_t i, - ae_state *_state) -{ - ae_bool result; - - - ae_assert(i>=-1&&insequences, "Assertion failed", _state); - result = ae_false; - if( s->nsequences==0 ) - { - return result; - } - if( i<0 ) - { - i = s->nsequences-1; - } - result = s->sequenceidx.ptr.p_int[i+1]-s->sequenceidx.ptr.p_int[i]>=s->windowwidth; - return result; -} - - -/************************************************************************* -This function performs basis update. Either full update (recalculated from -the very beginning) or partial update (handles append to the end of the -dataset). - -With AppendLen=0 this function behaves as follows: -* if AreBasisAndSolverValid=False, then solver object is created from - scratch, initial calculations are performed according to specific SSA - algorithm being chosen. Basis/Solver validity flag is set to True, then - we immediately return. -* if AreBasisAndSolverValid=True, then nothing is done - we immediately - return. - -With AppendLen>0 this function behaves as follows: -* if AreBasisAndSolverValid=False, then exception is generated; you can - append points only to fully constructed basis. Call this function with - zero AppendLen BEFORE append, then perform append, then call it one more - time with non-zero AppendLen. -* if AreBasisAndSolverValid=True, then basis is incrementally updated. It - also updates recurrence relation used for prediction. It is expected that - either AppendLen=1, or AppendLen=length(last_sequence). Basis update is - performed with probability UpdateIts (larger-than-one values mean that - some amount of iterations is always performed). - - -In any case, after calling this function we either: -* have an exception -* have completely valid basis - -IMPORTANT: this function expects that we do NOT call it for degenerate tasks - (no data). So, call it after check with HasSomethingToAnalyze() - returned True. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -static void ssa_updatebasis(ssamodel* s, - ae_int_t appendlen, - double updateits, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t srcoffs; - ae_int_t dstoffs; - ae_int_t winw; - ae_int_t windowstotal; - ae_int_t requesttype; - ae_int_t requestsize; - double v; - ae_bool degeneraterecurrence; - double nu2; - ae_int_t subspaceits; - ae_bool needevd; - - - winw = s->windowwidth; - - /* - * Critical checks - */ - ae_assert(appendlen>=0, "SSA: incorrect parameters passed to UpdateBasis(), integrity check failed", _state); - ae_assert(!(!s->arebasisandsolvervalid&&appendlen!=0), "SSA: incorrect parameters passed to UpdateBasis(), integrity check failed", _state); - ae_assert(!(appendlen==0&&ae_fp_greater(updateits,0.0)), "SSA: incorrect parameters passed to UpdateBasis(), integrity check failed", _state); - - /* - * Everything is OK, nothing to do - */ - if( s->arebasisandsolvervalid&&appendlen==0 ) - { - return; - } - - /* - * Seed RNG with fixed or random seed. - * - * RNG used when pseudorandomly deciding whether - * to re-evaluate basis or not. Sandom seed is - * important when we have several simultaneously - * calculated SSA models - we do not want them - * to be re-evaluated in same moments). - */ - if( !s->arebasisandsolvervalid ) - { - if( s->rngseed>0 ) - { - hqrndseed(s->rngseed, s->rngseed+235, &s->rs, _state); - } - else - { - hqrndrandomize(&s->rs, _state); - } - } - - /* - * Compute XXT for algorithms which need it - */ - if( !s->arebasisandsolvervalid ) - { - ae_assert(appendlen==0, "SSA: integrity check failed / 34cx6", _state); - if( s->algotype==2 ) - { - - /* - * Compute X*X^T for direct algorithm. - * Quite straightforward, no subtle optimizations. - */ - rmatrixsetlengthatleast(&s->xxt, winw, winw, _state); - windowstotal = 0; - for(i=0; i<=s->nsequences-1; i++) - { - windowstotal = windowstotal+ae_maxint(s->sequenceidx.ptr.p_int[i+1]-s->sequenceidx.ptr.p_int[i]-winw+1, 0, _state); - } - ae_assert(windowstotal>0, "SSA: integrity check in UpdateBasis() failed / 76t34", _state); - for(i=0; i<=winw-1; i++) - { - for(j=0; j<=winw-1; j++) - { - s->xxt.ptr.pp_double[i][j] = (double)(0); - } - } - ssa_updatexxtprepare(s, windowstotal, winw, s->memorylimit, _state); - for(i=0; i<=s->nsequences-1; i++) - { - for(j=0; j<=ae_maxint(s->sequenceidx.ptr.p_int[i+1]-s->sequenceidx.ptr.p_int[i]-winw+1, 0, _state)-1; j++) - { - ssa_updatexxtsend(s, &s->sequencedata, s->sequenceidx.ptr.p_int[i]+j, &s->xxt, _state); - } - } - ssa_updatexxtfinalize(s, &s->xxt, _state); - } - if( s->algotype==3 ) - { - - /* - * Compute X*X^T for real-time algorithm: - * * prepare queue of windows to merge into XXT - * * shuffle queue in order to avoid time-related biases in algorithm - * * dequeue first chunk - */ - rmatrixsetlengthatleast(&s->xxt, winw, winw, _state); - windowstotal = 0; - for(i=0; i<=s->nsequences-1; i++) - { - windowstotal = windowstotal+ae_maxint(s->sequenceidx.ptr.p_int[i+1]-s->sequenceidx.ptr.p_int[i]-winw+1, 0, _state); - } - ae_assert(windowstotal>0, "SSA: integrity check in UpdateBasis() failed / 76t34", _state); - ivectorsetlengthatleast(&s->rtqueue, windowstotal, _state); - dstoffs = 0; - for(i=0; i<=s->nsequences-1; i++) - { - for(j=0; j<=ae_maxint(s->sequenceidx.ptr.p_int[i+1]-s->sequenceidx.ptr.p_int[i]-winw+1, 0, _state)-1; j++) - { - srcoffs = s->sequenceidx.ptr.p_int[i]+j; - s->rtqueue.ptr.p_int[dstoffs] = srcoffs; - inc(&dstoffs, _state); - } - } - ae_assert(dstoffs==windowstotal, "SSA: integrity check in UpdateBasis() failed / fh45f", _state); - if( s->rtpowerup>1 ) - { - - /* - * Shuffle queue, it helps to avoid time-related bias in algorithm - */ - for(i=0; i<=windowstotal-1; i++) - { - j = i+hqrnduniformi(&s->rs, windowstotal-i, _state); - swapelementsi(&s->rtqueue, i, j, _state); - } - } - s->rtqueuecnt = windowstotal; - s->rtqueuechunk = 1; - s->rtqueuechunk = ae_maxint(s->rtqueuechunk, s->rtqueuecnt/s->rtpowerup, _state); - s->rtqueuechunk = ae_maxint(s->rtqueuechunk, 2*s->topk, _state); - ssa_realtimedequeue(s, 0.0, ae_minint(s->rtqueuechunk, s->rtqueuecnt, _state), _state); - } - } - - /* - * Handle possible updates for XXT: - * * check that append involves either last point of last sequence, - * or entire last sequence - * * if last sequence is shorter than window width, perform quick exit - - * we have nothing to update - no windows to insert into XXT - * * update XXT - */ - if( appendlen>0 ) - { - ae_assert(s->arebasisandsolvervalid, "SSA: integrity check failed / 5gvz3", _state); - ae_assert(s->nsequences>=1, "SSA: integrity check failed / 658ev", _state); - ae_assert(appendlen==1||appendlen==s->sequenceidx.ptr.p_int[s->nsequences]-s->sequenceidx.ptr.p_int[s->nsequences-1]-winw+1, "SSA: integrity check failed / sd3g7", _state); - if( s->sequenceidx.ptr.p_int[s->nsequences]-s->sequenceidx.ptr.p_int[s->nsequences-1]algotype==2||s->algotype==3 ) - { - if( appendlen>1 ) - { - - /* - * Long append, use GEMM for updates - */ - ssa_updatexxtprepare(s, appendlen, winw, s->memorylimit, _state); - for(j=0; j<=ae_maxint(s->sequenceidx.ptr.p_int[s->nsequences]-s->sequenceidx.ptr.p_int[s->nsequences-1]-winw+1, 0, _state)-1; j++) - { - ssa_updatexxtsend(s, &s->sequencedata, s->sequenceidx.ptr.p_int[s->nsequences-1]+j, &s->xxt, _state); - } - ssa_updatexxtfinalize(s, &s->xxt, _state); - } - else - { - - /* - * Just one element is added, use rank-1 update - */ - rmatrixger(winw, winw, &s->xxt, 0, 0, 1.0, &s->sequencedata, s->sequenceidx.ptr.p_int[s->nsequences]-winw, &s->sequencedata, s->sequenceidx.ptr.p_int[s->nsequences]-winw, _state); - } - } - } - - /* - * Now, perform basis calculation - either full recalculation (AppendLen=0) - * or quick update (AppendLen>0). - */ - if( s->algotype==1 ) - { - - /* - * Precomputed basis - */ - if( winw!=s->precomputedwidth ) - { - - /* - * Window width has changed, reset basis to zeros - */ - s->nbasis = 1; - rmatrixsetlengthatleast(&s->basis, winw, 1, _state); - rvectorsetlengthatleast(&s->sv, 1, _state); - for(i=0; i<=winw-1; i++) - { - s->basis.ptr.pp_double[i][0] = 0.0; - } - s->sv.ptr.p_double[0] = 0.0; - } - else - { - - /* - * OK, use precomputed basis - */ - s->nbasis = s->precomputednbasis; - rmatrixsetlengthatleast(&s->basis, winw, s->nbasis, _state); - rvectorsetlengthatleast(&s->sv, s->nbasis, _state); - for(j=0; j<=s->nbasis-1; j++) - { - s->sv.ptr.p_double[j] = 0.0; - for(i=0; i<=winw-1; i++) - { - s->basis.ptr.pp_double[i][j] = s->precomputedbasis.ptr.pp_double[i][j]; - } - } - } - rmatrixsetlengthatleast(&s->basist, s->nbasis, winw, _state); - rmatrixtranspose(winw, s->nbasis, &s->basis, 0, 0, &s->basist, 0, 0, _state); - } - else - { - if( s->algotype==2 ) - { - - /* - * Direct top-K algorithm - * - * Calculate eigenvectors with SMatrixEVD(), reorder by descending - * of magnitudes. - * - * Update is performed for invalid basis or for non-zero UpdateIts. - */ - needevd = !s->arebasisandsolvervalid; - needevd = needevd||ae_fp_greater_eq(updateits,(double)(1)); - needevd = needevd||ae_fp_less(hqrnduniformr(&s->rs, _state),updateits-ae_ifloor(updateits, _state)); - if( needevd ) - { - inc(&s->dbgcntevd, _state); - s->nbasis = ae_minint(winw, s->topk, _state); - if( !smatrixevd(&s->xxt, winw, 1, ae_true, &s->sv, &s->basis, _state) ) - { - ae_assert(ae_false, "SSA: SMatrixEVD failed", _state); - } - for(i=0; i<=winw-1; i++) - { - k = winw-1-i; - if( i>=k ) - { - break; - } - v = s->sv.ptr.p_double[i]; - s->sv.ptr.p_double[i] = s->sv.ptr.p_double[k]; - s->sv.ptr.p_double[k] = v; - for(j=0; j<=winw-1; j++) - { - v = s->basis.ptr.pp_double[j][i]; - s->basis.ptr.pp_double[j][i] = s->basis.ptr.pp_double[j][k]; - s->basis.ptr.pp_double[j][k] = v; - } - } - for(i=0; i<=s->nbasis-1; i++) - { - s->sv.ptr.p_double[i] = ae_sqrt(ae_maxreal(s->sv.ptr.p_double[i], 0.0, _state), _state); - } - rmatrixsetlengthatleast(&s->basist, s->nbasis, winw, _state); - rmatrixtranspose(winw, s->nbasis, &s->basis, 0, 0, &s->basist, 0, 0, _state); - } - } - else - { - if( s->algotype==3 ) - { - - /* - * Real-time top-K. - * - * Determine actual number of basis components, prepare subspace - * solver (either create from scratch or reuse). - * - * Update is always performed for invalid basis; for a valid basis - * it is performed with probability UpdateIts. - */ - if( s->rtpowerup==1 ) - { - subspaceits = s->defaultsubspaceits; - } - else - { - subspaceits = 3; - } - if( appendlen>0 ) - { - ae_assert(s->arebasisandsolvervalid, "SSA: integrity check in UpdateBasis() failed / srg6f", _state); - ae_assert(ae_fp_greater_eq(updateits,(double)(0)), "SSA: integrity check in UpdateBasis() failed / srg4f", _state); - subspaceits = ae_ifloor(updateits, _state); - if( ae_fp_less(hqrnduniformr(&s->rs, _state),updateits-ae_ifloor(updateits, _state)) ) - { - inc(&subspaceits, _state); - } - ae_assert(subspaceits>=0, "SSA: integrity check in UpdateBasis() failed / srg9f", _state); - } - - /* - * Dequeue pending dataset and merge it into XXT. - * - * Dequeuing is done only for appends, and only when we have - * non-empty queue. - */ - if( appendlen>0&&s->rtqueuecnt>0 ) - { - ssa_realtimedequeue(s, 1.0, ae_minint(s->rtqueuechunk, s->rtqueuecnt, _state), _state); - } - - /* - * Now, proceed to solver - */ - if( subspaceits>0 ) - { - if( appendlen==0 ) - { - s->nbasis = ae_minint(winw, s->topk, _state); - eigsubspacecreatebuf(winw, s->nbasis, &s->solver, _state); - } - else - { - eigsubspacesetwarmstart(&s->solver, ae_true, _state); - } - eigsubspacesetcond(&s->solver, 0.0, subspaceits, _state); - - /* - * Perform initial basis estimation - */ - inc(&s->dbgcntevd, _state); - eigsubspaceoocstart(&s->solver, 0, _state); - while(eigsubspaceooccontinue(&s->solver, _state)) - { - eigsubspaceoocgetrequestinfo(&s->solver, &requesttype, &requestsize, _state); - ae_assert(requesttype==0, "SSA: integrity check in UpdateBasis() failed / 346372", _state); - rmatrixgemm(winw, requestsize, winw, 1.0, &s->xxt, 0, 0, 0, &s->solver.x, 0, 0, 0, 0.0, &s->solver.ax, 0, 0, _state); - } - eigsubspaceoocstop(&s->solver, &s->sv, &s->basis, &s->solverrep, _state); - for(i=0; i<=s->nbasis-1; i++) - { - s->sv.ptr.p_double[i] = ae_sqrt(ae_maxreal(s->sv.ptr.p_double[i], 0.0, _state), _state); - } - rmatrixsetlengthatleast(&s->basist, s->nbasis, winw, _state); - rmatrixtranspose(winw, s->nbasis, &s->basis, 0, 0, &s->basist, 0, 0, _state); - } - } - else - { - ae_assert(ae_false, "SSA: integrity check in UpdateBasis() failed / dfgs34", _state); - } - } - } - - /* - * Update recurrent relation - */ - rvectorsetlengthatleast(&s->forecasta, ae_maxint(winw-1, 1, _state), _state); - degeneraterecurrence = ae_false; - if( winw>1 ) - { - - /* - * Non-degenerate case - */ - rvectorsetlengthatleast(&s->tmp0, s->nbasis, _state); - nu2 = 0.0; - for(i=0; i<=s->nbasis-1; i++) - { - v = s->basist.ptr.pp_double[i][winw-1]; - s->tmp0.ptr.p_double[i] = v; - nu2 = nu2+v*v; - } - if( ae_fp_less(nu2,1-1000*ae_machineepsilon) ) - { - rmatrixgemv(winw-1, s->nbasis, 1/(1-nu2), &s->basist, 0, 0, 1, &s->tmp0, 0, 0.0, &s->forecasta, 0, _state); - } - else - { - degeneraterecurrence = ae_true; - } - } - else - { - degeneraterecurrence = ae_true; - } - if( degeneraterecurrence ) - { - for(i=0; i<=ae_maxint(winw-1, 1, _state)-1; i++) - { - s->forecasta.ptr.p_double[i] = 0.0; - } - s->forecasta.ptr.p_double[ae_maxint(winw-1, 1, _state)-1] = 1.0; - } - - /* - * Set validity flag - */ - s->arebasisandsolvervalid = ae_true; -} - - -/************************************************************************* -This function performs analysis using current basis. It assumes and checks -that validity flag AreBasisAndSolverValid is set. - -INPUT PARAMETERS: - S - model - Data - array which holds data in elements [I0,I1): - * right bound is not included. - * I1-I0>=WindowWidth (assertion is performed). - Trend - preallocated output array, large enough - Noise - preallocated output array, large enough - Offs - offset in Trend/Noise where result is stored; - I1-I0 elements are written starting at offset - Offs. - -OUTPUT PARAMETERS: - Trend, Noise - processing results - - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -static void ssa_analyzesequence(ssamodel* s, - /* Real */ ae_vector* data, - ae_int_t i0, - ae_int_t i1, - /* Real */ ae_vector* trend, - /* Real */ ae_vector* noise, - ae_int_t offs, - ae_state *_state) -{ - ae_int_t winw; - ae_int_t nwindows; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t cnt; - ae_int_t batchstart; - ae_int_t batchlimit; - ae_int_t batchsize; - - - ae_assert(s->arebasisandsolvervalid, "AnalyzeSequence: integrity check failed / d84sz0", _state); - ae_assert(i1-i0>=s->windowwidth, "AnalyzeSequence: integrity check failed / d84sz1", _state); - ae_assert(s->nbasis>=1, "AnalyzeSequence: integrity check failed / d84sz2", _state); - nwindows = i1-i0-s->windowwidth+1; - winw = s->windowwidth; - batchlimit = ae_maxint(nwindows, 1, _state); - if( s->memorylimit>0 ) - { - batchlimit = ae_minint(batchlimit, ae_maxint(s->memorylimit/winw, 4*winw, _state), _state); - } - - /* - * Zero-initialize trend and counts - */ - cnt = i1-i0; - ivectorsetlengthatleast(&s->aseqcounts, cnt, _state); - for(i=0; i<=cnt-1; i++) - { - s->aseqcounts.ptr.p_int[i] = 0; - trend->ptr.p_double[offs+i] = 0.0; - } - - /* - * Reset temporaries if algorithm settings changed since last round - */ - if( s->aseqtrajectory.cols!=winw ) - { - ae_matrix_set_length(&s->aseqtrajectory, 0, 0, _state); - } - if( s->aseqtbproduct.cols!=s->nbasis ) - { - ae_matrix_set_length(&s->aseqtbproduct, 0, 0, _state); - } - - /* - * Perform batch processing - */ - rmatrixsetlengthatleast(&s->aseqtrajectory, batchlimit, winw, _state); - rmatrixsetlengthatleast(&s->aseqtbproduct, batchlimit, s->nbasis, _state); - batchsize = 0; - batchstart = offs; - for(i=0; i<=nwindows-1; i++) - { - - /* - * Enqueue next row of trajectory matrix - */ - if( batchsize==0 ) - { - batchstart = i; - } - for(j=0; j<=winw-1; j++) - { - s->aseqtrajectory.ptr.pp_double[batchsize][j] = data->ptr.p_double[i0+i+j]; - } - inc(&batchsize, _state); - - /* - * Process batch - */ - if( batchsize==batchlimit||i==nwindows-1 ) - { - - /* - * Project onto basis - */ - rmatrixgemm(batchsize, s->nbasis, winw, 1.0, &s->aseqtrajectory, 0, 0, 0, &s->basist, 0, 0, 1, 0.0, &s->aseqtbproduct, 0, 0, _state); - rmatrixgemm(batchsize, winw, s->nbasis, 1.0, &s->aseqtbproduct, 0, 0, 0, &s->basist, 0, 0, 0, 0.0, &s->aseqtrajectory, 0, 0, _state); - - /* - * Hankelize - */ - for(k=0; k<=batchsize-1; k++) - { - for(j=0; j<=winw-1; j++) - { - trend->ptr.p_double[offs+batchstart+k+j] = trend->ptr.p_double[offs+batchstart+k+j]+s->aseqtrajectory.ptr.pp_double[k][j]; - s->aseqcounts.ptr.p_int[batchstart+k+j] = s->aseqcounts.ptr.p_int[batchstart+k+j]+1; - } - } - - /* - * Reset batch size - */ - batchsize = 0; - } - } - for(i=0; i<=cnt-1; i++) - { - trend->ptr.p_double[offs+i] = trend->ptr.p_double[offs+i]/s->aseqcounts.ptr.p_int[i]; - } - - /* - * Output noise - */ - for(i=0; i<=cnt-1; i++) - { - noise->ptr.p_double[offs+i] = data->ptr.p_double[i0+i]-trend->ptr.p_double[offs+i]; - } -} - - -/************************************************************************* -This function performs averaged forecasting. It assumes that basis is -already built, everything is valid and checked. See comments on similar -public functions to find out more about averaged predictions. - -INPUT PARAMETERS: - S - model - Data - array which holds data in elements [I0,I1): - * right bound is not included. - * I1-I0>=WindowWidth (assertion is performed). - M - number of sliding windows to combine, M>=1. If - your dataset has less than M sliding windows, this - parameter will be silently reduced. - ForecastLen - number of ticks to predict, ForecastLen>=1 - Trend - preallocated output array, large enough - Offs - offset in Trend where result is stored; - I1-I0 elements are written starting at offset - Offs. - -OUTPUT PARAMETERS: - Trend - array[ForecastLen], forecasted trend - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -static void ssa_forecastavgsequence(ssamodel* s, - /* Real */ ae_vector* data, - ae_int_t i0, - ae_int_t i1, - ae_int_t m, - ae_int_t forecastlen, - ae_bool smooth, - /* Real */ ae_vector* trend, - ae_int_t offs, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t winw; - - - ae_assert(s->arebasisandsolvervalid, "ForecastAvgSequence: integrity check failed / d84sz0", _state); - ae_assert(i1-i0-s->windowwidth+1>=m, "ForecastAvgSequence: integrity check failed / d84sz1", _state); - ae_assert(s->nbasis>=1, "ForecastAvgSequence: integrity check failed / d84sz2", _state); - ae_assert(s->windowwidth>=2, "ForecastAvgSequence: integrity check failed / 5tgdg5", _state); - ae_assert(s->windowwidth>s->nbasis, "ForecastAvgSequence: integrity check failed / d5g56w", _state); - winw = s->windowwidth; - - /* - * Prepare M synchronized predictions for the last known tick - * (last one is an actual value of the trend, previous M-1 predictions - * are predictions from differently positioned sliding windows). - */ - rmatrixsetlengthatleast(&s->fctrendm, m, winw, _state); - rvectorsetlengthatleast(&s->tmp0, ae_maxint(m, s->nbasis, _state), _state); - rvectorsetlengthatleast(&s->tmp1, winw, _state); - for(k=0; k<=m-1; k++) - { - - /* - * Perform prediction for rows [0,K-1] - */ - rmatrixgemv(k, winw-1, 1.0, &s->fctrendm, 0, 1, 0, &s->forecasta, 0, 0.0, &s->tmp0, 0, _state); - for(i=0; i<=k-1; i++) - { - for(j=1; j<=winw-1; j++) - { - s->fctrendm.ptr.pp_double[i][j-1] = s->fctrendm.ptr.pp_double[i][j]; - } - s->fctrendm.ptr.pp_double[i][winw-1] = s->tmp0.ptr.p_double[i]; - } - - /* - * Perform trend extraction for row K, add it to dataset - */ - if( smooth ) - { - rmatrixgemv(s->nbasis, winw, 1.0, &s->basist, 0, 0, 0, data, i1-winw-(m-1-k), 0.0, &s->tmp0, 0, _state); - rmatrixgemv(s->windowwidth, s->nbasis, 1.0, &s->basis, 0, 0, 0, &s->tmp0, 0, 0.0, &s->tmp1, 0, _state); - for(j=0; j<=winw-1; j++) - { - s->fctrendm.ptr.pp_double[k][j] = s->tmp1.ptr.p_double[j]; - } - } - else - { - for(j=0; j<=winw-1; j++) - { - s->fctrendm.ptr.pp_double[k][j] = data->ptr.p_double[i1-winw-(m-1-k)+j]; - } - } - } - - /* - * Now we have M synchronized predictions of the sequence state at the last - * know moment (last "prediction" is just a copy of the trend). Let's start - * batch prediction! - */ - for(k=0; k<=forecastlen-1; k++) - { - rmatrixgemv(m, winw-1, 1.0, &s->fctrendm, 0, 1, 0, &s->forecasta, 0, 0.0, &s->tmp0, 0, _state); - trend->ptr.p_double[offs+k] = 0.0; - for(i=0; i<=m-1; i++) - { - for(j=1; j<=winw-1; j++) - { - s->fctrendm.ptr.pp_double[i][j-1] = s->fctrendm.ptr.pp_double[i][j]; - } - s->fctrendm.ptr.pp_double[i][winw-1] = s->tmp0.ptr.p_double[i]; - trend->ptr.p_double[offs+k] = trend->ptr.p_double[offs+k]+s->tmp0.ptr.p_double[i]; - } - trend->ptr.p_double[offs+k] = trend->ptr.p_double[offs+k]/m; - } -} - - -/************************************************************************* -This function extracts updates from real-time queue and applies them to -the S.XXT matrix. XXT is premultiplied by Beta, which can be 0.0 for -initial creation, 1.0 for subsequent updates, or even within (0,1) for some -kind of updates with decay. - -INPUT PARAMETERS: - S - model - Beta - >=0, coefficient to premultiply XXT - Cnt - 00, "SSA: RealTimeDequeue() integrity check failed / 43tdv", _state); - ae_assert(ae_isfinite(beta, _state)&&ae_fp_greater_eq(beta,(double)(0)), "SSA: RealTimeDequeue() integrity check failed / 5gdg6", _state); - ae_assert(cnt<=s->rtqueuecnt, "SSA: RealTimeDequeue() integrity check failed / 547yh", _state); - ae_assert(s->xxt.cols>=s->windowwidth, "SSA: RealTimeDequeue() integrity check failed / 54bf4", _state); - ae_assert(s->xxt.rows>=s->windowwidth, "SSA: RealTimeDequeue() integrity check failed / 9gdfn", _state); - winw = s->windowwidth; - - /* - * Premultiply XXT by Beta - */ - if( ae_fp_neq(beta,(double)(0)) ) - { - for(i=0; i<=winw-1; i++) - { - for(j=0; j<=winw-1; j++) - { - s->xxt.ptr.pp_double[i][j] = s->xxt.ptr.pp_double[i][j]*beta; - } - } - } - else - { - for(i=0; i<=winw-1; i++) - { - for(j=0; j<=winw-1; j++) - { - s->xxt.ptr.pp_double[i][j] = (double)(0); - } - } - } - - /* - * Dequeue - */ - ssa_updatexxtprepare(s, cnt, winw, s->memorylimit, _state); - for(i=0; i<=cnt-1; i++) - { - ssa_updatexxtsend(s, &s->sequencedata, s->rtqueue.ptr.p_int[s->rtqueuecnt-1], &s->xxt, _state); - dec(&s->rtqueuecnt, _state); - } - ssa_updatexxtfinalize(s, &s->xxt, _state); -} - - -/************************************************************************* -This function prepares batch buffer for XXT update. The idea is that we -send a stream of "XXT += u*u'" updates, and we want to package them into -one big matrix update U*U', applied with SYRK() kernel, but U can consume -too much memory, so we want to transparently divide it into few smaller -chunks. - -This set of functions solves this problem: -* UpdateXXTPrepare() prepares temporary buffers -* UpdateXXTSend() sends next u to the buffer, possibly initiating next SYRK() -* UpdateXXTFinalize() performs last SYRK() update - -INPUT PARAMETERS: - S - model, only fields with UX prefix are used - UpdateSize - number of updates - WindowWidth - window width, >0 - MemoryLimit - memory limit, non-positive value means no limit - -OUTPUT PARAMETERS: - S - UX temporaries updated - - -- ALGLIB -- - Copyright 20.12.2017 by Bochkanov Sergey -*************************************************************************/ -static void ssa_updatexxtprepare(ssamodel* s, - ae_int_t updatesize, - ae_int_t windowwidth, - ae_int_t memorylimit, - ae_state *_state) -{ - - - ae_assert(windowwidth>0, "UpdateXXTPrepare: WinW<=0", _state); - s->uxbatchlimit = ae_maxint(updatesize, 1, _state); - if( memorylimit>0 ) - { - s->uxbatchlimit = ae_minint(s->uxbatchlimit, ae_maxint(memorylimit/windowwidth, 4*windowwidth, _state), _state); - } - s->uxbatchwidth = windowwidth; - s->uxbatchsize = 0; - if( s->uxbatch.cols!=windowwidth ) - { - ae_matrix_set_length(&s->uxbatch, 0, 0, _state); - } - rmatrixsetlengthatleast(&s->uxbatch, s->uxbatchlimit, windowwidth, _state); -} - - -/************************************************************************* -This function sends update u*u' to the batch buffer. - -INPUT PARAMETERS: - S - model, only fields with UX prefix are used - U - WindowWidth-sized update, starts at I0 - I0 - starting position for update - -OUTPUT PARAMETERS: - S - UX temporaries updated - XXT - array[WindowWidth,WindowWidth], in the middle - of update. All intermediate updates are - applied to the upper triangle. - - -- ALGLIB -- - Copyright 20.12.2017 by Bochkanov Sergey -*************************************************************************/ -static void ssa_updatexxtsend(ssamodel* s, - /* Real */ ae_vector* u, - ae_int_t i0, - /* Real */ ae_matrix* xxt, - ae_state *_state) -{ - - - ae_assert(i0+s->uxbatchwidth-1cnt, "UpdateXXTSend: incorrect U size", _state); - ae_assert(s->uxbatchsize>=0, "UpdateXXTSend: integrity check failure", _state); - ae_assert(s->uxbatchsize<=s->uxbatchlimit, "UpdateXXTSend: integrity check failure", _state); - ae_assert(s->uxbatchlimit>=1, "UpdateXXTSend: integrity check failure", _state); - - /* - * Send pending batch if full - */ - if( s->uxbatchsize==s->uxbatchlimit ) - { - rmatrixsyrk(s->uxbatchwidth, s->uxbatchsize, 1.0, &s->uxbatch, 0, 0, 2, 1.0, xxt, 0, 0, ae_true, _state); - s->uxbatchsize = 0; - } - - /* - * Append update to batch - */ - ae_v_move(&s->uxbatch.ptr.pp_double[s->uxbatchsize][0], 1, &u->ptr.p_double[i0], 1, ae_v_len(0,s->uxbatchwidth-1)); - inc(&s->uxbatchsize, _state); -} - - -/************************************************************************* -This function finalizes batch buffer. Call it after the last update. - -INPUT PARAMETERS: - S - model, only fields with UX prefix are used - -OUTPUT PARAMETERS: - S - UX temporaries updated - XXT - array[WindowWidth,WindowWidth], updated with - all previous updates, both triangles of the - symmetric matrix are present. - - -- ALGLIB -- - Copyright 20.12.2017 by Bochkanov Sergey -*************************************************************************/ -static void ssa_updatexxtfinalize(ssamodel* s, - /* Real */ ae_matrix* xxt, - ae_state *_state) -{ - - - ae_assert(s->uxbatchsize>=0, "UpdateXXTFinalize: integrity check failure", _state); - ae_assert(s->uxbatchsize<=s->uxbatchlimit, "UpdateXXTFinalize: integrity check failure", _state); - ae_assert(s->uxbatchlimit>=1, "UpdateXXTFinalize: integrity check failure", _state); - if( s->uxbatchsize>0 ) - { - rmatrixsyrk(s->uxbatchwidth, s->uxbatchsize, 1.0, &s->uxbatch, 0, 0, 2, 1.0, &s->xxt, 0, 0, ae_true, _state); - s->uxbatchsize = 0; - } - rmatrixenforcesymmetricity(&s->xxt, s->uxbatchwidth, ae_true, _state); -} - - -void _ssamodel_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - ssamodel *p = (ssamodel*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->sequenceidx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->sequencedata, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->precomputedbasis, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->basis, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->basist, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->sv, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->forecasta, 0, DT_REAL, _state, make_automatic); - _eigsubspacestate_init(&p->solver, _state, make_automatic); - ae_matrix_init(&p->xxt, 0, 0, DT_REAL, _state, make_automatic); - _hqrndstate_init(&p->rs, _state, make_automatic); - ae_vector_init(&p->rtqueue, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic); - _eigsubspacereport_init(&p->solverrep, _state, make_automatic); - ae_vector_init(&p->alongtrend, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->alongnoise, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->aseqtrajectory, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->aseqtbproduct, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->aseqcounts, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->fctrend, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fcnoise, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->fctrendm, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->uxbatch, 0, 0, DT_REAL, _state, make_automatic); -} - - -void _ssamodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - ssamodel *dst = (ssamodel*)_dst; - ssamodel *src = (ssamodel*)_src; - dst->nsequences = src->nsequences; - ae_vector_init_copy(&dst->sequenceidx, &src->sequenceidx, _state, make_automatic); - ae_vector_init_copy(&dst->sequencedata, &src->sequencedata, _state, make_automatic); - dst->algotype = src->algotype; - dst->windowwidth = src->windowwidth; - dst->rtpowerup = src->rtpowerup; - dst->topk = src->topk; - dst->precomputedwidth = src->precomputedwidth; - dst->precomputednbasis = src->precomputednbasis; - ae_matrix_init_copy(&dst->precomputedbasis, &src->precomputedbasis, _state, make_automatic); - dst->defaultsubspaceits = src->defaultsubspaceits; - dst->memorylimit = src->memorylimit; - dst->arebasisandsolvervalid = src->arebasisandsolvervalid; - ae_matrix_init_copy(&dst->basis, &src->basis, _state, make_automatic); - ae_matrix_init_copy(&dst->basist, &src->basist, _state, make_automatic); - ae_vector_init_copy(&dst->sv, &src->sv, _state, make_automatic); - ae_vector_init_copy(&dst->forecasta, &src->forecasta, _state, make_automatic); - dst->nbasis = src->nbasis; - _eigsubspacestate_init_copy(&dst->solver, &src->solver, _state, make_automatic); - ae_matrix_init_copy(&dst->xxt, &src->xxt, _state, make_automatic); - _hqrndstate_init_copy(&dst->rs, &src->rs, _state, make_automatic); - dst->rngseed = src->rngseed; - ae_vector_init_copy(&dst->rtqueue, &src->rtqueue, _state, make_automatic); - dst->rtqueuecnt = src->rtqueuecnt; - dst->rtqueuechunk = src->rtqueuechunk; - dst->dbgcntevd = src->dbgcntevd; - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic); - _eigsubspacereport_init_copy(&dst->solverrep, &src->solverrep, _state, make_automatic); - ae_vector_init_copy(&dst->alongtrend, &src->alongtrend, _state, make_automatic); - ae_vector_init_copy(&dst->alongnoise, &src->alongnoise, _state, make_automatic); - ae_matrix_init_copy(&dst->aseqtrajectory, &src->aseqtrajectory, _state, make_automatic); - ae_matrix_init_copy(&dst->aseqtbproduct, &src->aseqtbproduct, _state, make_automatic); - ae_vector_init_copy(&dst->aseqcounts, &src->aseqcounts, _state, make_automatic); - ae_vector_init_copy(&dst->fctrend, &src->fctrend, _state, make_automatic); - ae_vector_init_copy(&dst->fcnoise, &src->fcnoise, _state, make_automatic); - ae_matrix_init_copy(&dst->fctrendm, &src->fctrendm, _state, make_automatic); - ae_matrix_init_copy(&dst->uxbatch, &src->uxbatch, _state, make_automatic); - dst->uxbatchwidth = src->uxbatchwidth; - dst->uxbatchsize = src->uxbatchsize; - dst->uxbatchlimit = src->uxbatchlimit; -} - - -void _ssamodel_clear(void* _p) -{ - ssamodel *p = (ssamodel*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->sequenceidx); - ae_vector_clear(&p->sequencedata); - ae_matrix_clear(&p->precomputedbasis); - ae_matrix_clear(&p->basis); - ae_matrix_clear(&p->basist); - ae_vector_clear(&p->sv); - ae_vector_clear(&p->forecasta); - _eigsubspacestate_clear(&p->solver); - ae_matrix_clear(&p->xxt); - _hqrndstate_clear(&p->rs); - ae_vector_clear(&p->rtqueue); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->tmp1); - _eigsubspacereport_clear(&p->solverrep); - ae_vector_clear(&p->alongtrend); - ae_vector_clear(&p->alongnoise); - ae_matrix_clear(&p->aseqtrajectory); - ae_matrix_clear(&p->aseqtbproduct); - ae_vector_clear(&p->aseqcounts); - ae_vector_clear(&p->fctrend); - ae_vector_clear(&p->fcnoise); - ae_matrix_clear(&p->fctrendm); - ae_matrix_clear(&p->uxbatch); -} - - -void _ssamodel_destroy(void* _p) -{ - ssamodel *p = (ssamodel*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->sequenceidx); - ae_vector_destroy(&p->sequencedata); - ae_matrix_destroy(&p->precomputedbasis); - ae_matrix_destroy(&p->basis); - ae_matrix_destroy(&p->basist); - ae_vector_destroy(&p->sv); - ae_vector_destroy(&p->forecasta); - _eigsubspacestate_destroy(&p->solver); - ae_matrix_destroy(&p->xxt); - _hqrndstate_destroy(&p->rs); - ae_vector_destroy(&p->rtqueue); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->tmp1); - _eigsubspacereport_destroy(&p->solverrep); - ae_vector_destroy(&p->alongtrend); - ae_vector_destroy(&p->alongnoise); - ae_matrix_destroy(&p->aseqtrajectory); - ae_matrix_destroy(&p->aseqtbproduct); - ae_vector_destroy(&p->aseqcounts); - ae_vector_destroy(&p->fctrend); - ae_vector_destroy(&p->fcnoise); - ae_matrix_destroy(&p->fctrendm); - ae_matrix_destroy(&p->uxbatch); -} - - -#endif -#if defined(AE_COMPILE_LINREG) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Linear regression - -Subroutine builds model: - - Y = A(0)*X[0] + ... + A(N-1)*X[N-1] + A(N) - -and model found in ALGLIB format, covariation matrix, training set errors -(rms, average, average relative) and leave-one-out cross-validation -estimate of the generalization error. CV estimate calculated using fast -algorithm with O(NPoints*NVars) complexity. - -When covariation matrix is calculated standard deviations of function -values are assumed to be equal to RMS error on the training set. - -INPUT PARAMETERS: - XY - training set, array [0..NPoints-1,0..NVars]: - * NVars columns - independent variables - * last column - dependent variable - NPoints - training set size, NPoints>NVars+1 - NVars - number of independent variables - -OUTPUT PARAMETERS: - Info - return code: - * -255, in case of unknown internal error - * -4, if internal SVD subroutine haven't converged - * -1, if incorrect parameters was passed (NPointsrmserror, _state)*npoints/(npoints-nvars-1); - for(i=0; i<=nvars; i++) - { - ae_v_muld(&ar->c.ptr.pp_double[i][0], 1, ae_v_len(0,nvars), sigma2); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Linear regression - -Variant of LRBuild which uses vector of standatd deviations (errors in -function values). - -INPUT PARAMETERS: - XY - training set, array [0..NPoints-1,0..NVars]: - * NVars columns - independent variables - * last column - dependent variable - S - standard deviations (errors in function values) - array[0..NPoints-1], S[i]>0. - NPoints - training set size, NPoints>NVars+1 - NVars - number of independent variables - -OUTPUT PARAMETERS: - Info - return code: - * -255, in case of unknown internal error - * -4, if internal SVD subroutine haven't converged - * -1, if incorrect parameters was passed (NPointsptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - xyi.ptr.pp_double[i][nvars] = (double)(1); - xyi.ptr.pp_double[i][nvars+1] = xy->ptr.pp_double[i][nvars]; - } - - /* - * Standartization - */ - ae_vector_set_length(&x, npoints-1+1, _state); - ae_vector_set_length(&means, nvars-1+1, _state); - ae_vector_set_length(&sigmas, nvars-1+1, _state); - for(j=0; j<=nvars-1; j++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[0][j], xy->stride, ae_v_len(0,npoints-1)); - samplemoments(&x, npoints, &mean, &variance, &skewness, &kurtosis, _state); - means.ptr.p_double[j] = mean; - sigmas.ptr.p_double[j] = ae_sqrt(variance, _state); - if( ae_fp_eq(sigmas.ptr.p_double[j],(double)(0)) ) - { - sigmas.ptr.p_double[j] = (double)(1); - } - for(i=0; i<=npoints-1; i++) - { - xyi.ptr.pp_double[i][j] = (xyi.ptr.pp_double[i][j]-means.ptr.p_double[j])/sigmas.ptr.p_double[j]; - } - } - - /* - * Internal processing - */ - linreg_lrinternal(&xyi, s, npoints, nvars+1, info, lm, ar, _state); - if( *info<0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Un-standartization - */ - offs = ae_round(lm->w.ptr.p_double[3], _state); - for(j=0; j<=nvars-1; j++) - { - - /* - * Constant term is updated (and its covariance too, - * since it gets some variance from J-th component) - */ - lm->w.ptr.p_double[offs+nvars] = lm->w.ptr.p_double[offs+nvars]-lm->w.ptr.p_double[offs+j]*means.ptr.p_double[j]/sigmas.ptr.p_double[j]; - v = means.ptr.p_double[j]/sigmas.ptr.p_double[j]; - ae_v_subd(&ar->c.ptr.pp_double[nvars][0], 1, &ar->c.ptr.pp_double[j][0], 1, ae_v_len(0,nvars), v); - ae_v_subd(&ar->c.ptr.pp_double[0][nvars], ar->c.stride, &ar->c.ptr.pp_double[0][j], ar->c.stride, ae_v_len(0,nvars), v); - - /* - * J-th term is updated - */ - lm->w.ptr.p_double[offs+j] = lm->w.ptr.p_double[offs+j]/sigmas.ptr.p_double[j]; - v = 1/sigmas.ptr.p_double[j]; - ae_v_muld(&ar->c.ptr.pp_double[j][0], 1, ae_v_len(0,nvars), v); - ae_v_muld(&ar->c.ptr.pp_double[0][j], ar->c.stride, ae_v_len(0,nvars), v); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Like LRBuildS, but builds model - - Y = A(0)*X[0] + ... + A(N-1)*X[N-1] - -i.e. with zero constant term. - - -- ALGLIB -- - Copyright 30.10.2008 by Bochkanov Sergey -*************************************************************************/ -void lrbuildzs(/* Real */ ae_matrix* xy, - /* Real */ ae_vector* s, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t* info, - linearmodel* lm, - lrreport* ar, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix xyi; - ae_vector x; - ae_vector c; - ae_int_t i; - ae_int_t j; - double v; - ae_int_t offs; - double mean; - double variance; - double skewness; - double kurtosis; - - ae_frame_make(_state, &_frame_block); - memset(&xyi, 0, sizeof(xyi)); - memset(&x, 0, sizeof(x)); - memset(&c, 0, sizeof(c)); - *info = 0; - _linearmodel_clear(lm); - _lrreport_clear(ar); - ae_matrix_init(&xyi, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c, 0, DT_REAL, _state, ae_true); - - - /* - * Test parameters - */ - if( npoints<=nvars+1||nvars<1 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - - /* - * Copy data, add one more column (constant term) - */ - ae_matrix_set_length(&xyi, npoints-1+1, nvars+1+1, _state); - for(i=0; i<=npoints-1; i++) - { - ae_v_move(&xyi.ptr.pp_double[i][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - xyi.ptr.pp_double[i][nvars] = (double)(0); - xyi.ptr.pp_double[i][nvars+1] = xy->ptr.pp_double[i][nvars]; - } - - /* - * Standartization: unusual scaling - */ - ae_vector_set_length(&x, npoints-1+1, _state); - ae_vector_set_length(&c, nvars-1+1, _state); - for(j=0; j<=nvars-1; j++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[0][j], xy->stride, ae_v_len(0,npoints-1)); - samplemoments(&x, npoints, &mean, &variance, &skewness, &kurtosis, _state); - if( ae_fp_greater(ae_fabs(mean, _state),ae_sqrt(variance, _state)) ) - { - - /* - * variation is relatively small, it is better to - * bring mean value to 1 - */ - c.ptr.p_double[j] = mean; - } - else - { - - /* - * variation is large, it is better to bring variance to 1 - */ - if( ae_fp_eq(variance,(double)(0)) ) - { - variance = (double)(1); - } - c.ptr.p_double[j] = ae_sqrt(variance, _state); - } - for(i=0; i<=npoints-1; i++) - { - xyi.ptr.pp_double[i][j] = xyi.ptr.pp_double[i][j]/c.ptr.p_double[j]; - } - } - - /* - * Internal processing - */ - linreg_lrinternal(&xyi, s, npoints, nvars+1, info, lm, ar, _state); - if( *info<0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Un-standartization - */ - offs = ae_round(lm->w.ptr.p_double[3], _state); - for(j=0; j<=nvars-1; j++) - { - - /* - * J-th term is updated - */ - lm->w.ptr.p_double[offs+j] = lm->w.ptr.p_double[offs+j]/c.ptr.p_double[j]; - v = 1/c.ptr.p_double[j]; - ae_v_muld(&ar->c.ptr.pp_double[j][0], 1, ae_v_len(0,nvars), v); - ae_v_muld(&ar->c.ptr.pp_double[0][j], ar->c.stride, ae_v_len(0,nvars), v); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Like LRBuild but builds model - - Y = A(0)*X[0] + ... + A(N-1)*X[N-1] - -i.e. with zero constant term. - - -- ALGLIB -- - Copyright 30.10.2008 by Bochkanov Sergey -*************************************************************************/ -void lrbuildz(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t* info, - linearmodel* lm, - lrreport* ar, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector s; - ae_int_t i; - double sigma2; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - *info = 0; - _linearmodel_clear(lm); - _lrreport_clear(ar); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - - if( npoints<=nvars+1||nvars<1 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_vector_set_length(&s, npoints-1+1, _state); - for(i=0; i<=npoints-1; i++) - { - s.ptr.p_double[i] = (double)(1); - } - lrbuildzs(xy, &s, npoints, nvars, info, lm, ar, _state); - if( *info<0 ) - { - ae_frame_leave(_state); - return; - } - sigma2 = ae_sqr(ar->rmserror, _state)*npoints/(npoints-nvars-1); - for(i=0; i<=nvars; i++) - { - ae_v_muld(&ar->c.ptr.pp_double[i][0], 1, ae_v_len(0,nvars), sigma2); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Unpacks coefficients of linear model. - -INPUT PARAMETERS: - LM - linear model in ALGLIB format - -OUTPUT PARAMETERS: - V - coefficients, array[0..NVars] - constant term (intercept) is stored in the V[NVars]. - NVars - number of independent variables (one less than number - of coefficients) - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -void lrunpack(linearmodel* lm, - /* Real */ ae_vector* v, - ae_int_t* nvars, - ae_state *_state) -{ - ae_int_t offs; - - ae_vector_clear(v); - *nvars = 0; - - ae_assert(ae_round(lm->w.ptr.p_double[1], _state)==linreg_lrvnum, "LINREG: Incorrect LINREG version!", _state); - *nvars = ae_round(lm->w.ptr.p_double[2], _state); - offs = ae_round(lm->w.ptr.p_double[3], _state); - ae_vector_set_length(v, *nvars+1, _state); - ae_v_move(&v->ptr.p_double[0], 1, &lm->w.ptr.p_double[offs], 1, ae_v_len(0,*nvars)); -} - - -/************************************************************************* -"Packs" coefficients and creates linear model in ALGLIB format (LRUnpack -reversed). - -INPUT PARAMETERS: - V - coefficients, array[0..NVars] - NVars - number of independent variables - -OUTPUT PAREMETERS: - LM - linear model. - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -void lrpack(/* Real */ ae_vector* v, - ae_int_t nvars, - linearmodel* lm, - ae_state *_state) -{ - ae_int_t offs; - - _linearmodel_clear(lm); - - ae_vector_set_length(&lm->w, 4+nvars+1, _state); - offs = 4; - lm->w.ptr.p_double[0] = (double)(4+nvars+1); - lm->w.ptr.p_double[1] = (double)(linreg_lrvnum); - lm->w.ptr.p_double[2] = (double)(nvars); - lm->w.ptr.p_double[3] = (double)(offs); - ae_v_move(&lm->w.ptr.p_double[offs], 1, &v->ptr.p_double[0], 1, ae_v_len(offs,offs+nvars)); -} - - -/************************************************************************* -Procesing - -INPUT PARAMETERS: - LM - linear model - X - input vector, array[0..NVars-1]. - -Result: - value of linear model regression estimate - - -- ALGLIB -- - Copyright 03.09.2008 by Bochkanov Sergey -*************************************************************************/ -double lrprocess(linearmodel* lm, - /* Real */ ae_vector* x, - ae_state *_state) -{ - double v; - ae_int_t offs; - ae_int_t nvars; - double result; - - - ae_assert(ae_round(lm->w.ptr.p_double[1], _state)==linreg_lrvnum, "LINREG: Incorrect LINREG version!", _state); - nvars = ae_round(lm->w.ptr.p_double[2], _state); - offs = ae_round(lm->w.ptr.p_double[3], _state); - v = ae_v_dotproduct(&x->ptr.p_double[0], 1, &lm->w.ptr.p_double[offs], 1, ae_v_len(0,nvars-1)); - result = v+lm->w.ptr.p_double[offs+nvars]; - return result; -} - - -/************************************************************************* -RMS error on the test set - -INPUT PARAMETERS: - LM - linear model - XY - test set - NPoints - test set size - -RESULT: - root mean square error. - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -double lrrmserror(linearmodel* lm, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_int_t i; - double v; - ae_int_t offs; - ae_int_t nvars; - double result; - - - ae_assert(ae_round(lm->w.ptr.p_double[1], _state)==linreg_lrvnum, "LINREG: Incorrect LINREG version!", _state); - nvars = ae_round(lm->w.ptr.p_double[2], _state); - offs = ae_round(lm->w.ptr.p_double[3], _state); - result = (double)(0); - for(i=0; i<=npoints-1; i++) - { - v = ae_v_dotproduct(&xy->ptr.pp_double[i][0], 1, &lm->w.ptr.p_double[offs], 1, ae_v_len(0,nvars-1)); - v = v+lm->w.ptr.p_double[offs+nvars]; - result = result+ae_sqr(v-xy->ptr.pp_double[i][nvars], _state); - } - result = ae_sqrt(result/npoints, _state); - return result; -} - - -/************************************************************************* -Average error on the test set - -INPUT PARAMETERS: - LM - linear model - XY - test set - NPoints - test set size - -RESULT: - average error. - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -double lravgerror(linearmodel* lm, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_int_t i; - double v; - ae_int_t offs; - ae_int_t nvars; - double result; - - - ae_assert(ae_round(lm->w.ptr.p_double[1], _state)==linreg_lrvnum, "LINREG: Incorrect LINREG version!", _state); - nvars = ae_round(lm->w.ptr.p_double[2], _state); - offs = ae_round(lm->w.ptr.p_double[3], _state); - result = (double)(0); - for(i=0; i<=npoints-1; i++) - { - v = ae_v_dotproduct(&xy->ptr.pp_double[i][0], 1, &lm->w.ptr.p_double[offs], 1, ae_v_len(0,nvars-1)); - v = v+lm->w.ptr.p_double[offs+nvars]; - result = result+ae_fabs(v-xy->ptr.pp_double[i][nvars], _state); - } - result = result/npoints; - return result; -} - - -/************************************************************************* -RMS error on the test set - -INPUT PARAMETERS: - LM - linear model - XY - test set - NPoints - test set size - -RESULT: - average relative error. - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -double lravgrelerror(linearmodel* lm, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - double v; - ae_int_t offs; - ae_int_t nvars; - double result; - - - ae_assert(ae_round(lm->w.ptr.p_double[1], _state)==linreg_lrvnum, "LINREG: Incorrect LINREG version!", _state); - nvars = ae_round(lm->w.ptr.p_double[2], _state); - offs = ae_round(lm->w.ptr.p_double[3], _state); - result = (double)(0); - k = 0; - for(i=0; i<=npoints-1; i++) - { - if( ae_fp_neq(xy->ptr.pp_double[i][nvars],(double)(0)) ) - { - v = ae_v_dotproduct(&xy->ptr.pp_double[i][0], 1, &lm->w.ptr.p_double[offs], 1, ae_v_len(0,nvars-1)); - v = v+lm->w.ptr.p_double[offs+nvars]; - result = result+ae_fabs((v-xy->ptr.pp_double[i][nvars])/xy->ptr.pp_double[i][nvars], _state); - k = k+1; - } - } - if( k!=0 ) - { - result = result/k; - } - return result; -} - - -/************************************************************************* -Copying of LinearModel strucure - -INPUT PARAMETERS: - LM1 - original - -OUTPUT PARAMETERS: - LM2 - copy - - -- ALGLIB -- - Copyright 15.03.2009 by Bochkanov Sergey -*************************************************************************/ -void lrcopy(linearmodel* lm1, linearmodel* lm2, ae_state *_state) -{ - ae_int_t k; - - _linearmodel_clear(lm2); - - k = ae_round(lm1->w.ptr.p_double[0], _state); - ae_vector_set_length(&lm2->w, k-1+1, _state); - ae_v_move(&lm2->w.ptr.p_double[0], 1, &lm1->w.ptr.p_double[0], 1, ae_v_len(0,k-1)); -} - - -void lrlines(/* Real */ ae_matrix* xy, - /* Real */ ae_vector* s, - ae_int_t n, - ae_int_t* info, - double* a, - double* b, - double* vara, - double* varb, - double* covab, - double* corrab, - double* p, - ae_state *_state) -{ - ae_int_t i; - double ss; - double sx; - double sxx; - double sy; - double stt; - double e1; - double e2; - double t; - double chi2; - - *info = 0; - *a = 0; - *b = 0; - *vara = 0; - *varb = 0; - *covab = 0; - *corrab = 0; - *p = 0; - - if( n<2 ) - { - *info = -1; - return; - } - for(i=0; i<=n-1; i++) - { - if( ae_fp_less_eq(s->ptr.p_double[i],(double)(0)) ) - { - *info = -2; - return; - } - } - *info = 1; - - /* - * Calculate S, SX, SY, SXX - */ - ss = (double)(0); - sx = (double)(0); - sy = (double)(0); - sxx = (double)(0); - for(i=0; i<=n-1; i++) - { - t = ae_sqr(s->ptr.p_double[i], _state); - ss = ss+1/t; - sx = sx+xy->ptr.pp_double[i][0]/t; - sy = sy+xy->ptr.pp_double[i][1]/t; - sxx = sxx+ae_sqr(xy->ptr.pp_double[i][0], _state)/t; - } - - /* - * Test for condition number - */ - t = ae_sqrt(4*ae_sqr(sx, _state)+ae_sqr(ss-sxx, _state), _state); - e1 = 0.5*(ss+sxx+t); - e2 = 0.5*(ss+sxx-t); - if( ae_fp_less_eq(ae_minreal(e1, e2, _state),1000*ae_machineepsilon*ae_maxreal(e1, e2, _state)) ) - { - *info = -3; - return; - } - - /* - * Calculate A, B - */ - *a = (double)(0); - *b = (double)(0); - stt = (double)(0); - for(i=0; i<=n-1; i++) - { - t = (xy->ptr.pp_double[i][0]-sx/ss)/s->ptr.p_double[i]; - *b = *b+t*xy->ptr.pp_double[i][1]/s->ptr.p_double[i]; - stt = stt+ae_sqr(t, _state); - } - *b = *b/stt; - *a = (sy-sx*(*b))/ss; - - /* - * Calculate goodness-of-fit - */ - if( n>2 ) - { - chi2 = (double)(0); - for(i=0; i<=n-1; i++) - { - chi2 = chi2+ae_sqr((xy->ptr.pp_double[i][1]-(*a)-*b*xy->ptr.pp_double[i][0])/s->ptr.p_double[i], _state); - } - *p = incompletegammac((double)(n-2)/(double)2, chi2/2, _state); - } - else - { - *p = (double)(1); - } - - /* - * Calculate other parameters - */ - *vara = (1+ae_sqr(sx, _state)/(ss*stt))/ss; - *varb = 1/stt; - *covab = -sx/(ss*stt); - *corrab = *covab/ae_sqrt(*vara*(*varb), _state); -} - - -void lrline(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t* info, - double* a, - double* b, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector s; - ae_int_t i; - double vara; - double varb; - double covab; - double corrab; - double p; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - *info = 0; - *a = 0; - *b = 0; - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - - if( n<2 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_vector_set_length(&s, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = (double)(1); - } - lrlines(xy, &s, n, info, a, b, &vara, &varb, &covab, &corrab, &p, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal linear regression subroutine -*************************************************************************/ -static void linreg_lrinternal(/* Real */ ae_matrix* xy, - /* Real */ ae_vector* s, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t* info, - linearmodel* lm, - lrreport* ar, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix u; - ae_matrix vt; - ae_matrix vm; - ae_matrix xym; - ae_vector b; - ae_vector sv; - ae_vector t; - ae_vector svi; - ae_vector work; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t ncv; - ae_int_t na; - ae_int_t nacv; - double r; - double p; - double epstol; - lrreport ar2; - ae_int_t offs; - linearmodel tlm; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&u, 0, sizeof(u)); - memset(&vt, 0, sizeof(vt)); - memset(&vm, 0, sizeof(vm)); - memset(&xym, 0, sizeof(xym)); - memset(&b, 0, sizeof(b)); - memset(&sv, 0, sizeof(sv)); - memset(&t, 0, sizeof(t)); - memset(&svi, 0, sizeof(svi)); - memset(&work, 0, sizeof(work)); - memset(&ar2, 0, sizeof(ar2)); - memset(&tlm, 0, sizeof(tlm)); - *info = 0; - _linearmodel_clear(lm); - _lrreport_clear(ar); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vt, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vm, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xym, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sv, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - ae_vector_init(&svi, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - _lrreport_init(&ar2, _state, ae_true); - _linearmodel_init(&tlm, _state, ae_true); - - epstol = (double)(1000); - - /* - * Check for errors in data - */ - if( npointsptr.p_double[i],(double)(0)) ) - { - *info = -2; - ae_frame_leave(_state); - return; - } - } - *info = 1; - - /* - * Create design matrix - */ - ae_matrix_set_length(&a, npoints-1+1, nvars-1+1, _state); - ae_vector_set_length(&b, npoints-1+1, _state); - for(i=0; i<=npoints-1; i++) - { - r = 1/s->ptr.p_double[i]; - ae_v_moved(&a.ptr.pp_double[i][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1), r); - b.ptr.p_double[i] = xy->ptr.pp_double[i][nvars]/s->ptr.p_double[i]; - } - - /* - * Allocate W: - * W[0] array size - * W[1] version number, 0 - * W[2] NVars (minus 1, to be compatible with external representation) - * W[3] coefficients offset - */ - ae_vector_set_length(&lm->w, 4+nvars-1+1, _state); - offs = 4; - lm->w.ptr.p_double[0] = (double)(4+nvars); - lm->w.ptr.p_double[1] = (double)(linreg_lrvnum); - lm->w.ptr.p_double[2] = (double)(nvars-1); - lm->w.ptr.p_double[3] = (double)(offs); - - /* - * Solve problem using SVD: - * - * 0. check for degeneracy (different types) - * 1. A = U*diag(sv)*V' - * 2. T = b'*U - * 3. w = SUM((T[i]/sv[i])*V[..,i]) - * 4. cov(wi,wj) = SUM(Vji*Vjk/sv[i]^2,K=1..M) - * - * see $15.4 of "Numerical Recipes in C" for more information - */ - ae_vector_set_length(&t, nvars-1+1, _state); - ae_vector_set_length(&svi, nvars-1+1, _state); - ae_matrix_set_length(&ar->c, nvars-1+1, nvars-1+1, _state); - ae_matrix_set_length(&vm, nvars-1+1, nvars-1+1, _state); - if( !rmatrixsvd(&a, npoints, nvars, 1, 1, 2, &sv, &u, &vt, _state) ) - { - *info = -4; - ae_frame_leave(_state); - return; - } - if( ae_fp_less_eq(sv.ptr.p_double[0],(double)(0)) ) - { - - /* - * Degenerate case: zero design matrix. - */ - for(i=offs; i<=offs+nvars-1; i++) - { - lm->w.ptr.p_double[i] = (double)(0); - } - ar->rmserror = lrrmserror(lm, xy, npoints, _state); - ar->avgerror = lravgerror(lm, xy, npoints, _state); - ar->avgrelerror = lravgrelerror(lm, xy, npoints, _state); - ar->cvrmserror = ar->rmserror; - ar->cvavgerror = ar->avgerror; - ar->cvavgrelerror = ar->avgrelerror; - ar->ncvdefects = 0; - ae_vector_set_length(&ar->cvdefects, nvars-1+1, _state); - for(i=0; i<=nvars-1; i++) - { - ar->cvdefects.ptr.p_int[i] = -1; - } - ae_matrix_set_length(&ar->c, nvars-1+1, nvars-1+1, _state); - for(i=0; i<=nvars-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - ar->c.ptr.pp_double[i][j] = (double)(0); - } - } - ae_frame_leave(_state); - return; - } - if( ae_fp_less_eq(sv.ptr.p_double[nvars-1],epstol*ae_machineepsilon*sv.ptr.p_double[0]) ) - { - - /* - * Degenerate case, non-zero design matrix. - * - * We can leave it and solve task in SVD least squares fashion. - * Solution and covariance matrix will be obtained correctly, - * but CV error estimates - will not. It is better to reduce - * it to non-degenerate task and to obtain correct CV estimates. - */ - for(k=nvars; k>=1; k--) - { - if( ae_fp_greater(sv.ptr.p_double[k-1],epstol*ae_machineepsilon*sv.ptr.p_double[0]) ) - { - - /* - * Reduce - */ - ae_matrix_set_length(&xym, npoints-1+1, k+1, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=k-1; j++) - { - r = ae_v_dotproduct(&xy->ptr.pp_double[i][0], 1, &vt.ptr.pp_double[j][0], 1, ae_v_len(0,nvars-1)); - xym.ptr.pp_double[i][j] = r; - } - xym.ptr.pp_double[i][k] = xy->ptr.pp_double[i][nvars]; - } - - /* - * Solve - */ - linreg_lrinternal(&xym, s, npoints, k, info, &tlm, &ar2, _state); - if( *info!=1 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Convert back to un-reduced format - */ - for(j=0; j<=nvars-1; j++) - { - lm->w.ptr.p_double[offs+j] = (double)(0); - } - for(j=0; j<=k-1; j++) - { - r = tlm.w.ptr.p_double[offs+j]; - ae_v_addd(&lm->w.ptr.p_double[offs], 1, &vt.ptr.pp_double[j][0], 1, ae_v_len(offs,offs+nvars-1), r); - } - ar->rmserror = ar2.rmserror; - ar->avgerror = ar2.avgerror; - ar->avgrelerror = ar2.avgrelerror; - ar->cvrmserror = ar2.cvrmserror; - ar->cvavgerror = ar2.cvavgerror; - ar->cvavgrelerror = ar2.cvavgrelerror; - ar->ncvdefects = ar2.ncvdefects; - ae_vector_set_length(&ar->cvdefects, nvars-1+1, _state); - for(j=0; j<=ar->ncvdefects-1; j++) - { - ar->cvdefects.ptr.p_int[j] = ar2.cvdefects.ptr.p_int[j]; - } - for(j=ar->ncvdefects; j<=nvars-1; j++) - { - ar->cvdefects.ptr.p_int[j] = -1; - } - ae_matrix_set_length(&ar->c, nvars-1+1, nvars-1+1, _state); - ae_vector_set_length(&work, nvars+1, _state); - matrixmatrixmultiply(&ar2.c, 0, k-1, 0, k-1, ae_false, &vt, 0, k-1, 0, nvars-1, ae_false, 1.0, &vm, 0, k-1, 0, nvars-1, 0.0, &work, _state); - matrixmatrixmultiply(&vt, 0, k-1, 0, nvars-1, ae_true, &vm, 0, k-1, 0, nvars-1, ae_false, 1.0, &ar->c, 0, nvars-1, 0, nvars-1, 0.0, &work, _state); - ae_frame_leave(_state); - return; - } - } - *info = -255; - ae_frame_leave(_state); - return; - } - for(i=0; i<=nvars-1; i++) - { - if( ae_fp_greater(sv.ptr.p_double[i],epstol*ae_machineepsilon*sv.ptr.p_double[0]) ) - { - svi.ptr.p_double[i] = 1/sv.ptr.p_double[i]; - } - else - { - svi.ptr.p_double[i] = (double)(0); - } - } - for(i=0; i<=nvars-1; i++) - { - t.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=npoints-1; i++) - { - r = b.ptr.p_double[i]; - ae_v_addd(&t.ptr.p_double[0], 1, &u.ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1), r); - } - for(i=0; i<=nvars-1; i++) - { - lm->w.ptr.p_double[offs+i] = (double)(0); - } - for(i=0; i<=nvars-1; i++) - { - r = t.ptr.p_double[i]*svi.ptr.p_double[i]; - ae_v_addd(&lm->w.ptr.p_double[offs], 1, &vt.ptr.pp_double[i][0], 1, ae_v_len(offs,offs+nvars-1), r); - } - for(j=0; j<=nvars-1; j++) - { - r = svi.ptr.p_double[j]; - ae_v_moved(&vm.ptr.pp_double[0][j], vm.stride, &vt.ptr.pp_double[j][0], 1, ae_v_len(0,nvars-1), r); - } - for(i=0; i<=nvars-1; i++) - { - for(j=i; j<=nvars-1; j++) - { - r = ae_v_dotproduct(&vm.ptr.pp_double[i][0], 1, &vm.ptr.pp_double[j][0], 1, ae_v_len(0,nvars-1)); - ar->c.ptr.pp_double[i][j] = r; - ar->c.ptr.pp_double[j][i] = r; - } - } - - /* - * Leave-1-out cross-validation error. - * - * NOTATIONS: - * A design matrix - * A*x = b original linear least squares task - * U*S*V' SVD of A - * ai i-th row of the A - * bi i-th element of the b - * xf solution of the original LLS task - * - * Cross-validation error of i-th element from a sample is - * calculated using following formula: - * - * ERRi = ai*xf - (ai*xf-bi*(ui*ui'))/(1-ui*ui') (1) - * - * This formula can be derived from normal equations of the - * original task - * - * (A'*A)x = A'*b (2) - * - * by applying modification (zeroing out i-th row of A) to (2): - * - * (A-ai)'*(A-ai) = (A-ai)'*b - * - * and using Sherman-Morrison formula for updating matrix inverse - * - * NOTE 1: b is not zeroed out since it is much simpler and - * does not influence final result. - * - * NOTE 2: some design matrices A have such ui that 1-ui*ui'=0. - * Formula (1) can't be applied for such cases and they are skipped - * from CV calculation (which distorts resulting CV estimate). - * But from the properties of U we can conclude that there can - * be no more than NVars such vectors. Usually - * NVars << NPoints, so in a normal case it only slightly - * influences result. - */ - ncv = 0; - na = 0; - nacv = 0; - ar->rmserror = (double)(0); - ar->avgerror = (double)(0); - ar->avgrelerror = (double)(0); - ar->cvrmserror = (double)(0); - ar->cvavgerror = (double)(0); - ar->cvavgrelerror = (double)(0); - ar->ncvdefects = 0; - ae_vector_set_length(&ar->cvdefects, nvars-1+1, _state); - for(i=0; i<=nvars-1; i++) - { - ar->cvdefects.ptr.p_int[i] = -1; - } - for(i=0; i<=npoints-1; i++) - { - - /* - * Error on a training set - */ - r = ae_v_dotproduct(&xy->ptr.pp_double[i][0], 1, &lm->w.ptr.p_double[offs], 1, ae_v_len(0,nvars-1)); - ar->rmserror = ar->rmserror+ae_sqr(r-xy->ptr.pp_double[i][nvars], _state); - ar->avgerror = ar->avgerror+ae_fabs(r-xy->ptr.pp_double[i][nvars], _state); - if( ae_fp_neq(xy->ptr.pp_double[i][nvars],(double)(0)) ) - { - ar->avgrelerror = ar->avgrelerror+ae_fabs((r-xy->ptr.pp_double[i][nvars])/xy->ptr.pp_double[i][nvars], _state); - na = na+1; - } - - /* - * Error using fast leave-one-out cross-validation - */ - p = ae_v_dotproduct(&u.ptr.pp_double[i][0], 1, &u.ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - if( ae_fp_greater(p,1-epstol*ae_machineepsilon) ) - { - ar->cvdefects.ptr.p_int[ar->ncvdefects] = i; - ar->ncvdefects = ar->ncvdefects+1; - continue; - } - r = s->ptr.p_double[i]*(r/s->ptr.p_double[i]-b.ptr.p_double[i]*p)/(1-p); - ar->cvrmserror = ar->cvrmserror+ae_sqr(r-xy->ptr.pp_double[i][nvars], _state); - ar->cvavgerror = ar->cvavgerror+ae_fabs(r-xy->ptr.pp_double[i][nvars], _state); - if( ae_fp_neq(xy->ptr.pp_double[i][nvars],(double)(0)) ) - { - ar->cvavgrelerror = ar->cvavgrelerror+ae_fabs((r-xy->ptr.pp_double[i][nvars])/xy->ptr.pp_double[i][nvars], _state); - nacv = nacv+1; - } - ncv = ncv+1; - } - if( ncv==0 ) - { - - /* - * Something strange: ALL ui are degenerate. - * Unexpected... - */ - *info = -255; - ae_frame_leave(_state); - return; - } - ar->rmserror = ae_sqrt(ar->rmserror/npoints, _state); - ar->avgerror = ar->avgerror/npoints; - if( na!=0 ) - { - ar->avgrelerror = ar->avgrelerror/na; - } - ar->cvrmserror = ae_sqrt(ar->cvrmserror/ncv, _state); - ar->cvavgerror = ar->cvavgerror/ncv; - if( nacv!=0 ) - { - ar->cvavgrelerror = ar->cvavgrelerror/nacv; - } - ae_frame_leave(_state); -} - - -void _linearmodel_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - linearmodel *p = (linearmodel*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->w, 0, DT_REAL, _state, make_automatic); -} - - -void _linearmodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - linearmodel *dst = (linearmodel*)_dst; - linearmodel *src = (linearmodel*)_src; - ae_vector_init_copy(&dst->w, &src->w, _state, make_automatic); -} - - -void _linearmodel_clear(void* _p) -{ - linearmodel *p = (linearmodel*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->w); -} - - -void _linearmodel_destroy(void* _p) -{ - linearmodel *p = (linearmodel*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->w); -} - - -void _lrreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - lrreport *p = (lrreport*)_p; - ae_touch_ptr((void*)p); - ae_matrix_init(&p->c, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cvdefects, 0, DT_INT, _state, make_automatic); -} - - -void _lrreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - lrreport *dst = (lrreport*)_dst; - lrreport *src = (lrreport*)_src; - ae_matrix_init_copy(&dst->c, &src->c, _state, make_automatic); - dst->rmserror = src->rmserror; - dst->avgerror = src->avgerror; - dst->avgrelerror = src->avgrelerror; - dst->cvrmserror = src->cvrmserror; - dst->cvavgerror = src->cvavgerror; - dst->cvavgrelerror = src->cvavgrelerror; - dst->ncvdefects = src->ncvdefects; - ae_vector_init_copy(&dst->cvdefects, &src->cvdefects, _state, make_automatic); -} - - -void _lrreport_clear(void* _p) -{ - lrreport *p = (lrreport*)_p; - ae_touch_ptr((void*)p); - ae_matrix_clear(&p->c); - ae_vector_clear(&p->cvdefects); -} - - -void _lrreport_destroy(void* _p) -{ - lrreport *p = (lrreport*)_p; - ae_touch_ptr((void*)p); - ae_matrix_destroy(&p->c); - ae_vector_destroy(&p->cvdefects); -} - - -#endif -#if defined(AE_COMPILE_FILTERS) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Filters: simple moving averages (unsymmetric). - -This filter replaces array by results of SMA(K) filter. SMA(K) is defined -as filter which averages at most K previous points (previous - not points -AROUND central point) - or less, in case of the first K-1 points. - -INPUT PARAMETERS: - X - array[N], array to process. It can be larger than N, - in this case only first N points are processed. - N - points count, N>=0 - K - K>=1 (K can be larger than N , such cases will be - correctly handled). Window width. K=1 corresponds to - identity transformation (nothing changes). - -OUTPUT PARAMETERS: - X - array, whose first N elements were processed with SMA(K) - -NOTE 1: this function uses efficient in-place algorithm which does not - allocate temporary arrays. - -NOTE 2: this algorithm makes only one pass through array and uses running - sum to speed-up calculation of the averages. Additional measures - are taken to ensure that running sum on a long sequence of zero - elements will be correctly reset to zero even in the presence of - round-off error. - -NOTE 3: this is unsymmetric version of the algorithm, which does NOT - averages points after the current one. Only X[i], X[i-1], ... are - used when calculating new value of X[i]. We should also note that - this algorithm uses BOTH previous points and current one, i.e. - new value of X[i] depends on BOTH previous point and X[i] itself. - - -- ALGLIB -- - Copyright 25.10.2011 by Bochkanov Sergey -*************************************************************************/ -void filtersma(/* Real */ ae_vector* x, - ae_int_t n, - ae_int_t k, - ae_state *_state) -{ - ae_int_t i; - double runningsum; - double termsinsum; - ae_int_t zeroprefix; - double v; - - - ae_assert(n>=0, "FilterSMA: N<0", _state); - ae_assert(x->cnt>=n, "FilterSMA: Length(X)=1, "FilterSMA: K<1", _state); - - /* - * Quick exit, if necessary - */ - if( n<=1||k==1 ) - { - return; - } - - /* - * Prepare variables (see below for explanation) - */ - runningsum = 0.0; - termsinsum = (double)(0); - for(i=ae_maxint(n-k, 0, _state); i<=n-1; i++) - { - runningsum = runningsum+x->ptr.p_double[i]; - termsinsum = termsinsum+1; - } - i = ae_maxint(n-k, 0, _state); - zeroprefix = 0; - while(i<=n-1&&ae_fp_eq(x->ptr.p_double[i],(double)(0))) - { - zeroprefix = zeroprefix+1; - i = i+1; - } - - /* - * General case: we assume that N>1 and K>1 - * - * Make one pass through all elements. At the beginning of - * the iteration we have: - * * I element being processed - * * RunningSum current value of the running sum - * (including I-th element) - * * TermsInSum number of terms in sum, 0<=TermsInSum<=K - * * ZeroPrefix length of the sequence of zero elements - * which starts at X[I-K+1] and continues towards X[I]. - * Equal to zero in case X[I-K+1] is non-zero. - * This value is used to make RunningSum exactly zero - * when it follows from the problem properties. - */ - for(i=n-1; i>=0; i--) - { - - /* - * Store new value of X[i], save old value in V - */ - v = x->ptr.p_double[i]; - x->ptr.p_double[i] = runningsum/termsinsum; - - /* - * Update RunningSum and TermsInSum - */ - if( i-k>=0 ) - { - runningsum = runningsum-v+x->ptr.p_double[i-k]; - } - else - { - runningsum = runningsum-v; - termsinsum = termsinsum-1; - } - - /* - * Update ZeroPrefix. - * In case we have ZeroPrefix=TermsInSum, - * RunningSum is reset to zero. - */ - if( i-k>=0 ) - { - if( ae_fp_neq(x->ptr.p_double[i-k],(double)(0)) ) - { - zeroprefix = 0; - } - else - { - zeroprefix = ae_minint(zeroprefix+1, k, _state); - } - } - else - { - zeroprefix = ae_minint(zeroprefix, i+1, _state); - } - if( ae_fp_eq((double)(zeroprefix),termsinsum) ) - { - runningsum = (double)(0); - } - } -} - - -/************************************************************************* -Filters: exponential moving averages. - -This filter replaces array by results of EMA(alpha) filter. EMA(alpha) is -defined as filter which replaces X[] by S[]: - S[0] = X[0] - S[t] = alpha*X[t] + (1-alpha)*S[t-1] - -INPUT PARAMETERS: - X - array[N], array to process. It can be larger than N, - in this case only first N points are processed. - N - points count, N>=0 - alpha - 0=0, "FilterEMA: N<0", _state); - ae_assert(x->cnt>=n, "FilterEMA: Length(X)1", _state); - - /* - * Quick exit, if necessary - */ - if( n<=1||ae_fp_eq(alpha,(double)(1)) ) - { - return; - } - - /* - * Process - */ - for(i=1; i<=n-1; i++) - { - x->ptr.p_double[i] = alpha*x->ptr.p_double[i]+(1-alpha)*x->ptr.p_double[i-1]; - } -} - - -/************************************************************************* -Filters: linear regression moving averages. - -This filter replaces array by results of LRMA(K) filter. - -LRMA(K) is defined as filter which, for each data point, builds linear -regression model using K prevous points (point itself is included in -these K points) and calculates value of this linear model at the point in -question. - -INPUT PARAMETERS: - X - array[N], array to process. It can be larger than N, - in this case only first N points are processed. - N - points count, N>=0 - K - K>=1 (K can be larger than N , such cases will be - correctly handled). Window width. K=1 corresponds to - identity transformation (nothing changes). - -OUTPUT PARAMETERS: - X - array, whose first N elements were processed with SMA(K) - -NOTE 1: this function uses efficient in-place algorithm which does not - allocate temporary arrays. - -NOTE 2: this algorithm makes only one pass through array and uses running - sum to speed-up calculation of the averages. Additional measures - are taken to ensure that running sum on a long sequence of zero - elements will be correctly reset to zero even in the presence of - round-off error. - -NOTE 3: this is unsymmetric version of the algorithm, which does NOT - averages points after the current one. Only X[i], X[i-1], ... are - used when calculating new value of X[i]. We should also note that - this algorithm uses BOTH previous points and current one, i.e. - new value of X[i] depends on BOTH previous point and X[i] itself. - - -- ALGLIB -- - Copyright 25.10.2011 by Bochkanov Sergey -*************************************************************************/ -void filterlrma(/* Real */ ae_vector* x, - ae_int_t n, - ae_int_t k, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t m; - ae_matrix xy; - ae_vector s; - ae_int_t info; - double a; - double b; - double vara; - double varb; - double covab; - double corrab; - double p; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&s, 0, sizeof(s)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=0, "FilterLRMA: N<0", _state); - ae_assert(x->cnt>=n, "FilterLRMA: Length(X)=1, "FilterLRMA: K<1", _state); - - /* - * Quick exit, if necessary: - * * either N is equal to 1 (nothing to average) - * * or K is 1 (only point itself is used) or 2 (model is too simple, - * we will always get identity transformation) - */ - if( n<=1||k<=2 ) - { - ae_frame_leave(_state); - return; - } - - /* - * General case: K>2, N>1. - * We do not process points with I<2 because first two points (I=0 and I=1) will be - * left unmodified by LRMA filter in any case. - */ - ae_matrix_set_length(&xy, k, 2, _state); - ae_vector_set_length(&s, k, _state); - for(i=0; i<=k-1; i++) - { - xy.ptr.pp_double[i][0] = (double)(i); - s.ptr.p_double[i] = 1.0; - } - for(i=n-1; i>=2; i--) - { - m = ae_minint(i+1, k, _state); - ae_v_move(&xy.ptr.pp_double[0][1], xy.stride, &x->ptr.p_double[i-m+1], 1, ae_v_len(0,m-1)); - lrlines(&xy, &s, m, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state); - ae_assert(info==1, "FilterLRMA: internal error", _state); - x->ptr.p_double[i] = a+b*(m-1); - } - ae_frame_leave(_state); -} - - -#endif -#if defined(AE_COMPILE_LOGIT) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This subroutine trains logit model. - -INPUT PARAMETERS: - XY - training set, array[0..NPoints-1,0..NVars] - First NVars columns store values of independent - variables, next column stores number of class (from 0 - to NClasses-1) which dataset element belongs to. Fractional - values are rounded to nearest integer. - NPoints - training set size, NPoints>=1 - NVars - number of independent variables, NVars>=1 - NClasses - number of classes, NClasses>=2 - -OUTPUT PARAMETERS: - Info - return code: - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed - (NPointsptr.pp_double[i][nvars], _state)<0||ae_round(xy->ptr.pp_double[i][nvars], _state)>=nclasses ) - { - *info = -2; - ae_frame_leave(_state); - return; - } - } - *info = 1; - - /* - * Initialize data - */ - rep->ngrad = 0; - rep->nhess = 0; - - /* - * Allocate array - */ - offs = 5; - ssize = 5+(nvars+1)*(nclasses-1)+nclasses; - ae_vector_set_length(&lm->w, ssize-1+1, _state); - lm->w.ptr.p_double[0] = (double)(ssize); - lm->w.ptr.p_double[1] = (double)(logit_logitvnum); - lm->w.ptr.p_double[2] = (double)(nvars); - lm->w.ptr.p_double[3] = (double)(nclasses); - lm->w.ptr.p_double[4] = (double)(offs); - - /* - * Degenerate case: all outputs are equal - */ - allsame = ae_true; - for(i=1; i<=npoints-1; i++) - { - if( ae_round(xy->ptr.pp_double[i][nvars], _state)!=ae_round(xy->ptr.pp_double[i-1][nvars], _state) ) - { - allsame = ae_false; - } - } - if( allsame ) - { - for(i=0; i<=(nvars+1)*(nclasses-1)-1; i++) - { - lm->w.ptr.p_double[offs+i] = (double)(0); - } - v = -2*ae_log(ae_minrealnumber, _state); - k = ae_round(xy->ptr.pp_double[0][nvars], _state); - if( k==nclasses-1 ) - { - for(i=0; i<=nclasses-2; i++) - { - lm->w.ptr.p_double[offs+i*(nvars+1)+nvars] = -v; - } - } - else - { - for(i=0; i<=nclasses-2; i++) - { - if( i==k ) - { - lm->w.ptr.p_double[offs+i*(nvars+1)+nvars] = v; - } - else - { - lm->w.ptr.p_double[offs+i*(nvars+1)+nvars] = (double)(0); - } - } - } - ae_frame_leave(_state); - return; - } - - /* - * General case. - * Prepare task and network. Allocate space. - */ - mlpcreatec0(nvars, nclasses, &network, _state); - mlpinitpreprocessor(&network, xy, npoints, _state); - mlpproperties(&network, &nin, &nout, &wcount, _state); - for(i=0; i<=wcount-1; i++) - { - network.weights.ptr.p_double[i] = (2*ae_randomreal(_state)-1)/nvars; - } - ae_vector_set_length(&g, wcount-1+1, _state); - ae_matrix_set_length(&h, wcount-1+1, wcount-1+1, _state); - ae_vector_set_length(&wbase, wcount-1+1, _state); - ae_vector_set_length(&wdir, wcount-1+1, _state); - ae_vector_set_length(&work, wcount-1+1, _state); - - /* - * First stage: optimize in gradient direction. - */ - for(k=0; k<=wcount/3+10; k++) - { - - /* - * Calculate gradient in starting point - */ - mlpgradnbatch(&network, xy, npoints, &e, &g, _state); - v = ae_v_dotproduct(&network.weights.ptr.p_double[0], 1, &network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - e = e+0.5*decay*v; - ae_v_addd(&g.ptr.p_double[0], 1, &network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), decay); - rep->ngrad = rep->ngrad+1; - - /* - * Setup optimization scheme - */ - ae_v_moveneg(&wdir.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - v = ae_v_dotproduct(&wdir.ptr.p_double[0], 1, &wdir.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - wstep = ae_sqrt(v, _state); - v = 1/ae_sqrt(v, _state); - ae_v_muld(&wdir.ptr.p_double[0], 1, ae_v_len(0,wcount-1), v); - mcstage = 0; - logit_mnlmcsrch(wcount, &network.weights, &e, &g, &wdir, &wstep, &mcinfo, &mcnfev, &work, &mcstate, &mcstage, _state); - while(mcstage!=0) - { - mlpgradnbatch(&network, xy, npoints, &e, &g, _state); - v = ae_v_dotproduct(&network.weights.ptr.p_double[0], 1, &network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - e = e+0.5*decay*v; - ae_v_addd(&g.ptr.p_double[0], 1, &network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), decay); - rep->ngrad = rep->ngrad+1; - logit_mnlmcsrch(wcount, &network.weights, &e, &g, &wdir, &wstep, &mcinfo, &mcnfev, &work, &mcstate, &mcstage, _state); - } - } - - /* - * Second stage: use Hessian when we are close to the minimum - */ - for(;;) - { - - /* - * Calculate and update E/G/H - */ - mlphessiannbatch(&network, xy, npoints, &e, &g, &h, _state); - v = ae_v_dotproduct(&network.weights.ptr.p_double[0], 1, &network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - e = e+0.5*decay*v; - ae_v_addd(&g.ptr.p_double[0], 1, &network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), decay); - for(k=0; k<=wcount-1; k++) - { - h.ptr.pp_double[k][k] = h.ptr.pp_double[k][k]+decay; - } - rep->nhess = rep->nhess+1; - - /* - * Select step direction - * NOTE: it is important to use lower-triangle Cholesky - * factorization since it is much faster than higher-triangle version. - */ - spd = spdmatrixcholesky(&h, wcount, ae_false, _state); - spdmatrixcholeskysolve(&h, wcount, ae_false, &g, &solverinfo, &solverrep, &wdir, _state); - spd = solverinfo>0; - if( spd ) - { - - /* - * H is positive definite. - * Step in Newton direction. - */ - ae_v_muld(&wdir.ptr.p_double[0], 1, ae_v_len(0,wcount-1), -1); - spd = ae_true; - } - else - { - - /* - * H is indefinite. - * Step in gradient direction. - */ - ae_v_moveneg(&wdir.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - spd = ae_false; - } - - /* - * Optimize in WDir direction - */ - v = ae_v_dotproduct(&wdir.ptr.p_double[0], 1, &wdir.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - wstep = ae_sqrt(v, _state); - v = 1/ae_sqrt(v, _state); - ae_v_muld(&wdir.ptr.p_double[0], 1, ae_v_len(0,wcount-1), v); - mcstage = 0; - logit_mnlmcsrch(wcount, &network.weights, &e, &g, &wdir, &wstep, &mcinfo, &mcnfev, &work, &mcstate, &mcstage, _state); - while(mcstage!=0) - { - mlpgradnbatch(&network, xy, npoints, &e, &g, _state); - v = ae_v_dotproduct(&network.weights.ptr.p_double[0], 1, &network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - e = e+0.5*decay*v; - ae_v_addd(&g.ptr.p_double[0], 1, &network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), decay); - rep->ngrad = rep->ngrad+1; - logit_mnlmcsrch(wcount, &network.weights, &e, &g, &wdir, &wstep, &mcinfo, &mcnfev, &work, &mcstate, &mcstage, _state); - } - if( spd&&((mcinfo==2||mcinfo==4)||mcinfo==6) ) - { - break; - } - } - - /* - * Convert from NN format to MNL format - */ - ae_v_move(&lm->w.ptr.p_double[offs], 1, &network.weights.ptr.p_double[0], 1, ae_v_len(offs,offs+wcount-1)); - for(k=0; k<=nvars-1; k++) - { - for(i=0; i<=nclasses-2; i++) - { - s = network.columnsigmas.ptr.p_double[k]; - if( ae_fp_eq(s,(double)(0)) ) - { - s = (double)(1); - } - j = offs+(nvars+1)*i; - v = lm->w.ptr.p_double[j+k]; - lm->w.ptr.p_double[j+k] = v/s; - lm->w.ptr.p_double[j+nvars] = lm->w.ptr.p_double[j+nvars]+v*network.columnmeans.ptr.p_double[k]/s; - } - } - for(k=0; k<=nclasses-2; k++) - { - lm->w.ptr.p_double[offs+(nvars+1)*k+nvars] = -lm->w.ptr.p_double[offs+(nvars+1)*k+nvars]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Procesing - -INPUT PARAMETERS: - LM - logit model, passed by non-constant reference - (some fields of structure are used as temporaries - when calculating model output). - X - input vector, array[0..NVars-1]. - Y - (possibly) preallocated buffer; if size of Y is less than - NClasses, it will be reallocated.If it is large enough, it - is NOT reallocated, so we can save some time on reallocation. - -OUTPUT PARAMETERS: - Y - result, array[0..NClasses-1] - Vector of posterior probabilities for classification task. - - -- ALGLIB -- - Copyright 10.09.2008 by Bochkanov Sergey -*************************************************************************/ -void mnlprocess(logitmodel* lm, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t nvars; - ae_int_t nclasses; - ae_int_t offs; - ae_int_t i; - ae_int_t i1; - double s; - - - ae_assert(ae_fp_eq(lm->w.ptr.p_double[1],(double)(logit_logitvnum)), "MNLProcess: unexpected model version", _state); - nvars = ae_round(lm->w.ptr.p_double[2], _state); - nclasses = ae_round(lm->w.ptr.p_double[3], _state); - offs = ae_round(lm->w.ptr.p_double[4], _state); - logit_mnliexp(&lm->w, x, _state); - s = (double)(0); - i1 = offs+(nvars+1)*(nclasses-1); - for(i=i1; i<=i1+nclasses-1; i++) - { - s = s+lm->w.ptr.p_double[i]; - } - if( y->cntptr.p_double[i] = lm->w.ptr.p_double[i1+i]/s; - } -} - - -/************************************************************************* -'interactive' variant of MNLProcess for languages like Python which -support constructs like "Y = MNLProcess(LM,X)" and interactive mode of the -interpreter - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 10.09.2008 by Bochkanov Sergey -*************************************************************************/ -void mnlprocessi(logitmodel* lm, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - - ae_vector_clear(y); - - mnlprocess(lm, x, y, _state); -} - - -/************************************************************************* -Unpacks coefficients of logit model. Logit model have form: - - P(class=i) = S(i) / (S(0) + S(1) + ... +S(M-1)) - S(i) = Exp(A[i,0]*X[0] + ... + A[i,N-1]*X[N-1] + A[i,N]), when iw.ptr.p_double[1],(double)(logit_logitvnum)), "MNLUnpack: unexpected model version", _state); - *nvars = ae_round(lm->w.ptr.p_double[2], _state); - *nclasses = ae_round(lm->w.ptr.p_double[3], _state); - offs = ae_round(lm->w.ptr.p_double[4], _state); - ae_matrix_set_length(a, *nclasses-2+1, *nvars+1, _state); - for(i=0; i<=*nclasses-2; i++) - { - ae_v_move(&a->ptr.pp_double[i][0], 1, &lm->w.ptr.p_double[offs+i*(*nvars+1)], 1, ae_v_len(0,*nvars)); - } -} - - -/************************************************************************* -"Packs" coefficients and creates logit model in ALGLIB format (MNLUnpack -reversed). - -INPUT PARAMETERS: - A - model (see MNLUnpack) - NVars - number of independent variables - NClasses - number of classes - -OUTPUT PARAMETERS: - LM - logit model. - - -- ALGLIB -- - Copyright 10.09.2008 by Bochkanov Sergey -*************************************************************************/ -void mnlpack(/* Real */ ae_matrix* a, - ae_int_t nvars, - ae_int_t nclasses, - logitmodel* lm, - ae_state *_state) -{ - ae_int_t offs; - ae_int_t i; - ae_int_t ssize; - - _logitmodel_clear(lm); - - offs = 5; - ssize = 5+(nvars+1)*(nclasses-1)+nclasses; - ae_vector_set_length(&lm->w, ssize-1+1, _state); - lm->w.ptr.p_double[0] = (double)(ssize); - lm->w.ptr.p_double[1] = (double)(logit_logitvnum); - lm->w.ptr.p_double[2] = (double)(nvars); - lm->w.ptr.p_double[3] = (double)(nclasses); - lm->w.ptr.p_double[4] = (double)(offs); - for(i=0; i<=nclasses-2; i++) - { - ae_v_move(&lm->w.ptr.p_double[offs+i*(nvars+1)], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(offs+i*(nvars+1),offs+i*(nvars+1)+nvars)); - } -} - - -/************************************************************************* -Copying of LogitModel strucure - -INPUT PARAMETERS: - LM1 - original - -OUTPUT PARAMETERS: - LM2 - copy - - -- ALGLIB -- - Copyright 15.03.2009 by Bochkanov Sergey -*************************************************************************/ -void mnlcopy(logitmodel* lm1, logitmodel* lm2, ae_state *_state) -{ - ae_int_t k; - - _logitmodel_clear(lm2); - - k = ae_round(lm1->w.ptr.p_double[0], _state); - ae_vector_set_length(&lm2->w, k-1+1, _state); - ae_v_move(&lm2->w.ptr.p_double[0], 1, &lm1->w.ptr.p_double[0], 1, ae_v_len(0,k-1)); -} - - -/************************************************************************* -Average cross-entropy (in bits per element) on the test set - -INPUT PARAMETERS: - LM - logit model - XY - test set - NPoints - test set size - -RESULT: - CrossEntropy/(NPoints*ln(2)). - - -- ALGLIB -- - Copyright 10.09.2008 by Bochkanov Sergey -*************************************************************************/ -double mnlavgce(logitmodel* lm, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nvars; - ae_int_t nclasses; - ae_int_t i; - ae_vector workx; - ae_vector worky; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&workx, 0, sizeof(workx)); - memset(&worky, 0, sizeof(worky)); - ae_vector_init(&workx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&worky, 0, DT_REAL, _state, ae_true); - - ae_assert(ae_fp_eq(lm->w.ptr.p_double[1],(double)(logit_logitvnum)), "MNLClsError: unexpected model version", _state); - nvars = ae_round(lm->w.ptr.p_double[2], _state); - nclasses = ae_round(lm->w.ptr.p_double[3], _state); - ae_vector_set_length(&workx, nvars-1+1, _state); - ae_vector_set_length(&worky, nclasses-1+1, _state); - result = (double)(0); - for(i=0; i<=npoints-1; i++) - { - ae_assert(ae_round(xy->ptr.pp_double[i][nvars], _state)>=0&&ae_round(xy->ptr.pp_double[i][nvars], _state)ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - mnlprocess(lm, &workx, &worky, _state); - if( ae_fp_greater(worky.ptr.p_double[ae_round(xy->ptr.pp_double[i][nvars], _state)],(double)(0)) ) - { - result = result-ae_log(worky.ptr.p_double[ae_round(xy->ptr.pp_double[i][nvars], _state)], _state); - } - else - { - result = result-ae_log(ae_minrealnumber, _state); - } - } - result = result/(npoints*ae_log((double)(2), _state)); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Relative classification error on the test set - -INPUT PARAMETERS: - LM - logit model - XY - test set - NPoints - test set size - -RESULT: - percent of incorrectly classified cases. - - -- ALGLIB -- - Copyright 10.09.2008 by Bochkanov Sergey -*************************************************************************/ -double mnlrelclserror(logitmodel* lm, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - double result; - - - result = (double)mnlclserror(lm, xy, npoints, _state)/(double)npoints; - return result; -} - - -/************************************************************************* -RMS error on the test set - -INPUT PARAMETERS: - LM - logit model - XY - test set - NPoints - test set size - -RESULT: - root mean square error (error when estimating posterior probabilities). - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -double mnlrmserror(logitmodel* lm, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - double relcls; - double avgce; - double rms; - double avg; - double avgrel; - double result; - - - ae_assert(ae_round(lm->w.ptr.p_double[1], _state)==logit_logitvnum, "MNLRMSError: Incorrect MNL version!", _state); - logit_mnlallerrors(lm, xy, npoints, &relcls, &avgce, &rms, &avg, &avgrel, _state); - result = rms; - return result; -} - - -/************************************************************************* -Average error on the test set - -INPUT PARAMETERS: - LM - logit model - XY - test set - NPoints - test set size - -RESULT: - average error (error when estimating posterior probabilities). - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -double mnlavgerror(logitmodel* lm, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - double relcls; - double avgce; - double rms; - double avg; - double avgrel; - double result; - - - ae_assert(ae_round(lm->w.ptr.p_double[1], _state)==logit_logitvnum, "MNLRMSError: Incorrect MNL version!", _state); - logit_mnlallerrors(lm, xy, npoints, &relcls, &avgce, &rms, &avg, &avgrel, _state); - result = avg; - return result; -} - - -/************************************************************************* -Average relative error on the test set - -INPUT PARAMETERS: - LM - logit model - XY - test set - NPoints - test set size - -RESULT: - average relative error (error when estimating posterior probabilities). - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -double mnlavgrelerror(logitmodel* lm, - /* Real */ ae_matrix* xy, - ae_int_t ssize, - ae_state *_state) -{ - double relcls; - double avgce; - double rms; - double avg; - double avgrel; - double result; - - - ae_assert(ae_round(lm->w.ptr.p_double[1], _state)==logit_logitvnum, "MNLRMSError: Incorrect MNL version!", _state); - logit_mnlallerrors(lm, xy, ssize, &relcls, &avgce, &rms, &avg, &avgrel, _state); - result = avgrel; - return result; -} - - -/************************************************************************* -Classification error on test set = MNLRelClsError*NPoints - - -- ALGLIB -- - Copyright 10.09.2008 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mnlclserror(logitmodel* lm, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nvars; - ae_int_t nclasses; - ae_int_t i; - ae_int_t j; - ae_vector workx; - ae_vector worky; - ae_int_t nmax; - ae_int_t result; - - ae_frame_make(_state, &_frame_block); - memset(&workx, 0, sizeof(workx)); - memset(&worky, 0, sizeof(worky)); - ae_vector_init(&workx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&worky, 0, DT_REAL, _state, ae_true); - - ae_assert(ae_fp_eq(lm->w.ptr.p_double[1],(double)(logit_logitvnum)), "MNLClsError: unexpected model version", _state); - nvars = ae_round(lm->w.ptr.p_double[2], _state); - nclasses = ae_round(lm->w.ptr.p_double[3], _state); - ae_vector_set_length(&workx, nvars-1+1, _state); - ae_vector_set_length(&worky, nclasses-1+1, _state); - result = 0; - for(i=0; i<=npoints-1; i++) - { - - /* - * Process - */ - ae_v_move(&workx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - mnlprocess(lm, &workx, &worky, _state); - - /* - * Logit version of the answer - */ - nmax = 0; - for(j=0; j<=nclasses-1; j++) - { - if( ae_fp_greater(worky.ptr.p_double[j],worky.ptr.p_double[nmax]) ) - { - nmax = j; - } - } - - /* - * compare - */ - if( nmax!=ae_round(xy->ptr.pp_double[i][nvars], _state) ) - { - result = result+1; - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Internal subroutine. Places exponents of the anti-overflow shifted -internal linear outputs into the service part of the W array. -*************************************************************************/ -static void logit_mnliexp(/* Real */ ae_vector* w, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t nvars; - ae_int_t nclasses; - ae_int_t offs; - ae_int_t i; - ae_int_t i1; - double v; - double mx; - - - ae_assert(ae_fp_eq(w->ptr.p_double[1],(double)(logit_logitvnum)), "LOGIT: unexpected model version", _state); - nvars = ae_round(w->ptr.p_double[2], _state); - nclasses = ae_round(w->ptr.p_double[3], _state); - offs = ae_round(w->ptr.p_double[4], _state); - i1 = offs+(nvars+1)*(nclasses-1); - for(i=0; i<=nclasses-2; i++) - { - v = ae_v_dotproduct(&w->ptr.p_double[offs+i*(nvars+1)], 1, &x->ptr.p_double[0], 1, ae_v_len(offs+i*(nvars+1),offs+i*(nvars+1)+nvars-1)); - w->ptr.p_double[i1+i] = v+w->ptr.p_double[offs+i*(nvars+1)+nvars]; - } - w->ptr.p_double[i1+nclasses-1] = (double)(0); - mx = (double)(0); - for(i=i1; i<=i1+nclasses-1; i++) - { - mx = ae_maxreal(mx, w->ptr.p_double[i], _state); - } - for(i=i1; i<=i1+nclasses-1; i++) - { - w->ptr.p_double[i] = ae_exp(w->ptr.p_double[i]-mx, _state); - } -} - - -/************************************************************************* -Calculation of all types of errors - - -- ALGLIB -- - Copyright 30.08.2008 by Bochkanov Sergey -*************************************************************************/ -static void logit_mnlallerrors(logitmodel* lm, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double* relcls, - double* avgce, - double* rms, - double* avg, - double* avgrel, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nvars; - ae_int_t nclasses; - ae_int_t i; - ae_vector buf; - ae_vector workx; - ae_vector y; - ae_vector dy; - - ae_frame_make(_state, &_frame_block); - memset(&buf, 0, sizeof(buf)); - memset(&workx, 0, sizeof(workx)); - memset(&y, 0, sizeof(y)); - memset(&dy, 0, sizeof(dy)); - *relcls = 0; - *avgce = 0; - *rms = 0; - *avg = 0; - *avgrel = 0; - ae_vector_init(&buf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&workx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dy, 0, DT_REAL, _state, ae_true); - - ae_assert(ae_round(lm->w.ptr.p_double[1], _state)==logit_logitvnum, "MNL unit: Incorrect MNL version!", _state); - nvars = ae_round(lm->w.ptr.p_double[2], _state); - nclasses = ae_round(lm->w.ptr.p_double[3], _state); - ae_vector_set_length(&workx, nvars-1+1, _state); - ae_vector_set_length(&y, nclasses-1+1, _state); - ae_vector_set_length(&dy, 0+1, _state); - dserrallocate(nclasses, &buf, _state); - for(i=0; i<=npoints-1; i++) - { - ae_v_move(&workx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - mnlprocess(lm, &workx, &y, _state); - dy.ptr.p_double[0] = xy->ptr.pp_double[i][nvars]; - dserraccumulate(&buf, &y, &dy, _state); - } - dserrfinish(&buf, _state); - *relcls = buf.ptr.p_double[0]; - *avgce = buf.ptr.p_double[1]; - *rms = buf.ptr.p_double[2]; - *avg = buf.ptr.p_double[3]; - *avgrel = buf.ptr.p_double[4]; - ae_frame_leave(_state); -} - - -/************************************************************************* -THE PURPOSE OF MCSRCH IS TO FIND A STEP WHICH SATISFIES A SUFFICIENT -DECREASE CONDITION AND A CURVATURE CONDITION. - -AT EACH STAGE THE SUBROUTINE UPDATES AN INTERVAL OF UNCERTAINTY WITH -ENDPOINTS STX AND STY. THE INTERVAL OF UNCERTAINTY IS INITIALLY CHOSEN -SO THAT IT CONTAINS A MINIMIZER OF THE MODIFIED FUNCTION - - F(X+STP*S) - F(X) - FTOL*STP*(GRADF(X)'S). - -IF A STEP IS OBTAINED FOR WHICH THE MODIFIED FUNCTION HAS A NONPOSITIVE -FUNCTION VALUE AND NONNEGATIVE DERIVATIVE, THEN THE INTERVAL OF -UNCERTAINTY IS CHOSEN SO THAT IT CONTAINS A MINIMIZER OF F(X+STP*S). - -THE ALGORITHM IS DESIGNED TO FIND A STEP WHICH SATISFIES THE SUFFICIENT -DECREASE CONDITION - - F(X+STP*S) .LE. F(X) + FTOL*STP*(GRADF(X)'S), - -AND THE CURVATURE CONDITION - - ABS(GRADF(X+STP*S)'S)) .LE. GTOL*ABS(GRADF(X)'S). - -IF FTOL IS LESS THAN GTOL AND IF, FOR EXAMPLE, THE FUNCTION IS BOUNDED -BELOW, THEN THERE IS ALWAYS A STEP WHICH SATISFIES BOTH CONDITIONS. -IF NO STEP CAN BE FOUND WHICH SATISFIES BOTH CONDITIONS, THEN THE -ALGORITHM USUALLY STOPS WHEN ROUNDING ERRORS PREVENT FURTHER PROGRESS. -IN THIS CASE STP ONLY SATISFIES THE SUFFICIENT DECREASE CONDITION. - -PARAMETERS DESCRIPRION - -N IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER OF VARIABLES. - -X IS AN ARRAY OF LENGTH N. ON INPUT IT MUST CONTAIN THE BASE POINT FOR -THE LINE SEARCH. ON OUTPUT IT CONTAINS X+STP*S. - -F IS A VARIABLE. ON INPUT IT MUST CONTAIN THE VALUE OF F AT X. ON OUTPUT -IT CONTAINS THE VALUE OF F AT X + STP*S. - -G IS AN ARRAY OF LENGTH N. ON INPUT IT MUST CONTAIN THE GRADIENT OF F AT X. -ON OUTPUT IT CONTAINS THE GRADIENT OF F AT X + STP*S. - -S IS AN INPUT ARRAY OF LENGTH N WHICH SPECIFIES THE SEARCH DIRECTION. - -STP IS A NONNEGATIVE VARIABLE. ON INPUT STP CONTAINS AN INITIAL ESTIMATE -OF A SATISFACTORY STEP. ON OUTPUT STP CONTAINS THE FINAL ESTIMATE. - -FTOL AND GTOL ARE NONNEGATIVE INPUT VARIABLES. TERMINATION OCCURS WHEN THE -SUFFICIENT DECREASE CONDITION AND THE DIRECTIONAL DERIVATIVE CONDITION ARE -SATISFIED. - -XTOL IS A NONNEGATIVE INPUT VARIABLE. TERMINATION OCCURS WHEN THE RELATIVE -WIDTH OF THE INTERVAL OF UNCERTAINTY IS AT MOST XTOL. - -STPMIN AND STPMAX ARE NONNEGATIVE INPUT VARIABLES WHICH SPECIFY LOWER AND -UPPER BOUNDS FOR THE STEP. - -MAXFEV IS A POSITIVE INTEGER INPUT VARIABLE. TERMINATION OCCURS WHEN THE -NUMBER OF CALLS TO FCN IS AT LEAST MAXFEV BY THE END OF AN ITERATION. - -INFO IS AN INTEGER OUTPUT VARIABLE SET AS FOLLOWS: - INFO = 0 IMPROPER INPUT PARAMETERS. - - INFO = 1 THE SUFFICIENT DECREASE CONDITION AND THE - DIRECTIONAL DERIVATIVE CONDITION HOLD. - - INFO = 2 RELATIVE WIDTH OF THE INTERVAL OF UNCERTAINTY - IS AT MOST XTOL. - - INFO = 3 NUMBER OF CALLS TO FCN HAS REACHED MAXFEV. - - INFO = 4 THE STEP IS AT THE LOWER BOUND STPMIN. - - INFO = 5 THE STEP IS AT THE UPPER BOUND STPMAX. - - INFO = 6 ROUNDING ERRORS PREVENT FURTHER PROGRESS. - THERE MAY NOT BE A STEP WHICH SATISFIES THE - SUFFICIENT DECREASE AND CURVATURE CONDITIONS. - TOLERANCES MAY BE TOO SMALL. - -NFEV IS AN INTEGER OUTPUT VARIABLE SET TO THE NUMBER OF CALLS TO FCN. - -WA IS A WORK ARRAY OF LENGTH N. - -ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JUNE 1983 -JORGE J. MORE', DAVID J. THUENTE -*************************************************************************/ -static void logit_mnlmcsrch(ae_int_t n, - /* Real */ ae_vector* x, - double* f, - /* Real */ ae_vector* g, - /* Real */ ae_vector* s, - double* stp, - ae_int_t* info, - ae_int_t* nfev, - /* Real */ ae_vector* wa, - logitmcstate* state, - ae_int_t* stage, - ae_state *_state) -{ - double v; - double p5; - double p66; - double zero; - - - - /* - * init - */ - p5 = 0.5; - p66 = 0.66; - state->xtrapf = 4.0; - zero = (double)(0); - - /* - * Main cycle - */ - for(;;) - { - if( *stage==0 ) - { - - /* - * NEXT - */ - *stage = 2; - continue; - } - if( *stage==2 ) - { - state->infoc = 1; - *info = 0; - - /* - * CHECK THE INPUT PARAMETERS FOR ERRORS. - */ - if( ((((((n<=0||ae_fp_less_eq(*stp,(double)(0)))||ae_fp_less(logit_ftol,(double)(0)))||ae_fp_less(logit_gtol,zero))||ae_fp_less(logit_xtol,zero))||ae_fp_less(logit_stpmin,zero))||ae_fp_less(logit_stpmax,logit_stpmin))||logit_maxfev<=0 ) - { - *stage = 0; - return; - } - - /* - * COMPUTE THE INITIAL GRADIENT IN THE SEARCH DIRECTION - * AND CHECK THAT S IS A DESCENT DIRECTION. - */ - v = ae_v_dotproduct(&g->ptr.p_double[0], 1, &s->ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->dginit = v; - if( ae_fp_greater_eq(state->dginit,(double)(0)) ) - { - *stage = 0; - return; - } - - /* - * INITIALIZE LOCAL VARIABLES. - */ - state->brackt = ae_false; - state->stage1 = ae_true; - *nfev = 0; - state->finit = *f; - state->dgtest = logit_ftol*state->dginit; - state->width = logit_stpmax-logit_stpmin; - state->width1 = state->width/p5; - ae_v_move(&wa->ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - - /* - * THE VARIABLES STX, FX, DGX CONTAIN THE VALUES OF THE STEP, - * FUNCTION, AND DIRECTIONAL DERIVATIVE AT THE BEST STEP. - * THE VARIABLES STY, FY, DGY CONTAIN THE VALUE OF THE STEP, - * FUNCTION, AND DERIVATIVE AT THE OTHER ENDPOINT OF - * THE INTERVAL OF UNCERTAINTY. - * THE VARIABLES STP, F, DG CONTAIN THE VALUES OF THE STEP, - * FUNCTION, AND DERIVATIVE AT THE CURRENT STEP. - */ - state->stx = (double)(0); - state->fx = state->finit; - state->dgx = state->dginit; - state->sty = (double)(0); - state->fy = state->finit; - state->dgy = state->dginit; - - /* - * NEXT - */ - *stage = 3; - continue; - } - if( *stage==3 ) - { - - /* - * START OF ITERATION. - * - * SET THE MINIMUM AND MAXIMUM STEPS TO CORRESPOND - * TO THE PRESENT INTERVAL OF UNCERTAINTY. - */ - if( state->brackt ) - { - if( ae_fp_less(state->stx,state->sty) ) - { - state->stmin = state->stx; - state->stmax = state->sty; - } - else - { - state->stmin = state->sty; - state->stmax = state->stx; - } - } - else - { - state->stmin = state->stx; - state->stmax = *stp+state->xtrapf*(*stp-state->stx); - } - - /* - * FORCE THE STEP TO BE WITHIN THE BOUNDS STPMAX AND STPMIN. - */ - if( ae_fp_greater(*stp,logit_stpmax) ) - { - *stp = logit_stpmax; - } - if( ae_fp_less(*stp,logit_stpmin) ) - { - *stp = logit_stpmin; - } - - /* - * IF AN UNUSUAL TERMINATION IS TO OCCUR THEN LET - * STP BE THE LOWEST POINT OBTAINED SO FAR. - */ - if( (((state->brackt&&(ae_fp_less_eq(*stp,state->stmin)||ae_fp_greater_eq(*stp,state->stmax)))||*nfev>=logit_maxfev-1)||state->infoc==0)||(state->brackt&&ae_fp_less_eq(state->stmax-state->stmin,logit_xtol*state->stmax)) ) - { - *stp = state->stx; - } - - /* - * EVALUATE THE FUNCTION AND GRADIENT AT STP - * AND COMPUTE THE DIRECTIONAL DERIVATIVE. - */ - ae_v_move(&x->ptr.p_double[0], 1, &wa->ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_addd(&x->ptr.p_double[0], 1, &s->ptr.p_double[0], 1, ae_v_len(0,n-1), *stp); - - /* - * NEXT - */ - *stage = 4; - return; - } - if( *stage==4 ) - { - *info = 0; - *nfev = *nfev+1; - v = ae_v_dotproduct(&g->ptr.p_double[0], 1, &s->ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->dg = v; - state->ftest1 = state->finit+*stp*state->dgtest; - - /* - * TEST FOR CONVERGENCE. - */ - if( (state->brackt&&(ae_fp_less_eq(*stp,state->stmin)||ae_fp_greater_eq(*stp,state->stmax)))||state->infoc==0 ) - { - *info = 6; - } - if( (ae_fp_eq(*stp,logit_stpmax)&&ae_fp_less_eq(*f,state->ftest1))&&ae_fp_less_eq(state->dg,state->dgtest) ) - { - *info = 5; - } - if( ae_fp_eq(*stp,logit_stpmin)&&(ae_fp_greater(*f,state->ftest1)||ae_fp_greater_eq(state->dg,state->dgtest)) ) - { - *info = 4; - } - if( *nfev>=logit_maxfev ) - { - *info = 3; - } - if( state->brackt&&ae_fp_less_eq(state->stmax-state->stmin,logit_xtol*state->stmax) ) - { - *info = 2; - } - if( ae_fp_less_eq(*f,state->ftest1)&&ae_fp_less_eq(ae_fabs(state->dg, _state),-logit_gtol*state->dginit) ) - { - *info = 1; - } - - /* - * CHECK FOR TERMINATION. - */ - if( *info!=0 ) - { - *stage = 0; - return; - } - - /* - * IN THE FIRST STAGE WE SEEK A STEP FOR WHICH THE MODIFIED - * FUNCTION HAS A NONPOSITIVE VALUE AND NONNEGATIVE DERIVATIVE. - */ - if( (state->stage1&&ae_fp_less_eq(*f,state->ftest1))&&ae_fp_greater_eq(state->dg,ae_minreal(logit_ftol, logit_gtol, _state)*state->dginit) ) - { - state->stage1 = ae_false; - } - - /* - * A MODIFIED FUNCTION IS USED TO PREDICT THE STEP ONLY IF - * WE HAVE NOT OBTAINED A STEP FOR WHICH THE MODIFIED - * FUNCTION HAS A NONPOSITIVE FUNCTION VALUE AND NONNEGATIVE - * DERIVATIVE, AND IF A LOWER FUNCTION VALUE HAS BEEN - * OBTAINED BUT THE DECREASE IS NOT SUFFICIENT. - */ - if( (state->stage1&&ae_fp_less_eq(*f,state->fx))&&ae_fp_greater(*f,state->ftest1) ) - { - - /* - * DEFINE THE MODIFIED FUNCTION AND DERIVATIVE VALUES. - */ - state->fm = *f-*stp*state->dgtest; - state->fxm = state->fx-state->stx*state->dgtest; - state->fym = state->fy-state->sty*state->dgtest; - state->dgm = state->dg-state->dgtest; - state->dgxm = state->dgx-state->dgtest; - state->dgym = state->dgy-state->dgtest; - - /* - * CALL CSTEP TO UPDATE THE INTERVAL OF UNCERTAINTY - * AND TO COMPUTE THE NEW STEP. - */ - logit_mnlmcstep(&state->stx, &state->fxm, &state->dgxm, &state->sty, &state->fym, &state->dgym, stp, state->fm, state->dgm, &state->brackt, state->stmin, state->stmax, &state->infoc, _state); - - /* - * RESET THE FUNCTION AND GRADIENT VALUES FOR F. - */ - state->fx = state->fxm+state->stx*state->dgtest; - state->fy = state->fym+state->sty*state->dgtest; - state->dgx = state->dgxm+state->dgtest; - state->dgy = state->dgym+state->dgtest; - } - else - { - - /* - * CALL MCSTEP TO UPDATE THE INTERVAL OF UNCERTAINTY - * AND TO COMPUTE THE NEW STEP. - */ - logit_mnlmcstep(&state->stx, &state->fx, &state->dgx, &state->sty, &state->fy, &state->dgy, stp, *f, state->dg, &state->brackt, state->stmin, state->stmax, &state->infoc, _state); - } - - /* - * FORCE A SUFFICIENT DECREASE IN THE SIZE OF THE - * INTERVAL OF UNCERTAINTY. - */ - if( state->brackt ) - { - if( ae_fp_greater_eq(ae_fabs(state->sty-state->stx, _state),p66*state->width1) ) - { - *stp = state->stx+p5*(state->sty-state->stx); - } - state->width1 = state->width; - state->width = ae_fabs(state->sty-state->stx, _state); - } - - /* - * NEXT. - */ - *stage = 3; - continue; - } - } -} - - -static void logit_mnlmcstep(double* stx, - double* fx, - double* dx, - double* sty, - double* fy, - double* dy, - double* stp, - double fp, - double dp, - ae_bool* brackt, - double stmin, - double stmax, - ae_int_t* info, - ae_state *_state) -{ - ae_bool bound; - double gamma; - double p; - double q; - double r; - double s; - double sgnd; - double stpc; - double stpf; - double stpq; - double theta; - - - *info = 0; - - /* - * CHECK THE INPUT PARAMETERS FOR ERRORS. - */ - if( ((*brackt&&(ae_fp_less_eq(*stp,ae_minreal(*stx, *sty, _state))||ae_fp_greater_eq(*stp,ae_maxreal(*stx, *sty, _state))))||ae_fp_greater_eq(*dx*(*stp-(*stx)),(double)(0)))||ae_fp_less(stmax,stmin) ) - { - return; - } - - /* - * DETERMINE IF THE DERIVATIVES HAVE OPPOSITE SIGN. - */ - sgnd = dp*(*dx/ae_fabs(*dx, _state)); - - /* - * FIRST CASE. A HIGHER FUNCTION VALUE. - * THE MINIMUM IS BRACKETED. IF THE CUBIC STEP IS CLOSER - * TO STX THAN THE QUADRATIC STEP, THE CUBIC STEP IS TAKEN, - * ELSE THE AVERAGE OF THE CUBIC AND QUADRATIC STEPS IS TAKEN. - */ - if( ae_fp_greater(fp,*fx) ) - { - *info = 1; - bound = ae_true; - theta = 3*(*fx-fp)/(*stp-(*stx))+(*dx)+dp; - s = ae_maxreal(ae_fabs(theta, _state), ae_maxreal(ae_fabs(*dx, _state), ae_fabs(dp, _state), _state), _state); - gamma = s*ae_sqrt(ae_sqr(theta/s, _state)-*dx/s*(dp/s), _state); - if( ae_fp_less(*stp,*stx) ) - { - gamma = -gamma; - } - p = gamma-(*dx)+theta; - q = gamma-(*dx)+gamma+dp; - r = p/q; - stpc = *stx+r*(*stp-(*stx)); - stpq = *stx+*dx/((*fx-fp)/(*stp-(*stx))+(*dx))/2*(*stp-(*stx)); - if( ae_fp_less(ae_fabs(stpc-(*stx), _state),ae_fabs(stpq-(*stx), _state)) ) - { - stpf = stpc; - } - else - { - stpf = stpc+(stpq-stpc)/2; - } - *brackt = ae_true; - } - else - { - if( ae_fp_less(sgnd,(double)(0)) ) - { - - /* - * SECOND CASE. A LOWER FUNCTION VALUE AND DERIVATIVES OF - * OPPOSITE SIGN. THE MINIMUM IS BRACKETED. IF THE CUBIC - * STEP IS CLOSER TO STX THAN THE QUADRATIC (SECANT) STEP, - * THE CUBIC STEP IS TAKEN, ELSE THE QUADRATIC STEP IS TAKEN. - */ - *info = 2; - bound = ae_false; - theta = 3*(*fx-fp)/(*stp-(*stx))+(*dx)+dp; - s = ae_maxreal(ae_fabs(theta, _state), ae_maxreal(ae_fabs(*dx, _state), ae_fabs(dp, _state), _state), _state); - gamma = s*ae_sqrt(ae_sqr(theta/s, _state)-*dx/s*(dp/s), _state); - if( ae_fp_greater(*stp,*stx) ) - { - gamma = -gamma; - } - p = gamma-dp+theta; - q = gamma-dp+gamma+(*dx); - r = p/q; - stpc = *stp+r*(*stx-(*stp)); - stpq = *stp+dp/(dp-(*dx))*(*stx-(*stp)); - if( ae_fp_greater(ae_fabs(stpc-(*stp), _state),ae_fabs(stpq-(*stp), _state)) ) - { - stpf = stpc; - } - else - { - stpf = stpq; - } - *brackt = ae_true; - } - else - { - if( ae_fp_less(ae_fabs(dp, _state),ae_fabs(*dx, _state)) ) - { - - /* - * THIRD CASE. A LOWER FUNCTION VALUE, DERIVATIVES OF THE - * SAME SIGN, AND THE MAGNITUDE OF THE DERIVATIVE DECREASES. - * THE CUBIC STEP IS ONLY USED IF THE CUBIC TENDS TO INFINITY - * IN THE DIRECTION OF THE STEP OR IF THE MINIMUM OF THE CUBIC - * IS BEYOND STP. OTHERWISE THE CUBIC STEP IS DEFINED TO BE - * EITHER STPMIN OR STPMAX. THE QUADRATIC (SECANT) STEP IS ALSO - * COMPUTED AND IF THE MINIMUM IS BRACKETED THEN THE THE STEP - * CLOSEST TO STX IS TAKEN, ELSE THE STEP FARTHEST AWAY IS TAKEN. - */ - *info = 3; - bound = ae_true; - theta = 3*(*fx-fp)/(*stp-(*stx))+(*dx)+dp; - s = ae_maxreal(ae_fabs(theta, _state), ae_maxreal(ae_fabs(*dx, _state), ae_fabs(dp, _state), _state), _state); - - /* - * THE CASE GAMMA = 0 ONLY ARISES IF THE CUBIC DOES NOT TEND - * TO INFINITY IN THE DIRECTION OF THE STEP. - */ - gamma = s*ae_sqrt(ae_maxreal((double)(0), ae_sqr(theta/s, _state)-*dx/s*(dp/s), _state), _state); - if( ae_fp_greater(*stp,*stx) ) - { - gamma = -gamma; - } - p = gamma-dp+theta; - q = gamma+(*dx-dp)+gamma; - r = p/q; - if( ae_fp_less(r,(double)(0))&&ae_fp_neq(gamma,(double)(0)) ) - { - stpc = *stp+r*(*stx-(*stp)); - } - else - { - if( ae_fp_greater(*stp,*stx) ) - { - stpc = stmax; - } - else - { - stpc = stmin; - } - } - stpq = *stp+dp/(dp-(*dx))*(*stx-(*stp)); - if( *brackt ) - { - if( ae_fp_less(ae_fabs(*stp-stpc, _state),ae_fabs(*stp-stpq, _state)) ) - { - stpf = stpc; - } - else - { - stpf = stpq; - } - } - else - { - if( ae_fp_greater(ae_fabs(*stp-stpc, _state),ae_fabs(*stp-stpq, _state)) ) - { - stpf = stpc; - } - else - { - stpf = stpq; - } - } - } - else - { - - /* - * FOURTH CASE. A LOWER FUNCTION VALUE, DERIVATIVES OF THE - * SAME SIGN, AND THE MAGNITUDE OF THE DERIVATIVE DOES - * NOT DECREASE. IF THE MINIMUM IS NOT BRACKETED, THE STEP - * IS EITHER STPMIN OR STPMAX, ELSE THE CUBIC STEP IS TAKEN. - */ - *info = 4; - bound = ae_false; - if( *brackt ) - { - theta = 3*(fp-(*fy))/(*sty-(*stp))+(*dy)+dp; - s = ae_maxreal(ae_fabs(theta, _state), ae_maxreal(ae_fabs(*dy, _state), ae_fabs(dp, _state), _state), _state); - gamma = s*ae_sqrt(ae_sqr(theta/s, _state)-*dy/s*(dp/s), _state); - if( ae_fp_greater(*stp,*sty) ) - { - gamma = -gamma; - } - p = gamma-dp+theta; - q = gamma-dp+gamma+(*dy); - r = p/q; - stpc = *stp+r*(*sty-(*stp)); - stpf = stpc; - } - else - { - if( ae_fp_greater(*stp,*stx) ) - { - stpf = stmax; - } - else - { - stpf = stmin; - } - } - } - } - } - - /* - * UPDATE THE INTERVAL OF UNCERTAINTY. THIS UPDATE DOES NOT - * DEPEND ON THE NEW STEP OR THE CASE ANALYSIS ABOVE. - */ - if( ae_fp_greater(fp,*fx) ) - { - *sty = *stp; - *fy = fp; - *dy = dp; - } - else - { - if( ae_fp_less(sgnd,0.0) ) - { - *sty = *stx; - *fy = *fx; - *dy = *dx; - } - *stx = *stp; - *fx = fp; - *dx = dp; - } - - /* - * COMPUTE THE NEW STEP AND SAFEGUARD IT. - */ - stpf = ae_minreal(stmax, stpf, _state); - stpf = ae_maxreal(stmin, stpf, _state); - *stp = stpf; - if( *brackt&&bound ) - { - if( ae_fp_greater(*sty,*stx) ) - { - *stp = ae_minreal(*stx+0.66*(*sty-(*stx)), *stp, _state); - } - else - { - *stp = ae_maxreal(*stx+0.66*(*sty-(*stx)), *stp, _state); - } - } -} - - -void _logitmodel_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - logitmodel *p = (logitmodel*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->w, 0, DT_REAL, _state, make_automatic); -} - - -void _logitmodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - logitmodel *dst = (logitmodel*)_dst; - logitmodel *src = (logitmodel*)_src; - ae_vector_init_copy(&dst->w, &src->w, _state, make_automatic); -} - - -void _logitmodel_clear(void* _p) -{ - logitmodel *p = (logitmodel*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->w); -} - - -void _logitmodel_destroy(void* _p) -{ - logitmodel *p = (logitmodel*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->w); -} - - -void _logitmcstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - logitmcstate *p = (logitmcstate*)_p; - ae_touch_ptr((void*)p); -} - - -void _logitmcstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - logitmcstate *dst = (logitmcstate*)_dst; - logitmcstate *src = (logitmcstate*)_src; - dst->brackt = src->brackt; - dst->stage1 = src->stage1; - dst->infoc = src->infoc; - dst->dg = src->dg; - dst->dgm = src->dgm; - dst->dginit = src->dginit; - dst->dgtest = src->dgtest; - dst->dgx = src->dgx; - dst->dgxm = src->dgxm; - dst->dgy = src->dgy; - dst->dgym = src->dgym; - dst->finit = src->finit; - dst->ftest1 = src->ftest1; - dst->fm = src->fm; - dst->fx = src->fx; - dst->fxm = src->fxm; - dst->fy = src->fy; - dst->fym = src->fym; - dst->stx = src->stx; - dst->sty = src->sty; - dst->stmin = src->stmin; - dst->stmax = src->stmax; - dst->width = src->width; - dst->width1 = src->width1; - dst->xtrapf = src->xtrapf; -} - - -void _logitmcstate_clear(void* _p) -{ - logitmcstate *p = (logitmcstate*)_p; - ae_touch_ptr((void*)p); -} - - -void _logitmcstate_destroy(void* _p) -{ - logitmcstate *p = (logitmcstate*)_p; - ae_touch_ptr((void*)p); -} - - -void _mnlreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - mnlreport *p = (mnlreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _mnlreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - mnlreport *dst = (mnlreport*)_dst; - mnlreport *src = (mnlreport*)_src; - dst->ngrad = src->ngrad; - dst->nhess = src->nhess; -} - - -void _mnlreport_clear(void* _p) -{ - mnlreport *p = (mnlreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _mnlreport_destroy(void* _p) -{ - mnlreport *p = (mnlreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_MCPD) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -DESCRIPTION: - -This function creates MCPD (Markov Chains for Population Data) solver. - -This solver can be used to find transition matrix P for N-dimensional -prediction problem where transition from X[i] to X[i+1] is modelled as - X[i+1] = P*X[i] -where X[i] and X[i+1] are N-dimensional population vectors (components of -each X are non-negative), and P is a N*N transition matrix (elements of P -are non-negative, each column sums to 1.0). - -Such models arise when when: -* there is some population of individuals -* individuals can have different states -* individuals can transit from one state to another -* population size is constant, i.e. there is no new individuals and no one - leaves population -* you want to model transitions of individuals from one state into another - -USAGE: - -Here we give very brief outline of the MCPD. We strongly recommend you to -read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide -on data analysis which is available at http://www.alglib.net/dataanalysis/ - -1. User initializes algorithm state with MCPDCreate() call - -2. User adds one or more tracks - sequences of states which describe - evolution of a system being modelled from different starting conditions - -3. User may add optional boundary, equality and/or linear constraints on - the coefficients of P by calling one of the following functions: - * MCPDSetEC() to set equality constraints - * MCPDSetBC() to set bound constraints - * MCPDSetLC() to set linear constraints - -4. Optionally, user may set custom weights for prediction errors (by - default, algorithm assigns non-equal, automatically chosen weights for - errors in the prediction of different components of X). It can be done - with a call of MCPDSetPredictionWeights() function. - -5. User calls MCPDSolve() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. - -6. User calls MCPDResults() to get solution - -INPUT PARAMETERS: - N - problem dimension, N>=1 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdcreate(ae_int_t n, mcpdstate* s, ae_state *_state) -{ - - _mcpdstate_clear(s); - - ae_assert(n>=1, "MCPDCreate: N<1", _state); - mcpd_mcpdinit(n, -1, -1, s, _state); -} - - -/************************************************************************* -DESCRIPTION: - -This function is a specialized version of MCPDCreate() function, and we -recommend you to read comments for this function for general information -about MCPD solver. - -This function creates MCPD (Markov Chains for Population Data) solver -for "Entry-state" model, i.e. model where transition from X[i] to X[i+1] -is modelled as - X[i+1] = P*X[i] -where - X[i] and X[i+1] are N-dimensional state vectors - P is a N*N transition matrix -and one selected component of X[] is called "entry" state and is treated -in a special way: - system state always transits from "entry" state to some another state - system state can not transit from any state into "entry" state -Such conditions basically mean that row of P which corresponds to "entry" -state is zero. - -Such models arise when: -* there is some population of individuals -* individuals can have different states -* individuals can transit from one state to another -* population size is NOT constant - at every moment of time there is some - (unpredictable) amount of "new" individuals, which can transit into one - of the states at the next turn, but still no one leaves population -* you want to model transitions of individuals from one state into another -* but you do NOT want to predict amount of "new" individuals because it - does not depends on individuals already present (hence system can not - transit INTO entry state - it can only transit FROM it). - -This model is discussed in more details in the ALGLIB User Guide (see -http://www.alglib.net/dataanalysis/ for more data). - -INPUT PARAMETERS: - N - problem dimension, N>=2 - EntryState- index of entry state, in 0..N-1 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdcreateentry(ae_int_t n, - ae_int_t entrystate, - mcpdstate* s, - ae_state *_state) -{ - - _mcpdstate_clear(s); - - ae_assert(n>=2, "MCPDCreateEntry: N<2", _state); - ae_assert(entrystate>=0, "MCPDCreateEntry: EntryState<0", _state); - ae_assert(entrystate=N", _state); - mcpd_mcpdinit(n, entrystate, -1, s, _state); -} - - -/************************************************************************* -DESCRIPTION: - -This function is a specialized version of MCPDCreate() function, and we -recommend you to read comments for this function for general information -about MCPD solver. - -This function creates MCPD (Markov Chains for Population Data) solver -for "Exit-state" model, i.e. model where transition from X[i] to X[i+1] -is modelled as - X[i+1] = P*X[i] -where - X[i] and X[i+1] are N-dimensional state vectors - P is a N*N transition matrix -and one selected component of X[] is called "exit" state and is treated -in a special way: - system state can transit from any state into "exit" state - system state can not transit from "exit" state into any other state - transition operator discards "exit" state (makes it zero at each turn) -Such conditions basically mean that column of P which corresponds to -"exit" state is zero. Multiplication by such P may decrease sum of vector -components. - -Such models arise when: -* there is some population of individuals -* individuals can have different states -* individuals can transit from one state to another -* population size is NOT constant - individuals can move into "exit" state - and leave population at the next turn, but there are no new individuals -* amount of individuals which leave population can be predicted -* you want to model transitions of individuals from one state into another - (including transitions into the "exit" state) - -This model is discussed in more details in the ALGLIB User Guide (see -http://www.alglib.net/dataanalysis/ for more data). - -INPUT PARAMETERS: - N - problem dimension, N>=2 - ExitState- index of exit state, in 0..N-1 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdcreateexit(ae_int_t n, - ae_int_t exitstate, - mcpdstate* s, - ae_state *_state) -{ - - _mcpdstate_clear(s); - - ae_assert(n>=2, "MCPDCreateExit: N<2", _state); - ae_assert(exitstate>=0, "MCPDCreateExit: ExitState<0", _state); - ae_assert(exitstate=N", _state); - mcpd_mcpdinit(n, -1, exitstate, s, _state); -} - - -/************************************************************************* -DESCRIPTION: - -This function is a specialized version of MCPDCreate() function, and we -recommend you to read comments for this function for general information -about MCPD solver. - -This function creates MCPD (Markov Chains for Population Data) solver -for "Entry-Exit-states" model, i.e. model where transition from X[i] to -X[i+1] is modelled as - X[i+1] = P*X[i] -where - X[i] and X[i+1] are N-dimensional state vectors - P is a N*N transition matrix -one selected component of X[] is called "entry" state and is treated in a -special way: - system state always transits from "entry" state to some another state - system state can not transit from any state into "entry" state -and another one component of X[] is called "exit" state and is treated in -a special way too: - system state can transit from any state into "exit" state - system state can not transit from "exit" state into any other state - transition operator discards "exit" state (makes it zero at each turn) -Such conditions basically mean that: - row of P which corresponds to "entry" state is zero - column of P which corresponds to "exit" state is zero -Multiplication by such P may decrease sum of vector components. - -Such models arise when: -* there is some population of individuals -* individuals can have different states -* individuals can transit from one state to another -* population size is NOT constant -* at every moment of time there is some (unpredictable) amount of "new" - individuals, which can transit into one of the states at the next turn -* some individuals can move (predictably) into "exit" state and leave - population at the next turn -* you want to model transitions of individuals from one state into another, - including transitions from the "entry" state and into the "exit" state. -* but you do NOT want to predict amount of "new" individuals because it - does not depends on individuals already present (hence system can not - transit INTO entry state - it can only transit FROM it). - -This model is discussed in more details in the ALGLIB User Guide (see -http://www.alglib.net/dataanalysis/ for more data). - -INPUT PARAMETERS: - N - problem dimension, N>=2 - EntryState- index of entry state, in 0..N-1 - ExitState- index of exit state, in 0..N-1 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdcreateentryexit(ae_int_t n, - ae_int_t entrystate, - ae_int_t exitstate, - mcpdstate* s, - ae_state *_state) -{ - - _mcpdstate_clear(s); - - ae_assert(n>=2, "MCPDCreateEntryExit: N<2", _state); - ae_assert(entrystate>=0, "MCPDCreateEntryExit: EntryState<0", _state); - ae_assert(entrystate=N", _state); - ae_assert(exitstate>=0, "MCPDCreateEntryExit: ExitState<0", _state); - ae_assert(exitstate=N", _state); - ae_assert(entrystate!=exitstate, "MCPDCreateEntryExit: EntryState=ExitState", _state); - mcpd_mcpdinit(n, entrystate, exitstate, s, _state); -} - - -/************************************************************************* -This function is used to add a track - sequence of system states at the -different moments of its evolution. - -You may add one or several tracks to the MCPD solver. In case you have -several tracks, they won't overwrite each other. For example, if you pass -two tracks, A1-A2-A3 (system at t=A+1, t=A+2 and t=A+3) and B1-B2-B3, then -solver will try to model transitions from t=A+1 to t=A+2, t=A+2 to t=A+3, -t=B+1 to t=B+2, t=B+2 to t=B+3. But it WONT mix these two tracks - i.e. it -wont try to model transition from t=A+3 to t=B+1. - -INPUT PARAMETERS: - S - solver - XY - track, array[K,N]: - * I-th row is a state at t=I - * elements of XY must be non-negative (exception will be - thrown on negative elements) - K - number of points in a track - * if given, only leading K rows of XY are used - * if not given, automatically determined from size of XY - -NOTES: - -1. Track may contain either proportional or population data: - * with proportional data all rows of XY must sum to 1.0, i.e. we have - proportions instead of absolute population values - * with population data rows of XY contain population counts and generally - do not sum to 1.0 (although they still must be non-negative) - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdaddtrack(mcpdstate* s, - /* Real */ ae_matrix* xy, - ae_int_t k, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t n; - double s0; - double s1; - - - n = s->n; - ae_assert(k>=0, "MCPDAddTrack: K<0", _state); - ae_assert(xy->cols>=n, "MCPDAddTrack: Cols(XY)rows>=k, "MCPDAddTrack: Rows(XY)ptr.pp_double[i][j],(double)(0)), "MCPDAddTrack: XY contains negative elements", _state); - } - } - if( k<2 ) - { - return; - } - if( s->data.rowsnpairs+k-1 ) - { - rmatrixresize(&s->data, ae_maxint(2*s->data.rows, s->npairs+k-1, _state), 2*n, _state); - } - for(i=0; i<=k-2; i++) - { - s0 = (double)(0); - s1 = (double)(0); - for(j=0; j<=n-1; j++) - { - if( s->states.ptr.p_int[j]>=0 ) - { - s0 = s0+xy->ptr.pp_double[i][j]; - } - if( s->states.ptr.p_int[j]<=0 ) - { - s1 = s1+xy->ptr.pp_double[i+1][j]; - } - } - if( ae_fp_greater(s0,(double)(0))&&ae_fp_greater(s1,(double)(0)) ) - { - for(j=0; j<=n-1; j++) - { - if( s->states.ptr.p_int[j]>=0 ) - { - s->data.ptr.pp_double[s->npairs][j] = xy->ptr.pp_double[i][j]/s0; - } - else - { - s->data.ptr.pp_double[s->npairs][j] = 0.0; - } - if( s->states.ptr.p_int[j]<=0 ) - { - s->data.ptr.pp_double[s->npairs][n+j] = xy->ptr.pp_double[i+1][j]/s1; - } - else - { - s->data.ptr.pp_double[s->npairs][n+j] = 0.0; - } - } - s->npairs = s->npairs+1; - } - } -} - - -/************************************************************************* -This function is used to add equality constraints on the elements of the -transition matrix P. - -MCPD solver has four types of constraints which can be placed on P: -* user-specified equality constraints (optional) -* user-specified bound constraints (optional) -* user-specified general linear constraints (optional) -* basic constraints (always present): - * non-negativity: P[i,j]>=0 - * consistency: every column of P sums to 1.0 - -Final constraints which are passed to the underlying optimizer are -calculated as intersection of all present constraints. For example, you -may specify boundary constraint on P[0,0] and equality one: - 0.1<=P[0,0]<=0.9 - P[0,0]=0.5 -Such combination of constraints will be silently reduced to their -intersection, which is P[0,0]=0.5. - -This function can be used to place equality constraints on arbitrary -subset of elements of P. Set of constraints is specified by EC, which may -contain either NAN's or finite numbers from [0,1]. NAN denotes absence of -constraint, finite number denotes equality constraint on specific element -of P. - -You can also use MCPDAddEC() function which allows to ADD equality -constraint for one element of P without changing constraints for other -elements. - -These functions (MCPDSetEC and MCPDAddEC) interact as follows: -* there is internal matrix of equality constraints which is stored in the - MCPD solver -* MCPDSetEC() replaces this matrix by another one (SET) -* MCPDAddEC() modifies one element of this matrix and leaves other ones - unchanged (ADD) -* thus MCPDAddEC() call preserves all modifications done by previous - calls, while MCPDSetEC() completely discards all changes done to the - equality constraints. - -INPUT PARAMETERS: - S - solver - EC - equality constraints, array[N,N]. Elements of EC can be - either NAN's or finite numbers from [0,1]. NAN denotes - absence of constraints, while finite value denotes - equality constraint on the corresponding element of P. - -NOTES: - -1. infinite values of EC will lead to exception being thrown. Values less -than 0.0 or greater than 1.0 will lead to error code being returned after -call to MCPDSolve(). - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdsetec(mcpdstate* s, - /* Real */ ae_matrix* ec, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t n; - - - n = s->n; - ae_assert(ec->cols>=n, "MCPDSetEC: Cols(EC)rows>=n, "MCPDSetEC: Rows(EC)ptr.pp_double[i][j], _state)||ae_isnan(ec->ptr.pp_double[i][j], _state), "MCPDSetEC: EC containts infinite elements", _state); - s->ec.ptr.pp_double[i][j] = ec->ptr.pp_double[i][j]; - } - } -} - - -/************************************************************************* -This function is used to add equality constraints on the elements of the -transition matrix P. - -MCPD solver has four types of constraints which can be placed on P: -* user-specified equality constraints (optional) -* user-specified bound constraints (optional) -* user-specified general linear constraints (optional) -* basic constraints (always present): - * non-negativity: P[i,j]>=0 - * consistency: every column of P sums to 1.0 - -Final constraints which are passed to the underlying optimizer are -calculated as intersection of all present constraints. For example, you -may specify boundary constraint on P[0,0] and equality one: - 0.1<=P[0,0]<=0.9 - P[0,0]=0.5 -Such combination of constraints will be silently reduced to their -intersection, which is P[0,0]=0.5. - -This function can be used to ADD equality constraint for one element of P -without changing constraints for other elements. - -You can also use MCPDSetEC() function which allows you to specify -arbitrary set of equality constraints in one call. - -These functions (MCPDSetEC and MCPDAddEC) interact as follows: -* there is internal matrix of equality constraints which is stored in the - MCPD solver -* MCPDSetEC() replaces this matrix by another one (SET) -* MCPDAddEC() modifies one element of this matrix and leaves other ones - unchanged (ADD) -* thus MCPDAddEC() call preserves all modifications done by previous - calls, while MCPDSetEC() completely discards all changes done to the - equality constraints. - -INPUT PARAMETERS: - S - solver - I - row index of element being constrained - J - column index of element being constrained - C - value (constraint for P[I,J]). Can be either NAN (no - constraint) or finite value from [0,1]. - -NOTES: - -1. infinite values of C will lead to exception being thrown. Values less -than 0.0 or greater than 1.0 will lead to error code being returned after -call to MCPDSolve(). - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdaddec(mcpdstate* s, - ae_int_t i, - ae_int_t j, - double c, - ae_state *_state) -{ - - - ae_assert(i>=0, "MCPDAddEC: I<0", _state); - ae_assert(in, "MCPDAddEC: I>=N", _state); - ae_assert(j>=0, "MCPDAddEC: J<0", _state); - ae_assert(jn, "MCPDAddEC: J>=N", _state); - ae_assert(ae_isnan(c, _state)||ae_isfinite(c, _state), "MCPDAddEC: C is not finite number or NAN", _state); - s->ec.ptr.pp_double[i][j] = c; -} - - -/************************************************************************* -This function is used to add bound constraints on the elements of the -transition matrix P. - -MCPD solver has four types of constraints which can be placed on P: -* user-specified equality constraints (optional) -* user-specified bound constraints (optional) -* user-specified general linear constraints (optional) -* basic constraints (always present): - * non-negativity: P[i,j]>=0 - * consistency: every column of P sums to 1.0 - -Final constraints which are passed to the underlying optimizer are -calculated as intersection of all present constraints. For example, you -may specify boundary constraint on P[0,0] and equality one: - 0.1<=P[0,0]<=0.9 - P[0,0]=0.5 -Such combination of constraints will be silently reduced to their -intersection, which is P[0,0]=0.5. - -This function can be used to place bound constraints on arbitrary -subset of elements of P. Set of constraints is specified by BndL/BndU -matrices, which may contain arbitrary combination of finite numbers or -infinities (like -INFn; - ae_assert(bndl->cols>=n, "MCPDSetBC: Cols(BndL)rows>=n, "MCPDSetBC: Rows(BndL)cols>=n, "MCPDSetBC: Cols(BndU)rows>=n, "MCPDSetBC: Rows(BndU)ptr.pp_double[i][j], _state)||ae_isneginf(bndl->ptr.pp_double[i][j], _state), "MCPDSetBC: BndL containts NAN or +INF", _state); - ae_assert(ae_isfinite(bndu->ptr.pp_double[i][j], _state)||ae_isposinf(bndu->ptr.pp_double[i][j], _state), "MCPDSetBC: BndU containts NAN or -INF", _state); - s->bndl.ptr.pp_double[i][j] = bndl->ptr.pp_double[i][j]; - s->bndu.ptr.pp_double[i][j] = bndu->ptr.pp_double[i][j]; - } - } -} - - -/************************************************************************* -This function is used to add bound constraints on the elements of the -transition matrix P. - -MCPD solver has four types of constraints which can be placed on P: -* user-specified equality constraints (optional) -* user-specified bound constraints (optional) -* user-specified general linear constraints (optional) -* basic constraints (always present): - * non-negativity: P[i,j]>=0 - * consistency: every column of P sums to 1.0 - -Final constraints which are passed to the underlying optimizer are -calculated as intersection of all present constraints. For example, you -may specify boundary constraint on P[0,0] and equality one: - 0.1<=P[0,0]<=0.9 - P[0,0]=0.5 -Such combination of constraints will be silently reduced to their -intersection, which is P[0,0]=0.5. - -This function can be used to ADD bound constraint for one element of P -without changing constraints for other elements. - -You can also use MCPDSetBC() function which allows to place bound -constraints on arbitrary subset of elements of P. Set of constraints is -specified by BndL/BndU matrices, which may contain arbitrary combination -of finite numbers or infinities (like -INF=0, "MCPDAddBC: I<0", _state); - ae_assert(in, "MCPDAddBC: I>=N", _state); - ae_assert(j>=0, "MCPDAddBC: J<0", _state); - ae_assert(jn, "MCPDAddBC: J>=N", _state); - ae_assert(ae_isfinite(bndl, _state)||ae_isneginf(bndl, _state), "MCPDAddBC: BndL is NAN or +INF", _state); - ae_assert(ae_isfinite(bndu, _state)||ae_isposinf(bndu, _state), "MCPDAddBC: BndU is NAN or -INF", _state); - s->bndl.ptr.pp_double[i][j] = bndl; - s->bndu.ptr.pp_double[i][j] = bndu; -} - - -/************************************************************************* -This function is used to set linear equality/inequality constraints on the -elements of the transition matrix P. - -This function can be used to set one or several general linear constraints -on the elements of P. Two types of constraints are supported: -* equality constraints -* inequality constraints (both less-or-equal and greater-or-equal) - -Coefficients of constraints are specified by matrix C (one of the -parameters). One row of C corresponds to one constraint. Because -transition matrix P has N*N elements, we need N*N columns to store all -coefficients (they are stored row by row), and one more column to store -right part - hence C has N*N+1 columns. Constraint kind is stored in the -CT array. - -Thus, I-th linear constraint is - P[0,0]*C[I,0] + P[0,1]*C[I,1] + .. + P[0,N-1]*C[I,N-1] + - + P[1,0]*C[I,N] + P[1,1]*C[I,N+1] + ... + - + P[N-1,N-1]*C[I,N*N-1] ?=? C[I,N*N] -where ?=? can be either "=" (CT[i]=0), "<=" (CT[i]<0) or ">=" (CT[i]>0). - -Your constraint may involve only some subset of P (less than N*N elements). -For example it can be something like - P[0,0] + P[0,1] = 0.5 -In this case you still should pass matrix with N*N+1 columns, but all its -elements (except for C[0,0], C[0,1] and C[0,N*N-1]) will be zero. - -INPUT PARAMETERS: - S - solver - C - array[K,N*N+1] - coefficients of constraints - (see above for complete description) - CT - array[K] - constraint types - (see above for complete description) - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdsetlc(mcpdstate* s, - /* Real */ ae_matrix* c, - /* Integer */ ae_vector* ct, - ae_int_t k, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t n; - - - n = s->n; - ae_assert(c->cols>=n*n+1, "MCPDSetLC: Cols(C)rows>=k, "MCPDSetLC: Rows(C)cnt>=k, "MCPDSetLC: Len(CT)c, k, n*n+1, _state); - ivectorsetlengthatleast(&s->ct, k, _state); - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n*n; j++) - { - s->c.ptr.pp_double[i][j] = c->ptr.pp_double[i][j]; - } - s->ct.ptr.p_int[i] = ct->ptr.p_int[i]; - } - s->ccnt = k; -} - - -/************************************************************************* -This function allows to tune amount of Tikhonov regularization being -applied to your problem. - -By default, regularizing term is equal to r*||P-prior_P||^2, where r is a -small non-zero value, P is transition matrix, prior_P is identity matrix, -||X||^2 is a sum of squared elements of X. - -This function allows you to change coefficient r. You can also change -prior values with MCPDSetPrior() function. - -INPUT PARAMETERS: - S - solver - V - regularization coefficient, finite non-negative value. It - is not recommended to specify zero value unless you are - pretty sure that you want it. - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdsettikhonovregularizer(mcpdstate* s, double v, ae_state *_state) -{ - - - ae_assert(ae_isfinite(v, _state), "MCPDSetTikhonovRegularizer: V is infinite or NAN", _state); - ae_assert(ae_fp_greater_eq(v,0.0), "MCPDSetTikhonovRegularizer: V is less than zero", _state); - s->regterm = v; -} - - -/************************************************************************* -This function allows to set prior values used for regularization of your -problem. - -By default, regularizing term is equal to r*||P-prior_P||^2, where r is a -small non-zero value, P is transition matrix, prior_P is identity matrix, -||X||^2 is a sum of squared elements of X. - -This function allows you to change prior values prior_P. You can also -change r with MCPDSetTikhonovRegularizer() function. - -INPUT PARAMETERS: - S - solver - PP - array[N,N], matrix of prior values: - 1. elements must be real numbers from [0,1] - 2. columns must sum to 1.0. - First property is checked (exception is thrown otherwise), - while second one is not checked/enforced. - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdsetprior(mcpdstate* s, - /* Real */ ae_matrix* pp, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _pp; - ae_int_t i; - ae_int_t j; - ae_int_t n; - - ae_frame_make(_state, &_frame_block); - memset(&_pp, 0, sizeof(_pp)); - ae_matrix_init_copy(&_pp, pp, _state, ae_true); - pp = &_pp; - - n = s->n; - ae_assert(pp->cols>=n, "MCPDSetPrior: Cols(PP)rows>=n, "MCPDSetPrior: Rows(PP)ptr.pp_double[i][j], _state), "MCPDSetPrior: PP containts infinite elements", _state); - ae_assert(ae_fp_greater_eq(pp->ptr.pp_double[i][j],0.0)&&ae_fp_less_eq(pp->ptr.pp_double[i][j],1.0), "MCPDSetPrior: PP[i,j] is less than 0.0 or greater than 1.0", _state); - s->priorp.ptr.pp_double[i][j] = pp->ptr.pp_double[i][j]; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function is used to change prediction weights - -MCPD solver scales prediction errors as follows - Error(P) = ||W*(y-P*x)||^2 -where - x is a system state at time t - y is a system state at time t+1 - P is a transition matrix - W is a diagonal scaling matrix - -By default, weights are chosen in order to minimize relative prediction -error instead of absolute one. For example, if one component of state is -about 0.5 in magnitude and another one is about 0.05, then algorithm will -make corresponding weights equal to 2.0 and 20.0. - -INPUT PARAMETERS: - S - solver - PW - array[N], weights: - * must be non-negative values (exception will be thrown otherwise) - * zero values will be replaced by automatically chosen values - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdsetpredictionweights(mcpdstate* s, - /* Real */ ae_vector* pw, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - - - n = s->n; - ae_assert(pw->cnt>=n, "MCPDSetPredictionWeights: Length(PW)ptr.p_double[i], _state), "MCPDSetPredictionWeights: PW containts infinite or NAN elements", _state); - ae_assert(ae_fp_greater_eq(pw->ptr.p_double[i],(double)(0)), "MCPDSetPredictionWeights: PW containts negative elements", _state); - s->pw.ptr.p_double[i] = pw->ptr.p_double[i]; - } -} - - -/************************************************************************* -This function is used to start solution of the MCPD problem. - -After return from this function, you can use MCPDResults() to get solution -and completion code. - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdsolve(mcpdstate* s, ae_state *_state) -{ - ae_int_t n; - ae_int_t npairs; - ae_int_t ccnt; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t k2; - double v; - double vv; - - - n = s->n; - npairs = s->npairs; - - /* - * init fields of S - */ - s->repterminationtype = 0; - s->repinneriterationscount = 0; - s->repouteriterationscount = 0; - s->repnfev = 0; - for(k=0; k<=n-1; k++) - { - for(k2=0; k2<=n-1; k2++) - { - s->p.ptr.pp_double[k][k2] = _state->v_nan; - } - } - - /* - * Generate "effective" weights for prediction and calculate preconditioner - */ - for(i=0; i<=n-1; i++) - { - if( ae_fp_eq(s->pw.ptr.p_double[i],(double)(0)) ) - { - v = (double)(0); - k = 0; - for(j=0; j<=npairs-1; j++) - { - if( ae_fp_neq(s->data.ptr.pp_double[j][n+i],(double)(0)) ) - { - v = v+s->data.ptr.pp_double[j][n+i]; - k = k+1; - } - } - if( k!=0 ) - { - s->effectivew.ptr.p_double[i] = k/v; - } - else - { - s->effectivew.ptr.p_double[i] = 1.0; - } - } - else - { - s->effectivew.ptr.p_double[i] = s->pw.ptr.p_double[i]; - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - s->h.ptr.p_double[i*n+j] = 2*s->regterm; - } - } - for(k=0; k<=npairs-1; k++) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - s->h.ptr.p_double[i*n+j] = s->h.ptr.p_double[i*n+j]+2*ae_sqr(s->effectivew.ptr.p_double[i], _state)*ae_sqr(s->data.ptr.pp_double[k][j], _state); - } - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_eq(s->h.ptr.p_double[i*n+j],(double)(0)) ) - { - s->h.ptr.p_double[i*n+j] = (double)(1); - } - } - } - - /* - * Generate "effective" BndL/BndU - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - - /* - * Set default boundary constraints. - * Lower bound is always zero, upper bound is calculated - * with respect to entry/exit states. - */ - s->effectivebndl.ptr.p_double[i*n+j] = 0.0; - if( s->states.ptr.p_int[i]>0||s->states.ptr.p_int[j]<0 ) - { - s->effectivebndu.ptr.p_double[i*n+j] = 0.0; - } - else - { - s->effectivebndu.ptr.p_double[i*n+j] = 1.0; - } - - /* - * Calculate intersection of the default and user-specified bound constraints. - * This code checks consistency of such combination. - */ - if( ae_isfinite(s->bndl.ptr.pp_double[i][j], _state)&&ae_fp_greater(s->bndl.ptr.pp_double[i][j],s->effectivebndl.ptr.p_double[i*n+j]) ) - { - s->effectivebndl.ptr.p_double[i*n+j] = s->bndl.ptr.pp_double[i][j]; - } - if( ae_isfinite(s->bndu.ptr.pp_double[i][j], _state)&&ae_fp_less(s->bndu.ptr.pp_double[i][j],s->effectivebndu.ptr.p_double[i*n+j]) ) - { - s->effectivebndu.ptr.p_double[i*n+j] = s->bndu.ptr.pp_double[i][j]; - } - if( ae_fp_greater(s->effectivebndl.ptr.p_double[i*n+j],s->effectivebndu.ptr.p_double[i*n+j]) ) - { - s->repterminationtype = -3; - return; - } - - /* - * Calculate intersection of the effective bound constraints - * and user-specified equality constraints. - * This code checks consistency of such combination. - */ - if( ae_isfinite(s->ec.ptr.pp_double[i][j], _state) ) - { - if( ae_fp_less(s->ec.ptr.pp_double[i][j],s->effectivebndl.ptr.p_double[i*n+j])||ae_fp_greater(s->ec.ptr.pp_double[i][j],s->effectivebndu.ptr.p_double[i*n+j]) ) - { - s->repterminationtype = -3; - return; - } - s->effectivebndl.ptr.p_double[i*n+j] = s->ec.ptr.pp_double[i][j]; - s->effectivebndu.ptr.p_double[i*n+j] = s->ec.ptr.pp_double[i][j]; - } - } - } - - /* - * Generate linear constraints: - * * "default" sums-to-one constraints (not generated for "exit" states) - */ - rmatrixsetlengthatleast(&s->effectivec, s->ccnt+n, n*n+1, _state); - ivectorsetlengthatleast(&s->effectivect, s->ccnt+n, _state); - ccnt = s->ccnt; - for(i=0; i<=s->ccnt-1; i++) - { - for(j=0; j<=n*n; j++) - { - s->effectivec.ptr.pp_double[i][j] = s->c.ptr.pp_double[i][j]; - } - s->effectivect.ptr.p_int[i] = s->ct.ptr.p_int[i]; - } - for(i=0; i<=n-1; i++) - { - if( s->states.ptr.p_int[i]>=0 ) - { - for(k=0; k<=n*n-1; k++) - { - s->effectivec.ptr.pp_double[ccnt][k] = (double)(0); - } - for(k=0; k<=n-1; k++) - { - s->effectivec.ptr.pp_double[ccnt][k*n+i] = (double)(1); - } - s->effectivec.ptr.pp_double[ccnt][n*n] = 1.0; - s->effectivect.ptr.p_int[ccnt] = 0; - ccnt = ccnt+1; - } - } - - /* - * create optimizer - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - s->tmpp.ptr.p_double[i*n+j] = (double)1/(double)n; - } - } - minbleicrestartfrom(&s->bs, &s->tmpp, _state); - minbleicsetbc(&s->bs, &s->effectivebndl, &s->effectivebndu, _state); - minbleicsetlc(&s->bs, &s->effectivec, &s->effectivect, ccnt, _state); - minbleicsetcond(&s->bs, 0.0, 0.0, mcpd_xtol, 0, _state); - minbleicsetprecdiag(&s->bs, &s->h, _state); - - /* - * solve problem - */ - while(minbleiciteration(&s->bs, _state)) - { - ae_assert(s->bs.needfg, "MCPDSolve: internal error", _state); - if( s->bs.needfg ) - { - - /* - * Calculate regularization term - */ - s->bs.f = 0.0; - vv = s->regterm; - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - s->bs.f = s->bs.f+vv*ae_sqr(s->bs.x.ptr.p_double[i*n+j]-s->priorp.ptr.pp_double[i][j], _state); - s->bs.g.ptr.p_double[i*n+j] = 2*vv*(s->bs.x.ptr.p_double[i*n+j]-s->priorp.ptr.pp_double[i][j]); - } - } - - /* - * calculate prediction error/gradient for K-th pair - */ - for(k=0; k<=npairs-1; k++) - { - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&s->bs.x.ptr.p_double[i*n], 1, &s->data.ptr.pp_double[k][0], 1, ae_v_len(i*n,i*n+n-1)); - vv = s->effectivew.ptr.p_double[i]; - s->bs.f = s->bs.f+ae_sqr(vv*(v-s->data.ptr.pp_double[k][n+i]), _state); - for(j=0; j<=n-1; j++) - { - s->bs.g.ptr.p_double[i*n+j] = s->bs.g.ptr.p_double[i*n+j]+2*vv*vv*(v-s->data.ptr.pp_double[k][n+i])*s->data.ptr.pp_double[k][j]; - } - } - } - - /* - * continue - */ - continue; - } - } - minbleicresultsbuf(&s->bs, &s->tmpp, &s->br, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - s->p.ptr.pp_double[i][j] = s->tmpp.ptr.p_double[i*n+j]; - } - } - s->repterminationtype = s->br.terminationtype; - s->repinneriterationscount = s->br.inneriterationscount; - s->repouteriterationscount = s->br.outeriterationscount; - s->repnfev = s->br.nfev; -} - - -/************************************************************************* -MCPD results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - P - array[N,N], transition matrix - Rep - optimization report. You should check Rep.TerminationType - in order to distinguish successful termination from - unsuccessful one. Speaking short, positive values denote - success, negative ones are failures. - More information about fields of this structure can be - found in the comments on MCPDReport datatype. - - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdresults(mcpdstate* s, - /* Real */ ae_matrix* p, - mcpdreport* rep, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(p); - _mcpdreport_clear(rep); - - ae_matrix_set_length(p, s->n, s->n, _state); - for(i=0; i<=s->n-1; i++) - { - for(j=0; j<=s->n-1; j++) - { - p->ptr.pp_double[i][j] = s->p.ptr.pp_double[i][j]; - } - } - rep->terminationtype = s->repterminationtype; - rep->inneriterationscount = s->repinneriterationscount; - rep->outeriterationscount = s->repouteriterationscount; - rep->nfev = s->repnfev; -} - - -/************************************************************************* -Internal initialization function - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -static void mcpd_mcpdinit(ae_int_t n, - ae_int_t entrystate, - ae_int_t exitstate, - mcpdstate* s, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - ae_assert(n>=1, "MCPDCreate: N<1", _state); - s->n = n; - ae_vector_set_length(&s->states, n, _state); - for(i=0; i<=n-1; i++) - { - s->states.ptr.p_int[i] = 0; - } - if( entrystate>=0 ) - { - s->states.ptr.p_int[entrystate] = 1; - } - if( exitstate>=0 ) - { - s->states.ptr.p_int[exitstate] = -1; - } - s->npairs = 0; - s->regterm = 1.0E-8; - s->ccnt = 0; - ae_matrix_set_length(&s->p, n, n, _state); - ae_matrix_set_length(&s->ec, n, n, _state); - ae_matrix_set_length(&s->bndl, n, n, _state); - ae_matrix_set_length(&s->bndu, n, n, _state); - ae_vector_set_length(&s->pw, n, _state); - ae_matrix_set_length(&s->priorp, n, n, _state); - ae_vector_set_length(&s->tmpp, n*n, _state); - ae_vector_set_length(&s->effectivew, n, _state); - ae_vector_set_length(&s->effectivebndl, n*n, _state); - ae_vector_set_length(&s->effectivebndu, n*n, _state); - ae_vector_set_length(&s->h, n*n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - s->p.ptr.pp_double[i][j] = 0.0; - s->priorp.ptr.pp_double[i][j] = 0.0; - s->bndl.ptr.pp_double[i][j] = _state->v_neginf; - s->bndu.ptr.pp_double[i][j] = _state->v_posinf; - s->ec.ptr.pp_double[i][j] = _state->v_nan; - } - s->pw.ptr.p_double[i] = 0.0; - s->priorp.ptr.pp_double[i][i] = 1.0; - } - ae_matrix_set_length(&s->data, 1, 2*n, _state); - for(i=0; i<=2*n-1; i++) - { - s->data.ptr.pp_double[0][i] = 0.0; - } - for(i=0; i<=n*n-1; i++) - { - s->tmpp.ptr.p_double[i] = 0.0; - } - minbleiccreate(n*n, &s->tmpp, &s->bs, _state); -} - - -void _mcpdstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - mcpdstate *p = (mcpdstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->states, 0, DT_INT, _state, make_automatic); - ae_matrix_init(&p->data, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->ec, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->bndl, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->bndu, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->c, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ct, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->pw, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->priorp, 0, 0, DT_REAL, _state, make_automatic); - _minbleicstate_init(&p->bs, _state, make_automatic); - _minbleicreport_init(&p->br, _state, make_automatic); - ae_vector_init(&p->tmpp, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->effectivew, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->effectivebndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->effectivebndu, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->effectivec, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->effectivect, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->h, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->p, 0, 0, DT_REAL, _state, make_automatic); -} - - -void _mcpdstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - mcpdstate *dst = (mcpdstate*)_dst; - mcpdstate *src = (mcpdstate*)_src; - dst->n = src->n; - ae_vector_init_copy(&dst->states, &src->states, _state, make_automatic); - dst->npairs = src->npairs; - ae_matrix_init_copy(&dst->data, &src->data, _state, make_automatic); - ae_matrix_init_copy(&dst->ec, &src->ec, _state, make_automatic); - ae_matrix_init_copy(&dst->bndl, &src->bndl, _state, make_automatic); - ae_matrix_init_copy(&dst->bndu, &src->bndu, _state, make_automatic); - ae_matrix_init_copy(&dst->c, &src->c, _state, make_automatic); - ae_vector_init_copy(&dst->ct, &src->ct, _state, make_automatic); - dst->ccnt = src->ccnt; - ae_vector_init_copy(&dst->pw, &src->pw, _state, make_automatic); - ae_matrix_init_copy(&dst->priorp, &src->priorp, _state, make_automatic); - dst->regterm = src->regterm; - _minbleicstate_init_copy(&dst->bs, &src->bs, _state, make_automatic); - dst->repinneriterationscount = src->repinneriterationscount; - dst->repouteriterationscount = src->repouteriterationscount; - dst->repnfev = src->repnfev; - dst->repterminationtype = src->repterminationtype; - _minbleicreport_init_copy(&dst->br, &src->br, _state, make_automatic); - ae_vector_init_copy(&dst->tmpp, &src->tmpp, _state, make_automatic); - ae_vector_init_copy(&dst->effectivew, &src->effectivew, _state, make_automatic); - ae_vector_init_copy(&dst->effectivebndl, &src->effectivebndl, _state, make_automatic); - ae_vector_init_copy(&dst->effectivebndu, &src->effectivebndu, _state, make_automatic); - ae_matrix_init_copy(&dst->effectivec, &src->effectivec, _state, make_automatic); - ae_vector_init_copy(&dst->effectivect, &src->effectivect, _state, make_automatic); - ae_vector_init_copy(&dst->h, &src->h, _state, make_automatic); - ae_matrix_init_copy(&dst->p, &src->p, _state, make_automatic); -} - - -void _mcpdstate_clear(void* _p) -{ - mcpdstate *p = (mcpdstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->states); - ae_matrix_clear(&p->data); - ae_matrix_clear(&p->ec); - ae_matrix_clear(&p->bndl); - ae_matrix_clear(&p->bndu); - ae_matrix_clear(&p->c); - ae_vector_clear(&p->ct); - ae_vector_clear(&p->pw); - ae_matrix_clear(&p->priorp); - _minbleicstate_clear(&p->bs); - _minbleicreport_clear(&p->br); - ae_vector_clear(&p->tmpp); - ae_vector_clear(&p->effectivew); - ae_vector_clear(&p->effectivebndl); - ae_vector_clear(&p->effectivebndu); - ae_matrix_clear(&p->effectivec); - ae_vector_clear(&p->effectivect); - ae_vector_clear(&p->h); - ae_matrix_clear(&p->p); -} - - -void _mcpdstate_destroy(void* _p) -{ - mcpdstate *p = (mcpdstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->states); - ae_matrix_destroy(&p->data); - ae_matrix_destroy(&p->ec); - ae_matrix_destroy(&p->bndl); - ae_matrix_destroy(&p->bndu); - ae_matrix_destroy(&p->c); - ae_vector_destroy(&p->ct); - ae_vector_destroy(&p->pw); - ae_matrix_destroy(&p->priorp); - _minbleicstate_destroy(&p->bs); - _minbleicreport_destroy(&p->br); - ae_vector_destroy(&p->tmpp); - ae_vector_destroy(&p->effectivew); - ae_vector_destroy(&p->effectivebndl); - ae_vector_destroy(&p->effectivebndu); - ae_matrix_destroy(&p->effectivec); - ae_vector_destroy(&p->effectivect); - ae_vector_destroy(&p->h); - ae_matrix_destroy(&p->p); -} - - -void _mcpdreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - mcpdreport *p = (mcpdreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _mcpdreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - mcpdreport *dst = (mcpdreport*)_dst; - mcpdreport *src = (mcpdreport*)_src; - dst->inneriterationscount = src->inneriterationscount; - dst->outeriterationscount = src->outeriterationscount; - dst->nfev = src->nfev; - dst->terminationtype = src->terminationtype; -} - - -void _mcpdreport_clear(void* _p) -{ - mcpdreport *p = (mcpdreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _mcpdreport_destroy(void* _p) -{ - mcpdreport *p = (mcpdreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_MLPE) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Like MLPCreate0, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreate0(ae_int_t nin, - ae_int_t nout, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron net; - - ae_frame_make(_state, &_frame_block); - memset(&net, 0, sizeof(net)); - _mlpensemble_clear(ensemble); - _multilayerperceptron_init(&net, _state, ae_true); - - mlpcreate0(nin, nout, &net, _state); - mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Like MLPCreate1, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreate1(ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron net; - - ae_frame_make(_state, &_frame_block); - memset(&net, 0, sizeof(net)); - _mlpensemble_clear(ensemble); - _multilayerperceptron_init(&net, _state, ae_true); - - mlpcreate1(nin, nhid, nout, &net, _state); - mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Like MLPCreate2, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreate2(ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron net; - - ae_frame_make(_state, &_frame_block); - memset(&net, 0, sizeof(net)); - _mlpensemble_clear(ensemble); - _multilayerperceptron_init(&net, _state, ae_true); - - mlpcreate2(nin, nhid1, nhid2, nout, &net, _state); - mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Like MLPCreateB0, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreateb0(ae_int_t nin, - ae_int_t nout, - double b, - double d, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron net; - - ae_frame_make(_state, &_frame_block); - memset(&net, 0, sizeof(net)); - _mlpensemble_clear(ensemble); - _multilayerperceptron_init(&net, _state, ae_true); - - mlpcreateb0(nin, nout, b, d, &net, _state); - mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Like MLPCreateB1, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreateb1(ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - double b, - double d, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron net; - - ae_frame_make(_state, &_frame_block); - memset(&net, 0, sizeof(net)); - _mlpensemble_clear(ensemble); - _multilayerperceptron_init(&net, _state, ae_true); - - mlpcreateb1(nin, nhid, nout, b, d, &net, _state); - mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Like MLPCreateB2, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreateb2(ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - double b, - double d, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron net; - - ae_frame_make(_state, &_frame_block); - memset(&net, 0, sizeof(net)); - _mlpensemble_clear(ensemble); - _multilayerperceptron_init(&net, _state, ae_true); - - mlpcreateb2(nin, nhid1, nhid2, nout, b, d, &net, _state); - mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Like MLPCreateR0, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreater0(ae_int_t nin, - ae_int_t nout, - double a, - double b, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron net; - - ae_frame_make(_state, &_frame_block); - memset(&net, 0, sizeof(net)); - _mlpensemble_clear(ensemble); - _multilayerperceptron_init(&net, _state, ae_true); - - mlpcreater0(nin, nout, a, b, &net, _state); - mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Like MLPCreateR1, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreater1(ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - double a, - double b, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron net; - - ae_frame_make(_state, &_frame_block); - memset(&net, 0, sizeof(net)); - _mlpensemble_clear(ensemble); - _multilayerperceptron_init(&net, _state, ae_true); - - mlpcreater1(nin, nhid, nout, a, b, &net, _state); - mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Like MLPCreateR2, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreater2(ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - double a, - double b, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron net; - - ae_frame_make(_state, &_frame_block); - memset(&net, 0, sizeof(net)); - _mlpensemble_clear(ensemble); - _multilayerperceptron_init(&net, _state, ae_true); - - mlpcreater2(nin, nhid1, nhid2, nout, a, b, &net, _state); - mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Like MLPCreateC0, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreatec0(ae_int_t nin, - ae_int_t nout, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron net; - - ae_frame_make(_state, &_frame_block); - memset(&net, 0, sizeof(net)); - _mlpensemble_clear(ensemble); - _multilayerperceptron_init(&net, _state, ae_true); - - mlpcreatec0(nin, nout, &net, _state); - mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Like MLPCreateC1, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreatec1(ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron net; - - ae_frame_make(_state, &_frame_block); - memset(&net, 0, sizeof(net)); - _mlpensemble_clear(ensemble); - _multilayerperceptron_init(&net, _state, ae_true); - - mlpcreatec1(nin, nhid, nout, &net, _state); - mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Like MLPCreateC2, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreatec2(ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron net; - - ae_frame_make(_state, &_frame_block); - memset(&net, 0, sizeof(net)); - _mlpensemble_clear(ensemble); - _multilayerperceptron_init(&net, _state, ae_true); - - mlpcreatec2(nin, nhid1, nhid2, nout, &net, _state); - mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Creates ensemble from network. Only network geometry is copied. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreatefromnetwork(multilayerperceptron* network, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state) -{ - ae_int_t i; - ae_int_t ccount; - ae_int_t wcount; - - _mlpensemble_clear(ensemble); - - ae_assert(ensemblesize>0, "MLPECreate: incorrect ensemble size!", _state); - - /* - * Copy network - */ - mlpcopy(network, &ensemble->network, _state); - - /* - * network properties - */ - if( mlpissoftmax(network, _state) ) - { - ccount = mlpgetinputscount(&ensemble->network, _state); - } - else - { - ccount = mlpgetinputscount(&ensemble->network, _state)+mlpgetoutputscount(&ensemble->network, _state); - } - wcount = mlpgetweightscount(&ensemble->network, _state); - ensemble->ensemblesize = ensemblesize; - - /* - * weights, means, sigmas - */ - ae_vector_set_length(&ensemble->weights, ensemblesize*wcount, _state); - ae_vector_set_length(&ensemble->columnmeans, ensemblesize*ccount, _state); - ae_vector_set_length(&ensemble->columnsigmas, ensemblesize*ccount, _state); - for(i=0; i<=ensemblesize*wcount-1; i++) - { - ensemble->weights.ptr.p_double[i] = ae_randomreal(_state)-0.5; - } - for(i=0; i<=ensemblesize-1; i++) - { - ae_v_move(&ensemble->columnmeans.ptr.p_double[i*ccount], 1, &network->columnmeans.ptr.p_double[0], 1, ae_v_len(i*ccount,(i+1)*ccount-1)); - ae_v_move(&ensemble->columnsigmas.ptr.p_double[i*ccount], 1, &network->columnsigmas.ptr.p_double[0], 1, ae_v_len(i*ccount,(i+1)*ccount-1)); - } - - /* - * temporaries, internal buffers - */ - ae_vector_set_length(&ensemble->y, mlpgetoutputscount(&ensemble->network, _state), _state); -} - - -/************************************************************************* -Copying of MLPEnsemble strucure - -INPUT PARAMETERS: - Ensemble1 - original - -OUTPUT PARAMETERS: - Ensemble2 - copy - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecopy(mlpensemble* ensemble1, - mlpensemble* ensemble2, - ae_state *_state) -{ - ae_int_t ccount; - ae_int_t wcount; - - _mlpensemble_clear(ensemble2); - - - /* - * Unload info - */ - if( mlpissoftmax(&ensemble1->network, _state) ) - { - ccount = mlpgetinputscount(&ensemble1->network, _state); - } - else - { - ccount = mlpgetinputscount(&ensemble1->network, _state)+mlpgetoutputscount(&ensemble1->network, _state); - } - wcount = mlpgetweightscount(&ensemble1->network, _state); - - /* - * Allocate space - */ - ae_vector_set_length(&ensemble2->weights, ensemble1->ensemblesize*wcount, _state); - ae_vector_set_length(&ensemble2->columnmeans, ensemble1->ensemblesize*ccount, _state); - ae_vector_set_length(&ensemble2->columnsigmas, ensemble1->ensemblesize*ccount, _state); - ae_vector_set_length(&ensemble2->y, mlpgetoutputscount(&ensemble1->network, _state), _state); - - /* - * Copy - */ - ensemble2->ensemblesize = ensemble1->ensemblesize; - ae_v_move(&ensemble2->weights.ptr.p_double[0], 1, &ensemble1->weights.ptr.p_double[0], 1, ae_v_len(0,ensemble1->ensemblesize*wcount-1)); - ae_v_move(&ensemble2->columnmeans.ptr.p_double[0], 1, &ensemble1->columnmeans.ptr.p_double[0], 1, ae_v_len(0,ensemble1->ensemblesize*ccount-1)); - ae_v_move(&ensemble2->columnsigmas.ptr.p_double[0], 1, &ensemble1->columnsigmas.ptr.p_double[0], 1, ae_v_len(0,ensemble1->ensemblesize*ccount-1)); - mlpcopy(&ensemble1->network, &ensemble2->network, _state); -} - - -/************************************************************************* -Randomization of MLP ensemble - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlperandomize(mlpensemble* ensemble, ae_state *_state) -{ - ae_int_t i; - ae_int_t wcount; - - - wcount = mlpgetweightscount(&ensemble->network, _state); - for(i=0; i<=ensemble->ensemblesize*wcount-1; i++) - { - ensemble->weights.ptr.p_double[i] = ae_randomreal(_state)-0.5; - } -} - - -/************************************************************************* -Return ensemble properties (number of inputs and outputs). - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpeproperties(mlpensemble* ensemble, - ae_int_t* nin, - ae_int_t* nout, - ae_state *_state) -{ - - *nin = 0; - *nout = 0; - - *nin = mlpgetinputscount(&ensemble->network, _state); - *nout = mlpgetoutputscount(&ensemble->network, _state); -} - - -/************************************************************************* -Return normalization type (whether ensemble is SOFTMAX-normalized or not). - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -ae_bool mlpeissoftmax(mlpensemble* ensemble, ae_state *_state) -{ - ae_bool result; - - - result = mlpissoftmax(&ensemble->network, _state); - return result; -} - - -/************************************************************************* -Procesing - -INPUT PARAMETERS: - Ensemble- neural networks ensemble - X - input vector, array[0..NIn-1]. - Y - (possibly) preallocated buffer; if size of Y is less than - NOut, it will be reallocated. If it is large enough, it - is NOT reallocated, so we can save some time on reallocation. - - -OUTPUT PARAMETERS: - Y - result. Regression estimate when solving regression task, - vector of posterior probabilities for classification task. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpeprocess(mlpensemble* ensemble, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - ae_int_t es; - ae_int_t wc; - ae_int_t cc; - double v; - ae_int_t nout; - - - if( y->cntnetwork, _state) ) - { - ae_vector_set_length(y, mlpgetoutputscount(&ensemble->network, _state), _state); - } - es = ensemble->ensemblesize; - wc = mlpgetweightscount(&ensemble->network, _state); - if( mlpissoftmax(&ensemble->network, _state) ) - { - cc = mlpgetinputscount(&ensemble->network, _state); - } - else - { - cc = mlpgetinputscount(&ensemble->network, _state)+mlpgetoutputscount(&ensemble->network, _state); - } - v = (double)1/(double)es; - nout = mlpgetoutputscount(&ensemble->network, _state); - for(i=0; i<=nout-1; i++) - { - y->ptr.p_double[i] = (double)(0); - } - for(i=0; i<=es-1; i++) - { - ae_v_move(&ensemble->network.weights.ptr.p_double[0], 1, &ensemble->weights.ptr.p_double[i*wc], 1, ae_v_len(0,wc-1)); - ae_v_move(&ensemble->network.columnmeans.ptr.p_double[0], 1, &ensemble->columnmeans.ptr.p_double[i*cc], 1, ae_v_len(0,cc-1)); - ae_v_move(&ensemble->network.columnsigmas.ptr.p_double[0], 1, &ensemble->columnsigmas.ptr.p_double[i*cc], 1, ae_v_len(0,cc-1)); - mlpprocess(&ensemble->network, x, &ensemble->y, _state); - ae_v_addd(&y->ptr.p_double[0], 1, &ensemble->y.ptr.p_double[0], 1, ae_v_len(0,nout-1), v); - } -} - - -/************************************************************************* -'interactive' variant of MLPEProcess for languages like Python which -support constructs like "Y = MLPEProcess(LM,X)" and interactive mode of the -interpreter - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpeprocessi(mlpensemble* ensemble, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - - ae_vector_clear(y); - - mlpeprocess(ensemble, x, y, _state); -} - - -/************************************************************************* -Calculation of all types of errors - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpeallerrorsx(mlpensemble* ensemble, - /* Real */ ae_matrix* densexy, - sparsematrix* sparsexy, - ae_int_t datasetsize, - ae_int_t datasettype, - /* Integer */ ae_vector* idx, - ae_int_t subset0, - ae_int_t subset1, - ae_int_t subsettype, - ae_shared_pool* buf, - modelerrors* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t nin; - ae_int_t nout; - ae_bool iscls; - ae_int_t srcidx; - mlpbuffers *pbuf; - ae_smart_ptr _pbuf; - modelerrors rep0; - modelerrors rep1; - - ae_frame_make(_state, &_frame_block); - memset(&_pbuf, 0, sizeof(_pbuf)); - memset(&rep0, 0, sizeof(rep0)); - memset(&rep1, 0, sizeof(rep1)); - ae_smart_ptr_init(&_pbuf, (void**)&pbuf, _state, ae_true); - _modelerrors_init(&rep0, _state, ae_true); - _modelerrors_init(&rep1, _state, ae_true); - - - /* - * Get network information - */ - nin = mlpgetinputscount(&ensemble->network, _state); - nout = mlpgetoutputscount(&ensemble->network, _state); - iscls = mlpissoftmax(&ensemble->network, _state); - - /* - * Retrieve buffer, prepare, process data, recycle buffer - */ - ae_shared_pool_retrieve(buf, &_pbuf, _state); - if( iscls ) - { - dserrallocate(nout, &pbuf->tmp0, _state); - } - else - { - dserrallocate(-nout, &pbuf->tmp0, _state); - } - rvectorsetlengthatleast(&pbuf->x, nin, _state); - rvectorsetlengthatleast(&pbuf->y, nout, _state); - rvectorsetlengthatleast(&pbuf->desiredy, nout, _state); - for(i=subset0; i<=subset1-1; i++) - { - srcidx = -1; - if( subsettype==0 ) - { - srcidx = i; - } - if( subsettype==1 ) - { - srcidx = idx->ptr.p_int[i]; - } - ae_assert(srcidx>=0, "MLPEAllErrorsX: internal error", _state); - if( datasettype==0 ) - { - ae_v_move(&pbuf->x.ptr.p_double[0], 1, &densexy->ptr.pp_double[srcidx][0], 1, ae_v_len(0,nin-1)); - } - if( datasettype==1 ) - { - sparsegetrow(sparsexy, srcidx, &pbuf->x, _state); - } - mlpeprocess(ensemble, &pbuf->x, &pbuf->y, _state); - if( mlpissoftmax(&ensemble->network, _state) ) - { - if( datasettype==0 ) - { - pbuf->desiredy.ptr.p_double[0] = densexy->ptr.pp_double[srcidx][nin]; - } - if( datasettype==1 ) - { - pbuf->desiredy.ptr.p_double[0] = sparseget(sparsexy, srcidx, nin, _state); - } - } - else - { - if( datasettype==0 ) - { - ae_v_move(&pbuf->desiredy.ptr.p_double[0], 1, &densexy->ptr.pp_double[srcidx][nin], 1, ae_v_len(0,nout-1)); - } - if( datasettype==1 ) - { - for(j=0; j<=nout-1; j++) - { - pbuf->desiredy.ptr.p_double[j] = sparseget(sparsexy, srcidx, nin+j, _state); - } - } - } - dserraccumulate(&pbuf->tmp0, &pbuf->y, &pbuf->desiredy, _state); - } - dserrfinish(&pbuf->tmp0, _state); - rep->relclserror = pbuf->tmp0.ptr.p_double[0]; - rep->avgce = pbuf->tmp0.ptr.p_double[1]/ae_log((double)(2), _state); - rep->rmserror = pbuf->tmp0.ptr.p_double[2]; - rep->avgerror = pbuf->tmp0.ptr.p_double[3]; - rep->avgrelerror = pbuf->tmp0.ptr.p_double[4]; - ae_shared_pool_recycle(buf, &_pbuf, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Calculation of all types of errors on dataset given by sparse matrix - - -- ALGLIB -- - Copyright 10.09.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpeallerrorssparse(mlpensemble* ensemble, - sparsematrix* xy, - ae_int_t npoints, - double* relcls, - double* avgce, - double* rms, - double* avg, - double* avgrel, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_vector buf; - ae_vector workx; - ae_vector y; - ae_vector dy; - ae_int_t nin; - ae_int_t nout; - - ae_frame_make(_state, &_frame_block); - memset(&buf, 0, sizeof(buf)); - memset(&workx, 0, sizeof(workx)); - memset(&y, 0, sizeof(y)); - memset(&dy, 0, sizeof(dy)); - *relcls = 0; - *avgce = 0; - *rms = 0; - *avg = 0; - *avgrel = 0; - ae_vector_init(&buf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&workx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dy, 0, DT_REAL, _state, ae_true); - - nin = mlpgetinputscount(&ensemble->network, _state); - nout = mlpgetoutputscount(&ensemble->network, _state); - if( mlpissoftmax(&ensemble->network, _state) ) - { - ae_vector_set_length(&dy, 1, _state); - dserrallocate(nout, &buf, _state); - } - else - { - ae_vector_set_length(&dy, nout, _state); - dserrallocate(-nout, &buf, _state); - } - for(i=0; i<=npoints-1; i++) - { - sparsegetrow(xy, i, &workx, _state); - mlpeprocess(ensemble, &workx, &y, _state); - if( mlpissoftmax(&ensemble->network, _state) ) - { - dy.ptr.p_double[0] = workx.ptr.p_double[nin]; - } - else - { - ae_v_move(&dy.ptr.p_double[0], 1, &workx.ptr.p_double[nin], 1, ae_v_len(0,nout-1)); - } - dserraccumulate(&buf, &y, &dy, _state); - } - dserrfinish(&buf, _state); - *relcls = buf.ptr.p_double[0]; - *avgce = buf.ptr.p_double[1]; - *rms = buf.ptr.p_double[2]; - *avg = buf.ptr.p_double[3]; - *avgrel = buf.ptr.p_double[4]; - ae_frame_leave(_state); -} - - -/************************************************************************* -Relative classification error on the test set - -INPUT PARAMETERS: - Ensemble- ensemble - XY - test set - NPoints - test set size - -RESULT: - percent of incorrectly classified cases. - Works both for classifier betwork and for regression networks which -are used as classifiers. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -double mlperelclserror(mlpensemble* ensemble, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_frame _frame_block; - modelerrors rep; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&rep, 0, sizeof(rep)); - _modelerrors_init(&rep, _state, ae_true); - - mlpeallerrorsx(ensemble, xy, &ensemble->network.dummysxy, npoints, 0, &ensemble->network.dummyidx, 0, npoints, 0, &ensemble->network.buf, &rep, _state); - result = rep.relclserror; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Average cross-entropy (in bits per element) on the test set - -INPUT PARAMETERS: - Ensemble- ensemble - XY - test set - NPoints - test set size - -RESULT: - CrossEntropy/(NPoints*LN(2)). - Zero if ensemble solves regression task. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -double mlpeavgce(mlpensemble* ensemble, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_frame _frame_block; - modelerrors rep; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&rep, 0, sizeof(rep)); - _modelerrors_init(&rep, _state, ae_true); - - mlpeallerrorsx(ensemble, xy, &ensemble->network.dummysxy, npoints, 0, &ensemble->network.dummyidx, 0, npoints, 0, &ensemble->network.buf, &rep, _state); - result = rep.avgce; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -RMS error on the test set - -INPUT PARAMETERS: - Ensemble- ensemble - XY - test set - NPoints - test set size - -RESULT: - root mean square error. - Its meaning for regression task is obvious. As for classification task -RMS error means error when estimating posterior probabilities. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -double mlpermserror(mlpensemble* ensemble, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_frame _frame_block; - modelerrors rep; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&rep, 0, sizeof(rep)); - _modelerrors_init(&rep, _state, ae_true); - - mlpeallerrorsx(ensemble, xy, &ensemble->network.dummysxy, npoints, 0, &ensemble->network.dummyidx, 0, npoints, 0, &ensemble->network.buf, &rep, _state); - result = rep.rmserror; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Average error on the test set - -INPUT PARAMETERS: - Ensemble- ensemble - XY - test set - NPoints - test set size - -RESULT: - Its meaning for regression task is obvious. As for classification task -it means average error when estimating posterior probabilities. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -double mlpeavgerror(mlpensemble* ensemble, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_frame _frame_block; - modelerrors rep; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&rep, 0, sizeof(rep)); - _modelerrors_init(&rep, _state, ae_true); - - mlpeallerrorsx(ensemble, xy, &ensemble->network.dummysxy, npoints, 0, &ensemble->network.dummyidx, 0, npoints, 0, &ensemble->network.buf, &rep, _state); - result = rep.avgerror; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Average relative error on the test set - -INPUT PARAMETERS: - Ensemble- ensemble - XY - test set - NPoints - test set size - -RESULT: - Its meaning for regression task is obvious. As for classification task -it means average relative error when estimating posterior probabilities. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -double mlpeavgrelerror(mlpensemble* ensemble, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_frame _frame_block; - modelerrors rep; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&rep, 0, sizeof(rep)); - _modelerrors_init(&rep, _state, ae_true); - - mlpeallerrorsx(ensemble, xy, &ensemble->network.dummysxy, npoints, 0, &ensemble->network.dummyidx, 0, npoints, 0, &ensemble->network.buf, &rep, _state); - result = rep.avgrelerror; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Serializer: allocation - - -- ALGLIB -- - Copyright 19.10.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpealloc(ae_serializer* s, mlpensemble* ensemble, ae_state *_state) -{ - - - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - allocrealarray(s, &ensemble->weights, -1, _state); - allocrealarray(s, &ensemble->columnmeans, -1, _state); - allocrealarray(s, &ensemble->columnsigmas, -1, _state); - mlpalloc(s, &ensemble->network, _state); -} - - -/************************************************************************* -Serializer: serialization - - -- ALGLIB -- - Copyright 14.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpeserialize(ae_serializer* s, - mlpensemble* ensemble, - ae_state *_state) -{ - - - ae_serializer_serialize_int(s, getmlpeserializationcode(_state), _state); - ae_serializer_serialize_int(s, mlpe_mlpefirstversion, _state); - ae_serializer_serialize_int(s, ensemble->ensemblesize, _state); - serializerealarray(s, &ensemble->weights, -1, _state); - serializerealarray(s, &ensemble->columnmeans, -1, _state); - serializerealarray(s, &ensemble->columnsigmas, -1, _state); - mlpserialize(s, &ensemble->network, _state); -} - - -/************************************************************************* -Serializer: unserialization - - -- ALGLIB -- - Copyright 14.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpeunserialize(ae_serializer* s, - mlpensemble* ensemble, - ae_state *_state) -{ - ae_int_t i0; - ae_int_t i1; - - _mlpensemble_clear(ensemble); - - - /* - * check correctness of header - */ - ae_serializer_unserialize_int(s, &i0, _state); - ae_assert(i0==getmlpeserializationcode(_state), "MLPEUnserialize: stream header corrupted", _state); - ae_serializer_unserialize_int(s, &i1, _state); - ae_assert(i1==mlpe_mlpefirstversion, "MLPEUnserialize: stream header corrupted", _state); - - /* - * Create network - */ - ae_serializer_unserialize_int(s, &ensemble->ensemblesize, _state); - unserializerealarray(s, &ensemble->weights, _state); - unserializerealarray(s, &ensemble->columnmeans, _state); - unserializerealarray(s, &ensemble->columnsigmas, _state); - mlpunserialize(s, &ensemble->network, _state); - - /* - * Allocate termoraries - */ - ae_vector_set_length(&ensemble->y, mlpgetoutputscount(&ensemble->network, _state), _state); -} - - -void _mlpensemble_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - mlpensemble *p = (mlpensemble*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->weights, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->columnmeans, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->columnsigmas, 0, DT_REAL, _state, make_automatic); - _multilayerperceptron_init(&p->network, _state, make_automatic); - ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic); -} - - -void _mlpensemble_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - mlpensemble *dst = (mlpensemble*)_dst; - mlpensemble *src = (mlpensemble*)_src; - dst->ensemblesize = src->ensemblesize; - ae_vector_init_copy(&dst->weights, &src->weights, _state, make_automatic); - ae_vector_init_copy(&dst->columnmeans, &src->columnmeans, _state, make_automatic); - ae_vector_init_copy(&dst->columnsigmas, &src->columnsigmas, _state, make_automatic); - _multilayerperceptron_init_copy(&dst->network, &src->network, _state, make_automatic); - ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic); -} - - -void _mlpensemble_clear(void* _p) -{ - mlpensemble *p = (mlpensemble*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->weights); - ae_vector_clear(&p->columnmeans); - ae_vector_clear(&p->columnsigmas); - _multilayerperceptron_clear(&p->network); - ae_vector_clear(&p->y); -} - - -void _mlpensemble_destroy(void* _p) -{ - mlpensemble *p = (mlpensemble*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->weights); - ae_vector_destroy(&p->columnmeans); - ae_vector_destroy(&p->columnsigmas); - _multilayerperceptron_destroy(&p->network); - ae_vector_destroy(&p->y); -} - - -#endif -#if defined(AE_COMPILE_MLPTRAIN) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Neural network training using modified Levenberg-Marquardt with exact -Hessian calculation and regularization. Subroutine trains neural network -with restarts from random positions. Algorithm is well suited for small -and medium scale problems (hundreds of weights). - -INPUT PARAMETERS: - Network - neural network with initialized geometry - XY - training set - NPoints - training set size - Decay - weight decay constant, >=0.001 - Decay term 'Decay*||Weights||^2' is added to error - function. - If you don't know what Decay to choose, use 0.001. - Restarts - number of restarts from random position, >0. - If you don't know what Restarts to choose, use 2. - -OUTPUT PARAMETERS: - Network - trained neural network. - Info - return code: - * -9, if internal matrix inverse subroutine failed - * -2, if there is a point with class number - outside of [0..NOut-1]. - * -1, if wrong parameters specified - (NPoints<0, Restarts<1). - * 2, if task has been solved. - Rep - training report - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -void mlptrainlm(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - ae_int_t* info, - mlpreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - double lmsteptol; - ae_int_t i; - ae_int_t k; - double v; - double e; - double enew; - double xnorm2; - double stepnorm; - ae_vector g; - ae_vector d; - ae_matrix h; - ae_matrix hmod; - ae_matrix z; - ae_bool spd; - double nu; - double lambdav; - double lambdaup; - double lambdadown; - minlbfgsreport internalrep; - minlbfgsstate state; - ae_vector x; - ae_vector y; - ae_vector wbase; - ae_vector wdir; - ae_vector wt; - ae_vector wx; - ae_int_t pass; - ae_vector wbest; - double ebest; - ae_int_t invinfo; - matinvreport invrep; - ae_int_t solverinfo; - densesolverreport solverrep; - - ae_frame_make(_state, &_frame_block); - memset(&g, 0, sizeof(g)); - memset(&d, 0, sizeof(d)); - memset(&h, 0, sizeof(h)); - memset(&hmod, 0, sizeof(hmod)); - memset(&z, 0, sizeof(z)); - memset(&internalrep, 0, sizeof(internalrep)); - memset(&state, 0, sizeof(state)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&wbase, 0, sizeof(wbase)); - memset(&wdir, 0, sizeof(wdir)); - memset(&wt, 0, sizeof(wt)); - memset(&wx, 0, sizeof(wx)); - memset(&wbest, 0, sizeof(wbest)); - memset(&invrep, 0, sizeof(invrep)); - memset(&solverrep, 0, sizeof(solverrep)); - *info = 0; - _mlpreport_clear(rep); - ae_vector_init(&g, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&h, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&hmod, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true); - _minlbfgsreport_init(&internalrep, _state, ae_true); - _minlbfgsstate_init(&state, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wbase, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wdir, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wt, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wbest, 0, DT_REAL, _state, ae_true); - _matinvreport_init(&invrep, _state, ae_true); - _densesolverreport_init(&solverrep, _state, ae_true); - - mlpproperties(network, &nin, &nout, &wcount, _state); - lambdaup = (double)(10); - lambdadown = 0.3; - lmsteptol = 0.001; - - /* - * Test for inputs - */ - if( npoints<=0||restarts<1 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - if( mlpissoftmax(network, _state) ) - { - for(i=0; i<=npoints-1; i++) - { - if( ae_round(xy->ptr.pp_double[i][nin], _state)<0||ae_round(xy->ptr.pp_double[i][nin], _state)>=nout ) - { - *info = -2; - ae_frame_leave(_state); - return; - } - } - } - decay = ae_maxreal(decay, mlptrain_mindecay, _state); - *info = 2; - - /* - * Initialize data - */ - rep->ngrad = 0; - rep->nhess = 0; - rep->ncholesky = 0; - - /* - * General case. - * Prepare task and network. Allocate space. - */ - mlpinitpreprocessor(network, xy, npoints, _state); - ae_vector_set_length(&g, wcount-1+1, _state); - ae_matrix_set_length(&h, wcount-1+1, wcount-1+1, _state); - ae_matrix_set_length(&hmod, wcount-1+1, wcount-1+1, _state); - ae_vector_set_length(&wbase, wcount-1+1, _state); - ae_vector_set_length(&wdir, wcount-1+1, _state); - ae_vector_set_length(&wbest, wcount-1+1, _state); - ae_vector_set_length(&wt, wcount-1+1, _state); - ae_vector_set_length(&wx, wcount-1+1, _state); - ebest = ae_maxrealnumber; - - /* - * Multiple passes - */ - for(pass=1; pass<=restarts; pass++) - { - - /* - * Initialize weights - */ - mlprandomize(network, _state); - - /* - * First stage of the hybrid algorithm: LBFGS - */ - ae_v_move(&wbase.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - minlbfgscreate(wcount, ae_minint(wcount, 5, _state), &wbase, &state, _state); - minlbfgssetcond(&state, (double)(0), (double)(0), (double)(0), ae_maxint(25, wcount, _state), _state); - while(minlbfgsiteration(&state, _state)) - { - - /* - * gradient - */ - ae_v_move(&network->weights.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - mlpgradbatch(network, xy, npoints, &state.f, &state.g, _state); - - /* - * weight decay - */ - v = ae_v_dotproduct(&network->weights.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - state.f = state.f+0.5*decay*v; - ae_v_addd(&state.g.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), decay); - - /* - * next iteration - */ - rep->ngrad = rep->ngrad+1; - } - minlbfgsresults(&state, &wbase, &internalrep, _state); - ae_v_move(&network->weights.ptr.p_double[0], 1, &wbase.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - - /* - * Second stage of the hybrid algorithm: LM - * - * Initialize H with identity matrix, - * G with gradient, - * E with regularized error. - */ - mlphessianbatch(network, xy, npoints, &e, &g, &h, _state); - v = ae_v_dotproduct(&network->weights.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - e = e+0.5*decay*v; - ae_v_addd(&g.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), decay); - for(k=0; k<=wcount-1; k++) - { - h.ptr.pp_double[k][k] = h.ptr.pp_double[k][k]+decay; - } - rep->nhess = rep->nhess+1; - lambdav = 0.001; - nu = (double)(2); - for(;;) - { - - /* - * 1. HMod = H+lambda*I - * 2. Try to solve (H+Lambda*I)*dx = -g. - * Increase lambda if left part is not positive definite. - */ - for(i=0; i<=wcount-1; i++) - { - ae_v_move(&hmod.ptr.pp_double[i][0], 1, &h.ptr.pp_double[i][0], 1, ae_v_len(0,wcount-1)); - hmod.ptr.pp_double[i][i] = hmod.ptr.pp_double[i][i]+lambdav; - } - spd = spdmatrixcholesky(&hmod, wcount, ae_true, _state); - rep->ncholesky = rep->ncholesky+1; - if( !spd ) - { - lambdav = lambdav*lambdaup*nu; - nu = nu*2; - continue; - } - spdmatrixcholeskysolve(&hmod, wcount, ae_true, &g, &solverinfo, &solverrep, &wdir, _state); - if( solverinfo<0 ) - { - lambdav = lambdav*lambdaup*nu; - nu = nu*2; - continue; - } - ae_v_muld(&wdir.ptr.p_double[0], 1, ae_v_len(0,wcount-1), -1); - - /* - * Lambda found. - * 1. Save old w in WBase - * 1. Test some stopping criterions - * 2. If error(w+wdir)>error(w), increase lambda - */ - ae_v_add(&network->weights.ptr.p_double[0], 1, &wdir.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - xnorm2 = ae_v_dotproduct(&network->weights.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - stepnorm = ae_v_dotproduct(&wdir.ptr.p_double[0], 1, &wdir.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - stepnorm = ae_sqrt(stepnorm, _state); - enew = mlperror(network, xy, npoints, _state)+0.5*decay*xnorm2; - if( ae_fp_less(stepnorm,lmsteptol*(1+ae_sqrt(xnorm2, _state))) ) - { - break; - } - if( ae_fp_greater(enew,e) ) - { - lambdav = lambdav*lambdaup*nu; - nu = nu*2; - continue; - } - - /* - * Optimize using inv(cholesky(H)) as preconditioner - */ - rmatrixtrinverse(&hmod, wcount, ae_true, ae_false, &invinfo, &invrep, _state); - if( invinfo<=0 ) - { - - /* - * if matrix can't be inverted then exit with errors - * TODO: make WCount steps in direction suggested by HMod - */ - *info = -9; - ae_frame_leave(_state); - return; - } - ae_v_move(&wbase.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - for(i=0; i<=wcount-1; i++) - { - wt.ptr.p_double[i] = (double)(0); - } - minlbfgscreatex(wcount, wcount, &wt, 1, 0.0, &state, _state); - minlbfgssetcond(&state, (double)(0), (double)(0), (double)(0), 5, _state); - while(minlbfgsiteration(&state, _state)) - { - - /* - * gradient - */ - for(i=0; i<=wcount-1; i++) - { - v = ae_v_dotproduct(&state.x.ptr.p_double[i], 1, &hmod.ptr.pp_double[i][i], 1, ae_v_len(i,wcount-1)); - network->weights.ptr.p_double[i] = wbase.ptr.p_double[i]+v; - } - mlpgradbatch(network, xy, npoints, &state.f, &g, _state); - for(i=0; i<=wcount-1; i++) - { - state.g.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=wcount-1; i++) - { - v = g.ptr.p_double[i]; - ae_v_addd(&state.g.ptr.p_double[i], 1, &hmod.ptr.pp_double[i][i], 1, ae_v_len(i,wcount-1), v); - } - - /* - * weight decay - * grad(x'*x) = A'*(x0+A*t) - */ - v = ae_v_dotproduct(&network->weights.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - state.f = state.f+0.5*decay*v; - for(i=0; i<=wcount-1; i++) - { - v = decay*network->weights.ptr.p_double[i]; - ae_v_addd(&state.g.ptr.p_double[i], 1, &hmod.ptr.pp_double[i][i], 1, ae_v_len(i,wcount-1), v); - } - - /* - * next iteration - */ - rep->ngrad = rep->ngrad+1; - } - minlbfgsresults(&state, &wt, &internalrep, _state); - - /* - * Accept new position. - * Calculate Hessian - */ - for(i=0; i<=wcount-1; i++) - { - v = ae_v_dotproduct(&wt.ptr.p_double[i], 1, &hmod.ptr.pp_double[i][i], 1, ae_v_len(i,wcount-1)); - network->weights.ptr.p_double[i] = wbase.ptr.p_double[i]+v; - } - mlphessianbatch(network, xy, npoints, &e, &g, &h, _state); - v = ae_v_dotproduct(&network->weights.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - e = e+0.5*decay*v; - ae_v_addd(&g.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), decay); - for(k=0; k<=wcount-1; k++) - { - h.ptr.pp_double[k][k] = h.ptr.pp_double[k][k]+decay; - } - rep->nhess = rep->nhess+1; - - /* - * Update lambda - */ - lambdav = lambdav*lambdadown; - nu = (double)(2); - } - - /* - * update WBest - */ - v = ae_v_dotproduct(&network->weights.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - e = 0.5*decay*v+mlperror(network, xy, npoints, _state); - if( ae_fp_less(e,ebest) ) - { - ebest = e; - ae_v_move(&wbest.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - } - } - - /* - * copy WBest to output - */ - ae_v_move(&network->weights.ptr.p_double[0], 1, &wbest.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -Neural network training using L-BFGS algorithm with regularization. -Subroutine trains neural network with restarts from random positions. -Algorithm is well suited for problems of any dimensionality (memory -requirements and step complexity are linear by weights number). - -INPUT PARAMETERS: - Network - neural network with initialized geometry - XY - training set - NPoints - training set size - Decay - weight decay constant, >=0.001 - Decay term 'Decay*||Weights||^2' is added to error - function. - If you don't know what Decay to choose, use 0.001. - Restarts - number of restarts from random position, >0. - If you don't know what Restarts to choose, use 2. - WStep - stopping criterion. Algorithm stops if step size is - less than WStep. Recommended value - 0.01. Zero step - size means stopping after MaxIts iterations. - MaxIts - stopping criterion. Algorithm stops after MaxIts - iterations (NOT gradient calculations). Zero MaxIts - means stopping when step is sufficiently small. - -OUTPUT PARAMETERS: - Network - trained neural network. - Info - return code: - * -8, if both WStep=0 and MaxIts=0 - * -2, if there is a point with class number - outside of [0..NOut-1]. - * -1, if wrong parameters specified - (NPoints<0, Restarts<1). - * 2, if task has been solved. - Rep - training report - - -- ALGLIB -- - Copyright 09.12.2007 by Bochkanov Sergey -*************************************************************************/ -void mlptrainlbfgs(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - double wstep, - ae_int_t maxits, - ae_int_t* info, - mlpreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t pass; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_vector w; - ae_vector wbest; - double e; - double v; - double ebest; - minlbfgsreport internalrep; - minlbfgsstate state; - - ae_frame_make(_state, &_frame_block); - memset(&w, 0, sizeof(w)); - memset(&wbest, 0, sizeof(wbest)); - memset(&internalrep, 0, sizeof(internalrep)); - memset(&state, 0, sizeof(state)); - *info = 0; - _mlpreport_clear(rep); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wbest, 0, DT_REAL, _state, ae_true); - _minlbfgsreport_init(&internalrep, _state, ae_true); - _minlbfgsstate_init(&state, _state, ae_true); - - - /* - * Test inputs, parse flags, read network geometry - */ - if( ae_fp_eq(wstep,(double)(0))&&maxits==0 ) - { - *info = -8; - ae_frame_leave(_state); - return; - } - if( ((npoints<=0||restarts<1)||ae_fp_less(wstep,(double)(0)))||maxits<0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - mlpproperties(network, &nin, &nout, &wcount, _state); - if( mlpissoftmax(network, _state) ) - { - for(i=0; i<=npoints-1; i++) - { - if( ae_round(xy->ptr.pp_double[i][nin], _state)<0||ae_round(xy->ptr.pp_double[i][nin], _state)>=nout ) - { - *info = -2; - ae_frame_leave(_state); - return; - } - } - } - decay = ae_maxreal(decay, mlptrain_mindecay, _state); - *info = 2; - - /* - * Prepare - */ - mlpinitpreprocessor(network, xy, npoints, _state); - ae_vector_set_length(&w, wcount-1+1, _state); - ae_vector_set_length(&wbest, wcount-1+1, _state); - ebest = ae_maxrealnumber; - - /* - * Multiple starts - */ - rep->ncholesky = 0; - rep->nhess = 0; - rep->ngrad = 0; - for(pass=1; pass<=restarts; pass++) - { - - /* - * Process - */ - mlprandomize(network, _state); - ae_v_move(&w.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - minlbfgscreate(wcount, ae_minint(wcount, 10, _state), &w, &state, _state); - minlbfgssetcond(&state, 0.0, 0.0, wstep, maxits, _state); - while(minlbfgsiteration(&state, _state)) - { - ae_v_move(&network->weights.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - mlpgradnbatch(network, xy, npoints, &state.f, &state.g, _state); - v = ae_v_dotproduct(&network->weights.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - state.f = state.f+0.5*decay*v; - ae_v_addd(&state.g.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), decay); - rep->ngrad = rep->ngrad+1; - } - minlbfgsresults(&state, &w, &internalrep, _state); - ae_v_move(&network->weights.ptr.p_double[0], 1, &w.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - - /* - * Compare with best - */ - v = ae_v_dotproduct(&network->weights.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - e = mlperrorn(network, xy, npoints, _state)+0.5*decay*v; - if( ae_fp_less(e,ebest) ) - { - ae_v_move(&wbest.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - ebest = e; - } - } - - /* - * The best network - */ - ae_v_move(&network->weights.ptr.p_double[0], 1, &wbest.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -Neural network training using early stopping (base algorithm - L-BFGS with -regularization). - -INPUT PARAMETERS: - Network - neural network with initialized geometry - TrnXY - training set - TrnSize - training set size, TrnSize>0 - ValXY - validation set - ValSize - validation set size, ValSize>0 - Decay - weight decay constant, >=0.001 - Decay term 'Decay*||Weights||^2' is added to error - function. - If you don't know what Decay to choose, use 0.001. - Restarts - number of restarts, either: - * strictly positive number - algorithm make specified - number of restarts from random position. - * -1, in which case algorithm makes exactly one run - from the initial state of the network (no randomization). - If you don't know what Restarts to choose, choose one - one the following: - * -1 (deterministic start) - * +1 (one random restart) - * +5 (moderate amount of random restarts) - -OUTPUT PARAMETERS: - Network - trained neural network. - Info - return code: - * -2, if there is a point with class number - outside of [0..NOut-1]. - * -1, if wrong parameters specified - (NPoints<0, Restarts<1, ...). - * 2, task has been solved, stopping criterion met - - sufficiently small step size. Not expected (we - use EARLY stopping) but possible and not an - error. - * 6, task has been solved, stopping criterion met - - increasing of validation set error. - Rep - training report - -NOTE: - -Algorithm stops if validation set error increases for a long enough or -step size is small enought (there are task where validation set may -decrease for eternity). In any case solution returned corresponds to the -minimum of validation set error. - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -void mlptraines(multilayerperceptron* network, - /* Real */ ae_matrix* trnxy, - ae_int_t trnsize, - /* Real */ ae_matrix* valxy, - ae_int_t valsize, - double decay, - ae_int_t restarts, - ae_int_t* info, - mlpreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t pass; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_vector w; - ae_vector wbest; - double e; - double v; - double ebest; - ae_vector wfinal; - double efinal; - ae_int_t itcnt; - ae_int_t itbest; - minlbfgsreport internalrep; - minlbfgsstate state; - double wstep; - ae_bool needrandomization; - - ae_frame_make(_state, &_frame_block); - memset(&w, 0, sizeof(w)); - memset(&wbest, 0, sizeof(wbest)); - memset(&wfinal, 0, sizeof(wfinal)); - memset(&internalrep, 0, sizeof(internalrep)); - memset(&state, 0, sizeof(state)); - *info = 0; - _mlpreport_clear(rep); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wbest, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wfinal, 0, DT_REAL, _state, ae_true); - _minlbfgsreport_init(&internalrep, _state, ae_true); - _minlbfgsstate_init(&state, _state, ae_true); - - wstep = 0.001; - - /* - * Test inputs, parse flags, read network geometry - */ - if( ((trnsize<=0||valsize<=0)||(restarts<1&&restarts!=-1))||ae_fp_less(decay,(double)(0)) ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - if( restarts==-1 ) - { - needrandomization = ae_false; - restarts = 1; - } - else - { - needrandomization = ae_true; - } - mlpproperties(network, &nin, &nout, &wcount, _state); - if( mlpissoftmax(network, _state) ) - { - for(i=0; i<=trnsize-1; i++) - { - if( ae_round(trnxy->ptr.pp_double[i][nin], _state)<0||ae_round(trnxy->ptr.pp_double[i][nin], _state)>=nout ) - { - *info = -2; - ae_frame_leave(_state); - return; - } - } - for(i=0; i<=valsize-1; i++) - { - if( ae_round(valxy->ptr.pp_double[i][nin], _state)<0||ae_round(valxy->ptr.pp_double[i][nin], _state)>=nout ) - { - *info = -2; - ae_frame_leave(_state); - return; - } - } - } - *info = 2; - - /* - * Prepare - */ - mlpinitpreprocessor(network, trnxy, trnsize, _state); - ae_vector_set_length(&w, wcount-1+1, _state); - ae_vector_set_length(&wbest, wcount-1+1, _state); - ae_vector_set_length(&wfinal, wcount-1+1, _state); - efinal = ae_maxrealnumber; - for(i=0; i<=wcount-1; i++) - { - wfinal.ptr.p_double[i] = (double)(0); - } - - /* - * Multiple starts - */ - rep->ncholesky = 0; - rep->nhess = 0; - rep->ngrad = 0; - for(pass=1; pass<=restarts; pass++) - { - - /* - * Process - */ - if( needrandomization ) - { - mlprandomize(network, _state); - } - ebest = mlperror(network, valxy, valsize, _state); - ae_v_move(&wbest.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - itbest = 0; - itcnt = 0; - ae_v_move(&w.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - minlbfgscreate(wcount, ae_minint(wcount, 10, _state), &w, &state, _state); - minlbfgssetcond(&state, 0.0, 0.0, wstep, 0, _state); - minlbfgssetxrep(&state, ae_true, _state); - while(minlbfgsiteration(&state, _state)) - { - - /* - * Calculate gradient - */ - if( state.needfg ) - { - ae_v_move(&network->weights.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - mlpgradnbatch(network, trnxy, trnsize, &state.f, &state.g, _state); - v = ae_v_dotproduct(&network->weights.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - state.f = state.f+0.5*decay*v; - ae_v_addd(&state.g.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), decay); - rep->ngrad = rep->ngrad+1; - } - - /* - * Validation set - */ - if( state.xupdated ) - { - ae_v_move(&network->weights.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - e = mlperror(network, valxy, valsize, _state); - if( ae_fp_less(e,ebest) ) - { - ebest = e; - ae_v_move(&wbest.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - itbest = itcnt; - } - if( itcnt>30&&ae_fp_greater((double)(itcnt),1.5*itbest) ) - { - *info = 6; - break; - } - itcnt = itcnt+1; - } - } - minlbfgsresults(&state, &w, &internalrep, _state); - - /* - * Compare with final answer - */ - if( ae_fp_less(ebest,efinal) ) - { - ae_v_move(&wfinal.ptr.p_double[0], 1, &wbest.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - efinal = ebest; - } - } - - /* - * The best network - */ - ae_v_move(&network->weights.ptr.p_double[0], 1, &wfinal.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -Cross-validation estimate of generalization error. - -Base algorithm - L-BFGS. - -INPUT PARAMETERS: - Network - neural network with initialized geometry. Network is - not changed during cross-validation - it is used only - as a representative of its architecture. - XY - training set. - SSize - training set size - Decay - weight decay, same as in MLPTrainLBFGS - Restarts - number of restarts, >0. - restarts are counted for each partition separately, so - total number of restarts will be Restarts*FoldsCount. - WStep - stopping criterion, same as in MLPTrainLBFGS - MaxIts - stopping criterion, same as in MLPTrainLBFGS - FoldsCount - number of folds in k-fold cross-validation, - 2<=FoldsCount<=SSize. - recommended value: 10. - -OUTPUT PARAMETERS: - Info - return code, same as in MLPTrainLBFGS - Rep - report, same as in MLPTrainLM/MLPTrainLBFGS - CVRep - generalization error estimates - - -- ALGLIB -- - Copyright 09.12.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpkfoldcvlbfgs(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - double wstep, - ae_int_t maxits, - ae_int_t foldscount, - ae_int_t* info, - mlpreport* rep, - mlpcvreport* cvrep, - ae_state *_state) -{ - - *info = 0; - _mlpreport_clear(rep); - _mlpcvreport_clear(cvrep); - - mlptrain_mlpkfoldcvgeneral(network, xy, npoints, decay, restarts, foldscount, ae_false, wstep, maxits, info, rep, cvrep, _state); -} - - -/************************************************************************* -Cross-validation estimate of generalization error. - -Base algorithm - Levenberg-Marquardt. - -INPUT PARAMETERS: - Network - neural network with initialized geometry. Network is - not changed during cross-validation - it is used only - as a representative of its architecture. - XY - training set. - SSize - training set size - Decay - weight decay, same as in MLPTrainLBFGS - Restarts - number of restarts, >0. - restarts are counted for each partition separately, so - total number of restarts will be Restarts*FoldsCount. - FoldsCount - number of folds in k-fold cross-validation, - 2<=FoldsCount<=SSize. - recommended value: 10. - -OUTPUT PARAMETERS: - Info - return code, same as in MLPTrainLBFGS - Rep - report, same as in MLPTrainLM/MLPTrainLBFGS - CVRep - generalization error estimates - - -- ALGLIB -- - Copyright 09.12.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpkfoldcvlm(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - ae_int_t foldscount, - ae_int_t* info, - mlpreport* rep, - mlpcvreport* cvrep, - ae_state *_state) -{ - - *info = 0; - _mlpreport_clear(rep); - _mlpcvreport_clear(cvrep); - - mlptrain_mlpkfoldcvgeneral(network, xy, npoints, decay, restarts, foldscount, ae_true, 0.0, 0, info, rep, cvrep, _state); -} - - -/************************************************************************* -This function estimates generalization error using cross-validation on the -current dataset with current training settings. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - trainer object - Network - neural network. It must have same number of inputs and - output/classes as was specified during creation of the - trainer object. Network is not changed during cross- - validation and is not trained - it is used only as - representative of its architecture. I.e., we estimate - generalization properties of ARCHITECTURE, not some - specific network. - NRestarts - number of restarts, >=0: - * NRestarts>0 means that for each cross-validation - round specified number of random restarts is - performed, with best network being chosen after - training. - * NRestarts=0 is same as NRestarts=1 - FoldsCount - number of folds in k-fold cross-validation: - * 2<=FoldsCount<=size of dataset - * recommended value: 10. - * values larger than dataset size will be silently - truncated down to dataset size - -OUTPUT PARAMETERS: - Rep - structure which contains cross-validation estimates: - * Rep.RelCLSError - fraction of misclassified cases. - * Rep.AvgCE - acerage cross-entropy - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average error - * Rep.AvgRelError - average relative error - -NOTE: when no dataset was specified with MLPSetDataset/SetSparseDataset(), - or subset with only one point was given, zeros are returned as - estimates. - -NOTE: this method performs FoldsCount cross-validation rounds, each one - with NRestarts random starts. Thus, FoldsCount*NRestarts networks - are trained in total. - -NOTE: Rep.RelCLSError/Rep.AvgCE are zero on regression problems. - -NOTE: on classification problems Rep.RMSError/Rep.AvgError/Rep.AvgRelError - contain errors in prediction of posterior probabilities. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpkfoldcv(mlptrainer* s, - multilayerperceptron* network, - ae_int_t nrestarts, - ae_int_t foldscount, - mlpreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_shared_pool pooldatacv; - mlpparallelizationcv datacv; - mlpparallelizationcv *sdatacv; - ae_smart_ptr _sdatacv; - ae_matrix cvy; - ae_vector folds; - ae_vector buf; - ae_vector dy; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t rowsize; - ae_int_t ntype; - ae_int_t ttype; - ae_int_t i; - ae_int_t j; - ae_int_t k; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&pooldatacv, 0, sizeof(pooldatacv)); - memset(&datacv, 0, sizeof(datacv)); - memset(&_sdatacv, 0, sizeof(_sdatacv)); - memset(&cvy, 0, sizeof(cvy)); - memset(&folds, 0, sizeof(folds)); - memset(&buf, 0, sizeof(buf)); - memset(&dy, 0, sizeof(dy)); - memset(&rs, 0, sizeof(rs)); - _mlpreport_clear(rep); - ae_shared_pool_init(&pooldatacv, _state, ae_true); - _mlpparallelizationcv_init(&datacv, _state, ae_true); - ae_smart_ptr_init(&_sdatacv, (void**)&sdatacv, _state, ae_true); - ae_matrix_init(&cvy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&folds, 0, DT_INT, _state, ae_true); - ae_vector_init(&buf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dy, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - if( !mlpissoftmax(network, _state) ) - { - ntype = 0; - } - else - { - ntype = 1; - } - if( s->rcpar ) - { - ttype = 0; - } - else - { - ttype = 1; - } - ae_assert(ntype==ttype, "MLPKFoldCV: type of input network is not similar to network type in trainer object", _state); - ae_assert(s->npoints>=0, "MLPKFoldCV: possible trainer S is not initialized(S.NPoints<0)", _state); - mlpproperties(network, &nin, &nout, &wcount, _state); - ae_assert(s->nin==nin, "MLPKFoldCV: number of inputs in trainer is not equal to number of inputs in network", _state); - ae_assert(s->nout==nout, "MLPKFoldCV: number of outputs in trainer is not equal to number of outputs in network", _state); - ae_assert(nrestarts>=0, "MLPKFoldCV: NRestarts<0", _state); - ae_assert(foldscount>=2, "MLPKFoldCV: FoldsCount<2", _state); - if( foldscount>s->npoints ) - { - foldscount = s->npoints; - } - rep->relclserror = (double)(0); - rep->avgce = (double)(0); - rep->rmserror = (double)(0); - rep->avgerror = (double)(0); - rep->avgrelerror = (double)(0); - hqrndrandomize(&rs, _state); - rep->ngrad = 0; - rep->nhess = 0; - rep->ncholesky = 0; - if( s->npoints==0||s->npoints==1 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Read network geometry, test parameters - */ - if( s->rcpar ) - { - rowsize = nin+nout; - ae_vector_set_length(&dy, nout, _state); - dserrallocate(-nout, &buf, _state); - } - else - { - rowsize = nin+1; - ae_vector_set_length(&dy, 1, _state); - dserrallocate(nout, &buf, _state); - } - - /* - * Folds - */ - ae_vector_set_length(&folds, s->npoints, _state); - for(i=0; i<=s->npoints-1; i++) - { - folds.ptr.p_int[i] = i*foldscount/s->npoints; - } - for(i=0; i<=s->npoints-2; i++) - { - j = i+hqrnduniformi(&rs, s->npoints-i, _state); - if( j!=i ) - { - k = folds.ptr.p_int[i]; - folds.ptr.p_int[i] = folds.ptr.p_int[j]; - folds.ptr.p_int[j] = k; - } - } - ae_matrix_set_length(&cvy, s->npoints, nout, _state); - - /* - * Initialize SEED-value for shared pool - */ - datacv.ngrad = 0; - mlpcopy(network, &datacv.network, _state); - ae_vector_set_length(&datacv.subset, s->npoints, _state); - ae_vector_set_length(&datacv.xyrow, rowsize, _state); - ae_vector_set_length(&datacv.y, nout, _state); - - /* - * Create shared pool - */ - ae_shared_pool_set_seed(&pooldatacv, &datacv, sizeof(datacv), _mlpparallelizationcv_init, _mlpparallelizationcv_init_copy, _mlpparallelizationcv_destroy, _state); - - /* - * Parallelization - */ - mlptrain_mthreadcv(s, rowsize, nrestarts, &folds, 0, foldscount, &cvy, &pooldatacv, wcount, _state); - - /* - * Calculate value for NGrad - */ - ae_shared_pool_first_recycled(&pooldatacv, &_sdatacv, _state); - while(sdatacv!=NULL) - { - rep->ngrad = rep->ngrad+sdatacv->ngrad; - ae_shared_pool_next_recycled(&pooldatacv, &_sdatacv, _state); - } - - /* - * Connect of results and calculate cross-validation error - */ - for(i=0; i<=s->npoints-1; i++) - { - if( s->datatype==0 ) - { - ae_v_move(&datacv.xyrow.ptr.p_double[0], 1, &s->densexy.ptr.pp_double[i][0], 1, ae_v_len(0,rowsize-1)); - } - if( s->datatype==1 ) - { - sparsegetrow(&s->sparsexy, i, &datacv.xyrow, _state); - } - ae_v_move(&datacv.y.ptr.p_double[0], 1, &cvy.ptr.pp_double[i][0], 1, ae_v_len(0,nout-1)); - if( s->rcpar ) - { - ae_v_move(&dy.ptr.p_double[0], 1, &datacv.xyrow.ptr.p_double[nin], 1, ae_v_len(0,nout-1)); - } - else - { - dy.ptr.p_double[0] = datacv.xyrow.ptr.p_double[nin]; - } - dserraccumulate(&buf, &datacv.y, &dy, _state); - } - dserrfinish(&buf, _state); - rep->relclserror = buf.ptr.p_double[0]; - rep->avgce = buf.ptr.p_double[1]; - rep->rmserror = buf.ptr.p_double[2]; - rep->avgerror = buf.ptr.p_double[3]; - rep->avgrelerror = buf.ptr.p_double[4]; - ae_frame_leave(_state); -} - - -/************************************************************************* -Creation of the network trainer object for regression networks - -INPUT PARAMETERS: - NIn - number of inputs, NIn>=1 - NOut - number of outputs, NOut>=1 - -OUTPUT PARAMETERS: - S - neural network trainer object. - This structure can be used to train any regression - network with NIn inputs and NOut outputs. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpcreatetrainer(ae_int_t nin, - ae_int_t nout, - mlptrainer* s, - ae_state *_state) -{ - - _mlptrainer_clear(s); - - ae_assert(nin>=1, "MLPCreateTrainer: NIn<1.", _state); - ae_assert(nout>=1, "MLPCreateTrainer: NOut<1.", _state); - s->nin = nin; - s->nout = nout; - s->rcpar = ae_true; - s->lbfgsfactor = mlptrain_defaultlbfgsfactor; - s->decay = 1.0E-6; - mlpsetcond(s, (double)(0), 0, _state); - s->datatype = 0; - s->npoints = 0; - mlpsetalgobatch(s, _state); -} - - -/************************************************************************* -Creation of the network trainer object for classification networks - -INPUT PARAMETERS: - NIn - number of inputs, NIn>=1 - NClasses - number of classes, NClasses>=2 - -OUTPUT PARAMETERS: - S - neural network trainer object. - This structure can be used to train any classification - network with NIn inputs and NOut outputs. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpcreatetrainercls(ae_int_t nin, - ae_int_t nclasses, - mlptrainer* s, - ae_state *_state) -{ - - _mlptrainer_clear(s); - - ae_assert(nin>=1, "MLPCreateTrainerCls: NIn<1.", _state); - ae_assert(nclasses>=2, "MLPCreateTrainerCls: NClasses<2.", _state); - s->nin = nin; - s->nout = nclasses; - s->rcpar = ae_false; - s->lbfgsfactor = mlptrain_defaultlbfgsfactor; - s->decay = 1.0E-6; - mlpsetcond(s, (double)(0), 0, _state); - s->datatype = 0; - s->npoints = 0; - mlpsetalgobatch(s, _state); -} - - -/************************************************************************* -This function sets "current dataset" of the trainer object to one passed -by user. - -INPUT PARAMETERS: - S - trainer object - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. - NPoints - points count, >=0. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -datasetformat is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpsetdataset(mlptrainer* s, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_int_t ndim; - ae_int_t i; - ae_int_t j; - - - ae_assert(s->nin>=1, "MLPSetDataset: possible parameter S is not initialized or spoiled(S.NIn<=0).", _state); - ae_assert(npoints>=0, "MLPSetDataset: NPoint<0", _state); - ae_assert(npoints<=xy->rows, "MLPSetDataset: invalid size of matrix XY(NPoint more then rows of matrix XY)", _state); - s->datatype = 0; - s->npoints = npoints; - if( npoints==0 ) - { - return; - } - if( s->rcpar ) - { - ae_assert(s->nout>=1, "MLPSetDataset: possible parameter S is not initialized or is spoiled(NOut<1 for regression).", _state); - ndim = s->nin+s->nout; - ae_assert(ndim<=xy->cols, "MLPSetDataset: invalid size of matrix XY(too few columns in matrix XY).", _state); - ae_assert(apservisfinitematrix(xy, npoints, ndim, _state), "MLPSetDataset: parameter XY contains Infinite or NaN.", _state); - } - else - { - ae_assert(s->nout>=2, "MLPSetDataset: possible parameter S is not initialized or is spoiled(NClasses<2 for classifier).", _state); - ndim = s->nin+1; - ae_assert(ndim<=xy->cols, "MLPSetDataset: invalid size of matrix XY(too few columns in matrix XY).", _state); - ae_assert(apservisfinitematrix(xy, npoints, ndim, _state), "MLPSetDataset: parameter XY contains Infinite or NaN.", _state); - for(i=0; i<=npoints-1; i++) - { - ae_assert(ae_round(xy->ptr.pp_double[i][s->nin], _state)>=0&&ae_round(xy->ptr.pp_double[i][s->nin], _state)nout, "MLPSetDataset: invalid parameter XY(in classifier used nonexistent class number: either XY[.,NIn]<0 or XY[.,NIn]>=NClasses).", _state); - } - } - rmatrixsetlengthatleast(&s->densexy, npoints, ndim, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=ndim-1; j++) - { - s->densexy.ptr.pp_double[i][j] = xy->ptr.pp_double[i][j]; - } - } -} - - -/************************************************************************* -This function sets "current dataset" of the trainer object to one passed -by user (sparse matrix is used to store dataset). - -INPUT PARAMETERS: - S - trainer object - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Any sparse storage format can be used: - Hash-table, CRS... - NPoints - points count, >=0 - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -datasetformat is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpsetsparsedataset(mlptrainer* s, - sparsematrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - double v; - ae_int_t t0; - ae_int_t t1; - ae_int_t i; - ae_int_t j; - - - - /* - * Check correctness of the data - */ - ae_assert(s->nin>0, "MLPSetSparseDataset: possible parameter S is not initialized or spoiled(S.NIn<=0).", _state); - ae_assert(npoints>=0, "MLPSetSparseDataset: NPoint<0", _state); - ae_assert(npoints<=sparsegetnrows(xy, _state), "MLPSetSparseDataset: invalid size of sparse matrix XY(NPoint more then rows of matrix XY)", _state); - if( npoints>0 ) - { - t0 = 0; - t1 = 0; - if( s->rcpar ) - { - ae_assert(s->nout>=1, "MLPSetSparseDataset: possible parameter S is not initialized or is spoiled(NOut<1 for regression).", _state); - ae_assert(s->nin+s->nout<=sparsegetncols(xy, _state), "MLPSetSparseDataset: invalid size of sparse matrix XY(too few columns in sparse matrix XY).", _state); - while(sparseenumerate(xy, &t0, &t1, &i, &j, &v, _state)) - { - if( inin+s->nout ) - { - ae_assert(ae_isfinite(v, _state), "MLPSetSparseDataset: sparse matrix XY contains Infinite or NaN.", _state); - } - } - } - else - { - ae_assert(s->nout>=2, "MLPSetSparseDataset: possible parameter S is not initialized or is spoiled(NClasses<2 for classifier).", _state); - ae_assert(s->nin+1<=sparsegetncols(xy, _state), "MLPSetSparseDataset: invalid size of sparse matrix XY(too few columns in sparse matrix XY).", _state); - while(sparseenumerate(xy, &t0, &t1, &i, &j, &v, _state)) - { - if( inin ) - { - if( j!=s->nin ) - { - ae_assert(ae_isfinite(v, _state), "MLPSetSparseDataset: sparse matrix XY contains Infinite or NaN.", _state); - } - else - { - ae_assert((ae_isfinite(v, _state)&&ae_round(v, _state)>=0)&&ae_round(v, _state)nout, "MLPSetSparseDataset: invalid sparse matrix XY(in classifier used nonexistent class number: either XY[.,NIn]<0 or XY[.,NIn]>=NClasses).", _state); - } - } - } - } - } - - /* - * Set dataset - */ - s->datatype = 1; - s->npoints = npoints; - sparsecopytocrs(xy, &s->sparsexy, _state); -} - - -/************************************************************************* -This function sets weight decay coefficient which is used for training. - -INPUT PARAMETERS: - S - trainer object - Decay - weight decay coefficient, >=0. Weight decay term - 'Decay*||Weights||^2' is added to error function. If - you don't know what Decay to choose, use 1.0E-3. - Weight decay can be set to zero, in this case network - is trained without weight decay. - -NOTE: by default network uses some small nonzero value for weight decay. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpsetdecay(mlptrainer* s, double decay, ae_state *_state) -{ - - - ae_assert(ae_isfinite(decay, _state), "MLPSetDecay: parameter Decay contains Infinite or NaN.", _state); - ae_assert(ae_fp_greater_eq(decay,(double)(0)), "MLPSetDecay: Decay<0.", _state); - s->decay = decay; -} - - -/************************************************************************* -This function sets stopping criteria for the optimizer. - -INPUT PARAMETERS: - S - trainer object - WStep - stopping criterion. Algorithm stops if step size is - less than WStep. Recommended value - 0.01. Zero step - size means stopping after MaxIts iterations. - WStep>=0. - MaxIts - stopping criterion. Algorithm stops after MaxIts - epochs (full passes over entire dataset). Zero MaxIts - means stopping when step is sufficiently small. - MaxIts>=0. - -NOTE: by default, WStep=0.005 and MaxIts=0 are used. These values are also - used when MLPSetCond() is called with WStep=0 and MaxIts=0. - -NOTE: these stopping criteria are used for all kinds of neural training - - from "conventional" networks to early stopping ensembles. When used - for "conventional" networks, they are used as the only stopping - criteria. When combined with early stopping, they used as ADDITIONAL - stopping criteria which can terminate early stopping algorithm. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpsetcond(mlptrainer* s, - double wstep, - ae_int_t maxits, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(wstep, _state), "MLPSetCond: parameter WStep contains Infinite or NaN.", _state); - ae_assert(ae_fp_greater_eq(wstep,(double)(0)), "MLPSetCond: WStep<0.", _state); - ae_assert(maxits>=0, "MLPSetCond: MaxIts<0.", _state); - if( ae_fp_neq(wstep,(double)(0))||maxits!=0 ) - { - s->wstep = wstep; - s->maxits = maxits; - } - else - { - s->wstep = 0.005; - s->maxits = 0; - } -} - - -/************************************************************************* -This function sets training algorithm: batch training using L-BFGS will be -used. - -This algorithm: -* the most robust for small-scale problems, but may be too slow for large - scale ones. -* perfoms full pass through the dataset before performing step -* uses conditions specified by MLPSetCond() for stopping -* is default one used by trainer object - -INPUT PARAMETERS: - S - trainer object - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpsetalgobatch(mlptrainer* s, ae_state *_state) -{ - - - s->algokind = 0; -} - - -/************************************************************************* -This function trains neural network passed to this function, using current -dataset (one which was passed to MLPSetDataset() or MLPSetSparseDataset()) -and current training settings. Training from NRestarts random starting -positions is performed, best network is chosen. - -Training is performed using current training algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - trainer object - Network - neural network. It must have same number of inputs and - output/classes as was specified during creation of the - trainer object. - NRestarts - number of restarts, >=0: - * NRestarts>0 means that specified number of random - restarts are performed, best network is chosen after - training - * NRestarts=0 means that current state of the network - is used for training. - -OUTPUT PARAMETERS: - Network - trained network - -NOTE: when no dataset was specified with MLPSetDataset/SetSparseDataset(), - network is filled by zero values. Same behavior for functions - MLPStartTraining and MLPContinueTraining. - -NOTE: this method uses sum-of-squares error function for training. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlptrainnetwork(mlptrainer* s, - multilayerperceptron* network, - ae_int_t nrestarts, - mlpreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t ntype; - ae_int_t ttype; - ae_shared_pool trnpool; - - ae_frame_make(_state, &_frame_block); - memset(&trnpool, 0, sizeof(trnpool)); - _mlpreport_clear(rep); - ae_shared_pool_init(&trnpool, _state, ae_true); - - ae_assert(s->npoints>=0, "MLPTrainNetwork: parameter S is not initialized or is spoiled(S.NPoints<0)", _state); - if( !mlpissoftmax(network, _state) ) - { - ntype = 0; - } - else - { - ntype = 1; - } - if( s->rcpar ) - { - ttype = 0; - } - else - { - ttype = 1; - } - ae_assert(ntype==ttype, "MLPTrainNetwork: type of input network is not similar to network type in trainer object", _state); - mlpproperties(network, &nin, &nout, &wcount, _state); - ae_assert(s->nin==nin, "MLPTrainNetwork: number of inputs in trainer is not equal to number of inputs in network", _state); - ae_assert(s->nout==nout, "MLPTrainNetwork: number of outputs in trainer is not equal to number of outputs in network", _state); - ae_assert(nrestarts>=0, "MLPTrainNetwork: NRestarts<0.", _state); - - /* - * Train - */ - mlptrain_mlptrainnetworkx(s, nrestarts, -1, &s->subset, -1, &s->subset, 0, network, rep, ae_true, &trnpool, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -IMPORTANT: this is an "expert" version of the MLPTrain() function. We do - not recommend you to use it unless you are pretty sure that you - need ability to monitor training progress. - -This function performs step-by-step training of the neural network. Here -"step-by-step" means that training starts with MLPStartTraining() call, -and then user subsequently calls MLPContinueTraining() to perform one more -iteration of the training. - -After call to this function trainer object remembers network and is ready -to train it. However, no training is performed until first call to -MLPContinueTraining() function. Subsequent calls to MLPContinueTraining() -will advance training progress one iteration further. - -EXAMPLE: - > - > ...initialize network and trainer object.... - > - > MLPStartTraining(Trainer, Network, True) - > while MLPContinueTraining(Trainer, Network) do - > ...visualize training progress... - > - -INPUT PARAMETERS: - S - trainer object - Network - neural network. It must have same number of inputs and - output/classes as was specified during creation of the - trainer object. - RandomStart - randomize network before training or not: - * True means that network is randomized and its - initial state (one which was passed to the trainer - object) is lost. - * False means that training is started from the - current state of the network - -OUTPUT PARAMETERS: - Network - neural network which is ready to training (weights are - initialized, preprocessor is initialized using current - training set) - -NOTE: this method uses sum-of-squares error function for training. - -NOTE: it is expected that trainer object settings are NOT changed during - step-by-step training, i.e. no one changes stopping criteria or - training set during training. It is possible and there is no defense - against such actions, but algorithm behavior in such cases is - undefined and can be unpredictable. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpstarttraining(mlptrainer* s, - multilayerperceptron* network, - ae_bool randomstart, - ae_state *_state) -{ - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t ntype; - ae_int_t ttype; - - - ae_assert(s->npoints>=0, "MLPStartTraining: parameter S is not initialized or is spoiled(S.NPoints<0)", _state); - if( !mlpissoftmax(network, _state) ) - { - ntype = 0; - } - else - { - ntype = 1; - } - if( s->rcpar ) - { - ttype = 0; - } - else - { - ttype = 1; - } - ae_assert(ntype==ttype, "MLPStartTraining: type of input network is not similar to network type in trainer object", _state); - mlpproperties(network, &nin, &nout, &wcount, _state); - ae_assert(s->nin==nin, "MLPStartTraining: number of inputs in trainer is not equal to number of inputs in the network.", _state); - ae_assert(s->nout==nout, "MLPStartTraining: number of outputs in trainer is not equal to number of outputs in the network.", _state); - - /* - * Initialize temporaries - */ - mlptrain_initmlptrnsession(network, randomstart, s, &s->session, _state); - - /* - * Train network - */ - mlptrain_mlpstarttrainingx(s, randomstart, -1, &s->subset, -1, &s->session, _state); - - /* - * Update network - */ - mlpcopytunableparameters(&s->session.network, network, _state); -} - - -/************************************************************************* -IMPORTANT: this is an "expert" version of the MLPTrain() function. We do - not recommend you to use it unless you are pretty sure that you - need ability to monitor training progress. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -This function performs step-by-step training of the neural network. Here -"step-by-step" means that training starts with MLPStartTraining() call, -and then user subsequently calls MLPContinueTraining() to perform one more -iteration of the training. - -This function performs one more iteration of the training and returns -either True (training continues) or False (training stopped). In case True -was returned, Network weights are updated according to the current state -of the optimization progress. In case False was returned, no additional -updates is performed (previous update of the network weights moved us to -the final point, and no additional updates is needed). - -EXAMPLE: - > - > [initialize network and trainer object] - > - > MLPStartTraining(Trainer, Network, True) - > while MLPContinueTraining(Trainer, Network) do - > [visualize training progress] - > - -INPUT PARAMETERS: - S - trainer object - Network - neural network structure, which is used to store - current state of the training process. - -OUTPUT PARAMETERS: - Network - weights of the neural network are rewritten by the - current approximation. - -NOTE: this method uses sum-of-squares error function for training. - -NOTE: it is expected that trainer object settings are NOT changed during - step-by-step training, i.e. no one changes stopping criteria or - training set during training. It is possible and there is no defense - against such actions, but algorithm behavior in such cases is - undefined and can be unpredictable. - -NOTE: It is expected that Network is the same one which was passed to - MLPStartTraining() function. However, THIS function checks only - following: - * that number of network inputs is consistent with trainer object - settings - * that number of network outputs/classes is consistent with trainer - object settings - * that number of network weights is the same as number of weights in - the network passed to MLPStartTraining() function - Exception is thrown when these conditions are violated. - - It is also expected that you do not change state of the network on - your own - the only party who has right to change network during its - training is a trainer object. Any attempt to interfere with trainer - may lead to unpredictable results. - - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -ae_bool mlpcontinuetraining(mlptrainer* s, - multilayerperceptron* network, - ae_state *_state) -{ - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t ntype; - ae_int_t ttype; - ae_bool result; - - - ae_assert(s->npoints>=0, "MLPContinueTraining: parameter S is not initialized or is spoiled(S.NPoints<0)", _state); - if( s->rcpar ) - { - ttype = 0; - } - else - { - ttype = 1; - } - if( !mlpissoftmax(network, _state) ) - { - ntype = 0; - } - else - { - ntype = 1; - } - ae_assert(ntype==ttype, "MLPContinueTraining: type of input network is not similar to network type in trainer object.", _state); - mlpproperties(network, &nin, &nout, &wcount, _state); - ae_assert(s->nin==nin, "MLPContinueTraining: number of inputs in trainer is not equal to number of inputs in the network.", _state); - ae_assert(s->nout==nout, "MLPContinueTraining: number of outputs in trainer is not equal to number of outputs in the network.", _state); - result = mlptrain_mlpcontinuetrainingx(s, &s->subset, -1, &s->ngradbatch, &s->session, _state); - if( result ) - { - ae_v_move(&network->weights.ptr.p_double[0], 1, &s->session.network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - } - return result; -} - - -/************************************************************************* -Training neural networks ensemble using bootstrap aggregating (bagging). -Modified Levenberg-Marquardt algorithm is used as base training method. - -INPUT PARAMETERS: - Ensemble - model with initialized geometry - XY - training set - NPoints - training set size - Decay - weight decay coefficient, >=0.001 - Restarts - restarts, >0. - -OUTPUT PARAMETERS: - Ensemble - trained model - Info - return code: - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed - (NPoints<0, Restarts<1). - * 2, if task has been solved. - Rep - training report. - OOBErrors - out-of-bag generalization error estimate - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpebagginglm(mlpensemble* ensemble, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - ae_int_t* info, - mlpreport* rep, - mlpcvreport* ooberrors, - ae_state *_state) -{ - - *info = 0; - _mlpreport_clear(rep); - _mlpcvreport_clear(ooberrors); - - mlptrain_mlpebagginginternal(ensemble, xy, npoints, decay, restarts, 0.0, 0, ae_true, info, rep, ooberrors, _state); -} - - -/************************************************************************* -Training neural networks ensemble using bootstrap aggregating (bagging). -L-BFGS algorithm is used as base training method. - -INPUT PARAMETERS: - Ensemble - model with initialized geometry - XY - training set - NPoints - training set size - Decay - weight decay coefficient, >=0.001 - Restarts - restarts, >0. - WStep - stopping criterion, same as in MLPTrainLBFGS - MaxIts - stopping criterion, same as in MLPTrainLBFGS - -OUTPUT PARAMETERS: - Ensemble - trained model - Info - return code: - * -8, if both WStep=0 and MaxIts=0 - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed - (NPoints<0, Restarts<1). - * 2, if task has been solved. - Rep - training report. - OOBErrors - out-of-bag generalization error estimate - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpebagginglbfgs(mlpensemble* ensemble, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - double wstep, - ae_int_t maxits, - ae_int_t* info, - mlpreport* rep, - mlpcvreport* ooberrors, - ae_state *_state) -{ - - *info = 0; - _mlpreport_clear(rep); - _mlpcvreport_clear(ooberrors); - - mlptrain_mlpebagginginternal(ensemble, xy, npoints, decay, restarts, wstep, maxits, ae_false, info, rep, ooberrors, _state); -} - - -/************************************************************************* -Training neural networks ensemble using early stopping. - -INPUT PARAMETERS: - Ensemble - model with initialized geometry - XY - training set - NPoints - training set size - Decay - weight decay coefficient, >=0.001 - Restarts - restarts, >0. - -OUTPUT PARAMETERS: - Ensemble - trained model - Info - return code: - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed - (NPoints<0, Restarts<1). - * 6, if task has been solved. - Rep - training report. - OOBErrors - out-of-bag generalization error estimate - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpetraines(mlpensemble* ensemble, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - ae_int_t* info, - mlpreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t k; - ae_int_t ccount; - ae_int_t pcount; - ae_matrix trnxy; - ae_matrix valxy; - ae_int_t trnsize; - ae_int_t valsize; - ae_int_t tmpinfo; - mlpreport tmprep; - modelerrors moderr; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - - ae_frame_make(_state, &_frame_block); - memset(&trnxy, 0, sizeof(trnxy)); - memset(&valxy, 0, sizeof(valxy)); - memset(&tmprep, 0, sizeof(tmprep)); - memset(&moderr, 0, sizeof(moderr)); - *info = 0; - _mlpreport_clear(rep); - ae_matrix_init(&trnxy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&valxy, 0, 0, DT_REAL, _state, ae_true); - _mlpreport_init(&tmprep, _state, ae_true); - _modelerrors_init(&moderr, _state, ae_true); - - nin = mlpgetinputscount(&ensemble->network, _state); - nout = mlpgetoutputscount(&ensemble->network, _state); - wcount = mlpgetweightscount(&ensemble->network, _state); - if( (npoints<2||restarts<1)||ae_fp_less(decay,(double)(0)) ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - if( mlpissoftmax(&ensemble->network, _state) ) - { - for(i=0; i<=npoints-1; i++) - { - if( ae_round(xy->ptr.pp_double[i][nin], _state)<0||ae_round(xy->ptr.pp_double[i][nin], _state)>=nout ) - { - *info = -2; - ae_frame_leave(_state); - return; - } - } - } - *info = 6; - - /* - * allocate - */ - if( mlpissoftmax(&ensemble->network, _state) ) - { - ccount = nin+1; - pcount = nin; - } - else - { - ccount = nin+nout; - pcount = nin+nout; - } - ae_matrix_set_length(&trnxy, npoints, ccount, _state); - ae_matrix_set_length(&valxy, npoints, ccount, _state); - rep->ngrad = 0; - rep->nhess = 0; - rep->ncholesky = 0; - - /* - * train networks - */ - for(k=0; k<=ensemble->ensemblesize-1; k++) - { - - /* - * Split set - */ - do - { - trnsize = 0; - valsize = 0; - for(i=0; i<=npoints-1; i++) - { - if( ae_fp_less(ae_randomreal(_state),0.66) ) - { - - /* - * Assign sample to training set - */ - ae_v_move(&trnxy.ptr.pp_double[trnsize][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,ccount-1)); - trnsize = trnsize+1; - } - else - { - - /* - * Assign sample to validation set - */ - ae_v_move(&valxy.ptr.pp_double[valsize][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,ccount-1)); - valsize = valsize+1; - } - } - } - while(!(trnsize!=0&&valsize!=0)); - - /* - * Train - */ - mlptraines(&ensemble->network, &trnxy, trnsize, &valxy, valsize, decay, restarts, &tmpinfo, &tmprep, _state); - if( tmpinfo<0 ) - { - *info = tmpinfo; - ae_frame_leave(_state); - return; - } - - /* - * save results - */ - ae_v_move(&ensemble->weights.ptr.p_double[k*wcount], 1, &ensemble->network.weights.ptr.p_double[0], 1, ae_v_len(k*wcount,(k+1)*wcount-1)); - ae_v_move(&ensemble->columnmeans.ptr.p_double[k*pcount], 1, &ensemble->network.columnmeans.ptr.p_double[0], 1, ae_v_len(k*pcount,(k+1)*pcount-1)); - ae_v_move(&ensemble->columnsigmas.ptr.p_double[k*pcount], 1, &ensemble->network.columnsigmas.ptr.p_double[0], 1, ae_v_len(k*pcount,(k+1)*pcount-1)); - rep->ngrad = rep->ngrad+tmprep.ngrad; - rep->nhess = rep->nhess+tmprep.nhess; - rep->ncholesky = rep->ncholesky+tmprep.ncholesky; - } - mlpeallerrorsx(ensemble, xy, &ensemble->network.dummysxy, npoints, 0, &ensemble->network.dummyidx, 0, npoints, 0, &ensemble->network.buf, &moderr, _state); - rep->relclserror = moderr.relclserror; - rep->avgce = moderr.avgce; - rep->rmserror = moderr.rmserror; - rep->avgerror = moderr.avgerror; - rep->avgrelerror = moderr.avgrelerror; - ae_frame_leave(_state); -} - - -/************************************************************************* -This function trains neural network ensemble passed to this function using -current dataset and early stopping training algorithm. Each early stopping -round performs NRestarts random restarts (thus, EnsembleSize*NRestarts -training rounds is performed in total). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - trainer object; - Ensemble - neural network ensemble. It must have same number of - inputs and outputs/classes as was specified during - creation of the trainer object. - NRestarts - number of restarts, >=0: - * NRestarts>0 means that specified number of random - restarts are performed during each ES round; - * NRestarts=0 is silently replaced by 1. - -OUTPUT PARAMETERS: - Ensemble - trained ensemble; - Rep - it contains all type of errors. - -NOTE: this training method uses BOTH early stopping and weight decay! So, - you should select weight decay before starting training just as you - select it before training "conventional" networks. - -NOTE: when no dataset was specified with MLPSetDataset/SetSparseDataset(), - or single-point dataset was passed, ensemble is filled by zero - values. - -NOTE: this method uses sum-of-squares error function for training. - - -- ALGLIB -- - Copyright 22.08.2012 by Bochkanov Sergey -*************************************************************************/ -void mlptrainensemblees(mlptrainer* s, - mlpensemble* ensemble, - ae_int_t nrestarts, - mlpreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nin; - ae_int_t nout; - ae_int_t ntype; - ae_int_t ttype; - ae_shared_pool esessions; - sinteger sgrad; - modelerrors tmprep; - - ae_frame_make(_state, &_frame_block); - memset(&esessions, 0, sizeof(esessions)); - memset(&sgrad, 0, sizeof(sgrad)); - memset(&tmprep, 0, sizeof(tmprep)); - _mlpreport_clear(rep); - ae_shared_pool_init(&esessions, _state, ae_true); - _sinteger_init(&sgrad, _state, ae_true); - _modelerrors_init(&tmprep, _state, ae_true); - - ae_assert(s->npoints>=0, "MLPTrainEnsembleES: parameter S is not initialized or is spoiled(S.NPoints<0)", _state); - if( !mlpeissoftmax(ensemble, _state) ) - { - ntype = 0; - } - else - { - ntype = 1; - } - if( s->rcpar ) - { - ttype = 0; - } - else - { - ttype = 1; - } - ae_assert(ntype==ttype, "MLPTrainEnsembleES: internal error - type of input network is not similar to network type in trainer object", _state); - nin = mlpgetinputscount(&ensemble->network, _state); - ae_assert(s->nin==nin, "MLPTrainEnsembleES: number of inputs in trainer is not equal to number of inputs in ensemble network", _state); - nout = mlpgetoutputscount(&ensemble->network, _state); - ae_assert(s->nout==nout, "MLPTrainEnsembleES: number of outputs in trainer is not equal to number of outputs in ensemble network", _state); - ae_assert(nrestarts>=0, "MLPTrainEnsembleES: NRestarts<0.", _state); - - /* - * Initialize parameter Rep - */ - rep->relclserror = (double)(0); - rep->avgce = (double)(0); - rep->rmserror = (double)(0); - rep->avgerror = (double)(0); - rep->avgrelerror = (double)(0); - rep->ngrad = 0; - rep->nhess = 0; - rep->ncholesky = 0; - - /* - * Allocate - */ - ivectorsetlengthatleast(&s->subset, s->npoints, _state); - ivectorsetlengthatleast(&s->valsubset, s->npoints, _state); - - /* - * Start training - * - * NOTE: ESessions is not initialized because MLPTrainEnsembleX - * needs uninitialized pool. - */ - sgrad.val = 0; - mlptrain_mlptrainensemblex(s, ensemble, 0, ensemble->ensemblesize, nrestarts, 0, &sgrad, ae_true, &esessions, _state); - rep->ngrad = sgrad.val; - - /* - * Calculate errors. - */ - if( s->datatype==0 ) - { - mlpeallerrorsx(ensemble, &s->densexy, &s->sparsexy, s->npoints, 0, &ensemble->network.dummyidx, 0, s->npoints, 0, &ensemble->network.buf, &tmprep, _state); - } - if( s->datatype==1 ) - { - mlpeallerrorsx(ensemble, &s->densexy, &s->sparsexy, s->npoints, 1, &ensemble->network.dummyidx, 0, s->npoints, 0, &ensemble->network.buf, &tmprep, _state); - } - rep->relclserror = tmprep.relclserror; - rep->avgce = tmprep.avgce; - rep->rmserror = tmprep.rmserror; - rep->avgerror = tmprep.avgerror; - rep->avgrelerror = tmprep.avgrelerror; - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal cross-validation subroutine -*************************************************************************/ -static void mlptrain_mlpkfoldcvgeneral(multilayerperceptron* n, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - ae_int_t foldscount, - ae_bool lmalgorithm, - double wstep, - ae_int_t maxits, - ae_int_t* info, - mlpreport* rep, - mlpcvreport* cvrep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t fold; - ae_int_t j; - ae_int_t k; - multilayerperceptron network; - ae_int_t nin; - ae_int_t nout; - ae_int_t rowlen; - ae_int_t wcount; - ae_int_t nclasses; - ae_int_t tssize; - ae_int_t cvssize; - ae_matrix cvset; - ae_matrix testset; - ae_vector folds; - ae_int_t relcnt; - mlpreport internalrep; - ae_vector x; - ae_vector y; - - ae_frame_make(_state, &_frame_block); - memset(&network, 0, sizeof(network)); - memset(&cvset, 0, sizeof(cvset)); - memset(&testset, 0, sizeof(testset)); - memset(&folds, 0, sizeof(folds)); - memset(&internalrep, 0, sizeof(internalrep)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - *info = 0; - _mlpreport_clear(rep); - _mlpcvreport_clear(cvrep); - _multilayerperceptron_init(&network, _state, ae_true); - ae_matrix_init(&cvset, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&testset, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&folds, 0, DT_INT, _state, ae_true); - _mlpreport_init(&internalrep, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - - - /* - * Read network geometry, test parameters - */ - mlpproperties(n, &nin, &nout, &wcount, _state); - if( mlpissoftmax(n, _state) ) - { - nclasses = nout; - rowlen = nin+1; - } - else - { - nclasses = -nout; - rowlen = nin+nout; - } - if( (npoints<=0||foldscount<2)||foldscount>npoints ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - mlpcopy(n, &network, _state); - - /* - * K-fold out cross-validation. - * First, estimate generalization error - */ - ae_matrix_set_length(&testset, npoints-1+1, rowlen-1+1, _state); - ae_matrix_set_length(&cvset, npoints-1+1, rowlen-1+1, _state); - ae_vector_set_length(&x, nin-1+1, _state); - ae_vector_set_length(&y, nout-1+1, _state); - mlptrain_mlpkfoldsplit(xy, npoints, nclasses, foldscount, ae_false, &folds, _state); - cvrep->relclserror = (double)(0); - cvrep->avgce = (double)(0); - cvrep->rmserror = (double)(0); - cvrep->avgerror = (double)(0); - cvrep->avgrelerror = (double)(0); - rep->ngrad = 0; - rep->nhess = 0; - rep->ncholesky = 0; - relcnt = 0; - for(fold=0; fold<=foldscount-1; fold++) - { - - /* - * Separate set - */ - tssize = 0; - cvssize = 0; - for(i=0; i<=npoints-1; i++) - { - if( folds.ptr.p_int[i]==fold ) - { - ae_v_move(&testset.ptr.pp_double[tssize][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,rowlen-1)); - tssize = tssize+1; - } - else - { - ae_v_move(&cvset.ptr.pp_double[cvssize][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,rowlen-1)); - cvssize = cvssize+1; - } - } - - /* - * Train on CV training set - */ - if( lmalgorithm ) - { - mlptrainlm(&network, &cvset, cvssize, decay, restarts, info, &internalrep, _state); - } - else - { - mlptrainlbfgs(&network, &cvset, cvssize, decay, restarts, wstep, maxits, info, &internalrep, _state); - } - if( *info<0 ) - { - cvrep->relclserror = (double)(0); - cvrep->avgce = (double)(0); - cvrep->rmserror = (double)(0); - cvrep->avgerror = (double)(0); - cvrep->avgrelerror = (double)(0); - ae_frame_leave(_state); - return; - } - rep->ngrad = rep->ngrad+internalrep.ngrad; - rep->nhess = rep->nhess+internalrep.nhess; - rep->ncholesky = rep->ncholesky+internalrep.ncholesky; - - /* - * Estimate error using CV test set - */ - if( mlpissoftmax(&network, _state) ) - { - - /* - * classification-only code - */ - cvrep->relclserror = cvrep->relclserror+mlpclserror(&network, &testset, tssize, _state); - cvrep->avgce = cvrep->avgce+mlperrorn(&network, &testset, tssize, _state); - } - for(i=0; i<=tssize-1; i++) - { - ae_v_move(&x.ptr.p_double[0], 1, &testset.ptr.pp_double[i][0], 1, ae_v_len(0,nin-1)); - mlpprocess(&network, &x, &y, _state); - if( mlpissoftmax(&network, _state) ) - { - - /* - * Classification-specific code - */ - k = ae_round(testset.ptr.pp_double[i][nin], _state); - for(j=0; j<=nout-1; j++) - { - if( j==k ) - { - cvrep->rmserror = cvrep->rmserror+ae_sqr(y.ptr.p_double[j]-1, _state); - cvrep->avgerror = cvrep->avgerror+ae_fabs(y.ptr.p_double[j]-1, _state); - cvrep->avgrelerror = cvrep->avgrelerror+ae_fabs(y.ptr.p_double[j]-1, _state); - relcnt = relcnt+1; - } - else - { - cvrep->rmserror = cvrep->rmserror+ae_sqr(y.ptr.p_double[j], _state); - cvrep->avgerror = cvrep->avgerror+ae_fabs(y.ptr.p_double[j], _state); - } - } - } - else - { - - /* - * Regression-specific code - */ - for(j=0; j<=nout-1; j++) - { - cvrep->rmserror = cvrep->rmserror+ae_sqr(y.ptr.p_double[j]-testset.ptr.pp_double[i][nin+j], _state); - cvrep->avgerror = cvrep->avgerror+ae_fabs(y.ptr.p_double[j]-testset.ptr.pp_double[i][nin+j], _state); - if( ae_fp_neq(testset.ptr.pp_double[i][nin+j],(double)(0)) ) - { - cvrep->avgrelerror = cvrep->avgrelerror+ae_fabs((y.ptr.p_double[j]-testset.ptr.pp_double[i][nin+j])/testset.ptr.pp_double[i][nin+j], _state); - relcnt = relcnt+1; - } - } - } - } - } - if( mlpissoftmax(&network, _state) ) - { - cvrep->relclserror = cvrep->relclserror/npoints; - cvrep->avgce = cvrep->avgce/(ae_log((double)(2), _state)*npoints); - } - cvrep->rmserror = ae_sqrt(cvrep->rmserror/(npoints*nout), _state); - cvrep->avgerror = cvrep->avgerror/(npoints*nout); - if( relcnt>0 ) - { - cvrep->avgrelerror = cvrep->avgrelerror/relcnt; - } - *info = 1; - ae_frame_leave(_state); -} - - -/************************************************************************* -Subroutine prepares K-fold split of the training set. - -NOTES: - "NClasses>0" means that we have classification task. - "NClasses<0" means regression task with -NClasses real outputs. -*************************************************************************/ -static void mlptrain_mlpkfoldsplit(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nclasses, - ae_int_t foldscount, - ae_bool stratifiedsplits, - /* Integer */ ae_vector* folds, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t k; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - ae_vector_clear(folds); - _hqrndstate_init(&rs, _state, ae_true); - - - /* - * test parameters - */ - ae_assert(npoints>0, "MLPKFoldSplit: wrong NPoints!", _state); - ae_assert(nclasses>1||nclasses<0, "MLPKFoldSplit: wrong NClasses!", _state); - ae_assert(foldscount>=2&&foldscount<=npoints, "MLPKFoldSplit: wrong FoldsCount!", _state); - ae_assert(!stratifiedsplits, "MLPKFoldSplit: stratified splits are not supported!", _state); - - /* - * Folds - */ - hqrndrandomize(&rs, _state); - ae_vector_set_length(folds, npoints-1+1, _state); - for(i=0; i<=npoints-1; i++) - { - folds->ptr.p_int[i] = i*foldscount/npoints; - } - for(i=0; i<=npoints-2; i++) - { - j = i+hqrnduniformi(&rs, npoints-i, _state); - if( j!=i ) - { - k = folds->ptr.p_int[i]; - folds->ptr.p_int[i] = folds->ptr.p_int[j]; - folds->ptr.p_int[j] = k; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal subroutine for parallelization function MLPFoldCV. - - -INPUT PARAMETERS: - S - trainer object; - RowSize - row size(eitherNIn+NOut or NIn+1); - NRestarts - number of restarts(>=0); - Folds - cross-validation set; - Fold - the number of first cross-validation(>=0); - DFold - the number of second cross-validation(>=Fold+1); - CVY - parameter which stores the result is returned by network, - training on I-th cross-validation set. - It has to be preallocated. - PoolDataCV- parameter for parallelization. - WCount - number of weights in network, used to make decisions on - parallelization. - -NOTE: There are no checks on the parameters correctness. - - -- ALGLIB -- - Copyright 25.09.2012 by Bochkanov Sergey -*************************************************************************/ -static void mlptrain_mthreadcv(mlptrainer* s, - ae_int_t rowsize, - ae_int_t nrestarts, - /* Integer */ ae_vector* folds, - ae_int_t fold, - ae_int_t dfold, - /* Real */ ae_matrix* cvy, - ae_shared_pool* pooldatacv, - ae_int_t wcount, - ae_state *_state) -{ - ae_frame _frame_block; - mlpparallelizationcv *datacv; - ae_smart_ptr _datacv; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&_datacv, 0, sizeof(_datacv)); - ae_smart_ptr_init(&_datacv, (void**)&datacv, _state, ae_true); - - if( fold==dfold-1 ) - { - - /* - * Separate set - */ - ae_shared_pool_retrieve(pooldatacv, &_datacv, _state); - datacv->subsetsize = 0; - for(i=0; i<=s->npoints-1; i++) - { - if( folds->ptr.p_int[i]!=fold ) - { - datacv->subset.ptr.p_int[datacv->subsetsize] = i; - datacv->subsetsize = datacv->subsetsize+1; - } - } - - /* - * Train on CV training set - */ - mlptrain_mlptrainnetworkx(s, nrestarts, -1, &datacv->subset, datacv->subsetsize, &datacv->subset, 0, &datacv->network, &datacv->rep, ae_true, &datacv->trnpool, _state); - datacv->ngrad = datacv->ngrad+datacv->rep.ngrad; - - /* - * Estimate error using CV test set - */ - for(i=0; i<=s->npoints-1; i++) - { - if( folds->ptr.p_int[i]==fold ) - { - if( s->datatype==0 ) - { - ae_v_move(&datacv->xyrow.ptr.p_double[0], 1, &s->densexy.ptr.pp_double[i][0], 1, ae_v_len(0,rowsize-1)); - } - if( s->datatype==1 ) - { - sparsegetrow(&s->sparsexy, i, &datacv->xyrow, _state); - } - mlpprocess(&datacv->network, &datacv->xyrow, &datacv->y, _state); - ae_v_move(&cvy->ptr.pp_double[i][0], 1, &datacv->y.ptr.p_double[0], 1, ae_v_len(0,s->nout-1)); - } - } - ae_shared_pool_recycle(pooldatacv, &_datacv, _state); - } - else - { - ae_assert(foldDFold-1).", _state); - - /* - * We expect that minimum number of iterations before convergence is 100. - * Hence is our approach to evaluation of task complexity. - */ - if( ae_fp_greater_eq(ae_maxint(nrestarts, 1, _state)*rmul3((double)(2*wcount), (double)(s->npoints), (double)(100), _state),smpactivationlevel(_state)) ) - { - if( _trypexec_mlptrain_mthreadcv(s,rowsize,nrestarts,folds,fold,dfold,cvy,pooldatacv,wcount, _state) ) - { - ae_frame_leave(_state); - return; - } - } - - /* - * Split task - */ - mlptrain_mthreadcv(s, rowsize, nrestarts, folds, fold, (fold+dfold)/2, cvy, pooldatacv, wcount, _state); - mlptrain_mthreadcv(s, rowsize, nrestarts, folds, (fold+dfold)/2, dfold, cvy, pooldatacv, wcount, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_mlptrain_mthreadcv(mlptrainer* s, - ae_int_t rowsize, - ae_int_t nrestarts, - /* Integer */ ae_vector* folds, - ae_int_t fold, - ae_int_t dfold, - /* Real */ ae_matrix* cvy, - ae_shared_pool* pooldatacv, - ae_int_t wcount, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -This function trains neural network passed to this function, using current -dataset (one which was passed to MLPSetDataset() or MLPSetSparseDataset()) -and current training settings. Training from NRestarts random starting -positions is performed, best network is chosen. - -This function is inteded to be used internally. It may be used in several -settings: -* training with ValSubsetSize=0, corresponds to "normal" training with - termination criteria based on S.MaxIts (steps count) and S.WStep (step - size). Training sample is given by TrnSubset/TrnSubsetSize. -* training with ValSubsetSize>0, corresponds to early stopping training - with additional MaxIts/WStep stopping criteria. Training sample is given - by TrnSubset/TrnSubsetSize, validation sample is given by ValSubset/ - ValSubsetSize. - - -- ALGLIB -- - Copyright 13.08.2012 by Bochkanov Sergey -*************************************************************************/ -static void mlptrain_mlptrainnetworkx(mlptrainer* s, - ae_int_t nrestarts, - ae_int_t algokind, - /* Integer */ ae_vector* trnsubset, - ae_int_t trnsubsetsize, - /* Integer */ ae_vector* valsubset, - ae_int_t valsubsetsize, - multilayerperceptron* network, - mlpreport* rep, - ae_bool isrootcall, - ae_shared_pool* sessions, - ae_state *_state) -{ - ae_frame _frame_block; - modelerrors modrep; - double eval; - double ebest; - ae_int_t ngradbatch; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t pcount; - ae_int_t itbest; - ae_int_t itcnt; - ae_int_t ntype; - ae_int_t ttype; - ae_bool rndstart; - ae_int_t i; - ae_int_t nr0; - ae_int_t nr1; - mlpreport rep0; - mlpreport rep1; - ae_bool randomizenetwork; - double bestrmserror; - smlptrnsession *psession; - ae_smart_ptr _psession; - - ae_frame_make(_state, &_frame_block); - memset(&modrep, 0, sizeof(modrep)); - memset(&rep0, 0, sizeof(rep0)); - memset(&rep1, 0, sizeof(rep1)); - memset(&_psession, 0, sizeof(_psession)); - _modelerrors_init(&modrep, _state, ae_true); - _mlpreport_init(&rep0, _state, ae_true); - _mlpreport_init(&rep1, _state, ae_true); - ae_smart_ptr_init(&_psession, (void**)&psession, _state, ae_true); - - mlpproperties(network, &nin, &nout, &wcount, _state); - - /* - * Process root call - */ - if( isrootcall ) - { - - /* - * Try parallelization - * We expect that minimum number of iterations before convergence is 100. - * Hence is our approach to evaluation of task complexity. - */ - if( ae_fp_greater_eq(ae_maxint(nrestarts, 1, _state)*rmul3((double)(2*wcount), (double)(s->npoints), (double)(100), _state),smpactivationlevel(_state)) ) - { - if( _trypexec_mlptrain_mlptrainnetworkx(s,nrestarts,algokind,trnsubset,trnsubsetsize,valsubset,valsubsetsize,network,rep,isrootcall,sessions, _state) ) - { - ae_frame_leave(_state); - return; - } - } - - /* - * Check correctness of parameters - */ - ae_assert(algokind==0||algokind==-1, "MLPTrainNetworkX: unexpected AlgoKind", _state); - ae_assert(s->npoints>=0, "MLPTrainNetworkX: internal error - parameter S is not initialized or is spoiled(S.NPoints<0)", _state); - if( s->rcpar ) - { - ttype = 0; - } - else - { - ttype = 1; - } - if( !mlpissoftmax(network, _state) ) - { - ntype = 0; - } - else - { - ntype = 1; - } - ae_assert(ntype==ttype, "MLPTrainNetworkX: internal error - type of the training network is not similar to network type in trainer object", _state); - ae_assert(s->nin==nin, "MLPTrainNetworkX: internal error - number of inputs in trainer is not equal to number of inputs in the training network.", _state); - ae_assert(s->nout==nout, "MLPTrainNetworkX: internal error - number of outputs in trainer is not equal to number of outputs in the training network.", _state); - ae_assert(nrestarts>=0, "MLPTrainNetworkX: internal error - NRestarts<0.", _state); - ae_assert(trnsubset->cnt>=trnsubsetsize, "MLPTrainNetworkX: internal error - parameter TrnSubsetSize more than input subset size(Length(TrnSubset)ptr.p_int[i]>=0&&trnsubset->ptr.p_int[i]<=s->npoints-1, "MLPTrainNetworkX: internal error - parameter TrnSubset contains incorrect index(TrnSubset[I]<0 or TrnSubset[I]>S.NPoints-1)", _state); - } - ae_assert(valsubset->cnt>=valsubsetsize, "MLPTrainNetworkX: internal error - parameter ValSubsetSize more than input subset size(Length(ValSubset)ptr.p_int[i]>=0&&valsubset->ptr.p_int[i]<=s->npoints-1, "MLPTrainNetworkX: internal error - parameter ValSubset contains incorrect index(ValSubset[I]<0 or ValSubset[I]>S.NPoints-1)", _state); - } - - /* - * Train - */ - randomizenetwork = nrestarts>0; - mlptrain_initmlptrnsessions(network, randomizenetwork, s, sessions, _state); - mlptrain_mlptrainnetworkx(s, nrestarts, algokind, trnsubset, trnsubsetsize, valsubset, valsubsetsize, network, rep, ae_false, sessions, _state); - - /* - * Choose best network - */ - bestrmserror = ae_maxrealnumber; - ae_shared_pool_first_recycled(sessions, &_psession, _state); - while(psession!=NULL) - { - if( ae_fp_less(psession->bestrmserror,bestrmserror) ) - { - mlpimporttunableparameters(network, &psession->bestparameters, _state); - bestrmserror = psession->bestrmserror; - } - ae_shared_pool_next_recycled(sessions, &_psession, _state); - } - - /* - * Calculate errors - */ - if( s->datatype==0 ) - { - mlpallerrorssubset(network, &s->densexy, s->npoints, trnsubset, trnsubsetsize, &modrep, _state); - } - if( s->datatype==1 ) - { - mlpallerrorssparsesubset(network, &s->sparsexy, s->npoints, trnsubset, trnsubsetsize, &modrep, _state); - } - rep->relclserror = modrep.relclserror; - rep->avgce = modrep.avgce; - rep->rmserror = modrep.rmserror; - rep->avgerror = modrep.avgerror; - rep->avgrelerror = modrep.avgrelerror; - - /* - * Done - */ - ae_frame_leave(_state); - return; - } - - /* - * Split problem, if we have more than 1 restart - */ - if( nrestarts>=2 ) - { - - /* - * Divide problem with NRestarts into two: NR0 and NR1. - */ - nr0 = nrestarts/2; - nr1 = nrestarts-nr0; - mlptrain_mlptrainnetworkx(s, nr0, algokind, trnsubset, trnsubsetsize, valsubset, valsubsetsize, network, &rep0, ae_false, sessions, _state); - mlptrain_mlptrainnetworkx(s, nr1, algokind, trnsubset, trnsubsetsize, valsubset, valsubsetsize, network, &rep1, ae_false, sessions, _state); - - /* - * Aggregate results - */ - rep->ngrad = rep0.ngrad+rep1.ngrad; - rep->nhess = rep0.nhess+rep1.nhess; - rep->ncholesky = rep0.ncholesky+rep1.ncholesky; - - /* - * Done :) - */ - ae_frame_leave(_state); - return; - } - - /* - * Execution with NRestarts=1 or NRestarts=0: - * * NRestarts=1 means that network is restarted from random position - * * NRestarts=0 means that network is not randomized - */ - ae_assert(nrestarts==0||nrestarts==1, "MLPTrainNetworkX: internal error", _state); - rep->ngrad = 0; - rep->nhess = 0; - rep->ncholesky = 0; - ae_shared_pool_retrieve(sessions, &_psession, _state); - if( ((s->datatype==0||s->datatype==1)&&s->npoints>0)&&trnsubsetsize!=0 ) - { - - /* - * Train network using combination of early stopping and step-size - * and step-count based criteria. Network state with best value of - * validation set error is stored in WBuf0. When validation set is - * zero, most recent state of network is stored. - */ - rndstart = nrestarts!=0; - ngradbatch = 0; - eval = (double)(0); - ebest = (double)(0); - itbest = 0; - itcnt = 0; - mlptrain_mlpstarttrainingx(s, rndstart, algokind, trnsubset, trnsubsetsize, psession, _state); - if( s->datatype==0 ) - { - ebest = mlperrorsubset(&psession->network, &s->densexy, s->npoints, valsubset, valsubsetsize, _state); - } - if( s->datatype==1 ) - { - ebest = mlperrorsparsesubset(&psession->network, &s->sparsexy, s->npoints, valsubset, valsubsetsize, _state); - } - ae_v_move(&psession->wbuf0.ptr.p_double[0], 1, &psession->network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - while(mlptrain_mlpcontinuetrainingx(s, trnsubset, trnsubsetsize, &ngradbatch, psession, _state)) - { - if( s->datatype==0 ) - { - eval = mlperrorsubset(&psession->network, &s->densexy, s->npoints, valsubset, valsubsetsize, _state); - } - if( s->datatype==1 ) - { - eval = mlperrorsparsesubset(&psession->network, &s->sparsexy, s->npoints, valsubset, valsubsetsize, _state); - } - if( ae_fp_less_eq(eval,ebest)||valsubsetsize==0 ) - { - ae_v_move(&psession->wbuf0.ptr.p_double[0], 1, &psession->network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - ebest = eval; - itbest = itcnt; - } - if( itcnt>30&&ae_fp_greater((double)(itcnt),1.5*itbest) ) - { - break; - } - itcnt = itcnt+1; - } - ae_v_move(&psession->network.weights.ptr.p_double[0], 1, &psession->wbuf0.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - rep->ngrad = ngradbatch; - } - else - { - for(i=0; i<=wcount-1; i++) - { - psession->network.weights.ptr.p_double[i] = (double)(0); - } - } - - /* - * Evaluate network performance and update PSession.BestParameters/BestRMSError - * (if needed). - */ - if( s->datatype==0 ) - { - mlpallerrorssubset(&psession->network, &s->densexy, s->npoints, trnsubset, trnsubsetsize, &modrep, _state); - } - if( s->datatype==1 ) - { - mlpallerrorssparsesubset(&psession->network, &s->sparsexy, s->npoints, trnsubset, trnsubsetsize, &modrep, _state); - } - if( ae_fp_less(modrep.rmserror,psession->bestrmserror) ) - { - mlpexporttunableparameters(&psession->network, &psession->bestparameters, &pcount, _state); - psession->bestrmserror = modrep.rmserror; - } - - /* - * Move session back to pool - */ - ae_shared_pool_recycle(sessions, &_psession, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_mlptrain_mlptrainnetworkx(mlptrainer* s, - ae_int_t nrestarts, - ae_int_t algokind, - /* Integer */ ae_vector* trnsubset, - ae_int_t trnsubsetsize, - /* Integer */ ae_vector* valsubset, - ae_int_t valsubsetsize, - multilayerperceptron* network, - mlpreport* rep, - ae_bool isrootcall, - ae_shared_pool* sessions, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -This function trains neural network ensemble passed to this function using -current dataset and early stopping training algorithm. Each early stopping -round performs NRestarts random restarts (thus, EnsembleSize*NRestarts -training rounds is performed in total). - - - -- ALGLIB -- - Copyright 22.08.2012 by Bochkanov Sergey -*************************************************************************/ -static void mlptrain_mlptrainensemblex(mlptrainer* s, - mlpensemble* ensemble, - ae_int_t idx0, - ae_int_t idx1, - ae_int_t nrestarts, - ae_int_t trainingmethod, - sinteger* ngrad, - ae_bool isrootcall, - ae_shared_pool* esessions, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t pcount; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t trnsubsetsize; - ae_int_t valsubsetsize; - ae_int_t k0; - sinteger ngrad0; - sinteger ngrad1; - mlpetrnsession *psession; - ae_smart_ptr _psession; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&ngrad0, 0, sizeof(ngrad0)); - memset(&ngrad1, 0, sizeof(ngrad1)); - memset(&_psession, 0, sizeof(_psession)); - memset(&rs, 0, sizeof(rs)); - _sinteger_init(&ngrad0, _state, ae_true); - _sinteger_init(&ngrad1, _state, ae_true); - ae_smart_ptr_init(&_psession, (void**)&psession, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - nin = mlpgetinputscount(&ensemble->network, _state); - nout = mlpgetoutputscount(&ensemble->network, _state); - wcount = mlpgetweightscount(&ensemble->network, _state); - if( mlpissoftmax(&ensemble->network, _state) ) - { - pcount = nin; - } - else - { - pcount = nin+nout; - } - if( nrestarts<=0 ) - { - nrestarts = 1; - } - - /* - * Handle degenerate case - */ - if( s->npoints<2 ) - { - for(i=idx0; i<=idx1-1; i++) - { - for(j=0; j<=wcount-1; j++) - { - ensemble->weights.ptr.p_double[i*wcount+j] = 0.0; - } - for(j=0; j<=pcount-1; j++) - { - ensemble->columnmeans.ptr.p_double[i*pcount+j] = 0.0; - ensemble->columnsigmas.ptr.p_double[i*pcount+j] = 1.0; - } - } - ae_frame_leave(_state); - return; - } - - /* - * Process root call - */ - if( isrootcall ) - { - - /* - * Try parallelization - * We expect that minimum number of iterations before convergence is 100. - * Hence is our approach to evaluation of task complexity. - */ - if( ae_fp_greater_eq(ae_maxint(nrestarts, 1, _state)*(idx1-idx0)*rmul3((double)(2*wcount), (double)(s->npoints), (double)(100), _state),smpactivationlevel(_state)) ) - { - if( _trypexec_mlptrain_mlptrainensemblex(s,ensemble,idx0,idx1,nrestarts,trainingmethod,ngrad,isrootcall,esessions, _state) ) - { - ae_frame_leave(_state); - return; - } - } - - /* - * Prepare: - * * prepare MLPETrnSessions - * * fill ensemble by zeros (helps to detect errors) - */ - mlptrain_initmlpetrnsessions(&ensemble->network, s, esessions, _state); - for(i=idx0; i<=idx1-1; i++) - { - for(j=0; j<=wcount-1; j++) - { - ensemble->weights.ptr.p_double[i*wcount+j] = 0.0; - } - for(j=0; j<=pcount-1; j++) - { - ensemble->columnmeans.ptr.p_double[i*pcount+j] = 0.0; - ensemble->columnsigmas.ptr.p_double[i*pcount+j] = 0.0; - } - } - - /* - * Train in non-root mode and exit - */ - mlptrain_mlptrainensemblex(s, ensemble, idx0, idx1, nrestarts, trainingmethod, ngrad, ae_false, esessions, _state); - ae_frame_leave(_state); - return; - } - - /* - * Split problem - */ - if( idx1-idx0>=2 ) - { - k0 = (idx1-idx0)/2; - ngrad0.val = 0; - ngrad1.val = 0; - mlptrain_mlptrainensemblex(s, ensemble, idx0, idx0+k0, nrestarts, trainingmethod, &ngrad0, ae_false, esessions, _state); - mlptrain_mlptrainensemblex(s, ensemble, idx0+k0, idx1, nrestarts, trainingmethod, &ngrad1, ae_false, esessions, _state); - ngrad->val = ngrad0.val+ngrad1.val; - ae_frame_leave(_state); - return; - } - - /* - * Retrieve and prepare session - */ - ae_shared_pool_retrieve(esessions, &_psession, _state); - - /* - * Train - */ - hqrndrandomize(&rs, _state); - for(k=idx0; k<=idx1-1; k++) - { - - /* - * Split set - */ - trnsubsetsize = 0; - valsubsetsize = 0; - if( trainingmethod==0 ) - { - do - { - trnsubsetsize = 0; - valsubsetsize = 0; - for(i=0; i<=s->npoints-1; i++) - { - if( ae_fp_less(ae_randomreal(_state),0.66) ) - { - - /* - * Assign sample to training set - */ - psession->trnsubset.ptr.p_int[trnsubsetsize] = i; - trnsubsetsize = trnsubsetsize+1; - } - else - { - - /* - * Assign sample to validation set - */ - psession->valsubset.ptr.p_int[valsubsetsize] = i; - valsubsetsize = valsubsetsize+1; - } - } - } - while(!(trnsubsetsize!=0&&valsubsetsize!=0)); - } - if( trainingmethod==1 ) - { - valsubsetsize = 0; - trnsubsetsize = s->npoints; - for(i=0; i<=s->npoints-1; i++) - { - psession->trnsubset.ptr.p_int[i] = hqrnduniformi(&rs, s->npoints, _state); - } - } - - /* - * Train - */ - mlptrain_mlptrainnetworkx(s, nrestarts, -1, &psession->trnsubset, trnsubsetsize, &psession->valsubset, valsubsetsize, &psession->network, &psession->mlprep, ae_true, &psession->mlpsessions, _state); - ngrad->val = ngrad->val+psession->mlprep.ngrad; - - /* - * Save results - */ - ae_v_move(&ensemble->weights.ptr.p_double[k*wcount], 1, &psession->network.weights.ptr.p_double[0], 1, ae_v_len(k*wcount,(k+1)*wcount-1)); - ae_v_move(&ensemble->columnmeans.ptr.p_double[k*pcount], 1, &psession->network.columnmeans.ptr.p_double[0], 1, ae_v_len(k*pcount,(k+1)*pcount-1)); - ae_v_move(&ensemble->columnsigmas.ptr.p_double[k*pcount], 1, &psession->network.columnsigmas.ptr.p_double[0], 1, ae_v_len(k*pcount,(k+1)*pcount-1)); - } - - /* - * Recycle session - */ - ae_shared_pool_recycle(esessions, &_psession, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_mlptrain_mlptrainensemblex(mlptrainer* s, - mlpensemble* ensemble, - ae_int_t idx0, - ae_int_t idx1, - ae_int_t nrestarts, - ae_int_t trainingmethod, - sinteger* ngrad, - ae_bool isrootcall, - ae_shared_pool* esessions, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -This function performs step-by-step training of the neural network. Here -"step-by-step" means that training starts with MLPStartTrainingX call, -and then user subsequently calls MLPContinueTrainingX to perform one more -iteration of the training. - -After call to this function trainer object remembers network and is ready -to train it. However, no training is performed until first call to -MLPContinueTraining() function. Subsequent calls to MLPContinueTraining() -will advance traing progress one iteration further. - - - -- ALGLIB -- - Copyright 13.08.2012 by Bochkanov Sergey -*************************************************************************/ -static void mlptrain_mlpstarttrainingx(mlptrainer* s, - ae_bool randomstart, - ae_int_t algokind, - /* Integer */ ae_vector* subset, - ae_int_t subsetsize, - smlptrnsession* session, - ae_state *_state) -{ - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t ntype; - ae_int_t ttype; - ae_int_t i; - - - - /* - * Check parameters - */ - ae_assert(s->npoints>=0, "MLPStartTrainingX: internal error - parameter S is not initialized or is spoiled(S.NPoints<0)", _state); - ae_assert(algokind==0||algokind==-1, "MLPStartTrainingX: unexpected AlgoKind", _state); - if( s->rcpar ) - { - ttype = 0; - } - else - { - ttype = 1; - } - if( !mlpissoftmax(&session->network, _state) ) - { - ntype = 0; - } - else - { - ntype = 1; - } - ae_assert(ntype==ttype, "MLPStartTrainingX: internal error - type of the resulting network is not similar to network type in trainer object", _state); - mlpproperties(&session->network, &nin, &nout, &wcount, _state); - ae_assert(s->nin==nin, "MLPStartTrainingX: number of inputs in trainer is not equal to number of inputs in the network.", _state); - ae_assert(s->nout==nout, "MLPStartTrainingX: number of outputs in trainer is not equal to number of outputs in the network.", _state); - ae_assert(subset->cnt>=subsetsize, "MLPStartTrainingX: internal error - parameter SubsetSize more than input subset size(Length(Subset)ptr.p_int[i]>=0&&subset->ptr.p_int[i]<=s->npoints-1, "MLPStartTrainingX: internal error - parameter Subset contains incorrect index(Subset[I]<0 or Subset[I]>S.NPoints-1)", _state); - } - - /* - * Prepare session - */ - minlbfgssetcond(&session->optimizer, 0.0, 0.0, s->wstep, s->maxits, _state); - if( s->npoints>0&&subsetsize!=0 ) - { - if( randomstart ) - { - mlprandomize(&session->network, _state); - } - minlbfgsrestartfrom(&session->optimizer, &session->network.weights, _state); - } - else - { - for(i=0; i<=wcount-1; i++) - { - session->network.weights.ptr.p_double[i] = (double)(0); - } - } - if( algokind==-1 ) - { - session->algoused = s->algokind; - if( s->algokind==1 ) - { - session->minibatchsize = s->minibatchsize; - } - } - else - { - session->algoused = 0; - } - hqrndrandomize(&session->generator, _state); - ae_vector_set_length(&session->rstate.ia, 15+1, _state); - ae_vector_set_length(&session->rstate.ra, 1+1, _state); - session->rstate.stage = -1; -} - - -/************************************************************************* -This function performs step-by-step training of the neural network. Here -"step-by-step" means that training starts with MLPStartTrainingX call, -and then user subsequently calls MLPContinueTrainingX to perform one more -iteration of the training. - -This function performs one more iteration of the training and returns -either True (training continues) or False (training stopped). In case True -was returned, Network weights are updated according to the current state -of the optimization progress. In case False was returned, no additional -updates is performed (previous update of the network weights moved us to -the final point, and no additional updates is needed). - -EXAMPLE: - > - > [initialize network and trainer object] - > - > MLPStartTraining(Trainer, Network, True) - > while MLPContinueTraining(Trainer, Network) do - > [visualize training progress] - > - - - -- ALGLIB -- - Copyright 13.08.2012 by Bochkanov Sergey -*************************************************************************/ -static ae_bool mlptrain_mlpcontinuetrainingx(mlptrainer* s, - /* Integer */ ae_vector* subset, - ae_int_t subsetsize, - ae_int_t* ngradbatch, - smlptrnsession* session, - ae_state *_state) -{ - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t twcount; - ae_int_t ntype; - ae_int_t ttype; - double decay; - double v; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t trnsetsize; - ae_int_t epoch; - ae_int_t minibatchcount; - ae_int_t minibatchidx; - ae_int_t cursize; - ae_int_t idx0; - ae_int_t idx1; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( session->rstate.stage>=0 ) - { - nin = session->rstate.ia.ptr.p_int[0]; - nout = session->rstate.ia.ptr.p_int[1]; - wcount = session->rstate.ia.ptr.p_int[2]; - twcount = session->rstate.ia.ptr.p_int[3]; - ntype = session->rstate.ia.ptr.p_int[4]; - ttype = session->rstate.ia.ptr.p_int[5]; - i = session->rstate.ia.ptr.p_int[6]; - j = session->rstate.ia.ptr.p_int[7]; - k = session->rstate.ia.ptr.p_int[8]; - trnsetsize = session->rstate.ia.ptr.p_int[9]; - epoch = session->rstate.ia.ptr.p_int[10]; - minibatchcount = session->rstate.ia.ptr.p_int[11]; - minibatchidx = session->rstate.ia.ptr.p_int[12]; - cursize = session->rstate.ia.ptr.p_int[13]; - idx0 = session->rstate.ia.ptr.p_int[14]; - idx1 = session->rstate.ia.ptr.p_int[15]; - decay = session->rstate.ra.ptr.p_double[0]; - v = session->rstate.ra.ptr.p_double[1]; - } - else - { - nin = 359; - nout = -58; - wcount = -919; - twcount = -909; - ntype = 81; - ttype = 255; - i = 74; - j = -788; - k = 809; - trnsetsize = 205; - epoch = -838; - minibatchcount = 939; - minibatchidx = -526; - cursize = 763; - idx0 = -541; - idx1 = -698; - decay = -900; - v = -318; - } - if( session->rstate.stage==0 ) - { - goto lbl_0; - } - - /* - * Routine body - */ - - /* - * Check correctness of inputs - */ - ae_assert(s->npoints>=0, "MLPContinueTrainingX: internal error - parameter S is not initialized or is spoiled(S.NPoints<0).", _state); - if( s->rcpar ) - { - ttype = 0; - } - else - { - ttype = 1; - } - if( !mlpissoftmax(&session->network, _state) ) - { - ntype = 0; - } - else - { - ntype = 1; - } - ae_assert(ntype==ttype, "MLPContinueTrainingX: internal error - type of the resulting network is not similar to network type in trainer object.", _state); - mlpproperties(&session->network, &nin, &nout, &wcount, _state); - ae_assert(s->nin==nin, "MLPContinueTrainingX: internal error - number of inputs in trainer is not equal to number of inputs in the network.", _state); - ae_assert(s->nout==nout, "MLPContinueTrainingX: internal error - number of outputs in trainer is not equal to number of outputs in the network.", _state); - ae_assert(subset->cnt>=subsetsize, "MLPContinueTrainingX: internal error - parameter SubsetSize more than input subset size(Length(Subset)ptr.p_int[i]>=0&&subset->ptr.p_int[i]<=s->npoints-1, "MLPContinueTrainingX: internal error - parameter Subset contains incorrect index(Subset[I]<0 or Subset[I]>S.NPoints-1).", _state); - } - - /* - * Quick exit on empty training set - */ - if( s->npoints==0||subsetsize==0 ) - { - result = ae_false; - return result; - } - - /* - * Minibatch training - */ - if( session->algoused==1 ) - { - ae_assert(ae_false, "MINIBATCH TRAINING IS NOT IMPLEMENTED YET", _state); - } - - /* - * Last option: full batch training - */ - decay = s->decay; -lbl_1: - if( !minlbfgsiteration(&session->optimizer, _state) ) - { - goto lbl_2; - } - if( !session->optimizer.xupdated ) - { - goto lbl_3; - } - ae_v_move(&session->network.weights.ptr.p_double[0], 1, &session->optimizer.x.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - session->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: -lbl_3: - ae_v_move(&session->network.weights.ptr.p_double[0], 1, &session->optimizer.x.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - if( s->datatype==0 ) - { - mlpgradbatchsubset(&session->network, &s->densexy, s->npoints, subset, subsetsize, &session->optimizer.f, &session->optimizer.g, _state); - } - if( s->datatype==1 ) - { - mlpgradbatchsparsesubset(&session->network, &s->sparsexy, s->npoints, subset, subsetsize, &session->optimizer.f, &session->optimizer.g, _state); - } - - /* - * Increment number of operations performed on batch gradient - */ - *ngradbatch = *ngradbatch+1; - v = ae_v_dotproduct(&session->network.weights.ptr.p_double[0], 1, &session->network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - session->optimizer.f = session->optimizer.f+0.5*decay*v; - ae_v_addd(&session->optimizer.g.ptr.p_double[0], 1, &session->network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), decay); - goto lbl_1; -lbl_2: - minlbfgsresultsbuf(&session->optimizer, &session->network.weights, &session->optimizerrep, _state); - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - session->rstate.ia.ptr.p_int[0] = nin; - session->rstate.ia.ptr.p_int[1] = nout; - session->rstate.ia.ptr.p_int[2] = wcount; - session->rstate.ia.ptr.p_int[3] = twcount; - session->rstate.ia.ptr.p_int[4] = ntype; - session->rstate.ia.ptr.p_int[5] = ttype; - session->rstate.ia.ptr.p_int[6] = i; - session->rstate.ia.ptr.p_int[7] = j; - session->rstate.ia.ptr.p_int[8] = k; - session->rstate.ia.ptr.p_int[9] = trnsetsize; - session->rstate.ia.ptr.p_int[10] = epoch; - session->rstate.ia.ptr.p_int[11] = minibatchcount; - session->rstate.ia.ptr.p_int[12] = minibatchidx; - session->rstate.ia.ptr.p_int[13] = cursize; - session->rstate.ia.ptr.p_int[14] = idx0; - session->rstate.ia.ptr.p_int[15] = idx1; - session->rstate.ra.ptr.p_double[0] = decay; - session->rstate.ra.ptr.p_double[1] = v; - return result; -} - - -/************************************************************************* -Internal bagging subroutine. - - -- ALGLIB -- - Copyright 19.02.2009 by Bochkanov Sergey -*************************************************************************/ -static void mlptrain_mlpebagginginternal(mlpensemble* ensemble, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - double wstep, - ae_int_t maxits, - ae_bool lmalgorithm, - ae_int_t* info, - mlpreport* rep, - mlpcvreport* ooberrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix xys; - ae_vector s; - ae_matrix oobbuf; - ae_vector oobcntbuf; - ae_vector x; - ae_vector y; - ae_vector dy; - ae_vector dsbuf; - ae_int_t ccnt; - ae_int_t pcnt; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - mlpreport tmprep; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&xys, 0, sizeof(xys)); - memset(&s, 0, sizeof(s)); - memset(&oobbuf, 0, sizeof(oobbuf)); - memset(&oobcntbuf, 0, sizeof(oobcntbuf)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&dy, 0, sizeof(dy)); - memset(&dsbuf, 0, sizeof(dsbuf)); - memset(&tmprep, 0, sizeof(tmprep)); - memset(&rs, 0, sizeof(rs)); - *info = 0; - _mlpreport_clear(rep); - _mlpcvreport_clear(ooberrors); - ae_matrix_init(&xys, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_BOOL, _state, ae_true); - ae_matrix_init(&oobbuf, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&oobcntbuf, 0, DT_INT, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dy, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dsbuf, 0, DT_REAL, _state, ae_true); - _mlpreport_init(&tmprep, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - nin = mlpgetinputscount(&ensemble->network, _state); - nout = mlpgetoutputscount(&ensemble->network, _state); - wcount = mlpgetweightscount(&ensemble->network, _state); - - /* - * Test for inputs - */ - if( (!lmalgorithm&&ae_fp_eq(wstep,(double)(0)))&&maxits==0 ) - { - *info = -8; - ae_frame_leave(_state); - return; - } - if( ((npoints<=0||restarts<1)||ae_fp_less(wstep,(double)(0)))||maxits<0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - if( mlpissoftmax(&ensemble->network, _state) ) - { - for(i=0; i<=npoints-1; i++) - { - if( ae_round(xy->ptr.pp_double[i][nin], _state)<0||ae_round(xy->ptr.pp_double[i][nin], _state)>=nout ) - { - *info = -2; - ae_frame_leave(_state); - return; - } - } - } - - /* - * allocate temporaries - */ - *info = 2; - rep->ngrad = 0; - rep->nhess = 0; - rep->ncholesky = 0; - ooberrors->relclserror = (double)(0); - ooberrors->avgce = (double)(0); - ooberrors->rmserror = (double)(0); - ooberrors->avgerror = (double)(0); - ooberrors->avgrelerror = (double)(0); - if( mlpissoftmax(&ensemble->network, _state) ) - { - ccnt = nin+1; - pcnt = nin; - } - else - { - ccnt = nin+nout; - pcnt = nin+nout; - } - ae_matrix_set_length(&xys, npoints, ccnt, _state); - ae_vector_set_length(&s, npoints, _state); - ae_matrix_set_length(&oobbuf, npoints, nout, _state); - ae_vector_set_length(&oobcntbuf, npoints, _state); - ae_vector_set_length(&x, nin, _state); - ae_vector_set_length(&y, nout, _state); - if( mlpissoftmax(&ensemble->network, _state) ) - { - ae_vector_set_length(&dy, 1, _state); - } - else - { - ae_vector_set_length(&dy, nout, _state); - } - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nout-1; j++) - { - oobbuf.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=npoints-1; i++) - { - oobcntbuf.ptr.p_int[i] = 0; - } - - /* - * main bagging cycle - */ - hqrndrandomize(&rs, _state); - for(k=0; k<=ensemble->ensemblesize-1; k++) - { - - /* - * prepare dataset - */ - for(i=0; i<=npoints-1; i++) - { - s.ptr.p_bool[i] = ae_false; - } - for(i=0; i<=npoints-1; i++) - { - j = hqrnduniformi(&rs, npoints, _state); - s.ptr.p_bool[j] = ae_true; - ae_v_move(&xys.ptr.pp_double[i][0], 1, &xy->ptr.pp_double[j][0], 1, ae_v_len(0,ccnt-1)); - } - - /* - * train - */ - if( lmalgorithm ) - { - mlptrainlm(&ensemble->network, &xys, npoints, decay, restarts, info, &tmprep, _state); - } - else - { - mlptrainlbfgs(&ensemble->network, &xys, npoints, decay, restarts, wstep, maxits, info, &tmprep, _state); - } - if( *info<0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * save results - */ - rep->ngrad = rep->ngrad+tmprep.ngrad; - rep->nhess = rep->nhess+tmprep.nhess; - rep->ncholesky = rep->ncholesky+tmprep.ncholesky; - ae_v_move(&ensemble->weights.ptr.p_double[k*wcount], 1, &ensemble->network.weights.ptr.p_double[0], 1, ae_v_len(k*wcount,(k+1)*wcount-1)); - ae_v_move(&ensemble->columnmeans.ptr.p_double[k*pcnt], 1, &ensemble->network.columnmeans.ptr.p_double[0], 1, ae_v_len(k*pcnt,(k+1)*pcnt-1)); - ae_v_move(&ensemble->columnsigmas.ptr.p_double[k*pcnt], 1, &ensemble->network.columnsigmas.ptr.p_double[0], 1, ae_v_len(k*pcnt,(k+1)*pcnt-1)); - - /* - * OOB estimates - */ - for(i=0; i<=npoints-1; i++) - { - if( !s.ptr.p_bool[i] ) - { - ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nin-1)); - mlpprocess(&ensemble->network, &x, &y, _state); - ae_v_add(&oobbuf.ptr.pp_double[i][0], 1, &y.ptr.p_double[0], 1, ae_v_len(0,nout-1)); - oobcntbuf.ptr.p_int[i] = oobcntbuf.ptr.p_int[i]+1; - } - } - } - - /* - * OOB estimates - */ - if( mlpissoftmax(&ensemble->network, _state) ) - { - dserrallocate(nout, &dsbuf, _state); - } - else - { - dserrallocate(-nout, &dsbuf, _state); - } - for(i=0; i<=npoints-1; i++) - { - if( oobcntbuf.ptr.p_int[i]!=0 ) - { - v = (double)1/(double)oobcntbuf.ptr.p_int[i]; - ae_v_moved(&y.ptr.p_double[0], 1, &oobbuf.ptr.pp_double[i][0], 1, ae_v_len(0,nout-1), v); - if( mlpissoftmax(&ensemble->network, _state) ) - { - dy.ptr.p_double[0] = xy->ptr.pp_double[i][nin]; - } - else - { - ae_v_moved(&dy.ptr.p_double[0], 1, &xy->ptr.pp_double[i][nin], 1, ae_v_len(0,nout-1), v); - } - dserraccumulate(&dsbuf, &y, &dy, _state); - } - } - dserrfinish(&dsbuf, _state); - ooberrors->relclserror = dsbuf.ptr.p_double[0]; - ooberrors->avgce = dsbuf.ptr.p_double[1]; - ooberrors->rmserror = dsbuf.ptr.p_double[2]; - ooberrors->avgerror = dsbuf.ptr.p_double[3]; - ooberrors->avgrelerror = dsbuf.ptr.p_double[4]; - ae_frame_leave(_state); -} - - -/************************************************************************* -This function initializes temporaries needed for training session. - - - -- ALGLIB -- - Copyright 01.07.2013 by Bochkanov Sergey -*************************************************************************/ -static void mlptrain_initmlptrnsession(multilayerperceptron* networktrained, - ae_bool randomizenetwork, - mlptrainer* trainer, - smlptrnsession* session, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t pcount; - ae_vector dummysubset; - - ae_frame_make(_state, &_frame_block); - memset(&dummysubset, 0, sizeof(dummysubset)); - ae_vector_init(&dummysubset, 0, DT_INT, _state, ae_true); - - - /* - * Prepare network: - * * copy input network to Session.Network - * * re-initialize preprocessor and weights if RandomizeNetwork=True - */ - mlpcopy(networktrained, &session->network, _state); - if( randomizenetwork ) - { - ae_assert(trainer->datatype==0||trainer->datatype==1, "InitTemporaries: unexpected Trainer.DataType", _state); - if( trainer->datatype==0 ) - { - mlpinitpreprocessorsubset(&session->network, &trainer->densexy, trainer->npoints, &dummysubset, -1, _state); - } - if( trainer->datatype==1 ) - { - mlpinitpreprocessorsparsesubset(&session->network, &trainer->sparsexy, trainer->npoints, &dummysubset, -1, _state); - } - mlprandomize(&session->network, _state); - session->randomizenetwork = ae_true; - } - else - { - session->randomizenetwork = ae_false; - } - - /* - * Determine network geometry and initialize optimizer - */ - mlpproperties(&session->network, &nin, &nout, &wcount, _state); - minlbfgscreate(wcount, ae_minint(wcount, trainer->lbfgsfactor, _state), &session->network.weights, &session->optimizer, _state); - minlbfgssetxrep(&session->optimizer, ae_true, _state); - - /* - * Create buffers - */ - ae_vector_set_length(&session->wbuf0, wcount, _state); - ae_vector_set_length(&session->wbuf1, wcount, _state); - - /* - * Initialize session result - */ - mlpexporttunableparameters(&session->network, &session->bestparameters, &pcount, _state); - session->bestrmserror = ae_maxrealnumber; - ae_frame_leave(_state); -} - - -/************************************************************************* -This function initializes temporaries needed for training session. - -*************************************************************************/ -static void mlptrain_initmlptrnsessions(multilayerperceptron* networktrained, - ae_bool randomizenetwork, - mlptrainer* trainer, - ae_shared_pool* sessions, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector dummysubset; - smlptrnsession t; - smlptrnsession *p; - ae_smart_ptr _p; - - ae_frame_make(_state, &_frame_block); - memset(&dummysubset, 0, sizeof(dummysubset)); - memset(&t, 0, sizeof(t)); - memset(&_p, 0, sizeof(_p)); - ae_vector_init(&dummysubset, 0, DT_INT, _state, ae_true); - _smlptrnsession_init(&t, _state, ae_true); - ae_smart_ptr_init(&_p, (void**)&p, _state, ae_true); - - if( ae_shared_pool_is_initialized(sessions) ) - { - - /* - * Pool was already initialized. - * Clear sessions stored in the pool. - */ - ae_shared_pool_first_recycled(sessions, &_p, _state); - while(p!=NULL) - { - ae_assert(mlpsamearchitecture(&p->network, networktrained, _state), "InitMLPTrnSessions: internal consistency error", _state); - p->bestrmserror = ae_maxrealnumber; - ae_shared_pool_next_recycled(sessions, &_p, _state); - } - } - else - { - - /* - * Prepare session and seed pool - */ - mlptrain_initmlptrnsession(networktrained, randomizenetwork, trainer, &t, _state); - ae_shared_pool_set_seed(sessions, &t, sizeof(t), _smlptrnsession_init, _smlptrnsession_init_copy, _smlptrnsession_destroy, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function initializes temporaries needed for ensemble training. - -*************************************************************************/ -static void mlptrain_initmlpetrnsession(multilayerperceptron* individualnetwork, - mlptrainer* trainer, - mlpetrnsession* session, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector dummysubset; - - ae_frame_make(_state, &_frame_block); - memset(&dummysubset, 0, sizeof(dummysubset)); - ae_vector_init(&dummysubset, 0, DT_INT, _state, ae_true); - - - /* - * Prepare network: - * * copy input network to Session.Network - * * re-initialize preprocessor and weights if RandomizeNetwork=True - */ - mlpcopy(individualnetwork, &session->network, _state); - mlptrain_initmlptrnsessions(individualnetwork, ae_true, trainer, &session->mlpsessions, _state); - ivectorsetlengthatleast(&session->trnsubset, trainer->npoints, _state); - ivectorsetlengthatleast(&session->valsubset, trainer->npoints, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function initializes temporaries needed for training session. - -*************************************************************************/ -static void mlptrain_initmlpetrnsessions(multilayerperceptron* individualnetwork, - mlptrainer* trainer, - ae_shared_pool* sessions, - ae_state *_state) -{ - ae_frame _frame_block; - mlpetrnsession t; - - ae_frame_make(_state, &_frame_block); - memset(&t, 0, sizeof(t)); - _mlpetrnsession_init(&t, _state, ae_true); - - if( !ae_shared_pool_is_initialized(sessions) ) - { - mlptrain_initmlpetrnsession(individualnetwork, trainer, &t, _state); - ae_shared_pool_set_seed(sessions, &t, sizeof(t), _mlpetrnsession_init, _mlpetrnsession_init_copy, _mlpetrnsession_destroy, _state); - } - ae_frame_leave(_state); -} - - -void _mlpreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - mlpreport *p = (mlpreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _mlpreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - mlpreport *dst = (mlpreport*)_dst; - mlpreport *src = (mlpreport*)_src; - dst->relclserror = src->relclserror; - dst->avgce = src->avgce; - dst->rmserror = src->rmserror; - dst->avgerror = src->avgerror; - dst->avgrelerror = src->avgrelerror; - dst->ngrad = src->ngrad; - dst->nhess = src->nhess; - dst->ncholesky = src->ncholesky; -} - - -void _mlpreport_clear(void* _p) -{ - mlpreport *p = (mlpreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _mlpreport_destroy(void* _p) -{ - mlpreport *p = (mlpreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _mlpcvreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - mlpcvreport *p = (mlpcvreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _mlpcvreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - mlpcvreport *dst = (mlpcvreport*)_dst; - mlpcvreport *src = (mlpcvreport*)_src; - dst->relclserror = src->relclserror; - dst->avgce = src->avgce; - dst->rmserror = src->rmserror; - dst->avgerror = src->avgerror; - dst->avgrelerror = src->avgrelerror; -} - - -void _mlpcvreport_clear(void* _p) -{ - mlpcvreport *p = (mlpcvreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _mlpcvreport_destroy(void* _p) -{ - mlpcvreport *p = (mlpcvreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _smlptrnsession_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - smlptrnsession *p = (smlptrnsession*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->bestparameters, 0, DT_REAL, _state, make_automatic); - _multilayerperceptron_init(&p->network, _state, make_automatic); - _minlbfgsstate_init(&p->optimizer, _state, make_automatic); - _minlbfgsreport_init(&p->optimizerrep, _state, make_automatic); - ae_vector_init(&p->wbuf0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->wbuf1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->allminibatches, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->currentminibatch, 0, DT_INT, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); - _hqrndstate_init(&p->generator, _state, make_automatic); -} - - -void _smlptrnsession_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - smlptrnsession *dst = (smlptrnsession*)_dst; - smlptrnsession *src = (smlptrnsession*)_src; - ae_vector_init_copy(&dst->bestparameters, &src->bestparameters, _state, make_automatic); - dst->bestrmserror = src->bestrmserror; - dst->randomizenetwork = src->randomizenetwork; - _multilayerperceptron_init_copy(&dst->network, &src->network, _state, make_automatic); - _minlbfgsstate_init_copy(&dst->optimizer, &src->optimizer, _state, make_automatic); - _minlbfgsreport_init_copy(&dst->optimizerrep, &src->optimizerrep, _state, make_automatic); - ae_vector_init_copy(&dst->wbuf0, &src->wbuf0, _state, make_automatic); - ae_vector_init_copy(&dst->wbuf1, &src->wbuf1, _state, make_automatic); - ae_vector_init_copy(&dst->allminibatches, &src->allminibatches, _state, make_automatic); - ae_vector_init_copy(&dst->currentminibatch, &src->currentminibatch, _state, make_automatic); - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); - dst->algoused = src->algoused; - dst->minibatchsize = src->minibatchsize; - _hqrndstate_init_copy(&dst->generator, &src->generator, _state, make_automatic); -} - - -void _smlptrnsession_clear(void* _p) -{ - smlptrnsession *p = (smlptrnsession*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->bestparameters); - _multilayerperceptron_clear(&p->network); - _minlbfgsstate_clear(&p->optimizer); - _minlbfgsreport_clear(&p->optimizerrep); - ae_vector_clear(&p->wbuf0); - ae_vector_clear(&p->wbuf1); - ae_vector_clear(&p->allminibatches); - ae_vector_clear(&p->currentminibatch); - _rcommstate_clear(&p->rstate); - _hqrndstate_clear(&p->generator); -} - - -void _smlptrnsession_destroy(void* _p) -{ - smlptrnsession *p = (smlptrnsession*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->bestparameters); - _multilayerperceptron_destroy(&p->network); - _minlbfgsstate_destroy(&p->optimizer); - _minlbfgsreport_destroy(&p->optimizerrep); - ae_vector_destroy(&p->wbuf0); - ae_vector_destroy(&p->wbuf1); - ae_vector_destroy(&p->allminibatches); - ae_vector_destroy(&p->currentminibatch); - _rcommstate_destroy(&p->rstate); - _hqrndstate_destroy(&p->generator); -} - - -void _mlpetrnsession_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - mlpetrnsession *p = (mlpetrnsession*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->trnsubset, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->valsubset, 0, DT_INT, _state, make_automatic); - ae_shared_pool_init(&p->mlpsessions, _state, make_automatic); - _mlpreport_init(&p->mlprep, _state, make_automatic); - _multilayerperceptron_init(&p->network, _state, make_automatic); -} - - -void _mlpetrnsession_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - mlpetrnsession *dst = (mlpetrnsession*)_dst; - mlpetrnsession *src = (mlpetrnsession*)_src; - ae_vector_init_copy(&dst->trnsubset, &src->trnsubset, _state, make_automatic); - ae_vector_init_copy(&dst->valsubset, &src->valsubset, _state, make_automatic); - ae_shared_pool_init_copy(&dst->mlpsessions, &src->mlpsessions, _state, make_automatic); - _mlpreport_init_copy(&dst->mlprep, &src->mlprep, _state, make_automatic); - _multilayerperceptron_init_copy(&dst->network, &src->network, _state, make_automatic); -} - - -void _mlpetrnsession_clear(void* _p) -{ - mlpetrnsession *p = (mlpetrnsession*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->trnsubset); - ae_vector_clear(&p->valsubset); - ae_shared_pool_clear(&p->mlpsessions); - _mlpreport_clear(&p->mlprep); - _multilayerperceptron_clear(&p->network); -} - - -void _mlpetrnsession_destroy(void* _p) -{ - mlpetrnsession *p = (mlpetrnsession*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->trnsubset); - ae_vector_destroy(&p->valsubset); - ae_shared_pool_destroy(&p->mlpsessions); - _mlpreport_destroy(&p->mlprep); - _multilayerperceptron_destroy(&p->network); -} - - -void _mlptrainer_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - mlptrainer *p = (mlptrainer*)_p; - ae_touch_ptr((void*)p); - ae_matrix_init(&p->densexy, 0, 0, DT_REAL, _state, make_automatic); - _sparsematrix_init(&p->sparsexy, _state, make_automatic); - _smlptrnsession_init(&p->session, _state, make_automatic); - ae_vector_init(&p->subset, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->valsubset, 0, DT_INT, _state, make_automatic); -} - - -void _mlptrainer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - mlptrainer *dst = (mlptrainer*)_dst; - mlptrainer *src = (mlptrainer*)_src; - dst->nin = src->nin; - dst->nout = src->nout; - dst->rcpar = src->rcpar; - dst->lbfgsfactor = src->lbfgsfactor; - dst->decay = src->decay; - dst->wstep = src->wstep; - dst->maxits = src->maxits; - dst->datatype = src->datatype; - dst->npoints = src->npoints; - ae_matrix_init_copy(&dst->densexy, &src->densexy, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparsexy, &src->sparsexy, _state, make_automatic); - _smlptrnsession_init_copy(&dst->session, &src->session, _state, make_automatic); - dst->ngradbatch = src->ngradbatch; - ae_vector_init_copy(&dst->subset, &src->subset, _state, make_automatic); - dst->subsetsize = src->subsetsize; - ae_vector_init_copy(&dst->valsubset, &src->valsubset, _state, make_automatic); - dst->valsubsetsize = src->valsubsetsize; - dst->algokind = src->algokind; - dst->minibatchsize = src->minibatchsize; -} - - -void _mlptrainer_clear(void* _p) -{ - mlptrainer *p = (mlptrainer*)_p; - ae_touch_ptr((void*)p); - ae_matrix_clear(&p->densexy); - _sparsematrix_clear(&p->sparsexy); - _smlptrnsession_clear(&p->session); - ae_vector_clear(&p->subset); - ae_vector_clear(&p->valsubset); -} - - -void _mlptrainer_destroy(void* _p) -{ - mlptrainer *p = (mlptrainer*)_p; - ae_touch_ptr((void*)p); - ae_matrix_destroy(&p->densexy); - _sparsematrix_destroy(&p->sparsexy); - _smlptrnsession_destroy(&p->session); - ae_vector_destroy(&p->subset); - ae_vector_destroy(&p->valsubset); -} - - -void _mlpparallelizationcv_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - mlpparallelizationcv *p = (mlpparallelizationcv*)_p; - ae_touch_ptr((void*)p); - _multilayerperceptron_init(&p->network, _state, make_automatic); - _mlpreport_init(&p->rep, _state, make_automatic); - ae_vector_init(&p->subset, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->xyrow, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic); - ae_shared_pool_init(&p->trnpool, _state, make_automatic); -} - - -void _mlpparallelizationcv_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - mlpparallelizationcv *dst = (mlpparallelizationcv*)_dst; - mlpparallelizationcv *src = (mlpparallelizationcv*)_src; - _multilayerperceptron_init_copy(&dst->network, &src->network, _state, make_automatic); - _mlpreport_init_copy(&dst->rep, &src->rep, _state, make_automatic); - ae_vector_init_copy(&dst->subset, &src->subset, _state, make_automatic); - dst->subsetsize = src->subsetsize; - ae_vector_init_copy(&dst->xyrow, &src->xyrow, _state, make_automatic); - ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic); - dst->ngrad = src->ngrad; - ae_shared_pool_init_copy(&dst->trnpool, &src->trnpool, _state, make_automatic); -} - - -void _mlpparallelizationcv_clear(void* _p) -{ - mlpparallelizationcv *p = (mlpparallelizationcv*)_p; - ae_touch_ptr((void*)p); - _multilayerperceptron_clear(&p->network); - _mlpreport_clear(&p->rep); - ae_vector_clear(&p->subset); - ae_vector_clear(&p->xyrow); - ae_vector_clear(&p->y); - ae_shared_pool_clear(&p->trnpool); -} - - -void _mlpparallelizationcv_destroy(void* _p) -{ - mlpparallelizationcv *p = (mlpparallelizationcv*)_p; - ae_touch_ptr((void*)p); - _multilayerperceptron_destroy(&p->network); - _mlpreport_destroy(&p->rep); - ae_vector_destroy(&p->subset); - ae_vector_destroy(&p->xyrow); - ae_vector_destroy(&p->y); - ae_shared_pool_destroy(&p->trnpool); -} - - -#endif -#if defined(AE_COMPILE_CLUSTERING) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function initializes clusterizer object. Newly initialized object is -empty, i.e. it does not contain dataset. You should use it as follows: -1. creation -2. dataset is added with ClusterizerSetPoints() -3. additional parameters are set -3. clusterization is performed with one of the clustering functions - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizercreate(clusterizerstate* s, ae_state *_state) -{ - - _clusterizerstate_clear(s); - - s->npoints = 0; - s->nfeatures = 0; - s->disttype = 2; - s->ahcalgo = 0; - s->kmeansrestarts = 1; - s->kmeansmaxits = 0; - s->kmeansinitalgo = 0; - s->kmeansdbgnoits = ae_false; - s->seed = 1; - kmeansinitbuf(&s->kmeanstmp, _state); -} - - -/************************************************************************* -This function adds dataset to the clusterizer structure. - -This function overrides all previous calls of ClusterizerSetPoints() or -ClusterizerSetDistances(). - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - XY - array[NPoints,NFeatures], dataset - NPoints - number of points, >=0 - NFeatures- number of features, >=1 - DistType- distance function: - * 0 Chebyshev distance (L-inf norm) - * 1 city block distance (L1 norm) - * 2 Euclidean distance (L2 norm), non-squared - * 10 Pearson correlation: - dist(a,b) = 1-corr(a,b) - * 11 Absolute Pearson correlation: - dist(a,b) = 1-|corr(a,b)| - * 12 Uncentered Pearson correlation (cosine of the angle): - dist(a,b) = a'*b/(|a|*|b|) - * 13 Absolute uncentered Pearson correlation - dist(a,b) = |a'*b|/(|a|*|b|) - * 20 Spearman rank correlation: - dist(a,b) = 1-rankcorr(a,b) - * 21 Absolute Spearman rank correlation - dist(a,b) = 1-|rankcorr(a,b)| - -NOTE 1: different distance functions have different performance penalty: - * Euclidean or Pearson correlation distances are the fastest ones - * Spearman correlation distance function is a bit slower - * city block and Chebyshev distances are order of magnitude slower - - The reason behing difference in performance is that correlation-based - distance functions are computed using optimized linear algebra kernels, - while Chebyshev and city block distance functions are computed using - simple nested loops with two branches at each iteration. - -NOTE 2: different clustering algorithms have different limitations: - * agglomerative hierarchical clustering algorithms may be used with - any kind of distance metric - * k-means++ clustering algorithm may be used only with Euclidean - distance function - Thus, list of specific clustering algorithms you may use depends - on distance function you specify when you set your dataset. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizersetpoints(clusterizerstate* s, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nfeatures, - ae_int_t disttype, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert((((((((disttype==0||disttype==1)||disttype==2)||disttype==10)||disttype==11)||disttype==12)||disttype==13)||disttype==20)||disttype==21, "ClusterizerSetPoints: incorrect DistType", _state); - ae_assert(npoints>=0, "ClusterizerSetPoints: NPoints<0", _state); - ae_assert(nfeatures>=1, "ClusterizerSetPoints: NFeatures<1", _state); - ae_assert(xy->rows>=npoints, "ClusterizerSetPoints: Rows(XY)cols>=nfeatures, "ClusterizerSetPoints: Cols(XY)npoints = npoints; - s->nfeatures = nfeatures; - s->disttype = disttype; - rmatrixsetlengthatleast(&s->xy, npoints, nfeatures, _state); - for(i=0; i<=npoints-1; i++) - { - ae_v_move(&s->xy.ptr.pp_double[i][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nfeatures-1)); - } -} - - -/************************************************************************* -This function adds dataset given by distance matrix to the clusterizer -structure. It is important that dataset is not given explicitly - only -distance matrix is given. - -This function overrides all previous calls of ClusterizerSetPoints() or -ClusterizerSetDistances(). - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - D - array[NPoints,NPoints], distance matrix given by its upper - or lower triangle (main diagonal is ignored because its - entries are expected to be zero). - NPoints - number of points - IsUpper - whether upper or lower triangle of D is given. - -NOTE 1: different clustering algorithms have different limitations: - * agglomerative hierarchical clustering algorithms may be used with - any kind of distance metric, including one which is given by - distance matrix - * k-means++ clustering algorithm may be used only with Euclidean - distance function and explicitly given points - it can not be - used with dataset given by distance matrix - Thus, if you call this function, you will be unable to use k-means - clustering algorithm to process your problem. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizersetdistances(clusterizerstate* s, - /* Real */ ae_matrix* d, - ae_int_t npoints, - ae_bool isupper, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t j0; - ae_int_t j1; - - - ae_assert(npoints>=0, "ClusterizerSetDistances: NPoints<0", _state); - ae_assert(d->rows>=npoints, "ClusterizerSetDistances: Rows(D)cols>=npoints, "ClusterizerSetDistances: Cols(D)npoints = npoints; - s->nfeatures = 0; - s->disttype = -1; - rmatrixsetlengthatleast(&s->d, npoints, npoints, _state); - for(i=0; i<=npoints-1; i++) - { - if( isupper ) - { - j0 = i+1; - j1 = npoints-1; - } - else - { - j0 = 0; - j1 = i-1; - } - for(j=j0; j<=j1; j++) - { - ae_assert(ae_isfinite(d->ptr.pp_double[i][j], _state)&&ae_fp_greater_eq(d->ptr.pp_double[i][j],(double)(0)), "ClusterizerSetDistances: D contains infinite, NAN or negative elements", _state); - s->d.ptr.pp_double[i][j] = d->ptr.pp_double[i][j]; - s->d.ptr.pp_double[j][i] = d->ptr.pp_double[i][j]; - } - s->d.ptr.pp_double[i][i] = (double)(0); - } -} - - -/************************************************************************* -This function sets agglomerative hierarchical clustering algorithm - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - Algo - algorithm type: - * 0 complete linkage (default algorithm) - * 1 single linkage - * 2 unweighted average linkage - * 3 weighted average linkage - * 4 Ward's method - -NOTE: Ward's method works correctly only with Euclidean distance, that's - why algorithm will return negative termination code (failure) for - any other distance type. - - It is possible, however, to use this method with user-supplied - distance matrix. It is your responsibility to pass one which was - calculated with Euclidean distance function. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizersetahcalgo(clusterizerstate* s, - ae_int_t algo, - ae_state *_state) -{ - - - ae_assert((((algo==0||algo==1)||algo==2)||algo==3)||algo==4, "ClusterizerSetHCAlgo: incorrect algorithm type", _state); - s->ahcalgo = algo; -} - - -/************************************************************************* -This function sets k-means properties: number of restarts and maximum -number of iterations per one run. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - Restarts- restarts count, >=1. - k-means++ algorithm performs several restarts and chooses - best set of centers (one with minimum squared distance). - MaxIts - maximum number of k-means iterations performed during one - run. >=0, zero value means that algorithm performs unlimited - number of iterations. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizersetkmeanslimits(clusterizerstate* s, - ae_int_t restarts, - ae_int_t maxits, - ae_state *_state) -{ - - - ae_assert(restarts>=1, "ClusterizerSetKMeansLimits: Restarts<=0", _state); - ae_assert(maxits>=0, "ClusterizerSetKMeansLimits: MaxIts<0", _state); - s->kmeansrestarts = restarts; - s->kmeansmaxits = maxits; -} - - -/************************************************************************* -This function sets k-means initialization algorithm. Several different -algorithms can be chosen, including k-means++. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - InitAlgo- initialization algorithm: - * 0 automatic selection ( different versions of ALGLIB - may select different algorithms) - * 1 random initialization - * 2 k-means++ initialization (best quality of initial - centers, but long non-parallelizable initialization - phase with bad cache locality) - * 3 "fast-greedy" algorithm with efficient, easy to - parallelize initialization. Quality of initial centers - is somewhat worse than that of k-means++. This - algorithm is a default one in the current version of - ALGLIB. - *-1 "debug" algorithm which always selects first K rows - of dataset; this algorithm is used for debug purposes - only. Do not use it in the industrial code! - - -- ALGLIB -- - Copyright 21.01.2015 by Bochkanov Sergey -*************************************************************************/ -void clusterizersetkmeansinit(clusterizerstate* s, - ae_int_t initalgo, - ae_state *_state) -{ - - - ae_assert(initalgo>=-1&&initalgo<=3, "ClusterizerSetKMeansInit: InitAlgo is incorrect", _state); - s->kmeansinitalgo = initalgo; -} - - -/************************************************************************* -This function sets seed which is used to initialize internal RNG. By -default, deterministic seed is used - same for each run of clusterizer. If -you specify non-deterministic seed value, then some algorithms which -depend on random initialization (in current version: k-means) may return -slightly different results after each run. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - Seed - seed: - * positive values = use deterministic seed for each run of - algorithms which depend on random initialization - * zero or negative values = use non-deterministic seed - - -- ALGLIB -- - Copyright 08.06.2017 by Bochkanov Sergey -*************************************************************************/ -void clusterizersetseed(clusterizerstate* s, - ae_int_t seed, - ae_state *_state) -{ - - - s->seed = seed; -} - - -/************************************************************************* -This function performs agglomerative hierarchical clustering - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: Agglomerative hierarchical clustering algorithm has two phases: - distance matrix calculation and clustering itself. Only first phase - (distance matrix calculation) is accelerated by Intel MKL and - multithreading. Thus, acceleration is significant only for medium or - high-dimensional problems. - - Although activating multithreading gives some speedup over single- - threaded execution, you should not expect nearly-linear scaling - with respect to cores count. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - -OUTPUT PARAMETERS: - Rep - clustering results; see description of AHCReport - structure for more information. - -NOTE 1: hierarchical clustering algorithms require large amounts of memory. - In particular, this implementation needs sizeof(double)*NPoints^2 - bytes, which are used to store distance matrix. In case we work - with user-supplied matrix, this amount is multiplied by 2 (we have - to store original matrix and to work with its copy). - - For example, problem with 10000 points would require 800M of RAM, - even when working in a 1-dimensional space. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizerrunahc(clusterizerstate* s, - ahcreport* rep, - ae_state *_state) -{ - ae_int_t npoints; - ae_int_t nfeatures; - - _ahcreport_clear(rep); - - npoints = s->npoints; - nfeatures = s->nfeatures; - - /* - * Fill Rep.NPoints, quick exit when NPoints<=1 - */ - rep->npoints = npoints; - if( npoints==0 ) - { - ae_vector_set_length(&rep->p, 0, _state); - ae_matrix_set_length(&rep->z, 0, 0, _state); - ae_matrix_set_length(&rep->pz, 0, 0, _state); - ae_matrix_set_length(&rep->pm, 0, 0, _state); - ae_vector_set_length(&rep->mergedist, 0, _state); - rep->terminationtype = 1; - return; - } - if( npoints==1 ) - { - ae_vector_set_length(&rep->p, 1, _state); - ae_matrix_set_length(&rep->z, 0, 0, _state); - ae_matrix_set_length(&rep->pz, 0, 0, _state); - ae_matrix_set_length(&rep->pm, 0, 0, _state); - ae_vector_set_length(&rep->mergedist, 0, _state); - rep->p.ptr.p_int[0] = 0; - rep->terminationtype = 1; - return; - } - - /* - * More than one point - */ - if( s->disttype==-1 ) - { - - /* - * Run clusterizer with user-supplied distance matrix - */ - clustering_clusterizerrunahcinternal(s, &s->d, rep, _state); - return; - } - else - { - - /* - * Check combination of AHC algo and distance type - */ - if( s->ahcalgo==4&&s->disttype!=2 ) - { - rep->terminationtype = -5; - return; - } - - /* - * Build distance matrix D. - */ - clusterizergetdistancesbuf(&s->distbuf, &s->xy, npoints, nfeatures, s->disttype, &s->tmpd, _state); - - /* - * Run clusterizer - */ - clustering_clusterizerrunahcinternal(s, &s->tmpd, rep, _state); - return; - } -} - - -/************************************************************************* -This function performs clustering by k-means++ algorithm. - -You may change algorithm properties by calling: -* ClusterizerSetKMeansLimits() to change number of restarts or iterations -* ClusterizerSetKMeansInit() to change initialization algorithm - -By default, one restart and unlimited number of iterations are used. -Initialization algorithm is chosen automatically. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: k-means clustering algorithm has two phases: selection of initial - centers and clustering itself. ALGLIB parallelizes both phases. - Parallel version is optimized for the following scenario: medium or - high-dimensional problem (8 or more dimensions) with large number of - points and clusters. However, some speed-up can be obtained even - when assumptions above are violated. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - K - number of clusters, K>=0. - K can be zero only when algorithm is called for empty - dataset, in this case completion code is set to - success (+1). - If K=0 and dataset size is non-zero, we can not - meaningfully assign points to some center (there are no - centers because K=0) and return -3 as completion code - (failure). - -OUTPUT PARAMETERS: - Rep - clustering results; see description of KMeansReport - structure for more information. - -NOTE 1: k-means clustering can be performed only for datasets with - Euclidean distance function. Algorithm will return negative - completion code in Rep.TerminationType in case dataset was added - to clusterizer with DistType other than Euclidean (or dataset was - specified by distance matrix instead of explicitly given points). - -NOTE 2: by default, k-means uses non-deterministic seed to initialize RNG - which is used to select initial centers. As result, each run of - algorithm may return different values. If you need deterministic - behavior, use ClusterizerSetSeed() function. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizerrunkmeans(clusterizerstate* s, - ae_int_t k, - kmeansreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix dummy; - - ae_frame_make(_state, &_frame_block); - memset(&dummy, 0, sizeof(dummy)); - _kmeansreport_clear(rep); - ae_matrix_init(&dummy, 0, 0, DT_REAL, _state, ae_true); - - ae_assert(k>=0, "ClusterizerRunKMeans: K<0", _state); - - /* - * Incorrect distance type - */ - if( s->disttype!=2 ) - { - rep->npoints = s->npoints; - rep->terminationtype = -5; - rep->k = k; - rep->iterationscount = 0; - rep->energy = 0.0; - ae_frame_leave(_state); - return; - } - - /* - * K>NPoints or (K=0 and NPoints>0) - */ - if( k>s->npoints||(k==0&&s->npoints>0) ) - { - rep->npoints = s->npoints; - rep->terminationtype = -3; - rep->k = k; - rep->iterationscount = 0; - rep->energy = 0.0; - ae_frame_leave(_state); - return; - } - - /* - * No points - */ - if( s->npoints==0 ) - { - rep->npoints = 0; - rep->terminationtype = 1; - rep->k = k; - rep->iterationscount = 0; - rep->energy = 0.0; - ae_frame_leave(_state); - return; - } - - /* - * Normal case: - * 1<=K<=NPoints, Euclidean distance - */ - rep->npoints = s->npoints; - rep->nfeatures = s->nfeatures; - rep->k = k; - rep->npoints = s->npoints; - rep->nfeatures = s->nfeatures; - kmeansgenerateinternal(&s->xy, s->npoints, s->nfeatures, k, s->kmeansinitalgo, s->seed, s->kmeansmaxits, s->kmeansrestarts, s->kmeansdbgnoits, &rep->terminationtype, &rep->iterationscount, &dummy, ae_false, &rep->c, ae_true, &rep->cidx, &rep->energy, &s->kmeanstmp, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function returns distance matrix for dataset - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - array[NPoints,NFeatures], dataset - NPoints - number of points, >=0 - NFeatures- number of features, >=1 - DistType- distance function: - * 0 Chebyshev distance (L-inf norm) - * 1 city block distance (L1 norm) - * 2 Euclidean distance (L2 norm, non-squared) - * 10 Pearson correlation: - dist(a,b) = 1-corr(a,b) - * 11 Absolute Pearson correlation: - dist(a,b) = 1-|corr(a,b)| - * 12 Uncentered Pearson correlation (cosine of the angle): - dist(a,b) = a'*b/(|a|*|b|) - * 13 Absolute uncentered Pearson correlation - dist(a,b) = |a'*b|/(|a|*|b|) - * 20 Spearman rank correlation: - dist(a,b) = 1-rankcorr(a,b) - * 21 Absolute Spearman rank correlation - dist(a,b) = 1-|rankcorr(a,b)| - -OUTPUT PARAMETERS: - D - array[NPoints,NPoints], distance matrix - (full matrix is returned, with lower and upper triangles) - -NOTE: different distance functions have different performance penalty: - * Euclidean or Pearson correlation distances are the fastest ones - * Spearman correlation distance function is a bit slower - * city block and Chebyshev distances are order of magnitude slower - - The reason behing difference in performance is that correlation-based - distance functions are computed using optimized linear algebra kernels, - while Chebyshev and city block distance functions are computed using - simple nested loops with two branches at each iteration. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizergetdistances(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nfeatures, - ae_int_t disttype, - /* Real */ ae_matrix* d, - ae_state *_state) -{ - ae_frame _frame_block; - apbuffers buf; - - ae_frame_make(_state, &_frame_block); - memset(&buf, 0, sizeof(buf)); - ae_matrix_clear(d); - _apbuffers_init(&buf, _state, ae_true); - - ae_assert(nfeatures>=1, "ClusterizerGetDistances: NFeatures<1", _state); - ae_assert(npoints>=0, "ClusterizerGetDistances: NPoints<1", _state); - ae_assert((((((((disttype==0||disttype==1)||disttype==2)||disttype==10)||disttype==11)||disttype==12)||disttype==13)||disttype==20)||disttype==21, "ClusterizerGetDistances: incorrect DistType", _state); - ae_assert(xy->rows>=npoints, "ClusterizerGetDistances: Rows(XY)cols>=nfeatures, "ClusterizerGetDistances: Cols(XY)=1, "ClusterizerGetDistancesBuf: NFeatures<1", _state); - ae_assert(npoints>=0, "ClusterizerGetDistancesBuf: NPoints<1", _state); - ae_assert((((((((disttype==0||disttype==1)||disttype==2)||disttype==10)||disttype==11)||disttype==12)||disttype==13)||disttype==20)||disttype==21, "ClusterizerGetDistancesBuf: incorrect DistType", _state); - ae_assert(xy->rows>=npoints, "ClusterizerGetDistancesBuf: Rows(XY)cols>=nfeatures, "ClusterizerGetDistancesBuf: Cols(XY)ptr.pp_double[0][0] = (double)(0); - return; - } - - /* - * Build distance matrix D. - */ - if( disttype==0||disttype==1 ) - { - - /* - * Chebyshev or city-block distances: - * * recursively calculate upper triangle (with main diagonal) - * * copy it to the bottom part of the matrix - */ - rmatrixsetlengthatleast(d, npoints, npoints, _state); - clustering_evaluatedistancematrixrec(xy, nfeatures, disttype, d, 0, npoints, 0, npoints, _state); - rmatrixenforcesymmetricity(d, npoints, ae_true, _state); - return; - } - if( disttype==2 ) - { - - /* - * Euclidean distance - * - * NOTE: parallelization is done within RMatrixSYRK - */ - rmatrixsetlengthatleast(d, npoints, npoints, _state); - rmatrixsetlengthatleast(&buf->rm0, npoints, nfeatures, _state); - rvectorsetlengthatleast(&buf->ra1, nfeatures, _state); - rvectorsetlengthatleast(&buf->ra0, npoints, _state); - for(j=0; j<=nfeatures-1; j++) - { - buf->ra1.ptr.p_double[j] = 0.0; - } - v = (double)1/(double)npoints; - for(i=0; i<=npoints-1; i++) - { - ae_v_addd(&buf->ra1.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nfeatures-1), v); - } - for(i=0; i<=npoints-1; i++) - { - ae_v_move(&buf->rm0.ptr.pp_double[i][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nfeatures-1)); - ae_v_sub(&buf->rm0.ptr.pp_double[i][0], 1, &buf->ra1.ptr.p_double[0], 1, ae_v_len(0,nfeatures-1)); - } - rmatrixsyrk(npoints, nfeatures, 1.0, &buf->rm0, 0, 0, 0, 0.0, d, 0, 0, ae_true, _state); - for(i=0; i<=npoints-1; i++) - { - buf->ra0.ptr.p_double[i] = d->ptr.pp_double[i][i]; - } - for(i=0; i<=npoints-1; i++) - { - d->ptr.pp_double[i][i] = 0.0; - for(j=i+1; j<=npoints-1; j++) - { - v = ae_sqrt(ae_maxreal(buf->ra0.ptr.p_double[i]+buf->ra0.ptr.p_double[j]-2*d->ptr.pp_double[i][j], 0.0, _state), _state); - d->ptr.pp_double[i][j] = v; - } - } - rmatrixenforcesymmetricity(d, npoints, ae_true, _state); - return; - } - if( disttype==10||disttype==11 ) - { - - /* - * Absolute/nonabsolute Pearson correlation distance - * - * NOTE: parallelization is done within PearsonCorrM, which calls RMatrixSYRK internally - */ - rmatrixsetlengthatleast(d, npoints, npoints, _state); - rvectorsetlengthatleast(&buf->ra0, npoints, _state); - rmatrixsetlengthatleast(&buf->rm0, npoints, nfeatures, _state); - for(i=0; i<=npoints-1; i++) - { - v = 0.0; - for(j=0; j<=nfeatures-1; j++) - { - v = v+xy->ptr.pp_double[i][j]; - } - v = v/nfeatures; - for(j=0; j<=nfeatures-1; j++) - { - buf->rm0.ptr.pp_double[i][j] = xy->ptr.pp_double[i][j]-v; - } - } - rmatrixsyrk(npoints, nfeatures, 1.0, &buf->rm0, 0, 0, 0, 0.0, d, 0, 0, ae_true, _state); - for(i=0; i<=npoints-1; i++) - { - buf->ra0.ptr.p_double[i] = d->ptr.pp_double[i][i]; - } - for(i=0; i<=npoints-1; i++) - { - d->ptr.pp_double[i][i] = 0.0; - for(j=i+1; j<=npoints-1; j++) - { - v = d->ptr.pp_double[i][j]/ae_sqrt(buf->ra0.ptr.p_double[i]*buf->ra0.ptr.p_double[j], _state); - if( disttype==10 ) - { - v = 1-v; - } - else - { - v = 1-ae_fabs(v, _state); - } - v = ae_maxreal(v, 0.0, _state); - d->ptr.pp_double[i][j] = v; - } - } - rmatrixenforcesymmetricity(d, npoints, ae_true, _state); - return; - } - if( disttype==12||disttype==13 ) - { - - /* - * Absolute/nonabsolute uncentered Pearson correlation distance - * - * NOTE: parallelization is done within RMatrixSYRK - */ - rmatrixsetlengthatleast(d, npoints, npoints, _state); - rvectorsetlengthatleast(&buf->ra0, npoints, _state); - rmatrixsyrk(npoints, nfeatures, 1.0, xy, 0, 0, 0, 0.0, d, 0, 0, ae_true, _state); - for(i=0; i<=npoints-1; i++) - { - buf->ra0.ptr.p_double[i] = d->ptr.pp_double[i][i]; - } - for(i=0; i<=npoints-1; i++) - { - d->ptr.pp_double[i][i] = 0.0; - for(j=i+1; j<=npoints-1; j++) - { - v = d->ptr.pp_double[i][j]/ae_sqrt(buf->ra0.ptr.p_double[i]*buf->ra0.ptr.p_double[j], _state); - if( disttype==13 ) - { - v = ae_fabs(v, _state); - } - v = ae_minreal(v, 1.0, _state); - d->ptr.pp_double[i][j] = 1-v; - } - } - rmatrixenforcesymmetricity(d, npoints, ae_true, _state); - return; - } - if( disttype==20||disttype==21 ) - { - - /* - * Spearman rank correlation - * - * NOTE: parallelization of correlation matrix is done within - * PearsonCorrM, which calls RMatrixSYRK internally - */ - rmatrixsetlengthatleast(d, npoints, npoints, _state); - rvectorsetlengthatleast(&buf->ra0, npoints, _state); - rmatrixsetlengthatleast(&buf->rm0, npoints, nfeatures, _state); - rmatrixcopy(npoints, nfeatures, xy, 0, 0, &buf->rm0, 0, 0, _state); - rankdatacentered(&buf->rm0, npoints, nfeatures, _state); - rmatrixsyrk(npoints, nfeatures, 1.0, &buf->rm0, 0, 0, 0, 0.0, d, 0, 0, ae_true, _state); - for(i=0; i<=npoints-1; i++) - { - if( ae_fp_greater(d->ptr.pp_double[i][i],(double)(0)) ) - { - buf->ra0.ptr.p_double[i] = 1/ae_sqrt(d->ptr.pp_double[i][i], _state); - } - else - { - buf->ra0.ptr.p_double[i] = 0.0; - } - } - for(i=0; i<=npoints-1; i++) - { - v = buf->ra0.ptr.p_double[i]; - d->ptr.pp_double[i][i] = 0.0; - for(j=i+1; j<=npoints-1; j++) - { - vv = d->ptr.pp_double[i][j]*v*buf->ra0.ptr.p_double[j]; - if( disttype==20 ) - { - vr = 1-vv; - } - else - { - vr = 1-ae_fabs(vv, _state); - } - if( ae_fp_less(vr,(double)(0)) ) - { - vr = 0.0; - } - d->ptr.pp_double[i][j] = vr; - } - } - rmatrixenforcesymmetricity(d, npoints, ae_true, _state); - return; - } - ae_assert(ae_false, "Assertion failed", _state); -} - - -/************************************************************************* -This function takes as input clusterization report Rep, desired clusters -count K, and builds top K clusters from hierarchical clusterization tree. -It returns assignment of points to clusters (array of cluster indexes). - -INPUT PARAMETERS: - Rep - report from ClusterizerRunAHC() performed on XY - K - desired number of clusters, 1<=K<=NPoints. - K can be zero only when NPoints=0. - -OUTPUT PARAMETERS: - CIdx - array[NPoints], I-th element contains cluster index (from - 0 to K-1) for I-th point of the dataset. - CZ - array[K]. This array allows to convert cluster indexes - returned by this function to indexes used by Rep.Z. J-th - cluster returned by this function corresponds to CZ[J]-th - cluster stored in Rep.Z/PZ/PM. - It is guaranteed that CZ[I]npoints; - ae_assert(npoints>=0, "ClusterizerGetKClusters: internal error in Rep integrity", _state); - ae_assert(k>=0, "ClusterizerGetKClusters: K<=0", _state); - ae_assert(k<=npoints, "ClusterizerGetKClusters: K>NPoints", _state); - ae_assert(k>0||npoints==0, "ClusterizerGetKClusters: K<=0", _state); - ae_assert(npoints==rep->npoints, "ClusterizerGetKClusters: NPoints<>Rep.NPoints", _state); - - /* - * Quick exit - */ - if( npoints==0 ) - { - ae_frame_leave(_state); - return; - } - if( npoints==1 ) - { - ae_vector_set_length(cz, 1, _state); - ae_vector_set_length(cidx, 1, _state); - cz->ptr.p_int[0] = 0; - cidx->ptr.p_int[0] = 0; - ae_frame_leave(_state); - return; - } - - /* - * Replay merges, from top to bottom, - * keep track of clusters being present at the moment - */ - ae_vector_set_length(&presentclusters, 2*npoints-1, _state); - ae_vector_set_length(&tmpidx, npoints, _state); - for(i=0; i<=2*npoints-3; i++) - { - presentclusters.ptr.p_bool[i] = ae_false; - } - presentclusters.ptr.p_bool[2*npoints-2] = ae_true; - for(i=0; i<=npoints-1; i++) - { - tmpidx.ptr.p_int[i] = 2*npoints-2; - } - for(mergeidx=npoints-2; mergeidx>=npoints-k; mergeidx--) - { - - /* - * Update information about clusters being present at the moment - */ - presentclusters.ptr.p_bool[npoints+mergeidx] = ae_false; - presentclusters.ptr.p_bool[rep->z.ptr.pp_int[mergeidx][0]] = ae_true; - presentclusters.ptr.p_bool[rep->z.ptr.pp_int[mergeidx][1]] = ae_true; - - /* - * Update TmpIdx according to the current state of the dataset - * - * NOTE: TmpIdx contains cluster indexes from [0..2*NPoints-2]; - * we will convert them to [0..K-1] later. - */ - i0 = rep->pm.ptr.pp_int[mergeidx][0]; - i1 = rep->pm.ptr.pp_int[mergeidx][1]; - t = rep->z.ptr.pp_int[mergeidx][0]; - for(i=i0; i<=i1; i++) - { - tmpidx.ptr.p_int[i] = t; - } - i0 = rep->pm.ptr.pp_int[mergeidx][2]; - i1 = rep->pm.ptr.pp_int[mergeidx][3]; - t = rep->z.ptr.pp_int[mergeidx][1]; - for(i=i0; i<=i1; i++) - { - tmpidx.ptr.p_int[i] = t; - } - } - - /* - * Fill CZ - array which allows us to convert cluster indexes - * from one system to another. - */ - ae_vector_set_length(cz, k, _state); - ae_vector_set_length(&clusterindexes, 2*npoints-1, _state); - t = 0; - for(i=0; i<=2*npoints-2; i++) - { - if( presentclusters.ptr.p_bool[i] ) - { - cz->ptr.p_int[t] = i; - clusterindexes.ptr.p_int[i] = t; - t = t+1; - } - } - ae_assert(t==k, "ClusterizerGetKClusters: internal error", _state); - - /* - * Convert indexes stored in CIdx - */ - ae_vector_set_length(cidx, npoints, _state); - for(i=0; i<=npoints-1; i++) - { - cidx->ptr.p_int[i] = clusterindexes.ptr.p_int[tmpidx.ptr.p_int[rep->p.ptr.p_int[i]]]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function accepts AHC report Rep, desired minimum intercluster -distance and returns top clusters from hierarchical clusterization tree -which are separated by distance R or HIGHER. - -It returns assignment of points to clusters (array of cluster indexes). - -There is one more function with similar name - ClusterizerSeparatedByCorr, -which returns clusters with intercluster correlation equal to R or LOWER -(note: higher for distance, lower for correlation). - -INPUT PARAMETERS: - Rep - report from ClusterizerRunAHC() performed on XY - R - desired minimum intercluster distance, R>=0 - -OUTPUT PARAMETERS: - K - number of clusters, 1<=K<=NPoints - CIdx - array[NPoints], I-th element contains cluster index (from - 0 to K-1) for I-th point of the dataset. - CZ - array[K]. This array allows to convert cluster indexes - returned by this function to indexes used by Rep.Z. J-th - cluster returned by this function corresponds to CZ[J]-th - cluster stored in Rep.Z/PZ/PM. - It is guaranteed that CZ[I]npoints&&ae_fp_greater_eq(rep->mergedist.ptr.p_double[rep->npoints-1-(*k)],r)) - { - *k = *k+1; - } - clusterizergetkclusters(rep, *k, cidx, cz, _state); -} - - -/************************************************************************* -This function accepts AHC report Rep, desired maximum intercluster -correlation and returns top clusters from hierarchical clusterization tree -which are separated by correlation R or LOWER. - -It returns assignment of points to clusters (array of cluster indexes). - -There is one more function with similar name - ClusterizerSeparatedByDist, -which returns clusters with intercluster distance equal to R or HIGHER -(note: higher for distance, lower for correlation). - -INPUT PARAMETERS: - Rep - report from ClusterizerRunAHC() performed on XY - R - desired maximum intercluster correlation, -1<=R<=+1 - -OUTPUT PARAMETERS: - K - number of clusters, 1<=K<=NPoints - CIdx - array[NPoints], I-th element contains cluster index (from - 0 to K-1) for I-th point of the dataset. - CZ - array[K]. This array allows to convert cluster indexes - returned by this function to indexes used by Rep.Z. J-th - cluster returned by this function corresponds to CZ[J]-th - cluster stored in Rep.Z/PZ/PM. - It is guaranteed that CZ[I]npoints&&ae_fp_greater_eq(rep->mergedist.ptr.p_double[rep->npoints-1-(*k)],1-r)) - { - *k = *k+1; - } - clusterizergetkclusters(rep, *k, cidx, cz, _state); -} - - -/************************************************************************* -K-means++ initialization - -INPUT PARAMETERS: - Buf - special reusable structure which stores previously allocated - memory, intended to avoid memory fragmentation when solving - multiple subsequent problems. Must be initialized prior to - usage. - -OUTPUT PARAMETERS: - Buf - initialized structure - - -- ALGLIB -- - Copyright 24.07.2015 by Bochkanov Sergey -*************************************************************************/ -void kmeansinitbuf(kmeansbuffers* buf, ae_state *_state) -{ - ae_frame _frame_block; - apbuffers updateseed; - - ae_frame_make(_state, &_frame_block); - memset(&updateseed, 0, sizeof(updateseed)); - _apbuffers_init(&updateseed, _state, ae_true); - - ae_shared_pool_set_seed(&buf->updatepool, &updateseed, sizeof(updateseed), _apbuffers_init, _apbuffers_init_copy, _apbuffers_destroy, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -K-means++ clusterization - -INPUT PARAMETERS: - XY - dataset, array [0..NPoints-1,0..NVars-1]. - NPoints - dataset size, NPoints>=K - NVars - number of variables, NVars>=1 - K - desired number of clusters, K>=1 - InitAlgo - initialization algorithm: - * 0 - automatic selection of best algorithm - * 1 - random selection of centers - * 2 - k-means++ - * 3 - fast-greedy init - *-1 - first K rows of dataset are used - (special debug algorithm) - Seed - seed value for internal RNG: - * positive value is used to initialize RNG in order to - induce deterministic behavior of algorithm - * zero or negative value means that random seed is - generated - MaxIts - iterations limit or zero for no limit - Restarts - number of restarts, Restarts>=1 - KMeansDbgNoIts- debug flag; if set, Lloyd's iteration is not performed, - only initialization phase. - Buf - special reusable structure which stores previously allocated - memory, intended to avoid memory fragmentation when solving - multiple subsequent problems: - * MUST BE INITIALIZED WITH KMeansInitBuffers() CALL BEFORE - FIRST PASS TO THIS FUNCTION! - * subsequent passes must be made without re-initialization - -OUTPUT PARAMETERS: - Info - return code: - * -3, if task is degenerate (number of distinct points is - less than K) - * -1, if incorrect NPoints/NFeatures/K/Restarts was passed - * 1, if subroutine finished successfully - IterationsCount- actual number of iterations performed by clusterizer - CCol - array[0..NVars-1,0..K-1].matrix whose columns store - cluster's centers - NeedCCol - True in case caller requires to store result in CCol - CRow - array[0..K-1,0..NVars-1], same as CCol, but centers are - stored in rows - NeedCRow - True in case caller requires to store result in CCol - XYC - array[NPoints], which contains cluster indexes - Energy - merit function of clusterization - - -- ALGLIB -- - Copyright 21.03.2009 by Bochkanov Sergey -*************************************************************************/ -void kmeansgenerateinternal(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t k, - ae_int_t initalgo, - ae_int_t seed, - ae_int_t maxits, - ae_int_t restarts, - ae_bool kmeansdbgnoits, - ae_int_t* info, - ae_int_t* iterationscount, - /* Real */ ae_matrix* ccol, - ae_bool needccol, - /* Real */ ae_matrix* crow, - ae_bool needcrow, - /* Integer */ ae_vector* xyc, - double* energy, - kmeansbuffers* buf, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t i1; - double e; - double eprev; - double v; - double vv; - ae_bool waschanges; - ae_bool zerosizeclusters; - ae_int_t pass; - ae_int_t itcnt; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - *info = 0; - *iterationscount = 0; - ae_matrix_clear(ccol); - ae_matrix_clear(crow); - ae_vector_clear(xyc); - *energy = 0; - _hqrndstate_init(&rs, _state, ae_true); - - - /* - * Test parameters - */ - if( ((npointsct, k, nvars, _state); - rmatrixsetlengthatleast(&buf->ctbest, k, nvars, _state); - ivectorsetlengthatleast(&buf->xycprev, npoints, _state); - ivectorsetlengthatleast(&buf->xycbest, npoints, _state); - rvectorsetlengthatleast(&buf->d2, npoints, _state); - ivectorsetlengthatleast(&buf->csizes, k, _state); - *energy = ae_maxrealnumber; - for(pass=1; pass<=restarts; pass++) - { - - /* - * Select initial centers. - * - * Note that for performance reasons centers are stored in ROWS of CT, not - * in columns. We'll transpose CT in the end and store it in the C. - * - * Also note that SelectInitialCenters() may return degenerate set of centers - * (some of them have no corresponding points in dataset, some are non-distinct). - * Algorithm below is robust enough to deal with such set. - */ - clustering_selectinitialcenters(xy, npoints, nvars, initalgo, &rs, k, &buf->ct, &buf->initbuf, &buf->updatepool, _state); - - /* - * Lloyd's iteration - */ - if( !kmeansdbgnoits ) - { - - /* - * Perform iteration as usual, in normal mode - */ - for(i=0; i<=npoints-1; i++) - { - xyc->ptr.p_int[i] = -1; - } - eprev = ae_maxrealnumber; - e = ae_maxrealnumber; - itcnt = 0; - while(maxits==0||itcntxycprev.ptr.p_int[i] = xyc->ptr.p_int[i]; - } - kmeansupdatedistances(xy, 0, npoints, nvars, &buf->ct, 0, k, xyc, &buf->d2, &buf->updatepool, _state); - waschanges = ae_false; - for(i=0; i<=npoints-1; i++) - { - waschanges = waschanges||xyc->ptr.p_int[i]!=buf->xycprev.ptr.p_int[i]; - } - - /* - * Update centers - */ - for(j=0; j<=k-1; j++) - { - buf->csizes.ptr.p_int[j] = 0; - } - for(i=0; i<=k-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - buf->ct.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=npoints-1; i++) - { - buf->csizes.ptr.p_int[xyc->ptr.p_int[i]] = buf->csizes.ptr.p_int[xyc->ptr.p_int[i]]+1; - ae_v_add(&buf->ct.ptr.pp_double[xyc->ptr.p_int[i]][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - } - zerosizeclusters = ae_false; - for(j=0; j<=k-1; j++) - { - if( buf->csizes.ptr.p_int[j]!=0 ) - { - v = (double)1/(double)buf->csizes.ptr.p_int[j]; - ae_v_muld(&buf->ct.ptr.pp_double[j][0], 1, ae_v_len(0,nvars-1), v); - } - zerosizeclusters = zerosizeclusters||buf->csizes.ptr.p_int[j]==0; - } - if( zerosizeclusters ) - { - - /* - * Some clusters have zero size - rare, but possible. - * We'll choose new centers for such clusters using k-means++ rule - * and restart algorithm, decrementing iteration counter - * in order to allow one more iteration (this one was useless - * and should not be counted). - */ - if( !clustering_fixcenters(xy, npoints, nvars, &buf->ct, k, &buf->initbuf, &buf->updatepool, _state) ) - { - *info = -3; - ae_frame_leave(_state); - return; - } - itcnt = itcnt-1; - continue; - } - - /* - * Stop if one of two conditions is met: - * 1. nothing has changed during iteration - * 2. energy function increased after recalculation on new centers - */ - e = (double)(0); - for(i=0; i<=npoints-1; i++) - { - v = 0.0; - i1 = xyc->ptr.p_int[i]; - for(j=0; j<=nvars-1; j++) - { - vv = xy->ptr.pp_double[i][j]-buf->ct.ptr.pp_double[i1][j]; - v = v+vv*vv; - } - e = e+v; - } - if( !waschanges||ae_fp_greater_eq(e,eprev) ) - { - break; - } - - /* - * Update EPrev - */ - eprev = e; - } - } - else - { - - /* - * Debug mode: no Lloyd's iteration. - * We just calculate potential E. - */ - kmeansupdatedistances(xy, 0, npoints, nvars, &buf->ct, 0, k, xyc, &buf->d2, &buf->updatepool, _state); - e = (double)(0); - for(i=0; i<=npoints-1; i++) - { - e = e+buf->d2.ptr.p_double[i]; - } - } - - /* - * Compare E with best centers found so far - */ - if( ae_fp_less(e,*energy) ) - { - - /* - * store partition. - */ - *energy = e; - copymatrix(&buf->ct, 0, k-1, 0, nvars-1, &buf->ctbest, 0, k-1, 0, nvars-1, _state); - for(i=0; i<=npoints-1; i++) - { - buf->xycbest.ptr.p_int[i] = xyc->ptr.p_int[i]; - } - } - } - - /* - * Copy and transpose - */ - if( needccol ) - { - ae_matrix_set_length(ccol, nvars, k, _state); - copyandtranspose(&buf->ctbest, 0, k-1, 0, nvars-1, ccol, 0, nvars-1, 0, k-1, _state); - } - if( needcrow ) - { - ae_matrix_set_length(crow, k, nvars, _state); - rmatrixcopy(k, nvars, &buf->ctbest, 0, 0, crow, 0, 0, _state); - } - for(i=0; i<=npoints-1; i++) - { - xyc->ptr.p_int[i] = buf->xycbest.ptr.p_int[i]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This procedure recalculates distances from points to centers and assigns -each point to closest center. - -INPUT PARAMETERS: - XY - dataset, array [0..NPoints-1,0..NVars-1]. - Idx0,Idx1 - define range of dataset [Idx0,Idx1) to process; - right boundary is not included. - NVars - number of variables, NVars>=1 - CT - matrix of centers, centers are stored in rows - CIdx0,CIdx1 - define range of centers [CIdx0,CIdx1) to process; - right boundary is not included. - XYC - preallocated output buffer, - XYDist2 - preallocated output buffer - Tmp - temporary buffer, automatically reallocated if needed - BufferPool - shared pool seeded with instance of APBuffers structure - (seed instance can be unitialized). It is recommended - to use this pool only with KMeansUpdateDistances() - function. - -OUTPUT PARAMETERS: - XYC - new assignment of points to centers are stored - in [Idx0,Idx1) - XYDist2 - squared distances from points to their centers are - stored in [Idx0,Idx1) - - -- ALGLIB -- - Copyright 21.01.2015 by Bochkanov Sergey -*************************************************************************/ -void kmeansupdatedistances(/* Real */ ae_matrix* xy, - ae_int_t idx0, - ae_int_t idx1, - ae_int_t nvars, - /* Real */ ae_matrix* ct, - ae_int_t cidx0, - ae_int_t cidx1, - /* Integer */ ae_vector* xyc, - /* Real */ ae_vector* xydist2, - ae_shared_pool* bufferpool, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t i0; - ae_int_t i1; - ae_int_t j; - ae_int_t cclosest; - double dclosest; - double vv; - apbuffers *buf; - ae_smart_ptr _buf; - double rcomplexity; - ae_int_t task0; - ae_int_t task1; - ae_int_t pblkcnt; - ae_int_t cblkcnt; - ae_int_t vblkcnt; - ae_int_t pblk; - ae_int_t cblk; - ae_int_t vblk; - ae_int_t p0; - ae_int_t p1; - ae_int_t c0; - ae_int_t c1; - ae_int_t v0; - ae_int_t v1; - double v00; - double v01; - double v10; - double v11; - double vp0; - double vp1; - double vc0; - double vc1; - ae_int_t pcnt; - ae_int_t pcntpadded; - ae_int_t ccnt; - ae_int_t ccntpadded; - ae_int_t offs0; - ae_int_t offs00; - ae_int_t offs01; - ae_int_t offs10; - ae_int_t offs11; - ae_int_t vcnt; - ae_int_t stride; - - ae_frame_make(_state, &_frame_block); - memset(&_buf, 0, sizeof(_buf)); - ae_smart_ptr_init(&_buf, (void**)&buf, _state, ae_true); - - - /* - * Quick exit for special cases - */ - if( idx1<=idx0 ) - { - ae_frame_leave(_state); - return; - } - if( cidx1<=cidx0 ) - { - ae_frame_leave(_state); - return; - } - if( nvars<=0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Try to recursively divide/process dataset - * - * NOTE: real arithmetics is used to avoid integer overflow on large problem sizes - */ - rcomplexity = 2*rmul3((double)(idx1-idx0), (double)(cidx1-cidx0), (double)(nvars), _state); - if( ae_fp_greater_eq(rcomplexity,smpactivationlevel(_state))&&idx1-idx0>=2*clustering_kmeansblocksize ) - { - if( _trypexec_kmeansupdatedistances(xy,idx0,idx1,nvars,ct,cidx0,cidx1,xyc,xydist2,bufferpool, _state) ) - { - ae_frame_leave(_state); - return; - } - } - if( ((ae_fp_greater_eq(rcomplexity,spawnlevel(_state))&&idx1-idx0>=2*clustering_kmeansblocksize)&&nvars>=clustering_kmeansparalleldim)&&cidx1-cidx0>=clustering_kmeansparallelk ) - { - splitlength(idx1-idx0, clustering_kmeansblocksize, &task0, &task1, _state); - kmeansupdatedistances(xy, idx0, idx0+task0, nvars, ct, cidx0, cidx1, xyc, xydist2, bufferpool, _state); - kmeansupdatedistances(xy, idx0+task0, idx1, nvars, ct, cidx0, cidx1, xyc, xydist2, bufferpool, _state); - ae_frame_leave(_state); - return; - } - - /* - * Dataset chunk is selected. - * - * Process it with blocked algorithm: - * * iterate over points, process them in KMeansBlockSize-ed chunks - * * for each chunk of dataset, iterate over centers, process them in KMeansBlockSize-ed chunks - * * for each chunk of dataset/centerset, iterate over variables, process them in KMeansBlockSize-ed chunks - */ - ae_assert(clustering_kmeansblocksize%2==0, "KMeansUpdateDistances: internal error", _state); - ae_shared_pool_retrieve(bufferpool, &_buf, _state); - rvectorsetlengthatleast(&buf->ra0, clustering_kmeansblocksize*clustering_kmeansblocksize, _state); - rvectorsetlengthatleast(&buf->ra1, clustering_kmeansblocksize*clustering_kmeansblocksize, _state); - rvectorsetlengthatleast(&buf->ra2, clustering_kmeansblocksize*clustering_kmeansblocksize, _state); - rvectorsetlengthatleast(&buf->ra3, clustering_kmeansblocksize, _state); - ivectorsetlengthatleast(&buf->ia3, clustering_kmeansblocksize, _state); - pblkcnt = chunkscount(idx1-idx0, clustering_kmeansblocksize, _state); - cblkcnt = chunkscount(cidx1-cidx0, clustering_kmeansblocksize, _state); - vblkcnt = chunkscount(nvars, clustering_kmeansblocksize, _state); - for(pblk=0; pblk<=pblkcnt-1; pblk++) - { - - /* - * Process PBlk-th chunk of dataset. - */ - p0 = idx0+pblk*clustering_kmeansblocksize; - p1 = ae_minint(p0+clustering_kmeansblocksize, idx1, _state); - - /* - * Prepare RA3[]/IA3[] for storage of best distances and best cluster numbers. - */ - for(i=0; i<=clustering_kmeansblocksize-1; i++) - { - buf->ra3.ptr.p_double[i] = ae_maxrealnumber; - buf->ia3.ptr.p_int[i] = -1; - } - - /* - * Iterare over chunks of centerset. - */ - for(cblk=0; cblk<=cblkcnt-1; cblk++) - { - - /* - * Process CBlk-th chunk of centerset - */ - c0 = cidx0+cblk*clustering_kmeansblocksize; - c1 = ae_minint(c0+clustering_kmeansblocksize, cidx1, _state); - - /* - * At this point we have to calculate a set of pairwise distances - * between points [P0,P1) and centers [C0,C1) and select best center - * for each point. It can also be done with blocked algorithm - * (blocking for variables). - * - * Following arrays are used: - * * RA0[] - matrix of distances, padded by zeros for even size, - * rows are stored with stride KMeansBlockSize. - * * RA1[] - matrix of points (variables corresponding to current - * block are extracted), padded by zeros for even size, - * rows are stored with stride KMeansBlockSize. - * * RA2[] - matrix of centers (variables corresponding to current - * block are extracted), padded by zeros for even size, - * rows are stored with stride KMeansBlockSize. - * - */ - pcnt = p1-p0; - pcntpadded = pcnt+pcnt%2; - ccnt = c1-c0; - ccntpadded = ccnt+ccnt%2; - stride = clustering_kmeansblocksize; - ae_assert(pcntpadded<=clustering_kmeansblocksize, "KMeansUpdateDistances: integrity error", _state); - ae_assert(ccntpadded<=clustering_kmeansblocksize, "KMeansUpdateDistances: integrity error", _state); - for(i=0; i<=pcntpadded-1; i++) - { - for(j=0; j<=ccntpadded-1; j++) - { - buf->ra0.ptr.p_double[i*stride+j] = 0.0; - } - } - for(vblk=0; vblk<=vblkcnt-1; vblk++) - { - - /* - * Fetch VBlk-th block of variables to arrays RA1 (points) and RA2 (centers). - * Pad points and centers with zeros. - */ - v0 = vblk*clustering_kmeansblocksize; - v1 = ae_minint(v0+clustering_kmeansblocksize, nvars, _state); - vcnt = v1-v0; - for(i=0; i<=pcnt-1; i++) - { - for(j=0; j<=vcnt-1; j++) - { - buf->ra1.ptr.p_double[i*stride+j] = xy->ptr.pp_double[p0+i][v0+j]; - } - } - for(i=pcnt; i<=pcntpadded-1; i++) - { - for(j=0; j<=vcnt-1; j++) - { - buf->ra1.ptr.p_double[i*stride+j] = 0.0; - } - } - for(i=0; i<=ccnt-1; i++) - { - for(j=0; j<=vcnt-1; j++) - { - buf->ra2.ptr.p_double[i*stride+j] = ct->ptr.pp_double[c0+i][v0+j]; - } - } - for(i=ccnt; i<=ccntpadded-1; i++) - { - for(j=0; j<=vcnt-1; j++) - { - buf->ra2.ptr.p_double[i*stride+j] = 0.0; - } - } - - /* - * Update distance matrix with sums-of-squared-differences of RA1 and RA2 - */ - i0 = 0; - while(i0ra0.ptr.p_double[offs0]; - v01 = buf->ra0.ptr.p_double[offs0+1]; - v10 = buf->ra0.ptr.p_double[offs0+stride]; - v11 = buf->ra0.ptr.p_double[offs0+stride+1]; - offs00 = i0*stride; - offs01 = offs00+stride; - offs10 = i1*stride; - offs11 = offs10+stride; - for(j=0; j<=vcnt-1; j++) - { - vp0 = buf->ra1.ptr.p_double[offs00+j]; - vp1 = buf->ra1.ptr.p_double[offs01+j]; - vc0 = buf->ra2.ptr.p_double[offs10+j]; - vc1 = buf->ra2.ptr.p_double[offs11+j]; - vv = vp0-vc0; - v00 = v00+vv*vv; - vv = vp0-vc1; - v01 = v01+vv*vv; - vv = vp1-vc0; - v10 = v10+vv*vv; - vv = vp1-vc1; - v11 = v11+vv*vv; - } - offs0 = i0*stride+i1; - buf->ra0.ptr.p_double[offs0] = v00; - buf->ra0.ptr.p_double[offs0+1] = v01; - buf->ra0.ptr.p_double[offs0+stride] = v10; - buf->ra0.ptr.p_double[offs0+stride+1] = v11; - i1 = i1+2; - } - i0 = i0+2; - } - } - for(i=0; i<=pcnt-1; i++) - { - cclosest = buf->ia3.ptr.p_int[i]; - dclosest = buf->ra3.ptr.p_double[i]; - for(j=0; j<=ccnt-1; j++) - { - if( ae_fp_less(buf->ra0.ptr.p_double[i*stride+j],dclosest) ) - { - dclosest = buf->ra0.ptr.p_double[i*stride+j]; - cclosest = c0+j; - } - } - buf->ia3.ptr.p_int[i] = cclosest; - buf->ra3.ptr.p_double[i] = dclosest; - } - } - - /* - * Store best centers to XYC[] - */ - for(i=p0; i<=p1-1; i++) - { - xyc->ptr.p_int[i] = buf->ia3.ptr.p_int[i-p0]; - xydist2->ptr.p_double[i] = buf->ra3.ptr.p_double[i-p0]; - } - } - ae_shared_pool_recycle(bufferpool, &_buf, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_kmeansupdatedistances(/* Real */ ae_matrix* xy, - ae_int_t idx0, - ae_int_t idx1, - ae_int_t nvars, - /* Real */ ae_matrix* ct, - ae_int_t cidx0, - ae_int_t cidx1, - /* Integer */ ae_vector* xyc, - /* Real */ ae_vector* xydist2, - ae_shared_pool* bufferpool, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -This function selects initial centers according to specified initialization -algorithm. - -IMPORTANT: this function provides no guarantees regarding selection of - DIFFERENT centers. Centers returned by this function may - include duplicates (say, when random sampling is used). It is - also possible that some centers are empty. - Algorithm which uses this function must be able to deal with it. - Say, you may want to use FixCenters() in order to fix empty centers. - -INPUT PARAMETERS: - XY - dataset, array [0..NPoints-1,0..NVars-1]. - NPoints - points count - NVars - number of variables, NVars>=1 - InitAlgo - initialization algorithm: - * 0 - automatic selection of best algorithm - * 1 - random selection - * 2 - k-means++ - * 3 - fast-greedy init - *-1 - first K rows of dataset are used (debug algorithm) - RS - RNG used to select centers - K - number of centers, K>=1 - CT - possibly preallocated output buffer, resized if needed - InitBuf - internal buffer, possibly unitialized instance of - APBuffers. It is recommended to use this instance only - with SelectInitialCenters() and FixCenters() functions, - because these functions may allocate really large storage. - UpdatePool - shared pool seeded with instance of APBuffers structure - (seed instance can be unitialized). Used internally with - KMeansUpdateDistances() function. It is recommended - to use this pool ONLY with KMeansUpdateDistances() - function. - -OUTPUT PARAMETERS: - CT - set of K clusters, one per row - -RESULT: - True on success, False on failure (impossible to create K independent clusters) - - -- ALGLIB -- - Copyright 21.01.2015 by Bochkanov Sergey -*************************************************************************/ -static void clustering_selectinitialcenters(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t initalgo, - hqrndstate* rs, - ae_int_t k, - /* Real */ ae_matrix* ct, - apbuffers* initbuf, - ae_shared_pool* updatepool, - ae_state *_state) -{ - ae_int_t cidx; - ae_int_t i; - ae_int_t j; - double v; - double vv; - double s; - ae_int_t lastnz; - ae_int_t ptidx; - ae_int_t samplesize; - ae_int_t samplescntnew; - ae_int_t samplescntall; - double samplescale; - - - - /* - * Check parameters - */ - ae_assert(npoints>0, "SelectInitialCenters: internal error", _state); - ae_assert(nvars>0, "SelectInitialCenters: internal error", _state); - ae_assert(k>0, "SelectInitialCenters: internal error", _state); - if( initalgo==0 ) - { - initalgo = 3; - } - rmatrixsetlengthatleast(ct, k, nvars, _state); - - /* - * Random initialization - */ - if( initalgo==-1 ) - { - for(i=0; i<=k-1; i++) - { - ae_v_move(&ct->ptr.pp_double[i][0], 1, &xy->ptr.pp_double[i%npoints][0], 1, ae_v_len(0,nvars-1)); - } - return; - } - - /* - * Random initialization - */ - if( initalgo==1 ) - { - for(i=0; i<=k-1; i++) - { - j = hqrnduniformi(rs, npoints, _state); - ae_v_move(&ct->ptr.pp_double[i][0], 1, &xy->ptr.pp_double[j][0], 1, ae_v_len(0,nvars-1)); - } - return; - } - - /* - * k-means++ initialization - */ - if( initalgo==2 ) - { - - /* - * Prepare distances array. - * Select initial center at random. - */ - rvectorsetlengthatleast(&initbuf->ra0, npoints, _state); - for(i=0; i<=npoints-1; i++) - { - initbuf->ra0.ptr.p_double[i] = ae_maxrealnumber; - } - ptidx = hqrnduniformi(rs, npoints, _state); - ae_v_move(&ct->ptr.pp_double[0][0], 1, &xy->ptr.pp_double[ptidx][0], 1, ae_v_len(0,nvars-1)); - - /* - * For each newly added center repeat: - * * reevaluate distances from points to best centers - * * sample points with probability dependent on distance - * * add new center - */ - for(cidx=0; cidx<=k-2; cidx++) - { - - /* - * Reevaluate distances - */ - s = 0.0; - for(i=0; i<=npoints-1; i++) - { - v = 0.0; - for(j=0; j<=nvars-1; j++) - { - vv = xy->ptr.pp_double[i][j]-ct->ptr.pp_double[cidx][j]; - v = v+vv*vv; - } - if( ae_fp_less(v,initbuf->ra0.ptr.p_double[i]) ) - { - initbuf->ra0.ptr.p_double[i] = v; - } - s = s+initbuf->ra0.ptr.p_double[i]; - } - - /* - * If all distances are zero, it means that we can not find enough - * distinct points. In this case we just select non-distinct center - * at random and continue iterations. This issue will be handled - * later in the FixCenters() function. - */ - if( ae_fp_eq(s,0.0) ) - { - ptidx = hqrnduniformi(rs, npoints, _state); - ae_v_move(&ct->ptr.pp_double[cidx+1][0], 1, &xy->ptr.pp_double[ptidx][0], 1, ae_v_len(0,nvars-1)); - continue; - } - - /* - * Select point as center using its distance. - * We also handle situation when because of rounding errors - * no point was selected - in this case, last non-zero one - * will be used. - */ - v = hqrnduniformr(rs, _state); - vv = 0.0; - lastnz = -1; - ptidx = -1; - for(i=0; i<=npoints-1; i++) - { - if( ae_fp_eq(initbuf->ra0.ptr.p_double[i],0.0) ) - { - continue; - } - lastnz = i; - vv = vv+initbuf->ra0.ptr.p_double[i]; - if( ae_fp_less_eq(v,vv/s) ) - { - ptidx = i; - break; - } - } - ae_assert(lastnz>=0, "SelectInitialCenters: integrity error", _state); - if( ptidx<0 ) - { - ptidx = lastnz; - } - ae_v_move(&ct->ptr.pp_double[cidx+1][0], 1, &xy->ptr.pp_double[ptidx][0], 1, ae_v_len(0,nvars-1)); - } - return; - } - - /* - * "Fast-greedy" algorithm based on "Scalable k-means++". - * - * We perform several rounds, within each round we sample about 0.5*K points - * (not exactly 0.5*K) until we have 2*K points sampled. Before each round - * we calculate distances from dataset points to closest points sampled so far. - * We sample dataset points independently using distance xtimes 0.5*K divided by total - * as probability (similar to k-means++, but each point is sampled independently; - * after each round we have roughtly 0.5*K points added to sample). - * - * After sampling is done, we run "greedy" version of k-means++ on this subsample - * which selects most distant point on every round. - */ - if( initalgo==3 ) - { - - /* - * Prepare arrays. - * Select initial center at random, add it to "new" part of sample, - * which is stored at the beginning of the array - */ - samplesize = 2*k; - samplescale = 0.5*k; - rmatrixsetlengthatleast(&initbuf->rm0, samplesize, nvars, _state); - ptidx = hqrnduniformi(rs, npoints, _state); - ae_v_move(&initbuf->rm0.ptr.pp_double[0][0], 1, &xy->ptr.pp_double[ptidx][0], 1, ae_v_len(0,nvars-1)); - samplescntnew = 1; - samplescntall = 1; - rvectorsetlengthatleast(&initbuf->ra0, npoints, _state); - rvectorsetlengthatleast(&initbuf->ra1, npoints, _state); - ivectorsetlengthatleast(&initbuf->ia1, npoints, _state); - for(i=0; i<=npoints-1; i++) - { - initbuf->ra0.ptr.p_double[i] = ae_maxrealnumber; - } - - /* - * Repeat until samples count is 2*K - */ - while(samplescntallrm0, samplescntall-samplescntnew, samplescntall, &initbuf->ia1, &initbuf->ra1, updatepool, _state); - samplescntnew = 0; - - /* - * Merge new distances with old ones. - * Calculate sum of distances, if sum is exactly zero - fill sample - * by randomly selected points and terminate. - */ - s = 0.0; - for(i=0; i<=npoints-1; i++) - { - initbuf->ra0.ptr.p_double[i] = ae_minreal(initbuf->ra0.ptr.p_double[i], initbuf->ra1.ptr.p_double[i], _state); - s = s+initbuf->ra0.ptr.p_double[i]; - } - if( ae_fp_eq(s,0.0) ) - { - while(samplescntallrm0.ptr.pp_double[samplescntall][0], 1, &xy->ptr.pp_double[ptidx][0], 1, ae_v_len(0,nvars-1)); - inc(&samplescntall, _state); - inc(&samplescntnew, _state); - } - break; - } - - /* - * Sample points independently. - */ - for(i=0; i<=npoints-1; i++) - { - if( samplescntall==samplesize ) - { - break; - } - if( ae_fp_eq(initbuf->ra0.ptr.p_double[i],0.0) ) - { - continue; - } - if( ae_fp_less_eq(hqrnduniformr(rs, _state),samplescale*initbuf->ra0.ptr.p_double[i]/s) ) - { - ae_v_move(&initbuf->rm0.ptr.pp_double[samplescntall][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - inc(&samplescntall, _state); - inc(&samplescntnew, _state); - } - } - } - - /* - * Run greedy version of k-means on sampled points - */ - rvectorsetlengthatleast(&initbuf->ra0, samplescntall, _state); - for(i=0; i<=samplescntall-1; i++) - { - initbuf->ra0.ptr.p_double[i] = ae_maxrealnumber; - } - ptidx = hqrnduniformi(rs, samplescntall, _state); - ae_v_move(&ct->ptr.pp_double[0][0], 1, &initbuf->rm0.ptr.pp_double[ptidx][0], 1, ae_v_len(0,nvars-1)); - for(cidx=0; cidx<=k-2; cidx++) - { - - /* - * Reevaluate distances - */ - for(i=0; i<=samplescntall-1; i++) - { - v = 0.0; - for(j=0; j<=nvars-1; j++) - { - vv = initbuf->rm0.ptr.pp_double[i][j]-ct->ptr.pp_double[cidx][j]; - v = v+vv*vv; - } - if( ae_fp_less(v,initbuf->ra0.ptr.p_double[i]) ) - { - initbuf->ra0.ptr.p_double[i] = v; - } - } - - /* - * Select point as center in greedy manner - most distant - * point is selected. - */ - ptidx = 0; - for(i=0; i<=samplescntall-1; i++) - { - if( ae_fp_greater(initbuf->ra0.ptr.p_double[i],initbuf->ra0.ptr.p_double[ptidx]) ) - { - ptidx = i; - } - } - ae_v_move(&ct->ptr.pp_double[cidx+1][0], 1, &initbuf->rm0.ptr.pp_double[ptidx][0], 1, ae_v_len(0,nvars-1)); - } - return; - } - - /* - * Internal error - */ - ae_assert(ae_false, "SelectInitialCenters: internal error", _state); -} - - -/************************************************************************* -This function "fixes" centers, i.e. replaces ones which have no neighbor -points by new centers which have at least one neighbor. If it is impossible -to fix centers (not enough distinct points in the dataset), this function -returns False. - -INPUT PARAMETERS: - XY - dataset, array [0..NPoints-1,0..NVars-1]. - NPoints - points count, >=1 - NVars - number of variables, NVars>=1 - CT - centers - K - number of centers, K>=1 - InitBuf - internal buffer, possibly unitialized instance of - APBuffers. It is recommended to use this instance only - with SelectInitialCenters() and FixCenters() functions, - because these functions may allocate really large storage. - UpdatePool - shared pool seeded with instance of APBuffers structure - (seed instance can be unitialized). Used internally with - KMeansUpdateDistances() function. It is recommended - to use this pool ONLY with KMeansUpdateDistances() - function. - -OUTPUT PARAMETERS: - CT - set of K centers, one per row - -RESULT: - True on success, False on failure (impossible to create K independent clusters) - - -- ALGLIB -- - Copyright 21.01.2015 by Bochkanov Sergey -*************************************************************************/ -static ae_bool clustering_fixcenters(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - /* Real */ ae_matrix* ct, - ae_int_t k, - apbuffers* initbuf, - ae_shared_pool* updatepool, - ae_state *_state) -{ - ae_int_t fixiteration; - ae_int_t centertofix; - ae_int_t i; - ae_int_t j; - ae_int_t pdistant; - double ddistant; - double v; - ae_bool result; - - - ae_assert(npoints>=1, "FixCenters: internal error", _state); - ae_assert(nvars>=1, "FixCenters: internal error", _state); - ae_assert(k>=1, "FixCenters: internal error", _state); - - /* - * Calculate distances from points to best centers (RA0) - * and best center indexes (IA0) - */ - ivectorsetlengthatleast(&initbuf->ia0, npoints, _state); - rvectorsetlengthatleast(&initbuf->ra0, npoints, _state); - kmeansupdatedistances(xy, 0, npoints, nvars, ct, 0, k, &initbuf->ia0, &initbuf->ra0, updatepool, _state); - - /* - * Repeat loop: - * * find first center which has no corresponding point - * * set it to the most distant (from the rest of the centerset) point - * * recalculate distances, update IA0/RA0 - * * repeat - * - * Loop is repeated for at most 2*K iterations. It is stopped once we have - * no "empty" clusters. - */ - bvectorsetlengthatleast(&initbuf->ba0, k, _state); - for(fixiteration=0; fixiteration<=2*k; fixiteration++) - { - - /* - * Select center to fix (one which is not mentioned in IA0), - * terminate if there is no such center. - * BA0[] stores True for centers which have at least one point. - */ - for(i=0; i<=k-1; i++) - { - initbuf->ba0.ptr.p_bool[i] = ae_false; - } - for(i=0; i<=npoints-1; i++) - { - initbuf->ba0.ptr.p_bool[initbuf->ia0.ptr.p_int[i]] = ae_true; - } - centertofix = -1; - for(i=0; i<=k-1; i++) - { - if( !initbuf->ba0.ptr.p_bool[i] ) - { - centertofix = i; - break; - } - } - if( centertofix<0 ) - { - result = ae_true; - return result; - } - - /* - * Replace center to fix by the most distant point. - * Update IA0/RA0 - */ - pdistant = 0; - ddistant = initbuf->ra0.ptr.p_double[pdistant]; - for(i=0; i<=npoints-1; i++) - { - if( ae_fp_greater(initbuf->ra0.ptr.p_double[i],ddistant) ) - { - ddistant = initbuf->ra0.ptr.p_double[i]; - pdistant = i; - } - } - if( ae_fp_eq(ddistant,0.0) ) - { - break; - } - ae_v_move(&ct->ptr.pp_double[centertofix][0], 1, &xy->ptr.pp_double[pdistant][0], 1, ae_v_len(0,nvars-1)); - for(i=0; i<=npoints-1; i++) - { - v = 0.0; - for(j=0; j<=nvars-1; j++) - { - v = v+ae_sqr(xy->ptr.pp_double[i][j]-ct->ptr.pp_double[centertofix][j], _state); - } - if( ae_fp_less(v,initbuf->ra0.ptr.p_double[i]) ) - { - initbuf->ra0.ptr.p_double[i] = v; - initbuf->ia0.ptr.p_int[i] = centertofix; - } - } - } - result = ae_false; - return result; -} - - -/************************************************************************* -This function performs agglomerative hierarchical clustering using -precomputed distance matrix. Internal function, should not be called -directly. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - D - distance matrix, array[S.NFeatures,S.NFeatures] - Contents of the matrix is destroyed during - algorithm operation. - -OUTPUT PARAMETERS: - Rep - clustering results; see description of AHCReport - structure for more information. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -static void clustering_clusterizerrunahcinternal(clusterizerstate* s, - /* Real */ ae_matrix* d, - ahcreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - ae_int_t mergeidx; - ae_int_t c0; - ae_int_t c1; - ae_int_t s0; - ae_int_t s1; - ae_int_t ar; - ae_int_t br; - ae_int_t npoints; - ae_vector cidx; - ae_vector csizes; - ae_vector nnidx; - ae_matrix cinfo; - ae_int_t n0; - ae_int_t n1; - ae_int_t ni; - double d01; - - ae_frame_make(_state, &_frame_block); - memset(&cidx, 0, sizeof(cidx)); - memset(&csizes, 0, sizeof(csizes)); - memset(&nnidx, 0, sizeof(nnidx)); - memset(&cinfo, 0, sizeof(cinfo)); - ae_vector_init(&cidx, 0, DT_INT, _state, ae_true); - ae_vector_init(&csizes, 0, DT_INT, _state, ae_true); - ae_vector_init(&nnidx, 0, DT_INT, _state, ae_true); - ae_matrix_init(&cinfo, 0, 0, DT_INT, _state, ae_true); - - npoints = s->npoints; - - /* - * Fill Rep.NPoints, quick exit when NPoints<=1 - */ - rep->npoints = npoints; - if( npoints==0 ) - { - ae_vector_set_length(&rep->p, 0, _state); - ae_matrix_set_length(&rep->z, 0, 0, _state); - ae_matrix_set_length(&rep->pz, 0, 0, _state); - ae_matrix_set_length(&rep->pm, 0, 0, _state); - ae_vector_set_length(&rep->mergedist, 0, _state); - rep->terminationtype = 1; - ae_frame_leave(_state); - return; - } - if( npoints==1 ) - { - ae_vector_set_length(&rep->p, 1, _state); - ae_matrix_set_length(&rep->z, 0, 0, _state); - ae_matrix_set_length(&rep->pz, 0, 0, _state); - ae_matrix_set_length(&rep->pm, 0, 0, _state); - ae_vector_set_length(&rep->mergedist, 0, _state); - rep->p.ptr.p_int[0] = 0; - rep->terminationtype = 1; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&rep->z, npoints-1, 2, _state); - ae_vector_set_length(&rep->mergedist, npoints-1, _state); - rep->terminationtype = 1; - - /* - * Build list of nearest neighbors - */ - ae_vector_set_length(&nnidx, npoints, _state); - for(i=0; i<=npoints-1; i++) - { - - /* - * Calculate index of the nearest neighbor - */ - k = -1; - v = ae_maxrealnumber; - for(j=0; j<=npoints-1; j++) - { - if( j!=i&&ae_fp_less(d->ptr.pp_double[i][j],v) ) - { - k = j; - v = d->ptr.pp_double[i][j]; - } - } - ae_assert(ae_fp_less(v,ae_maxrealnumber), "ClusterizerRunAHC: internal error", _state); - nnidx.ptr.p_int[i] = k; - } - - /* - * For AHCAlgo=4 (Ward's method) replace distances by their squares times 0.5 - */ - if( s->ahcalgo==4 ) - { - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=npoints-1; j++) - { - d->ptr.pp_double[i][j] = 0.5*d->ptr.pp_double[i][j]*d->ptr.pp_double[i][j]; - } - } - } - - /* - * Distance matrix is built, perform merges. - * - * NOTE 1: CIdx is array[NPoints] which maps rows/columns of the - * distance matrix D to indexes of clusters. Values of CIdx - * from [0,NPoints) denote single-point clusters, and values - * from [NPoints,2*NPoints-1) denote ones obtained by merging - * smaller clusters. Negative calues correspond to absent clusters. - * - * Initially it contains [0...NPoints-1], after each merge - * one element of CIdx (one with index C0) is replaced by - * NPoints+MergeIdx, and another one with index C1 is - * rewritten by -1. - * - * NOTE 2: CSizes is array[NPoints] which stores sizes of clusters. - * - */ - ae_vector_set_length(&cidx, npoints, _state); - ae_vector_set_length(&csizes, npoints, _state); - for(i=0; i<=npoints-1; i++) - { - cidx.ptr.p_int[i] = i; - csizes.ptr.p_int[i] = 1; - } - for(mergeidx=0; mergeidx<=npoints-2; mergeidx++) - { - - /* - * Select pair of clusters (C0,C1) with CIdx[C0]=0 ) - { - if( ae_fp_less(d->ptr.pp_double[i][nnidx.ptr.p_int[i]],d01) ) - { - c0 = i; - c1 = nnidx.ptr.p_int[i]; - d01 = d->ptr.pp_double[i][nnidx.ptr.p_int[i]]; - } - } - } - ae_assert(ae_fp_less(d01,ae_maxrealnumber), "ClusterizerRunAHC: internal error", _state); - if( cidx.ptr.p_int[c0]>cidx.ptr.p_int[c1] ) - { - i = c1; - c1 = c0; - c0 = i; - } - - /* - * Fill one row of Rep.Z and one element of Rep.MergeDist - */ - rep->z.ptr.pp_int[mergeidx][0] = cidx.ptr.p_int[c0]; - rep->z.ptr.pp_int[mergeidx][1] = cidx.ptr.p_int[c1]; - rep->mergedist.ptr.p_double[mergeidx] = d01; - - /* - * Update distance matrix: - * * row/column C0 are updated by distances to the new cluster - * * row/column C1 are considered empty (we can fill them by zeros, - * but do not want to spend time - we just ignore them) - * - * NOTE: it is important to update distance matrix BEFORE CIdx/CSizes - * are updated. - */ - ae_assert((((s->ahcalgo==0||s->ahcalgo==1)||s->ahcalgo==2)||s->ahcalgo==3)||s->ahcalgo==4, "ClusterizerRunAHC: internal error", _state); - for(i=0; i<=npoints-1; i++) - { - if( i!=c0&&i!=c1 ) - { - n0 = csizes.ptr.p_int[c0]; - n1 = csizes.ptr.p_int[c1]; - ni = csizes.ptr.p_int[i]; - if( s->ahcalgo==0 ) - { - d->ptr.pp_double[i][c0] = ae_maxreal(d->ptr.pp_double[i][c0], d->ptr.pp_double[i][c1], _state); - } - if( s->ahcalgo==1 ) - { - d->ptr.pp_double[i][c0] = ae_minreal(d->ptr.pp_double[i][c0], d->ptr.pp_double[i][c1], _state); - } - if( s->ahcalgo==2 ) - { - d->ptr.pp_double[i][c0] = (csizes.ptr.p_int[c0]*d->ptr.pp_double[i][c0]+csizes.ptr.p_int[c1]*d->ptr.pp_double[i][c1])/(csizes.ptr.p_int[c0]+csizes.ptr.p_int[c1]); - } - if( s->ahcalgo==3 ) - { - d->ptr.pp_double[i][c0] = (d->ptr.pp_double[i][c0]+d->ptr.pp_double[i][c1])/2; - } - if( s->ahcalgo==4 ) - { - d->ptr.pp_double[i][c0] = ((n0+ni)*d->ptr.pp_double[i][c0]+(n1+ni)*d->ptr.pp_double[i][c1]-ni*d01)/(n0+n1+ni); - } - d->ptr.pp_double[c0][i] = d->ptr.pp_double[i][c0]; - } - } - - /* - * Update CIdx and CSizes - */ - cidx.ptr.p_int[c0] = npoints+mergeidx; - cidx.ptr.p_int[c1] = -1; - csizes.ptr.p_int[c0] = csizes.ptr.p_int[c0]+csizes.ptr.p_int[c1]; - csizes.ptr.p_int[c1] = 0; - - /* - * Update nearest neighbors array: - * * update nearest neighbors of everything except for C0/C1 - * * update neighbors of C0/C1 - */ - for(i=0; i<=npoints-1; i++) - { - if( (cidx.ptr.p_int[i]>=0&&i!=c0)&&(nnidx.ptr.p_int[i]==c0||nnidx.ptr.p_int[i]==c1) ) - { - - /* - * I-th cluster which is distinct from C0/C1 has former C0/C1 cluster as its nearest - * neighbor. We handle this issue depending on specific AHC algorithm being used. - */ - if( s->ahcalgo==1 ) - { - - /* - * Single linkage. Merging of two clusters together - * does NOT change distances between new cluster and - * other clusters. - * - * The only thing we have to do is to update nearest neighbor index - */ - nnidx.ptr.p_int[i] = c0; - } - else - { - - /* - * Something other than single linkage. We have to re-examine - * all the row to find nearest neighbor. - */ - k = -1; - v = ae_maxrealnumber; - for(j=0; j<=npoints-1; j++) - { - if( (cidx.ptr.p_int[j]>=0&&j!=i)&&ae_fp_less(d->ptr.pp_double[i][j],v) ) - { - k = j; - v = d->ptr.pp_double[i][j]; - } - } - ae_assert(ae_fp_less(v,ae_maxrealnumber)||mergeidx==npoints-2, "ClusterizerRunAHC: internal error", _state); - nnidx.ptr.p_int[i] = k; - } - } - } - k = -1; - v = ae_maxrealnumber; - for(j=0; j<=npoints-1; j++) - { - if( (cidx.ptr.p_int[j]>=0&&j!=c0)&&ae_fp_less(d->ptr.pp_double[c0][j],v) ) - { - k = j; - v = d->ptr.pp_double[c0][j]; - } - } - ae_assert(ae_fp_less(v,ae_maxrealnumber)||mergeidx==npoints-2, "ClusterizerRunAHC: internal error", _state); - nnidx.ptr.p_int[c0] = k; - } - - /* - * Calculate Rep.P and Rep.PM. - * - * In order to do that, we fill CInfo matrix - (2*NPoints-1)*3 matrix, - * with I-th row containing: - * * CInfo[I,0] - size of I-th cluster - * * CInfo[I,1] - beginning of I-th cluster - * * CInfo[I,2] - end of I-th cluster - * * CInfo[I,3] - height of I-th cluster - * - * We perform it as follows: - * * first NPoints clusters have unit size (CInfo[I,0]=1) and zero - * height (CInfo[I,3]=0) - * * we replay NPoints-1 merges from first to last and fill sizes of - * corresponding clusters (new size is a sum of sizes of clusters - * being merged) and height (new height is max(heights)+1). - * * now we ready to determine locations of clusters. Last cluster - * spans entire dataset, we know it. We replay merges from last to - * first, during each merge we already know location of the merge - * result, and we can position first cluster to the left part of - * the result, and second cluster to the right part. - */ - ae_vector_set_length(&rep->p, npoints, _state); - ae_matrix_set_length(&rep->pm, npoints-1, 6, _state); - ae_matrix_set_length(&cinfo, 2*npoints-1, 4, _state); - for(i=0; i<=npoints-1; i++) - { - cinfo.ptr.pp_int[i][0] = 1; - cinfo.ptr.pp_int[i][3] = 0; - } - for(i=0; i<=npoints-2; i++) - { - cinfo.ptr.pp_int[npoints+i][0] = cinfo.ptr.pp_int[rep->z.ptr.pp_int[i][0]][0]+cinfo.ptr.pp_int[rep->z.ptr.pp_int[i][1]][0]; - cinfo.ptr.pp_int[npoints+i][3] = ae_maxint(cinfo.ptr.pp_int[rep->z.ptr.pp_int[i][0]][3], cinfo.ptr.pp_int[rep->z.ptr.pp_int[i][1]][3], _state)+1; - } - cinfo.ptr.pp_int[2*npoints-2][1] = 0; - cinfo.ptr.pp_int[2*npoints-2][2] = npoints-1; - for(i=npoints-2; i>=0; i--) - { - - /* - * We merge C0 which spans [A0,B0] and C1 (spans [A1,B1]), - * with unknown A0, B0, A1, B1. However, we know that result - * is CR, which spans [AR,BR] with known AR/BR, and we know - * sizes of C0, C1, CR (denotes as S0, S1, SR). - */ - c0 = rep->z.ptr.pp_int[i][0]; - c1 = rep->z.ptr.pp_int[i][1]; - s0 = cinfo.ptr.pp_int[c0][0]; - s1 = cinfo.ptr.pp_int[c1][0]; - ar = cinfo.ptr.pp_int[npoints+i][1]; - br = cinfo.ptr.pp_int[npoints+i][2]; - cinfo.ptr.pp_int[c0][1] = ar; - cinfo.ptr.pp_int[c0][2] = ar+s0-1; - cinfo.ptr.pp_int[c1][1] = br-(s1-1); - cinfo.ptr.pp_int[c1][2] = br; - rep->pm.ptr.pp_int[i][0] = cinfo.ptr.pp_int[c0][1]; - rep->pm.ptr.pp_int[i][1] = cinfo.ptr.pp_int[c0][2]; - rep->pm.ptr.pp_int[i][2] = cinfo.ptr.pp_int[c1][1]; - rep->pm.ptr.pp_int[i][3] = cinfo.ptr.pp_int[c1][2]; - rep->pm.ptr.pp_int[i][4] = cinfo.ptr.pp_int[c0][3]; - rep->pm.ptr.pp_int[i][5] = cinfo.ptr.pp_int[c1][3]; - } - for(i=0; i<=npoints-1; i++) - { - ae_assert(cinfo.ptr.pp_int[i][1]==cinfo.ptr.pp_int[i][2], "Assertion failed", _state); - rep->p.ptr.p_int[i] = cinfo.ptr.pp_int[i][1]; - } - - /* - * Calculate Rep.PZ - */ - ae_matrix_set_length(&rep->pz, npoints-1, 2, _state); - for(i=0; i<=npoints-2; i++) - { - rep->pz.ptr.pp_int[i][0] = rep->z.ptr.pp_int[i][0]; - rep->pz.ptr.pp_int[i][1] = rep->z.ptr.pp_int[i][1]; - if( rep->pz.ptr.pp_int[i][0]pz.ptr.pp_int[i][0] = rep->p.ptr.p_int[rep->pz.ptr.pp_int[i][0]]; - } - if( rep->pz.ptr.pp_int[i][1]pz.ptr.pp_int[i][1] = rep->p.ptr.p_int[rep->pz.ptr.pp_int[i][1]]; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function recursively evaluates distance matrix for SOME (not all!) -distance types. - -INPUT PARAMETERS: - XY - array[?,NFeatures], dataset - NFeatures- number of features, >=1 - DistType- distance function: - * 0 Chebyshev distance (L-inf norm) - * 1 city block distance (L1 norm) - D - preallocated output matrix - I0,I1 - half interval of rows to calculate: [I0,I1) is processed - J0,J1 - half interval of cols to calculate: [J0,J1) is processed - -OUTPUT PARAMETERS: - D - array[NPoints,NPoints], distance matrix - upper triangle and main diagonal are initialized with - data. - -NOTE: intersection of [I0,I1) and [J0,J1) may completely lie in upper - triangle, only partially intersect with it, or have zero intersection. - In any case, only intersection of submatrix given by [I0,I1)*[J0,J1) - with upper triangle of the matrix is evaluated. - - Say, for 4x4 distance matrix A: - * [0,2)*[0,2) will result in evaluation of A00, A01, A11 - * [2,4)*[2,4) will result in evaluation of A22, A23, A32, A33 - * [2,4)*[0,2) will result in evaluation of empty set of elements - - - -- ALGLIB -- - Copyright 07.04.2013 by Bochkanov Sergey -*************************************************************************/ -static void clustering_evaluatedistancematrixrec(/* Real */ ae_matrix* xy, - ae_int_t nfeatures, - ae_int_t disttype, - /* Real */ ae_matrix* d, - ae_int_t i0, - ae_int_t i1, - ae_int_t j0, - ae_int_t j1, - ae_state *_state) -{ - double rcomplexity; - ae_int_t len0; - ae_int_t len1; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double vv; - - - ae_assert(disttype==0||disttype==1, "EvaluateDistanceMatrixRec: incorrect DistType", _state); - - /* - * Normalize J0/J1: - * * J0:=max(J0,I0) - we ignore lower triangle - * * J1:=max(J1,J0) - normalize J1 - */ - j0 = ae_maxint(j0, i0, _state); - j1 = ae_maxint(j1, j0, _state); - if( j1<=j0||i1<=i0 ) - { - return; - } - rcomplexity = clustering_complexitymultiplier*rmul3((double)(i1-i0), (double)(j1-j0), (double)(nfeatures), _state); - if( (i1-i0>2||j1-j0>2)&&ae_fp_greater_eq(rcomplexity,smpactivationlevel(_state)) ) - { - if( _trypexec_clustering_evaluatedistancematrixrec(xy,nfeatures,disttype,d,i0,i1,j0,j1, _state) ) - { - return; - } - } - - /* - * Try to process in parallel. Two condtions must hold in order to - * activate parallel processing: - * 1. I1-I0>2 or J1-J0>2 - * 2. (I1-I0)*(J1-J0)*NFeatures>=ParallelComplexity - * - * NOTE: all quantities are converted to reals in order to avoid - * integer overflow during multiplication - * - * NOTE: strict inequality in (1) is necessary to reduce task to 2x2 - * basecases. In future versions we will be able to handle such - * basecases more efficiently than 1x1 cases. - */ - if( ae_fp_greater_eq(rcomplexity,spawnlevel(_state))&&(i1-i0>2||j1-j0>2) ) - { - - /* - * Recursive division along largest of dimensions - */ - if( i1-i0>j1-j0 ) - { - splitlengtheven(i1-i0, &len0, &len1, _state); - clustering_evaluatedistancematrixrec(xy, nfeatures, disttype, d, i0, i0+len0, j0, j1, _state); - clustering_evaluatedistancematrixrec(xy, nfeatures, disttype, d, i0+len0, i1, j0, j1, _state); - } - else - { - splitlengtheven(j1-j0, &len0, &len1, _state); - clustering_evaluatedistancematrixrec(xy, nfeatures, disttype, d, i0, i1, j0, j0+len0, _state); - clustering_evaluatedistancematrixrec(xy, nfeatures, disttype, d, i0, i1, j0+len0, j1, _state); - } - return; - } - - /* - * Sequential processing - */ - for(i=i0; i<=i1-1; i++) - { - for(j=j0; j<=j1-1; j++) - { - if( j>=i ) - { - v = 0.0; - if( disttype==0 ) - { - for(k=0; k<=nfeatures-1; k++) - { - vv = xy->ptr.pp_double[i][k]-xy->ptr.pp_double[j][k]; - if( ae_fp_less(vv,(double)(0)) ) - { - vv = -vv; - } - if( ae_fp_greater(vv,v) ) - { - v = vv; - } - } - } - if( disttype==1 ) - { - for(k=0; k<=nfeatures-1; k++) - { - vv = xy->ptr.pp_double[i][k]-xy->ptr.pp_double[j][k]; - if( ae_fp_less(vv,(double)(0)) ) - { - vv = -vv; - } - v = v+vv; - } - } - d->ptr.pp_double[i][j] = v; - } - } - } -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_clustering_evaluatedistancematrixrec(/* Real */ ae_matrix* xy, - ae_int_t nfeatures, - ae_int_t disttype, - /* Real */ ae_matrix* d, - ae_int_t i0, - ae_int_t i1, - ae_int_t j0, - ae_int_t j1, - ae_state *_state) -{ - return ae_false; -} - - -void _kmeansbuffers_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - kmeansbuffers *p = (kmeansbuffers*)_p; - ae_touch_ptr((void*)p); - ae_matrix_init(&p->ct, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->ctbest, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xycbest, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->xycprev, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->d2, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->csizes, 0, DT_INT, _state, make_automatic); - _apbuffers_init(&p->initbuf, _state, make_automatic); - ae_shared_pool_init(&p->updatepool, _state, make_automatic); -} - - -void _kmeansbuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - kmeansbuffers *dst = (kmeansbuffers*)_dst; - kmeansbuffers *src = (kmeansbuffers*)_src; - ae_matrix_init_copy(&dst->ct, &src->ct, _state, make_automatic); - ae_matrix_init_copy(&dst->ctbest, &src->ctbest, _state, make_automatic); - ae_vector_init_copy(&dst->xycbest, &src->xycbest, _state, make_automatic); - ae_vector_init_copy(&dst->xycprev, &src->xycprev, _state, make_automatic); - ae_vector_init_copy(&dst->d2, &src->d2, _state, make_automatic); - ae_vector_init_copy(&dst->csizes, &src->csizes, _state, make_automatic); - _apbuffers_init_copy(&dst->initbuf, &src->initbuf, _state, make_automatic); - ae_shared_pool_init_copy(&dst->updatepool, &src->updatepool, _state, make_automatic); -} - - -void _kmeansbuffers_clear(void* _p) -{ - kmeansbuffers *p = (kmeansbuffers*)_p; - ae_touch_ptr((void*)p); - ae_matrix_clear(&p->ct); - ae_matrix_clear(&p->ctbest); - ae_vector_clear(&p->xycbest); - ae_vector_clear(&p->xycprev); - ae_vector_clear(&p->d2); - ae_vector_clear(&p->csizes); - _apbuffers_clear(&p->initbuf); - ae_shared_pool_clear(&p->updatepool); -} - - -void _kmeansbuffers_destroy(void* _p) -{ - kmeansbuffers *p = (kmeansbuffers*)_p; - ae_touch_ptr((void*)p); - ae_matrix_destroy(&p->ct); - ae_matrix_destroy(&p->ctbest); - ae_vector_destroy(&p->xycbest); - ae_vector_destroy(&p->xycprev); - ae_vector_destroy(&p->d2); - ae_vector_destroy(&p->csizes); - _apbuffers_destroy(&p->initbuf); - ae_shared_pool_destroy(&p->updatepool); -} - - -void _clusterizerstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - clusterizerstate *p = (clusterizerstate*)_p; - ae_touch_ptr((void*)p); - ae_matrix_init(&p->xy, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->d, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->tmpd, 0, 0, DT_REAL, _state, make_automatic); - _apbuffers_init(&p->distbuf, _state, make_automatic); - _kmeansbuffers_init(&p->kmeanstmp, _state, make_automatic); -} - - -void _clusterizerstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - clusterizerstate *dst = (clusterizerstate*)_dst; - clusterizerstate *src = (clusterizerstate*)_src; - dst->npoints = src->npoints; - dst->nfeatures = src->nfeatures; - dst->disttype = src->disttype; - ae_matrix_init_copy(&dst->xy, &src->xy, _state, make_automatic); - ae_matrix_init_copy(&dst->d, &src->d, _state, make_automatic); - dst->ahcalgo = src->ahcalgo; - dst->kmeansrestarts = src->kmeansrestarts; - dst->kmeansmaxits = src->kmeansmaxits; - dst->kmeansinitalgo = src->kmeansinitalgo; - dst->kmeansdbgnoits = src->kmeansdbgnoits; - dst->seed = src->seed; - ae_matrix_init_copy(&dst->tmpd, &src->tmpd, _state, make_automatic); - _apbuffers_init_copy(&dst->distbuf, &src->distbuf, _state, make_automatic); - _kmeansbuffers_init_copy(&dst->kmeanstmp, &src->kmeanstmp, _state, make_automatic); -} - - -void _clusterizerstate_clear(void* _p) -{ - clusterizerstate *p = (clusterizerstate*)_p; - ae_touch_ptr((void*)p); - ae_matrix_clear(&p->xy); - ae_matrix_clear(&p->d); - ae_matrix_clear(&p->tmpd); - _apbuffers_clear(&p->distbuf); - _kmeansbuffers_clear(&p->kmeanstmp); -} - - -void _clusterizerstate_destroy(void* _p) -{ - clusterizerstate *p = (clusterizerstate*)_p; - ae_touch_ptr((void*)p); - ae_matrix_destroy(&p->xy); - ae_matrix_destroy(&p->d); - ae_matrix_destroy(&p->tmpd); - _apbuffers_destroy(&p->distbuf); - _kmeansbuffers_destroy(&p->kmeanstmp); -} - - -void _ahcreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - ahcreport *p = (ahcreport*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->p, 0, DT_INT, _state, make_automatic); - ae_matrix_init(&p->z, 0, 0, DT_INT, _state, make_automatic); - ae_matrix_init(&p->pz, 0, 0, DT_INT, _state, make_automatic); - ae_matrix_init(&p->pm, 0, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->mergedist, 0, DT_REAL, _state, make_automatic); -} - - -void _ahcreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - ahcreport *dst = (ahcreport*)_dst; - ahcreport *src = (ahcreport*)_src; - dst->terminationtype = src->terminationtype; - dst->npoints = src->npoints; - ae_vector_init_copy(&dst->p, &src->p, _state, make_automatic); - ae_matrix_init_copy(&dst->z, &src->z, _state, make_automatic); - ae_matrix_init_copy(&dst->pz, &src->pz, _state, make_automatic); - ae_matrix_init_copy(&dst->pm, &src->pm, _state, make_automatic); - ae_vector_init_copy(&dst->mergedist, &src->mergedist, _state, make_automatic); -} - - -void _ahcreport_clear(void* _p) -{ - ahcreport *p = (ahcreport*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->p); - ae_matrix_clear(&p->z); - ae_matrix_clear(&p->pz); - ae_matrix_clear(&p->pm); - ae_vector_clear(&p->mergedist); -} - - -void _ahcreport_destroy(void* _p) -{ - ahcreport *p = (ahcreport*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->p); - ae_matrix_destroy(&p->z); - ae_matrix_destroy(&p->pz); - ae_matrix_destroy(&p->pm); - ae_vector_destroy(&p->mergedist); -} - - -void _kmeansreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - kmeansreport *p = (kmeansreport*)_p; - ae_touch_ptr((void*)p); - ae_matrix_init(&p->c, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cidx, 0, DT_INT, _state, make_automatic); -} - - -void _kmeansreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - kmeansreport *dst = (kmeansreport*)_dst; - kmeansreport *src = (kmeansreport*)_src; - dst->npoints = src->npoints; - dst->nfeatures = src->nfeatures; - dst->terminationtype = src->terminationtype; - dst->iterationscount = src->iterationscount; - dst->energy = src->energy; - dst->k = src->k; - ae_matrix_init_copy(&dst->c, &src->c, _state, make_automatic); - ae_vector_init_copy(&dst->cidx, &src->cidx, _state, make_automatic); -} - - -void _kmeansreport_clear(void* _p) -{ - kmeansreport *p = (kmeansreport*)_p; - ae_touch_ptr((void*)p); - ae_matrix_clear(&p->c); - ae_vector_clear(&p->cidx); -} - - -void _kmeansreport_destroy(void* _p) -{ - kmeansreport *p = (kmeansreport*)_p; - ae_touch_ptr((void*)p); - ae_matrix_destroy(&p->c); - ae_vector_destroy(&p->cidx); -} - - -#endif -#if defined(AE_COMPILE_DFOREST) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function creates buffer structure which can be used to perform -parallel inference requests. - -DF subpackage provides two sets of computing functions - ones which use -internal buffer of DF model (these functions are single-threaded because -they use same buffer, which can not shared between threads), and ones -which use external buffer. - -This function is used to initialize external buffer. - -INPUT PARAMETERS - Model - DF model which is associated with newly created buffer - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: buffer object should be used only with model which was used to - initialize buffer. Any attempt to use buffer with different - object is dangerous - you may get integrity check failure - (exception) because sizes of internal arrays do not fit to - dimensions of the model structure. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void dfcreatebuffer(decisionforest* model, - decisionforestbuffer* buf, - ae_state *_state) -{ - - _decisionforestbuffer_clear(buf); - - ae_vector_set_length(&buf->x, model->nvars, _state); - ae_vector_set_length(&buf->y, model->nclasses, _state); -} - - -/************************************************************************* -This subroutine creates DecisionForestBuilder object which is used to -train decision forests. - -By default, new builder stores empty dataset and some reasonable default -settings. At the very least, you should specify dataset prior to building -decision forest. You can also tweak settings of the forest construction -algorithm (recommended, although default setting should work well). - -Following actions are mandatory: -* calling dfbuildersetdataset() to specify dataset -* calling dfbuilderbuildrandomforest() to build decision forest using - current dataset and default settings - -Additionally, you may call: -* dfbuildersetrndvars() or dfbuildersetrndvarsratio() to specify number of - variables randomly chosen for each split -* dfbuildersetsubsampleratio() to specify fraction of the dataset randomly - subsampled to build each tree -* dfbuildersetseed() to control random seed chosen for tree construction - -INPUT PARAMETERS: - none - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildercreate(decisionforestbuilder* s, ae_state *_state) -{ - - _decisionforestbuilder_clear(s); - - - /* - * Empty dataset - */ - s->dstype = -1; - s->npoints = 0; - s->nvars = 0; - s->nclasses = 1; - - /* - * Default training settings - */ - s->rdfalgo = 0; - s->rdfratio = 0.5; - s->rdfvars = 0.0; - s->rdfglobalseed = 0; - s->rdfsplitstrength = 2; - s->rdfimportance = 0; - - /* - * Other fields - */ - s->rdfprogress = 0; - s->rdftotal = 1; -} - - -/************************************************************************* -This subroutine adds dense dataset to the internal storage of the builder -object. Specifying your dataset in the dense format means that the dense -version of the forest construction algorithm will be invoked. - -INPUT PARAMETERS: - S - decision forest builder object - XY - array[NPoints,NVars+1] (minimum size; actual size can - be larger, only leading part is used anyway), dataset: - * first NVars elements of each row store values of the - independent variables - * last column store class number (in 0...NClasses-1) - or real value of the dependent variable - NPoints - number of rows in the dataset, NPoints>=1 - NVars - number of independent variables, NVars>=1 - NClasses - indicates type of the problem being solved: - * NClasses>=2 means that classification problem is - solved (last column of the dataset stores class - number) - * NClasses=1 means that regression problem is solved - (last column of the dataset stores variable value) - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetdataset(decisionforestbuilder* s, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - - /* - * Check parameters - */ - ae_assert(npoints>=1, "dfbuildersetdataset: npoints<1", _state); - ae_assert(nvars>=1, "dfbuildersetdataset: nvars<1", _state); - ae_assert(nclasses>=1, "dfbuildersetdataset: nclasses<1", _state); - ae_assert(xy->rows>=npoints, "dfbuildersetdataset: rows(xy)cols>=nvars+1, "dfbuildersetdataset: cols(xy)1 ) - { - for(i=0; i<=npoints-1; i++) - { - j = ae_round(xy->ptr.pp_double[i][nvars], _state); - ae_assert(j>=0&&jdstype = 0; - s->npoints = npoints; - s->nvars = nvars; - s->nclasses = nclasses; - rvectorsetlengthatleast(&s->dsdata, npoints*nvars, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - s->dsdata.ptr.p_double[j*npoints+i] = xy->ptr.pp_double[i][j]; - } - } - if( nclasses>1 ) - { - ivectorsetlengthatleast(&s->dsival, npoints, _state); - for(i=0; i<=npoints-1; i++) - { - s->dsival.ptr.p_int[i] = ae_round(xy->ptr.pp_double[i][nvars], _state); - } - } - else - { - rvectorsetlengthatleast(&s->dsrval, npoints, _state); - for(i=0; i<=npoints-1; i++) - { - s->dsrval.ptr.p_double[i] = xy->ptr.pp_double[i][nvars]; - } - } -} - - -/************************************************************************* -This function sets number of variables (in [1,NVars] range) used by -decision forest construction algorithm. - -The default option is to use roughly sqrt(NVars) variables. - -INPUT PARAMETERS: - S - decision forest builder object - RndVars - number of randomly selected variables; values outside - of [1,NVars] range are silently clipped. - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetrndvars(decisionforestbuilder* s, - ae_int_t rndvars, - ae_state *_state) -{ - - - s->rdfvars = (double)(ae_maxint(rndvars, 1, _state)); -} - - -/************************************************************************* -This function sets number of variables used by decision forest construction -algorithm as a fraction of total variable count (0,1) range. - -The default option is to use roughly sqrt(NVars) variables. - -INPUT PARAMETERS: - S - decision forest builder object - F - round(NVars*F) variables are selected - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetrndvarsratio(decisionforestbuilder* s, - double f, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(f, _state), "dfbuildersetrndvarsratio: F is INF or NAN", _state); - s->rdfvars = -ae_maxreal(f, ae_machineepsilon, _state); -} - - -/************************************************************************* -This function tells decision forest builder to automatically choose number -of variables used by decision forest construction algorithm. Roughly -sqrt(NVars) variables will be used. - -INPUT PARAMETERS: - S - decision forest builder object - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetrndvarsauto(decisionforestbuilder* s, ae_state *_state) -{ - - - s->rdfvars = (double)(0); -} - - -/************************************************************************* -This function sets size of dataset subsample generated the decision forest -construction algorithm. Size is specified as a fraction of total dataset -size. - -The default option is to use 50% of the dataset for training, 50% for the -OOB estimates. You can decrease fraction F down to 10%, 1% or even below -in order to reduce overfitting. - -INPUT PARAMETERS: - S - decision forest builder object - F - fraction of the dataset to use, in (0,1] range. Values - outside of this range will be silently clipped. At - least one element is always selected for the training - set. - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetsubsampleratio(decisionforestbuilder* s, - double f, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(f, _state), "dfbuildersetrndvarsfraction: F is INF or NAN", _state); - s->rdfratio = ae_maxreal(f, ae_machineepsilon, _state); -} - - -/************************************************************************* -This function sets seed used by internal RNG for random subsampling and -random selection of variable subsets. - -By default random seed is used, i.e. every time you build decision forest, -we seed generator with new value obtained from system-wide RNG. Thus, -decision forest builder returns non-deterministic results. You can change -such behavior by specyfing fixed positive seed value. - -INPUT PARAMETERS: - S - decision forest builder object - SeedVal - seed value: - * positive values are used for seeding RNG with fixed - seed, i.e. subsequent runs on same data will return - same decision forests - * non-positive seed means that random seed is used - for every run of builder, i.e. subsequent runs on - same datasets will return slightly different - decision forests - -OUTPUT PARAMETERS: - S - decision forest builder, see - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetseed(decisionforestbuilder* s, - ae_int_t seedval, - ae_state *_state) -{ - - - s->rdfglobalseed = seedval; -} - - -/************************************************************************* -This function sets random decision forest construction algorithm. - -As for now, only one decision forest construction algorithm is supported - -a dense "baseline" RDF algorithm. - -INPUT PARAMETERS: - S - decision forest builder object - AlgoType - algorithm type: - * 0 = baseline dense RDF - -OUTPUT PARAMETERS: - S - decision forest builder, see - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetrdfalgo(decisionforestbuilder* s, - ae_int_t algotype, - ae_state *_state) -{ - - - ae_assert(algotype==0, "dfbuildersetrdfalgo: unexpected algotype", _state); - s->rdfalgo = algotype; -} - - -/************************************************************************* -This function sets split selection algorithm used by decision forest -classifier. You may choose several algorithms, with different speed and -quality of the results. - -INPUT PARAMETERS: - S - decision forest builder object - SplitStrength- split type: - * 0 = split at the random position, fastest one - * 1 = split at the middle of the range - * 2 = strong split at the best point of the range (default) - -OUTPUT PARAMETERS: - S - decision forest builder, see - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetrdfsplitstrength(decisionforestbuilder* s, - ae_int_t splitstrength, - ae_state *_state) -{ - - - ae_assert((splitstrength==0||splitstrength==1)||splitstrength==2, "dfbuildersetrdfsplitstrength: unexpected split type", _state); - s->rdfsplitstrength = splitstrength; -} - - -/************************************************************************* -This function tells decision forest construction algorithm to use -Gini impurity based variable importance estimation (also known as MDI). - -This version of importance estimation algorithm analyzes mean decrease in -impurity (MDI) on training sample during splits. The result is divided -by impurity at the root node in order to produce estimate in [0,1] range. - -Such estimates are fast to calculate and beautifully normalized (sum to -one) but have following downsides: -* They ALWAYS sum to 1.0, even if output is completely unpredictable. I.e. - MDI allows to order variables by importance, but does not tell us about - "absolute" importances of variables -* there exist some bias towards continuous and high-cardinality categorical - variables - -NOTE: informally speaking, MDA (permutation importance) rating answers the - question "what part of the model predictive power is ruined by - permuting k-th variable?" while MDI tells us "what part of the model - predictive power was achieved due to usage of k-th variable". - - Thus, MDA rates each variable independently at "0 to 1" scale while - MDI (and OOB-MDI too) tends to divide "unit amount of importance" - between several important variables. - - If all variables are equally important, they will have same - MDI/OOB-MDI rating, equal (for OOB-MDI: roughly equal) to 1/NVars. - However, roughly same picture will be produced for the "all - variables provide information no one is critical" situation and for - the "all variables are critical, drop any one, everything is ruined" - situation. - - Contrary to that, MDA will rate critical variable as ~1.0 important, - and important but non-critical variable will have less than unit - rating. - -NOTE: quite an often MDA and MDI return same results. It generally happens - on problems with low test set error (a few percents at most) and - large enough training set to avoid overfitting. - - The difference between MDA, MDI and OOB-MDI becomes important only - on "hard" tasks with high test set error and/or small training set. - -INPUT PARAMETERS: - S - decision forest builder object - -OUTPUT PARAMETERS: - S - decision forest builder object. Next call to the forest - construction function will produce: - * importance estimates in rep.varimportances field - * variable ranks in rep.topvars field - - -- ALGLIB -- - Copyright 29.07.2019 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetimportancetrngini(decisionforestbuilder* s, - ae_state *_state) -{ - - - s->rdfimportance = dforest_needtrngini; -} - - -/************************************************************************* -This function tells decision forest construction algorithm to use -out-of-bag version of Gini variable importance estimation (also known as -OOB-MDI). - -This version of importance estimation algorithm analyzes mean decrease in -impurity (MDI) on out-of-bag sample during splits. The result is divided -by impurity at the root node in order to produce estimate in [0,1] range. - -Such estimates are fast to calculate and resistant to overfitting issues -(thanks to the out-of-bag estimates used). However, OOB Gini rating has -following downsides: -* there exist some bias towards continuous and high-cardinality categorical - variables -* Gini rating allows us to order variables by importance, but it is hard - to define importance of the variable by itself. - -NOTE: informally speaking, MDA (permutation importance) rating answers the - question "what part of the model predictive power is ruined by - permuting k-th variable?" while MDI tells us "what part of the model - predictive power was achieved due to usage of k-th variable". - - Thus, MDA rates each variable independently at "0 to 1" scale while - MDI (and OOB-MDI too) tends to divide "unit amount of importance" - between several important variables. - - If all variables are equally important, they will have same - MDI/OOB-MDI rating, equal (for OOB-MDI: roughly equal) to 1/NVars. - However, roughly same picture will be produced for the "all - variables provide information no one is critical" situation and for - the "all variables are critical, drop any one, everything is ruined" - situation. - - Contrary to that, MDA will rate critical variable as ~1.0 important, - and important but non-critical variable will have less than unit - rating. - -NOTE: quite an often MDA and MDI return same results. It generally happens - on problems with low test set error (a few percents at most) and - large enough training set to avoid overfitting. - - The difference between MDA, MDI and OOB-MDI becomes important only - on "hard" tasks with high test set error and/or small training set. - -INPUT PARAMETERS: - S - decision forest builder object - -OUTPUT PARAMETERS: - S - decision forest builder object. Next call to the forest - construction function will produce: - * importance estimates in rep.varimportances field - * variable ranks in rep.topvars field - - -- ALGLIB -- - Copyright 29.07.2019 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetimportanceoobgini(decisionforestbuilder* s, - ae_state *_state) -{ - - - s->rdfimportance = dforest_needoobgini; -} - - -/************************************************************************* -This function tells decision forest construction algorithm to use -permutation variable importance estimator (also known as MDA). - -This version of importance estimation algorithm analyzes mean increase in -out-of-bag sum of squared residuals after random permutation of J-th -variable. The result is divided by error computed with all variables being -perturbed in order to produce R-squared-like estimate in [0,1] range. - -Such estimate is slower to calculate than Gini-based rating because it -needs multiple inference runs for each of variables being studied. - -ALGLIB uses parallelized and highly optimized algorithm which analyzes -path through the decision tree and allows to handle most perturbations -in O(1) time; nevertheless, requesting MDA importances may increase forest -construction time from 10% to 200% (or more, if you have thousands of -variables). - -However, MDA rating has following benefits over Gini-based ones: -* no bias towards specific variable types -* ability to directly evaluate "absolute" importance of some variable at - "0 to 1" scale (contrary to Gini-based rating, which returns comparative - importances). - -NOTE: informally speaking, MDA (permutation importance) rating answers the - question "what part of the model predictive power is ruined by - permuting k-th variable?" while MDI tells us "what part of the model - predictive power was achieved due to usage of k-th variable". - - Thus, MDA rates each variable independently at "0 to 1" scale while - MDI (and OOB-MDI too) tends to divide "unit amount of importance" - between several important variables. - - If all variables are equally important, they will have same - MDI/OOB-MDI rating, equal (for OOB-MDI: roughly equal) to 1/NVars. - However, roughly same picture will be produced for the "all - variables provide information no one is critical" situation and for - the "all variables are critical, drop any one, everything is ruined" - situation. - - Contrary to that, MDA will rate critical variable as ~1.0 important, - and important but non-critical variable will have less than unit - rating. - -NOTE: quite an often MDA and MDI return same results. It generally happens - on problems with low test set error (a few percents at most) and - large enough training set to avoid overfitting. - - The difference between MDA, MDI and OOB-MDI becomes important only - on "hard" tasks with high test set error and/or small training set. - -INPUT PARAMETERS: - S - decision forest builder object - -OUTPUT PARAMETERS: - S - decision forest builder object. Next call to the forest - construction function will produce: - * importance estimates in rep.varimportances field - * variable ranks in rep.topvars field - - -- ALGLIB -- - Copyright 29.07.2019 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetimportancepermutation(decisionforestbuilder* s, - ae_state *_state) -{ - - - s->rdfimportance = dforest_needpermutation; -} - - -/************************************************************************* -This function tells decision forest construction algorithm to skip -variable importance estimation. - -INPUT PARAMETERS: - S - decision forest builder object - -OUTPUT PARAMETERS: - S - decision forest builder object. Next call to the forest - construction function will result in forest being built - without variable importance estimation. - - -- ALGLIB -- - Copyright 29.07.2019 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetimportancenone(decisionforestbuilder* s, - ae_state *_state) -{ - - - s->rdfimportance = 0; -} - - -/************************************************************************* -This function is an alias for dfbuilderpeekprogress(), left in ALGLIB for -backward compatibility reasons. - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -double dfbuildergetprogress(decisionforestbuilder* s, ae_state *_state) -{ - double result; - - - result = dfbuilderpeekprogress(s, _state); - return result; -} - - -/************************************************************************* -This function is used to peek into decision forest construction process -from some other thread and get current progress indicator. - -It returns value in [0,1]. - -INPUT PARAMETERS: - S - decision forest builder object used to build forest - in some other thread - -RESULT: - progress value, in [0,1] - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -double dfbuilderpeekprogress(decisionforestbuilder* s, ae_state *_state) -{ - double result; - - - result = s->rdfprogress/ae_maxreal((double)(s->rdftotal), (double)(1), _state); - result = ae_maxreal(result, (double)(0), _state); - result = ae_minreal(result, (double)(1), _state); - return result; -} - - -/************************************************************************* -This subroutine builds decision forest according to current settings using -dataset internally stored in the builder object. Dense algorithm is used. - -NOTE: this function uses dense algorithm for forest construction - independently from the dataset format (dense or sparse). - -NOTE: forest built with this function is stored in-memory using 64-bit - data structures for offsets/indexes/split values. It is possible to - convert forest into more memory-efficient compressed binary - representation. Depending on the problem properties, 3.7x-5.7x - compression factors are possible. - - The downsides of compression are (a) slight reduction in the model - accuracy and (b) ~1.5x reduction in the inference speed (due to - increased complexity of the storage format). - - See comments on dfbinarycompression() for more info. - -Default settings are used by the algorithm; you can tweak them with the -help of the following functions: -* dfbuildersetrfactor() - to control a fraction of the dataset used for - subsampling -* dfbuildersetrandomvars() - to control number of variables randomly chosen - for decision rule creation - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - decision forest builder object - NTrees - NTrees>=1, number of trees to train - -OUTPUT PARAMETERS: - DF - decision forest. You can compress this forest to more - compact 16-bit representation with dfbinarycompression() - Rep - report, see below for information on its fields. - -=== report information produced by forest construction function ========== - -Decision forest training report includes following information: -* training set errors -* out-of-bag estimates of errors -* variable importance ratings - -Following fields are used to store information: -* training set errors are stored in rep.relclserror, rep.avgce, rep.rmserror, - rep.avgerror and rep.avgrelerror -* out-of-bag estimates of errors are stored in rep.oobrelclserror, rep.oobavgce, - rep.oobrmserror, rep.oobavgerror and rep.oobavgrelerror - -Variable importance reports, if requested by dfbuildersetimportancegini(), -dfbuildersetimportancetrngini() or dfbuildersetimportancepermutation() -call, are stored in: -* rep.varimportances field stores importance ratings -* rep.topvars stores variable indexes ordered from the most important to - less important ones - -You can find more information about report fields in: -* comments on dfreport structure -* comments on dfbuildersetimportancegini function -* comments on dfbuildersetimportancetrngini function -* comments on dfbuildersetimportancepermutation function - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuilderbuildrandomforest(decisionforestbuilder* s, - ae_int_t ntrees, - decisionforest* df, - dfreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t nvars; - ae_int_t nclasses; - ae_int_t npoints; - ae_int_t trnsize; - ae_int_t maxtreesize; - ae_int_t sessionseed; - dfworkbuf workbufseed; - dfvotebuf votebufseed; - dftreebuf treebufseed; - - ae_frame_make(_state, &_frame_block); - memset(&workbufseed, 0, sizeof(workbufseed)); - memset(&votebufseed, 0, sizeof(votebufseed)); - memset(&treebufseed, 0, sizeof(treebufseed)); - _decisionforest_clear(df); - _dfreport_clear(rep); - _dfworkbuf_init(&workbufseed, _state, ae_true); - _dfvotebuf_init(&votebufseed, _state, ae_true); - _dftreebuf_init(&treebufseed, _state, ae_true); - - ae_assert(ntrees>=1, "DFBuilderBuildRandomForest: ntrees<1", _state); - dforest_cleanreport(s, rep, _state); - npoints = s->npoints; - nvars = s->nvars; - nclasses = s->nclasses; - - /* - * Set up progress counter - */ - s->rdfprogress = 0; - s->rdftotal = ntrees*npoints; - if( s->rdfimportance==dforest_needpermutation ) - { - s->rdftotal = s->rdftotal+ntrees*npoints; - } - - /* - * Quick exit for empty dataset - */ - if( s->dstype==-1||npoints==0 ) - { - ae_assert(dforest_leafnodewidth==2, "DFBuilderBuildRandomForest: integrity check failed", _state); - df->forestformat = dforest_dfuncompressedv0; - df->nvars = s->nvars; - df->nclasses = s->nclasses; - df->ntrees = 1; - df->bufsize = 1+dforest_leafnodewidth; - ae_vector_set_length(&df->trees, 1+dforest_leafnodewidth, _state); - df->trees.ptr.p_double[0] = (double)(1+dforest_leafnodewidth); - df->trees.ptr.p_double[1] = (double)(-1); - df->trees.ptr.p_double[2] = 0.0; - dfcreatebuffer(df, &df->buffer, _state); - ae_frame_leave(_state); - return; - } - ae_assert(npoints>0, "DFBuilderBuildRandomForest: integrity check failed", _state); - - /* - * Analyze dataset statistics, perform preprocessing - */ - dforest_analyzeandpreprocessdataset(s, _state); - - /* - * Prepare "work", "vote" and "tree" pools and other settings - */ - trnsize = ae_round(npoints*s->rdfratio, _state); - trnsize = ae_maxint(trnsize, 1, _state); - trnsize = ae_minint(trnsize, npoints, _state); - maxtreesize = 1+dforest_innernodewidth*(trnsize-1)+dforest_leafnodewidth*trnsize; - ae_vector_set_length(&workbufseed.varpool, nvars, _state); - ae_vector_set_length(&workbufseed.trnset, trnsize, _state); - ae_vector_set_length(&workbufseed.oobset, npoints-trnsize, _state); - ae_vector_set_length(&workbufseed.tmp0i, npoints, _state); - ae_vector_set_length(&workbufseed.tmp1i, npoints, _state); - ae_vector_set_length(&workbufseed.tmp0r, npoints, _state); - ae_vector_set_length(&workbufseed.tmp1r, npoints, _state); - ae_vector_set_length(&workbufseed.tmp2r, npoints, _state); - ae_vector_set_length(&workbufseed.tmp3r, npoints, _state); - ae_vector_set_length(&workbufseed.trnlabelsi, npoints, _state); - ae_vector_set_length(&workbufseed.trnlabelsr, npoints, _state); - ae_vector_set_length(&workbufseed.ooblabelsi, npoints, _state); - ae_vector_set_length(&workbufseed.ooblabelsr, npoints, _state); - ae_vector_set_length(&workbufseed.curvals, npoints, _state); - ae_vector_set_length(&workbufseed.bestvals, npoints, _state); - ae_vector_set_length(&workbufseed.classpriors, nclasses, _state); - ae_vector_set_length(&workbufseed.classtotals0, nclasses, _state); - ae_vector_set_length(&workbufseed.classtotals1, nclasses, _state); - ae_vector_set_length(&workbufseed.classtotals01, 2*nclasses, _state); - ae_vector_set_length(&workbufseed.treebuf, maxtreesize, _state); - workbufseed.trnsize = trnsize; - workbufseed.oobsize = npoints-trnsize; - ae_vector_set_length(&votebufseed.trntotals, npoints*nclasses, _state); - ae_vector_set_length(&votebufseed.oobtotals, npoints*nclasses, _state); - for(i=0; i<=npoints*nclasses-1; i++) - { - votebufseed.trntotals.ptr.p_double[i] = (double)(0); - votebufseed.oobtotals.ptr.p_double[i] = (double)(0); - } - ae_vector_set_length(&votebufseed.trncounts, npoints, _state); - ae_vector_set_length(&votebufseed.oobcounts, npoints, _state); - for(i=0; i<=npoints-1; i++) - { - votebufseed.trncounts.ptr.p_int[i] = 0; - votebufseed.oobcounts.ptr.p_int[i] = 0; - } - ae_vector_set_length(&votebufseed.giniimportances, nvars, _state); - for(i=0; i<=nvars-1; i++) - { - votebufseed.giniimportances.ptr.p_double[i] = 0.0; - } - treebufseed.treeidx = -1; - ae_shared_pool_set_seed(&s->workpool, &workbufseed, sizeof(workbufseed), _dfworkbuf_init, _dfworkbuf_init_copy, _dfworkbuf_destroy, _state); - ae_shared_pool_set_seed(&s->votepool, &votebufseed, sizeof(votebufseed), _dfvotebuf_init, _dfvotebuf_init_copy, _dfvotebuf_destroy, _state); - ae_shared_pool_set_seed(&s->treepool, &treebufseed, sizeof(treebufseed), _dftreebuf_init, _dftreebuf_init_copy, _dftreebuf_destroy, _state); - ae_shared_pool_set_seed(&s->treefactory, &treebufseed, sizeof(treebufseed), _dftreebuf_init, _dftreebuf_init_copy, _dftreebuf_destroy, _state); - - /* - * Select session seed (individual trees are constructed using - * combination of session and local seeds). - */ - sessionseed = s->rdfglobalseed; - if( s->rdfglobalseed<=0 ) - { - sessionseed = ae_randominteger(30000, _state); - } - - /* - * Prepare In-and-Out-of-Bag matrix, if needed - */ - s->neediobmatrix = s->rdfimportance==dforest_needpermutation; - if( s->neediobmatrix ) - { - - /* - * Prepare default state of In-and-Out-of-Bag matrix - */ - bmatrixsetlengthatleast(&s->iobmatrix, ntrees, npoints, _state); - for(i=0; i<=ntrees-1; i++) - { - for(j=0; j<=npoints-1; j++) - { - s->iobmatrix.ptr.pp_bool[i][j] = ae_false; - } - } - } - - /* - * Build trees (in parallel, if possible) - */ - dforest_buildrandomtree(s, 0, ntrees, _state); - - /* - * Merge trees and output result - */ - dforest_mergetrees(s, df, _state); - - /* - * Process voting results and output training set and OOB errors. - * Finalize tree construction. - */ - dforest_processvotingresults(s, ntrees, &votebufseed, rep, _state); - dfcreatebuffer(df, &df->buffer, _state); - - /* - * Perform variable importance estimation - */ - dforest_estimatevariableimportance(s, sessionseed, df, ntrees, rep, _state); - - /* - * Update progress counter - */ - s->rdfprogress = s->rdftotal; - ae_frame_leave(_state); -} - - -/************************************************************************* -This function performs binary compression of the decision forest. - -Original decision forest produced by the forest builder is stored using -64-bit representation for all numbers - offsets, variable indexes, split -points. - -It is possible to significantly reduce model size by means of: -* using compressed dynamic encoding for integers (offsets and variable - indexes), which uses just 1 byte to store small ints (less than 128), - just 2 bytes for larger values (less than 128^2) and so on -* storing floating point numbers using 8-bit exponent and 16-bit mantissa - -As result, model needs significantly less memory (compression factor -depends on variable and class counts). In particular: -* NVars<128 and NClasses<128 result in 4.4x-5.7x model size reduction -* NVars<16384 and NClasses<128 result in 3.7x-4.5x model size reduction - -Such storage format performs lossless compression of all integers, but -compression of floating point values (split values) is lossy, with roughly -0.01% relative error introduced during rounding. Thus, we recommend you to -re-evaluate model accuracy after compression. - -Another downside of compression is ~1.5x reduction in the inference -speed due to necessity of dynamic decompression of the compressed model. - -INPUT PARAMETERS: - DF - decision forest built by forest builder - -OUTPUT PARAMETERS: - DF - replaced by compressed forest - -RESULT: - compression factor (in-RAM size of the compressed model vs than of the - uncompressed one), positive number larger than 1.0 - - -- ALGLIB -- - Copyright 22.07.2019 by Bochkanov Sergey -*************************************************************************/ -double dfbinarycompression(decisionforest* df, ae_state *_state) -{ - double result; - - - result = dforest_binarycompression(df, ae_false, _state); - return result; -} - - -/************************************************************************* -This is a 8-bit version of dfbinarycompression. -Not recommended for external use because it is too lossy. - - -- ALGLIB -- - Copyright 22.07.2019 by Bochkanov Sergey -*************************************************************************/ -double dfbinarycompression8(decisionforest* df, ae_state *_state) -{ - double result; - - - result = dforest_binarycompression(df, ae_true, _state); - return result; -} - - -/************************************************************************* -Inference using decision forest - -IMPORTANT: this function is thread-unsafe and may modify internal - structures of the model! You can not use same model object for - parallel evaluation from several threads. - - Use dftsprocess() with independent thread-local buffers if - you need thread-safe evaluation. - -INPUT PARAMETERS: - DF - decision forest model - X - input vector, array[NVars] - Y - possibly preallocated buffer, reallocated if too small - -OUTPUT PARAMETERS: - Y - result. Regression estimate when solving regression task, - vector of posterior probabilities for classification task. - -See also DFProcessI. - - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -void dfprocess(decisionforest* df, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t offs; - ae_int_t i; - double v; - ae_int_t treesize; - ae_bool processed; - - - - /* - * Process - * - * Although comments above warn you about thread-unsafety of this - * function, it is de facto thread-safe. However, thread safety is - * an accidental side-effect of the specific inference algorithm - * being used. It may disappear in the future versions of the DF - * models, so you should NOT rely on it. - */ - if( y->cntnclasses ) - { - ae_vector_set_length(y, df->nclasses, _state); - } - for(i=0; i<=df->nclasses-1; i++) - { - y->ptr.p_double[i] = (double)(0); - } - processed = ae_false; - if( df->forestformat==dforest_dfuncompressedv0 ) - { - - /* - * Process trees stored in uncompressed format - */ - offs = 0; - for(i=0; i<=df->ntrees-1; i++) - { - dforest_dfprocessinternaluncompressed(df, offs, offs+1, x, y, _state); - offs = offs+ae_round(df->trees.ptr.p_double[offs], _state); - } - processed = ae_true; - } - if( df->forestformat==dforest_dfcompressedv0 ) - { - - /* - * Process trees stored in compressed format - */ - offs = 0; - for(i=0; i<=df->ntrees-1; i++) - { - treesize = dforest_unstreamuint(&df->trees8, &offs, _state); - dforest_dfprocessinternalcompressed(df, offs, x, y, _state); - offs = offs+treesize; - } - processed = ae_true; - } - ae_assert(processed, "DFProcess: integrity check failed (unexpected format?)", _state); - v = (double)1/(double)df->ntrees; - ae_v_muld(&y->ptr.p_double[0], 1, ae_v_len(0,df->nclasses-1), v); -} - - -/************************************************************************* -'interactive' variant of DFProcess for languages like Python which support -constructs like "Y = DFProcessI(DF,X)" and interactive mode of interpreter - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - -IMPORTANT: this function is thread-unsafe and may modify internal - structures of the model! You can not use same model object for - parallel evaluation from several threads. - - Use dftsprocess() with independent thread-local buffers if - you need thread-safe evaluation. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void dfprocessi(decisionforest* df, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - - ae_vector_clear(y); - - dfprocess(df, x, y, _state); -} - - -/************************************************************************* -This function returns first component of the inferred vector (i.e. one -with index #0). - -It is a convenience wrapper for dfprocess() intended for either: -* 1-dimensional regression problems -* 2-class classification problems - -In the former case this function returns inference result as scalar, which -is definitely more convenient that wrapping it as vector. In the latter -case it returns probability of object belonging to class #0. - -If you call it for anything different from two cases above, it will work -as defined, i.e. return y[0], although it is of less use in such cases. - -IMPORTANT: this function is thread-unsafe and modifies internal structures - of the model! You can not use same model object for parallel - evaluation from several threads. - - Use dftsprocess() with independent thread-local buffers, if - you need thread-safe evaluation. - -INPUT PARAMETERS: - Model - DF model - X - input vector, array[0..NVars-1]. - -RESULT: - Y[0] - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double dfprocess0(decisionforest* model, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t i; - ae_int_t nvars; - double result; - - - nvars = model->nvars; - for(i=0; i<=nvars-1; i++) - { - model->buffer.x.ptr.p_double[i] = x->ptr.p_double[i]; - } - dfprocess(model, &model->buffer.x, &model->buffer.y, _state); - result = model->buffer.y.ptr.p_double[0]; - return result; -} - - -/************************************************************************* -This function returns most probable class number for an input X. It is -same as calling dfprocess(model,x,y), then determining i=argmax(y[i]) and -returning i. - -A class number in [0,NOut) range in returned for classification problems, --1 is returned when this function is called for regression problems. - -IMPORTANT: this function is thread-unsafe and modifies internal structures - of the model! You can not use same model object for parallel - evaluation from several threads. - - Use dftsprocess() with independent thread-local buffers, if - you need thread-safe evaluation. - -INPUT PARAMETERS: - Model - decision forest model - X - input vector, array[0..NVars-1]. - -RESULT: - class number, -1 for regression tasks - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -ae_int_t dfclassify(decisionforest* model, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t i; - ae_int_t nvars; - ae_int_t nout; - ae_int_t result; - - - if( model->nclasses<2 ) - { - result = -1; - return result; - } - nvars = model->nvars; - nout = model->nclasses; - for(i=0; i<=nvars-1; i++) - { - model->buffer.x.ptr.p_double[i] = x->ptr.p_double[i]; - } - dfprocess(model, &model->buffer.x, &model->buffer.y, _state); - result = 0; - for(i=1; i<=nout-1; i++) - { - if( model->buffer.y.ptr.p_double[i]>model->buffer.y.ptr.p_double[result] ) - { - result = i; - } - } - return result; -} - - -/************************************************************************* -Inference using decision forest - -Thread-safe procesing using external buffer for temporaries. - -This function is thread-safe (i.e . you can use same DF model from -multiple threads) as long as you use different buffer objects for different -threads. - -INPUT PARAMETERS: - DF - decision forest model - Buf - buffer object, must be allocated specifically for this - model with dfcreatebuffer(). - X - input vector, array[NVars] - Y - possibly preallocated buffer, reallocated if too small - -OUTPUT PARAMETERS: - Y - result. Regression estimate when solving regression task, - vector of posterior probabilities for classification task. - -See also DFProcessI. - - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -void dftsprocess(decisionforest* df, - decisionforestbuffer* buf, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - - - - /* - * Although docs warn you about thread-unsafety of the dfprocess() - * function, it is de facto thread-safe. However, thread safety is - * an accidental side-effect of the specific inference algorithm - * being used. It may disappear in the future versions of the DF - * models, so you should NOT rely on it. - */ - dfprocess(df, x, y, _state); -} - - -/************************************************************************* -Relative classification error on the test set - -INPUT PARAMETERS: - DF - decision forest model - XY - test set - NPoints - test set size - -RESULT: - percent of incorrectly classified cases. - Zero if model solves regression task. - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -double dfrelclserror(decisionforest* df, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - double result; - - - result = (double)dforest_dfclserror(df, xy, npoints, _state)/(double)npoints; - return result; -} - - -/************************************************************************* -Average cross-entropy (in bits per element) on the test set - -INPUT PARAMETERS: - DF - decision forest model - XY - test set - NPoints - test set size - -RESULT: - CrossEntropy/(NPoints*LN(2)). - Zero if model solves regression task. - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -double dfavgce(decisionforest* df, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector x; - ae_vector y; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t tmpi; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&x, df->nvars-1+1, _state); - ae_vector_set_length(&y, df->nclasses-1+1, _state); - result = (double)(0); - for(i=0; i<=npoints-1; i++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,df->nvars-1)); - dfprocess(df, &x, &y, _state); - if( df->nclasses>1 ) - { - - /* - * classification-specific code - */ - k = ae_round(xy->ptr.pp_double[i][df->nvars], _state); - tmpi = 0; - for(j=1; j<=df->nclasses-1; j++) - { - if( ae_fp_greater(y.ptr.p_double[j],y.ptr.p_double[tmpi]) ) - { - tmpi = j; - } - } - if( ae_fp_neq(y.ptr.p_double[k],(double)(0)) ) - { - result = result-ae_log(y.ptr.p_double[k], _state); - } - else - { - result = result-ae_log(ae_minrealnumber, _state); - } - } - } - result = result/npoints; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -RMS error on the test set - -INPUT PARAMETERS: - DF - decision forest model - XY - test set - NPoints - test set size - -RESULT: - root mean square error. - Its meaning for regression task is obvious. As for - classification task, RMS error means error when estimating posterior - probabilities. - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -double dfrmserror(decisionforest* df, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector x; - ae_vector y; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t tmpi; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&x, df->nvars-1+1, _state); - ae_vector_set_length(&y, df->nclasses-1+1, _state); - result = (double)(0); - for(i=0; i<=npoints-1; i++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,df->nvars-1)); - dfprocess(df, &x, &y, _state); - if( df->nclasses>1 ) - { - - /* - * classification-specific code - */ - k = ae_round(xy->ptr.pp_double[i][df->nvars], _state); - tmpi = 0; - for(j=1; j<=df->nclasses-1; j++) - { - if( ae_fp_greater(y.ptr.p_double[j],y.ptr.p_double[tmpi]) ) - { - tmpi = j; - } - } - for(j=0; j<=df->nclasses-1; j++) - { - if( j==k ) - { - result = result+ae_sqr(y.ptr.p_double[j]-1, _state); - } - else - { - result = result+ae_sqr(y.ptr.p_double[j], _state); - } - } - } - else - { - - /* - * regression-specific code - */ - result = result+ae_sqr(y.ptr.p_double[0]-xy->ptr.pp_double[i][df->nvars], _state); - } - } - result = ae_sqrt(result/(npoints*df->nclasses), _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Average error on the test set - -INPUT PARAMETERS: - DF - decision forest model - XY - test set - NPoints - test set size - -RESULT: - Its meaning for regression task is obvious. As for - classification task, it means average error when estimating posterior - probabilities. - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -double dfavgerror(decisionforest* df, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector x; - ae_vector y; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&x, df->nvars-1+1, _state); - ae_vector_set_length(&y, df->nclasses-1+1, _state); - result = (double)(0); - for(i=0; i<=npoints-1; i++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,df->nvars-1)); - dfprocess(df, &x, &y, _state); - if( df->nclasses>1 ) - { - - /* - * classification-specific code - */ - k = ae_round(xy->ptr.pp_double[i][df->nvars], _state); - for(j=0; j<=df->nclasses-1; j++) - { - if( j==k ) - { - result = result+ae_fabs(y.ptr.p_double[j]-1, _state); - } - else - { - result = result+ae_fabs(y.ptr.p_double[j], _state); - } - } - } - else - { - - /* - * regression-specific code - */ - result = result+ae_fabs(y.ptr.p_double[0]-xy->ptr.pp_double[i][df->nvars], _state); - } - } - result = result/(npoints*df->nclasses); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Average relative error on the test set - -INPUT PARAMETERS: - DF - decision forest model - XY - test set - NPoints - test set size - -RESULT: - Its meaning for regression task is obvious. As for - classification task, it means average relative error when estimating - posterior probability of belonging to the correct class. - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -double dfavgrelerror(decisionforest* df, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector x; - ae_vector y; - ae_int_t relcnt; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&x, df->nvars-1+1, _state); - ae_vector_set_length(&y, df->nclasses-1+1, _state); - result = (double)(0); - relcnt = 0; - for(i=0; i<=npoints-1; i++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,df->nvars-1)); - dfprocess(df, &x, &y, _state); - if( df->nclasses>1 ) - { - - /* - * classification-specific code - */ - k = ae_round(xy->ptr.pp_double[i][df->nvars], _state); - for(j=0; j<=df->nclasses-1; j++) - { - if( j==k ) - { - result = result+ae_fabs(y.ptr.p_double[j]-1, _state); - relcnt = relcnt+1; - } - } - } - else - { - - /* - * regression-specific code - */ - if( ae_fp_neq(xy->ptr.pp_double[i][df->nvars],(double)(0)) ) - { - result = result+ae_fabs((y.ptr.p_double[0]-xy->ptr.pp_double[i][df->nvars])/xy->ptr.pp_double[i][df->nvars], _state); - relcnt = relcnt+1; - } - } - } - if( relcnt>0 ) - { - result = result/relcnt; - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Copying of DecisionForest strucure - -INPUT PARAMETERS: - DF1 - original - -OUTPUT PARAMETERS: - DF2 - copy - - -- ALGLIB -- - Copyright 13.02.2009 by Bochkanov Sergey -*************************************************************************/ -void dfcopy(decisionforest* df1, decisionforest* df2, ae_state *_state) -{ - ae_int_t i; - ae_int_t bufsize; - - _decisionforest_clear(df2); - - if( df1->forestformat==dforest_dfuncompressedv0 ) - { - df2->forestformat = df1->forestformat; - df2->nvars = df1->nvars; - df2->nclasses = df1->nclasses; - df2->ntrees = df1->ntrees; - df2->bufsize = df1->bufsize; - ae_vector_set_length(&df2->trees, df1->bufsize, _state); - ae_v_move(&df2->trees.ptr.p_double[0], 1, &df1->trees.ptr.p_double[0], 1, ae_v_len(0,df1->bufsize-1)); - dfcreatebuffer(df2, &df2->buffer, _state); - return; - } - if( df1->forestformat==dforest_dfcompressedv0 ) - { - df2->forestformat = df1->forestformat; - df2->usemantissa8 = df1->usemantissa8; - df2->nvars = df1->nvars; - df2->nclasses = df1->nclasses; - df2->ntrees = df1->ntrees; - bufsize = df1->trees8.cnt; - ae_vector_set_length(&(df2->trees8), bufsize, _state); - for(i=0; i<=bufsize-1; i++) - { - df2->trees8.ptr.p_ubyte[i] = (unsigned char)(df1->trees8.ptr.p_ubyte[i]); - } - dfcreatebuffer(df2, &df2->buffer, _state); - return; - } - ae_assert(ae_false, "DFCopy: unexpected forest format", _state); -} - - -/************************************************************************* -Serializer: allocation - - -- ALGLIB -- - Copyright 14.03.2011 by Bochkanov Sergey -*************************************************************************/ -void dfalloc(ae_serializer* s, decisionforest* forest, ae_state *_state) -{ - - - if( forest->forestformat==dforest_dfuncompressedv0 ) - { - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - allocrealarray(s, &forest->trees, forest->bufsize, _state); - return; - } - if( forest->forestformat==dforest_dfcompressedv0 ) - { - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_byte_array(s, &forest->trees8); - return; - } - ae_assert(ae_false, "DFAlloc: unexpected forest format", _state); -} - - -/************************************************************************* -Serializer: serialization - - -- ALGLIB -- - Copyright 14.03.2011 by Bochkanov Sergey -*************************************************************************/ -void dfserialize(ae_serializer* s, - decisionforest* forest, - ae_state *_state) -{ - - - if( forest->forestformat==dforest_dfuncompressedv0 ) - { - ae_serializer_serialize_int(s, getrdfserializationcode(_state), _state); - ae_serializer_serialize_int(s, dforest_dfuncompressedv0, _state); - ae_serializer_serialize_int(s, forest->nvars, _state); - ae_serializer_serialize_int(s, forest->nclasses, _state); - ae_serializer_serialize_int(s, forest->ntrees, _state); - ae_serializer_serialize_int(s, forest->bufsize, _state); - serializerealarray(s, &forest->trees, forest->bufsize, _state); - return; - } - if( forest->forestformat==dforest_dfcompressedv0 ) - { - ae_serializer_serialize_int(s, getrdfserializationcode(_state), _state); - ae_serializer_serialize_int(s, forest->forestformat, _state); - ae_serializer_serialize_bool(s, forest->usemantissa8, _state); - ae_serializer_serialize_int(s, forest->nvars, _state); - ae_serializer_serialize_int(s, forest->nclasses, _state); - ae_serializer_serialize_int(s, forest->ntrees, _state); - ae_serializer_serialize_byte_array(s, &forest->trees8, _state); - return; - } - ae_assert(ae_false, "DFSerialize: unexpected forest format", _state); -} - - -/************************************************************************* -Serializer: unserialization - - -- ALGLIB -- - Copyright 14.03.2011 by Bochkanov Sergey -*************************************************************************/ -void dfunserialize(ae_serializer* s, - decisionforest* forest, - ae_state *_state) -{ - ae_int_t i0; - ae_int_t forestformat; - ae_bool processed; - - _decisionforest_clear(forest); - - - /* - * check correctness of header - */ - ae_serializer_unserialize_int(s, &i0, _state); - ae_assert(i0==getrdfserializationcode(_state), "DFUnserialize: stream header corrupted", _state); - - /* - * Read forest - */ - ae_serializer_unserialize_int(s, &forestformat, _state); - processed = ae_false; - if( forestformat==dforest_dfuncompressedv0 ) - { - - /* - * Unserialize data - */ - forest->forestformat = forestformat; - ae_serializer_unserialize_int(s, &forest->nvars, _state); - ae_serializer_unserialize_int(s, &forest->nclasses, _state); - ae_serializer_unserialize_int(s, &forest->ntrees, _state); - ae_serializer_unserialize_int(s, &forest->bufsize, _state); - unserializerealarray(s, &forest->trees, _state); - processed = ae_true; - } - if( forestformat==dforest_dfcompressedv0 ) - { - - /* - * Unserialize data - */ - forest->forestformat = forestformat; - ae_serializer_unserialize_bool(s, &forest->usemantissa8, _state); - ae_serializer_unserialize_int(s, &forest->nvars, _state); - ae_serializer_unserialize_int(s, &forest->nclasses, _state); - ae_serializer_unserialize_int(s, &forest->ntrees, _state); - ae_serializer_unserialize_byte_array(s, &forest->trees8, _state); - processed = ae_true; - } - ae_assert(processed, "DFUnserialize: unexpected forest format", _state); - - /* - * Prepare buffer - */ - dfcreatebuffer(forest, &forest->buffer, _state); -} - - -/************************************************************************* -This subroutine builds random decision forest. - ---------- DEPRECATED VERSION! USE DECISION FOREST BUILDER OBJECT --------- - - -- ALGLIB -- - Copyright 19.02.2009 by Bochkanov Sergey -*************************************************************************/ -void dfbuildrandomdecisionforest(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - ae_int_t ntrees, - double r, - ae_int_t* info, - decisionforest* df, - dfreport* rep, - ae_state *_state) -{ - ae_int_t samplesize; - - *info = 0; - _decisionforest_clear(df); - _dfreport_clear(rep); - - if( ae_fp_less_eq(r,(double)(0))||ae_fp_greater(r,(double)(1)) ) - { - *info = -1; - return; - } - samplesize = ae_maxint(ae_round(r*npoints, _state), 1, _state); - dfbuildinternal(xy, npoints, nvars, nclasses, ntrees, samplesize, ae_maxint(nvars/2, 1, _state), dforest_dfusestrongsplits+dforest_dfuseevs, info, df, rep, _state); -} - - -/************************************************************************* -This subroutine builds random decision forest. - ---------- DEPRECATED VERSION! USE DECISION FOREST BUILDER OBJECT --------- - - -- ALGLIB -- - Copyright 19.02.2009 by Bochkanov Sergey -*************************************************************************/ -void dfbuildrandomdecisionforestx1(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - ae_int_t ntrees, - ae_int_t nrndvars, - double r, - ae_int_t* info, - decisionforest* df, - dfreport* rep, - ae_state *_state) -{ - ae_int_t samplesize; - - *info = 0; - _decisionforest_clear(df); - _dfreport_clear(rep); - - if( ae_fp_less_eq(r,(double)(0))||ae_fp_greater(r,(double)(1)) ) - { - *info = -1; - return; - } - if( nrndvars<=0||nrndvars>nvars ) - { - *info = -1; - return; - } - samplesize = ae_maxint(ae_round(r*npoints, _state), 1, _state); - dfbuildinternal(xy, npoints, nvars, nclasses, ntrees, samplesize, nrndvars, dforest_dfusestrongsplits+dforest_dfuseevs, info, df, rep, _state); -} - - -void dfbuildinternal(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - ae_int_t ntrees, - ae_int_t samplesize, - ae_int_t nfeatures, - ae_int_t flags, - ae_int_t* info, - decisionforest* df, - dfreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - decisionforestbuilder builder; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&builder, 0, sizeof(builder)); - *info = 0; - _decisionforest_clear(df); - _dfreport_clear(rep); - _decisionforestbuilder_init(&builder, _state, ae_true); - - - /* - * Test for inputs - */ - if( (((((npoints<1||samplesize<1)||samplesize>npoints)||nvars<1)||nclasses<1)||ntrees<1)||nfeatures<1 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - if( nclasses>1 ) - { - for(i=0; i<=npoints-1; i++) - { - if( ae_round(xy->ptr.pp_double[i][nvars], _state)<0||ae_round(xy->ptr.pp_double[i][nvars], _state)>=nclasses ) - { - *info = -2; - ae_frame_leave(_state); - return; - } - } - } - *info = 1; - dfbuildercreate(&builder, _state); - dfbuildersetdataset(&builder, xy, npoints, nvars, nclasses, _state); - dfbuildersetsubsampleratio(&builder, (double)samplesize/(double)npoints, _state); - dfbuildersetrndvars(&builder, nfeatures, _state); - dfbuilderbuildrandomforest(&builder, ntrees, df, rep, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Builds a range of random trees [TreeIdx0,TreeIdx1) using decision forest -algorithm. Tree index is used to seed per-tree RNG. - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -static void dforest_buildrandomtree(decisionforestbuilder* s, - ae_int_t treeidx0, - ae_int_t treeidx1, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t treeidx; - ae_int_t i; - ae_int_t j; - ae_int_t npoints; - ae_int_t nvars; - ae_int_t nclasses; - hqrndstate rs; - dfworkbuf *workbuf; - ae_smart_ptr _workbuf; - dfvotebuf *votebuf; - ae_smart_ptr _votebuf; - dftreebuf *treebuf; - ae_smart_ptr _treebuf; - ae_int_t treesize; - ae_int_t varstoselect; - ae_int_t workingsetsize; - double meanloss; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - memset(&_workbuf, 0, sizeof(_workbuf)); - memset(&_votebuf, 0, sizeof(_votebuf)); - memset(&_treebuf, 0, sizeof(_treebuf)); - _hqrndstate_init(&rs, _state, ae_true); - ae_smart_ptr_init(&_workbuf, (void**)&workbuf, _state, ae_true); - ae_smart_ptr_init(&_votebuf, (void**)&votebuf, _state, ae_true); - ae_smart_ptr_init(&_treebuf, (void**)&treebuf, _state, ae_true); - - - /* - * Perform parallelization - */ - if( treeidx1-treeidx0>1 ) - { - if( _trypexec_dforest_buildrandomtree(s,treeidx0,treeidx1, _state) ) - { - ae_frame_leave(_state); - return; - } - j = (treeidx1-treeidx0)/2; - dforest_buildrandomtree(s, treeidx0, treeidx0+j, _state); - dforest_buildrandomtree(s, treeidx0+j, treeidx1, _state); - ae_frame_leave(_state); - return; - } - else - { - ae_assert(treeidx1-treeidx0==1, "RDF: integrity check failed", _state); - treeidx = treeidx0; - } - - /* - * Prepare - */ - npoints = s->npoints; - nvars = s->nvars; - nclasses = s->nclasses; - if( s->rdfglobalseed>0 ) - { - hqrndseed(s->rdfglobalseed, 1+treeidx, &rs, _state); - } - else - { - hqrndseed(ae_randominteger(30000, _state), 1+treeidx, &rs, _state); - } - - /* - * Retrieve buffers. - */ - ae_shared_pool_retrieve(&s->workpool, &_workbuf, _state); - ae_shared_pool_retrieve(&s->votepool, &_votebuf, _state); - - /* - * Prepare everything for tree construction. - */ - ae_assert(workbuf->trnsize>=1, "DForest: integrity check failed (34636)", _state); - ae_assert(workbuf->oobsize>=0, "DForest: integrity check failed (45745)", _state); - ae_assert(workbuf->trnsize+workbuf->oobsize==npoints, "DForest: integrity check failed (89415)", _state); - workingsetsize = -1; - workbuf->varpoolsize = 0; - for(i=0; i<=nvars-1; i++) - { - if( ae_fp_neq(s->dsmin.ptr.p_double[i],s->dsmax.ptr.p_double[i]) ) - { - workbuf->varpool.ptr.p_int[workbuf->varpoolsize] = i; - inc(&workbuf->varpoolsize, _state); - } - } - workingsetsize = workbuf->varpoolsize; - ae_assert(workingsetsize>=0, "DForest: integrity check failed (73f5)", _state); - for(i=0; i<=npoints-1; i++) - { - workbuf->tmp0i.ptr.p_int[i] = i; - } - for(i=0; i<=workbuf->trnsize-1; i++) - { - j = hqrnduniformi(&rs, npoints-i, _state); - swapelementsi(&workbuf->tmp0i, i, i+j, _state); - workbuf->trnset.ptr.p_int[i] = workbuf->tmp0i.ptr.p_int[i]; - if( nclasses>1 ) - { - workbuf->trnlabelsi.ptr.p_int[i] = s->dsival.ptr.p_int[workbuf->tmp0i.ptr.p_int[i]]; - } - else - { - workbuf->trnlabelsr.ptr.p_double[i] = s->dsrval.ptr.p_double[workbuf->tmp0i.ptr.p_int[i]]; - } - if( s->neediobmatrix ) - { - s->iobmatrix.ptr.pp_bool[treeidx][workbuf->trnset.ptr.p_int[i]] = ae_true; - } - } - for(i=0; i<=workbuf->oobsize-1; i++) - { - j = workbuf->tmp0i.ptr.p_int[workbuf->trnsize+i]; - workbuf->oobset.ptr.p_int[i] = j; - if( nclasses>1 ) - { - workbuf->ooblabelsi.ptr.p_int[i] = s->dsival.ptr.p_int[j]; - } - else - { - workbuf->ooblabelsr.ptr.p_double[i] = s->dsrval.ptr.p_double[j]; - } - } - varstoselect = ae_round(ae_sqrt((double)(nvars), _state), _state); - if( ae_fp_greater(s->rdfvars,(double)(0)) ) - { - varstoselect = ae_round(s->rdfvars, _state); - } - if( ae_fp_less(s->rdfvars,(double)(0)) ) - { - varstoselect = ae_round(-nvars*s->rdfvars, _state); - } - varstoselect = ae_maxint(varstoselect, 1, _state); - varstoselect = ae_minint(varstoselect, nvars, _state); - - /* - * Perform recurrent construction - */ - if( s->rdfimportance==dforest_needtrngini ) - { - meanloss = dforest_meannrms2(nclasses, &workbuf->trnlabelsi, &workbuf->trnlabelsr, 0, workbuf->trnsize, &workbuf->trnlabelsi, &workbuf->trnlabelsr, 0, workbuf->trnsize, &workbuf->tmpnrms2, _state); - } - else - { - meanloss = dforest_meannrms2(nclasses, &workbuf->trnlabelsi, &workbuf->trnlabelsr, 0, workbuf->trnsize, &workbuf->ooblabelsi, &workbuf->ooblabelsr, 0, workbuf->oobsize, &workbuf->tmpnrms2, _state); - } - treesize = 1; - dforest_buildrandomtreerec(s, workbuf, workingsetsize, varstoselect, &workbuf->treebuf, votebuf, &rs, 0, workbuf->trnsize, 0, workbuf->oobsize, meanloss, meanloss, &treesize, _state); - workbuf->treebuf.ptr.p_double[0] = (double)(treesize); - - /* - * Store tree - */ - ae_shared_pool_retrieve(&s->treefactory, &_treebuf, _state); - ae_vector_set_length(&treebuf->treebuf, treesize, _state); - for(i=0; i<=treesize-1; i++) - { - treebuf->treebuf.ptr.p_double[i] = workbuf->treebuf.ptr.p_double[i]; - } - treebuf->treeidx = treeidx; - ae_shared_pool_recycle(&s->treepool, &_treebuf, _state); - - /* - * Return other buffers to appropriate pools - */ - ae_shared_pool_recycle(&s->workpool, &_workbuf, _state); - ae_shared_pool_recycle(&s->votepool, &_votebuf, _state); - - /* - * Update progress indicator - */ - threadunsafeincby(&s->rdfprogress, npoints, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_dforest_buildrandomtree(decisionforestbuilder* s, - ae_int_t treeidx0, - ae_int_t treeidx1, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -Recurrent tree construction function using caller-allocated buffers and -caller-initialized RNG. - -Following iterms are processed: -* items [Idx0,Idx1) of WorkBuf.TrnSet -* items [OOBIdx0, OOBIdx1) of WorkBuf.OOBSet - -TreeSize on input must be 1 (header element of the tree), on output it -contains size of the tree. - -OOBLoss on input must contain value of MeanNRMS2(...) computed for entire -dataset. - -Variables from #0 to #WorkingSet-1 from WorkBuf.VarPool are used (for -block algorithm: blocks, not vars) - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -static void dforest_buildrandomtreerec(decisionforestbuilder* s, - dfworkbuf* workbuf, - ae_int_t workingset, - ae_int_t varstoselect, - /* Real */ ae_vector* treebuf, - dfvotebuf* votebuf, - hqrndstate* rs, - ae_int_t idx0, - ae_int_t idx1, - ae_int_t oobidx0, - ae_int_t oobidx1, - double meanloss, - double topmostmeanloss, - ae_int_t* treesize, - ae_state *_state) -{ - ae_int_t npoints; - ae_int_t nclasses; - ae_int_t i; - ae_int_t j; - ae_int_t j0; - double v; - ae_bool labelsaresame; - ae_int_t offs; - ae_int_t varbest; - double splitbest; - ae_int_t i1; - ae_int_t i2; - ae_int_t idxtrn; - ae_int_t idxoob; - double meanloss0; - double meanloss1; - - - ae_assert(s->dstype==0, "not supported skbdgfsi!", _state); - ae_assert(idx0npoints; - nclasses = s->nclasses; - - /* - * Check labels: all same or not? - */ - if( nclasses>1 ) - { - labelsaresame = ae_true; - for(i=0; i<=nclasses-1; i++) - { - workbuf->classpriors.ptr.p_int[i] = 0; - } - j0 = workbuf->trnlabelsi.ptr.p_int[idx0]; - for(i=idx0; i<=idx1-1; i++) - { - j = workbuf->trnlabelsi.ptr.p_int[i]; - workbuf->classpriors.ptr.p_int[j] = workbuf->classpriors.ptr.p_int[j]+1; - labelsaresame = labelsaresame&&j0==j; - } - } - else - { - labelsaresame = ae_false; - } - - /* - * Leaf node - */ - if( idx1-idx0==1||labelsaresame ) - { - if( nclasses==1 ) - { - dforest_outputleaf(s, workbuf, treebuf, votebuf, idx0, idx1, oobidx0, oobidx1, treesize, workbuf->trnlabelsr.ptr.p_double[idx0], _state); - } - else - { - dforest_outputleaf(s, workbuf, treebuf, votebuf, idx0, idx1, oobidx0, oobidx1, treesize, (double)(workbuf->trnlabelsi.ptr.p_int[idx0]), _state); - } - return; - } - - /* - * Non-leaf node. - * Investigate possible splits. - */ - ae_assert(s->rdfalgo==0, "BuildRandomForest: unexpected algo", _state); - dforest_choosecurrentsplitdense(s, workbuf, &workingset, varstoselect, rs, idx0, idx1, &varbest, &splitbest, _state); - if( varbest<0 ) - { - - /* - * No good split was found; make leaf (label is randomly chosen) and exit. - */ - if( nclasses>1 ) - { - v = (double)(workbuf->trnlabelsi.ptr.p_int[idx0+hqrnduniformi(rs, idx1-idx0, _state)]); - } - else - { - v = workbuf->trnlabelsr.ptr.p_double[idx0+hqrnduniformi(rs, idx1-idx0, _state)]; - } - dforest_outputleaf(s, workbuf, treebuf, votebuf, idx0, idx1, oobidx0, oobidx1, treesize, v, _state); - return; - } - - /* - * Good split WAS found, we can perform it: - * * first, we split training set - * * then, we similarly split OOB set - */ - ae_assert(s->dstype==0, "not supported 54bfdh", _state); - offs = npoints*varbest; - i1 = idx0; - i2 = idx1-1; - while(i1<=i2) - { - - /* - * Reorder indexes so that left partition is in [Idx0..I1), - * and right partition is in [I2+1..Idx1) - */ - if( workbuf->bestvals.ptr.p_double[i1]bestvals.ptr.p_double[i2]>=splitbest ) - { - i2 = i2-1; - continue; - } - j = workbuf->trnset.ptr.p_int[i1]; - workbuf->trnset.ptr.p_int[i1] = workbuf->trnset.ptr.p_int[i2]; - workbuf->trnset.ptr.p_int[i2] = j; - if( nclasses>1 ) - { - j = workbuf->trnlabelsi.ptr.p_int[i1]; - workbuf->trnlabelsi.ptr.p_int[i1] = workbuf->trnlabelsi.ptr.p_int[i2]; - workbuf->trnlabelsi.ptr.p_int[i2] = j; - } - else - { - v = workbuf->trnlabelsr.ptr.p_double[i1]; - workbuf->trnlabelsr.ptr.p_double[i1] = workbuf->trnlabelsr.ptr.p_double[i2]; - workbuf->trnlabelsr.ptr.p_double[i2] = v; - } - i1 = i1+1; - i2 = i2-1; - } - ae_assert(i1==i2+1, "BuildRandomTreeRec: integrity check failed (45rds3)", _state); - idxtrn = i1; - if( oobidx0dsdata.ptr.p_double[offs+workbuf->oobset.ptr.p_int[i1]]dsdata.ptr.p_double[offs+workbuf->oobset.ptr.p_int[i2]]>=splitbest ) - { - i2 = i2-1; - continue; - } - j = workbuf->oobset.ptr.p_int[i1]; - workbuf->oobset.ptr.p_int[i1] = workbuf->oobset.ptr.p_int[i2]; - workbuf->oobset.ptr.p_int[i2] = j; - if( nclasses>1 ) - { - j = workbuf->ooblabelsi.ptr.p_int[i1]; - workbuf->ooblabelsi.ptr.p_int[i1] = workbuf->ooblabelsi.ptr.p_int[i2]; - workbuf->ooblabelsi.ptr.p_int[i2] = j; - } - else - { - v = workbuf->ooblabelsr.ptr.p_double[i1]; - workbuf->ooblabelsr.ptr.p_double[i1] = workbuf->ooblabelsr.ptr.p_double[i2]; - workbuf->ooblabelsr.ptr.p_double[i2] = v; - } - i1 = i1+1; - i2 = i2-1; - } - ae_assert(i1==i2+1, "BuildRandomTreeRec: integrity check failed (643fs3)", _state); - idxoob = i1; - } - else - { - idxoob = oobidx0; - } - - /* - * Compute estimates of NRMS2 loss over TRN or OOB subsets, update Gini importances - */ - if( s->rdfimportance==dforest_needtrngini ) - { - meanloss0 = dforest_meannrms2(nclasses, &workbuf->trnlabelsi, &workbuf->trnlabelsr, idx0, idxtrn, &workbuf->trnlabelsi, &workbuf->trnlabelsr, idx0, idxtrn, &workbuf->tmpnrms2, _state); - meanloss1 = dforest_meannrms2(nclasses, &workbuf->trnlabelsi, &workbuf->trnlabelsr, idxtrn, idx1, &workbuf->trnlabelsi, &workbuf->trnlabelsr, idxtrn, idx1, &workbuf->tmpnrms2, _state); - } - else - { - meanloss0 = dforest_meannrms2(nclasses, &workbuf->trnlabelsi, &workbuf->trnlabelsr, idx0, idxtrn, &workbuf->ooblabelsi, &workbuf->ooblabelsr, oobidx0, idxoob, &workbuf->tmpnrms2, _state); - meanloss1 = dforest_meannrms2(nclasses, &workbuf->trnlabelsi, &workbuf->trnlabelsr, idxtrn, idx1, &workbuf->ooblabelsi, &workbuf->ooblabelsr, idxoob, oobidx1, &workbuf->tmpnrms2, _state); - } - votebuf->giniimportances.ptr.p_double[varbest] = votebuf->giniimportances.ptr.p_double[varbest]+(meanloss-(meanloss0+meanloss1))/(topmostmeanloss+1.0e-20); - - /* - * Generate tree node and subtrees (recursively) - */ - treebuf->ptr.p_double[*treesize] = (double)(varbest); - treebuf->ptr.p_double[*treesize+1] = splitbest; - i = *treesize; - *treesize = *treesize+dforest_innernodewidth; - dforest_buildrandomtreerec(s, workbuf, workingset, varstoselect, treebuf, votebuf, rs, idx0, idxtrn, oobidx0, idxoob, meanloss0, topmostmeanloss, treesize, _state); - treebuf->ptr.p_double[i+2] = (double)(*treesize); - dforest_buildrandomtreerec(s, workbuf, workingset, varstoselect, treebuf, votebuf, rs, idxtrn, idx1, idxoob, oobidx1, meanloss1, topmostmeanloss, treesize, _state); -} - - -/************************************************************************* -Estimates permutation variable importance ratings for a range of dataset -points. - -Initial call to this function should span entire range of the dataset, -[Idx0,Idx1)=[0,NPoints), because function performs initialization of some -internal structures when called with these arguments. - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -static void dforest_estimatevariableimportance(decisionforestbuilder* s, - ae_int_t sessionseed, - decisionforest* df, - ae_int_t ntrees, - dfreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t npoints; - ae_int_t nvars; - ae_int_t nclasses; - ae_int_t nperm; - ae_int_t i; - ae_int_t j; - ae_int_t k; - dfvotebuf *vote; - ae_smart_ptr _vote; - ae_vector tmpr0; - ae_vector tmpr1; - ae_vector tmpi0; - ae_vector losses; - dfpermimpbuf permseed; - dfpermimpbuf *permresult; - ae_smart_ptr _permresult; - ae_shared_pool permpool; - double nopermloss; - double totalpermloss; - hqrndstate varimprs; - - ae_frame_make(_state, &_frame_block); - memset(&_vote, 0, sizeof(_vote)); - memset(&tmpr0, 0, sizeof(tmpr0)); - memset(&tmpr1, 0, sizeof(tmpr1)); - memset(&tmpi0, 0, sizeof(tmpi0)); - memset(&losses, 0, sizeof(losses)); - memset(&permseed, 0, sizeof(permseed)); - memset(&_permresult, 0, sizeof(_permresult)); - memset(&permpool, 0, sizeof(permpool)); - memset(&varimprs, 0, sizeof(varimprs)); - ae_smart_ptr_init(&_vote, (void**)&vote, _state, ae_true); - ae_vector_init(&tmpr0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpr1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpi0, 0, DT_INT, _state, ae_true); - ae_vector_init(&losses, 0, DT_REAL, _state, ae_true); - _dfpermimpbuf_init(&permseed, _state, ae_true); - ae_smart_ptr_init(&_permresult, (void**)&permresult, _state, ae_true); - ae_shared_pool_init(&permpool, _state, ae_true); - _hqrndstate_init(&varimprs, _state, ae_true); - - npoints = s->npoints; - nvars = s->nvars; - nclasses = s->nclasses; - - /* - * No importance rating - */ - if( s->rdfimportance==0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Gini importance - */ - if( s->rdfimportance==dforest_needtrngini||s->rdfimportance==dforest_needoobgini ) - { - - /* - * Merge OOB Gini importances computed during tree generation - */ - ae_shared_pool_first_recycled(&s->votepool, &_vote, _state); - while(vote!=NULL) - { - for(i=0; i<=nvars-1; i++) - { - rep->varimportances.ptr.p_double[i] = rep->varimportances.ptr.p_double[i]+vote->giniimportances.ptr.p_double[i]/ntrees; - } - ae_shared_pool_next_recycled(&s->votepool, &_vote, _state); - } - for(i=0; i<=nvars-1; i++) - { - rep->varimportances.ptr.p_double[i] = boundval(rep->varimportances.ptr.p_double[i], (double)(0), (double)(1), _state); - } - - /* - * Compute topvars[] array - */ - ae_vector_set_length(&tmpr0, nvars, _state); - for(j=0; j<=nvars-1; j++) - { - tmpr0.ptr.p_double[j] = -rep->varimportances.ptr.p_double[j]; - rep->topvars.ptr.p_int[j] = j; - } - tagsortfasti(&tmpr0, &rep->topvars, &tmpr1, &tmpi0, nvars, _state); - ae_frame_leave(_state); - return; - } - - /* - * Permutation importance - */ - if( s->rdfimportance==dforest_needpermutation ) - { - ae_assert(df->forestformat==dforest_dfuncompressedv0, "EstimateVariableImportance: integrity check failed (ff)", _state); - ae_assert(s->iobmatrix.rows>=ntrees&&s->iobmatrix.cols>=npoints, "EstimateVariableImportance: integrity check failed (IOB)", _state); - - /* - * Generate packed representation of the shuffle which is applied to all variables - * - * Ideally we want to apply different permutations to different variables, - * i.e. we have to generate and store NPoints*NVars random numbers. - * However due to performance and memory restrictions we prefer to use compact - * representation: - * * we store one "reference" permutation P_ref in VarImpShuffle2[0:NPoints-1] - * * a permutation P_j applied to variable J is obtained by circularly shifting - * elements in P_ref by VarImpShuffle2[NPoints+J] - */ - hqrndseed(sessionseed, 1117, &varimprs, _state); - ivectorsetlengthatleast(&s->varimpshuffle2, npoints+nvars, _state); - for(i=0; i<=npoints-1; i++) - { - s->varimpshuffle2.ptr.p_int[i] = i; - } - for(i=0; i<=npoints-2; i++) - { - j = i+hqrnduniformi(&varimprs, npoints-i, _state); - k = s->varimpshuffle2.ptr.p_int[i]; - s->varimpshuffle2.ptr.p_int[i] = s->varimpshuffle2.ptr.p_int[j]; - s->varimpshuffle2.ptr.p_int[j] = k; - } - for(i=0; i<=nvars-1; i++) - { - s->varimpshuffle2.ptr.p_int[npoints+i] = hqrnduniformi(&varimprs, npoints, _state); - } - - /* - * Prepare buffer object, seed pool - */ - nperm = nvars+2; - ae_vector_set_length(&permseed.losses, nperm, _state); - for(j=0; j<=nperm-1; j++) - { - permseed.losses.ptr.p_double[j] = (double)(0); - } - ae_vector_set_length(&permseed.yv, nperm*nclasses, _state); - ae_vector_set_length(&permseed.xraw, nvars, _state); - ae_vector_set_length(&permseed.xdist, nvars, _state); - ae_vector_set_length(&permseed.xcur, nvars, _state); - ae_vector_set_length(&permseed.targety, nclasses, _state); - ae_vector_set_length(&permseed.startnodes, nvars, _state); - ae_vector_set_length(&permseed.y, nclasses, _state); - ae_shared_pool_set_seed(&permpool, &permseed, sizeof(permseed), _dfpermimpbuf_init, _dfpermimpbuf_init_copy, _dfpermimpbuf_destroy, _state); - - /* - * Recursively split subset and process (using parallel capabilities, if possible) - */ - dforest_estimatepermutationimportances(s, df, ntrees, &permpool, 0, npoints, _state); - - /* - * Merge results - */ - ae_vector_set_length(&losses, nperm, _state); - for(j=0; j<=nperm-1; j++) - { - losses.ptr.p_double[j] = 1.0e-20; - } - ae_shared_pool_first_recycled(&permpool, &_permresult, _state); - while(permresult!=NULL) - { - for(j=0; j<=nperm-1; j++) - { - losses.ptr.p_double[j] = losses.ptr.p_double[j]+permresult->losses.ptr.p_double[j]; - } - ae_shared_pool_next_recycled(&permpool, &_permresult, _state); - } - - /* - * Compute importances - */ - nopermloss = losses.ptr.p_double[nvars+1]; - totalpermloss = losses.ptr.p_double[nvars]; - for(i=0; i<=nvars-1; i++) - { - rep->varimportances.ptr.p_double[i] = 1-nopermloss/totalpermloss-(1-losses.ptr.p_double[i]/totalpermloss); - rep->varimportances.ptr.p_double[i] = boundval(rep->varimportances.ptr.p_double[i], (double)(0), (double)(1), _state); - } - - /* - * Compute topvars[] array - */ - ae_vector_set_length(&tmpr0, nvars, _state); - for(j=0; j<=nvars-1; j++) - { - tmpr0.ptr.p_double[j] = -rep->varimportances.ptr.p_double[j]; - rep->topvars.ptr.p_int[j] = j; - } - tagsortfasti(&tmpr0, &rep->topvars, &tmpr1, &tmpi0, nvars, _state); - ae_frame_leave(_state); - return; - } - ae_assert(ae_false, "EstimateVariableImportance: unexpected importance type", _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_dforest_estimatevariableimportance(decisionforestbuilder* s, - ae_int_t sessionseed, - decisionforest* df, - ae_int_t ntrees, - dfreport* rep, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -Estimates permutation variable importance ratings for a range of dataset -points. - -Initial call to this function should span entire range of the dataset, -[Idx0,Idx1)=[0,NPoints), because function performs initialization of some -internal structures when called with these arguments. - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -static void dforest_estimatepermutationimportances(decisionforestbuilder* s, - decisionforest* df, - ae_int_t ntrees, - ae_shared_pool* permpool, - ae_int_t idx0, - ae_int_t idx1, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t npoints; - ae_int_t nvars; - ae_int_t nclasses; - ae_int_t nperm; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - ae_int_t treeroot; - ae_int_t nodeoffs; - double prediction; - ae_int_t varidx; - ae_int_t oobcounts; - ae_int_t srcidx; - dfpermimpbuf *permimpbuf; - ae_smart_ptr _permimpbuf; - - ae_frame_make(_state, &_frame_block); - memset(&_permimpbuf, 0, sizeof(_permimpbuf)); - ae_smart_ptr_init(&_permimpbuf, (void**)&permimpbuf, _state, ae_true); - - npoints = s->npoints; - nvars = s->nvars; - nclasses = s->nclasses; - ae_assert(df->forestformat==dforest_dfuncompressedv0, "EstimateVariableImportance: integrity check failed (ff)", _state); - ae_assert((idx0>=0&&idx0<=idx1)&&idx1<=npoints, "EstimateVariableImportance: integrity check failed (idx)", _state); - ae_assert(s->iobmatrix.rows>=ntrees&&s->iobmatrix.cols>=npoints, "EstimateVariableImportance: integrity check failed (IOB)", _state); - - /* - * Perform parallelization if batch is too large - */ - if( idx1-idx0>dforest_permutationimportancebatchsize ) - { - if( _trypexec_dforest_estimatepermutationimportances(s,df,ntrees,permpool,idx0,idx1, _state) ) - { - ae_frame_leave(_state); - return; - } - j = (idx1-idx0)/2; - dforest_estimatepermutationimportances(s, df, ntrees, permpool, idx0, idx0+j, _state); - dforest_estimatepermutationimportances(s, df, ntrees, permpool, idx0+j, idx1, _state); - ae_frame_leave(_state); - return; - } - - /* - * Retrieve buffer object from pool - */ - ae_shared_pool_retrieve(permpool, &_permimpbuf, _state); - - /* - * Process range of points [idx0,idx1) - */ - nperm = nvars+2; - for(i=idx0; i<=idx1-1; i++) - { - ae_assert(s->dstype==0, "EstimateVariableImportance: unexpected dataset type", _state); - for(j=0; j<=nvars-1; j++) - { - permimpbuf->xraw.ptr.p_double[j] = s->dsdata.ptr.p_double[j*npoints+i]; - srcidx = s->varimpshuffle2.ptr.p_int[(i+s->varimpshuffle2.ptr.p_int[npoints+j])%npoints]; - permimpbuf->xdist.ptr.p_double[j] = s->dsdata.ptr.p_double[j*npoints+srcidx]; - } - if( nclasses>1 ) - { - for(j=0; j<=nclasses-1; j++) - { - permimpbuf->targety.ptr.p_double[j] = (double)(0); - } - permimpbuf->targety.ptr.p_double[s->dsival.ptr.p_int[i]] = (double)(1); - } - else - { - permimpbuf->targety.ptr.p_double[0] = s->dsrval.ptr.p_double[i]; - } - - /* - * Process all trees, for each tree compute NPerm losses corresponding - * to various permutations of variable values - */ - for(j=0; j<=nperm*nclasses-1; j++) - { - permimpbuf->yv.ptr.p_double[j] = (double)(0); - } - oobcounts = 0; - treeroot = 0; - for(k=0; k<=ntrees-1; k++) - { - if( !s->iobmatrix.ptr.pp_bool[k][i] ) - { - - /* - * Process original (unperturbed) point and analyze path from the - * tree root to the final leaf. Output prediction to RawPrediction. - * - * Additionally, for each variable in [0,NVars-1] save offset of - * the first split on this variable. It allows us to quickly compute - * tree decision when perturbation does not change decision path. - */ - ae_assert(df->forestformat==dforest_dfuncompressedv0, "EstimateVariableImportance: integrity check failed (ff)", _state); - nodeoffs = treeroot+1; - for(j=0; j<=nvars-1; j++) - { - permimpbuf->startnodes.ptr.p_int[j] = -1; - } - prediction = (double)(0); - for(;;) - { - if( ae_fp_eq(df->trees.ptr.p_double[nodeoffs],(double)(-1)) ) - { - prediction = df->trees.ptr.p_double[nodeoffs+1]; - break; - } - j = ae_round(df->trees.ptr.p_double[nodeoffs], _state); - if( permimpbuf->startnodes.ptr.p_int[j]<0 ) - { - permimpbuf->startnodes.ptr.p_int[j] = nodeoffs; - } - if( permimpbuf->xraw.ptr.p_double[j]trees.ptr.p_double[nodeoffs+1] ) - { - nodeoffs = nodeoffs+dforest_innernodewidth; - } - else - { - nodeoffs = treeroot+ae_round(df->trees.ptr.p_double[nodeoffs+2], _state); - } - } - - /* - * Save loss for unperturbed point - */ - varidx = nvars+1; - if( nclasses>1 ) - { - j = ae_round(prediction, _state); - permimpbuf->yv.ptr.p_double[varidx*nclasses+j] = permimpbuf->yv.ptr.p_double[varidx*nclasses+j]+1; - } - else - { - permimpbuf->yv.ptr.p_double[varidx] = permimpbuf->yv.ptr.p_double[varidx]+prediction; - } - - /* - * Save loss for all variables being perturbed (XDist). - * This loss is used as a reference loss when we compute R-squared. - */ - varidx = nvars; - for(j=0; j<=nclasses-1; j++) - { - permimpbuf->y.ptr.p_double[j] = (double)(0); - } - dforest_dfprocessinternaluncompressed(df, treeroot, treeroot+1, &permimpbuf->xdist, &permimpbuf->y, _state); - for(j=0; j<=nclasses-1; j++) - { - permimpbuf->yv.ptr.p_double[varidx*nclasses+j] = permimpbuf->yv.ptr.p_double[varidx*nclasses+j]+permimpbuf->y.ptr.p_double[j]; - } - - /* - * Compute losses for variable #VarIdx being perturbed. Quite an often decision - * process does not actually depend on the variable #VarIdx (path from the tree - * root does not include splits on this variable). In such cases we perform - * quick exit from the loop with precomputed value. - */ - for(j=0; j<=nvars-1; j++) - { - permimpbuf->xcur.ptr.p_double[j] = permimpbuf->xraw.ptr.p_double[j]; - } - for(varidx=0; varidx<=nvars-1; varidx++) - { - if( permimpbuf->startnodes.ptr.p_int[varidx]>=0 ) - { - - /* - * Path from tree root to the final leaf involves split on variable #VarIdx. - * Restart computation from the position first split on #VarIdx. - */ - ae_assert(df->forestformat==dforest_dfuncompressedv0, "EstimateVariableImportance: integrity check failed (ff)", _state); - permimpbuf->xcur.ptr.p_double[varidx] = permimpbuf->xdist.ptr.p_double[varidx]; - nodeoffs = permimpbuf->startnodes.ptr.p_int[varidx]; - for(;;) - { - if( ae_fp_eq(df->trees.ptr.p_double[nodeoffs],(double)(-1)) ) - { - if( nclasses>1 ) - { - j = ae_round(df->trees.ptr.p_double[nodeoffs+1], _state); - permimpbuf->yv.ptr.p_double[varidx*nclasses+j] = permimpbuf->yv.ptr.p_double[varidx*nclasses+j]+1; - } - else - { - permimpbuf->yv.ptr.p_double[varidx] = permimpbuf->yv.ptr.p_double[varidx]+df->trees.ptr.p_double[nodeoffs+1]; - } - break; - } - j = ae_round(df->trees.ptr.p_double[nodeoffs], _state); - if( permimpbuf->xcur.ptr.p_double[j]trees.ptr.p_double[nodeoffs+1] ) - { - nodeoffs = nodeoffs+dforest_innernodewidth; - } - else - { - nodeoffs = treeroot+ae_round(df->trees.ptr.p_double[nodeoffs+2], _state); - } - } - permimpbuf->xcur.ptr.p_double[varidx] = permimpbuf->xraw.ptr.p_double[varidx]; - } - else - { - - /* - * Path from tree root to the final leaf does NOT involve split on variable #VarIdx. - * Permutation does not change tree output, reuse already computed value. - */ - if( nclasses>1 ) - { - j = ae_round(prediction, _state); - permimpbuf->yv.ptr.p_double[varidx*nclasses+j] = permimpbuf->yv.ptr.p_double[varidx*nclasses+j]+1; - } - else - { - permimpbuf->yv.ptr.p_double[varidx] = permimpbuf->yv.ptr.p_double[varidx]+prediction; - } - } - } - - /* - * update OOB counter - */ - inc(&oobcounts, _state); - } - treeroot = treeroot+ae_round(df->trees.ptr.p_double[treeroot], _state); - } - - /* - * Now YV[] stores NPerm versions of the forest output for various permutations of variable values. - * Update losses. - */ - for(j=0; j<=nperm-1; j++) - { - for(k=0; k<=nclasses-1; k++) - { - permimpbuf->yv.ptr.p_double[j*nclasses+k] = permimpbuf->yv.ptr.p_double[j*nclasses+k]/coalesce((double)(oobcounts), (double)(1), _state); - } - v = (double)(0); - for(k=0; k<=nclasses-1; k++) - { - v = v+ae_sqr(permimpbuf->yv.ptr.p_double[j*nclasses+k]-permimpbuf->targety.ptr.p_double[k], _state); - } - permimpbuf->losses.ptr.p_double[j] = permimpbuf->losses.ptr.p_double[j]+v; - } - - /* - * Update progress indicator - */ - threadunsafeincby(&s->rdfprogress, ntrees, _state); - } - - /* - * Recycle buffer object with updated Losses[] field - */ - ae_shared_pool_recycle(permpool, &_permimpbuf, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_dforest_estimatepermutationimportances(decisionforestbuilder* s, - decisionforest* df, - ae_int_t ntrees, - ae_shared_pool* permpool, - ae_int_t idx0, - ae_int_t idx1, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -Sets report fields to their default values - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -static void dforest_cleanreport(decisionforestbuilder* s, - dfreport* rep, - ae_state *_state) -{ - ae_int_t i; - - - rep->relclserror = (double)(0); - rep->avgce = (double)(0); - rep->rmserror = (double)(0); - rep->avgerror = (double)(0); - rep->avgrelerror = (double)(0); - rep->oobrelclserror = (double)(0); - rep->oobavgce = (double)(0); - rep->oobrmserror = (double)(0); - rep->oobavgerror = (double)(0); - rep->oobavgrelerror = (double)(0); - ae_vector_set_length(&rep->topvars, s->nvars, _state); - ae_vector_set_length(&rep->varimportances, s->nvars, _state); - for(i=0; i<=s->nvars-1; i++) - { - rep->topvars.ptr.p_int[i] = i; - rep->varimportances.ptr.p_double[i] = (double)(0); - } -} - - -/************************************************************************* -This function returns NRMS2 loss (sum of squared residuals) for a constant- -output model: -* model output is a mean over TRN set being passed (for classification - problems - NClasses-dimensional vector of class probabilities) -* model is evaluated over TST set being passed, with L2 loss being returned - -Input parameters: - NClasses - ">1" for classification, "=1" for regression - TrnLabelsI - training set labels, class indexes (for NClasses>1) - TrnLabelsR - training set output values (for NClasses=1) - TrnIdx0, TrnIdx1 - a range [Idx0,Idx1) of elements in LabelsI/R is considered - TstLabelsI - training set labels, class indexes (for NClasses>1) - TstLabelsR - training set output values (for NClasses=1) - TstIdx0, TstIdx1 - a range [Idx0,Idx1) of elements in LabelsI/R is considered - TmpI - temporary array, reallocated as needed - -Result: - sum of squared residuals; - for NClasses>=2 it coincides with Gini impurity times (Idx1-Idx0) - -Following fields of WorkBuf are used as temporaries: -* TmpMeanNRMS2 - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -static double dforest_meannrms2(ae_int_t nclasses, - /* Integer */ ae_vector* trnlabelsi, - /* Real */ ae_vector* trnlabelsr, - ae_int_t trnidx0, - ae_int_t trnidx1, - /* Integer */ ae_vector* tstlabelsi, - /* Real */ ae_vector* tstlabelsr, - ae_int_t tstidx0, - ae_int_t tstidx1, - /* Integer */ ae_vector* tmpi, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - ae_int_t ntrn; - ae_int_t ntst; - double v; - double vv; - double invntrn; - double pitrn; - double nitst; - double result; - - - ae_assert(trnidx0<=trnidx1, "MeanNRMS2: integrity check failed (8754)", _state); - ae_assert(tstidx0<=tstidx1, "MeanNRMS2: integrity check failed (8754)", _state); - result = (double)(0); - ntrn = trnidx1-trnidx0; - ntst = tstidx1-tstidx0; - if( ntrn==0||ntst==0 ) - { - return result; - } - invntrn = 1.0/ntrn; - if( nclasses>1 ) - { - - /* - * Classification problem - */ - ivectorsetlengthatleast(tmpi, 2*nclasses, _state); - for(i=0; i<=2*nclasses-1; i++) - { - tmpi->ptr.p_int[i] = 0; - } - for(i=trnidx0; i<=trnidx1-1; i++) - { - k = trnlabelsi->ptr.p_int[i]; - tmpi->ptr.p_int[k] = tmpi->ptr.p_int[k]+1; - } - for(i=tstidx0; i<=tstidx1-1; i++) - { - k = tstlabelsi->ptr.p_int[i]; - tmpi->ptr.p_int[k+nclasses] = tmpi->ptr.p_int[k+nclasses]+1; - } - for(i=0; i<=nclasses-1; i++) - { - pitrn = tmpi->ptr.p_int[i]*invntrn; - nitst = (double)(tmpi->ptr.p_int[i+nclasses]); - result = result+nitst*(1-pitrn)*(1-pitrn); - result = result+(ntst-nitst)*pitrn*pitrn; - } - } - else - { - - /* - * regression-specific code - */ - v = (double)(0); - for(i=trnidx0; i<=trnidx1-1; i++) - { - v = v+trnlabelsr->ptr.p_double[i]; - } - v = v*invntrn; - for(i=tstidx0; i<=tstidx1-1; i++) - { - vv = tstlabelsr->ptr.p_double[i]-v; - result = result+vv*vv; - } - } - return result; -} - - -/************************************************************************* -This function is a part of the recurrent tree construction function; it -selects variable for splitting according to current tree construction -algorithm. - -Note: modifies VarsInPool, may decrease it if some variables become non-informative -and leave the pool. - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -static void dforest_choosecurrentsplitdense(decisionforestbuilder* s, - dfworkbuf* workbuf, - ae_int_t* varsinpool, - ae_int_t varstoselect, - hqrndstate* rs, - ae_int_t idx0, - ae_int_t idx1, - ae_int_t* varbest, - double* splitbest, - ae_state *_state) -{ - ae_int_t npoints; - double errbest; - ae_int_t varstried; - ae_int_t varcur; - ae_bool valuesaresame; - ae_int_t offs; - double split; - ae_int_t i; - double v; - double v0; - double currms; - ae_int_t info; - - *varbest = 0; - *splitbest = 0; - - ae_assert(s->dstype==0, "sparsity is not supported 4terg!", _state); - ae_assert(s->rdfalgo==0, "BuildRandomTreeRec: integrity check failed (1657)", _state); - ae_assert(idx0npoints; - - /* - * Select split according to dense direct RDF algorithm - */ - *varbest = -1; - errbest = ae_maxrealnumber; - *splitbest = (double)(0); - varstried = 0; - while(varstried<=ae_minint(varstoselect, *varsinpool, _state)-1) - { - - /* - * select variables from pool - */ - swapelementsi(&workbuf->varpool, varstried, varstried+hqrnduniformi(rs, *varsinpool-varstried, _state), _state); - varcur = workbuf->varpool.ptr.p_int[varstried]; - - /* - * Load variable values to working array. - * If all variable values are same, variable is excluded from pool and we re-run variable selection. - */ - valuesaresame = ae_true; - ae_assert(s->dstype==0, "not supported segsv34fs", _state); - offs = npoints*varcur; - v0 = s->dsdata.ptr.p_double[offs+workbuf->trnset.ptr.p_int[idx0]]; - for(i=idx0; i<=idx1-1; i++) - { - v = s->dsdata.ptr.p_double[offs+workbuf->trnset.ptr.p_int[i]]; - workbuf->curvals.ptr.p_double[i] = v; - valuesaresame = valuesaresame&&v==v0; - } - if( valuesaresame ) - { - - /* - * Variable does not change across current subset. - * Exclude variable from pool, go to the next iteration. - * VarsTried is not increased. - * - * NOTE: it is essential that updated VarsInPool is passed - * down to children but not up to caller - it is - * possible that one level higher this variable is - * not-fixed. - */ - swapelementsi(&workbuf->varpool, varstried, *varsinpool-1, _state); - *varsinpool = *varsinpool-1; - continue; - } - - /* - * Now we are ready to infer the split - */ - dforest_evaluatedensesplit(s, workbuf, rs, varcur, idx0, idx1, &info, &split, &currms, _state); - if( info>0&&(*varbest<0||ae_fp_less_eq(currms,errbest)) ) - { - errbest = currms; - *varbest = varcur; - *splitbest = split; - for(i=idx0; i<=idx1-1; i++) - { - workbuf->bestvals.ptr.p_double[i] = workbuf->curvals.ptr.p_double[i]; - } - } - - /* - * Next iteration - */ - varstried = varstried+1; - } -} - - -/************************************************************************* -This function performs split on some specific dense variable whose values -are stored in WorkBuf.CurVals[Idx0,Idx1) and labels are stored in -WorkBuf.TrnLabelsR/I[Idx0,Idx1). - -It returns split value and associated RMS error. It is responsibility of -the caller to make sure that variable has at least two distinct values, -i.e. it is possible to make a split. - -Precomputed values of following fields of WorkBuf are used: -* ClassPriors - -Following fields of WorkBuf are used as temporaries: -* ClassTotals0,1,01 -* Tmp0I, Tmp1I, Tmp0R, Tmp1R, Tmp2R, Tmp3R - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -static void dforest_evaluatedensesplit(decisionforestbuilder* s, - dfworkbuf* workbuf, - hqrndstate* rs, - ae_int_t splitvar, - ae_int_t idx0, - ae_int_t idx1, - ae_int_t* info, - double* split, - double* rms, - ae_state *_state) -{ - ae_int_t nclasses; - ae_int_t i; - ae_int_t j; - ae_int_t k0; - ae_int_t k1; - double v; - double v0; - double v1; - double v2; - ae_int_t sl; - ae_int_t sr; - - *info = 0; - *split = 0; - *rms = 0; - - ae_assert(idx0nclasses; - if( s->dsbinary.ptr.p_bool[splitvar] ) - { - - /* - * Try simple binary split, if possible - * Split can be inferred from minimum/maximum values, just calculate RMS error - */ - *info = 1; - *split = dforest_getsplit(s, s->dsmin.ptr.p_double[splitvar], s->dsmax.ptr.p_double[splitvar], rs, _state); - if( nclasses>1 ) - { - - /* - * Classification problem - */ - for(j=0; j<=nclasses-1; j++) - { - workbuf->classtotals0.ptr.p_int[j] = 0; - } - sl = 0; - for(i=idx0; i<=idx1-1; i++) - { - if( workbuf->curvals.ptr.p_double[i]<*split ) - { - j = workbuf->trnlabelsi.ptr.p_int[i]; - workbuf->classtotals0.ptr.p_int[j] = workbuf->classtotals0.ptr.p_int[j]+1; - sl = sl+1; - } - } - sr = idx1-idx0-sl; - ae_assert(sl!=0&&sr!=0, "BuildRandomTreeRec: something strange, impossible failure!", _state); - v0 = (double)1/(double)sl; - v1 = (double)1/(double)sr; - *rms = (double)(0); - for(j=0; j<=nclasses-1; j++) - { - k0 = workbuf->classtotals0.ptr.p_int[j]; - k1 = workbuf->classpriors.ptr.p_int[j]-k0; - *rms = *rms+k0*(1-v0*k0)+k1*(1-v1*k1); - } - *rms = ae_sqrt(*rms/(nclasses*(idx1-idx0+1)), _state); - } - else - { - - /* - * regression-specific code - */ - sl = 0; - sr = 0; - v1 = (double)(0); - v2 = (double)(0); - for(j=idx0; j<=idx1-1; j++) - { - if( workbuf->curvals.ptr.p_double[j]<*split ) - { - v1 = v1+workbuf->trnlabelsr.ptr.p_double[j]; - sl = sl+1; - } - else - { - v2 = v2+workbuf->trnlabelsr.ptr.p_double[j]; - sr = sr+1; - } - } - ae_assert(sl!=0&&sr!=0, "BuildRandomTreeRec: something strange, impossible failure!", _state); - v1 = v1/sl; - v2 = v2/sr; - *rms = (double)(0); - for(j=0; j<=idx1-idx0-1; j++) - { - v = workbuf->trnlabelsr.ptr.p_double[idx0+j]; - if( workbuf->curvals.ptr.p_double[j]<*split ) - { - v = v-v1; - } - else - { - v = v-v2; - } - *rms = *rms+v*v; - } - *rms = ae_sqrt(*rms/(idx1-idx0+1), _state); - } - } - else - { - - /* - * General split - */ - *info = 0; - if( nclasses>1 ) - { - for(i=0; i<=idx1-idx0-1; i++) - { - workbuf->tmp0r.ptr.p_double[i] = workbuf->curvals.ptr.p_double[idx0+i]; - workbuf->tmp0i.ptr.p_int[i] = workbuf->trnlabelsi.ptr.p_int[idx0+i]; - } - dforest_classifiersplit(s, workbuf, &workbuf->tmp0r, &workbuf->tmp0i, idx1-idx0, rs, info, split, rms, &workbuf->tmp1r, &workbuf->tmp1i, _state); - } - else - { - for(i=0; i<=idx1-idx0-1; i++) - { - workbuf->tmp0r.ptr.p_double[i] = workbuf->curvals.ptr.p_double[idx0+i]; - workbuf->tmp1r.ptr.p_double[i] = workbuf->trnlabelsr.ptr.p_double[idx0+i]; - } - dforest_regressionsplit(s, workbuf, &workbuf->tmp0r, &workbuf->tmp1r, idx1-idx0, info, split, rms, &workbuf->tmp2r, &workbuf->tmp3r, _state); - } - } -} - - -/************************************************************************* -Classifier split -*************************************************************************/ -static void dforest_classifiersplit(decisionforestbuilder* s, - dfworkbuf* workbuf, - /* Real */ ae_vector* x, - /* Integer */ ae_vector* c, - ae_int_t n, - hqrndstate* rs, - ae_int_t* info, - double* threshold, - double* e, - /* Real */ ae_vector* sortrbuf, - /* Integer */ ae_vector* sortibuf, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t n0; - ae_int_t n0prev; - double v; - ae_int_t advanceby; - double rms; - ae_int_t k0; - ae_int_t k1; - double v0; - double v1; - ae_int_t nclasses; - double vmin; - double vmax; - - *info = 0; - *threshold = 0; - *e = 0; - - ae_assert((s->rdfsplitstrength==0||s->rdfsplitstrength==1)||s->rdfsplitstrength==2, "RDF: unexpected split type at ClassifierSplit()", _state); - nclasses = s->nclasses; - advanceby = 1; - if( n>=20 ) - { - advanceby = ae_maxint(2, ae_round(n*0.05, _state), _state); - } - *info = -1; - *threshold = (double)(0); - *e = ae_maxrealnumber; - - /* - * Random split - */ - if( s->rdfsplitstrength==0 ) - { - - /* - * Evaluate minimum, maximum and randomly selected values - */ - vmin = x->ptr.p_double[0]; - vmax = x->ptr.p_double[0]; - for(i=1; i<=n-1; i++) - { - v = x->ptr.p_double[i]; - if( vvmax ) - { - vmax = v; - } - } - if( ae_fp_eq(vmin,vmax) ) - { - return; - } - v = x->ptr.p_double[hqrnduniformi(rs, n, _state)]; - if( ae_fp_eq(v,vmin) ) - { - v = vmax; - } - - /* - * Calculate RMS error associated with the split - */ - for(i=0; i<=nclasses-1; i++) - { - workbuf->classtotals0.ptr.p_int[i] = 0; - } - n0 = 0; - for(i=0; i<=n-1; i++) - { - if( x->ptr.p_double[i]ptr.p_int[i]; - workbuf->classtotals0.ptr.p_int[k] = workbuf->classtotals0.ptr.p_int[k]+1; - n0 = n0+1; - } - } - ae_assert(n0>0&&n0classtotals0.ptr.p_int[j]; - k1 = workbuf->classpriors.ptr.p_int[j]-k0; - rms = rms+k0*(1-v0*k0)+k1*(1-v1*k1); - } - *threshold = v; - *info = 1; - *e = rms; - return; - } - - /* - * Stronger splits which require us to sort the data - * Quick check for degeneracy - */ - tagsortfasti(x, c, sortrbuf, sortibuf, n, _state); - v = 0.5*(x->ptr.p_double[0]+x->ptr.p_double[n-1]); - if( !(ae_fp_less(x->ptr.p_double[0],v)&&ae_fp_less(v,x->ptr.p_double[n-1])) ) - { - return; - } - - /* - * Split at the middle - */ - if( s->rdfsplitstrength==1 ) - { - - /* - * Select split position - */ - vmin = x->ptr.p_double[0]; - vmax = x->ptr.p_double[n-1]; - v = x->ptr.p_double[n/2]; - if( ae_fp_eq(v,vmin) ) - { - v = vmin+0.001*(vmax-vmin); - } - if( ae_fp_eq(v,vmin) ) - { - v = vmax; - } - - /* - * Calculate RMS error associated with the split - */ - for(i=0; i<=nclasses-1; i++) - { - workbuf->classtotals0.ptr.p_int[i] = 0; - } - n0 = 0; - for(i=0; i<=n-1; i++) - { - if( x->ptr.p_double[i]ptr.p_int[i]; - workbuf->classtotals0.ptr.p_int[k] = workbuf->classtotals0.ptr.p_int[k]+1; - n0 = n0+1; - } - } - ae_assert(n0>0&&n0classtotals0.ptr.p_int[j]; - k1 = workbuf->classpriors.ptr.p_int[j]-k0; - rms = rms+k0*(1-v0*k0)+k1*(1-v1*k1); - } - *threshold = v; - *info = 1; - *e = rms; - return; - } - - /* - * Strong split - */ - if( s->rdfsplitstrength==2 ) - { - - /* - * Prepare initial split. - * Evaluate current split, prepare next one, repeat. - */ - for(i=0; i<=nclasses-1; i++) - { - workbuf->classtotals0.ptr.p_int[i] = 0; - } - n0 = 1; - while(n0ptr.p_double[n0]==x->ptr.p_double[n0-1]) - { - n0 = n0+1; - } - ae_assert(n0ptr.p_int[i]; - workbuf->classtotals0.ptr.p_int[k] = workbuf->classtotals0.ptr.p_int[k]+1; - } - *info = -1; - *threshold = x->ptr.p_double[n-1]; - *e = ae_maxrealnumber; - while(n0classtotals0.ptr.p_int[j]; - k1 = workbuf->classpriors.ptr.p_int[j]-k0; - rms = rms+k0*(1-v0*k0)+k1*(1-v1*k1); - } - if( *info<0||rms<*e ) - { - *info = 1; - *e = rms; - *threshold = 0.5*(x->ptr.p_double[n0-1]+x->ptr.p_double[n0]); - if( *threshold<=x->ptr.p_double[n0-1] ) - { - *threshold = x->ptr.p_double[n0]; - } - } - - /* - * Advance - */ - n0prev = n0; - while(n0ptr.p_double[n0]; - while(n0ptr.p_double[n0]==v) - { - k = c->ptr.p_int[n0]; - workbuf->classtotals0.ptr.p_int[k] = workbuf->classtotals0.ptr.p_int[k]+1; - n0 = n0+1; - } - } - } - if( *info>0 ) - { - *e = ae_sqrt(*e/(nclasses*n), _state); - } - return; - } - ae_assert(ae_false, "RDF: ClassifierSplit(), critical error", _state); -} - - -/************************************************************************* -Regression model split -*************************************************************************/ -static void dforest_regressionsplit(decisionforestbuilder* s, - dfworkbuf* workbuf, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t* info, - double* threshold, - double* e, - /* Real */ ae_vector* sortrbuf, - /* Real */ ae_vector* sortrbuf2, - ae_state *_state) -{ - ae_int_t i; - double vmin; - double vmax; - double bnd01; - double bnd12; - double bnd23; - ae_int_t total0; - ae_int_t total1; - ae_int_t total2; - ae_int_t total3; - ae_int_t cnt0; - ae_int_t cnt1; - ae_int_t cnt2; - ae_int_t cnt3; - ae_int_t n0; - ae_int_t advanceby; - double v; - double v0; - double v1; - double rms; - ae_int_t n0prev; - ae_int_t k0; - ae_int_t k1; - - *info = 0; - *threshold = 0; - *e = 0; - - advanceby = 1; - if( n>=20 ) - { - advanceby = ae_maxint(2, ae_round(n*0.05, _state), _state); - } - - /* - * Sort data - * Quick check for degeneracy - */ - tagsortfastr(x, y, sortrbuf, sortrbuf2, n, _state); - v = 0.5*(x->ptr.p_double[0]+x->ptr.p_double[n-1]); - if( !(ae_fp_less(x->ptr.p_double[0],v)&&ae_fp_less(v,x->ptr.p_double[n-1])) ) - { - *info = -1; - *threshold = x->ptr.p_double[n-1]; - *e = ae_maxrealnumber; - return; - } - - /* - * Prepare initial split. - * Evaluate current split, prepare next one, repeat. - */ - vmin = y->ptr.p_double[0]; - vmax = y->ptr.p_double[0]; - for(i=1; i<=n-1; i++) - { - v = y->ptr.p_double[i]; - if( vvmax ) - { - vmax = v; - } - } - bnd12 = 0.5*(vmin+vmax); - bnd01 = 0.5*(vmin+bnd12); - bnd23 = 0.5*(vmax+bnd12); - total0 = 0; - total1 = 0; - total2 = 0; - total3 = 0; - for(i=0; i<=n-1; i++) - { - v = y->ptr.p_double[i]; - if( vptr.p_double[n0]==x->ptr.p_double[n0-1]) - { - n0 = n0+1; - } - ae_assert(n0ptr.p_double[i]; - if( vptr.p_double[n-1]; - *e = ae_maxrealnumber; - while(n0ptr.p_double[n0-1]+x->ptr.p_double[n0]); - if( *threshold<=x->ptr.p_double[n0-1] ) - { - *threshold = x->ptr.p_double[n0]; - } - } - - /* - * Advance - */ - n0prev = n0; - while(n0ptr.p_double[n0]; - while(n0ptr.p_double[n0]==v0) - { - v = y->ptr.p_double[n0]; - if( v0 ) - { - *e = ae_sqrt(*e/(4*n), _state); - } -} - - -/************************************************************************* -Returns split: either deterministic split at the middle of [A,B], or randomly -chosen split. - -It is guaranteed that Anclasses; - if( nclasses==1 ) - { - - /* - * Store split to the tree - */ - treebuf->ptr.p_double[*treesize] = (double)(-1); - treebuf->ptr.p_double[*treesize+1] = leafval; - - /* - * Update training and OOB voting stats - */ - for(i=idx0; i<=idx1-1; i++) - { - j = workbuf->trnset.ptr.p_int[i]; - votebuf->trntotals.ptr.p_double[j] = votebuf->trntotals.ptr.p_double[j]+leafval; - votebuf->trncounts.ptr.p_int[j] = votebuf->trncounts.ptr.p_int[j]+1; - } - for(i=oobidx0; i<=oobidx1-1; i++) - { - j = workbuf->oobset.ptr.p_int[i]; - votebuf->oobtotals.ptr.p_double[j] = votebuf->oobtotals.ptr.p_double[j]+leafval; - votebuf->oobcounts.ptr.p_int[j] = votebuf->oobcounts.ptr.p_int[j]+1; - } - } - else - { - - /* - * Store split to the tree - */ - treebuf->ptr.p_double[*treesize] = (double)(-1); - treebuf->ptr.p_double[*treesize+1] = leafval; - - /* - * Update training and OOB voting stats - */ - leafvali = ae_round(leafval, _state); - for(i=idx0; i<=idx1-1; i++) - { - j = workbuf->trnset.ptr.p_int[i]; - votebuf->trntotals.ptr.p_double[j*nclasses+leafvali] = votebuf->trntotals.ptr.p_double[j*nclasses+leafvali]+1; - votebuf->trncounts.ptr.p_int[j] = votebuf->trncounts.ptr.p_int[j]+1; - } - for(i=oobidx0; i<=oobidx1-1; i++) - { - j = workbuf->oobset.ptr.p_int[i]; - votebuf->oobtotals.ptr.p_double[j*nclasses+leafvali] = votebuf->oobtotals.ptr.p_double[j*nclasses+leafvali]+1; - votebuf->oobcounts.ptr.p_int[j] = votebuf->oobcounts.ptr.p_int[j]+1; - } - } - *treesize = *treesize+dforest_leafnodewidth; -} - - -/************************************************************************* -This function performs generic and algorithm-specific preprocessing of the -dataset - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -static void dforest_analyzeandpreprocessdataset(decisionforestbuilder* s, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nvars; - ae_int_t nclasses; - ae_int_t npoints; - ae_int_t i; - ae_int_t j; - ae_bool isbinary; - double v; - double v0; - double v1; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - _hqrndstate_init(&rs, _state, ae_true); - - ae_assert(s->dstype==0, "no sparsity", _state); - npoints = s->npoints; - nvars = s->nvars; - nclasses = s->nclasses; - - /* - * seed local RNG - */ - if( s->rdfglobalseed>0 ) - { - hqrndseed(s->rdfglobalseed, 3532, &rs, _state); - } - else - { - hqrndseed(ae_randominteger(30000, _state), 3532, &rs, _state); - } - - /* - * Generic processing - */ - ae_assert(npoints>=1, "BuildRandomForest: integrity check failed", _state); - rvectorsetlengthatleast(&s->dsmin, nvars, _state); - rvectorsetlengthatleast(&s->dsmax, nvars, _state); - bvectorsetlengthatleast(&s->dsbinary, nvars, _state); - for(i=0; i<=nvars-1; i++) - { - v0 = s->dsdata.ptr.p_double[i*npoints+0]; - v1 = s->dsdata.ptr.p_double[i*npoints+0]; - for(j=1; j<=npoints-1; j++) - { - v = s->dsdata.ptr.p_double[i*npoints+j]; - if( vv1 ) - { - v1 = v; - } - } - s->dsmin.ptr.p_double[i] = v0; - s->dsmax.ptr.p_double[i] = v1; - ae_assert(ae_fp_less_eq(v0,v1), "BuildRandomForest: strange integrity check failure", _state); - isbinary = ae_true; - for(j=0; j<=npoints-1; j++) - { - v = s->dsdata.ptr.p_double[i*npoints+j]; - isbinary = isbinary&&(v==v0||v==v1); - } - s->dsbinary.ptr.p_bool[i] = isbinary; - } - if( nclasses==1 ) - { - s->dsravg = (double)(0); - for(i=0; i<=npoints-1; i++) - { - s->dsravg = s->dsravg+s->dsrval.ptr.p_double[i]; - } - s->dsravg = s->dsravg/npoints; - } - else - { - ivectorsetlengthatleast(&s->dsctotals, nclasses, _state); - for(i=0; i<=nclasses-1; i++) - { - s->dsctotals.ptr.p_int[i] = 0; - } - for(i=0; i<=npoints-1; i++) - { - s->dsctotals.ptr.p_int[s->dsival.ptr.p_int[i]] = s->dsctotals.ptr.p_int[s->dsival.ptr.p_int[i]]+1; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function merges together trees generated during training and outputs -it to the decision forest. - -INPUT PARAMETERS: - S - decision forest builder object - NTrees - NTrees>=1, number of trees to train - -OUTPUT PARAMETERS: - DF - decision forest - Rep - report - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -static void dforest_mergetrees(decisionforestbuilder* s, - decisionforest* df, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t cursize; - ae_int_t offs; - dftreebuf *tree; - ae_smart_ptr _tree; - ae_vector treesizes; - ae_vector treeoffsets; - - ae_frame_make(_state, &_frame_block); - memset(&_tree, 0, sizeof(_tree)); - memset(&treesizes, 0, sizeof(treesizes)); - memset(&treeoffsets, 0, sizeof(treeoffsets)); - ae_smart_ptr_init(&_tree, (void**)&tree, _state, ae_true); - ae_vector_init(&treesizes, 0, DT_INT, _state, ae_true); - ae_vector_init(&treeoffsets, 0, DT_INT, _state, ae_true); - - df->forestformat = dforest_dfuncompressedv0; - df->nvars = s->nvars; - df->nclasses = s->nclasses; - df->bufsize = 0; - df->ntrees = 0; - - /* - * Determine trees count - */ - ae_shared_pool_first_recycled(&s->treepool, &_tree, _state); - while(tree!=NULL) - { - df->ntrees = df->ntrees+1; - ae_shared_pool_next_recycled(&s->treepool, &_tree, _state); - } - ae_assert(df->ntrees>0, "MergeTrees: integrity check failed, zero trees count", _state); - - /* - * Determine individual tree sizes and total buffer size - */ - ae_vector_set_length(&treesizes, df->ntrees, _state); - for(i=0; i<=df->ntrees-1; i++) - { - treesizes.ptr.p_int[i] = -1; - } - ae_shared_pool_first_recycled(&s->treepool, &_tree, _state); - while(tree!=NULL) - { - ae_assert(tree->treeidx>=0&&tree->treeidxntrees, "MergeTrees: integrity check failed (wrong TreeIdx)", _state); - ae_assert(treesizes.ptr.p_int[tree->treeidx]<0, "MergeTrees: integrity check failed (duplicate TreeIdx)", _state); - df->bufsize = df->bufsize+ae_round(tree->treebuf.ptr.p_double[0], _state); - treesizes.ptr.p_int[tree->treeidx] = ae_round(tree->treebuf.ptr.p_double[0], _state); - ae_shared_pool_next_recycled(&s->treepool, &_tree, _state); - } - for(i=0; i<=df->ntrees-1; i++) - { - ae_assert(treesizes.ptr.p_int[i]>0, "MergeTrees: integrity check failed (wrong TreeSize)", _state); - } - - /* - * Determine offsets for individual trees in output buffer - */ - ae_vector_set_length(&treeoffsets, df->ntrees, _state); - treeoffsets.ptr.p_int[0] = 0; - for(i=1; i<=df->ntrees-1; i++) - { - treeoffsets.ptr.p_int[i] = treeoffsets.ptr.p_int[i-1]+treesizes.ptr.p_int[i-1]; - } - - /* - * Output trees - * - * NOTE: since ALGLIB 3.16.0 trees are sorted by tree index prior to - * output (necessary for variable importance estimation), that's - * why we need array of tree offsets - */ - ae_vector_set_length(&df->trees, df->bufsize, _state); - ae_shared_pool_first_recycled(&s->treepool, &_tree, _state); - while(tree!=NULL) - { - cursize = ae_round(tree->treebuf.ptr.p_double[0], _state); - offs = treeoffsets.ptr.p_int[tree->treeidx]; - for(i=0; i<=cursize-1; i++) - { - df->trees.ptr.p_double[offs+i] = tree->treebuf.ptr.p_double[i]; - } - ae_shared_pool_next_recycled(&s->treepool, &_tree, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function post-processes voting array and calculates TRN and OOB errors. - -INPUT PARAMETERS: - S - decision forest builder object - NTrees - number of trees in the forest - Buf - possibly preallocated vote buffer, its contents is - overwritten by this function - -OUTPUT PARAMETERS: - Rep - report fields corresponding to errors are updated - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -static void dforest_processvotingresults(decisionforestbuilder* s, - ae_int_t ntrees, - dfvotebuf* buf, - dfreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - dfvotebuf *vote; - ae_smart_ptr _vote; - ae_int_t nvars; - ae_int_t nclasses; - ae_int_t npoints; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t k1; - double v; - ae_int_t avgrelcnt; - ae_int_t oobavgrelcnt; - - ae_frame_make(_state, &_frame_block); - memset(&_vote, 0, sizeof(_vote)); - ae_smart_ptr_init(&_vote, (void**)&vote, _state, ae_true); - - npoints = s->npoints; - nvars = s->nvars; - nclasses = s->nclasses; - ae_assert(npoints>0, "DFOREST: integrity check failed", _state); - ae_assert(nvars>0, "DFOREST: integrity check failed", _state); - ae_assert(nclasses>0, "DFOREST: integrity check failed", _state); - - /* - * Prepare vote buffer - */ - rvectorsetlengthatleast(&buf->trntotals, npoints*nclasses, _state); - rvectorsetlengthatleast(&buf->oobtotals, npoints*nclasses, _state); - for(i=0; i<=npoints*nclasses-1; i++) - { - buf->trntotals.ptr.p_double[i] = (double)(0); - buf->oobtotals.ptr.p_double[i] = (double)(0); - } - ivectorsetlengthatleast(&buf->trncounts, npoints, _state); - ivectorsetlengthatleast(&buf->oobcounts, npoints, _state); - for(i=0; i<=npoints-1; i++) - { - buf->trncounts.ptr.p_int[i] = 0; - buf->oobcounts.ptr.p_int[i] = 0; - } - - /* - * Merge voting arrays - */ - ae_shared_pool_first_recycled(&s->votepool, &_vote, _state); - while(vote!=NULL) - { - for(i=0; i<=npoints*nclasses-1; i++) - { - buf->trntotals.ptr.p_double[i] = buf->trntotals.ptr.p_double[i]+vote->trntotals.ptr.p_double[i]+vote->oobtotals.ptr.p_double[i]; - buf->oobtotals.ptr.p_double[i] = buf->oobtotals.ptr.p_double[i]+vote->oobtotals.ptr.p_double[i]; - } - for(i=0; i<=npoints-1; i++) - { - buf->trncounts.ptr.p_int[i] = buf->trncounts.ptr.p_int[i]+vote->trncounts.ptr.p_int[i]+vote->oobcounts.ptr.p_int[i]; - buf->oobcounts.ptr.p_int[i] = buf->oobcounts.ptr.p_int[i]+vote->oobcounts.ptr.p_int[i]; - } - ae_shared_pool_next_recycled(&s->votepool, &_vote, _state); - } - for(i=0; i<=npoints-1; i++) - { - v = 1/coalesce((double)(buf->trncounts.ptr.p_int[i]), (double)(1), _state); - for(j=0; j<=nclasses-1; j++) - { - buf->trntotals.ptr.p_double[i*nclasses+j] = buf->trntotals.ptr.p_double[i*nclasses+j]*v; - } - v = 1/coalesce((double)(buf->oobcounts.ptr.p_int[i]), (double)(1), _state); - for(j=0; j<=nclasses-1; j++) - { - buf->oobtotals.ptr.p_double[i*nclasses+j] = buf->oobtotals.ptr.p_double[i*nclasses+j]*v; - } - } - - /* - * Use aggregated voting data to output error metrics - */ - avgrelcnt = 0; - oobavgrelcnt = 0; - rep->rmserror = (double)(0); - rep->avgerror = (double)(0); - rep->avgrelerror = (double)(0); - rep->relclserror = (double)(0); - rep->avgce = (double)(0); - rep->oobrmserror = (double)(0); - rep->oobavgerror = (double)(0); - rep->oobavgrelerror = (double)(0); - rep->oobrelclserror = (double)(0); - rep->oobavgce = (double)(0); - for(i=0; i<=npoints-1; i++) - { - if( nclasses>1 ) - { - - /* - * classification-specific code - */ - k = s->dsival.ptr.p_int[i]; - for(j=0; j<=nclasses-1; j++) - { - v = buf->trntotals.ptr.p_double[i*nclasses+j]; - if( j==k ) - { - rep->avgce = rep->avgce-ae_log(coalesce(v, ae_minrealnumber, _state), _state); - rep->rmserror = rep->rmserror+ae_sqr(v-1, _state); - rep->avgerror = rep->avgerror+ae_fabs(v-1, _state); - rep->avgrelerror = rep->avgrelerror+ae_fabs(v-1, _state); - inc(&avgrelcnt, _state); - } - else - { - rep->rmserror = rep->rmserror+ae_sqr(v, _state); - rep->avgerror = rep->avgerror+ae_fabs(v, _state); - } - v = buf->oobtotals.ptr.p_double[i*nclasses+j]; - if( j==k ) - { - rep->oobavgce = rep->oobavgce-ae_log(coalesce(v, ae_minrealnumber, _state), _state); - rep->oobrmserror = rep->oobrmserror+ae_sqr(v-1, _state); - rep->oobavgerror = rep->oobavgerror+ae_fabs(v-1, _state); - rep->oobavgrelerror = rep->oobavgrelerror+ae_fabs(v-1, _state); - inc(&oobavgrelcnt, _state); - } - else - { - rep->oobrmserror = rep->oobrmserror+ae_sqr(v, _state); - rep->oobavgerror = rep->oobavgerror+ae_fabs(v, _state); - } - } - - /* - * Classification errors are handled separately - */ - k1 = 0; - for(j=1; j<=nclasses-1; j++) - { - if( buf->trntotals.ptr.p_double[i*nclasses+j]>buf->trntotals.ptr.p_double[i*nclasses+k1] ) - { - k1 = j; - } - } - if( k1!=k ) - { - rep->relclserror = rep->relclserror+1; - } - k1 = 0; - for(j=1; j<=nclasses-1; j++) - { - if( buf->oobtotals.ptr.p_double[i*nclasses+j]>buf->oobtotals.ptr.p_double[i*nclasses+k1] ) - { - k1 = j; - } - } - if( k1!=k ) - { - rep->oobrelclserror = rep->oobrelclserror+1; - } - } - else - { - - /* - * regression-specific code - */ - v = buf->trntotals.ptr.p_double[i]-s->dsrval.ptr.p_double[i]; - rep->rmserror = rep->rmserror+ae_sqr(v, _state); - rep->avgerror = rep->avgerror+ae_fabs(v, _state); - if( ae_fp_neq(s->dsrval.ptr.p_double[i],(double)(0)) ) - { - rep->avgrelerror = rep->avgrelerror+ae_fabs(v/s->dsrval.ptr.p_double[i], _state); - avgrelcnt = avgrelcnt+1; - } - v = buf->oobtotals.ptr.p_double[i]-s->dsrval.ptr.p_double[i]; - rep->oobrmserror = rep->oobrmserror+ae_sqr(v, _state); - rep->oobavgerror = rep->oobavgerror+ae_fabs(v, _state); - if( ae_fp_neq(s->dsrval.ptr.p_double[i],(double)(0)) ) - { - rep->oobavgrelerror = rep->oobavgrelerror+ae_fabs(v/s->dsrval.ptr.p_double[i], _state); - oobavgrelcnt = oobavgrelcnt+1; - } - } - } - rep->relclserror = rep->relclserror/npoints; - rep->rmserror = ae_sqrt(rep->rmserror/(npoints*nclasses), _state); - rep->avgerror = rep->avgerror/(npoints*nclasses); - rep->avgrelerror = rep->avgrelerror/coalesce((double)(avgrelcnt), (double)(1), _state); - rep->oobrelclserror = rep->oobrelclserror/npoints; - rep->oobrmserror = ae_sqrt(rep->oobrmserror/(npoints*nclasses), _state); - rep->oobavgerror = rep->oobavgerror/(npoints*nclasses); - rep->oobavgrelerror = rep->oobavgrelerror/coalesce((double)(oobavgrelcnt), (double)(1), _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function performs binary compression of decision forest, using either -8-bit mantissa (a bit more compact representation) or 16-bit mantissa for -splits and regression outputs. - -Forest is compressed in-place. - -Return value is a compression factor. - - -- ALGLIB -- - Copyright 22.07.2019 by Bochkanov Sergey -*************************************************************************/ -static double dforest_binarycompression(decisionforest* df, - ae_bool usemantissa8, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t size8; - ae_int_t size8i; - ae_int_t offssrc; - ae_int_t offsdst; - ae_int_t i; - ae_vector dummyi; - ae_int_t maxrawtreesize; - ae_vector compressedsizes; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&dummyi, 0, sizeof(dummyi)); - memset(&compressedsizes, 0, sizeof(compressedsizes)); - ae_vector_init(&dummyi, 0, DT_INT, _state, ae_true); - ae_vector_init(&compressedsizes, 0, DT_INT, _state, ae_true); - - - /* - * Quick exit if already compressed - */ - if( df->forestformat==dforest_dfcompressedv0 ) - { - result = (double)(1); - ae_frame_leave(_state); - return result; - } - - /* - * Check that source format is supported - */ - ae_assert(df->forestformat==dforest_dfuncompressedv0, "BinaryCompression: unexpected forest format", _state); - - /* - * Compute sizes of uncompressed and compressed trees. - */ - size8 = 0; - offssrc = 0; - maxrawtreesize = 0; - for(i=0; i<=df->ntrees-1; i++) - { - size8i = dforest_computecompressedsizerec(df, usemantissa8, offssrc, offssrc+1, &dummyi, ae_false, _state); - size8 = size8+dforest_computecompresseduintsize(size8i, _state)+size8i; - maxrawtreesize = ae_maxint(maxrawtreesize, ae_round(df->trees.ptr.p_double[offssrc], _state), _state); - offssrc = offssrc+ae_round(df->trees.ptr.p_double[offssrc], _state); - } - result = (double)(8*df->trees.cnt)/(double)(size8+1); - - /* - * Allocate memory and perform compression - */ - ae_vector_set_length(&(df->trees8), size8, _state); - ae_vector_set_length(&compressedsizes, maxrawtreesize, _state); - offssrc = 0; - offsdst = 0; - for(i=0; i<=df->ntrees-1; i++) - { - - /* - * Call compressed size evaluator one more time, now saving subtree sizes into temporary array - */ - size8i = dforest_computecompressedsizerec(df, usemantissa8, offssrc, offssrc+1, &compressedsizes, ae_true, _state); - - /* - * Output tree header (length in bytes) - */ - dforest_streamuint(&df->trees8, &offsdst, size8i, _state); - - /* - * Compress recursively - */ - dforest_compressrec(df, usemantissa8, offssrc, offssrc+1, &compressedsizes, &df->trees8, &offsdst, _state); - - /* - * Next tree - */ - offssrc = offssrc+ae_round(df->trees.ptr.p_double[offssrc], _state); - } - ae_assert(offsdst==size8, "BinaryCompression: integrity check failed (stream length)", _state); - - /* - * Finalize forest conversion, clear previously allocated memory - */ - df->forestformat = dforest_dfcompressedv0; - df->usemantissa8 = usemantissa8; - ae_vector_set_length(&df->trees, 0, _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function returns exact number of bytes required to store compressed -version of the tree starting at location TreeBase. - -PARAMETERS: - DF - decision forest - UseMantissa8 - whether 8-bit or 16-bit mantissas are used to store - floating point numbers - TreeRoot - root of the specific tree being stored (offset in DF.Trees) - TreePos - position within tree (first location in the tree - is TreeRoot+1) - CompressedSizes - not referenced if SaveCompressedSizes is False; - otherwise, values computed by this function for - specific values of TreePos are stored to - CompressedSizes[TreePos-TreeRoot] (other elements - of the array are not referenced). - This array must be preallocated by caller. - - -- ALGLIB -- - Copyright 22.07.2019 by Bochkanov Sergey -*************************************************************************/ -static ae_int_t dforest_computecompressedsizerec(decisionforest* df, - ae_bool usemantissa8, - ae_int_t treeroot, - ae_int_t treepos, - /* Integer */ ae_vector* compressedsizes, - ae_bool savecompressedsizes, - ae_state *_state) -{ - ae_int_t jmponbranch; - ae_int_t child0size; - ae_int_t child1size; - ae_int_t fpwidth; - ae_int_t result; - - - if( usemantissa8 ) - { - fpwidth = 2; - } - else - { - fpwidth = 3; - } - - /* - * Leaf or split? - */ - if( ae_fp_eq(df->trees.ptr.p_double[treepos],(double)(-1)) ) - { - - /* - * Leaf - */ - result = dforest_computecompresseduintsize(2*df->nvars, _state); - if( df->nclasses==1 ) - { - result = result+fpwidth; - } - else - { - result = result+dforest_computecompresseduintsize(ae_round(df->trees.ptr.p_double[treepos+1], _state), _state); - } - } - else - { - - /* - * Split - */ - jmponbranch = ae_round(df->trees.ptr.p_double[treepos+2], _state); - child0size = dforest_computecompressedsizerec(df, usemantissa8, treeroot, treepos+dforest_innernodewidth, compressedsizes, savecompressedsizes, _state); - child1size = dforest_computecompressedsizerec(df, usemantissa8, treeroot, treeroot+jmponbranch, compressedsizes, savecompressedsizes, _state); - if( child0size<=child1size ) - { - - /* - * Child #0 comes first because it is shorter - */ - result = dforest_computecompresseduintsize(ae_round(df->trees.ptr.p_double[treepos], _state), _state); - result = result+fpwidth; - result = result+dforest_computecompresseduintsize(child0size, _state); - } - else - { - - /* - * Child #1 comes first because it is shorter - */ - result = dforest_computecompresseduintsize(ae_round(df->trees.ptr.p_double[treepos], _state)+df->nvars, _state); - result = result+fpwidth; - result = result+dforest_computecompresseduintsize(child1size, _state); - } - result = result+child0size+child1size; - } - - /* - * Do we have to save compressed sizes? - */ - if( savecompressedsizes ) - { - ae_assert(treepos-treerootcnt, "ComputeCompressedSizeRec: integrity check failed", _state); - compressedsizes->ptr.p_int[treepos-treeroot] = result; - } - return result; -} - - -/************************************************************************* -This function returns exact number of bytes required to store compressed -version of the tree starting at location TreeBase. - -PARAMETERS: - DF - decision forest - UseMantissa8 - whether 8-bit or 16-bit mantissas are used to store - floating point numbers - TreeRoot - root of the specific tree being stored (offset in DF.Trees) - TreePos - position within tree (first location in the tree - is TreeRoot+1) - CompressedSizes - not referenced if SaveCompressedSizes is False; - otherwise, values computed by this function for - specific values of TreePos are stored to - CompressedSizes[TreePos-TreeRoot] (other elements - of the array are not referenced). - This array must be preallocated by caller. - - -- ALGLIB -- - Copyright 22.07.2019 by Bochkanov Sergey -*************************************************************************/ -static void dforest_compressrec(decisionforest* df, - ae_bool usemantissa8, - ae_int_t treeroot, - ae_int_t treepos, - /* Integer */ ae_vector* compressedsizes, - ae_vector* buf, - ae_int_t* dstoffs, - ae_state *_state) -{ - ae_int_t jmponbranch; - ae_int_t child0size; - ae_int_t child1size; - ae_int_t varidx; - double leafval; - double splitval; - ae_int_t dstoffsold; - - - dstoffsold = *dstoffs; - - /* - * Leaf or split? - */ - varidx = ae_round(df->trees.ptr.p_double[treepos], _state); - if( varidx==-1 ) - { - - /* - * Leaf node: - * * stream special value which denotes leaf (2*NVars) - * * then, stream scalar value (floating point) or class number (unsigned integer) - */ - leafval = df->trees.ptr.p_double[treepos+1]; - dforest_streamuint(buf, dstoffs, 2*df->nvars, _state); - if( df->nclasses==1 ) - { - dforest_streamfloat(buf, usemantissa8, dstoffs, leafval, _state); - } - else - { - dforest_streamuint(buf, dstoffs, ae_round(leafval, _state), _state); - } - } - else - { - - /* - * Split node: - * * fetch compressed sizes of child nodes, decide which child goes first - */ - jmponbranch = ae_round(df->trees.ptr.p_double[treepos+2], _state); - splitval = df->trees.ptr.p_double[treepos+1]; - child0size = compressedsizes->ptr.p_int[treepos+dforest_innernodewidth-treeroot]; - child1size = compressedsizes->ptr.p_int[treeroot+jmponbranch-treeroot]; - if( child0size<=child1size ) - { - - /* - * Child #0 comes first because it is shorter: - * * stream variable index used for splitting; - * value in [0,NVars) range indicates that split is - * "if VAR=VAL then BRANCH0 else BRANCH1" - * * stream value used for splitting - * * stream children #0 and #1 - */ - dforest_streamuint(buf, dstoffs, varidx+df->nvars, _state); - dforest_streamfloat(buf, usemantissa8, dstoffs, splitval, _state); - dforest_streamuint(buf, dstoffs, child1size, _state); - dforest_compressrec(df, usemantissa8, treeroot, treeroot+jmponbranch, compressedsizes, buf, dstoffs, _state); - dforest_compressrec(df, usemantissa8, treeroot, treepos+dforest_innernodewidth, compressedsizes, buf, dstoffs, _state); - } - } - - /* - * Integrity check at the end - */ - ae_assert(*dstoffs-dstoffsold==compressedsizes->ptr.p_int[treepos-treeroot], "CompressRec: integrity check failed (compressed size at leaf)", _state); -} - - -/************************************************************************* -This function returns exact number of bytes required to store compressed -unsigned integer number (negative arguments result in assertion being -generated). - - -- ALGLIB -- - Copyright 22.07.2019 by Bochkanov Sergey -*************************************************************************/ -static ae_int_t dforest_computecompresseduintsize(ae_int_t v, - ae_state *_state) -{ - ae_int_t result; - - - ae_assert(v>=0, "Assertion failed", _state); - result = 1; - while(v>=128) - { - v = v/128; - result = result+1; - } - return result; -} - - -/************************************************************************* -This function stores compressed unsigned integer number (negative arguments -result in assertion being generated) to byte array at location Offs and -increments Offs by number of bytes being stored. - - -- ALGLIB -- - Copyright 22.07.2019 by Bochkanov Sergey -*************************************************************************/ -static void dforest_streamuint(ae_vector* buf, - ae_int_t* offs, - ae_int_t v, - ae_state *_state) -{ - ae_int_t v0; - - - ae_assert(v>=0, "Assertion failed", _state); - for(;;) - { - - /* - * Save 7 least significant bits of V, use 8th bit as a flag which - * tells us whether subsequent 7-bit packages will be sent. - */ - v0 = v%128; - if( v>=128 ) - { - v0 = v0+128; - } - buf->ptr.p_ubyte[*(offs)] = (unsigned char)(v0); - *offs = *offs+1; - v = v/128; - if( v==0 ) - { - break; - } - } -} - - -/************************************************************************* -This function reads compressed unsigned integer number from byte array -starting at location Offs and increments Offs by number of bytes being -read. - - -- ALGLIB -- - Copyright 22.07.2019 by Bochkanov Sergey -*************************************************************************/ -static ae_int_t dforest_unstreamuint(ae_vector* buf, - ae_int_t* offs, - ae_state *_state) -{ - ae_int_t v0; - ae_int_t p; - ae_int_t result; - - - result = 0; - p = 1; - for(;;) - { - - /* - * Rad 7 bits of V, use 8th bit as a flag which tells us whether - * subsequent 7-bit packages will be received. - */ - v0 = buf->ptr.p_ubyte[*(offs)]; - *offs = *offs+1; - result = result+v0%128*p; - if( v0<128 ) - { - break; - } - p = p*128; - } - return result; -} - - -/************************************************************************* -This function stores compressed floating point number to byte array at -location Offs and increments Offs by number of bytes being stored. - -Either 8-bit mantissa or 16-bit mantissa is used. The exponent is always -7 bits of exponent + sign. Values which do not fit into exponent range are -truncated to fit. - - -- ALGLIB -- - Copyright 22.07.2019 by Bochkanov Sergey -*************************************************************************/ -static void dforest_streamfloat(ae_vector* buf, - ae_bool usemantissa8, - ae_int_t* offs, - double v, - ae_state *_state) -{ - ae_int_t signbit; - ae_int_t e; - ae_int_t m; - double twopow30; - double twopowm30; - double twopow10; - double twopowm10; - - - ae_assert(ae_isfinite(v, _state), "StreamFloat: V is not finite number", _state); - - /* - * Special case: zero - */ - if( v==0.0 ) - { - if( usemantissa8 ) - { - buf->ptr.p_ubyte[*offs+0] = (unsigned char)(0); - buf->ptr.p_ubyte[*offs+1] = (unsigned char)(0); - *offs = *offs+2; - } - else - { - buf->ptr.p_ubyte[*offs+0] = (unsigned char)(0); - buf->ptr.p_ubyte[*offs+1] = (unsigned char)(0); - buf->ptr.p_ubyte[*offs+2] = (unsigned char)(0); - *offs = *offs+3; - } - return; - } - - /* - * Handle sign - */ - signbit = 0; - if( v<0.0 ) - { - v = -v; - signbit = 128; - } - - /* - * Compute exponent - */ - twopow30 = (double)(1073741824); - twopow10 = (double)(1024); - twopowm30 = 1.0/twopow30; - twopowm10 = 1.0/twopow10; - e = 0; - while(v>=twopow30) - { - v = v*twopowm30; - e = e+30; - } - while(v>=twopow10) - { - v = v*twopowm10; - e = e+10; - } - while(v>=1.0) - { - v = v*0.5; - e = e+1; - } - while(v=0.5&&v<1.0, "StreamFloat: integrity check failed", _state); - - /* - * Handle exponent underflow/overflow - */ - if( e<-63 ) - { - signbit = 0; - e = 0; - v = (double)(0); - } - if( e>63 ) - { - e = 63; - v = 1.0; - } - - /* - * Save to stream - */ - if( usemantissa8 ) - { - m = ae_round(v*256, _state); - if( m==256 ) - { - m = m/2; - e = ae_minint(e+1, 63, _state); - } - buf->ptr.p_ubyte[*offs+0] = (unsigned char)(e+64+signbit); - buf->ptr.p_ubyte[*offs+1] = (unsigned char)(m); - *offs = *offs+2; - } - else - { - m = ae_round(v*65536, _state); - if( m==65536 ) - { - m = m/2; - e = ae_minint(e+1, 63, _state); - } - buf->ptr.p_ubyte[*offs+0] = (unsigned char)(e+64+signbit); - buf->ptr.p_ubyte[*offs+1] = (unsigned char)(m%256); - buf->ptr.p_ubyte[*offs+2] = (unsigned char)(m/256); - *offs = *offs+3; - } -} - - -/************************************************************************* -This function reads compressed floating point number from the byte array -starting from location Offs and increments Offs by number of bytes being -read. - -Either 8-bit mantissa or 16-bit mantissa is used. The exponent is always -7 bits of exponent + sign. Values which do not fit into exponent range are -truncated to fit. - - -- ALGLIB -- - Copyright 22.07.2019 by Bochkanov Sergey -*************************************************************************/ -static double dforest_unstreamfloat(ae_vector* buf, - ae_bool usemantissa8, - ae_int_t* offs, - ae_state *_state) -{ - ae_int_t e; - double v; - double inv256; - double result; - - - - /* - * Read from stream - */ - inv256 = 1.0/256.0; - if( usemantissa8 ) - { - e = buf->ptr.p_ubyte[*offs+0]; - v = buf->ptr.p_ubyte[*offs+1]*inv256; - *offs = *offs+2; - } - else - { - e = buf->ptr.p_ubyte[*offs+0]; - v = (buf->ptr.p_ubyte[*offs+1]*inv256+buf->ptr.p_ubyte[*offs+2])*inv256; - *offs = *offs+3; - } - - /* - * Decode - */ - if( e>128 ) - { - v = -v; - e = e-128; - } - e = e-64; - result = dforest_xfastpow((double)(2), e, _state)*v; - return result; -} - - -/************************************************************************* -Classification error -*************************************************************************/ -static ae_int_t dforest_dfclserror(decisionforest* df, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector x; - ae_vector y; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t tmpi; - ae_int_t result; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - - if( df->nclasses<=1 ) - { - result = 0; - ae_frame_leave(_state); - return result; - } - ae_vector_set_length(&x, df->nvars-1+1, _state); - ae_vector_set_length(&y, df->nclasses-1+1, _state); - result = 0; - for(i=0; i<=npoints-1; i++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,df->nvars-1)); - dfprocess(df, &x, &y, _state); - k = ae_round(xy->ptr.pp_double[i][df->nvars], _state); - tmpi = 0; - for(j=1; j<=df->nclasses-1; j++) - { - if( ae_fp_greater(y.ptr.p_double[j],y.ptr.p_double[tmpi]) ) - { - tmpi = j; - } - } - if( tmpi!=k ) - { - result = result+1; - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Internal subroutine for processing one decision tree stored in uncompressed -format starting at SubtreeRoot (this index points to the header of the tree, -not its first node). First node being processed is located at NodeOffs. -*************************************************************************/ -static void dforest_dfprocessinternaluncompressed(decisionforest* df, - ae_int_t subtreeroot, - ae_int_t nodeoffs, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t idx; - - - ae_assert(df->forestformat==dforest_dfuncompressedv0, "DFProcessInternal: unexpected forest format", _state); - - /* - * Navigate through the tree - */ - for(;;) - { - if( ae_fp_eq(df->trees.ptr.p_double[nodeoffs],(double)(-1)) ) - { - if( df->nclasses==1 ) - { - y->ptr.p_double[0] = y->ptr.p_double[0]+df->trees.ptr.p_double[nodeoffs+1]; - } - else - { - idx = ae_round(df->trees.ptr.p_double[nodeoffs+1], _state); - y->ptr.p_double[idx] = y->ptr.p_double[idx]+1; - } - break; - } - if( x->ptr.p_double[ae_round(df->trees.ptr.p_double[nodeoffs], _state)]trees.ptr.p_double[nodeoffs+1] ) - { - nodeoffs = nodeoffs+dforest_innernodewidth; - } - else - { - nodeoffs = subtreeroot+ae_round(df->trees.ptr.p_double[nodeoffs+2], _state); - } - } -} - - -/************************************************************************* -Internal subroutine for processing one decision tree stored in compressed -format starting at Offs (this index points to the first node of the tree, -right past the header field). -*************************************************************************/ -static void dforest_dfprocessinternalcompressed(decisionforest* df, - ae_int_t offs, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t leafindicator; - ae_int_t varidx; - double splitval; - ae_int_t jmplen; - double leafval; - ae_int_t leafcls; - - - ae_assert(df->forestformat==dforest_dfcompressedv0, "DFProcessInternal: unexpected forest format", _state); - - /* - * Navigate through the tree - */ - leafindicator = 2*df->nvars; - for(;;) - { - - /* - * Read variable idx - */ - varidx = dforest_unstreamuint(&df->trees8, &offs, _state); - - /* - * Is it leaf? - */ - if( varidx==leafindicator ) - { - if( df->nclasses==1 ) - { - - /* - * Regression forest - */ - leafval = dforest_unstreamfloat(&df->trees8, df->usemantissa8, &offs, _state); - y->ptr.p_double[0] = y->ptr.p_double[0]+leafval; - } - else - { - - /* - * Classification forest - */ - leafcls = dforest_unstreamuint(&df->trees8, &offs, _state); - y->ptr.p_double[leafcls] = y->ptr.p_double[leafcls]+1; - } - break; - } - - /* - * Process node - */ - splitval = dforest_unstreamfloat(&df->trees8, df->usemantissa8, &offs, _state); - jmplen = dforest_unstreamuint(&df->trees8, &offs, _state); - if( varidxnvars ) - { - - /* - * The split rule is "if VARptr.p_double[varidx]>=splitval ) - { - offs = offs+jmplen; - } - } - else - { - - /* - * The split rule is "if VAR>=VAL then BRANCH0 else BRANCH1" - */ - varidx = varidx-df->nvars; - if( x->ptr.p_double[varidx]0 ) - { - if( n%2==0 ) - { - result = dforest_xfastpow(r, n/2, _state); - result = result*result; - } - else - { - result = r*dforest_xfastpow(r, n-1, _state); - } - return result; - } - if( n==0 ) - { - result = (double)(1); - } - if( n<0 ) - { - result = dforest_xfastpow(1/r, -n, _state); - } - return result; -} - - -void _decisionforestbuilder_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - decisionforestbuilder *p = (decisionforestbuilder*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->dsdata, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dsrval, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dsival, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->dsmin, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dsmax, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dsbinary, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->dsctotals, 0, DT_INT, _state, make_automatic); - ae_shared_pool_init(&p->workpool, _state, make_automatic); - ae_shared_pool_init(&p->votepool, _state, make_automatic); - ae_shared_pool_init(&p->treepool, _state, make_automatic); - ae_shared_pool_init(&p->treefactory, _state, make_automatic); - ae_matrix_init(&p->iobmatrix, 0, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->varimpshuffle2, 0, DT_INT, _state, make_automatic); -} - - -void _decisionforestbuilder_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - decisionforestbuilder *dst = (decisionforestbuilder*)_dst; - decisionforestbuilder *src = (decisionforestbuilder*)_src; - dst->dstype = src->dstype; - dst->npoints = src->npoints; - dst->nvars = src->nvars; - dst->nclasses = src->nclasses; - ae_vector_init_copy(&dst->dsdata, &src->dsdata, _state, make_automatic); - ae_vector_init_copy(&dst->dsrval, &src->dsrval, _state, make_automatic); - ae_vector_init_copy(&dst->dsival, &src->dsival, _state, make_automatic); - dst->rdfalgo = src->rdfalgo; - dst->rdfratio = src->rdfratio; - dst->rdfvars = src->rdfvars; - dst->rdfglobalseed = src->rdfglobalseed; - dst->rdfsplitstrength = src->rdfsplitstrength; - dst->rdfimportance = src->rdfimportance; - ae_vector_init_copy(&dst->dsmin, &src->dsmin, _state, make_automatic); - ae_vector_init_copy(&dst->dsmax, &src->dsmax, _state, make_automatic); - ae_vector_init_copy(&dst->dsbinary, &src->dsbinary, _state, make_automatic); - dst->dsravg = src->dsravg; - ae_vector_init_copy(&dst->dsctotals, &src->dsctotals, _state, make_automatic); - dst->rdfprogress = src->rdfprogress; - dst->rdftotal = src->rdftotal; - ae_shared_pool_init_copy(&dst->workpool, &src->workpool, _state, make_automatic); - ae_shared_pool_init_copy(&dst->votepool, &src->votepool, _state, make_automatic); - ae_shared_pool_init_copy(&dst->treepool, &src->treepool, _state, make_automatic); - ae_shared_pool_init_copy(&dst->treefactory, &src->treefactory, _state, make_automatic); - dst->neediobmatrix = src->neediobmatrix; - ae_matrix_init_copy(&dst->iobmatrix, &src->iobmatrix, _state, make_automatic); - ae_vector_init_copy(&dst->varimpshuffle2, &src->varimpshuffle2, _state, make_automatic); -} - - -void _decisionforestbuilder_clear(void* _p) -{ - decisionforestbuilder *p = (decisionforestbuilder*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->dsdata); - ae_vector_clear(&p->dsrval); - ae_vector_clear(&p->dsival); - ae_vector_clear(&p->dsmin); - ae_vector_clear(&p->dsmax); - ae_vector_clear(&p->dsbinary); - ae_vector_clear(&p->dsctotals); - ae_shared_pool_clear(&p->workpool); - ae_shared_pool_clear(&p->votepool); - ae_shared_pool_clear(&p->treepool); - ae_shared_pool_clear(&p->treefactory); - ae_matrix_clear(&p->iobmatrix); - ae_vector_clear(&p->varimpshuffle2); -} - - -void _decisionforestbuilder_destroy(void* _p) -{ - decisionforestbuilder *p = (decisionforestbuilder*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->dsdata); - ae_vector_destroy(&p->dsrval); - ae_vector_destroy(&p->dsival); - ae_vector_destroy(&p->dsmin); - ae_vector_destroy(&p->dsmax); - ae_vector_destroy(&p->dsbinary); - ae_vector_destroy(&p->dsctotals); - ae_shared_pool_destroy(&p->workpool); - ae_shared_pool_destroy(&p->votepool); - ae_shared_pool_destroy(&p->treepool); - ae_shared_pool_destroy(&p->treefactory); - ae_matrix_destroy(&p->iobmatrix); - ae_vector_destroy(&p->varimpshuffle2); -} - - -void _dfworkbuf_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - dfworkbuf *p = (dfworkbuf*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->classpriors, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->varpool, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->trnset, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->trnlabelsr, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->trnlabelsi, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->oobset, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->ooblabelsr, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ooblabelsi, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->treebuf, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->curvals, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bestvals, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp0i, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->tmp1i, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->tmp0r, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp1r, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp2r, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp3r, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpnrms2, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->classtotals0, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->classtotals1, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->classtotals01, 0, DT_INT, _state, make_automatic); -} - - -void _dfworkbuf_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - dfworkbuf *dst = (dfworkbuf*)_dst; - dfworkbuf *src = (dfworkbuf*)_src; - ae_vector_init_copy(&dst->classpriors, &src->classpriors, _state, make_automatic); - ae_vector_init_copy(&dst->varpool, &src->varpool, _state, make_automatic); - dst->varpoolsize = src->varpoolsize; - ae_vector_init_copy(&dst->trnset, &src->trnset, _state, make_automatic); - dst->trnsize = src->trnsize; - ae_vector_init_copy(&dst->trnlabelsr, &src->trnlabelsr, _state, make_automatic); - ae_vector_init_copy(&dst->trnlabelsi, &src->trnlabelsi, _state, make_automatic); - ae_vector_init_copy(&dst->oobset, &src->oobset, _state, make_automatic); - dst->oobsize = src->oobsize; - ae_vector_init_copy(&dst->ooblabelsr, &src->ooblabelsr, _state, make_automatic); - ae_vector_init_copy(&dst->ooblabelsi, &src->ooblabelsi, _state, make_automatic); - ae_vector_init_copy(&dst->treebuf, &src->treebuf, _state, make_automatic); - ae_vector_init_copy(&dst->curvals, &src->curvals, _state, make_automatic); - ae_vector_init_copy(&dst->bestvals, &src->bestvals, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0i, &src->tmp0i, _state, make_automatic); - ae_vector_init_copy(&dst->tmp1i, &src->tmp1i, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0r, &src->tmp0r, _state, make_automatic); - ae_vector_init_copy(&dst->tmp1r, &src->tmp1r, _state, make_automatic); - ae_vector_init_copy(&dst->tmp2r, &src->tmp2r, _state, make_automatic); - ae_vector_init_copy(&dst->tmp3r, &src->tmp3r, _state, make_automatic); - ae_vector_init_copy(&dst->tmpnrms2, &src->tmpnrms2, _state, make_automatic); - ae_vector_init_copy(&dst->classtotals0, &src->classtotals0, _state, make_automatic); - ae_vector_init_copy(&dst->classtotals1, &src->classtotals1, _state, make_automatic); - ae_vector_init_copy(&dst->classtotals01, &src->classtotals01, _state, make_automatic); -} - - -void _dfworkbuf_clear(void* _p) -{ - dfworkbuf *p = (dfworkbuf*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->classpriors); - ae_vector_clear(&p->varpool); - ae_vector_clear(&p->trnset); - ae_vector_clear(&p->trnlabelsr); - ae_vector_clear(&p->trnlabelsi); - ae_vector_clear(&p->oobset); - ae_vector_clear(&p->ooblabelsr); - ae_vector_clear(&p->ooblabelsi); - ae_vector_clear(&p->treebuf); - ae_vector_clear(&p->curvals); - ae_vector_clear(&p->bestvals); - ae_vector_clear(&p->tmp0i); - ae_vector_clear(&p->tmp1i); - ae_vector_clear(&p->tmp0r); - ae_vector_clear(&p->tmp1r); - ae_vector_clear(&p->tmp2r); - ae_vector_clear(&p->tmp3r); - ae_vector_clear(&p->tmpnrms2); - ae_vector_clear(&p->classtotals0); - ae_vector_clear(&p->classtotals1); - ae_vector_clear(&p->classtotals01); -} - - -void _dfworkbuf_destroy(void* _p) -{ - dfworkbuf *p = (dfworkbuf*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->classpriors); - ae_vector_destroy(&p->varpool); - ae_vector_destroy(&p->trnset); - ae_vector_destroy(&p->trnlabelsr); - ae_vector_destroy(&p->trnlabelsi); - ae_vector_destroy(&p->oobset); - ae_vector_destroy(&p->ooblabelsr); - ae_vector_destroy(&p->ooblabelsi); - ae_vector_destroy(&p->treebuf); - ae_vector_destroy(&p->curvals); - ae_vector_destroy(&p->bestvals); - ae_vector_destroy(&p->tmp0i); - ae_vector_destroy(&p->tmp1i); - ae_vector_destroy(&p->tmp0r); - ae_vector_destroy(&p->tmp1r); - ae_vector_destroy(&p->tmp2r); - ae_vector_destroy(&p->tmp3r); - ae_vector_destroy(&p->tmpnrms2); - ae_vector_destroy(&p->classtotals0); - ae_vector_destroy(&p->classtotals1); - ae_vector_destroy(&p->classtotals01); -} - - -void _dfvotebuf_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - dfvotebuf *p = (dfvotebuf*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->trntotals, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->oobtotals, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->trncounts, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->oobcounts, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->giniimportances, 0, DT_REAL, _state, make_automatic); -} - - -void _dfvotebuf_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - dfvotebuf *dst = (dfvotebuf*)_dst; - dfvotebuf *src = (dfvotebuf*)_src; - ae_vector_init_copy(&dst->trntotals, &src->trntotals, _state, make_automatic); - ae_vector_init_copy(&dst->oobtotals, &src->oobtotals, _state, make_automatic); - ae_vector_init_copy(&dst->trncounts, &src->trncounts, _state, make_automatic); - ae_vector_init_copy(&dst->oobcounts, &src->oobcounts, _state, make_automatic); - ae_vector_init_copy(&dst->giniimportances, &src->giniimportances, _state, make_automatic); -} - - -void _dfvotebuf_clear(void* _p) -{ - dfvotebuf *p = (dfvotebuf*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->trntotals); - ae_vector_clear(&p->oobtotals); - ae_vector_clear(&p->trncounts); - ae_vector_clear(&p->oobcounts); - ae_vector_clear(&p->giniimportances); -} - - -void _dfvotebuf_destroy(void* _p) -{ - dfvotebuf *p = (dfvotebuf*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->trntotals); - ae_vector_destroy(&p->oobtotals); - ae_vector_destroy(&p->trncounts); - ae_vector_destroy(&p->oobcounts); - ae_vector_destroy(&p->giniimportances); -} - - -void _dfpermimpbuf_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - dfpermimpbuf *p = (dfpermimpbuf*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->losses, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xraw, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xdist, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xcur, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->yv, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->targety, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->startnodes, 0, DT_INT, _state, make_automatic); -} - - -void _dfpermimpbuf_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - dfpermimpbuf *dst = (dfpermimpbuf*)_dst; - dfpermimpbuf *src = (dfpermimpbuf*)_src; - ae_vector_init_copy(&dst->losses, &src->losses, _state, make_automatic); - ae_vector_init_copy(&dst->xraw, &src->xraw, _state, make_automatic); - ae_vector_init_copy(&dst->xdist, &src->xdist, _state, make_automatic); - ae_vector_init_copy(&dst->xcur, &src->xcur, _state, make_automatic); - ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic); - ae_vector_init_copy(&dst->yv, &src->yv, _state, make_automatic); - ae_vector_init_copy(&dst->targety, &src->targety, _state, make_automatic); - ae_vector_init_copy(&dst->startnodes, &src->startnodes, _state, make_automatic); -} - - -void _dfpermimpbuf_clear(void* _p) -{ - dfpermimpbuf *p = (dfpermimpbuf*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->losses); - ae_vector_clear(&p->xraw); - ae_vector_clear(&p->xdist); - ae_vector_clear(&p->xcur); - ae_vector_clear(&p->y); - ae_vector_clear(&p->yv); - ae_vector_clear(&p->targety); - ae_vector_clear(&p->startnodes); -} - - -void _dfpermimpbuf_destroy(void* _p) -{ - dfpermimpbuf *p = (dfpermimpbuf*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->losses); - ae_vector_destroy(&p->xraw); - ae_vector_destroy(&p->xdist); - ae_vector_destroy(&p->xcur); - ae_vector_destroy(&p->y); - ae_vector_destroy(&p->yv); - ae_vector_destroy(&p->targety); - ae_vector_destroy(&p->startnodes); -} - - -void _dftreebuf_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - dftreebuf *p = (dftreebuf*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->treebuf, 0, DT_REAL, _state, make_automatic); -} - - -void _dftreebuf_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - dftreebuf *dst = (dftreebuf*)_dst; - dftreebuf *src = (dftreebuf*)_src; - ae_vector_init_copy(&dst->treebuf, &src->treebuf, _state, make_automatic); - dst->treeidx = src->treeidx; -} - - -void _dftreebuf_clear(void* _p) -{ - dftreebuf *p = (dftreebuf*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->treebuf); -} - - -void _dftreebuf_destroy(void* _p) -{ - dftreebuf *p = (dftreebuf*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->treebuf); -} - - -void _decisionforestbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - decisionforestbuffer *p = (decisionforestbuffer*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic); -} - - -void _decisionforestbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - decisionforestbuffer *dst = (decisionforestbuffer*)_dst; - decisionforestbuffer *src = (decisionforestbuffer*)_src; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic); -} - - -void _decisionforestbuffer_clear(void* _p) -{ - decisionforestbuffer *p = (decisionforestbuffer*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->x); - ae_vector_clear(&p->y); -} - - -void _decisionforestbuffer_destroy(void* _p) -{ - decisionforestbuffer *p = (decisionforestbuffer*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->y); -} - - -void _decisionforest_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - decisionforest *p = (decisionforest*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->trees, 0, DT_REAL, _state, make_automatic); - _decisionforestbuffer_init(&p->buffer, _state, make_automatic); - ae_vector_init(&p->trees8, 0, DT_BYTE, _state, make_automatic); -} - - -void _decisionforest_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - decisionforest *dst = (decisionforest*)_dst; - decisionforest *src = (decisionforest*)_src; - dst->forestformat = src->forestformat; - dst->usemantissa8 = src->usemantissa8; - dst->nvars = src->nvars; - dst->nclasses = src->nclasses; - dst->ntrees = src->ntrees; - dst->bufsize = src->bufsize; - ae_vector_init_copy(&dst->trees, &src->trees, _state, make_automatic); - _decisionforestbuffer_init_copy(&dst->buffer, &src->buffer, _state, make_automatic); - ae_vector_init_copy(&dst->trees8, &src->trees8, _state, make_automatic); -} - - -void _decisionforest_clear(void* _p) -{ - decisionforest *p = (decisionforest*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->trees); - _decisionforestbuffer_clear(&p->buffer); - ae_vector_clear(&p->trees8); -} - - -void _decisionforest_destroy(void* _p) -{ - decisionforest *p = (decisionforest*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->trees); - _decisionforestbuffer_destroy(&p->buffer); - ae_vector_destroy(&p->trees8); -} - - -void _dfreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - dfreport *p = (dfreport*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->topvars, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->varimportances, 0, DT_REAL, _state, make_automatic); -} - - -void _dfreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - dfreport *dst = (dfreport*)_dst; - dfreport *src = (dfreport*)_src; - dst->relclserror = src->relclserror; - dst->avgce = src->avgce; - dst->rmserror = src->rmserror; - dst->avgerror = src->avgerror; - dst->avgrelerror = src->avgrelerror; - dst->oobrelclserror = src->oobrelclserror; - dst->oobavgce = src->oobavgce; - dst->oobrmserror = src->oobrmserror; - dst->oobavgerror = src->oobavgerror; - dst->oobavgrelerror = src->oobavgrelerror; - ae_vector_init_copy(&dst->topvars, &src->topvars, _state, make_automatic); - ae_vector_init_copy(&dst->varimportances, &src->varimportances, _state, make_automatic); -} - - -void _dfreport_clear(void* _p) -{ - dfreport *p = (dfreport*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->topvars); - ae_vector_clear(&p->varimportances); -} - - -void _dfreport_destroy(void* _p) -{ - dfreport *p = (dfreport*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->topvars); - ae_vector_destroy(&p->varimportances); -} - - -void _dfinternalbuffers_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - dfinternalbuffers *p = (dfinternalbuffers*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->treebuf, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->idxbuf, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->tmpbufr, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpbufr2, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpbufi, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->classibuf, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->sortrbuf, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->sortrbuf2, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->sortibuf, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->varpool, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->evsbin, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->evssplits, 0, DT_REAL, _state, make_automatic); -} - - -void _dfinternalbuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - dfinternalbuffers *dst = (dfinternalbuffers*)_dst; - dfinternalbuffers *src = (dfinternalbuffers*)_src; - ae_vector_init_copy(&dst->treebuf, &src->treebuf, _state, make_automatic); - ae_vector_init_copy(&dst->idxbuf, &src->idxbuf, _state, make_automatic); - ae_vector_init_copy(&dst->tmpbufr, &src->tmpbufr, _state, make_automatic); - ae_vector_init_copy(&dst->tmpbufr2, &src->tmpbufr2, _state, make_automatic); - ae_vector_init_copy(&dst->tmpbufi, &src->tmpbufi, _state, make_automatic); - ae_vector_init_copy(&dst->classibuf, &src->classibuf, _state, make_automatic); - ae_vector_init_copy(&dst->sortrbuf, &src->sortrbuf, _state, make_automatic); - ae_vector_init_copy(&dst->sortrbuf2, &src->sortrbuf2, _state, make_automatic); - ae_vector_init_copy(&dst->sortibuf, &src->sortibuf, _state, make_automatic); - ae_vector_init_copy(&dst->varpool, &src->varpool, _state, make_automatic); - ae_vector_init_copy(&dst->evsbin, &src->evsbin, _state, make_automatic); - ae_vector_init_copy(&dst->evssplits, &src->evssplits, _state, make_automatic); -} - - -void _dfinternalbuffers_clear(void* _p) -{ - dfinternalbuffers *p = (dfinternalbuffers*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->treebuf); - ae_vector_clear(&p->idxbuf); - ae_vector_clear(&p->tmpbufr); - ae_vector_clear(&p->tmpbufr2); - ae_vector_clear(&p->tmpbufi); - ae_vector_clear(&p->classibuf); - ae_vector_clear(&p->sortrbuf); - ae_vector_clear(&p->sortrbuf2); - ae_vector_clear(&p->sortibuf); - ae_vector_clear(&p->varpool); - ae_vector_clear(&p->evsbin); - ae_vector_clear(&p->evssplits); -} - - -void _dfinternalbuffers_destroy(void* _p) -{ - dfinternalbuffers *p = (dfinternalbuffers*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->treebuf); - ae_vector_destroy(&p->idxbuf); - ae_vector_destroy(&p->tmpbufr); - ae_vector_destroy(&p->tmpbufr2); - ae_vector_destroy(&p->tmpbufi); - ae_vector_destroy(&p->classibuf); - ae_vector_destroy(&p->sortrbuf); - ae_vector_destroy(&p->sortrbuf2); - ae_vector_destroy(&p->sortibuf); - ae_vector_destroy(&p->varpool); - ae_vector_destroy(&p->evsbin); - ae_vector_destroy(&p->evssplits); -} - - -#endif -#if defined(AE_COMPILE_KNN) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function creates buffer structure which can be used to perform -parallel KNN requests. - -KNN subpackage provides two sets of computing functions - ones which use -internal buffer of KNN model (these functions are single-threaded because -they use same buffer, which can not shared between threads), and ones -which use external buffer. - -This function is used to initialize external buffer. - -INPUT PARAMETERS - Model - KNN model which is associated with newly created buffer - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: buffer object should be used only with model which was used to - initialize buffer. Any attempt to use buffer with different - object is dangerous - you may get integrity check failure - (exception) because sizes of internal arrays do not fit to - dimensions of the model structure. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knncreatebuffer(knnmodel* model, knnbuffer* buf, ae_state *_state) -{ - - _knnbuffer_clear(buf); - - if( !model->isdummy ) - { - kdtreecreaterequestbuffer(&model->tree, &buf->treebuf, _state); - } - ae_vector_set_length(&buf->x, model->nvars, _state); - ae_vector_set_length(&buf->y, model->nout, _state); -} - - -/************************************************************************* -This subroutine creates KNNBuilder object which is used to train KNN models. - -By default, new builder stores empty dataset and some reasonable default -settings. At the very least, you should specify dataset prior to building -KNN model. You can also tweak settings of the model construction algorithm -(recommended, although default settings should work well). - -Following actions are mandatory: -* calling knnbuildersetdataset() to specify dataset -* calling knnbuilderbuildknnmodel() to build KNN model using current - dataset and default settings - -Additionally, you may call: -* knnbuildersetnorm() to change norm being used - -INPUT PARAMETERS: - none - -OUTPUT PARAMETERS: - S - KNN builder - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnbuildercreate(knnbuilder* s, ae_state *_state) -{ - - _knnbuilder_clear(s); - - - /* - * Empty dataset - */ - s->dstype = -1; - s->npoints = 0; - s->nvars = 0; - s->iscls = ae_false; - s->nout = 1; - - /* - * Default training settings - */ - s->knnnrm = 2; -} - - -/************************************************************************* -Specifies regression problem (one or more continuous output variables are -predicted). There also exists "classification" version of this function. - -This subroutine adds dense dataset to the internal storage of the builder -object. Specifying your dataset in the dense format means that the dense -version of the KNN construction algorithm will be invoked. - -INPUT PARAMETERS: - S - KNN builder object - XY - array[NPoints,NVars+NOut] (note: actual size can be - larger, only leading part is used anyway), dataset: - * first NVars elements of each row store values of the - independent variables - * next NOut elements store values of the dependent - variables - NPoints - number of rows in the dataset, NPoints>=1 - NVars - number of independent variables, NVars>=1 - NOut - number of dependent variables, NOut>=1 - -OUTPUT PARAMETERS: - S - KNN builder - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnbuildersetdatasetreg(knnbuilder* s, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nout, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - - /* - * Check parameters - */ - ae_assert(npoints>=1, "knnbuildersetdatasetreg: npoints<1", _state); - ae_assert(nvars>=1, "knnbuildersetdatasetreg: nvars<1", _state); - ae_assert(nout>=1, "knnbuildersetdatasetreg: nout<1", _state); - ae_assert(xy->rows>=npoints, "knnbuildersetdatasetreg: rows(xy)cols>=nvars+nout, "knnbuildersetdatasetreg: cols(xy)dstype = 0; - s->iscls = ae_false; - s->npoints = npoints; - s->nvars = nvars; - s->nout = nout; - rmatrixsetlengthatleast(&s->dsdata, npoints, nvars, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - s->dsdata.ptr.pp_double[i][j] = xy->ptr.pp_double[i][j]; - } - } - rvectorsetlengthatleast(&s->dsrval, npoints*nout, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nout-1; j++) - { - s->dsrval.ptr.p_double[i*nout+j] = xy->ptr.pp_double[i][nvars+j]; - } - } -} - - -/************************************************************************* -Specifies classification problem (two or more classes are predicted). -There also exists "regression" version of this function. - -This subroutine adds dense dataset to the internal storage of the builder -object. Specifying your dataset in the dense format means that the dense -version of the KNN construction algorithm will be invoked. - -INPUT PARAMETERS: - S - KNN builder object - XY - array[NPoints,NVars+1] (note: actual size can be - larger, only leading part is used anyway), dataset: - * first NVars elements of each row store values of the - independent variables - * next element stores class index, in [0,NClasses) - NPoints - number of rows in the dataset, NPoints>=1 - NVars - number of independent variables, NVars>=1 - NClasses - number of classes, NClasses>=2 - -OUTPUT PARAMETERS: - S - KNN builder - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnbuildersetdatasetcls(knnbuilder* s, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - - /* - * Check parameters - */ - ae_assert(npoints>=1, "knnbuildersetdatasetcls: npoints<1", _state); - ae_assert(nvars>=1, "knnbuildersetdatasetcls: nvars<1", _state); - ae_assert(nclasses>=2, "knnbuildersetdatasetcls: nclasses<2", _state); - ae_assert(xy->rows>=npoints, "knnbuildersetdatasetcls: rows(xy)cols>=nvars+1, "knnbuildersetdatasetcls: cols(xy)ptr.pp_double[i][nvars], _state); - ae_assert(j>=0&&jiscls = ae_true; - s->dstype = 0; - s->npoints = npoints; - s->nvars = nvars; - s->nout = nclasses; - rmatrixsetlengthatleast(&s->dsdata, npoints, nvars, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - s->dsdata.ptr.pp_double[i][j] = xy->ptr.pp_double[i][j]; - } - } - ivectorsetlengthatleast(&s->dsival, npoints, _state); - for(i=0; i<=npoints-1; i++) - { - s->dsival.ptr.p_int[i] = ae_round(xy->ptr.pp_double[i][nvars], _state); - } -} - - -/************************************************************************* -This function sets norm type used for neighbor search. - -INPUT PARAMETERS: - S - decision forest builder object - NormType - norm type: - * 0 inf-norm - * 1 1-norm - * 2 Euclidean norm (default) - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnbuildersetnorm(knnbuilder* s, ae_int_t nrmtype, ae_state *_state) -{ - - - ae_assert((nrmtype==0||nrmtype==1)||nrmtype==2, "knnbuildersetnorm: unexpected norm type", _state); - s->knnnrm = nrmtype; -} - - -/************************************************************************* -This subroutine builds KNN model according to current settings, using -dataset internally stored in the builder object. - -The model being built performs inference using Eps-approximate K nearest -neighbors search algorithm, with: -* K=1, Eps=0 corresponding to the "nearest neighbor algorithm" -* K>1, Eps=0 corresponding to the "K nearest neighbors algorithm" -* K>=1, Eps>0 corresponding to "approximate nearest neighbors algorithm" - -An approximate KNN is a good option for high-dimensional datasets (exact -KNN works slowly when dimensions count grows). - -An ALGLIB implementation of kd-trees is used to perform k-nn searches. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - KNN builder object - K - number of neighbors to search for, K>=1 - Eps - approximation factor: - * Eps=0 means that exact kNN search is performed - * Eps>0 means that (1+Eps)-approximate search is performed - -OUTPUT PARAMETERS: - Model - KNN model - Rep - report - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnbuilderbuildknnmodel(knnbuilder* s, - ae_int_t k, - double eps, - knnmodel* model, - knnreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t nvars; - ae_int_t nout; - ae_int_t npoints; - ae_bool iscls; - ae_matrix xy; - ae_vector tags; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&tags, 0, sizeof(tags)); - _knnmodel_clear(model); - _knnreport_clear(rep); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tags, 0, DT_INT, _state, ae_true); - - npoints = s->npoints; - nvars = s->nvars; - nout = s->nout; - iscls = s->iscls; - - /* - * Check settings - */ - ae_assert(k>=1, "knnbuilderbuildknnmodel: k<1", _state); - ae_assert(ae_isfinite(eps, _state)&&ae_fp_greater_eq(eps,(double)(0)), "knnbuilderbuildknnmodel: eps<0", _state); - - /* - * Prepare output - */ - knn_clearreport(rep, _state); - model->nvars = nvars; - model->nout = nout; - model->iscls = iscls; - model->k = k; - model->eps = eps; - model->isdummy = ae_false; - - /* - * Quick exit for empty dataset - */ - if( s->dstype==-1 ) - { - model->isdummy = ae_true; - ae_frame_leave(_state); - return; - } - - /* - * Build kd-tree - */ - if( iscls ) - { - ae_matrix_set_length(&xy, npoints, nvars+1, _state); - ae_vector_set_length(&tags, npoints, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - xy.ptr.pp_double[i][j] = s->dsdata.ptr.pp_double[i][j]; - } - xy.ptr.pp_double[i][nvars] = (double)(s->dsival.ptr.p_int[i]); - tags.ptr.p_int[i] = s->dsival.ptr.p_int[i]; - } - kdtreebuildtagged(&xy, &tags, npoints, nvars, 0, s->knnnrm, &model->tree, _state); - } - else - { - ae_matrix_set_length(&xy, npoints, nvars+nout, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - xy.ptr.pp_double[i][j] = s->dsdata.ptr.pp_double[i][j]; - } - for(j=0; j<=nout-1; j++) - { - xy.ptr.pp_double[i][nvars+j] = s->dsrval.ptr.p_double[i*nout+j]; - } - } - kdtreebuild(&xy, npoints, nvars, nout, s->knnnrm, &model->tree, _state); - } - - /* - * Build buffer - */ - knncreatebuffer(model, &model->buffer, _state); - - /* - * Report - */ - knnallerrors(model, &xy, npoints, rep, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Changing search settings of KNN model. - -K and EPS parameters of KNN (AKNN) search are specified during model -construction. However, plain KNN algorithm with Euclidean distance allows -you to change them at any moment. - -NOTE: future versions of KNN model may support advanced versions of KNN, - such as NCA or LMNN. It is possible that such algorithms won't allow - you to change search settings on the fly. If you call this function - for an algorithm which does not support on-the-fly changes, it will - throw an exception. - -INPUT PARAMETERS: - Model - KNN model - K - K>=1, neighbors count - EPS - accuracy of the EPS-approximate NN search. Set to 0.0, if - you want to perform "classic" KNN search. Specify larger - values if you need to speed-up high-dimensional KNN - queries. - -OUTPUT PARAMETERS: - nothing on success, exception on failure - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnrewritekeps(knnmodel* model, - ae_int_t k, - double eps, - ae_state *_state) -{ - - - ae_assert(k>=1, "knnrewritekeps: k<1", _state); - ae_assert(ae_isfinite(eps, _state)&&ae_fp_greater_eq(eps,(double)(0)), "knnrewritekeps: eps<0", _state); - model->k = k; - model->eps = eps; -} - - -/************************************************************************* -Inference using KNN model. - -See also knnprocess0(), knnprocessi() and knnclassify() for options with a -bit more convenient interface. - -IMPORTANT: this function is thread-unsafe and modifies internal structures - of the model! You can not use same model object for parallel - evaluation from several threads. - - Use knntsprocess() with independent thread-local buffers, if - you need thread-safe evaluation. - -INPUT PARAMETERS: - Model - KNN model - X - input vector, array[0..NVars-1]. - Y - possible preallocated buffer. Reused if long enough. - -OUTPUT PARAMETERS: - Y - result. Regression estimate when solving regression task, - vector of posterior probabilities for classification task. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnprocess(knnmodel* model, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - - - knntsprocess(model, &model->buffer, x, y, _state); -} - - -/************************************************************************* -This function returns first component of the inferred vector (i.e. one -with index #0). - -It is a convenience wrapper for knnprocess() intended for either: -* 1-dimensional regression problems -* 2-class classification problems - -In the former case this function returns inference result as scalar, which -is definitely more convenient that wrapping it as vector. In the latter -case it returns probability of object belonging to class #0. - -If you call it for anything different from two cases above, it will work -as defined, i.e. return y[0], although it is of less use in such cases. - -IMPORTANT: this function is thread-unsafe and modifies internal structures - of the model! You can not use same model object for parallel - evaluation from several threads. - - Use knntsprocess() with independent thread-local buffers, if - you need thread-safe evaluation. - -INPUT PARAMETERS: - Model - KNN model - X - input vector, array[0..NVars-1]. - -RESULT: - Y[0] - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double knnprocess0(knnmodel* model, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t i; - ae_int_t nvars; - double result; - - - nvars = model->nvars; - for(i=0; i<=nvars-1; i++) - { - model->buffer.x.ptr.p_double[i] = x->ptr.p_double[i]; - } - knn_processinternal(model, &model->buffer, _state); - result = model->buffer.y.ptr.p_double[0]; - return result; -} - - -/************************************************************************* -This function returns most probable class number for an input X. It is -same as calling knnprocess(model,x,y), then determining i=argmax(y[i]) and -returning i. - -A class number in [0,NOut) range in returned for classification problems, --1 is returned when this function is called for regression problems. - -IMPORTANT: this function is thread-unsafe and modifies internal structures - of the model! You can not use same model object for parallel - evaluation from several threads. - - Use knntsprocess() with independent thread-local buffers, if - you need thread-safe evaluation. - -INPUT PARAMETERS: - Model - KNN model - X - input vector, array[0..NVars-1]. - -RESULT: - class number, -1 for regression tasks - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -ae_int_t knnclassify(knnmodel* model, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t i; - ae_int_t nvars; - ae_int_t nout; - ae_int_t result; - - - if( !model->iscls ) - { - result = -1; - return result; - } - nvars = model->nvars; - nout = model->nout; - for(i=0; i<=nvars-1; i++) - { - model->buffer.x.ptr.p_double[i] = x->ptr.p_double[i]; - } - knn_processinternal(model, &model->buffer, _state); - result = 0; - for(i=1; i<=nout-1; i++) - { - if( model->buffer.y.ptr.p_double[i]>model->buffer.y.ptr.p_double[result] ) - { - result = i; - } - } - return result; -} - - -/************************************************************************* -'interactive' variant of knnprocess() for languages like Python which -support constructs like "y = knnprocessi(model,x)" and interactive mode of -the interpreter. - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - -IMPORTANT: this function is thread-unsafe and may modify internal - structures of the model! You can not use same model object for - parallel evaluation from several threads. - - Use knntsprocess() with independent thread-local buffers if - you need thread-safe evaluation. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnprocessi(knnmodel* model, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - - ae_vector_clear(y); - - knnprocess(model, x, y, _state); -} - - -/************************************************************************* -Thread-safe procesing using external buffer for temporaries. - -This function is thread-safe (i.e . you can use same KNN model from -multiple threads) as long as you use different buffer objects for different -threads. - -INPUT PARAMETERS: - Model - KNN model - Buf - buffer object, must be allocated specifically for this - model with knncreatebuffer(). - X - input vector, array[NVars] - -OUTPUT PARAMETERS: - Y - result, array[NOut]. Regression estimate when solving - regression task, vector of posterior probabilities for - a classification task. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knntsprocess(knnmodel* model, - knnbuffer* buf, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - ae_int_t nvars; - ae_int_t nout; - - - nvars = model->nvars; - nout = model->nout; - for(i=0; i<=nvars-1; i++) - { - buf->x.ptr.p_double[i] = x->ptr.p_double[i]; - } - knn_processinternal(model, buf, _state); - if( y->cntptr.p_double[i] = buf->y.ptr.p_double[i]; - } -} - - -/************************************************************************* -Relative classification error on the test set - -INPUT PARAMETERS: - Model - KNN model - XY - test set - NPoints - test set size - -RESULT: - percent of incorrectly classified cases. - Zero if model solves regression task. - -NOTE: if you need several different kinds of error metrics, it is better - to use knnallerrors() which computes all error metric with just one - pass over dataset. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double knnrelclserror(knnmodel* model, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_frame _frame_block; - knnreport rep; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&rep, 0, sizeof(rep)); - _knnreport_init(&rep, _state, ae_true); - - knnallerrors(model, xy, npoints, &rep, _state); - result = rep.relclserror; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Average cross-entropy (in bits per element) on the test set - -INPUT PARAMETERS: - Model - KNN model - XY - test set - NPoints - test set size - -RESULT: - CrossEntropy/NPoints. - Zero if model solves regression task. - -NOTE: the cross-entropy metric is too unstable when used to evaluate KNN - models (such models can report exactly zero probabilities), so we - do not recommend using it. - -NOTE: if you need several different kinds of error metrics, it is better - to use knnallerrors() which computes all error metric with just one - pass over dataset. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double knnavgce(knnmodel* model, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_frame _frame_block; - knnreport rep; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&rep, 0, sizeof(rep)); - _knnreport_init(&rep, _state, ae_true); - - knnallerrors(model, xy, npoints, &rep, _state); - result = rep.avgce; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -RMS error on the test set. - -Its meaning for regression task is obvious. As for classification problems, -RMS error means error when estimating posterior probabilities. - -INPUT PARAMETERS: - Model - KNN model - XY - test set - NPoints - test set size - -RESULT: - root mean square error. - -NOTE: if you need several different kinds of error metrics, it is better - to use knnallerrors() which computes all error metric with just one - pass over dataset. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double knnrmserror(knnmodel* model, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_frame _frame_block; - knnreport rep; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&rep, 0, sizeof(rep)); - _knnreport_init(&rep, _state, ae_true); - - knnallerrors(model, xy, npoints, &rep, _state); - result = rep.rmserror; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Average error on the test set - -Its meaning for regression task is obvious. As for classification problems, -average error means error when estimating posterior probabilities. - -INPUT PARAMETERS: - Model - KNN model - XY - test set - NPoints - test set size - -RESULT: - average error - -NOTE: if you need several different kinds of error metrics, it is better - to use knnallerrors() which computes all error metric with just one - pass over dataset. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double knnavgerror(knnmodel* model, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_frame _frame_block; - knnreport rep; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&rep, 0, sizeof(rep)); - _knnreport_init(&rep, _state, ae_true); - - knnallerrors(model, xy, npoints, &rep, _state); - result = rep.avgerror; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Average relative error on the test set - -Its meaning for regression task is obvious. As for classification problems, -average relative error means error when estimating posterior probabilities. - -INPUT PARAMETERS: - Model - KNN model - XY - test set - NPoints - test set size - -RESULT: - average relative error - -NOTE: if you need several different kinds of error metrics, it is better - to use knnallerrors() which computes all error metric with just one - pass over dataset. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double knnavgrelerror(knnmodel* model, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state) -{ - ae_frame _frame_block; - knnreport rep; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&rep, 0, sizeof(rep)); - _knnreport_init(&rep, _state, ae_true); - - knnallerrors(model, xy, npoints, &rep, _state); - result = rep.avgrelerror; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Calculates all kinds of errors for the model in one call. - -INPUT PARAMETERS: - Model - KNN model - XY - test set: - * one row per point - * first NVars columns store independent variables - * depending on problem type: - * next column stores class number in [0,NClasses) - for - classification problems - * next NOut columns store dependent variables - for - regression problems - NPoints - test set size, NPoints>=0 - -OUTPUT PARAMETERS: - Rep - following fields are loaded with errors for both regression - and classification models: - * rep.rmserror - RMS error for the output - * rep.avgerror - average error - * rep.avgrelerror - average relative error - following fields are set only for classification models, - zero for regression ones: - * relclserror - relative classification error, in [0,1] - * avgce - average cross-entropy in bits per dataset entry - -NOTE: the cross-entropy metric is too unstable when used to evaluate KNN - models (such models can report exactly zero probabilities), so we - do not recommend using it. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnallerrors(knnmodel* model, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - knnreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - knnbuffer buf; - ae_vector desiredy; - ae_vector errbuf; - ae_int_t nvars; - ae_int_t nout; - ae_int_t ny; - ae_bool iscls; - ae_int_t i; - ae_int_t j; - - ae_frame_make(_state, &_frame_block); - memset(&buf, 0, sizeof(buf)); - memset(&desiredy, 0, sizeof(desiredy)); - memset(&errbuf, 0, sizeof(errbuf)); - _knnreport_clear(rep); - _knnbuffer_init(&buf, _state, ae_true); - ae_vector_init(&desiredy, 0, DT_REAL, _state, ae_true); - ae_vector_init(&errbuf, 0, DT_REAL, _state, ae_true); - - nvars = model->nvars; - nout = model->nout; - iscls = model->iscls; - if( iscls ) - { - ny = 1; - } - else - { - ny = nout; - } - - /* - * Check input - */ - ae_assert(npoints>=0, "knnallerrors: npoints<0", _state); - ae_assert(xy->rows>=npoints, "knnallerrors: rows(xy)cols>=nvars+ny, "knnallerrors: cols(xy)isdummy||npoints==0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Process using local buffer - */ - knncreatebuffer(model, &buf, _state); - if( iscls ) - { - dserrallocate(nout, &errbuf, _state); - } - else - { - dserrallocate(-nout, &errbuf, _state); - } - ae_vector_set_length(&desiredy, ny, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - buf.x.ptr.p_double[j] = xy->ptr.pp_double[i][j]; - } - if( iscls ) - { - j = ae_round(xy->ptr.pp_double[i][nvars], _state); - ae_assert(j>=0&&jptr.pp_double[i][nvars+j]; - } - } - knn_processinternal(model, &buf, _state); - dserraccumulate(&errbuf, &buf.y, &desiredy, _state); - } - dserrfinish(&errbuf, _state); - - /* - * Extract results - */ - if( iscls ) - { - rep->relclserror = errbuf.ptr.p_double[0]; - rep->avgce = errbuf.ptr.p_double[1]; - } - rep->rmserror = errbuf.ptr.p_double[2]; - rep->avgerror = errbuf.ptr.p_double[3]; - rep->avgrelerror = errbuf.ptr.p_double[4]; - ae_frame_leave(_state); -} - - -/************************************************************************* -Serializer: allocation - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnalloc(ae_serializer* s, knnmodel* model, ae_state *_state) -{ - - - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - if( !model->isdummy ) - { - kdtreealloc(s, &model->tree, _state); - } -} - - -/************************************************************************* -Serializer: serialization - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnserialize(ae_serializer* s, knnmodel* model, ae_state *_state) -{ - - - ae_serializer_serialize_int(s, getknnserializationcode(_state), _state); - ae_serializer_serialize_int(s, knn_knnfirstversion, _state); - ae_serializer_serialize_int(s, model->nvars, _state); - ae_serializer_serialize_int(s, model->nout, _state); - ae_serializer_serialize_int(s, model->k, _state); - ae_serializer_serialize_double(s, model->eps, _state); - ae_serializer_serialize_bool(s, model->iscls, _state); - ae_serializer_serialize_bool(s, model->isdummy, _state); - if( !model->isdummy ) - { - kdtreeserialize(s, &model->tree, _state); - } -} - - -/************************************************************************* -Serializer: unserialization - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnunserialize(ae_serializer* s, knnmodel* model, ae_state *_state) -{ - ae_int_t i0; - ae_int_t i1; - - _knnmodel_clear(model); - - - /* - * check correctness of header - */ - ae_serializer_unserialize_int(s, &i0, _state); - ae_assert(i0==getknnserializationcode(_state), "KNNUnserialize: stream header corrupted", _state); - ae_serializer_unserialize_int(s, &i1, _state); - ae_assert(i1==knn_knnfirstversion, "KNNUnserialize: stream header corrupted", _state); - - /* - * Unserialize data - */ - ae_serializer_unserialize_int(s, &model->nvars, _state); - ae_serializer_unserialize_int(s, &model->nout, _state); - ae_serializer_unserialize_int(s, &model->k, _state); - ae_serializer_unserialize_double(s, &model->eps, _state); - ae_serializer_unserialize_bool(s, &model->iscls, _state); - ae_serializer_unserialize_bool(s, &model->isdummy, _state); - if( !model->isdummy ) - { - kdtreeunserialize(s, &model->tree, _state); - } - - /* - * Prepare local buffer - */ - knncreatebuffer(model, &model->buffer, _state); -} - - -/************************************************************************* -Sets report fields to their default values - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -static void knn_clearreport(knnreport* rep, ae_state *_state) -{ - - - rep->relclserror = (double)(0); - rep->avgce = (double)(0); - rep->rmserror = (double)(0); - rep->avgerror = (double)(0); - rep->avgrelerror = (double)(0); -} - - -/************************************************************************* -This function processes buf.X and stores result to buf.Y - -INPUT PARAMETERS - Model - KNN model - Buf - processing buffer. - - -IMPORTANT: buffer object should be used only with model which was used to - initialize buffer. Any attempt to use buffer with different - object is dangerous - you may get integrity check failure - (exception) because sizes of internal arrays do not fit to - dimensions of the model structure. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -static void knn_processinternal(knnmodel* model, - knnbuffer* buf, - ae_state *_state) -{ - ae_int_t nvars; - ae_int_t nout; - ae_bool iscls; - ae_int_t nncnt; - ae_int_t i; - ae_int_t j; - double v; - - - nvars = model->nvars; - nout = model->nout; - iscls = model->iscls; - - /* - * Quick exit if needed - */ - if( model->isdummy ) - { - for(i=0; i<=nout-1; i++) - { - buf->y.ptr.p_double[i] = (double)(0); - } - return; - } - - /* - * Perform request, average results - */ - for(i=0; i<=nout-1; i++) - { - buf->y.ptr.p_double[i] = (double)(0); - } - nncnt = kdtreetsqueryaknn(&model->tree, &buf->treebuf, &buf->x, model->k, ae_true, model->eps, _state); - v = 1/coalesce((double)(nncnt), (double)(1), _state); - if( iscls ) - { - kdtreetsqueryresultstags(&model->tree, &buf->treebuf, &buf->tags, _state); - for(i=0; i<=nncnt-1; i++) - { - j = buf->tags.ptr.p_int[i]; - buf->y.ptr.p_double[j] = buf->y.ptr.p_double[j]+v; - } - } - else - { - kdtreetsqueryresultsxy(&model->tree, &buf->treebuf, &buf->xy, _state); - for(i=0; i<=nncnt-1; i++) - { - for(j=0; j<=nout-1; j++) - { - buf->y.ptr.p_double[j] = buf->y.ptr.p_double[j]+v*buf->xy.ptr.pp_double[i][nvars+j]; - } - } - } -} - - -void _knnbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - knnbuffer *p = (knnbuffer*)_p; - ae_touch_ptr((void*)p); - _kdtreerequestbuffer_init(&p->treebuf, _state, make_automatic); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tags, 0, DT_INT, _state, make_automatic); - ae_matrix_init(&p->xy, 0, 0, DT_REAL, _state, make_automatic); -} - - -void _knnbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - knnbuffer *dst = (knnbuffer*)_dst; - knnbuffer *src = (knnbuffer*)_src; - _kdtreerequestbuffer_init_copy(&dst->treebuf, &src->treebuf, _state, make_automatic); - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic); - ae_vector_init_copy(&dst->tags, &src->tags, _state, make_automatic); - ae_matrix_init_copy(&dst->xy, &src->xy, _state, make_automatic); -} - - -void _knnbuffer_clear(void* _p) -{ - knnbuffer *p = (knnbuffer*)_p; - ae_touch_ptr((void*)p); - _kdtreerequestbuffer_clear(&p->treebuf); - ae_vector_clear(&p->x); - ae_vector_clear(&p->y); - ae_vector_clear(&p->tags); - ae_matrix_clear(&p->xy); -} - - -void _knnbuffer_destroy(void* _p) -{ - knnbuffer *p = (knnbuffer*)_p; - ae_touch_ptr((void*)p); - _kdtreerequestbuffer_destroy(&p->treebuf); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->y); - ae_vector_destroy(&p->tags); - ae_matrix_destroy(&p->xy); -} - - -void _knnbuilder_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - knnbuilder *p = (knnbuilder*)_p; - ae_touch_ptr((void*)p); - ae_matrix_init(&p->dsdata, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dsrval, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dsival, 0, DT_INT, _state, make_automatic); -} - - -void _knnbuilder_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - knnbuilder *dst = (knnbuilder*)_dst; - knnbuilder *src = (knnbuilder*)_src; - dst->dstype = src->dstype; - dst->npoints = src->npoints; - dst->nvars = src->nvars; - dst->iscls = src->iscls; - dst->nout = src->nout; - ae_matrix_init_copy(&dst->dsdata, &src->dsdata, _state, make_automatic); - ae_vector_init_copy(&dst->dsrval, &src->dsrval, _state, make_automatic); - ae_vector_init_copy(&dst->dsival, &src->dsival, _state, make_automatic); - dst->knnnrm = src->knnnrm; -} - - -void _knnbuilder_clear(void* _p) -{ - knnbuilder *p = (knnbuilder*)_p; - ae_touch_ptr((void*)p); - ae_matrix_clear(&p->dsdata); - ae_vector_clear(&p->dsrval); - ae_vector_clear(&p->dsival); -} - - -void _knnbuilder_destroy(void* _p) -{ - knnbuilder *p = (knnbuilder*)_p; - ae_touch_ptr((void*)p); - ae_matrix_destroy(&p->dsdata); - ae_vector_destroy(&p->dsrval); - ae_vector_destroy(&p->dsival); -} - - -void _knnmodel_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - knnmodel *p = (knnmodel*)_p; - ae_touch_ptr((void*)p); - _kdtree_init(&p->tree, _state, make_automatic); - _knnbuffer_init(&p->buffer, _state, make_automatic); -} - - -void _knnmodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - knnmodel *dst = (knnmodel*)_dst; - knnmodel *src = (knnmodel*)_src; - dst->nvars = src->nvars; - dst->nout = src->nout; - dst->k = src->k; - dst->eps = src->eps; - dst->iscls = src->iscls; - dst->isdummy = src->isdummy; - _kdtree_init_copy(&dst->tree, &src->tree, _state, make_automatic); - _knnbuffer_init_copy(&dst->buffer, &src->buffer, _state, make_automatic); -} - - -void _knnmodel_clear(void* _p) -{ - knnmodel *p = (knnmodel*)_p; - ae_touch_ptr((void*)p); - _kdtree_clear(&p->tree); - _knnbuffer_clear(&p->buffer); -} - - -void _knnmodel_destroy(void* _p) -{ - knnmodel *p = (knnmodel*)_p; - ae_touch_ptr((void*)p); - _kdtree_destroy(&p->tree); - _knnbuffer_destroy(&p->buffer); -} - - -void _knnreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - knnreport *p = (knnreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _knnreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - knnreport *dst = (knnreport*)_dst; - knnreport *src = (knnreport*)_src; - dst->relclserror = src->relclserror; - dst->avgce = src->avgce; - dst->rmserror = src->rmserror; - dst->avgerror = src->avgerror; - dst->avgrelerror = src->avgrelerror; -} - - -void _knnreport_clear(void* _p) -{ - knnreport *p = (knnreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _knnreport_destroy(void* _p) -{ - knnreport *p = (knnreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_DATACOMP) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -k-means++ clusterization. -Backward compatibility function, we recommend to use CLUSTERING subpackage -as better replacement. - - -- ALGLIB -- - Copyright 21.03.2009 by Bochkanov Sergey -*************************************************************************/ -void kmeansgenerate(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t k, - ae_int_t restarts, - ae_int_t* info, - /* Real */ ae_matrix* c, - /* Integer */ ae_vector* xyc, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix dummy; - ae_int_t itscnt; - double e; - kmeansbuffers buf; - - ae_frame_make(_state, &_frame_block); - memset(&dummy, 0, sizeof(dummy)); - memset(&buf, 0, sizeof(buf)); - *info = 0; - ae_matrix_clear(c); - ae_vector_clear(xyc); - ae_matrix_init(&dummy, 0, 0, DT_REAL, _state, ae_true); - _kmeansbuffers_init(&buf, _state, ae_true); - - kmeansinitbuf(&buf, _state); - kmeansgenerateinternal(xy, npoints, nvars, k, 0, 1, 0, restarts, ae_false, info, &itscnt, c, ae_true, &dummy, ae_false, xyc, &e, &buf, _state); - ae_frame_leave(_state); -} - - -#endif - -} - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/dataanalysis.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/dataanalysis.h deleted file mode 100644 index 18c3d09..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/dataanalysis.h +++ /dev/null @@ -1,10477 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifndef _dataanalysis_pkg_h -#define _dataanalysis_pkg_h -#include "ap.h" -#include "alglibinternal.h" -#include "alglibmisc.h" -#include "linalg.h" -#include "statistics.h" -#include "specialfunctions.h" -#include "solvers.h" -#include "optimization.h" - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (DATATYPES) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_PCA) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_BDSS) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - double relclserror; - double avgce; - double rmserror; - double avgerror; - double avgrelerror; -} cvreport; -#endif -#if defined(AE_COMPILE_MLPBASE) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - double relclserror; - double avgce; - double rmserror; - double avgerror; - double avgrelerror; -} modelerrors; -typedef struct -{ - double f; - ae_vector g; -} smlpgrad; -typedef struct -{ - ae_int_t hlnetworktype; - ae_int_t hlnormtype; - ae_vector hllayersizes; - ae_vector hlconnections; - ae_vector hlneurons; - ae_vector structinfo; - ae_vector weights; - ae_vector columnmeans; - ae_vector columnsigmas; - ae_vector neurons; - ae_vector dfdnet; - ae_vector derror; - ae_vector x; - ae_vector y; - ae_matrix xy; - ae_vector xyrow; - ae_vector nwbuf; - ae_vector integerbuf; - modelerrors err; - ae_vector rndbuf; - ae_shared_pool buf; - ae_shared_pool gradbuf; - ae_matrix dummydxy; - sparsematrix dummysxy; - ae_vector dummyidx; - ae_shared_pool dummypool; -} multilayerperceptron; -#endif -#if defined(AE_COMPILE_LDA) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_SSA) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t nsequences; - ae_vector sequenceidx; - ae_vector sequencedata; - ae_int_t algotype; - ae_int_t windowwidth; - ae_int_t rtpowerup; - ae_int_t topk; - ae_int_t precomputedwidth; - ae_int_t precomputednbasis; - ae_matrix precomputedbasis; - ae_int_t defaultsubspaceits; - ae_int_t memorylimit; - ae_bool arebasisandsolvervalid; - ae_matrix basis; - ae_matrix basist; - ae_vector sv; - ae_vector forecasta; - ae_int_t nbasis; - eigsubspacestate solver; - ae_matrix xxt; - hqrndstate rs; - ae_int_t rngseed; - ae_vector rtqueue; - ae_int_t rtqueuecnt; - ae_int_t rtqueuechunk; - ae_int_t dbgcntevd; - ae_vector tmp0; - ae_vector tmp1; - eigsubspacereport solverrep; - ae_vector alongtrend; - ae_vector alongnoise; - ae_matrix aseqtrajectory; - ae_matrix aseqtbproduct; - ae_vector aseqcounts; - ae_vector fctrend; - ae_vector fcnoise; - ae_matrix fctrendm; - ae_matrix uxbatch; - ae_int_t uxbatchwidth; - ae_int_t uxbatchsize; - ae_int_t uxbatchlimit; -} ssamodel; -#endif -#if defined(AE_COMPILE_LINREG) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_vector w; -} linearmodel; -typedef struct -{ - ae_matrix c; - double rmserror; - double avgerror; - double avgrelerror; - double cvrmserror; - double cvavgerror; - double cvavgrelerror; - ae_int_t ncvdefects; - ae_vector cvdefects; -} lrreport; -#endif -#if defined(AE_COMPILE_FILTERS) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_LOGIT) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_vector w; -} logitmodel; -typedef struct -{ - ae_bool brackt; - ae_bool stage1; - ae_int_t infoc; - double dg; - double dgm; - double dginit; - double dgtest; - double dgx; - double dgxm; - double dgy; - double dgym; - double finit; - double ftest1; - double fm; - double fx; - double fxm; - double fy; - double fym; - double stx; - double sty; - double stmin; - double stmax; - double width; - double width1; - double xtrapf; -} logitmcstate; -typedef struct -{ - ae_int_t ngrad; - ae_int_t nhess; -} mnlreport; -#endif -#if defined(AE_COMPILE_MCPD) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t n; - ae_vector states; - ae_int_t npairs; - ae_matrix data; - ae_matrix ec; - ae_matrix bndl; - ae_matrix bndu; - ae_matrix c; - ae_vector ct; - ae_int_t ccnt; - ae_vector pw; - ae_matrix priorp; - double regterm; - minbleicstate bs; - ae_int_t repinneriterationscount; - ae_int_t repouteriterationscount; - ae_int_t repnfev; - ae_int_t repterminationtype; - minbleicreport br; - ae_vector tmpp; - ae_vector effectivew; - ae_vector effectivebndl; - ae_vector effectivebndu; - ae_matrix effectivec; - ae_vector effectivect; - ae_vector h; - ae_matrix p; -} mcpdstate; -typedef struct -{ - ae_int_t inneriterationscount; - ae_int_t outeriterationscount; - ae_int_t nfev; - ae_int_t terminationtype; -} mcpdreport; -#endif -#if defined(AE_COMPILE_MLPE) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t ensemblesize; - ae_vector weights; - ae_vector columnmeans; - ae_vector columnsigmas; - multilayerperceptron network; - ae_vector y; -} mlpensemble; -#endif -#if defined(AE_COMPILE_MLPTRAIN) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - double relclserror; - double avgce; - double rmserror; - double avgerror; - double avgrelerror; - ae_int_t ngrad; - ae_int_t nhess; - ae_int_t ncholesky; -} mlpreport; -typedef struct -{ - double relclserror; - double avgce; - double rmserror; - double avgerror; - double avgrelerror; -} mlpcvreport; -typedef struct -{ - ae_vector bestparameters; - double bestrmserror; - ae_bool randomizenetwork; - multilayerperceptron network; - minlbfgsstate optimizer; - minlbfgsreport optimizerrep; - ae_vector wbuf0; - ae_vector wbuf1; - ae_vector allminibatches; - ae_vector currentminibatch; - rcommstate rstate; - ae_int_t algoused; - ae_int_t minibatchsize; - hqrndstate generator; -} smlptrnsession; -typedef struct -{ - ae_vector trnsubset; - ae_vector valsubset; - ae_shared_pool mlpsessions; - mlpreport mlprep; - multilayerperceptron network; -} mlpetrnsession; -typedef struct -{ - ae_int_t nin; - ae_int_t nout; - ae_bool rcpar; - ae_int_t lbfgsfactor; - double decay; - double wstep; - ae_int_t maxits; - ae_int_t datatype; - ae_int_t npoints; - ae_matrix densexy; - sparsematrix sparsexy; - smlptrnsession session; - ae_int_t ngradbatch; - ae_vector subset; - ae_int_t subsetsize; - ae_vector valsubset; - ae_int_t valsubsetsize; - ae_int_t algokind; - ae_int_t minibatchsize; -} mlptrainer; -typedef struct -{ - multilayerperceptron network; - mlpreport rep; - ae_vector subset; - ae_int_t subsetsize; - ae_vector xyrow; - ae_vector y; - ae_int_t ngrad; - ae_shared_pool trnpool; -} mlpparallelizationcv; -#endif -#if defined(AE_COMPILE_CLUSTERING) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_matrix ct; - ae_matrix ctbest; - ae_vector xycbest; - ae_vector xycprev; - ae_vector d2; - ae_vector csizes; - apbuffers initbuf; - ae_shared_pool updatepool; -} kmeansbuffers; -typedef struct -{ - ae_int_t npoints; - ae_int_t nfeatures; - ae_int_t disttype; - ae_matrix xy; - ae_matrix d; - ae_int_t ahcalgo; - ae_int_t kmeansrestarts; - ae_int_t kmeansmaxits; - ae_int_t kmeansinitalgo; - ae_bool kmeansdbgnoits; - ae_int_t seed; - ae_matrix tmpd; - apbuffers distbuf; - kmeansbuffers kmeanstmp; -} clusterizerstate; -typedef struct -{ - ae_int_t terminationtype; - ae_int_t npoints; - ae_vector p; - ae_matrix z; - ae_matrix pz; - ae_matrix pm; - ae_vector mergedist; -} ahcreport; -typedef struct -{ - ae_int_t npoints; - ae_int_t nfeatures; - ae_int_t terminationtype; - ae_int_t iterationscount; - double energy; - ae_int_t k; - ae_matrix c; - ae_vector cidx; -} kmeansreport; -#endif -#if defined(AE_COMPILE_DFOREST) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t dstype; - ae_int_t npoints; - ae_int_t nvars; - ae_int_t nclasses; - ae_vector dsdata; - ae_vector dsrval; - ae_vector dsival; - ae_int_t rdfalgo; - double rdfratio; - double rdfvars; - ae_int_t rdfglobalseed; - ae_int_t rdfsplitstrength; - ae_int_t rdfimportance; - ae_vector dsmin; - ae_vector dsmax; - ae_vector dsbinary; - double dsravg; - ae_vector dsctotals; - ae_int_t rdfprogress; - ae_int_t rdftotal; - ae_shared_pool workpool; - ae_shared_pool votepool; - ae_shared_pool treepool; - ae_shared_pool treefactory; - ae_bool neediobmatrix; - ae_matrix iobmatrix; - ae_vector varimpshuffle2; -} decisionforestbuilder; -typedef struct -{ - ae_vector classpriors; - ae_vector varpool; - ae_int_t varpoolsize; - ae_vector trnset; - ae_int_t trnsize; - ae_vector trnlabelsr; - ae_vector trnlabelsi; - ae_vector oobset; - ae_int_t oobsize; - ae_vector ooblabelsr; - ae_vector ooblabelsi; - ae_vector treebuf; - ae_vector curvals; - ae_vector bestvals; - ae_vector tmp0i; - ae_vector tmp1i; - ae_vector tmp0r; - ae_vector tmp1r; - ae_vector tmp2r; - ae_vector tmp3r; - ae_vector tmpnrms2; - ae_vector classtotals0; - ae_vector classtotals1; - ae_vector classtotals01; -} dfworkbuf; -typedef struct -{ - ae_vector trntotals; - ae_vector oobtotals; - ae_vector trncounts; - ae_vector oobcounts; - ae_vector giniimportances; -} dfvotebuf; -typedef struct -{ - ae_vector losses; - ae_vector xraw; - ae_vector xdist; - ae_vector xcur; - ae_vector y; - ae_vector yv; - ae_vector targety; - ae_vector startnodes; -} dfpermimpbuf; -typedef struct -{ - ae_vector treebuf; - ae_int_t treeidx; -} dftreebuf; -typedef struct -{ - ae_vector x; - ae_vector y; -} decisionforestbuffer; -typedef struct -{ - ae_int_t forestformat; - ae_bool usemantissa8; - ae_int_t nvars; - ae_int_t nclasses; - ae_int_t ntrees; - ae_int_t bufsize; - ae_vector trees; - decisionforestbuffer buffer; - ae_vector trees8; -} decisionforest; -typedef struct -{ - double relclserror; - double avgce; - double rmserror; - double avgerror; - double avgrelerror; - double oobrelclserror; - double oobavgce; - double oobrmserror; - double oobavgerror; - double oobavgrelerror; - ae_vector topvars; - ae_vector varimportances; -} dfreport; -typedef struct -{ - ae_vector treebuf; - ae_vector idxbuf; - ae_vector tmpbufr; - ae_vector tmpbufr2; - ae_vector tmpbufi; - ae_vector classibuf; - ae_vector sortrbuf; - ae_vector sortrbuf2; - ae_vector sortibuf; - ae_vector varpool; - ae_vector evsbin; - ae_vector evssplits; -} dfinternalbuffers; -#endif -#if defined(AE_COMPILE_KNN) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - kdtreerequestbuffer treebuf; - ae_vector x; - ae_vector y; - ae_vector tags; - ae_matrix xy; -} knnbuffer; -typedef struct -{ - ae_int_t dstype; - ae_int_t npoints; - ae_int_t nvars; - ae_bool iscls; - ae_int_t nout; - ae_matrix dsdata; - ae_vector dsrval; - ae_vector dsival; - ae_int_t knnnrm; -} knnbuilder; -typedef struct -{ - ae_int_t nvars; - ae_int_t nout; - ae_int_t k; - double eps; - ae_bool iscls; - ae_bool isdummy; - kdtree tree; - knnbuffer buffer; -} knnmodel; -typedef struct -{ - double relclserror; - double avgce; - double rmserror; - double avgerror; - double avgrelerror; -} knnreport; -#endif -#if defined(AE_COMPILE_DATACOMP) || !defined(AE_PARTIAL_BUILD) -#endif - -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_PCA) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_BDSS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MLPBASE) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Model's errors: - * RelCLSError - fraction of misclassified cases. - * AvgCE - acerage cross-entropy - * RMSError - root-mean-square error - * AvgError - average error - * AvgRelError - average relative error - -NOTE 1: RelCLSError/AvgCE are zero on regression problems. - -NOTE 2: on classification problems RMSError/AvgError/AvgRelError contain - errors in prediction of posterior probabilities -*************************************************************************/ -class _modelerrors_owner -{ -public: - _modelerrors_owner(); - _modelerrors_owner(const _modelerrors_owner &rhs); - _modelerrors_owner& operator=(const _modelerrors_owner &rhs); - virtual ~_modelerrors_owner(); - alglib_impl::modelerrors* c_ptr(); - alglib_impl::modelerrors* c_ptr() const; -protected: - alglib_impl::modelerrors *p_struct; -}; -class modelerrors : public _modelerrors_owner -{ -public: - modelerrors(); - modelerrors(const modelerrors &rhs); - modelerrors& operator=(const modelerrors &rhs); - virtual ~modelerrors(); - double &relclserror; - double &avgce; - double &rmserror; - double &avgerror; - double &avgrelerror; - -}; - - -/************************************************************************* - -*************************************************************************/ -class _multilayerperceptron_owner -{ -public: - _multilayerperceptron_owner(); - _multilayerperceptron_owner(const _multilayerperceptron_owner &rhs); - _multilayerperceptron_owner& operator=(const _multilayerperceptron_owner &rhs); - virtual ~_multilayerperceptron_owner(); - alglib_impl::multilayerperceptron* c_ptr(); - alglib_impl::multilayerperceptron* c_ptr() const; -protected: - alglib_impl::multilayerperceptron *p_struct; -}; -class multilayerperceptron : public _multilayerperceptron_owner -{ -public: - multilayerperceptron(); - multilayerperceptron(const multilayerperceptron &rhs); - multilayerperceptron& operator=(const multilayerperceptron &rhs); - virtual ~multilayerperceptron(); - -}; -#endif - -#if defined(AE_COMPILE_LDA) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SSA) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores state of the SSA model. - -You should use ALGLIB functions to work with this object. -*************************************************************************/ -class _ssamodel_owner -{ -public: - _ssamodel_owner(); - _ssamodel_owner(const _ssamodel_owner &rhs); - _ssamodel_owner& operator=(const _ssamodel_owner &rhs); - virtual ~_ssamodel_owner(); - alglib_impl::ssamodel* c_ptr(); - alglib_impl::ssamodel* c_ptr() const; -protected: - alglib_impl::ssamodel *p_struct; -}; -class ssamodel : public _ssamodel_owner -{ -public: - ssamodel(); - ssamodel(const ssamodel &rhs); - ssamodel& operator=(const ssamodel &rhs); - virtual ~ssamodel(); - -}; -#endif - -#if defined(AE_COMPILE_LINREG) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - -*************************************************************************/ -class _linearmodel_owner -{ -public: - _linearmodel_owner(); - _linearmodel_owner(const _linearmodel_owner &rhs); - _linearmodel_owner& operator=(const _linearmodel_owner &rhs); - virtual ~_linearmodel_owner(); - alglib_impl::linearmodel* c_ptr(); - alglib_impl::linearmodel* c_ptr() const; -protected: - alglib_impl::linearmodel *p_struct; -}; -class linearmodel : public _linearmodel_owner -{ -public: - linearmodel(); - linearmodel(const linearmodel &rhs); - linearmodel& operator=(const linearmodel &rhs); - virtual ~linearmodel(); - -}; - - -/************************************************************************* -LRReport structure contains additional information about linear model: -* C - covariation matrix, array[0..NVars,0..NVars]. - C[i,j] = Cov(A[i],A[j]) -* RMSError - root mean square error on a training set -* AvgError - average error on a training set -* AvgRelError - average relative error on a training set (excluding - observations with zero function value). -* CVRMSError - leave-one-out cross-validation estimate of - generalization error. Calculated using fast algorithm - with O(NVars*NPoints) complexity. -* CVAvgError - cross-validation estimate of average error -* CVAvgRelError - cross-validation estimate of average relative error - -All other fields of the structure are intended for internal use and should -not be used outside ALGLIB. -*************************************************************************/ -class _lrreport_owner -{ -public: - _lrreport_owner(); - _lrreport_owner(const _lrreport_owner &rhs); - _lrreport_owner& operator=(const _lrreport_owner &rhs); - virtual ~_lrreport_owner(); - alglib_impl::lrreport* c_ptr(); - alglib_impl::lrreport* c_ptr() const; -protected: - alglib_impl::lrreport *p_struct; -}; -class lrreport : public _lrreport_owner -{ -public: - lrreport(); - lrreport(const lrreport &rhs); - lrreport& operator=(const lrreport &rhs); - virtual ~lrreport(); - real_2d_array c; - double &rmserror; - double &avgerror; - double &avgrelerror; - double &cvrmserror; - double &cvavgerror; - double &cvavgrelerror; - ae_int_t &ncvdefects; - integer_1d_array cvdefects; - -}; -#endif - -#if defined(AE_COMPILE_FILTERS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_LOGIT) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - -*************************************************************************/ -class _logitmodel_owner -{ -public: - _logitmodel_owner(); - _logitmodel_owner(const _logitmodel_owner &rhs); - _logitmodel_owner& operator=(const _logitmodel_owner &rhs); - virtual ~_logitmodel_owner(); - alglib_impl::logitmodel* c_ptr(); - alglib_impl::logitmodel* c_ptr() const; -protected: - alglib_impl::logitmodel *p_struct; -}; -class logitmodel : public _logitmodel_owner -{ -public: - logitmodel(); - logitmodel(const logitmodel &rhs); - logitmodel& operator=(const logitmodel &rhs); - virtual ~logitmodel(); - -}; - - -/************************************************************************* -MNLReport structure contains information about training process: -* NGrad - number of gradient calculations -* NHess - number of Hessian calculations -*************************************************************************/ -class _mnlreport_owner -{ -public: - _mnlreport_owner(); - _mnlreport_owner(const _mnlreport_owner &rhs); - _mnlreport_owner& operator=(const _mnlreport_owner &rhs); - virtual ~_mnlreport_owner(); - alglib_impl::mnlreport* c_ptr(); - alglib_impl::mnlreport* c_ptr() const; -protected: - alglib_impl::mnlreport *p_struct; -}; -class mnlreport : public _mnlreport_owner -{ -public: - mnlreport(); - mnlreport(const mnlreport &rhs); - mnlreport& operator=(const mnlreport &rhs); - virtual ~mnlreport(); - ae_int_t &ngrad; - ae_int_t &nhess; - -}; -#endif - -#if defined(AE_COMPILE_MCPD) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This structure is a MCPD (Markov Chains for Population Data) solver. - -You should use ALGLIB functions in order to work with this object. - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -class _mcpdstate_owner -{ -public: - _mcpdstate_owner(); - _mcpdstate_owner(const _mcpdstate_owner &rhs); - _mcpdstate_owner& operator=(const _mcpdstate_owner &rhs); - virtual ~_mcpdstate_owner(); - alglib_impl::mcpdstate* c_ptr(); - alglib_impl::mcpdstate* c_ptr() const; -protected: - alglib_impl::mcpdstate *p_struct; -}; -class mcpdstate : public _mcpdstate_owner -{ -public: - mcpdstate(); - mcpdstate(const mcpdstate &rhs); - mcpdstate& operator=(const mcpdstate &rhs); - virtual ~mcpdstate(); - -}; - - -/************************************************************************* -This structure is a MCPD training report: - InnerIterationsCount - number of inner iterations of the - underlying optimization algorithm - OuterIterationsCount - number of outer iterations of the - underlying optimization algorithm - NFEV - number of merit function evaluations - TerminationType - termination type - (same as for MinBLEIC optimizer, positive - values denote success, negative ones - - failure) - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -class _mcpdreport_owner -{ -public: - _mcpdreport_owner(); - _mcpdreport_owner(const _mcpdreport_owner &rhs); - _mcpdreport_owner& operator=(const _mcpdreport_owner &rhs); - virtual ~_mcpdreport_owner(); - alglib_impl::mcpdreport* c_ptr(); - alglib_impl::mcpdreport* c_ptr() const; -protected: - alglib_impl::mcpdreport *p_struct; -}; -class mcpdreport : public _mcpdreport_owner -{ -public: - mcpdreport(); - mcpdreport(const mcpdreport &rhs); - mcpdreport& operator=(const mcpdreport &rhs); - virtual ~mcpdreport(); - ae_int_t &inneriterationscount; - ae_int_t &outeriterationscount; - ae_int_t &nfev; - ae_int_t &terminationtype; - -}; -#endif - -#if defined(AE_COMPILE_MLPE) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Neural networks ensemble -*************************************************************************/ -class _mlpensemble_owner -{ -public: - _mlpensemble_owner(); - _mlpensemble_owner(const _mlpensemble_owner &rhs); - _mlpensemble_owner& operator=(const _mlpensemble_owner &rhs); - virtual ~_mlpensemble_owner(); - alglib_impl::mlpensemble* c_ptr(); - alglib_impl::mlpensemble* c_ptr() const; -protected: - alglib_impl::mlpensemble *p_struct; -}; -class mlpensemble : public _mlpensemble_owner -{ -public: - mlpensemble(); - mlpensemble(const mlpensemble &rhs); - mlpensemble& operator=(const mlpensemble &rhs); - virtual ~mlpensemble(); - -}; -#endif - -#if defined(AE_COMPILE_MLPTRAIN) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Training report: - * RelCLSError - fraction of misclassified cases. - * AvgCE - acerage cross-entropy - * RMSError - root-mean-square error - * AvgError - average error - * AvgRelError - average relative error - * NGrad - number of gradient calculations - * NHess - number of Hessian calculations - * NCholesky - number of Cholesky decompositions - -NOTE 1: RelCLSError/AvgCE are zero on regression problems. - -NOTE 2: on classification problems RMSError/AvgError/AvgRelError contain - errors in prediction of posterior probabilities -*************************************************************************/ -class _mlpreport_owner -{ -public: - _mlpreport_owner(); - _mlpreport_owner(const _mlpreport_owner &rhs); - _mlpreport_owner& operator=(const _mlpreport_owner &rhs); - virtual ~_mlpreport_owner(); - alglib_impl::mlpreport* c_ptr(); - alglib_impl::mlpreport* c_ptr() const; -protected: - alglib_impl::mlpreport *p_struct; -}; -class mlpreport : public _mlpreport_owner -{ -public: - mlpreport(); - mlpreport(const mlpreport &rhs); - mlpreport& operator=(const mlpreport &rhs); - virtual ~mlpreport(); - double &relclserror; - double &avgce; - double &rmserror; - double &avgerror; - double &avgrelerror; - ae_int_t &ngrad; - ae_int_t &nhess; - ae_int_t &ncholesky; - -}; - - -/************************************************************************* -Cross-validation estimates of generalization error -*************************************************************************/ -class _mlpcvreport_owner -{ -public: - _mlpcvreport_owner(); - _mlpcvreport_owner(const _mlpcvreport_owner &rhs); - _mlpcvreport_owner& operator=(const _mlpcvreport_owner &rhs); - virtual ~_mlpcvreport_owner(); - alglib_impl::mlpcvreport* c_ptr(); - alglib_impl::mlpcvreport* c_ptr() const; -protected: - alglib_impl::mlpcvreport *p_struct; -}; -class mlpcvreport : public _mlpcvreport_owner -{ -public: - mlpcvreport(); - mlpcvreport(const mlpcvreport &rhs); - mlpcvreport& operator=(const mlpcvreport &rhs); - virtual ~mlpcvreport(); - double &relclserror; - double &avgce; - double &rmserror; - double &avgerror; - double &avgrelerror; - -}; - - -/************************************************************************* -Trainer object for neural network. - -You should not try to access fields of this object directly - use ALGLIB -functions to work with this object. -*************************************************************************/ -class _mlptrainer_owner -{ -public: - _mlptrainer_owner(); - _mlptrainer_owner(const _mlptrainer_owner &rhs); - _mlptrainer_owner& operator=(const _mlptrainer_owner &rhs); - virtual ~_mlptrainer_owner(); - alglib_impl::mlptrainer* c_ptr(); - alglib_impl::mlptrainer* c_ptr() const; -protected: - alglib_impl::mlptrainer *p_struct; -}; -class mlptrainer : public _mlptrainer_owner -{ -public: - mlptrainer(); - mlptrainer(const mlptrainer &rhs); - mlptrainer& operator=(const mlptrainer &rhs); - virtual ~mlptrainer(); - -}; -#endif - -#if defined(AE_COMPILE_CLUSTERING) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This structure is a clusterization engine. - -You should not try to access its fields directly. -Use ALGLIB functions in order to work with this object. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -class _clusterizerstate_owner -{ -public: - _clusterizerstate_owner(); - _clusterizerstate_owner(const _clusterizerstate_owner &rhs); - _clusterizerstate_owner& operator=(const _clusterizerstate_owner &rhs); - virtual ~_clusterizerstate_owner(); - alglib_impl::clusterizerstate* c_ptr(); - alglib_impl::clusterizerstate* c_ptr() const; -protected: - alglib_impl::clusterizerstate *p_struct; -}; -class clusterizerstate : public _clusterizerstate_owner -{ -public: - clusterizerstate(); - clusterizerstate(const clusterizerstate &rhs); - clusterizerstate& operator=(const clusterizerstate &rhs); - virtual ~clusterizerstate(); - -}; - - -/************************************************************************* -This structure is used to store results of the agglomerative hierarchical -clustering (AHC). - -Following information is returned: - -* TerminationType - completion code: - * 1 for successful completion of algorithm - * -5 inappropriate combination of clustering algorithm and distance - function was used. As for now, it is possible only when Ward's - method is called for dataset with non-Euclidean distance function. - In case negative completion code is returned, other fields of report - structure are invalid and should not be used. - -* NPoints contains number of points in the original dataset - -* Z contains information about merges performed (see below). Z contains - indexes from the original (unsorted) dataset and it can be used when you - need to know what points were merged. However, it is not convenient when - you want to build a dendrograd (see below). - -* if you want to build dendrogram, you can use Z, but it is not good - option, because Z contains indexes from unsorted dataset. Dendrogram - built from such dataset is likely to have intersections. So, you have to - reorder you points before building dendrogram. - Permutation which reorders point is returned in P. Another representation - of merges, which is more convenient for dendorgram construction, is - returned in PM. - -* more information on format of Z, P and PM can be found below and in the - examples from ALGLIB Reference Manual. - -FORMAL DESCRIPTION OF FIELDS: - NPoints number of points - Z array[NPoints-1,2], contains indexes of clusters - linked in pairs to form clustering tree. I-th row - corresponds to I-th merge: - * Z[I,0] - index of the first cluster to merge - * Z[I,1] - index of the second cluster to merge - * Z[I,0]=0 - NFeatures number of variables, >=1 - TerminationType completion code: - * -5 if distance type is anything different from - Euclidean metric - * -3 for degenerate dataset: a) less than K distinct - points, b) K=0 for non-empty dataset. - * +1 for successful completion - K number of clusters - C array[K,NFeatures], rows of the array store centers - CIdx array[NPoints], which contains cluster indexes - IterationsCount actual number of iterations performed by clusterizer. - If algorithm performed more than one random restart, - total number of iterations is returned. - Energy merit function, "energy", sum of squared deviations - from cluster centers - - -- ALGLIB -- - Copyright 27.11.2012 by Bochkanov Sergey -*************************************************************************/ -class _kmeansreport_owner -{ -public: - _kmeansreport_owner(); - _kmeansreport_owner(const _kmeansreport_owner &rhs); - _kmeansreport_owner& operator=(const _kmeansreport_owner &rhs); - virtual ~_kmeansreport_owner(); - alglib_impl::kmeansreport* c_ptr(); - alglib_impl::kmeansreport* c_ptr() const; -protected: - alglib_impl::kmeansreport *p_struct; -}; -class kmeansreport : public _kmeansreport_owner -{ -public: - kmeansreport(); - kmeansreport(const kmeansreport &rhs); - kmeansreport& operator=(const kmeansreport &rhs); - virtual ~kmeansreport(); - ae_int_t &npoints; - ae_int_t &nfeatures; - ae_int_t &terminationtype; - ae_int_t &iterationscount; - double &energy; - ae_int_t &k; - real_2d_array c; - integer_1d_array cidx; - -}; -#endif - -#if defined(AE_COMPILE_DFOREST) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -A random forest (decision forest) builder object. - -Used to store dataset and specify decision forest training algorithm settings. -*************************************************************************/ -class _decisionforestbuilder_owner -{ -public: - _decisionforestbuilder_owner(); - _decisionforestbuilder_owner(const _decisionforestbuilder_owner &rhs); - _decisionforestbuilder_owner& operator=(const _decisionforestbuilder_owner &rhs); - virtual ~_decisionforestbuilder_owner(); - alglib_impl::decisionforestbuilder* c_ptr(); - alglib_impl::decisionforestbuilder* c_ptr() const; -protected: - alglib_impl::decisionforestbuilder *p_struct; -}; -class decisionforestbuilder : public _decisionforestbuilder_owner -{ -public: - decisionforestbuilder(); - decisionforestbuilder(const decisionforestbuilder &rhs); - decisionforestbuilder& operator=(const decisionforestbuilder &rhs); - virtual ~decisionforestbuilder(); - -}; - - -/************************************************************************* -Buffer object which is used to perform various requests (usually model -inference) in the multithreaded mode (multiple threads working with same -DF object). - -This object should be created with DFCreateBuffer(). -*************************************************************************/ -class _decisionforestbuffer_owner -{ -public: - _decisionforestbuffer_owner(); - _decisionforestbuffer_owner(const _decisionforestbuffer_owner &rhs); - _decisionforestbuffer_owner& operator=(const _decisionforestbuffer_owner &rhs); - virtual ~_decisionforestbuffer_owner(); - alglib_impl::decisionforestbuffer* c_ptr(); - alglib_impl::decisionforestbuffer* c_ptr() const; -protected: - alglib_impl::decisionforestbuffer *p_struct; -}; -class decisionforestbuffer : public _decisionforestbuffer_owner -{ -public: - decisionforestbuffer(); - decisionforestbuffer(const decisionforestbuffer &rhs); - decisionforestbuffer& operator=(const decisionforestbuffer &rhs); - virtual ~decisionforestbuffer(); - -}; - - -/************************************************************************* -Decision forest (random forest) model. -*************************************************************************/ -class _decisionforest_owner -{ -public: - _decisionforest_owner(); - _decisionforest_owner(const _decisionforest_owner &rhs); - _decisionforest_owner& operator=(const _decisionforest_owner &rhs); - virtual ~_decisionforest_owner(); - alglib_impl::decisionforest* c_ptr(); - alglib_impl::decisionforest* c_ptr() const; -protected: - alglib_impl::decisionforest *p_struct; -}; -class decisionforest : public _decisionforest_owner -{ -public: - decisionforest(); - decisionforest(const decisionforest &rhs); - decisionforest& operator=(const decisionforest &rhs); - virtual ~decisionforest(); - -}; - - -/************************************************************************* -Decision forest training report. - -=== training/oob errors ================================================== - -Following fields store training set errors: -* relclserror - fraction of misclassified cases, [0,1] -* avgce - average cross-entropy in bits per symbol -* rmserror - root-mean-square error -* avgerror - average error -* avgrelerror - average relative error - -Out-of-bag estimates are stored in fields with same names, but "oob" prefix. - -For classification problems: -* RMS, AVG and AVGREL errors are calculated for posterior probabilities - -For regression problems: -* RELCLS and AVGCE errors are zero - -=== variable importance ================================================== - -Following fields are used to store variable importance information: - -* topvars - variables ordered from the most important to - less important ones (according to current - choice of importance raiting). - For example, topvars[0] contains index of the - most important variable, and topvars[0:2] are - indexes of 3 most important ones and so on. - -* varimportances - array[nvars], ratings (the larger, the more - important the variable is, always in [0,1] - range). - By default, filled by zeros (no importance - ratings are provided unless you explicitly - request them). - Zero rating means that variable is not important, - however you will rarely encounter such a thing, - in many cases unimportant variables produce - nearly-zero (but nonzero) ratings. - -Variable importance report must be EXPLICITLY requested by calling: -* dfbuildersetimportancegini() function, if you need out-of-bag Gini-based - importance rating also known as MDI (fast to calculate, resistant to - overfitting issues, but has some bias towards continuous and - high-cardinality categorical variables) -* dfbuildersetimportancetrngini() function, if you need training set Gini- - -based importance rating (what other packages typically report). -* dfbuildersetimportancepermutation() function, if you need permutation- - based importance rating also known as MDA (slower to calculate, but less - biased) -* dfbuildersetimportancenone() function, if you do not need importance - ratings - ratings will be zero, topvars[] will be [0,1,2,...] - -Different importance ratings (Gini or permutation) produce non-comparable -values. Although in all cases rating values lie in [0,1] range, there are -exist differences: -* informally speaking, Gini importance rating tends to divide "unit amount - of importance" between several important variables, i.e. it produces - estimates which roughly sum to 1.0 (or less than 1.0, if your task can - not be solved exactly). If all variables are equally important, they - will have same rating, roughly 1/NVars, even if every variable is - critically important. -* from the other side, permutation importance tells us what percentage of - the model predictive power will be ruined by permuting this specific - variable. It does not produce estimates which sum to one. Critically - important variable will have rating close to 1.0, and you may have - multiple variables with such a rating. - -More information on variable importance ratings can be found in comments -on the dfbuildersetimportancegini() and dfbuildersetimportancepermutation() -functions. -*************************************************************************/ -class _dfreport_owner -{ -public: - _dfreport_owner(); - _dfreport_owner(const _dfreport_owner &rhs); - _dfreport_owner& operator=(const _dfreport_owner &rhs); - virtual ~_dfreport_owner(); - alglib_impl::dfreport* c_ptr(); - alglib_impl::dfreport* c_ptr() const; -protected: - alglib_impl::dfreport *p_struct; -}; -class dfreport : public _dfreport_owner -{ -public: - dfreport(); - dfreport(const dfreport &rhs); - dfreport& operator=(const dfreport &rhs); - virtual ~dfreport(); - double &relclserror; - double &avgce; - double &rmserror; - double &avgerror; - double &avgrelerror; - double &oobrelclserror; - double &oobavgce; - double &oobrmserror; - double &oobavgerror; - double &oobavgrelerror; - integer_1d_array topvars; - real_1d_array varimportances; - -}; -#endif - -#if defined(AE_COMPILE_KNN) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Buffer object which is used to perform various requests (usually model -inference) in the multithreaded mode (multiple threads working with same -KNN object). - -This object should be created with KNNCreateBuffer(). -*************************************************************************/ -class _knnbuffer_owner -{ -public: - _knnbuffer_owner(); - _knnbuffer_owner(const _knnbuffer_owner &rhs); - _knnbuffer_owner& operator=(const _knnbuffer_owner &rhs); - virtual ~_knnbuffer_owner(); - alglib_impl::knnbuffer* c_ptr(); - alglib_impl::knnbuffer* c_ptr() const; -protected: - alglib_impl::knnbuffer *p_struct; -}; -class knnbuffer : public _knnbuffer_owner -{ -public: - knnbuffer(); - knnbuffer(const knnbuffer &rhs); - knnbuffer& operator=(const knnbuffer &rhs); - virtual ~knnbuffer(); - -}; - - -/************************************************************************* -A KNN builder object; this object encapsulates dataset and all related -settings, it is used to create an actual instance of KNN model. -*************************************************************************/ -class _knnbuilder_owner -{ -public: - _knnbuilder_owner(); - _knnbuilder_owner(const _knnbuilder_owner &rhs); - _knnbuilder_owner& operator=(const _knnbuilder_owner &rhs); - virtual ~_knnbuilder_owner(); - alglib_impl::knnbuilder* c_ptr(); - alglib_impl::knnbuilder* c_ptr() const; -protected: - alglib_impl::knnbuilder *p_struct; -}; -class knnbuilder : public _knnbuilder_owner -{ -public: - knnbuilder(); - knnbuilder(const knnbuilder &rhs); - knnbuilder& operator=(const knnbuilder &rhs); - virtual ~knnbuilder(); - -}; - - -/************************************************************************* -KNN model, can be used for classification or regression -*************************************************************************/ -class _knnmodel_owner -{ -public: - _knnmodel_owner(); - _knnmodel_owner(const _knnmodel_owner &rhs); - _knnmodel_owner& operator=(const _knnmodel_owner &rhs); - virtual ~_knnmodel_owner(); - alglib_impl::knnmodel* c_ptr(); - alglib_impl::knnmodel* c_ptr() const; -protected: - alglib_impl::knnmodel *p_struct; -}; -class knnmodel : public _knnmodel_owner -{ -public: - knnmodel(); - knnmodel(const knnmodel &rhs); - knnmodel& operator=(const knnmodel &rhs); - virtual ~knnmodel(); - -}; - - -/************************************************************************* -KNN training report. - -Following fields store training set errors: -* relclserror - fraction of misclassified cases, [0,1] -* avgce - average cross-entropy in bits per symbol -* rmserror - root-mean-square error -* avgerror - average error -* avgrelerror - average relative error - -For classification problems: -* RMS, AVG and AVGREL errors are calculated for posterior probabilities - -For regression problems: -* RELCLS and AVGCE errors are zero -*************************************************************************/ -class _knnreport_owner -{ -public: - _knnreport_owner(); - _knnreport_owner(const _knnreport_owner &rhs); - _knnreport_owner& operator=(const _knnreport_owner &rhs); - virtual ~_knnreport_owner(); - alglib_impl::knnreport* c_ptr(); - alglib_impl::knnreport* c_ptr() const; -protected: - alglib_impl::knnreport *p_struct; -}; -class knnreport : public _knnreport_owner -{ -public: - knnreport(); - knnreport(const knnreport &rhs); - knnreport& operator=(const knnreport &rhs); - virtual ~knnreport(); - double &relclserror; - double &avgce; - double &rmserror; - double &avgerror; - double &avgrelerror; - -}; -#endif - -#if defined(AE_COMPILE_DATACOMP) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_PCA) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Principal components analysis - -This function builds orthogonal basis where first axis corresponds to -direction with maximum variance, second axis maximizes variance in the -subspace orthogonal to first axis and so on. - -This function builds FULL basis, i.e. returns N vectors corresponding to -ALL directions, no matter how informative. If you need just a few (say, -10 or 50) of the most important directions, you may find it faster to use -one of the reduced versions: -* pcatruncatedsubspace() - for subspace iteration based method - -It should be noted that, unlike LDA, PCA does not use class labels. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - dataset, array[0..NPoints-1,0..NVars-1]. - matrix contains ONLY INDEPENDENT VARIABLES. - NPoints - dataset size, NPoints>=0 - NVars - number of independent variables, NVars>=1 - -OUTPUT PARAMETERS: - Info - return code: - * -4, if SVD subroutine haven't converged - * -1, if wrong parameters has been passed (NPoints<0, - NVars<1) - * 1, if task is solved - S2 - array[0..NVars-1]. variance values corresponding - to basis vectors. - V - array[0..NVars-1,0..NVars-1] - matrix, whose columns store basis vectors. - - -- ALGLIB -- - Copyright 25.08.2008 by Bochkanov Sergey -*************************************************************************/ -void pcabuildbasis(const real_2d_array &x, const ae_int_t npoints, const ae_int_t nvars, ae_int_t &info, real_1d_array &s2, real_2d_array &v, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Principal components analysis - -This function performs truncated PCA, i.e. returns just a few most important -directions. - -Internally it uses iterative eigensolver which is very efficient when only -a minor fraction of full basis is required. Thus, if you need full basis, -it is better to use pcabuildbasis() function. - -It should be noted that, unlike LDA, PCA does not use class labels. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - dataset, array[0..NPoints-1,0..NVars-1]. - matrix contains ONLY INDEPENDENT VARIABLES. - NPoints - dataset size, NPoints>=0 - NVars - number of independent variables, NVars>=1 - NNeeded - number of requested components, in [1,NVars] range; - this function is efficient only for NNeeded<=0 - NVars - number of independent variables, NVars>=1 - NNeeded - number of requested components, in [1,NVars] range; - this function is efficient only for NNeeded<1) - * -1, incorrect pararemets were passed (N<=0). - * 1, OK - Threshold- partiton boundary. Left part contains values which are - strictly less than Threshold. Right part contains values - which are greater than or equal to Threshold. - PAL, PBL- probabilities P(0|v=Threshold) and P(1|v>=Threshold) - CVE - cross-validation estimate of cross-entropy - - -- ALGLIB -- - Copyright 22.05.2008 by Bochkanov Sergey -*************************************************************************/ -void dsoptimalsplit2(const real_1d_array &a, const integer_1d_array &c, const ae_int_t n, ae_int_t &info, double &threshold, double &pal, double &pbl, double &par, double &pbr, double &cve, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Optimal partition, internal subroutine. Fast version. - -Accepts: - A array[0..N-1] array of attributes array[0..N-1] - C array[0..N-1] array of class labels - TiesBuf array[0..N] temporaries (ties) - CntBuf array[0..2*NC-1] temporaries (counts) - Alpha centering factor (0<=alpha<=1, recommended value - 0.05) - BufR array[0..N-1] temporaries - BufI array[0..N-1] temporaries - -Output: - Info error code (">0"=OK, "<0"=bad) - RMS training set RMS error - CVRMS leave-one-out RMS error - -Note: - content of all arrays is changed by subroutine; - it doesn't allocate temporaries. - - -- ALGLIB -- - Copyright 11.12.2008 by Bochkanov Sergey -*************************************************************************/ -void dsoptimalsplit2fast(real_1d_array &a, integer_1d_array &c, integer_1d_array &tiesbuf, integer_1d_array &cntbuf, real_1d_array &bufr, integer_1d_array &bufi, const ae_int_t n, const ae_int_t nc, const double alpha, ae_int_t &info, double &threshold, double &rms, double &cvrms, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_MLPBASE) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -void mlpserialize(multilayerperceptron &obj, std::string &s_out); - - -/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -void mlpunserialize(const std::string &s_in, multilayerperceptron &obj); - - - - -/************************************************************************* -This function serializes data structure to C++ stream. - -Data stream generated by this function is same as string representation -generated by string version of serializer - alphanumeric characters, -dots, underscores, minus signs, which are grouped into words separated by -spaces and CR+LF. - -We recommend you to read comments on string version of serializer to find -out more about serialization of AlGLIB objects. -*************************************************************************/ -void mlpserialize(multilayerperceptron &obj, std::ostream &s_out); - - -/************************************************************************* -This function unserializes data structure from stream. -*************************************************************************/ -void mlpunserialize(const std::istream &s_in, multilayerperceptron &obj); - - -/************************************************************************* -Creates neural network with NIn inputs, NOut outputs, without hidden -layers, with linear output layer. Network weights are filled with small -random values. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcreate0(const ae_int_t nin, const ae_int_t nout, multilayerperceptron &network, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Same as MLPCreate0, but with one hidden layer (NHid neurons) with -non-linear activation function. Output layer is linear. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcreate1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, multilayerperceptron &network, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Same as MLPCreate0, but with two hidden layers (NHid1 and NHid2 neurons) -with non-linear activation function. Output layer is linear. - $ALL - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcreate2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, multilayerperceptron &network, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Creates neural network with NIn inputs, NOut outputs, without hidden -layers with non-linear output layer. Network weights are filled with small -random values. - -Activation function of the output layer takes values: - - (B, +INF), if D>=0 - -or - - (-INF, B), if D<0. - - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpcreateb0(const ae_int_t nin, const ae_int_t nout, const double b, const double d, multilayerperceptron &network, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Same as MLPCreateB0 but with non-linear hidden layer. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpcreateb1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const double b, const double d, multilayerperceptron &network, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Same as MLPCreateB0 but with two non-linear hidden layers. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpcreateb2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const double b, const double d, multilayerperceptron &network, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Creates neural network with NIn inputs, NOut outputs, without hidden -layers with non-linear output layer. Network weights are filled with small -random values. Activation function of the output layer takes values [A,B]. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpcreater0(const ae_int_t nin, const ae_int_t nout, const double a, const double b, multilayerperceptron &network, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Same as MLPCreateR0, but with non-linear hidden layer. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpcreater1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const double a, const double b, multilayerperceptron &network, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Same as MLPCreateR0, but with two non-linear hidden layers. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpcreater2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const double a, const double b, multilayerperceptron &network, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Creates classifier network with NIn inputs and NOut possible classes. -Network contains no hidden layers and linear output layer with SOFTMAX- -normalization (so outputs sums up to 1.0 and converge to posterior -probabilities). - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcreatec0(const ae_int_t nin, const ae_int_t nout, multilayerperceptron &network, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Same as MLPCreateC0, but with one non-linear hidden layer. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcreatec1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, multilayerperceptron &network, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Same as MLPCreateC0, but with two non-linear hidden layers. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcreatec2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, multilayerperceptron &network, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Copying of neural network - -INPUT PARAMETERS: - Network1 - original - -OUTPUT PARAMETERS: - Network2 - copy - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpcopy(const multilayerperceptron &network1, multilayerperceptron &network2, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function copies tunable parameters (weights/means/sigmas) from one -network to another with same architecture. It performs some rudimentary -checks that architectures are same, and throws exception if check fails. - -It is intended for fast copying of states between two network which are -known to have same geometry. - -INPUT PARAMETERS: - Network1 - source, must be correctly initialized - Network2 - target, must have same architecture - -OUTPUT PARAMETERS: - Network2 - network state is copied from source to target - - -- ALGLIB -- - Copyright 20.06.2013 by Bochkanov Sergey -*************************************************************************/ -void mlpcopytunableparameters(const multilayerperceptron &network1, const multilayerperceptron &network2, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Randomization of neural network weights - - -- ALGLIB -- - Copyright 06.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlprandomize(const multilayerperceptron &network, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Randomization of neural network weights and standartisator - - -- ALGLIB -- - Copyright 10.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlprandomizefull(const multilayerperceptron &network, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Internal subroutine. - - -- ALGLIB -- - Copyright 30.03.2008 by Bochkanov Sergey -*************************************************************************/ -void mlpinitpreprocessor(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Returns information about initialized network: number of inputs, outputs, -weights. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpproperties(const multilayerperceptron &network, ae_int_t &nin, ae_int_t &nout, ae_int_t &wcount, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Returns number of inputs. - - -- ALGLIB -- - Copyright 19.10.2011 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mlpgetinputscount(const multilayerperceptron &network, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Returns number of outputs. - - -- ALGLIB -- - Copyright 19.10.2011 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mlpgetoutputscount(const multilayerperceptron &network, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Returns number of weights. - - -- ALGLIB -- - Copyright 19.10.2011 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mlpgetweightscount(const multilayerperceptron &network, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Tells whether network is SOFTMAX-normalized (i.e. classifier) or not. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -bool mlpissoftmax(const multilayerperceptron &network, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function returns total number of layers (including input, hidden and -output layers). - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mlpgetlayerscount(const multilayerperceptron &network, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function returns size of K-th layer. - -K=0 corresponds to input layer, K=CNT-1 corresponds to output layer. - -Size of the output layer is always equal to the number of outputs, although -when we have softmax-normalized network, last neuron doesn't have any -connections - it is just zero. - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mlpgetlayersize(const multilayerperceptron &network, const ae_int_t k, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function returns offset/scaling coefficients for I-th input of the -network. - -INPUT PARAMETERS: - Network - network - I - input index - -OUTPUT PARAMETERS: - Mean - mean term - Sigma - sigma term, guaranteed to be nonzero. - -I-th input is passed through linear transformation - IN[i] = (IN[i]-Mean)/Sigma -before feeding to the network - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpgetinputscaling(const multilayerperceptron &network, const ae_int_t i, double &mean, double &sigma, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function returns offset/scaling coefficients for I-th output of the -network. - -INPUT PARAMETERS: - Network - network - I - input index - -OUTPUT PARAMETERS: - Mean - mean term - Sigma - sigma term, guaranteed to be nonzero. - -I-th output is passed through linear transformation - OUT[i] = OUT[i]*Sigma+Mean -before returning it to user. In case we have SOFTMAX-normalized network, -we return (Mean,Sigma)=(0.0,1.0). - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpgetoutputscaling(const multilayerperceptron &network, const ae_int_t i, double &mean, double &sigma, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function returns information about Ith neuron of Kth layer - -INPUT PARAMETERS: - Network - network - K - layer index - I - neuron index (within layer) - -OUTPUT PARAMETERS: - FKind - activation function type (used by MLPActivationFunction()) - this value is zero for input or linear neurons - Threshold - also called offset, bias - zero for input neurons - -NOTE: this function throws exception if layer or neuron with given index -do not exists. - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpgetneuroninfo(const multilayerperceptron &network, const ae_int_t k, const ae_int_t i, ae_int_t &fkind, double &threshold, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function returns information about connection from I0-th neuron of -K0-th layer to I1-th neuron of K1-th layer. - -INPUT PARAMETERS: - Network - network - K0 - layer index - I0 - neuron index (within layer) - K1 - layer index - I1 - neuron index (within layer) - -RESULT: - connection weight (zero for non-existent connections) - -This function: -1. throws exception if layer or neuron with given index do not exists. -2. returns zero if neurons exist, but there is no connection between them - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -double mlpgetweight(const multilayerperceptron &network, const ae_int_t k0, const ae_int_t i0, const ae_int_t k1, const ae_int_t i1, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets offset/scaling coefficients for I-th input of the -network. - -INPUT PARAMETERS: - Network - network - I - input index - Mean - mean term - Sigma - sigma term (if zero, will be replaced by 1.0) - -NTE: I-th input is passed through linear transformation - IN[i] = (IN[i]-Mean)/Sigma -before feeding to the network. This function sets Mean and Sigma. - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpsetinputscaling(const multilayerperceptron &network, const ae_int_t i, const double mean, const double sigma, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets offset/scaling coefficients for I-th output of the -network. - -INPUT PARAMETERS: - Network - network - I - input index - Mean - mean term - Sigma - sigma term (if zero, will be replaced by 1.0) - -OUTPUT PARAMETERS: - -NOTE: I-th output is passed through linear transformation - OUT[i] = OUT[i]*Sigma+Mean -before returning it to user. This function sets Sigma/Mean. In case we -have SOFTMAX-normalized network, you can not set (Sigma,Mean) to anything -other than(0.0,1.0) - this function will throw exception. - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpsetoutputscaling(const multilayerperceptron &network, const ae_int_t i, const double mean, const double sigma, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function modifies information about Ith neuron of Kth layer - -INPUT PARAMETERS: - Network - network - K - layer index - I - neuron index (within layer) - FKind - activation function type (used by MLPActivationFunction()) - this value must be zero for input neurons - (you can not set activation function for input neurons) - Threshold - also called offset, bias - this value must be zero for input neurons - (you can not set threshold for input neurons) - -NOTES: -1. this function throws exception if layer or neuron with given index do - not exists. -2. this function also throws exception when you try to set non-linear - activation function for input neurons (any kind of network) or for output - neurons of classifier network. -3. this function throws exception when you try to set non-zero threshold for - input neurons (any kind of network). - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpsetneuroninfo(const multilayerperceptron &network, const ae_int_t k, const ae_int_t i, const ae_int_t fkind, const double threshold, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function modifies information about connection from I0-th neuron of -K0-th layer to I1-th neuron of K1-th layer. - -INPUT PARAMETERS: - Network - network - K0 - layer index - I0 - neuron index (within layer) - K1 - layer index - I1 - neuron index (within layer) - W - connection weight (must be zero for non-existent - connections) - -This function: -1. throws exception if layer or neuron with given index do not exists. -2. throws exception if you try to set non-zero weight for non-existent - connection - - -- ALGLIB -- - Copyright 25.03.2011 by Bochkanov Sergey -*************************************************************************/ -void mlpsetweight(const multilayerperceptron &network, const ae_int_t k0, const ae_int_t i0, const ae_int_t k1, const ae_int_t i1, const double w, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Neural network activation function - -INPUT PARAMETERS: - NET - neuron input - K - function index (zero for linear function) - -OUTPUT PARAMETERS: - F - function - DF - its derivative - D2F - its second derivative - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpactivationfunction(const double net, const ae_int_t k, double &f, double &df, double &d2f, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Procesing - -INPUT PARAMETERS: - Network - neural network - X - input vector, array[0..NIn-1]. - -OUTPUT PARAMETERS: - Y - result. Regression estimate when solving regression task, - vector of posterior probabilities for classification task. - -See also MLPProcessI - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpprocess(const multilayerperceptron &network, const real_1d_array &x, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -'interactive' variant of MLPProcess for languages like Python which -support constructs like "Y = MLPProcess(NN,X)" and interactive mode of the -interpreter - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 21.09.2010 by Bochkanov Sergey -*************************************************************************/ -void mlpprocessi(const multilayerperceptron &network, const real_1d_array &x, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Error of the neural network on dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: - sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2) - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -double mlperror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Error of the neural network on dataset given by sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - NPoints - points count, >=0 - -RESULT: - sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2) - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -double mlperrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Natural error function for neural network, internal subroutine. - -NOTE: this function is single-threaded. Unlike other error function, it -receives no speed-up from being executed in SMP mode. - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -double mlperrorn(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Classification error of the neural network on dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: - classification error (number of misclassified cases) - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -ae_int_t mlpclserror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Relative classification error on the test set. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: -Percent of incorrectly classified cases. Works both for classifier -networks and general purpose networks used as classifiers. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 25.12.2008 by Bochkanov Sergey -*************************************************************************/ -double mlprelclserror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Relative classification error on the test set given by sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. Sparse matrix must use CRS format - for storage. - NPoints - points count, >=0. - -RESULT: -Percent of incorrectly classified cases. Works both for classifier -networks and general purpose networks used as classifiers. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 09.08.2012 by Bochkanov Sergey -*************************************************************************/ -double mlprelclserrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Average cross-entropy (in bits per element) on the test set. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: -CrossEntropy/(NPoints*LN(2)). -Zero if network solves regression task. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 08.01.2009 by Bochkanov Sergey -*************************************************************************/ -double mlpavgce(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Average cross-entropy (in bits per element) on the test set given by -sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - NPoints - points count, >=0. - -RESULT: -CrossEntropy/(NPoints*LN(2)). -Zero if network solves regression task. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 9.08.2012 by Bochkanov Sergey -*************************************************************************/ -double mlpavgcesparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -RMS error on the test set given. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: -Root mean square error. Its meaning for regression task is obvious. As for -classification task, RMS error means error when estimating posterior -probabilities. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -double mlprmserror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -RMS error on the test set given by sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - NPoints - points count, >=0. - -RESULT: -Root mean square error. Its meaning for regression task is obvious. As for -classification task, RMS error means error when estimating posterior -probabilities. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 09.08.2012 by Bochkanov Sergey -*************************************************************************/ -double mlprmserrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Average absolute error on the test set. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: -Its meaning for regression task is obvious. As for classification task, it -means average error when estimating posterior probabilities. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 11.03.2008 by Bochkanov Sergey -*************************************************************************/ -double mlpavgerror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Average absolute error on the test set given by sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - NPoints - points count, >=0. - -RESULT: -Its meaning for regression task is obvious. As for classification task, it -means average error when estimating posterior probabilities. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 09.08.2012 by Bochkanov Sergey -*************************************************************************/ -double mlpavgerrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Average relative error on the test set. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - NPoints - points count. - -RESULT: -Its meaning for regression task is obvious. As for classification task, it -means average relative error when estimating posterior probability of -belonging to the correct class. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 11.03.2008 by Bochkanov Sergey -*************************************************************************/ -double mlpavgrelerror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Average relative error on the test set given by sparse matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - NPoints - points count, >=0. - -RESULT: -Its meaning for regression task is obvious. As for classification task, it -means average relative error when estimating posterior probability of -belonging to the correct class. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 09.08.2012 by Bochkanov Sergey -*************************************************************************/ -double mlpavgrelerrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Gradient calculation - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - X - input vector, length of array must be at least NIn - DesiredY- desired outputs, length of array must be at least NOut - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) - Grad - gradient of E with respect to weights of network, array[WCount] - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpgrad(const multilayerperceptron &network, const real_1d_array &x, const real_1d_array &desiredy, double &e, real_1d_array &grad, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Gradient calculation (natural error function is used) - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - X - input vector, length of array must be at least NIn - DesiredY- desired outputs, length of array must be at least NOut - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, sum-of-squares for regression networks, - cross-entropy for classification networks. - Grad - gradient of E with respect to weights of network, array[WCount] - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpgradn(const multilayerperceptron &network, const real_1d_array &x, const real_1d_array &desiredy, double &e, real_1d_array &grad, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Batch gradient calculation for a set of inputs/outputs - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset in dense format; one sample = one row: - * first NIn columns contain inputs, - * for regression problem, next NOut columns store - desired outputs. - * for classification problem, next column (just one!) - stores class number. - SSize - number of elements in XY - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) - Grad - gradient of E with respect to weights of network, array[WCount] - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpgradbatch(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, double &e, real_1d_array &grad, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Batch gradient calculation for a set of inputs/outputs given by sparse -matrices - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset in sparse format; one sample = one row: - * MATRIX MUST BE STORED IN CRS FORMAT - * first NIn columns contain inputs. - * for regression problem, next NOut columns store - desired outputs. - * for classification problem, next column (just one!) - stores class number. - SSize - number of elements in XY - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) - Grad - gradient of E with respect to weights of network, array[WCount] - - -- ALGLIB -- - Copyright 26.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpgradbatchsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t ssize, double &e, real_1d_array &grad, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Batch gradient calculation for a subset of dataset - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset in dense format; one sample = one row: - * first NIn columns contain inputs, - * for regression problem, next NOut columns store - desired outputs. - * for classification problem, next column (just one!) - stores class number. - SetSize - real size of XY, SetSize>=0; - Idx - subset of SubsetSize elements, array[SubsetSize]: - * Idx[I] stores row index in the original dataset which is - given by XY. Gradient is calculated with respect to rows - whose indexes are stored in Idx[]. - * Idx[] must store correct indexes; this function throws - an exception in case incorrect index (less than 0 or - larger than rows(XY)) is given - * Idx[] may store indexes in any order and even with - repetitions. - SubsetSize- number of elements in Idx[] array: - * positive value means that subset given by Idx[] is processed - * zero value results in zero gradient - * negative value means that full dataset is processed - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) - Grad - gradient of E with respect to weights of network, - array[WCount] - - -- ALGLIB -- - Copyright 26.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpgradbatchsubset(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t setsize, const integer_1d_array &idx, const ae_int_t subsetsize, double &e, real_1d_array &grad, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Batch gradient calculation for a set of inputs/outputs for a subset of -dataset given by set of indexes. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset in sparse format; one sample = one row: - * MATRIX MUST BE STORED IN CRS FORMAT - * first NIn columns contain inputs, - * for regression problem, next NOut columns store - desired outputs. - * for classification problem, next column (just one!) - stores class number. - SetSize - real size of XY, SetSize>=0; - Idx - subset of SubsetSize elements, array[SubsetSize]: - * Idx[I] stores row index in the original dataset which is - given by XY. Gradient is calculated with respect to rows - whose indexes are stored in Idx[]. - * Idx[] must store correct indexes; this function throws - an exception in case incorrect index (less than 0 or - larger than rows(XY)) is given - * Idx[] may store indexes in any order and even with - repetitions. - SubsetSize- number of elements in Idx[] array: - * positive value means that subset given by Idx[] is processed - * zero value results in zero gradient - * negative value means that full dataset is processed - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) - Grad - gradient of E with respect to weights of network, - array[WCount] - -NOTE: when SubsetSize<0 is used full dataset by call MLPGradBatchSparse - function. - - -- ALGLIB -- - Copyright 26.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpgradbatchsparsesubset(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t setsize, const integer_1d_array &idx, const ae_int_t subsetsize, double &e, real_1d_array &grad, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Batch gradient calculation for a set of inputs/outputs -(natural error function is used) - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - set of inputs/outputs; one sample = one row; - first NIn columns contain inputs, - next NOut columns - desired outputs. - SSize - number of elements in XY - Grad - possibly preallocated array. If size of array is smaller - than WCount, it will be reallocated. It is recommended to - reuse previously allocated array to reduce allocation - overhead. - -OUTPUT PARAMETERS: - E - error function, sum-of-squares for regression networks, - cross-entropy for classification networks. - Grad - gradient of E with respect to weights of network, array[WCount] - - -- ALGLIB -- - Copyright 04.11.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpgradnbatch(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, double &e, real_1d_array &grad, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Batch Hessian calculation (natural error function) using R-algorithm. -Internal subroutine. - - -- ALGLIB -- - Copyright 26.01.2008 by Bochkanov Sergey. - - Hessian calculation based on R-algorithm described in - "Fast Exact Multiplication by the Hessian", - B. A. Pearlmutter, - Neural Computation, 1994. -*************************************************************************/ -void mlphessiannbatch(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, double &e, real_1d_array &grad, real_2d_array &h, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Batch Hessian calculation using R-algorithm. -Internal subroutine. - - -- ALGLIB -- - Copyright 26.01.2008 by Bochkanov Sergey. - - Hessian calculation based on R-algorithm described in - "Fast Exact Multiplication by the Hessian", - B. A. Pearlmutter, - Neural Computation, 1994. -*************************************************************************/ -void mlphessianbatch(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, double &e, real_1d_array &grad, real_2d_array &h, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Calculation of all types of errors on subset of dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset; one sample = one row; - first NIn columns contain inputs, - next NOut columns - desired outputs. - SetSize - real size of XY, SetSize>=0; - Subset - subset of SubsetSize elements, array[SubsetSize]; - SubsetSize- number of elements in Subset[] array: - * if SubsetSize>0, rows of XY with indices Subset[0]... - ...Subset[SubsetSize-1] are processed - * if SubsetSize=0, zeros are returned - * if SubsetSize<0, entire dataset is processed; Subset[] - array is ignored in this case. - -OUTPUT PARAMETERS: - Rep - it contains all type of errors. - - -- ALGLIB -- - Copyright 04.09.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpallerrorssubset(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize, modelerrors &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Calculation of all types of errors on subset of dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - network initialized with one of the network creation funcs - XY - original dataset given by sparse matrix; - one sample = one row; - first NIn columns contain inputs, - next NOut columns - desired outputs. - SetSize - real size of XY, SetSize>=0; - Subset - subset of SubsetSize elements, array[SubsetSize]; - SubsetSize- number of elements in Subset[] array: - * if SubsetSize>0, rows of XY with indices Subset[0]... - ...Subset[SubsetSize-1] are processed - * if SubsetSize=0, zeros are returned - * if SubsetSize<0, entire dataset is processed; Subset[] - array is ignored in this case. - -OUTPUT PARAMETERS: - Rep - it contains all type of errors. - - - -- ALGLIB -- - Copyright 04.09.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpallerrorssparsesubset(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize, modelerrors &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Error of the neural network on subset of dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format; - SetSize - real size of XY, SetSize>=0; - Subset - subset of SubsetSize elements, array[SubsetSize]; - SubsetSize- number of elements in Subset[] array: - * if SubsetSize>0, rows of XY with indices Subset[0]... - ...Subset[SubsetSize-1] are processed - * if SubsetSize=0, zeros are returned - * if SubsetSize<0, entire dataset is processed; Subset[] - array is ignored in this case. - -RESULT: - sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2) - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 04.09.2012 by Bochkanov Sergey -*************************************************************************/ -double mlperrorsubset(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Error of the neural network on subset of sparse dataset. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Network - neural network; - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Sparse matrix must use CRS format for - storage. - SetSize - real size of XY, SetSize>=0; - it is used when SubsetSize<0; - Subset - subset of SubsetSize elements, array[SubsetSize]; - SubsetSize- number of elements in Subset[] array: - * if SubsetSize>0, rows of XY with indices Subset[0]... - ...Subset[SubsetSize-1] are processed - * if SubsetSize=0, zeros are returned - * if SubsetSize<0, entire dataset is processed; Subset[] - array is ignored in this case. - -RESULT: - sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2) - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -dataset format is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 04.09.2012 by Bochkanov Sergey -*************************************************************************/ -double mlperrorsparsesubset(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_LDA) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Multiclass Fisher LDA - -Subroutine finds coefficients of linear combination which optimally separates -training set on classes. - -COMMERCIAL EDITION OF ALGLIB: - - ! Commercial version of ALGLIB includes two important improvements of - ! this function, which can be used from C++ and C#: - ! * Intel MKL support (lightweight Intel MKL is shipped with ALGLIB) - ! * multithreading support - ! - ! Intel MKL gives approximately constant (with respect to number of - ! worker threads) acceleration factor which depends on CPU being used, - ! problem size and "baseline" ALGLIB edition which is used for - ! comparison. Best results are achieved for high-dimensional problems - ! (NVars is at least 256). - ! - ! Multithreading is used to accelerate initial phase of LDA, which - ! includes calculation of products of large matrices. Again, for best - ! efficiency problem must be high-dimensional. - ! - ! Generally, commercial ALGLIB is several times faster than open-source - ! generic C edition, and many times faster than open-source C# edition. - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - training set, array[0..NPoints-1,0..NVars]. - First NVars columns store values of independent - variables, next column stores number of class (from 0 - to NClasses-1) which dataset element belongs to. Fractional - values are rounded to nearest integer. - NPoints - training set size, NPoints>=0 - NVars - number of independent variables, NVars>=1 - NClasses - number of classes, NClasses>=2 - - -OUTPUT PARAMETERS: - Info - return code: - * -4, if internal EVD subroutine hasn't converged - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed (NPoints<0, - NVars<1, NClasses<2) - * 1, if task has been solved - * 2, if there was a multicollinearity in training set, - but task has been solved. - W - linear combination coefficients, array[0..NVars-1] - - -- ALGLIB -- - Copyright 31.05.2008 by Bochkanov Sergey -*************************************************************************/ -void fisherlda(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, ae_int_t &info, real_1d_array &w, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -N-dimensional multiclass Fisher LDA - -Subroutine finds coefficients of linear combinations which optimally separates -training set on classes. It returns N-dimensional basis whose vector are sorted -by quality of training set separation (in descending order). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - training set, array[0..NPoints-1,0..NVars]. - First NVars columns store values of independent - variables, next column stores number of class (from 0 - to NClasses-1) which dataset element belongs to. Fractional - values are rounded to nearest integer. - NPoints - training set size, NPoints>=0 - NVars - number of independent variables, NVars>=1 - NClasses - number of classes, NClasses>=2 - - -OUTPUT PARAMETERS: - Info - return code: - * -4, if internal EVD subroutine hasn't converged - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed (NPoints<0, - NVars<1, NClasses<2) - * 1, if task has been solved - * 2, if there was a multicollinearity in training set, - but task has been solved. - W - basis, array[0..NVars-1,0..NVars-1] - columns of matrix stores basis vectors, sorted by - quality of training set separation (in descending order) - - -- ALGLIB -- - Copyright 31.05.2008 by Bochkanov Sergey -*************************************************************************/ -void fisherldan(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, ae_int_t &info, real_2d_array &w, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_SSA) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This function creates SSA model object. Right after creation model is in -"dummy" mode - you can add data, but analyzing/prediction will return -just zeros (it assumes that basis is empty). - -HOW TO USE SSA MODEL: - -1. create model with ssacreate() -2. add data with one/many ssaaddsequence() calls -3. choose SSA algorithm with one of ssasetalgo...() functions: - * ssasetalgotopkdirect() for direct one-run analysis - * ssasetalgotopkrealtime() for algorithm optimized for many subsequent - runs with warm-start capabilities - * ssasetalgoprecomputed() for user-supplied basis -4. set window width with ssasetwindow() -5. perform one of the analysis-related activities: - a) call ssagetbasis() to get basis - b) call ssaanalyzelast() ssaanalyzesequence() or ssaanalyzelastwindow() - to perform analysis (trend/noise separation) - c) call one of the forecasting functions (ssaforecastlast() or - ssaforecastsequence()) to perform prediction; alternatively, you can - extract linear recurrence coefficients with ssagetlrr(). - SSA analysis will be performed during first call to analysis-related - function. SSA model is smart enough to track all changes in the dataset - and model settings, to cache previously computed basis and to - re-evaluate basis only when necessary. - -Additionally, if your setting involves constant stream of incoming data, -you can perform quick update already calculated model with one of the -incremental append-and-update functions: ssaappendpointandupdate() or -ssaappendsequenceandupdate(). - -NOTE: steps (2), (3), (4) can be performed in arbitrary order. - -INPUT PARAMETERS: - none - -OUTPUT PARAMETERS: - S - structure which stores model state - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssacreate(ssamodel &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets window width for SSA model. You should call it before -analysis phase. Default window width is 1 (not for real use). - -Special notes: -* this function call can be performed at any moment before first call to - analysis-related functions -* changing window width invalidates internally stored basis; if you change - window width AFTER you call analysis-related function, next analysis - phase will require re-calculation of the basis according to current - algorithm. -* calling this function with exactly same window width as current one has - no effect -* if you specify window width larger than any data sequence stored in the - model, analysis will return zero basis. - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - WindowWidth - >=1, new window width - -OUTPUT PARAMETERS: - S - SSA model, updated - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssasetwindow(const ssamodel &s, const ae_int_t windowwidth, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets seed which is used to initialize internal RNG when -we make pseudorandom decisions on model updates. - -By default, deterministic seed is used - which results in same sequence of -pseudorandom decisions every time you run SSA model. If you specify non- -deterministic seed value, then SSA model may return slightly different -results after each run. - -This function can be useful when you have several SSA models updated with -sseappendpointandupdate() called with 01 means that delayed power-up is performed - - -- ALGLIB -- - Copyright 03.11.2017 by Bochkanov Sergey -*************************************************************************/ -void ssasetpoweruplength(const ssamodel &s, const ae_int_t pwlen, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets memory limit of SSA analysis. - -Straightforward SSA with sequence length T and window width W needs O(T*W) -memory. It is possible to reduce memory consumption by splitting task into -smaller chunks. - -Thus function allows you to specify approximate memory limit (measured in -double precision numbers used for buffers). Actual memory consumption will -be comparable to the number specified by you. - -Default memory limit is 50.000.000 (400Mbytes) in current version. - -INPUT PARAMETERS: - S - SSA model - MemLimit- memory limit, >=0. Zero value means no limit. - - -- ALGLIB -- - Copyright 20.12.2017 by Bochkanov Sergey -*************************************************************************/ -void ssasetmemorylimit(const ssamodel &s, const ae_int_t memlimit, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function adds data sequence to SSA model. Only single-dimensional -sequences are supported. - -What is a sequences? Following definitions/requirements apply: -* a sequence is an array of values measured in subsequent, equally - separated time moments (ticks). -* you may have many sequences in your dataset; say, one sequence may - correspond to one trading session. -* sequence length should be larger than current window length (shorter - sequences will be ignored during analysis). -* analysis is performed within a sequence; different sequences are NOT - stacked together to produce one large contiguous stream of data. -* analysis is performed for all sequences at once, i.e. same set of basis - vectors is computed for all sequences - -INCREMENTAL ANALYSIS - -This function is non intended for incremental updates of previously found -SSA basis. Calling it invalidates all previous analysis results (basis is -reset and will be recalculated from zero during next analysis). - -If you want to perform incremental/real-time SSA, consider using -following functions: -* ssaappendpointandupdate() for appending one point -* ssaappendsequenceandupdate() for appending new sequence - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - X - array[N], data, can be larger (additional values - are ignored) - N - data length, can be automatically determined from - the array length. N>=0. - -OUTPUT PARAMETERS: - S - SSA model, updated - -NOTE: you can clear dataset with ssacleardata() - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaaddsequence(const ssamodel &s, const real_1d_array &x, const ae_int_t n, const xparams _xparams = alglib::xdefault); -void ssaaddsequence(const ssamodel &s, const real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function appends single point to last data sequence stored in the SSA -model and tries to update model in the incremental manner (if possible -with current algorithm). - -If you want to add more than one point at once: -* if you want to add M points to the same sequence, perform M-1 calls with - UpdateIts parameter set to 0.0, and last call with non-zero UpdateIts. -* if you want to add new sequence, use ssaappendsequenceandupdate() - -Running time of this function does NOT depend on dataset size, only on -window width and number of singular vectors. Depending on algorithm being -used, incremental update has complexity: -* for top-K real time - O(UpdateIts*K*Width^2), with fractional UpdateIts -* for top-K direct - O(Width^3) for any non-zero UpdateIts -* for precomputed basis - O(1), no update is performed - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - X - new point - UpdateIts - >=0, floating point (!) value, desired update - frequency: - * zero value means that point is stored, but no - update is performed - * integer part of the value means that specified - number of iterations is always performed - * fractional part of the value means that one - iteration is performed with this probability. - - Recommended value: 0=1, number of ticks in the sequence - UpdateIts - >=0, floating point (!) value, desired update - frequency: - * zero value means that point is stored, but no - update is performed - * integer part of the value means that specified - number of iterations is always performed - * fractional part of the value means that one - iteration is performed with this probability. - - Recommended value: 0=1 - NBasis - number of basis vectors, 1<=NBasis<=WindowWidth - -OUTPUT PARAMETERS: - S - updated model - -NOTE: calling this function invalidates basis in all cases. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssasetalgoprecomputed(const ssamodel &s, const real_2d_array &a, const ae_int_t windowwidth, const ae_int_t nbasis, const xparams _xparams = alglib::xdefault); -void ssasetalgoprecomputed(const ssamodel &s, const real_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets SSA algorithm to "direct top-K" algorithm. - -"Direct top-K" algorithm performs full SVD of the N*WINDOW trajectory -matrix (hence its name - direct solver is used), then extracts top K -components. Overall running time is O(N*WINDOW^2), where N is a number of -ticks in the dataset, WINDOW is window width. - -This algorithm may handle "append" requests which add just one/few ticks -to the end of the last sequence in O(WINDOW^3) time, which is ~N/WINDOW -times faster than re-computing everything from scratch. - -INPUT PARAMETERS: - S - SSA model - TopK - number of components to analyze; TopK>=1. - -OUTPUT PARAMETERS: - S - updated model - - -NOTE: TopK>WindowWidth is silently decreased to WindowWidth during analysis - phase - -NOTE: calling this function invalidates basis, except for the situation - when this algorithm was already set with same parameters. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssasetalgotopkdirect(const ssamodel &s, const ae_int_t topk, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets SSA algorithm to "top-K real time algorithm". This algo -extracts K components with largest singular values. - -It is real-time version of top-K algorithm which is optimized for -incremental processing and fast start-up. Internally it uses subspace -eigensolver for truncated SVD. It results in ability to perform quick -updates of the basis when only a few points/sequences is added to dataset. - -Performance profile of the algorithm is given below: -* O(K*WindowWidth^2) running time for incremental update of the dataset - with one of the "append-and-update" functions (ssaappendpointandupdate() - or ssaappendsequenceandupdate()). -* O(N*WindowWidth^2) running time for initial basis evaluation (N=size of - dataset) -* ability to split costly initialization across several incremental - updates of the basis (so called "Power-Up" functionality, activated by - ssasetpoweruplength() function) - -INPUT PARAMETERS: - S - SSA model - TopK - number of components to analyze; TopK>=1. - -OUTPUT PARAMETERS: - S - updated model - -NOTE: this algorithm is optimized for large-scale tasks with large - datasets. On toy problems with just 5-10 points it can return basis - which is slightly different from that returned by direct algorithm - (ssasetalgotopkdirect() function). However, the difference becomes - negligible as dataset grows. - -NOTE: TopK>WindowWidth is silently decreased to WindowWidth during analysis - phase - -NOTE: calling this function invalidates basis, except for the situation - when this algorithm was already set with same parameters. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssasetalgotopkrealtime(const ssamodel &s, const ae_int_t topk, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function clears all data stored in the model and invalidates all -basis components found so far. - -INPUT PARAMETERS: - S - SSA model created with ssacreate() - -OUTPUT PARAMETERS: - S - SSA model, updated - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssacleardata(const ssamodel &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function executes SSA on internally stored dataset and returns basis -found by current method. - -INPUT PARAMETERS: - S - SSA model - -OUTPUT PARAMETERS: - A - array[WindowWidth,NBasis], basis; vectors are - stored in matrix columns, by descreasing variance - SV - array[NBasis]: - * zeros - for model initialized with SSASetAlgoPrecomputed() - * singular values - for other algorithms - WindowWidth - current window - NBasis - basis size - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Calling this function in degenerate cases (no data or all data are -shorter than window size; no algorithm is specified) returns basis with -just one zero vector. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssagetbasis(const ssamodel &s, real_2d_array &a, real_1d_array &sv, ae_int_t &windowwidth, ae_int_t &nbasis, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function returns linear recurrence relation (LRR) coefficients found -by current SSA algorithm. - -INPUT PARAMETERS: - S - SSA model - -OUTPUT PARAMETERS: - A - array[WindowWidth-1]. Coefficients of the - linear recurrence of the form: - X[W-1] = X[W-2]*A[W-2] + X[W-3]*A[W-3] + ... + X[0]*A[0]. - Empty array for WindowWidth=1. - WindowWidth - current window width - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Calling this function in degenerate cases (no data or all data are -shorter than window size; no algorithm is specified) returns zeros. - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssagetlrr(const ssamodel &s, real_1d_array &a, ae_int_t &windowwidth, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function executes SSA on internally stored dataset and returns -analysis for the last window of the last sequence. Such analysis is -an lightweight alternative for full scale reconstruction (see below). - -Typical use case for this function is real-time setting, when you are -interested in quick-and-dirty (very quick and very dirty) processing of -just a few last ticks of the trend. - -IMPORTANT: full scale SSA involves analysis of the ENTIRE dataset, - with reconstruction being done for all positions of sliding - window with subsequent hankelization (diagonal averaging) of - the resulting matrix. - - Such analysis requires O((DataLen-Window)*Window*NBasis) FLOPs - and can be quite costly. However, it has nice noise-canceling - effects due to averaging. - - This function performs REDUCED analysis of the last window. It - is much faster - just O(Window*NBasis), but its results are - DIFFERENT from that of ssaanalyzelast(). In particular, first - few points of the trend are much more prone to noise. - -INPUT PARAMETERS: - S - SSA model - -OUTPUT PARAMETERS: - Trend - array[WindowSize], reconstructed trend line - Noise - array[WindowSize], the rest of the signal; - it holds that ActualData = Trend+Noise. - NTicks - current WindowSize - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - -In any case, only basis is reused. Reconstruction is performed from -scratch every time you call this function. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* last sequence is shorter than the window length (analysis can be done, - but we can not perform reconstruction on the last sequence) - -Calling this function in degenerate cases returns following result: -* in any case, WindowWidth ticks is returned -* trend is assumed to be zero -* noise is initialized by the last sequence; if last sequence is shorter - than the window size, it is moved to the end of the array, and the - beginning of the noise array is filled by zeros - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaanalyzelastwindow(const ssamodel &s, real_1d_array &trend, real_1d_array &noise, ae_int_t &nticks, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function: -* builds SSA basis using internally stored (entire) dataset -* returns reconstruction for the last NTicks of the last sequence - -If you want to analyze some other sequence, use ssaanalyzesequence(). - -Reconstruction phase involves generation of NTicks-WindowWidth sliding -windows, their decomposition using empirical orthogonal functions found by -SSA, followed by averaging of each data point across several overlapping -windows. Thus, every point in the output trend is reconstructed using up -to WindowWidth overlapping windows (WindowWidth windows exactly in the -inner points, just one window at the extremal points). - -IMPORTANT: due to averaging this function returns different results for - different values of NTicks. It is expected and not a bug. - - For example: - * Trend[NTicks-1] is always same because it is not averaged in - any case (same applies to Trend[0]). - * Trend[NTicks-2] has different values for NTicks=WindowWidth - and NTicks=WindowWidth+1 because former case means that no - averaging is performed, and latter case means that averaging - using two sliding windows is performed. Larger values of - NTicks produce same results as NTicks=WindowWidth+1. - * ...and so on... - -PERFORMANCE: this function has O((NTicks-WindowWidth)*WindowWidth*NBasis) - running time. If you work in time-constrained setting and - have to analyze just a few last ticks, choosing NTicks equal - to WindowWidth+SmoothingLen, with SmoothingLen=1...WindowWidth - will result in good compromise between noise cancellation and - analysis speed. - -INPUT PARAMETERS: - S - SSA model - NTicks - number of ticks to analyze, Nticks>=1. - * special case of NTicks<=WindowWidth is handled - by analyzing last window and returning NTicks - last ticks. - * special case NTicks>LastSequenceLen is handled - by prepending result with NTicks-LastSequenceLen - zeros. - -OUTPUT PARAMETERS: - Trend - array[NTicks], reconstructed trend line - Noise - array[NTicks], the rest of the signal; - it holds that ActualData = Trend+Noise. - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - -In any case, only basis is reused. Reconstruction is performed from -scratch every time you call this function. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* last sequence is shorter than the window length (analysis can be done, - but we can not perform reconstruction on the last sequence) - -Calling this function in degenerate cases returns following result: -* in any case, NTicks ticks is returned -* trend is assumed to be zero -* noise is initialized by the last sequence; if last sequence is shorter - than the window size, it is moved to the end of the array, and the - beginning of the noise array is filled by zeros - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaanalyzelast(const ssamodel &s, const ae_int_t nticks, real_1d_array &trend, real_1d_array &noise, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function: -* builds SSA basis using internally stored (entire) dataset -* returns reconstruction for the sequence being passed to this function - -If you want to analyze last sequence stored in the model, use -ssaanalyzelast(). - -Reconstruction phase involves generation of NTicks-WindowWidth sliding -windows, their decomposition using empirical orthogonal functions found by -SSA, followed by averaging of each data point across several overlapping -windows. Thus, every point in the output trend is reconstructed using up -to WindowWidth overlapping windows (WindowWidth windows exactly in the -inner points, just one window at the extremal points). - -PERFORMANCE: this function has O((NTicks-WindowWidth)*WindowWidth*NBasis) - running time. If you work in time-constrained setting and - have to analyze just a few last ticks, choosing NTicks equal - to WindowWidth+SmoothingLen, with SmoothingLen=1...WindowWidth - will result in good compromise between noise cancellation and - analysis speed. - -INPUT PARAMETERS: - S - SSA model - Data - array[NTicks], can be larger (only NTicks leading - elements will be used) - NTicks - number of ticks to analyze, Nticks>=1. - * special case of NTicks=1 - -OUTPUT PARAMETERS: - Trend - array[NTicks], predicted trend line - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* last sequence is shorter than the WindowWidth (analysis can be done, - but we can not perform forecasting on the last sequence) -* window lentgh is 1 (impossible to use for forecasting) -* SSA analysis algorithm is configured to extract basis whose size is - equal to window length (impossible to use for forecasting; only basis - whose size is less than window length can be used). - -Calling this function in degenerate cases returns following result: -* NTicks copies of the last value is returned for non-empty task with - large enough dataset, but with overcomplete basis (window width=1 or - basis size is equal to window width) -* zero trend with length=NTicks is returned for empty task - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is ever constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaforecastlast(const ssamodel &s, const ae_int_t nticks, real_1d_array &trend, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function builds SSA basis and performs forecasting for a user- -specified sequence, returning value of trend. - -Forecasting is done in two stages: -* first, we extract trend from the WindowWidth last elements of the - sequence. This stage is optional, you can turn it off if you pass - data which are already processed with SSA. Of course, you can turn it - off even for raw data, but it is not recommended - noise suppression is - very important for correct prediction. -* then, we apply LRR for last WindowWidth-1 elements of the extracted - trend. - -This function has following running time: -* O(NBasis*WindowWidth) for trend extraction phase -* O(WindowWidth*NTicks) for forecast phase - -NOTE: this algorithm performs prediction using only one - last - sliding - window. Predictions produced by such approach are smooth - continuations of the reconstructed trend line, but they can be - easily corrupted by noise. If you need noise-resistant prediction, - use ssaforecastavgsequence() function, which averages predictions - built using several sliding windows. - -INPUT PARAMETERS: - S - SSA model - Data - array[NTicks], data to forecast - DataLen - number of ticks in the data, DataLen>=1 - ForecastLen - number of ticks to predict, ForecastLen>=1 - ApplySmoothing - whether to apply smoothing trend extraction or not; - if you do not know what to specify, pass True. - -OUTPUT PARAMETERS: - Trend - array[ForecastLen], forecasted trend - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* data sequence is shorter than the WindowWidth (analysis can be done, - but we can not perform forecasting on the last sequence) -* window lentgh is 1 (impossible to use for forecasting) -* SSA analysis algorithm is configured to extract basis whose size is - equal to window length (impossible to use for forecasting; only basis - whose size is less than window length can be used). - -Calling this function in degenerate cases returns following result: -* ForecastLen copies of the last value is returned for non-empty task with - large enough dataset, but with overcomplete basis (window width=1 or - basis size is equal to window width) -* zero trend with length=ForecastLen is returned for empty task - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is ever constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaforecastsequence(const ssamodel &s, const real_1d_array &data, const ae_int_t datalen, const ae_int_t forecastlen, const bool applysmoothing, real_1d_array &trend, const xparams _xparams = alglib::xdefault); -void ssaforecastsequence(const ssamodel &s, const real_1d_array &data, const ae_int_t forecastlen, real_1d_array &trend, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function builds SSA basis and performs forecasting for a specified -number of ticks, returning value of trend. - -Forecast is performed as follows: -* SSA trend extraction is applied to last M sliding windows of the - internally stored dataset -* for each of M sliding windows, M predictions are built -* average value of M predictions is returned - -This function has following running time: -* O(NBasis*WindowWidth*M) for trend extraction phase (always performed) -* O(WindowWidth*NTicks*M) for forecast phase - -NOTE: noise reduction is ALWAYS applied by this algorithm; if you want to - apply recurrence relation to raw unprocessed data, use another - function - ssaforecastsequence() which allows to turn on and off - noise reduction phase. - -NOTE: combination of several predictions results in lesser sensitivity to - noise, but it may produce undesirable discontinuities between last - point of the trend and first point of the prediction. The reason is - that last point of the trend is usually corrupted by noise, but - average value of several predictions is less sensitive to noise, - thus discontinuity appears. It is not a bug. - -INPUT PARAMETERS: - S - SSA model - M - number of sliding windows to combine, M>=1. If - your dataset has less than M sliding windows, this - parameter will be silently reduced. - NTicks - number of ticks to forecast, NTicks>=1 - -OUTPUT PARAMETERS: - Trend - array[NTicks], predicted trend line - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* last sequence is shorter than the WindowWidth (analysis can be done, - but we can not perform forecasting on the last sequence) -* window lentgh is 1 (impossible to use for forecasting) -* SSA analysis algorithm is configured to extract basis whose size is - equal to window length (impossible to use for forecasting; only basis - whose size is less than window length can be used). - -Calling this function in degenerate cases returns following result: -* NTicks copies of the last value is returned for non-empty task with - large enough dataset, but with overcomplete basis (window width=1 or - basis size is equal to window width) -* zero trend with length=NTicks is returned for empty task - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is ever constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaforecastavglast(const ssamodel &s, const ae_int_t m, const ae_int_t nticks, real_1d_array &trend, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function builds SSA basis and performs forecasting for a user- -specified sequence, returning value of trend. - -Forecasting is done in two stages: -* first, we extract trend from M last sliding windows of the sequence. - This stage is optional, you can turn it off if you pass data which - are already processed with SSA. Of course, you can turn it off even - for raw data, but it is not recommended - noise suppression is very - important for correct prediction. -* then, we apply LRR independently for M sliding windows -* average of M predictions is returned - -This function has following running time: -* O(NBasis*WindowWidth*M) for trend extraction phase -* O(WindowWidth*NTicks*M) for forecast phase - -NOTE: combination of several predictions results in lesser sensitivity to - noise, but it may produce undesirable discontinuities between last - point of the trend and first point of the prediction. The reason is - that last point of the trend is usually corrupted by noise, but - average value of several predictions is less sensitive to noise, - thus discontinuity appears. It is not a bug. - -INPUT PARAMETERS: - S - SSA model - Data - array[NTicks], data to forecast - DataLen - number of ticks in the data, DataLen>=1 - M - number of sliding windows to combine, M>=1. If - your dataset has less than M sliding windows, this - parameter will be silently reduced. - ForecastLen - number of ticks to predict, ForecastLen>=1 - ApplySmoothing - whether to apply smoothing trend extraction or not. - if you do not know what to specify, pass true. - -OUTPUT PARAMETERS: - Trend - array[ForecastLen], forecasted trend - - -CACHING/REUSE OF THE BASIS - -Caching/reuse of previous results is performed: -* first call performs full run of SSA; basis is stored in the cache -* subsequent calls reuse previously cached basis -* if you call any function which changes model properties (window length, - algorithm, dataset), internal basis will be invalidated. -* the only calls which do NOT invalidate basis are listed below: - a) ssasetwindow() with same window length - b) ssaappendpointandupdate() - c) ssaappendsequenceandupdate() - d) ssasetalgotopk...() with exactly same K - Calling these functions will result in reuse of previously found basis. - - -HANDLING OF DEGENERATE CASES - -Following degenerate cases may happen: -* dataset is empty (no analysis can be done) -* all sequences are shorter than the window length,no analysis can be done -* no algorithm is specified (no analysis can be done) -* data sequence is shorter than the WindowWidth (analysis can be done, - but we can not perform forecasting on the last sequence) -* window lentgh is 1 (impossible to use for forecasting) -* SSA analysis algorithm is configured to extract basis whose size is - equal to window length (impossible to use for forecasting; only basis - whose size is less than window length can be used). - -Calling this function in degenerate cases returns following result: -* ForecastLen copies of the last value is returned for non-empty task with - large enough dataset, but with overcomplete basis (window width=1 or - basis size is equal to window width) -* zero trend with length=ForecastLen is returned for empty task - -No analysis is performed in degenerate cases (we immediately return dummy -values, no basis is ever constructed). - - -- ALGLIB -- - Copyright 30.10.2017 by Bochkanov Sergey -*************************************************************************/ -void ssaforecastavgsequence(const ssamodel &s, const real_1d_array &data, const ae_int_t datalen, const ae_int_t m, const ae_int_t forecastlen, const bool applysmoothing, real_1d_array &trend, const xparams _xparams = alglib::xdefault); -void ssaforecastavgsequence(const ssamodel &s, const real_1d_array &data, const ae_int_t m, const ae_int_t forecastlen, real_1d_array &trend, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_LINREG) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Linear regression - -Subroutine builds model: - - Y = A(0)*X[0] + ... + A(N-1)*X[N-1] + A(N) - -and model found in ALGLIB format, covariation matrix, training set errors -(rms, average, average relative) and leave-one-out cross-validation -estimate of the generalization error. CV estimate calculated using fast -algorithm with O(NPoints*NVars) complexity. - -When covariation matrix is calculated standard deviations of function -values are assumed to be equal to RMS error on the training set. - -INPUT PARAMETERS: - XY - training set, array [0..NPoints-1,0..NVars]: - * NVars columns - independent variables - * last column - dependent variable - NPoints - training set size, NPoints>NVars+1 - NVars - number of independent variables - -OUTPUT PARAMETERS: - Info - return code: - * -255, in case of unknown internal error - * -4, if internal SVD subroutine haven't converged - * -1, if incorrect parameters was passed (NPoints0. - NPoints - training set size, NPoints>NVars+1 - NVars - number of independent variables - -OUTPUT PARAMETERS: - Info - return code: - * -255, in case of unknown internal error - * -4, if internal SVD subroutine haven't converged - * -1, if incorrect parameters was passed (NPoints=0 - K - K>=1 (K can be larger than N , such cases will be - correctly handled). Window width. K=1 corresponds to - identity transformation (nothing changes). - -OUTPUT PARAMETERS: - X - array, whose first N elements were processed with SMA(K) - -NOTE 1: this function uses efficient in-place algorithm which does not - allocate temporary arrays. - -NOTE 2: this algorithm makes only one pass through array and uses running - sum to speed-up calculation of the averages. Additional measures - are taken to ensure that running sum on a long sequence of zero - elements will be correctly reset to zero even in the presence of - round-off error. - -NOTE 3: this is unsymmetric version of the algorithm, which does NOT - averages points after the current one. Only X[i], X[i-1], ... are - used when calculating new value of X[i]. We should also note that - this algorithm uses BOTH previous points and current one, i.e. - new value of X[i] depends on BOTH previous point and X[i] itself. - - -- ALGLIB -- - Copyright 25.10.2011 by Bochkanov Sergey -*************************************************************************/ -void filtersma(real_1d_array &x, const ae_int_t n, const ae_int_t k, const xparams _xparams = alglib::xdefault); -void filtersma(real_1d_array &x, const ae_int_t k, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Filters: exponential moving averages. - -This filter replaces array by results of EMA(alpha) filter. EMA(alpha) is -defined as filter which replaces X[] by S[]: - S[0] = X[0] - S[t] = alpha*X[t] + (1-alpha)*S[t-1] - -INPUT PARAMETERS: - X - array[N], array to process. It can be larger than N, - in this case only first N points are processed. - N - points count, N>=0 - alpha - 0=0 - K - K>=1 (K can be larger than N , such cases will be - correctly handled). Window width. K=1 corresponds to - identity transformation (nothing changes). - -OUTPUT PARAMETERS: - X - array, whose first N elements were processed with SMA(K) - -NOTE 1: this function uses efficient in-place algorithm which does not - allocate temporary arrays. - -NOTE 2: this algorithm makes only one pass through array and uses running - sum to speed-up calculation of the averages. Additional measures - are taken to ensure that running sum on a long sequence of zero - elements will be correctly reset to zero even in the presence of - round-off error. - -NOTE 3: this is unsymmetric version of the algorithm, which does NOT - averages points after the current one. Only X[i], X[i-1], ... are - used when calculating new value of X[i]. We should also note that - this algorithm uses BOTH previous points and current one, i.e. - new value of X[i] depends on BOTH previous point and X[i] itself. - - -- ALGLIB -- - Copyright 25.10.2011 by Bochkanov Sergey -*************************************************************************/ -void filterlrma(real_1d_array &x, const ae_int_t n, const ae_int_t k, const xparams _xparams = alglib::xdefault); -void filterlrma(real_1d_array &x, const ae_int_t k, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_LOGIT) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This subroutine trains logit model. - -INPUT PARAMETERS: - XY - training set, array[0..NPoints-1,0..NVars] - First NVars columns store values of independent - variables, next column stores number of class (from 0 - to NClasses-1) which dataset element belongs to. Fractional - values are rounded to nearest integer. - NPoints - training set size, NPoints>=1 - NVars - number of independent variables, NVars>=1 - NClasses - number of classes, NClasses>=2 - -OUTPUT PARAMETERS: - Info - return code: - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed - (NPoints=1 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdcreate(const ae_int_t n, mcpdstate &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -DESCRIPTION: - -This function is a specialized version of MCPDCreate() function, and we -recommend you to read comments for this function for general information -about MCPD solver. - -This function creates MCPD (Markov Chains for Population Data) solver -for "Entry-state" model, i.e. model where transition from X[i] to X[i+1] -is modelled as - X[i+1] = P*X[i] -where - X[i] and X[i+1] are N-dimensional state vectors - P is a N*N transition matrix -and one selected component of X[] is called "entry" state and is treated -in a special way: - system state always transits from "entry" state to some another state - system state can not transit from any state into "entry" state -Such conditions basically mean that row of P which corresponds to "entry" -state is zero. - -Such models arise when: -* there is some population of individuals -* individuals can have different states -* individuals can transit from one state to another -* population size is NOT constant - at every moment of time there is some - (unpredictable) amount of "new" individuals, which can transit into one - of the states at the next turn, but still no one leaves population -* you want to model transitions of individuals from one state into another -* but you do NOT want to predict amount of "new" individuals because it - does not depends on individuals already present (hence system can not - transit INTO entry state - it can only transit FROM it). - -This model is discussed in more details in the ALGLIB User Guide (see -http://www.alglib.net/dataanalysis/ for more data). - -INPUT PARAMETERS: - N - problem dimension, N>=2 - EntryState- index of entry state, in 0..N-1 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdcreateentry(const ae_int_t n, const ae_int_t entrystate, mcpdstate &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -DESCRIPTION: - -This function is a specialized version of MCPDCreate() function, and we -recommend you to read comments for this function for general information -about MCPD solver. - -This function creates MCPD (Markov Chains for Population Data) solver -for "Exit-state" model, i.e. model where transition from X[i] to X[i+1] -is modelled as - X[i+1] = P*X[i] -where - X[i] and X[i+1] are N-dimensional state vectors - P is a N*N transition matrix -and one selected component of X[] is called "exit" state and is treated -in a special way: - system state can transit from any state into "exit" state - system state can not transit from "exit" state into any other state - transition operator discards "exit" state (makes it zero at each turn) -Such conditions basically mean that column of P which corresponds to -"exit" state is zero. Multiplication by such P may decrease sum of vector -components. - -Such models arise when: -* there is some population of individuals -* individuals can have different states -* individuals can transit from one state to another -* population size is NOT constant - individuals can move into "exit" state - and leave population at the next turn, but there are no new individuals -* amount of individuals which leave population can be predicted -* you want to model transitions of individuals from one state into another - (including transitions into the "exit" state) - -This model is discussed in more details in the ALGLIB User Guide (see -http://www.alglib.net/dataanalysis/ for more data). - -INPUT PARAMETERS: - N - problem dimension, N>=2 - ExitState- index of exit state, in 0..N-1 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdcreateexit(const ae_int_t n, const ae_int_t exitstate, mcpdstate &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -DESCRIPTION: - -This function is a specialized version of MCPDCreate() function, and we -recommend you to read comments for this function for general information -about MCPD solver. - -This function creates MCPD (Markov Chains for Population Data) solver -for "Entry-Exit-states" model, i.e. model where transition from X[i] to -X[i+1] is modelled as - X[i+1] = P*X[i] -where - X[i] and X[i+1] are N-dimensional state vectors - P is a N*N transition matrix -one selected component of X[] is called "entry" state and is treated in a -special way: - system state always transits from "entry" state to some another state - system state can not transit from any state into "entry" state -and another one component of X[] is called "exit" state and is treated in -a special way too: - system state can transit from any state into "exit" state - system state can not transit from "exit" state into any other state - transition operator discards "exit" state (makes it zero at each turn) -Such conditions basically mean that: - row of P which corresponds to "entry" state is zero - column of P which corresponds to "exit" state is zero -Multiplication by such P may decrease sum of vector components. - -Such models arise when: -* there is some population of individuals -* individuals can have different states -* individuals can transit from one state to another -* population size is NOT constant -* at every moment of time there is some (unpredictable) amount of "new" - individuals, which can transit into one of the states at the next turn -* some individuals can move (predictably) into "exit" state and leave - population at the next turn -* you want to model transitions of individuals from one state into another, - including transitions from the "entry" state and into the "exit" state. -* but you do NOT want to predict amount of "new" individuals because it - does not depends on individuals already present (hence system can not - transit INTO entry state - it can only transit FROM it). - -This model is discussed in more details in the ALGLIB User Guide (see -http://www.alglib.net/dataanalysis/ for more data). - -INPUT PARAMETERS: - N - problem dimension, N>=2 - EntryState- index of entry state, in 0..N-1 - ExitState- index of exit state, in 0..N-1 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdcreateentryexit(const ae_int_t n, const ae_int_t entrystate, const ae_int_t exitstate, mcpdstate &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is used to add a track - sequence of system states at the -different moments of its evolution. - -You may add one or several tracks to the MCPD solver. In case you have -several tracks, they won't overwrite each other. For example, if you pass -two tracks, A1-A2-A3 (system at t=A+1, t=A+2 and t=A+3) and B1-B2-B3, then -solver will try to model transitions from t=A+1 to t=A+2, t=A+2 to t=A+3, -t=B+1 to t=B+2, t=B+2 to t=B+3. But it WONT mix these two tracks - i.e. it -wont try to model transition from t=A+3 to t=B+1. - -INPUT PARAMETERS: - S - solver - XY - track, array[K,N]: - * I-th row is a state at t=I - * elements of XY must be non-negative (exception will be - thrown on negative elements) - K - number of points in a track - * if given, only leading K rows of XY are used - * if not given, automatically determined from size of XY - -NOTES: - -1. Track may contain either proportional or population data: - * with proportional data all rows of XY must sum to 1.0, i.e. we have - proportions instead of absolute population values - * with population data rows of XY contain population counts and generally - do not sum to 1.0 (although they still must be non-negative) - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdaddtrack(const mcpdstate &s, const real_2d_array &xy, const ae_int_t k, const xparams _xparams = alglib::xdefault); -void mcpdaddtrack(const mcpdstate &s, const real_2d_array &xy, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is used to add equality constraints on the elements of the -transition matrix P. - -MCPD solver has four types of constraints which can be placed on P: -* user-specified equality constraints (optional) -* user-specified bound constraints (optional) -* user-specified general linear constraints (optional) -* basic constraints (always present): - * non-negativity: P[i,j]>=0 - * consistency: every column of P sums to 1.0 - -Final constraints which are passed to the underlying optimizer are -calculated as intersection of all present constraints. For example, you -may specify boundary constraint on P[0,0] and equality one: - 0.1<=P[0,0]<=0.9 - P[0,0]=0.5 -Such combination of constraints will be silently reduced to their -intersection, which is P[0,0]=0.5. - -This function can be used to place equality constraints on arbitrary -subset of elements of P. Set of constraints is specified by EC, which may -contain either NAN's or finite numbers from [0,1]. NAN denotes absence of -constraint, finite number denotes equality constraint on specific element -of P. - -You can also use MCPDAddEC() function which allows to ADD equality -constraint for one element of P without changing constraints for other -elements. - -These functions (MCPDSetEC and MCPDAddEC) interact as follows: -* there is internal matrix of equality constraints which is stored in the - MCPD solver -* MCPDSetEC() replaces this matrix by another one (SET) -* MCPDAddEC() modifies one element of this matrix and leaves other ones - unchanged (ADD) -* thus MCPDAddEC() call preserves all modifications done by previous - calls, while MCPDSetEC() completely discards all changes done to the - equality constraints. - -INPUT PARAMETERS: - S - solver - EC - equality constraints, array[N,N]. Elements of EC can be - either NAN's or finite numbers from [0,1]. NAN denotes - absence of constraints, while finite value denotes - equality constraint on the corresponding element of P. - -NOTES: - -1. infinite values of EC will lead to exception being thrown. Values less -than 0.0 or greater than 1.0 will lead to error code being returned after -call to MCPDSolve(). - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdsetec(const mcpdstate &s, const real_2d_array &ec, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is used to add equality constraints on the elements of the -transition matrix P. - -MCPD solver has four types of constraints which can be placed on P: -* user-specified equality constraints (optional) -* user-specified bound constraints (optional) -* user-specified general linear constraints (optional) -* basic constraints (always present): - * non-negativity: P[i,j]>=0 - * consistency: every column of P sums to 1.0 - -Final constraints which are passed to the underlying optimizer are -calculated as intersection of all present constraints. For example, you -may specify boundary constraint on P[0,0] and equality one: - 0.1<=P[0,0]<=0.9 - P[0,0]=0.5 -Such combination of constraints will be silently reduced to their -intersection, which is P[0,0]=0.5. - -This function can be used to ADD equality constraint for one element of P -without changing constraints for other elements. - -You can also use MCPDSetEC() function which allows you to specify -arbitrary set of equality constraints in one call. - -These functions (MCPDSetEC and MCPDAddEC) interact as follows: -* there is internal matrix of equality constraints which is stored in the - MCPD solver -* MCPDSetEC() replaces this matrix by another one (SET) -* MCPDAddEC() modifies one element of this matrix and leaves other ones - unchanged (ADD) -* thus MCPDAddEC() call preserves all modifications done by previous - calls, while MCPDSetEC() completely discards all changes done to the - equality constraints. - -INPUT PARAMETERS: - S - solver - I - row index of element being constrained - J - column index of element being constrained - C - value (constraint for P[I,J]). Can be either NAN (no - constraint) or finite value from [0,1]. - -NOTES: - -1. infinite values of C will lead to exception being thrown. Values less -than 0.0 or greater than 1.0 will lead to error code being returned after -call to MCPDSolve(). - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdaddec(const mcpdstate &s, const ae_int_t i, const ae_int_t j, const double c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is used to add bound constraints on the elements of the -transition matrix P. - -MCPD solver has four types of constraints which can be placed on P: -* user-specified equality constraints (optional) -* user-specified bound constraints (optional) -* user-specified general linear constraints (optional) -* basic constraints (always present): - * non-negativity: P[i,j]>=0 - * consistency: every column of P sums to 1.0 - -Final constraints which are passed to the underlying optimizer are -calculated as intersection of all present constraints. For example, you -may specify boundary constraint on P[0,0] and equality one: - 0.1<=P[0,0]<=0.9 - P[0,0]=0.5 -Such combination of constraints will be silently reduced to their -intersection, which is P[0,0]=0.5. - -This function can be used to place bound constraints on arbitrary -subset of elements of P. Set of constraints is specified by BndL/BndU -matrices, which may contain arbitrary combination of finite numbers or -infinities (like -INF=0 - * consistency: every column of P sums to 1.0 - -Final constraints which are passed to the underlying optimizer are -calculated as intersection of all present constraints. For example, you -may specify boundary constraint on P[0,0] and equality one: - 0.1<=P[0,0]<=0.9 - P[0,0]=0.5 -Such combination of constraints will be silently reduced to their -intersection, which is P[0,0]=0.5. - -This function can be used to ADD bound constraint for one element of P -without changing constraints for other elements. - -You can also use MCPDSetBC() function which allows to place bound -constraints on arbitrary subset of elements of P. Set of constraints is -specified by BndL/BndU matrices, which may contain arbitrary combination -of finite numbers or infinities (like -INF=" (CT[i]>0). - -Your constraint may involve only some subset of P (less than N*N elements). -For example it can be something like - P[0,0] + P[0,1] = 0.5 -In this case you still should pass matrix with N*N+1 columns, but all its -elements (except for C[0,0], C[0,1] and C[0,N*N-1]) will be zero. - -INPUT PARAMETERS: - S - solver - C - array[K,N*N+1] - coefficients of constraints - (see above for complete description) - CT - array[K] - constraint types - (see above for complete description) - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdsetlc(const mcpdstate &s, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams = alglib::xdefault); -void mcpdsetlc(const mcpdstate &s, const real_2d_array &c, const integer_1d_array &ct, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function allows to tune amount of Tikhonov regularization being -applied to your problem. - -By default, regularizing term is equal to r*||P-prior_P||^2, where r is a -small non-zero value, P is transition matrix, prior_P is identity matrix, -||X||^2 is a sum of squared elements of X. - -This function allows you to change coefficient r. You can also change -prior values with MCPDSetPrior() function. - -INPUT PARAMETERS: - S - solver - V - regularization coefficient, finite non-negative value. It - is not recommended to specify zero value unless you are - pretty sure that you want it. - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdsettikhonovregularizer(const mcpdstate &s, const double v, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function allows to set prior values used for regularization of your -problem. - -By default, regularizing term is equal to r*||P-prior_P||^2, where r is a -small non-zero value, P is transition matrix, prior_P is identity matrix, -||X||^2 is a sum of squared elements of X. - -This function allows you to change prior values prior_P. You can also -change r with MCPDSetTikhonovRegularizer() function. - -INPUT PARAMETERS: - S - solver - PP - array[N,N], matrix of prior values: - 1. elements must be real numbers from [0,1] - 2. columns must sum to 1.0. - First property is checked (exception is thrown otherwise), - while second one is not checked/enforced. - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdsetprior(const mcpdstate &s, const real_2d_array &pp, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is used to change prediction weights - -MCPD solver scales prediction errors as follows - Error(P) = ||W*(y-P*x)||^2 -where - x is a system state at time t - y is a system state at time t+1 - P is a transition matrix - W is a diagonal scaling matrix - -By default, weights are chosen in order to minimize relative prediction -error instead of absolute one. For example, if one component of state is -about 0.5 in magnitude and another one is about 0.05, then algorithm will -make corresponding weights equal to 2.0 and 20.0. - -INPUT PARAMETERS: - S - solver - PW - array[N], weights: - * must be non-negative values (exception will be thrown otherwise) - * zero values will be replaced by automatically chosen values - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdsetpredictionweights(const mcpdstate &s, const real_1d_array &pw, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is used to start solution of the MCPD problem. - -After return from this function, you can use MCPDResults() to get solution -and completion code. - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdsolve(const mcpdstate &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -MCPD results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - P - array[N,N], transition matrix - Rep - optimization report. You should check Rep.TerminationType - in order to distinguish successful termination from - unsuccessful one. Speaking short, positive values denote - success, negative ones are failures. - More information about fields of this structure can be - found in the comments on MCPDReport datatype. - - - -- ALGLIB -- - Copyright 23.05.2010 by Bochkanov Sergey -*************************************************************************/ -void mcpdresults(const mcpdstate &s, real_2d_array &p, mcpdreport &rep, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_MLPE) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -void mlpeserialize(mlpensemble &obj, std::string &s_out); - - -/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -void mlpeunserialize(const std::string &s_in, mlpensemble &obj); - - - - -/************************************************************************* -This function serializes data structure to C++ stream. - -Data stream generated by this function is same as string representation -generated by string version of serializer - alphanumeric characters, -dots, underscores, minus signs, which are grouped into words separated by -spaces and CR+LF. - -We recommend you to read comments on string version of serializer to find -out more about serialization of AlGLIB objects. -*************************************************************************/ -void mlpeserialize(mlpensemble &obj, std::ostream &s_out); - - -/************************************************************************* -This function unserializes data structure from stream. -*************************************************************************/ -void mlpeunserialize(const std::istream &s_in, mlpensemble &obj); - - -/************************************************************************* -Like MLPCreate0, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreate0(const ae_int_t nin, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Like MLPCreate1, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreate1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Like MLPCreate2, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreate2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Like MLPCreateB0, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreateb0(const ae_int_t nin, const ae_int_t nout, const double b, const double d, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Like MLPCreateB1, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreateb1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const double b, const double d, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Like MLPCreateB2, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreateb2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const double b, const double d, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Like MLPCreateR0, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreater0(const ae_int_t nin, const ae_int_t nout, const double a, const double b, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Like MLPCreateR1, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreater1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const double a, const double b, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Like MLPCreateR2, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreater2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const double a, const double b, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Like MLPCreateC0, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreatec0(const ae_int_t nin, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Like MLPCreateC1, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreatec1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Like MLPCreateC2, but for ensembles. - - -- ALGLIB -- - Copyright 18.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreatec2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Creates ensemble from network. Only network geometry is copied. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpecreatefromnetwork(const multilayerperceptron &network, const ae_int_t ensemblesize, mlpensemble &ensemble, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Randomization of MLP ensemble - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlperandomize(const mlpensemble &ensemble, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Return ensemble properties (number of inputs and outputs). - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpeproperties(const mlpensemble &ensemble, ae_int_t &nin, ae_int_t &nout, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Return normalization type (whether ensemble is SOFTMAX-normalized or not). - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -bool mlpeissoftmax(const mlpensemble &ensemble, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Procesing - -INPUT PARAMETERS: - Ensemble- neural networks ensemble - X - input vector, array[0..NIn-1]. - Y - (possibly) preallocated buffer; if size of Y is less than - NOut, it will be reallocated. If it is large enough, it - is NOT reallocated, so we can save some time on reallocation. - - -OUTPUT PARAMETERS: - Y - result. Regression estimate when solving regression task, - vector of posterior probabilities for classification task. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpeprocess(const mlpensemble &ensemble, const real_1d_array &x, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -'interactive' variant of MLPEProcess for languages like Python which -support constructs like "Y = MLPEProcess(LM,X)" and interactive mode of the -interpreter - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpeprocessi(const mlpensemble &ensemble, const real_1d_array &x, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Relative classification error on the test set - -INPUT PARAMETERS: - Ensemble- ensemble - XY - test set - NPoints - test set size - -RESULT: - percent of incorrectly classified cases. - Works both for classifier betwork and for regression networks which -are used as classifiers. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -double mlperelclserror(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Average cross-entropy (in bits per element) on the test set - -INPUT PARAMETERS: - Ensemble- ensemble - XY - test set - NPoints - test set size - -RESULT: - CrossEntropy/(NPoints*LN(2)). - Zero if ensemble solves regression task. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -double mlpeavgce(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -RMS error on the test set - -INPUT PARAMETERS: - Ensemble- ensemble - XY - test set - NPoints - test set size - -RESULT: - root mean square error. - Its meaning for regression task is obvious. As for classification task -RMS error means error when estimating posterior probabilities. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -double mlpermserror(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Average error on the test set - -INPUT PARAMETERS: - Ensemble- ensemble - XY - test set - NPoints - test set size - -RESULT: - Its meaning for regression task is obvious. As for classification task -it means average error when estimating posterior probabilities. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -double mlpeavgerror(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Average relative error on the test set - -INPUT PARAMETERS: - Ensemble- ensemble - XY - test set - NPoints - test set size - -RESULT: - Its meaning for regression task is obvious. As for classification task -it means average relative error when estimating posterior probabilities. - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -double mlpeavgrelerror(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_MLPTRAIN) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Neural network training using modified Levenberg-Marquardt with exact -Hessian calculation and regularization. Subroutine trains neural network -with restarts from random positions. Algorithm is well suited for small -and medium scale problems (hundreds of weights). - -INPUT PARAMETERS: - Network - neural network with initialized geometry - XY - training set - NPoints - training set size - Decay - weight decay constant, >=0.001 - Decay term 'Decay*||Weights||^2' is added to error - function. - If you don't know what Decay to choose, use 0.001. - Restarts - number of restarts from random position, >0. - If you don't know what Restarts to choose, use 2. - -OUTPUT PARAMETERS: - Network - trained neural network. - Info - return code: - * -9, if internal matrix inverse subroutine failed - * -2, if there is a point with class number - outside of [0..NOut-1]. - * -1, if wrong parameters specified - (NPoints<0, Restarts<1). - * 2, if task has been solved. - Rep - training report - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -void mlptrainlm(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, ae_int_t &info, mlpreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Neural network training using L-BFGS algorithm with regularization. -Subroutine trains neural network with restarts from random positions. -Algorithm is well suited for problems of any dimensionality (memory -requirements and step complexity are linear by weights number). - -INPUT PARAMETERS: - Network - neural network with initialized geometry - XY - training set - NPoints - training set size - Decay - weight decay constant, >=0.001 - Decay term 'Decay*||Weights||^2' is added to error - function. - If you don't know what Decay to choose, use 0.001. - Restarts - number of restarts from random position, >0. - If you don't know what Restarts to choose, use 2. - WStep - stopping criterion. Algorithm stops if step size is - less than WStep. Recommended value - 0.01. Zero step - size means stopping after MaxIts iterations. - MaxIts - stopping criterion. Algorithm stops after MaxIts - iterations (NOT gradient calculations). Zero MaxIts - means stopping when step is sufficiently small. - -OUTPUT PARAMETERS: - Network - trained neural network. - Info - return code: - * -8, if both WStep=0 and MaxIts=0 - * -2, if there is a point with class number - outside of [0..NOut-1]. - * -1, if wrong parameters specified - (NPoints<0, Restarts<1). - * 2, if task has been solved. - Rep - training report - - -- ALGLIB -- - Copyright 09.12.2007 by Bochkanov Sergey -*************************************************************************/ -void mlptrainlbfgs(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, const double wstep, const ae_int_t maxits, ae_int_t &info, mlpreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Neural network training using early stopping (base algorithm - L-BFGS with -regularization). - -INPUT PARAMETERS: - Network - neural network with initialized geometry - TrnXY - training set - TrnSize - training set size, TrnSize>0 - ValXY - validation set - ValSize - validation set size, ValSize>0 - Decay - weight decay constant, >=0.001 - Decay term 'Decay*||Weights||^2' is added to error - function. - If you don't know what Decay to choose, use 0.001. - Restarts - number of restarts, either: - * strictly positive number - algorithm make specified - number of restarts from random position. - * -1, in which case algorithm makes exactly one run - from the initial state of the network (no randomization). - If you don't know what Restarts to choose, choose one - one the following: - * -1 (deterministic start) - * +1 (one random restart) - * +5 (moderate amount of random restarts) - -OUTPUT PARAMETERS: - Network - trained neural network. - Info - return code: - * -2, if there is a point with class number - outside of [0..NOut-1]. - * -1, if wrong parameters specified - (NPoints<0, Restarts<1, ...). - * 2, task has been solved, stopping criterion met - - sufficiently small step size. Not expected (we - use EARLY stopping) but possible and not an - error. - * 6, task has been solved, stopping criterion met - - increasing of validation set error. - Rep - training report - -NOTE: - -Algorithm stops if validation set error increases for a long enough or -step size is small enought (there are task where validation set may -decrease for eternity). In any case solution returned corresponds to the -minimum of validation set error. - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -void mlptraines(const multilayerperceptron &network, const real_2d_array &trnxy, const ae_int_t trnsize, const real_2d_array &valxy, const ae_int_t valsize, const double decay, const ae_int_t restarts, ae_int_t &info, mlpreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Cross-validation estimate of generalization error. - -Base algorithm - L-BFGS. - -INPUT PARAMETERS: - Network - neural network with initialized geometry. Network is - not changed during cross-validation - it is used only - as a representative of its architecture. - XY - training set. - SSize - training set size - Decay - weight decay, same as in MLPTrainLBFGS - Restarts - number of restarts, >0. - restarts are counted for each partition separately, so - total number of restarts will be Restarts*FoldsCount. - WStep - stopping criterion, same as in MLPTrainLBFGS - MaxIts - stopping criterion, same as in MLPTrainLBFGS - FoldsCount - number of folds in k-fold cross-validation, - 2<=FoldsCount<=SSize. - recommended value: 10. - -OUTPUT PARAMETERS: - Info - return code, same as in MLPTrainLBFGS - Rep - report, same as in MLPTrainLM/MLPTrainLBFGS - CVRep - generalization error estimates - - -- ALGLIB -- - Copyright 09.12.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpkfoldcvlbfgs(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, const double wstep, const ae_int_t maxits, const ae_int_t foldscount, ae_int_t &info, mlpreport &rep, mlpcvreport &cvrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Cross-validation estimate of generalization error. - -Base algorithm - Levenberg-Marquardt. - -INPUT PARAMETERS: - Network - neural network with initialized geometry. Network is - not changed during cross-validation - it is used only - as a representative of its architecture. - XY - training set. - SSize - training set size - Decay - weight decay, same as in MLPTrainLBFGS - Restarts - number of restarts, >0. - restarts are counted for each partition separately, so - total number of restarts will be Restarts*FoldsCount. - FoldsCount - number of folds in k-fold cross-validation, - 2<=FoldsCount<=SSize. - recommended value: 10. - -OUTPUT PARAMETERS: - Info - return code, same as in MLPTrainLBFGS - Rep - report, same as in MLPTrainLM/MLPTrainLBFGS - CVRep - generalization error estimates - - -- ALGLIB -- - Copyright 09.12.2007 by Bochkanov Sergey -*************************************************************************/ -void mlpkfoldcvlm(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, const ae_int_t foldscount, ae_int_t &info, mlpreport &rep, mlpcvreport &cvrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function estimates generalization error using cross-validation on the -current dataset with current training settings. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - trainer object - Network - neural network. It must have same number of inputs and - output/classes as was specified during creation of the - trainer object. Network is not changed during cross- - validation and is not trained - it is used only as - representative of its architecture. I.e., we estimate - generalization properties of ARCHITECTURE, not some - specific network. - NRestarts - number of restarts, >=0: - * NRestarts>0 means that for each cross-validation - round specified number of random restarts is - performed, with best network being chosen after - training. - * NRestarts=0 is same as NRestarts=1 - FoldsCount - number of folds in k-fold cross-validation: - * 2<=FoldsCount<=size of dataset - * recommended value: 10. - * values larger than dataset size will be silently - truncated down to dataset size - -OUTPUT PARAMETERS: - Rep - structure which contains cross-validation estimates: - * Rep.RelCLSError - fraction of misclassified cases. - * Rep.AvgCE - acerage cross-entropy - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average error - * Rep.AvgRelError - average relative error - -NOTE: when no dataset was specified with MLPSetDataset/SetSparseDataset(), - or subset with only one point was given, zeros are returned as - estimates. - -NOTE: this method performs FoldsCount cross-validation rounds, each one - with NRestarts random starts. Thus, FoldsCount*NRestarts networks - are trained in total. - -NOTE: Rep.RelCLSError/Rep.AvgCE are zero on regression problems. - -NOTE: on classification problems Rep.RMSError/Rep.AvgError/Rep.AvgRelError - contain errors in prediction of posterior probabilities. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpkfoldcv(const mlptrainer &s, const multilayerperceptron &network, const ae_int_t nrestarts, const ae_int_t foldscount, mlpreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Creation of the network trainer object for regression networks - -INPUT PARAMETERS: - NIn - number of inputs, NIn>=1 - NOut - number of outputs, NOut>=1 - -OUTPUT PARAMETERS: - S - neural network trainer object. - This structure can be used to train any regression - network with NIn inputs and NOut outputs. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpcreatetrainer(const ae_int_t nin, const ae_int_t nout, mlptrainer &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Creation of the network trainer object for classification networks - -INPUT PARAMETERS: - NIn - number of inputs, NIn>=1 - NClasses - number of classes, NClasses>=2 - -OUTPUT PARAMETERS: - S - neural network trainer object. - This structure can be used to train any classification - network with NIn inputs and NOut outputs. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpcreatetrainercls(const ae_int_t nin, const ae_int_t nclasses, mlptrainer &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets "current dataset" of the trainer object to one passed -by user. - -INPUT PARAMETERS: - S - trainer object - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. - NPoints - points count, >=0. - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -datasetformat is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpsetdataset(const mlptrainer &s, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets "current dataset" of the trainer object to one passed -by user (sparse matrix is used to store dataset). - -INPUT PARAMETERS: - S - trainer object - XY - training set, see below for information on the - training set format. This function checks correctness - of the dataset (no NANs/INFs, class numbers are - correct) and throws exception when incorrect dataset - is passed. Any sparse storage format can be used: - Hash-table, CRS... - NPoints - points count, >=0 - -DATASET FORMAT: - -This function uses two different dataset formats - one for regression -networks, another one for classification networks. - -For regression networks with NIn inputs and NOut outputs following dataset -format is used: -* dataset is given by NPoints*(NIn+NOut) matrix -* each row corresponds to one example -* first NIn columns are inputs, next NOut columns are outputs - -For classification networks with NIn inputs and NClasses clases following -datasetformat is used: -* dataset is given by NPoints*(NIn+1) matrix -* each row corresponds to one example -* first NIn columns are inputs, last column stores class number (from 0 to - NClasses-1). - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpsetsparsedataset(const mlptrainer &s, const sparsematrix &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets weight decay coefficient which is used for training. - -INPUT PARAMETERS: - S - trainer object - Decay - weight decay coefficient, >=0. Weight decay term - 'Decay*||Weights||^2' is added to error function. If - you don't know what Decay to choose, use 1.0E-3. - Weight decay can be set to zero, in this case network - is trained without weight decay. - -NOTE: by default network uses some small nonzero value for weight decay. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpsetdecay(const mlptrainer &s, const double decay, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets stopping criteria for the optimizer. - -INPUT PARAMETERS: - S - trainer object - WStep - stopping criterion. Algorithm stops if step size is - less than WStep. Recommended value - 0.01. Zero step - size means stopping after MaxIts iterations. - WStep>=0. - MaxIts - stopping criterion. Algorithm stops after MaxIts - epochs (full passes over entire dataset). Zero MaxIts - means stopping when step is sufficiently small. - MaxIts>=0. - -NOTE: by default, WStep=0.005 and MaxIts=0 are used. These values are also - used when MLPSetCond() is called with WStep=0 and MaxIts=0. - -NOTE: these stopping criteria are used for all kinds of neural training - - from "conventional" networks to early stopping ensembles. When used - for "conventional" networks, they are used as the only stopping - criteria. When combined with early stopping, they used as ADDITIONAL - stopping criteria which can terminate early stopping algorithm. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpsetcond(const mlptrainer &s, const double wstep, const ae_int_t maxits, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets training algorithm: batch training using L-BFGS will be -used. - -This algorithm: -* the most robust for small-scale problems, but may be too slow for large - scale ones. -* perfoms full pass through the dataset before performing step -* uses conditions specified by MLPSetCond() for stopping -* is default one used by trainer object - -INPUT PARAMETERS: - S - trainer object - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpsetalgobatch(const mlptrainer &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function trains neural network passed to this function, using current -dataset (one which was passed to MLPSetDataset() or MLPSetSparseDataset()) -and current training settings. Training from NRestarts random starting -positions is performed, best network is chosen. - -Training is performed using current training algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - trainer object - Network - neural network. It must have same number of inputs and - output/classes as was specified during creation of the - trainer object. - NRestarts - number of restarts, >=0: - * NRestarts>0 means that specified number of random - restarts are performed, best network is chosen after - training - * NRestarts=0 means that current state of the network - is used for training. - -OUTPUT PARAMETERS: - Network - trained network - -NOTE: when no dataset was specified with MLPSetDataset/SetSparseDataset(), - network is filled by zero values. Same behavior for functions - MLPStartTraining and MLPContinueTraining. - -NOTE: this method uses sum-of-squares error function for training. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlptrainnetwork(const mlptrainer &s, const multilayerperceptron &network, const ae_int_t nrestarts, mlpreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -IMPORTANT: this is an "expert" version of the MLPTrain() function. We do - not recommend you to use it unless you are pretty sure that you - need ability to monitor training progress. - -This function performs step-by-step training of the neural network. Here -"step-by-step" means that training starts with MLPStartTraining() call, -and then user subsequently calls MLPContinueTraining() to perform one more -iteration of the training. - -After call to this function trainer object remembers network and is ready -to train it. However, no training is performed until first call to -MLPContinueTraining() function. Subsequent calls to MLPContinueTraining() -will advance training progress one iteration further. - -EXAMPLE: - > - > ...initialize network and trainer object.... - > - > MLPStartTraining(Trainer, Network, True) - > while MLPContinueTraining(Trainer, Network) do - > ...visualize training progress... - > - -INPUT PARAMETERS: - S - trainer object - Network - neural network. It must have same number of inputs and - output/classes as was specified during creation of the - trainer object. - RandomStart - randomize network before training or not: - * True means that network is randomized and its - initial state (one which was passed to the trainer - object) is lost. - * False means that training is started from the - current state of the network - -OUTPUT PARAMETERS: - Network - neural network which is ready to training (weights are - initialized, preprocessor is initialized using current - training set) - -NOTE: this method uses sum-of-squares error function for training. - -NOTE: it is expected that trainer object settings are NOT changed during - step-by-step training, i.e. no one changes stopping criteria or - training set during training. It is possible and there is no defense - against such actions, but algorithm behavior in such cases is - undefined and can be unpredictable. - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -void mlpstarttraining(const mlptrainer &s, const multilayerperceptron &network, const bool randomstart, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -IMPORTANT: this is an "expert" version of the MLPTrain() function. We do - not recommend you to use it unless you are pretty sure that you - need ability to monitor training progress. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -This function performs step-by-step training of the neural network. Here -"step-by-step" means that training starts with MLPStartTraining() call, -and then user subsequently calls MLPContinueTraining() to perform one more -iteration of the training. - -This function performs one more iteration of the training and returns -either True (training continues) or False (training stopped). In case True -was returned, Network weights are updated according to the current state -of the optimization progress. In case False was returned, no additional -updates is performed (previous update of the network weights moved us to -the final point, and no additional updates is needed). - -EXAMPLE: - > - > [initialize network and trainer object] - > - > MLPStartTraining(Trainer, Network, True) - > while MLPContinueTraining(Trainer, Network) do - > [visualize training progress] - > - -INPUT PARAMETERS: - S - trainer object - Network - neural network structure, which is used to store - current state of the training process. - -OUTPUT PARAMETERS: - Network - weights of the neural network are rewritten by the - current approximation. - -NOTE: this method uses sum-of-squares error function for training. - -NOTE: it is expected that trainer object settings are NOT changed during - step-by-step training, i.e. no one changes stopping criteria or - training set during training. It is possible and there is no defense - against such actions, but algorithm behavior in such cases is - undefined and can be unpredictable. - -NOTE: It is expected that Network is the same one which was passed to - MLPStartTraining() function. However, THIS function checks only - following: - * that number of network inputs is consistent with trainer object - settings - * that number of network outputs/classes is consistent with trainer - object settings - * that number of network weights is the same as number of weights in - the network passed to MLPStartTraining() function - Exception is thrown when these conditions are violated. - - It is also expected that you do not change state of the network on - your own - the only party who has right to change network during its - training is a trainer object. Any attempt to interfere with trainer - may lead to unpredictable results. - - - -- ALGLIB -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -bool mlpcontinuetraining(const mlptrainer &s, const multilayerperceptron &network, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Training neural networks ensemble using bootstrap aggregating (bagging). -Modified Levenberg-Marquardt algorithm is used as base training method. - -INPUT PARAMETERS: - Ensemble - model with initialized geometry - XY - training set - NPoints - training set size - Decay - weight decay coefficient, >=0.001 - Restarts - restarts, >0. - -OUTPUT PARAMETERS: - Ensemble - trained model - Info - return code: - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed - (NPoints<0, Restarts<1). - * 2, if task has been solved. - Rep - training report. - OOBErrors - out-of-bag generalization error estimate - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpebagginglm(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, ae_int_t &info, mlpreport &rep, mlpcvreport &ooberrors, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Training neural networks ensemble using bootstrap aggregating (bagging). -L-BFGS algorithm is used as base training method. - -INPUT PARAMETERS: - Ensemble - model with initialized geometry - XY - training set - NPoints - training set size - Decay - weight decay coefficient, >=0.001 - Restarts - restarts, >0. - WStep - stopping criterion, same as in MLPTrainLBFGS - MaxIts - stopping criterion, same as in MLPTrainLBFGS - -OUTPUT PARAMETERS: - Ensemble - trained model - Info - return code: - * -8, if both WStep=0 and MaxIts=0 - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed - (NPoints<0, Restarts<1). - * 2, if task has been solved. - Rep - training report. - OOBErrors - out-of-bag generalization error estimate - - -- ALGLIB -- - Copyright 17.02.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpebagginglbfgs(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, const double wstep, const ae_int_t maxits, ae_int_t &info, mlpreport &rep, mlpcvreport &ooberrors, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Training neural networks ensemble using early stopping. - -INPUT PARAMETERS: - Ensemble - model with initialized geometry - XY - training set - NPoints - training set size - Decay - weight decay coefficient, >=0.001 - Restarts - restarts, >0. - -OUTPUT PARAMETERS: - Ensemble - trained model - Info - return code: - * -2, if there is a point with class number - outside of [0..NClasses-1]. - * -1, if incorrect parameters was passed - (NPoints<0, Restarts<1). - * 6, if task has been solved. - Rep - training report. - OOBErrors - out-of-bag generalization error estimate - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -void mlpetraines(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, ae_int_t &info, mlpreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function trains neural network ensemble passed to this function using -current dataset and early stopping training algorithm. Each early stopping -round performs NRestarts random restarts (thus, EnsembleSize*NRestarts -training rounds is performed in total). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - trainer object; - Ensemble - neural network ensemble. It must have same number of - inputs and outputs/classes as was specified during - creation of the trainer object. - NRestarts - number of restarts, >=0: - * NRestarts>0 means that specified number of random - restarts are performed during each ES round; - * NRestarts=0 is silently replaced by 1. - -OUTPUT PARAMETERS: - Ensemble - trained ensemble; - Rep - it contains all type of errors. - -NOTE: this training method uses BOTH early stopping and weight decay! So, - you should select weight decay before starting training just as you - select it before training "conventional" networks. - -NOTE: when no dataset was specified with MLPSetDataset/SetSparseDataset(), - or single-point dataset was passed, ensemble is filled by zero - values. - -NOTE: this method uses sum-of-squares error function for training. - - -- ALGLIB -- - Copyright 22.08.2012 by Bochkanov Sergey -*************************************************************************/ -void mlptrainensemblees(const mlptrainer &s, const mlpensemble &ensemble, const ae_int_t nrestarts, mlpreport &rep, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_CLUSTERING) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This function initializes clusterizer object. Newly initialized object is -empty, i.e. it does not contain dataset. You should use it as follows: -1. creation -2. dataset is added with ClusterizerSetPoints() -3. additional parameters are set -3. clusterization is performed with one of the clustering functions - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizercreate(clusterizerstate &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function adds dataset to the clusterizer structure. - -This function overrides all previous calls of ClusterizerSetPoints() or -ClusterizerSetDistances(). - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - XY - array[NPoints,NFeatures], dataset - NPoints - number of points, >=0 - NFeatures- number of features, >=1 - DistType- distance function: - * 0 Chebyshev distance (L-inf norm) - * 1 city block distance (L1 norm) - * 2 Euclidean distance (L2 norm), non-squared - * 10 Pearson correlation: - dist(a,b) = 1-corr(a,b) - * 11 Absolute Pearson correlation: - dist(a,b) = 1-|corr(a,b)| - * 12 Uncentered Pearson correlation (cosine of the angle): - dist(a,b) = a'*b/(|a|*|b|) - * 13 Absolute uncentered Pearson correlation - dist(a,b) = |a'*b|/(|a|*|b|) - * 20 Spearman rank correlation: - dist(a,b) = 1-rankcorr(a,b) - * 21 Absolute Spearman rank correlation - dist(a,b) = 1-|rankcorr(a,b)| - -NOTE 1: different distance functions have different performance penalty: - * Euclidean or Pearson correlation distances are the fastest ones - * Spearman correlation distance function is a bit slower - * city block and Chebyshev distances are order of magnitude slower - - The reason behing difference in performance is that correlation-based - distance functions are computed using optimized linear algebra kernels, - while Chebyshev and city block distance functions are computed using - simple nested loops with two branches at each iteration. - -NOTE 2: different clustering algorithms have different limitations: - * agglomerative hierarchical clustering algorithms may be used with - any kind of distance metric - * k-means++ clustering algorithm may be used only with Euclidean - distance function - Thus, list of specific clustering algorithms you may use depends - on distance function you specify when you set your dataset. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizersetpoints(const clusterizerstate &s, const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nfeatures, const ae_int_t disttype, const xparams _xparams = alglib::xdefault); -void clusterizersetpoints(const clusterizerstate &s, const real_2d_array &xy, const ae_int_t disttype, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function adds dataset given by distance matrix to the clusterizer -structure. It is important that dataset is not given explicitly - only -distance matrix is given. - -This function overrides all previous calls of ClusterizerSetPoints() or -ClusterizerSetDistances(). - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - D - array[NPoints,NPoints], distance matrix given by its upper - or lower triangle (main diagonal is ignored because its - entries are expected to be zero). - NPoints - number of points - IsUpper - whether upper or lower triangle of D is given. - -NOTE 1: different clustering algorithms have different limitations: - * agglomerative hierarchical clustering algorithms may be used with - any kind of distance metric, including one which is given by - distance matrix - * k-means++ clustering algorithm may be used only with Euclidean - distance function and explicitly given points - it can not be - used with dataset given by distance matrix - Thus, if you call this function, you will be unable to use k-means - clustering algorithm to process your problem. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizersetdistances(const clusterizerstate &s, const real_2d_array &d, const ae_int_t npoints, const bool isupper, const xparams _xparams = alglib::xdefault); -void clusterizersetdistances(const clusterizerstate &s, const real_2d_array &d, const bool isupper, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets agglomerative hierarchical clustering algorithm - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - Algo - algorithm type: - * 0 complete linkage (default algorithm) - * 1 single linkage - * 2 unweighted average linkage - * 3 weighted average linkage - * 4 Ward's method - -NOTE: Ward's method works correctly only with Euclidean distance, that's - why algorithm will return negative termination code (failure) for - any other distance type. - - It is possible, however, to use this method with user-supplied - distance matrix. It is your responsibility to pass one which was - calculated with Euclidean distance function. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizersetahcalgo(const clusterizerstate &s, const ae_int_t algo, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets k-means properties: number of restarts and maximum -number of iterations per one run. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - Restarts- restarts count, >=1. - k-means++ algorithm performs several restarts and chooses - best set of centers (one with minimum squared distance). - MaxIts - maximum number of k-means iterations performed during one - run. >=0, zero value means that algorithm performs unlimited - number of iterations. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizersetkmeanslimits(const clusterizerstate &s, const ae_int_t restarts, const ae_int_t maxits, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets k-means initialization algorithm. Several different -algorithms can be chosen, including k-means++. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - InitAlgo- initialization algorithm: - * 0 automatic selection ( different versions of ALGLIB - may select different algorithms) - * 1 random initialization - * 2 k-means++ initialization (best quality of initial - centers, but long non-parallelizable initialization - phase with bad cache locality) - * 3 "fast-greedy" algorithm with efficient, easy to - parallelize initialization. Quality of initial centers - is somewhat worse than that of k-means++. This - algorithm is a default one in the current version of - ALGLIB. - *-1 "debug" algorithm which always selects first K rows - of dataset; this algorithm is used for debug purposes - only. Do not use it in the industrial code! - - -- ALGLIB -- - Copyright 21.01.2015 by Bochkanov Sergey -*************************************************************************/ -void clusterizersetkmeansinit(const clusterizerstate &s, const ae_int_t initalgo, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets seed which is used to initialize internal RNG. By -default, deterministic seed is used - same for each run of clusterizer. If -you specify non-deterministic seed value, then some algorithms which -depend on random initialization (in current version: k-means) may return -slightly different results after each run. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - Seed - seed: - * positive values = use deterministic seed for each run of - algorithms which depend on random initialization - * zero or negative values = use non-deterministic seed - - -- ALGLIB -- - Copyright 08.06.2017 by Bochkanov Sergey -*************************************************************************/ -void clusterizersetseed(const clusterizerstate &s, const ae_int_t seed, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function performs agglomerative hierarchical clustering - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: Agglomerative hierarchical clustering algorithm has two phases: - distance matrix calculation and clustering itself. Only first phase - (distance matrix calculation) is accelerated by Intel MKL and - multithreading. Thus, acceleration is significant only for medium or - high-dimensional problems. - - Although activating multithreading gives some speedup over single- - threaded execution, you should not expect nearly-linear scaling - with respect to cores count. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - -OUTPUT PARAMETERS: - Rep - clustering results; see description of AHCReport - structure for more information. - -NOTE 1: hierarchical clustering algorithms require large amounts of memory. - In particular, this implementation needs sizeof(double)*NPoints^2 - bytes, which are used to store distance matrix. In case we work - with user-supplied matrix, this amount is multiplied by 2 (we have - to store original matrix and to work with its copy). - - For example, problem with 10000 points would require 800M of RAM, - even when working in a 1-dimensional space. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizerrunahc(const clusterizerstate &s, ahcreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function performs clustering by k-means++ algorithm. - -You may change algorithm properties by calling: -* ClusterizerSetKMeansLimits() to change number of restarts or iterations -* ClusterizerSetKMeansInit() to change initialization algorithm - -By default, one restart and unlimited number of iterations are used. -Initialization algorithm is chosen automatically. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: k-means clustering algorithm has two phases: selection of initial - centers and clustering itself. ALGLIB parallelizes both phases. - Parallel version is optimized for the following scenario: medium or - high-dimensional problem (8 or more dimensions) with large number of - points and clusters. However, some speed-up can be obtained even - when assumptions above are violated. - -INPUT PARAMETERS: - S - clusterizer state, initialized by ClusterizerCreate() - K - number of clusters, K>=0. - K can be zero only when algorithm is called for empty - dataset, in this case completion code is set to - success (+1). - If K=0 and dataset size is non-zero, we can not - meaningfully assign points to some center (there are no - centers because K=0) and return -3 as completion code - (failure). - -OUTPUT PARAMETERS: - Rep - clustering results; see description of KMeansReport - structure for more information. - -NOTE 1: k-means clustering can be performed only for datasets with - Euclidean distance function. Algorithm will return negative - completion code in Rep.TerminationType in case dataset was added - to clusterizer with DistType other than Euclidean (or dataset was - specified by distance matrix instead of explicitly given points). - -NOTE 2: by default, k-means uses non-deterministic seed to initialize RNG - which is used to select initial centers. As result, each run of - algorithm may return different values. If you need deterministic - behavior, use ClusterizerSetSeed() function. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizerrunkmeans(const clusterizerstate &s, const ae_int_t k, kmeansreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function returns distance matrix for dataset - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - array[NPoints,NFeatures], dataset - NPoints - number of points, >=0 - NFeatures- number of features, >=1 - DistType- distance function: - * 0 Chebyshev distance (L-inf norm) - * 1 city block distance (L1 norm) - * 2 Euclidean distance (L2 norm, non-squared) - * 10 Pearson correlation: - dist(a,b) = 1-corr(a,b) - * 11 Absolute Pearson correlation: - dist(a,b) = 1-|corr(a,b)| - * 12 Uncentered Pearson correlation (cosine of the angle): - dist(a,b) = a'*b/(|a|*|b|) - * 13 Absolute uncentered Pearson correlation - dist(a,b) = |a'*b|/(|a|*|b|) - * 20 Spearman rank correlation: - dist(a,b) = 1-rankcorr(a,b) - * 21 Absolute Spearman rank correlation - dist(a,b) = 1-|rankcorr(a,b)| - -OUTPUT PARAMETERS: - D - array[NPoints,NPoints], distance matrix - (full matrix is returned, with lower and upper triangles) - -NOTE: different distance functions have different performance penalty: - * Euclidean or Pearson correlation distances are the fastest ones - * Spearman correlation distance function is a bit slower - * city block and Chebyshev distances are order of magnitude slower - - The reason behing difference in performance is that correlation-based - distance functions are computed using optimized linear algebra kernels, - while Chebyshev and city block distance functions are computed using - simple nested loops with two branches at each iteration. - - -- ALGLIB -- - Copyright 10.07.2012 by Bochkanov Sergey -*************************************************************************/ -void clusterizergetdistances(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nfeatures, const ae_int_t disttype, real_2d_array &d, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function takes as input clusterization report Rep, desired clusters -count K, and builds top K clusters from hierarchical clusterization tree. -It returns assignment of points to clusters (array of cluster indexes). - -INPUT PARAMETERS: - Rep - report from ClusterizerRunAHC() performed on XY - K - desired number of clusters, 1<=K<=NPoints. - K can be zero only when NPoints=0. - -OUTPUT PARAMETERS: - CIdx - array[NPoints], I-th element contains cluster index (from - 0 to K-1) for I-th point of the dataset. - CZ - array[K]. This array allows to convert cluster indexes - returned by this function to indexes used by Rep.Z. J-th - cluster returned by this function corresponds to CZ[J]-th - cluster stored in Rep.Z/PZ/PM. - It is guaranteed that CZ[I]=0 - -OUTPUT PARAMETERS: - K - number of clusters, 1<=K<=NPoints - CIdx - array[NPoints], I-th element contains cluster index (from - 0 to K-1) for I-th point of the dataset. - CZ - array[K]. This array allows to convert cluster indexes - returned by this function to indexes used by Rep.Z. J-th - cluster returned by this function corresponds to CZ[J]-th - cluster stored in Rep.Z/PZ/PM. - It is guaranteed that CZ[I]=1 - NVars - number of independent variables, NVars>=1 - NClasses - indicates type of the problem being solved: - * NClasses>=2 means that classification problem is - solved (last column of the dataset stores class - number) - * NClasses=1 means that regression problem is solved - (last column of the dataset stores variable value) - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetdataset(const decisionforestbuilder &s, const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets number of variables (in [1,NVars] range) used by -decision forest construction algorithm. - -The default option is to use roughly sqrt(NVars) variables. - -INPUT PARAMETERS: - S - decision forest builder object - RndVars - number of randomly selected variables; values outside - of [1,NVars] range are silently clipped. - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetrndvars(const decisionforestbuilder &s, const ae_int_t rndvars, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets number of variables used by decision forest construction -algorithm as a fraction of total variable count (0,1) range. - -The default option is to use roughly sqrt(NVars) variables. - -INPUT PARAMETERS: - S - decision forest builder object - F - round(NVars*F) variables are selected - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetrndvarsratio(const decisionforestbuilder &s, const double f, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function tells decision forest builder to automatically choose number -of variables used by decision forest construction algorithm. Roughly -sqrt(NVars) variables will be used. - -INPUT PARAMETERS: - S - decision forest builder object - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetrndvarsauto(const decisionforestbuilder &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets size of dataset subsample generated the decision forest -construction algorithm. Size is specified as a fraction of total dataset -size. - -The default option is to use 50% of the dataset for training, 50% for the -OOB estimates. You can decrease fraction F down to 10%, 1% or even below -in order to reduce overfitting. - -INPUT PARAMETERS: - S - decision forest builder object - F - fraction of the dataset to use, in (0,1] range. Values - outside of this range will be silently clipped. At - least one element is always selected for the training - set. - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetsubsampleratio(const decisionforestbuilder &s, const double f, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets seed used by internal RNG for random subsampling and -random selection of variable subsets. - -By default random seed is used, i.e. every time you build decision forest, -we seed generator with new value obtained from system-wide RNG. Thus, -decision forest builder returns non-deterministic results. You can change -such behavior by specyfing fixed positive seed value. - -INPUT PARAMETERS: - S - decision forest builder object - SeedVal - seed value: - * positive values are used for seeding RNG with fixed - seed, i.e. subsequent runs on same data will return - same decision forests - * non-positive seed means that random seed is used - for every run of builder, i.e. subsequent runs on - same datasets will return slightly different - decision forests - -OUTPUT PARAMETERS: - S - decision forest builder, see - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetseed(const decisionforestbuilder &s, const ae_int_t seedval, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets random decision forest construction algorithm. - -As for now, only one decision forest construction algorithm is supported - -a dense "baseline" RDF algorithm. - -INPUT PARAMETERS: - S - decision forest builder object - AlgoType - algorithm type: - * 0 = baseline dense RDF - -OUTPUT PARAMETERS: - S - decision forest builder, see - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetrdfalgo(const decisionforestbuilder &s, const ae_int_t algotype, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets split selection algorithm used by decision forest -classifier. You may choose several algorithms, with different speed and -quality of the results. - -INPUT PARAMETERS: - S - decision forest builder object - SplitStrength- split type: - * 0 = split at the random position, fastest one - * 1 = split at the middle of the range - * 2 = strong split at the best point of the range (default) - -OUTPUT PARAMETERS: - S - decision forest builder, see - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetrdfsplitstrength(const decisionforestbuilder &s, const ae_int_t splitstrength, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function tells decision forest construction algorithm to use -Gini impurity based variable importance estimation (also known as MDI). - -This version of importance estimation algorithm analyzes mean decrease in -impurity (MDI) on training sample during splits. The result is divided -by impurity at the root node in order to produce estimate in [0,1] range. - -Such estimates are fast to calculate and beautifully normalized (sum to -one) but have following downsides: -* They ALWAYS sum to 1.0, even if output is completely unpredictable. I.e. - MDI allows to order variables by importance, but does not tell us about - "absolute" importances of variables -* there exist some bias towards continuous and high-cardinality categorical - variables - -NOTE: informally speaking, MDA (permutation importance) rating answers the - question "what part of the model predictive power is ruined by - permuting k-th variable?" while MDI tells us "what part of the model - predictive power was achieved due to usage of k-th variable". - - Thus, MDA rates each variable independently at "0 to 1" scale while - MDI (and OOB-MDI too) tends to divide "unit amount of importance" - between several important variables. - - If all variables are equally important, they will have same - MDI/OOB-MDI rating, equal (for OOB-MDI: roughly equal) to 1/NVars. - However, roughly same picture will be produced for the "all - variables provide information no one is critical" situation and for - the "all variables are critical, drop any one, everything is ruined" - situation. - - Contrary to that, MDA will rate critical variable as ~1.0 important, - and important but non-critical variable will have less than unit - rating. - -NOTE: quite an often MDA and MDI return same results. It generally happens - on problems with low test set error (a few percents at most) and - large enough training set to avoid overfitting. - - The difference between MDA, MDI and OOB-MDI becomes important only - on "hard" tasks with high test set error and/or small training set. - -INPUT PARAMETERS: - S - decision forest builder object - -OUTPUT PARAMETERS: - S - decision forest builder object. Next call to the forest - construction function will produce: - * importance estimates in rep.varimportances field - * variable ranks in rep.topvars field - - -- ALGLIB -- - Copyright 29.07.2019 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetimportancetrngini(const decisionforestbuilder &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function tells decision forest construction algorithm to use -out-of-bag version of Gini variable importance estimation (also known as -OOB-MDI). - -This version of importance estimation algorithm analyzes mean decrease in -impurity (MDI) on out-of-bag sample during splits. The result is divided -by impurity at the root node in order to produce estimate in [0,1] range. - -Such estimates are fast to calculate and resistant to overfitting issues -(thanks to the out-of-bag estimates used). However, OOB Gini rating has -following downsides: -* there exist some bias towards continuous and high-cardinality categorical - variables -* Gini rating allows us to order variables by importance, but it is hard - to define importance of the variable by itself. - -NOTE: informally speaking, MDA (permutation importance) rating answers the - question "what part of the model predictive power is ruined by - permuting k-th variable?" while MDI tells us "what part of the model - predictive power was achieved due to usage of k-th variable". - - Thus, MDA rates each variable independently at "0 to 1" scale while - MDI (and OOB-MDI too) tends to divide "unit amount of importance" - between several important variables. - - If all variables are equally important, they will have same - MDI/OOB-MDI rating, equal (for OOB-MDI: roughly equal) to 1/NVars. - However, roughly same picture will be produced for the "all - variables provide information no one is critical" situation and for - the "all variables are critical, drop any one, everything is ruined" - situation. - - Contrary to that, MDA will rate critical variable as ~1.0 important, - and important but non-critical variable will have less than unit - rating. - -NOTE: quite an often MDA and MDI return same results. It generally happens - on problems with low test set error (a few percents at most) and - large enough training set to avoid overfitting. - - The difference between MDA, MDI and OOB-MDI becomes important only - on "hard" tasks with high test set error and/or small training set. - -INPUT PARAMETERS: - S - decision forest builder object - -OUTPUT PARAMETERS: - S - decision forest builder object. Next call to the forest - construction function will produce: - * importance estimates in rep.varimportances field - * variable ranks in rep.topvars field - - -- ALGLIB -- - Copyright 29.07.2019 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetimportanceoobgini(const decisionforestbuilder &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function tells decision forest construction algorithm to use -permutation variable importance estimator (also known as MDA). - -This version of importance estimation algorithm analyzes mean increase in -out-of-bag sum of squared residuals after random permutation of J-th -variable. The result is divided by error computed with all variables being -perturbed in order to produce R-squared-like estimate in [0,1] range. - -Such estimate is slower to calculate than Gini-based rating because it -needs multiple inference runs for each of variables being studied. - -ALGLIB uses parallelized and highly optimized algorithm which analyzes -path through the decision tree and allows to handle most perturbations -in O(1) time; nevertheless, requesting MDA importances may increase forest -construction time from 10% to 200% (or more, if you have thousands of -variables). - -However, MDA rating has following benefits over Gini-based ones: -* no bias towards specific variable types -* ability to directly evaluate "absolute" importance of some variable at - "0 to 1" scale (contrary to Gini-based rating, which returns comparative - importances). - -NOTE: informally speaking, MDA (permutation importance) rating answers the - question "what part of the model predictive power is ruined by - permuting k-th variable?" while MDI tells us "what part of the model - predictive power was achieved due to usage of k-th variable". - - Thus, MDA rates each variable independently at "0 to 1" scale while - MDI (and OOB-MDI too) tends to divide "unit amount of importance" - between several important variables. - - If all variables are equally important, they will have same - MDI/OOB-MDI rating, equal (for OOB-MDI: roughly equal) to 1/NVars. - However, roughly same picture will be produced for the "all - variables provide information no one is critical" situation and for - the "all variables are critical, drop any one, everything is ruined" - situation. - - Contrary to that, MDA will rate critical variable as ~1.0 important, - and important but non-critical variable will have less than unit - rating. - -NOTE: quite an often MDA and MDI return same results. It generally happens - on problems with low test set error (a few percents at most) and - large enough training set to avoid overfitting. - - The difference between MDA, MDI and OOB-MDI becomes important only - on "hard" tasks with high test set error and/or small training set. - -INPUT PARAMETERS: - S - decision forest builder object - -OUTPUT PARAMETERS: - S - decision forest builder object. Next call to the forest - construction function will produce: - * importance estimates in rep.varimportances field - * variable ranks in rep.topvars field - - -- ALGLIB -- - Copyright 29.07.2019 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetimportancepermutation(const decisionforestbuilder &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function tells decision forest construction algorithm to skip -variable importance estimation. - -INPUT PARAMETERS: - S - decision forest builder object - -OUTPUT PARAMETERS: - S - decision forest builder object. Next call to the forest - construction function will result in forest being built - without variable importance estimation. - - -- ALGLIB -- - Copyright 29.07.2019 by Bochkanov Sergey -*************************************************************************/ -void dfbuildersetimportancenone(const decisionforestbuilder &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is an alias for dfbuilderpeekprogress(), left in ALGLIB for -backward compatibility reasons. - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -double dfbuildergetprogress(const decisionforestbuilder &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is used to peek into decision forest construction process -from some other thread and get current progress indicator. - -It returns value in [0,1]. - -INPUT PARAMETERS: - S - decision forest builder object used to build forest - in some other thread - -RESULT: - progress value, in [0,1] - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -double dfbuilderpeekprogress(const decisionforestbuilder &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine builds decision forest according to current settings using -dataset internally stored in the builder object. Dense algorithm is used. - -NOTE: this function uses dense algorithm for forest construction - independently from the dataset format (dense or sparse). - -NOTE: forest built with this function is stored in-memory using 64-bit - data structures for offsets/indexes/split values. It is possible to - convert forest into more memory-efficient compressed binary - representation. Depending on the problem properties, 3.7x-5.7x - compression factors are possible. - - The downsides of compression are (a) slight reduction in the model - accuracy and (b) ~1.5x reduction in the inference speed (due to - increased complexity of the storage format). - - See comments on dfbinarycompression() for more info. - -Default settings are used by the algorithm; you can tweak them with the -help of the following functions: -* dfbuildersetrfactor() - to control a fraction of the dataset used for - subsampling -* dfbuildersetrandomvars() - to control number of variables randomly chosen - for decision rule creation - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - decision forest builder object - NTrees - NTrees>=1, number of trees to train - -OUTPUT PARAMETERS: - DF - decision forest. You can compress this forest to more - compact 16-bit representation with dfbinarycompression() - Rep - report, see below for information on its fields. - -=== report information produced by forest construction function ========== - -Decision forest training report includes following information: -* training set errors -* out-of-bag estimates of errors -* variable importance ratings - -Following fields are used to store information: -* training set errors are stored in rep.relclserror, rep.avgce, rep.rmserror, - rep.avgerror and rep.avgrelerror -* out-of-bag estimates of errors are stored in rep.oobrelclserror, rep.oobavgce, - rep.oobrmserror, rep.oobavgerror and rep.oobavgrelerror - -Variable importance reports, if requested by dfbuildersetimportancegini(), -dfbuildersetimportancetrngini() or dfbuildersetimportancepermutation() -call, are stored in: -* rep.varimportances field stores importance ratings -* rep.topvars stores variable indexes ordered from the most important to - less important ones - -You can find more information about report fields in: -* comments on dfreport structure -* comments on dfbuildersetimportancegini function -* comments on dfbuildersetimportancetrngini function -* comments on dfbuildersetimportancepermutation function - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -void dfbuilderbuildrandomforest(const decisionforestbuilder &s, const ae_int_t ntrees, decisionforest &df, dfreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function performs binary compression of the decision forest. - -Original decision forest produced by the forest builder is stored using -64-bit representation for all numbers - offsets, variable indexes, split -points. - -It is possible to significantly reduce model size by means of: -* using compressed dynamic encoding for integers (offsets and variable - indexes), which uses just 1 byte to store small ints (less than 128), - just 2 bytes for larger values (less than 128^2) and so on -* storing floating point numbers using 8-bit exponent and 16-bit mantissa - -As result, model needs significantly less memory (compression factor -depends on variable and class counts). In particular: -* NVars<128 and NClasses<128 result in 4.4x-5.7x model size reduction -* NVars<16384 and NClasses<128 result in 3.7x-4.5x model size reduction - -Such storage format performs lossless compression of all integers, but -compression of floating point values (split values) is lossy, with roughly -0.01% relative error introduced during rounding. Thus, we recommend you to -re-evaluate model accuracy after compression. - -Another downside of compression is ~1.5x reduction in the inference -speed due to necessity of dynamic decompression of the compressed model. - -INPUT PARAMETERS: - DF - decision forest built by forest builder - -OUTPUT PARAMETERS: - DF - replaced by compressed forest - -RESULT: - compression factor (in-RAM size of the compressed model vs than of the - uncompressed one), positive number larger than 1.0 - - -- ALGLIB -- - Copyright 22.07.2019 by Bochkanov Sergey -*************************************************************************/ -double dfbinarycompression(const decisionforest &df, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Inference using decision forest - -IMPORTANT: this function is thread-unsafe and may modify internal - structures of the model! You can not use same model object for - parallel evaluation from several threads. - - Use dftsprocess() with independent thread-local buffers if - you need thread-safe evaluation. - -INPUT PARAMETERS: - DF - decision forest model - X - input vector, array[NVars] - Y - possibly preallocated buffer, reallocated if too small - -OUTPUT PARAMETERS: - Y - result. Regression estimate when solving regression task, - vector of posterior probabilities for classification task. - -See also DFProcessI. - - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -void dfprocess(const decisionforest &df, const real_1d_array &x, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -'interactive' variant of DFProcess for languages like Python which support -constructs like "Y = DFProcessI(DF,X)" and interactive mode of interpreter - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - -IMPORTANT: this function is thread-unsafe and may modify internal - structures of the model! You can not use same model object for - parallel evaluation from several threads. - - Use dftsprocess() with independent thread-local buffers if - you need thread-safe evaluation. - - -- ALGLIB -- - Copyright 28.02.2010 by Bochkanov Sergey -*************************************************************************/ -void dfprocessi(const decisionforest &df, const real_1d_array &x, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function returns first component of the inferred vector (i.e. one -with index #0). - -It is a convenience wrapper for dfprocess() intended for either: -* 1-dimensional regression problems -* 2-class classification problems - -In the former case this function returns inference result as scalar, which -is definitely more convenient that wrapping it as vector. In the latter -case it returns probability of object belonging to class #0. - -If you call it for anything different from two cases above, it will work -as defined, i.e. return y[0], although it is of less use in such cases. - -IMPORTANT: this function is thread-unsafe and modifies internal structures - of the model! You can not use same model object for parallel - evaluation from several threads. - - Use dftsprocess() with independent thread-local buffers, if - you need thread-safe evaluation. - -INPUT PARAMETERS: - Model - DF model - X - input vector, array[0..NVars-1]. - -RESULT: - Y[0] - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double dfprocess0(const decisionforest &model, const real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function returns most probable class number for an input X. It is -same as calling dfprocess(model,x,y), then determining i=argmax(y[i]) and -returning i. - -A class number in [0,NOut) range in returned for classification problems, --1 is returned when this function is called for regression problems. - -IMPORTANT: this function is thread-unsafe and modifies internal structures - of the model! You can not use same model object for parallel - evaluation from several threads. - - Use dftsprocess() with independent thread-local buffers, if - you need thread-safe evaluation. - -INPUT PARAMETERS: - Model - decision forest model - X - input vector, array[0..NVars-1]. - -RESULT: - class number, -1 for regression tasks - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -ae_int_t dfclassify(const decisionforest &model, const real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Inference using decision forest - -Thread-safe procesing using external buffer for temporaries. - -This function is thread-safe (i.e . you can use same DF model from -multiple threads) as long as you use different buffer objects for different -threads. - -INPUT PARAMETERS: - DF - decision forest model - Buf - buffer object, must be allocated specifically for this - model with dfcreatebuffer(). - X - input vector, array[NVars] - Y - possibly preallocated buffer, reallocated if too small - -OUTPUT PARAMETERS: - Y - result. Regression estimate when solving regression task, - vector of posterior probabilities for classification task. - -See also DFProcessI. - - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -void dftsprocess(const decisionforest &df, const decisionforestbuffer &buf, const real_1d_array &x, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Relative classification error on the test set - -INPUT PARAMETERS: - DF - decision forest model - XY - test set - NPoints - test set size - -RESULT: - percent of incorrectly classified cases. - Zero if model solves regression task. - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -double dfrelclserror(const decisionforest &df, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Average cross-entropy (in bits per element) on the test set - -INPUT PARAMETERS: - DF - decision forest model - XY - test set - NPoints - test set size - -RESULT: - CrossEntropy/(NPoints*LN(2)). - Zero if model solves regression task. - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -double dfavgce(const decisionforest &df, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -RMS error on the test set - -INPUT PARAMETERS: - DF - decision forest model - XY - test set - NPoints - test set size - -RESULT: - root mean square error. - Its meaning for regression task is obvious. As for - classification task, RMS error means error when estimating posterior - probabilities. - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -double dfrmserror(const decisionforest &df, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Average error on the test set - -INPUT PARAMETERS: - DF - decision forest model - XY - test set - NPoints - test set size - -RESULT: - Its meaning for regression task is obvious. As for - classification task, it means average error when estimating posterior - probabilities. - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -double dfavgerror(const decisionforest &df, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Average relative error on the test set - -INPUT PARAMETERS: - DF - decision forest model - XY - test set - NPoints - test set size - -RESULT: - Its meaning for regression task is obvious. As for - classification task, it means average relative error when estimating - posterior probability of belonging to the correct class. - - -- ALGLIB -- - Copyright 16.02.2009 by Bochkanov Sergey -*************************************************************************/ -double dfavgrelerror(const decisionforest &df, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine builds random decision forest. - ---------- DEPRECATED VERSION! USE DECISION FOREST BUILDER OBJECT --------- - - -- ALGLIB -- - Copyright 19.02.2009 by Bochkanov Sergey -*************************************************************************/ -void dfbuildrandomdecisionforest(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, const ae_int_t ntrees, const double r, ae_int_t &info, decisionforest &df, dfreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine builds random decision forest. - ---------- DEPRECATED VERSION! USE DECISION FOREST BUILDER OBJECT --------- - - -- ALGLIB -- - Copyright 19.02.2009 by Bochkanov Sergey -*************************************************************************/ -void dfbuildrandomdecisionforestx1(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, const ae_int_t ntrees, const ae_int_t nrndvars, const double r, ae_int_t &info, decisionforest &df, dfreport &rep, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_KNN) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -void knnserialize(knnmodel &obj, std::string &s_out); - - -/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -void knnunserialize(const std::string &s_in, knnmodel &obj); - - - - -/************************************************************************* -This function serializes data structure to C++ stream. - -Data stream generated by this function is same as string representation -generated by string version of serializer - alphanumeric characters, -dots, underscores, minus signs, which are grouped into words separated by -spaces and CR+LF. - -We recommend you to read comments on string version of serializer to find -out more about serialization of AlGLIB objects. -*************************************************************************/ -void knnserialize(knnmodel &obj, std::ostream &s_out); - - -/************************************************************************* -This function unserializes data structure from stream. -*************************************************************************/ -void knnunserialize(const std::istream &s_in, knnmodel &obj); - - -/************************************************************************* -This function creates buffer structure which can be used to perform -parallel KNN requests. - -KNN subpackage provides two sets of computing functions - ones which use -internal buffer of KNN model (these functions are single-threaded because -they use same buffer, which can not shared between threads), and ones -which use external buffer. - -This function is used to initialize external buffer. - -INPUT PARAMETERS - Model - KNN model which is associated with newly created buffer - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: buffer object should be used only with model which was used to - initialize buffer. Any attempt to use buffer with different - object is dangerous - you may get integrity check failure - (exception) because sizes of internal arrays do not fit to - dimensions of the model structure. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knncreatebuffer(const knnmodel &model, knnbuffer &buf, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine creates KNNBuilder object which is used to train KNN models. - -By default, new builder stores empty dataset and some reasonable default -settings. At the very least, you should specify dataset prior to building -KNN model. You can also tweak settings of the model construction algorithm -(recommended, although default settings should work well). - -Following actions are mandatory: -* calling knnbuildersetdataset() to specify dataset -* calling knnbuilderbuildknnmodel() to build KNN model using current - dataset and default settings - -Additionally, you may call: -* knnbuildersetnorm() to change norm being used - -INPUT PARAMETERS: - none - -OUTPUT PARAMETERS: - S - KNN builder - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnbuildercreate(knnbuilder &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Specifies regression problem (one or more continuous output variables are -predicted). There also exists "classification" version of this function. - -This subroutine adds dense dataset to the internal storage of the builder -object. Specifying your dataset in the dense format means that the dense -version of the KNN construction algorithm will be invoked. - -INPUT PARAMETERS: - S - KNN builder object - XY - array[NPoints,NVars+NOut] (note: actual size can be - larger, only leading part is used anyway), dataset: - * first NVars elements of each row store values of the - independent variables - * next NOut elements store values of the dependent - variables - NPoints - number of rows in the dataset, NPoints>=1 - NVars - number of independent variables, NVars>=1 - NOut - number of dependent variables, NOut>=1 - -OUTPUT PARAMETERS: - S - KNN builder - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnbuildersetdatasetreg(const knnbuilder &s, const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nout, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Specifies classification problem (two or more classes are predicted). -There also exists "regression" version of this function. - -This subroutine adds dense dataset to the internal storage of the builder -object. Specifying your dataset in the dense format means that the dense -version of the KNN construction algorithm will be invoked. - -INPUT PARAMETERS: - S - KNN builder object - XY - array[NPoints,NVars+1] (note: actual size can be - larger, only leading part is used anyway), dataset: - * first NVars elements of each row store values of the - independent variables - * next element stores class index, in [0,NClasses) - NPoints - number of rows in the dataset, NPoints>=1 - NVars - number of independent variables, NVars>=1 - NClasses - number of classes, NClasses>=2 - -OUTPUT PARAMETERS: - S - KNN builder - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnbuildersetdatasetcls(const knnbuilder &s, const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets norm type used for neighbor search. - -INPUT PARAMETERS: - S - decision forest builder object - NormType - norm type: - * 0 inf-norm - * 1 1-norm - * 2 Euclidean norm (default) - -OUTPUT PARAMETERS: - S - decision forest builder - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnbuildersetnorm(const knnbuilder &s, const ae_int_t nrmtype, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine builds KNN model according to current settings, using -dataset internally stored in the builder object. - -The model being built performs inference using Eps-approximate K nearest -neighbors search algorithm, with: -* K=1, Eps=0 corresponding to the "nearest neighbor algorithm" -* K>1, Eps=0 corresponding to the "K nearest neighbors algorithm" -* K>=1, Eps>0 corresponding to "approximate nearest neighbors algorithm" - -An approximate KNN is a good option for high-dimensional datasets (exact -KNN works slowly when dimensions count grows). - -An ALGLIB implementation of kd-trees is used to perform k-nn searches. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - KNN builder object - K - number of neighbors to search for, K>=1 - Eps - approximation factor: - * Eps=0 means that exact kNN search is performed - * Eps>0 means that (1+Eps)-approximate search is performed - -OUTPUT PARAMETERS: - Model - KNN model - Rep - report - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnbuilderbuildknnmodel(const knnbuilder &s, const ae_int_t k, const double eps, knnmodel &model, knnreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Changing search settings of KNN model. - -K and EPS parameters of KNN (AKNN) search are specified during model -construction. However, plain KNN algorithm with Euclidean distance allows -you to change them at any moment. - -NOTE: future versions of KNN model may support advanced versions of KNN, - such as NCA or LMNN. It is possible that such algorithms won't allow - you to change search settings on the fly. If you call this function - for an algorithm which does not support on-the-fly changes, it will - throw an exception. - -INPUT PARAMETERS: - Model - KNN model - K - K>=1, neighbors count - EPS - accuracy of the EPS-approximate NN search. Set to 0.0, if - you want to perform "classic" KNN search. Specify larger - values if you need to speed-up high-dimensional KNN - queries. - -OUTPUT PARAMETERS: - nothing on success, exception on failure - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnrewritekeps(const knnmodel &model, const ae_int_t k, const double eps, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Inference using KNN model. - -See also knnprocess0(), knnprocessi() and knnclassify() for options with a -bit more convenient interface. - -IMPORTANT: this function is thread-unsafe and modifies internal structures - of the model! You can not use same model object for parallel - evaluation from several threads. - - Use knntsprocess() with independent thread-local buffers, if - you need thread-safe evaluation. - -INPUT PARAMETERS: - Model - KNN model - X - input vector, array[0..NVars-1]. - Y - possible preallocated buffer. Reused if long enough. - -OUTPUT PARAMETERS: - Y - result. Regression estimate when solving regression task, - vector of posterior probabilities for classification task. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnprocess(const knnmodel &model, const real_1d_array &x, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function returns first component of the inferred vector (i.e. one -with index #0). - -It is a convenience wrapper for knnprocess() intended for either: -* 1-dimensional regression problems -* 2-class classification problems - -In the former case this function returns inference result as scalar, which -is definitely more convenient that wrapping it as vector. In the latter -case it returns probability of object belonging to class #0. - -If you call it for anything different from two cases above, it will work -as defined, i.e. return y[0], although it is of less use in such cases. - -IMPORTANT: this function is thread-unsafe and modifies internal structures - of the model! You can not use same model object for parallel - evaluation from several threads. - - Use knntsprocess() with independent thread-local buffers, if - you need thread-safe evaluation. - -INPUT PARAMETERS: - Model - KNN model - X - input vector, array[0..NVars-1]. - -RESULT: - Y[0] - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double knnprocess0(const knnmodel &model, const real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function returns most probable class number for an input X. It is -same as calling knnprocess(model,x,y), then determining i=argmax(y[i]) and -returning i. - -A class number in [0,NOut) range in returned for classification problems, --1 is returned when this function is called for regression problems. - -IMPORTANT: this function is thread-unsafe and modifies internal structures - of the model! You can not use same model object for parallel - evaluation from several threads. - - Use knntsprocess() with independent thread-local buffers, if - you need thread-safe evaluation. - -INPUT PARAMETERS: - Model - KNN model - X - input vector, array[0..NVars-1]. - -RESULT: - class number, -1 for regression tasks - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -ae_int_t knnclassify(const knnmodel &model, const real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -'interactive' variant of knnprocess() for languages like Python which -support constructs like "y = knnprocessi(model,x)" and interactive mode of -the interpreter. - -This function allocates new array on each call, so it is significantly -slower than its 'non-interactive' counterpart, but it is more convenient -when you call it from command line. - -IMPORTANT: this function is thread-unsafe and may modify internal - structures of the model! You can not use same model object for - parallel evaluation from several threads. - - Use knntsprocess() with independent thread-local buffers if - you need thread-safe evaluation. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnprocessi(const knnmodel &model, const real_1d_array &x, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Thread-safe procesing using external buffer for temporaries. - -This function is thread-safe (i.e . you can use same KNN model from -multiple threads) as long as you use different buffer objects for different -threads. - -INPUT PARAMETERS: - Model - KNN model - Buf - buffer object, must be allocated specifically for this - model with knncreatebuffer(). - X - input vector, array[NVars] - -OUTPUT PARAMETERS: - Y - result, array[NOut]. Regression estimate when solving - regression task, vector of posterior probabilities for - a classification task. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knntsprocess(const knnmodel &model, const knnbuffer &buf, const real_1d_array &x, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Relative classification error on the test set - -INPUT PARAMETERS: - Model - KNN model - XY - test set - NPoints - test set size - -RESULT: - percent of incorrectly classified cases. - Zero if model solves regression task. - -NOTE: if you need several different kinds of error metrics, it is better - to use knnallerrors() which computes all error metric with just one - pass over dataset. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double knnrelclserror(const knnmodel &model, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Average cross-entropy (in bits per element) on the test set - -INPUT PARAMETERS: - Model - KNN model - XY - test set - NPoints - test set size - -RESULT: - CrossEntropy/NPoints. - Zero if model solves regression task. - -NOTE: the cross-entropy metric is too unstable when used to evaluate KNN - models (such models can report exactly zero probabilities), so we - do not recommend using it. - -NOTE: if you need several different kinds of error metrics, it is better - to use knnallerrors() which computes all error metric with just one - pass over dataset. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double knnavgce(const knnmodel &model, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -RMS error on the test set. - -Its meaning for regression task is obvious. As for classification problems, -RMS error means error when estimating posterior probabilities. - -INPUT PARAMETERS: - Model - KNN model - XY - test set - NPoints - test set size - -RESULT: - root mean square error. - -NOTE: if you need several different kinds of error metrics, it is better - to use knnallerrors() which computes all error metric with just one - pass over dataset. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double knnrmserror(const knnmodel &model, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Average error on the test set - -Its meaning for regression task is obvious. As for classification problems, -average error means error when estimating posterior probabilities. - -INPUT PARAMETERS: - Model - KNN model - XY - test set - NPoints - test set size - -RESULT: - average error - -NOTE: if you need several different kinds of error metrics, it is better - to use knnallerrors() which computes all error metric with just one - pass over dataset. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double knnavgerror(const knnmodel &model, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Average relative error on the test set - -Its meaning for regression task is obvious. As for classification problems, -average relative error means error when estimating posterior probabilities. - -INPUT PARAMETERS: - Model - KNN model - XY - test set - NPoints - test set size - -RESULT: - average relative error - -NOTE: if you need several different kinds of error metrics, it is better - to use knnallerrors() which computes all error metric with just one - pass over dataset. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -double knnavgrelerror(const knnmodel &model, const real_2d_array &xy, const ae_int_t npoints, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Calculates all kinds of errors for the model in one call. - -INPUT PARAMETERS: - Model - KNN model - XY - test set: - * one row per point - * first NVars columns store independent variables - * depending on problem type: - * next column stores class number in [0,NClasses) - for - classification problems - * next NOut columns store dependent variables - for - regression problems - NPoints - test set size, NPoints>=0 - -OUTPUT PARAMETERS: - Rep - following fields are loaded with errors for both regression - and classification models: - * rep.rmserror - RMS error for the output - * rep.avgerror - average error - * rep.avgrelerror - average relative error - following fields are set only for classification models, - zero for regression ones: - * relclserror - relative classification error, in [0,1] - * avgce - average cross-entropy in bits per dataset entry - -NOTE: the cross-entropy metric is too unstable when used to evaluate KNN - models (such models can report exactly zero probabilities), so we - do not recommend using it. - - -- ALGLIB -- - Copyright 15.02.2019 by Bochkanov Sergey -*************************************************************************/ -void knnallerrors(const knnmodel &model, const real_2d_array &xy, const ae_int_t npoints, knnreport &rep, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_DATACOMP) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -k-means++ clusterization. -Backward compatibility function, we recommend to use CLUSTERING subpackage -as better replacement. - - -- ALGLIB -- - Copyright 21.03.2009 by Bochkanov Sergey -*************************************************************************/ -void kmeansgenerate(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t k, const ae_int_t restarts, ae_int_t &info, real_2d_array &c, integer_1d_array &xyc, const xparams _xparams = alglib::xdefault); -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (FUNCTIONS) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_PCA) || !defined(AE_PARTIAL_BUILD) -void pcabuildbasis(/* Real */ ae_matrix* x, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t* info, - /* Real */ ae_vector* s2, - /* Real */ ae_matrix* v, - ae_state *_state); -void pcatruncatedsubspace(/* Real */ ae_matrix* x, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nneeded, - double eps, - ae_int_t maxits, - /* Real */ ae_vector* s2, - /* Real */ ae_matrix* v, - ae_state *_state); -void pcatruncatedsubspacesparse(sparsematrix* x, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nneeded, - double eps, - ae_int_t maxits, - /* Real */ ae_vector* s2, - /* Real */ ae_matrix* v, - ae_state *_state); -#endif -#if defined(AE_COMPILE_BDSS) || !defined(AE_PARTIAL_BUILD) -void dserrallocate(ae_int_t nclasses, - /* Real */ ae_vector* buf, - ae_state *_state); -void dserraccumulate(/* Real */ ae_vector* buf, - /* Real */ ae_vector* y, - /* Real */ ae_vector* desiredy, - ae_state *_state); -void dserrfinish(/* Real */ ae_vector* buf, ae_state *_state); -void dsnormalize(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t* info, - /* Real */ ae_vector* means, - /* Real */ ae_vector* sigmas, - ae_state *_state); -void dsnormalizec(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t* info, - /* Real */ ae_vector* means, - /* Real */ ae_vector* sigmas, - ae_state *_state); -double dsgetmeanmindistance(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_state *_state); -void dstie(/* Real */ ae_vector* a, - ae_int_t n, - /* Integer */ ae_vector* ties, - ae_int_t* tiecount, - /* Integer */ ae_vector* p1, - /* Integer */ ae_vector* p2, - ae_state *_state); -void dstiefasti(/* Real */ ae_vector* a, - /* Integer */ ae_vector* b, - ae_int_t n, - /* Integer */ ae_vector* ties, - ae_int_t* tiecount, - /* Real */ ae_vector* bufr, - /* Integer */ ae_vector* bufi, - ae_state *_state); -void dsoptimalsplit2(/* Real */ ae_vector* a, - /* Integer */ ae_vector* c, - ae_int_t n, - ae_int_t* info, - double* threshold, - double* pal, - double* pbl, - double* par, - double* pbr, - double* cve, - ae_state *_state); -void dsoptimalsplit2fast(/* Real */ ae_vector* a, - /* Integer */ ae_vector* c, - /* Integer */ ae_vector* tiesbuf, - /* Integer */ ae_vector* cntbuf, - /* Real */ ae_vector* bufr, - /* Integer */ ae_vector* bufi, - ae_int_t n, - ae_int_t nc, - double alpha, - ae_int_t* info, - double* threshold, - double* rms, - double* cvrms, - ae_state *_state); -void dssplitk(/* Real */ ae_vector* a, - /* Integer */ ae_vector* c, - ae_int_t n, - ae_int_t nc, - ae_int_t kmax, - ae_int_t* info, - /* Real */ ae_vector* thresholds, - ae_int_t* ni, - double* cve, - ae_state *_state); -void dsoptimalsplitk(/* Real */ ae_vector* a, - /* Integer */ ae_vector* c, - ae_int_t n, - ae_int_t nc, - ae_int_t kmax, - ae_int_t* info, - /* Real */ ae_vector* thresholds, - ae_int_t* ni, - double* cve, - ae_state *_state); -void _cvreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _cvreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _cvreport_clear(void* _p); -void _cvreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_MLPBASE) || !defined(AE_PARTIAL_BUILD) -ae_int_t mlpgradsplitcost(ae_state *_state); -ae_int_t mlpgradsplitsize(ae_state *_state); -void mlpcreate0(ae_int_t nin, - ae_int_t nout, - multilayerperceptron* network, - ae_state *_state); -void mlpcreate1(ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - multilayerperceptron* network, - ae_state *_state); -void mlpcreate2(ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - multilayerperceptron* network, - ae_state *_state); -void mlpcreateb0(ae_int_t nin, - ae_int_t nout, - double b, - double d, - multilayerperceptron* network, - ae_state *_state); -void mlpcreateb1(ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - double b, - double d, - multilayerperceptron* network, - ae_state *_state); -void mlpcreateb2(ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - double b, - double d, - multilayerperceptron* network, - ae_state *_state); -void mlpcreater0(ae_int_t nin, - ae_int_t nout, - double a, - double b, - multilayerperceptron* network, - ae_state *_state); -void mlpcreater1(ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - double a, - double b, - multilayerperceptron* network, - ae_state *_state); -void mlpcreater2(ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - double a, - double b, - multilayerperceptron* network, - ae_state *_state); -void mlpcreatec0(ae_int_t nin, - ae_int_t nout, - multilayerperceptron* network, - ae_state *_state); -void mlpcreatec1(ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - multilayerperceptron* network, - ae_state *_state); -void mlpcreatec2(ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - multilayerperceptron* network, - ae_state *_state); -void mlpcopy(multilayerperceptron* network1, - multilayerperceptron* network2, - ae_state *_state); -void mlpcopyshared(multilayerperceptron* network1, - multilayerperceptron* network2, - ae_state *_state); -ae_bool mlpsamearchitecture(multilayerperceptron* network1, - multilayerperceptron* network2, - ae_state *_state); -void mlpcopytunableparameters(multilayerperceptron* network1, - multilayerperceptron* network2, - ae_state *_state); -void mlpexporttunableparameters(multilayerperceptron* network, - /* Real */ ae_vector* p, - ae_int_t* pcount, - ae_state *_state); -void mlpimporttunableparameters(multilayerperceptron* network, - /* Real */ ae_vector* p, - ae_state *_state); -void mlpserializeold(multilayerperceptron* network, - /* Real */ ae_vector* ra, - ae_int_t* rlen, - ae_state *_state); -void mlpunserializeold(/* Real */ ae_vector* ra, - multilayerperceptron* network, - ae_state *_state); -void mlprandomize(multilayerperceptron* network, ae_state *_state); -void mlprandomizefull(multilayerperceptron* network, ae_state *_state); -void mlpinitpreprocessor(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t ssize, - ae_state *_state); -void mlpinitpreprocessorsparse(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t ssize, - ae_state *_state); -void mlpinitpreprocessorsubset(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t setsize, - /* Integer */ ae_vector* idx, - ae_int_t subsetsize, - ae_state *_state); -void mlpinitpreprocessorsparsesubset(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t setsize, - /* Integer */ ae_vector* idx, - ae_int_t subsetsize, - ae_state *_state); -void mlpproperties(multilayerperceptron* network, - ae_int_t* nin, - ae_int_t* nout, - ae_int_t* wcount, - ae_state *_state); -ae_int_t mlpntotal(multilayerperceptron* network, ae_state *_state); -ae_int_t mlpgetinputscount(multilayerperceptron* network, - ae_state *_state); -ae_int_t mlpgetoutputscount(multilayerperceptron* network, - ae_state *_state); -ae_int_t mlpgetweightscount(multilayerperceptron* network, - ae_state *_state); -ae_bool mlpissoftmax(multilayerperceptron* network, ae_state *_state); -ae_int_t mlpgetlayerscount(multilayerperceptron* network, - ae_state *_state); -ae_int_t mlpgetlayersize(multilayerperceptron* network, - ae_int_t k, - ae_state *_state); -void mlpgetinputscaling(multilayerperceptron* network, - ae_int_t i, - double* mean, - double* sigma, - ae_state *_state); -void mlpgetoutputscaling(multilayerperceptron* network, - ae_int_t i, - double* mean, - double* sigma, - ae_state *_state); -void mlpgetneuroninfo(multilayerperceptron* network, - ae_int_t k, - ae_int_t i, - ae_int_t* fkind, - double* threshold, - ae_state *_state); -double mlpgetweight(multilayerperceptron* network, - ae_int_t k0, - ae_int_t i0, - ae_int_t k1, - ae_int_t i1, - ae_state *_state); -void mlpsetinputscaling(multilayerperceptron* network, - ae_int_t i, - double mean, - double sigma, - ae_state *_state); -void mlpsetoutputscaling(multilayerperceptron* network, - ae_int_t i, - double mean, - double sigma, - ae_state *_state); -void mlpsetneuroninfo(multilayerperceptron* network, - ae_int_t k, - ae_int_t i, - ae_int_t fkind, - double threshold, - ae_state *_state); -void mlpsetweight(multilayerperceptron* network, - ae_int_t k0, - ae_int_t i0, - ae_int_t k1, - ae_int_t i1, - double w, - ae_state *_state); -void mlpactivationfunction(double net, - ae_int_t k, - double* f, - double* df, - double* d2f, - ae_state *_state); -void mlpprocess(multilayerperceptron* network, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void mlpprocessi(multilayerperceptron* network, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -double mlperror(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double mlperrorsparse(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t npoints, - ae_state *_state); -double mlperrorn(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t ssize, - ae_state *_state); -ae_int_t mlpclserror(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double mlprelclserror(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double mlprelclserrorsparse(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t npoints, - ae_state *_state); -double mlpavgce(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double mlpavgcesparse(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t npoints, - ae_state *_state); -double mlprmserror(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double mlprmserrorsparse(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t npoints, - ae_state *_state); -double mlpavgerror(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double mlpavgerrorsparse(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t npoints, - ae_state *_state); -double mlpavgrelerror(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double mlpavgrelerrorsparse(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t npoints, - ae_state *_state); -void mlpgrad(multilayerperceptron* network, - /* Real */ ae_vector* x, - /* Real */ ae_vector* desiredy, - double* e, - /* Real */ ae_vector* grad, - ae_state *_state); -void mlpgradn(multilayerperceptron* network, - /* Real */ ae_vector* x, - /* Real */ ae_vector* desiredy, - double* e, - /* Real */ ae_vector* grad, - ae_state *_state); -void mlpgradbatch(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t ssize, - double* e, - /* Real */ ae_vector* grad, - ae_state *_state); -void mlpgradbatchsparse(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t ssize, - double* e, - /* Real */ ae_vector* grad, - ae_state *_state); -void mlpgradbatchsubset(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t setsize, - /* Integer */ ae_vector* idx, - ae_int_t subsetsize, - double* e, - /* Real */ ae_vector* grad, - ae_state *_state); -void mlpgradbatchsparsesubset(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t setsize, - /* Integer */ ae_vector* idx, - ae_int_t subsetsize, - double* e, - /* Real */ ae_vector* grad, - ae_state *_state); -void mlpgradbatchx(multilayerperceptron* network, - /* Real */ ae_matrix* densexy, - sparsematrix* sparsexy, - ae_int_t datasetsize, - ae_int_t datasettype, - /* Integer */ ae_vector* idx, - ae_int_t subset0, - ae_int_t subset1, - ae_int_t subsettype, - ae_shared_pool* buf, - ae_shared_pool* gradbuf, - ae_state *_state); -ae_bool _trypexec_mlpgradbatchx(multilayerperceptron* network, - /* Real */ ae_matrix* densexy, - sparsematrix* sparsexy, - ae_int_t datasetsize, - ae_int_t datasettype, - /* Integer */ ae_vector* idx, - ae_int_t subset0, - ae_int_t subset1, - ae_int_t subsettype, - ae_shared_pool* buf, - ae_shared_pool* gradbuf, ae_state *_state); -void mlpgradnbatch(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t ssize, - double* e, - /* Real */ ae_vector* grad, - ae_state *_state); -void mlphessiannbatch(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t ssize, - double* e, - /* Real */ ae_vector* grad, - /* Real */ ae_matrix* h, - ae_state *_state); -void mlphessianbatch(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t ssize, - double* e, - /* Real */ ae_vector* grad, - /* Real */ ae_matrix* h, - ae_state *_state); -void mlpinternalprocessvector(/* Integer */ ae_vector* structinfo, - /* Real */ ae_vector* weights, - /* Real */ ae_vector* columnmeans, - /* Real */ ae_vector* columnsigmas, - /* Real */ ae_vector* neurons, - /* Real */ ae_vector* dfdnet, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void mlpalloc(ae_serializer* s, - multilayerperceptron* network, - ae_state *_state); -void mlpserialize(ae_serializer* s, - multilayerperceptron* network, - ae_state *_state); -void mlpunserialize(ae_serializer* s, - multilayerperceptron* network, - ae_state *_state); -void mlpallerrorssubset(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t setsize, - /* Integer */ ae_vector* subset, - ae_int_t subsetsize, - modelerrors* rep, - ae_state *_state); -void mlpallerrorssparsesubset(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t setsize, - /* Integer */ ae_vector* subset, - ae_int_t subsetsize, - modelerrors* rep, - ae_state *_state); -double mlperrorsubset(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t setsize, - /* Integer */ ae_vector* subset, - ae_int_t subsetsize, - ae_state *_state); -double mlperrorsparsesubset(multilayerperceptron* network, - sparsematrix* xy, - ae_int_t setsize, - /* Integer */ ae_vector* subset, - ae_int_t subsetsize, - ae_state *_state); -void mlpallerrorsx(multilayerperceptron* network, - /* Real */ ae_matrix* densexy, - sparsematrix* sparsexy, - ae_int_t datasetsize, - ae_int_t datasettype, - /* Integer */ ae_vector* idx, - ae_int_t subset0, - ae_int_t subset1, - ae_int_t subsettype, - ae_shared_pool* buf, - modelerrors* rep, - ae_state *_state); -ae_bool _trypexec_mlpallerrorsx(multilayerperceptron* network, - /* Real */ ae_matrix* densexy, - sparsematrix* sparsexy, - ae_int_t datasetsize, - ae_int_t datasettype, - /* Integer */ ae_vector* idx, - ae_int_t subset0, - ae_int_t subset1, - ae_int_t subsettype, - ae_shared_pool* buf, - modelerrors* rep, ae_state *_state); -void _modelerrors_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _modelerrors_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _modelerrors_clear(void* _p); -void _modelerrors_destroy(void* _p); -void _smlpgrad_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _smlpgrad_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _smlpgrad_clear(void* _p); -void _smlpgrad_destroy(void* _p); -void _multilayerperceptron_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _multilayerperceptron_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _multilayerperceptron_clear(void* _p); -void _multilayerperceptron_destroy(void* _p); -#endif -#if defined(AE_COMPILE_LDA) || !defined(AE_PARTIAL_BUILD) -void fisherlda(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - ae_int_t* info, - /* Real */ ae_vector* w, - ae_state *_state); -void fisherldan(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - ae_int_t* info, - /* Real */ ae_matrix* w, - ae_state *_state); -#endif -#if defined(AE_COMPILE_SSA) || !defined(AE_PARTIAL_BUILD) -void ssacreate(ssamodel* s, ae_state *_state); -void ssasetwindow(ssamodel* s, ae_int_t windowwidth, ae_state *_state); -void ssasetseed(ssamodel* s, ae_int_t seed, ae_state *_state); -void ssasetpoweruplength(ssamodel* s, ae_int_t pwlen, ae_state *_state); -void ssasetmemorylimit(ssamodel* s, ae_int_t memlimit, ae_state *_state); -void ssaaddsequence(ssamodel* s, - /* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state); -void ssaappendpointandupdate(ssamodel* s, - double x, - double updateits, - ae_state *_state); -void ssaappendsequenceandupdate(ssamodel* s, - /* Real */ ae_vector* x, - ae_int_t nticks, - double updateits, - ae_state *_state); -void ssasetalgoprecomputed(ssamodel* s, - /* Real */ ae_matrix* a, - ae_int_t windowwidth, - ae_int_t nbasis, - ae_state *_state); -void ssasetalgotopkdirect(ssamodel* s, ae_int_t topk, ae_state *_state); -void ssasetalgotopkrealtime(ssamodel* s, ae_int_t topk, ae_state *_state); -void ssacleardata(ssamodel* s, ae_state *_state); -void ssagetbasis(ssamodel* s, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* sv, - ae_int_t* windowwidth, - ae_int_t* nbasis, - ae_state *_state); -void ssagetlrr(ssamodel* s, - /* Real */ ae_vector* a, - ae_int_t* windowwidth, - ae_state *_state); -void ssaanalyzelastwindow(ssamodel* s, - /* Real */ ae_vector* trend, - /* Real */ ae_vector* noise, - ae_int_t* nticks, - ae_state *_state); -void ssaanalyzelast(ssamodel* s, - ae_int_t nticks, - /* Real */ ae_vector* trend, - /* Real */ ae_vector* noise, - ae_state *_state); -void ssaanalyzesequence(ssamodel* s, - /* Real */ ae_vector* data, - ae_int_t nticks, - /* Real */ ae_vector* trend, - /* Real */ ae_vector* noise, - ae_state *_state); -void ssaforecastlast(ssamodel* s, - ae_int_t nticks, - /* Real */ ae_vector* trend, - ae_state *_state); -void ssaforecastsequence(ssamodel* s, - /* Real */ ae_vector* data, - ae_int_t datalen, - ae_int_t forecastlen, - ae_bool applysmoothing, - /* Real */ ae_vector* trend, - ae_state *_state); -void ssaforecastavglast(ssamodel* s, - ae_int_t m, - ae_int_t nticks, - /* Real */ ae_vector* trend, - ae_state *_state); -void ssaforecastavgsequence(ssamodel* s, - /* Real */ ae_vector* data, - ae_int_t datalen, - ae_int_t m, - ae_int_t forecastlen, - ae_bool applysmoothing, - /* Real */ ae_vector* trend, - ae_state *_state); -void _ssamodel_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _ssamodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _ssamodel_clear(void* _p); -void _ssamodel_destroy(void* _p); -#endif -#if defined(AE_COMPILE_LINREG) || !defined(AE_PARTIAL_BUILD) -void lrbuild(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t* info, - linearmodel* lm, - lrreport* ar, - ae_state *_state); -void lrbuilds(/* Real */ ae_matrix* xy, - /* Real */ ae_vector* s, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t* info, - linearmodel* lm, - lrreport* ar, - ae_state *_state); -void lrbuildzs(/* Real */ ae_matrix* xy, - /* Real */ ae_vector* s, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t* info, - linearmodel* lm, - lrreport* ar, - ae_state *_state); -void lrbuildz(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t* info, - linearmodel* lm, - lrreport* ar, - ae_state *_state); -void lrunpack(linearmodel* lm, - /* Real */ ae_vector* v, - ae_int_t* nvars, - ae_state *_state); -void lrpack(/* Real */ ae_vector* v, - ae_int_t nvars, - linearmodel* lm, - ae_state *_state); -double lrprocess(linearmodel* lm, - /* Real */ ae_vector* x, - ae_state *_state); -double lrrmserror(linearmodel* lm, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double lravgerror(linearmodel* lm, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double lravgrelerror(linearmodel* lm, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -void lrcopy(linearmodel* lm1, linearmodel* lm2, ae_state *_state); -void lrlines(/* Real */ ae_matrix* xy, - /* Real */ ae_vector* s, - ae_int_t n, - ae_int_t* info, - double* a, - double* b, - double* vara, - double* varb, - double* covab, - double* corrab, - double* p, - ae_state *_state); -void lrline(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t* info, - double* a, - double* b, - ae_state *_state); -void _linearmodel_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _linearmodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _linearmodel_clear(void* _p); -void _linearmodel_destroy(void* _p); -void _lrreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _lrreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _lrreport_clear(void* _p); -void _lrreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_FILTERS) || !defined(AE_PARTIAL_BUILD) -void filtersma(/* Real */ ae_vector* x, - ae_int_t n, - ae_int_t k, - ae_state *_state); -void filterema(/* Real */ ae_vector* x, - ae_int_t n, - double alpha, - ae_state *_state); -void filterlrma(/* Real */ ae_vector* x, - ae_int_t n, - ae_int_t k, - ae_state *_state); -#endif -#if defined(AE_COMPILE_LOGIT) || !defined(AE_PARTIAL_BUILD) -void mnltrainh(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - ae_int_t* info, - logitmodel* lm, - mnlreport* rep, - ae_state *_state); -void mnlprocess(logitmodel* lm, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void mnlprocessi(logitmodel* lm, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void mnlunpack(logitmodel* lm, - /* Real */ ae_matrix* a, - ae_int_t* nvars, - ae_int_t* nclasses, - ae_state *_state); -void mnlpack(/* Real */ ae_matrix* a, - ae_int_t nvars, - ae_int_t nclasses, - logitmodel* lm, - ae_state *_state); -void mnlcopy(logitmodel* lm1, logitmodel* lm2, ae_state *_state); -double mnlavgce(logitmodel* lm, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double mnlrelclserror(logitmodel* lm, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double mnlrmserror(logitmodel* lm, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double mnlavgerror(logitmodel* lm, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double mnlavgrelerror(logitmodel* lm, - /* Real */ ae_matrix* xy, - ae_int_t ssize, - ae_state *_state); -ae_int_t mnlclserror(logitmodel* lm, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -void _logitmodel_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _logitmodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _logitmodel_clear(void* _p); -void _logitmodel_destroy(void* _p); -void _logitmcstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _logitmcstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _logitmcstate_clear(void* _p); -void _logitmcstate_destroy(void* _p); -void _mnlreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _mnlreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _mnlreport_clear(void* _p); -void _mnlreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_MCPD) || !defined(AE_PARTIAL_BUILD) -void mcpdcreate(ae_int_t n, mcpdstate* s, ae_state *_state); -void mcpdcreateentry(ae_int_t n, - ae_int_t entrystate, - mcpdstate* s, - ae_state *_state); -void mcpdcreateexit(ae_int_t n, - ae_int_t exitstate, - mcpdstate* s, - ae_state *_state); -void mcpdcreateentryexit(ae_int_t n, - ae_int_t entrystate, - ae_int_t exitstate, - mcpdstate* s, - ae_state *_state); -void mcpdaddtrack(mcpdstate* s, - /* Real */ ae_matrix* xy, - ae_int_t k, - ae_state *_state); -void mcpdsetec(mcpdstate* s, - /* Real */ ae_matrix* ec, - ae_state *_state); -void mcpdaddec(mcpdstate* s, - ae_int_t i, - ae_int_t j, - double c, - ae_state *_state); -void mcpdsetbc(mcpdstate* s, - /* Real */ ae_matrix* bndl, - /* Real */ ae_matrix* bndu, - ae_state *_state); -void mcpdaddbc(mcpdstate* s, - ae_int_t i, - ae_int_t j, - double bndl, - double bndu, - ae_state *_state); -void mcpdsetlc(mcpdstate* s, - /* Real */ ae_matrix* c, - /* Integer */ ae_vector* ct, - ae_int_t k, - ae_state *_state); -void mcpdsettikhonovregularizer(mcpdstate* s, double v, ae_state *_state); -void mcpdsetprior(mcpdstate* s, - /* Real */ ae_matrix* pp, - ae_state *_state); -void mcpdsetpredictionweights(mcpdstate* s, - /* Real */ ae_vector* pw, - ae_state *_state); -void mcpdsolve(mcpdstate* s, ae_state *_state); -void mcpdresults(mcpdstate* s, - /* Real */ ae_matrix* p, - mcpdreport* rep, - ae_state *_state); -void _mcpdstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _mcpdstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _mcpdstate_clear(void* _p); -void _mcpdstate_destroy(void* _p); -void _mcpdreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _mcpdreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _mcpdreport_clear(void* _p); -void _mcpdreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_MLPE) || !defined(AE_PARTIAL_BUILD) -void mlpecreate0(ae_int_t nin, - ae_int_t nout, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state); -void mlpecreate1(ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state); -void mlpecreate2(ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state); -void mlpecreateb0(ae_int_t nin, - ae_int_t nout, - double b, - double d, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state); -void mlpecreateb1(ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - double b, - double d, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state); -void mlpecreateb2(ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - double b, - double d, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state); -void mlpecreater0(ae_int_t nin, - ae_int_t nout, - double a, - double b, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state); -void mlpecreater1(ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - double a, - double b, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state); -void mlpecreater2(ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - double a, - double b, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state); -void mlpecreatec0(ae_int_t nin, - ae_int_t nout, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state); -void mlpecreatec1(ae_int_t nin, - ae_int_t nhid, - ae_int_t nout, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state); -void mlpecreatec2(ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state); -void mlpecreatefromnetwork(multilayerperceptron* network, - ae_int_t ensemblesize, - mlpensemble* ensemble, - ae_state *_state); -void mlpecopy(mlpensemble* ensemble1, - mlpensemble* ensemble2, - ae_state *_state); -void mlperandomize(mlpensemble* ensemble, ae_state *_state); -void mlpeproperties(mlpensemble* ensemble, - ae_int_t* nin, - ae_int_t* nout, - ae_state *_state); -ae_bool mlpeissoftmax(mlpensemble* ensemble, ae_state *_state); -void mlpeprocess(mlpensemble* ensemble, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void mlpeprocessi(mlpensemble* ensemble, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void mlpeallerrorsx(mlpensemble* ensemble, - /* Real */ ae_matrix* densexy, - sparsematrix* sparsexy, - ae_int_t datasetsize, - ae_int_t datasettype, - /* Integer */ ae_vector* idx, - ae_int_t subset0, - ae_int_t subset1, - ae_int_t subsettype, - ae_shared_pool* buf, - modelerrors* rep, - ae_state *_state); -void mlpeallerrorssparse(mlpensemble* ensemble, - sparsematrix* xy, - ae_int_t npoints, - double* relcls, - double* avgce, - double* rms, - double* avg, - double* avgrel, - ae_state *_state); -double mlperelclserror(mlpensemble* ensemble, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double mlpeavgce(mlpensemble* ensemble, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double mlpermserror(mlpensemble* ensemble, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double mlpeavgerror(mlpensemble* ensemble, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double mlpeavgrelerror(mlpensemble* ensemble, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -void mlpealloc(ae_serializer* s, mlpensemble* ensemble, ae_state *_state); -void mlpeserialize(ae_serializer* s, - mlpensemble* ensemble, - ae_state *_state); -void mlpeunserialize(ae_serializer* s, - mlpensemble* ensemble, - ae_state *_state); -void _mlpensemble_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _mlpensemble_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _mlpensemble_clear(void* _p); -void _mlpensemble_destroy(void* _p); -#endif -#if defined(AE_COMPILE_MLPTRAIN) || !defined(AE_PARTIAL_BUILD) -void mlptrainlm(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - ae_int_t* info, - mlpreport* rep, - ae_state *_state); -void mlptrainlbfgs(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - double wstep, - ae_int_t maxits, - ae_int_t* info, - mlpreport* rep, - ae_state *_state); -void mlptraines(multilayerperceptron* network, - /* Real */ ae_matrix* trnxy, - ae_int_t trnsize, - /* Real */ ae_matrix* valxy, - ae_int_t valsize, - double decay, - ae_int_t restarts, - ae_int_t* info, - mlpreport* rep, - ae_state *_state); -void mlpkfoldcvlbfgs(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - double wstep, - ae_int_t maxits, - ae_int_t foldscount, - ae_int_t* info, - mlpreport* rep, - mlpcvreport* cvrep, - ae_state *_state); -void mlpkfoldcvlm(multilayerperceptron* network, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - ae_int_t foldscount, - ae_int_t* info, - mlpreport* rep, - mlpcvreport* cvrep, - ae_state *_state); -void mlpkfoldcv(mlptrainer* s, - multilayerperceptron* network, - ae_int_t nrestarts, - ae_int_t foldscount, - mlpreport* rep, - ae_state *_state); -void mlpcreatetrainer(ae_int_t nin, - ae_int_t nout, - mlptrainer* s, - ae_state *_state); -void mlpcreatetrainercls(ae_int_t nin, - ae_int_t nclasses, - mlptrainer* s, - ae_state *_state); -void mlpsetdataset(mlptrainer* s, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -void mlpsetsparsedataset(mlptrainer* s, - sparsematrix* xy, - ae_int_t npoints, - ae_state *_state); -void mlpsetdecay(mlptrainer* s, double decay, ae_state *_state); -void mlpsetcond(mlptrainer* s, - double wstep, - ae_int_t maxits, - ae_state *_state); -void mlpsetalgobatch(mlptrainer* s, ae_state *_state); -void mlptrainnetwork(mlptrainer* s, - multilayerperceptron* network, - ae_int_t nrestarts, - mlpreport* rep, - ae_state *_state); -void mlpstarttraining(mlptrainer* s, - multilayerperceptron* network, - ae_bool randomstart, - ae_state *_state); -ae_bool mlpcontinuetraining(mlptrainer* s, - multilayerperceptron* network, - ae_state *_state); -void mlpebagginglm(mlpensemble* ensemble, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - ae_int_t* info, - mlpreport* rep, - mlpcvreport* ooberrors, - ae_state *_state); -void mlpebagginglbfgs(mlpensemble* ensemble, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - double wstep, - ae_int_t maxits, - ae_int_t* info, - mlpreport* rep, - mlpcvreport* ooberrors, - ae_state *_state); -void mlpetraines(mlpensemble* ensemble, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double decay, - ae_int_t restarts, - ae_int_t* info, - mlpreport* rep, - ae_state *_state); -void mlptrainensemblees(mlptrainer* s, - mlpensemble* ensemble, - ae_int_t nrestarts, - mlpreport* rep, - ae_state *_state); -void _mlpreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _mlpreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _mlpreport_clear(void* _p); -void _mlpreport_destroy(void* _p); -void _mlpcvreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _mlpcvreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _mlpcvreport_clear(void* _p); -void _mlpcvreport_destroy(void* _p); -void _smlptrnsession_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _smlptrnsession_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _smlptrnsession_clear(void* _p); -void _smlptrnsession_destroy(void* _p); -void _mlpetrnsession_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _mlpetrnsession_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _mlpetrnsession_clear(void* _p); -void _mlpetrnsession_destroy(void* _p); -void _mlptrainer_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _mlptrainer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _mlptrainer_clear(void* _p); -void _mlptrainer_destroy(void* _p); -void _mlpparallelizationcv_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _mlpparallelizationcv_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _mlpparallelizationcv_clear(void* _p); -void _mlpparallelizationcv_destroy(void* _p); -#endif -#if defined(AE_COMPILE_CLUSTERING) || !defined(AE_PARTIAL_BUILD) -void clusterizercreate(clusterizerstate* s, ae_state *_state); -void clusterizersetpoints(clusterizerstate* s, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nfeatures, - ae_int_t disttype, - ae_state *_state); -void clusterizersetdistances(clusterizerstate* s, - /* Real */ ae_matrix* d, - ae_int_t npoints, - ae_bool isupper, - ae_state *_state); -void clusterizersetahcalgo(clusterizerstate* s, - ae_int_t algo, - ae_state *_state); -void clusterizersetkmeanslimits(clusterizerstate* s, - ae_int_t restarts, - ae_int_t maxits, - ae_state *_state); -void clusterizersetkmeansinit(clusterizerstate* s, - ae_int_t initalgo, - ae_state *_state); -void clusterizersetseed(clusterizerstate* s, - ae_int_t seed, - ae_state *_state); -void clusterizerrunahc(clusterizerstate* s, - ahcreport* rep, - ae_state *_state); -void clusterizerrunkmeans(clusterizerstate* s, - ae_int_t k, - kmeansreport* rep, - ae_state *_state); -void clusterizergetdistances(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nfeatures, - ae_int_t disttype, - /* Real */ ae_matrix* d, - ae_state *_state); -void clusterizergetdistancesbuf(apbuffers* buf, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nfeatures, - ae_int_t disttype, - /* Real */ ae_matrix* d, - ae_state *_state); -void clusterizergetkclusters(ahcreport* rep, - ae_int_t k, - /* Integer */ ae_vector* cidx, - /* Integer */ ae_vector* cz, - ae_state *_state); -void clusterizerseparatedbydist(ahcreport* rep, - double r, - ae_int_t* k, - /* Integer */ ae_vector* cidx, - /* Integer */ ae_vector* cz, - ae_state *_state); -void clusterizerseparatedbycorr(ahcreport* rep, - double r, - ae_int_t* k, - /* Integer */ ae_vector* cidx, - /* Integer */ ae_vector* cz, - ae_state *_state); -void kmeansinitbuf(kmeansbuffers* buf, ae_state *_state); -void kmeansgenerateinternal(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t k, - ae_int_t initalgo, - ae_int_t seed, - ae_int_t maxits, - ae_int_t restarts, - ae_bool kmeansdbgnoits, - ae_int_t* info, - ae_int_t* iterationscount, - /* Real */ ae_matrix* ccol, - ae_bool needccol, - /* Real */ ae_matrix* crow, - ae_bool needcrow, - /* Integer */ ae_vector* xyc, - double* energy, - kmeansbuffers* buf, - ae_state *_state); -void kmeansupdatedistances(/* Real */ ae_matrix* xy, - ae_int_t idx0, - ae_int_t idx1, - ae_int_t nvars, - /* Real */ ae_matrix* ct, - ae_int_t cidx0, - ae_int_t cidx1, - /* Integer */ ae_vector* xyc, - /* Real */ ae_vector* xydist2, - ae_shared_pool* bufferpool, - ae_state *_state); -ae_bool _trypexec_kmeansupdatedistances(/* Real */ ae_matrix* xy, - ae_int_t idx0, - ae_int_t idx1, - ae_int_t nvars, - /* Real */ ae_matrix* ct, - ae_int_t cidx0, - ae_int_t cidx1, - /* Integer */ ae_vector* xyc, - /* Real */ ae_vector* xydist2, - ae_shared_pool* bufferpool, ae_state *_state); -void _kmeansbuffers_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _kmeansbuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _kmeansbuffers_clear(void* _p); -void _kmeansbuffers_destroy(void* _p); -void _clusterizerstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _clusterizerstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _clusterizerstate_clear(void* _p); -void _clusterizerstate_destroy(void* _p); -void _ahcreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _ahcreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _ahcreport_clear(void* _p); -void _ahcreport_destroy(void* _p); -void _kmeansreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _kmeansreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _kmeansreport_clear(void* _p); -void _kmeansreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_DFOREST) || !defined(AE_PARTIAL_BUILD) -void dfcreatebuffer(decisionforest* model, - decisionforestbuffer* buf, - ae_state *_state); -void dfbuildercreate(decisionforestbuilder* s, ae_state *_state); -void dfbuildersetdataset(decisionforestbuilder* s, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - ae_state *_state); -void dfbuildersetrndvars(decisionforestbuilder* s, - ae_int_t rndvars, - ae_state *_state); -void dfbuildersetrndvarsratio(decisionforestbuilder* s, - double f, - ae_state *_state); -void dfbuildersetrndvarsauto(decisionforestbuilder* s, ae_state *_state); -void dfbuildersetsubsampleratio(decisionforestbuilder* s, - double f, - ae_state *_state); -void dfbuildersetseed(decisionforestbuilder* s, - ae_int_t seedval, - ae_state *_state); -void dfbuildersetrdfalgo(decisionforestbuilder* s, - ae_int_t algotype, - ae_state *_state); -void dfbuildersetrdfsplitstrength(decisionforestbuilder* s, - ae_int_t splitstrength, - ae_state *_state); -void dfbuildersetimportancetrngini(decisionforestbuilder* s, - ae_state *_state); -void dfbuildersetimportanceoobgini(decisionforestbuilder* s, - ae_state *_state); -void dfbuildersetimportancepermutation(decisionforestbuilder* s, - ae_state *_state); -void dfbuildersetimportancenone(decisionforestbuilder* s, - ae_state *_state); -double dfbuildergetprogress(decisionforestbuilder* s, ae_state *_state); -double dfbuilderpeekprogress(decisionforestbuilder* s, ae_state *_state); -void dfbuilderbuildrandomforest(decisionforestbuilder* s, - ae_int_t ntrees, - decisionforest* df, - dfreport* rep, - ae_state *_state); -double dfbinarycompression(decisionforest* df, ae_state *_state); -double dfbinarycompression8(decisionforest* df, ae_state *_state); -void dfprocess(decisionforest* df, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void dfprocessi(decisionforest* df, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -double dfprocess0(decisionforest* model, - /* Real */ ae_vector* x, - ae_state *_state); -ae_int_t dfclassify(decisionforest* model, - /* Real */ ae_vector* x, - ae_state *_state); -void dftsprocess(decisionforest* df, - decisionforestbuffer* buf, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -double dfrelclserror(decisionforest* df, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double dfavgce(decisionforest* df, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double dfrmserror(decisionforest* df, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double dfavgerror(decisionforest* df, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double dfavgrelerror(decisionforest* df, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -void dfcopy(decisionforest* df1, decisionforest* df2, ae_state *_state); -void dfalloc(ae_serializer* s, decisionforest* forest, ae_state *_state); -void dfserialize(ae_serializer* s, - decisionforest* forest, - ae_state *_state); -void dfunserialize(ae_serializer* s, - decisionforest* forest, - ae_state *_state); -void dfbuildrandomdecisionforest(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - ae_int_t ntrees, - double r, - ae_int_t* info, - decisionforest* df, - dfreport* rep, - ae_state *_state); -void dfbuildrandomdecisionforestx1(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - ae_int_t ntrees, - ae_int_t nrndvars, - double r, - ae_int_t* info, - decisionforest* df, - dfreport* rep, - ae_state *_state); -void dfbuildinternal(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - ae_int_t ntrees, - ae_int_t samplesize, - ae_int_t nfeatures, - ae_int_t flags, - ae_int_t* info, - decisionforest* df, - dfreport* rep, - ae_state *_state); -void _decisionforestbuilder_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _decisionforestbuilder_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _decisionforestbuilder_clear(void* _p); -void _decisionforestbuilder_destroy(void* _p); -void _dfworkbuf_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _dfworkbuf_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _dfworkbuf_clear(void* _p); -void _dfworkbuf_destroy(void* _p); -void _dfvotebuf_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _dfvotebuf_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _dfvotebuf_clear(void* _p); -void _dfvotebuf_destroy(void* _p); -void _dfpermimpbuf_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _dfpermimpbuf_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _dfpermimpbuf_clear(void* _p); -void _dfpermimpbuf_destroy(void* _p); -void _dftreebuf_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _dftreebuf_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _dftreebuf_clear(void* _p); -void _dftreebuf_destroy(void* _p); -void _decisionforestbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _decisionforestbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _decisionforestbuffer_clear(void* _p); -void _decisionforestbuffer_destroy(void* _p); -void _decisionforest_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _decisionforest_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _decisionforest_clear(void* _p); -void _decisionforest_destroy(void* _p); -void _dfreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _dfreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _dfreport_clear(void* _p); -void _dfreport_destroy(void* _p); -void _dfinternalbuffers_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _dfinternalbuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _dfinternalbuffers_clear(void* _p); -void _dfinternalbuffers_destroy(void* _p); -#endif -#if defined(AE_COMPILE_KNN) || !defined(AE_PARTIAL_BUILD) -void knncreatebuffer(knnmodel* model, knnbuffer* buf, ae_state *_state); -void knnbuildercreate(knnbuilder* s, ae_state *_state); -void knnbuildersetdatasetreg(knnbuilder* s, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nout, - ae_state *_state); -void knnbuildersetdatasetcls(knnbuilder* s, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t nclasses, - ae_state *_state); -void knnbuildersetnorm(knnbuilder* s, ae_int_t nrmtype, ae_state *_state); -void knnbuilderbuildknnmodel(knnbuilder* s, - ae_int_t k, - double eps, - knnmodel* model, - knnreport* rep, - ae_state *_state); -void knnrewritekeps(knnmodel* model, - ae_int_t k, - double eps, - ae_state *_state); -void knnprocess(knnmodel* model, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -double knnprocess0(knnmodel* model, - /* Real */ ae_vector* x, - ae_state *_state); -ae_int_t knnclassify(knnmodel* model, - /* Real */ ae_vector* x, - ae_state *_state); -void knnprocessi(knnmodel* model, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void knntsprocess(knnmodel* model, - knnbuffer* buf, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -double knnrelclserror(knnmodel* model, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double knnavgce(knnmodel* model, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double knnrmserror(knnmodel* model, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double knnavgerror(knnmodel* model, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -double knnavgrelerror(knnmodel* model, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_state *_state); -void knnallerrors(knnmodel* model, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - knnreport* rep, - ae_state *_state); -void knnalloc(ae_serializer* s, knnmodel* model, ae_state *_state); -void knnserialize(ae_serializer* s, knnmodel* model, ae_state *_state); -void knnunserialize(ae_serializer* s, knnmodel* model, ae_state *_state); -void _knnbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _knnbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _knnbuffer_clear(void* _p); -void _knnbuffer_destroy(void* _p); -void _knnbuilder_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _knnbuilder_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _knnbuilder_clear(void* _p); -void _knnbuilder_destroy(void* _p); -void _knnmodel_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _knnmodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _knnmodel_clear(void* _p); -void _knnmodel_destroy(void* _p); -void _knnreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _knnreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _knnreport_clear(void* _p); -void _knnreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_DATACOMP) || !defined(AE_PARTIAL_BUILD) -void kmeansgenerate(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - ae_int_t k, - ae_int_t restarts, - ae_int_t* info, - /* Real */ ae_matrix* c, - /* Integer */ ae_vector* xyc, - ae_state *_state); -#endif - -} -#endif - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/diffequations.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/diffequations.cpp deleted file mode 100644 index 22bbd93..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/diffequations.cpp +++ /dev/null @@ -1,1318 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifdef _MSC_VER -#define _CRT_SECURE_NO_WARNINGS -#endif -#include "stdafx.h" -#include "diffequations.h" - -// disable some irrelevant warnings -#if (AE_COMPILER==AE_MSVC) && !defined(AE_ALL_WARNINGS) -#pragma warning(disable:4100) -#pragma warning(disable:4127) -#pragma warning(disable:4611) -#pragma warning(disable:4702) -#pragma warning(disable:4996) -#endif - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_ODESOLVER) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_ODESOLVER) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - -*************************************************************************/ -_odesolverstate_owner::_odesolverstate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_odesolverstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::odesolverstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::odesolverstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::odesolverstate)); - alglib_impl::_odesolverstate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_odesolverstate_owner::_odesolverstate_owner(const _odesolverstate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_odesolverstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: odesolverstate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::odesolverstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::odesolverstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::odesolverstate)); - alglib_impl::_odesolverstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_odesolverstate_owner& _odesolverstate_owner::operator=(const _odesolverstate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: odesolverstate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: odesolverstate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_odesolverstate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::odesolverstate)); - alglib_impl::_odesolverstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_odesolverstate_owner::~_odesolverstate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_odesolverstate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::odesolverstate* _odesolverstate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::odesolverstate* _odesolverstate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -odesolverstate::odesolverstate() : _odesolverstate_owner() ,needdy(p_struct->needdy),y(&p_struct->y),dy(&p_struct->dy),x(p_struct->x) -{ -} - -odesolverstate::odesolverstate(const odesolverstate &rhs):_odesolverstate_owner(rhs) ,needdy(p_struct->needdy),y(&p_struct->y),dy(&p_struct->dy),x(p_struct->x) -{ -} - -odesolverstate& odesolverstate::operator=(const odesolverstate &rhs) -{ - if( this==&rhs ) - return *this; - _odesolverstate_owner::operator=(rhs); - return *this; -} - -odesolverstate::~odesolverstate() -{ -} - - -/************************************************************************* - -*************************************************************************/ -_odesolverreport_owner::_odesolverreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_odesolverreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::odesolverreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::odesolverreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::odesolverreport)); - alglib_impl::_odesolverreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_odesolverreport_owner::_odesolverreport_owner(const _odesolverreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_odesolverreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: odesolverreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::odesolverreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::odesolverreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::odesolverreport)); - alglib_impl::_odesolverreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_odesolverreport_owner& _odesolverreport_owner::operator=(const _odesolverreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: odesolverreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: odesolverreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_odesolverreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::odesolverreport)); - alglib_impl::_odesolverreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_odesolverreport_owner::~_odesolverreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_odesolverreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::odesolverreport* _odesolverreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::odesolverreport* _odesolverreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -odesolverreport::odesolverreport() : _odesolverreport_owner() ,nfev(p_struct->nfev),terminationtype(p_struct->terminationtype) -{ -} - -odesolverreport::odesolverreport(const odesolverreport &rhs):_odesolverreport_owner(rhs) ,nfev(p_struct->nfev),terminationtype(p_struct->terminationtype) -{ -} - -odesolverreport& odesolverreport::operator=(const odesolverreport &rhs) -{ - if( this==&rhs ) - return *this; - _odesolverreport_owner::operator=(rhs); - return *this; -} - -odesolverreport::~odesolverreport() -{ -} - -/************************************************************************* -Cash-Karp adaptive ODE solver. - -This subroutine solves ODE Y'=f(Y,x) with initial conditions Y(xs)=Ys -(here Y may be single variable or vector of N variables). - -INPUT PARAMETERS: - Y - initial conditions, array[0..N-1]. - contains values of Y[] at X[0] - N - system size - X - points at which Y should be tabulated, array[0..M-1] - integrations starts at X[0], ends at X[M-1], intermediate - values at X[i] are returned too. - SHOULD BE ORDERED BY ASCENDING OR BY DESCENDING! - M - number of intermediate points + first point + last point: - * M>2 means that you need both Y(X[M-1]) and M-2 values at - intermediate points - * M=2 means that you want just to integrate from X[0] to - X[1] and don't interested in intermediate values. - * M=1 means that you don't want to integrate :) - it is degenerate case, but it will be handled correctly. - * M<1 means error - Eps - tolerance (absolute/relative error on each step will be - less than Eps). When passing: - * Eps>0, it means desired ABSOLUTE error - * Eps<0, it means desired RELATIVE error. Relative errors - are calculated with respect to maximum values of Y seen - so far. Be careful to use this criterion when starting - from Y[] that are close to zero. - H - initial step lenth, it will be adjusted automatically - after the first step. If H=0, step will be selected - automatically (usualy it will be equal to 0.001 of - min(x[i]-x[j])). - -OUTPUT PARAMETERS - State - structure which stores algorithm state between subsequent - calls of OdeSolverIteration. Used for reverse communication. - This structure should be passed to the OdeSolverIteration - subroutine. - -SEE ALSO - AutoGKSmoothW, AutoGKSingular, AutoGKIteration, AutoGKResults. - - - -- ALGLIB -- - Copyright 01.09.2009 by Bochkanov Sergey -*************************************************************************/ -void odesolverrkck(const real_1d_array &y, const ae_int_t n, const real_1d_array &x, const ae_int_t m, const double eps, const double h, odesolverstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::odesolverrkck(const_cast(y.c_ptr()), n, const_cast(x.c_ptr()), m, eps, h, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Cash-Karp adaptive ODE solver. - -This subroutine solves ODE Y'=f(Y,x) with initial conditions Y(xs)=Ys -(here Y may be single variable or vector of N variables). - -INPUT PARAMETERS: - Y - initial conditions, array[0..N-1]. - contains values of Y[] at X[0] - N - system size - X - points at which Y should be tabulated, array[0..M-1] - integrations starts at X[0], ends at X[M-1], intermediate - values at X[i] are returned too. - SHOULD BE ORDERED BY ASCENDING OR BY DESCENDING! - M - number of intermediate points + first point + last point: - * M>2 means that you need both Y(X[M-1]) and M-2 values at - intermediate points - * M=2 means that you want just to integrate from X[0] to - X[1] and don't interested in intermediate values. - * M=1 means that you don't want to integrate :) - it is degenerate case, but it will be handled correctly. - * M<1 means error - Eps - tolerance (absolute/relative error on each step will be - less than Eps). When passing: - * Eps>0, it means desired ABSOLUTE error - * Eps<0, it means desired RELATIVE error. Relative errors - are calculated with respect to maximum values of Y seen - so far. Be careful to use this criterion when starting - from Y[] that are close to zero. - H - initial step lenth, it will be adjusted automatically - after the first step. If H=0, step will be selected - automatically (usualy it will be equal to 0.001 of - min(x[i]-x[j])). - -OUTPUT PARAMETERS - State - structure which stores algorithm state between subsequent - calls of OdeSolverIteration. Used for reverse communication. - This structure should be passed to the OdeSolverIteration - subroutine. - -SEE ALSO - AutoGKSmoothW, AutoGKSingular, AutoGKIteration, AutoGKResults. - - - -- ALGLIB -- - Copyright 01.09.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void odesolverrkck(const real_1d_array &y, const real_1d_array &x, const double eps, const double h, odesolverstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t m; - - n = y.length(); - m = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::odesolverrkck(const_cast(y.c_ptr()), n, const_cast(x.c_ptr()), m, eps, h, const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool odesolveriteration(const odesolverstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::odesolveriteration(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - - -void odesolversolve(odesolverstate &state, - void (*diff)(const real_1d_array &y, double x, real_1d_array &dy, void *ptr), - void *ptr, const xparams _xparams){ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(diff!=NULL, "ALGLIB: error in 'odesolversolve()' (diff is NULL)", &_alglib_env_state); - while( alglib_impl::odesolveriteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needdy ) - { - diff(state.y, state.x, state.dy, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: unexpected error in 'odesolversolve'", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - - -/************************************************************************* -ODE solver results - -Called after OdeSolverIteration returned False. - -INPUT PARAMETERS: - State - algorithm state (used by OdeSolverIteration). - -OUTPUT PARAMETERS: - M - number of tabulated values, M>=1 - XTbl - array[0..M-1], values of X - YTbl - array[0..M-1,0..N-1], values of Y in X[i] - Rep - solver report: - * Rep.TerminationType completetion code: - * -2 X is not ordered by ascending/descending or - there are non-distinct X[], i.e. X[i]=X[i+1] - * -1 incorrect parameters were specified - * 1 task has been solved - * Rep.NFEV contains number of function calculations - - -- ALGLIB -- - Copyright 01.09.2009 by Bochkanov Sergey -*************************************************************************/ -void odesolverresults(const odesolverstate &state, ae_int_t &m, real_1d_array &xtbl, real_2d_array &ytbl, odesolverreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::odesolverresults(const_cast(state.c_ptr()), &m, const_cast(xtbl.c_ptr()), const_cast(ytbl.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF COMPUTATIONAL CORE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_ODESOLVER) || !defined(AE_PARTIAL_BUILD) -static double odesolver_odesolvermaxgrow = 3.0; -static double odesolver_odesolvermaxshrink = 10.0; -static void odesolver_odesolverinit(ae_int_t solvertype, - /* Real */ ae_vector* y, - ae_int_t n, - /* Real */ ae_vector* x, - ae_int_t m, - double eps, - double h, - odesolverstate* state, - ae_state *_state); - - -#endif - -#if defined(AE_COMPILE_ODESOLVER) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Cash-Karp adaptive ODE solver. - -This subroutine solves ODE Y'=f(Y,x) with initial conditions Y(xs)=Ys -(here Y may be single variable or vector of N variables). - -INPUT PARAMETERS: - Y - initial conditions, array[0..N-1]. - contains values of Y[] at X[0] - N - system size - X - points at which Y should be tabulated, array[0..M-1] - integrations starts at X[0], ends at X[M-1], intermediate - values at X[i] are returned too. - SHOULD BE ORDERED BY ASCENDING OR BY DESCENDING! - M - number of intermediate points + first point + last point: - * M>2 means that you need both Y(X[M-1]) and M-2 values at - intermediate points - * M=2 means that you want just to integrate from X[0] to - X[1] and don't interested in intermediate values. - * M=1 means that you don't want to integrate :) - it is degenerate case, but it will be handled correctly. - * M<1 means error - Eps - tolerance (absolute/relative error on each step will be - less than Eps). When passing: - * Eps>0, it means desired ABSOLUTE error - * Eps<0, it means desired RELATIVE error. Relative errors - are calculated with respect to maximum values of Y seen - so far. Be careful to use this criterion when starting - from Y[] that are close to zero. - H - initial step lenth, it will be adjusted automatically - after the first step. If H=0, step will be selected - automatically (usualy it will be equal to 0.001 of - min(x[i]-x[j])). - -OUTPUT PARAMETERS - State - structure which stores algorithm state between subsequent - calls of OdeSolverIteration. Used for reverse communication. - This structure should be passed to the OdeSolverIteration - subroutine. - -SEE ALSO - AutoGKSmoothW, AutoGKSingular, AutoGKIteration, AutoGKResults. - - - -- ALGLIB -- - Copyright 01.09.2009 by Bochkanov Sergey -*************************************************************************/ -void odesolverrkck(/* Real */ ae_vector* y, - ae_int_t n, - /* Real */ ae_vector* x, - ae_int_t m, - double eps, - double h, - odesolverstate* state, - ae_state *_state) -{ - - _odesolverstate_clear(state); - - ae_assert(n>=1, "ODESolverRKCK: N<1!", _state); - ae_assert(m>=1, "ODESolverRKCK: M<1!", _state); - ae_assert(y->cnt>=n, "ODESolverRKCK: Length(Y)cnt>=m, "ODESolverRKCK: Length(X)rstate.stage>=0 ) - { - n = state->rstate.ia.ptr.p_int[0]; - m = state->rstate.ia.ptr.p_int[1]; - i = state->rstate.ia.ptr.p_int[2]; - j = state->rstate.ia.ptr.p_int[3]; - k = state->rstate.ia.ptr.p_int[4]; - klimit = state->rstate.ia.ptr.p_int[5]; - gridpoint = state->rstate.ba.ptr.p_bool[0]; - xc = state->rstate.ra.ptr.p_double[0]; - v = state->rstate.ra.ptr.p_double[1]; - h = state->rstate.ra.ptr.p_double[2]; - h2 = state->rstate.ra.ptr.p_double[3]; - err = state->rstate.ra.ptr.p_double[4]; - maxgrowpow = state->rstate.ra.ptr.p_double[5]; - } - else - { - n = 359; - m = -58; - i = -919; - j = -909; - k = 81; - klimit = 255; - gridpoint = ae_false; - xc = -788; - v = 809; - h = 205; - h2 = -838; - err = 939; - maxgrowpow = -526; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - - /* - * Routine body - */ - - /* - * prepare - */ - if( state->repterminationtype!=0 ) - { - result = ae_false; - return result; - } - n = state->n; - m = state->m; - h = state->h; - maxgrowpow = ae_pow(odesolver_odesolvermaxgrow, (double)(5), _state); - state->repnfev = 0; - - /* - * some preliminary checks for internal errors - * after this we assume that H>0 and M>1 - */ - ae_assert(ae_fp_greater(state->h,(double)(0)), "ODESolver: internal error", _state); - ae_assert(m>1, "ODESolverIteration: internal error", _state); - - /* - * choose solver - */ - if( state->solvertype!=0 ) - { - goto lbl_1; - } - - /* - * Cask-Karp solver - * Prepare coefficients table. - * Check it for errors - */ - ae_vector_set_length(&state->rka, 6, _state); - state->rka.ptr.p_double[0] = (double)(0); - state->rka.ptr.p_double[1] = (double)1/(double)5; - state->rka.ptr.p_double[2] = (double)3/(double)10; - state->rka.ptr.p_double[3] = (double)3/(double)5; - state->rka.ptr.p_double[4] = (double)(1); - state->rka.ptr.p_double[5] = (double)7/(double)8; - ae_matrix_set_length(&state->rkb, 6, 5, _state); - state->rkb.ptr.pp_double[1][0] = (double)1/(double)5; - state->rkb.ptr.pp_double[2][0] = (double)3/(double)40; - state->rkb.ptr.pp_double[2][1] = (double)9/(double)40; - state->rkb.ptr.pp_double[3][0] = (double)3/(double)10; - state->rkb.ptr.pp_double[3][1] = -(double)9/(double)10; - state->rkb.ptr.pp_double[3][2] = (double)6/(double)5; - state->rkb.ptr.pp_double[4][0] = -(double)11/(double)54; - state->rkb.ptr.pp_double[4][1] = (double)5/(double)2; - state->rkb.ptr.pp_double[4][2] = -(double)70/(double)27; - state->rkb.ptr.pp_double[4][3] = (double)35/(double)27; - state->rkb.ptr.pp_double[5][0] = (double)1631/(double)55296; - state->rkb.ptr.pp_double[5][1] = (double)175/(double)512; - state->rkb.ptr.pp_double[5][2] = (double)575/(double)13824; - state->rkb.ptr.pp_double[5][3] = (double)44275/(double)110592; - state->rkb.ptr.pp_double[5][4] = (double)253/(double)4096; - ae_vector_set_length(&state->rkc, 6, _state); - state->rkc.ptr.p_double[0] = (double)37/(double)378; - state->rkc.ptr.p_double[1] = (double)(0); - state->rkc.ptr.p_double[2] = (double)250/(double)621; - state->rkc.ptr.p_double[3] = (double)125/(double)594; - state->rkc.ptr.p_double[4] = (double)(0); - state->rkc.ptr.p_double[5] = (double)512/(double)1771; - ae_vector_set_length(&state->rkcs, 6, _state); - state->rkcs.ptr.p_double[0] = (double)2825/(double)27648; - state->rkcs.ptr.p_double[1] = (double)(0); - state->rkcs.ptr.p_double[2] = (double)18575/(double)48384; - state->rkcs.ptr.p_double[3] = (double)13525/(double)55296; - state->rkcs.ptr.p_double[4] = (double)277/(double)14336; - state->rkcs.ptr.p_double[5] = (double)1/(double)4; - ae_matrix_set_length(&state->rkk, 6, n, _state); - - /* - * Main cycle consists of two iterations: - * * outer where we travel from X[i-1] to X[i] - * * inner where we travel inside [X[i-1],X[i]] - */ - ae_matrix_set_length(&state->ytbl, m, n, _state); - ae_vector_set_length(&state->escale, n, _state); - ae_vector_set_length(&state->yn, n, _state); - ae_vector_set_length(&state->yns, n, _state); - xc = state->xg.ptr.p_double[0]; - ae_v_move(&state->ytbl.ptr.pp_double[0][0], 1, &state->yc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(j=0; j<=n-1; j++) - { - state->escale.ptr.p_double[j] = (double)(0); - } - i = 1; -lbl_3: - if( i>m-1 ) - { - goto lbl_5; - } - - /* - * begin inner iteration - */ -lbl_6: - if( ae_false ) - { - goto lbl_7; - } - - /* - * truncate step if needed (beyond right boundary). - * determine should we store X or not - */ - if( ae_fp_greater_eq(xc+h,state->xg.ptr.p_double[i]) ) - { - h = state->xg.ptr.p_double[i]-xc; - gridpoint = ae_true; - } - else - { - gridpoint = ae_false; - } - - /* - * Update error scale maximums - * - * These maximums are initialized by zeros, - * then updated every iterations. - */ - for(j=0; j<=n-1; j++) - { - state->escale.ptr.p_double[j] = ae_maxreal(state->escale.ptr.p_double[j], ae_fabs(state->yc.ptr.p_double[j], _state), _state); - } - - /* - * make one step: - * 1. calculate all info needed to do step - * 2. update errors scale maximums using values/derivatives - * obtained during (1) - * - * Take into account that we use scaling of X to reduce task - * to the form where x[0] < x[1] < ... < x[n-1]. So X is - * replaced by x=xscale*t, and dy/dx=f(y,x) is replaced - * by dy/dt=xscale*f(y,xscale*t). - */ - ae_v_move(&state->yn.ptr.p_double[0], 1, &state->yc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->yns.ptr.p_double[0], 1, &state->yc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - k = 0; -lbl_8: - if( k>5 ) - { - goto lbl_10; - } - - /* - * prepare data for the next update of YN/YNS - */ - state->x = state->xscale*(xc+state->rka.ptr.p_double[k]*h); - ae_v_move(&state->y.ptr.p_double[0], 1, &state->yc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(j=0; j<=k-1; j++) - { - v = state->rkb.ptr.pp_double[k][j]; - ae_v_addd(&state->y.ptr.p_double[0], 1, &state->rkk.ptr.pp_double[j][0], 1, ae_v_len(0,n-1), v); - } - state->needdy = ae_true; - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - state->needdy = ae_false; - state->repnfev = state->repnfev+1; - v = h*state->xscale; - ae_v_moved(&state->rkk.ptr.pp_double[k][0], 1, &state->dy.ptr.p_double[0], 1, ae_v_len(0,n-1), v); - - /* - * update YN/YNS - */ - v = state->rkc.ptr.p_double[k]; - ae_v_addd(&state->yn.ptr.p_double[0], 1, &state->rkk.ptr.pp_double[k][0], 1, ae_v_len(0,n-1), v); - v = state->rkcs.ptr.p_double[k]; - ae_v_addd(&state->yns.ptr.p_double[0], 1, &state->rkk.ptr.pp_double[k][0], 1, ae_v_len(0,n-1), v); - k = k+1; - goto lbl_8; -lbl_10: - - /* - * estimate error - */ - err = (double)(0); - for(j=0; j<=n-1; j++) - { - if( !state->fraceps ) - { - - /* - * absolute error is estimated - */ - err = ae_maxreal(err, ae_fabs(state->yn.ptr.p_double[j]-state->yns.ptr.p_double[j], _state), _state); - } - else - { - - /* - * Relative error is estimated - */ - v = state->escale.ptr.p_double[j]; - if( ae_fp_eq(v,(double)(0)) ) - { - v = (double)(1); - } - err = ae_maxreal(err, ae_fabs(state->yn.ptr.p_double[j]-state->yns.ptr.p_double[j], _state)/v, _state); - } - } - - /* - * calculate new step, restart if necessary - */ - if( ae_fp_less_eq(maxgrowpow*err,state->eps) ) - { - h2 = odesolver_odesolvermaxgrow*h; - } - else - { - h2 = h*ae_pow(state->eps/err, 0.2, _state); - } - if( ae_fp_less(h2,h/odesolver_odesolvermaxshrink) ) - { - h2 = h/odesolver_odesolvermaxshrink; - } - if( ae_fp_greater(err,state->eps) ) - { - h = h2; - goto lbl_6; - } - - /* - * advance position - */ - xc = xc+h; - ae_v_move(&state->yc.ptr.p_double[0], 1, &state->yn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - - /* - * update H - */ - h = h2; - - /* - * break on grid point - */ - if( gridpoint ) - { - goto lbl_7; - } - goto lbl_6; -lbl_7: - - /* - * save result - */ - ae_v_move(&state->ytbl.ptr.pp_double[i][0], 1, &state->yc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - i = i+1; - goto lbl_3; -lbl_5: - state->repterminationtype = 1; - result = ae_false; - return result; -lbl_1: - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = n; - state->rstate.ia.ptr.p_int[1] = m; - state->rstate.ia.ptr.p_int[2] = i; - state->rstate.ia.ptr.p_int[3] = j; - state->rstate.ia.ptr.p_int[4] = k; - state->rstate.ia.ptr.p_int[5] = klimit; - state->rstate.ba.ptr.p_bool[0] = gridpoint; - state->rstate.ra.ptr.p_double[0] = xc; - state->rstate.ra.ptr.p_double[1] = v; - state->rstate.ra.ptr.p_double[2] = h; - state->rstate.ra.ptr.p_double[3] = h2; - state->rstate.ra.ptr.p_double[4] = err; - state->rstate.ra.ptr.p_double[5] = maxgrowpow; - return result; -} - - -/************************************************************************* -ODE solver results - -Called after OdeSolverIteration returned False. - -INPUT PARAMETERS: - State - algorithm state (used by OdeSolverIteration). - -OUTPUT PARAMETERS: - M - number of tabulated values, M>=1 - XTbl - array[0..M-1], values of X - YTbl - array[0..M-1,0..N-1], values of Y in X[i] - Rep - solver report: - * Rep.TerminationType completetion code: - * -2 X is not ordered by ascending/descending or - there are non-distinct X[], i.e. X[i]=X[i+1] - * -1 incorrect parameters were specified - * 1 task has been solved - * Rep.NFEV contains number of function calculations - - -- ALGLIB -- - Copyright 01.09.2009 by Bochkanov Sergey -*************************************************************************/ -void odesolverresults(odesolverstate* state, - ae_int_t* m, - /* Real */ ae_vector* xtbl, - /* Real */ ae_matrix* ytbl, - odesolverreport* rep, - ae_state *_state) -{ - double v; - ae_int_t i; - - *m = 0; - ae_vector_clear(xtbl); - ae_matrix_clear(ytbl); - _odesolverreport_clear(rep); - - rep->terminationtype = state->repterminationtype; - if( rep->terminationtype>0 ) - { - *m = state->m; - rep->nfev = state->repnfev; - ae_vector_set_length(xtbl, state->m, _state); - v = state->xscale; - ae_v_moved(&xtbl->ptr.p_double[0], 1, &state->xg.ptr.p_double[0], 1, ae_v_len(0,state->m-1), v); - ae_matrix_set_length(ytbl, state->m, state->n, _state); - for(i=0; i<=state->m-1; i++) - { - ae_v_move(&ytbl->ptr.pp_double[i][0], 1, &state->ytbl.ptr.pp_double[i][0], 1, ae_v_len(0,state->n-1)); - } - } - else - { - rep->nfev = 0; - } -} - - -/************************************************************************* -Internal initialization subroutine -*************************************************************************/ -static void odesolver_odesolverinit(ae_int_t solvertype, - /* Real */ ae_vector* y, - ae_int_t n, - /* Real */ ae_vector* x, - ae_int_t m, - double eps, - double h, - odesolverstate* state, - ae_state *_state) -{ - ae_int_t i; - double v; - - _odesolverstate_clear(state); - - - /* - * Prepare RComm - */ - ae_vector_set_length(&state->rstate.ia, 5+1, _state); - ae_vector_set_length(&state->rstate.ba, 0+1, _state); - ae_vector_set_length(&state->rstate.ra, 5+1, _state); - state->rstate.stage = -1; - state->needdy = ae_false; - - /* - * check parameters. - */ - if( (n<=0||m<1)||ae_fp_eq(eps,(double)(0)) ) - { - state->repterminationtype = -1; - return; - } - if( ae_fp_less(h,(double)(0)) ) - { - h = -h; - } - - /* - * quick exit if necessary. - * after this block we assume that M>1 - */ - if( m==1 ) - { - state->repnfev = 0; - state->repterminationtype = 1; - ae_matrix_set_length(&state->ytbl, 1, n, _state); - ae_v_move(&state->ytbl.ptr.pp_double[0][0], 1, &y->ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_vector_set_length(&state->xg, m, _state); - ae_v_move(&state->xg.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,m-1)); - return; - } - - /* - * check again: correct order of X[] - */ - if( ae_fp_eq(x->ptr.p_double[1],x->ptr.p_double[0]) ) - { - state->repterminationtype = -2; - return; - } - for(i=1; i<=m-1; i++) - { - if( (ae_fp_greater(x->ptr.p_double[1],x->ptr.p_double[0])&&ae_fp_less_eq(x->ptr.p_double[i],x->ptr.p_double[i-1]))||(ae_fp_less(x->ptr.p_double[1],x->ptr.p_double[0])&&ae_fp_greater_eq(x->ptr.p_double[i],x->ptr.p_double[i-1])) ) - { - state->repterminationtype = -2; - return; - } - } - - /* - * auto-select H if necessary - */ - if( ae_fp_eq(h,(double)(0)) ) - { - v = ae_fabs(x->ptr.p_double[1]-x->ptr.p_double[0], _state); - for(i=2; i<=m-1; i++) - { - v = ae_minreal(v, ae_fabs(x->ptr.p_double[i]-x->ptr.p_double[i-1], _state), _state); - } - h = 0.001*v; - } - - /* - * store parameters - */ - state->n = n; - state->m = m; - state->h = h; - state->eps = ae_fabs(eps, _state); - state->fraceps = ae_fp_less(eps,(double)(0)); - ae_vector_set_length(&state->xg, m, _state); - ae_v_move(&state->xg.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,m-1)); - if( ae_fp_greater(x->ptr.p_double[1],x->ptr.p_double[0]) ) - { - state->xscale = (double)(1); - } - else - { - state->xscale = (double)(-1); - ae_v_muld(&state->xg.ptr.p_double[0], 1, ae_v_len(0,m-1), -1); - } - ae_vector_set_length(&state->yc, n, _state); - ae_v_move(&state->yc.ptr.p_double[0], 1, &y->ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->solvertype = solvertype; - state->repterminationtype = 0; - - /* - * Allocate arrays - */ - ae_vector_set_length(&state->y, n, _state); - ae_vector_set_length(&state->dy, n, _state); -} - - -void _odesolverstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - odesolverstate *p = (odesolverstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->yc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->escale, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xg, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dy, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->ytbl, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->yn, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->yns, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rka, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rkc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rkcs, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->rkb, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->rkk, 0, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); -} - - -void _odesolverstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - odesolverstate *dst = (odesolverstate*)_dst; - odesolverstate *src = (odesolverstate*)_src; - dst->n = src->n; - dst->m = src->m; - dst->xscale = src->xscale; - dst->h = src->h; - dst->eps = src->eps; - dst->fraceps = src->fraceps; - ae_vector_init_copy(&dst->yc, &src->yc, _state, make_automatic); - ae_vector_init_copy(&dst->escale, &src->escale, _state, make_automatic); - ae_vector_init_copy(&dst->xg, &src->xg, _state, make_automatic); - dst->solvertype = src->solvertype; - dst->needdy = src->needdy; - dst->x = src->x; - ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic); - ae_vector_init_copy(&dst->dy, &src->dy, _state, make_automatic); - ae_matrix_init_copy(&dst->ytbl, &src->ytbl, _state, make_automatic); - dst->repterminationtype = src->repterminationtype; - dst->repnfev = src->repnfev; - ae_vector_init_copy(&dst->yn, &src->yn, _state, make_automatic); - ae_vector_init_copy(&dst->yns, &src->yns, _state, make_automatic); - ae_vector_init_copy(&dst->rka, &src->rka, _state, make_automatic); - ae_vector_init_copy(&dst->rkc, &src->rkc, _state, make_automatic); - ae_vector_init_copy(&dst->rkcs, &src->rkcs, _state, make_automatic); - ae_matrix_init_copy(&dst->rkb, &src->rkb, _state, make_automatic); - ae_matrix_init_copy(&dst->rkk, &src->rkk, _state, make_automatic); - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); -} - - -void _odesolverstate_clear(void* _p) -{ - odesolverstate *p = (odesolverstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->yc); - ae_vector_clear(&p->escale); - ae_vector_clear(&p->xg); - ae_vector_clear(&p->y); - ae_vector_clear(&p->dy); - ae_matrix_clear(&p->ytbl); - ae_vector_clear(&p->yn); - ae_vector_clear(&p->yns); - ae_vector_clear(&p->rka); - ae_vector_clear(&p->rkc); - ae_vector_clear(&p->rkcs); - ae_matrix_clear(&p->rkb); - ae_matrix_clear(&p->rkk); - _rcommstate_clear(&p->rstate); -} - - -void _odesolverstate_destroy(void* _p) -{ - odesolverstate *p = (odesolverstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->yc); - ae_vector_destroy(&p->escale); - ae_vector_destroy(&p->xg); - ae_vector_destroy(&p->y); - ae_vector_destroy(&p->dy); - ae_matrix_destroy(&p->ytbl); - ae_vector_destroy(&p->yn); - ae_vector_destroy(&p->yns); - ae_vector_destroy(&p->rka); - ae_vector_destroy(&p->rkc); - ae_vector_destroy(&p->rkcs); - ae_matrix_destroy(&p->rkb); - ae_matrix_destroy(&p->rkk); - _rcommstate_destroy(&p->rstate); -} - - -void _odesolverreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - odesolverreport *p = (odesolverreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _odesolverreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - odesolverreport *dst = (odesolverreport*)_dst; - odesolverreport *src = (odesolverreport*)_src; - dst->nfev = src->nfev; - dst->terminationtype = src->terminationtype; -} - - -void _odesolverreport_clear(void* _p) -{ - odesolverreport *p = (odesolverreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _odesolverreport_destroy(void* _p) -{ - odesolverreport *p = (odesolverreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif - -} - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/diffequations.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/diffequations.h deleted file mode 100644 index b5ba925..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/diffequations.h +++ /dev/null @@ -1,276 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifndef _diffequations_pkg_h -#define _diffequations_pkg_h -#include "ap.h" -#include "alglibinternal.h" - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (DATATYPES) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_ODESOLVER) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t n; - ae_int_t m; - double xscale; - double h; - double eps; - ae_bool fraceps; - ae_vector yc; - ae_vector escale; - ae_vector xg; - ae_int_t solvertype; - ae_bool needdy; - double x; - ae_vector y; - ae_vector dy; - ae_matrix ytbl; - ae_int_t repterminationtype; - ae_int_t repnfev; - ae_vector yn; - ae_vector yns; - ae_vector rka; - ae_vector rkc; - ae_vector rkcs; - ae_matrix rkb; - ae_matrix rkk; - rcommstate rstate; -} odesolverstate; -typedef struct -{ - ae_int_t nfev; - ae_int_t terminationtype; -} odesolverreport; -#endif - -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_ODESOLVER) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - -*************************************************************************/ -class _odesolverstate_owner -{ -public: - _odesolverstate_owner(); - _odesolverstate_owner(const _odesolverstate_owner &rhs); - _odesolverstate_owner& operator=(const _odesolverstate_owner &rhs); - virtual ~_odesolverstate_owner(); - alglib_impl::odesolverstate* c_ptr(); - alglib_impl::odesolverstate* c_ptr() const; -protected: - alglib_impl::odesolverstate *p_struct; -}; -class odesolverstate : public _odesolverstate_owner -{ -public: - odesolverstate(); - odesolverstate(const odesolverstate &rhs); - odesolverstate& operator=(const odesolverstate &rhs); - virtual ~odesolverstate(); - ae_bool &needdy; - real_1d_array y; - real_1d_array dy; - double &x; - -}; - - -/************************************************************************* - -*************************************************************************/ -class _odesolverreport_owner -{ -public: - _odesolverreport_owner(); - _odesolverreport_owner(const _odesolverreport_owner &rhs); - _odesolverreport_owner& operator=(const _odesolverreport_owner &rhs); - virtual ~_odesolverreport_owner(); - alglib_impl::odesolverreport* c_ptr(); - alglib_impl::odesolverreport* c_ptr() const; -protected: - alglib_impl::odesolverreport *p_struct; -}; -class odesolverreport : public _odesolverreport_owner -{ -public: - odesolverreport(); - odesolverreport(const odesolverreport &rhs); - odesolverreport& operator=(const odesolverreport &rhs); - virtual ~odesolverreport(); - ae_int_t &nfev; - ae_int_t &terminationtype; - -}; -#endif - -#if defined(AE_COMPILE_ODESOLVER) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Cash-Karp adaptive ODE solver. - -This subroutine solves ODE Y'=f(Y,x) with initial conditions Y(xs)=Ys -(here Y may be single variable or vector of N variables). - -INPUT PARAMETERS: - Y - initial conditions, array[0..N-1]. - contains values of Y[] at X[0] - N - system size - X - points at which Y should be tabulated, array[0..M-1] - integrations starts at X[0], ends at X[M-1], intermediate - values at X[i] are returned too. - SHOULD BE ORDERED BY ASCENDING OR BY DESCENDING! - M - number of intermediate points + first point + last point: - * M>2 means that you need both Y(X[M-1]) and M-2 values at - intermediate points - * M=2 means that you want just to integrate from X[0] to - X[1] and don't interested in intermediate values. - * M=1 means that you don't want to integrate :) - it is degenerate case, but it will be handled correctly. - * M<1 means error - Eps - tolerance (absolute/relative error on each step will be - less than Eps). When passing: - * Eps>0, it means desired ABSOLUTE error - * Eps<0, it means desired RELATIVE error. Relative errors - are calculated with respect to maximum values of Y seen - so far. Be careful to use this criterion when starting - from Y[] that are close to zero. - H - initial step lenth, it will be adjusted automatically - after the first step. If H=0, step will be selected - automatically (usualy it will be equal to 0.001 of - min(x[i]-x[j])). - -OUTPUT PARAMETERS - State - structure which stores algorithm state between subsequent - calls of OdeSolverIteration. Used for reverse communication. - This structure should be passed to the OdeSolverIteration - subroutine. - -SEE ALSO - AutoGKSmoothW, AutoGKSingular, AutoGKIteration, AutoGKResults. - - - -- ALGLIB -- - Copyright 01.09.2009 by Bochkanov Sergey -*************************************************************************/ -void odesolverrkck(const real_1d_array &y, const ae_int_t n, const real_1d_array &x, const ae_int_t m, const double eps, const double h, odesolverstate &state, const xparams _xparams = alglib::xdefault); -void odesolverrkck(const real_1d_array &y, const real_1d_array &x, const double eps, const double h, odesolverstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool odesolveriteration(const odesolverstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is used to launcn iterations of ODE solver - -It accepts following parameters: - diff - callback which calculates dy/dx for given y and x - ptr - optional pointer which is passed to diff; can be NULL - - - -- ALGLIB -- - Copyright 01.09.2009 by Bochkanov Sergey - -*************************************************************************/ -void odesolversolve(odesolverstate &state, - void (*diff)(const real_1d_array &y, double x, real_1d_array &dy, void *ptr), - void *ptr = NULL, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -ODE solver results - -Called after OdeSolverIteration returned False. - -INPUT PARAMETERS: - State - algorithm state (used by OdeSolverIteration). - -OUTPUT PARAMETERS: - M - number of tabulated values, M>=1 - XTbl - array[0..M-1], values of X - YTbl - array[0..M-1,0..N-1], values of Y in X[i] - Rep - solver report: - * Rep.TerminationType completetion code: - * -2 X is not ordered by ascending/descending or - there are non-distinct X[], i.e. X[i]=X[i+1] - * -1 incorrect parameters were specified - * 1 task has been solved - * Rep.NFEV contains number of function calculations - - -- ALGLIB -- - Copyright 01.09.2009 by Bochkanov Sergey -*************************************************************************/ -void odesolverresults(const odesolverstate &state, ae_int_t &m, real_1d_array &xtbl, real_2d_array &ytbl, odesolverreport &rep, const xparams _xparams = alglib::xdefault); -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (FUNCTIONS) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_ODESOLVER) || !defined(AE_PARTIAL_BUILD) -void odesolverrkck(/* Real */ ae_vector* y, - ae_int_t n, - /* Real */ ae_vector* x, - ae_int_t m, - double eps, - double h, - odesolverstate* state, - ae_state *_state); -ae_bool odesolveriteration(odesolverstate* state, ae_state *_state); -void odesolverresults(odesolverstate* state, - ae_int_t* m, - /* Real */ ae_vector* xtbl, - /* Real */ ae_matrix* ytbl, - odesolverreport* rep, - ae_state *_state); -void _odesolverstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _odesolverstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _odesolverstate_clear(void* _p); -void _odesolverstate_destroy(void* _p); -void _odesolverreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _odesolverreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _odesolverreport_clear(void* _p); -void _odesolverreport_destroy(void* _p); -#endif - -} -#endif - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/fasttransforms.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/fasttransforms.cpp deleted file mode 100644 index 447a7e3..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/fasttransforms.cpp +++ /dev/null @@ -1,3751 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifdef _MSC_VER -#define _CRT_SECURE_NO_WARNINGS -#endif -#include "stdafx.h" -#include "fasttransforms.h" - -// disable some irrelevant warnings -#if (AE_COMPILER==AE_MSVC) && !defined(AE_ALL_WARNINGS) -#pragma warning(disable:4100) -#pragma warning(disable:4127) -#pragma warning(disable:4611) -#pragma warning(disable:4702) -#pragma warning(disable:4996) -#endif - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_FFT) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_FHT) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_CONV) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_CORR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_FFT) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -1-dimensional complex FFT. - -Array size N may be arbitrary number (composite or prime). Composite N's -are handled with cache-oblivious variation of a Cooley-Tukey algorithm. -Small prime-factors are transformed using hard coded codelets (similar to -FFTW codelets, but without low-level optimization), large prime-factors -are handled with Bluestein's algorithm. - -Fastests transforms are for smooth N's (prime factors are 2, 3, 5 only), -most fast for powers of 2. When N have prime factors larger than these, -but orders of magnitude smaller than N, computations will be about 4 times -slower than for nearby highly composite N's. When N itself is prime, speed -will be 6 times lower. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - A - array[0..N-1] - complex function to be transformed - N - problem size - -OUTPUT PARAMETERS - A - DFT of a input array, array[0..N-1] - A_out[j] = SUM(A_in[k]*exp(-2*pi*sqrt(-1)*j*k/N), k = 0..N-1) - - - -- ALGLIB -- - Copyright 29.05.2009 by Bochkanov Sergey -*************************************************************************/ -void fftc1d(complex_1d_array &a, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::fftc1d(const_cast(a.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -1-dimensional complex FFT. - -Array size N may be arbitrary number (composite or prime). Composite N's -are handled with cache-oblivious variation of a Cooley-Tukey algorithm. -Small prime-factors are transformed using hard coded codelets (similar to -FFTW codelets, but without low-level optimization), large prime-factors -are handled with Bluestein's algorithm. - -Fastests transforms are for smooth N's (prime factors are 2, 3, 5 only), -most fast for powers of 2. When N have prime factors larger than these, -but orders of magnitude smaller than N, computations will be about 4 times -slower than for nearby highly composite N's. When N itself is prime, speed -will be 6 times lower. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - A - array[0..N-1] - complex function to be transformed - N - problem size - -OUTPUT PARAMETERS - A - DFT of a input array, array[0..N-1] - A_out[j] = SUM(A_in[k]*exp(-2*pi*sqrt(-1)*j*k/N), k = 0..N-1) - - - -- ALGLIB -- - Copyright 29.05.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void fftc1d(complex_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = a.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::fftc1d(const_cast(a.c_ptr()), n, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -1-dimensional complex inverse FFT. - -Array size N may be arbitrary number (composite or prime). Algorithm has -O(N*logN) complexity for any N (composite or prime). - -See FFTC1D() description for more information about algorithm performance. - -INPUT PARAMETERS - A - array[0..N-1] - complex array to be transformed - N - problem size - -OUTPUT PARAMETERS - A - inverse DFT of a input array, array[0..N-1] - A_out[j] = SUM(A_in[k]/N*exp(+2*pi*sqrt(-1)*j*k/N), k = 0..N-1) - - - -- ALGLIB -- - Copyright 29.05.2009 by Bochkanov Sergey -*************************************************************************/ -void fftc1dinv(complex_1d_array &a, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::fftc1dinv(const_cast(a.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -1-dimensional complex inverse FFT. - -Array size N may be arbitrary number (composite or prime). Algorithm has -O(N*logN) complexity for any N (composite or prime). - -See FFTC1D() description for more information about algorithm performance. - -INPUT PARAMETERS - A - array[0..N-1] - complex array to be transformed - N - problem size - -OUTPUT PARAMETERS - A - inverse DFT of a input array, array[0..N-1] - A_out[j] = SUM(A_in[k]/N*exp(+2*pi*sqrt(-1)*j*k/N), k = 0..N-1) - - - -- ALGLIB -- - Copyright 29.05.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void fftc1dinv(complex_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = a.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::fftc1dinv(const_cast(a.c_ptr()), n, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -1-dimensional real FFT. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - A - array[0..N-1] - real function to be transformed - N - problem size - -OUTPUT PARAMETERS - F - DFT of a input array, array[0..N-1] - F[j] = SUM(A[k]*exp(-2*pi*sqrt(-1)*j*k/N), k = 0..N-1) - -NOTE: - F[] satisfies symmetry property F[k] = conj(F[N-k]), so just one half -of array is usually needed. But for convinience subroutine returns full -complex array (with frequencies above N/2), so its result may be used by -other FFT-related subroutines. - - - -- ALGLIB -- - Copyright 01.06.2009 by Bochkanov Sergey -*************************************************************************/ -void fftr1d(const real_1d_array &a, const ae_int_t n, complex_1d_array &f, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::fftr1d(const_cast(a.c_ptr()), n, const_cast(f.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -1-dimensional real FFT. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - A - array[0..N-1] - real function to be transformed - N - problem size - -OUTPUT PARAMETERS - F - DFT of a input array, array[0..N-1] - F[j] = SUM(A[k]*exp(-2*pi*sqrt(-1)*j*k/N), k = 0..N-1) - -NOTE: - F[] satisfies symmetry property F[k] = conj(F[N-k]), so just one half -of array is usually needed. But for convinience subroutine returns full -complex array (with frequencies above N/2), so its result may be used by -other FFT-related subroutines. - - - -- ALGLIB -- - Copyright 01.06.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void fftr1d(const real_1d_array &a, complex_1d_array &f, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = a.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::fftr1d(const_cast(a.c_ptr()), n, const_cast(f.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -1-dimensional real inverse FFT. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - F - array[0..floor(N/2)] - frequencies from forward real FFT - N - problem size - -OUTPUT PARAMETERS - A - inverse DFT of a input array, array[0..N-1] - -NOTE: - F[] should satisfy symmetry property F[k] = conj(F[N-k]), so just one -half of frequencies array is needed - elements from 0 to floor(N/2). F[0] -is ALWAYS real. If N is even F[floor(N/2)] is real too. If N is odd, then -F[floor(N/2)] has no special properties. - -Relying on properties noted above, FFTR1DInv subroutine uses only elements -from 0th to floor(N/2)-th. It ignores imaginary part of F[0], and in case -N is even it ignores imaginary part of F[floor(N/2)] too. - -When you call this function using full arguments list - "FFTR1DInv(F,N,A)" -- you can pass either either frequencies array with N elements or reduced -array with roughly N/2 elements - subroutine will successfully transform -both. - -If you call this function using reduced arguments list - "FFTR1DInv(F,A)" -- you must pass FULL array with N elements (although higher N/2 are still -not used) because array size is used to automatically determine FFT length - - - -- ALGLIB -- - Copyright 01.06.2009 by Bochkanov Sergey -*************************************************************************/ -void fftr1dinv(const complex_1d_array &f, const ae_int_t n, real_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::fftr1dinv(const_cast(f.c_ptr()), n, const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -1-dimensional real inverse FFT. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - F - array[0..floor(N/2)] - frequencies from forward real FFT - N - problem size - -OUTPUT PARAMETERS - A - inverse DFT of a input array, array[0..N-1] - -NOTE: - F[] should satisfy symmetry property F[k] = conj(F[N-k]), so just one -half of frequencies array is needed - elements from 0 to floor(N/2). F[0] -is ALWAYS real. If N is even F[floor(N/2)] is real too. If N is odd, then -F[floor(N/2)] has no special properties. - -Relying on properties noted above, FFTR1DInv subroutine uses only elements -from 0th to floor(N/2)-th. It ignores imaginary part of F[0], and in case -N is even it ignores imaginary part of F[floor(N/2)] too. - -When you call this function using full arguments list - "FFTR1DInv(F,N,A)" -- you can pass either either frequencies array with N elements or reduced -array with roughly N/2 elements - subroutine will successfully transform -both. - -If you call this function using reduced arguments list - "FFTR1DInv(F,A)" -- you must pass FULL array with N elements (although higher N/2 are still -not used) because array size is used to automatically determine FFT length - - - -- ALGLIB -- - Copyright 01.06.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void fftr1dinv(const complex_1d_array &f, real_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = f.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::fftr1dinv(const_cast(f.c_ptr()), n, const_cast(a.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif -#endif - -#if defined(AE_COMPILE_FHT) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -1-dimensional Fast Hartley Transform. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - A - array[0..N-1] - real function to be transformed - N - problem size - -OUTPUT PARAMETERS - A - FHT of a input array, array[0..N-1], - A_out[k] = sum(A_in[j]*(cos(2*pi*j*k/N)+sin(2*pi*j*k/N)), j=0..N-1) - - - -- ALGLIB -- - Copyright 04.06.2009 by Bochkanov Sergey -*************************************************************************/ -void fhtr1d(real_1d_array &a, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::fhtr1d(const_cast(a.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -1-dimensional inverse FHT. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - A - array[0..N-1] - complex array to be transformed - N - problem size - -OUTPUT PARAMETERS - A - inverse FHT of a input array, array[0..N-1] - - - -- ALGLIB -- - Copyright 29.05.2009 by Bochkanov Sergey -*************************************************************************/ -void fhtr1dinv(real_1d_array &a, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::fhtr1dinv(const_cast(a.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_CONV) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -1-dimensional complex convolution. - -For given A/B returns conv(A,B) (non-circular). Subroutine can automatically -choose between three implementations: straightforward O(M*N) formula for -very small N (or M), overlap-add algorithm for cases where max(M,N) is -significantly larger than min(M,N), but O(M*N) algorithm is too slow, and -general FFT-based formula for cases where two previois algorithms are too -slow. - -Algorithm has max(M,N)*log(max(M,N)) complexity for any M/N. - -INPUT PARAMETERS - A - array[0..M-1] - complex function to be transformed - M - problem size - B - array[0..N-1] - complex function to be transformed - N - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..N+M-2]. - -NOTE: - It is assumed that A is zero at T<0, B is zero too. If one or both -functions have non-zero values at negative T's, you can still use this -subroutine - just shift its result correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convc1d(const complex_1d_array &a, const ae_int_t m, const complex_1d_array &b, const ae_int_t n, complex_1d_array &r, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::convc1d(const_cast(a.c_ptr()), m, const_cast(b.c_ptr()), n, const_cast(r.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -1-dimensional complex non-circular deconvolution (inverse of ConvC1D()). - -Algorithm has M*log(M)) complexity for any M (composite or prime). - -INPUT PARAMETERS - A - array[0..M-1] - convolved signal, A = conv(R, B) - M - convolved signal length - B - array[0..N-1] - response - N - response length, N<=M - -OUTPUT PARAMETERS - R - deconvolved signal. array[0..M-N]. - -NOTE: - deconvolution is unstable process and may result in division by zero -(if your response function is degenerate, i.e. has zero Fourier coefficient). - -NOTE: - It is assumed that A is zero at T<0, B is zero too. If one or both -functions have non-zero values at negative T's, you can still use this -subroutine - just shift its result correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convc1dinv(const complex_1d_array &a, const ae_int_t m, const complex_1d_array &b, const ae_int_t n, complex_1d_array &r, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::convc1dinv(const_cast(a.c_ptr()), m, const_cast(b.c_ptr()), n, const_cast(r.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -1-dimensional circular complex convolution. - -For given S/R returns conv(S,R) (circular). Algorithm has linearithmic -complexity for any M/N. - -IMPORTANT: normal convolution is commutative, i.e. it is symmetric - -conv(A,B)=conv(B,A). Cyclic convolution IS NOT. One function - S - is a -signal, periodic function, and another - R - is a response, non-periodic -function with limited length. - -INPUT PARAMETERS - S - array[0..M-1] - complex periodic signal - M - problem size - B - array[0..N-1] - complex non-periodic response - N - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..M-1]. - -NOTE: - It is assumed that B is zero at T<0. If it has non-zero values at -negative T's, you can still use this subroutine - just shift its result -correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convc1dcircular(const complex_1d_array &s, const ae_int_t m, const complex_1d_array &r, const ae_int_t n, complex_1d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::convc1dcircular(const_cast(s.c_ptr()), m, const_cast(r.c_ptr()), n, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -1-dimensional circular complex deconvolution (inverse of ConvC1DCircular()). - -Algorithm has M*log(M)) complexity for any M (composite or prime). - -INPUT PARAMETERS - A - array[0..M-1] - convolved periodic signal, A = conv(R, B) - M - convolved signal length - B - array[0..N-1] - non-periodic response - N - response length - -OUTPUT PARAMETERS - R - deconvolved signal. array[0..M-1]. - -NOTE: - deconvolution is unstable process and may result in division by zero -(if your response function is degenerate, i.e. has zero Fourier coefficient). - -NOTE: - It is assumed that B is zero at T<0. If it has non-zero values at -negative T's, you can still use this subroutine - just shift its result -correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convc1dcircularinv(const complex_1d_array &a, const ae_int_t m, const complex_1d_array &b, const ae_int_t n, complex_1d_array &r, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::convc1dcircularinv(const_cast(a.c_ptr()), m, const_cast(b.c_ptr()), n, const_cast(r.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -1-dimensional real convolution. - -Analogous to ConvC1D(), see ConvC1D() comments for more details. - -INPUT PARAMETERS - A - array[0..M-1] - real function to be transformed - M - problem size - B - array[0..N-1] - real function to be transformed - N - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..N+M-2]. - -NOTE: - It is assumed that A is zero at T<0, B is zero too. If one or both -functions have non-zero values at negative T's, you can still use this -subroutine - just shift its result correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convr1d(const real_1d_array &a, const ae_int_t m, const real_1d_array &b, const ae_int_t n, real_1d_array &r, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::convr1d(const_cast(a.c_ptr()), m, const_cast(b.c_ptr()), n, const_cast(r.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -1-dimensional real deconvolution (inverse of ConvC1D()). - -Algorithm has M*log(M)) complexity for any M (composite or prime). - -INPUT PARAMETERS - A - array[0..M-1] - convolved signal, A = conv(R, B) - M - convolved signal length - B - array[0..N-1] - response - N - response length, N<=M - -OUTPUT PARAMETERS - R - deconvolved signal. array[0..M-N]. - -NOTE: - deconvolution is unstable process and may result in division by zero -(if your response function is degenerate, i.e. has zero Fourier coefficient). - -NOTE: - It is assumed that A is zero at T<0, B is zero too. If one or both -functions have non-zero values at negative T's, you can still use this -subroutine - just shift its result correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convr1dinv(const real_1d_array &a, const ae_int_t m, const real_1d_array &b, const ae_int_t n, real_1d_array &r, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::convr1dinv(const_cast(a.c_ptr()), m, const_cast(b.c_ptr()), n, const_cast(r.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -1-dimensional circular real convolution. - -Analogous to ConvC1DCircular(), see ConvC1DCircular() comments for more details. - -INPUT PARAMETERS - S - array[0..M-1] - real signal - M - problem size - B - array[0..N-1] - real response - N - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..M-1]. - -NOTE: - It is assumed that B is zero at T<0. If it has non-zero values at -negative T's, you can still use this subroutine - just shift its result -correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convr1dcircular(const real_1d_array &s, const ae_int_t m, const real_1d_array &r, const ae_int_t n, real_1d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::convr1dcircular(const_cast(s.c_ptr()), m, const_cast(r.c_ptr()), n, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -1-dimensional complex deconvolution (inverse of ConvC1D()). - -Algorithm has M*log(M)) complexity for any M (composite or prime). - -INPUT PARAMETERS - A - array[0..M-1] - convolved signal, A = conv(R, B) - M - convolved signal length - B - array[0..N-1] - response - N - response length - -OUTPUT PARAMETERS - R - deconvolved signal. array[0..M-N]. - -NOTE: - deconvolution is unstable process and may result in division by zero -(if your response function is degenerate, i.e. has zero Fourier coefficient). - -NOTE: - It is assumed that B is zero at T<0. If it has non-zero values at -negative T's, you can still use this subroutine - just shift its result -correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convr1dcircularinv(const real_1d_array &a, const ae_int_t m, const real_1d_array &b, const ae_int_t n, real_1d_array &r, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::convr1dcircularinv(const_cast(a.c_ptr()), m, const_cast(b.c_ptr()), n, const_cast(r.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_CORR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -1-dimensional complex cross-correlation. - -For given Pattern/Signal returns corr(Pattern,Signal) (non-circular). - -Correlation is calculated using reduction to convolution. Algorithm with -max(N,N)*log(max(N,N)) complexity is used (see ConvC1D() for more info -about performance). - -IMPORTANT: - for historical reasons subroutine accepts its parameters in reversed - order: CorrC1D(Signal, Pattern) = Pattern x Signal (using traditional - definition of cross-correlation, denoting cross-correlation as "x"). - -INPUT PARAMETERS - Signal - array[0..N-1] - complex function to be transformed, - signal containing pattern - N - problem size - Pattern - array[0..M-1] - complex function to be transformed, - pattern to search withing signal - M - problem size - -OUTPUT PARAMETERS - R - cross-correlation, array[0..N+M-2]: - * positive lags are stored in R[0..N-1], - R[i] = sum(conj(pattern[j])*signal[i+j] - * negative lags are stored in R[N..N+M-2], - R[N+M-1-i] = sum(conj(pattern[j])*signal[-i+j] - -NOTE: - It is assumed that pattern domain is [0..M-1]. If Pattern is non-zero -on [-K..M-1], you can still use this subroutine, just shift result by K. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void corrc1d(const complex_1d_array &signal, const ae_int_t n, const complex_1d_array &pattern, const ae_int_t m, complex_1d_array &r, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::corrc1d(const_cast(signal.c_ptr()), n, const_cast(pattern.c_ptr()), m, const_cast(r.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -1-dimensional circular complex cross-correlation. - -For given Pattern/Signal returns corr(Pattern,Signal) (circular). -Algorithm has linearithmic complexity for any M/N. - -IMPORTANT: - for historical reasons subroutine accepts its parameters in reversed - order: CorrC1DCircular(Signal, Pattern) = Pattern x Signal (using - traditional definition of cross-correlation, denoting cross-correlation - as "x"). - -INPUT PARAMETERS - Signal - array[0..N-1] - complex function to be transformed, - periodic signal containing pattern - N - problem size - Pattern - array[0..M-1] - complex function to be transformed, - non-periodic pattern to search withing signal - M - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..M-1]. - - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void corrc1dcircular(const complex_1d_array &signal, const ae_int_t m, const complex_1d_array &pattern, const ae_int_t n, complex_1d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::corrc1dcircular(const_cast(signal.c_ptr()), m, const_cast(pattern.c_ptr()), n, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -1-dimensional real cross-correlation. - -For given Pattern/Signal returns corr(Pattern,Signal) (non-circular). - -Correlation is calculated using reduction to convolution. Algorithm with -max(N,N)*log(max(N,N)) complexity is used (see ConvC1D() for more info -about performance). - -IMPORTANT: - for historical reasons subroutine accepts its parameters in reversed - order: CorrR1D(Signal, Pattern) = Pattern x Signal (using traditional - definition of cross-correlation, denoting cross-correlation as "x"). - -INPUT PARAMETERS - Signal - array[0..N-1] - real function to be transformed, - signal containing pattern - N - problem size - Pattern - array[0..M-1] - real function to be transformed, - pattern to search withing signal - M - problem size - -OUTPUT PARAMETERS - R - cross-correlation, array[0..N+M-2]: - * positive lags are stored in R[0..N-1], - R[i] = sum(pattern[j]*signal[i+j] - * negative lags are stored in R[N..N+M-2], - R[N+M-1-i] = sum(pattern[j]*signal[-i+j] - -NOTE: - It is assumed that pattern domain is [0..M-1]. If Pattern is non-zero -on [-K..M-1], you can still use this subroutine, just shift result by K. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void corrr1d(const real_1d_array &signal, const ae_int_t n, const real_1d_array &pattern, const ae_int_t m, real_1d_array &r, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::corrr1d(const_cast(signal.c_ptr()), n, const_cast(pattern.c_ptr()), m, const_cast(r.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -1-dimensional circular real cross-correlation. - -For given Pattern/Signal returns corr(Pattern,Signal) (circular). -Algorithm has linearithmic complexity for any M/N. - -IMPORTANT: - for historical reasons subroutine accepts its parameters in reversed - order: CorrR1DCircular(Signal, Pattern) = Pattern x Signal (using - traditional definition of cross-correlation, denoting cross-correlation - as "x"). - -INPUT PARAMETERS - Signal - array[0..N-1] - real function to be transformed, - periodic signal containing pattern - N - problem size - Pattern - array[0..M-1] - real function to be transformed, - non-periodic pattern to search withing signal - M - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..M-1]. - - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void corrr1dcircular(const real_1d_array &signal, const ae_int_t m, const real_1d_array &pattern, const ae_int_t n, real_1d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::corrr1dcircular(const_cast(signal.c_ptr()), m, const_cast(pattern.c_ptr()), n, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF COMPUTATIONAL CORE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_FFT) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_FHT) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_CONV) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_CORR) || !defined(AE_PARTIAL_BUILD) - - -#endif - -#if defined(AE_COMPILE_FFT) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -1-dimensional complex FFT. - -Array size N may be arbitrary number (composite or prime). Composite N's -are handled with cache-oblivious variation of a Cooley-Tukey algorithm. -Small prime-factors are transformed using hard coded codelets (similar to -FFTW codelets, but without low-level optimization), large prime-factors -are handled with Bluestein's algorithm. - -Fastests transforms are for smooth N's (prime factors are 2, 3, 5 only), -most fast for powers of 2. When N have prime factors larger than these, -but orders of magnitude smaller than N, computations will be about 4 times -slower than for nearby highly composite N's. When N itself is prime, speed -will be 6 times lower. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - A - array[0..N-1] - complex function to be transformed - N - problem size - -OUTPUT PARAMETERS - A - DFT of a input array, array[0..N-1] - A_out[j] = SUM(A_in[k]*exp(-2*pi*sqrt(-1)*j*k/N), k = 0..N-1) - - - -- ALGLIB -- - Copyright 29.05.2009 by Bochkanov Sergey -*************************************************************************/ -void fftc1d(/* Complex */ ae_vector* a, ae_int_t n, ae_state *_state) -{ - ae_frame _frame_block; - fasttransformplan plan; - ae_int_t i; - ae_vector buf; - - ae_frame_make(_state, &_frame_block); - memset(&plan, 0, sizeof(plan)); - memset(&buf, 0, sizeof(buf)); - _fasttransformplan_init(&plan, _state, ae_true); - ae_vector_init(&buf, 0, DT_REAL, _state, ae_true); - - ae_assert(n>0, "FFTC1D: incorrect N!", _state); - ae_assert(a->cnt>=n, "FFTC1D: Length(A)ptr.p_complex[i].x; - buf.ptr.p_double[2*i+1] = a->ptr.p_complex[i].y; - } - - /* - * Generate plan and execute it. - * - * Plan is a combination of a successive factorizations of N and - * precomputed data. It is much like a FFTW plan, but is not stored - * between subroutine calls and is much simpler. - */ - ftcomplexfftplan(n, 1, &plan, _state); - ftapplyplan(&plan, &buf, 0, 1, _state); - - /* - * result - */ - for(i=0; i<=n-1; i++) - { - a->ptr.p_complex[i].x = buf.ptr.p_double[2*i+0]; - a->ptr.p_complex[i].y = buf.ptr.p_double[2*i+1]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -1-dimensional complex inverse FFT. - -Array size N may be arbitrary number (composite or prime). Algorithm has -O(N*logN) complexity for any N (composite or prime). - -See FFTC1D() description for more information about algorithm performance. - -INPUT PARAMETERS - A - array[0..N-1] - complex array to be transformed - N - problem size - -OUTPUT PARAMETERS - A - inverse DFT of a input array, array[0..N-1] - A_out[j] = SUM(A_in[k]/N*exp(+2*pi*sqrt(-1)*j*k/N), k = 0..N-1) - - - -- ALGLIB -- - Copyright 29.05.2009 by Bochkanov Sergey -*************************************************************************/ -void fftc1dinv(/* Complex */ ae_vector* a, ae_int_t n, ae_state *_state) -{ - ae_int_t i; - - - ae_assert(n>0, "FFTC1DInv: incorrect N!", _state); - ae_assert(a->cnt>=n, "FFTC1DInv: Length(A)ptr.p_complex[i].y = -a->ptr.p_complex[i].y; - } - fftc1d(a, n, _state); - for(i=0; i<=n-1; i++) - { - a->ptr.p_complex[i].x = a->ptr.p_complex[i].x/n; - a->ptr.p_complex[i].y = -a->ptr.p_complex[i].y/n; - } -} - - -/************************************************************************* -1-dimensional real FFT. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - A - array[0..N-1] - real function to be transformed - N - problem size - -OUTPUT PARAMETERS - F - DFT of a input array, array[0..N-1] - F[j] = SUM(A[k]*exp(-2*pi*sqrt(-1)*j*k/N), k = 0..N-1) - -NOTE: - F[] satisfies symmetry property F[k] = conj(F[N-k]), so just one half -of array is usually needed. But for convinience subroutine returns full -complex array (with frequencies above N/2), so its result may be used by -other FFT-related subroutines. - - - -- ALGLIB -- - Copyright 01.06.2009 by Bochkanov Sergey -*************************************************************************/ -void fftr1d(/* Real */ ae_vector* a, - ae_int_t n, - /* Complex */ ae_vector* f, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t n2; - ae_int_t idx; - ae_complex hn; - ae_complex hmnc; - ae_complex v; - ae_vector buf; - fasttransformplan plan; - - ae_frame_make(_state, &_frame_block); - memset(&buf, 0, sizeof(buf)); - memset(&plan, 0, sizeof(plan)); - ae_vector_clear(f); - ae_vector_init(&buf, 0, DT_REAL, _state, ae_true); - _fasttransformplan_init(&plan, _state, ae_true); - - ae_assert(n>0, "FFTR1D: incorrect N!", _state); - ae_assert(a->cnt>=n, "FFTR1D: Length(A)ptr.p_complex[0] = ae_complex_from_d(a->ptr.p_double[0]); - ae_frame_leave(_state); - return; - } - if( n==2 ) - { - ae_vector_set_length(f, 2, _state); - f->ptr.p_complex[0].x = a->ptr.p_double[0]+a->ptr.p_double[1]; - f->ptr.p_complex[0].y = (double)(0); - f->ptr.p_complex[1].x = a->ptr.p_double[0]-a->ptr.p_double[1]; - f->ptr.p_complex[1].y = (double)(0); - ae_frame_leave(_state); - return; - } - - /* - * Choose between odd-size and even-size FFTs - */ - if( n%2==0 ) - { - - /* - * even-size real FFT, use reduction to the complex task - */ - n2 = n/2; - ae_vector_set_length(&buf, n, _state); - ae_v_move(&buf.ptr.p_double[0], 1, &a->ptr.p_double[0], 1, ae_v_len(0,n-1)); - ftcomplexfftplan(n2, 1, &plan, _state); - ftapplyplan(&plan, &buf, 0, 1, _state); - ae_vector_set_length(f, n, _state); - for(i=0; i<=n2; i++) - { - idx = 2*(i%n2); - hn.x = buf.ptr.p_double[idx+0]; - hn.y = buf.ptr.p_double[idx+1]; - idx = 2*((n2-i)%n2); - hmnc.x = buf.ptr.p_double[idx+0]; - hmnc.y = -buf.ptr.p_double[idx+1]; - v.x = -ae_sin(-2*ae_pi*i/n, _state); - v.y = ae_cos(-2*ae_pi*i/n, _state); - f->ptr.p_complex[i] = ae_c_sub(ae_c_add(hn,hmnc),ae_c_mul(v,ae_c_sub(hn,hmnc))); - f->ptr.p_complex[i].x = 0.5*f->ptr.p_complex[i].x; - f->ptr.p_complex[i].y = 0.5*f->ptr.p_complex[i].y; - } - for(i=n2+1; i<=n-1; i++) - { - f->ptr.p_complex[i] = ae_c_conj(f->ptr.p_complex[n-i], _state); - } - } - else - { - - /* - * use complex FFT - */ - ae_vector_set_length(f, n, _state); - for(i=0; i<=n-1; i++) - { - f->ptr.p_complex[i] = ae_complex_from_d(a->ptr.p_double[i]); - } - fftc1d(f, n, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -1-dimensional real inverse FFT. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - F - array[0..floor(N/2)] - frequencies from forward real FFT - N - problem size - -OUTPUT PARAMETERS - A - inverse DFT of a input array, array[0..N-1] - -NOTE: - F[] should satisfy symmetry property F[k] = conj(F[N-k]), so just one -half of frequencies array is needed - elements from 0 to floor(N/2). F[0] -is ALWAYS real. If N is even F[floor(N/2)] is real too. If N is odd, then -F[floor(N/2)] has no special properties. - -Relying on properties noted above, FFTR1DInv subroutine uses only elements -from 0th to floor(N/2)-th. It ignores imaginary part of F[0], and in case -N is even it ignores imaginary part of F[floor(N/2)] too. - -When you call this function using full arguments list - "FFTR1DInv(F,N,A)" -- you can pass either either frequencies array with N elements or reduced -array with roughly N/2 elements - subroutine will successfully transform -both. - -If you call this function using reduced arguments list - "FFTR1DInv(F,A)" -- you must pass FULL array with N elements (although higher N/2 are still -not used) because array size is used to automatically determine FFT length - - - -- ALGLIB -- - Copyright 01.06.2009 by Bochkanov Sergey -*************************************************************************/ -void fftr1dinv(/* Complex */ ae_vector* f, - ae_int_t n, - /* Real */ ae_vector* a, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_vector h; - ae_vector fh; - - ae_frame_make(_state, &_frame_block); - memset(&h, 0, sizeof(h)); - memset(&fh, 0, sizeof(fh)); - ae_vector_clear(a); - ae_vector_init(&h, 0, DT_REAL, _state, ae_true); - ae_vector_init(&fh, 0, DT_COMPLEX, _state, ae_true); - - ae_assert(n>0, "FFTR1DInv: incorrect N!", _state); - ae_assert(f->cnt>=ae_ifloor((double)n/(double)2, _state)+1, "FFTR1DInv: Length(F)ptr.p_complex[0].x, _state), "FFTR1DInv: F contains infinite or NAN values!", _state); - for(i=1; i<=ae_ifloor((double)n/(double)2, _state)-1; i++) - { - ae_assert(ae_isfinite(f->ptr.p_complex[i].x, _state)&&ae_isfinite(f->ptr.p_complex[i].y, _state), "FFTR1DInv: F contains infinite or NAN values!", _state); - } - ae_assert(ae_isfinite(f->ptr.p_complex[ae_ifloor((double)n/(double)2, _state)].x, _state), "FFTR1DInv: F contains infinite or NAN values!", _state); - if( n%2!=0 ) - { - ae_assert(ae_isfinite(f->ptr.p_complex[ae_ifloor((double)n/(double)2, _state)].y, _state), "FFTR1DInv: F contains infinite or NAN values!", _state); - } - - /* - * Special case: N=1, FFT is just identity transform. - * After this block we assume that N is strictly greater than 1. - */ - if( n==1 ) - { - ae_vector_set_length(a, 1, _state); - a->ptr.p_double[0] = f->ptr.p_complex[0].x; - ae_frame_leave(_state); - return; - } - - /* - * inverse real FFT is reduced to the inverse real FHT, - * which is reduced to the forward real FHT, - * which is reduced to the forward real FFT. - * - * Don't worry, it is really compact and efficient reduction :) - */ - ae_vector_set_length(&h, n, _state); - ae_vector_set_length(a, n, _state); - h.ptr.p_double[0] = f->ptr.p_complex[0].x; - for(i=1; i<=ae_ifloor((double)n/(double)2, _state)-1; i++) - { - h.ptr.p_double[i] = f->ptr.p_complex[i].x-f->ptr.p_complex[i].y; - h.ptr.p_double[n-i] = f->ptr.p_complex[i].x+f->ptr.p_complex[i].y; - } - if( n%2==0 ) - { - h.ptr.p_double[ae_ifloor((double)n/(double)2, _state)] = f->ptr.p_complex[ae_ifloor((double)n/(double)2, _state)].x; - } - else - { - h.ptr.p_double[ae_ifloor((double)n/(double)2, _state)] = f->ptr.p_complex[ae_ifloor((double)n/(double)2, _state)].x-f->ptr.p_complex[ae_ifloor((double)n/(double)2, _state)].y; - h.ptr.p_double[ae_ifloor((double)n/(double)2, _state)+1] = f->ptr.p_complex[ae_ifloor((double)n/(double)2, _state)].x+f->ptr.p_complex[ae_ifloor((double)n/(double)2, _state)].y; - } - fftr1d(&h, n, &fh, _state); - for(i=0; i<=n-1; i++) - { - a->ptr.p_double[i] = (fh.ptr.p_complex[i].x-fh.ptr.p_complex[i].y)/n; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal subroutine. Never call it directly! - - - -- ALGLIB -- - Copyright 01.06.2009 by Bochkanov Sergey -*************************************************************************/ -void fftr1dinternaleven(/* Real */ ae_vector* a, - ae_int_t n, - /* Real */ ae_vector* buf, - fasttransformplan* plan, - ae_state *_state) -{ - double x; - double y; - ae_int_t i; - ae_int_t n2; - ae_int_t idx; - ae_complex hn; - ae_complex hmnc; - ae_complex v; - - - ae_assert(n>0&&n%2==0, "FFTR1DEvenInplace: incorrect N!", _state); - - /* - * Special cases: - * * N=2 - * - * After this block we assume that N is strictly greater than 2 - */ - if( n==2 ) - { - x = a->ptr.p_double[0]+a->ptr.p_double[1]; - y = a->ptr.p_double[0]-a->ptr.p_double[1]; - a->ptr.p_double[0] = x; - a->ptr.p_double[1] = y; - return; - } - - /* - * even-size real FFT, use reduction to the complex task - */ - n2 = n/2; - ae_v_move(&buf->ptr.p_double[0], 1, &a->ptr.p_double[0], 1, ae_v_len(0,n-1)); - ftapplyplan(plan, buf, 0, 1, _state); - a->ptr.p_double[0] = buf->ptr.p_double[0]+buf->ptr.p_double[1]; - for(i=1; i<=n2-1; i++) - { - idx = 2*(i%n2); - hn.x = buf->ptr.p_double[idx+0]; - hn.y = buf->ptr.p_double[idx+1]; - idx = 2*(n2-i); - hmnc.x = buf->ptr.p_double[idx+0]; - hmnc.y = -buf->ptr.p_double[idx+1]; - v.x = -ae_sin(-2*ae_pi*i/n, _state); - v.y = ae_cos(-2*ae_pi*i/n, _state); - v = ae_c_sub(ae_c_add(hn,hmnc),ae_c_mul(v,ae_c_sub(hn,hmnc))); - a->ptr.p_double[2*i+0] = 0.5*v.x; - a->ptr.p_double[2*i+1] = 0.5*v.y; - } - a->ptr.p_double[1] = buf->ptr.p_double[0]-buf->ptr.p_double[1]; -} - - -/************************************************************************* -Internal subroutine. Never call it directly! - - - -- ALGLIB -- - Copyright 01.06.2009 by Bochkanov Sergey -*************************************************************************/ -void fftr1dinvinternaleven(/* Real */ ae_vector* a, - ae_int_t n, - /* Real */ ae_vector* buf, - fasttransformplan* plan, - ae_state *_state) -{ - double x; - double y; - double t; - ae_int_t i; - ae_int_t n2; - - - ae_assert(n>0&&n%2==0, "FFTR1DInvInternalEven: incorrect N!", _state); - - /* - * Special cases: - * * N=2 - * - * After this block we assume that N is strictly greater than 2 - */ - if( n==2 ) - { - x = 0.5*(a->ptr.p_double[0]+a->ptr.p_double[1]); - y = 0.5*(a->ptr.p_double[0]-a->ptr.p_double[1]); - a->ptr.p_double[0] = x; - a->ptr.p_double[1] = y; - return; - } - - /* - * inverse real FFT is reduced to the inverse real FHT, - * which is reduced to the forward real FHT, - * which is reduced to the forward real FFT. - * - * Don't worry, it is really compact and efficient reduction :) - */ - n2 = n/2; - buf->ptr.p_double[0] = a->ptr.p_double[0]; - for(i=1; i<=n2-1; i++) - { - x = a->ptr.p_double[2*i+0]; - y = a->ptr.p_double[2*i+1]; - buf->ptr.p_double[i] = x-y; - buf->ptr.p_double[n-i] = x+y; - } - buf->ptr.p_double[n2] = a->ptr.p_double[1]; - fftr1dinternaleven(buf, n, a, plan, _state); - a->ptr.p_double[0] = buf->ptr.p_double[0]/n; - t = (double)1/(double)n; - for(i=1; i<=n2-1; i++) - { - x = buf->ptr.p_double[2*i+0]; - y = buf->ptr.p_double[2*i+1]; - a->ptr.p_double[i] = t*(x-y); - a->ptr.p_double[n-i] = t*(x+y); - } - a->ptr.p_double[n2] = buf->ptr.p_double[1]/n; -} - - -#endif -#if defined(AE_COMPILE_FHT) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -1-dimensional Fast Hartley Transform. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - A - array[0..N-1] - real function to be transformed - N - problem size - -OUTPUT PARAMETERS - A - FHT of a input array, array[0..N-1], - A_out[k] = sum(A_in[j]*(cos(2*pi*j*k/N)+sin(2*pi*j*k/N)), j=0..N-1) - - - -- ALGLIB -- - Copyright 04.06.2009 by Bochkanov Sergey -*************************************************************************/ -void fhtr1d(/* Real */ ae_vector* a, ae_int_t n, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_vector fa; - - ae_frame_make(_state, &_frame_block); - memset(&fa, 0, sizeof(fa)); - ae_vector_init(&fa, 0, DT_COMPLEX, _state, ae_true); - - ae_assert(n>0, "FHTR1D: incorrect N!", _state); - - /* - * Special case: N=1, FHT is just identity transform. - * After this block we assume that N is strictly greater than 1. - */ - if( n==1 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Reduce FHt to real FFT - */ - fftr1d(a, n, &fa, _state); - for(i=0; i<=n-1; i++) - { - a->ptr.p_double[i] = fa.ptr.p_complex[i].x-fa.ptr.p_complex[i].y; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -1-dimensional inverse FHT. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - A - array[0..N-1] - complex array to be transformed - N - problem size - -OUTPUT PARAMETERS - A - inverse FHT of a input array, array[0..N-1] - - - -- ALGLIB -- - Copyright 29.05.2009 by Bochkanov Sergey -*************************************************************************/ -void fhtr1dinv(/* Real */ ae_vector* a, ae_int_t n, ae_state *_state) -{ - ae_int_t i; - - - ae_assert(n>0, "FHTR1DInv: incorrect N!", _state); - - /* - * Special case: N=1, iFHT is just identity transform. - * After this block we assume that N is strictly greater than 1. - */ - if( n==1 ) - { - return; - } - - /* - * Inverse FHT can be expressed in terms of the FHT as - * - * invfht(x) = fht(x)/N - */ - fhtr1d(a, n, _state); - for(i=0; i<=n-1; i++) - { - a->ptr.p_double[i] = a->ptr.p_double[i]/n; - } -} - - -#endif -#if defined(AE_COMPILE_CONV) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -1-dimensional complex convolution. - -For given A/B returns conv(A,B) (non-circular). Subroutine can automatically -choose between three implementations: straightforward O(M*N) formula for -very small N (or M), overlap-add algorithm for cases where max(M,N) is -significantly larger than min(M,N), but O(M*N) algorithm is too slow, and -general FFT-based formula for cases where two previois algorithms are too -slow. - -Algorithm has max(M,N)*log(max(M,N)) complexity for any M/N. - -INPUT PARAMETERS - A - array[0..M-1] - complex function to be transformed - M - problem size - B - array[0..N-1] - complex function to be transformed - N - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..N+M-2]. - -NOTE: - It is assumed that A is zero at T<0, B is zero too. If one or both -functions have non-zero values at negative T's, you can still use this -subroutine - just shift its result correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convc1d(/* Complex */ ae_vector* a, - ae_int_t m, - /* Complex */ ae_vector* b, - ae_int_t n, - /* Complex */ ae_vector* r, - ae_state *_state) -{ - - ae_vector_clear(r); - - ae_assert(n>0&&m>0, "ConvC1D: incorrect N or M!", _state); - - /* - * normalize task: make M>=N, - * so A will be longer that B. - */ - if( m0&&m>0)&&n<=m, "ConvC1DInv: incorrect N or M!", _state); - p = ftbasefindsmooth(m, _state); - ftcomplexfftplan(p, 1, &plan, _state); - ae_vector_set_length(&buf, 2*p, _state); - for(i=0; i<=m-1; i++) - { - buf.ptr.p_double[2*i+0] = a->ptr.p_complex[i].x; - buf.ptr.p_double[2*i+1] = a->ptr.p_complex[i].y; - } - for(i=m; i<=p-1; i++) - { - buf.ptr.p_double[2*i+0] = (double)(0); - buf.ptr.p_double[2*i+1] = (double)(0); - } - ae_vector_set_length(&buf2, 2*p, _state); - for(i=0; i<=n-1; i++) - { - buf2.ptr.p_double[2*i+0] = b->ptr.p_complex[i].x; - buf2.ptr.p_double[2*i+1] = b->ptr.p_complex[i].y; - } - for(i=n; i<=p-1; i++) - { - buf2.ptr.p_double[2*i+0] = (double)(0); - buf2.ptr.p_double[2*i+1] = (double)(0); - } - ftapplyplan(&plan, &buf, 0, 1, _state); - ftapplyplan(&plan, &buf2, 0, 1, _state); - for(i=0; i<=p-1; i++) - { - c1.x = buf.ptr.p_double[2*i+0]; - c1.y = buf.ptr.p_double[2*i+1]; - c2.x = buf2.ptr.p_double[2*i+0]; - c2.y = buf2.ptr.p_double[2*i+1]; - c3 = ae_c_div(c1,c2); - buf.ptr.p_double[2*i+0] = c3.x; - buf.ptr.p_double[2*i+1] = -c3.y; - } - ftapplyplan(&plan, &buf, 0, 1, _state); - t = (double)1/(double)p; - ae_vector_set_length(r, m-n+1, _state); - for(i=0; i<=m-n; i++) - { - r->ptr.p_complex[i].x = t*buf.ptr.p_double[2*i+0]; - r->ptr.p_complex[i].y = -t*buf.ptr.p_double[2*i+1]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -1-dimensional circular complex convolution. - -For given S/R returns conv(S,R) (circular). Algorithm has linearithmic -complexity for any M/N. - -IMPORTANT: normal convolution is commutative, i.e. it is symmetric - -conv(A,B)=conv(B,A). Cyclic convolution IS NOT. One function - S - is a -signal, periodic function, and another - R - is a response, non-periodic -function with limited length. - -INPUT PARAMETERS - S - array[0..M-1] - complex periodic signal - M - problem size - B - array[0..N-1] - complex non-periodic response - N - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..M-1]. - -NOTE: - It is assumed that B is zero at T<0. If it has non-zero values at -negative T's, you can still use this subroutine - just shift its result -correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convc1dcircular(/* Complex */ ae_vector* s, - ae_int_t m, - /* Complex */ ae_vector* r, - ae_int_t n, - /* Complex */ ae_vector* c, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector buf; - ae_int_t i1; - ae_int_t i2; - ae_int_t j2; - - ae_frame_make(_state, &_frame_block); - memset(&buf, 0, sizeof(buf)); - ae_vector_clear(c); - ae_vector_init(&buf, 0, DT_COMPLEX, _state, ae_true); - - ae_assert(n>0&&m>0, "ConvC1DCircular: incorrect N or M!", _state); - - /* - * normalize task: make M>=N, - * so A will be longer (at least - not shorter) that B. - */ - if( mptr.p_complex[i1], 1, "N", ae_v_len(0,j2)); - i1 = i1+m; - } - convc1dcircular(s, m, &buf, m, c, _state); - ae_frame_leave(_state); - return; - } - convc1dx(s, m, r, n, ae_true, -1, 0, c, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -1-dimensional circular complex deconvolution (inverse of ConvC1DCircular()). - -Algorithm has M*log(M)) complexity for any M (composite or prime). - -INPUT PARAMETERS - A - array[0..M-1] - convolved periodic signal, A = conv(R, B) - M - convolved signal length - B - array[0..N-1] - non-periodic response - N - response length - -OUTPUT PARAMETERS - R - deconvolved signal. array[0..M-1]. - -NOTE: - deconvolution is unstable process and may result in division by zero -(if your response function is degenerate, i.e. has zero Fourier coefficient). - -NOTE: - It is assumed that B is zero at T<0. If it has non-zero values at -negative T's, you can still use this subroutine - just shift its result -correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convc1dcircularinv(/* Complex */ ae_vector* a, - ae_int_t m, - /* Complex */ ae_vector* b, - ae_int_t n, - /* Complex */ ae_vector* r, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t i1; - ae_int_t i2; - ae_int_t j2; - ae_vector buf; - ae_vector buf2; - ae_vector cbuf; - fasttransformplan plan; - ae_complex c1; - ae_complex c2; - ae_complex c3; - double t; - - ae_frame_make(_state, &_frame_block); - memset(&buf, 0, sizeof(buf)); - memset(&buf2, 0, sizeof(buf2)); - memset(&cbuf, 0, sizeof(cbuf)); - memset(&plan, 0, sizeof(plan)); - ae_vector_clear(r); - ae_vector_init(&buf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&buf2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cbuf, 0, DT_COMPLEX, _state, ae_true); - _fasttransformplan_init(&plan, _state, ae_true); - - ae_assert(n>0&&m>0, "ConvC1DCircularInv: incorrect N or M!", _state); - - /* - * normalize task: make M>=N, - * so A will be longer (at least - not shorter) that B. - */ - if( mptr.p_complex[i1], 1, "N", ae_v_len(0,j2)); - i1 = i1+m; - } - convc1dcircularinv(a, m, &cbuf, m, r, _state); - ae_frame_leave(_state); - return; - } - - /* - * Task is normalized - */ - ftcomplexfftplan(m, 1, &plan, _state); - ae_vector_set_length(&buf, 2*m, _state); - for(i=0; i<=m-1; i++) - { - buf.ptr.p_double[2*i+0] = a->ptr.p_complex[i].x; - buf.ptr.p_double[2*i+1] = a->ptr.p_complex[i].y; - } - ae_vector_set_length(&buf2, 2*m, _state); - for(i=0; i<=n-1; i++) - { - buf2.ptr.p_double[2*i+0] = b->ptr.p_complex[i].x; - buf2.ptr.p_double[2*i+1] = b->ptr.p_complex[i].y; - } - for(i=n; i<=m-1; i++) - { - buf2.ptr.p_double[2*i+0] = (double)(0); - buf2.ptr.p_double[2*i+1] = (double)(0); - } - ftapplyplan(&plan, &buf, 0, 1, _state); - ftapplyplan(&plan, &buf2, 0, 1, _state); - for(i=0; i<=m-1; i++) - { - c1.x = buf.ptr.p_double[2*i+0]; - c1.y = buf.ptr.p_double[2*i+1]; - c2.x = buf2.ptr.p_double[2*i+0]; - c2.y = buf2.ptr.p_double[2*i+1]; - c3 = ae_c_div(c1,c2); - buf.ptr.p_double[2*i+0] = c3.x; - buf.ptr.p_double[2*i+1] = -c3.y; - } - ftapplyplan(&plan, &buf, 0, 1, _state); - t = (double)1/(double)m; - ae_vector_set_length(r, m, _state); - for(i=0; i<=m-1; i++) - { - r->ptr.p_complex[i].x = t*buf.ptr.p_double[2*i+0]; - r->ptr.p_complex[i].y = -t*buf.ptr.p_double[2*i+1]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -1-dimensional real convolution. - -Analogous to ConvC1D(), see ConvC1D() comments for more details. - -INPUT PARAMETERS - A - array[0..M-1] - real function to be transformed - M - problem size - B - array[0..N-1] - real function to be transformed - N - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..N+M-2]. - -NOTE: - It is assumed that A is zero at T<0, B is zero too. If one or both -functions have non-zero values at negative T's, you can still use this -subroutine - just shift its result correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convr1d(/* Real */ ae_vector* a, - ae_int_t m, - /* Real */ ae_vector* b, - ae_int_t n, - /* Real */ ae_vector* r, - ae_state *_state) -{ - - ae_vector_clear(r); - - ae_assert(n>0&&m>0, "ConvR1D: incorrect N or M!", _state); - - /* - * normalize task: make M>=N, - * so A will be longer that B. - */ - if( m0&&m>0)&&n<=m, "ConvR1DInv: incorrect N or M!", _state); - p = ftbasefindsmootheven(m, _state); - ae_vector_set_length(&buf, p, _state); - ae_v_move(&buf.ptr.p_double[0], 1, &a->ptr.p_double[0], 1, ae_v_len(0,m-1)); - for(i=m; i<=p-1; i++) - { - buf.ptr.p_double[i] = (double)(0); - } - ae_vector_set_length(&buf2, p, _state); - ae_v_move(&buf2.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=n; i<=p-1; i++) - { - buf2.ptr.p_double[i] = (double)(0); - } - ae_vector_set_length(&buf3, p, _state); - ftcomplexfftplan(p/2, 1, &plan, _state); - fftr1dinternaleven(&buf, p, &buf3, &plan, _state); - fftr1dinternaleven(&buf2, p, &buf3, &plan, _state); - buf.ptr.p_double[0] = buf.ptr.p_double[0]/buf2.ptr.p_double[0]; - buf.ptr.p_double[1] = buf.ptr.p_double[1]/buf2.ptr.p_double[1]; - for(i=1; i<=p/2-1; i++) - { - c1.x = buf.ptr.p_double[2*i+0]; - c1.y = buf.ptr.p_double[2*i+1]; - c2.x = buf2.ptr.p_double[2*i+0]; - c2.y = buf2.ptr.p_double[2*i+1]; - c3 = ae_c_div(c1,c2); - buf.ptr.p_double[2*i+0] = c3.x; - buf.ptr.p_double[2*i+1] = c3.y; - } - fftr1dinvinternaleven(&buf, p, &buf3, &plan, _state); - ae_vector_set_length(r, m-n+1, _state); - ae_v_move(&r->ptr.p_double[0], 1, &buf.ptr.p_double[0], 1, ae_v_len(0,m-n)); - ae_frame_leave(_state); -} - - -/************************************************************************* -1-dimensional circular real convolution. - -Analogous to ConvC1DCircular(), see ConvC1DCircular() comments for more details. - -INPUT PARAMETERS - S - array[0..M-1] - real signal - M - problem size - B - array[0..N-1] - real response - N - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..M-1]. - -NOTE: - It is assumed that B is zero at T<0. If it has non-zero values at -negative T's, you can still use this subroutine - just shift its result -correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convr1dcircular(/* Real */ ae_vector* s, - ae_int_t m, - /* Real */ ae_vector* r, - ae_int_t n, - /* Real */ ae_vector* c, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector buf; - ae_int_t i1; - ae_int_t i2; - ae_int_t j2; - - ae_frame_make(_state, &_frame_block); - memset(&buf, 0, sizeof(buf)); - ae_vector_clear(c); - ae_vector_init(&buf, 0, DT_REAL, _state, ae_true); - - ae_assert(n>0&&m>0, "ConvC1DCircular: incorrect N or M!", _state); - - /* - * normalize task: make M>=N, - * so A will be longer (at least - not shorter) that B. - */ - if( mptr.p_double[i1], 1, ae_v_len(0,j2)); - i1 = i1+m; - } - convr1dcircular(s, m, &buf, m, c, _state); - ae_frame_leave(_state); - return; - } - - /* - * reduce to usual convolution - */ - convr1dx(s, m, r, n, ae_true, -1, 0, c, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -1-dimensional complex deconvolution (inverse of ConvC1D()). - -Algorithm has M*log(M)) complexity for any M (composite or prime). - -INPUT PARAMETERS - A - array[0..M-1] - convolved signal, A = conv(R, B) - M - convolved signal length - B - array[0..N-1] - response - N - response length - -OUTPUT PARAMETERS - R - deconvolved signal. array[0..M-N]. - -NOTE: - deconvolution is unstable process and may result in division by zero -(if your response function is degenerate, i.e. has zero Fourier coefficient). - -NOTE: - It is assumed that B is zero at T<0. If it has non-zero values at -negative T's, you can still use this subroutine - just shift its result -correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convr1dcircularinv(/* Real */ ae_vector* a, - ae_int_t m, - /* Real */ ae_vector* b, - ae_int_t n, - /* Real */ ae_vector* r, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t i1; - ae_int_t i2; - ae_int_t j2; - ae_vector buf; - ae_vector buf2; - ae_vector buf3; - ae_vector cbuf; - ae_vector cbuf2; - fasttransformplan plan; - ae_complex c1; - ae_complex c2; - ae_complex c3; - - ae_frame_make(_state, &_frame_block); - memset(&buf, 0, sizeof(buf)); - memset(&buf2, 0, sizeof(buf2)); - memset(&buf3, 0, sizeof(buf3)); - memset(&cbuf, 0, sizeof(cbuf)); - memset(&cbuf2, 0, sizeof(cbuf2)); - memset(&plan, 0, sizeof(plan)); - ae_vector_clear(r); - ae_vector_init(&buf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&buf2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&buf3, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cbuf, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&cbuf2, 0, DT_COMPLEX, _state, ae_true); - _fasttransformplan_init(&plan, _state, ae_true); - - ae_assert(n>0&&m>0, "ConvR1DCircularInv: incorrect N or M!", _state); - - /* - * normalize task: make M>=N, - * so A will be longer (at least - not shorter) that B. - */ - if( mptr.p_double[i1], 1, ae_v_len(0,j2)); - i1 = i1+m; - } - convr1dcircularinv(a, m, &buf, m, r, _state); - ae_frame_leave(_state); - return; - } - - /* - * Task is normalized - */ - if( m%2==0 ) - { - - /* - * size is even, use fast even-size FFT - */ - ae_vector_set_length(&buf, m, _state); - ae_v_move(&buf.ptr.p_double[0], 1, &a->ptr.p_double[0], 1, ae_v_len(0,m-1)); - ae_vector_set_length(&buf2, m, _state); - ae_v_move(&buf2.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=n; i<=m-1; i++) - { - buf2.ptr.p_double[i] = (double)(0); - } - ae_vector_set_length(&buf3, m, _state); - ftcomplexfftplan(m/2, 1, &plan, _state); - fftr1dinternaleven(&buf, m, &buf3, &plan, _state); - fftr1dinternaleven(&buf2, m, &buf3, &plan, _state); - buf.ptr.p_double[0] = buf.ptr.p_double[0]/buf2.ptr.p_double[0]; - buf.ptr.p_double[1] = buf.ptr.p_double[1]/buf2.ptr.p_double[1]; - for(i=1; i<=m/2-1; i++) - { - c1.x = buf.ptr.p_double[2*i+0]; - c1.y = buf.ptr.p_double[2*i+1]; - c2.x = buf2.ptr.p_double[2*i+0]; - c2.y = buf2.ptr.p_double[2*i+1]; - c3 = ae_c_div(c1,c2); - buf.ptr.p_double[2*i+0] = c3.x; - buf.ptr.p_double[2*i+1] = c3.y; - } - fftr1dinvinternaleven(&buf, m, &buf3, &plan, _state); - ae_vector_set_length(r, m, _state); - ae_v_move(&r->ptr.p_double[0], 1, &buf.ptr.p_double[0], 1, ae_v_len(0,m-1)); - } - else - { - - /* - * odd-size, use general real FFT - */ - fftr1d(a, m, &cbuf, _state); - ae_vector_set_length(&buf2, m, _state); - ae_v_move(&buf2.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=n; i<=m-1; i++) - { - buf2.ptr.p_double[i] = (double)(0); - } - fftr1d(&buf2, m, &cbuf2, _state); - for(i=0; i<=ae_ifloor((double)m/(double)2, _state); i++) - { - cbuf.ptr.p_complex[i] = ae_c_div(cbuf.ptr.p_complex[i],cbuf2.ptr.p_complex[i]); - } - fftr1dinv(&cbuf, m, r, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -1-dimensional complex convolution. - -Extended subroutine which allows to choose convolution algorithm. -Intended for internal use, ALGLIB users should call ConvC1D()/ConvC1DCircular(). - -INPUT PARAMETERS - A - array[0..M-1] - complex function to be transformed - M - problem size - B - array[0..N-1] - complex function to be transformed - N - problem size, N<=M - Alg - algorithm type: - *-2 auto-select Q for overlap-add - *-1 auto-select algorithm and parameters - * 0 straightforward formula for small N's - * 1 general FFT-based code - * 2 overlap-add with length Q - Q - length for overlap-add - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..N+M-1]. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convc1dx(/* Complex */ ae_vector* a, - ae_int_t m, - /* Complex */ ae_vector* b, - ae_int_t n, - ae_bool circular, - ae_int_t alg, - ae_int_t q, - /* Complex */ ae_vector* r, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t p; - ae_int_t ptotal; - ae_int_t i1; - ae_int_t i2; - ae_int_t j1; - ae_int_t j2; - ae_vector bbuf; - ae_complex v; - double ax; - double ay; - double bx; - double by; - double t; - double tx; - double ty; - double flopcand; - double flopbest; - ae_int_t algbest; - fasttransformplan plan; - ae_vector buf; - ae_vector buf2; - - ae_frame_make(_state, &_frame_block); - memset(&bbuf, 0, sizeof(bbuf)); - memset(&plan, 0, sizeof(plan)); - memset(&buf, 0, sizeof(buf)); - memset(&buf2, 0, sizeof(buf2)); - ae_vector_clear(r); - ae_vector_init(&bbuf, 0, DT_COMPLEX, _state, ae_true); - _fasttransformplan_init(&plan, _state, ae_true); - ae_vector_init(&buf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&buf2, 0, DT_REAL, _state, ae_true); - - ae_assert(n>0&&m>0, "ConvC1DX: incorrect N or M!", _state); - ae_assert(n<=m, "ConvC1DX: Nptr.p_complex[0]; - ae_v_cmovec(&r->ptr.p_complex[0], 1, &a->ptr.p_complex[0], 1, "N", ae_v_len(0,m-1), v); - ae_frame_leave(_state); - return; - } - - /* - * use straightforward formula - */ - if( circular ) - { - - /* - * circular convolution - */ - ae_vector_set_length(r, m, _state); - v = b->ptr.p_complex[0]; - ae_v_cmovec(&r->ptr.p_complex[0], 1, &a->ptr.p_complex[0], 1, "N", ae_v_len(0,m-1), v); - for(i=1; i<=n-1; i++) - { - v = b->ptr.p_complex[i]; - i1 = 0; - i2 = i-1; - j1 = m-i; - j2 = m-1; - ae_v_caddc(&r->ptr.p_complex[i1], 1, &a->ptr.p_complex[j1], 1, "N", ae_v_len(i1,i2), v); - i1 = i; - i2 = m-1; - j1 = 0; - j2 = m-i-1; - ae_v_caddc(&r->ptr.p_complex[i1], 1, &a->ptr.p_complex[j1], 1, "N", ae_v_len(i1,i2), v); - } - } - else - { - - /* - * non-circular convolution - */ - ae_vector_set_length(r, m+n-1, _state); - for(i=0; i<=m+n-2; i++) - { - r->ptr.p_complex[i] = ae_complex_from_i(0); - } - for(i=0; i<=n-1; i++) - { - v = b->ptr.p_complex[i]; - ae_v_caddc(&r->ptr.p_complex[i], 1, &a->ptr.p_complex[0], 1, "N", ae_v_len(i,i+m-1), v); - } - } - ae_frame_leave(_state); - return; - } - - /* - * general FFT-based code for - * circular and non-circular convolutions. - * - * First, if convolution is circular, we test whether M is smooth or not. - * If it is smooth, we just use M-length FFT to calculate convolution. - * If it is not, we calculate non-circular convolution and wrap it arount. - * - * IF convolution is non-circular, we use zero-padding + FFT. - */ - if( alg==1 ) - { - if( circular&&ftbaseissmooth(m, _state) ) - { - - /* - * special code for circular convolution with smooth M - */ - ftcomplexfftplan(m, 1, &plan, _state); - ae_vector_set_length(&buf, 2*m, _state); - for(i=0; i<=m-1; i++) - { - buf.ptr.p_double[2*i+0] = a->ptr.p_complex[i].x; - buf.ptr.p_double[2*i+1] = a->ptr.p_complex[i].y; - } - ae_vector_set_length(&buf2, 2*m, _state); - for(i=0; i<=n-1; i++) - { - buf2.ptr.p_double[2*i+0] = b->ptr.p_complex[i].x; - buf2.ptr.p_double[2*i+1] = b->ptr.p_complex[i].y; - } - for(i=n; i<=m-1; i++) - { - buf2.ptr.p_double[2*i+0] = (double)(0); - buf2.ptr.p_double[2*i+1] = (double)(0); - } - ftapplyplan(&plan, &buf, 0, 1, _state); - ftapplyplan(&plan, &buf2, 0, 1, _state); - for(i=0; i<=m-1; i++) - { - ax = buf.ptr.p_double[2*i+0]; - ay = buf.ptr.p_double[2*i+1]; - bx = buf2.ptr.p_double[2*i+0]; - by = buf2.ptr.p_double[2*i+1]; - tx = ax*bx-ay*by; - ty = ax*by+ay*bx; - buf.ptr.p_double[2*i+0] = tx; - buf.ptr.p_double[2*i+1] = -ty; - } - ftapplyplan(&plan, &buf, 0, 1, _state); - t = (double)1/(double)m; - ae_vector_set_length(r, m, _state); - for(i=0; i<=m-1; i++) - { - r->ptr.p_complex[i].x = t*buf.ptr.p_double[2*i+0]; - r->ptr.p_complex[i].y = -t*buf.ptr.p_double[2*i+1]; - } - } - else - { - - /* - * M is non-smooth, general code (circular/non-circular): - * * first part is the same for circular and non-circular - * convolutions. zero padding, FFTs, inverse FFTs - * * second part differs: - * * for non-circular convolution we just copy array - * * for circular convolution we add array tail to its head - */ - p = ftbasefindsmooth(m+n-1, _state); - ftcomplexfftplan(p, 1, &plan, _state); - ae_vector_set_length(&buf, 2*p, _state); - for(i=0; i<=m-1; i++) - { - buf.ptr.p_double[2*i+0] = a->ptr.p_complex[i].x; - buf.ptr.p_double[2*i+1] = a->ptr.p_complex[i].y; - } - for(i=m; i<=p-1; i++) - { - buf.ptr.p_double[2*i+0] = (double)(0); - buf.ptr.p_double[2*i+1] = (double)(0); - } - ae_vector_set_length(&buf2, 2*p, _state); - for(i=0; i<=n-1; i++) - { - buf2.ptr.p_double[2*i+0] = b->ptr.p_complex[i].x; - buf2.ptr.p_double[2*i+1] = b->ptr.p_complex[i].y; - } - for(i=n; i<=p-1; i++) - { - buf2.ptr.p_double[2*i+0] = (double)(0); - buf2.ptr.p_double[2*i+1] = (double)(0); - } - ftapplyplan(&plan, &buf, 0, 1, _state); - ftapplyplan(&plan, &buf2, 0, 1, _state); - for(i=0; i<=p-1; i++) - { - ax = buf.ptr.p_double[2*i+0]; - ay = buf.ptr.p_double[2*i+1]; - bx = buf2.ptr.p_double[2*i+0]; - by = buf2.ptr.p_double[2*i+1]; - tx = ax*bx-ay*by; - ty = ax*by+ay*bx; - buf.ptr.p_double[2*i+0] = tx; - buf.ptr.p_double[2*i+1] = -ty; - } - ftapplyplan(&plan, &buf, 0, 1, _state); - t = (double)1/(double)p; - if( circular ) - { - - /* - * circular, add tail to head - */ - ae_vector_set_length(r, m, _state); - for(i=0; i<=m-1; i++) - { - r->ptr.p_complex[i].x = t*buf.ptr.p_double[2*i+0]; - r->ptr.p_complex[i].y = -t*buf.ptr.p_double[2*i+1]; - } - for(i=m; i<=m+n-2; i++) - { - r->ptr.p_complex[i-m].x = r->ptr.p_complex[i-m].x+t*buf.ptr.p_double[2*i+0]; - r->ptr.p_complex[i-m].y = r->ptr.p_complex[i-m].y-t*buf.ptr.p_double[2*i+1]; - } - } - else - { - - /* - * non-circular, just copy - */ - ae_vector_set_length(r, m+n-1, _state); - for(i=0; i<=m+n-2; i++) - { - r->ptr.p_complex[i].x = t*buf.ptr.p_double[2*i+0]; - r->ptr.p_complex[i].y = -t*buf.ptr.p_double[2*i+1]; - } - } - } - ae_frame_leave(_state); - return; - } - - /* - * overlap-add method for - * circular and non-circular convolutions. - * - * First part of code (separate FFTs of input blocks) is the same - * for all types of convolution. Second part (overlapping outputs) - * differs for different types of convolution. We just copy output - * when convolution is non-circular. We wrap it around, if it is - * circular. - */ - if( alg==2 ) - { - ae_vector_set_length(&buf, 2*(q+n-1), _state); - - /* - * prepare R - */ - if( circular ) - { - ae_vector_set_length(r, m, _state); - for(i=0; i<=m-1; i++) - { - r->ptr.p_complex[i] = ae_complex_from_i(0); - } - } - else - { - ae_vector_set_length(r, m+n-1, _state); - for(i=0; i<=m+n-2; i++) - { - r->ptr.p_complex[i] = ae_complex_from_i(0); - } - } - - /* - * pre-calculated FFT(B) - */ - ae_vector_set_length(&bbuf, q+n-1, _state); - ae_v_cmove(&bbuf.ptr.p_complex[0], 1, &b->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1)); - for(j=n; j<=q+n-2; j++) - { - bbuf.ptr.p_complex[j] = ae_complex_from_i(0); - } - fftc1d(&bbuf, q+n-1, _state); - - /* - * prepare FFT plan for chunks of A - */ - ftcomplexfftplan(q+n-1, 1, &plan, _state); - - /* - * main overlap-add cycle - */ - i = 0; - while(i<=m-1) - { - p = ae_minint(q, m-i, _state); - for(j=0; j<=p-1; j++) - { - buf.ptr.p_double[2*j+0] = a->ptr.p_complex[i+j].x; - buf.ptr.p_double[2*j+1] = a->ptr.p_complex[i+j].y; - } - for(j=p; j<=q+n-2; j++) - { - buf.ptr.p_double[2*j+0] = (double)(0); - buf.ptr.p_double[2*j+1] = (double)(0); - } - ftapplyplan(&plan, &buf, 0, 1, _state); - for(j=0; j<=q+n-2; j++) - { - ax = buf.ptr.p_double[2*j+0]; - ay = buf.ptr.p_double[2*j+1]; - bx = bbuf.ptr.p_complex[j].x; - by = bbuf.ptr.p_complex[j].y; - tx = ax*bx-ay*by; - ty = ax*by+ay*bx; - buf.ptr.p_double[2*j+0] = tx; - buf.ptr.p_double[2*j+1] = -ty; - } - ftapplyplan(&plan, &buf, 0, 1, _state); - t = (double)1/(double)(q+n-1); - if( circular ) - { - j1 = ae_minint(i+p+n-2, m-1, _state)-i; - j2 = j1+1; - } - else - { - j1 = p+n-2; - j2 = j1+1; - } - for(j=0; j<=j1; j++) - { - r->ptr.p_complex[i+j].x = r->ptr.p_complex[i+j].x+buf.ptr.p_double[2*j+0]*t; - r->ptr.p_complex[i+j].y = r->ptr.p_complex[i+j].y-buf.ptr.p_double[2*j+1]*t; - } - for(j=j2; j<=p+n-2; j++) - { - r->ptr.p_complex[j-j2].x = r->ptr.p_complex[j-j2].x+buf.ptr.p_double[2*j+0]*t; - r->ptr.p_complex[j-j2].y = r->ptr.p_complex[j-j2].y-buf.ptr.p_double[2*j+1]*t; - } - i = i+p; - } - ae_frame_leave(_state); - return; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -1-dimensional real convolution. - -Extended subroutine which allows to choose convolution algorithm. -Intended for internal use, ALGLIB users should call ConvR1D(). - -INPUT PARAMETERS - A - array[0..M-1] - complex function to be transformed - M - problem size - B - array[0..N-1] - complex function to be transformed - N - problem size, N<=M - Alg - algorithm type: - *-2 auto-select Q for overlap-add - *-1 auto-select algorithm and parameters - * 0 straightforward formula for small N's - * 1 general FFT-based code - * 2 overlap-add with length Q - Q - length for overlap-add - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..N+M-1]. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convr1dx(/* Real */ ae_vector* a, - ae_int_t m, - /* Real */ ae_vector* b, - ae_int_t n, - ae_bool circular, - ae_int_t alg, - ae_int_t q, - /* Real */ ae_vector* r, - ae_state *_state) -{ - ae_frame _frame_block; - double v; - ae_int_t i; - ae_int_t j; - ae_int_t p; - ae_int_t ptotal; - ae_int_t i1; - ae_int_t i2; - ae_int_t j1; - ae_int_t j2; - double ax; - double ay; - double bx; - double by; - double tx; - double ty; - double flopcand; - double flopbest; - ae_int_t algbest; - fasttransformplan plan; - ae_vector buf; - ae_vector buf2; - ae_vector buf3; - - ae_frame_make(_state, &_frame_block); - memset(&plan, 0, sizeof(plan)); - memset(&buf, 0, sizeof(buf)); - memset(&buf2, 0, sizeof(buf2)); - memset(&buf3, 0, sizeof(buf3)); - ae_vector_clear(r); - _fasttransformplan_init(&plan, _state, ae_true); - ae_vector_init(&buf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&buf2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&buf3, 0, DT_REAL, _state, ae_true); - - ae_assert(n>0&&m>0, "ConvC1DX: incorrect N or M!", _state); - ae_assert(n<=m, "ConvC1DX: Nptr.p_double[0]; - ae_v_moved(&r->ptr.p_double[0], 1, &a->ptr.p_double[0], 1, ae_v_len(0,m-1), v); - ae_frame_leave(_state); - return; - } - - /* - * use straightforward formula - */ - if( circular ) - { - - /* - * circular convolution - */ - ae_vector_set_length(r, m, _state); - v = b->ptr.p_double[0]; - ae_v_moved(&r->ptr.p_double[0], 1, &a->ptr.p_double[0], 1, ae_v_len(0,m-1), v); - for(i=1; i<=n-1; i++) - { - v = b->ptr.p_double[i]; - i1 = 0; - i2 = i-1; - j1 = m-i; - j2 = m-1; - ae_v_addd(&r->ptr.p_double[i1], 1, &a->ptr.p_double[j1], 1, ae_v_len(i1,i2), v); - i1 = i; - i2 = m-1; - j1 = 0; - j2 = m-i-1; - ae_v_addd(&r->ptr.p_double[i1], 1, &a->ptr.p_double[j1], 1, ae_v_len(i1,i2), v); - } - } - else - { - - /* - * non-circular convolution - */ - ae_vector_set_length(r, m+n-1, _state); - for(i=0; i<=m+n-2; i++) - { - r->ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - v = b->ptr.p_double[i]; - ae_v_addd(&r->ptr.p_double[i], 1, &a->ptr.p_double[0], 1, ae_v_len(i,i+m-1), v); - } - } - ae_frame_leave(_state); - return; - } - - /* - * general FFT-based code for - * circular and non-circular convolutions. - * - * First, if convolution is circular, we test whether M is smooth or not. - * If it is smooth, we just use M-length FFT to calculate convolution. - * If it is not, we calculate non-circular convolution and wrap it arount. - * - * If convolution is non-circular, we use zero-padding + FFT. - * - * We assume that M+N-1>2 - we should call small case code otherwise - */ - if( alg==1 ) - { - ae_assert(m+n-1>2, "ConvR1DX: internal error!", _state); - if( (circular&&ftbaseissmooth(m, _state))&&m%2==0 ) - { - - /* - * special code for circular convolution with smooth even M - */ - ae_vector_set_length(&buf, m, _state); - ae_v_move(&buf.ptr.p_double[0], 1, &a->ptr.p_double[0], 1, ae_v_len(0,m-1)); - ae_vector_set_length(&buf2, m, _state); - ae_v_move(&buf2.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=n; i<=m-1; i++) - { - buf2.ptr.p_double[i] = (double)(0); - } - ae_vector_set_length(&buf3, m, _state); - ftcomplexfftplan(m/2, 1, &plan, _state); - fftr1dinternaleven(&buf, m, &buf3, &plan, _state); - fftr1dinternaleven(&buf2, m, &buf3, &plan, _state); - buf.ptr.p_double[0] = buf.ptr.p_double[0]*buf2.ptr.p_double[0]; - buf.ptr.p_double[1] = buf.ptr.p_double[1]*buf2.ptr.p_double[1]; - for(i=1; i<=m/2-1; i++) - { - ax = buf.ptr.p_double[2*i+0]; - ay = buf.ptr.p_double[2*i+1]; - bx = buf2.ptr.p_double[2*i+0]; - by = buf2.ptr.p_double[2*i+1]; - tx = ax*bx-ay*by; - ty = ax*by+ay*bx; - buf.ptr.p_double[2*i+0] = tx; - buf.ptr.p_double[2*i+1] = ty; - } - fftr1dinvinternaleven(&buf, m, &buf3, &plan, _state); - ae_vector_set_length(r, m, _state); - ae_v_move(&r->ptr.p_double[0], 1, &buf.ptr.p_double[0], 1, ae_v_len(0,m-1)); - } - else - { - - /* - * M is non-smooth or non-even, general code (circular/non-circular): - * * first part is the same for circular and non-circular - * convolutions. zero padding, FFTs, inverse FFTs - * * second part differs: - * * for non-circular convolution we just copy array - * * for circular convolution we add array tail to its head - */ - p = ftbasefindsmootheven(m+n-1, _state); - ae_vector_set_length(&buf, p, _state); - ae_v_move(&buf.ptr.p_double[0], 1, &a->ptr.p_double[0], 1, ae_v_len(0,m-1)); - for(i=m; i<=p-1; i++) - { - buf.ptr.p_double[i] = (double)(0); - } - ae_vector_set_length(&buf2, p, _state); - ae_v_move(&buf2.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=n; i<=p-1; i++) - { - buf2.ptr.p_double[i] = (double)(0); - } - ae_vector_set_length(&buf3, p, _state); - ftcomplexfftplan(p/2, 1, &plan, _state); - fftr1dinternaleven(&buf, p, &buf3, &plan, _state); - fftr1dinternaleven(&buf2, p, &buf3, &plan, _state); - buf.ptr.p_double[0] = buf.ptr.p_double[0]*buf2.ptr.p_double[0]; - buf.ptr.p_double[1] = buf.ptr.p_double[1]*buf2.ptr.p_double[1]; - for(i=1; i<=p/2-1; i++) - { - ax = buf.ptr.p_double[2*i+0]; - ay = buf.ptr.p_double[2*i+1]; - bx = buf2.ptr.p_double[2*i+0]; - by = buf2.ptr.p_double[2*i+1]; - tx = ax*bx-ay*by; - ty = ax*by+ay*bx; - buf.ptr.p_double[2*i+0] = tx; - buf.ptr.p_double[2*i+1] = ty; - } - fftr1dinvinternaleven(&buf, p, &buf3, &plan, _state); - if( circular ) - { - - /* - * circular, add tail to head - */ - ae_vector_set_length(r, m, _state); - ae_v_move(&r->ptr.p_double[0], 1, &buf.ptr.p_double[0], 1, ae_v_len(0,m-1)); - if( n>=2 ) - { - ae_v_add(&r->ptr.p_double[0], 1, &buf.ptr.p_double[m], 1, ae_v_len(0,n-2)); - } - } - else - { - - /* - * non-circular, just copy - */ - ae_vector_set_length(r, m+n-1, _state); - ae_v_move(&r->ptr.p_double[0], 1, &buf.ptr.p_double[0], 1, ae_v_len(0,m+n-2)); - } - } - ae_frame_leave(_state); - return; - } - - /* - * overlap-add method - */ - if( alg==2 ) - { - ae_assert((q+n-1)%2==0, "ConvR1DX: internal error!", _state); - ae_vector_set_length(&buf, q+n-1, _state); - ae_vector_set_length(&buf2, q+n-1, _state); - ae_vector_set_length(&buf3, q+n-1, _state); - ftcomplexfftplan((q+n-1)/2, 1, &plan, _state); - - /* - * prepare R - */ - if( circular ) - { - ae_vector_set_length(r, m, _state); - for(i=0; i<=m-1; i++) - { - r->ptr.p_double[i] = (double)(0); - } - } - else - { - ae_vector_set_length(r, m+n-1, _state); - for(i=0; i<=m+n-2; i++) - { - r->ptr.p_double[i] = (double)(0); - } - } - - /* - * pre-calculated FFT(B) - */ - ae_v_move(&buf2.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(j=n; j<=q+n-2; j++) - { - buf2.ptr.p_double[j] = (double)(0); - } - fftr1dinternaleven(&buf2, q+n-1, &buf3, &plan, _state); - - /* - * main overlap-add cycle - */ - i = 0; - while(i<=m-1) - { - p = ae_minint(q, m-i, _state); - ae_v_move(&buf.ptr.p_double[0], 1, &a->ptr.p_double[i], 1, ae_v_len(0,p-1)); - for(j=p; j<=q+n-2; j++) - { - buf.ptr.p_double[j] = (double)(0); - } - fftr1dinternaleven(&buf, q+n-1, &buf3, &plan, _state); - buf.ptr.p_double[0] = buf.ptr.p_double[0]*buf2.ptr.p_double[0]; - buf.ptr.p_double[1] = buf.ptr.p_double[1]*buf2.ptr.p_double[1]; - for(j=1; j<=(q+n-1)/2-1; j++) - { - ax = buf.ptr.p_double[2*j+0]; - ay = buf.ptr.p_double[2*j+1]; - bx = buf2.ptr.p_double[2*j+0]; - by = buf2.ptr.p_double[2*j+1]; - tx = ax*bx-ay*by; - ty = ax*by+ay*bx; - buf.ptr.p_double[2*j+0] = tx; - buf.ptr.p_double[2*j+1] = ty; - } - fftr1dinvinternaleven(&buf, q+n-1, &buf3, &plan, _state); - if( circular ) - { - j1 = ae_minint(i+p+n-2, m-1, _state)-i; - j2 = j1+1; - } - else - { - j1 = p+n-2; - j2 = j1+1; - } - ae_v_add(&r->ptr.p_double[i], 1, &buf.ptr.p_double[0], 1, ae_v_len(i,i+j1)); - if( p+n-2>=j2 ) - { - ae_v_add(&r->ptr.p_double[0], 1, &buf.ptr.p_double[j2], 1, ae_v_len(0,p+n-2-j2)); - } - i = i+p; - } - ae_frame_leave(_state); - return; - } - ae_frame_leave(_state); -} - - -#endif -#if defined(AE_COMPILE_CORR) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -1-dimensional complex cross-correlation. - -For given Pattern/Signal returns corr(Pattern,Signal) (non-circular). - -Correlation is calculated using reduction to convolution. Algorithm with -max(N,N)*log(max(N,N)) complexity is used (see ConvC1D() for more info -about performance). - -IMPORTANT: - for historical reasons subroutine accepts its parameters in reversed - order: CorrC1D(Signal, Pattern) = Pattern x Signal (using traditional - definition of cross-correlation, denoting cross-correlation as "x"). - -INPUT PARAMETERS - Signal - array[0..N-1] - complex function to be transformed, - signal containing pattern - N - problem size - Pattern - array[0..M-1] - complex function to be transformed, - pattern to search withing signal - M - problem size - -OUTPUT PARAMETERS - R - cross-correlation, array[0..N+M-2]: - * positive lags are stored in R[0..N-1], - R[i] = sum(conj(pattern[j])*signal[i+j] - * negative lags are stored in R[N..N+M-2], - R[N+M-1-i] = sum(conj(pattern[j])*signal[-i+j] - -NOTE: - It is assumed that pattern domain is [0..M-1]. If Pattern is non-zero -on [-K..M-1], you can still use this subroutine, just shift result by K. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void corrc1d(/* Complex */ ae_vector* signal, - ae_int_t n, - /* Complex */ ae_vector* pattern, - ae_int_t m, - /* Complex */ ae_vector* r, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector p; - ae_vector b; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&p, 0, sizeof(p)); - memset(&b, 0, sizeof(b)); - ae_vector_clear(r); - ae_vector_init(&p, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&b, 0, DT_COMPLEX, _state, ae_true); - - ae_assert(n>0&&m>0, "CorrC1D: incorrect N or M!", _state); - ae_vector_set_length(&p, m, _state); - for(i=0; i<=m-1; i++) - { - p.ptr.p_complex[m-1-i] = ae_c_conj(pattern->ptr.p_complex[i], _state); - } - convc1d(&p, m, signal, n, &b, _state); - ae_vector_set_length(r, m+n-1, _state); - ae_v_cmove(&r->ptr.p_complex[0], 1, &b.ptr.p_complex[m-1], 1, "N", ae_v_len(0,n-1)); - if( m+n-2>=n ) - { - ae_v_cmove(&r->ptr.p_complex[n], 1, &b.ptr.p_complex[0], 1, "N", ae_v_len(n,m+n-2)); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -1-dimensional circular complex cross-correlation. - -For given Pattern/Signal returns corr(Pattern,Signal) (circular). -Algorithm has linearithmic complexity for any M/N. - -IMPORTANT: - for historical reasons subroutine accepts its parameters in reversed - order: CorrC1DCircular(Signal, Pattern) = Pattern x Signal (using - traditional definition of cross-correlation, denoting cross-correlation - as "x"). - -INPUT PARAMETERS - Signal - array[0..N-1] - complex function to be transformed, - periodic signal containing pattern - N - problem size - Pattern - array[0..M-1] - complex function to be transformed, - non-periodic pattern to search withing signal - M - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..M-1]. - - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void corrc1dcircular(/* Complex */ ae_vector* signal, - ae_int_t m, - /* Complex */ ae_vector* pattern, - ae_int_t n, - /* Complex */ ae_vector* c, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector p; - ae_vector b; - ae_int_t i1; - ae_int_t i2; - ae_int_t i; - ae_int_t j2; - - ae_frame_make(_state, &_frame_block); - memset(&p, 0, sizeof(p)); - memset(&b, 0, sizeof(b)); - ae_vector_clear(c); - ae_vector_init(&p, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&b, 0, DT_COMPLEX, _state, ae_true); - - ae_assert(n>0&&m>0, "ConvC1DCircular: incorrect N or M!", _state); - - /* - * normalize task: make M>=N, - * so A will be longer (at least - not shorter) that B. - */ - if( mptr.p_complex[i1], 1, "N", ae_v_len(0,j2)); - i1 = i1+m; - } - corrc1dcircular(signal, m, &b, m, c, _state); - ae_frame_leave(_state); - return; - } - - /* - * Task is normalized - */ - ae_vector_set_length(&p, n, _state); - for(i=0; i<=n-1; i++) - { - p.ptr.p_complex[n-1-i] = ae_c_conj(pattern->ptr.p_complex[i], _state); - } - convc1dcircular(signal, m, &p, n, &b, _state); - ae_vector_set_length(c, m, _state); - ae_v_cmove(&c->ptr.p_complex[0], 1, &b.ptr.p_complex[n-1], 1, "N", ae_v_len(0,m-n)); - if( m-n+1<=m-1 ) - { - ae_v_cmove(&c->ptr.p_complex[m-n+1], 1, &b.ptr.p_complex[0], 1, "N", ae_v_len(m-n+1,m-1)); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -1-dimensional real cross-correlation. - -For given Pattern/Signal returns corr(Pattern,Signal) (non-circular). - -Correlation is calculated using reduction to convolution. Algorithm with -max(N,N)*log(max(N,N)) complexity is used (see ConvC1D() for more info -about performance). - -IMPORTANT: - for historical reasons subroutine accepts its parameters in reversed - order: CorrR1D(Signal, Pattern) = Pattern x Signal (using traditional - definition of cross-correlation, denoting cross-correlation as "x"). - -INPUT PARAMETERS - Signal - array[0..N-1] - real function to be transformed, - signal containing pattern - N - problem size - Pattern - array[0..M-1] - real function to be transformed, - pattern to search withing signal - M - problem size - -OUTPUT PARAMETERS - R - cross-correlation, array[0..N+M-2]: - * positive lags are stored in R[0..N-1], - R[i] = sum(pattern[j]*signal[i+j] - * negative lags are stored in R[N..N+M-2], - R[N+M-1-i] = sum(pattern[j]*signal[-i+j] - -NOTE: - It is assumed that pattern domain is [0..M-1]. If Pattern is non-zero -on [-K..M-1], you can still use this subroutine, just shift result by K. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void corrr1d(/* Real */ ae_vector* signal, - ae_int_t n, - /* Real */ ae_vector* pattern, - ae_int_t m, - /* Real */ ae_vector* r, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector p; - ae_vector b; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&p, 0, sizeof(p)); - memset(&b, 0, sizeof(b)); - ae_vector_clear(r); - ae_vector_init(&p, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - - ae_assert(n>0&&m>0, "CorrR1D: incorrect N or M!", _state); - ae_vector_set_length(&p, m, _state); - for(i=0; i<=m-1; i++) - { - p.ptr.p_double[m-1-i] = pattern->ptr.p_double[i]; - } - convr1d(&p, m, signal, n, &b, _state); - ae_vector_set_length(r, m+n-1, _state); - ae_v_move(&r->ptr.p_double[0], 1, &b.ptr.p_double[m-1], 1, ae_v_len(0,n-1)); - if( m+n-2>=n ) - { - ae_v_move(&r->ptr.p_double[n], 1, &b.ptr.p_double[0], 1, ae_v_len(n,m+n-2)); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -1-dimensional circular real cross-correlation. - -For given Pattern/Signal returns corr(Pattern,Signal) (circular). -Algorithm has linearithmic complexity for any M/N. - -IMPORTANT: - for historical reasons subroutine accepts its parameters in reversed - order: CorrR1DCircular(Signal, Pattern) = Pattern x Signal (using - traditional definition of cross-correlation, denoting cross-correlation - as "x"). - -INPUT PARAMETERS - Signal - array[0..N-1] - real function to be transformed, - periodic signal containing pattern - N - problem size - Pattern - array[0..M-1] - real function to be transformed, - non-periodic pattern to search withing signal - M - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..M-1]. - - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void corrr1dcircular(/* Real */ ae_vector* signal, - ae_int_t m, - /* Real */ ae_vector* pattern, - ae_int_t n, - /* Real */ ae_vector* c, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector p; - ae_vector b; - ae_int_t i1; - ae_int_t i2; - ae_int_t i; - ae_int_t j2; - - ae_frame_make(_state, &_frame_block); - memset(&p, 0, sizeof(p)); - memset(&b, 0, sizeof(b)); - ae_vector_clear(c); - ae_vector_init(&p, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - - ae_assert(n>0&&m>0, "ConvC1DCircular: incorrect N or M!", _state); - - /* - * normalize task: make M>=N, - * so A will be longer (at least - not shorter) that B. - */ - if( mptr.p_double[i1], 1, ae_v_len(0,j2)); - i1 = i1+m; - } - corrr1dcircular(signal, m, &b, m, c, _state); - ae_frame_leave(_state); - return; - } - - /* - * Task is normalized - */ - ae_vector_set_length(&p, n, _state); - for(i=0; i<=n-1; i++) - { - p.ptr.p_double[n-1-i] = pattern->ptr.p_double[i]; - } - convr1dcircular(signal, m, &p, n, &b, _state); - ae_vector_set_length(c, m, _state); - ae_v_move(&c->ptr.p_double[0], 1, &b.ptr.p_double[n-1], 1, ae_v_len(0,m-n)); - if( m-n+1<=m-1 ) - { - ae_v_move(&c->ptr.p_double[m-n+1], 1, &b.ptr.p_double[0], 1, ae_v_len(m-n+1,m-1)); - } - ae_frame_leave(_state); -} - - -#endif - -} - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/fasttransforms.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/fasttransforms.h deleted file mode 100644 index 340d482..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/fasttransforms.h +++ /dev/null @@ -1,731 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifndef _fasttransforms_pkg_h -#define _fasttransforms_pkg_h -#include "ap.h" -#include "alglibinternal.h" - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (DATATYPES) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_FFT) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_FHT) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_CONV) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_CORR) || !defined(AE_PARTIAL_BUILD) -#endif - -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_FFT) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_FHT) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_CONV) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_CORR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_FFT) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -1-dimensional complex FFT. - -Array size N may be arbitrary number (composite or prime). Composite N's -are handled with cache-oblivious variation of a Cooley-Tukey algorithm. -Small prime-factors are transformed using hard coded codelets (similar to -FFTW codelets, but without low-level optimization), large prime-factors -are handled with Bluestein's algorithm. - -Fastests transforms are for smooth N's (prime factors are 2, 3, 5 only), -most fast for powers of 2. When N have prime factors larger than these, -but orders of magnitude smaller than N, computations will be about 4 times -slower than for nearby highly composite N's. When N itself is prime, speed -will be 6 times lower. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - A - array[0..N-1] - complex function to be transformed - N - problem size - -OUTPUT PARAMETERS - A - DFT of a input array, array[0..N-1] - A_out[j] = SUM(A_in[k]*exp(-2*pi*sqrt(-1)*j*k/N), k = 0..N-1) - - - -- ALGLIB -- - Copyright 29.05.2009 by Bochkanov Sergey -*************************************************************************/ -void fftc1d(complex_1d_array &a, const ae_int_t n, const xparams _xparams = alglib::xdefault); -void fftc1d(complex_1d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -1-dimensional complex inverse FFT. - -Array size N may be arbitrary number (composite or prime). Algorithm has -O(N*logN) complexity for any N (composite or prime). - -See FFTC1D() description for more information about algorithm performance. - -INPUT PARAMETERS - A - array[0..N-1] - complex array to be transformed - N - problem size - -OUTPUT PARAMETERS - A - inverse DFT of a input array, array[0..N-1] - A_out[j] = SUM(A_in[k]/N*exp(+2*pi*sqrt(-1)*j*k/N), k = 0..N-1) - - - -- ALGLIB -- - Copyright 29.05.2009 by Bochkanov Sergey -*************************************************************************/ -void fftc1dinv(complex_1d_array &a, const ae_int_t n, const xparams _xparams = alglib::xdefault); -void fftc1dinv(complex_1d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -1-dimensional real FFT. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - A - array[0..N-1] - real function to be transformed - N - problem size - -OUTPUT PARAMETERS - F - DFT of a input array, array[0..N-1] - F[j] = SUM(A[k]*exp(-2*pi*sqrt(-1)*j*k/N), k = 0..N-1) - -NOTE: - F[] satisfies symmetry property F[k] = conj(F[N-k]), so just one half -of array is usually needed. But for convinience subroutine returns full -complex array (with frequencies above N/2), so its result may be used by -other FFT-related subroutines. - - - -- ALGLIB -- - Copyright 01.06.2009 by Bochkanov Sergey -*************************************************************************/ -void fftr1d(const real_1d_array &a, const ae_int_t n, complex_1d_array &f, const xparams _xparams = alglib::xdefault); -void fftr1d(const real_1d_array &a, complex_1d_array &f, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -1-dimensional real inverse FFT. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - F - array[0..floor(N/2)] - frequencies from forward real FFT - N - problem size - -OUTPUT PARAMETERS - A - inverse DFT of a input array, array[0..N-1] - -NOTE: - F[] should satisfy symmetry property F[k] = conj(F[N-k]), so just one -half of frequencies array is needed - elements from 0 to floor(N/2). F[0] -is ALWAYS real. If N is even F[floor(N/2)] is real too. If N is odd, then -F[floor(N/2)] has no special properties. - -Relying on properties noted above, FFTR1DInv subroutine uses only elements -from 0th to floor(N/2)-th. It ignores imaginary part of F[0], and in case -N is even it ignores imaginary part of F[floor(N/2)] too. - -When you call this function using full arguments list - "FFTR1DInv(F,N,A)" -- you can pass either either frequencies array with N elements or reduced -array with roughly N/2 elements - subroutine will successfully transform -both. - -If you call this function using reduced arguments list - "FFTR1DInv(F,A)" -- you must pass FULL array with N elements (although higher N/2 are still -not used) because array size is used to automatically determine FFT length - - - -- ALGLIB -- - Copyright 01.06.2009 by Bochkanov Sergey -*************************************************************************/ -void fftr1dinv(const complex_1d_array &f, const ae_int_t n, real_1d_array &a, const xparams _xparams = alglib::xdefault); -void fftr1dinv(const complex_1d_array &f, real_1d_array &a, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_FHT) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -1-dimensional Fast Hartley Transform. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - A - array[0..N-1] - real function to be transformed - N - problem size - -OUTPUT PARAMETERS - A - FHT of a input array, array[0..N-1], - A_out[k] = sum(A_in[j]*(cos(2*pi*j*k/N)+sin(2*pi*j*k/N)), j=0..N-1) - - - -- ALGLIB -- - Copyright 04.06.2009 by Bochkanov Sergey -*************************************************************************/ -void fhtr1d(real_1d_array &a, const ae_int_t n, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -1-dimensional inverse FHT. - -Algorithm has O(N*logN) complexity for any N (composite or prime). - -INPUT PARAMETERS - A - array[0..N-1] - complex array to be transformed - N - problem size - -OUTPUT PARAMETERS - A - inverse FHT of a input array, array[0..N-1] - - - -- ALGLIB -- - Copyright 29.05.2009 by Bochkanov Sergey -*************************************************************************/ -void fhtr1dinv(real_1d_array &a, const ae_int_t n, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_CONV) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -1-dimensional complex convolution. - -For given A/B returns conv(A,B) (non-circular). Subroutine can automatically -choose between three implementations: straightforward O(M*N) formula for -very small N (or M), overlap-add algorithm for cases where max(M,N) is -significantly larger than min(M,N), but O(M*N) algorithm is too slow, and -general FFT-based formula for cases where two previois algorithms are too -slow. - -Algorithm has max(M,N)*log(max(M,N)) complexity for any M/N. - -INPUT PARAMETERS - A - array[0..M-1] - complex function to be transformed - M - problem size - B - array[0..N-1] - complex function to be transformed - N - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..N+M-2]. - -NOTE: - It is assumed that A is zero at T<0, B is zero too. If one or both -functions have non-zero values at negative T's, you can still use this -subroutine - just shift its result correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convc1d(const complex_1d_array &a, const ae_int_t m, const complex_1d_array &b, const ae_int_t n, complex_1d_array &r, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -1-dimensional complex non-circular deconvolution (inverse of ConvC1D()). - -Algorithm has M*log(M)) complexity for any M (composite or prime). - -INPUT PARAMETERS - A - array[0..M-1] - convolved signal, A = conv(R, B) - M - convolved signal length - B - array[0..N-1] - response - N - response length, N<=M - -OUTPUT PARAMETERS - R - deconvolved signal. array[0..M-N]. - -NOTE: - deconvolution is unstable process and may result in division by zero -(if your response function is degenerate, i.e. has zero Fourier coefficient). - -NOTE: - It is assumed that A is zero at T<0, B is zero too. If one or both -functions have non-zero values at negative T's, you can still use this -subroutine - just shift its result correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convc1dinv(const complex_1d_array &a, const ae_int_t m, const complex_1d_array &b, const ae_int_t n, complex_1d_array &r, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -1-dimensional circular complex convolution. - -For given S/R returns conv(S,R) (circular). Algorithm has linearithmic -complexity for any M/N. - -IMPORTANT: normal convolution is commutative, i.e. it is symmetric - -conv(A,B)=conv(B,A). Cyclic convolution IS NOT. One function - S - is a -signal, periodic function, and another - R - is a response, non-periodic -function with limited length. - -INPUT PARAMETERS - S - array[0..M-1] - complex periodic signal - M - problem size - B - array[0..N-1] - complex non-periodic response - N - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..M-1]. - -NOTE: - It is assumed that B is zero at T<0. If it has non-zero values at -negative T's, you can still use this subroutine - just shift its result -correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convc1dcircular(const complex_1d_array &s, const ae_int_t m, const complex_1d_array &r, const ae_int_t n, complex_1d_array &c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -1-dimensional circular complex deconvolution (inverse of ConvC1DCircular()). - -Algorithm has M*log(M)) complexity for any M (composite or prime). - -INPUT PARAMETERS - A - array[0..M-1] - convolved periodic signal, A = conv(R, B) - M - convolved signal length - B - array[0..N-1] - non-periodic response - N - response length - -OUTPUT PARAMETERS - R - deconvolved signal. array[0..M-1]. - -NOTE: - deconvolution is unstable process and may result in division by zero -(if your response function is degenerate, i.e. has zero Fourier coefficient). - -NOTE: - It is assumed that B is zero at T<0. If it has non-zero values at -negative T's, you can still use this subroutine - just shift its result -correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convc1dcircularinv(const complex_1d_array &a, const ae_int_t m, const complex_1d_array &b, const ae_int_t n, complex_1d_array &r, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -1-dimensional real convolution. - -Analogous to ConvC1D(), see ConvC1D() comments for more details. - -INPUT PARAMETERS - A - array[0..M-1] - real function to be transformed - M - problem size - B - array[0..N-1] - real function to be transformed - N - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..N+M-2]. - -NOTE: - It is assumed that A is zero at T<0, B is zero too. If one or both -functions have non-zero values at negative T's, you can still use this -subroutine - just shift its result correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convr1d(const real_1d_array &a, const ae_int_t m, const real_1d_array &b, const ae_int_t n, real_1d_array &r, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -1-dimensional real deconvolution (inverse of ConvC1D()). - -Algorithm has M*log(M)) complexity for any M (composite or prime). - -INPUT PARAMETERS - A - array[0..M-1] - convolved signal, A = conv(R, B) - M - convolved signal length - B - array[0..N-1] - response - N - response length, N<=M - -OUTPUT PARAMETERS - R - deconvolved signal. array[0..M-N]. - -NOTE: - deconvolution is unstable process and may result in division by zero -(if your response function is degenerate, i.e. has zero Fourier coefficient). - -NOTE: - It is assumed that A is zero at T<0, B is zero too. If one or both -functions have non-zero values at negative T's, you can still use this -subroutine - just shift its result correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convr1dinv(const real_1d_array &a, const ae_int_t m, const real_1d_array &b, const ae_int_t n, real_1d_array &r, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -1-dimensional circular real convolution. - -Analogous to ConvC1DCircular(), see ConvC1DCircular() comments for more details. - -INPUT PARAMETERS - S - array[0..M-1] - real signal - M - problem size - B - array[0..N-1] - real response - N - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..M-1]. - -NOTE: - It is assumed that B is zero at T<0. If it has non-zero values at -negative T's, you can still use this subroutine - just shift its result -correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convr1dcircular(const real_1d_array &s, const ae_int_t m, const real_1d_array &r, const ae_int_t n, real_1d_array &c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -1-dimensional complex deconvolution (inverse of ConvC1D()). - -Algorithm has M*log(M)) complexity for any M (composite or prime). - -INPUT PARAMETERS - A - array[0..M-1] - convolved signal, A = conv(R, B) - M - convolved signal length - B - array[0..N-1] - response - N - response length - -OUTPUT PARAMETERS - R - deconvolved signal. array[0..M-N]. - -NOTE: - deconvolution is unstable process and may result in division by zero -(if your response function is degenerate, i.e. has zero Fourier coefficient). - -NOTE: - It is assumed that B is zero at T<0. If it has non-zero values at -negative T's, you can still use this subroutine - just shift its result -correspondingly. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void convr1dcircularinv(const real_1d_array &a, const ae_int_t m, const real_1d_array &b, const ae_int_t n, real_1d_array &r, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_CORR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -1-dimensional complex cross-correlation. - -For given Pattern/Signal returns corr(Pattern,Signal) (non-circular). - -Correlation is calculated using reduction to convolution. Algorithm with -max(N,N)*log(max(N,N)) complexity is used (see ConvC1D() for more info -about performance). - -IMPORTANT: - for historical reasons subroutine accepts its parameters in reversed - order: CorrC1D(Signal, Pattern) = Pattern x Signal (using traditional - definition of cross-correlation, denoting cross-correlation as "x"). - -INPUT PARAMETERS - Signal - array[0..N-1] - complex function to be transformed, - signal containing pattern - N - problem size - Pattern - array[0..M-1] - complex function to be transformed, - pattern to search withing signal - M - problem size - -OUTPUT PARAMETERS - R - cross-correlation, array[0..N+M-2]: - * positive lags are stored in R[0..N-1], - R[i] = sum(conj(pattern[j])*signal[i+j] - * negative lags are stored in R[N..N+M-2], - R[N+M-1-i] = sum(conj(pattern[j])*signal[-i+j] - -NOTE: - It is assumed that pattern domain is [0..M-1]. If Pattern is non-zero -on [-K..M-1], you can still use this subroutine, just shift result by K. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void corrc1d(const complex_1d_array &signal, const ae_int_t n, const complex_1d_array &pattern, const ae_int_t m, complex_1d_array &r, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -1-dimensional circular complex cross-correlation. - -For given Pattern/Signal returns corr(Pattern,Signal) (circular). -Algorithm has linearithmic complexity for any M/N. - -IMPORTANT: - for historical reasons subroutine accepts its parameters in reversed - order: CorrC1DCircular(Signal, Pattern) = Pattern x Signal (using - traditional definition of cross-correlation, denoting cross-correlation - as "x"). - -INPUT PARAMETERS - Signal - array[0..N-1] - complex function to be transformed, - periodic signal containing pattern - N - problem size - Pattern - array[0..M-1] - complex function to be transformed, - non-periodic pattern to search withing signal - M - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..M-1]. - - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void corrc1dcircular(const complex_1d_array &signal, const ae_int_t m, const complex_1d_array &pattern, const ae_int_t n, complex_1d_array &c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -1-dimensional real cross-correlation. - -For given Pattern/Signal returns corr(Pattern,Signal) (non-circular). - -Correlation is calculated using reduction to convolution. Algorithm with -max(N,N)*log(max(N,N)) complexity is used (see ConvC1D() for more info -about performance). - -IMPORTANT: - for historical reasons subroutine accepts its parameters in reversed - order: CorrR1D(Signal, Pattern) = Pattern x Signal (using traditional - definition of cross-correlation, denoting cross-correlation as "x"). - -INPUT PARAMETERS - Signal - array[0..N-1] - real function to be transformed, - signal containing pattern - N - problem size - Pattern - array[0..M-1] - real function to be transformed, - pattern to search withing signal - M - problem size - -OUTPUT PARAMETERS - R - cross-correlation, array[0..N+M-2]: - * positive lags are stored in R[0..N-1], - R[i] = sum(pattern[j]*signal[i+j] - * negative lags are stored in R[N..N+M-2], - R[N+M-1-i] = sum(pattern[j]*signal[-i+j] - -NOTE: - It is assumed that pattern domain is [0..M-1]. If Pattern is non-zero -on [-K..M-1], you can still use this subroutine, just shift result by K. - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void corrr1d(const real_1d_array &signal, const ae_int_t n, const real_1d_array &pattern, const ae_int_t m, real_1d_array &r, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -1-dimensional circular real cross-correlation. - -For given Pattern/Signal returns corr(Pattern,Signal) (circular). -Algorithm has linearithmic complexity for any M/N. - -IMPORTANT: - for historical reasons subroutine accepts its parameters in reversed - order: CorrR1DCircular(Signal, Pattern) = Pattern x Signal (using - traditional definition of cross-correlation, denoting cross-correlation - as "x"). - -INPUT PARAMETERS - Signal - array[0..N-1] - real function to be transformed, - periodic signal containing pattern - N - problem size - Pattern - array[0..M-1] - real function to be transformed, - non-periodic pattern to search withing signal - M - problem size - -OUTPUT PARAMETERS - R - convolution: A*B. array[0..M-1]. - - - -- ALGLIB -- - Copyright 21.07.2009 by Bochkanov Sergey -*************************************************************************/ -void corrr1dcircular(const real_1d_array &signal, const ae_int_t m, const real_1d_array &pattern, const ae_int_t n, real_1d_array &c, const xparams _xparams = alglib::xdefault); -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (FUNCTIONS) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_FFT) || !defined(AE_PARTIAL_BUILD) -void fftc1d(/* Complex */ ae_vector* a, ae_int_t n, ae_state *_state); -void fftc1dinv(/* Complex */ ae_vector* a, ae_int_t n, ae_state *_state); -void fftr1d(/* Real */ ae_vector* a, - ae_int_t n, - /* Complex */ ae_vector* f, - ae_state *_state); -void fftr1dinv(/* Complex */ ae_vector* f, - ae_int_t n, - /* Real */ ae_vector* a, - ae_state *_state); -void fftr1dinternaleven(/* Real */ ae_vector* a, - ae_int_t n, - /* Real */ ae_vector* buf, - fasttransformplan* plan, - ae_state *_state); -void fftr1dinvinternaleven(/* Real */ ae_vector* a, - ae_int_t n, - /* Real */ ae_vector* buf, - fasttransformplan* plan, - ae_state *_state); -#endif -#if defined(AE_COMPILE_FHT) || !defined(AE_PARTIAL_BUILD) -void fhtr1d(/* Real */ ae_vector* a, ae_int_t n, ae_state *_state); -void fhtr1dinv(/* Real */ ae_vector* a, ae_int_t n, ae_state *_state); -#endif -#if defined(AE_COMPILE_CONV) || !defined(AE_PARTIAL_BUILD) -void convc1d(/* Complex */ ae_vector* a, - ae_int_t m, - /* Complex */ ae_vector* b, - ae_int_t n, - /* Complex */ ae_vector* r, - ae_state *_state); -void convc1dinv(/* Complex */ ae_vector* a, - ae_int_t m, - /* Complex */ ae_vector* b, - ae_int_t n, - /* Complex */ ae_vector* r, - ae_state *_state); -void convc1dcircular(/* Complex */ ae_vector* s, - ae_int_t m, - /* Complex */ ae_vector* r, - ae_int_t n, - /* Complex */ ae_vector* c, - ae_state *_state); -void convc1dcircularinv(/* Complex */ ae_vector* a, - ae_int_t m, - /* Complex */ ae_vector* b, - ae_int_t n, - /* Complex */ ae_vector* r, - ae_state *_state); -void convr1d(/* Real */ ae_vector* a, - ae_int_t m, - /* Real */ ae_vector* b, - ae_int_t n, - /* Real */ ae_vector* r, - ae_state *_state); -void convr1dinv(/* Real */ ae_vector* a, - ae_int_t m, - /* Real */ ae_vector* b, - ae_int_t n, - /* Real */ ae_vector* r, - ae_state *_state); -void convr1dcircular(/* Real */ ae_vector* s, - ae_int_t m, - /* Real */ ae_vector* r, - ae_int_t n, - /* Real */ ae_vector* c, - ae_state *_state); -void convr1dcircularinv(/* Real */ ae_vector* a, - ae_int_t m, - /* Real */ ae_vector* b, - ae_int_t n, - /* Real */ ae_vector* r, - ae_state *_state); -void convc1dx(/* Complex */ ae_vector* a, - ae_int_t m, - /* Complex */ ae_vector* b, - ae_int_t n, - ae_bool circular, - ae_int_t alg, - ae_int_t q, - /* Complex */ ae_vector* r, - ae_state *_state); -void convr1dx(/* Real */ ae_vector* a, - ae_int_t m, - /* Real */ ae_vector* b, - ae_int_t n, - ae_bool circular, - ae_int_t alg, - ae_int_t q, - /* Real */ ae_vector* r, - ae_state *_state); -#endif -#if defined(AE_COMPILE_CORR) || !defined(AE_PARTIAL_BUILD) -void corrc1d(/* Complex */ ae_vector* signal, - ae_int_t n, - /* Complex */ ae_vector* pattern, - ae_int_t m, - /* Complex */ ae_vector* r, - ae_state *_state); -void corrc1dcircular(/* Complex */ ae_vector* signal, - ae_int_t m, - /* Complex */ ae_vector* pattern, - ae_int_t n, - /* Complex */ ae_vector* c, - ae_state *_state); -void corrr1d(/* Real */ ae_vector* signal, - ae_int_t n, - /* Real */ ae_vector* pattern, - ae_int_t m, - /* Real */ ae_vector* r, - ae_state *_state); -void corrr1dcircular(/* Real */ ae_vector* signal, - ae_int_t m, - /* Real */ ae_vector* pattern, - ae_int_t n, - /* Real */ ae_vector* c, - ae_state *_state); -#endif - -} -#endif - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/integration.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/integration.cpp deleted file mode 100644 index 3f946b2..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/integration.cpp +++ /dev/null @@ -1,4240 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifdef _MSC_VER -#define _CRT_SECURE_NO_WARNINGS -#endif -#include "stdafx.h" -#include "integration.h" - -// disable some irrelevant warnings -#if (AE_COMPILER==AE_MSVC) && !defined(AE_ALL_WARNINGS) -#pragma warning(disable:4100) -#pragma warning(disable:4127) -#pragma warning(disable:4611) -#pragma warning(disable:4702) -#pragma warning(disable:4996) -#endif - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_GQ) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_GKQ) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_AUTOGK) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_GQ) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Computation of nodes and weights for a Gauss quadrature formula - -The algorithm generates the N-point Gauss quadrature formula with weight -function given by coefficients alpha and beta of a recurrence relation -which generates a system of orthogonal polynomials: - -P-1(x) = 0 -P0(x) = 1 -Pn+1(x) = (x-alpha(n))*Pn(x) - beta(n)*Pn-1(x) - -and zeroth moment Mu0 - -Mu0 = integral(W(x)dx,a,b) - -INPUT PARAMETERS: - Alpha - array[0..N-1], alpha coefficients - Beta - array[0..N-1], beta coefficients - Zero-indexed element is not used and may be arbitrary. - Beta[I]>0. - Mu0 - zeroth moment of the weight function. - N - number of nodes of the quadrature formula, N>=1 - -OUTPUT PARAMETERS: - Info - error code: - * -3 internal eigenproblem solver hasn't converged - * -2 Beta[i]<=0 - * -1 incorrect N was passed - * 1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - -- ALGLIB -- - Copyright 2005-2009 by Bochkanov Sergey -*************************************************************************/ -void gqgeneraterec(const real_1d_array &alpha, const real_1d_array &beta, const double mu0, const ae_int_t n, ae_int_t &info, real_1d_array &x, real_1d_array &w, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::gqgeneraterec(const_cast(alpha.c_ptr()), const_cast(beta.c_ptr()), mu0, n, &info, const_cast(x.c_ptr()), const_cast(w.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Computation of nodes and weights for a Gauss-Lobatto quadrature formula - -The algorithm generates the N-point Gauss-Lobatto quadrature formula with -weight function given by coefficients alpha and beta of a recurrence which -generates a system of orthogonal polynomials. - -P-1(x) = 0 -P0(x) = 1 -Pn+1(x) = (x-alpha(n))*Pn(x) - beta(n)*Pn-1(x) - -and zeroth moment Mu0 - -Mu0 = integral(W(x)dx,a,b) - -INPUT PARAMETERS: - Alpha - array[0..N-2], alpha coefficients - Beta - array[0..N-2], beta coefficients. - Zero-indexed element is not used, may be arbitrary. - Beta[I]>0 - Mu0 - zeroth moment of the weighting function. - A - left boundary of the integration interval. - B - right boundary of the integration interval. - N - number of nodes of the quadrature formula, N>=3 - (including the left and right boundary nodes). - -OUTPUT PARAMETERS: - Info - error code: - * -3 internal eigenproblem solver hasn't converged - * -2 Beta[i]<=0 - * -1 incorrect N was passed - * 1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - -- ALGLIB -- - Copyright 2005-2009 by Bochkanov Sergey -*************************************************************************/ -void gqgenerategausslobattorec(const real_1d_array &alpha, const real_1d_array &beta, const double mu0, const double a, const double b, const ae_int_t n, ae_int_t &info, real_1d_array &x, real_1d_array &w, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::gqgenerategausslobattorec(const_cast(alpha.c_ptr()), const_cast(beta.c_ptr()), mu0, a, b, n, &info, const_cast(x.c_ptr()), const_cast(w.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Computation of nodes and weights for a Gauss-Radau quadrature formula - -The algorithm generates the N-point Gauss-Radau quadrature formula with -weight function given by the coefficients alpha and beta of a recurrence -which generates a system of orthogonal polynomials. - -P-1(x) = 0 -P0(x) = 1 -Pn+1(x) = (x-alpha(n))*Pn(x) - beta(n)*Pn-1(x) - -and zeroth moment Mu0 - -Mu0 = integral(W(x)dx,a,b) - -INPUT PARAMETERS: - Alpha - array[0..N-2], alpha coefficients. - Beta - array[0..N-1], beta coefficients - Zero-indexed element is not used. - Beta[I]>0 - Mu0 - zeroth moment of the weighting function. - A - left boundary of the integration interval. - N - number of nodes of the quadrature formula, N>=2 - (including the left boundary node). - -OUTPUT PARAMETERS: - Info - error code: - * -3 internal eigenproblem solver hasn't converged - * -2 Beta[i]<=0 - * -1 incorrect N was passed - * 1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - - -- ALGLIB -- - Copyright 2005-2009 by Bochkanov Sergey -*************************************************************************/ -void gqgenerategaussradaurec(const real_1d_array &alpha, const real_1d_array &beta, const double mu0, const double a, const ae_int_t n, ae_int_t &info, real_1d_array &x, real_1d_array &w, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::gqgenerategaussradaurec(const_cast(alpha.c_ptr()), const_cast(beta.c_ptr()), mu0, a, n, &info, const_cast(x.c_ptr()), const_cast(w.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Returns nodes/weights for Gauss-Legendre quadrature on [-1,1] with N -nodes. - -INPUT PARAMETERS: - N - number of nodes, >=1 - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. N is too large to obtain - weights/nodes with high enough accuracy. - Try to use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gqgenerategausslegendre(const ae_int_t n, ae_int_t &info, real_1d_array &x, real_1d_array &w, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::gqgenerategausslegendre(n, &info, const_cast(x.c_ptr()), const_cast(w.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Returns nodes/weights for Gauss-Jacobi quadrature on [-1,1] with weight -function W(x)=Power(1-x,Alpha)*Power(1+x,Beta). - -INPUT PARAMETERS: - N - number of nodes, >=1 - Alpha - power-law coefficient, Alpha>-1 - Beta - power-law coefficient, Beta>-1 - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. Alpha or Beta are too close - to -1 to obtain weights/nodes with high enough - accuracy, or, may be, N is too large. Try to - use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N/Alpha/Beta was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gqgenerategaussjacobi(const ae_int_t n, const double alpha, const double beta, ae_int_t &info, real_1d_array &x, real_1d_array &w, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::gqgenerategaussjacobi(n, alpha, beta, &info, const_cast(x.c_ptr()), const_cast(w.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Returns nodes/weights for Gauss-Laguerre quadrature on [0,+inf) with -weight function W(x)=Power(x,Alpha)*Exp(-x) - -INPUT PARAMETERS: - N - number of nodes, >=1 - Alpha - power-law coefficient, Alpha>-1 - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. Alpha is too close to -1 to - obtain weights/nodes with high enough accuracy - or, may be, N is too large. Try to use - multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N/Alpha was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gqgenerategausslaguerre(const ae_int_t n, const double alpha, ae_int_t &info, real_1d_array &x, real_1d_array &w, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::gqgenerategausslaguerre(n, alpha, &info, const_cast(x.c_ptr()), const_cast(w.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Returns nodes/weights for Gauss-Hermite quadrature on (-inf,+inf) with -weight function W(x)=Exp(-x*x) - -INPUT PARAMETERS: - N - number of nodes, >=1 - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. May be, N is too large. Try to - use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N/Alpha was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gqgenerategausshermite(const ae_int_t n, ae_int_t &info, real_1d_array &x, real_1d_array &w, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::gqgenerategausshermite(n, &info, const_cast(x.c_ptr()), const_cast(w.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_GKQ) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Computation of nodes and weights of a Gauss-Kronrod quadrature formula - -The algorithm generates the N-point Gauss-Kronrod quadrature formula with -weight function given by coefficients alpha and beta of a recurrence -relation which generates a system of orthogonal polynomials: - - P-1(x) = 0 - P0(x) = 1 - Pn+1(x) = (x-alpha(n))*Pn(x) - beta(n)*Pn-1(x) - -and zero moment Mu0 - - Mu0 = integral(W(x)dx,a,b) - - -INPUT PARAMETERS: - Alpha - alpha coefficients, array[0..floor(3*K/2)]. - Beta - beta coefficients, array[0..ceil(3*K/2)]. - Beta[0] is not used and may be arbitrary. - Beta[I]>0. - Mu0 - zeroth moment of the weight function. - N - number of nodes of the Gauss-Kronrod quadrature formula, - N >= 3, - N = 2*K+1. - -OUTPUT PARAMETERS: - Info - error code: - * -5 no real and positive Gauss-Kronrod formula can - be created for such a weight function with a - given number of nodes. - * -4 N is too large, task may be ill conditioned - - x[i]=x[i+1] found. - * -3 internal eigenproblem solver hasn't converged - * -2 Beta[i]<=0 - * -1 incorrect N was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - WKronrod - array[0..N-1] - Kronrod weights - WGauss - array[0..N-1] - Gauss weights (interleaved with zeros - corresponding to extended Kronrod nodes). - - -- ALGLIB -- - Copyright 08.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gkqgeneraterec(const real_1d_array &alpha, const real_1d_array &beta, const double mu0, const ae_int_t n, ae_int_t &info, real_1d_array &x, real_1d_array &wkronrod, real_1d_array &wgauss, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::gkqgeneraterec(const_cast(alpha.c_ptr()), const_cast(beta.c_ptr()), mu0, n, &info, const_cast(x.c_ptr()), const_cast(wkronrod.c_ptr()), const_cast(wgauss.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Returns Gauss and Gauss-Kronrod nodes/weights for Gauss-Legendre -quadrature with N points. - -GKQLegendreCalc (calculation) or GKQLegendreTbl (precomputed table) is -used depending on machine precision and number of nodes. - -INPUT PARAMETERS: - N - number of Kronrod nodes, must be odd number, >=3. - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. N is too large to obtain - weights/nodes with high enough accuracy. - Try to use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, ordered in - ascending order. - WKronrod - array[0..N-1] - Kronrod weights - WGauss - array[0..N-1] - Gauss weights (interleaved with zeros - corresponding to extended Kronrod nodes). - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gkqgenerategausslegendre(const ae_int_t n, ae_int_t &info, real_1d_array &x, real_1d_array &wkronrod, real_1d_array &wgauss, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::gkqgenerategausslegendre(n, &info, const_cast(x.c_ptr()), const_cast(wkronrod.c_ptr()), const_cast(wgauss.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Returns Gauss and Gauss-Kronrod nodes/weights for Gauss-Jacobi -quadrature on [-1,1] with weight function - - W(x)=Power(1-x,Alpha)*Power(1+x,Beta). - -INPUT PARAMETERS: - N - number of Kronrod nodes, must be odd number, >=3. - Alpha - power-law coefficient, Alpha>-1 - Beta - power-law coefficient, Beta>-1 - -OUTPUT PARAMETERS: - Info - error code: - * -5 no real and positive Gauss-Kronrod formula can - be created for such a weight function with a - given number of nodes. - * -4 an error was detected when calculating - weights/nodes. Alpha or Beta are too close - to -1 to obtain weights/nodes with high enough - accuracy, or, may be, N is too large. Try to - use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N was passed - * +1 OK - * +2 OK, but quadrature rule have exterior nodes, - x[0]<-1 or x[n-1]>+1 - X - array[0..N-1] - array of quadrature nodes, ordered in - ascending order. - WKronrod - array[0..N-1] - Kronrod weights - WGauss - array[0..N-1] - Gauss weights (interleaved with zeros - corresponding to extended Kronrod nodes). - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gkqgenerategaussjacobi(const ae_int_t n, const double alpha, const double beta, ae_int_t &info, real_1d_array &x, real_1d_array &wkronrod, real_1d_array &wgauss, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::gkqgenerategaussjacobi(n, alpha, beta, &info, const_cast(x.c_ptr()), const_cast(wkronrod.c_ptr()), const_cast(wgauss.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Returns Gauss and Gauss-Kronrod nodes for quadrature with N points. - -Reduction to tridiagonal eigenproblem is used. - -INPUT PARAMETERS: - N - number of Kronrod nodes, must be odd number, >=3. - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. N is too large to obtain - weights/nodes with high enough accuracy. - Try to use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, ordered in - ascending order. - WKronrod - array[0..N-1] - Kronrod weights - WGauss - array[0..N-1] - Gauss weights (interleaved with zeros - corresponding to extended Kronrod nodes). - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gkqlegendrecalc(const ae_int_t n, ae_int_t &info, real_1d_array &x, real_1d_array &wkronrod, real_1d_array &wgauss, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::gkqlegendrecalc(n, &info, const_cast(x.c_ptr()), const_cast(wkronrod.c_ptr()), const_cast(wgauss.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Returns Gauss and Gauss-Kronrod nodes for quadrature with N points using -pre-calculated table. Nodes/weights were computed with accuracy up to -1.0E-32 (if MPFR version of ALGLIB is used). In standard double precision -accuracy reduces to something about 2.0E-16 (depending on your compiler's -handling of long floating point constants). - -INPUT PARAMETERS: - N - number of Kronrod nodes. - N can be 15, 21, 31, 41, 51, 61. - -OUTPUT PARAMETERS: - X - array[0..N-1] - array of quadrature nodes, ordered in - ascending order. - WKronrod - array[0..N-1] - Kronrod weights - WGauss - array[0..N-1] - Gauss weights (interleaved with zeros - corresponding to extended Kronrod nodes). - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gkqlegendretbl(const ae_int_t n, real_1d_array &x, real_1d_array &wkronrod, real_1d_array &wgauss, double &eps, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::gkqlegendretbl(n, const_cast(x.c_ptr()), const_cast(wkronrod.c_ptr()), const_cast(wgauss.c_ptr()), &eps, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_AUTOGK) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Integration report: -* TerminationType = completetion code: - * -5 non-convergence of Gauss-Kronrod nodes - calculation subroutine. - * -1 incorrect parameters were specified - * 1 OK -* Rep.NFEV countains number of function calculations -* Rep.NIntervals contains number of intervals [a,b] - was partitioned into. -*************************************************************************/ -_autogkreport_owner::_autogkreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_autogkreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::autogkreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::autogkreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::autogkreport)); - alglib_impl::_autogkreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_autogkreport_owner::_autogkreport_owner(const _autogkreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_autogkreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: autogkreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::autogkreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::autogkreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::autogkreport)); - alglib_impl::_autogkreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_autogkreport_owner& _autogkreport_owner::operator=(const _autogkreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: autogkreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: autogkreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_autogkreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::autogkreport)); - alglib_impl::_autogkreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_autogkreport_owner::~_autogkreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_autogkreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::autogkreport* _autogkreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::autogkreport* _autogkreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -autogkreport::autogkreport() : _autogkreport_owner() ,terminationtype(p_struct->terminationtype),nfev(p_struct->nfev),nintervals(p_struct->nintervals) -{ -} - -autogkreport::autogkreport(const autogkreport &rhs):_autogkreport_owner(rhs) ,terminationtype(p_struct->terminationtype),nfev(p_struct->nfev),nintervals(p_struct->nintervals) -{ -} - -autogkreport& autogkreport::operator=(const autogkreport &rhs) -{ - if( this==&rhs ) - return *this; - _autogkreport_owner::operator=(rhs); - return *this; -} - -autogkreport::~autogkreport() -{ -} - - -/************************************************************************* -This structure stores state of the integration algorithm. - -Although this class has public fields, they are not intended for external -use. You should use ALGLIB functions to work with this class: -* autogksmooth()/AutoGKSmoothW()/... to create objects -* autogkintegrate() to begin integration -* autogkresults() to get results -*************************************************************************/ -_autogkstate_owner::_autogkstate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_autogkstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::autogkstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::autogkstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::autogkstate)); - alglib_impl::_autogkstate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_autogkstate_owner::_autogkstate_owner(const _autogkstate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_autogkstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: autogkstate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::autogkstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::autogkstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::autogkstate)); - alglib_impl::_autogkstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_autogkstate_owner& _autogkstate_owner::operator=(const _autogkstate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: autogkstate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: autogkstate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_autogkstate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::autogkstate)); - alglib_impl::_autogkstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_autogkstate_owner::~_autogkstate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_autogkstate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::autogkstate* _autogkstate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::autogkstate* _autogkstate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -autogkstate::autogkstate() : _autogkstate_owner() ,needf(p_struct->needf),x(p_struct->x),xminusa(p_struct->xminusa),bminusx(p_struct->bminusx),f(p_struct->f) -{ -} - -autogkstate::autogkstate(const autogkstate &rhs):_autogkstate_owner(rhs) ,needf(p_struct->needf),x(p_struct->x),xminusa(p_struct->xminusa),bminusx(p_struct->bminusx),f(p_struct->f) -{ -} - -autogkstate& autogkstate::operator=(const autogkstate &rhs) -{ - if( this==&rhs ) - return *this; - _autogkstate_owner::operator=(rhs); - return *this; -} - -autogkstate::~autogkstate() -{ -} - -/************************************************************************* -Integration of a smooth function F(x) on a finite interval [a,b]. - -Fast-convergent algorithm based on a Gauss-Kronrod formula is used. Result -is calculated with accuracy close to the machine precision. - -Algorithm works well only with smooth integrands. It may be used with -continuous non-smooth integrands, but with less performance. - -It should never be used with integrands which have integrable singularities -at lower or upper limits - algorithm may crash. Use AutoGKSingular in such -cases. - -INPUT PARAMETERS: - A, B - interval boundaries (AB) - -OUTPUT PARAMETERS - State - structure which stores algorithm state - -SEE ALSO - AutoGKSmoothW, AutoGKSingular, AutoGKResults. - - - -- ALGLIB -- - Copyright 06.05.2009 by Bochkanov Sergey -*************************************************************************/ -void autogksmooth(const double a, const double b, autogkstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::autogksmooth(a, b, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Integration of a smooth function F(x) on a finite interval [a,b]. - -This subroutine is same as AutoGKSmooth(), but it guarantees that interval -[a,b] is partitioned into subintervals which have width at most XWidth. - -Subroutine can be used when integrating nearly-constant function with -narrow "bumps" (about XWidth wide). If "bumps" are too narrow, AutoGKSmooth -subroutine can overlook them. - -INPUT PARAMETERS: - A, B - interval boundaries (AB) - -OUTPUT PARAMETERS - State - structure which stores algorithm state - -SEE ALSO - AutoGKSmooth, AutoGKSingular, AutoGKResults. - - - -- ALGLIB -- - Copyright 06.05.2009 by Bochkanov Sergey -*************************************************************************/ -void autogksmoothw(const double a, const double b, const double xwidth, autogkstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::autogksmoothw(a, b, xwidth, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Integration on a finite interval [A,B]. -Integrand have integrable singularities at A/B. - -F(X) must diverge as "(x-A)^alpha" at A, as "(B-x)^beta" at B, with known -alpha/beta (alpha>-1, beta>-1). If alpha/beta are not known, estimates -from below can be used (but these estimates should be greater than -1 too). - -One of alpha/beta variables (or even both alpha/beta) may be equal to 0, -which means than function F(x) is non-singular at A/B. Anyway (singular at -bounds or not), function F(x) is supposed to be continuous on (A,B). - -Fast-convergent algorithm based on a Gauss-Kronrod formula is used. Result -is calculated with accuracy close to the machine precision. - -INPUT PARAMETERS: - A, B - interval boundaries (AB) - Alpha - power-law coefficient of the F(x) at A, - Alpha>-1 - Beta - power-law coefficient of the F(x) at B, - Beta>-1 - -OUTPUT PARAMETERS - State - structure which stores algorithm state - -SEE ALSO - AutoGKSmooth, AutoGKSmoothW, AutoGKResults. - - - -- ALGLIB -- - Copyright 06.05.2009 by Bochkanov Sergey -*************************************************************************/ -void autogksingular(const double a, const double b, const double alpha, const double beta, autogkstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::autogksingular(a, b, alpha, beta, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool autogkiteration(const autogkstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::autogkiteration(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - - -void autogkintegrate(autogkstate &state, - void (*func)(double x, double xminusa, double bminusx, double &y, void *ptr), - void *ptr, const xparams _xparams){ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'autogkintegrate()' (func is NULL)", &_alglib_env_state); - while( alglib_impl::autogkiteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needf ) - { - func(state.x, state.xminusa, state.bminusx, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: unexpected error in 'autogkintegrate()'", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - - -/************************************************************************* -Adaptive integration results - -Called after AutoGKIteration returned False. - -Input parameters: - State - algorithm state (used by AutoGKIteration). - -Output parameters: - V - integral(f(x)dx,a,b) - Rep - optimization report (see AutoGKReport description) - - -- ALGLIB -- - Copyright 14.11.2007 by Bochkanov Sergey -*************************************************************************/ -void autogkresults(const autogkstate &state, double &v, autogkreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::autogkresults(const_cast(state.c_ptr()), &v, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF COMPUTATIONAL CORE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_GQ) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_GKQ) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_AUTOGK) || !defined(AE_PARTIAL_BUILD) -static ae_int_t autogk_maxsubintervals = 10000; -static void autogk_autogkinternalprepare(double a, - double b, - double eps, - double xwidth, - autogkinternalstate* state, - ae_state *_state); -static ae_bool autogk_autogkinternaliteration(autogkinternalstate* state, - ae_state *_state); -static void autogk_mheappop(/* Real */ ae_matrix* heap, - ae_int_t heapsize, - ae_int_t heapwidth, - ae_state *_state); -static void autogk_mheappush(/* Real */ ae_matrix* heap, - ae_int_t heapsize, - ae_int_t heapwidth, - ae_state *_state); -static void autogk_mheapresize(/* Real */ ae_matrix* heap, - ae_int_t* heapsize, - ae_int_t newheapsize, - ae_int_t heapwidth, - ae_state *_state); - - -#endif - -#if defined(AE_COMPILE_GQ) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Computation of nodes and weights for a Gauss quadrature formula - -The algorithm generates the N-point Gauss quadrature formula with weight -function given by coefficients alpha and beta of a recurrence relation -which generates a system of orthogonal polynomials: - -P-1(x) = 0 -P0(x) = 1 -Pn+1(x) = (x-alpha(n))*Pn(x) - beta(n)*Pn-1(x) - -and zeroth moment Mu0 - -Mu0 = integral(W(x)dx,a,b) - -INPUT PARAMETERS: - Alpha - array[0..N-1], alpha coefficients - Beta - array[0..N-1], beta coefficients - Zero-indexed element is not used and may be arbitrary. - Beta[I]>0. - Mu0 - zeroth moment of the weight function. - N - number of nodes of the quadrature formula, N>=1 - -OUTPUT PARAMETERS: - Info - error code: - * -3 internal eigenproblem solver hasn't converged - * -2 Beta[i]<=0 - * -1 incorrect N was passed - * 1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - -- ALGLIB -- - Copyright 2005-2009 by Bochkanov Sergey -*************************************************************************/ -void gqgeneraterec(/* Real */ ae_vector* alpha, - /* Real */ ae_vector* beta, - double mu0, - ae_int_t n, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_vector d; - ae_vector e; - ae_matrix z; - - ae_frame_make(_state, &_frame_block); - memset(&d, 0, sizeof(d)); - memset(&e, 0, sizeof(e)); - memset(&z, 0, sizeof(z)); - *info = 0; - ae_vector_clear(x); - ae_vector_clear(w); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&e, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true); - - if( n<1 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - *info = 1; - - /* - * Initialize - */ - ae_vector_set_length(&d, n, _state); - ae_vector_set_length(&e, n, _state); - for(i=1; i<=n-1; i++) - { - d.ptr.p_double[i-1] = alpha->ptr.p_double[i-1]; - if( ae_fp_less_eq(beta->ptr.p_double[i],(double)(0)) ) - { - *info = -2; - ae_frame_leave(_state); - return; - } - e.ptr.p_double[i-1] = ae_sqrt(beta->ptr.p_double[i], _state); - } - d.ptr.p_double[n-1] = alpha->ptr.p_double[n-1]; - - /* - * EVD - */ - if( !smatrixtdevd(&d, &e, n, 3, &z, _state) ) - { - *info = -3; - ae_frame_leave(_state); - return; - } - - /* - * Generate - */ - ae_vector_set_length(x, n, _state); - ae_vector_set_length(w, n, _state); - for(i=1; i<=n; i++) - { - x->ptr.p_double[i-1] = d.ptr.p_double[i-1]; - w->ptr.p_double[i-1] = mu0*ae_sqr(z.ptr.pp_double[0][i-1], _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Computation of nodes and weights for a Gauss-Lobatto quadrature formula - -The algorithm generates the N-point Gauss-Lobatto quadrature formula with -weight function given by coefficients alpha and beta of a recurrence which -generates a system of orthogonal polynomials. - -P-1(x) = 0 -P0(x) = 1 -Pn+1(x) = (x-alpha(n))*Pn(x) - beta(n)*Pn-1(x) - -and zeroth moment Mu0 - -Mu0 = integral(W(x)dx,a,b) - -INPUT PARAMETERS: - Alpha - array[0..N-2], alpha coefficients - Beta - array[0..N-2], beta coefficients. - Zero-indexed element is not used, may be arbitrary. - Beta[I]>0 - Mu0 - zeroth moment of the weighting function. - A - left boundary of the integration interval. - B - right boundary of the integration interval. - N - number of nodes of the quadrature formula, N>=3 - (including the left and right boundary nodes). - -OUTPUT PARAMETERS: - Info - error code: - * -3 internal eigenproblem solver hasn't converged - * -2 Beta[i]<=0 - * -1 incorrect N was passed - * 1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - -- ALGLIB -- - Copyright 2005-2009 by Bochkanov Sergey -*************************************************************************/ -void gqgenerategausslobattorec(/* Real */ ae_vector* alpha, - /* Real */ ae_vector* beta, - double mu0, - double a, - double b, - ae_int_t n, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _alpha; - ae_vector _beta; - ae_int_t i; - ae_vector d; - ae_vector e; - ae_matrix z; - double pim1a; - double pia; - double pim1b; - double pib; - double t; - double a11; - double a12; - double a21; - double a22; - double b1; - double b2; - double alph; - double bet; - - ae_frame_make(_state, &_frame_block); - memset(&_alpha, 0, sizeof(_alpha)); - memset(&_beta, 0, sizeof(_beta)); - memset(&d, 0, sizeof(d)); - memset(&e, 0, sizeof(e)); - memset(&z, 0, sizeof(z)); - ae_vector_init_copy(&_alpha, alpha, _state, ae_true); - alpha = &_alpha; - ae_vector_init_copy(&_beta, beta, _state, ae_true); - beta = &_beta; - *info = 0; - ae_vector_clear(x); - ae_vector_clear(w); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&e, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true); - - if( n<=2 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - *info = 1; - - /* - * Initialize, D[1:N+1], E[1:N] - */ - n = n-2; - ae_vector_set_length(&d, n+2, _state); - ae_vector_set_length(&e, n+1, _state); - for(i=1; i<=n+1; i++) - { - d.ptr.p_double[i-1] = alpha->ptr.p_double[i-1]; - } - for(i=1; i<=n; i++) - { - if( ae_fp_less_eq(beta->ptr.p_double[i],(double)(0)) ) - { - *info = -2; - ae_frame_leave(_state); - return; - } - e.ptr.p_double[i-1] = ae_sqrt(beta->ptr.p_double[i], _state); - } - - /* - * Caclulate Pn(a), Pn+1(a), Pn(b), Pn+1(b) - */ - beta->ptr.p_double[0] = (double)(0); - pim1a = (double)(0); - pia = (double)(1); - pim1b = (double)(0); - pib = (double)(1); - for(i=1; i<=n+1; i++) - { - - /* - * Pi(a) - */ - t = (a-alpha->ptr.p_double[i-1])*pia-beta->ptr.p_double[i-1]*pim1a; - pim1a = pia; - pia = t; - - /* - * Pi(b) - */ - t = (b-alpha->ptr.p_double[i-1])*pib-beta->ptr.p_double[i-1]*pim1b; - pim1b = pib; - pib = t; - } - - /* - * Calculate alpha'(n+1), beta'(n+1) - */ - a11 = pia; - a12 = pim1a; - a21 = pib; - a22 = pim1b; - b1 = a*pia; - b2 = b*pib; - if( ae_fp_greater(ae_fabs(a11, _state),ae_fabs(a21, _state)) ) - { - a22 = a22-a12*a21/a11; - b2 = b2-b1*a21/a11; - bet = b2/a22; - alph = (b1-bet*a12)/a11; - } - else - { - a12 = a12-a22*a11/a21; - b1 = b1-b2*a11/a21; - bet = b1/a12; - alph = (b2-bet*a22)/a21; - } - if( ae_fp_less(bet,(double)(0)) ) - { - *info = -3; - ae_frame_leave(_state); - return; - } - d.ptr.p_double[n+1] = alph; - e.ptr.p_double[n] = ae_sqrt(bet, _state); - - /* - * EVD - */ - if( !smatrixtdevd(&d, &e, n+2, 3, &z, _state) ) - { - *info = -3; - ae_frame_leave(_state); - return; - } - - /* - * Generate - */ - ae_vector_set_length(x, n+2, _state); - ae_vector_set_length(w, n+2, _state); - for(i=1; i<=n+2; i++) - { - x->ptr.p_double[i-1] = d.ptr.p_double[i-1]; - w->ptr.p_double[i-1] = mu0*ae_sqr(z.ptr.pp_double[0][i-1], _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Computation of nodes and weights for a Gauss-Radau quadrature formula - -The algorithm generates the N-point Gauss-Radau quadrature formula with -weight function given by the coefficients alpha and beta of a recurrence -which generates a system of orthogonal polynomials. - -P-1(x) = 0 -P0(x) = 1 -Pn+1(x) = (x-alpha(n))*Pn(x) - beta(n)*Pn-1(x) - -and zeroth moment Mu0 - -Mu0 = integral(W(x)dx,a,b) - -INPUT PARAMETERS: - Alpha - array[0..N-2], alpha coefficients. - Beta - array[0..N-1], beta coefficients - Zero-indexed element is not used. - Beta[I]>0 - Mu0 - zeroth moment of the weighting function. - A - left boundary of the integration interval. - N - number of nodes of the quadrature formula, N>=2 - (including the left boundary node). - -OUTPUT PARAMETERS: - Info - error code: - * -3 internal eigenproblem solver hasn't converged - * -2 Beta[i]<=0 - * -1 incorrect N was passed - * 1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - - -- ALGLIB -- - Copyright 2005-2009 by Bochkanov Sergey -*************************************************************************/ -void gqgenerategaussradaurec(/* Real */ ae_vector* alpha, - /* Real */ ae_vector* beta, - double mu0, - double a, - ae_int_t n, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _alpha; - ae_vector _beta; - ae_int_t i; - ae_vector d; - ae_vector e; - ae_matrix z; - double polim1; - double poli; - double t; - - ae_frame_make(_state, &_frame_block); - memset(&_alpha, 0, sizeof(_alpha)); - memset(&_beta, 0, sizeof(_beta)); - memset(&d, 0, sizeof(d)); - memset(&e, 0, sizeof(e)); - memset(&z, 0, sizeof(z)); - ae_vector_init_copy(&_alpha, alpha, _state, ae_true); - alpha = &_alpha; - ae_vector_init_copy(&_beta, beta, _state, ae_true); - beta = &_beta; - *info = 0; - ae_vector_clear(x); - ae_vector_clear(w); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&e, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true); - - if( n<2 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - *info = 1; - - /* - * Initialize, D[1:N], E[1:N] - */ - n = n-1; - ae_vector_set_length(&d, n+1, _state); - ae_vector_set_length(&e, n, _state); - for(i=1; i<=n; i++) - { - d.ptr.p_double[i-1] = alpha->ptr.p_double[i-1]; - if( ae_fp_less_eq(beta->ptr.p_double[i],(double)(0)) ) - { - *info = -2; - ae_frame_leave(_state); - return; - } - e.ptr.p_double[i-1] = ae_sqrt(beta->ptr.p_double[i], _state); - } - - /* - * Caclulate Pn(a), Pn-1(a), and D[N+1] - */ - beta->ptr.p_double[0] = (double)(0); - polim1 = (double)(0); - poli = (double)(1); - for(i=1; i<=n; i++) - { - t = (a-alpha->ptr.p_double[i-1])*poli-beta->ptr.p_double[i-1]*polim1; - polim1 = poli; - poli = t; - } - d.ptr.p_double[n] = a-beta->ptr.p_double[n]*polim1/poli; - - /* - * EVD - */ - if( !smatrixtdevd(&d, &e, n+1, 3, &z, _state) ) - { - *info = -3; - ae_frame_leave(_state); - return; - } - - /* - * Generate - */ - ae_vector_set_length(x, n+1, _state); - ae_vector_set_length(w, n+1, _state); - for(i=1; i<=n+1; i++) - { - x->ptr.p_double[i-1] = d.ptr.p_double[i-1]; - w->ptr.p_double[i-1] = mu0*ae_sqr(z.ptr.pp_double[0][i-1], _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Returns nodes/weights for Gauss-Legendre quadrature on [-1,1] with N -nodes. - -INPUT PARAMETERS: - N - number of nodes, >=1 - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. N is too large to obtain - weights/nodes with high enough accuracy. - Try to use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gqgenerategausslegendre(ae_int_t n, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector alpha; - ae_vector beta; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&alpha, 0, sizeof(alpha)); - memset(&beta, 0, sizeof(beta)); - *info = 0; - ae_vector_clear(x); - ae_vector_clear(w); - ae_vector_init(&alpha, 0, DT_REAL, _state, ae_true); - ae_vector_init(&beta, 0, DT_REAL, _state, ae_true); - - if( n<1 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_vector_set_length(&alpha, n, _state); - ae_vector_set_length(&beta, n, _state); - for(i=0; i<=n-1; i++) - { - alpha.ptr.p_double[i] = (double)(0); - } - beta.ptr.p_double[0] = (double)(2); - for(i=1; i<=n-1; i++) - { - beta.ptr.p_double[i] = 1/(4-1/ae_sqr((double)(i), _state)); - } - gqgeneraterec(&alpha, &beta, beta.ptr.p_double[0], n, info, x, w, _state); - - /* - * test basic properties to detect errors - */ - if( *info>0 ) - { - if( ae_fp_less(x->ptr.p_double[0],(double)(-1))||ae_fp_greater(x->ptr.p_double[n-1],(double)(1)) ) - { - *info = -4; - } - for(i=0; i<=n-2; i++) - { - if( ae_fp_greater_eq(x->ptr.p_double[i],x->ptr.p_double[i+1]) ) - { - *info = -4; - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Returns nodes/weights for Gauss-Jacobi quadrature on [-1,1] with weight -function W(x)=Power(1-x,Alpha)*Power(1+x,Beta). - -INPUT PARAMETERS: - N - number of nodes, >=1 - Alpha - power-law coefficient, Alpha>-1 - Beta - power-law coefficient, Beta>-1 - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. Alpha or Beta are too close - to -1 to obtain weights/nodes with high enough - accuracy, or, may be, N is too large. Try to - use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N/Alpha/Beta was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gqgenerategaussjacobi(ae_int_t n, - double alpha, - double beta, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector a; - ae_vector b; - double alpha2; - double beta2; - double apb; - double t; - ae_int_t i; - double s; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - *info = 0; - ae_vector_clear(x); - ae_vector_clear(w); - ae_vector_init(&a, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - - if( (n<1||ae_fp_less_eq(alpha,(double)(-1)))||ae_fp_less_eq(beta,(double)(-1)) ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_vector_set_length(&a, n, _state); - ae_vector_set_length(&b, n, _state); - apb = alpha+beta; - a.ptr.p_double[0] = (beta-alpha)/(apb+2); - t = (apb+1)*ae_log((double)(2), _state)+lngamma(alpha+1, &s, _state)+lngamma(beta+1, &s, _state)-lngamma(apb+2, &s, _state); - if( ae_fp_greater(t,ae_log(ae_maxrealnumber, _state)) ) - { - *info = -4; - ae_frame_leave(_state); - return; - } - b.ptr.p_double[0] = ae_exp(t, _state); - if( n>1 ) - { - alpha2 = ae_sqr(alpha, _state); - beta2 = ae_sqr(beta, _state); - a.ptr.p_double[1] = (beta2-alpha2)/((apb+2)*(apb+4)); - b.ptr.p_double[1] = 4*(alpha+1)*(beta+1)/((apb+3)*ae_sqr(apb+2, _state)); - for(i=2; i<=n-1; i++) - { - a.ptr.p_double[i] = 0.25*(beta2-alpha2)/(i*i*(1+0.5*apb/i)*(1+0.5*(apb+2)/i)); - b.ptr.p_double[i] = 0.25*(1+alpha/i)*(1+beta/i)*(1+apb/i)/((1+0.5*(apb+1)/i)*(1+0.5*(apb-1)/i)*ae_sqr(1+0.5*apb/i, _state)); - } - } - gqgeneraterec(&a, &b, b.ptr.p_double[0], n, info, x, w, _state); - - /* - * test basic properties to detect errors - */ - if( *info>0 ) - { - if( ae_fp_less(x->ptr.p_double[0],(double)(-1))||ae_fp_greater(x->ptr.p_double[n-1],(double)(1)) ) - { - *info = -4; - } - for(i=0; i<=n-2; i++) - { - if( ae_fp_greater_eq(x->ptr.p_double[i],x->ptr.p_double[i+1]) ) - { - *info = -4; - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Returns nodes/weights for Gauss-Laguerre quadrature on [0,+inf) with -weight function W(x)=Power(x,Alpha)*Exp(-x) - -INPUT PARAMETERS: - N - number of nodes, >=1 - Alpha - power-law coefficient, Alpha>-1 - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. Alpha is too close to -1 to - obtain weights/nodes with high enough accuracy - or, may be, N is too large. Try to use - multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N/Alpha was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gqgenerategausslaguerre(ae_int_t n, - double alpha, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector a; - ae_vector b; - double t; - ae_int_t i; - double s; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - *info = 0; - ae_vector_clear(x); - ae_vector_clear(w); - ae_vector_init(&a, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - - if( n<1||ae_fp_less_eq(alpha,(double)(-1)) ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_vector_set_length(&a, n, _state); - ae_vector_set_length(&b, n, _state); - a.ptr.p_double[0] = alpha+1; - t = lngamma(alpha+1, &s, _state); - if( ae_fp_greater_eq(t,ae_log(ae_maxrealnumber, _state)) ) - { - *info = -4; - ae_frame_leave(_state); - return; - } - b.ptr.p_double[0] = ae_exp(t, _state); - if( n>1 ) - { - for(i=1; i<=n-1; i++) - { - a.ptr.p_double[i] = 2*i+alpha+1; - b.ptr.p_double[i] = i*(i+alpha); - } - } - gqgeneraterec(&a, &b, b.ptr.p_double[0], n, info, x, w, _state); - - /* - * test basic properties to detect errors - */ - if( *info>0 ) - { - if( ae_fp_less(x->ptr.p_double[0],(double)(0)) ) - { - *info = -4; - } - for(i=0; i<=n-2; i++) - { - if( ae_fp_greater_eq(x->ptr.p_double[i],x->ptr.p_double[i+1]) ) - { - *info = -4; - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Returns nodes/weights for Gauss-Hermite quadrature on (-inf,+inf) with -weight function W(x)=Exp(-x*x) - -INPUT PARAMETERS: - N - number of nodes, >=1 - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. May be, N is too large. Try to - use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N/Alpha was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gqgenerategausshermite(ae_int_t n, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector a; - ae_vector b; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - *info = 0; - ae_vector_clear(x); - ae_vector_clear(w); - ae_vector_init(&a, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - - if( n<1 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_vector_set_length(&a, n, _state); - ae_vector_set_length(&b, n, _state); - for(i=0; i<=n-1; i++) - { - a.ptr.p_double[i] = (double)(0); - } - b.ptr.p_double[0] = ae_sqrt(4*ae_atan((double)(1), _state), _state); - if( n>1 ) - { - for(i=1; i<=n-1; i++) - { - b.ptr.p_double[i] = 0.5*i; - } - } - gqgeneraterec(&a, &b, b.ptr.p_double[0], n, info, x, w, _state); - - /* - * test basic properties to detect errors - */ - if( *info>0 ) - { - for(i=0; i<=n-2; i++) - { - if( ae_fp_greater_eq(x->ptr.p_double[i],x->ptr.p_double[i+1]) ) - { - *info = -4; - } - } - } - ae_frame_leave(_state); -} - - -#endif -#if defined(AE_COMPILE_GKQ) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Computation of nodes and weights of a Gauss-Kronrod quadrature formula - -The algorithm generates the N-point Gauss-Kronrod quadrature formula with -weight function given by coefficients alpha and beta of a recurrence -relation which generates a system of orthogonal polynomials: - - P-1(x) = 0 - P0(x) = 1 - Pn+1(x) = (x-alpha(n))*Pn(x) - beta(n)*Pn-1(x) - -and zero moment Mu0 - - Mu0 = integral(W(x)dx,a,b) - - -INPUT PARAMETERS: - Alpha - alpha coefficients, array[0..floor(3*K/2)]. - Beta - beta coefficients, array[0..ceil(3*K/2)]. - Beta[0] is not used and may be arbitrary. - Beta[I]>0. - Mu0 - zeroth moment of the weight function. - N - number of nodes of the Gauss-Kronrod quadrature formula, - N >= 3, - N = 2*K+1. - -OUTPUT PARAMETERS: - Info - error code: - * -5 no real and positive Gauss-Kronrod formula can - be created for such a weight function with a - given number of nodes. - * -4 N is too large, task may be ill conditioned - - x[i]=x[i+1] found. - * -3 internal eigenproblem solver hasn't converged - * -2 Beta[i]<=0 - * -1 incorrect N was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - WKronrod - array[0..N-1] - Kronrod weights - WGauss - array[0..N-1] - Gauss weights (interleaved with zeros - corresponding to extended Kronrod nodes). - - -- ALGLIB -- - Copyright 08.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gkqgeneraterec(/* Real */ ae_vector* alpha, - /* Real */ ae_vector* beta, - double mu0, - ae_int_t n, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* wkronrod, - /* Real */ ae_vector* wgauss, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _alpha; - ae_vector _beta; - ae_vector ta; - ae_int_t i; - ae_int_t j; - ae_vector t; - ae_vector s; - ae_int_t wlen; - ae_int_t woffs; - double u; - ae_int_t m; - ae_int_t l; - ae_int_t k; - ae_vector xgtmp; - ae_vector wgtmp; - - ae_frame_make(_state, &_frame_block); - memset(&_alpha, 0, sizeof(_alpha)); - memset(&_beta, 0, sizeof(_beta)); - memset(&ta, 0, sizeof(ta)); - memset(&t, 0, sizeof(t)); - memset(&s, 0, sizeof(s)); - memset(&xgtmp, 0, sizeof(xgtmp)); - memset(&wgtmp, 0, sizeof(wgtmp)); - ae_vector_init_copy(&_alpha, alpha, _state, ae_true); - alpha = &_alpha; - ae_vector_init_copy(&_beta, beta, _state, ae_true); - beta = &_beta; - *info = 0; - ae_vector_clear(x); - ae_vector_clear(wkronrod); - ae_vector_clear(wgauss); - ae_vector_init(&ta, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xgtmp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wgtmp, 0, DT_REAL, _state, ae_true); - - if( n%2!=1||n<3 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - for(i=0; i<=ae_iceil((double)(3*(n/2))/(double)2, _state); i++) - { - if( ae_fp_less_eq(beta->ptr.p_double[i],(double)(0)) ) - { - *info = -2; - ae_frame_leave(_state); - return; - } - } - *info = 1; - - /* - * from external conventions about N/Beta/Mu0 to internal - */ - n = n/2; - beta->ptr.p_double[0] = mu0; - - /* - * Calculate Gauss nodes/weights, save them for later processing - */ - gqgeneraterec(alpha, beta, mu0, n, info, &xgtmp, &wgtmp, _state); - if( *info<0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Resize: - * * A from 0..floor(3*n/2) to 0..2*n - * * B from 0..ceil(3*n/2) to 0..2*n - */ - ae_vector_set_length(&ta, ae_ifloor((double)(3*n)/(double)2, _state)+1, _state); - ae_v_move(&ta.ptr.p_double[0], 1, &alpha->ptr.p_double[0], 1, ae_v_len(0,ae_ifloor((double)(3*n)/(double)2, _state))); - ae_vector_set_length(alpha, 2*n+1, _state); - ae_v_move(&alpha->ptr.p_double[0], 1, &ta.ptr.p_double[0], 1, ae_v_len(0,ae_ifloor((double)(3*n)/(double)2, _state))); - for(i=ae_ifloor((double)(3*n)/(double)2, _state)+1; i<=2*n; i++) - { - alpha->ptr.p_double[i] = (double)(0); - } - ae_vector_set_length(&ta, ae_iceil((double)(3*n)/(double)2, _state)+1, _state); - ae_v_move(&ta.ptr.p_double[0], 1, &beta->ptr.p_double[0], 1, ae_v_len(0,ae_iceil((double)(3*n)/(double)2, _state))); - ae_vector_set_length(beta, 2*n+1, _state); - ae_v_move(&beta->ptr.p_double[0], 1, &ta.ptr.p_double[0], 1, ae_v_len(0,ae_iceil((double)(3*n)/(double)2, _state))); - for(i=ae_iceil((double)(3*n)/(double)2, _state)+1; i<=2*n; i++) - { - beta->ptr.p_double[i] = (double)(0); - } - - /* - * Initialize T, S - */ - wlen = 2+n/2; - ae_vector_set_length(&t, wlen, _state); - ae_vector_set_length(&s, wlen, _state); - ae_vector_set_length(&ta, wlen, _state); - woffs = 1; - for(i=0; i<=wlen-1; i++) - { - t.ptr.p_double[i] = (double)(0); - s.ptr.p_double[i] = (double)(0); - } - - /* - * Algorithm from Dirk P. Laurie, "Calculation of Gauss-Kronrod quadrature rules", 1997. - */ - t.ptr.p_double[woffs+0] = beta->ptr.p_double[n+1]; - for(m=0; m<=n-2; m++) - { - u = (double)(0); - for(k=(m+1)/2; k>=0; k--) - { - l = m-k; - u = u+(alpha->ptr.p_double[k+n+1]-alpha->ptr.p_double[l])*t.ptr.p_double[woffs+k]+beta->ptr.p_double[k+n+1]*s.ptr.p_double[woffs+k-1]-beta->ptr.p_double[l]*s.ptr.p_double[woffs+k]; - s.ptr.p_double[woffs+k] = u; - } - ae_v_move(&ta.ptr.p_double[0], 1, &t.ptr.p_double[0], 1, ae_v_len(0,wlen-1)); - ae_v_move(&t.ptr.p_double[0], 1, &s.ptr.p_double[0], 1, ae_v_len(0,wlen-1)); - ae_v_move(&s.ptr.p_double[0], 1, &ta.ptr.p_double[0], 1, ae_v_len(0,wlen-1)); - } - for(j=n/2; j>=0; j--) - { - s.ptr.p_double[woffs+j] = s.ptr.p_double[woffs+j-1]; - } - for(m=n-1; m<=2*n-3; m++) - { - u = (double)(0); - for(k=m+1-n; k<=(m-1)/2; k++) - { - l = m-k; - j = n-1-l; - u = u-(alpha->ptr.p_double[k+n+1]-alpha->ptr.p_double[l])*t.ptr.p_double[woffs+j]-beta->ptr.p_double[k+n+1]*s.ptr.p_double[woffs+j]+beta->ptr.p_double[l]*s.ptr.p_double[woffs+j+1]; - s.ptr.p_double[woffs+j] = u; - } - if( m%2==0 ) - { - k = m/2; - alpha->ptr.p_double[k+n+1] = alpha->ptr.p_double[k]+(s.ptr.p_double[woffs+j]-beta->ptr.p_double[k+n+1]*s.ptr.p_double[woffs+j+1])/t.ptr.p_double[woffs+j+1]; - } - else - { - k = (m+1)/2; - beta->ptr.p_double[k+n+1] = s.ptr.p_double[woffs+j]/s.ptr.p_double[woffs+j+1]; - } - ae_v_move(&ta.ptr.p_double[0], 1, &t.ptr.p_double[0], 1, ae_v_len(0,wlen-1)); - ae_v_move(&t.ptr.p_double[0], 1, &s.ptr.p_double[0], 1, ae_v_len(0,wlen-1)); - ae_v_move(&s.ptr.p_double[0], 1, &ta.ptr.p_double[0], 1, ae_v_len(0,wlen-1)); - } - alpha->ptr.p_double[2*n] = alpha->ptr.p_double[n-1]-beta->ptr.p_double[2*n]*s.ptr.p_double[woffs+0]/t.ptr.p_double[woffs+0]; - - /* - * calculation of Kronrod nodes and weights, unpacking of Gauss weights - */ - gqgeneraterec(alpha, beta, mu0, 2*n+1, info, x, wkronrod, _state); - if( *info==-2 ) - { - *info = -5; - } - if( *info<0 ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=2*n-1; i++) - { - if( ae_fp_greater_eq(x->ptr.p_double[i],x->ptr.p_double[i+1]) ) - { - *info = -4; - } - } - if( *info<0 ) - { - ae_frame_leave(_state); - return; - } - ae_vector_set_length(wgauss, 2*n+1, _state); - for(i=0; i<=2*n; i++) - { - wgauss->ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - wgauss->ptr.p_double[2*i+1] = wgtmp.ptr.p_double[i]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Returns Gauss and Gauss-Kronrod nodes/weights for Gauss-Legendre -quadrature with N points. - -GKQLegendreCalc (calculation) or GKQLegendreTbl (precomputed table) is -used depending on machine precision and number of nodes. - -INPUT PARAMETERS: - N - number of Kronrod nodes, must be odd number, >=3. - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. N is too large to obtain - weights/nodes with high enough accuracy. - Try to use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, ordered in - ascending order. - WKronrod - array[0..N-1] - Kronrod weights - WGauss - array[0..N-1] - Gauss weights (interleaved with zeros - corresponding to extended Kronrod nodes). - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gkqgenerategausslegendre(ae_int_t n, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* wkronrod, - /* Real */ ae_vector* wgauss, - ae_state *_state) -{ - double eps; - - *info = 0; - ae_vector_clear(x); - ae_vector_clear(wkronrod); - ae_vector_clear(wgauss); - - if( ae_fp_greater(ae_machineepsilon,1.0E-32)&&(((((n==15||n==21)||n==31)||n==41)||n==51)||n==61) ) - { - *info = 1; - gkqlegendretbl(n, x, wkronrod, wgauss, &eps, _state); - } - else - { - gkqlegendrecalc(n, info, x, wkronrod, wgauss, _state); - } -} - - -/************************************************************************* -Returns Gauss and Gauss-Kronrod nodes/weights for Gauss-Jacobi -quadrature on [-1,1] with weight function - - W(x)=Power(1-x,Alpha)*Power(1+x,Beta). - -INPUT PARAMETERS: - N - number of Kronrod nodes, must be odd number, >=3. - Alpha - power-law coefficient, Alpha>-1 - Beta - power-law coefficient, Beta>-1 - -OUTPUT PARAMETERS: - Info - error code: - * -5 no real and positive Gauss-Kronrod formula can - be created for such a weight function with a - given number of nodes. - * -4 an error was detected when calculating - weights/nodes. Alpha or Beta are too close - to -1 to obtain weights/nodes with high enough - accuracy, or, may be, N is too large. Try to - use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N was passed - * +1 OK - * +2 OK, but quadrature rule have exterior nodes, - x[0]<-1 or x[n-1]>+1 - X - array[0..N-1] - array of quadrature nodes, ordered in - ascending order. - WKronrod - array[0..N-1] - Kronrod weights - WGauss - array[0..N-1] - Gauss weights (interleaved with zeros - corresponding to extended Kronrod nodes). - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gkqgenerategaussjacobi(ae_int_t n, - double alpha, - double beta, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* wkronrod, - /* Real */ ae_vector* wgauss, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t clen; - ae_vector a; - ae_vector b; - double alpha2; - double beta2; - double apb; - double t; - ae_int_t i; - double s; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - *info = 0; - ae_vector_clear(x); - ae_vector_clear(wkronrod); - ae_vector_clear(wgauss); - ae_vector_init(&a, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - - if( n%2!=1||n<3 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - if( ae_fp_less_eq(alpha,(double)(-1))||ae_fp_less_eq(beta,(double)(-1)) ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - clen = ae_iceil((double)(3*(n/2))/(double)2, _state)+1; - ae_vector_set_length(&a, clen, _state); - ae_vector_set_length(&b, clen, _state); - for(i=0; i<=clen-1; i++) - { - a.ptr.p_double[i] = (double)(0); - } - apb = alpha+beta; - a.ptr.p_double[0] = (beta-alpha)/(apb+2); - t = (apb+1)*ae_log((double)(2), _state)+lngamma(alpha+1, &s, _state)+lngamma(beta+1, &s, _state)-lngamma(apb+2, &s, _state); - if( ae_fp_greater(t,ae_log(ae_maxrealnumber, _state)) ) - { - *info = -4; - ae_frame_leave(_state); - return; - } - b.ptr.p_double[0] = ae_exp(t, _state); - if( clen>1 ) - { - alpha2 = ae_sqr(alpha, _state); - beta2 = ae_sqr(beta, _state); - a.ptr.p_double[1] = (beta2-alpha2)/((apb+2)*(apb+4)); - b.ptr.p_double[1] = 4*(alpha+1)*(beta+1)/((apb+3)*ae_sqr(apb+2, _state)); - for(i=2; i<=clen-1; i++) - { - a.ptr.p_double[i] = 0.25*(beta2-alpha2)/(i*i*(1+0.5*apb/i)*(1+0.5*(apb+2)/i)); - b.ptr.p_double[i] = 0.25*(1+alpha/i)*(1+beta/i)*(1+apb/i)/((1+0.5*(apb+1)/i)*(1+0.5*(apb-1)/i)*ae_sqr(1+0.5*apb/i, _state)); - } - } - gkqgeneraterec(&a, &b, b.ptr.p_double[0], n, info, x, wkronrod, wgauss, _state); - - /* - * test basic properties to detect errors - */ - if( *info>0 ) - { - if( ae_fp_less(x->ptr.p_double[0],(double)(-1))||ae_fp_greater(x->ptr.p_double[n-1],(double)(1)) ) - { - *info = 2; - } - for(i=0; i<=n-2; i++) - { - if( ae_fp_greater_eq(x->ptr.p_double[i],x->ptr.p_double[i+1]) ) - { - *info = -4; - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Returns Gauss and Gauss-Kronrod nodes for quadrature with N points. - -Reduction to tridiagonal eigenproblem is used. - -INPUT PARAMETERS: - N - number of Kronrod nodes, must be odd number, >=3. - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. N is too large to obtain - weights/nodes with high enough accuracy. - Try to use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, ordered in - ascending order. - WKronrod - array[0..N-1] - Kronrod weights - WGauss - array[0..N-1] - Gauss weights (interleaved with zeros - corresponding to extended Kronrod nodes). - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gkqlegendrecalc(ae_int_t n, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* wkronrod, - /* Real */ ae_vector* wgauss, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector alpha; - ae_vector beta; - ae_int_t alen; - ae_int_t blen; - double mu0; - ae_int_t k; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&alpha, 0, sizeof(alpha)); - memset(&beta, 0, sizeof(beta)); - *info = 0; - ae_vector_clear(x); - ae_vector_clear(wkronrod); - ae_vector_clear(wgauss); - ae_vector_init(&alpha, 0, DT_REAL, _state, ae_true); - ae_vector_init(&beta, 0, DT_REAL, _state, ae_true); - - if( n%2!=1||n<3 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - mu0 = (double)(2); - alen = ae_ifloor((double)(3*(n/2))/(double)2, _state)+1; - blen = ae_iceil((double)(3*(n/2))/(double)2, _state)+1; - ae_vector_set_length(&alpha, alen, _state); - ae_vector_set_length(&beta, blen, _state); - for(k=0; k<=alen-1; k++) - { - alpha.ptr.p_double[k] = (double)(0); - } - beta.ptr.p_double[0] = (double)(2); - for(k=1; k<=blen-1; k++) - { - beta.ptr.p_double[k] = 1/(4-1/ae_sqr((double)(k), _state)); - } - gkqgeneraterec(&alpha, &beta, mu0, n, info, x, wkronrod, wgauss, _state); - - /* - * test basic properties to detect errors - */ - if( *info>0 ) - { - if( ae_fp_less(x->ptr.p_double[0],(double)(-1))||ae_fp_greater(x->ptr.p_double[n-1],(double)(1)) ) - { - *info = -4; - } - for(i=0; i<=n-2; i++) - { - if( ae_fp_greater_eq(x->ptr.p_double[i],x->ptr.p_double[i+1]) ) - { - *info = -4; - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Returns Gauss and Gauss-Kronrod nodes for quadrature with N points using -pre-calculated table. Nodes/weights were computed with accuracy up to -1.0E-32 (if MPFR version of ALGLIB is used). In standard double precision -accuracy reduces to something about 2.0E-16 (depending on your compiler's -handling of long floating point constants). - -INPUT PARAMETERS: - N - number of Kronrod nodes. - N can be 15, 21, 31, 41, 51, 61. - -OUTPUT PARAMETERS: - X - array[0..N-1] - array of quadrature nodes, ordered in - ascending order. - WKronrod - array[0..N-1] - Kronrod weights - WGauss - array[0..N-1] - Gauss weights (interleaved with zeros - corresponding to extended Kronrod nodes). - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gkqlegendretbl(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* wkronrod, - /* Real */ ae_vector* wgauss, - double* eps, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t ng; - ae_vector p1; - ae_vector p2; - double tmp; - - ae_frame_make(_state, &_frame_block); - memset(&p1, 0, sizeof(p1)); - memset(&p2, 0, sizeof(p2)); - ae_vector_clear(x); - ae_vector_clear(wkronrod); - ae_vector_clear(wgauss); - *eps = 0; - ae_vector_init(&p1, 0, DT_INT, _state, ae_true); - ae_vector_init(&p2, 0, DT_INT, _state, ae_true); - - - /* - * these initializers are not really necessary, - * but without them compiler complains about uninitialized locals - */ - ng = 0; - - /* - * Process - */ - ae_assert(((((n==15||n==21)||n==31)||n==41)||n==51)||n==61, "GKQNodesTbl: incorrect N!", _state); - ae_vector_set_length(x, n, _state); - ae_vector_set_length(wkronrod, n, _state); - ae_vector_set_length(wgauss, n, _state); - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = (double)(0); - wkronrod->ptr.p_double[i] = (double)(0); - wgauss->ptr.p_double[i] = (double)(0); - } - *eps = ae_maxreal(ae_machineepsilon, 1.0E-32, _state); - if( n==15 ) - { - ng = 4; - wgauss->ptr.p_double[0] = 0.129484966168869693270611432679082; - wgauss->ptr.p_double[1] = 0.279705391489276667901467771423780; - wgauss->ptr.p_double[2] = 0.381830050505118944950369775488975; - wgauss->ptr.p_double[3] = 0.417959183673469387755102040816327; - x->ptr.p_double[0] = 0.991455371120812639206854697526329; - x->ptr.p_double[1] = 0.949107912342758524526189684047851; - x->ptr.p_double[2] = 0.864864423359769072789712788640926; - x->ptr.p_double[3] = 0.741531185599394439863864773280788; - x->ptr.p_double[4] = 0.586087235467691130294144838258730; - x->ptr.p_double[5] = 0.405845151377397166906606412076961; - x->ptr.p_double[6] = 0.207784955007898467600689403773245; - x->ptr.p_double[7] = 0.000000000000000000000000000000000; - wkronrod->ptr.p_double[0] = 0.022935322010529224963732008058970; - wkronrod->ptr.p_double[1] = 0.063092092629978553290700663189204; - wkronrod->ptr.p_double[2] = 0.104790010322250183839876322541518; - wkronrod->ptr.p_double[3] = 0.140653259715525918745189590510238; - wkronrod->ptr.p_double[4] = 0.169004726639267902826583426598550; - wkronrod->ptr.p_double[5] = 0.190350578064785409913256402421014; - wkronrod->ptr.p_double[6] = 0.204432940075298892414161999234649; - wkronrod->ptr.p_double[7] = 0.209482141084727828012999174891714; - } - if( n==21 ) - { - ng = 5; - wgauss->ptr.p_double[0] = 0.066671344308688137593568809893332; - wgauss->ptr.p_double[1] = 0.149451349150580593145776339657697; - wgauss->ptr.p_double[2] = 0.219086362515982043995534934228163; - wgauss->ptr.p_double[3] = 0.269266719309996355091226921569469; - wgauss->ptr.p_double[4] = 0.295524224714752870173892994651338; - x->ptr.p_double[0] = 0.995657163025808080735527280689003; - x->ptr.p_double[1] = 0.973906528517171720077964012084452; - x->ptr.p_double[2] = 0.930157491355708226001207180059508; - x->ptr.p_double[3] = 0.865063366688984510732096688423493; - x->ptr.p_double[4] = 0.780817726586416897063717578345042; - x->ptr.p_double[5] = 0.679409568299024406234327365114874; - x->ptr.p_double[6] = 0.562757134668604683339000099272694; - x->ptr.p_double[7] = 0.433395394129247190799265943165784; - x->ptr.p_double[8] = 0.294392862701460198131126603103866; - x->ptr.p_double[9] = 0.148874338981631210884826001129720; - x->ptr.p_double[10] = 0.000000000000000000000000000000000; - wkronrod->ptr.p_double[0] = 0.011694638867371874278064396062192; - wkronrod->ptr.p_double[1] = 0.032558162307964727478818972459390; - wkronrod->ptr.p_double[2] = 0.054755896574351996031381300244580; - wkronrod->ptr.p_double[3] = 0.075039674810919952767043140916190; - wkronrod->ptr.p_double[4] = 0.093125454583697605535065465083366; - wkronrod->ptr.p_double[5] = 0.109387158802297641899210590325805; - wkronrod->ptr.p_double[6] = 0.123491976262065851077958109831074; - wkronrod->ptr.p_double[7] = 0.134709217311473325928054001771707; - wkronrod->ptr.p_double[8] = 0.142775938577060080797094273138717; - wkronrod->ptr.p_double[9] = 0.147739104901338491374841515972068; - wkronrod->ptr.p_double[10] = 0.149445554002916905664936468389821; - } - if( n==31 ) - { - ng = 8; - wgauss->ptr.p_double[0] = 0.030753241996117268354628393577204; - wgauss->ptr.p_double[1] = 0.070366047488108124709267416450667; - wgauss->ptr.p_double[2] = 0.107159220467171935011869546685869; - wgauss->ptr.p_double[3] = 0.139570677926154314447804794511028; - wgauss->ptr.p_double[4] = 0.166269205816993933553200860481209; - wgauss->ptr.p_double[5] = 0.186161000015562211026800561866423; - wgauss->ptr.p_double[6] = 0.198431485327111576456118326443839; - wgauss->ptr.p_double[7] = 0.202578241925561272880620199967519; - x->ptr.p_double[0] = 0.998002298693397060285172840152271; - x->ptr.p_double[1] = 0.987992518020485428489565718586613; - x->ptr.p_double[2] = 0.967739075679139134257347978784337; - x->ptr.p_double[3] = 0.937273392400705904307758947710209; - x->ptr.p_double[4] = 0.897264532344081900882509656454496; - x->ptr.p_double[5] = 0.848206583410427216200648320774217; - x->ptr.p_double[6] = 0.790418501442465932967649294817947; - x->ptr.p_double[7] = 0.724417731360170047416186054613938; - x->ptr.p_double[8] = 0.650996741297416970533735895313275; - x->ptr.p_double[9] = 0.570972172608538847537226737253911; - x->ptr.p_double[10] = 0.485081863640239680693655740232351; - x->ptr.p_double[11] = 0.394151347077563369897207370981045; - x->ptr.p_double[12] = 0.299180007153168812166780024266389; - x->ptr.p_double[13] = 0.201194093997434522300628303394596; - x->ptr.p_double[14] = 0.101142066918717499027074231447392; - x->ptr.p_double[15] = 0.000000000000000000000000000000000; - wkronrod->ptr.p_double[0] = 0.005377479872923348987792051430128; - wkronrod->ptr.p_double[1] = 0.015007947329316122538374763075807; - wkronrod->ptr.p_double[2] = 0.025460847326715320186874001019653; - wkronrod->ptr.p_double[3] = 0.035346360791375846222037948478360; - wkronrod->ptr.p_double[4] = 0.044589751324764876608227299373280; - wkronrod->ptr.p_double[5] = 0.053481524690928087265343147239430; - wkronrod->ptr.p_double[6] = 0.062009567800670640285139230960803; - wkronrod->ptr.p_double[7] = 0.069854121318728258709520077099147; - wkronrod->ptr.p_double[8] = 0.076849680757720378894432777482659; - wkronrod->ptr.p_double[9] = 0.083080502823133021038289247286104; - wkronrod->ptr.p_double[10] = 0.088564443056211770647275443693774; - wkronrod->ptr.p_double[11] = 0.093126598170825321225486872747346; - wkronrod->ptr.p_double[12] = 0.096642726983623678505179907627589; - wkronrod->ptr.p_double[13] = 0.099173598721791959332393173484603; - wkronrod->ptr.p_double[14] = 0.100769845523875595044946662617570; - wkronrod->ptr.p_double[15] = 0.101330007014791549017374792767493; - } - if( n==41 ) - { - ng = 10; - wgauss->ptr.p_double[0] = 0.017614007139152118311861962351853; - wgauss->ptr.p_double[1] = 0.040601429800386941331039952274932; - wgauss->ptr.p_double[2] = 0.062672048334109063569506535187042; - wgauss->ptr.p_double[3] = 0.083276741576704748724758143222046; - wgauss->ptr.p_double[4] = 0.101930119817240435036750135480350; - wgauss->ptr.p_double[5] = 0.118194531961518417312377377711382; - wgauss->ptr.p_double[6] = 0.131688638449176626898494499748163; - wgauss->ptr.p_double[7] = 0.142096109318382051329298325067165; - wgauss->ptr.p_double[8] = 0.149172986472603746787828737001969; - wgauss->ptr.p_double[9] = 0.152753387130725850698084331955098; - x->ptr.p_double[0] = 0.998859031588277663838315576545863; - x->ptr.p_double[1] = 0.993128599185094924786122388471320; - x->ptr.p_double[2] = 0.981507877450250259193342994720217; - x->ptr.p_double[3] = 0.963971927277913791267666131197277; - x->ptr.p_double[4] = 0.940822633831754753519982722212443; - x->ptr.p_double[5] = 0.912234428251325905867752441203298; - x->ptr.p_double[6] = 0.878276811252281976077442995113078; - x->ptr.p_double[7] = 0.839116971822218823394529061701521; - x->ptr.p_double[8] = 0.795041428837551198350638833272788; - x->ptr.p_double[9] = 0.746331906460150792614305070355642; - x->ptr.p_double[10] = 0.693237656334751384805490711845932; - x->ptr.p_double[11] = 0.636053680726515025452836696226286; - x->ptr.p_double[12] = 0.575140446819710315342946036586425; - x->ptr.p_double[13] = 0.510867001950827098004364050955251; - x->ptr.p_double[14] = 0.443593175238725103199992213492640; - x->ptr.p_double[15] = 0.373706088715419560672548177024927; - x->ptr.p_double[16] = 0.301627868114913004320555356858592; - x->ptr.p_double[17] = 0.227785851141645078080496195368575; - x->ptr.p_double[18] = 0.152605465240922675505220241022678; - x->ptr.p_double[19] = 0.076526521133497333754640409398838; - x->ptr.p_double[20] = 0.000000000000000000000000000000000; - wkronrod->ptr.p_double[0] = 0.003073583718520531501218293246031; - wkronrod->ptr.p_double[1] = 0.008600269855642942198661787950102; - wkronrod->ptr.p_double[2] = 0.014626169256971252983787960308868; - wkronrod->ptr.p_double[3] = 0.020388373461266523598010231432755; - wkronrod->ptr.p_double[4] = 0.025882133604951158834505067096153; - wkronrod->ptr.p_double[5] = 0.031287306777032798958543119323801; - wkronrod->ptr.p_double[6] = 0.036600169758200798030557240707211; - wkronrod->ptr.p_double[7] = 0.041668873327973686263788305936895; - wkronrod->ptr.p_double[8] = 0.046434821867497674720231880926108; - wkronrod->ptr.p_double[9] = 0.050944573923728691932707670050345; - wkronrod->ptr.p_double[10] = 0.055195105348285994744832372419777; - wkronrod->ptr.p_double[11] = 0.059111400880639572374967220648594; - wkronrod->ptr.p_double[12] = 0.062653237554781168025870122174255; - wkronrod->ptr.p_double[13] = 0.065834597133618422111563556969398; - wkronrod->ptr.p_double[14] = 0.068648672928521619345623411885368; - wkronrod->ptr.p_double[15] = 0.071054423553444068305790361723210; - wkronrod->ptr.p_double[16] = 0.073030690332786667495189417658913; - wkronrod->ptr.p_double[17] = 0.074582875400499188986581418362488; - wkronrod->ptr.p_double[18] = 0.075704497684556674659542775376617; - wkronrod->ptr.p_double[19] = 0.076377867672080736705502835038061; - wkronrod->ptr.p_double[20] = 0.076600711917999656445049901530102; - } - if( n==51 ) - { - ng = 13; - wgauss->ptr.p_double[0] = 0.011393798501026287947902964113235; - wgauss->ptr.p_double[1] = 0.026354986615032137261901815295299; - wgauss->ptr.p_double[2] = 0.040939156701306312655623487711646; - wgauss->ptr.p_double[3] = 0.054904695975835191925936891540473; - wgauss->ptr.p_double[4] = 0.068038333812356917207187185656708; - wgauss->ptr.p_double[5] = 0.080140700335001018013234959669111; - wgauss->ptr.p_double[6] = 0.091028261982963649811497220702892; - wgauss->ptr.p_double[7] = 0.100535949067050644202206890392686; - wgauss->ptr.p_double[8] = 0.108519624474263653116093957050117; - wgauss->ptr.p_double[9] = 0.114858259145711648339325545869556; - wgauss->ptr.p_double[10] = 0.119455763535784772228178126512901; - wgauss->ptr.p_double[11] = 0.122242442990310041688959518945852; - wgauss->ptr.p_double[12] = 0.123176053726715451203902873079050; - x->ptr.p_double[0] = 0.999262104992609834193457486540341; - x->ptr.p_double[1] = 0.995556969790498097908784946893902; - x->ptr.p_double[2] = 0.988035794534077247637331014577406; - x->ptr.p_double[3] = 0.976663921459517511498315386479594; - x->ptr.p_double[4] = 0.961614986425842512418130033660167; - x->ptr.p_double[5] = 0.942974571228974339414011169658471; - x->ptr.p_double[6] = 0.920747115281701561746346084546331; - x->ptr.p_double[7] = 0.894991997878275368851042006782805; - x->ptr.p_double[8] = 0.865847065293275595448996969588340; - x->ptr.p_double[9] = 0.833442628760834001421021108693570; - x->ptr.p_double[10] = 0.797873797998500059410410904994307; - x->ptr.p_double[11] = 0.759259263037357630577282865204361; - x->ptr.p_double[12] = 0.717766406813084388186654079773298; - x->ptr.p_double[13] = 0.673566368473468364485120633247622; - x->ptr.p_double[14] = 0.626810099010317412788122681624518; - x->ptr.p_double[15] = 0.577662930241222967723689841612654; - x->ptr.p_double[16] = 0.526325284334719182599623778158010; - x->ptr.p_double[17] = 0.473002731445714960522182115009192; - x->ptr.p_double[18] = 0.417885382193037748851814394594572; - x->ptr.p_double[19] = 0.361172305809387837735821730127641; - x->ptr.p_double[20] = 0.303089538931107830167478909980339; - x->ptr.p_double[21] = 0.243866883720988432045190362797452; - x->ptr.p_double[22] = 0.183718939421048892015969888759528; - x->ptr.p_double[23] = 0.122864692610710396387359818808037; - x->ptr.p_double[24] = 0.061544483005685078886546392366797; - x->ptr.p_double[25] = 0.000000000000000000000000000000000; - wkronrod->ptr.p_double[0] = 0.001987383892330315926507851882843; - wkronrod->ptr.p_double[1] = 0.005561932135356713758040236901066; - wkronrod->ptr.p_double[2] = 0.009473973386174151607207710523655; - wkronrod->ptr.p_double[3] = 0.013236229195571674813656405846976; - wkronrod->ptr.p_double[4] = 0.016847817709128298231516667536336; - wkronrod->ptr.p_double[5] = 0.020435371145882835456568292235939; - wkronrod->ptr.p_double[6] = 0.024009945606953216220092489164881; - wkronrod->ptr.p_double[7] = 0.027475317587851737802948455517811; - wkronrod->ptr.p_double[8] = 0.030792300167387488891109020215229; - wkronrod->ptr.p_double[9] = 0.034002130274329337836748795229551; - wkronrod->ptr.p_double[10] = 0.037116271483415543560330625367620; - wkronrod->ptr.p_double[11] = 0.040083825504032382074839284467076; - wkronrod->ptr.p_double[12] = 0.042872845020170049476895792439495; - wkronrod->ptr.p_double[13] = 0.045502913049921788909870584752660; - wkronrod->ptr.p_double[14] = 0.047982537138836713906392255756915; - wkronrod->ptr.p_double[15] = 0.050277679080715671963325259433440; - wkronrod->ptr.p_double[16] = 0.052362885806407475864366712137873; - wkronrod->ptr.p_double[17] = 0.054251129888545490144543370459876; - wkronrod->ptr.p_double[18] = 0.055950811220412317308240686382747; - wkronrod->ptr.p_double[19] = 0.057437116361567832853582693939506; - wkronrod->ptr.p_double[20] = 0.058689680022394207961974175856788; - wkronrod->ptr.p_double[21] = 0.059720340324174059979099291932562; - wkronrod->ptr.p_double[22] = 0.060539455376045862945360267517565; - wkronrod->ptr.p_double[23] = 0.061128509717053048305859030416293; - wkronrod->ptr.p_double[24] = 0.061471189871425316661544131965264; - wkronrod->ptr.p_double[25] = 0.061580818067832935078759824240055; - } - if( n==61 ) - { - ng = 15; - wgauss->ptr.p_double[0] = 0.007968192496166605615465883474674; - wgauss->ptr.p_double[1] = 0.018466468311090959142302131912047; - wgauss->ptr.p_double[2] = 0.028784707883323369349719179611292; - wgauss->ptr.p_double[3] = 0.038799192569627049596801936446348; - wgauss->ptr.p_double[4] = 0.048402672830594052902938140422808; - wgauss->ptr.p_double[5] = 0.057493156217619066481721689402056; - wgauss->ptr.p_double[6] = 0.065974229882180495128128515115962; - wgauss->ptr.p_double[7] = 0.073755974737705206268243850022191; - wgauss->ptr.p_double[8] = 0.080755895229420215354694938460530; - wgauss->ptr.p_double[9] = 0.086899787201082979802387530715126; - wgauss->ptr.p_double[10] = 0.092122522237786128717632707087619; - wgauss->ptr.p_double[11] = 0.096368737174644259639468626351810; - wgauss->ptr.p_double[12] = 0.099593420586795267062780282103569; - wgauss->ptr.p_double[13] = 0.101762389748405504596428952168554; - wgauss->ptr.p_double[14] = 0.102852652893558840341285636705415; - x->ptr.p_double[0] = 0.999484410050490637571325895705811; - x->ptr.p_double[1] = 0.996893484074649540271630050918695; - x->ptr.p_double[2] = 0.991630996870404594858628366109486; - x->ptr.p_double[3] = 0.983668123279747209970032581605663; - x->ptr.p_double[4] = 0.973116322501126268374693868423707; - x->ptr.p_double[5] = 0.960021864968307512216871025581798; - x->ptr.p_double[6] = 0.944374444748559979415831324037439; - x->ptr.p_double[7] = 0.926200047429274325879324277080474; - x->ptr.p_double[8] = 0.905573307699907798546522558925958; - x->ptr.p_double[9] = 0.882560535792052681543116462530226; - x->ptr.p_double[10] = 0.857205233546061098958658510658944; - x->ptr.p_double[11] = 0.829565762382768397442898119732502; - x->ptr.p_double[12] = 0.799727835821839083013668942322683; - x->ptr.p_double[13] = 0.767777432104826194917977340974503; - x->ptr.p_double[14] = 0.733790062453226804726171131369528; - x->ptr.p_double[15] = 0.697850494793315796932292388026640; - x->ptr.p_double[16] = 0.660061064126626961370053668149271; - x->ptr.p_double[17] = 0.620526182989242861140477556431189; - x->ptr.p_double[18] = 0.579345235826361691756024932172540; - x->ptr.p_double[19] = 0.536624148142019899264169793311073; - x->ptr.p_double[20] = 0.492480467861778574993693061207709; - x->ptr.p_double[21] = 0.447033769538089176780609900322854; - x->ptr.p_double[22] = 0.400401254830394392535476211542661; - x->ptr.p_double[23] = 0.352704725530878113471037207089374; - x->ptr.p_double[24] = 0.304073202273625077372677107199257; - x->ptr.p_double[25] = 0.254636926167889846439805129817805; - x->ptr.p_double[26] = 0.204525116682309891438957671002025; - x->ptr.p_double[27] = 0.153869913608583546963794672743256; - x->ptr.p_double[28] = 0.102806937966737030147096751318001; - x->ptr.p_double[29] = 0.051471842555317695833025213166723; - x->ptr.p_double[30] = 0.000000000000000000000000000000000; - wkronrod->ptr.p_double[0] = 0.001389013698677007624551591226760; - wkronrod->ptr.p_double[1] = 0.003890461127099884051267201844516; - wkronrod->ptr.p_double[2] = 0.006630703915931292173319826369750; - wkronrod->ptr.p_double[3] = 0.009273279659517763428441146892024; - wkronrod->ptr.p_double[4] = 0.011823015253496341742232898853251; - wkronrod->ptr.p_double[5] = 0.014369729507045804812451432443580; - wkronrod->ptr.p_double[6] = 0.016920889189053272627572289420322; - wkronrod->ptr.p_double[7] = 0.019414141193942381173408951050128; - wkronrod->ptr.p_double[8] = 0.021828035821609192297167485738339; - wkronrod->ptr.p_double[9] = 0.024191162078080601365686370725232; - wkronrod->ptr.p_double[10] = 0.026509954882333101610601709335075; - wkronrod->ptr.p_double[11] = 0.028754048765041292843978785354334; - wkronrod->ptr.p_double[12] = 0.030907257562387762472884252943092; - wkronrod->ptr.p_double[13] = 0.032981447057483726031814191016854; - wkronrod->ptr.p_double[14] = 0.034979338028060024137499670731468; - wkronrod->ptr.p_double[15] = 0.036882364651821229223911065617136; - wkronrod->ptr.p_double[16] = 0.038678945624727592950348651532281; - wkronrod->ptr.p_double[17] = 0.040374538951535959111995279752468; - wkronrod->ptr.p_double[18] = 0.041969810215164246147147541285970; - wkronrod->ptr.p_double[19] = 0.043452539701356069316831728117073; - wkronrod->ptr.p_double[20] = 0.044814800133162663192355551616723; - wkronrod->ptr.p_double[21] = 0.046059238271006988116271735559374; - wkronrod->ptr.p_double[22] = 0.047185546569299153945261478181099; - wkronrod->ptr.p_double[23] = 0.048185861757087129140779492298305; - wkronrod->ptr.p_double[24] = 0.049055434555029778887528165367238; - wkronrod->ptr.p_double[25] = 0.049795683427074206357811569379942; - wkronrod->ptr.p_double[26] = 0.050405921402782346840893085653585; - wkronrod->ptr.p_double[27] = 0.050881795898749606492297473049805; - wkronrod->ptr.p_double[28] = 0.051221547849258772170656282604944; - wkronrod->ptr.p_double[29] = 0.051426128537459025933862879215781; - wkronrod->ptr.p_double[30] = 0.051494729429451567558340433647099; - } - - /* - * copy nodes - */ - for(i=n-1; i>=n/2; i--) - { - x->ptr.p_double[i] = -x->ptr.p_double[n-1-i]; - } - - /* - * copy Kronrod weights - */ - for(i=n-1; i>=n/2; i--) - { - wkronrod->ptr.p_double[i] = wkronrod->ptr.p_double[n-1-i]; - } - - /* - * copy Gauss weights - */ - for(i=ng-1; i>=0; i--) - { - wgauss->ptr.p_double[n-2-2*i] = wgauss->ptr.p_double[i]; - wgauss->ptr.p_double[1+2*i] = wgauss->ptr.p_double[i]; - } - for(i=0; i<=n/2; i++) - { - wgauss->ptr.p_double[2*i] = (double)(0); - } - - /* - * reorder - */ - tagsort(x, n, &p1, &p2, _state); - for(i=0; i<=n-1; i++) - { - tmp = wkronrod->ptr.p_double[i]; - wkronrod->ptr.p_double[i] = wkronrod->ptr.p_double[p2.ptr.p_int[i]]; - wkronrod->ptr.p_double[p2.ptr.p_int[i]] = tmp; - tmp = wgauss->ptr.p_double[i]; - wgauss->ptr.p_double[i] = wgauss->ptr.p_double[p2.ptr.p_int[i]]; - wgauss->ptr.p_double[p2.ptr.p_int[i]] = tmp; - } - ae_frame_leave(_state); -} - - -#endif -#if defined(AE_COMPILE_AUTOGK) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Integration of a smooth function F(x) on a finite interval [a,b]. - -Fast-convergent algorithm based on a Gauss-Kronrod formula is used. Result -is calculated with accuracy close to the machine precision. - -Algorithm works well only with smooth integrands. It may be used with -continuous non-smooth integrands, but with less performance. - -It should never be used with integrands which have integrable singularities -at lower or upper limits - algorithm may crash. Use AutoGKSingular in such -cases. - -INPUT PARAMETERS: - A, B - interval boundaries (AB) - -OUTPUT PARAMETERS - State - structure which stores algorithm state - -SEE ALSO - AutoGKSmoothW, AutoGKSingular, AutoGKResults. - - - -- ALGLIB -- - Copyright 06.05.2009 by Bochkanov Sergey -*************************************************************************/ -void autogksmooth(double a, - double b, - autogkstate* state, - ae_state *_state) -{ - - _autogkstate_clear(state); - - ae_assert(ae_isfinite(a, _state), "AutoGKSmooth: A is not finite!", _state); - ae_assert(ae_isfinite(b, _state), "AutoGKSmooth: B is not finite!", _state); - autogksmoothw(a, b, 0.0, state, _state); -} - - -/************************************************************************* -Integration of a smooth function F(x) on a finite interval [a,b]. - -This subroutine is same as AutoGKSmooth(), but it guarantees that interval -[a,b] is partitioned into subintervals which have width at most XWidth. - -Subroutine can be used when integrating nearly-constant function with -narrow "bumps" (about XWidth wide). If "bumps" are too narrow, AutoGKSmooth -subroutine can overlook them. - -INPUT PARAMETERS: - A, B - interval boundaries (AB) - -OUTPUT PARAMETERS - State - structure which stores algorithm state - -SEE ALSO - AutoGKSmooth, AutoGKSingular, AutoGKResults. - - - -- ALGLIB -- - Copyright 06.05.2009 by Bochkanov Sergey -*************************************************************************/ -void autogksmoothw(double a, - double b, - double xwidth, - autogkstate* state, - ae_state *_state) -{ - - _autogkstate_clear(state); - - ae_assert(ae_isfinite(a, _state), "AutoGKSmoothW: A is not finite!", _state); - ae_assert(ae_isfinite(b, _state), "AutoGKSmoothW: B is not finite!", _state); - ae_assert(ae_isfinite(xwidth, _state), "AutoGKSmoothW: XWidth is not finite!", _state); - state->wrappermode = 0; - state->a = a; - state->b = b; - state->xwidth = xwidth; - state->needf = ae_false; - ae_vector_set_length(&state->rstate.ra, 10+1, _state); - state->rstate.stage = -1; -} - - -/************************************************************************* -Integration on a finite interval [A,B]. -Integrand have integrable singularities at A/B. - -F(X) must diverge as "(x-A)^alpha" at A, as "(B-x)^beta" at B, with known -alpha/beta (alpha>-1, beta>-1). If alpha/beta are not known, estimates -from below can be used (but these estimates should be greater than -1 too). - -One of alpha/beta variables (or even both alpha/beta) may be equal to 0, -which means than function F(x) is non-singular at A/B. Anyway (singular at -bounds or not), function F(x) is supposed to be continuous on (A,B). - -Fast-convergent algorithm based on a Gauss-Kronrod formula is used. Result -is calculated with accuracy close to the machine precision. - -INPUT PARAMETERS: - A, B - interval boundaries (AB) - Alpha - power-law coefficient of the F(x) at A, - Alpha>-1 - Beta - power-law coefficient of the F(x) at B, - Beta>-1 - -OUTPUT PARAMETERS - State - structure which stores algorithm state - -SEE ALSO - AutoGKSmooth, AutoGKSmoothW, AutoGKResults. - - - -- ALGLIB -- - Copyright 06.05.2009 by Bochkanov Sergey -*************************************************************************/ -void autogksingular(double a, - double b, - double alpha, - double beta, - autogkstate* state, - ae_state *_state) -{ - - _autogkstate_clear(state); - - ae_assert(ae_isfinite(a, _state), "AutoGKSingular: A is not finite!", _state); - ae_assert(ae_isfinite(b, _state), "AutoGKSingular: B is not finite!", _state); - ae_assert(ae_isfinite(alpha, _state), "AutoGKSingular: Alpha is not finite!", _state); - ae_assert(ae_isfinite(beta, _state), "AutoGKSingular: Beta is not finite!", _state); - state->wrappermode = 1; - state->a = a; - state->b = b; - state->alpha = alpha; - state->beta = beta; - state->xwidth = 0.0; - state->needf = ae_false; - ae_vector_set_length(&state->rstate.ra, 10+1, _state); - state->rstate.stage = -1; -} - - -/************************************************************************* - - -- ALGLIB -- - Copyright 07.05.2009 by Bochkanov Sergey -*************************************************************************/ -ae_bool autogkiteration(autogkstate* state, ae_state *_state) -{ - double s; - double tmp; - double eps; - double a; - double b; - double x; - double t; - double alpha; - double beta; - double v1; - double v2; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - s = state->rstate.ra.ptr.p_double[0]; - tmp = state->rstate.ra.ptr.p_double[1]; - eps = state->rstate.ra.ptr.p_double[2]; - a = state->rstate.ra.ptr.p_double[3]; - b = state->rstate.ra.ptr.p_double[4]; - x = state->rstate.ra.ptr.p_double[5]; - t = state->rstate.ra.ptr.p_double[6]; - alpha = state->rstate.ra.ptr.p_double[7]; - beta = state->rstate.ra.ptr.p_double[8]; - v1 = state->rstate.ra.ptr.p_double[9]; - v2 = state->rstate.ra.ptr.p_double[10]; - } - else - { - s = 359; - tmp = -58; - eps = -919; - a = -909; - b = 81; - x = 255; - t = 74; - alpha = -788; - beta = 809; - v1 = 205; - v2 = -838; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - if( state->rstate.stage==1 ) - { - goto lbl_1; - } - if( state->rstate.stage==2 ) - { - goto lbl_2; - } - - /* - * Routine body - */ - eps = (double)(0); - a = state->a; - b = state->b; - alpha = state->alpha; - beta = state->beta; - state->terminationtype = -1; - state->nfev = 0; - state->nintervals = 0; - - /* - * smooth function at a finite interval - */ - if( state->wrappermode!=0 ) - { - goto lbl_3; - } - - /* - * special case - */ - if( ae_fp_eq(a,b) ) - { - state->terminationtype = 1; - state->v = (double)(0); - result = ae_false; - return result; - } - - /* - * general case - */ - autogk_autogkinternalprepare(a, b, eps, state->xwidth, &state->internalstate, _state); -lbl_5: - if( !autogk_autogkinternaliteration(&state->internalstate, _state) ) - { - goto lbl_6; - } - x = state->internalstate.x; - state->x = x; - state->xminusa = x-a; - state->bminusx = b-x; - state->needf = ae_true; - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - state->needf = ae_false; - state->nfev = state->nfev+1; - state->internalstate.f = state->f; - goto lbl_5; -lbl_6: - state->v = state->internalstate.r; - state->terminationtype = state->internalstate.info; - state->nintervals = state->internalstate.heapused; - result = ae_false; - return result; -lbl_3: - - /* - * function with power-law singularities at the ends of a finite interval - */ - if( state->wrappermode!=1 ) - { - goto lbl_7; - } - - /* - * test coefficients - */ - if( ae_fp_less_eq(alpha,(double)(-1))||ae_fp_less_eq(beta,(double)(-1)) ) - { - state->terminationtype = -1; - state->v = (double)(0); - result = ae_false; - return result; - } - - /* - * special cases - */ - if( ae_fp_eq(a,b) ) - { - state->terminationtype = 1; - state->v = (double)(0); - result = ae_false; - return result; - } - - /* - * reduction to general form - */ - if( ae_fp_less(a,b) ) - { - s = (double)(1); - } - else - { - s = (double)(-1); - tmp = a; - a = b; - b = tmp; - tmp = alpha; - alpha = beta; - beta = tmp; - } - alpha = ae_minreal(alpha, (double)(0), _state); - beta = ae_minreal(beta, (double)(0), _state); - - /* - * first, integrate left half of [a,b]: - * integral(f(x)dx, a, (b+a)/2) = - * = 1/(1+alpha) * integral(t^(-alpha/(1+alpha))*f(a+t^(1/(1+alpha)))dt, 0, (0.5*(b-a))^(1+alpha)) - */ - autogk_autogkinternalprepare((double)(0), ae_pow(0.5*(b-a), 1+alpha, _state), eps, state->xwidth, &state->internalstate, _state); -lbl_9: - if( !autogk_autogkinternaliteration(&state->internalstate, _state) ) - { - goto lbl_10; - } - - /* - * Fill State.X, State.XMinusA, State.BMinusX. - * Latter two are filled correctly even if Binternalstate.x; - t = ae_pow(x, 1/(1+alpha), _state); - state->x = a+t; - if( ae_fp_greater(s,(double)(0)) ) - { - state->xminusa = t; - state->bminusx = b-(a+t); - } - else - { - state->xminusa = a+t-b; - state->bminusx = -t; - } - state->needf = ae_true; - state->rstate.stage = 1; - goto lbl_rcomm; -lbl_1: - state->needf = ae_false; - if( ae_fp_neq(alpha,(double)(0)) ) - { - state->internalstate.f = state->f*ae_pow(x, -alpha/(1+alpha), _state)/(1+alpha); - } - else - { - state->internalstate.f = state->f; - } - state->nfev = state->nfev+1; - goto lbl_9; -lbl_10: - v1 = state->internalstate.r; - state->nintervals = state->nintervals+state->internalstate.heapused; - - /* - * then, integrate right half of [a,b]: - * integral(f(x)dx, (b+a)/2, b) = - * = 1/(1+beta) * integral(t^(-beta/(1+beta))*f(b-t^(1/(1+beta)))dt, 0, (0.5*(b-a))^(1+beta)) - */ - autogk_autogkinternalprepare((double)(0), ae_pow(0.5*(b-a), 1+beta, _state), eps, state->xwidth, &state->internalstate, _state); -lbl_11: - if( !autogk_autogkinternaliteration(&state->internalstate, _state) ) - { - goto lbl_12; - } - - /* - * Fill State.X, State.XMinusA, State.BMinusX. - * Latter two are filled correctly (X-A, B-X) even if Binternalstate.x; - t = ae_pow(x, 1/(1+beta), _state); - state->x = b-t; - if( ae_fp_greater(s,(double)(0)) ) - { - state->xminusa = b-t-a; - state->bminusx = t; - } - else - { - state->xminusa = -t; - state->bminusx = a-(b-t); - } - state->needf = ae_true; - state->rstate.stage = 2; - goto lbl_rcomm; -lbl_2: - state->needf = ae_false; - if( ae_fp_neq(beta,(double)(0)) ) - { - state->internalstate.f = state->f*ae_pow(x, -beta/(1+beta), _state)/(1+beta); - } - else - { - state->internalstate.f = state->f; - } - state->nfev = state->nfev+1; - goto lbl_11; -lbl_12: - v2 = state->internalstate.r; - state->nintervals = state->nintervals+state->internalstate.heapused; - - /* - * final result - */ - state->v = s*(v1+v2); - state->terminationtype = 1; - result = ae_false; - return result; -lbl_7: - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ra.ptr.p_double[0] = s; - state->rstate.ra.ptr.p_double[1] = tmp; - state->rstate.ra.ptr.p_double[2] = eps; - state->rstate.ra.ptr.p_double[3] = a; - state->rstate.ra.ptr.p_double[4] = b; - state->rstate.ra.ptr.p_double[5] = x; - state->rstate.ra.ptr.p_double[6] = t; - state->rstate.ra.ptr.p_double[7] = alpha; - state->rstate.ra.ptr.p_double[8] = beta; - state->rstate.ra.ptr.p_double[9] = v1; - state->rstate.ra.ptr.p_double[10] = v2; - return result; -} - - -/************************************************************************* -Adaptive integration results - -Called after AutoGKIteration returned False. - -Input parameters: - State - algorithm state (used by AutoGKIteration). - -Output parameters: - V - integral(f(x)dx,a,b) - Rep - optimization report (see AutoGKReport description) - - -- ALGLIB -- - Copyright 14.11.2007 by Bochkanov Sergey -*************************************************************************/ -void autogkresults(autogkstate* state, - double* v, - autogkreport* rep, - ae_state *_state) -{ - - *v = 0; - _autogkreport_clear(rep); - - *v = state->v; - rep->terminationtype = state->terminationtype; - rep->nfev = state->nfev; - rep->nintervals = state->nintervals; -} - - -/************************************************************************* -Internal AutoGK subroutine -eps<0 - error -eps=0 - automatic eps selection - -width<0 - error -width=0 - no width requirements -*************************************************************************/ -static void autogk_autogkinternalprepare(double a, - double b, - double eps, - double xwidth, - autogkinternalstate* state, - ae_state *_state) -{ - - - - /* - * Save settings - */ - state->a = a; - state->b = b; - state->eps = eps; - state->xwidth = xwidth; - - /* - * Prepare RComm structure - */ - ae_vector_set_length(&state->rstate.ia, 3+1, _state); - ae_vector_set_length(&state->rstate.ra, 8+1, _state); - state->rstate.stage = -1; -} - - -/************************************************************************* -Internal AutoGK subroutine -*************************************************************************/ -static ae_bool autogk_autogkinternaliteration(autogkinternalstate* state, - ae_state *_state) -{ - double c1; - double c2; - ae_int_t i; - ae_int_t j; - double intg; - double intk; - double inta; - double v; - double ta; - double tb; - ae_int_t ns; - double qeps; - ae_int_t info; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - i = state->rstate.ia.ptr.p_int[0]; - j = state->rstate.ia.ptr.p_int[1]; - ns = state->rstate.ia.ptr.p_int[2]; - info = state->rstate.ia.ptr.p_int[3]; - c1 = state->rstate.ra.ptr.p_double[0]; - c2 = state->rstate.ra.ptr.p_double[1]; - intg = state->rstate.ra.ptr.p_double[2]; - intk = state->rstate.ra.ptr.p_double[3]; - inta = state->rstate.ra.ptr.p_double[4]; - v = state->rstate.ra.ptr.p_double[5]; - ta = state->rstate.ra.ptr.p_double[6]; - tb = state->rstate.ra.ptr.p_double[7]; - qeps = state->rstate.ra.ptr.p_double[8]; - } - else - { - i = 939; - j = -526; - ns = 763; - info = -541; - c1 = -698; - c2 = -900; - intg = -318; - intk = -940; - inta = 1016; - v = -229; - ta = -536; - tb = 487; - qeps = -115; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - if( state->rstate.stage==1 ) - { - goto lbl_1; - } - if( state->rstate.stage==2 ) - { - goto lbl_2; - } - - /* - * Routine body - */ - - /* - * initialize quadratures. - * use 15-point Gauss-Kronrod formula. - */ - state->n = 15; - gkqgenerategausslegendre(state->n, &info, &state->qn, &state->wk, &state->wg, _state); - if( info<0 ) - { - state->info = -5; - state->r = (double)(0); - result = ae_false; - return result; - } - ae_vector_set_length(&state->wr, state->n, _state); - for(i=0; i<=state->n-1; i++) - { - if( i==0 ) - { - state->wr.ptr.p_double[i] = 0.5*ae_fabs(state->qn.ptr.p_double[1]-state->qn.ptr.p_double[0], _state); - continue; - } - if( i==state->n-1 ) - { - state->wr.ptr.p_double[state->n-1] = 0.5*ae_fabs(state->qn.ptr.p_double[state->n-1]-state->qn.ptr.p_double[state->n-2], _state); - continue; - } - state->wr.ptr.p_double[i] = 0.5*ae_fabs(state->qn.ptr.p_double[i-1]-state->qn.ptr.p_double[i+1], _state); - } - - /* - * special case - */ - if( ae_fp_eq(state->a,state->b) ) - { - state->info = 1; - state->r = (double)(0); - result = ae_false; - return result; - } - - /* - * test parameters - */ - if( ae_fp_less(state->eps,(double)(0))||ae_fp_less(state->xwidth,(double)(0)) ) - { - state->info = -1; - state->r = (double)(0); - result = ae_false; - return result; - } - state->info = 1; - if( ae_fp_eq(state->eps,(double)(0)) ) - { - state->eps = 100000*ae_machineepsilon; - } - - /* - * First, prepare heap - * * column 0 - absolute error - * * column 1 - integral of a F(x) (calculated using Kronrod extension nodes) - * * column 2 - integral of a |F(x)| (calculated using modified rect. method) - * * column 3 - left boundary of a subinterval - * * column 4 - right boundary of a subinterval - */ - if( ae_fp_neq(state->xwidth,(double)(0)) ) - { - goto lbl_3; - } - - /* - * no maximum width requirements - * start from one big subinterval - */ - state->heapwidth = 5; - state->heapsize = 1; - state->heapused = 1; - ae_matrix_set_length(&state->heap, state->heapsize, state->heapwidth, _state); - c1 = 0.5*(state->b-state->a); - c2 = 0.5*(state->b+state->a); - intg = (double)(0); - intk = (double)(0); - inta = (double)(0); - i = 0; -lbl_5: - if( i>state->n-1 ) - { - goto lbl_7; - } - - /* - * obtain F - */ - state->x = c1*state->qn.ptr.p_double[i]+c2; - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - v = state->f; - - /* - * Gauss-Kronrod formula - */ - intk = intk+v*state->wk.ptr.p_double[i]; - if( i%2==1 ) - { - intg = intg+v*state->wg.ptr.p_double[i]; - } - - /* - * Integral |F(x)| - * Use rectangles method - */ - inta = inta+ae_fabs(v, _state)*state->wr.ptr.p_double[i]; - i = i+1; - goto lbl_5; -lbl_7: - intk = intk*(state->b-state->a)*0.5; - intg = intg*(state->b-state->a)*0.5; - inta = inta*(state->b-state->a)*0.5; - state->heap.ptr.pp_double[0][0] = ae_fabs(intg-intk, _state); - state->heap.ptr.pp_double[0][1] = intk; - state->heap.ptr.pp_double[0][2] = inta; - state->heap.ptr.pp_double[0][3] = state->a; - state->heap.ptr.pp_double[0][4] = state->b; - state->sumerr = state->heap.ptr.pp_double[0][0]; - state->sumabs = ae_fabs(inta, _state); - goto lbl_4; -lbl_3: - - /* - * maximum subinterval should be no more than XWidth. - * so we create Ceil((B-A)/XWidth)+1 small subintervals - */ - ns = ae_iceil(ae_fabs(state->b-state->a, _state)/state->xwidth, _state)+1; - state->heapsize = ns; - state->heapused = ns; - state->heapwidth = 5; - ae_matrix_set_length(&state->heap, state->heapsize, state->heapwidth, _state); - state->sumerr = (double)(0); - state->sumabs = (double)(0); - j = 0; -lbl_8: - if( j>ns-1 ) - { - goto lbl_10; - } - ta = state->a+j*(state->b-state->a)/ns; - tb = state->a+(j+1)*(state->b-state->a)/ns; - c1 = 0.5*(tb-ta); - c2 = 0.5*(tb+ta); - intg = (double)(0); - intk = (double)(0); - inta = (double)(0); - i = 0; -lbl_11: - if( i>state->n-1 ) - { - goto lbl_13; - } - - /* - * obtain F - */ - state->x = c1*state->qn.ptr.p_double[i]+c2; - state->rstate.stage = 1; - goto lbl_rcomm; -lbl_1: - v = state->f; - - /* - * Gauss-Kronrod formula - */ - intk = intk+v*state->wk.ptr.p_double[i]; - if( i%2==1 ) - { - intg = intg+v*state->wg.ptr.p_double[i]; - } - - /* - * Integral |F(x)| - * Use rectangles method - */ - inta = inta+ae_fabs(v, _state)*state->wr.ptr.p_double[i]; - i = i+1; - goto lbl_11; -lbl_13: - intk = intk*(tb-ta)*0.5; - intg = intg*(tb-ta)*0.5; - inta = inta*(tb-ta)*0.5; - state->heap.ptr.pp_double[j][0] = ae_fabs(intg-intk, _state); - state->heap.ptr.pp_double[j][1] = intk; - state->heap.ptr.pp_double[j][2] = inta; - state->heap.ptr.pp_double[j][3] = ta; - state->heap.ptr.pp_double[j][4] = tb; - state->sumerr = state->sumerr+state->heap.ptr.pp_double[j][0]; - state->sumabs = state->sumabs+ae_fabs(inta, _state); - j = j+1; - goto lbl_8; -lbl_10: -lbl_4: - - /* - * method iterations - */ -lbl_14: - if( ae_false ) - { - goto lbl_15; - } - - /* - * additional memory if needed - */ - if( state->heapused==state->heapsize ) - { - autogk_mheapresize(&state->heap, &state->heapsize, 4*state->heapsize, state->heapwidth, _state); - } - - /* - * TODO: every 20 iterations recalculate errors/sums - */ - if( ae_fp_less_eq(state->sumerr,state->eps*state->sumabs)||state->heapused>=autogk_maxsubintervals ) - { - state->r = (double)(0); - for(j=0; j<=state->heapused-1; j++) - { - state->r = state->r+state->heap.ptr.pp_double[j][1]; - } - result = ae_false; - return result; - } - - /* - * Exclude interval with maximum absolute error - */ - autogk_mheappop(&state->heap, state->heapused, state->heapwidth, _state); - state->sumerr = state->sumerr-state->heap.ptr.pp_double[state->heapused-1][0]; - state->sumabs = state->sumabs-state->heap.ptr.pp_double[state->heapused-1][2]; - - /* - * Divide interval, create subintervals - */ - ta = state->heap.ptr.pp_double[state->heapused-1][3]; - tb = state->heap.ptr.pp_double[state->heapused-1][4]; - state->heap.ptr.pp_double[state->heapused-1][3] = ta; - state->heap.ptr.pp_double[state->heapused-1][4] = 0.5*(ta+tb); - state->heap.ptr.pp_double[state->heapused][3] = 0.5*(ta+tb); - state->heap.ptr.pp_double[state->heapused][4] = tb; - j = state->heapused-1; -lbl_16: - if( j>state->heapused ) - { - goto lbl_18; - } - c1 = 0.5*(state->heap.ptr.pp_double[j][4]-state->heap.ptr.pp_double[j][3]); - c2 = 0.5*(state->heap.ptr.pp_double[j][4]+state->heap.ptr.pp_double[j][3]); - intg = (double)(0); - intk = (double)(0); - inta = (double)(0); - i = 0; -lbl_19: - if( i>state->n-1 ) - { - goto lbl_21; - } - - /* - * F(x) - */ - state->x = c1*state->qn.ptr.p_double[i]+c2; - state->rstate.stage = 2; - goto lbl_rcomm; -lbl_2: - v = state->f; - - /* - * Gauss-Kronrod formula - */ - intk = intk+v*state->wk.ptr.p_double[i]; - if( i%2==1 ) - { - intg = intg+v*state->wg.ptr.p_double[i]; - } - - /* - * Integral |F(x)| - * Use rectangles method - */ - inta = inta+ae_fabs(v, _state)*state->wr.ptr.p_double[i]; - i = i+1; - goto lbl_19; -lbl_21: - intk = intk*(state->heap.ptr.pp_double[j][4]-state->heap.ptr.pp_double[j][3])*0.5; - intg = intg*(state->heap.ptr.pp_double[j][4]-state->heap.ptr.pp_double[j][3])*0.5; - inta = inta*(state->heap.ptr.pp_double[j][4]-state->heap.ptr.pp_double[j][3])*0.5; - state->heap.ptr.pp_double[j][0] = ae_fabs(intg-intk, _state); - state->heap.ptr.pp_double[j][1] = intk; - state->heap.ptr.pp_double[j][2] = inta; - state->sumerr = state->sumerr+state->heap.ptr.pp_double[j][0]; - state->sumabs = state->sumabs+state->heap.ptr.pp_double[j][2]; - j = j+1; - goto lbl_16; -lbl_18: - autogk_mheappush(&state->heap, state->heapused-1, state->heapwidth, _state); - autogk_mheappush(&state->heap, state->heapused, state->heapwidth, _state); - state->heapused = state->heapused+1; - goto lbl_14; -lbl_15: - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = i; - state->rstate.ia.ptr.p_int[1] = j; - state->rstate.ia.ptr.p_int[2] = ns; - state->rstate.ia.ptr.p_int[3] = info; - state->rstate.ra.ptr.p_double[0] = c1; - state->rstate.ra.ptr.p_double[1] = c2; - state->rstate.ra.ptr.p_double[2] = intg; - state->rstate.ra.ptr.p_double[3] = intk; - state->rstate.ra.ptr.p_double[4] = inta; - state->rstate.ra.ptr.p_double[5] = v; - state->rstate.ra.ptr.p_double[6] = ta; - state->rstate.ra.ptr.p_double[7] = tb; - state->rstate.ra.ptr.p_double[8] = qeps; - return result; -} - - -static void autogk_mheappop(/* Real */ ae_matrix* heap, - ae_int_t heapsize, - ae_int_t heapwidth, - ae_state *_state) -{ - ae_int_t i; - ae_int_t p; - double t; - ae_int_t maxcp; - - - if( heapsize==1 ) - { - return; - } - for(i=0; i<=heapwidth-1; i++) - { - t = heap->ptr.pp_double[heapsize-1][i]; - heap->ptr.pp_double[heapsize-1][i] = heap->ptr.pp_double[0][i]; - heap->ptr.pp_double[0][i] = t; - } - p = 0; - while(2*p+1ptr.pp_double[2*p+2][0],heap->ptr.pp_double[2*p+1][0]) ) - { - maxcp = 2*p+2; - } - } - if( ae_fp_less(heap->ptr.pp_double[p][0],heap->ptr.pp_double[maxcp][0]) ) - { - for(i=0; i<=heapwidth-1; i++) - { - t = heap->ptr.pp_double[p][i]; - heap->ptr.pp_double[p][i] = heap->ptr.pp_double[maxcp][i]; - heap->ptr.pp_double[maxcp][i] = t; - } - p = maxcp; - } - else - { - break; - } - } -} - - -static void autogk_mheappush(/* Real */ ae_matrix* heap, - ae_int_t heapsize, - ae_int_t heapwidth, - ae_state *_state) -{ - ae_int_t i; - ae_int_t p; - double t; - ae_int_t parent; - - - if( heapsize==0 ) - { - return; - } - p = heapsize; - while(p!=0) - { - parent = (p-1)/2; - if( ae_fp_greater(heap->ptr.pp_double[p][0],heap->ptr.pp_double[parent][0]) ) - { - for(i=0; i<=heapwidth-1; i++) - { - t = heap->ptr.pp_double[p][i]; - heap->ptr.pp_double[p][i] = heap->ptr.pp_double[parent][i]; - heap->ptr.pp_double[parent][i] = t; - } - p = parent; - } - else - { - break; - } - } -} - - -static void autogk_mheapresize(/* Real */ ae_matrix* heap, - ae_int_t* heapsize, - ae_int_t newheapsize, - ae_int_t heapwidth, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix tmp; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&tmp, 0, sizeof(tmp)); - ae_matrix_init(&tmp, 0, 0, DT_REAL, _state, ae_true); - - ae_matrix_set_length(&tmp, *heapsize, heapwidth, _state); - for(i=0; i<=*heapsize-1; i++) - { - ae_v_move(&tmp.ptr.pp_double[i][0], 1, &heap->ptr.pp_double[i][0], 1, ae_v_len(0,heapwidth-1)); - } - ae_matrix_set_length(heap, newheapsize, heapwidth, _state); - for(i=0; i<=*heapsize-1; i++) - { - ae_v_move(&heap->ptr.pp_double[i][0], 1, &tmp.ptr.pp_double[i][0], 1, ae_v_len(0,heapwidth-1)); - } - *heapsize = newheapsize; - ae_frame_leave(_state); -} - - -void _autogkreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - autogkreport *p = (autogkreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _autogkreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - autogkreport *dst = (autogkreport*)_dst; - autogkreport *src = (autogkreport*)_src; - dst->terminationtype = src->terminationtype; - dst->nfev = src->nfev; - dst->nintervals = src->nintervals; -} - - -void _autogkreport_clear(void* _p) -{ - autogkreport *p = (autogkreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _autogkreport_destroy(void* _p) -{ - autogkreport *p = (autogkreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _autogkinternalstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - autogkinternalstate *p = (autogkinternalstate*)_p; - ae_touch_ptr((void*)p); - ae_matrix_init(&p->heap, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->qn, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->wg, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->wk, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->wr, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); -} - - -void _autogkinternalstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - autogkinternalstate *dst = (autogkinternalstate*)_dst; - autogkinternalstate *src = (autogkinternalstate*)_src; - dst->a = src->a; - dst->b = src->b; - dst->eps = src->eps; - dst->xwidth = src->xwidth; - dst->x = src->x; - dst->f = src->f; - dst->info = src->info; - dst->r = src->r; - ae_matrix_init_copy(&dst->heap, &src->heap, _state, make_automatic); - dst->heapsize = src->heapsize; - dst->heapwidth = src->heapwidth; - dst->heapused = src->heapused; - dst->sumerr = src->sumerr; - dst->sumabs = src->sumabs; - ae_vector_init_copy(&dst->qn, &src->qn, _state, make_automatic); - ae_vector_init_copy(&dst->wg, &src->wg, _state, make_automatic); - ae_vector_init_copy(&dst->wk, &src->wk, _state, make_automatic); - ae_vector_init_copy(&dst->wr, &src->wr, _state, make_automatic); - dst->n = src->n; - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); -} - - -void _autogkinternalstate_clear(void* _p) -{ - autogkinternalstate *p = (autogkinternalstate*)_p; - ae_touch_ptr((void*)p); - ae_matrix_clear(&p->heap); - ae_vector_clear(&p->qn); - ae_vector_clear(&p->wg); - ae_vector_clear(&p->wk); - ae_vector_clear(&p->wr); - _rcommstate_clear(&p->rstate); -} - - -void _autogkinternalstate_destroy(void* _p) -{ - autogkinternalstate *p = (autogkinternalstate*)_p; - ae_touch_ptr((void*)p); - ae_matrix_destroy(&p->heap); - ae_vector_destroy(&p->qn); - ae_vector_destroy(&p->wg); - ae_vector_destroy(&p->wk); - ae_vector_destroy(&p->wr); - _rcommstate_destroy(&p->rstate); -} - - -void _autogkstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - autogkstate *p = (autogkstate*)_p; - ae_touch_ptr((void*)p); - _autogkinternalstate_init(&p->internalstate, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); -} - - -void _autogkstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - autogkstate *dst = (autogkstate*)_dst; - autogkstate *src = (autogkstate*)_src; - dst->a = src->a; - dst->b = src->b; - dst->alpha = src->alpha; - dst->beta = src->beta; - dst->xwidth = src->xwidth; - dst->x = src->x; - dst->xminusa = src->xminusa; - dst->bminusx = src->bminusx; - dst->needf = src->needf; - dst->f = src->f; - dst->wrappermode = src->wrappermode; - _autogkinternalstate_init_copy(&dst->internalstate, &src->internalstate, _state, make_automatic); - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); - dst->v = src->v; - dst->terminationtype = src->terminationtype; - dst->nfev = src->nfev; - dst->nintervals = src->nintervals; -} - - -void _autogkstate_clear(void* _p) -{ - autogkstate *p = (autogkstate*)_p; - ae_touch_ptr((void*)p); - _autogkinternalstate_clear(&p->internalstate); - _rcommstate_clear(&p->rstate); -} - - -void _autogkstate_destroy(void* _p) -{ - autogkstate *p = (autogkstate*)_p; - ae_touch_ptr((void*)p); - _autogkinternalstate_destroy(&p->internalstate); - _rcommstate_destroy(&p->rstate); -} - - -#endif - -} - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/integration.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/integration.h deleted file mode 100644 index 5bbb54e..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/integration.h +++ /dev/null @@ -1,863 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifndef _integration_pkg_h -#define _integration_pkg_h -#include "ap.h" -#include "alglibinternal.h" -#include "alglibmisc.h" -#include "linalg.h" -#include "specialfunctions.h" - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (DATATYPES) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_GQ) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_GKQ) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_AUTOGK) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t terminationtype; - ae_int_t nfev; - ae_int_t nintervals; -} autogkreport; -typedef struct -{ - double a; - double b; - double eps; - double xwidth; - double x; - double f; - ae_int_t info; - double r; - ae_matrix heap; - ae_int_t heapsize; - ae_int_t heapwidth; - ae_int_t heapused; - double sumerr; - double sumabs; - ae_vector qn; - ae_vector wg; - ae_vector wk; - ae_vector wr; - ae_int_t n; - rcommstate rstate; -} autogkinternalstate; -typedef struct -{ - double a; - double b; - double alpha; - double beta; - double xwidth; - double x; - double xminusa; - double bminusx; - ae_bool needf; - double f; - ae_int_t wrappermode; - autogkinternalstate internalstate; - rcommstate rstate; - double v; - ae_int_t terminationtype; - ae_int_t nfev; - ae_int_t nintervals; -} autogkstate; -#endif - -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_GQ) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_GKQ) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_AUTOGK) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Integration report: -* TerminationType = completetion code: - * -5 non-convergence of Gauss-Kronrod nodes - calculation subroutine. - * -1 incorrect parameters were specified - * 1 OK -* Rep.NFEV countains number of function calculations -* Rep.NIntervals contains number of intervals [a,b] - was partitioned into. -*************************************************************************/ -class _autogkreport_owner -{ -public: - _autogkreport_owner(); - _autogkreport_owner(const _autogkreport_owner &rhs); - _autogkreport_owner& operator=(const _autogkreport_owner &rhs); - virtual ~_autogkreport_owner(); - alglib_impl::autogkreport* c_ptr(); - alglib_impl::autogkreport* c_ptr() const; -protected: - alglib_impl::autogkreport *p_struct; -}; -class autogkreport : public _autogkreport_owner -{ -public: - autogkreport(); - autogkreport(const autogkreport &rhs); - autogkreport& operator=(const autogkreport &rhs); - virtual ~autogkreport(); - ae_int_t &terminationtype; - ae_int_t &nfev; - ae_int_t &nintervals; - -}; - - -/************************************************************************* -This structure stores state of the integration algorithm. - -Although this class has public fields, they are not intended for external -use. You should use ALGLIB functions to work with this class: -* autogksmooth()/AutoGKSmoothW()/... to create objects -* autogkintegrate() to begin integration -* autogkresults() to get results -*************************************************************************/ -class _autogkstate_owner -{ -public: - _autogkstate_owner(); - _autogkstate_owner(const _autogkstate_owner &rhs); - _autogkstate_owner& operator=(const _autogkstate_owner &rhs); - virtual ~_autogkstate_owner(); - alglib_impl::autogkstate* c_ptr(); - alglib_impl::autogkstate* c_ptr() const; -protected: - alglib_impl::autogkstate *p_struct; -}; -class autogkstate : public _autogkstate_owner -{ -public: - autogkstate(); - autogkstate(const autogkstate &rhs); - autogkstate& operator=(const autogkstate &rhs); - virtual ~autogkstate(); - ae_bool &needf; - double &x; - double &xminusa; - double &bminusx; - double &f; - -}; -#endif - -#if defined(AE_COMPILE_GQ) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Computation of nodes and weights for a Gauss quadrature formula - -The algorithm generates the N-point Gauss quadrature formula with weight -function given by coefficients alpha and beta of a recurrence relation -which generates a system of orthogonal polynomials: - -P-1(x) = 0 -P0(x) = 1 -Pn+1(x) = (x-alpha(n))*Pn(x) - beta(n)*Pn-1(x) - -and zeroth moment Mu0 - -Mu0 = integral(W(x)dx,a,b) - -INPUT PARAMETERS: - Alpha - array[0..N-1], alpha coefficients - Beta - array[0..N-1], beta coefficients - Zero-indexed element is not used and may be arbitrary. - Beta[I]>0. - Mu0 - zeroth moment of the weight function. - N - number of nodes of the quadrature formula, N>=1 - -OUTPUT PARAMETERS: - Info - error code: - * -3 internal eigenproblem solver hasn't converged - * -2 Beta[i]<=0 - * -1 incorrect N was passed - * 1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - -- ALGLIB -- - Copyright 2005-2009 by Bochkanov Sergey -*************************************************************************/ -void gqgeneraterec(const real_1d_array &alpha, const real_1d_array &beta, const double mu0, const ae_int_t n, ae_int_t &info, real_1d_array &x, real_1d_array &w, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Computation of nodes and weights for a Gauss-Lobatto quadrature formula - -The algorithm generates the N-point Gauss-Lobatto quadrature formula with -weight function given by coefficients alpha and beta of a recurrence which -generates a system of orthogonal polynomials. - -P-1(x) = 0 -P0(x) = 1 -Pn+1(x) = (x-alpha(n))*Pn(x) - beta(n)*Pn-1(x) - -and zeroth moment Mu0 - -Mu0 = integral(W(x)dx,a,b) - -INPUT PARAMETERS: - Alpha - array[0..N-2], alpha coefficients - Beta - array[0..N-2], beta coefficients. - Zero-indexed element is not used, may be arbitrary. - Beta[I]>0 - Mu0 - zeroth moment of the weighting function. - A - left boundary of the integration interval. - B - right boundary of the integration interval. - N - number of nodes of the quadrature formula, N>=3 - (including the left and right boundary nodes). - -OUTPUT PARAMETERS: - Info - error code: - * -3 internal eigenproblem solver hasn't converged - * -2 Beta[i]<=0 - * -1 incorrect N was passed - * 1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - -- ALGLIB -- - Copyright 2005-2009 by Bochkanov Sergey -*************************************************************************/ -void gqgenerategausslobattorec(const real_1d_array &alpha, const real_1d_array &beta, const double mu0, const double a, const double b, const ae_int_t n, ae_int_t &info, real_1d_array &x, real_1d_array &w, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Computation of nodes and weights for a Gauss-Radau quadrature formula - -The algorithm generates the N-point Gauss-Radau quadrature formula with -weight function given by the coefficients alpha and beta of a recurrence -which generates a system of orthogonal polynomials. - -P-1(x) = 0 -P0(x) = 1 -Pn+1(x) = (x-alpha(n))*Pn(x) - beta(n)*Pn-1(x) - -and zeroth moment Mu0 - -Mu0 = integral(W(x)dx,a,b) - -INPUT PARAMETERS: - Alpha - array[0..N-2], alpha coefficients. - Beta - array[0..N-1], beta coefficients - Zero-indexed element is not used. - Beta[I]>0 - Mu0 - zeroth moment of the weighting function. - A - left boundary of the integration interval. - N - number of nodes of the quadrature formula, N>=2 - (including the left boundary node). - -OUTPUT PARAMETERS: - Info - error code: - * -3 internal eigenproblem solver hasn't converged - * -2 Beta[i]<=0 - * -1 incorrect N was passed - * 1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - - -- ALGLIB -- - Copyright 2005-2009 by Bochkanov Sergey -*************************************************************************/ -void gqgenerategaussradaurec(const real_1d_array &alpha, const real_1d_array &beta, const double mu0, const double a, const ae_int_t n, ae_int_t &info, real_1d_array &x, real_1d_array &w, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Returns nodes/weights for Gauss-Legendre quadrature on [-1,1] with N -nodes. - -INPUT PARAMETERS: - N - number of nodes, >=1 - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. N is too large to obtain - weights/nodes with high enough accuracy. - Try to use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gqgenerategausslegendre(const ae_int_t n, ae_int_t &info, real_1d_array &x, real_1d_array &w, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Returns nodes/weights for Gauss-Jacobi quadrature on [-1,1] with weight -function W(x)=Power(1-x,Alpha)*Power(1+x,Beta). - -INPUT PARAMETERS: - N - number of nodes, >=1 - Alpha - power-law coefficient, Alpha>-1 - Beta - power-law coefficient, Beta>-1 - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. Alpha or Beta are too close - to -1 to obtain weights/nodes with high enough - accuracy, or, may be, N is too large. Try to - use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N/Alpha/Beta was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gqgenerategaussjacobi(const ae_int_t n, const double alpha, const double beta, ae_int_t &info, real_1d_array &x, real_1d_array &w, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Returns nodes/weights for Gauss-Laguerre quadrature on [0,+inf) with -weight function W(x)=Power(x,Alpha)*Exp(-x) - -INPUT PARAMETERS: - N - number of nodes, >=1 - Alpha - power-law coefficient, Alpha>-1 - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. Alpha is too close to -1 to - obtain weights/nodes with high enough accuracy - or, may be, N is too large. Try to use - multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N/Alpha was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gqgenerategausslaguerre(const ae_int_t n, const double alpha, ae_int_t &info, real_1d_array &x, real_1d_array &w, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Returns nodes/weights for Gauss-Hermite quadrature on (-inf,+inf) with -weight function W(x)=Exp(-x*x) - -INPUT PARAMETERS: - N - number of nodes, >=1 - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. May be, N is too large. Try to - use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N/Alpha was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - W - array[0..N-1] - array of quadrature weights. - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gqgenerategausshermite(const ae_int_t n, ae_int_t &info, real_1d_array &x, real_1d_array &w, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_GKQ) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Computation of nodes and weights of a Gauss-Kronrod quadrature formula - -The algorithm generates the N-point Gauss-Kronrod quadrature formula with -weight function given by coefficients alpha and beta of a recurrence -relation which generates a system of orthogonal polynomials: - - P-1(x) = 0 - P0(x) = 1 - Pn+1(x) = (x-alpha(n))*Pn(x) - beta(n)*Pn-1(x) - -and zero moment Mu0 - - Mu0 = integral(W(x)dx,a,b) - - -INPUT PARAMETERS: - Alpha - alpha coefficients, array[0..floor(3*K/2)]. - Beta - beta coefficients, array[0..ceil(3*K/2)]. - Beta[0] is not used and may be arbitrary. - Beta[I]>0. - Mu0 - zeroth moment of the weight function. - N - number of nodes of the Gauss-Kronrod quadrature formula, - N >= 3, - N = 2*K+1. - -OUTPUT PARAMETERS: - Info - error code: - * -5 no real and positive Gauss-Kronrod formula can - be created for such a weight function with a - given number of nodes. - * -4 N is too large, task may be ill conditioned - - x[i]=x[i+1] found. - * -3 internal eigenproblem solver hasn't converged - * -2 Beta[i]<=0 - * -1 incorrect N was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, - in ascending order. - WKronrod - array[0..N-1] - Kronrod weights - WGauss - array[0..N-1] - Gauss weights (interleaved with zeros - corresponding to extended Kronrod nodes). - - -- ALGLIB -- - Copyright 08.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gkqgeneraterec(const real_1d_array &alpha, const real_1d_array &beta, const double mu0, const ae_int_t n, ae_int_t &info, real_1d_array &x, real_1d_array &wkronrod, real_1d_array &wgauss, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Returns Gauss and Gauss-Kronrod nodes/weights for Gauss-Legendre -quadrature with N points. - -GKQLegendreCalc (calculation) or GKQLegendreTbl (precomputed table) is -used depending on machine precision and number of nodes. - -INPUT PARAMETERS: - N - number of Kronrod nodes, must be odd number, >=3. - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. N is too large to obtain - weights/nodes with high enough accuracy. - Try to use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, ordered in - ascending order. - WKronrod - array[0..N-1] - Kronrod weights - WGauss - array[0..N-1] - Gauss weights (interleaved with zeros - corresponding to extended Kronrod nodes). - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gkqgenerategausslegendre(const ae_int_t n, ae_int_t &info, real_1d_array &x, real_1d_array &wkronrod, real_1d_array &wgauss, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Returns Gauss and Gauss-Kronrod nodes/weights for Gauss-Jacobi -quadrature on [-1,1] with weight function - - W(x)=Power(1-x,Alpha)*Power(1+x,Beta). - -INPUT PARAMETERS: - N - number of Kronrod nodes, must be odd number, >=3. - Alpha - power-law coefficient, Alpha>-1 - Beta - power-law coefficient, Beta>-1 - -OUTPUT PARAMETERS: - Info - error code: - * -5 no real and positive Gauss-Kronrod formula can - be created for such a weight function with a - given number of nodes. - * -4 an error was detected when calculating - weights/nodes. Alpha or Beta are too close - to -1 to obtain weights/nodes with high enough - accuracy, or, may be, N is too large. Try to - use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N was passed - * +1 OK - * +2 OK, but quadrature rule have exterior nodes, - x[0]<-1 or x[n-1]>+1 - X - array[0..N-1] - array of quadrature nodes, ordered in - ascending order. - WKronrod - array[0..N-1] - Kronrod weights - WGauss - array[0..N-1] - Gauss weights (interleaved with zeros - corresponding to extended Kronrod nodes). - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gkqgenerategaussjacobi(const ae_int_t n, const double alpha, const double beta, ae_int_t &info, real_1d_array &x, real_1d_array &wkronrod, real_1d_array &wgauss, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Returns Gauss and Gauss-Kronrod nodes for quadrature with N points. - -Reduction to tridiagonal eigenproblem is used. - -INPUT PARAMETERS: - N - number of Kronrod nodes, must be odd number, >=3. - -OUTPUT PARAMETERS: - Info - error code: - * -4 an error was detected when calculating - weights/nodes. N is too large to obtain - weights/nodes with high enough accuracy. - Try to use multiple precision version. - * -3 internal eigenproblem solver hasn't converged - * -1 incorrect N was passed - * +1 OK - X - array[0..N-1] - array of quadrature nodes, ordered in - ascending order. - WKronrod - array[0..N-1] - Kronrod weights - WGauss - array[0..N-1] - Gauss weights (interleaved with zeros - corresponding to extended Kronrod nodes). - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gkqlegendrecalc(const ae_int_t n, ae_int_t &info, real_1d_array &x, real_1d_array &wkronrod, real_1d_array &wgauss, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Returns Gauss and Gauss-Kronrod nodes for quadrature with N points using -pre-calculated table. Nodes/weights were computed with accuracy up to -1.0E-32 (if MPFR version of ALGLIB is used). In standard double precision -accuracy reduces to something about 2.0E-16 (depending on your compiler's -handling of long floating point constants). - -INPUT PARAMETERS: - N - number of Kronrod nodes. - N can be 15, 21, 31, 41, 51, 61. - -OUTPUT PARAMETERS: - X - array[0..N-1] - array of quadrature nodes, ordered in - ascending order. - WKronrod - array[0..N-1] - Kronrod weights - WGauss - array[0..N-1] - Gauss weights (interleaved with zeros - corresponding to extended Kronrod nodes). - - - -- ALGLIB -- - Copyright 12.05.2009 by Bochkanov Sergey -*************************************************************************/ -void gkqlegendretbl(const ae_int_t n, real_1d_array &x, real_1d_array &wkronrod, real_1d_array &wgauss, double &eps, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_AUTOGK) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Integration of a smooth function F(x) on a finite interval [a,b]. - -Fast-convergent algorithm based on a Gauss-Kronrod formula is used. Result -is calculated with accuracy close to the machine precision. - -Algorithm works well only with smooth integrands. It may be used with -continuous non-smooth integrands, but with less performance. - -It should never be used with integrands which have integrable singularities -at lower or upper limits - algorithm may crash. Use AutoGKSingular in such -cases. - -INPUT PARAMETERS: - A, B - interval boundaries (AB) - -OUTPUT PARAMETERS - State - structure which stores algorithm state - -SEE ALSO - AutoGKSmoothW, AutoGKSingular, AutoGKResults. - - - -- ALGLIB -- - Copyright 06.05.2009 by Bochkanov Sergey -*************************************************************************/ -void autogksmooth(const double a, const double b, autogkstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Integration of a smooth function F(x) on a finite interval [a,b]. - -This subroutine is same as AutoGKSmooth(), but it guarantees that interval -[a,b] is partitioned into subintervals which have width at most XWidth. - -Subroutine can be used when integrating nearly-constant function with -narrow "bumps" (about XWidth wide). If "bumps" are too narrow, AutoGKSmooth -subroutine can overlook them. - -INPUT PARAMETERS: - A, B - interval boundaries (AB) - -OUTPUT PARAMETERS - State - structure which stores algorithm state - -SEE ALSO - AutoGKSmooth, AutoGKSingular, AutoGKResults. - - - -- ALGLIB -- - Copyright 06.05.2009 by Bochkanov Sergey -*************************************************************************/ -void autogksmoothw(const double a, const double b, const double xwidth, autogkstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Integration on a finite interval [A,B]. -Integrand have integrable singularities at A/B. - -F(X) must diverge as "(x-A)^alpha" at A, as "(B-x)^beta" at B, with known -alpha/beta (alpha>-1, beta>-1). If alpha/beta are not known, estimates -from below can be used (but these estimates should be greater than -1 too). - -One of alpha/beta variables (or even both alpha/beta) may be equal to 0, -which means than function F(x) is non-singular at A/B. Anyway (singular at -bounds or not), function F(x) is supposed to be continuous on (A,B). - -Fast-convergent algorithm based on a Gauss-Kronrod formula is used. Result -is calculated with accuracy close to the machine precision. - -INPUT PARAMETERS: - A, B - interval boundaries (AB) - Alpha - power-law coefficient of the F(x) at A, - Alpha>-1 - Beta - power-law coefficient of the F(x) at B, - Beta>-1 - -OUTPUT PARAMETERS - State - structure which stores algorithm state - -SEE ALSO - AutoGKSmooth, AutoGKSmoothW, AutoGKResults. - - - -- ALGLIB -- - Copyright 06.05.2009 by Bochkanov Sergey -*************************************************************************/ -void autogksingular(const double a, const double b, const double alpha, const double beta, autogkstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool autogkiteration(const autogkstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is used to launcn iterations of the 1-dimensional integrator - -It accepts following parameters: - func - callback which calculates f(x) for given x - ptr - optional pointer which is passed to func; can be NULL - - - -- ALGLIB -- - Copyright 07.05.2009 by Bochkanov Sergey - -*************************************************************************/ -void autogkintegrate(autogkstate &state, - void (*func)(double x, double xminusa, double bminusx, double &y, void *ptr), - void *ptr = NULL, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Adaptive integration results - -Called after AutoGKIteration returned False. - -Input parameters: - State - algorithm state (used by AutoGKIteration). - -Output parameters: - V - integral(f(x)dx,a,b) - Rep - optimization report (see AutoGKReport description) - - -- ALGLIB -- - Copyright 14.11.2007 by Bochkanov Sergey -*************************************************************************/ -void autogkresults(const autogkstate &state, double &v, autogkreport &rep, const xparams _xparams = alglib::xdefault); -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (FUNCTIONS) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_GQ) || !defined(AE_PARTIAL_BUILD) -void gqgeneraterec(/* Real */ ae_vector* alpha, - /* Real */ ae_vector* beta, - double mu0, - ae_int_t n, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state); -void gqgenerategausslobattorec(/* Real */ ae_vector* alpha, - /* Real */ ae_vector* beta, - double mu0, - double a, - double b, - ae_int_t n, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state); -void gqgenerategaussradaurec(/* Real */ ae_vector* alpha, - /* Real */ ae_vector* beta, - double mu0, - double a, - ae_int_t n, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state); -void gqgenerategausslegendre(ae_int_t n, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state); -void gqgenerategaussjacobi(ae_int_t n, - double alpha, - double beta, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state); -void gqgenerategausslaguerre(ae_int_t n, - double alpha, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state); -void gqgenerategausshermite(ae_int_t n, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state); -#endif -#if defined(AE_COMPILE_GKQ) || !defined(AE_PARTIAL_BUILD) -void gkqgeneraterec(/* Real */ ae_vector* alpha, - /* Real */ ae_vector* beta, - double mu0, - ae_int_t n, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* wkronrod, - /* Real */ ae_vector* wgauss, - ae_state *_state); -void gkqgenerategausslegendre(ae_int_t n, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* wkronrod, - /* Real */ ae_vector* wgauss, - ae_state *_state); -void gkqgenerategaussjacobi(ae_int_t n, - double alpha, - double beta, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* wkronrod, - /* Real */ ae_vector* wgauss, - ae_state *_state); -void gkqlegendrecalc(ae_int_t n, - ae_int_t* info, - /* Real */ ae_vector* x, - /* Real */ ae_vector* wkronrod, - /* Real */ ae_vector* wgauss, - ae_state *_state); -void gkqlegendretbl(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* wkronrod, - /* Real */ ae_vector* wgauss, - double* eps, - ae_state *_state); -#endif -#if defined(AE_COMPILE_AUTOGK) || !defined(AE_PARTIAL_BUILD) -void autogksmooth(double a, - double b, - autogkstate* state, - ae_state *_state); -void autogksmoothw(double a, - double b, - double xwidth, - autogkstate* state, - ae_state *_state); -void autogksingular(double a, - double b, - double alpha, - double beta, - autogkstate* state, - ae_state *_state); -ae_bool autogkiteration(autogkstate* state, ae_state *_state); -void autogkresults(autogkstate* state, - double* v, - autogkreport* rep, - ae_state *_state); -void _autogkreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _autogkreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _autogkreport_clear(void* _p); -void _autogkreport_destroy(void* _p); -void _autogkinternalstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _autogkinternalstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _autogkinternalstate_clear(void* _p); -void _autogkinternalstate_destroy(void* _p); -void _autogkstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _autogkstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _autogkstate_clear(void* _p); -void _autogkstate_destroy(void* _p); -#endif - -} -#endif - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/interpolation.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/interpolation.cpp deleted file mode 100644 index fb6f2f1..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/interpolation.cpp +++ /dev/null @@ -1,55960 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifdef _MSC_VER -#define _CRT_SECURE_NO_WARNINGS -#endif -#include "stdafx.h" -#include "interpolation.h" - -// disable some irrelevant warnings -#if (AE_COMPILER==AE_MSVC) && !defined(AE_ALL_WARNINGS) -#pragma warning(disable:4100) -#pragma warning(disable:4127) -#pragma warning(disable:4611) -#pragma warning(disable:4702) -#pragma warning(disable:4996) -#endif - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_IDW) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_RATINT) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_FITSPHERE) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_INTFITSERV) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPLINE1D) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_PARAMETRIC) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPLINE3D) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_POLINT) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_LSFIT) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_RBFV2) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPLINE2D) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_RBFV1) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_RBF) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_INTCOMP) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_IDW) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Buffer object which is used to perform evaluation requests in the -multithreaded mode (multiple threads working with same IDW object). - -This object should be created with idwcreatecalcbuffer(). -*************************************************************************/ -_idwcalcbuffer_owner::_idwcalcbuffer_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_idwcalcbuffer_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::idwcalcbuffer*)alglib_impl::ae_malloc(sizeof(alglib_impl::idwcalcbuffer), &_state); - memset(p_struct, 0, sizeof(alglib_impl::idwcalcbuffer)); - alglib_impl::_idwcalcbuffer_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_idwcalcbuffer_owner::_idwcalcbuffer_owner(const _idwcalcbuffer_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_idwcalcbuffer_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: idwcalcbuffer copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::idwcalcbuffer*)alglib_impl::ae_malloc(sizeof(alglib_impl::idwcalcbuffer), &_state); - memset(p_struct, 0, sizeof(alglib_impl::idwcalcbuffer)); - alglib_impl::_idwcalcbuffer_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_idwcalcbuffer_owner& _idwcalcbuffer_owner::operator=(const _idwcalcbuffer_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: idwcalcbuffer assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: idwcalcbuffer assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_idwcalcbuffer_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::idwcalcbuffer)); - alglib_impl::_idwcalcbuffer_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_idwcalcbuffer_owner::~_idwcalcbuffer_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_idwcalcbuffer_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::idwcalcbuffer* _idwcalcbuffer_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::idwcalcbuffer* _idwcalcbuffer_owner::c_ptr() const -{ - return const_cast(p_struct); -} -idwcalcbuffer::idwcalcbuffer() : _idwcalcbuffer_owner() -{ -} - -idwcalcbuffer::idwcalcbuffer(const idwcalcbuffer &rhs):_idwcalcbuffer_owner(rhs) -{ -} - -idwcalcbuffer& idwcalcbuffer::operator=(const idwcalcbuffer &rhs) -{ - if( this==&rhs ) - return *this; - _idwcalcbuffer_owner::operator=(rhs); - return *this; -} - -idwcalcbuffer::~idwcalcbuffer() -{ -} - - -/************************************************************************* -IDW (Inverse Distance Weighting) model object. -*************************************************************************/ -_idwmodel_owner::_idwmodel_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_idwmodel_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::idwmodel*)alglib_impl::ae_malloc(sizeof(alglib_impl::idwmodel), &_state); - memset(p_struct, 0, sizeof(alglib_impl::idwmodel)); - alglib_impl::_idwmodel_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_idwmodel_owner::_idwmodel_owner(const _idwmodel_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_idwmodel_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: idwmodel copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::idwmodel*)alglib_impl::ae_malloc(sizeof(alglib_impl::idwmodel), &_state); - memset(p_struct, 0, sizeof(alglib_impl::idwmodel)); - alglib_impl::_idwmodel_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_idwmodel_owner& _idwmodel_owner::operator=(const _idwmodel_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: idwmodel assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: idwmodel assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_idwmodel_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::idwmodel)); - alglib_impl::_idwmodel_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_idwmodel_owner::~_idwmodel_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_idwmodel_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::idwmodel* _idwmodel_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::idwmodel* _idwmodel_owner::c_ptr() const -{ - return const_cast(p_struct); -} -idwmodel::idwmodel() : _idwmodel_owner() -{ -} - -idwmodel::idwmodel(const idwmodel &rhs):_idwmodel_owner(rhs) -{ -} - -idwmodel& idwmodel::operator=(const idwmodel &rhs) -{ - if( this==&rhs ) - return *this; - _idwmodel_owner::operator=(rhs); - return *this; -} - -idwmodel::~idwmodel() -{ -} - - -/************************************************************************* -Builder object used to generate IDW (Inverse Distance Weighting) model. -*************************************************************************/ -_idwbuilder_owner::_idwbuilder_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_idwbuilder_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::idwbuilder*)alglib_impl::ae_malloc(sizeof(alglib_impl::idwbuilder), &_state); - memset(p_struct, 0, sizeof(alglib_impl::idwbuilder)); - alglib_impl::_idwbuilder_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_idwbuilder_owner::_idwbuilder_owner(const _idwbuilder_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_idwbuilder_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: idwbuilder copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::idwbuilder*)alglib_impl::ae_malloc(sizeof(alglib_impl::idwbuilder), &_state); - memset(p_struct, 0, sizeof(alglib_impl::idwbuilder)); - alglib_impl::_idwbuilder_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_idwbuilder_owner& _idwbuilder_owner::operator=(const _idwbuilder_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: idwbuilder assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: idwbuilder assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_idwbuilder_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::idwbuilder)); - alglib_impl::_idwbuilder_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_idwbuilder_owner::~_idwbuilder_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_idwbuilder_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::idwbuilder* _idwbuilder_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::idwbuilder* _idwbuilder_owner::c_ptr() const -{ - return const_cast(p_struct); -} -idwbuilder::idwbuilder() : _idwbuilder_owner() -{ -} - -idwbuilder::idwbuilder(const idwbuilder &rhs):_idwbuilder_owner(rhs) -{ -} - -idwbuilder& idwbuilder::operator=(const idwbuilder &rhs) -{ - if( this==&rhs ) - return *this; - _idwbuilder_owner::operator=(rhs); - return *this; -} - -idwbuilder::~idwbuilder() -{ -} - - -/************************************************************************* -IDW fitting report: - rmserror RMS error - avgerror average error - maxerror maximum error - r2 coefficient of determination, R-squared, 1-RSS/TSS -*************************************************************************/ -_idwreport_owner::_idwreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_idwreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::idwreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::idwreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::idwreport)); - alglib_impl::_idwreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_idwreport_owner::_idwreport_owner(const _idwreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_idwreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: idwreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::idwreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::idwreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::idwreport)); - alglib_impl::_idwreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_idwreport_owner& _idwreport_owner::operator=(const _idwreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: idwreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: idwreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_idwreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::idwreport)); - alglib_impl::_idwreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_idwreport_owner::~_idwreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_idwreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::idwreport* _idwreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::idwreport* _idwreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -idwreport::idwreport() : _idwreport_owner() ,rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),maxerror(p_struct->maxerror),r2(p_struct->r2) -{ -} - -idwreport::idwreport(const idwreport &rhs):_idwreport_owner(rhs) ,rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),maxerror(p_struct->maxerror),r2(p_struct->r2) -{ -} - -idwreport& idwreport::operator=(const idwreport &rhs) -{ - if( this==&rhs ) - return *this; - _idwreport_owner::operator=(rhs); - return *this; -} - -idwreport::~idwreport() -{ -} - - -/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -void idwserialize(idwmodel &obj, std::string &s_out) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - alglib_impl::ae_int_t ssize; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_alloc_start(&serializer); - alglib_impl::idwalloc(&serializer, obj.c_ptr(), &state); - ssize = alglib_impl::ae_serializer_get_alloc_size(&serializer); - s_out.clear(); - s_out.reserve((size_t)(ssize+1)); - alglib_impl::ae_serializer_sstart_str(&serializer, &s_out); - alglib_impl::idwserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_assert( s_out.length()<=(size_t)ssize, "ALGLIB: serialization integrity error", &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} -/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -void idwunserialize(const std::string &s_in, idwmodel &obj) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_ustart_str(&serializer, &s_in); - alglib_impl::idwunserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} - - -/************************************************************************* -This function serializes data structure to C++ stream. - -Data stream generated by this function is same as string representation -generated by string version of serializer - alphanumeric characters, -dots, underscores, minus signs, which are grouped into words separated by -spaces and CR+LF. - -We recommend you to read comments on string version of serializer to find -out more about serialization of AlGLIB objects. -*************************************************************************/ -void idwserialize(idwmodel &obj, std::ostream &s_out) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_alloc_start(&serializer); - alglib_impl::idwalloc(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_get_alloc_size(&serializer); // not actually needed, but we have to ask - alglib_impl::ae_serializer_sstart_stream(&serializer, &s_out); - alglib_impl::idwserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} -/************************************************************************* -This function unserializes data structure from stream. -*************************************************************************/ -void idwunserialize(const std::istream &s_in, idwmodel &obj) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_ustart_stream(&serializer, &s_in); - alglib_impl::idwunserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} - -/************************************************************************* -This function creates buffer structure which can be used to perform -parallel IDW model evaluations (with one IDW model instance being -used from multiple threads, as long as different threads use different -instances of buffer). - -This buffer object can be used with idwtscalcbuf() function (here "ts" -stands for "thread-safe", "buf" is a suffix which denotes function which -reuses previously allocated output space). - -How to use it: -* create IDW model structure or load it from file -* call idwcreatecalcbuffer(), once per thread working with IDW model (you - should call this function only AFTER model initialization, see below for - more information) -* call idwtscalcbuf() from different threads, with each thread working - with its own copy of buffer object. - -INPUT PARAMETERS - S - IDW model - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: buffer object should be used only with IDW model object which - was used to initialize buffer. Any attempt to use buffer with - different object is dangerous - you may get memory violation - error because sizes of internal arrays do not fit to dimensions - of the IDW structure. - -IMPORTANT: you should call this function only for model which was built - with model builder (or unserialized from file). Sizes of some - internal structures are determined only after model is built, - so buffer object created before model construction stage will - be useless (and any attempt to use it will result in exception). - - -- ALGLIB -- - Copyright 22.10.2018 by Sergey Bochkanov -*************************************************************************/ -void idwcreatecalcbuffer(const idwmodel &s, idwcalcbuffer &buf, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::idwcreatecalcbuffer(const_cast(s.c_ptr()), const_cast(buf.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine creates builder object used to generate IDW model from -irregularly sampled (scattered) dataset. Multidimensional scalar/vector- --valued are supported. - -Builder object is used to fit model to data as follows: -* builder object is created with idwbuildercreate() function -* dataset is added with idwbuildersetpoints() function -* one of the modern IDW algorithms is chosen with either: - * idwbuildersetalgomstab() - Multilayer STABilized algorithm (interpolation) - Alternatively, one of the textbook algorithms can be chosen (not recommended): - * idwbuildersetalgotextbookshepard() - textbook Shepard algorithm - * idwbuildersetalgotextbookmodshepard()-textbook modified Shepard algorithm -* finally, model construction is performed with idwfit() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - NX - dimensionality of the argument, NX>=1 - NY - dimensionality of the function being modeled, NY>=1; - NY=1 corresponds to classic scalar function, NY>=1 corresponds - to vector-valued function. - -OUTPUT PARAMETERS: - State- builder object - - -- ALGLIB PROJECT -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildercreate(const ae_int_t nx, const ae_int_t ny, idwbuilder &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::idwbuildercreate(nx, ny, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function changes number of layers used by IDW-MSTAB algorithm. - -The more layers you have, the finer details can be reproduced with IDW -model. The less layers you have, the less memory and CPU time is consumed -by the model. - -Memory consumption grows linearly with layers count, running time grows -sub-linearly. - -The default number of layers is 16, which allows you to reproduce details -at distance down to SRad/65536. You will rarely need to change it. - -INPUT PARAMETERS: - State - builder object - NLayers - NLayers>=1, the number of layers used by the model. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetnlayers(const idwbuilder &state, const ae_int_t nlayers, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::idwbuildersetnlayers(const_cast(state.c_ptr()), nlayers, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function adds dataset to the builder object. - -This function overrides results of the previous calls, i.e. multiple calls -of this function will result in only the last set being added. - -INPUT PARAMETERS: - State - builder object - XY - points, array[N,NX+NY]. One row corresponds to one point - in the dataset. First NX elements are coordinates, next - NY elements are function values. Array may be larger than - specified, in this case only leading [N,NX+NY] elements - will be used. - N - number of points in the dataset, N>=0. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetpoints(const idwbuilder &state, const real_2d_array &xy, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::idwbuildersetpoints(const_cast(state.c_ptr()), const_cast(xy.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function adds dataset to the builder object. - -This function overrides results of the previous calls, i.e. multiple calls -of this function will result in only the last set being added. - -INPUT PARAMETERS: - State - builder object - XY - points, array[N,NX+NY]. One row corresponds to one point - in the dataset. First NX elements are coordinates, next - NY elements are function values. Array may be larger than - specified, in this case only leading [N,NX+NY] elements - will be used. - N - number of points in the dataset, N>=0. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void idwbuildersetpoints(const idwbuilder &state, const real_2d_array &xy, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = xy.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::idwbuildersetpoints(const_cast(state.c_ptr()), const_cast(xy.c_ptr()), n, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets IDW model construction algorithm to the Multilayer -Stabilized IDW method (IDW-MSTAB), a latest incarnation of the inverse -distance weighting interpolation which fixes shortcomings of the original -and modified Shepard's variants. - -The distinctive features of IDW-MSTAB are: -1) exact interpolation is pursued (as opposed to fitting and noise - suppression) -2) improved robustness when compared with that of other algorithms: - * MSTAB shows almost no strange fitting artifacts like ripples and - sharp spikes (unlike N-dimensional splines and HRBFs) - * MSTAB does not return function values far from the interval spanned - by the dataset; say, if all your points have |f|<=1, you can be sure - that model value won't deviate too much from [-1,+1] -3) good model construction time competing with that of HRBFs and bicubic - splines -4) ability to work with any number of dimensions, starting from NX=1 - -The drawbacks of IDW-MSTAB (and all IDW algorithms in general) are: -1) dependence of the model evaluation time on the search radius -2) bad extrapolation properties, models built by this method are usually - conservative in their predictions - -Thus, IDW-MSTAB is a good "default" option if you want to perform -scattered multidimensional interpolation. Although it has its drawbacks, -it is easy to use and robust, which makes it a good first step. - - -INPUT PARAMETERS: - State - builder object - SRad - initial search radius, SRad>0 is required. A model value - is obtained by "smart" averaging of the dataset points - within search radius. - -NOTE 1: IDW interpolation can correctly handle ANY dataset, including - datasets with non-distinct points. In case non-distinct points are - found, an average value for this point will be calculated. - -NOTE 2: the memory requirements for model storage are O(NPoints*NLayers). - The model construction needs twice as much memory as model storage. - -NOTE 3: by default 16 IDW layers are built which is enough for most cases. - You can change this parameter with idwbuildersetnlayers() method. - Larger values may be necessary if you need to reproduce extrafine - details at distances smaller than SRad/65536. Smaller value may - be necessary if you have to save memory and computing time, and - ready to sacrifice some model quality. - - -ALGORITHM DESCRIPTION - -ALGLIB implementation of IDW is somewhat similar to the modified Shepard's -method (one with search radius R) but overcomes several of its drawbacks, -namely: -1) a tendency to show stepwise behavior for uniform datasets -2) a tendency to show terrible interpolation properties for highly - nonuniform datasets which often arise in geospatial tasks - (function values are densely sampled across multiple separated - "tracks") - -IDW-MSTAB method performs several passes over dataset and builds a sequence -of progressively refined IDW models (layers), which starts from one with -largest search radius SRad and continues to smaller search radii until -required number of layers is built. Highest layers reproduce global -behavior of the target function at larger distances whilst lower layers -reproduce fine details at smaller distances. - -Each layer is an IDW model built with following modifications: -* weights go to zero when distance approach to the current search radius -* an additional regularizing term is added to the distance: w=1/(d^2+lambda) -* an additional fictional term with unit weight and zero function value is - added in order to promote continuity properties at the isolated and - boundary points - -By default, 16 layers is built, which is enough for most cases. You can -change this parameter with idwbuildersetnlayers() method. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetalgomstab(const idwbuilder &state, const double srad, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::idwbuildersetalgomstab(const_cast(state.c_ptr()), srad, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets IDW model construction algorithm to the textbook -Shepard's algorithm with custom (user-specified) power parameter. - -IMPORTANT: we do NOT recommend using textbook IDW algorithms because they - have terrible interpolation properties. Use MSTAB in all cases. - -INPUT PARAMETERS: - State - builder object - P - power parameter, P>0; good value to start with is 2.0 - -NOTE 1: IDW interpolation can correctly handle ANY dataset, including - datasets with non-distinct points. In case non-distinct points are - found, an average value for this point will be calculated. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetalgotextbookshepard(const idwbuilder &state, const double p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::idwbuildersetalgotextbookshepard(const_cast(state.c_ptr()), p, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets IDW model construction algorithm to the 'textbook' -modified Shepard's algorithm with user-specified search radius. - -IMPORTANT: we do NOT recommend using textbook IDW algorithms because they - have terrible interpolation properties. Use MSTAB in all cases. - -INPUT PARAMETERS: - State - builder object - R - search radius - -NOTE 1: IDW interpolation can correctly handle ANY dataset, including - datasets with non-distinct points. In case non-distinct points are - found, an average value for this point will be calculated. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetalgotextbookmodshepard(const idwbuilder &state, const double r, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::idwbuildersetalgotextbookmodshepard(const_cast(state.c_ptr()), r, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets prior term (model value at infinity) as user-specified -value. - -INPUT PARAMETERS: - S - spline builder - V - value for user-defined prior - -NOTE: for vector-valued models all components of the prior are set to same - user-specified value - - -- ALGLIB -- - Copyright 29.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetuserterm(const idwbuilder &state, const double v, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::idwbuildersetuserterm(const_cast(state.c_ptr()), v, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets constant prior term (model value at infinity). - -Constant prior term is determined as mean value over dataset. - -INPUT PARAMETERS: - S - spline builder - - -- ALGLIB -- - Copyright 29.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetconstterm(const idwbuilder &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::idwbuildersetconstterm(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets zero prior term (model value at infinity). - -INPUT PARAMETERS: - S - spline builder - - -- ALGLIB -- - Copyright 29.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetzeroterm(const idwbuilder &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::idwbuildersetzeroterm(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -IDW interpolation: scalar target, 1-dimensional argument - -NOTE: this function modifies internal temporaries of the IDW model, thus - IT IS NOT THREAD-SAFE! If you want to perform parallel model - evaluation from the multiple threads, use idwtscalcbuf() with per- - thread buffer object. - -INPUT PARAMETERS: - S - IDW interpolant built with IDW builder - X0 - argument value - -Result: - IDW interpolant S(X0) - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -double idwcalc1(const idwmodel &s, const double x0, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::idwcalc1(const_cast(s.c_ptr()), x0, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -IDW interpolation: scalar target, 2-dimensional argument - -NOTE: this function modifies internal temporaries of the IDW model, thus - IT IS NOT THREAD-SAFE! If you want to perform parallel model - evaluation from the multiple threads, use idwtscalcbuf() with per- - thread buffer object. - -INPUT PARAMETERS: - S - IDW interpolant built with IDW builder - X0, X1 - argument value - -Result: - IDW interpolant S(X0,X1) - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -double idwcalc2(const idwmodel &s, const double x0, const double x1, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::idwcalc2(const_cast(s.c_ptr()), x0, x1, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -IDW interpolation: scalar target, 3-dimensional argument - -NOTE: this function modifies internal temporaries of the IDW model, thus - IT IS NOT THREAD-SAFE! If you want to perform parallel model - evaluation from the multiple threads, use idwtscalcbuf() with per- - thread buffer object. - -INPUT PARAMETERS: - S - IDW interpolant built with IDW builder - X0,X1,X2- argument value - -Result: - IDW interpolant S(X0,X1,X2) - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -double idwcalc3(const idwmodel &s, const double x0, const double x1, const double x2, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::idwcalc3(const_cast(s.c_ptr()), x0, x1, x2, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function calculates values of the IDW model at the given point. - -This is general function which can be used for arbitrary NX (dimension of -the space of arguments) and NY (dimension of the function itself). However -when you have NY=1 you may find more convenient to use idwcalc1(), -idwcalc2() or idwcalc3(). - -NOTE: this function modifies internal temporaries of the IDW model, thus - IT IS NOT THREAD-SAFE! If you want to perform parallel model - evaluation from the multiple threads, use idwtscalcbuf() with per- - thread buffer object. - -INPUT PARAMETERS: - S - IDW model - X - coordinates, array[NX]. X may have more than NX elements, - in this case only leading NX will be used. - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is out-parameter and will be - reallocated after call to this function. In case you want - to reuse previously allocated Y, you may use idwcalcbuf(), - which reallocates Y only when it is too small. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwcalc(const idwmodel &s, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::idwcalc(const_cast(s.c_ptr()), const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates values of the IDW model at the given point. - -Same as idwcalc(), but does not reallocate Y when in is large enough to -store function values. - -NOTE: this function modifies internal temporaries of the IDW model, thus - IT IS NOT THREAD-SAFE! If you want to perform parallel model - evaluation from the multiple threads, use idwtscalcbuf() with per- - thread buffer object. - -INPUT PARAMETERS: - S - IDW model - X - coordinates, array[NX]. X may have more than NX elements, - in this case only leading NX will be used. - Y - possibly preallocated array - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is not reallocated when it - is larger than NY. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwcalcbuf(const idwmodel &s, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::idwcalcbuf(const_cast(s.c_ptr()), const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates values of the IDW model at the given point, using -external buffer object (internal temporaries of IDW model are not -modified). - -This function allows to use same IDW model object in different threads, -assuming that different threads use different instances of the buffer -structure. - -INPUT PARAMETERS: - S - IDW model, may be shared between different threads - Buf - buffer object created for this particular instance of IDW - model with idwcreatecalcbuffer(). - X - coordinates, array[NX]. X may have more than NX elements, - in this case only leading NX will be used. - Y - possibly preallocated array - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is not reallocated when it - is larger than NY. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void idwtscalcbuf(const idwmodel &s, const idwcalcbuffer &buf, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::idwtscalcbuf(const_cast(s.c_ptr()), const_cast(buf.c_ptr()), const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function fits IDW model to the dataset using current IDW construction -algorithm. A model being built and fitting report are returned. - -INPUT PARAMETERS: - State - builder object - -OUTPUT PARAMETERS: - Model - an IDW model built with current algorithm - Rep - model fitting report, fields of this structure contain - information about average fitting errors. - -NOTE: although IDW-MSTAB algorithm is an interpolation method, i.e. it - tries to fit the model exactly, it can handle datasets with non- - distinct points which can not be fit exactly; in such cases least- - squares fitting is performed. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwfit(const idwbuilder &state, idwmodel &model, idwreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::idwfit(const_cast(state.c_ptr()), const_cast(model.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_RATINT) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Barycentric interpolant. -*************************************************************************/ -_barycentricinterpolant_owner::_barycentricinterpolant_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_barycentricinterpolant_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::barycentricinterpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::barycentricinterpolant), &_state); - memset(p_struct, 0, sizeof(alglib_impl::barycentricinterpolant)); - alglib_impl::_barycentricinterpolant_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_barycentricinterpolant_owner::_barycentricinterpolant_owner(const _barycentricinterpolant_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_barycentricinterpolant_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: barycentricinterpolant copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::barycentricinterpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::barycentricinterpolant), &_state); - memset(p_struct, 0, sizeof(alglib_impl::barycentricinterpolant)); - alglib_impl::_barycentricinterpolant_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_barycentricinterpolant_owner& _barycentricinterpolant_owner::operator=(const _barycentricinterpolant_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: barycentricinterpolant assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: barycentricinterpolant assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_barycentricinterpolant_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::barycentricinterpolant)); - alglib_impl::_barycentricinterpolant_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_barycentricinterpolant_owner::~_barycentricinterpolant_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_barycentricinterpolant_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::barycentricinterpolant* _barycentricinterpolant_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::barycentricinterpolant* _barycentricinterpolant_owner::c_ptr() const -{ - return const_cast(p_struct); -} -barycentricinterpolant::barycentricinterpolant() : _barycentricinterpolant_owner() -{ -} - -barycentricinterpolant::barycentricinterpolant(const barycentricinterpolant &rhs):_barycentricinterpolant_owner(rhs) -{ -} - -barycentricinterpolant& barycentricinterpolant::operator=(const barycentricinterpolant &rhs) -{ - if( this==&rhs ) - return *this; - _barycentricinterpolant_owner::operator=(rhs); - return *this; -} - -barycentricinterpolant::~barycentricinterpolant() -{ -} - -/************************************************************************* -Rational interpolation using barycentric formula - -F(t) = SUM(i=0,n-1,w[i]*f[i]/(t-x[i])) / SUM(i=0,n-1,w[i]/(t-x[i])) - -Input parameters: - B - barycentric interpolant built with one of model building - subroutines. - T - interpolation point - -Result: - barycentric interpolant F(t) - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -double barycentriccalc(const barycentricinterpolant &b, const double t, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::barycentriccalc(const_cast(b.c_ptr()), t, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Differentiation of barycentric interpolant: first derivative. - -Algorithm used in this subroutine is very robust and should not fail until -provided with values too close to MaxRealNumber (usually MaxRealNumber/N -or greater will overflow). - -INPUT PARAMETERS: - B - barycentric interpolant built with one of model building - subroutines. - T - interpolation point - -OUTPUT PARAMETERS: - F - barycentric interpolant at T - DF - first derivative - -NOTE - - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentricdiff1(const barycentricinterpolant &b, const double t, double &f, double &df, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::barycentricdiff1(const_cast(b.c_ptr()), t, &f, &df, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Differentiation of barycentric interpolant: first/second derivatives. - -INPUT PARAMETERS: - B - barycentric interpolant built with one of model building - subroutines. - T - interpolation point - -OUTPUT PARAMETERS: - F - barycentric interpolant at T - DF - first derivative - D2F - second derivative - -NOTE: this algorithm may fail due to overflow/underflor if used on data -whose values are close to MaxRealNumber or MinRealNumber. Use more robust -BarycentricDiff1() subroutine in such cases. - - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentricdiff2(const barycentricinterpolant &b, const double t, double &f, double &df, double &d2f, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::barycentricdiff2(const_cast(b.c_ptr()), t, &f, &df, &d2f, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine performs linear transformation of the argument. - -INPUT PARAMETERS: - B - rational interpolant in barycentric form - CA, CB - transformation coefficients: x = CA*t + CB - -OUTPUT PARAMETERS: - B - transformed interpolant with X replaced by T - - -- ALGLIB PROJECT -- - Copyright 19.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentriclintransx(const barycentricinterpolant &b, const double ca, const double cb, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::barycentriclintransx(const_cast(b.c_ptr()), ca, cb, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine performs linear transformation of the barycentric -interpolant. - -INPUT PARAMETERS: - B - rational interpolant in barycentric form - CA, CB - transformation coefficients: B2(x) = CA*B(x) + CB - -OUTPUT PARAMETERS: - B - transformed interpolant - - -- ALGLIB PROJECT -- - Copyright 19.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentriclintransy(const barycentricinterpolant &b, const double ca, const double cb, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::barycentriclintransy(const_cast(b.c_ptr()), ca, cb, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Extracts X/Y/W arrays from rational interpolant - -INPUT PARAMETERS: - B - barycentric interpolant - -OUTPUT PARAMETERS: - N - nodes count, N>0 - X - interpolation nodes, array[0..N-1] - F - function values, array[0..N-1] - W - barycentric weights, array[0..N-1] - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentricunpack(const barycentricinterpolant &b, ae_int_t &n, real_1d_array &x, real_1d_array &y, real_1d_array &w, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::barycentricunpack(const_cast(b.c_ptr()), &n, const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(w.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Rational interpolant from X/Y/W arrays - -F(t) = SUM(i=0,n-1,w[i]*f[i]/(t-x[i])) / SUM(i=0,n-1,w[i]/(t-x[i])) - -INPUT PARAMETERS: - X - interpolation nodes, array[0..N-1] - F - function values, array[0..N-1] - W - barycentric weights, array[0..N-1] - N - nodes count, N>0 - -OUTPUT PARAMETERS: - B - barycentric interpolant built from (X, Y, W) - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentricbuildxyw(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t n, barycentricinterpolant &b, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::barycentricbuildxyw(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(w.c_ptr()), n, const_cast(b.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Rational interpolant without poles - -The subroutine constructs the rational interpolating function without real -poles (see 'Barycentric rational interpolation with no poles and high -rates of approximation', Michael S. Floater. and Kai Hormann, for more -information on this subject). - -Input parameters: - X - interpolation nodes, array[0..N-1]. - Y - function values, array[0..N-1]. - N - number of nodes, N>0. - D - order of the interpolation scheme, 0 <= D <= N-1. - D<0 will cause an error. - D>=N it will be replaced with D=N-1. - if you don't know what D to choose, use small value about 3-5. - -Output parameters: - B - barycentric interpolant. - -Note: - this algorithm always succeeds and calculates the weights with close - to machine precision. - - -- ALGLIB PROJECT -- - Copyright 17.06.2007 by Bochkanov Sergey -*************************************************************************/ -void barycentricbuildfloaterhormann(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t d, barycentricinterpolant &b, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::barycentricbuildfloaterhormann(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, d, const_cast(b.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_FITSPHERE) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Fits least squares (LS) circle (or NX-dimensional sphere) to data (a set -of points in NX-dimensional space). - -Least squares circle minimizes sum of squared deviations between distances -from points to the center and some "candidate" radius, which is also -fitted to the data. - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - -OUTPUT PARAMETERS: - CX - central point for a sphere - R - radius - - -- ALGLIB -- - Copyright 07.05.2018 by Bochkanov Sergey -*************************************************************************/ -void fitspherels(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &r, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::fitspherels(const_cast(xy.c_ptr()), npoints, nx, const_cast(cx.c_ptr()), &r, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Fits minimum circumscribed (MC) circle (or NX-dimensional sphere) to data -(a set of points in NX-dimensional space). - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - -OUTPUT PARAMETERS: - CX - central point for a sphere - RHi - radius - -NOTE: this function is an easy-to-use wrapper around more powerful "expert" - function fitspherex(). - - This wrapper is optimized for ease of use and stability - at the - cost of somewhat lower performance (we have to use very tight - stopping criteria for inner optimizer because we want to make sure - that it will converge on any dataset). - - If you are ready to experiment with settings of "expert" function, - you can achieve ~2-4x speedup over standard "bulletproof" settings. - - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void fitspheremc(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &rhi, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::fitspheremc(const_cast(xy.c_ptr()), npoints, nx, const_cast(cx.c_ptr()), &rhi, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Fits maximum inscribed circle (or NX-dimensional sphere) to data (a set of -points in NX-dimensional space). - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - -OUTPUT PARAMETERS: - CX - central point for a sphere - RLo - radius - -NOTE: this function is an easy-to-use wrapper around more powerful "expert" - function fitspherex(). - - This wrapper is optimized for ease of use and stability - at the - cost of somewhat lower performance (we have to use very tight - stopping criteria for inner optimizer because we want to make sure - that it will converge on any dataset). - - If you are ready to experiment with settings of "expert" function, - you can achieve ~2-4x speedup over standard "bulletproof" settings. - - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void fitspheremi(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &rlo, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::fitspheremi(const_cast(xy.c_ptr()), npoints, nx, const_cast(cx.c_ptr()), &rlo, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Fits minimum zone circle (or NX-dimensional sphere) to data (a set of -points in NX-dimensional space). - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - -OUTPUT PARAMETERS: - CX - central point for a sphere - RLo - radius of inscribed circle - RHo - radius of circumscribed circle - -NOTE: this function is an easy-to-use wrapper around more powerful "expert" - function fitspherex(). - - This wrapper is optimized for ease of use and stability - at the - cost of somewhat lower performance (we have to use very tight - stopping criteria for inner optimizer because we want to make sure - that it will converge on any dataset). - - If you are ready to experiment with settings of "expert" function, - you can achieve ~2-4x speedup over standard "bulletproof" settings. - - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void fitspheremz(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &rlo, double &rhi, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::fitspheremz(const_cast(xy.c_ptr()), npoints, nx, const_cast(cx.c_ptr()), &rlo, &rhi, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Fitting minimum circumscribed, maximum inscribed or minimum zone circles -(or NX-dimensional spheres) to data (a set of points in NX-dimensional -space). - -This is expert function which allows to tweak many parameters of -underlying nonlinear solver: -* stopping criteria for inner iterations -* number of outer iterations -* penalty coefficient used to handle nonlinear constraints (we convert - unconstrained nonsmooth optimization problem ivolving max() and/or min() - operations to quadratically constrained smooth one). - -You may tweak all these parameters or only some of them, leaving other -ones at their default state - just specify zero value, and solver will -fill it with appropriate default one. - -These comments also include some discussion of approach used to handle -such unusual fitting problem, its stability, drawbacks of alternative -methods, and convergence properties. - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - ProblemType-used to encode problem type: - * 0 for least squares circle - * 1 for minimum circumscribed circle/sphere fitting (MC) - * 2 for maximum inscribed circle/sphere fitting (MI) - * 3 for minimum zone circle fitting (difference between - Rhi and Rlo is minimized), denoted as MZ - EpsX - stopping condition for NLC optimizer: - * must be non-negative - * use 0 to choose default value (1.0E-12 is used by default) - * you may specify larger values, up to 1.0E-6, if you want - to speed-up solver; NLC solver performs several - preconditioned outer iterations, so final result - typically has precision much better than EpsX. - AULIts - number of outer iterations performed by NLC optimizer: - * must be non-negative - * use 0 to choose default value (20 is used by default) - * you may specify values smaller than 20 if you want to - speed up solver; 10 often results in good combination of - precision and speed; sometimes you may get good results - with just 6 outer iterations. - Ignored for ProblemType=0. - Penalty - penalty coefficient for NLC optimizer: - * must be non-negative - * use 0 to choose default value (1.0E6 in current version) - * it should be really large, 1.0E6...1.0E7 is a good value - to start from; - * generally, default value is good enough - Ignored for ProblemType=0. - -OUTPUT PARAMETERS: - CX - central point for a sphere - RLo - radius: - * for ProblemType=2,3, radius of the inscribed sphere - * for ProblemType=0 - radius of the least squares sphere - * for ProblemType=1 - zero - RHo - radius: - * for ProblemType=1,3, radius of the circumscribed sphere - * for ProblemType=0 - radius of the least squares sphere - * for ProblemType=2 - zero - -NOTE: ON THE UNIQUENESS OF SOLUTIONS - -ALGLIB provides solution to several related circle fitting problems: MC -(minimum circumscribed), MI (maximum inscribed) and MZ (minimum zone) -fitting, LS (least squares) fitting. - -It is important to note that among these problems only MC and LS are -convex and have unique solution independently from starting point. - -As for MI, it may (or may not, depending on dataset properties) have -multiple solutions, and it always has one degenerate solution C=infinity -which corresponds to infinitely large radius. Thus, there are no guarantees -that solution to MI returned by this solver will be the best one (and no -one can provide you with such guarantee because problem is NP-hard). The -only guarantee you have is that this solution is locally optimal, i.e. it -can not be improved by infinitesimally small tweaks in the parameters. - -It is also possible to "run away" to infinity when started from bad -initial point located outside of point cloud (or when point cloud does not -span entire circumference/surface of the sphere). - -Finally, MZ (minimum zone circle) stands somewhere between MC and MI in -stability. It is somewhat regularized by "circumscribed" term of the merit -function; however, solutions to MZ may be non-unique, and in some unlucky -cases it is also possible to "run away to infinity". - - -NOTE: ON THE NONLINEARLY CONSTRAINED PROGRAMMING APPROACH - -The problem formulation for MC (minimum circumscribed circle; for the -sake of simplicity we omit MZ and MI here) is: - - [ [ ]2 ] - min [ max [ XY[i]-C ] ] - C [ i [ ] ] - -i.e. it is unconstrained nonsmooth optimization problem of finding "best" -central point, with radius R being unambiguously determined from C. In -order to move away from non-smoothness we use following reformulation: - - [ ] [ ]2 - min [ R ] subject to R>=0, [ XY[i]-C ] <= R^2 - C,R [ ] [ ] - -i.e. it becomes smooth quadratically constrained optimization problem with -linear target function. Such problem statement is 100% equivalent to the -original nonsmooth one, but much easier to approach. We solve it with -MinNLC solver provided by ALGLIB. - - -NOTE: ON INSTABILITY OF SEQUENTIAL LINEARIZATION APPROACH - -ALGLIB has nonlinearly constrained solver which proved to be stable on -such problems. However, some authors proposed to linearize constraints in -the vicinity of current approximation (Ci,Ri) and to get next approximate -solution (Ci+1,Ri+1) as solution to linear programming problem. Obviously, -LP problems are easier than nonlinearly constrained ones. - -Indeed, such approach to MC/MI/MZ resulted in ~10-20x increase in -performance (when compared with NLC solver). However, it turned out that -in some cases linearized model fails to predict correct direction for next -step and tells us that we converged to solution even when we are still 2-4 -digits of precision away from it. - -It is important that it is not failure of LP solver - it is failure of the -linear model; even when solved exactly, it fails to handle subtle -nonlinearities which arise near the solution. We validated it by comparing -results returned by ALGLIB linear solver with that of MATLAB. - -In our experiments with linearization: -* MC failed most often, at both realistic and synthetic datasets -* MI sometimes failed, but sometimes succeeded -* MZ often succeeded; our guess is that presence of two independent sets - of constraints (one set for Rlo and another one for Rhi) and two terms - in the target function (Rlo and Rhi) regularizes task, so when linear - model fails to handle nonlinearities from Rlo, it uses Rhi as a hint - (and vice versa). - -Because linearization approach failed to achieve stable results, we do not -include it in ALGLIB. - - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void fitspherex(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, const ae_int_t problemtype, const double epsx, const ae_int_t aulits, const double penalty, real_1d_array &cx, double &rlo, double &rhi, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::fitspherex(const_cast(xy.c_ptr()), npoints, nx, problemtype, epsx, aulits, penalty, const_cast(cx.c_ptr()), &rlo, &rhi, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_INTFITSERV) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPLINE1D) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -1-dimensional spline interpolant -*************************************************************************/ -_spline1dinterpolant_owner::_spline1dinterpolant_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_spline1dinterpolant_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::spline1dinterpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline1dinterpolant), &_state); - memset(p_struct, 0, sizeof(alglib_impl::spline1dinterpolant)); - alglib_impl::_spline1dinterpolant_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_spline1dinterpolant_owner::_spline1dinterpolant_owner(const _spline1dinterpolant_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_spline1dinterpolant_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline1dinterpolant copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::spline1dinterpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline1dinterpolant), &_state); - memset(p_struct, 0, sizeof(alglib_impl::spline1dinterpolant)); - alglib_impl::_spline1dinterpolant_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_spline1dinterpolant_owner& _spline1dinterpolant_owner::operator=(const _spline1dinterpolant_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: spline1dinterpolant assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline1dinterpolant assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_spline1dinterpolant_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::spline1dinterpolant)); - alglib_impl::_spline1dinterpolant_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_spline1dinterpolant_owner::~_spline1dinterpolant_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_spline1dinterpolant_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::spline1dinterpolant* _spline1dinterpolant_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::spline1dinterpolant* _spline1dinterpolant_owner::c_ptr() const -{ - return const_cast(p_struct); -} -spline1dinterpolant::spline1dinterpolant() : _spline1dinterpolant_owner() -{ -} - -spline1dinterpolant::spline1dinterpolant(const spline1dinterpolant &rhs):_spline1dinterpolant_owner(rhs) -{ -} - -spline1dinterpolant& spline1dinterpolant::operator=(const spline1dinterpolant &rhs) -{ - if( this==&rhs ) - return *this; - _spline1dinterpolant_owner::operator=(rhs); - return *this; -} - -spline1dinterpolant::~spline1dinterpolant() -{ -} - - -/************************************************************************* -Spline fitting report: - RMSError RMS error - AvgError average error - AvgRelError average relative error (for non-zero Y[I]) - MaxError maximum error - -Fields below are filled by obsolete functions (Spline1DFitCubic, -Spline1DFitHermite). Modern fitting functions do NOT fill these fields: - TaskRCond reciprocal of task's condition number -*************************************************************************/ -_spline1dfitreport_owner::_spline1dfitreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_spline1dfitreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::spline1dfitreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline1dfitreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::spline1dfitreport)); - alglib_impl::_spline1dfitreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_spline1dfitreport_owner::_spline1dfitreport_owner(const _spline1dfitreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_spline1dfitreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline1dfitreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::spline1dfitreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline1dfitreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::spline1dfitreport)); - alglib_impl::_spline1dfitreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_spline1dfitreport_owner& _spline1dfitreport_owner::operator=(const _spline1dfitreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: spline1dfitreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline1dfitreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_spline1dfitreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::spline1dfitreport)); - alglib_impl::_spline1dfitreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_spline1dfitreport_owner::~_spline1dfitreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_spline1dfitreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::spline1dfitreport* _spline1dfitreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::spline1dfitreport* _spline1dfitreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -spline1dfitreport::spline1dfitreport() : _spline1dfitreport_owner() ,taskrcond(p_struct->taskrcond),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),maxerror(p_struct->maxerror) -{ -} - -spline1dfitreport::spline1dfitreport(const spline1dfitreport &rhs):_spline1dfitreport_owner(rhs) ,taskrcond(p_struct->taskrcond),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),maxerror(p_struct->maxerror) -{ -} - -spline1dfitreport& spline1dfitreport::operator=(const spline1dfitreport &rhs) -{ - if( this==&rhs ) - return *this; - _spline1dfitreport_owner::operator=(rhs); - return *this; -} - -spline1dfitreport::~spline1dfitreport() -{ -} - -/************************************************************************* -This subroutine builds linear spline interpolant - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1] - Y - function values, array[0..N-1] - N - points count (optional): - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - -OUTPUT PARAMETERS: - C - spline interpolant - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - - -- ALGLIB PROJECT -- - Copyright 24.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dbuildlinear(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, spline1dinterpolant &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dbuildlinear(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine builds linear spline interpolant - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1] - Y - function values, array[0..N-1] - N - points count (optional): - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - -OUTPUT PARAMETERS: - C - spline interpolant - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - - -- ALGLIB PROJECT -- - Copyright 24.06.2007 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spline1dbuildlinear(const real_1d_array &x, const real_1d_array &y, spline1dinterpolant &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (x.length()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dbuildlinear': looks like one of arguments has wrong size"); - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dbuildlinear(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, const_cast(c.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This subroutine builds cubic spline interpolant. - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1]. - Y - function values, array[0..N-1]. - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - -OUTPUT PARAMETERS: - C - spline interpolant - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 23.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dbuildcubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t boundltype, const double boundl, const ae_int_t boundrtype, const double boundr, spline1dinterpolant &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dbuildcubic(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine builds cubic spline interpolant. - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1]. - Y - function values, array[0..N-1]. - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - -OUTPUT PARAMETERS: - C - spline interpolant - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 23.06.2007 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spline1dbuildcubic(const real_1d_array &x, const real_1d_array &y, spline1dinterpolant &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t boundltype; - double boundl; - ae_int_t boundrtype; - double boundr; - if( (x.length()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dbuildcubic': looks like one of arguments has wrong size"); - n = x.length(); - boundltype = 0; - boundl = 0; - boundrtype = 0; - boundr = 0; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dbuildcubic(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast(c.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function solves following problem: given table y[] of function values -at nodes x[], it calculates and returns table of function derivatives d[] -(calculated at the same nodes x[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - spline nodes - Y - function values - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - -OUTPUT PARAMETERS: - D - derivative values at X[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Derivative values are correctly reordered on return, so D[I] is always -equal to S'(X[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -void spline1dgriddiffcubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t boundltype, const double boundl, const ae_int_t boundrtype, const double boundr, real_1d_array &d, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dgriddiffcubic(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast(d.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function solves following problem: given table y[] of function values -at nodes x[], it calculates and returns table of function derivatives d[] -(calculated at the same nodes x[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - spline nodes - Y - function values - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - -OUTPUT PARAMETERS: - D - derivative values at X[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Derivative values are correctly reordered on return, so D[I] is always -equal to S'(X[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spline1dgriddiffcubic(const real_1d_array &x, const real_1d_array &y, real_1d_array &d, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t boundltype; - double boundl; - ae_int_t boundrtype; - double boundr; - if( (x.length()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dgriddiffcubic': looks like one of arguments has wrong size"); - n = x.length(); - boundltype = 0; - boundl = 0; - boundrtype = 0; - boundr = 0; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dgriddiffcubic(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast(d.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function solves following problem: given table y[] of function values -at nodes x[], it calculates and returns tables of first and second -function derivatives d1[] and d2[] (calculated at the same nodes x[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - spline nodes - Y - function values - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - -OUTPUT PARAMETERS: - D1 - S' values at X[] - D2 - S'' values at X[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Derivative values are correctly reordered on return, so D[I] is always -equal to S'(X[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -void spline1dgriddiff2cubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t boundltype, const double boundl, const ae_int_t boundrtype, const double boundr, real_1d_array &d1, real_1d_array &d2, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dgriddiff2cubic(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast(d1.c_ptr()), const_cast(d2.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function solves following problem: given table y[] of function values -at nodes x[], it calculates and returns tables of first and second -function derivatives d1[] and d2[] (calculated at the same nodes x[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - spline nodes - Y - function values - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - -OUTPUT PARAMETERS: - D1 - S' values at X[] - D2 - S'' values at X[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Derivative values are correctly reordered on return, so D[I] is always -equal to S'(X[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spline1dgriddiff2cubic(const real_1d_array &x, const real_1d_array &y, real_1d_array &d1, real_1d_array &d2, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t boundltype; - double boundl; - ae_int_t boundrtype; - double boundr; - if( (x.length()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dgriddiff2cubic': looks like one of arguments has wrong size"); - n = x.length(); - boundltype = 0; - boundl = 0; - boundrtype = 0; - boundr = 0; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dgriddiff2cubic(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast(d1.c_ptr()), const_cast(d2.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function solves following problem: given table y[] of function values -at old nodes x[] and new nodes x2[], it calculates and returns table of -function values y2[] (calculated at x2[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - old spline nodes - Y - function values - X2 - new spline nodes - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points from X/Y are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - N2 - new points count: - * N2>=2 - * if given, only first N2 points from X2 are used - * if not given, automatically detected from X2 size - -OUTPUT PARAMETERS: - F2 - function values at X2[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Function values are correctly reordered on return, so F2[I] is always -equal to S(X2[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -void spline1dconvcubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t boundltype, const double boundl, const ae_int_t boundrtype, const double boundr, const real_1d_array &x2, const ae_int_t n2, real_1d_array &y2, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dconvcubic(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast(x2.c_ptr()), n2, const_cast(y2.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function solves following problem: given table y[] of function values -at old nodes x[] and new nodes x2[], it calculates and returns table of -function values y2[] (calculated at x2[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - old spline nodes - Y - function values - X2 - new spline nodes - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points from X/Y are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - N2 - new points count: - * N2>=2 - * if given, only first N2 points from X2 are used - * if not given, automatically detected from X2 size - -OUTPUT PARAMETERS: - F2 - function values at X2[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Function values are correctly reordered on return, so F2[I] is always -equal to S(X2[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spline1dconvcubic(const real_1d_array &x, const real_1d_array &y, const real_1d_array &x2, real_1d_array &y2, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t boundltype; - double boundl; - ae_int_t boundrtype; - double boundr; - ae_int_t n2; - if( (x.length()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dconvcubic': looks like one of arguments has wrong size"); - n = x.length(); - boundltype = 0; - boundl = 0; - boundrtype = 0; - boundr = 0; - n2 = x2.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dconvcubic(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast(x2.c_ptr()), n2, const_cast(y2.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function solves following problem: given table y[] of function values -at old nodes x[] and new nodes x2[], it calculates and returns table of -function values y2[] and derivatives d2[] (calculated at x2[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - old spline nodes - Y - function values - X2 - new spline nodes - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points from X/Y are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - N2 - new points count: - * N2>=2 - * if given, only first N2 points from X2 are used - * if not given, automatically detected from X2 size - -OUTPUT PARAMETERS: - F2 - function values at X2[] - D2 - first derivatives at X2[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Function values are correctly reordered on return, so F2[I] is always -equal to S(X2[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -void spline1dconvdiffcubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t boundltype, const double boundl, const ae_int_t boundrtype, const double boundr, const real_1d_array &x2, const ae_int_t n2, real_1d_array &y2, real_1d_array &d2, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dconvdiffcubic(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast(x2.c_ptr()), n2, const_cast(y2.c_ptr()), const_cast(d2.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function solves following problem: given table y[] of function values -at old nodes x[] and new nodes x2[], it calculates and returns table of -function values y2[] and derivatives d2[] (calculated at x2[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - old spline nodes - Y - function values - X2 - new spline nodes - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points from X/Y are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - N2 - new points count: - * N2>=2 - * if given, only first N2 points from X2 are used - * if not given, automatically detected from X2 size - -OUTPUT PARAMETERS: - F2 - function values at X2[] - D2 - first derivatives at X2[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Function values are correctly reordered on return, so F2[I] is always -equal to S(X2[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spline1dconvdiffcubic(const real_1d_array &x, const real_1d_array &y, const real_1d_array &x2, real_1d_array &y2, real_1d_array &d2, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t boundltype; - double boundl; - ae_int_t boundrtype; - double boundr; - ae_int_t n2; - if( (x.length()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dconvdiffcubic': looks like one of arguments has wrong size"); - n = x.length(); - boundltype = 0; - boundl = 0; - boundrtype = 0; - boundr = 0; - n2 = x2.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dconvdiffcubic(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast(x2.c_ptr()), n2, const_cast(y2.c_ptr()), const_cast(d2.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function solves following problem: given table y[] of function values -at old nodes x[] and new nodes x2[], it calculates and returns table of -function values y2[], first and second derivatives d2[] and dd2[] -(calculated at x2[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - old spline nodes - Y - function values - X2 - new spline nodes - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points from X/Y are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - N2 - new points count: - * N2>=2 - * if given, only first N2 points from X2 are used - * if not given, automatically detected from X2 size - -OUTPUT PARAMETERS: - F2 - function values at X2[] - D2 - first derivatives at X2[] - DD2 - second derivatives at X2[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Function values are correctly reordered on return, so F2[I] is always -equal to S(X2[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -void spline1dconvdiff2cubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t boundltype, const double boundl, const ae_int_t boundrtype, const double boundr, const real_1d_array &x2, const ae_int_t n2, real_1d_array &y2, real_1d_array &d2, real_1d_array &dd2, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dconvdiff2cubic(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast(x2.c_ptr()), n2, const_cast(y2.c_ptr()), const_cast(d2.c_ptr()), const_cast(dd2.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function solves following problem: given table y[] of function values -at old nodes x[] and new nodes x2[], it calculates and returns table of -function values y2[], first and second derivatives d2[] and dd2[] -(calculated at x2[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - old spline nodes - Y - function values - X2 - new spline nodes - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points from X/Y are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - N2 - new points count: - * N2>=2 - * if given, only first N2 points from X2 are used - * if not given, automatically detected from X2 size - -OUTPUT PARAMETERS: - F2 - function values at X2[] - D2 - first derivatives at X2[] - DD2 - second derivatives at X2[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Function values are correctly reordered on return, so F2[I] is always -equal to S(X2[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spline1dconvdiff2cubic(const real_1d_array &x, const real_1d_array &y, const real_1d_array &x2, real_1d_array &y2, real_1d_array &d2, real_1d_array &dd2, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t boundltype; - double boundl; - ae_int_t boundrtype; - double boundr; - ae_int_t n2; - if( (x.length()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dconvdiff2cubic': looks like one of arguments has wrong size"); - n = x.length(); - boundltype = 0; - boundl = 0; - boundrtype = 0; - boundr = 0; - n2 = x2.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dconvdiff2cubic(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast(x2.c_ptr()), n2, const_cast(y2.c_ptr()), const_cast(d2.c_ptr()), const_cast(dd2.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This subroutine builds Catmull-Rom spline interpolant. - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1]. - Y - function values, array[0..N-1]. - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundType - boundary condition type: - * -1 for periodic boundary condition - * 0 for parabolically terminated spline (default) - Tension - tension parameter: - * tension=0 corresponds to classic Catmull-Rom spline (default) - * 0(x.c_ptr()), const_cast(y.c_ptr()), n, boundtype, tension, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine builds Catmull-Rom spline interpolant. - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1]. - Y - function values, array[0..N-1]. - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundType - boundary condition type: - * -1 for periodic boundary condition - * 0 for parabolically terminated spline (default) - Tension - tension parameter: - * tension=0 corresponds to classic Catmull-Rom spline (default) - * 0(x.c_ptr()), const_cast(y.c_ptr()), n, boundtype, tension, const_cast(c.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This subroutine builds Hermite spline interpolant. - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1] - Y - function values, array[0..N-1] - D - derivatives, array[0..N-1] - N - points count (optional): - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - -OUTPUT PARAMETERS: - C - spline interpolant. - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - - -- ALGLIB PROJECT -- - Copyright 23.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dbuildhermite(const real_1d_array &x, const real_1d_array &y, const real_1d_array &d, const ae_int_t n, spline1dinterpolant &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dbuildhermite(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(d.c_ptr()), n, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine builds Hermite spline interpolant. - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1] - Y - function values, array[0..N-1] - D - derivatives, array[0..N-1] - N - points count (optional): - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - -OUTPUT PARAMETERS: - C - spline interpolant. - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - - -- ALGLIB PROJECT -- - Copyright 23.06.2007 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spline1dbuildhermite(const real_1d_array &x, const real_1d_array &y, const real_1d_array &d, spline1dinterpolant &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (x.length()!=y.length()) || (x.length()!=d.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dbuildhermite': looks like one of arguments has wrong size"); - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dbuildhermite(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(d.c_ptr()), n, const_cast(c.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This subroutine builds Akima spline interpolant - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1] - Y - function values, array[0..N-1] - N - points count (optional): - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - -OUTPUT PARAMETERS: - C - spline interpolant - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - - -- ALGLIB PROJECT -- - Copyright 24.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dbuildakima(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, spline1dinterpolant &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dbuildakima(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine builds Akima spline interpolant - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1] - Y - function values, array[0..N-1] - N - points count (optional): - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - -OUTPUT PARAMETERS: - C - spline interpolant - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - - -- ALGLIB PROJECT -- - Copyright 24.06.2007 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spline1dbuildakima(const real_1d_array &x, const real_1d_array &y, spline1dinterpolant &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (x.length()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dbuildakima': looks like one of arguments has wrong size"); - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dbuildakima(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, const_cast(c.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This subroutine calculates the value of the spline at the given point X. - -INPUT PARAMETERS: - C - spline interpolant - X - point - -Result: - S(x) - - -- ALGLIB PROJECT -- - Copyright 23.06.2007 by Bochkanov Sergey -*************************************************************************/ -double spline1dcalc(const spline1dinterpolant &c, const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::spline1dcalc(const_cast(c.c_ptr()), x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This subroutine differentiates the spline. - -INPUT PARAMETERS: - C - spline interpolant. - X - point - -Result: - S - S(x) - DS - S'(x) - D2S - S''(x) - - -- ALGLIB PROJECT -- - Copyright 24.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1ddiff(const spline1dinterpolant &c, const double x, double &s, double &ds, double &d2s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1ddiff(const_cast(c.c_ptr()), x, &s, &ds, &d2s, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine unpacks the spline into the coefficients table. - -INPUT PARAMETERS: - C - spline interpolant. - X - point - -OUTPUT PARAMETERS: - Tbl - coefficients table, unpacked format, array[0..N-2, 0..5]. - For I = 0...N-2: - Tbl[I,0] = X[i] - Tbl[I,1] = X[i+1] - Tbl[I,2] = C0 - Tbl[I,3] = C1 - Tbl[I,4] = C2 - Tbl[I,5] = C3 - On [x[i], x[i+1]] spline is equals to: - S(x) = C0 + C1*t + C2*t^2 + C3*t^3 - t = x-x[i] - -NOTE: - You can rebuild spline with Spline1DBuildHermite() function, which - accepts as inputs function values and derivatives at nodes, which are - easy to calculate when you have coefficients. - - -- ALGLIB PROJECT -- - Copyright 29.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dunpack(const spline1dinterpolant &c, ae_int_t &n, real_2d_array &tbl, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dunpack(const_cast(c.c_ptr()), &n, const_cast(tbl.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine performs linear transformation of the spline argument. - -INPUT PARAMETERS: - C - spline interpolant. - A, B- transformation coefficients: x = A*t + B -Result: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 30.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dlintransx(const spline1dinterpolant &c, const double a, const double b, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dlintransx(const_cast(c.c_ptr()), a, b, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine performs linear transformation of the spline. - -INPUT PARAMETERS: - C - spline interpolant. - A, B- transformation coefficients: S2(x) = A*S(x) + B -Result: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 30.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dlintransy(const spline1dinterpolant &c, const double a, const double b, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dlintransy(const_cast(c.c_ptr()), a, b, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine integrates the spline. - -INPUT PARAMETERS: - C - spline interpolant. - X - right bound of the integration interval [a, x], - here 'a' denotes min(x[]) -Result: - integral(S(t)dt,a,x) - - -- ALGLIB PROJECT -- - Copyright 23.06.2007 by Bochkanov Sergey -*************************************************************************/ -double spline1dintegrate(const spline1dinterpolant &c, const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::spline1dintegrate(const_cast(c.c_ptr()), x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Fitting by smoothing (penalized) cubic spline. - -This function approximates N scattered points (some of X[] may be equal to -each other) by cubic spline with M nodes at equidistant grid spanning -interval [min(x,xc),max(x,xc)]. - -The problem is regularized by adding nonlinearity penalty to usual least -squares penalty function: - - MERIT_FUNC = F_LS + F_NL - -where F_LS is a least squares error term, and F_NL is a nonlinearity -penalty which is roughly proportional to LambdaNS*integral{ S''(x)^2*dx }. -Algorithm applies automatic renormalization of F_NL which makes penalty -term roughly invariant to scaling of X[] and changes in M. - -This function is a new edition of penalized regression spline fitting, -a fast and compact one which needs much less resources that its previous -version: just O(maxMN) memory and O(maxMN*log(maxMN)) time. - -NOTE: it is OK to run this function with both M<>N; say, it is - possible to process 100 points with 1000-node spline. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - N - number of points (optional): - * N>0 - * if given, only first N elements of X/Y are processed - * if not given, automatically determined from lengths - M - number of basis functions ( = number_of_nodes), M>=4. - LambdaNS - LambdaNS>=0, regularization constant passed by user. - It penalizes nonlinearity in the regression spline. - Possible values to start from are 0.00001, 0.1, 1 - -OUTPUT PARAMETERS: - S - spline interpolant. - Rep - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - - -- ALGLIB PROJECT -- - Copyright 27.08.2019 by Bochkanov Sergey -*************************************************************************/ -void spline1dfit(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t m, const double lambdans, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dfit(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, m, lambdans, const_cast(s.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Fitting by smoothing (penalized) cubic spline. - -This function approximates N scattered points (some of X[] may be equal to -each other) by cubic spline with M nodes at equidistant grid spanning -interval [min(x,xc),max(x,xc)]. - -The problem is regularized by adding nonlinearity penalty to usual least -squares penalty function: - - MERIT_FUNC = F_LS + F_NL - -where F_LS is a least squares error term, and F_NL is a nonlinearity -penalty which is roughly proportional to LambdaNS*integral{ S''(x)^2*dx }. -Algorithm applies automatic renormalization of F_NL which makes penalty -term roughly invariant to scaling of X[] and changes in M. - -This function is a new edition of penalized regression spline fitting, -a fast and compact one which needs much less resources that its previous -version: just O(maxMN) memory and O(maxMN*log(maxMN)) time. - -NOTE: it is OK to run this function with both M<>N; say, it is - possible to process 100 points with 1000-node spline. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - N - number of points (optional): - * N>0 - * if given, only first N elements of X/Y are processed - * if not given, automatically determined from lengths - M - number of basis functions ( = number_of_nodes), M>=4. - LambdaNS - LambdaNS>=0, regularization constant passed by user. - It penalizes nonlinearity in the regression spline. - Possible values to start from are 0.00001, 0.1, 1 - -OUTPUT PARAMETERS: - S - spline interpolant. - Rep - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - - -- ALGLIB PROJECT -- - Copyright 27.08.2019 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spline1dfit(const real_1d_array &x, const real_1d_array &y, const ae_int_t m, const double lambdans, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (x.length()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dfit': looks like one of arguments has wrong size"); - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dfit(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, m, lambdans, const_cast(s.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function builds monotone cubic Hermite interpolant. This interpolant -is monotonic in [x(0),x(n-1)] and is constant outside of this interval. - -In case y[] form non-monotonic sequence, interpolant is piecewise -monotonic. Say, for x=(0,1,2,3,4) and y=(0,1,2,1,0) interpolant will -monotonically grow at [0..2] and monotonically decrease at [2..4]. - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1]. Subroutine automatically - sorts points, so caller may pass unsorted array. - Y - function values, array[0..N-1] - N - the number of points(N>=2). - -OUTPUT PARAMETERS: - C - spline interpolant. - - -- ALGLIB PROJECT -- - Copyright 21.06.2012 by Bochkanov Sergey -*************************************************************************/ -void spline1dbuildmonotone(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, spline1dinterpolant &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dbuildmonotone(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function builds monotone cubic Hermite interpolant. This interpolant -is monotonic in [x(0),x(n-1)] and is constant outside of this interval. - -In case y[] form non-monotonic sequence, interpolant is piecewise -monotonic. Say, for x=(0,1,2,3,4) and y=(0,1,2,1,0) interpolant will -monotonically grow at [0..2] and monotonically decrease at [2..4]. - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1]. Subroutine automatically - sorts points, so caller may pass unsorted array. - Y - function values, array[0..N-1] - N - the number of points(N>=2). - -OUTPUT PARAMETERS: - C - spline interpolant. - - -- ALGLIB PROJECT -- - Copyright 21.06.2012 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spline1dbuildmonotone(const real_1d_array &x, const real_1d_array &y, spline1dinterpolant &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (x.length()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dbuildmonotone': looks like one of arguments has wrong size"); - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dbuildmonotone(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, const_cast(c.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif -#endif - -#if defined(AE_COMPILE_PARAMETRIC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Parametric spline inteprolant: 2-dimensional curve. - -You should not try to access its members directly - use PSpline2XXXXXXXX() -functions instead. -*************************************************************************/ -_pspline2interpolant_owner::_pspline2interpolant_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_pspline2interpolant_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::pspline2interpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::pspline2interpolant), &_state); - memset(p_struct, 0, sizeof(alglib_impl::pspline2interpolant)); - alglib_impl::_pspline2interpolant_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_pspline2interpolant_owner::_pspline2interpolant_owner(const _pspline2interpolant_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_pspline2interpolant_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: pspline2interpolant copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::pspline2interpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::pspline2interpolant), &_state); - memset(p_struct, 0, sizeof(alglib_impl::pspline2interpolant)); - alglib_impl::_pspline2interpolant_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_pspline2interpolant_owner& _pspline2interpolant_owner::operator=(const _pspline2interpolant_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: pspline2interpolant assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: pspline2interpolant assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_pspline2interpolant_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::pspline2interpolant)); - alglib_impl::_pspline2interpolant_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_pspline2interpolant_owner::~_pspline2interpolant_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_pspline2interpolant_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::pspline2interpolant* _pspline2interpolant_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::pspline2interpolant* _pspline2interpolant_owner::c_ptr() const -{ - return const_cast(p_struct); -} -pspline2interpolant::pspline2interpolant() : _pspline2interpolant_owner() -{ -} - -pspline2interpolant::pspline2interpolant(const pspline2interpolant &rhs):_pspline2interpolant_owner(rhs) -{ -} - -pspline2interpolant& pspline2interpolant::operator=(const pspline2interpolant &rhs) -{ - if( this==&rhs ) - return *this; - _pspline2interpolant_owner::operator=(rhs); - return *this; -} - -pspline2interpolant::~pspline2interpolant() -{ -} - - -/************************************************************************* -Parametric spline inteprolant: 3-dimensional curve. - -You should not try to access its members directly - use PSpline3XXXXXXXX() -functions instead. -*************************************************************************/ -_pspline3interpolant_owner::_pspline3interpolant_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_pspline3interpolant_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::pspline3interpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::pspline3interpolant), &_state); - memset(p_struct, 0, sizeof(alglib_impl::pspline3interpolant)); - alglib_impl::_pspline3interpolant_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_pspline3interpolant_owner::_pspline3interpolant_owner(const _pspline3interpolant_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_pspline3interpolant_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: pspline3interpolant copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::pspline3interpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::pspline3interpolant), &_state); - memset(p_struct, 0, sizeof(alglib_impl::pspline3interpolant)); - alglib_impl::_pspline3interpolant_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_pspline3interpolant_owner& _pspline3interpolant_owner::operator=(const _pspline3interpolant_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: pspline3interpolant assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: pspline3interpolant assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_pspline3interpolant_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::pspline3interpolant)); - alglib_impl::_pspline3interpolant_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_pspline3interpolant_owner::~_pspline3interpolant_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_pspline3interpolant_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::pspline3interpolant* _pspline3interpolant_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::pspline3interpolant* _pspline3interpolant_owner::c_ptr() const -{ - return const_cast(p_struct); -} -pspline3interpolant::pspline3interpolant() : _pspline3interpolant_owner() -{ -} - -pspline3interpolant::pspline3interpolant(const pspline3interpolant &rhs):_pspline3interpolant_owner(rhs) -{ -} - -pspline3interpolant& pspline3interpolant::operator=(const pspline3interpolant &rhs) -{ - if( this==&rhs ) - return *this; - _pspline3interpolant_owner::operator=(rhs); - return *this; -} - -pspline3interpolant::~pspline3interpolant() -{ -} - -/************************************************************************* -This function builds non-periodic 2-dimensional parametric spline which -starts at (X[0],Y[0]) and ends at (X[N-1],Y[N-1]). - -INPUT PARAMETERS: - XY - points, array[0..N-1,0..1]. - XY[I,0:1] corresponds to the Ith point. - Order of points is important! - N - points count, N>=5 for Akima splines, N>=2 for other types of - splines. - ST - spline type: - * 0 Akima spline - * 1 parabolically terminated Catmull-Rom spline (Tension=0) - * 2 parabolically terminated cubic spline - PT - parameterization type: - * 0 uniform - * 1 chord length - * 2 centripetal - -OUTPUT PARAMETERS: - P - parametric spline interpolant - - -NOTES: -* this function assumes that there all consequent points are distinct. - I.e. (x0,y0)<>(x1,y1), (x1,y1)<>(x2,y2), (x2,y2)<>(x3,y3) and so on. - However, non-consequent points may coincide, i.e. we can have (x0,y0)= - =(x2,y2). - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline2build(const real_2d_array &xy, const ae_int_t n, const ae_int_t st, const ae_int_t pt, pspline2interpolant &p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::pspline2build(const_cast(xy.c_ptr()), n, st, pt, const_cast(p.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function builds non-periodic 3-dimensional parametric spline which -starts at (X[0],Y[0],Z[0]) and ends at (X[N-1],Y[N-1],Z[N-1]). - -Same as PSpline2Build() function, but for 3D, so we won't duplicate its -description here. - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline3build(const real_2d_array &xy, const ae_int_t n, const ae_int_t st, const ae_int_t pt, pspline3interpolant &p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::pspline3build(const_cast(xy.c_ptr()), n, st, pt, const_cast(p.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function builds periodic 2-dimensional parametric spline which -starts at (X[0],Y[0]), goes through all points to (X[N-1],Y[N-1]) and then -back to (X[0],Y[0]). - -INPUT PARAMETERS: - XY - points, array[0..N-1,0..1]. - XY[I,0:1] corresponds to the Ith point. - XY[N-1,0:1] must be different from XY[0,0:1]. - Order of points is important! - N - points count, N>=3 for other types of splines. - ST - spline type: - * 1 Catmull-Rom spline (Tension=0) with cyclic boundary conditions - * 2 cubic spline with cyclic boundary conditions - PT - parameterization type: - * 0 uniform - * 1 chord length - * 2 centripetal - -OUTPUT PARAMETERS: - P - parametric spline interpolant - - -NOTES: -* this function assumes that there all consequent points are distinct. - I.e. (x0,y0)<>(x1,y1), (x1,y1)<>(x2,y2), (x2,y2)<>(x3,y3) and so on. - However, non-consequent points may coincide, i.e. we can have (x0,y0)= - =(x2,y2). -* last point of sequence is NOT equal to the first point. You shouldn't - make curve "explicitly periodic" by making them equal. - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline2buildperiodic(const real_2d_array &xy, const ae_int_t n, const ae_int_t st, const ae_int_t pt, pspline2interpolant &p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::pspline2buildperiodic(const_cast(xy.c_ptr()), n, st, pt, const_cast(p.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function builds periodic 3-dimensional parametric spline which -starts at (X[0],Y[0],Z[0]), goes through all points to (X[N-1],Y[N-1],Z[N-1]) -and then back to (X[0],Y[0],Z[0]). - -Same as PSpline2Build() function, but for 3D, so we won't duplicate its -description here. - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline3buildperiodic(const real_2d_array &xy, const ae_int_t n, const ae_int_t st, const ae_int_t pt, pspline3interpolant &p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::pspline3buildperiodic(const_cast(xy.c_ptr()), n, st, pt, const_cast(p.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function returns vector of parameter values correspoding to points. - -I.e. for P created from (X[0],Y[0])...(X[N-1],Y[N-1]) and U=TValues(P) we -have - (X[0],Y[0]) = PSpline2Calc(P,U[0]), - (X[1],Y[1]) = PSpline2Calc(P,U[1]), - (X[2],Y[2]) = PSpline2Calc(P,U[2]), - ... - -INPUT PARAMETERS: - P - parametric spline interpolant - -OUTPUT PARAMETERS: - N - array size - T - array[0..N-1] - - -NOTES: -* for non-periodic splines U[0]=0, U[0](p.c_ptr()), &n, const_cast(t.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function returns vector of parameter values correspoding to points. - -Same as PSpline2ParameterValues(), but for 3D. - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline3parametervalues(const pspline3interpolant &p, ae_int_t &n, real_1d_array &t, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::pspline3parametervalues(const_cast(p.c_ptr()), &n, const_cast(t.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates the value of the parametric spline for a given -value of parameter T - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-position - Y - Y-position - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline2calc(const pspline2interpolant &p, const double t, double &x, double &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::pspline2calc(const_cast(p.c_ptr()), t, &x, &y, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates the value of the parametric spline for a given -value of parameter T. - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-position - Y - Y-position - Z - Z-position - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline3calc(const pspline3interpolant &p, const double t, double &x, double &y, double &z, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::pspline3calc(const_cast(p.c_ptr()), t, &x, &y, &z, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates tangent vector for a given value of parameter T - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-component of tangent vector (normalized) - Y - Y-component of tangent vector (normalized) - -NOTE: - X^2+Y^2 is either 1 (for non-zero tangent vector) or 0. - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline2tangent(const pspline2interpolant &p, const double t, double &x, double &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::pspline2tangent(const_cast(p.c_ptr()), t, &x, &y, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates tangent vector for a given value of parameter T - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-component of tangent vector (normalized) - Y - Y-component of tangent vector (normalized) - Z - Z-component of tangent vector (normalized) - -NOTE: - X^2+Y^2+Z^2 is either 1 (for non-zero tangent vector) or 0. - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline3tangent(const pspline3interpolant &p, const double t, double &x, double &y, double &z, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::pspline3tangent(const_cast(p.c_ptr()), t, &x, &y, &z, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates derivative, i.e. it returns (dX/dT,dY/dT). - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-value - DX - X-derivative - Y - Y-value - DY - Y-derivative - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline2diff(const pspline2interpolant &p, const double t, double &x, double &dx, double &y, double &dy, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::pspline2diff(const_cast(p.c_ptr()), t, &x, &dx, &y, &dy, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates derivative, i.e. it returns (dX/dT,dY/dT,dZ/dT). - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-value - DX - X-derivative - Y - Y-value - DY - Y-derivative - Z - Z-value - DZ - Z-derivative - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline3diff(const pspline3interpolant &p, const double t, double &x, double &dx, double &y, double &dy, double &z, double &dz, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::pspline3diff(const_cast(p.c_ptr()), t, &x, &dx, &y, &dy, &z, &dz, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates first and second derivative with respect to T. - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-value - DX - derivative - D2X - second derivative - Y - Y-value - DY - derivative - D2Y - second derivative - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline2diff2(const pspline2interpolant &p, const double t, double &x, double &dx, double &d2x, double &y, double &dy, double &d2y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::pspline2diff2(const_cast(p.c_ptr()), t, &x, &dx, &d2x, &y, &dy, &d2y, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates first and second derivative with respect to T. - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-value - DX - derivative - D2X - second derivative - Y - Y-value - DY - derivative - D2Y - second derivative - Z - Z-value - DZ - derivative - D2Z - second derivative - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline3diff2(const pspline3interpolant &p, const double t, double &x, double &dx, double &d2x, double &y, double &dy, double &d2y, double &z, double &dz, double &d2z, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::pspline3diff2(const_cast(p.c_ptr()), t, &x, &dx, &d2x, &y, &dy, &d2y, &z, &dz, &d2z, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates arc length, i.e. length of curve between t=a -and t=b. - -INPUT PARAMETERS: - P - parametric spline interpolant - A,B - parameter values corresponding to arc ends: - * B>A will result in positive length returned - * B(p.c_ptr()), a, b, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function calculates arc length, i.e. length of curve between t=a -and t=b. - -INPUT PARAMETERS: - P - parametric spline interpolant - A,B - parameter values corresponding to arc ends: - * B>A will result in positive length returned - * B(p.c_ptr()), a, b, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This subroutine fits piecewise linear curve to points with Ramer-Douglas- -Peucker algorithm. This function performs PARAMETRIC fit, i.e. it can be -used to fit curves like circles. - -On input it accepts dataset which describes parametric multidimensional -curve X(t), with X being vector, and t taking values in [0,N), where N is -a number of points in dataset. As result, it returns reduced dataset X2, -which can be used to build parametric curve X2(t), which approximates -X(t) with desired precision (or has specified number of sections). - - -INPUT PARAMETERS: - X - array of multidimensional points: - * at least N elements, leading N elements are used if more - than N elements were specified - * order of points is IMPORTANT because it is parametric - fit - * each row of array is one point which has D coordinates - N - number of elements in X - D - number of dimensions (elements per row of X) - StopM - stopping condition - desired number of sections: - * at most M sections are generated by this function - * less than M sections can be generated if we have N(x.c_ptr()), n, d, stopm, stopeps, const_cast(x2.c_ptr()), const_cast(idx2.c_ptr()), &nsections, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_SPLINE3D) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -3-dimensional spline inteprolant -*************************************************************************/ -_spline3dinterpolant_owner::_spline3dinterpolant_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_spline3dinterpolant_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::spline3dinterpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline3dinterpolant), &_state); - memset(p_struct, 0, sizeof(alglib_impl::spline3dinterpolant)); - alglib_impl::_spline3dinterpolant_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_spline3dinterpolant_owner::_spline3dinterpolant_owner(const _spline3dinterpolant_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_spline3dinterpolant_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline3dinterpolant copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::spline3dinterpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline3dinterpolant), &_state); - memset(p_struct, 0, sizeof(alglib_impl::spline3dinterpolant)); - alglib_impl::_spline3dinterpolant_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_spline3dinterpolant_owner& _spline3dinterpolant_owner::operator=(const _spline3dinterpolant_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: spline3dinterpolant assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline3dinterpolant assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_spline3dinterpolant_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::spline3dinterpolant)); - alglib_impl::_spline3dinterpolant_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_spline3dinterpolant_owner::~_spline3dinterpolant_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_spline3dinterpolant_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::spline3dinterpolant* _spline3dinterpolant_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::spline3dinterpolant* _spline3dinterpolant_owner::c_ptr() const -{ - return const_cast(p_struct); -} -spline3dinterpolant::spline3dinterpolant() : _spline3dinterpolant_owner() -{ -} - -spline3dinterpolant::spline3dinterpolant(const spline3dinterpolant &rhs):_spline3dinterpolant_owner(rhs) -{ -} - -spline3dinterpolant& spline3dinterpolant::operator=(const spline3dinterpolant &rhs) -{ - if( this==&rhs ) - return *this; - _spline3dinterpolant_owner::operator=(rhs); - return *this; -} - -spline3dinterpolant::~spline3dinterpolant() -{ -} - -/************************************************************************* -This subroutine calculates the value of the trilinear or tricubic spline at -the given point (X,Y,Z). - -INPUT PARAMETERS: - C - coefficients table. - Built by BuildBilinearSpline or BuildBicubicSpline. - X, Y, - Z - point - -Result: - S(x,y,z) - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -double spline3dcalc(const spline3dinterpolant &c, const double x, const double y, const double z, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::spline3dcalc(const_cast(c.c_ptr()), x, y, z, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This subroutine performs linear transformation of the spline argument. - -INPUT PARAMETERS: - C - spline interpolant - AX, BX - transformation coefficients: x = A*u + B - AY, BY - transformation coefficients: y = A*v + B - AZ, BZ - transformation coefficients: z = A*w + B - -OUTPUT PARAMETERS: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline3dlintransxyz(const spline3dinterpolant &c, const double ax, const double bx, const double ay, const double by, const double az, const double bz, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline3dlintransxyz(const_cast(c.c_ptr()), ax, bx, ay, by, az, bz, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine performs linear transformation of the spline. - -INPUT PARAMETERS: - C - spline interpolant. - A, B- transformation coefficients: S2(x,y) = A*S(x,y,z) + B - -OUTPUT PARAMETERS: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline3dlintransf(const spline3dinterpolant &c, const double a, const double b, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline3dlintransf(const_cast(c.c_ptr()), a, b, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Trilinear spline resampling - -INPUT PARAMETERS: - A - array[0..OldXCount*OldYCount*OldZCount-1], function - values at the old grid, : - A[0] x=0,y=0,z=0 - A[1] x=1,y=0,z=0 - A[..] ... - A[..] x=oldxcount-1,y=0,z=0 - A[..] x=0,y=1,z=0 - A[..] ... - ... - OldZCount - old Z-count, OldZCount>1 - OldYCount - old Y-count, OldYCount>1 - OldXCount - old X-count, OldXCount>1 - NewZCount - new Z-count, NewZCount>1 - NewYCount - new Y-count, NewYCount>1 - NewXCount - new X-count, NewXCount>1 - -OUTPUT PARAMETERS: - B - array[0..NewXCount*NewYCount*NewZCount-1], function - values at the new grid: - B[0] x=0,y=0,z=0 - B[1] x=1,y=0,z=0 - B[..] ... - B[..] x=newxcount-1,y=0,z=0 - B[..] x=0,y=1,z=0 - B[..] ... - ... - - -- ALGLIB routine -- - 26.04.2012 - Copyright by Bochkanov Sergey -*************************************************************************/ -void spline3dresampletrilinear(const real_1d_array &a, const ae_int_t oldzcount, const ae_int_t oldycount, const ae_int_t oldxcount, const ae_int_t newzcount, const ae_int_t newycount, const ae_int_t newxcount, real_1d_array &b, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline3dresampletrilinear(const_cast(a.c_ptr()), oldzcount, oldycount, oldxcount, newzcount, newycount, newxcount, const_cast(b.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine builds trilinear vector-valued spline. - -INPUT PARAMETERS: - X - spline abscissas, array[0..N-1] - Y - spline ordinates, array[0..M-1] - Z - spline applicates, array[0..L-1] - F - function values, array[0..M*N*L*D-1]: - * first D elements store D values at (X[0],Y[0],Z[0]) - * next D elements store D values at (X[1],Y[0],Z[0]) - * next D elements store D values at (X[2],Y[0],Z[0]) - * ... - * next D elements store D values at (X[0],Y[1],Z[0]) - * next D elements store D values at (X[1],Y[1],Z[0]) - * next D elements store D values at (X[2],Y[1],Z[0]) - * ... - * next D elements store D values at (X[0],Y[0],Z[1]) - * next D elements store D values at (X[1],Y[0],Z[1]) - * next D elements store D values at (X[2],Y[0],Z[1]) - * ... - * general form - D function values at (X[i],Y[j]) are stored - at F[D*(N*(M*K+J)+I)...D*(N*(M*K+J)+I)+D-1]. - M,N, - L - grid size, M>=2, N>=2, L>=2 - D - vector dimension, D>=1 - -OUTPUT PARAMETERS: - C - spline interpolant - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline3dbuildtrilinearv(const real_1d_array &x, const ae_int_t n, const real_1d_array &y, const ae_int_t m, const real_1d_array &z, const ae_int_t l, const real_1d_array &f, const ae_int_t d, spline3dinterpolant &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline3dbuildtrilinearv(const_cast(x.c_ptr()), n, const_cast(y.c_ptr()), m, const_cast(z.c_ptr()), l, const_cast(f.c_ptr()), d, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine calculates bilinear or bicubic vector-valued spline at the -given point (X,Y,Z). - -INPUT PARAMETERS: - C - spline interpolant. - X, Y, - Z - point - F - output buffer, possibly preallocated array. In case array size - is large enough to store result, it is not reallocated. Array - which is too short will be reallocated - -OUTPUT PARAMETERS: - F - array[D] (or larger) which stores function values - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline3dcalcvbuf(const spline3dinterpolant &c, const double x, const double y, const double z, real_1d_array &f, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline3dcalcvbuf(const_cast(c.c_ptr()), x, y, z, const_cast(f.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine calculates trilinear or tricubic vector-valued spline at the -given point (X,Y,Z). - -INPUT PARAMETERS: - C - spline interpolant. - X, Y, - Z - point - -OUTPUT PARAMETERS: - F - array[D] which stores function values. F is out-parameter and - it is reallocated after call to this function. In case you - want to reuse previously allocated F, you may use - Spline2DCalcVBuf(), which reallocates F only when it is too - small. - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline3dcalcv(const spline3dinterpolant &c, const double x, const double y, const double z, real_1d_array &f, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline3dcalcv(const_cast(c.c_ptr()), x, y, z, const_cast(f.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine unpacks tri-dimensional spline into the coefficients table - -INPUT PARAMETERS: - C - spline interpolant. - -Result: - N - grid size (X) - M - grid size (Y) - L - grid size (Z) - D - number of components - SType- spline type. Currently, only one spline type is supported: - trilinear spline, as indicated by SType=1. - Tbl - spline coefficients: [0..(N-1)*(M-1)*(L-1)*D-1, 0..13]. - For T=0..D-1 (component index), I = 0...N-2 (x index), - J=0..M-2 (y index), K=0..L-2 (z index): - Q := T + I*D + J*D*(N-1) + K*D*(N-1)*(M-1), - - Q-th row stores decomposition for T-th component of the - vector-valued function - - Tbl[Q,0] = X[i] - Tbl[Q,1] = X[i+1] - Tbl[Q,2] = Y[j] - Tbl[Q,3] = Y[j+1] - Tbl[Q,4] = Z[k] - Tbl[Q,5] = Z[k+1] - - Tbl[Q,6] = C000 - Tbl[Q,7] = C100 - Tbl[Q,8] = C010 - Tbl[Q,9] = C110 - Tbl[Q,10]= C001 - Tbl[Q,11]= C101 - Tbl[Q,12]= C011 - Tbl[Q,13]= C111 - On each grid square spline is equals to: - S(x) = SUM(c[i,j,k]*(x^i)*(y^j)*(z^k), i=0..1, j=0..1, k=0..1) - t = x-x[j] - u = y-y[i] - v = z-z[k] - - NOTE: format of Tbl is given for SType=1. Future versions of - ALGLIB can use different formats for different values of - SType. - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline3dunpackv(const spline3dinterpolant &c, ae_int_t &n, ae_int_t &m, ae_int_t &l, ae_int_t &d, ae_int_t &stype, real_2d_array &tbl, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline3dunpackv(const_cast(c.c_ptr()), &n, &m, &l, &d, &stype, const_cast(tbl.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_POLINT) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Conversion from barycentric representation to Chebyshev basis. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - P - polynomial in barycentric form - A,B - base interval for Chebyshev polynomials (see below) - A<>B - -OUTPUT PARAMETERS - T - coefficients of Chebyshev representation; - P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N-1 }, - where Ti - I-th Chebyshev polynomial. - -NOTES: - barycentric interpolant passed as P may be either polynomial obtained - from polynomial interpolation/ fitting or rational function which is - NOT polynomial. We can't distinguish between these two cases, and this - algorithm just tries to work assuming that P IS a polynomial. If not, - algorithm will return results, but they won't have any meaning. - - -- ALGLIB -- - Copyright 30.09.2010 by Bochkanov Sergey -*************************************************************************/ -void polynomialbar2cheb(const barycentricinterpolant &p, const double a, const double b, real_1d_array &t, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::polynomialbar2cheb(const_cast(p.c_ptr()), a, b, const_cast(t.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Conversion from Chebyshev basis to barycentric representation. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - T - coefficients of Chebyshev representation; - P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N }, - where Ti - I-th Chebyshev polynomial. - N - number of coefficients: - * if given, only leading N elements of T are used - * if not given, automatically determined from size of T - A,B - base interval for Chebyshev polynomials (see above) - A(t.c_ptr()), n, a, b, const_cast(p.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Conversion from Chebyshev basis to barycentric representation. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - T - coefficients of Chebyshev representation; - P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N }, - where Ti - I-th Chebyshev polynomial. - N - number of coefficients: - * if given, only leading N elements of T are used - * if not given, automatically determined from size of T - A,B - base interval for Chebyshev polynomials (see above) - A(t.c_ptr()), n, a, b, const_cast(p.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Conversion from barycentric representation to power basis. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - P - polynomial in barycentric form - C - offset (see below); 0.0 is used as default value. - S - scale (see below); 1.0 is used as default value. S<>0. - -OUTPUT PARAMETERS - A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 } - N - number of coefficients (polynomial degree plus 1) - -NOTES: -1. this function accepts offset and scale, which can be set to improve - numerical properties of polynomial. For example, if P was obtained as - result of interpolation on [-1,+1], you can set C=0 and S=1 and - represent P as sum of 1, x, x^2, x^3 and so on. In most cases you it - is exactly what you need. - - However, if your interpolation model was built on [999,1001], you will - see significant growth of numerical errors when using {1, x, x^2, x^3} - as basis. Representing P as sum of 1, (x-1000), (x-1000)^2, (x-1000)^3 - will be better option. Such representation can be obtained by using - 1000.0 as offset C and 1.0 as scale S. - -2. power basis is ill-conditioned and tricks described above can't solve - this problem completely. This function will return coefficients in - any case, but for N>8 they will become unreliable. However, N's - less than 5 are pretty safe. - -3. barycentric interpolant passed as P may be either polynomial obtained - from polynomial interpolation/ fitting or rational function which is - NOT polynomial. We can't distinguish between these two cases, and this - algorithm just tries to work assuming that P IS a polynomial. If not, - algorithm will return results, but they won't have any meaning. - - -- ALGLIB -- - Copyright 30.09.2010 by Bochkanov Sergey -*************************************************************************/ -void polynomialbar2pow(const barycentricinterpolant &p, const double c, const double s, real_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::polynomialbar2pow(const_cast(p.c_ptr()), c, s, const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Conversion from barycentric representation to power basis. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - P - polynomial in barycentric form - C - offset (see below); 0.0 is used as default value. - S - scale (see below); 1.0 is used as default value. S<>0. - -OUTPUT PARAMETERS - A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 } - N - number of coefficients (polynomial degree plus 1) - -NOTES: -1. this function accepts offset and scale, which can be set to improve - numerical properties of polynomial. For example, if P was obtained as - result of interpolation on [-1,+1], you can set C=0 and S=1 and - represent P as sum of 1, x, x^2, x^3 and so on. In most cases you it - is exactly what you need. - - However, if your interpolation model was built on [999,1001], you will - see significant growth of numerical errors when using {1, x, x^2, x^3} - as basis. Representing P as sum of 1, (x-1000), (x-1000)^2, (x-1000)^3 - will be better option. Such representation can be obtained by using - 1000.0 as offset C and 1.0 as scale S. - -2. power basis is ill-conditioned and tricks described above can't solve - this problem completely. This function will return coefficients in - any case, but for N>8 they will become unreliable. However, N's - less than 5 are pretty safe. - -3. barycentric interpolant passed as P may be either polynomial obtained - from polynomial interpolation/ fitting or rational function which is - NOT polynomial. We can't distinguish between these two cases, and this - algorithm just tries to work assuming that P IS a polynomial. If not, - algorithm will return results, but they won't have any meaning. - - -- ALGLIB -- - Copyright 30.09.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void polynomialbar2pow(const barycentricinterpolant &p, real_1d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - double c; - double s; - - c = 0; - s = 1; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::polynomialbar2pow(const_cast(p.c_ptr()), c, s, const_cast(a.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Conversion from power basis to barycentric representation. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 } - N - number of coefficients (polynomial degree plus 1) - * if given, only leading N elements of A are used - * if not given, automatically determined from size of A - C - offset (see below); 0.0 is used as default value. - S - scale (see below); 1.0 is used as default value. S<>0. - -OUTPUT PARAMETERS - P - polynomial in barycentric form - - -NOTES: -1. this function accepts offset and scale, which can be set to improve - numerical properties of polynomial. For example, if you interpolate on - [-1,+1], you can set C=0 and S=1 and convert from sum of 1, x, x^2, - x^3 and so on. In most cases you it is exactly what you need. - - However, if your interpolation model was built on [999,1001], you will - see significant growth of numerical errors when using {1, x, x^2, x^3} - as input basis. Converting from sum of 1, (x-1000), (x-1000)^2, - (x-1000)^3 will be better option (you have to specify 1000.0 as offset - C and 1.0 as scale S). - -2. power basis is ill-conditioned and tricks described above can't solve - this problem completely. This function will return barycentric model - in any case, but for N>8 accuracy well degrade. However, N's less than - 5 are pretty safe. - - -- ALGLIB -- - Copyright 30.09.2010 by Bochkanov Sergey -*************************************************************************/ -void polynomialpow2bar(const real_1d_array &a, const ae_int_t n, const double c, const double s, barycentricinterpolant &p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::polynomialpow2bar(const_cast(a.c_ptr()), n, c, s, const_cast(p.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Conversion from power basis to barycentric representation. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 } - N - number of coefficients (polynomial degree plus 1) - * if given, only leading N elements of A are used - * if not given, automatically determined from size of A - C - offset (see below); 0.0 is used as default value. - S - scale (see below); 1.0 is used as default value. S<>0. - -OUTPUT PARAMETERS - P - polynomial in barycentric form - - -NOTES: -1. this function accepts offset and scale, which can be set to improve - numerical properties of polynomial. For example, if you interpolate on - [-1,+1], you can set C=0 and S=1 and convert from sum of 1, x, x^2, - x^3 and so on. In most cases you it is exactly what you need. - - However, if your interpolation model was built on [999,1001], you will - see significant growth of numerical errors when using {1, x, x^2, x^3} - as input basis. Converting from sum of 1, (x-1000), (x-1000)^2, - (x-1000)^3 will be better option (you have to specify 1000.0 as offset - C and 1.0 as scale S). - -2. power basis is ill-conditioned and tricks described above can't solve - this problem completely. This function will return barycentric model - in any case, but for N>8 accuracy well degrade. However, N's less than - 5 are pretty safe. - - -- ALGLIB -- - Copyright 30.09.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void polynomialpow2bar(const real_1d_array &a, barycentricinterpolant &p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - double c; - double s; - - n = a.length(); - c = 0; - s = 1; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::polynomialpow2bar(const_cast(a.c_ptr()), n, c, s, const_cast(p.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Lagrange intepolant: generation of the model on the general grid. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - X - abscissas, array[0..N-1] - Y - function values, array[0..N-1] - N - number of points, N>=1 - -OUTPUT PARAMETERS - P - barycentric model which represents Lagrange interpolant - (see ratint unit info and BarycentricCalc() description for - more information). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void polynomialbuild(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, barycentricinterpolant &p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::polynomialbuild(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, const_cast(p.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Lagrange intepolant: generation of the model on the general grid. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - X - abscissas, array[0..N-1] - Y - function values, array[0..N-1] - N - number of points, N>=1 - -OUTPUT PARAMETERS - P - barycentric model which represents Lagrange interpolant - (see ratint unit info and BarycentricCalc() description for - more information). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void polynomialbuild(const real_1d_array &x, const real_1d_array &y, barycentricinterpolant &p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (x.length()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'polynomialbuild': looks like one of arguments has wrong size"); - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::polynomialbuild(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, const_cast(p.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Lagrange intepolant: generation of the model on equidistant grid. -This function has O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - Y - function values at the nodes, array[0..N-1] - N - number of points, N>=1 - for N=1 a constant model is constructed. - -OUTPUT PARAMETERS - P - barycentric model which represents Lagrange interpolant - (see ratint unit info and BarycentricCalc() description for - more information). - - -- ALGLIB -- - Copyright 03.12.2009 by Bochkanov Sergey -*************************************************************************/ -void polynomialbuildeqdist(const double a, const double b, const real_1d_array &y, const ae_int_t n, barycentricinterpolant &p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::polynomialbuildeqdist(a, b, const_cast(y.c_ptr()), n, const_cast(p.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Lagrange intepolant: generation of the model on equidistant grid. -This function has O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - Y - function values at the nodes, array[0..N-1] - N - number of points, N>=1 - for N=1 a constant model is constructed. - -OUTPUT PARAMETERS - P - barycentric model which represents Lagrange interpolant - (see ratint unit info and BarycentricCalc() description for - more information). - - -- ALGLIB -- - Copyright 03.12.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void polynomialbuildeqdist(const double a, const double b, const real_1d_array &y, barycentricinterpolant &p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = y.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::polynomialbuildeqdist(a, b, const_cast(y.c_ptr()), n, const_cast(p.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Lagrange intepolant on Chebyshev grid (first kind). -This function has O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - Y - function values at the nodes, array[0..N-1], - Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n))) - N - number of points, N>=1 - for N=1 a constant model is constructed. - -OUTPUT PARAMETERS - P - barycentric model which represents Lagrange interpolant - (see ratint unit info and BarycentricCalc() description for - more information). - - -- ALGLIB -- - Copyright 03.12.2009 by Bochkanov Sergey -*************************************************************************/ -void polynomialbuildcheb1(const double a, const double b, const real_1d_array &y, const ae_int_t n, barycentricinterpolant &p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::polynomialbuildcheb1(a, b, const_cast(y.c_ptr()), n, const_cast(p.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Lagrange intepolant on Chebyshev grid (first kind). -This function has O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - Y - function values at the nodes, array[0..N-1], - Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n))) - N - number of points, N>=1 - for N=1 a constant model is constructed. - -OUTPUT PARAMETERS - P - barycentric model which represents Lagrange interpolant - (see ratint unit info and BarycentricCalc() description for - more information). - - -- ALGLIB -- - Copyright 03.12.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void polynomialbuildcheb1(const double a, const double b, const real_1d_array &y, barycentricinterpolant &p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = y.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::polynomialbuildcheb1(a, b, const_cast(y.c_ptr()), n, const_cast(p.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Lagrange intepolant on Chebyshev grid (second kind). -This function has O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - Y - function values at the nodes, array[0..N-1], - Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1))) - N - number of points, N>=1 - for N=1 a constant model is constructed. - -OUTPUT PARAMETERS - P - barycentric model which represents Lagrange interpolant - (see ratint unit info and BarycentricCalc() description for - more information). - - -- ALGLIB -- - Copyright 03.12.2009 by Bochkanov Sergey -*************************************************************************/ -void polynomialbuildcheb2(const double a, const double b, const real_1d_array &y, const ae_int_t n, barycentricinterpolant &p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::polynomialbuildcheb2(a, b, const_cast(y.c_ptr()), n, const_cast(p.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Lagrange intepolant on Chebyshev grid (second kind). -This function has O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - Y - function values at the nodes, array[0..N-1], - Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1))) - N - number of points, N>=1 - for N=1 a constant model is constructed. - -OUTPUT PARAMETERS - P - barycentric model which represents Lagrange interpolant - (see ratint unit info and BarycentricCalc() description for - more information). - - -- ALGLIB -- - Copyright 03.12.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void polynomialbuildcheb2(const double a, const double b, const real_1d_array &y, barycentricinterpolant &p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = y.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::polynomialbuildcheb2(a, b, const_cast(y.c_ptr()), n, const_cast(p.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Fast equidistant polynomial interpolation function with O(N) complexity - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - F - function values, array[0..N-1] - N - number of points on equidistant grid, N>=1 - for N=1 a constant model is constructed. - T - position where P(x) is calculated - -RESULT - value of the Lagrange interpolant at T - -IMPORTANT - this function provides fast interface which is not overflow-safe - nor it is very precise. - the best option is to use PolynomialBuildEqDist()/BarycentricCalc() - subroutines unless you are pretty sure that your data will not result - in overflow. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -double polynomialcalceqdist(const double a, const double b, const real_1d_array &f, const ae_int_t n, const double t, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::polynomialcalceqdist(a, b, const_cast(f.c_ptr()), n, t, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Fast equidistant polynomial interpolation function with O(N) complexity - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - F - function values, array[0..N-1] - N - number of points on equidistant grid, N>=1 - for N=1 a constant model is constructed. - T - position where P(x) is calculated - -RESULT - value of the Lagrange interpolant at T - -IMPORTANT - this function provides fast interface which is not overflow-safe - nor it is very precise. - the best option is to use PolynomialBuildEqDist()/BarycentricCalc() - subroutines unless you are pretty sure that your data will not result - in overflow. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -double polynomialcalceqdist(const double a, const double b, const real_1d_array &f, const double t, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = f.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::polynomialcalceqdist(a, b, const_cast(f.c_ptr()), n, t, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -Fast polynomial interpolation function on Chebyshev points (first kind) -with O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - F - function values, array[0..N-1] - N - number of points on Chebyshev grid (first kind), - X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n)) - for N=1 a constant model is constructed. - T - position where P(x) is calculated - -RESULT - value of the Lagrange interpolant at T - -IMPORTANT - this function provides fast interface which is not overflow-safe - nor it is very precise. - the best option is to use PolIntBuildCheb1()/BarycentricCalc() - subroutines unless you are pretty sure that your data will not result - in overflow. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -double polynomialcalccheb1(const double a, const double b, const real_1d_array &f, const ae_int_t n, const double t, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::polynomialcalccheb1(a, b, const_cast(f.c_ptr()), n, t, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Fast polynomial interpolation function on Chebyshev points (first kind) -with O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - F - function values, array[0..N-1] - N - number of points on Chebyshev grid (first kind), - X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n)) - for N=1 a constant model is constructed. - T - position where P(x) is calculated - -RESULT - value of the Lagrange interpolant at T - -IMPORTANT - this function provides fast interface which is not overflow-safe - nor it is very precise. - the best option is to use PolIntBuildCheb1()/BarycentricCalc() - subroutines unless you are pretty sure that your data will not result - in overflow. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -double polynomialcalccheb1(const double a, const double b, const real_1d_array &f, const double t, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = f.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::polynomialcalccheb1(a, b, const_cast(f.c_ptr()), n, t, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -Fast polynomial interpolation function on Chebyshev points (second kind) -with O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - F - function values, array[0..N-1] - N - number of points on Chebyshev grid (second kind), - X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1)) - for N=1 a constant model is constructed. - T - position where P(x) is calculated - -RESULT - value of the Lagrange interpolant at T - -IMPORTANT - this function provides fast interface which is not overflow-safe - nor it is very precise. - the best option is to use PolIntBuildCheb2()/BarycentricCalc() - subroutines unless you are pretty sure that your data will not result - in overflow. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -double polynomialcalccheb2(const double a, const double b, const real_1d_array &f, const ae_int_t n, const double t, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::polynomialcalccheb2(a, b, const_cast(f.c_ptr()), n, t, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Fast polynomial interpolation function on Chebyshev points (second kind) -with O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - F - function values, array[0..N-1] - N - number of points on Chebyshev grid (second kind), - X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1)) - for N=1 a constant model is constructed. - T - position where P(x) is calculated - -RESULT - value of the Lagrange interpolant at T - -IMPORTANT - this function provides fast interface which is not overflow-safe - nor it is very precise. - the best option is to use PolIntBuildCheb2()/BarycentricCalc() - subroutines unless you are pretty sure that your data will not result - in overflow. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -double polynomialcalccheb2(const double a, const double b, const real_1d_array &f, const double t, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = f.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::polynomialcalccheb2(a, b, const_cast(f.c_ptr()), n, t, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif -#endif - -#if defined(AE_COMPILE_LSFIT) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Polynomial fitting report: - TaskRCond reciprocal of task's condition number - RMSError RMS error - AvgError average error - AvgRelError average relative error (for non-zero Y[I]) - MaxError maximum error -*************************************************************************/ -_polynomialfitreport_owner::_polynomialfitreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_polynomialfitreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::polynomialfitreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::polynomialfitreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::polynomialfitreport)); - alglib_impl::_polynomialfitreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_polynomialfitreport_owner::_polynomialfitreport_owner(const _polynomialfitreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_polynomialfitreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: polynomialfitreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::polynomialfitreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::polynomialfitreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::polynomialfitreport)); - alglib_impl::_polynomialfitreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_polynomialfitreport_owner& _polynomialfitreport_owner::operator=(const _polynomialfitreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: polynomialfitreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: polynomialfitreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_polynomialfitreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::polynomialfitreport)); - alglib_impl::_polynomialfitreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_polynomialfitreport_owner::~_polynomialfitreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_polynomialfitreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::polynomialfitreport* _polynomialfitreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::polynomialfitreport* _polynomialfitreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -polynomialfitreport::polynomialfitreport() : _polynomialfitreport_owner() ,taskrcond(p_struct->taskrcond),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),maxerror(p_struct->maxerror) -{ -} - -polynomialfitreport::polynomialfitreport(const polynomialfitreport &rhs):_polynomialfitreport_owner(rhs) ,taskrcond(p_struct->taskrcond),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),maxerror(p_struct->maxerror) -{ -} - -polynomialfitreport& polynomialfitreport::operator=(const polynomialfitreport &rhs) -{ - if( this==&rhs ) - return *this; - _polynomialfitreport_owner::operator=(rhs); - return *this; -} - -polynomialfitreport::~polynomialfitreport() -{ -} - - -/************************************************************************* -Barycentric fitting report: - RMSError RMS error - AvgError average error - AvgRelError average relative error (for non-zero Y[I]) - MaxError maximum error - TaskRCond reciprocal of task's condition number -*************************************************************************/ -_barycentricfitreport_owner::_barycentricfitreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_barycentricfitreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::barycentricfitreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::barycentricfitreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::barycentricfitreport)); - alglib_impl::_barycentricfitreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_barycentricfitreport_owner::_barycentricfitreport_owner(const _barycentricfitreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_barycentricfitreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: barycentricfitreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::barycentricfitreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::barycentricfitreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::barycentricfitreport)); - alglib_impl::_barycentricfitreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_barycentricfitreport_owner& _barycentricfitreport_owner::operator=(const _barycentricfitreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: barycentricfitreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: barycentricfitreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_barycentricfitreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::barycentricfitreport)); - alglib_impl::_barycentricfitreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_barycentricfitreport_owner::~_barycentricfitreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_barycentricfitreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::barycentricfitreport* _barycentricfitreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::barycentricfitreport* _barycentricfitreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -barycentricfitreport::barycentricfitreport() : _barycentricfitreport_owner() ,taskrcond(p_struct->taskrcond),dbest(p_struct->dbest),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),maxerror(p_struct->maxerror) -{ -} - -barycentricfitreport::barycentricfitreport(const barycentricfitreport &rhs):_barycentricfitreport_owner(rhs) ,taskrcond(p_struct->taskrcond),dbest(p_struct->dbest),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),maxerror(p_struct->maxerror) -{ -} - -barycentricfitreport& barycentricfitreport::operator=(const barycentricfitreport &rhs) -{ - if( this==&rhs ) - return *this; - _barycentricfitreport_owner::operator=(rhs); - return *this; -} - -barycentricfitreport::~barycentricfitreport() -{ -} - - -/************************************************************************* -Least squares fitting report. This structure contains informational fields -which are set by fitting functions provided by this unit. - -Different functions initialize different sets of fields, so you should -read documentation on specific function you used in order to know which -fields are initialized. - - TaskRCond reciprocal of task's condition number - IterationsCount number of internal iterations - - VarIdx if user-supplied gradient contains errors which were - detected by nonlinear fitter, this field is set to - index of the first component of gradient which is - suspected to be spoiled by bugs. - - RMSError RMS error - AvgError average error - AvgRelError average relative error (for non-zero Y[I]) - MaxError maximum error - - WRMSError weighted RMS error - - CovPar covariance matrix for parameters, filled by some solvers - ErrPar vector of errors in parameters, filled by some solvers - ErrCurve vector of fit errors - variability of the best-fit - curve, filled by some solvers. - Noise vector of per-point noise estimates, filled by - some solvers. - R2 coefficient of determination (non-weighted, non-adjusted), - filled by some solvers. -*************************************************************************/ -_lsfitreport_owner::_lsfitreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_lsfitreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::lsfitreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::lsfitreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::lsfitreport)); - alglib_impl::_lsfitreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_lsfitreport_owner::_lsfitreport_owner(const _lsfitreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_lsfitreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: lsfitreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::lsfitreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::lsfitreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::lsfitreport)); - alglib_impl::_lsfitreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_lsfitreport_owner& _lsfitreport_owner::operator=(const _lsfitreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: lsfitreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: lsfitreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_lsfitreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::lsfitreport)); - alglib_impl::_lsfitreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_lsfitreport_owner::~_lsfitreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_lsfitreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::lsfitreport* _lsfitreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::lsfitreport* _lsfitreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -lsfitreport::lsfitreport() : _lsfitreport_owner() ,taskrcond(p_struct->taskrcond),iterationscount(p_struct->iterationscount),varidx(p_struct->varidx),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),maxerror(p_struct->maxerror),wrmserror(p_struct->wrmserror),covpar(&p_struct->covpar),errpar(&p_struct->errpar),errcurve(&p_struct->errcurve),noise(&p_struct->noise),r2(p_struct->r2) -{ -} - -lsfitreport::lsfitreport(const lsfitreport &rhs):_lsfitreport_owner(rhs) ,taskrcond(p_struct->taskrcond),iterationscount(p_struct->iterationscount),varidx(p_struct->varidx),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),maxerror(p_struct->maxerror),wrmserror(p_struct->wrmserror),covpar(&p_struct->covpar),errpar(&p_struct->errpar),errcurve(&p_struct->errcurve),noise(&p_struct->noise),r2(p_struct->r2) -{ -} - -lsfitreport& lsfitreport::operator=(const lsfitreport &rhs) -{ - if( this==&rhs ) - return *this; - _lsfitreport_owner::operator=(rhs); - return *this; -} - -lsfitreport::~lsfitreport() -{ -} - - -/************************************************************************* -Nonlinear fitter. - -You should use ALGLIB functions to work with fitter. -Never try to access its fields directly! -*************************************************************************/ -_lsfitstate_owner::_lsfitstate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_lsfitstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::lsfitstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::lsfitstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::lsfitstate)); - alglib_impl::_lsfitstate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_lsfitstate_owner::_lsfitstate_owner(const _lsfitstate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_lsfitstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: lsfitstate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::lsfitstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::lsfitstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::lsfitstate)); - alglib_impl::_lsfitstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_lsfitstate_owner& _lsfitstate_owner::operator=(const _lsfitstate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: lsfitstate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: lsfitstate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_lsfitstate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::lsfitstate)); - alglib_impl::_lsfitstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_lsfitstate_owner::~_lsfitstate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_lsfitstate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::lsfitstate* _lsfitstate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::lsfitstate* _lsfitstate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -lsfitstate::lsfitstate() : _lsfitstate_owner() ,needf(p_struct->needf),needfg(p_struct->needfg),needfgh(p_struct->needfgh),xupdated(p_struct->xupdated),c(&p_struct->c),f(p_struct->f),g(&p_struct->g),h(&p_struct->h),x(&p_struct->x) -{ -} - -lsfitstate::lsfitstate(const lsfitstate &rhs):_lsfitstate_owner(rhs) ,needf(p_struct->needf),needfg(p_struct->needfg),needfgh(p_struct->needfgh),xupdated(p_struct->xupdated),c(&p_struct->c),f(p_struct->f),g(&p_struct->g),h(&p_struct->h),x(&p_struct->x) -{ -} - -lsfitstate& lsfitstate::operator=(const lsfitstate &rhs) -{ - if( this==&rhs ) - return *this; - _lsfitstate_owner::operator=(rhs); - return *this; -} - -lsfitstate::~lsfitstate() -{ -} - -/************************************************************************* -This subroutine fits piecewise linear curve to points with Ramer-Douglas- -Peucker algorithm, which stops after generating specified number of linear -sections. - -IMPORTANT: -* it does NOT perform least-squares fitting; it builds curve, but this - curve does not minimize some least squares metric. See description of - RDP algorithm (say, in Wikipedia) for more details on WHAT is performed. -* this function does NOT work with parametric curves (i.e. curves which - can be represented as {X(t),Y(t)}. It works with curves which can be - represented as Y(X). Thus, it is impossible to model figures like - circles with this functions. - If you want to work with parametric curves, you should use - ParametricRDPFixed() function provided by "Parametric" subpackage of - "Interpolation" package. - -INPUT PARAMETERS: - X - array of X-coordinates: - * at least N elements - * can be unordered (points are automatically sorted) - * this function may accept non-distinct X (see below for - more information on handling of such inputs) - Y - array of Y-coordinates: - * at least N elements - N - number of elements in X/Y - M - desired number of sections: - * at most M sections are generated by this function - * less than M sections can be generated if we have N(x.c_ptr()), const_cast(y.c_ptr()), n, m, const_cast(x2.c_ptr()), const_cast(y2.c_ptr()), &nsections, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine fits piecewise linear curve to points with Ramer-Douglas- -Peucker algorithm, which stops after achieving desired precision. - -IMPORTANT: -* it performs non-least-squares fitting; it builds curve, but this curve - does not minimize some least squares metric. See description of RDP - algorithm (say, in Wikipedia) for more details on WHAT is performed. -* this function does NOT work with parametric curves (i.e. curves which - can be represented as {X(t),Y(t)}. It works with curves which can be - represented as Y(X). Thus, it is impossible to model figures like circles - with this functions. - If you want to work with parametric curves, you should use - ParametricRDPFixed() function provided by "Parametric" subpackage of - "Interpolation" package. - -INPUT PARAMETERS: - X - array of X-coordinates: - * at least N elements - * can be unordered (points are automatically sorted) - * this function may accept non-distinct X (see below for - more information on handling of such inputs) - Y - array of Y-coordinates: - * at least N elements - N - number of elements in X/Y - Eps - positive number, desired precision. - - -OUTPUT PARAMETERS: - X2 - X-values of corner points for piecewise approximation, - has length NSections+1 or zero (for NSections=0). - Y2 - Y-values of corner points, - has length NSections+1 or zero (for NSections=0). - NSections- number of sections found by algorithm, - NSections can be zero for degenerate datasets - (N<=1 or all X[] are non-distinct). - -NOTE: X2/Y2 are ordered arrays, i.e. (X2[0],Y2[0]) is a first point of - curve, (X2[NSection-1],Y2[NSection-1]) is the last point. - - -- ALGLIB -- - Copyright 02.10.2014 by Bochkanov Sergey -*************************************************************************/ -void lstfitpiecewiselinearrdp(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const double eps, real_1d_array &x2, real_1d_array &y2, ae_int_t &nsections, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lstfitpiecewiselinearrdp(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, eps, const_cast(x2.c_ptr()), const_cast(y2.c_ptr()), &nsections, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Fitting by polynomials in barycentric form. This function provides simple -unterface for unconstrained unweighted fitting. See PolynomialFitWC() if -you need constrained fitting. - -Task is linear, so linear least squares solver is used. Complexity of this -computational scheme is O(N*M^2), mostly dominated by least squares solver - -SEE ALSO: - PolynomialFitWC() - -NOTES: - you can convert P from barycentric form to the power or Chebyshev - basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions from - POLINT subpackage. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - N - number of points, N>0 - * if given, only leading N elements of X/Y are used - * if not given, automatically determined from sizes of X/Y - M - number of basis functions (= polynomial_degree + 1), M>=1 - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearW() subroutine: - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - P - interpolant in barycentric form. - Rep - report, same format as in LSFitLinearW() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - - -- ALGLIB PROJECT -- - Copyright 10.12.2009 by Bochkanov Sergey -*************************************************************************/ -void polynomialfit(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t m, ae_int_t &info, barycentricinterpolant &p, polynomialfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::polynomialfit(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, m, &info, const_cast(p.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Fitting by polynomials in barycentric form. This function provides simple -unterface for unconstrained unweighted fitting. See PolynomialFitWC() if -you need constrained fitting. - -Task is linear, so linear least squares solver is used. Complexity of this -computational scheme is O(N*M^2), mostly dominated by least squares solver - -SEE ALSO: - PolynomialFitWC() - -NOTES: - you can convert P from barycentric form to the power or Chebyshev - basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions from - POLINT subpackage. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - N - number of points, N>0 - * if given, only leading N elements of X/Y are used - * if not given, automatically determined from sizes of X/Y - M - number of basis functions (= polynomial_degree + 1), M>=1 - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearW() subroutine: - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - P - interpolant in barycentric form. - Rep - report, same format as in LSFitLinearW() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - - -- ALGLIB PROJECT -- - Copyright 10.12.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void polynomialfit(const real_1d_array &x, const real_1d_array &y, const ae_int_t m, ae_int_t &info, barycentricinterpolant &p, polynomialfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (x.length()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'polynomialfit': looks like one of arguments has wrong size"); - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::polynomialfit(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, m, &info, const_cast(p.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Weighted fitting by polynomials in barycentric form, with constraints on -function values or first derivatives. - -Small regularizing term is used when solving constrained tasks (to improve -stability). - -Task is linear, so linear least squares solver is used. Complexity of this -computational scheme is O(N*M^2), mostly dominated by least squares solver - -SEE ALSO: - PolynomialFit() - -NOTES: - you can convert P from barycentric form to the power or Chebyshev - basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions from - POLINT subpackage. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - W - weights, array[0..N-1] - Each summand in square sum of approximation deviations from - given values is multiplied by the square of corresponding - weight. Fill it by 1's if you don't want to solve weighted - task. - N - number of points, N>0. - * if given, only leading N elements of X/Y/W are used - * if not given, automatically determined from sizes of X/Y/W - XC - points where polynomial values/derivatives are constrained, - array[0..K-1]. - YC - values of constraints, array[0..K-1] - DC - array[0..K-1], types of constraints: - * DC[i]=0 means that P(XC[i])=YC[i] - * DC[i]=1 means that P'(XC[i])=YC[i] - SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS - K - number of constraints, 0<=K=1 - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearW() subroutine: - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - P - interpolant in barycentric form. - Rep - report, same format as in LSFitLinearW() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - -SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: - -Setting constraints can lead to undesired results, like ill-conditioned -behavior, or inconsistency being detected. From the other side, it allows -us to improve quality of the fit. Here we summarize our experience with -constrained regression splines: -* even simple constraints can be inconsistent, see Wikipedia article on - this subject: http://en.wikipedia.org/wiki/Birkhoff_interpolation -* the greater is M (given fixed constraints), the more chances that - constraints will be consistent -* in the general case, consistency of constraints is NOT GUARANTEED. -* in the one special cases, however, we can guarantee consistency. This - case is: M>1 and constraints on the function values (NOT DERIVATIVES) - -Our final recommendation is to use constraints WHEN AND ONLY when you -can't solve your task without them. Anything beyond special cases given -above is not guaranteed and may result in inconsistency. - - -- ALGLIB PROJECT -- - Copyright 10.12.2009 by Bochkanov Sergey -*************************************************************************/ -void polynomialfitwc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t n, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t k, const ae_int_t m, ae_int_t &info, barycentricinterpolant &p, polynomialfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::polynomialfitwc(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(w.c_ptr()), n, const_cast(xc.c_ptr()), const_cast(yc.c_ptr()), const_cast(dc.c_ptr()), k, m, &info, const_cast(p.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Weighted fitting by polynomials in barycentric form, with constraints on -function values or first derivatives. - -Small regularizing term is used when solving constrained tasks (to improve -stability). - -Task is linear, so linear least squares solver is used. Complexity of this -computational scheme is O(N*M^2), mostly dominated by least squares solver - -SEE ALSO: - PolynomialFit() - -NOTES: - you can convert P from barycentric form to the power or Chebyshev - basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions from - POLINT subpackage. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - W - weights, array[0..N-1] - Each summand in square sum of approximation deviations from - given values is multiplied by the square of corresponding - weight. Fill it by 1's if you don't want to solve weighted - task. - N - number of points, N>0. - * if given, only leading N elements of X/Y/W are used - * if not given, automatically determined from sizes of X/Y/W - XC - points where polynomial values/derivatives are constrained, - array[0..K-1]. - YC - values of constraints, array[0..K-1] - DC - array[0..K-1], types of constraints: - * DC[i]=0 means that P(XC[i])=YC[i] - * DC[i]=1 means that P'(XC[i])=YC[i] - SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS - K - number of constraints, 0<=K=1 - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearW() subroutine: - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - P - interpolant in barycentric form. - Rep - report, same format as in LSFitLinearW() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - -SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: - -Setting constraints can lead to undesired results, like ill-conditioned -behavior, or inconsistency being detected. From the other side, it allows -us to improve quality of the fit. Here we summarize our experience with -constrained regression splines: -* even simple constraints can be inconsistent, see Wikipedia article on - this subject: http://en.wikipedia.org/wiki/Birkhoff_interpolation -* the greater is M (given fixed constraints), the more chances that - constraints will be consistent -* in the general case, consistency of constraints is NOT GUARANTEED. -* in the one special cases, however, we can guarantee consistency. This - case is: M>1 and constraints on the function values (NOT DERIVATIVES) - -Our final recommendation is to use constraints WHEN AND ONLY when you -can't solve your task without them. Anything beyond special cases given -above is not guaranteed and may result in inconsistency. - - -- ALGLIB PROJECT -- - Copyright 10.12.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void polynomialfitwc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t m, ae_int_t &info, barycentricinterpolant &p, polynomialfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t k; - if( (x.length()!=y.length()) || (x.length()!=w.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'polynomialfitwc': looks like one of arguments has wrong size"); - if( (xc.length()!=yc.length()) || (xc.length()!=dc.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'polynomialfitwc': looks like one of arguments has wrong size"); - n = x.length(); - k = xc.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::polynomialfitwc(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(w.c_ptr()), n, const_cast(xc.c_ptr()), const_cast(yc.c_ptr()), const_cast(dc.c_ptr()), k, m, &info, const_cast(p.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function calculates value of four-parameter logistic (4PL) model at -specified point X. 4PL model has following form: - - F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B)) - -INPUT PARAMETERS: - X - current point, X>=0: - * zero X is correctly handled even for B<=0 - * negative X results in exception. - A, B, C, D- parameters of 4PL model: - * A is unconstrained - * B is unconstrained; zero or negative values are handled - correctly. - * C>0, non-positive value results in exception - * D is unconstrained - -RESULT: - model value at X - -NOTE: if B=0, denominator is assumed to be equal to 2.0 even for zero X - (strictly speaking, 0^0 is undefined). - -NOTE: this function also throws exception if all input parameters are - correct, but overflow was detected during calculations. - -NOTE: this function performs a lot of checks; if you need really high - performance, consider evaluating model yourself, without checking - for degenerate cases. - - - -- ALGLIB PROJECT -- - Copyright 14.05.2014 by Bochkanov Sergey -*************************************************************************/ -double logisticcalc4(const double x, const double a, const double b, const double c, const double d, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::logisticcalc4(x, a, b, c, d, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function calculates value of five-parameter logistic (5PL) model at -specified point X. 5PL model has following form: - - F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G) - -INPUT PARAMETERS: - X - current point, X>=0: - * zero X is correctly handled even for B<=0 - * negative X results in exception. - A, B, C, D, G- parameters of 5PL model: - * A is unconstrained - * B is unconstrained; zero or negative values are handled - correctly. - * C>0, non-positive value results in exception - * D is unconstrained - * G>0, non-positive value results in exception - -RESULT: - model value at X - -NOTE: if B=0, denominator is assumed to be equal to Power(2.0,G) even for - zero X (strictly speaking, 0^0 is undefined). - -NOTE: this function also throws exception if all input parameters are - correct, but overflow was detected during calculations. - -NOTE: this function performs a lot of checks; if you need really high - performance, consider evaluating model yourself, without checking - for degenerate cases. - - - -- ALGLIB PROJECT -- - Copyright 14.05.2014 by Bochkanov Sergey -*************************************************************************/ -double logisticcalc5(const double x, const double a, const double b, const double c, const double d, const double g, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::logisticcalc5(x, a, b, c, d, g, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function fits four-parameter logistic (4PL) model to data provided -by user. 4PL model has following form: - - F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B)) - -Here: - * A, D - unconstrained (see LogisticFit4EC() for constrained 4PL) - * B>=0 - * C>0 - -IMPORTANT: output of this function is constrained in such way that B>0. - Because 4PL model is symmetric with respect to B, there is no - need to explore B<0. Constraining B makes algorithm easier - to stabilize and debug. - Users who for some reason prefer to work with negative B's - should transform output themselves (swap A and D, replace B by - -B). - -4PL fitting is implemented as follows: -* we perform small number of restarts from random locations which helps to - solve problem of bad local extrema. Locations are only partially random - - we use input data to determine good initial guess, but we include - controlled amount of randomness. -* we perform Levenberg-Marquardt fitting with very tight constraints on - parameters B and C - it allows us to find good initial guess for the - second stage without risk of running into "flat spot". -* second Levenberg-Marquardt round is performed without excessive - constraints. Results from the previous round are used as initial guess. -* after fitting is done, we compare results with best values found so far, - rewrite "best solution" if needed, and move to next random location. - -Overall algorithm is very stable and is not prone to bad local extrema. -Furthermore, it automatically scales when input data have very large or -very small range. - -INPUT PARAMETERS: - X - array[N], stores X-values. - MUST include only non-negative numbers (but may include - zero values). Can be unsorted. - Y - array[N], values to fit. - N - number of points. If N is less than length of X/Y, only - leading N elements are used. - -OUTPUT PARAMETERS: - A, B, C, D- parameters of 4PL model - Rep - fitting report. This structure has many fields, but ONLY - ONES LISTED BELOW ARE SET: - * Rep.IterationsCount - number of iterations performed - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average absolute error - * Rep.AvgRelError - average relative error (calculated for - non-zero Y-values) - * Rep.MaxError - maximum absolute error - * Rep.R2 - coefficient of determination, R-squared. This - coefficient is calculated as R2=1-RSS/TSS (in case - of nonlinear regression there are multiple ways to - define R2, each of them giving different results). - -NOTE: for stability reasons the B parameter is restricted by [1/1000,1000] - range. It prevents algorithm from making trial steps deep into the - area of bad parameters. - -NOTE: after you obtained coefficients, you can evaluate model with - LogisticCalc4() function. - -NOTE: if you need better control over fitting process than provided by this - function, you may use LogisticFit45X(). - -NOTE: step is automatically scaled according to scale of parameters being - fitted before we compare its length with EpsX. Thus, this function - can be used to fit data with very small or very large values without - changing EpsX. - - - -- ALGLIB PROJECT -- - Copyright 14.02.2014 by Bochkanov Sergey -*************************************************************************/ -void logisticfit4(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, double &a, double &b, double &c, double &d, lsfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::logisticfit4(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, &a, &b, &c, &d, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function fits four-parameter logistic (4PL) model to data provided -by user, with optional constraints on parameters A and D. 4PL model has -following form: - - F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B)) - -Here: - * A, D - with optional equality constraints - * B>=0 - * C>0 - -IMPORTANT: output of this function is constrained in such way that B>0. - Because 4PL model is symmetric with respect to B, there is no - need to explore B<0. Constraining B makes algorithm easier - to stabilize and debug. - Users who for some reason prefer to work with negative B's - should transform output themselves (swap A and D, replace B by - -B). - -4PL fitting is implemented as follows: -* we perform small number of restarts from random locations which helps to - solve problem of bad local extrema. Locations are only partially random - - we use input data to determine good initial guess, but we include - controlled amount of randomness. -* we perform Levenberg-Marquardt fitting with very tight constraints on - parameters B and C - it allows us to find good initial guess for the - second stage without risk of running into "flat spot". -* second Levenberg-Marquardt round is performed without excessive - constraints. Results from the previous round are used as initial guess. -* after fitting is done, we compare results with best values found so far, - rewrite "best solution" if needed, and move to next random location. - -Overall algorithm is very stable and is not prone to bad local extrema. -Furthermore, it automatically scales when input data have very large or -very small range. - -INPUT PARAMETERS: - X - array[N], stores X-values. - MUST include only non-negative numbers (but may include - zero values). Can be unsorted. - Y - array[N], values to fit. - N - number of points. If N is less than length of X/Y, only - leading N elements are used. - CnstrLeft- optional equality constraint for model value at the left - boundary (at X=0). Specify NAN (Not-a-Number) if you do - not need constraint on the model value at X=0 (in C++ you - can pass alglib::fp_nan as parameter, in C# it will be - Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - CnstrRight- optional equality constraint for model value at X=infinity. - Specify NAN (Not-a-Number) if you do not need constraint - on the model value (in C++ you can pass alglib::fp_nan as - parameter, in C# it will be Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - -OUTPUT PARAMETERS: - A, B, C, D- parameters of 4PL model - Rep - fitting report. This structure has many fields, but ONLY - ONES LISTED BELOW ARE SET: - * Rep.IterationsCount - number of iterations performed - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average absolute error - * Rep.AvgRelError - average relative error (calculated for - non-zero Y-values) - * Rep.MaxError - maximum absolute error - * Rep.R2 - coefficient of determination, R-squared. This - coefficient is calculated as R2=1-RSS/TSS (in case - of nonlinear regression there are multiple ways to - define R2, each of them giving different results). - -NOTE: for stability reasons the B parameter is restricted by [1/1000,1000] - range. It prevents algorithm from making trial steps deep into the - area of bad parameters. - -NOTE: after you obtained coefficients, you can evaluate model with - LogisticCalc4() function. - -NOTE: if you need better control over fitting process than provided by this - function, you may use LogisticFit45X(). - -NOTE: step is automatically scaled according to scale of parameters being - fitted before we compare its length with EpsX. Thus, this function - can be used to fit data with very small or very large values without - changing EpsX. - -EQUALITY CONSTRAINTS ON PARAMETERS - -4PL/5PL solver supports equality constraints on model values at the left -boundary (X=0) and right boundary (X=infinity). These constraints are -completely optional and you can specify both of them, only one - or no -constraints at all. - -Parameter CnstrLeft contains left constraint (or NAN for unconstrained -fitting), and CnstrRight contains right one. For 4PL, left constraint -ALWAYS corresponds to parameter A, and right one is ALWAYS constraint on -D. That's because 4PL model is normalized in such way that B>=0. - - - -- ALGLIB PROJECT -- - Copyright 14.02.2014 by Bochkanov Sergey -*************************************************************************/ -void logisticfit4ec(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const double cnstrleft, const double cnstrright, double &a, double &b, double &c, double &d, lsfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::logisticfit4ec(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, cnstrleft, cnstrright, &a, &b, &c, &d, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function fits five-parameter logistic (5PL) model to data provided -by user. 5PL model has following form: - - F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G) - -Here: - * A, D - unconstrained - * B - unconstrained - * C>0 - * G>0 - -IMPORTANT: unlike in 4PL fitting, output of this function is NOT - constrained in such way that B is guaranteed to be positive. - Furthermore, unlike 4PL, 5PL model is NOT symmetric with - respect to B, so you can NOT transform model to equivalent one, - with B having desired sign (>0 or <0). - -5PL fitting is implemented as follows: -* we perform small number of restarts from random locations which helps to - solve problem of bad local extrema. Locations are only partially random - - we use input data to determine good initial guess, but we include - controlled amount of randomness. -* we perform Levenberg-Marquardt fitting with very tight constraints on - parameters B and C - it allows us to find good initial guess for the - second stage without risk of running into "flat spot". Parameter G is - fixed at G=1. -* second Levenberg-Marquardt round is performed without excessive - constraints on B and C, but with G still equal to 1. Results from the - previous round are used as initial guess. -* third Levenberg-Marquardt round relaxes constraints on G and tries two - different models - one with B>0 and one with B<0. -* after fitting is done, we compare results with best values found so far, - rewrite "best solution" if needed, and move to next random location. - -Overall algorithm is very stable and is not prone to bad local extrema. -Furthermore, it automatically scales when input data have very large or -very small range. - -INPUT PARAMETERS: - X - array[N], stores X-values. - MUST include only non-negative numbers (but may include - zero values). Can be unsorted. - Y - array[N], values to fit. - N - number of points. If N is less than length of X/Y, only - leading N elements are used. - -OUTPUT PARAMETERS: - A,B,C,D,G- parameters of 5PL model - Rep - fitting report. This structure has many fields, but ONLY - ONES LISTED BELOW ARE SET: - * Rep.IterationsCount - number of iterations performed - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average absolute error - * Rep.AvgRelError - average relative error (calculated for - non-zero Y-values) - * Rep.MaxError - maximum absolute error - * Rep.R2 - coefficient of determination, R-squared. This - coefficient is calculated as R2=1-RSS/TSS (in case - of nonlinear regression there are multiple ways to - define R2, each of them giving different results). - -NOTE: for better stability B parameter is restricted by [+-1/1000,+-1000] - range, and G is restricted by [1/10,10] range. It prevents algorithm - from making trial steps deep into the area of bad parameters. - -NOTE: after you obtained coefficients, you can evaluate model with - LogisticCalc5() function. - -NOTE: if you need better control over fitting process than provided by this - function, you may use LogisticFit45X(). - -NOTE: step is automatically scaled according to scale of parameters being - fitted before we compare its length with EpsX. Thus, this function - can be used to fit data with very small or very large values without - changing EpsX. - - - -- ALGLIB PROJECT -- - Copyright 14.02.2014 by Bochkanov Sergey -*************************************************************************/ -void logisticfit5(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, double &a, double &b, double &c, double &d, double &g, lsfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::logisticfit5(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, &a, &b, &c, &d, &g, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function fits five-parameter logistic (5PL) model to data provided -by user, subject to optional equality constraints on parameters A and D. -5PL model has following form: - - F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G) - -Here: - * A, D - with optional equality constraints - * B - unconstrained - * C>0 - * G>0 - -IMPORTANT: unlike in 4PL fitting, output of this function is NOT - constrained in such way that B is guaranteed to be positive. - Furthermore, unlike 4PL, 5PL model is NOT symmetric with - respect to B, so you can NOT transform model to equivalent one, - with B having desired sign (>0 or <0). - -5PL fitting is implemented as follows: -* we perform small number of restarts from random locations which helps to - solve problem of bad local extrema. Locations are only partially random - - we use input data to determine good initial guess, but we include - controlled amount of randomness. -* we perform Levenberg-Marquardt fitting with very tight constraints on - parameters B and C - it allows us to find good initial guess for the - second stage without risk of running into "flat spot". Parameter G is - fixed at G=1. -* second Levenberg-Marquardt round is performed without excessive - constraints on B and C, but with G still equal to 1. Results from the - previous round are used as initial guess. -* third Levenberg-Marquardt round relaxes constraints on G and tries two - different models - one with B>0 and one with B<0. -* after fitting is done, we compare results with best values found so far, - rewrite "best solution" if needed, and move to next random location. - -Overall algorithm is very stable and is not prone to bad local extrema. -Furthermore, it automatically scales when input data have very large or -very small range. - -INPUT PARAMETERS: - X - array[N], stores X-values. - MUST include only non-negative numbers (but may include - zero values). Can be unsorted. - Y - array[N], values to fit. - N - number of points. If N is less than length of X/Y, only - leading N elements are used. - CnstrLeft- optional equality constraint for model value at the left - boundary (at X=0). Specify NAN (Not-a-Number) if you do - not need constraint on the model value at X=0 (in C++ you - can pass alglib::fp_nan as parameter, in C# it will be - Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - CnstrRight- optional equality constraint for model value at X=infinity. - Specify NAN (Not-a-Number) if you do not need constraint - on the model value (in C++ you can pass alglib::fp_nan as - parameter, in C# it will be Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - -OUTPUT PARAMETERS: - A,B,C,D,G- parameters of 5PL model - Rep - fitting report. This structure has many fields, but ONLY - ONES LISTED BELOW ARE SET: - * Rep.IterationsCount - number of iterations performed - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average absolute error - * Rep.AvgRelError - average relative error (calculated for - non-zero Y-values) - * Rep.MaxError - maximum absolute error - * Rep.R2 - coefficient of determination, R-squared. This - coefficient is calculated as R2=1-RSS/TSS (in case - of nonlinear regression there are multiple ways to - define R2, each of them giving different results). - -NOTE: for better stability B parameter is restricted by [+-1/1000,+-1000] - range, and G is restricted by [1/10,10] range. It prevents algorithm - from making trial steps deep into the area of bad parameters. - -NOTE: after you obtained coefficients, you can evaluate model with - LogisticCalc5() function. - -NOTE: if you need better control over fitting process than provided by this - function, you may use LogisticFit45X(). - -NOTE: step is automatically scaled according to scale of parameters being - fitted before we compare its length with EpsX. Thus, this function - can be used to fit data with very small or very large values without - changing EpsX. - -EQUALITY CONSTRAINTS ON PARAMETERS - -5PL solver supports equality constraints on model values at the left -boundary (X=0) and right boundary (X=infinity). These constraints are -completely optional and you can specify both of them, only one - or no -constraints at all. - -Parameter CnstrLeft contains left constraint (or NAN for unconstrained -fitting), and CnstrRight contains right one. - -Unlike 4PL one, 5PL model is NOT symmetric with respect to change in sign -of B. Thus, negative B's are possible, and left constraint may constrain -parameter A (for positive B's) - or parameter D (for negative B's). -Similarly changes meaning of right constraint. - -You do not have to decide what parameter to constrain - algorithm will -automatically determine correct parameters as fitting progresses. However, -question highlighted above is important when you interpret fitting results. - - - -- ALGLIB PROJECT -- - Copyright 14.02.2014 by Bochkanov Sergey -*************************************************************************/ -void logisticfit5ec(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const double cnstrleft, const double cnstrright, double &a, double &b, double &c, double &d, double &g, lsfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::logisticfit5ec(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, cnstrleft, cnstrright, &a, &b, &c, &d, &g, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is "expert" 4PL/5PL fitting function, which can be used if you need -better control over fitting process than provided by LogisticFit4() or -LogisticFit5(). - -This function fits model of the form - - F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B)) (4PL model) - -or - - F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G) (5PL model) - -Here: - * A, D - unconstrained - * B>=0 for 4PL, unconstrained for 5PL - * C>0 - * G>0 (if present) - -INPUT PARAMETERS: - X - array[N], stores X-values. - MUST include only non-negative numbers (but may include - zero values). Can be unsorted. - Y - array[N], values to fit. - N - number of points. If N is less than length of X/Y, only - leading N elements are used. - CnstrLeft- optional equality constraint for model value at the left - boundary (at X=0). Specify NAN (Not-a-Number) if you do - not need constraint on the model value at X=0 (in C++ you - can pass alglib::fp_nan as parameter, in C# it will be - Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - CnstrRight- optional equality constraint for model value at X=infinity. - Specify NAN (Not-a-Number) if you do not need constraint - on the model value (in C++ you can pass alglib::fp_nan as - parameter, in C# it will be Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - Is4PL - whether 4PL or 5PL models are fitted - LambdaV - regularization coefficient, LambdaV>=0. - Set it to zero unless you know what you are doing. - EpsX - stopping condition (step size), EpsX>=0. - Zero value means that small step is automatically chosen. - See notes below for more information. - RsCnt - number of repeated restarts from random points. 4PL/5PL - models are prone to problem of bad local extrema. Utilizing - multiple random restarts allows us to improve algorithm - convergence. - RsCnt>=0. - Zero value means that function automatically choose small - amount of restarts (recommended). - -OUTPUT PARAMETERS: - A, B, C, D- parameters of 4PL model - G - parameter of 5PL model; for Is4PL=True, G=1 is returned. - Rep - fitting report. This structure has many fields, but ONLY - ONES LISTED BELOW ARE SET: - * Rep.IterationsCount - number of iterations performed - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average absolute error - * Rep.AvgRelError - average relative error (calculated for - non-zero Y-values) - * Rep.MaxError - maximum absolute error - * Rep.R2 - coefficient of determination, R-squared. This - coefficient is calculated as R2=1-RSS/TSS (in case - of nonlinear regression there are multiple ways to - define R2, each of them giving different results). - -NOTE: for better stability B parameter is restricted by [+-1/1000,+-1000] - range, and G is restricted by [1/10,10] range. It prevents algorithm - from making trial steps deep into the area of bad parameters. - -NOTE: after you obtained coefficients, you can evaluate model with - LogisticCalc5() function. - -NOTE: step is automatically scaled according to scale of parameters being - fitted before we compare its length with EpsX. Thus, this function - can be used to fit data with very small or very large values without - changing EpsX. - -EQUALITY CONSTRAINTS ON PARAMETERS - -4PL/5PL solver supports equality constraints on model values at the left -boundary (X=0) and right boundary (X=infinity). These constraints are -completely optional and you can specify both of them, only one - or no -constraints at all. - -Parameter CnstrLeft contains left constraint (or NAN for unconstrained -fitting), and CnstrRight contains right one. For 4PL, left constraint -ALWAYS corresponds to parameter A, and right one is ALWAYS constraint on -D. That's because 4PL model is normalized in such way that B>=0. - -For 5PL model things are different. Unlike 4PL one, 5PL model is NOT -symmetric with respect to change in sign of B. Thus, negative B's are -possible, and left constraint may constrain parameter A (for positive B's) -- or parameter D (for negative B's). Similarly changes meaning of right -constraint. - -You do not have to decide what parameter to constrain - algorithm will -automatically determine correct parameters as fitting progresses. However, -question highlighted above is important when you interpret fitting results. - - - -- ALGLIB PROJECT -- - Copyright 14.02.2014 by Bochkanov Sergey -*************************************************************************/ -void logisticfit45x(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const double cnstrleft, const double cnstrright, const bool is4pl, const double lambdav, const double epsx, const ae_int_t rscnt, double &a, double &b, double &c, double &d, double &g, lsfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::logisticfit45x(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, cnstrleft, cnstrright, is4pl, lambdav, epsx, rscnt, &a, &b, &c, &d, &g, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Weghted rational least squares fitting using Floater-Hormann rational -functions with optimal D chosen from [0,9], with constraints and -individual weights. - -Equidistant grid with M node on [min(x),max(x)] is used to build basis -functions. Different values of D are tried, optimal D (least WEIGHTED root -mean square error) is chosen. Task is linear, so linear least squares -solver is used. Complexity of this computational scheme is O(N*M^2) -(mostly dominated by the least squares solver). - -SEE ALSO -* BarycentricFitFloaterHormann(), "lightweight" fitting without invididual - weights and constraints. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - W - weights, array[0..N-1] - Each summand in square sum of approximation deviations from - given values is multiplied by the square of corresponding - weight. Fill it by 1's if you don't want to solve weighted - task. - N - number of points, N>0. - XC - points where function values/derivatives are constrained, - array[0..K-1]. - YC - values of constraints, array[0..K-1] - DC - array[0..K-1], types of constraints: - * DC[i]=0 means that S(XC[i])=YC[i] - * DC[i]=1 means that S'(XC[i])=YC[i] - SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS - K - number of constraints, 0<=K=2. - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearWC() subroutine. - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - -1 means another errors in parameters passed - (N<=0, for example) - B - barycentric interpolant. - Rep - report, same format as in LSFitLinearWC() subroutine. - Following fields are set: - * DBest best value of the D parameter - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroutine doesn't calculate task's condition number for K<>0. - -SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: - -Setting constraints can lead to undesired results, like ill-conditioned -behavior, or inconsistency being detected. From the other side, it allows -us to improve quality of the fit. Here we summarize our experience with -constrained barycentric interpolants: -* excessive constraints can be inconsistent. Floater-Hormann basis - functions aren't as flexible as splines (although they are very smooth). -* the more evenly constraints are spread across [min(x),max(x)], the more - chances that they will be consistent -* the greater is M (given fixed constraints), the more chances that - constraints will be consistent -* in the general case, consistency of constraints IS NOT GUARANTEED. -* in the several special cases, however, we CAN guarantee consistency. -* one of this cases is constraints on the function VALUES at the interval - boundaries. Note that consustency of the constraints on the function - DERIVATIVES is NOT guaranteed (you can use in such cases cubic splines - which are more flexible). -* another special case is ONE constraint on the function value (OR, but - not AND, derivative) anywhere in the interval - -Our final recommendation is to use constraints WHEN AND ONLY WHEN you -can't solve your task without them. Anything beyond special cases given -above is not guaranteed and may result in inconsistency. - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentricfitfloaterhormannwc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t n, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t k, const ae_int_t m, ae_int_t &info, barycentricinterpolant &b, barycentricfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::barycentricfitfloaterhormannwc(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(w.c_ptr()), n, const_cast(xc.c_ptr()), const_cast(yc.c_ptr()), const_cast(dc.c_ptr()), k, m, &info, const_cast(b.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Rational least squares fitting using Floater-Hormann rational functions -with optimal D chosen from [0,9]. - -Equidistant grid with M node on [min(x),max(x)] is used to build basis -functions. Different values of D are tried, optimal D (least root mean -square error) is chosen. Task is linear, so linear least squares solver -is used. Complexity of this computational scheme is O(N*M^2) (mostly -dominated by the least squares solver). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - N - number of points, N>0. - M - number of basis functions ( = number_of_nodes), M>=2. - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearWC() subroutine. - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - B - barycentric interpolant. - Rep - report, same format as in LSFitLinearWC() subroutine. - Following fields are set: - * DBest best value of the D parameter - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentricfitfloaterhormann(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t m, ae_int_t &info, barycentricinterpolant &b, barycentricfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::barycentricfitfloaterhormann(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, m, &info, const_cast(b.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Weighted fitting by cubic spline, with constraints on function values or -derivatives. - -Equidistant grid with M-2 nodes on [min(x,xc),max(x,xc)] is used to build -basis functions. Basis functions are cubic splines with continuous second -derivatives and non-fixed first derivatives at interval ends. Small -regularizing term is used when solving constrained tasks (to improve -stability). - -Task is linear, so linear least squares solver is used. Complexity of this -computational scheme is O(N*M^2), mostly dominated by least squares solver - -SEE ALSO - Spline1DFitHermiteWC() - fitting by Hermite splines (more flexible, - less smooth) - Spline1DFitCubic() - "lightweight" fitting by cubic splines, - without invididual weights and constraints - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - W - weights, array[0..N-1] - Each summand in square sum of approximation deviations from - given values is multiplied by the square of corresponding - weight. Fill it by 1's if you don't want to solve weighted - task. - N - number of points (optional): - * N>0 - * if given, only first N elements of X/Y/W are processed - * if not given, automatically determined from X/Y/W sizes - XC - points where spline values/derivatives are constrained, - array[0..K-1]. - YC - values of constraints, array[0..K-1] - DC - array[0..K-1], types of constraints: - * DC[i]=0 means that S(XC[i])=YC[i] - * DC[i]=1 means that S'(XC[i])=YC[i] - SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS - K - number of constraints (optional): - * 0<=K=4. - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearWC() subroutine. - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - S - spline interpolant. - Rep - report, same format as in LSFitLinearWC() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - -SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: - -Setting constraints can lead to undesired results, like ill-conditioned -behavior, or inconsistency being detected. From the other side, it allows -us to improve quality of the fit. Here we summarize our experience with -constrained regression splines: -* excessive constraints can be inconsistent. Splines are piecewise cubic - functions, and it is easy to create an example, where large number of - constraints concentrated in small area will result in inconsistency. - Just because spline is not flexible enough to satisfy all of them. And - same constraints spread across the [min(x),max(x)] will be perfectly - consistent. -* the more evenly constraints are spread across [min(x),max(x)], the more - chances that they will be consistent -* the greater is M (given fixed constraints), the more chances that - constraints will be consistent -* in the general case, consistency of constraints IS NOT GUARANTEED. -* in the several special cases, however, we CAN guarantee consistency. -* one of this cases is constraints on the function values AND/OR its - derivatives at the interval boundaries. -* another special case is ONE constraint on the function value (OR, but - not AND, derivative) anywhere in the interval - -Our final recommendation is to use constraints WHEN AND ONLY WHEN you -can't solve your task without them. Anything beyond special cases given -above is not guaranteed and may result in inconsistency. - - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -void spline1dfitcubicwc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t n, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t k, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dfitcubicwc(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(w.c_ptr()), n, const_cast(xc.c_ptr()), const_cast(yc.c_ptr()), const_cast(dc.c_ptr()), k, m, &info, const_cast(s.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Weighted fitting by cubic spline, with constraints on function values or -derivatives. - -Equidistant grid with M-2 nodes on [min(x,xc),max(x,xc)] is used to build -basis functions. Basis functions are cubic splines with continuous second -derivatives and non-fixed first derivatives at interval ends. Small -regularizing term is used when solving constrained tasks (to improve -stability). - -Task is linear, so linear least squares solver is used. Complexity of this -computational scheme is O(N*M^2), mostly dominated by least squares solver - -SEE ALSO - Spline1DFitHermiteWC() - fitting by Hermite splines (more flexible, - less smooth) - Spline1DFitCubic() - "lightweight" fitting by cubic splines, - without invididual weights and constraints - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - W - weights, array[0..N-1] - Each summand in square sum of approximation deviations from - given values is multiplied by the square of corresponding - weight. Fill it by 1's if you don't want to solve weighted - task. - N - number of points (optional): - * N>0 - * if given, only first N elements of X/Y/W are processed - * if not given, automatically determined from X/Y/W sizes - XC - points where spline values/derivatives are constrained, - array[0..K-1]. - YC - values of constraints, array[0..K-1] - DC - array[0..K-1], types of constraints: - * DC[i]=0 means that S(XC[i])=YC[i] - * DC[i]=1 means that S'(XC[i])=YC[i] - SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS - K - number of constraints (optional): - * 0<=K=4. - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearWC() subroutine. - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - S - spline interpolant. - Rep - report, same format as in LSFitLinearWC() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - -SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: - -Setting constraints can lead to undesired results, like ill-conditioned -behavior, or inconsistency being detected. From the other side, it allows -us to improve quality of the fit. Here we summarize our experience with -constrained regression splines: -* excessive constraints can be inconsistent. Splines are piecewise cubic - functions, and it is easy to create an example, where large number of - constraints concentrated in small area will result in inconsistency. - Just because spline is not flexible enough to satisfy all of them. And - same constraints spread across the [min(x),max(x)] will be perfectly - consistent. -* the more evenly constraints are spread across [min(x),max(x)], the more - chances that they will be consistent -* the greater is M (given fixed constraints), the more chances that - constraints will be consistent -* in the general case, consistency of constraints IS NOT GUARANTEED. -* in the several special cases, however, we CAN guarantee consistency. -* one of this cases is constraints on the function values AND/OR its - derivatives at the interval boundaries. -* another special case is ONE constraint on the function value (OR, but - not AND, derivative) anywhere in the interval - -Our final recommendation is to use constraints WHEN AND ONLY WHEN you -can't solve your task without them. Anything beyond special cases given -above is not guaranteed and may result in inconsistency. - - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spline1dfitcubicwc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t k; - if( (x.length()!=y.length()) || (x.length()!=w.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dfitcubicwc': looks like one of arguments has wrong size"); - if( (xc.length()!=yc.length()) || (xc.length()!=dc.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dfitcubicwc': looks like one of arguments has wrong size"); - n = x.length(); - k = xc.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dfitcubicwc(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(w.c_ptr()), n, const_cast(xc.c_ptr()), const_cast(yc.c_ptr()), const_cast(dc.c_ptr()), k, m, &info, const_cast(s.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Weighted fitting by Hermite spline, with constraints on function values -or first derivatives. - -Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is used to build -basis functions. Basis functions are Hermite splines. Small regularizing -term is used when solving constrained tasks (to improve stability). - -Task is linear, so linear least squares solver is used. Complexity of this -computational scheme is O(N*M^2), mostly dominated by least squares solver - -SEE ALSO - Spline1DFitCubicWC() - fitting by Cubic splines (less flexible, - more smooth) - Spline1DFitHermite() - "lightweight" Hermite fitting, without - invididual weights and constraints - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - W - weights, array[0..N-1] - Each summand in square sum of approximation deviations from - given values is multiplied by the square of corresponding - weight. Fill it by 1's if you don't want to solve weighted - task. - N - number of points (optional): - * N>0 - * if given, only first N elements of X/Y/W are processed - * if not given, automatically determined from X/Y/W sizes - XC - points where spline values/derivatives are constrained, - array[0..K-1]. - YC - values of constraints, array[0..K-1] - DC - array[0..K-1], types of constraints: - * DC[i]=0 means that S(XC[i])=YC[i] - * DC[i]=1 means that S'(XC[i])=YC[i] - SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS - K - number of constraints (optional): - * 0<=K=4, - M IS EVEN! - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearW() subroutine: - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - -2 means odd M was passed (which is not supported) - -1 means another errors in parameters passed - (N<=0, for example) - S - spline interpolant. - Rep - report, same format as in LSFitLinearW() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - -IMPORTANT: - this subroitine supports only even M's - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - -SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: - -Setting constraints can lead to undesired results, like ill-conditioned -behavior, or inconsistency being detected. From the other side, it allows -us to improve quality of the fit. Here we summarize our experience with -constrained regression splines: -* excessive constraints can be inconsistent. Splines are piecewise cubic - functions, and it is easy to create an example, where large number of - constraints concentrated in small area will result in inconsistency. - Just because spline is not flexible enough to satisfy all of them. And - same constraints spread across the [min(x),max(x)] will be perfectly - consistent. -* the more evenly constraints are spread across [min(x),max(x)], the more - chances that they will be consistent -* the greater is M (given fixed constraints), the more chances that - constraints will be consistent -* in the general case, consistency of constraints is NOT GUARANTEED. -* in the several special cases, however, we can guarantee consistency. -* one of this cases is M>=4 and constraints on the function value - (AND/OR its derivative) at the interval boundaries. -* another special case is M>=4 and ONE constraint on the function value - (OR, BUT NOT AND, derivative) anywhere in [min(x),max(x)] - -Our final recommendation is to use constraints WHEN AND ONLY when you -can't solve your task without them. Anything beyond special cases given -above is not guaranteed and may result in inconsistency. - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -void spline1dfithermitewc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t n, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t k, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dfithermitewc(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(w.c_ptr()), n, const_cast(xc.c_ptr()), const_cast(yc.c_ptr()), const_cast(dc.c_ptr()), k, m, &info, const_cast(s.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Weighted fitting by Hermite spline, with constraints on function values -or first derivatives. - -Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is used to build -basis functions. Basis functions are Hermite splines. Small regularizing -term is used when solving constrained tasks (to improve stability). - -Task is linear, so linear least squares solver is used. Complexity of this -computational scheme is O(N*M^2), mostly dominated by least squares solver - -SEE ALSO - Spline1DFitCubicWC() - fitting by Cubic splines (less flexible, - more smooth) - Spline1DFitHermite() - "lightweight" Hermite fitting, without - invididual weights and constraints - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - W - weights, array[0..N-1] - Each summand in square sum of approximation deviations from - given values is multiplied by the square of corresponding - weight. Fill it by 1's if you don't want to solve weighted - task. - N - number of points (optional): - * N>0 - * if given, only first N elements of X/Y/W are processed - * if not given, automatically determined from X/Y/W sizes - XC - points where spline values/derivatives are constrained, - array[0..K-1]. - YC - values of constraints, array[0..K-1] - DC - array[0..K-1], types of constraints: - * DC[i]=0 means that S(XC[i])=YC[i] - * DC[i]=1 means that S'(XC[i])=YC[i] - SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS - K - number of constraints (optional): - * 0<=K=4, - M IS EVEN! - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearW() subroutine: - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - -2 means odd M was passed (which is not supported) - -1 means another errors in parameters passed - (N<=0, for example) - S - spline interpolant. - Rep - report, same format as in LSFitLinearW() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - -IMPORTANT: - this subroitine supports only even M's - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - -SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: - -Setting constraints can lead to undesired results, like ill-conditioned -behavior, or inconsistency being detected. From the other side, it allows -us to improve quality of the fit. Here we summarize our experience with -constrained regression splines: -* excessive constraints can be inconsistent. Splines are piecewise cubic - functions, and it is easy to create an example, where large number of - constraints concentrated in small area will result in inconsistency. - Just because spline is not flexible enough to satisfy all of them. And - same constraints spread across the [min(x),max(x)] will be perfectly - consistent. -* the more evenly constraints are spread across [min(x),max(x)], the more - chances that they will be consistent -* the greater is M (given fixed constraints), the more chances that - constraints will be consistent -* in the general case, consistency of constraints is NOT GUARANTEED. -* in the several special cases, however, we can guarantee consistency. -* one of this cases is M>=4 and constraints on the function value - (AND/OR its derivative) at the interval boundaries. -* another special case is M>=4 and ONE constraint on the function value - (OR, BUT NOT AND, derivative) anywhere in [min(x),max(x)] - -Our final recommendation is to use constraints WHEN AND ONLY when you -can't solve your task without them. Anything beyond special cases given -above is not guaranteed and may result in inconsistency. - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spline1dfithermitewc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t k; - if( (x.length()!=y.length()) || (x.length()!=w.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dfithermitewc': looks like one of arguments has wrong size"); - if( (xc.length()!=yc.length()) || (xc.length()!=dc.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dfithermitewc': looks like one of arguments has wrong size"); - n = x.length(); - k = xc.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dfithermitewc(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(w.c_ptr()), n, const_cast(xc.c_ptr()), const_cast(yc.c_ptr()), const_cast(dc.c_ptr()), k, m, &info, const_cast(s.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Least squares fitting by cubic spline. - -This subroutine is "lightweight" alternative for more complex and feature- -rich Spline1DFitCubicWC(). See Spline1DFitCubicWC() for more information -about subroutine parameters (we don't duplicate it here because of length) - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -void spline1dfitcubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dfitcubic(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, m, &info, const_cast(s.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Least squares fitting by cubic spline. - -This subroutine is "lightweight" alternative for more complex and feature- -rich Spline1DFitCubicWC(). See Spline1DFitCubicWC() for more information -about subroutine parameters (we don't duplicate it here because of length) - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spline1dfitcubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (x.length()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dfitcubic': looks like one of arguments has wrong size"); - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dfitcubic(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, m, &info, const_cast(s.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Least squares fitting by Hermite spline. - -This subroutine is "lightweight" alternative for more complex and feature- -rich Spline1DFitHermiteWC(). See Spline1DFitHermiteWC() description for -more information about subroutine parameters (we don't duplicate it here -because of length). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -void spline1dfithermite(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dfithermite(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, m, &info, const_cast(s.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Least squares fitting by Hermite spline. - -This subroutine is "lightweight" alternative for more complex and feature- -rich Spline1DFitHermiteWC(). See Spline1DFitHermiteWC() description for -more information about subroutine parameters (we don't duplicate it here -because of length). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spline1dfithermite(const real_1d_array &x, const real_1d_array &y, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (x.length()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dfithermite': looks like one of arguments has wrong size"); - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dfithermite(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, m, &info, const_cast(s.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Weighted linear least squares fitting. - -QR decomposition is used to reduce task to MxM, then triangular solver or -SVD-based solver is used depending on condition number of the system. It -allows to maximize speed and retain decent accuracy. - -IMPORTANT: if you want to perform polynomial fitting, it may be more - convenient to use PolynomialFit() function. This function gives - best results on polynomial problems and solves numerical - stability issues which arise when you fit high-degree - polynomials to your data. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Y - array[0..N-1] Function values in N points. - W - array[0..N-1] Weights corresponding to function values. - Each summand in square sum of approximation deviations - from given values is multiplied by the square of - corresponding weight. - FMatrix - a table of basis functions values, array[0..N-1, 0..M-1]. - FMatrix[I, J] - value of J-th basis function in I-th point. - N - number of points used. N>=1. - M - number of basis functions, M>=1. - -OUTPUT PARAMETERS: - Info - error code: - * -4 internal SVD decomposition subroutine failed (very - rare and for degenerate systems only) - * -1 incorrect N/M were specified - * 1 task is solved - C - decomposition coefficients, array[0..M-1] - Rep - fitting report. Following fields are set: - * Rep.TaskRCond reciprocal of condition number - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(F*CovPar*F')), - where F is functions matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitlinearw(const real_1d_array &y, const real_1d_array &w, const real_2d_array &fmatrix, const ae_int_t n, const ae_int_t m, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitlinearw(const_cast(y.c_ptr()), const_cast(w.c_ptr()), const_cast(fmatrix.c_ptr()), n, m, &info, const_cast(c.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Weighted linear least squares fitting. - -QR decomposition is used to reduce task to MxM, then triangular solver or -SVD-based solver is used depending on condition number of the system. It -allows to maximize speed and retain decent accuracy. - -IMPORTANT: if you want to perform polynomial fitting, it may be more - convenient to use PolynomialFit() function. This function gives - best results on polynomial problems and solves numerical - stability issues which arise when you fit high-degree - polynomials to your data. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Y - array[0..N-1] Function values in N points. - W - array[0..N-1] Weights corresponding to function values. - Each summand in square sum of approximation deviations - from given values is multiplied by the square of - corresponding weight. - FMatrix - a table of basis functions values, array[0..N-1, 0..M-1]. - FMatrix[I, J] - value of J-th basis function in I-th point. - N - number of points used. N>=1. - M - number of basis functions, M>=1. - -OUTPUT PARAMETERS: - Info - error code: - * -4 internal SVD decomposition subroutine failed (very - rare and for degenerate systems only) - * -1 incorrect N/M were specified - * 1 task is solved - C - decomposition coefficients, array[0..M-1] - Rep - fitting report. Following fields are set: - * Rep.TaskRCond reciprocal of condition number - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(F*CovPar*F')), - where F is functions matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void lsfitlinearw(const real_1d_array &y, const real_1d_array &w, const real_2d_array &fmatrix, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t m; - if( (y.length()!=w.length()) || (y.length()!=fmatrix.rows())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitlinearw': looks like one of arguments has wrong size"); - n = y.length(); - m = fmatrix.cols(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitlinearw(const_cast(y.c_ptr()), const_cast(w.c_ptr()), const_cast(fmatrix.c_ptr()), n, m, &info, const_cast(c.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Weighted constained linear least squares fitting. - -This is variation of LSFitLinearW(), which searchs for min|A*x=b| given -that K additional constaints C*x=bc are satisfied. It reduces original -task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinearW() -is called. - -IMPORTANT: if you want to perform polynomial fitting, it may be more - convenient to use PolynomialFit() function. This function gives - best results on polynomial problems and solves numerical - stability issues which arise when you fit high-degree - polynomials to your data. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Y - array[0..N-1] Function values in N points. - W - array[0..N-1] Weights corresponding to function values. - Each summand in square sum of approximation deviations - from given values is multiplied by the square of - corresponding weight. - FMatrix - a table of basis functions values, array[0..N-1, 0..M-1]. - FMatrix[I,J] - value of J-th basis function in I-th point. - CMatrix - a table of constaints, array[0..K-1,0..M]. - I-th row of CMatrix corresponds to I-th linear constraint: - CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M] - N - number of points used. N>=1. - M - number of basis functions, M>=1. - K - number of constraints, 0 <= K < M - K=0 corresponds to absence of constraints. - -OUTPUT PARAMETERS: - Info - error code: - * -4 internal SVD decomposition subroutine failed (very - rare and for degenerate systems only) - * -3 either too many constraints (M or more), - degenerate constraints (some constraints are - repetead twice) or inconsistent constraints were - specified. - * 1 task is solved - C - decomposition coefficients, array[0..M-1] - Rep - fitting report. Following fields are set: - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(F*CovPar*F')), - where F is functions matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -IMPORTANT: errors in parameters are calculated without taking into - account boundary/linear constraints! Presence of constraints - changes distribution of errors, but there is no easy way to - account for constraints when you calculate covariance matrix. - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 07.09.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitlinearwc(const real_1d_array &y, const real_1d_array &w, const real_2d_array &fmatrix, const real_2d_array &cmatrix, const ae_int_t n, const ae_int_t m, const ae_int_t k, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitlinearwc(const_cast(y.c_ptr()), const_cast(w.c_ptr()), const_cast(fmatrix.c_ptr()), const_cast(cmatrix.c_ptr()), n, m, k, &info, const_cast(c.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Weighted constained linear least squares fitting. - -This is variation of LSFitLinearW(), which searchs for min|A*x=b| given -that K additional constaints C*x=bc are satisfied. It reduces original -task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinearW() -is called. - -IMPORTANT: if you want to perform polynomial fitting, it may be more - convenient to use PolynomialFit() function. This function gives - best results on polynomial problems and solves numerical - stability issues which arise when you fit high-degree - polynomials to your data. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Y - array[0..N-1] Function values in N points. - W - array[0..N-1] Weights corresponding to function values. - Each summand in square sum of approximation deviations - from given values is multiplied by the square of - corresponding weight. - FMatrix - a table of basis functions values, array[0..N-1, 0..M-1]. - FMatrix[I,J] - value of J-th basis function in I-th point. - CMatrix - a table of constaints, array[0..K-1,0..M]. - I-th row of CMatrix corresponds to I-th linear constraint: - CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M] - N - number of points used. N>=1. - M - number of basis functions, M>=1. - K - number of constraints, 0 <= K < M - K=0 corresponds to absence of constraints. - -OUTPUT PARAMETERS: - Info - error code: - * -4 internal SVD decomposition subroutine failed (very - rare and for degenerate systems only) - * -3 either too many constraints (M or more), - degenerate constraints (some constraints are - repetead twice) or inconsistent constraints were - specified. - * 1 task is solved - C - decomposition coefficients, array[0..M-1] - Rep - fitting report. Following fields are set: - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(F*CovPar*F')), - where F is functions matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -IMPORTANT: errors in parameters are calculated without taking into - account boundary/linear constraints! Presence of constraints - changes distribution of errors, but there is no easy way to - account for constraints when you calculate covariance matrix. - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 07.09.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void lsfitlinearwc(const real_1d_array &y, const real_1d_array &w, const real_2d_array &fmatrix, const real_2d_array &cmatrix, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t m; - ae_int_t k; - if( (y.length()!=w.length()) || (y.length()!=fmatrix.rows())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitlinearwc': looks like one of arguments has wrong size"); - if( (fmatrix.cols()!=cmatrix.cols()-1)) - _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitlinearwc': looks like one of arguments has wrong size"); - n = y.length(); - m = fmatrix.cols(); - k = cmatrix.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitlinearwc(const_cast(y.c_ptr()), const_cast(w.c_ptr()), const_cast(fmatrix.c_ptr()), const_cast(cmatrix.c_ptr()), n, m, k, &info, const_cast(c.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Linear least squares fitting. - -QR decomposition is used to reduce task to MxM, then triangular solver or -SVD-based solver is used depending on condition number of the system. It -allows to maximize speed and retain decent accuracy. - -IMPORTANT: if you want to perform polynomial fitting, it may be more - convenient to use PolynomialFit() function. This function gives - best results on polynomial problems and solves numerical - stability issues which arise when you fit high-degree - polynomials to your data. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Y - array[0..N-1] Function values in N points. - FMatrix - a table of basis functions values, array[0..N-1, 0..M-1]. - FMatrix[I, J] - value of J-th basis function in I-th point. - N - number of points used. N>=1. - M - number of basis functions, M>=1. - -OUTPUT PARAMETERS: - Info - error code: - * -4 internal SVD decomposition subroutine failed (very - rare and for degenerate systems only) - * 1 task is solved - C - decomposition coefficients, array[0..M-1] - Rep - fitting report. Following fields are set: - * Rep.TaskRCond reciprocal of condition number - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(F*CovPar*F')), - where F is functions matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitlinear(const real_1d_array &y, const real_2d_array &fmatrix, const ae_int_t n, const ae_int_t m, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitlinear(const_cast(y.c_ptr()), const_cast(fmatrix.c_ptr()), n, m, &info, const_cast(c.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Linear least squares fitting. - -QR decomposition is used to reduce task to MxM, then triangular solver or -SVD-based solver is used depending on condition number of the system. It -allows to maximize speed and retain decent accuracy. - -IMPORTANT: if you want to perform polynomial fitting, it may be more - convenient to use PolynomialFit() function. This function gives - best results on polynomial problems and solves numerical - stability issues which arise when you fit high-degree - polynomials to your data. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Y - array[0..N-1] Function values in N points. - FMatrix - a table of basis functions values, array[0..N-1, 0..M-1]. - FMatrix[I, J] - value of J-th basis function in I-th point. - N - number of points used. N>=1. - M - number of basis functions, M>=1. - -OUTPUT PARAMETERS: - Info - error code: - * -4 internal SVD decomposition subroutine failed (very - rare and for degenerate systems only) - * 1 task is solved - C - decomposition coefficients, array[0..M-1] - Rep - fitting report. Following fields are set: - * Rep.TaskRCond reciprocal of condition number - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(F*CovPar*F')), - where F is functions matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void lsfitlinear(const real_1d_array &y, const real_2d_array &fmatrix, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t m; - if( (y.length()!=fmatrix.rows())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitlinear': looks like one of arguments has wrong size"); - n = y.length(); - m = fmatrix.cols(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitlinear(const_cast(y.c_ptr()), const_cast(fmatrix.c_ptr()), n, m, &info, const_cast(c.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Constained linear least squares fitting. - -This is variation of LSFitLinear(), which searchs for min|A*x=b| given -that K additional constaints C*x=bc are satisfied. It reduces original -task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinear() -is called. - -IMPORTANT: if you want to perform polynomial fitting, it may be more - convenient to use PolynomialFit() function. This function gives - best results on polynomial problems and solves numerical - stability issues which arise when you fit high-degree - polynomials to your data. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Y - array[0..N-1] Function values in N points. - FMatrix - a table of basis functions values, array[0..N-1, 0..M-1]. - FMatrix[I,J] - value of J-th basis function in I-th point. - CMatrix - a table of constaints, array[0..K-1,0..M]. - I-th row of CMatrix corresponds to I-th linear constraint: - CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M] - N - number of points used. N>=1. - M - number of basis functions, M>=1. - K - number of constraints, 0 <= K < M - K=0 corresponds to absence of constraints. - -OUTPUT PARAMETERS: - Info - error code: - * -4 internal SVD decomposition subroutine failed (very - rare and for degenerate systems only) - * -3 either too many constraints (M or more), - degenerate constraints (some constraints are - repetead twice) or inconsistent constraints were - specified. - * 1 task is solved - C - decomposition coefficients, array[0..M-1] - Rep - fitting report. Following fields are set: - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(F*CovPar*F')), - where F is functions matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -IMPORTANT: errors in parameters are calculated without taking into - account boundary/linear constraints! Presence of constraints - changes distribution of errors, but there is no easy way to - account for constraints when you calculate covariance matrix. - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 07.09.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitlinearc(const real_1d_array &y, const real_2d_array &fmatrix, const real_2d_array &cmatrix, const ae_int_t n, const ae_int_t m, const ae_int_t k, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitlinearc(const_cast(y.c_ptr()), const_cast(fmatrix.c_ptr()), const_cast(cmatrix.c_ptr()), n, m, k, &info, const_cast(c.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Constained linear least squares fitting. - -This is variation of LSFitLinear(), which searchs for min|A*x=b| given -that K additional constaints C*x=bc are satisfied. It reduces original -task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinear() -is called. - -IMPORTANT: if you want to perform polynomial fitting, it may be more - convenient to use PolynomialFit() function. This function gives - best results on polynomial problems and solves numerical - stability issues which arise when you fit high-degree - polynomials to your data. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Y - array[0..N-1] Function values in N points. - FMatrix - a table of basis functions values, array[0..N-1, 0..M-1]. - FMatrix[I,J] - value of J-th basis function in I-th point. - CMatrix - a table of constaints, array[0..K-1,0..M]. - I-th row of CMatrix corresponds to I-th linear constraint: - CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M] - N - number of points used. N>=1. - M - number of basis functions, M>=1. - K - number of constraints, 0 <= K < M - K=0 corresponds to absence of constraints. - -OUTPUT PARAMETERS: - Info - error code: - * -4 internal SVD decomposition subroutine failed (very - rare and for degenerate systems only) - * -3 either too many constraints (M or more), - degenerate constraints (some constraints are - repetead twice) or inconsistent constraints were - specified. - * 1 task is solved - C - decomposition coefficients, array[0..M-1] - Rep - fitting report. Following fields are set: - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(F*CovPar*F')), - where F is functions matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -IMPORTANT: errors in parameters are calculated without taking into - account boundary/linear constraints! Presence of constraints - changes distribution of errors, but there is no easy way to - account for constraints when you calculate covariance matrix. - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 07.09.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void lsfitlinearc(const real_1d_array &y, const real_2d_array &fmatrix, const real_2d_array &cmatrix, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t m; - ae_int_t k; - if( (y.length()!=fmatrix.rows())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitlinearc': looks like one of arguments has wrong size"); - if( (fmatrix.cols()!=cmatrix.cols()-1)) - _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitlinearc': looks like one of arguments has wrong size"); - n = y.length(); - m = fmatrix.cols(); - k = cmatrix.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitlinearc(const_cast(y.c_ptr()), const_cast(fmatrix.c_ptr()), const_cast(cmatrix.c_ptr()), n, m, k, &info, const_cast(c.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Weighted nonlinear least squares fitting using function values only. - -Combination of numerical differentiation and secant updates is used to -obtain function Jacobian. - -Nonlinear task min(F(c)) is solved, where - - F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * w is an N-dimensional vector of weight coefficients, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses only f(c,x[i]). - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - W - weights, array[0..N-1] - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - DiffStep- numerical differentiation step; - should not be very small or large; - large = loss of accuracy - small = growth of round-off errors - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 18.10.2008 by Bochkanov Sergey -*************************************************************************/ -void lsfitcreatewf(const real_2d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &c, const ae_int_t n, const ae_int_t m, const ae_int_t k, const double diffstep, lsfitstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitcreatewf(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(w.c_ptr()), const_cast(c.c_ptr()), n, m, k, diffstep, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Weighted nonlinear least squares fitting using function values only. - -Combination of numerical differentiation and secant updates is used to -obtain function Jacobian. - -Nonlinear task min(F(c)) is solved, where - - F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * w is an N-dimensional vector of weight coefficients, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses only f(c,x[i]). - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - W - weights, array[0..N-1] - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - DiffStep- numerical differentiation step; - should not be very small or large; - large = loss of accuracy - small = growth of round-off errors - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 18.10.2008 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void lsfitcreatewf(const real_2d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &c, const double diffstep, lsfitstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t m; - ae_int_t k; - if( (x.rows()!=y.length()) || (x.rows()!=w.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitcreatewf': looks like one of arguments has wrong size"); - n = x.rows(); - m = x.cols(); - k = c.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitcreatewf(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(w.c_ptr()), const_cast(c.c_ptr()), n, m, k, diffstep, const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Nonlinear least squares fitting using function values only. - -Combination of numerical differentiation and secant updates is used to -obtain function Jacobian. - -Nonlinear task min(F(c)) is solved, where - - F(c) = (f(c,x[0])-y[0])^2 + ... + (f(c,x[n-1])-y[n-1])^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * w is an N-dimensional vector of weight coefficients, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses only f(c,x[i]). - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - DiffStep- numerical differentiation step; - should not be very small or large; - large = loss of accuracy - small = growth of round-off errors - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 18.10.2008 by Bochkanov Sergey -*************************************************************************/ -void lsfitcreatef(const real_2d_array &x, const real_1d_array &y, const real_1d_array &c, const ae_int_t n, const ae_int_t m, const ae_int_t k, const double diffstep, lsfitstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitcreatef(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(c.c_ptr()), n, m, k, diffstep, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Nonlinear least squares fitting using function values only. - -Combination of numerical differentiation and secant updates is used to -obtain function Jacobian. - -Nonlinear task min(F(c)) is solved, where - - F(c) = (f(c,x[0])-y[0])^2 + ... + (f(c,x[n-1])-y[n-1])^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * w is an N-dimensional vector of weight coefficients, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses only f(c,x[i]). - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - DiffStep- numerical differentiation step; - should not be very small or large; - large = loss of accuracy - small = growth of round-off errors - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 18.10.2008 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void lsfitcreatef(const real_2d_array &x, const real_1d_array &y, const real_1d_array &c, const double diffstep, lsfitstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t m; - ae_int_t k; - if( (x.rows()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitcreatef': looks like one of arguments has wrong size"); - n = x.rows(); - m = x.cols(); - k = c.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitcreatef(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(c.c_ptr()), n, m, k, diffstep, const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Weighted nonlinear least squares fitting using gradient only. - -Nonlinear task min(F(c)) is solved, where - - F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * w is an N-dimensional vector of weight coefficients, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses only f(c,x[i]) and its gradient. - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - W - weights, array[0..N-1] - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - CheapFG - boolean flag, which is: - * True if both function and gradient calculation complexity - are less than O(M^2). An improved algorithm can - be used which corresponds to FGJ scheme from - MINLM unit. - * False otherwise. - Standard Jacibian-bases Levenberg-Marquardt algo - will be used (FJ scheme). - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -See also: - LSFitResults - LSFitCreateFG (fitting without weights) - LSFitCreateWFGH (fitting using Hessian) - LSFitCreateFGH (fitting using Hessian, without weights) - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitcreatewfg(const real_2d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &c, const ae_int_t n, const ae_int_t m, const ae_int_t k, const bool cheapfg, lsfitstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitcreatewfg(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(w.c_ptr()), const_cast(c.c_ptr()), n, m, k, cheapfg, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Weighted nonlinear least squares fitting using gradient only. - -Nonlinear task min(F(c)) is solved, where - - F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * w is an N-dimensional vector of weight coefficients, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses only f(c,x[i]) and its gradient. - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - W - weights, array[0..N-1] - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - CheapFG - boolean flag, which is: - * True if both function and gradient calculation complexity - are less than O(M^2). An improved algorithm can - be used which corresponds to FGJ scheme from - MINLM unit. - * False otherwise. - Standard Jacibian-bases Levenberg-Marquardt algo - will be used (FJ scheme). - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -See also: - LSFitResults - LSFitCreateFG (fitting without weights) - LSFitCreateWFGH (fitting using Hessian) - LSFitCreateFGH (fitting using Hessian, without weights) - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void lsfitcreatewfg(const real_2d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &c, const bool cheapfg, lsfitstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t m; - ae_int_t k; - if( (x.rows()!=y.length()) || (x.rows()!=w.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitcreatewfg': looks like one of arguments has wrong size"); - n = x.rows(); - m = x.cols(); - k = c.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitcreatewfg(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(w.c_ptr()), const_cast(c.c_ptr()), n, m, k, cheapfg, const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Nonlinear least squares fitting using gradient only, without individual -weights. - -Nonlinear task min(F(c)) is solved, where - - F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses only f(c,x[i]) and its gradient. - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - CheapFG - boolean flag, which is: - * True if both function and gradient calculation complexity - are less than O(M^2). An improved algorithm can - be used which corresponds to FGJ scheme from - MINLM unit. - * False otherwise. - Standard Jacibian-bases Levenberg-Marquardt algo - will be used (FJ scheme). - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitcreatefg(const real_2d_array &x, const real_1d_array &y, const real_1d_array &c, const ae_int_t n, const ae_int_t m, const ae_int_t k, const bool cheapfg, lsfitstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitcreatefg(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(c.c_ptr()), n, m, k, cheapfg, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Nonlinear least squares fitting using gradient only, without individual -weights. - -Nonlinear task min(F(c)) is solved, where - - F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses only f(c,x[i]) and its gradient. - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - CheapFG - boolean flag, which is: - * True if both function and gradient calculation complexity - are less than O(M^2). An improved algorithm can - be used which corresponds to FGJ scheme from - MINLM unit. - * False otherwise. - Standard Jacibian-bases Levenberg-Marquardt algo - will be used (FJ scheme). - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void lsfitcreatefg(const real_2d_array &x, const real_1d_array &y, const real_1d_array &c, const bool cheapfg, lsfitstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t m; - ae_int_t k; - if( (x.rows()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitcreatefg': looks like one of arguments has wrong size"); - n = x.rows(); - m = x.cols(); - k = c.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitcreatefg(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(c.c_ptr()), n, m, k, cheapfg, const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Weighted nonlinear least squares fitting using gradient/Hessian. - -Nonlinear task min(F(c)) is solved, where - - F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * w is an N-dimensional vector of weight coefficients, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses f(c,x[i]), its gradient and its Hessian. - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - W - weights, array[0..N-1] - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitcreatewfgh(const real_2d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &c, const ae_int_t n, const ae_int_t m, const ae_int_t k, lsfitstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitcreatewfgh(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(w.c_ptr()), const_cast(c.c_ptr()), n, m, k, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Weighted nonlinear least squares fitting using gradient/Hessian. - -Nonlinear task min(F(c)) is solved, where - - F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * w is an N-dimensional vector of weight coefficients, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses f(c,x[i]), its gradient and its Hessian. - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - W - weights, array[0..N-1] - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void lsfitcreatewfgh(const real_2d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &c, lsfitstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t m; - ae_int_t k; - if( (x.rows()!=y.length()) || (x.rows()!=w.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitcreatewfgh': looks like one of arguments has wrong size"); - n = x.rows(); - m = x.cols(); - k = c.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitcreatewfgh(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(w.c_ptr()), const_cast(c.c_ptr()), n, m, k, const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Nonlinear least squares fitting using gradient/Hessian, without individial -weights. - -Nonlinear task min(F(c)) is solved, where - - F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses f(c,x[i]), its gradient and its Hessian. - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitcreatefgh(const real_2d_array &x, const real_1d_array &y, const real_1d_array &c, const ae_int_t n, const ae_int_t m, const ae_int_t k, lsfitstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitcreatefgh(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(c.c_ptr()), n, m, k, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Nonlinear least squares fitting using gradient/Hessian, without individial -weights. - -Nonlinear task min(F(c)) is solved, where - - F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses f(c,x[i]), its gradient and its Hessian. - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void lsfitcreatefgh(const real_2d_array &x, const real_1d_array &y, const real_1d_array &c, lsfitstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t m; - ae_int_t k; - if( (x.rows()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitcreatefgh': looks like one of arguments has wrong size"); - n = x.rows(); - m = x.cols(); - k = c.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitcreatefgh(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(c.c_ptr()), n, m, k, const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Stopping conditions for nonlinear least squares fitting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - ste pvector, dx=X(k+1)-X(k) - * s - scaling coefficients set by LSFitSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. Only Levenberg-Marquardt - iterations are counted (L-BFGS/CG iterations are NOT - counted because their cost is very low compared to that of - LM). - -NOTE - -Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic -stopping criterion selection (according to the scheme used by MINLM unit). - - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetcond(const lsfitstate &state, const double epsx, const ae_int_t maxits, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitsetcond(const_cast(state.c_ptr()), epsx, maxits, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which leads to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - -NOTE: non-zero StpMax leads to moderate performance degradation because -intermediate step of preconditioned L-BFGS optimization is incompatible -with limits on step size. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetstpmax(const lsfitstate &state, const double stpmax, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitsetstpmax(const_cast(state.c_ptr()), stpmax, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -When reports are needed, State.C (current parameters) and State.F (current -value of fitting function) are reported. - - - -- ALGLIB -- - Copyright 15.08.2010 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetxrep(const lsfitstate &state, const bool needxrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitsetxrep(const_cast(state.c_ptr()), needxrep, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets scaling coefficients for underlying optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Generally, scale is NOT considered to be a form of preconditioner. But LM -optimizer is unique in that it uses scaling matrix both in the stopping -condition tests and as Marquardt damping factor. - -Proper scaling is very important for the algorithm performance. It is less -important for the quality of results, but still has some influence (it is -easier to converge when variables are properly scaled, so premature -stopping is possible when very badly scalled variables are combined with -relaxed stopping conditions). - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetscale(const lsfitstate &state, const real_1d_array &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitsetscale(const_cast(state.c_ptr()), const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets boundary constraints for underlying optimizer - -Boundary constraints are inactive by default (after initial creation). -They are preserved until explicitly turned off with another SetBC() call. - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[K]. - If some (all) variables are unbounded, you may specify - very small number or -INF (latter is recommended because - it will allow solver to use better algorithm). - BndU - upper bounds, array[K]. - If some (all) variables are unbounded, you may specify - very large number or +INF (latter is recommended because - it will allow solver to use better algorithm). - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - -NOTE 2: unlike other constrained optimization algorithms, this solver has -following useful properties: -* bound constraints are always satisfied exactly -* function is evaluated only INSIDE area specified by bound constraints - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetbc(const lsfitstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitsetbc(const_cast(state.c_ptr()), const_cast(bndl.c_ptr()), const_cast(bndu.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets linear constraints for underlying optimizer - -Linear constraints are inactive by default (after initial creation). -They are preserved until explicitly turned off with another SetLC() call. - -INPUT PARAMETERS: - State - structure stores algorithm state - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -IMPORTANT: if you have linear constraints, it is strongly recommended to - set scale of variables with lsfitsetscale(). QP solver which is - used to calculate linearly constrained steps heavily relies on - good scaling of input problems. - -NOTE: linear (non-box) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations. - -NOTE: general linear constraints add significant overhead to solution - process. Although solver performs roughly same amount of iterations - (when compared with similar box-only constrained problem), each - iteration now involves solution of linearly constrained QP - subproblem, which requires ~3-5 times more Cholesky decompositions. - Thus, if you can reformulate your problem in such way this it has - only box constraints, it may be beneficial to do so. - - -- ALGLIB -- - Copyright 29.04.2017 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetlc(const lsfitstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitsetlc(const_cast(state.c_ptr()), const_cast(c.c_ptr()), const_cast(ct.c_ptr()), k, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets linear constraints for underlying optimizer - -Linear constraints are inactive by default (after initial creation). -They are preserved until explicitly turned off with another SetLC() call. - -INPUT PARAMETERS: - State - structure stores algorithm state - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -IMPORTANT: if you have linear constraints, it is strongly recommended to - set scale of variables with lsfitsetscale(). QP solver which is - used to calculate linearly constrained steps heavily relies on - good scaling of input problems. - -NOTE: linear (non-box) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations. - -NOTE: general linear constraints add significant overhead to solution - process. Although solver performs roughly same amount of iterations - (when compared with similar box-only constrained problem), each - iteration now involves solution of linearly constrained QP - subproblem, which requires ~3-5 times more Cholesky decompositions. - Thus, if you can reformulate your problem in such way this it has - only box constraints, it may be beneficial to do so. - - -- ALGLIB -- - Copyright 29.04.2017 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void lsfitsetlc(const lsfitstate &state, const real_2d_array &c, const integer_1d_array &ct, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t k; - if( (c.rows()!=ct.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitsetlc': looks like one of arguments has wrong size"); - k = c.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitsetlc(const_cast(state.c_ptr()), const_cast(c.c_ptr()), const_cast(ct.c_ptr()), k, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool lsfititeration(const lsfitstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::lsfititeration(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - - -void lsfitfit(lsfitstate &state, - void (*func)(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr), - void (*rep)(const real_1d_array &c, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'lsfitfit()' (func is NULL)", &_alglib_env_state); - while( alglib_impl::lsfititeration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needf ) - { - func(state.c, state.x, state.f, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.c, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'lsfitfit' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - -void lsfitfit(lsfitstate &state, - void (*func)(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr), - void (*grad)(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*rep)(const real_1d_array &c, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'lsfitfit()' (func is NULL)", &_alglib_env_state); - alglib_impl::ae_assert(grad!=NULL, "ALGLIB: error in 'lsfitfit()' (grad is NULL)", &_alglib_env_state); - while( alglib_impl::lsfititeration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needf ) - { - func(state.c, state.x, state.f, ptr); - continue; - } - if( state.needfg ) - { - grad(state.c, state.x, state.f, state.g, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.c, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'lsfitfit' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - -void lsfitfit(lsfitstate &state, - void (*func)(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr), - void (*grad)(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*hess)(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, real_2d_array &hess, void *ptr), - void (*rep)(const real_1d_array &c, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'lsfitfit()' (func is NULL)", &_alglib_env_state); - alglib_impl::ae_assert(grad!=NULL, "ALGLIB: error in 'lsfitfit()' (grad is NULL)", &_alglib_env_state); - alglib_impl::ae_assert(hess!=NULL, "ALGLIB: error in 'lsfitfit()' (hess is NULL)", &_alglib_env_state); - while( alglib_impl::lsfititeration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needf ) - { - func(state.c, state.x, state.f, ptr); - continue; - } - if( state.needfg ) - { - grad(state.c, state.x, state.f, state.g, ptr); - continue; - } - if( state.needfgh ) - { - hess(state.c, state.x, state.f, state.g, state.h, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.c, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'lsfitfit' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - - -/************************************************************************* -Nonlinear least squares fitting results. - -Called after return from LSFitFit(). - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - Info - completion code: - * -8 optimizer detected NAN/INF in the target - function and/or gradient - * -7 gradient verification failed. - See LSFitSetGradientCheck() for more information. - * -3 inconsistent constraints - * 2 relative step is no more than EpsX. - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible - C - array[0..K-1], solution - Rep - optimization report. On success following fields are set: - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - * WRMSError weighted rms error on the (X,Y). - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(J*CovPar*J')), - where J is Jacobian matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -IMPORTANT: errors in parameters are calculated without taking into - account boundary/linear constraints! Presence of constraints - changes distribution of errors, but there is no easy way to - account for constraints when you calculate covariance matrix. - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitresults(const lsfitstate &state, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitresults(const_cast(state.c_ptr()), &info, const_cast(c.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine turns on verification of the user-supplied analytic -gradient: -* user calls this subroutine before fitting begins -* LSFitFit() is called -* prior to actual fitting, for each point in data set X_i and each - component of parameters being fited C_j algorithm performs following - steps: - * two trial steps are made to C_j-TestStep*S[j] and C_j+TestStep*S[j], - where C_j is j-th parameter and S[j] is a scale of j-th parameter - * if needed, steps are bounded with respect to constraints on C[] - * F(X_i|C) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - * in case difference between prediction and actual value is higher than - some predetermined threshold, algorithm stops with completion code -7; - Rep.VarIdx is set to index of the parameter with incorrect derivative. -* after verification is over, algorithm proceeds to the actual optimization. - -NOTE 1: verification needs N*K (points count * parameters count) gradient - evaluations. It is very costly and you should use it only for low - dimensional problems, when you want to be sure that you've - correctly calculated analytic derivatives. You should not use it - in the production code (unless you want to check derivatives - provided by some third party). - -NOTE 2: you should carefully choose TestStep. Value which is too large - (so large that function behaviour is significantly non-cubic) will - lead to false alarms. You may use different step for different - parameters by means of setting scale with LSFitSetScale(). - -NOTE 3: this function may lead to false positives. In case it reports that - I-th derivative was calculated incorrectly, you may decrease test - step and try one more time - maybe your function changes too - sharply and your step is too large for such rapidly chanding - function. - -NOTE 4: this function works only for optimizers created with LSFitCreateWFG() - or LSFitCreateFG() constructors. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step: - * TestStep=0 turns verification off - * TestStep>0 activates verification - - -- ALGLIB -- - Copyright 15.06.2012 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetgradientcheck(const lsfitstate &state, const double teststep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lsfitsetgradientcheck(const_cast(state.c_ptr()), teststep, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_RBFV2) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPLINE2D) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -2-dimensional spline inteprolant -*************************************************************************/ -_spline2dinterpolant_owner::_spline2dinterpolant_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_spline2dinterpolant_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::spline2dinterpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline2dinterpolant), &_state); - memset(p_struct, 0, sizeof(alglib_impl::spline2dinterpolant)); - alglib_impl::_spline2dinterpolant_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_spline2dinterpolant_owner::_spline2dinterpolant_owner(const _spline2dinterpolant_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_spline2dinterpolant_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline2dinterpolant copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::spline2dinterpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline2dinterpolant), &_state); - memset(p_struct, 0, sizeof(alglib_impl::spline2dinterpolant)); - alglib_impl::_spline2dinterpolant_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_spline2dinterpolant_owner& _spline2dinterpolant_owner::operator=(const _spline2dinterpolant_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: spline2dinterpolant assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline2dinterpolant assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_spline2dinterpolant_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::spline2dinterpolant)); - alglib_impl::_spline2dinterpolant_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_spline2dinterpolant_owner::~_spline2dinterpolant_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_spline2dinterpolant_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::spline2dinterpolant* _spline2dinterpolant_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::spline2dinterpolant* _spline2dinterpolant_owner::c_ptr() const -{ - return const_cast(p_struct); -} -spline2dinterpolant::spline2dinterpolant() : _spline2dinterpolant_owner() -{ -} - -spline2dinterpolant::spline2dinterpolant(const spline2dinterpolant &rhs):_spline2dinterpolant_owner(rhs) -{ -} - -spline2dinterpolant& spline2dinterpolant::operator=(const spline2dinterpolant &rhs) -{ - if( this==&rhs ) - return *this; - _spline2dinterpolant_owner::operator=(rhs); - return *this; -} - -spline2dinterpolant::~spline2dinterpolant() -{ -} - - -/************************************************************************* -Nonlinear least squares solver used to fit 2D splines to data -*************************************************************************/ -_spline2dbuilder_owner::_spline2dbuilder_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_spline2dbuilder_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::spline2dbuilder*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline2dbuilder), &_state); - memset(p_struct, 0, sizeof(alglib_impl::spline2dbuilder)); - alglib_impl::_spline2dbuilder_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_spline2dbuilder_owner::_spline2dbuilder_owner(const _spline2dbuilder_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_spline2dbuilder_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline2dbuilder copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::spline2dbuilder*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline2dbuilder), &_state); - memset(p_struct, 0, sizeof(alglib_impl::spline2dbuilder)); - alglib_impl::_spline2dbuilder_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_spline2dbuilder_owner& _spline2dbuilder_owner::operator=(const _spline2dbuilder_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: spline2dbuilder assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline2dbuilder assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_spline2dbuilder_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::spline2dbuilder)); - alglib_impl::_spline2dbuilder_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_spline2dbuilder_owner::~_spline2dbuilder_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_spline2dbuilder_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::spline2dbuilder* _spline2dbuilder_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::spline2dbuilder* _spline2dbuilder_owner::c_ptr() const -{ - return const_cast(p_struct); -} -spline2dbuilder::spline2dbuilder() : _spline2dbuilder_owner() -{ -} - -spline2dbuilder::spline2dbuilder(const spline2dbuilder &rhs):_spline2dbuilder_owner(rhs) -{ -} - -spline2dbuilder& spline2dbuilder::operator=(const spline2dbuilder &rhs) -{ - if( this==&rhs ) - return *this; - _spline2dbuilder_owner::operator=(rhs); - return *this; -} - -spline2dbuilder::~spline2dbuilder() -{ -} - - -/************************************************************************* -Spline 2D fitting report: - rmserror RMS error - avgerror average error - maxerror maximum error - r2 coefficient of determination, R-squared, 1-RSS/TSS -*************************************************************************/ -_spline2dfitreport_owner::_spline2dfitreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_spline2dfitreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::spline2dfitreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline2dfitreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::spline2dfitreport)); - alglib_impl::_spline2dfitreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_spline2dfitreport_owner::_spline2dfitreport_owner(const _spline2dfitreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_spline2dfitreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline2dfitreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::spline2dfitreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline2dfitreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::spline2dfitreport)); - alglib_impl::_spline2dfitreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_spline2dfitreport_owner& _spline2dfitreport_owner::operator=(const _spline2dfitreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: spline2dfitreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline2dfitreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_spline2dfitreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::spline2dfitreport)); - alglib_impl::_spline2dfitreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_spline2dfitreport_owner::~_spline2dfitreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_spline2dfitreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::spline2dfitreport* _spline2dfitreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::spline2dfitreport* _spline2dfitreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -spline2dfitreport::spline2dfitreport() : _spline2dfitreport_owner() ,rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),maxerror(p_struct->maxerror),r2(p_struct->r2) -{ -} - -spline2dfitreport::spline2dfitreport(const spline2dfitreport &rhs):_spline2dfitreport_owner(rhs) ,rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),maxerror(p_struct->maxerror),r2(p_struct->r2) -{ -} - -spline2dfitreport& spline2dfitreport::operator=(const spline2dfitreport &rhs) -{ - if( this==&rhs ) - return *this; - _spline2dfitreport_owner::operator=(rhs); - return *this; -} - -spline2dfitreport::~spline2dfitreport() -{ -} - - -/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -void spline2dserialize(spline2dinterpolant &obj, std::string &s_out) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - alglib_impl::ae_int_t ssize; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_alloc_start(&serializer); - alglib_impl::spline2dalloc(&serializer, obj.c_ptr(), &state); - ssize = alglib_impl::ae_serializer_get_alloc_size(&serializer); - s_out.clear(); - s_out.reserve((size_t)(ssize+1)); - alglib_impl::ae_serializer_sstart_str(&serializer, &s_out); - alglib_impl::spline2dserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_assert( s_out.length()<=(size_t)ssize, "ALGLIB: serialization integrity error", &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} -/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -void spline2dunserialize(const std::string &s_in, spline2dinterpolant &obj) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_ustart_str(&serializer, &s_in); - alglib_impl::spline2dunserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} - - -/************************************************************************* -This function serializes data structure to C++ stream. - -Data stream generated by this function is same as string representation -generated by string version of serializer - alphanumeric characters, -dots, underscores, minus signs, which are grouped into words separated by -spaces and CR+LF. - -We recommend you to read comments on string version of serializer to find -out more about serialization of AlGLIB objects. -*************************************************************************/ -void spline2dserialize(spline2dinterpolant &obj, std::ostream &s_out) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_alloc_start(&serializer); - alglib_impl::spline2dalloc(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_get_alloc_size(&serializer); // not actually needed, but we have to ask - alglib_impl::ae_serializer_sstart_stream(&serializer, &s_out); - alglib_impl::spline2dserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} -/************************************************************************* -This function unserializes data structure from stream. -*************************************************************************/ -void spline2dunserialize(const std::istream &s_in, spline2dinterpolant &obj) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_ustart_stream(&serializer, &s_in); - alglib_impl::spline2dunserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} - -/************************************************************************* -This subroutine calculates the value of the bilinear or bicubic spline at -the given point X. - -Input parameters: - C - 2D spline object. - Built by spline2dbuildbilinearv or spline2dbuildbicubicv. - X, Y- point - -Result: - S(x,y) - - -- ALGLIB PROJECT -- - Copyright 05.07.2007 by Bochkanov Sergey -*************************************************************************/ -double spline2dcalc(const spline2dinterpolant &c, const double x, const double y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::spline2dcalc(const_cast(c.c_ptr()), x, y, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This subroutine calculates the value of the bilinear or bicubic spline at -the given point X and its derivatives. - -Input parameters: - C - spline interpolant. - X, Y- point - -Output parameters: - F - S(x,y) - FX - dS(x,y)/dX - FY - dS(x,y)/dY - FXY - d2S(x,y)/dXdY - - -- ALGLIB PROJECT -- - Copyright 05.07.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2ddiff(const spline2dinterpolant &c, const double x, const double y, double &f, double &fx, double &fy, double &fxy, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2ddiff(const_cast(c.c_ptr()), x, y, &f, &fx, &fy, &fxy, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine calculates bilinear or bicubic vector-valued spline at the -given point (X,Y). - -If you need just some specific component of vector-valued spline, you can -use spline2dcalcvi() function. - -INPUT PARAMETERS: - C - spline interpolant. - X, Y- point - F - output buffer, possibly preallocated array. In case array size - is large enough to store result, it is not reallocated. Array - which is too short will be reallocated - -OUTPUT PARAMETERS: - F - array[D] (or larger) which stores function values - - -- ALGLIB PROJECT -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dcalcvbuf(const spline2dinterpolant &c, const double x, const double y, real_1d_array &f, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dcalcvbuf(const_cast(c.c_ptr()), x, y, const_cast(f.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine calculates specific component of vector-valued bilinear or -bicubic spline at the given point (X,Y). - -INPUT PARAMETERS: - C - spline interpolant. - X, Y- point - I - component index, in [0,D). An exception is generated for out - of range values. - -RESULT: - value of I-th component - - -- ALGLIB PROJECT -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -double spline2dcalcvi(const spline2dinterpolant &c, const double x, const double y, const ae_int_t i, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::spline2dcalcvi(const_cast(c.c_ptr()), x, y, i, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This subroutine calculates bilinear or bicubic vector-valued spline at the -given point (X,Y). - -INPUT PARAMETERS: - C - spline interpolant. - X, Y- point - -OUTPUT PARAMETERS: - F - array[D] which stores function values. F is out-parameter and - it is reallocated after call to this function. In case you - want to reuse previously allocated F, you may use - Spline2DCalcVBuf(), which reallocates F only when it is too - small. - - -- ALGLIB PROJECT -- - Copyright 16.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline2dcalcv(const spline2dinterpolant &c, const double x, const double y, real_1d_array &f, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dcalcv(const_cast(c.c_ptr()), x, y, const_cast(f.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine calculates value of specific component of bilinear or -bicubic vector-valued spline and its derivatives. - -Input parameters: - C - spline interpolant. - X, Y- point - I - component index, in [0,D) - -Output parameters: - F - S(x,y) - FX - dS(x,y)/dX - FY - dS(x,y)/dY - FXY - d2S(x,y)/dXdY - - -- ALGLIB PROJECT -- - Copyright 05.07.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2ddiffvi(const spline2dinterpolant &c, const double x, const double y, const ae_int_t i, double &f, double &fx, double &fy, double &fxy, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2ddiffvi(const_cast(c.c_ptr()), x, y, i, &f, &fx, &fy, &fxy, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine performs linear transformation of the spline argument. - -Input parameters: - C - spline interpolant - AX, BX - transformation coefficients: x = A*t + B - AY, BY - transformation coefficients: y = A*u + B -Result: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 30.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2dlintransxy(const spline2dinterpolant &c, const double ax, const double bx, const double ay, const double by, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dlintransxy(const_cast(c.c_ptr()), ax, bx, ay, by, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine performs linear transformation of the spline. - -Input parameters: - C - spline interpolant. - A, B- transformation coefficients: S2(x,y) = A*S(x,y) + B - -Output parameters: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 30.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2dlintransf(const spline2dinterpolant &c, const double a, const double b, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dlintransf(const_cast(c.c_ptr()), a, b, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine makes the copy of the spline model. - -Input parameters: - C - spline interpolant - -Output parameters: - CC - spline copy - - -- ALGLIB PROJECT -- - Copyright 29.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2dcopy(const spline2dinterpolant &c, spline2dinterpolant &cc, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dcopy(const_cast(c.c_ptr()), const_cast(cc.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Bicubic spline resampling - -Input parameters: - A - function values at the old grid, - array[0..OldHeight-1, 0..OldWidth-1] - OldHeight - old grid height, OldHeight>1 - OldWidth - old grid width, OldWidth>1 - NewHeight - new grid height, NewHeight>1 - NewWidth - new grid width, NewWidth>1 - -Output parameters: - B - function values at the new grid, - array[0..NewHeight-1, 0..NewWidth-1] - - -- ALGLIB routine -- - 15 May, 2007 - Copyright by Bochkanov Sergey -*************************************************************************/ -void spline2dresamplebicubic(const real_2d_array &a, const ae_int_t oldheight, const ae_int_t oldwidth, real_2d_array &b, const ae_int_t newheight, const ae_int_t newwidth, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dresamplebicubic(const_cast(a.c_ptr()), oldheight, oldwidth, const_cast(b.c_ptr()), newheight, newwidth, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Bilinear spline resampling - -Input parameters: - A - function values at the old grid, - array[0..OldHeight-1, 0..OldWidth-1] - OldHeight - old grid height, OldHeight>1 - OldWidth - old grid width, OldWidth>1 - NewHeight - new grid height, NewHeight>1 - NewWidth - new grid width, NewWidth>1 - -Output parameters: - B - function values at the new grid, - array[0..NewHeight-1, 0..NewWidth-1] - - -- ALGLIB routine -- - 09.07.2007 - Copyright by Bochkanov Sergey -*************************************************************************/ -void spline2dresamplebilinear(const real_2d_array &a, const ae_int_t oldheight, const ae_int_t oldwidth, real_2d_array &b, const ae_int_t newheight, const ae_int_t newwidth, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dresamplebilinear(const_cast(a.c_ptr()), oldheight, oldwidth, const_cast(b.c_ptr()), newheight, newwidth, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine builds bilinear vector-valued spline. - -Input parameters: - X - spline abscissas, array[0..N-1] - Y - spline ordinates, array[0..M-1] - F - function values, array[0..M*N*D-1]: - * first D elements store D values at (X[0],Y[0]) - * next D elements store D values at (X[1],Y[0]) - * general form - D function values at (X[i],Y[j]) are stored - at F[D*(J*N+I)...D*(J*N+I)+D-1]. - M,N - grid size, M>=2, N>=2 - D - vector dimension, D>=1 - -Output parameters: - C - spline interpolant - - -- ALGLIB PROJECT -- - Copyright 16.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildbilinearv(const real_1d_array &x, const ae_int_t n, const real_1d_array &y, const ae_int_t m, const real_1d_array &f, const ae_int_t d, spline2dinterpolant &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dbuildbilinearv(const_cast(x.c_ptr()), n, const_cast(y.c_ptr()), m, const_cast(f.c_ptr()), d, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine builds bicubic vector-valued spline. - -Input parameters: - X - spline abscissas, array[0..N-1] - Y - spline ordinates, array[0..M-1] - F - function values, array[0..M*N*D-1]: - * first D elements store D values at (X[0],Y[0]) - * next D elements store D values at (X[1],Y[0]) - * general form - D function values at (X[i],Y[j]) are stored - at F[D*(J*N+I)...D*(J*N+I)+D-1]. - M,N - grid size, M>=2, N>=2 - D - vector dimension, D>=1 - -Output parameters: - C - spline interpolant - - -- ALGLIB PROJECT -- - Copyright 16.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildbicubicv(const real_1d_array &x, const ae_int_t n, const real_1d_array &y, const ae_int_t m, const real_1d_array &f, const ae_int_t d, spline2dinterpolant &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dbuildbicubicv(const_cast(x.c_ptr()), n, const_cast(y.c_ptr()), m, const_cast(f.c_ptr()), d, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine unpacks two-dimensional spline into the coefficients table - -Input parameters: - C - spline interpolant. - -Result: - M, N- grid size (x-axis and y-axis) - D - number of components - Tbl - coefficients table, unpacked format, - D - components: [0..(N-1)*(M-1)*D-1, 0..19]. - For T=0..D-1 (component index), I = 0...N-2 (x index), - J=0..M-2 (y index): - K := T + I*D + J*D*(N-1) - - K-th row stores decomposition for T-th component of the - vector-valued function - - Tbl[K,0] = X[i] - Tbl[K,1] = X[i+1] - Tbl[K,2] = Y[j] - Tbl[K,3] = Y[j+1] - Tbl[K,4] = C00 - Tbl[K,5] = C01 - Tbl[K,6] = C02 - Tbl[K,7] = C03 - Tbl[K,8] = C10 - Tbl[K,9] = C11 - ... - Tbl[K,19] = C33 - On each grid square spline is equals to: - S(x) = SUM(c[i,j]*(t^i)*(u^j), i=0..3, j=0..3) - t = x-x[j] - u = y-y[i] - - -- ALGLIB PROJECT -- - Copyright 16.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline2dunpackv(const spline2dinterpolant &c, ae_int_t &m, ae_int_t &n, ae_int_t &d, real_2d_array &tbl, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dunpackv(const_cast(c.c_ptr()), &m, &n, &d, const_cast(tbl.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine was deprecated in ALGLIB 3.6.0 - -We recommend you to switch to Spline2DBuildBilinearV(), which is more -flexible and accepts its arguments in more convenient order. - - -- ALGLIB PROJECT -- - Copyright 05.07.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildbilinear(const real_1d_array &x, const real_1d_array &y, const real_2d_array &f, const ae_int_t m, const ae_int_t n, spline2dinterpolant &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dbuildbilinear(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(f.c_ptr()), m, n, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine was deprecated in ALGLIB 3.6.0 - -We recommend you to switch to Spline2DBuildBicubicV(), which is more -flexible and accepts its arguments in more convenient order. - - -- ALGLIB PROJECT -- - Copyright 05.07.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildbicubic(const real_1d_array &x, const real_1d_array &y, const real_2d_array &f, const ae_int_t m, const ae_int_t n, spline2dinterpolant &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dbuildbicubic(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(f.c_ptr()), m, n, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine was deprecated in ALGLIB 3.6.0 - -We recommend you to switch to Spline2DUnpackV(), which is more flexible -and accepts its arguments in more convenient order. - - -- ALGLIB PROJECT -- - Copyright 29.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2dunpack(const spline2dinterpolant &c, ae_int_t &m, ae_int_t &n, real_2d_array &tbl, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dunpack(const_cast(c.c_ptr()), &m, &n, const_cast(tbl.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine creates least squares solver used to fit 2D splines to -irregularly sampled (scattered) data. - -Solver object is used to perform spline fits as follows: -* solver object is created with spline2dbuildercreate() function -* dataset is added with spline2dbuildersetpoints() function -* fit area is chosen: - * spline2dbuildersetarea() - for user-defined area - * spline2dbuildersetareaauto() - for automatically chosen area -* number of grid nodes is chosen with spline2dbuildersetgrid() -* prior term is chosen with one of the following functions: - * spline2dbuildersetlinterm() to set linear prior - * spline2dbuildersetconstterm() to set constant prior - * spline2dbuildersetzeroterm() to set zero prior - * spline2dbuildersetuserterm() to set user-defined constant prior -* solver algorithm is chosen with either: - * spline2dbuildersetalgoblocklls() - BlockLLS algorithm, medium-scale problems - * spline2dbuildersetalgofastddm() - FastDDM algorithm, large-scale problems -* finally, fitting itself is performed with spline2dfit() function. - -Most of the steps above can be omitted, solver is configured with good -defaults. The minimum is to call: -* spline2dbuildercreate() to create solver object -* spline2dbuildersetpoints() to specify dataset -* spline2dbuildersetgrid() to tell how many nodes you need -* spline2dfit() to perform fit - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - D - positive number, number of Y-components: D=1 for simple scalar - fit, D>1 for vector-valued spline fitting. - -OUTPUT PARAMETERS: - S - solver object - - -- ALGLIB PROJECT -- - Copyright 29.01.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildercreate(const ae_int_t d, spline2dbuilder &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dbuildercreate(d, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets constant prior term (model is a sum of bicubic spline -and global prior, which can be linear, constant, user-defined constant or -zero). - -Constant prior term is determined by least squares fitting. - -INPUT PARAMETERS: - S - spline builder - V - value for user-defined prior - - -- ALGLIB -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetuserterm(const spline2dbuilder &state, const double v, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dbuildersetuserterm(const_cast(state.c_ptr()), v, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets linear prior term (model is a sum of bicubic spline and -global prior, which can be linear, constant, user-defined constant or -zero). - -Linear prior term is determined by least squares fitting. - -INPUT PARAMETERS: - S - spline builder - - -- ALGLIB -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetlinterm(const spline2dbuilder &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dbuildersetlinterm(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets constant prior term (model is a sum of bicubic spline -and global prior, which can be linear, constant, user-defined constant or -zero). - -Constant prior term is determined by least squares fitting. - -INPUT PARAMETERS: - S - spline builder - - -- ALGLIB -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetconstterm(const spline2dbuilder &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dbuildersetconstterm(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets zero prior term (model is a sum of bicubic spline and -global prior, which can be linear, constant, user-defined constant or -zero). - -INPUT PARAMETERS: - S - spline builder - - -- ALGLIB -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetzeroterm(const spline2dbuilder &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dbuildersetzeroterm(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function adds dataset to the builder object. - -This function overrides results of the previous calls, i.e. multiple calls -of this function will result in only the last set being added. - -INPUT PARAMETERS: - S - spline 2D builder object - XY - points, array[N,2+D]. One row corresponds to one point - in the dataset. First 2 elements are coordinates, next - D elements are function values. Array may be larger than - specified, in this case only leading [N,NX+NY] elements - will be used. - N - number of points in the dataset - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetpoints(const spline2dbuilder &state, const real_2d_array &xy, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dbuildersetpoints(const_cast(state.c_ptr()), const_cast(xy.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets area where 2D spline interpolant is built. "Auto" means -that area extent is determined automatically from dataset extent. - -INPUT PARAMETERS: - S - spline 2D builder object - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetareaauto(const spline2dbuilder &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dbuildersetareaauto(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets area where 2D spline interpolant is built to -user-defined one: [XA,XB]*[YA,YB] - -INPUT PARAMETERS: - S - spline 2D builder object - XA,XB - spatial extent in the first (X) dimension, XA(state.c_ptr()), xa, xb, ya, yb, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets nodes count for 2D spline interpolant. Fitting is -performed on area defined with one of the "setarea" functions; this one -sets number of nodes placed upon the fitting area. - -INPUT PARAMETERS: - S - spline 2D builder object - KX - nodes count for the first (X) dimension; fitting interval - [XA,XB] is separated into KX-1 subintervals, with KX nodes - created at the boundaries. - KY - nodes count for the first (Y) dimension; fitting interval - [YA,YB] is separated into KY-1 subintervals, with KY nodes - created at the boundaries. - -NOTE: at least 4 nodes is created in each dimension, so KX and KY are - silently increased if needed. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetgrid(const spline2dbuilder &state, const ae_int_t kx, const ae_int_t ky, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dbuildersetgrid(const_cast(state.c_ptr()), kx, ky, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function allows you to choose least squares solver used to perform -fitting. This function sets solver algorithm to "FastDDM", which performs -fast parallel fitting by splitting problem into smaller chunks and merging -results together. - -This solver is optimized for large-scale problems, starting from 256x256 -grids, and up to 10000x10000 grids. Of course, it will work for smaller -grids too. - -More detailed description of the algorithm is given below: -* algorithm generates hierarchy of nested grids, ranging from ~16x16 - (topmost "layer" of the model) to ~KX*KY one (final layer). Upper layers - model global behavior of the function, lower layers are used to model - fine details. Moving from layer to layer doubles grid density. -* fitting is started from topmost layer, subsequent layers are fitted - using residuals from previous ones. -* user may choose to skip generation of upper layers and generate only a - few bottom ones, which will result in much better performance and - parallelization efficiency, at the cost of algorithm inability to "patch" - large holes in the dataset. -* every layer is regularized using progressively increasing regularization - coefficient; thus, increasing LambdaV penalizes fine details first, - leaving lower frequencies almost intact for a while. -* after fitting is done, all layers are merged together into one bicubic - spline - -IMPORTANT: regularization coefficient used by this solver is different - from the one used by BlockLLS. Latter utilizes nonlinearity - penalty, which is global in nature (large regularization - results in global linear trend being extracted); this solver - uses another, localized form of penalty, which is suitable for - parallel processing. - -Notes on memory and performance: -* memory requirements: most memory is consumed during modeling of the - higher layers; ~[512*NPoints] bytes is required for a model with full - hierarchy of grids being generated. However, if you skip a few topmost - layers, you will get nearly constant (wrt. points count and grid size) - memory consumption. -* serial running time: O(K*K)+O(NPoints) for a KxK grid -* parallelism potential: good. You may get nearly linear speed-up when - performing fitting with just a few layers. Adding more layers results in - model becoming more global, which somewhat reduces efficiency of the - parallel code. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - spline 2D builder object - NLayers - number of layers in the model: - * NLayers>=1 means that up to chosen number of bottom - layers is fitted - * NLayers=0 means that maximum number of layers is chosen - (according to current grid size) - * NLayers<=-1 means that up to |NLayers| topmost layers is - skipped - Recommendations: - * good "default" value is 2 layers - * you may need more layers, if your dataset is very - irregular and you want to "patch" large holes. For a - grid step H (equal to AreaWidth/GridSize) you may expect - that last layer reproduces variations at distance H (and - can patch holes that wide); that higher layers operate - at distances 2*H, 4*H, 8*H and so on. - * good value for "bullletproof" mode is NLayers=0, which - results in complete hierarchy of layers being generated. - LambdaV - regularization coefficient, chosen in such a way that it - penalizes bottom layers (fine details) first. - LambdaV>=0, zero value means that no penalty is applied. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetalgofastddm(const spline2dbuilder &state, const ae_int_t nlayers, const double lambdav, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dbuildersetalgofastddm(const_cast(state.c_ptr()), nlayers, lambdav, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function allows you to choose least squares solver used to perform -fitting. This function sets solver algorithm to "BlockLLS", which performs -least squares fitting with fast sparse direct solver, with optional -nonsmoothness penalty being applied. - -Nonlinearity penalty has the following form: - - [ ] - P() ~ Lambda* integral[ (d2S/dx2)^2 + 2*(d2S/dxdy)^2 + (d2S/dy2)^2 ]dxdy - [ ] - -here integral is calculated over entire grid, and "~" means "proportional" -because integral is normalized after calcilation. Extremely large values -of Lambda result in linear fit being performed. - -NOTE: this algorithm is the most robust and controllable one, but it is - limited by 512x512 grids and (say) up to 1.000.000 points. However, - ALGLIB has one more spline solver: FastDDM algorithm, which is - intended for really large-scale problems (in 10M-100M range). FastDDM - algorithm also has better parallelism properties. - -More information on BlockLLS solver: -* memory requirements: ~[32*K^3+256*NPoints] bytes for KxK grid with - NPoints-sized dataset -* serial running time: O(K^4+NPoints) -* parallelism potential: limited. You may get some sublinear gain when - working with large grids (K's in 256..512 range) - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - spline 2D builder object - LambdaNS- non-negative value: - * positive value means that some smoothing is applied - * zero value means that no smoothing is applied, and - corresponding entries of design matrix are numerically - zero and dropped from consideration. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetalgoblocklls(const spline2dbuilder &state, const double lambdans, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dbuildersetalgoblocklls(const_cast(state.c_ptr()), lambdans, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function allows you to choose least squares solver used to perform -fitting. This function sets solver algorithm to "NaiveLLS". - -IMPORTANT: NaiveLLS is NOT intended to be used in real life code! This - algorithm solves problem by generated dense (K^2)x(K^2+NPoints) - matrix and solves linear least squares problem with dense - solver. - - It is here just to test BlockLLS against reference solver - (and maybe for someone trying to compare well optimized solver - against straightforward approach to the LLS problem). - -More information on naive LLS solver: -* memory requirements: ~[8*K^4+256*NPoints] bytes for KxK grid. -* serial running time: O(K^6+NPoints) for KxK grid -* when compared with BlockLLS, NaiveLLS has ~K larger memory demand and - ~K^2 larger running time. - -INPUT PARAMETERS: - S - spline 2D builder object - LambdaNS- nonsmoothness penalty - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetalgonaivells(const spline2dbuilder &state, const double lambdans, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dbuildersetalgonaivells(const_cast(state.c_ptr()), lambdans, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function fits bicubic spline to current dataset, using current area/ -grid and current LLS solver. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - State - spline 2D builder object - -OUTPUT PARAMETERS: - S - 2D spline, fit result - Rep - fitting report, which provides some additional info about - errors, R2 coefficient and so on. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dfit(const spline2dbuilder &state, spline2dinterpolant &s, spline2dfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline2dfit(const_cast(state.c_ptr()), const_cast(s.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_RBFV1) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_RBF) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Buffer object which is used to perform nearest neighbor requests in the -multithreaded mode (multiple threads working with same KD-tree object). - -This object should be created with KDTreeCreateBuffer(). -*************************************************************************/ -_rbfcalcbuffer_owner::_rbfcalcbuffer_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_rbfcalcbuffer_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::rbfcalcbuffer*)alglib_impl::ae_malloc(sizeof(alglib_impl::rbfcalcbuffer), &_state); - memset(p_struct, 0, sizeof(alglib_impl::rbfcalcbuffer)); - alglib_impl::_rbfcalcbuffer_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_rbfcalcbuffer_owner::_rbfcalcbuffer_owner(const _rbfcalcbuffer_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_rbfcalcbuffer_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: rbfcalcbuffer copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::rbfcalcbuffer*)alglib_impl::ae_malloc(sizeof(alglib_impl::rbfcalcbuffer), &_state); - memset(p_struct, 0, sizeof(alglib_impl::rbfcalcbuffer)); - alglib_impl::_rbfcalcbuffer_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_rbfcalcbuffer_owner& _rbfcalcbuffer_owner::operator=(const _rbfcalcbuffer_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: rbfcalcbuffer assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: rbfcalcbuffer assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_rbfcalcbuffer_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::rbfcalcbuffer)); - alglib_impl::_rbfcalcbuffer_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_rbfcalcbuffer_owner::~_rbfcalcbuffer_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_rbfcalcbuffer_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::rbfcalcbuffer* _rbfcalcbuffer_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::rbfcalcbuffer* _rbfcalcbuffer_owner::c_ptr() const -{ - return const_cast(p_struct); -} -rbfcalcbuffer::rbfcalcbuffer() : _rbfcalcbuffer_owner() -{ -} - -rbfcalcbuffer::rbfcalcbuffer(const rbfcalcbuffer &rhs):_rbfcalcbuffer_owner(rhs) -{ -} - -rbfcalcbuffer& rbfcalcbuffer::operator=(const rbfcalcbuffer &rhs) -{ - if( this==&rhs ) - return *this; - _rbfcalcbuffer_owner::operator=(rhs); - return *this; -} - -rbfcalcbuffer::~rbfcalcbuffer() -{ -} - - -/************************************************************************* -RBF model. - -Never try to directly work with fields of this object - always use ALGLIB -functions to use this object. -*************************************************************************/ -_rbfmodel_owner::_rbfmodel_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_rbfmodel_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::rbfmodel*)alglib_impl::ae_malloc(sizeof(alglib_impl::rbfmodel), &_state); - memset(p_struct, 0, sizeof(alglib_impl::rbfmodel)); - alglib_impl::_rbfmodel_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_rbfmodel_owner::_rbfmodel_owner(const _rbfmodel_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_rbfmodel_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: rbfmodel copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::rbfmodel*)alglib_impl::ae_malloc(sizeof(alglib_impl::rbfmodel), &_state); - memset(p_struct, 0, sizeof(alglib_impl::rbfmodel)); - alglib_impl::_rbfmodel_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_rbfmodel_owner& _rbfmodel_owner::operator=(const _rbfmodel_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: rbfmodel assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: rbfmodel assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_rbfmodel_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::rbfmodel)); - alglib_impl::_rbfmodel_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_rbfmodel_owner::~_rbfmodel_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_rbfmodel_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::rbfmodel* _rbfmodel_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::rbfmodel* _rbfmodel_owner::c_ptr() const -{ - return const_cast(p_struct); -} -rbfmodel::rbfmodel() : _rbfmodel_owner() -{ -} - -rbfmodel::rbfmodel(const rbfmodel &rhs):_rbfmodel_owner(rhs) -{ -} - -rbfmodel& rbfmodel::operator=(const rbfmodel &rhs) -{ - if( this==&rhs ) - return *this; - _rbfmodel_owner::operator=(rhs); - return *this; -} - -rbfmodel::~rbfmodel() -{ -} - - -/************************************************************************* -RBF solution report: -* TerminationType - termination type, positive values - success, - non-positive - failure. - -Fields which are set by modern RBF solvers (hierarchical): -* RMSError - root-mean-square error; NAN for old solvers (ML, QNN) -* MaxError - maximum error; NAN for old solvers (ML, QNN) -*************************************************************************/ -_rbfreport_owner::_rbfreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_rbfreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::rbfreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::rbfreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::rbfreport)); - alglib_impl::_rbfreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_rbfreport_owner::_rbfreport_owner(const _rbfreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_rbfreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: rbfreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::rbfreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::rbfreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::rbfreport)); - alglib_impl::_rbfreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_rbfreport_owner& _rbfreport_owner::operator=(const _rbfreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: rbfreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: rbfreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_rbfreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::rbfreport)); - alglib_impl::_rbfreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_rbfreport_owner::~_rbfreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_rbfreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::rbfreport* _rbfreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::rbfreport* _rbfreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -rbfreport::rbfreport() : _rbfreport_owner() ,rmserror(p_struct->rmserror),maxerror(p_struct->maxerror),arows(p_struct->arows),acols(p_struct->acols),annz(p_struct->annz),iterationscount(p_struct->iterationscount),nmv(p_struct->nmv),terminationtype(p_struct->terminationtype) -{ -} - -rbfreport::rbfreport(const rbfreport &rhs):_rbfreport_owner(rhs) ,rmserror(p_struct->rmserror),maxerror(p_struct->maxerror),arows(p_struct->arows),acols(p_struct->acols),annz(p_struct->annz),iterationscount(p_struct->iterationscount),nmv(p_struct->nmv),terminationtype(p_struct->terminationtype) -{ -} - -rbfreport& rbfreport::operator=(const rbfreport &rhs) -{ - if( this==&rhs ) - return *this; - _rbfreport_owner::operator=(rhs); - return *this; -} - -rbfreport::~rbfreport() -{ -} - - -/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -void rbfserialize(rbfmodel &obj, std::string &s_out) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - alglib_impl::ae_int_t ssize; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_alloc_start(&serializer); - alglib_impl::rbfalloc(&serializer, obj.c_ptr(), &state); - ssize = alglib_impl::ae_serializer_get_alloc_size(&serializer); - s_out.clear(); - s_out.reserve((size_t)(ssize+1)); - alglib_impl::ae_serializer_sstart_str(&serializer, &s_out); - alglib_impl::rbfserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_assert( s_out.length()<=(size_t)ssize, "ALGLIB: serialization integrity error", &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} -/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -void rbfunserialize(const std::string &s_in, rbfmodel &obj) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_ustart_str(&serializer, &s_in); - alglib_impl::rbfunserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} - - -/************************************************************************* -This function serializes data structure to C++ stream. - -Data stream generated by this function is same as string representation -generated by string version of serializer - alphanumeric characters, -dots, underscores, minus signs, which are grouped into words separated by -spaces and CR+LF. - -We recommend you to read comments on string version of serializer to find -out more about serialization of AlGLIB objects. -*************************************************************************/ -void rbfserialize(rbfmodel &obj, std::ostream &s_out) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_alloc_start(&serializer); - alglib_impl::rbfalloc(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_get_alloc_size(&serializer); // not actually needed, but we have to ask - alglib_impl::ae_serializer_sstart_stream(&serializer, &s_out); - alglib_impl::rbfserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} -/************************************************************************* -This function unserializes data structure from stream. -*************************************************************************/ -void rbfunserialize(const std::istream &s_in, rbfmodel &obj) -{ - jmp_buf _break_jump; - alglib_impl::ae_state state; - alglib_impl::ae_serializer serializer; - - alglib_impl::ae_state_init(&state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&state, &_break_jump); - alglib_impl::ae_serializer_init(&serializer); - alglib_impl::ae_serializer_ustart_stream(&serializer, &s_in); - alglib_impl::rbfunserialize(&serializer, obj.c_ptr(), &state); - alglib_impl::ae_serializer_stop(&serializer, &state); - alglib_impl::ae_serializer_clear(&serializer); - alglib_impl::ae_state_clear(&state); -} - -/************************************************************************* -This function creates RBF model for a scalar (NY=1) or vector (NY>1) -function in a NX-dimensional space (NX>=1). - -Newly created model is empty. It can be used for interpolation right after -creation, but it just returns zeros. You have to add points to the model, -tune interpolation settings, and then call model construction function -rbfbuildmodel() which will update model according to your specification. - -USAGE: -1. User creates model with rbfcreate() -2. User adds dataset with rbfsetpoints() (points do NOT have to be on a - regular grid) or rbfsetpointsandscales(). -3. (OPTIONAL) User chooses polynomial term by calling: - * rbflinterm() to set linear term - * rbfconstterm() to set constant term - * rbfzeroterm() to set zero term - By default, linear term is used. -4. User tweaks algorithm properties with rbfsetalgohierarchical() method - (or chooses one of the legacy algorithms - QNN (rbfsetalgoqnn) or ML - (rbfsetalgomultilayer)). -5. User calls rbfbuildmodel() function which rebuilds model according to - the specification -6. User may call rbfcalc() to calculate model value at the specified point, - rbfgridcalc() to calculate model values at the points of the regular - grid. User may extract model coefficients with rbfunpack() call. - -IMPORTANT: we recommend you to use latest model construction algorithm - - hierarchical RBFs, which is activated by rbfsetalgohierarchical() - function. This algorithm is the fastest one, and most memory- - efficient. - However, it is incompatible with older versions of ALGLIB - (pre-3.11). So, if you serialize hierarchical model, you will - be unable to load it in pre-3.11 ALGLIB. Other model types (QNN - and RBF-ML) are still backward-compatible. - -INPUT PARAMETERS: - NX - dimension of the space, NX>=1 - NY - function dimension, NY>=1 - -OUTPUT PARAMETERS: - S - RBF model (initially equals to zero) - -NOTE 1: memory requirements. RBF models require amount of memory which is - proportional to the number of data points. Some additional memory - is allocated during model construction, but most of this memory is - freed after model coefficients are calculated. Amount of this - additional memory depends on model construction algorithm being - used. - -NOTE 2: prior to ALGLIB version 3.11, RBF models supported only NX=2 or - NX=3. Any attempt to create single-dimensional or more than - 3-dimensional RBF model resulted in exception. - - ALGLIB 3.11 supports any NX>0, but models created with NX!=2 and - NX!=3 are incompatible with (a) older versions of ALGLIB, (b) old - model construction algorithms (QNN or RBF-ML). - - So, if you create a model with NX=2 or NX=3, then, depending on - specific model construction algorithm being chosen, you will (QNN - and RBF-ML) or will not (HierarchicalRBF) get backward compatibility - with older versions of ALGLIB. You have a choice here. - - However, if you create a model with NX neither 2 nor 3, you have - no backward compatibility from the start, and you are forced to - use hierarchical RBFs and ALGLIB 3.11 or later. - - -- ALGLIB -- - Copyright 13.12.2011, 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfcreate(const ae_int_t nx, const ae_int_t ny, rbfmodel &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfcreate(nx, ny, const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function creates buffer structure which can be used to perform -parallel RBF model evaluations (with one RBF model instance being -used from multiple threads, as long as different threads use different -instances of buffer). - -This buffer object can be used with rbftscalcbuf() function (here "ts" -stands for "thread-safe", "buf" is a suffix which denotes function which -reuses previously allocated output space). - -How to use it: -* create RBF model structure with rbfcreate() -* load data, tune parameters -* call rbfbuildmodel() -* call rbfcreatecalcbuffer(), once per thread working with RBF model (you - should call this function only AFTER call to rbfbuildmodel(), see below - for more information) -* call rbftscalcbuf() from different threads, with each thread working - with its own copy of buffer object. - -INPUT PARAMETERS - S - RBF model - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: buffer object should be used only with RBF model object which - was used to initialize buffer. Any attempt to use buffer with - different object is dangerous - you may get memory violation - error because sizes of internal arrays do not fit to dimensions - of RBF structure. - -IMPORTANT: you should call this function only for model which was built - with rbfbuildmodel() function, after successful invocation of - rbfbuildmodel(). Sizes of some internal structures are - determined only after model is built, so buffer object created - before model construction stage will be useless (and any - attempt to use it will result in exception). - - -- ALGLIB -- - Copyright 02.04.2016 by Sergey Bochkanov -*************************************************************************/ -void rbfcreatecalcbuffer(const rbfmodel &s, rbfcalcbuffer &buf, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfcreatecalcbuffer(const_cast(s.c_ptr()), const_cast(buf.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function adds dataset. - -This function overrides results of the previous calls, i.e. multiple calls -of this function will result in only the last set being added. - -IMPORTANT: ALGLIB version 3.11 and later allows you to specify a set of - per-dimension scales. Interpolation radii are multiplied by the - scale vector. It may be useful if you have mixed spatio-temporal - data (say, a set of 3D slices recorded at different times). - You should call rbfsetpointsandscales() function to use this - feature. - -INPUT PARAMETERS: - S - RBF model, initialized by rbfcreate() call. - XY - points, array[N,NX+NY]. One row corresponds to one point - in the dataset. First NX elements are coordinates, next - NY elements are function values. Array may be larger than - specified, in this case only leading [N,NX+NY] elements - will be used. - N - number of points in the dataset - -After you've added dataset and (optionally) tuned algorithm settings you -should call rbfbuildmodel() in order to build a model for you. - -NOTE: dataset added by this function is not saved during model serialization. - MODEL ITSELF is serialized, but data used to build it are not. - - So, if you 1) add dataset to empty RBF model, 2) serialize and - unserialize it, then you will get an empty RBF model with no dataset - being attached. - - From the other side, if you call rbfbuildmodel() between (1) and (2), - then after (2) you will get your fully constructed RBF model - but - again with no dataset attached, so subsequent calls to rbfbuildmodel() - will produce empty model. - - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfsetpoints(const rbfmodel &s, const real_2d_array &xy, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfsetpoints(const_cast(s.c_ptr()), const_cast(xy.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function adds dataset. - -This function overrides results of the previous calls, i.e. multiple calls -of this function will result in only the last set being added. - -IMPORTANT: ALGLIB version 3.11 and later allows you to specify a set of - per-dimension scales. Interpolation radii are multiplied by the - scale vector. It may be useful if you have mixed spatio-temporal - data (say, a set of 3D slices recorded at different times). - You should call rbfsetpointsandscales() function to use this - feature. - -INPUT PARAMETERS: - S - RBF model, initialized by rbfcreate() call. - XY - points, array[N,NX+NY]. One row corresponds to one point - in the dataset. First NX elements are coordinates, next - NY elements are function values. Array may be larger than - specified, in this case only leading [N,NX+NY] elements - will be used. - N - number of points in the dataset - -After you've added dataset and (optionally) tuned algorithm settings you -should call rbfbuildmodel() in order to build a model for you. - -NOTE: dataset added by this function is not saved during model serialization. - MODEL ITSELF is serialized, but data used to build it are not. - - So, if you 1) add dataset to empty RBF model, 2) serialize and - unserialize it, then you will get an empty RBF model with no dataset - being attached. - - From the other side, if you call rbfbuildmodel() between (1) and (2), - then after (2) you will get your fully constructed RBF model - but - again with no dataset attached, so subsequent calls to rbfbuildmodel() - will produce empty model. - - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void rbfsetpoints(const rbfmodel &s, const real_2d_array &xy, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = xy.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfsetpoints(const_cast(s.c_ptr()), const_cast(xy.c_ptr()), n, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function adds dataset and a vector of per-dimension scales. - -It may be useful if you have mixed spatio-temporal data - say, a set of 3D -slices recorded at different times. Such data typically require different -RBF radii for spatial and temporal dimensions. ALGLIB solves this problem -by specifying single RBF radius, which is (optionally) multiplied by the -scale vector. - -This function overrides results of the previous calls, i.e. multiple calls -of this function will result in only the last set being added. - -IMPORTANT: only HierarchicalRBF algorithm can work with scaled points. So, - using this function results in RBF models which can be used in - ALGLIB 3.11 or later. Previous versions of the library will be - unable to unserialize models produced by HierarchicalRBF algo. - - Any attempt to use this function with RBF-ML or QNN algorithms - will result in -3 error code being returned (incorrect - algorithm). - -INPUT PARAMETERS: - R - RBF model, initialized by rbfcreate() call. - XY - points, array[N,NX+NY]. One row corresponds to one point - in the dataset. First NX elements are coordinates, next - NY elements are function values. Array may be larger than - specified, in this case only leading [N,NX+NY] elements - will be used. - N - number of points in the dataset - S - array[NX], scale vector, S[i]>0. - -After you've added dataset and (optionally) tuned algorithm settings you -should call rbfbuildmodel() in order to build a model for you. - -NOTE: dataset added by this function is not saved during model serialization. - MODEL ITSELF is serialized, but data used to build it are not. - - So, if you 1) add dataset to empty RBF model, 2) serialize and - unserialize it, then you will get an empty RBF model with no dataset - being attached. - - From the other side, if you call rbfbuildmodel() between (1) and (2), - then after (2) you will get your fully constructed RBF model - but - again with no dataset attached, so subsequent calls to rbfbuildmodel() - will produce empty model. - - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfsetpointsandscales(const rbfmodel &r, const real_2d_array &xy, const ae_int_t n, const real_1d_array &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfsetpointsandscales(const_cast(r.c_ptr()), const_cast(xy.c_ptr()), n, const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function adds dataset and a vector of per-dimension scales. - -It may be useful if you have mixed spatio-temporal data - say, a set of 3D -slices recorded at different times. Such data typically require different -RBF radii for spatial and temporal dimensions. ALGLIB solves this problem -by specifying single RBF radius, which is (optionally) multiplied by the -scale vector. - -This function overrides results of the previous calls, i.e. multiple calls -of this function will result in only the last set being added. - -IMPORTANT: only HierarchicalRBF algorithm can work with scaled points. So, - using this function results in RBF models which can be used in - ALGLIB 3.11 or later. Previous versions of the library will be - unable to unserialize models produced by HierarchicalRBF algo. - - Any attempt to use this function with RBF-ML or QNN algorithms - will result in -3 error code being returned (incorrect - algorithm). - -INPUT PARAMETERS: - R - RBF model, initialized by rbfcreate() call. - XY - points, array[N,NX+NY]. One row corresponds to one point - in the dataset. First NX elements are coordinates, next - NY elements are function values. Array may be larger than - specified, in this case only leading [N,NX+NY] elements - will be used. - N - number of points in the dataset - S - array[NX], scale vector, S[i]>0. - -After you've added dataset and (optionally) tuned algorithm settings you -should call rbfbuildmodel() in order to build a model for you. - -NOTE: dataset added by this function is not saved during model serialization. - MODEL ITSELF is serialized, but data used to build it are not. - - So, if you 1) add dataset to empty RBF model, 2) serialize and - unserialize it, then you will get an empty RBF model with no dataset - being attached. - - From the other side, if you call rbfbuildmodel() between (1) and (2), - then after (2) you will get your fully constructed RBF model - but - again with no dataset attached, so subsequent calls to rbfbuildmodel() - will produce empty model. - - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void rbfsetpointsandscales(const rbfmodel &r, const real_2d_array &xy, const real_1d_array &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = xy.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfsetpointsandscales(const_cast(r.c_ptr()), const_cast(xy.c_ptr()), n, const_cast(s.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -DEPRECATED:since version 3.11 ALGLIB includes new RBF model construction - algorithm, Hierarchical RBF. This algorithm is faster and - requires less memory than QNN and RBF-ML. It is especially good - for large-scale interpolation problems. So, we recommend you to - consider Hierarchical RBF as default option. - -========================================================================== - -This function sets RBF interpolation algorithm. ALGLIB supports several -RBF algorithms with different properties. - -This algorithm is called RBF-QNN and it is good for point sets with -following properties: -a) all points are distinct -b) all points are well separated. -c) points distribution is approximately uniform. There is no "contour - lines", clusters of points, or other small-scale structures. - -Algorithm description: -1) interpolation centers are allocated to data points -2) interpolation radii are calculated as distances to the nearest centers - times Q coefficient (where Q is a value from [0.75,1.50]). -3) after performing (2) radii are transformed in order to avoid situation - when single outlier has very large radius and influences many points - across all dataset. Transformation has following form: - new_r[i] = min(r[i],Z*median(r[])) - where r[i] is I-th radius, median() is a median radius across entire - dataset, Z is user-specified value which controls amount of deviation - from median radius. - -When (a) is violated, we will be unable to build RBF model. When (b) or -(c) are violated, model will be built, but interpolation quality will be -low. See http://www.alglib.net/interpolation/ for more information on this -subject. - -This algorithm is used by default. - -Additional Q parameter controls smoothness properties of the RBF basis: -* Q<0.75 will give perfectly conditioned basis, but terrible smoothness - properties (RBF interpolant will have sharp peaks around function values) -* Q around 1.0 gives good balance between smoothness and condition number -* Q>1.5 will lead to badly conditioned systems and slow convergence of the - underlying linear solver (although smoothness will be very good) -* Q>2.0 will effectively make optimizer useless because it won't converge - within reasonable amount of iterations. It is possible to set such large - Q, but it is advised not to do so. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - Q - Q parameter, Q>0, recommended value - 1.0 - Z - Z parameter, Z>0, recommended value - 5.0 - -NOTE: this function has some serialization-related subtleties. We - recommend you to study serialization examples from ALGLIB Reference - Manual if you want to perform serialization of your models. - - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfsetalgoqnn(const rbfmodel &s, const double q, const double z, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfsetalgoqnn(const_cast(s.c_ptr()), q, z, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -DEPRECATED:since version 3.11 ALGLIB includes new RBF model construction - algorithm, Hierarchical RBF. This algorithm is faster and - requires less memory than QNN and RBF-ML. It is especially good - for large-scale interpolation problems. So, we recommend you to - consider Hierarchical RBF as default option. - -========================================================================== - -This function sets RBF interpolation algorithm. ALGLIB supports several -RBF algorithms with different properties. - -This algorithm is called RBF-QNN and it is good for point sets with -following properties: -a) all points are distinct -b) all points are well separated. -c) points distribution is approximately uniform. There is no "contour - lines", clusters of points, or other small-scale structures. - -Algorithm description: -1) interpolation centers are allocated to data points -2) interpolation radii are calculated as distances to the nearest centers - times Q coefficient (where Q is a value from [0.75,1.50]). -3) after performing (2) radii are transformed in order to avoid situation - when single outlier has very large radius and influences many points - across all dataset. Transformation has following form: - new_r[i] = min(r[i],Z*median(r[])) - where r[i] is I-th radius, median() is a median radius across entire - dataset, Z is user-specified value which controls amount of deviation - from median radius. - -When (a) is violated, we will be unable to build RBF model. When (b) or -(c) are violated, model will be built, but interpolation quality will be -low. See http://www.alglib.net/interpolation/ for more information on this -subject. - -This algorithm is used by default. - -Additional Q parameter controls smoothness properties of the RBF basis: -* Q<0.75 will give perfectly conditioned basis, but terrible smoothness - properties (RBF interpolant will have sharp peaks around function values) -* Q around 1.0 gives good balance between smoothness and condition number -* Q>1.5 will lead to badly conditioned systems and slow convergence of the - underlying linear solver (although smoothness will be very good) -* Q>2.0 will effectively make optimizer useless because it won't converge - within reasonable amount of iterations. It is possible to set such large - Q, but it is advised not to do so. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - Q - Q parameter, Q>0, recommended value - 1.0 - Z - Z parameter, Z>0, recommended value - 5.0 - -NOTE: this function has some serialization-related subtleties. We - recommend you to study serialization examples from ALGLIB Reference - Manual if you want to perform serialization of your models. - - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void rbfsetalgoqnn(const rbfmodel &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - double q; - double z; - - q = 1.0; - z = 5.0; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfsetalgoqnn(const_cast(s.c_ptr()), q, z, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -DEPRECATED:since version 3.11 ALGLIB includes new RBF model construction - algorithm, Hierarchical RBF. This algorithm is faster and - requires less memory than QNN and RBF-ML. It is especially good - for large-scale interpolation problems. So, we recommend you to - consider Hierarchical RBF as default option. - -========================================================================== - -This function sets RBF interpolation algorithm. ALGLIB supports several -RBF algorithms with different properties. - -This algorithm is called RBF-ML. It builds multilayer RBF model, i.e. -model with subsequently decreasing radii, which allows us to combine -smoothness (due to large radii of the first layers) with exactness (due -to small radii of the last layers) and fast convergence. - -Internally RBF-ML uses many different means of acceleration, from sparse -matrices to KD-trees, which results in algorithm whose working time is -roughly proportional to N*log(N)*Density*RBase^2*NLayers, where N is a -number of points, Density is an average density if points per unit of the -interpolation space, RBase is an initial radius, NLayers is a number of -layers. - -RBF-ML is good for following kinds of interpolation problems: -1. "exact" problems (perfect fit) with well separated points -2. least squares problems with arbitrary distribution of points (algorithm - gives perfect fit where it is possible, and resorts to least squares - fit in the hard areas). -3. noisy problems where we want to apply some controlled amount of - smoothing. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - RBase - RBase parameter, RBase>0 - NLayers - NLayers parameter, NLayers>0, recommended value to start - with - about 5. - LambdaV - regularization value, can be useful when solving problem - in the least squares sense. Optimal lambda is problem- - dependent and require trial and error. In our experience, - good lambda can be as large as 0.1, and you can use 0.001 - as initial guess. - Default value - 0.01, which is used when LambdaV is not - given. You can specify zero value, but it is not - recommended to do so. - -TUNING ALGORITHM - -In order to use this algorithm you have to choose three parameters: -* initial radius RBase -* number of layers in the model NLayers -* regularization coefficient LambdaV - -Initial radius is easy to choose - you can pick any number several times -larger than the average distance between points. Algorithm won't break -down if you choose radius which is too large (model construction time will -increase, but model will be built correctly). - -Choose such number of layers that RLast=RBase/2^(NLayers-1) (radius used -by the last layer) will be smaller than the typical distance between -points. In case model error is too large, you can increase number of -layers. Having more layers will make model construction and evaluation -proportionally slower, but it will allow you to have model which precisely -fits your data. From the other side, if you want to suppress noise, you -can DECREASE number of layers to make your model less flexible. - -Regularization coefficient LambdaV controls smoothness of the individual -models built for each layer. We recommend you to use default value in case -you don't want to tune this parameter, because having non-zero LambdaV -accelerates and stabilizes internal iterative algorithm. In case you want -to suppress noise you can use LambdaV as additional parameter (larger -value = more smoothness) to tune. - -TYPICAL ERRORS - -1. Using initial radius which is too large. Memory requirements of the - RBF-ML are roughly proportional to N*Density*RBase^2 (where Density is - an average density of points per unit of the interpolation space). In - the extreme case of the very large RBase we will need O(N^2) units of - memory - and many layers in order to decrease radius to some reasonably - small value. - -2. Using too small number of layers - RBF models with large radius are not - flexible enough to reproduce small variations in the target function. - You need many layers with different radii, from large to small, in - order to have good model. - -3. Using initial radius which is too small. You will get model with - "holes" in the areas which are too far away from interpolation centers. - However, algorithm will work correctly (and quickly) in this case. - -4. Using too many layers - you will get too large and too slow model. This - model will perfectly reproduce your function, but maybe you will be - able to achieve similar results with less layers (and less memory). - - -- ALGLIB -- - Copyright 02.03.2012 by Bochkanov Sergey -*************************************************************************/ -void rbfsetalgomultilayer(const rbfmodel &s, const double rbase, const ae_int_t nlayers, const double lambdav, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfsetalgomultilayer(const_cast(s.c_ptr()), rbase, nlayers, lambdav, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -DEPRECATED:since version 3.11 ALGLIB includes new RBF model construction - algorithm, Hierarchical RBF. This algorithm is faster and - requires less memory than QNN and RBF-ML. It is especially good - for large-scale interpolation problems. So, we recommend you to - consider Hierarchical RBF as default option. - -========================================================================== - -This function sets RBF interpolation algorithm. ALGLIB supports several -RBF algorithms with different properties. - -This algorithm is called RBF-ML. It builds multilayer RBF model, i.e. -model with subsequently decreasing radii, which allows us to combine -smoothness (due to large radii of the first layers) with exactness (due -to small radii of the last layers) and fast convergence. - -Internally RBF-ML uses many different means of acceleration, from sparse -matrices to KD-trees, which results in algorithm whose working time is -roughly proportional to N*log(N)*Density*RBase^2*NLayers, where N is a -number of points, Density is an average density if points per unit of the -interpolation space, RBase is an initial radius, NLayers is a number of -layers. - -RBF-ML is good for following kinds of interpolation problems: -1. "exact" problems (perfect fit) with well separated points -2. least squares problems with arbitrary distribution of points (algorithm - gives perfect fit where it is possible, and resorts to least squares - fit in the hard areas). -3. noisy problems where we want to apply some controlled amount of - smoothing. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - RBase - RBase parameter, RBase>0 - NLayers - NLayers parameter, NLayers>0, recommended value to start - with - about 5. - LambdaV - regularization value, can be useful when solving problem - in the least squares sense. Optimal lambda is problem- - dependent and require trial and error. In our experience, - good lambda can be as large as 0.1, and you can use 0.001 - as initial guess. - Default value - 0.01, which is used when LambdaV is not - given. You can specify zero value, but it is not - recommended to do so. - -TUNING ALGORITHM - -In order to use this algorithm you have to choose three parameters: -* initial radius RBase -* number of layers in the model NLayers -* regularization coefficient LambdaV - -Initial radius is easy to choose - you can pick any number several times -larger than the average distance between points. Algorithm won't break -down if you choose radius which is too large (model construction time will -increase, but model will be built correctly). - -Choose such number of layers that RLast=RBase/2^(NLayers-1) (radius used -by the last layer) will be smaller than the typical distance between -points. In case model error is too large, you can increase number of -layers. Having more layers will make model construction and evaluation -proportionally slower, but it will allow you to have model which precisely -fits your data. From the other side, if you want to suppress noise, you -can DECREASE number of layers to make your model less flexible. - -Regularization coefficient LambdaV controls smoothness of the individual -models built for each layer. We recommend you to use default value in case -you don't want to tune this parameter, because having non-zero LambdaV -accelerates and stabilizes internal iterative algorithm. In case you want -to suppress noise you can use LambdaV as additional parameter (larger -value = more smoothness) to tune. - -TYPICAL ERRORS - -1. Using initial radius which is too large. Memory requirements of the - RBF-ML are roughly proportional to N*Density*RBase^2 (where Density is - an average density of points per unit of the interpolation space). In - the extreme case of the very large RBase we will need O(N^2) units of - memory - and many layers in order to decrease radius to some reasonably - small value. - -2. Using too small number of layers - RBF models with large radius are not - flexible enough to reproduce small variations in the target function. - You need many layers with different radii, from large to small, in - order to have good model. - -3. Using initial radius which is too small. You will get model with - "holes" in the areas which are too far away from interpolation centers. - However, algorithm will work correctly (and quickly) in this case. - -4. Using too many layers - you will get too large and too slow model. This - model will perfectly reproduce your function, but maybe you will be - able to achieve similar results with less layers (and less memory). - - -- ALGLIB -- - Copyright 02.03.2012 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void rbfsetalgomultilayer(const rbfmodel &s, const double rbase, const ae_int_t nlayers, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - double lambdav; - - lambdav = 0.01; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfsetalgomultilayer(const_cast(s.c_ptr()), rbase, nlayers, lambdav, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets RBF interpolation algorithm. ALGLIB supports several -RBF algorithms with different properties. - -This algorithm is called Hierarchical RBF. It similar to its previous -incarnation, RBF-ML, i.e. it also builds a sequence of models with -decreasing radii. However, it uses more economical way of building upper -layers (ones with large radii), which results in faster model construction -and evaluation, as well as smaller memory footprint during construction. - -This algorithm has following important features: -* ability to handle millions of points -* controllable smoothing via nonlinearity penalization -* support for NX-dimensional models with NX=1 or NX>3 (unlike QNN or RBF-ML) -* support for specification of per-dimensional radii via scale vector, - which is set by means of rbfsetpointsandscales() function. This feature - is useful if you solve spatio-temporal interpolation problems, where - different radii are required for spatial and temporal dimensions. - -Running times are roughly proportional to: -* N*log(N)*NLayers - for model construction -* N*NLayers - for model evaluation -You may see that running time does not depend on search radius or points -density, just on number of layers in the hierarchy. - -IMPORTANT: this model construction algorithm was introduced in ALGLIB 3.11 - and produces models which are INCOMPATIBLE with previous - versions of ALGLIB. You can not unserialize models produced - with this function in ALGLIB 3.10 or earlier. - -INPUT PARAMETERS: - S - RBF model, initialized by rbfcreate() call - RBase - RBase parameter, RBase>0 - NLayers - NLayers parameter, NLayers>0, recommended value to start - with - about 5. - LambdaNS- >=0, nonlinearity penalty coefficient, negative values are - not allowed. This parameter adds controllable smoothing to - the problem, which may reduce noise. Specification of non- - zero lambda means that in addition to fitting error solver - will also minimize LambdaNS*|S''(x)|^2 (appropriately - generalized to multiple dimensions. - - Specification of exactly zero value means that no penalty - is added (we do not even evaluate matrix of second - derivatives which is necessary for smoothing). - - Calculation of nonlinearity penalty is costly - it results - in several-fold increase of model construction time. - Evaluation time remains the same. - - Optimal lambda is problem-dependent and requires trial - and error. Good value to start from is 1e-5...1e-6, - which corresponds to slightly noticeable smoothing of the - function. Value 1e-2 usually means that quite heavy - smoothing is applied. - -TUNING ALGORITHM - -In order to use this algorithm you have to choose three parameters: -* initial radius RBase -* number of layers in the model NLayers -* penalty coefficient LambdaNS - -Initial radius is easy to choose - you can pick any number several times -larger than the average distance between points. Algorithm won't break -down if you choose radius which is too large (model construction time will -increase, but model will be built correctly). - -Choose such number of layers that RLast=RBase/2^(NLayers-1) (radius used -by the last layer) will be smaller than the typical distance between -points. In case model error is too large, you can increase number of -layers. Having more layers will make model construction and evaluation -proportionally slower, but it will allow you to have model which precisely -fits your data. From the other side, if you want to suppress noise, you -can DECREASE number of layers to make your model less flexible (or specify -non-zero LambdaNS). - -TYPICAL ERRORS - -1. Using too small number of layers - RBF models with large radius are not - flexible enough to reproduce small variations in the target function. - You need many layers with different radii, from large to small, in - order to have good model. - -2. Using initial radius which is too small. You will get model with - "holes" in the areas which are too far away from interpolation centers. - However, algorithm will work correctly (and quickly) in this case. - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfsetalgohierarchical(const rbfmodel &s, const double rbase, const ae_int_t nlayers, const double lambdans, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfsetalgohierarchical(const_cast(s.c_ptr()), rbase, nlayers, lambdans, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets linear term (model is a sum of radial basis functions -plus linear polynomial). This function won't have effect until next call -to RBFBuildModel(). - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - -NOTE: this function has some serialization-related subtleties. We - recommend you to study serialization examples from ALGLIB Reference - Manual if you want to perform serialization of your models. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfsetlinterm(const rbfmodel &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfsetlinterm(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets constant term (model is a sum of radial basis functions -plus constant). This function won't have effect until next call to -RBFBuildModel(). - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - -NOTE: this function has some serialization-related subtleties. We - recommend you to study serialization examples from ALGLIB Reference - Manual if you want to perform serialization of your models. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfsetconstterm(const rbfmodel &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfsetconstterm(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets zero term (model is a sum of radial basis functions -without polynomial term). This function won't have effect until next call -to RBFBuildModel(). - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - -NOTE: this function has some serialization-related subtleties. We - recommend you to study serialization examples from ALGLIB Reference - Manual if you want to perform serialization of your models. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfsetzeroterm(const rbfmodel &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfsetzeroterm(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets basis function type, which can be: -* 0 for classic Gaussian -* 1 for fast and compact bell-like basis function, which becomes exactly - zero at distance equal to 3*R (default option). - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - BF - basis function type: - * 0 - classic Gaussian - * 1 - fast and compact one - - -- ALGLIB -- - Copyright 01.02.2017 by Bochkanov Sergey -*************************************************************************/ -void rbfsetv2bf(const rbfmodel &s, const ae_int_t bf, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfsetv2bf(const_cast(s.c_ptr()), bf, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets stopping criteria of the underlying linear solver for -hierarchical (version 2) RBF constructor. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - MaxIts - this criterion will stop algorithm after MaxIts iterations. - Typically a few hundreds iterations is required, with 400 - being a good default value to start experimentation. - Zero value means that default value will be selected. - - -- ALGLIB -- - Copyright 01.02.2017 by Bochkanov Sergey -*************************************************************************/ -void rbfsetv2its(const rbfmodel &s, const ae_int_t maxits, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfsetv2its(const_cast(s.c_ptr()), maxits, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets support radius parameter of hierarchical (version 2) -RBF constructor. - -Hierarchical RBF model achieves great speed-up by removing from the model -excessive (too dense) nodes. Say, if you have RBF radius equal to 1 meter, -and two nodes are just 1 millimeter apart, you may remove one of them -without reducing model quality. - -Support radius parameter is used to justify which points need removal, and -which do not. If two points are less than SUPPORT_R*CUR_RADIUS units of -distance apart, one of them is removed from the model. The larger support -radius is, the faster model construction AND evaluation are. However, -too large values result in "bumpy" models. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - R - support radius coefficient, >=0. - Recommended values are [0.1,0.4] range, with 0.1 being - default value. - - -- ALGLIB -- - Copyright 01.02.2017 by Bochkanov Sergey -*************************************************************************/ -void rbfsetv2supportr(const rbfmodel &s, const double r, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfsetv2supportr(const_cast(s.c_ptr()), r, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function builds RBF model and returns report (contains some -information which can be used for evaluation of the algorithm properties). - -Call to this function modifies RBF model by calculating its centers/radii/ -weights and saving them into RBFModel structure. Initially RBFModel -contain zero coefficients, but after call to this function we will have -coefficients which were calculated in order to fit our dataset. - -After you called this function you can call RBFCalc(), RBFGridCalc() and -other model calculation functions. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - Rep - report: - * Rep.TerminationType: - * -5 - non-distinct basis function centers were detected, - interpolation aborted; only QNN returns this - error code, other algorithms can handle non- - distinct nodes. - * -4 - nonconvergence of the internal SVD solver - * -3 incorrect model construction algorithm was chosen: - QNN or RBF-ML, combined with one of the incompatible - features - NX=1 or NX>3; points with per-dimension - scales. - * 1 - successful termination - * 8 - a termination request was submitted via - rbfrequesttermination() function. - - Fields which are set only by modern RBF solvers (hierarchical - or nonnegative; older solvers like QNN and ML initialize these - fields by NANs): - * rep.rmserror - root-mean-square error at nodes - * rep.maxerror - maximum error at nodes - - Fields are used for debugging purposes: - * Rep.IterationsCount - iterations count of the LSQR solver - * Rep.NMV - number of matrix-vector products - * Rep.ARows - rows count for the system matrix - * Rep.ACols - columns count for the system matrix - * Rep.ANNZ - number of significantly non-zero elements - (elements above some algorithm-determined threshold) - -NOTE: failure to build model will leave current state of the structure -unchanged. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfbuildmodel(const rbfmodel &s, rbfreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfbuildmodel(const_cast(s.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates values of the RBF model in the given point. - -IMPORTANT: this function works only with modern (hierarchical) RBFs. It - can not be used with legacy (version 1) RBFs because older RBF - code does not support 1-dimensional models. - -This function should be used when we have NY=1 (scalar function) and NX=1 -(1-dimensional space). If you have 3-dimensional space, use rbfcalc3(). If -you have 2-dimensional space, use rbfcalc3(). If you have general -situation (NX-dimensional space, NY-dimensional function) you should use -generic rbfcalc(). - -If you want to perform parallel model evaluation from multiple threads, -use rbftscalcbuf() with per-thread buffer object. - -This function returns 0.0 when: -* model is not initialized -* NX<>1 -* NY<>1 - -INPUT PARAMETERS: - S - RBF model - X0 - X-coordinate, finite number - -RESULT: - value of the model or 0.0 (as defined above) - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -double rbfcalc1(const rbfmodel &s, const double x0, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::rbfcalc1(const_cast(s.c_ptr()), x0, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function calculates values of the RBF model in the given point. - -This function should be used when we have NY=1 (scalar function) and NX=2 -(2-dimensional space). If you have 3-dimensional space, use rbfcalc3(). If -you have general situation (NX-dimensional space, NY-dimensional function) -you should use generic rbfcalc(). - -If you want to calculate function values many times, consider using -rbfgridcalc2v(), which is far more efficient than many subsequent calls to -rbfcalc2(). - -If you want to perform parallel model evaluation from multiple threads, -use rbftscalcbuf() with per-thread buffer object. - -This function returns 0.0 when: -* model is not initialized -* NX<>2 - *NY<>1 - -INPUT PARAMETERS: - S - RBF model - X0 - first coordinate, finite number - X1 - second coordinate, finite number - -RESULT: - value of the model or 0.0 (as defined above) - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -double rbfcalc2(const rbfmodel &s, const double x0, const double x1, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::rbfcalc2(const_cast(s.c_ptr()), x0, x1, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function calculates value of the RBF model in the given point. - -This function should be used when we have NY=1 (scalar function) and NX=3 -(3-dimensional space). If you have 2-dimensional space, use rbfcalc2(). If -you have general situation (NX-dimensional space, NY-dimensional function) -you should use generic rbfcalc(). - -If you want to calculate function values many times, consider using -rbfgridcalc3v(), which is far more efficient than many subsequent calls to -rbfcalc3(). - -If you want to perform parallel model evaluation from multiple threads, -use rbftscalcbuf() with per-thread buffer object. - -This function returns 0.0 when: -* model is not initialized -* NX<>3 - *NY<>1 - -INPUT PARAMETERS: - S - RBF model - X0 - first coordinate, finite number - X1 - second coordinate, finite number - X2 - third coordinate, finite number - -RESULT: - value of the model or 0.0 (as defined above) - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -double rbfcalc3(const rbfmodel &s, const double x0, const double x1, const double x2, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::rbfcalc3(const_cast(s.c_ptr()), x0, x1, x2, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function calculates values of the RBF model at the given point. - -This is general function which can be used for arbitrary NX (dimension of -the space of arguments) and NY (dimension of the function itself). However -when you have NY=1 you may find more convenient to use rbfcalc2() or -rbfcalc3(). - -If you want to perform parallel model evaluation from multiple threads, -use rbftscalcbuf() with per-thread buffer object. - -This function returns 0.0 when model is not initialized. - -INPUT PARAMETERS: - S - RBF model - X - coordinates, array[NX]. - X may have more than NX elements, in this case only - leading NX will be used. - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is out-parameter and - reallocated after call to this function. In case you want - to reuse previously allocated Y, you may use RBFCalcBuf(), - which reallocates Y only when it is too small. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfcalc(const rbfmodel &s, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfcalc(const_cast(s.c_ptr()), const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates values of the RBF model at the given point. - -Same as rbfcalc(), but does not reallocate Y when in is large enough to -store function values. - -If you want to perform parallel model evaluation from multiple threads, -use rbftscalcbuf() with per-thread buffer object. - -INPUT PARAMETERS: - S - RBF model - X - coordinates, array[NX]. - X may have more than NX elements, in this case only - leading NX will be used. - Y - possibly preallocated array - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is not reallocated when it - is larger than NY. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfcalcbuf(const rbfmodel &s, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfcalcbuf(const_cast(s.c_ptr()), const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates values of the RBF model at the given point, using -external buffer object (internal temporaries of RBF model are not -modified). - -This function allows to use same RBF model object in different threads, -assuming that different threads use different instances of buffer -structure. - -INPUT PARAMETERS: - S - RBF model, may be shared between different threads - Buf - buffer object created for this particular instance of RBF - model with rbfcreatecalcbuffer(). - X - coordinates, array[NX]. - X may have more than NX elements, in this case only - leading NX will be used. - Y - possibly preallocated array - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is not reallocated when it - is larger than NY. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbftscalcbuf(const rbfmodel &s, const rbfcalcbuffer &buf, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbftscalcbuf(const_cast(s.c_ptr()), const_cast(buf.c_ptr()), const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is legacy function for gridded calculation of RBF model. - -It is superseded by rbfgridcalc2v() and rbfgridcalc2vsubset() functions. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfgridcalc2(const rbfmodel &s, const real_1d_array &x0, const ae_int_t n0, const real_1d_array &x1, const ae_int_t n1, real_2d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfgridcalc2(const_cast(s.c_ptr()), const_cast(x0.c_ptr()), n0, const_cast(x1.c_ptr()), n1, const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates values of the RBF model at the regular grid, -which has N0*N1 points, with Point[I,J] = (X0[I], X1[J]). Vector-valued -RBF models are supported. - -This function returns 0.0 when: -* model is not initialized -* NX<>2 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: Parallel processing is implemented only for modern (hierarchical) - RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still - processed serially. - -INPUT PARAMETERS: - S - RBF model, used in read-only mode, can be shared between - multiple invocations of this function from multiple - threads. - - X0 - array of grid nodes, first coordinates, array[N0]. - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N0 - grid size (number of nodes) in the first dimension - - X1 - array of grid nodes, second coordinates, array[N1] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N1 - grid size (number of nodes) in the second dimension - -OUTPUT PARAMETERS: - Y - function values, array[NY*N0*N1], where NY is a number of - "output" vector values (this function supports vector- - valued RBF models). Y is out-variable and is reallocated - by this function. - Y[K+NY*(I0+I1*N0)]=F_k(X0[I0],X1[I1]), for: - * K=0...NY-1 - * I0=0...N0-1 - * I1=0...N1-1 - -NOTE: this function supports weakly ordered grid nodes, i.e. you may have - X[i]=X[i+1] for some i. It does not provide you any performance - benefits due to duplication of points, just convenience and - flexibility. - -NOTE: this function is re-entrant, i.e. you may use same rbfmodel - structure in multiple threads calling this function for different - grids. - -NOTE: if you need function values on some subset of regular grid, which - may be described as "several compact and dense islands", you may - use rbfgridcalc2vsubset(). - - -- ALGLIB -- - Copyright 27.01.2017 by Bochkanov Sergey -*************************************************************************/ -void rbfgridcalc2v(const rbfmodel &s, const real_1d_array &x0, const ae_int_t n0, const real_1d_array &x1, const ae_int_t n1, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfgridcalc2v(const_cast(s.c_ptr()), const_cast(x0.c_ptr()), n0, const_cast(x1.c_ptr()), n1, const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates values of the RBF model at some subset of regular -grid: -* grid has N0*N1 points, with Point[I,J] = (X0[I], X1[J]) -* only values at some subset of this grid are required -Vector-valued RBF models are supported. - -This function returns 0.0 when: -* model is not initialized -* NX<>2 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: Parallel processing is implemented only for modern (hierarchical) - RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still - processed serially. - -INPUT PARAMETERS: - S - RBF model, used in read-only mode, can be shared between - multiple invocations of this function from multiple - threads. - - X0 - array of grid nodes, first coordinates, array[N0]. - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N0 - grid size (number of nodes) in the first dimension - - X1 - array of grid nodes, second coordinates, array[N1] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N1 - grid size (number of nodes) in the second dimension - - FlagY - array[N0*N1]: - * Y[I0+I1*N0] corresponds to node (X0[I0],X1[I1]) - * it is a "bitmap" array which contains False for nodes - which are NOT calculated, and True for nodes which are - required. - -OUTPUT PARAMETERS: - Y - function values, array[NY*N0*N1*N2], where NY is a number - of "output" vector values (this function supports vector- - valued RBF models): - * Y[K+NY*(I0+I1*N0)]=F_k(X0[I0],X1[I1]), - for K=0...NY-1, I0=0...N0-1, I1=0...N1-1. - * elements of Y[] which correspond to FlagY[]=True are - loaded by model values (which may be exactly zero for - some nodes). - * elements of Y[] which correspond to FlagY[]=False MAY be - initialized by zeros OR may be calculated. This function - processes grid as a hierarchy of nested blocks and - micro-rows. If just one element of micro-row is required, - entire micro-row (up to 8 nodes in the current version, - but no promises) is calculated. - -NOTE: this function supports weakly ordered grid nodes, i.e. you may have - X[i]=X[i+1] for some i. It does not provide you any performance - benefits due to duplication of points, just convenience and - flexibility. - -NOTE: this function is re-entrant, i.e. you may use same rbfmodel - structure in multiple threads calling this function for different - grids. - - -- ALGLIB -- - Copyright 04.03.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfgridcalc2vsubset(const rbfmodel &s, const real_1d_array &x0, const ae_int_t n0, const real_1d_array &x1, const ae_int_t n1, const boolean_1d_array &flagy, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfgridcalc2vsubset(const_cast(s.c_ptr()), const_cast(x0.c_ptr()), n0, const_cast(x1.c_ptr()), n1, const_cast(flagy.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates values of the RBF model at the regular grid, -which has N0*N1*N2 points, with Point[I,J,K] = (X0[I], X1[J], X2[K]). -Vector-valued RBF models are supported. - -This function returns 0.0 when: -* model is not initialized -* NX<>3 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: Parallel processing is implemented only for modern (hierarchical) - RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still - processed serially. - -INPUT PARAMETERS: - S - RBF model, used in read-only mode, can be shared between - multiple invocations of this function from multiple - threads. - - X0 - array of grid nodes, first coordinates, array[N0]. - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N0 - grid size (number of nodes) in the first dimension - - X1 - array of grid nodes, second coordinates, array[N1] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N1 - grid size (number of nodes) in the second dimension - - X2 - array of grid nodes, third coordinates, array[N2] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N2 - grid size (number of nodes) in the third dimension - -OUTPUT PARAMETERS: - Y - function values, array[NY*N0*N1*N2], where NY is a number - of "output" vector values (this function supports vector- - valued RBF models). Y is out-variable and is reallocated - by this function. - Y[K+NY*(I0+I1*N0+I2*N0*N1)]=F_k(X0[I0],X1[I1],X2[I2]), for: - * K=0...NY-1 - * I0=0...N0-1 - * I1=0...N1-1 - * I2=0...N2-1 - -NOTE: this function supports weakly ordered grid nodes, i.e. you may have - X[i]=X[i+1] for some i. It does not provide you any performance - benefits due to duplication of points, just convenience and - flexibility. - -NOTE: this function is re-entrant, i.e. you may use same rbfmodel - structure in multiple threads calling this function for different - grids. - -NOTE: if you need function values on some subset of regular grid, which - may be described as "several compact and dense islands", you may - use rbfgridcalc3vsubset(). - - -- ALGLIB -- - Copyright 04.03.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfgridcalc3v(const rbfmodel &s, const real_1d_array &x0, const ae_int_t n0, const real_1d_array &x1, const ae_int_t n1, const real_1d_array &x2, const ae_int_t n2, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfgridcalc3v(const_cast(s.c_ptr()), const_cast(x0.c_ptr()), n0, const_cast(x1.c_ptr()), n1, const_cast(x2.c_ptr()), n2, const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates values of the RBF model at some subset of regular -grid: -* grid has N0*N1*N2 points, with Point[I,J,K] = (X0[I], X1[J], X2[K]) -* only values at some subset of this grid are required -Vector-valued RBF models are supported. - -This function returns 0.0 when: -* model is not initialized -* NX<>3 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: Parallel processing is implemented only for modern (hierarchical) - RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still - processed serially. - -INPUT PARAMETERS: - S - RBF model, used in read-only mode, can be shared between - multiple invocations of this function from multiple - threads. - - X0 - array of grid nodes, first coordinates, array[N0]. - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N0 - grid size (number of nodes) in the first dimension - - X1 - array of grid nodes, second coordinates, array[N1] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N1 - grid size (number of nodes) in the second dimension - - X2 - array of grid nodes, third coordinates, array[N2] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N2 - grid size (number of nodes) in the third dimension - - FlagY - array[N0*N1*N2]: - * Y[I0+I1*N0+I2*N0*N1] corresponds to node (X0[I0],X1[I1],X2[I2]) - * it is a "bitmap" array which contains False for nodes - which are NOT calculated, and True for nodes which are - required. - -OUTPUT PARAMETERS: - Y - function values, array[NY*N0*N1*N2], where NY is a number - of "output" vector values (this function supports vector- - valued RBF models): - * Y[K+NY*(I0+I1*N0+I2*N0*N1)]=F_k(X0[I0],X1[I1],X2[I2]), - for K=0...NY-1, I0=0...N0-1, I1=0...N1-1, I2=0...N2-1. - * elements of Y[] which correspond to FlagY[]=True are - loaded by model values (which may be exactly zero for - some nodes). - * elements of Y[] which correspond to FlagY[]=False MAY be - initialized by zeros OR may be calculated. This function - processes grid as a hierarchy of nested blocks and - micro-rows. If just one element of micro-row is required, - entire micro-row (up to 8 nodes in the current version, - but no promises) is calculated. - -NOTE: this function supports weakly ordered grid nodes, i.e. you may have - X[i]=X[i+1] for some i. It does not provide you any performance - benefits due to duplication of points, just convenience and - flexibility. - -NOTE: this function is re-entrant, i.e. you may use same rbfmodel - structure in multiple threads calling this function for different - grids. - - -- ALGLIB -- - Copyright 04.03.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfgridcalc3vsubset(const rbfmodel &s, const real_1d_array &x0, const ae_int_t n0, const real_1d_array &x1, const ae_int_t n1, const real_1d_array &x2, const ae_int_t n2, const boolean_1d_array &flagy, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfgridcalc3vsubset(const_cast(s.c_ptr()), const_cast(x0.c_ptr()), n0, const_cast(x1.c_ptr()), n1, const_cast(x2.c_ptr()), n2, const_cast(flagy.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function "unpacks" RBF model by extracting its coefficients. - -INPUT PARAMETERS: - S - RBF model - -OUTPUT PARAMETERS: - NX - dimensionality of argument - NY - dimensionality of the target function - XWR - model information, array[NC,NX+NY+1]. - One row of the array corresponds to one basis function: - * first NX columns - coordinates of the center - * next NY columns - weights, one per dimension of the - function being modelled - For ModelVersion=1: - * last column - radius, same for all dimensions of - the function being modelled - For ModelVersion=2: - * last NX columns - radii, one per dimension - NC - number of the centers - V - polynomial term , array[NY,NX+1]. One row per one - dimension of the function being modelled. First NX - elements are linear coefficients, V[NX] is equal to the - constant part. - ModelVersion-version of the RBF model: - * 1 - for models created by QNN and RBF-ML algorithms, - compatible with ALGLIB 3.10 or earlier. - * 2 - for models created by HierarchicalRBF, requires - ALGLIB 3.11 or later - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfunpack(const rbfmodel &s, ae_int_t &nx, ae_int_t &ny, real_2d_array &xwr, ae_int_t &nc, real_2d_array &v, ae_int_t &modelversion, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfunpack(const_cast(s.c_ptr()), &nx, &ny, const_cast(xwr.c_ptr()), &nc, const_cast(v.c_ptr()), &modelversion, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function returns model version. - -INPUT PARAMETERS: - S - RBF model - -RESULT: - * 1 - for models created by QNN and RBF-ML algorithms, - compatible with ALGLIB 3.10 or earlier. - * 2 - for models created by HierarchicalRBF, requires - ALGLIB 3.11 or later - - -- ALGLIB -- - Copyright 06.07.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t rbfgetmodelversion(const rbfmodel &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::rbfgetmodelversion(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function is used to peek into hierarchical RBF construction process -from some other thread and get current progress indicator. It returns -value in [0,1]. - -IMPORTANT: only HRBFs (hierarchical RBFs) support peeking into progress - indicator. Legacy RBF-ML and RBF-QNN do not support it. You - will always get 0 value. - -INPUT PARAMETERS: - S - RBF model object - -RESULT: - progress value, in [0,1] - - -- ALGLIB -- - Copyright 17.11.2018 by Bochkanov Sergey -*************************************************************************/ -double rbfpeekprogress(const rbfmodel &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::rbfpeekprogress(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function is used to submit a request for termination of the -hierarchical RBF construction process from some other thread. As result, -RBF construction is terminated smoothly (with proper deallocation of all -necessary resources) and resultant model is filled by zeros. - -A rep.terminationtype=8 will be returned upon receiving such request. - -IMPORTANT: only HRBFs (hierarchical RBFs) support termination requests. - Legacy RBF-ML and RBF-QNN do not support it. An attempt to - terminate their construction will be ignored. - -IMPORTANT: termination request flag is cleared when the model construction - starts. Thus, any pre-construction termination requests will be - silently ignored - only ones submitted AFTER construction has - actually began will be handled. - -INPUT PARAMETERS: - S - RBF model object - - -- ALGLIB -- - Copyright 17.11.2018 by Bochkanov Sergey -*************************************************************************/ -void rbfrequesttermination(const rbfmodel &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rbfrequesttermination(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_INTCOMP) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This function is left for backward compatibility. -Use fitspheremc() instead. - - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void nsfitspheremcc(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &rhi, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::nsfitspheremcc(const_cast(xy.c_ptr()), npoints, nx, const_cast(cx.c_ptr()), &rhi, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is left for backward compatibility. -Use fitspheremi() instead. - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void nsfitspheremic(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &rlo, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::nsfitspheremic(const_cast(xy.c_ptr()), npoints, nx, const_cast(cx.c_ptr()), &rlo, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is left for backward compatibility. -Use fitspheremz() instead. - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void nsfitspheremzc(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &rlo, double &rhi, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::nsfitspheremzc(const_cast(xy.c_ptr()), npoints, nx, const_cast(cx.c_ptr()), &rlo, &rhi, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is left for backward compatibility. -Use fitspherex() instead. - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void nsfitspherex(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, const ae_int_t problemtype, const double epsx, const ae_int_t aulits, const double penalty, real_1d_array &cx, double &rlo, double &rhi, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::nsfitspherex(const_cast(xy.c_ptr()), npoints, nx, problemtype, epsx, aulits, penalty, const_cast(cx.c_ptr()), &rlo, &rhi, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is an obsolete and deprecated version of fitting by -penalized cubic spline. - -It was superseded by spline1dfit(), which is an orders of magnitude faster -and more memory-efficient implementation. - -Do NOT use this function in the new code! - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -void spline1dfitpenalized(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t m, const double rho, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dfitpenalized(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, m, rho, &info, const_cast(s.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is an obsolete and deprecated version of fitting by -penalized cubic spline. - -It was superseded by spline1dfit(), which is an orders of magnitude faster -and more memory-efficient implementation. - -Do NOT use this function in the new code! - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spline1dfitpenalized(const real_1d_array &x, const real_1d_array &y, const ae_int_t m, const double rho, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (x.length()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dfitpenalized': looks like one of arguments has wrong size"); - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dfitpenalized(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, m, rho, &info, const_cast(s.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function is an obsolete and deprecated version of fitting by -penalized cubic spline. - -It was superseded by spline1dfit(), which is an orders of magnitude faster -and more memory-efficient implementation. - -Do NOT use this function in the new code! - - -- ALGLIB PROJECT -- - Copyright 19.10.2010 by Bochkanov Sergey -*************************************************************************/ -void spline1dfitpenalizedw(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t n, const ae_int_t m, const double rho, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dfitpenalizedw(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(w.c_ptr()), n, m, rho, &info, const_cast(s.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is an obsolete and deprecated version of fitting by -penalized cubic spline. - -It was superseded by spline1dfit(), which is an orders of magnitude faster -and more memory-efficient implementation. - -Do NOT use this function in the new code! - - -- ALGLIB PROJECT -- - Copyright 19.10.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spline1dfitpenalizedw(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t m, const double rho, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (x.length()!=y.length()) || (x.length()!=w.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dfitpenalizedw': looks like one of arguments has wrong size"); - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spline1dfitpenalizedw(const_cast(x.c_ptr()), const_cast(y.c_ptr()), const_cast(w.c_ptr()), n, m, rho, &info, const_cast(s.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF COMPUTATIONAL CORE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_IDW) || !defined(AE_PARTIAL_BUILD) -static double idw_w0 = 1.0; -static double idw_meps = 1.0E-50; -static ae_int_t idw_defaultnlayers = 16; -static double idw_defaultlambda0 = 0.3333; -static void idw_errormetricsviacalc(idwbuilder* state, - idwmodel* model, - idwreport* rep, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_RATINT) || !defined(AE_PARTIAL_BUILD) -static void ratint_barycentricnormalize(barycentricinterpolant* b, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_FITSPHERE) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_INTFITSERV) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_SPLINE1D) || !defined(AE_PARTIAL_BUILD) -static double spline1d_lambdareg = 1.0e-9; -static double spline1d_cholreg = 1.0e-12; -static void spline1d_spline1dgriddiffcubicinternal(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t boundltype, - double boundl, - ae_int_t boundrtype, - double boundr, - /* Real */ ae_vector* d, - /* Real */ ae_vector* a1, - /* Real */ ae_vector* a2, - /* Real */ ae_vector* a3, - /* Real */ ae_vector* b, - /* Real */ ae_vector* dt, - ae_state *_state); -static void spline1d_heapsortpoints(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_state *_state); -static void spline1d_heapsortppoints(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Integer */ ae_vector* p, - ae_int_t n, - ae_state *_state); -static void spline1d_solvetridiagonal(/* Real */ ae_vector* a, - /* Real */ ae_vector* b, - /* Real */ ae_vector* c, - /* Real */ ae_vector* d, - ae_int_t n, - /* Real */ ae_vector* x, - ae_state *_state); -static void spline1d_solvecyclictridiagonal(/* Real */ ae_vector* a, - /* Real */ ae_vector* b, - /* Real */ ae_vector* c, - /* Real */ ae_vector* d, - ae_int_t n, - /* Real */ ae_vector* x, - ae_state *_state); -static double spline1d_diffthreepoint(double t, - double x0, - double f0, - double x1, - double f1, - double x2, - double f2, - ae_state *_state); -static void spline1d_hermitecalc(double p0, - double m0, - double p1, - double m1, - double t, - double* s, - double* ds, - ae_state *_state); -static double spline1d_rescaleval(double a0, - double b0, - double a1, - double b1, - double t, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_PARAMETRIC) || !defined(AE_PARTIAL_BUILD) -static void parametric_pspline2par(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t pt, - /* Real */ ae_vector* p, - ae_state *_state); -static void parametric_pspline3par(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t pt, - /* Real */ ae_vector* p, - ae_state *_state); -static void parametric_rdpanalyzesectionpar(/* Real */ ae_matrix* xy, - ae_int_t i0, - ae_int_t i1, - ae_int_t d, - ae_int_t* worstidx, - double* worsterror, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_SPLINE3D) || !defined(AE_PARTIAL_BUILD) -static void spline3d_spline3ddiff(spline3dinterpolant* c, - double x, - double y, - double z, - double* f, - double* fx, - double* fy, - double* fxy, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_POLINT) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_LSFIT) || !defined(AE_PARTIAL_BUILD) -static void lsfit_rdpanalyzesection(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t i0, - ae_int_t i1, - ae_int_t* worstidx, - double* worsterror, - ae_state *_state); -static void lsfit_rdprecursive(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t i0, - ae_int_t i1, - double eps, - /* Real */ ae_vector* xout, - /* Real */ ae_vector* yout, - ae_int_t* nout, - ae_state *_state); -static void lsfit_logisticfitinternal(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_bool is4pl, - double lambdav, - minlmstate* state, - minlmreport* replm, - /* Real */ ae_vector* p1, - double* flast, - ae_state *_state); -static void lsfit_logisticfit45errors(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - double a, - double b, - double c, - double d, - double g, - lsfitreport* rep, - ae_state *_state); -static void lsfit_spline1dfitinternal(ae_int_t st, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_int_t n, - /* Real */ ae_vector* xc, - /* Real */ ae_vector* yc, - /* Integer */ ae_vector* dc, - ae_int_t k, - ae_int_t m, - ae_int_t* info, - spline1dinterpolant* s, - spline1dfitreport* rep, - ae_state *_state); -static void lsfit_lsfitlinearinternal(/* Real */ ae_vector* y, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* fmatrix, - ae_int_t n, - ae_int_t m, - ae_int_t* info, - /* Real */ ae_vector* c, - lsfitreport* rep, - ae_state *_state); -static void lsfit_lsfitclearrequestfields(lsfitstate* state, - ae_state *_state); -static void lsfit_barycentriccalcbasis(barycentricinterpolant* b, - double t, - /* Real */ ae_vector* y, - ae_state *_state); -static void lsfit_internalchebyshevfit(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_int_t n, - /* Real */ ae_vector* xc, - /* Real */ ae_vector* yc, - /* Integer */ ae_vector* dc, - ae_int_t k, - ae_int_t m, - ae_int_t* info, - /* Real */ ae_vector* c, - lsfitreport* rep, - ae_state *_state); -static void lsfit_barycentricfitwcfixedd(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_int_t n, - /* Real */ ae_vector* xc, - /* Real */ ae_vector* yc, - /* Integer */ ae_vector* dc, - ae_int_t k, - ae_int_t m, - ae_int_t d, - ae_int_t* info, - barycentricinterpolant* b, - barycentricfitreport* rep, - ae_state *_state); -static void lsfit_clearreport(lsfitreport* rep, ae_state *_state); -static void lsfit_estimateerrors(/* Real */ ae_matrix* f1, - /* Real */ ae_vector* f0, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - /* Real */ ae_vector* x, - /* Real */ ae_vector* s, - ae_int_t n, - ae_int_t k, - lsfitreport* rep, - /* Real */ ae_matrix* z, - ae_int_t zkind, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_RBFV2) || !defined(AE_PARTIAL_BUILD) -static double rbfv2_defaultlambdareg = 1.0E-6; -static double rbfv2_defaultsupportr = 0.10; -static ae_int_t rbfv2_defaultmaxits = 400; -static ae_int_t rbfv2_defaultbf = 1; -static ae_int_t rbfv2_maxnodesize = 6; -static double rbfv2_complexitymultiplier = 100.0; -static ae_bool rbfv2_rbfv2buildlinearmodel(/* Real */ ae_matrix* x, - /* Real */ ae_matrix* y, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - ae_int_t modeltype, - /* Real */ ae_matrix* v, - ae_state *_state); -static void rbfv2_allocatecalcbuffer(rbfv2model* s, - rbfv2calcbuffer* buf, - ae_state *_state); -static void rbfv2_convertandappendtree(kdtree* curtree, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - /* Integer */ ae_vector* kdnodes, - /* Real */ ae_vector* kdsplits, - /* Real */ ae_vector* cw, - ae_state *_state); -static void rbfv2_converttreerec(kdtree* curtree, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - ae_int_t nodeoffset, - ae_int_t nodesbase, - ae_int_t splitsbase, - ae_int_t cwbase, - /* Integer */ ae_vector* localnodes, - ae_int_t* localnodessize, - /* Real */ ae_vector* localsplits, - ae_int_t* localsplitssize, - /* Real */ ae_vector* localcw, - ae_int_t* localcwsize, - /* Real */ ae_matrix* xybuf, - ae_state *_state); -static void rbfv2_partialcalcrec(rbfv2model* s, - rbfv2calcbuffer* buf, - ae_int_t rootidx, - double invr2, - double queryr2, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -static void rbfv2_partialrowcalcrec(rbfv2model* s, - rbfv2calcbuffer* buf, - ae_int_t rootidx, - double invr2, - double rquery2, - double rfar2, - /* Real */ ae_vector* cx, - /* Real */ ae_vector* rx, - /* Boolean */ ae_vector* rf, - ae_int_t rowsize, - /* Real */ ae_vector* ry, - ae_state *_state); -static void rbfv2_preparepartialquery(/* Real */ ae_vector* x, - /* Real */ ae_vector* kdboxmin, - /* Real */ ae_vector* kdboxmax, - ae_int_t nx, - rbfv2calcbuffer* buf, - ae_int_t* cnt, - ae_state *_state); -static void rbfv2_partialqueryrec(/* Integer */ ae_vector* kdnodes, - /* Real */ ae_vector* kdsplits, - /* Real */ ae_vector* cw, - ae_int_t nx, - ae_int_t ny, - rbfv2calcbuffer* buf, - ae_int_t rootidx, - double queryr2, - /* Real */ ae_vector* x, - /* Real */ ae_vector* r2, - /* Integer */ ae_vector* offs, - ae_int_t* k, - ae_state *_state); -static ae_int_t rbfv2_partialcountrec(/* Integer */ ae_vector* kdnodes, - /* Real */ ae_vector* kdsplits, - /* Real */ ae_vector* cw, - ae_int_t nx, - ae_int_t ny, - rbfv2calcbuffer* buf, - ae_int_t rootidx, - double queryr2, - /* Real */ ae_vector* x, - ae_state *_state); -static void rbfv2_partialunpackrec(/* Integer */ ae_vector* kdnodes, - /* Real */ ae_vector* kdsplits, - /* Real */ ae_vector* cw, - /* Real */ ae_vector* s, - ae_int_t nx, - ae_int_t ny, - ae_int_t rootidx, - double r, - /* Real */ ae_matrix* xwr, - ae_int_t* k, - ae_state *_state); -static ae_int_t rbfv2_designmatrixrowsize(/* Integer */ ae_vector* kdnodes, - /* Real */ ae_vector* kdsplits, - /* Real */ ae_vector* cw, - /* Real */ ae_vector* ri, - /* Integer */ ae_vector* kdroots, - /* Real */ ae_vector* kdboxmin, - /* Real */ ae_vector* kdboxmax, - ae_int_t nx, - ae_int_t ny, - ae_int_t nh, - ae_int_t level, - double rcoeff, - /* Real */ ae_vector* x0, - rbfv2calcbuffer* calcbuf, - ae_state *_state); -static void rbfv2_designmatrixgeneraterow(/* Integer */ ae_vector* kdnodes, - /* Real */ ae_vector* kdsplits, - /* Real */ ae_vector* cw, - /* Real */ ae_vector* ri, - /* Integer */ ae_vector* kdroots, - /* Real */ ae_vector* kdboxmin, - /* Real */ ae_vector* kdboxmax, - /* Integer */ ae_vector* cwrange, - ae_int_t nx, - ae_int_t ny, - ae_int_t nh, - ae_int_t level, - ae_int_t bf, - double rcoeff, - ae_int_t rowsperpoint, - double penalty, - /* Real */ ae_vector* x0, - rbfv2calcbuffer* calcbuf, - /* Real */ ae_vector* tmpr2, - /* Integer */ ae_vector* tmpoffs, - /* Integer */ ae_vector* rowidx, - /* Real */ ae_vector* rowval, - ae_int_t* rowsize, - ae_state *_state); -static void rbfv2_zerofill(rbfv2model* s, - ae_int_t nx, - ae_int_t ny, - ae_int_t bf, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_SPLINE2D) || !defined(AE_PARTIAL_BUILD) -static double spline2d_cholreg = 1.0E-12; -static double spline2d_lambdaregblocklls = 1.0E-6; -static double spline2d_lambdaregfastddm = 1.0E-4; -static double spline2d_lambdadecay = 0.5; -static void spline2d_bicubiccalcderivatives(/* Real */ ae_matrix* a, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* dx, - /* Real */ ae_matrix* dy, - /* Real */ ae_matrix* dxy, - ae_state *_state); -static void spline2d_generatedesignmatrix(/* Real */ ae_vector* xy, - ae_int_t npoints, - ae_int_t d, - ae_int_t kx, - ae_int_t ky, - double smoothing, - double lambdareg, - spline1dinterpolant* basis1, - sparsematrix* av, - sparsematrix* ah, - ae_int_t* arows, - ae_state *_state); -static void spline2d_updatesplinetable(/* Real */ ae_vector* z, - ae_int_t kx, - ae_int_t ky, - ae_int_t d, - spline1dinterpolant* basis1, - ae_int_t bfrad, - /* Real */ ae_vector* ftbl, - ae_int_t m, - ae_int_t n, - ae_int_t scalexy, - ae_state *_state); -static void spline2d_fastddmfit(/* Real */ ae_vector* xy, - ae_int_t npoints, - ae_int_t d, - ae_int_t kx, - ae_int_t ky, - ae_int_t basecasex, - ae_int_t basecasey, - ae_int_t maxcoresize, - ae_int_t interfacesize, - ae_int_t nlayers, - double smoothing, - ae_int_t lsqrcnt, - spline1dinterpolant* basis1, - spline2dinterpolant* spline, - spline2dfitreport* rep, - double tss, - ae_state *_state); -static void spline2d_fastddmfitlayer(/* Real */ ae_vector* xy, - ae_int_t d, - ae_int_t scalexy, - /* Integer */ ae_vector* xyindex, - ae_int_t basecasex, - ae_int_t tilex0, - ae_int_t tilex1, - ae_int_t tilescountx, - ae_int_t basecasey, - ae_int_t tiley0, - ae_int_t tiley1, - ae_int_t tilescounty, - ae_int_t maxcoresize, - ae_int_t interfacesize, - ae_int_t lsqrcnt, - double lambdareg, - spline1dinterpolant* basis1, - ae_shared_pool* pool, - spline2dinterpolant* spline, - ae_state *_state); -ae_bool _trypexec_spline2d_fastddmfitlayer(/* Real */ ae_vector* xy, - ae_int_t d, - ae_int_t scalexy, - /* Integer */ ae_vector* xyindex, - ae_int_t basecasex, - ae_int_t tilex0, - ae_int_t tilex1, - ae_int_t tilescountx, - ae_int_t basecasey, - ae_int_t tiley0, - ae_int_t tiley1, - ae_int_t tilescounty, - ae_int_t maxcoresize, - ae_int_t interfacesize, - ae_int_t lsqrcnt, - double lambdareg, - spline1dinterpolant* basis1, - ae_shared_pool* pool, - spline2dinterpolant* spline, ae_state *_state); -static void spline2d_blockllsfit(spline2dxdesignmatrix* xdesign, - ae_int_t lsqrcnt, - /* Real */ ae_vector* z, - spline2dfitreport* rep, - double tss, - spline2dblockllsbuf* buf, - ae_state *_state); -static void spline2d_naivellsfit(sparsematrix* av, - sparsematrix* ah, - ae_int_t arows, - /* Real */ ae_vector* xy, - ae_int_t kx, - ae_int_t ky, - ae_int_t npoints, - ae_int_t d, - ae_int_t lsqrcnt, - /* Real */ ae_vector* z, - spline2dfitreport* rep, - double tss, - ae_state *_state); -static ae_int_t spline2d_getcelloffset(ae_int_t kx, - ae_int_t ky, - ae_int_t blockbandwidth, - ae_int_t i, - ae_int_t j, - ae_state *_state); -static void spline2d_copycellto(ae_int_t kx, - ae_int_t ky, - ae_int_t blockbandwidth, - /* Real */ ae_matrix* blockata, - ae_int_t i, - ae_int_t j, - /* Real */ ae_matrix* dst, - ae_int_t dst0, - ae_int_t dst1, - ae_state *_state); -static void spline2d_flushtozerocell(ae_int_t kx, - ae_int_t ky, - ae_int_t blockbandwidth, - /* Real */ ae_matrix* blockata, - ae_int_t i, - ae_int_t j, - double eps, - ae_state *_state); -static void spline2d_blockllsgenerateata(sparsematrix* ah, - ae_int_t ky0, - ae_int_t ky1, - ae_int_t kx, - ae_int_t ky, - /* Real */ ae_matrix* blockata, - sreal* mxata, - ae_state *_state); -ae_bool _trypexec_spline2d_blockllsgenerateata(sparsematrix* ah, - ae_int_t ky0, - ae_int_t ky1, - ae_int_t kx, - ae_int_t ky, - /* Real */ ae_matrix* blockata, - sreal* mxata, ae_state *_state); -static ae_bool spline2d_blockllscholesky(/* Real */ ae_matrix* blockata, - ae_int_t kx, - ae_int_t ky, - /* Real */ ae_matrix* trsmbuf2, - /* Real */ ae_matrix* cholbuf2, - /* Real */ ae_vector* cholbuf1, - ae_state *_state); -static void spline2d_blockllstrsv(/* Real */ ae_matrix* blockata, - ae_int_t kx, - ae_int_t ky, - ae_bool transu, - /* Real */ ae_vector* b, - ae_state *_state); -static void spline2d_computeresidualsfromscratch(/* Real */ ae_vector* xy, - /* Real */ ae_vector* yraw, - ae_int_t npoints, - ae_int_t d, - ae_int_t scalexy, - spline2dinterpolant* spline, - ae_state *_state); -ae_bool _trypexec_spline2d_computeresidualsfromscratch(/* Real */ ae_vector* xy, - /* Real */ ae_vector* yraw, - ae_int_t npoints, - ae_int_t d, - ae_int_t scalexy, - spline2dinterpolant* spline, ae_state *_state); -static void spline2d_computeresidualsfromscratchrec(/* Real */ ae_vector* xy, - /* Real */ ae_vector* yraw, - ae_int_t pt0, - ae_int_t pt1, - ae_int_t chunksize, - ae_int_t d, - ae_int_t scalexy, - spline2dinterpolant* spline, - ae_shared_pool* pool, - ae_state *_state); -ae_bool _trypexec_spline2d_computeresidualsfromscratchrec(/* Real */ ae_vector* xy, - /* Real */ ae_vector* yraw, - ae_int_t pt0, - ae_int_t pt1, - ae_int_t chunksize, - ae_int_t d, - ae_int_t scalexy, - spline2dinterpolant* spline, - ae_shared_pool* pool, ae_state *_state); -static void spline2d_reorderdatasetandbuildindex(/* Real */ ae_vector* xy, - ae_int_t npoints, - ae_int_t d, - /* Real */ ae_vector* shadow, - ae_int_t ns, - ae_int_t kx, - ae_int_t ky, - /* Integer */ ae_vector* xyindex, - /* Integer */ ae_vector* bufi, - ae_state *_state); -static void spline2d_rescaledatasetandrefineindex(/* Real */ ae_vector* xy, - ae_int_t npoints, - ae_int_t d, - /* Real */ ae_vector* shadow, - ae_int_t ns, - ae_int_t kx, - ae_int_t ky, - /* Integer */ ae_vector* xyindex, - /* Integer */ ae_vector* bufi, - ae_state *_state); -static void spline2d_expandindexrows(/* Real */ ae_vector* xy, - ae_int_t d, - /* Real */ ae_vector* shadow, - ae_int_t ns, - /* Integer */ ae_vector* cidx, - ae_int_t pt0, - ae_int_t pt1, - /* Integer */ ae_vector* xyindexprev, - ae_int_t row0, - ae_int_t row1, - /* Integer */ ae_vector* xyindexnew, - ae_int_t kxnew, - ae_int_t kynew, - ae_bool rootcall, - ae_state *_state); -ae_bool _trypexec_spline2d_expandindexrows(/* Real */ ae_vector* xy, - ae_int_t d, - /* Real */ ae_vector* shadow, - ae_int_t ns, - /* Integer */ ae_vector* cidx, - ae_int_t pt0, - ae_int_t pt1, - /* Integer */ ae_vector* xyindexprev, - ae_int_t row0, - ae_int_t row1, - /* Integer */ ae_vector* xyindexnew, - ae_int_t kxnew, - ae_int_t kynew, - ae_bool rootcall, ae_state *_state); -static void spline2d_reorderdatasetandbuildindexrec(/* Real */ ae_vector* xy, - ae_int_t d, - /* Real */ ae_vector* shadow, - ae_int_t ns, - /* Integer */ ae_vector* cidx, - ae_int_t pt0, - ae_int_t pt1, - /* Integer */ ae_vector* xyindex, - ae_int_t idx0, - ae_int_t idx1, - ae_bool rootcall, - ae_state *_state); -ae_bool _trypexec_spline2d_reorderdatasetandbuildindexrec(/* Real */ ae_vector* xy, - ae_int_t d, - /* Real */ ae_vector* shadow, - ae_int_t ns, - /* Integer */ ae_vector* cidx, - ae_int_t pt0, - ae_int_t pt1, - /* Integer */ ae_vector* xyindex, - ae_int_t idx0, - ae_int_t idx1, - ae_bool rootcall, ae_state *_state); -static void spline2d_xdesigngenerate(/* Real */ ae_vector* xy, - /* Integer */ ae_vector* xyindex, - ae_int_t kx0, - ae_int_t kx1, - ae_int_t kxtotal, - ae_int_t ky0, - ae_int_t ky1, - ae_int_t kytotal, - ae_int_t d, - double lambdareg, - double lambdans, - spline1dinterpolant* basis1, - spline2dxdesignmatrix* a, - ae_state *_state); -static void spline2d_xdesignmv(spline2dxdesignmatrix* a, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -static void spline2d_xdesignmtv(spline2dxdesignmatrix* a, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -static void spline2d_xdesignblockata(spline2dxdesignmatrix* a, - /* Real */ ae_matrix* blockata, - double* mxata, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_RBFV1) || !defined(AE_PARTIAL_BUILD) -static ae_int_t rbfv1_mxnx = 3; -static double rbfv1_rbffarradius = 6; -static double rbfv1_rbfnearradius = 2.1; -static double rbfv1_rbfmlradius = 3; -static double rbfv1_minbasecasecost = 100000; -static ae_bool rbfv1_rbfv1buildlinearmodel(/* Real */ ae_matrix* x, - /* Real */ ae_matrix* y, - ae_int_t n, - ae_int_t ny, - ae_int_t modeltype, - /* Real */ ae_matrix* v, - ae_state *_state); -static void rbfv1_buildrbfmodellsqr(/* Real */ ae_matrix* x, - /* Real */ ae_matrix* y, - /* Real */ ae_matrix* xc, - /* Real */ ae_vector* r, - ae_int_t n, - ae_int_t nc, - ae_int_t ny, - kdtree* pointstree, - kdtree* centerstree, - double epsort, - double epserr, - ae_int_t maxits, - ae_int_t* gnnz, - ae_int_t* snnz, - /* Real */ ae_matrix* w, - ae_int_t* info, - ae_int_t* iterationscount, - ae_int_t* nmv, - ae_state *_state); -static void rbfv1_buildrbfmlayersmodellsqr(/* Real */ ae_matrix* x, - /* Real */ ae_matrix* y, - /* Real */ ae_matrix* xc, - double rval, - /* Real */ ae_vector* r, - ae_int_t n, - ae_int_t* nc, - ae_int_t ny, - ae_int_t nlayers, - kdtree* centerstree, - double epsort, - double epserr, - ae_int_t maxits, - double lambdav, - ae_int_t* annz, - /* Real */ ae_matrix* w, - ae_int_t* info, - ae_int_t* iterationscount, - ae_int_t* nmv, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_RBF) || !defined(AE_PARTIAL_BUILD) -static double rbf_eps = 1.0E-6; -static double rbf_rbffarradius = 6; -static ae_int_t rbf_rbffirstversion = 0; -static ae_int_t rbf_rbfversion2 = 2; -static void rbf_rbfpreparenonserializablefields(rbfmodel* s, - ae_state *_state); -static void rbf_initializev1(ae_int_t nx, - ae_int_t ny, - rbfv1model* s, - ae_state *_state); -static void rbf_initializev2(ae_int_t nx, - ae_int_t ny, - rbfv2model* s, - ae_state *_state); -static void rbf_clearreportfields(rbfreport* rep, ae_state *_state); - - -#endif -#if defined(AE_COMPILE_INTCOMP) || !defined(AE_PARTIAL_BUILD) - - -#endif - -#if defined(AE_COMPILE_IDW) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function creates buffer structure which can be used to perform -parallel IDW model evaluations (with one IDW model instance being -used from multiple threads, as long as different threads use different -instances of buffer). - -This buffer object can be used with idwtscalcbuf() function (here "ts" -stands for "thread-safe", "buf" is a suffix which denotes function which -reuses previously allocated output space). - -How to use it: -* create IDW model structure or load it from file -* call idwcreatecalcbuffer(), once per thread working with IDW model (you - should call this function only AFTER model initialization, see below for - more information) -* call idwtscalcbuf() from different threads, with each thread working - with its own copy of buffer object. - -INPUT PARAMETERS - S - IDW model - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: buffer object should be used only with IDW model object which - was used to initialize buffer. Any attempt to use buffer with - different object is dangerous - you may get memory violation - error because sizes of internal arrays do not fit to dimensions - of the IDW structure. - -IMPORTANT: you should call this function only for model which was built - with model builder (or unserialized from file). Sizes of some - internal structures are determined only after model is built, - so buffer object created before model construction stage will - be useless (and any attempt to use it will result in exception). - - -- ALGLIB -- - Copyright 22.10.2018 by Sergey Bochkanov -*************************************************************************/ -void idwcreatecalcbuffer(idwmodel* s, - idwcalcbuffer* buf, - ae_state *_state) -{ - - _idwcalcbuffer_clear(buf); - - ae_assert(s->nx>=1, "IDWCreateCalcBuffer: integrity check failed", _state); - ae_assert(s->ny>=1, "IDWCreateCalcBuffer: integrity check failed", _state); - ae_assert(s->nlayers>=0, "IDWCreateCalcBuffer: integrity check failed", _state); - ae_assert(s->algotype>=0, "IDWCreateCalcBuffer: integrity check failed", _state); - if( s->nlayers>=1&&s->algotype!=0 ) - { - kdtreecreaterequestbuffer(&s->tree, &buf->requestbuffer, _state); - } - rvectorsetlengthatleast(&buf->x, s->nx, _state); - rvectorsetlengthatleast(&buf->y, s->ny, _state); - rvectorsetlengthatleast(&buf->tsyw, s->ny*ae_maxint(s->nlayers, 1, _state), _state); - rvectorsetlengthatleast(&buf->tsw, ae_maxint(s->nlayers, 1, _state), _state); -} - - -/************************************************************************* -This subroutine creates builder object used to generate IDW model from -irregularly sampled (scattered) dataset. Multidimensional scalar/vector- --valued are supported. - -Builder object is used to fit model to data as follows: -* builder object is created with idwbuildercreate() function -* dataset is added with idwbuildersetpoints() function -* one of the modern IDW algorithms is chosen with either: - * idwbuildersetalgomstab() - Multilayer STABilized algorithm (interpolation) - Alternatively, one of the textbook algorithms can be chosen (not recommended): - * idwbuildersetalgotextbookshepard() - textbook Shepard algorithm - * idwbuildersetalgotextbookmodshepard()-textbook modified Shepard algorithm -* finally, model construction is performed with idwfit() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - NX - dimensionality of the argument, NX>=1 - NY - dimensionality of the function being modeled, NY>=1; - NY=1 corresponds to classic scalar function, NY>=1 corresponds - to vector-valued function. - -OUTPUT PARAMETERS: - State- builder object - - -- ALGLIB PROJECT -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildercreate(ae_int_t nx, - ae_int_t ny, - idwbuilder* state, - ae_state *_state) -{ - - _idwbuilder_clear(state); - - ae_assert(nx>=1, "IDWBuilderCreate: NX<=0", _state); - ae_assert(ny>=1, "IDWBuilderCreate: NY<=0", _state); - - /* - * We choose reasonable defaults for the algorithm: - * * MSTAB algorithm - * * 12 layers - * * default radius - * * default Lambda0 - */ - state->algotype = 2; - state->priortermtype = 2; - rvectorsetlengthatleast(&state->priortermval, ny, _state); - state->nlayers = idw_defaultnlayers; - state->r0 = (double)(0); - state->rdecay = 0.5; - state->lambda0 = idw_defaultlambda0; - state->lambdalast = (double)(0); - state->lambdadecay = 1.0; - - /* - * Other parameters, not used but initialized - */ - state->shepardp = (double)(0); - - /* - * Initial dataset is empty - */ - state->npoints = 0; - state->nx = nx; - state->ny = ny; -} - - -/************************************************************************* -This function changes number of layers used by IDW-MSTAB algorithm. - -The more layers you have, the finer details can be reproduced with IDW -model. The less layers you have, the less memory and CPU time is consumed -by the model. - -Memory consumption grows linearly with layers count, running time grows -sub-linearly. - -The default number of layers is 16, which allows you to reproduce details -at distance down to SRad/65536. You will rarely need to change it. - -INPUT PARAMETERS: - State - builder object - NLayers - NLayers>=1, the number of layers used by the model. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetnlayers(idwbuilder* state, - ae_int_t nlayers, - ae_state *_state) -{ - - - ae_assert(nlayers>=1, "IDWBuilderSetNLayers: N<1", _state); - state->nlayers = nlayers; -} - - -/************************************************************************* -This function adds dataset to the builder object. - -This function overrides results of the previous calls, i.e. multiple calls -of this function will result in only the last set being added. - -INPUT PARAMETERS: - State - builder object - XY - points, array[N,NX+NY]. One row corresponds to one point - in the dataset. First NX elements are coordinates, next - NY elements are function values. Array may be larger than - specified, in this case only leading [N,NX+NY] elements - will be used. - N - number of points in the dataset, N>=0. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetpoints(idwbuilder* state, - /* Real */ ae_matrix* xy, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t ew; - - - ae_assert(n>=0, "IDWBuilderSetPoints: N<0", _state); - ae_assert(xy->rows>=n, "IDWBuilderSetPoints: Rows(XY)cols>=state->nx+state->ny, "IDWBuilderSetPoints: Cols(XY)nx+state->ny, _state), "IDWBuilderSetPoints: XY contains infinite or NaN values!", _state); - state->npoints = n; - ew = state->nx+state->ny; - rvectorsetlengthatleast(&state->xy, n*ew, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=ew-1; j++) - { - state->xy.ptr.p_double[i*ew+j] = xy->ptr.pp_double[i][j]; - } - } -} - - -/************************************************************************* -This function sets IDW model construction algorithm to the Multilayer -Stabilized IDW method (IDW-MSTAB), a latest incarnation of the inverse -distance weighting interpolation which fixes shortcomings of the original -and modified Shepard's variants. - -The distinctive features of IDW-MSTAB are: -1) exact interpolation is pursued (as opposed to fitting and noise - suppression) -2) improved robustness when compared with that of other algorithms: - * MSTAB shows almost no strange fitting artifacts like ripples and - sharp spikes (unlike N-dimensional splines and HRBFs) - * MSTAB does not return function values far from the interval spanned - by the dataset; say, if all your points have |f|<=1, you can be sure - that model value won't deviate too much from [-1,+1] -3) good model construction time competing with that of HRBFs and bicubic - splines -4) ability to work with any number of dimensions, starting from NX=1 - -The drawbacks of IDW-MSTAB (and all IDW algorithms in general) are: -1) dependence of the model evaluation time on the search radius -2) bad extrapolation properties, models built by this method are usually - conservative in their predictions - -Thus, IDW-MSTAB is a good "default" option if you want to perform -scattered multidimensional interpolation. Although it has its drawbacks, -it is easy to use and robust, which makes it a good first step. - - -INPUT PARAMETERS: - State - builder object - SRad - initial search radius, SRad>0 is required. A model value - is obtained by "smart" averaging of the dataset points - within search radius. - -NOTE 1: IDW interpolation can correctly handle ANY dataset, including - datasets with non-distinct points. In case non-distinct points are - found, an average value for this point will be calculated. - -NOTE 2: the memory requirements for model storage are O(NPoints*NLayers). - The model construction needs twice as much memory as model storage. - -NOTE 3: by default 16 IDW layers are built which is enough for most cases. - You can change this parameter with idwbuildersetnlayers() method. - Larger values may be necessary if you need to reproduce extrafine - details at distances smaller than SRad/65536. Smaller value may - be necessary if you have to save memory and computing time, and - ready to sacrifice some model quality. - - -ALGORITHM DESCRIPTION - -ALGLIB implementation of IDW is somewhat similar to the modified Shepard's -method (one with search radius R) but overcomes several of its drawbacks, -namely: -1) a tendency to show stepwise behavior for uniform datasets -2) a tendency to show terrible interpolation properties for highly - nonuniform datasets which often arise in geospatial tasks - (function values are densely sampled across multiple separated - "tracks") - -IDW-MSTAB method performs several passes over dataset and builds a sequence -of progressively refined IDW models (layers), which starts from one with -largest search radius SRad and continues to smaller search radii until -required number of layers is built. Highest layers reproduce global -behavior of the target function at larger distances whilst lower layers -reproduce fine details at smaller distances. - -Each layer is an IDW model built with following modifications: -* weights go to zero when distance approach to the current search radius -* an additional regularizing term is added to the distance: w=1/(d^2+lambda) -* an additional fictional term with unit weight and zero function value is - added in order to promote continuity properties at the isolated and - boundary points - -By default, 16 layers is built, which is enough for most cases. You can -change this parameter with idwbuildersetnlayers() method. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetalgomstab(idwbuilder* state, - double srad, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(srad, _state), "IDWBuilderSetAlgoMSTAB: SRad is not finite", _state); - ae_assert(ae_fp_greater(srad,(double)(0)), "IDWBuilderSetAlgoMSTAB: SRad<=0", _state); - - /* - * Set algorithm - */ - state->algotype = 2; - - /* - * Set options - */ - state->r0 = srad; - state->rdecay = 0.5; - state->lambda0 = idw_defaultlambda0; - state->lambdalast = (double)(0); - state->lambdadecay = 1.0; -} - - -/************************************************************************* -This function sets IDW model construction algorithm to the textbook -Shepard's algorithm with custom (user-specified) power parameter. - -IMPORTANT: we do NOT recommend using textbook IDW algorithms because they - have terrible interpolation properties. Use MSTAB in all cases. - -INPUT PARAMETERS: - State - builder object - P - power parameter, P>0; good value to start with is 2.0 - -NOTE 1: IDW interpolation can correctly handle ANY dataset, including - datasets with non-distinct points. In case non-distinct points are - found, an average value for this point will be calculated. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetalgotextbookshepard(idwbuilder* state, - double p, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(p, _state), "IDWBuilderSetAlgoShepard: P is not finite", _state); - ae_assert(ae_fp_greater(p,(double)(0)), "IDWBuilderSetAlgoShepard: P<=0", _state); - - /* - * Set algorithm and options - */ - state->algotype = 0; - state->shepardp = p; -} - - -/************************************************************************* -This function sets IDW model construction algorithm to the 'textbook' -modified Shepard's algorithm with user-specified search radius. - -IMPORTANT: we do NOT recommend using textbook IDW algorithms because they - have terrible interpolation properties. Use MSTAB in all cases. - -INPUT PARAMETERS: - State - builder object - R - search radius - -NOTE 1: IDW interpolation can correctly handle ANY dataset, including - datasets with non-distinct points. In case non-distinct points are - found, an average value for this point will be calculated. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetalgotextbookmodshepard(idwbuilder* state, - double r, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(r, _state), "IDWBuilderSetAlgoModShepard: R is not finite", _state); - ae_assert(ae_fp_greater(r,(double)(0)), "IDWBuilderSetAlgoModShepard: R<=0", _state); - - /* - * Set algorithm and options - */ - state->algotype = 1; - state->r0 = r; -} - - -/************************************************************************* -This function sets prior term (model value at infinity) as user-specified -value. - -INPUT PARAMETERS: - S - spline builder - V - value for user-defined prior - -NOTE: for vector-valued models all components of the prior are set to same - user-specified value - - -- ALGLIB -- - Copyright 29.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetuserterm(idwbuilder* state, double v, ae_state *_state) -{ - ae_int_t j; - - - ae_assert(ae_isfinite(v, _state), "IDWBuilderSetUserTerm: infinite/NAN value passed", _state); - state->priortermtype = 0; - for(j=0; j<=state->ny-1; j++) - { - state->priortermval.ptr.p_double[j] = v; - } -} - - -/************************************************************************* -This function sets constant prior term (model value at infinity). - -Constant prior term is determined as mean value over dataset. - -INPUT PARAMETERS: - S - spline builder - - -- ALGLIB -- - Copyright 29.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetconstterm(idwbuilder* state, ae_state *_state) -{ - - - state->priortermtype = 2; -} - - -/************************************************************************* -This function sets zero prior term (model value at infinity). - -INPUT PARAMETERS: - S - spline builder - - -- ALGLIB -- - Copyright 29.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetzeroterm(idwbuilder* state, ae_state *_state) -{ - - - state->priortermtype = 3; -} - - -/************************************************************************* -IDW interpolation: scalar target, 1-dimensional argument - -NOTE: this function modifies internal temporaries of the IDW model, thus - IT IS NOT THREAD-SAFE! If you want to perform parallel model - evaluation from the multiple threads, use idwtscalcbuf() with per- - thread buffer object. - -INPUT PARAMETERS: - S - IDW interpolant built with IDW builder - X0 - argument value - -Result: - IDW interpolant S(X0) - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -double idwcalc1(idwmodel* s, double x0, ae_state *_state) -{ - double result; - - - ae_assert(s->nx==1, "IDWCalc1: S.NX<>1", _state); - ae_assert(s->ny==1, "IDWCalc1: S.NY<>1", _state); - ae_assert(ae_isfinite(x0, _state), "IDWCalc1: X0 is INF or NAN", _state); - s->buffer.x.ptr.p_double[0] = x0; - idwtscalcbuf(s, &s->buffer, &s->buffer.x, &s->buffer.y, _state); - result = s->buffer.y.ptr.p_double[0]; - return result; -} - - -/************************************************************************* -IDW interpolation: scalar target, 2-dimensional argument - -NOTE: this function modifies internal temporaries of the IDW model, thus - IT IS NOT THREAD-SAFE! If you want to perform parallel model - evaluation from the multiple threads, use idwtscalcbuf() with per- - thread buffer object. - -INPUT PARAMETERS: - S - IDW interpolant built with IDW builder - X0, X1 - argument value - -Result: - IDW interpolant S(X0,X1) - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -double idwcalc2(idwmodel* s, double x0, double x1, ae_state *_state) -{ - double result; - - - ae_assert(s->nx==2, "IDWCalc2: S.NX<>2", _state); - ae_assert(s->ny==1, "IDWCalc2: S.NY<>1", _state); - ae_assert(ae_isfinite(x0, _state), "IDWCalc2: X0 is INF or NAN", _state); - ae_assert(ae_isfinite(x1, _state), "IDWCalc2: X1 is INF or NAN", _state); - s->buffer.x.ptr.p_double[0] = x0; - s->buffer.x.ptr.p_double[1] = x1; - idwtscalcbuf(s, &s->buffer, &s->buffer.x, &s->buffer.y, _state); - result = s->buffer.y.ptr.p_double[0]; - return result; -} - - -/************************************************************************* -IDW interpolation: scalar target, 3-dimensional argument - -NOTE: this function modifies internal temporaries of the IDW model, thus - IT IS NOT THREAD-SAFE! If you want to perform parallel model - evaluation from the multiple threads, use idwtscalcbuf() with per- - thread buffer object. - -INPUT PARAMETERS: - S - IDW interpolant built with IDW builder - X0,X1,X2- argument value - -Result: - IDW interpolant S(X0,X1,X2) - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -double idwcalc3(idwmodel* s, - double x0, - double x1, - double x2, - ae_state *_state) -{ - double result; - - - ae_assert(s->nx==3, "IDWCalc3: S.NX<>3", _state); - ae_assert(s->ny==1, "IDWCalc3: S.NY<>1", _state); - ae_assert(ae_isfinite(x0, _state), "IDWCalc3: X0 is INF or NAN", _state); - ae_assert(ae_isfinite(x1, _state), "IDWCalc3: X1 is INF or NAN", _state); - ae_assert(ae_isfinite(x2, _state), "IDWCalc3: X2 is INF or NAN", _state); - s->buffer.x.ptr.p_double[0] = x0; - s->buffer.x.ptr.p_double[1] = x1; - s->buffer.x.ptr.p_double[2] = x2; - idwtscalcbuf(s, &s->buffer, &s->buffer.x, &s->buffer.y, _state); - result = s->buffer.y.ptr.p_double[0]; - return result; -} - - -/************************************************************************* -This function calculates values of the IDW model at the given point. - -This is general function which can be used for arbitrary NX (dimension of -the space of arguments) and NY (dimension of the function itself). However -when you have NY=1 you may find more convenient to use idwcalc1(), -idwcalc2() or idwcalc3(). - -NOTE: this function modifies internal temporaries of the IDW model, thus - IT IS NOT THREAD-SAFE! If you want to perform parallel model - evaluation from the multiple threads, use idwtscalcbuf() with per- - thread buffer object. - -INPUT PARAMETERS: - S - IDW model - X - coordinates, array[NX]. X may have more than NX elements, - in this case only leading NX will be used. - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is out-parameter and will be - reallocated after call to this function. In case you want - to reuse previously allocated Y, you may use idwcalcbuf(), - which reallocates Y only when it is too small. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwcalc(idwmodel* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - - ae_vector_clear(y); - - idwtscalcbuf(s, &s->buffer, x, y, _state); -} - - -/************************************************************************* -This function calculates values of the IDW model at the given point. - -Same as idwcalc(), but does not reallocate Y when in is large enough to -store function values. - -NOTE: this function modifies internal temporaries of the IDW model, thus - IT IS NOT THREAD-SAFE! If you want to perform parallel model - evaluation from the multiple threads, use idwtscalcbuf() with per- - thread buffer object. - -INPUT PARAMETERS: - S - IDW model - X - coordinates, array[NX]. X may have more than NX elements, - in this case only leading NX will be used. - Y - possibly preallocated array - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is not reallocated when it - is larger than NY. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwcalcbuf(idwmodel* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - - - idwtscalcbuf(s, &s->buffer, x, y, _state); -} - - -/************************************************************************* -This function calculates values of the IDW model at the given point, using -external buffer object (internal temporaries of IDW model are not -modified). - -This function allows to use same IDW model object in different threads, -assuming that different threads use different instances of the buffer -structure. - -INPUT PARAMETERS: - S - IDW model, may be shared between different threads - Buf - buffer object created for this particular instance of IDW - model with idwcreatecalcbuffer(). - X - coordinates, array[NX]. X may have more than NX elements, - in this case only leading NX will be used. - Y - possibly preallocated array - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is not reallocated when it - is larger than NY. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void idwtscalcbuf(idwmodel* s, - idwcalcbuffer* buf, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t ew; - ae_int_t k; - ae_int_t layeridx; - ae_int_t nx; - ae_int_t ny; - ae_int_t npoints; - double v; - double vv; - double f; - double p; - double r; - double eps; - double lambdacur; - double lambdadecay; - double invrdecay; - double invr; - ae_bool fastcalcpossible; - double wf0; - double ws0; - double wf1; - double ws1; - - - nx = s->nx; - ny = s->ny; - ae_assert(x->cnt>=nx, "IDWTsCalcBuf: Length(X)cntnlayers==0 ) - { - for(j=0; j<=ny-1; j++) - { - y->ptr.p_double[j] = s->globalprior.ptr.p_double[j]; - } - return; - } - - /* - * Textbook Shepard's method - */ - if( s->algotype==0 ) - { - npoints = s->npoints; - ae_assert(npoints>0, "IDWTsCalcBuf: integrity check failed", _state); - eps = 1.0E-50; - ew = nx+ny; - p = s->shepardp; - for(j=0; j<=ny-1; j++) - { - y->ptr.p_double[j] = (double)(0); - buf->tsyw.ptr.p_double[j] = eps; - } - for(i=0; i<=npoints-1; i++) - { - - /* - * Compute squared distance - */ - v = (double)(0); - for(j=0; j<=nx-1; j++) - { - vv = s->shepardxy.ptr.p_double[i*ew+j]-x->ptr.p_double[j]; - v = v+vv*vv; - } - - /* - * Compute weight (with small regularizing addition) - */ - v = ae_pow(v, p*0.5, _state); - v = 1/(eps+v); - - /* - * Accumulate - */ - for(j=0; j<=ny-1; j++) - { - y->ptr.p_double[j] = y->ptr.p_double[j]+v*s->shepardxy.ptr.p_double[i*ew+nx+j]; - buf->tsyw.ptr.p_double[j] = buf->tsyw.ptr.p_double[j]+v; - } - } - for(j=0; j<=ny-1; j++) - { - y->ptr.p_double[j] = y->ptr.p_double[j]/buf->tsyw.ptr.p_double[j]+s->globalprior.ptr.p_double[j]; - } - return; - } - - /* - * Textbook modified Shepard's method - */ - if( s->algotype==1 ) - { - eps = 1.0E-50; - r = s->r0; - for(j=0; j<=ny-1; j++) - { - y->ptr.p_double[j] = (double)(0); - buf->tsyw.ptr.p_double[j] = eps; - } - k = kdtreetsqueryrnn(&s->tree, &buf->requestbuffer, x, r, ae_true, _state); - kdtreetsqueryresultsxy(&s->tree, &buf->requestbuffer, &buf->tsxy, _state); - kdtreetsqueryresultsdistances(&s->tree, &buf->requestbuffer, &buf->tsdist, _state); - for(i=0; i<=k-1; i++) - { - v = buf->tsdist.ptr.p_double[i]; - v = (r-v)/(r*v+eps); - v = v*v; - for(j=0; j<=ny-1; j++) - { - y->ptr.p_double[j] = y->ptr.p_double[j]+v*buf->tsxy.ptr.pp_double[i][nx+j]; - buf->tsyw.ptr.p_double[j] = buf->tsyw.ptr.p_double[j]+v; - } - } - for(j=0; j<=ny-1; j++) - { - y->ptr.p_double[j] = y->ptr.p_double[j]/buf->tsyw.ptr.p_double[j]+s->globalprior.ptr.p_double[j]; - } - return; - } - - /* - * MSTAB - */ - if( s->algotype==2 ) - { - ae_assert(ae_fp_eq(idw_w0,(double)(1)), "IDWTsCalcBuf: unexpected W0, integrity check failed", _state); - invrdecay = 1/s->rdecay; - invr = 1/s->r0; - lambdadecay = s->lambdadecay; - fastcalcpossible = (ny==1&&s->nlayers>=3)&&ae_fp_eq(lambdadecay,(double)(1)); - if( fastcalcpossible ) - { - - /* - * Important special case, NY=1, no lambda-decay, - * we can perform optimized fast evaluation - */ - wf0 = (double)(0); - ws0 = idw_w0; - wf1 = (double)(0); - ws1 = idw_w0; - for(j=0; j<=s->nlayers-1; j++) - { - buf->tsyw.ptr.p_double[j] = (double)(0); - buf->tsw.ptr.p_double[j] = idw_w0; - } - } - else - { - - /* - * Setup variables for generic evaluation path - */ - for(j=0; j<=ny*s->nlayers-1; j++) - { - buf->tsyw.ptr.p_double[j] = (double)(0); - } - for(j=0; j<=s->nlayers-1; j++) - { - buf->tsw.ptr.p_double[j] = idw_w0; - } - } - k = kdtreetsqueryrnnu(&s->tree, &buf->requestbuffer, x, s->r0, ae_true, _state); - kdtreetsqueryresultsxy(&s->tree, &buf->requestbuffer, &buf->tsxy, _state); - kdtreetsqueryresultsdistances(&s->tree, &buf->requestbuffer, &buf->tsdist, _state); - for(i=0; i<=k-1; i++) - { - lambdacur = s->lambda0; - vv = buf->tsdist.ptr.p_double[i]*invr; - if( fastcalcpossible ) - { - - /* - * Important special case, fast evaluation possible - */ - v = vv*vv; - v = (1-v)*(1-v)/(v+lambdacur); - f = buf->tsxy.ptr.pp_double[i][nx+0]; - wf0 = wf0+v*f; - ws0 = ws0+v; - vv = vv*invrdecay; - if( vv>=1.0 ) - { - continue; - } - v = vv*vv; - v = (1-v)*(1-v)/(v+lambdacur); - f = buf->tsxy.ptr.pp_double[i][nx+1]; - wf1 = wf1+v*f; - ws1 = ws1+v; - vv = vv*invrdecay; - if( vv>=1.0 ) - { - continue; - } - for(layeridx=2; layeridx<=s->nlayers-1; layeridx++) - { - if( layeridx==s->nlayers-1 ) - { - lambdacur = s->lambdalast; - } - v = vv*vv; - v = (1-v)*(1-v)/(v+lambdacur); - f = buf->tsxy.ptr.pp_double[i][nx+layeridx]; - buf->tsyw.ptr.p_double[layeridx] = buf->tsyw.ptr.p_double[layeridx]+v*f; - buf->tsw.ptr.p_double[layeridx] = buf->tsw.ptr.p_double[layeridx]+v; - vv = vv*invrdecay; - if( vv>=1.0 ) - { - break; - } - } - } - else - { - - /* - * General case - */ - for(layeridx=0; layeridx<=s->nlayers-1; layeridx++) - { - if( layeridx==s->nlayers-1 ) - { - lambdacur = s->lambdalast; - } - if( vv>=1.0 ) - { - break; - } - v = vv*vv; - v = (1-v)*(1-v)/(v+lambdacur); - for(j=0; j<=ny-1; j++) - { - f = buf->tsxy.ptr.pp_double[i][nx+layeridx*ny+j]; - buf->tsyw.ptr.p_double[layeridx*ny+j] = buf->tsyw.ptr.p_double[layeridx*ny+j]+v*f; - } - buf->tsw.ptr.p_double[layeridx] = buf->tsw.ptr.p_double[layeridx]+v; - lambdacur = lambdacur*lambdadecay; - vv = vv*invrdecay; - } - } - } - if( fastcalcpossible ) - { - - /* - * Important special case, finalize evaluations - */ - buf->tsyw.ptr.p_double[0] = wf0; - buf->tsw.ptr.p_double[0] = ws0; - buf->tsyw.ptr.p_double[1] = wf1; - buf->tsw.ptr.p_double[1] = ws1; - } - for(j=0; j<=ny-1; j++) - { - y->ptr.p_double[j] = s->globalprior.ptr.p_double[j]; - } - for(layeridx=0; layeridx<=s->nlayers-1; layeridx++) - { - for(j=0; j<=ny-1; j++) - { - y->ptr.p_double[j] = y->ptr.p_double[j]+buf->tsyw.ptr.p_double[layeridx*ny+j]/buf->tsw.ptr.p_double[layeridx]; - } - } - return; - } - - /* - * - */ - ae_assert(ae_false, "IDWTsCalcBuf: unexpected AlgoType", _state); -} - - -/************************************************************************* -This function fits IDW model to the dataset using current IDW construction -algorithm. A model being built and fitting report are returned. - -INPUT PARAMETERS: - State - builder object - -OUTPUT PARAMETERS: - Model - an IDW model built with current algorithm - Rep - model fitting report, fields of this structure contain - information about average fitting errors. - -NOTE: although IDW-MSTAB algorithm is an interpolation method, i.e. it - tries to fit the model exactly, it can handle datasets with non- - distinct points which can not be fit exactly; in such cases least- - squares fitting is performed. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwfit(idwbuilder* state, - idwmodel* model, - idwreport* rep, - ae_state *_state) -{ - ae_int_t i; - ae_int_t i0; - ae_int_t j; - ae_int_t k; - ae_int_t layeridx; - ae_int_t srcidx; - double v; - double vv; - ae_int_t npoints; - ae_int_t nx; - ae_int_t ny; - double rcur; - double lambdacur; - double rss; - double tss; - - _idwmodel_clear(model); - _idwreport_clear(rep); - - nx = state->nx; - ny = state->ny; - npoints = state->npoints; - - /* - * Clear report fields - */ - rep->rmserror = (double)(0); - rep->avgerror = (double)(0); - rep->maxerror = (double)(0); - rep->r2 = 1.0; - - /* - * Quick exit for empty dataset - */ - if( state->npoints==0 ) - { - model->nx = nx; - model->ny = ny; - ae_vector_set_length(&model->globalprior, ny, _state); - for(i=0; i<=ny-1; i++) - { - model->globalprior.ptr.p_double[i] = (double)(0); - } - model->algotype = 0; - model->nlayers = 0; - model->r0 = (double)(1); - model->rdecay = 0.5; - model->lambda0 = (double)(0); - model->lambdalast = (double)(0); - model->lambdadecay = (double)(1); - model->shepardp = (double)(2); - model->npoints = 0; - idwcreatecalcbuffer(model, &model->buffer, _state); - return; - } - - /* - * Compute temporaries which will be required later: - * * global mean - */ - ae_assert(state->npoints>0, "IDWFit: integrity check failed", _state); - rvectorsetlengthatleast(&state->tmpmean, ny, _state); - for(j=0; j<=ny-1; j++) - { - state->tmpmean.ptr.p_double[j] = (double)(0); - } - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=ny-1; j++) - { - state->tmpmean.ptr.p_double[j] = state->tmpmean.ptr.p_double[j]+state->xy.ptr.p_double[i*(nx+ny)+nx+j]; - } - } - for(j=0; j<=ny-1; j++) - { - state->tmpmean.ptr.p_double[j] = state->tmpmean.ptr.p_double[j]/npoints; - } - - /* - * Compute global prior - * - * NOTE: for original Shepard's method it is always mean value - */ - rvectorsetlengthatleast(&model->globalprior, ny, _state); - for(j=0; j<=ny-1; j++) - { - model->globalprior.ptr.p_double[j] = state->tmpmean.ptr.p_double[j]; - } - if( state->algotype!=0 ) - { - - /* - * Algorithm is set to one of the "advanced" versions with search - * radius which can handle non-mean prior term - */ - if( state->priortermtype==0 ) - { - - /* - * User-specified prior - */ - for(j=0; j<=ny-1; j++) - { - model->globalprior.ptr.p_double[j] = state->priortermval.ptr.p_double[j]; - } - } - if( state->priortermtype==3 ) - { - - /* - * Zero prior - */ - for(j=0; j<=ny-1; j++) - { - model->globalprior.ptr.p_double[j] = (double)(0); - } - } - } - - /* - * Textbook Shepard - */ - if( state->algotype==0 ) - { - - /* - * Initialize model - */ - model->algotype = 0; - model->nx = nx; - model->ny = ny; - model->nlayers = 1; - model->r0 = (double)(1); - model->rdecay = 0.5; - model->lambda0 = (double)(0); - model->lambdalast = (double)(0); - model->lambdadecay = (double)(1); - model->shepardp = state->shepardp; - - /* - * Copy dataset - */ - rvectorsetlengthatleast(&model->shepardxy, npoints*(nx+ny), _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nx-1; j++) - { - model->shepardxy.ptr.p_double[i*(nx+ny)+j] = state->xy.ptr.p_double[i*(nx+ny)+j]; - } - for(j=0; j<=ny-1; j++) - { - model->shepardxy.ptr.p_double[i*(nx+ny)+nx+j] = state->xy.ptr.p_double[i*(nx+ny)+nx+j]-model->globalprior.ptr.p_double[j]; - } - } - model->npoints = npoints; - - /* - * Prepare internal buffer - * Evaluate report fields - */ - idwcreatecalcbuffer(model, &model->buffer, _state); - idw_errormetricsviacalc(state, model, rep, _state); - return; - } - - /* - * Textbook modified Shepard's method - */ - if( state->algotype==1 ) - { - - /* - * Initialize model - */ - model->algotype = 1; - model->nx = nx; - model->ny = ny; - model->nlayers = 1; - model->r0 = state->r0; - model->rdecay = (double)(1); - model->lambda0 = (double)(0); - model->lambdalast = (double)(0); - model->lambdadecay = (double)(1); - model->shepardp = (double)(0); - - /* - * Build kd-tree search structure - */ - rmatrixsetlengthatleast(&state->tmpxy, npoints, nx+ny, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nx-1; j++) - { - state->tmpxy.ptr.pp_double[i][j] = state->xy.ptr.p_double[i*(nx+ny)+j]; - } - for(j=0; j<=ny-1; j++) - { - state->tmpxy.ptr.pp_double[i][nx+j] = state->xy.ptr.p_double[i*(nx+ny)+nx+j]-model->globalprior.ptr.p_double[j]; - } - } - kdtreebuild(&state->tmpxy, npoints, nx, ny, 2, &model->tree, _state); - - /* - * Prepare internal buffer - * Evaluate report fields - */ - idwcreatecalcbuffer(model, &model->buffer, _state); - idw_errormetricsviacalc(state, model, rep, _state); - return; - } - - /* - * MSTAB algorithm - */ - if( state->algotype==2 ) - { - ae_assert(state->nlayers>=1, "IDWFit: integrity check failed", _state); - - /* - * Initialize model - */ - model->algotype = 2; - model->nx = nx; - model->ny = ny; - model->nlayers = state->nlayers; - model->r0 = state->r0; - model->rdecay = 0.5; - model->lambda0 = state->lambda0; - model->lambdadecay = 1.0; - model->lambdalast = idw_meps; - model->shepardp = (double)(0); - - /* - * Build kd-tree search structure, - * prepare input residuals for the first layer of the model - */ - rmatrixsetlengthatleast(&state->tmpxy, npoints, nx, _state); - rmatrixsetlengthatleast(&state->tmplayers, npoints, nx+ny*(state->nlayers+1), _state); - ivectorsetlengthatleast(&state->tmptags, npoints, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nx-1; j++) - { - v = state->xy.ptr.p_double[i*(nx+ny)+j]; - state->tmpxy.ptr.pp_double[i][j] = v; - state->tmplayers.ptr.pp_double[i][j] = v; - } - state->tmptags.ptr.p_int[i] = i; - for(j=0; j<=ny-1; j++) - { - state->tmplayers.ptr.pp_double[i][nx+j] = state->xy.ptr.p_double[i*(nx+ny)+nx+j]-model->globalprior.ptr.p_double[j]; - } - } - kdtreebuildtagged(&state->tmpxy, &state->tmptags, npoints, nx, 0, 2, &state->tmptree, _state); - - /* - * Iteratively build layer by layer - */ - rvectorsetlengthatleast(&state->tmpx, nx, _state); - rvectorsetlengthatleast(&state->tmpwy, ny, _state); - rvectorsetlengthatleast(&state->tmpw, ny, _state); - for(layeridx=0; layeridx<=state->nlayers-1; layeridx++) - { - - /* - * Determine layer metrics - */ - rcur = model->r0*ae_pow(model->rdecay, (double)(layeridx), _state); - lambdacur = model->lambda0*ae_pow(model->lambdadecay, (double)(layeridx), _state); - if( layeridx==state->nlayers-1 ) - { - lambdacur = model->lambdalast; - } - - /* - * For each point compute residual from fitting with current layer - */ - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nx-1; j++) - { - state->tmpx.ptr.p_double[j] = state->tmplayers.ptr.pp_double[i][j]; - } - k = kdtreequeryrnn(&state->tmptree, &state->tmpx, rcur, ae_true, _state); - kdtreequeryresultstags(&state->tmptree, &state->tmptags, _state); - kdtreequeryresultsdistances(&state->tmptree, &state->tmpdist, _state); - for(j=0; j<=ny-1; j++) - { - state->tmpwy.ptr.p_double[j] = (double)(0); - state->tmpw.ptr.p_double[j] = idw_w0; - } - for(i0=0; i0<=k-1; i0++) - { - vv = state->tmpdist.ptr.p_double[i0]/rcur; - vv = vv*vv; - v = (1-vv)*(1-vv)/(vv+lambdacur); - srcidx = state->tmptags.ptr.p_int[i0]; - for(j=0; j<=ny-1; j++) - { - state->tmpwy.ptr.p_double[j] = state->tmpwy.ptr.p_double[j]+v*state->tmplayers.ptr.pp_double[srcidx][nx+layeridx*ny+j]; - state->tmpw.ptr.p_double[j] = state->tmpw.ptr.p_double[j]+v; - } - } - for(j=0; j<=ny-1; j++) - { - v = state->tmplayers.ptr.pp_double[i][nx+layeridx*ny+j]; - state->tmplayers.ptr.pp_double[i][nx+(layeridx+1)*ny+j] = v-state->tmpwy.ptr.p_double[j]/state->tmpw.ptr.p_double[j]; - } - } - } - kdtreebuild(&state->tmplayers, npoints, nx, ny*state->nlayers, 2, &model->tree, _state); - - /* - * Evaluate report fields - */ - rep->rmserror = (double)(0); - rep->avgerror = (double)(0); - rep->maxerror = (double)(0); - rss = (double)(0); - tss = (double)(0); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=ny-1; j++) - { - v = ae_fabs(state->tmplayers.ptr.pp_double[i][nx+state->nlayers*ny+j], _state); - rep->rmserror = rep->rmserror+v*v; - rep->avgerror = rep->avgerror+v; - rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(v, _state), _state); - rss = rss+v*v; - tss = tss+ae_sqr(state->xy.ptr.p_double[i*(nx+ny)+nx+j]-state->tmpmean.ptr.p_double[j], _state); - } - } - rep->rmserror = ae_sqrt(rep->rmserror/(npoints*ny), _state); - rep->avgerror = rep->avgerror/(npoints*ny); - rep->r2 = 1.0-rss/coalesce(tss, 1.0, _state); - - /* - * Prepare internal buffer - */ - idwcreatecalcbuffer(model, &model->buffer, _state); - return; - } - - /* - * Unknown algorithm - */ - ae_assert(ae_false, "IDWFit: integrity check failed, unexpected algorithm", _state); -} - - -/************************************************************************* -Serializer: allocation - - -- ALGLIB -- - Copyright 28.02.2018 by Bochkanov Sergey -*************************************************************************/ -void idwalloc(ae_serializer* s, idwmodel* model, ae_state *_state) -{ - ae_bool processed; - - - - /* - * Header - */ - ae_serializer_alloc_entry(s); - - /* - * Algorithm type and fields which are set for all algorithms - */ - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - allocrealarray(s, &model->globalprior, -1, _state); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - - /* - * Algorithm-specific fields - */ - processed = ae_false; - if( model->algotype==0 ) - { - ae_serializer_alloc_entry(s); - allocrealarray(s, &model->shepardxy, -1, _state); - processed = ae_true; - } - if( model->algotype>0 ) - { - kdtreealloc(s, &model->tree, _state); - processed = ae_true; - } - ae_assert(processed, "IDW: integrity check failed during serialization", _state); -} - - -/************************************************************************* -Serializer: serialization - - -- ALGLIB -- - Copyright 28.02.2018 by Bochkanov Sergey -*************************************************************************/ -void idwserialize(ae_serializer* s, idwmodel* model, ae_state *_state) -{ - ae_bool processed; - - - - /* - * Header - */ - ae_serializer_serialize_int(s, getidwserializationcode(_state), _state); - - /* - * Algorithm type and fields which are set for all algorithms - */ - ae_serializer_serialize_int(s, model->algotype, _state); - ae_serializer_serialize_int(s, model->nx, _state); - ae_serializer_serialize_int(s, model->ny, _state); - serializerealarray(s, &model->globalprior, -1, _state); - ae_serializer_serialize_int(s, model->nlayers, _state); - ae_serializer_serialize_double(s, model->r0, _state); - ae_serializer_serialize_double(s, model->rdecay, _state); - ae_serializer_serialize_double(s, model->lambda0, _state); - ae_serializer_serialize_double(s, model->lambdalast, _state); - ae_serializer_serialize_double(s, model->lambdadecay, _state); - ae_serializer_serialize_double(s, model->shepardp, _state); - - /* - * Algorithm-specific fields - */ - processed = ae_false; - if( model->algotype==0 ) - { - ae_serializer_serialize_int(s, model->npoints, _state); - serializerealarray(s, &model->shepardxy, -1, _state); - processed = ae_true; - } - if( model->algotype>0 ) - { - kdtreeserialize(s, &model->tree, _state); - processed = ae_true; - } - ae_assert(processed, "IDW: integrity check failed during serialization", _state); -} - - -/************************************************************************* -Serializer: unserialization - - -- ALGLIB -- - Copyright 28.02.2018 by Bochkanov Sergey -*************************************************************************/ -void idwunserialize(ae_serializer* s, idwmodel* model, ae_state *_state) -{ - ae_bool processed; - ae_int_t scode; - - _idwmodel_clear(model); - - - /* - * Header - */ - ae_serializer_unserialize_int(s, &scode, _state); - ae_assert(scode==getidwserializationcode(_state), "IDWUnserialize: stream header corrupted", _state); - - /* - * Algorithm type and fields which are set for all algorithms - */ - ae_serializer_unserialize_int(s, &model->algotype, _state); - ae_serializer_unserialize_int(s, &model->nx, _state); - ae_serializer_unserialize_int(s, &model->ny, _state); - unserializerealarray(s, &model->globalprior, _state); - ae_serializer_unserialize_int(s, &model->nlayers, _state); - ae_serializer_unserialize_double(s, &model->r0, _state); - ae_serializer_unserialize_double(s, &model->rdecay, _state); - ae_serializer_unserialize_double(s, &model->lambda0, _state); - ae_serializer_unserialize_double(s, &model->lambdalast, _state); - ae_serializer_unserialize_double(s, &model->lambdadecay, _state); - ae_serializer_unserialize_double(s, &model->shepardp, _state); - - /* - * Algorithm-specific fields - */ - processed = ae_false; - if( model->algotype==0 ) - { - ae_serializer_unserialize_int(s, &model->npoints, _state); - unserializerealarray(s, &model->shepardxy, _state); - processed = ae_true; - } - if( model->algotype>0 ) - { - kdtreeunserialize(s, &model->tree, _state); - processed = ae_true; - } - ae_assert(processed, "IDW: integrity check failed during serialization", _state); - - /* - * Temporary buffers - */ - idwcreatecalcbuffer(model, &model->buffer, _state); -} - - -/************************************************************************* -This function evaluates error metrics for the model using IDWTsCalcBuf() -to calculate model at each point. - -NOTE: modern IDW algorithms (MSTAB, MSMOOTH) can generate residuals during - model construction, so they do not need this function in order to - evaluate error metrics. - -Following fields of Rep are filled: -* rep.rmserror -* rep.avgerror -* rep.maxerror -* rep.r2 - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -static void idw_errormetricsviacalc(idwbuilder* state, - idwmodel* model, - idwreport* rep, - ae_state *_state) -{ - ae_int_t npoints; - ae_int_t nx; - ae_int_t ny; - ae_int_t i; - ae_int_t j; - double v; - double vv; - double rss; - double tss; - - - npoints = state->npoints; - nx = state->nx; - ny = state->ny; - if( npoints==0 ) - { - rep->rmserror = (double)(0); - rep->avgerror = (double)(0); - rep->maxerror = (double)(0); - rep->r2 = (double)(1); - return; - } - rep->rmserror = (double)(0); - rep->avgerror = (double)(0); - rep->maxerror = (double)(0); - rss = (double)(0); - tss = (double)(0); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nx-1; j++) - { - model->buffer.x.ptr.p_double[j] = state->xy.ptr.p_double[i*(nx+ny)+j]; - } - idwtscalcbuf(model, &model->buffer, &model->buffer.x, &model->buffer.y, _state); - for(j=0; j<=ny-1; j++) - { - vv = state->xy.ptr.p_double[i*(nx+ny)+nx+j]; - v = ae_fabs(vv-model->buffer.y.ptr.p_double[j], _state); - rep->rmserror = rep->rmserror+v*v; - rep->avgerror = rep->avgerror+v; - rep->maxerror = ae_maxreal(rep->maxerror, v, _state); - rss = rss+v*v; - tss = tss+ae_sqr(vv-state->tmpmean.ptr.p_double[j], _state); - } - } - rep->rmserror = ae_sqrt(rep->rmserror/(npoints*ny), _state); - rep->avgerror = rep->avgerror/(npoints*ny); - rep->r2 = 1.0-rss/coalesce(tss, 1.0, _state); -} - - -void _idwcalcbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - idwcalcbuffer *p = (idwcalcbuffer*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tsyw, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tsw, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->tsxy, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tsdist, 0, DT_REAL, _state, make_automatic); - _kdtreerequestbuffer_init(&p->requestbuffer, _state, make_automatic); -} - - -void _idwcalcbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - idwcalcbuffer *dst = (idwcalcbuffer*)_dst; - idwcalcbuffer *src = (idwcalcbuffer*)_src; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic); - ae_vector_init_copy(&dst->tsyw, &src->tsyw, _state, make_automatic); - ae_vector_init_copy(&dst->tsw, &src->tsw, _state, make_automatic); - ae_matrix_init_copy(&dst->tsxy, &src->tsxy, _state, make_automatic); - ae_vector_init_copy(&dst->tsdist, &src->tsdist, _state, make_automatic); - _kdtreerequestbuffer_init_copy(&dst->requestbuffer, &src->requestbuffer, _state, make_automatic); -} - - -void _idwcalcbuffer_clear(void* _p) -{ - idwcalcbuffer *p = (idwcalcbuffer*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->x); - ae_vector_clear(&p->y); - ae_vector_clear(&p->tsyw); - ae_vector_clear(&p->tsw); - ae_matrix_clear(&p->tsxy); - ae_vector_clear(&p->tsdist); - _kdtreerequestbuffer_clear(&p->requestbuffer); -} - - -void _idwcalcbuffer_destroy(void* _p) -{ - idwcalcbuffer *p = (idwcalcbuffer*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->y); - ae_vector_destroy(&p->tsyw); - ae_vector_destroy(&p->tsw); - ae_matrix_destroy(&p->tsxy); - ae_vector_destroy(&p->tsdist); - _kdtreerequestbuffer_destroy(&p->requestbuffer); -} - - -void _idwmodel_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - idwmodel *p = (idwmodel*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->globalprior, 0, DT_REAL, _state, make_automatic); - _kdtree_init(&p->tree, _state, make_automatic); - ae_vector_init(&p->shepardxy, 0, DT_REAL, _state, make_automatic); - _idwcalcbuffer_init(&p->buffer, _state, make_automatic); -} - - -void _idwmodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - idwmodel *dst = (idwmodel*)_dst; - idwmodel *src = (idwmodel*)_src; - dst->nx = src->nx; - dst->ny = src->ny; - ae_vector_init_copy(&dst->globalprior, &src->globalprior, _state, make_automatic); - dst->algotype = src->algotype; - dst->nlayers = src->nlayers; - dst->r0 = src->r0; - dst->rdecay = src->rdecay; - dst->lambda0 = src->lambda0; - dst->lambdalast = src->lambdalast; - dst->lambdadecay = src->lambdadecay; - dst->shepardp = src->shepardp; - _kdtree_init_copy(&dst->tree, &src->tree, _state, make_automatic); - dst->npoints = src->npoints; - ae_vector_init_copy(&dst->shepardxy, &src->shepardxy, _state, make_automatic); - _idwcalcbuffer_init_copy(&dst->buffer, &src->buffer, _state, make_automatic); -} - - -void _idwmodel_clear(void* _p) -{ - idwmodel *p = (idwmodel*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->globalprior); - _kdtree_clear(&p->tree); - ae_vector_clear(&p->shepardxy); - _idwcalcbuffer_clear(&p->buffer); -} - - -void _idwmodel_destroy(void* _p) -{ - idwmodel *p = (idwmodel*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->globalprior); - _kdtree_destroy(&p->tree); - ae_vector_destroy(&p->shepardxy); - _idwcalcbuffer_destroy(&p->buffer); -} - - -void _idwbuilder_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - idwbuilder *p = (idwbuilder*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->priortermval, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xy, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->tmpxy, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->tmplayers, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmptags, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->tmpdist, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpwy, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpw, 0, DT_REAL, _state, make_automatic); - _kdtree_init(&p->tmptree, _state, make_automatic); - ae_vector_init(&p->tmpmean, 0, DT_REAL, _state, make_automatic); -} - - -void _idwbuilder_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - idwbuilder *dst = (idwbuilder*)_dst; - idwbuilder *src = (idwbuilder*)_src; - dst->priortermtype = src->priortermtype; - ae_vector_init_copy(&dst->priortermval, &src->priortermval, _state, make_automatic); - dst->algotype = src->algotype; - dst->nlayers = src->nlayers; - dst->r0 = src->r0; - dst->rdecay = src->rdecay; - dst->lambda0 = src->lambda0; - dst->lambdalast = src->lambdalast; - dst->lambdadecay = src->lambdadecay; - dst->shepardp = src->shepardp; - ae_vector_init_copy(&dst->xy, &src->xy, _state, make_automatic); - dst->npoints = src->npoints; - dst->nx = src->nx; - dst->ny = src->ny; - ae_matrix_init_copy(&dst->tmpxy, &src->tmpxy, _state, make_automatic); - ae_matrix_init_copy(&dst->tmplayers, &src->tmplayers, _state, make_automatic); - ae_vector_init_copy(&dst->tmptags, &src->tmptags, _state, make_automatic); - ae_vector_init_copy(&dst->tmpdist, &src->tmpdist, _state, make_automatic); - ae_vector_init_copy(&dst->tmpx, &src->tmpx, _state, make_automatic); - ae_vector_init_copy(&dst->tmpwy, &src->tmpwy, _state, make_automatic); - ae_vector_init_copy(&dst->tmpw, &src->tmpw, _state, make_automatic); - _kdtree_init_copy(&dst->tmptree, &src->tmptree, _state, make_automatic); - ae_vector_init_copy(&dst->tmpmean, &src->tmpmean, _state, make_automatic); -} - - -void _idwbuilder_clear(void* _p) -{ - idwbuilder *p = (idwbuilder*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->priortermval); - ae_vector_clear(&p->xy); - ae_matrix_clear(&p->tmpxy); - ae_matrix_clear(&p->tmplayers); - ae_vector_clear(&p->tmptags); - ae_vector_clear(&p->tmpdist); - ae_vector_clear(&p->tmpx); - ae_vector_clear(&p->tmpwy); - ae_vector_clear(&p->tmpw); - _kdtree_clear(&p->tmptree); - ae_vector_clear(&p->tmpmean); -} - - -void _idwbuilder_destroy(void* _p) -{ - idwbuilder *p = (idwbuilder*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->priortermval); - ae_vector_destroy(&p->xy); - ae_matrix_destroy(&p->tmpxy); - ae_matrix_destroy(&p->tmplayers); - ae_vector_destroy(&p->tmptags); - ae_vector_destroy(&p->tmpdist); - ae_vector_destroy(&p->tmpx); - ae_vector_destroy(&p->tmpwy); - ae_vector_destroy(&p->tmpw); - _kdtree_destroy(&p->tmptree); - ae_vector_destroy(&p->tmpmean); -} - - -void _idwreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - idwreport *p = (idwreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _idwreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - idwreport *dst = (idwreport*)_dst; - idwreport *src = (idwreport*)_src; - dst->rmserror = src->rmserror; - dst->avgerror = src->avgerror; - dst->maxerror = src->maxerror; - dst->r2 = src->r2; -} - - -void _idwreport_clear(void* _p) -{ - idwreport *p = (idwreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _idwreport_destroy(void* _p) -{ - idwreport *p = (idwreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_RATINT) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Rational interpolation using barycentric formula - -F(t) = SUM(i=0,n-1,w[i]*f[i]/(t-x[i])) / SUM(i=0,n-1,w[i]/(t-x[i])) - -Input parameters: - B - barycentric interpolant built with one of model building - subroutines. - T - interpolation point - -Result: - barycentric interpolant F(t) - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -double barycentriccalc(barycentricinterpolant* b, - double t, - ae_state *_state) -{ - double s1; - double s2; - double s; - double v; - ae_int_t i; - double result; - - - ae_assert(!ae_isinf(t, _state), "BarycentricCalc: infinite T!", _state); - - /* - * special case: NaN - */ - if( ae_isnan(t, _state) ) - { - result = _state->v_nan; - return result; - } - - /* - * special case: N=1 - */ - if( b->n==1 ) - { - result = b->sy*b->y.ptr.p_double[0]; - return result; - } - - /* - * Here we assume that task is normalized, i.e.: - * 1. abs(Y[i])<=1 - * 2. abs(W[i])<=1 - * 3. X[] is ordered - */ - s = ae_fabs(t-b->x.ptr.p_double[0], _state); - for(i=0; i<=b->n-1; i++) - { - v = b->x.ptr.p_double[i]; - if( ae_fp_eq(v,t) ) - { - result = b->sy*b->y.ptr.p_double[i]; - return result; - } - v = ae_fabs(t-v, _state); - if( ae_fp_less(v,s) ) - { - s = v; - } - } - s1 = (double)(0); - s2 = (double)(0); - for(i=0; i<=b->n-1; i++) - { - v = s/(t-b->x.ptr.p_double[i]); - v = v*b->w.ptr.p_double[i]; - s1 = s1+v*b->y.ptr.p_double[i]; - s2 = s2+v; - } - result = b->sy*s1/s2; - return result; -} - - -/************************************************************************* -Differentiation of barycentric interpolant: first derivative. - -Algorithm used in this subroutine is very robust and should not fail until -provided with values too close to MaxRealNumber (usually MaxRealNumber/N -or greater will overflow). - -INPUT PARAMETERS: - B - barycentric interpolant built with one of model building - subroutines. - T - interpolation point - -OUTPUT PARAMETERS: - F - barycentric interpolant at T - DF - first derivative - -NOTE - - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentricdiff1(barycentricinterpolant* b, - double t, - double* f, - double* df, - ae_state *_state) -{ - double v; - double vv; - ae_int_t i; - ae_int_t k; - double n0; - double n1; - double d0; - double d1; - double s0; - double s1; - double xk; - double xi; - double xmin; - double xmax; - double xscale1; - double xoffs1; - double xscale2; - double xoffs2; - double xprev; - - *f = 0; - *df = 0; - - ae_assert(!ae_isinf(t, _state), "BarycentricDiff1: infinite T!", _state); - - /* - * special case: NaN - */ - if( ae_isnan(t, _state) ) - { - *f = _state->v_nan; - *df = _state->v_nan; - return; - } - - /* - * special case: N=1 - */ - if( b->n==1 ) - { - *f = b->sy*b->y.ptr.p_double[0]; - *df = (double)(0); - return; - } - if( ae_fp_eq(b->sy,(double)(0)) ) - { - *f = (double)(0); - *df = (double)(0); - return; - } - ae_assert(ae_fp_greater(b->sy,(double)(0)), "BarycentricDiff1: internal error", _state); - - /* - * We assume than N>1 and B.SY>0. Find: - * 1. pivot point (X[i] closest to T) - * 2. width of interval containing X[i] - */ - v = ae_fabs(b->x.ptr.p_double[0]-t, _state); - k = 0; - xmin = b->x.ptr.p_double[0]; - xmax = b->x.ptr.p_double[0]; - for(i=1; i<=b->n-1; i++) - { - vv = b->x.ptr.p_double[i]; - if( ae_fp_less(ae_fabs(vv-t, _state),v) ) - { - v = ae_fabs(vv-t, _state); - k = i; - } - xmin = ae_minreal(xmin, vv, _state); - xmax = ae_maxreal(xmax, vv, _state); - } - - /* - * pivot point found, calculate dNumerator and dDenominator - */ - xscale1 = 1/(xmax-xmin); - xoffs1 = -xmin/(xmax-xmin)+1; - xscale2 = (double)(2); - xoffs2 = (double)(-3); - t = t*xscale1+xoffs1; - t = t*xscale2+xoffs2; - xk = b->x.ptr.p_double[k]; - xk = xk*xscale1+xoffs1; - xk = xk*xscale2+xoffs2; - v = t-xk; - n0 = (double)(0); - n1 = (double)(0); - d0 = (double)(0); - d1 = (double)(0); - xprev = (double)(-2); - for(i=0; i<=b->n-1; i++) - { - xi = b->x.ptr.p_double[i]; - xi = xi*xscale1+xoffs1; - xi = xi*xscale2+xoffs2; - ae_assert(ae_fp_greater(xi,xprev), "BarycentricDiff1: points are too close!", _state); - xprev = xi; - if( i!=k ) - { - vv = ae_sqr(t-xi, _state); - s0 = (t-xk)/(t-xi); - s1 = (xk-xi)/vv; - } - else - { - s0 = (double)(1); - s1 = (double)(0); - } - vv = b->w.ptr.p_double[i]*b->y.ptr.p_double[i]; - n0 = n0+s0*vv; - n1 = n1+s1*vv; - vv = b->w.ptr.p_double[i]; - d0 = d0+s0*vv; - d1 = d1+s1*vv; - } - *f = b->sy*n0/d0; - *df = (n1*d0-n0*d1)/ae_sqr(d0, _state); - if( ae_fp_neq(*df,(double)(0)) ) - { - *df = ae_sign(*df, _state)*ae_exp(ae_log(ae_fabs(*df, _state), _state)+ae_log(b->sy, _state)+ae_log(xscale1, _state)+ae_log(xscale2, _state), _state); - } -} - - -/************************************************************************* -Differentiation of barycentric interpolant: first/second derivatives. - -INPUT PARAMETERS: - B - barycentric interpolant built with one of model building - subroutines. - T - interpolation point - -OUTPUT PARAMETERS: - F - barycentric interpolant at T - DF - first derivative - D2F - second derivative - -NOTE: this algorithm may fail due to overflow/underflor if used on data -whose values are close to MaxRealNumber or MinRealNumber. Use more robust -BarycentricDiff1() subroutine in such cases. - - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentricdiff2(barycentricinterpolant* b, - double t, - double* f, - double* df, - double* d2f, - ae_state *_state) -{ - double v; - double vv; - ae_int_t i; - ae_int_t k; - double n0; - double n1; - double n2; - double d0; - double d1; - double d2; - double s0; - double s1; - double s2; - double xk; - double xi; - - *f = 0; - *df = 0; - *d2f = 0; - - ae_assert(!ae_isinf(t, _state), "BarycentricDiff1: infinite T!", _state); - - /* - * special case: NaN - */ - if( ae_isnan(t, _state) ) - { - *f = _state->v_nan; - *df = _state->v_nan; - *d2f = _state->v_nan; - return; - } - - /* - * special case: N=1 - */ - if( b->n==1 ) - { - *f = b->sy*b->y.ptr.p_double[0]; - *df = (double)(0); - *d2f = (double)(0); - return; - } - if( ae_fp_eq(b->sy,(double)(0)) ) - { - *f = (double)(0); - *df = (double)(0); - *d2f = (double)(0); - return; - } - - /* - * We assume than N>1 and B.SY>0. Find: - * 1. pivot point (X[i] closest to T) - * 2. width of interval containing X[i] - */ - ae_assert(ae_fp_greater(b->sy,(double)(0)), "BarycentricDiff: internal error", _state); - *f = (double)(0); - *df = (double)(0); - *d2f = (double)(0); - v = ae_fabs(b->x.ptr.p_double[0]-t, _state); - k = 0; - for(i=1; i<=b->n-1; i++) - { - vv = b->x.ptr.p_double[i]; - if( ae_fp_less(ae_fabs(vv-t, _state),v) ) - { - v = ae_fabs(vv-t, _state); - k = i; - } - } - - /* - * pivot point found, calculate dNumerator and dDenominator - */ - xk = b->x.ptr.p_double[k]; - v = t-xk; - n0 = (double)(0); - n1 = (double)(0); - n2 = (double)(0); - d0 = (double)(0); - d1 = (double)(0); - d2 = (double)(0); - for(i=0; i<=b->n-1; i++) - { - if( i!=k ) - { - xi = b->x.ptr.p_double[i]; - vv = ae_sqr(t-xi, _state); - s0 = (t-xk)/(t-xi); - s1 = (xk-xi)/vv; - s2 = -2*(xk-xi)/(vv*(t-xi)); - } - else - { - s0 = (double)(1); - s1 = (double)(0); - s2 = (double)(0); - } - vv = b->w.ptr.p_double[i]*b->y.ptr.p_double[i]; - n0 = n0+s0*vv; - n1 = n1+s1*vv; - n2 = n2+s2*vv; - vv = b->w.ptr.p_double[i]; - d0 = d0+s0*vv; - d1 = d1+s1*vv; - d2 = d2+s2*vv; - } - *f = b->sy*n0/d0; - *df = b->sy*(n1*d0-n0*d1)/ae_sqr(d0, _state); - *d2f = b->sy*((n2*d0-n0*d2)*ae_sqr(d0, _state)-(n1*d0-n0*d1)*2*d0*d1)/ae_sqr(ae_sqr(d0, _state), _state); -} - - -/************************************************************************* -This subroutine performs linear transformation of the argument. - -INPUT PARAMETERS: - B - rational interpolant in barycentric form - CA, CB - transformation coefficients: x = CA*t + CB - -OUTPUT PARAMETERS: - B - transformed interpolant with X replaced by T - - -- ALGLIB PROJECT -- - Copyright 19.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentriclintransx(barycentricinterpolant* b, - double ca, - double cb, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - - - - /* - * special case, replace by constant F(CB) - */ - if( ae_fp_eq(ca,(double)(0)) ) - { - b->sy = barycentriccalc(b, cb, _state); - v = (double)(1); - for(i=0; i<=b->n-1; i++) - { - b->y.ptr.p_double[i] = (double)(1); - b->w.ptr.p_double[i] = v; - v = -v; - } - return; - } - - /* - * general case: CA<>0 - */ - for(i=0; i<=b->n-1; i++) - { - b->x.ptr.p_double[i] = (b->x.ptr.p_double[i]-cb)/ca; - } - if( ae_fp_less(ca,(double)(0)) ) - { - for(i=0; i<=b->n-1; i++) - { - if( in-1-i ) - { - j = b->n-1-i; - v = b->x.ptr.p_double[i]; - b->x.ptr.p_double[i] = b->x.ptr.p_double[j]; - b->x.ptr.p_double[j] = v; - v = b->y.ptr.p_double[i]; - b->y.ptr.p_double[i] = b->y.ptr.p_double[j]; - b->y.ptr.p_double[j] = v; - v = b->w.ptr.p_double[i]; - b->w.ptr.p_double[i] = b->w.ptr.p_double[j]; - b->w.ptr.p_double[j] = v; - } - else - { - break; - } - } - } -} - - -/************************************************************************* -This subroutine performs linear transformation of the barycentric -interpolant. - -INPUT PARAMETERS: - B - rational interpolant in barycentric form - CA, CB - transformation coefficients: B2(x) = CA*B(x) + CB - -OUTPUT PARAMETERS: - B - transformed interpolant - - -- ALGLIB PROJECT -- - Copyright 19.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentriclintransy(barycentricinterpolant* b, - double ca, - double cb, - ae_state *_state) -{ - ae_int_t i; - double v; - - - for(i=0; i<=b->n-1; i++) - { - b->y.ptr.p_double[i] = ca*b->sy*b->y.ptr.p_double[i]+cb; - } - b->sy = (double)(0); - for(i=0; i<=b->n-1; i++) - { - b->sy = ae_maxreal(b->sy, ae_fabs(b->y.ptr.p_double[i], _state), _state); - } - if( ae_fp_greater(b->sy,(double)(0)) ) - { - v = 1/b->sy; - ae_v_muld(&b->y.ptr.p_double[0], 1, ae_v_len(0,b->n-1), v); - } -} - - -/************************************************************************* -Extracts X/Y/W arrays from rational interpolant - -INPUT PARAMETERS: - B - barycentric interpolant - -OUTPUT PARAMETERS: - N - nodes count, N>0 - X - interpolation nodes, array[0..N-1] - F - function values, array[0..N-1] - W - barycentric weights, array[0..N-1] - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentricunpack(barycentricinterpolant* b, - ae_int_t* n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_state *_state) -{ - double v; - - *n = 0; - ae_vector_clear(x); - ae_vector_clear(y); - ae_vector_clear(w); - - *n = b->n; - ae_vector_set_length(x, *n, _state); - ae_vector_set_length(y, *n, _state); - ae_vector_set_length(w, *n, _state); - v = b->sy; - ae_v_move(&x->ptr.p_double[0], 1, &b->x.ptr.p_double[0], 1, ae_v_len(0,*n-1)); - ae_v_moved(&y->ptr.p_double[0], 1, &b->y.ptr.p_double[0], 1, ae_v_len(0,*n-1), v); - ae_v_move(&w->ptr.p_double[0], 1, &b->w.ptr.p_double[0], 1, ae_v_len(0,*n-1)); -} - - -/************************************************************************* -Rational interpolant from X/Y/W arrays - -F(t) = SUM(i=0,n-1,w[i]*f[i]/(t-x[i])) / SUM(i=0,n-1,w[i]/(t-x[i])) - -INPUT PARAMETERS: - X - interpolation nodes, array[0..N-1] - F - function values, array[0..N-1] - W - barycentric weights, array[0..N-1] - N - nodes count, N>0 - -OUTPUT PARAMETERS: - B - barycentric interpolant built from (X, Y, W) - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentricbuildxyw(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_int_t n, - barycentricinterpolant* b, - ae_state *_state) -{ - - _barycentricinterpolant_clear(b); - - ae_assert(n>0, "BarycentricBuildXYW: incorrect N!", _state); - - /* - * fill X/Y/W - */ - ae_vector_set_length(&b->x, n, _state); - ae_vector_set_length(&b->y, n, _state); - ae_vector_set_length(&b->w, n, _state); - ae_v_move(&b->x.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&b->y.ptr.p_double[0], 1, &y->ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&b->w.ptr.p_double[0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,n-1)); - b->n = n; - - /* - * Normalize - */ - ratint_barycentricnormalize(b, _state); -} - - -/************************************************************************* -Rational interpolant without poles - -The subroutine constructs the rational interpolating function without real -poles (see 'Barycentric rational interpolation with no poles and high -rates of approximation', Michael S. Floater. and Kai Hormann, for more -information on this subject). - -Input parameters: - X - interpolation nodes, array[0..N-1]. - Y - function values, array[0..N-1]. - N - number of nodes, N>0. - D - order of the interpolation scheme, 0 <= D <= N-1. - D<0 will cause an error. - D>=N it will be replaced with D=N-1. - if you don't know what D to choose, use small value about 3-5. - -Output parameters: - B - barycentric interpolant. - -Note: - this algorithm always succeeds and calculates the weights with close - to machine precision. - - -- ALGLIB PROJECT -- - Copyright 17.06.2007 by Bochkanov Sergey -*************************************************************************/ -void barycentricbuildfloaterhormann(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t d, - barycentricinterpolant* b, - ae_state *_state) -{ - ae_frame _frame_block; - double s0; - double s; - double v; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_vector perm; - ae_vector wtemp; - ae_vector sortrbuf; - ae_vector sortrbuf2; - - ae_frame_make(_state, &_frame_block); - memset(&perm, 0, sizeof(perm)); - memset(&wtemp, 0, sizeof(wtemp)); - memset(&sortrbuf, 0, sizeof(sortrbuf)); - memset(&sortrbuf2, 0, sizeof(sortrbuf2)); - _barycentricinterpolant_clear(b); - ae_vector_init(&perm, 0, DT_INT, _state, ae_true); - ae_vector_init(&wtemp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sortrbuf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sortrbuf2, 0, DT_REAL, _state, ae_true); - - ae_assert(n>0, "BarycentricFloaterHormann: N<=0!", _state); - ae_assert(d>=0, "BarycentricFloaterHormann: incorrect D!", _state); - - /* - * Prepare - */ - if( d>n-1 ) - { - d = n-1; - } - b->n = n; - - /* - * special case: N=1 - */ - if( n==1 ) - { - ae_vector_set_length(&b->x, n, _state); - ae_vector_set_length(&b->y, n, _state); - ae_vector_set_length(&b->w, n, _state); - b->x.ptr.p_double[0] = x->ptr.p_double[0]; - b->y.ptr.p_double[0] = y->ptr.p_double[0]; - b->w.ptr.p_double[0] = (double)(1); - ratint_barycentricnormalize(b, _state); - ae_frame_leave(_state); - return; - } - - /* - * Fill X/Y - */ - ae_vector_set_length(&b->x, n, _state); - ae_vector_set_length(&b->y, n, _state); - ae_v_move(&b->x.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&b->y.ptr.p_double[0], 1, &y->ptr.p_double[0], 1, ae_v_len(0,n-1)); - tagsortfastr(&b->x, &b->y, &sortrbuf, &sortrbuf2, n, _state); - - /* - * Calculate Wk - */ - ae_vector_set_length(&b->w, n, _state); - s0 = (double)(1); - for(k=1; k<=d; k++) - { - s0 = -s0; - } - for(k=0; k<=n-1; k++) - { - - /* - * Wk - */ - s = (double)(0); - for(i=ae_maxint(k-d, 0, _state); i<=ae_minint(k, n-1-d, _state); i++) - { - v = (double)(1); - for(j=i; j<=i+d; j++) - { - if( j!=k ) - { - v = v/ae_fabs(b->x.ptr.p_double[k]-b->x.ptr.p_double[j], _state); - } - } - s = s+v; - } - b->w.ptr.p_double[k] = s0*s; - - /* - * Next S0 - */ - s0 = -s0; - } - - /* - * Normalize - */ - ratint_barycentricnormalize(b, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Copying of the barycentric interpolant (for internal use only) - -INPUT PARAMETERS: - B - barycentric interpolant - -OUTPUT PARAMETERS: - B2 - copy(B1) - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentriccopy(barycentricinterpolant* b, - barycentricinterpolant* b2, - ae_state *_state) -{ - - _barycentricinterpolant_clear(b2); - - b2->n = b->n; - b2->sy = b->sy; - ae_vector_set_length(&b2->x, b2->n, _state); - ae_vector_set_length(&b2->y, b2->n, _state); - ae_vector_set_length(&b2->w, b2->n, _state); - ae_v_move(&b2->x.ptr.p_double[0], 1, &b->x.ptr.p_double[0], 1, ae_v_len(0,b2->n-1)); - ae_v_move(&b2->y.ptr.p_double[0], 1, &b->y.ptr.p_double[0], 1, ae_v_len(0,b2->n-1)); - ae_v_move(&b2->w.ptr.p_double[0], 1, &b->w.ptr.p_double[0], 1, ae_v_len(0,b2->n-1)); -} - - -/************************************************************************* -Normalization of barycentric interpolant: -* B.N, B.X, B.Y and B.W are initialized -* B.SY is NOT initialized -* Y[] is normalized, scaling coefficient is stored in B.SY -* W[] is normalized, no scaling coefficient is stored -* X[] is sorted - -Internal subroutine. -*************************************************************************/ -static void ratint_barycentricnormalize(barycentricinterpolant* b, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector p1; - ae_vector p2; - ae_int_t i; - ae_int_t j; - ae_int_t j2; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&p1, 0, sizeof(p1)); - memset(&p2, 0, sizeof(p2)); - ae_vector_init(&p1, 0, DT_INT, _state, ae_true); - ae_vector_init(&p2, 0, DT_INT, _state, ae_true); - - - /* - * Normalize task: |Y|<=1, |W|<=1, sort X[] - */ - b->sy = (double)(0); - for(i=0; i<=b->n-1; i++) - { - b->sy = ae_maxreal(b->sy, ae_fabs(b->y.ptr.p_double[i], _state), _state); - } - if( ae_fp_greater(b->sy,(double)(0))&&ae_fp_greater(ae_fabs(b->sy-1, _state),10*ae_machineepsilon) ) - { - v = 1/b->sy; - ae_v_muld(&b->y.ptr.p_double[0], 1, ae_v_len(0,b->n-1), v); - } - v = (double)(0); - for(i=0; i<=b->n-1; i++) - { - v = ae_maxreal(v, ae_fabs(b->w.ptr.p_double[i], _state), _state); - } - if( ae_fp_greater(v,(double)(0))&&ae_fp_greater(ae_fabs(v-1, _state),10*ae_machineepsilon) ) - { - v = 1/v; - ae_v_muld(&b->w.ptr.p_double[0], 1, ae_v_len(0,b->n-1), v); - } - for(i=0; i<=b->n-2; i++) - { - if( ae_fp_less(b->x.ptr.p_double[i+1],b->x.ptr.p_double[i]) ) - { - tagsort(&b->x, b->n, &p1, &p2, _state); - for(j=0; j<=b->n-1; j++) - { - j2 = p2.ptr.p_int[j]; - v = b->y.ptr.p_double[j]; - b->y.ptr.p_double[j] = b->y.ptr.p_double[j2]; - b->y.ptr.p_double[j2] = v; - v = b->w.ptr.p_double[j]; - b->w.ptr.p_double[j] = b->w.ptr.p_double[j2]; - b->w.ptr.p_double[j2] = v; - } - break; - } - } - ae_frame_leave(_state); -} - - -void _barycentricinterpolant_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - barycentricinterpolant *p = (barycentricinterpolant*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->w, 0, DT_REAL, _state, make_automatic); -} - - -void _barycentricinterpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - barycentricinterpolant *dst = (barycentricinterpolant*)_dst; - barycentricinterpolant *src = (barycentricinterpolant*)_src; - dst->n = src->n; - dst->sy = src->sy; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic); - ae_vector_init_copy(&dst->w, &src->w, _state, make_automatic); -} - - -void _barycentricinterpolant_clear(void* _p) -{ - barycentricinterpolant *p = (barycentricinterpolant*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->x); - ae_vector_clear(&p->y); - ae_vector_clear(&p->w); -} - - -void _barycentricinterpolant_destroy(void* _p) -{ - barycentricinterpolant *p = (barycentricinterpolant*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->y); - ae_vector_destroy(&p->w); -} - - -#endif -#if defined(AE_COMPILE_FITSPHERE) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Fits least squares (LS) circle (or NX-dimensional sphere) to data (a set -of points in NX-dimensional space). - -Least squares circle minimizes sum of squared deviations between distances -from points to the center and some "candidate" radius, which is also -fitted to the data. - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - -OUTPUT PARAMETERS: - CX - central point for a sphere - R - radius - - -- ALGLIB -- - Copyright 07.05.2018 by Bochkanov Sergey -*************************************************************************/ -void fitspherels(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - /* Real */ ae_vector* cx, - double* r, - ae_state *_state) -{ - double dummy; - - ae_vector_clear(cx); - *r = 0; - - fitspherex(xy, npoints, nx, 0, 0.0, 0, 0.0, cx, &dummy, r, _state); -} - - -/************************************************************************* -Fits minimum circumscribed (MC) circle (or NX-dimensional sphere) to data -(a set of points in NX-dimensional space). - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - -OUTPUT PARAMETERS: - CX - central point for a sphere - RHi - radius - -NOTE: this function is an easy-to-use wrapper around more powerful "expert" - function fitspherex(). - - This wrapper is optimized for ease of use and stability - at the - cost of somewhat lower performance (we have to use very tight - stopping criteria for inner optimizer because we want to make sure - that it will converge on any dataset). - - If you are ready to experiment with settings of "expert" function, - you can achieve ~2-4x speedup over standard "bulletproof" settings. - - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void fitspheremc(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - /* Real */ ae_vector* cx, - double* rhi, - ae_state *_state) -{ - double dummy; - - ae_vector_clear(cx); - *rhi = 0; - - fitspherex(xy, npoints, nx, 1, 0.0, 0, 0.0, cx, &dummy, rhi, _state); -} - - -/************************************************************************* -Fits maximum inscribed circle (or NX-dimensional sphere) to data (a set of -points in NX-dimensional space). - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - -OUTPUT PARAMETERS: - CX - central point for a sphere - RLo - radius - -NOTE: this function is an easy-to-use wrapper around more powerful "expert" - function fitspherex(). - - This wrapper is optimized for ease of use and stability - at the - cost of somewhat lower performance (we have to use very tight - stopping criteria for inner optimizer because we want to make sure - that it will converge on any dataset). - - If you are ready to experiment with settings of "expert" function, - you can achieve ~2-4x speedup over standard "bulletproof" settings. - - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void fitspheremi(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - /* Real */ ae_vector* cx, - double* rlo, - ae_state *_state) -{ - double dummy; - - ae_vector_clear(cx); - *rlo = 0; - - fitspherex(xy, npoints, nx, 2, 0.0, 0, 0.0, cx, rlo, &dummy, _state); -} - - -/************************************************************************* -Fits minimum zone circle (or NX-dimensional sphere) to data (a set of -points in NX-dimensional space). - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - -OUTPUT PARAMETERS: - CX - central point for a sphere - RLo - radius of inscribed circle - RHo - radius of circumscribed circle - -NOTE: this function is an easy-to-use wrapper around more powerful "expert" - function fitspherex(). - - This wrapper is optimized for ease of use and stability - at the - cost of somewhat lower performance (we have to use very tight - stopping criteria for inner optimizer because we want to make sure - that it will converge on any dataset). - - If you are ready to experiment with settings of "expert" function, - you can achieve ~2-4x speedup over standard "bulletproof" settings. - - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void fitspheremz(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - /* Real */ ae_vector* cx, - double* rlo, - double* rhi, - ae_state *_state) -{ - - ae_vector_clear(cx); - *rlo = 0; - *rhi = 0; - - fitspherex(xy, npoints, nx, 3, 0.0, 0, 0.0, cx, rlo, rhi, _state); -} - - -/************************************************************************* -Fitting minimum circumscribed, maximum inscribed or minimum zone circles -(or NX-dimensional spheres) to data (a set of points in NX-dimensional -space). - -This is expert function which allows to tweak many parameters of -underlying nonlinear solver: -* stopping criteria for inner iterations -* number of outer iterations -* penalty coefficient used to handle nonlinear constraints (we convert - unconstrained nonsmooth optimization problem ivolving max() and/or min() - operations to quadratically constrained smooth one). - -You may tweak all these parameters or only some of them, leaving other -ones at their default state - just specify zero value, and solver will -fill it with appropriate default one. - -These comments also include some discussion of approach used to handle -such unusual fitting problem, its stability, drawbacks of alternative -methods, and convergence properties. - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - ProblemType-used to encode problem type: - * 0 for least squares circle - * 1 for minimum circumscribed circle/sphere fitting (MC) - * 2 for maximum inscribed circle/sphere fitting (MI) - * 3 for minimum zone circle fitting (difference between - Rhi and Rlo is minimized), denoted as MZ - EpsX - stopping condition for NLC optimizer: - * must be non-negative - * use 0 to choose default value (1.0E-12 is used by default) - * you may specify larger values, up to 1.0E-6, if you want - to speed-up solver; NLC solver performs several - preconditioned outer iterations, so final result - typically has precision much better than EpsX. - AULIts - number of outer iterations performed by NLC optimizer: - * must be non-negative - * use 0 to choose default value (20 is used by default) - * you may specify values smaller than 20 if you want to - speed up solver; 10 often results in good combination of - precision and speed; sometimes you may get good results - with just 6 outer iterations. - Ignored for ProblemType=0. - Penalty - penalty coefficient for NLC optimizer: - * must be non-negative - * use 0 to choose default value (1.0E6 in current version) - * it should be really large, 1.0E6...1.0E7 is a good value - to start from; - * generally, default value is good enough - Ignored for ProblemType=0. - -OUTPUT PARAMETERS: - CX - central point for a sphere - RLo - radius: - * for ProblemType=2,3, radius of the inscribed sphere - * for ProblemType=0 - radius of the least squares sphere - * for ProblemType=1 - zero - RHo - radius: - * for ProblemType=1,3, radius of the circumscribed sphere - * for ProblemType=0 - radius of the least squares sphere - * for ProblemType=2 - zero - -NOTE: ON THE UNIQUENESS OF SOLUTIONS - -ALGLIB provides solution to several related circle fitting problems: MC -(minimum circumscribed), MI (maximum inscribed) and MZ (minimum zone) -fitting, LS (least squares) fitting. - -It is important to note that among these problems only MC and LS are -convex and have unique solution independently from starting point. - -As for MI, it may (or may not, depending on dataset properties) have -multiple solutions, and it always has one degenerate solution C=infinity -which corresponds to infinitely large radius. Thus, there are no guarantees -that solution to MI returned by this solver will be the best one (and no -one can provide you with such guarantee because problem is NP-hard). The -only guarantee you have is that this solution is locally optimal, i.e. it -can not be improved by infinitesimally small tweaks in the parameters. - -It is also possible to "run away" to infinity when started from bad -initial point located outside of point cloud (or when point cloud does not -span entire circumference/surface of the sphere). - -Finally, MZ (minimum zone circle) stands somewhere between MC and MI in -stability. It is somewhat regularized by "circumscribed" term of the merit -function; however, solutions to MZ may be non-unique, and in some unlucky -cases it is also possible to "run away to infinity". - - -NOTE: ON THE NONLINEARLY CONSTRAINED PROGRAMMING APPROACH - -The problem formulation for MC (minimum circumscribed circle; for the -sake of simplicity we omit MZ and MI here) is: - - [ [ ]2 ] - min [ max [ XY[i]-C ] ] - C [ i [ ] ] - -i.e. it is unconstrained nonsmooth optimization problem of finding "best" -central point, with radius R being unambiguously determined from C. In -order to move away from non-smoothness we use following reformulation: - - [ ] [ ]2 - min [ R ] subject to R>=0, [ XY[i]-C ] <= R^2 - C,R [ ] [ ] - -i.e. it becomes smooth quadratically constrained optimization problem with -linear target function. Such problem statement is 100% equivalent to the -original nonsmooth one, but much easier to approach. We solve it with -MinNLC solver provided by ALGLIB. - - -NOTE: ON INSTABILITY OF SEQUENTIAL LINEARIZATION APPROACH - -ALGLIB has nonlinearly constrained solver which proved to be stable on -such problems. However, some authors proposed to linearize constraints in -the vicinity of current approximation (Ci,Ri) and to get next approximate -solution (Ci+1,Ri+1) as solution to linear programming problem. Obviously, -LP problems are easier than nonlinearly constrained ones. - -Indeed, such approach to MC/MI/MZ resulted in ~10-20x increase in -performance (when compared with NLC solver). However, it turned out that -in some cases linearized model fails to predict correct direction for next -step and tells us that we converged to solution even when we are still 2-4 -digits of precision away from it. - -It is important that it is not failure of LP solver - it is failure of the -linear model; even when solved exactly, it fails to handle subtle -nonlinearities which arise near the solution. We validated it by comparing -results returned by ALGLIB linear solver with that of MATLAB. - -In our experiments with linearization: -* MC failed most often, at both realistic and synthetic datasets -* MI sometimes failed, but sometimes succeeded -* MZ often succeeded; our guess is that presence of two independent sets - of constraints (one set for Rlo and another one for Rhi) and two terms - in the target function (Rlo and Rhi) regularizes task, so when linear - model fails to handle nonlinearities from Rlo, it uses Rhi as a hint - (and vice versa). - -Because linearization approach failed to achieve stable results, we do not -include it in ALGLIB. - - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void fitspherex(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - ae_int_t problemtype, - double epsx, - ae_int_t aulits, - double penalty, - /* Real */ ae_vector* cx, - double* rlo, - double* rhi, - ae_state *_state) -{ - ae_frame _frame_block; - fitsphereinternalreport rep; - - ae_frame_make(_state, &_frame_block); - memset(&rep, 0, sizeof(rep)); - ae_vector_clear(cx); - *rlo = 0; - *rhi = 0; - _fitsphereinternalreport_init(&rep, _state, ae_true); - - ae_assert(ae_isfinite(penalty, _state)&&ae_fp_greater_eq(penalty,(double)(0)), "FitSphereX: Penalty<0 or is not finite", _state); - ae_assert(ae_isfinite(epsx, _state)&&ae_fp_greater_eq(epsx,(double)(0)), "FitSphereX: EpsX<0 or is not finite", _state); - ae_assert(aulits>=0, "FitSphereX: AULIts<0", _state); - fitsphereinternal(xy, npoints, nx, problemtype, 0, epsx, aulits, penalty, cx, rlo, rhi, &rep, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Fitting minimum circumscribed, maximum inscribed or minimum zone circles -(or NX-dimensional spheres) to data (a set of points in NX-dimensional -space). - -Internal computational function. - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - ProblemType-used to encode problem type: - * 0 for least squares circle - * 1 for minimum circumscribed circle/sphere fitting (MC) - * 2 for maximum inscribed circle/sphere fitting (MI) - * 3 for minimum zone circle fitting (difference between - Rhi and Rlo is minimized), denoted as MZ - SolverType- solver to use: - * 0 use best solver available (1 in current version) - * 1 use nonlinearly constrained optimization approach, AUL - (it is roughly 10-20 times slower than SPC-LIN, but - much more stable) - * 2 use special fast IMPRECISE solver, SPC-LIN sequential - linearization approach; SPC-LIN is fast, but sometimes - fails to converge with more than 3 digits of precision; - see comments below. - NOT RECOMMENDED UNLESS YOU REALLY NEED HIGH PERFORMANCE - AT THE COST OF SOME PRECISION. - * 3 use nonlinearly constrained optimization approach, SLP - (most robust one, but somewhat slower than AUL) - Ignored for ProblemType=0. - EpsX - stopping criteria for SLP and NLC optimizers: - * must be non-negative - * use 0 to choose default value (1.0E-12 is used by default) - * if you use SLP solver, you should use default values - * if you use NLC solver, you may specify larger values, up - to 1.0E-6, if you want to speed-up solver; NLC solver - performs several preconditioned outer iterations, so final - result typically has precision much better than EpsX. - AULIts - number of iterations performed by NLC optimizer: - * must be non-negative - * use 0 to choose default value (20 is used by default) - * you may specify values smaller than 20 if you want to - speed up solver; 10 often results in good combination of - precision and speed - Ignored for ProblemType=0. - Penalty - penalty coefficient for NLC optimizer (ignored for SLP): - * must be non-negative - * use 0 to choose default value (1.0E6 in current version) - * it should be really large, 1.0E6...1.0E7 is a good value - to start from; - * generally, default value is good enough - * ignored by SLP optimizer - Ignored for ProblemType=0. - -OUTPUT PARAMETERS: - CX - central point for a sphere - RLo - radius: - * for ProblemType=2,3, radius of the inscribed sphere - * for ProblemType=0 - radius of the least squares sphere - * for ProblemType=1 - zero - RHo - radius: - * for ProblemType=1,3, radius of the circumscribed sphere - * for ProblemType=0 - radius of the least squares sphere - * for ProblemType=2 - zero - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void fitsphereinternal(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - ae_int_t problemtype, - ae_int_t solvertype, - double epsx, - ae_int_t aulits, - double penalty, - /* Real */ ae_vector* cx, - double* rlo, - double* rhi, - fitsphereinternalreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - double v; - double vv; - ae_int_t cpr; - ae_bool userlo; - ae_bool userhi; - double vlo; - double vhi; - ae_vector vmin; - ae_vector vmax; - double spread; - ae_vector pcr; - ae_vector scr; - ae_vector bl; - ae_vector bu; - ae_int_t suboffset; - ae_int_t dstrow; - minnlcstate nlcstate; - minnlcreport nlcrep; - ae_matrix cmatrix; - ae_vector ct; - ae_int_t outeridx; - ae_int_t maxouterits; - ae_int_t maxits; - double safeguard; - double bi; - minbleicstate blcstate; - minbleicreport blcrep; - ae_vector prevc; - minlmstate lmstate; - minlmreport lmrep; - - ae_frame_make(_state, &_frame_block); - memset(&vmin, 0, sizeof(vmin)); - memset(&vmax, 0, sizeof(vmax)); - memset(&pcr, 0, sizeof(pcr)); - memset(&scr, 0, sizeof(scr)); - memset(&bl, 0, sizeof(bl)); - memset(&bu, 0, sizeof(bu)); - memset(&nlcstate, 0, sizeof(nlcstate)); - memset(&nlcrep, 0, sizeof(nlcrep)); - memset(&cmatrix, 0, sizeof(cmatrix)); - memset(&ct, 0, sizeof(ct)); - memset(&blcstate, 0, sizeof(blcstate)); - memset(&blcrep, 0, sizeof(blcrep)); - memset(&prevc, 0, sizeof(prevc)); - memset(&lmstate, 0, sizeof(lmstate)); - memset(&lmrep, 0, sizeof(lmrep)); - ae_vector_clear(cx); - *rlo = 0; - *rhi = 0; - _fitsphereinternalreport_clear(rep); - ae_vector_init(&vmin, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vmax, 0, DT_REAL, _state, ae_true); - ae_vector_init(&pcr, 0, DT_REAL, _state, ae_true); - ae_vector_init(&scr, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bu, 0, DT_REAL, _state, ae_true); - _minnlcstate_init(&nlcstate, _state, ae_true); - _minnlcreport_init(&nlcrep, _state, ae_true); - ae_matrix_init(&cmatrix, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - _minbleicstate_init(&blcstate, _state, ae_true); - _minbleicreport_init(&blcrep, _state, ae_true); - ae_vector_init(&prevc, 0, DT_REAL, _state, ae_true); - _minlmstate_init(&lmstate, _state, ae_true); - _minlmreport_init(&lmrep, _state, ae_true); - - - /* - * Check input parameters - */ - ae_assert(npoints>0, "FitSphereX: NPoints<=0", _state); - ae_assert(nx>0, "FitSphereX: NX<=0", _state); - ae_assert(apservisfinitematrix(xy, npoints, nx, _state), "FitSphereX: XY contains infinite or NAN values", _state); - ae_assert(problemtype>=0&&problemtype<=3, "FitSphereX: ProblemType is neither 0, 1, 2 or 3", _state); - ae_assert(solvertype>=0&&solvertype<=3, "FitSphereX: ProblemType is neither 1, 2 or 3", _state); - ae_assert(ae_isfinite(penalty, _state)&&ae_fp_greater_eq(penalty,(double)(0)), "FitSphereX: Penalty<0 or is not finite", _state); - ae_assert(ae_isfinite(epsx, _state)&&ae_fp_greater_eq(epsx,(double)(0)), "FitSphereX: EpsX<0 or is not finite", _state); - ae_assert(aulits>=0, "FitSphereX: AULIts<0", _state); - if( solvertype==0 ) - { - solvertype = 1; - } - if( ae_fp_eq(penalty,(double)(0)) ) - { - penalty = 1.0E6; - } - if( ae_fp_eq(epsx,(double)(0)) ) - { - epsx = 1.0E-12; - } - if( aulits==0 ) - { - aulits = 20; - } - safeguard = (double)(10); - maxouterits = 10; - maxits = 10000; - rep->nfev = 0; - rep->iterationscount = 0; - - /* - * Determine initial values, initial estimates and spread of the points - */ - ae_vector_set_length(&vmin, nx, _state); - ae_vector_set_length(&vmax, nx, _state); - ae_vector_set_length(cx, nx, _state); - for(j=0; j<=nx-1; j++) - { - vmin.ptr.p_double[j] = xy->ptr.pp_double[0][j]; - vmax.ptr.p_double[j] = xy->ptr.pp_double[0][j]; - cx->ptr.p_double[j] = (double)(0); - } - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nx-1; j++) - { - cx->ptr.p_double[j] = cx->ptr.p_double[j]+xy->ptr.pp_double[i][j]; - vmin.ptr.p_double[j] = ae_minreal(vmin.ptr.p_double[j], xy->ptr.pp_double[i][j], _state); - vmax.ptr.p_double[j] = ae_maxreal(vmax.ptr.p_double[j], xy->ptr.pp_double[i][j], _state); - } - } - spread = (double)(0); - for(j=0; j<=nx-1; j++) - { - cx->ptr.p_double[j] = cx->ptr.p_double[j]/npoints; - spread = ae_maxreal(spread, vmax.ptr.p_double[j]-vmin.ptr.p_double[j], _state); - } - *rlo = ae_maxrealnumber; - *rhi = (double)(0); - for(i=0; i<=npoints-1; i++) - { - v = (double)(0); - for(j=0; j<=nx-1; j++) - { - v = v+ae_sqr(xy->ptr.pp_double[i][j]-cx->ptr.p_double[j], _state); - } - v = ae_sqrt(v, _state); - *rhi = ae_maxreal(*rhi, v, _state); - *rlo = ae_minreal(*rlo, v, _state); - } - - /* - * Handle degenerate case of zero spread - */ - if( ae_fp_eq(spread,(double)(0)) ) - { - for(j=0; j<=nx-1; j++) - { - cx->ptr.p_double[j] = vmin.ptr.p_double[j]; - } - *rhi = (double)(0); - *rlo = (double)(0); - ae_frame_leave(_state); - return; - } - - /* - * Prepare initial point for optimizer, scale vector and box constraints - */ - ae_vector_set_length(&pcr, nx+2, _state); - ae_vector_set_length(&scr, nx+2, _state); - ae_vector_set_length(&bl, nx+2, _state); - ae_vector_set_length(&bu, nx+2, _state); - for(j=0; j<=nx-1; j++) - { - pcr.ptr.p_double[j] = cx->ptr.p_double[j]; - scr.ptr.p_double[j] = 0.1*spread; - bl.ptr.p_double[j] = cx->ptr.p_double[j]-safeguard*spread; - bu.ptr.p_double[j] = cx->ptr.p_double[j]+safeguard*spread; - } - pcr.ptr.p_double[nx+0] = *rlo; - pcr.ptr.p_double[nx+1] = *rhi; - scr.ptr.p_double[nx+0] = 0.5*spread; - scr.ptr.p_double[nx+1] = 0.5*spread; - bl.ptr.p_double[nx+0] = (double)(0); - bl.ptr.p_double[nx+1] = (double)(0); - bu.ptr.p_double[nx+0] = safeguard*(*rhi); - bu.ptr.p_double[nx+1] = safeguard*(*rhi); - - /* - * First branch: least squares fitting vs MI/MC/MZ fitting - */ - if( problemtype==0 ) - { - - /* - * Solve problem with Levenberg-Marquardt algorithm - */ - pcr.ptr.p_double[nx] = *rhi; - minlmcreatevj(nx+1, npoints, &pcr, &lmstate, _state); - minlmsetscale(&lmstate, &scr, _state); - minlmsetbc(&lmstate, &bl, &bu, _state); - minlmsetcond(&lmstate, epsx, maxits, _state); - while(minlmiteration(&lmstate, _state)) - { - if( lmstate.needfij||lmstate.needfi ) - { - inc(&rep->nfev, _state); - for(i=0; i<=npoints-1; i++) - { - v = (double)(0); - for(j=0; j<=nx-1; j++) - { - v = v+ae_sqr(lmstate.x.ptr.p_double[j]-xy->ptr.pp_double[i][j], _state); - } - lmstate.fi.ptr.p_double[i] = ae_sqrt(v, _state)-lmstate.x.ptr.p_double[nx]; - if( lmstate.needfij ) - { - for(j=0; j<=nx-1; j++) - { - lmstate.j.ptr.pp_double[i][j] = 0.5/(1.0E-9*spread+ae_sqrt(v, _state))*2*(lmstate.x.ptr.p_double[j]-xy->ptr.pp_double[i][j]); - } - lmstate.j.ptr.pp_double[i][nx] = (double)(-1); - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minlmresults(&lmstate, &pcr, &lmrep, _state); - ae_assert(lmrep.terminationtype>0, "FitSphereX: unexpected failure of LM solver", _state); - rep->iterationscount = rep->iterationscount+lmrep.iterationscount; - - /* - * Offload center coordinates from PCR to CX, - * re-calculate exact value of RLo/RHi using CX. - */ - for(j=0; j<=nx-1; j++) - { - cx->ptr.p_double[j] = pcr.ptr.p_double[j]; - } - vv = (double)(0); - for(i=0; i<=npoints-1; i++) - { - v = (double)(0); - for(j=0; j<=nx-1; j++) - { - v = v+ae_sqr(xy->ptr.pp_double[i][j]-cx->ptr.p_double[j], _state); - } - v = ae_sqrt(v, _state); - vv = vv+v/npoints; - } - *rlo = vv; - *rhi = vv; - } - else - { - - /* - * MI, MC, MZ fitting. - * Prepare problem metrics - */ - userlo = problemtype==2||problemtype==3; - userhi = problemtype==1||problemtype==3; - if( userlo&&userhi ) - { - cpr = 2; - } - else - { - cpr = 1; - } - if( userlo ) - { - vlo = (double)(1); - } - else - { - vlo = (double)(0); - } - if( userhi ) - { - vhi = (double)(1); - } - else - { - vhi = (double)(0); - } - - /* - * Solve with NLC solver; problem is treated as general nonlinearly constrained - * programming, with augmented Lagrangian solver or SLP being used. - */ - if( solvertype==1||solvertype==3 ) - { - minnlccreate(nx+2, &pcr, &nlcstate, _state); - minnlcsetscale(&nlcstate, &scr, _state); - minnlcsetbc(&nlcstate, &bl, &bu, _state); - minnlcsetnlc(&nlcstate, 0, cpr*npoints, _state); - minnlcsetcond(&nlcstate, epsx, maxits, _state); - minnlcsetprecexactrobust(&nlcstate, 5, _state); - minnlcsetstpmax(&nlcstate, 0.1, _state); - if( solvertype==1 ) - { - minnlcsetalgoaul(&nlcstate, penalty, aulits, _state); - } - else - { - minnlcsetalgoslp(&nlcstate, _state); - } - minnlcrestartfrom(&nlcstate, &pcr, _state); - while(minnlciteration(&nlcstate, _state)) - { - if( nlcstate.needfij ) - { - inc(&rep->nfev, _state); - nlcstate.fi.ptr.p_double[0] = vhi*nlcstate.x.ptr.p_double[nx+1]-vlo*nlcstate.x.ptr.p_double[nx+0]; - for(j=0; j<=nx-1; j++) - { - nlcstate.j.ptr.pp_double[0][j] = (double)(0); - } - nlcstate.j.ptr.pp_double[0][nx+0] = -1*vlo; - nlcstate.j.ptr.pp_double[0][nx+1] = 1*vhi; - for(i=0; i<=npoints-1; i++) - { - suboffset = 0; - if( userhi ) - { - dstrow = 1+cpr*i+suboffset; - v = (double)(0); - for(j=0; j<=nx-1; j++) - { - vv = nlcstate.x.ptr.p_double[j]-xy->ptr.pp_double[i][j]; - v = v+vv*vv; - nlcstate.j.ptr.pp_double[dstrow][j] = 2*vv; - } - vv = nlcstate.x.ptr.p_double[nx+1]; - v = v-vv*vv; - nlcstate.j.ptr.pp_double[dstrow][nx+0] = (double)(0); - nlcstate.j.ptr.pp_double[dstrow][nx+1] = -2*vv; - nlcstate.fi.ptr.p_double[dstrow] = v; - inc(&suboffset, _state); - } - if( userlo ) - { - dstrow = 1+cpr*i+suboffset; - v = (double)(0); - for(j=0; j<=nx-1; j++) - { - vv = nlcstate.x.ptr.p_double[j]-xy->ptr.pp_double[i][j]; - v = v-vv*vv; - nlcstate.j.ptr.pp_double[dstrow][j] = -2*vv; - } - vv = nlcstate.x.ptr.p_double[nx+0]; - v = v+vv*vv; - nlcstate.j.ptr.pp_double[dstrow][nx+0] = 2*vv; - nlcstate.j.ptr.pp_double[dstrow][nx+1] = (double)(0); - nlcstate.fi.ptr.p_double[dstrow] = v; - inc(&suboffset, _state); - } - ae_assert(suboffset==cpr, "Assertion failed", _state); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&nlcstate, &pcr, &nlcrep, _state); - ae_assert(nlcrep.terminationtype>0, "FitSphereX: unexpected failure of NLC solver", _state); - rep->iterationscount = rep->iterationscount+nlcrep.iterationscount; - - /* - * Offload center coordinates from PCR to CX, - * re-calculate exact value of RLo/RHi using CX. - */ - for(j=0; j<=nx-1; j++) - { - cx->ptr.p_double[j] = pcr.ptr.p_double[j]; - } - *rlo = ae_maxrealnumber; - *rhi = (double)(0); - for(i=0; i<=npoints-1; i++) - { - v = (double)(0); - for(j=0; j<=nx-1; j++) - { - v = v+ae_sqr(xy->ptr.pp_double[i][j]-cx->ptr.p_double[j], _state); - } - v = ae_sqrt(v, _state); - *rhi = ae_maxreal(*rhi, v, _state); - *rlo = ae_minreal(*rlo, v, _state); - } - if( !userlo ) - { - *rlo = (double)(0); - } - if( !userhi ) - { - *rhi = (double)(0); - } - ae_frame_leave(_state); - return; - } - - /* - * Solve problem with SLP (sequential LP) approach; this approach - * is much faster than NLP, but often fails for MI and MC (for MZ - * it performs well enough). - * - * REFERENCE: "On a sequential linear programming approach to finding - * the smallest circumscribed, largest inscribed, and minimum - * zone circle or sphere", Helmuth Spath and G.A.Watson - */ - if( solvertype==2 ) - { - ae_matrix_set_length(&cmatrix, cpr*npoints, nx+3, _state); - ae_vector_set_length(&ct, cpr*npoints, _state); - ae_vector_set_length(&prevc, nx, _state); - minbleiccreate(nx+2, &pcr, &blcstate, _state); - minbleicsetscale(&blcstate, &scr, _state); - minbleicsetbc(&blcstate, &bl, &bu, _state); - minbleicsetcond(&blcstate, (double)(0), (double)(0), epsx, maxits, _state); - for(outeridx=0; outeridx<=maxouterits-1; outeridx++) - { - - /* - * Prepare initial point for algorithm; center coordinates at - * PCR are used to calculate RLo/RHi and update PCR with them. - */ - *rlo = ae_maxrealnumber; - *rhi = (double)(0); - for(i=0; i<=npoints-1; i++) - { - v = (double)(0); - for(j=0; j<=nx-1; j++) - { - v = v+ae_sqr(xy->ptr.pp_double[i][j]-pcr.ptr.p_double[j], _state); - } - v = ae_sqrt(v, _state); - *rhi = ae_maxreal(*rhi, v, _state); - *rlo = ae_minreal(*rlo, v, _state); - } - pcr.ptr.p_double[nx+0] = *rlo*0.99999; - pcr.ptr.p_double[nx+1] = *rhi/0.99999; - - /* - * Generate matrix of linear constraints - */ - for(i=0; i<=npoints-1; i++) - { - v = (double)(0); - for(j=0; j<=nx-1; j++) - { - v = v+ae_sqr(xy->ptr.pp_double[i][j], _state); - } - bi = -v/2; - suboffset = 0; - if( userhi ) - { - dstrow = cpr*i+suboffset; - for(j=0; j<=nx-1; j++) - { - cmatrix.ptr.pp_double[dstrow][j] = pcr.ptr.p_double[j]/2-xy->ptr.pp_double[i][j]; - } - cmatrix.ptr.pp_double[dstrow][nx+0] = (double)(0); - cmatrix.ptr.pp_double[dstrow][nx+1] = -*rhi/2; - cmatrix.ptr.pp_double[dstrow][nx+2] = bi; - ct.ptr.p_int[dstrow] = -1; - inc(&suboffset, _state); - } - if( userlo ) - { - dstrow = cpr*i+suboffset; - for(j=0; j<=nx-1; j++) - { - cmatrix.ptr.pp_double[dstrow][j] = -(pcr.ptr.p_double[j]/2-xy->ptr.pp_double[i][j]); - } - cmatrix.ptr.pp_double[dstrow][nx+0] = *rlo/2; - cmatrix.ptr.pp_double[dstrow][nx+1] = (double)(0); - cmatrix.ptr.pp_double[dstrow][nx+2] = -bi; - ct.ptr.p_int[dstrow] = -1; - inc(&suboffset, _state); - } - ae_assert(suboffset==cpr, "Assertion failed", _state); - } - - /* - * Solve LP subproblem with MinBLEIC - */ - for(j=0; j<=nx-1; j++) - { - prevc.ptr.p_double[j] = pcr.ptr.p_double[j]; - } - minbleicsetlc(&blcstate, &cmatrix, &ct, cpr*npoints, _state); - minbleicrestartfrom(&blcstate, &pcr, _state); - while(minbleiciteration(&blcstate, _state)) - { - if( blcstate.needfg ) - { - inc(&rep->nfev, _state); - blcstate.f = vhi*blcstate.x.ptr.p_double[nx+1]-vlo*blcstate.x.ptr.p_double[nx+0]; - for(j=0; j<=nx-1; j++) - { - blcstate.g.ptr.p_double[j] = (double)(0); - } - blcstate.g.ptr.p_double[nx+0] = -1*vlo; - blcstate.g.ptr.p_double[nx+1] = 1*vhi; - continue; - } - } - minbleicresults(&blcstate, &pcr, &blcrep, _state); - ae_assert(blcrep.terminationtype>0, "FitSphereX: unexpected failure of BLEIC solver", _state); - rep->iterationscount = rep->iterationscount+blcrep.iterationscount; - - /* - * Terminate iterations early if we converged - */ - v = (double)(0); - for(j=0; j<=nx-1; j++) - { - v = v+ae_sqr(prevc.ptr.p_double[j]-pcr.ptr.p_double[j], _state); - } - v = ae_sqrt(v, _state); - if( ae_fp_less_eq(v,epsx) ) - { - break; - } - } - - /* - * Offload center coordinates from PCR to CX, - * re-calculate exact value of RLo/RHi using CX. - */ - for(j=0; j<=nx-1; j++) - { - cx->ptr.p_double[j] = pcr.ptr.p_double[j]; - } - *rlo = ae_maxrealnumber; - *rhi = (double)(0); - for(i=0; i<=npoints-1; i++) - { - v = (double)(0); - for(j=0; j<=nx-1; j++) - { - v = v+ae_sqr(xy->ptr.pp_double[i][j]-cx->ptr.p_double[j], _state); - } - v = ae_sqrt(v, _state); - *rhi = ae_maxreal(*rhi, v, _state); - *rlo = ae_minreal(*rlo, v, _state); - } - if( !userlo ) - { - *rlo = (double)(0); - } - if( !userhi ) - { - *rhi = (double)(0); - } - ae_frame_leave(_state); - return; - } - - /* - * Oooops...! - */ - ae_assert(ae_false, "FitSphereX: integrity check failed", _state); - } - ae_frame_leave(_state); -} - - -void _fitsphereinternalreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - fitsphereinternalreport *p = (fitsphereinternalreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _fitsphereinternalreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - fitsphereinternalreport *dst = (fitsphereinternalreport*)_dst; - fitsphereinternalreport *src = (fitsphereinternalreport*)_src; - dst->nfev = src->nfev; - dst->iterationscount = src->iterationscount; -} - - -void _fitsphereinternalreport_clear(void* _p) -{ - fitsphereinternalreport *p = (fitsphereinternalreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _fitsphereinternalreport_destroy(void* _p) -{ - fitsphereinternalreport *p = (fitsphereinternalreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_INTFITSERV) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Internal subroutine: automatic scaling for LLS tasks. -NEVER CALL IT DIRECTLY! - -Maps abscissas to [-1,1], standartizes ordinates and correspondingly scales -constraints. It also scales weights so that max(W[i])=1 - -Transformations performed: -* X, XC [XA,XB] => [-1,+1] - transformation makes min(X)=-1, max(X)=+1 - -* Y [SA,SB] => [0,1] - transformation makes mean(Y)=0, stddev(Y)=1 - -* YC transformed accordingly to SA, SB, DC[I] - - -- ALGLIB PROJECT -- - Copyright 08.09.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitscalexy(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_int_t n, - /* Real */ ae_vector* xc, - /* Real */ ae_vector* yc, - /* Integer */ ae_vector* dc, - ae_int_t k, - double* xa, - double* xb, - double* sa, - double* sb, - /* Real */ ae_vector* xoriginal, - /* Real */ ae_vector* yoriginal, - ae_state *_state) -{ - double xmin; - double xmax; - ae_int_t i; - double mx; - - *xa = 0; - *xb = 0; - *sa = 0; - *sb = 0; - ae_vector_clear(xoriginal); - ae_vector_clear(yoriginal); - - ae_assert(n>=1, "LSFitScaleXY: incorrect N", _state); - ae_assert(k>=0, "LSFitScaleXY: incorrect K", _state); - xmin = x->ptr.p_double[0]; - xmax = x->ptr.p_double[0]; - for(i=1; i<=n-1; i++) - { - xmin = ae_minreal(xmin, x->ptr.p_double[i], _state); - xmax = ae_maxreal(xmax, x->ptr.p_double[i], _state); - } - for(i=0; i<=k-1; i++) - { - xmin = ae_minreal(xmin, xc->ptr.p_double[i], _state); - xmax = ae_maxreal(xmax, xc->ptr.p_double[i], _state); - } - if( ae_fp_eq(xmin,xmax) ) - { - if( ae_fp_eq(xmin,(double)(0)) ) - { - xmin = (double)(-1); - xmax = (double)(1); - } - else - { - if( ae_fp_greater(xmin,(double)(0)) ) - { - xmin = 0.5*xmin; - } - else - { - xmax = 0.5*xmax; - } - } - } - ae_vector_set_length(xoriginal, n, _state); - ae_v_move(&xoriginal->ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - *xa = xmin; - *xb = xmax; - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = 2*(x->ptr.p_double[i]-0.5*(*xa+(*xb)))/(*xb-(*xa)); - } - for(i=0; i<=k-1; i++) - { - ae_assert(dc->ptr.p_int[i]>=0, "LSFitScaleXY: internal error!", _state); - xc->ptr.p_double[i] = 2*(xc->ptr.p_double[i]-0.5*(*xa+(*xb)))/(*xb-(*xa)); - yc->ptr.p_double[i] = yc->ptr.p_double[i]*ae_pow(0.5*(*xb-(*xa)), (double)(dc->ptr.p_int[i]), _state); - } - ae_vector_set_length(yoriginal, n, _state); - ae_v_move(&yoriginal->ptr.p_double[0], 1, &y->ptr.p_double[0], 1, ae_v_len(0,n-1)); - *sa = (double)(0); - for(i=0; i<=n-1; i++) - { - *sa = *sa+y->ptr.p_double[i]; - } - *sa = *sa/n; - *sb = (double)(0); - for(i=0; i<=n-1; i++) - { - *sb = *sb+ae_sqr(y->ptr.p_double[i]-(*sa), _state); - } - *sb = ae_sqrt(*sb/n, _state)+(*sa); - if( ae_fp_eq(*sb,*sa) ) - { - *sb = 2*(*sa); - } - if( ae_fp_eq(*sb,*sa) ) - { - *sb = *sa+1; - } - for(i=0; i<=n-1; i++) - { - y->ptr.p_double[i] = (y->ptr.p_double[i]-(*sa))/(*sb-(*sa)); - } - for(i=0; i<=k-1; i++) - { - if( dc->ptr.p_int[i]==0 ) - { - yc->ptr.p_double[i] = (yc->ptr.p_double[i]-(*sa))/(*sb-(*sa)); - } - else - { - yc->ptr.p_double[i] = yc->ptr.p_double[i]/(*sb-(*sa)); - } - } - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - mx = ae_maxreal(mx, ae_fabs(w->ptr.p_double[i], _state), _state); - } - if( ae_fp_neq(mx,(double)(0)) ) - { - for(i=0; i<=n-1; i++) - { - w->ptr.p_double[i] = w->ptr.p_double[i]/mx; - } - } -} - - -void buildpriorterm(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - ae_int_t modeltype, - double priorval, - /* Real */ ae_matrix* v, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t j0; - ae_int_t j1; - double rj; - ae_matrix araw; - ae_matrix amod; - ae_matrix braw; - ae_vector tmp0; - double lambdareg; - ae_int_t rfsits; - - ae_frame_make(_state, &_frame_block); - memset(&araw, 0, sizeof(araw)); - memset(&amod, 0, sizeof(amod)); - memset(&braw, 0, sizeof(braw)); - memset(&tmp0, 0, sizeof(tmp0)); - ae_matrix_clear(v); - ae_matrix_init(&araw, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&amod, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&braw, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=0, "BuildPriorTerm: N<0", _state); - ae_assert(nx>0, "BuildPriorTerm: NX<=0", _state); - ae_assert(ny>0, "BuildPriorTerm: NY<=0", _state); - ae_matrix_set_length(v, ny, nx+1, _state); - for(i=0; i<=v->rows-1; i++) - { - for(j=0; j<=v->cols-1; j++) - { - v->ptr.pp_double[i][j] = (double)(0); - } - } - if( n==0 ) - { - if( modeltype==0 ) - { - for(i=0; i<=ny-1; i++) - { - v->ptr.pp_double[i][nx] = priorval; - } - ae_frame_leave(_state); - return; - } - if( modeltype==1 ) - { - ae_frame_leave(_state); - return; - } - if( modeltype==2 ) - { - ae_frame_leave(_state); - return; - } - if( modeltype==3 ) - { - ae_frame_leave(_state); - return; - } - ae_assert(ae_false, "BuildPriorTerm: unexpected model type", _state); - } - if( modeltype==0 ) - { - for(i=0; i<=ny-1; i++) - { - v->ptr.pp_double[i][nx] = priorval; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=ny-1; j++) - { - xy->ptr.pp_double[i][nx+j] = xy->ptr.pp_double[i][nx+j]-priorval; - } - } - ae_frame_leave(_state); - return; - } - if( modeltype==2 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=ny-1; j++) - { - v->ptr.pp_double[j][nx] = v->ptr.pp_double[j][nx]+xy->ptr.pp_double[i][nx+j]; - } - } - for(j=0; j<=ny-1; j++) - { - v->ptr.pp_double[j][nx] = v->ptr.pp_double[j][nx]/coalesce((double)(n), (double)(1), _state); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=ny-1; j++) - { - xy->ptr.pp_double[i][nx+j] = xy->ptr.pp_double[i][nx+j]-v->ptr.pp_double[j][nx]; - } - } - ae_frame_leave(_state); - return; - } - if( modeltype==3 ) - { - ae_frame_leave(_state); - return; - } - ae_assert(modeltype==1, "BuildPriorTerm: unexpected model type", _state); - lambdareg = 0.0; - ae_matrix_set_length(&araw, nx+1, nx+1, _state); - ae_matrix_set_length(&braw, nx+1, ny, _state); - ae_vector_set_length(&tmp0, nx+1, _state); - ae_matrix_set_length(&amod, nx+1, nx+1, _state); - for(i=0; i<=nx; i++) - { - for(j=0; j<=nx; j++) - { - araw.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - tmp0.ptr.p_double[j] = xy->ptr.pp_double[i][j]; - } - tmp0.ptr.p_double[nx] = 1.0; - for(j0=0; j0<=nx; j0++) - { - for(j1=0; j1<=nx; j1++) - { - araw.ptr.pp_double[j0][j1] = araw.ptr.pp_double[j0][j1]+tmp0.ptr.p_double[j0]*tmp0.ptr.p_double[j1]; - } - } - } - for(rfsits=1; rfsits<=3; rfsits++) - { - for(i=0; i<=nx; i++) - { - for(j=0; j<=ny-1; j++) - { - braw.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - tmp0.ptr.p_double[j] = xy->ptr.pp_double[i][j]; - } - tmp0.ptr.p_double[nx] = 1.0; - for(j=0; j<=ny-1; j++) - { - rj = xy->ptr.pp_double[i][nx+j]; - for(j0=0; j0<=nx; j0++) - { - rj = rj-tmp0.ptr.p_double[j0]*v->ptr.pp_double[j][j0]; - } - for(j0=0; j0<=nx; j0++) - { - braw.ptr.pp_double[j0][j] = braw.ptr.pp_double[j0][j]+rj*tmp0.ptr.p_double[j0]; - } - } - } - for(;;) - { - for(i=0; i<=nx; i++) - { - for(j=0; j<=nx; j++) - { - amod.ptr.pp_double[i][j] = araw.ptr.pp_double[i][j]; - } - amod.ptr.pp_double[i][i] = amod.ptr.pp_double[i][i]+lambdareg*coalesce(amod.ptr.pp_double[i][i], (double)(1), _state); - } - if( spdmatrixcholesky(&amod, nx+1, ae_true, _state) ) - { - break; - } - lambdareg = coalesce(10*lambdareg, 1.0E-12, _state); - } - rmatrixlefttrsm(nx+1, ny, &amod, 0, 0, ae_true, ae_false, 1, &braw, 0, 0, _state); - rmatrixlefttrsm(nx+1, ny, &amod, 0, 0, ae_true, ae_false, 0, &braw, 0, 0, _state); - for(i=0; i<=nx; i++) - { - for(j=0; j<=ny-1; j++) - { - v->ptr.pp_double[j][i] = v->ptr.pp_double[j][i]+braw.ptr.pp_double[i][j]; - } - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - tmp0.ptr.p_double[j] = xy->ptr.pp_double[i][j]; - } - tmp0.ptr.p_double[nx] = 1.0; - for(j=0; j<=ny-1; j++) - { - rj = 0.0; - for(j0=0; j0<=nx; j0++) - { - rj = rj+tmp0.ptr.p_double[j0]*v->ptr.pp_double[j][j0]; - } - xy->ptr.pp_double[i][nx+j] = xy->ptr.pp_double[i][nx+j]-rj; - } - } - ae_frame_leave(_state); -} - - -void buildpriorterm1(/* Real */ ae_vector* xy1, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - ae_int_t modeltype, - double priorval, - /* Real */ ae_matrix* v, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t j0; - ae_int_t j1; - ae_int_t ew; - double rj; - ae_matrix araw; - ae_matrix amod; - ae_matrix braw; - ae_vector tmp0; - double lambdareg; - ae_int_t rfsits; - - ae_frame_make(_state, &_frame_block); - memset(&araw, 0, sizeof(araw)); - memset(&amod, 0, sizeof(amod)); - memset(&braw, 0, sizeof(braw)); - memset(&tmp0, 0, sizeof(tmp0)); - ae_matrix_clear(v); - ae_matrix_init(&araw, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&amod, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&braw, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=0, "BuildPriorTerm: N<0", _state); - ae_assert(nx>0, "BuildPriorTerm: NX<=0", _state); - ae_assert(ny>0, "BuildPriorTerm: NY<=0", _state); - ew = nx+ny; - ae_matrix_set_length(v, ny, nx+1, _state); - for(i=0; i<=v->rows-1; i++) - { - for(j=0; j<=v->cols-1; j++) - { - v->ptr.pp_double[i][j] = (double)(0); - } - } - if( n==0 ) - { - if( modeltype==0 ) - { - for(i=0; i<=ny-1; i++) - { - v->ptr.pp_double[i][nx] = priorval; - } - ae_frame_leave(_state); - return; - } - if( modeltype==1 ) - { - ae_frame_leave(_state); - return; - } - if( modeltype==2 ) - { - ae_frame_leave(_state); - return; - } - if( modeltype==3 ) - { - ae_frame_leave(_state); - return; - } - ae_assert(ae_false, "BuildPriorTerm: unexpected model type", _state); - } - if( modeltype==0 ) - { - for(i=0; i<=ny-1; i++) - { - v->ptr.pp_double[i][nx] = priorval; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=ny-1; j++) - { - xy1->ptr.p_double[i*ew+nx+j] = xy1->ptr.p_double[i*ew+nx+j]-priorval; - } - } - ae_frame_leave(_state); - return; - } - if( modeltype==2 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=ny-1; j++) - { - v->ptr.pp_double[j][nx] = v->ptr.pp_double[j][nx]+xy1->ptr.p_double[i*ew+nx+j]; - } - } - for(j=0; j<=ny-1; j++) - { - v->ptr.pp_double[j][nx] = v->ptr.pp_double[j][nx]/coalesce((double)(n), (double)(1), _state); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=ny-1; j++) - { - xy1->ptr.p_double[i*ew+nx+j] = xy1->ptr.p_double[i*ew+nx+j]-v->ptr.pp_double[j][nx]; - } - } - ae_frame_leave(_state); - return; - } - if( modeltype==3 ) - { - ae_frame_leave(_state); - return; - } - ae_assert(modeltype==1, "BuildPriorTerm: unexpected model type", _state); - lambdareg = 0.0; - ae_matrix_set_length(&araw, nx+1, nx+1, _state); - ae_matrix_set_length(&braw, nx+1, ny, _state); - ae_vector_set_length(&tmp0, nx+1, _state); - ae_matrix_set_length(&amod, nx+1, nx+1, _state); - for(i=0; i<=nx; i++) - { - for(j=0; j<=nx; j++) - { - araw.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - tmp0.ptr.p_double[j] = xy1->ptr.p_double[i*ew+j]; - } - tmp0.ptr.p_double[nx] = 1.0; - for(j0=0; j0<=nx; j0++) - { - for(j1=0; j1<=nx; j1++) - { - araw.ptr.pp_double[j0][j1] = araw.ptr.pp_double[j0][j1]+tmp0.ptr.p_double[j0]*tmp0.ptr.p_double[j1]; - } - } - } - for(rfsits=1; rfsits<=3; rfsits++) - { - for(i=0; i<=nx; i++) - { - for(j=0; j<=ny-1; j++) - { - braw.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - tmp0.ptr.p_double[j] = xy1->ptr.p_double[i*ew+j]; - } - tmp0.ptr.p_double[nx] = 1.0; - for(j=0; j<=ny-1; j++) - { - rj = xy1->ptr.p_double[i*ew+nx+j]; - for(j0=0; j0<=nx; j0++) - { - rj = rj-tmp0.ptr.p_double[j0]*v->ptr.pp_double[j][j0]; - } - for(j0=0; j0<=nx; j0++) - { - braw.ptr.pp_double[j0][j] = braw.ptr.pp_double[j0][j]+rj*tmp0.ptr.p_double[j0]; - } - } - } - for(;;) - { - for(i=0; i<=nx; i++) - { - for(j=0; j<=nx; j++) - { - amod.ptr.pp_double[i][j] = araw.ptr.pp_double[i][j]; - } - amod.ptr.pp_double[i][i] = amod.ptr.pp_double[i][i]+lambdareg*coalesce(amod.ptr.pp_double[i][i], (double)(1), _state); - } - if( spdmatrixcholesky(&amod, nx+1, ae_true, _state) ) - { - break; - } - lambdareg = coalesce(10*lambdareg, 1.0E-12, _state); - } - rmatrixlefttrsm(nx+1, ny, &amod, 0, 0, ae_true, ae_false, 1, &braw, 0, 0, _state); - rmatrixlefttrsm(nx+1, ny, &amod, 0, 0, ae_true, ae_false, 0, &braw, 0, 0, _state); - for(i=0; i<=nx; i++) - { - for(j=0; j<=ny-1; j++) - { - v->ptr.pp_double[j][i] = v->ptr.pp_double[j][i]+braw.ptr.pp_double[i][j]; - } - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - tmp0.ptr.p_double[j] = xy1->ptr.p_double[i*ew+j]; - } - tmp0.ptr.p_double[nx] = 1.0; - for(j=0; j<=ny-1; j++) - { - rj = 0.0; - for(j0=0; j0<=nx; j0++) - { - rj = rj+tmp0.ptr.p_double[j0]*v->ptr.pp_double[j][j0]; - } - xy1->ptr.p_double[i*ew+nx+j] = xy1->ptr.p_double[i*ew+nx+j]-rj; - } - } - ae_frame_leave(_state); -} - - -#endif -#if defined(AE_COMPILE_SPLINE1D) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This subroutine builds linear spline interpolant - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1] - Y - function values, array[0..N-1] - N - points count (optional): - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - -OUTPUT PARAMETERS: - C - spline interpolant - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - - -- ALGLIB PROJECT -- - Copyright 24.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dbuildlinear(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - spline1dinterpolant* c, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - _spline1dinterpolant_clear(c); - - ae_assert(n>1, "Spline1DBuildLinear: N<2!", _state); - ae_assert(x->cnt>=n, "Spline1DBuildLinear: Length(X)cnt>=n, "Spline1DBuildLinear: Length(Y)periodic = ae_false; - c->n = n; - c->k = 3; - c->continuity = 0; - ae_vector_set_length(&c->x, n, _state); - ae_vector_set_length(&c->c, 4*(n-1)+2, _state); - for(i=0; i<=n-1; i++) - { - c->x.ptr.p_double[i] = x->ptr.p_double[i]; - } - for(i=0; i<=n-2; i++) - { - c->c.ptr.p_double[4*i+0] = y->ptr.p_double[i]; - c->c.ptr.p_double[4*i+1] = (y->ptr.p_double[i+1]-y->ptr.p_double[i])/(x->ptr.p_double[i+1]-x->ptr.p_double[i]); - c->c.ptr.p_double[4*i+2] = (double)(0); - c->c.ptr.p_double[4*i+3] = (double)(0); - } - c->c.ptr.p_double[4*(n-1)+0] = y->ptr.p_double[n-1]; - c->c.ptr.p_double[4*(n-1)+1] = c->c.ptr.p_double[4*(n-2)+1]; - ae_frame_leave(_state); -} - - -/************************************************************************* -This subroutine builds cubic spline interpolant. - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1]. - Y - function values, array[0..N-1]. - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - -OUTPUT PARAMETERS: - C - spline interpolant - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 23.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dbuildcubic(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t boundltype, - double boundl, - ae_int_t boundrtype, - double boundr, - spline1dinterpolant* c, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - ae_vector a1; - ae_vector a2; - ae_vector a3; - ae_vector b; - ae_vector dt; - ae_vector d; - ae_vector p; - ae_int_t ylen; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - memset(&a1, 0, sizeof(a1)); - memset(&a2, 0, sizeof(a2)); - memset(&a3, 0, sizeof(a3)); - memset(&b, 0, sizeof(b)); - memset(&dt, 0, sizeof(dt)); - memset(&d, 0, sizeof(d)); - memset(&p, 0, sizeof(p)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - _spline1dinterpolant_clear(c); - ae_vector_init(&a1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a3, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dt, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - - - /* - * check correctness of boundary conditions - */ - ae_assert(((boundltype==-1||boundltype==0)||boundltype==1)||boundltype==2, "Spline1DBuildCubic: incorrect BoundLType!", _state); - ae_assert(((boundrtype==-1||boundrtype==0)||boundrtype==1)||boundrtype==2, "Spline1DBuildCubic: incorrect BoundRType!", _state); - ae_assert((boundrtype==-1&&boundltype==-1)||(boundrtype!=-1&&boundltype!=-1), "Spline1DBuildCubic: incorrect BoundLType/BoundRType!", _state); - if( boundltype==1||boundltype==2 ) - { - ae_assert(ae_isfinite(boundl, _state), "Spline1DBuildCubic: BoundL is infinite or NAN!", _state); - } - if( boundrtype==1||boundrtype==2 ) - { - ae_assert(ae_isfinite(boundr, _state), "Spline1DBuildCubic: BoundR is infinite or NAN!", _state); - } - - /* - * check lengths of arguments - */ - ae_assert(n>=2, "Spline1DBuildCubic: N<2!", _state); - ae_assert(x->cnt>=n, "Spline1DBuildCubic: Length(X)cnt>=n, "Spline1DBuildCubic: Length(Y)ptr.p_double[n-1] = y->ptr.p_double[0]; - } - spline1d_spline1dgriddiffcubicinternal(x, y, n, boundltype, boundl, boundrtype, boundr, &d, &a1, &a2, &a3, &b, &dt, _state); - spline1dbuildhermite(x, y, &d, n, c, _state); - c->periodic = boundltype==-1||boundrtype==-1; - c->continuity = 2; - ae_frame_leave(_state); -} - - -/************************************************************************* -This function solves following problem: given table y[] of function values -at nodes x[], it calculates and returns table of function derivatives d[] -(calculated at the same nodes x[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - spline nodes - Y - function values - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - -OUTPUT PARAMETERS: - D - derivative values at X[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Derivative values are correctly reordered on return, so D[I] is always -equal to S'(X[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -void spline1dgriddiffcubic(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t boundltype, - double boundl, - ae_int_t boundrtype, - double boundr, - /* Real */ ae_vector* d, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - ae_vector a1; - ae_vector a2; - ae_vector a3; - ae_vector b; - ae_vector dt; - ae_vector p; - ae_int_t i; - ae_int_t ylen; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - memset(&a1, 0, sizeof(a1)); - memset(&a2, 0, sizeof(a2)); - memset(&a3, 0, sizeof(a3)); - memset(&b, 0, sizeof(b)); - memset(&dt, 0, sizeof(dt)); - memset(&p, 0, sizeof(p)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - ae_vector_clear(d); - ae_vector_init(&a1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a3, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dt, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - - - /* - * check correctness of boundary conditions - */ - ae_assert(((boundltype==-1||boundltype==0)||boundltype==1)||boundltype==2, "Spline1DGridDiffCubic: incorrect BoundLType!", _state); - ae_assert(((boundrtype==-1||boundrtype==0)||boundrtype==1)||boundrtype==2, "Spline1DGridDiffCubic: incorrect BoundRType!", _state); - ae_assert((boundrtype==-1&&boundltype==-1)||(boundrtype!=-1&&boundltype!=-1), "Spline1DGridDiffCubic: incorrect BoundLType/BoundRType!", _state); - if( boundltype==1||boundltype==2 ) - { - ae_assert(ae_isfinite(boundl, _state), "Spline1DGridDiffCubic: BoundL is infinite or NAN!", _state); - } - if( boundrtype==1||boundrtype==2 ) - { - ae_assert(ae_isfinite(boundr, _state), "Spline1DGridDiffCubic: BoundR is infinite or NAN!", _state); - } - - /* - * check lengths of arguments - */ - ae_assert(n>=2, "Spline1DGridDiffCubic: N<2!", _state); - ae_assert(x->cnt>=n, "Spline1DGridDiffCubic: Length(X)cnt>=n, "Spline1DGridDiffCubic: Length(Y)ptr.p_double[i]; - } - ae_v_move(&d->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function solves following problem: given table y[] of function values -at nodes x[], it calculates and returns tables of first and second -function derivatives d1[] and d2[] (calculated at the same nodes x[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - spline nodes - Y - function values - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - -OUTPUT PARAMETERS: - D1 - S' values at X[] - D2 - S'' values at X[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Derivative values are correctly reordered on return, so D[I] is always -equal to S'(X[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -void spline1dgriddiff2cubic(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t boundltype, - double boundl, - ae_int_t boundrtype, - double boundr, - /* Real */ ae_vector* d1, - /* Real */ ae_vector* d2, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - ae_vector a1; - ae_vector a2; - ae_vector a3; - ae_vector b; - ae_vector dt; - ae_vector p; - ae_int_t i; - ae_int_t ylen; - double delta; - double delta2; - double delta3; - double s2; - double s3; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - memset(&a1, 0, sizeof(a1)); - memset(&a2, 0, sizeof(a2)); - memset(&a3, 0, sizeof(a3)); - memset(&b, 0, sizeof(b)); - memset(&dt, 0, sizeof(dt)); - memset(&p, 0, sizeof(p)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - ae_vector_clear(d1); - ae_vector_clear(d2); - ae_vector_init(&a1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a3, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dt, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - - - /* - * check correctness of boundary conditions - */ - ae_assert(((boundltype==-1||boundltype==0)||boundltype==1)||boundltype==2, "Spline1DGridDiff2Cubic: incorrect BoundLType!", _state); - ae_assert(((boundrtype==-1||boundrtype==0)||boundrtype==1)||boundrtype==2, "Spline1DGridDiff2Cubic: incorrect BoundRType!", _state); - ae_assert((boundrtype==-1&&boundltype==-1)||(boundrtype!=-1&&boundltype!=-1), "Spline1DGridDiff2Cubic: incorrect BoundLType/BoundRType!", _state); - if( boundltype==1||boundltype==2 ) - { - ae_assert(ae_isfinite(boundl, _state), "Spline1DGridDiff2Cubic: BoundL is infinite or NAN!", _state); - } - if( boundrtype==1||boundrtype==2 ) - { - ae_assert(ae_isfinite(boundr, _state), "Spline1DGridDiff2Cubic: BoundR is infinite or NAN!", _state); - } - - /* - * check lengths of arguments - */ - ae_assert(n>=2, "Spline1DGridDiff2Cubic: N<2!", _state); - ae_assert(x->cnt>=n, "Spline1DGridDiff2Cubic: Length(X)cnt>=n, "Spline1DGridDiff2Cubic: Length(Y)ptr.p_double[i+1]-x->ptr.p_double[i]; - delta2 = ae_sqr(delta, _state); - delta3 = delta*delta2; - s2 = (3*(y->ptr.p_double[i+1]-y->ptr.p_double[i])-2*d1->ptr.p_double[i]*delta-d1->ptr.p_double[i+1]*delta)/delta2; - s3 = (2*(y->ptr.p_double[i]-y->ptr.p_double[i+1])+d1->ptr.p_double[i]*delta+d1->ptr.p_double[i+1]*delta)/delta3; - d2->ptr.p_double[i] = 2*s2; - } - d2->ptr.p_double[n-1] = 2*s2+6*s3*delta; - - /* - * Remember that HeapSortPPoints() call? - * Now we have to reorder them back. - */ - if( dt.cntptr.p_double[i]; - } - ae_v_move(&d1->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - dt.ptr.p_double[p.ptr.p_int[i]] = d2->ptr.p_double[i]; - } - ae_v_move(&d2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function solves following problem: given table y[] of function values -at old nodes x[] and new nodes x2[], it calculates and returns table of -function values y2[] (calculated at x2[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - old spline nodes - Y - function values - X2 - new spline nodes - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points from X/Y are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - N2 - new points count: - * N2>=2 - * if given, only first N2 points from X2 are used - * if not given, automatically detected from X2 size - -OUTPUT PARAMETERS: - F2 - function values at X2[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Function values are correctly reordered on return, so F2[I] is always -equal to S(X2[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -void spline1dconvcubic(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t boundltype, - double boundl, - ae_int_t boundrtype, - double boundr, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Real */ ae_vector* y2, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - ae_vector _x2; - ae_vector a1; - ae_vector a2; - ae_vector a3; - ae_vector b; - ae_vector d; - ae_vector dt; - ae_vector d1; - ae_vector d2; - ae_vector p; - ae_vector p2; - ae_int_t i; - ae_int_t ylen; - double t; - double t2; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - memset(&_x2, 0, sizeof(_x2)); - memset(&a1, 0, sizeof(a1)); - memset(&a2, 0, sizeof(a2)); - memset(&a3, 0, sizeof(a3)); - memset(&b, 0, sizeof(b)); - memset(&d, 0, sizeof(d)); - memset(&dt, 0, sizeof(dt)); - memset(&d1, 0, sizeof(d1)); - memset(&d2, 0, sizeof(d2)); - memset(&p, 0, sizeof(p)); - memset(&p2, 0, sizeof(p2)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - ae_vector_init_copy(&_x2, x2, _state, ae_true); - x2 = &_x2; - ae_vector_clear(y2); - ae_vector_init(&a1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a3, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dt, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - ae_vector_init(&p2, 0, DT_INT, _state, ae_true); - - - /* - * check correctness of boundary conditions - */ - ae_assert(((boundltype==-1||boundltype==0)||boundltype==1)||boundltype==2, "Spline1DConvCubic: incorrect BoundLType!", _state); - ae_assert(((boundrtype==-1||boundrtype==0)||boundrtype==1)||boundrtype==2, "Spline1DConvCubic: incorrect BoundRType!", _state); - ae_assert((boundrtype==-1&&boundltype==-1)||(boundrtype!=-1&&boundltype!=-1), "Spline1DConvCubic: incorrect BoundLType/BoundRType!", _state); - if( boundltype==1||boundltype==2 ) - { - ae_assert(ae_isfinite(boundl, _state), "Spline1DConvCubic: BoundL is infinite or NAN!", _state); - } - if( boundrtype==1||boundrtype==2 ) - { - ae_assert(ae_isfinite(boundr, _state), "Spline1DConvCubic: BoundR is infinite or NAN!", _state); - } - - /* - * check lengths of arguments - */ - ae_assert(n>=2, "Spline1DConvCubic: N<2!", _state); - ae_assert(x->cnt>=n, "Spline1DConvCubic: Length(X)cnt>=n, "Spline1DConvCubic: Length(Y)=2, "Spline1DConvCubic: N2<2!", _state); - ae_assert(x2->cnt>=n2, "Spline1DConvCubic: Length(X2)ptr.p_double[i]; - apperiodicmap(&t, x->ptr.p_double[0], x->ptr.p_double[n-1], &t2, _state); - x2->ptr.p_double[i] = t; - } - } - spline1d_heapsortppoints(x2, &dt, &p2, n2, _state); - - /* - * Now we've checked and preordered everything, so we: - * * call internal GridDiff() function to get Hermite form of spline - * * convert using internal Conv() function - * * convert Y2 back to original order - */ - spline1d_spline1dgriddiffcubicinternal(x, y, n, boundltype, boundl, boundrtype, boundr, &d, &a1, &a2, &a3, &b, &dt, _state); - spline1dconvdiffinternal(x, y, &d, n, x2, n2, y2, ae_true, &d1, ae_false, &d2, ae_false, _state); - ae_assert(dt.cnt>=n2, "Spline1DConvCubic: internal error!", _state); - for(i=0; i<=n2-1; i++) - { - dt.ptr.p_double[p2.ptr.p_int[i]] = y2->ptr.p_double[i]; - } - ae_v_move(&y2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n2-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function solves following problem: given table y[] of function values -at old nodes x[] and new nodes x2[], it calculates and returns table of -function values y2[] and derivatives d2[] (calculated at x2[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - old spline nodes - Y - function values - X2 - new spline nodes - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points from X/Y are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - N2 - new points count: - * N2>=2 - * if given, only first N2 points from X2 are used - * if not given, automatically detected from X2 size - -OUTPUT PARAMETERS: - F2 - function values at X2[] - D2 - first derivatives at X2[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Function values are correctly reordered on return, so F2[I] is always -equal to S(X2[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -void spline1dconvdiffcubic(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t boundltype, - double boundl, - ae_int_t boundrtype, - double boundr, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Real */ ae_vector* y2, - /* Real */ ae_vector* d2, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - ae_vector _x2; - ae_vector a1; - ae_vector a2; - ae_vector a3; - ae_vector b; - ae_vector d; - ae_vector dt; - ae_vector rt1; - ae_vector p; - ae_vector p2; - ae_int_t i; - ae_int_t ylen; - double t; - double t2; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - memset(&_x2, 0, sizeof(_x2)); - memset(&a1, 0, sizeof(a1)); - memset(&a2, 0, sizeof(a2)); - memset(&a3, 0, sizeof(a3)); - memset(&b, 0, sizeof(b)); - memset(&d, 0, sizeof(d)); - memset(&dt, 0, sizeof(dt)); - memset(&rt1, 0, sizeof(rt1)); - memset(&p, 0, sizeof(p)); - memset(&p2, 0, sizeof(p2)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - ae_vector_init_copy(&_x2, x2, _state, ae_true); - x2 = &_x2; - ae_vector_clear(y2); - ae_vector_clear(d2); - ae_vector_init(&a1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a3, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dt, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rt1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - ae_vector_init(&p2, 0, DT_INT, _state, ae_true); - - - /* - * check correctness of boundary conditions - */ - ae_assert(((boundltype==-1||boundltype==0)||boundltype==1)||boundltype==2, "Spline1DConvDiffCubic: incorrect BoundLType!", _state); - ae_assert(((boundrtype==-1||boundrtype==0)||boundrtype==1)||boundrtype==2, "Spline1DConvDiffCubic: incorrect BoundRType!", _state); - ae_assert((boundrtype==-1&&boundltype==-1)||(boundrtype!=-1&&boundltype!=-1), "Spline1DConvDiffCubic: incorrect BoundLType/BoundRType!", _state); - if( boundltype==1||boundltype==2 ) - { - ae_assert(ae_isfinite(boundl, _state), "Spline1DConvDiffCubic: BoundL is infinite or NAN!", _state); - } - if( boundrtype==1||boundrtype==2 ) - { - ae_assert(ae_isfinite(boundr, _state), "Spline1DConvDiffCubic: BoundR is infinite or NAN!", _state); - } - - /* - * check lengths of arguments - */ - ae_assert(n>=2, "Spline1DConvDiffCubic: N<2!", _state); - ae_assert(x->cnt>=n, "Spline1DConvDiffCubic: Length(X)cnt>=n, "Spline1DConvDiffCubic: Length(Y)=2, "Spline1DConvDiffCubic: N2<2!", _state); - ae_assert(x2->cnt>=n2, "Spline1DConvDiffCubic: Length(X2)ptr.p_double[i]; - apperiodicmap(&t, x->ptr.p_double[0], x->ptr.p_double[n-1], &t2, _state); - x2->ptr.p_double[i] = t; - } - } - spline1d_heapsortppoints(x2, &dt, &p2, n2, _state); - - /* - * Now we've checked and preordered everything, so we: - * * call internal GridDiff() function to get Hermite form of spline - * * convert using internal Conv() function - * * convert Y2 back to original order - */ - spline1d_spline1dgriddiffcubicinternal(x, y, n, boundltype, boundl, boundrtype, boundr, &d, &a1, &a2, &a3, &b, &dt, _state); - spline1dconvdiffinternal(x, y, &d, n, x2, n2, y2, ae_true, d2, ae_true, &rt1, ae_false, _state); - ae_assert(dt.cnt>=n2, "Spline1DConvDiffCubic: internal error!", _state); - for(i=0; i<=n2-1; i++) - { - dt.ptr.p_double[p2.ptr.p_int[i]] = y2->ptr.p_double[i]; - } - ae_v_move(&y2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n2-1)); - for(i=0; i<=n2-1; i++) - { - dt.ptr.p_double[p2.ptr.p_int[i]] = d2->ptr.p_double[i]; - } - ae_v_move(&d2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n2-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function solves following problem: given table y[] of function values -at old nodes x[] and new nodes x2[], it calculates and returns table of -function values y2[], first and second derivatives d2[] and dd2[] -(calculated at x2[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - old spline nodes - Y - function values - X2 - new spline nodes - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points from X/Y are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - N2 - new points count: - * N2>=2 - * if given, only first N2 points from X2 are used - * if not given, automatically detected from X2 size - -OUTPUT PARAMETERS: - F2 - function values at X2[] - D2 - first derivatives at X2[] - DD2 - second derivatives at X2[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Function values are correctly reordered on return, so F2[I] is always -equal to S(X2[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -void spline1dconvdiff2cubic(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t boundltype, - double boundl, - ae_int_t boundrtype, - double boundr, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Real */ ae_vector* y2, - /* Real */ ae_vector* d2, - /* Real */ ae_vector* dd2, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - ae_vector _x2; - ae_vector a1; - ae_vector a2; - ae_vector a3; - ae_vector b; - ae_vector d; - ae_vector dt; - ae_vector p; - ae_vector p2; - ae_int_t i; - ae_int_t ylen; - double t; - double t2; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - memset(&_x2, 0, sizeof(_x2)); - memset(&a1, 0, sizeof(a1)); - memset(&a2, 0, sizeof(a2)); - memset(&a3, 0, sizeof(a3)); - memset(&b, 0, sizeof(b)); - memset(&d, 0, sizeof(d)); - memset(&dt, 0, sizeof(dt)); - memset(&p, 0, sizeof(p)); - memset(&p2, 0, sizeof(p2)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - ae_vector_init_copy(&_x2, x2, _state, ae_true); - x2 = &_x2; - ae_vector_clear(y2); - ae_vector_clear(d2); - ae_vector_clear(dd2); - ae_vector_init(&a1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a3, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dt, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - ae_vector_init(&p2, 0, DT_INT, _state, ae_true); - - - /* - * check correctness of boundary conditions - */ - ae_assert(((boundltype==-1||boundltype==0)||boundltype==1)||boundltype==2, "Spline1DConvDiff2Cubic: incorrect BoundLType!", _state); - ae_assert(((boundrtype==-1||boundrtype==0)||boundrtype==1)||boundrtype==2, "Spline1DConvDiff2Cubic: incorrect BoundRType!", _state); - ae_assert((boundrtype==-1&&boundltype==-1)||(boundrtype!=-1&&boundltype!=-1), "Spline1DConvDiff2Cubic: incorrect BoundLType/BoundRType!", _state); - if( boundltype==1||boundltype==2 ) - { - ae_assert(ae_isfinite(boundl, _state), "Spline1DConvDiff2Cubic: BoundL is infinite or NAN!", _state); - } - if( boundrtype==1||boundrtype==2 ) - { - ae_assert(ae_isfinite(boundr, _state), "Spline1DConvDiff2Cubic: BoundR is infinite or NAN!", _state); - } - - /* - * check lengths of arguments - */ - ae_assert(n>=2, "Spline1DConvDiff2Cubic: N<2!", _state); - ae_assert(x->cnt>=n, "Spline1DConvDiff2Cubic: Length(X)cnt>=n, "Spline1DConvDiff2Cubic: Length(Y)=2, "Spline1DConvDiff2Cubic: N2<2!", _state); - ae_assert(x2->cnt>=n2, "Spline1DConvDiff2Cubic: Length(X2)ptr.p_double[i]; - apperiodicmap(&t, x->ptr.p_double[0], x->ptr.p_double[n-1], &t2, _state); - x2->ptr.p_double[i] = t; - } - } - spline1d_heapsortppoints(x2, &dt, &p2, n2, _state); - - /* - * Now we've checked and preordered everything, so we: - * * call internal GridDiff() function to get Hermite form of spline - * * convert using internal Conv() function - * * convert Y2 back to original order - */ - spline1d_spline1dgriddiffcubicinternal(x, y, n, boundltype, boundl, boundrtype, boundr, &d, &a1, &a2, &a3, &b, &dt, _state); - spline1dconvdiffinternal(x, y, &d, n, x2, n2, y2, ae_true, d2, ae_true, dd2, ae_true, _state); - ae_assert(dt.cnt>=n2, "Spline1DConvDiff2Cubic: internal error!", _state); - for(i=0; i<=n2-1; i++) - { - dt.ptr.p_double[p2.ptr.p_int[i]] = y2->ptr.p_double[i]; - } - ae_v_move(&y2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n2-1)); - for(i=0; i<=n2-1; i++) - { - dt.ptr.p_double[p2.ptr.p_int[i]] = d2->ptr.p_double[i]; - } - ae_v_move(&d2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n2-1)); - for(i=0; i<=n2-1; i++) - { - dt.ptr.p_double[p2.ptr.p_int[i]] = dd2->ptr.p_double[i]; - } - ae_v_move(&dd2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n2-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -This subroutine builds Catmull-Rom spline interpolant. - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1]. - Y - function values, array[0..N-1]. - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundType - boundary condition type: - * -1 for periodic boundary condition - * 0 for parabolically terminated spline (default) - Tension - tension parameter: - * tension=0 corresponds to classic Catmull-Rom spline (default) - * 0=2, "Spline1DBuildCatmullRom: N<2!", _state); - ae_assert(boundtype==-1||boundtype==0, "Spline1DBuildCatmullRom: incorrect BoundType!", _state); - ae_assert(ae_fp_greater_eq(tension,(double)(0)), "Spline1DBuildCatmullRom: Tension<0!", _state); - ae_assert(ae_fp_less_eq(tension,(double)(1)), "Spline1DBuildCatmullRom: Tension>1!", _state); - ae_assert(x->cnt>=n, "Spline1DBuildCatmullRom: Length(X)cnt>=n, "Spline1DBuildCatmullRom: Length(Y)ptr.p_double[n-1] = y->ptr.p_double[0]; - ae_vector_set_length(&d, n, _state); - d.ptr.p_double[0] = (y->ptr.p_double[1]-y->ptr.p_double[n-2])/(2*(x->ptr.p_double[1]-x->ptr.p_double[0]+x->ptr.p_double[n-1]-x->ptr.p_double[n-2])); - for(i=1; i<=n-2; i++) - { - d.ptr.p_double[i] = (1-tension)*(y->ptr.p_double[i+1]-y->ptr.p_double[i-1])/(x->ptr.p_double[i+1]-x->ptr.p_double[i-1]); - } - d.ptr.p_double[n-1] = d.ptr.p_double[0]; - - /* - * Now problem is reduced to the cubic Hermite spline - */ - spline1dbuildhermite(x, y, &d, n, c, _state); - c->periodic = ae_true; - } - else - { - - /* - * Non-periodic boundary conditions - */ - ae_vector_set_length(&d, n, _state); - for(i=1; i<=n-2; i++) - { - d.ptr.p_double[i] = (1-tension)*(y->ptr.p_double[i+1]-y->ptr.p_double[i-1])/(x->ptr.p_double[i+1]-x->ptr.p_double[i-1]); - } - d.ptr.p_double[0] = 2*(y->ptr.p_double[1]-y->ptr.p_double[0])/(x->ptr.p_double[1]-x->ptr.p_double[0])-d.ptr.p_double[1]; - d.ptr.p_double[n-1] = 2*(y->ptr.p_double[n-1]-y->ptr.p_double[n-2])/(x->ptr.p_double[n-1]-x->ptr.p_double[n-2])-d.ptr.p_double[n-2]; - - /* - * Now problem is reduced to the cubic Hermite spline - */ - spline1dbuildhermite(x, y, &d, n, c, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This subroutine builds Hermite spline interpolant. - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1] - Y - function values, array[0..N-1] - D - derivatives, array[0..N-1] - N - points count (optional): - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - -OUTPUT PARAMETERS: - C - spline interpolant. - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - - -- ALGLIB PROJECT -- - Copyright 23.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dbuildhermite(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* d, - ae_int_t n, - spline1dinterpolant* c, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - ae_vector _d; - ae_int_t i; - double delta; - double delta2; - double delta3; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - memset(&_d, 0, sizeof(_d)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - ae_vector_init_copy(&_d, d, _state, ae_true); - d = &_d; - _spline1dinterpolant_clear(c); - - ae_assert(n>=2, "Spline1DBuildHermite: N<2!", _state); - ae_assert(x->cnt>=n, "Spline1DBuildHermite: Length(X)cnt>=n, "Spline1DBuildHermite: Length(Y)cnt>=n, "Spline1DBuildHermite: Length(D)x, n, _state); - ae_vector_set_length(&c->c, 4*(n-1)+2, _state); - c->periodic = ae_false; - c->k = 3; - c->n = n; - c->continuity = 1; - for(i=0; i<=n-1; i++) - { - c->x.ptr.p_double[i] = x->ptr.p_double[i]; - } - for(i=0; i<=n-2; i++) - { - delta = x->ptr.p_double[i+1]-x->ptr.p_double[i]; - delta2 = ae_sqr(delta, _state); - delta3 = delta*delta2; - c->c.ptr.p_double[4*i+0] = y->ptr.p_double[i]; - c->c.ptr.p_double[4*i+1] = d->ptr.p_double[i]; - c->c.ptr.p_double[4*i+2] = (3*(y->ptr.p_double[i+1]-y->ptr.p_double[i])-2*d->ptr.p_double[i]*delta-d->ptr.p_double[i+1]*delta)/delta2; - c->c.ptr.p_double[4*i+3] = (2*(y->ptr.p_double[i]-y->ptr.p_double[i+1])+d->ptr.p_double[i]*delta+d->ptr.p_double[i+1]*delta)/delta3; - } - c->c.ptr.p_double[4*(n-1)+0] = y->ptr.p_double[n-1]; - c->c.ptr.p_double[4*(n-1)+1] = d->ptr.p_double[n-1]; - ae_frame_leave(_state); -} - - -/************************************************************************* -This subroutine builds Akima spline interpolant - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1] - Y - function values, array[0..N-1] - N - points count (optional): - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - -OUTPUT PARAMETERS: - C - spline interpolant - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - - -- ALGLIB PROJECT -- - Copyright 24.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dbuildakima(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - spline1dinterpolant* c, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - ae_int_t i; - ae_vector d; - ae_vector w; - ae_vector diff; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - memset(&d, 0, sizeof(d)); - memset(&w, 0, sizeof(w)); - memset(&diff, 0, sizeof(diff)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - _spline1dinterpolant_clear(c); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&diff, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=2, "Spline1DBuildAkima: N<2!", _state); - ae_assert(x->cnt>=n, "Spline1DBuildAkima: Length(X)cnt>=n, "Spline1DBuildAkima: Length(Y)ptr.p_double[i+1]-y->ptr.p_double[i])/(x->ptr.p_double[i+1]-x->ptr.p_double[i]); - } - for(i=1; i<=n-2; i++) - { - w.ptr.p_double[i] = ae_fabs(diff.ptr.p_double[i]-diff.ptr.p_double[i-1], _state); - } - - /* - * Prepare Hermite interpolation scheme - */ - ae_vector_set_length(&d, n, _state); - for(i=2; i<=n-3; i++) - { - if( ae_fp_neq(ae_fabs(w.ptr.p_double[i-1], _state)+ae_fabs(w.ptr.p_double[i+1], _state),(double)(0)) ) - { - d.ptr.p_double[i] = (w.ptr.p_double[i+1]*diff.ptr.p_double[i-1]+w.ptr.p_double[i-1]*diff.ptr.p_double[i])/(w.ptr.p_double[i+1]+w.ptr.p_double[i-1]); - } - else - { - d.ptr.p_double[i] = ((x->ptr.p_double[i+1]-x->ptr.p_double[i])*diff.ptr.p_double[i-1]+(x->ptr.p_double[i]-x->ptr.p_double[i-1])*diff.ptr.p_double[i])/(x->ptr.p_double[i+1]-x->ptr.p_double[i-1]); - } - } - d.ptr.p_double[0] = spline1d_diffthreepoint(x->ptr.p_double[0], x->ptr.p_double[0], y->ptr.p_double[0], x->ptr.p_double[1], y->ptr.p_double[1], x->ptr.p_double[2], y->ptr.p_double[2], _state); - d.ptr.p_double[1] = spline1d_diffthreepoint(x->ptr.p_double[1], x->ptr.p_double[0], y->ptr.p_double[0], x->ptr.p_double[1], y->ptr.p_double[1], x->ptr.p_double[2], y->ptr.p_double[2], _state); - d.ptr.p_double[n-2] = spline1d_diffthreepoint(x->ptr.p_double[n-2], x->ptr.p_double[n-3], y->ptr.p_double[n-3], x->ptr.p_double[n-2], y->ptr.p_double[n-2], x->ptr.p_double[n-1], y->ptr.p_double[n-1], _state); - d.ptr.p_double[n-1] = spline1d_diffthreepoint(x->ptr.p_double[n-1], x->ptr.p_double[n-3], y->ptr.p_double[n-3], x->ptr.p_double[n-2], y->ptr.p_double[n-2], x->ptr.p_double[n-1], y->ptr.p_double[n-1], _state); - - /* - * Build Akima spline using Hermite interpolation scheme - */ - spline1dbuildhermite(x, y, &d, n, c, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This subroutine calculates the value of the spline at the given point X. - -INPUT PARAMETERS: - C - spline interpolant - X - point - -Result: - S(x) - - -- ALGLIB PROJECT -- - Copyright 23.06.2007 by Bochkanov Sergey -*************************************************************************/ -double spline1dcalc(spline1dinterpolant* c, double x, ae_state *_state) -{ - ae_int_t l; - ae_int_t r; - ae_int_t m; - double t; - double result; - - - ae_assert(c->k==3, "Spline1DCalc: internal error", _state); - ae_assert(!ae_isinf(x, _state), "Spline1DCalc: infinite X!", _state); - - /* - * special case: NaN - */ - if( ae_isnan(x, _state) ) - { - result = _state->v_nan; - return result; - } - - /* - * correct if periodic - */ - if( c->periodic ) - { - apperiodicmap(&x, c->x.ptr.p_double[0], c->x.ptr.p_double[c->n-1], &t, _state); - } - - /* - * Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included) - */ - l = 0; - r = c->n-2+1; - while(l!=r-1) - { - m = (l+r)/2; - if( c->x.ptr.p_double[m]>=x ) - { - r = m; - } - else - { - l = m; - } - } - - /* - * Interpolation - */ - x = x-c->x.ptr.p_double[l]; - m = 4*l; - result = c->c.ptr.p_double[m]+x*(c->c.ptr.p_double[m+1]+x*(c->c.ptr.p_double[m+2]+x*c->c.ptr.p_double[m+3])); - return result; -} - - -/************************************************************************* -This subroutine differentiates the spline. - -INPUT PARAMETERS: - C - spline interpolant. - X - point - -Result: - S - S(x) - DS - S'(x) - D2S - S''(x) - - -- ALGLIB PROJECT -- - Copyright 24.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1ddiff(spline1dinterpolant* c, - double x, - double* s, - double* ds, - double* d2s, - ae_state *_state) -{ - ae_int_t l; - ae_int_t r; - ae_int_t m; - double t; - - *s = 0; - *ds = 0; - *d2s = 0; - - ae_assert(c->k==3, "Spline1DDiff: internal error", _state); - ae_assert(!ae_isinf(x, _state), "Spline1DDiff: infinite X!", _state); - - /* - * special case: NaN - */ - if( ae_isnan(x, _state) ) - { - *s = _state->v_nan; - *ds = _state->v_nan; - *d2s = _state->v_nan; - return; - } - - /* - * correct if periodic - */ - if( c->periodic ) - { - apperiodicmap(&x, c->x.ptr.p_double[0], c->x.ptr.p_double[c->n-1], &t, _state); - } - - /* - * Binary search - */ - l = 0; - r = c->n-2+1; - while(l!=r-1) - { - m = (l+r)/2; - if( c->x.ptr.p_double[m]>=x ) - { - r = m; - } - else - { - l = m; - } - } - - /* - * Differentiation - */ - x = x-c->x.ptr.p_double[l]; - m = 4*l; - *s = c->c.ptr.p_double[m]+x*(c->c.ptr.p_double[m+1]+x*(c->c.ptr.p_double[m+2]+x*c->c.ptr.p_double[m+3])); - *ds = c->c.ptr.p_double[m+1]+2*x*c->c.ptr.p_double[m+2]+3*ae_sqr(x, _state)*c->c.ptr.p_double[m+3]; - *d2s = 2*c->c.ptr.p_double[m+2]+6*x*c->c.ptr.p_double[m+3]; -} - - -/************************************************************************* -This subroutine makes the copy of the spline. - -INPUT PARAMETERS: - C - spline interpolant. - -Result: - CC - spline copy - - -- ALGLIB PROJECT -- - Copyright 29.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dcopy(spline1dinterpolant* c, - spline1dinterpolant* cc, - ae_state *_state) -{ - ae_int_t s; - - _spline1dinterpolant_clear(cc); - - cc->periodic = c->periodic; - cc->n = c->n; - cc->k = c->k; - cc->continuity = c->continuity; - ae_vector_set_length(&cc->x, cc->n, _state); - ae_v_move(&cc->x.ptr.p_double[0], 1, &c->x.ptr.p_double[0], 1, ae_v_len(0,cc->n-1)); - s = c->c.cnt; - ae_vector_set_length(&cc->c, s, _state); - ae_v_move(&cc->c.ptr.p_double[0], 1, &c->c.ptr.p_double[0], 1, ae_v_len(0,s-1)); -} - - -/************************************************************************* -This subroutine unpacks the spline into the coefficients table. - -INPUT PARAMETERS: - C - spline interpolant. - X - point - -OUTPUT PARAMETERS: - Tbl - coefficients table, unpacked format, array[0..N-2, 0..5]. - For I = 0...N-2: - Tbl[I,0] = X[i] - Tbl[I,1] = X[i+1] - Tbl[I,2] = C0 - Tbl[I,3] = C1 - Tbl[I,4] = C2 - Tbl[I,5] = C3 - On [x[i], x[i+1]] spline is equals to: - S(x) = C0 + C1*t + C2*t^2 + C3*t^3 - t = x-x[i] - -NOTE: - You can rebuild spline with Spline1DBuildHermite() function, which - accepts as inputs function values and derivatives at nodes, which are - easy to calculate when you have coefficients. - - -- ALGLIB PROJECT -- - Copyright 29.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dunpack(spline1dinterpolant* c, - ae_int_t* n, - /* Real */ ae_matrix* tbl, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - *n = 0; - ae_matrix_clear(tbl); - - ae_matrix_set_length(tbl, c->n-2+1, 2+c->k+1, _state); - *n = c->n; - - /* - * Fill - */ - for(i=0; i<=*n-2; i++) - { - tbl->ptr.pp_double[i][0] = c->x.ptr.p_double[i]; - tbl->ptr.pp_double[i][1] = c->x.ptr.p_double[i+1]; - for(j=0; j<=c->k; j++) - { - tbl->ptr.pp_double[i][2+j] = c->c.ptr.p_double[(c->k+1)*i+j]; - } - } -} - - -/************************************************************************* -This subroutine performs linear transformation of the spline argument. - -INPUT PARAMETERS: - C - spline interpolant. - A, B- transformation coefficients: x = A*t + B -Result: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 30.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dlintransx(spline1dinterpolant* c, - double a, - double b, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t n; - double v; - double dv; - double d2v; - ae_vector x; - ae_vector y; - ae_vector d; - ae_bool isperiodic; - ae_int_t contval; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&d, 0, sizeof(d)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - - ae_assert(c->k==3, "Spline1DLinTransX: internal error", _state); - n = c->n; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - ae_vector_set_length(&d, n, _state); - - /* - * Unpack, X, Y, dY/dX. - * Scale and pack with Spline1DBuildHermite again. - */ - if( ae_fp_eq(a,(double)(0)) ) - { - - /* - * Special case: A=0 - */ - v = spline1dcalc(c, b, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = c->x.ptr.p_double[i]; - y.ptr.p_double[i] = v; - d.ptr.p_double[i] = 0.0; - } - } - else - { - - /* - * General case, A<>0 - */ - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = c->x.ptr.p_double[i]; - spline1ddiff(c, x.ptr.p_double[i], &v, &dv, &d2v, _state); - x.ptr.p_double[i] = (x.ptr.p_double[i]-b)/a; - y.ptr.p_double[i] = v; - d.ptr.p_double[i] = a*dv; - } - } - isperiodic = c->periodic; - contval = c->continuity; - if( contval>0 ) - { - spline1dbuildhermite(&x, &y, &d, n, c, _state); - } - else - { - spline1dbuildlinear(&x, &y, n, c, _state); - } - c->periodic = isperiodic; - c->continuity = contval; - ae_frame_leave(_state); -} - - -/************************************************************************* -This subroutine performs linear transformation of the spline. - -INPUT PARAMETERS: - C - spline interpolant. - A, B- transformation coefficients: S2(x) = A*S(x) + B -Result: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 30.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dlintransy(spline1dinterpolant* c, - double a, - double b, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t n; - - - ae_assert(c->k==3, "Spline1DLinTransX: internal error", _state); - n = c->n; - for(i=0; i<=n-2; i++) - { - c->c.ptr.p_double[4*i] = a*c->c.ptr.p_double[4*i]+b; - for(j=1; j<=3; j++) - { - c->c.ptr.p_double[4*i+j] = a*c->c.ptr.p_double[4*i+j]; - } - } - c->c.ptr.p_double[4*(n-1)+0] = a*c->c.ptr.p_double[4*(n-1)+0]+b; - c->c.ptr.p_double[4*(n-1)+1] = a*c->c.ptr.p_double[4*(n-1)+1]; -} - - -/************************************************************************* -This subroutine integrates the spline. - -INPUT PARAMETERS: - C - spline interpolant. - X - right bound of the integration interval [a, x], - here 'a' denotes min(x[]) -Result: - integral(S(t)dt,a,x) - - -- ALGLIB PROJECT -- - Copyright 23.06.2007 by Bochkanov Sergey -*************************************************************************/ -double spline1dintegrate(spline1dinterpolant* c, - double x, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t l; - ae_int_t r; - ae_int_t m; - double w; - double v; - double t; - double intab; - double additionalterm; - double result; - - - n = c->n; - - /* - * Periodic splines require special treatment. We make - * following transformation: - * - * integral(S(t)dt,A,X) = integral(S(t)dt,A,Z)+AdditionalTerm - * - * here X may lie outside of [A,B], Z lies strictly in [A,B], - * AdditionalTerm is equals to integral(S(t)dt,A,B) times some - * integer number (may be zero). - */ - if( c->periodic&&(ae_fp_less(x,c->x.ptr.p_double[0])||ae_fp_greater(x,c->x.ptr.p_double[c->n-1])) ) - { - - /* - * compute integral(S(x)dx,A,B) - */ - intab = (double)(0); - for(i=0; i<=c->n-2; i++) - { - w = c->x.ptr.p_double[i+1]-c->x.ptr.p_double[i]; - m = (c->k+1)*i; - intab = intab+c->c.ptr.p_double[m]*w; - v = w; - for(j=1; j<=c->k; j++) - { - v = v*w; - intab = intab+c->c.ptr.p_double[m+j]*v/(j+1); - } - } - - /* - * map X into [A,B] - */ - apperiodicmap(&x, c->x.ptr.p_double[0], c->x.ptr.p_double[c->n-1], &t, _state); - additionalterm = t*intab; - } - else - { - additionalterm = (double)(0); - } - - /* - * Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included) - */ - l = 0; - r = n-2+1; - while(l!=r-1) - { - m = (l+r)/2; - if( ae_fp_greater_eq(c->x.ptr.p_double[m],x) ) - { - r = m; - } - else - { - l = m; - } - } - - /* - * Integration - */ - result = (double)(0); - for(i=0; i<=l-1; i++) - { - w = c->x.ptr.p_double[i+1]-c->x.ptr.p_double[i]; - m = (c->k+1)*i; - result = result+c->c.ptr.p_double[m]*w; - v = w; - for(j=1; j<=c->k; j++) - { - v = v*w; - result = result+c->c.ptr.p_double[m+j]*v/(j+1); - } - } - w = x-c->x.ptr.p_double[l]; - m = (c->k+1)*l; - v = w; - result = result+c->c.ptr.p_double[m]*w; - for(j=1; j<=c->k; j++) - { - v = v*w; - result = result+c->c.ptr.p_double[m+j]*v/(j+1); - } - result = result+additionalterm; - return result; -} - - -/************************************************************************* -Fitting by smoothing (penalized) cubic spline. - -This function approximates N scattered points (some of X[] may be equal to -each other) by cubic spline with M nodes at equidistant grid spanning -interval [min(x,xc),max(x,xc)]. - -The problem is regularized by adding nonlinearity penalty to usual least -squares penalty function: - - MERIT_FUNC = F_LS + F_NL - -where F_LS is a least squares error term, and F_NL is a nonlinearity -penalty which is roughly proportional to LambdaNS*integral{ S''(x)^2*dx }. -Algorithm applies automatic renormalization of F_NL which makes penalty -term roughly invariant to scaling of X[] and changes in M. - -This function is a new edition of penalized regression spline fitting, -a fast and compact one which needs much less resources that its previous -version: just O(maxMN) memory and O(maxMN*log(maxMN)) time. - -NOTE: it is OK to run this function with both M<>N; say, it is - possible to process 100 points with 1000-node spline. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - N - number of points (optional): - * N>0 - * if given, only first N elements of X/Y are processed - * if not given, automatically determined from lengths - M - number of basis functions ( = number_of_nodes), M>=4. - LambdaNS - LambdaNS>=0, regularization constant passed by user. - It penalizes nonlinearity in the regression spline. - Possible values to start from are 0.00001, 0.1, 1 - -OUTPUT PARAMETERS: - S - spline interpolant. - Rep - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - - -- ALGLIB PROJECT -- - Copyright 27.08.2019 by Bochkanov Sergey -*************************************************************************/ -void spline1dfit(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t m, - double lambdans, - spline1dinterpolant* s, - spline1dfitreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - ae_int_t bfrad; - double xa; - double xb; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t k0; - ae_int_t k1; - double v; - double dv; - double d2v; - ae_int_t gridexpansion; - ae_vector xywork; - ae_matrix vterm; - ae_vector sx; - ae_vector sy; - ae_vector sdy; - ae_vector tmpx; - ae_vector tmpy; - spline1dinterpolant basis1; - sparsematrix av; - sparsematrix ah; - sparsematrix ata; - ae_vector targets; - double meany; - ae_int_t lsqrcnt; - ae_int_t nrel; - double rss; - double tss; - ae_int_t arows; - ae_vector tmp0; - ae_vector tmp1; - linlsqrstate solver; - linlsqrreport srep; - double creg; - double mxata; - ae_int_t bw; - ae_vector nzidx; - ae_vector nzval; - ae_int_t nzcnt; - double scaletargetsby; - double scalepenaltyby; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - memset(&xywork, 0, sizeof(xywork)); - memset(&vterm, 0, sizeof(vterm)); - memset(&sx, 0, sizeof(sx)); - memset(&sy, 0, sizeof(sy)); - memset(&sdy, 0, sizeof(sdy)); - memset(&tmpx, 0, sizeof(tmpx)); - memset(&tmpy, 0, sizeof(tmpy)); - memset(&basis1, 0, sizeof(basis1)); - memset(&av, 0, sizeof(av)); - memset(&ah, 0, sizeof(ah)); - memset(&ata, 0, sizeof(ata)); - memset(&targets, 0, sizeof(targets)); - memset(&tmp0, 0, sizeof(tmp0)); - memset(&tmp1, 0, sizeof(tmp1)); - memset(&solver, 0, sizeof(solver)); - memset(&srep, 0, sizeof(srep)); - memset(&nzidx, 0, sizeof(nzidx)); - memset(&nzval, 0, sizeof(nzval)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - _spline1dinterpolant_clear(s); - _spline1dfitreport_clear(rep); - ae_vector_init(&xywork, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vterm, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sy, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sdy, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpy, 0, DT_REAL, _state, ae_true); - _spline1dinterpolant_init(&basis1, _state, ae_true); - _sparsematrix_init(&av, _state, ae_true); - _sparsematrix_init(&ah, _state, ae_true); - _sparsematrix_init(&ata, _state, ae_true); - ae_vector_init(&targets, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true); - _linlsqrstate_init(&solver, _state, ae_true); - _linlsqrreport_init(&srep, _state, ae_true); - ae_vector_init(&nzidx, 0, DT_INT, _state, ae_true); - ae_vector_init(&nzval, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=1, "Spline1DFit: N<1!", _state); - ae_assert(m>=1, "Spline1DFit: M<1!", _state); - ae_assert(x->cnt>=n, "Spline1DFit: Length(X)cnt>=n, "Spline1DFit: Length(Y)ptr.p_double[0]; - xb = x->ptr.p_double[n-1]; - if( ae_fp_eq(xa,xb) ) - { - v = xa; - if( ae_fp_greater_eq(v,(double)(0)) ) - { - xa = v/2-1; - xb = v*2+1; - } - else - { - xa = v*2-1; - xb = v/2+1; - } - } - ae_assert(ae_fp_less(xa,xb), "Spline1DFit: integrity error", _state); - - /* - * Perform a grid correction according to current grid expansion size. - */ - m = ae_maxint(m, 4, _state); - gridexpansion = 1; - v = (xb-xa)/m; - xa = xa-v*gridexpansion; - xb = xb+v*gridexpansion; - m = m+2*gridexpansion; - - /* - * Convert X/Y to work representation, remove linear trend (in - * order to improve condition number). - * - * Compute total-sum-of-squares (needed later for R2 coefficient). - */ - ae_vector_set_length(&xywork, 2*n, _state); - for(i=0; i<=n-1; i++) - { - xywork.ptr.p_double[2*i+0] = (x->ptr.p_double[i]-xa)/(xb-xa); - xywork.ptr.p_double[2*i+1] = y->ptr.p_double[i]; - } - buildpriorterm1(&xywork, n, 1, 1, 1, 0.0, &vterm, _state); - meany = (double)(0); - for(i=0; i<=n-1; i++) - { - meany = meany+y->ptr.p_double[i]; - } - meany = meany/n; - tss = (double)(0); - for(i=0; i<=n-1; i++) - { - tss = tss+ae_sqr(y->ptr.p_double[i]-meany, _state); - } - - /* - * Build 1D compact basis function - * Generate design matrix AV ("vertical") and its transpose AH ("horizontal"). - */ - ae_vector_set_length(&tmpx, 7, _state); - ae_vector_set_length(&tmpy, 7, _state); - tmpx.ptr.p_double[0] = -(double)3/(double)(m-1); - tmpx.ptr.p_double[1] = -(double)2/(double)(m-1); - tmpx.ptr.p_double[2] = -(double)1/(double)(m-1); - tmpx.ptr.p_double[3] = (double)0/(double)(m-1); - tmpx.ptr.p_double[4] = (double)1/(double)(m-1); - tmpx.ptr.p_double[5] = (double)2/(double)(m-1); - tmpx.ptr.p_double[6] = (double)3/(double)(m-1); - tmpy.ptr.p_double[0] = (double)(0); - tmpy.ptr.p_double[1] = (double)(0); - tmpy.ptr.p_double[2] = (double)1/(double)12; - tmpy.ptr.p_double[3] = (double)2/(double)6; - tmpy.ptr.p_double[4] = (double)1/(double)12; - tmpy.ptr.p_double[5] = (double)(0); - tmpy.ptr.p_double[6] = (double)(0); - spline1dbuildcubic(&tmpx, &tmpy, tmpx.cnt, 2, 0.0, 2, 0.0, &basis1, _state); - arows = n+2*m; - sparsecreate(arows, m, 0, &av, _state); - setlengthzero(&targets, arows, _state); - scaletargetsby = 1/ae_sqrt((double)(n), _state); - scalepenaltyby = 1/ae_sqrt((double)(m), _state); - for(i=0; i<=n-1; i++) - { - - /* - * Generate design matrix row #I which corresponds to I-th dataset point - */ - k = ae_ifloor(boundval(xywork.ptr.p_double[2*i+0]*(m-1), (double)(0), (double)(m-1), _state), _state); - k0 = ae_maxint(k-(bfrad-1), 0, _state); - k1 = ae_minint(k+bfrad, m-1, _state); - for(j=k0; j<=k1; j++) - { - sparseset(&av, i, j, spline1dcalc(&basis1, xywork.ptr.p_double[2*i+0]-(double)j/(double)(m-1), _state)*scaletargetsby, _state); - } - targets.ptr.p_double[i] = xywork.ptr.p_double[2*i+1]*scaletargetsby; - } - for(i=0; i<=m-1; i++) - { - - /* - * Generate design matrix row #(I+N) which corresponds to nonlinearity penalty at I-th node - */ - k0 = ae_maxint(i-(bfrad-1), 0, _state); - k1 = ae_minint(i+(bfrad-1), m-1, _state); - for(j=k0; j<=k1; j++) - { - spline1ddiff(&basis1, (double)i/(double)(m-1)-(double)j/(double)(m-1), &v, &dv, &d2v, _state); - sparseset(&av, n+i, j, lambdans*d2v*scalepenaltyby, _state); - } - } - for(i=0; i<=m-1; i++) - { - - /* - * Generate design matrix row #(I+N+M) which corresponds to regularization for I-th coefficient - */ - sparseset(&av, n+m+i, i, spline1d_lambdareg, _state); - } - sparseconverttocrs(&av, _state); - sparsecopytransposecrs(&av, &ah, _state); - - /* - * Build 7-diagonal (bandwidth=3) normal equations matrix and perform Cholesky - * decomposition (to be used later as preconditioner for LSQR iterations). - */ - bw = 3; - sparsecreatesksband(m, m, bw, &ata, _state); - mxata = (double)(0); - for(i=0; i<=m-1; i++) - { - for(j=i; j<=ae_minint(i+bw, m-1, _state); j++) - { - - /* - * Get pattern of nonzeros in one of the rows (let it be I-th one) - * and compute dot product only for nonzero entries. - */ - sparsegetcompressedrow(&ah, i, &nzidx, &nzval, &nzcnt, _state); - v = (double)(0); - for(k=0; k<=nzcnt-1; k++) - { - v = v+sparseget(&ah, i, nzidx.ptr.p_int[k], _state)*sparseget(&ah, j, nzidx.ptr.p_int[k], _state); - } - - /* - * Update ATA and max(ATA) - */ - sparseset(&ata, i, j, v, _state); - if( i==j ) - { - mxata = ae_maxreal(mxata, ae_fabs(v, _state), _state); - } - } - } - mxata = coalesce(mxata, 1.0, _state); - creg = spline1d_cholreg; - for(;;) - { - - /* - * Regularization - */ - for(i=0; i<=m-1; i++) - { - sparseset(&ata, i, i, sparseget(&ata, i, i, _state)+mxata*creg, _state); - } - - /* - * Try Cholesky factorization. - */ - if( !sparsecholeskyskyline(&ata, m, ae_true, _state) ) - { - - /* - * Factorization failed, increase regularizer and repeat - */ - creg = coalesce(10*creg, 1.0E-12, _state); - continue; - } - break; - } - - /* - * Solve with preconditioned LSQR: - * - * use Cholesky factor U of squared design matrix A'*A to - * transform min|A*x-b| to min|[A*inv(U)]*y-b| with y=U*x. - * - * Preconditioned problem is solved with LSQR solver, which - * gives superior results to normal equations approach. Due - * to Cholesky preconditioner being utilized we can solve - * problem in just a few iterations. - */ - rvectorsetlengthatleast(&tmp0, arows, _state); - rvectorsetlengthatleast(&tmp1, m, _state); - linlsqrcreatebuf(arows, m, &solver, _state); - linlsqrsetb(&solver, &targets, _state); - linlsqrsetcond(&solver, 1.0E-14, 1.0E-14, lsqrcnt, _state); - while(linlsqriteration(&solver, _state)) - { - if( solver.needmv ) - { - for(i=0; i<=m-1; i++) - { - tmp1.ptr.p_double[i] = solver.x.ptr.p_double[i]; - } - - /* - * Use Cholesky factorization of the system matrix - * as preconditioner: solve TRSV(U,Solver.X) - */ - sparsetrsv(&ata, ae_true, ae_false, 0, &tmp1, _state); - - /* - * After preconditioning is done, multiply by A - */ - sparsemv(&av, &tmp1, &solver.mv, _state); - } - if( solver.needmtv ) - { - - /* - * Multiply by design matrix A - */ - sparsemtv(&av, &solver.x, &solver.mtv, _state); - - /* - * Multiply by preconditioner: solve TRSV(U',A*Solver.X) - */ - sparsetrsv(&ata, ae_true, ae_false, 1, &solver.mtv, _state); - } - } - linlsqrresults(&solver, &tmp1, &srep, _state); - sparsetrsv(&ata, ae_true, ae_false, 0, &tmp1, _state); - - /* - * Generate output spline as a table of spline valued and first - * derivatives at nodes (used to build Hermite spline) - */ - ae_vector_set_length(&sx, m, _state); - ae_vector_set_length(&sy, m, _state); - ae_vector_set_length(&sdy, m, _state); - for(i=0; i<=m-1; i++) - { - sx.ptr.p_double[i] = (double)i/(double)(m-1); - sy.ptr.p_double[i] = (double)(0); - sdy.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=m-1; i++) - { - k0 = ae_maxint(i-(bfrad-1), 0, _state); - k1 = ae_minint(i+bfrad, m-1, _state); - for(j=k0; j<=k1; j++) - { - spline1ddiff(&basis1, (double)j/(double)(m-1)-(double)i/(double)(m-1), &v, &dv, &d2v, _state); - sy.ptr.p_double[j] = sy.ptr.p_double[j]+tmp1.ptr.p_double[i]*v; - sdy.ptr.p_double[j] = sdy.ptr.p_double[j]+tmp1.ptr.p_double[i]*dv; - } - } - - /* - * Calculate model values - */ - sparsemv(&av, &tmp1, &tmp0, _state); - for(i=0; i<=n-1; i++) - { - tmp0.ptr.p_double[i] = tmp0.ptr.p_double[i]/scaletargetsby; - } - rss = 0.0; - nrel = 0; - rep->rmserror = (double)(0); - rep->maxerror = (double)(0); - rep->avgerror = (double)(0); - rep->avgrelerror = (double)(0); - for(i=0; i<=n-1; i++) - { - v = xywork.ptr.p_double[2*i+1]-tmp0.ptr.p_double[i]; - rss = rss+v*v; - rep->rmserror = rep->rmserror+ae_sqr(v, _state); - rep->avgerror = rep->avgerror+ae_fabs(v, _state); - rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(v, _state), _state); - if( ae_fp_neq(y->ptr.p_double[i],(double)(0)) ) - { - rep->avgrelerror = rep->avgrelerror+ae_fabs(v/y->ptr.p_double[i], _state); - nrel = nrel+1; - } - } - rep->rmserror = ae_sqrt(rep->rmserror/n, _state); - rep->avgerror = rep->avgerror/n; - rep->avgrelerror = rep->avgrelerror/coalesce((double)(nrel), 1.0, _state); - - /* - * Append prior term. - * Transform spline to original coordinates. - * Output. - */ - for(i=0; i<=m-1; i++) - { - sy.ptr.p_double[i] = sy.ptr.p_double[i]+vterm.ptr.pp_double[0][0]*sx.ptr.p_double[i]+vterm.ptr.pp_double[0][1]; - sdy.ptr.p_double[i] = sdy.ptr.p_double[i]+vterm.ptr.pp_double[0][0]; - } - for(i=0; i<=m-1; i++) - { - sx.ptr.p_double[i] = sx.ptr.p_double[i]*(xb-xa)+xa; - sdy.ptr.p_double[i] = sdy.ptr.p_double[i]/(xb-xa); - } - spline1dbuildhermite(&sx, &sy, &sdy, m, s, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal version of Spline1DConvDiff - -Converts from Hermite spline given by grid XOld to new grid X2 - -INPUT PARAMETERS: - XOld - old grid - YOld - values at old grid - DOld - first derivative at old grid - N - grid size - X2 - new grid - N2 - new grid size - Y - possibly preallocated output array - (reallocate if too small) - NeedY - do we need Y? - D1 - possibly preallocated output array - (reallocate if too small) - NeedD1 - do we need D1? - D2 - possibly preallocated output array - (reallocate if too small) - NeedD2 - do we need D1? - -OUTPUT ARRAYS: - Y - values, if needed - D1 - first derivative, if needed - D2 - second derivative, if needed - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -void spline1dconvdiffinternal(/* Real */ ae_vector* xold, - /* Real */ ae_vector* yold, - /* Real */ ae_vector* dold, - ae_int_t n, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Real */ ae_vector* y, - ae_bool needy, - /* Real */ ae_vector* d1, - ae_bool needd1, - /* Real */ ae_vector* d2, - ae_bool needd2, - ae_state *_state) -{ - ae_int_t intervalindex; - ae_int_t pointindex; - ae_bool havetoadvance; - double c0; - double c1; - double c2; - double c3; - double a; - double b; - double w; - double w2; - double w3; - double fa; - double fb; - double da; - double db; - double t; - - - - /* - * Prepare space - */ - if( needy&&y->cntcntcnt=n2 ) - { - break; - } - t = x2->ptr.p_double[pointindex]; - - /* - * do we need to advance interval? - */ - havetoadvance = ae_false; - if( intervalindex==-1 ) - { - havetoadvance = ae_true; - } - else - { - if( intervalindexptr.p_double[intervalindex]; - b = xold->ptr.p_double[intervalindex+1]; - w = b-a; - w2 = w*w; - w3 = w*w2; - fa = yold->ptr.p_double[intervalindex]; - fb = yold->ptr.p_double[intervalindex+1]; - da = dold->ptr.p_double[intervalindex]; - db = dold->ptr.p_double[intervalindex+1]; - c0 = fa; - c1 = da; - c2 = (3*(fb-fa)-2*da*w-db*w)/w2; - c3 = (2*(fa-fb)+da*w+db*w)/w3; - continue; - } - - /* - * Calculate spline and its derivatives using power basis - */ - t = t-a; - if( needy ) - { - y->ptr.p_double[pointindex] = c0+t*(c1+t*(c2+t*c3)); - } - if( needd1 ) - { - d1->ptr.p_double[pointindex] = c1+2*t*c2+3*t*t*c3; - } - if( needd2 ) - { - d2->ptr.p_double[pointindex] = 2*c2+6*t*c3; - } - pointindex = pointindex+1; - } -} - - -/************************************************************************* -This function finds all roots and extrema of the spline S(x) defined at -[A,B] (interval which contains spline nodes). - -It does not extrapolates function, so roots and extrema located outside -of [A,B] will not be found. It returns all isolated (including multiple) -roots and extrema. - -INPUT PARAMETERS - C - spline interpolant - -OUTPUT PARAMETERS - R - array[NR], contains roots of the spline. - In case there is no roots, this array has zero length. - NR - number of roots, >=0 - DR - is set to True in case there is at least one interval - where spline is just a zero constant. Such degenerate - cases are not reported in the R/NR - E - array[NE], contains extrema (maximums/minimums) of - the spline. In case there is no extrema, this array - has zero length. - ET - array[NE], extrema types: - * ET[i]>0 in case I-th extrema is a minimum - * ET[i]<0 in case I-th extrema is a maximum - NE - number of extrema, >=0 - DE - is set to True in case there is at least one interval - where spline is a constant. Such degenerate cases are - not reported in the E/NE. - -NOTES: - -1. This function does NOT report following kinds of roots: - * intervals where function is constantly zero - * roots which are outside of [A,B] (note: it CAN return A or B) - -2. This function does NOT report following kinds of extrema: - * intervals where function is a constant - * extrema which are outside of (A,B) (note: it WON'T return A or B) - - -- ALGLIB PROJECT -- - Copyright 26.09.2011 by Bochkanov Sergey -*************************************************************************/ -void spline1drootsandextrema(spline1dinterpolant* c, - /* Real */ ae_vector* r, - ae_int_t* nr, - ae_bool* dr, - /* Real */ ae_vector* e, - /* Integer */ ae_vector* et, - ae_int_t* ne, - ae_bool* de, - ae_state *_state) -{ - ae_frame _frame_block; - double pl; - double ml; - double pll; - double pr; - double mr; - ae_vector tr; - ae_vector tmpr; - ae_vector tmpe; - ae_vector tmpet; - ae_vector tmpc; - double x0; - double x1; - double x2; - double ex0; - double ex1; - ae_int_t tne; - ae_int_t tnr; - ae_int_t i; - ae_int_t j; - ae_bool nstep; - - ae_frame_make(_state, &_frame_block); - memset(&tr, 0, sizeof(tr)); - memset(&tmpr, 0, sizeof(tmpr)); - memset(&tmpe, 0, sizeof(tmpe)); - memset(&tmpet, 0, sizeof(tmpet)); - memset(&tmpc, 0, sizeof(tmpc)); - ae_vector_clear(r); - *nr = 0; - *dr = ae_false; - ae_vector_clear(e); - ae_vector_clear(et); - *ne = 0; - *de = ae_false; - ae_vector_init(&tr, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpr, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpe, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpet, 0, DT_INT, _state, ae_true); - ae_vector_init(&tmpc, 0, DT_REAL, _state, ae_true); - - - /* - *exception handling - */ - ae_assert(c->k==3, "Spline1DRootsAndExtrema : incorrect parameter C.K!", _state); - ae_assert(c->continuity>=0, "Spline1DRootsAndExtrema : parameter C.Continuity must not be less than 0!", _state); - - /* - *initialization of variable - */ - *nr = 0; - *ne = 0; - *dr = ae_false; - *de = ae_false; - nstep = ae_true; - - /* - *consider case, when C.Continuty=0 - */ - if( c->continuity==0 ) - { - - /* - *allocation for auxiliary arrays - *'TmpR ' - it stores a time value for roots - *'TmpE ' - it stores a time value for extremums - *'TmpET '- it stores a time value for extremums type - */ - rvectorsetlengthatleast(&tmpr, 3*(c->n-1), _state); - rvectorsetlengthatleast(&tmpe, 2*(c->n-1), _state); - ivectorsetlengthatleast(&tmpet, 2*(c->n-1), _state); - - /* - *start calculating - */ - for(i=0; i<=c->n-2; i++) - { - - /* - *initialization pL, mL, pR, mR - */ - pl = c->c.ptr.p_double[4*i]; - ml = c->c.ptr.p_double[4*i+1]; - pr = c->c.ptr.p_double[4*(i+1)]; - mr = c->c.ptr.p_double[4*i+1]+2*c->c.ptr.p_double[4*i+2]*(c->x.ptr.p_double[i+1]-c->x.ptr.p_double[i])+3*c->c.ptr.p_double[4*i+3]*(c->x.ptr.p_double[i+1]-c->x.ptr.p_double[i])*(c->x.ptr.p_double[i+1]-c->x.ptr.p_double[i]); - - /* - *pre-searching roots and extremums - */ - solvecubicpolinom(pl, ml, pr, mr, c->x.ptr.p_double[i], c->x.ptr.p_double[i+1], &x0, &x1, &x2, &ex0, &ex1, &tnr, &tne, &tr, _state); - *dr = *dr||tnr==-1; - *de = *de||tne==-1; - - /* - *searching of roots - */ - if( tnr==1&&nstep ) - { - - /* - *is there roots? - */ - if( *nr>0 ) - { - - /* - *is a next root equal a previous root? - *if is't, then write new root - */ - if( ae_fp_neq(x0,tmpr.ptr.p_double[*nr-1]) ) - { - tmpr.ptr.p_double[*nr] = x0; - *nr = *nr+1; - } - } - else - { - - /* - *write a first root - */ - tmpr.ptr.p_double[*nr] = x0; - *nr = *nr+1; - } - } - else - { - - /* - *case when function at a segment identically to zero - *then we have to clear a root, if the one located on a - *constant segment - */ - if( tnr==-1 ) - { - - /* - *safe state variable as constant - */ - if( nstep ) - { - nstep = ae_false; - } - - /* - *clear the root, if there is - */ - if( *nr>0 ) - { - if( ae_fp_eq(c->x.ptr.p_double[i],tmpr.ptr.p_double[*nr-1]) ) - { - *nr = *nr-1; - } - } - - /* - *change state for 'DR' - */ - if( !*dr ) - { - *dr = ae_true; - } - } - else - { - nstep = ae_true; - } - } - - /* - *searching of extremums - */ - if( i>0 ) - { - pll = c->c.ptr.p_double[4*(i-1)]; - - /* - *if pL=pLL or pL=pR then - */ - if( tne==-1 ) - { - if( !*de ) - { - *de = ae_true; - } - } - else - { - if( ae_fp_greater(pl,pll)&&ae_fp_greater(pl,pr) ) - { - - /* - *maximum - */ - tmpet.ptr.p_int[*ne] = -1; - tmpe.ptr.p_double[*ne] = c->x.ptr.p_double[i]; - *ne = *ne+1; - } - else - { - if( ae_fp_less(pl,pll)&&ae_fp_less(pl,pr) ) - { - - /* - *minimum - */ - tmpet.ptr.p_int[*ne] = 1; - tmpe.ptr.p_double[*ne] = c->x.ptr.p_double[i]; - *ne = *ne+1; - } - } - } - } - } - - /* - *write final result - */ - rvectorsetlengthatleast(r, *nr, _state); - rvectorsetlengthatleast(e, *ne, _state); - ivectorsetlengthatleast(et, *ne, _state); - - /* - *write roots - */ - for(i=0; i<=*nr-1; i++) - { - r->ptr.p_double[i] = tmpr.ptr.p_double[i]; - } - - /* - *write extremums and their types - */ - for(i=0; i<=*ne-1; i++) - { - e->ptr.p_double[i] = tmpe.ptr.p_double[i]; - et->ptr.p_int[i] = tmpet.ptr.p_int[i]; - } - } - else - { - - /* - *case, when C.Continuity>=1 - *'TmpR ' - it stores a time value for roots - *'TmpC' - it stores a time value for extremums and - *their function value (TmpC={EX0,F(EX0), EX1,F(EX1), ..., EXn,F(EXn)};) - *'TmpE' - it stores a time value for extremums only - *'TmpET'- it stores a time value for extremums type - */ - rvectorsetlengthatleast(&tmpr, 2*c->n-1, _state); - rvectorsetlengthatleast(&tmpc, 4*c->n, _state); - rvectorsetlengthatleast(&tmpe, 2*c->n, _state); - ivectorsetlengthatleast(&tmpet, 2*c->n, _state); - - /* - *start calculating - */ - for(i=0; i<=c->n-2; i++) - { - - /* - *we calculate pL,mL, pR,mR as Fi+1(F'i+1) at left border - */ - pl = c->c.ptr.p_double[4*i]; - ml = c->c.ptr.p_double[4*i+1]; - pr = c->c.ptr.p_double[4*(i+1)]; - mr = c->c.ptr.p_double[4*(i+1)+1]; - - /* - *calculating roots and extremums at [X[i],X[i+1]] - */ - solvecubicpolinom(pl, ml, pr, mr, c->x.ptr.p_double[i], c->x.ptr.p_double[i+1], &x0, &x1, &x2, &ex0, &ex1, &tnr, &tne, &tr, _state); - - /* - *searching roots - */ - if( tnr>0 ) - { - - /* - *re-init tR - */ - if( tnr>=1 ) - { - tr.ptr.p_double[0] = x0; - } - if( tnr>=2 ) - { - tr.ptr.p_double[1] = x1; - } - if( tnr==3 ) - { - tr.ptr.p_double[2] = x2; - } - - /* - *start root selection - */ - if( *nr>0 ) - { - if( ae_fp_neq(tmpr.ptr.p_double[*nr-1],x0) ) - { - - /* - *previous segment was't constant identical zero - */ - if( nstep ) - { - for(j=0; j<=tnr-1; j++) - { - tmpr.ptr.p_double[*nr+j] = tr.ptr.p_double[j]; - } - *nr = *nr+tnr; - } - else - { - - /* - *previous segment was constant identical zero - *and we must ignore [NR+j-1] root - */ - for(j=1; j<=tnr-1; j++) - { - tmpr.ptr.p_double[*nr+j-1] = tr.ptr.p_double[j]; - } - *nr = *nr+tnr-1; - nstep = ae_true; - } - } - else - { - for(j=1; j<=tnr-1; j++) - { - tmpr.ptr.p_double[*nr+j-1] = tr.ptr.p_double[j]; - } - *nr = *nr+tnr-1; - } - } - else - { - - /* - *write first root - */ - for(j=0; j<=tnr-1; j++) - { - tmpr.ptr.p_double[*nr+j] = tr.ptr.p_double[j]; - } - *nr = *nr+tnr; - } - } - else - { - if( tnr==-1 ) - { - - /* - *decrement 'NR' if at previous step was writen a root - *(previous segment identical zero) - */ - if( *nr>0&&nstep ) - { - *nr = *nr-1; - } - - /* - *previous segment is't constant - */ - if( nstep ) - { - nstep = ae_false; - } - - /* - *rewrite 'DR' - */ - if( !*dr ) - { - *dr = ae_true; - } - } - } - - /* - *searching extremums - *write all term like extremums - */ - if( tne==1 ) - { - if( *ne>0 ) - { - - /* - *just ignore identical extremums - *because he must be one - */ - if( ae_fp_neq(tmpc.ptr.p_double[*ne-2],ex0) ) - { - tmpc.ptr.p_double[*ne] = ex0; - tmpc.ptr.p_double[*ne+1] = c->c.ptr.p_double[4*i]+c->c.ptr.p_double[4*i+1]*(ex0-c->x.ptr.p_double[i])+c->c.ptr.p_double[4*i+2]*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i])+c->c.ptr.p_double[4*i+3]*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i]); - *ne = *ne+2; - } - } - else - { - - /* - *write first extremum and it function value - */ - tmpc.ptr.p_double[*ne] = ex0; - tmpc.ptr.p_double[*ne+1] = c->c.ptr.p_double[4*i]+c->c.ptr.p_double[4*i+1]*(ex0-c->x.ptr.p_double[i])+c->c.ptr.p_double[4*i+2]*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i])+c->c.ptr.p_double[4*i+3]*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i]); - *ne = *ne+2; - } - } - else - { - if( tne==2 ) - { - if( *ne>0 ) - { - - /* - *ignore identical extremum - */ - if( ae_fp_neq(tmpc.ptr.p_double[*ne-2],ex0) ) - { - tmpc.ptr.p_double[*ne] = ex0; - tmpc.ptr.p_double[*ne+1] = c->c.ptr.p_double[4*i]+c->c.ptr.p_double[4*i+1]*(ex0-c->x.ptr.p_double[i])+c->c.ptr.p_double[4*i+2]*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i])+c->c.ptr.p_double[4*i+3]*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i]); - *ne = *ne+2; - } - } - else - { - - /* - *write first extremum - */ - tmpc.ptr.p_double[*ne] = ex0; - tmpc.ptr.p_double[*ne+1] = c->c.ptr.p_double[4*i]+c->c.ptr.p_double[4*i+1]*(ex0-c->x.ptr.p_double[i])+c->c.ptr.p_double[4*i+2]*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i])+c->c.ptr.p_double[4*i+3]*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i]); - *ne = *ne+2; - } - - /* - *write second extremum - */ - tmpc.ptr.p_double[*ne] = ex1; - tmpc.ptr.p_double[*ne+1] = c->c.ptr.p_double[4*i]+c->c.ptr.p_double[4*i+1]*(ex1-c->x.ptr.p_double[i])+c->c.ptr.p_double[4*i+2]*(ex1-c->x.ptr.p_double[i])*(ex1-c->x.ptr.p_double[i])+c->c.ptr.p_double[4*i+3]*(ex1-c->x.ptr.p_double[i])*(ex1-c->x.ptr.p_double[i])*(ex1-c->x.ptr.p_double[i]); - *ne = *ne+2; - } - else - { - if( tne==-1 ) - { - if( !*de ) - { - *de = ae_true; - } - } - } - } - } - - /* - *checking of arrays - *get number of extremums (tNe=NE/2) - *initialize pL as value F0(X[0]) and - *initialize pR as value Fn-1(X[N]) - */ - tne = *ne/2; - *ne = 0; - pl = c->c.ptr.p_double[0]; - pr = c->c.ptr.p_double[4*(c->n-1)]; - for(i=0; i<=tne-1; i++) - { - if( i>0&&ix.ptr.p_double[0]) ) - { - if( ae_fp_greater(tmpc.ptr.p_double[2*i+1],pl)&&ae_fp_greater(tmpc.ptr.p_double[2*i+1],tmpc.ptr.p_double[2*(i+1)+1]) ) - { - - /* - *maximum - */ - tmpe.ptr.p_double[*ne] = tmpc.ptr.p_double[2*i]; - tmpet.ptr.p_int[*ne] = -1; - *ne = *ne+1; - } - else - { - if( ae_fp_less(tmpc.ptr.p_double[2*i+1],pl)&&ae_fp_less(tmpc.ptr.p_double[2*i+1],tmpc.ptr.p_double[2*(i+1)+1]) ) - { - - /* - *minimum - */ - tmpe.ptr.p_double[*ne] = tmpc.ptr.p_double[2*i]; - tmpet.ptr.p_int[*ne] = 1; - *ne = *ne+1; - } - } - } - } - else - { - if( i==tne-1 ) - { - if( ae_fp_neq(tmpc.ptr.p_double[2*i],c->x.ptr.p_double[c->n-1]) ) - { - if( ae_fp_greater(tmpc.ptr.p_double[2*i+1],tmpc.ptr.p_double[2*(i-1)+1])&&ae_fp_greater(tmpc.ptr.p_double[2*i+1],pr) ) - { - - /* - *maximum - */ - tmpe.ptr.p_double[*ne] = tmpc.ptr.p_double[2*i]; - tmpet.ptr.p_int[*ne] = -1; - *ne = *ne+1; - } - else - { - if( ae_fp_less(tmpc.ptr.p_double[2*i+1],tmpc.ptr.p_double[2*(i-1)+1])&&ae_fp_less(tmpc.ptr.p_double[2*i+1],pr) ) - { - - /* - *minimum - */ - tmpe.ptr.p_double[*ne] = tmpc.ptr.p_double[2*i]; - tmpet.ptr.p_int[*ne] = 1; - *ne = *ne+1; - } - } - } - } - } - } - } - - /* - *final results - *allocate R, E, ET - */ - rvectorsetlengthatleast(r, *nr, _state); - rvectorsetlengthatleast(e, *ne, _state); - ivectorsetlengthatleast(et, *ne, _state); - - /* - *write result for extremus and their types - */ - for(i=0; i<=*ne-1; i++) - { - e->ptr.p_double[i] = tmpe.ptr.p_double[i]; - et->ptr.p_int[i] = tmpet.ptr.p_int[i]; - } - - /* - *write result for roots - */ - for(i=0; i<=*nr-1; i++) - { - r->ptr.p_double[i] = tmpr.ptr.p_double[i]; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal subroutine. Heap sort. -*************************************************************************/ -void heapsortdpoints(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* d, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector rbuf; - ae_vector ibuf; - ae_vector rbuf2; - ae_vector ibuf2; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&rbuf, 0, sizeof(rbuf)); - memset(&ibuf, 0, sizeof(ibuf)); - memset(&rbuf2, 0, sizeof(rbuf2)); - memset(&ibuf2, 0, sizeof(ibuf2)); - ae_vector_init(&rbuf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ibuf, 0, DT_INT, _state, ae_true); - ae_vector_init(&rbuf2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ibuf2, 0, DT_INT, _state, ae_true); - - ae_vector_set_length(&ibuf, n, _state); - ae_vector_set_length(&rbuf, n, _state); - for(i=0; i<=n-1; i++) - { - ibuf.ptr.p_int[i] = i; - } - tagsortfasti(x, &ibuf, &rbuf2, &ibuf2, n, _state); - for(i=0; i<=n-1; i++) - { - rbuf.ptr.p_double[i] = y->ptr.p_double[ibuf.ptr.p_int[i]]; - } - ae_v_move(&y->ptr.p_double[0], 1, &rbuf.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - rbuf.ptr.p_double[i] = d->ptr.p_double[ibuf.ptr.p_int[i]]; - } - ae_v_move(&d->ptr.p_double[0], 1, &rbuf.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -This procedure search roots of an quadratic equation inside [0;1] and it number of roots. - -INPUT PARAMETERS: - P0 - value of a function at 0 - M0 - value of a derivative at 0 - P1 - value of a function at 1 - M1 - value of a derivative at 1 - -OUTPUT PARAMETERS: - X0 - first root of an equation - X1 - second root of an equation - NR - number of roots - -RESTRICTIONS OF PARAMETERS: - -Parameters for this procedure has't to be zero simultaneously. Is expected, -that input polinom is't degenerate or constant identicaly ZERO. - - -REMARK: - -The procedure always fill value for X1 and X2, even if it is't belongs to [0;1]. -But first true root(even if existing one) is in X1. -Number of roots is NR. - - -- ALGLIB PROJECT -- - Copyright 26.09.2011 by Bochkanov Sergey -*************************************************************************/ -void solvepolinom2(double p0, - double m0, - double p1, - double m1, - double* x0, - double* x1, - ae_int_t* nr, - ae_state *_state) -{ - double a; - double b; - double c; - double dd; - double tmp; - double exf; - double extr; - - *x0 = 0; - *x1 = 0; - *nr = 0; - - - /* - *calculate parameters for equation: A, B and C - */ - a = 6*p0+3*m0-6*p1+3*m1; - b = -6*p0-4*m0+6*p1-2*m1; - c = m0; - - /* - *check case, when A=0 - *we are considering the linear equation - */ - if( ae_fp_eq(a,(double)(0)) ) - { - - /* - *B<>0 and root inside [0;1] - *one root - */ - if( (ae_fp_neq(b,(double)(0))&&ae_sign(c, _state)*ae_sign(b, _state)<=0)&&ae_fp_greater_eq(ae_fabs(b, _state),ae_fabs(c, _state)) ) - { - *x0 = -c/b; - *nr = 1; - return; - } - else - { - *nr = 0; - return; - } - } - - /* - *consider case, when extremumu outside (0;1) - *exist one root only - */ - if( ae_fp_less_eq(ae_fabs(2*a, _state),ae_fabs(b, _state))||ae_sign(b, _state)*ae_sign(a, _state)>=0 ) - { - if( ae_sign(m0, _state)*ae_sign(m1, _state)>0 ) - { - *nr = 0; - return; - } - - /* - *consider case, when the one exist - *same sign of derivative - */ - if( ae_sign(m0, _state)*ae_sign(m1, _state)<0 ) - { - *nr = 1; - extr = -b/(2*a); - dd = b*b-4*a*c; - if( ae_fp_less(dd,(double)(0)) ) - { - return; - } - *x0 = (-b-ae_sqrt(dd, _state))/(2*a); - *x1 = (-b+ae_sqrt(dd, _state))/(2*a); - if( (ae_fp_greater_eq(extr,(double)(1))&&ae_fp_less_eq(*x1,extr))||(ae_fp_less_eq(extr,(double)(0))&&ae_fp_greater_eq(*x1,extr)) ) - { - *x0 = *x1; - } - return; - } - - /* - *consider case, when the one is 0 - */ - if( ae_fp_eq(m0,(double)(0)) ) - { - *x0 = (double)(0); - *nr = 1; - return; - } - if( ae_fp_eq(m1,(double)(0)) ) - { - *x0 = (double)(1); - *nr = 1; - return; - } - } - else - { - - /* - *consider case, when both of derivatives is 0 - */ - if( ae_fp_eq(m0,(double)(0))&&ae_fp_eq(m1,(double)(0)) ) - { - *x0 = (double)(0); - *x1 = (double)(1); - *nr = 2; - return; - } - - /* - *consider case, when derivative at 0 is 0, and derivative at 1 is't 0 - */ - if( ae_fp_eq(m0,(double)(0))&&ae_fp_neq(m1,(double)(0)) ) - { - dd = b*b-4*a*c; - if( ae_fp_less(dd,(double)(0)) ) - { - *x0 = (double)(0); - *nr = 1; - return; - } - *x0 = (-b-ae_sqrt(dd, _state))/(2*a); - *x1 = (-b+ae_sqrt(dd, _state))/(2*a); - extr = -b/(2*a); - exf = a*extr*extr+b*extr+c; - if( ae_sign(exf, _state)*ae_sign(m1, _state)>0 ) - { - *x0 = (double)(0); - *nr = 1; - return; - } - else - { - if( ae_fp_greater(extr,*x0) ) - { - *x0 = (double)(0); - } - else - { - *x1 = (double)(0); - } - *nr = 2; - - /* - *roots must placed ascending - */ - if( ae_fp_greater(*x0,*x1) ) - { - tmp = *x0; - *x0 = *x1; - *x1 = tmp; - } - return; - } - } - if( ae_fp_eq(m1,(double)(0))&&ae_fp_neq(m0,(double)(0)) ) - { - dd = b*b-4*a*c; - if( ae_fp_less(dd,(double)(0)) ) - { - *x0 = (double)(1); - *nr = 1; - return; - } - *x0 = (-b-ae_sqrt(dd, _state))/(2*a); - *x1 = (-b+ae_sqrt(dd, _state))/(2*a); - extr = -b/(2*a); - exf = a*extr*extr+b*extr+c; - if( ae_sign(exf, _state)*ae_sign(m0, _state)>0 ) - { - *x0 = (double)(1); - *nr = 1; - return; - } - else - { - if( ae_fp_less(extr,*x0) ) - { - *x0 = (double)(1); - } - else - { - *x1 = (double)(1); - } - *nr = 2; - - /* - *roots must placed ascending - */ - if( ae_fp_greater(*x0,*x1) ) - { - tmp = *x0; - *x0 = *x1; - *x1 = tmp; - } - return; - } - } - else - { - extr = -b/(2*a); - exf = a*extr*extr+b*extr+c; - if( ae_sign(exf, _state)*ae_sign(m0, _state)>0&&ae_sign(exf, _state)*ae_sign(m1, _state)>0 ) - { - *nr = 0; - return; - } - dd = b*b-4*a*c; - if( ae_fp_less(dd,(double)(0)) ) - { - *nr = 0; - return; - } - *x0 = (-b-ae_sqrt(dd, _state))/(2*a); - *x1 = (-b+ae_sqrt(dd, _state))/(2*a); - - /* - *if EXF and m0, EXF and m1 has different signs, then equation has two roots - */ - if( ae_sign(exf, _state)*ae_sign(m0, _state)<0&&ae_sign(exf, _state)*ae_sign(m1, _state)<0 ) - { - *nr = 2; - - /* - *roots must placed ascending - */ - if( ae_fp_greater(*x0,*x1) ) - { - tmp = *x0; - *x0 = *x1; - *x1 = tmp; - } - return; - } - else - { - *nr = 1; - if( ae_sign(exf, _state)*ae_sign(m0, _state)<0 ) - { - if( ae_fp_less(*x1,extr) ) - { - *x0 = *x1; - } - return; - } - if( ae_sign(exf, _state)*ae_sign(m1, _state)<0 ) - { - if( ae_fp_greater(*x1,extr) ) - { - *x0 = *x1; - } - return; - } - } - } - } -} - - -/************************************************************************* -This procedure search roots of an cubic equation inside [A;B], it number of roots -and number of extremums. - -INPUT PARAMETERS: - pA - value of a function at A - mA - value of a derivative at A - pB - value of a function at B - mB - value of a derivative at B - A0 - left border [A0;B0] - B0 - right border [A0;B0] - -OUTPUT PARAMETERS: - X0 - first root of an equation - X1 - second root of an equation - X2 - third root of an equation - EX0 - first extremum of a function - EX0 - second extremum of a function - NR - number of roots - NR - number of extrmums - -RESTRICTIONS OF PARAMETERS: - -Length of [A;B] must be positive and is't zero, i.e. A<>B and AB - */ - ae_assert(ae_fp_less(a,b), "\nSolveCubicPolinom: incorrect borders for [A;B]!\n", _state); - - /* - *case 1 - *function can be identicaly to ZERO - */ - if( ((ae_fp_eq(ma,(double)(0))&&ae_fp_eq(mb,(double)(0)))&&ae_fp_eq(pa,pb))&&ae_fp_eq(pa,(double)(0)) ) - { - *nr = -1; - *ne = -1; - return; - } - if( (ae_fp_eq(ma,(double)(0))&&ae_fp_eq(mb,(double)(0)))&&ae_fp_eq(pa,pb) ) - { - *nr = 0; - *ne = -1; - return; - } - tmpma = ma*(b-a); - tmpmb = mb*(b-a); - solvepolinom2(pa, tmpma, pb, tmpmb, ex0, ex1, ne, _state); - *ex0 = spline1d_rescaleval((double)(0), (double)(1), a, b, *ex0, _state); - *ex1 = spline1d_rescaleval((double)(0), (double)(1), a, b, *ex1, _state); - - /* - *case 3.1 - *no extremums at [A;B] - */ - if( *ne==0 ) - { - *nr = bisectmethod(pa, tmpma, pb, tmpmb, (double)(0), (double)(1), x0, _state); - if( *nr==1 ) - { - *x0 = spline1d_rescaleval((double)(0), (double)(1), a, b, *x0, _state); - } - return; - } - - /* - *case 3.2 - *one extremum - */ - if( *ne==1 ) - { - if( ae_fp_eq(*ex0,a)||ae_fp_eq(*ex0,b) ) - { - *nr = bisectmethod(pa, tmpma, pb, tmpmb, (double)(0), (double)(1), x0, _state); - if( *nr==1 ) - { - *x0 = spline1d_rescaleval((double)(0), (double)(1), a, b, *x0, _state); - } - return; - } - else - { - *nr = 0; - i = 0; - tex0 = spline1d_rescaleval(a, b, (double)(0), (double)(1), *ex0, _state); - *nr = bisectmethod(pa, tmpma, pb, tmpmb, (double)(0), tex0, x0, _state)+(*nr); - if( *nr>i ) - { - tempdata->ptr.p_double[i] = spline1d_rescaleval((double)(0), tex0, a, *ex0, *x0, _state); - i = i+1; - } - *nr = bisectmethod(pa, tmpma, pb, tmpmb, tex0, (double)(1), x0, _state)+(*nr); - if( *nr>i ) - { - *x0 = spline1d_rescaleval(tex0, (double)(1), *ex0, b, *x0, _state); - if( i>0 ) - { - if( ae_fp_neq(*x0,tempdata->ptr.p_double[i-1]) ) - { - tempdata->ptr.p_double[i] = *x0; - i = i+1; - } - else - { - *nr = *nr-1; - } - } - else - { - tempdata->ptr.p_double[i] = *x0; - i = i+1; - } - } - if( *nr>0 ) - { - *x0 = tempdata->ptr.p_double[0]; - if( *nr>1 ) - { - *x1 = tempdata->ptr.p_double[1]; - } - return; - } - } - return; - } - else - { - - /* - *case 3.3 - *two extremums(or more, but it's impossible) - * - * - *case 3.3.0 - *both extremums at the border - */ - if( ae_fp_eq(*ex0,a)&&ae_fp_eq(*ex1,b) ) - { - *nr = bisectmethod(pa, tmpma, pb, tmpmb, (double)(0), (double)(1), x0, _state); - if( *nr==1 ) - { - *x0 = spline1d_rescaleval((double)(0), (double)(1), a, b, *x0, _state); - } - return; - } - if( ae_fp_eq(*ex0,a)&&ae_fp_neq(*ex1,b) ) - { - *nr = 0; - i = 0; - tex1 = spline1d_rescaleval(a, b, (double)(0), (double)(1), *ex1, _state); - *nr = bisectmethod(pa, tmpma, pb, tmpmb, (double)(0), tex1, x0, _state)+(*nr); - if( *nr>i ) - { - tempdata->ptr.p_double[i] = spline1d_rescaleval((double)(0), tex1, a, *ex1, *x0, _state); - i = i+1; - } - *nr = bisectmethod(pa, tmpma, pb, tmpmb, tex1, (double)(1), x0, _state)+(*nr); - if( *nr>i ) - { - *x0 = spline1d_rescaleval(tex1, (double)(1), *ex1, b, *x0, _state); - if( ae_fp_neq(*x0,tempdata->ptr.p_double[i-1]) ) - { - tempdata->ptr.p_double[i] = *x0; - i = i+1; - } - else - { - *nr = *nr-1; - } - } - if( *nr>0 ) - { - *x0 = tempdata->ptr.p_double[0]; - if( *nr>1 ) - { - *x1 = tempdata->ptr.p_double[1]; - } - return; - } - } - if( ae_fp_eq(*ex1,b)&&ae_fp_neq(*ex0,a) ) - { - *nr = 0; - i = 0; - tex0 = spline1d_rescaleval(a, b, (double)(0), (double)(1), *ex0, _state); - *nr = bisectmethod(pa, tmpma, pb, tmpmb, (double)(0), tex0, x0, _state)+(*nr); - if( *nr>i ) - { - tempdata->ptr.p_double[i] = spline1d_rescaleval((double)(0), tex0, a, *ex0, *x0, _state); - i = i+1; - } - *nr = bisectmethod(pa, tmpma, pb, tmpmb, tex0, (double)(1), x0, _state)+(*nr); - if( *nr>i ) - { - *x0 = spline1d_rescaleval(tex0, (double)(1), *ex0, b, *x0, _state); - if( i>0 ) - { - if( ae_fp_neq(*x0,tempdata->ptr.p_double[i-1]) ) - { - tempdata->ptr.p_double[i] = *x0; - i = i+1; - } - else - { - *nr = *nr-1; - } - } - else - { - tempdata->ptr.p_double[i] = *x0; - i = i+1; - } - } - if( *nr>0 ) - { - *x0 = tempdata->ptr.p_double[0]; - if( *nr>1 ) - { - *x1 = tempdata->ptr.p_double[1]; - } - return; - } - } - else - { - - /* - *case 3.3.2 - *both extremums inside (0;1) - */ - *nr = 0; - i = 0; - tex0 = spline1d_rescaleval(a, b, (double)(0), (double)(1), *ex0, _state); - tex1 = spline1d_rescaleval(a, b, (double)(0), (double)(1), *ex1, _state); - *nr = bisectmethod(pa, tmpma, pb, tmpmb, (double)(0), tex0, x0, _state)+(*nr); - if( *nr>i ) - { - tempdata->ptr.p_double[i] = spline1d_rescaleval((double)(0), tex0, a, *ex0, *x0, _state); - i = i+1; - } - *nr = bisectmethod(pa, tmpma, pb, tmpmb, tex0, tex1, x0, _state)+(*nr); - if( *nr>i ) - { - *x0 = spline1d_rescaleval(tex0, tex1, *ex0, *ex1, *x0, _state); - if( i>0 ) - { - if( ae_fp_neq(*x0,tempdata->ptr.p_double[i-1]) ) - { - tempdata->ptr.p_double[i] = *x0; - i = i+1; - } - else - { - *nr = *nr-1; - } - } - else - { - tempdata->ptr.p_double[i] = *x0; - i = i+1; - } - } - *nr = bisectmethod(pa, tmpma, pb, tmpmb, tex1, (double)(1), x0, _state)+(*nr); - if( *nr>i ) - { - *x0 = spline1d_rescaleval(tex1, (double)(1), *ex1, b, *x0, _state); - if( i>0 ) - { - if( ae_fp_neq(*x0,tempdata->ptr.p_double[i-1]) ) - { - tempdata->ptr.p_double[i] = *x0; - i = i+1; - } - else - { - *nr = *nr-1; - } - } - else - { - tempdata->ptr.p_double[i] = *x0; - i = i+1; - } - } - - /* - *write are found roots - */ - if( *nr>0 ) - { - *x0 = tempdata->ptr.p_double[0]; - if( *nr>1 ) - { - *x1 = tempdata->ptr.p_double[1]; - } - if( *nr>2 ) - { - *x2 = tempdata->ptr.p_double[2]; - } - return; - } - } - } -} - - -/************************************************************************* -Function for searching a root at [A;B] by bisection method and return number of roots -(0 or 1) - -INPUT PARAMETERS: - pA - value of a function at A - mA - value of a derivative at A - pB - value of a function at B - mB - value of a derivative at B - A0 - left border [A0;B0] - B0 - right border [A0;B0] - -RESTRICTIONS OF PARAMETERS: - -We assume, that B0>A0. - - -REMARK: - -Assume, that exist one root only at [A;B], else -function may be work incorrectly. -The function dont check value A0,B0! - - -- ALGLIB PROJECT -- - Copyright 26.09.2011 by Bochkanov Sergey -*************************************************************************/ -ae_int_t bisectmethod(double pa, - double ma, - double pb, - double mb, - double a, - double b, - double* x, - ae_state *_state) -{ - double vacuum; - double eps; - double a0; - double b0; - double m; - double lf; - double rf; - double mf; - ae_int_t result; - - *x = 0; - - - /* - *accuracy - */ - eps = 1000*(b-a)*ae_machineepsilon; - - /* - *initialization left and right borders - */ - a0 = a; - b0 = b; - - /* - *initialize function value at 'A' and 'B' - */ - spline1d_hermitecalc(pa, ma, pb, mb, a, &lf, &vacuum, _state); - spline1d_hermitecalc(pa, ma, pb, mb, b, &rf, &vacuum, _state); - - /* - *check, that 'A' and 'B' are't roots, - *and that root exist - */ - if( ae_sign(lf, _state)*ae_sign(rf, _state)>0 ) - { - result = 0; - return result; - } - else - { - if( ae_fp_eq(lf,(double)(0)) ) - { - *x = a; - result = 1; - return result; - } - else - { - if( ae_fp_eq(rf,(double)(0)) ) - { - *x = b; - result = 1; - return result; - } - } - } - - /* - *searching a root - */ - do - { - m = (b0+a0)/2; - spline1d_hermitecalc(pa, ma, pb, mb, a0, &lf, &vacuum, _state); - spline1d_hermitecalc(pa, ma, pb, mb, b0, &rf, &vacuum, _state); - spline1d_hermitecalc(pa, ma, pb, mb, m, &mf, &vacuum, _state); - if( ae_sign(mf, _state)*ae_sign(lf, _state)<0 ) - { - b0 = m; - } - else - { - if( ae_sign(mf, _state)*ae_sign(rf, _state)<0 ) - { - a0 = m; - } - else - { - if( ae_fp_eq(lf,(double)(0)) ) - { - *x = a0; - result = 1; - return result; - } - if( ae_fp_eq(rf,(double)(0)) ) - { - *x = b0; - result = 1; - return result; - } - if( ae_fp_eq(mf,(double)(0)) ) - { - *x = m; - result = 1; - return result; - } - } - } - } - while(ae_fp_greater_eq(ae_fabs(b0-a0, _state),eps)); - *x = m; - result = 1; - return result; -} - - -/************************************************************************* -This function builds monotone cubic Hermite interpolant. This interpolant -is monotonic in [x(0),x(n-1)] and is constant outside of this interval. - -In case y[] form non-monotonic sequence, interpolant is piecewise -monotonic. Say, for x=(0,1,2,3,4) and y=(0,1,2,1,0) interpolant will -monotonically grow at [0..2] and monotonically decrease at [2..4]. - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1]. Subroutine automatically - sorts points, so caller may pass unsorted array. - Y - function values, array[0..N-1] - N - the number of points(N>=2). - -OUTPUT PARAMETERS: - C - spline interpolant. - - -- ALGLIB PROJECT -- - Copyright 21.06.2012 by Bochkanov Sergey -*************************************************************************/ -void spline1dbuildmonotone(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - spline1dinterpolant* c, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - ae_vector d; - ae_vector ex; - ae_vector ey; - ae_vector p; - double delta; - double alpha; - double beta; - ae_int_t tmpn; - ae_int_t sn; - double ca; - double cb; - double epsilon; - ae_int_t i; - ae_int_t j; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - memset(&d, 0, sizeof(d)); - memset(&ex, 0, sizeof(ex)); - memset(&ey, 0, sizeof(ey)); - memset(&p, 0, sizeof(p)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - _spline1dinterpolant_clear(c); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ex, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ey, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - - - /* - * Check lengths of arguments - */ - ae_assert(n>=2, "Spline1DBuildMonotone: N<2", _state); - ae_assert(x->cnt>=n, "Spline1DBuildMonotone: Length(X)cnt>=n, "Spline1DBuildMonotone: Length(Y)ptr.p_double[0]-ae_fabs(x->ptr.p_double[1]-x->ptr.p_double[0], _state); - ex.ptr.p_double[n-1] = x->ptr.p_double[n-3]+ae_fabs(x->ptr.p_double[n-3]-x->ptr.p_double[n-4], _state); - ey.ptr.p_double[0] = y->ptr.p_double[0]; - ey.ptr.p_double[n-1] = y->ptr.p_double[n-3]; - for(i=1; i<=n-2; i++) - { - ex.ptr.p_double[i] = x->ptr.p_double[i-1]; - ey.ptr.p_double[i] = y->ptr.p_double[i-1]; - } - - /* - * Init sign of the function for first segment - */ - i = 0; - ca = (double)(0); - do - { - ca = ey.ptr.p_double[i+1]-ey.ptr.p_double[i]; - i = i+1; - } - while(!(ae_fp_neq(ca,(double)(0))||i>n-2)); - if( ae_fp_neq(ca,(double)(0)) ) - { - ca = ca/ae_fabs(ca, _state); - } - i = 0; - while(i=2, "Spline1DBuildMonotone: internal error", _state); - - /* - * Calculate derivatives for current segment - */ - d.ptr.p_double[i] = (double)(0); - d.ptr.p_double[sn-1] = (double)(0); - for(j=i+1; j<=sn-2; j++) - { - d.ptr.p_double[j] = ((ey.ptr.p_double[j]-ey.ptr.p_double[j-1])/(ex.ptr.p_double[j]-ex.ptr.p_double[j-1])+(ey.ptr.p_double[j+1]-ey.ptr.p_double[j])/(ex.ptr.p_double[j+1]-ex.ptr.p_double[j]))/2; - } - for(j=i; j<=sn-2; j++) - { - delta = (ey.ptr.p_double[j+1]-ey.ptr.p_double[j])/(ex.ptr.p_double[j+1]-ex.ptr.p_double[j]); - if( ae_fp_less_eq(ae_fabs(delta, _state),epsilon) ) - { - d.ptr.p_double[j] = (double)(0); - d.ptr.p_double[j+1] = (double)(0); - } - else - { - alpha = d.ptr.p_double[j]/delta; - beta = d.ptr.p_double[j+1]/delta; - if( ae_fp_neq(alpha,(double)(0)) ) - { - cb = alpha*ae_sqrt(1+ae_sqr(beta/alpha, _state), _state); - } - else - { - if( ae_fp_neq(beta,(double)(0)) ) - { - cb = beta; - } - else - { - continue; - } - } - if( ae_fp_greater(cb,(double)(3)) ) - { - d.ptr.p_double[j] = 3*alpha*delta/cb; - d.ptr.p_double[j+1] = 3*beta*delta/cb; - } - } - } - - /* - * Transition to next segment - */ - i = sn-1; - } - spline1dbuildhermite(&ex, &ey, &d, n, c, _state); - c->continuity = 2; - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal version of Spline1DGridDiffCubic. - -Accepts pre-ordered X/Y, temporary arrays (which may be preallocated, if -you want to save time, or not) and output array (which may be preallocated -too). - -Y is passed as var-parameter because we may need to force last element to -be equal to the first one (if periodic boundary conditions are specified). - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -static void spline1d_spline1dgriddiffcubicinternal(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t boundltype, - double boundl, - ae_int_t boundrtype, - double boundr, - /* Real */ ae_vector* d, - /* Real */ ae_vector* a1, - /* Real */ ae_vector* a2, - /* Real */ ae_vector* a3, - /* Real */ ae_vector* b, - /* Real */ ae_vector* dt, - ae_state *_state) -{ - ae_int_t i; - - - - /* - * allocate arrays - */ - if( d->cntcntcntcntcntcntptr.p_double[0] = (y->ptr.p_double[1]-y->ptr.p_double[0])/(x->ptr.p_double[1]-x->ptr.p_double[0]); - d->ptr.p_double[1] = d->ptr.p_double[0]; - return; - } - if( (n==2&&boundltype==-1)&&boundrtype==-1 ) - { - d->ptr.p_double[0] = (double)(0); - d->ptr.p_double[1] = (double)(0); - return; - } - - /* - * Periodic and non-periodic boundary conditions are - * two separate classes - */ - if( boundrtype==-1&&boundltype==-1 ) - { - - /* - * Periodic boundary conditions - */ - y->ptr.p_double[n-1] = y->ptr.p_double[0]; - - /* - * Boundary conditions at N-1 points - * (one point less because last point is the same as first point). - */ - a1->ptr.p_double[0] = x->ptr.p_double[1]-x->ptr.p_double[0]; - a2->ptr.p_double[0] = 2*(x->ptr.p_double[1]-x->ptr.p_double[0]+x->ptr.p_double[n-1]-x->ptr.p_double[n-2]); - a3->ptr.p_double[0] = x->ptr.p_double[n-1]-x->ptr.p_double[n-2]; - b->ptr.p_double[0] = 3*(y->ptr.p_double[n-1]-y->ptr.p_double[n-2])/(x->ptr.p_double[n-1]-x->ptr.p_double[n-2])*(x->ptr.p_double[1]-x->ptr.p_double[0])+3*(y->ptr.p_double[1]-y->ptr.p_double[0])/(x->ptr.p_double[1]-x->ptr.p_double[0])*(x->ptr.p_double[n-1]-x->ptr.p_double[n-2]); - for(i=1; i<=n-2; i++) - { - - /* - * Altough last point is [N-2], we use X[N-1] and Y[N-1] - * (because of periodicity) - */ - a1->ptr.p_double[i] = x->ptr.p_double[i+1]-x->ptr.p_double[i]; - a2->ptr.p_double[i] = 2*(x->ptr.p_double[i+1]-x->ptr.p_double[i-1]); - a3->ptr.p_double[i] = x->ptr.p_double[i]-x->ptr.p_double[i-1]; - b->ptr.p_double[i] = 3*(y->ptr.p_double[i]-y->ptr.p_double[i-1])/(x->ptr.p_double[i]-x->ptr.p_double[i-1])*(x->ptr.p_double[i+1]-x->ptr.p_double[i])+3*(y->ptr.p_double[i+1]-y->ptr.p_double[i])/(x->ptr.p_double[i+1]-x->ptr.p_double[i])*(x->ptr.p_double[i]-x->ptr.p_double[i-1]); - } - - /* - * Solve, add last point (with index N-1) - */ - spline1d_solvecyclictridiagonal(a1, a2, a3, b, n-1, dt, _state); - ae_v_move(&d->ptr.p_double[0], 1, &dt->ptr.p_double[0], 1, ae_v_len(0,n-2)); - d->ptr.p_double[n-1] = d->ptr.p_double[0]; - } - else - { - - /* - * Non-periodic boundary condition. - * Left boundary conditions. - */ - if( boundltype==0 ) - { - a1->ptr.p_double[0] = (double)(0); - a2->ptr.p_double[0] = (double)(1); - a3->ptr.p_double[0] = (double)(1); - b->ptr.p_double[0] = 2*(y->ptr.p_double[1]-y->ptr.p_double[0])/(x->ptr.p_double[1]-x->ptr.p_double[0]); - } - if( boundltype==1 ) - { - a1->ptr.p_double[0] = (double)(0); - a2->ptr.p_double[0] = (double)(1); - a3->ptr.p_double[0] = (double)(0); - b->ptr.p_double[0] = boundl; - } - if( boundltype==2 ) - { - a1->ptr.p_double[0] = (double)(0); - a2->ptr.p_double[0] = (double)(2); - a3->ptr.p_double[0] = (double)(1); - b->ptr.p_double[0] = 3*(y->ptr.p_double[1]-y->ptr.p_double[0])/(x->ptr.p_double[1]-x->ptr.p_double[0])-0.5*boundl*(x->ptr.p_double[1]-x->ptr.p_double[0]); - } - - /* - * Central conditions - */ - for(i=1; i<=n-2; i++) - { - a1->ptr.p_double[i] = x->ptr.p_double[i+1]-x->ptr.p_double[i]; - a2->ptr.p_double[i] = 2*(x->ptr.p_double[i+1]-x->ptr.p_double[i-1]); - a3->ptr.p_double[i] = x->ptr.p_double[i]-x->ptr.p_double[i-1]; - b->ptr.p_double[i] = 3*(y->ptr.p_double[i]-y->ptr.p_double[i-1])/(x->ptr.p_double[i]-x->ptr.p_double[i-1])*(x->ptr.p_double[i+1]-x->ptr.p_double[i])+3*(y->ptr.p_double[i+1]-y->ptr.p_double[i])/(x->ptr.p_double[i+1]-x->ptr.p_double[i])*(x->ptr.p_double[i]-x->ptr.p_double[i-1]); - } - - /* - * Right boundary conditions - */ - if( boundrtype==0 ) - { - a1->ptr.p_double[n-1] = (double)(1); - a2->ptr.p_double[n-1] = (double)(1); - a3->ptr.p_double[n-1] = (double)(0); - b->ptr.p_double[n-1] = 2*(y->ptr.p_double[n-1]-y->ptr.p_double[n-2])/(x->ptr.p_double[n-1]-x->ptr.p_double[n-2]); - } - if( boundrtype==1 ) - { - a1->ptr.p_double[n-1] = (double)(0); - a2->ptr.p_double[n-1] = (double)(1); - a3->ptr.p_double[n-1] = (double)(0); - b->ptr.p_double[n-1] = boundr; - } - if( boundrtype==2 ) - { - a1->ptr.p_double[n-1] = (double)(1); - a2->ptr.p_double[n-1] = (double)(2); - a3->ptr.p_double[n-1] = (double)(0); - b->ptr.p_double[n-1] = 3*(y->ptr.p_double[n-1]-y->ptr.p_double[n-2])/(x->ptr.p_double[n-1]-x->ptr.p_double[n-2])+0.5*boundr*(x->ptr.p_double[n-1]-x->ptr.p_double[n-2]); - } - - /* - * Solve - */ - spline1d_solvetridiagonal(a1, a2, a3, b, n, d, _state); - } -} - - -/************************************************************************* -Internal subroutine. Heap sort. -*************************************************************************/ -static void spline1d_heapsortpoints(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector bufx; - ae_vector bufy; - - ae_frame_make(_state, &_frame_block); - memset(&bufx, 0, sizeof(bufx)); - memset(&bufy, 0, sizeof(bufy)); - ae_vector_init(&bufx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bufy, 0, DT_REAL, _state, ae_true); - - tagsortfastr(x, y, &bufx, &bufy, n, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal subroutine. Heap sort. - -Accepts: - X, Y - points - P - empty or preallocated array - -Returns: - X, Y - sorted by X - P - array of permutations; I-th position of output - arrays X/Y contains (X[P[I]],Y[P[I]]) -*************************************************************************/ -static void spline1d_heapsortppoints(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Integer */ ae_vector* p, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector rbuf; - ae_vector ibuf; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&rbuf, 0, sizeof(rbuf)); - memset(&ibuf, 0, sizeof(ibuf)); - ae_vector_init(&rbuf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ibuf, 0, DT_INT, _state, ae_true); - - if( p->cntptr.p_int[i] = i; - } - tagsortfasti(x, p, &rbuf, &ibuf, n, _state); - for(i=0; i<=n-1; i++) - { - rbuf.ptr.p_double[i] = y->ptr.p_double[p->ptr.p_int[i]]; - } - ae_v_move(&y->ptr.p_double[0], 1, &rbuf.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal subroutine. Tridiagonal solver. Solves - -( B[0] C[0] -( A[1] B[1] C[1] ) -( A[2] B[2] C[2] ) -( .......... ) * X = D -( .......... ) -( A[N-2] B[N-2] C[N-2] ) -( A[N-1] B[N-1] ) - -*************************************************************************/ -static void spline1d_solvetridiagonal(/* Real */ ae_vector* a, - /* Real */ ae_vector* b, - /* Real */ ae_vector* c, - /* Real */ ae_vector* d, - ae_int_t n, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _b; - ae_vector _d; - ae_int_t k; - double t; - - ae_frame_make(_state, &_frame_block); - memset(&_b, 0, sizeof(_b)); - memset(&_d, 0, sizeof(_d)); - ae_vector_init_copy(&_b, b, _state, ae_true); - b = &_b; - ae_vector_init_copy(&_d, d, _state, ae_true); - d = &_d; - - if( x->cntptr.p_double[k]/b->ptr.p_double[k-1]; - b->ptr.p_double[k] = b->ptr.p_double[k]-t*c->ptr.p_double[k-1]; - d->ptr.p_double[k] = d->ptr.p_double[k]-t*d->ptr.p_double[k-1]; - } - x->ptr.p_double[n-1] = d->ptr.p_double[n-1]/b->ptr.p_double[n-1]; - for(k=n-2; k>=0; k--) - { - x->ptr.p_double[k] = (d->ptr.p_double[k]-c->ptr.p_double[k]*x->ptr.p_double[k+1])/b->ptr.p_double[k]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal subroutine. Cyclic tridiagonal solver. Solves - -( B[0] C[0] A[0] ) -( A[1] B[1] C[1] ) -( A[2] B[2] C[2] ) -( .......... ) * X = D -( .......... ) -( A[N-2] B[N-2] C[N-2] ) -( C[N-1] A[N-1] B[N-1] ) -*************************************************************************/ -static void spline1d_solvecyclictridiagonal(/* Real */ ae_vector* a, - /* Real */ ae_vector* b, - /* Real */ ae_vector* c, - /* Real */ ae_vector* d, - ae_int_t n, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _b; - ae_int_t k; - double alpha; - double beta; - double gamma; - ae_vector y; - ae_vector z; - ae_vector u; - - ae_frame_make(_state, &_frame_block); - memset(&_b, 0, sizeof(_b)); - memset(&y, 0, sizeof(y)); - memset(&z, 0, sizeof(z)); - memset(&u, 0, sizeof(u)); - ae_vector_init_copy(&_b, b, _state, ae_true); - b = &_b; - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&z, 0, DT_REAL, _state, ae_true); - ae_vector_init(&u, 0, DT_REAL, _state, ae_true); - - if( x->cntptr.p_double[0]; - alpha = c->ptr.p_double[n-1]; - gamma = -b->ptr.p_double[0]; - b->ptr.p_double[0] = 2*b->ptr.p_double[0]; - b->ptr.p_double[n-1] = b->ptr.p_double[n-1]-alpha*beta/gamma; - ae_vector_set_length(&u, n, _state); - for(k=0; k<=n-1; k++) - { - u.ptr.p_double[k] = (double)(0); - } - u.ptr.p_double[0] = gamma; - u.ptr.p_double[n-1] = alpha; - spline1d_solvetridiagonal(a, b, c, d, n, &y, _state); - spline1d_solvetridiagonal(a, b, c, &u, n, &z, _state); - for(k=0; k<=n-1; k++) - { - x->ptr.p_double[k] = y.ptr.p_double[k]-(y.ptr.p_double[0]+beta/gamma*y.ptr.p_double[n-1])/(1+z.ptr.p_double[0]+beta/gamma*z.ptr.p_double[n-1])*z.ptr.p_double[k]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal subroutine. Three-point differentiation -*************************************************************************/ -static double spline1d_diffthreepoint(double t, - double x0, - double f0, - double x1, - double f1, - double x2, - double f2, - ae_state *_state) -{ - double a; - double b; - double result; - - - t = t-x0; - x1 = x1-x0; - x2 = x2-x0; - a = (f2-f0-x2/x1*(f1-f0))/(ae_sqr(x2, _state)-x1*x2); - b = (f1-f0-a*ae_sqr(x1, _state))/x1; - result = 2*a*t+b; - return result; -} - - -/************************************************************************* -Procedure for calculating value of a function is providet in the form of -Hermite polinom - -INPUT PARAMETERS: - P0 - value of a function at 0 - M0 - value of a derivative at 0 - P1 - value of a function at 1 - M1 - value of a derivative at 1 - T - point inside [0;1] - -OUTPUT PARAMETERS: - S - value of a function at T - B0 - value of a derivative function at T - - -- ALGLIB PROJECT -- - Copyright 26.09.2011 by Bochkanov Sergey -*************************************************************************/ -static void spline1d_hermitecalc(double p0, - double m0, - double p1, - double m1, - double t, - double* s, - double* ds, - ae_state *_state) -{ - - *s = 0; - *ds = 0; - - *s = p0*(1+2*t)*(1-t)*(1-t)+m0*t*(1-t)*(1-t)+p1*(3-2*t)*t*t+m1*t*t*(t-1); - *ds = -p0*6*t*(1-t)+m0*(1-t)*(1-3*t)+p1*6*t*(1-t)+m1*t*(3*t-2); -} - - -/************************************************************************* -Function for mapping from [A0;B0] to [A1;B1] - -INPUT PARAMETERS: - A0 - left border [A0;B0] - B0 - right border [A0;B0] - A1 - left border [A1;B1] - B1 - right border [A1;B1] - T - value inside [A0;B0] - -RESTRICTIONS OF PARAMETERS: - -We assume, that B0>A0 and B1>A1. But we chech, that T is inside [A0;B0], -and if TB0 then T - B1. - -INPUT PARAMETERS: - A0 - left border for segment [A0;B0] from 'T' is converted to [A1;B1] - B0 - right border for segment [A0;B0] from 'T' is converted to [A1;B1] - A1 - left border for segment [A1;B1] to 'T' is converted from [A0;B0] - B1 - right border for segment [A1;B1] to 'T' is converted from [A0;B0] - T - the parameter is mapped from [A0;B0] to [A1;B1] - -Result: - is converted value for 'T' from [A0;B0] to [A1;B1] - -REMARK: - -The function dont check value A0,B0 and A1,B1! - - -- ALGLIB PROJECT -- - Copyright 26.09.2011 by Bochkanov Sergey -*************************************************************************/ -static double spline1d_rescaleval(double a0, - double b0, - double a1, - double b1, - double t, - ae_state *_state) -{ - double result; - - - - /* - *return left border - */ - if( ae_fp_less_eq(t,a0) ) - { - result = a1; - return result; - } - - /* - *return right border - */ - if( ae_fp_greater_eq(t,b0) ) - { - result = b1; - return result; - } - - /* - *return value between left and right borders - */ - result = (b1-a1)*(t-a0)/(b0-a0)+a1; - return result; -} - - -void _spline1dinterpolant_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - spline1dinterpolant *p = (spline1dinterpolant*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->c, 0, DT_REAL, _state, make_automatic); -} - - -void _spline1dinterpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - spline1dinterpolant *dst = (spline1dinterpolant*)_dst; - spline1dinterpolant *src = (spline1dinterpolant*)_src; - dst->periodic = src->periodic; - dst->n = src->n; - dst->k = src->k; - dst->continuity = src->continuity; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->c, &src->c, _state, make_automatic); -} - - -void _spline1dinterpolant_clear(void* _p) -{ - spline1dinterpolant *p = (spline1dinterpolant*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->x); - ae_vector_clear(&p->c); -} - - -void _spline1dinterpolant_destroy(void* _p) -{ - spline1dinterpolant *p = (spline1dinterpolant*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->c); -} - - -void _spline1dfitreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - spline1dfitreport *p = (spline1dfitreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _spline1dfitreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - spline1dfitreport *dst = (spline1dfitreport*)_dst; - spline1dfitreport *src = (spline1dfitreport*)_src; - dst->taskrcond = src->taskrcond; - dst->rmserror = src->rmserror; - dst->avgerror = src->avgerror; - dst->avgrelerror = src->avgrelerror; - dst->maxerror = src->maxerror; -} - - -void _spline1dfitreport_clear(void* _p) -{ - spline1dfitreport *p = (spline1dfitreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _spline1dfitreport_destroy(void* _p) -{ - spline1dfitreport *p = (spline1dfitreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_PARAMETRIC) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function builds non-periodic 2-dimensional parametric spline which -starts at (X[0],Y[0]) and ends at (X[N-1],Y[N-1]). - -INPUT PARAMETERS: - XY - points, array[0..N-1,0..1]. - XY[I,0:1] corresponds to the Ith point. - Order of points is important! - N - points count, N>=5 for Akima splines, N>=2 for other types of - splines. - ST - spline type: - * 0 Akima spline - * 1 parabolically terminated Catmull-Rom spline (Tension=0) - * 2 parabolically terminated cubic spline - PT - parameterization type: - * 0 uniform - * 1 chord length - * 2 centripetal - -OUTPUT PARAMETERS: - P - parametric spline interpolant - - -NOTES: -* this function assumes that there all consequent points are distinct. - I.e. (x0,y0)<>(x1,y1), (x1,y1)<>(x2,y2), (x2,y2)<>(x3,y3) and so on. - However, non-consequent points may coincide, i.e. we can have (x0,y0)= - =(x2,y2). - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline2build(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t st, - ae_int_t pt, - pspline2interpolant* p, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _xy; - ae_vector tmp; - - ae_frame_make(_state, &_frame_block); - memset(&_xy, 0, sizeof(_xy)); - memset(&tmp, 0, sizeof(tmp)); - ae_matrix_init_copy(&_xy, xy, _state, ae_true); - xy = &_xy; - _pspline2interpolant_clear(p); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - - ae_assert(st>=0&&st<=2, "PSpline2Build: incorrect spline type!", _state); - ae_assert(pt>=0&&pt<=2, "PSpline2Build: incorrect parameterization type!", _state); - if( st==0 ) - { - ae_assert(n>=5, "PSpline2Build: N<5 (minimum value for Akima splines)!", _state); - } - else - { - ae_assert(n>=2, "PSpline2Build: N<2!", _state); - } - - /* - * Prepare - */ - p->n = n; - p->periodic = ae_false; - ae_vector_set_length(&tmp, n, _state); - - /* - * Build parameterization, check that all parameters are distinct - */ - parametric_pspline2par(xy, n, pt, &p->p, _state); - ae_assert(aredistinct(&p->p, n, _state), "PSpline2Build: consequent points are too close!", _state); - - /* - * Build splines - */ - if( st==0 ) - { - ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1)); - spline1dbuildakima(&p->p, &tmp, n, &p->x, _state); - ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1)); - spline1dbuildakima(&p->p, &tmp, n, &p->y, _state); - } - if( st==1 ) - { - ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1)); - spline1dbuildcatmullrom(&p->p, &tmp, n, 0, 0.0, &p->x, _state); - ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1)); - spline1dbuildcatmullrom(&p->p, &tmp, n, 0, 0.0, &p->y, _state); - } - if( st==2 ) - { - ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1)); - spline1dbuildcubic(&p->p, &tmp, n, 0, 0.0, 0, 0.0, &p->x, _state); - ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1)); - spline1dbuildcubic(&p->p, &tmp, n, 0, 0.0, 0, 0.0, &p->y, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function builds non-periodic 3-dimensional parametric spline which -starts at (X[0],Y[0],Z[0]) and ends at (X[N-1],Y[N-1],Z[N-1]). - -Same as PSpline2Build() function, but for 3D, so we won't duplicate its -description here. - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline3build(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t st, - ae_int_t pt, - pspline3interpolant* p, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _xy; - ae_vector tmp; - - ae_frame_make(_state, &_frame_block); - memset(&_xy, 0, sizeof(_xy)); - memset(&tmp, 0, sizeof(tmp)); - ae_matrix_init_copy(&_xy, xy, _state, ae_true); - xy = &_xy; - _pspline3interpolant_clear(p); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - - ae_assert(st>=0&&st<=2, "PSpline3Build: incorrect spline type!", _state); - ae_assert(pt>=0&&pt<=2, "PSpline3Build: incorrect parameterization type!", _state); - if( st==0 ) - { - ae_assert(n>=5, "PSpline3Build: N<5 (minimum value for Akima splines)!", _state); - } - else - { - ae_assert(n>=2, "PSpline3Build: N<2!", _state); - } - - /* - * Prepare - */ - p->n = n; - p->periodic = ae_false; - ae_vector_set_length(&tmp, n, _state); - - /* - * Build parameterization, check that all parameters are distinct - */ - parametric_pspline3par(xy, n, pt, &p->p, _state); - ae_assert(aredistinct(&p->p, n, _state), "PSpline3Build: consequent points are too close!", _state); - - /* - * Build splines - */ - if( st==0 ) - { - ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1)); - spline1dbuildakima(&p->p, &tmp, n, &p->x, _state); - ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1)); - spline1dbuildakima(&p->p, &tmp, n, &p->y, _state); - ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][2], xy->stride, ae_v_len(0,n-1)); - spline1dbuildakima(&p->p, &tmp, n, &p->z, _state); - } - if( st==1 ) - { - ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1)); - spline1dbuildcatmullrom(&p->p, &tmp, n, 0, 0.0, &p->x, _state); - ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1)); - spline1dbuildcatmullrom(&p->p, &tmp, n, 0, 0.0, &p->y, _state); - ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][2], xy->stride, ae_v_len(0,n-1)); - spline1dbuildcatmullrom(&p->p, &tmp, n, 0, 0.0, &p->z, _state); - } - if( st==2 ) - { - ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1)); - spline1dbuildcubic(&p->p, &tmp, n, 0, 0.0, 0, 0.0, &p->x, _state); - ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1)); - spline1dbuildcubic(&p->p, &tmp, n, 0, 0.0, 0, 0.0, &p->y, _state); - ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][2], xy->stride, ae_v_len(0,n-1)); - spline1dbuildcubic(&p->p, &tmp, n, 0, 0.0, 0, 0.0, &p->z, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function builds periodic 2-dimensional parametric spline which -starts at (X[0],Y[0]), goes through all points to (X[N-1],Y[N-1]) and then -back to (X[0],Y[0]). - -INPUT PARAMETERS: - XY - points, array[0..N-1,0..1]. - XY[I,0:1] corresponds to the Ith point. - XY[N-1,0:1] must be different from XY[0,0:1]. - Order of points is important! - N - points count, N>=3 for other types of splines. - ST - spline type: - * 1 Catmull-Rom spline (Tension=0) with cyclic boundary conditions - * 2 cubic spline with cyclic boundary conditions - PT - parameterization type: - * 0 uniform - * 1 chord length - * 2 centripetal - -OUTPUT PARAMETERS: - P - parametric spline interpolant - - -NOTES: -* this function assumes that there all consequent points are distinct. - I.e. (x0,y0)<>(x1,y1), (x1,y1)<>(x2,y2), (x2,y2)<>(x3,y3) and so on. - However, non-consequent points may coincide, i.e. we can have (x0,y0)= - =(x2,y2). -* last point of sequence is NOT equal to the first point. You shouldn't - make curve "explicitly periodic" by making them equal. - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline2buildperiodic(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t st, - ae_int_t pt, - pspline2interpolant* p, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _xy; - ae_matrix xyp; - ae_vector tmp; - - ae_frame_make(_state, &_frame_block); - memset(&_xy, 0, sizeof(_xy)); - memset(&xyp, 0, sizeof(xyp)); - memset(&tmp, 0, sizeof(tmp)); - ae_matrix_init_copy(&_xy, xy, _state, ae_true); - xy = &_xy; - _pspline2interpolant_clear(p); - ae_matrix_init(&xyp, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - - ae_assert(st>=1&&st<=2, "PSpline2BuildPeriodic: incorrect spline type!", _state); - ae_assert(pt>=0&&pt<=2, "PSpline2BuildPeriodic: incorrect parameterization type!", _state); - ae_assert(n>=3, "PSpline2BuildPeriodic: N<3!", _state); - - /* - * Prepare - */ - p->n = n; - p->periodic = ae_true; - ae_vector_set_length(&tmp, n+1, _state); - ae_matrix_set_length(&xyp, n+1, 2, _state); - ae_v_move(&xyp.ptr.pp_double[0][0], xyp.stride, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1)); - ae_v_move(&xyp.ptr.pp_double[0][1], xyp.stride, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1)); - ae_v_move(&xyp.ptr.pp_double[n][0], 1, &xy->ptr.pp_double[0][0], 1, ae_v_len(0,1)); - - /* - * Build parameterization, check that all parameters are distinct - */ - parametric_pspline2par(&xyp, n+1, pt, &p->p, _state); - ae_assert(aredistinct(&p->p, n+1, _state), "PSpline2BuildPeriodic: consequent (or first and last) points are too close!", _state); - - /* - * Build splines - */ - if( st==1 ) - { - ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][0], xyp.stride, ae_v_len(0,n)); - spline1dbuildcatmullrom(&p->p, &tmp, n+1, -1, 0.0, &p->x, _state); - ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][1], xyp.stride, ae_v_len(0,n)); - spline1dbuildcatmullrom(&p->p, &tmp, n+1, -1, 0.0, &p->y, _state); - } - if( st==2 ) - { - ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][0], xyp.stride, ae_v_len(0,n)); - spline1dbuildcubic(&p->p, &tmp, n+1, -1, 0.0, -1, 0.0, &p->x, _state); - ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][1], xyp.stride, ae_v_len(0,n)); - spline1dbuildcubic(&p->p, &tmp, n+1, -1, 0.0, -1, 0.0, &p->y, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function builds periodic 3-dimensional parametric spline which -starts at (X[0],Y[0],Z[0]), goes through all points to (X[N-1],Y[N-1],Z[N-1]) -and then back to (X[0],Y[0],Z[0]). - -Same as PSpline2Build() function, but for 3D, so we won't duplicate its -description here. - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline3buildperiodic(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t st, - ae_int_t pt, - pspline3interpolant* p, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _xy; - ae_matrix xyp; - ae_vector tmp; - - ae_frame_make(_state, &_frame_block); - memset(&_xy, 0, sizeof(_xy)); - memset(&xyp, 0, sizeof(xyp)); - memset(&tmp, 0, sizeof(tmp)); - ae_matrix_init_copy(&_xy, xy, _state, ae_true); - xy = &_xy; - _pspline3interpolant_clear(p); - ae_matrix_init(&xyp, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - - ae_assert(st>=1&&st<=2, "PSpline3BuildPeriodic: incorrect spline type!", _state); - ae_assert(pt>=0&&pt<=2, "PSpline3BuildPeriodic: incorrect parameterization type!", _state); - ae_assert(n>=3, "PSpline3BuildPeriodic: N<3!", _state); - - /* - * Prepare - */ - p->n = n; - p->periodic = ae_true; - ae_vector_set_length(&tmp, n+1, _state); - ae_matrix_set_length(&xyp, n+1, 3, _state); - ae_v_move(&xyp.ptr.pp_double[0][0], xyp.stride, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1)); - ae_v_move(&xyp.ptr.pp_double[0][1], xyp.stride, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1)); - ae_v_move(&xyp.ptr.pp_double[0][2], xyp.stride, &xy->ptr.pp_double[0][2], xy->stride, ae_v_len(0,n-1)); - ae_v_move(&xyp.ptr.pp_double[n][0], 1, &xy->ptr.pp_double[0][0], 1, ae_v_len(0,2)); - - /* - * Build parameterization, check that all parameters are distinct - */ - parametric_pspline3par(&xyp, n+1, pt, &p->p, _state); - ae_assert(aredistinct(&p->p, n+1, _state), "PSplineBuild2Periodic: consequent (or first and last) points are too close!", _state); - - /* - * Build splines - */ - if( st==1 ) - { - ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][0], xyp.stride, ae_v_len(0,n)); - spline1dbuildcatmullrom(&p->p, &tmp, n+1, -1, 0.0, &p->x, _state); - ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][1], xyp.stride, ae_v_len(0,n)); - spline1dbuildcatmullrom(&p->p, &tmp, n+1, -1, 0.0, &p->y, _state); - ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][2], xyp.stride, ae_v_len(0,n)); - spline1dbuildcatmullrom(&p->p, &tmp, n+1, -1, 0.0, &p->z, _state); - } - if( st==2 ) - { - ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][0], xyp.stride, ae_v_len(0,n)); - spline1dbuildcubic(&p->p, &tmp, n+1, -1, 0.0, -1, 0.0, &p->x, _state); - ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][1], xyp.stride, ae_v_len(0,n)); - spline1dbuildcubic(&p->p, &tmp, n+1, -1, 0.0, -1, 0.0, &p->y, _state); - ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][2], xyp.stride, ae_v_len(0,n)); - spline1dbuildcubic(&p->p, &tmp, n+1, -1, 0.0, -1, 0.0, &p->z, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function returns vector of parameter values correspoding to points. - -I.e. for P created from (X[0],Y[0])...(X[N-1],Y[N-1]) and U=TValues(P) we -have - (X[0],Y[0]) = PSpline2Calc(P,U[0]), - (X[1],Y[1]) = PSpline2Calc(P,U[1]), - (X[2],Y[2]) = PSpline2Calc(P,U[2]), - ... - -INPUT PARAMETERS: - P - parametric spline interpolant - -OUTPUT PARAMETERS: - N - array size - T - array[0..N-1] - - -NOTES: -* for non-periodic splines U[0]=0, U[0]n>=2, "PSpline2ParameterValues: internal error!", _state); - *n = p->n; - ae_vector_set_length(t, *n, _state); - ae_v_move(&t->ptr.p_double[0], 1, &p->p.ptr.p_double[0], 1, ae_v_len(0,*n-1)); - t->ptr.p_double[0] = (double)(0); - if( !p->periodic ) - { - t->ptr.p_double[*n-1] = (double)(1); - } -} - - -/************************************************************************* -This function returns vector of parameter values correspoding to points. - -Same as PSpline2ParameterValues(), but for 3D. - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline3parametervalues(pspline3interpolant* p, - ae_int_t* n, - /* Real */ ae_vector* t, - ae_state *_state) -{ - - *n = 0; - ae_vector_clear(t); - - ae_assert(p->n>=2, "PSpline3ParameterValues: internal error!", _state); - *n = p->n; - ae_vector_set_length(t, *n, _state); - ae_v_move(&t->ptr.p_double[0], 1, &p->p.ptr.p_double[0], 1, ae_v_len(0,*n-1)); - t->ptr.p_double[0] = (double)(0); - if( !p->periodic ) - { - t->ptr.p_double[*n-1] = (double)(1); - } -} - - -/************************************************************************* -This function calculates the value of the parametric spline for a given -value of parameter T - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-position - Y - Y-position - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline2calc(pspline2interpolant* p, - double t, - double* x, - double* y, - ae_state *_state) -{ - - *x = 0; - *y = 0; - - if( p->periodic ) - { - t = t-ae_ifloor(t, _state); - } - *x = spline1dcalc(&p->x, t, _state); - *y = spline1dcalc(&p->y, t, _state); -} - - -/************************************************************************* -This function calculates the value of the parametric spline for a given -value of parameter T. - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-position - Y - Y-position - Z - Z-position - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline3calc(pspline3interpolant* p, - double t, - double* x, - double* y, - double* z, - ae_state *_state) -{ - - *x = 0; - *y = 0; - *z = 0; - - if( p->periodic ) - { - t = t-ae_ifloor(t, _state); - } - *x = spline1dcalc(&p->x, t, _state); - *y = spline1dcalc(&p->y, t, _state); - *z = spline1dcalc(&p->z, t, _state); -} - - -/************************************************************************* -This function calculates tangent vector for a given value of parameter T - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-component of tangent vector (normalized) - Y - Y-component of tangent vector (normalized) - -NOTE: - X^2+Y^2 is either 1 (for non-zero tangent vector) or 0. - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline2tangent(pspline2interpolant* p, - double t, - double* x, - double* y, - ae_state *_state) -{ - double v; - double v0; - double v1; - - *x = 0; - *y = 0; - - if( p->periodic ) - { - t = t-ae_ifloor(t, _state); - } - pspline2diff(p, t, &v0, x, &v1, y, _state); - if( ae_fp_neq(*x,(double)(0))||ae_fp_neq(*y,(double)(0)) ) - { - - /* - * this code is a bit more complex than X^2+Y^2 to avoid - * overflow for large values of X and Y. - */ - v = safepythag2(*x, *y, _state); - *x = *x/v; - *y = *y/v; - } -} - - -/************************************************************************* -This function calculates tangent vector for a given value of parameter T - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-component of tangent vector (normalized) - Y - Y-component of tangent vector (normalized) - Z - Z-component of tangent vector (normalized) - -NOTE: - X^2+Y^2+Z^2 is either 1 (for non-zero tangent vector) or 0. - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline3tangent(pspline3interpolant* p, - double t, - double* x, - double* y, - double* z, - ae_state *_state) -{ - double v; - double v0; - double v1; - double v2; - - *x = 0; - *y = 0; - *z = 0; - - if( p->periodic ) - { - t = t-ae_ifloor(t, _state); - } - pspline3diff(p, t, &v0, x, &v1, y, &v2, z, _state); - if( (ae_fp_neq(*x,(double)(0))||ae_fp_neq(*y,(double)(0)))||ae_fp_neq(*z,(double)(0)) ) - { - v = safepythag3(*x, *y, *z, _state); - *x = *x/v; - *y = *y/v; - *z = *z/v; - } -} - - -/************************************************************************* -This function calculates derivative, i.e. it returns (dX/dT,dY/dT). - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-value - DX - X-derivative - Y - Y-value - DY - Y-derivative - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline2diff(pspline2interpolant* p, - double t, - double* x, - double* dx, - double* y, - double* dy, - ae_state *_state) -{ - double d2s; - - *x = 0; - *dx = 0; - *y = 0; - *dy = 0; - - if( p->periodic ) - { - t = t-ae_ifloor(t, _state); - } - spline1ddiff(&p->x, t, x, dx, &d2s, _state); - spline1ddiff(&p->y, t, y, dy, &d2s, _state); -} - - -/************************************************************************* -This function calculates derivative, i.e. it returns (dX/dT,dY/dT,dZ/dT). - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-value - DX - X-derivative - Y - Y-value - DY - Y-derivative - Z - Z-value - DZ - Z-derivative - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline3diff(pspline3interpolant* p, - double t, - double* x, - double* dx, - double* y, - double* dy, - double* z, - double* dz, - ae_state *_state) -{ - double d2s; - - *x = 0; - *dx = 0; - *y = 0; - *dy = 0; - *z = 0; - *dz = 0; - - if( p->periodic ) - { - t = t-ae_ifloor(t, _state); - } - spline1ddiff(&p->x, t, x, dx, &d2s, _state); - spline1ddiff(&p->y, t, y, dy, &d2s, _state); - spline1ddiff(&p->z, t, z, dz, &d2s, _state); -} - - -/************************************************************************* -This function calculates first and second derivative with respect to T. - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-value - DX - derivative - D2X - second derivative - Y - Y-value - DY - derivative - D2Y - second derivative - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline2diff2(pspline2interpolant* p, - double t, - double* x, - double* dx, - double* d2x, - double* y, - double* dy, - double* d2y, - ae_state *_state) -{ - - *x = 0; - *dx = 0; - *d2x = 0; - *y = 0; - *dy = 0; - *d2y = 0; - - if( p->periodic ) - { - t = t-ae_ifloor(t, _state); - } - spline1ddiff(&p->x, t, x, dx, d2x, _state); - spline1ddiff(&p->y, t, y, dy, d2y, _state); -} - - -/************************************************************************* -This function calculates first and second derivative with respect to T. - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-value - DX - derivative - D2X - second derivative - Y - Y-value - DY - derivative - D2Y - second derivative - Z - Z-value - DZ - derivative - D2Z - second derivative - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline3diff2(pspline3interpolant* p, - double t, - double* x, - double* dx, - double* d2x, - double* y, - double* dy, - double* d2y, - double* z, - double* dz, - double* d2z, - ae_state *_state) -{ - - *x = 0; - *dx = 0; - *d2x = 0; - *y = 0; - *dy = 0; - *d2y = 0; - *z = 0; - *dz = 0; - *d2z = 0; - - if( p->periodic ) - { - t = t-ae_ifloor(t, _state); - } - spline1ddiff(&p->x, t, x, dx, d2x, _state); - spline1ddiff(&p->y, t, y, dy, d2y, _state); - spline1ddiff(&p->z, t, z, dz, d2z, _state); -} - - -/************************************************************************* -This function calculates arc length, i.e. length of curve between t=a -and t=b. - -INPUT PARAMETERS: - P - parametric spline interpolant - A,B - parameter values corresponding to arc ends: - * B>A will result in positive length returned - * Bx, state.x, &sx, &dsx, &d2sx, _state); - spline1ddiff(&p->y, state.x, &sy, &dsy, &d2sy, _state); - state.f = safepythag2(dsx, dsy, _state); - } - autogkresults(&state, &result, &rep, _state); - ae_assert(rep.terminationtype>0, "PSpline2ArcLength: internal error!", _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function calculates arc length, i.e. length of curve between t=a -and t=b. - -INPUT PARAMETERS: - P - parametric spline interpolant - A,B - parameter values corresponding to arc ends: - * B>A will result in positive length returned - * Bx, state.x, &sx, &dsx, &d2sx, _state); - spline1ddiff(&p->y, state.x, &sy, &dsy, &d2sy, _state); - spline1ddiff(&p->z, state.x, &sz, &dsz, &d2sz, _state); - state.f = safepythag3(dsx, dsy, dsz, _state); - } - autogkresults(&state, &result, &rep, _state); - ae_assert(rep.terminationtype>0, "PSpline3ArcLength: internal error!", _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This subroutine fits piecewise linear curve to points with Ramer-Douglas- -Peucker algorithm. This function performs PARAMETRIC fit, i.e. it can be -used to fit curves like circles. - -On input it accepts dataset which describes parametric multidimensional -curve X(t), with X being vector, and t taking values in [0,N), where N is -a number of points in dataset. As result, it returns reduced dataset X2, -which can be used to build parametric curve X2(t), which approximates -X(t) with desired precision (or has specified number of sections). - - -INPUT PARAMETERS: - X - array of multidimensional points: - * at least N elements, leading N elements are used if more - than N elements were specified - * order of points is IMPORTANT because it is parametric - fit - * each row of array is one point which has D coordinates - N - number of elements in X - D - number of dimensions (elements per row of X) - StopM - stopping condition - desired number of sections: - * at most M sections are generated by this function - * less than M sections can be generated if we have N=0, "LSTFitPiecewiseLinearParametricRDP: N<0", _state); - ae_assert(d>=1, "LSTFitPiecewiseLinearParametricRDP: D<=0", _state); - ae_assert(stopm>=0, "LSTFitPiecewiseLinearParametricRDP: StopM<1", _state); - ae_assert(ae_isfinite(stopeps, _state)&&ae_fp_greater_eq(stopeps,(double)(0)), "LSTFitPiecewiseLinearParametricRDP: StopEps<0 or is infinite", _state); - ae_assert(x->rows>=n, "LSTFitPiecewiseLinearParametricRDP: Rows(X)cols>=d, "LSTFitPiecewiseLinearParametricRDP: Cols(X)ptr.pp_double[i][j],x->ptr.pp_double[0][j]); - } - } - if( allsame ) - { - *nsections = 0; - ae_frame_leave(_state); - return; - } - - /* - * Prepare first section - */ - parametric_rdpanalyzesectionpar(x, 0, n-1, d, &worstidx, &worsterror, _state); - ae_matrix_set_length(§ions, n, 4, _state); - ae_vector_set_length(&heaperrors, n, _state); - ae_vector_set_length(&heaptags, n, _state); - *nsections = 1; - sections.ptr.pp_double[0][0] = (double)(0); - sections.ptr.pp_double[0][1] = (double)(n-1); - sections.ptr.pp_double[0][2] = (double)(worstidx); - sections.ptr.pp_double[0][3] = worsterror; - heaperrors.ptr.p_double[0] = worsterror; - heaptags.ptr.p_int[0] = 0; - ae_assert(ae_fp_eq(sections.ptr.pp_double[0][1],(double)(n-1)), "RDP algorithm: integrity check failed", _state); - - /* - * Main loop. - * Repeatedly find section with worst error and divide it. - * Terminate after M-th section, or because of other reasons (see loop internals). - */ - for(;;) - { - - /* - * Break loop if one of the stopping conditions was met. - * Store index of worst section to K. - */ - if( ae_fp_eq(heaperrors.ptr.p_double[0],(double)(0)) ) - { - break; - } - if( ae_fp_greater(stopeps,(double)(0))&&ae_fp_less_eq(heaperrors.ptr.p_double[0],stopeps) ) - { - break; - } - if( stopm>0&&*nsections>=stopm ) - { - break; - } - k = heaptags.ptr.p_int[0]; - - /* - * K-th section is divided in two: - * * first one spans interval from X[Sections[K,0]] to X[Sections[K,2]] - * * second one spans interval from X[Sections[K,2]] to X[Sections[K,1]] - * - * First section is stored at K-th position, second one is appended to the table. - * Then we update heap which stores pairs of (error,section_index) - */ - k0 = ae_round(sections.ptr.pp_double[k][0], _state); - k1 = ae_round(sections.ptr.pp_double[k][1], _state); - k2 = ae_round(sections.ptr.pp_double[k][2], _state); - parametric_rdpanalyzesectionpar(x, k0, k2, d, &idx0, &e0, _state); - parametric_rdpanalyzesectionpar(x, k2, k1, d, &idx1, &e1, _state); - sections.ptr.pp_double[k][0] = (double)(k0); - sections.ptr.pp_double[k][1] = (double)(k2); - sections.ptr.pp_double[k][2] = (double)(idx0); - sections.ptr.pp_double[k][3] = e0; - tagheapreplacetopi(&heaperrors, &heaptags, *nsections, e0, k, _state); - sections.ptr.pp_double[*nsections][0] = (double)(k2); - sections.ptr.pp_double[*nsections][1] = (double)(k1); - sections.ptr.pp_double[*nsections][2] = (double)(idx1); - sections.ptr.pp_double[*nsections][3] = e1; - tagheappushi(&heaperrors, &heaptags, nsections, e1, *nsections, _state); - } - - /* - * Convert from sections to indexes - */ - ae_vector_set_length(&buf0, *nsections+1, _state); - for(i=0; i<=*nsections-1; i++) - { - buf0.ptr.p_double[i] = (double)(ae_round(sections.ptr.pp_double[i][0], _state)); - } - buf0.ptr.p_double[*nsections] = (double)(n-1); - tagsortfast(&buf0, &buf1, *nsections+1, _state); - ae_vector_set_length(idx2, *nsections+1, _state); - for(i=0; i<=*nsections; i++) - { - idx2->ptr.p_int[i] = ae_round(buf0.ptr.p_double[i], _state); - } - ae_assert(idx2->ptr.p_int[0]==0, "RDP algorithm: integrity check failed", _state); - ae_assert(idx2->ptr.p_int[*nsections]==n-1, "RDP algorithm: integrity check failed", _state); - - /* - * Output sections: - * * first NSection elements of X2/Y2 are filled by x/y at left boundaries of sections - * * last element of X2/Y2 is filled by right boundary of rightmost section - * * X2/Y2 is sorted by ascending of X2 - */ - ae_matrix_set_length(x2, *nsections+1, d, _state); - for(i=0; i<=*nsections; i++) - { - for(j=0; j<=d-1; j++) - { - x2->ptr.pp_double[i][j] = x->ptr.pp_double[idx2->ptr.p_int[i]][j]; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Builds non-periodic parameterization for 2-dimensional spline -*************************************************************************/ -static void parametric_pspline2par(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t pt, - /* Real */ ae_vector* p, - ae_state *_state) -{ - double v; - ae_int_t i; - - ae_vector_clear(p); - - ae_assert(pt>=0&&pt<=2, "PSpline2Par: internal error!", _state); - - /* - * Build parameterization: - * * fill by non-normalized values - * * normalize them so we have P[0]=0, P[N-1]=1. - */ - ae_vector_set_length(p, n, _state); - if( pt==0 ) - { - for(i=0; i<=n-1; i++) - { - p->ptr.p_double[i] = (double)(i); - } - } - if( pt==1 ) - { - p->ptr.p_double[0] = (double)(0); - for(i=1; i<=n-1; i++) - { - p->ptr.p_double[i] = p->ptr.p_double[i-1]+safepythag2(xy->ptr.pp_double[i][0]-xy->ptr.pp_double[i-1][0], xy->ptr.pp_double[i][1]-xy->ptr.pp_double[i-1][1], _state); - } - } - if( pt==2 ) - { - p->ptr.p_double[0] = (double)(0); - for(i=1; i<=n-1; i++) - { - p->ptr.p_double[i] = p->ptr.p_double[i-1]+ae_sqrt(safepythag2(xy->ptr.pp_double[i][0]-xy->ptr.pp_double[i-1][0], xy->ptr.pp_double[i][1]-xy->ptr.pp_double[i-1][1], _state), _state); - } - } - v = 1/p->ptr.p_double[n-1]; - ae_v_muld(&p->ptr.p_double[0], 1, ae_v_len(0,n-1), v); -} - - -/************************************************************************* -Builds non-periodic parameterization for 3-dimensional spline -*************************************************************************/ -static void parametric_pspline3par(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t pt, - /* Real */ ae_vector* p, - ae_state *_state) -{ - double v; - ae_int_t i; - - ae_vector_clear(p); - - ae_assert(pt>=0&&pt<=2, "PSpline3Par: internal error!", _state); - - /* - * Build parameterization: - * * fill by non-normalized values - * * normalize them so we have P[0]=0, P[N-1]=1. - */ - ae_vector_set_length(p, n, _state); - if( pt==0 ) - { - for(i=0; i<=n-1; i++) - { - p->ptr.p_double[i] = (double)(i); - } - } - if( pt==1 ) - { - p->ptr.p_double[0] = (double)(0); - for(i=1; i<=n-1; i++) - { - p->ptr.p_double[i] = p->ptr.p_double[i-1]+safepythag3(xy->ptr.pp_double[i][0]-xy->ptr.pp_double[i-1][0], xy->ptr.pp_double[i][1]-xy->ptr.pp_double[i-1][1], xy->ptr.pp_double[i][2]-xy->ptr.pp_double[i-1][2], _state); - } - } - if( pt==2 ) - { - p->ptr.p_double[0] = (double)(0); - for(i=1; i<=n-1; i++) - { - p->ptr.p_double[i] = p->ptr.p_double[i-1]+ae_sqrt(safepythag3(xy->ptr.pp_double[i][0]-xy->ptr.pp_double[i-1][0], xy->ptr.pp_double[i][1]-xy->ptr.pp_double[i-1][1], xy->ptr.pp_double[i][2]-xy->ptr.pp_double[i-1][2], _state), _state); - } - } - v = 1/p->ptr.p_double[n-1]; - ae_v_muld(&p->ptr.p_double[0], 1, ae_v_len(0,n-1), v); -} - - -/************************************************************************* -This function analyzes section of curve for processing by RDP algorithm: -given set of points X,Y with indexes [I0,I1] it returns point with -worst deviation from linear model (PARAMETRIC version which sees curve -as X(t) with vector X). - -Input parameters: - XY - array - I0,I1 - interval (boundaries included) to process - D - number of dimensions - -OUTPUT PARAMETERS: - WorstIdx - index of worst point - WorstError - error at worst point - -NOTE: this function guarantees that it returns exactly zero for a section - with less than 3 points. - - -- ALGLIB PROJECT -- - Copyright 02.10.2014 by Bochkanov Sergey -*************************************************************************/ -static void parametric_rdpanalyzesectionpar(/* Real */ ae_matrix* xy, - ae_int_t i0, - ae_int_t i1, - ae_int_t d, - ae_int_t* worstidx, - double* worsterror, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - double d2; - double ts; - double vv; - - *worstidx = 0; - *worsterror = 0; - - - /* - * Quick exit for 0, 1, 2 points - */ - if( i1-i0+1<3 ) - { - *worstidx = i0; - *worsterror = 0.0; - return; - } - - /* - * Estimate D2 - squared distance between XY[I1] and XY[I0]. - * In case D2=0 handle it as special case. - */ - d2 = 0.0; - for(j=0; j<=d-1; j++) - { - d2 = d2+ae_sqr(xy->ptr.pp_double[i1][j]-xy->ptr.pp_double[i0][j], _state); - } - if( ae_fp_eq(d2,(double)(0)) ) - { - - /* - * First and last points are equal, interval evaluation is - * trivial - we just calculate distance from all points to - * the first/last one. - */ - *worstidx = i0; - *worsterror = 0.0; - for(i=i0+1; i<=i1-1; i++) - { - vv = 0.0; - for(j=0; j<=d-1; j++) - { - v = xy->ptr.pp_double[i][j]-xy->ptr.pp_double[i0][j]; - vv = vv+v*v; - } - vv = ae_sqrt(vv, _state); - if( ae_fp_greater(vv,*worsterror) ) - { - *worsterror = vv; - *worstidx = i; - } - } - return; - } - - /* - * General case - * - * Current section of curve is modeled as x(t) = d*t+c, where - * d = XY[I1]-XY[I0] - * c = XY[I0] - * t is in [0,1] - */ - *worstidx = i0; - *worsterror = 0.0; - for(i=i0+1; i<=i1-1; i++) - { - - /* - * Determine t_s - parameter value for projected point. - */ - ts = (double)(i-i0)/(double)(i1-i0); - - /* - * Estimate error norm - */ - vv = 0.0; - for(j=0; j<=d-1; j++) - { - v = (xy->ptr.pp_double[i1][j]-xy->ptr.pp_double[i0][j])*ts-(xy->ptr.pp_double[i][j]-xy->ptr.pp_double[i0][j]); - vv = vv+ae_sqr(v, _state); - } - vv = ae_sqrt(vv, _state); - if( ae_fp_greater(vv,*worsterror) ) - { - *worsterror = vv; - *worstidx = i; - } - } -} - - -void _pspline2interpolant_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - pspline2interpolant *p = (pspline2interpolant*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->p, 0, DT_REAL, _state, make_automatic); - _spline1dinterpolant_init(&p->x, _state, make_automatic); - _spline1dinterpolant_init(&p->y, _state, make_automatic); -} - - -void _pspline2interpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - pspline2interpolant *dst = (pspline2interpolant*)_dst; - pspline2interpolant *src = (pspline2interpolant*)_src; - dst->n = src->n; - dst->periodic = src->periodic; - ae_vector_init_copy(&dst->p, &src->p, _state, make_automatic); - _spline1dinterpolant_init_copy(&dst->x, &src->x, _state, make_automatic); - _spline1dinterpolant_init_copy(&dst->y, &src->y, _state, make_automatic); -} - - -void _pspline2interpolant_clear(void* _p) -{ - pspline2interpolant *p = (pspline2interpolant*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->p); - _spline1dinterpolant_clear(&p->x); - _spline1dinterpolant_clear(&p->y); -} - - -void _pspline2interpolant_destroy(void* _p) -{ - pspline2interpolant *p = (pspline2interpolant*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->p); - _spline1dinterpolant_destroy(&p->x); - _spline1dinterpolant_destroy(&p->y); -} - - -void _pspline3interpolant_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - pspline3interpolant *p = (pspline3interpolant*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->p, 0, DT_REAL, _state, make_automatic); - _spline1dinterpolant_init(&p->x, _state, make_automatic); - _spline1dinterpolant_init(&p->y, _state, make_automatic); - _spline1dinterpolant_init(&p->z, _state, make_automatic); -} - - -void _pspline3interpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - pspline3interpolant *dst = (pspline3interpolant*)_dst; - pspline3interpolant *src = (pspline3interpolant*)_src; - dst->n = src->n; - dst->periodic = src->periodic; - ae_vector_init_copy(&dst->p, &src->p, _state, make_automatic); - _spline1dinterpolant_init_copy(&dst->x, &src->x, _state, make_automatic); - _spline1dinterpolant_init_copy(&dst->y, &src->y, _state, make_automatic); - _spline1dinterpolant_init_copy(&dst->z, &src->z, _state, make_automatic); -} - - -void _pspline3interpolant_clear(void* _p) -{ - pspline3interpolant *p = (pspline3interpolant*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->p); - _spline1dinterpolant_clear(&p->x); - _spline1dinterpolant_clear(&p->y); - _spline1dinterpolant_clear(&p->z); -} - - -void _pspline3interpolant_destroy(void* _p) -{ - pspline3interpolant *p = (pspline3interpolant*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->p); - _spline1dinterpolant_destroy(&p->x); - _spline1dinterpolant_destroy(&p->y); - _spline1dinterpolant_destroy(&p->z); -} - - -#endif -#if defined(AE_COMPILE_SPLINE3D) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This subroutine calculates the value of the trilinear or tricubic spline at -the given point (X,Y,Z). - -INPUT PARAMETERS: - C - coefficients table. - Built by BuildBilinearSpline or BuildBicubicSpline. - X, Y, - Z - point - -Result: - S(x,y,z) - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -double spline3dcalc(spline3dinterpolant* c, - double x, - double y, - double z, - ae_state *_state) -{ - double v; - double vx; - double vy; - double vxy; - double result; - - - ae_assert(c->stype==-1||c->stype==-3, "Spline3DCalc: incorrect C (incorrect parameter C.SType)", _state); - ae_assert((ae_isfinite(x, _state)&&ae_isfinite(y, _state))&&ae_isfinite(z, _state), "Spline3DCalc: X=NaN/Infinite, Y=NaN/Infinite or Z=NaN/Infinite", _state); - if( c->d!=1 ) - { - result = (double)(0); - return result; - } - spline3d_spline3ddiff(c, x, y, z, &v, &vx, &vy, &vxy, _state); - result = v; - return result; -} - - -/************************************************************************* -This subroutine performs linear transformation of the spline argument. - -INPUT PARAMETERS: - C - spline interpolant - AX, BX - transformation coefficients: x = A*u + B - AY, BY - transformation coefficients: y = A*v + B - AZ, BZ - transformation coefficients: z = A*w + B - -OUTPUT PARAMETERS: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline3dlintransxyz(spline3dinterpolant* c, - double ax, - double bx, - double ay, - double by, - double az, - double bz, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector x; - ae_vector y; - ae_vector z; - ae_vector f; - ae_vector v; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t di; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&z, 0, sizeof(z)); - memset(&f, 0, sizeof(f)); - memset(&v, 0, sizeof(v)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&z, 0, DT_REAL, _state, ae_true); - ae_vector_init(&f, 0, DT_REAL, _state, ae_true); - ae_vector_init(&v, 0, DT_REAL, _state, ae_true); - - ae_assert(c->stype==-3||c->stype==-1, "Spline3DLinTransXYZ: incorrect C (incorrect parameter C.SType)", _state); - ae_vector_set_length(&x, c->n, _state); - ae_vector_set_length(&y, c->m, _state); - ae_vector_set_length(&z, c->l, _state); - ae_vector_set_length(&f, c->m*c->n*c->l*c->d, _state); - for(j=0; j<=c->n-1; j++) - { - x.ptr.p_double[j] = c->x.ptr.p_double[j]; - } - for(i=0; i<=c->m-1; i++) - { - y.ptr.p_double[i] = c->y.ptr.p_double[i]; - } - for(i=0; i<=c->l-1; i++) - { - z.ptr.p_double[i] = c->z.ptr.p_double[i]; - } - - /* - * Handle different combinations of zero/nonzero AX/AY/AZ - */ - if( (ae_fp_neq(ax,(double)(0))&&ae_fp_neq(ay,(double)(0)))&&ae_fp_neq(az,(double)(0)) ) - { - ae_v_move(&f.ptr.p_double[0], 1, &c->f.ptr.p_double[0], 1, ae_v_len(0,c->m*c->n*c->l*c->d-1)); - } - if( (ae_fp_eq(ax,(double)(0))&&ae_fp_neq(ay,(double)(0)))&&ae_fp_neq(az,(double)(0)) ) - { - for(i=0; i<=c->m-1; i++) - { - for(j=0; j<=c->l-1; j++) - { - spline3dcalcv(c, bx, y.ptr.p_double[i], z.ptr.p_double[j], &v, _state); - for(k=0; k<=c->n-1; k++) - { - for(di=0; di<=c->d-1; di++) - { - f.ptr.p_double[c->d*(c->n*(c->m*j+i)+k)+di] = v.ptr.p_double[di]; - } - } - } - } - ax = (double)(1); - bx = (double)(0); - } - if( (ae_fp_neq(ax,(double)(0))&&ae_fp_eq(ay,(double)(0)))&&ae_fp_neq(az,(double)(0)) ) - { - for(i=0; i<=c->n-1; i++) - { - for(j=0; j<=c->l-1; j++) - { - spline3dcalcv(c, x.ptr.p_double[i], by, z.ptr.p_double[j], &v, _state); - for(k=0; k<=c->m-1; k++) - { - for(di=0; di<=c->d-1; di++) - { - f.ptr.p_double[c->d*(c->n*(c->m*j+k)+i)+di] = v.ptr.p_double[di]; - } - } - } - } - ay = (double)(1); - by = (double)(0); - } - if( (ae_fp_neq(ax,(double)(0))&&ae_fp_neq(ay,(double)(0)))&&ae_fp_eq(az,(double)(0)) ) - { - for(i=0; i<=c->n-1; i++) - { - for(j=0; j<=c->m-1; j++) - { - spline3dcalcv(c, x.ptr.p_double[i], y.ptr.p_double[j], bz, &v, _state); - for(k=0; k<=c->l-1; k++) - { - for(di=0; di<=c->d-1; di++) - { - f.ptr.p_double[c->d*(c->n*(c->m*k+j)+i)+di] = v.ptr.p_double[di]; - } - } - } - } - az = (double)(1); - bz = (double)(0); - } - if( (ae_fp_eq(ax,(double)(0))&&ae_fp_eq(ay,(double)(0)))&&ae_fp_neq(az,(double)(0)) ) - { - for(i=0; i<=c->l-1; i++) - { - spline3dcalcv(c, bx, by, z.ptr.p_double[i], &v, _state); - for(k=0; k<=c->m-1; k++) - { - for(j=0; j<=c->n-1; j++) - { - for(di=0; di<=c->d-1; di++) - { - f.ptr.p_double[c->d*(c->n*(c->m*i+k)+j)+di] = v.ptr.p_double[di]; - } - } - } - } - ax = (double)(1); - bx = (double)(0); - ay = (double)(1); - by = (double)(0); - } - if( (ae_fp_eq(ax,(double)(0))&&ae_fp_neq(ay,(double)(0)))&&ae_fp_eq(az,(double)(0)) ) - { - for(i=0; i<=c->m-1; i++) - { - spline3dcalcv(c, bx, y.ptr.p_double[i], bz, &v, _state); - for(k=0; k<=c->l-1; k++) - { - for(j=0; j<=c->n-1; j++) - { - for(di=0; di<=c->d-1; di++) - { - f.ptr.p_double[c->d*(c->n*(c->m*k+i)+j)+di] = v.ptr.p_double[di]; - } - } - } - } - ax = (double)(1); - bx = (double)(0); - az = (double)(1); - bz = (double)(0); - } - if( (ae_fp_neq(ax,(double)(0))&&ae_fp_eq(ay,(double)(0)))&&ae_fp_eq(az,(double)(0)) ) - { - for(i=0; i<=c->n-1; i++) - { - spline3dcalcv(c, x.ptr.p_double[i], by, bz, &v, _state); - for(k=0; k<=c->l-1; k++) - { - for(j=0; j<=c->m-1; j++) - { - for(di=0; di<=c->d-1; di++) - { - f.ptr.p_double[c->d*(c->n*(c->m*k+j)+i)+di] = v.ptr.p_double[di]; - } - } - } - } - ay = (double)(1); - by = (double)(0); - az = (double)(1); - bz = (double)(0); - } - if( (ae_fp_eq(ax,(double)(0))&&ae_fp_eq(ay,(double)(0)))&&ae_fp_eq(az,(double)(0)) ) - { - spline3dcalcv(c, bx, by, bz, &v, _state); - for(k=0; k<=c->l-1; k++) - { - for(j=0; j<=c->m-1; j++) - { - for(i=0; i<=c->n-1; i++) - { - for(di=0; di<=c->d-1; di++) - { - f.ptr.p_double[c->d*(c->n*(c->m*k+j)+i)+di] = v.ptr.p_double[di]; - } - } - } - } - ax = (double)(1); - bx = (double)(0); - ay = (double)(1); - by = (double)(0); - az = (double)(1); - bz = (double)(0); - } - - /* - * General case: AX<>0, AY<>0, AZ<>0 - * Unpack, scale and pack again. - */ - for(i=0; i<=c->n-1; i++) - { - x.ptr.p_double[i] = (x.ptr.p_double[i]-bx)/ax; - } - for(i=0; i<=c->m-1; i++) - { - y.ptr.p_double[i] = (y.ptr.p_double[i]-by)/ay; - } - for(i=0; i<=c->l-1; i++) - { - z.ptr.p_double[i] = (z.ptr.p_double[i]-bz)/az; - } - if( c->stype==-1 ) - { - spline3dbuildtrilinearv(&x, c->n, &y, c->m, &z, c->l, &f, c->d, c, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This subroutine performs linear transformation of the spline. - -INPUT PARAMETERS: - C - spline interpolant. - A, B- transformation coefficients: S2(x,y) = A*S(x,y,z) + B - -OUTPUT PARAMETERS: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline3dlintransf(spline3dinterpolant* c, - double a, - double b, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector x; - ae_vector y; - ae_vector z; - ae_vector f; - ae_int_t i; - ae_int_t j; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&z, 0, sizeof(z)); - memset(&f, 0, sizeof(f)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&z, 0, DT_REAL, _state, ae_true); - ae_vector_init(&f, 0, DT_REAL, _state, ae_true); - - ae_assert(c->stype==-3||c->stype==-1, "Spline3DLinTransF: incorrect C (incorrect parameter C.SType)", _state); - ae_vector_set_length(&x, c->n, _state); - ae_vector_set_length(&y, c->m, _state); - ae_vector_set_length(&z, c->l, _state); - ae_vector_set_length(&f, c->m*c->n*c->l*c->d, _state); - for(j=0; j<=c->n-1; j++) - { - x.ptr.p_double[j] = c->x.ptr.p_double[j]; - } - for(i=0; i<=c->m-1; i++) - { - y.ptr.p_double[i] = c->y.ptr.p_double[i]; - } - for(i=0; i<=c->l-1; i++) - { - z.ptr.p_double[i] = c->z.ptr.p_double[i]; - } - for(i=0; i<=c->m*c->n*c->l*c->d-1; i++) - { - f.ptr.p_double[i] = a*c->f.ptr.p_double[i]+b; - } - if( c->stype==-1 ) - { - spline3dbuildtrilinearv(&x, c->n, &y, c->m, &z, c->l, &f, c->d, c, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This subroutine makes the copy of the spline model. - -INPUT PARAMETERS: - C - spline interpolant - -OUTPUT PARAMETERS: - CC - spline copy - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline3dcopy(spline3dinterpolant* c, - spline3dinterpolant* cc, - ae_state *_state) -{ - ae_int_t tblsize; - - _spline3dinterpolant_clear(cc); - - ae_assert(c->k==1||c->k==3, "Spline3DCopy: incorrect C (incorrect parameter C.K)", _state); - cc->k = c->k; - cc->n = c->n; - cc->m = c->m; - cc->l = c->l; - cc->d = c->d; - tblsize = c->n*c->m*c->l*c->d; - cc->stype = c->stype; - ae_vector_set_length(&cc->x, cc->n, _state); - ae_vector_set_length(&cc->y, cc->m, _state); - ae_vector_set_length(&cc->z, cc->l, _state); - ae_vector_set_length(&cc->f, tblsize, _state); - ae_v_move(&cc->x.ptr.p_double[0], 1, &c->x.ptr.p_double[0], 1, ae_v_len(0,cc->n-1)); - ae_v_move(&cc->y.ptr.p_double[0], 1, &c->y.ptr.p_double[0], 1, ae_v_len(0,cc->m-1)); - ae_v_move(&cc->z.ptr.p_double[0], 1, &c->z.ptr.p_double[0], 1, ae_v_len(0,cc->l-1)); - ae_v_move(&cc->f.ptr.p_double[0], 1, &c->f.ptr.p_double[0], 1, ae_v_len(0,tblsize-1)); -} - - -/************************************************************************* -Trilinear spline resampling - -INPUT PARAMETERS: - A - array[0..OldXCount*OldYCount*OldZCount-1], function - values at the old grid, : - A[0] x=0,y=0,z=0 - A[1] x=1,y=0,z=0 - A[..] ... - A[..] x=oldxcount-1,y=0,z=0 - A[..] x=0,y=1,z=0 - A[..] ... - ... - OldZCount - old Z-count, OldZCount>1 - OldYCount - old Y-count, OldYCount>1 - OldXCount - old X-count, OldXCount>1 - NewZCount - new Z-count, NewZCount>1 - NewYCount - new Y-count, NewYCount>1 - NewXCount - new X-count, NewXCount>1 - -OUTPUT PARAMETERS: - B - array[0..NewXCount*NewYCount*NewZCount-1], function - values at the new grid: - B[0] x=0,y=0,z=0 - B[1] x=1,y=0,z=0 - B[..] ... - B[..] x=newxcount-1,y=0,z=0 - B[..] x=0,y=1,z=0 - B[..] ... - ... - - -- ALGLIB routine -- - 26.04.2012 - Copyright by Bochkanov Sergey -*************************************************************************/ -void spline3dresampletrilinear(/* Real */ ae_vector* a, - ae_int_t oldzcount, - ae_int_t oldycount, - ae_int_t oldxcount, - ae_int_t newzcount, - ae_int_t newycount, - ae_int_t newxcount, - /* Real */ ae_vector* b, - ae_state *_state) -{ - double xd; - double yd; - double zd; - double c0; - double c1; - double c2; - double c3; - ae_int_t ix; - ae_int_t iy; - ae_int_t iz; - ae_int_t i; - ae_int_t j; - ae_int_t k; - - ae_vector_clear(b); - - ae_assert((oldycount>1&&oldzcount>1)&&oldxcount>1, "Spline3DResampleTrilinear: length/width/height less than 1", _state); - ae_assert((newycount>1&&newzcount>1)&&newxcount>1, "Spline3DResampleTrilinear: length/width/height less than 1", _state); - ae_assert(a->cnt>=oldycount*oldzcount*oldxcount, "Spline3DResampleTrilinear: length/width/height less than 1", _state); - ae_vector_set_length(b, newxcount*newycount*newzcount, _state); - for(i=0; i<=newxcount-1; i++) - { - for(j=0; j<=newycount-1; j++) - { - for(k=0; k<=newzcount-1; k++) - { - ix = i*(oldxcount-1)/(newxcount-1); - if( ix==oldxcount-1 ) - { - ix = oldxcount-2; - } - xd = (double)(i*(oldxcount-1))/(double)(newxcount-1)-ix; - iy = j*(oldycount-1)/(newycount-1); - if( iy==oldycount-1 ) - { - iy = oldycount-2; - } - yd = (double)(j*(oldycount-1))/(double)(newycount-1)-iy; - iz = k*(oldzcount-1)/(newzcount-1); - if( iz==oldzcount-1 ) - { - iz = oldzcount-2; - } - zd = (double)(k*(oldzcount-1))/(double)(newzcount-1)-iz; - c0 = a->ptr.p_double[oldxcount*(oldycount*iz+iy)+ix]*(1-xd)+a->ptr.p_double[oldxcount*(oldycount*iz+iy)+(ix+1)]*xd; - c1 = a->ptr.p_double[oldxcount*(oldycount*iz+(iy+1))+ix]*(1-xd)+a->ptr.p_double[oldxcount*(oldycount*iz+(iy+1))+(ix+1)]*xd; - c2 = a->ptr.p_double[oldxcount*(oldycount*(iz+1)+iy)+ix]*(1-xd)+a->ptr.p_double[oldxcount*(oldycount*(iz+1)+iy)+(ix+1)]*xd; - c3 = a->ptr.p_double[oldxcount*(oldycount*(iz+1)+(iy+1))+ix]*(1-xd)+a->ptr.p_double[oldxcount*(oldycount*(iz+1)+(iy+1))+(ix+1)]*xd; - c0 = c0*(1-yd)+c1*yd; - c1 = c2*(1-yd)+c3*yd; - b->ptr.p_double[newxcount*(newycount*k+j)+i] = c0*(1-zd)+c1*zd; - } - } - } -} - - -/************************************************************************* -This subroutine builds trilinear vector-valued spline. - -INPUT PARAMETERS: - X - spline abscissas, array[0..N-1] - Y - spline ordinates, array[0..M-1] - Z - spline applicates, array[0..L-1] - F - function values, array[0..M*N*L*D-1]: - * first D elements store D values at (X[0],Y[0],Z[0]) - * next D elements store D values at (X[1],Y[0],Z[0]) - * next D elements store D values at (X[2],Y[0],Z[0]) - * ... - * next D elements store D values at (X[0],Y[1],Z[0]) - * next D elements store D values at (X[1],Y[1],Z[0]) - * next D elements store D values at (X[2],Y[1],Z[0]) - * ... - * next D elements store D values at (X[0],Y[0],Z[1]) - * next D elements store D values at (X[1],Y[0],Z[1]) - * next D elements store D values at (X[2],Y[0],Z[1]) - * ... - * general form - D function values at (X[i],Y[j]) are stored - at F[D*(N*(M*K+J)+I)...D*(N*(M*K+J)+I)+D-1]. - M,N, - L - grid size, M>=2, N>=2, L>=2 - D - vector dimension, D>=1 - -OUTPUT PARAMETERS: - C - spline interpolant - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline3dbuildtrilinearv(/* Real */ ae_vector* x, - ae_int_t n, - /* Real */ ae_vector* y, - ae_int_t m, - /* Real */ ae_vector* z, - ae_int_t l, - /* Real */ ae_vector* f, - ae_int_t d, - spline3dinterpolant* c, - ae_state *_state) -{ - double t; - ae_int_t tblsize; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t i0; - ae_int_t j0; - - _spline3dinterpolant_clear(c); - - ae_assert(m>=2, "Spline3DBuildTrilinearV: M<2", _state); - ae_assert(n>=2, "Spline3DBuildTrilinearV: N<2", _state); - ae_assert(l>=2, "Spline3DBuildTrilinearV: L<2", _state); - ae_assert(d>=1, "Spline3DBuildTrilinearV: D<1", _state); - ae_assert((x->cnt>=n&&y->cnt>=m)&&z->cnt>=l, "Spline3DBuildTrilinearV: length of X, Y or Z is too short (Length(X/Y/Z)cnt>=tblsize, "Spline3DBuildTrilinearV: length of F is too short (Length(F)k = 1; - c->n = n; - c->m = m; - c->l = l; - c->d = d; - c->stype = -1; - ae_vector_set_length(&c->x, c->n, _state); - ae_vector_set_length(&c->y, c->m, _state); - ae_vector_set_length(&c->z, c->l, _state); - ae_vector_set_length(&c->f, tblsize, _state); - for(i=0; i<=c->n-1; i++) - { - c->x.ptr.p_double[i] = x->ptr.p_double[i]; - } - for(i=0; i<=c->m-1; i++) - { - c->y.ptr.p_double[i] = y->ptr.p_double[i]; - } - for(i=0; i<=c->l-1; i++) - { - c->z.ptr.p_double[i] = z->ptr.p_double[i]; - } - for(i=0; i<=tblsize-1; i++) - { - c->f.ptr.p_double[i] = f->ptr.p_double[i]; - } - - /* - * Sort points: - * * sort x; - * * sort y; - * * sort z. - */ - for(j=0; j<=c->n-1; j++) - { - k = j; - for(i=j+1; i<=c->n-1; i++) - { - if( ae_fp_less(c->x.ptr.p_double[i],c->x.ptr.p_double[k]) ) - { - k = i; - } - } - if( k!=j ) - { - for(i=0; i<=c->m-1; i++) - { - for(j0=0; j0<=c->l-1; j0++) - { - for(i0=0; i0<=c->d-1; i0++) - { - t = c->f.ptr.p_double[c->d*(c->n*(c->m*j0+i)+j)+i0]; - c->f.ptr.p_double[c->d*(c->n*(c->m*j0+i)+j)+i0] = c->f.ptr.p_double[c->d*(c->n*(c->m*j0+i)+k)+i0]; - c->f.ptr.p_double[c->d*(c->n*(c->m*j0+i)+k)+i0] = t; - } - } - } - t = c->x.ptr.p_double[j]; - c->x.ptr.p_double[j] = c->x.ptr.p_double[k]; - c->x.ptr.p_double[k] = t; - } - } - for(i=0; i<=c->m-1; i++) - { - k = i; - for(j=i+1; j<=c->m-1; j++) - { - if( ae_fp_less(c->y.ptr.p_double[j],c->y.ptr.p_double[k]) ) - { - k = j; - } - } - if( k!=i ) - { - for(j=0; j<=c->n-1; j++) - { - for(j0=0; j0<=c->l-1; j0++) - { - for(i0=0; i0<=c->d-1; i0++) - { - t = c->f.ptr.p_double[c->d*(c->n*(c->m*j0+i)+j)+i0]; - c->f.ptr.p_double[c->d*(c->n*(c->m*j0+i)+j)+i0] = c->f.ptr.p_double[c->d*(c->n*(c->m*j0+k)+j)+i0]; - c->f.ptr.p_double[c->d*(c->n*(c->m*j0+k)+j)+i0] = t; - } - } - } - t = c->y.ptr.p_double[i]; - c->y.ptr.p_double[i] = c->y.ptr.p_double[k]; - c->y.ptr.p_double[k] = t; - } - } - for(k=0; k<=c->l-1; k++) - { - i = k; - for(j=i+1; j<=c->l-1; j++) - { - if( ae_fp_less(c->z.ptr.p_double[j],c->z.ptr.p_double[i]) ) - { - i = j; - } - } - if( i!=k ) - { - for(j=0; j<=c->m-1; j++) - { - for(j0=0; j0<=c->n-1; j0++) - { - for(i0=0; i0<=c->d-1; i0++) - { - t = c->f.ptr.p_double[c->d*(c->n*(c->m*k+j)+j0)+i0]; - c->f.ptr.p_double[c->d*(c->n*(c->m*k+j)+j0)+i0] = c->f.ptr.p_double[c->d*(c->n*(c->m*i+j)+j0)+i0]; - c->f.ptr.p_double[c->d*(c->n*(c->m*i+j)+j0)+i0] = t; - } - } - } - t = c->z.ptr.p_double[k]; - c->z.ptr.p_double[k] = c->z.ptr.p_double[i]; - c->z.ptr.p_double[i] = t; - } - } -} - - -/************************************************************************* -This subroutine calculates bilinear or bicubic vector-valued spline at the -given point (X,Y,Z). - -INPUT PARAMETERS: - C - spline interpolant. - X, Y, - Z - point - F - output buffer, possibly preallocated array. In case array size - is large enough to store result, it is not reallocated. Array - which is too short will be reallocated - -OUTPUT PARAMETERS: - F - array[D] (or larger) which stores function values - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline3dcalcvbuf(spline3dinterpolant* c, - double x, - double y, - double z, - /* Real */ ae_vector* f, - ae_state *_state) -{ - double xd; - double yd; - double zd; - double c0; - double c1; - double c2; - double c3; - ae_int_t ix; - ae_int_t iy; - ae_int_t iz; - ae_int_t l; - ae_int_t r; - ae_int_t h; - ae_int_t i; - - - ae_assert(c->stype==-1||c->stype==-3, "Spline3DCalcVBuf: incorrect C (incorrect parameter C.SType)", _state); - ae_assert((ae_isfinite(x, _state)&&ae_isfinite(y, _state))&&ae_isfinite(z, _state), "Spline3DCalcVBuf: X, Y or Z contains NaN/Infinite", _state); - rvectorsetlengthatleast(f, c->d, _state); - - /* - * Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included) - */ - l = 0; - r = c->n-1; - while(l!=r-1) - { - h = (l+r)/2; - if( ae_fp_greater_eq(c->x.ptr.p_double[h],x) ) - { - r = h; - } - else - { - l = h; - } - } - ix = l; - - /* - * Binary search in the [ y[0], ..., y[n-2] ] (y[n-1] is not included) - */ - l = 0; - r = c->m-1; - while(l!=r-1) - { - h = (l+r)/2; - if( ae_fp_greater_eq(c->y.ptr.p_double[h],y) ) - { - r = h; - } - else - { - l = h; - } - } - iy = l; - - /* - * Binary search in the [ z[0], ..., z[n-2] ] (z[n-1] is not included) - */ - l = 0; - r = c->l-1; - while(l!=r-1) - { - h = (l+r)/2; - if( ae_fp_greater_eq(c->z.ptr.p_double[h],z) ) - { - r = h; - } - else - { - l = h; - } - } - iz = l; - xd = (x-c->x.ptr.p_double[ix])/(c->x.ptr.p_double[ix+1]-c->x.ptr.p_double[ix]); - yd = (y-c->y.ptr.p_double[iy])/(c->y.ptr.p_double[iy+1]-c->y.ptr.p_double[iy]); - zd = (z-c->z.ptr.p_double[iz])/(c->z.ptr.p_double[iz+1]-c->z.ptr.p_double[iz]); - for(i=0; i<=c->d-1; i++) - { - - /* - * Trilinear interpolation - */ - if( c->stype==-1 ) - { - c0 = c->f.ptr.p_double[c->d*(c->n*(c->m*iz+iy)+ix)+i]*(1-xd)+c->f.ptr.p_double[c->d*(c->n*(c->m*iz+iy)+(ix+1))+i]*xd; - c1 = c->f.ptr.p_double[c->d*(c->n*(c->m*iz+(iy+1))+ix)+i]*(1-xd)+c->f.ptr.p_double[c->d*(c->n*(c->m*iz+(iy+1))+(ix+1))+i]*xd; - c2 = c->f.ptr.p_double[c->d*(c->n*(c->m*(iz+1)+iy)+ix)+i]*(1-xd)+c->f.ptr.p_double[c->d*(c->n*(c->m*(iz+1)+iy)+(ix+1))+i]*xd; - c3 = c->f.ptr.p_double[c->d*(c->n*(c->m*(iz+1)+(iy+1))+ix)+i]*(1-xd)+c->f.ptr.p_double[c->d*(c->n*(c->m*(iz+1)+(iy+1))+(ix+1))+i]*xd; - c0 = c0*(1-yd)+c1*yd; - c1 = c2*(1-yd)+c3*yd; - f->ptr.p_double[i] = c0*(1-zd)+c1*zd; - } - } -} - - -/************************************************************************* -This subroutine calculates trilinear or tricubic vector-valued spline at the -given point (X,Y,Z). - -INPUT PARAMETERS: - C - spline interpolant. - X, Y, - Z - point - -OUTPUT PARAMETERS: - F - array[D] which stores function values. F is out-parameter and - it is reallocated after call to this function. In case you - want to reuse previously allocated F, you may use - Spline2DCalcVBuf(), which reallocates F only when it is too - small. - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline3dcalcv(spline3dinterpolant* c, - double x, - double y, - double z, - /* Real */ ae_vector* f, - ae_state *_state) -{ - - ae_vector_clear(f); - - ae_assert(c->stype==-1||c->stype==-3, "Spline3DCalcV: incorrect C (incorrect parameter C.SType)", _state); - ae_assert((ae_isfinite(x, _state)&&ae_isfinite(y, _state))&&ae_isfinite(z, _state), "Spline3DCalcV: X=NaN/Infinite, Y=NaN/Infinite or Z=NaN/Infinite", _state); - ae_vector_set_length(f, c->d, _state); - spline3dcalcvbuf(c, x, y, z, f, _state); -} - - -/************************************************************************* -This subroutine unpacks tri-dimensional spline into the coefficients table - -INPUT PARAMETERS: - C - spline interpolant. - -Result: - N - grid size (X) - M - grid size (Y) - L - grid size (Z) - D - number of components - SType- spline type. Currently, only one spline type is supported: - trilinear spline, as indicated by SType=1. - Tbl - spline coefficients: [0..(N-1)*(M-1)*(L-1)*D-1, 0..13]. - For T=0..D-1 (component index), I = 0...N-2 (x index), - J=0..M-2 (y index), K=0..L-2 (z index): - Q := T + I*D + J*D*(N-1) + K*D*(N-1)*(M-1), - - Q-th row stores decomposition for T-th component of the - vector-valued function - - Tbl[Q,0] = X[i] - Tbl[Q,1] = X[i+1] - Tbl[Q,2] = Y[j] - Tbl[Q,3] = Y[j+1] - Tbl[Q,4] = Z[k] - Tbl[Q,5] = Z[k+1] - - Tbl[Q,6] = C000 - Tbl[Q,7] = C100 - Tbl[Q,8] = C010 - Tbl[Q,9] = C110 - Tbl[Q,10]= C001 - Tbl[Q,11]= C101 - Tbl[Q,12]= C011 - Tbl[Q,13]= C111 - On each grid square spline is equals to: - S(x) = SUM(c[i,j,k]*(x^i)*(y^j)*(z^k), i=0..1, j=0..1, k=0..1) - t = x-x[j] - u = y-y[i] - v = z-z[k] - - NOTE: format of Tbl is given for SType=1. Future versions of - ALGLIB can use different formats for different values of - SType. - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline3dunpackv(spline3dinterpolant* c, - ae_int_t* n, - ae_int_t* m, - ae_int_t* l, - ae_int_t* d, - ae_int_t* stype, - /* Real */ ae_matrix* tbl, - ae_state *_state) -{ - ae_int_t p; - ae_int_t ci; - ae_int_t cj; - ae_int_t ck; - double du; - double dv; - double dw; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t di; - ae_int_t i0; - - *n = 0; - *m = 0; - *l = 0; - *d = 0; - *stype = 0; - ae_matrix_clear(tbl); - - ae_assert(c->stype==-1, "Spline3DUnpackV: incorrect C (incorrect parameter C.SType)", _state); - *n = c->n; - *m = c->m; - *l = c->l; - *d = c->d; - *stype = ae_iabs(c->stype, _state); - ae_matrix_set_length(tbl, (*n-1)*(*m-1)*(*l-1)*(*d), 14, _state); - - /* - * Fill - */ - for(i=0; i<=*n-2; i++) - { - for(j=0; j<=*m-2; j++) - { - for(k=0; k<=*l-2; k++) - { - for(di=0; di<=*d-1; di++) - { - p = *d*((*n-1)*((*m-1)*k+j)+i)+di; - tbl->ptr.pp_double[p][0] = c->x.ptr.p_double[i]; - tbl->ptr.pp_double[p][1] = c->x.ptr.p_double[i+1]; - tbl->ptr.pp_double[p][2] = c->y.ptr.p_double[j]; - tbl->ptr.pp_double[p][3] = c->y.ptr.p_double[j+1]; - tbl->ptr.pp_double[p][4] = c->z.ptr.p_double[k]; - tbl->ptr.pp_double[p][5] = c->z.ptr.p_double[k+1]; - du = 1/(tbl->ptr.pp_double[p][1]-tbl->ptr.pp_double[p][0]); - dv = 1/(tbl->ptr.pp_double[p][3]-tbl->ptr.pp_double[p][2]); - dw = 1/(tbl->ptr.pp_double[p][5]-tbl->ptr.pp_double[p][4]); - - /* - * Trilinear interpolation - */ - if( c->stype==-1 ) - { - for(i0=6; i0<=13; i0++) - { - tbl->ptr.pp_double[p][i0] = (double)(0); - } - tbl->ptr.pp_double[p][6+2*(2*0+0)+0] = c->f.ptr.p_double[*d*(*n*(*m*k+j)+i)+di]; - tbl->ptr.pp_double[p][6+2*(2*0+0)+1] = c->f.ptr.p_double[*d*(*n*(*m*k+j)+(i+1))+di]-c->f.ptr.p_double[*d*(*n*(*m*k+j)+i)+di]; - tbl->ptr.pp_double[p][6+2*(2*0+1)+0] = c->f.ptr.p_double[*d*(*n*(*m*k+(j+1))+i)+di]-c->f.ptr.p_double[*d*(*n*(*m*k+j)+i)+di]; - tbl->ptr.pp_double[p][6+2*(2*0+1)+1] = c->f.ptr.p_double[*d*(*n*(*m*k+(j+1))+(i+1))+di]-c->f.ptr.p_double[*d*(*n*(*m*k+(j+1))+i)+di]-c->f.ptr.p_double[*d*(*n*(*m*k+j)+(i+1))+di]+c->f.ptr.p_double[*d*(*n*(*m*k+j)+i)+di]; - tbl->ptr.pp_double[p][6+2*(2*1+0)+0] = c->f.ptr.p_double[*d*(*n*(*m*(k+1)+j)+i)+di]-c->f.ptr.p_double[*d*(*n*(*m*k+j)+i)+di]; - tbl->ptr.pp_double[p][6+2*(2*1+0)+1] = c->f.ptr.p_double[*d*(*n*(*m*(k+1)+j)+(i+1))+di]-c->f.ptr.p_double[*d*(*n*(*m*(k+1)+j)+i)+di]-c->f.ptr.p_double[*d*(*n*(*m*k+j)+(i+1))+di]+c->f.ptr.p_double[*d*(*n*(*m*k+j)+i)+di]; - tbl->ptr.pp_double[p][6+2*(2*1+1)+0] = c->f.ptr.p_double[*d*(*n*(*m*(k+1)+(j+1))+i)+di]-c->f.ptr.p_double[*d*(*n*(*m*(k+1)+j)+i)+di]-c->f.ptr.p_double[*d*(*n*(*m*k+(j+1))+i)+di]+c->f.ptr.p_double[*d*(*n*(*m*k+j)+i)+di]; - tbl->ptr.pp_double[p][6+2*(2*1+1)+1] = c->f.ptr.p_double[*d*(*n*(*m*(k+1)+(j+1))+(i+1))+di]-c->f.ptr.p_double[*d*(*n*(*m*(k+1)+(j+1))+i)+di]-c->f.ptr.p_double[*d*(*n*(*m*(k+1)+j)+(i+1))+di]+c->f.ptr.p_double[*d*(*n*(*m*(k+1)+j)+i)+di]-c->f.ptr.p_double[*d*(*n*(*m*k+(j+1))+(i+1))+di]+c->f.ptr.p_double[*d*(*n*(*m*k+(j+1))+i)+di]+c->f.ptr.p_double[*d*(*n*(*m*k+j)+(i+1))+di]-c->f.ptr.p_double[*d*(*n*(*m*k+j)+i)+di]; - } - - /* - * Rescale Cij - */ - for(ci=0; ci<=1; ci++) - { - for(cj=0; cj<=1; cj++) - { - for(ck=0; ck<=1; ck++) - { - tbl->ptr.pp_double[p][6+2*(2*ck+cj)+ci] = tbl->ptr.pp_double[p][6+2*(2*ck+cj)+ci]*ae_pow(du, (double)(ci), _state)*ae_pow(dv, (double)(cj), _state)*ae_pow(dw, (double)(ck), _state); - } - } - } - } - } - } - } -} - - -/************************************************************************* -This subroutine calculates the value of the trilinear(or tricubic;possible -will be later) spline at the given point X(and its derivatives; possible -will be later). - -INPUT PARAMETERS: - C - spline interpolant. - X, Y, Z - point - -OUTPUT PARAMETERS: - F - S(x,y,z) - FX - dS(x,y,z)/dX - FY - dS(x,y,z)/dY - FXY - d2S(x,y,z)/dXdY - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -static void spline3d_spline3ddiff(spline3dinterpolant* c, - double x, - double y, - double z, - double* f, - double* fx, - double* fy, - double* fxy, - ae_state *_state) -{ - double xd; - double yd; - double zd; - double c0; - double c1; - double c2; - double c3; - ae_int_t ix; - ae_int_t iy; - ae_int_t iz; - ae_int_t l; - ae_int_t r; - ae_int_t h; - - *f = 0; - *fx = 0; - *fy = 0; - *fxy = 0; - - ae_assert(c->stype==-1||c->stype==-3, "Spline3DDiff: incorrect C (incorrect parameter C.SType)", _state); - ae_assert(ae_isfinite(x, _state)&&ae_isfinite(y, _state), "Spline3DDiff: X or Y contains NaN or Infinite value", _state); - - /* - * Prepare F, dF/dX, dF/dY, d2F/dXdY - */ - *f = (double)(0); - *fx = (double)(0); - *fy = (double)(0); - *fxy = (double)(0); - if( c->d!=1 ) - { - return; - } - - /* - * Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included) - */ - l = 0; - r = c->n-1; - while(l!=r-1) - { - h = (l+r)/2; - if( ae_fp_greater_eq(c->x.ptr.p_double[h],x) ) - { - r = h; - } - else - { - l = h; - } - } - ix = l; - - /* - * Binary search in the [ y[0], ..., y[n-2] ] (y[n-1] is not included) - */ - l = 0; - r = c->m-1; - while(l!=r-1) - { - h = (l+r)/2; - if( ae_fp_greater_eq(c->y.ptr.p_double[h],y) ) - { - r = h; - } - else - { - l = h; - } - } - iy = l; - - /* - * Binary search in the [ z[0], ..., z[n-2] ] (z[n-1] is not included) - */ - l = 0; - r = c->l-1; - while(l!=r-1) - { - h = (l+r)/2; - if( ae_fp_greater_eq(c->z.ptr.p_double[h],z) ) - { - r = h; - } - else - { - l = h; - } - } - iz = l; - xd = (x-c->x.ptr.p_double[ix])/(c->x.ptr.p_double[ix+1]-c->x.ptr.p_double[ix]); - yd = (y-c->y.ptr.p_double[iy])/(c->y.ptr.p_double[iy+1]-c->y.ptr.p_double[iy]); - zd = (z-c->z.ptr.p_double[iz])/(c->z.ptr.p_double[iz+1]-c->z.ptr.p_double[iz]); - - /* - * Trilinear interpolation - */ - if( c->stype==-1 ) - { - c0 = c->f.ptr.p_double[c->n*(c->m*iz+iy)+ix]*(1-xd)+c->f.ptr.p_double[c->n*(c->m*iz+iy)+(ix+1)]*xd; - c1 = c->f.ptr.p_double[c->n*(c->m*iz+(iy+1))+ix]*(1-xd)+c->f.ptr.p_double[c->n*(c->m*iz+(iy+1))+(ix+1)]*xd; - c2 = c->f.ptr.p_double[c->n*(c->m*(iz+1)+iy)+ix]*(1-xd)+c->f.ptr.p_double[c->n*(c->m*(iz+1)+iy)+(ix+1)]*xd; - c3 = c->f.ptr.p_double[c->n*(c->m*(iz+1)+(iy+1))+ix]*(1-xd)+c->f.ptr.p_double[c->n*(c->m*(iz+1)+(iy+1))+(ix+1)]*xd; - c0 = c0*(1-yd)+c1*yd; - c1 = c2*(1-yd)+c3*yd; - *f = c0*(1-zd)+c1*zd; - } -} - - -void _spline3dinterpolant_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - spline3dinterpolant *p = (spline3dinterpolant*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->z, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->f, 0, DT_REAL, _state, make_automatic); -} - - -void _spline3dinterpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - spline3dinterpolant *dst = (spline3dinterpolant*)_dst; - spline3dinterpolant *src = (spline3dinterpolant*)_src; - dst->k = src->k; - dst->stype = src->stype; - dst->n = src->n; - dst->m = src->m; - dst->l = src->l; - dst->d = src->d; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic); - ae_vector_init_copy(&dst->z, &src->z, _state, make_automatic); - ae_vector_init_copy(&dst->f, &src->f, _state, make_automatic); -} - - -void _spline3dinterpolant_clear(void* _p) -{ - spline3dinterpolant *p = (spline3dinterpolant*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->x); - ae_vector_clear(&p->y); - ae_vector_clear(&p->z); - ae_vector_clear(&p->f); -} - - -void _spline3dinterpolant_destroy(void* _p) -{ - spline3dinterpolant *p = (spline3dinterpolant*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->y); - ae_vector_destroy(&p->z); - ae_vector_destroy(&p->f); -} - - -#endif -#if defined(AE_COMPILE_POLINT) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Conversion from barycentric representation to Chebyshev basis. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - P - polynomial in barycentric form - A,B - base interval for Chebyshev polynomials (see below) - A<>B - -OUTPUT PARAMETERS - T - coefficients of Chebyshev representation; - P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N-1 }, - where Ti - I-th Chebyshev polynomial. - -NOTES: - barycentric interpolant passed as P may be either polynomial obtained - from polynomial interpolation/ fitting or rational function which is - NOT polynomial. We can't distinguish between these two cases, and this - algorithm just tries to work assuming that P IS a polynomial. If not, - algorithm will return results, but they won't have any meaning. - - -- ALGLIB -- - Copyright 30.09.2010 by Bochkanov Sergey -*************************************************************************/ -void polynomialbar2cheb(barycentricinterpolant* p, - double a, - double b, - /* Real */ ae_vector* t, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t k; - ae_vector vp; - ae_vector vx; - ae_vector tk; - ae_vector tk1; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&vp, 0, sizeof(vp)); - memset(&vx, 0, sizeof(vx)); - memset(&tk, 0, sizeof(tk)); - memset(&tk1, 0, sizeof(tk1)); - ae_vector_clear(t); - ae_vector_init(&vp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tk, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tk1, 0, DT_REAL, _state, ae_true); - - ae_assert(ae_isfinite(a, _state), "PolynomialBar2Cheb: A is not finite!", _state); - ae_assert(ae_isfinite(b, _state), "PolynomialBar2Cheb: B is not finite!", _state); - ae_assert(ae_fp_neq(a,b), "PolynomialBar2Cheb: A=B!", _state); - ae_assert(p->n>0, "PolynomialBar2Cheb: P is not correctly initialized barycentric interpolant!", _state); - - /* - * Calculate function values on a Chebyshev grid - */ - ae_vector_set_length(&vp, p->n, _state); - ae_vector_set_length(&vx, p->n, _state); - for(i=0; i<=p->n-1; i++) - { - vx.ptr.p_double[i] = ae_cos(ae_pi*(i+0.5)/p->n, _state); - vp.ptr.p_double[i] = barycentriccalc(p, 0.5*(vx.ptr.p_double[i]+1)*(b-a)+a, _state); - } - - /* - * T[0] - */ - ae_vector_set_length(t, p->n, _state); - v = (double)(0); - for(i=0; i<=p->n-1; i++) - { - v = v+vp.ptr.p_double[i]; - } - t->ptr.p_double[0] = v/p->n; - - /* - * other T's. - * - * NOTES: - * 1. TK stores T{k} on VX, TK1 stores T{k-1} on VX - * 2. we can do same calculations with fast DCT, but it - * * adds dependencies - * * still leaves us with O(N^2) algorithm because - * preparation of function values is O(N^2) process - */ - if( p->n>1 ) - { - ae_vector_set_length(&tk, p->n, _state); - ae_vector_set_length(&tk1, p->n, _state); - for(i=0; i<=p->n-1; i++) - { - tk.ptr.p_double[i] = vx.ptr.p_double[i]; - tk1.ptr.p_double[i] = (double)(1); - } - for(k=1; k<=p->n-1; k++) - { - - /* - * calculate discrete product of function vector and TK - */ - v = ae_v_dotproduct(&tk.ptr.p_double[0], 1, &vp.ptr.p_double[0], 1, ae_v_len(0,p->n-1)); - t->ptr.p_double[k] = v/(0.5*p->n); - - /* - * Update TK and TK1 - */ - for(i=0; i<=p->n-1; i++) - { - v = 2*vx.ptr.p_double[i]*tk.ptr.p_double[i]-tk1.ptr.p_double[i]; - tk1.ptr.p_double[i] = tk.ptr.p_double[i]; - tk.ptr.p_double[i] = v; - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Conversion from Chebyshev basis to barycentric representation. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - T - coefficients of Chebyshev representation; - P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N }, - where Ti - I-th Chebyshev polynomial. - N - number of coefficients: - * if given, only leading N elements of T are used - * if not given, automatically determined from size of T - A,B - base interval for Chebyshev polynomials (see above) - A=1, "PolynomialBar2Cheb: N<1", _state); - ae_assert(t->cnt>=n, "PolynomialBar2Cheb: Length(T)ptr.p_double[0]; - tk1 = (double)(1); - tk = vx; - for(k=1; k<=n-1; k++) - { - vy = vy+t->ptr.p_double[k]*tk; - v = 2*vx*tk-tk1; - tk1 = tk; - tk = v; - } - y.ptr.p_double[i] = vy; - } - - /* - * Build barycentric interpolant, map grid from [-1,+1] to [A,B] - */ - polynomialbuildcheb1(a, b, &y, n, p, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Conversion from barycentric representation to power basis. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - P - polynomial in barycentric form - C - offset (see below); 0.0 is used as default value. - S - scale (see below); 1.0 is used as default value. S<>0. - -OUTPUT PARAMETERS - A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 } - N - number of coefficients (polynomial degree plus 1) - -NOTES: -1. this function accepts offset and scale, which can be set to improve - numerical properties of polynomial. For example, if P was obtained as - result of interpolation on [-1,+1], you can set C=0 and S=1 and - represent P as sum of 1, x, x^2, x^3 and so on. In most cases you it - is exactly what you need. - - However, if your interpolation model was built on [999,1001], you will - see significant growth of numerical errors when using {1, x, x^2, x^3} - as basis. Representing P as sum of 1, (x-1000), (x-1000)^2, (x-1000)^3 - will be better option. Such representation can be obtained by using - 1000.0 as offset C and 1.0 as scale S. - -2. power basis is ill-conditioned and tricks described above can't solve - this problem completely. This function will return coefficients in - any case, but for N>8 they will become unreliable. However, N's - less than 5 are pretty safe. - -3. barycentric interpolant passed as P may be either polynomial obtained - from polynomial interpolation/ fitting or rational function which is - NOT polynomial. We can't distinguish between these two cases, and this - algorithm just tries to work assuming that P IS a polynomial. If not, - algorithm will return results, but they won't have any meaning. - - -- ALGLIB -- - Copyright 30.09.2010 by Bochkanov Sergey -*************************************************************************/ -void polynomialbar2pow(barycentricinterpolant* p, - double c, - double s, - /* Real */ ae_vector* a, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t k; - double e; - double d; - ae_vector vp; - ae_vector vx; - ae_vector tk; - ae_vector tk1; - ae_vector t; - double v; - double c0; - double s0; - double va; - double vb; - ae_vector vai; - ae_vector vbi; - double minx; - double maxx; - - ae_frame_make(_state, &_frame_block); - memset(&vp, 0, sizeof(vp)); - memset(&vx, 0, sizeof(vx)); - memset(&tk, 0, sizeof(tk)); - memset(&tk1, 0, sizeof(tk1)); - memset(&t, 0, sizeof(t)); - memset(&vai, 0, sizeof(vai)); - memset(&vbi, 0, sizeof(vbi)); - ae_vector_clear(a); - ae_vector_init(&vp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tk, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tk1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vai, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vbi, 0, DT_REAL, _state, ae_true); - - - /* - * We have barycentric model built using set of points X[], and we - * want to convert it to power basis centered about point C with - * scale S: I-th basis function is ((X-C)/S)^i. - * - * We use following three-stage algorithm: - * - * 1. we build Chebyshev representation of polynomial using - * intermediate center C0 and scale S0, which are derived from X[]: - * C0 = 0.5*(min(X)+max(X)), S0 = 0.5*(max(X)-min(X)). Chebyshev - * representation is built by sampling points around center C0, - * with typical distance between them proportional to S0. - * 2. then we transform form Chebyshev basis to intermediate power - * basis, using same center/scale C0/S0. - * 3. after that, we apply linear transformation to intermediate - * power basis which moves it to final center/scale C/S. - * - * The idea of such multi-stage algorithm is that it is much easier to - * transform barycentric model to Chebyshev basis, and only later to - * power basis, than transforming it directly to power basis. It is - * also more numerically stable to sample points using intermediate C0/S0, - * which are derived from user-supplied model, than using "final" C/S, - * which may be unsuitable for sampling (say, if S=1, we may have stability - * problems when working with models built from dataset with non-unit - * scale of abscissas). - */ - ae_assert(ae_isfinite(c, _state), "PolynomialBar2Pow: C is not finite!", _state); - ae_assert(ae_isfinite(s, _state), "PolynomialBar2Pow: S is not finite!", _state); - ae_assert(ae_fp_neq(s,(double)(0)), "PolynomialBar2Pow: S=0!", _state); - ae_assert(p->n>0, "PolynomialBar2Pow: P is not correctly initialized barycentric interpolant!", _state); - - /* - * Select intermediate center/scale - */ - minx = p->x.ptr.p_double[0]; - maxx = p->x.ptr.p_double[0]; - for(i=1; i<=p->n-1; i++) - { - minx = ae_minreal(minx, p->x.ptr.p_double[i], _state); - maxx = ae_maxreal(maxx, p->x.ptr.p_double[i], _state); - } - if( ae_fp_eq(minx,maxx) ) - { - c0 = minx; - s0 = 1.0; - } - else - { - c0 = 0.5*(maxx+minx); - s0 = 0.5*(maxx-minx); - } - - /* - * Calculate function values on a Chebyshev grid using intermediate C0/S0 - */ - ae_vector_set_length(&vp, p->n+1, _state); - ae_vector_set_length(&vx, p->n, _state); - for(i=0; i<=p->n-1; i++) - { - vx.ptr.p_double[i] = ae_cos(ae_pi*(i+0.5)/p->n, _state); - vp.ptr.p_double[i] = barycentriccalc(p, s0*vx.ptr.p_double[i]+c0, _state); - } - - /* - * T[0] - */ - ae_vector_set_length(&t, p->n, _state); - v = (double)(0); - for(i=0; i<=p->n-1; i++) - { - v = v+vp.ptr.p_double[i]; - } - t.ptr.p_double[0] = v/p->n; - - /* - * other T's. - * - * NOTES: - * 1. TK stores T{k} on VX, TK1 stores T{k-1} on VX - * 2. we can do same calculations with fast DCT, but it - * * adds dependencies - * * still leaves us with O(N^2) algorithm because - * preparation of function values is O(N^2) process - */ - if( p->n>1 ) - { - ae_vector_set_length(&tk, p->n, _state); - ae_vector_set_length(&tk1, p->n, _state); - for(i=0; i<=p->n-1; i++) - { - tk.ptr.p_double[i] = vx.ptr.p_double[i]; - tk1.ptr.p_double[i] = (double)(1); - } - for(k=1; k<=p->n-1; k++) - { - - /* - * calculate discrete product of function vector and TK - */ - v = ae_v_dotproduct(&tk.ptr.p_double[0], 1, &vp.ptr.p_double[0], 1, ae_v_len(0,p->n-1)); - t.ptr.p_double[k] = v/(0.5*p->n); - - /* - * Update TK and TK1 - */ - for(i=0; i<=p->n-1; i++) - { - v = 2*vx.ptr.p_double[i]*tk.ptr.p_double[i]-tk1.ptr.p_double[i]; - tk1.ptr.p_double[i] = tk.ptr.p_double[i]; - tk.ptr.p_double[i] = v; - } - } - } - - /* - * Convert from Chebyshev basis to power basis - */ - ae_vector_set_length(a, p->n, _state); - for(i=0; i<=p->n-1; i++) - { - a->ptr.p_double[i] = (double)(0); - } - d = (double)(0); - for(i=0; i<=p->n-1; i++) - { - for(k=i; k<=p->n-1; k++) - { - e = a->ptr.p_double[k]; - a->ptr.p_double[k] = (double)(0); - if( i<=1&&k==i ) - { - a->ptr.p_double[k] = (double)(1); - } - else - { - if( i!=0 ) - { - a->ptr.p_double[k] = 2*d; - } - if( k>i+1 ) - { - a->ptr.p_double[k] = a->ptr.p_double[k]-a->ptr.p_double[k-2]; - } - } - d = e; - } - d = a->ptr.p_double[i]; - e = (double)(0); - k = i; - while(k<=p->n-1) - { - e = e+a->ptr.p_double[k]*t.ptr.p_double[k]; - k = k+2; - } - a->ptr.p_double[i] = e; - } - - /* - * Apply linear transformation which converts basis from intermediate - * one Fi=((x-C0)/S0)^i to final one Fi=((x-C)/S)^i. - * - * We have y=(x-C0)/S0, z=(x-C)/S, and coefficients A[] for basis Fi(y). - * Because we have y=A*z+B, for A=s/s0 and B=c/s0-c0/s0, we can perform - * substitution and get coefficients A_new[] in basis Fi(z). - */ - ae_assert(vp.cnt>=p->n+1, "PolynomialBar2Pow: internal error", _state); - ae_assert(t.cnt>=p->n, "PolynomialBar2Pow: internal error", _state); - for(i=0; i<=p->n-1; i++) - { - t.ptr.p_double[i] = 0.0; - } - va = s/s0; - vb = c/s0-c0/s0; - ae_vector_set_length(&vai, p->n, _state); - ae_vector_set_length(&vbi, p->n, _state); - vai.ptr.p_double[0] = (double)(1); - vbi.ptr.p_double[0] = (double)(1); - for(k=1; k<=p->n-1; k++) - { - vai.ptr.p_double[k] = vai.ptr.p_double[k-1]*va; - vbi.ptr.p_double[k] = vbi.ptr.p_double[k-1]*vb; - } - for(k=0; k<=p->n-1; k++) - { - - /* - * Generate set of binomial coefficients in VP[] - */ - if( k>0 ) - { - vp.ptr.p_double[k] = (double)(1); - for(i=k-1; i>=1; i--) - { - vp.ptr.p_double[i] = vp.ptr.p_double[i]+vp.ptr.p_double[i-1]; - } - vp.ptr.p_double[0] = (double)(1); - } - else - { - vp.ptr.p_double[0] = (double)(1); - } - - /* - * Update T[] with expansion of K-th basis function - */ - for(i=0; i<=k; i++) - { - t.ptr.p_double[i] = t.ptr.p_double[i]+a->ptr.p_double[k]*vai.ptr.p_double[i]*vbi.ptr.p_double[k-i]*vp.ptr.p_double[i]; - } - } - for(k=0; k<=p->n-1; k++) - { - a->ptr.p_double[k] = t.ptr.p_double[k]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Conversion from power basis to barycentric representation. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 } - N - number of coefficients (polynomial degree plus 1) - * if given, only leading N elements of A are used - * if not given, automatically determined from size of A - C - offset (see below); 0.0 is used as default value. - S - scale (see below); 1.0 is used as default value. S<>0. - -OUTPUT PARAMETERS - P - polynomial in barycentric form - - -NOTES: -1. this function accepts offset and scale, which can be set to improve - numerical properties of polynomial. For example, if you interpolate on - [-1,+1], you can set C=0 and S=1 and convert from sum of 1, x, x^2, - x^3 and so on. In most cases you it is exactly what you need. - - However, if your interpolation model was built on [999,1001], you will - see significant growth of numerical errors when using {1, x, x^2, x^3} - as input basis. Converting from sum of 1, (x-1000), (x-1000)^2, - (x-1000)^3 will be better option (you have to specify 1000.0 as offset - C and 1.0 as scale S). - -2. power basis is ill-conditioned and tricks described above can't solve - this problem completely. This function will return barycentric model - in any case, but for N>8 accuracy well degrade. However, N's less than - 5 are pretty safe. - - -- ALGLIB -- - Copyright 30.09.2010 by Bochkanov Sergey -*************************************************************************/ -void polynomialpow2bar(/* Real */ ae_vector* a, - ae_int_t n, - double c, - double s, - barycentricinterpolant* p, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t k; - ae_vector y; - double vx; - double vy; - double px; - - ae_frame_make(_state, &_frame_block); - memset(&y, 0, sizeof(y)); - _barycentricinterpolant_clear(p); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - - ae_assert(ae_isfinite(c, _state), "PolynomialPow2Bar: C is not finite!", _state); - ae_assert(ae_isfinite(s, _state), "PolynomialPow2Bar: S is not finite!", _state); - ae_assert(ae_fp_neq(s,(double)(0)), "PolynomialPow2Bar: S is zero!", _state); - ae_assert(n>=1, "PolynomialPow2Bar: N<1", _state); - ae_assert(a->cnt>=n, "PolynomialPow2Bar: Length(A)ptr.p_double[0]; - px = vx; - for(k=1; k<=n-1; k++) - { - vy = vy+px*a->ptr.p_double[k]; - px = px*vx; - } - y.ptr.p_double[i] = vy; - } - - /* - * Build barycentric interpolant, map grid from [-1,+1] to [A,B] - */ - polynomialbuildcheb1(c-s, c+s, &y, n, p, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Lagrange intepolant: generation of the model on the general grid. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - X - abscissas, array[0..N-1] - Y - function values, array[0..N-1] - N - number of points, N>=1 - -OUTPUT PARAMETERS - P - barycentric model which represents Lagrange interpolant - (see ratint unit info and BarycentricCalc() description for - more information). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void polynomialbuild(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - barycentricinterpolant* p, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - ae_int_t j; - ae_int_t k; - ae_vector w; - double b; - double a; - double v; - double mx; - ae_vector sortrbuf; - ae_vector sortrbuf2; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - memset(&w, 0, sizeof(w)); - memset(&sortrbuf, 0, sizeof(sortrbuf)); - memset(&sortrbuf2, 0, sizeof(sortrbuf2)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - _barycentricinterpolant_clear(p); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sortrbuf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sortrbuf2, 0, DT_REAL, _state, ae_true); - - ae_assert(n>0, "PolynomialBuild: N<=0!", _state); - ae_assert(x->cnt>=n, "PolynomialBuild: Length(X)cnt>=n, "PolynomialBuild: Length(Y)ptr.p_double[0]; - b = x->ptr.p_double[0]; - for(j=0; j<=n-1; j++) - { - w.ptr.p_double[j] = (double)(1); - a = ae_minreal(a, x->ptr.p_double[j], _state); - b = ae_maxreal(b, x->ptr.p_double[j], _state); - } - for(k=0; k<=n-1; k++) - { - - /* - * W[K] is used instead of 0.0 because - * cycle on J does not touch K-th element - * and we MUST get maximum from ALL elements - */ - mx = ae_fabs(w.ptr.p_double[k], _state); - for(j=0; j<=n-1; j++) - { - if( j!=k ) - { - v = (b-a)/(x->ptr.p_double[j]-x->ptr.p_double[k]); - w.ptr.p_double[j] = w.ptr.p_double[j]*v; - mx = ae_maxreal(mx, ae_fabs(w.ptr.p_double[j], _state), _state); - } - } - if( k%5==0 ) - { - - /* - * every 5-th run we renormalize W[] - */ - v = 1/mx; - ae_v_muld(&w.ptr.p_double[0], 1, ae_v_len(0,n-1), v); - } - } - barycentricbuildxyw(x, y, &w, n, p, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Lagrange intepolant: generation of the model on equidistant grid. -This function has O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - Y - function values at the nodes, array[0..N-1] - N - number of points, N>=1 - for N=1 a constant model is constructed. - -OUTPUT PARAMETERS - P - barycentric model which represents Lagrange interpolant - (see ratint unit info and BarycentricCalc() description for - more information). - - -- ALGLIB -- - Copyright 03.12.2009 by Bochkanov Sergey -*************************************************************************/ -void polynomialbuildeqdist(double a, - double b, - /* Real */ ae_vector* y, - ae_int_t n, - barycentricinterpolant* p, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_vector w; - ae_vector x; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&w, 0, sizeof(w)); - memset(&x, 0, sizeof(x)); - _barycentricinterpolant_clear(p); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - - ae_assert(n>0, "PolynomialBuildEqDist: N<=0!", _state); - ae_assert(y->cnt>=n, "PolynomialBuildEqDist: Length(Y)=1 - for N=1 a constant model is constructed. - -OUTPUT PARAMETERS - P - barycentric model which represents Lagrange interpolant - (see ratint unit info and BarycentricCalc() description for - more information). - - -- ALGLIB -- - Copyright 03.12.2009 by Bochkanov Sergey -*************************************************************************/ -void polynomialbuildcheb1(double a, - double b, - /* Real */ ae_vector* y, - ae_int_t n, - barycentricinterpolant* p, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_vector w; - ae_vector x; - double v; - double t; - - ae_frame_make(_state, &_frame_block); - memset(&w, 0, sizeof(w)); - memset(&x, 0, sizeof(x)); - _barycentricinterpolant_clear(p); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - - ae_assert(n>0, "PolynomialBuildCheb1: N<=0!", _state); - ae_assert(y->cnt>=n, "PolynomialBuildCheb1: Length(Y)=1 - for N=1 a constant model is constructed. - -OUTPUT PARAMETERS - P - barycentric model which represents Lagrange interpolant - (see ratint unit info and BarycentricCalc() description for - more information). - - -- ALGLIB -- - Copyright 03.12.2009 by Bochkanov Sergey -*************************************************************************/ -void polynomialbuildcheb2(double a, - double b, - /* Real */ ae_vector* y, - ae_int_t n, - barycentricinterpolant* p, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_vector w; - ae_vector x; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&w, 0, sizeof(w)); - memset(&x, 0, sizeof(x)); - _barycentricinterpolant_clear(p); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - - ae_assert(n>0, "PolynomialBuildCheb2: N<=0!", _state); - ae_assert(y->cnt>=n, "PolynomialBuildCheb2: Length(Y)=1 - for N=1 a constant model is constructed. - T - position where P(x) is calculated - -RESULT - value of the Lagrange interpolant at T - -IMPORTANT - this function provides fast interface which is not overflow-safe - nor it is very precise. - the best option is to use PolynomialBuildEqDist()/BarycentricCalc() - subroutines unless you are pretty sure that your data will not result - in overflow. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -double polynomialcalceqdist(double a, - double b, - /* Real */ ae_vector* f, - ae_int_t n, - double t, - ae_state *_state) -{ - double s1; - double s2; - double v; - double threshold; - double s; - double h; - ae_int_t i; - ae_int_t j; - double w; - double x; - double result; - - - ae_assert(n>0, "PolynomialCalcEqDist: N<=0!", _state); - ae_assert(f->cnt>=n, "PolynomialCalcEqDist: Length(F)v_nan; - return result; - } - - /* - * Special case: N=1 - */ - if( n==1 ) - { - result = f->ptr.p_double[0]; - return result; - } - - /* - * First, decide: should we use "safe" formula (guarded - * against overflow) or fast one? - */ - threshold = ae_sqrt(ae_minrealnumber, _state); - j = 0; - s = t-a; - for(i=1; i<=n-1; i++) - { - x = a+(double)i/(double)(n-1)*(b-a); - if( ae_fp_less(ae_fabs(t-x, _state),ae_fabs(s, _state)) ) - { - s = t-x; - j = i; - } - } - if( ae_fp_eq(s,(double)(0)) ) - { - result = f->ptr.p_double[j]; - return result; - } - if( ae_fp_greater(ae_fabs(s, _state),threshold) ) - { - - /* - * use fast formula - */ - j = -1; - s = 1.0; - } - - /* - * Calculate using safe or fast barycentric formula - */ - s1 = (double)(0); - s2 = (double)(0); - w = 1.0; - h = (b-a)/(n-1); - for(i=0; i<=n-1; i++) - { - if( i!=j ) - { - v = s*w/(t-(a+i*h)); - s1 = s1+v*f->ptr.p_double[i]; - s2 = s2+v; - } - else - { - v = w; - s1 = s1+v*f->ptr.p_double[i]; - s2 = s2+v; - } - w = -w*(n-1-i); - w = w/(i+1); - } - result = s1/s2; - return result; -} - - -/************************************************************************* -Fast polynomial interpolation function on Chebyshev points (first kind) -with O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - F - function values, array[0..N-1] - N - number of points on Chebyshev grid (first kind), - X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n)) - for N=1 a constant model is constructed. - T - position where P(x) is calculated - -RESULT - value of the Lagrange interpolant at T - -IMPORTANT - this function provides fast interface which is not overflow-safe - nor it is very precise. - the best option is to use PolIntBuildCheb1()/BarycentricCalc() - subroutines unless you are pretty sure that your data will not result - in overflow. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -double polynomialcalccheb1(double a, - double b, - /* Real */ ae_vector* f, - ae_int_t n, - double t, - ae_state *_state) -{ - double s1; - double s2; - double v; - double threshold; - double s; - ae_int_t i; - ae_int_t j; - double a0; - double delta; - double alpha; - double beta; - double ca; - double sa; - double tempc; - double temps; - double x; - double w; - double p1; - double result; - - - ae_assert(n>0, "PolynomialCalcCheb1: N<=0!", _state); - ae_assert(f->cnt>=n, "PolynomialCalcCheb1: Length(F)v_nan; - return result; - } - - /* - * Special case: N=1 - */ - if( n==1 ) - { - result = f->ptr.p_double[0]; - return result; - } - - /* - * Prepare information for the recurrence formula - * used to calculate sin(pi*(2j+1)/(2n+2)) and - * cos(pi*(2j+1)/(2n+2)): - * - * A0 = pi/(2n+2) - * Delta = pi/(n+1) - * Alpha = 2 sin^2 (Delta/2) - * Beta = sin(Delta) - * - * so that sin(..) = sin(A0+j*delta) and cos(..) = cos(A0+j*delta). - * Then we use - * - * sin(x+delta) = sin(x) - (alpha*sin(x) - beta*cos(x)) - * cos(x+delta) = cos(x) - (alpha*cos(x) - beta*sin(x)) - * - * to repeatedly calculate sin(..) and cos(..). - */ - threshold = ae_sqrt(ae_minrealnumber, _state); - t = (t-0.5*(a+b))/(0.5*(b-a)); - a0 = ae_pi/(2*(n-1)+2); - delta = 2*ae_pi/(2*(n-1)+2); - alpha = 2*ae_sqr(ae_sin(delta/2, _state), _state); - beta = ae_sin(delta, _state); - - /* - * First, decide: should we use "safe" formula (guarded - * against overflow) or fast one? - */ - ca = ae_cos(a0, _state); - sa = ae_sin(a0, _state); - j = 0; - x = ca; - s = t-x; - for(i=1; i<=n-1; i++) - { - - /* - * Next X[i] - */ - temps = sa-(alpha*sa-beta*ca); - tempc = ca-(alpha*ca+beta*sa); - sa = temps; - ca = tempc; - x = ca; - - /* - * Use X[i] - */ - if( ae_fp_less(ae_fabs(t-x, _state),ae_fabs(s, _state)) ) - { - s = t-x; - j = i; - } - } - if( ae_fp_eq(s,(double)(0)) ) - { - result = f->ptr.p_double[j]; - return result; - } - if( ae_fp_greater(ae_fabs(s, _state),threshold) ) - { - - /* - * use fast formula - */ - j = -1; - s = 1.0; - } - - /* - * Calculate using safe or fast barycentric formula - */ - s1 = (double)(0); - s2 = (double)(0); - ca = ae_cos(a0, _state); - sa = ae_sin(a0, _state); - p1 = 1.0; - for(i=0; i<=n-1; i++) - { - - /* - * Calculate X[i], W[i] - */ - x = ca; - w = p1*sa; - - /* - * Proceed - */ - if( i!=j ) - { - v = s*w/(t-x); - s1 = s1+v*f->ptr.p_double[i]; - s2 = s2+v; - } - else - { - v = w; - s1 = s1+v*f->ptr.p_double[i]; - s2 = s2+v; - } - - /* - * Next CA, SA, P1 - */ - temps = sa-(alpha*sa-beta*ca); - tempc = ca-(alpha*ca+beta*sa); - sa = temps; - ca = tempc; - p1 = -p1; - } - result = s1/s2; - return result; -} - - -/************************************************************************* -Fast polynomial interpolation function on Chebyshev points (second kind) -with O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - F - function values, array[0..N-1] - N - number of points on Chebyshev grid (second kind), - X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1)) - for N=1 a constant model is constructed. - T - position where P(x) is calculated - -RESULT - value of the Lagrange interpolant at T - -IMPORTANT - this function provides fast interface which is not overflow-safe - nor it is very precise. - the best option is to use PolIntBuildCheb2()/BarycentricCalc() - subroutines unless you are pretty sure that your data will not result - in overflow. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -double polynomialcalccheb2(double a, - double b, - /* Real */ ae_vector* f, - ae_int_t n, - double t, - ae_state *_state) -{ - double s1; - double s2; - double v; - double threshold; - double s; - ae_int_t i; - ae_int_t j; - double a0; - double delta; - double alpha; - double beta; - double ca; - double sa; - double tempc; - double temps; - double x; - double w; - double p1; - double result; - - - ae_assert(n>0, "PolynomialCalcCheb2: N<=0!", _state); - ae_assert(f->cnt>=n, "PolynomialCalcCheb2: Length(F)v_nan; - return result; - } - - /* - * Special case: N=1 - */ - if( n==1 ) - { - result = f->ptr.p_double[0]; - return result; - } - - /* - * Prepare information for the recurrence formula - * used to calculate sin(pi*i/n) and - * cos(pi*i/n): - * - * A0 = 0 - * Delta = pi/n - * Alpha = 2 sin^2 (Delta/2) - * Beta = sin(Delta) - * - * so that sin(..) = sin(A0+j*delta) and cos(..) = cos(A0+j*delta). - * Then we use - * - * sin(x+delta) = sin(x) - (alpha*sin(x) - beta*cos(x)) - * cos(x+delta) = cos(x) - (alpha*cos(x) - beta*sin(x)) - * - * to repeatedly calculate sin(..) and cos(..). - */ - threshold = ae_sqrt(ae_minrealnumber, _state); - t = (t-0.5*(a+b))/(0.5*(b-a)); - a0 = 0.0; - delta = ae_pi/(n-1); - alpha = 2*ae_sqr(ae_sin(delta/2, _state), _state); - beta = ae_sin(delta, _state); - - /* - * First, decide: should we use "safe" formula (guarded - * against overflow) or fast one? - */ - ca = ae_cos(a0, _state); - sa = ae_sin(a0, _state); - j = 0; - x = ca; - s = t-x; - for(i=1; i<=n-1; i++) - { - - /* - * Next X[i] - */ - temps = sa-(alpha*sa-beta*ca); - tempc = ca-(alpha*ca+beta*sa); - sa = temps; - ca = tempc; - x = ca; - - /* - * Use X[i] - */ - if( ae_fp_less(ae_fabs(t-x, _state),ae_fabs(s, _state)) ) - { - s = t-x; - j = i; - } - } - if( ae_fp_eq(s,(double)(0)) ) - { - result = f->ptr.p_double[j]; - return result; - } - if( ae_fp_greater(ae_fabs(s, _state),threshold) ) - { - - /* - * use fast formula - */ - j = -1; - s = 1.0; - } - - /* - * Calculate using safe or fast barycentric formula - */ - s1 = (double)(0); - s2 = (double)(0); - ca = ae_cos(a0, _state); - sa = ae_sin(a0, _state); - p1 = 1.0; - for(i=0; i<=n-1; i++) - { - - /* - * Calculate X[i], W[i] - */ - x = ca; - if( i==0||i==n-1 ) - { - w = 0.5*p1; - } - else - { - w = 1.0*p1; - } - - /* - * Proceed - */ - if( i!=j ) - { - v = s*w/(t-x); - s1 = s1+v*f->ptr.p_double[i]; - s2 = s2+v; - } - else - { - v = w; - s1 = s1+v*f->ptr.p_double[i]; - s2 = s2+v; - } - - /* - * Next CA, SA, P1 - */ - temps = sa-(alpha*sa-beta*ca); - tempc = ca-(alpha*ca+beta*sa); - sa = temps; - ca = tempc; - p1 = -p1; - } - result = s1/s2; - return result; -} - - -#endif -#if defined(AE_COMPILE_LSFIT) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This subroutine fits piecewise linear curve to points with Ramer-Douglas- -Peucker algorithm, which stops after generating specified number of linear -sections. - -IMPORTANT: -* it does NOT perform least-squares fitting; it builds curve, but this - curve does not minimize some least squares metric. See description of - RDP algorithm (say, in Wikipedia) for more details on WHAT is performed. -* this function does NOT work with parametric curves (i.e. curves which - can be represented as {X(t),Y(t)}. It works with curves which can be - represented as Y(X). Thus, it is impossible to model figures like - circles with this functions. - If you want to work with parametric curves, you should use - ParametricRDPFixed() function provided by "Parametric" subpackage of - "Interpolation" package. - -INPUT PARAMETERS: - X - array of X-coordinates: - * at least N elements - * can be unordered (points are automatically sorted) - * this function may accept non-distinct X (see below for - more information on handling of such inputs) - Y - array of Y-coordinates: - * at least N elements - N - number of elements in X/Y - M - desired number of sections: - * at most M sections are generated by this function - * less than M sections can be generated if we have N=0, "LSTFitPiecewiseLinearRDPFixed: N<0", _state); - ae_assert(m>=1, "LSTFitPiecewiseLinearRDPFixed: M<1", _state); - ae_assert(x->cnt>=n, "LSTFitPiecewiseLinearRDPFixed: Length(X)cnt>=n, "LSTFitPiecewiseLinearRDPFixed: Length(Y)ptr.p_double[i]; - while(j<=n-1&&ae_fp_eq(x->ptr.p_double[j],x->ptr.p_double[i])) - { - v = v+y->ptr.p_double[j]; - j = j+1; - } - v = v/(j-i); - for(k=i; k<=j-1; k++) - { - y->ptr.p_double[k] = v; - } - i = j; - } - - /* - * Handle degenerate case x[0]=x[N-1] - */ - if( ae_fp_eq(x->ptr.p_double[n-1],x->ptr.p_double[0]) ) - { - *nsections = 0; - ae_frame_leave(_state); - return; - } - - /* - * Prepare first section - */ - lsfit_rdpanalyzesection(x, y, 0, n-1, &worstidx, &worsterror, _state); - ae_matrix_set_length(§ions, m, 4, _state); - ae_vector_set_length(&heaperrors, m, _state); - ae_vector_set_length(&heaptags, m, _state); - *nsections = 1; - sections.ptr.pp_double[0][0] = (double)(0); - sections.ptr.pp_double[0][1] = (double)(n-1); - sections.ptr.pp_double[0][2] = (double)(worstidx); - sections.ptr.pp_double[0][3] = worsterror; - heaperrors.ptr.p_double[0] = worsterror; - heaptags.ptr.p_int[0] = 0; - ae_assert(ae_fp_eq(sections.ptr.pp_double[0][1],(double)(n-1)), "RDP algorithm: integrity check failed", _state); - - /* - * Main loop. - * Repeatedly find section with worst error and divide it. - * Terminate after M-th section, or because of other reasons (see loop internals). - */ - while(*nsectionsptr.p_double[ae_round(sections.ptr.pp_double[i][1], _state)],x->ptr.p_double[k]) ) - { - k = ae_round(sections.ptr.pp_double[i][1], _state); - } - } - points.ptr.p_double[*nsections] = (double)(k); - tagsortfast(&points, &buf0, *nsections+1, _state); - - /* - * Output sections: - * * first NSection elements of X2/Y2 are filled by x/y at left boundaries of sections - * * last element of X2/Y2 is filled by right boundary of rightmost section - * * X2/Y2 is sorted by ascending of X2 - */ - ae_vector_set_length(x2, *nsections+1, _state); - ae_vector_set_length(y2, *nsections+1, _state); - for(i=0; i<=*nsections; i++) - { - x2->ptr.p_double[i] = x->ptr.p_double[ae_round(points.ptr.p_double[i], _state)]; - y2->ptr.p_double[i] = y->ptr.p_double[ae_round(points.ptr.p_double[i], _state)]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This subroutine fits piecewise linear curve to points with Ramer-Douglas- -Peucker algorithm, which stops after achieving desired precision. - -IMPORTANT: -* it performs non-least-squares fitting; it builds curve, but this curve - does not minimize some least squares metric. See description of RDP - algorithm (say, in Wikipedia) for more details on WHAT is performed. -* this function does NOT work with parametric curves (i.e. curves which - can be represented as {X(t),Y(t)}. It works with curves which can be - represented as Y(X). Thus, it is impossible to model figures like circles - with this functions. - If you want to work with parametric curves, you should use - ParametricRDPFixed() function provided by "Parametric" subpackage of - "Interpolation" package. - -INPUT PARAMETERS: - X - array of X-coordinates: - * at least N elements - * can be unordered (points are automatically sorted) - * this function may accept non-distinct X (see below for - more information on handling of such inputs) - Y - array of Y-coordinates: - * at least N elements - N - number of elements in X/Y - Eps - positive number, desired precision. - - -OUTPUT PARAMETERS: - X2 - X-values of corner points for piecewise approximation, - has length NSections+1 or zero (for NSections=0). - Y2 - Y-values of corner points, - has length NSections+1 or zero (for NSections=0). - NSections- number of sections found by algorithm, - NSections can be zero for degenerate datasets - (N<=1 or all X[] are non-distinct). - -NOTE: X2/Y2 are ordered arrays, i.e. (X2[0],Y2[0]) is a first point of - curve, (X2[NSection-1],Y2[NSection-1]) is the last point. - - -- ALGLIB -- - Copyright 02.10.2014 by Bochkanov Sergey -*************************************************************************/ -void lstfitpiecewiselinearrdp(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - double eps, - /* Real */ ae_vector* x2, - /* Real */ ae_vector* y2, - ae_int_t* nsections, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_vector buf0; - ae_vector buf1; - ae_vector xtmp; - ae_vector ytmp; - double v; - ae_int_t npts; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - memset(&buf0, 0, sizeof(buf0)); - memset(&buf1, 0, sizeof(buf1)); - memset(&xtmp, 0, sizeof(xtmp)); - memset(&ytmp, 0, sizeof(ytmp)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - ae_vector_clear(x2); - ae_vector_clear(y2); - *nsections = 0; - ae_vector_init(&buf0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&buf1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xtmp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ytmp, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=0, "LSTFitPiecewiseLinearRDP: N<0", _state); - ae_assert(ae_fp_greater(eps,(double)(0)), "LSTFitPiecewiseLinearRDP: Eps<=0", _state); - ae_assert(x->cnt>=n, "LSTFitPiecewiseLinearRDP: Length(X)cnt>=n, "LSTFitPiecewiseLinearRDP: Length(Y)ptr.p_double[i]; - while(j<=n-1&&ae_fp_eq(x->ptr.p_double[j],x->ptr.p_double[i])) - { - v = v+y->ptr.p_double[j]; - j = j+1; - } - v = v/(j-i); - for(k=i; k<=j-1; k++) - { - y->ptr.p_double[k] = v; - } - i = j; - } - - /* - * Handle degenerate case x[0]=x[N-1] - */ - if( ae_fp_eq(x->ptr.p_double[n-1],x->ptr.p_double[0]) ) - { - *nsections = 0; - ae_frame_leave(_state); - return; - } - - /* - * Prepare data for recursive algorithm - */ - ae_vector_set_length(&xtmp, n, _state); - ae_vector_set_length(&ytmp, n, _state); - npts = 2; - xtmp.ptr.p_double[0] = x->ptr.p_double[0]; - ytmp.ptr.p_double[0] = y->ptr.p_double[0]; - xtmp.ptr.p_double[1] = x->ptr.p_double[n-1]; - ytmp.ptr.p_double[1] = y->ptr.p_double[n-1]; - lsfit_rdprecursive(x, y, 0, n-1, eps, &xtmp, &ytmp, &npts, _state); - - /* - * Output sections: - * * first NSection elements of X2/Y2 are filled by x/y at left boundaries of sections - * * last element of X2/Y2 is filled by right boundary of rightmost section - * * X2/Y2 is sorted by ascending of X2 - */ - *nsections = npts-1; - ae_vector_set_length(x2, npts, _state); - ae_vector_set_length(y2, npts, _state); - for(i=0; i<=*nsections; i++) - { - x2->ptr.p_double[i] = xtmp.ptr.p_double[i]; - y2->ptr.p_double[i] = ytmp.ptr.p_double[i]; - } - tagsortfastr(x2, y2, &buf0, &buf1, npts, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Fitting by polynomials in barycentric form. This function provides simple -unterface for unconstrained unweighted fitting. See PolynomialFitWC() if -you need constrained fitting. - -Task is linear, so linear least squares solver is used. Complexity of this -computational scheme is O(N*M^2), mostly dominated by least squares solver - -SEE ALSO: - PolynomialFitWC() - -NOTES: - you can convert P from barycentric form to the power or Chebyshev - basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions from - POLINT subpackage. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - N - number of points, N>0 - * if given, only leading N elements of X/Y are used - * if not given, automatically determined from sizes of X/Y - M - number of basis functions (= polynomial_degree + 1), M>=1 - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearW() subroutine: - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - P - interpolant in barycentric form. - Rep - report, same format as in LSFitLinearW() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - - -- ALGLIB PROJECT -- - Copyright 10.12.2009 by Bochkanov Sergey -*************************************************************************/ -void polynomialfit(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t m, - ae_int_t* info, - barycentricinterpolant* p, - polynomialfitreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_vector w; - ae_vector xc; - ae_vector yc; - ae_vector dc; - - ae_frame_make(_state, &_frame_block); - memset(&w, 0, sizeof(w)); - memset(&xc, 0, sizeof(xc)); - memset(&yc, 0, sizeof(yc)); - memset(&dc, 0, sizeof(dc)); - *info = 0; - _barycentricinterpolant_clear(p); - _polynomialfitreport_clear(rep); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dc, 0, DT_INT, _state, ae_true); - - ae_assert(n>0, "PolynomialFit: N<=0!", _state); - ae_assert(m>0, "PolynomialFit: M<=0!", _state); - ae_assert(x->cnt>=n, "PolynomialFit: Length(X)cnt>=n, "PolynomialFit: Length(Y)0. - * if given, only leading N elements of X/Y/W are used - * if not given, automatically determined from sizes of X/Y/W - XC - points where polynomial values/derivatives are constrained, - array[0..K-1]. - YC - values of constraints, array[0..K-1] - DC - array[0..K-1], types of constraints: - * DC[i]=0 means that P(XC[i])=YC[i] - * DC[i]=1 means that P'(XC[i])=YC[i] - SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS - K - number of constraints, 0<=K=1 - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearW() subroutine: - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - P - interpolant in barycentric form. - Rep - report, same format as in LSFitLinearW() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - -SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: - -Setting constraints can lead to undesired results, like ill-conditioned -behavior, or inconsistency being detected. From the other side, it allows -us to improve quality of the fit. Here we summarize our experience with -constrained regression splines: -* even simple constraints can be inconsistent, see Wikipedia article on - this subject: http://en.wikipedia.org/wiki/Birkhoff_interpolation -* the greater is M (given fixed constraints), the more chances that - constraints will be consistent -* in the general case, consistency of constraints is NOT GUARANTEED. -* in the one special cases, however, we can guarantee consistency. This - case is: M>1 and constraints on the function values (NOT DERIVATIVES) - -Our final recommendation is to use constraints WHEN AND ONLY when you -can't solve your task without them. Anything beyond special cases given -above is not guaranteed and may result in inconsistency. - - -- ALGLIB PROJECT -- - Copyright 10.12.2009 by Bochkanov Sergey -*************************************************************************/ -void polynomialfitwc(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_int_t n, - /* Real */ ae_vector* xc, - /* Real */ ae_vector* yc, - /* Integer */ ae_vector* dc, - ae_int_t k, - ae_int_t m, - ae_int_t* info, - barycentricinterpolant* p, - polynomialfitreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - ae_vector _w; - ae_vector _xc; - ae_vector _yc; - double xa; - double xb; - double sa; - double sb; - ae_vector xoriginal; - ae_vector yoriginal; - ae_vector y2; - ae_vector w2; - ae_vector tmp; - ae_vector tmp2; - ae_vector bx; - ae_vector by; - ae_vector bw; - ae_int_t i; - ae_int_t j; - double u; - double v; - double s; - ae_int_t relcnt; - lsfitreport lrep; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - memset(&_w, 0, sizeof(_w)); - memset(&_xc, 0, sizeof(_xc)); - memset(&_yc, 0, sizeof(_yc)); - memset(&xoriginal, 0, sizeof(xoriginal)); - memset(&yoriginal, 0, sizeof(yoriginal)); - memset(&y2, 0, sizeof(y2)); - memset(&w2, 0, sizeof(w2)); - memset(&tmp, 0, sizeof(tmp)); - memset(&tmp2, 0, sizeof(tmp2)); - memset(&bx, 0, sizeof(bx)); - memset(&by, 0, sizeof(by)); - memset(&bw, 0, sizeof(bw)); - memset(&lrep, 0, sizeof(lrep)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - ae_vector_init_copy(&_w, w, _state, ae_true); - w = &_w; - ae_vector_init_copy(&_xc, xc, _state, ae_true); - xc = &_xc; - ae_vector_init_copy(&_yc, yc, _state, ae_true); - yc = &_yc; - *info = 0; - _barycentricinterpolant_clear(p); - _polynomialfitreport_clear(rep); - ae_vector_init(&xoriginal, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yoriginal, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&by, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bw, 0, DT_REAL, _state, ae_true); - _lsfitreport_init(&lrep, _state, ae_true); - - ae_assert(n>0, "PolynomialFitWC: N<=0!", _state); - ae_assert(m>0, "PolynomialFitWC: M<=0!", _state); - ae_assert(k>=0, "PolynomialFitWC: K<0!", _state); - ae_assert(k=M!", _state); - ae_assert(x->cnt>=n, "PolynomialFitWC: Length(X)cnt>=n, "PolynomialFitWC: Length(Y)cnt>=n, "PolynomialFitWC: Length(W)cnt>=k, "PolynomialFitWC: Length(XC)cnt>=k, "PolynomialFitWC: Length(YC)cnt>=k, "PolynomialFitWC: Length(DC)ptr.p_int[i]==0||dc->ptr.p_int[i]==1, "PolynomialFitWC: one of DC[] is not 0 or 1!", _state); - } - - /* - * Scale X, Y, XC, YC. - * Solve scaled problem using internal Chebyshev fitting function. - */ - lsfitscalexy(x, y, w, n, xc, yc, dc, k, &xa, &xb, &sa, &sb, &xoriginal, &yoriginal, _state); - lsfit_internalchebyshevfit(x, y, w, n, xc, yc, dc, k, m, info, &tmp, &lrep, _state); - if( *info<0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Generate barycentric model and scale it - * * BX, BY store barycentric model nodes - * * FMatrix is reused (remember - it is at least MxM, what we need) - * - * Model intialization is done in O(M^2). In principle, it can be - * done in O(M*log(M)), but before it we solved task with O(N*M^2) - * complexity, so it is only a small amount of total time spent. - */ - ae_vector_set_length(&bx, m, _state); - ae_vector_set_length(&by, m, _state); - ae_vector_set_length(&bw, m, _state); - ae_vector_set_length(&tmp2, m, _state); - s = (double)(1); - for(i=0; i<=m-1; i++) - { - if( m!=1 ) - { - u = ae_cos(ae_pi*i/(m-1), _state); - } - else - { - u = (double)(0); - } - v = (double)(0); - for(j=0; j<=m-1; j++) - { - if( j==0 ) - { - tmp2.ptr.p_double[j] = (double)(1); - } - else - { - if( j==1 ) - { - tmp2.ptr.p_double[j] = u; - } - else - { - tmp2.ptr.p_double[j] = 2*u*tmp2.ptr.p_double[j-1]-tmp2.ptr.p_double[j-2]; - } - } - v = v+tmp.ptr.p_double[j]*tmp2.ptr.p_double[j]; - } - bx.ptr.p_double[i] = u; - by.ptr.p_double[i] = v; - bw.ptr.p_double[i] = s; - if( i==0||i==m-1 ) - { - bw.ptr.p_double[i] = 0.5*bw.ptr.p_double[i]; - } - s = -s; - } - barycentricbuildxyw(&bx, &by, &bw, m, p, _state); - barycentriclintransx(p, 2/(xb-xa), -(xa+xb)/(xb-xa), _state); - barycentriclintransy(p, sb-sa, sa, _state); - - /* - * Scale absolute errors obtained from LSFitLinearW. - * Relative error should be calculated separately - * (because of shifting/scaling of the task) - */ - rep->taskrcond = lrep.taskrcond; - rep->rmserror = lrep.rmserror*(sb-sa); - rep->avgerror = lrep.avgerror*(sb-sa); - rep->maxerror = lrep.maxerror*(sb-sa); - rep->avgrelerror = (double)(0); - relcnt = 0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_neq(yoriginal.ptr.p_double[i],(double)(0)) ) - { - rep->avgrelerror = rep->avgrelerror+ae_fabs(barycentriccalc(p, xoriginal.ptr.p_double[i], _state)-yoriginal.ptr.p_double[i], _state)/ae_fabs(yoriginal.ptr.p_double[i], _state); - relcnt = relcnt+1; - } - } - if( relcnt!=0 ) - { - rep->avgrelerror = rep->avgrelerror/relcnt; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function calculates value of four-parameter logistic (4PL) model at -specified point X. 4PL model has following form: - - F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B)) - -INPUT PARAMETERS: - X - current point, X>=0: - * zero X is correctly handled even for B<=0 - * negative X results in exception. - A, B, C, D- parameters of 4PL model: - * A is unconstrained - * B is unconstrained; zero or negative values are handled - correctly. - * C>0, non-positive value results in exception - * D is unconstrained - -RESULT: - model value at X - -NOTE: if B=0, denominator is assumed to be equal to 2.0 even for zero X - (strictly speaking, 0^0 is undefined). - -NOTE: this function also throws exception if all input parameters are - correct, but overflow was detected during calculations. - -NOTE: this function performs a lot of checks; if you need really high - performance, consider evaluating model yourself, without checking - for degenerate cases. - - - -- ALGLIB PROJECT -- - Copyright 14.05.2014 by Bochkanov Sergey -*************************************************************************/ -double logisticcalc4(double x, - double a, - double b, - double c, - double d, - ae_state *_state) -{ - double result; - - - ae_assert(ae_isfinite(x, _state), "LogisticCalc4: X is not finite", _state); - ae_assert(ae_isfinite(a, _state), "LogisticCalc4: A is not finite", _state); - ae_assert(ae_isfinite(b, _state), "LogisticCalc4: B is not finite", _state); - ae_assert(ae_isfinite(c, _state), "LogisticCalc4: C is not finite", _state); - ae_assert(ae_isfinite(d, _state), "LogisticCalc4: D is not finite", _state); - ae_assert(ae_fp_greater_eq(x,(double)(0)), "LogisticCalc4: X is negative", _state); - ae_assert(ae_fp_greater(c,(double)(0)), "LogisticCalc4: C is non-positive", _state); - - /* - * Check for degenerate cases - */ - if( ae_fp_eq(b,(double)(0)) ) - { - result = 0.5*(a+d); - return result; - } - if( ae_fp_eq(x,(double)(0)) ) - { - if( ae_fp_greater(b,(double)(0)) ) - { - result = a; - } - else - { - result = d; - } - return result; - } - - /* - * General case - */ - result = d+(a-d)/(1.0+ae_pow(x/c, b, _state)); - ae_assert(ae_isfinite(result, _state), "LogisticCalc4: overflow during calculations", _state); - return result; -} - - -/************************************************************************* -This function calculates value of five-parameter logistic (5PL) model at -specified point X. 5PL model has following form: - - F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G) - -INPUT PARAMETERS: - X - current point, X>=0: - * zero X is correctly handled even for B<=0 - * negative X results in exception. - A, B, C, D, G- parameters of 5PL model: - * A is unconstrained - * B is unconstrained; zero or negative values are handled - correctly. - * C>0, non-positive value results in exception - * D is unconstrained - * G>0, non-positive value results in exception - -RESULT: - model value at X - -NOTE: if B=0, denominator is assumed to be equal to Power(2.0,G) even for - zero X (strictly speaking, 0^0 is undefined). - -NOTE: this function also throws exception if all input parameters are - correct, but overflow was detected during calculations. - -NOTE: this function performs a lot of checks; if you need really high - performance, consider evaluating model yourself, without checking - for degenerate cases. - - - -- ALGLIB PROJECT -- - Copyright 14.05.2014 by Bochkanov Sergey -*************************************************************************/ -double logisticcalc5(double x, - double a, - double b, - double c, - double d, - double g, - ae_state *_state) -{ - double result; - - - ae_assert(ae_isfinite(x, _state), "LogisticCalc5: X is not finite", _state); - ae_assert(ae_isfinite(a, _state), "LogisticCalc5: A is not finite", _state); - ae_assert(ae_isfinite(b, _state), "LogisticCalc5: B is not finite", _state); - ae_assert(ae_isfinite(c, _state), "LogisticCalc5: C is not finite", _state); - ae_assert(ae_isfinite(d, _state), "LogisticCalc5: D is not finite", _state); - ae_assert(ae_isfinite(g, _state), "LogisticCalc5: G is not finite", _state); - ae_assert(ae_fp_greater_eq(x,(double)(0)), "LogisticCalc5: X is negative", _state); - ae_assert(ae_fp_greater(c,(double)(0)), "LogisticCalc5: C is non-positive", _state); - ae_assert(ae_fp_greater(g,(double)(0)), "LogisticCalc5: G is non-positive", _state); - - /* - * Check for degenerate cases - */ - if( ae_fp_eq(b,(double)(0)) ) - { - result = d+(a-d)/ae_pow(2.0, g, _state); - return result; - } - if( ae_fp_eq(x,(double)(0)) ) - { - if( ae_fp_greater(b,(double)(0)) ) - { - result = a; - } - else - { - result = d; - } - return result; - } - - /* - * General case - */ - result = d+(a-d)/ae_pow(1.0+ae_pow(x/c, b, _state), g, _state); - ae_assert(ae_isfinite(result, _state), "LogisticCalc5: overflow during calculations", _state); - return result; -} - - -/************************************************************************* -This function fits four-parameter logistic (4PL) model to data provided -by user. 4PL model has following form: - - F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B)) - -Here: - * A, D - unconstrained (see LogisticFit4EC() for constrained 4PL) - * B>=0 - * C>0 - -IMPORTANT: output of this function is constrained in such way that B>0. - Because 4PL model is symmetric with respect to B, there is no - need to explore B<0. Constraining B makes algorithm easier - to stabilize and debug. - Users who for some reason prefer to work with negative B's - should transform output themselves (swap A and D, replace B by - -B). - -4PL fitting is implemented as follows: -* we perform small number of restarts from random locations which helps to - solve problem of bad local extrema. Locations are only partially random - - we use input data to determine good initial guess, but we include - controlled amount of randomness. -* we perform Levenberg-Marquardt fitting with very tight constraints on - parameters B and C - it allows us to find good initial guess for the - second stage without risk of running into "flat spot". -* second Levenberg-Marquardt round is performed without excessive - constraints. Results from the previous round are used as initial guess. -* after fitting is done, we compare results with best values found so far, - rewrite "best solution" if needed, and move to next random location. - -Overall algorithm is very stable and is not prone to bad local extrema. -Furthermore, it automatically scales when input data have very large or -very small range. - -INPUT PARAMETERS: - X - array[N], stores X-values. - MUST include only non-negative numbers (but may include - zero values). Can be unsorted. - Y - array[N], values to fit. - N - number of points. If N is less than length of X/Y, only - leading N elements are used. - -OUTPUT PARAMETERS: - A, B, C, D- parameters of 4PL model - Rep - fitting report. This structure has many fields, but ONLY - ONES LISTED BELOW ARE SET: - * Rep.IterationsCount - number of iterations performed - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average absolute error - * Rep.AvgRelError - average relative error (calculated for - non-zero Y-values) - * Rep.MaxError - maximum absolute error - * Rep.R2 - coefficient of determination, R-squared. This - coefficient is calculated as R2=1-RSS/TSS (in case - of nonlinear regression there are multiple ways to - define R2, each of them giving different results). - -NOTE: for stability reasons the B parameter is restricted by [1/1000,1000] - range. It prevents algorithm from making trial steps deep into the - area of bad parameters. - -NOTE: after you obtained coefficients, you can evaluate model with - LogisticCalc4() function. - -NOTE: if you need better control over fitting process than provided by this - function, you may use LogisticFit45X(). - -NOTE: step is automatically scaled according to scale of parameters being - fitted before we compare its length with EpsX. Thus, this function - can be used to fit data with very small or very large values without - changing EpsX. - - - -- ALGLIB PROJECT -- - Copyright 14.02.2014 by Bochkanov Sergey -*************************************************************************/ -void logisticfit4(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - double* a, - double* b, - double* c, - double* d, - lsfitreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - double g; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - *a = 0; - *b = 0; - *c = 0; - *d = 0; - _lsfitreport_clear(rep); - - logisticfit45x(x, y, n, _state->v_nan, _state->v_nan, ae_true, 0.0, 0.0, 0, a, b, c, d, &g, rep, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function fits four-parameter logistic (4PL) model to data provided -by user, with optional constraints on parameters A and D. 4PL model has -following form: - - F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B)) - -Here: - * A, D - with optional equality constraints - * B>=0 - * C>0 - -IMPORTANT: output of this function is constrained in such way that B>0. - Because 4PL model is symmetric with respect to B, there is no - need to explore B<0. Constraining B makes algorithm easier - to stabilize and debug. - Users who for some reason prefer to work with negative B's - should transform output themselves (swap A and D, replace B by - -B). - -4PL fitting is implemented as follows: -* we perform small number of restarts from random locations which helps to - solve problem of bad local extrema. Locations are only partially random - - we use input data to determine good initial guess, but we include - controlled amount of randomness. -* we perform Levenberg-Marquardt fitting with very tight constraints on - parameters B and C - it allows us to find good initial guess for the - second stage without risk of running into "flat spot". -* second Levenberg-Marquardt round is performed without excessive - constraints. Results from the previous round are used as initial guess. -* after fitting is done, we compare results with best values found so far, - rewrite "best solution" if needed, and move to next random location. - -Overall algorithm is very stable and is not prone to bad local extrema. -Furthermore, it automatically scales when input data have very large or -very small range. - -INPUT PARAMETERS: - X - array[N], stores X-values. - MUST include only non-negative numbers (but may include - zero values). Can be unsorted. - Y - array[N], values to fit. - N - number of points. If N is less than length of X/Y, only - leading N elements are used. - CnstrLeft- optional equality constraint for model value at the left - boundary (at X=0). Specify NAN (Not-a-Number) if you do - not need constraint on the model value at X=0 (in C++ you - can pass alglib::fp_nan as parameter, in C# it will be - Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - CnstrRight- optional equality constraint for model value at X=infinity. - Specify NAN (Not-a-Number) if you do not need constraint - on the model value (in C++ you can pass alglib::fp_nan as - parameter, in C# it will be Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - -OUTPUT PARAMETERS: - A, B, C, D- parameters of 4PL model - Rep - fitting report. This structure has many fields, but ONLY - ONES LISTED BELOW ARE SET: - * Rep.IterationsCount - number of iterations performed - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average absolute error - * Rep.AvgRelError - average relative error (calculated for - non-zero Y-values) - * Rep.MaxError - maximum absolute error - * Rep.R2 - coefficient of determination, R-squared. This - coefficient is calculated as R2=1-RSS/TSS (in case - of nonlinear regression there are multiple ways to - define R2, each of them giving different results). - -NOTE: for stability reasons the B parameter is restricted by [1/1000,1000] - range. It prevents algorithm from making trial steps deep into the - area of bad parameters. - -NOTE: after you obtained coefficients, you can evaluate model with - LogisticCalc4() function. - -NOTE: if you need better control over fitting process than provided by this - function, you may use LogisticFit45X(). - -NOTE: step is automatically scaled according to scale of parameters being - fitted before we compare its length with EpsX. Thus, this function - can be used to fit data with very small or very large values without - changing EpsX. - -EQUALITY CONSTRAINTS ON PARAMETERS - -4PL/5PL solver supports equality constraints on model values at the left -boundary (X=0) and right boundary (X=infinity). These constraints are -completely optional and you can specify both of them, only one - or no -constraints at all. - -Parameter CnstrLeft contains left constraint (or NAN for unconstrained -fitting), and CnstrRight contains right one. For 4PL, left constraint -ALWAYS corresponds to parameter A, and right one is ALWAYS constraint on -D. That's because 4PL model is normalized in such way that B>=0. - - - -- ALGLIB PROJECT -- - Copyright 14.02.2014 by Bochkanov Sergey -*************************************************************************/ -void logisticfit4ec(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - double cnstrleft, - double cnstrright, - double* a, - double* b, - double* c, - double* d, - lsfitreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - double g; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - *a = 0; - *b = 0; - *c = 0; - *d = 0; - _lsfitreport_clear(rep); - - logisticfit45x(x, y, n, cnstrleft, cnstrright, ae_true, 0.0, 0.0, 0, a, b, c, d, &g, rep, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function fits five-parameter logistic (5PL) model to data provided -by user. 5PL model has following form: - - F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G) - -Here: - * A, D - unconstrained - * B - unconstrained - * C>0 - * G>0 - -IMPORTANT: unlike in 4PL fitting, output of this function is NOT - constrained in such way that B is guaranteed to be positive. - Furthermore, unlike 4PL, 5PL model is NOT symmetric with - respect to B, so you can NOT transform model to equivalent one, - with B having desired sign (>0 or <0). - -5PL fitting is implemented as follows: -* we perform small number of restarts from random locations which helps to - solve problem of bad local extrema. Locations are only partially random - - we use input data to determine good initial guess, but we include - controlled amount of randomness. -* we perform Levenberg-Marquardt fitting with very tight constraints on - parameters B and C - it allows us to find good initial guess for the - second stage without risk of running into "flat spot". Parameter G is - fixed at G=1. -* second Levenberg-Marquardt round is performed without excessive - constraints on B and C, but with G still equal to 1. Results from the - previous round are used as initial guess. -* third Levenberg-Marquardt round relaxes constraints on G and tries two - different models - one with B>0 and one with B<0. -* after fitting is done, we compare results with best values found so far, - rewrite "best solution" if needed, and move to next random location. - -Overall algorithm is very stable and is not prone to bad local extrema. -Furthermore, it automatically scales when input data have very large or -very small range. - -INPUT PARAMETERS: - X - array[N], stores X-values. - MUST include only non-negative numbers (but may include - zero values). Can be unsorted. - Y - array[N], values to fit. - N - number of points. If N is less than length of X/Y, only - leading N elements are used. - -OUTPUT PARAMETERS: - A,B,C,D,G- parameters of 5PL model - Rep - fitting report. This structure has many fields, but ONLY - ONES LISTED BELOW ARE SET: - * Rep.IterationsCount - number of iterations performed - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average absolute error - * Rep.AvgRelError - average relative error (calculated for - non-zero Y-values) - * Rep.MaxError - maximum absolute error - * Rep.R2 - coefficient of determination, R-squared. This - coefficient is calculated as R2=1-RSS/TSS (in case - of nonlinear regression there are multiple ways to - define R2, each of them giving different results). - -NOTE: for better stability B parameter is restricted by [+-1/1000,+-1000] - range, and G is restricted by [1/10,10] range. It prevents algorithm - from making trial steps deep into the area of bad parameters. - -NOTE: after you obtained coefficients, you can evaluate model with - LogisticCalc5() function. - -NOTE: if you need better control over fitting process than provided by this - function, you may use LogisticFit45X(). - -NOTE: step is automatically scaled according to scale of parameters being - fitted before we compare its length with EpsX. Thus, this function - can be used to fit data with very small or very large values without - changing EpsX. - - - -- ALGLIB PROJECT -- - Copyright 14.02.2014 by Bochkanov Sergey -*************************************************************************/ -void logisticfit5(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - double* a, - double* b, - double* c, - double* d, - double* g, - lsfitreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - *a = 0; - *b = 0; - *c = 0; - *d = 0; - *g = 0; - _lsfitreport_clear(rep); - - logisticfit45x(x, y, n, _state->v_nan, _state->v_nan, ae_false, 0.0, 0.0, 0, a, b, c, d, g, rep, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function fits five-parameter logistic (5PL) model to data provided -by user, subject to optional equality constraints on parameters A and D. -5PL model has following form: - - F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G) - -Here: - * A, D - with optional equality constraints - * B - unconstrained - * C>0 - * G>0 - -IMPORTANT: unlike in 4PL fitting, output of this function is NOT - constrained in such way that B is guaranteed to be positive. - Furthermore, unlike 4PL, 5PL model is NOT symmetric with - respect to B, so you can NOT transform model to equivalent one, - with B having desired sign (>0 or <0). - -5PL fitting is implemented as follows: -* we perform small number of restarts from random locations which helps to - solve problem of bad local extrema. Locations are only partially random - - we use input data to determine good initial guess, but we include - controlled amount of randomness. -* we perform Levenberg-Marquardt fitting with very tight constraints on - parameters B and C - it allows us to find good initial guess for the - second stage without risk of running into "flat spot". Parameter G is - fixed at G=1. -* second Levenberg-Marquardt round is performed without excessive - constraints on B and C, but with G still equal to 1. Results from the - previous round are used as initial guess. -* third Levenberg-Marquardt round relaxes constraints on G and tries two - different models - one with B>0 and one with B<0. -* after fitting is done, we compare results with best values found so far, - rewrite "best solution" if needed, and move to next random location. - -Overall algorithm is very stable and is not prone to bad local extrema. -Furthermore, it automatically scales when input data have very large or -very small range. - -INPUT PARAMETERS: - X - array[N], stores X-values. - MUST include only non-negative numbers (but may include - zero values). Can be unsorted. - Y - array[N], values to fit. - N - number of points. If N is less than length of X/Y, only - leading N elements are used. - CnstrLeft- optional equality constraint for model value at the left - boundary (at X=0). Specify NAN (Not-a-Number) if you do - not need constraint on the model value at X=0 (in C++ you - can pass alglib::fp_nan as parameter, in C# it will be - Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - CnstrRight- optional equality constraint for model value at X=infinity. - Specify NAN (Not-a-Number) if you do not need constraint - on the model value (in C++ you can pass alglib::fp_nan as - parameter, in C# it will be Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - -OUTPUT PARAMETERS: - A,B,C,D,G- parameters of 5PL model - Rep - fitting report. This structure has many fields, but ONLY - ONES LISTED BELOW ARE SET: - * Rep.IterationsCount - number of iterations performed - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average absolute error - * Rep.AvgRelError - average relative error (calculated for - non-zero Y-values) - * Rep.MaxError - maximum absolute error - * Rep.R2 - coefficient of determination, R-squared. This - coefficient is calculated as R2=1-RSS/TSS (in case - of nonlinear regression there are multiple ways to - define R2, each of them giving different results). - -NOTE: for better stability B parameter is restricted by [+-1/1000,+-1000] - range, and G is restricted by [1/10,10] range. It prevents algorithm - from making trial steps deep into the area of bad parameters. - -NOTE: after you obtained coefficients, you can evaluate model with - LogisticCalc5() function. - -NOTE: if you need better control over fitting process than provided by this - function, you may use LogisticFit45X(). - -NOTE: step is automatically scaled according to scale of parameters being - fitted before we compare its length with EpsX. Thus, this function - can be used to fit data with very small or very large values without - changing EpsX. - -EQUALITY CONSTRAINTS ON PARAMETERS - -5PL solver supports equality constraints on model values at the left -boundary (X=0) and right boundary (X=infinity). These constraints are -completely optional and you can specify both of them, only one - or no -constraints at all. - -Parameter CnstrLeft contains left constraint (or NAN for unconstrained -fitting), and CnstrRight contains right one. - -Unlike 4PL one, 5PL model is NOT symmetric with respect to change in sign -of B. Thus, negative B's are possible, and left constraint may constrain -parameter A (for positive B's) - or parameter D (for negative B's). -Similarly changes meaning of right constraint. - -You do not have to decide what parameter to constrain - algorithm will -automatically determine correct parameters as fitting progresses. However, -question highlighted above is important when you interpret fitting results. - - - -- ALGLIB PROJECT -- - Copyright 14.02.2014 by Bochkanov Sergey -*************************************************************************/ -void logisticfit5ec(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - double cnstrleft, - double cnstrright, - double* a, - double* b, - double* c, - double* d, - double* g, - lsfitreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - *a = 0; - *b = 0; - *c = 0; - *d = 0; - *g = 0; - _lsfitreport_clear(rep); - - logisticfit45x(x, y, n, cnstrleft, cnstrright, ae_false, 0.0, 0.0, 0, a, b, c, d, g, rep, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This is "expert" 4PL/5PL fitting function, which can be used if you need -better control over fitting process than provided by LogisticFit4() or -LogisticFit5(). - -This function fits model of the form - - F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B)) (4PL model) - -or - - F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G) (5PL model) - -Here: - * A, D - unconstrained - * B>=0 for 4PL, unconstrained for 5PL - * C>0 - * G>0 (if present) - -INPUT PARAMETERS: - X - array[N], stores X-values. - MUST include only non-negative numbers (but may include - zero values). Can be unsorted. - Y - array[N], values to fit. - N - number of points. If N is less than length of X/Y, only - leading N elements are used. - CnstrLeft- optional equality constraint for model value at the left - boundary (at X=0). Specify NAN (Not-a-Number) if you do - not need constraint on the model value at X=0 (in C++ you - can pass alglib::fp_nan as parameter, in C# it will be - Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - CnstrRight- optional equality constraint for model value at X=infinity. - Specify NAN (Not-a-Number) if you do not need constraint - on the model value (in C++ you can pass alglib::fp_nan as - parameter, in C# it will be Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - Is4PL - whether 4PL or 5PL models are fitted - LambdaV - regularization coefficient, LambdaV>=0. - Set it to zero unless you know what you are doing. - EpsX - stopping condition (step size), EpsX>=0. - Zero value means that small step is automatically chosen. - See notes below for more information. - RsCnt - number of repeated restarts from random points. 4PL/5PL - models are prone to problem of bad local extrema. Utilizing - multiple random restarts allows us to improve algorithm - convergence. - RsCnt>=0. - Zero value means that function automatically choose small - amount of restarts (recommended). - -OUTPUT PARAMETERS: - A, B, C, D- parameters of 4PL model - G - parameter of 5PL model; for Is4PL=True, G=1 is returned. - Rep - fitting report. This structure has many fields, but ONLY - ONES LISTED BELOW ARE SET: - * Rep.IterationsCount - number of iterations performed - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average absolute error - * Rep.AvgRelError - average relative error (calculated for - non-zero Y-values) - * Rep.MaxError - maximum absolute error - * Rep.R2 - coefficient of determination, R-squared. This - coefficient is calculated as R2=1-RSS/TSS (in case - of nonlinear regression there are multiple ways to - define R2, each of them giving different results). - -NOTE: for better stability B parameter is restricted by [+-1/1000,+-1000] - range, and G is restricted by [1/10,10] range. It prevents algorithm - from making trial steps deep into the area of bad parameters. - -NOTE: after you obtained coefficients, you can evaluate model with - LogisticCalc5() function. - -NOTE: step is automatically scaled according to scale of parameters being - fitted before we compare its length with EpsX. Thus, this function - can be used to fit data with very small or very large values without - changing EpsX. - -EQUALITY CONSTRAINTS ON PARAMETERS - -4PL/5PL solver supports equality constraints on model values at the left -boundary (X=0) and right boundary (X=infinity). These constraints are -completely optional and you can specify both of them, only one - or no -constraints at all. - -Parameter CnstrLeft contains left constraint (or NAN for unconstrained -fitting), and CnstrRight contains right one. For 4PL, left constraint -ALWAYS corresponds to parameter A, and right one is ALWAYS constraint on -D. That's because 4PL model is normalized in such way that B>=0. - -For 5PL model things are different. Unlike 4PL one, 5PL model is NOT -symmetric with respect to change in sign of B. Thus, negative B's are -possible, and left constraint may constrain parameter A (for positive B's) -- or parameter D (for negative B's). Similarly changes meaning of right -constraint. - -You do not have to decide what parameter to constrain - algorithm will -automatically determine correct parameters as fitting progresses. However, -question highlighted above is important when you interpret fitting results. - - - -- ALGLIB PROJECT -- - Copyright 14.02.2014 by Bochkanov Sergey -*************************************************************************/ -void logisticfit45x(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - double cnstrleft, - double cnstrright, - ae_bool is4pl, - double lambdav, - double epsx, - ae_int_t rscnt, - double* a, - double* b, - double* c, - double* d, - double* g, - lsfitreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - ae_int_t i; - ae_int_t outerit; - ae_int_t nz; - double v; - ae_vector p0; - ae_vector p1; - ae_vector p2; - ae_vector bndl; - ae_vector bndu; - ae_vector s; - ae_vector bndl1; - ae_vector bndu1; - ae_vector bndl2; - ae_vector bndu2; - ae_matrix z; - hqrndstate rs; - minlmstate state; - minlmreport replm; - ae_int_t maxits; - double fbest; - double flast; - double scalex; - double scaley; - ae_vector bufx; - ae_vector bufy; - double fposb; - double fnegb; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - memset(&p0, 0, sizeof(p0)); - memset(&p1, 0, sizeof(p1)); - memset(&p2, 0, sizeof(p2)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&s, 0, sizeof(s)); - memset(&bndl1, 0, sizeof(bndl1)); - memset(&bndu1, 0, sizeof(bndu1)); - memset(&bndl2, 0, sizeof(bndl2)); - memset(&bndu2, 0, sizeof(bndu2)); - memset(&z, 0, sizeof(z)); - memset(&rs, 0, sizeof(rs)); - memset(&state, 0, sizeof(state)); - memset(&replm, 0, sizeof(replm)); - memset(&bufx, 0, sizeof(bufx)); - memset(&bufy, 0, sizeof(bufy)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - *a = 0; - *b = 0; - *c = 0; - *d = 0; - *g = 0; - _lsfitreport_clear(rep); - ae_vector_init(&p0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu2, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - _minlmstate_init(&state, _state, ae_true); - _minlmreport_init(&replm, _state, ae_true); - ae_vector_init(&bufx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bufy, 0, DT_REAL, _state, ae_true); - - ae_assert(ae_isfinite(epsx, _state), "LogisticFitX: EpsX is infinite/NAN", _state); - ae_assert(ae_isfinite(lambdav, _state), "LogisticFitX: LambdaV is infinite/NAN", _state); - ae_assert(ae_isfinite(cnstrleft, _state)||ae_isnan(cnstrleft, _state), "LogisticFitX: CnstrLeft is NOT finite or NAN", _state); - ae_assert(ae_isfinite(cnstrright, _state)||ae_isnan(cnstrright, _state), "LogisticFitX: CnstrRight is NOT finite or NAN", _state); - ae_assert(ae_fp_greater_eq(lambdav,(double)(0)), "LogisticFitX: negative LambdaV", _state); - ae_assert(n>0, "LogisticFitX: N<=0", _state); - ae_assert(rscnt>=0, "LogisticFitX: RsCnt<0", _state); - ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "LogisticFitX: EpsX<0", _state); - ae_assert(x->cnt>=n, "LogisticFitX: Length(X)cnt>=n, "LogisticFitX: Length(Y)ptr.p_double[0],(double)(0)), "LogisticFitX: some X[] are negative", _state); - nz = n; - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(x->ptr.p_double[i],(double)(0)) ) - { - nz = i; - break; - } - } - - /* - * For NZ=N (all X[] are zero) special code is used. - * For NZiterationscount = 0; - if( nz==n ) - { - - /* - * NZ=N, degenerate problem. - * No need to run optimizer. - */ - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+y->ptr.p_double[i]; - } - v = v/n; - if( ae_isfinite(cnstrleft, _state) ) - { - *a = cnstrleft; - } - else - { - *a = v; - } - *b = (double)(1); - *c = (double)(1); - if( ae_isfinite(cnstrright, _state) ) - { - *d = cnstrright; - } - else - { - *d = *a; - } - *g = (double)(1); - lsfit_logisticfit45errors(x, y, n, *a, *b, *c, *d, *g, rep, _state); - ae_frame_leave(_state); - return; - } - - /* - * Non-degenerate problem. - * Determine scale of data. - */ - scalex = x->ptr.p_double[nz+(n-nz)/2]; - ae_assert(ae_fp_greater(scalex,(double)(0)), "LogisticFitX: internal error", _state); - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+y->ptr.p_double[i]; - } - v = v/n; - scaley = 0.0; - for(i=0; i<=n-1; i++) - { - scaley = scaley+ae_sqr(y->ptr.p_double[i]-v, _state); - } - scaley = ae_sqrt(scaley/n, _state); - if( ae_fp_eq(scaley,(double)(0)) ) - { - scaley = 1.0; - } - ae_vector_set_length(&s, 5, _state); - s.ptr.p_double[0] = scaley; - s.ptr.p_double[1] = 0.1; - s.ptr.p_double[2] = scalex; - s.ptr.p_double[3] = scaley; - s.ptr.p_double[4] = 0.1; - ae_vector_set_length(&p0, 5, _state); - p0.ptr.p_double[0] = (double)(0); - p0.ptr.p_double[1] = (double)(0); - p0.ptr.p_double[2] = (double)(0); - p0.ptr.p_double[3] = (double)(0); - p0.ptr.p_double[4] = (double)(0); - ae_vector_set_length(&bndl, 5, _state); - ae_vector_set_length(&bndu, 5, _state); - ae_vector_set_length(&bndl1, 5, _state); - ae_vector_set_length(&bndu1, 5, _state); - ae_vector_set_length(&bndl2, 5, _state); - ae_vector_set_length(&bndu2, 5, _state); - minlmcreatevj(5, n+5, &p0, &state, _state); - minlmsetscale(&state, &s, _state); - minlmsetcond(&state, epsx, maxits, _state); - minlmsetxrep(&state, ae_true, _state); - ae_vector_set_length(&p1, 5, _state); - ae_vector_set_length(&p2, 5, _state); - - /* - * Is it 4PL problem? - */ - if( is4pl ) - { - - /* - * Run outer iterations - */ - *a = (double)(0); - *b = (double)(1); - *c = (double)(1); - *d = (double)(1); - *g = (double)(1); - fbest = ae_maxrealnumber; - for(outerit=0; outerit<=rscnt-1; outerit++) - { - - /* - * Prepare initial point; use B>0 - */ - if( ae_isfinite(cnstrleft, _state) ) - { - p1.ptr.p_double[0] = cnstrleft; - } - else - { - p1.ptr.p_double[0] = y->ptr.p_double[0]+0.15*scaley*(hqrnduniformr(&rs, _state)-0.5); - } - p1.ptr.p_double[1] = 0.5+hqrnduniformr(&rs, _state); - p1.ptr.p_double[2] = x->ptr.p_double[nz+hqrnduniformi(&rs, n-nz, _state)]; - if( ae_isfinite(cnstrright, _state) ) - { - p1.ptr.p_double[3] = cnstrright; - } - else - { - p1.ptr.p_double[3] = y->ptr.p_double[n-1]+0.25*scaley*(hqrnduniformr(&rs, _state)-0.5); - } - p1.ptr.p_double[4] = 1.0; - - /* - * Run optimization with tight constraints and increased regularization - */ - if( ae_isfinite(cnstrleft, _state) ) - { - bndl.ptr.p_double[0] = cnstrleft; - bndu.ptr.p_double[0] = cnstrleft; - } - else - { - bndl.ptr.p_double[0] = _state->v_neginf; - bndu.ptr.p_double[0] = _state->v_posinf; - } - bndl.ptr.p_double[1] = 0.5; - bndu.ptr.p_double[1] = 2.0; - bndl.ptr.p_double[2] = 0.5*scalex; - bndu.ptr.p_double[2] = 2.0*scalex; - if( ae_isfinite(cnstrright, _state) ) - { - bndl.ptr.p_double[3] = cnstrright; - bndu.ptr.p_double[3] = cnstrright; - } - else - { - bndl.ptr.p_double[3] = _state->v_neginf; - bndu.ptr.p_double[3] = _state->v_posinf; - } - bndl.ptr.p_double[4] = 1.0; - bndu.ptr.p_double[4] = 1.0; - minlmsetbc(&state, &bndl, &bndu, _state); - lsfit_logisticfitinternal(x, y, n, is4pl, 100*lambdav, &state, &replm, &p1, &flast, _state); - rep->iterationscount = rep->iterationscount+replm.iterationscount; - - /* - * Relax constraints, run optimization one more time - */ - bndl.ptr.p_double[1] = 0.1; - bndu.ptr.p_double[1] = 10.0; - bndl.ptr.p_double[2] = ae_machineepsilon*scalex; - bndu.ptr.p_double[2] = scalex/ae_machineepsilon; - minlmsetbc(&state, &bndl, &bndu, _state); - lsfit_logisticfitinternal(x, y, n, is4pl, lambdav, &state, &replm, &p1, &flast, _state); - rep->iterationscount = rep->iterationscount+replm.iterationscount; - - /* - * Relax constraints more, run optimization one more time - */ - bndl.ptr.p_double[1] = 0.01; - bndu.ptr.p_double[1] = 100.0; - minlmsetbc(&state, &bndl, &bndu, _state); - lsfit_logisticfitinternal(x, y, n, is4pl, lambdav, &state, &replm, &p1, &flast, _state); - rep->iterationscount = rep->iterationscount+replm.iterationscount; - - /* - * Relax constraints ever more, run optimization one more time - */ - bndl.ptr.p_double[1] = 0.001; - bndu.ptr.p_double[1] = 1000.0; - minlmsetbc(&state, &bndl, &bndu, _state); - lsfit_logisticfitinternal(x, y, n, is4pl, lambdav, &state, &replm, &p1, &flast, _state); - rep->iterationscount = rep->iterationscount+replm.iterationscount; - - /* - * Compare results with best value found so far. - */ - if( ae_fp_less(flast,fbest) ) - { - *a = p1.ptr.p_double[0]; - *b = p1.ptr.p_double[1]; - *c = p1.ptr.p_double[2]; - *d = p1.ptr.p_double[3]; - *g = p1.ptr.p_double[4]; - fbest = flast; - } - } - lsfit_logisticfit45errors(x, y, n, *a, *b, *c, *d, *g, rep, _state); - ae_frame_leave(_state); - return; - } - - /* - * Well.... we have 5PL fit, and we have to test two separate branches: - * B>0 and B<0, because of asymmetry in the curve. First, we run optimization - * with tight constraints two times, in order to determine better sign for B. - * - * Run outer iterations - */ - *a = (double)(0); - *b = (double)(1); - *c = (double)(1); - *d = (double)(1); - *g = (double)(1); - fbest = ae_maxrealnumber; - for(outerit=0; outerit<=rscnt-1; outerit++) - { - - /* - * First, we try positive B. - */ - p1.ptr.p_double[0] = y->ptr.p_double[0]+0.15*scaley*(hqrnduniformr(&rs, _state)-0.5); - p1.ptr.p_double[1] = 0.5+hqrnduniformr(&rs, _state); - p1.ptr.p_double[2] = x->ptr.p_double[nz+hqrnduniformi(&rs, n-nz, _state)]; - p1.ptr.p_double[3] = y->ptr.p_double[n-1]+0.25*scaley*(hqrnduniformr(&rs, _state)-0.5); - p1.ptr.p_double[4] = 1.0; - bndl1.ptr.p_double[0] = _state->v_neginf; - bndu1.ptr.p_double[0] = _state->v_posinf; - bndl1.ptr.p_double[1] = 0.5; - bndu1.ptr.p_double[1] = 2.0; - bndl1.ptr.p_double[2] = 0.5*scalex; - bndu1.ptr.p_double[2] = 2.0*scalex; - bndl1.ptr.p_double[3] = _state->v_neginf; - bndu1.ptr.p_double[3] = _state->v_posinf; - bndl1.ptr.p_double[4] = 0.5; - bndu1.ptr.p_double[4] = 2.0; - if( ae_isfinite(cnstrleft, _state) ) - { - p1.ptr.p_double[0] = cnstrleft; - bndl1.ptr.p_double[0] = cnstrleft; - bndu1.ptr.p_double[0] = cnstrleft; - } - if( ae_isfinite(cnstrright, _state) ) - { - p1.ptr.p_double[3] = cnstrright; - bndl1.ptr.p_double[3] = cnstrright; - bndu1.ptr.p_double[3] = cnstrright; - } - minlmsetbc(&state, &bndl1, &bndu1, _state); - lsfit_logisticfitinternal(x, y, n, is4pl, 100*lambdav, &state, &replm, &p1, &fposb, _state); - rep->iterationscount = rep->iterationscount+replm.iterationscount; - - /* - * Second attempt - with negative B (constraints are still tight). - */ - p2.ptr.p_double[0] = y->ptr.p_double[n-1]+0.15*scaley*(hqrnduniformr(&rs, _state)-0.5); - p2.ptr.p_double[1] = -(0.5+hqrnduniformr(&rs, _state)); - p2.ptr.p_double[2] = x->ptr.p_double[nz+hqrnduniformi(&rs, n-nz, _state)]; - p2.ptr.p_double[3] = y->ptr.p_double[0]+0.25*scaley*(hqrnduniformr(&rs, _state)-0.5); - p2.ptr.p_double[4] = 1.0; - bndl2.ptr.p_double[0] = _state->v_neginf; - bndu2.ptr.p_double[0] = _state->v_posinf; - bndl2.ptr.p_double[1] = -2.0; - bndu2.ptr.p_double[1] = -0.5; - bndl2.ptr.p_double[2] = 0.5*scalex; - bndu2.ptr.p_double[2] = 2.0*scalex; - bndl2.ptr.p_double[3] = _state->v_neginf; - bndu2.ptr.p_double[3] = _state->v_posinf; - bndl2.ptr.p_double[4] = 0.5; - bndu2.ptr.p_double[4] = 2.0; - if( ae_isfinite(cnstrleft, _state) ) - { - p2.ptr.p_double[3] = cnstrleft; - bndl2.ptr.p_double[3] = cnstrleft; - bndu2.ptr.p_double[3] = cnstrleft; - } - if( ae_isfinite(cnstrright, _state) ) - { - p2.ptr.p_double[0] = cnstrright; - bndl2.ptr.p_double[0] = cnstrright; - bndu2.ptr.p_double[0] = cnstrright; - } - minlmsetbc(&state, &bndl2, &bndu2, _state); - lsfit_logisticfitinternal(x, y, n, is4pl, 100*lambdav, &state, &replm, &p2, &fnegb, _state); - rep->iterationscount = rep->iterationscount+replm.iterationscount; - - /* - * Select best version of B sign - */ - if( ae_fp_less(fposb,fnegb) ) - { - - /* - * Prepare relaxed constraints assuming that B is positive - */ - bndl1.ptr.p_double[1] = 0.1; - bndu1.ptr.p_double[1] = 10.0; - bndl1.ptr.p_double[2] = ae_machineepsilon*scalex; - bndu1.ptr.p_double[2] = scalex/ae_machineepsilon; - bndl1.ptr.p_double[4] = 0.1; - bndu1.ptr.p_double[4] = 10.0; - minlmsetbc(&state, &bndl1, &bndu1, _state); - lsfit_logisticfitinternal(x, y, n, is4pl, lambdav, &state, &replm, &p1, &flast, _state); - rep->iterationscount = rep->iterationscount+replm.iterationscount; - - /* - * Prepare stronger relaxation of constraints - */ - bndl1.ptr.p_double[1] = 0.01; - bndu1.ptr.p_double[1] = 100.0; - minlmsetbc(&state, &bndl1, &bndu1, _state); - lsfit_logisticfitinternal(x, y, n, is4pl, lambdav, &state, &replm, &p1, &flast, _state); - rep->iterationscount = rep->iterationscount+replm.iterationscount; - - /* - * Prepare stronger relaxation of constraints - */ - bndl1.ptr.p_double[1] = 0.001; - bndu1.ptr.p_double[1] = 1000.0; - minlmsetbc(&state, &bndl1, &bndu1, _state); - lsfit_logisticfitinternal(x, y, n, is4pl, lambdav, &state, &replm, &p1, &flast, _state); - rep->iterationscount = rep->iterationscount+replm.iterationscount; - - /* - * Compare results with best value found so far. - */ - if( ae_fp_less(flast,fbest) ) - { - *a = p1.ptr.p_double[0]; - *b = p1.ptr.p_double[1]; - *c = p1.ptr.p_double[2]; - *d = p1.ptr.p_double[3]; - *g = p1.ptr.p_double[4]; - fbest = flast; - } - } - else - { - - /* - * Prepare relaxed constraints assuming that B is negative - */ - bndl2.ptr.p_double[1] = -10.0; - bndu2.ptr.p_double[1] = -0.1; - bndl2.ptr.p_double[2] = ae_machineepsilon*scalex; - bndu2.ptr.p_double[2] = scalex/ae_machineepsilon; - bndl2.ptr.p_double[4] = 0.1; - bndu2.ptr.p_double[4] = 10.0; - minlmsetbc(&state, &bndl2, &bndu2, _state); - lsfit_logisticfitinternal(x, y, n, is4pl, lambdav, &state, &replm, &p2, &flast, _state); - rep->iterationscount = rep->iterationscount+replm.iterationscount; - - /* - * Prepare stronger relaxation - */ - bndl2.ptr.p_double[1] = -100.0; - bndu2.ptr.p_double[1] = -0.01; - minlmsetbc(&state, &bndl2, &bndu2, _state); - lsfit_logisticfitinternal(x, y, n, is4pl, lambdav, &state, &replm, &p2, &flast, _state); - rep->iterationscount = rep->iterationscount+replm.iterationscount; - - /* - * Prepare stronger relaxation - */ - bndl2.ptr.p_double[1] = -1000.0; - bndu2.ptr.p_double[1] = -0.001; - minlmsetbc(&state, &bndl2, &bndu2, _state); - lsfit_logisticfitinternal(x, y, n, is4pl, lambdav, &state, &replm, &p2, &flast, _state); - rep->iterationscount = rep->iterationscount+replm.iterationscount; - - /* - * Compare results with best value found so far. - */ - if( ae_fp_less(flast,fbest) ) - { - *a = p2.ptr.p_double[0]; - *b = p2.ptr.p_double[1]; - *c = p2.ptr.p_double[2]; - *d = p2.ptr.p_double[3]; - *g = p2.ptr.p_double[4]; - fbest = flast; - } - } - } - lsfit_logisticfit45errors(x, y, n, *a, *b, *c, *d, *g, rep, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Weghted rational least squares fitting using Floater-Hormann rational -functions with optimal D chosen from [0,9], with constraints and -individual weights. - -Equidistant grid with M node on [min(x),max(x)] is used to build basis -functions. Different values of D are tried, optimal D (least WEIGHTED root -mean square error) is chosen. Task is linear, so linear least squares -solver is used. Complexity of this computational scheme is O(N*M^2) -(mostly dominated by the least squares solver). - -SEE ALSO -* BarycentricFitFloaterHormann(), "lightweight" fitting without invididual - weights and constraints. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - W - weights, array[0..N-1] - Each summand in square sum of approximation deviations from - given values is multiplied by the square of corresponding - weight. Fill it by 1's if you don't want to solve weighted - task. - N - number of points, N>0. - XC - points where function values/derivatives are constrained, - array[0..K-1]. - YC - values of constraints, array[0..K-1] - DC - array[0..K-1], types of constraints: - * DC[i]=0 means that S(XC[i])=YC[i] - * DC[i]=1 means that S'(XC[i])=YC[i] - SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS - K - number of constraints, 0<=K=2. - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearWC() subroutine. - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - -1 means another errors in parameters passed - (N<=0, for example) - B - barycentric interpolant. - Rep - report, same format as in LSFitLinearWC() subroutine. - Following fields are set: - * DBest best value of the D parameter - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroutine doesn't calculate task's condition number for K<>0. - -SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: - -Setting constraints can lead to undesired results, like ill-conditioned -behavior, or inconsistency being detected. From the other side, it allows -us to improve quality of the fit. Here we summarize our experience with -constrained barycentric interpolants: -* excessive constraints can be inconsistent. Floater-Hormann basis - functions aren't as flexible as splines (although they are very smooth). -* the more evenly constraints are spread across [min(x),max(x)], the more - chances that they will be consistent -* the greater is M (given fixed constraints), the more chances that - constraints will be consistent -* in the general case, consistency of constraints IS NOT GUARANTEED. -* in the several special cases, however, we CAN guarantee consistency. -* one of this cases is constraints on the function VALUES at the interval - boundaries. Note that consustency of the constraints on the function - DERIVATIVES is NOT guaranteed (you can use in such cases cubic splines - which are more flexible). -* another special case is ONE constraint on the function value (OR, but - not AND, derivative) anywhere in the interval - -Our final recommendation is to use constraints WHEN AND ONLY WHEN you -can't solve your task without them. Anything beyond special cases given -above is not guaranteed and may result in inconsistency. - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentricfitfloaterhormannwc(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_int_t n, - /* Real */ ae_vector* xc, - /* Real */ ae_vector* yc, - /* Integer */ ae_vector* dc, - ae_int_t k, - ae_int_t m, - ae_int_t* info, - barycentricinterpolant* b, - barycentricfitreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t d; - ae_int_t i; - double wrmscur; - double wrmsbest; - barycentricinterpolant locb; - barycentricfitreport locrep; - ae_int_t locinfo; - - ae_frame_make(_state, &_frame_block); - memset(&locb, 0, sizeof(locb)); - memset(&locrep, 0, sizeof(locrep)); - *info = 0; - _barycentricinterpolant_clear(b); - _barycentricfitreport_clear(rep); - _barycentricinterpolant_init(&locb, _state, ae_true); - _barycentricfitreport_init(&locrep, _state, ae_true); - - ae_assert(n>0, "BarycentricFitFloaterHormannWC: N<=0!", _state); - ae_assert(m>0, "BarycentricFitFloaterHormannWC: M<=0!", _state); - ae_assert(k>=0, "BarycentricFitFloaterHormannWC: K<0!", _state); - ae_assert(k=M!", _state); - ae_assert(x->cnt>=n, "BarycentricFitFloaterHormannWC: Length(X)cnt>=n, "BarycentricFitFloaterHormannWC: Length(Y)cnt>=n, "BarycentricFitFloaterHormannWC: Length(W)cnt>=k, "BarycentricFitFloaterHormannWC: Length(XC)cnt>=k, "BarycentricFitFloaterHormannWC: Length(YC)cnt>=k, "BarycentricFitFloaterHormannWC: Length(DC)ptr.p_int[i]==0||dc->ptr.p_int[i]==1, "BarycentricFitFloaterHormannWC: one of DC[] is not 0 or 1!", _state); - } - - /* - * Find optimal D - * - * Info is -3 by default (degenerate constraints). - * If LocInfo will always be equal to -3, Info will remain equal to -3. - * If at least once LocInfo will be -4, Info will be -4. - */ - wrmsbest = ae_maxrealnumber; - rep->dbest = -1; - *info = -3; - for(d=0; d<=ae_minint(9, n-1, _state); d++) - { - lsfit_barycentricfitwcfixedd(x, y, w, n, xc, yc, dc, k, m, d, &locinfo, &locb, &locrep, _state); - ae_assert((locinfo==-4||locinfo==-3)||locinfo>0, "BarycentricFitFloaterHormannWC: unexpected result from BarycentricFitWCFixedD!", _state); - if( locinfo>0 ) - { - - /* - * Calculate weghted RMS - */ - wrmscur = (double)(0); - for(i=0; i<=n-1; i++) - { - wrmscur = wrmscur+ae_sqr(w->ptr.p_double[i]*(y->ptr.p_double[i]-barycentriccalc(&locb, x->ptr.p_double[i], _state)), _state); - } - wrmscur = ae_sqrt(wrmscur/n, _state); - if( ae_fp_less(wrmscur,wrmsbest)||rep->dbest<0 ) - { - barycentriccopy(&locb, b, _state); - rep->dbest = d; - *info = 1; - rep->rmserror = locrep.rmserror; - rep->avgerror = locrep.avgerror; - rep->avgrelerror = locrep.avgrelerror; - rep->maxerror = locrep.maxerror; - rep->taskrcond = locrep.taskrcond; - wrmsbest = wrmscur; - } - } - else - { - if( locinfo!=-3&&*info<0 ) - { - *info = locinfo; - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Rational least squares fitting using Floater-Hormann rational functions -with optimal D chosen from [0,9]. - -Equidistant grid with M node on [min(x),max(x)] is used to build basis -functions. Different values of D are tried, optimal D (least root mean -square error) is chosen. Task is linear, so linear least squares solver -is used. Complexity of this computational scheme is O(N*M^2) (mostly -dominated by the least squares solver). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - N - number of points, N>0. - M - number of basis functions ( = number_of_nodes), M>=2. - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearWC() subroutine. - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - B - barycentric interpolant. - Rep - report, same format as in LSFitLinearWC() subroutine. - Following fields are set: - * DBest best value of the D parameter - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentricfitfloaterhormann(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t m, - ae_int_t* info, - barycentricinterpolant* b, - barycentricfitreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector w; - ae_vector xc; - ae_vector yc; - ae_vector dc; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&w, 0, sizeof(w)); - memset(&xc, 0, sizeof(xc)); - memset(&yc, 0, sizeof(yc)); - memset(&dc, 0, sizeof(dc)); - *info = 0; - _barycentricinterpolant_clear(b); - _barycentricfitreport_clear(rep); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dc, 0, DT_INT, _state, ae_true); - - ae_assert(n>0, "BarycentricFitFloaterHormann: N<=0!", _state); - ae_assert(m>0, "BarycentricFitFloaterHormann: M<=0!", _state); - ae_assert(x->cnt>=n, "BarycentricFitFloaterHormann: Length(X)cnt>=n, "BarycentricFitFloaterHormann: Length(Y)0 - * if given, only first N elements of X/Y/W are processed - * if not given, automatically determined from X/Y/W sizes - XC - points where spline values/derivatives are constrained, - array[0..K-1]. - YC - values of constraints, array[0..K-1] - DC - array[0..K-1], types of constraints: - * DC[i]=0 means that S(XC[i])=YC[i] - * DC[i]=1 means that S'(XC[i])=YC[i] - SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS - K - number of constraints (optional): - * 0<=K=4. - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearWC() subroutine. - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - S - spline interpolant. - Rep - report, same format as in LSFitLinearWC() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - -SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: - -Setting constraints can lead to undesired results, like ill-conditioned -behavior, or inconsistency being detected. From the other side, it allows -us to improve quality of the fit. Here we summarize our experience with -constrained regression splines: -* excessive constraints can be inconsistent. Splines are piecewise cubic - functions, and it is easy to create an example, where large number of - constraints concentrated in small area will result in inconsistency. - Just because spline is not flexible enough to satisfy all of them. And - same constraints spread across the [min(x),max(x)] will be perfectly - consistent. -* the more evenly constraints are spread across [min(x),max(x)], the more - chances that they will be consistent -* the greater is M (given fixed constraints), the more chances that - constraints will be consistent -* in the general case, consistency of constraints IS NOT GUARANTEED. -* in the several special cases, however, we CAN guarantee consistency. -* one of this cases is constraints on the function values AND/OR its - derivatives at the interval boundaries. -* another special case is ONE constraint on the function value (OR, but - not AND, derivative) anywhere in the interval - -Our final recommendation is to use constraints WHEN AND ONLY WHEN you -can't solve your task without them. Anything beyond special cases given -above is not guaranteed and may result in inconsistency. - - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -void spline1dfitcubicwc(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_int_t n, - /* Real */ ae_vector* xc, - /* Real */ ae_vector* yc, - /* Integer */ ae_vector* dc, - ae_int_t k, - ae_int_t m, - ae_int_t* info, - spline1dinterpolant* s, - spline1dfitreport* rep, - ae_state *_state) -{ - ae_int_t i; - - *info = 0; - _spline1dinterpolant_clear(s); - _spline1dfitreport_clear(rep); - - ae_assert(n>=1, "Spline1DFitCubicWC: N<1!", _state); - ae_assert(m>=4, "Spline1DFitCubicWC: M<4!", _state); - ae_assert(k>=0, "Spline1DFitCubicWC: K<0!", _state); - ae_assert(k=M!", _state); - ae_assert(x->cnt>=n, "Spline1DFitCubicWC: Length(X)cnt>=n, "Spline1DFitCubicWC: Length(Y)cnt>=n, "Spline1DFitCubicWC: Length(W)cnt>=k, "Spline1DFitCubicWC: Length(XC)cnt>=k, "Spline1DFitCubicWC: Length(YC)cnt>=k, "Spline1DFitCubicWC: Length(DC)ptr.p_int[i]==0||dc->ptr.p_int[i]==1, "Spline1DFitCubicWC: DC[i] is neither 0 or 1!", _state); - } - lsfit_spline1dfitinternal(0, x, y, w, n, xc, yc, dc, k, m, info, s, rep, _state); -} - - -/************************************************************************* -Weighted fitting by Hermite spline, with constraints on function values -or first derivatives. - -Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is used to build -basis functions. Basis functions are Hermite splines. Small regularizing -term is used when solving constrained tasks (to improve stability). - -Task is linear, so linear least squares solver is used. Complexity of this -computational scheme is O(N*M^2), mostly dominated by least squares solver - -SEE ALSO - Spline1DFitCubicWC() - fitting by Cubic splines (less flexible, - more smooth) - Spline1DFitHermite() - "lightweight" Hermite fitting, without - invididual weights and constraints - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - W - weights, array[0..N-1] - Each summand in square sum of approximation deviations from - given values is multiplied by the square of corresponding - weight. Fill it by 1's if you don't want to solve weighted - task. - N - number of points (optional): - * N>0 - * if given, only first N elements of X/Y/W are processed - * if not given, automatically determined from X/Y/W sizes - XC - points where spline values/derivatives are constrained, - array[0..K-1]. - YC - values of constraints, array[0..K-1] - DC - array[0..K-1], types of constraints: - * DC[i]=0 means that S(XC[i])=YC[i] - * DC[i]=1 means that S'(XC[i])=YC[i] - SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS - K - number of constraints (optional): - * 0<=K=4, - M IS EVEN! - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearW() subroutine: - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - -2 means odd M was passed (which is not supported) - -1 means another errors in parameters passed - (N<=0, for example) - S - spline interpolant. - Rep - report, same format as in LSFitLinearW() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - -IMPORTANT: - this subroitine supports only even M's - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - -SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: - -Setting constraints can lead to undesired results, like ill-conditioned -behavior, or inconsistency being detected. From the other side, it allows -us to improve quality of the fit. Here we summarize our experience with -constrained regression splines: -* excessive constraints can be inconsistent. Splines are piecewise cubic - functions, and it is easy to create an example, where large number of - constraints concentrated in small area will result in inconsistency. - Just because spline is not flexible enough to satisfy all of them. And - same constraints spread across the [min(x),max(x)] will be perfectly - consistent. -* the more evenly constraints are spread across [min(x),max(x)], the more - chances that they will be consistent -* the greater is M (given fixed constraints), the more chances that - constraints will be consistent -* in the general case, consistency of constraints is NOT GUARANTEED. -* in the several special cases, however, we can guarantee consistency. -* one of this cases is M>=4 and constraints on the function value - (AND/OR its derivative) at the interval boundaries. -* another special case is M>=4 and ONE constraint on the function value - (OR, BUT NOT AND, derivative) anywhere in [min(x),max(x)] - -Our final recommendation is to use constraints WHEN AND ONLY when you -can't solve your task without them. Anything beyond special cases given -above is not guaranteed and may result in inconsistency. - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -void spline1dfithermitewc(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_int_t n, - /* Real */ ae_vector* xc, - /* Real */ ae_vector* yc, - /* Integer */ ae_vector* dc, - ae_int_t k, - ae_int_t m, - ae_int_t* info, - spline1dinterpolant* s, - spline1dfitreport* rep, - ae_state *_state) -{ - ae_int_t i; - - *info = 0; - _spline1dinterpolant_clear(s); - _spline1dfitreport_clear(rep); - - ae_assert(n>=1, "Spline1DFitHermiteWC: N<1!", _state); - ae_assert(m>=4, "Spline1DFitHermiteWC: M<4!", _state); - ae_assert(m%2==0, "Spline1DFitHermiteWC: M is odd!", _state); - ae_assert(k>=0, "Spline1DFitHermiteWC: K<0!", _state); - ae_assert(k=M!", _state); - ae_assert(x->cnt>=n, "Spline1DFitHermiteWC: Length(X)cnt>=n, "Spline1DFitHermiteWC: Length(Y)cnt>=n, "Spline1DFitHermiteWC: Length(W)cnt>=k, "Spline1DFitHermiteWC: Length(XC)cnt>=k, "Spline1DFitHermiteWC: Length(YC)cnt>=k, "Spline1DFitHermiteWC: Length(DC)ptr.p_int[i]==0||dc->ptr.p_int[i]==1, "Spline1DFitHermiteWC: DC[i] is neither 0 or 1!", _state); - } - lsfit_spline1dfitinternal(1, x, y, w, n, xc, yc, dc, k, m, info, s, rep, _state); -} - - -/************************************************************************* -Least squares fitting by cubic spline. - -This subroutine is "lightweight" alternative for more complex and feature- -rich Spline1DFitCubicWC(). See Spline1DFitCubicWC() for more information -about subroutine parameters (we don't duplicate it here because of length) - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -void spline1dfitcubic(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t m, - ae_int_t* info, - spline1dinterpolant* s, - spline1dfitreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_vector w; - ae_vector xc; - ae_vector yc; - ae_vector dc; - - ae_frame_make(_state, &_frame_block); - memset(&w, 0, sizeof(w)); - memset(&xc, 0, sizeof(xc)); - memset(&yc, 0, sizeof(yc)); - memset(&dc, 0, sizeof(dc)); - *info = 0; - _spline1dinterpolant_clear(s); - _spline1dfitreport_clear(rep); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dc, 0, DT_INT, _state, ae_true); - - ae_assert(n>=1, "Spline1DFitCubic: N<1!", _state); - ae_assert(m>=4, "Spline1DFitCubic: M<4!", _state); - ae_assert(x->cnt>=n, "Spline1DFitCubic: Length(X)cnt>=n, "Spline1DFitCubic: Length(Y)=1, "Spline1DFitHermite: N<1!", _state); - ae_assert(m>=4, "Spline1DFitHermite: M<4!", _state); - ae_assert(m%2==0, "Spline1DFitHermite: M is odd!", _state); - ae_assert(x->cnt>=n, "Spline1DFitHermite: Length(X)cnt>=n, "Spline1DFitHermite: Length(Y)=1. - M - number of basis functions, M>=1. - -OUTPUT PARAMETERS: - Info - error code: - * -4 internal SVD decomposition subroutine failed (very - rare and for degenerate systems only) - * -1 incorrect N/M were specified - * 1 task is solved - C - decomposition coefficients, array[0..M-1] - Rep - fitting report. Following fields are set: - * Rep.TaskRCond reciprocal of condition number - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(F*CovPar*F')), - where F is functions matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitlinearw(/* Real */ ae_vector* y, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* fmatrix, - ae_int_t n, - ae_int_t m, - ae_int_t* info, - /* Real */ ae_vector* c, - lsfitreport* rep, - ae_state *_state) -{ - - *info = 0; - ae_vector_clear(c); - _lsfitreport_clear(rep); - - ae_assert(n>=1, "LSFitLinearW: N<1!", _state); - ae_assert(m>=1, "LSFitLinearW: M<1!", _state); - ae_assert(y->cnt>=n, "LSFitLinearW: length(Y)cnt>=n, "LSFitLinearW: length(W)rows>=n, "LSFitLinearW: rows(FMatrix)cols>=m, "LSFitLinearW: cols(FMatrix)=1. - M - number of basis functions, M>=1. - K - number of constraints, 0 <= K < M - K=0 corresponds to absence of constraints. - -OUTPUT PARAMETERS: - Info - error code: - * -4 internal SVD decomposition subroutine failed (very - rare and for degenerate systems only) - * -3 either too many constraints (M or more), - degenerate constraints (some constraints are - repetead twice) or inconsistent constraints were - specified. - * 1 task is solved - C - decomposition coefficients, array[0..M-1] - Rep - fitting report. Following fields are set: - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(F*CovPar*F')), - where F is functions matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -IMPORTANT: errors in parameters are calculated without taking into - account boundary/linear constraints! Presence of constraints - changes distribution of errors, but there is no easy way to - account for constraints when you calculate covariance matrix. - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 07.09.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitlinearwc(/* Real */ ae_vector* y, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* fmatrix, - /* Real */ ae_matrix* cmatrix, - ae_int_t n, - ae_int_t m, - ae_int_t k, - ae_int_t* info, - /* Real */ ae_vector* c, - lsfitreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _y; - ae_matrix _cmatrix; - ae_int_t i; - ae_int_t j; - ae_vector tau; - ae_matrix q; - ae_matrix f2; - ae_vector tmp; - ae_vector c0; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&_y, 0, sizeof(_y)); - memset(&_cmatrix, 0, sizeof(_cmatrix)); - memset(&tau, 0, sizeof(tau)); - memset(&q, 0, sizeof(q)); - memset(&f2, 0, sizeof(f2)); - memset(&tmp, 0, sizeof(tmp)); - memset(&c0, 0, sizeof(c0)); - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - ae_matrix_init_copy(&_cmatrix, cmatrix, _state, ae_true); - cmatrix = &_cmatrix; - *info = 0; - ae_vector_clear(c); - _lsfitreport_clear(rep); - ae_vector_init(&tau, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&f2, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c0, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=1, "LSFitLinearWC: N<1!", _state); - ae_assert(m>=1, "LSFitLinearWC: M<1!", _state); - ae_assert(k>=0, "LSFitLinearWC: K<0!", _state); - ae_assert(y->cnt>=n, "LSFitLinearWC: length(Y)cnt>=n, "LSFitLinearWC: length(W)rows>=n, "LSFitLinearWC: rows(FMatrix)cols>=m, "LSFitLinearWC: cols(FMatrix)rows>=k, "LSFitLinearWC: rows(CMatrix)cols>=m+1||k==0, "LSFitLinearWC: cols(CMatrix)=m ) - { - *info = -3; - ae_frame_leave(_state); - return; - } - - /* - * Solve - */ - if( k==0 ) - { - - /* - * no constraints - */ - lsfit_lsfitlinearinternal(y, w, fmatrix, n, m, info, c, rep, _state); - } - else - { - - /* - * First, find general form solution of constraints system: - * * factorize C = L*Q - * * unpack Q - * * fill upper part of C with zeros (for RCond) - * - * We got C=C0+Q2'*y where Q2 is lower M-K rows of Q. - */ - rmatrixlq(cmatrix, k, m, &tau, _state); - rmatrixlqunpackq(cmatrix, k, m, &tau, m, &q, _state); - for(i=0; i<=k-1; i++) - { - for(j=i+1; j<=m-1; j++) - { - cmatrix->ptr.pp_double[i][j] = 0.0; - } - } - if( ae_fp_less(rmatrixlurcondinf(cmatrix, k, _state),1000*ae_machineepsilon) ) - { - *info = -3; - ae_frame_leave(_state); - return; - } - ae_vector_set_length(&tmp, k, _state); - for(i=0; i<=k-1; i++) - { - if( i>0 ) - { - v = ae_v_dotproduct(&cmatrix->ptr.pp_double[i][0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,i-1)); - } - else - { - v = (double)(0); - } - tmp.ptr.p_double[i] = (cmatrix->ptr.pp_double[i][m]-v)/cmatrix->ptr.pp_double[i][i]; - } - ae_vector_set_length(&c0, m, _state); - for(i=0; i<=m-1; i++) - { - c0.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=k-1; i++) - { - v = tmp.ptr.p_double[i]; - ae_v_addd(&c0.ptr.p_double[0], 1, &q.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v); - } - - /* - * Second, prepare modified matrix F2 = F*Q2' and solve modified task - */ - ae_vector_set_length(&tmp, ae_maxint(n, m, _state)+1, _state); - ae_matrix_set_length(&f2, n, m-k, _state); - matrixvectormultiply(fmatrix, 0, n-1, 0, m-1, ae_false, &c0, 0, m-1, -1.0, y, 0, n-1, 1.0, _state); - rmatrixgemm(n, m-k, m, 1.0, fmatrix, 0, 0, 0, &q, k, 0, 1, 0.0, &f2, 0, 0, _state); - lsfit_lsfitlinearinternal(y, w, &f2, n, m-k, info, &tmp, rep, _state); - rep->taskrcond = (double)(-1); - if( *info<=0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * then, convert back to original answer: C = C0 + Q2'*Y0 - */ - ae_vector_set_length(c, m, _state); - ae_v_move(&c->ptr.p_double[0], 1, &c0.ptr.p_double[0], 1, ae_v_len(0,m-1)); - matrixvectormultiply(&q, k, m-1, 0, m-1, ae_true, &tmp, 0, m-k-1, 1.0, c, 0, m-1, 1.0, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Linear least squares fitting. - -QR decomposition is used to reduce task to MxM, then triangular solver or -SVD-based solver is used depending on condition number of the system. It -allows to maximize speed and retain decent accuracy. - -IMPORTANT: if you want to perform polynomial fitting, it may be more - convenient to use PolynomialFit() function. This function gives - best results on polynomial problems and solves numerical - stability issues which arise when you fit high-degree - polynomials to your data. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Y - array[0..N-1] Function values in N points. - FMatrix - a table of basis functions values, array[0..N-1, 0..M-1]. - FMatrix[I, J] - value of J-th basis function in I-th point. - N - number of points used. N>=1. - M - number of basis functions, M>=1. - -OUTPUT PARAMETERS: - Info - error code: - * -4 internal SVD decomposition subroutine failed (very - rare and for degenerate systems only) - * 1 task is solved - C - decomposition coefficients, array[0..M-1] - Rep - fitting report. Following fields are set: - * Rep.TaskRCond reciprocal of condition number - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(F*CovPar*F')), - where F is functions matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitlinear(/* Real */ ae_vector* y, - /* Real */ ae_matrix* fmatrix, - ae_int_t n, - ae_int_t m, - ae_int_t* info, - /* Real */ ae_vector* c, - lsfitreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector w; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&w, 0, sizeof(w)); - *info = 0; - ae_vector_clear(c); - _lsfitreport_clear(rep); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=1, "LSFitLinear: N<1!", _state); - ae_assert(m>=1, "LSFitLinear: M<1!", _state); - ae_assert(y->cnt>=n, "LSFitLinear: length(Y)rows>=n, "LSFitLinear: rows(FMatrix)cols>=m, "LSFitLinear: cols(FMatrix)=1. - M - number of basis functions, M>=1. - K - number of constraints, 0 <= K < M - K=0 corresponds to absence of constraints. - -OUTPUT PARAMETERS: - Info - error code: - * -4 internal SVD decomposition subroutine failed (very - rare and for degenerate systems only) - * -3 either too many constraints (M or more), - degenerate constraints (some constraints are - repetead twice) or inconsistent constraints were - specified. - * 1 task is solved - C - decomposition coefficients, array[0..M-1] - Rep - fitting report. Following fields are set: - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(F*CovPar*F')), - where F is functions matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -IMPORTANT: errors in parameters are calculated without taking into - account boundary/linear constraints! Presence of constraints - changes distribution of errors, but there is no easy way to - account for constraints when you calculate covariance matrix. - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 07.09.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitlinearc(/* Real */ ae_vector* y, - /* Real */ ae_matrix* fmatrix, - /* Real */ ae_matrix* cmatrix, - ae_int_t n, - ae_int_t m, - ae_int_t k, - ae_int_t* info, - /* Real */ ae_vector* c, - lsfitreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _y; - ae_vector w; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&_y, 0, sizeof(_y)); - memset(&w, 0, sizeof(w)); - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - *info = 0; - ae_vector_clear(c); - _lsfitreport_clear(rep); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=1, "LSFitLinearC: N<1!", _state); - ae_assert(m>=1, "LSFitLinearC: M<1!", _state); - ae_assert(k>=0, "LSFitLinearC: K<0!", _state); - ae_assert(y->cnt>=n, "LSFitLinearC: length(Y)rows>=n, "LSFitLinearC: rows(FMatrix)cols>=m, "LSFitLinearC: cols(FMatrix)rows>=k, "LSFitLinearC: rows(CMatrix)cols>=m+1||k==0, "LSFitLinearC: cols(CMatrix)1 - M - dimension of space - K - number of parameters being fitted - DiffStep- numerical differentiation step; - should not be very small or large; - large = loss of accuracy - small = growth of round-off errors - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 18.10.2008 by Bochkanov Sergey -*************************************************************************/ -void lsfitcreatewf(/* Real */ ae_matrix* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - /* Real */ ae_vector* c, - ae_int_t n, - ae_int_t m, - ae_int_t k, - double diffstep, - lsfitstate* state, - ae_state *_state) -{ - ae_int_t i; - - _lsfitstate_clear(state); - - ae_assert(n>=1, "LSFitCreateWF: N<1!", _state); - ae_assert(m>=1, "LSFitCreateWF: M<1!", _state); - ae_assert(k>=1, "LSFitCreateWF: K<1!", _state); - ae_assert(c->cnt>=k, "LSFitCreateWF: length(C)cnt>=n, "LSFitCreateWF: length(Y)cnt>=n, "LSFitCreateWF: length(W)rows>=n, "LSFitCreateWF: rows(X)cols>=m, "LSFitCreateWF: cols(X)teststep = (double)(0); - state->diffstep = diffstep; - state->npoints = n; - state->nweights = n; - state->wkind = 1; - state->m = m; - state->k = k; - lsfitsetcond(state, 0.0, 0, _state); - lsfitsetstpmax(state, 0.0, _state); - lsfitsetxrep(state, ae_false, _state); - ae_matrix_set_length(&state->taskx, n, m, _state); - ae_vector_set_length(&state->tasky, n, _state); - ae_vector_set_length(&state->taskw, n, _state); - ae_vector_set_length(&state->c, k, _state); - ae_vector_set_length(&state->c0, k, _state); - ae_vector_set_length(&state->c1, k, _state); - ae_v_move(&state->c0.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1)); - ae_v_move(&state->c1.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1)); - ae_vector_set_length(&state->x, m, _state); - ae_v_move(&state->taskw.ptr.p_double[0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - ae_v_move(&state->taskx.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m-1)); - state->tasky.ptr.p_double[i] = y->ptr.p_double[i]; - } - ae_vector_set_length(&state->s, k, _state); - ae_vector_set_length(&state->bndl, k, _state); - ae_vector_set_length(&state->bndu, k, _state); - for(i=0; i<=k-1; i++) - { - state->s.ptr.p_double[i] = 1.0; - state->bndl.ptr.p_double[i] = _state->v_neginf; - state->bndu.ptr.p_double[i] = _state->v_posinf; - } - state->optalgo = 0; - state->prevnpt = -1; - state->prevalgo = -1; - state->nec = 0; - state->nic = 0; - minlmcreatev(k, n, &state->c0, diffstep, &state->optstate, _state); - lsfit_lsfitclearrequestfields(state, _state); - ae_vector_set_length(&state->rstate.ia, 6+1, _state); - ae_vector_set_length(&state->rstate.ra, 8+1, _state); - state->rstate.stage = -1; -} - - -/************************************************************************* -Nonlinear least squares fitting using function values only. - -Combination of numerical differentiation and secant updates is used to -obtain function Jacobian. - -Nonlinear task min(F(c)) is solved, where - - F(c) = (f(c,x[0])-y[0])^2 + ... + (f(c,x[n-1])-y[n-1])^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * w is an N-dimensional vector of weight coefficients, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses only f(c,x[i]). - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - DiffStep- numerical differentiation step; - should not be very small or large; - large = loss of accuracy - small = growth of round-off errors - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 18.10.2008 by Bochkanov Sergey -*************************************************************************/ -void lsfitcreatef(/* Real */ ae_matrix* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* c, - ae_int_t n, - ae_int_t m, - ae_int_t k, - double diffstep, - lsfitstate* state, - ae_state *_state) -{ - ae_int_t i; - - _lsfitstate_clear(state); - - ae_assert(n>=1, "LSFitCreateF: N<1!", _state); - ae_assert(m>=1, "LSFitCreateF: M<1!", _state); - ae_assert(k>=1, "LSFitCreateF: K<1!", _state); - ae_assert(c->cnt>=k, "LSFitCreateF: length(C)cnt>=n, "LSFitCreateF: length(Y)rows>=n, "LSFitCreateF: rows(X)cols>=m, "LSFitCreateF: cols(X)rows>=n, "LSFitCreateF: rows(X)cols>=m, "LSFitCreateF: cols(X)teststep = (double)(0); - state->diffstep = diffstep; - state->npoints = n; - state->wkind = 0; - state->m = m; - state->k = k; - lsfitsetcond(state, 0.0, 0, _state); - lsfitsetstpmax(state, 0.0, _state); - lsfitsetxrep(state, ae_false, _state); - ae_matrix_set_length(&state->taskx, n, m, _state); - ae_vector_set_length(&state->tasky, n, _state); - ae_vector_set_length(&state->c, k, _state); - ae_vector_set_length(&state->c0, k, _state); - ae_vector_set_length(&state->c1, k, _state); - ae_v_move(&state->c0.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1)); - ae_v_move(&state->c1.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1)); - ae_vector_set_length(&state->x, m, _state); - for(i=0; i<=n-1; i++) - { - ae_v_move(&state->taskx.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m-1)); - state->tasky.ptr.p_double[i] = y->ptr.p_double[i]; - } - ae_vector_set_length(&state->s, k, _state); - ae_vector_set_length(&state->bndl, k, _state); - ae_vector_set_length(&state->bndu, k, _state); - for(i=0; i<=k-1; i++) - { - state->s.ptr.p_double[i] = 1.0; - state->bndl.ptr.p_double[i] = _state->v_neginf; - state->bndu.ptr.p_double[i] = _state->v_posinf; - } - state->optalgo = 0; - state->prevnpt = -1; - state->prevalgo = -1; - state->nec = 0; - state->nic = 0; - minlmcreatev(k, n, &state->c0, diffstep, &state->optstate, _state); - lsfit_lsfitclearrequestfields(state, _state); - ae_vector_set_length(&state->rstate.ia, 6+1, _state); - ae_vector_set_length(&state->rstate.ra, 8+1, _state); - state->rstate.stage = -1; -} - - -/************************************************************************* -Weighted nonlinear least squares fitting using gradient only. - -Nonlinear task min(F(c)) is solved, where - - F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * w is an N-dimensional vector of weight coefficients, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses only f(c,x[i]) and its gradient. - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - W - weights, array[0..N-1] - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - CheapFG - boolean flag, which is: - * True if both function and gradient calculation complexity - are less than O(M^2). An improved algorithm can - be used which corresponds to FGJ scheme from - MINLM unit. - * False otherwise. - Standard Jacibian-bases Levenberg-Marquardt algo - will be used (FJ scheme). - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -See also: - LSFitResults - LSFitCreateFG (fitting without weights) - LSFitCreateWFGH (fitting using Hessian) - LSFitCreateFGH (fitting using Hessian, without weights) - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitcreatewfg(/* Real */ ae_matrix* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - /* Real */ ae_vector* c, - ae_int_t n, - ae_int_t m, - ae_int_t k, - ae_bool cheapfg, - lsfitstate* state, - ae_state *_state) -{ - ae_int_t i; - - _lsfitstate_clear(state); - - ae_assert(n>=1, "LSFitCreateWFG: N<1!", _state); - ae_assert(m>=1, "LSFitCreateWFG: M<1!", _state); - ae_assert(k>=1, "LSFitCreateWFG: K<1!", _state); - ae_assert(c->cnt>=k, "LSFitCreateWFG: length(C)cnt>=n, "LSFitCreateWFG: length(Y)cnt>=n, "LSFitCreateWFG: length(W)rows>=n, "LSFitCreateWFG: rows(X)cols>=m, "LSFitCreateWFG: cols(X)teststep = (double)(0); - state->diffstep = (double)(0); - state->npoints = n; - state->nweights = n; - state->wkind = 1; - state->m = m; - state->k = k; - lsfitsetcond(state, 0.0, 0, _state); - lsfitsetstpmax(state, 0.0, _state); - lsfitsetxrep(state, ae_false, _state); - ae_matrix_set_length(&state->taskx, n, m, _state); - ae_vector_set_length(&state->tasky, n, _state); - ae_vector_set_length(&state->taskw, n, _state); - ae_vector_set_length(&state->c, k, _state); - ae_vector_set_length(&state->c0, k, _state); - ae_vector_set_length(&state->c1, k, _state); - ae_v_move(&state->c0.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1)); - ae_v_move(&state->c1.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1)); - ae_vector_set_length(&state->x, m, _state); - ae_vector_set_length(&state->g, k, _state); - ae_v_move(&state->taskw.ptr.p_double[0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - ae_v_move(&state->taskx.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m-1)); - state->tasky.ptr.p_double[i] = y->ptr.p_double[i]; - } - ae_vector_set_length(&state->s, k, _state); - ae_vector_set_length(&state->bndl, k, _state); - ae_vector_set_length(&state->bndu, k, _state); - for(i=0; i<=k-1; i++) - { - state->s.ptr.p_double[i] = 1.0; - state->bndl.ptr.p_double[i] = _state->v_neginf; - state->bndu.ptr.p_double[i] = _state->v_posinf; - } - state->optalgo = 1; - state->prevnpt = -1; - state->prevalgo = -1; - state->nec = 0; - state->nic = 0; - if( cheapfg ) - { - minlmcreatevgj(k, n, &state->c0, &state->optstate, _state); - } - else - { - minlmcreatevj(k, n, &state->c0, &state->optstate, _state); - } - lsfit_lsfitclearrequestfields(state, _state); - ae_vector_set_length(&state->rstate.ia, 6+1, _state); - ae_vector_set_length(&state->rstate.ra, 8+1, _state); - state->rstate.stage = -1; -} - - -/************************************************************************* -Nonlinear least squares fitting using gradient only, without individual -weights. - -Nonlinear task min(F(c)) is solved, where - - F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses only f(c,x[i]) and its gradient. - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - CheapFG - boolean flag, which is: - * True if both function and gradient calculation complexity - are less than O(M^2). An improved algorithm can - be used which corresponds to FGJ scheme from - MINLM unit. - * False otherwise. - Standard Jacibian-bases Levenberg-Marquardt algo - will be used (FJ scheme). - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitcreatefg(/* Real */ ae_matrix* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* c, - ae_int_t n, - ae_int_t m, - ae_int_t k, - ae_bool cheapfg, - lsfitstate* state, - ae_state *_state) -{ - ae_int_t i; - - _lsfitstate_clear(state); - - ae_assert(n>=1, "LSFitCreateFG: N<1!", _state); - ae_assert(m>=1, "LSFitCreateFG: M<1!", _state); - ae_assert(k>=1, "LSFitCreateFG: K<1!", _state); - ae_assert(c->cnt>=k, "LSFitCreateFG: length(C)cnt>=n, "LSFitCreateFG: length(Y)rows>=n, "LSFitCreateFG: rows(X)cols>=m, "LSFitCreateFG: cols(X)rows>=n, "LSFitCreateFG: rows(X)cols>=m, "LSFitCreateFG: cols(X)teststep = (double)(0); - state->diffstep = (double)(0); - state->npoints = n; - state->wkind = 0; - state->m = m; - state->k = k; - lsfitsetcond(state, 0.0, 0, _state); - lsfitsetstpmax(state, 0.0, _state); - lsfitsetxrep(state, ae_false, _state); - ae_matrix_set_length(&state->taskx, n, m, _state); - ae_vector_set_length(&state->tasky, n, _state); - ae_vector_set_length(&state->c, k, _state); - ae_vector_set_length(&state->c0, k, _state); - ae_vector_set_length(&state->c1, k, _state); - ae_v_move(&state->c0.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1)); - ae_v_move(&state->c1.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1)); - ae_vector_set_length(&state->x, m, _state); - ae_vector_set_length(&state->g, k, _state); - for(i=0; i<=n-1; i++) - { - ae_v_move(&state->taskx.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m-1)); - state->tasky.ptr.p_double[i] = y->ptr.p_double[i]; - } - ae_vector_set_length(&state->s, k, _state); - ae_vector_set_length(&state->bndl, k, _state); - ae_vector_set_length(&state->bndu, k, _state); - for(i=0; i<=k-1; i++) - { - state->s.ptr.p_double[i] = 1.0; - state->bndl.ptr.p_double[i] = _state->v_neginf; - state->bndu.ptr.p_double[i] = _state->v_posinf; - } - state->optalgo = 1; - state->prevnpt = -1; - state->prevalgo = -1; - state->nec = 0; - state->nic = 0; - if( cheapfg ) - { - minlmcreatevgj(k, n, &state->c0, &state->optstate, _state); - } - else - { - minlmcreatevj(k, n, &state->c0, &state->optstate, _state); - } - lsfit_lsfitclearrequestfields(state, _state); - ae_vector_set_length(&state->rstate.ia, 6+1, _state); - ae_vector_set_length(&state->rstate.ra, 8+1, _state); - state->rstate.stage = -1; -} - - -/************************************************************************* -Weighted nonlinear least squares fitting using gradient/Hessian. - -Nonlinear task min(F(c)) is solved, where - - F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * w is an N-dimensional vector of weight coefficients, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses f(c,x[i]), its gradient and its Hessian. - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - W - weights, array[0..N-1] - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitcreatewfgh(/* Real */ ae_matrix* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - /* Real */ ae_vector* c, - ae_int_t n, - ae_int_t m, - ae_int_t k, - lsfitstate* state, - ae_state *_state) -{ - ae_int_t i; - - _lsfitstate_clear(state); - - ae_assert(n>=1, "LSFitCreateWFGH: N<1!", _state); - ae_assert(m>=1, "LSFitCreateWFGH: M<1!", _state); - ae_assert(k>=1, "LSFitCreateWFGH: K<1!", _state); - ae_assert(c->cnt>=k, "LSFitCreateWFGH: length(C)cnt>=n, "LSFitCreateWFGH: length(Y)cnt>=n, "LSFitCreateWFGH: length(W)rows>=n, "LSFitCreateWFGH: rows(X)cols>=m, "LSFitCreateWFGH: cols(X)teststep = (double)(0); - state->diffstep = (double)(0); - state->npoints = n; - state->nweights = n; - state->wkind = 1; - state->m = m; - state->k = k; - lsfitsetcond(state, 0.0, 0, _state); - lsfitsetstpmax(state, 0.0, _state); - lsfitsetxrep(state, ae_false, _state); - ae_matrix_set_length(&state->taskx, n, m, _state); - ae_vector_set_length(&state->tasky, n, _state); - ae_vector_set_length(&state->taskw, n, _state); - ae_vector_set_length(&state->c, k, _state); - ae_vector_set_length(&state->c0, k, _state); - ae_vector_set_length(&state->c1, k, _state); - ae_v_move(&state->c0.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1)); - ae_v_move(&state->c1.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1)); - ae_matrix_set_length(&state->h, k, k, _state); - ae_vector_set_length(&state->x, m, _state); - ae_vector_set_length(&state->g, k, _state); - ae_v_move(&state->taskw.ptr.p_double[0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - ae_v_move(&state->taskx.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m-1)); - state->tasky.ptr.p_double[i] = y->ptr.p_double[i]; - } - ae_vector_set_length(&state->s, k, _state); - ae_vector_set_length(&state->bndl, k, _state); - ae_vector_set_length(&state->bndu, k, _state); - for(i=0; i<=k-1; i++) - { - state->s.ptr.p_double[i] = 1.0; - state->bndl.ptr.p_double[i] = _state->v_neginf; - state->bndu.ptr.p_double[i] = _state->v_posinf; - } - state->optalgo = 2; - state->prevnpt = -1; - state->prevalgo = -1; - state->nec = 0; - state->nic = 0; - minlmcreatefgh(k, &state->c0, &state->optstate, _state); - lsfit_lsfitclearrequestfields(state, _state); - ae_vector_set_length(&state->rstate.ia, 6+1, _state); - ae_vector_set_length(&state->rstate.ra, 8+1, _state); - state->rstate.stage = -1; -} - - -/************************************************************************* -Nonlinear least squares fitting using gradient/Hessian, without individial -weights. - -Nonlinear task min(F(c)) is solved, where - - F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses f(c,x[i]), its gradient and its Hessian. - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitcreatefgh(/* Real */ ae_matrix* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* c, - ae_int_t n, - ae_int_t m, - ae_int_t k, - lsfitstate* state, - ae_state *_state) -{ - ae_int_t i; - - _lsfitstate_clear(state); - - ae_assert(n>=1, "LSFitCreateFGH: N<1!", _state); - ae_assert(m>=1, "LSFitCreateFGH: M<1!", _state); - ae_assert(k>=1, "LSFitCreateFGH: K<1!", _state); - ae_assert(c->cnt>=k, "LSFitCreateFGH: length(C)cnt>=n, "LSFitCreateFGH: length(Y)rows>=n, "LSFitCreateFGH: rows(X)cols>=m, "LSFitCreateFGH: cols(X)teststep = (double)(0); - state->diffstep = (double)(0); - state->npoints = n; - state->wkind = 0; - state->m = m; - state->k = k; - lsfitsetcond(state, 0.0, 0, _state); - lsfitsetstpmax(state, 0.0, _state); - lsfitsetxrep(state, ae_false, _state); - ae_matrix_set_length(&state->taskx, n, m, _state); - ae_vector_set_length(&state->tasky, n, _state); - ae_vector_set_length(&state->c, k, _state); - ae_vector_set_length(&state->c0, k, _state); - ae_vector_set_length(&state->c1, k, _state); - ae_v_move(&state->c0.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1)); - ae_v_move(&state->c1.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1)); - ae_matrix_set_length(&state->h, k, k, _state); - ae_vector_set_length(&state->x, m, _state); - ae_vector_set_length(&state->g, k, _state); - for(i=0; i<=n-1; i++) - { - ae_v_move(&state->taskx.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m-1)); - state->tasky.ptr.p_double[i] = y->ptr.p_double[i]; - } - ae_vector_set_length(&state->s, k, _state); - ae_vector_set_length(&state->bndl, k, _state); - ae_vector_set_length(&state->bndu, k, _state); - for(i=0; i<=k-1; i++) - { - state->s.ptr.p_double[i] = 1.0; - state->bndl.ptr.p_double[i] = _state->v_neginf; - state->bndu.ptr.p_double[i] = _state->v_posinf; - } - state->optalgo = 2; - state->prevnpt = -1; - state->prevalgo = -1; - state->nec = 0; - state->nic = 0; - minlmcreatefgh(k, &state->c0, &state->optstate, _state); - lsfit_lsfitclearrequestfields(state, _state); - ae_vector_set_length(&state->rstate.ia, 6+1, _state); - ae_vector_set_length(&state->rstate.ra, 8+1, _state); - state->rstate.stage = -1; -} - - -/************************************************************************* -Stopping conditions for nonlinear least squares fitting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - ste pvector, dx=X(k+1)-X(k) - * s - scaling coefficients set by LSFitSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. Only Levenberg-Marquardt - iterations are counted (L-BFGS/CG iterations are NOT - counted because their cost is very low compared to that of - LM). - -NOTE - -Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic -stopping criterion selection (according to the scheme used by MINLM unit). - - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetcond(lsfitstate* state, - double epsx, - ae_int_t maxits, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(epsx, _state), "LSFitSetCond: EpsX is not finite!", _state); - ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "LSFitSetCond: negative EpsX!", _state); - ae_assert(maxits>=0, "LSFitSetCond: negative MaxIts!", _state); - state->epsx = epsx; - state->maxits = maxits; -} - - -/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which leads to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - -NOTE: non-zero StpMax leads to moderate performance degradation because -intermediate step of preconditioned L-BFGS optimization is incompatible -with limits on step size. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetstpmax(lsfitstate* state, double stpmax, ae_state *_state) -{ - - - ae_assert(ae_fp_greater_eq(stpmax,(double)(0)), "LSFitSetStpMax: StpMax<0!", _state); - state->stpmax = stpmax; -} - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -When reports are needed, State.C (current parameters) and State.F (current -value of fitting function) are reported. - - - -- ALGLIB -- - Copyright 15.08.2010 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetxrep(lsfitstate* state, ae_bool needxrep, ae_state *_state) -{ - - - state->xrep = needxrep; -} - - -/************************************************************************* -This function sets scaling coefficients for underlying optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Generally, scale is NOT considered to be a form of preconditioner. But LM -optimizer is unique in that it uses scaling matrix both in the stopping -condition tests and as Marquardt damping factor. - -Proper scaling is very important for the algorithm performance. It is less -important for the quality of results, but still has some influence (it is -easier to converge when variables are properly scaled, so premature -stopping is possible when very badly scalled variables are combined with -relaxed stopping conditions). - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetscale(lsfitstate* state, - /* Real */ ae_vector* s, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(s->cnt>=state->k, "LSFitSetScale: Length(S)k-1; i++) - { - ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "LSFitSetScale: S contains infinite or NAN elements", _state); - ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "LSFitSetScale: S contains infinite or NAN elements", _state); - state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state); - } -} - - -/************************************************************************* -This function sets boundary constraints for underlying optimizer - -Boundary constraints are inactive by default (after initial creation). -They are preserved until explicitly turned off with another SetBC() call. - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[K]. - If some (all) variables are unbounded, you may specify - very small number or -INF (latter is recommended because - it will allow solver to use better algorithm). - BndU - upper bounds, array[K]. - If some (all) variables are unbounded, you may specify - very large number or +INF (latter is recommended because - it will allow solver to use better algorithm). - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - -NOTE 2: unlike other constrained optimization algorithms, this solver has -following useful properties: -* bound constraints are always satisfied exactly -* function is evaluated only INSIDE area specified by bound constraints - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetbc(lsfitstate* state, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - - - k = state->k; - ae_assert(bndl->cnt>=k, "LSFitSetBC: Length(BndL)cnt>=k, "LSFitSetBC: Length(BndU)ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "LSFitSetBC: BndL contains NAN or +INF", _state); - ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "LSFitSetBC: BndU contains NAN or -INF", _state); - if( ae_isfinite(bndl->ptr.p_double[i], _state)&&ae_isfinite(bndu->ptr.p_double[i], _state) ) - { - ae_assert(ae_fp_less_eq(bndl->ptr.p_double[i],bndu->ptr.p_double[i]), "LSFitSetBC: BndL[i]>BndU[i]", _state); - } - state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i]; - state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i]; - } -} - - -/************************************************************************* -This function sets linear constraints for underlying optimizer - -Linear constraints are inactive by default (after initial creation). -They are preserved until explicitly turned off with another SetLC() call. - -INPUT PARAMETERS: - State - structure stores algorithm state - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -IMPORTANT: if you have linear constraints, it is strongly recommended to - set scale of variables with lsfitsetscale(). QP solver which is - used to calculate linearly constrained steps heavily relies on - good scaling of input problems. - -NOTE: linear (non-box) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations. - -NOTE: general linear constraints add significant overhead to solution - process. Although solver performs roughly same amount of iterations - (when compared with similar box-only constrained problem), each - iteration now involves solution of linearly constrained QP - subproblem, which requires ~3-5 times more Cholesky decompositions. - Thus, if you can reformulate your problem in such way this it has - only box constraints, it may be beneficial to do so. - - -- ALGLIB -- - Copyright 29.04.2017 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetlc(lsfitstate* state, - /* Real */ ae_matrix* c, - /* Integer */ ae_vector* ct, - ae_int_t k, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - - - n = state->k; - - /* - * First, check for errors in the inputs - */ - ae_assert(k>=0, "LSFitSetLC: K<0", _state); - ae_assert(c->cols>=n+1||k==0, "LSFitSetLC: Cols(C)rows>=k, "LSFitSetLC: Rows(C)cnt>=k, "LSFitSetLC: Length(CT)nec = 0; - state->nic = 0; - return; - } - - /* - * Equality constraints are stored first, in the upper - * NEC rows of State.CLEIC matrix. Inequality constraints - * are stored in the next NIC rows. - * - * NOTE: we convert inequality constraints to the form - * A*x<=b before copying them. - */ - rmatrixsetlengthatleast(&state->cleic, k, n+1, _state); - state->nec = 0; - state->nic = 0; - for(i=0; i<=k-1; i++) - { - if( ct->ptr.p_int[i]==0 ) - { - ae_v_move(&state->cleic.ptr.pp_double[state->nec][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n)); - state->nec = state->nec+1; - } - } - for(i=0; i<=k-1; i++) - { - if( ct->ptr.p_int[i]!=0 ) - { - if( ct->ptr.p_int[i]>0 ) - { - ae_v_moveneg(&state->cleic.ptr.pp_double[state->nec+state->nic][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n)); - } - else - { - ae_v_move(&state->cleic.ptr.pp_double[state->nec+state->nic][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n)); - } - state->nic = state->nic+1; - } - } -} - - -/************************************************************************* -NOTES: - -1. this algorithm is somewhat unusual because it works with parameterized - function f(C,X), where X is a function argument (we have many points - which are characterized by different argument values), and C is a - parameter to fit. - - For example, if we want to do linear fit by f(c0,c1,x) = c0*x+c1, then - x will be argument, and {c0,c1} will be parameters. - - It is important to understand that this algorithm finds minimum in the - space of function PARAMETERS (not arguments), so it needs derivatives - of f() with respect to C, not X. - - In the example above it will need f=c0*x+c1 and {df/dc0,df/dc1} = {x,1} - instead of {df/dx} = {c0}. - -2. Callback functions accept C as the first parameter, and X as the second - -3. If state was created with LSFitCreateFG(), algorithm needs just - function and its gradient, but if state was created with - LSFitCreateFGH(), algorithm will need function, gradient and Hessian. - - According to the said above, there ase several versions of this - function, which accept different sets of callbacks. - - This flexibility opens way to subtle errors - you may create state with - LSFitCreateFGH() (optimization using Hessian), but call function which - does not accept Hessian. So when algorithm will request Hessian, there - will be no callback to call. In this case exception will be thrown. - - Be careful to avoid such errors because there is no way to find them at - compile time - you can see them at runtime only. - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -ae_bool lsfititeration(lsfitstate* state, ae_state *_state) -{ - double lx; - double lf; - double ld; - double rx; - double rf; - double rd; - ae_int_t n; - ae_int_t m; - ae_int_t k; - double v; - double vv; - double relcnt; - ae_int_t i; - ae_int_t j; - ae_int_t j1; - ae_int_t info; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - n = state->rstate.ia.ptr.p_int[0]; - m = state->rstate.ia.ptr.p_int[1]; - k = state->rstate.ia.ptr.p_int[2]; - i = state->rstate.ia.ptr.p_int[3]; - j = state->rstate.ia.ptr.p_int[4]; - j1 = state->rstate.ia.ptr.p_int[5]; - info = state->rstate.ia.ptr.p_int[6]; - lx = state->rstate.ra.ptr.p_double[0]; - lf = state->rstate.ra.ptr.p_double[1]; - ld = state->rstate.ra.ptr.p_double[2]; - rx = state->rstate.ra.ptr.p_double[3]; - rf = state->rstate.ra.ptr.p_double[4]; - rd = state->rstate.ra.ptr.p_double[5]; - v = state->rstate.ra.ptr.p_double[6]; - vv = state->rstate.ra.ptr.p_double[7]; - relcnt = state->rstate.ra.ptr.p_double[8]; - } - else - { - n = 359; - m = -58; - k = -919; - i = -909; - j = 81; - j1 = 255; - info = 74; - lx = -788; - lf = 809; - ld = 205; - rx = -838; - rf = 939; - rd = -526; - v = 763; - vv = -541; - relcnt = -698; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - if( state->rstate.stage==1 ) - { - goto lbl_1; - } - if( state->rstate.stage==2 ) - { - goto lbl_2; - } - if( state->rstate.stage==3 ) - { - goto lbl_3; - } - if( state->rstate.stage==4 ) - { - goto lbl_4; - } - if( state->rstate.stage==5 ) - { - goto lbl_5; - } - if( state->rstate.stage==6 ) - { - goto lbl_6; - } - if( state->rstate.stage==7 ) - { - goto lbl_7; - } - if( state->rstate.stage==8 ) - { - goto lbl_8; - } - if( state->rstate.stage==9 ) - { - goto lbl_9; - } - if( state->rstate.stage==10 ) - { - goto lbl_10; - } - if( state->rstate.stage==11 ) - { - goto lbl_11; - } - if( state->rstate.stage==12 ) - { - goto lbl_12; - } - if( state->rstate.stage==13 ) - { - goto lbl_13; - } - - /* - * Routine body - */ - - /* - * Init - */ - if( state->wkind==1 ) - { - ae_assert(state->npoints==state->nweights, "LSFitFit: number of points is not equal to the number of weights", _state); - } - state->repvaridx = -1; - n = state->npoints; - m = state->m; - k = state->k; - ivectorsetlengthatleast(&state->tmpct, state->nec+state->nic, _state); - for(i=0; i<=state->nec-1; i++) - { - state->tmpct.ptr.p_int[i] = 0; - } - for(i=0; i<=state->nic-1; i++) - { - state->tmpct.ptr.p_int[state->nec+i] = -1; - } - minlmsetcond(&state->optstate, state->epsx, state->maxits, _state); - minlmsetstpmax(&state->optstate, state->stpmax, _state); - minlmsetxrep(&state->optstate, state->xrep, _state); - minlmsetscale(&state->optstate, &state->s, _state); - minlmsetbc(&state->optstate, &state->bndl, &state->bndu, _state); - minlmsetlc(&state->optstate, &state->cleic, &state->tmpct, state->nec+state->nic, _state); - - /* - * Check that user-supplied gradient is correct - */ - lsfit_lsfitclearrequestfields(state, _state); - if( !(ae_fp_greater(state->teststep,(double)(0))&&state->optalgo==1) ) - { - goto lbl_14; - } - for(i=0; i<=k-1; i++) - { - state->c.ptr.p_double[i] = state->c0.ptr.p_double[i]; - if( ae_isfinite(state->bndl.ptr.p_double[i], _state) ) - { - state->c.ptr.p_double[i] = ae_maxreal(state->c.ptr.p_double[i], state->bndl.ptr.p_double[i], _state); - } - if( ae_isfinite(state->bndu.ptr.p_double[i], _state) ) - { - state->c.ptr.p_double[i] = ae_minreal(state->c.ptr.p_double[i], state->bndu.ptr.p_double[i], _state); - } - } - state->needfg = ae_true; - i = 0; -lbl_16: - if( i>k-1 ) - { - goto lbl_18; - } - ae_assert(ae_fp_less_eq(state->bndl.ptr.p_double[i],state->c.ptr.p_double[i])&&ae_fp_less_eq(state->c.ptr.p_double[i],state->bndu.ptr.p_double[i]), "LSFitIteration: internal error(State.C is out of bounds)", _state); - v = state->c.ptr.p_double[i]; - j = 0; -lbl_19: - if( j>n-1 ) - { - goto lbl_21; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[j][0], 1, ae_v_len(0,m-1)); - state->c.ptr.p_double[i] = v-state->teststep*state->s.ptr.p_double[i]; - if( ae_isfinite(state->bndl.ptr.p_double[i], _state) ) - { - state->c.ptr.p_double[i] = ae_maxreal(state->c.ptr.p_double[i], state->bndl.ptr.p_double[i], _state); - } - lx = state->c.ptr.p_double[i]; - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - lf = state->f; - ld = state->g.ptr.p_double[i]; - state->c.ptr.p_double[i] = v+state->teststep*state->s.ptr.p_double[i]; - if( ae_isfinite(state->bndu.ptr.p_double[i], _state) ) - { - state->c.ptr.p_double[i] = ae_minreal(state->c.ptr.p_double[i], state->bndu.ptr.p_double[i], _state); - } - rx = state->c.ptr.p_double[i]; - state->rstate.stage = 1; - goto lbl_rcomm; -lbl_1: - rf = state->f; - rd = state->g.ptr.p_double[i]; - state->c.ptr.p_double[i] = (lx+rx)/2; - if( ae_isfinite(state->bndl.ptr.p_double[i], _state) ) - { - state->c.ptr.p_double[i] = ae_maxreal(state->c.ptr.p_double[i], state->bndl.ptr.p_double[i], _state); - } - if( ae_isfinite(state->bndu.ptr.p_double[i], _state) ) - { - state->c.ptr.p_double[i] = ae_minreal(state->c.ptr.p_double[i], state->bndu.ptr.p_double[i], _state); - } - state->rstate.stage = 2; - goto lbl_rcomm; -lbl_2: - state->c.ptr.p_double[i] = v; - if( !derivativecheck(lf, ld, rf, rd, state->f, state->g.ptr.p_double[i], rx-lx, _state) ) - { - state->repvaridx = i; - state->repterminationtype = -7; - result = ae_false; - return result; - } - j = j+1; - goto lbl_19; -lbl_21: - i = i+1; - goto lbl_16; -lbl_18: - state->needfg = ae_false; -lbl_14: - - /* - * Fill WCur by weights: - * * for WKind=0 unit weights are chosen - * * for WKind=1 we use user-supplied weights stored in State.TaskW - */ - rvectorsetlengthatleast(&state->wcur, n, _state); - for(i=0; i<=n-1; i++) - { - state->wcur.ptr.p_double[i] = 1.0; - if( state->wkind==1 ) - { - state->wcur.ptr.p_double[i] = state->taskw.ptr.p_double[i]; - } - } - - /* - * Optimize - */ -lbl_22: - if( !minlmiteration(&state->optstate, _state) ) - { - goto lbl_23; - } - if( !state->optstate.needfi ) - { - goto lbl_24; - } - - /* - * calculate f[] = wi*(f(xi,c)-yi) - */ - i = 0; -lbl_26: - if( i>n-1 ) - { - goto lbl_28; - } - ae_v_move(&state->c.ptr.p_double[0], 1, &state->optstate.x.ptr.p_double[0], 1, ae_v_len(0,k-1)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1)); - state->pointindex = i; - lsfit_lsfitclearrequestfields(state, _state); - state->needf = ae_true; - state->rstate.stage = 3; - goto lbl_rcomm; -lbl_3: - state->needf = ae_false; - vv = state->wcur.ptr.p_double[i]; - state->optstate.fi.ptr.p_double[i] = vv*(state->f-state->tasky.ptr.p_double[i]); - i = i+1; - goto lbl_26; -lbl_28: - goto lbl_22; -lbl_24: - if( !state->optstate.needf ) - { - goto lbl_29; - } - - /* - * calculate F = sum (wi*(f(xi,c)-yi))^2 - */ - state->optstate.f = (double)(0); - i = 0; -lbl_31: - if( i>n-1 ) - { - goto lbl_33; - } - ae_v_move(&state->c.ptr.p_double[0], 1, &state->optstate.x.ptr.p_double[0], 1, ae_v_len(0,k-1)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1)); - state->pointindex = i; - lsfit_lsfitclearrequestfields(state, _state); - state->needf = ae_true; - state->rstate.stage = 4; - goto lbl_rcomm; -lbl_4: - state->needf = ae_false; - vv = state->wcur.ptr.p_double[i]; - state->optstate.f = state->optstate.f+ae_sqr(vv*(state->f-state->tasky.ptr.p_double[i]), _state); - i = i+1; - goto lbl_31; -lbl_33: - goto lbl_22; -lbl_29: - if( !state->optstate.needfg ) - { - goto lbl_34; - } - - /* - * calculate F/gradF - */ - state->optstate.f = (double)(0); - for(i=0; i<=k-1; i++) - { - state->optstate.g.ptr.p_double[i] = (double)(0); - } - i = 0; -lbl_36: - if( i>n-1 ) - { - goto lbl_38; - } - ae_v_move(&state->c.ptr.p_double[0], 1, &state->optstate.x.ptr.p_double[0], 1, ae_v_len(0,k-1)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1)); - state->pointindex = i; - lsfit_lsfitclearrequestfields(state, _state); - state->needfg = ae_true; - state->rstate.stage = 5; - goto lbl_rcomm; -lbl_5: - state->needfg = ae_false; - vv = state->wcur.ptr.p_double[i]; - state->optstate.f = state->optstate.f+ae_sqr(vv*(state->f-state->tasky.ptr.p_double[i]), _state); - v = ae_sqr(vv, _state)*2*(state->f-state->tasky.ptr.p_double[i]); - ae_v_addd(&state->optstate.g.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,k-1), v); - i = i+1; - goto lbl_36; -lbl_38: - goto lbl_22; -lbl_34: - if( !state->optstate.needfij ) - { - goto lbl_39; - } - - /* - * calculate Fi/jac(Fi) - */ - i = 0; -lbl_41: - if( i>n-1 ) - { - goto lbl_43; - } - ae_v_move(&state->c.ptr.p_double[0], 1, &state->optstate.x.ptr.p_double[0], 1, ae_v_len(0,k-1)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1)); - state->pointindex = i; - lsfit_lsfitclearrequestfields(state, _state); - state->needfg = ae_true; - state->rstate.stage = 6; - goto lbl_rcomm; -lbl_6: - state->needfg = ae_false; - vv = state->wcur.ptr.p_double[i]; - state->optstate.fi.ptr.p_double[i] = vv*(state->f-state->tasky.ptr.p_double[i]); - ae_v_moved(&state->optstate.j.ptr.pp_double[i][0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,k-1), vv); - i = i+1; - goto lbl_41; -lbl_43: - goto lbl_22; -lbl_39: - if( !state->optstate.needfgh ) - { - goto lbl_44; - } - - /* - * calculate F/grad(F)/hess(F) - */ - state->optstate.f = (double)(0); - for(i=0; i<=k-1; i++) - { - state->optstate.g.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=k-1; i++) - { - for(j=0; j<=k-1; j++) - { - state->optstate.h.ptr.pp_double[i][j] = (double)(0); - } - } - i = 0; -lbl_46: - if( i>n-1 ) - { - goto lbl_48; - } - ae_v_move(&state->c.ptr.p_double[0], 1, &state->optstate.x.ptr.p_double[0], 1, ae_v_len(0,k-1)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1)); - state->pointindex = i; - lsfit_lsfitclearrequestfields(state, _state); - state->needfgh = ae_true; - state->rstate.stage = 7; - goto lbl_rcomm; -lbl_7: - state->needfgh = ae_false; - vv = state->wcur.ptr.p_double[i]; - state->optstate.f = state->optstate.f+ae_sqr(vv*(state->f-state->tasky.ptr.p_double[i]), _state); - v = ae_sqr(vv, _state)*2*(state->f-state->tasky.ptr.p_double[i]); - ae_v_addd(&state->optstate.g.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,k-1), v); - for(j=0; j<=k-1; j++) - { - v = 2*ae_sqr(vv, _state)*state->g.ptr.p_double[j]; - ae_v_addd(&state->optstate.h.ptr.pp_double[j][0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,k-1), v); - v = 2*ae_sqr(vv, _state)*(state->f-state->tasky.ptr.p_double[i]); - ae_v_addd(&state->optstate.h.ptr.pp_double[j][0], 1, &state->h.ptr.pp_double[j][0], 1, ae_v_len(0,k-1), v); - } - i = i+1; - goto lbl_46; -lbl_48: - goto lbl_22; -lbl_44: - if( !state->optstate.xupdated ) - { - goto lbl_49; - } - - /* - * Report new iteration - */ - ae_v_move(&state->c.ptr.p_double[0], 1, &state->optstate.x.ptr.p_double[0], 1, ae_v_len(0,k-1)); - state->f = state->optstate.f; - lsfit_lsfitclearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 8; - goto lbl_rcomm; -lbl_8: - state->xupdated = ae_false; - goto lbl_22; -lbl_49: - goto lbl_22; -lbl_23: - - /* - * Extract results - * - * NOTE: reverse communication protocol used by this unit does NOT - * allow us to reallocate State.C[] array. Thus, we extract - * results to the temporary variable in order to avoid possible - * reallocation. - */ - minlmresults(&state->optstate, &state->c1, &state->optrep, _state); - state->repterminationtype = state->optrep.terminationtype; - state->repiterationscount = state->optrep.iterationscount; - - /* - * calculate errors - */ - if( state->repterminationtype<=0 ) - { - goto lbl_51; - } - - /* - * Calculate RMS/Avg/Max/... errors - */ - state->reprmserror = (double)(0); - state->repwrmserror = (double)(0); - state->repavgerror = (double)(0); - state->repavgrelerror = (double)(0); - state->repmaxerror = (double)(0); - relcnt = (double)(0); - i = 0; -lbl_53: - if( i>n-1 ) - { - goto lbl_55; - } - ae_v_move(&state->c.ptr.p_double[0], 1, &state->c1.ptr.p_double[0], 1, ae_v_len(0,k-1)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1)); - state->pointindex = i; - lsfit_lsfitclearrequestfields(state, _state); - state->needf = ae_true; - state->rstate.stage = 9; - goto lbl_rcomm; -lbl_9: - state->needf = ae_false; - v = state->f; - vv = state->wcur.ptr.p_double[i]; - state->reprmserror = state->reprmserror+ae_sqr(v-state->tasky.ptr.p_double[i], _state); - state->repwrmserror = state->repwrmserror+ae_sqr(vv*(v-state->tasky.ptr.p_double[i]), _state); - state->repavgerror = state->repavgerror+ae_fabs(v-state->tasky.ptr.p_double[i], _state); - if( ae_fp_neq(state->tasky.ptr.p_double[i],(double)(0)) ) - { - state->repavgrelerror = state->repavgrelerror+ae_fabs(v-state->tasky.ptr.p_double[i], _state)/ae_fabs(state->tasky.ptr.p_double[i], _state); - relcnt = relcnt+1; - } - state->repmaxerror = ae_maxreal(state->repmaxerror, ae_fabs(v-state->tasky.ptr.p_double[i], _state), _state); - i = i+1; - goto lbl_53; -lbl_55: - state->reprmserror = ae_sqrt(state->reprmserror/n, _state); - state->repwrmserror = ae_sqrt(state->repwrmserror/n, _state); - state->repavgerror = state->repavgerror/n; - if( ae_fp_neq(relcnt,(double)(0)) ) - { - state->repavgrelerror = state->repavgrelerror/relcnt; - } - - /* - * Calculate covariance matrix - */ - rmatrixsetlengthatleast(&state->tmpjac, n, k, _state); - rvectorsetlengthatleast(&state->tmpf, n, _state); - rvectorsetlengthatleast(&state->tmp, k, _state); - if( ae_fp_less_eq(state->diffstep,(double)(0)) ) - { - goto lbl_56; - } - - /* - * Compute Jacobian by means of numerical differentiation - */ - lsfit_lsfitclearrequestfields(state, _state); - state->needf = ae_true; - i = 0; -lbl_58: - if( i>n-1 ) - { - goto lbl_60; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1)); - state->pointindex = i; - state->rstate.stage = 10; - goto lbl_rcomm; -lbl_10: - state->tmpf.ptr.p_double[i] = state->f; - j = 0; -lbl_61: - if( j>k-1 ) - { - goto lbl_63; - } - v = state->c.ptr.p_double[j]; - lx = v-state->diffstep*state->s.ptr.p_double[j]; - state->c.ptr.p_double[j] = lx; - if( ae_isfinite(state->bndl.ptr.p_double[j], _state) ) - { - state->c.ptr.p_double[j] = ae_maxreal(state->c.ptr.p_double[j], state->bndl.ptr.p_double[j], _state); - } - state->rstate.stage = 11; - goto lbl_rcomm; -lbl_11: - lf = state->f; - rx = v+state->diffstep*state->s.ptr.p_double[j]; - state->c.ptr.p_double[j] = rx; - if( ae_isfinite(state->bndu.ptr.p_double[j], _state) ) - { - state->c.ptr.p_double[j] = ae_minreal(state->c.ptr.p_double[j], state->bndu.ptr.p_double[j], _state); - } - state->rstate.stage = 12; - goto lbl_rcomm; -lbl_12: - rf = state->f; - state->c.ptr.p_double[j] = v; - if( ae_fp_neq(rx,lx) ) - { - state->tmpjac.ptr.pp_double[i][j] = (rf-lf)/(rx-lx); - } - else - { - state->tmpjac.ptr.pp_double[i][j] = (double)(0); - } - j = j+1; - goto lbl_61; -lbl_63: - i = i+1; - goto lbl_58; -lbl_60: - state->needf = ae_false; - goto lbl_57; -lbl_56: - - /* - * Jacobian is calculated with user-provided analytic gradient - */ - lsfit_lsfitclearrequestfields(state, _state); - state->needfg = ae_true; - i = 0; -lbl_64: - if( i>n-1 ) - { - goto lbl_66; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1)); - state->pointindex = i; - state->rstate.stage = 13; - goto lbl_rcomm; -lbl_13: - state->tmpf.ptr.p_double[i] = state->f; - for(j=0; j<=k-1; j++) - { - state->tmpjac.ptr.pp_double[i][j] = state->g.ptr.p_double[j]; - } - i = i+1; - goto lbl_64; -lbl_66: - state->needfg = ae_false; -lbl_57: - for(i=0; i<=k-1; i++) - { - state->tmp.ptr.p_double[i] = 0.0; - } - lsfit_estimateerrors(&state->tmpjac, &state->tmpf, &state->tasky, &state->wcur, &state->tmp, &state->s, n, k, &state->rep, &state->tmpjacw, 0, _state); -lbl_51: - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = n; - state->rstate.ia.ptr.p_int[1] = m; - state->rstate.ia.ptr.p_int[2] = k; - state->rstate.ia.ptr.p_int[3] = i; - state->rstate.ia.ptr.p_int[4] = j; - state->rstate.ia.ptr.p_int[5] = j1; - state->rstate.ia.ptr.p_int[6] = info; - state->rstate.ra.ptr.p_double[0] = lx; - state->rstate.ra.ptr.p_double[1] = lf; - state->rstate.ra.ptr.p_double[2] = ld; - state->rstate.ra.ptr.p_double[3] = rx; - state->rstate.ra.ptr.p_double[4] = rf; - state->rstate.ra.ptr.p_double[5] = rd; - state->rstate.ra.ptr.p_double[6] = v; - state->rstate.ra.ptr.p_double[7] = vv; - state->rstate.ra.ptr.p_double[8] = relcnt; - return result; -} - - -/************************************************************************* -Nonlinear least squares fitting results. - -Called after return from LSFitFit(). - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - Info - completion code: - * -8 optimizer detected NAN/INF in the target - function and/or gradient - * -7 gradient verification failed. - See LSFitSetGradientCheck() for more information. - * -3 inconsistent constraints - * 2 relative step is no more than EpsX. - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible - C - array[0..K-1], solution - Rep - optimization report. On success following fields are set: - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - * WRMSError weighted rms error on the (X,Y). - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(J*CovPar*J')), - where J is Jacobian matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -IMPORTANT: errors in parameters are calculated without taking into - account boundary/linear constraints! Presence of constraints - changes distribution of errors, but there is no easy way to - account for constraints when you calculate covariance matrix. - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitresults(lsfitstate* state, - ae_int_t* info, - /* Real */ ae_vector* c, - lsfitreport* rep, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - *info = 0; - ae_vector_clear(c); - _lsfitreport_clear(rep); - - lsfit_clearreport(rep, _state); - *info = state->repterminationtype; - rep->varidx = state->repvaridx; - if( *info>0 ) - { - ae_vector_set_length(c, state->k, _state); - ae_v_move(&c->ptr.p_double[0], 1, &state->c1.ptr.p_double[0], 1, ae_v_len(0,state->k-1)); - rep->rmserror = state->reprmserror; - rep->wrmserror = state->repwrmserror; - rep->avgerror = state->repavgerror; - rep->avgrelerror = state->repavgrelerror; - rep->maxerror = state->repmaxerror; - rep->iterationscount = state->repiterationscount; - ae_matrix_set_length(&rep->covpar, state->k, state->k, _state); - ae_vector_set_length(&rep->errpar, state->k, _state); - ae_vector_set_length(&rep->errcurve, state->npoints, _state); - ae_vector_set_length(&rep->noise, state->npoints, _state); - rep->r2 = state->rep.r2; - for(i=0; i<=state->k-1; i++) - { - for(j=0; j<=state->k-1; j++) - { - rep->covpar.ptr.pp_double[i][j] = state->rep.covpar.ptr.pp_double[i][j]; - } - rep->errpar.ptr.p_double[i] = state->rep.errpar.ptr.p_double[i]; - } - for(i=0; i<=state->npoints-1; i++) - { - rep->errcurve.ptr.p_double[i] = state->rep.errcurve.ptr.p_double[i]; - rep->noise.ptr.p_double[i] = state->rep.noise.ptr.p_double[i]; - } - } -} - - -/************************************************************************* -This subroutine turns on verification of the user-supplied analytic -gradient: -* user calls this subroutine before fitting begins -* LSFitFit() is called -* prior to actual fitting, for each point in data set X_i and each - component of parameters being fited C_j algorithm performs following - steps: - * two trial steps are made to C_j-TestStep*S[j] and C_j+TestStep*S[j], - where C_j is j-th parameter and S[j] is a scale of j-th parameter - * if needed, steps are bounded with respect to constraints on C[] - * F(X_i|C) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - * in case difference between prediction and actual value is higher than - some predetermined threshold, algorithm stops with completion code -7; - Rep.VarIdx is set to index of the parameter with incorrect derivative. -* after verification is over, algorithm proceeds to the actual optimization. - -NOTE 1: verification needs N*K (points count * parameters count) gradient - evaluations. It is very costly and you should use it only for low - dimensional problems, when you want to be sure that you've - correctly calculated analytic derivatives. You should not use it - in the production code (unless you want to check derivatives - provided by some third party). - -NOTE 2: you should carefully choose TestStep. Value which is too large - (so large that function behaviour is significantly non-cubic) will - lead to false alarms. You may use different step for different - parameters by means of setting scale with LSFitSetScale(). - -NOTE 3: this function may lead to false positives. In case it reports that - I-th derivative was calculated incorrectly, you may decrease test - step and try one more time - maybe your function changes too - sharply and your step is too large for such rapidly chanding - function. - -NOTE 4: this function works only for optimizers created with LSFitCreateWFG() - or LSFitCreateFG() constructors. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step: - * TestStep=0 turns verification off - * TestStep>0 activates verification - - -- ALGLIB -- - Copyright 15.06.2012 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetgradientcheck(lsfitstate* state, - double teststep, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(teststep, _state), "LSFitSetGradientCheck: TestStep contains NaN or Infinite", _state); - ae_assert(ae_fp_greater_eq(teststep,(double)(0)), "LSFitSetGradientCheck: invalid argument TestStep(TestStep<0)", _state); - state->teststep = teststep; -} - - -/************************************************************************* -This function analyzes section of curve for processing by RDP algorithm: -given set of points X,Y with indexes [I0,I1] it returns point with -worst deviation from linear model (non-parametric version which sees curve -as Y(x)). - -Input parameters: - X, Y - SORTED arrays. - I0,I1 - interval (boundaries included) to process - Eps - desired precision - -OUTPUT PARAMETERS: - WorstIdx - index of worst point - WorstError - error at worst point - -NOTE: this function guarantees that it returns exactly zero for a section - with less than 3 points. - - -- ALGLIB PROJECT -- - Copyright 02.10.2014 by Bochkanov Sergey -*************************************************************************/ -static void lsfit_rdpanalyzesection(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t i0, - ae_int_t i1, - ae_int_t* worstidx, - double* worsterror, - ae_state *_state) -{ - ae_int_t i; - double xleft; - double xright; - double vx; - double ve; - double a; - double b; - - *worstidx = 0; - *worsterror = 0; - - xleft = x->ptr.p_double[i0]; - xright = x->ptr.p_double[i1]; - if( i1-i0+1<3||ae_fp_eq(xright,xleft) ) - { - *worstidx = i0; - *worsterror = 0.0; - return; - } - a = (y->ptr.p_double[i1]-y->ptr.p_double[i0])/(xright-xleft); - b = (y->ptr.p_double[i0]*xright-y->ptr.p_double[i1]*xleft)/(xright-xleft); - *worstidx = -1; - *worsterror = (double)(0); - for(i=i0+1; i<=i1-1; i++) - { - vx = x->ptr.p_double[i]; - ve = ae_fabs(a*vx+b-y->ptr.p_double[i], _state); - if( (ae_fp_greater(vx,xleft)&&ae_fp_less(vx,xright))&&ae_fp_greater(ve,*worsterror) ) - { - *worsterror = ve; - *worstidx = i; - } - } -} - - -/************************************************************************* -Recursive splitting of interval [I0,I1] (right boundary included) with RDP -algorithm (non-parametric version which sees curve as Y(x)). - -Input parameters: - X, Y - SORTED arrays. - I0,I1 - interval (boundaries included) to process - Eps - desired precision - XOut,YOut - preallocated output arrays large enough to store result; - XOut[0..1], YOut[0..1] contain first and last points of - curve - NOut - must contain 2 on input - -OUTPUT PARAMETERS: - XOut, YOut - curve generated by RDP algorithm, UNSORTED - NOut - number of points in curve - - -- ALGLIB PROJECT -- - Copyright 02.10.2014 by Bochkanov Sergey -*************************************************************************/ -static void lsfit_rdprecursive(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t i0, - ae_int_t i1, - double eps, - /* Real */ ae_vector* xout, - /* Real */ ae_vector* yout, - ae_int_t* nout, - ae_state *_state) -{ - ae_int_t worstidx; - double worsterror; - - - ae_assert(ae_fp_greater(eps,(double)(0)), "RDPRecursive: internal error, Eps<0", _state); - lsfit_rdpanalyzesection(x, y, i0, i1, &worstidx, &worsterror, _state); - if( ae_fp_less_eq(worsterror,eps) ) - { - return; - } - xout->ptr.p_double[*nout] = x->ptr.p_double[worstidx]; - yout->ptr.p_double[*nout] = y->ptr.p_double[worstidx]; - *nout = *nout+1; - if( worstidx-i0x.ptr.p_double[0]; - tb = state->x.ptr.p_double[1]; - tc = state->x.ptr.p_double[2]; - td = state->x.ptr.p_double[3]; - tg = state->x.ptr.p_double[4]; - if( state->xupdated ) - { - - /* - * Save best function value obtained so far. - */ - *flast = state->f; - continue; - } - if( state->needfi||state->needfij ) - { - - /* - * Function vector and Jacobian - */ - for(i=0; i<=n-1; i++) - { - ae_assert(ae_fp_greater_eq(x->ptr.p_double[i],(double)(0)), "LogisticFitInternal: integrity error", _state); - - /* - * Handle zero X - */ - if( ae_fp_eq(x->ptr.p_double[i],(double)(0)) ) - { - if( ae_fp_greater_eq(tb,(double)(0)) ) - { - - /* - * Positive or zero TB, limit X^TB subject to X->+0 is equal to zero. - */ - state->fi.ptr.p_double[i] = ta-y->ptr.p_double[i]; - if( state->needfij ) - { - state->j.ptr.pp_double[i][0] = (double)(1); - state->j.ptr.pp_double[i][1] = (double)(0); - state->j.ptr.pp_double[i][2] = (double)(0); - state->j.ptr.pp_double[i][3] = (double)(0); - state->j.ptr.pp_double[i][4] = (double)(0); - } - } - else - { - - /* - * Negative TB, limit X^TB subject to X->+0 is equal to +INF. - */ - state->fi.ptr.p_double[i] = td-y->ptr.p_double[i]; - if( state->needfij ) - { - state->j.ptr.pp_double[i][0] = (double)(0); - state->j.ptr.pp_double[i][1] = (double)(0); - state->j.ptr.pp_double[i][2] = (double)(0); - state->j.ptr.pp_double[i][3] = (double)(1); - state->j.ptr.pp_double[i][4] = (double)(0); - } - } - continue; - } - - /* - * Positive X. - * Prepare VP0/VP1, it may become infinite or nearly overflow in some rare cases, - * handle these cases - */ - vp0 = ae_pow(x->ptr.p_double[i]/tc, tb, _state); - if( is4pl ) - { - vp1 = 1+vp0; - } - else - { - vp1 = ae_pow(1+vp0, tg, _state); - } - if( (!ae_isfinite(vp1, _state)||ae_fp_greater(vp0,1.0E50))||ae_fp_greater(vp1,1.0E50) ) - { - - /* - * VP0/VP1 are not finite, assume that it is +INF or -INF - */ - state->fi.ptr.p_double[i] = td-y->ptr.p_double[i]; - if( state->needfij ) - { - state->j.ptr.pp_double[i][0] = (double)(0); - state->j.ptr.pp_double[i][1] = (double)(0); - state->j.ptr.pp_double[i][2] = (double)(0); - state->j.ptr.pp_double[i][3] = (double)(1); - state->j.ptr.pp_double[i][4] = (double)(0); - } - continue; - } - - /* - * VP0/VP1 are finite, normal processing - */ - if( is4pl ) - { - state->fi.ptr.p_double[i] = td+(ta-td)/vp1-y->ptr.p_double[i]; - if( state->needfij ) - { - state->j.ptr.pp_double[i][0] = 1/vp1; - state->j.ptr.pp_double[i][1] = -(ta-td)*vp0*ae_log(x->ptr.p_double[i]/tc, _state)/ae_sqr(vp1, _state); - state->j.ptr.pp_double[i][2] = (ta-td)*(tb/tc)*vp0/ae_sqr(vp1, _state); - state->j.ptr.pp_double[i][3] = 1-1/vp1; - state->j.ptr.pp_double[i][4] = (double)(0); - } - } - else - { - state->fi.ptr.p_double[i] = td+(ta-td)/vp1-y->ptr.p_double[i]; - if( state->needfij ) - { - state->j.ptr.pp_double[i][0] = 1/vp1; - state->j.ptr.pp_double[i][1] = (ta-td)*(-tg)*ae_pow(1+vp0, -tg-1, _state)*vp0*ae_log(x->ptr.p_double[i]/tc, _state); - state->j.ptr.pp_double[i][2] = (ta-td)*(-tg)*ae_pow(1+vp0, -tg-1, _state)*vp0*(-tb/tc); - state->j.ptr.pp_double[i][3] = 1-1/vp1; - state->j.ptr.pp_double[i][4] = -(ta-td)/vp1*ae_log(1+vp0, _state); - } - } - } - - /* - * Add regularizer - */ - for(i=0; i<=4; i++) - { - state->fi.ptr.p_double[n+i] = lambdav*state->x.ptr.p_double[i]; - if( state->needfij ) - { - for(j=0; j<=4; j++) - { - state->j.ptr.pp_double[n+i][j] = 0.0; - } - state->j.ptr.pp_double[n+i][i] = lambdav; - } - } - - /* - * Done - */ - continue; - } - ae_assert(ae_false, "LogisticFitX: internal error", _state); - } - minlmresultsbuf(state, p1, replm, _state); - ae_assert(replm->terminationtype>0, "LogisticFitX: internal error", _state); -} - - -/************************************************************************* -Calculate errors for 4PL/5PL fit. -Leaves other fields of Rep unchanged, so caller should properly initialize -it with ClearRep() call. - - -- ALGLIB PROJECT -- - Copyright 28.04.2017 by Bochkanov Sergey -*************************************************************************/ -static void lsfit_logisticfit45errors(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - double a, - double b, - double c, - double d, - double g, - lsfitreport* rep, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - double v; - double rss; - double tss; - double meany; - - - - /* - * Calculate errors - */ - rep->rmserror = (double)(0); - rep->avgerror = (double)(0); - rep->avgrelerror = (double)(0); - rep->maxerror = (double)(0); - k = 0; - rss = 0.0; - tss = 0.0; - meany = 0.0; - for(i=0; i<=n-1; i++) - { - meany = meany+y->ptr.p_double[i]; - } - meany = meany/n; - for(i=0; i<=n-1; i++) - { - - /* - * Calculate residual from regression - */ - if( ae_fp_greater(x->ptr.p_double[i],(double)(0)) ) - { - v = d+(a-d)/ae_pow(1.0+ae_pow(x->ptr.p_double[i]/c, b, _state), g, _state)-y->ptr.p_double[i]; - } - else - { - if( ae_fp_greater_eq(b,(double)(0)) ) - { - v = a-y->ptr.p_double[i]; - } - else - { - v = d-y->ptr.p_double[i]; - } - } - - /* - * Update RSS (residual sum of squares) and TSS (total sum of squares) - * which are used to calculate coefficient of determination. - * - * NOTE: we use formula R2 = 1-RSS/TSS because it has nice property of - * being equal to 0.0 if and only if model perfectly fits data. - * - * When we fit nonlinear models, there are exist multiple ways of - * determining R2, each of them giving different results. Formula - * above is the most intuitive one. - */ - rss = rss+v*v; - tss = tss+ae_sqr(y->ptr.p_double[i]-meany, _state); - - /* - * Update errors - */ - rep->rmserror = rep->rmserror+ae_sqr(v, _state); - rep->avgerror = rep->avgerror+ae_fabs(v, _state); - if( ae_fp_neq(y->ptr.p_double[i],(double)(0)) ) - { - rep->avgrelerror = rep->avgrelerror+ae_fabs(v/y->ptr.p_double[i], _state); - k = k+1; - } - rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(v, _state), _state); - } - rep->rmserror = ae_sqrt(rep->rmserror/n, _state); - rep->avgerror = rep->avgerror/n; - if( k>0 ) - { - rep->avgrelerror = rep->avgrelerror/k; - } - rep->r2 = 1.0-rss/tss; -} - - -/************************************************************************* -Internal spline fitting subroutine - - -- ALGLIB PROJECT -- - Copyright 08.09.2009 by Bochkanov Sergey -*************************************************************************/ -static void lsfit_spline1dfitinternal(ae_int_t st, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_int_t n, - /* Real */ ae_vector* xc, - /* Real */ ae_vector* yc, - /* Integer */ ae_vector* dc, - ae_int_t k, - ae_int_t m, - ae_int_t* info, - spline1dinterpolant* s, - spline1dfitreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - ae_vector _w; - ae_vector _xc; - ae_vector _yc; - ae_matrix fmatrix; - ae_matrix cmatrix; - ae_vector y2; - ae_vector w2; - ae_vector sx; - ae_vector sy; - ae_vector sd; - ae_vector tmp; - ae_vector xoriginal; - ae_vector yoriginal; - lsfitreport lrep; - double v0; - double v1; - double v2; - double mx; - spline1dinterpolant s2; - ae_int_t i; - ae_int_t j; - ae_int_t relcnt; - double xa; - double xb; - double sa; - double sb; - double bl; - double br; - double decay; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - memset(&_w, 0, sizeof(_w)); - memset(&_xc, 0, sizeof(_xc)); - memset(&_yc, 0, sizeof(_yc)); - memset(&fmatrix, 0, sizeof(fmatrix)); - memset(&cmatrix, 0, sizeof(cmatrix)); - memset(&y2, 0, sizeof(y2)); - memset(&w2, 0, sizeof(w2)); - memset(&sx, 0, sizeof(sx)); - memset(&sy, 0, sizeof(sy)); - memset(&sd, 0, sizeof(sd)); - memset(&tmp, 0, sizeof(tmp)); - memset(&xoriginal, 0, sizeof(xoriginal)); - memset(&yoriginal, 0, sizeof(yoriginal)); - memset(&lrep, 0, sizeof(lrep)); - memset(&s2, 0, sizeof(s2)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - ae_vector_init_copy(&_w, w, _state, ae_true); - w = &_w; - ae_vector_init_copy(&_xc, xc, _state, ae_true); - xc = &_xc; - ae_vector_init_copy(&_yc, yc, _state, ae_true); - yc = &_yc; - *info = 0; - _spline1dinterpolant_clear(s); - _spline1dfitreport_clear(rep); - ae_matrix_init(&fmatrix, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&cmatrix, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sy, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sd, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xoriginal, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yoriginal, 0, DT_REAL, _state, ae_true); - _lsfitreport_init(&lrep, _state, ae_true); - _spline1dinterpolant_init(&s2, _state, ae_true); - - ae_assert(st==0||st==1, "Spline1DFit: internal error!", _state); - if( st==0&&m<4 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - if( st==1&&m<4 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - if( (n<1||k<0)||k>=m ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - for(i=0; i<=k-1; i++) - { - *info = 0; - if( dc->ptr.p_int[i]<0 ) - { - *info = -1; - } - if( dc->ptr.p_int[i]>1 ) - { - *info = -1; - } - if( *info<0 ) - { - ae_frame_leave(_state); - return; - } - } - if( st==1&&m%2!=0 ) - { - - /* - * Hermite fitter must have even number of basis functions - */ - *info = -2; - ae_frame_leave(_state); - return; - } - - /* - * weight decay for correct handling of task which becomes - * degenerate after constraints are applied - */ - decay = 10000*ae_machineepsilon; - - /* - * Scale X, Y, XC, YC - */ - lsfitscalexy(x, y, w, n, xc, yc, dc, k, &xa, &xb, &sa, &sb, &xoriginal, &yoriginal, _state); - - /* - * allocate space, initialize: - * * SX - grid for basis functions - * * SY - values of basis functions at grid points - * * FMatrix- values of basis functions at X[] - * * CMatrix- values (derivatives) of basis functions at XC[] - */ - ae_vector_set_length(&y2, n+m, _state); - ae_vector_set_length(&w2, n+m, _state); - ae_matrix_set_length(&fmatrix, n+m, m, _state); - if( k>0 ) - { - ae_matrix_set_length(&cmatrix, k, m+1, _state); - } - if( st==0 ) - { - - /* - * allocate space for cubic spline - */ - ae_vector_set_length(&sx, m-2, _state); - ae_vector_set_length(&sy, m-2, _state); - for(j=0; j<=m-2-1; j++) - { - sx.ptr.p_double[j] = (double)(2*j)/(double)(m-2-1)-1; - } - } - if( st==1 ) - { - - /* - * allocate space for Hermite spline - */ - ae_vector_set_length(&sx, m/2, _state); - ae_vector_set_length(&sy, m/2, _state); - ae_vector_set_length(&sd, m/2, _state); - for(j=0; j<=m/2-1; j++) - { - sx.ptr.p_double[j] = (double)(2*j)/(double)(m/2-1)-1; - } - } - - /* - * Prepare design and constraints matrices: - * * fill constraints matrix - * * fill first N rows of design matrix with values - * * fill next M rows of design matrix with regularizing term - * * append M zeros to Y - * * append M elements, mean(abs(W)) each, to W - */ - for(j=0; j<=m-1; j++) - { - - /* - * prepare Jth basis function - */ - if( st==0 ) - { - - /* - * cubic spline basis - */ - for(i=0; i<=m-2-1; i++) - { - sy.ptr.p_double[i] = (double)(0); - } - bl = (double)(0); - br = (double)(0); - if( jptr.p_double[i], _state); - } - for(i=0; i<=k-1; i++) - { - ae_assert(dc->ptr.p_int[i]>=0&&dc->ptr.p_int[i]<=2, "Spline1DFit: internal error!", _state); - spline1ddiff(&s2, xc->ptr.p_double[i], &v0, &v1, &v2, _state); - if( dc->ptr.p_int[i]==0 ) - { - cmatrix.ptr.pp_double[i][j] = v0; - } - if( dc->ptr.p_int[i]==1 ) - { - cmatrix.ptr.pp_double[i][j] = v1; - } - if( dc->ptr.p_int[i]==2 ) - { - cmatrix.ptr.pp_double[i][j] = v2; - } - } - } - for(i=0; i<=k-1; i++) - { - cmatrix.ptr.pp_double[i][m] = yc->ptr.p_double[i]; - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - if( i==j ) - { - fmatrix.ptr.pp_double[n+i][j] = decay; - } - else - { - fmatrix.ptr.pp_double[n+i][j] = (double)(0); - } - } - } - ae_vector_set_length(&y2, n+m, _state); - ae_vector_set_length(&w2, n+m, _state); - ae_v_move(&y2.ptr.p_double[0], 1, &y->ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&w2.ptr.p_double[0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,n-1)); - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - mx = mx+ae_fabs(w->ptr.p_double[i], _state); - } - mx = mx/n; - for(i=0; i<=m-1; i++) - { - y2.ptr.p_double[n+i] = (double)(0); - w2.ptr.p_double[n+i] = mx; - } - - /* - * Solve constrained task - */ - if( k>0 ) - { - - /* - * solve using regularization - */ - lsfitlinearwc(&y2, &w2, &fmatrix, &cmatrix, n+m, m, k, info, &tmp, &lrep, _state); - } - else - { - - /* - * no constraints, no regularization needed - */ - lsfitlinearwc(y, w, &fmatrix, &cmatrix, n, m, k, info, &tmp, &lrep, _state); - } - if( *info<0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Generate spline and scale it - */ - if( st==0 ) - { - - /* - * cubic spline basis - */ - ae_v_move(&sy.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,m-2-1)); - spline1dbuildcubic(&sx, &sy, m-2, 1, tmp.ptr.p_double[m-2], 1, tmp.ptr.p_double[m-1], s, _state); - } - if( st==1 ) - { - - /* - * Hermite basis - */ - for(i=0; i<=m/2-1; i++) - { - sy.ptr.p_double[i] = tmp.ptr.p_double[2*i]; - sd.ptr.p_double[i] = tmp.ptr.p_double[2*i+1]; - } - spline1dbuildhermite(&sx, &sy, &sd, m/2, s, _state); - } - spline1dlintransx(s, 2/(xb-xa), -(xa+xb)/(xb-xa), _state); - spline1dlintransy(s, sb-sa, sa, _state); - - /* - * Scale absolute errors obtained from LSFitLinearW. - * Relative error should be calculated separately - * (because of shifting/scaling of the task) - */ - rep->taskrcond = lrep.taskrcond; - rep->rmserror = lrep.rmserror*(sb-sa); - rep->avgerror = lrep.avgerror*(sb-sa); - rep->maxerror = lrep.maxerror*(sb-sa); - rep->avgrelerror = (double)(0); - relcnt = 0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_neq(yoriginal.ptr.p_double[i],(double)(0)) ) - { - rep->avgrelerror = rep->avgrelerror+ae_fabs(spline1dcalc(s, xoriginal.ptr.p_double[i], _state)-yoriginal.ptr.p_double[i], _state)/ae_fabs(yoriginal.ptr.p_double[i], _state); - relcnt = relcnt+1; - } - } - if( relcnt!=0 ) - { - rep->avgrelerror = rep->avgrelerror/relcnt; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal fitting subroutine -*************************************************************************/ -static void lsfit_lsfitlinearinternal(/* Real */ ae_vector* y, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* fmatrix, - ae_int_t n, - ae_int_t m, - ae_int_t* info, - /* Real */ ae_vector* c, - lsfitreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - double threshold; - ae_matrix ft; - ae_matrix q; - ae_matrix l; - ae_matrix r; - ae_vector b; - ae_vector wmod; - ae_vector tau; - ae_vector nzeros; - ae_vector s; - ae_int_t i; - ae_int_t j; - double v; - ae_vector sv; - ae_matrix u; - ae_matrix vt; - ae_vector tmp; - ae_vector utb; - ae_vector sutb; - ae_int_t relcnt; - - ae_frame_make(_state, &_frame_block); - memset(&ft, 0, sizeof(ft)); - memset(&q, 0, sizeof(q)); - memset(&l, 0, sizeof(l)); - memset(&r, 0, sizeof(r)); - memset(&b, 0, sizeof(b)); - memset(&wmod, 0, sizeof(wmod)); - memset(&tau, 0, sizeof(tau)); - memset(&nzeros, 0, sizeof(nzeros)); - memset(&s, 0, sizeof(s)); - memset(&sv, 0, sizeof(sv)); - memset(&u, 0, sizeof(u)); - memset(&vt, 0, sizeof(vt)); - memset(&tmp, 0, sizeof(tmp)); - memset(&utb, 0, sizeof(utb)); - memset(&sutb, 0, sizeof(sutb)); - *info = 0; - ae_vector_clear(c); - _lsfitreport_clear(rep); - ae_matrix_init(&ft, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&l, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&r, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wmod, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tau, 0, DT_REAL, _state, ae_true); - ae_vector_init(&nzeros, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sv, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vt, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&utb, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sutb, 0, DT_REAL, _state, ae_true); - - lsfit_clearreport(rep, _state); - if( n<1||m<1 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - *info = 1; - threshold = ae_sqrt(ae_machineepsilon, _state); - - /* - * Degenerate case, needs special handling - */ - if( nptr.p_double[j]; - ae_v_moved(&ft.ptr.pp_double[j][0], 1, &fmatrix->ptr.pp_double[j][0], 1, ae_v_len(0,m-1), v); - b.ptr.p_double[j] = w->ptr.p_double[j]*y->ptr.p_double[j]; - wmod.ptr.p_double[j] = (double)(1); - } - - /* - * LQ decomposition and reduction to M=N - */ - ae_vector_set_length(c, m, _state); - for(i=0; i<=m-1; i++) - { - c->ptr.p_double[i] = (double)(0); - } - rep->taskrcond = (double)(0); - rmatrixlq(&ft, n, m, &tau, _state); - rmatrixlqunpackq(&ft, n, m, &tau, n, &q, _state); - rmatrixlqunpackl(&ft, n, m, &l, _state); - lsfit_lsfitlinearinternal(&b, &wmod, &l, n, n, info, &tmp, rep, _state); - if( *info<=0 ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - v = tmp.ptr.p_double[i]; - ae_v_addd(&c->ptr.p_double[0], 1, &q.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v); - } - ae_frame_leave(_state); - return; - } - - /* - * N>=M. Generate design matrix and reduce to N=M using - * QR decomposition. - */ - ae_matrix_set_length(&ft, n, m, _state); - ae_vector_set_length(&b, n, _state); - for(j=0; j<=n-1; j++) - { - v = w->ptr.p_double[j]; - ae_v_moved(&ft.ptr.pp_double[j][0], 1, &fmatrix->ptr.pp_double[j][0], 1, ae_v_len(0,m-1), v); - b.ptr.p_double[j] = w->ptr.p_double[j]*y->ptr.p_double[j]; - } - rmatrixqr(&ft, n, m, &tau, _state); - rmatrixqrunpackq(&ft, n, m, &tau, m, &q, _state); - rmatrixqrunpackr(&ft, n, m, &r, _state); - ae_vector_set_length(&tmp, m, _state); - for(i=0; i<=m-1; i++) - { - tmp.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - v = b.ptr.p_double[i]; - ae_v_addd(&tmp.ptr.p_double[0], 1, &q.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v); - } - ae_vector_set_length(&b, m, _state); - ae_v_move(&b.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,m-1)); - - /* - * R contains reduced MxM design upper triangular matrix, - * B contains reduced Mx1 right part. - * - * Determine system condition number and decide - * should we use triangular solver (faster) or - * SVD-based solver (more stable). - * - * We can use LU-based RCond estimator for this task. - */ - rep->taskrcond = rmatrixlurcondinf(&r, m, _state); - if( ae_fp_greater(rep->taskrcond,threshold) ) - { - - /* - * use QR-based solver - */ - ae_vector_set_length(c, m, _state); - c->ptr.p_double[m-1] = b.ptr.p_double[m-1]/r.ptr.pp_double[m-1][m-1]; - for(i=m-2; i>=0; i--) - { - v = ae_v_dotproduct(&r.ptr.pp_double[i][i+1], 1, &c->ptr.p_double[i+1], 1, ae_v_len(i+1,m-1)); - c->ptr.p_double[i] = (b.ptr.p_double[i]-v)/r.ptr.pp_double[i][i]; - } - } - else - { - - /* - * use SVD-based solver - */ - if( !rmatrixsvd(&r, m, m, 1, 1, 2, &sv, &u, &vt, _state) ) - { - *info = -4; - ae_frame_leave(_state); - return; - } - ae_vector_set_length(&utb, m, _state); - ae_vector_set_length(&sutb, m, _state); - for(i=0; i<=m-1; i++) - { - utb.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=m-1; i++) - { - v = b.ptr.p_double[i]; - ae_v_addd(&utb.ptr.p_double[0], 1, &u.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v); - } - if( ae_fp_greater(sv.ptr.p_double[0],(double)(0)) ) - { - rep->taskrcond = sv.ptr.p_double[m-1]/sv.ptr.p_double[0]; - for(i=0; i<=m-1; i++) - { - if( ae_fp_greater(sv.ptr.p_double[i],threshold*sv.ptr.p_double[0]) ) - { - sutb.ptr.p_double[i] = utb.ptr.p_double[i]/sv.ptr.p_double[i]; - } - else - { - sutb.ptr.p_double[i] = (double)(0); - } - } - } - else - { - rep->taskrcond = (double)(0); - for(i=0; i<=m-1; i++) - { - sutb.ptr.p_double[i] = (double)(0); - } - } - ae_vector_set_length(c, m, _state); - for(i=0; i<=m-1; i++) - { - c->ptr.p_double[i] = (double)(0); - } - for(i=0; i<=m-1; i++) - { - v = sutb.ptr.p_double[i]; - ae_v_addd(&c->ptr.p_double[0], 1, &vt.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v); - } - } - - /* - * calculate errors - */ - rep->rmserror = (double)(0); - rep->avgerror = (double)(0); - rep->avgrelerror = (double)(0); - rep->maxerror = (double)(0); - relcnt = 0; - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&fmatrix->ptr.pp_double[i][0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,m-1)); - rep->rmserror = rep->rmserror+ae_sqr(v-y->ptr.p_double[i], _state); - rep->avgerror = rep->avgerror+ae_fabs(v-y->ptr.p_double[i], _state); - if( ae_fp_neq(y->ptr.p_double[i],(double)(0)) ) - { - rep->avgrelerror = rep->avgrelerror+ae_fabs(v-y->ptr.p_double[i], _state)/ae_fabs(y->ptr.p_double[i], _state); - relcnt = relcnt+1; - } - rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(v-y->ptr.p_double[i], _state), _state); - } - rep->rmserror = ae_sqrt(rep->rmserror/n, _state); - rep->avgerror = rep->avgerror/n; - if( relcnt!=0 ) - { - rep->avgrelerror = rep->avgrelerror/relcnt; - } - ae_vector_set_length(&nzeros, n, _state); - ae_vector_set_length(&s, m, _state); - for(i=0; i<=m-1; i++) - { - s.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - s.ptr.p_double[j] = s.ptr.p_double[j]+ae_sqr(fmatrix->ptr.pp_double[i][j], _state); - } - nzeros.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=m-1; i++) - { - if( ae_fp_neq(s.ptr.p_double[i],(double)(0)) ) - { - s.ptr.p_double[i] = ae_sqrt(1/s.ptr.p_double[i], _state); - } - else - { - s.ptr.p_double[i] = (double)(1); - } - } - lsfit_estimateerrors(fmatrix, &nzeros, y, w, c, &s, n, m, rep, &r, 1, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal subroutine -*************************************************************************/ -static void lsfit_lsfitclearrequestfields(lsfitstate* state, - ae_state *_state) -{ - - - state->needf = ae_false; - state->needfg = ae_false; - state->needfgh = ae_false; - state->xupdated = ae_false; -} - - -/************************************************************************* -Internal subroutine, calculates barycentric basis functions. -Used for efficient simultaneous calculation of N basis functions. - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -static void lsfit_barycentriccalcbasis(barycentricinterpolant* b, - double t, - /* Real */ ae_vector* y, - ae_state *_state) -{ - double s2; - double s; - double v; - ae_int_t i; - ae_int_t j; - - - - /* - * special case: N=1 - */ - if( b->n==1 ) - { - y->ptr.p_double[0] = (double)(1); - return; - } - - /* - * Here we assume that task is normalized, i.e.: - * 1. abs(Y[i])<=1 - * 2. abs(W[i])<=1 - * 3. X[] is ordered - * - * First, we decide: should we use "safe" formula (guarded - * against overflow) or fast one? - */ - s = ae_fabs(t-b->x.ptr.p_double[0], _state); - for(i=0; i<=b->n-1; i++) - { - v = b->x.ptr.p_double[i]; - if( ae_fp_eq(v,t) ) - { - for(j=0; j<=b->n-1; j++) - { - y->ptr.p_double[j] = (double)(0); - } - y->ptr.p_double[i] = (double)(1); - return; - } - v = ae_fabs(t-v, _state); - if( ae_fp_less(v,s) ) - { - s = v; - } - } - s2 = (double)(0); - for(i=0; i<=b->n-1; i++) - { - v = s/(t-b->x.ptr.p_double[i]); - v = v*b->w.ptr.p_double[i]; - y->ptr.p_double[i] = v; - s2 = s2+v; - } - v = 1/s2; - ae_v_muld(&y->ptr.p_double[0], 1, ae_v_len(0,b->n-1), v); -} - - -/************************************************************************* -This is internal function for Chebyshev fitting. - -It assumes that input data are normalized: -* X/XC belong to [-1,+1], -* mean(Y)=0, stddev(Y)=1. - -It does not checks inputs for errors. - -This function is used to fit general (shifted) Chebyshev models, power -basis models or barycentric models. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - W - weights, array[0..N-1] - N - number of points, N>0. - XC - points where polynomial values/derivatives are constrained, - array[0..K-1]. - YC - values of constraints, array[0..K-1] - DC - array[0..K-1], types of constraints: - * DC[i]=0 means that P(XC[i])=YC[i] - * DC[i]=1 means that P'(XC[i])=YC[i] - K - number of constraints, 0<=K=1 - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearW() subroutine: - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - C - interpolant in Chebyshev form; [-1,+1] is used as base interval - Rep - report, same format as in LSFitLinearW() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - - -- ALGLIB PROJECT -- - Copyright 10.12.2009 by Bochkanov Sergey -*************************************************************************/ -static void lsfit_internalchebyshevfit(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_int_t n, - /* Real */ ae_vector* xc, - /* Real */ ae_vector* yc, - /* Integer */ ae_vector* dc, - ae_int_t k, - ae_int_t m, - ae_int_t* info, - /* Real */ ae_vector* c, - lsfitreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _xc; - ae_vector _yc; - ae_vector y2; - ae_vector w2; - ae_vector tmp; - ae_vector tmp2; - ae_vector tmpdiff; - ae_vector bx; - ae_vector by; - ae_vector bw; - ae_matrix fmatrix; - ae_matrix cmatrix; - ae_int_t i; - ae_int_t j; - double mx; - double decay; - - ae_frame_make(_state, &_frame_block); - memset(&_xc, 0, sizeof(_xc)); - memset(&_yc, 0, sizeof(_yc)); - memset(&y2, 0, sizeof(y2)); - memset(&w2, 0, sizeof(w2)); - memset(&tmp, 0, sizeof(tmp)); - memset(&tmp2, 0, sizeof(tmp2)); - memset(&tmpdiff, 0, sizeof(tmpdiff)); - memset(&bx, 0, sizeof(bx)); - memset(&by, 0, sizeof(by)); - memset(&bw, 0, sizeof(bw)); - memset(&fmatrix, 0, sizeof(fmatrix)); - memset(&cmatrix, 0, sizeof(cmatrix)); - ae_vector_init_copy(&_xc, xc, _state, ae_true); - xc = &_xc; - ae_vector_init_copy(&_yc, yc, _state, ae_true); - yc = &_yc; - *info = 0; - ae_vector_clear(c); - _lsfitreport_clear(rep); - ae_vector_init(&y2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpdiff, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&by, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bw, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&fmatrix, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&cmatrix, 0, 0, DT_REAL, _state, ae_true); - - lsfit_clearreport(rep, _state); - - /* - * weight decay for correct handling of task which becomes - * degenerate after constraints are applied - */ - decay = 10000*ae_machineepsilon; - - /* - * allocate space, initialize/fill: - * * FMatrix- values of basis functions at X[] - * * CMatrix- values (derivatives) of basis functions at XC[] - * * fill constraints matrix - * * fill first N rows of design matrix with values - * * fill next M rows of design matrix with regularizing term - * * append M zeros to Y - * * append M elements, mean(abs(W)) each, to W - */ - ae_vector_set_length(&y2, n+m, _state); - ae_vector_set_length(&w2, n+m, _state); - ae_vector_set_length(&tmp, m, _state); - ae_vector_set_length(&tmpdiff, m, _state); - ae_matrix_set_length(&fmatrix, n+m, m, _state); - if( k>0 ) - { - ae_matrix_set_length(&cmatrix, k, m+1, _state); - } - - /* - * Fill design matrix, Y2, W2: - * * first N rows with basis functions for original points - * * next M rows with decay terms - */ - for(i=0; i<=n-1; i++) - { - - /* - * prepare Ith row - * use Tmp for calculations to avoid multidimensional arrays overhead - */ - for(j=0; j<=m-1; j++) - { - if( j==0 ) - { - tmp.ptr.p_double[j] = (double)(1); - } - else - { - if( j==1 ) - { - tmp.ptr.p_double[j] = x->ptr.p_double[i]; - } - else - { - tmp.ptr.p_double[j] = 2*x->ptr.p_double[i]*tmp.ptr.p_double[j-1]-tmp.ptr.p_double[j-2]; - } - } - } - ae_v_move(&fmatrix.ptr.pp_double[i][0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,m-1)); - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - if( i==j ) - { - fmatrix.ptr.pp_double[n+i][j] = decay; - } - else - { - fmatrix.ptr.pp_double[n+i][j] = (double)(0); - } - } - } - ae_v_move(&y2.ptr.p_double[0], 1, &y->ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&w2.ptr.p_double[0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,n-1)); - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - mx = mx+ae_fabs(w->ptr.p_double[i], _state); - } - mx = mx/n; - for(i=0; i<=m-1; i++) - { - y2.ptr.p_double[n+i] = (double)(0); - w2.ptr.p_double[n+i] = mx; - } - - /* - * fill constraints matrix - */ - for(i=0; i<=k-1; i++) - { - - /* - * prepare Ith row - * use Tmp for basis function values, - * TmpDiff for basos function derivatives - */ - for(j=0; j<=m-1; j++) - { - if( j==0 ) - { - tmp.ptr.p_double[j] = (double)(1); - tmpdiff.ptr.p_double[j] = (double)(0); - } - else - { - if( j==1 ) - { - tmp.ptr.p_double[j] = xc->ptr.p_double[i]; - tmpdiff.ptr.p_double[j] = (double)(1); - } - else - { - tmp.ptr.p_double[j] = 2*xc->ptr.p_double[i]*tmp.ptr.p_double[j-1]-tmp.ptr.p_double[j-2]; - tmpdiff.ptr.p_double[j] = 2*(tmp.ptr.p_double[j-1]+xc->ptr.p_double[i]*tmpdiff.ptr.p_double[j-1])-tmpdiff.ptr.p_double[j-2]; - } - } - } - if( dc->ptr.p_int[i]==0 ) - { - ae_v_move(&cmatrix.ptr.pp_double[i][0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,m-1)); - } - if( dc->ptr.p_int[i]==1 ) - { - ae_v_move(&cmatrix.ptr.pp_double[i][0], 1, &tmpdiff.ptr.p_double[0], 1, ae_v_len(0,m-1)); - } - cmatrix.ptr.pp_double[i][m] = yc->ptr.p_double[i]; - } - - /* - * Solve constrained task - */ - if( k>0 ) - { - - /* - * solve using regularization - */ - lsfitlinearwc(&y2, &w2, &fmatrix, &cmatrix, n+m, m, k, info, c, rep, _state); - } - else - { - - /* - * no constraints, no regularization needed - */ - lsfitlinearwc(y, w, &fmatrix, &cmatrix, n, m, 0, info, c, rep, _state); - } - if( *info<0 ) - { - ae_frame_leave(_state); - return; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal Floater-Hormann fitting subroutine for fixed D -*************************************************************************/ -static void lsfit_barycentricfitwcfixedd(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_int_t n, - /* Real */ ae_vector* xc, - /* Real */ ae_vector* yc, - /* Integer */ ae_vector* dc, - ae_int_t k, - ae_int_t m, - ae_int_t d, - ae_int_t* info, - barycentricinterpolant* b, - barycentricfitreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - ae_vector _w; - ae_vector _xc; - ae_vector _yc; - ae_matrix fmatrix; - ae_matrix cmatrix; - ae_vector y2; - ae_vector w2; - ae_vector sx; - ae_vector sy; - ae_vector sbf; - ae_vector xoriginal; - ae_vector yoriginal; - ae_vector tmp; - lsfitreport lrep; - double v0; - double v1; - double mx; - barycentricinterpolant b2; - ae_int_t i; - ae_int_t j; - ae_int_t relcnt; - double xa; - double xb; - double sa; - double sb; - double decay; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - memset(&_w, 0, sizeof(_w)); - memset(&_xc, 0, sizeof(_xc)); - memset(&_yc, 0, sizeof(_yc)); - memset(&fmatrix, 0, sizeof(fmatrix)); - memset(&cmatrix, 0, sizeof(cmatrix)); - memset(&y2, 0, sizeof(y2)); - memset(&w2, 0, sizeof(w2)); - memset(&sx, 0, sizeof(sx)); - memset(&sy, 0, sizeof(sy)); - memset(&sbf, 0, sizeof(sbf)); - memset(&xoriginal, 0, sizeof(xoriginal)); - memset(&yoriginal, 0, sizeof(yoriginal)); - memset(&tmp, 0, sizeof(tmp)); - memset(&lrep, 0, sizeof(lrep)); - memset(&b2, 0, sizeof(b2)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - ae_vector_init_copy(&_w, w, _state, ae_true); - w = &_w; - ae_vector_init_copy(&_xc, xc, _state, ae_true); - xc = &_xc; - ae_vector_init_copy(&_yc, yc, _state, ae_true); - yc = &_yc; - *info = 0; - _barycentricinterpolant_clear(b); - _barycentricfitreport_clear(rep); - ae_matrix_init(&fmatrix, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&cmatrix, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sy, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sbf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xoriginal, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yoriginal, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - _lsfitreport_init(&lrep, _state, ae_true); - _barycentricinterpolant_init(&b2, _state, ae_true); - - if( ((n<1||m<2)||k<0)||k>=m ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - for(i=0; i<=k-1; i++) - { - *info = 0; - if( dc->ptr.p_int[i]<0 ) - { - *info = -1; - } - if( dc->ptr.p_int[i]>1 ) - { - *info = -1; - } - if( *info<0 ) - { - ae_frame_leave(_state); - return; - } - } - - /* - * weight decay for correct handling of task which becomes - * degenerate after constraints are applied - */ - decay = 10000*ae_machineepsilon; - - /* - * Scale X, Y, XC, YC - */ - lsfitscalexy(x, y, w, n, xc, yc, dc, k, &xa, &xb, &sa, &sb, &xoriginal, &yoriginal, _state); - - /* - * allocate space, initialize: - * * FMatrix- values of basis functions at X[] - * * CMatrix- values (derivatives) of basis functions at XC[] - */ - ae_vector_set_length(&y2, n+m, _state); - ae_vector_set_length(&w2, n+m, _state); - ae_matrix_set_length(&fmatrix, n+m, m, _state); - if( k>0 ) - { - ae_matrix_set_length(&cmatrix, k, m+1, _state); - } - ae_vector_set_length(&y2, n+m, _state); - ae_vector_set_length(&w2, n+m, _state); - - /* - * Prepare design and constraints matrices: - * * fill constraints matrix - * * fill first N rows of design matrix with values - * * fill next M rows of design matrix with regularizing term - * * append M zeros to Y - * * append M elements, mean(abs(W)) each, to W - */ - ae_vector_set_length(&sx, m, _state); - ae_vector_set_length(&sy, m, _state); - ae_vector_set_length(&sbf, m, _state); - for(j=0; j<=m-1; j++) - { - sx.ptr.p_double[j] = (double)(2*j)/(double)(m-1)-1; - } - for(i=0; i<=m-1; i++) - { - sy.ptr.p_double[i] = (double)(1); - } - barycentricbuildfloaterhormann(&sx, &sy, m, d, &b2, _state); - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - lsfit_barycentriccalcbasis(&b2, x->ptr.p_double[i], &sbf, _state); - ae_v_move(&fmatrix.ptr.pp_double[i][0], 1, &sbf.ptr.p_double[0], 1, ae_v_len(0,m-1)); - y2.ptr.p_double[i] = y->ptr.p_double[i]; - w2.ptr.p_double[i] = w->ptr.p_double[i]; - mx = mx+ae_fabs(w->ptr.p_double[i], _state)/n; - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - if( i==j ) - { - fmatrix.ptr.pp_double[n+i][j] = decay; - } - else - { - fmatrix.ptr.pp_double[n+i][j] = (double)(0); - } - } - y2.ptr.p_double[n+i] = (double)(0); - w2.ptr.p_double[n+i] = mx; - } - if( k>0 ) - { - for(j=0; j<=m-1; j++) - { - for(i=0; i<=m-1; i++) - { - sy.ptr.p_double[i] = (double)(0); - } - sy.ptr.p_double[j] = (double)(1); - barycentricbuildfloaterhormann(&sx, &sy, m, d, &b2, _state); - for(i=0; i<=k-1; i++) - { - ae_assert(dc->ptr.p_int[i]>=0&&dc->ptr.p_int[i]<=1, "BarycentricFit: internal error!", _state); - barycentricdiff1(&b2, xc->ptr.p_double[i], &v0, &v1, _state); - if( dc->ptr.p_int[i]==0 ) - { - cmatrix.ptr.pp_double[i][j] = v0; - } - if( dc->ptr.p_int[i]==1 ) - { - cmatrix.ptr.pp_double[i][j] = v1; - } - } - } - for(i=0; i<=k-1; i++) - { - cmatrix.ptr.pp_double[i][m] = yc->ptr.p_double[i]; - } - } - - /* - * Solve constrained task - */ - if( k>0 ) - { - - /* - * solve using regularization - */ - lsfitlinearwc(&y2, &w2, &fmatrix, &cmatrix, n+m, m, k, info, &tmp, &lrep, _state); - } - else - { - - /* - * no constraints, no regularization needed - */ - lsfitlinearwc(y, w, &fmatrix, &cmatrix, n, m, k, info, &tmp, &lrep, _state); - } - if( *info<0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Generate interpolant and scale it - */ - ae_v_move(&sy.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,m-1)); - barycentricbuildfloaterhormann(&sx, &sy, m, d, b, _state); - barycentriclintransx(b, 2/(xb-xa), -(xa+xb)/(xb-xa), _state); - barycentriclintransy(b, sb-sa, sa, _state); - - /* - * Scale absolute errors obtained from LSFitLinearW. - * Relative error should be calculated separately - * (because of shifting/scaling of the task) - */ - rep->taskrcond = lrep.taskrcond; - rep->rmserror = lrep.rmserror*(sb-sa); - rep->avgerror = lrep.avgerror*(sb-sa); - rep->maxerror = lrep.maxerror*(sb-sa); - rep->avgrelerror = (double)(0); - relcnt = 0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_neq(yoriginal.ptr.p_double[i],(double)(0)) ) - { - rep->avgrelerror = rep->avgrelerror+ae_fabs(barycentriccalc(b, xoriginal.ptr.p_double[i], _state)-yoriginal.ptr.p_double[i], _state)/ae_fabs(yoriginal.ptr.p_double[i], _state); - relcnt = relcnt+1; - } - } - if( relcnt!=0 ) - { - rep->avgrelerror = rep->avgrelerror/relcnt; - } - ae_frame_leave(_state); -} - - -static void lsfit_clearreport(lsfitreport* rep, ae_state *_state) -{ - - - rep->taskrcond = (double)(0); - rep->iterationscount = 0; - rep->varidx = -1; - rep->rmserror = (double)(0); - rep->avgerror = (double)(0); - rep->avgrelerror = (double)(0); - rep->maxerror = (double)(0); - rep->wrmserror = (double)(0); - rep->r2 = (double)(0); - ae_matrix_set_length(&rep->covpar, 0, 0, _state); - ae_vector_set_length(&rep->errpar, 0, _state); - ae_vector_set_length(&rep->errcurve, 0, _state); - ae_vector_set_length(&rep->noise, 0, _state); -} - - -/************************************************************************* -This internal function estimates covariance matrix and other error-related -information for linear/nonlinear least squares model. - -It has a bit awkward interface, but it can be used for both linear and -nonlinear problems. - -INPUT PARAMETERS: - F1 - array[0..N-1,0..K-1]: - * for linear problems - matrix of function values - * for nonlinear problems - Jacobian matrix - F0 - array[0..N-1]: - * for linear problems - must be filled with zeros - * for nonlinear problems - must store values of function being - fitted - Y - array[0..N-1]: - * for linear and nonlinear problems - must store target values - W - weights, array[0..N-1]: - * for linear and nonlinear problems - weights - X - array[0..K-1]: - * for linear and nonlinear problems - current solution - S - array[0..K-1]: - * its components should be strictly positive - * squared inverse of this diagonal matrix is used as damping - factor for covariance matrix (linear and nonlinear problems) - * for nonlinear problems, when scale of the variables is usually - explicitly given by user, you may use scale vector for this - parameter - * for linear problems you may set this parameter to - S=sqrt(1/diag(F'*F)) - * this parameter is automatically rescaled by this function, - only relative magnitudes of its components (with respect to - each other) matter. - N - number of points, N>0. - K - number of dimensions - Rep - structure which is used to store results - Z - additional matrix which, depending on ZKind, may contain some - information used to accelerate calculations - or just can be - temporary buffer: - * for ZKind=0 Z contains no information, just temporary - buffer which can be resized and used as needed - * for ZKind=1 Z contains triangular matrix from QR - decomposition of W*F1. This matrix can be used - to speedup calculation of covariance matrix. - It should not be changed by algorithm. - ZKind- contents of Z - -OUTPUT PARAMETERS: - -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(J*CovPar*J')), - where J is Jacobian matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] -* Rep.R2 coefficient of determination (non-weighted) - -Other fields of Rep are not changed. - -IMPORTANT: errors in parameters are calculated without taking into - account boundary/linear constraints! Presence of constraints - changes distribution of errors, but there is no easy way to - account for constraints when you calculate covariance matrix. - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - - -- ALGLIB PROJECT -- - Copyright 10.12.2009 by Bochkanov Sergey -*************************************************************************/ -static void lsfit_estimateerrors(/* Real */ ae_matrix* f1, - /* Real */ ae_vector* f0, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - /* Real */ ae_vector* x, - /* Real */ ae_vector* s, - ae_int_t n, - ae_int_t k, - lsfitreport* rep, - /* Real */ ae_matrix* z, - ae_int_t zkind, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _s; - ae_int_t i; - ae_int_t j; - ae_int_t j1; - double v; - double noisec; - ae_int_t info; - matinvreport invrep; - ae_int_t nzcnt; - double avg; - double rss; - double tss; - double sz; - double ss; - - ae_frame_make(_state, &_frame_block); - memset(&_s, 0, sizeof(_s)); - memset(&invrep, 0, sizeof(invrep)); - ae_vector_init_copy(&_s, s, _state, ae_true); - s = &_s; - _matinvreport_init(&invrep, _state, ae_true); - - - /* - * Compute NZCnt - count of non-zero weights - */ - nzcnt = 0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_neq(w->ptr.p_double[i],(double)(0)) ) - { - nzcnt = nzcnt+1; - } - } - - /* - * Compute R2 - */ - if( nzcnt>0 ) - { - avg = 0.0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_neq(w->ptr.p_double[i],(double)(0)) ) - { - avg = avg+y->ptr.p_double[i]; - } - } - avg = avg/nzcnt; - rss = 0.0; - tss = 0.0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_neq(w->ptr.p_double[i],(double)(0)) ) - { - v = ae_v_dotproduct(&f1->ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,k-1)); - v = v+f0->ptr.p_double[i]; - rss = rss+ae_sqr(v-y->ptr.p_double[i], _state); - tss = tss+ae_sqr(y->ptr.p_double[i]-avg, _state); - } - } - if( ae_fp_neq(tss,(double)(0)) ) - { - rep->r2 = ae_maxreal(1.0-rss/tss, 0.0, _state); - } - else - { - rep->r2 = 1.0; - } - } - else - { - rep->r2 = (double)(0); - } - - /* - * Compute estimate of proportionality between noise in the data and weights: - * NoiseC = mean(per-point-noise*per-point-weight) - * Noise level (standard deviation) at each point is equal to NoiseC/W[I]. - */ - if( nzcnt>k ) - { - noisec = 0.0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_neq(w->ptr.p_double[i],(double)(0)) ) - { - v = ae_v_dotproduct(&f1->ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,k-1)); - v = v+f0->ptr.p_double[i]; - noisec = noisec+ae_sqr((v-y->ptr.p_double[i])*w->ptr.p_double[i], _state); - } - } - noisec = ae_sqrt(noisec/(nzcnt-k), _state); - } - else - { - noisec = 0.0; - } - - /* - * Two branches on noise level: - * * NoiseC>0 normal situation - * * NoiseC=0 degenerate case CovPar is filled by zeros - */ - rmatrixsetlengthatleast(&rep->covpar, k, k, _state); - if( ae_fp_greater(noisec,(double)(0)) ) - { - - /* - * Normal situation: non-zero noise level - */ - ae_assert(zkind==0||zkind==1, "LSFit: internal error in EstimateErrors() function", _state); - if( zkind==0 ) - { - - /* - * Z contains no additional information which can be used to speed up - * calculations. We have to calculate covariance matrix on our own: - * * Compute scaled Jacobian N*J, where N[i,i]=WCur[I]/NoiseC, store in Z - * * Compute Z'*Z, store in CovPar - * * Apply moderate regularization to CovPar and compute matrix inverse. - * In case inverse failed, increase regularization parameter and try - * again. - */ - rmatrixsetlengthatleast(z, n, k, _state); - for(i=0; i<=n-1; i++) - { - v = w->ptr.p_double[i]/noisec; - ae_v_moved(&z->ptr.pp_double[i][0], 1, &f1->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v); - } - - /* - * Convert S to automatically scaled damped matrix: - * * calculate SZ - sum of diagonal elements of Z'*Z - * * calculate SS - sum of diagonal elements of S^(-2) - * * overwrite S by (SZ/SS)*S^(-2) - * * now S has approximately same magnitude as giagonal of Z'*Z - */ - sz = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=k-1; j++) - { - sz = sz+z->ptr.pp_double[i][j]*z->ptr.pp_double[i][j]; - } - } - if( ae_fp_eq(sz,(double)(0)) ) - { - sz = (double)(1); - } - ss = (double)(0); - for(j=0; j<=k-1; j++) - { - ss = ss+1/ae_sqr(s->ptr.p_double[j], _state); - } - for(j=0; j<=k-1; j++) - { - s->ptr.p_double[j] = sz/ss/ae_sqr(s->ptr.p_double[j], _state); - } - - /* - * Calculate damped inverse inv(Z'*Z+S). - * We increase damping factor V until Z'*Z become well-conditioned. - */ - v = 1.0E3*ae_machineepsilon; - do - { - rmatrixsyrk(k, n, 1.0, z, 0, 0, 2, 0.0, &rep->covpar, 0, 0, ae_true, _state); - for(i=0; i<=k-1; i++) - { - rep->covpar.ptr.pp_double[i][i] = rep->covpar.ptr.pp_double[i][i]+v*s->ptr.p_double[i]; - } - spdmatrixinverse(&rep->covpar, k, ae_true, &info, &invrep, _state); - v = 10*v; - } - while(info<=0); - for(i=0; i<=k-1; i++) - { - for(j=i+1; j<=k-1; j++) - { - rep->covpar.ptr.pp_double[j][i] = rep->covpar.ptr.pp_double[i][j]; - } - } - } - if( zkind==1 ) - { - - /* - * We can reuse additional information: - * * Z contains R matrix from QR decomposition of W*F1 - * * After multiplication by 1/NoiseC we get Z_mod = N*F1, where diag(N)=w[i]/NoiseC - * * Such triangular Z_mod is a Cholesky factor from decomposition of J'*N'*N*J. - * Thus, we can calculate covariance matrix as inverse of the matrix given by - * its Cholesky decomposition. It allow us to avoid time-consuming calculation - * of J'*N'*N*J in CovPar - complexity is reduced from O(N*K^2) to O(K^3), which - * is quite good because K is usually orders of magnitude smaller than N. - * - * First, convert S to automatically scaled damped matrix: - * * calculate SZ - sum of magnitudes of diagonal elements of Z/NoiseC - * * calculate SS - sum of diagonal elements of S^(-1) - * * overwrite S by (SZ/SS)*S^(-1) - * * now S has approximately same magnitude as giagonal of Z'*Z - */ - sz = (double)(0); - for(j=0; j<=k-1; j++) - { - sz = sz+ae_fabs(z->ptr.pp_double[j][j]/noisec, _state); - } - if( ae_fp_eq(sz,(double)(0)) ) - { - sz = (double)(1); - } - ss = (double)(0); - for(j=0; j<=k-1; j++) - { - ss = ss+1/s->ptr.p_double[j]; - } - for(j=0; j<=k-1; j++) - { - s->ptr.p_double[j] = sz/ss/s->ptr.p_double[j]; - } - - /* - * Calculate damped inverse of inv((Z+v*S)'*(Z+v*S)) - * We increase damping factor V until matrix become well-conditioned. - */ - v = 1.0E3*ae_machineepsilon; - do - { - for(i=0; i<=k-1; i++) - { - for(j=i; j<=k-1; j++) - { - rep->covpar.ptr.pp_double[i][j] = z->ptr.pp_double[i][j]/noisec; - } - rep->covpar.ptr.pp_double[i][i] = rep->covpar.ptr.pp_double[i][i]+v*s->ptr.p_double[i]; - } - spdmatrixcholeskyinverse(&rep->covpar, k, ae_true, &info, &invrep, _state); - v = 10*v; - } - while(info<=0); - for(i=0; i<=k-1; i++) - { - for(j=i+1; j<=k-1; j++) - { - rep->covpar.ptr.pp_double[j][i] = rep->covpar.ptr.pp_double[i][j]; - } - } - } - } - else - { - - /* - * Degenerate situation: zero noise level, covariance matrix is zero. - */ - for(i=0; i<=k-1; i++) - { - for(j=0; j<=k-1; j++) - { - rep->covpar.ptr.pp_double[j][i] = (double)(0); - } - } - } - - /* - * Estimate erorrs in parameters, curve and per-point noise - */ - rvectorsetlengthatleast(&rep->errpar, k, _state); - rvectorsetlengthatleast(&rep->errcurve, n, _state); - rvectorsetlengthatleast(&rep->noise, n, _state); - for(i=0; i<=k-1; i++) - { - rep->errpar.ptr.p_double[i] = ae_sqrt(rep->covpar.ptr.pp_double[i][i], _state); - } - for(i=0; i<=n-1; i++) - { - - /* - * ErrCurve[I] is sqrt(P[i,i]) where P=J*CovPar*J' - */ - v = 0.0; - for(j=0; j<=k-1; j++) - { - for(j1=0; j1<=k-1; j1++) - { - v = v+f1->ptr.pp_double[i][j]*rep->covpar.ptr.pp_double[j][j1]*f1->ptr.pp_double[i][j1]; - } - } - rep->errcurve.ptr.p_double[i] = ae_sqrt(v, _state); - - /* - * Noise[i] is filled using weights and current estimate of noise level - */ - if( ae_fp_neq(w->ptr.p_double[i],(double)(0)) ) - { - rep->noise.ptr.p_double[i] = noisec/w->ptr.p_double[i]; - } - else - { - rep->noise.ptr.p_double[i] = (double)(0); - } - } - ae_frame_leave(_state); -} - - -void _polynomialfitreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - polynomialfitreport *p = (polynomialfitreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _polynomialfitreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - polynomialfitreport *dst = (polynomialfitreport*)_dst; - polynomialfitreport *src = (polynomialfitreport*)_src; - dst->taskrcond = src->taskrcond; - dst->rmserror = src->rmserror; - dst->avgerror = src->avgerror; - dst->avgrelerror = src->avgrelerror; - dst->maxerror = src->maxerror; -} - - -void _polynomialfitreport_clear(void* _p) -{ - polynomialfitreport *p = (polynomialfitreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _polynomialfitreport_destroy(void* _p) -{ - polynomialfitreport *p = (polynomialfitreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _barycentricfitreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - barycentricfitreport *p = (barycentricfitreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _barycentricfitreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - barycentricfitreport *dst = (barycentricfitreport*)_dst; - barycentricfitreport *src = (barycentricfitreport*)_src; - dst->taskrcond = src->taskrcond; - dst->dbest = src->dbest; - dst->rmserror = src->rmserror; - dst->avgerror = src->avgerror; - dst->avgrelerror = src->avgrelerror; - dst->maxerror = src->maxerror; -} - - -void _barycentricfitreport_clear(void* _p) -{ - barycentricfitreport *p = (barycentricfitreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _barycentricfitreport_destroy(void* _p) -{ - barycentricfitreport *p = (barycentricfitreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _lsfitreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - lsfitreport *p = (lsfitreport*)_p; - ae_touch_ptr((void*)p); - ae_matrix_init(&p->covpar, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->errpar, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->errcurve, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->noise, 0, DT_REAL, _state, make_automatic); -} - - -void _lsfitreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - lsfitreport *dst = (lsfitreport*)_dst; - lsfitreport *src = (lsfitreport*)_src; - dst->taskrcond = src->taskrcond; - dst->iterationscount = src->iterationscount; - dst->varidx = src->varidx; - dst->rmserror = src->rmserror; - dst->avgerror = src->avgerror; - dst->avgrelerror = src->avgrelerror; - dst->maxerror = src->maxerror; - dst->wrmserror = src->wrmserror; - ae_matrix_init_copy(&dst->covpar, &src->covpar, _state, make_automatic); - ae_vector_init_copy(&dst->errpar, &src->errpar, _state, make_automatic); - ae_vector_init_copy(&dst->errcurve, &src->errcurve, _state, make_automatic); - ae_vector_init_copy(&dst->noise, &src->noise, _state, make_automatic); - dst->r2 = src->r2; -} - - -void _lsfitreport_clear(void* _p) -{ - lsfitreport *p = (lsfitreport*)_p; - ae_touch_ptr((void*)p); - ae_matrix_clear(&p->covpar); - ae_vector_clear(&p->errpar); - ae_vector_clear(&p->errcurve); - ae_vector_clear(&p->noise); -} - - -void _lsfitreport_destroy(void* _p) -{ - lsfitreport *p = (lsfitreport*)_p; - ae_touch_ptr((void*)p); - ae_matrix_destroy(&p->covpar); - ae_vector_destroy(&p->errpar); - ae_vector_destroy(&p->errcurve); - ae_vector_destroy(&p->noise); -} - - -void _lsfitstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - lsfitstate *p = (lsfitstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->c0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->c1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->taskx, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tasky, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->taskw, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->cleic, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->c, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->h, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->wcur, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpct, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->tmp, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpf, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->tmpjac, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->tmpjacw, 0, 0, DT_REAL, _state, make_automatic); - _matinvreport_init(&p->invrep, _state, make_automatic); - _lsfitreport_init(&p->rep, _state, make_automatic); - _minlmstate_init(&p->optstate, _state, make_automatic); - _minlmreport_init(&p->optrep, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); -} - - -void _lsfitstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - lsfitstate *dst = (lsfitstate*)_dst; - lsfitstate *src = (lsfitstate*)_src; - dst->optalgo = src->optalgo; - dst->m = src->m; - dst->k = src->k; - dst->epsx = src->epsx; - dst->maxits = src->maxits; - dst->stpmax = src->stpmax; - dst->xrep = src->xrep; - ae_vector_init_copy(&dst->c0, &src->c0, _state, make_automatic); - ae_vector_init_copy(&dst->c1, &src->c1, _state, make_automatic); - ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic); - ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic); - ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic); - ae_matrix_init_copy(&dst->taskx, &src->taskx, _state, make_automatic); - ae_vector_init_copy(&dst->tasky, &src->tasky, _state, make_automatic); - dst->npoints = src->npoints; - ae_vector_init_copy(&dst->taskw, &src->taskw, _state, make_automatic); - dst->nweights = src->nweights; - dst->wkind = src->wkind; - dst->wits = src->wits; - dst->diffstep = src->diffstep; - dst->teststep = src->teststep; - ae_matrix_init_copy(&dst->cleic, &src->cleic, _state, make_automatic); - dst->nec = src->nec; - dst->nic = src->nic; - dst->xupdated = src->xupdated; - dst->needf = src->needf; - dst->needfg = src->needfg; - dst->needfgh = src->needfgh; - dst->pointindex = src->pointindex; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->c, &src->c, _state, make_automatic); - dst->f = src->f; - ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic); - ae_matrix_init_copy(&dst->h, &src->h, _state, make_automatic); - ae_vector_init_copy(&dst->wcur, &src->wcur, _state, make_automatic); - ae_vector_init_copy(&dst->tmpct, &src->tmpct, _state, make_automatic); - ae_vector_init_copy(&dst->tmp, &src->tmp, _state, make_automatic); - ae_vector_init_copy(&dst->tmpf, &src->tmpf, _state, make_automatic); - ae_matrix_init_copy(&dst->tmpjac, &src->tmpjac, _state, make_automatic); - ae_matrix_init_copy(&dst->tmpjacw, &src->tmpjacw, _state, make_automatic); - dst->tmpnoise = src->tmpnoise; - _matinvreport_init_copy(&dst->invrep, &src->invrep, _state, make_automatic); - dst->repiterationscount = src->repiterationscount; - dst->repterminationtype = src->repterminationtype; - dst->repvaridx = src->repvaridx; - dst->reprmserror = src->reprmserror; - dst->repavgerror = src->repavgerror; - dst->repavgrelerror = src->repavgrelerror; - dst->repmaxerror = src->repmaxerror; - dst->repwrmserror = src->repwrmserror; - _lsfitreport_init_copy(&dst->rep, &src->rep, _state, make_automatic); - _minlmstate_init_copy(&dst->optstate, &src->optstate, _state, make_automatic); - _minlmreport_init_copy(&dst->optrep, &src->optrep, _state, make_automatic); - dst->prevnpt = src->prevnpt; - dst->prevalgo = src->prevalgo; - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); -} - - -void _lsfitstate_clear(void* _p) -{ - lsfitstate *p = (lsfitstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->c0); - ae_vector_clear(&p->c1); - ae_vector_clear(&p->s); - ae_vector_clear(&p->bndl); - ae_vector_clear(&p->bndu); - ae_matrix_clear(&p->taskx); - ae_vector_clear(&p->tasky); - ae_vector_clear(&p->taskw); - ae_matrix_clear(&p->cleic); - ae_vector_clear(&p->x); - ae_vector_clear(&p->c); - ae_vector_clear(&p->g); - ae_matrix_clear(&p->h); - ae_vector_clear(&p->wcur); - ae_vector_clear(&p->tmpct); - ae_vector_clear(&p->tmp); - ae_vector_clear(&p->tmpf); - ae_matrix_clear(&p->tmpjac); - ae_matrix_clear(&p->tmpjacw); - _matinvreport_clear(&p->invrep); - _lsfitreport_clear(&p->rep); - _minlmstate_clear(&p->optstate); - _minlmreport_clear(&p->optrep); - _rcommstate_clear(&p->rstate); -} - - -void _lsfitstate_destroy(void* _p) -{ - lsfitstate *p = (lsfitstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->c0); - ae_vector_destroy(&p->c1); - ae_vector_destroy(&p->s); - ae_vector_destroy(&p->bndl); - ae_vector_destroy(&p->bndu); - ae_matrix_destroy(&p->taskx); - ae_vector_destroy(&p->tasky); - ae_vector_destroy(&p->taskw); - ae_matrix_destroy(&p->cleic); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->c); - ae_vector_destroy(&p->g); - ae_matrix_destroy(&p->h); - ae_vector_destroy(&p->wcur); - ae_vector_destroy(&p->tmpct); - ae_vector_destroy(&p->tmp); - ae_vector_destroy(&p->tmpf); - ae_matrix_destroy(&p->tmpjac); - ae_matrix_destroy(&p->tmpjacw); - _matinvreport_destroy(&p->invrep); - _lsfitreport_destroy(&p->rep); - _minlmstate_destroy(&p->optstate); - _minlmreport_destroy(&p->optrep); - _rcommstate_destroy(&p->rstate); -} - - -#endif -#if defined(AE_COMPILE_RBFV2) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function creates RBF model for a scalar (NY=1) or vector (NY>1) -function in a NX-dimensional space (NX=2 or NX=3). - -INPUT PARAMETERS: - NX - dimension of the space, NX=2 or NX=3 - NY - function dimension, NY>=1 - -OUTPUT PARAMETERS: - S - RBF model (initially equals to zero) - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfv2create(ae_int_t nx, - ae_int_t ny, - rbfv2model* s, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - _rbfv2model_clear(s); - - ae_assert(nx>=1, "RBFCreate: NX<1", _state); - ae_assert(ny>=1, "RBFCreate: NY<1", _state); - - /* - * Serializable parameters - */ - s->nx = nx; - s->ny = ny; - s->bf = 0; - s->nh = 0; - ae_matrix_set_length(&s->v, ny, nx+1, _state); - for(i=0; i<=ny-1; i++) - { - for(j=0; j<=nx; j++) - { - s->v.ptr.pp_double[i][j] = (double)(0); - } - } - - /* - * Non-serializable parameters - */ - s->lambdareg = rbfv2_defaultlambdareg; - s->maxits = rbfv2_defaultmaxits; - s->supportr = rbfv2_defaultsupportr; - s->basisfunction = rbfv2_defaultbf; -} - - -/************************************************************************* -This function creates buffer structure which can be used to perform -parallel RBF model evaluations (with one RBF model instance being -used from multiple threads, as long as different threads use different -instances of buffer). - -This buffer object can be used with rbftscalcbuf() function (here "ts" -stands for "thread-safe", "buf" is a suffix which denotes function which -reuses previously allocated output space). - -How to use it: -* create RBF model structure with rbfcreate() -* load data, tune parameters -* call rbfbuildmodel() -* call rbfcreatecalcbuffer(), once per thread working with RBF model (you - should call this function only AFTER call to rbfbuildmodel(), see below - for more information) -* call rbftscalcbuf() from different threads, with each thread working - with its own copy of buffer object. - -INPUT PARAMETERS - S - RBF model - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: buffer object should be used only with RBF model object which - was used to initialize buffer. Any attempt to use buffer with - different object is dangerous - you may get memory violation - error because sizes of internal arrays do not fit to dimensions - of RBF structure. - -IMPORTANT: you should call this function only for model which was built - with rbfbuildmodel() function, after successful invocation of - rbfbuildmodel(). Sizes of some internal structures are - determined only after model is built, so buffer object created - before model construction stage will be useless (and any - attempt to use it will result in exception). - - -- ALGLIB -- - Copyright 02.04.2016 by Sergey Bochkanov -*************************************************************************/ -void rbfv2createcalcbuffer(rbfv2model* s, - rbfv2calcbuffer* buf, - ae_state *_state) -{ - - _rbfv2calcbuffer_clear(buf); - - rbfv2_allocatecalcbuffer(s, buf, _state); -} - - -/************************************************************************* -This function builds hierarchical RBF model. - -INPUT PARAMETERS: - X - array[N,S.NX], X-values - Y - array[N,S.NY], Y-values - ScaleVec- array[S.NX], vector of per-dimension scales - N - points count - ATerm - linear term type, 1 for linear, 2 for constant, 3 for zero. - NH - hierarchy height - RBase - base RBF radius - BF - basis function type: 0 for Gaussian, 1 for compact - LambdaNS- non-smoothness penalty coefficient. Exactly zero value means - that no penalty is applied, and even system matrix does not - contain penalty-related rows. Value of 1 means - S - RBF model, initialized by RBFCreate() call. - progress10000- variable used for progress reports, it is regularly set - to the current progress multiplied by 10000, in order to - get value in [0,10000] range. The rationale for such scaling - is that it allows us to use integer type to store progress, - which has less potential for non-atomic corruption on unprotected - reads from another threads. - You can read this variable from some other thread to get - estimate of the current progress. - Initial value of this variable is ignored, it is written by - this function, but not read. - terminationrequest - variable used for termination requests; its initial - value must be False, and you can set it to True from some - other thread. This routine regularly checks this variable - and will terminate model construction shortly upon discovering - that termination was requested. - -OUTPUT PARAMETERS: - S - updated model (for rep.terminationtype>0, unchanged otherwise) - Rep - report: - * Rep.TerminationType: - * -5 - non-distinct basis function centers were detected, - interpolation aborted - * -4 - nonconvergence of the internal SVD solver - * 1 - successful termination - * 8 terminated by user via rbfrequesttermination() - Fields are used for debugging purposes: - * Rep.IterationsCount - iterations count of the LSQR solver - * Rep.NMV - number of matrix-vector products - * Rep.ARows - rows count for the system matrix - * Rep.ACols - columns count for the system matrix - * Rep.ANNZ - number of significantly non-zero elements - (elements above some algorithm-determined threshold) - -NOTE: failure to build model will leave current state of the structure -unchanged. - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfv2buildhierarchical(/* Real */ ae_matrix* x, - /* Real */ ae_matrix* y, - ae_int_t n, - /* Real */ ae_vector* scalevec, - ae_int_t aterm, - ae_int_t nh, - double rbase, - double lambdans, - rbfv2model* s, - ae_int_t* progress10000, - ae_bool* terminationrequest, - rbfv2report* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nx; - ae_int_t ny; - ae_int_t bf; - ae_matrix rhs; - ae_matrix residualy; - ae_matrix v; - ae_int_t rowsperpoint; - ae_vector hidx; - ae_vector xr; - ae_vector ri; - ae_vector kdroots; - ae_vector kdnodes; - ae_vector kdsplits; - ae_vector kdboxmin; - ae_vector kdboxmax; - ae_vector cw; - ae_vector cwrange; - ae_matrix curxy; - ae_int_t curn; - ae_int_t nbasis; - kdtree curtree; - kdtree globaltree; - ae_vector x0; - ae_vector x1; - ae_vector tags; - ae_vector dist; - ae_vector nncnt; - ae_vector rowsizes; - ae_vector diagata; - ae_vector prec; - ae_vector tmpx; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t k2; - ae_int_t levelidx; - ae_int_t offsi; - ae_int_t offsj; - double val; - double criticalr; - ae_int_t cnt; - double avgdiagata; - ae_vector avgrowsize; - double sumrowsize; - double rprogress; - ae_int_t maxits; - linlsqrstate linstate; - linlsqrreport lsqrrep; - sparsematrix sparseacrs; - ae_vector densew1; - ae_vector denseb1; - rbfv2calcbuffer calcbuf; - ae_vector vr2; - ae_vector voffs; - ae_vector rowindexes; - ae_vector rowvals; - double penalty; - - ae_frame_make(_state, &_frame_block); - memset(&rhs, 0, sizeof(rhs)); - memset(&residualy, 0, sizeof(residualy)); - memset(&v, 0, sizeof(v)); - memset(&hidx, 0, sizeof(hidx)); - memset(&xr, 0, sizeof(xr)); - memset(&ri, 0, sizeof(ri)); - memset(&kdroots, 0, sizeof(kdroots)); - memset(&kdnodes, 0, sizeof(kdnodes)); - memset(&kdsplits, 0, sizeof(kdsplits)); - memset(&kdboxmin, 0, sizeof(kdboxmin)); - memset(&kdboxmax, 0, sizeof(kdboxmax)); - memset(&cw, 0, sizeof(cw)); - memset(&cwrange, 0, sizeof(cwrange)); - memset(&curxy, 0, sizeof(curxy)); - memset(&curtree, 0, sizeof(curtree)); - memset(&globaltree, 0, sizeof(globaltree)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&tags, 0, sizeof(tags)); - memset(&dist, 0, sizeof(dist)); - memset(&nncnt, 0, sizeof(nncnt)); - memset(&rowsizes, 0, sizeof(rowsizes)); - memset(&diagata, 0, sizeof(diagata)); - memset(&prec, 0, sizeof(prec)); - memset(&tmpx, 0, sizeof(tmpx)); - memset(&avgrowsize, 0, sizeof(avgrowsize)); - memset(&linstate, 0, sizeof(linstate)); - memset(&lsqrrep, 0, sizeof(lsqrrep)); - memset(&sparseacrs, 0, sizeof(sparseacrs)); - memset(&densew1, 0, sizeof(densew1)); - memset(&denseb1, 0, sizeof(denseb1)); - memset(&calcbuf, 0, sizeof(calcbuf)); - memset(&vr2, 0, sizeof(vr2)); - memset(&voffs, 0, sizeof(voffs)); - memset(&rowindexes, 0, sizeof(rowindexes)); - memset(&rowvals, 0, sizeof(rowvals)); - _rbfv2report_clear(rep); - ae_matrix_init(&rhs, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&residualy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&hidx, 0, DT_INT, _state, ae_true); - ae_vector_init(&xr, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ri, 0, DT_REAL, _state, ae_true); - ae_vector_init(&kdroots, 0, DT_INT, _state, ae_true); - ae_vector_init(&kdnodes, 0, DT_INT, _state, ae_true); - ae_vector_init(&kdsplits, 0, DT_REAL, _state, ae_true); - ae_vector_init(&kdboxmin, 0, DT_REAL, _state, ae_true); - ae_vector_init(&kdboxmax, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cw, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cwrange, 0, DT_INT, _state, ae_true); - ae_matrix_init(&curxy, 0, 0, DT_REAL, _state, ae_true); - _kdtree_init(&curtree, _state, ae_true); - _kdtree_init(&globaltree, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tags, 0, DT_INT, _state, ae_true); - ae_vector_init(&dist, 0, DT_REAL, _state, ae_true); - ae_vector_init(&nncnt, 0, DT_INT, _state, ae_true); - ae_vector_init(&rowsizes, 0, DT_INT, _state, ae_true); - ae_vector_init(&diagata, 0, DT_REAL, _state, ae_true); - ae_vector_init(&prec, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&avgrowsize, 0, DT_REAL, _state, ae_true); - _linlsqrstate_init(&linstate, _state, ae_true); - _linlsqrreport_init(&lsqrrep, _state, ae_true); - _sparsematrix_init(&sparseacrs, _state, ae_true); - ae_vector_init(&densew1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&denseb1, 0, DT_REAL, _state, ae_true); - _rbfv2calcbuffer_init(&calcbuf, _state, ae_true); - ae_vector_init(&vr2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&voffs, 0, DT_INT, _state, ae_true); - ae_vector_init(&rowindexes, 0, DT_INT, _state, ae_true); - ae_vector_init(&rowvals, 0, DT_REAL, _state, ae_true); - - ae_assert(s->nx>0, "RBFV2BuildHierarchical: incorrect NX", _state); - ae_assert(s->ny>0, "RBFV2BuildHierarchical: incorrect NY", _state); - ae_assert(ae_fp_greater_eq(lambdans,(double)(0)), "RBFV2BuildHierarchical: incorrect LambdaNS", _state); - for(j=0; j<=s->nx-1; j++) - { - ae_assert(ae_fp_greater(scalevec->ptr.p_double[j],(double)(0)), "RBFV2BuildHierarchical: incorrect ScaleVec", _state); - } - nx = s->nx; - ny = s->ny; - bf = s->basisfunction; - ae_assert(bf==0||bf==1, "RBFV2BuildHierarchical: incorrect BF", _state); - - /* - * Clean up communication and report fields - */ - *progress10000 = 0; - rep->maxerror = (double)(0); - rep->rmserror = (double)(0); - - /* - * Quick exit when we have no points - */ - if( n==0 ) - { - rbfv2_zerofill(s, nx, ny, bf, _state); - rep->terminationtype = 1; - *progress10000 = 10000; - ae_frame_leave(_state); - return; - } - - /* - * First model in a sequence - linear model. - * Residuals from linear regression are stored in the ResidualY variable - * (used later to build RBF models). - */ - ae_matrix_set_length(&residualy, n, ny, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=ny-1; j++) - { - residualy.ptr.pp_double[i][j] = y->ptr.pp_double[i][j]; - } - } - if( !rbfv2_rbfv2buildlinearmodel(x, &residualy, n, nx, ny, aterm, &v, _state) ) - { - rbfv2_zerofill(s, nx, ny, bf, _state); - rep->terminationtype = -5; - *progress10000 = 10000; - ae_frame_leave(_state); - return; - } - - /* - * Handle special case: multilayer model with NLayers=0. - * Quick exit. - */ - if( nh==0 ) - { - rep->terminationtype = 1; - rbfv2_zerofill(s, nx, ny, bf, _state); - for(i=0; i<=ny-1; i++) - { - for(j=0; j<=nx; j++) - { - s->v.ptr.pp_double[i][j] = v.ptr.pp_double[i][j]; - } - } - rep->maxerror = (double)(0); - rep->rmserror = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=ny-1; j++) - { - rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(residualy.ptr.pp_double[i][j], _state), _state); - rep->rmserror = rep->rmserror+ae_sqr(residualy.ptr.pp_double[i][j], _state); - } - } - rep->rmserror = ae_sqrt(rep->rmserror/(n*ny), _state); - *progress10000 = 10000; - ae_frame_leave(_state); - return; - } - - /* - * Penalty coefficient is set to LambdaNS*RBase^2. - * - * We use such normalization because VALUES of radial basis - * functions have roughly unit magnitude, but their DERIVATIVES - * are (roughly) inversely proportional to the radius. Thus, - * without additional scaling, regularization coefficient - * looses invariancy w.r.t. scaling of variables. - */ - if( ae_fp_eq(lambdans,(double)(0)) ) - { - rowsperpoint = 1; - } - else - { - - /* - * NOTE: simplified penalty function is used, which does not provide rotation invariance - */ - rowsperpoint = 1+nx; - } - penalty = lambdans*ae_sqr(rbase, _state); - - /* - * Prepare temporary structures - */ - ae_matrix_set_length(&rhs, n*rowsperpoint, ny, _state); - ae_matrix_set_length(&curxy, n, nx+ny, _state); - ae_vector_set_length(&x0, nx, _state); - ae_vector_set_length(&x1, nx, _state); - ae_vector_set_length(&tags, n, _state); - ae_vector_set_length(&dist, n, _state); - ae_vector_set_length(&vr2, n, _state); - ae_vector_set_length(&voffs, n, _state); - ae_vector_set_length(&nncnt, n, _state); - ae_vector_set_length(&rowsizes, n*rowsperpoint, _state); - ae_vector_set_length(&denseb1, n*rowsperpoint, _state); - for(i=0; i<=n*rowsperpoint-1; i++) - { - for(j=0; j<=ny-1; j++) - { - rhs.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - curxy.ptr.pp_double[i][j] = x->ptr.pp_double[i][j]/scalevec->ptr.p_double[j]; - } - for(j=0; j<=ny-1; j++) - { - rhs.ptr.pp_double[i*rowsperpoint][j] = residualy.ptr.pp_double[i][j]; - } - tags.ptr.p_int[i] = i; - } - kdtreebuildtagged(&curxy, &tags, n, nx, 0, 2, &globaltree, _state); - - /* - * Generate sequence of layer radii. - * Prepare assignment of different levels to points. - */ - ae_assert(n>0, "RBFV2BuildHierarchical: integrity check failed", _state); - ae_vector_set_length(&ri, nh, _state); - for(levelidx=0; levelidx<=nh-1; levelidx++) - { - ri.ptr.p_double[levelidx] = rbase*ae_pow((double)(2), (double)(-levelidx), _state); - } - ae_vector_set_length(&hidx, n, _state); - ae_vector_set_length(&xr, n, _state); - for(i=0; i<=n-1; i++) - { - hidx.ptr.p_int[i] = nh; - xr.ptr.p_double[i] = ae_maxrealnumber; - ae_assert(ae_fp_greater(xr.ptr.p_double[i],ri.ptr.p_double[0]), "RBFV2BuildHierarchical: integrity check failed", _state); - } - for(levelidx=0; levelidx<=nh-1; levelidx++) - { - - /* - * Scan dataset points, for each such point that distance to nearest - * "support" point is larger than SupportR*Ri[LevelIdx] we: - * * set distance of current point to 0 (it is support now) and update HIdx - * * perform R-NN request with radius SupportR*Ri[LevelIdx] - * * for each point in request update its distance - */ - criticalr = s->supportr*ri.ptr.p_double[levelidx]; - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(xr.ptr.p_double[i],criticalr) ) - { - - /* - * Mark point as support - */ - ae_assert(hidx.ptr.p_int[i]==nh, "RBFV2BuildHierarchical: integrity check failed", _state); - hidx.ptr.p_int[i] = levelidx; - xr.ptr.p_double[i] = (double)(0); - - /* - * Update neighbors - */ - for(j=0; j<=nx-1; j++) - { - x0.ptr.p_double[j] = x->ptr.pp_double[i][j]/scalevec->ptr.p_double[j]; - } - k = kdtreequeryrnn(&globaltree, &x0, criticalr, ae_true, _state); - kdtreequeryresultstags(&globaltree, &tags, _state); - kdtreequeryresultsdistances(&globaltree, &dist, _state); - for(j=0; j<=k-1; j++) - { - xr.ptr.p_double[tags.ptr.p_int[j]] = ae_minreal(xr.ptr.p_double[tags.ptr.p_int[j]], dist.ptr.p_double[j], _state); - } - } - } - } - - /* - * Build multitree (with zero weights) according to hierarchy. - * - * NOTE: this code assumes that during every iteration kdNodes, - * kdSplits and CW have size which EXACTLY fits their - * contents, and that these variables are resized at each - * iteration when we add new hierarchical model. - */ - ae_vector_set_length(&kdroots, nh+1, _state); - ae_vector_set_length(&kdnodes, 0, _state); - ae_vector_set_length(&kdsplits, 0, _state); - ae_vector_set_length(&kdboxmin, nx, _state); - ae_vector_set_length(&kdboxmax, nx, _state); - ae_vector_set_length(&cw, 0, _state); - ae_vector_set_length(&cwrange, nh+1, _state); - kdtreeexplorebox(&globaltree, &kdboxmin, &kdboxmax, _state); - cwrange.ptr.p_int[0] = 0; - for(levelidx=0; levelidx<=nh-1; levelidx++) - { - - /* - * Prepare radius and root offset - */ - kdroots.ptr.p_int[levelidx] = kdnodes.cnt; - - /* - * Generate LevelIdx-th tree and append to multi-tree - */ - curn = 0; - for(i=0; i<=n-1; i++) - { - if( hidx.ptr.p_int[i]<=levelidx ) - { - for(j=0; j<=nx-1; j++) - { - curxy.ptr.pp_double[curn][j] = x->ptr.pp_double[i][j]/scalevec->ptr.p_double[j]; - } - for(j=0; j<=ny-1; j++) - { - curxy.ptr.pp_double[curn][nx+j] = (double)(0); - } - inc(&curn, _state); - } - } - ae_assert(curn>0, "RBFV2BuildHierarchical: integrity check failed", _state); - kdtreebuild(&curxy, curn, nx, ny, 2, &curtree, _state); - rbfv2_convertandappendtree(&curtree, curn, nx, ny, &kdnodes, &kdsplits, &cw, _state); - - /* - * Fill entry of CWRange (we assume that length of CW exactly fits its actual size) - */ - cwrange.ptr.p_int[levelidx+1] = cw.cnt; - } - kdroots.ptr.p_int[nh] = kdnodes.cnt; - - /* - * Prepare buffer and scaled dataset - */ - rbfv2_allocatecalcbuffer(s, &calcbuf, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - curxy.ptr.pp_double[i][j] = x->ptr.pp_double[i][j]/scalevec->ptr.p_double[j]; - } - } - - /* - * Calculate average row sizes for each layer; these values are used - * for smooth progress reporting (it adds some overhead, but in most - * cases - insignificant one). - */ - rvectorsetlengthatleast(&avgrowsize, nh, _state); - sumrowsize = (double)(0); - for(levelidx=0; levelidx<=nh-1; levelidx++) - { - cnt = 0; - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - x0.ptr.p_double[j] = curxy.ptr.pp_double[i][j]; - } - cnt = cnt+rbfv2_designmatrixrowsize(&kdnodes, &kdsplits, &cw, &ri, &kdroots, &kdboxmin, &kdboxmax, nx, ny, nh, levelidx, rbfv2nearradius(bf, _state), &x0, &calcbuf, _state); - } - avgrowsize.ptr.p_double[levelidx] = coalesce((double)(cnt), (double)(1), _state)/coalesce((double)(n), (double)(1), _state); - sumrowsize = sumrowsize+avgrowsize.ptr.p_double[levelidx]; - } - - /* - * Build unconstrained model with LSQR solver, applied layer by layer - */ - for(levelidx=0; levelidx<=nh-1; levelidx++) - { - - /* - * Generate A - matrix of basis functions (near radius is used) - * - * NOTE: AvgDiagATA is average value of diagonal element of A^T*A. - * It is used to calculate value of Tikhonov regularization - * coefficient. - */ - nbasis = (cwrange.ptr.p_int[levelidx+1]-cwrange.ptr.p_int[levelidx])/(nx+ny); - ae_assert(cwrange.ptr.p_int[levelidx+1]-cwrange.ptr.p_int[levelidx]==nbasis*(nx+ny), "Assertion failed", _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - x0.ptr.p_double[j] = curxy.ptr.pp_double[i][j]; - } - cnt = rbfv2_designmatrixrowsize(&kdnodes, &kdsplits, &cw, &ri, &kdroots, &kdboxmin, &kdboxmax, nx, ny, nh, levelidx, rbfv2nearradius(bf, _state), &x0, &calcbuf, _state); - nncnt.ptr.p_int[i] = cnt; - for(j=0; j<=rowsperpoint-1; j++) - { - rowsizes.ptr.p_int[i*rowsperpoint+j] = cnt; - } - } - ivectorsetlengthatleast(&rowindexes, nbasis, _state); - rvectorsetlengthatleast(&rowvals, nbasis*rowsperpoint, _state); - rvectorsetlengthatleast(&diagata, nbasis, _state); - sparsecreatecrsbuf(n*rowsperpoint, nbasis, &rowsizes, &sparseacrs, _state); - avgdiagata = 0.0; - for(j=0; j<=nbasis-1; j++) - { - diagata.ptr.p_double[j] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - - /* - * Fill design matrix row, diagonal of A^T*A - */ - for(j=0; j<=nx-1; j++) - { - x0.ptr.p_double[j] = curxy.ptr.pp_double[i][j]; - } - rbfv2_designmatrixgeneraterow(&kdnodes, &kdsplits, &cw, &ri, &kdroots, &kdboxmin, &kdboxmax, &cwrange, nx, ny, nh, levelidx, bf, rbfv2nearradius(bf, _state), rowsperpoint, penalty, &x0, &calcbuf, &vr2, &voffs, &rowindexes, &rowvals, &cnt, _state); - ae_assert(cnt==nncnt.ptr.p_int[i], "RBFV2BuildHierarchical: integrity check failed", _state); - for(k=0; k<=rowsperpoint-1; k++) - { - for(j=0; j<=cnt-1; j++) - { - val = rowvals.ptr.p_double[j*rowsperpoint+k]; - sparseset(&sparseacrs, i*rowsperpoint+k, rowindexes.ptr.p_int[j], val, _state); - avgdiagata = avgdiagata+ae_sqr(val, _state); - diagata.ptr.p_double[rowindexes.ptr.p_int[j]] = diagata.ptr.p_double[rowindexes.ptr.p_int[j]]+ae_sqr(val, _state); - } - } - - /* - * Handle possible termination requests - */ - if( *terminationrequest ) - { - - /* - * Request for termination was submitted, terminate immediately - */ - rbfv2_zerofill(s, nx, ny, bf, _state); - rep->terminationtype = 8; - *progress10000 = 10000; - ae_frame_leave(_state); - return; - } - } - avgdiagata = avgdiagata/nbasis; - rvectorsetlengthatleast(&prec, nbasis, _state); - for(j=0; j<=nbasis-1; j++) - { - prec.ptr.p_double[j] = 1/coalesce(ae_sqrt(diagata.ptr.p_double[j], _state), (double)(1), _state); - } - - /* - * solve - */ - maxits = coalescei(s->maxits, rbfv2_defaultmaxits, _state); - rvectorsetlengthatleast(&tmpx, nbasis, _state); - linlsqrcreate(n*rowsperpoint, nbasis, &linstate, _state); - linlsqrsetcond(&linstate, 0.0, 0.0, maxits, _state); - linlsqrsetlambdai(&linstate, ae_sqrt(s->lambdareg*avgdiagata, _state), _state); - for(j=0; j<=ny-1; j++) - { - for(i=0; i<=n*rowsperpoint-1; i++) - { - denseb1.ptr.p_double[i] = rhs.ptr.pp_double[i][j]; - } - linlsqrsetb(&linstate, &denseb1, _state); - linlsqrrestart(&linstate, _state); - linlsqrsetxrep(&linstate, ae_true, _state); - while(linlsqriteration(&linstate, _state)) - { - if( *terminationrequest ) - { - - /* - * Request for termination was submitted, terminate immediately - */ - rbfv2_zerofill(s, nx, ny, bf, _state); - rep->terminationtype = 8; - *progress10000 = 10000; - ae_frame_leave(_state); - return; - } - if( linstate.needmv ) - { - for(i=0; i<=nbasis-1; i++) - { - tmpx.ptr.p_double[i] = prec.ptr.p_double[i]*linstate.x.ptr.p_double[i]; - } - sparsemv(&sparseacrs, &tmpx, &linstate.mv, _state); - continue; - } - if( linstate.needmtv ) - { - sparsemtv(&sparseacrs, &linstate.x, &linstate.mtv, _state); - for(i=0; i<=nbasis-1; i++) - { - linstate.mtv.ptr.p_double[i] = prec.ptr.p_double[i]*linstate.mtv.ptr.p_double[i]; - } - continue; - } - if( linstate.xupdated ) - { - rprogress = (double)(0); - for(i=0; i<=levelidx-1; i++) - { - rprogress = rprogress+maxits*ny*avgrowsize.ptr.p_double[i]; - } - rprogress = rprogress+(linlsqrpeekiterationscount(&linstate, _state)+j*maxits)*avgrowsize.ptr.p_double[levelidx]; - rprogress = rprogress/(sumrowsize*maxits*ny); - rprogress = 10000*rprogress; - rprogress = ae_maxreal(rprogress, (double)(0), _state); - rprogress = ae_minreal(rprogress, (double)(10000), _state); - ae_assert(*progress10000<=ae_round(rprogress, _state)+1, "HRBF: integrity check failed (progress indicator) even after +1 safeguard correction", _state); - *progress10000 = ae_round(rprogress, _state); - continue; - } - ae_assert(ae_false, "HRBF: unexpected request from LSQR solver", _state); - } - linlsqrresults(&linstate, &densew1, &lsqrrep, _state); - ae_assert(lsqrrep.terminationtype>0, "RBFV2BuildHierarchical: integrity check failed", _state); - for(i=0; i<=nbasis-1; i++) - { - densew1.ptr.p_double[i] = prec.ptr.p_double[i]*densew1.ptr.p_double[i]; - } - for(i=0; i<=nbasis-1; i++) - { - offsi = cwrange.ptr.p_int[levelidx]+(nx+ny)*i; - cw.ptr.p_double[offsi+nx+j] = densew1.ptr.p_double[i]; - } - } - - /* - * Update residuals (far radius is used) - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - x0.ptr.p_double[j] = curxy.ptr.pp_double[i][j]; - } - rbfv2_designmatrixgeneraterow(&kdnodes, &kdsplits, &cw, &ri, &kdroots, &kdboxmin, &kdboxmax, &cwrange, nx, ny, nh, levelidx, bf, rbfv2farradius(bf, _state), rowsperpoint, penalty, &x0, &calcbuf, &vr2, &voffs, &rowindexes, &rowvals, &cnt, _state); - for(j=0; j<=cnt-1; j++) - { - offsj = cwrange.ptr.p_int[levelidx]+(nx+ny)*rowindexes.ptr.p_int[j]+nx; - for(k=0; k<=rowsperpoint-1; k++) - { - val = rowvals.ptr.p_double[j*rowsperpoint+k]; - for(k2=0; k2<=ny-1; k2++) - { - rhs.ptr.pp_double[i*rowsperpoint+k][k2] = rhs.ptr.pp_double[i*rowsperpoint+k][k2]-val*cw.ptr.p_double[offsj+k2]; - } - } - } - } - } - - /* - * Model is built. - * - * Copy local variables by swapping, global ones (ScaleVec) are copied - * explicitly. - */ - s->bf = bf; - s->nh = nh; - ae_swap_vectors(&s->ri, &ri); - ae_swap_vectors(&s->kdroots, &kdroots); - ae_swap_vectors(&s->kdnodes, &kdnodes); - ae_swap_vectors(&s->kdsplits, &kdsplits); - ae_swap_vectors(&s->kdboxmin, &kdboxmin); - ae_swap_vectors(&s->kdboxmax, &kdboxmax); - ae_swap_vectors(&s->cw, &cw); - ae_swap_matrices(&s->v, &v); - ae_vector_set_length(&s->s, nx, _state); - for(i=0; i<=nx-1; i++) - { - s->s.ptr.p_double[i] = scalevec->ptr.p_double[i]; - } - rep->terminationtype = 1; - - /* - * Calculate maximum and RMS errors - */ - rep->maxerror = (double)(0); - rep->rmserror = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=ny-1; j++) - { - rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(rhs.ptr.pp_double[i*rowsperpoint][j], _state), _state); - rep->rmserror = rep->rmserror+ae_sqr(rhs.ptr.pp_double[i*rowsperpoint][j], _state); - } - } - rep->rmserror = ae_sqrt(rep->rmserror/(n*ny), _state); - - /* - * Update progress reports - */ - *progress10000 = 10000; - ae_frame_leave(_state); -} - - -/************************************************************************* -Serializer: allocation - - -- ALGLIB -- - Copyright 02.02.2012 by Bochkanov Sergey -*************************************************************************/ -void rbfv2alloc(ae_serializer* s, rbfv2model* model, ae_state *_state) -{ - - - - /* - * Data - */ - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - allocrealarray(s, &model->ri, -1, _state); - allocrealarray(s, &model->s, -1, _state); - allocintegerarray(s, &model->kdroots, -1, _state); - allocintegerarray(s, &model->kdnodes, -1, _state); - allocrealarray(s, &model->kdsplits, -1, _state); - allocrealarray(s, &model->kdboxmin, -1, _state); - allocrealarray(s, &model->kdboxmax, -1, _state); - allocrealarray(s, &model->cw, -1, _state); - allocrealmatrix(s, &model->v, -1, -1, _state); -} - - -/************************************************************************* -Serializer: serialization - - -- ALGLIB -- - Copyright 02.02.2012 by Bochkanov Sergey -*************************************************************************/ -void rbfv2serialize(ae_serializer* s, rbfv2model* model, ae_state *_state) -{ - - - - /* - * Data - */ - ae_serializer_serialize_int(s, model->nx, _state); - ae_serializer_serialize_int(s, model->ny, _state); - ae_serializer_serialize_int(s, model->nh, _state); - ae_serializer_serialize_int(s, model->bf, _state); - serializerealarray(s, &model->ri, -1, _state); - serializerealarray(s, &model->s, -1, _state); - serializeintegerarray(s, &model->kdroots, -1, _state); - serializeintegerarray(s, &model->kdnodes, -1, _state); - serializerealarray(s, &model->kdsplits, -1, _state); - serializerealarray(s, &model->kdboxmin, -1, _state); - serializerealarray(s, &model->kdboxmax, -1, _state); - serializerealarray(s, &model->cw, -1, _state); - serializerealmatrix(s, &model->v, -1, -1, _state); -} - - -/************************************************************************* -Serializer: unserialization - - -- ALGLIB -- - Copyright 02.02.2012 by Bochkanov Sergey -*************************************************************************/ -void rbfv2unserialize(ae_serializer* s, - rbfv2model* model, - ae_state *_state) -{ - ae_int_t nx; - ae_int_t ny; - - _rbfv2model_clear(model); - - - /* - * Unserialize primary model parameters, initialize model. - * - * It is necessary to call RBFCreate() because some internal fields - * which are NOT unserialized will need initialization. - */ - ae_serializer_unserialize_int(s, &nx, _state); - ae_serializer_unserialize_int(s, &ny, _state); - rbfv2create(nx, ny, model, _state); - ae_serializer_unserialize_int(s, &model->nh, _state); - ae_serializer_unserialize_int(s, &model->bf, _state); - unserializerealarray(s, &model->ri, _state); - unserializerealarray(s, &model->s, _state); - unserializeintegerarray(s, &model->kdroots, _state); - unserializeintegerarray(s, &model->kdnodes, _state); - unserializerealarray(s, &model->kdsplits, _state); - unserializerealarray(s, &model->kdboxmin, _state); - unserializerealarray(s, &model->kdboxmax, _state); - unserializerealarray(s, &model->cw, _state); - unserializerealmatrix(s, &model->v, _state); -} - - -/************************************************************************* -Returns far radius for basis function type -*************************************************************************/ -double rbfv2farradius(ae_int_t bf, ae_state *_state) -{ - double result; - - - result = (double)(1); - if( bf==0 ) - { - result = 5.0; - } - if( bf==1 ) - { - result = (double)(3); - } - return result; -} - - -/************************************************************************* -Returns near radius for basis function type -*************************************************************************/ -double rbfv2nearradius(ae_int_t bf, ae_state *_state) -{ - double result; - - - result = (double)(1); - if( bf==0 ) - { - result = 3.0; - } - if( bf==1 ) - { - result = (double)(3); - } - return result; -} - - -/************************************************************************* -Returns basis function value. -Assumes that D2>=0 -*************************************************************************/ -double rbfv2basisfunc(ae_int_t bf, double d2, ae_state *_state) -{ - double v; - double result; - - - result = (double)(0); - if( bf==0 ) - { - result = ae_exp(-d2, _state); - return result; - } - if( bf==1 ) - { - - /* - * if D2<3: - * Exp(1)*Exp(-D2)*Exp(-1/(1-D2/9)) - * else: - * 0 - */ - v = 1-d2/9; - if( ae_fp_less_eq(v,(double)(0)) ) - { - result = (double)(0); - return result; - } - result = 2.718281828459045*ae_exp(-d2, _state)*ae_exp(-1/v, _state); - return result; - } - ae_assert(ae_false, "RBFV2BasisFunc: unknown BF type", _state); - return result; -} - - -/************************************************************************* -Returns basis function value, first and second derivatives -Assumes that D2>=0 -*************************************************************************/ -void rbfv2basisfuncdiff2(ae_int_t bf, - double d2, - double* f, - double* df, - double* d2f, - ae_state *_state) -{ - double v; - - *f = 0; - *df = 0; - *d2f = 0; - - if( bf==0 ) - { - *f = ae_exp(-d2, _state); - *df = -*f; - *d2f = *f; - return; - } - if( bf==1 ) - { - - /* - * if D2<3: - * F = Exp(1)*Exp(-D2)*Exp(-1/(1-D2/9)) - * dF = -F * [pow(D2/9-1,-2)/9 + 1] - * d2F = -dF * [pow(D2/9-1,-2)/9 + 1] + F*(2/81)*pow(D2/9-1,-3) - * else: - * 0 - */ - v = 1-d2/9; - if( ae_fp_less_eq(v,(double)(0)) ) - { - *f = (double)(0); - *df = (double)(0); - *d2f = (double)(0); - return; - } - *f = ae_exp((double)(1), _state)*ae_exp(-d2, _state)*ae_exp(-1/v, _state); - *df = -*f*(1/(9*v*v)+1); - *d2f = -*df*(1/(9*v*v)+1)+*f*((double)2/(double)81)/(v*v*v); - return; - } - ae_assert(ae_false, "RBFV2BasisFuncDiff2: unknown BF type", _state); -} - - -/************************************************************************* -This function calculates values of the RBF model in the given point. - -This function should be used when we have NY=1 (scalar function) and NX=1 -(1-dimensional space). - -This function returns 0.0 when: -* model is not initialized -* NX<>1 - *NY<>1 - -INPUT PARAMETERS: - S - RBF model - X0 - X-coordinate, finite number - -RESULT: - value of the model or 0.0 (as defined above) - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -double rbfv2calc1(rbfv2model* s, double x0, ae_state *_state) -{ - double result; - - - ae_assert(ae_isfinite(x0, _state), "RBFCalc1: invalid value for X0 (X0 is Inf)!", _state); - if( s->ny!=1||s->nx!=1 ) - { - result = (double)(0); - return result; - } - result = s->v.ptr.pp_double[0][0]*x0-s->v.ptr.pp_double[0][1]; - if( s->nh==0 ) - { - return result; - } - rbfv2_allocatecalcbuffer(s, &s->calcbuf, _state); - s->calcbuf.x123.ptr.p_double[0] = x0; - rbfv2tscalcbuf(s, &s->calcbuf, &s->calcbuf.x123, &s->calcbuf.y123, _state); - result = s->calcbuf.y123.ptr.p_double[0]; - return result; -} - - -/************************************************************************* -This function calculates values of the RBF model in the given point. - -This function should be used when we have NY=1 (scalar function) and NX=2 -(2-dimensional space). If you have 3-dimensional space, use RBFCalc3(). If -you have general situation (NX-dimensional space, NY-dimensional function) -you should use general, less efficient implementation RBFCalc(). - -If you want to calculate function values many times, consider using -RBFGridCalc2(), which is far more efficient than many subsequent calls to -RBFCalc2(). - -This function returns 0.0 when: -* model is not initialized -* NX<>2 - *NY<>1 - -INPUT PARAMETERS: - S - RBF model - X0 - first coordinate, finite number - X1 - second coordinate, finite number - -RESULT: - value of the model or 0.0 (as defined above) - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -double rbfv2calc2(rbfv2model* s, double x0, double x1, ae_state *_state) -{ - double result; - - - ae_assert(ae_isfinite(x0, _state), "RBFCalc2: invalid value for X0 (X0 is Inf)!", _state); - ae_assert(ae_isfinite(x1, _state), "RBFCalc2: invalid value for X1 (X1 is Inf)!", _state); - if( s->ny!=1||s->nx!=2 ) - { - result = (double)(0); - return result; - } - result = s->v.ptr.pp_double[0][0]*x0+s->v.ptr.pp_double[0][1]*x1+s->v.ptr.pp_double[0][2]; - if( s->nh==0 ) - { - return result; - } - rbfv2_allocatecalcbuffer(s, &s->calcbuf, _state); - s->calcbuf.x123.ptr.p_double[0] = x0; - s->calcbuf.x123.ptr.p_double[1] = x1; - rbfv2tscalcbuf(s, &s->calcbuf, &s->calcbuf.x123, &s->calcbuf.y123, _state); - result = s->calcbuf.y123.ptr.p_double[0]; - return result; -} - - -/************************************************************************* -This function calculates values of the RBF model in the given point. - -This function should be used when we have NY=1 (scalar function) and NX=3 -(3-dimensional space). If you have 2-dimensional space, use RBFCalc2(). If -you have general situation (NX-dimensional space, NY-dimensional function) -you should use general, less efficient implementation RBFCalc(). - -This function returns 0.0 when: -* model is not initialized -* NX<>3 - *NY<>1 - -INPUT PARAMETERS: - S - RBF model - X0 - first coordinate, finite number - X1 - second coordinate, finite number - X2 - third coordinate, finite number - -RESULT: - value of the model or 0.0 (as defined above) - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -double rbfv2calc3(rbfv2model* s, - double x0, - double x1, - double x2, - ae_state *_state) -{ - double result; - - - ae_assert(ae_isfinite(x0, _state), "RBFCalc3: invalid value for X0 (X0 is Inf or NaN)!", _state); - ae_assert(ae_isfinite(x1, _state), "RBFCalc3: invalid value for X1 (X1 is Inf or NaN)!", _state); - ae_assert(ae_isfinite(x2, _state), "RBFCalc3: invalid value for X2 (X2 is Inf or NaN)!", _state); - if( s->ny!=1||s->nx!=3 ) - { - result = (double)(0); - return result; - } - result = s->v.ptr.pp_double[0][0]*x0+s->v.ptr.pp_double[0][1]*x1+s->v.ptr.pp_double[0][2]*x2+s->v.ptr.pp_double[0][3]; - if( s->nh==0 ) - { - return result; - } - rbfv2_allocatecalcbuffer(s, &s->calcbuf, _state); - s->calcbuf.x123.ptr.p_double[0] = x0; - s->calcbuf.x123.ptr.p_double[1] = x1; - s->calcbuf.x123.ptr.p_double[2] = x2; - rbfv2tscalcbuf(s, &s->calcbuf, &s->calcbuf.x123, &s->calcbuf.y123, _state); - result = s->calcbuf.y123.ptr.p_double[0]; - return result; -} - - -/************************************************************************* -This function calculates values of the RBF model at the given point. - -Same as RBFCalc(), but does not reallocate Y when in is large enough to -store function values. - -INPUT PARAMETERS: - S - RBF model - X - coordinates, array[NX]. - X may have more than NX elements, in this case only - leading NX will be used. - Y - possibly preallocated array - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is not reallocated when it - is larger than NY. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfv2calcbuf(rbfv2model* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - - - rbfv2tscalcbuf(s, &s->calcbuf, x, y, _state); -} - - -/************************************************************************* -This function calculates values of the RBF model at the given point, using -external buffer object (internal temporaries of RBF model are not -modified). - -This function allows to use same RBF model object in different threads, -assuming that different threads use different instances of buffer -structure. - -INPUT PARAMETERS: - S - RBF model, may be shared between different threads - Buf - buffer object created for this particular instance of RBF - model with rbfcreatecalcbuffer(). - X - coordinates, array[NX]. - X may have more than NX elements, in this case only - leading NX will be used. - Y - possibly preallocated array - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is not reallocated when it - is larger than NY. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfv2tscalcbuf(rbfv2model* s, - rbfv2calcbuffer* buf, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t levelidx; - double rcur; - double rquery2; - double invrc2; - ae_int_t nx; - ae_int_t ny; - - - ae_assert(x->cnt>=s->nx, "RBFCalcBuf: Length(X)nx, _state), "RBFCalcBuf: X contains infinite or NaN values", _state); - nx = s->nx; - ny = s->ny; - - /* - * Handle linear term - */ - if( y->cntptr.p_double[i] = s->v.ptr.pp_double[i][nx]; - for(j=0; j<=nx-1; j++) - { - y->ptr.p_double[i] = y->ptr.p_double[i]+s->v.ptr.pp_double[i][j]*x->ptr.p_double[j]; - } - } - if( s->nh==0 ) - { - return; - } - - /* - * Handle nonlinear term - */ - rbfv2_allocatecalcbuffer(s, buf, _state); - for(j=0; j<=nx-1; j++) - { - buf->x.ptr.p_double[j] = x->ptr.p_double[j]/s->s.ptr.p_double[j]; - } - for(levelidx=0; levelidx<=s->nh-1; levelidx++) - { - - /* - * Prepare fields of Buf required by PartialCalcRec() - */ - buf->curdist2 = (double)(0); - for(j=0; j<=nx-1; j++) - { - buf->curboxmin.ptr.p_double[j] = s->kdboxmin.ptr.p_double[j]; - buf->curboxmax.ptr.p_double[j] = s->kdboxmax.ptr.p_double[j]; - if( ae_fp_less(buf->x.ptr.p_double[j],buf->curboxmin.ptr.p_double[j]) ) - { - buf->curdist2 = buf->curdist2+ae_sqr(buf->curboxmin.ptr.p_double[j]-buf->x.ptr.p_double[j], _state); - } - else - { - if( ae_fp_greater(buf->x.ptr.p_double[j],buf->curboxmax.ptr.p_double[j]) ) - { - buf->curdist2 = buf->curdist2+ae_sqr(buf->x.ptr.p_double[j]-buf->curboxmax.ptr.p_double[j], _state); - } - } - } - - /* - * Call PartialCalcRec() - */ - rcur = s->ri.ptr.p_double[levelidx]; - invrc2 = 1/(rcur*rcur); - rquery2 = ae_sqr(rcur*rbfv2farradius(s->bf, _state), _state); - rbfv2_partialcalcrec(s, buf, s->kdroots.ptr.p_int[levelidx], invrc2, rquery2, &buf->x, y, _state); - } -} - - -/************************************************************************* -This function calculates values of the RBF model at the regular grid. - -Grid have N0*N1 points, with Point[I,J] = (X0[I], X1[J]) - -This function returns 0.0 when: -* model is not initialized -* NX<>2 - *NY<>1 - -INPUT PARAMETERS: - S - RBF model - X0 - array of grid nodes, first coordinates, array[N0] - N0 - grid size (number of nodes) in the first dimension - X1 - array of grid nodes, second coordinates, array[N1] - N1 - grid size (number of nodes) in the second dimension - -OUTPUT PARAMETERS: - Y - function values, array[N0,N1]. Y is out-variable and - is reallocated by this function. - -NOTE: as a special exception, this function supports unordered arrays X0 - and X1. However, future versions may be more efficient for X0/X1 - ordered by ascending. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfv2gridcalc2(rbfv2model* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_matrix* y, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector cpx0; - ae_vector cpx1; - ae_vector dummyx2; - ae_vector dummyx3; - ae_vector dummyflag; - ae_vector p01; - ae_vector p11; - ae_vector p2; - ae_vector vy; - ae_int_t i; - ae_int_t j; - - ae_frame_make(_state, &_frame_block); - memset(&cpx0, 0, sizeof(cpx0)); - memset(&cpx1, 0, sizeof(cpx1)); - memset(&dummyx2, 0, sizeof(dummyx2)); - memset(&dummyx3, 0, sizeof(dummyx3)); - memset(&dummyflag, 0, sizeof(dummyflag)); - memset(&p01, 0, sizeof(p01)); - memset(&p11, 0, sizeof(p11)); - memset(&p2, 0, sizeof(p2)); - memset(&vy, 0, sizeof(vy)); - ae_matrix_clear(y); - ae_vector_init(&cpx0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cpx1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dummyx2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dummyx3, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dummyflag, 0, DT_BOOL, _state, ae_true); - ae_vector_init(&p01, 0, DT_INT, _state, ae_true); - ae_vector_init(&p11, 0, DT_INT, _state, ae_true); - ae_vector_init(&p2, 0, DT_INT, _state, ae_true); - ae_vector_init(&vy, 0, DT_REAL, _state, ae_true); - - ae_assert(n0>0, "RBFGridCalc2: invalid value for N0 (N0<=0)!", _state); - ae_assert(n1>0, "RBFGridCalc2: invalid value for N1 (N1<=0)!", _state); - ae_assert(x0->cnt>=n0, "RBFGridCalc2: Length(X0)cnt>=n1, "RBFGridCalc2: Length(X1)ptr.pp_double[i][j] = (double)(0); - } - } - if( s->ny!=1||s->nx!=2 ) - { - ae_frame_leave(_state); - return; - } - - /* - *create and sort arrays - */ - ae_vector_set_length(&cpx0, n0, _state); - for(i=0; i<=n0-1; i++) - { - cpx0.ptr.p_double[i] = x0->ptr.p_double[i]; - } - tagsort(&cpx0, n0, &p01, &p2, _state); - ae_vector_set_length(&cpx1, n1, _state); - for(i=0; i<=n1-1; i++) - { - cpx1.ptr.p_double[i] = x1->ptr.p_double[i]; - } - tagsort(&cpx1, n1, &p11, &p2, _state); - ae_vector_set_length(&dummyx2, 1, _state); - dummyx2.ptr.p_double[0] = (double)(0); - ae_vector_set_length(&dummyx3, 1, _state); - dummyx3.ptr.p_double[0] = (double)(0); - ae_vector_set_length(&vy, n0*n1, _state); - rbfv2gridcalcvx(s, &cpx0, n0, &cpx1, n1, &dummyx2, 1, &dummyx3, 1, &dummyflag, ae_false, &vy, _state); - for(i=0; i<=n0-1; i++) - { - for(j=0; j<=n1-1; j++) - { - y->ptr.pp_double[i][j] = vy.ptr.p_double[i+j*n0]; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function is used to perform gridded calculation for 2D, 3D or 4D -problems. It accepts parameters X0...X3 and counters N0...N3. If RBF model -has dimensionality less than 4, corresponding arrays should contain just -one element equal to zero, and corresponding N's should be equal to 1. - -NOTE: array Y should be preallocated by caller. - - -- ALGLIB -- - Copyright 12.07.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfv2gridcalcvx(rbfv2model* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Real */ ae_vector* x3, - ae_int_t n3, - /* Boolean */ ae_vector* flagy, - ae_bool sparsey, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nx; - ae_int_t ny; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_vector tx; - ae_vector ty; - ae_vector z; - ae_int_t dstoffs; - ae_int_t dummy; - rbfv2gridcalcbuffer bufseedv2; - ae_shared_pool bufpool; - ae_int_t rowidx; - ae_int_t rowcnt; - double v; - double rcur; - ae_int_t levelidx; - double searchradius2; - ae_int_t ntrials; - double avgfuncpernode; - hqrndstate rs; - ae_vector blocks0; - ae_vector blocks1; - ae_vector blocks2; - ae_vector blocks3; - ae_int_t blockscnt0; - ae_int_t blockscnt1; - ae_int_t blockscnt2; - ae_int_t blockscnt3; - double blockwidth0; - double blockwidth1; - double blockwidth2; - double blockwidth3; - ae_int_t maxblocksize; - - ae_frame_make(_state, &_frame_block); - memset(&tx, 0, sizeof(tx)); - memset(&ty, 0, sizeof(ty)); - memset(&z, 0, sizeof(z)); - memset(&bufseedv2, 0, sizeof(bufseedv2)); - memset(&bufpool, 0, sizeof(bufpool)); - memset(&rs, 0, sizeof(rs)); - memset(&blocks0, 0, sizeof(blocks0)); - memset(&blocks1, 0, sizeof(blocks1)); - memset(&blocks2, 0, sizeof(blocks2)); - memset(&blocks3, 0, sizeof(blocks3)); - ae_vector_init(&tx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ty, 0, DT_REAL, _state, ae_true); - ae_vector_init(&z, 0, DT_REAL, _state, ae_true); - _rbfv2gridcalcbuffer_init(&bufseedv2, _state, ae_true); - ae_shared_pool_init(&bufpool, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - ae_vector_init(&blocks0, 0, DT_INT, _state, ae_true); - ae_vector_init(&blocks1, 0, DT_INT, _state, ae_true); - ae_vector_init(&blocks2, 0, DT_INT, _state, ae_true); - ae_vector_init(&blocks3, 0, DT_INT, _state, ae_true); - - nx = s->nx; - ny = s->ny; - hqrndseed(532, 54734, &rs, _state); - - /* - * Perform integrity checks - */ - ae_assert(s->nx==2||s->nx==3, "RBFGridCalcVX: integrity check failed", _state); - ae_assert(s->nx>=4||((x3->cnt>=1&&ae_fp_eq(x3->ptr.p_double[0],(double)(0)))&&n3==1), "RBFGridCalcVX: integrity check failed", _state); - ae_assert(s->nx>=3||((x2->cnt>=1&&ae_fp_eq(x2->ptr.p_double[0],(double)(0)))&&n2==1), "RBFGridCalcVX: integrity check failed", _state); - ae_assert(s->nx>=2||((x1->cnt>=1&&ae_fp_eq(x1->ptr.p_double[0],(double)(0)))&&n1==1), "RBFGridCalcVX: integrity check failed", _state); - - /* - * Allocate arrays - */ - ae_assert(s->nx<=4, "RBFGridCalcVX: integrity check failed", _state); - ae_vector_set_length(&z, ny, _state); - ae_vector_set_length(&tx, 4, _state); - ae_vector_set_length(&ty, ny, _state); - - /* - * Calculate linear term - */ - rowcnt = n1*n2*n3; - for(rowidx=0; rowidx<=rowcnt-1; rowidx++) - { - - /* - * Calculate TX - current position - */ - k = rowidx; - tx.ptr.p_double[0] = (double)(0); - tx.ptr.p_double[1] = x1->ptr.p_double[k%n1]; - k = k/n1; - tx.ptr.p_double[2] = x2->ptr.p_double[k%n2]; - k = k/n2; - tx.ptr.p_double[3] = x3->ptr.p_double[k%n3]; - k = k/n3; - ae_assert(k==0, "RBFGridCalcVX: integrity check failed", _state); - for(j=0; j<=ny-1; j++) - { - v = s->v.ptr.pp_double[j][nx]; - for(k=1; k<=nx-1; k++) - { - v = v+tx.ptr.p_double[k]*s->v.ptr.pp_double[j][k]; - } - z.ptr.p_double[j] = v; - } - for(i=0; i<=n0-1; i++) - { - dstoffs = ny*(rowidx*n0+i); - if( sparsey&&!flagy->ptr.p_bool[rowidx*n0+i] ) - { - for(j=0; j<=ny-1; j++) - { - y->ptr.p_double[j+dstoffs] = (double)(0); - } - continue; - } - v = x0->ptr.p_double[i]; - for(j=0; j<=ny-1; j++) - { - y->ptr.p_double[j+dstoffs] = z.ptr.p_double[j]+v*s->v.ptr.pp_double[j][0]; - } - } - } - if( s->nh==0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Process RBF terms, layer by layer - */ - for(levelidx=0; levelidx<=s->nh-1; levelidx++) - { - rcur = s->ri.ptr.p_double[levelidx]; - blockwidth0 = (double)(1); - blockwidth1 = (double)(1); - blockwidth2 = (double)(1); - blockwidth3 = (double)(1); - if( nx>=1 ) - { - blockwidth0 = rcur*s->s.ptr.p_double[0]; - } - if( nx>=2 ) - { - blockwidth1 = rcur*s->s.ptr.p_double[1]; - } - if( nx>=3 ) - { - blockwidth2 = rcur*s->s.ptr.p_double[2]; - } - if( nx>=4 ) - { - blockwidth3 = rcur*s->s.ptr.p_double[3]; - } - maxblocksize = 8; - - /* - * Group grid nodes into blocks according to current radius - */ - ae_vector_set_length(&blocks0, n0+1, _state); - blockscnt0 = 0; - blocks0.ptr.p_int[0] = 0; - for(i=1; i<=n0-1; i++) - { - if( ae_fp_greater(x0->ptr.p_double[i]-x0->ptr.p_double[blocks0.ptr.p_int[blockscnt0]],blockwidth0)||i-blocks0.ptr.p_int[blockscnt0]>=maxblocksize ) - { - inc(&blockscnt0, _state); - blocks0.ptr.p_int[blockscnt0] = i; - } - } - inc(&blockscnt0, _state); - blocks0.ptr.p_int[blockscnt0] = n0; - ae_vector_set_length(&blocks1, n1+1, _state); - blockscnt1 = 0; - blocks1.ptr.p_int[0] = 0; - for(i=1; i<=n1-1; i++) - { - if( ae_fp_greater(x1->ptr.p_double[i]-x1->ptr.p_double[blocks1.ptr.p_int[blockscnt1]],blockwidth1)||i-blocks1.ptr.p_int[blockscnt1]>=maxblocksize ) - { - inc(&blockscnt1, _state); - blocks1.ptr.p_int[blockscnt1] = i; - } - } - inc(&blockscnt1, _state); - blocks1.ptr.p_int[blockscnt1] = n1; - ae_vector_set_length(&blocks2, n2+1, _state); - blockscnt2 = 0; - blocks2.ptr.p_int[0] = 0; - for(i=1; i<=n2-1; i++) - { - if( ae_fp_greater(x2->ptr.p_double[i]-x2->ptr.p_double[blocks2.ptr.p_int[blockscnt2]],blockwidth2)||i-blocks2.ptr.p_int[blockscnt2]>=maxblocksize ) - { - inc(&blockscnt2, _state); - blocks2.ptr.p_int[blockscnt2] = i; - } - } - inc(&blockscnt2, _state); - blocks2.ptr.p_int[blockscnt2] = n2; - ae_vector_set_length(&blocks3, n3+1, _state); - blockscnt3 = 0; - blocks3.ptr.p_int[0] = 0; - for(i=1; i<=n3-1; i++) - { - if( ae_fp_greater(x3->ptr.p_double[i]-x3->ptr.p_double[blocks3.ptr.p_int[blockscnt3]],blockwidth3)||i-blocks3.ptr.p_int[blockscnt3]>=maxblocksize ) - { - inc(&blockscnt3, _state); - blocks3.ptr.p_int[blockscnt3] = i; - } - } - inc(&blockscnt3, _state); - blocks3.ptr.p_int[blockscnt3] = n3; - - /* - * Prepare seed for shared pool - */ - rbfv2_allocatecalcbuffer(s, &bufseedv2.calcbuf, _state); - ae_shared_pool_set_seed(&bufpool, &bufseedv2, sizeof(bufseedv2), _rbfv2gridcalcbuffer_init, _rbfv2gridcalcbuffer_init_copy, _rbfv2gridcalcbuffer_destroy, _state); - - /* - * Determine average number of neighbor per node - */ - searchradius2 = ae_sqr(rcur*rbfv2farradius(s->bf, _state), _state); - ntrials = 100; - avgfuncpernode = 0.0; - for(i=0; i<=ntrials-1; i++) - { - tx.ptr.p_double[0] = x0->ptr.p_double[hqrnduniformi(&rs, n0, _state)]; - tx.ptr.p_double[1] = x1->ptr.p_double[hqrnduniformi(&rs, n1, _state)]; - tx.ptr.p_double[2] = x2->ptr.p_double[hqrnduniformi(&rs, n2, _state)]; - tx.ptr.p_double[3] = x3->ptr.p_double[hqrnduniformi(&rs, n3, _state)]; - rbfv2_preparepartialquery(&tx, &s->kdboxmin, &s->kdboxmax, nx, &bufseedv2.calcbuf, &dummy, _state); - avgfuncpernode = avgfuncpernode+(double)rbfv2_partialcountrec(&s->kdnodes, &s->kdsplits, &s->cw, nx, ny, &bufseedv2.calcbuf, s->kdroots.ptr.p_int[levelidx], searchradius2, &tx, _state)/(double)ntrials; - } - - /* - * Perform calculation in multithreaded mode - */ - rbfv2partialgridcalcrec(s, x0, n0, x1, n1, x2, n2, x3, n3, &blocks0, 0, blockscnt0, &blocks1, 0, blockscnt1, &blocks2, 0, blockscnt2, &blocks3, 0, blockscnt3, flagy, sparsey, levelidx, avgfuncpernode, &bufpool, y, _state); - } - ae_frame_leave(_state); -} - - -void rbfv2partialgridcalcrec(rbfv2model* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Real */ ae_vector* x3, - ae_int_t n3, - /* Integer */ ae_vector* blocks0, - ae_int_t block0a, - ae_int_t block0b, - /* Integer */ ae_vector* blocks1, - ae_int_t block1a, - ae_int_t block1b, - /* Integer */ ae_vector* blocks2, - ae_int_t block2a, - ae_int_t block2b, - /* Integer */ ae_vector* blocks3, - ae_int_t block3a, - ae_int_t block3b, - /* Boolean */ ae_vector* flagy, - ae_bool sparsey, - ae_int_t levelidx, - double avgfuncpernode, - ae_shared_pool* bufpool, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nx; - ae_int_t ny; - ae_int_t k; - ae_int_t l; - ae_int_t blkidx; - ae_int_t blkcnt; - ae_int_t nodeidx; - ae_int_t nodescnt; - ae_int_t rowidx; - ae_int_t rowscnt; - ae_int_t i0; - ae_int_t i1; - ae_int_t i2; - ae_int_t i3; - ae_int_t j0; - ae_int_t j1; - ae_int_t j2; - ae_int_t j3; - double rcur; - double invrc2; - double rquery2; - double rfar2; - ae_int_t dstoffs; - ae_int_t srcoffs; - ae_int_t dummy; - double rowwidth; - double maxrowwidth; - double problemcost; - ae_int_t maxbs; - ae_int_t midpoint; - ae_bool emptyrow; - rbfv2gridcalcbuffer *buf; - ae_smart_ptr _buf; - - ae_frame_make(_state, &_frame_block); - memset(&_buf, 0, sizeof(_buf)); - ae_smart_ptr_init(&_buf, (void**)&buf, _state, ae_true); - - nx = s->nx; - ny = s->ny; - - /* - * Integrity checks - */ - ae_assert(s->nx==2||s->nx==3, "RBFV2PartialGridCalcRec: integrity check failed", _state); - - /* - * Try to split large problem - */ - problemcost = s->ny*2*(avgfuncpernode+1); - problemcost = problemcost*(blocks0->ptr.p_int[block0b]-blocks0->ptr.p_int[block0a]); - problemcost = problemcost*(blocks1->ptr.p_int[block1b]-blocks1->ptr.p_int[block1a]); - problemcost = problemcost*(blocks2->ptr.p_int[block2b]-blocks2->ptr.p_int[block2a]); - problemcost = problemcost*(blocks3->ptr.p_int[block3b]-blocks3->ptr.p_int[block3a]); - maxbs = 0; - maxbs = ae_maxint(maxbs, block0b-block0a, _state); - maxbs = ae_maxint(maxbs, block1b-block1a, _state); - maxbs = ae_maxint(maxbs, block2b-block2a, _state); - maxbs = ae_maxint(maxbs, block3b-block3a, _state); - if( ae_fp_greater_eq(problemcost*rbfv2_complexitymultiplier,smpactivationlevel(_state)) ) - { - if( _trypexec_rbfv2partialgridcalcrec(s,x0,n0,x1,n1,x2,n2,x3,n3,blocks0,block0a,block0b,blocks1,block1a,block1b,blocks2,block2a,block2b,blocks3,block3a,block3b,flagy,sparsey,levelidx,avgfuncpernode,bufpool,y, _state) ) - { - ae_frame_leave(_state); - return; - } - } - if( ae_fp_greater_eq(problemcost*rbfv2_complexitymultiplier,spawnlevel(_state))&&maxbs>=2 ) - { - if( block0b-block0a==maxbs ) - { - midpoint = block0a+maxbs/2; - rbfv2partialgridcalcrec(s, x0, n0, x1, n1, x2, n2, x3, n3, blocks0, block0a, midpoint, blocks1, block1a, block1b, blocks2, block2a, block2b, blocks3, block3a, block3b, flagy, sparsey, levelidx, avgfuncpernode, bufpool, y, _state); - rbfv2partialgridcalcrec(s, x0, n0, x1, n1, x2, n2, x3, n3, blocks0, midpoint, block0b, blocks1, block1a, block1b, blocks2, block2a, block2b, blocks3, block3a, block3b, flagy, sparsey, levelidx, avgfuncpernode, bufpool, y, _state); - ae_frame_leave(_state); - return; - } - if( block1b-block1a==maxbs ) - { - midpoint = block1a+maxbs/2; - rbfv2partialgridcalcrec(s, x0, n0, x1, n1, x2, n2, x3, n3, blocks0, block0a, block0b, blocks1, block1a, midpoint, blocks2, block2a, block2b, blocks3, block3a, block3b, flagy, sparsey, levelidx, avgfuncpernode, bufpool, y, _state); - rbfv2partialgridcalcrec(s, x0, n0, x1, n1, x2, n2, x3, n3, blocks0, block0a, block0b, blocks1, midpoint, block1b, blocks2, block2a, block2b, blocks3, block3a, block3b, flagy, sparsey, levelidx, avgfuncpernode, bufpool, y, _state); - ae_frame_leave(_state); - return; - } - if( block2b-block2a==maxbs ) - { - midpoint = block2a+maxbs/2; - rbfv2partialgridcalcrec(s, x0, n0, x1, n1, x2, n2, x3, n3, blocks0, block0a, block0b, blocks1, block1a, block1b, blocks2, block2a, midpoint, blocks3, block3a, block3b, flagy, sparsey, levelidx, avgfuncpernode, bufpool, y, _state); - rbfv2partialgridcalcrec(s, x0, n0, x1, n1, x2, n2, x3, n3, blocks0, block0a, block0b, blocks1, block1a, block1b, blocks2, midpoint, block2b, blocks3, block3a, block3b, flagy, sparsey, levelidx, avgfuncpernode, bufpool, y, _state); - ae_frame_leave(_state); - return; - } - if( block3b-block3a==maxbs ) - { - midpoint = block3a+maxbs/2; - rbfv2partialgridcalcrec(s, x0, n0, x1, n1, x2, n2, x3, n3, blocks0, block0a, block0b, blocks1, block1a, block1b, blocks2, block2a, block2b, blocks3, block3a, midpoint, flagy, sparsey, levelidx, avgfuncpernode, bufpool, y, _state); - rbfv2partialgridcalcrec(s, x0, n0, x1, n1, x2, n2, x3, n3, blocks0, block0a, block0b, blocks1, block1a, block1b, blocks2, block2a, block2b, blocks3, midpoint, block3b, flagy, sparsey, levelidx, avgfuncpernode, bufpool, y, _state); - ae_frame_leave(_state); - return; - } - ae_assert(ae_false, "RBFV2PartialGridCalcRec: integrity check failed", _state); - } - - /* - * Retrieve buffer object from pool (it will be returned later) - */ - ae_shared_pool_retrieve(bufpool, &_buf, _state); - - /* - * Calculate RBF model - */ - ae_assert(nx<=4, "RBFV2PartialGridCalcRec: integrity check failed", _state); - ae_vector_set_length(&buf->tx, 4, _state); - ae_vector_set_length(&buf->cx, 4, _state); - ae_vector_set_length(&buf->ty, ny, _state); - rcur = s->ri.ptr.p_double[levelidx]; - invrc2 = 1/(rcur*rcur); - blkcnt = (block3b-block3a)*(block2b-block2a)*(block1b-block1a)*(block0b-block0a); - for(blkidx=0; blkidx<=blkcnt-1; blkidx++) - { - - /* - * Select block (I0,I1,I2,I3). - * - * NOTE: for problems with NX<4 corresponding I_? are zero. - */ - k = blkidx; - i0 = block0a+k%(block0b-block0a); - k = k/(block0b-block0a); - i1 = block1a+k%(block1b-block1a); - k = k/(block1b-block1a); - i2 = block2a+k%(block2b-block2a); - k = k/(block2b-block2a); - i3 = block3a+k%(block3b-block3a); - k = k/(block3b-block3a); - ae_assert(k==0, "RBFV2PartialGridCalcRec: integrity check failed", _state); - - /* - * We partitioned grid into blocks and selected block with - * index (I0,I1,I2,I3). This block is a 4D cube (some dimensions - * may be zero) of nodes with indexes (J0,J1,J2,J3), which is - * further partitioned into a set of rows, each row corresponding - * to indexes J1...J3 being fixed. - * - * We process block row by row, and each row may be handled - * by either "generic" (nodes are processed separately) or - * batch algorithm (that's the reason to use rows, after all). - * - * - * Process nodes of the block - */ - rowscnt = (blocks3->ptr.p_int[i3+1]-blocks3->ptr.p_int[i3])*(blocks2->ptr.p_int[i2+1]-blocks2->ptr.p_int[i2])*(blocks1->ptr.p_int[i1+1]-blocks1->ptr.p_int[i1]); - for(rowidx=0; rowidx<=rowscnt-1; rowidx++) - { - - /* - * Find out node indexes (*,J1,J2,J3). - * - * NOTE: for problems with NX<4 corresponding J_? are zero. - */ - k = rowidx; - j1 = blocks1->ptr.p_int[i1]+k%(blocks1->ptr.p_int[i1+1]-blocks1->ptr.p_int[i1]); - k = k/(blocks1->ptr.p_int[i1+1]-blocks1->ptr.p_int[i1]); - j2 = blocks2->ptr.p_int[i2]+k%(blocks2->ptr.p_int[i2+1]-blocks2->ptr.p_int[i2]); - k = k/(blocks2->ptr.p_int[i2+1]-blocks2->ptr.p_int[i2]); - j3 = blocks3->ptr.p_int[i3]+k%(blocks3->ptr.p_int[i3+1]-blocks3->ptr.p_int[i3]); - k = k/(blocks3->ptr.p_int[i3+1]-blocks3->ptr.p_int[i3]); - ae_assert(k==0, "RBFV2PartialGridCalcRec: integrity check failed", _state); - - /* - * Analyze row, skip completely empty rows - */ - nodescnt = blocks0->ptr.p_int[i0+1]-blocks0->ptr.p_int[i0]; - srcoffs = blocks0->ptr.p_int[i0]+(j1+(j2+j3*n2)*n1)*n0; - emptyrow = ae_true; - for(nodeidx=0; nodeidx<=nodescnt-1; nodeidx++) - { - emptyrow = emptyrow&&(sparsey&&!flagy->ptr.p_bool[srcoffs+nodeidx]); - } - if( emptyrow ) - { - continue; - } - - /* - * Process row - use either "batch" (rowsize>1) or "generic" - * (row size is 1) algorithm. - * - * NOTE: "generic" version may also be used as fallback code for - * situations when we do not want to use batch code. - */ - maxrowwidth = 0.5*rbfv2nearradius(s->bf, _state)*rcur*s->s.ptr.p_double[0]; - rowwidth = x0->ptr.p_double[blocks0->ptr.p_int[i0+1]-1]-x0->ptr.p_double[blocks0->ptr.p_int[i0]]; - if( nodescnt>1&&ae_fp_less_eq(rowwidth,maxrowwidth) ) - { - - /* - * "Batch" code which processes entire row at once, saving - * some time in kd-tree search code. - */ - rquery2 = ae_sqr(rcur*rbfv2farradius(s->bf, _state)+0.5*rowwidth/s->s.ptr.p_double[0], _state); - rfar2 = ae_sqr(rcur*rbfv2farradius(s->bf, _state), _state); - j0 = blocks0->ptr.p_int[i0]; - if( nx>0 ) - { - buf->cx.ptr.p_double[0] = (x0->ptr.p_double[j0]+0.5*rowwidth)/s->s.ptr.p_double[0]; - } - if( nx>1 ) - { - buf->cx.ptr.p_double[1] = x1->ptr.p_double[j1]/s->s.ptr.p_double[1]; - } - if( nx>2 ) - { - buf->cx.ptr.p_double[2] = x2->ptr.p_double[j2]/s->s.ptr.p_double[2]; - } - if( nx>3 ) - { - buf->cx.ptr.p_double[3] = x3->ptr.p_double[j3]/s->s.ptr.p_double[3]; - } - srcoffs = j0+(j1+(j2+j3*n2)*n1)*n0; - dstoffs = ny*srcoffs; - rvectorsetlengthatleast(&buf->rx, nodescnt, _state); - bvectorsetlengthatleast(&buf->rf, nodescnt, _state); - rvectorsetlengthatleast(&buf->ry, nodescnt*ny, _state); - for(nodeidx=0; nodeidx<=nodescnt-1; nodeidx++) - { - buf->rx.ptr.p_double[nodeidx] = x0->ptr.p_double[j0+nodeidx]/s->s.ptr.p_double[0]; - buf->rf.ptr.p_bool[nodeidx] = !sparsey||flagy->ptr.p_bool[srcoffs+nodeidx]; - } - for(k=0; k<=nodescnt*ny-1; k++) - { - buf->ry.ptr.p_double[k] = (double)(0); - } - rbfv2_preparepartialquery(&buf->cx, &s->kdboxmin, &s->kdboxmax, nx, &buf->calcbuf, &dummy, _state); - rbfv2_partialrowcalcrec(s, &buf->calcbuf, s->kdroots.ptr.p_int[levelidx], invrc2, rquery2, rfar2, &buf->cx, &buf->rx, &buf->rf, nodescnt, &buf->ry, _state); - for(k=0; k<=nodescnt*ny-1; k++) - { - y->ptr.p_double[dstoffs+k] = y->ptr.p_double[dstoffs+k]+buf->ry.ptr.p_double[k]; - } - } - else - { - - /* - * "Generic" code. Although we usually move here - * only when NodesCnt=1, we still use a loop on - * NodeIdx just to be able to use this branch as - * fallback code without any modifications. - */ - rquery2 = ae_sqr(rcur*rbfv2farradius(s->bf, _state), _state); - for(nodeidx=0; nodeidx<=nodescnt-1; nodeidx++) - { - - /* - * Prepare TX - current point - */ - j0 = blocks0->ptr.p_int[i0]+nodeidx; - if( nx>0 ) - { - buf->tx.ptr.p_double[0] = x0->ptr.p_double[j0]/s->s.ptr.p_double[0]; - } - if( nx>1 ) - { - buf->tx.ptr.p_double[1] = x1->ptr.p_double[j1]/s->s.ptr.p_double[1]; - } - if( nx>2 ) - { - buf->tx.ptr.p_double[2] = x2->ptr.p_double[j2]/s->s.ptr.p_double[2]; - } - if( nx>3 ) - { - buf->tx.ptr.p_double[3] = x3->ptr.p_double[j3]/s->s.ptr.p_double[3]; - } - - /* - * Evaluate and add to Y - */ - srcoffs = j0+(j1+(j2+j3*n2)*n1)*n0; - dstoffs = ny*srcoffs; - for(l=0; l<=ny-1; l++) - { - buf->ty.ptr.p_double[l] = (double)(0); - } - if( !sparsey||flagy->ptr.p_bool[srcoffs] ) - { - rbfv2_preparepartialquery(&buf->tx, &s->kdboxmin, &s->kdboxmax, nx, &buf->calcbuf, &dummy, _state); - rbfv2_partialcalcrec(s, &buf->calcbuf, s->kdroots.ptr.p_int[levelidx], invrc2, rquery2, &buf->tx, &buf->ty, _state); - } - for(l=0; l<=ny-1; l++) - { - y->ptr.p_double[dstoffs+l] = y->ptr.p_double[dstoffs+l]+buf->ty.ptr.p_double[l]; - } - } - } - } - } - - /* - * Recycle buffer object back to pool - */ - ae_shared_pool_recycle(bufpool, &_buf, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_rbfv2partialgridcalcrec(rbfv2model* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Real */ ae_vector* x3, - ae_int_t n3, - /* Integer */ ae_vector* blocks0, - ae_int_t block0a, - ae_int_t block0b, - /* Integer */ ae_vector* blocks1, - ae_int_t block1a, - ae_int_t block1b, - /* Integer */ ae_vector* blocks2, - ae_int_t block2a, - ae_int_t block2b, - /* Integer */ ae_vector* blocks3, - ae_int_t block3a, - ae_int_t block3b, - /* Boolean */ ae_vector* flagy, - ae_bool sparsey, - ae_int_t levelidx, - double avgfuncpernode, - ae_shared_pool* bufpool, - /* Real */ ae_vector* y, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -This function "unpacks" RBF model by extracting its coefficients. - -INPUT PARAMETERS: - S - RBF model - -OUTPUT PARAMETERS: - NX - dimensionality of argument - NY - dimensionality of the target function - XWR - model information, array[NC,NX+NY+1]. - One row of the array corresponds to one basis function: - * first NX columns - coordinates of the center - * next NY columns - weights, one per dimension of the - function being modelled - * last NX columns - radii, per dimension - NC - number of the centers - V - polynomial term , array[NY,NX+1]. One row per one - dimension of the function being modelled. First NX - elements are linear coefficients, V[NX] is equal to the - constant part. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfv2unpack(rbfv2model* s, - ae_int_t* nx, - ae_int_t* ny, - /* Real */ ae_matrix* xwr, - ae_int_t* nc, - /* Real */ ae_matrix* v, - ae_state *_state) -{ - ae_int_t i; - ae_int_t ncactual; - - *nx = 0; - *ny = 0; - ae_matrix_clear(xwr); - *nc = 0; - ae_matrix_clear(v); - - *nx = s->nx; - *ny = s->ny; - *nc = 0; - - /* - * Fill V - */ - ae_matrix_set_length(v, s->ny, s->nx+1, _state); - for(i=0; i<=s->ny-1; i++) - { - ae_v_move(&v->ptr.pp_double[i][0], 1, &s->v.ptr.pp_double[i][0], 1, ae_v_len(0,s->nx)); - } - - /* - * Fill XWR - */ - ae_assert(s->cw.cnt%(s->nx+s->ny)==0, "RBFV2Unpack: integrity error", _state); - *nc = s->cw.cnt/(s->nx+s->ny); - ncactual = 0; - if( *nc>0 ) - { - ae_matrix_set_length(xwr, *nc, s->nx+s->ny+s->nx, _state); - for(i=0; i<=s->nh-1; i++) - { - rbfv2_partialunpackrec(&s->kdnodes, &s->kdsplits, &s->cw, &s->s, s->nx, s->ny, s->kdroots.ptr.p_int[i], s->ri.ptr.p_double[i], xwr, &ncactual, _state); - } - } - ae_assert(*nc==ncactual, "RBFV2Unpack: integrity error", _state); -} - - -static ae_bool rbfv2_rbfv2buildlinearmodel(/* Real */ ae_matrix* x, - /* Real */ ae_matrix* y, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - ae_int_t modeltype, - /* Real */ ae_matrix* v, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector tmpy; - ae_matrix a; - double scaling; - ae_vector shifting; - double mn; - double mx; - ae_vector c; - lsfitreport rep; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t info; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&tmpy, 0, sizeof(tmpy)); - memset(&a, 0, sizeof(a)); - memset(&shifting, 0, sizeof(shifting)); - memset(&c, 0, sizeof(c)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_clear(v); - ae_vector_init(&tmpy, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&shifting, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c, 0, DT_REAL, _state, ae_true); - _lsfitreport_init(&rep, _state, ae_true); - - ae_assert(n>=0, "BuildLinearModel: N<0", _state); - ae_assert(nx>0, "BuildLinearModel: NX<=0", _state); - ae_assert(ny>0, "BuildLinearModel: NY<=0", _state); - - /* - * Handle degenerate case (N=0) - */ - result = ae_true; - ae_matrix_set_length(v, ny, nx+1, _state); - if( n==0 ) - { - for(j=0; j<=nx; j++) - { - for(i=0; i<=ny-1; i++) - { - v->ptr.pp_double[i][j] = (double)(0); - } - } - ae_frame_leave(_state); - return result; - } - - /* - * Allocate temporaries - */ - ae_vector_set_length(&tmpy, n, _state); - - /* - * General linear model. - */ - if( modeltype==1 ) - { - - /* - * Calculate scaling/shifting, transform variables, prepare LLS problem - */ - ae_matrix_set_length(&a, n, nx+1, _state); - ae_vector_set_length(&shifting, nx, _state); - scaling = (double)(0); - for(i=0; i<=nx-1; i++) - { - mn = x->ptr.pp_double[0][i]; - mx = mn; - for(j=1; j<=n-1; j++) - { - if( ae_fp_greater(mn,x->ptr.pp_double[j][i]) ) - { - mn = x->ptr.pp_double[j][i]; - } - if( ae_fp_less(mx,x->ptr.pp_double[j][i]) ) - { - mx = x->ptr.pp_double[j][i]; - } - } - scaling = ae_maxreal(scaling, mx-mn, _state); - shifting.ptr.p_double[i] = 0.5*(mx+mn); - } - if( ae_fp_eq(scaling,(double)(0)) ) - { - scaling = (double)(1); - } - else - { - scaling = 0.5*scaling; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - a.ptr.pp_double[i][j] = (x->ptr.pp_double[i][j]-shifting.ptr.p_double[j])/scaling; - } - } - for(i=0; i<=n-1; i++) - { - a.ptr.pp_double[i][nx] = (double)(1); - } - - /* - * Solve linear system in transformed variables, make backward - */ - for(i=0; i<=ny-1; i++) - { - for(j=0; j<=n-1; j++) - { - tmpy.ptr.p_double[j] = y->ptr.pp_double[j][i]; - } - lsfitlinear(&tmpy, &a, n, nx+1, &info, &c, &rep, _state); - if( info<=0 ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - for(j=0; j<=nx-1; j++) - { - v->ptr.pp_double[i][j] = c.ptr.p_double[j]/scaling; - } - v->ptr.pp_double[i][nx] = c.ptr.p_double[nx]; - for(j=0; j<=nx-1; j++) - { - v->ptr.pp_double[i][nx] = v->ptr.pp_double[i][nx]-shifting.ptr.p_double[j]*v->ptr.pp_double[i][j]; - } - for(j=0; j<=n-1; j++) - { - for(k=0; k<=nx-1; k++) - { - y->ptr.pp_double[j][i] = y->ptr.pp_double[j][i]-x->ptr.pp_double[j][k]*v->ptr.pp_double[i][k]; - } - y->ptr.pp_double[j][i] = y->ptr.pp_double[j][i]-v->ptr.pp_double[i][nx]; - } - } - ae_frame_leave(_state); - return result; - } - - /* - * Constant model, very simple - */ - if( modeltype==2 ) - { - for(i=0; i<=ny-1; i++) - { - for(j=0; j<=nx; j++) - { - v->ptr.pp_double[i][j] = (double)(0); - } - for(j=0; j<=n-1; j++) - { - v->ptr.pp_double[i][nx] = v->ptr.pp_double[i][nx]+y->ptr.pp_double[j][i]; - } - if( n>0 ) - { - v->ptr.pp_double[i][nx] = v->ptr.pp_double[i][nx]/n; - } - for(j=0; j<=n-1; j++) - { - y->ptr.pp_double[j][i] = y->ptr.pp_double[j][i]-v->ptr.pp_double[i][nx]; - } - } - ae_frame_leave(_state); - return result; - } - - /* - * Zero model - */ - ae_assert(modeltype==3, "BuildLinearModel: unknown model type", _state); - for(i=0; i<=ny-1; i++) - { - for(j=0; j<=nx; j++) - { - v->ptr.pp_double[i][j] = (double)(0); - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Reallocates calcBuf if necessary, reuses previously allocated space if -possible. - - -- ALGLIB -- - Copyright 20.06.2016 by Sergey Bochkanov -*************************************************************************/ -static void rbfv2_allocatecalcbuffer(rbfv2model* s, - rbfv2calcbuffer* buf, - ae_state *_state) -{ - - - if( buf->x.cntnx ) - { - ae_vector_set_length(&buf->x, s->nx, _state); - } - if( buf->curboxmin.cntnx ) - { - ae_vector_set_length(&buf->curboxmin, s->nx, _state); - } - if( buf->curboxmax.cntnx ) - { - ae_vector_set_length(&buf->curboxmax, s->nx, _state); - } - if( buf->x123.cntnx ) - { - ae_vector_set_length(&buf->x123, s->nx, _state); - } - if( buf->y123.cntny ) - { - ae_vector_set_length(&buf->y123, s->ny, _state); - } -} - - -/************************************************************************* -Extracts structure (and XY-values too) from kd-tree built for a small -subset of points and appends it to multi-tree. - - - -- ALGLIB -- - Copyright 20.06.2016 by Sergey Bochkanov -*************************************************************************/ -static void rbfv2_convertandappendtree(kdtree* curtree, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - /* Integer */ ae_vector* kdnodes, - /* Real */ ae_vector* kdsplits, - /* Real */ ae_vector* cw, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nodesbase; - ae_int_t splitsbase; - ae_int_t cwbase; - ae_vector localnodes; - ae_vector localsplits; - ae_vector localcw; - ae_matrix xybuf; - ae_int_t localnodessize; - ae_int_t localsplitssize; - ae_int_t localcwsize; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&localnodes, 0, sizeof(localnodes)); - memset(&localsplits, 0, sizeof(localsplits)); - memset(&localcw, 0, sizeof(localcw)); - memset(&xybuf, 0, sizeof(xybuf)); - ae_vector_init(&localnodes, 0, DT_INT, _state, ae_true); - ae_vector_init(&localsplits, 0, DT_REAL, _state, ae_true); - ae_vector_init(&localcw, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xybuf, 0, 0, DT_REAL, _state, ae_true); - - - /* - * Calculate base offsets - */ - nodesbase = kdnodes->cnt; - splitsbase = kdsplits->cnt; - cwbase = cw->cnt; - - /* - * Prepare local copy of tree - */ - ae_vector_set_length(&localnodes, n*rbfv2_maxnodesize, _state); - ae_vector_set_length(&localsplits, n, _state); - ae_vector_set_length(&localcw, (nx+ny)*n, _state); - localnodessize = 0; - localsplitssize = 0; - localcwsize = 0; - rbfv2_converttreerec(curtree, n, nx, ny, 0, nodesbase, splitsbase, cwbase, &localnodes, &localnodessize, &localsplits, &localsplitssize, &localcw, &localcwsize, &xybuf, _state); - - /* - * Append to multi-tree - */ - ivectorresize(kdnodes, kdnodes->cnt+localnodessize, _state); - rvectorresize(kdsplits, kdsplits->cnt+localsplitssize, _state); - rvectorresize(cw, cw->cnt+localcwsize, _state); - for(i=0; i<=localnodessize-1; i++) - { - kdnodes->ptr.p_int[nodesbase+i] = localnodes.ptr.p_int[i]; - } - for(i=0; i<=localsplitssize-1; i++) - { - kdsplits->ptr.p_double[splitsbase+i] = localsplits.ptr.p_double[i]; - } - for(i=0; i<=localcwsize-1; i++) - { - cw->ptr.p_double[cwbase+i] = localcw.ptr.p_double[i]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Recurrent tree conversion - - CurTree - tree to convert - N, NX, NY - dataset metrics - NodeOffset - offset of current tree node, 0 for root - NodesBase - a value which is added to intra-tree node indexes; - although this tree is stored in separate array, it - is intended to be stored in the larger tree, with - localNodes being moved to offset NodesBase. - SplitsBase - similarly, offset of localSplits in the final tree - CWBase - similarly, offset of localCW in the final tree -*************************************************************************/ -static void rbfv2_converttreerec(kdtree* curtree, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - ae_int_t nodeoffset, - ae_int_t nodesbase, - ae_int_t splitsbase, - ae_int_t cwbase, - /* Integer */ ae_vector* localnodes, - ae_int_t* localnodessize, - /* Real */ ae_vector* localsplits, - ae_int_t* localsplitssize, - /* Real */ ae_vector* localcw, - ae_int_t* localcwsize, - /* Real */ ae_matrix* xybuf, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t nodetype; - ae_int_t cnt; - ae_int_t d; - double s; - ae_int_t nodele; - ae_int_t nodege; - ae_int_t oldnodessize; - - - kdtreeexplorenodetype(curtree, nodeoffset, &nodetype, _state); - - /* - * Leaf node - */ - if( nodetype==0 ) - { - kdtreeexploreleaf(curtree, nodeoffset, xybuf, &cnt, _state); - ae_assert(localnodes->cnt>=*localnodessize+2, "ConvertTreeRec: integrity check failed", _state); - ae_assert(localcw->cnt>=*localcwsize+cnt*(nx+ny), "ConvertTreeRec: integrity check failed", _state); - localnodes->ptr.p_int[*localnodessize+0] = cnt; - localnodes->ptr.p_int[*localnodessize+1] = cwbase+(*localcwsize); - *localnodessize = *localnodessize+2; - for(i=0; i<=cnt-1; i++) - { - for(j=0; j<=nx+ny-1; j++) - { - localcw->ptr.p_double[*localcwsize+i*(nx+ny)+j] = xybuf->ptr.pp_double[i][j]; - } - } - *localcwsize = *localcwsize+cnt*(nx+ny); - return; - } - - /* - * Split node - */ - if( nodetype==1 ) - { - kdtreeexploresplit(curtree, nodeoffset, &d, &s, &nodele, &nodege, _state); - ae_assert(localnodes->cnt>=*localnodessize+rbfv2_maxnodesize, "ConvertTreeRec: integrity check failed", _state); - ae_assert(localsplits->cnt>=*localsplitssize+1, "ConvertTreeRec: integrity check failed", _state); - oldnodessize = *localnodessize; - localnodes->ptr.p_int[*localnodessize+0] = 0; - localnodes->ptr.p_int[*localnodessize+1] = d; - localnodes->ptr.p_int[*localnodessize+2] = splitsbase+(*localsplitssize); - localnodes->ptr.p_int[*localnodessize+3] = -1; - localnodes->ptr.p_int[*localnodessize+4] = -1; - *localnodessize = *localnodessize+5; - localsplits->ptr.p_double[*localsplitssize+0] = s; - *localsplitssize = *localsplitssize+1; - localnodes->ptr.p_int[oldnodessize+3] = nodesbase+(*localnodessize); - rbfv2_converttreerec(curtree, n, nx, ny, nodele, nodesbase, splitsbase, cwbase, localnodes, localnodessize, localsplits, localsplitssize, localcw, localcwsize, xybuf, _state); - localnodes->ptr.p_int[oldnodessize+4] = nodesbase+(*localnodessize); - rbfv2_converttreerec(curtree, n, nx, ny, nodege, nodesbase, splitsbase, cwbase, localnodes, localnodessize, localsplits, localsplitssize, localcw, localcwsize, xybuf, _state); - return; - } - - /* - * Integrity error - */ - ae_assert(ae_false, "ConvertTreeRec: integrity check failed", _state); -} - - -/************************************************************************* -This function performs partial calculation of hierarchical model: given -evaluation point X and partially computed value Y, it updates Y by values -computed using part of multi-tree given by RootIdx. - -INPUT PARAMETERS: - S - V2 model - Buf - calc-buffer, this function uses following fields: - * Buf.CurBoxMin - should be set by caller - * Buf.CurBoxMax - should be set by caller - * Buf.CurDist2 - squared distance from X to current bounding box, - should be set by caller - RootIdx - offset of partial kd-tree - InvR2 - 1/R^2, where R is basis function radius - QueryR2 - squared query radius, usually it is (R*FarRadius(BasisFunction))^2 - X - evaluation point, array[NX] - Y - partial value, array[NY] - -OUTPUT PARAMETERS - Y - updated partial value - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -static void rbfv2_partialcalcrec(rbfv2model* s, - rbfv2calcbuffer* buf, - ae_int_t rootidx, - double invr2, - double queryr2, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double ptdist2; - double v; - double v0; - double v1; - ae_int_t cwoffs; - ae_int_t cwcnt; - ae_int_t itemoffs; - double arg; - double val; - ae_int_t d; - double split; - ae_int_t childle; - ae_int_t childge; - ae_int_t childoffs; - ae_bool updatemin; - double prevdist2; - double t1; - ae_int_t nx; - ae_int_t ny; - - - nx = s->nx; - ny = s->ny; - - /* - * Helps to avoid spurious warnings - */ - val = (double)(0); - - /* - * Leaf node. - */ - if( s->kdnodes.ptr.p_int[rootidx]>0 ) - { - cwcnt = s->kdnodes.ptr.p_int[rootidx+0]; - cwoffs = s->kdnodes.ptr.p_int[rootidx+1]; - for(i=0; i<=cwcnt-1; i++) - { - - /* - * Calculate distance - */ - itemoffs = cwoffs+i*(nx+ny); - ptdist2 = (double)(0); - for(j=0; j<=nx-1; j++) - { - v = s->cw.ptr.p_double[itemoffs+j]-x->ptr.p_double[j]; - ptdist2 = ptdist2+v*v; - } - - /* - * Skip points if distance too large - */ - if( ptdist2>=queryr2 ) - { - continue; - } - - /* - * Update Y - */ - arg = ptdist2*invr2; - if( s->bf==0 ) - { - val = ae_exp(-arg, _state); - } - else - { - if( s->bf==1 ) - { - val = rbfv2basisfunc(s->bf, arg, _state); - } - else - { - ae_assert(ae_false, "PartialCalcRec: integrity check failed", _state); - } - } - itemoffs = itemoffs+nx; - for(j=0; j<=ny-1; j++) - { - y->ptr.p_double[j] = y->ptr.p_double[j]+val*s->cw.ptr.p_double[itemoffs+j]; - } - } - return; - } - - /* - * Simple split - */ - if( s->kdnodes.ptr.p_int[rootidx]==0 ) - { - - /* - * Load: - * * D dimension to split - * * Split split position - * * ChildLE, ChildGE - indexes of childs - */ - d = s->kdnodes.ptr.p_int[rootidx+1]; - split = s->kdsplits.ptr.p_double[s->kdnodes.ptr.p_int[rootidx+2]]; - childle = s->kdnodes.ptr.p_int[rootidx+3]; - childge = s->kdnodes.ptr.p_int[rootidx+4]; - - /* - * Navigate through childs - */ - for(i=0; i<=1; i++) - { - - /* - * Select child to process: - * * ChildOffs current child offset in Nodes[] - * * UpdateMin whether minimum or maximum value - * of bounding box is changed on update - */ - updatemin = i!=0; - if( i==0 ) - { - childoffs = childle; - } - else - { - childoffs = childge; - } - - /* - * Update bounding box and current distance - */ - prevdist2 = buf->curdist2; - t1 = x->ptr.p_double[d]; - if( updatemin ) - { - v = buf->curboxmin.ptr.p_double[d]; - if( t1<=split ) - { - v0 = v-t1; - if( v0<0 ) - { - v0 = (double)(0); - } - v1 = split-t1; - buf->curdist2 = buf->curdist2-v0*v0+v1*v1; - } - buf->curboxmin.ptr.p_double[d] = split; - } - else - { - v = buf->curboxmax.ptr.p_double[d]; - if( t1>=split ) - { - v0 = t1-v; - if( v0<0 ) - { - v0 = (double)(0); - } - v1 = t1-split; - buf->curdist2 = buf->curdist2-v0*v0+v1*v1; - } - buf->curboxmax.ptr.p_double[d] = split; - } - - /* - * Decide: to dive into cell or not to dive - */ - if( buf->curdist2curboxmin.ptr.p_double[d] = v; - } - else - { - buf->curboxmax.ptr.p_double[d] = v; - } - buf->curdist2 = prevdist2; - } - return; - } - - /* - * Integrity failure - */ - ae_assert(ae_false, "PartialCalcRec: integrity check failed", _state); -} - - -/************************************************************************* -This function performs same operation as partialcalcrec(), but for entire -row of the grid. "Row" is a set of nodes (x0,x1,x2,x3) which share x1..x3, -but have different x0's. (note: for 2D/3D problems x2..x3 are zero). - -Row is given by: -* central point XC, which is located at the center of the row, and used to - perform kd-tree requests -* set of x0 coordinates stored in RX array (array may be unordered, but it - is expected that spread of x0 is no more than R; function may be - inefficient for larger spreads). -* set of YFlag values stored in RF - -INPUT PARAMETERS: - S - V2 model - Buf - calc-buffer, this function uses following fields: - * Buf.CurBoxMin - should be set by caller - * Buf.CurBoxMax - should be set by caller - * Buf.CurDist2 - squared distance from X to current bounding box, - should be set by caller - RootIdx - offset of partial kd-tree - InvR2 - 1/R^2, where R is basis function radius - RQuery2 - squared query radius, usually it is (R*FarRadius(BasisFunction)+0.5*RowWidth)^2, - where RowWidth is its spatial extent (after scaling of - variables). This radius is used to perform initial query - for neighbors of CX. - RFar2 - squared far radius; far radius is used to perform actual - filtering of results of query made with RQuery2. - CX - central point, array[NX], used for queries - RX - x0 coordinates, array[RowSize] - RF - sparsity flags, array[RowSize] - RowSize - row size in elements - RY - input partial value, array[NY] - -OUTPUT PARAMETERS - RY - updated partial value (function adds its results to RY) - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -static void rbfv2_partialrowcalcrec(rbfv2model* s, - rbfv2calcbuffer* buf, - ae_int_t rootidx, - double invr2, - double rquery2, - double rfar2, - /* Real */ ae_vector* cx, - /* Real */ ae_vector* rx, - /* Boolean */ ae_vector* rf, - ae_int_t rowsize, - /* Real */ ae_vector* ry, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t i0; - ae_int_t i1; - double partialptdist2; - double ptdist2; - double v; - double v0; - double v1; - ae_int_t cwoffs; - ae_int_t cwcnt; - ae_int_t itemoffs; - ae_int_t woffs; - double val; - ae_int_t d; - double split; - ae_int_t childle; - ae_int_t childge; - ae_int_t childoffs; - ae_bool updatemin; - double prevdist2; - double t1; - ae_int_t nx; - ae_int_t ny; - - - nx = s->nx; - ny = s->ny; - - /* - * Leaf node. - */ - if( s->kdnodes.ptr.p_int[rootidx]>0 ) - { - cwcnt = s->kdnodes.ptr.p_int[rootidx+0]; - cwoffs = s->kdnodes.ptr.p_int[rootidx+1]; - for(i0=0; i0<=cwcnt-1; i0++) - { - - /* - * Calculate partial distance (components from 1 to NX-1) - */ - itemoffs = cwoffs+i0*(nx+ny); - partialptdist2 = (double)(0); - for(j=1; j<=nx-1; j++) - { - v = s->cw.ptr.p_double[itemoffs+j]-cx->ptr.p_double[j]; - partialptdist2 = partialptdist2+v*v; - } - - /* - * Process each element of the row - */ - for(i1=0; i1<=rowsize-1; i1++) - { - if( rf->ptr.p_bool[i1] ) - { - - /* - * Calculate distance - */ - v = s->cw.ptr.p_double[itemoffs]-rx->ptr.p_double[i1]; - ptdist2 = partialptdist2+v*v; - - /* - * Skip points if distance too large - */ - if( ptdist2>=rfar2 ) - { - continue; - } - - /* - * Update Y - */ - val = rbfv2basisfunc(s->bf, ptdist2*invr2, _state); - woffs = itemoffs+nx; - for(j=0; j<=ny-1; j++) - { - ry->ptr.p_double[j+i1*ny] = ry->ptr.p_double[j+i1*ny]+val*s->cw.ptr.p_double[woffs+j]; - } - } - } - } - return; - } - - /* - * Simple split - */ - if( s->kdnodes.ptr.p_int[rootidx]==0 ) - { - - /* - * Load: - * * D dimension to split - * * Split split position - * * ChildLE, ChildGE - indexes of childs - */ - d = s->kdnodes.ptr.p_int[rootidx+1]; - split = s->kdsplits.ptr.p_double[s->kdnodes.ptr.p_int[rootidx+2]]; - childle = s->kdnodes.ptr.p_int[rootidx+3]; - childge = s->kdnodes.ptr.p_int[rootidx+4]; - - /* - * Navigate through childs - */ - for(i=0; i<=1; i++) - { - - /* - * Select child to process: - * * ChildOffs current child offset in Nodes[] - * * UpdateMin whether minimum or maximum value - * of bounding box is changed on update - */ - updatemin = i!=0; - if( i==0 ) - { - childoffs = childle; - } - else - { - childoffs = childge; - } - - /* - * Update bounding box and current distance - */ - prevdist2 = buf->curdist2; - t1 = cx->ptr.p_double[d]; - if( updatemin ) - { - v = buf->curboxmin.ptr.p_double[d]; - if( t1<=split ) - { - v0 = v-t1; - if( v0<0 ) - { - v0 = (double)(0); - } - v1 = split-t1; - buf->curdist2 = buf->curdist2-v0*v0+v1*v1; - } - buf->curboxmin.ptr.p_double[d] = split; - } - else - { - v = buf->curboxmax.ptr.p_double[d]; - if( t1>=split ) - { - v0 = t1-v; - if( v0<0 ) - { - v0 = (double)(0); - } - v1 = t1-split; - buf->curdist2 = buf->curdist2-v0*v0+v1*v1; - } - buf->curboxmax.ptr.p_double[d] = split; - } - - /* - * Decide: to dive into cell or not to dive - */ - if( buf->curdist2curboxmin.ptr.p_double[d] = v; - } - else - { - buf->curboxmax.ptr.p_double[d] = v; - } - buf->curdist2 = prevdist2; - } - return; - } - - /* - * Integrity failure - */ - ae_assert(ae_false, "PartialCalcRec: integrity check failed", _state); -} - - -/************************************************************************* -This function prepares partial query - -INPUT PARAMETERS: - X - query point - kdBoxMin, kdBoxMax - current bounding box - NX - problem size - Buf - preallocated buffer; this function just loads data, but - does not allocate place for them. - Cnt - counter variable which is set to zery by this function, as - convenience, and to remember about necessity to zero counter - prior to calling partialqueryrec(). - -OUTPUT PARAMETERS - Buf - calc-buffer: - * Buf.CurBoxMin - current box - * Buf.CurBoxMax - current box - * Buf.CurDist2 - squared distance from X to current box - Cnt - set to zero - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -static void rbfv2_preparepartialquery(/* Real */ ae_vector* x, - /* Real */ ae_vector* kdboxmin, - /* Real */ ae_vector* kdboxmax, - ae_int_t nx, - rbfv2calcbuffer* buf, - ae_int_t* cnt, - ae_state *_state) -{ - ae_int_t j; - - - *cnt = 0; - buf->curdist2 = (double)(0); - for(j=0; j<=nx-1; j++) - { - buf->curboxmin.ptr.p_double[j] = kdboxmin->ptr.p_double[j]; - buf->curboxmax.ptr.p_double[j] = kdboxmax->ptr.p_double[j]; - if( ae_fp_less(x->ptr.p_double[j],buf->curboxmin.ptr.p_double[j]) ) - { - buf->curdist2 = buf->curdist2+ae_sqr(buf->curboxmin.ptr.p_double[j]-x->ptr.p_double[j], _state); - } - else - { - if( ae_fp_greater(x->ptr.p_double[j],buf->curboxmax.ptr.p_double[j]) ) - { - buf->curdist2 = buf->curdist2+ae_sqr(x->ptr.p_double[j]-buf->curboxmax.ptr.p_double[j], _state); - } - } - } -} - - -/************************************************************************* -This function performs partial (for just one subtree of multi-tree) query -for neighbors located in R-sphere around X. It returns squared distances -from X to points and offsets in S.CW[] array for points being found. - -INPUT PARAMETERS: - kdNodes, kdSplits, CW, NX, NY - corresponding fields of V2 model - Buf - calc-buffer, this function uses following fields: - * Buf.CurBoxMin - should be set by caller - * Buf.CurBoxMax - should be set by caller - * Buf.CurDist2 - squared distance from X to current - bounding box, should be set by caller - You may use preparepartialquery() function to initialize - these fields. - RootIdx - offset of partial kd-tree - QueryR2 - squared query radius - X - array[NX], point being queried - R2 - preallocated output buffer; it is caller's responsibility - to make sure that R2 has enough space. - Offs - preallocated output buffer; it is caller's responsibility - to make sure that Offs has enough space. - K - MUST BE ZERO ON INITIAL CALL. This variable is incremented, - not set. So, any no-zero value will result in the incorrect - points count being returned. - -OUTPUT PARAMETERS - R2 - squared distances in first K elements - Offs - offsets in S.CW in first K elements - K - points count - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -static void rbfv2_partialqueryrec(/* Integer */ ae_vector* kdnodes, - /* Real */ ae_vector* kdsplits, - /* Real */ ae_vector* cw, - ae_int_t nx, - ae_int_t ny, - rbfv2calcbuffer* buf, - ae_int_t rootidx, - double queryr2, - /* Real */ ae_vector* x, - /* Real */ ae_vector* r2, - /* Integer */ ae_vector* offs, - ae_int_t* k, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double ptdist2; - double v; - ae_int_t cwoffs; - ae_int_t cwcnt; - ae_int_t itemoffs; - ae_int_t d; - double split; - ae_int_t childle; - ae_int_t childge; - ae_int_t childoffs; - ae_bool updatemin; - double prevdist2; - double t1; - - - - /* - * Leaf node. - */ - if( kdnodes->ptr.p_int[rootidx]>0 ) - { - cwcnt = kdnodes->ptr.p_int[rootidx+0]; - cwoffs = kdnodes->ptr.p_int[rootidx+1]; - for(i=0; i<=cwcnt-1; i++) - { - - /* - * Calculate distance - */ - itemoffs = cwoffs+i*(nx+ny); - ptdist2 = (double)(0); - for(j=0; j<=nx-1; j++) - { - v = cw->ptr.p_double[itemoffs+j]-x->ptr.p_double[j]; - ptdist2 = ptdist2+v*v; - } - - /* - * Skip points if distance too large - */ - if( ae_fp_greater_eq(ptdist2,queryr2) ) - { - continue; - } - - /* - * Output - */ - r2->ptr.p_double[*k] = ptdist2; - offs->ptr.p_int[*k] = itemoffs; - *k = *k+1; - } - return; - } - - /* - * Simple split - */ - if( kdnodes->ptr.p_int[rootidx]==0 ) - { - - /* - * Load: - * * D dimension to split - * * Split split position - * * ChildLE, ChildGE - indexes of childs - */ - d = kdnodes->ptr.p_int[rootidx+1]; - split = kdsplits->ptr.p_double[kdnodes->ptr.p_int[rootidx+2]]; - childle = kdnodes->ptr.p_int[rootidx+3]; - childge = kdnodes->ptr.p_int[rootidx+4]; - - /* - * Navigate through childs - */ - for(i=0; i<=1; i++) - { - - /* - * Select child to process: - * * ChildOffs current child offset in Nodes[] - * * UpdateMin whether minimum or maximum value - * of bounding box is changed on update - */ - updatemin = i!=0; - if( i==0 ) - { - childoffs = childle; - } - else - { - childoffs = childge; - } - - /* - * Update bounding box and current distance - */ - prevdist2 = buf->curdist2; - t1 = x->ptr.p_double[d]; - if( updatemin ) - { - v = buf->curboxmin.ptr.p_double[d]; - if( ae_fp_less_eq(t1,split) ) - { - buf->curdist2 = buf->curdist2-ae_sqr(ae_maxreal(v-t1, (double)(0), _state), _state)+ae_sqr(split-t1, _state); - } - buf->curboxmin.ptr.p_double[d] = split; - } - else - { - v = buf->curboxmax.ptr.p_double[d]; - if( ae_fp_greater_eq(t1,split) ) - { - buf->curdist2 = buf->curdist2-ae_sqr(ae_maxreal(t1-v, (double)(0), _state), _state)+ae_sqr(t1-split, _state); - } - buf->curboxmax.ptr.p_double[d] = split; - } - - /* - * Decide: to dive into cell or not to dive - */ - if( ae_fp_less(buf->curdist2,queryr2) ) - { - rbfv2_partialqueryrec(kdnodes, kdsplits, cw, nx, ny, buf, childoffs, queryr2, x, r2, offs, k, _state); - } - - /* - * Restore bounding box and distance - */ - if( updatemin ) - { - buf->curboxmin.ptr.p_double[d] = v; - } - else - { - buf->curboxmax.ptr.p_double[d] = v; - } - buf->curdist2 = prevdist2; - } - return; - } - - /* - * Integrity failure - */ - ae_assert(ae_false, "PartialQueryRec: integrity check failed", _state); -} - - -/************************************************************************* -This function performs partial (for just one subtree of multi-tree) -counting of neighbors located in R-sphere around X. - -This function does not guarantee consistency of results with other partial -queries, it should be used only to get approximate estimates (well, we do -not use approximate algorithms, but rounding errors may give us -inconsistent results in just-at-the-boundary cases). - -INPUT PARAMETERS: - kdNodes, kdSplits, CW, NX, NY - corresponding fields of V2 model - Buf - calc-buffer, this function uses following fields: - * Buf.CurBoxMin - should be set by caller - * Buf.CurBoxMax - should be set by caller - * Buf.CurDist2 - squared distance from X to current - bounding box, should be set by caller - You may use preparepartialquery() function to initialize - these fields. - RootIdx - offset of partial kd-tree - QueryR2 - squared query radius - X - array[NX], point being queried - -RESULT: - points count - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -static ae_int_t rbfv2_partialcountrec(/* Integer */ ae_vector* kdnodes, - /* Real */ ae_vector* kdsplits, - /* Real */ ae_vector* cw, - ae_int_t nx, - ae_int_t ny, - rbfv2calcbuffer* buf, - ae_int_t rootidx, - double queryr2, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double ptdist2; - double v; - ae_int_t cwoffs; - ae_int_t cwcnt; - ae_int_t itemoffs; - ae_int_t d; - double split; - ae_int_t childle; - ae_int_t childge; - ae_int_t childoffs; - ae_bool updatemin; - double prevdist2; - double t1; - ae_int_t result; - - - result = 0; - - /* - * Leaf node. - */ - if( kdnodes->ptr.p_int[rootidx]>0 ) - { - cwcnt = kdnodes->ptr.p_int[rootidx+0]; - cwoffs = kdnodes->ptr.p_int[rootidx+1]; - for(i=0; i<=cwcnt-1; i++) - { - - /* - * Calculate distance - */ - itemoffs = cwoffs+i*(nx+ny); - ptdist2 = (double)(0); - for(j=0; j<=nx-1; j++) - { - v = cw->ptr.p_double[itemoffs+j]-x->ptr.p_double[j]; - ptdist2 = ptdist2+v*v; - } - - /* - * Skip points if distance too large - */ - if( ae_fp_greater_eq(ptdist2,queryr2) ) - { - continue; - } - - /* - * Output - */ - result = result+1; - } - return result; - } - - /* - * Simple split - */ - if( kdnodes->ptr.p_int[rootidx]==0 ) - { - - /* - * Load: - * * D dimension to split - * * Split split position - * * ChildLE, ChildGE - indexes of childs - */ - d = kdnodes->ptr.p_int[rootidx+1]; - split = kdsplits->ptr.p_double[kdnodes->ptr.p_int[rootidx+2]]; - childle = kdnodes->ptr.p_int[rootidx+3]; - childge = kdnodes->ptr.p_int[rootidx+4]; - - /* - * Navigate through childs - */ - for(i=0; i<=1; i++) - { - - /* - * Select child to process: - * * ChildOffs current child offset in Nodes[] - * * UpdateMin whether minimum or maximum value - * of bounding box is changed on update - */ - updatemin = i!=0; - if( i==0 ) - { - childoffs = childle; - } - else - { - childoffs = childge; - } - - /* - * Update bounding box and current distance - */ - prevdist2 = buf->curdist2; - t1 = x->ptr.p_double[d]; - if( updatemin ) - { - v = buf->curboxmin.ptr.p_double[d]; - if( ae_fp_less_eq(t1,split) ) - { - buf->curdist2 = buf->curdist2-ae_sqr(ae_maxreal(v-t1, (double)(0), _state), _state)+ae_sqr(split-t1, _state); - } - buf->curboxmin.ptr.p_double[d] = split; - } - else - { - v = buf->curboxmax.ptr.p_double[d]; - if( ae_fp_greater_eq(t1,split) ) - { - buf->curdist2 = buf->curdist2-ae_sqr(ae_maxreal(t1-v, (double)(0), _state), _state)+ae_sqr(t1-split, _state); - } - buf->curboxmax.ptr.p_double[d] = split; - } - - /* - * Decide: to dive into cell or not to dive - */ - if( ae_fp_less(buf->curdist2,queryr2) ) - { - result = result+rbfv2_partialcountrec(kdnodes, kdsplits, cw, nx, ny, buf, childoffs, queryr2, x, _state); - } - - /* - * Restore bounding box and distance - */ - if( updatemin ) - { - buf->curboxmin.ptr.p_double[d] = v; - } - else - { - buf->curboxmax.ptr.p_double[d] = v; - } - buf->curdist2 = prevdist2; - } - return result; - } - - /* - * Integrity failure - */ - ae_assert(ae_false, "PartialCountRec: integrity check failed", _state); - return result; -} - - -/************************************************************************* -This function performs partial (for just one subtree of multi-tree) unpack -for RBF model. It appends center coordinates, weights and per-dimension -radii (according to current scaling) to preallocated output array. - -INPUT PARAMETERS: - kdNodes, kdSplits, CW, S, NX, NY - corresponding fields of V2 model - RootIdx - offset of partial kd-tree - R - radius for current partial tree - XWR - preallocated output buffer; it is caller's responsibility - to make sure that XWR has enough space. First K rows are - already occupied. - K - number of already occupied rows in XWR. - -OUTPUT PARAMETERS - XWR - updated XWR - K - updated rows count - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -static void rbfv2_partialunpackrec(/* Integer */ ae_vector* kdnodes, - /* Real */ ae_vector* kdsplits, - /* Real */ ae_vector* cw, - /* Real */ ae_vector* s, - ae_int_t nx, - ae_int_t ny, - ae_int_t rootidx, - double r, - /* Real */ ae_matrix* xwr, - ae_int_t* k, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t childle; - ae_int_t childge; - ae_int_t itemoffs; - ae_int_t cwoffs; - ae_int_t cwcnt; - - - - /* - * Leaf node. - */ - if( kdnodes->ptr.p_int[rootidx]>0 ) - { - cwcnt = kdnodes->ptr.p_int[rootidx+0]; - cwoffs = kdnodes->ptr.p_int[rootidx+1]; - for(i=0; i<=cwcnt-1; i++) - { - itemoffs = cwoffs+i*(nx+ny); - for(j=0; j<=nx+ny-1; j++) - { - xwr->ptr.pp_double[*k][j] = cw->ptr.p_double[itemoffs+j]; - } - for(j=0; j<=nx-1; j++) - { - xwr->ptr.pp_double[*k][j] = xwr->ptr.pp_double[*k][j]*s->ptr.p_double[j]; - } - for(j=0; j<=nx-1; j++) - { - xwr->ptr.pp_double[*k][nx+ny+j] = r*s->ptr.p_double[j]; - } - *k = *k+1; - } - return; - } - - /* - * Simple split - */ - if( kdnodes->ptr.p_int[rootidx]==0 ) - { - - /* - * Load: - * * ChildLE, ChildGE - indexes of childs - */ - childle = kdnodes->ptr.p_int[rootidx+3]; - childge = kdnodes->ptr.p_int[rootidx+4]; - - /* - * Process both parts of split - */ - rbfv2_partialunpackrec(kdnodes, kdsplits, cw, s, nx, ny, childle, r, xwr, k, _state); - rbfv2_partialunpackrec(kdnodes, kdsplits, cw, s, nx, ny, childge, r, xwr, k, _state); - return; - } - - /* - * Integrity failure - */ - ae_assert(ae_false, "PartialUnpackRec: integrity check failed", _state); -} - - -/************************************************************************* -This function returns size of design matrix row for evaluation point X0, -given: -* query radius multiplier (either RBFV2NearRadius() or RBFV2FarRadius()) -* hierarchy level: value in [0,NH) for single-level model, or negative - value for multilevel model (all levels of hierarchy in single matrix, - like one used by nonnegative RBF) - -INPUT PARAMETERS: - kdNodes, kdSplits, CW, Ri, kdRoots, kdBoxMin, kdBoxMax, NX, NY, NH - corresponding fields of V2 model - Level - value in [0,NH) for single-level design matrix, negative - value for multilevel design matrix - RCoeff - radius coefficient, either RBFV2NearRadius() or RBFV2FarRadius() - X0 - query point - CalcBuf - buffer for PreparePartialQuery(), allocated by caller - -RESULT: - row size - - -- ALGLIB -- - Copyright 28.09.2016 by Bochkanov Sergey -*************************************************************************/ -static ae_int_t rbfv2_designmatrixrowsize(/* Integer */ ae_vector* kdnodes, - /* Real */ ae_vector* kdsplits, - /* Real */ ae_vector* cw, - /* Real */ ae_vector* ri, - /* Integer */ ae_vector* kdroots, - /* Real */ ae_vector* kdboxmin, - /* Real */ ae_vector* kdboxmax, - ae_int_t nx, - ae_int_t ny, - ae_int_t nh, - ae_int_t level, - double rcoeff, - /* Real */ ae_vector* x0, - rbfv2calcbuffer* calcbuf, - ae_state *_state) -{ - ae_int_t dummy; - ae_int_t levelidx; - ae_int_t level0; - ae_int_t level1; - double curradius2; - ae_int_t result; - - - ae_assert(nh>0, "DesignMatrixRowSize: integrity failure", _state); - if( level>=0 ) - { - level0 = level; - level1 = level; - } - else - { - level0 = 0; - level1 = nh-1; - } - result = 0; - for(levelidx=level0; levelidx<=level1; levelidx++) - { - curradius2 = ae_sqr(ri->ptr.p_double[levelidx]*rcoeff, _state); - rbfv2_preparepartialquery(x0, kdboxmin, kdboxmax, nx, calcbuf, &dummy, _state); - result = result+rbfv2_partialcountrec(kdnodes, kdsplits, cw, nx, ny, calcbuf, kdroots->ptr.p_int[levelidx], curradius2, x0, _state); - } - return result; -} - - -/************************************************************************* -This function generates design matrix row for evaluation point X0, given: -* query radius multiplier (either RBFV2NearRadius() or RBFV2FarRadius()) -* hierarchy level: value in [0,NH) for single-level model, or negative - value for multilevel model (all levels of hierarchy in single matrix, - like one used by nonnegative RBF) - -INPUT PARAMETERS: - kdNodes, kdSplits, CW, Ri, kdRoots, kdBoxMin, kdBoxMax, NX, NY, NH - corresponding fields of V2 model - - CWRange - internal array[NH+1] used by RBF construction function, - stores ranges of CW occupied by NH trees. - Level - value in [0,NH) for single-level design matrix, negative - value for multilevel design matrix - BF - basis function type - RCoeff - radius coefficient, either RBFV2NearRadius() or RBFV2FarRadius() - RowsPerPoint-equal to: - * 1 for unpenalized regression model - * 1+NX for basic form of nonsmoothness penalty - Penalty - nonsmoothness penalty coefficient - - X0 - query point - - CalcBuf - buffer for PreparePartialQuery(), allocated by caller - R2 - preallocated temporary buffer, size is at least NPoints; - it is caller's responsibility to make sure that R2 has enough space. - Offs - preallocated temporary buffer; size is at least NPoints; - it is caller's responsibility to make sure that Offs has enough space. - K - MUST BE ZERO ON INITIAL CALL. This variable is incremented, - not set. So, any no-zero value will result in the incorrect - points count being returned. - RowIdx - preallocated array, at least RowSize elements - RowVal - preallocated array, at least RowSize*RowsPerPoint elements - -RESULT: - RowIdx - RowSize elements are filled with column indexes of non-zero - design matrix entries - RowVal - RowSize*RowsPerPoint elements are filled with design matrix - values, with column RowIdx[0] being stored in first RowsPerPoint - elements of RowVal, column RowIdx[1] being stored in next - RowsPerPoint elements, and so on. - - First element in contiguous set of RowsPerPoint elements - corresponds to - - RowSize - number of columns per row - - -- ALGLIB -- - Copyright 28.09.2016 by Bochkanov Sergey -*************************************************************************/ -static void rbfv2_designmatrixgeneraterow(/* Integer */ ae_vector* kdnodes, - /* Real */ ae_vector* kdsplits, - /* Real */ ae_vector* cw, - /* Real */ ae_vector* ri, - /* Integer */ ae_vector* kdroots, - /* Real */ ae_vector* kdboxmin, - /* Real */ ae_vector* kdboxmax, - /* Integer */ ae_vector* cwrange, - ae_int_t nx, - ae_int_t ny, - ae_int_t nh, - ae_int_t level, - ae_int_t bf, - double rcoeff, - ae_int_t rowsperpoint, - double penalty, - /* Real */ ae_vector* x0, - rbfv2calcbuffer* calcbuf, - /* Real */ ae_vector* tmpr2, - /* Integer */ ae_vector* tmpoffs, - /* Integer */ ae_vector* rowidx, - /* Real */ ae_vector* rowval, - ae_int_t* rowsize, - ae_state *_state) -{ - ae_int_t j; - ae_int_t k; - ae_int_t cnt; - ae_int_t levelidx; - ae_int_t level0; - ae_int_t level1; - double invri2; - double curradius2; - double val; - double dval; - double d2val; - - *rowsize = 0; - - ae_assert(nh>0, "DesignMatrixGenerateRow: integrity failure (a)", _state); - ae_assert(rowsperpoint==1||rowsperpoint==1+nx, "DesignMatrixGenerateRow: integrity failure (b)", _state); - if( level>=0 ) - { - level0 = level; - level1 = level; - } - else - { - level0 = 0; - level1 = nh-1; - } - *rowsize = 0; - for(levelidx=level0; levelidx<=level1; levelidx++) - { - curradius2 = ae_sqr(ri->ptr.p_double[levelidx]*rcoeff, _state); - invri2 = 1/ae_sqr(ri->ptr.p_double[levelidx], _state); - rbfv2_preparepartialquery(x0, kdboxmin, kdboxmax, nx, calcbuf, &cnt, _state); - rbfv2_partialqueryrec(kdnodes, kdsplits, cw, nx, ny, calcbuf, kdroots->ptr.p_int[levelidx], curradius2, x0, tmpr2, tmpoffs, &cnt, _state); - ae_assert(tmpr2->cnt>=cnt, "DesignMatrixRowSize: integrity failure (c)", _state); - ae_assert(tmpoffs->cnt>=cnt, "DesignMatrixRowSize: integrity failure (d)", _state); - ae_assert(rowidx->cnt>=*rowsize+cnt, "DesignMatrixRowSize: integrity failure (e)", _state); - ae_assert(rowval->cnt>=rowsperpoint*(*rowsize+cnt), "DesignMatrixRowSize: integrity failure (f)", _state); - for(j=0; j<=cnt-1; j++) - { - - /* - * Generate element corresponding to fitting error. - * Store derivative information which may be required later. - */ - ae_assert((tmpoffs->ptr.p_int[j]-cwrange->ptr.p_int[level0])%(nx+ny)==0, "DesignMatrixRowSize: integrity failure (g)", _state); - rbfv2basisfuncdiff2(bf, tmpr2->ptr.p_double[j]*invri2, &val, &dval, &d2val, _state); - rowidx->ptr.p_int[*rowsize+j] = (tmpoffs->ptr.p_int[j]-cwrange->ptr.p_int[level0])/(nx+ny); - rowval->ptr.p_double[(*rowsize+j)*rowsperpoint+0] = val; - if( rowsperpoint==1 ) - { - continue; - } - - /* - * Generate elements corresponding to nonsmoothness penalty - */ - ae_assert(rowsperpoint==1+nx, "DesignMatrixRowSize: integrity failure (h)", _state); - for(k=0; k<=nx-1; k++) - { - rowval->ptr.p_double[(*rowsize+j)*rowsperpoint+1+k] = penalty*(dval*2*invri2+d2val*ae_sqr(2*(x0->ptr.p_double[k]-cw->ptr.p_double[tmpoffs->ptr.p_int[j]+k])*invri2, _state)); - } - } - - /* - * Update columns counter - */ - *rowsize = *rowsize+cnt; - } -} - - -/************************************************************************* -This function fills RBF model by zeros. - - -- ALGLIB -- - Copyright 17.11.2018 by Bochkanov Sergey -*************************************************************************/ -static void rbfv2_zerofill(rbfv2model* s, - ae_int_t nx, - ae_int_t ny, - ae_int_t bf, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - s->bf = bf; - s->nh = 0; - ae_vector_set_length(&s->ri, 0, _state); - ae_vector_set_length(&s->s, 0, _state); - ae_vector_set_length(&s->kdroots, 0, _state); - ae_vector_set_length(&s->kdnodes, 0, _state); - ae_vector_set_length(&s->kdsplits, 0, _state); - ae_vector_set_length(&s->kdboxmin, 0, _state); - ae_vector_set_length(&s->kdboxmax, 0, _state); - ae_vector_set_length(&s->cw, 0, _state); - ae_matrix_set_length(&s->v, ny, nx+1, _state); - for(i=0; i<=ny-1; i++) - { - for(j=0; j<=nx; j++) - { - s->v.ptr.pp_double[i][j] = (double)(0); - } - } -} - - -void _rbfv2calcbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - rbfv2calcbuffer *p = (rbfv2calcbuffer*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->curboxmin, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->curboxmax, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->x123, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->y123, 0, DT_REAL, _state, make_automatic); -} - - -void _rbfv2calcbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - rbfv2calcbuffer *dst = (rbfv2calcbuffer*)_dst; - rbfv2calcbuffer *src = (rbfv2calcbuffer*)_src; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->curboxmin, &src->curboxmin, _state, make_automatic); - ae_vector_init_copy(&dst->curboxmax, &src->curboxmax, _state, make_automatic); - dst->curdist2 = src->curdist2; - ae_vector_init_copy(&dst->x123, &src->x123, _state, make_automatic); - ae_vector_init_copy(&dst->y123, &src->y123, _state, make_automatic); -} - - -void _rbfv2calcbuffer_clear(void* _p) -{ - rbfv2calcbuffer *p = (rbfv2calcbuffer*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->x); - ae_vector_clear(&p->curboxmin); - ae_vector_clear(&p->curboxmax); - ae_vector_clear(&p->x123); - ae_vector_clear(&p->y123); -} - - -void _rbfv2calcbuffer_destroy(void* _p) -{ - rbfv2calcbuffer *p = (rbfv2calcbuffer*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->curboxmin); - ae_vector_destroy(&p->curboxmax); - ae_vector_destroy(&p->x123); - ae_vector_destroy(&p->y123); -} - - -void _rbfv2model_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - rbfv2model *p = (rbfv2model*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->ri, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->kdroots, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->kdnodes, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->kdsplits, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->kdboxmin, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->kdboxmax, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cw, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->v, 0, 0, DT_REAL, _state, make_automatic); - _rbfv2calcbuffer_init(&p->calcbuf, _state, make_automatic); -} - - -void _rbfv2model_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - rbfv2model *dst = (rbfv2model*)_dst; - rbfv2model *src = (rbfv2model*)_src; - dst->ny = src->ny; - dst->nx = src->nx; - dst->bf = src->bf; - dst->nh = src->nh; - ae_vector_init_copy(&dst->ri, &src->ri, _state, make_automatic); - ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic); - ae_vector_init_copy(&dst->kdroots, &src->kdroots, _state, make_automatic); - ae_vector_init_copy(&dst->kdnodes, &src->kdnodes, _state, make_automatic); - ae_vector_init_copy(&dst->kdsplits, &src->kdsplits, _state, make_automatic); - ae_vector_init_copy(&dst->kdboxmin, &src->kdboxmin, _state, make_automatic); - ae_vector_init_copy(&dst->kdboxmax, &src->kdboxmax, _state, make_automatic); - ae_vector_init_copy(&dst->cw, &src->cw, _state, make_automatic); - ae_matrix_init_copy(&dst->v, &src->v, _state, make_automatic); - dst->lambdareg = src->lambdareg; - dst->maxits = src->maxits; - dst->supportr = src->supportr; - dst->basisfunction = src->basisfunction; - _rbfv2calcbuffer_init_copy(&dst->calcbuf, &src->calcbuf, _state, make_automatic); -} - - -void _rbfv2model_clear(void* _p) -{ - rbfv2model *p = (rbfv2model*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->ri); - ae_vector_clear(&p->s); - ae_vector_clear(&p->kdroots); - ae_vector_clear(&p->kdnodes); - ae_vector_clear(&p->kdsplits); - ae_vector_clear(&p->kdboxmin); - ae_vector_clear(&p->kdboxmax); - ae_vector_clear(&p->cw); - ae_matrix_clear(&p->v); - _rbfv2calcbuffer_clear(&p->calcbuf); -} - - -void _rbfv2model_destroy(void* _p) -{ - rbfv2model *p = (rbfv2model*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->ri); - ae_vector_destroy(&p->s); - ae_vector_destroy(&p->kdroots); - ae_vector_destroy(&p->kdnodes); - ae_vector_destroy(&p->kdsplits); - ae_vector_destroy(&p->kdboxmin); - ae_vector_destroy(&p->kdboxmax); - ae_vector_destroy(&p->cw); - ae_matrix_destroy(&p->v); - _rbfv2calcbuffer_destroy(&p->calcbuf); -} - - -void _rbfv2gridcalcbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - rbfv2gridcalcbuffer *p = (rbfv2gridcalcbuffer*)_p; - ae_touch_ptr((void*)p); - _rbfv2calcbuffer_init(&p->calcbuf, _state, make_automatic); - ae_vector_init(&p->cx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ry, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ty, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rf, 0, DT_BOOL, _state, make_automatic); -} - - -void _rbfv2gridcalcbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - rbfv2gridcalcbuffer *dst = (rbfv2gridcalcbuffer*)_dst; - rbfv2gridcalcbuffer *src = (rbfv2gridcalcbuffer*)_src; - _rbfv2calcbuffer_init_copy(&dst->calcbuf, &src->calcbuf, _state, make_automatic); - ae_vector_init_copy(&dst->cx, &src->cx, _state, make_automatic); - ae_vector_init_copy(&dst->rx, &src->rx, _state, make_automatic); - ae_vector_init_copy(&dst->ry, &src->ry, _state, make_automatic); - ae_vector_init_copy(&dst->tx, &src->tx, _state, make_automatic); - ae_vector_init_copy(&dst->ty, &src->ty, _state, make_automatic); - ae_vector_init_copy(&dst->rf, &src->rf, _state, make_automatic); -} - - -void _rbfv2gridcalcbuffer_clear(void* _p) -{ - rbfv2gridcalcbuffer *p = (rbfv2gridcalcbuffer*)_p; - ae_touch_ptr((void*)p); - _rbfv2calcbuffer_clear(&p->calcbuf); - ae_vector_clear(&p->cx); - ae_vector_clear(&p->rx); - ae_vector_clear(&p->ry); - ae_vector_clear(&p->tx); - ae_vector_clear(&p->ty); - ae_vector_clear(&p->rf); -} - - -void _rbfv2gridcalcbuffer_destroy(void* _p) -{ - rbfv2gridcalcbuffer *p = (rbfv2gridcalcbuffer*)_p; - ae_touch_ptr((void*)p); - _rbfv2calcbuffer_destroy(&p->calcbuf); - ae_vector_destroy(&p->cx); - ae_vector_destroy(&p->rx); - ae_vector_destroy(&p->ry); - ae_vector_destroy(&p->tx); - ae_vector_destroy(&p->ty); - ae_vector_destroy(&p->rf); -} - - -void _rbfv2report_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - rbfv2report *p = (rbfv2report*)_p; - ae_touch_ptr((void*)p); -} - - -void _rbfv2report_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - rbfv2report *dst = (rbfv2report*)_dst; - rbfv2report *src = (rbfv2report*)_src; - dst->terminationtype = src->terminationtype; - dst->maxerror = src->maxerror; - dst->rmserror = src->rmserror; -} - - -void _rbfv2report_clear(void* _p) -{ - rbfv2report *p = (rbfv2report*)_p; - ae_touch_ptr((void*)p); -} - - -void _rbfv2report_destroy(void* _p) -{ - rbfv2report *p = (rbfv2report*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_SPLINE2D) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This subroutine calculates the value of the bilinear or bicubic spline at -the given point X. - -Input parameters: - C - 2D spline object. - Built by spline2dbuildbilinearv or spline2dbuildbicubicv. - X, Y- point - -Result: - S(x,y) - - -- ALGLIB PROJECT -- - Copyright 05.07.2007 by Bochkanov Sergey -*************************************************************************/ -double spline2dcalc(spline2dinterpolant* c, - double x, - double y, - ae_state *_state) -{ - ae_int_t ix; - ae_int_t iy; - ae_int_t l; - ae_int_t r; - ae_int_t h; - double t; - double dt; - double u; - double du; - double y1; - double y2; - double y3; - double y4; - ae_int_t s1; - ae_int_t s2; - ae_int_t s3; - ae_int_t s4; - ae_int_t sfx; - ae_int_t sfy; - ae_int_t sfxy; - double t2; - double t3; - double u2; - double u3; - double ht00; - double ht01; - double ht10; - double ht11; - double hu00; - double hu01; - double hu10; - double hu11; - double result; - - - ae_assert(c->stype==-1||c->stype==-3, "Spline2DCalc: incorrect C (incorrect parameter C.SType)", _state); - ae_assert(ae_isfinite(x, _state)&&ae_isfinite(y, _state), "Spline2DCalc: X or Y contains NaN or Infinite value", _state); - if( c->d!=1 ) - { - result = (double)(0); - return result; - } - - /* - * Determine evaluation interval - */ - l = 0; - r = c->n-1; - while(l!=r-1) - { - h = (l+r)/2; - if( ae_fp_greater_eq(c->x.ptr.p_double[h],x) ) - { - r = h; - } - else - { - l = h; - } - } - dt = 1.0/(c->x.ptr.p_double[l+1]-c->x.ptr.p_double[l]); - t = (x-c->x.ptr.p_double[l])*dt; - ix = l; - l = 0; - r = c->m-1; - while(l!=r-1) - { - h = (l+r)/2; - if( ae_fp_greater_eq(c->y.ptr.p_double[h],y) ) - { - r = h; - } - else - { - l = h; - } - } - du = 1.0/(c->y.ptr.p_double[l+1]-c->y.ptr.p_double[l]); - u = (y-c->y.ptr.p_double[l])*du; - iy = l; - - /* - * Bilinear interpolation - */ - if( c->stype==-1 ) - { - y1 = c->f.ptr.p_double[c->n*iy+ix]; - y2 = c->f.ptr.p_double[c->n*iy+(ix+1)]; - y3 = c->f.ptr.p_double[c->n*(iy+1)+(ix+1)]; - y4 = c->f.ptr.p_double[c->n*(iy+1)+ix]; - result = (1-t)*(1-u)*y1+t*(1-u)*y2+t*u*y3+(1-t)*u*y4; - return result; - } - - /* - * Bicubic interpolation: - * * calculate Hermite basis for dimensions X and Y (variables T and U), - * here HTij means basis function whose I-th derivative has value 1 at T=J. - * Same for HUij. - * * after initial calculation, apply scaling by DT/DU to the basis - * * calculate using stored table of second derivatives - */ - ae_assert(c->stype==-3, "Spline2DCalc: integrity check failed", _state); - sfx = c->n*c->m; - sfy = 2*c->n*c->m; - sfxy = 3*c->n*c->m; - s1 = c->n*iy+ix; - s2 = c->n*iy+(ix+1); - s3 = c->n*(iy+1)+ix; - s4 = c->n*(iy+1)+(ix+1); - t2 = t*t; - t3 = t*t2; - u2 = u*u; - u3 = u*u2; - ht00 = 2*t3-3*t2+1; - ht10 = t3-2*t2+t; - ht01 = -2*t3+3*t2; - ht11 = t3-t2; - hu00 = 2*u3-3*u2+1; - hu10 = u3-2*u2+u; - hu01 = -2*u3+3*u2; - hu11 = u3-u2; - ht10 = ht10/dt; - ht11 = ht11/dt; - hu10 = hu10/du; - hu11 = hu11/du; - result = (double)(0); - result = result+c->f.ptr.p_double[s1]*ht00*hu00+c->f.ptr.p_double[s2]*ht01*hu00+c->f.ptr.p_double[s3]*ht00*hu01+c->f.ptr.p_double[s4]*ht01*hu01; - result = result+c->f.ptr.p_double[sfx+s1]*ht10*hu00+c->f.ptr.p_double[sfx+s2]*ht11*hu00+c->f.ptr.p_double[sfx+s3]*ht10*hu01+c->f.ptr.p_double[sfx+s4]*ht11*hu01; - result = result+c->f.ptr.p_double[sfy+s1]*ht00*hu10+c->f.ptr.p_double[sfy+s2]*ht01*hu10+c->f.ptr.p_double[sfy+s3]*ht00*hu11+c->f.ptr.p_double[sfy+s4]*ht01*hu11; - result = result+c->f.ptr.p_double[sfxy+s1]*ht10*hu10+c->f.ptr.p_double[sfxy+s2]*ht11*hu10+c->f.ptr.p_double[sfxy+s3]*ht10*hu11+c->f.ptr.p_double[sfxy+s4]*ht11*hu11; - return result; -} - - -/************************************************************************* -This subroutine calculates the value of the bilinear or bicubic spline at -the given point X and its derivatives. - -Input parameters: - C - spline interpolant. - X, Y- point - -Output parameters: - F - S(x,y) - FX - dS(x,y)/dX - FY - dS(x,y)/dY - FXY - d2S(x,y)/dXdY - - -- ALGLIB PROJECT -- - Copyright 05.07.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2ddiff(spline2dinterpolant* c, - double x, - double y, - double* f, - double* fx, - double* fy, - double* fxy, - ae_state *_state) -{ - double t; - double dt; - double u; - double du; - ae_int_t ix; - ae_int_t iy; - ae_int_t l; - ae_int_t r; - ae_int_t h; - ae_int_t s1; - ae_int_t s2; - ae_int_t s3; - ae_int_t s4; - ae_int_t sfx; - ae_int_t sfy; - ae_int_t sfxy; - double y1; - double y2; - double y3; - double y4; - double v0; - double v1; - double v2; - double v3; - double t2; - double t3; - double u2; - double u3; - double ht00; - double ht01; - double ht10; - double ht11; - double hu00; - double hu01; - double hu10; - double hu11; - double dht00; - double dht01; - double dht10; - double dht11; - double dhu00; - double dhu01; - double dhu10; - double dhu11; - - *f = 0; - *fx = 0; - *fy = 0; - *fxy = 0; - - ae_assert(c->stype==-1||c->stype==-3, "Spline2DDiff: incorrect C (incorrect parameter C.SType)", _state); - ae_assert(ae_isfinite(x, _state)&&ae_isfinite(y, _state), "Spline2DDiff: X or Y contains NaN or Infinite value", _state); - - /* - * Prepare F, dF/dX, dF/dY, d2F/dXdY - */ - *f = (double)(0); - *fx = (double)(0); - *fy = (double)(0); - *fxy = (double)(0); - if( c->d!=1 ) - { - return; - } - - /* - * Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included) - */ - l = 0; - r = c->n-1; - while(l!=r-1) - { - h = (l+r)/2; - if( ae_fp_greater_eq(c->x.ptr.p_double[h],x) ) - { - r = h; - } - else - { - l = h; - } - } - t = (x-c->x.ptr.p_double[l])/(c->x.ptr.p_double[l+1]-c->x.ptr.p_double[l]); - dt = 1.0/(c->x.ptr.p_double[l+1]-c->x.ptr.p_double[l]); - ix = l; - - /* - * Binary search in the [ y[0], ..., y[m-2] ] (y[m-1] is not included) - */ - l = 0; - r = c->m-1; - while(l!=r-1) - { - h = (l+r)/2; - if( ae_fp_greater_eq(c->y.ptr.p_double[h],y) ) - { - r = h; - } - else - { - l = h; - } - } - u = (y-c->y.ptr.p_double[l])/(c->y.ptr.p_double[l+1]-c->y.ptr.p_double[l]); - du = 1.0/(c->y.ptr.p_double[l+1]-c->y.ptr.p_double[l]); - iy = l; - - /* - * Bilinear interpolation - */ - if( c->stype==-1 ) - { - y1 = c->f.ptr.p_double[c->n*iy+ix]; - y2 = c->f.ptr.p_double[c->n*iy+(ix+1)]; - y3 = c->f.ptr.p_double[c->n*(iy+1)+(ix+1)]; - y4 = c->f.ptr.p_double[c->n*(iy+1)+ix]; - *f = (1-t)*(1-u)*y1+t*(1-u)*y2+t*u*y3+(1-t)*u*y4; - *fx = (-(1-u)*y1+(1-u)*y2+u*y3-u*y4)*dt; - *fy = (-(1-t)*y1-t*y2+t*y3+(1-t)*y4)*du; - *fxy = (y1-y2+y3-y4)*du*dt; - return; - } - - /* - * Bicubic interpolation - */ - if( c->stype==-3 ) - { - sfx = c->n*c->m; - sfy = 2*c->n*c->m; - sfxy = 3*c->n*c->m; - s1 = c->n*iy+ix; - s2 = c->n*iy+(ix+1); - s3 = c->n*(iy+1)+ix; - s4 = c->n*(iy+1)+(ix+1); - t2 = t*t; - t3 = t*t2; - u2 = u*u; - u3 = u*u2; - ht00 = 2*t3-3*t2+1; - ht10 = t3-2*t2+t; - ht01 = -2*t3+3*t2; - ht11 = t3-t2; - hu00 = 2*u3-3*u2+1; - hu10 = u3-2*u2+u; - hu01 = -2*u3+3*u2; - hu11 = u3-u2; - ht10 = ht10/dt; - ht11 = ht11/dt; - hu10 = hu10/du; - hu11 = hu11/du; - dht00 = 6*t2-6*t; - dht10 = 3*t2-4*t+1; - dht01 = -6*t2+6*t; - dht11 = 3*t2-2*t; - dhu00 = 6*u2-6*u; - dhu10 = 3*u2-4*u+1; - dhu01 = -6*u2+6*u; - dhu11 = 3*u2-2*u; - dht00 = dht00*dt; - dht01 = dht01*dt; - dhu00 = dhu00*du; - dhu01 = dhu01*du; - *f = (double)(0); - *fx = (double)(0); - *fy = (double)(0); - *fxy = (double)(0); - v0 = c->f.ptr.p_double[s1]; - v1 = c->f.ptr.p_double[s2]; - v2 = c->f.ptr.p_double[s3]; - v3 = c->f.ptr.p_double[s4]; - *f = *f+v0*ht00*hu00+v1*ht01*hu00+v2*ht00*hu01+v3*ht01*hu01; - *fx = *fx+v0*dht00*hu00+v1*dht01*hu00+v2*dht00*hu01+v3*dht01*hu01; - *fy = *fy+v0*ht00*dhu00+v1*ht01*dhu00+v2*ht00*dhu01+v3*ht01*dhu01; - *fxy = *fxy+v0*dht00*dhu00+v1*dht01*dhu00+v2*dht00*dhu01+v3*dht01*dhu01; - v0 = c->f.ptr.p_double[sfx+s1]; - v1 = c->f.ptr.p_double[sfx+s2]; - v2 = c->f.ptr.p_double[sfx+s3]; - v3 = c->f.ptr.p_double[sfx+s4]; - *f = *f+v0*ht10*hu00+v1*ht11*hu00+v2*ht10*hu01+v3*ht11*hu01; - *fx = *fx+v0*dht10*hu00+v1*dht11*hu00+v2*dht10*hu01+v3*dht11*hu01; - *fy = *fy+v0*ht10*dhu00+v1*ht11*dhu00+v2*ht10*dhu01+v3*ht11*dhu01; - *fxy = *fxy+v0*dht10*dhu00+v1*dht11*dhu00+v2*dht10*dhu01+v3*dht11*dhu01; - v0 = c->f.ptr.p_double[sfy+s1]; - v1 = c->f.ptr.p_double[sfy+s2]; - v2 = c->f.ptr.p_double[sfy+s3]; - v3 = c->f.ptr.p_double[sfy+s4]; - *f = *f+v0*ht00*hu10+v1*ht01*hu10+v2*ht00*hu11+v3*ht01*hu11; - *fx = *fx+v0*dht00*hu10+v1*dht01*hu10+v2*dht00*hu11+v3*dht01*hu11; - *fy = *fy+v0*ht00*dhu10+v1*ht01*dhu10+v2*ht00*dhu11+v3*ht01*dhu11; - *fxy = *fxy+v0*dht00*dhu10+v1*dht01*dhu10+v2*dht00*dhu11+v3*dht01*dhu11; - v0 = c->f.ptr.p_double[sfxy+s1]; - v1 = c->f.ptr.p_double[sfxy+s2]; - v2 = c->f.ptr.p_double[sfxy+s3]; - v3 = c->f.ptr.p_double[sfxy+s4]; - *f = *f+v0*ht10*hu10+v1*ht11*hu10+v2*ht10*hu11+v3*ht11*hu11; - *fx = *fx+v0*dht10*hu10+v1*dht11*hu10+v2*dht10*hu11+v3*dht11*hu11; - *fy = *fy+v0*ht10*dhu10+v1*ht11*dhu10+v2*ht10*dhu11+v3*ht11*dhu11; - *fxy = *fxy+v0*dht10*dhu10+v1*dht11*dhu10+v2*dht10*dhu11+v3*dht11*dhu11; - return; - } -} - - -/************************************************************************* -This subroutine calculates bilinear or bicubic vector-valued spline at the -given point (X,Y). - -If you need just some specific component of vector-valued spline, you can -use spline2dcalcvi() function. - -INPUT PARAMETERS: - C - spline interpolant. - X, Y- point - F - output buffer, possibly preallocated array. In case array size - is large enough to store result, it is not reallocated. Array - which is too short will be reallocated - -OUTPUT PARAMETERS: - F - array[D] (or larger) which stores function values - - -- ALGLIB PROJECT -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dcalcvbuf(spline2dinterpolant* c, - double x, - double y, - /* Real */ ae_vector* f, - ae_state *_state) -{ - ae_int_t ix; - ae_int_t iy; - ae_int_t l; - ae_int_t r; - ae_int_t h; - ae_int_t i; - double t; - double dt; - double u; - double du; - double y1; - double y2; - double y3; - double y4; - ae_int_t s1; - ae_int_t s2; - ae_int_t s3; - ae_int_t s4; - ae_int_t sfx; - ae_int_t sfy; - ae_int_t sfxy; - double t2; - double t3; - double u2; - double u3; - double ht00; - double ht01; - double ht10; - double ht11; - double hu00; - double hu01; - double hu10; - double hu11; - - - ae_assert(c->stype==-1||c->stype==-3, "Spline2DCalcVBuf: incorrect C (incorrect parameter C.SType)", _state); - ae_assert(ae_isfinite(x, _state)&&ae_isfinite(y, _state), "Spline2DCalcVBuf: X or Y contains NaN or Infinite value", _state); - - /* - * Allocate place for output - */ - rvectorsetlengthatleast(f, c->d, _state); - - /* - * Determine evaluation interval - */ - l = 0; - r = c->n-1; - while(l!=r-1) - { - h = (l+r)/2; - if( ae_fp_greater_eq(c->x.ptr.p_double[h],x) ) - { - r = h; - } - else - { - l = h; - } - } - dt = 1.0/(c->x.ptr.p_double[l+1]-c->x.ptr.p_double[l]); - t = (x-c->x.ptr.p_double[l])*dt; - ix = l; - l = 0; - r = c->m-1; - while(l!=r-1) - { - h = (l+r)/2; - if( ae_fp_greater_eq(c->y.ptr.p_double[h],y) ) - { - r = h; - } - else - { - l = h; - } - } - du = 1.0/(c->y.ptr.p_double[l+1]-c->y.ptr.p_double[l]); - u = (y-c->y.ptr.p_double[l])*du; - iy = l; - - /* - * Bilinear interpolation - */ - if( c->stype==-1 ) - { - for(i=0; i<=c->d-1; i++) - { - y1 = c->f.ptr.p_double[c->d*(c->n*iy+ix)+i]; - y2 = c->f.ptr.p_double[c->d*(c->n*iy+(ix+1))+i]; - y3 = c->f.ptr.p_double[c->d*(c->n*(iy+1)+(ix+1))+i]; - y4 = c->f.ptr.p_double[c->d*(c->n*(iy+1)+ix)+i]; - f->ptr.p_double[i] = (1-t)*(1-u)*y1+t*(1-u)*y2+t*u*y3+(1-t)*u*y4; - } - return; - } - - /* - * Bicubic interpolation: - * * calculate Hermite basis for dimensions X and Y (variables T and U), - * here HTij means basis function whose I-th derivative has value 1 at T=J. - * Same for HUij. - * * after initial calculation, apply scaling by DT/DU to the basis - * * calculate using stored table of second derivatives - */ - ae_assert(c->stype==-3, "Spline2DCalc: integrity check failed", _state); - sfx = c->n*c->m*c->d; - sfy = 2*c->n*c->m*c->d; - sfxy = 3*c->n*c->m*c->d; - s1 = (c->n*iy+ix)*c->d; - s2 = (c->n*iy+(ix+1))*c->d; - s3 = (c->n*(iy+1)+ix)*c->d; - s4 = (c->n*(iy+1)+(ix+1))*c->d; - t2 = t*t; - t3 = t*t2; - u2 = u*u; - u3 = u*u2; - ht00 = 2*t3-3*t2+1; - ht10 = t3-2*t2+t; - ht01 = -2*t3+3*t2; - ht11 = t3-t2; - hu00 = 2*u3-3*u2+1; - hu10 = u3-2*u2+u; - hu01 = -2*u3+3*u2; - hu11 = u3-u2; - ht10 = ht10/dt; - ht11 = ht11/dt; - hu10 = hu10/du; - hu11 = hu11/du; - for(i=0; i<=c->d-1; i++) - { - - /* - * Calculate I-th component - */ - f->ptr.p_double[i] = (double)(0); - f->ptr.p_double[i] = f->ptr.p_double[i]+c->f.ptr.p_double[s1]*ht00*hu00+c->f.ptr.p_double[s2]*ht01*hu00+c->f.ptr.p_double[s3]*ht00*hu01+c->f.ptr.p_double[s4]*ht01*hu01; - f->ptr.p_double[i] = f->ptr.p_double[i]+c->f.ptr.p_double[sfx+s1]*ht10*hu00+c->f.ptr.p_double[sfx+s2]*ht11*hu00+c->f.ptr.p_double[sfx+s3]*ht10*hu01+c->f.ptr.p_double[sfx+s4]*ht11*hu01; - f->ptr.p_double[i] = f->ptr.p_double[i]+c->f.ptr.p_double[sfy+s1]*ht00*hu10+c->f.ptr.p_double[sfy+s2]*ht01*hu10+c->f.ptr.p_double[sfy+s3]*ht00*hu11+c->f.ptr.p_double[sfy+s4]*ht01*hu11; - f->ptr.p_double[i] = f->ptr.p_double[i]+c->f.ptr.p_double[sfxy+s1]*ht10*hu10+c->f.ptr.p_double[sfxy+s2]*ht11*hu10+c->f.ptr.p_double[sfxy+s3]*ht10*hu11+c->f.ptr.p_double[sfxy+s4]*ht11*hu11; - - /* - * Advance source indexes - */ - s1 = s1+1; - s2 = s2+1; - s3 = s3+1; - s4 = s4+1; - } -} - - -/************************************************************************* -This subroutine calculates specific component of vector-valued bilinear or -bicubic spline at the given point (X,Y). - -INPUT PARAMETERS: - C - spline interpolant. - X, Y- point - I - component index, in [0,D). An exception is generated for out - of range values. - -RESULT: - value of I-th component - - -- ALGLIB PROJECT -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -double spline2dcalcvi(spline2dinterpolant* c, - double x, - double y, - ae_int_t i, - ae_state *_state) -{ - ae_int_t ix; - ae_int_t iy; - ae_int_t l; - ae_int_t r; - ae_int_t h; - double t; - double dt; - double u; - double du; - double y1; - double y2; - double y3; - double y4; - ae_int_t s1; - ae_int_t s2; - ae_int_t s3; - ae_int_t s4; - ae_int_t sfx; - ae_int_t sfy; - ae_int_t sfxy; - double t2; - double t3; - double u2; - double u3; - double ht00; - double ht01; - double ht10; - double ht11; - double hu00; - double hu01; - double hu10; - double hu11; - double result; - - - ae_assert(c->stype==-1||c->stype==-3, "Spline2DCalcVi: incorrect C (incorrect parameter C.SType)", _state); - ae_assert(ae_isfinite(x, _state)&&ae_isfinite(y, _state), "Spline2DCalcVi: X or Y contains NaN or Infinite value", _state); - ae_assert(i>=0&&id, "Spline2DCalcVi: incorrect I (I<0 or I>=D)", _state); - - /* - * Determine evaluation interval - */ - l = 0; - r = c->n-1; - while(l!=r-1) - { - h = (l+r)/2; - if( ae_fp_greater_eq(c->x.ptr.p_double[h],x) ) - { - r = h; - } - else - { - l = h; - } - } - dt = 1.0/(c->x.ptr.p_double[l+1]-c->x.ptr.p_double[l]); - t = (x-c->x.ptr.p_double[l])*dt; - ix = l; - l = 0; - r = c->m-1; - while(l!=r-1) - { - h = (l+r)/2; - if( ae_fp_greater_eq(c->y.ptr.p_double[h],y) ) - { - r = h; - } - else - { - l = h; - } - } - du = 1.0/(c->y.ptr.p_double[l+1]-c->y.ptr.p_double[l]); - u = (y-c->y.ptr.p_double[l])*du; - iy = l; - - /* - * Bilinear interpolation - */ - if( c->stype==-1 ) - { - y1 = c->f.ptr.p_double[c->d*(c->n*iy+ix)+i]; - y2 = c->f.ptr.p_double[c->d*(c->n*iy+(ix+1))+i]; - y3 = c->f.ptr.p_double[c->d*(c->n*(iy+1)+(ix+1))+i]; - y4 = c->f.ptr.p_double[c->d*(c->n*(iy+1)+ix)+i]; - result = (1-t)*(1-u)*y1+t*(1-u)*y2+t*u*y3+(1-t)*u*y4; - return result; - } - - /* - * Bicubic interpolation: - * * calculate Hermite basis for dimensions X and Y (variables T and U), - * here HTij means basis function whose I-th derivative has value 1 at T=J. - * Same for HUij. - * * after initial calculation, apply scaling by DT/DU to the basis - * * calculate using stored table of second derivatives - */ - ae_assert(c->stype==-3, "Spline2DCalc: integrity check failed", _state); - sfx = c->n*c->m*c->d; - sfy = 2*c->n*c->m*c->d; - sfxy = 3*c->n*c->m*c->d; - s1 = (c->n*iy+ix)*c->d; - s2 = (c->n*iy+(ix+1))*c->d; - s3 = (c->n*(iy+1)+ix)*c->d; - s4 = (c->n*(iy+1)+(ix+1))*c->d; - t2 = t*t; - t3 = t*t2; - u2 = u*u; - u3 = u*u2; - ht00 = 2*t3-3*t2+1; - ht10 = t3-2*t2+t; - ht01 = -2*t3+3*t2; - ht11 = t3-t2; - hu00 = 2*u3-3*u2+1; - hu10 = u3-2*u2+u; - hu01 = -2*u3+3*u2; - hu11 = u3-u2; - ht10 = ht10/dt; - ht11 = ht11/dt; - hu10 = hu10/du; - hu11 = hu11/du; - - /* - * Advance source indexes to I-th position - */ - s1 = s1+i; - s2 = s2+i; - s3 = s3+i; - s4 = s4+i; - - /* - * Calculate I-th component - */ - result = (double)(0); - result = result+c->f.ptr.p_double[s1]*ht00*hu00+c->f.ptr.p_double[s2]*ht01*hu00+c->f.ptr.p_double[s3]*ht00*hu01+c->f.ptr.p_double[s4]*ht01*hu01; - result = result+c->f.ptr.p_double[sfx+s1]*ht10*hu00+c->f.ptr.p_double[sfx+s2]*ht11*hu00+c->f.ptr.p_double[sfx+s3]*ht10*hu01+c->f.ptr.p_double[sfx+s4]*ht11*hu01; - result = result+c->f.ptr.p_double[sfy+s1]*ht00*hu10+c->f.ptr.p_double[sfy+s2]*ht01*hu10+c->f.ptr.p_double[sfy+s3]*ht00*hu11+c->f.ptr.p_double[sfy+s4]*ht01*hu11; - result = result+c->f.ptr.p_double[sfxy+s1]*ht10*hu10+c->f.ptr.p_double[sfxy+s2]*ht11*hu10+c->f.ptr.p_double[sfxy+s3]*ht10*hu11+c->f.ptr.p_double[sfxy+s4]*ht11*hu11; - return result; -} - - -/************************************************************************* -This subroutine calculates bilinear or bicubic vector-valued spline at the -given point (X,Y). - -INPUT PARAMETERS: - C - spline interpolant. - X, Y- point - -OUTPUT PARAMETERS: - F - array[D] which stores function values. F is out-parameter and - it is reallocated after call to this function. In case you - want to reuse previously allocated F, you may use - Spline2DCalcVBuf(), which reallocates F only when it is too - small. - - -- ALGLIB PROJECT -- - Copyright 16.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline2dcalcv(spline2dinterpolant* c, - double x, - double y, - /* Real */ ae_vector* f, - ae_state *_state) -{ - - ae_vector_clear(f); - - ae_assert(c->stype==-1||c->stype==-3, "Spline2DCalcV: incorrect C (incorrect parameter C.SType)", _state); - ae_assert(ae_isfinite(x, _state)&&ae_isfinite(y, _state), "Spline2DCalcV: either X=NaN/Infinite or Y=NaN/Infinite", _state); - spline2dcalcvbuf(c, x, y, f, _state); -} - - -/************************************************************************* -This subroutine calculates value of specific component of bilinear or -bicubic vector-valued spline and its derivatives. - -Input parameters: - C - spline interpolant. - X, Y- point - I - component index, in [0,D) - -Output parameters: - F - S(x,y) - FX - dS(x,y)/dX - FY - dS(x,y)/dY - FXY - d2S(x,y)/dXdY - - -- ALGLIB PROJECT -- - Copyright 05.07.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2ddiffvi(spline2dinterpolant* c, - double x, - double y, - ae_int_t i, - double* f, - double* fx, - double* fy, - double* fxy, - ae_state *_state) -{ - ae_int_t d; - double t; - double dt; - double u; - double du; - ae_int_t ix; - ae_int_t iy; - ae_int_t l; - ae_int_t r; - ae_int_t h; - ae_int_t s1; - ae_int_t s2; - ae_int_t s3; - ae_int_t s4; - ae_int_t sfx; - ae_int_t sfy; - ae_int_t sfxy; - double y1; - double y2; - double y3; - double y4; - double v0; - double v1; - double v2; - double v3; - double t2; - double t3; - double u2; - double u3; - double ht00; - double ht01; - double ht10; - double ht11; - double hu00; - double hu01; - double hu10; - double hu11; - double dht00; - double dht01; - double dht10; - double dht11; - double dhu00; - double dhu01; - double dhu10; - double dhu11; - - *f = 0; - *fx = 0; - *fy = 0; - *fxy = 0; - - ae_assert(c->stype==-1||c->stype==-3, "Spline2DDiffVI: incorrect C (incorrect parameter C.SType)", _state); - ae_assert(ae_isfinite(x, _state)&&ae_isfinite(y, _state), "Spline2DDiffVI: X or Y contains NaN or Infinite value", _state); - ae_assert(i>=0&&id, "Spline2DDiffVI: I<0 or I>=D", _state); - - /* - * Prepare F, dF/dX, dF/dY, d2F/dXdY - */ - *f = (double)(0); - *fx = (double)(0); - *fy = (double)(0); - *fxy = (double)(0); - d = c->d; - - /* - * Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included) - */ - l = 0; - r = c->n-1; - while(l!=r-1) - { - h = (l+r)/2; - if( ae_fp_greater_eq(c->x.ptr.p_double[h],x) ) - { - r = h; - } - else - { - l = h; - } - } - t = (x-c->x.ptr.p_double[l])/(c->x.ptr.p_double[l+1]-c->x.ptr.p_double[l]); - dt = 1.0/(c->x.ptr.p_double[l+1]-c->x.ptr.p_double[l]); - ix = l; - - /* - * Binary search in the [ y[0], ..., y[m-2] ] (y[m-1] is not included) - */ - l = 0; - r = c->m-1; - while(l!=r-1) - { - h = (l+r)/2; - if( ae_fp_greater_eq(c->y.ptr.p_double[h],y) ) - { - r = h; - } - else - { - l = h; - } - } - u = (y-c->y.ptr.p_double[l])/(c->y.ptr.p_double[l+1]-c->y.ptr.p_double[l]); - du = 1.0/(c->y.ptr.p_double[l+1]-c->y.ptr.p_double[l]); - iy = l; - - /* - * Bilinear interpolation - */ - if( c->stype==-1 ) - { - y1 = c->f.ptr.p_double[d*(c->n*iy+ix)+i]; - y2 = c->f.ptr.p_double[d*(c->n*iy+(ix+1))+i]; - y3 = c->f.ptr.p_double[d*(c->n*(iy+1)+(ix+1))+i]; - y4 = c->f.ptr.p_double[d*(c->n*(iy+1)+ix)+i]; - *f = (1-t)*(1-u)*y1+t*(1-u)*y2+t*u*y3+(1-t)*u*y4; - *fx = (-(1-u)*y1+(1-u)*y2+u*y3-u*y4)*dt; - *fy = (-(1-t)*y1-t*y2+t*y3+(1-t)*y4)*du; - *fxy = (y1-y2+y3-y4)*du*dt; - return; - } - - /* - * Bicubic interpolation - */ - if( c->stype==-3 ) - { - sfx = c->n*c->m*d; - sfy = 2*c->n*c->m*d; - sfxy = 3*c->n*c->m*d; - s1 = d*(c->n*iy+ix)+i; - s2 = d*(c->n*iy+(ix+1))+i; - s3 = d*(c->n*(iy+1)+ix)+i; - s4 = d*(c->n*(iy+1)+(ix+1))+i; - t2 = t*t; - t3 = t*t2; - u2 = u*u; - u3 = u*u2; - ht00 = 2*t3-3*t2+1; - ht10 = t3-2*t2+t; - ht01 = -2*t3+3*t2; - ht11 = t3-t2; - hu00 = 2*u3-3*u2+1; - hu10 = u3-2*u2+u; - hu01 = -2*u3+3*u2; - hu11 = u3-u2; - ht10 = ht10/dt; - ht11 = ht11/dt; - hu10 = hu10/du; - hu11 = hu11/du; - dht00 = 6*t2-6*t; - dht10 = 3*t2-4*t+1; - dht01 = -6*t2+6*t; - dht11 = 3*t2-2*t; - dhu00 = 6*u2-6*u; - dhu10 = 3*u2-4*u+1; - dhu01 = -6*u2+6*u; - dhu11 = 3*u2-2*u; - dht00 = dht00*dt; - dht01 = dht01*dt; - dhu00 = dhu00*du; - dhu01 = dhu01*du; - *f = (double)(0); - *fx = (double)(0); - *fy = (double)(0); - *fxy = (double)(0); - v0 = c->f.ptr.p_double[s1]; - v1 = c->f.ptr.p_double[s2]; - v2 = c->f.ptr.p_double[s3]; - v3 = c->f.ptr.p_double[s4]; - *f = *f+v0*ht00*hu00+v1*ht01*hu00+v2*ht00*hu01+v3*ht01*hu01; - *fx = *fx+v0*dht00*hu00+v1*dht01*hu00+v2*dht00*hu01+v3*dht01*hu01; - *fy = *fy+v0*ht00*dhu00+v1*ht01*dhu00+v2*ht00*dhu01+v3*ht01*dhu01; - *fxy = *fxy+v0*dht00*dhu00+v1*dht01*dhu00+v2*dht00*dhu01+v3*dht01*dhu01; - v0 = c->f.ptr.p_double[sfx+s1]; - v1 = c->f.ptr.p_double[sfx+s2]; - v2 = c->f.ptr.p_double[sfx+s3]; - v3 = c->f.ptr.p_double[sfx+s4]; - *f = *f+v0*ht10*hu00+v1*ht11*hu00+v2*ht10*hu01+v3*ht11*hu01; - *fx = *fx+v0*dht10*hu00+v1*dht11*hu00+v2*dht10*hu01+v3*dht11*hu01; - *fy = *fy+v0*ht10*dhu00+v1*ht11*dhu00+v2*ht10*dhu01+v3*ht11*dhu01; - *fxy = *fxy+v0*dht10*dhu00+v1*dht11*dhu00+v2*dht10*dhu01+v3*dht11*dhu01; - v0 = c->f.ptr.p_double[sfy+s1]; - v1 = c->f.ptr.p_double[sfy+s2]; - v2 = c->f.ptr.p_double[sfy+s3]; - v3 = c->f.ptr.p_double[sfy+s4]; - *f = *f+v0*ht00*hu10+v1*ht01*hu10+v2*ht00*hu11+v3*ht01*hu11; - *fx = *fx+v0*dht00*hu10+v1*dht01*hu10+v2*dht00*hu11+v3*dht01*hu11; - *fy = *fy+v0*ht00*dhu10+v1*ht01*dhu10+v2*ht00*dhu11+v3*ht01*dhu11; - *fxy = *fxy+v0*dht00*dhu10+v1*dht01*dhu10+v2*dht00*dhu11+v3*dht01*dhu11; - v0 = c->f.ptr.p_double[sfxy+s1]; - v1 = c->f.ptr.p_double[sfxy+s2]; - v2 = c->f.ptr.p_double[sfxy+s3]; - v3 = c->f.ptr.p_double[sfxy+s4]; - *f = *f+v0*ht10*hu10+v1*ht11*hu10+v2*ht10*hu11+v3*ht11*hu11; - *fx = *fx+v0*dht10*hu10+v1*dht11*hu10+v2*dht10*hu11+v3*dht11*hu11; - *fy = *fy+v0*ht10*dhu10+v1*ht11*dhu10+v2*ht10*dhu11+v3*ht11*dhu11; - *fxy = *fxy+v0*dht10*dhu10+v1*dht11*dhu10+v2*dht10*dhu11+v3*dht11*dhu11; - return; - } -} - - -/************************************************************************* -This subroutine performs linear transformation of the spline argument. - -Input parameters: - C - spline interpolant - AX, BX - transformation coefficients: x = A*t + B - AY, BY - transformation coefficients: y = A*u + B -Result: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 30.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2dlintransxy(spline2dinterpolant* c, - double ax, - double bx, - double ay, - double by, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector x; - ae_vector y; - ae_vector f; - ae_vector v; - ae_int_t i; - ae_int_t j; - ae_int_t k; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&f, 0, sizeof(f)); - memset(&v, 0, sizeof(v)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&f, 0, DT_REAL, _state, ae_true); - ae_vector_init(&v, 0, DT_REAL, _state, ae_true); - - ae_assert(c->stype==-3||c->stype==-1, "Spline2DLinTransXY: incorrect C (incorrect parameter C.SType)", _state); - ae_assert(ae_isfinite(ax, _state), "Spline2DLinTransXY: AX is infinite or NaN", _state); - ae_assert(ae_isfinite(bx, _state), "Spline2DLinTransXY: BX is infinite or NaN", _state); - ae_assert(ae_isfinite(ay, _state), "Spline2DLinTransXY: AY is infinite or NaN", _state); - ae_assert(ae_isfinite(by, _state), "Spline2DLinTransXY: BY is infinite or NaN", _state); - ae_vector_set_length(&x, c->n, _state); - ae_vector_set_length(&y, c->m, _state); - ae_vector_set_length(&f, c->m*c->n*c->d, _state); - for(j=0; j<=c->n-1; j++) - { - x.ptr.p_double[j] = c->x.ptr.p_double[j]; - } - for(i=0; i<=c->m-1; i++) - { - y.ptr.p_double[i] = c->y.ptr.p_double[i]; - } - for(i=0; i<=c->m-1; i++) - { - for(j=0; j<=c->n-1; j++) - { - for(k=0; k<=c->d-1; k++) - { - f.ptr.p_double[c->d*(i*c->n+j)+k] = c->f.ptr.p_double[c->d*(i*c->n+j)+k]; - } - } - } - - /* - * Handle different combinations of AX/AY - */ - if( ae_fp_eq(ax,(double)(0))&&ae_fp_neq(ay,(double)(0)) ) - { - for(i=0; i<=c->m-1; i++) - { - spline2dcalcvbuf(c, bx, y.ptr.p_double[i], &v, _state); - y.ptr.p_double[i] = (y.ptr.p_double[i]-by)/ay; - for(j=0; j<=c->n-1; j++) - { - for(k=0; k<=c->d-1; k++) - { - f.ptr.p_double[c->d*(i*c->n+j)+k] = v.ptr.p_double[k]; - } - } - } - } - if( ae_fp_neq(ax,(double)(0))&&ae_fp_eq(ay,(double)(0)) ) - { - for(j=0; j<=c->n-1; j++) - { - spline2dcalcvbuf(c, x.ptr.p_double[j], by, &v, _state); - x.ptr.p_double[j] = (x.ptr.p_double[j]-bx)/ax; - for(i=0; i<=c->m-1; i++) - { - for(k=0; k<=c->d-1; k++) - { - f.ptr.p_double[c->d*(i*c->n+j)+k] = v.ptr.p_double[k]; - } - } - } - } - if( ae_fp_neq(ax,(double)(0))&&ae_fp_neq(ay,(double)(0)) ) - { - for(j=0; j<=c->n-1; j++) - { - x.ptr.p_double[j] = (x.ptr.p_double[j]-bx)/ax; - } - for(i=0; i<=c->m-1; i++) - { - y.ptr.p_double[i] = (y.ptr.p_double[i]-by)/ay; - } - } - if( ae_fp_eq(ax,(double)(0))&&ae_fp_eq(ay,(double)(0)) ) - { - spline2dcalcvbuf(c, bx, by, &v, _state); - for(i=0; i<=c->m-1; i++) - { - for(j=0; j<=c->n-1; j++) - { - for(k=0; k<=c->d-1; k++) - { - f.ptr.p_double[c->d*(i*c->n+j)+k] = v.ptr.p_double[k]; - } - } - } - } - - /* - * Rebuild spline - */ - if( c->stype==-3 ) - { - spline2dbuildbicubicv(&x, c->n, &y, c->m, &f, c->d, c, _state); - } - if( c->stype==-1 ) - { - spline2dbuildbilinearv(&x, c->n, &y, c->m, &f, c->d, c, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This subroutine performs linear transformation of the spline. - -Input parameters: - C - spline interpolant. - A, B- transformation coefficients: S2(x,y) = A*S(x,y) + B - -Output parameters: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 30.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2dlintransf(spline2dinterpolant* c, - double a, - double b, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector x; - ae_vector y; - ae_vector f; - ae_int_t i; - ae_int_t j; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&f, 0, sizeof(f)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&f, 0, DT_REAL, _state, ae_true); - - ae_assert(c->stype==-3||c->stype==-1, "Spline2DLinTransF: incorrect C (incorrect parameter C.SType)", _state); - ae_vector_set_length(&x, c->n, _state); - ae_vector_set_length(&y, c->m, _state); - ae_vector_set_length(&f, c->m*c->n*c->d, _state); - for(j=0; j<=c->n-1; j++) - { - x.ptr.p_double[j] = c->x.ptr.p_double[j]; - } - for(i=0; i<=c->m-1; i++) - { - y.ptr.p_double[i] = c->y.ptr.p_double[i]; - } - for(i=0; i<=c->m*c->n*c->d-1; i++) - { - f.ptr.p_double[i] = a*c->f.ptr.p_double[i]+b; - } - if( c->stype==-3 ) - { - spline2dbuildbicubicv(&x, c->n, &y, c->m, &f, c->d, c, _state); - } - if( c->stype==-1 ) - { - spline2dbuildbilinearv(&x, c->n, &y, c->m, &f, c->d, c, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This subroutine makes the copy of the spline model. - -Input parameters: - C - spline interpolant - -Output parameters: - CC - spline copy - - -- ALGLIB PROJECT -- - Copyright 29.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2dcopy(spline2dinterpolant* c, - spline2dinterpolant* cc, - ae_state *_state) -{ - ae_int_t tblsize; - - _spline2dinterpolant_clear(cc); - - ae_assert(c->stype==-1||c->stype==-3, "Spline2DCopy: incorrect C (incorrect parameter C.SType)", _state); - cc->n = c->n; - cc->m = c->m; - cc->d = c->d; - cc->stype = c->stype; - tblsize = -1; - if( c->stype==-3 ) - { - tblsize = 4*c->n*c->m*c->d; - } - if( c->stype==-1 ) - { - tblsize = c->n*c->m*c->d; - } - ae_assert(tblsize>0, "Spline2DCopy: internal error", _state); - ae_vector_set_length(&cc->x, cc->n, _state); - ae_vector_set_length(&cc->y, cc->m, _state); - ae_vector_set_length(&cc->f, tblsize, _state); - ae_v_move(&cc->x.ptr.p_double[0], 1, &c->x.ptr.p_double[0], 1, ae_v_len(0,cc->n-1)); - ae_v_move(&cc->y.ptr.p_double[0], 1, &c->y.ptr.p_double[0], 1, ae_v_len(0,cc->m-1)); - ae_v_move(&cc->f.ptr.p_double[0], 1, &c->f.ptr.p_double[0], 1, ae_v_len(0,tblsize-1)); -} - - -/************************************************************************* -Bicubic spline resampling - -Input parameters: - A - function values at the old grid, - array[0..OldHeight-1, 0..OldWidth-1] - OldHeight - old grid height, OldHeight>1 - OldWidth - old grid width, OldWidth>1 - NewHeight - new grid height, NewHeight>1 - NewWidth - new grid width, NewWidth>1 - -Output parameters: - B - function values at the new grid, - array[0..NewHeight-1, 0..NewWidth-1] - - -- ALGLIB routine -- - 15 May, 2007 - Copyright by Bochkanov Sergey -*************************************************************************/ -void spline2dresamplebicubic(/* Real */ ae_matrix* a, - ae_int_t oldheight, - ae_int_t oldwidth, - /* Real */ ae_matrix* b, - ae_int_t newheight, - ae_int_t newwidth, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix buf; - ae_vector x; - ae_vector y; - spline1dinterpolant c; - ae_int_t mw; - ae_int_t mh; - ae_int_t i; - ae_int_t j; - - ae_frame_make(_state, &_frame_block); - memset(&buf, 0, sizeof(buf)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&c, 0, sizeof(c)); - ae_matrix_clear(b); - ae_matrix_init(&buf, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - _spline1dinterpolant_init(&c, _state, ae_true); - - ae_assert(oldwidth>1&&oldheight>1, "Spline2DResampleBicubic: width/height less than 1", _state); - ae_assert(newwidth>1&&newheight>1, "Spline2DResampleBicubic: width/height less than 1", _state); - - /* - * Prepare - */ - mw = ae_maxint(oldwidth, newwidth, _state); - mh = ae_maxint(oldheight, newheight, _state); - ae_matrix_set_length(b, newheight, newwidth, _state); - ae_matrix_set_length(&buf, oldheight, newwidth, _state); - ae_vector_set_length(&x, ae_maxint(mw, mh, _state), _state); - ae_vector_set_length(&y, ae_maxint(mw, mh, _state), _state); - - /* - * Horizontal interpolation - */ - for(i=0; i<=oldheight-1; i++) - { - - /* - * Fill X, Y - */ - for(j=0; j<=oldwidth-1; j++) - { - x.ptr.p_double[j] = (double)j/(double)(oldwidth-1); - y.ptr.p_double[j] = a->ptr.pp_double[i][j]; - } - - /* - * Interpolate and place result into temporary matrix - */ - spline1dbuildcubic(&x, &y, oldwidth, 0, 0.0, 0, 0.0, &c, _state); - for(j=0; j<=newwidth-1; j++) - { - buf.ptr.pp_double[i][j] = spline1dcalc(&c, (double)j/(double)(newwidth-1), _state); - } - } - - /* - * Vertical interpolation - */ - for(j=0; j<=newwidth-1; j++) - { - - /* - * Fill X, Y - */ - for(i=0; i<=oldheight-1; i++) - { - x.ptr.p_double[i] = (double)i/(double)(oldheight-1); - y.ptr.p_double[i] = buf.ptr.pp_double[i][j]; - } - - /* - * Interpolate and place result into B - */ - spline1dbuildcubic(&x, &y, oldheight, 0, 0.0, 0, 0.0, &c, _state); - for(i=0; i<=newheight-1; i++) - { - b->ptr.pp_double[i][j] = spline1dcalc(&c, (double)i/(double)(newheight-1), _state); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Bilinear spline resampling - -Input parameters: - A - function values at the old grid, - array[0..OldHeight-1, 0..OldWidth-1] - OldHeight - old grid height, OldHeight>1 - OldWidth - old grid width, OldWidth>1 - NewHeight - new grid height, NewHeight>1 - NewWidth - new grid width, NewWidth>1 - -Output parameters: - B - function values at the new grid, - array[0..NewHeight-1, 0..NewWidth-1] - - -- ALGLIB routine -- - 09.07.2007 - Copyright by Bochkanov Sergey -*************************************************************************/ -void spline2dresamplebilinear(/* Real */ ae_matrix* a, - ae_int_t oldheight, - ae_int_t oldwidth, - /* Real */ ae_matrix* b, - ae_int_t newheight, - ae_int_t newwidth, - ae_state *_state) -{ - ae_int_t l; - ae_int_t c; - double t; - double u; - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(b); - - ae_assert(oldwidth>1&&oldheight>1, "Spline2DResampleBilinear: width/height less than 1", _state); - ae_assert(newwidth>1&&newheight>1, "Spline2DResampleBilinear: width/height less than 1", _state); - ae_matrix_set_length(b, newheight, newwidth, _state); - for(i=0; i<=newheight-1; i++) - { - for(j=0; j<=newwidth-1; j++) - { - l = i*(oldheight-1)/(newheight-1); - if( l==oldheight-1 ) - { - l = oldheight-2; - } - u = (double)i/(double)(newheight-1)*(oldheight-1)-l; - c = j*(oldwidth-1)/(newwidth-1); - if( c==oldwidth-1 ) - { - c = oldwidth-2; - } - t = (double)(j*(oldwidth-1))/(double)(newwidth-1)-c; - b->ptr.pp_double[i][j] = (1-t)*(1-u)*a->ptr.pp_double[l][c]+t*(1-u)*a->ptr.pp_double[l][c+1]+t*u*a->ptr.pp_double[l+1][c+1]+(1-t)*u*a->ptr.pp_double[l+1][c]; - } - } -} - - -/************************************************************************* -This subroutine builds bilinear vector-valued spline. - -Input parameters: - X - spline abscissas, array[0..N-1] - Y - spline ordinates, array[0..M-1] - F - function values, array[0..M*N*D-1]: - * first D elements store D values at (X[0],Y[0]) - * next D elements store D values at (X[1],Y[0]) - * general form - D function values at (X[i],Y[j]) are stored - at F[D*(J*N+I)...D*(J*N+I)+D-1]. - M,N - grid size, M>=2, N>=2 - D - vector dimension, D>=1 - -Output parameters: - C - spline interpolant - - -- ALGLIB PROJECT -- - Copyright 16.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildbilinearv(/* Real */ ae_vector* x, - ae_int_t n, - /* Real */ ae_vector* y, - ae_int_t m, - /* Real */ ae_vector* f, - ae_int_t d, - spline2dinterpolant* c, - ae_state *_state) -{ - double t; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t i0; - - _spline2dinterpolant_clear(c); - - ae_assert(n>=2, "Spline2DBuildBilinearV: N is less then 2", _state); - ae_assert(m>=2, "Spline2DBuildBilinearV: M is less then 2", _state); - ae_assert(d>=1, "Spline2DBuildBilinearV: invalid argument D (D<1)", _state); - ae_assert(x->cnt>=n&&y->cnt>=m, "Spline2DBuildBilinearV: length of X or Y is too short (Length(X/Y)cnt>=k, "Spline2DBuildBilinearV: length of F is too short (Length(F)n = n; - c->m = m; - c->d = d; - c->stype = -1; - ae_vector_set_length(&c->x, c->n, _state); - ae_vector_set_length(&c->y, c->m, _state); - ae_vector_set_length(&c->f, k, _state); - for(i=0; i<=c->n-1; i++) - { - c->x.ptr.p_double[i] = x->ptr.p_double[i]; - } - for(i=0; i<=c->m-1; i++) - { - c->y.ptr.p_double[i] = y->ptr.p_double[i]; - } - for(i=0; i<=k-1; i++) - { - c->f.ptr.p_double[i] = f->ptr.p_double[i]; - } - - /* - * Sort points - */ - for(j=0; j<=c->n-1; j++) - { - k = j; - for(i=j+1; i<=c->n-1; i++) - { - if( ae_fp_less(c->x.ptr.p_double[i],c->x.ptr.p_double[k]) ) - { - k = i; - } - } - if( k!=j ) - { - for(i=0; i<=c->m-1; i++) - { - for(i0=0; i0<=c->d-1; i0++) - { - t = c->f.ptr.p_double[c->d*(i*c->n+j)+i0]; - c->f.ptr.p_double[c->d*(i*c->n+j)+i0] = c->f.ptr.p_double[c->d*(i*c->n+k)+i0]; - c->f.ptr.p_double[c->d*(i*c->n+k)+i0] = t; - } - } - t = c->x.ptr.p_double[j]; - c->x.ptr.p_double[j] = c->x.ptr.p_double[k]; - c->x.ptr.p_double[k] = t; - } - } - for(i=0; i<=c->m-1; i++) - { - k = i; - for(j=i+1; j<=c->m-1; j++) - { - if( ae_fp_less(c->y.ptr.p_double[j],c->y.ptr.p_double[k]) ) - { - k = j; - } - } - if( k!=i ) - { - for(j=0; j<=c->n-1; j++) - { - for(i0=0; i0<=c->d-1; i0++) - { - t = c->f.ptr.p_double[c->d*(i*c->n+j)+i0]; - c->f.ptr.p_double[c->d*(i*c->n+j)+i0] = c->f.ptr.p_double[c->d*(k*c->n+j)+i0]; - c->f.ptr.p_double[c->d*(k*c->n+j)+i0] = t; - } - } - t = c->y.ptr.p_double[i]; - c->y.ptr.p_double[i] = c->y.ptr.p_double[k]; - c->y.ptr.p_double[k] = t; - } - } -} - - -/************************************************************************* -This subroutine builds bicubic vector-valued spline. - -Input parameters: - X - spline abscissas, array[0..N-1] - Y - spline ordinates, array[0..M-1] - F - function values, array[0..M*N*D-1]: - * first D elements store D values at (X[0],Y[0]) - * next D elements store D values at (X[1],Y[0]) - * general form - D function values at (X[i],Y[j]) are stored - at F[D*(J*N+I)...D*(J*N+I)+D-1]. - M,N - grid size, M>=2, N>=2 - D - vector dimension, D>=1 - -Output parameters: - C - spline interpolant - - -- ALGLIB PROJECT -- - Copyright 16.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildbicubicv(/* Real */ ae_vector* x, - ae_int_t n, - /* Real */ ae_vector* y, - ae_int_t m, - /* Real */ ae_vector* f, - ae_int_t d, - spline2dinterpolant* c, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _f; - ae_matrix tf; - ae_matrix dx; - ae_matrix dy; - ae_matrix dxy; - double t; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t di; - - ae_frame_make(_state, &_frame_block); - memset(&_f, 0, sizeof(_f)); - memset(&tf, 0, sizeof(tf)); - memset(&dx, 0, sizeof(dx)); - memset(&dy, 0, sizeof(dy)); - memset(&dxy, 0, sizeof(dxy)); - ae_vector_init_copy(&_f, f, _state, ae_true); - f = &_f; - _spline2dinterpolant_clear(c); - ae_matrix_init(&tf, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&dx, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&dy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&dxy, 0, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=2, "Spline2DBuildBicubicV: N is less than 2", _state); - ae_assert(m>=2, "Spline2DBuildBicubicV: M is less than 2", _state); - ae_assert(d>=1, "Spline2DBuildBicubicV: invalid argument D (D<1)", _state); - ae_assert(x->cnt>=n&&y->cnt>=m, "Spline2DBuildBicubicV: length of X or Y is too short (Length(X/Y)cnt>=k, "Spline2DBuildBicubicV: length of F is too short (Length(F)d = d; - c->n = n; - c->m = m; - c->stype = -3; - k = 4*k; - ae_vector_set_length(&c->x, c->n, _state); - ae_vector_set_length(&c->y, c->m, _state); - ae_vector_set_length(&c->f, k, _state); - ae_matrix_set_length(&tf, c->m, c->n, _state); - for(i=0; i<=c->n-1; i++) - { - c->x.ptr.p_double[i] = x->ptr.p_double[i]; - } - for(i=0; i<=c->m-1; i++) - { - c->y.ptr.p_double[i] = y->ptr.p_double[i]; - } - - /* - * Sort points - */ - for(j=0; j<=c->n-1; j++) - { - k = j; - for(i=j+1; i<=c->n-1; i++) - { - if( ae_fp_less(c->x.ptr.p_double[i],c->x.ptr.p_double[k]) ) - { - k = i; - } - } - if( k!=j ) - { - for(i=0; i<=c->m-1; i++) - { - for(di=0; di<=c->d-1; di++) - { - t = f->ptr.p_double[c->d*(i*c->n+j)+di]; - f->ptr.p_double[c->d*(i*c->n+j)+di] = f->ptr.p_double[c->d*(i*c->n+k)+di]; - f->ptr.p_double[c->d*(i*c->n+k)+di] = t; - } - } - t = c->x.ptr.p_double[j]; - c->x.ptr.p_double[j] = c->x.ptr.p_double[k]; - c->x.ptr.p_double[k] = t; - } - } - for(i=0; i<=c->m-1; i++) - { - k = i; - for(j=i+1; j<=c->m-1; j++) - { - if( ae_fp_less(c->y.ptr.p_double[j],c->y.ptr.p_double[k]) ) - { - k = j; - } - } - if( k!=i ) - { - for(j=0; j<=c->n-1; j++) - { - for(di=0; di<=c->d-1; di++) - { - t = f->ptr.p_double[c->d*(i*c->n+j)+di]; - f->ptr.p_double[c->d*(i*c->n+j)+di] = f->ptr.p_double[c->d*(k*c->n+j)+di]; - f->ptr.p_double[c->d*(k*c->n+j)+di] = t; - } - } - t = c->y.ptr.p_double[i]; - c->y.ptr.p_double[i] = c->y.ptr.p_double[k]; - c->y.ptr.p_double[k] = t; - } - } - for(di=0; di<=c->d-1; di++) - { - for(i=0; i<=c->m-1; i++) - { - for(j=0; j<=c->n-1; j++) - { - tf.ptr.pp_double[i][j] = f->ptr.p_double[c->d*(i*c->n+j)+di]; - } - } - spline2d_bicubiccalcderivatives(&tf, &c->x, &c->y, c->m, c->n, &dx, &dy, &dxy, _state); - for(i=0; i<=c->m-1; i++) - { - for(j=0; j<=c->n-1; j++) - { - k = c->d*(i*c->n+j)+di; - c->f.ptr.p_double[k] = tf.ptr.pp_double[i][j]; - c->f.ptr.p_double[c->n*c->m*c->d+k] = dx.ptr.pp_double[i][j]; - c->f.ptr.p_double[2*c->n*c->m*c->d+k] = dy.ptr.pp_double[i][j]; - c->f.ptr.p_double[3*c->n*c->m*c->d+k] = dxy.ptr.pp_double[i][j]; - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This subroutine unpacks two-dimensional spline into the coefficients table - -Input parameters: - C - spline interpolant. - -Result: - M, N- grid size (x-axis and y-axis) - D - number of components - Tbl - coefficients table, unpacked format, - D - components: [0..(N-1)*(M-1)*D-1, 0..19]. - For T=0..D-1 (component index), I = 0...N-2 (x index), - J=0..M-2 (y index): - K := T + I*D + J*D*(N-1) - - K-th row stores decomposition for T-th component of the - vector-valued function - - Tbl[K,0] = X[i] - Tbl[K,1] = X[i+1] - Tbl[K,2] = Y[j] - Tbl[K,3] = Y[j+1] - Tbl[K,4] = C00 - Tbl[K,5] = C01 - Tbl[K,6] = C02 - Tbl[K,7] = C03 - Tbl[K,8] = C10 - Tbl[K,9] = C11 - ... - Tbl[K,19] = C33 - On each grid square spline is equals to: - S(x) = SUM(c[i,j]*(t^i)*(u^j), i=0..3, j=0..3) - t = x-x[j] - u = y-y[i] - - -- ALGLIB PROJECT -- - Copyright 16.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline2dunpackv(spline2dinterpolant* c, - ae_int_t* m, - ae_int_t* n, - ae_int_t* d, - /* Real */ ae_matrix* tbl, - ae_state *_state) -{ - ae_int_t k; - ae_int_t p; - ae_int_t ci; - ae_int_t cj; - ae_int_t s1; - ae_int_t s2; - ae_int_t s3; - ae_int_t s4; - ae_int_t sfx; - ae_int_t sfy; - ae_int_t sfxy; - double y1; - double y2; - double y3; - double y4; - double dt; - double du; - ae_int_t i; - ae_int_t j; - ae_int_t k0; - - *m = 0; - *n = 0; - *d = 0; - ae_matrix_clear(tbl); - - ae_assert(c->stype==-3||c->stype==-1, "Spline2DUnpackV: incorrect C (incorrect parameter C.SType)", _state); - *n = c->n; - *m = c->m; - *d = c->d; - ae_matrix_set_length(tbl, (*n-1)*(*m-1)*(*d), 20, _state); - sfx = *n*(*m)*(*d); - sfy = 2*(*n)*(*m)*(*d); - sfxy = 3*(*n)*(*m)*(*d); - for(i=0; i<=*m-2; i++) - { - for(j=0; j<=*n-2; j++) - { - for(k=0; k<=*d-1; k++) - { - p = *d*(i*(*n-1)+j)+k; - tbl->ptr.pp_double[p][0] = c->x.ptr.p_double[j]; - tbl->ptr.pp_double[p][1] = c->x.ptr.p_double[j+1]; - tbl->ptr.pp_double[p][2] = c->y.ptr.p_double[i]; - tbl->ptr.pp_double[p][3] = c->y.ptr.p_double[i+1]; - dt = 1/(tbl->ptr.pp_double[p][1]-tbl->ptr.pp_double[p][0]); - du = 1/(tbl->ptr.pp_double[p][3]-tbl->ptr.pp_double[p][2]); - - /* - * Bilinear interpolation - */ - if( c->stype==-1 ) - { - for(k0=4; k0<=19; k0++) - { - tbl->ptr.pp_double[p][k0] = (double)(0); - } - y1 = c->f.ptr.p_double[*d*(*n*i+j)+k]; - y2 = c->f.ptr.p_double[*d*(*n*i+(j+1))+k]; - y3 = c->f.ptr.p_double[*d*(*n*(i+1)+(j+1))+k]; - y4 = c->f.ptr.p_double[*d*(*n*(i+1)+j)+k]; - tbl->ptr.pp_double[p][4] = y1; - tbl->ptr.pp_double[p][4+1*4+0] = y2-y1; - tbl->ptr.pp_double[p][4+0*4+1] = y4-y1; - tbl->ptr.pp_double[p][4+1*4+1] = y3-y2-y4+y1; - } - - /* - * Bicubic interpolation - */ - if( c->stype==-3 ) - { - s1 = *d*(*n*i+j)+k; - s2 = *d*(*n*i+(j+1))+k; - s3 = *d*(*n*(i+1)+(j+1))+k; - s4 = *d*(*n*(i+1)+j)+k; - tbl->ptr.pp_double[p][4+0*4+0] = c->f.ptr.p_double[s1]; - tbl->ptr.pp_double[p][4+0*4+1] = c->f.ptr.p_double[sfy+s1]/du; - tbl->ptr.pp_double[p][4+0*4+2] = -3*c->f.ptr.p_double[s1]+3*c->f.ptr.p_double[s4]-2*c->f.ptr.p_double[sfy+s1]/du-c->f.ptr.p_double[sfy+s4]/du; - tbl->ptr.pp_double[p][4+0*4+3] = 2*c->f.ptr.p_double[s1]-2*c->f.ptr.p_double[s4]+c->f.ptr.p_double[sfy+s1]/du+c->f.ptr.p_double[sfy+s4]/du; - tbl->ptr.pp_double[p][4+1*4+0] = c->f.ptr.p_double[sfx+s1]/dt; - tbl->ptr.pp_double[p][4+1*4+1] = c->f.ptr.p_double[sfxy+s1]/(dt*du); - tbl->ptr.pp_double[p][4+1*4+2] = -3*c->f.ptr.p_double[sfx+s1]/dt+3*c->f.ptr.p_double[sfx+s4]/dt-2*c->f.ptr.p_double[sfxy+s1]/(dt*du)-c->f.ptr.p_double[sfxy+s4]/(dt*du); - tbl->ptr.pp_double[p][4+1*4+3] = 2*c->f.ptr.p_double[sfx+s1]/dt-2*c->f.ptr.p_double[sfx+s4]/dt+c->f.ptr.p_double[sfxy+s1]/(dt*du)+c->f.ptr.p_double[sfxy+s4]/(dt*du); - tbl->ptr.pp_double[p][4+2*4+0] = -3*c->f.ptr.p_double[s1]+3*c->f.ptr.p_double[s2]-2*c->f.ptr.p_double[sfx+s1]/dt-c->f.ptr.p_double[sfx+s2]/dt; - tbl->ptr.pp_double[p][4+2*4+1] = -3*c->f.ptr.p_double[sfy+s1]/du+3*c->f.ptr.p_double[sfy+s2]/du-2*c->f.ptr.p_double[sfxy+s1]/(dt*du)-c->f.ptr.p_double[sfxy+s2]/(dt*du); - tbl->ptr.pp_double[p][4+2*4+2] = 9*c->f.ptr.p_double[s1]-9*c->f.ptr.p_double[s2]+9*c->f.ptr.p_double[s3]-9*c->f.ptr.p_double[s4]+6*c->f.ptr.p_double[sfx+s1]/dt+3*c->f.ptr.p_double[sfx+s2]/dt-3*c->f.ptr.p_double[sfx+s3]/dt-6*c->f.ptr.p_double[sfx+s4]/dt+6*c->f.ptr.p_double[sfy+s1]/du-6*c->f.ptr.p_double[sfy+s2]/du-3*c->f.ptr.p_double[sfy+s3]/du+3*c->f.ptr.p_double[sfy+s4]/du+4*c->f.ptr.p_double[sfxy+s1]/(dt*du)+2*c->f.ptr.p_double[sfxy+s2]/(dt*du)+c->f.ptr.p_double[sfxy+s3]/(dt*du)+2*c->f.ptr.p_double[sfxy+s4]/(dt*du); - tbl->ptr.pp_double[p][4+2*4+3] = -6*c->f.ptr.p_double[s1]+6*c->f.ptr.p_double[s2]-6*c->f.ptr.p_double[s3]+6*c->f.ptr.p_double[s4]-4*c->f.ptr.p_double[sfx+s1]/dt-2*c->f.ptr.p_double[sfx+s2]/dt+2*c->f.ptr.p_double[sfx+s3]/dt+4*c->f.ptr.p_double[sfx+s4]/dt-3*c->f.ptr.p_double[sfy+s1]/du+3*c->f.ptr.p_double[sfy+s2]/du+3*c->f.ptr.p_double[sfy+s3]/du-3*c->f.ptr.p_double[sfy+s4]/du-2*c->f.ptr.p_double[sfxy+s1]/(dt*du)-c->f.ptr.p_double[sfxy+s2]/(dt*du)-c->f.ptr.p_double[sfxy+s3]/(dt*du)-2*c->f.ptr.p_double[sfxy+s4]/(dt*du); - tbl->ptr.pp_double[p][4+3*4+0] = 2*c->f.ptr.p_double[s1]-2*c->f.ptr.p_double[s2]+c->f.ptr.p_double[sfx+s1]/dt+c->f.ptr.p_double[sfx+s2]/dt; - tbl->ptr.pp_double[p][4+3*4+1] = 2*c->f.ptr.p_double[sfy+s1]/du-2*c->f.ptr.p_double[sfy+s2]/du+c->f.ptr.p_double[sfxy+s1]/(dt*du)+c->f.ptr.p_double[sfxy+s2]/(dt*du); - tbl->ptr.pp_double[p][4+3*4+2] = -6*c->f.ptr.p_double[s1]+6*c->f.ptr.p_double[s2]-6*c->f.ptr.p_double[s3]+6*c->f.ptr.p_double[s4]-3*c->f.ptr.p_double[sfx+s1]/dt-3*c->f.ptr.p_double[sfx+s2]/dt+3*c->f.ptr.p_double[sfx+s3]/dt+3*c->f.ptr.p_double[sfx+s4]/dt-4*c->f.ptr.p_double[sfy+s1]/du+4*c->f.ptr.p_double[sfy+s2]/du+2*c->f.ptr.p_double[sfy+s3]/du-2*c->f.ptr.p_double[sfy+s4]/du-2*c->f.ptr.p_double[sfxy+s1]/(dt*du)-2*c->f.ptr.p_double[sfxy+s2]/(dt*du)-c->f.ptr.p_double[sfxy+s3]/(dt*du)-c->f.ptr.p_double[sfxy+s4]/(dt*du); - tbl->ptr.pp_double[p][4+3*4+3] = 4*c->f.ptr.p_double[s1]-4*c->f.ptr.p_double[s2]+4*c->f.ptr.p_double[s3]-4*c->f.ptr.p_double[s4]+2*c->f.ptr.p_double[sfx+s1]/dt+2*c->f.ptr.p_double[sfx+s2]/dt-2*c->f.ptr.p_double[sfx+s3]/dt-2*c->f.ptr.p_double[sfx+s4]/dt+2*c->f.ptr.p_double[sfy+s1]/du-2*c->f.ptr.p_double[sfy+s2]/du-2*c->f.ptr.p_double[sfy+s3]/du+2*c->f.ptr.p_double[sfy+s4]/du+c->f.ptr.p_double[sfxy+s1]/(dt*du)+c->f.ptr.p_double[sfxy+s2]/(dt*du)+c->f.ptr.p_double[sfxy+s3]/(dt*du)+c->f.ptr.p_double[sfxy+s4]/(dt*du); - } - - /* - * Rescale Cij - */ - for(ci=0; ci<=3; ci++) - { - for(cj=0; cj<=3; cj++) - { - tbl->ptr.pp_double[p][4+ci*4+cj] = tbl->ptr.pp_double[p][4+ci*4+cj]*ae_pow(dt, (double)(ci), _state)*ae_pow(du, (double)(cj), _state); - } - } - } - } - } -} - - -/************************************************************************* -This subroutine was deprecated in ALGLIB 3.6.0 - -We recommend you to switch to Spline2DBuildBilinearV(), which is more -flexible and accepts its arguments in more convenient order. - - -- ALGLIB PROJECT -- - Copyright 05.07.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildbilinear(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_matrix* f, - ae_int_t m, - ae_int_t n, - spline2dinterpolant* c, - ae_state *_state) -{ - double t; - ae_int_t i; - ae_int_t j; - ae_int_t k; - - _spline2dinterpolant_clear(c); - - ae_assert(n>=2, "Spline2DBuildBilinear: N<2", _state); - ae_assert(m>=2, "Spline2DBuildBilinear: M<2", _state); - ae_assert(x->cnt>=n&&y->cnt>=m, "Spline2DBuildBilinear: length of X or Y is too short (Length(X/Y)rows>=m&&f->cols>=n, "Spline2DBuildBilinear: size of F is too small (rows(F)n = n; - c->m = m; - c->d = 1; - c->stype = -1; - ae_vector_set_length(&c->x, c->n, _state); - ae_vector_set_length(&c->y, c->m, _state); - ae_vector_set_length(&c->f, c->n*c->m, _state); - for(i=0; i<=c->n-1; i++) - { - c->x.ptr.p_double[i] = x->ptr.p_double[i]; - } - for(i=0; i<=c->m-1; i++) - { - c->y.ptr.p_double[i] = y->ptr.p_double[i]; - } - for(i=0; i<=c->m-1; i++) - { - for(j=0; j<=c->n-1; j++) - { - c->f.ptr.p_double[i*c->n+j] = f->ptr.pp_double[i][j]; - } - } - - /* - * Sort points - */ - for(j=0; j<=c->n-1; j++) - { - k = j; - for(i=j+1; i<=c->n-1; i++) - { - if( ae_fp_less(c->x.ptr.p_double[i],c->x.ptr.p_double[k]) ) - { - k = i; - } - } - if( k!=j ) - { - for(i=0; i<=c->m-1; i++) - { - t = c->f.ptr.p_double[i*c->n+j]; - c->f.ptr.p_double[i*c->n+j] = c->f.ptr.p_double[i*c->n+k]; - c->f.ptr.p_double[i*c->n+k] = t; - } - t = c->x.ptr.p_double[j]; - c->x.ptr.p_double[j] = c->x.ptr.p_double[k]; - c->x.ptr.p_double[k] = t; - } - } - for(i=0; i<=c->m-1; i++) - { - k = i; - for(j=i+1; j<=c->m-1; j++) - { - if( ae_fp_less(c->y.ptr.p_double[j],c->y.ptr.p_double[k]) ) - { - k = j; - } - } - if( k!=i ) - { - for(j=0; j<=c->n-1; j++) - { - t = c->f.ptr.p_double[i*c->n+j]; - c->f.ptr.p_double[i*c->n+j] = c->f.ptr.p_double[k*c->n+j]; - c->f.ptr.p_double[k*c->n+j] = t; - } - t = c->y.ptr.p_double[i]; - c->y.ptr.p_double[i] = c->y.ptr.p_double[k]; - c->y.ptr.p_double[k] = t; - } - } -} - - -/************************************************************************* -This subroutine was deprecated in ALGLIB 3.6.0 - -We recommend you to switch to Spline2DBuildBicubicV(), which is more -flexible and accepts its arguments in more convenient order. - - -- ALGLIB PROJECT -- - Copyright 05.07.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildbicubic(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_matrix* f, - ae_int_t m, - ae_int_t n, - spline2dinterpolant* c, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _f; - ae_int_t sfx; - ae_int_t sfy; - ae_int_t sfxy; - ae_matrix dx; - ae_matrix dy; - ae_matrix dxy; - double t; - ae_int_t i; - ae_int_t j; - ae_int_t k; - - ae_frame_make(_state, &_frame_block); - memset(&_f, 0, sizeof(_f)); - memset(&dx, 0, sizeof(dx)); - memset(&dy, 0, sizeof(dy)); - memset(&dxy, 0, sizeof(dxy)); - ae_matrix_init_copy(&_f, f, _state, ae_true); - f = &_f; - _spline2dinterpolant_clear(c); - ae_matrix_init(&dx, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&dy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&dxy, 0, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=2, "Spline2DBuildBicubicSpline: N<2", _state); - ae_assert(m>=2, "Spline2DBuildBicubicSpline: M<2", _state); - ae_assert(x->cnt>=n&&y->cnt>=m, "Spline2DBuildBicubic: length of X or Y is too short (Length(X/Y)rows>=m&&f->cols>=n, "Spline2DBuildBicubic: size of F is too small (rows(F)d = 1; - c->n = n; - c->m = m; - c->stype = -3; - sfx = c->n*c->m; - sfy = 2*c->n*c->m; - sfxy = 3*c->n*c->m; - ae_vector_set_length(&c->x, c->n, _state); - ae_vector_set_length(&c->y, c->m, _state); - ae_vector_set_length(&c->f, 4*c->n*c->m, _state); - for(i=0; i<=c->n-1; i++) - { - c->x.ptr.p_double[i] = x->ptr.p_double[i]; - } - for(i=0; i<=c->m-1; i++) - { - c->y.ptr.p_double[i] = y->ptr.p_double[i]; - } - - /* - * Sort points - */ - for(j=0; j<=c->n-1; j++) - { - k = j; - for(i=j+1; i<=c->n-1; i++) - { - if( ae_fp_less(c->x.ptr.p_double[i],c->x.ptr.p_double[k]) ) - { - k = i; - } - } - if( k!=j ) - { - for(i=0; i<=c->m-1; i++) - { - t = f->ptr.pp_double[i][j]; - f->ptr.pp_double[i][j] = f->ptr.pp_double[i][k]; - f->ptr.pp_double[i][k] = t; - } - t = c->x.ptr.p_double[j]; - c->x.ptr.p_double[j] = c->x.ptr.p_double[k]; - c->x.ptr.p_double[k] = t; - } - } - for(i=0; i<=c->m-1; i++) - { - k = i; - for(j=i+1; j<=c->m-1; j++) - { - if( ae_fp_less(c->y.ptr.p_double[j],c->y.ptr.p_double[k]) ) - { - k = j; - } - } - if( k!=i ) - { - for(j=0; j<=c->n-1; j++) - { - t = f->ptr.pp_double[i][j]; - f->ptr.pp_double[i][j] = f->ptr.pp_double[k][j]; - f->ptr.pp_double[k][j] = t; - } - t = c->y.ptr.p_double[i]; - c->y.ptr.p_double[i] = c->y.ptr.p_double[k]; - c->y.ptr.p_double[k] = t; - } - } - spline2d_bicubiccalcderivatives(f, &c->x, &c->y, c->m, c->n, &dx, &dy, &dxy, _state); - for(i=0; i<=c->m-1; i++) - { - for(j=0; j<=c->n-1; j++) - { - k = i*c->n+j; - c->f.ptr.p_double[k] = f->ptr.pp_double[i][j]; - c->f.ptr.p_double[sfx+k] = dx.ptr.pp_double[i][j]; - c->f.ptr.p_double[sfy+k] = dy.ptr.pp_double[i][j]; - c->f.ptr.p_double[sfxy+k] = dxy.ptr.pp_double[i][j]; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This subroutine was deprecated in ALGLIB 3.6.0 - -We recommend you to switch to Spline2DUnpackV(), which is more flexible -and accepts its arguments in more convenient order. - - -- ALGLIB PROJECT -- - Copyright 29.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2dunpack(spline2dinterpolant* c, - ae_int_t* m, - ae_int_t* n, - /* Real */ ae_matrix* tbl, - ae_state *_state) -{ - ae_int_t k; - ae_int_t p; - ae_int_t ci; - ae_int_t cj; - ae_int_t s1; - ae_int_t s2; - ae_int_t s3; - ae_int_t s4; - ae_int_t sfx; - ae_int_t sfy; - ae_int_t sfxy; - double y1; - double y2; - double y3; - double y4; - double dt; - double du; - ae_int_t i; - ae_int_t j; - - *m = 0; - *n = 0; - ae_matrix_clear(tbl); - - ae_assert(c->stype==-3||c->stype==-1, "Spline2DUnpack: incorrect C (incorrect parameter C.SType)", _state); - if( c->d!=1 ) - { - *n = 0; - *m = 0; - return; - } - *n = c->n; - *m = c->m; - ae_matrix_set_length(tbl, (*n-1)*(*m-1), 20, _state); - sfx = *n*(*m); - sfy = 2*(*n)*(*m); - sfxy = 3*(*n)*(*m); - - /* - * Fill - */ - for(i=0; i<=*m-2; i++) - { - for(j=0; j<=*n-2; j++) - { - p = i*(*n-1)+j; - tbl->ptr.pp_double[p][0] = c->x.ptr.p_double[j]; - tbl->ptr.pp_double[p][1] = c->x.ptr.p_double[j+1]; - tbl->ptr.pp_double[p][2] = c->y.ptr.p_double[i]; - tbl->ptr.pp_double[p][3] = c->y.ptr.p_double[i+1]; - dt = 1/(tbl->ptr.pp_double[p][1]-tbl->ptr.pp_double[p][0]); - du = 1/(tbl->ptr.pp_double[p][3]-tbl->ptr.pp_double[p][2]); - - /* - * Bilinear interpolation - */ - if( c->stype==-1 ) - { - for(k=4; k<=19; k++) - { - tbl->ptr.pp_double[p][k] = (double)(0); - } - y1 = c->f.ptr.p_double[*n*i+j]; - y2 = c->f.ptr.p_double[*n*i+(j+1)]; - y3 = c->f.ptr.p_double[*n*(i+1)+(j+1)]; - y4 = c->f.ptr.p_double[*n*(i+1)+j]; - tbl->ptr.pp_double[p][4] = y1; - tbl->ptr.pp_double[p][4+1*4+0] = y2-y1; - tbl->ptr.pp_double[p][4+0*4+1] = y4-y1; - tbl->ptr.pp_double[p][4+1*4+1] = y3-y2-y4+y1; - } - - /* - * Bicubic interpolation - */ - if( c->stype==-3 ) - { - s1 = *n*i+j; - s2 = *n*i+(j+1); - s3 = *n*(i+1)+(j+1); - s4 = *n*(i+1)+j; - tbl->ptr.pp_double[p][4+0*4+0] = c->f.ptr.p_double[s1]; - tbl->ptr.pp_double[p][4+0*4+1] = c->f.ptr.p_double[sfy+s1]/du; - tbl->ptr.pp_double[p][4+0*4+2] = -3*c->f.ptr.p_double[s1]+3*c->f.ptr.p_double[s4]-2*c->f.ptr.p_double[sfy+s1]/du-c->f.ptr.p_double[sfy+s4]/du; - tbl->ptr.pp_double[p][4+0*4+3] = 2*c->f.ptr.p_double[s1]-2*c->f.ptr.p_double[s4]+c->f.ptr.p_double[sfy+s1]/du+c->f.ptr.p_double[sfy+s4]/du; - tbl->ptr.pp_double[p][4+1*4+0] = c->f.ptr.p_double[sfx+s1]/dt; - tbl->ptr.pp_double[p][4+1*4+1] = c->f.ptr.p_double[sfxy+s1]/(dt*du); - tbl->ptr.pp_double[p][4+1*4+2] = -3*c->f.ptr.p_double[sfx+s1]/dt+3*c->f.ptr.p_double[sfx+s4]/dt-2*c->f.ptr.p_double[sfxy+s1]/(dt*du)-c->f.ptr.p_double[sfxy+s4]/(dt*du); - tbl->ptr.pp_double[p][4+1*4+3] = 2*c->f.ptr.p_double[sfx+s1]/dt-2*c->f.ptr.p_double[sfx+s4]/dt+c->f.ptr.p_double[sfxy+s1]/(dt*du)+c->f.ptr.p_double[sfxy+s4]/(dt*du); - tbl->ptr.pp_double[p][4+2*4+0] = -3*c->f.ptr.p_double[s1]+3*c->f.ptr.p_double[s2]-2*c->f.ptr.p_double[sfx+s1]/dt-c->f.ptr.p_double[sfx+s2]/dt; - tbl->ptr.pp_double[p][4+2*4+1] = -3*c->f.ptr.p_double[sfy+s1]/du+3*c->f.ptr.p_double[sfy+s2]/du-2*c->f.ptr.p_double[sfxy+s1]/(dt*du)-c->f.ptr.p_double[sfxy+s2]/(dt*du); - tbl->ptr.pp_double[p][4+2*4+2] = 9*c->f.ptr.p_double[s1]-9*c->f.ptr.p_double[s2]+9*c->f.ptr.p_double[s3]-9*c->f.ptr.p_double[s4]+6*c->f.ptr.p_double[sfx+s1]/dt+3*c->f.ptr.p_double[sfx+s2]/dt-3*c->f.ptr.p_double[sfx+s3]/dt-6*c->f.ptr.p_double[sfx+s4]/dt+6*c->f.ptr.p_double[sfy+s1]/du-6*c->f.ptr.p_double[sfy+s2]/du-3*c->f.ptr.p_double[sfy+s3]/du+3*c->f.ptr.p_double[sfy+s4]/du+4*c->f.ptr.p_double[sfxy+s1]/(dt*du)+2*c->f.ptr.p_double[sfxy+s2]/(dt*du)+c->f.ptr.p_double[sfxy+s3]/(dt*du)+2*c->f.ptr.p_double[sfxy+s4]/(dt*du); - tbl->ptr.pp_double[p][4+2*4+3] = -6*c->f.ptr.p_double[s1]+6*c->f.ptr.p_double[s2]-6*c->f.ptr.p_double[s3]+6*c->f.ptr.p_double[s4]-4*c->f.ptr.p_double[sfx+s1]/dt-2*c->f.ptr.p_double[sfx+s2]/dt+2*c->f.ptr.p_double[sfx+s3]/dt+4*c->f.ptr.p_double[sfx+s4]/dt-3*c->f.ptr.p_double[sfy+s1]/du+3*c->f.ptr.p_double[sfy+s2]/du+3*c->f.ptr.p_double[sfy+s3]/du-3*c->f.ptr.p_double[sfy+s4]/du-2*c->f.ptr.p_double[sfxy+s1]/(dt*du)-c->f.ptr.p_double[sfxy+s2]/(dt*du)-c->f.ptr.p_double[sfxy+s3]/(dt*du)-2*c->f.ptr.p_double[sfxy+s4]/(dt*du); - tbl->ptr.pp_double[p][4+3*4+0] = 2*c->f.ptr.p_double[s1]-2*c->f.ptr.p_double[s2]+c->f.ptr.p_double[sfx+s1]/dt+c->f.ptr.p_double[sfx+s2]/dt; - tbl->ptr.pp_double[p][4+3*4+1] = 2*c->f.ptr.p_double[sfy+s1]/du-2*c->f.ptr.p_double[sfy+s2]/du+c->f.ptr.p_double[sfxy+s1]/(dt*du)+c->f.ptr.p_double[sfxy+s2]/(dt*du); - tbl->ptr.pp_double[p][4+3*4+2] = -6*c->f.ptr.p_double[s1]+6*c->f.ptr.p_double[s2]-6*c->f.ptr.p_double[s3]+6*c->f.ptr.p_double[s4]-3*c->f.ptr.p_double[sfx+s1]/dt-3*c->f.ptr.p_double[sfx+s2]/dt+3*c->f.ptr.p_double[sfx+s3]/dt+3*c->f.ptr.p_double[sfx+s4]/dt-4*c->f.ptr.p_double[sfy+s1]/du+4*c->f.ptr.p_double[sfy+s2]/du+2*c->f.ptr.p_double[sfy+s3]/du-2*c->f.ptr.p_double[sfy+s4]/du-2*c->f.ptr.p_double[sfxy+s1]/(dt*du)-2*c->f.ptr.p_double[sfxy+s2]/(dt*du)-c->f.ptr.p_double[sfxy+s3]/(dt*du)-c->f.ptr.p_double[sfxy+s4]/(dt*du); - tbl->ptr.pp_double[p][4+3*4+3] = 4*c->f.ptr.p_double[s1]-4*c->f.ptr.p_double[s2]+4*c->f.ptr.p_double[s3]-4*c->f.ptr.p_double[s4]+2*c->f.ptr.p_double[sfx+s1]/dt+2*c->f.ptr.p_double[sfx+s2]/dt-2*c->f.ptr.p_double[sfx+s3]/dt-2*c->f.ptr.p_double[sfx+s4]/dt+2*c->f.ptr.p_double[sfy+s1]/du-2*c->f.ptr.p_double[sfy+s2]/du-2*c->f.ptr.p_double[sfy+s3]/du+2*c->f.ptr.p_double[sfy+s4]/du+c->f.ptr.p_double[sfxy+s1]/(dt*du)+c->f.ptr.p_double[sfxy+s2]/(dt*du)+c->f.ptr.p_double[sfxy+s3]/(dt*du)+c->f.ptr.p_double[sfxy+s4]/(dt*du); - } - - /* - * Rescale Cij - */ - for(ci=0; ci<=3; ci++) - { - for(cj=0; cj<=3; cj++) - { - tbl->ptr.pp_double[p][4+ci*4+cj] = tbl->ptr.pp_double[p][4+ci*4+cj]*ae_pow(dt, (double)(ci), _state)*ae_pow(du, (double)(cj), _state); - } - } - } - } -} - - -/************************************************************************* -This subroutine creates least squares solver used to fit 2D splines to -irregularly sampled (scattered) data. - -Solver object is used to perform spline fits as follows: -* solver object is created with spline2dbuildercreate() function -* dataset is added with spline2dbuildersetpoints() function -* fit area is chosen: - * spline2dbuildersetarea() - for user-defined area - * spline2dbuildersetareaauto() - for automatically chosen area -* number of grid nodes is chosen with spline2dbuildersetgrid() -* prior term is chosen with one of the following functions: - * spline2dbuildersetlinterm() to set linear prior - * spline2dbuildersetconstterm() to set constant prior - * spline2dbuildersetzeroterm() to set zero prior - * spline2dbuildersetuserterm() to set user-defined constant prior -* solver algorithm is chosen with either: - * spline2dbuildersetalgoblocklls() - BlockLLS algorithm, medium-scale problems - * spline2dbuildersetalgofastddm() - FastDDM algorithm, large-scale problems -* finally, fitting itself is performed with spline2dfit() function. - -Most of the steps above can be omitted, solver is configured with good -defaults. The minimum is to call: -* spline2dbuildercreate() to create solver object -* spline2dbuildersetpoints() to specify dataset -* spline2dbuildersetgrid() to tell how many nodes you need -* spline2dfit() to perform fit - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - D - positive number, number of Y-components: D=1 for simple scalar - fit, D>1 for vector-valued spline fitting. - -OUTPUT PARAMETERS: - S - solver object - - -- ALGLIB PROJECT -- - Copyright 29.01.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildercreate(ae_int_t d, - spline2dbuilder* state, - ae_state *_state) -{ - - _spline2dbuilder_clear(state); - - ae_assert(d>=1, "Spline2DBuilderCreate: D<=0", _state); - - /* - * NOTES: - * - * 1. Prior term is set to linear one (good default option) - * 2. Solver is set to BlockLLS - good enough for small-scale problems. - * 3. Refinement rounds: 5; enough to get good convergence. - */ - state->priorterm = 1; - state->priortermval = (double)(0); - state->areatype = 0; - state->gridtype = 0; - state->smoothing = 0.0; - state->nlayers = 0; - state->solvertype = 1; - state->npoints = 0; - state->d = d; - state->sx = 1.0; - state->sy = 1.0; - state->lsqrcnt = 5; - - /* - * Algorithm settings - */ - state->adddegreeoffreedom = ae_true; - state->maxcoresize = 16; - state->interfacesize = 5; -} - - -/************************************************************************* -This function sets constant prior term (model is a sum of bicubic spline -and global prior, which can be linear, constant, user-defined constant or -zero). - -Constant prior term is determined by least squares fitting. - -INPUT PARAMETERS: - S - spline builder - V - value for user-defined prior - - -- ALGLIB -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetuserterm(spline2dbuilder* state, - double v, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(v, _state), "Spline2DBuilderSetUserTerm: infinite/NAN value passed", _state); - state->priorterm = 0; - state->priortermval = v; -} - - -/************************************************************************* -This function sets linear prior term (model is a sum of bicubic spline and -global prior, which can be linear, constant, user-defined constant or -zero). - -Linear prior term is determined by least squares fitting. - -INPUT PARAMETERS: - S - spline builder - - -- ALGLIB -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetlinterm(spline2dbuilder* state, ae_state *_state) -{ - - - state->priorterm = 1; -} - - -/************************************************************************* -This function sets constant prior term (model is a sum of bicubic spline -and global prior, which can be linear, constant, user-defined constant or -zero). - -Constant prior term is determined by least squares fitting. - -INPUT PARAMETERS: - S - spline builder - - -- ALGLIB -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetconstterm(spline2dbuilder* state, ae_state *_state) -{ - - - state->priorterm = 2; -} - - -/************************************************************************* -This function sets zero prior term (model is a sum of bicubic spline and -global prior, which can be linear, constant, user-defined constant or -zero). - -INPUT PARAMETERS: - S - spline builder - - -- ALGLIB -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetzeroterm(spline2dbuilder* state, ae_state *_state) -{ - - - state->priorterm = 3; -} - - -/************************************************************************* -This function adds dataset to the builder object. - -This function overrides results of the previous calls, i.e. multiple calls -of this function will result in only the last set being added. - -INPUT PARAMETERS: - S - spline 2D builder object - XY - points, array[N,2+D]. One row corresponds to one point - in the dataset. First 2 elements are coordinates, next - D elements are function values. Array may be larger than - specified, in this case only leading [N,NX+NY] elements - will be used. - N - number of points in the dataset - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetpoints(spline2dbuilder* state, - /* Real */ ae_matrix* xy, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t ew; - - - ae_assert(n>0, "Spline2DBuilderSetPoints: N<0", _state); - ae_assert(xy->rows>=n, "Spline2DBuilderSetPoints: Rows(XY)cols>=2+state->d, "Spline2DBuilderSetPoints: Cols(XY)d, _state), "Spline2DBuilderSetPoints: XY contains infinite or NaN values!", _state); - state->npoints = n; - ew = 2+state->d; - rvectorsetlengthatleast(&state->xy, n*ew, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=ew-1; j++) - { - state->xy.ptr.p_double[i*ew+j] = xy->ptr.pp_double[i][j]; - } - } -} - - -/************************************************************************* -This function sets area where 2D spline interpolant is built. "Auto" means -that area extent is determined automatically from dataset extent. - -INPUT PARAMETERS: - S - spline 2D builder object - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetareaauto(spline2dbuilder* state, ae_state *_state) -{ - - - state->areatype = 0; -} - - -/************************************************************************* -This function sets area where 2D spline interpolant is built to -user-defined one: [XA,XB]*[YA,YB] - -INPUT PARAMETERS: - S - spline 2D builder object - XA,XB - spatial extent in the first (X) dimension, XA=XB", _state); - ae_assert(ae_fp_less(ya,yb), "Spline2DBuilderSetArea: YA>=YB", _state); - state->areatype = 1; - state->xa = xa; - state->xb = xb; - state->ya = ya; - state->yb = yb; -} - - -/************************************************************************* -This function sets nodes count for 2D spline interpolant. Fitting is -performed on area defined with one of the "setarea" functions; this one -sets number of nodes placed upon the fitting area. - -INPUT PARAMETERS: - S - spline 2D builder object - KX - nodes count for the first (X) dimension; fitting interval - [XA,XB] is separated into KX-1 subintervals, with KX nodes - created at the boundaries. - KY - nodes count for the first (Y) dimension; fitting interval - [YA,YB] is separated into KY-1 subintervals, with KY nodes - created at the boundaries. - -NOTE: at least 4 nodes is created in each dimension, so KX and KY are - silently increased if needed. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetgrid(spline2dbuilder* state, - ae_int_t kx, - ae_int_t ky, - ae_state *_state) -{ - - - ae_assert(kx>0, "Spline2DBuilderSetGridSizePrecisely: KX<=0", _state); - ae_assert(ky>0, "Spline2DBuilderSetGridSizePrecisely: KY<=0", _state); - state->gridtype = 1; - state->kx = ae_maxint(kx, 4, _state); - state->ky = ae_maxint(ky, 4, _state); -} - - -/************************************************************************* -This function allows you to choose least squares solver used to perform -fitting. This function sets solver algorithm to "FastDDM", which performs -fast parallel fitting by splitting problem into smaller chunks and merging -results together. - -This solver is optimized for large-scale problems, starting from 256x256 -grids, and up to 10000x10000 grids. Of course, it will work for smaller -grids too. - -More detailed description of the algorithm is given below: -* algorithm generates hierarchy of nested grids, ranging from ~16x16 - (topmost "layer" of the model) to ~KX*KY one (final layer). Upper layers - model global behavior of the function, lower layers are used to model - fine details. Moving from layer to layer doubles grid density. -* fitting is started from topmost layer, subsequent layers are fitted - using residuals from previous ones. -* user may choose to skip generation of upper layers and generate only a - few bottom ones, which will result in much better performance and - parallelization efficiency, at the cost of algorithm inability to "patch" - large holes in the dataset. -* every layer is regularized using progressively increasing regularization - coefficient; thus, increasing LambdaV penalizes fine details first, - leaving lower frequencies almost intact for a while. -* after fitting is done, all layers are merged together into one bicubic - spline - -IMPORTANT: regularization coefficient used by this solver is different - from the one used by BlockLLS. Latter utilizes nonlinearity - penalty, which is global in nature (large regularization - results in global linear trend being extracted); this solver - uses another, localized form of penalty, which is suitable for - parallel processing. - -Notes on memory and performance: -* memory requirements: most memory is consumed during modeling of the - higher layers; ~[512*NPoints] bytes is required for a model with full - hierarchy of grids being generated. However, if you skip a few topmost - layers, you will get nearly constant (wrt. points count and grid size) - memory consumption. -* serial running time: O(K*K)+O(NPoints) for a KxK grid -* parallelism potential: good. You may get nearly linear speed-up when - performing fitting with just a few layers. Adding more layers results in - model becoming more global, which somewhat reduces efficiency of the - parallel code. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - spline 2D builder object - NLayers - number of layers in the model: - * NLayers>=1 means that up to chosen number of bottom - layers is fitted - * NLayers=0 means that maximum number of layers is chosen - (according to current grid size) - * NLayers<=-1 means that up to |NLayers| topmost layers is - skipped - Recommendations: - * good "default" value is 2 layers - * you may need more layers, if your dataset is very - irregular and you want to "patch" large holes. For a - grid step H (equal to AreaWidth/GridSize) you may expect - that last layer reproduces variations at distance H (and - can patch holes that wide); that higher layers operate - at distances 2*H, 4*H, 8*H and so on. - * good value for "bullletproof" mode is NLayers=0, which - results in complete hierarchy of layers being generated. - LambdaV - regularization coefficient, chosen in such a way that it - penalizes bottom layers (fine details) first. - LambdaV>=0, zero value means that no penalty is applied. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetalgofastddm(spline2dbuilder* state, - ae_int_t nlayers, - double lambdav, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(lambdav, _state), "Spline2DBuilderSetAlgoFastDDM: LambdaV is not finite value", _state); - ae_assert(ae_fp_greater_eq(lambdav,(double)(0)), "Spline2DBuilderSetAlgoFastDDM: LambdaV<0", _state); - state->solvertype = 3; - state->nlayers = nlayers; - state->smoothing = lambdav; -} - - -/************************************************************************* -This function allows you to choose least squares solver used to perform -fitting. This function sets solver algorithm to "BlockLLS", which performs -least squares fitting with fast sparse direct solver, with optional -nonsmoothness penalty being applied. - -Nonlinearity penalty has the following form: - - [ ] - P() ~ Lambda* integral[ (d2S/dx2)^2 + 2*(d2S/dxdy)^2 + (d2S/dy2)^2 ]dxdy - [ ] - -here integral is calculated over entire grid, and "~" means "proportional" -because integral is normalized after calcilation. Extremely large values -of Lambda result in linear fit being performed. - -NOTE: this algorithm is the most robust and controllable one, but it is - limited by 512x512 grids and (say) up to 1.000.000 points. However, - ALGLIB has one more spline solver: FastDDM algorithm, which is - intended for really large-scale problems (in 10M-100M range). FastDDM - algorithm also has better parallelism properties. - -More information on BlockLLS solver: -* memory requirements: ~[32*K^3+256*NPoints] bytes for KxK grid with - NPoints-sized dataset -* serial running time: O(K^4+NPoints) -* parallelism potential: limited. You may get some sublinear gain when - working with large grids (K's in 256..512 range) - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - spline 2D builder object - LambdaNS- non-negative value: - * positive value means that some smoothing is applied - * zero value means that no smoothing is applied, and - corresponding entries of design matrix are numerically - zero and dropped from consideration. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetalgoblocklls(spline2dbuilder* state, - double lambdans, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(lambdans, _state), "Spline2DBuilderSetAlgoBlockLLS: LambdaNS is not finite value", _state); - ae_assert(ae_fp_greater_eq(lambdans,(double)(0)), "Spline2DBuilderSetAlgoBlockLLS: LambdaNS<0", _state); - state->solvertype = 1; - state->smoothing = lambdans; -} - - -/************************************************************************* -This function allows you to choose least squares solver used to perform -fitting. This function sets solver algorithm to "NaiveLLS". - -IMPORTANT: NaiveLLS is NOT intended to be used in real life code! This - algorithm solves problem by generated dense (K^2)x(K^2+NPoints) - matrix and solves linear least squares problem with dense - solver. - - It is here just to test BlockLLS against reference solver - (and maybe for someone trying to compare well optimized solver - against straightforward approach to the LLS problem). - -More information on naive LLS solver: -* memory requirements: ~[8*K^4+256*NPoints] bytes for KxK grid. -* serial running time: O(K^6+NPoints) for KxK grid -* when compared with BlockLLS, NaiveLLS has ~K larger memory demand and - ~K^2 larger running time. - -INPUT PARAMETERS: - S - spline 2D builder object - LambdaNS- nonsmoothness penalty - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetalgonaivells(spline2dbuilder* state, - double lambdans, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(lambdans, _state), "Spline2DBuilderSetAlgoBlockLLS: LambdaNS is not finite value", _state); - ae_assert(ae_fp_greater_eq(lambdans,(double)(0)), "Spline2DBuilderSetAlgoBlockLLS: LambdaNS<0", _state); - state->solvertype = 2; - state->smoothing = lambdans; -} - - -/************************************************************************* -This function fits bicubic spline to current dataset, using current area/ -grid and current LLS solver. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - State - spline 2D builder object - -OUTPUT PARAMETERS: - S - 2D spline, fit result - Rep - fitting report, which provides some additional info about - errors, R2 coefficient and so on. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dfit(spline2dbuilder* state, - spline2dinterpolant* s, - spline2dfitreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - double xa; - double xb; - double ya; - double yb; - double xaraw; - double xbraw; - double yaraw; - double ybraw; - ae_int_t kx; - ae_int_t ky; - double hx; - double hy; - double invhx; - double invhy; - ae_int_t gridexpansion; - ae_int_t nzwidth; - ae_int_t bfrad; - ae_int_t npoints; - ae_int_t d; - ae_int_t ew; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - ae_int_t k0; - ae_int_t k1; - double vx; - double vy; - ae_int_t arows; - ae_int_t acopied; - ae_int_t basecasex; - ae_int_t basecasey; - double eps; - ae_vector xywork; - ae_matrix vterm; - ae_vector tmpx; - ae_vector tmpy; - ae_vector tmp0; - ae_vector tmp1; - ae_vector meany; - ae_vector xyindex; - ae_vector tmpi; - spline1dinterpolant basis1; - sparsematrix av; - sparsematrix ah; - spline2dxdesignmatrix xdesignmatrix; - ae_vector z; - spline2dblockllsbuf blockllsbuf; - ae_int_t sfx; - ae_int_t sfy; - ae_int_t sfxy; - double tss; - ae_int_t dstidx; - - ae_frame_make(_state, &_frame_block); - memset(&xywork, 0, sizeof(xywork)); - memset(&vterm, 0, sizeof(vterm)); - memset(&tmpx, 0, sizeof(tmpx)); - memset(&tmpy, 0, sizeof(tmpy)); - memset(&tmp0, 0, sizeof(tmp0)); - memset(&tmp1, 0, sizeof(tmp1)); - memset(&meany, 0, sizeof(meany)); - memset(&xyindex, 0, sizeof(xyindex)); - memset(&tmpi, 0, sizeof(tmpi)); - memset(&basis1, 0, sizeof(basis1)); - memset(&av, 0, sizeof(av)); - memset(&ah, 0, sizeof(ah)); - memset(&xdesignmatrix, 0, sizeof(xdesignmatrix)); - memset(&z, 0, sizeof(z)); - memset(&blockllsbuf, 0, sizeof(blockllsbuf)); - _spline2dinterpolant_clear(s); - _spline2dfitreport_clear(rep); - ae_vector_init(&xywork, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vterm, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpy, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&meany, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xyindex, 0, DT_INT, _state, ae_true); - ae_vector_init(&tmpi, 0, DT_INT, _state, ae_true); - _spline1dinterpolant_init(&basis1, _state, ae_true); - _sparsematrix_init(&av, _state, ae_true); - _sparsematrix_init(&ah, _state, ae_true); - _spline2dxdesignmatrix_init(&xdesignmatrix, _state, ae_true); - ae_vector_init(&z, 0, DT_REAL, _state, ae_true); - _spline2dblockllsbuf_init(&blockllsbuf, _state, ae_true); - - nzwidth = 4; - bfrad = 2; - npoints = state->npoints; - d = state->d; - ew = 2+d; - - /* - * Integrity checks - */ - ae_assert(ae_fp_eq(state->sx,(double)(1)), "Spline2DFit: integrity error", _state); - ae_assert(ae_fp_eq(state->sy,(double)(1)), "Spline2DFit: integrity error", _state); - - /* - * Determine actual area size and grid step - * - * NOTE: initialize vars by zeros in order to avoid spurious - * compiler warnings. - */ - xa = (double)(0); - xb = (double)(0); - ya = (double)(0); - yb = (double)(0); - if( state->areatype==0 ) - { - if( npoints>0 ) - { - xa = state->xy.ptr.p_double[0]; - xb = state->xy.ptr.p_double[0]; - ya = state->xy.ptr.p_double[1]; - yb = state->xy.ptr.p_double[1]; - for(i=1; i<=npoints-1; i++) - { - xa = ae_minreal(xa, state->xy.ptr.p_double[i*ew+0], _state); - xb = ae_maxreal(xb, state->xy.ptr.p_double[i*ew+0], _state); - ya = ae_minreal(ya, state->xy.ptr.p_double[i*ew+1], _state); - yb = ae_maxreal(yb, state->xy.ptr.p_double[i*ew+1], _state); - } - } - else - { - xa = (double)(-1); - xb = (double)(1); - ya = (double)(-1); - yb = (double)(1); - } - } - else - { - if( state->areatype==1 ) - { - xa = state->xa; - xb = state->xb; - ya = state->ya; - yb = state->yb; - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - if( ae_fp_eq(xa,xb) ) - { - v = xa; - if( ae_fp_greater_eq(v,(double)(0)) ) - { - xa = v/2-1; - xb = v*2+1; - } - else - { - xa = v*2-1; - xb = v/2+1; - } - } - if( ae_fp_eq(ya,yb) ) - { - v = ya; - if( ae_fp_greater_eq(v,(double)(0)) ) - { - ya = v/2-1; - yb = v*2+1; - } - else - { - ya = v*2-1; - yb = v/2+1; - } - } - ae_assert(ae_fp_less(xa,xb), "Spline2DFit: integrity error", _state); - ae_assert(ae_fp_less(ya,yb), "Spline2DFit: integrity error", _state); - kx = 0; - ky = 0; - if( state->gridtype==0 ) - { - kx = 4; - ky = 4; - } - else - { - if( state->gridtype==1 ) - { - kx = state->kx; - ky = state->ky; - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - ae_assert(kx>0, "Spline2DFit: integrity error", _state); - ae_assert(ky>0, "Spline2DFit: integrity error", _state); - basecasex = -1; - basecasey = -1; - if( state->solvertype==3 ) - { - - /* - * Large-scale solver with special requirements to grid size. - */ - kx = ae_maxint(kx, nzwidth, _state); - ky = ae_maxint(ky, nzwidth, _state); - k = 1; - while(imin2(kx, ky, _state)>state->maxcoresize+1) - { - kx = idivup(kx-1, 2, _state)+1; - ky = idivup(ky-1, 2, _state)+1; - k = k+1; - } - basecasex = kx-1; - k0 = 1; - while(kx>state->maxcoresize+1) - { - basecasex = idivup(kx-1, 2, _state); - kx = basecasex+1; - k0 = k0+1; - } - while(k0>1) - { - kx = (kx-1)*2+1; - k0 = k0-1; - } - basecasey = ky-1; - k1 = 1; - while(ky>state->maxcoresize+1) - { - basecasey = idivup(ky-1, 2, _state); - ky = basecasey+1; - k1 = k1+1; - } - while(k1>1) - { - ky = (ky-1)*2+1; - k1 = k1-1; - } - while(k>1) - { - kx = (kx-1)*2+1; - ky = (ky-1)*2+1; - k = k-1; - } - - /* - * Grid is NOT expanded. We have very strict requirements on - * grid size, and we do not want to overcomplicate it by - * playing with grid size in order to add one more degree of - * freedom. It is not relevant for such large tasks. - */ - gridexpansion = 0; - } - else - { - - /* - * Medium-scale solvers which are tolerant to grid size. - */ - kx = ae_maxint(kx, nzwidth, _state); - ky = ae_maxint(ky, nzwidth, _state); - - /* - * Grid is expanded by 1 in order to add one more effective degree - * of freedom to the spline. Having additional nodes outside of the - * area allows us to emulate changes in the derivative at the bound - * without having specialized "boundary" version of the basis function. - */ - if( state->adddegreeoffreedom ) - { - gridexpansion = 1; - } - else - { - gridexpansion = 0; - } - } - hx = coalesce(xb-xa, 1.0, _state)/(kx-1); - hy = coalesce(yb-ya, 1.0, _state)/(ky-1); - invhx = 1/hx; - invhy = 1/hy; - - /* - * We determined "raw" grid size. Now perform a grid correction according - * to current grid expansion size. - */ - xaraw = xa; - yaraw = ya; - xbraw = xb; - ybraw = yb; - xa = xa-hx*gridexpansion; - ya = ya-hy*gridexpansion; - xb = xb+hx*gridexpansion; - yb = yb+hy*gridexpansion; - kx = kx+2*gridexpansion; - ky = ky+2*gridexpansion; - - /* - * Create output spline using transformed (unit-scale) - * coordinates, fill by zero values - */ - s->d = d; - s->n = kx; - s->m = ky; - s->stype = -3; - sfx = s->n*s->m*d; - sfy = 2*s->n*s->m*d; - sfxy = 3*s->n*s->m*d; - ae_vector_set_length(&s->x, s->n, _state); - ae_vector_set_length(&s->y, s->m, _state); - ae_vector_set_length(&s->f, 4*s->n*s->m*d, _state); - for(i=0; i<=s->n-1; i++) - { - s->x.ptr.p_double[i] = (double)(i); - } - for(i=0; i<=s->m-1; i++) - { - s->y.ptr.p_double[i] = (double)(i); - } - for(i=0; i<=4*s->n*s->m*d-1; i++) - { - s->f.ptr.p_double[i] = 0.0; - } - - /* - * Create local copy of dataset (only points in the grid are copied; - * we allow small step out of the grid, by Eps*H, in order to deal - * with numerical rounding errors). - * - * An additional copy of Y-values is created at columns beyond 2+J; - * it is preserved during all transformations. This copy is used - * to calculate error-related metrics. - * - * Calculate mean(Y), TSS - */ - ae_vector_set_length(&meany, d, _state); - for(j=0; j<=d-1; j++) - { - meany.ptr.p_double[j] = (double)(0); - } - rvectorsetlengthatleast(&xywork, npoints*ew, _state); - acopied = 0; - eps = 1.0E-6; - for(i=0; i<=npoints-1; i++) - { - vx = state->xy.ptr.p_double[i*ew+0]; - vy = state->xy.ptr.p_double[i*ew+1]; - if( ((ae_fp_less_eq(xaraw-eps*hx,vx)&&ae_fp_less_eq(vx,xbraw+eps*hx))&&ae_fp_less_eq(yaraw-eps*hy,vy))&&ae_fp_less_eq(vy,ybraw+eps*hy) ) - { - xywork.ptr.p_double[acopied*ew+0] = (vx-xa)*invhx; - xywork.ptr.p_double[acopied*ew+1] = (vy-ya)*invhy; - for(j=0; j<=d-1; j++) - { - v = state->xy.ptr.p_double[i*ew+2+j]; - xywork.ptr.p_double[acopied*ew+2+j] = v; - meany.ptr.p_double[j] = meany.ptr.p_double[j]+v; - } - acopied = acopied+1; - } - } - npoints = acopied; - for(j=0; j<=d-1; j++) - { - meany.ptr.p_double[j] = meany.ptr.p_double[j]/coalesce((double)(npoints), (double)(1), _state); - } - tss = 0.0; - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=d-1; j++) - { - tss = tss+ae_sqr(xywork.ptr.p_double[i*ew+2+j]-meany.ptr.p_double[j], _state); - } - } - tss = coalesce(tss, 1.0, _state); - - /* - * Handle prior term. - * Modify output spline. - * Quick exit if dataset is empty. - */ - buildpriorterm1(&xywork, npoints, 2, d, state->priorterm, state->priortermval, &vterm, _state); - if( npoints==0 ) - { - - /* - * Quick exit - */ - for(k=0; k<=s->n*s->m-1; k++) - { - k0 = k%s->n; - k1 = k/s->n; - for(j=0; j<=d-1; j++) - { - dstidx = d*(k1*s->n+k0)+j; - s->f.ptr.p_double[dstidx] = s->f.ptr.p_double[dstidx]+vterm.ptr.pp_double[j][0]*s->x.ptr.p_double[k0]+vterm.ptr.pp_double[j][1]*s->y.ptr.p_double[k1]+vterm.ptr.pp_double[j][2]; - s->f.ptr.p_double[sfx+dstidx] = s->f.ptr.p_double[sfx+dstidx]+vterm.ptr.pp_double[j][0]; - s->f.ptr.p_double[sfy+dstidx] = s->f.ptr.p_double[sfy+dstidx]+vterm.ptr.pp_double[j][1]; - } - } - for(i=0; i<=s->n-1; i++) - { - s->x.ptr.p_double[i] = s->x.ptr.p_double[i]*hx+xa; - } - for(i=0; i<=s->m-1; i++) - { - s->y.ptr.p_double[i] = s->y.ptr.p_double[i]*hy+ya; - } - for(i=0; i<=s->n*s->m*d-1; i++) - { - s->f.ptr.p_double[sfx+i] = s->f.ptr.p_double[sfx+i]*invhx; - s->f.ptr.p_double[sfy+i] = s->f.ptr.p_double[sfy+i]*invhy; - s->f.ptr.p_double[sfxy+i] = s->f.ptr.p_double[sfxy+i]*invhx*invhy; - } - rep->rmserror = (double)(0); - rep->avgerror = (double)(0); - rep->maxerror = (double)(0); - rep->r2 = 1.0; - ae_frame_leave(_state); - return; - } - - /* - * Build 1D compact basis function - * Generate design matrix - */ - ae_vector_set_length(&tmpx, 7, _state); - ae_vector_set_length(&tmpy, 7, _state); - tmpx.ptr.p_double[0] = (double)(-3); - tmpx.ptr.p_double[1] = (double)(-2); - tmpx.ptr.p_double[2] = (double)(-1); - tmpx.ptr.p_double[3] = (double)(0); - tmpx.ptr.p_double[4] = (double)(1); - tmpx.ptr.p_double[5] = (double)(2); - tmpx.ptr.p_double[6] = (double)(3); - tmpy.ptr.p_double[0] = (double)(0); - tmpy.ptr.p_double[1] = (double)(0); - tmpy.ptr.p_double[2] = (double)1/(double)12; - tmpy.ptr.p_double[3] = (double)2/(double)6; - tmpy.ptr.p_double[4] = (double)1/(double)12; - tmpy.ptr.p_double[5] = (double)(0); - tmpy.ptr.p_double[6] = (double)(0); - spline1dbuildcubic(&tmpx, &tmpy, tmpx.cnt, 2, 0.0, 2, 0.0, &basis1, _state); - - /* - * Solve. - * Update spline. - */ - if( state->solvertype==1 ) - { - - /* - * BlockLLS - */ - spline2d_reorderdatasetandbuildindex(&xywork, npoints, d, &tmp0, 0, kx, ky, &xyindex, &tmpi, _state); - spline2d_xdesigngenerate(&xywork, &xyindex, 0, kx, kx, 0, ky, ky, d, spline2d_lambdaregblocklls, state->smoothing, &basis1, &xdesignmatrix, _state); - spline2d_blockllsfit(&xdesignmatrix, state->lsqrcnt, &z, rep, tss, &blockllsbuf, _state); - spline2d_updatesplinetable(&z, kx, ky, d, &basis1, bfrad, &s->f, s->m, s->n, 1, _state); - } - else - { - if( state->solvertype==2 ) - { - - /* - * NaiveLLS, reference implementation - */ - spline2d_generatedesignmatrix(&xywork, npoints, d, kx, ky, state->smoothing, spline2d_lambdaregblocklls, &basis1, &av, &ah, &arows, _state); - spline2d_naivellsfit(&av, &ah, arows, &xywork, kx, ky, npoints, d, state->lsqrcnt, &z, rep, tss, _state); - spline2d_updatesplinetable(&z, kx, ky, d, &basis1, bfrad, &s->f, s->m, s->n, 1, _state); - } - else - { - if( state->solvertype==3 ) - { - - /* - * FastDDM method - */ - ae_assert(basecasex>0, "Spline2DFit: integrity error", _state); - ae_assert(basecasey>0, "Spline2DFit: integrity error", _state); - spline2d_fastddmfit(&xywork, npoints, d, kx, ky, basecasex, basecasey, state->maxcoresize, state->interfacesize, state->nlayers, state->smoothing, state->lsqrcnt, &basis1, s, rep, tss, _state); - } - else - { - ae_assert(ae_false, "Spline2DFit: integrity error", _state); - } - } - } - - /* - * Append prior term. - * Transform spline to original coordinates - */ - for(k=0; k<=s->n*s->m-1; k++) - { - k0 = k%s->n; - k1 = k/s->n; - for(j=0; j<=d-1; j++) - { - dstidx = d*(k1*s->n+k0)+j; - s->f.ptr.p_double[dstidx] = s->f.ptr.p_double[dstidx]+vterm.ptr.pp_double[j][0]*s->x.ptr.p_double[k0]+vterm.ptr.pp_double[j][1]*s->y.ptr.p_double[k1]+vterm.ptr.pp_double[j][2]; - s->f.ptr.p_double[sfx+dstidx] = s->f.ptr.p_double[sfx+dstidx]+vterm.ptr.pp_double[j][0]; - s->f.ptr.p_double[sfy+dstidx] = s->f.ptr.p_double[sfy+dstidx]+vterm.ptr.pp_double[j][1]; - } - } - for(i=0; i<=s->n-1; i++) - { - s->x.ptr.p_double[i] = s->x.ptr.p_double[i]*hx+xa; - } - for(i=0; i<=s->m-1; i++) - { - s->y.ptr.p_double[i] = s->y.ptr.p_double[i]*hy+ya; - } - for(i=0; i<=s->n*s->m*d-1; i++) - { - s->f.ptr.p_double[sfx+i] = s->f.ptr.p_double[sfx+i]*invhx; - s->f.ptr.p_double[sfy+i] = s->f.ptr.p_double[sfy+i]*invhy; - s->f.ptr.p_double[sfxy+i] = s->f.ptr.p_double[sfxy+i]*invhx*invhy; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Serializer: allocation - - -- ALGLIB -- - Copyright 28.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dalloc(ae_serializer* s, - spline2dinterpolant* spline, - ae_state *_state) -{ - - - - /* - * Header - */ - ae_serializer_alloc_entry(s); - - /* - * Data - */ - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - allocrealarray(s, &spline->x, -1, _state); - allocrealarray(s, &spline->y, -1, _state); - allocrealarray(s, &spline->f, -1, _state); -} - - -/************************************************************************* -Serializer: serialization - - -- ALGLIB -- - Copyright 28.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dserialize(ae_serializer* s, - spline2dinterpolant* spline, - ae_state *_state) -{ - - - - /* - * Header - */ - ae_serializer_serialize_int(s, getspline2dserializationcode(_state), _state); - - /* - * Data - */ - ae_serializer_serialize_int(s, spline->stype, _state); - ae_serializer_serialize_int(s, spline->n, _state); - ae_serializer_serialize_int(s, spline->m, _state); - ae_serializer_serialize_int(s, spline->d, _state); - serializerealarray(s, &spline->x, -1, _state); - serializerealarray(s, &spline->y, -1, _state); - serializerealarray(s, &spline->f, -1, _state); -} - - -/************************************************************************* -Serializer: unserialization - - -- ALGLIB -- - Copyright 28.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dunserialize(ae_serializer* s, - spline2dinterpolant* spline, - ae_state *_state) -{ - ae_int_t scode; - - _spline2dinterpolant_clear(spline); - - - /* - * Header - */ - ae_serializer_unserialize_int(s, &scode, _state); - ae_assert(scode==getspline2dserializationcode(_state), "Spline2DUnserialize: stream header corrupted", _state); - - /* - * Data - */ - ae_serializer_unserialize_int(s, &spline->stype, _state); - ae_serializer_unserialize_int(s, &spline->n, _state); - ae_serializer_unserialize_int(s, &spline->m, _state); - ae_serializer_unserialize_int(s, &spline->d, _state); - unserializerealarray(s, &spline->x, _state); - unserializerealarray(s, &spline->y, _state); - unserializerealarray(s, &spline->f, _state); -} - - -/************************************************************************* -Internal subroutine. -Calculation of the first derivatives and the cross-derivative. -*************************************************************************/ -static void spline2d_bicubiccalcderivatives(/* Real */ ae_matrix* a, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* dx, - /* Real */ ae_matrix* dy, - /* Real */ ae_matrix* dxy, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_vector xt; - ae_vector ft; - double s; - double ds; - double d2s; - spline1dinterpolant c; - - ae_frame_make(_state, &_frame_block); - memset(&xt, 0, sizeof(xt)); - memset(&ft, 0, sizeof(ft)); - memset(&c, 0, sizeof(c)); - ae_matrix_clear(dx); - ae_matrix_clear(dy); - ae_matrix_clear(dxy); - ae_vector_init(&xt, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ft, 0, DT_REAL, _state, ae_true); - _spline1dinterpolant_init(&c, _state, ae_true); - - ae_matrix_set_length(dx, m, n, _state); - ae_matrix_set_length(dy, m, n, _state); - ae_matrix_set_length(dxy, m, n, _state); - - /* - * dF/dX - */ - ae_vector_set_length(&xt, n, _state); - ae_vector_set_length(&ft, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - xt.ptr.p_double[j] = x->ptr.p_double[j]; - ft.ptr.p_double[j] = a->ptr.pp_double[i][j]; - } - spline1dbuildcubic(&xt, &ft, n, 0, 0.0, 0, 0.0, &c, _state); - for(j=0; j<=n-1; j++) - { - spline1ddiff(&c, x->ptr.p_double[j], &s, &ds, &d2s, _state); - dx->ptr.pp_double[i][j] = ds; - } - } - - /* - * dF/dY - */ - ae_vector_set_length(&xt, m, _state); - ae_vector_set_length(&ft, m, _state); - for(j=0; j<=n-1; j++) - { - for(i=0; i<=m-1; i++) - { - xt.ptr.p_double[i] = y->ptr.p_double[i]; - ft.ptr.p_double[i] = a->ptr.pp_double[i][j]; - } - spline1dbuildcubic(&xt, &ft, m, 0, 0.0, 0, 0.0, &c, _state); - for(i=0; i<=m-1; i++) - { - spline1ddiff(&c, y->ptr.p_double[i], &s, &ds, &d2s, _state); - dy->ptr.pp_double[i][j] = ds; - } - } - - /* - * d2F/dXdY - */ - ae_vector_set_length(&xt, n, _state); - ae_vector_set_length(&ft, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - xt.ptr.p_double[j] = x->ptr.p_double[j]; - ft.ptr.p_double[j] = dy->ptr.pp_double[i][j]; - } - spline1dbuildcubic(&xt, &ft, n, 0, 0.0, 0, 0.0, &c, _state); - for(j=0; j<=n-1; j++) - { - spline1ddiff(&c, x->ptr.p_double[j], &s, &ds, &d2s, _state); - dxy->ptr.pp_double[i][j] = ds; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function generates design matrix for the problem (in fact, two design -matrices are generated: "vertical" one and transposed (horizontal) one. - -INPUT PARAMETERS: - XY - array[NPoints*(2+D)]; dataset after scaling in such - way that grid step is equal to 1.0 in both dimensions. - NPoints - dataset size, NPoints>=1 - KX, KY - grid size, KX,KY>=4 - Smoothing - nonlinearity penalty coefficient, >=0 - LambdaReg - regularization coefficient, >=0 - Basis1 - basis spline, expected to be non-zero only at [-2,+2] - AV, AH - possibly preallocated buffers - -OUTPUT PARAMETERS: - AV - sparse matrix[ARows,KX*KY]; design matrix - AH - transpose of AV - ARows - number of rows in design matrix - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static void spline2d_generatedesignmatrix(/* Real */ ae_vector* xy, - ae_int_t npoints, - ae_int_t d, - ae_int_t kx, - ae_int_t ky, - double smoothing, - double lambdareg, - spline1dinterpolant* basis1, - sparsematrix* av, - sparsematrix* ah, - ae_int_t* arows, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nzwidth; - ae_int_t nzshift; - ae_int_t ew; - ae_int_t i; - ae_int_t j0; - ae_int_t j1; - ae_int_t k0; - ae_int_t k1; - ae_int_t dstidx; - double v; - double v0; - double v1; - double v2; - double w0; - double w1; - double w2; - ae_vector crx; - ae_vector cry; - ae_vector nrs; - ae_matrix d2x; - ae_matrix d2y; - ae_matrix dxy; - - ae_frame_make(_state, &_frame_block); - memset(&crx, 0, sizeof(crx)); - memset(&cry, 0, sizeof(cry)); - memset(&nrs, 0, sizeof(nrs)); - memset(&d2x, 0, sizeof(d2x)); - memset(&d2y, 0, sizeof(d2y)); - memset(&dxy, 0, sizeof(dxy)); - *arows = 0; - ae_vector_init(&crx, 0, DT_INT, _state, ae_true); - ae_vector_init(&cry, 0, DT_INT, _state, ae_true); - ae_vector_init(&nrs, 0, DT_INT, _state, ae_true); - ae_matrix_init(&d2x, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&d2y, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&dxy, 0, 0, DT_REAL, _state, ae_true); - - nzwidth = 4; - nzshift = 1; - ae_assert(npoints>0, "Spline2DFit: integrity check failed", _state); - ae_assert(kx>=nzwidth, "Spline2DFit: integrity check failed", _state); - ae_assert(ky>=nzwidth, "Spline2DFit: integrity check failed", _state); - ew = 2+d; - - /* - * Determine canonical rectangle for every point. Every point of the dataset is - * influenced by at most NZWidth*NZWidth basis functions, which form NZWidth*NZWidth - * canonical rectangle. - * - * Thus, we have (KX-NZWidth+1)*(KY-NZWidth+1) overlapping canonical rectangles. - * Assigning every point to its rectangle simplifies creation of sparse basis - * matrix at the next steps. - */ - ae_vector_set_length(&crx, npoints, _state); - ae_vector_set_length(&cry, npoints, _state); - for(i=0; i<=npoints-1; i++) - { - crx.ptr.p_int[i] = iboundval(ae_ifloor(xy->ptr.p_double[i*ew+0], _state)-nzshift, 0, kx-nzwidth, _state); - cry.ptr.p_int[i] = iboundval(ae_ifloor(xy->ptr.p_double[i*ew+1], _state)-nzshift, 0, ky-nzwidth, _state); - } - - /* - * Create vertical and horizontal design matrices - */ - *arows = npoints+kx*ky; - if( ae_fp_neq(smoothing,0.0) ) - { - ae_assert(ae_fp_greater(smoothing,0.0), "Spline2DFit: integrity check failed", _state); - *arows = *arows+3*(kx-2)*(ky-2); - } - ae_vector_set_length(&nrs, *arows, _state); - dstidx = 0; - for(i=0; i<=npoints-1; i++) - { - nrs.ptr.p_int[dstidx+i] = nzwidth*nzwidth; - } - dstidx = dstidx+npoints; - for(i=0; i<=kx*ky-1; i++) - { - nrs.ptr.p_int[dstidx+i] = 1; - } - dstidx = dstidx+kx*ky; - if( ae_fp_neq(smoothing,0.0) ) - { - for(i=0; i<=3*(kx-2)*(ky-2)-1; i++) - { - nrs.ptr.p_int[dstidx+i] = 3*3; - } - dstidx = dstidx+3*(kx-2)*(ky-2); - } - ae_assert(dstidx==(*arows), "Spline2DFit: integrity check failed", _state); - sparsecreatecrs(*arows, kx*ky, &nrs, av, _state); - dstidx = 0; - for(i=0; i<=npoints-1; i++) - { - for(j1=0; j1<=nzwidth-1; j1++) - { - for(j0=0; j0<=nzwidth-1; j0++) - { - v0 = spline1dcalc(basis1, xy->ptr.p_double[i*ew+0]-(crx.ptr.p_int[i]+j0), _state); - v1 = spline1dcalc(basis1, xy->ptr.p_double[i*ew+1]-(cry.ptr.p_int[i]+j1), _state); - sparseset(av, dstidx+i, (cry.ptr.p_int[i]+j1)*kx+(crx.ptr.p_int[i]+j0), v0*v1, _state); - } - } - } - dstidx = dstidx+npoints; - for(i=0; i<=kx*ky-1; i++) - { - sparseset(av, dstidx+i, i, lambdareg, _state); - } - dstidx = dstidx+kx*ky; - if( ae_fp_neq(smoothing,0.0) ) - { - - /* - * Smoothing is applied. Because all grid nodes are same, - * we apply same smoothing kernel, which is calculated only - * once at the beginning of design matrix generation. - */ - ae_matrix_set_length(&d2x, 3, 3, _state); - ae_matrix_set_length(&d2y, 3, 3, _state); - ae_matrix_set_length(&dxy, 3, 3, _state); - for(j1=0; j1<=2; j1++) - { - for(j0=0; j0<=2; j0++) - { - d2x.ptr.pp_double[j0][j1] = 0.0; - d2y.ptr.pp_double[j0][j1] = 0.0; - dxy.ptr.pp_double[j0][j1] = 0.0; - } - } - for(k1=0; k1<=2; k1++) - { - for(k0=0; k0<=2; k0++) - { - spline1ddiff(basis1, (double)(-(k0-1)), &v0, &v1, &v2, _state); - spline1ddiff(basis1, (double)(-(k1-1)), &w0, &w1, &w2, _state); - d2x.ptr.pp_double[k0][k1] = d2x.ptr.pp_double[k0][k1]+v2*w0; - d2y.ptr.pp_double[k0][k1] = d2y.ptr.pp_double[k0][k1]+w2*v0; - dxy.ptr.pp_double[k0][k1] = dxy.ptr.pp_double[k0][k1]+v1*w1; - } - } - - /* - * Now, kernel is ready - apply it to all inner nodes of the grid. - */ - for(j1=1; j1<=ky-2; j1++) - { - for(j0=1; j0<=kx-2; j0++) - { - - /* - * d2F/dx2 term - */ - v = smoothing; - for(k1=-1; k1<=1; k1++) - { - for(k0=-1; k0<=1; k0++) - { - sparseset(av, dstidx, (j1+k1)*kx+(j0+k0), v*d2x.ptr.pp_double[1+k0][1+k1], _state); - } - } - dstidx = dstidx+1; - - /* - * d2F/dy2 term - */ - v = smoothing; - for(k1=-1; k1<=1; k1++) - { - for(k0=-1; k0<=1; k0++) - { - sparseset(av, dstidx, (j1+k1)*kx+(j0+k0), v*d2y.ptr.pp_double[1+k0][1+k1], _state); - } - } - dstidx = dstidx+1; - - /* - * 2*d2F/dxdy term - */ - v = ae_sqrt((double)(2), _state)*smoothing; - for(k1=-1; k1<=1; k1++) - { - for(k0=-1; k0<=1; k0++) - { - sparseset(av, dstidx, (j1+k1)*kx+(j0+k0), v*dxy.ptr.pp_double[1+k0][1+k1], _state); - } - } - dstidx = dstidx+1; - } - } - } - ae_assert(dstidx==(*arows), "Spline2DFit: integrity check failed", _state); - sparsecopy(av, ah, _state); - sparsetransposecrs(ah, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function updates table of spline values/derivatives using coefficients -for a layer of basis functions. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static void spline2d_updatesplinetable(/* Real */ ae_vector* z, - ae_int_t kx, - ae_int_t ky, - ae_int_t d, - spline1dinterpolant* basis1, - ae_int_t bfrad, - /* Real */ ae_vector* ftbl, - ae_int_t m, - ae_int_t n, - ae_int_t scalexy, - ae_state *_state) -{ - ae_int_t k; - ae_int_t k0; - ae_int_t k1; - ae_int_t j; - ae_int_t j0; - ae_int_t j1; - ae_int_t j0a; - ae_int_t j0b; - ae_int_t j1a; - ae_int_t j1b; - double v; - double v0; - double v1; - double v01; - double v11; - double rdummy; - ae_int_t dstidx; - ae_int_t sfx; - ae_int_t sfy; - ae_int_t sfxy; - double invscalexy; - - - ae_assert(n==(kx-1)*scalexy+1, "Spline2DFit.UpdateSplineTable: integrity check failed", _state); - ae_assert(m==(ky-1)*scalexy+1, "Spline2DFit.UpdateSplineTable: integrity check failed", _state); - invscalexy = (double)1/(double)scalexy; - sfx = n*m*d; - sfy = 2*n*m*d; - sfxy = 3*n*m*d; - for(k=0; k<=kx*ky-1; k++) - { - k0 = k%kx; - k1 = k/kx; - j0a = iboundval(k0*scalexy-(bfrad*scalexy-1), 0, n-1, _state); - j0b = iboundval(k0*scalexy+(bfrad*scalexy-1), 0, n-1, _state); - j1a = iboundval(k1*scalexy-(bfrad*scalexy-1), 0, m-1, _state); - j1b = iboundval(k1*scalexy+(bfrad*scalexy-1), 0, m-1, _state); - for(j1=j1a; j1<=j1b; j1++) - { - spline1ddiff(basis1, (j1-k1*scalexy)*invscalexy, &v1, &v11, &rdummy, _state); - v11 = v11*invscalexy; - for(j0=j0a; j0<=j0b; j0++) - { - spline1ddiff(basis1, (j0-k0*scalexy)*invscalexy, &v0, &v01, &rdummy, _state); - v01 = v01*invscalexy; - for(j=0; j<=d-1; j++) - { - dstidx = d*(j1*n+j0)+j; - v = z->ptr.p_double[j*kx*ky+k]; - ftbl->ptr.p_double[dstidx] = ftbl->ptr.p_double[dstidx]+v0*v1*v; - ftbl->ptr.p_double[sfx+dstidx] = ftbl->ptr.p_double[sfx+dstidx]+v01*v1*v; - ftbl->ptr.p_double[sfy+dstidx] = ftbl->ptr.p_double[sfy+dstidx]+v0*v11*v; - ftbl->ptr.p_double[sfxy+dstidx] = ftbl->ptr.p_double[sfxy+dstidx]+v01*v11*v; - } - } - } - } -} - - -/************************************************************************* -This function performs fitting with FastDDM solver. -Internal function, never use it directly. - -INPUT PARAMETERS: - XY - array[NPoints*(2+D)], dataset; destroyed in process - KX, KY - grid size - TileSize - tile size - InterfaceSize- interface size - NPoints - points count - D - number of components in vector-valued spline, D>=1 - LSQRCnt - number of iterations, non-zero: - * LSQRCnt>0 means that specified amount of preconditioned - LSQR iterations will be performed to solve problem; - usually we need 2..5 its. Recommended option - best - convergence and stability/quality. - * LSQRCnt<0 means that instead of LSQR we use iterative - refinement on normal equations. Again, 2..5 its is enough. - Basis1 - basis spline, expected to be non-zero only at [-2,+2] - Z - possibly preallocated buffer for solution - Residuals - possibly preallocated buffer for residuals at dataset points - Rep - report structure; fields which are not set by this function - are left intact - TSS - total sum of squares; used to calculate R2 - - -OUTPUT PARAMETERS: - XY - destroyed in process - Z - array[KX*KY*D], filled by solution; KX*KY coefficients - corresponding to each of D dimensions are stored contiguously. - Rep - following fields are set: - * Rep.RMSError - * Rep.AvgError - * Rep.MaxError - * Rep.R2 - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static void spline2d_fastddmfit(/* Real */ ae_vector* xy, - ae_int_t npoints, - ae_int_t d, - ae_int_t kx, - ae_int_t ky, - ae_int_t basecasex, - ae_int_t basecasey, - ae_int_t maxcoresize, - ae_int_t interfacesize, - ae_int_t nlayers, - double smoothing, - ae_int_t lsqrcnt, - spline1dinterpolant* basis1, - spline2dinterpolant* spline, - spline2dfitreport* rep, - double tss, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t nzwidth; - ae_int_t xew; - ae_int_t ntotallayers; - ae_int_t scaleidx; - ae_int_t scalexy; - double invscalexy; - ae_int_t kxcur; - ae_int_t kycur; - ae_int_t tilescount0; - ae_int_t tilescount1; - double v; - double rss; - ae_vector yraw; - ae_vector xyindex; - ae_vector tmp0; - ae_vector bufi; - spline2dfastddmbuf seed; - ae_shared_pool pool; - spline2dxdesignmatrix xdesignmatrix; - spline2dblockllsbuf blockllsbuf; - spline2dfitreport dummyrep; - - ae_frame_make(_state, &_frame_block); - memset(&yraw, 0, sizeof(yraw)); - memset(&xyindex, 0, sizeof(xyindex)); - memset(&tmp0, 0, sizeof(tmp0)); - memset(&bufi, 0, sizeof(bufi)); - memset(&seed, 0, sizeof(seed)); - memset(&pool, 0, sizeof(pool)); - memset(&xdesignmatrix, 0, sizeof(xdesignmatrix)); - memset(&blockllsbuf, 0, sizeof(blockllsbuf)); - memset(&dummyrep, 0, sizeof(dummyrep)); - ae_vector_init(&yraw, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xyindex, 0, DT_INT, _state, ae_true); - ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bufi, 0, DT_INT, _state, ae_true); - _spline2dfastddmbuf_init(&seed, _state, ae_true); - ae_shared_pool_init(&pool, _state, ae_true); - _spline2dxdesignmatrix_init(&xdesignmatrix, _state, ae_true); - _spline2dblockllsbuf_init(&blockllsbuf, _state, ae_true); - _spline2dfitreport_init(&dummyrep, _state, ae_true); - - - /* - * Dataset metrics and integrity checks - */ - nzwidth = 4; - xew = 2+d; - ae_assert(maxcoresize>=2, "Spline2DFit: integrity check failed", _state); - ae_assert(interfacesize>=1, "Spline2DFit: integrity check failed", _state); - ae_assert(kx>=nzwidth, "Spline2DFit: integrity check failed", _state); - ae_assert(ky>=nzwidth, "Spline2DFit: integrity check failed", _state); - - /* - * Verify consistency of the grid size (KX,KY) with basecase sizes. - * Determine full number of layers. - */ - ae_assert(basecasex<=maxcoresize, "Spline2DFit: integrity error", _state); - ae_assert(basecasey<=maxcoresize, "Spline2DFit: integrity error", _state); - ntotallayers = 1; - scalexy = 1; - kxcur = kx; - kycur = ky; - while(kxcur>basecasex+1&&kycur>basecasey+1) - { - ae_assert(kxcur%2==1, "Spline2DFit: integrity error", _state); - ae_assert(kycur%2==1, "Spline2DFit: integrity error", _state); - kxcur = (kxcur-1)/2+1; - kycur = (kycur-1)/2+1; - scalexy = scalexy*2; - inc(&ntotallayers, _state); - } - invscalexy = (double)1/(double)scalexy; - ae_assert((kxcur<=maxcoresize+1&&kxcur==basecasex+1)||kxcur%basecasex==1, "Spline2DFit: integrity error", _state); - ae_assert((kycur<=maxcoresize+1&&kycur==basecasey+1)||kycur%basecasey==1, "Spline2DFit: integrity error", _state); - ae_assert(kxcur==basecasex+1||kycur==basecasey+1, "Spline2DFit: integrity error", _state); - - /* - * Initial scaling of dataset. - * Store original target values to YRaw. - */ - rvectorsetlengthatleast(&yraw, npoints*d, _state); - for(i=0; i<=npoints-1; i++) - { - xy->ptr.p_double[xew*i+0] = xy->ptr.p_double[xew*i+0]*invscalexy; - xy->ptr.p_double[xew*i+1] = xy->ptr.p_double[xew*i+1]*invscalexy; - for(j=0; j<=d-1; j++) - { - yraw.ptr.p_double[i*d+j] = xy->ptr.p_double[xew*i+2+j]; - } - } - kxcur = (kx-1)/scalexy+1; - kycur = (ky-1)/scalexy+1; - - /* - * Build initial dataset index; area is divided into (KXCur-1)*(KYCur-1) - * cells, with contiguous storage of points in the same cell. - * Iterate over different scales - */ - ae_shared_pool_set_seed(&pool, &seed, sizeof(seed), _spline2dfastddmbuf_init, _spline2dfastddmbuf_init_copy, _spline2dfastddmbuf_destroy, _state); - spline2d_reorderdatasetandbuildindex(xy, npoints, d, &yraw, d, kxcur, kycur, &xyindex, &bufi, _state); - for(scaleidx=ntotallayers-1; scaleidx>=0; scaleidx--) - { - if( (nlayers>0&&scaleidxrmserror = (double)(0); - rep->avgerror = (double)(0); - rep->maxerror = (double)(0); - rss = 0.0; - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=d-1; j++) - { - v = xy->ptr.p_double[i*xew+2+j]; - rss = rss+v*v; - rep->rmserror = rep->rmserror+ae_sqr(v, _state); - rep->avgerror = rep->avgerror+ae_fabs(v, _state); - rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(v, _state), _state); - } - } - rep->rmserror = ae_sqrt(rep->rmserror/coalesce((double)(npoints*d), 1.0, _state), _state); - rep->avgerror = rep->avgerror/coalesce((double)(npoints*d), 1.0, _state); - rep->r2 = 1.0-rss/coalesce(tss, 1.0, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Recursive fitting function for FastDDM algorithm. - -Works with KX*KY grid, with KX=BasecaseX*TilesCountX+1 and KY=BasecaseY*TilesCountY+1, -which is partitioned into TilesCountX*TilesCountY tiles, each having size -BasecaseX*BasecaseY. - -This function processes tiles in range [TileX0,TileX1)x[TileY0,TileY1) and -recursively divides this range until we move down to single tile, which -is processed with BlockLLS solver. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static void spline2d_fastddmfitlayer(/* Real */ ae_vector* xy, - ae_int_t d, - ae_int_t scalexy, - /* Integer */ ae_vector* xyindex, - ae_int_t basecasex, - ae_int_t tilex0, - ae_int_t tilex1, - ae_int_t tilescountx, - ae_int_t basecasey, - ae_int_t tiley0, - ae_int_t tiley1, - ae_int_t tilescounty, - ae_int_t maxcoresize, - ae_int_t interfacesize, - ae_int_t lsqrcnt, - double lambdareg, - spline1dinterpolant* basis1, - ae_shared_pool* pool, - spline2dinterpolant* spline, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t kx; - ae_int_t ky; - ae_int_t i; - ae_int_t j; - ae_int_t j0; - ae_int_t j1; - ae_int_t bfrad; - ae_int_t xa; - ae_int_t xb; - ae_int_t ya; - ae_int_t yb; - ae_int_t tile0; - ae_int_t tile1; - ae_int_t tilesize0; - ae_int_t tilesize1; - ae_int_t sfx; - ae_int_t sfy; - ae_int_t sfxy; - double dummytss; - double invscalexy; - ae_int_t cnt0; - ae_int_t cnt1; - ae_int_t offs; - double vs; - double vsx; - double vsy; - double vsxy; - spline2dfastddmbuf *buf; - ae_smart_ptr _buf; - - ae_frame_make(_state, &_frame_block); - memset(&_buf, 0, sizeof(_buf)); - ae_smart_ptr_init(&_buf, (void**)&buf, _state, ae_true); - - - /* - * Dataset metrics and fast integrity checks; - * no code with side effects is allowed before parallel split. - */ - bfrad = 2; - invscalexy = (double)1/(double)scalexy; - kx = basecasex*tilescountx+1; - ky = basecasey*tilescounty+1; - - /* - * Parallelism; because this function is intended for - * large-scale problems, we always try to: - * * invoke parallel execution mode - * * activate spawn support - */ - if( _trypexec_spline2d_fastddmfitlayer(xy,d,scalexy,xyindex,basecasex,tilex0,tilex1,tilescountx,basecasey,tiley0,tiley1,tilescounty,maxcoresize,interfacesize,lsqrcnt,lambdareg,basis1,pool,spline, _state) ) - { - ae_frame_leave(_state); - return; - } - if( imax2(tiley1-tiley0, tilex1-tilex0, _state)>=2 ) - { - if( tiley1-tiley0>tilex1-tilex0 ) - { - - /* - * Split problem in Y dimension - * - * NOTE: recursive calls to FastDDMFitLayer() compute - * residuals in the inner cells defined by XYIndex[], - * but we still have to compute residuals for cells - * BETWEEN two recursive subdivisions of the task. - */ - tiledsplit(tiley1-tiley0, 1, &j0, &j1, _state); - spline2d_fastddmfitlayer(xy, d, scalexy, xyindex, basecasex, tilex0, tilex1, tilescountx, basecasey, tiley0, tiley0+j0, tilescounty, maxcoresize, interfacesize, lsqrcnt, lambdareg, basis1, pool, spline, _state); - spline2d_fastddmfitlayer(xy, d, scalexy, xyindex, basecasex, tilex0, tilex1, tilescountx, basecasey, tiley0+j0, tiley1, tilescounty, maxcoresize, interfacesize, lsqrcnt, lambdareg, basis1, pool, spline, _state); - } - else - { - - /* - * Split problem in X dimension - * - * NOTE: recursive calls to FastDDMFitLayer() compute - * residuals in the inner cells defined by XYIndex[], - * but we still have to compute residuals for cells - * BETWEEN two recursive subdivisions of the task. - */ - tiledsplit(tilex1-tilex0, 1, &j0, &j1, _state); - spline2d_fastddmfitlayer(xy, d, scalexy, xyindex, basecasex, tilex0, tilex0+j0, tilescountx, basecasey, tiley0, tiley1, tilescounty, maxcoresize, interfacesize, lsqrcnt, lambdareg, basis1, pool, spline, _state); - spline2d_fastddmfitlayer(xy, d, scalexy, xyindex, basecasex, tilex0+j0, tilex1, tilescountx, basecasey, tiley0, tiley1, tilescounty, maxcoresize, interfacesize, lsqrcnt, lambdareg, basis1, pool, spline, _state); - } - ae_frame_leave(_state); - return; - } - ae_assert(tiley0==tiley1-1, "Spline2DFit.FastDDMFitLayer: integrity check failed", _state); - ae_assert(tilex0==tilex1-1, "Spline2DFit.FastDDMFitLayer: integrity check failed", _state); - tile1 = tiley0; - tile0 = tilex0; - - /* - * Retrieve temporaries - */ - ae_shared_pool_retrieve(pool, &_buf, _state); - - /* - * Analyze dataset - */ - xa = iboundval(tile0*basecasex-interfacesize, 0, kx, _state); - xb = iboundval((tile0+1)*basecasex+interfacesize, 0, kx, _state); - ya = iboundval(tile1*basecasey-interfacesize, 0, ky, _state); - yb = iboundval((tile1+1)*basecasey+interfacesize, 0, ky, _state); - tilesize0 = xb-xa; - tilesize1 = yb-ya; - - /* - * Solve current chunk with BlockLLS - */ - dummytss = 1.0; - spline2d_xdesigngenerate(xy, xyindex, xa, xb, kx, ya, yb, ky, d, lambdareg, 0.0, basis1, &buf->xdesignmatrix, _state); - spline2d_blockllsfit(&buf->xdesignmatrix, lsqrcnt, &buf->tmpz, &buf->dummyrep, dummytss, &buf->blockllsbuf, _state); - buf->localmodel.d = d; - buf->localmodel.m = tilesize1; - buf->localmodel.n = tilesize0; - buf->localmodel.stype = -3; - rvectorsetlengthatleast(&buf->localmodel.x, tilesize0, _state); - rvectorsetlengthatleast(&buf->localmodel.y, tilesize1, _state); - rvectorsetlengthatleast(&buf->localmodel.f, tilesize0*tilesize1*d*4, _state); - for(i=0; i<=tilesize0-1; i++) - { - buf->localmodel.x.ptr.p_double[i] = (double)(xa+i); - } - for(i=0; i<=tilesize1-1; i++) - { - buf->localmodel.y.ptr.p_double[i] = (double)(ya+i); - } - for(i=0; i<=tilesize0*tilesize1*d*4-1; i++) - { - buf->localmodel.f.ptr.p_double[i] = 0.0; - } - spline2d_updatesplinetable(&buf->tmpz, tilesize0, tilesize1, d, basis1, bfrad, &buf->localmodel.f, tilesize1, tilesize0, 1, _state); - - /* - * Transform local spline to original coordinates - */ - sfx = buf->localmodel.n*buf->localmodel.m*d; - sfy = 2*buf->localmodel.n*buf->localmodel.m*d; - sfxy = 3*buf->localmodel.n*buf->localmodel.m*d; - for(i=0; i<=tilesize0-1; i++) - { - buf->localmodel.x.ptr.p_double[i] = buf->localmodel.x.ptr.p_double[i]*scalexy; - } - for(i=0; i<=tilesize1-1; i++) - { - buf->localmodel.y.ptr.p_double[i] = buf->localmodel.y.ptr.p_double[i]*scalexy; - } - for(i=0; i<=tilesize0*tilesize1*d-1; i++) - { - buf->localmodel.f.ptr.p_double[sfx+i] = buf->localmodel.f.ptr.p_double[sfx+i]*invscalexy; - buf->localmodel.f.ptr.p_double[sfy+i] = buf->localmodel.f.ptr.p_double[sfy+i]*invscalexy; - buf->localmodel.f.ptr.p_double[sfxy+i] = buf->localmodel.f.ptr.p_double[sfxy+i]*(invscalexy*invscalexy); - } - - /* - * Output results; for inner and topmost/leftmost tiles we output only BasecaseX*BasecaseY - * inner elements; for rightmost/bottom ones we also output one column/row of the interface - * part. - * - * Such complexity is explained by the fact that area size (by design) is not evenly divisible - * by the tile size; it is divisible with remainder=1, and we expect that interface size is - * at least 1, so we can fill the missing rightmost/bottom elements of Z by the interface - * values. - */ - ae_assert(interfacesize>=1, "Spline2DFit: integrity check failed", _state); - sfx = spline->n*spline->m*d; - sfy = 2*spline->n*spline->m*d; - sfxy = 3*spline->n*spline->m*d; - cnt0 = basecasex*scalexy; - cnt1 = basecasey*scalexy; - if( tile0==tilescountx-1 ) - { - inc(&cnt0, _state); - } - if( tile1==tilescounty-1 ) - { - inc(&cnt1, _state); - } - offs = d*(spline->n*tile1*basecasey*scalexy+tile0*basecasex*scalexy); - for(j1=0; j1<=cnt1-1; j1++) - { - for(j0=0; j0<=cnt0-1; j0++) - { - for(j=0; j<=d-1; j++) - { - spline2ddiffvi(&buf->localmodel, (double)(tile0*basecasex*scalexy+j0), (double)(tile1*basecasey*scalexy+j1), j, &vs, &vsx, &vsy, &vsxy, _state); - spline->f.ptr.p_double[offs+d*(spline->n*j1+j0)+j] = spline->f.ptr.p_double[offs+d*(spline->n*j1+j0)+j]+vs; - spline->f.ptr.p_double[sfx+offs+d*(spline->n*j1+j0)+j] = spline->f.ptr.p_double[sfx+offs+d*(spline->n*j1+j0)+j]+vsx; - spline->f.ptr.p_double[sfy+offs+d*(spline->n*j1+j0)+j] = spline->f.ptr.p_double[sfy+offs+d*(spline->n*j1+j0)+j]+vsy; - spline->f.ptr.p_double[sfxy+offs+d*(spline->n*j1+j0)+j] = spline->f.ptr.p_double[sfxy+offs+d*(spline->n*j1+j0)+j]+vsxy; - } - } - } - - /* - * Recycle temporaries - */ - ae_shared_pool_recycle(pool, &_buf, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_spline2d_fastddmfitlayer(/* Real */ ae_vector* xy, - ae_int_t d, - ae_int_t scalexy, - /* Integer */ ae_vector* xyindex, - ae_int_t basecasex, - ae_int_t tilex0, - ae_int_t tilex1, - ae_int_t tilescountx, - ae_int_t basecasey, - ae_int_t tiley0, - ae_int_t tiley1, - ae_int_t tilescounty, - ae_int_t maxcoresize, - ae_int_t interfacesize, - ae_int_t lsqrcnt, - double lambdareg, - spline1dinterpolant* basis1, - ae_shared_pool* pool, - spline2dinterpolant* spline, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -This function performs fitting with BlockLLS solver. Internal function, -never use it directly. - -IMPORTANT: performance and memory requirements of this function are - asymmetric w.r.t. KX and KY: it has - * O(KY*KX^2) memory requirements - * O(KY*KX^3) running time - Thus, if you have large KY and small KX, simple transposition - of your dataset may give you great speedup. - -INPUT PARAMETERS: - AV - sparse matrix, [ARows,KX*KY] in size. "Vertical" version - of design matrix, rows [0,NPoints) contain values of basis - functions at dataset points. Other rows are used for - nonlinearity penalty and other stuff like that. - AH - transpose(AV), "horizontal" version of AV - ARows - rows count - XY - array[NPoints*(2+D)], dataset - KX, KY - grid size - NPoints - points count - D - number of components in vector-valued spline, D>=1 - LSQRCnt - number of iterations, non-zero: - * LSQRCnt>0 means that specified amount of preconditioned - LSQR iterations will be performed to solve problem; - usually we need 2..5 its. Recommended option - best - convergence and stability/quality. - * LSQRCnt<0 means that instead of LSQR we use iterative - refinement on normal equations. Again, 2..5 its is enough. - Z - possibly preallocated buffer for solution - Rep - report structure; fields which are not set by this function - are left intact - TSS - total sum of squares; used to calculate R2 - - -OUTPUT PARAMETERS: - XY - destroyed in process - Z - array[KX*KY*D], filled by solution; KX*KY coefficients - corresponding to each of D dimensions are stored contiguously. - Rep - following fields are set: - * Rep.RMSError - * Rep.AvgError - * Rep.MaxError - * Rep.R2 - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static void spline2d_blockllsfit(spline2dxdesignmatrix* xdesign, - ae_int_t lsqrcnt, - /* Real */ ae_vector* z, - spline2dfitreport* rep, - double tss, - spline2dblockllsbuf* buf, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t blockbandwidth; - ae_int_t d; - ae_int_t i; - ae_int_t j; - double lambdachol; - sreal mxata; - double v; - ae_int_t celloffset; - ae_int_t i0; - ae_int_t i1; - double rss; - ae_int_t arows; - ae_int_t bw2; - ae_int_t kx; - ae_int_t ky; - - ae_frame_make(_state, &_frame_block); - memset(&mxata, 0, sizeof(mxata)); - _sreal_init(&mxata, _state, ae_true); - - ae_assert(xdesign->blockwidth==4, "Spline2DFit: integrity check failed", _state); - blockbandwidth = 3; - d = xdesign->d; - arows = xdesign->nrows; - kx = xdesign->kx; - ky = xdesign->ky; - bw2 = xdesign->blockwidth*xdesign->blockwidth; - - /* - * Initial values for Z/Residuals - */ - rvectorsetlengthatleast(z, kx*ky*d, _state); - for(i=0; i<=kx*ky*d-1; i++) - { - z->ptr.p_double[i] = (double)(0); - } - - /* - * Create and factorize design matrix. Add regularizer if - * factorization failed (happens sometimes with zero - * smoothing and sparsely populated datasets). - * - * The algorithm below is refactoring of NaiveLLS algorithm, - * which uses sparsity properties and compressed block storage. - * - * Problem sparsity pattern results in block-band-diagonal - * matrix (block matrix with limited bandwidth, equal to 3 - * for bicubic splines). Thus, we have KY*KY blocks, each - * of them is KX*KX in size. Design matrix is stored in - * large NROWS*KX matrix, with NROWS=(BlockBandwidth+1)*KY*KX. - * - * We use adaptation of block skyline storage format, with - * TOWERSIZE*KX skyline bands (towers) stored sequentially; - * here TOWERSIZE=(BlockBandwidth+1)*KX. So, we have KY - * "towers", stored one below other, in BlockATA matrix. - * Every "tower" is a sequence of BlockBandwidth+1 cells, - * each of them being KX*KX in size. - */ - lambdachol = spline2d_cholreg; - rmatrixsetlengthatleast(&buf->blockata, (blockbandwidth+1)*ky*kx, kx, _state); - for(;;) - { - - /* - * Parallel generation of squared design matrix. - */ - spline2d_xdesignblockata(xdesign, &buf->blockata, &mxata.val, _state); - - /* - * Regularization - */ - v = coalesce(mxata.val, 1.0, _state)*lambdachol; - for(i1=0; i1<=ky-1; i1++) - { - celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, i1, i1, _state); - for(i0=0; i0<=kx-1; i0++) - { - buf->blockata.ptr.pp_double[celloffset+i0][i0] = buf->blockata.ptr.pp_double[celloffset+i0][i0]+v; - } - } - - /* - * Try Cholesky factorization. - */ - if( !spline2d_blockllscholesky(&buf->blockata, kx, ky, &buf->trsmbuf2, &buf->cholbuf2, &buf->cholbuf1, _state) ) - { - - /* - * Factorization failed, increase regularizer and repeat - */ - lambdachol = coalesce(10*lambdachol, 1.0E-12, _state); - continue; - } - break; - } - - /* - * Solve - */ - rss = 0.0; - rep->rmserror = (double)(0); - rep->avgerror = (double)(0); - rep->maxerror = (double)(0); - ae_assert(lsqrcnt>0, "Spline2DFit: integrity failure", _state); - rvectorsetlengthatleast(&buf->tmp0, arows, _state); - rvectorsetlengthatleast(&buf->tmp1, kx*ky, _state); - linlsqrcreatebuf(arows, kx*ky, &buf->solver, _state); - for(j=0; j<=d-1; j++) - { - - /* - * Preconditioned LSQR: - * - * use Cholesky factor U of squared design matrix A'*A to - * transform min|A*x-b| to min|[A*inv(U)]*y-b| with y=U*x. - * - * Preconditioned problem is solved with LSQR solver, which - * gives superior results than normal equations. - */ - for(i=0; i<=arows-1; i++) - { - if( inpoints ) - { - buf->tmp0.ptr.p_double[i] = xdesign->vals.ptr.pp_double[i][bw2+j]; - } - else - { - buf->tmp0.ptr.p_double[i] = 0.0; - } - } - linlsqrrestart(&buf->solver, _state); - linlsqrsetb(&buf->solver, &buf->tmp0, _state); - linlsqrsetcond(&buf->solver, 1.0E-14, 1.0E-14, lsqrcnt, _state); - while(linlsqriteration(&buf->solver, _state)) - { - if( buf->solver.needmv ) - { - - /* - * Use Cholesky factorization of the system matrix - * as preconditioner: solve TRSV(U,Solver.X) - */ - for(i=0; i<=kx*ky-1; i++) - { - buf->tmp1.ptr.p_double[i] = buf->solver.x.ptr.p_double[i]; - } - spline2d_blockllstrsv(&buf->blockata, kx, ky, ae_false, &buf->tmp1, _state); - - /* - * After preconditioning is done, multiply by A - */ - spline2d_xdesignmv(xdesign, &buf->tmp1, &buf->solver.mv, _state); - } - if( buf->solver.needmtv ) - { - - /* - * Multiply by design matrix A - */ - spline2d_xdesignmtv(xdesign, &buf->solver.x, &buf->solver.mtv, _state); - - /* - * Multiply by preconditioner: solve TRSV(U',A*Solver.X) - */ - spline2d_blockllstrsv(&buf->blockata, kx, ky, ae_true, &buf->solver.mtv, _state); - } - } - - /* - * Get results and post-multiply by preconditioner to get - * original variables. - */ - linlsqrresults(&buf->solver, &buf->tmp1, &buf->solverrep, _state); - spline2d_blockllstrsv(&buf->blockata, kx, ky, ae_false, &buf->tmp1, _state); - for(i=0; i<=kx*ky-1; i++) - { - z->ptr.p_double[kx*ky*j+i] = buf->tmp1.ptr.p_double[i]; - } - - /* - * Calculate model values - */ - spline2d_xdesignmv(xdesign, &buf->tmp1, &buf->tmp0, _state); - for(i=0; i<=xdesign->npoints-1; i++) - { - v = xdesign->vals.ptr.pp_double[i][bw2+j]-buf->tmp0.ptr.p_double[i]; - rss = rss+v*v; - rep->rmserror = rep->rmserror+ae_sqr(v, _state); - rep->avgerror = rep->avgerror+ae_fabs(v, _state); - rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(v, _state), _state); - } - } - rep->rmserror = ae_sqrt(rep->rmserror/coalesce((double)(xdesign->npoints*d), 1.0, _state), _state); - rep->avgerror = rep->avgerror/coalesce((double)(xdesign->npoints*d), 1.0, _state); - rep->r2 = 1.0-rss/coalesce(tss, 1.0, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function performs fitting with NaiveLLS solver. Internal function, -never use it directly. - -INPUT PARAMETERS: - AV - sparse matrix, [ARows,KX*KY] in size. "Vertical" version - of design matrix, rows [0,NPoints] contain values of basis - functions at dataset points. Other rows are used for - nonlinearity penalty and other stuff like that. - AH - transpose(AV), "horizontal" version of AV - ARows - rows count - XY - array[NPoints*(2+D)], dataset - KX, KY - grid size - NPoints - points count - D - number of components in vector-valued spline, D>=1 - LSQRCnt - number of iterations, non-zero: - * LSQRCnt>0 means that specified amount of preconditioned - LSQR iterations will be performed to solve problem; - usually we need 2..5 its. Recommended option - best - convergence and stability/quality. - * LSQRCnt<0 means that instead of LSQR we use iterative - refinement on normal equations. Again, 2..5 its is enough. - Z - possibly preallocated buffer for solution - Rep - report structure; fields which are not set by this function - are left intact - TSS - total sum of squares; used to calculate R2 - - -OUTPUT PARAMETERS: - XY - destroyed in process - Z - array[KX*KY*D], filled by solution; KX*KY coefficients - corresponding to each of D dimensions are stored contiguously. - Rep - following fields are set: - * Rep.RMSError - * Rep.AvgError - * Rep.MaxError - * Rep.R2 - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static void spline2d_naivellsfit(sparsematrix* av, - sparsematrix* ah, - ae_int_t arows, - /* Real */ ae_vector* xy, - ae_int_t kx, - ae_int_t ky, - ae_int_t npoints, - ae_int_t d, - ae_int_t lsqrcnt, - /* Real */ ae_vector* z, - spline2dfitreport* rep, - double tss, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t ew; - ae_int_t i; - ae_int_t j; - ae_int_t i0; - ae_int_t i1; - ae_int_t j0; - ae_int_t j1; - double v; - ae_int_t blockbandwidth; - double lambdareg; - ae_int_t srci; - ae_int_t srcj; - ae_int_t idxi; - ae_int_t idxj; - ae_int_t endi; - ae_int_t endj; - ae_int_t rfsidx; - ae_matrix ata; - ae_vector tmp0; - ae_vector tmp1; - double mxata; - linlsqrstate solver; - linlsqrreport solverrep; - double rss; - - ae_frame_make(_state, &_frame_block); - memset(&ata, 0, sizeof(ata)); - memset(&tmp0, 0, sizeof(tmp0)); - memset(&tmp1, 0, sizeof(tmp1)); - memset(&solver, 0, sizeof(solver)); - memset(&solverrep, 0, sizeof(solverrep)); - ae_matrix_init(&ata, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true); - _linlsqrstate_init(&solver, _state, ae_true); - _linlsqrreport_init(&solverrep, _state, ae_true); - - blockbandwidth = 3; - ew = 2+d; - - /* - * Initial values for Z/Residuals - */ - rvectorsetlengthatleast(z, kx*ky*d, _state); - for(i=0; i<=kx*ky*d-1; i++) - { - z->ptr.p_double[i] = (double)(0); - } - - /* - * Create and factorize design matrix. - * - * Add regularizer if factorization failed (happens sometimes - * with zero smoothing and sparsely populated datasets). - */ - lambdareg = spline2d_cholreg; - rmatrixsetlengthatleast(&ata, kx*ky, kx*ky, _state); - for(;;) - { - mxata = 0.0; - for(i=0; i<=kx*ky-1; i++) - { - for(j=i; j<=kx*ky-1; j++) - { - - /* - * Initialize by zero - */ - ata.ptr.pp_double[i][j] = (double)(0); - - /* - * Determine grid nodes corresponding to I and J; - * skip if too far away - */ - i0 = i%kx; - i1 = i/kx; - j0 = j%kx; - j1 = j/kx; - if( ae_iabs(i0-j0, _state)>blockbandwidth||ae_iabs(i1-j1, _state)>blockbandwidth ) - { - continue; - } - - /* - * Nodes are close enough, calculate product of columns I and J of A. - */ - v = (double)(0); - srci = ah->ridx.ptr.p_int[i]; - srcj = ah->ridx.ptr.p_int[j]; - endi = ah->ridx.ptr.p_int[i+1]; - endj = ah->ridx.ptr.p_int[j+1]; - for(;;) - { - if( srci>=endi||srcj>=endj ) - { - break; - } - idxi = ah->idx.ptr.p_int[srci]; - idxj = ah->idx.ptr.p_int[srcj]; - if( idxi==idxj ) - { - v = v+ah->vals.ptr.p_double[srci]*ah->vals.ptr.p_double[srcj]; - srci = srci+1; - srcj = srcj+1; - continue; - } - if( idxi0 ) - { - linlsqrcreate(arows, kx*ky, &solver, _state); - } - for(j=0; j<=d-1; j++) - { - ae_assert(lsqrcnt!=0, "Spline2DFit: integrity failure", _state); - if( lsqrcnt>0 ) - { - - /* - * Preconditioned LSQR: - * - * use Cholesky factor U of squared design matrix A'*A to - * transform min|A*x-b| to min|[A*inv(U)]*y-b| with y=U*x. - * - * Preconditioned problem is solved with LSQR solver, which - * gives superior results than normal equations. - */ - linlsqrcreate(arows, kx*ky, &solver, _state); - for(i=0; i<=arows-1; i++) - { - if( iptr.p_double[i*ew+2+j]; - } - else - { - tmp0.ptr.p_double[i] = 0.0; - } - } - linlsqrsetb(&solver, &tmp0, _state); - linlsqrsetcond(&solver, 1.0E-14, 1.0E-14, lsqrcnt, _state); - while(linlsqriteration(&solver, _state)) - { - if( solver.needmv ) - { - - /* - * Use Cholesky factorization of the system matrix - * as preconditioner: solve TRSV(U,Solver.X) - */ - for(i=0; i<=kx*ky-1; i++) - { - tmp1.ptr.p_double[i] = solver.x.ptr.p_double[i]; - } - rmatrixtrsv(kx*ky, &ata, 0, 0, ae_true, ae_false, 0, &tmp1, 0, _state); - - /* - * After preconditioning is done, multiply by A - */ - sparsemv(av, &tmp1, &solver.mv, _state); - } - if( solver.needmtv ) - { - - /* - * Multiply by design matrix A - */ - sparsemv(ah, &solver.x, &solver.mtv, _state); - - /* - * Multiply by preconditioner: solve TRSV(U',A*Solver.X) - */ - rmatrixtrsv(kx*ky, &ata, 0, 0, ae_true, ae_false, 1, &solver.mtv, 0, _state); - } - } - linlsqrresults(&solver, &tmp1, &solverrep, _state); - rmatrixtrsv(kx*ky, &ata, 0, 0, ae_true, ae_false, 0, &tmp1, 0, _state); - for(i=0; i<=kx*ky-1; i++) - { - z->ptr.p_double[kx*ky*j+i] = tmp1.ptr.p_double[i]; - } - - /* - * Calculate model values - */ - sparsemv(av, &tmp1, &tmp0, _state); - for(i=0; i<=npoints-1; i++) - { - xy->ptr.p_double[i*ew+2+j] = xy->ptr.p_double[i*ew+2+j]-tmp0.ptr.p_double[i]; - } - } - else - { - - /* - * Iterative refinement, inferior to LSQR - * - * For each dimension D: - * * fetch current estimate for solution from Z to Tmp1 - * * calculate residual r for current estimate, store in Tmp0 - * * calculate product of residual and design matrix A'*r, store it in Tmp1 - * * Cholesky solver - * * update current estimate - */ - for(rfsidx=1; rfsidx<=-lsqrcnt; rfsidx++) - { - for(i=0; i<=kx*ky-1; i++) - { - tmp1.ptr.p_double[i] = z->ptr.p_double[kx*ky*j+i]; - } - sparsemv(av, &tmp1, &tmp0, _state); - for(i=0; i<=arows-1; i++) - { - if( iptr.p_double[i*ew+2+j]; - } - else - { - v = (double)(0); - } - tmp0.ptr.p_double[i] = v-tmp0.ptr.p_double[i]; - } - sparsemv(ah, &tmp0, &tmp1, _state); - rmatrixtrsv(kx*ky, &ata, 0, 0, ae_true, ae_false, 1, &tmp1, 0, _state); - rmatrixtrsv(kx*ky, &ata, 0, 0, ae_true, ae_false, 0, &tmp1, 0, _state); - for(i=0; i<=kx*ky-1; i++) - { - z->ptr.p_double[kx*ky*j+i] = z->ptr.p_double[kx*ky*j+i]+tmp1.ptr.p_double[i]; - } - } - - /* - * Calculate model values - */ - for(i=0; i<=kx*ky-1; i++) - { - tmp1.ptr.p_double[i] = z->ptr.p_double[kx*ky*j+i]; - } - sparsemv(av, &tmp1, &tmp0, _state); - for(i=0; i<=npoints-1; i++) - { - xy->ptr.p_double[i*ew+2+j] = xy->ptr.p_double[i*ew+2+j]-tmp0.ptr.p_double[i]; - } - } - } - - /* - * Generate report - */ - rep->rmserror = (double)(0); - rep->avgerror = (double)(0); - rep->maxerror = (double)(0); - rss = 0.0; - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=d-1; j++) - { - v = xy->ptr.p_double[i*ew+2+j]; - rss = rss+v*v; - rep->rmserror = rep->rmserror+ae_sqr(v, _state); - rep->avgerror = rep->avgerror+ae_fabs(v, _state); - rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(v, _state), _state); - } - } - rep->rmserror = ae_sqrt(rep->rmserror/coalesce((double)(npoints*d), 1.0, _state), _state); - rep->avgerror = rep->avgerror/coalesce((double)(npoints*d), 1.0, _state); - rep->r2 = 1.0-rss/coalesce(tss, 1.0, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This is convenience function for band block storage format; it returns -offset of KX*KX-sized block (I,J) in a compressed 2D array. - -For specific offset=OFFSET, -block (I,J) will be stored in entries BlockMatrix[OFFSET:OFFSET+KX-1,0:KX-1] - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static ae_int_t spline2d_getcelloffset(ae_int_t kx, - ae_int_t ky, - ae_int_t blockbandwidth, - ae_int_t i, - ae_int_t j, - ae_state *_state) -{ - ae_int_t result; - - - ae_assert(i>=0&&i=0&&j=i&&j<=i+blockbandwidth, "Spline2DFit: GetCellOffset() integrity error", _state); - result = j*(blockbandwidth+1)*kx; - result = result+(blockbandwidth-(j-i))*kx; - return result; -} - - -/************************************************************************* -This is convenience function for band block storage format; it copies -cell (I,J) from compressed format to uncompressed general matrix, at desired -position. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static void spline2d_copycellto(ae_int_t kx, - ae_int_t ky, - ae_int_t blockbandwidth, - /* Real */ ae_matrix* blockata, - ae_int_t i, - ae_int_t j, - /* Real */ ae_matrix* dst, - ae_int_t dst0, - ae_int_t dst1, - ae_state *_state) -{ - ae_int_t celloffset; - ae_int_t idx0; - ae_int_t idx1; - - - celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, i, j, _state); - for(idx0=0; idx0<=kx-1; idx0++) - { - for(idx1=0; idx1<=kx-1; idx1++) - { - dst->ptr.pp_double[dst0+idx0][dst1+idx1] = blockata->ptr.pp_double[celloffset+idx0][idx1]; - } - } -} - - -/************************************************************************* -This is convenience function for band block storage format; it -truncates all elements of cell (I,J) which are less than Eps in magnitude. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static void spline2d_flushtozerocell(ae_int_t kx, - ae_int_t ky, - ae_int_t blockbandwidth, - /* Real */ ae_matrix* blockata, - ae_int_t i, - ae_int_t j, - double eps, - ae_state *_state) -{ - ae_int_t celloffset; - ae_int_t idx0; - ae_int_t idx1; - double eps2; - double v; - - - celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, i, j, _state); - eps2 = eps*eps; - for(idx0=0; idx0<=kx-1; idx0++) - { - for(idx1=0; idx1<=kx-1; idx1++) - { - v = blockata->ptr.pp_double[celloffset+idx0][idx1]; - if( v*vptr.pp_double[celloffset+idx0][idx1] = (double)(0); - } - } - } -} - - -/************************************************************************* -This function generates squared design matrix stored in block band format. - -We use adaptation of block skyline storage format, with -TOWERSIZE*KX skyline bands (towers) stored sequentially; -here TOWERSIZE=(BlockBandwidth+1)*KX. So, we have KY -"towers", stored one below other, in BlockATA matrix. -Every "tower" is a sequence of BlockBandwidth+1 cells, -each of them being KX*KX in size. - -INPUT PARAMETERS: - AH - sparse matrix, [KX*KY,ARows] in size. "Horizontal" version - of design matrix, cols [0,NPoints] contain values of basis - functions at dataset points. Other cols are used for - nonlinearity penalty and other stuff like that. - KY0, KY1- subset of output matrix bands to process; on entry it MUST - be set to 0 and KY respectively. - KX, KY - grid size - BlockATA- array[KY*(BlockBandwidth+1)*KX,KX], preallocated storage - for output matrix in compressed block band format - MXATA - on entry MUST be zero - -OUTPUT PARAMETERS: - BlockATA- AH*AH', stored in compressed block band format - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static void spline2d_blockllsgenerateata(sparsematrix* ah, - ae_int_t ky0, - ae_int_t ky1, - ae_int_t kx, - ae_int_t ky, - /* Real */ ae_matrix* blockata, - sreal* mxata, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t blockbandwidth; - double avgrowlen; - double cellcost; - double totalcost; - sreal tmpmxata; - ae_int_t i; - ae_int_t j; - ae_int_t i0; - ae_int_t i1; - ae_int_t j0; - ae_int_t j1; - ae_int_t celloffset; - double v; - ae_int_t srci; - ae_int_t srcj; - ae_int_t idxi; - ae_int_t idxj; - ae_int_t endi; - ae_int_t endj; - - ae_frame_make(_state, &_frame_block); - memset(&tmpmxata, 0, sizeof(tmpmxata)); - _sreal_init(&tmpmxata, _state, ae_true); - - ae_assert(ae_fp_greater_eq(mxata->val,(double)(0)), "BlockLLSGenerateATA: integrity check failed", _state); - blockbandwidth = 3; - - /* - * Determine problem cost, perform recursive subdivision - * (with optional parallelization) - */ - avgrowlen = (double)ah->ridx.ptr.p_int[kx*ky]/(double)(kx*ky); - cellcost = rmul3((double)(kx), (double)(1+2*blockbandwidth), avgrowlen, _state); - totalcost = rmul3((double)(ky1-ky0), (double)(1+2*blockbandwidth), cellcost, _state); - if( ky1-ky0>=2&&ae_fp_greater(totalcost,smpactivationlevel(_state)) ) - { - if( _trypexec_spline2d_blockllsgenerateata(ah,ky0,ky1,kx,ky,blockata,mxata, _state) ) - { - ae_frame_leave(_state); - return; - } - } - if( ky1-ky0>=2 ) - { - - /* - * Split X: X*A = (X1 X2)^T*A - */ - j = (ky1-ky0)/2; - spline2d_blockllsgenerateata(ah, ky0, ky0+j, kx, ky, blockata, &tmpmxata, _state); - spline2d_blockllsgenerateata(ah, ky0+j, ky1, kx, ky, blockata, mxata, _state); - mxata->val = ae_maxreal(mxata->val, tmpmxata.val, _state); - ae_frame_leave(_state); - return; - } - - /* - * Splitting in Y-dimension is done, fill I1-th "tower" - */ - ae_assert(ky1==ky0+1, "BlockLLSGenerateATA: integrity check failed", _state); - i1 = ky0; - for(j1=i1; j1<=ae_minint(ky-1, i1+blockbandwidth, _state); j1++) - { - celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, i1, j1, _state); - - /* - * Clear cell (I1,J1) - */ - for(i0=0; i0<=kx-1; i0++) - { - for(j0=0; j0<=kx-1; j0++) - { - blockata->ptr.pp_double[celloffset+i0][j0] = 0.0; - } - } - - /* - * Initialize cell internals - */ - for(i0=0; i0<=kx-1; i0++) - { - for(j0=0; j0<=kx-1; j0++) - { - if( ae_iabs(i0-j0, _state)<=blockbandwidth ) - { - - /* - * Nodes are close enough, calculate product of columns I and J of A. - */ - v = (double)(0); - i = i1*kx+i0; - j = j1*kx+j0; - srci = ah->ridx.ptr.p_int[i]; - srcj = ah->ridx.ptr.p_int[j]; - endi = ah->ridx.ptr.p_int[i+1]; - endj = ah->ridx.ptr.p_int[j+1]; - for(;;) - { - if( srci>=endi||srcj>=endj ) - { - break; - } - idxi = ah->idx.ptr.p_int[srci]; - idxj = ah->idx.ptr.p_int[srcj]; - if( idxi==idxj ) - { - v = v+ah->vals.ptr.p_double[srci]*ah->vals.ptr.p_double[srcj]; - srci = srci+1; - srcj = srcj+1; - continue; - } - if( idxiptr.pp_double[celloffset+i0][j0] = v; - mxata->val = ae_maxreal(mxata->val, ae_fabs(v, _state), _state); - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_spline2d_blockllsgenerateata(sparsematrix* ah, - ae_int_t ky0, - ae_int_t ky1, - ae_int_t kx, - ae_int_t ky, - /* Real */ ae_matrix* blockata, - sreal* mxata, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -This function performs Cholesky decomposition of squared design matrix -stored in block band format. - -INPUT PARAMETERS: - BlockATA - array[KY*(BlockBandwidth+1)*KX,KX], matrix in compressed - block band format - KX, KY - grid size - TrsmBuf2, - CholBuf2, - CholBuf1 - buffers; reused by this function on subsequent calls, - automatically preallocated on the first call - -OUTPUT PARAMETERS: - BlockATA- Cholesky factor, in compressed block band format - -Result: - True on success, False on Cholesky failure - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static ae_bool spline2d_blockllscholesky(/* Real */ ae_matrix* blockata, - ae_int_t kx, - ae_int_t ky, - /* Real */ ae_matrix* trsmbuf2, - /* Real */ ae_matrix* cholbuf2, - /* Real */ ae_vector* cholbuf1, - ae_state *_state) -{ - ae_int_t blockbandwidth; - ae_int_t blockidx; - ae_int_t i; - ae_int_t j; - ae_int_t celloffset; - ae_int_t celloffset1; - ae_bool result; - - - blockbandwidth = 3; - rmatrixsetlengthatleast(trsmbuf2, (blockbandwidth+1)*kx, (blockbandwidth+1)*kx, _state); - rmatrixsetlengthatleast(cholbuf2, kx, kx, _state); - rvectorsetlengthatleast(cholbuf1, kx, _state); - result = ae_true; - for(blockidx=0; blockidx<=ky-1; blockidx++) - { - - /* - * TRSM for TRAIL*TRAIL block matrix before current cell; - * here TRAIL=MinInt(BlockIdx,BlockBandwidth). - */ - for(i=0; i<=ae_minint(blockidx, blockbandwidth, _state)-1; i++) - { - for(j=i; j<=ae_minint(blockidx, blockbandwidth, _state)-1; j++) - { - spline2d_copycellto(kx, ky, blockbandwidth, blockata, ae_maxint(blockidx-blockbandwidth, 0, _state)+i, ae_maxint(blockidx-blockbandwidth, 0, _state)+j, trsmbuf2, i*kx, j*kx, _state); - } - } - celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, ae_maxint(blockidx-blockbandwidth, 0, _state), blockidx, _state); - rmatrixlefttrsm(ae_minint(blockidx, blockbandwidth, _state)*kx, kx, trsmbuf2, 0, 0, ae_true, ae_false, 1, blockata, celloffset, 0, _state); - - /* - * SYRK for diagonal cell: MaxInt(BlockIdx-BlockBandwidth,0) - * cells above diagonal one are used for update. - */ - celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, ae_maxint(blockidx-blockbandwidth, 0, _state), blockidx, _state); - celloffset1 = spline2d_getcelloffset(kx, ky, blockbandwidth, blockidx, blockidx, _state); - rmatrixsyrk(kx, ae_minint(blockidx, blockbandwidth, _state)*kx, -1.0, blockata, celloffset, 0, 1, 1.0, blockata, celloffset1, 0, ae_true, _state); - - /* - * Factorize diagonal cell - */ - celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, blockidx, blockidx, _state); - rmatrixcopy(kx, kx, blockata, celloffset, 0, cholbuf2, 0, 0, _state); - if( !spdmatrixcholeskyrec(cholbuf2, 0, kx, ae_true, cholbuf1, _state) ) - { - result = ae_false; - return result; - } - rmatrixcopy(kx, kx, cholbuf2, 0, 0, blockata, celloffset, 0, _state); - - /* - * PERFORMANCE TWEAK: drop nearly-denormals from last "tower". - * - * Sparse matrices like these may produce denormal numbers on - * sparse datasets, with significant (10x!) performance penalty - * on Intel chips. In order to avoid it, we manually truncate - * small enough numbers. - * - * We use 1.0E-50 as clipping level (not really denormal, but - * such small numbers are not actually important anyway). - */ - for(i=ae_maxint(blockidx-blockbandwidth, 0, _state); i<=blockidx; i++) - { - spline2d_flushtozerocell(kx, ky, blockbandwidth, blockata, i, blockidx, 1.0E-50, _state); - } - } - return result; -} - - -/************************************************************************* -This function performs TRSV on upper triangular Cholesky factor U, solving -either U*x=b or U'*x=b. - -INPUT PARAMETERS: - BlockATA - array[KY*(BlockBandwidth+1)*KX,KX], matrix U - in compressed block band format - KX, KY - grid size - TransU - whether to transpose U or not - B - array[KX*KY], on entry - stores right part B - -OUTPUT PARAMETERS: - B - replaced by X - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static void spline2d_blockllstrsv(/* Real */ ae_matrix* blockata, - ae_int_t kx, - ae_int_t ky, - ae_bool transu, - /* Real */ ae_vector* b, - ae_state *_state) -{ - ae_int_t blockbandwidth; - ae_int_t blockidx; - ae_int_t blockidx1; - ae_int_t celloffset; - - - blockbandwidth = 3; - if( !transu ) - { - - /* - * Solve U*x=b - */ - for(blockidx=ky-1; blockidx>=0; blockidx--) - { - for(blockidx1=1; blockidx1<=ae_minint(ky-(blockidx+1), blockbandwidth, _state); blockidx1++) - { - celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, blockidx, blockidx+blockidx1, _state); - rmatrixgemv(kx, kx, -1.0, blockata, celloffset, 0, 0, b, (blockidx+blockidx1)*kx, 1.0, b, blockidx*kx, _state); - } - celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, blockidx, blockidx, _state); - rmatrixtrsv(kx, blockata, celloffset, 0, ae_true, ae_false, 0, b, blockidx*kx, _state); - } - } - else - { - - /* - * Solve U'*x=b - */ - for(blockidx=0; blockidx<=ky-1; blockidx++) - { - celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, blockidx, blockidx, _state); - rmatrixtrsv(kx, blockata, celloffset, 0, ae_true, ae_false, 1, b, blockidx*kx, _state); - for(blockidx1=1; blockidx1<=ae_minint(ky-(blockidx+1), blockbandwidth, _state); blockidx1++) - { - celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, blockidx, blockidx+blockidx1, _state); - rmatrixgemv(kx, kx, -1.0, blockata, celloffset, 0, 1, b, blockidx*kx, 1.0, b, (blockidx+blockidx1)*kx, _state); - } - } - } -} - - -/************************************************************************* -This function computes residuals for dataset XY[], using array of original -values YRaw[], and loads residuals to XY. - -Processing is performed in parallel manner. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static void spline2d_computeresidualsfromscratch(/* Real */ ae_vector* xy, - /* Real */ ae_vector* yraw, - ae_int_t npoints, - ae_int_t d, - ae_int_t scalexy, - spline2dinterpolant* spline, - ae_state *_state) -{ - ae_frame _frame_block; - srealarray seed; - ae_shared_pool pool; - ae_int_t chunksize; - double pointcost; - - ae_frame_make(_state, &_frame_block); - memset(&seed, 0, sizeof(seed)); - memset(&pool, 0, sizeof(pool)); - _srealarray_init(&seed, _state, ae_true); - ae_shared_pool_init(&pool, _state, ae_true); - - - /* - * Setting up - */ - chunksize = 1000; - pointcost = 100.0; - if( ae_fp_greater(npoints*pointcost,smpactivationlevel(_state)) ) - { - if( _trypexec_spline2d_computeresidualsfromscratch(xy,yraw,npoints,d,scalexy,spline, _state) ) - { - ae_frame_leave(_state); - return; - } - } - ae_shared_pool_set_seed(&pool, &seed, sizeof(seed), _srealarray_init, _srealarray_init_copy, _srealarray_destroy, _state); - - /* - * Call compute workhorse - */ - spline2d_computeresidualsfromscratchrec(xy, yraw, 0, npoints, chunksize, d, scalexy, spline, &pool, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_spline2d_computeresidualsfromscratch(/* Real */ ae_vector* xy, - /* Real */ ae_vector* yraw, - ae_int_t npoints, - ae_int_t d, - ae_int_t scalexy, - spline2dinterpolant* spline, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -Recursive workhorse for ComputeResidualsFromScratch. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static void spline2d_computeresidualsfromscratchrec(/* Real */ ae_vector* xy, - /* Real */ ae_vector* yraw, - ae_int_t pt0, - ae_int_t pt1, - ae_int_t chunksize, - ae_int_t d, - ae_int_t scalexy, - spline2dinterpolant* spline, - ae_shared_pool* pool, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - srealarray *pbuf; - ae_smart_ptr _pbuf; - ae_int_t xew; - - ae_frame_make(_state, &_frame_block); - memset(&_pbuf, 0, sizeof(_pbuf)); - ae_smart_ptr_init(&_pbuf, (void**)&pbuf, _state, ae_true); - - xew = 2+d; - - /* - * Parallelism - */ - if( pt1-pt0>chunksize ) - { - tiledsplit(pt1-pt0, chunksize, &i, &j, _state); - spline2d_computeresidualsfromscratchrec(xy, yraw, pt0, pt0+i, chunksize, d, scalexy, spline, pool, _state); - spline2d_computeresidualsfromscratchrec(xy, yraw, pt0+i, pt1, chunksize, d, scalexy, spline, pool, _state); - ae_frame_leave(_state); - return; - } - - /* - * Serial execution - */ - ae_shared_pool_retrieve(pool, &_pbuf, _state); - for(i=pt0; i<=pt1-1; i++) - { - spline2dcalcvbuf(spline, xy->ptr.p_double[i*xew+0]*scalexy, xy->ptr.p_double[i*xew+1]*scalexy, &pbuf->val, _state); - for(j=0; j<=d-1; j++) - { - xy->ptr.p_double[i*xew+2+j] = yraw->ptr.p_double[i*d+j]-pbuf->val.ptr.p_double[j]; - } - } - ae_shared_pool_recycle(pool, &_pbuf, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_spline2d_computeresidualsfromscratchrec(/* Real */ ae_vector* xy, - /* Real */ ae_vector* yraw, - ae_int_t pt0, - ae_int_t pt1, - ae_int_t chunksize, - ae_int_t d, - ae_int_t scalexy, - spline2dinterpolant* spline, - ae_shared_pool* pool, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -This function reorders dataset and builds index: -* it is assumed that all points have X in [0,KX-1], Y in [0,KY-1] -* area is divided into (KX-1)*(KY-1) cells -* all points are reordered in such way that points in same cell are stored - contiguously -* dataset index, array[(KX-1)*(KY-1)+1], is generated. Points of cell I - now have indexes XYIndex[I]..XYIndex[I+1]-1; - -INPUT PARAMETERS: - XY - array[NPoints*(2+D)], dataset - KX, KY, D - grid size and dimensionality of the outputs - Shadow - shadow array[NPoints*NS], which is sorted together - with XY; if NS=0, it is not referenced at all. - NS - entry width of shadow array - BufI - possibly preallocated temporary buffer; resized if - needed. - -OUTPUT PARAMETERS: - XY - reordered - XYIndex - array[(KX-1)*(KY-1)+1], dataset index - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static void spline2d_reorderdatasetandbuildindex(/* Real */ ae_vector* xy, - ae_int_t npoints, - ae_int_t d, - /* Real */ ae_vector* shadow, - ae_int_t ns, - ae_int_t kx, - ae_int_t ky, - /* Integer */ ae_vector* xyindex, - /* Integer */ ae_vector* bufi, - ae_state *_state) -{ - ae_int_t i; - ae_int_t i0; - ae_int_t i1; - ae_int_t entrywidth; - - - - /* - * Set up - */ - ae_assert(kx>=2, "Spline2DFit.ReorderDatasetAndBuildIndex: integrity check failed", _state); - ae_assert(ky>=2, "Spline2DFit.ReorderDatasetAndBuildIndex: integrity check failed", _state); - entrywidth = 2+d; - ivectorsetlengthatleast(xyindex, (kx-1)*(ky-1)+1, _state); - ivectorsetlengthatleast(bufi, npoints, _state); - for(i=0; i<=npoints-1; i++) - { - i0 = iboundval(ae_ifloor(xy->ptr.p_double[i*entrywidth+0], _state), 0, kx-2, _state); - i1 = iboundval(ae_ifloor(xy->ptr.p_double[i*entrywidth+1], _state), 0, ky-2, _state); - bufi->ptr.p_int[i] = i1*(kx-1)+i0; - } - - /* - * Reorder - */ - spline2d_reorderdatasetandbuildindexrec(xy, d, shadow, ns, bufi, 0, npoints, xyindex, 0, (kx-1)*(ky-1), ae_true, _state); - xyindex->ptr.p_int[(kx-1)*(ky-1)] = npoints; -} - - -/************************************************************************* -This function multiplies all points in dataset by 2.0 and rebuilds index, -given previous index built for KX_prev=(KX-1)/2 and KY_prev=(KY-1)/2 - -INPUT PARAMETERS: - XY - array[NPoints*(2+D)], dataset BEFORE scaling - NPoints, D - dataset size and dimensionality of the outputs - Shadow - shadow array[NPoints*NS], which is sorted together - with XY; if NS=0, it is not referenced at all. - NS - entry width of shadow array - KX, KY - new grid dimensionality - XYIndex - index built for previous values of KX and KY - BufI - possibly preallocated temporary buffer; resized if - needed. - -OUTPUT PARAMETERS: - XY - reordered and multiplied by 2.0 - XYIndex - array[(KX-1)*(KY-1)+1], dataset index - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static void spline2d_rescaledatasetandrefineindex(/* Real */ ae_vector* xy, - ae_int_t npoints, - ae_int_t d, - /* Real */ ae_vector* shadow, - ae_int_t ns, - ae_int_t kx, - ae_int_t ky, - /* Integer */ ae_vector* xyindex, - /* Integer */ ae_vector* bufi, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector xyindexprev; - - ae_frame_make(_state, &_frame_block); - memset(&xyindexprev, 0, sizeof(xyindexprev)); - ae_vector_init(&xyindexprev, 0, DT_INT, _state, ae_true); - - - /* - * Set up - */ - ae_assert(kx>=2, "Spline2DFit.RescaleDataset2AndRefineIndex: integrity check failed", _state); - ae_assert(ky>=2, "Spline2DFit.RescaleDataset2AndRefineIndex: integrity check failed", _state); - ae_assert((kx-1)%2==0, "Spline2DFit.RescaleDataset2AndRefineIndex: integrity check failed", _state); - ae_assert((ky-1)%2==0, "Spline2DFit.RescaleDataset2AndRefineIndex: integrity check failed", _state); - ae_swap_vectors(xyindex, &xyindexprev); - ivectorsetlengthatleast(xyindex, (kx-1)*(ky-1)+1, _state); - ivectorsetlengthatleast(bufi, npoints, _state); - - /* - * Refine - */ - spline2d_expandindexrows(xy, d, shadow, ns, bufi, 0, npoints, &xyindexprev, 0, (ky+1)/2-1, xyindex, kx, ky, ae_true, _state); - xyindex->ptr.p_int[(kx-1)*(ky-1)] = npoints; - - /* - * Integrity check - */ - ae_frame_leave(_state); -} - - -/************************************************************************* -Recurrent divide-and-conquer indexing function - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static void spline2d_expandindexrows(/* Real */ ae_vector* xy, - ae_int_t d, - /* Real */ ae_vector* shadow, - ae_int_t ns, - /* Integer */ ae_vector* cidx, - ae_int_t pt0, - ae_int_t pt1, - /* Integer */ ae_vector* xyindexprev, - ae_int_t row0, - ae_int_t row1, - /* Integer */ ae_vector* xyindexnew, - ae_int_t kxnew, - ae_int_t kynew, - ae_bool rootcall, - ae_state *_state) -{ - ae_int_t i; - ae_int_t entrywidth; - ae_int_t kxprev; - double v; - ae_int_t i0; - ae_int_t i1; - double efficiency; - double cost; - ae_int_t rowmid; - - - kxprev = (kxnew+1)/2; - entrywidth = 2+d; - efficiency = 0.1; - cost = d*(pt1-pt0+1)*(ae_log((double)(kxnew), _state)/ae_log((double)(2), _state))/efficiency; - ae_assert(xyindexprev->ptr.p_int[row0*(kxprev-1)+0]==pt0, "Spline2DFit.ExpandIndexRows: integrity check failed", _state); - ae_assert(xyindexprev->ptr.p_int[row1*(kxprev-1)+0]==pt1, "Spline2DFit.ExpandIndexRows: integrity check failed", _state); - - /* - * Parallelism - */ - if( ((rootcall&&pt1-pt0>10000)&&row1-row0>=2)&&ae_fp_greater(cost,smpactivationlevel(_state)) ) - { - if( _trypexec_spline2d_expandindexrows(xy,d,shadow,ns,cidx,pt0,pt1,xyindexprev,row0,row1,xyindexnew,kxnew,kynew,rootcall, _state) ) - { - return; - } - } - - /* - * Partition - */ - if( row1-row0>=2 ) - { - tiledsplit(row1-row0, 1, &i0, &i1, _state); - rowmid = row0+i0; - spline2d_expandindexrows(xy, d, shadow, ns, cidx, pt0, xyindexprev->ptr.p_int[rowmid*(kxprev-1)+0], xyindexprev, row0, rowmid, xyindexnew, kxnew, kynew, ae_false, _state); - spline2d_expandindexrows(xy, d, shadow, ns, cidx, xyindexprev->ptr.p_int[rowmid*(kxprev-1)+0], pt1, xyindexprev, rowmid, row1, xyindexnew, kxnew, kynew, ae_false, _state); - return; - } - - /* - * Serial execution - */ - for(i=pt0; i<=pt1-1; i++) - { - v = 2*xy->ptr.p_double[i*entrywidth+0]; - xy->ptr.p_double[i*entrywidth+0] = v; - i0 = iboundval(ae_ifloor(v, _state), 0, kxnew-2, _state); - v = 2*xy->ptr.p_double[i*entrywidth+1]; - xy->ptr.p_double[i*entrywidth+1] = v; - i1 = iboundval(ae_ifloor(v, _state), 0, kynew-2, _state); - cidx->ptr.p_int[i] = i1*(kxnew-1)+i0; - } - spline2d_reorderdatasetandbuildindexrec(xy, d, shadow, ns, cidx, pt0, pt1, xyindexnew, 2*row0*(kxnew-1)+0, 2*row1*(kxnew-1)+0, ae_false, _state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_spline2d_expandindexrows(/* Real */ ae_vector* xy, - ae_int_t d, - /* Real */ ae_vector* shadow, - ae_int_t ns, - /* Integer */ ae_vector* cidx, - ae_int_t pt0, - ae_int_t pt1, - /* Integer */ ae_vector* xyindexprev, - ae_int_t row0, - ae_int_t row1, - /* Integer */ ae_vector* xyindexnew, - ae_int_t kxnew, - ae_int_t kynew, - ae_bool rootcall, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -Recurrent divide-and-conquer indexing function - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static void spline2d_reorderdatasetandbuildindexrec(/* Real */ ae_vector* xy, - ae_int_t d, - /* Real */ ae_vector* shadow, - ae_int_t ns, - /* Integer */ ae_vector* cidx, - ae_int_t pt0, - ae_int_t pt1, - /* Integer */ ae_vector* xyindex, - ae_int_t idx0, - ae_int_t idx1, - ae_bool rootcall, - ae_state *_state) -{ - ae_int_t entrywidth; - ae_int_t idxmid; - ae_int_t wrk0; - ae_int_t wrk1; - double efficiency; - double cost; - - - - /* - * Efficiency - performance of the code when compared with that - * of linear algebra code. - */ - entrywidth = 2+d; - efficiency = 0.1; - cost = d*(pt1-pt0+1)*ae_log((double)(idx1-idx0+1), _state)/ae_log((double)(2), _state)/efficiency; - - /* - * Parallelism - */ - if( ((rootcall&&pt1-pt0>10000)&&idx1-idx0>=2)&&ae_fp_greater(cost,smpactivationlevel(_state)) ) - { - if( _trypexec_spline2d_reorderdatasetandbuildindexrec(xy,d,shadow,ns,cidx,pt0,pt1,xyindex,idx0,idx1,rootcall, _state) ) - { - return; - } - } - - /* - * Store left bound to XYIndex - */ - xyindex->ptr.p_int[idx0] = pt0; - - /* - * Quick exit strategies - */ - if( idx1<=idx0+1 ) - { - return; - } - if( pt0==pt1 ) - { - for(idxmid=idx0+1; idxmid<=idx1-1; idxmid++) - { - xyindex->ptr.p_int[idxmid] = pt1; - } - return; - } - - /* - * Select middle element - */ - idxmid = idx0+(idx1-idx0)/2; - ae_assert(idx0ptr.p_int[wrk0]=pt0&&cidx->ptr.p_int[wrk1]>=idxmid) - { - wrk1 = wrk1-1; - } - if( wrk1<=wrk0 ) - { - break; - } - swapentries(xy, wrk0, wrk1, entrywidth, _state); - if( ns>0 ) - { - swapentries(shadow, wrk0, wrk1, ns, _state); - } - swapelementsi(cidx, wrk0, wrk1, _state); - } - spline2d_reorderdatasetandbuildindexrec(xy, d, shadow, ns, cidx, pt0, wrk0, xyindex, idx0, idxmid, ae_false, _state); - spline2d_reorderdatasetandbuildindexrec(xy, d, shadow, ns, cidx, wrk0, pt1, xyindex, idxmid, idx1, ae_false, _state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_spline2d_reorderdatasetandbuildindexrec(/* Real */ ae_vector* xy, - ae_int_t d, - /* Real */ ae_vector* shadow, - ae_int_t ns, - /* Integer */ ae_vector* cidx, - ae_int_t pt0, - ae_int_t pt1, - /* Integer */ ae_vector* xyindex, - ae_int_t idx0, - ae_int_t idx1, - ae_bool rootcall, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -This function performs fitting with BlockLLS solver. Internal function, -never use it directly. - -INPUT PARAMETERS: - XY - dataset, array[NPoints,2+D] - XYIndex - dataset index, see ReorderDatasetAndBuildIndex() for more info - KX0, KX1- X-indices of basis functions to select and fit; - range [KX0,KX1) is processed - KXTotal - total number of indexes in the entire grid - KY0, KY1- Y-indices of basis functions to select and fit; - range [KY0,KY1) is processed - KYTotal - total number of indexes in the entire grid - D - number of components in vector-valued spline, D>=1 - LambdaReg- regularization coefficient - LambdaNS- nonlinearity penalty, exactly zero value is specially handled - (entire set of rows is not added to the matrix) - Basis1 - single-dimensional B-spline - - -OUTPUT PARAMETERS: - A - design matrix - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static void spline2d_xdesigngenerate(/* Real */ ae_vector* xy, - /* Integer */ ae_vector* xyindex, - ae_int_t kx0, - ae_int_t kx1, - ae_int_t kxtotal, - ae_int_t ky0, - ae_int_t ky1, - ae_int_t kytotal, - ae_int_t d, - double lambdareg, - double lambdans, - spline1dinterpolant* basis1, - spline2dxdesignmatrix* a, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t entrywidth; - ae_int_t i; - ae_int_t j; - ae_int_t j0; - ae_int_t j1; - ae_int_t k0; - ae_int_t k1; - ae_int_t kx; - ae_int_t ky; - ae_int_t rowsdone; - ae_int_t batchesdone; - ae_int_t pt0; - ae_int_t pt1; - ae_int_t base0; - ae_int_t base1; - ae_int_t baseidx; - ae_int_t nzshift; - ae_int_t nzwidth; - ae_matrix d2x; - ae_matrix d2y; - ae_matrix dxy; - double v; - double v0; - double v1; - double v2; - double w0; - double w1; - double w2; - - ae_frame_make(_state, &_frame_block); - memset(&d2x, 0, sizeof(d2x)); - memset(&d2y, 0, sizeof(d2y)); - memset(&dxy, 0, sizeof(dxy)); - ae_matrix_init(&d2x, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&d2y, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&dxy, 0, 0, DT_REAL, _state, ae_true); - - nzshift = 1; - nzwidth = 4; - entrywidth = 2+d; - kx = kx1-kx0; - ky = ky1-ky0; - a->lambdareg = lambdareg; - a->blockwidth = 4; - a->kx = kx; - a->ky = ky; - a->d = d; - a->npoints = 0; - a->ndenserows = 0; - a->ndensebatches = 0; - a->maxbatch = 0; - for(j1=ky0; j1<=ky1-2; j1++) - { - for(j0=kx0; j0<=kx1-2; j0++) - { - i = xyindex->ptr.p_int[j1*(kxtotal-1)+j0+1]-xyindex->ptr.p_int[j1*(kxtotal-1)+j0]; - a->npoints = a->npoints+i; - a->ndenserows = a->ndenserows+i; - a->ndensebatches = a->ndensebatches+1; - a->maxbatch = ae_maxint(a->maxbatch, i, _state); - } - } - if( ae_fp_neq(lambdans,(double)(0)) ) - { - ae_assert(ae_fp_greater_eq(lambdans,(double)(0)), "Spline2DFit: integrity check failed", _state); - a->ndenserows = a->ndenserows+3*(kx-2)*(ky-2); - a->ndensebatches = a->ndensebatches+(kx-2)*(ky-2); - a->maxbatch = ae_maxint(a->maxbatch, 3, _state); - } - a->nrows = a->ndenserows+kx*ky; - rmatrixsetlengthatleast(&a->vals, a->ndenserows, a->blockwidth*a->blockwidth+d, _state); - ivectorsetlengthatleast(&a->batches, a->ndensebatches+1, _state); - ivectorsetlengthatleast(&a->batchbases, a->ndensebatches, _state); - - /* - * Setup output counters - */ - batchesdone = 0; - rowsdone = 0; - - /* - * Generate rows corresponding to dataset points - */ - ae_assert(kx>=nzwidth, "Spline2DFit: integrity check failed", _state); - ae_assert(ky>=nzwidth, "Spline2DFit: integrity check failed", _state); - rvectorsetlengthatleast(&a->tmp0, nzwidth, _state); - rvectorsetlengthatleast(&a->tmp1, nzwidth, _state); - a->batches.ptr.p_int[batchesdone] = 0; - for(j1=ky0; j1<=ky1-2; j1++) - { - for(j0=kx0; j0<=kx1-2; j0++) - { - pt0 = xyindex->ptr.p_int[j1*(kxtotal-1)+j0]; - pt1 = xyindex->ptr.p_int[j1*(kxtotal-1)+j0+1]; - base0 = iboundval(j0-kx0-nzshift, 0, kx-nzwidth, _state); - base1 = iboundval(j1-ky0-nzshift, 0, ky-nzwidth, _state); - baseidx = base1*kx+base0; - a->batchbases.ptr.p_int[batchesdone] = baseidx; - for(i=pt0; i<=pt1-1; i++) - { - for(k0=0; k0<=nzwidth-1; k0++) - { - a->tmp0.ptr.p_double[k0] = spline1dcalc(basis1, xy->ptr.p_double[i*entrywidth+0]-(base0+kx0+k0), _state); - } - for(k1=0; k1<=nzwidth-1; k1++) - { - a->tmp1.ptr.p_double[k1] = spline1dcalc(basis1, xy->ptr.p_double[i*entrywidth+1]-(base1+ky0+k1), _state); - } - for(k1=0; k1<=nzwidth-1; k1++) - { - for(k0=0; k0<=nzwidth-1; k0++) - { - a->vals.ptr.pp_double[rowsdone][k1*nzwidth+k0] = a->tmp0.ptr.p_double[k0]*a->tmp1.ptr.p_double[k1]; - } - } - for(j=0; j<=d-1; j++) - { - a->vals.ptr.pp_double[rowsdone][nzwidth*nzwidth+j] = xy->ptr.p_double[i*entrywidth+2+j]; - } - rowsdone = rowsdone+1; - } - batchesdone = batchesdone+1; - a->batches.ptr.p_int[batchesdone] = rowsdone; - } - } - - /* - * Generate rows corresponding to nonlinearity penalty - */ - if( ae_fp_greater(lambdans,(double)(0)) ) - { - - /* - * Smoothing is applied. Because all grid nodes are same, - * we apply same smoothing kernel, which is calculated only - * once at the beginning of design matrix generation. - */ - ae_matrix_set_length(&d2x, 3, 3, _state); - ae_matrix_set_length(&d2y, 3, 3, _state); - ae_matrix_set_length(&dxy, 3, 3, _state); - for(j1=0; j1<=2; j1++) - { - for(j0=0; j0<=2; j0++) - { - d2x.ptr.pp_double[j0][j1] = 0.0; - d2y.ptr.pp_double[j0][j1] = 0.0; - dxy.ptr.pp_double[j0][j1] = 0.0; - } - } - for(k1=0; k1<=2; k1++) - { - for(k0=0; k0<=2; k0++) - { - spline1ddiff(basis1, (double)(-(k0-1)), &v0, &v1, &v2, _state); - spline1ddiff(basis1, (double)(-(k1-1)), &w0, &w1, &w2, _state); - d2x.ptr.pp_double[k0][k1] = d2x.ptr.pp_double[k0][k1]+v2*w0; - d2y.ptr.pp_double[k0][k1] = d2y.ptr.pp_double[k0][k1]+w2*v0; - dxy.ptr.pp_double[k0][k1] = dxy.ptr.pp_double[k0][k1]+v1*w1; - } - } - - /* - * Now, kernel is ready - apply it to all inner nodes of the grid. - */ - for(j1=1; j1<=ky-2; j1++) - { - for(j0=1; j0<=kx-2; j0++) - { - base0 = imax2(j0-2, 0, _state); - base1 = imax2(j1-2, 0, _state); - baseidx = base1*kx+base0; - a->batchbases.ptr.p_int[batchesdone] = baseidx; - - /* - * d2F/dx2 term - */ - v = lambdans; - for(j=0; j<=nzwidth*nzwidth+d-1; j++) - { - a->vals.ptr.pp_double[rowsdone][j] = (double)(0); - } - for(k1=j1-1; k1<=j1+1; k1++) - { - for(k0=j0-1; k0<=j0+1; k0++) - { - a->vals.ptr.pp_double[rowsdone][nzwidth*(k1-base1)+(k0-base0)] = v*d2x.ptr.pp_double[1+(k0-j0)][1+(k1-j1)]; - } - } - rowsdone = rowsdone+1; - - /* - * d2F/dy2 term - */ - v = lambdans; - for(j=0; j<=nzwidth*nzwidth+d-1; j++) - { - a->vals.ptr.pp_double[rowsdone][j] = (double)(0); - } - for(k1=j1-1; k1<=j1+1; k1++) - { - for(k0=j0-1; k0<=j0+1; k0++) - { - a->vals.ptr.pp_double[rowsdone][nzwidth*(k1-base1)+(k0-base0)] = v*d2y.ptr.pp_double[1+(k0-j0)][1+(k1-j1)]; - } - } - rowsdone = rowsdone+1; - - /* - * 2*d2F/dxdy term - */ - v = ae_sqrt((double)(2), _state)*lambdans; - for(j=0; j<=nzwidth*nzwidth+d-1; j++) - { - a->vals.ptr.pp_double[rowsdone][j] = (double)(0); - } - for(k1=j1-1; k1<=j1+1; k1++) - { - for(k0=j0-1; k0<=j0+1; k0++) - { - a->vals.ptr.pp_double[rowsdone][nzwidth*(k1-base1)+(k0-base0)] = v*dxy.ptr.pp_double[1+(k0-j0)][1+(k1-j1)]; - } - } - rowsdone = rowsdone+1; - batchesdone = batchesdone+1; - a->batches.ptr.p_int[batchesdone] = rowsdone; - } - } - } - - /* - * Integrity post-check - */ - ae_assert(batchesdone==a->ndensebatches, "Spline2DFit: integrity check failed", _state); - ae_assert(rowsdone==a->ndenserows, "Spline2DFit: integrity check failed", _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function performs matrix-vector product of design matrix and dense -vector. - -INPUT PARAMETERS: - A - design matrix, (a.nrows) X (a.kx*a.ky); - some fields of A are used for temporaries, - so it is non-constant. - X - array[A.KX*A.KY] - - -OUTPUT PARAMETERS: - Y - product, array[A.NRows], automatically allocated - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static void spline2d_xdesignmv(spline2dxdesignmatrix* a, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t bidx; - ae_int_t i; - ae_int_t cnt; - double v; - ae_int_t baseidx; - ae_int_t outidx; - ae_int_t batchsize; - ae_int_t kx; - ae_int_t k0; - ae_int_t k1; - ae_int_t nzwidth; - - - nzwidth = 4; - ae_assert(a->blockwidth==nzwidth, "Spline2DFit: integrity check failed", _state); - ae_assert(x->cnt>=a->kx*a->ky, "Spline2DFit: integrity check failed", _state); - - /* - * Prepare - */ - rvectorsetlengthatleast(y, a->nrows, _state); - rvectorsetlengthatleast(&a->tmp0, nzwidth*nzwidth, _state); - rvectorsetlengthatleast(&a->tmp1, a->maxbatch, _state); - kx = a->kx; - outidx = 0; - - /* - * Process dense part - */ - for(bidx=0; bidx<=a->ndensebatches-1; bidx++) - { - if( a->batches.ptr.p_int[bidx+1]-a->batches.ptr.p_int[bidx]>0 ) - { - batchsize = a->batches.ptr.p_int[bidx+1]-a->batches.ptr.p_int[bidx]; - baseidx = a->batchbases.ptr.p_int[bidx]; - for(k1=0; k1<=nzwidth-1; k1++) - { - for(k0=0; k0<=nzwidth-1; k0++) - { - a->tmp0.ptr.p_double[k1*nzwidth+k0] = x->ptr.p_double[baseidx+k1*kx+k0]; - } - } - rmatrixgemv(batchsize, nzwidth*nzwidth, 1.0, &a->vals, a->batches.ptr.p_int[bidx], 0, 0, &a->tmp0, 0, 0.0, &a->tmp1, 0, _state); - for(i=0; i<=batchsize-1; i++) - { - y->ptr.p_double[outidx+i] = a->tmp1.ptr.p_double[i]; - } - outidx = outidx+batchsize; - } - } - ae_assert(outidx==a->ndenserows, "Spline2DFit: integrity check failed", _state); - - /* - * Process regularizer - */ - v = a->lambdareg; - cnt = a->kx*a->ky; - for(i=0; i<=cnt-1; i++) - { - y->ptr.p_double[outidx+i] = v*x->ptr.p_double[i]; - } - outidx = outidx+cnt; - - /* - * Post-check - */ - ae_assert(outidx==a->nrows, "Spline2DFit: integrity check failed", _state); -} - - -/************************************************************************* -This function performs matrix-vector product of transposed design matrix and dense -vector. - -INPUT PARAMETERS: - A - design matrix, (a.nrows) X (a.kx*a.ky); - some fields of A are used for temporaries, - so it is non-constant. - X - array[A.NRows] - - -OUTPUT PARAMETERS: - Y - product, array[A.KX*A.KY], automatically allocated - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static void spline2d_xdesignmtv(spline2dxdesignmatrix* a, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t bidx; - ae_int_t i; - ae_int_t cnt; - double v; - ae_int_t baseidx; - ae_int_t inidx; - ae_int_t batchsize; - ae_int_t kx; - ae_int_t k0; - ae_int_t k1; - ae_int_t nzwidth; - - - nzwidth = 4; - ae_assert(a->blockwidth==nzwidth, "Spline2DFit: integrity check failed", _state); - ae_assert(x->cnt>=a->nrows, "Spline2DFit: integrity check failed", _state); - - /* - * Prepare - */ - rvectorsetlengthatleast(y, a->kx*a->ky, _state); - rvectorsetlengthatleast(&a->tmp0, nzwidth*nzwidth, _state); - rvectorsetlengthatleast(&a->tmp1, a->maxbatch, _state); - kx = a->kx; - inidx = 0; - cnt = a->kx*a->ky; - for(i=0; i<=cnt-1; i++) - { - y->ptr.p_double[i] = (double)(0); - } - - /* - * Process dense part - */ - for(bidx=0; bidx<=a->ndensebatches-1; bidx++) - { - if( a->batches.ptr.p_int[bidx+1]-a->batches.ptr.p_int[bidx]>0 ) - { - batchsize = a->batches.ptr.p_int[bidx+1]-a->batches.ptr.p_int[bidx]; - baseidx = a->batchbases.ptr.p_int[bidx]; - for(i=0; i<=batchsize-1; i++) - { - a->tmp1.ptr.p_double[i] = x->ptr.p_double[inidx+i]; - } - rmatrixgemv(nzwidth*nzwidth, batchsize, 1.0, &a->vals, a->batches.ptr.p_int[bidx], 0, 1, &a->tmp1, 0, 0.0, &a->tmp0, 0, _state); - for(k1=0; k1<=nzwidth-1; k1++) - { - for(k0=0; k0<=nzwidth-1; k0++) - { - y->ptr.p_double[baseidx+k1*kx+k0] = y->ptr.p_double[baseidx+k1*kx+k0]+a->tmp0.ptr.p_double[k1*nzwidth+k0]; - } - } - inidx = inidx+batchsize; - } - } - ae_assert(inidx==a->ndenserows, "Spline2DFit: integrity check failed", _state); - - /* - * Process regularizer - */ - v = a->lambdareg; - cnt = a->kx*a->ky; - for(i=0; i<=cnt-1; i++) - { - y->ptr.p_double[i] = y->ptr.p_double[i]+v*x->ptr.p_double[inidx+i]; - } - inidx = inidx+cnt; - - /* - * Post-check - */ - ae_assert(inidx==a->nrows, "Spline2DFit: integrity check failed", _state); -} - - -/************************************************************************* -This function generates squared design matrix stored in block band format. - -We use an adaptation of block skyline storage format, with -TOWERSIZE*KX skyline bands (towers) stored sequentially; here -TOWERSIZE=(BlockBandwidth+1)*KX. So, we have KY "towers", stored one below -other, in BlockATA matrix. Every "tower" is a sequence of BlockBandwidth+1 -cells, each of them being KX*KX in size. - -INPUT PARAMETERS: - A - design matrix; some of its fields are used for temporaries - BlockATA- array[KY*(BlockBandwidth+1)*KX,KX], preallocated storage - for output matrix in compressed block band format - -OUTPUT PARAMETERS: - BlockATA- AH*AH', stored in compressed block band format - MXATA - max(|AH*AH'|), elementwise - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -static void spline2d_xdesignblockata(spline2dxdesignmatrix* a, - /* Real */ ae_matrix* blockata, - double* mxata, - ae_state *_state) -{ - ae_int_t blockbandwidth; - ae_int_t nzwidth; - ae_int_t kx; - ae_int_t ky; - ae_int_t i0; - ae_int_t i1; - ae_int_t j0; - ae_int_t j1; - ae_int_t celloffset; - ae_int_t bidx; - ae_int_t baseidx; - ae_int_t batchsize; - ae_int_t offs0; - ae_int_t offs1; - double v; - - - blockbandwidth = 3; - nzwidth = 4; - kx = a->kx; - ky = a->ky; - ae_assert(a->blockwidth==nzwidth, "Spline2DFit: integrity check failed", _state); - rmatrixsetlengthatleast(&a->tmp2, nzwidth*nzwidth, nzwidth*nzwidth, _state); - - /* - * Initial zero-fill: - * * zero-fill ALL elements of BlockATA - * * zero-fill ALL elements of Tmp2 - * - * Filling ALL elements, including unused ones, is essential for the - * purposes of calculating max(BlockATA). - */ - for(i1=0; i1<=ky-1; i1++) - { - for(i0=i1; i0<=ae_minint(ky-1, i1+blockbandwidth, _state); i0++) - { - celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, i1, i0, _state); - for(j1=0; j1<=kx-1; j1++) - { - for(j0=0; j0<=kx-1; j0++) - { - blockata->ptr.pp_double[celloffset+j1][j0] = 0.0; - } - } - } - } - for(j1=0; j1<=nzwidth*nzwidth-1; j1++) - { - for(j0=0; j0<=nzwidth*nzwidth-1; j0++) - { - a->tmp2.ptr.pp_double[j1][j0] = 0.0; - } - } - - /* - * Process dense part of A - */ - for(bidx=0; bidx<=a->ndensebatches-1; bidx++) - { - if( a->batches.ptr.p_int[bidx+1]-a->batches.ptr.p_int[bidx]>0 ) - { - - /* - * Generate 16x16 U = BATCH'*BATCH and add it to ATA. - * - * NOTE: it is essential that lower triangle of Tmp2 is - * filled by zeros. - */ - batchsize = a->batches.ptr.p_int[bidx+1]-a->batches.ptr.p_int[bidx]; - rmatrixsyrk(nzwidth*nzwidth, batchsize, 1.0, &a->vals, a->batches.ptr.p_int[bidx], 0, 2, 0.0, &a->tmp2, 0, 0, ae_true, _state); - baseidx = a->batchbases.ptr.p_int[bidx]; - for(i1=0; i1<=nzwidth-1; i1++) - { - for(j1=i1; j1<=nzwidth-1; j1++) - { - celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, baseidx/kx+i1, baseidx/kx+j1, _state); - offs0 = baseidx%kx; - offs1 = baseidx%kx; - for(i0=0; i0<=nzwidth-1; i0++) - { - for(j0=0; j0<=nzwidth-1; j0++) - { - v = a->tmp2.ptr.pp_double[i1*nzwidth+i0][j1*nzwidth+j0]; - blockata->ptr.pp_double[celloffset+offs1+i0][offs0+j0] = blockata->ptr.pp_double[celloffset+offs1+i0][offs0+j0]+v; - } - } - } - } - } - } - - /* - * Process regularizer term - */ - for(i1=0; i1<=ky-1; i1++) - { - celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, i1, i1, _state); - for(j1=0; j1<=kx-1; j1++) - { - blockata->ptr.pp_double[celloffset+j1][j1] = blockata->ptr.pp_double[celloffset+j1][j1]+ae_sqr(a->lambdareg, _state); - } - } - - /* - * Calculate max(ATA) - * - * NOTE: here we rely on zero initialization of unused parts of - * BlockATA and Tmp2. - */ - *mxata = 0.0; - for(i1=0; i1<=ky-1; i1++) - { - for(i0=i1; i0<=ae_minint(ky-1, i1+blockbandwidth, _state); i0++) - { - celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, i1, i0, _state); - for(j1=0; j1<=kx-1; j1++) - { - for(j0=0; j0<=kx-1; j0++) - { - *mxata = ae_maxreal(*mxata, ae_fabs(blockata->ptr.pp_double[celloffset+j1][j0], _state), _state); - } - } - } - } -} - - -void _spline2dinterpolant_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - spline2dinterpolant *p = (spline2dinterpolant*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->f, 0, DT_REAL, _state, make_automatic); -} - - -void _spline2dinterpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - spline2dinterpolant *dst = (spline2dinterpolant*)_dst; - spline2dinterpolant *src = (spline2dinterpolant*)_src; - dst->stype = src->stype; - dst->n = src->n; - dst->m = src->m; - dst->d = src->d; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic); - ae_vector_init_copy(&dst->f, &src->f, _state, make_automatic); -} - - -void _spline2dinterpolant_clear(void* _p) -{ - spline2dinterpolant *p = (spline2dinterpolant*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->x); - ae_vector_clear(&p->y); - ae_vector_clear(&p->f); -} - - -void _spline2dinterpolant_destroy(void* _p) -{ - spline2dinterpolant *p = (spline2dinterpolant*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->y); - ae_vector_destroy(&p->f); -} - - -void _spline2dbuilder_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - spline2dbuilder *p = (spline2dbuilder*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->xy, 0, DT_REAL, _state, make_automatic); -} - - -void _spline2dbuilder_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - spline2dbuilder *dst = (spline2dbuilder*)_dst; - spline2dbuilder *src = (spline2dbuilder*)_src; - dst->priorterm = src->priorterm; - dst->priortermval = src->priortermval; - dst->areatype = src->areatype; - dst->xa = src->xa; - dst->xb = src->xb; - dst->ya = src->ya; - dst->yb = src->yb; - dst->gridtype = src->gridtype; - dst->kx = src->kx; - dst->ky = src->ky; - dst->smoothing = src->smoothing; - dst->nlayers = src->nlayers; - dst->solvertype = src->solvertype; - dst->lambdabase = src->lambdabase; - ae_vector_init_copy(&dst->xy, &src->xy, _state, make_automatic); - dst->npoints = src->npoints; - dst->d = src->d; - dst->sx = src->sx; - dst->sy = src->sy; - dst->adddegreeoffreedom = src->adddegreeoffreedom; - dst->interfacesize = src->interfacesize; - dst->lsqrcnt = src->lsqrcnt; - dst->maxcoresize = src->maxcoresize; -} - - -void _spline2dbuilder_clear(void* _p) -{ - spline2dbuilder *p = (spline2dbuilder*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->xy); -} - - -void _spline2dbuilder_destroy(void* _p) -{ - spline2dbuilder *p = (spline2dbuilder*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->xy); -} - - -void _spline2dfitreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - spline2dfitreport *p = (spline2dfitreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _spline2dfitreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - spline2dfitreport *dst = (spline2dfitreport*)_dst; - spline2dfitreport *src = (spline2dfitreport*)_src; - dst->rmserror = src->rmserror; - dst->avgerror = src->avgerror; - dst->maxerror = src->maxerror; - dst->r2 = src->r2; -} - - -void _spline2dfitreport_clear(void* _p) -{ - spline2dfitreport *p = (spline2dfitreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _spline2dfitreport_destroy(void* _p) -{ - spline2dfitreport *p = (spline2dfitreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _spline2dxdesignmatrix_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - spline2dxdesignmatrix *p = (spline2dxdesignmatrix*)_p; - ae_touch_ptr((void*)p); - ae_matrix_init(&p->vals, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->batches, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->batchbases, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->tmp2, 0, 0, DT_REAL, _state, make_automatic); -} - - -void _spline2dxdesignmatrix_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - spline2dxdesignmatrix *dst = (spline2dxdesignmatrix*)_dst; - spline2dxdesignmatrix *src = (spline2dxdesignmatrix*)_src; - dst->blockwidth = src->blockwidth; - dst->kx = src->kx; - dst->ky = src->ky; - dst->npoints = src->npoints; - dst->nrows = src->nrows; - dst->ndenserows = src->ndenserows; - dst->ndensebatches = src->ndensebatches; - dst->d = src->d; - dst->maxbatch = src->maxbatch; - ae_matrix_init_copy(&dst->vals, &src->vals, _state, make_automatic); - ae_vector_init_copy(&dst->batches, &src->batches, _state, make_automatic); - ae_vector_init_copy(&dst->batchbases, &src->batchbases, _state, make_automatic); - dst->lambdareg = src->lambdareg; - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic); - ae_matrix_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic); -} - - -void _spline2dxdesignmatrix_clear(void* _p) -{ - spline2dxdesignmatrix *p = (spline2dxdesignmatrix*)_p; - ae_touch_ptr((void*)p); - ae_matrix_clear(&p->vals); - ae_vector_clear(&p->batches); - ae_vector_clear(&p->batchbases); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->tmp1); - ae_matrix_clear(&p->tmp2); -} - - -void _spline2dxdesignmatrix_destroy(void* _p) -{ - spline2dxdesignmatrix *p = (spline2dxdesignmatrix*)_p; - ae_touch_ptr((void*)p); - ae_matrix_destroy(&p->vals); - ae_vector_destroy(&p->batches); - ae_vector_destroy(&p->batchbases); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->tmp1); - ae_matrix_destroy(&p->tmp2); -} - - -void _spline2dblockllsbuf_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - spline2dblockllsbuf *p = (spline2dblockllsbuf*)_p; - ae_touch_ptr((void*)p); - _linlsqrstate_init(&p->solver, _state, make_automatic); - _linlsqrreport_init(&p->solverrep, _state, make_automatic); - ae_matrix_init(&p->blockata, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->trsmbuf2, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->cholbuf2, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cholbuf1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic); -} - - -void _spline2dblockllsbuf_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - spline2dblockllsbuf *dst = (spline2dblockllsbuf*)_dst; - spline2dblockllsbuf *src = (spline2dblockllsbuf*)_src; - _linlsqrstate_init_copy(&dst->solver, &src->solver, _state, make_automatic); - _linlsqrreport_init_copy(&dst->solverrep, &src->solverrep, _state, make_automatic); - ae_matrix_init_copy(&dst->blockata, &src->blockata, _state, make_automatic); - ae_matrix_init_copy(&dst->trsmbuf2, &src->trsmbuf2, _state, make_automatic); - ae_matrix_init_copy(&dst->cholbuf2, &src->cholbuf2, _state, make_automatic); - ae_vector_init_copy(&dst->cholbuf1, &src->cholbuf1, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic); -} - - -void _spline2dblockllsbuf_clear(void* _p) -{ - spline2dblockllsbuf *p = (spline2dblockllsbuf*)_p; - ae_touch_ptr((void*)p); - _linlsqrstate_clear(&p->solver); - _linlsqrreport_clear(&p->solverrep); - ae_matrix_clear(&p->blockata); - ae_matrix_clear(&p->trsmbuf2); - ae_matrix_clear(&p->cholbuf2); - ae_vector_clear(&p->cholbuf1); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->tmp1); -} - - -void _spline2dblockllsbuf_destroy(void* _p) -{ - spline2dblockllsbuf *p = (spline2dblockllsbuf*)_p; - ae_touch_ptr((void*)p); - _linlsqrstate_destroy(&p->solver); - _linlsqrreport_destroy(&p->solverrep); - ae_matrix_destroy(&p->blockata); - ae_matrix_destroy(&p->trsmbuf2); - ae_matrix_destroy(&p->cholbuf2); - ae_vector_destroy(&p->cholbuf1); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->tmp1); -} - - -void _spline2dfastddmbuf_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - spline2dfastddmbuf *p = (spline2dfastddmbuf*)_p; - ae_touch_ptr((void*)p); - _spline2dxdesignmatrix_init(&p->xdesignmatrix, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpz, 0, DT_REAL, _state, make_automatic); - _spline2dfitreport_init(&p->dummyrep, _state, make_automatic); - _spline2dinterpolant_init(&p->localmodel, _state, make_automatic); - _spline2dblockllsbuf_init(&p->blockllsbuf, _state, make_automatic); -} - - -void _spline2dfastddmbuf_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - spline2dfastddmbuf *dst = (spline2dfastddmbuf*)_dst; - spline2dfastddmbuf *src = (spline2dfastddmbuf*)_src; - _spline2dxdesignmatrix_init_copy(&dst->xdesignmatrix, &src->xdesignmatrix, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->tmpz, &src->tmpz, _state, make_automatic); - _spline2dfitreport_init_copy(&dst->dummyrep, &src->dummyrep, _state, make_automatic); - _spline2dinterpolant_init_copy(&dst->localmodel, &src->localmodel, _state, make_automatic); - _spline2dblockllsbuf_init_copy(&dst->blockllsbuf, &src->blockllsbuf, _state, make_automatic); -} - - -void _spline2dfastddmbuf_clear(void* _p) -{ - spline2dfastddmbuf *p = (spline2dfastddmbuf*)_p; - ae_touch_ptr((void*)p); - _spline2dxdesignmatrix_clear(&p->xdesignmatrix); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->tmpz); - _spline2dfitreport_clear(&p->dummyrep); - _spline2dinterpolant_clear(&p->localmodel); - _spline2dblockllsbuf_clear(&p->blockllsbuf); -} - - -void _spline2dfastddmbuf_destroy(void* _p) -{ - spline2dfastddmbuf *p = (spline2dfastddmbuf*)_p; - ae_touch_ptr((void*)p); - _spline2dxdesignmatrix_destroy(&p->xdesignmatrix); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->tmpz); - _spline2dfitreport_destroy(&p->dummyrep); - _spline2dinterpolant_destroy(&p->localmodel); - _spline2dblockllsbuf_destroy(&p->blockllsbuf); -} - - -#endif -#if defined(AE_COMPILE_RBFV1) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function creates RBF model for a scalar (NY=1) or vector (NY>1) -function in a NX-dimensional space (NX=2 or NX=3). - -INPUT PARAMETERS: - NX - dimension of the space, NX=2 or NX=3 - NY - function dimension, NY>=1 - -OUTPUT PARAMETERS: - S - RBF model (initially equals to zero) - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfv1create(ae_int_t nx, - ae_int_t ny, - rbfv1model* s, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - _rbfv1model_clear(s); - - ae_assert(nx==2||nx==3, "RBFCreate: NX<>2 and NX<>3", _state); - ae_assert(ny>=1, "RBFCreate: NY<1", _state); - s->nx = nx; - s->ny = ny; - s->nl = 0; - s->nc = 0; - ae_matrix_set_length(&s->v, ny, rbfv1_mxnx+1, _state); - for(i=0; i<=ny-1; i++) - { - for(j=0; j<=rbfv1_mxnx; j++) - { - s->v.ptr.pp_double[i][j] = (double)(0); - } - } - s->rmax = (double)(0); -} - - -/************************************************************************* -This function creates buffer structure which can be used to perform -parallel RBF model evaluations (with one RBF model instance being -used from multiple threads, as long as different threads use different -instances of buffer). - -This buffer object can be used with rbftscalcbuf() function (here "ts" -stands for "thread-safe", "buf" is a suffix which denotes function which -reuses previously allocated output space). - -How to use it: -* create RBF model structure with rbfcreate() -* load data, tune parameters -* call rbfbuildmodel() -* call rbfcreatecalcbuffer(), once per thread working with RBF model (you - should call this function only AFTER call to rbfbuildmodel(), see below - for more information) -* call rbftscalcbuf() from different threads, with each thread working - with its own copy of buffer object. - -INPUT PARAMETERS - S - RBF model - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: buffer object should be used only with RBF model object which - was used to initialize buffer. Any attempt to use buffer with - different object is dangerous - you may get memory violation - error because sizes of internal arrays do not fit to dimensions - of RBF structure. - -IMPORTANT: you should call this function only for model which was built - with rbfbuildmodel() function, after successful invocation of - rbfbuildmodel(). Sizes of some internal structures are - determined only after model is built, so buffer object created - before model construction stage will be useless (and any - attempt to use it will result in exception). - - -- ALGLIB -- - Copyright 02.04.2016 by Sergey Bochkanov -*************************************************************************/ -void rbfv1createcalcbuffer(rbfv1model* s, - rbfv1calcbuffer* buf, - ae_state *_state) -{ - - _rbfv1calcbuffer_clear(buf); - - kdtreecreaterequestbuffer(&s->tree, &buf->requestbuffer, _state); -} - - -/************************************************************************* -This function builds RBF model and returns report (contains some -information which can be used for evaluation of the algorithm properties). - -Call to this function modifies RBF model by calculating its centers/radii/ -weights and saving them into RBFModel structure. Initially RBFModel -contain zero coefficients, but after call to this function we will have -coefficients which were calculated in order to fit our dataset. - -After you called this function you can call RBFCalc(), RBFGridCalc() and -other model calculation functions. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - Rep - report: - * Rep.TerminationType: - * -5 - non-distinct basis function centers were detected, - interpolation aborted - * -4 - nonconvergence of the internal SVD solver - * 1 - successful termination - Fields are used for debugging purposes: - * Rep.IterationsCount - iterations count of the LSQR solver - * Rep.NMV - number of matrix-vector products - * Rep.ARows - rows count for the system matrix - * Rep.ACols - columns count for the system matrix - * Rep.ANNZ - number of significantly non-zero elements - (elements above some algorithm-determined threshold) - -NOTE: failure to build model will leave current state of the structure -unchanged. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfv1buildmodel(/* Real */ ae_matrix* x, - /* Real */ ae_matrix* y, - ae_int_t n, - ae_int_t aterm, - ae_int_t algorithmtype, - ae_int_t nlayers, - double radvalue, - double radzvalue, - double lambdav, - double epsort, - double epserr, - ae_int_t maxits, - rbfv1model* s, - rbfv1report* rep, - ae_state *_state) -{ - ae_frame _frame_block; - kdtree tree; - kdtree ctree; - ae_vector dist; - ae_vector xcx; - ae_matrix a; - ae_matrix v; - ae_matrix omega; - ae_matrix residualy; - ae_vector radius; - ae_matrix xc; - ae_int_t nc; - double rmax; - ae_vector tags; - ae_vector ctags; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t snnz; - ae_vector tmp0; - ae_vector tmp1; - ae_int_t layerscnt; - ae_bool modelstatus; - - ae_frame_make(_state, &_frame_block); - memset(&tree, 0, sizeof(tree)); - memset(&ctree, 0, sizeof(ctree)); - memset(&dist, 0, sizeof(dist)); - memset(&xcx, 0, sizeof(xcx)); - memset(&a, 0, sizeof(a)); - memset(&v, 0, sizeof(v)); - memset(&omega, 0, sizeof(omega)); - memset(&residualy, 0, sizeof(residualy)); - memset(&radius, 0, sizeof(radius)); - memset(&xc, 0, sizeof(xc)); - memset(&tags, 0, sizeof(tags)); - memset(&ctags, 0, sizeof(ctags)); - memset(&tmp0, 0, sizeof(tmp0)); - memset(&tmp1, 0, sizeof(tmp1)); - _rbfv1report_clear(rep); - _kdtree_init(&tree, _state, ae_true); - _kdtree_init(&ctree, _state, ae_true); - ae_vector_init(&dist, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xcx, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&omega, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&residualy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&radius, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xc, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tags, 0, DT_INT, _state, ae_true); - ae_vector_init(&ctags, 0, DT_INT, _state, ae_true); - ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true); - - ae_assert(s->nx==2||s->nx==3, "RBFBuildModel: S.NX<>2 or S.NX<>3!", _state); - - /* - * Quick exit when we have no points - */ - if( n==0 ) - { - rep->terminationtype = 1; - rep->iterationscount = 0; - rep->nmv = 0; - rep->arows = 0; - rep->acols = 0; - kdtreebuildtagged(&s->xc, &tags, 0, rbfv1_mxnx, 0, 2, &s->tree, _state); - ae_matrix_set_length(&s->xc, 0, 0, _state); - ae_matrix_set_length(&s->wr, 0, 0, _state); - s->nc = 0; - s->rmax = (double)(0); - ae_matrix_set_length(&s->v, s->ny, rbfv1_mxnx+1, _state); - for(i=0; i<=s->ny-1; i++) - { - for(j=0; j<=rbfv1_mxnx; j++) - { - s->v.ptr.pp_double[i][j] = (double)(0); - } - } - ae_frame_leave(_state); - return; - } - - /* - * General case, N>0 - */ - rep->annz = 0; - rep->iterationscount = 0; - rep->nmv = 0; - ae_vector_set_length(&xcx, rbfv1_mxnx, _state); - - /* - * First model in a sequence - linear model. - * Residuals from linear regression are stored in the ResidualY variable - * (used later to build RBF models). - */ - ae_matrix_set_length(&residualy, n, s->ny, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=s->ny-1; j++) - { - residualy.ptr.pp_double[i][j] = y->ptr.pp_double[i][j]; - } - } - if( !rbfv1_rbfv1buildlinearmodel(x, &residualy, n, s->ny, aterm, &v, _state) ) - { - rep->terminationtype = -5; - ae_frame_leave(_state); - return; - } - - /* - * Handle special case: multilayer model with NLayers=0. - * Quick exit. - */ - if( algorithmtype==2&&nlayers==0 ) - { - rep->terminationtype = 1; - rep->iterationscount = 0; - rep->nmv = 0; - rep->arows = 0; - rep->acols = 0; - kdtreebuildtagged(&s->xc, &tags, 0, rbfv1_mxnx, 0, 2, &s->tree, _state); - ae_matrix_set_length(&s->xc, 0, 0, _state); - ae_matrix_set_length(&s->wr, 0, 0, _state); - s->nc = 0; - s->rmax = (double)(0); - ae_matrix_set_length(&s->v, s->ny, rbfv1_mxnx+1, _state); - for(i=0; i<=s->ny-1; i++) - { - for(j=0; j<=rbfv1_mxnx; j++) - { - s->v.ptr.pp_double[i][j] = v.ptr.pp_double[i][j]; - } - } - ae_frame_leave(_state); - return; - } - - /* - * Second model in a sequence - RBF term. - * - * NOTE: assignments below are not necessary, but without them - * MSVC complains about unitialized variables. - */ - nc = 0; - rmax = (double)(0); - layerscnt = 0; - modelstatus = ae_false; - if( algorithmtype==1 ) - { - - /* - * Add RBF model. - * This model uses local KD-trees to speed-up nearest neighbor searches. - */ - nc = n; - ae_matrix_set_length(&xc, nc, rbfv1_mxnx, _state); - for(i=0; i<=nc-1; i++) - { - for(j=0; j<=rbfv1_mxnx-1; j++) - { - xc.ptr.pp_double[i][j] = x->ptr.pp_double[i][j]; - } - } - rmax = (double)(0); - ae_vector_set_length(&radius, nc, _state); - ae_vector_set_length(&ctags, nc, _state); - for(i=0; i<=nc-1; i++) - { - ctags.ptr.p_int[i] = i; - } - kdtreebuildtagged(&xc, &ctags, nc, rbfv1_mxnx, 0, 2, &ctree, _state); - if( nc==0 ) - { - rmax = (double)(1); - } - else - { - if( nc==1 ) - { - radius.ptr.p_double[0] = radvalue; - rmax = radius.ptr.p_double[0]; - } - else - { - - /* - * NC>1, calculate radii using distances to nearest neigbors - */ - for(i=0; i<=nc-1; i++) - { - for(j=0; j<=rbfv1_mxnx-1; j++) - { - xcx.ptr.p_double[j] = xc.ptr.pp_double[i][j]; - } - if( kdtreequeryknn(&ctree, &xcx, 1, ae_false, _state)>0 ) - { - kdtreequeryresultsdistances(&ctree, &dist, _state); - radius.ptr.p_double[i] = radvalue*dist.ptr.p_double[0]; - } - else - { - - /* - * No neighbors found (it will happen when we have only one center). - * Initialize radius with default value. - */ - radius.ptr.p_double[i] = 1.0; - } - } - - /* - * Apply filtering - */ - rvectorsetlengthatleast(&tmp0, nc, _state); - for(i=0; i<=nc-1; i++) - { - tmp0.ptr.p_double[i] = radius.ptr.p_double[i]; - } - tagsortfast(&tmp0, &tmp1, nc, _state); - for(i=0; i<=nc-1; i++) - { - radius.ptr.p_double[i] = ae_minreal(radius.ptr.p_double[i], radzvalue*tmp0.ptr.p_double[nc/2], _state); - } - - /* - * Calculate RMax, check that all radii are non-zero - */ - for(i=0; i<=nc-1; i++) - { - rmax = ae_maxreal(rmax, radius.ptr.p_double[i], _state); - } - for(i=0; i<=nc-1; i++) - { - if( ae_fp_eq(radius.ptr.p_double[i],(double)(0)) ) - { - rep->terminationtype = -5; - ae_frame_leave(_state); - return; - } - } - } - } - ivectorsetlengthatleast(&tags, n, _state); - for(i=0; i<=n-1; i++) - { - tags.ptr.p_int[i] = i; - } - kdtreebuildtagged(x, &tags, n, rbfv1_mxnx, 0, 2, &tree, _state); - rbfv1_buildrbfmodellsqr(x, &residualy, &xc, &radius, n, nc, s->ny, &tree, &ctree, epsort, epserr, maxits, &rep->annz, &snnz, &omega, &rep->terminationtype, &rep->iterationscount, &rep->nmv, _state); - layerscnt = 1; - modelstatus = ae_true; - } - if( algorithmtype==2 ) - { - rmax = radvalue; - rbfv1_buildrbfmlayersmodellsqr(x, &residualy, &xc, radvalue, &radius, n, &nc, s->ny, nlayers, &ctree, 1.0E-6, 1.0E-6, 50, lambdav, &rep->annz, &omega, &rep->terminationtype, &rep->iterationscount, &rep->nmv, _state); - layerscnt = nlayers; - modelstatus = ae_true; - } - ae_assert(modelstatus, "RBFBuildModel: integrity error", _state); - if( rep->terminationtype<=0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Model is built - */ - s->nc = nc/layerscnt; - s->rmax = rmax; - s->nl = layerscnt; - ae_matrix_set_length(&s->xc, s->nc, rbfv1_mxnx, _state); - ae_matrix_set_length(&s->wr, s->nc, 1+s->nl*s->ny, _state); - ae_matrix_set_length(&s->v, s->ny, rbfv1_mxnx+1, _state); - for(i=0; i<=s->nc-1; i++) - { - for(j=0; j<=rbfv1_mxnx-1; j++) - { - s->xc.ptr.pp_double[i][j] = xc.ptr.pp_double[i][j]; - } - } - ivectorsetlengthatleast(&tags, s->nc, _state); - for(i=0; i<=s->nc-1; i++) - { - tags.ptr.p_int[i] = i; - } - kdtreebuildtagged(&s->xc, &tags, s->nc, rbfv1_mxnx, 0, 2, &s->tree, _state); - for(i=0; i<=s->nc-1; i++) - { - s->wr.ptr.pp_double[i][0] = radius.ptr.p_double[i]; - for(k=0; k<=layerscnt-1; k++) - { - for(j=0; j<=s->ny-1; j++) - { - s->wr.ptr.pp_double[i][1+k*s->ny+j] = omega.ptr.pp_double[k*s->nc+i][j]; - } - } - } - for(i=0; i<=s->ny-1; i++) - { - for(j=0; j<=rbfv1_mxnx; j++) - { - s->v.ptr.pp_double[i][j] = v.ptr.pp_double[i][j]; - } - } - rep->terminationtype = 1; - rep->arows = n; - rep->acols = s->nc; - ae_frame_leave(_state); -} - - -/************************************************************************* -Serializer: allocation - - -- ALGLIB -- - Copyright 02.02.2012 by Bochkanov Sergey -*************************************************************************/ -void rbfv1alloc(ae_serializer* s, rbfv1model* model, ae_state *_state) -{ - - - - /* - * Data - */ - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - ae_serializer_alloc_entry(s); - kdtreealloc(s, &model->tree, _state); - allocrealmatrix(s, &model->xc, -1, -1, _state); - allocrealmatrix(s, &model->wr, -1, -1, _state); - ae_serializer_alloc_entry(s); - allocrealmatrix(s, &model->v, -1, -1, _state); -} - - -/************************************************************************* -Serializer: serialization - - -- ALGLIB -- - Copyright 02.02.2012 by Bochkanov Sergey -*************************************************************************/ -void rbfv1serialize(ae_serializer* s, rbfv1model* model, ae_state *_state) -{ - - - - /* - * Data - */ - ae_serializer_serialize_int(s, model->nx, _state); - ae_serializer_serialize_int(s, model->ny, _state); - ae_serializer_serialize_int(s, model->nc, _state); - ae_serializer_serialize_int(s, model->nl, _state); - kdtreeserialize(s, &model->tree, _state); - serializerealmatrix(s, &model->xc, -1, -1, _state); - serializerealmatrix(s, &model->wr, -1, -1, _state); - ae_serializer_serialize_double(s, model->rmax, _state); - serializerealmatrix(s, &model->v, -1, -1, _state); -} - - -/************************************************************************* -Serializer: unserialization - - -- ALGLIB -- - Copyright 02.02.2012 by Bochkanov Sergey -*************************************************************************/ -void rbfv1unserialize(ae_serializer* s, - rbfv1model* model, - ae_state *_state) -{ - ae_int_t nx; - ae_int_t ny; - - _rbfv1model_clear(model); - - - /* - * Unserialize primary model parameters, initialize model. - * - * It is necessary to call RBFCreate() because some internal fields - * which are NOT unserialized will need initialization. - */ - ae_serializer_unserialize_int(s, &nx, _state); - ae_serializer_unserialize_int(s, &ny, _state); - rbfv1create(nx, ny, model, _state); - ae_serializer_unserialize_int(s, &model->nc, _state); - ae_serializer_unserialize_int(s, &model->nl, _state); - kdtreeunserialize(s, &model->tree, _state); - unserializerealmatrix(s, &model->xc, _state); - unserializerealmatrix(s, &model->wr, _state); - ae_serializer_unserialize_double(s, &model->rmax, _state); - unserializerealmatrix(s, &model->v, _state); -} - - -/************************************************************************* -This function calculates values of the RBF model in the given point. - -This function should be used when we have NY=1 (scalar function) and NX=2 -(2-dimensional space). If you have 3-dimensional space, use RBFCalc3(). If -you have general situation (NX-dimensional space, NY-dimensional function) -you should use general, less efficient implementation RBFCalc(). - -If you want to calculate function values many times, consider using -RBFGridCalc2(), which is far more efficient than many subsequent calls to -RBFCalc2(). - -This function returns 0.0 when: -* model is not initialized -* NX<>2 - *NY<>1 - -INPUT PARAMETERS: - S - RBF model - X0 - first coordinate, finite number - X1 - second coordinate, finite number - -RESULT: - value of the model or 0.0 (as defined above) - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -double rbfv1calc2(rbfv1model* s, double x0, double x1, ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t lx; - ae_int_t tg; - double d2; - double t; - double bfcur; - double rcur; - double result; - - - ae_assert(ae_isfinite(x0, _state), "RBFCalc2: invalid value for X0 (X0 is Inf)!", _state); - ae_assert(ae_isfinite(x1, _state), "RBFCalc2: invalid value for X1 (X1 is Inf)!", _state); - if( s->ny!=1||s->nx!=2 ) - { - result = (double)(0); - return result; - } - result = s->v.ptr.pp_double[0][0]*x0+s->v.ptr.pp_double[0][1]*x1+s->v.ptr.pp_double[0][rbfv1_mxnx]; - if( s->nc==0 ) - { - return result; - } - rvectorsetlengthatleast(&s->calcbufxcx, rbfv1_mxnx, _state); - for(i=0; i<=rbfv1_mxnx-1; i++) - { - s->calcbufxcx.ptr.p_double[i] = 0.0; - } - s->calcbufxcx.ptr.p_double[0] = x0; - s->calcbufxcx.ptr.p_double[1] = x1; - lx = kdtreequeryrnn(&s->tree, &s->calcbufxcx, s->rmax*rbfv1_rbffarradius, ae_true, _state); - kdtreequeryresultsx(&s->tree, &s->calcbufx, _state); - kdtreequeryresultstags(&s->tree, &s->calcbuftags, _state); - for(i=0; i<=lx-1; i++) - { - tg = s->calcbuftags.ptr.p_int[i]; - d2 = ae_sqr(x0-s->calcbufx.ptr.pp_double[i][0], _state)+ae_sqr(x1-s->calcbufx.ptr.pp_double[i][1], _state); - rcur = s->wr.ptr.pp_double[tg][0]; - bfcur = ae_exp(-d2/(rcur*rcur), _state); - for(j=0; j<=s->nl-1; j++) - { - result = result+bfcur*s->wr.ptr.pp_double[tg][1+j]; - rcur = 0.5*rcur; - t = bfcur*bfcur; - bfcur = t*t; - } - } - return result; -} - - -/************************************************************************* -This function calculates values of the RBF model in the given point. - -This function should be used when we have NY=1 (scalar function) and NX=3 -(3-dimensional space). If you have 2-dimensional space, use RBFCalc2(). If -you have general situation (NX-dimensional space, NY-dimensional function) -you should use general, less efficient implementation RBFCalc(). - -This function returns 0.0 when: -* model is not initialized -* NX<>3 - *NY<>1 - -INPUT PARAMETERS: - S - RBF model - X0 - first coordinate, finite number - X1 - second coordinate, finite number - X2 - third coordinate, finite number - -RESULT: - value of the model or 0.0 (as defined above) - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -double rbfv1calc3(rbfv1model* s, - double x0, - double x1, - double x2, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t lx; - ae_int_t tg; - double t; - double rcur; - double bf; - double result; - - - ae_assert(ae_isfinite(x0, _state), "RBFCalc3: invalid value for X0 (X0 is Inf or NaN)!", _state); - ae_assert(ae_isfinite(x1, _state), "RBFCalc3: invalid value for X1 (X1 is Inf or NaN)!", _state); - ae_assert(ae_isfinite(x2, _state), "RBFCalc3: invalid value for X2 (X2 is Inf or NaN)!", _state); - if( s->ny!=1||s->nx!=3 ) - { - result = (double)(0); - return result; - } - result = s->v.ptr.pp_double[0][0]*x0+s->v.ptr.pp_double[0][1]*x1+s->v.ptr.pp_double[0][2]*x2+s->v.ptr.pp_double[0][rbfv1_mxnx]; - if( s->nc==0 ) - { - return result; - } - - /* - * calculating value for F(X) - */ - rvectorsetlengthatleast(&s->calcbufxcx, rbfv1_mxnx, _state); - for(i=0; i<=rbfv1_mxnx-1; i++) - { - s->calcbufxcx.ptr.p_double[i] = 0.0; - } - s->calcbufxcx.ptr.p_double[0] = x0; - s->calcbufxcx.ptr.p_double[1] = x1; - s->calcbufxcx.ptr.p_double[2] = x2; - lx = kdtreequeryrnn(&s->tree, &s->calcbufxcx, s->rmax*rbfv1_rbffarradius, ae_true, _state); - kdtreequeryresultsx(&s->tree, &s->calcbufx, _state); - kdtreequeryresultstags(&s->tree, &s->calcbuftags, _state); - for(i=0; i<=lx-1; i++) - { - tg = s->calcbuftags.ptr.p_int[i]; - rcur = s->wr.ptr.pp_double[tg][0]; - bf = ae_exp(-(ae_sqr(x0-s->calcbufx.ptr.pp_double[i][0], _state)+ae_sqr(x1-s->calcbufx.ptr.pp_double[i][1], _state)+ae_sqr(x2-s->calcbufx.ptr.pp_double[i][2], _state))/ae_sqr(rcur, _state), _state); - for(j=0; j<=s->nl-1; j++) - { - result = result+bf*s->wr.ptr.pp_double[tg][1+j]; - t = bf*bf; - bf = t*t; - } - } - return result; -} - - -/************************************************************************* -This function calculates values of the RBF model at the given point. - -Same as RBFCalc(), but does not reallocate Y when in is large enough to -store function values. - -INPUT PARAMETERS: - S - RBF model - X - coordinates, array[NX]. - X may have more than NX elements, in this case only - leading NX will be used. - Y - possibly preallocated array - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is not reallocated when it - is larger than NY. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfv1calcbuf(rbfv1model* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t lx; - ae_int_t tg; - double t; - double rcur; - double bf; - - - ae_assert(x->cnt>=s->nx, "RBFCalcBuf: Length(X)nx, _state), "RBFCalcBuf: X contains infinite or NaN values", _state); - if( y->cntny ) - { - ae_vector_set_length(y, s->ny, _state); - } - for(i=0; i<=s->ny-1; i++) - { - y->ptr.p_double[i] = s->v.ptr.pp_double[i][rbfv1_mxnx]; - for(j=0; j<=s->nx-1; j++) - { - y->ptr.p_double[i] = y->ptr.p_double[i]+s->v.ptr.pp_double[i][j]*x->ptr.p_double[j]; - } - } - if( s->nc==0 ) - { - return; - } - rvectorsetlengthatleast(&s->calcbufxcx, rbfv1_mxnx, _state); - for(i=0; i<=rbfv1_mxnx-1; i++) - { - s->calcbufxcx.ptr.p_double[i] = 0.0; - } - for(i=0; i<=s->nx-1; i++) - { - s->calcbufxcx.ptr.p_double[i] = x->ptr.p_double[i]; - } - lx = kdtreequeryrnn(&s->tree, &s->calcbufxcx, s->rmax*rbfv1_rbffarradius, ae_true, _state); - kdtreequeryresultsx(&s->tree, &s->calcbufx, _state); - kdtreequeryresultstags(&s->tree, &s->calcbuftags, _state); - for(i=0; i<=s->ny-1; i++) - { - for(j=0; j<=lx-1; j++) - { - tg = s->calcbuftags.ptr.p_int[j]; - rcur = s->wr.ptr.pp_double[tg][0]; - bf = ae_exp(-(ae_sqr(s->calcbufxcx.ptr.p_double[0]-s->calcbufx.ptr.pp_double[j][0], _state)+ae_sqr(s->calcbufxcx.ptr.p_double[1]-s->calcbufx.ptr.pp_double[j][1], _state)+ae_sqr(s->calcbufxcx.ptr.p_double[2]-s->calcbufx.ptr.pp_double[j][2], _state))/ae_sqr(rcur, _state), _state); - for(k=0; k<=s->nl-1; k++) - { - y->ptr.p_double[i] = y->ptr.p_double[i]+bf*s->wr.ptr.pp_double[tg][1+k*s->ny+i]; - t = bf*bf; - bf = t*t; - } - } - } -} - - -/************************************************************************* -This function calculates values of the RBF model at the given point, using -external buffer object (internal temporaries of RBF model are not -modified). - -This function allows to use same RBF model object in different threads, -assuming that different threads use different instances of buffer -structure. - -INPUT PARAMETERS: - S - RBF model, may be shared between different threads - Buf - buffer object created for this particular instance of RBF - model with rbfcreatecalcbuffer(). - X - coordinates, array[NX]. - X may have more than NX elements, in this case only - leading NX will be used. - Y - possibly preallocated array - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is not reallocated when it - is larger than NY. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfv1tscalcbuf(rbfv1model* s, - rbfv1calcbuffer* buf, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t lx; - ae_int_t tg; - double t; - double rcur; - double bf; - - - ae_assert(x->cnt>=s->nx, "RBFCalcBuf: Length(X)nx, _state), "RBFCalcBuf: X contains infinite or NaN values", _state); - if( y->cntny ) - { - ae_vector_set_length(y, s->ny, _state); - } - for(i=0; i<=s->ny-1; i++) - { - y->ptr.p_double[i] = s->v.ptr.pp_double[i][rbfv1_mxnx]; - for(j=0; j<=s->nx-1; j++) - { - y->ptr.p_double[i] = y->ptr.p_double[i]+s->v.ptr.pp_double[i][j]*x->ptr.p_double[j]; - } - } - if( s->nc==0 ) - { - return; - } - rvectorsetlengthatleast(&buf->calcbufxcx, rbfv1_mxnx, _state); - for(i=0; i<=rbfv1_mxnx-1; i++) - { - buf->calcbufxcx.ptr.p_double[i] = 0.0; - } - for(i=0; i<=s->nx-1; i++) - { - buf->calcbufxcx.ptr.p_double[i] = x->ptr.p_double[i]; - } - lx = kdtreetsqueryrnn(&s->tree, &buf->requestbuffer, &buf->calcbufxcx, s->rmax*rbfv1_rbffarradius, ae_true, _state); - kdtreetsqueryresultsx(&s->tree, &buf->requestbuffer, &buf->calcbufx, _state); - kdtreetsqueryresultstags(&s->tree, &buf->requestbuffer, &buf->calcbuftags, _state); - for(i=0; i<=s->ny-1; i++) - { - for(j=0; j<=lx-1; j++) - { - tg = buf->calcbuftags.ptr.p_int[j]; - rcur = s->wr.ptr.pp_double[tg][0]; - bf = ae_exp(-(ae_sqr(buf->calcbufxcx.ptr.p_double[0]-buf->calcbufx.ptr.pp_double[j][0], _state)+ae_sqr(buf->calcbufxcx.ptr.p_double[1]-buf->calcbufx.ptr.pp_double[j][1], _state)+ae_sqr(buf->calcbufxcx.ptr.p_double[2]-buf->calcbufx.ptr.pp_double[j][2], _state))/ae_sqr(rcur, _state), _state); - for(k=0; k<=s->nl-1; k++) - { - y->ptr.p_double[i] = y->ptr.p_double[i]+bf*s->wr.ptr.pp_double[tg][1+k*s->ny+i]; - t = bf*bf; - bf = t*t; - } - } - } -} - - -/************************************************************************* -This function calculates values of the RBF model at the regular grid. - -Grid have N0*N1 points, with Point[I,J] = (X0[I], X1[J]) - -This function returns 0.0 when: -* model is not initialized -* NX<>2 - *NY<>1 - -INPUT PARAMETERS: - S - RBF model - X0 - array of grid nodes, first coordinates, array[N0] - N0 - grid size (number of nodes) in the first dimension - X1 - array of grid nodes, second coordinates, array[N1] - N1 - grid size (number of nodes) in the second dimension - -OUTPUT PARAMETERS: - Y - function values, array[N0,N1]. Y is out-variable and - is reallocated by this function. - -NOTE: as a special exception, this function supports unordered arrays X0 - and X1. However, future versions may be more efficient for X0/X1 - ordered by ascending. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfv1gridcalc2(rbfv1model* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_matrix* y, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector cpx0; - ae_vector cpx1; - ae_vector p01; - ae_vector p11; - ae_vector p2; - double rlimit; - double xcnorm2; - ae_int_t hp01; - double hcpx0; - double xc0; - double xc1; - double omega; - double radius; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t d; - ae_int_t i00; - ae_int_t i01; - ae_int_t i10; - ae_int_t i11; - - ae_frame_make(_state, &_frame_block); - memset(&cpx0, 0, sizeof(cpx0)); - memset(&cpx1, 0, sizeof(cpx1)); - memset(&p01, 0, sizeof(p01)); - memset(&p11, 0, sizeof(p11)); - memset(&p2, 0, sizeof(p2)); - ae_matrix_clear(y); - ae_vector_init(&cpx0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cpx1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p01, 0, DT_INT, _state, ae_true); - ae_vector_init(&p11, 0, DT_INT, _state, ae_true); - ae_vector_init(&p2, 0, DT_INT, _state, ae_true); - - ae_assert(n0>0, "RBFGridCalc2: invalid value for N0 (N0<=0)!", _state); - ae_assert(n1>0, "RBFGridCalc2: invalid value for N1 (N1<=0)!", _state); - ae_assert(x0->cnt>=n0, "RBFGridCalc2: Length(X0)cnt>=n1, "RBFGridCalc2: Length(X1)ptr.pp_double[i][j] = (double)(0); - } - } - if( (s->ny!=1||s->nx!=2)||s->nc==0 ) - { - ae_frame_leave(_state); - return; - } - - /* - *create and sort arrays - */ - ae_vector_set_length(&cpx0, n0, _state); - for(i=0; i<=n0-1; i++) - { - cpx0.ptr.p_double[i] = x0->ptr.p_double[i]; - } - tagsort(&cpx0, n0, &p01, &p2, _state); - ae_vector_set_length(&cpx1, n1, _state); - for(i=0; i<=n1-1; i++) - { - cpx1.ptr.p_double[i] = x1->ptr.p_double[i]; - } - tagsort(&cpx1, n1, &p11, &p2, _state); - - /* - *calculate function's value - */ - for(i=0; i<=s->nc-1; i++) - { - radius = s->wr.ptr.pp_double[i][0]; - for(d=0; d<=s->nl-1; d++) - { - omega = s->wr.ptr.pp_double[i][1+d]; - rlimit = radius*rbfv1_rbffarradius; - - /* - *search lower and upper indexes - */ - i00 = lowerbound(&cpx0, n0, s->xc.ptr.pp_double[i][0]-rlimit, _state); - i01 = upperbound(&cpx0, n0, s->xc.ptr.pp_double[i][0]+rlimit, _state); - i10 = lowerbound(&cpx1, n1, s->xc.ptr.pp_double[i][1]-rlimit, _state); - i11 = upperbound(&cpx1, n1, s->xc.ptr.pp_double[i][1]+rlimit, _state); - xc0 = s->xc.ptr.pp_double[i][0]; - xc1 = s->xc.ptr.pp_double[i][1]; - for(j=i00; j<=i01-1; j++) - { - hcpx0 = cpx0.ptr.p_double[j]; - hp01 = p01.ptr.p_int[j]; - for(k=i10; k<=i11-1; k++) - { - xcnorm2 = ae_sqr(hcpx0-xc0, _state)+ae_sqr(cpx1.ptr.p_double[k]-xc1, _state); - if( ae_fp_less_eq(xcnorm2,rlimit*rlimit) ) - { - y->ptr.pp_double[hp01][p11.ptr.p_int[k]] = y->ptr.pp_double[hp01][p11.ptr.p_int[k]]+ae_exp(-xcnorm2/ae_sqr(radius, _state), _state)*omega; - } - } - } - radius = 0.5*radius; - } - } - - /* - *add linear term - */ - for(i=0; i<=n0-1; i++) - { - for(j=0; j<=n1-1; j++) - { - y->ptr.pp_double[i][j] = y->ptr.pp_double[i][j]+s->v.ptr.pp_double[0][0]*x0->ptr.p_double[i]+s->v.ptr.pp_double[0][1]*x1->ptr.p_double[j]+s->v.ptr.pp_double[0][rbfv1_mxnx]; - } - } - ae_frame_leave(_state); -} - - -void rbfv1gridcalc3vrec(rbfv1model* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Integer */ ae_vector* blocks0, - ae_int_t block0a, - ae_int_t block0b, - /* Integer */ ae_vector* blocks1, - ae_int_t block1a, - ae_int_t block1b, - /* Integer */ ae_vector* blocks2, - ae_int_t block2a, - ae_int_t block2b, - /* Boolean */ ae_vector* flagy, - ae_bool sparsey, - double searchradius, - double avgfuncpernode, - ae_shared_pool* bufpool, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t t; - ae_int_t l; - ae_int_t i0; - ae_int_t i1; - ae_int_t i2; - ae_int_t ic; - gridcalc3v1buf *pbuf; - ae_smart_ptr _pbuf; - ae_int_t flag12dim1; - ae_int_t flag12dim2; - double problemcost; - ae_int_t maxbs; - ae_int_t nx; - ae_int_t ny; - double v; - ae_int_t kc; - ae_int_t tg; - double rcur; - double rcur2; - double basisfuncval; - ae_int_t dstoffs; - ae_int_t srcoffs; - ae_int_t ubnd; - double w0; - double w1; - double w2; - ae_bool allnodes; - ae_bool somenodes; - - ae_frame_make(_state, &_frame_block); - memset(&_pbuf, 0, sizeof(_pbuf)); - ae_smart_ptr_init(&_pbuf, (void**)&pbuf, _state, ae_true); - - nx = s->nx; - ny = s->ny; - - /* - * Try to split large problem - */ - problemcost = (s->nl+1)*s->ny*2*(avgfuncpernode+1); - problemcost = problemcost*(blocks0->ptr.p_int[block0b]-blocks0->ptr.p_int[block0a]); - problemcost = problemcost*(blocks1->ptr.p_int[block1b]-blocks1->ptr.p_int[block1a]); - problemcost = problemcost*(blocks2->ptr.p_int[block2b]-blocks2->ptr.p_int[block2a]); - maxbs = 0; - maxbs = ae_maxint(maxbs, block0b-block0a, _state); - maxbs = ae_maxint(maxbs, block1b-block1a, _state); - maxbs = ae_maxint(maxbs, block2b-block2a, _state); - if( ae_fp_greater_eq(problemcost,rbfv1_minbasecasecost)&&maxbs>=2 ) - { - if( block0b-block0a==maxbs ) - { - rbfv1gridcalc3vrec(s, x0, n0, x1, n1, x2, n2, blocks0, block0a, block0a+maxbs/2, blocks1, block1a, block1b, blocks2, block2a, block2b, flagy, sparsey, searchradius, avgfuncpernode, bufpool, y, _state); - rbfv1gridcalc3vrec(s, x0, n0, x1, n1, x2, n2, blocks0, block0a+maxbs/2, block0b, blocks1, block1a, block1b, blocks2, block2a, block2b, flagy, sparsey, searchradius, avgfuncpernode, bufpool, y, _state); - ae_frame_leave(_state); - return; - } - if( block1b-block1a==maxbs ) - { - rbfv1gridcalc3vrec(s, x0, n0, x1, n1, x2, n2, blocks0, block0a, block0b, blocks1, block1a, block1a+maxbs/2, blocks2, block2a, block2b, flagy, sparsey, searchradius, avgfuncpernode, bufpool, y, _state); - rbfv1gridcalc3vrec(s, x0, n0, x1, n1, x2, n2, blocks0, block0a, block0b, blocks1, block1a+maxbs/2, block1b, blocks2, block2a, block2b, flagy, sparsey, searchradius, avgfuncpernode, bufpool, y, _state); - ae_frame_leave(_state); - return; - } - if( block2b-block2a==maxbs ) - { - rbfv1gridcalc3vrec(s, x0, n0, x1, n1, x2, n2, blocks0, block0a, block0b, blocks1, block1a, block1b, blocks2, block2a, block2a+maxbs/2, flagy, sparsey, searchradius, avgfuncpernode, bufpool, y, _state); - rbfv1gridcalc3vrec(s, x0, n0, x1, n1, x2, n2, blocks0, block0a, block0b, blocks1, block1a, block1b, blocks2, block2a+maxbs/2, block2b, flagy, sparsey, searchradius, avgfuncpernode, bufpool, y, _state); - ae_frame_leave(_state); - return; - } - } - - /* - * Retrieve buffer object from pool (it will be returned later) - */ - ae_shared_pool_retrieve(bufpool, &_pbuf, _state); - - /* - * Calculate RBF model - */ - for(i2=block2a; i2<=block2b-1; i2++) - { - for(i1=block1a; i1<=block1b-1; i1++) - { - for(i0=block0a; i0<=block0b-1; i0++) - { - - /* - * Analyze block - determine what elements are needed and what are not. - * - * After this block is done, two flag variables can be used: - * * SomeNodes, which is True when there are at least one node which have - * to be calculated - * * AllNodes, which is True when all nodes are required - */ - somenodes = ae_true; - allnodes = ae_true; - flag12dim1 = blocks1->ptr.p_int[i1+1]-blocks1->ptr.p_int[i1]; - flag12dim2 = blocks2->ptr.p_int[i2+1]-blocks2->ptr.p_int[i2]; - if( sparsey ) - { - - /* - * Use FlagY to determine what is required. - */ - bvectorsetlengthatleast(&pbuf->flag0, n0, _state); - bvectorsetlengthatleast(&pbuf->flag1, n1, _state); - bvectorsetlengthatleast(&pbuf->flag2, n2, _state); - bvectorsetlengthatleast(&pbuf->flag12, flag12dim1*flag12dim2, _state); - for(i=blocks0->ptr.p_int[i0]; i<=blocks0->ptr.p_int[i0+1]-1; i++) - { - pbuf->flag0.ptr.p_bool[i] = ae_false; - } - for(j=blocks1->ptr.p_int[i1]; j<=blocks1->ptr.p_int[i1+1]-1; j++) - { - pbuf->flag1.ptr.p_bool[j] = ae_false; - } - for(k=blocks2->ptr.p_int[i2]; k<=blocks2->ptr.p_int[i2+1]-1; k++) - { - pbuf->flag2.ptr.p_bool[k] = ae_false; - } - for(i=0; i<=flag12dim1*flag12dim2-1; i++) - { - pbuf->flag12.ptr.p_bool[i] = ae_false; - } - somenodes = ae_false; - allnodes = ae_true; - for(k=blocks2->ptr.p_int[i2]; k<=blocks2->ptr.p_int[i2+1]-1; k++) - { - for(j=blocks1->ptr.p_int[i1]; j<=blocks1->ptr.p_int[i1+1]-1; j++) - { - dstoffs = j-blocks1->ptr.p_int[i1]+flag12dim1*(k-blocks2->ptr.p_int[i2]); - srcoffs = j*n0+k*n0*n1; - for(i=blocks0->ptr.p_int[i0]; i<=blocks0->ptr.p_int[i0+1]-1; i++) - { - if( flagy->ptr.p_bool[srcoffs+i] ) - { - pbuf->flag0.ptr.p_bool[i] = ae_true; - pbuf->flag1.ptr.p_bool[j] = ae_true; - pbuf->flag2.ptr.p_bool[k] = ae_true; - pbuf->flag12.ptr.p_bool[dstoffs] = ae_true; - somenodes = ae_true; - } - else - { - allnodes = ae_false; - } - } - } - } - } - - /* - * Skip block if it is completely empty. - */ - if( !somenodes ) - { - continue; - } - - /* - * compute linear term for block (I0,I1,I2) - */ - for(k=blocks2->ptr.p_int[i2]; k<=blocks2->ptr.p_int[i2+1]-1; k++) - { - for(j=blocks1->ptr.p_int[i1]; j<=blocks1->ptr.p_int[i1+1]-1; j++) - { - - /* - * do we need this micro-row? - */ - if( !allnodes&&!pbuf->flag12.ptr.p_bool[j-blocks1->ptr.p_int[i1]+flag12dim1*(k-blocks2->ptr.p_int[i2])] ) - { - continue; - } - - /* - * Compute linear term - */ - for(i=blocks0->ptr.p_int[i0]; i<=blocks0->ptr.p_int[i0+1]-1; i++) - { - pbuf->tx.ptr.p_double[0] = x0->ptr.p_double[i]; - pbuf->tx.ptr.p_double[1] = x1->ptr.p_double[j]; - pbuf->tx.ptr.p_double[2] = x2->ptr.p_double[k]; - for(l=0; l<=s->ny-1; l++) - { - v = s->v.ptr.pp_double[l][rbfv1_mxnx]; - for(t=0; t<=nx-1; t++) - { - v = v+s->v.ptr.pp_double[l][t]*pbuf->tx.ptr.p_double[t]; - } - y->ptr.p_double[l+ny*(i+j*n0+k*n0*n1)] = v; - } - } - } - } - - /* - * compute RBF term for block (I0,I1,I2) - */ - pbuf->tx.ptr.p_double[0] = 0.5*(x0->ptr.p_double[blocks0->ptr.p_int[i0]]+x0->ptr.p_double[blocks0->ptr.p_int[i0+1]-1]); - pbuf->tx.ptr.p_double[1] = 0.5*(x1->ptr.p_double[blocks1->ptr.p_int[i1]]+x1->ptr.p_double[blocks1->ptr.p_int[i1+1]-1]); - pbuf->tx.ptr.p_double[2] = 0.5*(x2->ptr.p_double[blocks2->ptr.p_int[i2]]+x2->ptr.p_double[blocks2->ptr.p_int[i2+1]-1]); - kc = kdtreetsqueryrnn(&s->tree, &pbuf->requestbuf, &pbuf->tx, searchradius, ae_true, _state); - kdtreetsqueryresultsx(&s->tree, &pbuf->requestbuf, &pbuf->calcbufx, _state); - kdtreetsqueryresultstags(&s->tree, &pbuf->requestbuf, &pbuf->calcbuftags, _state); - for(ic=0; ic<=kc-1; ic++) - { - pbuf->cx.ptr.p_double[0] = pbuf->calcbufx.ptr.pp_double[ic][0]; - pbuf->cx.ptr.p_double[1] = pbuf->calcbufx.ptr.pp_double[ic][1]; - pbuf->cx.ptr.p_double[2] = pbuf->calcbufx.ptr.pp_double[ic][2]; - tg = pbuf->calcbuftags.ptr.p_int[ic]; - rcur = s->wr.ptr.pp_double[tg][0]; - rcur2 = rcur*rcur; - for(i=blocks0->ptr.p_int[i0]; i<=blocks0->ptr.p_int[i0+1]-1; i++) - { - if( allnodes||pbuf->flag0.ptr.p_bool[i] ) - { - pbuf->expbuf0.ptr.p_double[i] = ae_exp(-ae_sqr(x0->ptr.p_double[i]-pbuf->cx.ptr.p_double[0], _state)/rcur2, _state); - } - else - { - pbuf->expbuf0.ptr.p_double[i] = 0.0; - } - } - for(j=blocks1->ptr.p_int[i1]; j<=blocks1->ptr.p_int[i1+1]-1; j++) - { - if( allnodes||pbuf->flag1.ptr.p_bool[j] ) - { - pbuf->expbuf1.ptr.p_double[j] = ae_exp(-ae_sqr(x1->ptr.p_double[j]-pbuf->cx.ptr.p_double[1], _state)/rcur2, _state); - } - else - { - pbuf->expbuf1.ptr.p_double[j] = 0.0; - } - } - for(k=blocks2->ptr.p_int[i2]; k<=blocks2->ptr.p_int[i2+1]-1; k++) - { - if( allnodes||pbuf->flag2.ptr.p_bool[k] ) - { - pbuf->expbuf2.ptr.p_double[k] = ae_exp(-ae_sqr(x2->ptr.p_double[k]-pbuf->cx.ptr.p_double[2], _state)/rcur2, _state); - } - else - { - pbuf->expbuf2.ptr.p_double[k] = 0.0; - } - } - for(t=0; t<=s->nl-1; t++) - { - - /* - * Calculate - */ - for(k=blocks2->ptr.p_int[i2]; k<=blocks2->ptr.p_int[i2+1]-1; k++) - { - for(j=blocks1->ptr.p_int[i1]; j<=blocks1->ptr.p_int[i1+1]-1; j++) - { - - /* - * do we need this micro-row? - */ - if( !allnodes&&!pbuf->flag12.ptr.p_bool[j-blocks1->ptr.p_int[i1]+flag12dim1*(k-blocks2->ptr.p_int[i2])] ) - { - continue; - } - - /* - * Prepare local variables - */ - dstoffs = ny*(blocks0->ptr.p_int[i0]+j*n0+k*n0*n1); - v = pbuf->expbuf1.ptr.p_double[j]*pbuf->expbuf2.ptr.p_double[k]; - - /* - * Optimized for NY=1 - */ - if( s->ny==1 ) - { - w0 = s->wr.ptr.pp_double[tg][1+t*s->ny+0]; - ubnd = blocks0->ptr.p_int[i0+1]-1; - for(i=blocks0->ptr.p_int[i0]; i<=ubnd; i++) - { - basisfuncval = pbuf->expbuf0.ptr.p_double[i]*v; - y->ptr.p_double[dstoffs] = y->ptr.p_double[dstoffs]+basisfuncval*w0; - dstoffs = dstoffs+1; - } - continue; - } - - /* - * Optimized for NY=2 - */ - if( s->ny==2 ) - { - w0 = s->wr.ptr.pp_double[tg][1+t*s->ny+0]; - w1 = s->wr.ptr.pp_double[tg][1+t*s->ny+1]; - ubnd = blocks0->ptr.p_int[i0+1]-1; - for(i=blocks0->ptr.p_int[i0]; i<=ubnd; i++) - { - basisfuncval = pbuf->expbuf0.ptr.p_double[i]*v; - y->ptr.p_double[dstoffs+0] = y->ptr.p_double[dstoffs+0]+basisfuncval*w0; - y->ptr.p_double[dstoffs+1] = y->ptr.p_double[dstoffs+1]+basisfuncval*w1; - dstoffs = dstoffs+2; - } - continue; - } - - /* - * Optimized for NY=3 - */ - if( s->ny==3 ) - { - w0 = s->wr.ptr.pp_double[tg][1+t*s->ny+0]; - w1 = s->wr.ptr.pp_double[tg][1+t*s->ny+1]; - w2 = s->wr.ptr.pp_double[tg][1+t*s->ny+2]; - ubnd = blocks0->ptr.p_int[i0+1]-1; - for(i=blocks0->ptr.p_int[i0]; i<=ubnd; i++) - { - basisfuncval = pbuf->expbuf0.ptr.p_double[i]*v; - y->ptr.p_double[dstoffs+0] = y->ptr.p_double[dstoffs+0]+basisfuncval*w0; - y->ptr.p_double[dstoffs+1] = y->ptr.p_double[dstoffs+1]+basisfuncval*w1; - y->ptr.p_double[dstoffs+2] = y->ptr.p_double[dstoffs+2]+basisfuncval*w2; - dstoffs = dstoffs+3; - } - continue; - } - - /* - * General case - */ - for(i=blocks0->ptr.p_int[i0]; i<=blocks0->ptr.p_int[i0+1]-1; i++) - { - basisfuncval = pbuf->expbuf0.ptr.p_double[i]*v; - for(l=0; l<=s->ny-1; l++) - { - y->ptr.p_double[l+dstoffs] = y->ptr.p_double[l+dstoffs]+basisfuncval*s->wr.ptr.pp_double[tg][1+t*s->ny+l]; - } - dstoffs = dstoffs+ny; - } - } - } - - /* - * Update basis functions - */ - if( t!=s->nl-1 ) - { - ubnd = blocks0->ptr.p_int[i0+1]-1; - for(i=blocks0->ptr.p_int[i0]; i<=ubnd; i++) - { - if( allnodes||pbuf->flag0.ptr.p_bool[i] ) - { - v = pbuf->expbuf0.ptr.p_double[i]*pbuf->expbuf0.ptr.p_double[i]; - pbuf->expbuf0.ptr.p_double[i] = v*v; - } - } - ubnd = blocks1->ptr.p_int[i1+1]-1; - for(j=blocks1->ptr.p_int[i1]; j<=ubnd; j++) - { - if( allnodes||pbuf->flag1.ptr.p_bool[j] ) - { - v = pbuf->expbuf1.ptr.p_double[j]*pbuf->expbuf1.ptr.p_double[j]; - pbuf->expbuf1.ptr.p_double[j] = v*v; - } - } - ubnd = blocks2->ptr.p_int[i2+1]-1; - for(k=blocks2->ptr.p_int[i2]; k<=ubnd; k++) - { - if( allnodes||pbuf->flag2.ptr.p_bool[k] ) - { - v = pbuf->expbuf2.ptr.p_double[k]*pbuf->expbuf2.ptr.p_double[k]; - pbuf->expbuf2.ptr.p_double[k] = v*v; - } - } - } - } - } - } - } - } - - /* - * Recycle buffer object back to pool - */ - ae_shared_pool_recycle(bufpool, &_pbuf, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_rbfv1gridcalc3vrec(rbfv1model* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Integer */ ae_vector* blocks0, - ae_int_t block0a, - ae_int_t block0b, - /* Integer */ ae_vector* blocks1, - ae_int_t block1a, - ae_int_t block1b, - /* Integer */ ae_vector* blocks2, - ae_int_t block2a, - ae_int_t block2b, - /* Boolean */ ae_vector* flagy, - ae_bool sparsey, - double searchradius, - double avgfuncpernode, - ae_shared_pool* bufpool, - /* Real */ ae_vector* y, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -This function "unpacks" RBF model by extracting its coefficients. - -INPUT PARAMETERS: - S - RBF model - -OUTPUT PARAMETERS: - NX - dimensionality of argument - NY - dimensionality of the target function - XWR - model information, array[NC,NX+NY+1]. - One row of the array corresponds to one basis function: - * first NX columns - coordinates of the center - * next NY columns - weights, one per dimension of the - function being modelled - * last column - radius, same for all dimensions of - the function being modelled - NC - number of the centers - V - polynomial term , array[NY,NX+1]. One row per one - dimension of the function being modelled. First NX - elements are linear coefficients, V[NX] is equal to the - constant part. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfv1unpack(rbfv1model* s, - ae_int_t* nx, - ae_int_t* ny, - /* Real */ ae_matrix* xwr, - ae_int_t* nc, - /* Real */ ae_matrix* v, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double rcur; - - *nx = 0; - *ny = 0; - ae_matrix_clear(xwr); - *nc = 0; - ae_matrix_clear(v); - - *nx = s->nx; - *ny = s->ny; - *nc = s->nc; - - /* - * Fill V - */ - ae_matrix_set_length(v, s->ny, s->nx+1, _state); - for(i=0; i<=s->ny-1; i++) - { - ae_v_move(&v->ptr.pp_double[i][0], 1, &s->v.ptr.pp_double[i][0], 1, ae_v_len(0,s->nx-1)); - v->ptr.pp_double[i][s->nx] = s->v.ptr.pp_double[i][rbfv1_mxnx]; - } - - /* - * Fill XWR and V - */ - if( *nc*s->nl>0 ) - { - ae_matrix_set_length(xwr, s->nc*s->nl, s->nx+s->ny+1, _state); - for(i=0; i<=s->nc-1; i++) - { - rcur = s->wr.ptr.pp_double[i][0]; - for(j=0; j<=s->nl-1; j++) - { - ae_v_move(&xwr->ptr.pp_double[i*s->nl+j][0], 1, &s->xc.ptr.pp_double[i][0], 1, ae_v_len(0,s->nx-1)); - ae_v_move(&xwr->ptr.pp_double[i*s->nl+j][s->nx], 1, &s->wr.ptr.pp_double[i][1+j*s->ny], 1, ae_v_len(s->nx,s->nx+s->ny-1)); - xwr->ptr.pp_double[i*s->nl+j][s->nx+s->ny] = rcur; - rcur = 0.5*rcur; - } - } - } -} - - -static ae_bool rbfv1_rbfv1buildlinearmodel(/* Real */ ae_matrix* x, - /* Real */ ae_matrix* y, - ae_int_t n, - ae_int_t ny, - ae_int_t modeltype, - /* Real */ ae_matrix* v, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector tmpy; - ae_matrix a; - double scaling; - ae_vector shifting; - double mn; - double mx; - ae_vector c; - lsfitreport rep; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t info; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&tmpy, 0, sizeof(tmpy)); - memset(&a, 0, sizeof(a)); - memset(&shifting, 0, sizeof(shifting)); - memset(&c, 0, sizeof(c)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_clear(v); - ae_vector_init(&tmpy, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&shifting, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c, 0, DT_REAL, _state, ae_true); - _lsfitreport_init(&rep, _state, ae_true); - - ae_assert(n>=0, "BuildLinearModel: N<0", _state); - ae_assert(ny>0, "BuildLinearModel: NY<=0", _state); - - /* - * Handle degenerate case (N=0) - */ - result = ae_true; - ae_matrix_set_length(v, ny, rbfv1_mxnx+1, _state); - if( n==0 ) - { - for(j=0; j<=rbfv1_mxnx; j++) - { - for(i=0; i<=ny-1; i++) - { - v->ptr.pp_double[i][j] = (double)(0); - } - } - ae_frame_leave(_state); - return result; - } - - /* - * Allocate temporaries - */ - ae_vector_set_length(&tmpy, n, _state); - - /* - * General linear model. - */ - if( modeltype==1 ) - { - - /* - * Calculate scaling/shifting, transform variables, prepare LLS problem - */ - ae_matrix_set_length(&a, n, rbfv1_mxnx+1, _state); - ae_vector_set_length(&shifting, rbfv1_mxnx, _state); - scaling = (double)(0); - for(i=0; i<=rbfv1_mxnx-1; i++) - { - mn = x->ptr.pp_double[0][i]; - mx = mn; - for(j=1; j<=n-1; j++) - { - if( ae_fp_greater(mn,x->ptr.pp_double[j][i]) ) - { - mn = x->ptr.pp_double[j][i]; - } - if( ae_fp_less(mx,x->ptr.pp_double[j][i]) ) - { - mx = x->ptr.pp_double[j][i]; - } - } - scaling = ae_maxreal(scaling, mx-mn, _state); - shifting.ptr.p_double[i] = 0.5*(mx+mn); - } - if( ae_fp_eq(scaling,(double)(0)) ) - { - scaling = (double)(1); - } - else - { - scaling = 0.5*scaling; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=rbfv1_mxnx-1; j++) - { - a.ptr.pp_double[i][j] = (x->ptr.pp_double[i][j]-shifting.ptr.p_double[j])/scaling; - } - } - for(i=0; i<=n-1; i++) - { - a.ptr.pp_double[i][rbfv1_mxnx] = (double)(1); - } - - /* - * Solve linear system in transformed variables, make backward - */ - for(i=0; i<=ny-1; i++) - { - for(j=0; j<=n-1; j++) - { - tmpy.ptr.p_double[j] = y->ptr.pp_double[j][i]; - } - lsfitlinear(&tmpy, &a, n, rbfv1_mxnx+1, &info, &c, &rep, _state); - if( info<=0 ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - for(j=0; j<=rbfv1_mxnx-1; j++) - { - v->ptr.pp_double[i][j] = c.ptr.p_double[j]/scaling; - } - v->ptr.pp_double[i][rbfv1_mxnx] = c.ptr.p_double[rbfv1_mxnx]; - for(j=0; j<=rbfv1_mxnx-1; j++) - { - v->ptr.pp_double[i][rbfv1_mxnx] = v->ptr.pp_double[i][rbfv1_mxnx]-shifting.ptr.p_double[j]*v->ptr.pp_double[i][j]; - } - for(j=0; j<=n-1; j++) - { - for(k=0; k<=rbfv1_mxnx-1; k++) - { - y->ptr.pp_double[j][i] = y->ptr.pp_double[j][i]-x->ptr.pp_double[j][k]*v->ptr.pp_double[i][k]; - } - y->ptr.pp_double[j][i] = y->ptr.pp_double[j][i]-v->ptr.pp_double[i][rbfv1_mxnx]; - } - } - ae_frame_leave(_state); - return result; - } - - /* - * Constant model, very simple - */ - if( modeltype==2 ) - { - for(i=0; i<=ny-1; i++) - { - for(j=0; j<=rbfv1_mxnx; j++) - { - v->ptr.pp_double[i][j] = (double)(0); - } - for(j=0; j<=n-1; j++) - { - v->ptr.pp_double[i][rbfv1_mxnx] = v->ptr.pp_double[i][rbfv1_mxnx]+y->ptr.pp_double[j][i]; - } - if( n>0 ) - { - v->ptr.pp_double[i][rbfv1_mxnx] = v->ptr.pp_double[i][rbfv1_mxnx]/n; - } - for(j=0; j<=n-1; j++) - { - y->ptr.pp_double[j][i] = y->ptr.pp_double[j][i]-v->ptr.pp_double[i][rbfv1_mxnx]; - } - } - ae_frame_leave(_state); - return result; - } - - /* - * Zero model - */ - ae_assert(modeltype==3, "BuildLinearModel: unknown model type", _state); - for(i=0; i<=ny-1; i++) - { - for(j=0; j<=rbfv1_mxnx; j++) - { - v->ptr.pp_double[i][j] = (double)(0); - } - } - ae_frame_leave(_state); - return result; -} - - -static void rbfv1_buildrbfmodellsqr(/* Real */ ae_matrix* x, - /* Real */ ae_matrix* y, - /* Real */ ae_matrix* xc, - /* Real */ ae_vector* r, - ae_int_t n, - ae_int_t nc, - ae_int_t ny, - kdtree* pointstree, - kdtree* centerstree, - double epsort, - double epserr, - ae_int_t maxits, - ae_int_t* gnnz, - ae_int_t* snnz, - /* Real */ ae_matrix* w, - ae_int_t* info, - ae_int_t* iterationscount, - ae_int_t* nmv, - ae_state *_state) -{ - ae_frame _frame_block; - linlsqrstate state; - linlsqrreport lsqrrep; - sparsematrix spg; - sparsematrix sps; - ae_vector nearcenterscnt; - ae_vector nearpointscnt; - ae_vector skipnearpointscnt; - ae_vector farpointscnt; - ae_int_t maxnearcenterscnt; - ae_int_t maxnearpointscnt; - ae_int_t maxfarpointscnt; - ae_int_t sumnearcenterscnt; - ae_int_t sumnearpointscnt; - ae_int_t sumfarpointscnt; - double maxrad; - ae_vector pointstags; - ae_vector centerstags; - ae_matrix nearpoints; - ae_matrix nearcenters; - ae_matrix farpoints; - ae_int_t tmpi; - ae_int_t pointscnt; - ae_int_t centerscnt; - ae_vector xcx; - ae_vector tmpy; - ae_vector tc; - ae_vector g; - ae_vector c; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t sind; - ae_matrix a; - double vv; - double vx; - double vy; - double vz; - double vr; - double gnorm2; - ae_vector tmp0; - ae_vector tmp1; - ae_vector tmp2; - double fx; - ae_matrix xx; - ae_matrix cx; - double mrad; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&lsqrrep, 0, sizeof(lsqrrep)); - memset(&spg, 0, sizeof(spg)); - memset(&sps, 0, sizeof(sps)); - memset(&nearcenterscnt, 0, sizeof(nearcenterscnt)); - memset(&nearpointscnt, 0, sizeof(nearpointscnt)); - memset(&skipnearpointscnt, 0, sizeof(skipnearpointscnt)); - memset(&farpointscnt, 0, sizeof(farpointscnt)); - memset(&pointstags, 0, sizeof(pointstags)); - memset(¢erstags, 0, sizeof(centerstags)); - memset(&nearpoints, 0, sizeof(nearpoints)); - memset(&nearcenters, 0, sizeof(nearcenters)); - memset(&farpoints, 0, sizeof(farpoints)); - memset(&xcx, 0, sizeof(xcx)); - memset(&tmpy, 0, sizeof(tmpy)); - memset(&tc, 0, sizeof(tc)); - memset(&g, 0, sizeof(g)); - memset(&c, 0, sizeof(c)); - memset(&a, 0, sizeof(a)); - memset(&tmp0, 0, sizeof(tmp0)); - memset(&tmp1, 0, sizeof(tmp1)); - memset(&tmp2, 0, sizeof(tmp2)); - memset(&xx, 0, sizeof(xx)); - memset(&cx, 0, sizeof(cx)); - *gnnz = 0; - *snnz = 0; - ae_matrix_clear(w); - *info = 0; - *iterationscount = 0; - *nmv = 0; - _linlsqrstate_init(&state, _state, ae_true); - _linlsqrreport_init(&lsqrrep, _state, ae_true); - _sparsematrix_init(&spg, _state, ae_true); - _sparsematrix_init(&sps, _state, ae_true); - ae_vector_init(&nearcenterscnt, 0, DT_INT, _state, ae_true); - ae_vector_init(&nearpointscnt, 0, DT_INT, _state, ae_true); - ae_vector_init(&skipnearpointscnt, 0, DT_INT, _state, ae_true); - ae_vector_init(&farpointscnt, 0, DT_INT, _state, ae_true); - ae_vector_init(&pointstags, 0, DT_INT, _state, ae_true); - ae_vector_init(¢erstags, 0, DT_INT, _state, ae_true); - ae_matrix_init(&nearpoints, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&nearcenters, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&farpoints, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xcx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpy, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&g, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp2, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xx, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&cx, 0, 0, DT_REAL, _state, ae_true); - - - /* - * Handle special cases: NC=0 - */ - if( nc==0 ) - { - *info = 1; - *iterationscount = 0; - *nmv = 0; - ae_frame_leave(_state); - return; - } - - /* - * Prepare for general case, NC>0 - */ - ae_vector_set_length(&xcx, rbfv1_mxnx, _state); - ae_vector_set_length(&pointstags, n, _state); - ae_vector_set_length(¢erstags, nc, _state); - *info = -1; - *iterationscount = 0; - *nmv = 0; - - /* - * This block prepares quantities used to compute approximate cardinal basis functions (ACBFs): - * * NearCentersCnt[] - array[NC], whose elements store number of near centers used to build ACBF - * * NearPointsCnt[] - array[NC], number of near points used to build ACBF - * * FarPointsCnt[] - array[NC], number of far points (ones where ACBF is nonzero) - * * MaxNearCentersCnt - max(NearCentersCnt) - * * MaxNearPointsCnt - max(NearPointsCnt) - * * SumNearCentersCnt - sum(NearCentersCnt) - * * SumNearPointsCnt - sum(NearPointsCnt) - * * SumFarPointsCnt - sum(FarPointsCnt) - */ - ae_vector_set_length(&nearcenterscnt, nc, _state); - ae_vector_set_length(&nearpointscnt, nc, _state); - ae_vector_set_length(&skipnearpointscnt, nc, _state); - ae_vector_set_length(&farpointscnt, nc, _state); - maxnearcenterscnt = 0; - maxnearpointscnt = 0; - maxfarpointscnt = 0; - sumnearcenterscnt = 0; - sumnearpointscnt = 0; - sumfarpointscnt = 0; - for(i=0; i<=nc-1; i++) - { - for(j=0; j<=rbfv1_mxnx-1; j++) - { - xcx.ptr.p_double[j] = xc->ptr.pp_double[i][j]; - } - - /* - * Determine number of near centers and maximum radius of near centers - */ - nearcenterscnt.ptr.p_int[i] = kdtreequeryrnn(centerstree, &xcx, r->ptr.p_double[i]*rbfv1_rbfnearradius, ae_true, _state); - kdtreequeryresultstags(centerstree, ¢erstags, _state); - maxrad = (double)(0); - for(j=0; j<=nearcenterscnt.ptr.p_int[i]-1; j++) - { - maxrad = ae_maxreal(maxrad, ae_fabs(r->ptr.p_double[centerstags.ptr.p_int[j]], _state), _state); - } - - /* - * Determine number of near points (ones which used to build ACBF) - * and skipped points (the most near points which are NOT used to build ACBF - * and are NOT included in the near points count - */ - skipnearpointscnt.ptr.p_int[i] = kdtreequeryrnn(pointstree, &xcx, 0.1*r->ptr.p_double[i], ae_true, _state); - nearpointscnt.ptr.p_int[i] = kdtreequeryrnn(pointstree, &xcx, (r->ptr.p_double[i]+maxrad)*rbfv1_rbfnearradius, ae_true, _state)-skipnearpointscnt.ptr.p_int[i]; - ae_assert(nearpointscnt.ptr.p_int[i]>=0, "BuildRBFModelLSQR: internal error", _state); - - /* - * Determine number of far points - */ - farpointscnt.ptr.p_int[i] = kdtreequeryrnn(pointstree, &xcx, ae_maxreal(r->ptr.p_double[i]*rbfv1_rbfnearradius+maxrad*rbfv1_rbffarradius, r->ptr.p_double[i]*rbfv1_rbffarradius, _state), ae_true, _state); - - /* - * calculate sum and max, make some basic checks - */ - ae_assert(nearcenterscnt.ptr.p_int[i]>0, "BuildRBFModelLSQR: internal error", _state); - maxnearcenterscnt = ae_maxint(maxnearcenterscnt, nearcenterscnt.ptr.p_int[i], _state); - maxnearpointscnt = ae_maxint(maxnearpointscnt, nearpointscnt.ptr.p_int[i], _state); - maxfarpointscnt = ae_maxint(maxfarpointscnt, farpointscnt.ptr.p_int[i], _state); - sumnearcenterscnt = sumnearcenterscnt+nearcenterscnt.ptr.p_int[i]; - sumnearpointscnt = sumnearpointscnt+nearpointscnt.ptr.p_int[i]; - sumfarpointscnt = sumfarpointscnt+farpointscnt.ptr.p_int[i]; - } - *snnz = sumnearcenterscnt; - *gnnz = sumfarpointscnt; - ae_assert(maxnearcenterscnt>0, "BuildRBFModelLSQR: internal error", _state); - - /* - * Allocate temporaries. - * - * NOTE: we want to avoid allocation of zero-size arrays, so we - * use max(desired_size,1) instead of desired_size when performing - * memory allocation. - */ - ae_matrix_set_length(&a, maxnearpointscnt+maxnearcenterscnt, maxnearcenterscnt, _state); - ae_vector_set_length(&tmpy, maxnearpointscnt+maxnearcenterscnt, _state); - ae_vector_set_length(&g, maxnearcenterscnt, _state); - ae_vector_set_length(&c, maxnearcenterscnt, _state); - ae_matrix_set_length(&nearcenters, maxnearcenterscnt, rbfv1_mxnx, _state); - ae_matrix_set_length(&nearpoints, ae_maxint(maxnearpointscnt, 1, _state), rbfv1_mxnx, _state); - ae_matrix_set_length(&farpoints, ae_maxint(maxfarpointscnt, 1, _state), rbfv1_mxnx, _state); - - /* - * fill matrix SpG - */ - sparsecreate(n, nc, *gnnz, &spg, _state); - sparsecreate(nc, nc, *snnz, &sps, _state); - for(i=0; i<=nc-1; i++) - { - centerscnt = nearcenterscnt.ptr.p_int[i]; - - /* - * main center - */ - for(j=0; j<=rbfv1_mxnx-1; j++) - { - xcx.ptr.p_double[j] = xc->ptr.pp_double[i][j]; - } - - /* - * center's tree - */ - tmpi = kdtreequeryknn(centerstree, &xcx, centerscnt, ae_true, _state); - ae_assert(tmpi==centerscnt, "BuildRBFModelLSQR: internal error", _state); - kdtreequeryresultsx(centerstree, &cx, _state); - kdtreequeryresultstags(centerstree, ¢erstags, _state); - - /* - * point's tree - */ - mrad = (double)(0); - for(j=0; j<=centerscnt-1; j++) - { - mrad = ae_maxreal(mrad, r->ptr.p_double[centerstags.ptr.p_int[j]], _state); - } - - /* - * we need to be sure that 'CTree' contains - * at least one side center - */ - sparseset(&sps, i, i, (double)(1), _state); - c.ptr.p_double[0] = 1.0; - for(j=1; j<=centerscnt-1; j++) - { - c.ptr.p_double[j] = 0.0; - } - if( centerscnt>1&&nearpointscnt.ptr.p_int[i]>0 ) - { - - /* - * first KDTree request for points - */ - pointscnt = nearpointscnt.ptr.p_int[i]; - tmpi = kdtreequeryknn(pointstree, &xcx, skipnearpointscnt.ptr.p_int[i]+nearpointscnt.ptr.p_int[i], ae_true, _state); - ae_assert(tmpi==skipnearpointscnt.ptr.p_int[i]+nearpointscnt.ptr.p_int[i], "BuildRBFModelLSQR: internal error", _state); - kdtreequeryresultsx(pointstree, &xx, _state); - sind = skipnearpointscnt.ptr.p_int[i]; - for(j=0; j<=pointscnt-1; j++) - { - vx = xx.ptr.pp_double[sind+j][0]; - vy = xx.ptr.pp_double[sind+j][1]; - vz = xx.ptr.pp_double[sind+j][2]; - for(k=0; k<=centerscnt-1; k++) - { - vr = 0.0; - vv = vx-cx.ptr.pp_double[k][0]; - vr = vr+vv*vv; - vv = vy-cx.ptr.pp_double[k][1]; - vr = vr+vv*vv; - vv = vz-cx.ptr.pp_double[k][2]; - vr = vr+vv*vv; - vv = r->ptr.p_double[centerstags.ptr.p_int[k]]; - a.ptr.pp_double[j][k] = ae_exp(-vr/(vv*vv), _state); - } - } - for(j=0; j<=centerscnt-1; j++) - { - g.ptr.p_double[j] = ae_exp(-(ae_sqr(xcx.ptr.p_double[0]-cx.ptr.pp_double[j][0], _state)+ae_sqr(xcx.ptr.p_double[1]-cx.ptr.pp_double[j][1], _state)+ae_sqr(xcx.ptr.p_double[2]-cx.ptr.pp_double[j][2], _state))/ae_sqr(r->ptr.p_double[centerstags.ptr.p_int[j]], _state), _state); - } - - /* - * calculate the problem - */ - gnorm2 = ae_v_dotproduct(&g.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1)); - for(j=0; j<=pointscnt-1; j++) - { - vv = ae_v_dotproduct(&a.ptr.pp_double[j][0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1)); - vv = vv/gnorm2; - tmpy.ptr.p_double[j] = -vv; - ae_v_subd(&a.ptr.pp_double[j][0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1), vv); - } - for(j=pointscnt; j<=pointscnt+centerscnt-1; j++) - { - for(k=0; k<=centerscnt-1; k++) - { - a.ptr.pp_double[j][k] = 0.0; - } - a.ptr.pp_double[j][j-pointscnt] = 1.0E-6; - tmpy.ptr.p_double[j] = 0.0; - } - fblssolvels(&a, &tmpy, pointscnt+centerscnt, centerscnt, &tmp0, &tmp1, &tmp2, _state); - ae_v_move(&c.ptr.p_double[0], 1, &tmpy.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1)); - vv = ae_v_dotproduct(&g.ptr.p_double[0], 1, &c.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1)); - vv = vv/gnorm2; - ae_v_subd(&c.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1), vv); - vv = 1/gnorm2; - ae_v_addd(&c.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1), vv); - for(j=0; j<=centerscnt-1; j++) - { - sparseset(&sps, i, centerstags.ptr.p_int[j], c.ptr.p_double[j], _state); - } - } - - /* - * second KDTree request for points - */ - pointscnt = farpointscnt.ptr.p_int[i]; - tmpi = kdtreequeryknn(pointstree, &xcx, pointscnt, ae_true, _state); - ae_assert(tmpi==pointscnt, "BuildRBFModelLSQR: internal error", _state); - kdtreequeryresultsx(pointstree, &xx, _state); - kdtreequeryresultstags(pointstree, &pointstags, _state); - - /* - *fill SpG matrix - */ - for(j=0; j<=pointscnt-1; j++) - { - fx = (double)(0); - vx = xx.ptr.pp_double[j][0]; - vy = xx.ptr.pp_double[j][1]; - vz = xx.ptr.pp_double[j][2]; - for(k=0; k<=centerscnt-1; k++) - { - vr = 0.0; - vv = vx-cx.ptr.pp_double[k][0]; - vr = vr+vv*vv; - vv = vy-cx.ptr.pp_double[k][1]; - vr = vr+vv*vv; - vv = vz-cx.ptr.pp_double[k][2]; - vr = vr+vv*vv; - vv = r->ptr.p_double[centerstags.ptr.p_int[k]]; - vv = vv*vv; - fx = fx+c.ptr.p_double[k]*ae_exp(-vr/vv, _state); - } - sparseset(&spg, pointstags.ptr.p_int[j], i, fx, _state); - } - } - sparseconverttocrs(&spg, _state); - sparseconverttocrs(&sps, _state); - - /* - * solve by LSQR method - */ - ae_vector_set_length(&tmpy, n, _state); - ae_vector_set_length(&tc, nc, _state); - ae_matrix_set_length(w, nc, ny, _state); - linlsqrcreate(n, nc, &state, _state); - linlsqrsetcond(&state, epsort, epserr, maxits, _state); - for(i=0; i<=ny-1; i++) - { - for(j=0; j<=n-1; j++) - { - tmpy.ptr.p_double[j] = y->ptr.pp_double[j][i]; - } - linlsqrsolvesparse(&state, &spg, &tmpy, _state); - linlsqrresults(&state, &c, &lsqrrep, _state); - if( lsqrrep.terminationtype<=0 ) - { - *info = -4; - ae_frame_leave(_state); - return; - } - sparsemtv(&sps, &c, &tc, _state); - for(j=0; j<=nc-1; j++) - { - w->ptr.pp_double[j][i] = tc.ptr.p_double[j]; - } - *iterationscount = *iterationscount+lsqrrep.iterationscount; - *nmv = *nmv+lsqrrep.nmv; - } - *info = 1; - ae_frame_leave(_state); -} - - -static void rbfv1_buildrbfmlayersmodellsqr(/* Real */ ae_matrix* x, - /* Real */ ae_matrix* y, - /* Real */ ae_matrix* xc, - double rval, - /* Real */ ae_vector* r, - ae_int_t n, - ae_int_t* nc, - ae_int_t ny, - ae_int_t nlayers, - kdtree* centerstree, - double epsort, - double epserr, - ae_int_t maxits, - double lambdav, - ae_int_t* annz, - /* Real */ ae_matrix* w, - ae_int_t* info, - ae_int_t* iterationscount, - ae_int_t* nmv, - ae_state *_state) -{ - ae_frame _frame_block; - linlsqrstate state; - linlsqrreport lsqrrep; - sparsematrix spa; - double anorm; - ae_vector omega; - ae_vector xx; - ae_vector tmpy; - ae_matrix cx; - double yval; - ae_int_t nec; - ae_vector centerstags; - ae_int_t layer; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double rmaxbefore; - double rmaxafter; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&lsqrrep, 0, sizeof(lsqrrep)); - memset(&spa, 0, sizeof(spa)); - memset(&omega, 0, sizeof(omega)); - memset(&xx, 0, sizeof(xx)); - memset(&tmpy, 0, sizeof(tmpy)); - memset(&cx, 0, sizeof(cx)); - memset(¢erstags, 0, sizeof(centerstags)); - ae_matrix_clear(xc); - ae_vector_clear(r); - *nc = 0; - *annz = 0; - ae_matrix_clear(w); - *info = 0; - *iterationscount = 0; - *nmv = 0; - _linlsqrstate_init(&state, _state, ae_true); - _linlsqrreport_init(&lsqrrep, _state, ae_true); - _sparsematrix_init(&spa, _state, ae_true); - ae_vector_init(&omega, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpy, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&cx, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(¢erstags, 0, DT_INT, _state, ae_true); - - ae_assert(nlayers>=0, "BuildRBFMLayersModelLSQR: invalid argument(NLayers<0)", _state); - ae_assert(n>=0, "BuildRBFMLayersModelLSQR: invalid argument(N<0)", _state); - ae_assert(rbfv1_mxnx>0&&rbfv1_mxnx<=3, "BuildRBFMLayersModelLSQR: internal error(invalid global const MxNX: either MxNX<=0 or MxNX>3)", _state); - *annz = 0; - if( n==0||nlayers==0 ) - { - *info = 1; - *iterationscount = 0; - *nmv = 0; - ae_frame_leave(_state); - return; - } - *nc = n*nlayers; - ae_vector_set_length(&xx, rbfv1_mxnx, _state); - ae_vector_set_length(¢erstags, n, _state); - ae_matrix_set_length(xc, *nc, rbfv1_mxnx, _state); - ae_vector_set_length(r, *nc, _state); - for(i=0; i<=*nc-1; i++) - { - for(j=0; j<=rbfv1_mxnx-1; j++) - { - xc->ptr.pp_double[i][j] = x->ptr.pp_double[i%n][j]; - } - } - for(i=0; i<=*nc-1; i++) - { - r->ptr.p_double[i] = rval/ae_pow((double)(2), (double)(i/n), _state); - } - for(i=0; i<=n-1; i++) - { - centerstags.ptr.p_int[i] = i; - } - kdtreebuildtagged(xc, ¢erstags, n, rbfv1_mxnx, 0, 2, centerstree, _state); - ae_vector_set_length(&omega, n, _state); - ae_vector_set_length(&tmpy, n, _state); - ae_matrix_set_length(w, *nc, ny, _state); - *info = -1; - *iterationscount = 0; - *nmv = 0; - linlsqrcreate(n, n, &state, _state); - linlsqrsetcond(&state, epsort, epserr, maxits, _state); - linlsqrsetlambdai(&state, 1.0E-6, _state); - - /* - * calculate number of non-zero elements for sparse matrix - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=rbfv1_mxnx-1; j++) - { - xx.ptr.p_double[j] = x->ptr.pp_double[i][j]; - } - *annz = *annz+kdtreequeryrnn(centerstree, &xx, r->ptr.p_double[0]*rbfv1_rbfmlradius, ae_true, _state); - } - for(layer=0; layer<=nlayers-1; layer++) - { - - /* - * Fill sparse matrix, calculate norm(A) - */ - anorm = 0.0; - sparsecreate(n, n, *annz, &spa, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=rbfv1_mxnx-1; j++) - { - xx.ptr.p_double[j] = x->ptr.pp_double[i][j]; - } - nec = kdtreequeryrnn(centerstree, &xx, r->ptr.p_double[layer*n]*rbfv1_rbfmlradius, ae_true, _state); - kdtreequeryresultsx(centerstree, &cx, _state); - kdtreequeryresultstags(centerstree, ¢erstags, _state); - for(j=0; j<=nec-1; j++) - { - v = ae_exp(-(ae_sqr(xx.ptr.p_double[0]-cx.ptr.pp_double[j][0], _state)+ae_sqr(xx.ptr.p_double[1]-cx.ptr.pp_double[j][1], _state)+ae_sqr(xx.ptr.p_double[2]-cx.ptr.pp_double[j][2], _state))/ae_sqr(r->ptr.p_double[layer*n+centerstags.ptr.p_int[j]], _state), _state); - sparseset(&spa, i, centerstags.ptr.p_int[j], v, _state); - anorm = anorm+ae_sqr(v, _state); - } - } - anorm = ae_sqrt(anorm, _state); - sparseconverttocrs(&spa, _state); - - /* - * Calculate maximum residual before adding new layer. - * This value is not used by algorithm, the only purpose is to make debugging easier. - */ - rmaxbefore = 0.0; - for(j=0; j<=n-1; j++) - { - for(i=0; i<=ny-1; i++) - { - rmaxbefore = ae_maxreal(rmaxbefore, ae_fabs(y->ptr.pp_double[j][i], _state), _state); - } - } - - /* - * Process NY dimensions of the target function - */ - for(i=0; i<=ny-1; i++) - { - for(j=0; j<=n-1; j++) - { - tmpy.ptr.p_double[j] = y->ptr.pp_double[j][i]; - } - - /* - * calculate Omega for current layer - */ - linlsqrsetlambdai(&state, lambdav*anorm/n, _state); - linlsqrsolvesparse(&state, &spa, &tmpy, _state); - linlsqrresults(&state, &omega, &lsqrrep, _state); - if( lsqrrep.terminationtype<=0 ) - { - *info = -4; - ae_frame_leave(_state); - return; - } - - /* - * calculate error for current layer - */ - for(j=0; j<=n-1; j++) - { - yval = (double)(0); - for(k=0; k<=rbfv1_mxnx-1; k++) - { - xx.ptr.p_double[k] = x->ptr.pp_double[j][k]; - } - nec = kdtreequeryrnn(centerstree, &xx, r->ptr.p_double[layer*n]*rbfv1_rbffarradius, ae_true, _state); - kdtreequeryresultsx(centerstree, &cx, _state); - kdtreequeryresultstags(centerstree, ¢erstags, _state); - for(k=0; k<=nec-1; k++) - { - yval = yval+omega.ptr.p_double[centerstags.ptr.p_int[k]]*ae_exp(-(ae_sqr(xx.ptr.p_double[0]-cx.ptr.pp_double[k][0], _state)+ae_sqr(xx.ptr.p_double[1]-cx.ptr.pp_double[k][1], _state)+ae_sqr(xx.ptr.p_double[2]-cx.ptr.pp_double[k][2], _state))/ae_sqr(r->ptr.p_double[layer*n+centerstags.ptr.p_int[k]], _state), _state); - } - y->ptr.pp_double[j][i] = y->ptr.pp_double[j][i]-yval; - } - - /* - * write Omega in out parameter W - */ - for(j=0; j<=n-1; j++) - { - w->ptr.pp_double[layer*n+j][i] = omega.ptr.p_double[j]; - } - *iterationscount = *iterationscount+lsqrrep.iterationscount; - *nmv = *nmv+lsqrrep.nmv; - } - - /* - * Calculate maximum residual before adding new layer. - * This value is not used by algorithm, the only purpose is to make debugging easier. - */ - rmaxafter = 0.0; - for(j=0; j<=n-1; j++) - { - for(i=0; i<=ny-1; i++) - { - rmaxafter = ae_maxreal(rmaxafter, ae_fabs(y->ptr.pp_double[j][i], _state), _state); - } - } - } - *info = 1; - ae_frame_leave(_state); -} - - -void _rbfv1calcbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - rbfv1calcbuffer *p = (rbfv1calcbuffer*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->calcbufxcx, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->calcbufx, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->calcbuftags, 0, DT_INT, _state, make_automatic); - _kdtreerequestbuffer_init(&p->requestbuffer, _state, make_automatic); -} - - -void _rbfv1calcbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - rbfv1calcbuffer *dst = (rbfv1calcbuffer*)_dst; - rbfv1calcbuffer *src = (rbfv1calcbuffer*)_src; - ae_vector_init_copy(&dst->calcbufxcx, &src->calcbufxcx, _state, make_automatic); - ae_matrix_init_copy(&dst->calcbufx, &src->calcbufx, _state, make_automatic); - ae_vector_init_copy(&dst->calcbuftags, &src->calcbuftags, _state, make_automatic); - _kdtreerequestbuffer_init_copy(&dst->requestbuffer, &src->requestbuffer, _state, make_automatic); -} - - -void _rbfv1calcbuffer_clear(void* _p) -{ - rbfv1calcbuffer *p = (rbfv1calcbuffer*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->calcbufxcx); - ae_matrix_clear(&p->calcbufx); - ae_vector_clear(&p->calcbuftags); - _kdtreerequestbuffer_clear(&p->requestbuffer); -} - - -void _rbfv1calcbuffer_destroy(void* _p) -{ - rbfv1calcbuffer *p = (rbfv1calcbuffer*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->calcbufxcx); - ae_matrix_destroy(&p->calcbufx); - ae_vector_destroy(&p->calcbuftags); - _kdtreerequestbuffer_destroy(&p->requestbuffer); -} - - -void _rbfv1model_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - rbfv1model *p = (rbfv1model*)_p; - ae_touch_ptr((void*)p); - _kdtree_init(&p->tree, _state, make_automatic); - ae_matrix_init(&p->xc, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->wr, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->v, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->calcbufxcx, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->calcbufx, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->calcbuftags, 0, DT_INT, _state, make_automatic); -} - - -void _rbfv1model_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - rbfv1model *dst = (rbfv1model*)_dst; - rbfv1model *src = (rbfv1model*)_src; - dst->ny = src->ny; - dst->nx = src->nx; - dst->nc = src->nc; - dst->nl = src->nl; - _kdtree_init_copy(&dst->tree, &src->tree, _state, make_automatic); - ae_matrix_init_copy(&dst->xc, &src->xc, _state, make_automatic); - ae_matrix_init_copy(&dst->wr, &src->wr, _state, make_automatic); - dst->rmax = src->rmax; - ae_matrix_init_copy(&dst->v, &src->v, _state, make_automatic); - ae_vector_init_copy(&dst->calcbufxcx, &src->calcbufxcx, _state, make_automatic); - ae_matrix_init_copy(&dst->calcbufx, &src->calcbufx, _state, make_automatic); - ae_vector_init_copy(&dst->calcbuftags, &src->calcbuftags, _state, make_automatic); -} - - -void _rbfv1model_clear(void* _p) -{ - rbfv1model *p = (rbfv1model*)_p; - ae_touch_ptr((void*)p); - _kdtree_clear(&p->tree); - ae_matrix_clear(&p->xc); - ae_matrix_clear(&p->wr); - ae_matrix_clear(&p->v); - ae_vector_clear(&p->calcbufxcx); - ae_matrix_clear(&p->calcbufx); - ae_vector_clear(&p->calcbuftags); -} - - -void _rbfv1model_destroy(void* _p) -{ - rbfv1model *p = (rbfv1model*)_p; - ae_touch_ptr((void*)p); - _kdtree_destroy(&p->tree); - ae_matrix_destroy(&p->xc); - ae_matrix_destroy(&p->wr); - ae_matrix_destroy(&p->v); - ae_vector_destroy(&p->calcbufxcx); - ae_matrix_destroy(&p->calcbufx); - ae_vector_destroy(&p->calcbuftags); -} - - -void _gridcalc3v1buf_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - gridcalc3v1buf *p = (gridcalc3v1buf*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->tx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ty, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->flag0, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->flag1, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->flag2, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->flag12, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->expbuf0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->expbuf1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->expbuf2, 0, DT_REAL, _state, make_automatic); - _kdtreerequestbuffer_init(&p->requestbuf, _state, make_automatic); - ae_matrix_init(&p->calcbufx, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->calcbuftags, 0, DT_INT, _state, make_automatic); -} - - -void _gridcalc3v1buf_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - gridcalc3v1buf *dst = (gridcalc3v1buf*)_dst; - gridcalc3v1buf *src = (gridcalc3v1buf*)_src; - ae_vector_init_copy(&dst->tx, &src->tx, _state, make_automatic); - ae_vector_init_copy(&dst->cx, &src->cx, _state, make_automatic); - ae_vector_init_copy(&dst->ty, &src->ty, _state, make_automatic); - ae_vector_init_copy(&dst->flag0, &src->flag0, _state, make_automatic); - ae_vector_init_copy(&dst->flag1, &src->flag1, _state, make_automatic); - ae_vector_init_copy(&dst->flag2, &src->flag2, _state, make_automatic); - ae_vector_init_copy(&dst->flag12, &src->flag12, _state, make_automatic); - ae_vector_init_copy(&dst->expbuf0, &src->expbuf0, _state, make_automatic); - ae_vector_init_copy(&dst->expbuf1, &src->expbuf1, _state, make_automatic); - ae_vector_init_copy(&dst->expbuf2, &src->expbuf2, _state, make_automatic); - _kdtreerequestbuffer_init_copy(&dst->requestbuf, &src->requestbuf, _state, make_automatic); - ae_matrix_init_copy(&dst->calcbufx, &src->calcbufx, _state, make_automatic); - ae_vector_init_copy(&dst->calcbuftags, &src->calcbuftags, _state, make_automatic); -} - - -void _gridcalc3v1buf_clear(void* _p) -{ - gridcalc3v1buf *p = (gridcalc3v1buf*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->tx); - ae_vector_clear(&p->cx); - ae_vector_clear(&p->ty); - ae_vector_clear(&p->flag0); - ae_vector_clear(&p->flag1); - ae_vector_clear(&p->flag2); - ae_vector_clear(&p->flag12); - ae_vector_clear(&p->expbuf0); - ae_vector_clear(&p->expbuf1); - ae_vector_clear(&p->expbuf2); - _kdtreerequestbuffer_clear(&p->requestbuf); - ae_matrix_clear(&p->calcbufx); - ae_vector_clear(&p->calcbuftags); -} - - -void _gridcalc3v1buf_destroy(void* _p) -{ - gridcalc3v1buf *p = (gridcalc3v1buf*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->tx); - ae_vector_destroy(&p->cx); - ae_vector_destroy(&p->ty); - ae_vector_destroy(&p->flag0); - ae_vector_destroy(&p->flag1); - ae_vector_destroy(&p->flag2); - ae_vector_destroy(&p->flag12); - ae_vector_destroy(&p->expbuf0); - ae_vector_destroy(&p->expbuf1); - ae_vector_destroy(&p->expbuf2); - _kdtreerequestbuffer_destroy(&p->requestbuf); - ae_matrix_destroy(&p->calcbufx); - ae_vector_destroy(&p->calcbuftags); -} - - -void _rbfv1report_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - rbfv1report *p = (rbfv1report*)_p; - ae_touch_ptr((void*)p); -} - - -void _rbfv1report_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - rbfv1report *dst = (rbfv1report*)_dst; - rbfv1report *src = (rbfv1report*)_src; - dst->arows = src->arows; - dst->acols = src->acols; - dst->annz = src->annz; - dst->iterationscount = src->iterationscount; - dst->nmv = src->nmv; - dst->terminationtype = src->terminationtype; -} - - -void _rbfv1report_clear(void* _p) -{ - rbfv1report *p = (rbfv1report*)_p; - ae_touch_ptr((void*)p); -} - - -void _rbfv1report_destroy(void* _p) -{ - rbfv1report *p = (rbfv1report*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_RBF) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function creates RBF model for a scalar (NY=1) or vector (NY>1) -function in a NX-dimensional space (NX>=1). - -Newly created model is empty. It can be used for interpolation right after -creation, but it just returns zeros. You have to add points to the model, -tune interpolation settings, and then call model construction function -rbfbuildmodel() which will update model according to your specification. - -USAGE: -1. User creates model with rbfcreate() -2. User adds dataset with rbfsetpoints() (points do NOT have to be on a - regular grid) or rbfsetpointsandscales(). -3. (OPTIONAL) User chooses polynomial term by calling: - * rbflinterm() to set linear term - * rbfconstterm() to set constant term - * rbfzeroterm() to set zero term - By default, linear term is used. -4. User tweaks algorithm properties with rbfsetalgohierarchical() method - (or chooses one of the legacy algorithms - QNN (rbfsetalgoqnn) or ML - (rbfsetalgomultilayer)). -5. User calls rbfbuildmodel() function which rebuilds model according to - the specification -6. User may call rbfcalc() to calculate model value at the specified point, - rbfgridcalc() to calculate model values at the points of the regular - grid. User may extract model coefficients with rbfunpack() call. - -IMPORTANT: we recommend you to use latest model construction algorithm - - hierarchical RBFs, which is activated by rbfsetalgohierarchical() - function. This algorithm is the fastest one, and most memory- - efficient. - However, it is incompatible with older versions of ALGLIB - (pre-3.11). So, if you serialize hierarchical model, you will - be unable to load it in pre-3.11 ALGLIB. Other model types (QNN - and RBF-ML) are still backward-compatible. - -INPUT PARAMETERS: - NX - dimension of the space, NX>=1 - NY - function dimension, NY>=1 - -OUTPUT PARAMETERS: - S - RBF model (initially equals to zero) - -NOTE 1: memory requirements. RBF models require amount of memory which is - proportional to the number of data points. Some additional memory - is allocated during model construction, but most of this memory is - freed after model coefficients are calculated. Amount of this - additional memory depends on model construction algorithm being - used. - -NOTE 2: prior to ALGLIB version 3.11, RBF models supported only NX=2 or - NX=3. Any attempt to create single-dimensional or more than - 3-dimensional RBF model resulted in exception. - - ALGLIB 3.11 supports any NX>0, but models created with NX!=2 and - NX!=3 are incompatible with (a) older versions of ALGLIB, (b) old - model construction algorithms (QNN or RBF-ML). - - So, if you create a model with NX=2 or NX=3, then, depending on - specific model construction algorithm being chosen, you will (QNN - and RBF-ML) or will not (HierarchicalRBF) get backward compatibility - with older versions of ALGLIB. You have a choice here. - - However, if you create a model with NX neither 2 nor 3, you have - no backward compatibility from the start, and you are forced to - use hierarchical RBFs and ALGLIB 3.11 or later. - - -- ALGLIB -- - Copyright 13.12.2011, 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfcreate(ae_int_t nx, ae_int_t ny, rbfmodel* s, ae_state *_state) -{ - - _rbfmodel_clear(s); - - ae_assert(nx>=1, "RBFCreate: NX<1", _state); - ae_assert(ny>=1, "RBFCreate: NY<1", _state); - s->nx = nx; - s->ny = ny; - rbf_rbfpreparenonserializablefields(s, _state); - - /* - * Select default model version according to NX. - * - * The idea is that when we call this function with NX=2 or NX=3, backward - * compatible dummy (zero) V1 model is created, so serialization produces - * model which are compatible with pre-3.11 ALGLIB. - */ - rbf_initializev1(nx, ny, &s->model1, _state); - rbf_initializev2(nx, ny, &s->model2, _state); - if( nx==2||nx==3 ) - { - s->modelversion = 1; - } - else - { - s->modelversion = 2; - } - - /* - * Report fields - */ - s->progress10000 = 0; - s->terminationrequest = ae_false; -} - - -/************************************************************************* -This function creates buffer structure which can be used to perform -parallel RBF model evaluations (with one RBF model instance being -used from multiple threads, as long as different threads use different -instances of buffer). - -This buffer object can be used with rbftscalcbuf() function (here "ts" -stands for "thread-safe", "buf" is a suffix which denotes function which -reuses previously allocated output space). - -How to use it: -* create RBF model structure with rbfcreate() -* load data, tune parameters -* call rbfbuildmodel() -* call rbfcreatecalcbuffer(), once per thread working with RBF model (you - should call this function only AFTER call to rbfbuildmodel(), see below - for more information) -* call rbftscalcbuf() from different threads, with each thread working - with its own copy of buffer object. - -INPUT PARAMETERS - S - RBF model - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: buffer object should be used only with RBF model object which - was used to initialize buffer. Any attempt to use buffer with - different object is dangerous - you may get memory violation - error because sizes of internal arrays do not fit to dimensions - of RBF structure. - -IMPORTANT: you should call this function only for model which was built - with rbfbuildmodel() function, after successful invocation of - rbfbuildmodel(). Sizes of some internal structures are - determined only after model is built, so buffer object created - before model construction stage will be useless (and any - attempt to use it will result in exception). - - -- ALGLIB -- - Copyright 02.04.2016 by Sergey Bochkanov -*************************************************************************/ -void rbfcreatecalcbuffer(rbfmodel* s, - rbfcalcbuffer* buf, - ae_state *_state) -{ - - _rbfcalcbuffer_clear(buf); - - if( s->modelversion==1 ) - { - buf->modelversion = 1; - rbfv1createcalcbuffer(&s->model1, &buf->bufv1, _state); - return; - } - if( s->modelversion==2 ) - { - buf->modelversion = 2; - rbfv2createcalcbuffer(&s->model2, &buf->bufv2, _state); - return; - } - ae_assert(ae_false, "RBFCreateCalcBuffer: integrity check failed", _state); -} - - -/************************************************************************* -This function adds dataset. - -This function overrides results of the previous calls, i.e. multiple calls -of this function will result in only the last set being added. - -IMPORTANT: ALGLIB version 3.11 and later allows you to specify a set of - per-dimension scales. Interpolation radii are multiplied by the - scale vector. It may be useful if you have mixed spatio-temporal - data (say, a set of 3D slices recorded at different times). - You should call rbfsetpointsandscales() function to use this - feature. - -INPUT PARAMETERS: - S - RBF model, initialized by rbfcreate() call. - XY - points, array[N,NX+NY]. One row corresponds to one point - in the dataset. First NX elements are coordinates, next - NY elements are function values. Array may be larger than - specified, in this case only leading [N,NX+NY] elements - will be used. - N - number of points in the dataset - -After you've added dataset and (optionally) tuned algorithm settings you -should call rbfbuildmodel() in order to build a model for you. - -NOTE: dataset added by this function is not saved during model serialization. - MODEL ITSELF is serialized, but data used to build it are not. - - So, if you 1) add dataset to empty RBF model, 2) serialize and - unserialize it, then you will get an empty RBF model with no dataset - being attached. - - From the other side, if you call rbfbuildmodel() between (1) and (2), - then after (2) you will get your fully constructed RBF model - but - again with no dataset attached, so subsequent calls to rbfbuildmodel() - will produce empty model. - - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfsetpoints(rbfmodel* s, - /* Real */ ae_matrix* xy, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - ae_assert(n>0, "RBFSetPoints: N<0", _state); - ae_assert(xy->rows>=n, "RBFSetPoints: Rows(XY)cols>=s->nx+s->ny, "RBFSetPoints: Cols(XY)nx+s->ny, _state), "RBFSetPoints: XY contains infinite or NaN values!", _state); - s->n = n; - s->hasscale = ae_false; - ae_matrix_set_length(&s->x, s->n, s->nx, _state); - ae_matrix_set_length(&s->y, s->n, s->ny, _state); - for(i=0; i<=s->n-1; i++) - { - for(j=0; j<=s->nx-1; j++) - { - s->x.ptr.pp_double[i][j] = xy->ptr.pp_double[i][j]; - } - for(j=0; j<=s->ny-1; j++) - { - s->y.ptr.pp_double[i][j] = xy->ptr.pp_double[i][j+s->nx]; - } - } -} - - -/************************************************************************* -This function adds dataset and a vector of per-dimension scales. - -It may be useful if you have mixed spatio-temporal data - say, a set of 3D -slices recorded at different times. Such data typically require different -RBF radii for spatial and temporal dimensions. ALGLIB solves this problem -by specifying single RBF radius, which is (optionally) multiplied by the -scale vector. - -This function overrides results of the previous calls, i.e. multiple calls -of this function will result in only the last set being added. - -IMPORTANT: only HierarchicalRBF algorithm can work with scaled points. So, - using this function results in RBF models which can be used in - ALGLIB 3.11 or later. Previous versions of the library will be - unable to unserialize models produced by HierarchicalRBF algo. - - Any attempt to use this function with RBF-ML or QNN algorithms - will result in -3 error code being returned (incorrect - algorithm). - -INPUT PARAMETERS: - R - RBF model, initialized by rbfcreate() call. - XY - points, array[N,NX+NY]. One row corresponds to one point - in the dataset. First NX elements are coordinates, next - NY elements are function values. Array may be larger than - specified, in this case only leading [N,NX+NY] elements - will be used. - N - number of points in the dataset - S - array[NX], scale vector, S[i]>0. - -After you've added dataset and (optionally) tuned algorithm settings you -should call rbfbuildmodel() in order to build a model for you. - -NOTE: dataset added by this function is not saved during model serialization. - MODEL ITSELF is serialized, but data used to build it are not. - - So, if you 1) add dataset to empty RBF model, 2) serialize and - unserialize it, then you will get an empty RBF model with no dataset - being attached. - - From the other side, if you call rbfbuildmodel() between (1) and (2), - then after (2) you will get your fully constructed RBF model - but - again with no dataset attached, so subsequent calls to rbfbuildmodel() - will produce empty model. - - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfsetpointsandscales(rbfmodel* r, - /* Real */ ae_matrix* xy, - ae_int_t n, - /* Real */ ae_vector* s, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - ae_assert(n>0, "RBFSetPointsAndScales: N<0", _state); - ae_assert(xy->rows>=n, "RBFSetPointsAndScales: Rows(XY)cols>=r->nx+r->ny, "RBFSetPointsAndScales: Cols(XY)cnt>=r->nx, "RBFSetPointsAndScales: Length(S)n = n; - r->hasscale = ae_true; - ae_matrix_set_length(&r->x, r->n, r->nx, _state); - ae_matrix_set_length(&r->y, r->n, r->ny, _state); - for(i=0; i<=r->n-1; i++) - { - for(j=0; j<=r->nx-1; j++) - { - r->x.ptr.pp_double[i][j] = xy->ptr.pp_double[i][j]; - } - for(j=0; j<=r->ny-1; j++) - { - r->y.ptr.pp_double[i][j] = xy->ptr.pp_double[i][j+r->nx]; - } - } - ae_vector_set_length(&r->s, r->nx, _state); - for(i=0; i<=r->nx-1; i++) - { - ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "RBFSetPointsAndScales: S[i] is not finite number", _state); - ae_assert(ae_fp_greater(s->ptr.p_double[i],(double)(0)), "RBFSetPointsAndScales: S[i]<=0", _state); - r->s.ptr.p_double[i] = s->ptr.p_double[i]; - } -} - - -/************************************************************************* -DEPRECATED:since version 3.11 ALGLIB includes new RBF model construction - algorithm, Hierarchical RBF. This algorithm is faster and - requires less memory than QNN and RBF-ML. It is especially good - for large-scale interpolation problems. So, we recommend you to - consider Hierarchical RBF as default option. - -========================================================================== - -This function sets RBF interpolation algorithm. ALGLIB supports several -RBF algorithms with different properties. - -This algorithm is called RBF-QNN and it is good for point sets with -following properties: -a) all points are distinct -b) all points are well separated. -c) points distribution is approximately uniform. There is no "contour - lines", clusters of points, or other small-scale structures. - -Algorithm description: -1) interpolation centers are allocated to data points -2) interpolation radii are calculated as distances to the nearest centers - times Q coefficient (where Q is a value from [0.75,1.50]). -3) after performing (2) radii are transformed in order to avoid situation - when single outlier has very large radius and influences many points - across all dataset. Transformation has following form: - new_r[i] = min(r[i],Z*median(r[])) - where r[i] is I-th radius, median() is a median radius across entire - dataset, Z is user-specified value which controls amount of deviation - from median radius. - -When (a) is violated, we will be unable to build RBF model. When (b) or -(c) are violated, model will be built, but interpolation quality will be -low. See http://www.alglib.net/interpolation/ for more information on this -subject. - -This algorithm is used by default. - -Additional Q parameter controls smoothness properties of the RBF basis: -* Q<0.75 will give perfectly conditioned basis, but terrible smoothness - properties (RBF interpolant will have sharp peaks around function values) -* Q around 1.0 gives good balance between smoothness and condition number -* Q>1.5 will lead to badly conditioned systems and slow convergence of the - underlying linear solver (although smoothness will be very good) -* Q>2.0 will effectively make optimizer useless because it won't converge - within reasonable amount of iterations. It is possible to set such large - Q, but it is advised not to do so. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - Q - Q parameter, Q>0, recommended value - 1.0 - Z - Z parameter, Z>0, recommended value - 5.0 - -NOTE: this function has some serialization-related subtleties. We - recommend you to study serialization examples from ALGLIB Reference - Manual if you want to perform serialization of your models. - - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfsetalgoqnn(rbfmodel* s, double q, double z, ae_state *_state) -{ - - - ae_assert(ae_isfinite(q, _state), "RBFSetAlgoQNN: Q is infinite or NAN", _state); - ae_assert(ae_fp_greater(q,(double)(0)), "RBFSetAlgoQNN: Q<=0", _state); - ae_assert(ae_isfinite(z, _state), "RBFSetAlgoQNN: Z is infinite or NAN", _state); - ae_assert(ae_fp_greater(z,(double)(0)), "RBFSetAlgoQNN: Z<=0", _state); - s->radvalue = q; - s->radzvalue = z; - s->algorithmtype = 1; -} - - -/************************************************************************* -DEPRECATED:since version 3.11 ALGLIB includes new RBF model construction - algorithm, Hierarchical RBF. This algorithm is faster and - requires less memory than QNN and RBF-ML. It is especially good - for large-scale interpolation problems. So, we recommend you to - consider Hierarchical RBF as default option. - -========================================================================== - -This function sets RBF interpolation algorithm. ALGLIB supports several -RBF algorithms with different properties. - -This algorithm is called RBF-ML. It builds multilayer RBF model, i.e. -model with subsequently decreasing radii, which allows us to combine -smoothness (due to large radii of the first layers) with exactness (due -to small radii of the last layers) and fast convergence. - -Internally RBF-ML uses many different means of acceleration, from sparse -matrices to KD-trees, which results in algorithm whose working time is -roughly proportional to N*log(N)*Density*RBase^2*NLayers, where N is a -number of points, Density is an average density if points per unit of the -interpolation space, RBase is an initial radius, NLayers is a number of -layers. - -RBF-ML is good for following kinds of interpolation problems: -1. "exact" problems (perfect fit) with well separated points -2. least squares problems with arbitrary distribution of points (algorithm - gives perfect fit where it is possible, and resorts to least squares - fit in the hard areas). -3. noisy problems where we want to apply some controlled amount of - smoothing. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - RBase - RBase parameter, RBase>0 - NLayers - NLayers parameter, NLayers>0, recommended value to start - with - about 5. - LambdaV - regularization value, can be useful when solving problem - in the least squares sense. Optimal lambda is problem- - dependent and require trial and error. In our experience, - good lambda can be as large as 0.1, and you can use 0.001 - as initial guess. - Default value - 0.01, which is used when LambdaV is not - given. You can specify zero value, but it is not - recommended to do so. - -TUNING ALGORITHM - -In order to use this algorithm you have to choose three parameters: -* initial radius RBase -* number of layers in the model NLayers -* regularization coefficient LambdaV - -Initial radius is easy to choose - you can pick any number several times -larger than the average distance between points. Algorithm won't break -down if you choose radius which is too large (model construction time will -increase, but model will be built correctly). - -Choose such number of layers that RLast=RBase/2^(NLayers-1) (radius used -by the last layer) will be smaller than the typical distance between -points. In case model error is too large, you can increase number of -layers. Having more layers will make model construction and evaluation -proportionally slower, but it will allow you to have model which precisely -fits your data. From the other side, if you want to suppress noise, you -can DECREASE number of layers to make your model less flexible. - -Regularization coefficient LambdaV controls smoothness of the individual -models built for each layer. We recommend you to use default value in case -you don't want to tune this parameter, because having non-zero LambdaV -accelerates and stabilizes internal iterative algorithm. In case you want -to suppress noise you can use LambdaV as additional parameter (larger -value = more smoothness) to tune. - -TYPICAL ERRORS - -1. Using initial radius which is too large. Memory requirements of the - RBF-ML are roughly proportional to N*Density*RBase^2 (where Density is - an average density of points per unit of the interpolation space). In - the extreme case of the very large RBase we will need O(N^2) units of - memory - and many layers in order to decrease radius to some reasonably - small value. - -2. Using too small number of layers - RBF models with large radius are not - flexible enough to reproduce small variations in the target function. - You need many layers with different radii, from large to small, in - order to have good model. - -3. Using initial radius which is too small. You will get model with - "holes" in the areas which are too far away from interpolation centers. - However, algorithm will work correctly (and quickly) in this case. - -4. Using too many layers - you will get too large and too slow model. This - model will perfectly reproduce your function, but maybe you will be - able to achieve similar results with less layers (and less memory). - - -- ALGLIB -- - Copyright 02.03.2012 by Bochkanov Sergey -*************************************************************************/ -void rbfsetalgomultilayer(rbfmodel* s, - double rbase, - ae_int_t nlayers, - double lambdav, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(rbase, _state), "RBFSetAlgoMultiLayer: RBase is infinite or NaN", _state); - ae_assert(ae_fp_greater(rbase,(double)(0)), "RBFSetAlgoMultiLayer: RBase<=0", _state); - ae_assert(nlayers>=0, "RBFSetAlgoMultiLayer: NLayers<0", _state); - ae_assert(ae_isfinite(lambdav, _state), "RBFSetAlgoMultiLayer: LambdaV is infinite or NAN", _state); - ae_assert(ae_fp_greater_eq(lambdav,(double)(0)), "RBFSetAlgoMultiLayer: LambdaV<0", _state); - s->radvalue = rbase; - s->nlayers = nlayers; - s->algorithmtype = 2; - s->lambdav = lambdav; -} - - -/************************************************************************* -This function sets RBF interpolation algorithm. ALGLIB supports several -RBF algorithms with different properties. - -This algorithm is called Hierarchical RBF. It similar to its previous -incarnation, RBF-ML, i.e. it also builds a sequence of models with -decreasing radii. However, it uses more economical way of building upper -layers (ones with large radii), which results in faster model construction -and evaluation, as well as smaller memory footprint during construction. - -This algorithm has following important features: -* ability to handle millions of points -* controllable smoothing via nonlinearity penalization -* support for NX-dimensional models with NX=1 or NX>3 (unlike QNN or RBF-ML) -* support for specification of per-dimensional radii via scale vector, - which is set by means of rbfsetpointsandscales() function. This feature - is useful if you solve spatio-temporal interpolation problems, where - different radii are required for spatial and temporal dimensions. - -Running times are roughly proportional to: -* N*log(N)*NLayers - for model construction -* N*NLayers - for model evaluation -You may see that running time does not depend on search radius or points -density, just on number of layers in the hierarchy. - -IMPORTANT: this model construction algorithm was introduced in ALGLIB 3.11 - and produces models which are INCOMPATIBLE with previous - versions of ALGLIB. You can not unserialize models produced - with this function in ALGLIB 3.10 or earlier. - -INPUT PARAMETERS: - S - RBF model, initialized by rbfcreate() call - RBase - RBase parameter, RBase>0 - NLayers - NLayers parameter, NLayers>0, recommended value to start - with - about 5. - LambdaNS- >=0, nonlinearity penalty coefficient, negative values are - not allowed. This parameter adds controllable smoothing to - the problem, which may reduce noise. Specification of non- - zero lambda means that in addition to fitting error solver - will also minimize LambdaNS*|S''(x)|^2 (appropriately - generalized to multiple dimensions. - - Specification of exactly zero value means that no penalty - is added (we do not even evaluate matrix of second - derivatives which is necessary for smoothing). - - Calculation of nonlinearity penalty is costly - it results - in several-fold increase of model construction time. - Evaluation time remains the same. - - Optimal lambda is problem-dependent and requires trial - and error. Good value to start from is 1e-5...1e-6, - which corresponds to slightly noticeable smoothing of the - function. Value 1e-2 usually means that quite heavy - smoothing is applied. - -TUNING ALGORITHM - -In order to use this algorithm you have to choose three parameters: -* initial radius RBase -* number of layers in the model NLayers -* penalty coefficient LambdaNS - -Initial radius is easy to choose - you can pick any number several times -larger than the average distance between points. Algorithm won't break -down if you choose radius which is too large (model construction time will -increase, but model will be built correctly). - -Choose such number of layers that RLast=RBase/2^(NLayers-1) (radius used -by the last layer) will be smaller than the typical distance between -points. In case model error is too large, you can increase number of -layers. Having more layers will make model construction and evaluation -proportionally slower, but it will allow you to have model which precisely -fits your data. From the other side, if you want to suppress noise, you -can DECREASE number of layers to make your model less flexible (or specify -non-zero LambdaNS). - -TYPICAL ERRORS - -1. Using too small number of layers - RBF models with large radius are not - flexible enough to reproduce small variations in the target function. - You need many layers with different radii, from large to small, in - order to have good model. - -2. Using initial radius which is too small. You will get model with - "holes" in the areas which are too far away from interpolation centers. - However, algorithm will work correctly (and quickly) in this case. - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfsetalgohierarchical(rbfmodel* s, - double rbase, - ae_int_t nlayers, - double lambdans, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(rbase, _state), "RBFSetAlgoHierarchical: RBase is infinite or NaN", _state); - ae_assert(ae_fp_greater(rbase,(double)(0)), "RBFSetAlgoHierarchical: RBase<=0", _state); - ae_assert(nlayers>=0, "RBFSetAlgoHierarchical: NLayers<0", _state); - ae_assert(ae_isfinite(lambdans, _state)&&ae_fp_greater_eq(lambdans,(double)(0)), "RBFSetAlgoHierarchical: LambdaNS<0 or infinite", _state); - s->radvalue = rbase; - s->nlayers = nlayers; - s->algorithmtype = 3; - s->lambdav = lambdans; -} - - -/************************************************************************* -This function sets linear term (model is a sum of radial basis functions -plus linear polynomial). This function won't have effect until next call -to RBFBuildModel(). - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - -NOTE: this function has some serialization-related subtleties. We - recommend you to study serialization examples from ALGLIB Reference - Manual if you want to perform serialization of your models. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfsetlinterm(rbfmodel* s, ae_state *_state) -{ - - - s->aterm = 1; -} - - -/************************************************************************* -This function sets constant term (model is a sum of radial basis functions -plus constant). This function won't have effect until next call to -RBFBuildModel(). - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - -NOTE: this function has some serialization-related subtleties. We - recommend you to study serialization examples from ALGLIB Reference - Manual if you want to perform serialization of your models. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfsetconstterm(rbfmodel* s, ae_state *_state) -{ - - - s->aterm = 2; -} - - -/************************************************************************* -This function sets zero term (model is a sum of radial basis functions -without polynomial term). This function won't have effect until next call -to RBFBuildModel(). - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - -NOTE: this function has some serialization-related subtleties. We - recommend you to study serialization examples from ALGLIB Reference - Manual if you want to perform serialization of your models. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfsetzeroterm(rbfmodel* s, ae_state *_state) -{ - - - s->aterm = 3; -} - - -/************************************************************************* -This function sets basis function type, which can be: -* 0 for classic Gaussian -* 1 for fast and compact bell-like basis function, which becomes exactly - zero at distance equal to 3*R (default option). - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - BF - basis function type: - * 0 - classic Gaussian - * 1 - fast and compact one - - -- ALGLIB -- - Copyright 01.02.2017 by Bochkanov Sergey -*************************************************************************/ -void rbfsetv2bf(rbfmodel* s, ae_int_t bf, ae_state *_state) -{ - - - ae_assert(bf==0||bf==1, "RBFSetV2Its: BF<>0 and BF<>1", _state); - s->model2.basisfunction = bf; -} - - -/************************************************************************* -This function sets stopping criteria of the underlying linear solver for -hierarchical (version 2) RBF constructor. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - MaxIts - this criterion will stop algorithm after MaxIts iterations. - Typically a few hundreds iterations is required, with 400 - being a good default value to start experimentation. - Zero value means that default value will be selected. - - -- ALGLIB -- - Copyright 01.02.2017 by Bochkanov Sergey -*************************************************************************/ -void rbfsetv2its(rbfmodel* s, ae_int_t maxits, ae_state *_state) -{ - - - ae_assert(maxits>=0, "RBFSetV2Its: MaxIts is negative", _state); - s->model2.maxits = maxits; -} - - -/************************************************************************* -This function sets support radius parameter of hierarchical (version 2) -RBF constructor. - -Hierarchical RBF model achieves great speed-up by removing from the model -excessive (too dense) nodes. Say, if you have RBF radius equal to 1 meter, -and two nodes are just 1 millimeter apart, you may remove one of them -without reducing model quality. - -Support radius parameter is used to justify which points need removal, and -which do not. If two points are less than SUPPORT_R*CUR_RADIUS units of -distance apart, one of them is removed from the model. The larger support -radius is, the faster model construction AND evaluation are. However, -too large values result in "bumpy" models. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - R - support radius coefficient, >=0. - Recommended values are [0.1,0.4] range, with 0.1 being - default value. - - -- ALGLIB -- - Copyright 01.02.2017 by Bochkanov Sergey -*************************************************************************/ -void rbfsetv2supportr(rbfmodel* s, double r, ae_state *_state) -{ - - - ae_assert(ae_isfinite(r, _state), "RBFSetV2SupportR: R is not finite", _state); - ae_assert(ae_fp_greater_eq(r,(double)(0)), "RBFSetV2SupportR: R<0", _state); - s->model2.supportr = r; -} - - -/************************************************************************* -This function sets stopping criteria of the underlying linear solver. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - EpsOrt - orthogonality stopping criterion, EpsOrt>=0. Algorithm will - stop when ||A'*r||<=EpsOrt where A' is a transpose of the - system matrix, r is a residual vector. - Recommended value of EpsOrt is equal to 1E-6. - This criterion will stop algorithm when we have "bad fit" - situation, i.e. when we should stop in a point with large, - nonzero residual. - EpsErr - residual stopping criterion. Algorithm will stop when - ||r||<=EpsErr*||b||, where r is a residual vector, b is a - right part of the system (function values). - Recommended value of EpsErr is equal to 1E-3 or 1E-6. - This criterion will stop algorithm in a "good fit" - situation when we have near-zero residual near the desired - solution. - MaxIts - this criterion will stop algorithm after MaxIts iterations. - It should be used for debugging purposes only! - Zero MaxIts means that no limit is placed on the number of - iterations. - -We recommend to set moderate non-zero values EpsOrt and EpsErr -simultaneously. Values equal to 10E-6 are good to start with. In case you -need high performance and do not need high precision , you may decrease -EpsErr down to 0.001. However, we do not recommend decreasing EpsOrt. - -As for MaxIts, we recommend to leave it zero unless you know what you do. - -NOTE: this function has some serialization-related subtleties. We - recommend you to study serialization examples from ALGLIB Reference - Manual if you want to perform serialization of your models. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfsetcond(rbfmodel* s, - double epsort, - double epserr, - ae_int_t maxits, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(epsort, _state)&&ae_fp_greater_eq(epsort,(double)(0)), "RBFSetCond: EpsOrt is negative, INF or NAN", _state); - ae_assert(ae_isfinite(epserr, _state)&&ae_fp_greater_eq(epserr,(double)(0)), "RBFSetCond: EpsB is negative, INF or NAN", _state); - ae_assert(maxits>=0, "RBFSetCond: MaxIts is negative", _state); - if( (ae_fp_eq(epsort,(double)(0))&&ae_fp_eq(epserr,(double)(0)))&&maxits==0 ) - { - s->epsort = rbf_eps; - s->epserr = rbf_eps; - s->maxits = 0; - } - else - { - s->epsort = epsort; - s->epserr = epserr; - s->maxits = maxits; - } -} - - -/************************************************************************* -This function builds RBF model and returns report (contains some -information which can be used for evaluation of the algorithm properties). - -Call to this function modifies RBF model by calculating its centers/radii/ -weights and saving them into RBFModel structure. Initially RBFModel -contain zero coefficients, but after call to this function we will have -coefficients which were calculated in order to fit our dataset. - -After you called this function you can call RBFCalc(), RBFGridCalc() and -other model calculation functions. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - Rep - report: - * Rep.TerminationType: - * -5 - non-distinct basis function centers were detected, - interpolation aborted; only QNN returns this - error code, other algorithms can handle non- - distinct nodes. - * -4 - nonconvergence of the internal SVD solver - * -3 incorrect model construction algorithm was chosen: - QNN or RBF-ML, combined with one of the incompatible - features - NX=1 or NX>3; points with per-dimension - scales. - * 1 - successful termination - * 8 - a termination request was submitted via - rbfrequesttermination() function. - - Fields which are set only by modern RBF solvers (hierarchical - or nonnegative; older solvers like QNN and ML initialize these - fields by NANs): - * rep.rmserror - root-mean-square error at nodes - * rep.maxerror - maximum error at nodes - - Fields are used for debugging purposes: - * Rep.IterationsCount - iterations count of the LSQR solver - * Rep.NMV - number of matrix-vector products - * Rep.ARows - rows count for the system matrix - * Rep.ACols - columns count for the system matrix - * Rep.ANNZ - number of significantly non-zero elements - (elements above some algorithm-determined threshold) - -NOTE: failure to build model will leave current state of the structure -unchanged. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfbuildmodel(rbfmodel* s, rbfreport* rep, ae_state *_state) -{ - ae_frame _frame_block; - rbfv1report rep1; - rbfv2report rep2; - ae_matrix x3; - ae_vector scalevec; - ae_int_t i; - ae_int_t curalgorithmtype; - - ae_frame_make(_state, &_frame_block); - memset(&rep1, 0, sizeof(rep1)); - memset(&rep2, 0, sizeof(rep2)); - memset(&x3, 0, sizeof(x3)); - memset(&scalevec, 0, sizeof(scalevec)); - _rbfreport_clear(rep); - _rbfv1report_init(&rep1, _state, ae_true); - _rbfv2report_init(&rep2, _state, ae_true); - ae_matrix_init(&x3, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&scalevec, 0, DT_REAL, _state, ae_true); - - - /* - * Clean fields prior to processing - */ - rbf_clearreportfields(rep, _state); - s->progress10000 = 0; - s->terminationrequest = ae_false; - - /* - * Autoselect algorithm - */ - if( s->algorithmtype==0 ) - { - if( (s->nx<2||s->nx>3)||s->hasscale ) - { - curalgorithmtype = 3; - } - else - { - curalgorithmtype = 1; - } - } - else - { - curalgorithmtype = s->algorithmtype; - } - - /* - * Algorithms which generate V1 models - */ - if( curalgorithmtype==1||curalgorithmtype==2 ) - { - - /* - * Perform compatibility checks - */ - if( (s->nx<2||s->nx>3)||s->hasscale ) - { - rep->terminationtype = -3; - ae_frame_leave(_state); - return; - } - - /* - * Try to build model. - * - * NOTE: due to historical reasons RBFV1BuildModel() accepts points - * cast to 3-dimensional space, even if they are really 2-dimensional. - * So, for 2D data we have to explicitly convert them to 3D. - */ - if( s->nx==2 ) - { - - /* - * Convert data to 3D - */ - rmatrixsetlengthatleast(&x3, s->n, 3, _state); - for(i=0; i<=s->n-1; i++) - { - x3.ptr.pp_double[i][0] = s->x.ptr.pp_double[i][0]; - x3.ptr.pp_double[i][1] = s->x.ptr.pp_double[i][1]; - x3.ptr.pp_double[i][2] = (double)(0); - } - rbfv1buildmodel(&x3, &s->y, s->n, s->aterm, curalgorithmtype, s->nlayers, s->radvalue, s->radzvalue, s->lambdav, s->epsort, s->epserr, s->maxits, &s->model1, &rep1, _state); - } - else - { - - /* - * Work with raw data - */ - rbfv1buildmodel(&s->x, &s->y, s->n, s->aterm, curalgorithmtype, s->nlayers, s->radvalue, s->radzvalue, s->lambdav, s->epsort, s->epserr, s->maxits, &s->model1, &rep1, _state); - } - s->modelversion = 1; - - /* - * Convert report fields - */ - rep->arows = rep1.arows; - rep->acols = rep1.acols; - rep->annz = rep1.annz; - rep->iterationscount = rep1.iterationscount; - rep->nmv = rep1.nmv; - rep->terminationtype = rep1.terminationtype; - - /* - * Done - */ - ae_frame_leave(_state); - return; - } - - /* - * Algorithms which generate V2 models - */ - if( curalgorithmtype==3 ) - { - - /* - * Prepare scale vector - use unit values or user supplied ones - */ - ae_vector_set_length(&scalevec, s->nx, _state); - for(i=0; i<=s->nx-1; i++) - { - if( s->hasscale ) - { - scalevec.ptr.p_double[i] = s->s.ptr.p_double[i]; - } - else - { - scalevec.ptr.p_double[i] = (double)(1); - } - } - - /* - * Build model - */ - rbfv2buildhierarchical(&s->x, &s->y, s->n, &scalevec, s->aterm, s->nlayers, s->radvalue, s->lambdav, &s->model2, &s->progress10000, &s->terminationrequest, &rep2, _state); - s->modelversion = 2; - - /* - * Convert report fields - */ - rep->terminationtype = rep2.terminationtype; - rep->rmserror = rep2.rmserror; - rep->maxerror = rep2.maxerror; - - /* - * Done - */ - ae_frame_leave(_state); - return; - } - - /* - * Critical error - */ - ae_assert(ae_false, "RBFBuildModel: integrity check failure", _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function calculates values of the RBF model in the given point. - -IMPORTANT: this function works only with modern (hierarchical) RBFs. It - can not be used with legacy (version 1) RBFs because older RBF - code does not support 1-dimensional models. - -This function should be used when we have NY=1 (scalar function) and NX=1 -(1-dimensional space). If you have 3-dimensional space, use rbfcalc3(). If -you have 2-dimensional space, use rbfcalc3(). If you have general -situation (NX-dimensional space, NY-dimensional function) you should use -generic rbfcalc(). - -If you want to perform parallel model evaluation from multiple threads, -use rbftscalcbuf() with per-thread buffer object. - -This function returns 0.0 when: -* model is not initialized -* NX<>1 -* NY<>1 - -INPUT PARAMETERS: - S - RBF model - X0 - X-coordinate, finite number - -RESULT: - value of the model or 0.0 (as defined above) - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -double rbfcalc1(rbfmodel* s, double x0, ae_state *_state) -{ - double result; - - - ae_assert(ae_isfinite(x0, _state), "RBFCalc1: invalid value for X0 (X0 is Inf)!", _state); - result = (double)(0); - if( s->ny!=1||s->nx!=1 ) - { - return result; - } - if( s->modelversion==1 ) - { - result = (double)(0); - return result; - } - if( s->modelversion==2 ) - { - result = rbfv2calc1(&s->model2, x0, _state); - return result; - } - ae_assert(ae_false, "RBFCalc1: integrity check failed", _state); - return result; -} - - -/************************************************************************* -This function calculates values of the RBF model in the given point. - -This function should be used when we have NY=1 (scalar function) and NX=2 -(2-dimensional space). If you have 3-dimensional space, use rbfcalc3(). If -you have general situation (NX-dimensional space, NY-dimensional function) -you should use generic rbfcalc(). - -If you want to calculate function values many times, consider using -rbfgridcalc2v(), which is far more efficient than many subsequent calls to -rbfcalc2(). - -If you want to perform parallel model evaluation from multiple threads, -use rbftscalcbuf() with per-thread buffer object. - -This function returns 0.0 when: -* model is not initialized -* NX<>2 - *NY<>1 - -INPUT PARAMETERS: - S - RBF model - X0 - first coordinate, finite number - X1 - second coordinate, finite number - -RESULT: - value of the model or 0.0 (as defined above) - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -double rbfcalc2(rbfmodel* s, double x0, double x1, ae_state *_state) -{ - double result; - - - ae_assert(ae_isfinite(x0, _state), "RBFCalc2: invalid value for X0 (X0 is Inf)!", _state); - ae_assert(ae_isfinite(x1, _state), "RBFCalc2: invalid value for X1 (X1 is Inf)!", _state); - result = (double)(0); - if( s->ny!=1||s->nx!=2 ) - { - return result; - } - if( s->modelversion==1 ) - { - result = rbfv1calc2(&s->model1, x0, x1, _state); - return result; - } - if( s->modelversion==2 ) - { - result = rbfv2calc2(&s->model2, x0, x1, _state); - return result; - } - ae_assert(ae_false, "RBFCalc2: integrity check failed", _state); - return result; -} - - -/************************************************************************* -This function calculates value of the RBF model in the given point. - -This function should be used when we have NY=1 (scalar function) and NX=3 -(3-dimensional space). If you have 2-dimensional space, use rbfcalc2(). If -you have general situation (NX-dimensional space, NY-dimensional function) -you should use generic rbfcalc(). - -If you want to calculate function values many times, consider using -rbfgridcalc3v(), which is far more efficient than many subsequent calls to -rbfcalc3(). - -If you want to perform parallel model evaluation from multiple threads, -use rbftscalcbuf() with per-thread buffer object. - -This function returns 0.0 when: -* model is not initialized -* NX<>3 - *NY<>1 - -INPUT PARAMETERS: - S - RBF model - X0 - first coordinate, finite number - X1 - second coordinate, finite number - X2 - third coordinate, finite number - -RESULT: - value of the model or 0.0 (as defined above) - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -double rbfcalc3(rbfmodel* s, - double x0, - double x1, - double x2, - ae_state *_state) -{ - double result; - - - ae_assert(ae_isfinite(x0, _state), "RBFCalc3: invalid value for X0 (X0 is Inf or NaN)!", _state); - ae_assert(ae_isfinite(x1, _state), "RBFCalc3: invalid value for X1 (X1 is Inf or NaN)!", _state); - ae_assert(ae_isfinite(x2, _state), "RBFCalc3: invalid value for X2 (X2 is Inf or NaN)!", _state); - result = (double)(0); - if( s->ny!=1||s->nx!=3 ) - { - return result; - } - if( s->modelversion==1 ) - { - result = rbfv1calc3(&s->model1, x0, x1, x2, _state); - return result; - } - if( s->modelversion==2 ) - { - result = rbfv2calc3(&s->model2, x0, x1, x2, _state); - return result; - } - ae_assert(ae_false, "RBFCalc3: integrity check failed", _state); - return result; -} - - -/************************************************************************* -This function calculates values of the RBF model at the given point. - -This is general function which can be used for arbitrary NX (dimension of -the space of arguments) and NY (dimension of the function itself). However -when you have NY=1 you may find more convenient to use rbfcalc2() or -rbfcalc3(). - -If you want to perform parallel model evaluation from multiple threads, -use rbftscalcbuf() with per-thread buffer object. - -This function returns 0.0 when model is not initialized. - -INPUT PARAMETERS: - S - RBF model - X - coordinates, array[NX]. - X may have more than NX elements, in this case only - leading NX will be used. - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is out-parameter and - reallocated after call to this function. In case you want - to reuse previously allocated Y, you may use RBFCalcBuf(), - which reallocates Y only when it is too small. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfcalc(rbfmodel* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - - ae_vector_clear(y); - - ae_assert(x->cnt>=s->nx, "RBFCalc: Length(X)nx, _state), "RBFCalc: X contains infinite or NaN values", _state); - rbfcalcbuf(s, x, y, _state); -} - - -/************************************************************************* -This function calculates values of the RBF model at the given point. - -Same as rbfcalc(), but does not reallocate Y when in is large enough to -store function values. - -If you want to perform parallel model evaluation from multiple threads, -use rbftscalcbuf() with per-thread buffer object. - -INPUT PARAMETERS: - S - RBF model - X - coordinates, array[NX]. - X may have more than NX elements, in this case only - leading NX will be used. - Y - possibly preallocated array - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is not reallocated when it - is larger than NY. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfcalcbuf(rbfmodel* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(x->cnt>=s->nx, "RBFCalcBuf: Length(X)nx, _state), "RBFCalcBuf: X contains infinite or NaN values", _state); - if( y->cntny ) - { - ae_vector_set_length(y, s->ny, _state); - } - for(i=0; i<=s->ny-1; i++) - { - y->ptr.p_double[i] = (double)(0); - } - if( s->modelversion==1 ) - { - rbfv1calcbuf(&s->model1, x, y, _state); - return; - } - if( s->modelversion==2 ) - { - rbfv2calcbuf(&s->model2, x, y, _state); - return; - } - ae_assert(ae_false, "RBFCalcBuf: integrity check failed", _state); -} - - -/************************************************************************* -This function calculates values of the RBF model at the given point, using -external buffer object (internal temporaries of RBF model are not -modified). - -This function allows to use same RBF model object in different threads, -assuming that different threads use different instances of buffer -structure. - -INPUT PARAMETERS: - S - RBF model, may be shared between different threads - Buf - buffer object created for this particular instance of RBF - model with rbfcreatecalcbuffer(). - X - coordinates, array[NX]. - X may have more than NX elements, in this case only - leading NX will be used. - Y - possibly preallocated array - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is not reallocated when it - is larger than NY. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbftscalcbuf(rbfmodel* s, - rbfcalcbuffer* buf, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(x->cnt>=s->nx, "RBFCalcBuf: Length(X)nx, _state), "RBFCalcBuf: X contains infinite or NaN values", _state); - ae_assert(s->modelversion==buf->modelversion, "RBFCalcBuf: buffer object is not compatible with RBF model", _state); - if( y->cntny ) - { - ae_vector_set_length(y, s->ny, _state); - } - for(i=0; i<=s->ny-1; i++) - { - y->ptr.p_double[i] = (double)(0); - } - if( s->modelversion==1 ) - { - rbfv1tscalcbuf(&s->model1, &buf->bufv1, x, y, _state); - return; - } - if( s->modelversion==2 ) - { - rbfv2tscalcbuf(&s->model2, &buf->bufv2, x, y, _state); - return; - } - ae_assert(ae_false, "RBFTsCalcBuf: integrity check failed", _state); -} - - -/************************************************************************* -This is legacy function for gridded calculation of RBF model. - -It is superseded by rbfgridcalc2v() and rbfgridcalc2vsubset() functions. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfgridcalc2(rbfmodel* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_matrix* y, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector cpx0; - ae_vector cpx1; - ae_vector p01; - ae_vector p11; - ae_vector p2; - - ae_frame_make(_state, &_frame_block); - memset(&cpx0, 0, sizeof(cpx0)); - memset(&cpx1, 0, sizeof(cpx1)); - memset(&p01, 0, sizeof(p01)); - memset(&p11, 0, sizeof(p11)); - memset(&p2, 0, sizeof(p2)); - ae_matrix_clear(y); - ae_vector_init(&cpx0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cpx1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p01, 0, DT_INT, _state, ae_true); - ae_vector_init(&p11, 0, DT_INT, _state, ae_true); - ae_vector_init(&p2, 0, DT_INT, _state, ae_true); - - ae_assert(n0>0, "RBFGridCalc2: invalid value for N0 (N0<=0)!", _state); - ae_assert(n1>0, "RBFGridCalc2: invalid value for N1 (N1<=0)!", _state); - ae_assert(x0->cnt>=n0, "RBFGridCalc2: Length(X0)cnt>=n1, "RBFGridCalc2: Length(X1)modelversion==1 ) - { - rbfv1gridcalc2(&s->model1, x0, n0, x1, n1, y, _state); - ae_frame_leave(_state); - return; - } - if( s->modelversion==2 ) - { - rbfv2gridcalc2(&s->model2, x0, n0, x1, n1, y, _state); - ae_frame_leave(_state); - return; - } - ae_assert(ae_false, "RBFGridCalc2: integrity check failed", _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function calculates values of the RBF model at the regular grid, -which has N0*N1 points, with Point[I,J] = (X0[I], X1[J]). Vector-valued -RBF models are supported. - -This function returns 0.0 when: -* model is not initialized -* NX<>2 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: Parallel processing is implemented only for modern (hierarchical) - RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still - processed serially. - -INPUT PARAMETERS: - S - RBF model, used in read-only mode, can be shared between - multiple invocations of this function from multiple - threads. - - X0 - array of grid nodes, first coordinates, array[N0]. - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N0 - grid size (number of nodes) in the first dimension - - X1 - array of grid nodes, second coordinates, array[N1] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N1 - grid size (number of nodes) in the second dimension - -OUTPUT PARAMETERS: - Y - function values, array[NY*N0*N1], where NY is a number of - "output" vector values (this function supports vector- - valued RBF models). Y is out-variable and is reallocated - by this function. - Y[K+NY*(I0+I1*N0)]=F_k(X0[I0],X1[I1]), for: - * K=0...NY-1 - * I0=0...N0-1 - * I1=0...N1-1 - -NOTE: this function supports weakly ordered grid nodes, i.e. you may have - X[i]=X[i+1] for some i. It does not provide you any performance - benefits due to duplication of points, just convenience and - flexibility. - -NOTE: this function is re-entrant, i.e. you may use same rbfmodel - structure in multiple threads calling this function for different - grids. - -NOTE: if you need function values on some subset of regular grid, which - may be described as "several compact and dense islands", you may - use rbfgridcalc2vsubset(). - - -- ALGLIB -- - Copyright 27.01.2017 by Bochkanov Sergey -*************************************************************************/ -void rbfgridcalc2v(rbfmodel* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_vector dummy; - - ae_frame_make(_state, &_frame_block); - memset(&dummy, 0, sizeof(dummy)); - ae_vector_clear(y); - ae_vector_init(&dummy, 0, DT_BOOL, _state, ae_true); - - ae_assert(n0>0, "RBFGridCalc2V: invalid value for N0 (N0<=0)!", _state); - ae_assert(n1>0, "RBFGridCalc2V: invalid value for N1 (N1<=0)!", _state); - ae_assert(x0->cnt>=n0, "RBFGridCalc2V: Length(X0)cnt>=n1, "RBFGridCalc2V: Length(X1)ptr.p_double[i],x0->ptr.p_double[i+1]), "RBFGridCalc2V: X0 is not ordered by ascending", _state); - } - for(i=0; i<=n1-2; i++) - { - ae_assert(ae_fp_less_eq(x1->ptr.p_double[i],x1->ptr.p_double[i+1]), "RBFGridCalc2V: X1 is not ordered by ascending", _state); - } - rbfgridcalc2vx(s, x0, n0, x1, n1, &dummy, ae_false, y, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function calculates values of the RBF model at some subset of regular -grid: -* grid has N0*N1 points, with Point[I,J] = (X0[I], X1[J]) -* only values at some subset of this grid are required -Vector-valued RBF models are supported. - -This function returns 0.0 when: -* model is not initialized -* NX<>2 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: Parallel processing is implemented only for modern (hierarchical) - RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still - processed serially. - -INPUT PARAMETERS: - S - RBF model, used in read-only mode, can be shared between - multiple invocations of this function from multiple - threads. - - X0 - array of grid nodes, first coordinates, array[N0]. - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N0 - grid size (number of nodes) in the first dimension - - X1 - array of grid nodes, second coordinates, array[N1] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N1 - grid size (number of nodes) in the second dimension - - FlagY - array[N0*N1]: - * Y[I0+I1*N0] corresponds to node (X0[I0],X1[I1]) - * it is a "bitmap" array which contains False for nodes - which are NOT calculated, and True for nodes which are - required. - -OUTPUT PARAMETERS: - Y - function values, array[NY*N0*N1*N2], where NY is a number - of "output" vector values (this function supports vector- - valued RBF models): - * Y[K+NY*(I0+I1*N0)]=F_k(X0[I0],X1[I1]), - for K=0...NY-1, I0=0...N0-1, I1=0...N1-1. - * elements of Y[] which correspond to FlagY[]=True are - loaded by model values (which may be exactly zero for - some nodes). - * elements of Y[] which correspond to FlagY[]=False MAY be - initialized by zeros OR may be calculated. This function - processes grid as a hierarchy of nested blocks and - micro-rows. If just one element of micro-row is required, - entire micro-row (up to 8 nodes in the current version, - but no promises) is calculated. - -NOTE: this function supports weakly ordered grid nodes, i.e. you may have - X[i]=X[i+1] for some i. It does not provide you any performance - benefits due to duplication of points, just convenience and - flexibility. - -NOTE: this function is re-entrant, i.e. you may use same rbfmodel - structure in multiple threads calling this function for different - grids. - - -- ALGLIB -- - Copyright 04.03.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfgridcalc2vsubset(rbfmodel* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Boolean */ ae_vector* flagy, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - - ae_vector_clear(y); - - ae_assert(n0>0, "RBFGridCalc2VSubset: invalid value for N0 (N0<=0)!", _state); - ae_assert(n1>0, "RBFGridCalc2VSubset: invalid value for N1 (N1<=0)!", _state); - ae_assert(x0->cnt>=n0, "RBFGridCalc2VSubset: Length(X0)cnt>=n1, "RBFGridCalc2VSubset: Length(X1)cnt>=n0*n1, "RBFGridCalc2VSubset: Length(FlagY)ptr.p_double[i],x0->ptr.p_double[i+1]), "RBFGridCalc2VSubset: X0 is not ordered by ascending", _state); - } - for(i=0; i<=n1-2; i++) - { - ae_assert(ae_fp_less_eq(x1->ptr.p_double[i],x1->ptr.p_double[i+1]), "RBFGridCalc2VSubset: X1 is not ordered by ascending", _state); - } - rbfgridcalc2vx(s, x0, n0, x1, n1, flagy, ae_true, y, _state); -} - - -/************************************************************************* -This function calculates values of the RBF model at the regular grid, -which has N0*N1*N2 points, with Point[I,J,K] = (X0[I], X1[J], X2[K]). -Vector-valued RBF models are supported. - -This function returns 0.0 when: -* model is not initialized -* NX<>3 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: Parallel processing is implemented only for modern (hierarchical) - RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still - processed serially. - -INPUT PARAMETERS: - S - RBF model, used in read-only mode, can be shared between - multiple invocations of this function from multiple - threads. - - X0 - array of grid nodes, first coordinates, array[N0]. - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N0 - grid size (number of nodes) in the first dimension - - X1 - array of grid nodes, second coordinates, array[N1] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N1 - grid size (number of nodes) in the second dimension - - X2 - array of grid nodes, third coordinates, array[N2] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N2 - grid size (number of nodes) in the third dimension - -OUTPUT PARAMETERS: - Y - function values, array[NY*N0*N1*N2], where NY is a number - of "output" vector values (this function supports vector- - valued RBF models). Y is out-variable and is reallocated - by this function. - Y[K+NY*(I0+I1*N0+I2*N0*N1)]=F_k(X0[I0],X1[I1],X2[I2]), for: - * K=0...NY-1 - * I0=0...N0-1 - * I1=0...N1-1 - * I2=0...N2-1 - -NOTE: this function supports weakly ordered grid nodes, i.e. you may have - X[i]=X[i+1] for some i. It does not provide you any performance - benefits due to duplication of points, just convenience and - flexibility. - -NOTE: this function is re-entrant, i.e. you may use same rbfmodel - structure in multiple threads calling this function for different - grids. - -NOTE: if you need function values on some subset of regular grid, which - may be described as "several compact and dense islands", you may - use rbfgridcalc3vsubset(). - - -- ALGLIB -- - Copyright 04.03.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfgridcalc3v(rbfmodel* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_vector dummy; - - ae_frame_make(_state, &_frame_block); - memset(&dummy, 0, sizeof(dummy)); - ae_vector_clear(y); - ae_vector_init(&dummy, 0, DT_BOOL, _state, ae_true); - - ae_assert(n0>0, "RBFGridCalc3V: invalid value for N0 (N0<=0)!", _state); - ae_assert(n1>0, "RBFGridCalc3V: invalid value for N1 (N1<=0)!", _state); - ae_assert(n2>0, "RBFGridCalc3V: invalid value for N2 (N2<=0)!", _state); - ae_assert(x0->cnt>=n0, "RBFGridCalc3V: Length(X0)cnt>=n1, "RBFGridCalc3V: Length(X1)cnt>=n2, "RBFGridCalc3V: Length(X2)ptr.p_double[i],x0->ptr.p_double[i+1]), "RBFGridCalc3V: X0 is not ordered by ascending", _state); - } - for(i=0; i<=n1-2; i++) - { - ae_assert(ae_fp_less_eq(x1->ptr.p_double[i],x1->ptr.p_double[i+1]), "RBFGridCalc3V: X1 is not ordered by ascending", _state); - } - for(i=0; i<=n2-2; i++) - { - ae_assert(ae_fp_less_eq(x2->ptr.p_double[i],x2->ptr.p_double[i+1]), "RBFGridCalc3V: X2 is not ordered by ascending", _state); - } - rbfgridcalc3vx(s, x0, n0, x1, n1, x2, n2, &dummy, ae_false, y, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function calculates values of the RBF model at some subset of regular -grid: -* grid has N0*N1*N2 points, with Point[I,J,K] = (X0[I], X1[J], X2[K]) -* only values at some subset of this grid are required -Vector-valued RBF models are supported. - -This function returns 0.0 when: -* model is not initialized -* NX<>3 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: Parallel processing is implemented only for modern (hierarchical) - RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still - processed serially. - -INPUT PARAMETERS: - S - RBF model, used in read-only mode, can be shared between - multiple invocations of this function from multiple - threads. - - X0 - array of grid nodes, first coordinates, array[N0]. - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N0 - grid size (number of nodes) in the first dimension - - X1 - array of grid nodes, second coordinates, array[N1] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N1 - grid size (number of nodes) in the second dimension - - X2 - array of grid nodes, third coordinates, array[N2] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N2 - grid size (number of nodes) in the third dimension - - FlagY - array[N0*N1*N2]: - * Y[I0+I1*N0+I2*N0*N1] corresponds to node (X0[I0],X1[I1],X2[I2]) - * it is a "bitmap" array which contains False for nodes - which are NOT calculated, and True for nodes which are - required. - -OUTPUT PARAMETERS: - Y - function values, array[NY*N0*N1*N2], where NY is a number - of "output" vector values (this function supports vector- - valued RBF models): - * Y[K+NY*(I0+I1*N0+I2*N0*N1)]=F_k(X0[I0],X1[I1],X2[I2]), - for K=0...NY-1, I0=0...N0-1, I1=0...N1-1, I2=0...N2-1. - * elements of Y[] which correspond to FlagY[]=True are - loaded by model values (which may be exactly zero for - some nodes). - * elements of Y[] which correspond to FlagY[]=False MAY be - initialized by zeros OR may be calculated. This function - processes grid as a hierarchy of nested blocks and - micro-rows. If just one element of micro-row is required, - entire micro-row (up to 8 nodes in the current version, - but no promises) is calculated. - -NOTE: this function supports weakly ordered grid nodes, i.e. you may have - X[i]=X[i+1] for some i. It does not provide you any performance - benefits due to duplication of points, just convenience and - flexibility. - -NOTE: this function is re-entrant, i.e. you may use same rbfmodel - structure in multiple threads calling this function for different - grids. - - -- ALGLIB -- - Copyright 04.03.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfgridcalc3vsubset(rbfmodel* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Boolean */ ae_vector* flagy, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - - ae_vector_clear(y); - - ae_assert(n0>0, "RBFGridCalc3VSubset: invalid value for N0 (N0<=0)!", _state); - ae_assert(n1>0, "RBFGridCalc3VSubset: invalid value for N1 (N1<=0)!", _state); - ae_assert(n2>0, "RBFGridCalc3VSubset: invalid value for N2 (N2<=0)!", _state); - ae_assert(x0->cnt>=n0, "RBFGridCalc3VSubset: Length(X0)cnt>=n1, "RBFGridCalc3VSubset: Length(X1)cnt>=n2, "RBFGridCalc3VSubset: Length(X2)cnt>=n0*n1*n2, "RBFGridCalc3VSubset: Length(FlagY)ptr.p_double[i],x0->ptr.p_double[i+1]), "RBFGridCalc3VSubset: X0 is not ordered by ascending", _state); - } - for(i=0; i<=n1-2; i++) - { - ae_assert(ae_fp_less_eq(x1->ptr.p_double[i],x1->ptr.p_double[i+1]), "RBFGridCalc3VSubset: X1 is not ordered by ascending", _state); - } - for(i=0; i<=n2-2; i++) - { - ae_assert(ae_fp_less_eq(x2->ptr.p_double[i],x2->ptr.p_double[i+1]), "RBFGridCalc3VSubset: X2 is not ordered by ascending", _state); - } - rbfgridcalc3vx(s, x0, n0, x1, n1, x2, n2, flagy, ae_true, y, _state); -} - - -/************************************************************************* -This function, depending on SparseY, acts as RBFGridCalc2V (SparseY=False) -or RBFGridCalc2VSubset (SparseY=True) function. See comments for these -functions for more information - - -- ALGLIB -- - Copyright 04.03.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfgridcalc2vx(rbfmodel* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Boolean */ ae_vector* flagy, - ae_bool sparsey, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nx; - ae_int_t ny; - ae_int_t ylen; - hqrndstate rs; - ae_vector dummyx2; - ae_vector dummyx3; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t l; - ae_vector tx; - ae_vector ty; - ae_int_t dstoffs; - rbfcalcbuffer calcbuf; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - memset(&dummyx2, 0, sizeof(dummyx2)); - memset(&dummyx3, 0, sizeof(dummyx3)); - memset(&tx, 0, sizeof(tx)); - memset(&ty, 0, sizeof(ty)); - memset(&calcbuf, 0, sizeof(calcbuf)); - _hqrndstate_init(&rs, _state, ae_true); - ae_vector_init(&dummyx2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dummyx3, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ty, 0, DT_REAL, _state, ae_true); - _rbfcalcbuffer_init(&calcbuf, _state, ae_true); - - ae_assert(n0>0, "RBFGridCalc2VX: invalid value for N0 (N0<=0)!", _state); - ae_assert(n1>0, "RBFGridCalc2VX: invalid value for N1 (N1<=0)!", _state); - ae_assert(x0->cnt>=n0, "RBFGridCalc2VX: Length(X0)cnt>=n1, "RBFGridCalc2VX: Length(X1)ptr.p_double[i],x0->ptr.p_double[i+1]), "RBFGridCalc2VX: X0 is not ordered by ascending", _state); - } - for(i=0; i<=n1-2; i++) - { - ae_assert(ae_fp_less_eq(x1->ptr.p_double[i],x1->ptr.p_double[i+1]), "RBFGridCalc2VX: X1 is not ordered by ascending", _state); - } - - /* - * Prepare local variables - */ - nx = s->nx; - ny = s->ny; - hqrndseed(325, 46345, &rs, _state); - - /* - * Prepare output array - */ - ylen = ny*n0*n1; - ae_vector_set_length(y, ylen, _state); - for(i=0; i<=ylen-1; i++) - { - y->ptr.p_double[i] = (double)(0); - } - if( s->nx!=2 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Process V2 model - */ - if( s->modelversion==2 ) - { - ae_vector_set_length(&dummyx2, 1, _state); - dummyx2.ptr.p_double[0] = (double)(0); - ae_vector_set_length(&dummyx3, 1, _state); - dummyx3.ptr.p_double[0] = (double)(0); - rbfv2gridcalcvx(&s->model2, x0, n0, x1, n1, &dummyx2, 1, &dummyx3, 1, flagy, sparsey, y, _state); - ae_frame_leave(_state); - return; - } - - /* - * Reference code for V1 models - */ - if( s->modelversion==1 ) - { - ae_vector_set_length(&tx, nx, _state); - rbfcreatecalcbuffer(s, &calcbuf, _state); - for(i=0; i<=n0-1; i++) - { - for(j=0; j<=n1-1; j++) - { - k = i+j*n0; - dstoffs = ny*k; - if( sparsey&&!flagy->ptr.p_bool[k] ) - { - for(l=0; l<=ny-1; l++) - { - y->ptr.p_double[l+dstoffs] = (double)(0); - } - continue; - } - tx.ptr.p_double[0] = x0->ptr.p_double[i]; - tx.ptr.p_double[1] = x1->ptr.p_double[j]; - rbftscalcbuf(s, &calcbuf, &tx, &ty, _state); - for(l=0; l<=ny-1; l++) - { - y->ptr.p_double[l+dstoffs] = ty.ptr.p_double[l]; - } - } - } - ae_frame_leave(_state); - return; - } - - /* - * Unknown model - */ - ae_assert(ae_false, "RBFGradCalc3VX: integrity check failed", _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function, depending on SparseY, acts as RBFGridCalc3V (SparseY=False) -or RBFGridCalc3VSubset (SparseY=True) function. See comments for these -functions for more information - - -- ALGLIB -- - Copyright 04.03.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfgridcalc3vx(rbfmodel* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Boolean */ ae_vector* flagy, - ae_bool sparsey, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t ylen; - ae_int_t nx; - ae_int_t ny; - double rmax; - ae_vector blocks0; - ae_vector blocks1; - ae_vector blocks2; - ae_int_t blockscnt0; - ae_int_t blockscnt1; - ae_int_t blockscnt2; - double blockwidth; - double searchradius; - double avgfuncpernode; - ae_int_t ntrials; - ae_int_t maxblocksize; - gridcalc3v1buf bufseedv1; - ae_shared_pool bufpool; - hqrndstate rs; - ae_vector dummyx3; - - ae_frame_make(_state, &_frame_block); - memset(&blocks0, 0, sizeof(blocks0)); - memset(&blocks1, 0, sizeof(blocks1)); - memset(&blocks2, 0, sizeof(blocks2)); - memset(&bufseedv1, 0, sizeof(bufseedv1)); - memset(&bufpool, 0, sizeof(bufpool)); - memset(&rs, 0, sizeof(rs)); - memset(&dummyx3, 0, sizeof(dummyx3)); - ae_vector_init(&blocks0, 0, DT_INT, _state, ae_true); - ae_vector_init(&blocks1, 0, DT_INT, _state, ae_true); - ae_vector_init(&blocks2, 0, DT_INT, _state, ae_true); - _gridcalc3v1buf_init(&bufseedv1, _state, ae_true); - ae_shared_pool_init(&bufpool, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - ae_vector_init(&dummyx3, 0, DT_REAL, _state, ae_true); - - ae_assert(n0>0, "RBFGridCalc3V: invalid value for N0 (N0<=0)!", _state); - ae_assert(n1>0, "RBFGridCalc3V: invalid value for N1 (N1<=0)!", _state); - ae_assert(n2>0, "RBFGridCalc3V: invalid value for N2 (N2<=0)!", _state); - ae_assert(x0->cnt>=n0, "RBFGridCalc3V: Length(X0)cnt>=n1, "RBFGridCalc3V: Length(X1)cnt>=n2, "RBFGridCalc3V: Length(X2)ptr.p_double[i],x0->ptr.p_double[i+1]), "RBFGridCalc3V: X0 is not ordered by ascending", _state); - } - for(i=0; i<=n1-2; i++) - { - ae_assert(ae_fp_less_eq(x1->ptr.p_double[i],x1->ptr.p_double[i+1]), "RBFGridCalc3V: X1 is not ordered by ascending", _state); - } - for(i=0; i<=n2-2; i++) - { - ae_assert(ae_fp_less_eq(x2->ptr.p_double[i],x2->ptr.p_double[i+1]), "RBFGridCalc3V: X2 is not ordered by ascending", _state); - } - - /* - * Prepare local variables - */ - nx = s->nx; - ny = s->ny; - hqrndseed(325, 46345, &rs, _state); - - /* - * Prepare output array - */ - ylen = ny*n0*n1*n2; - ae_vector_set_length(y, ylen, _state); - for(i=0; i<=ylen-1; i++) - { - y->ptr.p_double[i] = (double)(0); - } - if( s->nx!=3 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Process V1 model - */ - if( s->modelversion==1 ) - { - - /* - * Fast exit for models without centers - */ - if( s->model1.nc==0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Prepare seed, create shared pool of temporary buffers - */ - ae_vector_set_length(&bufseedv1.cx, nx, _state); - ae_vector_set_length(&bufseedv1.tx, nx, _state); - ae_vector_set_length(&bufseedv1.ty, ny, _state); - ae_vector_set_length(&bufseedv1.expbuf0, n0, _state); - ae_vector_set_length(&bufseedv1.expbuf1, n1, _state); - ae_vector_set_length(&bufseedv1.expbuf2, n2, _state); - kdtreecreaterequestbuffer(&s->model1.tree, &bufseedv1.requestbuf, _state); - ae_shared_pool_set_seed(&bufpool, &bufseedv1, sizeof(bufseedv1), _gridcalc3v1buf_init, _gridcalc3v1buf_init_copy, _gridcalc3v1buf_destroy, _state); - - /* - * Analyze input grid: - * * analyze average number of basis functions per grid node - * * partition grid in into blocks - */ - rmax = s->model1.rmax; - blockwidth = 2*rmax; - maxblocksize = 8; - searchradius = rmax*rbf_rbffarradius+0.5*ae_sqrt((double)(s->nx), _state)*blockwidth; - ntrials = 100; - avgfuncpernode = 0.0; - for(i=0; i<=ntrials-1; i++) - { - bufseedv1.tx.ptr.p_double[0] = x0->ptr.p_double[hqrnduniformi(&rs, n0, _state)]; - bufseedv1.tx.ptr.p_double[1] = x1->ptr.p_double[hqrnduniformi(&rs, n1, _state)]; - bufseedv1.tx.ptr.p_double[2] = x2->ptr.p_double[hqrnduniformi(&rs, n2, _state)]; - avgfuncpernode = avgfuncpernode+(double)kdtreetsqueryrnn(&s->model1.tree, &bufseedv1.requestbuf, &bufseedv1.tx, searchradius, ae_true, _state)/(double)ntrials; - } - ae_vector_set_length(&blocks0, n0+1, _state); - blockscnt0 = 0; - blocks0.ptr.p_int[0] = 0; - for(i=1; i<=n0-1; i++) - { - if( ae_fp_greater(x0->ptr.p_double[i]-x0->ptr.p_double[blocks0.ptr.p_int[blockscnt0]],blockwidth)||i-blocks0.ptr.p_int[blockscnt0]>=maxblocksize ) - { - inc(&blockscnt0, _state); - blocks0.ptr.p_int[blockscnt0] = i; - } - } - inc(&blockscnt0, _state); - blocks0.ptr.p_int[blockscnt0] = n0; - ae_vector_set_length(&blocks1, n1+1, _state); - blockscnt1 = 0; - blocks1.ptr.p_int[0] = 0; - for(i=1; i<=n1-1; i++) - { - if( ae_fp_greater(x1->ptr.p_double[i]-x1->ptr.p_double[blocks1.ptr.p_int[blockscnt1]],blockwidth)||i-blocks1.ptr.p_int[blockscnt1]>=maxblocksize ) - { - inc(&blockscnt1, _state); - blocks1.ptr.p_int[blockscnt1] = i; - } - } - inc(&blockscnt1, _state); - blocks1.ptr.p_int[blockscnt1] = n1; - ae_vector_set_length(&blocks2, n2+1, _state); - blockscnt2 = 0; - blocks2.ptr.p_int[0] = 0; - for(i=1; i<=n2-1; i++) - { - if( ae_fp_greater(x2->ptr.p_double[i]-x2->ptr.p_double[blocks2.ptr.p_int[blockscnt2]],blockwidth)||i-blocks2.ptr.p_int[blockscnt2]>=maxblocksize ) - { - inc(&blockscnt2, _state); - blocks2.ptr.p_int[blockscnt2] = i; - } - } - inc(&blockscnt2, _state); - blocks2.ptr.p_int[blockscnt2] = n2; - - /* - * Perform calculation in multithreaded mode - */ - rbfv1gridcalc3vrec(&s->model1, x0, n0, x1, n1, x2, n2, &blocks0, 0, blockscnt0, &blocks1, 0, blockscnt1, &blocks2, 0, blockscnt2, flagy, sparsey, searchradius, avgfuncpernode, &bufpool, y, _state); - - /* - * Done - */ - ae_frame_leave(_state); - return; - } - - /* - * Process V2 model - */ - if( s->modelversion==2 ) - { - ae_vector_set_length(&dummyx3, 1, _state); - dummyx3.ptr.p_double[0] = (double)(0); - rbfv2gridcalcvx(&s->model2, x0, n0, x1, n1, x2, n2, &dummyx3, 1, flagy, sparsey, y, _state); - ae_frame_leave(_state); - return; - } - - /* - * Unknown model - */ - ae_assert(ae_false, "RBFGradCalc3VX: integrity check failed", _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function "unpacks" RBF model by extracting its coefficients. - -INPUT PARAMETERS: - S - RBF model - -OUTPUT PARAMETERS: - NX - dimensionality of argument - NY - dimensionality of the target function - XWR - model information, array[NC,NX+NY+1]. - One row of the array corresponds to one basis function: - * first NX columns - coordinates of the center - * next NY columns - weights, one per dimension of the - function being modelled - For ModelVersion=1: - * last column - radius, same for all dimensions of - the function being modelled - For ModelVersion=2: - * last NX columns - radii, one per dimension - NC - number of the centers - V - polynomial term , array[NY,NX+1]. One row per one - dimension of the function being modelled. First NX - elements are linear coefficients, V[NX] is equal to the - constant part. - ModelVersion-version of the RBF model: - * 1 - for models created by QNN and RBF-ML algorithms, - compatible with ALGLIB 3.10 or earlier. - * 2 - for models created by HierarchicalRBF, requires - ALGLIB 3.11 or later - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfunpack(rbfmodel* s, - ae_int_t* nx, - ae_int_t* ny, - /* Real */ ae_matrix* xwr, - ae_int_t* nc, - /* Real */ ae_matrix* v, - ae_int_t* modelversion, - ae_state *_state) -{ - - *nx = 0; - *ny = 0; - ae_matrix_clear(xwr); - *nc = 0; - ae_matrix_clear(v); - *modelversion = 0; - - if( s->modelversion==1 ) - { - *modelversion = 1; - rbfv1unpack(&s->model1, nx, ny, xwr, nc, v, _state); - return; - } - if( s->modelversion==2 ) - { - *modelversion = 2; - rbfv2unpack(&s->model2, nx, ny, xwr, nc, v, _state); - return; - } - ae_assert(ae_false, "RBFUnpack: integrity check failure", _state); -} - - -/************************************************************************* -This function returns model version. - -INPUT PARAMETERS: - S - RBF model - -RESULT: - * 1 - for models created by QNN and RBF-ML algorithms, - compatible with ALGLIB 3.10 or earlier. - * 2 - for models created by HierarchicalRBF, requires - ALGLIB 3.11 or later - - -- ALGLIB -- - Copyright 06.07.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t rbfgetmodelversion(rbfmodel* s, ae_state *_state) -{ - ae_int_t result; - - - result = s->modelversion; - return result; -} - - -/************************************************************************* -This function is used to peek into hierarchical RBF construction process -from some other thread and get current progress indicator. It returns -value in [0,1]. - -IMPORTANT: only HRBFs (hierarchical RBFs) support peeking into progress - indicator. Legacy RBF-ML and RBF-QNN do not support it. You - will always get 0 value. - -INPUT PARAMETERS: - S - RBF model object - -RESULT: - progress value, in [0,1] - - -- ALGLIB -- - Copyright 17.11.2018 by Bochkanov Sergey -*************************************************************************/ -double rbfpeekprogress(rbfmodel* s, ae_state *_state) -{ - double result; - - - result = (double)s->progress10000/(double)10000; - return result; -} - - -/************************************************************************* -This function is used to submit a request for termination of the -hierarchical RBF construction process from some other thread. As result, -RBF construction is terminated smoothly (with proper deallocation of all -necessary resources) and resultant model is filled by zeros. - -A rep.terminationtype=8 will be returned upon receiving such request. - -IMPORTANT: only HRBFs (hierarchical RBFs) support termination requests. - Legacy RBF-ML and RBF-QNN do not support it. An attempt to - terminate their construction will be ignored. - -IMPORTANT: termination request flag is cleared when the model construction - starts. Thus, any pre-construction termination requests will be - silently ignored - only ones submitted AFTER construction has - actually began will be handled. - -INPUT PARAMETERS: - S - RBF model object - - -- ALGLIB -- - Copyright 17.11.2018 by Bochkanov Sergey -*************************************************************************/ -void rbfrequesttermination(rbfmodel* s, ae_state *_state) -{ - - - s->terminationrequest = ae_true; -} - - -/************************************************************************* -Serializer: allocation - - -- ALGLIB -- - Copyright 02.02.2012 by Bochkanov Sergey -*************************************************************************/ -void rbfalloc(ae_serializer* s, rbfmodel* model, ae_state *_state) -{ - - - - /* - * Header - */ - ae_serializer_alloc_entry(s); - - /* - * V1 model - */ - if( model->modelversion==1 ) - { - - /* - * Header - */ - ae_serializer_alloc_entry(s); - rbfv1alloc(s, &model->model1, _state); - return; - } - - /* - * V2 model - */ - if( model->modelversion==2 ) - { - - /* - * Header - */ - ae_serializer_alloc_entry(s); - rbfv2alloc(s, &model->model2, _state); - return; - } - ae_assert(ae_false, "Assertion failed", _state); -} - - -/************************************************************************* -Serializer: serialization - - -- ALGLIB -- - Copyright 02.02.2012 by Bochkanov Sergey -*************************************************************************/ -void rbfserialize(ae_serializer* s, rbfmodel* model, ae_state *_state) -{ - - - - /* - * Header - */ - ae_serializer_serialize_int(s, getrbfserializationcode(_state), _state); - - /* - * V1 model - */ - if( model->modelversion==1 ) - { - ae_serializer_serialize_int(s, rbf_rbffirstversion, _state); - rbfv1serialize(s, &model->model1, _state); - return; - } - - /* - * V2 model - */ - if( model->modelversion==2 ) - { - - /* - * Header - */ - ae_serializer_serialize_int(s, rbf_rbfversion2, _state); - rbfv2serialize(s, &model->model2, _state); - return; - } - ae_assert(ae_false, "Assertion failed", _state); -} - - -/************************************************************************* -Serializer: unserialization - - -- ALGLIB -- - Copyright 02.02.2012 by Bochkanov Sergey -*************************************************************************/ -void rbfunserialize(ae_serializer* s, rbfmodel* model, ae_state *_state) -{ - ae_int_t i0; - ae_int_t i1; - - _rbfmodel_clear(model); - - rbf_rbfpreparenonserializablefields(model, _state); - - /* - * Header - */ - ae_serializer_unserialize_int(s, &i0, _state); - ae_assert(i0==getrbfserializationcode(_state), "RBFUnserialize: stream header corrupted", _state); - ae_serializer_unserialize_int(s, &i1, _state); - ae_assert(i1==rbf_rbffirstversion||i1==rbf_rbfversion2, "RBFUnserialize: stream header corrupted", _state); - - /* - * V1 model - */ - if( i1==rbf_rbffirstversion ) - { - rbfv1unserialize(s, &model->model1, _state); - model->modelversion = 1; - model->ny = model->model1.ny; - model->nx = model->model1.nx; - rbf_initializev2(model->nx, model->ny, &model->model2, _state); - return; - } - - /* - * V2 model - */ - if( i1==rbf_rbfversion2 ) - { - rbfv2unserialize(s, &model->model2, _state); - model->modelversion = 2; - model->ny = model->model2.ny; - model->nx = model->model2.nx; - rbf_initializev1(model->nx, model->ny, &model->model1, _state); - return; - } - ae_assert(ae_false, "Assertion failed", _state); -} - - -/************************************************************************* -Initialize empty model - - -- ALGLIB -- - Copyright 12.05.2016 by Bochkanov Sergey -*************************************************************************/ -static void rbf_rbfpreparenonserializablefields(rbfmodel* s, - ae_state *_state) -{ - - - s->n = 0; - s->hasscale = ae_false; - s->radvalue = (double)(1); - s->radzvalue = (double)(5); - s->nlayers = 0; - s->lambdav = (double)(0); - s->aterm = 1; - s->algorithmtype = 0; - s->epsort = rbf_eps; - s->epserr = rbf_eps; - s->maxits = 0; - s->nnmaxits = 100; -} - - -/************************************************************************* -Initialize V1 model (skip initialization for NX=1 or NX>3) - - -- ALGLIB -- - Copyright 12.05.2016 by Bochkanov Sergey -*************************************************************************/ -static void rbf_initializev1(ae_int_t nx, - ae_int_t ny, - rbfv1model* s, - ae_state *_state) -{ - - _rbfv1model_clear(s); - - if( nx==2||nx==3 ) - { - rbfv1create(nx, ny, s, _state); - } -} - - -/************************************************************************* -Initialize V2 model - - -- ALGLIB -- - Copyright 12.05.2016 by Bochkanov Sergey -*************************************************************************/ -static void rbf_initializev2(ae_int_t nx, - ae_int_t ny, - rbfv2model* s, - ae_state *_state) -{ - - _rbfv2model_clear(s); - - rbfv2create(nx, ny, s, _state); -} - - -/************************************************************************* -Cleans report fields - - -- ALGLIB -- - Copyright 16.06.2016 by Bochkanov Sergey -*************************************************************************/ -static void rbf_clearreportfields(rbfreport* rep, ae_state *_state) -{ - - - rep->rmserror = _state->v_nan; - rep->maxerror = _state->v_nan; - rep->arows = 0; - rep->acols = 0; - rep->annz = 0; - rep->iterationscount = 0; - rep->nmv = 0; - rep->terminationtype = 0; -} - - -void _rbfcalcbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - rbfcalcbuffer *p = (rbfcalcbuffer*)_p; - ae_touch_ptr((void*)p); - _rbfv1calcbuffer_init(&p->bufv1, _state, make_automatic); - _rbfv2calcbuffer_init(&p->bufv2, _state, make_automatic); -} - - -void _rbfcalcbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - rbfcalcbuffer *dst = (rbfcalcbuffer*)_dst; - rbfcalcbuffer *src = (rbfcalcbuffer*)_src; - dst->modelversion = src->modelversion; - _rbfv1calcbuffer_init_copy(&dst->bufv1, &src->bufv1, _state, make_automatic); - _rbfv2calcbuffer_init_copy(&dst->bufv2, &src->bufv2, _state, make_automatic); -} - - -void _rbfcalcbuffer_clear(void* _p) -{ - rbfcalcbuffer *p = (rbfcalcbuffer*)_p; - ae_touch_ptr((void*)p); - _rbfv1calcbuffer_clear(&p->bufv1); - _rbfv2calcbuffer_clear(&p->bufv2); -} - - -void _rbfcalcbuffer_destroy(void* _p) -{ - rbfcalcbuffer *p = (rbfcalcbuffer*)_p; - ae_touch_ptr((void*)p); - _rbfv1calcbuffer_destroy(&p->bufv1); - _rbfv2calcbuffer_destroy(&p->bufv2); -} - - -void _rbfmodel_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - rbfmodel *p = (rbfmodel*)_p; - ae_touch_ptr((void*)p); - _rbfv1model_init(&p->model1, _state, make_automatic); - _rbfv2model_init(&p->model2, _state, make_automatic); - ae_matrix_init(&p->x, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->y, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic); -} - - -void _rbfmodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - rbfmodel *dst = (rbfmodel*)_dst; - rbfmodel *src = (rbfmodel*)_src; - dst->nx = src->nx; - dst->ny = src->ny; - dst->modelversion = src->modelversion; - _rbfv1model_init_copy(&dst->model1, &src->model1, _state, make_automatic); - _rbfv2model_init_copy(&dst->model2, &src->model2, _state, make_automatic); - dst->lambdav = src->lambdav; - dst->radvalue = src->radvalue; - dst->radzvalue = src->radzvalue; - dst->nlayers = src->nlayers; - dst->aterm = src->aterm; - dst->algorithmtype = src->algorithmtype; - dst->epsort = src->epsort; - dst->epserr = src->epserr; - dst->maxits = src->maxits; - dst->nnmaxits = src->nnmaxits; - dst->n = src->n; - ae_matrix_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_matrix_init_copy(&dst->y, &src->y, _state, make_automatic); - dst->hasscale = src->hasscale; - ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic); - dst->progress10000 = src->progress10000; - dst->terminationrequest = src->terminationrequest; -} - - -void _rbfmodel_clear(void* _p) -{ - rbfmodel *p = (rbfmodel*)_p; - ae_touch_ptr((void*)p); - _rbfv1model_clear(&p->model1); - _rbfv2model_clear(&p->model2); - ae_matrix_clear(&p->x); - ae_matrix_clear(&p->y); - ae_vector_clear(&p->s); -} - - -void _rbfmodel_destroy(void* _p) -{ - rbfmodel *p = (rbfmodel*)_p; - ae_touch_ptr((void*)p); - _rbfv1model_destroy(&p->model1); - _rbfv2model_destroy(&p->model2); - ae_matrix_destroy(&p->x); - ae_matrix_destroy(&p->y); - ae_vector_destroy(&p->s); -} - - -void _rbfreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - rbfreport *p = (rbfreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _rbfreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - rbfreport *dst = (rbfreport*)_dst; - rbfreport *src = (rbfreport*)_src; - dst->rmserror = src->rmserror; - dst->maxerror = src->maxerror; - dst->arows = src->arows; - dst->acols = src->acols; - dst->annz = src->annz; - dst->iterationscount = src->iterationscount; - dst->nmv = src->nmv; - dst->terminationtype = src->terminationtype; -} - - -void _rbfreport_clear(void* _p) -{ - rbfreport *p = (rbfreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _rbfreport_destroy(void* _p) -{ - rbfreport *p = (rbfreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_INTCOMP) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function is left for backward compatibility. -Use fitspheremc() instead. - - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void nsfitspheremcc(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - /* Real */ ae_vector* cx, - double* rhi, - ae_state *_state) -{ - double dummy; - - ae_vector_clear(cx); - *rhi = 0; - - nsfitspherex(xy, npoints, nx, 1, 0.0, 0, 0.0, cx, &dummy, rhi, _state); -} - - -/************************************************************************* -This function is left for backward compatibility. -Use fitspheremi() instead. - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void nsfitspheremic(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - /* Real */ ae_vector* cx, - double* rlo, - ae_state *_state) -{ - double dummy; - - ae_vector_clear(cx); - *rlo = 0; - - nsfitspherex(xy, npoints, nx, 2, 0.0, 0, 0.0, cx, rlo, &dummy, _state); -} - - -/************************************************************************* -This function is left for backward compatibility. -Use fitspheremz() instead. - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void nsfitspheremzc(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - /* Real */ ae_vector* cx, - double* rlo, - double* rhi, - ae_state *_state) -{ - - ae_vector_clear(cx); - *rlo = 0; - *rhi = 0; - - nsfitspherex(xy, npoints, nx, 3, 0.0, 0, 0.0, cx, rlo, rhi, _state); -} - - -/************************************************************************* -This function is left for backward compatibility. -Use fitspherex() instead. - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void nsfitspherex(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - ae_int_t problemtype, - double epsx, - ae_int_t aulits, - double penalty, - /* Real */ ae_vector* cx, - double* rlo, - double* rhi, - ae_state *_state) -{ - - ae_vector_clear(cx); - *rlo = 0; - *rhi = 0; - - fitspherex(xy, npoints, nx, problemtype, epsx, aulits, penalty, cx, rlo, rhi, _state); -} - - -/************************************************************************* -This function is an obsolete and deprecated version of fitting by -penalized cubic spline. - -It was superseded by spline1dfit(), which is an orders of magnitude faster -and more memory-efficient implementation. - -Do NOT use this function in the new code! - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -void spline1dfitpenalized(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t m, - double rho, - ae_int_t* info, - spline1dinterpolant* s, - spline1dfitreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - ae_vector w; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - memset(&w, 0, sizeof(w)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - *info = 0; - _spline1dinterpolant_clear(s); - _spline1dfitreport_clear(rep); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=1, "Spline1DFitPenalized: N<1!", _state); - ae_assert(m>=4, "Spline1DFitPenalized: M<4!", _state); - ae_assert(x->cnt>=n, "Spline1DFitPenalized: Length(X)cnt>=n, "Spline1DFitPenalized: Length(Y)=1, "Spline1DFitPenalizedW: N<1!", _state); - ae_assert(m>=4, "Spline1DFitPenalizedW: M<4!", _state); - ae_assert(x->cnt>=n, "Spline1DFitPenalizedW: Length(X)cnt>=n, "Spline1DFitPenalizedW: Length(Y)cnt>=n, "Spline1DFitPenalizedW: Length(W)ptr.p_double[i]*fcolumn.ptr.p_double[i], _state); - } - fdmax = ae_maxreal(fdmax, v, _state); - - /* - * Fill temporary with second derivatives of basis function - */ - ae_v_move(&d2matrix.ptr.pp_double[b][0], 1, &bd2.ptr.p_double[0], 1, ae_v_len(0,m-1)); - } - - /* - * * calculate penalty matrix A - * * calculate max of diagonal elements of A - * * calculate PDecay - coefficient before penalty matrix - */ - for(i=0; i<=m-1; i++) - { - for(j=i; j<=m-1; j++) - { - - /* - * calculate integral(B_i''*B_j'') where B_i and B_j are - * i-th and j-th basis splines. - * B_i and B_j are piecewise linear functions. - */ - v = (double)(0); - for(b=0; b<=m-2; b++) - { - fa = d2matrix.ptr.pp_double[i][b]; - fb = d2matrix.ptr.pp_double[i][b+1]; - ga = d2matrix.ptr.pp_double[j][b]; - gb = d2matrix.ptr.pp_double[j][b+1]; - v = v+(bx.ptr.p_double[b+1]-bx.ptr.p_double[b])*(fa*ga+(fa*(gb-ga)+ga*(fb-fa))/2+(fb-fa)*(gb-ga)/3); - } - amatrix.ptr.pp_double[i][j] = v; - amatrix.ptr.pp_double[j][i] = v; - } - } - admax = (double)(0); - for(i=0; i<=m-1; i++) - { - admax = ae_maxreal(admax, ae_fabs(amatrix.ptr.pp_double[i][i], _state), _state); - } - pdecay = lambdav*fdmax/admax; - - /* - * Calculate TDecay for Tikhonov regularization - */ - tdecay = fdmax*(1+pdecay)*10*ae_machineepsilon; - - /* - * Prepare system - * - * NOTE: FMatrix is spoiled during this process - */ - for(i=0; i<=n-1; i++) - { - v = w->ptr.p_double[i]; - ae_v_muld(&fmatrix.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v); - } - rmatrixgemm(m, m, n, 1.0, &fmatrix, 0, 0, 1, &fmatrix, 0, 0, 0, 0.0, &nmatrix, 0, 0, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - nmatrix.ptr.pp_double[i][j] = nmatrix.ptr.pp_double[i][j]+pdecay*amatrix.ptr.pp_double[i][j]; - } - } - for(i=0; i<=m-1; i++) - { - nmatrix.ptr.pp_double[i][i] = nmatrix.ptr.pp_double[i][i]+tdecay; - } - for(i=0; i<=m-1; i++) - { - rightpart.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - v = y->ptr.p_double[i]*w->ptr.p_double[i]; - ae_v_addd(&rightpart.ptr.p_double[0], 1, &fmatrix.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v); - } - - /* - * Solve system - */ - if( !spdmatrixcholesky(&nmatrix, m, ae_true, _state) ) - { - *info = -4; - ae_frame_leave(_state); - return; - } - fblscholeskysolve(&nmatrix, 1.0, m, ae_true, &rightpart, &tmp0, _state); - ae_v_move(&c.ptr.p_double[0], 1, &rightpart.ptr.p_double[0], 1, ae_v_len(0,m-1)); - - /* - * add nodes to force linearity outside of the fitting interval - */ - spline1dgriddiffcubic(&bx, &c, m, 2, 0.0, 2, 0.0, &bd1, _state); - ae_vector_set_length(&tx, m+2, _state); - ae_vector_set_length(&ty, m+2, _state); - ae_vector_set_length(&td, m+2, _state); - ae_v_move(&tx.ptr.p_double[1], 1, &bx.ptr.p_double[0], 1, ae_v_len(1,m)); - ae_v_move(&ty.ptr.p_double[1], 1, &rightpart.ptr.p_double[0], 1, ae_v_len(1,m)); - ae_v_move(&td.ptr.p_double[1], 1, &bd1.ptr.p_double[0], 1, ae_v_len(1,m)); - tx.ptr.p_double[0] = tx.ptr.p_double[1]-(tx.ptr.p_double[2]-tx.ptr.p_double[1]); - ty.ptr.p_double[0] = ty.ptr.p_double[1]-td.ptr.p_double[1]*(tx.ptr.p_double[2]-tx.ptr.p_double[1]); - td.ptr.p_double[0] = td.ptr.p_double[1]; - tx.ptr.p_double[m+1] = tx.ptr.p_double[m]+(tx.ptr.p_double[m]-tx.ptr.p_double[m-1]); - ty.ptr.p_double[m+1] = ty.ptr.p_double[m]+td.ptr.p_double[m]*(tx.ptr.p_double[m]-tx.ptr.p_double[m-1]); - td.ptr.p_double[m+1] = td.ptr.p_double[m]; - spline1dbuildhermite(&tx, &ty, &td, m+2, s, _state); - spline1dlintransx(s, 2/(xb-xa), -(xa+xb)/(xb-xa), _state); - spline1dlintransy(s, sb-sa, sa, _state); - *info = 1; - - /* - * Fill report - */ - rep->rmserror = (double)(0); - rep->avgerror = (double)(0); - rep->avgrelerror = (double)(0); - rep->maxerror = (double)(0); - relcnt = (double)(0); - spline1dconvcubic(&bx, &rightpart, m, 2, 0.0, 2, 0.0, x, n, &fcolumn, _state); - for(i=0; i<=n-1; i++) - { - v = (sb-sa)*fcolumn.ptr.p_double[i]+sa; - rep->rmserror = rep->rmserror+ae_sqr(v-yoriginal.ptr.p_double[i], _state); - rep->avgerror = rep->avgerror+ae_fabs(v-yoriginal.ptr.p_double[i], _state); - if( ae_fp_neq(yoriginal.ptr.p_double[i],(double)(0)) ) - { - rep->avgrelerror = rep->avgrelerror+ae_fabs(v-yoriginal.ptr.p_double[i], _state)/ae_fabs(yoriginal.ptr.p_double[i], _state); - relcnt = relcnt+1; - } - rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(v-yoriginal.ptr.p_double[i], _state), _state); - } - rep->rmserror = ae_sqrt(rep->rmserror/n, _state); - rep->avgerror = rep->avgerror/n; - if( ae_fp_neq(relcnt,(double)(0)) ) - { - rep->avgrelerror = rep->avgrelerror/relcnt; - } - ae_frame_leave(_state); -} - - -#endif - -} - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/interpolation.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/interpolation.h deleted file mode 100644 index c33201c..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/interpolation.h +++ /dev/null @@ -1,9957 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifndef _interpolation_pkg_h -#define _interpolation_pkg_h -#include "ap.h" -#include "alglibinternal.h" -#include "alglibmisc.h" -#include "linalg.h" -#include "optimization.h" -#include "solvers.h" -#include "specialfunctions.h" -#include "integration.h" - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (DATATYPES) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_IDW) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_vector x; - ae_vector y; - ae_vector tsyw; - ae_vector tsw; - ae_matrix tsxy; - ae_vector tsdist; - kdtreerequestbuffer requestbuffer; -} idwcalcbuffer; -typedef struct -{ - ae_int_t nx; - ae_int_t ny; - ae_vector globalprior; - ae_int_t algotype; - ae_int_t nlayers; - double r0; - double rdecay; - double lambda0; - double lambdalast; - double lambdadecay; - double shepardp; - kdtree tree; - ae_int_t npoints; - ae_vector shepardxy; - idwcalcbuffer buffer; -} idwmodel; -typedef struct -{ - ae_int_t priortermtype; - ae_vector priortermval; - ae_int_t algotype; - ae_int_t nlayers; - double r0; - double rdecay; - double lambda0; - double lambdalast; - double lambdadecay; - double shepardp; - ae_vector xy; - ae_int_t npoints; - ae_int_t nx; - ae_int_t ny; - ae_matrix tmpxy; - ae_matrix tmplayers; - ae_vector tmptags; - ae_vector tmpdist; - ae_vector tmpx; - ae_vector tmpwy; - ae_vector tmpw; - kdtree tmptree; - ae_vector tmpmean; -} idwbuilder; -typedef struct -{ - double rmserror; - double avgerror; - double maxerror; - double r2; -} idwreport; -#endif -#if defined(AE_COMPILE_RATINT) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t n; - double sy; - ae_vector x; - ae_vector y; - ae_vector w; -} barycentricinterpolant; -#endif -#if defined(AE_COMPILE_FITSPHERE) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t nfev; - ae_int_t iterationscount; -} fitsphereinternalreport; -#endif -#if defined(AE_COMPILE_INTFITSERV) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_SPLINE1D) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_bool periodic; - ae_int_t n; - ae_int_t k; - ae_int_t continuity; - ae_vector x; - ae_vector c; -} spline1dinterpolant; -typedef struct -{ - double taskrcond; - double rmserror; - double avgerror; - double avgrelerror; - double maxerror; -} spline1dfitreport; -#endif -#if defined(AE_COMPILE_PARAMETRIC) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t n; - ae_bool periodic; - ae_vector p; - spline1dinterpolant x; - spline1dinterpolant y; -} pspline2interpolant; -typedef struct -{ - ae_int_t n; - ae_bool periodic; - ae_vector p; - spline1dinterpolant x; - spline1dinterpolant y; - spline1dinterpolant z; -} pspline3interpolant; -#endif -#if defined(AE_COMPILE_SPLINE3D) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t k; - ae_int_t stype; - ae_int_t n; - ae_int_t m; - ae_int_t l; - ae_int_t d; - ae_vector x; - ae_vector y; - ae_vector z; - ae_vector f; -} spline3dinterpolant; -#endif -#if defined(AE_COMPILE_POLINT) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_LSFIT) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - double taskrcond; - double rmserror; - double avgerror; - double avgrelerror; - double maxerror; -} polynomialfitreport; -typedef struct -{ - double taskrcond; - ae_int_t dbest; - double rmserror; - double avgerror; - double avgrelerror; - double maxerror; -} barycentricfitreport; -typedef struct -{ - double taskrcond; - ae_int_t iterationscount; - ae_int_t varidx; - double rmserror; - double avgerror; - double avgrelerror; - double maxerror; - double wrmserror; - ae_matrix covpar; - ae_vector errpar; - ae_vector errcurve; - ae_vector noise; - double r2; -} lsfitreport; -typedef struct -{ - ae_int_t optalgo; - ae_int_t m; - ae_int_t k; - double epsx; - ae_int_t maxits; - double stpmax; - ae_bool xrep; - ae_vector c0; - ae_vector c1; - ae_vector s; - ae_vector bndl; - ae_vector bndu; - ae_matrix taskx; - ae_vector tasky; - ae_int_t npoints; - ae_vector taskw; - ae_int_t nweights; - ae_int_t wkind; - ae_int_t wits; - double diffstep; - double teststep; - ae_matrix cleic; - ae_int_t nec; - ae_int_t nic; - ae_bool xupdated; - ae_bool needf; - ae_bool needfg; - ae_bool needfgh; - ae_int_t pointindex; - ae_vector x; - ae_vector c; - double f; - ae_vector g; - ae_matrix h; - ae_vector wcur; - ae_vector tmpct; - ae_vector tmp; - ae_vector tmpf; - ae_matrix tmpjac; - ae_matrix tmpjacw; - double tmpnoise; - matinvreport invrep; - ae_int_t repiterationscount; - ae_int_t repterminationtype; - ae_int_t repvaridx; - double reprmserror; - double repavgerror; - double repavgrelerror; - double repmaxerror; - double repwrmserror; - lsfitreport rep; - minlmstate optstate; - minlmreport optrep; - ae_int_t prevnpt; - ae_int_t prevalgo; - rcommstate rstate; -} lsfitstate; -#endif -#if defined(AE_COMPILE_RBFV2) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_vector x; - ae_vector curboxmin; - ae_vector curboxmax; - double curdist2; - ae_vector x123; - ae_vector y123; -} rbfv2calcbuffer; -typedef struct -{ - ae_int_t ny; - ae_int_t nx; - ae_int_t bf; - ae_int_t nh; - ae_vector ri; - ae_vector s; - ae_vector kdroots; - ae_vector kdnodes; - ae_vector kdsplits; - ae_vector kdboxmin; - ae_vector kdboxmax; - ae_vector cw; - ae_matrix v; - double lambdareg; - ae_int_t maxits; - double supportr; - ae_int_t basisfunction; - rbfv2calcbuffer calcbuf; -} rbfv2model; -typedef struct -{ - rbfv2calcbuffer calcbuf; - ae_vector cx; - ae_vector rx; - ae_vector ry; - ae_vector tx; - ae_vector ty; - ae_vector rf; -} rbfv2gridcalcbuffer; -typedef struct -{ - ae_int_t terminationtype; - double maxerror; - double rmserror; -} rbfv2report; -#endif -#if defined(AE_COMPILE_SPLINE2D) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t stype; - ae_int_t n; - ae_int_t m; - ae_int_t d; - ae_vector x; - ae_vector y; - ae_vector f; -} spline2dinterpolant; -typedef struct -{ - ae_int_t priorterm; - double priortermval; - ae_int_t areatype; - double xa; - double xb; - double ya; - double yb; - ae_int_t gridtype; - ae_int_t kx; - ae_int_t ky; - double smoothing; - ae_int_t nlayers; - ae_int_t solvertype; - double lambdabase; - ae_vector xy; - ae_int_t npoints; - ae_int_t d; - double sx; - double sy; - ae_bool adddegreeoffreedom; - ae_int_t interfacesize; - ae_int_t lsqrcnt; - ae_int_t maxcoresize; -} spline2dbuilder; -typedef struct -{ - double rmserror; - double avgerror; - double maxerror; - double r2; -} spline2dfitreport; -typedef struct -{ - ae_int_t blockwidth; - ae_int_t kx; - ae_int_t ky; - ae_int_t npoints; - ae_int_t nrows; - ae_int_t ndenserows; - ae_int_t ndensebatches; - ae_int_t d; - ae_int_t maxbatch; - ae_matrix vals; - ae_vector batches; - ae_vector batchbases; - double lambdareg; - ae_vector tmp0; - ae_vector tmp1; - ae_matrix tmp2; -} spline2dxdesignmatrix; -typedef struct -{ - linlsqrstate solver; - linlsqrreport solverrep; - ae_matrix blockata; - ae_matrix trsmbuf2; - ae_matrix cholbuf2; - ae_vector cholbuf1; - ae_vector tmp0; - ae_vector tmp1; -} spline2dblockllsbuf; -typedef struct -{ - spline2dxdesignmatrix xdesignmatrix; - ae_vector tmp0; - ae_vector tmpz; - spline2dfitreport dummyrep; - spline2dinterpolant localmodel; - spline2dblockllsbuf blockllsbuf; -} spline2dfastddmbuf; -#endif -#if defined(AE_COMPILE_RBFV1) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_vector calcbufxcx; - ae_matrix calcbufx; - ae_vector calcbuftags; - kdtreerequestbuffer requestbuffer; -} rbfv1calcbuffer; -typedef struct -{ - ae_int_t ny; - ae_int_t nx; - ae_int_t nc; - ae_int_t nl; - kdtree tree; - ae_matrix xc; - ae_matrix wr; - double rmax; - ae_matrix v; - ae_vector calcbufxcx; - ae_matrix calcbufx; - ae_vector calcbuftags; -} rbfv1model; -typedef struct -{ - ae_vector tx; - ae_vector cx; - ae_vector ty; - ae_vector flag0; - ae_vector flag1; - ae_vector flag2; - ae_vector flag12; - ae_vector expbuf0; - ae_vector expbuf1; - ae_vector expbuf2; - kdtreerequestbuffer requestbuf; - ae_matrix calcbufx; - ae_vector calcbuftags; -} gridcalc3v1buf; -typedef struct -{ - ae_int_t arows; - ae_int_t acols; - ae_int_t annz; - ae_int_t iterationscount; - ae_int_t nmv; - ae_int_t terminationtype; -} rbfv1report; -#endif -#if defined(AE_COMPILE_RBF) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t modelversion; - rbfv1calcbuffer bufv1; - rbfv2calcbuffer bufv2; -} rbfcalcbuffer; -typedef struct -{ - ae_int_t nx; - ae_int_t ny; - ae_int_t modelversion; - rbfv1model model1; - rbfv2model model2; - double lambdav; - double radvalue; - double radzvalue; - ae_int_t nlayers; - ae_int_t aterm; - ae_int_t algorithmtype; - double epsort; - double epserr; - ae_int_t maxits; - ae_int_t nnmaxits; - ae_int_t n; - ae_matrix x; - ae_matrix y; - ae_bool hasscale; - ae_vector s; - ae_int_t progress10000; - ae_bool terminationrequest; -} rbfmodel; -typedef struct -{ - double rmserror; - double maxerror; - ae_int_t arows; - ae_int_t acols; - ae_int_t annz; - ae_int_t iterationscount; - ae_int_t nmv; - ae_int_t terminationtype; -} rbfreport; -#endif -#if defined(AE_COMPILE_INTCOMP) || !defined(AE_PARTIAL_BUILD) -#endif - -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_IDW) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Buffer object which is used to perform evaluation requests in the -multithreaded mode (multiple threads working with same IDW object). - -This object should be created with idwcreatecalcbuffer(). -*************************************************************************/ -class _idwcalcbuffer_owner -{ -public: - _idwcalcbuffer_owner(); - _idwcalcbuffer_owner(const _idwcalcbuffer_owner &rhs); - _idwcalcbuffer_owner& operator=(const _idwcalcbuffer_owner &rhs); - virtual ~_idwcalcbuffer_owner(); - alglib_impl::idwcalcbuffer* c_ptr(); - alglib_impl::idwcalcbuffer* c_ptr() const; -protected: - alglib_impl::idwcalcbuffer *p_struct; -}; -class idwcalcbuffer : public _idwcalcbuffer_owner -{ -public: - idwcalcbuffer(); - idwcalcbuffer(const idwcalcbuffer &rhs); - idwcalcbuffer& operator=(const idwcalcbuffer &rhs); - virtual ~idwcalcbuffer(); - -}; - - -/************************************************************************* -IDW (Inverse Distance Weighting) model object. -*************************************************************************/ -class _idwmodel_owner -{ -public: - _idwmodel_owner(); - _idwmodel_owner(const _idwmodel_owner &rhs); - _idwmodel_owner& operator=(const _idwmodel_owner &rhs); - virtual ~_idwmodel_owner(); - alglib_impl::idwmodel* c_ptr(); - alglib_impl::idwmodel* c_ptr() const; -protected: - alglib_impl::idwmodel *p_struct; -}; -class idwmodel : public _idwmodel_owner -{ -public: - idwmodel(); - idwmodel(const idwmodel &rhs); - idwmodel& operator=(const idwmodel &rhs); - virtual ~idwmodel(); - -}; - - -/************************************************************************* -Builder object used to generate IDW (Inverse Distance Weighting) model. -*************************************************************************/ -class _idwbuilder_owner -{ -public: - _idwbuilder_owner(); - _idwbuilder_owner(const _idwbuilder_owner &rhs); - _idwbuilder_owner& operator=(const _idwbuilder_owner &rhs); - virtual ~_idwbuilder_owner(); - alglib_impl::idwbuilder* c_ptr(); - alglib_impl::idwbuilder* c_ptr() const; -protected: - alglib_impl::idwbuilder *p_struct; -}; -class idwbuilder : public _idwbuilder_owner -{ -public: - idwbuilder(); - idwbuilder(const idwbuilder &rhs); - idwbuilder& operator=(const idwbuilder &rhs); - virtual ~idwbuilder(); - -}; - - -/************************************************************************* -IDW fitting report: - rmserror RMS error - avgerror average error - maxerror maximum error - r2 coefficient of determination, R-squared, 1-RSS/TSS -*************************************************************************/ -class _idwreport_owner -{ -public: - _idwreport_owner(); - _idwreport_owner(const _idwreport_owner &rhs); - _idwreport_owner& operator=(const _idwreport_owner &rhs); - virtual ~_idwreport_owner(); - alglib_impl::idwreport* c_ptr(); - alglib_impl::idwreport* c_ptr() const; -protected: - alglib_impl::idwreport *p_struct; -}; -class idwreport : public _idwreport_owner -{ -public: - idwreport(); - idwreport(const idwreport &rhs); - idwreport& operator=(const idwreport &rhs); - virtual ~idwreport(); - double &rmserror; - double &avgerror; - double &maxerror; - double &r2; - -}; -#endif - -#if defined(AE_COMPILE_RATINT) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Barycentric interpolant. -*************************************************************************/ -class _barycentricinterpolant_owner -{ -public: - _barycentricinterpolant_owner(); - _barycentricinterpolant_owner(const _barycentricinterpolant_owner &rhs); - _barycentricinterpolant_owner& operator=(const _barycentricinterpolant_owner &rhs); - virtual ~_barycentricinterpolant_owner(); - alglib_impl::barycentricinterpolant* c_ptr(); - alglib_impl::barycentricinterpolant* c_ptr() const; -protected: - alglib_impl::barycentricinterpolant *p_struct; -}; -class barycentricinterpolant : public _barycentricinterpolant_owner -{ -public: - barycentricinterpolant(); - barycentricinterpolant(const barycentricinterpolant &rhs); - barycentricinterpolant& operator=(const barycentricinterpolant &rhs); - virtual ~barycentricinterpolant(); - -}; -#endif - -#if defined(AE_COMPILE_FITSPHERE) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_INTFITSERV) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPLINE1D) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -1-dimensional spline interpolant -*************************************************************************/ -class _spline1dinterpolant_owner -{ -public: - _spline1dinterpolant_owner(); - _spline1dinterpolant_owner(const _spline1dinterpolant_owner &rhs); - _spline1dinterpolant_owner& operator=(const _spline1dinterpolant_owner &rhs); - virtual ~_spline1dinterpolant_owner(); - alglib_impl::spline1dinterpolant* c_ptr(); - alglib_impl::spline1dinterpolant* c_ptr() const; -protected: - alglib_impl::spline1dinterpolant *p_struct; -}; -class spline1dinterpolant : public _spline1dinterpolant_owner -{ -public: - spline1dinterpolant(); - spline1dinterpolant(const spline1dinterpolant &rhs); - spline1dinterpolant& operator=(const spline1dinterpolant &rhs); - virtual ~spline1dinterpolant(); - -}; - - -/************************************************************************* -Spline fitting report: - RMSError RMS error - AvgError average error - AvgRelError average relative error (for non-zero Y[I]) - MaxError maximum error - -Fields below are filled by obsolete functions (Spline1DFitCubic, -Spline1DFitHermite). Modern fitting functions do NOT fill these fields: - TaskRCond reciprocal of task's condition number -*************************************************************************/ -class _spline1dfitreport_owner -{ -public: - _spline1dfitreport_owner(); - _spline1dfitreport_owner(const _spline1dfitreport_owner &rhs); - _spline1dfitreport_owner& operator=(const _spline1dfitreport_owner &rhs); - virtual ~_spline1dfitreport_owner(); - alglib_impl::spline1dfitreport* c_ptr(); - alglib_impl::spline1dfitreport* c_ptr() const; -protected: - alglib_impl::spline1dfitreport *p_struct; -}; -class spline1dfitreport : public _spline1dfitreport_owner -{ -public: - spline1dfitreport(); - spline1dfitreport(const spline1dfitreport &rhs); - spline1dfitreport& operator=(const spline1dfitreport &rhs); - virtual ~spline1dfitreport(); - double &taskrcond; - double &rmserror; - double &avgerror; - double &avgrelerror; - double &maxerror; - -}; -#endif - -#if defined(AE_COMPILE_PARAMETRIC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Parametric spline inteprolant: 2-dimensional curve. - -You should not try to access its members directly - use PSpline2XXXXXXXX() -functions instead. -*************************************************************************/ -class _pspline2interpolant_owner -{ -public: - _pspline2interpolant_owner(); - _pspline2interpolant_owner(const _pspline2interpolant_owner &rhs); - _pspline2interpolant_owner& operator=(const _pspline2interpolant_owner &rhs); - virtual ~_pspline2interpolant_owner(); - alglib_impl::pspline2interpolant* c_ptr(); - alglib_impl::pspline2interpolant* c_ptr() const; -protected: - alglib_impl::pspline2interpolant *p_struct; -}; -class pspline2interpolant : public _pspline2interpolant_owner -{ -public: - pspline2interpolant(); - pspline2interpolant(const pspline2interpolant &rhs); - pspline2interpolant& operator=(const pspline2interpolant &rhs); - virtual ~pspline2interpolant(); - -}; - - -/************************************************************************* -Parametric spline inteprolant: 3-dimensional curve. - -You should not try to access its members directly - use PSpline3XXXXXXXX() -functions instead. -*************************************************************************/ -class _pspline3interpolant_owner -{ -public: - _pspline3interpolant_owner(); - _pspline3interpolant_owner(const _pspline3interpolant_owner &rhs); - _pspline3interpolant_owner& operator=(const _pspline3interpolant_owner &rhs); - virtual ~_pspline3interpolant_owner(); - alglib_impl::pspline3interpolant* c_ptr(); - alglib_impl::pspline3interpolant* c_ptr() const; -protected: - alglib_impl::pspline3interpolant *p_struct; -}; -class pspline3interpolant : public _pspline3interpolant_owner -{ -public: - pspline3interpolant(); - pspline3interpolant(const pspline3interpolant &rhs); - pspline3interpolant& operator=(const pspline3interpolant &rhs); - virtual ~pspline3interpolant(); - -}; -#endif - -#if defined(AE_COMPILE_SPLINE3D) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -3-dimensional spline inteprolant -*************************************************************************/ -class _spline3dinterpolant_owner -{ -public: - _spline3dinterpolant_owner(); - _spline3dinterpolant_owner(const _spline3dinterpolant_owner &rhs); - _spline3dinterpolant_owner& operator=(const _spline3dinterpolant_owner &rhs); - virtual ~_spline3dinterpolant_owner(); - alglib_impl::spline3dinterpolant* c_ptr(); - alglib_impl::spline3dinterpolant* c_ptr() const; -protected: - alglib_impl::spline3dinterpolant *p_struct; -}; -class spline3dinterpolant : public _spline3dinterpolant_owner -{ -public: - spline3dinterpolant(); - spline3dinterpolant(const spline3dinterpolant &rhs); - spline3dinterpolant& operator=(const spline3dinterpolant &rhs); - virtual ~spline3dinterpolant(); - -}; -#endif - -#if defined(AE_COMPILE_POLINT) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_LSFIT) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Polynomial fitting report: - TaskRCond reciprocal of task's condition number - RMSError RMS error - AvgError average error - AvgRelError average relative error (for non-zero Y[I]) - MaxError maximum error -*************************************************************************/ -class _polynomialfitreport_owner -{ -public: - _polynomialfitreport_owner(); - _polynomialfitreport_owner(const _polynomialfitreport_owner &rhs); - _polynomialfitreport_owner& operator=(const _polynomialfitreport_owner &rhs); - virtual ~_polynomialfitreport_owner(); - alglib_impl::polynomialfitreport* c_ptr(); - alglib_impl::polynomialfitreport* c_ptr() const; -protected: - alglib_impl::polynomialfitreport *p_struct; -}; -class polynomialfitreport : public _polynomialfitreport_owner -{ -public: - polynomialfitreport(); - polynomialfitreport(const polynomialfitreport &rhs); - polynomialfitreport& operator=(const polynomialfitreport &rhs); - virtual ~polynomialfitreport(); - double &taskrcond; - double &rmserror; - double &avgerror; - double &avgrelerror; - double &maxerror; - -}; - - -/************************************************************************* -Barycentric fitting report: - RMSError RMS error - AvgError average error - AvgRelError average relative error (for non-zero Y[I]) - MaxError maximum error - TaskRCond reciprocal of task's condition number -*************************************************************************/ -class _barycentricfitreport_owner -{ -public: - _barycentricfitreport_owner(); - _barycentricfitreport_owner(const _barycentricfitreport_owner &rhs); - _barycentricfitreport_owner& operator=(const _barycentricfitreport_owner &rhs); - virtual ~_barycentricfitreport_owner(); - alglib_impl::barycentricfitreport* c_ptr(); - alglib_impl::barycentricfitreport* c_ptr() const; -protected: - alglib_impl::barycentricfitreport *p_struct; -}; -class barycentricfitreport : public _barycentricfitreport_owner -{ -public: - barycentricfitreport(); - barycentricfitreport(const barycentricfitreport &rhs); - barycentricfitreport& operator=(const barycentricfitreport &rhs); - virtual ~barycentricfitreport(); - double &taskrcond; - ae_int_t &dbest; - double &rmserror; - double &avgerror; - double &avgrelerror; - double &maxerror; - -}; - - -/************************************************************************* -Least squares fitting report. This structure contains informational fields -which are set by fitting functions provided by this unit. - -Different functions initialize different sets of fields, so you should -read documentation on specific function you used in order to know which -fields are initialized. - - TaskRCond reciprocal of task's condition number - IterationsCount number of internal iterations - - VarIdx if user-supplied gradient contains errors which were - detected by nonlinear fitter, this field is set to - index of the first component of gradient which is - suspected to be spoiled by bugs. - - RMSError RMS error - AvgError average error - AvgRelError average relative error (for non-zero Y[I]) - MaxError maximum error - - WRMSError weighted RMS error - - CovPar covariance matrix for parameters, filled by some solvers - ErrPar vector of errors in parameters, filled by some solvers - ErrCurve vector of fit errors - variability of the best-fit - curve, filled by some solvers. - Noise vector of per-point noise estimates, filled by - some solvers. - R2 coefficient of determination (non-weighted, non-adjusted), - filled by some solvers. -*************************************************************************/ -class _lsfitreport_owner -{ -public: - _lsfitreport_owner(); - _lsfitreport_owner(const _lsfitreport_owner &rhs); - _lsfitreport_owner& operator=(const _lsfitreport_owner &rhs); - virtual ~_lsfitreport_owner(); - alglib_impl::lsfitreport* c_ptr(); - alglib_impl::lsfitreport* c_ptr() const; -protected: - alglib_impl::lsfitreport *p_struct; -}; -class lsfitreport : public _lsfitreport_owner -{ -public: - lsfitreport(); - lsfitreport(const lsfitreport &rhs); - lsfitreport& operator=(const lsfitreport &rhs); - virtual ~lsfitreport(); - double &taskrcond; - ae_int_t &iterationscount; - ae_int_t &varidx; - double &rmserror; - double &avgerror; - double &avgrelerror; - double &maxerror; - double &wrmserror; - real_2d_array covpar; - real_1d_array errpar; - real_1d_array errcurve; - real_1d_array noise; - double &r2; - -}; - - -/************************************************************************* -Nonlinear fitter. - -You should use ALGLIB functions to work with fitter. -Never try to access its fields directly! -*************************************************************************/ -class _lsfitstate_owner -{ -public: - _lsfitstate_owner(); - _lsfitstate_owner(const _lsfitstate_owner &rhs); - _lsfitstate_owner& operator=(const _lsfitstate_owner &rhs); - virtual ~_lsfitstate_owner(); - alglib_impl::lsfitstate* c_ptr(); - alglib_impl::lsfitstate* c_ptr() const; -protected: - alglib_impl::lsfitstate *p_struct; -}; -class lsfitstate : public _lsfitstate_owner -{ -public: - lsfitstate(); - lsfitstate(const lsfitstate &rhs); - lsfitstate& operator=(const lsfitstate &rhs); - virtual ~lsfitstate(); - ae_bool &needf; - ae_bool &needfg; - ae_bool &needfgh; - ae_bool &xupdated; - real_1d_array c; - double &f; - real_1d_array g; - real_2d_array h; - real_1d_array x; - -}; -#endif - -#if defined(AE_COMPILE_RBFV2) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPLINE2D) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -2-dimensional spline inteprolant -*************************************************************************/ -class _spline2dinterpolant_owner -{ -public: - _spline2dinterpolant_owner(); - _spline2dinterpolant_owner(const _spline2dinterpolant_owner &rhs); - _spline2dinterpolant_owner& operator=(const _spline2dinterpolant_owner &rhs); - virtual ~_spline2dinterpolant_owner(); - alglib_impl::spline2dinterpolant* c_ptr(); - alglib_impl::spline2dinterpolant* c_ptr() const; -protected: - alglib_impl::spline2dinterpolant *p_struct; -}; -class spline2dinterpolant : public _spline2dinterpolant_owner -{ -public: - spline2dinterpolant(); - spline2dinterpolant(const spline2dinterpolant &rhs); - spline2dinterpolant& operator=(const spline2dinterpolant &rhs); - virtual ~spline2dinterpolant(); - -}; - - -/************************************************************************* -Nonlinear least squares solver used to fit 2D splines to data -*************************************************************************/ -class _spline2dbuilder_owner -{ -public: - _spline2dbuilder_owner(); - _spline2dbuilder_owner(const _spline2dbuilder_owner &rhs); - _spline2dbuilder_owner& operator=(const _spline2dbuilder_owner &rhs); - virtual ~_spline2dbuilder_owner(); - alglib_impl::spline2dbuilder* c_ptr(); - alglib_impl::spline2dbuilder* c_ptr() const; -protected: - alglib_impl::spline2dbuilder *p_struct; -}; -class spline2dbuilder : public _spline2dbuilder_owner -{ -public: - spline2dbuilder(); - spline2dbuilder(const spline2dbuilder &rhs); - spline2dbuilder& operator=(const spline2dbuilder &rhs); - virtual ~spline2dbuilder(); - -}; - - -/************************************************************************* -Spline 2D fitting report: - rmserror RMS error - avgerror average error - maxerror maximum error - r2 coefficient of determination, R-squared, 1-RSS/TSS -*************************************************************************/ -class _spline2dfitreport_owner -{ -public: - _spline2dfitreport_owner(); - _spline2dfitreport_owner(const _spline2dfitreport_owner &rhs); - _spline2dfitreport_owner& operator=(const _spline2dfitreport_owner &rhs); - virtual ~_spline2dfitreport_owner(); - alglib_impl::spline2dfitreport* c_ptr(); - alglib_impl::spline2dfitreport* c_ptr() const; -protected: - alglib_impl::spline2dfitreport *p_struct; -}; -class spline2dfitreport : public _spline2dfitreport_owner -{ -public: - spline2dfitreport(); - spline2dfitreport(const spline2dfitreport &rhs); - spline2dfitreport& operator=(const spline2dfitreport &rhs); - virtual ~spline2dfitreport(); - double &rmserror; - double &avgerror; - double &maxerror; - double &r2; - -}; -#endif - -#if defined(AE_COMPILE_RBFV1) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_RBF) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Buffer object which is used to perform nearest neighbor requests in the -multithreaded mode (multiple threads working with same KD-tree object). - -This object should be created with KDTreeCreateBuffer(). -*************************************************************************/ -class _rbfcalcbuffer_owner -{ -public: - _rbfcalcbuffer_owner(); - _rbfcalcbuffer_owner(const _rbfcalcbuffer_owner &rhs); - _rbfcalcbuffer_owner& operator=(const _rbfcalcbuffer_owner &rhs); - virtual ~_rbfcalcbuffer_owner(); - alglib_impl::rbfcalcbuffer* c_ptr(); - alglib_impl::rbfcalcbuffer* c_ptr() const; -protected: - alglib_impl::rbfcalcbuffer *p_struct; -}; -class rbfcalcbuffer : public _rbfcalcbuffer_owner -{ -public: - rbfcalcbuffer(); - rbfcalcbuffer(const rbfcalcbuffer &rhs); - rbfcalcbuffer& operator=(const rbfcalcbuffer &rhs); - virtual ~rbfcalcbuffer(); - -}; - - -/************************************************************************* -RBF model. - -Never try to directly work with fields of this object - always use ALGLIB -functions to use this object. -*************************************************************************/ -class _rbfmodel_owner -{ -public: - _rbfmodel_owner(); - _rbfmodel_owner(const _rbfmodel_owner &rhs); - _rbfmodel_owner& operator=(const _rbfmodel_owner &rhs); - virtual ~_rbfmodel_owner(); - alglib_impl::rbfmodel* c_ptr(); - alglib_impl::rbfmodel* c_ptr() const; -protected: - alglib_impl::rbfmodel *p_struct; -}; -class rbfmodel : public _rbfmodel_owner -{ -public: - rbfmodel(); - rbfmodel(const rbfmodel &rhs); - rbfmodel& operator=(const rbfmodel &rhs); - virtual ~rbfmodel(); - -}; - - -/************************************************************************* -RBF solution report: -* TerminationType - termination type, positive values - success, - non-positive - failure. - -Fields which are set by modern RBF solvers (hierarchical): -* RMSError - root-mean-square error; NAN for old solvers (ML, QNN) -* MaxError - maximum error; NAN for old solvers (ML, QNN) -*************************************************************************/ -class _rbfreport_owner -{ -public: - _rbfreport_owner(); - _rbfreport_owner(const _rbfreport_owner &rhs); - _rbfreport_owner& operator=(const _rbfreport_owner &rhs); - virtual ~_rbfreport_owner(); - alglib_impl::rbfreport* c_ptr(); - alglib_impl::rbfreport* c_ptr() const; -protected: - alglib_impl::rbfreport *p_struct; -}; -class rbfreport : public _rbfreport_owner -{ -public: - rbfreport(); - rbfreport(const rbfreport &rhs); - rbfreport& operator=(const rbfreport &rhs); - virtual ~rbfreport(); - double &rmserror; - double &maxerror; - ae_int_t &arows; - ae_int_t &acols; - ae_int_t &annz; - ae_int_t &iterationscount; - ae_int_t &nmv; - ae_int_t &terminationtype; - -}; -#endif - -#if defined(AE_COMPILE_INTCOMP) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_IDW) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -void idwserialize(idwmodel &obj, std::string &s_out); - - -/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -void idwunserialize(const std::string &s_in, idwmodel &obj); - - - - -/************************************************************************* -This function serializes data structure to C++ stream. - -Data stream generated by this function is same as string representation -generated by string version of serializer - alphanumeric characters, -dots, underscores, minus signs, which are grouped into words separated by -spaces and CR+LF. - -We recommend you to read comments on string version of serializer to find -out more about serialization of AlGLIB objects. -*************************************************************************/ -void idwserialize(idwmodel &obj, std::ostream &s_out); - - -/************************************************************************* -This function unserializes data structure from stream. -*************************************************************************/ -void idwunserialize(const std::istream &s_in, idwmodel &obj); - - -/************************************************************************* -This function creates buffer structure which can be used to perform -parallel IDW model evaluations (with one IDW model instance being -used from multiple threads, as long as different threads use different -instances of buffer). - -This buffer object can be used with idwtscalcbuf() function (here "ts" -stands for "thread-safe", "buf" is a suffix which denotes function which -reuses previously allocated output space). - -How to use it: -* create IDW model structure or load it from file -* call idwcreatecalcbuffer(), once per thread working with IDW model (you - should call this function only AFTER model initialization, see below for - more information) -* call idwtscalcbuf() from different threads, with each thread working - with its own copy of buffer object. - -INPUT PARAMETERS - S - IDW model - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: buffer object should be used only with IDW model object which - was used to initialize buffer. Any attempt to use buffer with - different object is dangerous - you may get memory violation - error because sizes of internal arrays do not fit to dimensions - of the IDW structure. - -IMPORTANT: you should call this function only for model which was built - with model builder (or unserialized from file). Sizes of some - internal structures are determined only after model is built, - so buffer object created before model construction stage will - be useless (and any attempt to use it will result in exception). - - -- ALGLIB -- - Copyright 22.10.2018 by Sergey Bochkanov -*************************************************************************/ -void idwcreatecalcbuffer(const idwmodel &s, idwcalcbuffer &buf, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine creates builder object used to generate IDW model from -irregularly sampled (scattered) dataset. Multidimensional scalar/vector- --valued are supported. - -Builder object is used to fit model to data as follows: -* builder object is created with idwbuildercreate() function -* dataset is added with idwbuildersetpoints() function -* one of the modern IDW algorithms is chosen with either: - * idwbuildersetalgomstab() - Multilayer STABilized algorithm (interpolation) - Alternatively, one of the textbook algorithms can be chosen (not recommended): - * idwbuildersetalgotextbookshepard() - textbook Shepard algorithm - * idwbuildersetalgotextbookmodshepard()-textbook modified Shepard algorithm -* finally, model construction is performed with idwfit() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - NX - dimensionality of the argument, NX>=1 - NY - dimensionality of the function being modeled, NY>=1; - NY=1 corresponds to classic scalar function, NY>=1 corresponds - to vector-valued function. - -OUTPUT PARAMETERS: - State- builder object - - -- ALGLIB PROJECT -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildercreate(const ae_int_t nx, const ae_int_t ny, idwbuilder &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function changes number of layers used by IDW-MSTAB algorithm. - -The more layers you have, the finer details can be reproduced with IDW -model. The less layers you have, the less memory and CPU time is consumed -by the model. - -Memory consumption grows linearly with layers count, running time grows -sub-linearly. - -The default number of layers is 16, which allows you to reproduce details -at distance down to SRad/65536. You will rarely need to change it. - -INPUT PARAMETERS: - State - builder object - NLayers - NLayers>=1, the number of layers used by the model. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetnlayers(const idwbuilder &state, const ae_int_t nlayers, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function adds dataset to the builder object. - -This function overrides results of the previous calls, i.e. multiple calls -of this function will result in only the last set being added. - -INPUT PARAMETERS: - State - builder object - XY - points, array[N,NX+NY]. One row corresponds to one point - in the dataset. First NX elements are coordinates, next - NY elements are function values. Array may be larger than - specified, in this case only leading [N,NX+NY] elements - will be used. - N - number of points in the dataset, N>=0. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetpoints(const idwbuilder &state, const real_2d_array &xy, const ae_int_t n, const xparams _xparams = alglib::xdefault); -void idwbuildersetpoints(const idwbuilder &state, const real_2d_array &xy, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets IDW model construction algorithm to the Multilayer -Stabilized IDW method (IDW-MSTAB), a latest incarnation of the inverse -distance weighting interpolation which fixes shortcomings of the original -and modified Shepard's variants. - -The distinctive features of IDW-MSTAB are: -1) exact interpolation is pursued (as opposed to fitting and noise - suppression) -2) improved robustness when compared with that of other algorithms: - * MSTAB shows almost no strange fitting artifacts like ripples and - sharp spikes (unlike N-dimensional splines and HRBFs) - * MSTAB does not return function values far from the interval spanned - by the dataset; say, if all your points have |f|<=1, you can be sure - that model value won't deviate too much from [-1,+1] -3) good model construction time competing with that of HRBFs and bicubic - splines -4) ability to work with any number of dimensions, starting from NX=1 - -The drawbacks of IDW-MSTAB (and all IDW algorithms in general) are: -1) dependence of the model evaluation time on the search radius -2) bad extrapolation properties, models built by this method are usually - conservative in their predictions - -Thus, IDW-MSTAB is a good "default" option if you want to perform -scattered multidimensional interpolation. Although it has its drawbacks, -it is easy to use and robust, which makes it a good first step. - - -INPUT PARAMETERS: - State - builder object - SRad - initial search radius, SRad>0 is required. A model value - is obtained by "smart" averaging of the dataset points - within search radius. - -NOTE 1: IDW interpolation can correctly handle ANY dataset, including - datasets with non-distinct points. In case non-distinct points are - found, an average value for this point will be calculated. - -NOTE 2: the memory requirements for model storage are O(NPoints*NLayers). - The model construction needs twice as much memory as model storage. - -NOTE 3: by default 16 IDW layers are built which is enough for most cases. - You can change this parameter with idwbuildersetnlayers() method. - Larger values may be necessary if you need to reproduce extrafine - details at distances smaller than SRad/65536. Smaller value may - be necessary if you have to save memory and computing time, and - ready to sacrifice some model quality. - - -ALGORITHM DESCRIPTION - -ALGLIB implementation of IDW is somewhat similar to the modified Shepard's -method (one with search radius R) but overcomes several of its drawbacks, -namely: -1) a tendency to show stepwise behavior for uniform datasets -2) a tendency to show terrible interpolation properties for highly - nonuniform datasets which often arise in geospatial tasks - (function values are densely sampled across multiple separated - "tracks") - -IDW-MSTAB method performs several passes over dataset and builds a sequence -of progressively refined IDW models (layers), which starts from one with -largest search radius SRad and continues to smaller search radii until -required number of layers is built. Highest layers reproduce global -behavior of the target function at larger distances whilst lower layers -reproduce fine details at smaller distances. - -Each layer is an IDW model built with following modifications: -* weights go to zero when distance approach to the current search radius -* an additional regularizing term is added to the distance: w=1/(d^2+lambda) -* an additional fictional term with unit weight and zero function value is - added in order to promote continuity properties at the isolated and - boundary points - -By default, 16 layers is built, which is enough for most cases. You can -change this parameter with idwbuildersetnlayers() method. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetalgomstab(const idwbuilder &state, const double srad, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets IDW model construction algorithm to the textbook -Shepard's algorithm with custom (user-specified) power parameter. - -IMPORTANT: we do NOT recommend using textbook IDW algorithms because they - have terrible interpolation properties. Use MSTAB in all cases. - -INPUT PARAMETERS: - State - builder object - P - power parameter, P>0; good value to start with is 2.0 - -NOTE 1: IDW interpolation can correctly handle ANY dataset, including - datasets with non-distinct points. In case non-distinct points are - found, an average value for this point will be calculated. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetalgotextbookshepard(const idwbuilder &state, const double p, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets IDW model construction algorithm to the 'textbook' -modified Shepard's algorithm with user-specified search radius. - -IMPORTANT: we do NOT recommend using textbook IDW algorithms because they - have terrible interpolation properties. Use MSTAB in all cases. - -INPUT PARAMETERS: - State - builder object - R - search radius - -NOTE 1: IDW interpolation can correctly handle ANY dataset, including - datasets with non-distinct points. In case non-distinct points are - found, an average value for this point will be calculated. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetalgotextbookmodshepard(const idwbuilder &state, const double r, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets prior term (model value at infinity) as user-specified -value. - -INPUT PARAMETERS: - S - spline builder - V - value for user-defined prior - -NOTE: for vector-valued models all components of the prior are set to same - user-specified value - - -- ALGLIB -- - Copyright 29.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetuserterm(const idwbuilder &state, const double v, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets constant prior term (model value at infinity). - -Constant prior term is determined as mean value over dataset. - -INPUT PARAMETERS: - S - spline builder - - -- ALGLIB -- - Copyright 29.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetconstterm(const idwbuilder &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets zero prior term (model value at infinity). - -INPUT PARAMETERS: - S - spline builder - - -- ALGLIB -- - Copyright 29.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwbuildersetzeroterm(const idwbuilder &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -IDW interpolation: scalar target, 1-dimensional argument - -NOTE: this function modifies internal temporaries of the IDW model, thus - IT IS NOT THREAD-SAFE! If you want to perform parallel model - evaluation from the multiple threads, use idwtscalcbuf() with per- - thread buffer object. - -INPUT PARAMETERS: - S - IDW interpolant built with IDW builder - X0 - argument value - -Result: - IDW interpolant S(X0) - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -double idwcalc1(const idwmodel &s, const double x0, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -IDW interpolation: scalar target, 2-dimensional argument - -NOTE: this function modifies internal temporaries of the IDW model, thus - IT IS NOT THREAD-SAFE! If you want to perform parallel model - evaluation from the multiple threads, use idwtscalcbuf() with per- - thread buffer object. - -INPUT PARAMETERS: - S - IDW interpolant built with IDW builder - X0, X1 - argument value - -Result: - IDW interpolant S(X0,X1) - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -double idwcalc2(const idwmodel &s, const double x0, const double x1, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -IDW interpolation: scalar target, 3-dimensional argument - -NOTE: this function modifies internal temporaries of the IDW model, thus - IT IS NOT THREAD-SAFE! If you want to perform parallel model - evaluation from the multiple threads, use idwtscalcbuf() with per- - thread buffer object. - -INPUT PARAMETERS: - S - IDW interpolant built with IDW builder - X0,X1,X2- argument value - -Result: - IDW interpolant S(X0,X1,X2) - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -double idwcalc3(const idwmodel &s, const double x0, const double x1, const double x2, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates values of the IDW model at the given point. - -This is general function which can be used for arbitrary NX (dimension of -the space of arguments) and NY (dimension of the function itself). However -when you have NY=1 you may find more convenient to use idwcalc1(), -idwcalc2() or idwcalc3(). - -NOTE: this function modifies internal temporaries of the IDW model, thus - IT IS NOT THREAD-SAFE! If you want to perform parallel model - evaluation from the multiple threads, use idwtscalcbuf() with per- - thread buffer object. - -INPUT PARAMETERS: - S - IDW model - X - coordinates, array[NX]. X may have more than NX elements, - in this case only leading NX will be used. - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is out-parameter and will be - reallocated after call to this function. In case you want - to reuse previously allocated Y, you may use idwcalcbuf(), - which reallocates Y only when it is too small. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwcalc(const idwmodel &s, const real_1d_array &x, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates values of the IDW model at the given point. - -Same as idwcalc(), but does not reallocate Y when in is large enough to -store function values. - -NOTE: this function modifies internal temporaries of the IDW model, thus - IT IS NOT THREAD-SAFE! If you want to perform parallel model - evaluation from the multiple threads, use idwtscalcbuf() with per- - thread buffer object. - -INPUT PARAMETERS: - S - IDW model - X - coordinates, array[NX]. X may have more than NX elements, - in this case only leading NX will be used. - Y - possibly preallocated array - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is not reallocated when it - is larger than NY. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwcalcbuf(const idwmodel &s, const real_1d_array &x, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates values of the IDW model at the given point, using -external buffer object (internal temporaries of IDW model are not -modified). - -This function allows to use same IDW model object in different threads, -assuming that different threads use different instances of the buffer -structure. - -INPUT PARAMETERS: - S - IDW model, may be shared between different threads - Buf - buffer object created for this particular instance of IDW - model with idwcreatecalcbuffer(). - X - coordinates, array[NX]. X may have more than NX elements, - in this case only leading NX will be used. - Y - possibly preallocated array - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is not reallocated when it - is larger than NY. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void idwtscalcbuf(const idwmodel &s, const idwcalcbuffer &buf, const real_1d_array &x, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function fits IDW model to the dataset using current IDW construction -algorithm. A model being built and fitting report are returned. - -INPUT PARAMETERS: - State - builder object - -OUTPUT PARAMETERS: - Model - an IDW model built with current algorithm - Rep - model fitting report, fields of this structure contain - information about average fitting errors. - -NOTE: although IDW-MSTAB algorithm is an interpolation method, i.e. it - tries to fit the model exactly, it can handle datasets with non- - distinct points which can not be fit exactly; in such cases least- - squares fitting is performed. - - -- ALGLIB -- - Copyright 22.10.2018 by Bochkanov Sergey -*************************************************************************/ -void idwfit(const idwbuilder &state, idwmodel &model, idwreport &rep, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_RATINT) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Rational interpolation using barycentric formula - -F(t) = SUM(i=0,n-1,w[i]*f[i]/(t-x[i])) / SUM(i=0,n-1,w[i]/(t-x[i])) - -Input parameters: - B - barycentric interpolant built with one of model building - subroutines. - T - interpolation point - -Result: - barycentric interpolant F(t) - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -double barycentriccalc(const barycentricinterpolant &b, const double t, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Differentiation of barycentric interpolant: first derivative. - -Algorithm used in this subroutine is very robust and should not fail until -provided with values too close to MaxRealNumber (usually MaxRealNumber/N -or greater will overflow). - -INPUT PARAMETERS: - B - barycentric interpolant built with one of model building - subroutines. - T - interpolation point - -OUTPUT PARAMETERS: - F - barycentric interpolant at T - DF - first derivative - -NOTE - - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentricdiff1(const barycentricinterpolant &b, const double t, double &f, double &df, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Differentiation of barycentric interpolant: first/second derivatives. - -INPUT PARAMETERS: - B - barycentric interpolant built with one of model building - subroutines. - T - interpolation point - -OUTPUT PARAMETERS: - F - barycentric interpolant at T - DF - first derivative - D2F - second derivative - -NOTE: this algorithm may fail due to overflow/underflor if used on data -whose values are close to MaxRealNumber or MinRealNumber. Use more robust -BarycentricDiff1() subroutine in such cases. - - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentricdiff2(const barycentricinterpolant &b, const double t, double &f, double &df, double &d2f, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine performs linear transformation of the argument. - -INPUT PARAMETERS: - B - rational interpolant in barycentric form - CA, CB - transformation coefficients: x = CA*t + CB - -OUTPUT PARAMETERS: - B - transformed interpolant with X replaced by T - - -- ALGLIB PROJECT -- - Copyright 19.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentriclintransx(const barycentricinterpolant &b, const double ca, const double cb, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine performs linear transformation of the barycentric -interpolant. - -INPUT PARAMETERS: - B - rational interpolant in barycentric form - CA, CB - transformation coefficients: B2(x) = CA*B(x) + CB - -OUTPUT PARAMETERS: - B - transformed interpolant - - -- ALGLIB PROJECT -- - Copyright 19.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentriclintransy(const barycentricinterpolant &b, const double ca, const double cb, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Extracts X/Y/W arrays from rational interpolant - -INPUT PARAMETERS: - B - barycentric interpolant - -OUTPUT PARAMETERS: - N - nodes count, N>0 - X - interpolation nodes, array[0..N-1] - F - function values, array[0..N-1] - W - barycentric weights, array[0..N-1] - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentricunpack(const barycentricinterpolant &b, ae_int_t &n, real_1d_array &x, real_1d_array &y, real_1d_array &w, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Rational interpolant from X/Y/W arrays - -F(t) = SUM(i=0,n-1,w[i]*f[i]/(t-x[i])) / SUM(i=0,n-1,w[i]/(t-x[i])) - -INPUT PARAMETERS: - X - interpolation nodes, array[0..N-1] - F - function values, array[0..N-1] - W - barycentric weights, array[0..N-1] - N - nodes count, N>0 - -OUTPUT PARAMETERS: - B - barycentric interpolant built from (X, Y, W) - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentricbuildxyw(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t n, barycentricinterpolant &b, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Rational interpolant without poles - -The subroutine constructs the rational interpolating function without real -poles (see 'Barycentric rational interpolation with no poles and high -rates of approximation', Michael S. Floater. and Kai Hormann, for more -information on this subject). - -Input parameters: - X - interpolation nodes, array[0..N-1]. - Y - function values, array[0..N-1]. - N - number of nodes, N>0. - D - order of the interpolation scheme, 0 <= D <= N-1. - D<0 will cause an error. - D>=N it will be replaced with D=N-1. - if you don't know what D to choose, use small value about 3-5. - -Output parameters: - B - barycentric interpolant. - -Note: - this algorithm always succeeds and calculates the weights with close - to machine precision. - - -- ALGLIB PROJECT -- - Copyright 17.06.2007 by Bochkanov Sergey -*************************************************************************/ -void barycentricbuildfloaterhormann(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t d, barycentricinterpolant &b, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_FITSPHERE) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Fits least squares (LS) circle (or NX-dimensional sphere) to data (a set -of points in NX-dimensional space). - -Least squares circle minimizes sum of squared deviations between distances -from points to the center and some "candidate" radius, which is also -fitted to the data. - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - -OUTPUT PARAMETERS: - CX - central point for a sphere - R - radius - - -- ALGLIB -- - Copyright 07.05.2018 by Bochkanov Sergey -*************************************************************************/ -void fitspherels(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &r, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Fits minimum circumscribed (MC) circle (or NX-dimensional sphere) to data -(a set of points in NX-dimensional space). - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - -OUTPUT PARAMETERS: - CX - central point for a sphere - RHi - radius - -NOTE: this function is an easy-to-use wrapper around more powerful "expert" - function fitspherex(). - - This wrapper is optimized for ease of use and stability - at the - cost of somewhat lower performance (we have to use very tight - stopping criteria for inner optimizer because we want to make sure - that it will converge on any dataset). - - If you are ready to experiment with settings of "expert" function, - you can achieve ~2-4x speedup over standard "bulletproof" settings. - - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void fitspheremc(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &rhi, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Fits maximum inscribed circle (or NX-dimensional sphere) to data (a set of -points in NX-dimensional space). - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - -OUTPUT PARAMETERS: - CX - central point for a sphere - RLo - radius - -NOTE: this function is an easy-to-use wrapper around more powerful "expert" - function fitspherex(). - - This wrapper is optimized for ease of use and stability - at the - cost of somewhat lower performance (we have to use very tight - stopping criteria for inner optimizer because we want to make sure - that it will converge on any dataset). - - If you are ready to experiment with settings of "expert" function, - you can achieve ~2-4x speedup over standard "bulletproof" settings. - - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void fitspheremi(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &rlo, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Fits minimum zone circle (or NX-dimensional sphere) to data (a set of -points in NX-dimensional space). - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - -OUTPUT PARAMETERS: - CX - central point for a sphere - RLo - radius of inscribed circle - RHo - radius of circumscribed circle - -NOTE: this function is an easy-to-use wrapper around more powerful "expert" - function fitspherex(). - - This wrapper is optimized for ease of use and stability - at the - cost of somewhat lower performance (we have to use very tight - stopping criteria for inner optimizer because we want to make sure - that it will converge on any dataset). - - If you are ready to experiment with settings of "expert" function, - you can achieve ~2-4x speedup over standard "bulletproof" settings. - - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void fitspheremz(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &rlo, double &rhi, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Fitting minimum circumscribed, maximum inscribed or minimum zone circles -(or NX-dimensional spheres) to data (a set of points in NX-dimensional -space). - -This is expert function which allows to tweak many parameters of -underlying nonlinear solver: -* stopping criteria for inner iterations -* number of outer iterations -* penalty coefficient used to handle nonlinear constraints (we convert - unconstrained nonsmooth optimization problem ivolving max() and/or min() - operations to quadratically constrained smooth one). - -You may tweak all these parameters or only some of them, leaving other -ones at their default state - just specify zero value, and solver will -fill it with appropriate default one. - -These comments also include some discussion of approach used to handle -such unusual fitting problem, its stability, drawbacks of alternative -methods, and convergence properties. - -INPUT PARAMETERS: - XY - array[NPoints,NX] (or larger), contains dataset. - One row = one point in NX-dimensional space. - NPoints - dataset size, NPoints>0 - NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on) - ProblemType-used to encode problem type: - * 0 for least squares circle - * 1 for minimum circumscribed circle/sphere fitting (MC) - * 2 for maximum inscribed circle/sphere fitting (MI) - * 3 for minimum zone circle fitting (difference between - Rhi and Rlo is minimized), denoted as MZ - EpsX - stopping condition for NLC optimizer: - * must be non-negative - * use 0 to choose default value (1.0E-12 is used by default) - * you may specify larger values, up to 1.0E-6, if you want - to speed-up solver; NLC solver performs several - preconditioned outer iterations, so final result - typically has precision much better than EpsX. - AULIts - number of outer iterations performed by NLC optimizer: - * must be non-negative - * use 0 to choose default value (20 is used by default) - * you may specify values smaller than 20 if you want to - speed up solver; 10 often results in good combination of - precision and speed; sometimes you may get good results - with just 6 outer iterations. - Ignored for ProblemType=0. - Penalty - penalty coefficient for NLC optimizer: - * must be non-negative - * use 0 to choose default value (1.0E6 in current version) - * it should be really large, 1.0E6...1.0E7 is a good value - to start from; - * generally, default value is good enough - Ignored for ProblemType=0. - -OUTPUT PARAMETERS: - CX - central point for a sphere - RLo - radius: - * for ProblemType=2,3, radius of the inscribed sphere - * for ProblemType=0 - radius of the least squares sphere - * for ProblemType=1 - zero - RHo - radius: - * for ProblemType=1,3, radius of the circumscribed sphere - * for ProblemType=0 - radius of the least squares sphere - * for ProblemType=2 - zero - -NOTE: ON THE UNIQUENESS OF SOLUTIONS - -ALGLIB provides solution to several related circle fitting problems: MC -(minimum circumscribed), MI (maximum inscribed) and MZ (minimum zone) -fitting, LS (least squares) fitting. - -It is important to note that among these problems only MC and LS are -convex and have unique solution independently from starting point. - -As for MI, it may (or may not, depending on dataset properties) have -multiple solutions, and it always has one degenerate solution C=infinity -which corresponds to infinitely large radius. Thus, there are no guarantees -that solution to MI returned by this solver will be the best one (and no -one can provide you with such guarantee because problem is NP-hard). The -only guarantee you have is that this solution is locally optimal, i.e. it -can not be improved by infinitesimally small tweaks in the parameters. - -It is also possible to "run away" to infinity when started from bad -initial point located outside of point cloud (or when point cloud does not -span entire circumference/surface of the sphere). - -Finally, MZ (minimum zone circle) stands somewhere between MC and MI in -stability. It is somewhat regularized by "circumscribed" term of the merit -function; however, solutions to MZ may be non-unique, and in some unlucky -cases it is also possible to "run away to infinity". - - -NOTE: ON THE NONLINEARLY CONSTRAINED PROGRAMMING APPROACH - -The problem formulation for MC (minimum circumscribed circle; for the -sake of simplicity we omit MZ and MI here) is: - - [ [ ]2 ] - min [ max [ XY[i]-C ] ] - C [ i [ ] ] - -i.e. it is unconstrained nonsmooth optimization problem of finding "best" -central point, with radius R being unambiguously determined from C. In -order to move away from non-smoothness we use following reformulation: - - [ ] [ ]2 - min [ R ] subject to R>=0, [ XY[i]-C ] <= R^2 - C,R [ ] [ ] - -i.e. it becomes smooth quadratically constrained optimization problem with -linear target function. Such problem statement is 100% equivalent to the -original nonsmooth one, but much easier to approach. We solve it with -MinNLC solver provided by ALGLIB. - - -NOTE: ON INSTABILITY OF SEQUENTIAL LINEARIZATION APPROACH - -ALGLIB has nonlinearly constrained solver which proved to be stable on -such problems. However, some authors proposed to linearize constraints in -the vicinity of current approximation (Ci,Ri) and to get next approximate -solution (Ci+1,Ri+1) as solution to linear programming problem. Obviously, -LP problems are easier than nonlinearly constrained ones. - -Indeed, such approach to MC/MI/MZ resulted in ~10-20x increase in -performance (when compared with NLC solver). However, it turned out that -in some cases linearized model fails to predict correct direction for next -step and tells us that we converged to solution even when we are still 2-4 -digits of precision away from it. - -It is important that it is not failure of LP solver - it is failure of the -linear model; even when solved exactly, it fails to handle subtle -nonlinearities which arise near the solution. We validated it by comparing -results returned by ALGLIB linear solver with that of MATLAB. - -In our experiments with linearization: -* MC failed most often, at both realistic and synthetic datasets -* MI sometimes failed, but sometimes succeeded -* MZ often succeeded; our guess is that presence of two independent sets - of constraints (one set for Rlo and another one for Rhi) and two terms - in the target function (Rlo and Rhi) regularizes task, so when linear - model fails to handle nonlinearities from Rlo, it uses Rhi as a hint - (and vice versa). - -Because linearization approach failed to achieve stable results, we do not -include it in ALGLIB. - - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void fitspherex(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, const ae_int_t problemtype, const double epsx, const ae_int_t aulits, const double penalty, real_1d_array &cx, double &rlo, double &rhi, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_INTFITSERV) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPLINE1D) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This subroutine builds linear spline interpolant - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1] - Y - function values, array[0..N-1] - N - points count (optional): - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - -OUTPUT PARAMETERS: - C - spline interpolant - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - - -- ALGLIB PROJECT -- - Copyright 24.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dbuildlinear(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, spline1dinterpolant &c, const xparams _xparams = alglib::xdefault); -void spline1dbuildlinear(const real_1d_array &x, const real_1d_array &y, spline1dinterpolant &c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine builds cubic spline interpolant. - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1]. - Y - function values, array[0..N-1]. - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - -OUTPUT PARAMETERS: - C - spline interpolant - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 23.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dbuildcubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t boundltype, const double boundl, const ae_int_t boundrtype, const double boundr, spline1dinterpolant &c, const xparams _xparams = alglib::xdefault); -void spline1dbuildcubic(const real_1d_array &x, const real_1d_array &y, spline1dinterpolant &c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function solves following problem: given table y[] of function values -at nodes x[], it calculates and returns table of function derivatives d[] -(calculated at the same nodes x[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - spline nodes - Y - function values - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - -OUTPUT PARAMETERS: - D - derivative values at X[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Derivative values are correctly reordered on return, so D[I] is always -equal to S'(X[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -void spline1dgriddiffcubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t boundltype, const double boundl, const ae_int_t boundrtype, const double boundr, real_1d_array &d, const xparams _xparams = alglib::xdefault); -void spline1dgriddiffcubic(const real_1d_array &x, const real_1d_array &y, real_1d_array &d, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function solves following problem: given table y[] of function values -at nodes x[], it calculates and returns tables of first and second -function derivatives d1[] and d2[] (calculated at the same nodes x[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - spline nodes - Y - function values - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - -OUTPUT PARAMETERS: - D1 - S' values at X[] - D2 - S'' values at X[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Derivative values are correctly reordered on return, so D[I] is always -equal to S'(X[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -void spline1dgriddiff2cubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t boundltype, const double boundl, const ae_int_t boundrtype, const double boundr, real_1d_array &d1, real_1d_array &d2, const xparams _xparams = alglib::xdefault); -void spline1dgriddiff2cubic(const real_1d_array &x, const real_1d_array &y, real_1d_array &d1, real_1d_array &d2, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function solves following problem: given table y[] of function values -at old nodes x[] and new nodes x2[], it calculates and returns table of -function values y2[] (calculated at x2[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - old spline nodes - Y - function values - X2 - new spline nodes - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points from X/Y are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - N2 - new points count: - * N2>=2 - * if given, only first N2 points from X2 are used - * if not given, automatically detected from X2 size - -OUTPUT PARAMETERS: - F2 - function values at X2[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Function values are correctly reordered on return, so F2[I] is always -equal to S(X2[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -void spline1dconvcubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t boundltype, const double boundl, const ae_int_t boundrtype, const double boundr, const real_1d_array &x2, const ae_int_t n2, real_1d_array &y2, const xparams _xparams = alglib::xdefault); -void spline1dconvcubic(const real_1d_array &x, const real_1d_array &y, const real_1d_array &x2, real_1d_array &y2, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function solves following problem: given table y[] of function values -at old nodes x[] and new nodes x2[], it calculates and returns table of -function values y2[] and derivatives d2[] (calculated at x2[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - old spline nodes - Y - function values - X2 - new spline nodes - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points from X/Y are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - N2 - new points count: - * N2>=2 - * if given, only first N2 points from X2 are used - * if not given, automatically detected from X2 size - -OUTPUT PARAMETERS: - F2 - function values at X2[] - D2 - first derivatives at X2[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Function values are correctly reordered on return, so F2[I] is always -equal to S(X2[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -void spline1dconvdiffcubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t boundltype, const double boundl, const ae_int_t boundrtype, const double boundr, const real_1d_array &x2, const ae_int_t n2, real_1d_array &y2, real_1d_array &d2, const xparams _xparams = alglib::xdefault); -void spline1dconvdiffcubic(const real_1d_array &x, const real_1d_array &y, const real_1d_array &x2, real_1d_array &y2, real_1d_array &d2, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function solves following problem: given table y[] of function values -at old nodes x[] and new nodes x2[], it calculates and returns table of -function values y2[], first and second derivatives d2[] and dd2[] -(calculated at x2[]). - -This function yields same result as Spline1DBuildCubic() call followed by -sequence of Spline1DDiff() calls, but it can be several times faster when -called for ordered X[] and X2[]. - -INPUT PARAMETERS: - X - old spline nodes - Y - function values - X2 - new spline nodes - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points from X/Y are used - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundLType - boundary condition type for the left boundary - BoundL - left boundary condition (first or second derivative, - depending on the BoundLType) - BoundRType - boundary condition type for the right boundary - BoundR - right boundary condition (first or second derivative, - depending on the BoundRType) - N2 - new points count: - * N2>=2 - * if given, only first N2 points from X2 are used - * if not given, automatically detected from X2 size - -OUTPUT PARAMETERS: - F2 - function values at X2[] - D2 - first derivatives at X2[] - DD2 - second derivatives at X2[] - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. -Function values are correctly reordered on return, so F2[I] is always -equal to S(X2[I]) independently of points order. - -SETTING BOUNDARY VALUES: - -The BoundLType/BoundRType parameters can have the following values: - * -1, which corresonds to the periodic (cyclic) boundary conditions. - In this case: - * both BoundLType and BoundRType must be equal to -1. - * BoundL/BoundR are ignored - * Y[last] is ignored (it is assumed to be equal to Y[first]). - * 0, which corresponds to the parabolically terminated spline - (BoundL and/or BoundR are ignored). - * 1, which corresponds to the first derivative boundary condition - * 2, which corresponds to the second derivative boundary condition - * by default, BoundType=0 is used - -PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: - -Problems with periodic boundary conditions have Y[first_point]=Y[last_point]. -However, this subroutine doesn't require you to specify equal values for -the first and last points - it automatically forces them to be equal by -copying Y[first_point] (corresponds to the leftmost, minimal X[]) to -Y[last_point]. However it is recommended to pass consistent values of Y[], -i.e. to make Y[first_point]=Y[last_point]. - - -- ALGLIB PROJECT -- - Copyright 03.09.2010 by Bochkanov Sergey -*************************************************************************/ -void spline1dconvdiff2cubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t boundltype, const double boundl, const ae_int_t boundrtype, const double boundr, const real_1d_array &x2, const ae_int_t n2, real_1d_array &y2, real_1d_array &d2, real_1d_array &dd2, const xparams _xparams = alglib::xdefault); -void spline1dconvdiff2cubic(const real_1d_array &x, const real_1d_array &y, const real_1d_array &x2, real_1d_array &y2, real_1d_array &d2, real_1d_array &dd2, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine builds Catmull-Rom spline interpolant. - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1]. - Y - function values, array[0..N-1]. - -OPTIONAL PARAMETERS: - N - points count: - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - BoundType - boundary condition type: - * -1 for periodic boundary condition - * 0 for parabolically terminated spline (default) - Tension - tension parameter: - * tension=0 corresponds to classic Catmull-Rom spline (default) - * 0=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - -OUTPUT PARAMETERS: - C - spline interpolant. - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - - -- ALGLIB PROJECT -- - Copyright 23.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dbuildhermite(const real_1d_array &x, const real_1d_array &y, const real_1d_array &d, const ae_int_t n, spline1dinterpolant &c, const xparams _xparams = alglib::xdefault); -void spline1dbuildhermite(const real_1d_array &x, const real_1d_array &y, const real_1d_array &d, spline1dinterpolant &c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine builds Akima spline interpolant - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1] - Y - function values, array[0..N-1] - N - points count (optional): - * N>=2 - * if given, only first N points are used to build spline - * if not given, automatically detected from X/Y sizes - (len(X) must be equal to len(Y)) - -OUTPUT PARAMETERS: - C - spline interpolant - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - - -- ALGLIB PROJECT -- - Copyright 24.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dbuildakima(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, spline1dinterpolant &c, const xparams _xparams = alglib::xdefault); -void spline1dbuildakima(const real_1d_array &x, const real_1d_array &y, spline1dinterpolant &c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine calculates the value of the spline at the given point X. - -INPUT PARAMETERS: - C - spline interpolant - X - point - -Result: - S(x) - - -- ALGLIB PROJECT -- - Copyright 23.06.2007 by Bochkanov Sergey -*************************************************************************/ -double spline1dcalc(const spline1dinterpolant &c, const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine differentiates the spline. - -INPUT PARAMETERS: - C - spline interpolant. - X - point - -Result: - S - S(x) - DS - S'(x) - D2S - S''(x) - - -- ALGLIB PROJECT -- - Copyright 24.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1ddiff(const spline1dinterpolant &c, const double x, double &s, double &ds, double &d2s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine unpacks the spline into the coefficients table. - -INPUT PARAMETERS: - C - spline interpolant. - X - point - -OUTPUT PARAMETERS: - Tbl - coefficients table, unpacked format, array[0..N-2, 0..5]. - For I = 0...N-2: - Tbl[I,0] = X[i] - Tbl[I,1] = X[i+1] - Tbl[I,2] = C0 - Tbl[I,3] = C1 - Tbl[I,4] = C2 - Tbl[I,5] = C3 - On [x[i], x[i+1]] spline is equals to: - S(x) = C0 + C1*t + C2*t^2 + C3*t^3 - t = x-x[i] - -NOTE: - You can rebuild spline with Spline1DBuildHermite() function, which - accepts as inputs function values and derivatives at nodes, which are - easy to calculate when you have coefficients. - - -- ALGLIB PROJECT -- - Copyright 29.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dunpack(const spline1dinterpolant &c, ae_int_t &n, real_2d_array &tbl, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine performs linear transformation of the spline argument. - -INPUT PARAMETERS: - C - spline interpolant. - A, B- transformation coefficients: x = A*t + B -Result: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 30.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dlintransx(const spline1dinterpolant &c, const double a, const double b, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine performs linear transformation of the spline. - -INPUT PARAMETERS: - C - spline interpolant. - A, B- transformation coefficients: S2(x) = A*S(x) + B -Result: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 30.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline1dlintransy(const spline1dinterpolant &c, const double a, const double b, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine integrates the spline. - -INPUT PARAMETERS: - C - spline interpolant. - X - right bound of the integration interval [a, x], - here 'a' denotes min(x[]) -Result: - integral(S(t)dt,a,x) - - -- ALGLIB PROJECT -- - Copyright 23.06.2007 by Bochkanov Sergey -*************************************************************************/ -double spline1dintegrate(const spline1dinterpolant &c, const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Fitting by smoothing (penalized) cubic spline. - -This function approximates N scattered points (some of X[] may be equal to -each other) by cubic spline with M nodes at equidistant grid spanning -interval [min(x,xc),max(x,xc)]. - -The problem is regularized by adding nonlinearity penalty to usual least -squares penalty function: - - MERIT_FUNC = F_LS + F_NL - -where F_LS is a least squares error term, and F_NL is a nonlinearity -penalty which is roughly proportional to LambdaNS*integral{ S''(x)^2*dx }. -Algorithm applies automatic renormalization of F_NL which makes penalty -term roughly invariant to scaling of X[] and changes in M. - -This function is a new edition of penalized regression spline fitting, -a fast and compact one which needs much less resources that its previous -version: just O(maxMN) memory and O(maxMN*log(maxMN)) time. - -NOTE: it is OK to run this function with both M<>N; say, it is - possible to process 100 points with 1000-node spline. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - N - number of points (optional): - * N>0 - * if given, only first N elements of X/Y are processed - * if not given, automatically determined from lengths - M - number of basis functions ( = number_of_nodes), M>=4. - LambdaNS - LambdaNS>=0, regularization constant passed by user. - It penalizes nonlinearity in the regression spline. - Possible values to start from are 0.00001, 0.1, 1 - -OUTPUT PARAMETERS: - S - spline interpolant. - Rep - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - - -- ALGLIB PROJECT -- - Copyright 27.08.2019 by Bochkanov Sergey -*************************************************************************/ -void spline1dfit(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t m, const double lambdans, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams = alglib::xdefault); -void spline1dfit(const real_1d_array &x, const real_1d_array &y, const ae_int_t m, const double lambdans, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function builds monotone cubic Hermite interpolant. This interpolant -is monotonic in [x(0),x(n-1)] and is constant outside of this interval. - -In case y[] form non-monotonic sequence, interpolant is piecewise -monotonic. Say, for x=(0,1,2,3,4) and y=(0,1,2,1,0) interpolant will -monotonically grow at [0..2] and monotonically decrease at [2..4]. - -INPUT PARAMETERS: - X - spline nodes, array[0..N-1]. Subroutine automatically - sorts points, so caller may pass unsorted array. - Y - function values, array[0..N-1] - N - the number of points(N>=2). - -OUTPUT PARAMETERS: - C - spline interpolant. - - -- ALGLIB PROJECT -- - Copyright 21.06.2012 by Bochkanov Sergey -*************************************************************************/ -void spline1dbuildmonotone(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, spline1dinterpolant &c, const xparams _xparams = alglib::xdefault); -void spline1dbuildmonotone(const real_1d_array &x, const real_1d_array &y, spline1dinterpolant &c, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_PARAMETRIC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This function builds non-periodic 2-dimensional parametric spline which -starts at (X[0],Y[0]) and ends at (X[N-1],Y[N-1]). - -INPUT PARAMETERS: - XY - points, array[0..N-1,0..1]. - XY[I,0:1] corresponds to the Ith point. - Order of points is important! - N - points count, N>=5 for Akima splines, N>=2 for other types of - splines. - ST - spline type: - * 0 Akima spline - * 1 parabolically terminated Catmull-Rom spline (Tension=0) - * 2 parabolically terminated cubic spline - PT - parameterization type: - * 0 uniform - * 1 chord length - * 2 centripetal - -OUTPUT PARAMETERS: - P - parametric spline interpolant - - -NOTES: -* this function assumes that there all consequent points are distinct. - I.e. (x0,y0)<>(x1,y1), (x1,y1)<>(x2,y2), (x2,y2)<>(x3,y3) and so on. - However, non-consequent points may coincide, i.e. we can have (x0,y0)= - =(x2,y2). - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline2build(const real_2d_array &xy, const ae_int_t n, const ae_int_t st, const ae_int_t pt, pspline2interpolant &p, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function builds non-periodic 3-dimensional parametric spline which -starts at (X[0],Y[0],Z[0]) and ends at (X[N-1],Y[N-1],Z[N-1]). - -Same as PSpline2Build() function, but for 3D, so we won't duplicate its -description here. - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline3build(const real_2d_array &xy, const ae_int_t n, const ae_int_t st, const ae_int_t pt, pspline3interpolant &p, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function builds periodic 2-dimensional parametric spline which -starts at (X[0],Y[0]), goes through all points to (X[N-1],Y[N-1]) and then -back to (X[0],Y[0]). - -INPUT PARAMETERS: - XY - points, array[0..N-1,0..1]. - XY[I,0:1] corresponds to the Ith point. - XY[N-1,0:1] must be different from XY[0,0:1]. - Order of points is important! - N - points count, N>=3 for other types of splines. - ST - spline type: - * 1 Catmull-Rom spline (Tension=0) with cyclic boundary conditions - * 2 cubic spline with cyclic boundary conditions - PT - parameterization type: - * 0 uniform - * 1 chord length - * 2 centripetal - -OUTPUT PARAMETERS: - P - parametric spline interpolant - - -NOTES: -* this function assumes that there all consequent points are distinct. - I.e. (x0,y0)<>(x1,y1), (x1,y1)<>(x2,y2), (x2,y2)<>(x3,y3) and so on. - However, non-consequent points may coincide, i.e. we can have (x0,y0)= - =(x2,y2). -* last point of sequence is NOT equal to the first point. You shouldn't - make curve "explicitly periodic" by making them equal. - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline2buildperiodic(const real_2d_array &xy, const ae_int_t n, const ae_int_t st, const ae_int_t pt, pspline2interpolant &p, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function builds periodic 3-dimensional parametric spline which -starts at (X[0],Y[0],Z[0]), goes through all points to (X[N-1],Y[N-1],Z[N-1]) -and then back to (X[0],Y[0],Z[0]). - -Same as PSpline2Build() function, but for 3D, so we won't duplicate its -description here. - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline3buildperiodic(const real_2d_array &xy, const ae_int_t n, const ae_int_t st, const ae_int_t pt, pspline3interpolant &p, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function returns vector of parameter values correspoding to points. - -I.e. for P created from (X[0],Y[0])...(X[N-1],Y[N-1]) and U=TValues(P) we -have - (X[0],Y[0]) = PSpline2Calc(P,U[0]), - (X[1],Y[1]) = PSpline2Calc(P,U[1]), - (X[2],Y[2]) = PSpline2Calc(P,U[2]), - ... - -INPUT PARAMETERS: - P - parametric spline interpolant - -OUTPUT PARAMETERS: - N - array size - T - array[0..N-1] - - -NOTES: -* for non-periodic splines U[0]=0, U[0]1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-position - Y - Y-position - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline2calc(const pspline2interpolant &p, const double t, double &x, double &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates the value of the parametric spline for a given -value of parameter T. - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-position - Y - Y-position - Z - Z-position - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline3calc(const pspline3interpolant &p, const double t, double &x, double &y, double &z, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates tangent vector for a given value of parameter T - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-component of tangent vector (normalized) - Y - Y-component of tangent vector (normalized) - -NOTE: - X^2+Y^2 is either 1 (for non-zero tangent vector) or 0. - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline2tangent(const pspline2interpolant &p, const double t, double &x, double &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates tangent vector for a given value of parameter T - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-component of tangent vector (normalized) - Y - Y-component of tangent vector (normalized) - Z - Z-component of tangent vector (normalized) - -NOTE: - X^2+Y^2+Z^2 is either 1 (for non-zero tangent vector) or 0. - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline3tangent(const pspline3interpolant &p, const double t, double &x, double &y, double &z, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates derivative, i.e. it returns (dX/dT,dY/dT). - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-value - DX - X-derivative - Y - Y-value - DY - Y-derivative - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline2diff(const pspline2interpolant &p, const double t, double &x, double &dx, double &y, double &dy, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates derivative, i.e. it returns (dX/dT,dY/dT,dZ/dT). - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-value - DX - X-derivative - Y - Y-value - DY - Y-derivative - Z - Z-value - DZ - Z-derivative - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline3diff(const pspline3interpolant &p, const double t, double &x, double &dx, double &y, double &dy, double &z, double &dz, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates first and second derivative with respect to T. - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-value - DX - derivative - D2X - second derivative - Y - Y-value - DY - derivative - D2Y - second derivative - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline2diff2(const pspline2interpolant &p, const double t, double &x, double &dx, double &d2x, double &y, double &dy, double &d2y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates first and second derivative with respect to T. - -INPUT PARAMETERS: - P - parametric spline interpolant - T - point: - * T in [0,1] corresponds to interval spanned by points - * for non-periodic splines T<0 (or T>1) correspond to parts of - the curve before the first (after the last) point - * for periodic splines T<0 (or T>1) are projected into [0,1] - by making T=T-floor(T). - -OUTPUT PARAMETERS: - X - X-value - DX - derivative - D2X - second derivative - Y - Y-value - DY - derivative - D2Y - second derivative - Z - Z-value - DZ - derivative - D2Z - second derivative - - - -- ALGLIB PROJECT -- - Copyright 28.05.2010 by Bochkanov Sergey -*************************************************************************/ -void pspline3diff2(const pspline3interpolant &p, const double t, double &x, double &dx, double &d2x, double &y, double &dy, double &d2y, double &z, double &dz, double &d2z, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates arc length, i.e. length of curve between t=a -and t=b. - -INPUT PARAMETERS: - P - parametric spline interpolant - A,B - parameter values corresponding to arc ends: - * B>A will result in positive length returned - * BA will result in positive length returned - * B1 - OldYCount - old Y-count, OldYCount>1 - OldXCount - old X-count, OldXCount>1 - NewZCount - new Z-count, NewZCount>1 - NewYCount - new Y-count, NewYCount>1 - NewXCount - new X-count, NewXCount>1 - -OUTPUT PARAMETERS: - B - array[0..NewXCount*NewYCount*NewZCount-1], function - values at the new grid: - B[0] x=0,y=0,z=0 - B[1] x=1,y=0,z=0 - B[..] ... - B[..] x=newxcount-1,y=0,z=0 - B[..] x=0,y=1,z=0 - B[..] ... - ... - - -- ALGLIB routine -- - 26.04.2012 - Copyright by Bochkanov Sergey -*************************************************************************/ -void spline3dresampletrilinear(const real_1d_array &a, const ae_int_t oldzcount, const ae_int_t oldycount, const ae_int_t oldxcount, const ae_int_t newzcount, const ae_int_t newycount, const ae_int_t newxcount, real_1d_array &b, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine builds trilinear vector-valued spline. - -INPUT PARAMETERS: - X - spline abscissas, array[0..N-1] - Y - spline ordinates, array[0..M-1] - Z - spline applicates, array[0..L-1] - F - function values, array[0..M*N*L*D-1]: - * first D elements store D values at (X[0],Y[0],Z[0]) - * next D elements store D values at (X[1],Y[0],Z[0]) - * next D elements store D values at (X[2],Y[0],Z[0]) - * ... - * next D elements store D values at (X[0],Y[1],Z[0]) - * next D elements store D values at (X[1],Y[1],Z[0]) - * next D elements store D values at (X[2],Y[1],Z[0]) - * ... - * next D elements store D values at (X[0],Y[0],Z[1]) - * next D elements store D values at (X[1],Y[0],Z[1]) - * next D elements store D values at (X[2],Y[0],Z[1]) - * ... - * general form - D function values at (X[i],Y[j]) are stored - at F[D*(N*(M*K+J)+I)...D*(N*(M*K+J)+I)+D-1]. - M,N, - L - grid size, M>=2, N>=2, L>=2 - D - vector dimension, D>=1 - -OUTPUT PARAMETERS: - C - spline interpolant - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline3dbuildtrilinearv(const real_1d_array &x, const ae_int_t n, const real_1d_array &y, const ae_int_t m, const real_1d_array &z, const ae_int_t l, const real_1d_array &f, const ae_int_t d, spline3dinterpolant &c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine calculates bilinear or bicubic vector-valued spline at the -given point (X,Y,Z). - -INPUT PARAMETERS: - C - spline interpolant. - X, Y, - Z - point - F - output buffer, possibly preallocated array. In case array size - is large enough to store result, it is not reallocated. Array - which is too short will be reallocated - -OUTPUT PARAMETERS: - F - array[D] (or larger) which stores function values - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline3dcalcvbuf(const spline3dinterpolant &c, const double x, const double y, const double z, real_1d_array &f, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine calculates trilinear or tricubic vector-valued spline at the -given point (X,Y,Z). - -INPUT PARAMETERS: - C - spline interpolant. - X, Y, - Z - point - -OUTPUT PARAMETERS: - F - array[D] which stores function values. F is out-parameter and - it is reallocated after call to this function. In case you - want to reuse previously allocated F, you may use - Spline2DCalcVBuf(), which reallocates F only when it is too - small. - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline3dcalcv(const spline3dinterpolant &c, const double x, const double y, const double z, real_1d_array &f, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine unpacks tri-dimensional spline into the coefficients table - -INPUT PARAMETERS: - C - spline interpolant. - -Result: - N - grid size (X) - M - grid size (Y) - L - grid size (Z) - D - number of components - SType- spline type. Currently, only one spline type is supported: - trilinear spline, as indicated by SType=1. - Tbl - spline coefficients: [0..(N-1)*(M-1)*(L-1)*D-1, 0..13]. - For T=0..D-1 (component index), I = 0...N-2 (x index), - J=0..M-2 (y index), K=0..L-2 (z index): - Q := T + I*D + J*D*(N-1) + K*D*(N-1)*(M-1), - - Q-th row stores decomposition for T-th component of the - vector-valued function - - Tbl[Q,0] = X[i] - Tbl[Q,1] = X[i+1] - Tbl[Q,2] = Y[j] - Tbl[Q,3] = Y[j+1] - Tbl[Q,4] = Z[k] - Tbl[Q,5] = Z[k+1] - - Tbl[Q,6] = C000 - Tbl[Q,7] = C100 - Tbl[Q,8] = C010 - Tbl[Q,9] = C110 - Tbl[Q,10]= C001 - Tbl[Q,11]= C101 - Tbl[Q,12]= C011 - Tbl[Q,13]= C111 - On each grid square spline is equals to: - S(x) = SUM(c[i,j,k]*(x^i)*(y^j)*(z^k), i=0..1, j=0..1, k=0..1) - t = x-x[j] - u = y-y[i] - v = z-z[k] - - NOTE: format of Tbl is given for SType=1. Future versions of - ALGLIB can use different formats for different values of - SType. - - -- ALGLIB PROJECT -- - Copyright 26.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline3dunpackv(const spline3dinterpolant &c, ae_int_t &n, ae_int_t &m, ae_int_t &l, ae_int_t &d, ae_int_t &stype, real_2d_array &tbl, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_POLINT) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Conversion from barycentric representation to Chebyshev basis. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - P - polynomial in barycentric form - A,B - base interval for Chebyshev polynomials (see below) - A<>B - -OUTPUT PARAMETERS - T - coefficients of Chebyshev representation; - P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N-1 }, - where Ti - I-th Chebyshev polynomial. - -NOTES: - barycentric interpolant passed as P may be either polynomial obtained - from polynomial interpolation/ fitting or rational function which is - NOT polynomial. We can't distinguish between these two cases, and this - algorithm just tries to work assuming that P IS a polynomial. If not, - algorithm will return results, but they won't have any meaning. - - -- ALGLIB -- - Copyright 30.09.2010 by Bochkanov Sergey -*************************************************************************/ -void polynomialbar2cheb(const barycentricinterpolant &p, const double a, const double b, real_1d_array &t, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Conversion from Chebyshev basis to barycentric representation. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - T - coefficients of Chebyshev representation; - P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N }, - where Ti - I-th Chebyshev polynomial. - N - number of coefficients: - * if given, only leading N elements of T are used - * if not given, automatically determined from size of T - A,B - base interval for Chebyshev polynomials (see above) - A0. - -OUTPUT PARAMETERS - A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 } - N - number of coefficients (polynomial degree plus 1) - -NOTES: -1. this function accepts offset and scale, which can be set to improve - numerical properties of polynomial. For example, if P was obtained as - result of interpolation on [-1,+1], you can set C=0 and S=1 and - represent P as sum of 1, x, x^2, x^3 and so on. In most cases you it - is exactly what you need. - - However, if your interpolation model was built on [999,1001], you will - see significant growth of numerical errors when using {1, x, x^2, x^3} - as basis. Representing P as sum of 1, (x-1000), (x-1000)^2, (x-1000)^3 - will be better option. Such representation can be obtained by using - 1000.0 as offset C and 1.0 as scale S. - -2. power basis is ill-conditioned and tricks described above can't solve - this problem completely. This function will return coefficients in - any case, but for N>8 they will become unreliable. However, N's - less than 5 are pretty safe. - -3. barycentric interpolant passed as P may be either polynomial obtained - from polynomial interpolation/ fitting or rational function which is - NOT polynomial. We can't distinguish between these two cases, and this - algorithm just tries to work assuming that P IS a polynomial. If not, - algorithm will return results, but they won't have any meaning. - - -- ALGLIB -- - Copyright 30.09.2010 by Bochkanov Sergey -*************************************************************************/ -void polynomialbar2pow(const barycentricinterpolant &p, const double c, const double s, real_1d_array &a, const xparams _xparams = alglib::xdefault); -void polynomialbar2pow(const barycentricinterpolant &p, real_1d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Conversion from power basis to barycentric representation. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 } - N - number of coefficients (polynomial degree plus 1) - * if given, only leading N elements of A are used - * if not given, automatically determined from size of A - C - offset (see below); 0.0 is used as default value. - S - scale (see below); 1.0 is used as default value. S<>0. - -OUTPUT PARAMETERS - P - polynomial in barycentric form - - -NOTES: -1. this function accepts offset and scale, which can be set to improve - numerical properties of polynomial. For example, if you interpolate on - [-1,+1], you can set C=0 and S=1 and convert from sum of 1, x, x^2, - x^3 and so on. In most cases you it is exactly what you need. - - However, if your interpolation model was built on [999,1001], you will - see significant growth of numerical errors when using {1, x, x^2, x^3} - as input basis. Converting from sum of 1, (x-1000), (x-1000)^2, - (x-1000)^3 will be better option (you have to specify 1000.0 as offset - C and 1.0 as scale S). - -2. power basis is ill-conditioned and tricks described above can't solve - this problem completely. This function will return barycentric model - in any case, but for N>8 accuracy well degrade. However, N's less than - 5 are pretty safe. - - -- ALGLIB -- - Copyright 30.09.2010 by Bochkanov Sergey -*************************************************************************/ -void polynomialpow2bar(const real_1d_array &a, const ae_int_t n, const double c, const double s, barycentricinterpolant &p, const xparams _xparams = alglib::xdefault); -void polynomialpow2bar(const real_1d_array &a, barycentricinterpolant &p, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Lagrange intepolant: generation of the model on the general grid. -This function has O(N^2) complexity. - -INPUT PARAMETERS: - X - abscissas, array[0..N-1] - Y - function values, array[0..N-1] - N - number of points, N>=1 - -OUTPUT PARAMETERS - P - barycentric model which represents Lagrange interpolant - (see ratint unit info and BarycentricCalc() description for - more information). - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -void polynomialbuild(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, barycentricinterpolant &p, const xparams _xparams = alglib::xdefault); -void polynomialbuild(const real_1d_array &x, const real_1d_array &y, barycentricinterpolant &p, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Lagrange intepolant: generation of the model on equidistant grid. -This function has O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - Y - function values at the nodes, array[0..N-1] - N - number of points, N>=1 - for N=1 a constant model is constructed. - -OUTPUT PARAMETERS - P - barycentric model which represents Lagrange interpolant - (see ratint unit info and BarycentricCalc() description for - more information). - - -- ALGLIB -- - Copyright 03.12.2009 by Bochkanov Sergey -*************************************************************************/ -void polynomialbuildeqdist(const double a, const double b, const real_1d_array &y, const ae_int_t n, barycentricinterpolant &p, const xparams _xparams = alglib::xdefault); -void polynomialbuildeqdist(const double a, const double b, const real_1d_array &y, barycentricinterpolant &p, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Lagrange intepolant on Chebyshev grid (first kind). -This function has O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - Y - function values at the nodes, array[0..N-1], - Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n))) - N - number of points, N>=1 - for N=1 a constant model is constructed. - -OUTPUT PARAMETERS - P - barycentric model which represents Lagrange interpolant - (see ratint unit info and BarycentricCalc() description for - more information). - - -- ALGLIB -- - Copyright 03.12.2009 by Bochkanov Sergey -*************************************************************************/ -void polynomialbuildcheb1(const double a, const double b, const real_1d_array &y, const ae_int_t n, barycentricinterpolant &p, const xparams _xparams = alglib::xdefault); -void polynomialbuildcheb1(const double a, const double b, const real_1d_array &y, barycentricinterpolant &p, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Lagrange intepolant on Chebyshev grid (second kind). -This function has O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - Y - function values at the nodes, array[0..N-1], - Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1))) - N - number of points, N>=1 - for N=1 a constant model is constructed. - -OUTPUT PARAMETERS - P - barycentric model which represents Lagrange interpolant - (see ratint unit info and BarycentricCalc() description for - more information). - - -- ALGLIB -- - Copyright 03.12.2009 by Bochkanov Sergey -*************************************************************************/ -void polynomialbuildcheb2(const double a, const double b, const real_1d_array &y, const ae_int_t n, barycentricinterpolant &p, const xparams _xparams = alglib::xdefault); -void polynomialbuildcheb2(const double a, const double b, const real_1d_array &y, barycentricinterpolant &p, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Fast equidistant polynomial interpolation function with O(N) complexity - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - F - function values, array[0..N-1] - N - number of points on equidistant grid, N>=1 - for N=1 a constant model is constructed. - T - position where P(x) is calculated - -RESULT - value of the Lagrange interpolant at T - -IMPORTANT - this function provides fast interface which is not overflow-safe - nor it is very precise. - the best option is to use PolynomialBuildEqDist()/BarycentricCalc() - subroutines unless you are pretty sure that your data will not result - in overflow. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -double polynomialcalceqdist(const double a, const double b, const real_1d_array &f, const ae_int_t n, const double t, const xparams _xparams = alglib::xdefault); -double polynomialcalceqdist(const double a, const double b, const real_1d_array &f, const double t, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Fast polynomial interpolation function on Chebyshev points (first kind) -with O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - F - function values, array[0..N-1] - N - number of points on Chebyshev grid (first kind), - X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n)) - for N=1 a constant model is constructed. - T - position where P(x) is calculated - -RESULT - value of the Lagrange interpolant at T - -IMPORTANT - this function provides fast interface which is not overflow-safe - nor it is very precise. - the best option is to use PolIntBuildCheb1()/BarycentricCalc() - subroutines unless you are pretty sure that your data will not result - in overflow. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -double polynomialcalccheb1(const double a, const double b, const real_1d_array &f, const ae_int_t n, const double t, const xparams _xparams = alglib::xdefault); -double polynomialcalccheb1(const double a, const double b, const real_1d_array &f, const double t, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Fast polynomial interpolation function on Chebyshev points (second kind) -with O(N) complexity. - -INPUT PARAMETERS: - A - left boundary of [A,B] - B - right boundary of [A,B] - F - function values, array[0..N-1] - N - number of points on Chebyshev grid (second kind), - X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1)) - for N=1 a constant model is constructed. - T - position where P(x) is calculated - -RESULT - value of the Lagrange interpolant at T - -IMPORTANT - this function provides fast interface which is not overflow-safe - nor it is very precise. - the best option is to use PolIntBuildCheb2()/BarycentricCalc() - subroutines unless you are pretty sure that your data will not result - in overflow. - - -- ALGLIB -- - Copyright 02.12.2009 by Bochkanov Sergey -*************************************************************************/ -double polynomialcalccheb2(const double a, const double b, const real_1d_array &f, const ae_int_t n, const double t, const xparams _xparams = alglib::xdefault); -double polynomialcalccheb2(const double a, const double b, const real_1d_array &f, const double t, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_LSFIT) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This subroutine fits piecewise linear curve to points with Ramer-Douglas- -Peucker algorithm, which stops after generating specified number of linear -sections. - -IMPORTANT: -* it does NOT perform least-squares fitting; it builds curve, but this - curve does not minimize some least squares metric. See description of - RDP algorithm (say, in Wikipedia) for more details on WHAT is performed. -* this function does NOT work with parametric curves (i.e. curves which - can be represented as {X(t),Y(t)}. It works with curves which can be - represented as Y(X). Thus, it is impossible to model figures like - circles with this functions. - If you want to work with parametric curves, you should use - ParametricRDPFixed() function provided by "Parametric" subpackage of - "Interpolation" package. - -INPUT PARAMETERS: - X - array of X-coordinates: - * at least N elements - * can be unordered (points are automatically sorted) - * this function may accept non-distinct X (see below for - more information on handling of such inputs) - Y - array of Y-coordinates: - * at least N elements - N - number of elements in X/Y - M - desired number of sections: - * at most M sections are generated by this function - * less than M sections can be generated if we have N0 - * if given, only leading N elements of X/Y are used - * if not given, automatically determined from sizes of X/Y - M - number of basis functions (= polynomial_degree + 1), M>=1 - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearW() subroutine: - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - P - interpolant in barycentric form. - Rep - report, same format as in LSFitLinearW() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - - -- ALGLIB PROJECT -- - Copyright 10.12.2009 by Bochkanov Sergey -*************************************************************************/ -void polynomialfit(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t m, ae_int_t &info, barycentricinterpolant &p, polynomialfitreport &rep, const xparams _xparams = alglib::xdefault); -void polynomialfit(const real_1d_array &x, const real_1d_array &y, const ae_int_t m, ae_int_t &info, barycentricinterpolant &p, polynomialfitreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Weighted fitting by polynomials in barycentric form, with constraints on -function values or first derivatives. - -Small regularizing term is used when solving constrained tasks (to improve -stability). - -Task is linear, so linear least squares solver is used. Complexity of this -computational scheme is O(N*M^2), mostly dominated by least squares solver - -SEE ALSO: - PolynomialFit() - -NOTES: - you can convert P from barycentric form to the power or Chebyshev - basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions from - POLINT subpackage. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - W - weights, array[0..N-1] - Each summand in square sum of approximation deviations from - given values is multiplied by the square of corresponding - weight. Fill it by 1's if you don't want to solve weighted - task. - N - number of points, N>0. - * if given, only leading N elements of X/Y/W are used - * if not given, automatically determined from sizes of X/Y/W - XC - points where polynomial values/derivatives are constrained, - array[0..K-1]. - YC - values of constraints, array[0..K-1] - DC - array[0..K-1], types of constraints: - * DC[i]=0 means that P(XC[i])=YC[i] - * DC[i]=1 means that P'(XC[i])=YC[i] - SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS - K - number of constraints, 0<=K=1 - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearW() subroutine: - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - P - interpolant in barycentric form. - Rep - report, same format as in LSFitLinearW() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - -SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: - -Setting constraints can lead to undesired results, like ill-conditioned -behavior, or inconsistency being detected. From the other side, it allows -us to improve quality of the fit. Here we summarize our experience with -constrained regression splines: -* even simple constraints can be inconsistent, see Wikipedia article on - this subject: http://en.wikipedia.org/wiki/Birkhoff_interpolation -* the greater is M (given fixed constraints), the more chances that - constraints will be consistent -* in the general case, consistency of constraints is NOT GUARANTEED. -* in the one special cases, however, we can guarantee consistency. This - case is: M>1 and constraints on the function values (NOT DERIVATIVES) - -Our final recommendation is to use constraints WHEN AND ONLY when you -can't solve your task without them. Anything beyond special cases given -above is not guaranteed and may result in inconsistency. - - -- ALGLIB PROJECT -- - Copyright 10.12.2009 by Bochkanov Sergey -*************************************************************************/ -void polynomialfitwc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t n, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t k, const ae_int_t m, ae_int_t &info, barycentricinterpolant &p, polynomialfitreport &rep, const xparams _xparams = alglib::xdefault); -void polynomialfitwc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t m, ae_int_t &info, barycentricinterpolant &p, polynomialfitreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates value of four-parameter logistic (4PL) model at -specified point X. 4PL model has following form: - - F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B)) - -INPUT PARAMETERS: - X - current point, X>=0: - * zero X is correctly handled even for B<=0 - * negative X results in exception. - A, B, C, D- parameters of 4PL model: - * A is unconstrained - * B is unconstrained; zero or negative values are handled - correctly. - * C>0, non-positive value results in exception - * D is unconstrained - -RESULT: - model value at X - -NOTE: if B=0, denominator is assumed to be equal to 2.0 even for zero X - (strictly speaking, 0^0 is undefined). - -NOTE: this function also throws exception if all input parameters are - correct, but overflow was detected during calculations. - -NOTE: this function performs a lot of checks; if you need really high - performance, consider evaluating model yourself, without checking - for degenerate cases. - - - -- ALGLIB PROJECT -- - Copyright 14.05.2014 by Bochkanov Sergey -*************************************************************************/ -double logisticcalc4(const double x, const double a, const double b, const double c, const double d, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates value of five-parameter logistic (5PL) model at -specified point X. 5PL model has following form: - - F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G) - -INPUT PARAMETERS: - X - current point, X>=0: - * zero X is correctly handled even for B<=0 - * negative X results in exception. - A, B, C, D, G- parameters of 5PL model: - * A is unconstrained - * B is unconstrained; zero or negative values are handled - correctly. - * C>0, non-positive value results in exception - * D is unconstrained - * G>0, non-positive value results in exception - -RESULT: - model value at X - -NOTE: if B=0, denominator is assumed to be equal to Power(2.0,G) even for - zero X (strictly speaking, 0^0 is undefined). - -NOTE: this function also throws exception if all input parameters are - correct, but overflow was detected during calculations. - -NOTE: this function performs a lot of checks; if you need really high - performance, consider evaluating model yourself, without checking - for degenerate cases. - - - -- ALGLIB PROJECT -- - Copyright 14.05.2014 by Bochkanov Sergey -*************************************************************************/ -double logisticcalc5(const double x, const double a, const double b, const double c, const double d, const double g, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function fits four-parameter logistic (4PL) model to data provided -by user. 4PL model has following form: - - F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B)) - -Here: - * A, D - unconstrained (see LogisticFit4EC() for constrained 4PL) - * B>=0 - * C>0 - -IMPORTANT: output of this function is constrained in such way that B>0. - Because 4PL model is symmetric with respect to B, there is no - need to explore B<0. Constraining B makes algorithm easier - to stabilize and debug. - Users who for some reason prefer to work with negative B's - should transform output themselves (swap A and D, replace B by - -B). - -4PL fitting is implemented as follows: -* we perform small number of restarts from random locations which helps to - solve problem of bad local extrema. Locations are only partially random - - we use input data to determine good initial guess, but we include - controlled amount of randomness. -* we perform Levenberg-Marquardt fitting with very tight constraints on - parameters B and C - it allows us to find good initial guess for the - second stage without risk of running into "flat spot". -* second Levenberg-Marquardt round is performed without excessive - constraints. Results from the previous round are used as initial guess. -* after fitting is done, we compare results with best values found so far, - rewrite "best solution" if needed, and move to next random location. - -Overall algorithm is very stable and is not prone to bad local extrema. -Furthermore, it automatically scales when input data have very large or -very small range. - -INPUT PARAMETERS: - X - array[N], stores X-values. - MUST include only non-negative numbers (but may include - zero values). Can be unsorted. - Y - array[N], values to fit. - N - number of points. If N is less than length of X/Y, only - leading N elements are used. - -OUTPUT PARAMETERS: - A, B, C, D- parameters of 4PL model - Rep - fitting report. This structure has many fields, but ONLY - ONES LISTED BELOW ARE SET: - * Rep.IterationsCount - number of iterations performed - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average absolute error - * Rep.AvgRelError - average relative error (calculated for - non-zero Y-values) - * Rep.MaxError - maximum absolute error - * Rep.R2 - coefficient of determination, R-squared. This - coefficient is calculated as R2=1-RSS/TSS (in case - of nonlinear regression there are multiple ways to - define R2, each of them giving different results). - -NOTE: for stability reasons the B parameter is restricted by [1/1000,1000] - range. It prevents algorithm from making trial steps deep into the - area of bad parameters. - -NOTE: after you obtained coefficients, you can evaluate model with - LogisticCalc4() function. - -NOTE: if you need better control over fitting process than provided by this - function, you may use LogisticFit45X(). - -NOTE: step is automatically scaled according to scale of parameters being - fitted before we compare its length with EpsX. Thus, this function - can be used to fit data with very small or very large values without - changing EpsX. - - - -- ALGLIB PROJECT -- - Copyright 14.02.2014 by Bochkanov Sergey -*************************************************************************/ -void logisticfit4(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, double &a, double &b, double &c, double &d, lsfitreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function fits four-parameter logistic (4PL) model to data provided -by user, with optional constraints on parameters A and D. 4PL model has -following form: - - F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B)) - -Here: - * A, D - with optional equality constraints - * B>=0 - * C>0 - -IMPORTANT: output of this function is constrained in such way that B>0. - Because 4PL model is symmetric with respect to B, there is no - need to explore B<0. Constraining B makes algorithm easier - to stabilize and debug. - Users who for some reason prefer to work with negative B's - should transform output themselves (swap A and D, replace B by - -B). - -4PL fitting is implemented as follows: -* we perform small number of restarts from random locations which helps to - solve problem of bad local extrema. Locations are only partially random - - we use input data to determine good initial guess, but we include - controlled amount of randomness. -* we perform Levenberg-Marquardt fitting with very tight constraints on - parameters B and C - it allows us to find good initial guess for the - second stage without risk of running into "flat spot". -* second Levenberg-Marquardt round is performed without excessive - constraints. Results from the previous round are used as initial guess. -* after fitting is done, we compare results with best values found so far, - rewrite "best solution" if needed, and move to next random location. - -Overall algorithm is very stable and is not prone to bad local extrema. -Furthermore, it automatically scales when input data have very large or -very small range. - -INPUT PARAMETERS: - X - array[N], stores X-values. - MUST include only non-negative numbers (but may include - zero values). Can be unsorted. - Y - array[N], values to fit. - N - number of points. If N is less than length of X/Y, only - leading N elements are used. - CnstrLeft- optional equality constraint for model value at the left - boundary (at X=0). Specify NAN (Not-a-Number) if you do - not need constraint on the model value at X=0 (in C++ you - can pass alglib::fp_nan as parameter, in C# it will be - Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - CnstrRight- optional equality constraint for model value at X=infinity. - Specify NAN (Not-a-Number) if you do not need constraint - on the model value (in C++ you can pass alglib::fp_nan as - parameter, in C# it will be Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - -OUTPUT PARAMETERS: - A, B, C, D- parameters of 4PL model - Rep - fitting report. This structure has many fields, but ONLY - ONES LISTED BELOW ARE SET: - * Rep.IterationsCount - number of iterations performed - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average absolute error - * Rep.AvgRelError - average relative error (calculated for - non-zero Y-values) - * Rep.MaxError - maximum absolute error - * Rep.R2 - coefficient of determination, R-squared. This - coefficient is calculated as R2=1-RSS/TSS (in case - of nonlinear regression there are multiple ways to - define R2, each of them giving different results). - -NOTE: for stability reasons the B parameter is restricted by [1/1000,1000] - range. It prevents algorithm from making trial steps deep into the - area of bad parameters. - -NOTE: after you obtained coefficients, you can evaluate model with - LogisticCalc4() function. - -NOTE: if you need better control over fitting process than provided by this - function, you may use LogisticFit45X(). - -NOTE: step is automatically scaled according to scale of parameters being - fitted before we compare its length with EpsX. Thus, this function - can be used to fit data with very small or very large values without - changing EpsX. - -EQUALITY CONSTRAINTS ON PARAMETERS - -4PL/5PL solver supports equality constraints on model values at the left -boundary (X=0) and right boundary (X=infinity). These constraints are -completely optional and you can specify both of them, only one - or no -constraints at all. - -Parameter CnstrLeft contains left constraint (or NAN for unconstrained -fitting), and CnstrRight contains right one. For 4PL, left constraint -ALWAYS corresponds to parameter A, and right one is ALWAYS constraint on -D. That's because 4PL model is normalized in such way that B>=0. - - - -- ALGLIB PROJECT -- - Copyright 14.02.2014 by Bochkanov Sergey -*************************************************************************/ -void logisticfit4ec(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const double cnstrleft, const double cnstrright, double &a, double &b, double &c, double &d, lsfitreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function fits five-parameter logistic (5PL) model to data provided -by user. 5PL model has following form: - - F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G) - -Here: - * A, D - unconstrained - * B - unconstrained - * C>0 - * G>0 - -IMPORTANT: unlike in 4PL fitting, output of this function is NOT - constrained in such way that B is guaranteed to be positive. - Furthermore, unlike 4PL, 5PL model is NOT symmetric with - respect to B, so you can NOT transform model to equivalent one, - with B having desired sign (>0 or <0). - -5PL fitting is implemented as follows: -* we perform small number of restarts from random locations which helps to - solve problem of bad local extrema. Locations are only partially random - - we use input data to determine good initial guess, but we include - controlled amount of randomness. -* we perform Levenberg-Marquardt fitting with very tight constraints on - parameters B and C - it allows us to find good initial guess for the - second stage without risk of running into "flat spot". Parameter G is - fixed at G=1. -* second Levenberg-Marquardt round is performed without excessive - constraints on B and C, but with G still equal to 1. Results from the - previous round are used as initial guess. -* third Levenberg-Marquardt round relaxes constraints on G and tries two - different models - one with B>0 and one with B<0. -* after fitting is done, we compare results with best values found so far, - rewrite "best solution" if needed, and move to next random location. - -Overall algorithm is very stable and is not prone to bad local extrema. -Furthermore, it automatically scales when input data have very large or -very small range. - -INPUT PARAMETERS: - X - array[N], stores X-values. - MUST include only non-negative numbers (but may include - zero values). Can be unsorted. - Y - array[N], values to fit. - N - number of points. If N is less than length of X/Y, only - leading N elements are used. - -OUTPUT PARAMETERS: - A,B,C,D,G- parameters of 5PL model - Rep - fitting report. This structure has many fields, but ONLY - ONES LISTED BELOW ARE SET: - * Rep.IterationsCount - number of iterations performed - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average absolute error - * Rep.AvgRelError - average relative error (calculated for - non-zero Y-values) - * Rep.MaxError - maximum absolute error - * Rep.R2 - coefficient of determination, R-squared. This - coefficient is calculated as R2=1-RSS/TSS (in case - of nonlinear regression there are multiple ways to - define R2, each of them giving different results). - -NOTE: for better stability B parameter is restricted by [+-1/1000,+-1000] - range, and G is restricted by [1/10,10] range. It prevents algorithm - from making trial steps deep into the area of bad parameters. - -NOTE: after you obtained coefficients, you can evaluate model with - LogisticCalc5() function. - -NOTE: if you need better control over fitting process than provided by this - function, you may use LogisticFit45X(). - -NOTE: step is automatically scaled according to scale of parameters being - fitted before we compare its length with EpsX. Thus, this function - can be used to fit data with very small or very large values without - changing EpsX. - - - -- ALGLIB PROJECT -- - Copyright 14.02.2014 by Bochkanov Sergey -*************************************************************************/ -void logisticfit5(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, double &a, double &b, double &c, double &d, double &g, lsfitreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function fits five-parameter logistic (5PL) model to data provided -by user, subject to optional equality constraints on parameters A and D. -5PL model has following form: - - F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G) - -Here: - * A, D - with optional equality constraints - * B - unconstrained - * C>0 - * G>0 - -IMPORTANT: unlike in 4PL fitting, output of this function is NOT - constrained in such way that B is guaranteed to be positive. - Furthermore, unlike 4PL, 5PL model is NOT symmetric with - respect to B, so you can NOT transform model to equivalent one, - with B having desired sign (>0 or <0). - -5PL fitting is implemented as follows: -* we perform small number of restarts from random locations which helps to - solve problem of bad local extrema. Locations are only partially random - - we use input data to determine good initial guess, but we include - controlled amount of randomness. -* we perform Levenberg-Marquardt fitting with very tight constraints on - parameters B and C - it allows us to find good initial guess for the - second stage without risk of running into "flat spot". Parameter G is - fixed at G=1. -* second Levenberg-Marquardt round is performed without excessive - constraints on B and C, but with G still equal to 1. Results from the - previous round are used as initial guess. -* third Levenberg-Marquardt round relaxes constraints on G and tries two - different models - one with B>0 and one with B<0. -* after fitting is done, we compare results with best values found so far, - rewrite "best solution" if needed, and move to next random location. - -Overall algorithm is very stable and is not prone to bad local extrema. -Furthermore, it automatically scales when input data have very large or -very small range. - -INPUT PARAMETERS: - X - array[N], stores X-values. - MUST include only non-negative numbers (but may include - zero values). Can be unsorted. - Y - array[N], values to fit. - N - number of points. If N is less than length of X/Y, only - leading N elements are used. - CnstrLeft- optional equality constraint for model value at the left - boundary (at X=0). Specify NAN (Not-a-Number) if you do - not need constraint on the model value at X=0 (in C++ you - can pass alglib::fp_nan as parameter, in C# it will be - Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - CnstrRight- optional equality constraint for model value at X=infinity. - Specify NAN (Not-a-Number) if you do not need constraint - on the model value (in C++ you can pass alglib::fp_nan as - parameter, in C# it will be Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - -OUTPUT PARAMETERS: - A,B,C,D,G- parameters of 5PL model - Rep - fitting report. This structure has many fields, but ONLY - ONES LISTED BELOW ARE SET: - * Rep.IterationsCount - number of iterations performed - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average absolute error - * Rep.AvgRelError - average relative error (calculated for - non-zero Y-values) - * Rep.MaxError - maximum absolute error - * Rep.R2 - coefficient of determination, R-squared. This - coefficient is calculated as R2=1-RSS/TSS (in case - of nonlinear regression there are multiple ways to - define R2, each of them giving different results). - -NOTE: for better stability B parameter is restricted by [+-1/1000,+-1000] - range, and G is restricted by [1/10,10] range. It prevents algorithm - from making trial steps deep into the area of bad parameters. - -NOTE: after you obtained coefficients, you can evaluate model with - LogisticCalc5() function. - -NOTE: if you need better control over fitting process than provided by this - function, you may use LogisticFit45X(). - -NOTE: step is automatically scaled according to scale of parameters being - fitted before we compare its length with EpsX. Thus, this function - can be used to fit data with very small or very large values without - changing EpsX. - -EQUALITY CONSTRAINTS ON PARAMETERS - -5PL solver supports equality constraints on model values at the left -boundary (X=0) and right boundary (X=infinity). These constraints are -completely optional and you can specify both of them, only one - or no -constraints at all. - -Parameter CnstrLeft contains left constraint (or NAN for unconstrained -fitting), and CnstrRight contains right one. - -Unlike 4PL one, 5PL model is NOT symmetric with respect to change in sign -of B. Thus, negative B's are possible, and left constraint may constrain -parameter A (for positive B's) - or parameter D (for negative B's). -Similarly changes meaning of right constraint. - -You do not have to decide what parameter to constrain - algorithm will -automatically determine correct parameters as fitting progresses. However, -question highlighted above is important when you interpret fitting results. - - - -- ALGLIB PROJECT -- - Copyright 14.02.2014 by Bochkanov Sergey -*************************************************************************/ -void logisticfit5ec(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const double cnstrleft, const double cnstrright, double &a, double &b, double &c, double &d, double &g, lsfitreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is "expert" 4PL/5PL fitting function, which can be used if you need -better control over fitting process than provided by LogisticFit4() or -LogisticFit5(). - -This function fits model of the form - - F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B)) (4PL model) - -or - - F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G) (5PL model) - -Here: - * A, D - unconstrained - * B>=0 for 4PL, unconstrained for 5PL - * C>0 - * G>0 (if present) - -INPUT PARAMETERS: - X - array[N], stores X-values. - MUST include only non-negative numbers (but may include - zero values). Can be unsorted. - Y - array[N], values to fit. - N - number of points. If N is less than length of X/Y, only - leading N elements are used. - CnstrLeft- optional equality constraint for model value at the left - boundary (at X=0). Specify NAN (Not-a-Number) if you do - not need constraint on the model value at X=0 (in C++ you - can pass alglib::fp_nan as parameter, in C# it will be - Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - CnstrRight- optional equality constraint for model value at X=infinity. - Specify NAN (Not-a-Number) if you do not need constraint - on the model value (in C++ you can pass alglib::fp_nan as - parameter, in C# it will be Double.NaN). - See below, section "EQUALITY CONSTRAINTS" for more - information about constraints. - Is4PL - whether 4PL or 5PL models are fitted - LambdaV - regularization coefficient, LambdaV>=0. - Set it to zero unless you know what you are doing. - EpsX - stopping condition (step size), EpsX>=0. - Zero value means that small step is automatically chosen. - See notes below for more information. - RsCnt - number of repeated restarts from random points. 4PL/5PL - models are prone to problem of bad local extrema. Utilizing - multiple random restarts allows us to improve algorithm - convergence. - RsCnt>=0. - Zero value means that function automatically choose small - amount of restarts (recommended). - -OUTPUT PARAMETERS: - A, B, C, D- parameters of 4PL model - G - parameter of 5PL model; for Is4PL=True, G=1 is returned. - Rep - fitting report. This structure has many fields, but ONLY - ONES LISTED BELOW ARE SET: - * Rep.IterationsCount - number of iterations performed - * Rep.RMSError - root-mean-square error - * Rep.AvgError - average absolute error - * Rep.AvgRelError - average relative error (calculated for - non-zero Y-values) - * Rep.MaxError - maximum absolute error - * Rep.R2 - coefficient of determination, R-squared. This - coefficient is calculated as R2=1-RSS/TSS (in case - of nonlinear regression there are multiple ways to - define R2, each of them giving different results). - -NOTE: for better stability B parameter is restricted by [+-1/1000,+-1000] - range, and G is restricted by [1/10,10] range. It prevents algorithm - from making trial steps deep into the area of bad parameters. - -NOTE: after you obtained coefficients, you can evaluate model with - LogisticCalc5() function. - -NOTE: step is automatically scaled according to scale of parameters being - fitted before we compare its length with EpsX. Thus, this function - can be used to fit data with very small or very large values without - changing EpsX. - -EQUALITY CONSTRAINTS ON PARAMETERS - -4PL/5PL solver supports equality constraints on model values at the left -boundary (X=0) and right boundary (X=infinity). These constraints are -completely optional and you can specify both of them, only one - or no -constraints at all. - -Parameter CnstrLeft contains left constraint (or NAN for unconstrained -fitting), and CnstrRight contains right one. For 4PL, left constraint -ALWAYS corresponds to parameter A, and right one is ALWAYS constraint on -D. That's because 4PL model is normalized in such way that B>=0. - -For 5PL model things are different. Unlike 4PL one, 5PL model is NOT -symmetric with respect to change in sign of B. Thus, negative B's are -possible, and left constraint may constrain parameter A (for positive B's) -- or parameter D (for negative B's). Similarly changes meaning of right -constraint. - -You do not have to decide what parameter to constrain - algorithm will -automatically determine correct parameters as fitting progresses. However, -question highlighted above is important when you interpret fitting results. - - - -- ALGLIB PROJECT -- - Copyright 14.02.2014 by Bochkanov Sergey -*************************************************************************/ -void logisticfit45x(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const double cnstrleft, const double cnstrright, const bool is4pl, const double lambdav, const double epsx, const ae_int_t rscnt, double &a, double &b, double &c, double &d, double &g, lsfitreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Weghted rational least squares fitting using Floater-Hormann rational -functions with optimal D chosen from [0,9], with constraints and -individual weights. - -Equidistant grid with M node on [min(x),max(x)] is used to build basis -functions. Different values of D are tried, optimal D (least WEIGHTED root -mean square error) is chosen. Task is linear, so linear least squares -solver is used. Complexity of this computational scheme is O(N*M^2) -(mostly dominated by the least squares solver). - -SEE ALSO -* BarycentricFitFloaterHormann(), "lightweight" fitting without invididual - weights and constraints. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - W - weights, array[0..N-1] - Each summand in square sum of approximation deviations from - given values is multiplied by the square of corresponding - weight. Fill it by 1's if you don't want to solve weighted - task. - N - number of points, N>0. - XC - points where function values/derivatives are constrained, - array[0..K-1]. - YC - values of constraints, array[0..K-1] - DC - array[0..K-1], types of constraints: - * DC[i]=0 means that S(XC[i])=YC[i] - * DC[i]=1 means that S'(XC[i])=YC[i] - SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS - K - number of constraints, 0<=K=2. - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearWC() subroutine. - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - -1 means another errors in parameters passed - (N<=0, for example) - B - barycentric interpolant. - Rep - report, same format as in LSFitLinearWC() subroutine. - Following fields are set: - * DBest best value of the D parameter - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroutine doesn't calculate task's condition number for K<>0. - -SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: - -Setting constraints can lead to undesired results, like ill-conditioned -behavior, or inconsistency being detected. From the other side, it allows -us to improve quality of the fit. Here we summarize our experience with -constrained barycentric interpolants: -* excessive constraints can be inconsistent. Floater-Hormann basis - functions aren't as flexible as splines (although they are very smooth). -* the more evenly constraints are spread across [min(x),max(x)], the more - chances that they will be consistent -* the greater is M (given fixed constraints), the more chances that - constraints will be consistent -* in the general case, consistency of constraints IS NOT GUARANTEED. -* in the several special cases, however, we CAN guarantee consistency. -* one of this cases is constraints on the function VALUES at the interval - boundaries. Note that consustency of the constraints on the function - DERIVATIVES is NOT guaranteed (you can use in such cases cubic splines - which are more flexible). -* another special case is ONE constraint on the function value (OR, but - not AND, derivative) anywhere in the interval - -Our final recommendation is to use constraints WHEN AND ONLY WHEN you -can't solve your task without them. Anything beyond special cases given -above is not guaranteed and may result in inconsistency. - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentricfitfloaterhormannwc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t n, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t k, const ae_int_t m, ae_int_t &info, barycentricinterpolant &b, barycentricfitreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Rational least squares fitting using Floater-Hormann rational functions -with optimal D chosen from [0,9]. - -Equidistant grid with M node on [min(x),max(x)] is used to build basis -functions. Different values of D are tried, optimal D (least root mean -square error) is chosen. Task is linear, so linear least squares solver -is used. Complexity of this computational scheme is O(N*M^2) (mostly -dominated by the least squares solver). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - N - number of points, N>0. - M - number of basis functions ( = number_of_nodes), M>=2. - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearWC() subroutine. - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - B - barycentric interpolant. - Rep - report, same format as in LSFitLinearWC() subroutine. - Following fields are set: - * DBest best value of the D parameter - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -void barycentricfitfloaterhormann(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t m, ae_int_t &info, barycentricinterpolant &b, barycentricfitreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Weighted fitting by cubic spline, with constraints on function values or -derivatives. - -Equidistant grid with M-2 nodes on [min(x,xc),max(x,xc)] is used to build -basis functions. Basis functions are cubic splines with continuous second -derivatives and non-fixed first derivatives at interval ends. Small -regularizing term is used when solving constrained tasks (to improve -stability). - -Task is linear, so linear least squares solver is used. Complexity of this -computational scheme is O(N*M^2), mostly dominated by least squares solver - -SEE ALSO - Spline1DFitHermiteWC() - fitting by Hermite splines (more flexible, - less smooth) - Spline1DFitCubic() - "lightweight" fitting by cubic splines, - without invididual weights and constraints - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - W - weights, array[0..N-1] - Each summand in square sum of approximation deviations from - given values is multiplied by the square of corresponding - weight. Fill it by 1's if you don't want to solve weighted - task. - N - number of points (optional): - * N>0 - * if given, only first N elements of X/Y/W are processed - * if not given, automatically determined from X/Y/W sizes - XC - points where spline values/derivatives are constrained, - array[0..K-1]. - YC - values of constraints, array[0..K-1] - DC - array[0..K-1], types of constraints: - * DC[i]=0 means that S(XC[i])=YC[i] - * DC[i]=1 means that S'(XC[i])=YC[i] - SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS - K - number of constraints (optional): - * 0<=K=4. - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearWC() subroutine. - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - S - spline interpolant. - Rep - report, same format as in LSFitLinearWC() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - -SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: - -Setting constraints can lead to undesired results, like ill-conditioned -behavior, or inconsistency being detected. From the other side, it allows -us to improve quality of the fit. Here we summarize our experience with -constrained regression splines: -* excessive constraints can be inconsistent. Splines are piecewise cubic - functions, and it is easy to create an example, where large number of - constraints concentrated in small area will result in inconsistency. - Just because spline is not flexible enough to satisfy all of them. And - same constraints spread across the [min(x),max(x)] will be perfectly - consistent. -* the more evenly constraints are spread across [min(x),max(x)], the more - chances that they will be consistent -* the greater is M (given fixed constraints), the more chances that - constraints will be consistent -* in the general case, consistency of constraints IS NOT GUARANTEED. -* in the several special cases, however, we CAN guarantee consistency. -* one of this cases is constraints on the function values AND/OR its - derivatives at the interval boundaries. -* another special case is ONE constraint on the function value (OR, but - not AND, derivative) anywhere in the interval - -Our final recommendation is to use constraints WHEN AND ONLY WHEN you -can't solve your task without them. Anything beyond special cases given -above is not guaranteed and may result in inconsistency. - - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -void spline1dfitcubicwc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t n, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t k, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams = alglib::xdefault); -void spline1dfitcubicwc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Weighted fitting by Hermite spline, with constraints on function values -or first derivatives. - -Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is used to build -basis functions. Basis functions are Hermite splines. Small regularizing -term is used when solving constrained tasks (to improve stability). - -Task is linear, so linear least squares solver is used. Complexity of this -computational scheme is O(N*M^2), mostly dominated by least squares solver - -SEE ALSO - Spline1DFitCubicWC() - fitting by Cubic splines (less flexible, - more smooth) - Spline1DFitHermite() - "lightweight" Hermite fitting, without - invididual weights and constraints - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - points, array[0..N-1]. - Y - function values, array[0..N-1]. - W - weights, array[0..N-1] - Each summand in square sum of approximation deviations from - given values is multiplied by the square of corresponding - weight. Fill it by 1's if you don't want to solve weighted - task. - N - number of points (optional): - * N>0 - * if given, only first N elements of X/Y/W are processed - * if not given, automatically determined from X/Y/W sizes - XC - points where spline values/derivatives are constrained, - array[0..K-1]. - YC - values of constraints, array[0..K-1] - DC - array[0..K-1], types of constraints: - * DC[i]=0 means that S(XC[i])=YC[i] - * DC[i]=1 means that S'(XC[i])=YC[i] - SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS - K - number of constraints (optional): - * 0<=K=4, - M IS EVEN! - -OUTPUT PARAMETERS: - Info- same format as in LSFitLinearW() subroutine: - * Info>0 task is solved - * Info<=0 an error occured: - -4 means inconvergence of internal SVD - -3 means inconsistent constraints - -2 means odd M was passed (which is not supported) - -1 means another errors in parameters passed - (N<=0, for example) - S - spline interpolant. - Rep - report, same format as in LSFitLinearW() subroutine. - Following fields are set: - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - -IMPORTANT: - this subroitine supports only even M's - - -ORDER OF POINTS - -Subroutine automatically sorts points, so caller may pass unsorted array. - -SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: - -Setting constraints can lead to undesired results, like ill-conditioned -behavior, or inconsistency being detected. From the other side, it allows -us to improve quality of the fit. Here we summarize our experience with -constrained regression splines: -* excessive constraints can be inconsistent. Splines are piecewise cubic - functions, and it is easy to create an example, where large number of - constraints concentrated in small area will result in inconsistency. - Just because spline is not flexible enough to satisfy all of them. And - same constraints spread across the [min(x),max(x)] will be perfectly - consistent. -* the more evenly constraints are spread across [min(x),max(x)], the more - chances that they will be consistent -* the greater is M (given fixed constraints), the more chances that - constraints will be consistent -* in the general case, consistency of constraints is NOT GUARANTEED. -* in the several special cases, however, we can guarantee consistency. -* one of this cases is M>=4 and constraints on the function value - (AND/OR its derivative) at the interval boundaries. -* another special case is M>=4 and ONE constraint on the function value - (OR, BUT NOT AND, derivative) anywhere in [min(x),max(x)] - -Our final recommendation is to use constraints WHEN AND ONLY when you -can't solve your task without them. Anything beyond special cases given -above is not guaranteed and may result in inconsistency. - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -void spline1dfithermitewc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t n, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t k, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams = alglib::xdefault); -void spline1dfithermitewc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Least squares fitting by cubic spline. - -This subroutine is "lightweight" alternative for more complex and feature- -rich Spline1DFitCubicWC(). See Spline1DFitCubicWC() for more information -about subroutine parameters (we don't duplicate it here because of length) - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -void spline1dfitcubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams = alglib::xdefault); -void spline1dfitcubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Least squares fitting by Hermite spline. - -This subroutine is "lightweight" alternative for more complex and feature- -rich Spline1DFitHermiteWC(). See Spline1DFitHermiteWC() description for -more information about subroutine parameters (we don't duplicate it here -because of length). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -void spline1dfithermite(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams = alglib::xdefault); -void spline1dfithermite(const real_1d_array &x, const real_1d_array &y, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Weighted linear least squares fitting. - -QR decomposition is used to reduce task to MxM, then triangular solver or -SVD-based solver is used depending on condition number of the system. It -allows to maximize speed and retain decent accuracy. - -IMPORTANT: if you want to perform polynomial fitting, it may be more - convenient to use PolynomialFit() function. This function gives - best results on polynomial problems and solves numerical - stability issues which arise when you fit high-degree - polynomials to your data. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Y - array[0..N-1] Function values in N points. - W - array[0..N-1] Weights corresponding to function values. - Each summand in square sum of approximation deviations - from given values is multiplied by the square of - corresponding weight. - FMatrix - a table of basis functions values, array[0..N-1, 0..M-1]. - FMatrix[I, J] - value of J-th basis function in I-th point. - N - number of points used. N>=1. - M - number of basis functions, M>=1. - -OUTPUT PARAMETERS: - Info - error code: - * -4 internal SVD decomposition subroutine failed (very - rare and for degenerate systems only) - * -1 incorrect N/M were specified - * 1 task is solved - C - decomposition coefficients, array[0..M-1] - Rep - fitting report. Following fields are set: - * Rep.TaskRCond reciprocal of condition number - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(F*CovPar*F')), - where F is functions matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitlinearw(const real_1d_array &y, const real_1d_array &w, const real_2d_array &fmatrix, const ae_int_t n, const ae_int_t m, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams = alglib::xdefault); -void lsfitlinearw(const real_1d_array &y, const real_1d_array &w, const real_2d_array &fmatrix, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Weighted constained linear least squares fitting. - -This is variation of LSFitLinearW(), which searchs for min|A*x=b| given -that K additional constaints C*x=bc are satisfied. It reduces original -task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinearW() -is called. - -IMPORTANT: if you want to perform polynomial fitting, it may be more - convenient to use PolynomialFit() function. This function gives - best results on polynomial problems and solves numerical - stability issues which arise when you fit high-degree - polynomials to your data. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Y - array[0..N-1] Function values in N points. - W - array[0..N-1] Weights corresponding to function values. - Each summand in square sum of approximation deviations - from given values is multiplied by the square of - corresponding weight. - FMatrix - a table of basis functions values, array[0..N-1, 0..M-1]. - FMatrix[I,J] - value of J-th basis function in I-th point. - CMatrix - a table of constaints, array[0..K-1,0..M]. - I-th row of CMatrix corresponds to I-th linear constraint: - CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M] - N - number of points used. N>=1. - M - number of basis functions, M>=1. - K - number of constraints, 0 <= K < M - K=0 corresponds to absence of constraints. - -OUTPUT PARAMETERS: - Info - error code: - * -4 internal SVD decomposition subroutine failed (very - rare and for degenerate systems only) - * -3 either too many constraints (M or more), - degenerate constraints (some constraints are - repetead twice) or inconsistent constraints were - specified. - * 1 task is solved - C - decomposition coefficients, array[0..M-1] - Rep - fitting report. Following fields are set: - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(F*CovPar*F')), - where F is functions matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -IMPORTANT: errors in parameters are calculated without taking into - account boundary/linear constraints! Presence of constraints - changes distribution of errors, but there is no easy way to - account for constraints when you calculate covariance matrix. - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 07.09.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitlinearwc(const real_1d_array &y, const real_1d_array &w, const real_2d_array &fmatrix, const real_2d_array &cmatrix, const ae_int_t n, const ae_int_t m, const ae_int_t k, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams = alglib::xdefault); -void lsfitlinearwc(const real_1d_array &y, const real_1d_array &w, const real_2d_array &fmatrix, const real_2d_array &cmatrix, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Linear least squares fitting. - -QR decomposition is used to reduce task to MxM, then triangular solver or -SVD-based solver is used depending on condition number of the system. It -allows to maximize speed and retain decent accuracy. - -IMPORTANT: if you want to perform polynomial fitting, it may be more - convenient to use PolynomialFit() function. This function gives - best results on polynomial problems and solves numerical - stability issues which arise when you fit high-degree - polynomials to your data. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Y - array[0..N-1] Function values in N points. - FMatrix - a table of basis functions values, array[0..N-1, 0..M-1]. - FMatrix[I, J] - value of J-th basis function in I-th point. - N - number of points used. N>=1. - M - number of basis functions, M>=1. - -OUTPUT PARAMETERS: - Info - error code: - * -4 internal SVD decomposition subroutine failed (very - rare and for degenerate systems only) - * 1 task is solved - C - decomposition coefficients, array[0..M-1] - Rep - fitting report. Following fields are set: - * Rep.TaskRCond reciprocal of condition number - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(F*CovPar*F')), - where F is functions matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitlinear(const real_1d_array &y, const real_2d_array &fmatrix, const ae_int_t n, const ae_int_t m, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams = alglib::xdefault); -void lsfitlinear(const real_1d_array &y, const real_2d_array &fmatrix, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Constained linear least squares fitting. - -This is variation of LSFitLinear(), which searchs for min|A*x=b| given -that K additional constaints C*x=bc are satisfied. It reduces original -task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinear() -is called. - -IMPORTANT: if you want to perform polynomial fitting, it may be more - convenient to use PolynomialFit() function. This function gives - best results on polynomial problems and solves numerical - stability issues which arise when you fit high-degree - polynomials to your data. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - Y - array[0..N-1] Function values in N points. - FMatrix - a table of basis functions values, array[0..N-1, 0..M-1]. - FMatrix[I,J] - value of J-th basis function in I-th point. - CMatrix - a table of constaints, array[0..K-1,0..M]. - I-th row of CMatrix corresponds to I-th linear constraint: - CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M] - N - number of points used. N>=1. - M - number of basis functions, M>=1. - K - number of constraints, 0 <= K < M - K=0 corresponds to absence of constraints. - -OUTPUT PARAMETERS: - Info - error code: - * -4 internal SVD decomposition subroutine failed (very - rare and for degenerate systems only) - * -3 either too many constraints (M or more), - degenerate constraints (some constraints are - repetead twice) or inconsistent constraints were - specified. - * 1 task is solved - C - decomposition coefficients, array[0..M-1] - Rep - fitting report. Following fields are set: - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - -IMPORTANT: - this subroitine doesn't calculate task's condition number for K<>0. - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(F*CovPar*F')), - where F is functions matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -IMPORTANT: errors in parameters are calculated without taking into - account boundary/linear constraints! Presence of constraints - changes distribution of errors, but there is no easy way to - account for constraints when you calculate covariance matrix. - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 07.09.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitlinearc(const real_1d_array &y, const real_2d_array &fmatrix, const real_2d_array &cmatrix, const ae_int_t n, const ae_int_t m, const ae_int_t k, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams = alglib::xdefault); -void lsfitlinearc(const real_1d_array &y, const real_2d_array &fmatrix, const real_2d_array &cmatrix, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Weighted nonlinear least squares fitting using function values only. - -Combination of numerical differentiation and secant updates is used to -obtain function Jacobian. - -Nonlinear task min(F(c)) is solved, where - - F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * w is an N-dimensional vector of weight coefficients, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses only f(c,x[i]). - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - W - weights, array[0..N-1] - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - DiffStep- numerical differentiation step; - should not be very small or large; - large = loss of accuracy - small = growth of round-off errors - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 18.10.2008 by Bochkanov Sergey -*************************************************************************/ -void lsfitcreatewf(const real_2d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &c, const ae_int_t n, const ae_int_t m, const ae_int_t k, const double diffstep, lsfitstate &state, const xparams _xparams = alglib::xdefault); -void lsfitcreatewf(const real_2d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &c, const double diffstep, lsfitstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Nonlinear least squares fitting using function values only. - -Combination of numerical differentiation and secant updates is used to -obtain function Jacobian. - -Nonlinear task min(F(c)) is solved, where - - F(c) = (f(c,x[0])-y[0])^2 + ... + (f(c,x[n-1])-y[n-1])^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * w is an N-dimensional vector of weight coefficients, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses only f(c,x[i]). - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - DiffStep- numerical differentiation step; - should not be very small or large; - large = loss of accuracy - small = growth of round-off errors - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 18.10.2008 by Bochkanov Sergey -*************************************************************************/ -void lsfitcreatef(const real_2d_array &x, const real_1d_array &y, const real_1d_array &c, const ae_int_t n, const ae_int_t m, const ae_int_t k, const double diffstep, lsfitstate &state, const xparams _xparams = alglib::xdefault); -void lsfitcreatef(const real_2d_array &x, const real_1d_array &y, const real_1d_array &c, const double diffstep, lsfitstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Weighted nonlinear least squares fitting using gradient only. - -Nonlinear task min(F(c)) is solved, where - - F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * w is an N-dimensional vector of weight coefficients, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses only f(c,x[i]) and its gradient. - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - W - weights, array[0..N-1] - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - CheapFG - boolean flag, which is: - * True if both function and gradient calculation complexity - are less than O(M^2). An improved algorithm can - be used which corresponds to FGJ scheme from - MINLM unit. - * False otherwise. - Standard Jacibian-bases Levenberg-Marquardt algo - will be used (FJ scheme). - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -See also: - LSFitResults - LSFitCreateFG (fitting without weights) - LSFitCreateWFGH (fitting using Hessian) - LSFitCreateFGH (fitting using Hessian, without weights) - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitcreatewfg(const real_2d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &c, const ae_int_t n, const ae_int_t m, const ae_int_t k, const bool cheapfg, lsfitstate &state, const xparams _xparams = alglib::xdefault); -void lsfitcreatewfg(const real_2d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &c, const bool cheapfg, lsfitstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Nonlinear least squares fitting using gradient only, without individual -weights. - -Nonlinear task min(F(c)) is solved, where - - F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses only f(c,x[i]) and its gradient. - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - CheapFG - boolean flag, which is: - * True if both function and gradient calculation complexity - are less than O(M^2). An improved algorithm can - be used which corresponds to FGJ scheme from - MINLM unit. - * False otherwise. - Standard Jacibian-bases Levenberg-Marquardt algo - will be used (FJ scheme). - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitcreatefg(const real_2d_array &x, const real_1d_array &y, const real_1d_array &c, const ae_int_t n, const ae_int_t m, const ae_int_t k, const bool cheapfg, lsfitstate &state, const xparams _xparams = alglib::xdefault); -void lsfitcreatefg(const real_2d_array &x, const real_1d_array &y, const real_1d_array &c, const bool cheapfg, lsfitstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Weighted nonlinear least squares fitting using gradient/Hessian. - -Nonlinear task min(F(c)) is solved, where - - F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * w is an N-dimensional vector of weight coefficients, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses f(c,x[i]), its gradient and its Hessian. - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - W - weights, array[0..N-1] - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitcreatewfgh(const real_2d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &c, const ae_int_t n, const ae_int_t m, const ae_int_t k, lsfitstate &state, const xparams _xparams = alglib::xdefault); -void lsfitcreatewfgh(const real_2d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &c, lsfitstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Nonlinear least squares fitting using gradient/Hessian, without individial -weights. - -Nonlinear task min(F(c)) is solved, where - - F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2, - - * N is a number of points, - * M is a dimension of a space points belong to, - * K is a dimension of a space of parameters being fitted, - * x is a set of N points, each of them is an M-dimensional vector, - * c is a K-dimensional vector of parameters being fitted - -This subroutine uses f(c,x[i]), its gradient and its Hessian. - -INPUT PARAMETERS: - X - array[0..N-1,0..M-1], points (one row = one point) - Y - array[0..N-1], function values. - C - array[0..K-1], initial approximation to the solution, - N - number of points, N>1 - M - dimension of space - K - number of parameters being fitted - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitcreatefgh(const real_2d_array &x, const real_1d_array &y, const real_1d_array &c, const ae_int_t n, const ae_int_t m, const ae_int_t k, lsfitstate &state, const xparams _xparams = alglib::xdefault); -void lsfitcreatefgh(const real_2d_array &x, const real_1d_array &y, const real_1d_array &c, lsfitstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Stopping conditions for nonlinear least squares fitting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - ste pvector, dx=X(k+1)-X(k) - * s - scaling coefficients set by LSFitSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. Only Levenberg-Marquardt - iterations are counted (L-BFGS/CG iterations are NOT - counted because their cost is very low compared to that of - LM). - -NOTE - -Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic -stopping criterion selection (according to the scheme used by MINLM unit). - - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetcond(const lsfitstate &state, const double epsx, const ae_int_t maxits, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which leads to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - -NOTE: non-zero StpMax leads to moderate performance degradation because -intermediate step of preconditioned L-BFGS optimization is incompatible -with limits on step size. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetstpmax(const lsfitstate &state, const double stpmax, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -When reports are needed, State.C (current parameters) and State.F (current -value of fitting function) are reported. - - - -- ALGLIB -- - Copyright 15.08.2010 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetxrep(const lsfitstate &state, const bool needxrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets scaling coefficients for underlying optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Generally, scale is NOT considered to be a form of preconditioner. But LM -optimizer is unique in that it uses scaling matrix both in the stopping -condition tests and as Marquardt damping factor. - -Proper scaling is very important for the algorithm performance. It is less -important for the quality of results, but still has some influence (it is -easier to converge when variables are properly scaled, so premature -stopping is possible when very badly scalled variables are combined with -relaxed stopping conditions). - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetscale(const lsfitstate &state, const real_1d_array &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets boundary constraints for underlying optimizer - -Boundary constraints are inactive by default (after initial creation). -They are preserved until explicitly turned off with another SetBC() call. - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[K]. - If some (all) variables are unbounded, you may specify - very small number or -INF (latter is recommended because - it will allow solver to use better algorithm). - BndU - upper bounds, array[K]. - If some (all) variables are unbounded, you may specify - very large number or +INF (latter is recommended because - it will allow solver to use better algorithm). - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - -NOTE 2: unlike other constrained optimization algorithms, this solver has -following useful properties: -* bound constraints are always satisfied exactly -* function is evaluated only INSIDE area specified by bound constraints - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetbc(const lsfitstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets linear constraints for underlying optimizer - -Linear constraints are inactive by default (after initial creation). -They are preserved until explicitly turned off with another SetLC() call. - -INPUT PARAMETERS: - State - structure stores algorithm state - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -IMPORTANT: if you have linear constraints, it is strongly recommended to - set scale of variables with lsfitsetscale(). QP solver which is - used to calculate linearly constrained steps heavily relies on - good scaling of input problems. - -NOTE: linear (non-box) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations. - -NOTE: general linear constraints add significant overhead to solution - process. Although solver performs roughly same amount of iterations - (when compared with similar box-only constrained problem), each - iteration now involves solution of linearly constrained QP - subproblem, which requires ~3-5 times more Cholesky decompositions. - Thus, if you can reformulate your problem in such way this it has - only box constraints, it may be beneficial to do so. - - -- ALGLIB -- - Copyright 29.04.2017 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetlc(const lsfitstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams = alglib::xdefault); -void lsfitsetlc(const lsfitstate &state, const real_2d_array &c, const integer_1d_array &ct, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool lsfititeration(const lsfitstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This family of functions is used to launcn iterations of nonlinear fitter - -These functions accept following parameters: - state - algorithm state - func - callback which calculates function (or merit function) - value func at given point x - grad - callback which calculates function (or merit function) - value func and gradient grad at given point x - hess - callback which calculates function (or merit function) - value func, gradient grad and Hessian hess at given point x - rep - optional callback which is called after each iteration - can be NULL - ptr - optional pointer which is passed to func/grad/hess/jac/rep - can be NULL - -NOTES: - -1. this algorithm is somewhat unusual because it works with parameterized - function f(C,X), where X is a function argument (we have many points - which are characterized by different argument values), and C is a - parameter to fit. - - For example, if we want to do linear fit by f(c0,c1,x) = c0*x+c1, then - x will be argument, and {c0,c1} will be parameters. - - It is important to understand that this algorithm finds minimum in the - space of function PARAMETERS (not arguments), so it needs derivatives - of f() with respect to C, not X. - - In the example above it will need f=c0*x+c1 and {df/dc0,df/dc1} = {x,1} - instead of {df/dx} = {c0}. - -2. Callback functions accept C as the first parameter, and X as the second - -3. If state was created with LSFitCreateFG(), algorithm needs just - function and its gradient, but if state was created with - LSFitCreateFGH(), algorithm will need function, gradient and Hessian. - - According to the said above, there ase several versions of this - function, which accept different sets of callbacks. - - This flexibility opens way to subtle errors - you may create state with - LSFitCreateFGH() (optimization using Hessian), but call function which - does not accept Hessian. So when algorithm will request Hessian, there - will be no callback to call. In this case exception will be thrown. - - Be careful to avoid such errors because there is no way to find them at - compile time - you can see them at runtime only. - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey - -*************************************************************************/ -void lsfitfit(lsfitstate &state, - void (*func)(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr), - void (*rep)(const real_1d_array &c, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void lsfitfit(lsfitstate &state, - void (*func)(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr), - void (*grad)(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*rep)(const real_1d_array &c, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void lsfitfit(lsfitstate &state, - void (*func)(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr), - void (*grad)(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*hess)(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, real_2d_array &hess, void *ptr), - void (*rep)(const real_1d_array &c, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Nonlinear least squares fitting results. - -Called after return from LSFitFit(). - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - Info - completion code: - * -8 optimizer detected NAN/INF in the target - function and/or gradient - * -7 gradient verification failed. - See LSFitSetGradientCheck() for more information. - * -3 inconsistent constraints - * 2 relative step is no more than EpsX. - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible - C - array[0..K-1], solution - Rep - optimization report. On success following fields are set: - * R2 non-adjusted coefficient of determination - (non-weighted) - * RMSError rms error on the (X,Y). - * AvgError average error on the (X,Y). - * AvgRelError average relative error on the non-zero Y - * MaxError maximum error - NON-WEIGHTED ERRORS ARE CALCULATED - * WRMSError weighted rms error on the (X,Y). - -ERRORS IN PARAMETERS - -This solver also calculates different kinds of errors in parameters and -fills corresponding fields of report: -* Rep.CovPar covariance matrix for parameters, array[K,K]. -* Rep.ErrPar errors in parameters, array[K], - errpar = sqrt(diag(CovPar)) -* Rep.ErrCurve vector of fit errors - standard deviations of empirical - best-fit curve from "ideal" best-fit curve built with - infinite number of samples, array[N]. - errcurve = sqrt(diag(J*CovPar*J')), - where J is Jacobian matrix. -* Rep.Noise vector of per-point estimates of noise, array[N] - -IMPORTANT: errors in parameters are calculated without taking into - account boundary/linear constraints! Presence of constraints - changes distribution of errors, but there is no easy way to - account for constraints when you calculate covariance matrix. - -NOTE: noise in the data is estimated as follows: - * for fitting without user-supplied weights all points are - assumed to have same level of noise, which is estimated from - the data - * for fitting with user-supplied weights we assume that noise - level in I-th point is inversely proportional to Ith weight. - Coefficient of proportionality is estimated from the data. - -NOTE: we apply small amount of regularization when we invert squared - Jacobian and calculate covariance matrix. It guarantees that - algorithm won't divide by zero during inversion, but skews - error estimates a bit (fractional error is about 10^-9). - - However, we believe that this difference is insignificant for - all practical purposes except for the situation when you want - to compare ALGLIB results with "reference" implementation up - to the last significant digit. - -NOTE: covariance matrix is estimated using correction for degrees - of freedom (covariances are divided by N-M instead of dividing - by N). - - -- ALGLIB -- - Copyright 17.08.2009 by Bochkanov Sergey -*************************************************************************/ -void lsfitresults(const lsfitstate &state, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine turns on verification of the user-supplied analytic -gradient: -* user calls this subroutine before fitting begins -* LSFitFit() is called -* prior to actual fitting, for each point in data set X_i and each - component of parameters being fited C_j algorithm performs following - steps: - * two trial steps are made to C_j-TestStep*S[j] and C_j+TestStep*S[j], - where C_j is j-th parameter and S[j] is a scale of j-th parameter - * if needed, steps are bounded with respect to constraints on C[] - * F(X_i|C) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - * in case difference between prediction and actual value is higher than - some predetermined threshold, algorithm stops with completion code -7; - Rep.VarIdx is set to index of the parameter with incorrect derivative. -* after verification is over, algorithm proceeds to the actual optimization. - -NOTE 1: verification needs N*K (points count * parameters count) gradient - evaluations. It is very costly and you should use it only for low - dimensional problems, when you want to be sure that you've - correctly calculated analytic derivatives. You should not use it - in the production code (unless you want to check derivatives - provided by some third party). - -NOTE 2: you should carefully choose TestStep. Value which is too large - (so large that function behaviour is significantly non-cubic) will - lead to false alarms. You may use different step for different - parameters by means of setting scale with LSFitSetScale(). - -NOTE 3: this function may lead to false positives. In case it reports that - I-th derivative was calculated incorrectly, you may decrease test - step and try one more time - maybe your function changes too - sharply and your step is too large for such rapidly chanding - function. - -NOTE 4: this function works only for optimizers created with LSFitCreateWFG() - or LSFitCreateFG() constructors. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step: - * TestStep=0 turns verification off - * TestStep>0 activates verification - - -- ALGLIB -- - Copyright 15.06.2012 by Bochkanov Sergey -*************************************************************************/ -void lsfitsetgradientcheck(const lsfitstate &state, const double teststep, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_RBFV2) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPLINE2D) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -void spline2dserialize(spline2dinterpolant &obj, std::string &s_out); - - -/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -void spline2dunserialize(const std::string &s_in, spline2dinterpolant &obj); - - - - -/************************************************************************* -This function serializes data structure to C++ stream. - -Data stream generated by this function is same as string representation -generated by string version of serializer - alphanumeric characters, -dots, underscores, minus signs, which are grouped into words separated by -spaces and CR+LF. - -We recommend you to read comments on string version of serializer to find -out more about serialization of AlGLIB objects. -*************************************************************************/ -void spline2dserialize(spline2dinterpolant &obj, std::ostream &s_out); - - -/************************************************************************* -This function unserializes data structure from stream. -*************************************************************************/ -void spline2dunserialize(const std::istream &s_in, spline2dinterpolant &obj); - - -/************************************************************************* -This subroutine calculates the value of the bilinear or bicubic spline at -the given point X. - -Input parameters: - C - 2D spline object. - Built by spline2dbuildbilinearv or spline2dbuildbicubicv. - X, Y- point - -Result: - S(x,y) - - -- ALGLIB PROJECT -- - Copyright 05.07.2007 by Bochkanov Sergey -*************************************************************************/ -double spline2dcalc(const spline2dinterpolant &c, const double x, const double y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine calculates the value of the bilinear or bicubic spline at -the given point X and its derivatives. - -Input parameters: - C - spline interpolant. - X, Y- point - -Output parameters: - F - S(x,y) - FX - dS(x,y)/dX - FY - dS(x,y)/dY - FXY - d2S(x,y)/dXdY - - -- ALGLIB PROJECT -- - Copyright 05.07.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2ddiff(const spline2dinterpolant &c, const double x, const double y, double &f, double &fx, double &fy, double &fxy, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine calculates bilinear or bicubic vector-valued spline at the -given point (X,Y). - -If you need just some specific component of vector-valued spline, you can -use spline2dcalcvi() function. - -INPUT PARAMETERS: - C - spline interpolant. - X, Y- point - F - output buffer, possibly preallocated array. In case array size - is large enough to store result, it is not reallocated. Array - which is too short will be reallocated - -OUTPUT PARAMETERS: - F - array[D] (or larger) which stores function values - - -- ALGLIB PROJECT -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dcalcvbuf(const spline2dinterpolant &c, const double x, const double y, real_1d_array &f, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine calculates specific component of vector-valued bilinear or -bicubic spline at the given point (X,Y). - -INPUT PARAMETERS: - C - spline interpolant. - X, Y- point - I - component index, in [0,D). An exception is generated for out - of range values. - -RESULT: - value of I-th component - - -- ALGLIB PROJECT -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -double spline2dcalcvi(const spline2dinterpolant &c, const double x, const double y, const ae_int_t i, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine calculates bilinear or bicubic vector-valued spline at the -given point (X,Y). - -INPUT PARAMETERS: - C - spline interpolant. - X, Y- point - -OUTPUT PARAMETERS: - F - array[D] which stores function values. F is out-parameter and - it is reallocated after call to this function. In case you - want to reuse previously allocated F, you may use - Spline2DCalcVBuf(), which reallocates F only when it is too - small. - - -- ALGLIB PROJECT -- - Copyright 16.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline2dcalcv(const spline2dinterpolant &c, const double x, const double y, real_1d_array &f, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine calculates value of specific component of bilinear or -bicubic vector-valued spline and its derivatives. - -Input parameters: - C - spline interpolant. - X, Y- point - I - component index, in [0,D) - -Output parameters: - F - S(x,y) - FX - dS(x,y)/dX - FY - dS(x,y)/dY - FXY - d2S(x,y)/dXdY - - -- ALGLIB PROJECT -- - Copyright 05.07.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2ddiffvi(const spline2dinterpolant &c, const double x, const double y, const ae_int_t i, double &f, double &fx, double &fy, double &fxy, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine performs linear transformation of the spline argument. - -Input parameters: - C - spline interpolant - AX, BX - transformation coefficients: x = A*t + B - AY, BY - transformation coefficients: y = A*u + B -Result: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 30.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2dlintransxy(const spline2dinterpolant &c, const double ax, const double bx, const double ay, const double by, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine performs linear transformation of the spline. - -Input parameters: - C - spline interpolant. - A, B- transformation coefficients: S2(x,y) = A*S(x,y) + B - -Output parameters: - C - transformed spline - - -- ALGLIB PROJECT -- - Copyright 30.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2dlintransf(const spline2dinterpolant &c, const double a, const double b, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine makes the copy of the spline model. - -Input parameters: - C - spline interpolant - -Output parameters: - CC - spline copy - - -- ALGLIB PROJECT -- - Copyright 29.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2dcopy(const spline2dinterpolant &c, spline2dinterpolant &cc, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Bicubic spline resampling - -Input parameters: - A - function values at the old grid, - array[0..OldHeight-1, 0..OldWidth-1] - OldHeight - old grid height, OldHeight>1 - OldWidth - old grid width, OldWidth>1 - NewHeight - new grid height, NewHeight>1 - NewWidth - new grid width, NewWidth>1 - -Output parameters: - B - function values at the new grid, - array[0..NewHeight-1, 0..NewWidth-1] - - -- ALGLIB routine -- - 15 May, 2007 - Copyright by Bochkanov Sergey -*************************************************************************/ -void spline2dresamplebicubic(const real_2d_array &a, const ae_int_t oldheight, const ae_int_t oldwidth, real_2d_array &b, const ae_int_t newheight, const ae_int_t newwidth, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Bilinear spline resampling - -Input parameters: - A - function values at the old grid, - array[0..OldHeight-1, 0..OldWidth-1] - OldHeight - old grid height, OldHeight>1 - OldWidth - old grid width, OldWidth>1 - NewHeight - new grid height, NewHeight>1 - NewWidth - new grid width, NewWidth>1 - -Output parameters: - B - function values at the new grid, - array[0..NewHeight-1, 0..NewWidth-1] - - -- ALGLIB routine -- - 09.07.2007 - Copyright by Bochkanov Sergey -*************************************************************************/ -void spline2dresamplebilinear(const real_2d_array &a, const ae_int_t oldheight, const ae_int_t oldwidth, real_2d_array &b, const ae_int_t newheight, const ae_int_t newwidth, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine builds bilinear vector-valued spline. - -Input parameters: - X - spline abscissas, array[0..N-1] - Y - spline ordinates, array[0..M-1] - F - function values, array[0..M*N*D-1]: - * first D elements store D values at (X[0],Y[0]) - * next D elements store D values at (X[1],Y[0]) - * general form - D function values at (X[i],Y[j]) are stored - at F[D*(J*N+I)...D*(J*N+I)+D-1]. - M,N - grid size, M>=2, N>=2 - D - vector dimension, D>=1 - -Output parameters: - C - spline interpolant - - -- ALGLIB PROJECT -- - Copyright 16.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildbilinearv(const real_1d_array &x, const ae_int_t n, const real_1d_array &y, const ae_int_t m, const real_1d_array &f, const ae_int_t d, spline2dinterpolant &c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine builds bicubic vector-valued spline. - -Input parameters: - X - spline abscissas, array[0..N-1] - Y - spline ordinates, array[0..M-1] - F - function values, array[0..M*N*D-1]: - * first D elements store D values at (X[0],Y[0]) - * next D elements store D values at (X[1],Y[0]) - * general form - D function values at (X[i],Y[j]) are stored - at F[D*(J*N+I)...D*(J*N+I)+D-1]. - M,N - grid size, M>=2, N>=2 - D - vector dimension, D>=1 - -Output parameters: - C - spline interpolant - - -- ALGLIB PROJECT -- - Copyright 16.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildbicubicv(const real_1d_array &x, const ae_int_t n, const real_1d_array &y, const ae_int_t m, const real_1d_array &f, const ae_int_t d, spline2dinterpolant &c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine unpacks two-dimensional spline into the coefficients table - -Input parameters: - C - spline interpolant. - -Result: - M, N- grid size (x-axis and y-axis) - D - number of components - Tbl - coefficients table, unpacked format, - D - components: [0..(N-1)*(M-1)*D-1, 0..19]. - For T=0..D-1 (component index), I = 0...N-2 (x index), - J=0..M-2 (y index): - K := T + I*D + J*D*(N-1) - - K-th row stores decomposition for T-th component of the - vector-valued function - - Tbl[K,0] = X[i] - Tbl[K,1] = X[i+1] - Tbl[K,2] = Y[j] - Tbl[K,3] = Y[j+1] - Tbl[K,4] = C00 - Tbl[K,5] = C01 - Tbl[K,6] = C02 - Tbl[K,7] = C03 - Tbl[K,8] = C10 - Tbl[K,9] = C11 - ... - Tbl[K,19] = C33 - On each grid square spline is equals to: - S(x) = SUM(c[i,j]*(t^i)*(u^j), i=0..3, j=0..3) - t = x-x[j] - u = y-y[i] - - -- ALGLIB PROJECT -- - Copyright 16.04.2012 by Bochkanov Sergey -*************************************************************************/ -void spline2dunpackv(const spline2dinterpolant &c, ae_int_t &m, ae_int_t &n, ae_int_t &d, real_2d_array &tbl, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine was deprecated in ALGLIB 3.6.0 - -We recommend you to switch to Spline2DBuildBilinearV(), which is more -flexible and accepts its arguments in more convenient order. - - -- ALGLIB PROJECT -- - Copyright 05.07.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildbilinear(const real_1d_array &x, const real_1d_array &y, const real_2d_array &f, const ae_int_t m, const ae_int_t n, spline2dinterpolant &c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine was deprecated in ALGLIB 3.6.0 - -We recommend you to switch to Spline2DBuildBicubicV(), which is more -flexible and accepts its arguments in more convenient order. - - -- ALGLIB PROJECT -- - Copyright 05.07.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildbicubic(const real_1d_array &x, const real_1d_array &y, const real_2d_array &f, const ae_int_t m, const ae_int_t n, spline2dinterpolant &c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine was deprecated in ALGLIB 3.6.0 - -We recommend you to switch to Spline2DUnpackV(), which is more flexible -and accepts its arguments in more convenient order. - - -- ALGLIB PROJECT -- - Copyright 29.06.2007 by Bochkanov Sergey -*************************************************************************/ -void spline2dunpack(const spline2dinterpolant &c, ae_int_t &m, ae_int_t &n, real_2d_array &tbl, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine creates least squares solver used to fit 2D splines to -irregularly sampled (scattered) data. - -Solver object is used to perform spline fits as follows: -* solver object is created with spline2dbuildercreate() function -* dataset is added with spline2dbuildersetpoints() function -* fit area is chosen: - * spline2dbuildersetarea() - for user-defined area - * spline2dbuildersetareaauto() - for automatically chosen area -* number of grid nodes is chosen with spline2dbuildersetgrid() -* prior term is chosen with one of the following functions: - * spline2dbuildersetlinterm() to set linear prior - * spline2dbuildersetconstterm() to set constant prior - * spline2dbuildersetzeroterm() to set zero prior - * spline2dbuildersetuserterm() to set user-defined constant prior -* solver algorithm is chosen with either: - * spline2dbuildersetalgoblocklls() - BlockLLS algorithm, medium-scale problems - * spline2dbuildersetalgofastddm() - FastDDM algorithm, large-scale problems -* finally, fitting itself is performed with spline2dfit() function. - -Most of the steps above can be omitted, solver is configured with good -defaults. The minimum is to call: -* spline2dbuildercreate() to create solver object -* spline2dbuildersetpoints() to specify dataset -* spline2dbuildersetgrid() to tell how many nodes you need -* spline2dfit() to perform fit - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - D - positive number, number of Y-components: D=1 for simple scalar - fit, D>1 for vector-valued spline fitting. - -OUTPUT PARAMETERS: - S - solver object - - -- ALGLIB PROJECT -- - Copyright 29.01.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildercreate(const ae_int_t d, spline2dbuilder &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets constant prior term (model is a sum of bicubic spline -and global prior, which can be linear, constant, user-defined constant or -zero). - -Constant prior term is determined by least squares fitting. - -INPUT PARAMETERS: - S - spline builder - V - value for user-defined prior - - -- ALGLIB -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetuserterm(const spline2dbuilder &state, const double v, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets linear prior term (model is a sum of bicubic spline and -global prior, which can be linear, constant, user-defined constant or -zero). - -Linear prior term is determined by least squares fitting. - -INPUT PARAMETERS: - S - spline builder - - -- ALGLIB -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetlinterm(const spline2dbuilder &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets constant prior term (model is a sum of bicubic spline -and global prior, which can be linear, constant, user-defined constant or -zero). - -Constant prior term is determined by least squares fitting. - -INPUT PARAMETERS: - S - spline builder - - -- ALGLIB -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetconstterm(const spline2dbuilder &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets zero prior term (model is a sum of bicubic spline and -global prior, which can be linear, constant, user-defined constant or -zero). - -INPUT PARAMETERS: - S - spline builder - - -- ALGLIB -- - Copyright 01.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetzeroterm(const spline2dbuilder &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function adds dataset to the builder object. - -This function overrides results of the previous calls, i.e. multiple calls -of this function will result in only the last set being added. - -INPUT PARAMETERS: - S - spline 2D builder object - XY - points, array[N,2+D]. One row corresponds to one point - in the dataset. First 2 elements are coordinates, next - D elements are function values. Array may be larger than - specified, in this case only leading [N,NX+NY] elements - will be used. - N - number of points in the dataset - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetpoints(const spline2dbuilder &state, const real_2d_array &xy, const ae_int_t n, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets area where 2D spline interpolant is built. "Auto" means -that area extent is determined automatically from dataset extent. - -INPUT PARAMETERS: - S - spline 2D builder object - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetareaauto(const spline2dbuilder &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets area where 2D spline interpolant is built to -user-defined one: [XA,XB]*[YA,YB] - -INPUT PARAMETERS: - S - spline 2D builder object - XA,XB - spatial extent in the first (X) dimension, XA=1 means that up to chosen number of bottom - layers is fitted - * NLayers=0 means that maximum number of layers is chosen - (according to current grid size) - * NLayers<=-1 means that up to |NLayers| topmost layers is - skipped - Recommendations: - * good "default" value is 2 layers - * you may need more layers, if your dataset is very - irregular and you want to "patch" large holes. For a - grid step H (equal to AreaWidth/GridSize) you may expect - that last layer reproduces variations at distance H (and - can patch holes that wide); that higher layers operate - at distances 2*H, 4*H, 8*H and so on. - * good value for "bullletproof" mode is NLayers=0, which - results in complete hierarchy of layers being generated. - LambdaV - regularization coefficient, chosen in such a way that it - penalizes bottom layers (fine details) first. - LambdaV>=0, zero value means that no penalty is applied. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetalgofastddm(const spline2dbuilder &state, const ae_int_t nlayers, const double lambdav, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function allows you to choose least squares solver used to perform -fitting. This function sets solver algorithm to "BlockLLS", which performs -least squares fitting with fast sparse direct solver, with optional -nonsmoothness penalty being applied. - -Nonlinearity penalty has the following form: - - [ ] - P() ~ Lambda* integral[ (d2S/dx2)^2 + 2*(d2S/dxdy)^2 + (d2S/dy2)^2 ]dxdy - [ ] - -here integral is calculated over entire grid, and "~" means "proportional" -because integral is normalized after calcilation. Extremely large values -of Lambda result in linear fit being performed. - -NOTE: this algorithm is the most robust and controllable one, but it is - limited by 512x512 grids and (say) up to 1.000.000 points. However, - ALGLIB has one more spline solver: FastDDM algorithm, which is - intended for really large-scale problems (in 10M-100M range). FastDDM - algorithm also has better parallelism properties. - -More information on BlockLLS solver: -* memory requirements: ~[32*K^3+256*NPoints] bytes for KxK grid with - NPoints-sized dataset -* serial running time: O(K^4+NPoints) -* parallelism potential: limited. You may get some sublinear gain when - working with large grids (K's in 256..512 range) - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - S - spline 2D builder object - LambdaNS- non-negative value: - * positive value means that some smoothing is applied - * zero value means that no smoothing is applied, and - corresponding entries of design matrix are numerically - zero and dropped from consideration. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetalgoblocklls(const spline2dbuilder &state, const double lambdans, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function allows you to choose least squares solver used to perform -fitting. This function sets solver algorithm to "NaiveLLS". - -IMPORTANT: NaiveLLS is NOT intended to be used in real life code! This - algorithm solves problem by generated dense (K^2)x(K^2+NPoints) - matrix and solves linear least squares problem with dense - solver. - - It is here just to test BlockLLS against reference solver - (and maybe for someone trying to compare well optimized solver - against straightforward approach to the LLS problem). - -More information on naive LLS solver: -* memory requirements: ~[8*K^4+256*NPoints] bytes for KxK grid. -* serial running time: O(K^6+NPoints) for KxK grid -* when compared with BlockLLS, NaiveLLS has ~K larger memory demand and - ~K^2 larger running time. - -INPUT PARAMETERS: - S - spline 2D builder object - LambdaNS- nonsmoothness penalty - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dbuildersetalgonaivells(const spline2dbuilder &state, const double lambdans, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function fits bicubic spline to current dataset, using current area/ -grid and current LLS solver. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - State - spline 2D builder object - -OUTPUT PARAMETERS: - S - 2D spline, fit result - Rep - fitting report, which provides some additional info about - errors, R2 coefficient and so on. - - -- ALGLIB -- - Copyright 05.02.2018 by Bochkanov Sergey -*************************************************************************/ -void spline2dfit(const spline2dbuilder &state, spline2dinterpolant &s, spline2dfitreport &rep, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_RBFV1) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_RBF) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This function serializes data structure to string. - -Important properties of s_out: -* it contains alphanumeric characters, dots, underscores, minus signs -* these symbols are grouped into words, which are separated by spaces - and Windows-style (CR+LF) newlines -* although serializer uses spaces and CR+LF as separators, you can - replace any separator character by arbitrary combination of spaces, - tabs, Windows or Unix newlines. It allows flexible reformatting of - the string in case you want to include it into text or XML file. - But you should not insert separators into the middle of the "words" - nor you should change case of letters. -* s_out can be freely moved between 32-bit and 64-bit systems, little - and big endian machines, and so on. You can serialize structure on - 32-bit machine and unserialize it on 64-bit one (or vice versa), or - serialize it on SPARC and unserialize on x86. You can also - serialize it in C++ version of ALGLIB and unserialize in C# one, - and vice versa. -*************************************************************************/ -void rbfserialize(rbfmodel &obj, std::string &s_out); - - -/************************************************************************* -This function unserializes data structure from string. -*************************************************************************/ -void rbfunserialize(const std::string &s_in, rbfmodel &obj); - - - - -/************************************************************************* -This function serializes data structure to C++ stream. - -Data stream generated by this function is same as string representation -generated by string version of serializer - alphanumeric characters, -dots, underscores, minus signs, which are grouped into words separated by -spaces and CR+LF. - -We recommend you to read comments on string version of serializer to find -out more about serialization of AlGLIB objects. -*************************************************************************/ -void rbfserialize(rbfmodel &obj, std::ostream &s_out); - - -/************************************************************************* -This function unserializes data structure from stream. -*************************************************************************/ -void rbfunserialize(const std::istream &s_in, rbfmodel &obj); - - -/************************************************************************* -This function creates RBF model for a scalar (NY=1) or vector (NY>1) -function in a NX-dimensional space (NX>=1). - -Newly created model is empty. It can be used for interpolation right after -creation, but it just returns zeros. You have to add points to the model, -tune interpolation settings, and then call model construction function -rbfbuildmodel() which will update model according to your specification. - -USAGE: -1. User creates model with rbfcreate() -2. User adds dataset with rbfsetpoints() (points do NOT have to be on a - regular grid) or rbfsetpointsandscales(). -3. (OPTIONAL) User chooses polynomial term by calling: - * rbflinterm() to set linear term - * rbfconstterm() to set constant term - * rbfzeroterm() to set zero term - By default, linear term is used. -4. User tweaks algorithm properties with rbfsetalgohierarchical() method - (or chooses one of the legacy algorithms - QNN (rbfsetalgoqnn) or ML - (rbfsetalgomultilayer)). -5. User calls rbfbuildmodel() function which rebuilds model according to - the specification -6. User may call rbfcalc() to calculate model value at the specified point, - rbfgridcalc() to calculate model values at the points of the regular - grid. User may extract model coefficients with rbfunpack() call. - -IMPORTANT: we recommend you to use latest model construction algorithm - - hierarchical RBFs, which is activated by rbfsetalgohierarchical() - function. This algorithm is the fastest one, and most memory- - efficient. - However, it is incompatible with older versions of ALGLIB - (pre-3.11). So, if you serialize hierarchical model, you will - be unable to load it in pre-3.11 ALGLIB. Other model types (QNN - and RBF-ML) are still backward-compatible. - -INPUT PARAMETERS: - NX - dimension of the space, NX>=1 - NY - function dimension, NY>=1 - -OUTPUT PARAMETERS: - S - RBF model (initially equals to zero) - -NOTE 1: memory requirements. RBF models require amount of memory which is - proportional to the number of data points. Some additional memory - is allocated during model construction, but most of this memory is - freed after model coefficients are calculated. Amount of this - additional memory depends on model construction algorithm being - used. - -NOTE 2: prior to ALGLIB version 3.11, RBF models supported only NX=2 or - NX=3. Any attempt to create single-dimensional or more than - 3-dimensional RBF model resulted in exception. - - ALGLIB 3.11 supports any NX>0, but models created with NX!=2 and - NX!=3 are incompatible with (a) older versions of ALGLIB, (b) old - model construction algorithms (QNN or RBF-ML). - - So, if you create a model with NX=2 or NX=3, then, depending on - specific model construction algorithm being chosen, you will (QNN - and RBF-ML) or will not (HierarchicalRBF) get backward compatibility - with older versions of ALGLIB. You have a choice here. - - However, if you create a model with NX neither 2 nor 3, you have - no backward compatibility from the start, and you are forced to - use hierarchical RBFs and ALGLIB 3.11 or later. - - -- ALGLIB -- - Copyright 13.12.2011, 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfcreate(const ae_int_t nx, const ae_int_t ny, rbfmodel &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function creates buffer structure which can be used to perform -parallel RBF model evaluations (with one RBF model instance being -used from multiple threads, as long as different threads use different -instances of buffer). - -This buffer object can be used with rbftscalcbuf() function (here "ts" -stands for "thread-safe", "buf" is a suffix which denotes function which -reuses previously allocated output space). - -How to use it: -* create RBF model structure with rbfcreate() -* load data, tune parameters -* call rbfbuildmodel() -* call rbfcreatecalcbuffer(), once per thread working with RBF model (you - should call this function only AFTER call to rbfbuildmodel(), see below - for more information) -* call rbftscalcbuf() from different threads, with each thread working - with its own copy of buffer object. - -INPUT PARAMETERS - S - RBF model - -OUTPUT PARAMETERS - Buf - external buffer. - - -IMPORTANT: buffer object should be used only with RBF model object which - was used to initialize buffer. Any attempt to use buffer with - different object is dangerous - you may get memory violation - error because sizes of internal arrays do not fit to dimensions - of RBF structure. - -IMPORTANT: you should call this function only for model which was built - with rbfbuildmodel() function, after successful invocation of - rbfbuildmodel(). Sizes of some internal structures are - determined only after model is built, so buffer object created - before model construction stage will be useless (and any - attempt to use it will result in exception). - - -- ALGLIB -- - Copyright 02.04.2016 by Sergey Bochkanov -*************************************************************************/ -void rbfcreatecalcbuffer(const rbfmodel &s, rbfcalcbuffer &buf, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function adds dataset. - -This function overrides results of the previous calls, i.e. multiple calls -of this function will result in only the last set being added. - -IMPORTANT: ALGLIB version 3.11 and later allows you to specify a set of - per-dimension scales. Interpolation radii are multiplied by the - scale vector. It may be useful if you have mixed spatio-temporal - data (say, a set of 3D slices recorded at different times). - You should call rbfsetpointsandscales() function to use this - feature. - -INPUT PARAMETERS: - S - RBF model, initialized by rbfcreate() call. - XY - points, array[N,NX+NY]. One row corresponds to one point - in the dataset. First NX elements are coordinates, next - NY elements are function values. Array may be larger than - specified, in this case only leading [N,NX+NY] elements - will be used. - N - number of points in the dataset - -After you've added dataset and (optionally) tuned algorithm settings you -should call rbfbuildmodel() in order to build a model for you. - -NOTE: dataset added by this function is not saved during model serialization. - MODEL ITSELF is serialized, but data used to build it are not. - - So, if you 1) add dataset to empty RBF model, 2) serialize and - unserialize it, then you will get an empty RBF model with no dataset - being attached. - - From the other side, if you call rbfbuildmodel() between (1) and (2), - then after (2) you will get your fully constructed RBF model - but - again with no dataset attached, so subsequent calls to rbfbuildmodel() - will produce empty model. - - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfsetpoints(const rbfmodel &s, const real_2d_array &xy, const ae_int_t n, const xparams _xparams = alglib::xdefault); -void rbfsetpoints(const rbfmodel &s, const real_2d_array &xy, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function adds dataset and a vector of per-dimension scales. - -It may be useful if you have mixed spatio-temporal data - say, a set of 3D -slices recorded at different times. Such data typically require different -RBF radii for spatial and temporal dimensions. ALGLIB solves this problem -by specifying single RBF radius, which is (optionally) multiplied by the -scale vector. - -This function overrides results of the previous calls, i.e. multiple calls -of this function will result in only the last set being added. - -IMPORTANT: only HierarchicalRBF algorithm can work with scaled points. So, - using this function results in RBF models which can be used in - ALGLIB 3.11 or later. Previous versions of the library will be - unable to unserialize models produced by HierarchicalRBF algo. - - Any attempt to use this function with RBF-ML or QNN algorithms - will result in -3 error code being returned (incorrect - algorithm). - -INPUT PARAMETERS: - R - RBF model, initialized by rbfcreate() call. - XY - points, array[N,NX+NY]. One row corresponds to one point - in the dataset. First NX elements are coordinates, next - NY elements are function values. Array may be larger than - specified, in this case only leading [N,NX+NY] elements - will be used. - N - number of points in the dataset - S - array[NX], scale vector, S[i]>0. - -After you've added dataset and (optionally) tuned algorithm settings you -should call rbfbuildmodel() in order to build a model for you. - -NOTE: dataset added by this function is not saved during model serialization. - MODEL ITSELF is serialized, but data used to build it are not. - - So, if you 1) add dataset to empty RBF model, 2) serialize and - unserialize it, then you will get an empty RBF model with no dataset - being attached. - - From the other side, if you call rbfbuildmodel() between (1) and (2), - then after (2) you will get your fully constructed RBF model - but - again with no dataset attached, so subsequent calls to rbfbuildmodel() - will produce empty model. - - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfsetpointsandscales(const rbfmodel &r, const real_2d_array &xy, const ae_int_t n, const real_1d_array &s, const xparams _xparams = alglib::xdefault); -void rbfsetpointsandscales(const rbfmodel &r, const real_2d_array &xy, const real_1d_array &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -DEPRECATED:since version 3.11 ALGLIB includes new RBF model construction - algorithm, Hierarchical RBF. This algorithm is faster and - requires less memory than QNN and RBF-ML. It is especially good - for large-scale interpolation problems. So, we recommend you to - consider Hierarchical RBF as default option. - -========================================================================== - -This function sets RBF interpolation algorithm. ALGLIB supports several -RBF algorithms with different properties. - -This algorithm is called RBF-QNN and it is good for point sets with -following properties: -a) all points are distinct -b) all points are well separated. -c) points distribution is approximately uniform. There is no "contour - lines", clusters of points, or other small-scale structures. - -Algorithm description: -1) interpolation centers are allocated to data points -2) interpolation radii are calculated as distances to the nearest centers - times Q coefficient (where Q is a value from [0.75,1.50]). -3) after performing (2) radii are transformed in order to avoid situation - when single outlier has very large radius and influences many points - across all dataset. Transformation has following form: - new_r[i] = min(r[i],Z*median(r[])) - where r[i] is I-th radius, median() is a median radius across entire - dataset, Z is user-specified value which controls amount of deviation - from median radius. - -When (a) is violated, we will be unable to build RBF model. When (b) or -(c) are violated, model will be built, but interpolation quality will be -low. See http://www.alglib.net/interpolation/ for more information on this -subject. - -This algorithm is used by default. - -Additional Q parameter controls smoothness properties of the RBF basis: -* Q<0.75 will give perfectly conditioned basis, but terrible smoothness - properties (RBF interpolant will have sharp peaks around function values) -* Q around 1.0 gives good balance between smoothness and condition number -* Q>1.5 will lead to badly conditioned systems and slow convergence of the - underlying linear solver (although smoothness will be very good) -* Q>2.0 will effectively make optimizer useless because it won't converge - within reasonable amount of iterations. It is possible to set such large - Q, but it is advised not to do so. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - Q - Q parameter, Q>0, recommended value - 1.0 - Z - Z parameter, Z>0, recommended value - 5.0 - -NOTE: this function has some serialization-related subtleties. We - recommend you to study serialization examples from ALGLIB Reference - Manual if you want to perform serialization of your models. - - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfsetalgoqnn(const rbfmodel &s, const double q, const double z, const xparams _xparams = alglib::xdefault); -void rbfsetalgoqnn(const rbfmodel &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -DEPRECATED:since version 3.11 ALGLIB includes new RBF model construction - algorithm, Hierarchical RBF. This algorithm is faster and - requires less memory than QNN and RBF-ML. It is especially good - for large-scale interpolation problems. So, we recommend you to - consider Hierarchical RBF as default option. - -========================================================================== - -This function sets RBF interpolation algorithm. ALGLIB supports several -RBF algorithms with different properties. - -This algorithm is called RBF-ML. It builds multilayer RBF model, i.e. -model with subsequently decreasing radii, which allows us to combine -smoothness (due to large radii of the first layers) with exactness (due -to small radii of the last layers) and fast convergence. - -Internally RBF-ML uses many different means of acceleration, from sparse -matrices to KD-trees, which results in algorithm whose working time is -roughly proportional to N*log(N)*Density*RBase^2*NLayers, where N is a -number of points, Density is an average density if points per unit of the -interpolation space, RBase is an initial radius, NLayers is a number of -layers. - -RBF-ML is good for following kinds of interpolation problems: -1. "exact" problems (perfect fit) with well separated points -2. least squares problems with arbitrary distribution of points (algorithm - gives perfect fit where it is possible, and resorts to least squares - fit in the hard areas). -3. noisy problems where we want to apply some controlled amount of - smoothing. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - RBase - RBase parameter, RBase>0 - NLayers - NLayers parameter, NLayers>0, recommended value to start - with - about 5. - LambdaV - regularization value, can be useful when solving problem - in the least squares sense. Optimal lambda is problem- - dependent and require trial and error. In our experience, - good lambda can be as large as 0.1, and you can use 0.001 - as initial guess. - Default value - 0.01, which is used when LambdaV is not - given. You can specify zero value, but it is not - recommended to do so. - -TUNING ALGORITHM - -In order to use this algorithm you have to choose three parameters: -* initial radius RBase -* number of layers in the model NLayers -* regularization coefficient LambdaV - -Initial radius is easy to choose - you can pick any number several times -larger than the average distance between points. Algorithm won't break -down if you choose radius which is too large (model construction time will -increase, but model will be built correctly). - -Choose such number of layers that RLast=RBase/2^(NLayers-1) (radius used -by the last layer) will be smaller than the typical distance between -points. In case model error is too large, you can increase number of -layers. Having more layers will make model construction and evaluation -proportionally slower, but it will allow you to have model which precisely -fits your data. From the other side, if you want to suppress noise, you -can DECREASE number of layers to make your model less flexible. - -Regularization coefficient LambdaV controls smoothness of the individual -models built for each layer. We recommend you to use default value in case -you don't want to tune this parameter, because having non-zero LambdaV -accelerates and stabilizes internal iterative algorithm. In case you want -to suppress noise you can use LambdaV as additional parameter (larger -value = more smoothness) to tune. - -TYPICAL ERRORS - -1. Using initial radius which is too large. Memory requirements of the - RBF-ML are roughly proportional to N*Density*RBase^2 (where Density is - an average density of points per unit of the interpolation space). In - the extreme case of the very large RBase we will need O(N^2) units of - memory - and many layers in order to decrease radius to some reasonably - small value. - -2. Using too small number of layers - RBF models with large radius are not - flexible enough to reproduce small variations in the target function. - You need many layers with different radii, from large to small, in - order to have good model. - -3. Using initial radius which is too small. You will get model with - "holes" in the areas which are too far away from interpolation centers. - However, algorithm will work correctly (and quickly) in this case. - -4. Using too many layers - you will get too large and too slow model. This - model will perfectly reproduce your function, but maybe you will be - able to achieve similar results with less layers (and less memory). - - -- ALGLIB -- - Copyright 02.03.2012 by Bochkanov Sergey -*************************************************************************/ -void rbfsetalgomultilayer(const rbfmodel &s, const double rbase, const ae_int_t nlayers, const double lambdav, const xparams _xparams = alglib::xdefault); -void rbfsetalgomultilayer(const rbfmodel &s, const double rbase, const ae_int_t nlayers, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets RBF interpolation algorithm. ALGLIB supports several -RBF algorithms with different properties. - -This algorithm is called Hierarchical RBF. It similar to its previous -incarnation, RBF-ML, i.e. it also builds a sequence of models with -decreasing radii. However, it uses more economical way of building upper -layers (ones with large radii), which results in faster model construction -and evaluation, as well as smaller memory footprint during construction. - -This algorithm has following important features: -* ability to handle millions of points -* controllable smoothing via nonlinearity penalization -* support for NX-dimensional models with NX=1 or NX>3 (unlike QNN or RBF-ML) -* support for specification of per-dimensional radii via scale vector, - which is set by means of rbfsetpointsandscales() function. This feature - is useful if you solve spatio-temporal interpolation problems, where - different radii are required for spatial and temporal dimensions. - -Running times are roughly proportional to: -* N*log(N)*NLayers - for model construction -* N*NLayers - for model evaluation -You may see that running time does not depend on search radius or points -density, just on number of layers in the hierarchy. - -IMPORTANT: this model construction algorithm was introduced in ALGLIB 3.11 - and produces models which are INCOMPATIBLE with previous - versions of ALGLIB. You can not unserialize models produced - with this function in ALGLIB 3.10 or earlier. - -INPUT PARAMETERS: - S - RBF model, initialized by rbfcreate() call - RBase - RBase parameter, RBase>0 - NLayers - NLayers parameter, NLayers>0, recommended value to start - with - about 5. - LambdaNS- >=0, nonlinearity penalty coefficient, negative values are - not allowed. This parameter adds controllable smoothing to - the problem, which may reduce noise. Specification of non- - zero lambda means that in addition to fitting error solver - will also minimize LambdaNS*|S''(x)|^2 (appropriately - generalized to multiple dimensions. - - Specification of exactly zero value means that no penalty - is added (we do not even evaluate matrix of second - derivatives which is necessary for smoothing). - - Calculation of nonlinearity penalty is costly - it results - in several-fold increase of model construction time. - Evaluation time remains the same. - - Optimal lambda is problem-dependent and requires trial - and error. Good value to start from is 1e-5...1e-6, - which corresponds to slightly noticeable smoothing of the - function. Value 1e-2 usually means that quite heavy - smoothing is applied. - -TUNING ALGORITHM - -In order to use this algorithm you have to choose three parameters: -* initial radius RBase -* number of layers in the model NLayers -* penalty coefficient LambdaNS - -Initial radius is easy to choose - you can pick any number several times -larger than the average distance between points. Algorithm won't break -down if you choose radius which is too large (model construction time will -increase, but model will be built correctly). - -Choose such number of layers that RLast=RBase/2^(NLayers-1) (radius used -by the last layer) will be smaller than the typical distance between -points. In case model error is too large, you can increase number of -layers. Having more layers will make model construction and evaluation -proportionally slower, but it will allow you to have model which precisely -fits your data. From the other side, if you want to suppress noise, you -can DECREASE number of layers to make your model less flexible (or specify -non-zero LambdaNS). - -TYPICAL ERRORS - -1. Using too small number of layers - RBF models with large radius are not - flexible enough to reproduce small variations in the target function. - You need many layers with different radii, from large to small, in - order to have good model. - -2. Using initial radius which is too small. You will get model with - "holes" in the areas which are too far away from interpolation centers. - However, algorithm will work correctly (and quickly) in this case. - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfsetalgohierarchical(const rbfmodel &s, const double rbase, const ae_int_t nlayers, const double lambdans, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets linear term (model is a sum of radial basis functions -plus linear polynomial). This function won't have effect until next call -to RBFBuildModel(). - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - -NOTE: this function has some serialization-related subtleties. We - recommend you to study serialization examples from ALGLIB Reference - Manual if you want to perform serialization of your models. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfsetlinterm(const rbfmodel &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets constant term (model is a sum of radial basis functions -plus constant). This function won't have effect until next call to -RBFBuildModel(). - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - -NOTE: this function has some serialization-related subtleties. We - recommend you to study serialization examples from ALGLIB Reference - Manual if you want to perform serialization of your models. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfsetconstterm(const rbfmodel &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets zero term (model is a sum of radial basis functions -without polynomial term). This function won't have effect until next call -to RBFBuildModel(). - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - -NOTE: this function has some serialization-related subtleties. We - recommend you to study serialization examples from ALGLIB Reference - Manual if you want to perform serialization of your models. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfsetzeroterm(const rbfmodel &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets basis function type, which can be: -* 0 for classic Gaussian -* 1 for fast and compact bell-like basis function, which becomes exactly - zero at distance equal to 3*R (default option). - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - BF - basis function type: - * 0 - classic Gaussian - * 1 - fast and compact one - - -- ALGLIB -- - Copyright 01.02.2017 by Bochkanov Sergey -*************************************************************************/ -void rbfsetv2bf(const rbfmodel &s, const ae_int_t bf, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets stopping criteria of the underlying linear solver for -hierarchical (version 2) RBF constructor. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - MaxIts - this criterion will stop algorithm after MaxIts iterations. - Typically a few hundreds iterations is required, with 400 - being a good default value to start experimentation. - Zero value means that default value will be selected. - - -- ALGLIB -- - Copyright 01.02.2017 by Bochkanov Sergey -*************************************************************************/ -void rbfsetv2its(const rbfmodel &s, const ae_int_t maxits, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets support radius parameter of hierarchical (version 2) -RBF constructor. - -Hierarchical RBF model achieves great speed-up by removing from the model -excessive (too dense) nodes. Say, if you have RBF radius equal to 1 meter, -and two nodes are just 1 millimeter apart, you may remove one of them -without reducing model quality. - -Support radius parameter is used to justify which points need removal, and -which do not. If two points are less than SUPPORT_R*CUR_RADIUS units of -distance apart, one of them is removed from the model. The larger support -radius is, the faster model construction AND evaluation are. However, -too large values result in "bumpy" models. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - R - support radius coefficient, >=0. - Recommended values are [0.1,0.4] range, with 0.1 being - default value. - - -- ALGLIB -- - Copyright 01.02.2017 by Bochkanov Sergey -*************************************************************************/ -void rbfsetv2supportr(const rbfmodel &s, const double r, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function builds RBF model and returns report (contains some -information which can be used for evaluation of the algorithm properties). - -Call to this function modifies RBF model by calculating its centers/radii/ -weights and saving them into RBFModel structure. Initially RBFModel -contain zero coefficients, but after call to this function we will have -coefficients which were calculated in order to fit our dataset. - -After you called this function you can call RBFCalc(), RBFGridCalc() and -other model calculation functions. - -INPUT PARAMETERS: - S - RBF model, initialized by RBFCreate() call - Rep - report: - * Rep.TerminationType: - * -5 - non-distinct basis function centers were detected, - interpolation aborted; only QNN returns this - error code, other algorithms can handle non- - distinct nodes. - * -4 - nonconvergence of the internal SVD solver - * -3 incorrect model construction algorithm was chosen: - QNN or RBF-ML, combined with one of the incompatible - features - NX=1 or NX>3; points with per-dimension - scales. - * 1 - successful termination - * 8 - a termination request was submitted via - rbfrequesttermination() function. - - Fields which are set only by modern RBF solvers (hierarchical - or nonnegative; older solvers like QNN and ML initialize these - fields by NANs): - * rep.rmserror - root-mean-square error at nodes - * rep.maxerror - maximum error at nodes - - Fields are used for debugging purposes: - * Rep.IterationsCount - iterations count of the LSQR solver - * Rep.NMV - number of matrix-vector products - * Rep.ARows - rows count for the system matrix - * Rep.ACols - columns count for the system matrix - * Rep.ANNZ - number of significantly non-zero elements - (elements above some algorithm-determined threshold) - -NOTE: failure to build model will leave current state of the structure -unchanged. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfbuildmodel(const rbfmodel &s, rbfreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates values of the RBF model in the given point. - -IMPORTANT: this function works only with modern (hierarchical) RBFs. It - can not be used with legacy (version 1) RBFs because older RBF - code does not support 1-dimensional models. - -This function should be used when we have NY=1 (scalar function) and NX=1 -(1-dimensional space). If you have 3-dimensional space, use rbfcalc3(). If -you have 2-dimensional space, use rbfcalc3(). If you have general -situation (NX-dimensional space, NY-dimensional function) you should use -generic rbfcalc(). - -If you want to perform parallel model evaluation from multiple threads, -use rbftscalcbuf() with per-thread buffer object. - -This function returns 0.0 when: -* model is not initialized -* NX<>1 -* NY<>1 - -INPUT PARAMETERS: - S - RBF model - X0 - X-coordinate, finite number - -RESULT: - value of the model or 0.0 (as defined above) - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -double rbfcalc1(const rbfmodel &s, const double x0, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates values of the RBF model in the given point. - -This function should be used when we have NY=1 (scalar function) and NX=2 -(2-dimensional space). If you have 3-dimensional space, use rbfcalc3(). If -you have general situation (NX-dimensional space, NY-dimensional function) -you should use generic rbfcalc(). - -If you want to calculate function values many times, consider using -rbfgridcalc2v(), which is far more efficient than many subsequent calls to -rbfcalc2(). - -If you want to perform parallel model evaluation from multiple threads, -use rbftscalcbuf() with per-thread buffer object. - -This function returns 0.0 when: -* model is not initialized -* NX<>2 - *NY<>1 - -INPUT PARAMETERS: - S - RBF model - X0 - first coordinate, finite number - X1 - second coordinate, finite number - -RESULT: - value of the model or 0.0 (as defined above) - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -double rbfcalc2(const rbfmodel &s, const double x0, const double x1, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates value of the RBF model in the given point. - -This function should be used when we have NY=1 (scalar function) and NX=3 -(3-dimensional space). If you have 2-dimensional space, use rbfcalc2(). If -you have general situation (NX-dimensional space, NY-dimensional function) -you should use generic rbfcalc(). - -If you want to calculate function values many times, consider using -rbfgridcalc3v(), which is far more efficient than many subsequent calls to -rbfcalc3(). - -If you want to perform parallel model evaluation from multiple threads, -use rbftscalcbuf() with per-thread buffer object. - -This function returns 0.0 when: -* model is not initialized -* NX<>3 - *NY<>1 - -INPUT PARAMETERS: - S - RBF model - X0 - first coordinate, finite number - X1 - second coordinate, finite number - X2 - third coordinate, finite number - -RESULT: - value of the model or 0.0 (as defined above) - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -double rbfcalc3(const rbfmodel &s, const double x0, const double x1, const double x2, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates values of the RBF model at the given point. - -This is general function which can be used for arbitrary NX (dimension of -the space of arguments) and NY (dimension of the function itself). However -when you have NY=1 you may find more convenient to use rbfcalc2() or -rbfcalc3(). - -If you want to perform parallel model evaluation from multiple threads, -use rbftscalcbuf() with per-thread buffer object. - -This function returns 0.0 when model is not initialized. - -INPUT PARAMETERS: - S - RBF model - X - coordinates, array[NX]. - X may have more than NX elements, in this case only - leading NX will be used. - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is out-parameter and - reallocated after call to this function. In case you want - to reuse previously allocated Y, you may use RBFCalcBuf(), - which reallocates Y only when it is too small. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfcalc(const rbfmodel &s, const real_1d_array &x, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates values of the RBF model at the given point. - -Same as rbfcalc(), but does not reallocate Y when in is large enough to -store function values. - -If you want to perform parallel model evaluation from multiple threads, -use rbftscalcbuf() with per-thread buffer object. - -INPUT PARAMETERS: - S - RBF model - X - coordinates, array[NX]. - X may have more than NX elements, in this case only - leading NX will be used. - Y - possibly preallocated array - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is not reallocated when it - is larger than NY. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfcalcbuf(const rbfmodel &s, const real_1d_array &x, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates values of the RBF model at the given point, using -external buffer object (internal temporaries of RBF model are not -modified). - -This function allows to use same RBF model object in different threads, -assuming that different threads use different instances of buffer -structure. - -INPUT PARAMETERS: - S - RBF model, may be shared between different threads - Buf - buffer object created for this particular instance of RBF - model with rbfcreatecalcbuffer(). - X - coordinates, array[NX]. - X may have more than NX elements, in this case only - leading NX will be used. - Y - possibly preallocated array - -OUTPUT PARAMETERS: - Y - function value, array[NY]. Y is not reallocated when it - is larger than NY. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbftscalcbuf(const rbfmodel &s, const rbfcalcbuffer &buf, const real_1d_array &x, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is legacy function for gridded calculation of RBF model. - -It is superseded by rbfgridcalc2v() and rbfgridcalc2vsubset() functions. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfgridcalc2(const rbfmodel &s, const real_1d_array &x0, const ae_int_t n0, const real_1d_array &x1, const ae_int_t n1, real_2d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates values of the RBF model at the regular grid, -which has N0*N1 points, with Point[I,J] = (X0[I], X1[J]). Vector-valued -RBF models are supported. - -This function returns 0.0 when: -* model is not initialized -* NX<>2 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: Parallel processing is implemented only for modern (hierarchical) - RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still - processed serially. - -INPUT PARAMETERS: - S - RBF model, used in read-only mode, can be shared between - multiple invocations of this function from multiple - threads. - - X0 - array of grid nodes, first coordinates, array[N0]. - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N0 - grid size (number of nodes) in the first dimension - - X1 - array of grid nodes, second coordinates, array[N1] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N1 - grid size (number of nodes) in the second dimension - -OUTPUT PARAMETERS: - Y - function values, array[NY*N0*N1], where NY is a number of - "output" vector values (this function supports vector- - valued RBF models). Y is out-variable and is reallocated - by this function. - Y[K+NY*(I0+I1*N0)]=F_k(X0[I0],X1[I1]), for: - * K=0...NY-1 - * I0=0...N0-1 - * I1=0...N1-1 - -NOTE: this function supports weakly ordered grid nodes, i.e. you may have - X[i]=X[i+1] for some i. It does not provide you any performance - benefits due to duplication of points, just convenience and - flexibility. - -NOTE: this function is re-entrant, i.e. you may use same rbfmodel - structure in multiple threads calling this function for different - grids. - -NOTE: if you need function values on some subset of regular grid, which - may be described as "several compact and dense islands", you may - use rbfgridcalc2vsubset(). - - -- ALGLIB -- - Copyright 27.01.2017 by Bochkanov Sergey -*************************************************************************/ -void rbfgridcalc2v(const rbfmodel &s, const real_1d_array &x0, const ae_int_t n0, const real_1d_array &x1, const ae_int_t n1, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates values of the RBF model at some subset of regular -grid: -* grid has N0*N1 points, with Point[I,J] = (X0[I], X1[J]) -* only values at some subset of this grid are required -Vector-valued RBF models are supported. - -This function returns 0.0 when: -* model is not initialized -* NX<>2 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: Parallel processing is implemented only for modern (hierarchical) - RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still - processed serially. - -INPUT PARAMETERS: - S - RBF model, used in read-only mode, can be shared between - multiple invocations of this function from multiple - threads. - - X0 - array of grid nodes, first coordinates, array[N0]. - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N0 - grid size (number of nodes) in the first dimension - - X1 - array of grid nodes, second coordinates, array[N1] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N1 - grid size (number of nodes) in the second dimension - - FlagY - array[N0*N1]: - * Y[I0+I1*N0] corresponds to node (X0[I0],X1[I1]) - * it is a "bitmap" array which contains False for nodes - which are NOT calculated, and True for nodes which are - required. - -OUTPUT PARAMETERS: - Y - function values, array[NY*N0*N1*N2], where NY is a number - of "output" vector values (this function supports vector- - valued RBF models): - * Y[K+NY*(I0+I1*N0)]=F_k(X0[I0],X1[I1]), - for K=0...NY-1, I0=0...N0-1, I1=0...N1-1. - * elements of Y[] which correspond to FlagY[]=True are - loaded by model values (which may be exactly zero for - some nodes). - * elements of Y[] which correspond to FlagY[]=False MAY be - initialized by zeros OR may be calculated. This function - processes grid as a hierarchy of nested blocks and - micro-rows. If just one element of micro-row is required, - entire micro-row (up to 8 nodes in the current version, - but no promises) is calculated. - -NOTE: this function supports weakly ordered grid nodes, i.e. you may have - X[i]=X[i+1] for some i. It does not provide you any performance - benefits due to duplication of points, just convenience and - flexibility. - -NOTE: this function is re-entrant, i.e. you may use same rbfmodel - structure in multiple threads calling this function for different - grids. - - -- ALGLIB -- - Copyright 04.03.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfgridcalc2vsubset(const rbfmodel &s, const real_1d_array &x0, const ae_int_t n0, const real_1d_array &x1, const ae_int_t n1, const boolean_1d_array &flagy, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates values of the RBF model at the regular grid, -which has N0*N1*N2 points, with Point[I,J,K] = (X0[I], X1[J], X2[K]). -Vector-valued RBF models are supported. - -This function returns 0.0 when: -* model is not initialized -* NX<>3 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: Parallel processing is implemented only for modern (hierarchical) - RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still - processed serially. - -INPUT PARAMETERS: - S - RBF model, used in read-only mode, can be shared between - multiple invocations of this function from multiple - threads. - - X0 - array of grid nodes, first coordinates, array[N0]. - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N0 - grid size (number of nodes) in the first dimension - - X1 - array of grid nodes, second coordinates, array[N1] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N1 - grid size (number of nodes) in the second dimension - - X2 - array of grid nodes, third coordinates, array[N2] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N2 - grid size (number of nodes) in the third dimension - -OUTPUT PARAMETERS: - Y - function values, array[NY*N0*N1*N2], where NY is a number - of "output" vector values (this function supports vector- - valued RBF models). Y is out-variable and is reallocated - by this function. - Y[K+NY*(I0+I1*N0+I2*N0*N1)]=F_k(X0[I0],X1[I1],X2[I2]), for: - * K=0...NY-1 - * I0=0...N0-1 - * I1=0...N1-1 - * I2=0...N2-1 - -NOTE: this function supports weakly ordered grid nodes, i.e. you may have - X[i]=X[i+1] for some i. It does not provide you any performance - benefits due to duplication of points, just convenience and - flexibility. - -NOTE: this function is re-entrant, i.e. you may use same rbfmodel - structure in multiple threads calling this function for different - grids. - -NOTE: if you need function values on some subset of regular grid, which - may be described as "several compact and dense islands", you may - use rbfgridcalc3vsubset(). - - -- ALGLIB -- - Copyright 04.03.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfgridcalc3v(const rbfmodel &s, const real_1d_array &x0, const ae_int_t n0, const real_1d_array &x1, const ae_int_t n1, const real_1d_array &x2, const ae_int_t n2, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates values of the RBF model at some subset of regular -grid: -* grid has N0*N1*N2 points, with Point[I,J,K] = (X0[I], X1[J], X2[K]) -* only values at some subset of this grid are required -Vector-valued RBF models are supported. - -This function returns 0.0 when: -* model is not initialized -* NX<>3 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -NOTE: Parallel processing is implemented only for modern (hierarchical) - RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still - processed serially. - -INPUT PARAMETERS: - S - RBF model, used in read-only mode, can be shared between - multiple invocations of this function from multiple - threads. - - X0 - array of grid nodes, first coordinates, array[N0]. - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N0 - grid size (number of nodes) in the first dimension - - X1 - array of grid nodes, second coordinates, array[N1] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N1 - grid size (number of nodes) in the second dimension - - X2 - array of grid nodes, third coordinates, array[N2] - Must be ordered by ascending. Exception is generated - if the array is not correctly ordered. - N2 - grid size (number of nodes) in the third dimension - - FlagY - array[N0*N1*N2]: - * Y[I0+I1*N0+I2*N0*N1] corresponds to node (X0[I0],X1[I1],X2[I2]) - * it is a "bitmap" array which contains False for nodes - which are NOT calculated, and True for nodes which are - required. - -OUTPUT PARAMETERS: - Y - function values, array[NY*N0*N1*N2], where NY is a number - of "output" vector values (this function supports vector- - valued RBF models): - * Y[K+NY*(I0+I1*N0+I2*N0*N1)]=F_k(X0[I0],X1[I1],X2[I2]), - for K=0...NY-1, I0=0...N0-1, I1=0...N1-1, I2=0...N2-1. - * elements of Y[] which correspond to FlagY[]=True are - loaded by model values (which may be exactly zero for - some nodes). - * elements of Y[] which correspond to FlagY[]=False MAY be - initialized by zeros OR may be calculated. This function - processes grid as a hierarchy of nested blocks and - micro-rows. If just one element of micro-row is required, - entire micro-row (up to 8 nodes in the current version, - but no promises) is calculated. - -NOTE: this function supports weakly ordered grid nodes, i.e. you may have - X[i]=X[i+1] for some i. It does not provide you any performance - benefits due to duplication of points, just convenience and - flexibility. - -NOTE: this function is re-entrant, i.e. you may use same rbfmodel - structure in multiple threads calling this function for different - grids. - - -- ALGLIB -- - Copyright 04.03.2016 by Bochkanov Sergey -*************************************************************************/ -void rbfgridcalc3vsubset(const rbfmodel &s, const real_1d_array &x0, const ae_int_t n0, const real_1d_array &x1, const ae_int_t n1, const real_1d_array &x2, const ae_int_t n2, const boolean_1d_array &flagy, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function "unpacks" RBF model by extracting its coefficients. - -INPUT PARAMETERS: - S - RBF model - -OUTPUT PARAMETERS: - NX - dimensionality of argument - NY - dimensionality of the target function - XWR - model information, array[NC,NX+NY+1]. - One row of the array corresponds to one basis function: - * first NX columns - coordinates of the center - * next NY columns - weights, one per dimension of the - function being modelled - For ModelVersion=1: - * last column - radius, same for all dimensions of - the function being modelled - For ModelVersion=2: - * last NX columns - radii, one per dimension - NC - number of the centers - V - polynomial term , array[NY,NX+1]. One row per one - dimension of the function being modelled. First NX - elements are linear coefficients, V[NX] is equal to the - constant part. - ModelVersion-version of the RBF model: - * 1 - for models created by QNN and RBF-ML algorithms, - compatible with ALGLIB 3.10 or earlier. - * 2 - for models created by HierarchicalRBF, requires - ALGLIB 3.11 or later - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -void rbfunpack(const rbfmodel &s, ae_int_t &nx, ae_int_t &ny, real_2d_array &xwr, ae_int_t &nc, real_2d_array &v, ae_int_t &modelversion, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function returns model version. - -INPUT PARAMETERS: - S - RBF model - -RESULT: - * 1 - for models created by QNN and RBF-ML algorithms, - compatible with ALGLIB 3.10 or earlier. - * 2 - for models created by HierarchicalRBF, requires - ALGLIB 3.11 or later - - -- ALGLIB -- - Copyright 06.07.2016 by Bochkanov Sergey -*************************************************************************/ -ae_int_t rbfgetmodelversion(const rbfmodel &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is used to peek into hierarchical RBF construction process -from some other thread and get current progress indicator. It returns -value in [0,1]. - -IMPORTANT: only HRBFs (hierarchical RBFs) support peeking into progress - indicator. Legacy RBF-ML and RBF-QNN do not support it. You - will always get 0 value. - -INPUT PARAMETERS: - S - RBF model object - -RESULT: - progress value, in [0,1] - - -- ALGLIB -- - Copyright 17.11.2018 by Bochkanov Sergey -*************************************************************************/ -double rbfpeekprogress(const rbfmodel &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is used to submit a request for termination of the -hierarchical RBF construction process from some other thread. As result, -RBF construction is terminated smoothly (with proper deallocation of all -necessary resources) and resultant model is filled by zeros. - -A rep.terminationtype=8 will be returned upon receiving such request. - -IMPORTANT: only HRBFs (hierarchical RBFs) support termination requests. - Legacy RBF-ML and RBF-QNN do not support it. An attempt to - terminate their construction will be ignored. - -IMPORTANT: termination request flag is cleared when the model construction - starts. Thus, any pre-construction termination requests will be - silently ignored - only ones submitted AFTER construction has - actually began will be handled. - -INPUT PARAMETERS: - S - RBF model object - - -- ALGLIB -- - Copyright 17.11.2018 by Bochkanov Sergey -*************************************************************************/ -void rbfrequesttermination(const rbfmodel &s, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_INTCOMP) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This function is left for backward compatibility. -Use fitspheremc() instead. - - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void nsfitspheremcc(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &rhi, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is left for backward compatibility. -Use fitspheremi() instead. - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void nsfitspheremic(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &rlo, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is left for backward compatibility. -Use fitspheremz() instead. - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void nsfitspheremzc(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &rlo, double &rhi, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is left for backward compatibility. -Use fitspherex() instead. - - -- ALGLIB -- - Copyright 14.04.2017 by Bochkanov Sergey -*************************************************************************/ -void nsfitspherex(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, const ae_int_t problemtype, const double epsx, const ae_int_t aulits, const double penalty, real_1d_array &cx, double &rlo, double &rhi, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is an obsolete and deprecated version of fitting by -penalized cubic spline. - -It was superseded by spline1dfit(), which is an orders of magnitude faster -and more memory-efficient implementation. - -Do NOT use this function in the new code! - - -- ALGLIB PROJECT -- - Copyright 18.08.2009 by Bochkanov Sergey -*************************************************************************/ -void spline1dfitpenalized(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t m, const double rho, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams = alglib::xdefault); -void spline1dfitpenalized(const real_1d_array &x, const real_1d_array &y, const ae_int_t m, const double rho, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is an obsolete and deprecated version of fitting by -penalized cubic spline. - -It was superseded by spline1dfit(), which is an orders of magnitude faster -and more memory-efficient implementation. - -Do NOT use this function in the new code! - - -- ALGLIB PROJECT -- - Copyright 19.10.2010 by Bochkanov Sergey -*************************************************************************/ -void spline1dfitpenalizedw(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t n, const ae_int_t m, const double rho, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams = alglib::xdefault); -void spline1dfitpenalizedw(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t m, const double rho, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams = alglib::xdefault); -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (FUNCTIONS) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_IDW) || !defined(AE_PARTIAL_BUILD) -void idwcreatecalcbuffer(idwmodel* s, - idwcalcbuffer* buf, - ae_state *_state); -void idwbuildercreate(ae_int_t nx, - ae_int_t ny, - idwbuilder* state, - ae_state *_state); -void idwbuildersetnlayers(idwbuilder* state, - ae_int_t nlayers, - ae_state *_state); -void idwbuildersetpoints(idwbuilder* state, - /* Real */ ae_matrix* xy, - ae_int_t n, - ae_state *_state); -void idwbuildersetalgomstab(idwbuilder* state, - double srad, - ae_state *_state); -void idwbuildersetalgotextbookshepard(idwbuilder* state, - double p, - ae_state *_state); -void idwbuildersetalgotextbookmodshepard(idwbuilder* state, - double r, - ae_state *_state); -void idwbuildersetuserterm(idwbuilder* state, double v, ae_state *_state); -void idwbuildersetconstterm(idwbuilder* state, ae_state *_state); -void idwbuildersetzeroterm(idwbuilder* state, ae_state *_state); -double idwcalc1(idwmodel* s, double x0, ae_state *_state); -double idwcalc2(idwmodel* s, double x0, double x1, ae_state *_state); -double idwcalc3(idwmodel* s, - double x0, - double x1, - double x2, - ae_state *_state); -void idwcalc(idwmodel* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void idwcalcbuf(idwmodel* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void idwtscalcbuf(idwmodel* s, - idwcalcbuffer* buf, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void idwfit(idwbuilder* state, - idwmodel* model, - idwreport* rep, - ae_state *_state); -void idwalloc(ae_serializer* s, idwmodel* model, ae_state *_state); -void idwserialize(ae_serializer* s, idwmodel* model, ae_state *_state); -void idwunserialize(ae_serializer* s, idwmodel* model, ae_state *_state); -void _idwcalcbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _idwcalcbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _idwcalcbuffer_clear(void* _p); -void _idwcalcbuffer_destroy(void* _p); -void _idwmodel_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _idwmodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _idwmodel_clear(void* _p); -void _idwmodel_destroy(void* _p); -void _idwbuilder_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _idwbuilder_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _idwbuilder_clear(void* _p); -void _idwbuilder_destroy(void* _p); -void _idwreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _idwreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _idwreport_clear(void* _p); -void _idwreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_RATINT) || !defined(AE_PARTIAL_BUILD) -double barycentriccalc(barycentricinterpolant* b, - double t, - ae_state *_state); -void barycentricdiff1(barycentricinterpolant* b, - double t, - double* f, - double* df, - ae_state *_state); -void barycentricdiff2(barycentricinterpolant* b, - double t, - double* f, - double* df, - double* d2f, - ae_state *_state); -void barycentriclintransx(barycentricinterpolant* b, - double ca, - double cb, - ae_state *_state); -void barycentriclintransy(barycentricinterpolant* b, - double ca, - double cb, - ae_state *_state); -void barycentricunpack(barycentricinterpolant* b, - ae_int_t* n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_state *_state); -void barycentricbuildxyw(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_int_t n, - barycentricinterpolant* b, - ae_state *_state); -void barycentricbuildfloaterhormann(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t d, - barycentricinterpolant* b, - ae_state *_state); -void barycentriccopy(barycentricinterpolant* b, - barycentricinterpolant* b2, - ae_state *_state); -void _barycentricinterpolant_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _barycentricinterpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _barycentricinterpolant_clear(void* _p); -void _barycentricinterpolant_destroy(void* _p); -#endif -#if defined(AE_COMPILE_FITSPHERE) || !defined(AE_PARTIAL_BUILD) -void fitspherels(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - /* Real */ ae_vector* cx, - double* r, - ae_state *_state); -void fitspheremc(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - /* Real */ ae_vector* cx, - double* rhi, - ae_state *_state); -void fitspheremi(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - /* Real */ ae_vector* cx, - double* rlo, - ae_state *_state); -void fitspheremz(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - /* Real */ ae_vector* cx, - double* rlo, - double* rhi, - ae_state *_state); -void fitspherex(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - ae_int_t problemtype, - double epsx, - ae_int_t aulits, - double penalty, - /* Real */ ae_vector* cx, - double* rlo, - double* rhi, - ae_state *_state); -void fitsphereinternal(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - ae_int_t problemtype, - ae_int_t solvertype, - double epsx, - ae_int_t aulits, - double penalty, - /* Real */ ae_vector* cx, - double* rlo, - double* rhi, - fitsphereinternalreport* rep, - ae_state *_state); -void _fitsphereinternalreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _fitsphereinternalreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _fitsphereinternalreport_clear(void* _p); -void _fitsphereinternalreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_INTFITSERV) || !defined(AE_PARTIAL_BUILD) -void lsfitscalexy(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_int_t n, - /* Real */ ae_vector* xc, - /* Real */ ae_vector* yc, - /* Integer */ ae_vector* dc, - ae_int_t k, - double* xa, - double* xb, - double* sa, - double* sb, - /* Real */ ae_vector* xoriginal, - /* Real */ ae_vector* yoriginal, - ae_state *_state); -void buildpriorterm(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - ae_int_t modeltype, - double priorval, - /* Real */ ae_matrix* v, - ae_state *_state); -void buildpriorterm1(/* Real */ ae_vector* xy1, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - ae_int_t modeltype, - double priorval, - /* Real */ ae_matrix* v, - ae_state *_state); -#endif -#if defined(AE_COMPILE_SPLINE1D) || !defined(AE_PARTIAL_BUILD) -void spline1dbuildlinear(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - spline1dinterpolant* c, - ae_state *_state); -void spline1dbuildcubic(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t boundltype, - double boundl, - ae_int_t boundrtype, - double boundr, - spline1dinterpolant* c, - ae_state *_state); -void spline1dgriddiffcubic(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t boundltype, - double boundl, - ae_int_t boundrtype, - double boundr, - /* Real */ ae_vector* d, - ae_state *_state); -void spline1dgriddiff2cubic(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t boundltype, - double boundl, - ae_int_t boundrtype, - double boundr, - /* Real */ ae_vector* d1, - /* Real */ ae_vector* d2, - ae_state *_state); -void spline1dconvcubic(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t boundltype, - double boundl, - ae_int_t boundrtype, - double boundr, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Real */ ae_vector* y2, - ae_state *_state); -void spline1dconvdiffcubic(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t boundltype, - double boundl, - ae_int_t boundrtype, - double boundr, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Real */ ae_vector* y2, - /* Real */ ae_vector* d2, - ae_state *_state); -void spline1dconvdiff2cubic(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t boundltype, - double boundl, - ae_int_t boundrtype, - double boundr, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Real */ ae_vector* y2, - /* Real */ ae_vector* d2, - /* Real */ ae_vector* dd2, - ae_state *_state); -void spline1dbuildcatmullrom(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t boundtype, - double tension, - spline1dinterpolant* c, - ae_state *_state); -void spline1dbuildhermite(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* d, - ae_int_t n, - spline1dinterpolant* c, - ae_state *_state); -void spline1dbuildakima(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - spline1dinterpolant* c, - ae_state *_state); -double spline1dcalc(spline1dinterpolant* c, double x, ae_state *_state); -void spline1ddiff(spline1dinterpolant* c, - double x, - double* s, - double* ds, - double* d2s, - ae_state *_state); -void spline1dcopy(spline1dinterpolant* c, - spline1dinterpolant* cc, - ae_state *_state); -void spline1dunpack(spline1dinterpolant* c, - ae_int_t* n, - /* Real */ ae_matrix* tbl, - ae_state *_state); -void spline1dlintransx(spline1dinterpolant* c, - double a, - double b, - ae_state *_state); -void spline1dlintransy(spline1dinterpolant* c, - double a, - double b, - ae_state *_state); -double spline1dintegrate(spline1dinterpolant* c, - double x, - ae_state *_state); -void spline1dfit(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t m, - double lambdans, - spline1dinterpolant* s, - spline1dfitreport* rep, - ae_state *_state); -void spline1dconvdiffinternal(/* Real */ ae_vector* xold, - /* Real */ ae_vector* yold, - /* Real */ ae_vector* dold, - ae_int_t n, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Real */ ae_vector* y, - ae_bool needy, - /* Real */ ae_vector* d1, - ae_bool needd1, - /* Real */ ae_vector* d2, - ae_bool needd2, - ae_state *_state); -void spline1drootsandextrema(spline1dinterpolant* c, - /* Real */ ae_vector* r, - ae_int_t* nr, - ae_bool* dr, - /* Real */ ae_vector* e, - /* Integer */ ae_vector* et, - ae_int_t* ne, - ae_bool* de, - ae_state *_state); -void heapsortdpoints(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* d, - ae_int_t n, - ae_state *_state); -void solvepolinom2(double p0, - double m0, - double p1, - double m1, - double* x0, - double* x1, - ae_int_t* nr, - ae_state *_state); -void solvecubicpolinom(double pa, - double ma, - double pb, - double mb, - double a, - double b, - double* x0, - double* x1, - double* x2, - double* ex0, - double* ex1, - ae_int_t* nr, - ae_int_t* ne, - /* Real */ ae_vector* tempdata, - ae_state *_state); -ae_int_t bisectmethod(double pa, - double ma, - double pb, - double mb, - double a, - double b, - double* x, - ae_state *_state); -void spline1dbuildmonotone(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - spline1dinterpolant* c, - ae_state *_state); -void _spline1dinterpolant_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _spline1dinterpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _spline1dinterpolant_clear(void* _p); -void _spline1dinterpolant_destroy(void* _p); -void _spline1dfitreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _spline1dfitreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _spline1dfitreport_clear(void* _p); -void _spline1dfitreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_PARAMETRIC) || !defined(AE_PARTIAL_BUILD) -void pspline2build(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t st, - ae_int_t pt, - pspline2interpolant* p, - ae_state *_state); -void pspline3build(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t st, - ae_int_t pt, - pspline3interpolant* p, - ae_state *_state); -void pspline2buildperiodic(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t st, - ae_int_t pt, - pspline2interpolant* p, - ae_state *_state); -void pspline3buildperiodic(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t st, - ae_int_t pt, - pspline3interpolant* p, - ae_state *_state); -void pspline2parametervalues(pspline2interpolant* p, - ae_int_t* n, - /* Real */ ae_vector* t, - ae_state *_state); -void pspline3parametervalues(pspline3interpolant* p, - ae_int_t* n, - /* Real */ ae_vector* t, - ae_state *_state); -void pspline2calc(pspline2interpolant* p, - double t, - double* x, - double* y, - ae_state *_state); -void pspline3calc(pspline3interpolant* p, - double t, - double* x, - double* y, - double* z, - ae_state *_state); -void pspline2tangent(pspline2interpolant* p, - double t, - double* x, - double* y, - ae_state *_state); -void pspline3tangent(pspline3interpolant* p, - double t, - double* x, - double* y, - double* z, - ae_state *_state); -void pspline2diff(pspline2interpolant* p, - double t, - double* x, - double* dx, - double* y, - double* dy, - ae_state *_state); -void pspline3diff(pspline3interpolant* p, - double t, - double* x, - double* dx, - double* y, - double* dy, - double* z, - double* dz, - ae_state *_state); -void pspline2diff2(pspline2interpolant* p, - double t, - double* x, - double* dx, - double* d2x, - double* y, - double* dy, - double* d2y, - ae_state *_state); -void pspline3diff2(pspline3interpolant* p, - double t, - double* x, - double* dx, - double* d2x, - double* y, - double* dy, - double* d2y, - double* z, - double* dz, - double* d2z, - ae_state *_state); -double pspline2arclength(pspline2interpolant* p, - double a, - double b, - ae_state *_state); -double pspline3arclength(pspline3interpolant* p, - double a, - double b, - ae_state *_state); -void parametricrdpfixed(/* Real */ ae_matrix* x, - ae_int_t n, - ae_int_t d, - ae_int_t stopm, - double stopeps, - /* Real */ ae_matrix* x2, - /* Integer */ ae_vector* idx2, - ae_int_t* nsections, - ae_state *_state); -void _pspline2interpolant_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _pspline2interpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _pspline2interpolant_clear(void* _p); -void _pspline2interpolant_destroy(void* _p); -void _pspline3interpolant_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _pspline3interpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _pspline3interpolant_clear(void* _p); -void _pspline3interpolant_destroy(void* _p); -#endif -#if defined(AE_COMPILE_SPLINE3D) || !defined(AE_PARTIAL_BUILD) -double spline3dcalc(spline3dinterpolant* c, - double x, - double y, - double z, - ae_state *_state); -void spline3dlintransxyz(spline3dinterpolant* c, - double ax, - double bx, - double ay, - double by, - double az, - double bz, - ae_state *_state); -void spline3dlintransf(spline3dinterpolant* c, - double a, - double b, - ae_state *_state); -void spline3dcopy(spline3dinterpolant* c, - spline3dinterpolant* cc, - ae_state *_state); -void spline3dresampletrilinear(/* Real */ ae_vector* a, - ae_int_t oldzcount, - ae_int_t oldycount, - ae_int_t oldxcount, - ae_int_t newzcount, - ae_int_t newycount, - ae_int_t newxcount, - /* Real */ ae_vector* b, - ae_state *_state); -void spline3dbuildtrilinearv(/* Real */ ae_vector* x, - ae_int_t n, - /* Real */ ae_vector* y, - ae_int_t m, - /* Real */ ae_vector* z, - ae_int_t l, - /* Real */ ae_vector* f, - ae_int_t d, - spline3dinterpolant* c, - ae_state *_state); -void spline3dcalcvbuf(spline3dinterpolant* c, - double x, - double y, - double z, - /* Real */ ae_vector* f, - ae_state *_state); -void spline3dcalcv(spline3dinterpolant* c, - double x, - double y, - double z, - /* Real */ ae_vector* f, - ae_state *_state); -void spline3dunpackv(spline3dinterpolant* c, - ae_int_t* n, - ae_int_t* m, - ae_int_t* l, - ae_int_t* d, - ae_int_t* stype, - /* Real */ ae_matrix* tbl, - ae_state *_state); -void _spline3dinterpolant_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _spline3dinterpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _spline3dinterpolant_clear(void* _p); -void _spline3dinterpolant_destroy(void* _p); -#endif -#if defined(AE_COMPILE_POLINT) || !defined(AE_PARTIAL_BUILD) -void polynomialbar2cheb(barycentricinterpolant* p, - double a, - double b, - /* Real */ ae_vector* t, - ae_state *_state); -void polynomialcheb2bar(/* Real */ ae_vector* t, - ae_int_t n, - double a, - double b, - barycentricinterpolant* p, - ae_state *_state); -void polynomialbar2pow(barycentricinterpolant* p, - double c, - double s, - /* Real */ ae_vector* a, - ae_state *_state); -void polynomialpow2bar(/* Real */ ae_vector* a, - ae_int_t n, - double c, - double s, - barycentricinterpolant* p, - ae_state *_state); -void polynomialbuild(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - barycentricinterpolant* p, - ae_state *_state); -void polynomialbuildeqdist(double a, - double b, - /* Real */ ae_vector* y, - ae_int_t n, - barycentricinterpolant* p, - ae_state *_state); -void polynomialbuildcheb1(double a, - double b, - /* Real */ ae_vector* y, - ae_int_t n, - barycentricinterpolant* p, - ae_state *_state); -void polynomialbuildcheb2(double a, - double b, - /* Real */ ae_vector* y, - ae_int_t n, - barycentricinterpolant* p, - ae_state *_state); -double polynomialcalceqdist(double a, - double b, - /* Real */ ae_vector* f, - ae_int_t n, - double t, - ae_state *_state); -double polynomialcalccheb1(double a, - double b, - /* Real */ ae_vector* f, - ae_int_t n, - double t, - ae_state *_state); -double polynomialcalccheb2(double a, - double b, - /* Real */ ae_vector* f, - ae_int_t n, - double t, - ae_state *_state); -#endif -#if defined(AE_COMPILE_LSFIT) || !defined(AE_PARTIAL_BUILD) -void lstfitpiecewiselinearrdpfixed(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* x2, - /* Real */ ae_vector* y2, - ae_int_t* nsections, - ae_state *_state); -void lstfitpiecewiselinearrdp(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - double eps, - /* Real */ ae_vector* x2, - /* Real */ ae_vector* y2, - ae_int_t* nsections, - ae_state *_state); -void polynomialfit(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t m, - ae_int_t* info, - barycentricinterpolant* p, - polynomialfitreport* rep, - ae_state *_state); -void polynomialfitwc(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_int_t n, - /* Real */ ae_vector* xc, - /* Real */ ae_vector* yc, - /* Integer */ ae_vector* dc, - ae_int_t k, - ae_int_t m, - ae_int_t* info, - barycentricinterpolant* p, - polynomialfitreport* rep, - ae_state *_state); -double logisticcalc4(double x, - double a, - double b, - double c, - double d, - ae_state *_state); -double logisticcalc5(double x, - double a, - double b, - double c, - double d, - double g, - ae_state *_state); -void logisticfit4(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - double* a, - double* b, - double* c, - double* d, - lsfitreport* rep, - ae_state *_state); -void logisticfit4ec(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - double cnstrleft, - double cnstrright, - double* a, - double* b, - double* c, - double* d, - lsfitreport* rep, - ae_state *_state); -void logisticfit5(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - double* a, - double* b, - double* c, - double* d, - double* g, - lsfitreport* rep, - ae_state *_state); -void logisticfit5ec(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - double cnstrleft, - double cnstrright, - double* a, - double* b, - double* c, - double* d, - double* g, - lsfitreport* rep, - ae_state *_state); -void logisticfit45x(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - double cnstrleft, - double cnstrright, - ae_bool is4pl, - double lambdav, - double epsx, - ae_int_t rscnt, - double* a, - double* b, - double* c, - double* d, - double* g, - lsfitreport* rep, - ae_state *_state); -void barycentricfitfloaterhormannwc(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_int_t n, - /* Real */ ae_vector* xc, - /* Real */ ae_vector* yc, - /* Integer */ ae_vector* dc, - ae_int_t k, - ae_int_t m, - ae_int_t* info, - barycentricinterpolant* b, - barycentricfitreport* rep, - ae_state *_state); -void barycentricfitfloaterhormann(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t m, - ae_int_t* info, - barycentricinterpolant* b, - barycentricfitreport* rep, - ae_state *_state); -void spline1dfitcubicwc(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_int_t n, - /* Real */ ae_vector* xc, - /* Real */ ae_vector* yc, - /* Integer */ ae_vector* dc, - ae_int_t k, - ae_int_t m, - ae_int_t* info, - spline1dinterpolant* s, - spline1dfitreport* rep, - ae_state *_state); -void spline1dfithermitewc(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_int_t n, - /* Real */ ae_vector* xc, - /* Real */ ae_vector* yc, - /* Integer */ ae_vector* dc, - ae_int_t k, - ae_int_t m, - ae_int_t* info, - spline1dinterpolant* s, - spline1dfitreport* rep, - ae_state *_state); -void spline1dfitcubic(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t m, - ae_int_t* info, - spline1dinterpolant* s, - spline1dfitreport* rep, - ae_state *_state); -void spline1dfithermite(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t m, - ae_int_t* info, - spline1dinterpolant* s, - spline1dfitreport* rep, - ae_state *_state); -void lsfitlinearw(/* Real */ ae_vector* y, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* fmatrix, - ae_int_t n, - ae_int_t m, - ae_int_t* info, - /* Real */ ae_vector* c, - lsfitreport* rep, - ae_state *_state); -void lsfitlinearwc(/* Real */ ae_vector* y, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* fmatrix, - /* Real */ ae_matrix* cmatrix, - ae_int_t n, - ae_int_t m, - ae_int_t k, - ae_int_t* info, - /* Real */ ae_vector* c, - lsfitreport* rep, - ae_state *_state); -void lsfitlinear(/* Real */ ae_vector* y, - /* Real */ ae_matrix* fmatrix, - ae_int_t n, - ae_int_t m, - ae_int_t* info, - /* Real */ ae_vector* c, - lsfitreport* rep, - ae_state *_state); -void lsfitlinearc(/* Real */ ae_vector* y, - /* Real */ ae_matrix* fmatrix, - /* Real */ ae_matrix* cmatrix, - ae_int_t n, - ae_int_t m, - ae_int_t k, - ae_int_t* info, - /* Real */ ae_vector* c, - lsfitreport* rep, - ae_state *_state); -void lsfitcreatewf(/* Real */ ae_matrix* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - /* Real */ ae_vector* c, - ae_int_t n, - ae_int_t m, - ae_int_t k, - double diffstep, - lsfitstate* state, - ae_state *_state); -void lsfitcreatef(/* Real */ ae_matrix* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* c, - ae_int_t n, - ae_int_t m, - ae_int_t k, - double diffstep, - lsfitstate* state, - ae_state *_state); -void lsfitcreatewfg(/* Real */ ae_matrix* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - /* Real */ ae_vector* c, - ae_int_t n, - ae_int_t m, - ae_int_t k, - ae_bool cheapfg, - lsfitstate* state, - ae_state *_state); -void lsfitcreatefg(/* Real */ ae_matrix* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* c, - ae_int_t n, - ae_int_t m, - ae_int_t k, - ae_bool cheapfg, - lsfitstate* state, - ae_state *_state); -void lsfitcreatewfgh(/* Real */ ae_matrix* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - /* Real */ ae_vector* c, - ae_int_t n, - ae_int_t m, - ae_int_t k, - lsfitstate* state, - ae_state *_state); -void lsfitcreatefgh(/* Real */ ae_matrix* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* c, - ae_int_t n, - ae_int_t m, - ae_int_t k, - lsfitstate* state, - ae_state *_state); -void lsfitsetcond(lsfitstate* state, - double epsx, - ae_int_t maxits, - ae_state *_state); -void lsfitsetstpmax(lsfitstate* state, double stpmax, ae_state *_state); -void lsfitsetxrep(lsfitstate* state, ae_bool needxrep, ae_state *_state); -void lsfitsetscale(lsfitstate* state, - /* Real */ ae_vector* s, - ae_state *_state); -void lsfitsetbc(lsfitstate* state, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_state *_state); -void lsfitsetlc(lsfitstate* state, - /* Real */ ae_matrix* c, - /* Integer */ ae_vector* ct, - ae_int_t k, - ae_state *_state); -ae_bool lsfititeration(lsfitstate* state, ae_state *_state); -void lsfitresults(lsfitstate* state, - ae_int_t* info, - /* Real */ ae_vector* c, - lsfitreport* rep, - ae_state *_state); -void lsfitsetgradientcheck(lsfitstate* state, - double teststep, - ae_state *_state); -void _polynomialfitreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _polynomialfitreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _polynomialfitreport_clear(void* _p); -void _polynomialfitreport_destroy(void* _p); -void _barycentricfitreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _barycentricfitreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _barycentricfitreport_clear(void* _p); -void _barycentricfitreport_destroy(void* _p); -void _lsfitreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _lsfitreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _lsfitreport_clear(void* _p); -void _lsfitreport_destroy(void* _p); -void _lsfitstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _lsfitstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _lsfitstate_clear(void* _p); -void _lsfitstate_destroy(void* _p); -#endif -#if defined(AE_COMPILE_RBFV2) || !defined(AE_PARTIAL_BUILD) -void rbfv2create(ae_int_t nx, - ae_int_t ny, - rbfv2model* s, - ae_state *_state); -void rbfv2createcalcbuffer(rbfv2model* s, - rbfv2calcbuffer* buf, - ae_state *_state); -void rbfv2buildhierarchical(/* Real */ ae_matrix* x, - /* Real */ ae_matrix* y, - ae_int_t n, - /* Real */ ae_vector* scalevec, - ae_int_t aterm, - ae_int_t nh, - double rbase, - double lambdans, - rbfv2model* s, - ae_int_t* progress10000, - ae_bool* terminationrequest, - rbfv2report* rep, - ae_state *_state); -void rbfv2alloc(ae_serializer* s, rbfv2model* model, ae_state *_state); -void rbfv2serialize(ae_serializer* s, rbfv2model* model, ae_state *_state); -void rbfv2unserialize(ae_serializer* s, - rbfv2model* model, - ae_state *_state); -double rbfv2farradius(ae_int_t bf, ae_state *_state); -double rbfv2nearradius(ae_int_t bf, ae_state *_state); -double rbfv2basisfunc(ae_int_t bf, double d2, ae_state *_state); -void rbfv2basisfuncdiff2(ae_int_t bf, - double d2, - double* f, - double* df, - double* d2f, - ae_state *_state); -double rbfv2calc1(rbfv2model* s, double x0, ae_state *_state); -double rbfv2calc2(rbfv2model* s, double x0, double x1, ae_state *_state); -double rbfv2calc3(rbfv2model* s, - double x0, - double x1, - double x2, - ae_state *_state); -void rbfv2calcbuf(rbfv2model* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void rbfv2tscalcbuf(rbfv2model* s, - rbfv2calcbuffer* buf, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void rbfv2gridcalc2(rbfv2model* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_matrix* y, - ae_state *_state); -void rbfv2gridcalcvx(rbfv2model* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Real */ ae_vector* x3, - ae_int_t n3, - /* Boolean */ ae_vector* flagy, - ae_bool sparsey, - /* Real */ ae_vector* y, - ae_state *_state); -void rbfv2partialgridcalcrec(rbfv2model* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Real */ ae_vector* x3, - ae_int_t n3, - /* Integer */ ae_vector* blocks0, - ae_int_t block0a, - ae_int_t block0b, - /* Integer */ ae_vector* blocks1, - ae_int_t block1a, - ae_int_t block1b, - /* Integer */ ae_vector* blocks2, - ae_int_t block2a, - ae_int_t block2b, - /* Integer */ ae_vector* blocks3, - ae_int_t block3a, - ae_int_t block3b, - /* Boolean */ ae_vector* flagy, - ae_bool sparsey, - ae_int_t levelidx, - double avgfuncpernode, - ae_shared_pool* bufpool, - /* Real */ ae_vector* y, - ae_state *_state); -ae_bool _trypexec_rbfv2partialgridcalcrec(rbfv2model* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Real */ ae_vector* x3, - ae_int_t n3, - /* Integer */ ae_vector* blocks0, - ae_int_t block0a, - ae_int_t block0b, - /* Integer */ ae_vector* blocks1, - ae_int_t block1a, - ae_int_t block1b, - /* Integer */ ae_vector* blocks2, - ae_int_t block2a, - ae_int_t block2b, - /* Integer */ ae_vector* blocks3, - ae_int_t block3a, - ae_int_t block3b, - /* Boolean */ ae_vector* flagy, - ae_bool sparsey, - ae_int_t levelidx, - double avgfuncpernode, - ae_shared_pool* bufpool, - /* Real */ ae_vector* y, ae_state *_state); -void rbfv2unpack(rbfv2model* s, - ae_int_t* nx, - ae_int_t* ny, - /* Real */ ae_matrix* xwr, - ae_int_t* nc, - /* Real */ ae_matrix* v, - ae_state *_state); -void _rbfv2calcbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _rbfv2calcbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _rbfv2calcbuffer_clear(void* _p); -void _rbfv2calcbuffer_destroy(void* _p); -void _rbfv2model_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _rbfv2model_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _rbfv2model_clear(void* _p); -void _rbfv2model_destroy(void* _p); -void _rbfv2gridcalcbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _rbfv2gridcalcbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _rbfv2gridcalcbuffer_clear(void* _p); -void _rbfv2gridcalcbuffer_destroy(void* _p); -void _rbfv2report_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _rbfv2report_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _rbfv2report_clear(void* _p); -void _rbfv2report_destroy(void* _p); -#endif -#if defined(AE_COMPILE_SPLINE2D) || !defined(AE_PARTIAL_BUILD) -double spline2dcalc(spline2dinterpolant* c, - double x, - double y, - ae_state *_state); -void spline2ddiff(spline2dinterpolant* c, - double x, - double y, - double* f, - double* fx, - double* fy, - double* fxy, - ae_state *_state); -void spline2dcalcvbuf(spline2dinterpolant* c, - double x, - double y, - /* Real */ ae_vector* f, - ae_state *_state); -double spline2dcalcvi(spline2dinterpolant* c, - double x, - double y, - ae_int_t i, - ae_state *_state); -void spline2dcalcv(spline2dinterpolant* c, - double x, - double y, - /* Real */ ae_vector* f, - ae_state *_state); -void spline2ddiffvi(spline2dinterpolant* c, - double x, - double y, - ae_int_t i, - double* f, - double* fx, - double* fy, - double* fxy, - ae_state *_state); -void spline2dlintransxy(spline2dinterpolant* c, - double ax, - double bx, - double ay, - double by, - ae_state *_state); -void spline2dlintransf(spline2dinterpolant* c, - double a, - double b, - ae_state *_state); -void spline2dcopy(spline2dinterpolant* c, - spline2dinterpolant* cc, - ae_state *_state); -void spline2dresamplebicubic(/* Real */ ae_matrix* a, - ae_int_t oldheight, - ae_int_t oldwidth, - /* Real */ ae_matrix* b, - ae_int_t newheight, - ae_int_t newwidth, - ae_state *_state); -void spline2dresamplebilinear(/* Real */ ae_matrix* a, - ae_int_t oldheight, - ae_int_t oldwidth, - /* Real */ ae_matrix* b, - ae_int_t newheight, - ae_int_t newwidth, - ae_state *_state); -void spline2dbuildbilinearv(/* Real */ ae_vector* x, - ae_int_t n, - /* Real */ ae_vector* y, - ae_int_t m, - /* Real */ ae_vector* f, - ae_int_t d, - spline2dinterpolant* c, - ae_state *_state); -void spline2dbuildbicubicv(/* Real */ ae_vector* x, - ae_int_t n, - /* Real */ ae_vector* y, - ae_int_t m, - /* Real */ ae_vector* f, - ae_int_t d, - spline2dinterpolant* c, - ae_state *_state); -void spline2dunpackv(spline2dinterpolant* c, - ae_int_t* m, - ae_int_t* n, - ae_int_t* d, - /* Real */ ae_matrix* tbl, - ae_state *_state); -void spline2dbuildbilinear(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_matrix* f, - ae_int_t m, - ae_int_t n, - spline2dinterpolant* c, - ae_state *_state); -void spline2dbuildbicubic(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_matrix* f, - ae_int_t m, - ae_int_t n, - spline2dinterpolant* c, - ae_state *_state); -void spline2dunpack(spline2dinterpolant* c, - ae_int_t* m, - ae_int_t* n, - /* Real */ ae_matrix* tbl, - ae_state *_state); -void spline2dbuildercreate(ae_int_t d, - spline2dbuilder* state, - ae_state *_state); -void spline2dbuildersetuserterm(spline2dbuilder* state, - double v, - ae_state *_state); -void spline2dbuildersetlinterm(spline2dbuilder* state, ae_state *_state); -void spline2dbuildersetconstterm(spline2dbuilder* state, ae_state *_state); -void spline2dbuildersetzeroterm(spline2dbuilder* state, ae_state *_state); -void spline2dbuildersetpoints(spline2dbuilder* state, - /* Real */ ae_matrix* xy, - ae_int_t n, - ae_state *_state); -void spline2dbuildersetareaauto(spline2dbuilder* state, ae_state *_state); -void spline2dbuildersetarea(spline2dbuilder* state, - double xa, - double xb, - double ya, - double yb, - ae_state *_state); -void spline2dbuildersetgrid(spline2dbuilder* state, - ae_int_t kx, - ae_int_t ky, - ae_state *_state); -void spline2dbuildersetalgofastddm(spline2dbuilder* state, - ae_int_t nlayers, - double lambdav, - ae_state *_state); -void spline2dbuildersetalgoblocklls(spline2dbuilder* state, - double lambdans, - ae_state *_state); -void spline2dbuildersetalgonaivells(spline2dbuilder* state, - double lambdans, - ae_state *_state); -void spline2dfit(spline2dbuilder* state, - spline2dinterpolant* s, - spline2dfitreport* rep, - ae_state *_state); -void spline2dalloc(ae_serializer* s, - spline2dinterpolant* spline, - ae_state *_state); -void spline2dserialize(ae_serializer* s, - spline2dinterpolant* spline, - ae_state *_state); -void spline2dunserialize(ae_serializer* s, - spline2dinterpolant* spline, - ae_state *_state); -void _spline2dinterpolant_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _spline2dinterpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _spline2dinterpolant_clear(void* _p); -void _spline2dinterpolant_destroy(void* _p); -void _spline2dbuilder_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _spline2dbuilder_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _spline2dbuilder_clear(void* _p); -void _spline2dbuilder_destroy(void* _p); -void _spline2dfitreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _spline2dfitreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _spline2dfitreport_clear(void* _p); -void _spline2dfitreport_destroy(void* _p); -void _spline2dxdesignmatrix_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _spline2dxdesignmatrix_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _spline2dxdesignmatrix_clear(void* _p); -void _spline2dxdesignmatrix_destroy(void* _p); -void _spline2dblockllsbuf_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _spline2dblockllsbuf_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _spline2dblockllsbuf_clear(void* _p); -void _spline2dblockllsbuf_destroy(void* _p); -void _spline2dfastddmbuf_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _spline2dfastddmbuf_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _spline2dfastddmbuf_clear(void* _p); -void _spline2dfastddmbuf_destroy(void* _p); -#endif -#if defined(AE_COMPILE_RBFV1) || !defined(AE_PARTIAL_BUILD) -void rbfv1create(ae_int_t nx, - ae_int_t ny, - rbfv1model* s, - ae_state *_state); -void rbfv1createcalcbuffer(rbfv1model* s, - rbfv1calcbuffer* buf, - ae_state *_state); -void rbfv1buildmodel(/* Real */ ae_matrix* x, - /* Real */ ae_matrix* y, - ae_int_t n, - ae_int_t aterm, - ae_int_t algorithmtype, - ae_int_t nlayers, - double radvalue, - double radzvalue, - double lambdav, - double epsort, - double epserr, - ae_int_t maxits, - rbfv1model* s, - rbfv1report* rep, - ae_state *_state); -void rbfv1alloc(ae_serializer* s, rbfv1model* model, ae_state *_state); -void rbfv1serialize(ae_serializer* s, rbfv1model* model, ae_state *_state); -void rbfv1unserialize(ae_serializer* s, - rbfv1model* model, - ae_state *_state); -double rbfv1calc2(rbfv1model* s, double x0, double x1, ae_state *_state); -double rbfv1calc3(rbfv1model* s, - double x0, - double x1, - double x2, - ae_state *_state); -void rbfv1calcbuf(rbfv1model* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void rbfv1tscalcbuf(rbfv1model* s, - rbfv1calcbuffer* buf, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void rbfv1gridcalc2(rbfv1model* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_matrix* y, - ae_state *_state); -void rbfv1gridcalc3vrec(rbfv1model* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Integer */ ae_vector* blocks0, - ae_int_t block0a, - ae_int_t block0b, - /* Integer */ ae_vector* blocks1, - ae_int_t block1a, - ae_int_t block1b, - /* Integer */ ae_vector* blocks2, - ae_int_t block2a, - ae_int_t block2b, - /* Boolean */ ae_vector* flagy, - ae_bool sparsey, - double searchradius, - double avgfuncpernode, - ae_shared_pool* bufpool, - /* Real */ ae_vector* y, - ae_state *_state); -ae_bool _trypexec_rbfv1gridcalc3vrec(rbfv1model* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Integer */ ae_vector* blocks0, - ae_int_t block0a, - ae_int_t block0b, - /* Integer */ ae_vector* blocks1, - ae_int_t block1a, - ae_int_t block1b, - /* Integer */ ae_vector* blocks2, - ae_int_t block2a, - ae_int_t block2b, - /* Boolean */ ae_vector* flagy, - ae_bool sparsey, - double searchradius, - double avgfuncpernode, - ae_shared_pool* bufpool, - /* Real */ ae_vector* y, ae_state *_state); -void rbfv1unpack(rbfv1model* s, - ae_int_t* nx, - ae_int_t* ny, - /* Real */ ae_matrix* xwr, - ae_int_t* nc, - /* Real */ ae_matrix* v, - ae_state *_state); -void _rbfv1calcbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _rbfv1calcbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _rbfv1calcbuffer_clear(void* _p); -void _rbfv1calcbuffer_destroy(void* _p); -void _rbfv1model_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _rbfv1model_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _rbfv1model_clear(void* _p); -void _rbfv1model_destroy(void* _p); -void _gridcalc3v1buf_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _gridcalc3v1buf_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _gridcalc3v1buf_clear(void* _p); -void _gridcalc3v1buf_destroy(void* _p); -void _rbfv1report_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _rbfv1report_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _rbfv1report_clear(void* _p); -void _rbfv1report_destroy(void* _p); -#endif -#if defined(AE_COMPILE_RBF) || !defined(AE_PARTIAL_BUILD) -void rbfcreate(ae_int_t nx, ae_int_t ny, rbfmodel* s, ae_state *_state); -void rbfcreatecalcbuffer(rbfmodel* s, - rbfcalcbuffer* buf, - ae_state *_state); -void rbfsetpoints(rbfmodel* s, - /* Real */ ae_matrix* xy, - ae_int_t n, - ae_state *_state); -void rbfsetpointsandscales(rbfmodel* r, - /* Real */ ae_matrix* xy, - ae_int_t n, - /* Real */ ae_vector* s, - ae_state *_state); -void rbfsetalgoqnn(rbfmodel* s, double q, double z, ae_state *_state); -void rbfsetalgomultilayer(rbfmodel* s, - double rbase, - ae_int_t nlayers, - double lambdav, - ae_state *_state); -void rbfsetalgohierarchical(rbfmodel* s, - double rbase, - ae_int_t nlayers, - double lambdans, - ae_state *_state); -void rbfsetlinterm(rbfmodel* s, ae_state *_state); -void rbfsetconstterm(rbfmodel* s, ae_state *_state); -void rbfsetzeroterm(rbfmodel* s, ae_state *_state); -void rbfsetv2bf(rbfmodel* s, ae_int_t bf, ae_state *_state); -void rbfsetv2its(rbfmodel* s, ae_int_t maxits, ae_state *_state); -void rbfsetv2supportr(rbfmodel* s, double r, ae_state *_state); -void rbfsetcond(rbfmodel* s, - double epsort, - double epserr, - ae_int_t maxits, - ae_state *_state); -void rbfbuildmodel(rbfmodel* s, rbfreport* rep, ae_state *_state); -double rbfcalc1(rbfmodel* s, double x0, ae_state *_state); -double rbfcalc2(rbfmodel* s, double x0, double x1, ae_state *_state); -double rbfcalc3(rbfmodel* s, - double x0, - double x1, - double x2, - ae_state *_state); -void rbfcalc(rbfmodel* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void rbfcalcbuf(rbfmodel* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void rbftscalcbuf(rbfmodel* s, - rbfcalcbuffer* buf, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void rbfgridcalc2(rbfmodel* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_matrix* y, - ae_state *_state); -void rbfgridcalc2v(rbfmodel* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_vector* y, - ae_state *_state); -void rbfgridcalc2vsubset(rbfmodel* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Boolean */ ae_vector* flagy, - /* Real */ ae_vector* y, - ae_state *_state); -void rbfgridcalc3v(rbfmodel* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Real */ ae_vector* y, - ae_state *_state); -void rbfgridcalc3vsubset(rbfmodel* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Boolean */ ae_vector* flagy, - /* Real */ ae_vector* y, - ae_state *_state); -void rbfgridcalc2vx(rbfmodel* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Boolean */ ae_vector* flagy, - ae_bool sparsey, - /* Real */ ae_vector* y, - ae_state *_state); -void rbfgridcalc3vx(rbfmodel* s, - /* Real */ ae_vector* x0, - ae_int_t n0, - /* Real */ ae_vector* x1, - ae_int_t n1, - /* Real */ ae_vector* x2, - ae_int_t n2, - /* Boolean */ ae_vector* flagy, - ae_bool sparsey, - /* Real */ ae_vector* y, - ae_state *_state); -void rbfunpack(rbfmodel* s, - ae_int_t* nx, - ae_int_t* ny, - /* Real */ ae_matrix* xwr, - ae_int_t* nc, - /* Real */ ae_matrix* v, - ae_int_t* modelversion, - ae_state *_state); -ae_int_t rbfgetmodelversion(rbfmodel* s, ae_state *_state); -double rbfpeekprogress(rbfmodel* s, ae_state *_state); -void rbfrequesttermination(rbfmodel* s, ae_state *_state); -void rbfalloc(ae_serializer* s, rbfmodel* model, ae_state *_state); -void rbfserialize(ae_serializer* s, rbfmodel* model, ae_state *_state); -void rbfunserialize(ae_serializer* s, rbfmodel* model, ae_state *_state); -void _rbfcalcbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _rbfcalcbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _rbfcalcbuffer_clear(void* _p); -void _rbfcalcbuffer_destroy(void* _p); -void _rbfmodel_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _rbfmodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _rbfmodel_clear(void* _p); -void _rbfmodel_destroy(void* _p); -void _rbfreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _rbfreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _rbfreport_clear(void* _p); -void _rbfreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_INTCOMP) || !defined(AE_PARTIAL_BUILD) -void nsfitspheremcc(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - /* Real */ ae_vector* cx, - double* rhi, - ae_state *_state); -void nsfitspheremic(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - /* Real */ ae_vector* cx, - double* rlo, - ae_state *_state); -void nsfitspheremzc(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - /* Real */ ae_vector* cx, - double* rlo, - double* rhi, - ae_state *_state); -void nsfitspherex(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - ae_int_t problemtype, - double epsx, - ae_int_t aulits, - double penalty, - /* Real */ ae_vector* cx, - double* rlo, - double* rhi, - ae_state *_state); -void spline1dfitpenalized(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t m, - double rho, - ae_int_t* info, - spline1dinterpolant* s, - spline1dfitreport* rep, - ae_state *_state); -void spline1dfitpenalizedw(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - ae_int_t n, - ae_int_t m, - double rho, - ae_int_t* info, - spline1dinterpolant* s, - spline1dfitreport* rep, - ae_state *_state); -#endif - -} -#endif - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/linalg.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/linalg.cpp deleted file mode 100644 index 83acda1..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/linalg.cpp +++ /dev/null @@ -1,59372 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifdef _MSC_VER -#define _CRT_SECURE_NO_WARNINGS -#endif -#include "stdafx.h" -#include "linalg.h" - -// disable some irrelevant warnings -#if (AE_COMPILER==AE_MSVC) && !defined(AE_ALL_WARNINGS) -#pragma warning(disable:4100) -#pragma warning(disable:4127) -#pragma warning(disable:4611) -#pragma warning(disable:4702) -#pragma warning(disable:4996) -#endif - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_SPARSE) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_ABLAS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_DLU) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPTRF) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_AMDORDERING) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPCHOL) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MATGEN) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_TRFAC) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_RCOND) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MATINV) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_ORTFAC) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_FBLS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_BDSVD) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SVD) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_NORMESTIMATOR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_HSSCHUR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_EVD) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SCHUR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPDGEVD) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_INVERSEUPDATE) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MATDET) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPARSE) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Sparse matrix structure. - -You should use ALGLIB functions to work with sparse matrix. Never try to -access its fields directly! - -NOTES ON THE SPARSE STORAGE FORMATS - -Sparse matrices can be stored using several formats: -* Hash-Table representation -* Compressed Row Storage (CRS) -* Skyline matrix storage (SKS) - -Each of the formats has benefits and drawbacks: -* Hash-table is good for dynamic operations (insertion of new elements), - but does not support linear algebra operations -* CRS is good for operations like matrix-vector or matrix-matrix products, - but its initialization is less convenient - you have to tell row sizes - at the initialization, and you have to fill matrix only row by row, - from left to right. -* SKS is a special format which is used to store triangular factors from - Cholesky factorization. It does not support dynamic modification, and - support for linear algebra operations is very limited. - -Tables below outline information about these two formats: - - OPERATIONS WITH MATRIX HASH CRS SKS - creation + + + - SparseGet + + + - SparseExists + + + - SparseRewriteExisting + + + - SparseSet + + + - SparseAdd + - SparseGetRow + + - SparseGetCompressedRow + + - sparse-dense linear algebra + + -*************************************************************************/ -_sparsematrix_owner::_sparsematrix_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_sparsematrix_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::sparsematrix*)alglib_impl::ae_malloc(sizeof(alglib_impl::sparsematrix), &_state); - memset(p_struct, 0, sizeof(alglib_impl::sparsematrix)); - alglib_impl::_sparsematrix_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_sparsematrix_owner::_sparsematrix_owner(const _sparsematrix_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_sparsematrix_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: sparsematrix copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::sparsematrix*)alglib_impl::ae_malloc(sizeof(alglib_impl::sparsematrix), &_state); - memset(p_struct, 0, sizeof(alglib_impl::sparsematrix)); - alglib_impl::_sparsematrix_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_sparsematrix_owner& _sparsematrix_owner::operator=(const _sparsematrix_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: sparsematrix assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: sparsematrix assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_sparsematrix_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::sparsematrix)); - alglib_impl::_sparsematrix_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_sparsematrix_owner::~_sparsematrix_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_sparsematrix_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::sparsematrix* _sparsematrix_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::sparsematrix* _sparsematrix_owner::c_ptr() const -{ - return const_cast(p_struct); -} -sparsematrix::sparsematrix() : _sparsematrix_owner() -{ -} - -sparsematrix::sparsematrix(const sparsematrix &rhs):_sparsematrix_owner(rhs) -{ -} - -sparsematrix& sparsematrix::operator=(const sparsematrix &rhs) -{ - if( this==&rhs ) - return *this; - _sparsematrix_owner::operator=(rhs); - return *this; -} - -sparsematrix::~sparsematrix() -{ -} - - -/************************************************************************* -Temporary buffers for sparse matrix operations. - -You should pass an instance of this structure to factorization functions. -It allows to reuse memory during repeated sparse factorizations. You do -not have to call some initialization function - simply passing an instance -to factorization function is enough. -*************************************************************************/ -_sparsebuffers_owner::_sparsebuffers_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_sparsebuffers_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::sparsebuffers*)alglib_impl::ae_malloc(sizeof(alglib_impl::sparsebuffers), &_state); - memset(p_struct, 0, sizeof(alglib_impl::sparsebuffers)); - alglib_impl::_sparsebuffers_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_sparsebuffers_owner::_sparsebuffers_owner(const _sparsebuffers_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_sparsebuffers_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: sparsebuffers copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::sparsebuffers*)alglib_impl::ae_malloc(sizeof(alglib_impl::sparsebuffers), &_state); - memset(p_struct, 0, sizeof(alglib_impl::sparsebuffers)); - alglib_impl::_sparsebuffers_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_sparsebuffers_owner& _sparsebuffers_owner::operator=(const _sparsebuffers_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: sparsebuffers assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: sparsebuffers assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_sparsebuffers_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::sparsebuffers)); - alglib_impl::_sparsebuffers_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_sparsebuffers_owner::~_sparsebuffers_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_sparsebuffers_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::sparsebuffers* _sparsebuffers_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::sparsebuffers* _sparsebuffers_owner::c_ptr() const -{ - return const_cast(p_struct); -} -sparsebuffers::sparsebuffers() : _sparsebuffers_owner() -{ -} - -sparsebuffers::sparsebuffers(const sparsebuffers &rhs):_sparsebuffers_owner(rhs) -{ -} - -sparsebuffers& sparsebuffers::operator=(const sparsebuffers &rhs) -{ - if( this==&rhs ) - return *this; - _sparsebuffers_owner::operator=(rhs); - return *this; -} - -sparsebuffers::~sparsebuffers() -{ -} - -/************************************************************************* -This function creates sparse matrix in a Hash-Table format. - -This function creates Hast-Table matrix, which can be converted to CRS -format after its initialization is over. Typical usage scenario for a -sparse matrix is: -1. creation in a Hash-Table format -2. insertion of the matrix elements -3. conversion to the CRS representation -4. matrix is passed to some linear algebra algorithm - -Some information about different matrix formats can be found below, in -the "NOTES" section. - -INPUT PARAMETERS - M - number of rows in a matrix, M>=1 - N - number of columns in a matrix, N>=1 - K - K>=0, expected number of non-zero elements in a matrix. - K can be inexact approximation, can be less than actual - number of elements (table will grow when needed) or - even zero). - It is important to understand that although hash-table - may grow automatically, it is better to provide good - estimate of data size. - -OUTPUT PARAMETERS - S - sparse M*N matrix in Hash-Table representation. - All elements of the matrix are zero. - -NOTE 1 - -Hash-tables use memory inefficiently, and they have to keep some amount -of the "spare memory" in order to have good performance. Hash table for -matrix with K non-zero elements will need C*K*(8+2*sizeof(int)) bytes, -where C is a small constant, about 1.5-2 in magnitude. - -CRS storage, from the other side, is more memory-efficient, and needs -just K*(8+sizeof(int))+M*sizeof(int) bytes, where M is a number of rows -in a matrix. - -When you convert from the Hash-Table to CRS representation, all unneeded -memory will be freed. - -NOTE 2 - -Comments of SparseMatrix structure outline information about different -sparse storage formats. We recommend you to read them before starting to -use ALGLIB sparse matrices. - -NOTE 3 - -This function completely overwrites S with new sparse matrix. Previously -allocated storage is NOT reused. If you want to reuse already allocated -memory, call SparseCreateBuf function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsecreate(const ae_int_t m, const ae_int_t n, const ae_int_t k, sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecreate(m, n, k, const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function creates sparse matrix in a Hash-Table format. - -This function creates Hast-Table matrix, which can be converted to CRS -format after its initialization is over. Typical usage scenario for a -sparse matrix is: -1. creation in a Hash-Table format -2. insertion of the matrix elements -3. conversion to the CRS representation -4. matrix is passed to some linear algebra algorithm - -Some information about different matrix formats can be found below, in -the "NOTES" section. - -INPUT PARAMETERS - M - number of rows in a matrix, M>=1 - N - number of columns in a matrix, N>=1 - K - K>=0, expected number of non-zero elements in a matrix. - K can be inexact approximation, can be less than actual - number of elements (table will grow when needed) or - even zero). - It is important to understand that although hash-table - may grow automatically, it is better to provide good - estimate of data size. - -OUTPUT PARAMETERS - S - sparse M*N matrix in Hash-Table representation. - All elements of the matrix are zero. - -NOTE 1 - -Hash-tables use memory inefficiently, and they have to keep some amount -of the "spare memory" in order to have good performance. Hash table for -matrix with K non-zero elements will need C*K*(8+2*sizeof(int)) bytes, -where C is a small constant, about 1.5-2 in magnitude. - -CRS storage, from the other side, is more memory-efficient, and needs -just K*(8+sizeof(int))+M*sizeof(int) bytes, where M is a number of rows -in a matrix. - -When you convert from the Hash-Table to CRS representation, all unneeded -memory will be freed. - -NOTE 2 - -Comments of SparseMatrix structure outline information about different -sparse storage formats. We recommend you to read them before starting to -use ALGLIB sparse matrices. - -NOTE 3 - -This function completely overwrites S with new sparse matrix. Previously -allocated storage is NOT reused. If you want to reuse already allocated -memory, call SparseCreateBuf function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void sparsecreate(const ae_int_t m, const ae_int_t n, sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t k; - - k = 0; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecreate(m, n, k, const_cast(s.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This version of SparseCreate function creates sparse matrix in Hash-Table -format, reusing previously allocated storage as much as possible. Read -comments for SparseCreate() for more information. - -INPUT PARAMETERS - M - number of rows in a matrix, M>=1 - N - number of columns in a matrix, N>=1 - K - K>=0, expected number of non-zero elements in a matrix. - K can be inexact approximation, can be less than actual - number of elements (table will grow when needed) or - even zero). - It is important to understand that although hash-table - may grow automatically, it is better to provide good - estimate of data size. - S - SparseMatrix structure which MAY contain some already - allocated storage. - -OUTPUT PARAMETERS - S - sparse M*N matrix in Hash-Table representation. - All elements of the matrix are zero. - Previously allocated storage is reused, if its size - is compatible with expected number of non-zeros K. - - -- ALGLIB PROJECT -- - Copyright 14.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatebuf(const ae_int_t m, const ae_int_t n, const ae_int_t k, const sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecreatebuf(m, n, k, const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This version of SparseCreate function creates sparse matrix in Hash-Table -format, reusing previously allocated storage as much as possible. Read -comments for SparseCreate() for more information. - -INPUT PARAMETERS - M - number of rows in a matrix, M>=1 - N - number of columns in a matrix, N>=1 - K - K>=0, expected number of non-zero elements in a matrix. - K can be inexact approximation, can be less than actual - number of elements (table will grow when needed) or - even zero). - It is important to understand that although hash-table - may grow automatically, it is better to provide good - estimate of data size. - S - SparseMatrix structure which MAY contain some already - allocated storage. - -OUTPUT PARAMETERS - S - sparse M*N matrix in Hash-Table representation. - All elements of the matrix are zero. - Previously allocated storage is reused, if its size - is compatible with expected number of non-zeros K. - - -- ALGLIB PROJECT -- - Copyright 14.01.2014 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void sparsecreatebuf(const ae_int_t m, const ae_int_t n, const sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t k; - - k = 0; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecreatebuf(m, n, k, const_cast(s.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function creates sparse matrix in a CRS format (expert function for -situations when you are running out of memory). - -This function creates CRS matrix. Typical usage scenario for a CRS matrix -is: -1. creation (you have to tell number of non-zero elements at each row at - this moment) -2. insertion of the matrix elements (row by row, from left to right) -3. matrix is passed to some linear algebra algorithm - -This function is a memory-efficient alternative to SparseCreate(), but it -is more complex because it requires you to know in advance how large your -matrix is. Some information about different matrix formats can be found -in comments on SparseMatrix structure. We recommend you to read them -before starting to use ALGLIB sparse matrices.. - -INPUT PARAMETERS - M - number of rows in a matrix, M>=1 - N - number of columns in a matrix, N>=1 - NER - number of elements at each row, array[M], NER[I]>=0 - -OUTPUT PARAMETERS - S - sparse M*N matrix in CRS representation. - You have to fill ALL non-zero elements by calling - SparseSet() BEFORE you try to use this matrix. - -NOTE: this function completely overwrites S with new sparse matrix. - Previously allocated storage is NOT reused. If you want to reuse - already allocated memory, call SparseCreateCRSBuf function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatecrs(const ae_int_t m, const ae_int_t n, const integer_1d_array &ner, sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecreatecrs(m, n, const_cast(ner.c_ptr()), const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function creates sparse matrix in a CRS format (expert function for -situations when you are running out of memory). This version of CRS -matrix creation function may reuse memory already allocated in S. - -This function creates CRS matrix. Typical usage scenario for a CRS matrix -is: -1. creation (you have to tell number of non-zero elements at each row at - this moment) -2. insertion of the matrix elements (row by row, from left to right) -3. matrix is passed to some linear algebra algorithm - -This function is a memory-efficient alternative to SparseCreate(), but it -is more complex because it requires you to know in advance how large your -matrix is. Some information about different matrix formats can be found -in comments on SparseMatrix structure. We recommend you to read them -before starting to use ALGLIB sparse matrices.. - -INPUT PARAMETERS - M - number of rows in a matrix, M>=1 - N - number of columns in a matrix, N>=1 - NER - number of elements at each row, array[M], NER[I]>=0 - S - sparse matrix structure with possibly preallocated - memory. - -OUTPUT PARAMETERS - S - sparse M*N matrix in CRS representation. - You have to fill ALL non-zero elements by calling - SparseSet() BEFORE you try to use this matrix. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatecrsbuf(const ae_int_t m, const ae_int_t n, const integer_1d_array &ner, const sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecreatecrsbuf(m, n, const_cast(ner.c_ptr()), const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function creates sparse matrix in a SKS format (skyline storage -format). In most cases you do not need this function - CRS format better -suits most use cases. - -INPUT PARAMETERS - M, N - number of rows(M) and columns (N) in a matrix: - * M=N (as for now, ALGLIB supports only square SKS) - * N>=1 - * M>=1 - D - "bottom" bandwidths, array[M], D[I]>=0. - I-th element stores number of non-zeros at I-th row, - below the diagonal (diagonal itself is not included) - U - "top" bandwidths, array[N], U[I]>=0. - I-th element stores number of non-zeros at I-th row, - above the diagonal (diagonal itself is not included) - -OUTPUT PARAMETERS - S - sparse M*N matrix in SKS representation. - All elements are filled by zeros. - You may use sparseset() to change their values. - -NOTE: this function completely overwrites S with new sparse matrix. - Previously allocated storage is NOT reused. If you want to reuse - already allocated memory, call SparseCreateSKSBuf function. - - -- ALGLIB PROJECT -- - Copyright 13.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatesks(const ae_int_t m, const ae_int_t n, const integer_1d_array &d, const integer_1d_array &u, sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecreatesks(m, n, const_cast(d.c_ptr()), const_cast(u.c_ptr()), const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is "buffered" version of SparseCreateSKS() which reuses memory -previously allocated in S (of course, memory is reallocated if needed). - -This function creates sparse matrix in a SKS format (skyline storage -format). In most cases you do not need this function - CRS format better -suits most use cases. - -INPUT PARAMETERS - M, N - number of rows(M) and columns (N) in a matrix: - * M=N (as for now, ALGLIB supports only square SKS) - * N>=1 - * M>=1 - D - "bottom" bandwidths, array[M], 0<=D[I]<=I. - I-th element stores number of non-zeros at I-th row, - below the diagonal (diagonal itself is not included) - U - "top" bandwidths, array[N], 0<=U[I]<=I. - I-th element stores number of non-zeros at I-th row, - above the diagonal (diagonal itself is not included) - -OUTPUT PARAMETERS - S - sparse M*N matrix in SKS representation. - All elements are filled by zeros. - You may use sparseset() to change their values. - - -- ALGLIB PROJECT -- - Copyright 13.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatesksbuf(const ae_int_t m, const ae_int_t n, const integer_1d_array &d, const integer_1d_array &u, const sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecreatesksbuf(m, n, const_cast(d.c_ptr()), const_cast(u.c_ptr()), const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function creates sparse matrix in a SKS format (skyline storage -format). Unlike more general sparsecreatesks(), this function creates -sparse matrix with constant bandwidth. - -You may want to use this function instead of sparsecreatesks() when your -matrix has constant or nearly-constant bandwidth, and you want to -simplify source code. - -INPUT PARAMETERS - M, N - number of rows(M) and columns (N) in a matrix: - * M=N (as for now, ALGLIB supports only square SKS) - * N>=1 - * M>=1 - BW - matrix bandwidth, BW>=0 - -OUTPUT PARAMETERS - S - sparse M*N matrix in SKS representation. - All elements are filled by zeros. - You may use sparseset() to change their values. - -NOTE: this function completely overwrites S with new sparse matrix. - Previously allocated storage is NOT reused. If you want to reuse - already allocated memory, call sparsecreatesksbandbuf function. - - -- ALGLIB PROJECT -- - Copyright 25.12.2017 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatesksband(const ae_int_t m, const ae_int_t n, const ae_int_t bw, sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecreatesksband(m, n, bw, const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is "buffered" version of sparsecreatesksband() which reuses memory -previously allocated in S (of course, memory is reallocated if needed). - -You may want to use this function instead of sparsecreatesksbuf() when -your matrix has constant or nearly-constant bandwidth, and you want to -simplify source code. - -INPUT PARAMETERS - M, N - number of rows(M) and columns (N) in a matrix: - * M=N (as for now, ALGLIB supports only square SKS) - * N>=1 - * M>=1 - BW - bandwidth, BW>=0 - -OUTPUT PARAMETERS - S - sparse M*N matrix in SKS representation. - All elements are filled by zeros. - You may use sparseset() to change their values. - - -- ALGLIB PROJECT -- - Copyright 13.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatesksbandbuf(const ae_int_t m, const ae_int_t n, const ae_int_t bw, const sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecreatesksbandbuf(m, n, bw, const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function copies S0 to S1. -This function completely deallocates memory owned by S1 before creating a -copy of S0. If you want to reuse memory, use SparseCopyBuf. - -NOTE: this function does not verify its arguments, it just copies all -fields of the structure. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsecopy(const sparsematrix &s0, sparsematrix &s1, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecopy(const_cast(s0.c_ptr()), const_cast(s1.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function copies S0 to S1. -Memory already allocated in S1 is reused as much as possible. - -NOTE: this function does not verify its arguments, it just copies all -fields of the structure. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsecopybuf(const sparsematrix &s0, const sparsematrix &s1, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecopybuf(const_cast(s0.c_ptr()), const_cast(s1.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function efficiently swaps contents of S0 and S1. - - -- ALGLIB PROJECT -- - Copyright 16.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparseswap(const sparsematrix &s0, const sparsematrix &s1, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparseswap(const_cast(s0.c_ptr()), const_cast(s1.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function adds value to S[i,j] - element of the sparse matrix. Matrix -must be in a Hash-Table mode. - -In case S[i,j] already exists in the table, V i added to its value. In -case S[i,j] is non-existent, it is inserted in the table. Table -automatically grows when necessary. - -INPUT PARAMETERS - S - sparse M*N matrix in Hash-Table representation. - Exception will be thrown for CRS matrix. - I - row index of the element to modify, 0<=I(s.c_ptr()), i, j, v, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function modifies S[i,j] - element of the sparse matrix. - -For Hash-based storage format: -* this function can be called at any moment - during matrix initialization - or later -* new value can be zero or non-zero. In case new value of S[i,j] is zero, - this element is deleted from the table. -* this function has no effect when called with zero V for non-existent - element. - -For CRS-bases storage format: -* this function can be called ONLY DURING MATRIX INITIALIZATION -* zero values are stored in the matrix similarly to non-zero ones -* elements must be initialized in correct order - from top row to bottom, - within row - from left to right. - -For SKS storage: -* this function can be called at any moment - during matrix initialization - or later -* zero values are stored in the matrix similarly to non-zero ones -* this function CAN NOT be called for non-existent (outside of the band - specified during SKS matrix creation) elements. Say, if you created SKS - matrix with bandwidth=2 and tried to call sparseset(s,0,10,VAL), an - exception will be generated. - -INPUT PARAMETERS - S - sparse M*N matrix in Hash-Table, SKS or CRS format. - I - row index of the element to modify, 0<=I(s.c_ptr()), i, j, v, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function returns S[i,j] - element of the sparse matrix. Matrix can -be in any mode (Hash-Table, CRS, SKS), but this function is less efficient -for CRS matrices. Hash-Table and SKS matrices can find element in O(1) -time, while CRS matrices need O(log(RS)) time, where RS is an number of -non-zero elements in a row. - -INPUT PARAMETERS - S - sparse M*N matrix - I - row index of the element to modify, 0<=I(s.c_ptr()), i, j, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function checks whether S[i,j] is present in the sparse matrix. It -returns True even for elements that are numerically zero (but still -have place allocated for them). - -The matrix can be in any mode (Hash-Table, CRS, SKS), but this function -is less efficient for CRS matrices. Hash-Table and SKS matrices can find -element in O(1) time, while CRS matrices need O(log(RS)) time, where RS -is an number of non-zero elements in a row. - -INPUT PARAMETERS - S - sparse M*N matrix - I - row index of the element to modify, 0<=I(s.c_ptr()), i, j, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function returns I-th diagonal element of the sparse matrix. - -Matrix can be in any mode (Hash-Table or CRS storage), but this function -is most efficient for CRS matrices - it requires less than 50 CPU cycles -to extract diagonal element. For Hash-Table matrices we still have O(1) -query time, but function is many times slower. - -INPUT PARAMETERS - S - sparse M*N matrix in Hash-Table representation. - Exception will be thrown for CRS matrix. - I - index of the element to modify, 0<=I(s.c_ptr()), i, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function calculates matrix-vector product S*x. Matrix S must be -stored in CRS or SKS format (exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse M*N matrix in CRS or SKS format. - X - array[N], input vector. For performance reasons we - make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - Y - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - Y - array[M], S*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsemv(const sparsematrix &s, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsemv(const_cast(s.c_ptr()), const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates matrix-vector product S^T*x. Matrix S must be -stored in CRS or SKS format (exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse M*N matrix in CRS or SKS format. - X - array[M], input vector. For performance reasons we - make only quick checks - we check that array size is - at least M, but we do not check for NAN's or INF's. - Y - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - Y - array[N], S^T*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsemtv(const sparsematrix &s, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsemtv(const_cast(s.c_ptr()), const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates generalized sparse matrix-vector product - - y := alpha*op(S)*x + beta*y - -Matrix S must be stored in CRS or SKS format (exception will be thrown -otherwise). op(S) can be either S or S^T. - -NOTE: this function expects Y to be large enough to store result. No - automatic preallocation happens for smaller arrays. - -INPUT PARAMETERS - S - sparse matrix in CRS or SKS format. - Alpha - source coefficient - OpS - operation type: - * OpS=0 => op(S) = S - * OpS=1 => op(S) = S^T - X - input vector, must have at least Cols(op(S))+IX elements - IX - subvector offset - Beta - destination coefficient - Y - preallocated output array, must have at least Rows(op(S))+IY elements - IY - subvector offset - -OUTPUT PARAMETERS - Y - elements [IY...IY+Rows(op(S))-1] are replaced by result, - other elements are not modified - -HANDLING OF SPECIAL CASES: -* below M=Rows(op(S)) and N=Cols(op(S)). Although current ALGLIB version - does not allow you to create zero-sized sparse matrices, internally - ALGLIB can deal with such matrices. So, comments for M or N equal to - zero are for internal use only. -* if M=0, then subroutine does nothing. It does not even touch arrays. -* if N=0 or Alpha=0.0, then: - * if Beta=0, then Y is filled by zeros. S and X are not referenced at - all. Initial values of Y are ignored (we do not multiply Y by zero, - we just rewrite it by zeros) - * if Beta<>0, then Y is replaced by Beta*Y -* if M>0, N>0, Alpha<>0, but Beta=0, then Y is replaced by alpha*op(S)*x - initial state of Y is ignored (rewritten without initial multiplication - by zeros). - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 10.12.2019 by Bochkanov Sergey -*************************************************************************/ -void sparsegemv(const sparsematrix &s, const double alpha, const ae_int_t ops, const real_1d_array &x, const ae_int_t ix, const double beta, const real_1d_array &y, const ae_int_t iy, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsegemv(const_cast(s.c_ptr()), alpha, ops, const_cast(x.c_ptr()), ix, beta, const_cast(y.c_ptr()), iy, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function simultaneously calculates two matrix-vector products: - S*x and S^T*x. -S must be square (non-rectangular) matrix stored in CRS or SKS format -(exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse N*N matrix in CRS or SKS format. - X - array[N], input vector. For performance reasons we - make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - Y0 - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - Y1 - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - Y0 - array[N], S*x - Y1 - array[N], S^T*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsemv2(const sparsematrix &s, const real_1d_array &x, real_1d_array &y0, real_1d_array &y1, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsemv2(const_cast(s.c_ptr()), const_cast(x.c_ptr()), const_cast(y0.c_ptr()), const_cast(y1.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates matrix-vector product S*x, when S is symmetric -matrix. Matrix S must be stored in CRS or SKS format (exception will be -thrown otherwise). - -INPUT PARAMETERS - S - sparse M*M matrix in CRS or SKS format. - IsUpper - whether upper or lower triangle of S is given: - * if upper triangle is given, only S[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only S[i,j] for j<=i - are used, and upper triangle is ignored. - X - array[N], input vector. For performance reasons we - make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - Y - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - Y - array[M], S*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsesmv(const sparsematrix &s, const bool isupper, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsesmv(const_cast(s.c_ptr()), isupper, const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates vector-matrix-vector product x'*S*x, where S is -symmetric matrix. Matrix S must be stored in CRS or SKS format (exception -will be thrown otherwise). - -INPUT PARAMETERS - S - sparse M*M matrix in CRS or SKS format. - IsUpper - whether upper or lower triangle of S is given: - * if upper triangle is given, only S[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only S[i,j] for j<=i - are used, and upper triangle is ignored. - X - array[N], input vector. For performance reasons we - make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - -RESULT - x'*S*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 27.01.2014 by Bochkanov Sergey -*************************************************************************/ -double sparsevsmv(const sparsematrix &s, const bool isupper, const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::sparsevsmv(const_cast(s.c_ptr()), isupper, const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function calculates matrix-matrix product S*A. Matrix S must be -stored in CRS or SKS format (exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse M*N matrix in CRS or SKS format. - A - array[N][K], input dense matrix. For performance reasons - we make only quick checks - we check that array size - is at least N, but we do not check for NAN's or INF's. - K - number of columns of matrix (A). - B - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - B - array[M][K], S*A - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsemm(const sparsematrix &s, const real_2d_array &a, const ae_int_t k, real_2d_array &b, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsemm(const_cast(s.c_ptr()), const_cast(a.c_ptr()), k, const_cast(b.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates matrix-matrix product S^T*A. Matrix S must be -stored in CRS or SKS format (exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse M*N matrix in CRS or SKS format. - A - array[M][K], input dense matrix. For performance reasons - we make only quick checks - we check that array size is - at least M, but we do not check for NAN's or INF's. - K - number of columns of matrix (A). - B - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - B - array[N][K], S^T*A - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsemtm(const sparsematrix &s, const real_2d_array &a, const ae_int_t k, real_2d_array &b, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsemtm(const_cast(s.c_ptr()), const_cast(a.c_ptr()), k, const_cast(b.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function simultaneously calculates two matrix-matrix products: - S*A and S^T*A. -S must be square (non-rectangular) matrix stored in CRS or SKS format -(exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse N*N matrix in CRS or SKS format. - A - array[N][K], input dense matrix. For performance reasons - we make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - K - number of columns of matrix (A). - B0 - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - B1 - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - B0 - array[N][K], S*A - B1 - array[N][K], S^T*A - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsemm2(const sparsematrix &s, const real_2d_array &a, const ae_int_t k, real_2d_array &b0, real_2d_array &b1, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsemm2(const_cast(s.c_ptr()), const_cast(a.c_ptr()), k, const_cast(b0.c_ptr()), const_cast(b1.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates matrix-matrix product S*A, when S is symmetric -matrix. Matrix S must be stored in CRS or SKS format (exception will be -thrown otherwise). - -INPUT PARAMETERS - S - sparse M*M matrix in CRS or SKS format. - IsUpper - whether upper or lower triangle of S is given: - * if upper triangle is given, only S[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only S[i,j] for j<=i - are used, and upper triangle is ignored. - A - array[N][K], input dense matrix. For performance reasons - we make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - K - number of columns of matrix (A). - B - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - B - array[M][K], S*A - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsesmm(const sparsematrix &s, const bool isupper, const real_2d_array &a, const ae_int_t k, real_2d_array &b, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsesmm(const_cast(s.c_ptr()), isupper, const_cast(a.c_ptr()), k, const_cast(b.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function calculates matrix-vector product op(S)*x, when x is vector, -S is symmetric triangular matrix, op(S) is transposition or no operation. -Matrix S must be stored in CRS or SKS format (exception will be thrown -otherwise). - -INPUT PARAMETERS - S - sparse square matrix in CRS or SKS format. - IsUpper - whether upper or lower triangle of S is used: - * if upper triangle is given, only S[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only S[i,j] for j<=i - are used, and upper triangle is ignored. - IsUnit - unit or non-unit diagonal: - * if True, diagonal elements of triangular matrix are - considered equal to 1.0. Actual elements stored in - S are not referenced at all. - * if False, diagonal stored in S is used - OpType - operation type: - * if 0, S*x is calculated - * if 1, (S^T)*x is calculated (transposition) - X - array[N] which stores input vector. For performance - reasons we make only quick checks - we check that - array size is at least N, but we do not check for - NAN's or INF's. - Y - possibly preallocated input buffer. Automatically - resized if its size is too small. - -OUTPUT PARAMETERS - Y - array[N], op(S)*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 20.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsetrmv(const sparsematrix &s, const bool isupper, const bool isunit, const ae_int_t optype, const real_1d_array &x, real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsetrmv(const_cast(s.c_ptr()), isupper, isunit, optype, const_cast(x.c_ptr()), const_cast(y.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function solves linear system op(S)*y=x where x is vector, S is -symmetric triangular matrix, op(S) is transposition or no operation. -Matrix S must be stored in CRS or SKS format (exception will be thrown -otherwise). - -INPUT PARAMETERS - S - sparse square matrix in CRS or SKS format. - IsUpper - whether upper or lower triangle of S is used: - * if upper triangle is given, only S[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only S[i,j] for j<=i - are used, and upper triangle is ignored. - IsUnit - unit or non-unit diagonal: - * if True, diagonal elements of triangular matrix are - considered equal to 1.0. Actual elements stored in - S are not referenced at all. - * if False, diagonal stored in S is used. It is your - responsibility to make sure that diagonal is - non-zero. - OpType - operation type: - * if 0, S*x is calculated - * if 1, (S^T)*x is calculated (transposition) - X - array[N] which stores input vector. For performance - reasons we make only quick checks - we check that - array size is at least N, but we do not check for - NAN's or INF's. - -OUTPUT PARAMETERS - X - array[N], inv(op(S))*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. - You must convert your matrix with SparseConvertToCRS/SKS() before - using this function. - -NOTE: no assertion or tests are done during algorithm operation. It is - your responsibility to provide invertible matrix to algorithm. - - -- ALGLIB PROJECT -- - Copyright 20.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsetrsv(const sparsematrix &s, const bool isupper, const bool isunit, const ae_int_t optype, const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsetrsv(const_cast(s.c_ptr()), isupper, isunit, optype, const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function applies permutation given by permutation table P (as opposed -to product form of permutation) to sparse symmetric matrix A, given by -either upper or lower triangle: B := P*A*P'. - -This function allocates completely new instance of B. Use buffered version -SparseSymmPermTblBuf() if you want to reuse already allocated structure. - -INPUT PARAMETERS - A - sparse square matrix in CRS format. - IsUpper - whether upper or lower triangle of A is used: - * if upper triangle is given, only A[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only A[i,j] for j<=i - are used, and upper triangle is ignored. - P - array[N] which stores permutation table; P[I]=J means - that I-th row/column of matrix A is moved to J-th - position. For performance reasons we do NOT check that - P[] is a correct permutation (that there is no - repetitions, just that all its elements are in [0,N) - range. - -OUTPUT PARAMETERS - B - permuted matrix. Permutation is applied to A from - the both sides, only upper or lower triangle (depending - on IsUpper) is stored. - -NOTE: this function throws exception when called for non-CRS matrix. You - must convert your matrix with SparseConvertToCRS() before using this - function. - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -void sparsesymmpermtbl(const sparsematrix &a, const bool isupper, const integer_1d_array &p, sparsematrix &b, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsesymmpermtbl(const_cast(a.c_ptr()), isupper, const_cast(p.c_ptr()), const_cast(b.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is a buffered version of SparseSymmPermTbl() that reuses -previously allocated storage in B as much as possible. - -This function applies permutation given by permutation table P (as opposed -to product form of permutation) to sparse symmetric matrix A, given by -either upper or lower triangle: B := P*A*P'. - -INPUT PARAMETERS - A - sparse square matrix in CRS format. - IsUpper - whether upper or lower triangle of A is used: - * if upper triangle is given, only A[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only A[i,j] for j<=i - are used, and upper triangle is ignored. - P - array[N] which stores permutation table; P[I]=J means - that I-th row/column of matrix A is moved to J-th - position. For performance reasons we do NOT check that - P[] is a correct permutation (that there is no - repetitions, just that all its elements are in [0,N) - range. - B - sparse matrix object that will hold output. - Previously allocated memory will be reused as much as - possible. - -OUTPUT PARAMETERS - B - permuted matrix. Permutation is applied to A from - the both sides, only upper or lower triangle (depending - on IsUpper) is stored. - -NOTE: this function throws exception when called for non-CRS matrix. You - must convert your matrix with SparseConvertToCRS() before using this - function. - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -void sparsesymmpermtblbuf(const sparsematrix &a, const bool isupper, const integer_1d_array &p, const sparsematrix &b, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsesymmpermtblbuf(const_cast(a.c_ptr()), isupper, const_cast(p.c_ptr()), const_cast(b.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This procedure resizes Hash-Table matrix. It can be called when you have -deleted too many elements from the matrix, and you want to free unneeded -memory. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparseresizematrix(const sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparseresizematrix(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is used to enumerate all elements of the sparse matrix. -Before first call user initializes T0 and T1 counters by zero. These -counters are used to remember current position in a matrix; after each -call they are updated by the function. - -Subsequent calls to this function return non-zero elements of the sparse -matrix, one by one. If you enumerate CRS matrix, matrix is traversed from -left to right, from top to bottom. In case you enumerate matrix stored as -Hash table, elements are returned in random order. - -EXAMPLE - > T0=0 - > T1=0 - > while SparseEnumerate(S,T0,T1,I,J,V) do - > ....do something with I,J,V - -INPUT PARAMETERS - S - sparse M*N matrix in Hash-Table or CRS representation. - T0 - internal counter - T1 - internal counter - -OUTPUT PARAMETERS - T0 - new value of the internal counter - T1 - new value of the internal counter - I - row index of non-zero element, 0<=I(s.c_ptr()), &t0, &t1, &i, &j, &v, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function rewrites existing (non-zero) element. It returns True if -element exists or False, when it is called for non-existing (zero) -element. - -This function works with any kind of the matrix. - -The purpose of this function is to provide convenient thread-safe way to -modify sparse matrix. Such modification (already existing element is -rewritten) is guaranteed to be thread-safe without any synchronization, as -long as different threads modify different elements. - -INPUT PARAMETERS - S - sparse M*N matrix in any kind of representation - (Hash, SKS, CRS). - I - row index of non-zero element to modify, 0<=I(s.c_ptr()), i, j, v, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function returns I-th row of the sparse matrix. Matrix must be stored -in CRS or SKS format. - -INPUT PARAMETERS: - S - sparse M*N matrix in CRS format - I - row index, 0<=I(s.c_ptr()), i, const_cast(irow.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function returns I-th row of the sparse matrix IN COMPRESSED FORMAT - -only non-zero elements are returned (with their indexes). Matrix must be -stored in CRS or SKS format. - -INPUT PARAMETERS: - S - sparse M*N matrix in CRS format - I - row index, 0<=I(s.c_ptr()), i, const_cast(colidx.c_ptr()), const_cast(vals.c_ptr()), &nzcnt, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function performs efficient in-place transpose of SKS matrix. No -additional memory is allocated during transposition. - -This function supports only skyline storage format (SKS). - -INPUT PARAMETERS - S - sparse matrix in SKS format. - -OUTPUT PARAMETERS - S - sparse matrix, transposed. - - -- ALGLIB PROJECT -- - Copyright 16.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsetransposesks(const sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsetransposesks(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function performs transpose of CRS matrix. - -INPUT PARAMETERS - S - sparse matrix in CRS format. - -OUTPUT PARAMETERS - S - sparse matrix, transposed. - -NOTE: internal temporary copy is allocated for the purposes of - transposition. It is deallocated after transposition. - - -- ALGLIB PROJECT -- - Copyright 30.01.2018 by Bochkanov Sergey -*************************************************************************/ -void sparsetransposecrs(const sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsetransposecrs(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function performs copying with transposition of CRS matrix. - -INPUT PARAMETERS - S0 - sparse matrix in CRS format. - -OUTPUT PARAMETERS - S1 - sparse matrix, transposed - - -- ALGLIB PROJECT -- - Copyright 23.07.2018 by Bochkanov Sergey -*************************************************************************/ -void sparsecopytransposecrs(const sparsematrix &s0, sparsematrix &s1, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecopytransposecrs(const_cast(s0.c_ptr()), const_cast(s1.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function performs copying with transposition of CRS matrix (buffered -version which reuses memory already allocated by the target as much as -possible). - -INPUT PARAMETERS - S0 - sparse matrix in CRS format. - -OUTPUT PARAMETERS - S1 - sparse matrix, transposed; previously allocated memory is - reused if possible. - - -- ALGLIB PROJECT -- - Copyright 23.07.2018 by Bochkanov Sergey -*************************************************************************/ -void sparsecopytransposecrsbuf(const sparsematrix &s0, const sparsematrix &s1, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecopytransposecrsbuf(const_cast(s0.c_ptr()), const_cast(s1.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function performs in-place conversion to desired sparse storage -format. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - Fmt - desired storage format of the output, as returned by - SparseGetMatrixType() function: - * 0 for hash-based storage - * 1 for CRS - * 2 for SKS - -OUTPUT PARAMETERS - S0 - sparse matrix in requested format. - -NOTE: in-place conversion wastes a lot of memory which is used to store - temporaries. If you perform a lot of repeated conversions, we - recommend to use out-of-place buffered conversion functions, like - SparseCopyToBuf(), which can reuse already allocated memory. - - -- ALGLIB PROJECT -- - Copyright 16.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparseconvertto(const sparsematrix &s0, const ae_int_t fmt, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparseconvertto(const_cast(s0.c_ptr()), fmt, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function performs out-of-place conversion to desired sparse storage -format. S0 is copied to S1 and converted on-the-fly. Memory allocated in -S1 is reused to maximum extent possible. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - Fmt - desired storage format of the output, as returned by - SparseGetMatrixType() function: - * 0 for hash-based storage - * 1 for CRS - * 2 for SKS - -OUTPUT PARAMETERS - S1 - sparse matrix in requested format. - - -- ALGLIB PROJECT -- - Copyright 16.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsecopytobuf(const sparsematrix &s0, const ae_int_t fmt, const sparsematrix &s1, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecopytobuf(const_cast(s0.c_ptr()), fmt, const_cast(s1.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function performs in-place conversion to Hash table storage. - -INPUT PARAMETERS - S - sparse matrix in CRS format. - -OUTPUT PARAMETERS - S - sparse matrix in Hash table format. - -NOTE: this function has no effect when called with matrix which is - already in Hash table mode. - -NOTE: in-place conversion involves allocation of temporary arrays. If you - perform a lot of repeated in- place conversions, it may lead to - memory fragmentation. Consider using out-of-place SparseCopyToHashBuf() - function in this case. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -void sparseconverttohash(const sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparseconverttohash(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function performs out-of-place conversion to Hash table storage -format. S0 is copied to S1 and converted on-the-fly. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - -OUTPUT PARAMETERS - S1 - sparse matrix in Hash table format. - -NOTE: if S0 is stored as Hash-table, it is just copied without conversion. - -NOTE: this function de-allocates memory occupied by S1 before starting - conversion. If you perform a lot of repeated conversions, it may - lead to memory fragmentation. In this case we recommend you to use - SparseCopyToHashBuf() function which re-uses memory in S1 as much as - possible. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -void sparsecopytohash(const sparsematrix &s0, sparsematrix &s1, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecopytohash(const_cast(s0.c_ptr()), const_cast(s1.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function performs out-of-place conversion to Hash table storage -format. S0 is copied to S1 and converted on-the-fly. Memory allocated in -S1 is reused to maximum extent possible. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - -OUTPUT PARAMETERS - S1 - sparse matrix in Hash table format. - -NOTE: if S0 is stored as Hash-table, it is just copied without conversion. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -void sparsecopytohashbuf(const sparsematrix &s0, const sparsematrix &s1, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecopytohashbuf(const_cast(s0.c_ptr()), const_cast(s1.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function converts matrix to CRS format. - -Some algorithms (linear algebra ones, for example) require matrices in -CRS format. This function allows to perform in-place conversion. - -INPUT PARAMETERS - S - sparse M*N matrix in any format - -OUTPUT PARAMETERS - S - matrix in CRS format - -NOTE: this function has no effect when called with matrix which is - already in CRS mode. - -NOTE: this function allocates temporary memory to store a copy of the - matrix. If you perform a lot of repeated conversions, we recommend - you to use SparseCopyToCRSBuf() function, which can reuse - previously allocated memory. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparseconverttocrs(const sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparseconverttocrs(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function performs out-of-place conversion to CRS format. S0 is -copied to S1 and converted on-the-fly. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - -OUTPUT PARAMETERS - S1 - sparse matrix in CRS format. - -NOTE: if S0 is stored as CRS, it is just copied without conversion. - -NOTE: this function de-allocates memory occupied by S1 before starting CRS - conversion. If you perform a lot of repeated CRS conversions, it may - lead to memory fragmentation. In this case we recommend you to use - SparseCopyToCRSBuf() function which re-uses memory in S1 as much as - possible. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -void sparsecopytocrs(const sparsematrix &s0, sparsematrix &s1, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecopytocrs(const_cast(s0.c_ptr()), const_cast(s1.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function performs out-of-place conversion to CRS format. S0 is -copied to S1 and converted on-the-fly. Memory allocated in S1 is reused to -maximum extent possible. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - S1 - matrix which may contain some pre-allocated memory, or - can be just uninitialized structure. - -OUTPUT PARAMETERS - S1 - sparse matrix in CRS format. - -NOTE: if S0 is stored as CRS, it is just copied without conversion. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -void sparsecopytocrsbuf(const sparsematrix &s0, const sparsematrix &s1, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecopytocrsbuf(const_cast(s0.c_ptr()), const_cast(s1.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function performs in-place conversion to SKS format. - -INPUT PARAMETERS - S - sparse matrix in any format. - -OUTPUT PARAMETERS - S - sparse matrix in SKS format. - -NOTE: this function has no effect when called with matrix which is - already in SKS mode. - -NOTE: in-place conversion involves allocation of temporary arrays. If you - perform a lot of repeated in- place conversions, it may lead to - memory fragmentation. Consider using out-of-place SparseCopyToSKSBuf() - function in this case. - - -- ALGLIB PROJECT -- - Copyright 15.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparseconverttosks(const sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparseconverttosks(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function performs out-of-place conversion to SKS storage format. -S0 is copied to S1 and converted on-the-fly. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - -OUTPUT PARAMETERS - S1 - sparse matrix in SKS format. - -NOTE: if S0 is stored as SKS, it is just copied without conversion. - -NOTE: this function de-allocates memory occupied by S1 before starting - conversion. If you perform a lot of repeated conversions, it may - lead to memory fragmentation. In this case we recommend you to use - SparseCopyToSKSBuf() function which re-uses memory in S1 as much as - possible. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -void sparsecopytosks(const sparsematrix &s0, sparsematrix &s1, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecopytosks(const_cast(s0.c_ptr()), const_cast(s1.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function performs out-of-place conversion to SKS format. S0 is -copied to S1 and converted on-the-fly. Memory allocated in S1 is reused -to maximum extent possible. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - -OUTPUT PARAMETERS - S1 - sparse matrix in SKS format. - -NOTE: if S0 is stored as SKS, it is just copied without conversion. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -void sparsecopytosksbuf(const sparsematrix &s0, const sparsematrix &s1, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecopytosksbuf(const_cast(s0.c_ptr()), const_cast(s1.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function returns type of the matrix storage format. - -INPUT PARAMETERS: - S - sparse matrix. - -RESULT: - sparse storage format used by matrix: - 0 - Hash-table - 1 - CRS (compressed row storage) - 2 - SKS (skyline) - -NOTE: future versions of ALGLIB may include additional sparse storage - formats. - - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -ae_int_t sparsegetmatrixtype(const sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::sparsegetmatrixtype(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function checks matrix storage format and returns True when matrix is -stored using Hash table representation. - -INPUT PARAMETERS: - S - sparse matrix. - -RESULT: - True if matrix type is Hash table - False if matrix type is not Hash table - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -bool sparseishash(const sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::sparseishash(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function checks matrix storage format and returns True when matrix is -stored using CRS representation. - -INPUT PARAMETERS: - S - sparse matrix. - -RESULT: - True if matrix type is CRS - False if matrix type is not CRS - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -bool sparseiscrs(const sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::sparseiscrs(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function checks matrix storage format and returns True when matrix is -stored using SKS representation. - -INPUT PARAMETERS: - S - sparse matrix. - -RESULT: - True if matrix type is SKS - False if matrix type is not SKS - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -bool sparseissks(const sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::sparseissks(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -The function frees all memory occupied by sparse matrix. Sparse matrix -structure becomes unusable after this call. - -OUTPUT PARAMETERS - S - sparse matrix to delete - - -- ALGLIB PROJECT -- - Copyright 24.07.2012 by Bochkanov Sergey -*************************************************************************/ -void sparsefree(sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsefree(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -The function returns number of rows of a sparse matrix. - -RESULT: number of rows of a sparse matrix. - - -- ALGLIB PROJECT -- - Copyright 23.08.2012 by Bochkanov Sergey -*************************************************************************/ -ae_int_t sparsegetnrows(const sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::sparsegetnrows(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -The function returns number of columns of a sparse matrix. - -RESULT: number of columns of a sparse matrix. - - -- ALGLIB PROJECT -- - Copyright 23.08.2012 by Bochkanov Sergey -*************************************************************************/ -ae_int_t sparsegetncols(const sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::sparsegetncols(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -The function returns number of strictly upper triangular non-zero elements -in the matrix. It counts SYMBOLICALLY non-zero elements, i.e. entries -in the sparse matrix data structure. If some element has zero numerical -value, it is still counted. - -This function has different cost for different types of matrices: -* for hash-based matrices it involves complete pass over entire hash-table - with O(NNZ) cost, where NNZ is number of non-zero elements -* for CRS and SKS matrix types cost of counting is O(N) (N - matrix size). - -RESULT: number of non-zero elements strictly above main diagonal - - -- ALGLIB PROJECT -- - Copyright 12.02.2014 by Bochkanov Sergey -*************************************************************************/ -ae_int_t sparsegetuppercount(const sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::sparsegetuppercount(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -The function returns number of strictly lower triangular non-zero elements -in the matrix. It counts SYMBOLICALLY non-zero elements, i.e. entries -in the sparse matrix data structure. If some element has zero numerical -value, it is still counted. - -This function has different cost for different types of matrices: -* for hash-based matrices it involves complete pass over entire hash-table - with O(NNZ) cost, where NNZ is number of non-zero elements -* for CRS and SKS matrix types cost of counting is O(N) (N - matrix size). - -RESULT: number of non-zero elements strictly below main diagonal - - -- ALGLIB PROJECT -- - Copyright 12.02.2014 by Bochkanov Sergey -*************************************************************************/ -ae_int_t sparsegetlowercount(const sparsematrix &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::sparsegetlowercount(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_ABLAS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Cache-oblivous complex "copy-and-transpose" - -Input parameters: - M - number of rows - N - number of columns - A - source matrix, MxN submatrix is copied and transposed - IA - submatrix offset (row index) - JA - submatrix offset (column index) - B - destination matrix, must be large enough to store result - IB - submatrix offset (row index) - JB - submatrix offset (column index) -*************************************************************************/ -void cmatrixtranspose(const ae_int_t m, const ae_int_t n, const complex_2d_array &a, const ae_int_t ia, const ae_int_t ja, complex_2d_array &b, const ae_int_t ib, const ae_int_t jb, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixtranspose(m, n, const_cast(a.c_ptr()), ia, ja, const_cast(b.c_ptr()), ib, jb, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Cache-oblivous real "copy-and-transpose" - -Input parameters: - M - number of rows - N - number of columns - A - source matrix, MxN submatrix is copied and transposed - IA - submatrix offset (row index) - JA - submatrix offset (column index) - B - destination matrix, must be large enough to store result - IB - submatrix offset (row index) - JB - submatrix offset (column index) -*************************************************************************/ -void rmatrixtranspose(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const real_2d_array &b, const ae_int_t ib, const ae_int_t jb, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixtranspose(m, n, const_cast(a.c_ptr()), ia, ja, const_cast(b.c_ptr()), ib, jb, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This code enforces symmetricy of the matrix by copying Upper part to lower -one (or vice versa). - -INPUT PARAMETERS: - A - matrix - N - number of rows/columns - IsUpper - whether we want to copy upper triangle to lower one (True) - or vice versa (False). -*************************************************************************/ -void rmatrixenforcesymmetricity(const real_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixenforcesymmetricity(const_cast(a.c_ptr()), n, isupper, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Copy - -Input parameters: - M - number of rows - N - number of columns - A - source matrix, MxN submatrix is copied and transposed - IA - submatrix offset (row index) - JA - submatrix offset (column index) - B - destination matrix, must be large enough to store result - IB - submatrix offset (row index) - JB - submatrix offset (column index) -*************************************************************************/ -void cmatrixcopy(const ae_int_t m, const ae_int_t n, const complex_2d_array &a, const ae_int_t ia, const ae_int_t ja, complex_2d_array &b, const ae_int_t ib, const ae_int_t jb, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixcopy(m, n, const_cast(a.c_ptr()), ia, ja, const_cast(b.c_ptr()), ib, jb, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Copy - -Input parameters: - N - subvector size - A - source vector, N elements are copied - IA - source offset (first element index) - B - destination vector, must be large enough to store result - IB - destination offset (first element index) -*************************************************************************/ -void rvectorcopy(const ae_int_t n, const real_1d_array &a, const ae_int_t ia, const real_1d_array &b, const ae_int_t ib, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rvectorcopy(n, const_cast(a.c_ptr()), ia, const_cast(b.c_ptr()), ib, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Copy - -Input parameters: - M - number of rows - N - number of columns - A - source matrix, MxN submatrix is copied and transposed - IA - submatrix offset (row index) - JA - submatrix offset (column index) - B - destination matrix, must be large enough to store result - IB - submatrix offset (row index) - JB - submatrix offset (column index) -*************************************************************************/ -void rmatrixcopy(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const real_2d_array &b, const ae_int_t ib, const ae_int_t jb, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixcopy(m, n, const_cast(a.c_ptr()), ia, ja, const_cast(b.c_ptr()), ib, jb, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Performs generalized copy: B := Beta*B + Alpha*A. - -If Beta=0, then previous contents of B is simply ignored. If Alpha=0, then -A is ignored and not referenced. If both Alpha and Beta are zero, B is -filled by zeros. - -Input parameters: - M - number of rows - N - number of columns - Alpha- coefficient - A - source matrix, MxN submatrix is copied and transposed - IA - submatrix offset (row index) - JA - submatrix offset (column index) - Beta- coefficient - B - destination matrix, must be large enough to store result - IB - submatrix offset (row index) - JB - submatrix offset (column index) -*************************************************************************/ -void rmatrixgencopy(const ae_int_t m, const ae_int_t n, const double alpha, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const double beta, const real_2d_array &b, const ae_int_t ib, const ae_int_t jb, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixgencopy(m, n, alpha, const_cast(a.c_ptr()), ia, ja, beta, const_cast(b.c_ptr()), ib, jb, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Rank-1 correction: A := A + alpha*u*v' - -NOTE: this function expects A to be large enough to store result. No - automatic preallocation happens for smaller arrays. No integrity - checks is performed for sizes of A, u, v. - -INPUT PARAMETERS: - M - number of rows - N - number of columns - A - target matrix, MxN submatrix is updated - IA - submatrix offset (row index) - JA - submatrix offset (column index) - Alpha- coefficient - U - vector #1 - IU - subvector offset - V - vector #2 - IV - subvector offset - - - -- ALGLIB routine -- - - 16.10.2017 - Bochkanov Sergey -*************************************************************************/ -void rmatrixger(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const double alpha, const real_1d_array &u, const ae_int_t iu, const real_1d_array &v, const ae_int_t iv, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixger(m, n, const_cast(a.c_ptr()), ia, ja, alpha, const_cast(u.c_ptr()), iu, const_cast(v.c_ptr()), iv, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Rank-1 correction: A := A + u*v' - -INPUT PARAMETERS: - M - number of rows - N - number of columns - A - target matrix, MxN submatrix is updated - IA - submatrix offset (row index) - JA - submatrix offset (column index) - U - vector #1 - IU - subvector offset - V - vector #2 - IV - subvector offset -*************************************************************************/ -void cmatrixrank1(const ae_int_t m, const ae_int_t n, complex_2d_array &a, const ae_int_t ia, const ae_int_t ja, complex_1d_array &u, const ae_int_t iu, complex_1d_array &v, const ae_int_t iv, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixrank1(m, n, const_cast(a.c_ptr()), ia, ja, const_cast(u.c_ptr()), iu, const_cast(v.c_ptr()), iv, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -IMPORTANT: this function is deprecated since ALGLIB 3.13. Use RMatrixGER() - which is more generic version of this function. - -Rank-1 correction: A := A + u*v' - -INPUT PARAMETERS: - M - number of rows - N - number of columns - A - target matrix, MxN submatrix is updated - IA - submatrix offset (row index) - JA - submatrix offset (column index) - U - vector #1 - IU - subvector offset - V - vector #2 - IV - subvector offset -*************************************************************************/ -void rmatrixrank1(const ae_int_t m, const ae_int_t n, real_2d_array &a, const ae_int_t ia, const ae_int_t ja, real_1d_array &u, const ae_int_t iu, real_1d_array &v, const ae_int_t iv, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixrank1(m, n, const_cast(a.c_ptr()), ia, ja, const_cast(u.c_ptr()), iu, const_cast(v.c_ptr()), iv, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* - -*************************************************************************/ -void rmatrixgemv(const ae_int_t m, const ae_int_t n, const double alpha, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t opa, const real_1d_array &x, const ae_int_t ix, const double beta, const real_1d_array &y, const ae_int_t iy, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixgemv(m, n, alpha, const_cast(a.c_ptr()), ia, ja, opa, const_cast(x.c_ptr()), ix, beta, const_cast(y.c_ptr()), iy, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Matrix-vector product: y := op(A)*x - -INPUT PARAMETERS: - M - number of rows of op(A) - M>=0 - N - number of columns of op(A) - N>=0 - A - target matrix - IA - submatrix offset (row index) - JA - submatrix offset (column index) - OpA - operation type: - * OpA=0 => op(A) = A - * OpA=1 => op(A) = A^T - * OpA=2 => op(A) = A^H - X - input vector - IX - subvector offset - IY - subvector offset - Y - preallocated matrix, must be large enough to store result - -OUTPUT PARAMETERS: - Y - vector which stores result - -if M=0, then subroutine does nothing. -if N=0, Y is filled by zeros. - - - -- ALGLIB routine -- - - 28.01.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixmv(const ae_int_t m, const ae_int_t n, const complex_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t opa, const complex_1d_array &x, const ae_int_t ix, complex_1d_array &y, const ae_int_t iy, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixmv(m, n, const_cast(a.c_ptr()), ia, ja, opa, const_cast(x.c_ptr()), ix, const_cast(y.c_ptr()), iy, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -IMPORTANT: this function is deprecated since ALGLIB 3.13. Use RMatrixGEMV() - which is more generic version of this function. - -Matrix-vector product: y := op(A)*x - -INPUT PARAMETERS: - M - number of rows of op(A) - N - number of columns of op(A) - A - target matrix - IA - submatrix offset (row index) - JA - submatrix offset (column index) - OpA - operation type: - * OpA=0 => op(A) = A - * OpA=1 => op(A) = A^T - X - input vector - IX - subvector offset - IY - subvector offset - Y - preallocated matrix, must be large enough to store result - -OUTPUT PARAMETERS: - Y - vector which stores result - -if M=0, then subroutine does nothing. -if N=0, Y is filled by zeros. - - - -- ALGLIB routine -- - - 28.01.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixmv(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t opa, const real_1d_array &x, const ae_int_t ix, const real_1d_array &y, const ae_int_t iy, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixmv(m, n, const_cast(a.c_ptr()), ia, ja, opa, const_cast(x.c_ptr()), ix, const_cast(y.c_ptr()), iy, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* - -*************************************************************************/ -void rmatrixsymv(const ae_int_t n, const double alpha, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const bool isupper, const real_1d_array &x, const ae_int_t ix, const double beta, const real_1d_array &y, const ae_int_t iy, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixsymv(n, alpha, const_cast(a.c_ptr()), ia, ja, isupper, const_cast(x.c_ptr()), ix, beta, const_cast(y.c_ptr()), iy, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* - -*************************************************************************/ -double rmatrixsyvmv(const ae_int_t n, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const bool isupper, const real_1d_array &x, const ae_int_t ix, const real_1d_array &tmp, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::rmatrixsyvmv(n, const_cast(a.c_ptr()), ia, ja, isupper, const_cast(x.c_ptr()), ix, const_cast(tmp.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This subroutine solves linear system op(A)*x=b where: -* A is NxN upper/lower triangular/unitriangular matrix -* X and B are Nx1 vectors -* "op" may be identity transformation, transposition, conjugate transposition - -Solution replaces X. - -IMPORTANT: * no overflow/underflow/denegeracy tests is performed. - * no integrity checks for operand sizes, out-of-bounds accesses - and so on is performed - -INPUT PARAMETERS - N - matrix size, N>=0 - A - matrix, actial matrix is stored in A[IA:IA+N-1,JA:JA+N-1] - IA - submatrix offset - JA - submatrix offset - IsUpper - whether matrix is upper triangular - IsUnit - whether matrix is unitriangular - OpType - transformation type: - * 0 - no transformation - * 1 - transposition - X - right part, actual vector is stored in X[IX:IX+N-1] - IX - offset - -OUTPUT PARAMETERS - X - solution replaces elements X[IX:IX+N-1] - - -- ALGLIB routine / remastering of LAPACK's DTRSV -- - (c) 2017 Bochkanov Sergey - converted to ALGLIB - (c) 2016 Reference BLAS level1 routine (LAPACK version 3.7.0) - Reference BLAS is a software package provided by Univ. of Tennessee, - Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd. -*************************************************************************/ -void rmatrixtrsv(const ae_int_t n, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const bool isupper, const bool isunit, const ae_int_t optype, const real_1d_array &x, const ae_int_t ix, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixtrsv(n, const_cast(a.c_ptr()), ia, ja, isupper, isunit, optype, const_cast(x.c_ptr()), ix, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine calculates X*op(A^-1) where: -* X is MxN general matrix -* A is NxN upper/lower triangular/unitriangular matrix -* "op" may be identity transformation, transposition, conjugate transposition -Multiplication result replaces X. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - M - matrix size, N>=0 - A - matrix, actial matrix is stored in A[I1:I1+N-1,J1:J1+N-1] - I1 - submatrix offset - J1 - submatrix offset - IsUpper - whether matrix is upper triangular - IsUnit - whether matrix is unitriangular - OpType - transformation type: - * 0 - no transformation - * 1 - transposition - * 2 - conjugate transposition - X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1] - I2 - submatrix offset - J2 - submatrix offset - - -- ALGLIB routine -- - 20.01.2018 - Bochkanov Sergey -*************************************************************************/ -void cmatrixrighttrsm(const ae_int_t m, const ae_int_t n, const complex_2d_array &a, const ae_int_t i1, const ae_int_t j1, const bool isupper, const bool isunit, const ae_int_t optype, const complex_2d_array &x, const ae_int_t i2, const ae_int_t j2, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixrighttrsm(m, n, const_cast(a.c_ptr()), i1, j1, isupper, isunit, optype, const_cast(x.c_ptr()), i2, j2, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine calculates op(A^-1)*X where: -* X is MxN general matrix -* A is MxM upper/lower triangular/unitriangular matrix -* "op" may be identity transformation, transposition, conjugate transposition -Multiplication result replaces X. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - M - matrix size, N>=0 - A - matrix, actial matrix is stored in A[I1:I1+M-1,J1:J1+M-1] - I1 - submatrix offset - J1 - submatrix offset - IsUpper - whether matrix is upper triangular - IsUnit - whether matrix is unitriangular - OpType - transformation type: - * 0 - no transformation - * 1 - transposition - * 2 - conjugate transposition - X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1] - I2 - submatrix offset - J2 - submatrix offset - - -- ALGLIB routine -- - 15.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -void cmatrixlefttrsm(const ae_int_t m, const ae_int_t n, const complex_2d_array &a, const ae_int_t i1, const ae_int_t j1, const bool isupper, const bool isunit, const ae_int_t optype, const complex_2d_array &x, const ae_int_t i2, const ae_int_t j2, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixlefttrsm(m, n, const_cast(a.c_ptr()), i1, j1, isupper, isunit, optype, const_cast(x.c_ptr()), i2, j2, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine calculates X*op(A^-1) where: -* X is MxN general matrix -* A is NxN upper/lower triangular/unitriangular matrix -* "op" may be identity transformation, transposition -Multiplication result replaces X. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - M - matrix size, N>=0 - A - matrix, actial matrix is stored in A[I1:I1+N-1,J1:J1+N-1] - I1 - submatrix offset - J1 - submatrix offset - IsUpper - whether matrix is upper triangular - IsUnit - whether matrix is unitriangular - OpType - transformation type: - * 0 - no transformation - * 1 - transposition - X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1] - I2 - submatrix offset - J2 - submatrix offset - - -- ALGLIB routine -- - 15.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -void rmatrixrighttrsm(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const ae_int_t i1, const ae_int_t j1, const bool isupper, const bool isunit, const ae_int_t optype, const real_2d_array &x, const ae_int_t i2, const ae_int_t j2, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixrighttrsm(m, n, const_cast(a.c_ptr()), i1, j1, isupper, isunit, optype, const_cast(x.c_ptr()), i2, j2, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine calculates op(A^-1)*X where: -* X is MxN general matrix -* A is MxM upper/lower triangular/unitriangular matrix -* "op" may be identity transformation, transposition -Multiplication result replaces X. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - M - matrix size, N>=0 - A - matrix, actial matrix is stored in A[I1:I1+M-1,J1:J1+M-1] - I1 - submatrix offset - J1 - submatrix offset - IsUpper - whether matrix is upper triangular - IsUnit - whether matrix is unitriangular - OpType - transformation type: - * 0 - no transformation - * 1 - transposition - X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1] - I2 - submatrix offset - J2 - submatrix offset - - -- ALGLIB routine -- - 15.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -void rmatrixlefttrsm(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const ae_int_t i1, const ae_int_t j1, const bool isupper, const bool isunit, const ae_int_t optype, const real_2d_array &x, const ae_int_t i2, const ae_int_t j2, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixlefttrsm(m, n, const_cast(a.c_ptr()), i1, j1, isupper, isunit, optype, const_cast(x.c_ptr()), i2, j2, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine calculates C=alpha*A*A^H+beta*C or C=alpha*A^H*A+beta*C -where: -* C is NxN Hermitian matrix given by its upper/lower triangle -* A is NxK matrix when A*A^H is calculated, KxN matrix otherwise - -Additional info: -* multiplication result replaces C. If Beta=0, C elements are not used in - calculations (not multiplied by zero - just not referenced) -* if Alpha=0, A is not used (not multiplied by zero - just not referenced) -* if both Beta and Alpha are zero, C is filled by zeros. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - K - matrix size, K>=0 - Alpha - coefficient - A - matrix - IA - submatrix offset (row index) - JA - submatrix offset (column index) - OpTypeA - multiplication type: - * 0 - A*A^H is calculated - * 2 - A^H*A is calculated - Beta - coefficient - C - preallocated input/output matrix - IC - submatrix offset (row index) - JC - submatrix offset (column index) - IsUpper - whether upper or lower triangle of C is updated; - this function updates only one half of C, leaving - other half unchanged (not referenced at all). - - -- ALGLIB routine -- - 16.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -void cmatrixherk(const ae_int_t n, const ae_int_t k, const double alpha, const complex_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t optypea, const double beta, const complex_2d_array &c, const ae_int_t ic, const ae_int_t jc, const bool isupper, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixherk(n, k, alpha, const_cast(a.c_ptr()), ia, ja, optypea, beta, const_cast(c.c_ptr()), ic, jc, isupper, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine calculates C=alpha*A*A^T+beta*C or C=alpha*A^T*A+beta*C -where: -* C is NxN symmetric matrix given by its upper/lower triangle -* A is NxK matrix when A*A^T is calculated, KxN matrix otherwise - -Additional info: -* multiplication result replaces C. If Beta=0, C elements are not used in - calculations (not multiplied by zero - just not referenced) -* if Alpha=0, A is not used (not multiplied by zero - just not referenced) -* if both Beta and Alpha are zero, C is filled by zeros. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - K - matrix size, K>=0 - Alpha - coefficient - A - matrix - IA - submatrix offset (row index) - JA - submatrix offset (column index) - OpTypeA - multiplication type: - * 0 - A*A^T is calculated - * 2 - A^T*A is calculated - Beta - coefficient - C - preallocated input/output matrix - IC - submatrix offset (row index) - JC - submatrix offset (column index) - IsUpper - whether C is upper triangular or lower triangular - - -- ALGLIB routine -- - 16.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -void rmatrixsyrk(const ae_int_t n, const ae_int_t k, const double alpha, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t optypea, const double beta, const real_2d_array &c, const ae_int_t ic, const ae_int_t jc, const bool isupper, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixsyrk(n, k, alpha, const_cast(a.c_ptr()), ia, ja, optypea, beta, const_cast(c.c_ptr()), ic, jc, isupper, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine calculates C = alpha*op1(A)*op2(B) +beta*C where: -* C is MxN general matrix -* op1(A) is MxK matrix -* op2(B) is KxN matrix -* "op" may be identity transformation, transposition, conjugate transposition - -Additional info: -* cache-oblivious algorithm is used. -* multiplication result replaces C. If Beta=0, C elements are not used in - calculations (not multiplied by zero - just not referenced) -* if Alpha=0, A is not used (not multiplied by zero - just not referenced) -* if both Beta and Alpha are zero, C is filled by zeros. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -IMPORTANT: - -This function does NOT preallocate output matrix C, it MUST be preallocated -by caller prior to calling this function. In case C does not have enough -space to store result, exception will be generated. - -INPUT PARAMETERS - M - matrix size, M>0 - N - matrix size, N>0 - K - matrix size, K>0 - Alpha - coefficient - A - matrix - IA - submatrix offset - JA - submatrix offset - OpTypeA - transformation type: - * 0 - no transformation - * 1 - transposition - * 2 - conjugate transposition - B - matrix - IB - submatrix offset - JB - submatrix offset - OpTypeB - transformation type: - * 0 - no transformation - * 1 - transposition - * 2 - conjugate transposition - Beta - coefficient - C - matrix (PREALLOCATED, large enough to store result) - IC - submatrix offset - JC - submatrix offset - - -- ALGLIB routine -- - 2009-2019 - Bochkanov Sergey -*************************************************************************/ -void cmatrixgemm(const ae_int_t m, const ae_int_t n, const ae_int_t k, const alglib::complex alpha, const complex_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t optypea, const complex_2d_array &b, const ae_int_t ib, const ae_int_t jb, const ae_int_t optypeb, const alglib::complex beta, const complex_2d_array &c, const ae_int_t ic, const ae_int_t jc, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixgemm(m, n, k, *alpha.c_ptr(), const_cast(a.c_ptr()), ia, ja, optypea, const_cast(b.c_ptr()), ib, jb, optypeb, *beta.c_ptr(), const_cast(c.c_ptr()), ic, jc, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine calculates C = alpha*op1(A)*op2(B) +beta*C where: -* C is MxN general matrix -* op1(A) is MxK matrix -* op2(B) is KxN matrix -* "op" may be identity transformation, transposition - -Additional info: -* cache-oblivious algorithm is used. -* multiplication result replaces C. If Beta=0, C elements are not used in - calculations (not multiplied by zero - just not referenced) -* if Alpha=0, A is not used (not multiplied by zero - just not referenced) -* if both Beta and Alpha are zero, C is filled by zeros. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -IMPORTANT: - -This function does NOT preallocate output matrix C, it MUST be preallocated -by caller prior to calling this function. In case C does not have enough -space to store result, exception will be generated. - -INPUT PARAMETERS - M - matrix size, M>0 - N - matrix size, N>0 - K - matrix size, K>0 - Alpha - coefficient - A - matrix - IA - submatrix offset - JA - submatrix offset - OpTypeA - transformation type: - * 0 - no transformation - * 1 - transposition - B - matrix - IB - submatrix offset - JB - submatrix offset - OpTypeB - transformation type: - * 0 - no transformation - * 1 - transposition - Beta - coefficient - C - PREALLOCATED output matrix, large enough to store result - IC - submatrix offset - JC - submatrix offset - - -- ALGLIB routine -- - 2009-2019 - Bochkanov Sergey -*************************************************************************/ -void rmatrixgemm(const ae_int_t m, const ae_int_t n, const ae_int_t k, const double alpha, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t optypea, const real_2d_array &b, const ae_int_t ib, const ae_int_t jb, const ae_int_t optypeb, const double beta, const real_2d_array &c, const ae_int_t ic, const ae_int_t jc, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixgemm(m, n, k, alpha, const_cast(a.c_ptr()), ia, ja, optypea, const_cast(b.c_ptr()), ib, jb, optypeb, beta, const_cast(c.c_ptr()), ic, jc, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine is an older version of CMatrixHERK(), one with wrong name -(it is HErmitian update, not SYmmetric). It is left here for backward -compatibility. - - -- ALGLIB routine -- - 16.12.2009 - Bochkanov Sergey -*************************************************************************/ -void cmatrixsyrk(const ae_int_t n, const ae_int_t k, const double alpha, const complex_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t optypea, const double beta, const complex_2d_array &c, const ae_int_t ic, const ae_int_t jc, const bool isupper, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixsyrk(n, k, alpha, const_cast(a.c_ptr()), ia, ja, optypea, beta, const_cast(c.c_ptr()), ic, jc, isupper, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_DLU) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPTRF) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_AMDORDERING) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPCHOL) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MATGEN) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Generation of a random uniformly distributed (Haar) orthogonal matrix - -INPUT PARAMETERS: - N - matrix size, N>=1 - -OUTPUT PARAMETERS: - A - orthogonal NxN matrix, array[0..N-1,0..N-1] - -NOTE: this function uses algorithm described in Stewart, G. W. (1980), - "The Efficient Generation of Random Orthogonal Matrices with an - Application to Condition Estimators". - - Speaking short, to generate an (N+1)x(N+1) orthogonal matrix, it: - * takes an NxN one - * takes uniformly distributed unit vector of dimension N+1. - * constructs a Householder reflection from the vector, then applies - it to the smaller matrix (embedded in the larger size with a 1 at - the bottom right corner). - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void rmatrixrndorthogonal(const ae_int_t n, real_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixrndorthogonal(n, const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Generation of random NxN matrix with given condition number and norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void rmatrixrndcond(const ae_int_t n, const double c, real_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixrndcond(n, c, const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Generation of a random Haar distributed orthogonal complex matrix - -INPUT PARAMETERS: - N - matrix size, N>=1 - -OUTPUT PARAMETERS: - A - orthogonal NxN matrix, array[0..N-1,0..N-1] - -NOTE: this function uses algorithm described in Stewart, G. W. (1980), - "The Efficient Generation of Random Orthogonal Matrices with an - Application to Condition Estimators". - - Speaking short, to generate an (N+1)x(N+1) orthogonal matrix, it: - * takes an NxN one - * takes uniformly distributed unit vector of dimension N+1. - * constructs a Householder reflection from the vector, then applies - it to the smaller matrix (embedded in the larger size with a 1 at - the bottom right corner). - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void cmatrixrndorthogonal(const ae_int_t n, complex_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixrndorthogonal(n, const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Generation of random NxN complex matrix with given condition number C and -norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void cmatrixrndcond(const ae_int_t n, const double c, complex_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixrndcond(n, c, const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Generation of random NxN symmetric matrix with given condition number and -norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void smatrixrndcond(const ae_int_t n, const double c, real_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::smatrixrndcond(n, c, const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Generation of random NxN symmetric positive definite matrix with given -condition number and norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random SPD matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void spdmatrixrndcond(const ae_int_t n, const double c, real_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spdmatrixrndcond(n, c, const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Generation of random NxN Hermitian matrix with given condition number and -norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void hmatrixrndcond(const ae_int_t n, const double c, complex_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hmatrixrndcond(n, c, const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Generation of random NxN Hermitian positive definite matrix with given -condition number and norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random HPD matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void hpdmatrixrndcond(const ae_int_t n, const double c, complex_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hpdmatrixrndcond(n, c, const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Multiplication of MxN matrix by NxN random Haar distributed orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..M-1, 0..N-1] - M, N- matrix size - -OUTPUT PARAMETERS: - A - A*Q, where Q is random NxN orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void rmatrixrndorthogonalfromtheright(real_2d_array &a, const ae_int_t m, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixrndorthogonalfromtheright(const_cast(a.c_ptr()), m, n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Multiplication of MxN matrix by MxM random Haar distributed orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..M-1, 0..N-1] - M, N- matrix size - -OUTPUT PARAMETERS: - A - Q*A, where Q is random MxM orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void rmatrixrndorthogonalfromtheleft(real_2d_array &a, const ae_int_t m, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixrndorthogonalfromtheleft(const_cast(a.c_ptr()), m, n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Multiplication of MxN complex matrix by NxN random Haar distributed -complex orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..M-1, 0..N-1] - M, N- matrix size - -OUTPUT PARAMETERS: - A - A*Q, where Q is random NxN orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void cmatrixrndorthogonalfromtheright(complex_2d_array &a, const ae_int_t m, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixrndorthogonalfromtheright(const_cast(a.c_ptr()), m, n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Multiplication of MxN complex matrix by MxM random Haar distributed -complex orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..M-1, 0..N-1] - M, N- matrix size - -OUTPUT PARAMETERS: - A - Q*A, where Q is random MxM orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void cmatrixrndorthogonalfromtheleft(complex_2d_array &a, const ae_int_t m, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixrndorthogonalfromtheleft(const_cast(a.c_ptr()), m, n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Symmetric multiplication of NxN matrix by random Haar distributed -orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..N-1, 0..N-1] - N - matrix size - -OUTPUT PARAMETERS: - A - Q'*A*Q, where Q is random NxN orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void smatrixrndmultiply(real_2d_array &a, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::smatrixrndmultiply(const_cast(a.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Hermitian multiplication of NxN matrix by random Haar distributed -complex orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..N-1, 0..N-1] - N - matrix size - -OUTPUT PARAMETERS: - A - Q^H*A*Q, where Q is random NxN orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void hmatrixrndmultiply(complex_2d_array &a, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hmatrixrndmultiply(const_cast(a.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_TRFAC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -An analysis of the sparse matrix decomposition, performed prior to actual -numerical factorization. You should not directly access fields of this -object - use appropriate ALGLIB functions to work with this object. -*************************************************************************/ -_sparsedecompositionanalysis_owner::_sparsedecompositionanalysis_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_sparsedecompositionanalysis_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::sparsedecompositionanalysis*)alglib_impl::ae_malloc(sizeof(alglib_impl::sparsedecompositionanalysis), &_state); - memset(p_struct, 0, sizeof(alglib_impl::sparsedecompositionanalysis)); - alglib_impl::_sparsedecompositionanalysis_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_sparsedecompositionanalysis_owner::_sparsedecompositionanalysis_owner(const _sparsedecompositionanalysis_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_sparsedecompositionanalysis_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: sparsedecompositionanalysis copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::sparsedecompositionanalysis*)alglib_impl::ae_malloc(sizeof(alglib_impl::sparsedecompositionanalysis), &_state); - memset(p_struct, 0, sizeof(alglib_impl::sparsedecompositionanalysis)); - alglib_impl::_sparsedecompositionanalysis_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_sparsedecompositionanalysis_owner& _sparsedecompositionanalysis_owner::operator=(const _sparsedecompositionanalysis_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: sparsedecompositionanalysis assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: sparsedecompositionanalysis assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_sparsedecompositionanalysis_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::sparsedecompositionanalysis)); - alglib_impl::_sparsedecompositionanalysis_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_sparsedecompositionanalysis_owner::~_sparsedecompositionanalysis_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_sparsedecompositionanalysis_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::sparsedecompositionanalysis* _sparsedecompositionanalysis_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::sparsedecompositionanalysis* _sparsedecompositionanalysis_owner::c_ptr() const -{ - return const_cast(p_struct); -} -sparsedecompositionanalysis::sparsedecompositionanalysis() : _sparsedecompositionanalysis_owner() -{ -} - -sparsedecompositionanalysis::sparsedecompositionanalysis(const sparsedecompositionanalysis &rhs):_sparsedecompositionanalysis_owner(rhs) -{ -} - -sparsedecompositionanalysis& sparsedecompositionanalysis::operator=(const sparsedecompositionanalysis &rhs) -{ - if( this==&rhs ) - return *this; - _sparsedecompositionanalysis_owner::operator=(rhs); - return *this; -} - -sparsedecompositionanalysis::~sparsedecompositionanalysis() -{ -} - -/************************************************************************* -LU decomposition of a general real matrix with row pivoting - -A is represented as A = P*L*U, where: -* L is lower unitriangular matrix -* U is upper triangular matrix -* P = P0*P1*...*PK, K=min(M,N)-1, - Pi - permutation matrix for I and Pivots[I] - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - array[0..M-1, 0..N-1]. - M - number of rows in matrix A. - N - number of columns in matrix A. - - -OUTPUT PARAMETERS: - A - matrices L and U in compact form: - * L is stored under main diagonal - * U is stored on and above main diagonal - Pivots - permutation matrix in compact form. - array[0..Min(M-1,N-1)]. - - -- ALGLIB routine -- - 10.01.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixlu(real_2d_array &a, const ae_int_t m, const ae_int_t n, integer_1d_array &pivots, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixlu(const_cast(a.c_ptr()), m, n, const_cast(pivots.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -LU decomposition of a general complex matrix with row pivoting - -A is represented as A = P*L*U, where: -* L is lower unitriangular matrix -* U is upper triangular matrix -* P = P0*P1*...*PK, K=min(M,N)-1, - Pi - permutation matrix for I and Pivots[I] - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - array[0..M-1, 0..N-1]. - M - number of rows in matrix A. - N - number of columns in matrix A. - - -OUTPUT PARAMETERS: - A - matrices L and U in compact form: - * L is stored under main diagonal - * U is stored on and above main diagonal - Pivots - permutation matrix in compact form. - array[0..Min(M-1,N-1)]. - - -- ALGLIB routine -- - 10.01.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixlu(complex_2d_array &a, const ae_int_t m, const ae_int_t n, integer_1d_array &pivots, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixlu(const_cast(a.c_ptr()), m, n, const_cast(pivots.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Cache-oblivious Cholesky decomposition - -The algorithm computes Cholesky decomposition of a Hermitian positive- -definite matrix. The result of an algorithm is a representation of A as -A=U'*U or A=L*L' (here X' denotes conj(X^T)). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - upper or lower triangle of a factorized matrix. - array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - if IsUpper=True, then A contains an upper triangle of - a symmetric matrix, otherwise A contains a lower one. - -OUTPUT PARAMETERS: - A - the result of factorization. If IsUpper=True, then - the upper triangle contains matrix U, so that A = U'*U, - and the elements below the main diagonal are not modified. - Similarly, if IsUpper = False. - -RESULT: - If the matrix is positive-definite, the function returns True. - Otherwise, the function returns False. Contents of A is not determined - in such case. - - -- ALGLIB routine -- - 15.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -bool hpdmatrixcholesky(complex_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::hpdmatrixcholesky(const_cast(a.c_ptr()), n, isupper, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Cache-oblivious Cholesky decomposition - -The algorithm computes Cholesky decomposition of a symmetric positive- -definite matrix. The result of an algorithm is a representation of A as -A=U^T*U or A=L*L^T - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - upper or lower triangle of a factorized matrix. - array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - if IsUpper=True, then A contains an upper triangle of - a symmetric matrix, otherwise A contains a lower one. - -OUTPUT PARAMETERS: - A - the result of factorization. If IsUpper=True, then - the upper triangle contains matrix U, so that A = U^T*U, - and the elements below the main diagonal are not modified. - Similarly, if IsUpper = False. - -RESULT: - If the matrix is positive-definite, the function returns True. - Otherwise, the function returns False. Contents of A is not determined - in such case. - - -- ALGLIB routine -- - 15.12.2009 - Bochkanov Sergey -*************************************************************************/ -bool spdmatrixcholesky(real_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::spdmatrixcholesky(const_cast(a.c_ptr()), n, isupper, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Update of Cholesky decomposition: rank-1 update to original A. "Buffered" -version which uses preallocated buffer which is saved between subsequent -function calls. - -This function uses internally allocated buffer which is not saved between -subsequent calls. So, if you perform a lot of subsequent updates, -we recommend you to use "buffered" version of this function: -SPDMatrixCholeskyUpdateAdd1Buf(). - -INPUT PARAMETERS: - A - upper or lower Cholesky factor. - array with elements [0..N-1, 0..N-1]. - Exception is thrown if array size is too small. - N - size of matrix A, N>0 - IsUpper - if IsUpper=True, then A contains upper Cholesky factor; - otherwise A contains a lower one. - U - array[N], rank-1 update to A: A_mod = A + u*u' - Exception is thrown if array size is too small. - BufR - possibly preallocated buffer; automatically resized if - needed. It is recommended to reuse this buffer if you - perform a lot of subsequent decompositions. - -OUTPUT PARAMETERS: - A - updated factorization. If IsUpper=True, then the upper - triangle contains matrix U, and the elements below the main - diagonal are not modified. Similarly, if IsUpper = False. - -NOTE: this function always succeeds, so it does not return completion code - -NOTE: this function checks sizes of input arrays, but it does NOT checks - for presence of infinities or NAN's. - - -- ALGLIB -- - 03.02.2014 - Sergey Bochkanov -*************************************************************************/ -void spdmatrixcholeskyupdateadd1(const real_2d_array &a, const ae_int_t n, const bool isupper, const real_1d_array &u, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spdmatrixcholeskyupdateadd1(const_cast(a.c_ptr()), n, isupper, const_cast(u.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Update of Cholesky decomposition: "fixing" some variables. - -This function uses internally allocated buffer which is not saved between -subsequent calls. So, if you perform a lot of subsequent updates, -we recommend you to use "buffered" version of this function: -SPDMatrixCholeskyUpdateFixBuf(). - -"FIXING" EXPLAINED: - - Suppose we have N*N positive definite matrix A. "Fixing" some variable - means filling corresponding row/column of A by zeros, and setting - diagonal element to 1. - - For example, if we fix 2nd variable in 4*4 matrix A, it becomes Af: - - ( A00 A01 A02 A03 ) ( Af00 0 Af02 Af03 ) - ( A10 A11 A12 A13 ) ( 0 1 0 0 ) - ( A20 A21 A22 A23 ) => ( Af20 0 Af22 Af23 ) - ( A30 A31 A32 A33 ) ( Af30 0 Af32 Af33 ) - - If we have Cholesky decomposition of A, it must be recalculated after - variables were fixed. However, it is possible to use efficient - algorithm, which needs O(K*N^2) time to "fix" K variables, given - Cholesky decomposition of original, "unfixed" A. - -INPUT PARAMETERS: - A - upper or lower Cholesky factor. - array with elements [0..N-1, 0..N-1]. - Exception is thrown if array size is too small. - N - size of matrix A, N>0 - IsUpper - if IsUpper=True, then A contains upper Cholesky factor; - otherwise A contains a lower one. - Fix - array[N], I-th element is True if I-th variable must be - fixed. Exception is thrown if array size is too small. - BufR - possibly preallocated buffer; automatically resized if - needed. It is recommended to reuse this buffer if you - perform a lot of subsequent decompositions. - -OUTPUT PARAMETERS: - A - updated factorization. If IsUpper=True, then the upper - triangle contains matrix U, and the elements below the main - diagonal are not modified. Similarly, if IsUpper = False. - -NOTE: this function always succeeds, so it does not return completion code - -NOTE: this function checks sizes of input arrays, but it does NOT checks - for presence of infinities or NAN's. - -NOTE: this function is efficient only for moderate amount of updated - variables - say, 0.1*N or 0.3*N. For larger amount of variables it - will still work, but you may get better performance with - straightforward Cholesky. - - -- ALGLIB -- - 03.02.2014 - Sergey Bochkanov -*************************************************************************/ -void spdmatrixcholeskyupdatefix(const real_2d_array &a, const ae_int_t n, const bool isupper, const boolean_1d_array &fix, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spdmatrixcholeskyupdatefix(const_cast(a.c_ptr()), n, isupper, const_cast(fix.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Update of Cholesky decomposition: rank-1 update to original A. "Buffered" -version which uses preallocated buffer which is saved between subsequent -function calls. - -See comments for SPDMatrixCholeskyUpdateAdd1() for more information. - -INPUT PARAMETERS: - A - upper or lower Cholesky factor. - array with elements [0..N-1, 0..N-1]. - Exception is thrown if array size is too small. - N - size of matrix A, N>0 - IsUpper - if IsUpper=True, then A contains upper Cholesky factor; - otherwise A contains a lower one. - U - array[N], rank-1 update to A: A_mod = A + u*u' - Exception is thrown if array size is too small. - BufR - possibly preallocated buffer; automatically resized if - needed. It is recommended to reuse this buffer if you - perform a lot of subsequent decompositions. - -OUTPUT PARAMETERS: - A - updated factorization. If IsUpper=True, then the upper - triangle contains matrix U, and the elements below the main - diagonal are not modified. Similarly, if IsUpper = False. - - -- ALGLIB -- - 03.02.2014 - Sergey Bochkanov -*************************************************************************/ -void spdmatrixcholeskyupdateadd1buf(const real_2d_array &a, const ae_int_t n, const bool isupper, const real_1d_array &u, real_1d_array &bufr, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spdmatrixcholeskyupdateadd1buf(const_cast(a.c_ptr()), n, isupper, const_cast(u.c_ptr()), const_cast(bufr.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Update of Cholesky decomposition: "fixing" some variables. "Buffered" -version which uses preallocated buffer which is saved between subsequent -function calls. - -See comments for SPDMatrixCholeskyUpdateFix() for more information. - -INPUT PARAMETERS: - A - upper or lower Cholesky factor. - array with elements [0..N-1, 0..N-1]. - Exception is thrown if array size is too small. - N - size of matrix A, N>0 - IsUpper - if IsUpper=True, then A contains upper Cholesky factor; - otherwise A contains a lower one. - Fix - array[N], I-th element is True if I-th variable must be - fixed. Exception is thrown if array size is too small. - BufR - possibly preallocated buffer; automatically resized if - needed. It is recommended to reuse this buffer if you - perform a lot of subsequent decompositions. - -OUTPUT PARAMETERS: - A - updated factorization. If IsUpper=True, then the upper - triangle contains matrix U, and the elements below the main - diagonal are not modified. Similarly, if IsUpper = False. - - -- ALGLIB -- - 03.02.2014 - Sergey Bochkanov -*************************************************************************/ -void spdmatrixcholeskyupdatefixbuf(const real_2d_array &a, const ae_int_t n, const bool isupper, const boolean_1d_array &fix, real_1d_array &bufr, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spdmatrixcholeskyupdatefixbuf(const_cast(a.c_ptr()), n, isupper, const_cast(fix.c_ptr()), const_cast(bufr.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Sparse LU decomposition with column pivoting for sparsity and row pivoting -for stability. Input must be square sparse matrix stored in CRS format. - -The algorithm computes LU decomposition of a general square matrix -(rectangular ones are not supported). The result of an algorithm is a -representation of A as A = P*L*U*Q, where: -* L is lower unitriangular matrix -* U is upper triangular matrix -* P = P0*P1*...*PK, K=N-1, Pi - permutation matrix for I and P[I] -* Q = QK*...*Q1*Q0, K=N-1, Qi - permutation matrix for I and Q[I] - -This function pivots columns for higher sparsity, and then pivots rows for -stability (larger element at the diagonal). - -INPUT PARAMETERS: - A - sparse NxN matrix in CRS format. An exception is generated - if matrix is non-CRS or non-square. - PivotType- pivoting strategy: - * 0 for best pivoting available (2 in current version) - * 1 for row-only pivoting (NOT RECOMMENDED) - * 2 for complete pivoting which produces most sparse outputs - -OUTPUT PARAMETERS: - A - the result of factorization, matrices L and U stored in - compact form using CRS sparse storage format: - * lower unitriangular L is stored strictly under main diagonal - * upper triangilar U is stored ON and ABOVE main diagonal - P - row permutation matrix in compact form, array[N] - Q - col permutation matrix in compact form, array[N] - -This function always succeeds, i.e. it ALWAYS returns valid factorization, -but for your convenience it also returns boolean value which helps to -detect symbolically degenerate matrices: -* function returns TRUE, if the matrix was factorized AND symbolically - non-degenerate -* function returns FALSE, if the matrix was factorized but U has strictly - zero elements at the diagonal (the factorization is returned anyway). - - - -- ALGLIB routine -- - 03.09.2018 - Bochkanov Sergey -*************************************************************************/ -bool sparselu(const sparsematrix &a, const ae_int_t pivottype, integer_1d_array &p, integer_1d_array &q, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::sparselu(const_cast(a.c_ptr()), pivottype, const_cast(p.c_ptr()), const_cast(q.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Sparse Cholesky decomposition for skyline matrixm using in-place algorithm -without allocating additional storage. - -The algorithm computes Cholesky decomposition of a symmetric positive- -definite sparse matrix. The result of an algorithm is a representation of -A as A=U^T*U or A=L*L^T - -This function allows to perform very efficient decomposition of low-profile -matrices (average bandwidth is ~5-10 elements). For larger matrices it is -recommended to use supernodal Cholesky decomposition: SparseCholeskyP() or -SparseCholeskyAnalyze()/SparseCholeskyFactorize(). - -INPUT PARAMETERS: - A - sparse matrix in skyline storage (SKS) format. - N - size of matrix A (can be smaller than actual size of A) - IsUpper - if IsUpper=True, then factorization is performed on upper - triangle. Another triangle is ignored (it may contant some - data, but it is not changed). - - -OUTPUT PARAMETERS: - A - the result of factorization, stored in SKS. If IsUpper=True, - then the upper triangle contains matrix U, such that - A = U^T*U. Lower triangle is not changed. - Similarly, if IsUpper = False. In this case L is returned, - and we have A = L*(L^T). - Note that THIS function does not perform permutation of - rows to reduce bandwidth. - -RESULT: - If the matrix is positive-definite, the function returns True. - Otherwise, the function returns False. Contents of A is not determined - in such case. - -NOTE: for performance reasons this function does NOT check that input - matrix includes only finite values. It is your responsibility to - make sure that there are no infinite or NAN values in the matrix. - - -- ALGLIB routine -- - 16.01.2014 - Bochkanov Sergey -*************************************************************************/ -bool sparsecholeskyskyline(const sparsematrix &a, const ae_int_t n, const bool isupper, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::sparsecholeskyskyline(const_cast(a.c_ptr()), n, isupper, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Sparse Cholesky decomposition for a matrix stored in any sparse storage, -without rows/cols permutation. - -This function is the most convenient (less parameters to specify), although -less efficient, version of sparse Cholesky. - -Internally it: -* calls SparseCholeskyAnalyze() function to perform symbolic analysis - phase with no permutation being configured. -* calls SparseCholeskyFactorize() function to perform numerical phase of - the factorization - -Following alternatives may result in better performance: -* using SparseCholeskyP(), which selects best pivoting available, which - almost always results in improved sparsity and cache locality -* using SparseCholeskyAnalyze() and SparseCholeskyFactorize() functions - directly, which may improve performance of repetitive factorizations - with same sparsity patterns. - -The latter also allows one to perform LDLT factorization of indefinite -matrix (one with strictly diagonal D, which is known to be stable only -in few special cases, like quasi-definite matrices). - -INPUT PARAMETERS: - A - a square NxN sparse matrix, stored in any storage format. - IsUpper - if IsUpper=True, then factorization is performed on upper - triangle. Another triangle is ignored on input, dropped - on output. Similarly, if IsUpper=False, the lower triangle - is processed. - -OUTPUT PARAMETERS: - A - the result of factorization, stored in CRS format: - * if IsUpper=True, then the upper triangle contains matrix - U such that A = U^T*U and the lower triangle is empty. - * similarly, if IsUpper=False, then lower triangular L is - returned and we have A = L*(L^T). - Note that THIS function does not perform permutation of - the rows to reduce fill-in. - -RESULT: - If the matrix is positive-definite, the function returns True. - Otherwise, the function returns False. Contents of A is undefined - in such case. - -NOTE: for performance reasons this function does NOT check that input - matrix includes only finite values. It is your responsibility to - make sure that there are no infinite or NAN values in the matrix. - - -- ALGLIB routine -- - 16.09.2020 - Bochkanov Sergey -*************************************************************************/ -bool sparsecholesky(const sparsematrix &a, const bool isupper, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::sparsecholesky(const_cast(a.c_ptr()), isupper, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Sparse Cholesky decomposition for a matrix stored in any sparse storage -format, with performance-enhancing permutation of rows/cols. - -Present version is configured to perform supernodal permutation which -sparsity reducing ordering. - -This function is a wrapper around generic sparse decomposition functions -that internally: -* calls SparseCholeskyAnalyze() function to perform symbolic analysis - phase with best available permutation being configured. -* calls SparseCholeskyFactorize() function to perform numerical phase of - the factorization. - -NOTE: using SparseCholeskyAnalyze() and SparseCholeskyFactorize() directly - may improve performance of repetitive factorizations with same - sparsity patterns. It also allows one to perform LDLT factorization - of indefinite matrix - a factorization with strictly diagonal D, - which is known to be stable only in few special cases, like quasi- - definite matrices. - -INPUT PARAMETERS: - A - a square NxN sparse matrix, stored in any storage format. - IsUpper - if IsUpper=True, then factorization is performed on upper - triangle. Another triangle is ignored on input, dropped - on output. Similarly, if IsUpper=False, the lower triangle - is processed. - -OUTPUT PARAMETERS: - A - the result of factorization, stored in CRS format: - * if IsUpper=True, then the upper triangle contains matrix - U such that A = U^T*U and the lower triangle is empty. - * similarly, if IsUpper=False, then lower triangular L is - returned and we have A = L*(L^T). - P - a row/column permutation, a product of P0*P1*...*Pk, k=N-1, - with Pi being permutation of rows/cols I and P[I] - -RESULT: - If the matrix is positive-definite, the function returns True. - Otherwise, the function returns False. Contents of A is undefined - in such case. - -NOTE: for performance reasons this function does NOT check that input - matrix includes only finite values. It is your responsibility to - make sure that there are no infinite or NAN values in the matrix. - - -- ALGLIB routine -- - 16.09.2020 - Bochkanov Sergey -*************************************************************************/ -bool sparsecholeskyp(const sparsematrix &a, const bool isupper, integer_1d_array &p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::sparsecholeskyp(const_cast(a.c_ptr()), isupper, const_cast(p.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Sparse Cholesky/LDLT decomposition: symbolic analysis phase. - -This function is a part of the 'expert' sparse Cholesky API: -* SparseCholeskyAnalyze(), that performs symbolic analysis phase and loads - matrix to be factorized into internal storage -* SparseCholeskySetModType(), that allows to use modified Cholesky/LDLT - with lower bounds on pivot magnitudes and additional overflow safeguards -* SparseCholeskyFactorize(), that performs numeric factorization using - precomputed symbolic analysis and internally stored matrix - and outputs - result -* SparseCholeskyReload(), that reloads one more matrix with same sparsity - pattern into internal storage so one may reuse previously allocated - temporaries and previously performed symbolic analysis - -This specific function performs preliminary analysis of the Cholesky/LDLT -factorization. It allows to choose different permutation types and to -choose between classic Cholesky and indefinite LDLT factorization (the -latter is computed with strictly diagonal D, i.e. without Bunch-Kauffman -pivoting). - -NOTE: L*D*LT family of factorization may be used to factorize indefinite - matrices. However, numerical stability is guaranteed ONLY for a class - of quasi-definite matrices. - -NOTE: all internal processing is performed with lower triangular matrices - stored in CRS format. Any other storage formats and/or upper - triangular storage means that one format conversion and/or one - transposition will be performed internally for the analysis and - factorization phases. Thus, highest performance is achieved when - input is a lower triangular CRS matrix. - -INPUT PARAMETERS: - A - sparse square matrix in any sparse storage format. - IsUpper - whether upper or lower triangle is decomposed (the - other one is ignored). - FactType - factorization type: - * 0 for traditional Cholesky of SPD matrix - * 1 for LDLT decomposition with strictly diagonal D, - which may have non-positive entries. - PermType - permutation type: - *-1 for absence of permutation - * 0 for best fill-in reducing permutation available - * 1 for supernodal ordering (improves locality and - performance, does NOT change fill-in factor) - * 2 for AMD (approximate minimum degree) ordering - -OUTPUT PARAMETERS: - Analysis - contains: - * symbolic analysis of the matrix structure which will - be used later to guide numerical factorization. - * specific numeric values loaded into internal memory - waiting for the factorization to be performed - -This function fails if and only if the matrix A is symbolically degenerate -i.e. has diagonal element which is exactly zero. In such case False is -returned, contents of Analysis object is undefined. - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -bool sparsecholeskyanalyze(const sparsematrix &a, const bool isupper, const ae_int_t facttype, const ae_int_t permtype, sparsedecompositionanalysis &analysis, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::sparsecholeskyanalyze(const_cast(a.c_ptr()), isupper, facttype, permtype, const_cast(analysis.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Sparse Cholesky decomposition: numerical analysis phase. - -This function is a part of the 'expert' sparse Cholesky API: -* SparseCholeskyAnalyze(), that performs symbolic analysis phase and loads - matrix to be factorized into internal storage -* SparseCholeskySetModType(), that allows to use modified Cholesky/LDLT - with lower bounds on pivot magnitudes and additional overflow safeguards -* SparseCholeskyFactorize(), that performs numeric factorization using - precomputed symbolic analysis and internally stored matrix - and outputs - result -* SparseCholeskyReload(), that reloads one more matrix with same sparsity - pattern into internal storage so one may reuse previously allocated - temporaries and previously performed symbolic analysis - -Depending on settings specified during SparseCholeskyAnalyze() call it may -produce classic Cholesky or L*D*LT decomposition (with strictly diagonal -D), without permutation or with performance-enhancing permutation P. - -NOTE: all internal processing is performed with lower triangular matrices - stored in CRS format. Any other storage formats and/or upper - triangular storage means that one format conversion and/or one - transposition will be performed internally for the analysis and - factorization phases. Thus, highest performance is achieved when - input is a lower triangular CRS matrix, and lower triangular output - is requested. - -NOTE: L*D*LT family of factorization may be used to factorize indefinite - matrices. However, numerical stability is guaranteed ONLY for a class - of quasi-definite matrices. - -INPUT PARAMETERS: - Analysis - prior analysis with internally stored matrix which will - be factorized - NeedUpper - whether upper triangular or lower triangular output is - needed - -OUTPUT PARAMETERS: - A - Cholesky decomposition of A stored in lower triangular - CRS format, i.e. A=L*L' (or upper triangular CRS, with - A=U'*U, depending on NeedUpper parameter). - D - array[N], diagonal factor. If no diagonal factor was - required during analysis phase, still returned but - filled with 1's - P - array[N], pivots. Permutation matrix P is a product of - P(0)*P(1)*...*P(N-1), where P(i) is a permutation of - row/col I and P[I] (with P[I]>=I). - If no permutation was requested during analysis phase, - still returned but filled with identity permutation. - -The function returns True when factorization resulted in nondegenerate -matrix. False is returned when factorization fails (Cholesky factorization -of indefinite matrix) or LDLT factorization has exactly zero elements at -the diagonal. In the latter case contents of A, D and P is undefined. - -The analysis object is not changed during the factorization. Subsequent -calls to SparseCholeskyFactorize() will result in same factorization being -performed one more time. - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -bool sparsecholeskyfactorize(const sparsedecompositionanalysis &analysis, const bool needupper, sparsematrix &a, real_1d_array &d, integer_1d_array &p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::sparsecholeskyfactorize(const_cast(analysis.c_ptr()), needupper, const_cast(a.c_ptr()), const_cast(d.c_ptr()), const_cast(p.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Sparse Cholesky decomposition: update internally stored matrix with -another one with exactly same sparsity pattern. - -This function is a part of the 'expert' sparse Cholesky API: -* SparseCholeskyAnalyze(), that performs symbolic analysis phase and loads - matrix to be factorized into internal storage -* SparseCholeskySetModType(), that allows to use modified Cholesky/LDLT - with lower bounds on pivot magnitudes and additional overflow safeguards -* SparseCholeskyFactorize(), that performs numeric factorization using - precomputed symbolic analysis and internally stored matrix - and outputs - result -* SparseCholeskyReload(), that reloads one more matrix with same sparsity - pattern into internal storage so one may reuse previously allocated - temporaries and previously performed symbolic analysis - -This specific function replaces internally stored numerical values with -ones from another sparse matrix (but having exactly same sparsity pattern -as one that was used for initial SparseCholeskyAnalyze() call). - -NOTE: all internal processing is performed with lower triangular matrices - stored in CRS format. Any other storage formats and/or upper - triangular storage means that one format conversion and/or one - transposition will be performed internally for the analysis and - factorization phases. Thus, highest performance is achieved when - input is a lower triangular CRS matrix. - -INPUT PARAMETERS: - Analysis - analysis object - A - sparse square matrix in any sparse storage format. It - MUST have exactly same sparsity pattern as that of the - matrix that was passed to SparseCholeskyAnalyze(). - Any difference (missing elements or additional elements) - may result in unpredictable and undefined behavior - - an algorithm may fail due to memory access violation. - IsUpper - whether upper or lower triangle is decomposed (the - other one is ignored). - -OUTPUT PARAMETERS: - Analysis - contains: - * symbolic analysis of the matrix structure which will - be used later to guide numerical factorization. - * specific numeric values loaded into internal memory - waiting for the factorization to be performed - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -void sparsecholeskyreload(const sparsedecompositionanalysis &analysis, const sparsematrix &a, const bool isupper, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsecholeskyreload(const_cast(analysis.c_ptr()), const_cast(a.c_ptr()), isupper, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_RCOND) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Estimate of a matrix condition number (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double rmatrixrcond1(const real_2d_array &a, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::rmatrixrcond1(const_cast(a.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Estimate of a matrix condition number (infinity-norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double rmatrixrcondinf(const real_2d_array &a, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::rmatrixrcondinf(const_cast(a.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Condition number estimate of a symmetric positive definite matrix. - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -It should be noted that 1-norm and inf-norm of condition numbers of symmetric -matrices are equal, so the algorithm doesn't take into account the -differences between these types of norms. - -Input parameters: - A - symmetric positive definite matrix which is given by its - upper or lower triangle depending on the value of - IsUpper. Array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - storage format. - -Result: - 1/LowerBound(cond(A)), if matrix A is positive definite, - -1, if matrix A is not positive definite, and its condition number - could not be found by this algorithm. - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double spdmatrixrcond(const real_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::spdmatrixrcond(const_cast(a.c_ptr()), n, isupper, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Triangular matrix: estimate of a condition number (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array[0..N-1, 0..N-1]. - N - size of A. - IsUpper - True, if the matrix is upper triangular. - IsUnit - True, if the matrix has a unit diagonal. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double rmatrixtrrcond1(const real_2d_array &a, const ae_int_t n, const bool isupper, const bool isunit, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::rmatrixtrrcond1(const_cast(a.c_ptr()), n, isupper, isunit, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Triangular matrix: estimate of a matrix condition number (infinity-norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - True, if the matrix is upper triangular. - IsUnit - True, if the matrix has a unit diagonal. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double rmatrixtrrcondinf(const real_2d_array &a, const ae_int_t n, const bool isupper, const bool isunit, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::rmatrixtrrcondinf(const_cast(a.c_ptr()), n, isupper, isunit, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Condition number estimate of a Hermitian positive definite matrix. - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -It should be noted that 1-norm and inf-norm of condition numbers of symmetric -matrices are equal, so the algorithm doesn't take into account the -differences between these types of norms. - -Input parameters: - A - Hermitian positive definite matrix which is given by its - upper or lower triangle depending on the value of - IsUpper. Array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - storage format. - -Result: - 1/LowerBound(cond(A)), if matrix A is positive definite, - -1, if matrix A is not positive definite, and its condition number - could not be found by this algorithm. - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double hpdmatrixrcond(const complex_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::hpdmatrixrcond(const_cast(a.c_ptr()), n, isupper, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Estimate of a matrix condition number (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double cmatrixrcond1(const complex_2d_array &a, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::cmatrixrcond1(const_cast(a.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Estimate of a matrix condition number (infinity-norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double cmatrixrcondinf(const complex_2d_array &a, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::cmatrixrcondinf(const_cast(a.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Estimate of the condition number of a matrix given by its LU decomposition (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - LUA - LU decomposition of a matrix in compact form. Output of - the RMatrixLU subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double rmatrixlurcond1(const real_2d_array &lua, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::rmatrixlurcond1(const_cast(lua.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Estimate of the condition number of a matrix given by its LU decomposition -(infinity norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - LUA - LU decomposition of a matrix in compact form. Output of - the RMatrixLU subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double rmatrixlurcondinf(const real_2d_array &lua, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::rmatrixlurcondinf(const_cast(lua.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Condition number estimate of a symmetric positive definite matrix given by -Cholesky decomposition. - -The algorithm calculates a lower bound of the condition number. In this -case, the algorithm does not return a lower bound of the condition number, -but an inverse number (to avoid an overflow in case of a singular matrix). - -It should be noted that 1-norm and inf-norm condition numbers of symmetric -matrices are equal, so the algorithm doesn't take into account the -differences between these types of norms. - -Input parameters: - CD - Cholesky decomposition of matrix A, - output of SMatrixCholesky subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double spdmatrixcholeskyrcond(const real_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::spdmatrixcholeskyrcond(const_cast(a.c_ptr()), n, isupper, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Condition number estimate of a Hermitian positive definite matrix given by -Cholesky decomposition. - -The algorithm calculates a lower bound of the condition number. In this -case, the algorithm does not return a lower bound of the condition number, -but an inverse number (to avoid an overflow in case of a singular matrix). - -It should be noted that 1-norm and inf-norm condition numbers of symmetric -matrices are equal, so the algorithm doesn't take into account the -differences between these types of norms. - -Input parameters: - CD - Cholesky decomposition of matrix A, - output of SMatrixCholesky subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double hpdmatrixcholeskyrcond(const complex_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::hpdmatrixcholeskyrcond(const_cast(a.c_ptr()), n, isupper, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Estimate of the condition number of a matrix given by its LU decomposition (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - LUA - LU decomposition of a matrix in compact form. Output of - the CMatrixLU subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double cmatrixlurcond1(const complex_2d_array &lua, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::cmatrixlurcond1(const_cast(lua.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Estimate of the condition number of a matrix given by its LU decomposition -(infinity norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - LUA - LU decomposition of a matrix in compact form. Output of - the CMatrixLU subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double cmatrixlurcondinf(const complex_2d_array &lua, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::cmatrixlurcondinf(const_cast(lua.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Triangular matrix: estimate of a condition number (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array[0..N-1, 0..N-1]. - N - size of A. - IsUpper - True, if the matrix is upper triangular. - IsUnit - True, if the matrix has a unit diagonal. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double cmatrixtrrcond1(const complex_2d_array &a, const ae_int_t n, const bool isupper, const bool isunit, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::cmatrixtrrcond1(const_cast(a.c_ptr()), n, isupper, isunit, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Triangular matrix: estimate of a matrix condition number (infinity-norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - True, if the matrix is upper triangular. - IsUnit - True, if the matrix has a unit diagonal. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double cmatrixtrrcondinf(const complex_2d_array &a, const ae_int_t n, const bool isupper, const bool isunit, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::cmatrixtrrcondinf(const_cast(a.c_ptr()), n, isupper, isunit, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_MATINV) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Matrix inverse report: -* R1 reciprocal of condition number in 1-norm -* RInf reciprocal of condition number in inf-norm -*************************************************************************/ -_matinvreport_owner::_matinvreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_matinvreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::matinvreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::matinvreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::matinvreport)); - alglib_impl::_matinvreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_matinvreport_owner::_matinvreport_owner(const _matinvreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_matinvreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: matinvreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::matinvreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::matinvreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::matinvreport)); - alglib_impl::_matinvreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_matinvreport_owner& _matinvreport_owner::operator=(const _matinvreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: matinvreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: matinvreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_matinvreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::matinvreport)); - alglib_impl::_matinvreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_matinvreport_owner::~_matinvreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_matinvreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::matinvreport* _matinvreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::matinvreport* _matinvreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -matinvreport::matinvreport() : _matinvreport_owner() ,r1(p_struct->r1),rinf(p_struct->rinf) -{ -} - -matinvreport::matinvreport(const matinvreport &rhs):_matinvreport_owner(rhs) ,r1(p_struct->r1),rinf(p_struct->rinf) -{ -} - -matinvreport& matinvreport::operator=(const matinvreport &rhs) -{ - if( this==&rhs ) - return *this; - _matinvreport_owner::operator=(rhs); - return *this; -} - -matinvreport::~matinvreport() -{ -} - -/************************************************************************* -Inversion of a matrix given by its LU decomposition. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - LU decomposition of the matrix - (output of RMatrixLU subroutine). - Pivots - table of permutations - (the output of RMatrixLU subroutine). - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - -OUTPUT PARAMETERS: - Info - return code: - * -3 A is singular, or VERY close to singular. - it is filled by zeros in such cases. - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - solver report, see below for more info - A - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - -SOLVER REPORT - -Subroutine sets following fields of the Rep structure: -* R1 reciprocal of condition number: 1/cond(A), 1-norm. -* RInf reciprocal of condition number: 1/cond(A), inf-norm. - - -- ALGLIB routine -- - 05.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixluinverse(real_2d_array &a, const integer_1d_array &pivots, const ae_int_t n, ae_int_t &info, matinvreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixluinverse(const_cast(a.c_ptr()), const_cast(pivots.c_ptr()), n, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Inversion of a matrix given by its LU decomposition. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - LU decomposition of the matrix - (output of RMatrixLU subroutine). - Pivots - table of permutations - (the output of RMatrixLU subroutine). - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - -OUTPUT PARAMETERS: - Info - return code: - * -3 A is singular, or VERY close to singular. - it is filled by zeros in such cases. - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - solver report, see below for more info - A - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - -SOLVER REPORT - -Subroutine sets following fields of the Rep structure: -* R1 reciprocal of condition number: 1/cond(A), 1-norm. -* RInf reciprocal of condition number: 1/cond(A), inf-norm. - - -- ALGLIB routine -- - 05.02.2010 - Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void rmatrixluinverse(real_2d_array &a, const integer_1d_array &pivots, ae_int_t &info, matinvreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (a.cols()!=a.rows()) || (a.cols()!=pivots.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'rmatrixluinverse': looks like one of arguments has wrong size"); - n = a.cols(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixluinverse(const_cast(a.c_ptr()), const_cast(pivots.c_ptr()), n, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Inversion of a general matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - -Result: - True, if the matrix is not singular. - False, if the matrix is singular. - - -- ALGLIB -- - Copyright 2005-2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixinverse(real_2d_array &a, const ae_int_t n, ae_int_t &info, matinvreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixinverse(const_cast(a.c_ptr()), n, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Inversion of a general matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - -Result: - True, if the matrix is not singular. - False, if the matrix is singular. - - -- ALGLIB -- - Copyright 2005-2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void rmatrixinverse(real_2d_array &a, ae_int_t &info, matinvreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (a.cols()!=a.rows())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'rmatrixinverse': looks like one of arguments has wrong size"); - n = a.cols(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixinverse(const_cast(a.c_ptr()), n, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Inversion of a matrix given by its LU decomposition. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - LU decomposition of the matrix - (output of CMatrixLU subroutine). - Pivots - table of permutations - (the output of CMatrixLU subroutine). - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - -OUTPUT PARAMETERS: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 05.02.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixluinverse(complex_2d_array &a, const integer_1d_array &pivots, const ae_int_t n, ae_int_t &info, matinvreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixluinverse(const_cast(a.c_ptr()), const_cast(pivots.c_ptr()), n, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Inversion of a matrix given by its LU decomposition. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - LU decomposition of the matrix - (output of CMatrixLU subroutine). - Pivots - table of permutations - (the output of CMatrixLU subroutine). - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - -OUTPUT PARAMETERS: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 05.02.2010 - Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void cmatrixluinverse(complex_2d_array &a, const integer_1d_array &pivots, ae_int_t &info, matinvreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (a.cols()!=a.rows()) || (a.cols()!=pivots.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'cmatrixluinverse': looks like one of arguments has wrong size"); - n = a.cols(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixluinverse(const_cast(a.c_ptr()), const_cast(pivots.c_ptr()), n, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Inversion of a general matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -void cmatrixinverse(complex_2d_array &a, const ae_int_t n, ae_int_t &info, matinvreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixinverse(const_cast(a.c_ptr()), n, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Inversion of a general matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void cmatrixinverse(complex_2d_array &a, ae_int_t &info, matinvreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (a.cols()!=a.rows())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'cmatrixinverse': looks like one of arguments has wrong size"); - n = a.cols(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixinverse(const_cast(a.c_ptr()), n, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Inversion of a symmetric positive definite matrix which is given -by Cholesky decomposition. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - Cholesky decomposition of the matrix to be inverted: - A=U'*U or A = L*L'. - Output of SPDMatrixCholesky subroutine. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - storage type (optional): - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, lower half is used. - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 10.02.2010 - Bochkanov Sergey -*************************************************************************/ -void spdmatrixcholeskyinverse(real_2d_array &a, const ae_int_t n, const bool isupper, ae_int_t &info, matinvreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spdmatrixcholeskyinverse(const_cast(a.c_ptr()), n, isupper, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Inversion of a symmetric positive definite matrix which is given -by Cholesky decomposition. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - Cholesky decomposition of the matrix to be inverted: - A=U'*U or A = L*L'. - Output of SPDMatrixCholesky subroutine. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - storage type (optional): - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, lower half is used. - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 10.02.2010 - Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spdmatrixcholeskyinverse(real_2d_array &a, ae_int_t &info, matinvreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - bool isupper; - if( (a.cols()!=a.rows())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spdmatrixcholeskyinverse': looks like one of arguments has wrong size"); - n = a.cols(); - isupper = false; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spdmatrixcholeskyinverse(const_cast(a.c_ptr()), n, isupper, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Inversion of a symmetric positive definite matrix. - -Given an upper or lower triangle of a symmetric positive definite matrix, -the algorithm generates matrix A^-1 and saves the upper or lower triangle -depending on the input. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix to be inverted (upper or lower triangle). - Array with elements [0..N-1,0..N-1]. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - storage type (optional): - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, both lower and upper triangles must be - filled. - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 10.02.2010 - Bochkanov Sergey -*************************************************************************/ -void spdmatrixinverse(real_2d_array &a, const ae_int_t n, const bool isupper, ae_int_t &info, matinvreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spdmatrixinverse(const_cast(a.c_ptr()), n, isupper, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Inversion of a symmetric positive definite matrix. - -Given an upper or lower triangle of a symmetric positive definite matrix, -the algorithm generates matrix A^-1 and saves the upper or lower triangle -depending on the input. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix to be inverted (upper or lower triangle). - Array with elements [0..N-1,0..N-1]. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - storage type (optional): - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, both lower and upper triangles must be - filled. - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 10.02.2010 - Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spdmatrixinverse(real_2d_array &a, ae_int_t &info, matinvreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - bool isupper; - if( (a.cols()!=a.rows())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spdmatrixinverse': looks like one of arguments has wrong size"); - if( !alglib_impl::ae_is_symmetric(const_cast(a.c_ptr())) ) - _ALGLIB_CPP_EXCEPTION("'a' parameter is not symmetric matrix"); - n = a.cols(); - isupper = false; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spdmatrixinverse(const_cast(a.c_ptr()), n, isupper, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - if( !alglib_impl::ae_force_symmetric(const_cast(a.c_ptr())) ) - _ALGLIB_CPP_EXCEPTION("Internal error while forcing symmetricity of 'a' parameter"); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Inversion of a Hermitian positive definite matrix which is given -by Cholesky decomposition. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - Cholesky decomposition of the matrix to be inverted: - A=U'*U or A = L*L'. - Output of HPDMatrixCholesky subroutine. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - storage type (optional): - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, lower half is used. - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 10.02.2010 - Bochkanov Sergey -*************************************************************************/ -void hpdmatrixcholeskyinverse(complex_2d_array &a, const ae_int_t n, const bool isupper, ae_int_t &info, matinvreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hpdmatrixcholeskyinverse(const_cast(a.c_ptr()), n, isupper, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Inversion of a Hermitian positive definite matrix which is given -by Cholesky decomposition. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - Cholesky decomposition of the matrix to be inverted: - A=U'*U or A = L*L'. - Output of HPDMatrixCholesky subroutine. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - storage type (optional): - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, lower half is used. - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 10.02.2010 - Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void hpdmatrixcholeskyinverse(complex_2d_array &a, ae_int_t &info, matinvreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - bool isupper; - if( (a.cols()!=a.rows())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'hpdmatrixcholeskyinverse': looks like one of arguments has wrong size"); - n = a.cols(); - isupper = false; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hpdmatrixcholeskyinverse(const_cast(a.c_ptr()), n, isupper, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Inversion of a Hermitian positive definite matrix. - -Given an upper or lower triangle of a Hermitian positive definite matrix, -the algorithm generates matrix A^-1 and saves the upper or lower triangle -depending on the input. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix to be inverted (upper or lower triangle). - Array with elements [0..N-1,0..N-1]. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - storage type (optional): - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, both lower and upper triangles must be - filled. - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 10.02.2010 - Bochkanov Sergey -*************************************************************************/ -void hpdmatrixinverse(complex_2d_array &a, const ae_int_t n, const bool isupper, ae_int_t &info, matinvreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hpdmatrixinverse(const_cast(a.c_ptr()), n, isupper, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Inversion of a Hermitian positive definite matrix. - -Given an upper or lower triangle of a Hermitian positive definite matrix, -the algorithm generates matrix A^-1 and saves the upper or lower triangle -depending on the input. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix to be inverted (upper or lower triangle). - Array with elements [0..N-1,0..N-1]. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - storage type (optional): - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, both lower and upper triangles must be - filled. - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 10.02.2010 - Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void hpdmatrixinverse(complex_2d_array &a, ae_int_t &info, matinvreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - bool isupper; - if( (a.cols()!=a.rows())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'hpdmatrixinverse': looks like one of arguments has wrong size"); - if( !alglib_impl::ae_is_hermitian(const_cast(a.c_ptr())) ) - _ALGLIB_CPP_EXCEPTION("'a' parameter is not Hermitian matrix"); - n = a.cols(); - isupper = false; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hpdmatrixinverse(const_cast(a.c_ptr()), n, isupper, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - if( !alglib_impl::ae_force_hermitian(const_cast(a.c_ptr())) ) - _ALGLIB_CPP_EXCEPTION("Internal error while forcing Hermitian properties of 'a' parameter"); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Triangular matrix inverse (real) - -The subroutine inverts the following types of matrices: - * upper triangular - * upper triangular with unit diagonal - * lower triangular - * lower triangular with unit diagonal - -In case of an upper (lower) triangular matrix, the inverse matrix will -also be upper (lower) triangular, and after the end of the algorithm, the -inverse matrix replaces the source matrix. The elements below (above) the -main diagonal are not changed by the algorithm. - -If the matrix has a unit diagonal, the inverse matrix also has a unit -diagonal, and the diagonal elements are not passed to the algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix, array[0..N-1, 0..N-1]. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - True, if the matrix is upper triangular. - IsUnit - diagonal type (optional): - * if True, matrix has unit diagonal (a[i,i] are NOT used) - * if False, matrix diagonal is arbitrary - * if not given, False is assumed - -Output parameters: - Info - same as for RMatrixLUInverse - Rep - same as for RMatrixLUInverse - A - same as for RMatrixLUInverse. - - -- ALGLIB -- - Copyright 05.02.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixtrinverse(real_2d_array &a, const ae_int_t n, const bool isupper, const bool isunit, ae_int_t &info, matinvreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixtrinverse(const_cast(a.c_ptr()), n, isupper, isunit, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Triangular matrix inverse (real) - -The subroutine inverts the following types of matrices: - * upper triangular - * upper triangular with unit diagonal - * lower triangular - * lower triangular with unit diagonal - -In case of an upper (lower) triangular matrix, the inverse matrix will -also be upper (lower) triangular, and after the end of the algorithm, the -inverse matrix replaces the source matrix. The elements below (above) the -main diagonal are not changed by the algorithm. - -If the matrix has a unit diagonal, the inverse matrix also has a unit -diagonal, and the diagonal elements are not passed to the algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix, array[0..N-1, 0..N-1]. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - True, if the matrix is upper triangular. - IsUnit - diagonal type (optional): - * if True, matrix has unit diagonal (a[i,i] are NOT used) - * if False, matrix diagonal is arbitrary - * if not given, False is assumed - -Output parameters: - Info - same as for RMatrixLUInverse - Rep - same as for RMatrixLUInverse - A - same as for RMatrixLUInverse. - - -- ALGLIB -- - Copyright 05.02.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void rmatrixtrinverse(real_2d_array &a, const bool isupper, ae_int_t &info, matinvreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - bool isunit; - if( (a.cols()!=a.rows())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'rmatrixtrinverse': looks like one of arguments has wrong size"); - n = a.cols(); - isunit = false; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixtrinverse(const_cast(a.c_ptr()), n, isupper, isunit, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Triangular matrix inverse (complex) - -The subroutine inverts the following types of matrices: - * upper triangular - * upper triangular with unit diagonal - * lower triangular - * lower triangular with unit diagonal - -In case of an upper (lower) triangular matrix, the inverse matrix will -also be upper (lower) triangular, and after the end of the algorithm, the -inverse matrix replaces the source matrix. The elements below (above) the -main diagonal are not changed by the algorithm. - -If the matrix has a unit diagonal, the inverse matrix also has a unit -diagonal, and the diagonal elements are not passed to the algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix, array[0..N-1, 0..N-1]. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - True, if the matrix is upper triangular. - IsUnit - diagonal type (optional): - * if True, matrix has unit diagonal (a[i,i] are NOT used) - * if False, matrix diagonal is arbitrary - * if not given, False is assumed - -Output parameters: - Info - same as for RMatrixLUInverse - Rep - same as for RMatrixLUInverse - A - same as for RMatrixLUInverse. - - -- ALGLIB -- - Copyright 05.02.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixtrinverse(complex_2d_array &a, const ae_int_t n, const bool isupper, const bool isunit, ae_int_t &info, matinvreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixtrinverse(const_cast(a.c_ptr()), n, isupper, isunit, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Triangular matrix inverse (complex) - -The subroutine inverts the following types of matrices: - * upper triangular - * upper triangular with unit diagonal - * lower triangular - * lower triangular with unit diagonal - -In case of an upper (lower) triangular matrix, the inverse matrix will -also be upper (lower) triangular, and after the end of the algorithm, the -inverse matrix replaces the source matrix. The elements below (above) the -main diagonal are not changed by the algorithm. - -If the matrix has a unit diagonal, the inverse matrix also has a unit -diagonal, and the diagonal elements are not passed to the algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix, array[0..N-1, 0..N-1]. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - True, if the matrix is upper triangular. - IsUnit - diagonal type (optional): - * if True, matrix has unit diagonal (a[i,i] are NOT used) - * if False, matrix diagonal is arbitrary - * if not given, False is assumed - -Output parameters: - Info - same as for RMatrixLUInverse - Rep - same as for RMatrixLUInverse - A - same as for RMatrixLUInverse. - - -- ALGLIB -- - Copyright 05.02.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void cmatrixtrinverse(complex_2d_array &a, const bool isupper, ae_int_t &info, matinvreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - bool isunit; - if( (a.cols()!=a.rows())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'cmatrixtrinverse': looks like one of arguments has wrong size"); - n = a.cols(); - isunit = false; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixtrinverse(const_cast(a.c_ptr()), n, isupper, isunit, &info, const_cast(rep.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif -#endif - -#if defined(AE_COMPILE_ORTFAC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -QR decomposition of a rectangular matrix of size MxN - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix A whose indexes range within [0..M-1, 0..N-1]. - M - number of rows in matrix A. - N - number of columns in matrix A. - -Output parameters: - A - matrices Q and R in compact form (see below). - Tau - array of scalar factors which are used to form - matrix Q. Array whose index ranges within [0.. Min(M-1,N-1)]. - -Matrix A is represented as A = QR, where Q is an orthogonal matrix of size -MxM, R - upper triangular (or upper trapezoid) matrix of size M x N. - -The elements of matrix R are located on and above the main diagonal of -matrix A. The elements which are located in Tau array and below the main -diagonal of matrix A are used to form matrix Q as follows: - -Matrix Q is represented as a product of elementary reflections - -Q = H(0)*H(2)*...*H(k-1), - -where k = min(m,n), and each H(i) is in the form - -H(i) = 1 - tau * v * (v^T) - -where tau is a scalar stored in Tau[I]; v - real vector, -so that v(0:i-1) = 0, v(i) = 1, v(i+1:m-1) stored in A(i+1:m-1,i). - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixqr(real_2d_array &a, const ae_int_t m, const ae_int_t n, real_1d_array &tau, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixqr(const_cast(a.c_ptr()), m, n, const_cast(tau.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -LQ decomposition of a rectangular matrix of size MxN - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix A whose indexes range within [0..M-1, 0..N-1]. - M - number of rows in matrix A. - N - number of columns in matrix A. - -Output parameters: - A - matrices L and Q in compact form (see below) - Tau - array of scalar factors which are used to form - matrix Q. Array whose index ranges within [0..Min(M,N)-1]. - -Matrix A is represented as A = LQ, where Q is an orthogonal matrix of size -MxM, L - lower triangular (or lower trapezoid) matrix of size M x N. - -The elements of matrix L are located on and below the main diagonal of -matrix A. The elements which are located in Tau array and above the main -diagonal of matrix A are used to form matrix Q as follows: - -Matrix Q is represented as a product of elementary reflections - -Q = H(k-1)*H(k-2)*...*H(1)*H(0), - -where k = min(m,n), and each H(i) is of the form - -H(i) = 1 - tau * v * (v^T) - -where tau is a scalar stored in Tau[I]; v - real vector, so that v(0:i-1)=0, -v(i) = 1, v(i+1:n-1) stored in A(i,i+1:n-1). - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixlq(real_2d_array &a, const ae_int_t m, const ae_int_t n, real_1d_array &tau, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixlq(const_cast(a.c_ptr()), m, n, const_cast(tau.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -QR decomposition of a rectangular complex matrix of size MxN - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix A whose indexes range within [0..M-1, 0..N-1] - M - number of rows in matrix A. - N - number of columns in matrix A. - -Output parameters: - A - matrices Q and R in compact form - Tau - array of scalar factors which are used to form matrix Q. Array - whose indexes range within [0.. Min(M,N)-1] - -Matrix A is represented as A = QR, where Q is an orthogonal matrix of size -MxM, R - upper triangular (or upper trapezoid) matrix of size MxN. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994 -*************************************************************************/ -void cmatrixqr(complex_2d_array &a, const ae_int_t m, const ae_int_t n, complex_1d_array &tau, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixqr(const_cast(a.c_ptr()), m, n, const_cast(tau.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -LQ decomposition of a rectangular complex matrix of size MxN - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix A whose indexes range within [0..M-1, 0..N-1] - M - number of rows in matrix A. - N - number of columns in matrix A. - -Output parameters: - A - matrices Q and L in compact form - Tau - array of scalar factors which are used to form matrix Q. Array - whose indexes range within [0.. Min(M,N)-1] - -Matrix A is represented as A = LQ, where Q is an orthogonal matrix of size -MxM, L - lower triangular (or lower trapezoid) matrix of size MxN. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994 -*************************************************************************/ -void cmatrixlq(complex_2d_array &a, const ae_int_t m, const ae_int_t n, complex_1d_array &tau, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixlq(const_cast(a.c_ptr()), m, n, const_cast(tau.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Partial unpacking of matrix Q from the QR decomposition of a matrix A - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrices Q and R in compact form. - Output of RMatrixQR subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - Tau - scalar factors which are used to form Q. - Output of the RMatrixQR subroutine. - QColumns - required number of columns of matrix Q. M>=QColumns>=0. - -Output parameters: - Q - first QColumns columns of matrix Q. - Array whose indexes range within [0..M-1, 0..QColumns-1]. - If QColumns=0, the array remains unchanged. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixqrunpackq(const real_2d_array &a, const ae_int_t m, const ae_int_t n, const real_1d_array &tau, const ae_int_t qcolumns, real_2d_array &q, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixqrunpackq(const_cast(a.c_ptr()), m, n, const_cast(tau.c_ptr()), qcolumns, const_cast(q.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Unpacking of matrix R from the QR decomposition of a matrix A - -Input parameters: - A - matrices Q and R in compact form. - Output of RMatrixQR subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - -Output parameters: - R - matrix R, array[0..M-1, 0..N-1]. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixqrunpackr(const real_2d_array &a, const ae_int_t m, const ae_int_t n, real_2d_array &r, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixqrunpackr(const_cast(a.c_ptr()), m, n, const_cast(r.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Partial unpacking of matrix Q from the LQ decomposition of a matrix A - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrices L and Q in compact form. - Output of RMatrixLQ subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - Tau - scalar factors which are used to form Q. - Output of the RMatrixLQ subroutine. - QRows - required number of rows in matrix Q. N>=QRows>=0. - -Output parameters: - Q - first QRows rows of matrix Q. Array whose indexes range - within [0..QRows-1, 0..N-1]. If QRows=0, the array remains - unchanged. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixlqunpackq(const real_2d_array &a, const ae_int_t m, const ae_int_t n, const real_1d_array &tau, const ae_int_t qrows, real_2d_array &q, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixlqunpackq(const_cast(a.c_ptr()), m, n, const_cast(tau.c_ptr()), qrows, const_cast(q.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Unpacking of matrix L from the LQ decomposition of a matrix A - -Input parameters: - A - matrices Q and L in compact form. - Output of RMatrixLQ subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - -Output parameters: - L - matrix L, array[0..M-1, 0..N-1]. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixlqunpackl(const real_2d_array &a, const ae_int_t m, const ae_int_t n, real_2d_array &l, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixlqunpackl(const_cast(a.c_ptr()), m, n, const_cast(l.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Partial unpacking of matrix Q from QR decomposition of a complex matrix A. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrices Q and R in compact form. - Output of CMatrixQR subroutine . - M - number of rows in matrix A. M>=0. - N - number of columns in matrix A. N>=0. - Tau - scalar factors which are used to form Q. - Output of CMatrixQR subroutine . - QColumns - required number of columns in matrix Q. M>=QColumns>=0. - -Output parameters: - Q - first QColumns columns of matrix Q. - Array whose index ranges within [0..M-1, 0..QColumns-1]. - If QColumns=0, array isn't changed. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixqrunpackq(const complex_2d_array &a, const ae_int_t m, const ae_int_t n, const complex_1d_array &tau, const ae_int_t qcolumns, complex_2d_array &q, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixqrunpackq(const_cast(a.c_ptr()), m, n, const_cast(tau.c_ptr()), qcolumns, const_cast(q.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Unpacking of matrix R from the QR decomposition of a matrix A - -Input parameters: - A - matrices Q and R in compact form. - Output of CMatrixQR subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - -Output parameters: - R - matrix R, array[0..M-1, 0..N-1]. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixqrunpackr(const complex_2d_array &a, const ae_int_t m, const ae_int_t n, complex_2d_array &r, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixqrunpackr(const_cast(a.c_ptr()), m, n, const_cast(r.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Partial unpacking of matrix Q from LQ decomposition of a complex matrix A. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrices Q and R in compact form. - Output of CMatrixLQ subroutine . - M - number of rows in matrix A. M>=0. - N - number of columns in matrix A. N>=0. - Tau - scalar factors which are used to form Q. - Output of CMatrixLQ subroutine . - QRows - required number of rows in matrix Q. N>=QColumns>=0. - -Output parameters: - Q - first QRows rows of matrix Q. - Array whose index ranges within [0..QRows-1, 0..N-1]. - If QRows=0, array isn't changed. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixlqunpackq(const complex_2d_array &a, const ae_int_t m, const ae_int_t n, const complex_1d_array &tau, const ae_int_t qrows, complex_2d_array &q, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixlqunpackq(const_cast(a.c_ptr()), m, n, const_cast(tau.c_ptr()), qrows, const_cast(q.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Unpacking of matrix L from the LQ decomposition of a matrix A - -Input parameters: - A - matrices Q and L in compact form. - Output of CMatrixLQ subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - -Output parameters: - L - matrix L, array[0..M-1, 0..N-1]. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixlqunpackl(const complex_2d_array &a, const ae_int_t m, const ae_int_t n, complex_2d_array &l, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixlqunpackl(const_cast(a.c_ptr()), m, n, const_cast(l.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Reduction of a rectangular matrix to bidiagonal form - -The algorithm reduces the rectangular matrix A to bidiagonal form by -orthogonal transformations P and Q: A = Q*B*(P^T). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - source matrix. array[0..M-1, 0..N-1] - M - number of rows in matrix A. - N - number of columns in matrix A. - -Output parameters: - A - matrices Q, B, P in compact form (see below). - TauQ - scalar factors which are used to form matrix Q. - TauP - scalar factors which are used to form matrix P. - -The main diagonal and one of the secondary diagonals of matrix A are -replaced with bidiagonal matrix B. Other elements contain elementary -reflections which form MxM matrix Q and NxN matrix P, respectively. - -If M>=N, B is the upper bidiagonal MxN matrix and is stored in the -corresponding elements of matrix A. Matrix Q is represented as a -product of elementary reflections Q = H(0)*H(1)*...*H(n-1), where -H(i) = 1-tau*v*v'. Here tau is a scalar which is stored in TauQ[i], and -vector v has the following structure: v(0:i-1)=0, v(i)=1, v(i+1:m-1) is -stored in elements A(i+1:m-1,i). Matrix P is as follows: P = -G(0)*G(1)*...*G(n-2), where G(i) = 1 - tau*u*u'. Tau is stored in TauP[i], -u(0:i)=0, u(i+1)=1, u(i+2:n-1) is stored in elements A(i,i+2:n-1). - -If M n): m=5, n=6 (m < n): - -( d e u1 u1 u1 ) ( d u1 u1 u1 u1 u1 ) -( v1 d e u2 u2 ) ( e d u2 u2 u2 u2 ) -( v1 v2 d e u3 ) ( v1 e d u3 u3 u3 ) -( v1 v2 v3 d e ) ( v1 v2 e d u4 u4 ) -( v1 v2 v3 v4 d ) ( v1 v2 v3 e d u5 ) -( v1 v2 v3 v4 v5 ) - -Here vi and ui are vectors which form H(i) and G(i), and d and e - -are the diagonal and off-diagonal elements of matrix B. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994. - Sergey Bochkanov, ALGLIB project, translation from FORTRAN to - pseudocode, 2007-2010. -*************************************************************************/ -void rmatrixbd(real_2d_array &a, const ae_int_t m, const ae_int_t n, real_1d_array &tauq, real_1d_array &taup, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixbd(const_cast(a.c_ptr()), m, n, const_cast(tauq.c_ptr()), const_cast(taup.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Unpacking matrix Q which reduces a matrix to bidiagonal form. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - QP - matrices Q and P in compact form. - Output of ToBidiagonal subroutine. - M - number of rows in matrix A. - N - number of columns in matrix A. - TAUQ - scalar factors which are used to form Q. - Output of ToBidiagonal subroutine. - QColumns - required number of columns in matrix Q. - M>=QColumns>=0. - -Output parameters: - Q - first QColumns columns of matrix Q. - Array[0..M-1, 0..QColumns-1] - If QColumns=0, the array is not modified. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixbdunpackq(const real_2d_array &qp, const ae_int_t m, const ae_int_t n, const real_1d_array &tauq, const ae_int_t qcolumns, real_2d_array &q, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixbdunpackq(const_cast(qp.c_ptr()), m, n, const_cast(tauq.c_ptr()), qcolumns, const_cast(q.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Multiplication by matrix Q which reduces matrix A to bidiagonal form. - -The algorithm allows pre- or post-multiply by Q or Q'. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - QP - matrices Q and P in compact form. - Output of ToBidiagonal subroutine. - M - number of rows in matrix A. - N - number of columns in matrix A. - TAUQ - scalar factors which are used to form Q. - Output of ToBidiagonal subroutine. - Z - multiplied matrix. - array[0..ZRows-1,0..ZColumns-1] - ZRows - number of rows in matrix Z. If FromTheRight=False, - ZRows=M, otherwise ZRows can be arbitrary. - ZColumns - number of columns in matrix Z. If FromTheRight=True, - ZColumns=M, otherwise ZColumns can be arbitrary. - FromTheRight - pre- or post-multiply. - DoTranspose - multiply by Q or Q'. - -Output parameters: - Z - product of Z and Q. - Array[0..ZRows-1,0..ZColumns-1] - If ZRows=0 or ZColumns=0, the array is not modified. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixbdmultiplybyq(const real_2d_array &qp, const ae_int_t m, const ae_int_t n, const real_1d_array &tauq, real_2d_array &z, const ae_int_t zrows, const ae_int_t zcolumns, const bool fromtheright, const bool dotranspose, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixbdmultiplybyq(const_cast(qp.c_ptr()), m, n, const_cast(tauq.c_ptr()), const_cast(z.c_ptr()), zrows, zcolumns, fromtheright, dotranspose, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Unpacking matrix P which reduces matrix A to bidiagonal form. -The subroutine returns transposed matrix P. - -Input parameters: - QP - matrices Q and P in compact form. - Output of ToBidiagonal subroutine. - M - number of rows in matrix A. - N - number of columns in matrix A. - TAUP - scalar factors which are used to form P. - Output of ToBidiagonal subroutine. - PTRows - required number of rows of matrix P^T. N >= PTRows >= 0. - -Output parameters: - PT - first PTRows columns of matrix P^T - Array[0..PTRows-1, 0..N-1] - If PTRows=0, the array is not modified. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixbdunpackpt(const real_2d_array &qp, const ae_int_t m, const ae_int_t n, const real_1d_array &taup, const ae_int_t ptrows, real_2d_array &pt, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixbdunpackpt(const_cast(qp.c_ptr()), m, n, const_cast(taup.c_ptr()), ptrows, const_cast(pt.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Multiplication by matrix P which reduces matrix A to bidiagonal form. - -The algorithm allows pre- or post-multiply by P or P'. - -Input parameters: - QP - matrices Q and P in compact form. - Output of RMatrixBD subroutine. - M - number of rows in matrix A. - N - number of columns in matrix A. - TAUP - scalar factors which are used to form P. - Output of RMatrixBD subroutine. - Z - multiplied matrix. - Array whose indexes range within [0..ZRows-1,0..ZColumns-1]. - ZRows - number of rows in matrix Z. If FromTheRight=False, - ZRows=N, otherwise ZRows can be arbitrary. - ZColumns - number of columns in matrix Z. If FromTheRight=True, - ZColumns=N, otherwise ZColumns can be arbitrary. - FromTheRight - pre- or post-multiply. - DoTranspose - multiply by P or P'. - -Output parameters: - Z - product of Z and P. - Array whose indexes range within [0..ZRows-1,0..ZColumns-1]. - If ZRows=0 or ZColumns=0, the array is not modified. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixbdmultiplybyp(const real_2d_array &qp, const ae_int_t m, const ae_int_t n, const real_1d_array &taup, real_2d_array &z, const ae_int_t zrows, const ae_int_t zcolumns, const bool fromtheright, const bool dotranspose, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixbdmultiplybyp(const_cast(qp.c_ptr()), m, n, const_cast(taup.c_ptr()), const_cast(z.c_ptr()), zrows, zcolumns, fromtheright, dotranspose, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Unpacking of the main and secondary diagonals of bidiagonal decomposition -of matrix A. - -Input parameters: - B - output of RMatrixBD subroutine. - M - number of rows in matrix B. - N - number of columns in matrix B. - -Output parameters: - IsUpper - True, if the matrix is upper bidiagonal. - otherwise IsUpper is False. - D - the main diagonal. - Array whose index ranges within [0..Min(M,N)-1]. - E - the secondary diagonal (upper or lower, depending on - the value of IsUpper). - Array index ranges within [0..Min(M,N)-1], the last - element is not used. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixbdunpackdiagonals(const real_2d_array &b, const ae_int_t m, const ae_int_t n, bool &isupper, real_1d_array &d, real_1d_array &e, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixbdunpackdiagonals(const_cast(b.c_ptr()), m, n, &isupper, const_cast(d.c_ptr()), const_cast(e.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Reduction of a square matrix to upper Hessenberg form: Q'*A*Q = H, -where Q is an orthogonal matrix, H - Hessenberg matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix A with elements [0..N-1, 0..N-1] - N - size of matrix A. - -Output parameters: - A - matrices Q and P in compact form (see below). - Tau - array of scalar factors which are used to form matrix Q. - Array whose index ranges within [0..N-2] - -Matrix H is located on the main diagonal, on the lower secondary diagonal -and above the main diagonal of matrix A. The elements which are used to -form matrix Q are situated in array Tau and below the lower secondary -diagonal of matrix A as follows: - -Matrix Q is represented as a product of elementary reflections - -Q = H(0)*H(2)*...*H(n-2), - -where each H(i) is given by - -H(i) = 1 - tau * v * (v^T) - -where tau is a scalar stored in Tau[I]; v - is a real vector, -so that v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) stored in A(i+2:n-1,i). - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - October 31, 1992 -*************************************************************************/ -void rmatrixhessenberg(real_2d_array &a, const ae_int_t n, real_1d_array &tau, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixhessenberg(const_cast(a.c_ptr()), n, const_cast(tau.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Unpacking matrix Q which reduces matrix A to upper Hessenberg form - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - output of RMatrixHessenberg subroutine. - N - size of matrix A. - Tau - scalar factors which are used to form Q. - Output of RMatrixHessenberg subroutine. - -Output parameters: - Q - matrix Q. - Array whose indexes range within [0..N-1, 0..N-1]. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixhessenbergunpackq(const real_2d_array &a, const ae_int_t n, const real_1d_array &tau, real_2d_array &q, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixhessenbergunpackq(const_cast(a.c_ptr()), n, const_cast(tau.c_ptr()), const_cast(q.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Unpacking matrix H (the result of matrix A reduction to upper Hessenberg form) - -Input parameters: - A - output of RMatrixHessenberg subroutine. - N - size of matrix A. - -Output parameters: - H - matrix H. Array whose indexes range within [0..N-1, 0..N-1]. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixhessenbergunpackh(const real_2d_array &a, const ae_int_t n, real_2d_array &h, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixhessenbergunpackh(const_cast(a.c_ptr()), n, const_cast(h.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Reduction of a symmetric matrix which is given by its higher or lower -triangular part to a tridiagonal matrix using orthogonal similarity -transformation: Q'*A*Q=T. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix to be transformed - array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - storage format. If IsUpper = True, then matrix A is given - by its upper triangle, and the lower triangle is not used - and not modified by the algorithm, and vice versa - if IsUpper = False. - -Output parameters: - A - matrices T and Q in compact form (see lower) - Tau - array of factors which are forming matrices H(i) - array with elements [0..N-2]. - D - main diagonal of symmetric matrix T. - array with elements [0..N-1]. - E - secondary diagonal of symmetric matrix T. - array with elements [0..N-2]. - - - If IsUpper=True, the matrix Q is represented as a product of elementary - reflectors - - Q = H(n-2) . . . H(2) H(0). - - Each H(i) has the form - - H(i) = I - tau * v * v' - - where tau is a real scalar, and v is a real vector with - v(i+1:n-1) = 0, v(i) = 1, v(0:i-1) is stored on exit in - A(0:i-1,i+1), and tau in TAU(i). - - If IsUpper=False, the matrix Q is represented as a product of elementary - reflectors - - Q = H(0) H(2) . . . H(n-2). - - Each H(i) has the form - - H(i) = I - tau * v * v' - - where tau is a real scalar, and v is a real vector with - v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) is stored on exit in A(i+2:n-1,i), - and tau in TAU(i). - - The contents of A on exit are illustrated by the following examples - with n = 5: - - if UPLO = 'U': if UPLO = 'L': - - ( d e v1 v2 v3 ) ( d ) - ( d e v2 v3 ) ( e d ) - ( d e v3 ) ( v0 e d ) - ( d e ) ( v0 v1 e d ) - ( d ) ( v0 v1 v2 e d ) - - where d and e denote diagonal and off-diagonal elements of T, and vi - denotes an element of the vector defining H(i). - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - October 31, 1992 -*************************************************************************/ -void smatrixtd(real_2d_array &a, const ae_int_t n, const bool isupper, real_1d_array &tau, real_1d_array &d, real_1d_array &e, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::smatrixtd(const_cast(a.c_ptr()), n, isupper, const_cast(tau.c_ptr()), const_cast(d.c_ptr()), const_cast(e.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Unpacking matrix Q which reduces symmetric matrix to a tridiagonal -form. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - the result of a SMatrixTD subroutine - N - size of matrix A. - IsUpper - storage format (a parameter of SMatrixTD subroutine) - Tau - the result of a SMatrixTD subroutine - -Output parameters: - Q - transformation matrix. - array with elements [0..N-1, 0..N-1]. - - -- ALGLIB -- - Copyright 2005-2010 by Bochkanov Sergey -*************************************************************************/ -void smatrixtdunpackq(const real_2d_array &a, const ae_int_t n, const bool isupper, const real_1d_array &tau, real_2d_array &q, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::smatrixtdunpackq(const_cast(a.c_ptr()), n, isupper, const_cast(tau.c_ptr()), const_cast(q.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Reduction of a Hermitian matrix which is given by its higher or lower -triangular part to a real tridiagonal matrix using unitary similarity -transformation: Q'*A*Q = T. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix to be transformed - array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - storage format. If IsUpper = True, then matrix A is given - by its upper triangle, and the lower triangle is not used - and not modified by the algorithm, and vice versa - if IsUpper = False. - -Output parameters: - A - matrices T and Q in compact form (see lower) - Tau - array of factors which are forming matrices H(i) - array with elements [0..N-2]. - D - main diagonal of real symmetric matrix T. - array with elements [0..N-1]. - E - secondary diagonal of real symmetric matrix T. - array with elements [0..N-2]. - - - If IsUpper=True, the matrix Q is represented as a product of elementary - reflectors - - Q = H(n-2) . . . H(2) H(0). - - Each H(i) has the form - - H(i) = I - tau * v * v' - - where tau is a complex scalar, and v is a complex vector with - v(i+1:n-1) = 0, v(i) = 1, v(0:i-1) is stored on exit in - A(0:i-1,i+1), and tau in TAU(i). - - If IsUpper=False, the matrix Q is represented as a product of elementary - reflectors - - Q = H(0) H(2) . . . H(n-2). - - Each H(i) has the form - - H(i) = I - tau * v * v' - - where tau is a complex scalar, and v is a complex vector with - v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) is stored on exit in A(i+2:n-1,i), - and tau in TAU(i). - - The contents of A on exit are illustrated by the following examples - with n = 5: - - if UPLO = 'U': if UPLO = 'L': - - ( d e v1 v2 v3 ) ( d ) - ( d e v2 v3 ) ( e d ) - ( d e v3 ) ( v0 e d ) - ( d e ) ( v0 v1 e d ) - ( d ) ( v0 v1 v2 e d ) - -where d and e denote diagonal and off-diagonal elements of T, and vi -denotes an element of the vector defining H(i). - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - October 31, 1992 -*************************************************************************/ -void hmatrixtd(complex_2d_array &a, const ae_int_t n, const bool isupper, complex_1d_array &tau, real_1d_array &d, real_1d_array &e, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hmatrixtd(const_cast(a.c_ptr()), n, isupper, const_cast(tau.c_ptr()), const_cast(d.c_ptr()), const_cast(e.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Unpacking matrix Q which reduces a Hermitian matrix to a real tridiagonal -form. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - the result of a HMatrixTD subroutine - N - size of matrix A. - IsUpper - storage format (a parameter of HMatrixTD subroutine) - Tau - the result of a HMatrixTD subroutine - -Output parameters: - Q - transformation matrix. - array with elements [0..N-1, 0..N-1]. - - -- ALGLIB -- - Copyright 2005-2010 by Bochkanov Sergey -*************************************************************************/ -void hmatrixtdunpackq(const complex_2d_array &a, const ae_int_t n, const bool isupper, const complex_1d_array &tau, complex_2d_array &q, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hmatrixtdunpackq(const_cast(a.c_ptr()), n, isupper, const_cast(tau.c_ptr()), const_cast(q.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_FBLS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_BDSVD) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Singular value decomposition of a bidiagonal matrix (extended algorithm) - -COMMERCIAL EDITION OF ALGLIB: - - ! Commercial version of ALGLIB includes one important improvement of - ! this function, which can be used from C++ and C#: - ! * Intel MKL support (lightweight Intel MKL is shipped with ALGLIB) - ! - ! Intel MKL gives approximately constant (with respect to number of - ! worker threads) acceleration factor which depends on CPU being used, - ! problem size and "baseline" ALGLIB edition which is used for - ! comparison. - ! - ! Generally, commercial ALGLIB is several times faster than open-source - ! generic C edition, and many times faster than open-source C# edition. - ! - ! Multithreaded acceleration is NOT supported for this function. - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -The algorithm performs the singular value decomposition of a bidiagonal -matrix B (upper or lower) representing it as B = Q*S*P^T, where Q and P - -orthogonal matrices, S - diagonal matrix with non-negative elements on the -main diagonal, in descending order. - -The algorithm finds singular values. In addition, the algorithm can -calculate matrices Q and P (more precisely, not the matrices, but their -product with given matrices U and VT - U*Q and (P^T)*VT)). Of course, -matrices U and VT can be of any type, including identity. Furthermore, the -algorithm can calculate Q'*C (this product is calculated more effectively -than U*Q, because this calculation operates with rows instead of matrix -columns). - -The feature of the algorithm is its ability to find all singular values -including those which are arbitrarily close to 0 with relative accuracy -close to machine precision. If the parameter IsFractionalAccuracyRequired -is set to True, all singular values will have high relative accuracy close -to machine precision. If the parameter is set to False, only the biggest -singular value will have relative accuracy close to machine precision. -The absolute error of other singular values is equal to the absolute error -of the biggest singular value. - -Input parameters: - D - main diagonal of matrix B. - Array whose index ranges within [0..N-1]. - E - superdiagonal (or subdiagonal) of matrix B. - Array whose index ranges within [0..N-2]. - N - size of matrix B. - IsUpper - True, if the matrix is upper bidiagonal. - IsFractionalAccuracyRequired - - THIS PARAMETER IS IGNORED SINCE ALGLIB 3.5.0 - SINGULAR VALUES ARE ALWAYS SEARCHED WITH HIGH ACCURACY. - U - matrix to be multiplied by Q. - Array whose indexes range within [0..NRU-1, 0..N-1]. - The matrix can be bigger, in that case only the submatrix - [0..NRU-1, 0..N-1] will be multiplied by Q. - NRU - number of rows in matrix U. - C - matrix to be multiplied by Q'. - Array whose indexes range within [0..N-1, 0..NCC-1]. - The matrix can be bigger, in that case only the submatrix - [0..N-1, 0..NCC-1] will be multiplied by Q'. - NCC - number of columns in matrix C. - VT - matrix to be multiplied by P^T. - Array whose indexes range within [0..N-1, 0..NCVT-1]. - The matrix can be bigger, in that case only the submatrix - [0..N-1, 0..NCVT-1] will be multiplied by P^T. - NCVT - number of columns in matrix VT. - -Output parameters: - D - singular values of matrix B in descending order. - U - if NRU>0, contains matrix U*Q. - VT - if NCVT>0, contains matrix (P^T)*VT. - C - if NCC>0, contains matrix Q'*C. - -Result: - True, if the algorithm has converged. - False, if the algorithm hasn't converged (rare case). - -NOTE: multiplication U*Q is performed by means of transposition to internal - buffer, multiplication and backward transposition. It helps to avoid - costly columnwise operations and speed-up algorithm. - -Additional information: - The type of convergence is controlled by the internal parameter TOL. - If the parameter is greater than 0, the singular values will have - relative accuracy TOL. If TOL<0, the singular values will have - absolute accuracy ABS(TOL)*norm(B). - By default, |TOL| falls within the range of 10*Epsilon and 100*Epsilon, - where Epsilon is the machine precision. It is not recommended to use - TOL less than 10*Epsilon since this will considerably slow down the - algorithm and may not lead to error decreasing. - -History: - * 31 March, 2007. - changed MAXITR from 6 to 12. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - October 31, 1999. -*************************************************************************/ -bool rmatrixbdsvd(real_1d_array &d, const real_1d_array &e, const ae_int_t n, const bool isupper, const bool isfractionalaccuracyrequired, real_2d_array &u, const ae_int_t nru, real_2d_array &c, const ae_int_t ncc, real_2d_array &vt, const ae_int_t ncvt, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::rmatrixbdsvd(const_cast(d.c_ptr()), const_cast(e.c_ptr()), n, isupper, isfractionalaccuracyrequired, const_cast(u.c_ptr()), nru, const_cast(c.c_ptr()), ncc, const_cast(vt.c_ptr()), ncvt, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_SVD) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Singular value decomposition of a rectangular matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -The algorithm calculates the singular value decomposition of a matrix of -size MxN: A = U * S * V^T - -The algorithm finds the singular values and, optionally, matrices U and V^T. -The algorithm can find both first min(M,N) columns of matrix U and rows of -matrix V^T (singular vectors), and matrices U and V^T wholly (of sizes MxM -and NxN respectively). - -Take into account that the subroutine does not return matrix V but V^T. - -Input parameters: - A - matrix to be decomposed. - Array whose indexes range within [0..M-1, 0..N-1]. - M - number of rows in matrix A. - N - number of columns in matrix A. - UNeeded - 0, 1 or 2. See the description of the parameter U. - VTNeeded - 0, 1 or 2. See the description of the parameter VT. - AdditionalMemory - - If the parameter: - * equals 0, the algorithm doesn't use additional - memory (lower requirements, lower performance). - * equals 1, the algorithm uses additional - memory of size min(M,N)*min(M,N) of real numbers. - It often speeds up the algorithm. - * equals 2, the algorithm uses additional - memory of size M*min(M,N) of real numbers. - It allows to get a maximum performance. - The recommended value of the parameter is 2. - -Output parameters: - W - contains singular values in descending order. - U - if UNeeded=0, U isn't changed, the left singular vectors - are not calculated. - if Uneeded=1, U contains left singular vectors (first - min(M,N) columns of matrix U). Array whose indexes range - within [0..M-1, 0..Min(M,N)-1]. - if UNeeded=2, U contains matrix U wholly. Array whose - indexes range within [0..M-1, 0..M-1]. - VT - if VTNeeded=0, VT isn't changed, the right singular vectors - are not calculated. - if VTNeeded=1, VT contains right singular vectors (first - min(M,N) rows of matrix V^T). Array whose indexes range - within [0..min(M,N)-1, 0..N-1]. - if VTNeeded=2, VT contains matrix V^T wholly. Array whose - indexes range within [0..N-1, 0..N-1]. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -bool rmatrixsvd(const real_2d_array &a, const ae_int_t m, const ae_int_t n, const ae_int_t uneeded, const ae_int_t vtneeded, const ae_int_t additionalmemory, real_1d_array &w, real_2d_array &u, real_2d_array &vt, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::rmatrixsvd(const_cast(a.c_ptr()), m, n, uneeded, vtneeded, additionalmemory, const_cast(w.c_ptr()), const_cast(u.c_ptr()), const_cast(vt.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_NORMESTIMATOR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores state of the iterative norm estimation algorithm. - -You should use ALGLIB functions to work with this object. -*************************************************************************/ -_normestimatorstate_owner::_normestimatorstate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_normestimatorstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::normestimatorstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::normestimatorstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::normestimatorstate)); - alglib_impl::_normestimatorstate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_normestimatorstate_owner::_normestimatorstate_owner(const _normestimatorstate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_normestimatorstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: normestimatorstate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::normestimatorstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::normestimatorstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::normestimatorstate)); - alglib_impl::_normestimatorstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_normestimatorstate_owner& _normestimatorstate_owner::operator=(const _normestimatorstate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: normestimatorstate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: normestimatorstate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_normestimatorstate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::normestimatorstate)); - alglib_impl::_normestimatorstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_normestimatorstate_owner::~_normestimatorstate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_normestimatorstate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::normestimatorstate* _normestimatorstate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::normestimatorstate* _normestimatorstate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -normestimatorstate::normestimatorstate() : _normestimatorstate_owner() -{ -} - -normestimatorstate::normestimatorstate(const normestimatorstate &rhs):_normestimatorstate_owner(rhs) -{ -} - -normestimatorstate& normestimatorstate::operator=(const normestimatorstate &rhs) -{ - if( this==&rhs ) - return *this; - _normestimatorstate_owner::operator=(rhs); - return *this; -} - -normestimatorstate::~normestimatorstate() -{ -} - -/************************************************************************* -This procedure initializes matrix norm estimator. - -USAGE: -1. User initializes algorithm state with NormEstimatorCreate() call -2. User calls NormEstimatorEstimateSparse() (or NormEstimatorIteration()) -3. User calls NormEstimatorResults() to get solution. - -INPUT PARAMETERS: - M - number of rows in the matrix being estimated, M>0 - N - number of columns in the matrix being estimated, N>0 - NStart - number of random starting vectors - recommended value - at least 5. - NIts - number of iterations to do with best starting vector - recommended value - at least 5. - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -NOTE: this algorithm is effectively deterministic, i.e. it always returns -same result when repeatedly called for the same matrix. In fact, algorithm -uses randomized starting vectors, but internal random numbers generator -always generates same sequence of the random values (it is a feature, not -bug). - -Algorithm can be made non-deterministic with NormEstimatorSetSeed(0) call. - - -- ALGLIB -- - Copyright 06.12.2011 by Bochkanov Sergey -*************************************************************************/ -void normestimatorcreate(const ae_int_t m, const ae_int_t n, const ae_int_t nstart, const ae_int_t nits, normestimatorstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::normestimatorcreate(m, n, nstart, nits, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function changes seed value used by algorithm. In some cases we need -deterministic processing, i.e. subsequent calls must return equal results, -in other cases we need non-deterministic algorithm which returns different -results for the same matrix on every pass. - -Setting zero seed will lead to non-deterministic algorithm, while non-zero -value will make our algorithm deterministic. - -INPUT PARAMETERS: - State - norm estimator state, must be initialized with a call - to NormEstimatorCreate() - SeedVal - seed value, >=0. Zero value = non-deterministic algo. - - -- ALGLIB -- - Copyright 06.12.2011 by Bochkanov Sergey -*************************************************************************/ -void normestimatorsetseed(const normestimatorstate &state, const ae_int_t seedval, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::normestimatorsetseed(const_cast(state.c_ptr()), seedval, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function estimates norm of the sparse M*N matrix A. - -INPUT PARAMETERS: - State - norm estimator state, must be initialized with a call - to NormEstimatorCreate() - A - sparse M*N matrix, must be converted to CRS format - prior to calling this function. - -After this function is over you can call NormEstimatorResults() to get -estimate of the norm(A). - - -- ALGLIB -- - Copyright 06.12.2011 by Bochkanov Sergey -*************************************************************************/ -void normestimatorestimatesparse(const normestimatorstate &state, const sparsematrix &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::normestimatorestimatesparse(const_cast(state.c_ptr()), const_cast(a.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Matrix norm estimation results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - Nrm - estimate of the matrix norm, Nrm>=0 - - -- ALGLIB -- - Copyright 06.12.2011 by Bochkanov Sergey -*************************************************************************/ -void normestimatorresults(const normestimatorstate &state, double &nrm, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::normestimatorresults(const_cast(state.c_ptr()), &nrm, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_HSSCHUR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_EVD) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores state of the subspace iteration algorithm. - -You should use ALGLIB functions to work with this object. -*************************************************************************/ -_eigsubspacestate_owner::_eigsubspacestate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_eigsubspacestate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::eigsubspacestate*)alglib_impl::ae_malloc(sizeof(alglib_impl::eigsubspacestate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::eigsubspacestate)); - alglib_impl::_eigsubspacestate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_eigsubspacestate_owner::_eigsubspacestate_owner(const _eigsubspacestate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_eigsubspacestate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: eigsubspacestate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::eigsubspacestate*)alglib_impl::ae_malloc(sizeof(alglib_impl::eigsubspacestate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::eigsubspacestate)); - alglib_impl::_eigsubspacestate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_eigsubspacestate_owner& _eigsubspacestate_owner::operator=(const _eigsubspacestate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: eigsubspacestate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: eigsubspacestate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_eigsubspacestate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::eigsubspacestate)); - alglib_impl::_eigsubspacestate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_eigsubspacestate_owner::~_eigsubspacestate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_eigsubspacestate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::eigsubspacestate* _eigsubspacestate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::eigsubspacestate* _eigsubspacestate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -eigsubspacestate::eigsubspacestate() : _eigsubspacestate_owner() -{ -} - -eigsubspacestate::eigsubspacestate(const eigsubspacestate &rhs):_eigsubspacestate_owner(rhs) -{ -} - -eigsubspacestate& eigsubspacestate::operator=(const eigsubspacestate &rhs) -{ - if( this==&rhs ) - return *this; - _eigsubspacestate_owner::operator=(rhs); - return *this; -} - -eigsubspacestate::~eigsubspacestate() -{ -} - - -/************************************************************************* -This object stores state of the subspace iteration algorithm. - -You should use ALGLIB functions to work with this object. -*************************************************************************/ -_eigsubspacereport_owner::_eigsubspacereport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_eigsubspacereport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::eigsubspacereport*)alglib_impl::ae_malloc(sizeof(alglib_impl::eigsubspacereport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::eigsubspacereport)); - alglib_impl::_eigsubspacereport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_eigsubspacereport_owner::_eigsubspacereport_owner(const _eigsubspacereport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_eigsubspacereport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: eigsubspacereport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::eigsubspacereport*)alglib_impl::ae_malloc(sizeof(alglib_impl::eigsubspacereport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::eigsubspacereport)); - alglib_impl::_eigsubspacereport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_eigsubspacereport_owner& _eigsubspacereport_owner::operator=(const _eigsubspacereport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: eigsubspacereport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: eigsubspacereport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_eigsubspacereport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::eigsubspacereport)); - alglib_impl::_eigsubspacereport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_eigsubspacereport_owner::~_eigsubspacereport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_eigsubspacereport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::eigsubspacereport* _eigsubspacereport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::eigsubspacereport* _eigsubspacereport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -eigsubspacereport::eigsubspacereport() : _eigsubspacereport_owner() ,iterationscount(p_struct->iterationscount) -{ -} - -eigsubspacereport::eigsubspacereport(const eigsubspacereport &rhs):_eigsubspacereport_owner(rhs) ,iterationscount(p_struct->iterationscount) -{ -} - -eigsubspacereport& eigsubspacereport::operator=(const eigsubspacereport &rhs) -{ - if( this==&rhs ) - return *this; - _eigsubspacereport_owner::operator=(rhs); - return *this; -} - -eigsubspacereport::~eigsubspacereport() -{ -} - -/************************************************************************* -This function initializes subspace iteration solver. This solver is used -to solve symmetric real eigenproblems where just a few (top K) eigenvalues -and corresponding eigenvectors is required. - -This solver can be significantly faster than complete EVD decomposition -in the following case: -* when only just a small fraction of top eigenpairs of dense matrix is - required. When K approaches N, this solver is slower than complete dense - EVD -* when problem matrix is sparse (and/or is not known explicitly, i.e. only - matrix-matrix product can be performed) - -USAGE (explicit dense/sparse matrix): -1. User initializes algorithm state with eigsubspacecreate() call -2. [optional] User tunes solver parameters by calling eigsubspacesetcond() - or other functions -3. User calls eigsubspacesolvedense() or eigsubspacesolvesparse() methods, - which take algorithm state and 2D array or alglib.sparsematrix object. - -USAGE (out-of-core mode): -1. User initializes algorithm state with eigsubspacecreate() call -2. [optional] User tunes solver parameters by calling eigsubspacesetcond() - or other functions -3. User activates out-of-core mode of the solver and repeatedly calls - communication functions in a loop like below: - > alglib.eigsubspaceoocstart(state) - > while alglib.eigsubspaceooccontinue(state) do - > alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) - > alglib.eigsubspaceoocgetrequestdata(state, out X) - > [calculate Y=A*X, with X=R^NxM] - > alglib.eigsubspaceoocsendresult(state, in Y) - > alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - N - problem dimensionality, N>0 - K - number of top eigenvector to calculate, 0(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Buffered version of constructor which aims to reuse previously allocated -memory as much as possible. - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspacecreatebuf(const ae_int_t n, const ae_int_t k, const eigsubspacestate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::eigsubspacecreatebuf(n, k, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets stopping critera for the solver: -* error in eigenvector/value allowed by solver -* maximum number of iterations to perform - -INPUT PARAMETERS: - State - solver structure - Eps - eps>=0, with non-zero value used to tell solver that - it can stop after all eigenvalues converged with - error roughly proportional to eps*MAX(LAMBDA_MAX), - where LAMBDA_MAX is a maximum eigenvalue. - Zero value means that no check for precision is - performed. - MaxIts - maxits>=0, with non-zero value used to tell solver - that it can stop after maxits steps (no matter how - precise current estimate is) - -NOTE: passing eps=0 and maxits=0 results in automatic selection of - moderate eps as stopping criteria (1.0E-6 in current implementation, - but it may change without notice). - -NOTE: very small values of eps are possible (say, 1.0E-12), although the - larger problem you solve (N and/or K), the harder it is to find - precise eigenvectors because rounding errors tend to accumulate. - -NOTE: passing non-zero eps results in some performance penalty, roughly - equal to 2N*(2K)^2 FLOPs per iteration. These additional computations - are required in order to estimate current error in eigenvalues via - Rayleigh-Ritz process. - Most of this additional time is spent in construction of ~2Kx2K - symmetric subproblem whose eigenvalues are checked with exact - eigensolver. - This additional time is negligible if you search for eigenvalues of - the large dense matrix, but may become noticeable on highly sparse - EVD problems, where cost of matrix-matrix product is low. - If you set eps to exactly zero, Rayleigh-Ritz phase is completely - turned off. - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspacesetcond(const eigsubspacestate &state, const double eps, const ae_int_t maxits, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::eigsubspacesetcond(const_cast(state.c_ptr()), eps, maxits, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets warm-start mode of the solver: next call to the solver -will reuse previous subspace as warm-start point. It can significantly -speed-up convergence when you solve many similar eigenproblems. - -INPUT PARAMETERS: - State - solver structure - UseWarmStart- either True or False - - -- ALGLIB -- - Copyright 12.11.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspacesetwarmstart(const eigsubspacestate &state, const bool usewarmstart, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::eigsubspacesetwarmstart(const_cast(state.c_ptr()), usewarmstart, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function initiates out-of-core mode of subspace eigensolver. It -should be used in conjunction with other out-of-core-related functions of -this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - State - solver object - MType - matrix type: - * 0 for real symmetric matrix (solver assumes that - matrix being processed is symmetric; symmetric - direct eigensolver is used for smaller subproblems - arising during solution of larger "full" task) - Future versions of ALGLIB may introduce support for - other matrix types; for now, only symmetric - eigenproblems are supported. - - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspaceoocstart(const eigsubspacestate &state, const ae_int_t mtype, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::eigsubspaceoocstart(const_cast(state.c_ptr()), mtype, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function performs subspace iteration in the out-of-core mode. It -should be used in conjunction with other out-of-core-related functions of -this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -bool eigsubspaceooccontinue(const eigsubspacestate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::eigsubspaceooccontinue(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This function is used to retrieve information about out-of-core request -sent by solver to user code: request type (current version of the solver -sends only requests for matrix-matrix products) and request size (size of -the matrices being multiplied). - -This function returns just request metrics; in order to get contents of -the matrices being multiplied, use eigsubspaceoocgetrequestdata(). - -It should be used in conjunction with other out-of-core-related functions -of this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - State - solver running in out-of-core mode - -OUTPUT PARAMETERS: - RequestType - type of the request to process: - * 0 - for matrix-matrix product A*X, with A being - NxN matrix whose eigenvalues/vectors are needed, - and X being NxREQUESTSIZE one which is returned - by the eigsubspaceoocgetrequestdata(). - RequestSize - size of the X matrix (number of columns), usually - it is several times larger than number of vectors - K requested by user. - - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspaceoocgetrequestinfo(const eigsubspacestate &state, ae_int_t &requesttype, ae_int_t &requestsize, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::eigsubspaceoocgetrequestinfo(const_cast(state.c_ptr()), &requesttype, &requestsize, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is used to retrieve information about out-of-core request -sent by solver to user code: matrix X (array[N,RequestSize) which have to -be multiplied by out-of-core matrix A in a product A*X. - -This function returns just request data; in order to get size of the data -prior to processing requestm, use eigsubspaceoocgetrequestinfo(). - -It should be used in conjunction with other out-of-core-related functions -of this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - State - solver running in out-of-core mode - X - possibly preallocated storage; reallocated if - needed, left unchanged, if large enough to store - request data. - -OUTPUT PARAMETERS: - X - array[N,RequestSize] or larger, leading rectangle - is filled with dense matrix X. - - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspaceoocgetrequestdata(const eigsubspacestate &state, real_2d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::eigsubspaceoocgetrequestdata(const_cast(state.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is used to send user reply to out-of-core request sent by -solver. Usually it is product A*X for returned by solver matrix X. - -It should be used in conjunction with other out-of-core-related functions -of this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - State - solver running in out-of-core mode - AX - array[N,RequestSize] or larger, leading rectangle - is filled with product A*X. - - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspaceoocsendresult(const eigsubspacestate &state, const real_2d_array &ax, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::eigsubspaceoocsendresult(const_cast(state.c_ptr()), const_cast(ax.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function finalizes out-of-core mode of subspace eigensolver. It -should be used in conjunction with other out-of-core-related functions of -this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - State - solver state - -OUTPUT PARAMETERS: - W - array[K], depending on solver settings: - * top K eigenvalues ordered by descending - if - eigenvectors are returned in Z - * zeros - if invariant subspace is returned in Z - Z - array[N,K], depending on solver settings either: - * matrix of eigenvectors found - * orthogonal basis of K-dimensional invariant subspace - Rep - report with additional parameters - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspaceoocstop(const eigsubspacestate &state, real_1d_array &w, real_2d_array &z, eigsubspacereport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::eigsubspaceoocstop(const_cast(state.c_ptr()), const_cast(w.c_ptr()), const_cast(z.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function runs eigensolver for dense NxN symmetric matrix A, given by -upper or lower triangle. - -This function can not process nonsymmetric matrices. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - State - solver state - A - array[N,N], symmetric NxN matrix given by one of its - triangles - IsUpper - whether upper or lower triangle of A is given (the - other one is not referenced at all). - -OUTPUT PARAMETERS: - W - array[K], top K eigenvalues ordered by descending - of their absolute values - Z - array[N,K], matrix of eigenvectors found - Rep - report with additional parameters - -NOTE: internally this function allocates a copy of NxN dense A. You should - take it into account when working with very large matrices occupying - almost all RAM. - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspacesolvedenses(const eigsubspacestate &state, const real_2d_array &a, const bool isupper, real_1d_array &w, real_2d_array &z, eigsubspacereport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::eigsubspacesolvedenses(const_cast(state.c_ptr()), const_cast(a.c_ptr()), isupper, const_cast(w.c_ptr()), const_cast(z.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function runs eigensolver for dense NxN symmetric matrix A, given by -upper or lower triangle. - -This function can not process nonsymmetric matrices. - -INPUT PARAMETERS: - State - solver state - A - NxN symmetric matrix given by one of its triangles - IsUpper - whether upper or lower triangle of A is given (the - other one is not referenced at all). - -OUTPUT PARAMETERS: - W - array[K], top K eigenvalues ordered by descending - of their absolute values - Z - array[N,K], matrix of eigenvectors found - Rep - report with additional parameters - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspacesolvesparses(const eigsubspacestate &state, const sparsematrix &a, const bool isupper, real_1d_array &w, real_2d_array &z, eigsubspacereport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::eigsubspacesolvesparses(const_cast(state.c_ptr()), const_cast(a.c_ptr()), isupper, const_cast(w.c_ptr()), const_cast(z.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Finding the eigenvalues and eigenvectors of a symmetric matrix - -The algorithm finds eigen pairs of a symmetric matrix by reducing it to -tridiagonal form and using the QL/QR algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - symmetric matrix which is given by its upper or lower - triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - IsUpper - storage format. - -Output parameters: - D - eigenvalues in ascending order. - Array whose index ranges within [0..N-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains the eigenvectors. - Array whose indexes range within [0..N-1, 0..N-1]. - The eigenvectors are stored in the matrix columns. - -Result: - True, if the algorithm has converged. - False, if the algorithm hasn't converged (rare case). - - -- ALGLIB -- - Copyright 2005-2008 by Bochkanov Sergey -*************************************************************************/ -bool smatrixevd(const real_2d_array &a, const ae_int_t n, const ae_int_t zneeded, const bool isupper, real_1d_array &d, real_2d_array &z, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::smatrixevd(const_cast(a.c_ptr()), n, zneeded, isupper, const_cast(d.c_ptr()), const_cast(z.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Subroutine for finding the eigenvalues (and eigenvectors) of a symmetric -matrix in a given half open interval (A, B] by using a bisection and -inverse iteration - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - symmetric matrix which is given by its upper or lower - triangular part. Array [0..N-1, 0..N-1]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - IsUpperA - storage format of matrix A. - B1, B2 - half open interval (B1, B2] to search eigenvalues in. - -Output parameters: - M - number of eigenvalues found in a given half-interval (M>=0). - W - array of the eigenvalues found. - Array whose index ranges within [0..M-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains eigenvectors. - Array whose indexes range within [0..N-1, 0..M-1]. - The eigenvectors are stored in the matrix columns. - -Result: - True, if successful. M contains the number of eigenvalues in the given - half-interval (could be equal to 0), W contains the eigenvalues, - Z contains the eigenvectors (if needed). - - False, if the bisection method subroutine wasn't able to find the - eigenvalues in the given interval or if the inverse iteration subroutine - wasn't able to find all the corresponding eigenvectors. - In that case, the eigenvalues and eigenvectors are not returned, - M is equal to 0. - - -- ALGLIB -- - Copyright 07.01.2006 by Bochkanov Sergey -*************************************************************************/ -bool smatrixevdr(const real_2d_array &a, const ae_int_t n, const ae_int_t zneeded, const bool isupper, const double b1, const double b2, ae_int_t &m, real_1d_array &w, real_2d_array &z, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::smatrixevdr(const_cast(a.c_ptr()), n, zneeded, isupper, b1, b2, &m, const_cast(w.c_ptr()), const_cast(z.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Subroutine for finding the eigenvalues and eigenvectors of a symmetric -matrix with given indexes by using bisection and inverse iteration methods. - -Input parameters: - A - symmetric matrix which is given by its upper or lower - triangular part. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - IsUpperA - storage format of matrix A. - I1, I2 - index interval for searching (from I1 to I2). - 0 <= I1 <= I2 <= N-1. - -Output parameters: - W - array of the eigenvalues found. - Array whose index ranges within [0..I2-I1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains eigenvectors. - Array whose indexes range within [0..N-1, 0..I2-I1]. - In that case, the eigenvectors are stored in the matrix columns. - -Result: - True, if successful. W contains the eigenvalues, Z contains the - eigenvectors (if needed). - - False, if the bisection method subroutine wasn't able to find the - eigenvalues in the given interval or if the inverse iteration subroutine - wasn't able to find all the corresponding eigenvectors. - In that case, the eigenvalues and eigenvectors are not returned. - - -- ALGLIB -- - Copyright 07.01.2006 by Bochkanov Sergey -*************************************************************************/ -bool smatrixevdi(const real_2d_array &a, const ae_int_t n, const ae_int_t zneeded, const bool isupper, const ae_int_t i1, const ae_int_t i2, real_1d_array &w, real_2d_array &z, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::smatrixevdi(const_cast(a.c_ptr()), n, zneeded, isupper, i1, i2, const_cast(w.c_ptr()), const_cast(z.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Finding the eigenvalues and eigenvectors of a Hermitian matrix - -The algorithm finds eigen pairs of a Hermitian matrix by reducing it to -real tridiagonal form and using the QL/QR algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - Hermitian matrix which is given by its upper or lower - triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - storage format. - ZNeeded - flag controlling whether the eigenvectors are needed or - not. If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - -Output parameters: - D - eigenvalues in ascending order. - Array whose index ranges within [0..N-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains the eigenvectors. - Array whose indexes range within [0..N-1, 0..N-1]. - The eigenvectors are stored in the matrix columns. - -Result: - True, if the algorithm has converged. - False, if the algorithm hasn't converged (rare case). - -Note: - eigenvectors of Hermitian matrix are defined up to multiplication by - a complex number L, such that |L|=1. - - -- ALGLIB -- - Copyright 2005, 23 March 2007 by Bochkanov Sergey -*************************************************************************/ -bool hmatrixevd(const complex_2d_array &a, const ae_int_t n, const ae_int_t zneeded, const bool isupper, real_1d_array &d, complex_2d_array &z, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::hmatrixevd(const_cast(a.c_ptr()), n, zneeded, isupper, const_cast(d.c_ptr()), const_cast(z.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Subroutine for finding the eigenvalues (and eigenvectors) of a Hermitian -matrix in a given half-interval (A, B] by using a bisection and inverse -iteration - -Input parameters: - A - Hermitian matrix which is given by its upper or lower - triangular part. Array whose indexes range within - [0..N-1, 0..N-1]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or - not. If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - IsUpperA - storage format of matrix A. - B1, B2 - half-interval (B1, B2] to search eigenvalues in. - -Output parameters: - M - number of eigenvalues found in a given half-interval, M>=0 - W - array of the eigenvalues found. - Array whose index ranges within [0..M-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains eigenvectors. - Array whose indexes range within [0..N-1, 0..M-1]. - The eigenvectors are stored in the matrix columns. - -Result: - True, if successful. M contains the number of eigenvalues in the given - half-interval (could be equal to 0), W contains the eigenvalues, - Z contains the eigenvectors (if needed). - - False, if the bisection method subroutine wasn't able to find the - eigenvalues in the given interval or if the inverse iteration - subroutine wasn't able to find all the corresponding eigenvectors. - In that case, the eigenvalues and eigenvectors are not returned, M is - equal to 0. - -Note: - eigen vectors of Hermitian matrix are defined up to multiplication by - a complex number L, such as |L|=1. - - -- ALGLIB -- - Copyright 07.01.2006, 24.03.2007 by Bochkanov Sergey. -*************************************************************************/ -bool hmatrixevdr(const complex_2d_array &a, const ae_int_t n, const ae_int_t zneeded, const bool isupper, const double b1, const double b2, ae_int_t &m, real_1d_array &w, complex_2d_array &z, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::hmatrixevdr(const_cast(a.c_ptr()), n, zneeded, isupper, b1, b2, &m, const_cast(w.c_ptr()), const_cast(z.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Subroutine for finding the eigenvalues and eigenvectors of a Hermitian -matrix with given indexes by using bisection and inverse iteration methods - -Input parameters: - A - Hermitian matrix which is given by its upper or lower - triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or - not. If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - IsUpperA - storage format of matrix A. - I1, I2 - index interval for searching (from I1 to I2). - 0 <= I1 <= I2 <= N-1. - -Output parameters: - W - array of the eigenvalues found. - Array whose index ranges within [0..I2-I1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains eigenvectors. - Array whose indexes range within [0..N-1, 0..I2-I1]. - In that case, the eigenvectors are stored in the matrix - columns. - -Result: - True, if successful. W contains the eigenvalues, Z contains the - eigenvectors (if needed). - - False, if the bisection method subroutine wasn't able to find the - eigenvalues in the given interval or if the inverse iteration - subroutine wasn't able to find all the corresponding eigenvectors. - In that case, the eigenvalues and eigenvectors are not returned. - -Note: - eigen vectors of Hermitian matrix are defined up to multiplication by - a complex number L, such as |L|=1. - - -- ALGLIB -- - Copyright 07.01.2006, 24.03.2007 by Bochkanov Sergey. -*************************************************************************/ -bool hmatrixevdi(const complex_2d_array &a, const ae_int_t n, const ae_int_t zneeded, const bool isupper, const ae_int_t i1, const ae_int_t i2, real_1d_array &w, complex_2d_array &z, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::hmatrixevdi(const_cast(a.c_ptr()), n, zneeded, isupper, i1, i2, const_cast(w.c_ptr()), const_cast(z.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Finding the eigenvalues and eigenvectors of a tridiagonal symmetric matrix - -The algorithm finds the eigen pairs of a tridiagonal symmetric matrix by -using an QL/QR algorithm with implicit shifts. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - D - the main diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-1]. - E - the secondary diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-2]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not needed; - * 1, the eigenvectors of a tridiagonal matrix - are multiplied by the square matrix Z. It is used if the - tridiagonal matrix is obtained by the similarity - transformation of a symmetric matrix; - * 2, the eigenvectors of a tridiagonal matrix replace the - square matrix Z; - * 3, matrix Z contains the first row of the eigenvectors - matrix. - Z - if ZNeeded=1, Z contains the square matrix by which the - eigenvectors are multiplied. - Array whose indexes range within [0..N-1, 0..N-1]. - -Output parameters: - D - eigenvalues in ascending order. - Array whose index ranges within [0..N-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains the product of a given matrix (from the left) - and the eigenvectors matrix (from the right); - * 2, Z contains the eigenvectors. - * 3, Z contains the first row of the eigenvectors matrix. - If ZNeeded<3, Z is the array whose indexes range within [0..N-1, 0..N-1]. - In that case, the eigenvectors are stored in the matrix columns. - If ZNeeded=3, Z is the array whose indexes range within [0..0, 0..N-1]. - -Result: - True, if the algorithm has converged. - False, if the algorithm hasn't converged. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994 -*************************************************************************/ -bool smatrixtdevd(real_1d_array &d, const real_1d_array &e, const ae_int_t n, const ae_int_t zneeded, real_2d_array &z, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::smatrixtdevd(const_cast(d.c_ptr()), const_cast(e.c_ptr()), n, zneeded, const_cast(z.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Subroutine for finding the tridiagonal matrix eigenvalues/vectors in a -given half-interval (A, B] by using bisection and inverse iteration. - -Input parameters: - D - the main diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-1]. - E - the secondary diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-2]. - N - size of matrix, N>=0. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not needed; - * 1, the eigenvectors of a tridiagonal matrix are multiplied - by the square matrix Z. It is used if the tridiagonal - matrix is obtained by the similarity transformation - of a symmetric matrix. - * 2, the eigenvectors of a tridiagonal matrix replace matrix Z. - A, B - half-interval (A, B] to search eigenvalues in. - Z - if ZNeeded is equal to: - * 0, Z isn't used and remains unchanged; - * 1, Z contains the square matrix (array whose indexes range - within [0..N-1, 0..N-1]) which reduces the given symmetric - matrix to tridiagonal form; - * 2, Z isn't used (but changed on the exit). - -Output parameters: - D - array of the eigenvalues found. - Array whose index ranges within [0..M-1]. - M - number of eigenvalues found in the given half-interval (M>=0). - Z - if ZNeeded is equal to: - * 0, doesn't contain any information; - * 1, contains the product of a given NxN matrix Z (from the - left) and NxM matrix of the eigenvectors found (from the - right). Array whose indexes range within [0..N-1, 0..M-1]. - * 2, contains the matrix of the eigenvectors found. - Array whose indexes range within [0..N-1, 0..M-1]. - -Result: - - True, if successful. In that case, M contains the number of eigenvalues - in the given half-interval (could be equal to 0), D contains the eigenvalues, - Z contains the eigenvectors (if needed). - It should be noted that the subroutine changes the size of arrays D and Z. - - False, if the bisection method subroutine wasn't able to find the - eigenvalues in the given interval or if the inverse iteration subroutine - wasn't able to find all the corresponding eigenvectors. In that case, - the eigenvalues and eigenvectors are not returned, M is equal to 0. - - -- ALGLIB -- - Copyright 31.03.2008 by Bochkanov Sergey -*************************************************************************/ -bool smatrixtdevdr(real_1d_array &d, const real_1d_array &e, const ae_int_t n, const ae_int_t zneeded, const double a, const double b, ae_int_t &m, real_2d_array &z, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::smatrixtdevdr(const_cast(d.c_ptr()), const_cast(e.c_ptr()), n, zneeded, a, b, &m, const_cast(z.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Subroutine for finding tridiagonal matrix eigenvalues/vectors with given -indexes (in ascending order) by using the bisection and inverse iteraion. - -Input parameters: - D - the main diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-1]. - E - the secondary diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-2]. - N - size of matrix. N>=0. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not needed; - * 1, the eigenvectors of a tridiagonal matrix are multiplied - by the square matrix Z. It is used if the - tridiagonal matrix is obtained by the similarity transformation - of a symmetric matrix. - * 2, the eigenvectors of a tridiagonal matrix replace - matrix Z. - I1, I2 - index interval for searching (from I1 to I2). - 0 <= I1 <= I2 <= N-1. - Z - if ZNeeded is equal to: - * 0, Z isn't used and remains unchanged; - * 1, Z contains the square matrix (array whose indexes range within [0..N-1, 0..N-1]) - which reduces the given symmetric matrix to tridiagonal form; - * 2, Z isn't used (but changed on the exit). - -Output parameters: - D - array of the eigenvalues found. - Array whose index ranges within [0..I2-I1]. - Z - if ZNeeded is equal to: - * 0, doesn't contain any information; - * 1, contains the product of a given NxN matrix Z (from the left) and - Nx(I2-I1) matrix of the eigenvectors found (from the right). - Array whose indexes range within [0..N-1, 0..I2-I1]. - * 2, contains the matrix of the eigenvalues found. - Array whose indexes range within [0..N-1, 0..I2-I1]. - - -Result: - - True, if successful. In that case, D contains the eigenvalues, - Z contains the eigenvectors (if needed). - It should be noted that the subroutine changes the size of arrays D and Z. - - False, if the bisection method subroutine wasn't able to find the eigenvalues - in the given interval or if the inverse iteration subroutine wasn't able - to find all the corresponding eigenvectors. In that case, the eigenvalues - and eigenvectors are not returned. - - -- ALGLIB -- - Copyright 25.12.2005 by Bochkanov Sergey -*************************************************************************/ -bool smatrixtdevdi(real_1d_array &d, const real_1d_array &e, const ae_int_t n, const ae_int_t zneeded, const ae_int_t i1, const ae_int_t i2, real_2d_array &z, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::smatrixtdevdi(const_cast(d.c_ptr()), const_cast(e.c_ptr()), n, zneeded, i1, i2, const_cast(z.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Finding eigenvalues and eigenvectors of a general (unsymmetric) matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -The algorithm finds eigenvalues and eigenvectors of a general matrix by -using the QR algorithm with multiple shifts. The algorithm can find -eigenvalues and both left and right eigenvectors. - -The right eigenvector is a vector x such that A*x = w*x, and the left -eigenvector is a vector y such that y'*A = w*y' (here y' implies a complex -conjugate transposition of vector y). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - VNeeded - flag controlling whether eigenvectors are needed or not. - If VNeeded is equal to: - * 0, eigenvectors are not returned; - * 1, right eigenvectors are returned; - * 2, left eigenvectors are returned; - * 3, both left and right eigenvectors are returned. - -Output parameters: - WR - real parts of eigenvalues. - Array whose index ranges within [0..N-1]. - WR - imaginary parts of eigenvalues. - Array whose index ranges within [0..N-1]. - VL, VR - arrays of left and right eigenvectors (if they are needed). - If WI[i]=0, the respective eigenvalue is a real number, - and it corresponds to the column number I of matrices VL/VR. - If WI[i]>0, we have a pair of complex conjugate numbers with - positive and negative imaginary parts: - the first eigenvalue WR[i] + sqrt(-1)*WI[i]; - the second eigenvalue WR[i+1] + sqrt(-1)*WI[i+1]; - WI[i]>0 - WI[i+1] = -WI[i] < 0 - In that case, the eigenvector corresponding to the first - eigenvalue is located in i and i+1 columns of matrices - VL/VR (the column number i contains the real part, and the - column number i+1 contains the imaginary part), and the vector - corresponding to the second eigenvalue is a complex conjugate to - the first vector. - Arrays whose indexes range within [0..N-1, 0..N-1]. - -Result: - True, if the algorithm has converged. - False, if the algorithm has not converged. - -Note 1: - Some users may ask the following question: what if WI[N-1]>0? - WI[N] must contain an eigenvalue which is complex conjugate to the - N-th eigenvalue, but the array has only size N? - The answer is as follows: such a situation cannot occur because the - algorithm finds a pairs of eigenvalues, therefore, if WI[i]>0, I is - strictly less than N-1. - -Note 2: - The algorithm performance depends on the value of the internal parameter - NS of the InternalSchurDecomposition subroutine which defines the number - of shifts in the QR algorithm (similarly to the block width in block-matrix - algorithms of linear algebra). If you require maximum performance - on your machine, it is recommended to adjust this parameter manually. - - -See also the InternalTREVC subroutine. - -The algorithm is based on the LAPACK 3.0 library. -*************************************************************************/ -bool rmatrixevd(const real_2d_array &a, const ae_int_t n, const ae_int_t vneeded, real_1d_array &wr, real_1d_array &wi, real_2d_array &vl, real_2d_array &vr, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::rmatrixevd(const_cast(a.c_ptr()), n, vneeded, const_cast(wr.c_ptr()), const_cast(wi.c_ptr()), const_cast(vl.c_ptr()), const_cast(vr.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_SCHUR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Subroutine performing the Schur decomposition of a general matrix by using -the QR algorithm with multiple shifts. - -COMMERCIAL EDITION OF ALGLIB: - - ! Commercial version of ALGLIB includes one important improvement of - ! this function, which can be used from C++ and C#: - ! * Intel MKL support (lightweight Intel MKL is shipped with ALGLIB) - ! - ! Intel MKL gives approximately constant (with respect to number of - ! worker threads) acceleration factor which depends on CPU being used, - ! problem size and "baseline" ALGLIB edition which is used for - ! comparison. - ! - ! Multithreaded acceleration is NOT supported for this function. - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -The source matrix A is represented as S'*A*S = T, where S is an orthogonal -matrix (Schur vectors), T - upper quasi-triangular matrix (with blocks of -sizes 1x1 and 2x2 on the main diagonal). - -Input parameters: - A - matrix to be decomposed. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of A, N>=0. - - -Output parameters: - A - contains matrix T. - Array whose indexes range within [0..N-1, 0..N-1]. - S - contains Schur vectors. - Array whose indexes range within [0..N-1, 0..N-1]. - -Note 1: - The block structure of matrix T can be easily recognized: since all - the elements below the blocks are zeros, the elements a[i+1,i] which - are equal to 0 show the block border. - -Note 2: - The algorithm performance depends on the value of the internal parameter - NS of the InternalSchurDecomposition subroutine which defines the number - of shifts in the QR algorithm (similarly to the block width in block-matrix - algorithms in linear algebra). If you require maximum performance on - your machine, it is recommended to adjust this parameter manually. - -Result: - True, - if the algorithm has converged and parameters A and S contain the result. - False, - if the algorithm has not converged. - -Algorithm implemented on the basis of the DHSEQR subroutine (LAPACK 3.0 library). -*************************************************************************/ -bool rmatrixschur(real_2d_array &a, const ae_int_t n, real_2d_array &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::rmatrixschur(const_cast(a.c_ptr()), n, const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_SPDGEVD) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Algorithm for solving the following generalized symmetric positive-definite -eigenproblem: - A*x = lambda*B*x (1) or - A*B*x = lambda*x (2) or - B*A*x = lambda*x (3). -where A is a symmetric matrix, B - symmetric positive-definite matrix. -The problem is solved by reducing it to an ordinary symmetric eigenvalue -problem. - -Input parameters: - A - symmetric matrix which is given by its upper or lower - triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrices A and B. - IsUpperA - storage format of matrix A. - B - symmetric positive-definite matrix which is given by - its upper or lower triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - IsUpperB - storage format of matrix B. - ZNeeded - if ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - ProblemType - if ProblemType is equal to: - * 1, the following problem is solved: A*x = lambda*B*x; - * 2, the following problem is solved: A*B*x = lambda*x; - * 3, the following problem is solved: B*A*x = lambda*x. - -Output parameters: - D - eigenvalues in ascending order. - Array whose index ranges within [0..N-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains eigenvectors. - Array whose indexes range within [0..N-1, 0..N-1]. - The eigenvectors are stored in matrix columns. It should - be noted that the eigenvectors in such problems do not - form an orthogonal system. - -Result: - True, if the problem was solved successfully. - False, if the error occurred during the Cholesky decomposition of matrix - B (the matrix isn't positive-definite) or during the work of the iterative - algorithm for solving the symmetric eigenproblem. - -See also the GeneralizedSymmetricDefiniteEVDReduce subroutine. - - -- ALGLIB -- - Copyright 1.28.2006 by Bochkanov Sergey -*************************************************************************/ -bool smatrixgevd(const real_2d_array &a, const ae_int_t n, const bool isuppera, const real_2d_array &b, const bool isupperb, const ae_int_t zneeded, const ae_int_t problemtype, real_1d_array &d, real_2d_array &z, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::smatrixgevd(const_cast(a.c_ptr()), n, isuppera, const_cast(b.c_ptr()), isupperb, zneeded, problemtype, const_cast(d.c_ptr()), const_cast(z.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Algorithm for reduction of the following generalized symmetric positive- -definite eigenvalue problem: - A*x = lambda*B*x (1) or - A*B*x = lambda*x (2) or - B*A*x = lambda*x (3) -to the symmetric eigenvalues problem C*y = lambda*y (eigenvalues of this and -the given problems are the same, and the eigenvectors of the given problem -could be obtained by multiplying the obtained eigenvectors by the -transformation matrix x = R*y). - -Here A is a symmetric matrix, B - symmetric positive-definite matrix. - -Input parameters: - A - symmetric matrix which is given by its upper or lower - triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrices A and B. - IsUpperA - storage format of matrix A. - B - symmetric positive-definite matrix which is given by - its upper or lower triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - IsUpperB - storage format of matrix B. - ProblemType - if ProblemType is equal to: - * 1, the following problem is solved: A*x = lambda*B*x; - * 2, the following problem is solved: A*B*x = lambda*x; - * 3, the following problem is solved: B*A*x = lambda*x. - -Output parameters: - A - symmetric matrix which is given by its upper or lower - triangle depending on IsUpperA. Contains matrix C. - Array whose indexes range within [0..N-1, 0..N-1]. - R - upper triangular or low triangular transformation matrix - which is used to obtain the eigenvectors of a given problem - as the product of eigenvectors of C (from the right) and - matrix R (from the left). If the matrix is upper - triangular, the elements below the main diagonal - are equal to 0 (and vice versa). Thus, we can perform - the multiplication without taking into account the - internal structure (which is an easier though less - effective way). - Array whose indexes range within [0..N-1, 0..N-1]. - IsUpperR - type of matrix R (upper or lower triangular). - -Result: - True, if the problem was reduced successfully. - False, if the error occurred during the Cholesky decomposition of - matrix B (the matrix is not positive-definite). - - -- ALGLIB -- - Copyright 1.28.2006 by Bochkanov Sergey -*************************************************************************/ -bool smatrixgevdreduce(real_2d_array &a, const ae_int_t n, const bool isuppera, const real_2d_array &b, const bool isupperb, const ae_int_t problemtype, real_2d_array &r, bool &isupperr, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::smatrixgevdreduce(const_cast(a.c_ptr()), n, isuppera, const_cast(b.c_ptr()), isupperb, problemtype, const_cast(r.c_ptr()), &isupperr, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_INVERSEUPDATE) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Inverse matrix update by the Sherman-Morrison formula - -The algorithm updates matrix A^-1 when adding a number to an element -of matrix A. - -Input parameters: - InvA - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - UpdRow - row where the element to be updated is stored. - UpdColumn - column where the element to be updated is stored. - UpdVal - a number to be added to the element. - - -Output parameters: - InvA - inverse of modified matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -void rmatrixinvupdatesimple(real_2d_array &inva, const ae_int_t n, const ae_int_t updrow, const ae_int_t updcolumn, const double updval, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixinvupdatesimple(const_cast(inva.c_ptr()), n, updrow, updcolumn, updval, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Inverse matrix update by the Sherman-Morrison formula - -The algorithm updates matrix A^-1 when adding a vector to a row -of matrix A. - -Input parameters: - InvA - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - UpdRow - the row of A whose vector V was added. - 0 <= Row <= N-1 - V - the vector to be added to a row. - Array whose index ranges within [0..N-1]. - -Output parameters: - InvA - inverse of modified matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -void rmatrixinvupdaterow(real_2d_array &inva, const ae_int_t n, const ae_int_t updrow, const real_1d_array &v, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixinvupdaterow(const_cast(inva.c_ptr()), n, updrow, const_cast(v.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Inverse matrix update by the Sherman-Morrison formula - -The algorithm updates matrix A^-1 when adding a vector to a column -of matrix A. - -Input parameters: - InvA - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - UpdColumn - the column of A whose vector U was added. - 0 <= UpdColumn <= N-1 - U - the vector to be added to a column. - Array whose index ranges within [0..N-1]. - -Output parameters: - InvA - inverse of modified matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -void rmatrixinvupdatecolumn(real_2d_array &inva, const ae_int_t n, const ae_int_t updcolumn, const real_1d_array &u, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixinvupdatecolumn(const_cast(inva.c_ptr()), n, updcolumn, const_cast(u.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Inverse matrix update by the Sherman-Morrison formula - -The algorithm computes the inverse of matrix A+u*v' by using the given matrix -A^-1 and the vectors u and v. - -Input parameters: - InvA - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - U - the vector modifying the matrix. - Array whose index ranges within [0..N-1]. - V - the vector modifying the matrix. - Array whose index ranges within [0..N-1]. - -Output parameters: - InvA - inverse of matrix A + u*v'. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -void rmatrixinvupdateuv(real_2d_array &inva, const ae_int_t n, const real_1d_array &u, const real_1d_array &v, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixinvupdateuv(const_cast(inva.c_ptr()), n, const_cast(u.c_ptr()), const_cast(v.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_MATDET) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Determinant calculation of the matrix given by its LU decomposition. - -Input parameters: - A - LU decomposition of the matrix (output of - RMatrixLU subroutine). - Pivots - table of permutations which were made during - the LU decomposition. - Output of RMatrixLU subroutine. - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -Result: matrix determinant. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -double rmatrixludet(const real_2d_array &a, const integer_1d_array &pivots, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::rmatrixludet(const_cast(a.c_ptr()), const_cast(pivots.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Determinant calculation of the matrix given by its LU decomposition. - -Input parameters: - A - LU decomposition of the matrix (output of - RMatrixLU subroutine). - Pivots - table of permutations which were made during - the LU decomposition. - Output of RMatrixLU subroutine. - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -Result: matrix determinant. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -double rmatrixludet(const real_2d_array &a, const integer_1d_array &pivots, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (a.rows()!=a.cols()) || (a.rows()!=pivots.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'rmatrixludet': looks like one of arguments has wrong size"); - n = a.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::rmatrixludet(const_cast(a.c_ptr()), const_cast(pivots.c_ptr()), n, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -Calculation of the determinant of a general matrix - -Input parameters: - A - matrix, array[0..N-1, 0..N-1] - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -Result: determinant of matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -double rmatrixdet(const real_2d_array &a, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::rmatrixdet(const_cast(a.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Calculation of the determinant of a general matrix - -Input parameters: - A - matrix, array[0..N-1, 0..N-1] - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -Result: determinant of matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -double rmatrixdet(const real_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (a.rows()!=a.cols())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'rmatrixdet': looks like one of arguments has wrong size"); - n = a.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::rmatrixdet(const_cast(a.c_ptr()), n, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -Determinant calculation of the matrix given by its LU decomposition. - -Input parameters: - A - LU decomposition of the matrix (output of - RMatrixLU subroutine). - Pivots - table of permutations which were made during - the LU decomposition. - Output of RMatrixLU subroutine. - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -Result: matrix determinant. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -alglib::complex cmatrixludet(const complex_2d_array &a, const integer_1d_array &pivots, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_complex result = alglib_impl::cmatrixludet(const_cast(a.c_ptr()), const_cast(pivots.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Determinant calculation of the matrix given by its LU decomposition. - -Input parameters: - A - LU decomposition of the matrix (output of - RMatrixLU subroutine). - Pivots - table of permutations which were made during - the LU decomposition. - Output of RMatrixLU subroutine. - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -Result: matrix determinant. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -alglib::complex cmatrixludet(const complex_2d_array &a, const integer_1d_array &pivots, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (a.rows()!=a.cols()) || (a.rows()!=pivots.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'cmatrixludet': looks like one of arguments has wrong size"); - n = a.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_complex result = alglib_impl::cmatrixludet(const_cast(a.c_ptr()), const_cast(pivots.c_ptr()), n, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -Calculation of the determinant of a general matrix - -Input parameters: - A - matrix, array[0..N-1, 0..N-1] - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -Result: determinant of matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -alglib::complex cmatrixdet(const complex_2d_array &a, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_complex result = alglib_impl::cmatrixdet(const_cast(a.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Calculation of the determinant of a general matrix - -Input parameters: - A - matrix, array[0..N-1, 0..N-1] - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -Result: determinant of matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -alglib::complex cmatrixdet(const complex_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (a.rows()!=a.cols())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'cmatrixdet': looks like one of arguments has wrong size"); - n = a.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_complex result = alglib_impl::cmatrixdet(const_cast(a.c_ptr()), n, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -Determinant calculation of the matrix given by the Cholesky decomposition. - -Input parameters: - A - Cholesky decomposition, - output of SMatrixCholesky subroutine. - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -As the determinant is equal to the product of squares of diagonal elements, -it's not necessary to specify which triangle - lower or upper - the matrix -is stored in. - -Result: - matrix determinant. - - -- ALGLIB -- - Copyright 2005-2008 by Bochkanov Sergey -*************************************************************************/ -double spdmatrixcholeskydet(const real_2d_array &a, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::spdmatrixcholeskydet(const_cast(a.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Determinant calculation of the matrix given by the Cholesky decomposition. - -Input parameters: - A - Cholesky decomposition, - output of SMatrixCholesky subroutine. - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -As the determinant is equal to the product of squares of diagonal elements, -it's not necessary to specify which triangle - lower or upper - the matrix -is stored in. - -Result: - matrix determinant. - - -- ALGLIB -- - Copyright 2005-2008 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -double spdmatrixcholeskydet(const real_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (a.rows()!=a.cols())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spdmatrixcholeskydet': looks like one of arguments has wrong size"); - n = a.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::spdmatrixcholeskydet(const_cast(a.c_ptr()), n, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -Determinant calculation of the symmetric positive definite matrix. - -Input parameters: - A - matrix. Array with elements [0..N-1, 0..N-1]. - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - IsUpper - (optional) storage type: - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, both lower and upper triangles must be - filled. - -Result: - determinant of matrix A. - If matrix A is not positive definite, exception is thrown. - - -- ALGLIB -- - Copyright 2005-2008 by Bochkanov Sergey -*************************************************************************/ -double spdmatrixdet(const real_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::spdmatrixdet(const_cast(a.c_ptr()), n, isupper, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Determinant calculation of the symmetric positive definite matrix. - -Input parameters: - A - matrix. Array with elements [0..N-1, 0..N-1]. - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - IsUpper - (optional) storage type: - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, both lower and upper triangles must be - filled. - -Result: - determinant of matrix A. - If matrix A is not positive definite, exception is thrown. - - -- ALGLIB -- - Copyright 2005-2008 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -double spdmatrixdet(const real_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - bool isupper; - if( (a.rows()!=a.cols())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spdmatrixdet': looks like one of arguments has wrong size"); - if( !alglib_impl::ae_is_symmetric(const_cast(a.c_ptr())) ) - _ALGLIB_CPP_EXCEPTION("'a' parameter is not symmetric matrix"); - n = a.rows(); - isupper = false; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::spdmatrixdet(const_cast(a.c_ptr()), n, isupper, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF COMPUTATIONAL CORE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_SPARSE) || !defined(AE_PARTIAL_BUILD) -static double sparse_desiredloadfactor = 0.66; -static double sparse_maxloadfactor = 0.75; -static double sparse_growfactor = 2.00; -static ae_int_t sparse_additional = 10; -static ae_int_t sparse_linalgswitch = 16; -static ae_int_t sparse_hash(ae_int_t i, - ae_int_t j, - ae_int_t tabsize, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_ABLAS) || !defined(AE_PARTIAL_BUILD) -static ae_int_t ablas_blas2minvendorkernelsize = 8; -static void ablas_ablasinternalsplitlength(ae_int_t n, - ae_int_t nb, - ae_int_t* n1, - ae_int_t* n2, - ae_state *_state); -static void ablas_cmatrixrighttrsm2(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state); -static void ablas_cmatrixlefttrsm2(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state); -static void ablas_rmatrixrighttrsm2(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state); -static void ablas_rmatrixlefttrsm2(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state); -static void ablas_cmatrixherk2(ae_int_t n, - ae_int_t k, - double alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state); -static void ablas_rmatrixsyrk2(ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state); -static void ablas_cmatrixgemmrec(ae_int_t m, - ae_int_t n, - ae_int_t k, - ae_complex alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Complex */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - ae_complex beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state); -ae_bool _trypexec_ablas_cmatrixgemmrec(ae_int_t m, - ae_int_t n, - ae_int_t k, - ae_complex alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Complex */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - ae_complex beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, ae_state *_state); -static void ablas_rmatrixgemmrec(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state); -ae_bool _trypexec_ablas_rmatrixgemmrec(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, ae_state *_state); - - -#endif -#if defined(AE_COMPILE_DLU) || !defined(AE_PARTIAL_BUILD) -static void dlu_cmatrixlup2(/* Complex */ ae_matrix* a, - ae_int_t offs, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - /* Complex */ ae_vector* tmp, - ae_state *_state); -static void dlu_rmatrixlup2(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - /* Real */ ae_vector* tmp, - ae_state *_state); -static void dlu_cmatrixplu2(/* Complex */ ae_matrix* a, - ae_int_t offs, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - /* Complex */ ae_vector* tmp, - ae_state *_state); -static void dlu_rmatrixplu2(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - /* Real */ ae_vector* tmp, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_SPTRF) || !defined(AE_PARTIAL_BUILD) -static double sptrf_densebnd = 0.10; -static ae_int_t sptrf_slswidth = 8; -static void sptrf_sluv2list1init(ae_int_t n, - sluv2list1matrix* a, - ae_state *_state); -static void sptrf_sluv2list1swap(sluv2list1matrix* a, - ae_int_t i, - ae_int_t j, - ae_state *_state); -static void sptrf_sluv2list1dropsequence(sluv2list1matrix* a, - ae_int_t i, - ae_state *_state); -static void sptrf_sluv2list1appendsequencetomatrix(sluv2list1matrix* a, - ae_int_t src, - ae_bool hasdiagonal, - double d, - ae_int_t nzmax, - sparsematrix* s, - ae_int_t dst, - ae_state *_state); -static void sptrf_sluv2list1pushsparsevector(sluv2list1matrix* a, - /* Integer */ ae_vector* si, - /* Real */ ae_vector* sv, - ae_int_t nz, - ae_state *_state); -static void sptrf_densetrailinit(sluv2densetrail* d, - ae_int_t n, - ae_state *_state); -static void sptrf_densetrailappendcolumn(sluv2densetrail* d, - /* Real */ ae_vector* x, - ae_int_t id, - ae_state *_state); -static void sptrf_sparsetrailinit(sparsematrix* s, - sluv2sparsetrail* a, - ae_state *_state); -static ae_bool sptrf_sparsetrailfindpivot(sluv2sparsetrail* a, - ae_int_t pivottype, - ae_int_t* ipiv, - ae_int_t* jpiv, - ae_state *_state); -static void sptrf_sparsetrailpivotout(sluv2sparsetrail* a, - ae_int_t ipiv, - ae_int_t jpiv, - double* uu, - /* Integer */ ae_vector* v0i, - /* Real */ ae_vector* v0r, - ae_int_t* nz0, - /* Integer */ ae_vector* v1i, - /* Real */ ae_vector* v1r, - ae_int_t* nz1, - ae_state *_state); -static void sptrf_sparsetraildensify(sluv2sparsetrail* a, - ae_int_t i1, - sluv2list1matrix* bupper, - sluv2densetrail* dtrail, - ae_state *_state); -static void sptrf_sparsetrailupdate(sluv2sparsetrail* a, - /* Integer */ ae_vector* v0i, - /* Real */ ae_vector* v0r, - ae_int_t nz0, - /* Integer */ ae_vector* v1i, - /* Real */ ae_vector* v1r, - ae_int_t nz1, - sluv2list1matrix* bupper, - sluv2densetrail* dtrail, - ae_bool densificationsupported, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_AMDORDERING) || !defined(AE_PARTIAL_BUILD) -static ae_int_t amdordering_knsheadersize = 2; -static ae_int_t amdordering_llmentrysize = 6; -static void amdordering_nsinitemptyslow(ae_int_t n, - amdnset* sa, - ae_state *_state); -static void amdordering_nscopy(amdnset* ssrc, - amdnset* sdst, - ae_state *_state); -static void amdordering_nsaddelement(amdnset* sa, - ae_int_t k, - ae_state *_state); -static void amdordering_nsaddkth(amdnset* sa, - amdknset* src, - ae_int_t k, - ae_state *_state); -static void amdordering_nssubtractkth(amdnset* sa, - amdknset* src, - ae_int_t k, - ae_state *_state); -static void amdordering_nsclear(amdnset* sa, ae_state *_state); -static ae_int_t amdordering_nscount(amdnset* sa, ae_state *_state); -static ae_int_t amdordering_nscountnotkth(amdnset* sa, - amdknset* src, - ae_int_t k, - ae_state *_state); -static ae_int_t amdordering_nscountandkth(amdnset* sa, - amdknset* src, - ae_int_t k, - ae_state *_state); -static ae_bool amdordering_nsequal(amdnset* s0, - amdnset* s1, - ae_state *_state); -static void amdordering_nsstartenumeration(amdnset* sa, ae_state *_state); -static ae_bool amdordering_nsenumerate(amdnset* sa, - ae_int_t* i, - ae_state *_state); -static void amdordering_knscompressstorage(amdknset* sa, ae_state *_state); -static void amdordering_knsreallocate(amdknset* sa, - ae_int_t setidx, - ae_int_t newallocated, - ae_state *_state); -static void amdordering_knsinit(ae_int_t k, - ae_int_t n, - ae_int_t kprealloc, - amdknset* sa, - ae_state *_state); -static void amdordering_knsinitfroma(sparsematrix* a, - ae_int_t n, - amdknset* sa, - ae_state *_state); -static void amdordering_knsstartenumeration(amdknset* sa, - ae_int_t i, - ae_state *_state); -static ae_bool amdordering_knsenumerate(amdknset* sa, - ae_int_t* i, - ae_state *_state); -static void amdordering_knsdirectaccess(amdknset* sa, - ae_int_t k, - ae_int_t* idxbegin, - ae_int_t* idxend, - ae_state *_state); -static void amdordering_knsaddnewelement(amdknset* sa, - ae_int_t i, - ae_int_t k, - ae_state *_state); -static void amdordering_knssubtract1(amdknset* sa, - ae_int_t i, - amdnset* src, - ae_state *_state); -static void amdordering_knsaddkthdistinct(amdknset* sa, - ae_int_t i, - amdknset* src, - ae_int_t k, - ae_state *_state); -static ae_int_t amdordering_knscountkth(amdknset* s0, - ae_int_t k, - ae_state *_state); -static ae_int_t amdordering_knscountnotkth(amdknset* s0, - ae_int_t i, - amdknset* s1, - ae_int_t k, - ae_state *_state); -static ae_int_t amdordering_knscountandkth(amdknset* s0, - ae_int_t i, - amdknset* s1, - ae_int_t k, - ae_state *_state); -static ae_int_t amdordering_knssumkth(amdknset* s0, - ae_int_t i, - ae_state *_state); -static void amdordering_knsclearkthnoreclaim(amdknset* sa, - ae_int_t k, - ae_state *_state); -static void amdordering_knsclearkthreclaim(amdknset* sa, - ae_int_t k, - ae_state *_state); -static void amdordering_mtxinit(ae_int_t n, - amdllmatrix* a, - ae_state *_state); -static void amdordering_mtxaddcolumnto(amdllmatrix* a, - ae_int_t j, - amdnset* s, - ae_state *_state); -static void amdordering_mtxinsertnewelement(amdllmatrix* a, - ae_int_t i, - ae_int_t j, - ae_state *_state); -static ae_int_t amdordering_mtxcountcolumn(amdllmatrix* a, - ae_int_t j, - ae_state *_state); -static void amdordering_mtxclearx(amdllmatrix* a, - ae_int_t k, - ae_bool iscol, - ae_state *_state); -static void amdordering_mtxclearcolumn(amdllmatrix* a, - ae_int_t j, - ae_state *_state); -static void amdordering_mtxclearrow(amdllmatrix* a, - ae_int_t j, - ae_state *_state); -static void amdordering_vtxinit(sparsematrix* a, - ae_int_t n, - ae_bool checkexactdegrees, - amdvertexset* s, - ae_state *_state); -static void amdordering_vtxremovevertex(amdvertexset* s, - ae_int_t p, - ae_state *_state); -static ae_int_t amdordering_vtxgetapprox(amdvertexset* s, - ae_int_t p, - ae_state *_state); -static ae_int_t amdordering_vtxgetexact(amdvertexset* s, - ae_int_t p, - ae_state *_state); -static ae_int_t amdordering_vtxgetapproxmindegree(amdvertexset* s, - ae_state *_state); -static void amdordering_vtxupdateapproximatedegree(amdvertexset* s, - ae_int_t p, - ae_int_t dnew, - ae_state *_state); -static void amdordering_vtxupdateexactdegree(amdvertexset* s, - ae_int_t p, - ae_int_t d, - ae_state *_state); -static void amdordering_amdselectpivotelement(amdbuffer* buf, - ae_int_t k, - ae_int_t* p, - ae_int_t* nodesize, - ae_state *_state); -static void amdordering_amdcomputelp(amdbuffer* buf, - ae_int_t p, - ae_state *_state); -static void amdordering_amdmasselimination(amdbuffer* buf, - ae_int_t p, - ae_int_t k, - ae_state *_state); -static void amdordering_amddetectsupernodes(amdbuffer* buf, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_SPCHOL) || !defined(AE_PARTIAL_BUILD) -static ae_int_t spchol_maxsupernode = 4; -static double spchol_maxmergeinefficiency = 0.25; -static ae_int_t spchol_smallfakestolerance = 2; -static ae_int_t spchol_maxfastkernel = 4; -static ae_bool spchol_relaxedsupernodes = ae_true; -static void spchol_generatedbgpermutation(sparsematrix* a, - ae_int_t n, - /* Integer */ ae_vector* perm, - /* Integer */ ae_vector* invperm, - ae_state *_state); -static void spchol_buildetree(sparsematrix* a, - ae_int_t n, - /* Integer */ ae_vector* parent, - /* Integer */ ae_vector* supernodalpermutation, - /* Integer */ ae_vector* invsupernodalpermutation, - /* Integer */ ae_vector* trawparentofrawnode, - /* Integer */ ae_vector* trawparentofreorderednode, - /* Integer */ ae_vector* ttmp, - /* Boolean */ ae_vector* tflagarray, - ae_state *_state); -static void spchol_createsupernodalstructure(sparsematrix* at, - /* Integer */ ae_vector* parent, - ae_int_t n, - spcholanalysis* analysis, - /* Integer */ ae_vector* node2supernode, - /* Integer */ ae_vector* tchildrenr, - /* Integer */ ae_vector* tchildreni, - /* Integer */ ae_vector* tparentnodeofsupernode, - /* Integer */ ae_vector* tfakenonzeros, - /* Integer */ ae_vector* ttmp0, - /* Boolean */ ae_vector* tflagarray, - ae_state *_state); -static void spchol_analyzesupernodaldependencies(spcholanalysis* analysis, - sparsematrix* rawa, - /* Integer */ ae_vector* node2supernode, - ae_int_t n, - /* Integer */ ae_vector* ttmp0, - /* Integer */ ae_vector* ttmp1, - /* Boolean */ ae_vector* tflagarray, - ae_state *_state); -static void spchol_extractmatrix(spcholanalysis* analysis, - /* Integer */ ae_vector* offsets, - /* Integer */ ae_vector* strides, - /* Real */ ae_vector* rowstorage, - /* Real */ ae_vector* diagd, - ae_int_t n, - sparsematrix* a, - /* Real */ ae_vector* d, - /* Integer */ ae_vector* p, - /* Integer */ ae_vector* tmpp, - ae_state *_state); -static void spchol_topologicalpermutation(sparsematrix* a, - /* Integer */ ae_vector* p, - sparsematrix* b, - ae_state *_state); -static ae_int_t spchol_computenonzeropattern(sparsematrix* wrkat, - ae_int_t columnidx, - ae_int_t n, - /* Integer */ ae_vector* superrowridx, - /* Integer */ ae_vector* superrowidx, - ae_int_t nsuper, - /* Integer */ ae_vector* childrennodesr, - /* Integer */ ae_vector* childrennodesi, - /* Integer */ ae_vector* node2supernode, - /* Boolean */ ae_vector* truearray, - /* Integer */ ae_vector* tmp0, - ae_state *_state); -static ae_int_t spchol_updatesupernode(spcholanalysis* analysis, - ae_int_t sidx, - ae_int_t cols0, - ae_int_t cols1, - ae_int_t offss, - /* Integer */ ae_vector* raw2smap, - ae_int_t uidx, - ae_int_t wrkrow, - /* Real */ ae_vector* diagd, - ae_int_t offsd, - ae_state *_state); -static ae_bool spchol_factorizesupernode(spcholanalysis* analysis, - ae_int_t sidx, - ae_state *_state); -static ae_int_t spchol_recommendedstridefor(ae_int_t rowsize, - ae_state *_state); -static ae_int_t spchol_alignpositioninarray(ae_int_t offs, - ae_state *_state); -static ae_bool spchol_updatekernel4444(/* Real */ ae_vector* rowstorage, - ae_int_t offss, - ae_int_t offsu, - ae_int_t uheight, - /* Real */ ae_vector* diagd, - ae_int_t offsd, - /* Integer */ ae_vector* raw2smap, - /* Integer */ ae_vector* superrowidx, - ae_int_t urbase, - ae_state *_state); -static ae_bool spchol_updatekernelabc4(/* Real */ ae_vector* rowstorage, - ae_int_t offss, - ae_int_t twidth, - ae_int_t offsu, - ae_int_t uheight, - ae_int_t urank, - ae_int_t urowstride, - ae_int_t uwidth, - /* Real */ ae_vector* diagd, - ae_int_t offsd, - /* Integer */ ae_vector* raw2smap, - /* Integer */ ae_vector* superrowidx, - ae_int_t urbase, - ae_state *_state); -static ae_bool spchol_updatekernelrank1(/* Real */ ae_vector* rowstorage, - ae_int_t offss, - ae_int_t twidth, - ae_int_t trowstride, - ae_int_t offsu, - ae_int_t uheight, - ae_int_t uwidth, - /* Real */ ae_vector* diagd, - ae_int_t offsd, - /* Integer */ ae_vector* raw2smap, - /* Integer */ ae_vector* superrowidx, - ae_int_t urbase, - ae_state *_state); -static ae_bool spchol_updatekernelrank2(/* Real */ ae_vector* rowstorage, - ae_int_t offss, - ae_int_t twidth, - ae_int_t trowstride, - ae_int_t offsu, - ae_int_t uheight, - ae_int_t uwidth, - /* Real */ ae_vector* diagd, - ae_int_t offsd, - /* Integer */ ae_vector* raw2smap, - /* Integer */ ae_vector* superrowidx, - ae_int_t urbase, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_MATGEN) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_TRFAC) || !defined(AE_PARTIAL_BUILD) -static ae_bool trfac_hpdmatrixcholeskyrec(/* Complex */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* tmp, - ae_state *_state); -static ae_bool trfac_hpdmatrixcholesky2(/* Complex */ ae_matrix* aaa, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* tmp, - ae_state *_state); -static ae_bool trfac_spdmatrixcholesky2(/* Real */ ae_matrix* aaa, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* tmp, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_RCOND) || !defined(AE_PARTIAL_BUILD) -static void rcond_rmatrixrcondtrinternal(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - ae_bool onenorm, - double anorm, - double* rc, - ae_state *_state); -static void rcond_cmatrixrcondtrinternal(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - ae_bool onenorm, - double anorm, - double* rc, - ae_state *_state); -static void rcond_spdmatrixrcondcholeskyinternal(/* Real */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - ae_bool isnormprovided, - double anorm, - double* rc, - ae_state *_state); -static void rcond_hpdmatrixrcondcholeskyinternal(/* Complex */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - ae_bool isnormprovided, - double anorm, - double* rc, - ae_state *_state); -static void rcond_rmatrixrcondluinternal(/* Real */ ae_matrix* lua, - ae_int_t n, - ae_bool onenorm, - ae_bool isanormprovided, - double anorm, - double* rc, - ae_state *_state); -static void rcond_cmatrixrcondluinternal(/* Complex */ ae_matrix* lua, - ae_int_t n, - ae_bool onenorm, - ae_bool isanormprovided, - double anorm, - double* rc, - ae_state *_state); -static void rcond_rmatrixestimatenorm(ae_int_t n, - /* Real */ ae_vector* v, - /* Real */ ae_vector* x, - /* Integer */ ae_vector* isgn, - double* est, - ae_int_t* kase, - ae_state *_state); -static void rcond_cmatrixestimatenorm(ae_int_t n, - /* Complex */ ae_vector* v, - /* Complex */ ae_vector* x, - double* est, - ae_int_t* kase, - /* Integer */ ae_vector* isave, - /* Real */ ae_vector* rsave, - ae_state *_state); -static double rcond_internalcomplexrcondscsum1(/* Complex */ ae_vector* x, - ae_int_t n, - ae_state *_state); -static ae_int_t rcond_internalcomplexrcondicmax1(/* Complex */ ae_vector* x, - ae_int_t n, - ae_state *_state); -static void rcond_internalcomplexrcondsaveall(/* Integer */ ae_vector* isave, - /* Real */ ae_vector* rsave, - ae_int_t* i, - ae_int_t* iter, - ae_int_t* j, - ae_int_t* jlast, - ae_int_t* jump, - double* absxi, - double* altsgn, - double* estold, - double* temp, - ae_state *_state); -static void rcond_internalcomplexrcondloadall(/* Integer */ ae_vector* isave, - /* Real */ ae_vector* rsave, - ae_int_t* i, - ae_int_t* iter, - ae_int_t* j, - ae_int_t* jlast, - ae_int_t* jump, - double* absxi, - double* altsgn, - double* estold, - double* temp, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_MATINV) || !defined(AE_PARTIAL_BUILD) -static void matinv_rmatrixtrinverserec(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - /* Real */ ae_vector* tmp, - sinteger* info, - ae_state *_state); -ae_bool _trypexec_matinv_rmatrixtrinverserec(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - /* Real */ ae_vector* tmp, - sinteger* info, ae_state *_state); -static void matinv_cmatrixtrinverserec(/* Complex */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - /* Complex */ ae_vector* tmp, - sinteger* info, - ae_state *_state); -ae_bool _trypexec_matinv_cmatrixtrinverserec(/* Complex */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - /* Complex */ ae_vector* tmp, - sinteger* info, ae_state *_state); -static void matinv_rmatrixluinverserec(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - /* Real */ ae_vector* work, - sinteger* info, - matinvreport* rep, - ae_state *_state); -ae_bool _trypexec_matinv_rmatrixluinverserec(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - /* Real */ ae_vector* work, - sinteger* info, - matinvreport* rep, ae_state *_state); -static void matinv_cmatrixluinverserec(/* Complex */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - /* Complex */ ae_vector* work, - sinteger* ssinfo, - matinvreport* rep, - ae_state *_state); -ae_bool _trypexec_matinv_cmatrixluinverserec(/* Complex */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - /* Complex */ ae_vector* work, - sinteger* ssinfo, - matinvreport* rep, ae_state *_state); -static void matinv_hpdmatrixcholeskyinverserec(/* Complex */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* tmp, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_ORTFAC) || !defined(AE_PARTIAL_BUILD) -static void ortfac_cmatrixqrbasecase(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_vector* work, - /* Complex */ ae_vector* t, - /* Complex */ ae_vector* tau, - ae_state *_state); -static void ortfac_cmatrixlqbasecase(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_vector* work, - /* Complex */ ae_vector* t, - /* Complex */ ae_vector* tau, - ae_state *_state); -static void ortfac_rmatrixblockreflector(/* Real */ ae_matrix* a, - /* Real */ ae_vector* tau, - ae_bool columnwisea, - ae_int_t lengtha, - ae_int_t blocksize, - /* Real */ ae_matrix* t, - /* Real */ ae_vector* work, - ae_state *_state); -static void ortfac_cmatrixblockreflector(/* Complex */ ae_matrix* a, - /* Complex */ ae_vector* tau, - ae_bool columnwisea, - ae_int_t lengtha, - ae_int_t blocksize, - /* Complex */ ae_matrix* t, - /* Complex */ ae_vector* work, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_FBLS) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_BDSVD) || !defined(AE_PARTIAL_BUILD) -static ae_bool bdsvd_bidiagonalsvddecompositioninternal(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_bool isupper, - ae_bool isfractionalaccuracyrequired, - /* Real */ ae_matrix* uu, - ae_int_t ustart, - ae_int_t nru, - /* Real */ ae_matrix* c, - ae_int_t cstart, - ae_int_t ncc, - /* Real */ ae_matrix* vt, - ae_int_t vstart, - ae_int_t ncvt, - ae_state *_state); -static double bdsvd_extsignbdsqr(double a, double b, ae_state *_state); -static void bdsvd_svd2x2(double f, - double g, - double h, - double* ssmin, - double* ssmax, - ae_state *_state); -static void bdsvd_svdv2x2(double f, - double g, - double h, - double* ssmin, - double* ssmax, - double* snr, - double* csr, - double* snl, - double* csl, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_SVD) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_NORMESTIMATOR) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_HSSCHUR) || !defined(AE_PARTIAL_BUILD) -static void hsschur_internalauxschur(ae_bool wantt, - ae_bool wantz, - ae_int_t n, - ae_int_t ilo, - ae_int_t ihi, - /* Real */ ae_matrix* h, - /* Real */ ae_vector* wr, - /* Real */ ae_vector* wi, - ae_int_t iloz, - ae_int_t ihiz, - /* Real */ ae_matrix* z, - /* Real */ ae_vector* work, - /* Real */ ae_vector* workv3, - /* Real */ ae_vector* workc1, - /* Real */ ae_vector* works1, - ae_int_t* info, - ae_state *_state); -static void hsschur_aux2x2schur(double* a, - double* b, - double* c, - double* d, - double* rt1r, - double* rt1i, - double* rt2r, - double* rt2i, - double* cs, - double* sn, - ae_state *_state); -static double hsschur_extschursign(double a, double b, ae_state *_state); -static ae_int_t hsschur_extschursigntoone(double b, ae_state *_state); - - -#endif -#if defined(AE_COMPILE_EVD) || !defined(AE_PARTIAL_BUILD) -static ae_int_t evd_stepswithintol = 2; -static void evd_clearrfields(eigsubspacestate* state, ae_state *_state); -static ae_bool evd_tridiagonalevd(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_int_t zneeded, - /* Real */ ae_matrix* z, - ae_state *_state); -static void evd_tdevde2(double a, - double b, - double c, - double* rt1, - double* rt2, - ae_state *_state); -static void evd_tdevdev2(double a, - double b, - double c, - double* rt1, - double* rt2, - double* cs1, - double* sn1, - ae_state *_state); -static double evd_tdevdpythag(double a, double b, ae_state *_state); -static double evd_tdevdextsign(double a, double b, ae_state *_state); -static ae_bool evd_internalbisectioneigenvalues(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_int_t irange, - ae_int_t iorder, - double vl, - double vu, - ae_int_t il, - ae_int_t iu, - double abstol, - /* Real */ ae_vector* w, - ae_int_t* m, - ae_int_t* nsplit, - /* Integer */ ae_vector* iblock, - /* Integer */ ae_vector* isplit, - ae_int_t* errorcode, - ae_state *_state); -static void evd_internaldstein(ae_int_t n, - /* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t m, - /* Real */ ae_vector* w, - /* Integer */ ae_vector* iblock, - /* Integer */ ae_vector* isplit, - /* Real */ ae_matrix* z, - /* Integer */ ae_vector* ifail, - ae_int_t* info, - ae_state *_state); -static void evd_tdininternaldlagtf(ae_int_t n, - /* Real */ ae_vector* a, - double lambdav, - /* Real */ ae_vector* b, - /* Real */ ae_vector* c, - double tol, - /* Real */ ae_vector* d, - /* Integer */ ae_vector* iin, - ae_int_t* info, - ae_state *_state); -static void evd_tdininternaldlagts(ae_int_t n, - /* Real */ ae_vector* a, - /* Real */ ae_vector* b, - /* Real */ ae_vector* c, - /* Real */ ae_vector* d, - /* Integer */ ae_vector* iin, - /* Real */ ae_vector* y, - double* tol, - ae_int_t* info, - ae_state *_state); -static void evd_internaldlaebz(ae_int_t ijob, - ae_int_t nitmax, - ae_int_t n, - ae_int_t mmax, - ae_int_t minp, - double abstol, - double reltol, - double pivmin, - /* Real */ ae_vector* d, - /* Real */ ae_vector* e, - /* Real */ ae_vector* e2, - /* Integer */ ae_vector* nval, - /* Real */ ae_matrix* ab, - /* Real */ ae_vector* c, - ae_int_t* mout, - /* Integer */ ae_matrix* nab, - /* Real */ ae_vector* work, - /* Integer */ ae_vector* iwork, - ae_int_t* info, - ae_state *_state); -static void evd_rmatrixinternaltrevc(/* Real */ ae_matrix* t, - ae_int_t n, - ae_int_t side, - ae_int_t howmny, - /* Boolean */ ae_vector* vselect, - /* Real */ ae_matrix* vl, - /* Real */ ae_matrix* vr, - ae_int_t* m, - ae_int_t* info, - ae_state *_state); -static void evd_internaltrevc(/* Real */ ae_matrix* t, - ae_int_t n, - ae_int_t side, - ae_int_t howmny, - /* Boolean */ ae_vector* vselect, - /* Real */ ae_matrix* vl, - /* Real */ ae_matrix* vr, - ae_int_t* m, - ae_int_t* info, - ae_state *_state); -static void evd_internalhsevdlaln2(ae_bool ltrans, - ae_int_t na, - ae_int_t nw, - double smin, - double ca, - /* Real */ ae_matrix* a, - double d1, - double d2, - /* Real */ ae_matrix* b, - double wr, - double wi, - /* Boolean */ ae_vector* rswap4, - /* Boolean */ ae_vector* zswap4, - /* Integer */ ae_matrix* ipivot44, - /* Real */ ae_vector* civ4, - /* Real */ ae_vector* crv4, - /* Real */ ae_matrix* x, - double* scl, - double* xnorm, - ae_int_t* info, - ae_state *_state); -static void evd_internalhsevdladiv(double a, - double b, - double c, - double d, - double* p, - double* q, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_SCHUR) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_SPDGEVD) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_INVERSEUPDATE) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_MATDET) || !defined(AE_PARTIAL_BUILD) - - -#endif - -#if defined(AE_COMPILE_SPARSE) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function creates sparse matrix in a Hash-Table format. - -This function creates Hast-Table matrix, which can be converted to CRS -format after its initialization is over. Typical usage scenario for a -sparse matrix is: -1. creation in a Hash-Table format -2. insertion of the matrix elements -3. conversion to the CRS representation -4. matrix is passed to some linear algebra algorithm - -Some information about different matrix formats can be found below, in -the "NOTES" section. - -INPUT PARAMETERS - M - number of rows in a matrix, M>=1 - N - number of columns in a matrix, N>=1 - K - K>=0, expected number of non-zero elements in a matrix. - K can be inexact approximation, can be less than actual - number of elements (table will grow when needed) or - even zero). - It is important to understand that although hash-table - may grow automatically, it is better to provide good - estimate of data size. - -OUTPUT PARAMETERS - S - sparse M*N matrix in Hash-Table representation. - All elements of the matrix are zero. - -NOTE 1 - -Hash-tables use memory inefficiently, and they have to keep some amount -of the "spare memory" in order to have good performance. Hash table for -matrix with K non-zero elements will need C*K*(8+2*sizeof(int)) bytes, -where C is a small constant, about 1.5-2 in magnitude. - -CRS storage, from the other side, is more memory-efficient, and needs -just K*(8+sizeof(int))+M*sizeof(int) bytes, where M is a number of rows -in a matrix. - -When you convert from the Hash-Table to CRS representation, all unneeded -memory will be freed. - -NOTE 2 - -Comments of SparseMatrix structure outline information about different -sparse storage formats. We recommend you to read them before starting to -use ALGLIB sparse matrices. - -NOTE 3 - -This function completely overwrites S with new sparse matrix. Previously -allocated storage is NOT reused. If you want to reuse already allocated -memory, call SparseCreateBuf function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsecreate(ae_int_t m, - ae_int_t n, - ae_int_t k, - sparsematrix* s, - ae_state *_state) -{ - - _sparsematrix_clear(s); - - sparsecreatebuf(m, n, k, s, _state); -} - - -/************************************************************************* -This version of SparseCreate function creates sparse matrix in Hash-Table -format, reusing previously allocated storage as much as possible. Read -comments for SparseCreate() for more information. - -INPUT PARAMETERS - M - number of rows in a matrix, M>=1 - N - number of columns in a matrix, N>=1 - K - K>=0, expected number of non-zero elements in a matrix. - K can be inexact approximation, can be less than actual - number of elements (table will grow when needed) or - even zero). - It is important to understand that although hash-table - may grow automatically, it is better to provide good - estimate of data size. - S - SparseMatrix structure which MAY contain some already - allocated storage. - -OUTPUT PARAMETERS - S - sparse M*N matrix in Hash-Table representation. - All elements of the matrix are zero. - Previously allocated storage is reused, if its size - is compatible with expected number of non-zeros K. - - -- ALGLIB PROJECT -- - Copyright 14.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatebuf(ae_int_t m, - ae_int_t n, - ae_int_t k, - sparsematrix* s, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(m>0, "SparseCreateBuf: M<=0", _state); - ae_assert(n>0, "SparseCreateBuf: N<=0", _state); - ae_assert(k>=0, "SparseCreateBuf: K<0", _state); - - /* - * Hash-table size is max(existing_size,requested_size) - * - * NOTE: it is important to use ALL available memory for hash table - * because it is impossible to efficiently reallocate table - * without temporary storage. So, if we want table with up to - * 1.000.000 elements, we have to create such table from the - * very beginning. Otherwise, the very idea of memory reuse - * will be compromised. - */ - s->tablesize = ae_round(k/sparse_desiredloadfactor+sparse_additional, _state); - rvectorsetlengthatleast(&s->vals, s->tablesize, _state); - s->tablesize = s->vals.cnt; - - /* - * Initialize other fields - */ - s->matrixtype = 0; - s->m = m; - s->n = n; - s->nfree = s->tablesize; - ivectorsetlengthatleast(&s->idx, 2*s->tablesize, _state); - for(i=0; i<=s->tablesize-1; i++) - { - s->idx.ptr.p_int[2*i] = -1; - } -} - - -/************************************************************************* -This function creates sparse matrix in a CRS format (expert function for -situations when you are running out of memory). - -This function creates CRS matrix. Typical usage scenario for a CRS matrix -is: -1. creation (you have to tell number of non-zero elements at each row at - this moment) -2. insertion of the matrix elements (row by row, from left to right) -3. matrix is passed to some linear algebra algorithm - -This function is a memory-efficient alternative to SparseCreate(), but it -is more complex because it requires you to know in advance how large your -matrix is. Some information about different matrix formats can be found -in comments on SparseMatrix structure. We recommend you to read them -before starting to use ALGLIB sparse matrices.. - -INPUT PARAMETERS - M - number of rows in a matrix, M>=1 - N - number of columns in a matrix, N>=1 - NER - number of elements at each row, array[M], NER[I]>=0 - -OUTPUT PARAMETERS - S - sparse M*N matrix in CRS representation. - You have to fill ALL non-zero elements by calling - SparseSet() BEFORE you try to use this matrix. - -NOTE: this function completely overwrites S with new sparse matrix. - Previously allocated storage is NOT reused. If you want to reuse - already allocated memory, call SparseCreateCRSBuf function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatecrs(ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* ner, - sparsematrix* s, - ae_state *_state) -{ - ae_int_t i; - - _sparsematrix_clear(s); - - ae_assert(m>0, "SparseCreateCRS: M<=0", _state); - ae_assert(n>0, "SparseCreateCRS: N<=0", _state); - ae_assert(ner->cnt>=m, "SparseCreateCRS: Length(NER)ptr.p_int[i]>=0, "SparseCreateCRS: NER[] contains negative elements", _state); - } - sparsecreatecrsbuf(m, n, ner, s, _state); -} - - -/************************************************************************* -This function creates sparse matrix in a CRS format (expert function for -situations when you are running out of memory). This version of CRS -matrix creation function may reuse memory already allocated in S. - -This function creates CRS matrix. Typical usage scenario for a CRS matrix -is: -1. creation (you have to tell number of non-zero elements at each row at - this moment) -2. insertion of the matrix elements (row by row, from left to right) -3. matrix is passed to some linear algebra algorithm - -This function is a memory-efficient alternative to SparseCreate(), but it -is more complex because it requires you to know in advance how large your -matrix is. Some information about different matrix formats can be found -in comments on SparseMatrix structure. We recommend you to read them -before starting to use ALGLIB sparse matrices.. - -INPUT PARAMETERS - M - number of rows in a matrix, M>=1 - N - number of columns in a matrix, N>=1 - NER - number of elements at each row, array[M], NER[I]>=0 - S - sparse matrix structure with possibly preallocated - memory. - -OUTPUT PARAMETERS - S - sparse M*N matrix in CRS representation. - You have to fill ALL non-zero elements by calling - SparseSet() BEFORE you try to use this matrix. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatecrsbuf(ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* ner, - sparsematrix* s, - ae_state *_state) -{ - ae_int_t i; - ae_int_t noe; - - - ae_assert(m>0, "SparseCreateCRSBuf: M<=0", _state); - ae_assert(n>0, "SparseCreateCRSBuf: N<=0", _state); - ae_assert(ner->cnt>=m, "SparseCreateCRSBuf: Length(NER)matrixtype = 1; - s->ninitialized = 0; - s->m = m; - s->n = n; - ivectorsetlengthatleast(&s->ridx, s->m+1, _state); - s->ridx.ptr.p_int[0] = 0; - for(i=0; i<=s->m-1; i++) - { - ae_assert(ner->ptr.p_int[i]>=0, "SparseCreateCRSBuf: NER[] contains negative elements", _state); - noe = noe+ner->ptr.p_int[i]; - s->ridx.ptr.p_int[i+1] = s->ridx.ptr.p_int[i]+ner->ptr.p_int[i]; - } - rvectorsetlengthatleast(&s->vals, noe, _state); - ivectorsetlengthatleast(&s->idx, noe, _state); - if( noe==0 ) - { - sparseinitduidx(s, _state); - } -} - - -/************************************************************************* -This function creates sparse matrix in a SKS format (skyline storage -format). In most cases you do not need this function - CRS format better -suits most use cases. - -INPUT PARAMETERS - M, N - number of rows(M) and columns (N) in a matrix: - * M=N (as for now, ALGLIB supports only square SKS) - * N>=1 - * M>=1 - D - "bottom" bandwidths, array[M], D[I]>=0. - I-th element stores number of non-zeros at I-th row, - below the diagonal (diagonal itself is not included) - U - "top" bandwidths, array[N], U[I]>=0. - I-th element stores number of non-zeros at I-th row, - above the diagonal (diagonal itself is not included) - -OUTPUT PARAMETERS - S - sparse M*N matrix in SKS representation. - All elements are filled by zeros. - You may use sparseset() to change their values. - -NOTE: this function completely overwrites S with new sparse matrix. - Previously allocated storage is NOT reused. If you want to reuse - already allocated memory, call SparseCreateSKSBuf function. - - -- ALGLIB PROJECT -- - Copyright 13.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatesks(ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* d, - /* Integer */ ae_vector* u, - sparsematrix* s, - ae_state *_state) -{ - ae_int_t i; - - _sparsematrix_clear(s); - - ae_assert(m>0, "SparseCreateSKS: M<=0", _state); - ae_assert(n>0, "SparseCreateSKS: N<=0", _state); - ae_assert(m==n, "SparseCreateSKS: M<>N", _state); - ae_assert(d->cnt>=m, "SparseCreateSKS: Length(D)cnt>=n, "SparseCreateSKS: Length(U)ptr.p_int[i]>=0, "SparseCreateSKS: D[] contains negative elements", _state); - ae_assert(d->ptr.p_int[i]<=i, "SparseCreateSKS: D[I]>I for some I", _state); - } - for(i=0; i<=n-1; i++) - { - ae_assert(u->ptr.p_int[i]>=0, "SparseCreateSKS: U[] contains negative elements", _state); - ae_assert(u->ptr.p_int[i]<=i, "SparseCreateSKS: U[I]>I for some I", _state); - } - sparsecreatesksbuf(m, n, d, u, s, _state); -} - - -/************************************************************************* -This is "buffered" version of SparseCreateSKS() which reuses memory -previously allocated in S (of course, memory is reallocated if needed). - -This function creates sparse matrix in a SKS format (skyline storage -format). In most cases you do not need this function - CRS format better -suits most use cases. - -INPUT PARAMETERS - M, N - number of rows(M) and columns (N) in a matrix: - * M=N (as for now, ALGLIB supports only square SKS) - * N>=1 - * M>=1 - D - "bottom" bandwidths, array[M], 0<=D[I]<=I. - I-th element stores number of non-zeros at I-th row, - below the diagonal (diagonal itself is not included) - U - "top" bandwidths, array[N], 0<=U[I]<=I. - I-th element stores number of non-zeros at I-th row, - above the diagonal (diagonal itself is not included) - -OUTPUT PARAMETERS - S - sparse M*N matrix in SKS representation. - All elements are filled by zeros. - You may use sparseset() to change their values. - - -- ALGLIB PROJECT -- - Copyright 13.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatesksbuf(ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* d, - /* Integer */ ae_vector* u, - sparsematrix* s, - ae_state *_state) -{ - ae_int_t i; - ae_int_t minmn; - ae_int_t nz; - ae_int_t mxd; - ae_int_t mxu; - - - ae_assert(m>0, "SparseCreateSKSBuf: M<=0", _state); - ae_assert(n>0, "SparseCreateSKSBuf: N<=0", _state); - ae_assert(m==n, "SparseCreateSKSBuf: M<>N", _state); - ae_assert(d->cnt>=m, "SparseCreateSKSBuf: Length(D)cnt>=n, "SparseCreateSKSBuf: Length(U)ptr.p_int[i]>=0, "SparseCreateSKSBuf: D[] contains negative elements", _state); - ae_assert(d->ptr.p_int[i]<=i, "SparseCreateSKSBuf: D[I]>I for some I", _state); - } - for(i=0; i<=n-1; i++) - { - ae_assert(u->ptr.p_int[i]>=0, "SparseCreateSKSBuf: U[] contains negative elements", _state); - ae_assert(u->ptr.p_int[i]<=i, "SparseCreateSKSBuf: U[I]>I for some I", _state); - } - minmn = ae_minint(m, n, _state); - s->matrixtype = 2; - s->ninitialized = 0; - s->m = m; - s->n = n; - ivectorsetlengthatleast(&s->ridx, minmn+1, _state); - s->ridx.ptr.p_int[0] = 0; - nz = 0; - for(i=0; i<=minmn-1; i++) - { - nz = nz+1+d->ptr.p_int[i]+u->ptr.p_int[i]; - s->ridx.ptr.p_int[i+1] = s->ridx.ptr.p_int[i]+1+d->ptr.p_int[i]+u->ptr.p_int[i]; - } - rvectorsetlengthatleast(&s->vals, nz, _state); - for(i=0; i<=nz-1; i++) - { - s->vals.ptr.p_double[i] = 0.0; - } - ivectorsetlengthatleast(&s->didx, m+1, _state); - mxd = 0; - for(i=0; i<=m-1; i++) - { - s->didx.ptr.p_int[i] = d->ptr.p_int[i]; - mxd = ae_maxint(mxd, d->ptr.p_int[i], _state); - } - s->didx.ptr.p_int[m] = mxd; - ivectorsetlengthatleast(&s->uidx, n+1, _state); - mxu = 0; - for(i=0; i<=n-1; i++) - { - s->uidx.ptr.p_int[i] = u->ptr.p_int[i]; - mxu = ae_maxint(mxu, u->ptr.p_int[i], _state); - } - s->uidx.ptr.p_int[n] = mxu; -} - - -/************************************************************************* -This function creates sparse matrix in a SKS format (skyline storage -format). Unlike more general sparsecreatesks(), this function creates -sparse matrix with constant bandwidth. - -You may want to use this function instead of sparsecreatesks() when your -matrix has constant or nearly-constant bandwidth, and you want to -simplify source code. - -INPUT PARAMETERS - M, N - number of rows(M) and columns (N) in a matrix: - * M=N (as for now, ALGLIB supports only square SKS) - * N>=1 - * M>=1 - BW - matrix bandwidth, BW>=0 - -OUTPUT PARAMETERS - S - sparse M*N matrix in SKS representation. - All elements are filled by zeros. - You may use sparseset() to change their values. - -NOTE: this function completely overwrites S with new sparse matrix. - Previously allocated storage is NOT reused. If you want to reuse - already allocated memory, call sparsecreatesksbandbuf function. - - -- ALGLIB PROJECT -- - Copyright 25.12.2017 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatesksband(ae_int_t m, - ae_int_t n, - ae_int_t bw, - sparsematrix* s, - ae_state *_state) -{ - - _sparsematrix_clear(s); - - ae_assert(m>0, "SparseCreateSKSBand: M<=0", _state); - ae_assert(n>0, "SparseCreateSKSBand: N<=0", _state); - ae_assert(bw>=0, "SparseCreateSKSBand: BW<0", _state); - ae_assert(m==n, "SparseCreateSKSBand: M!=N", _state); - sparsecreatesksbandbuf(m, n, bw, s, _state); -} - - -/************************************************************************* -This is "buffered" version of sparsecreatesksband() which reuses memory -previously allocated in S (of course, memory is reallocated if needed). - -You may want to use this function instead of sparsecreatesksbuf() when -your matrix has constant or nearly-constant bandwidth, and you want to -simplify source code. - -INPUT PARAMETERS - M, N - number of rows(M) and columns (N) in a matrix: - * M=N (as for now, ALGLIB supports only square SKS) - * N>=1 - * M>=1 - BW - bandwidth, BW>=0 - -OUTPUT PARAMETERS - S - sparse M*N matrix in SKS representation. - All elements are filled by zeros. - You may use sparseset() to change their values. - - -- ALGLIB PROJECT -- - Copyright 13.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatesksbandbuf(ae_int_t m, - ae_int_t n, - ae_int_t bw, - sparsematrix* s, - ae_state *_state) -{ - ae_int_t i; - ae_int_t minmn; - ae_int_t nz; - ae_int_t mxd; - ae_int_t mxu; - ae_int_t dui; - - - ae_assert(m>0, "SparseCreateSKSBandBuf: M<=0", _state); - ae_assert(n>0, "SparseCreateSKSBandBuf: N<=0", _state); - ae_assert(m==n, "SparseCreateSKSBandBuf: M!=N", _state); - ae_assert(bw>=0, "SparseCreateSKSBandBuf: BW<0", _state); - minmn = ae_minint(m, n, _state); - s->matrixtype = 2; - s->ninitialized = 0; - s->m = m; - s->n = n; - ivectorsetlengthatleast(&s->ridx, minmn+1, _state); - s->ridx.ptr.p_int[0] = 0; - nz = 0; - for(i=0; i<=minmn-1; i++) - { - dui = ae_minint(i, bw, _state); - nz = nz+1+2*dui; - s->ridx.ptr.p_int[i+1] = s->ridx.ptr.p_int[i]+1+2*dui; - } - rvectorsetlengthatleast(&s->vals, nz, _state); - for(i=0; i<=nz-1; i++) - { - s->vals.ptr.p_double[i] = 0.0; - } - ivectorsetlengthatleast(&s->didx, m+1, _state); - mxd = 0; - for(i=0; i<=m-1; i++) - { - dui = ae_minint(i, bw, _state); - s->didx.ptr.p_int[i] = dui; - mxd = ae_maxint(mxd, dui, _state); - } - s->didx.ptr.p_int[m] = mxd; - ivectorsetlengthatleast(&s->uidx, n+1, _state); - mxu = 0; - for(i=0; i<=n-1; i++) - { - dui = ae_minint(i, bw, _state); - s->uidx.ptr.p_int[i] = dui; - mxu = ae_maxint(mxu, dui, _state); - } - s->uidx.ptr.p_int[n] = mxu; -} - - -/************************************************************************* -This function copies S0 to S1. -This function completely deallocates memory owned by S1 before creating a -copy of S0. If you want to reuse memory, use SparseCopyBuf. - -NOTE: this function does not verify its arguments, it just copies all -fields of the structure. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsecopy(sparsematrix* s0, sparsematrix* s1, ae_state *_state) -{ - - _sparsematrix_clear(s1); - - sparsecopybuf(s0, s1, _state); -} - - -/************************************************************************* -This function copies S0 to S1. -Memory already allocated in S1 is reused as much as possible. - -NOTE: this function does not verify its arguments, it just copies all -fields of the structure. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsecopybuf(sparsematrix* s0, sparsematrix* s1, ae_state *_state) -{ - ae_int_t l; - ae_int_t i; - - - s1->matrixtype = s0->matrixtype; - s1->m = s0->m; - s1->n = s0->n; - s1->nfree = s0->nfree; - s1->ninitialized = s0->ninitialized; - s1->tablesize = s0->tablesize; - - /* - * Initialization for arrays - */ - l = s0->vals.cnt; - rvectorsetlengthatleast(&s1->vals, l, _state); - for(i=0; i<=l-1; i++) - { - s1->vals.ptr.p_double[i] = s0->vals.ptr.p_double[i]; - } - l = s0->ridx.cnt; - ivectorsetlengthatleast(&s1->ridx, l, _state); - for(i=0; i<=l-1; i++) - { - s1->ridx.ptr.p_int[i] = s0->ridx.ptr.p_int[i]; - } - l = s0->idx.cnt; - ivectorsetlengthatleast(&s1->idx, l, _state); - for(i=0; i<=l-1; i++) - { - s1->idx.ptr.p_int[i] = s0->idx.ptr.p_int[i]; - } - - /* - * Initalization for CRS-parameters - */ - l = s0->uidx.cnt; - ivectorsetlengthatleast(&s1->uidx, l, _state); - for(i=0; i<=l-1; i++) - { - s1->uidx.ptr.p_int[i] = s0->uidx.ptr.p_int[i]; - } - l = s0->didx.cnt; - ivectorsetlengthatleast(&s1->didx, l, _state); - for(i=0; i<=l-1; i++) - { - s1->didx.ptr.p_int[i] = s0->didx.ptr.p_int[i]; - } -} - - -/************************************************************************* -This function efficiently swaps contents of S0 and S1. - - -- ALGLIB PROJECT -- - Copyright 16.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparseswap(sparsematrix* s0, sparsematrix* s1, ae_state *_state) -{ - - - swapi(&s1->matrixtype, &s0->matrixtype, _state); - swapi(&s1->m, &s0->m, _state); - swapi(&s1->n, &s0->n, _state); - swapi(&s1->nfree, &s0->nfree, _state); - swapi(&s1->ninitialized, &s0->ninitialized, _state); - swapi(&s1->tablesize, &s0->tablesize, _state); - ae_swap_vectors(&s1->vals, &s0->vals); - ae_swap_vectors(&s1->ridx, &s0->ridx); - ae_swap_vectors(&s1->idx, &s0->idx); - ae_swap_vectors(&s1->uidx, &s0->uidx); - ae_swap_vectors(&s1->didx, &s0->didx); -} - - -/************************************************************************* -This function adds value to S[i,j] - element of the sparse matrix. Matrix -must be in a Hash-Table mode. - -In case S[i,j] already exists in the table, V i added to its value. In -case S[i,j] is non-existent, it is inserted in the table. Table -automatically grows when necessary. - -INPUT PARAMETERS - S - sparse M*N matrix in Hash-Table representation. - Exception will be thrown for CRS matrix. - I - row index of the element to modify, 0<=Imatrixtype==0, "SparseAdd: matrix must be in the Hash-Table mode to do this operation", _state); - ae_assert(i>=0, "SparseAdd: I<0", _state); - ae_assert(im, "SparseAdd: I>=M", _state); - ae_assert(j>=0, "SparseAdd: J<0", _state); - ae_assert(jn, "SparseAdd: J>=N", _state); - ae_assert(ae_isfinite(v, _state), "SparseAdd: V is not finite number", _state); - if( ae_fp_eq(v,(double)(0)) ) - { - return; - } - tcode = -1; - k = s->tablesize; - if( ae_fp_greater_eq((1-sparse_maxloadfactor)*k,(double)(s->nfree)) ) - { - sparseresizematrix(s, _state); - k = s->tablesize; - } - hashcode = sparse_hash(i, j, k, _state); - for(;;) - { - if( s->idx.ptr.p_int[2*hashcode]==-1 ) - { - if( tcode!=-1 ) - { - hashcode = tcode; - } - s->vals.ptr.p_double[hashcode] = v; - s->idx.ptr.p_int[2*hashcode] = i; - s->idx.ptr.p_int[2*hashcode+1] = j; - if( tcode==-1 ) - { - s->nfree = s->nfree-1; - } - return; - } - else - { - if( s->idx.ptr.p_int[2*hashcode]==i&&s->idx.ptr.p_int[2*hashcode+1]==j ) - { - s->vals.ptr.p_double[hashcode] = s->vals.ptr.p_double[hashcode]+v; - if( ae_fp_eq(s->vals.ptr.p_double[hashcode],(double)(0)) ) - { - s->idx.ptr.p_int[2*hashcode] = -2; - } - return; - } - - /* - * Is it deleted element? - */ - if( tcode==-1&&s->idx.ptr.p_int[2*hashcode]==-2 ) - { - tcode = hashcode; - } - - /* - * Next step - */ - hashcode = (hashcode+1)%k; - } - } -} - - -/************************************************************************* -This function modifies S[i,j] - element of the sparse matrix. - -For Hash-based storage format: -* this function can be called at any moment - during matrix initialization - or later -* new value can be zero or non-zero. In case new value of S[i,j] is zero, - this element is deleted from the table. -* this function has no effect when called with zero V for non-existent - element. - -For CRS-bases storage format: -* this function can be called ONLY DURING MATRIX INITIALIZATION -* zero values are stored in the matrix similarly to non-zero ones -* elements must be initialized in correct order - from top row to bottom, - within row - from left to right. - -For SKS storage: -* this function can be called at any moment - during matrix initialization - or later -* zero values are stored in the matrix similarly to non-zero ones -* this function CAN NOT be called for non-existent (outside of the band - specified during SKS matrix creation) elements. Say, if you created SKS - matrix with bandwidth=2 and tried to call sparseset(s,0,10,VAL), an - exception will be generated. - -INPUT PARAMETERS - S - sparse M*N matrix in Hash-Table, SKS or CRS format. - I - row index of the element to modify, 0<=Imatrixtype==0||s->matrixtype==1)||s->matrixtype==2, "SparseSet: unsupported matrix storage format", _state); - ae_assert(i>=0, "SparseSet: I<0", _state); - ae_assert(im, "SparseSet: I>=M", _state); - ae_assert(j>=0, "SparseSet: J<0", _state); - ae_assert(jn, "SparseSet: J>=N", _state); - ae_assert(ae_isfinite(v, _state), "SparseSet: V is not finite number", _state); - - /* - * Hash-table matrix - */ - if( s->matrixtype==0 ) - { - tcode = -1; - k = s->tablesize; - if( ae_fp_greater_eq((1-sparse_maxloadfactor)*k,(double)(s->nfree)) ) - { - sparseresizematrix(s, _state); - k = s->tablesize; - } - hashcode = sparse_hash(i, j, k, _state); - for(;;) - { - if( s->idx.ptr.p_int[2*hashcode]==-1 ) - { - if( ae_fp_neq(v,(double)(0)) ) - { - if( tcode!=-1 ) - { - hashcode = tcode; - } - s->vals.ptr.p_double[hashcode] = v; - s->idx.ptr.p_int[2*hashcode] = i; - s->idx.ptr.p_int[2*hashcode+1] = j; - if( tcode==-1 ) - { - s->nfree = s->nfree-1; - } - } - return; - } - else - { - if( s->idx.ptr.p_int[2*hashcode]==i&&s->idx.ptr.p_int[2*hashcode+1]==j ) - { - if( ae_fp_eq(v,(double)(0)) ) - { - s->idx.ptr.p_int[2*hashcode] = -2; - } - else - { - s->vals.ptr.p_double[hashcode] = v; - } - return; - } - if( tcode==-1&&s->idx.ptr.p_int[2*hashcode]==-2 ) - { - tcode = hashcode; - } - - /* - * Next step - */ - hashcode = (hashcode+1)%k; - } - } - } - - /* - * CRS matrix - */ - if( s->matrixtype==1 ) - { - ae_assert(s->ridx.ptr.p_int[i]<=s->ninitialized, "SparseSet: too few initialized elements at some row (you have promised more when called SparceCreateCRS)", _state); - ae_assert(s->ridx.ptr.p_int[i+1]>s->ninitialized, "SparseSet: too many initialized elements at some row (you have promised less when called SparceCreateCRS)", _state); - ae_assert(s->ninitialized==s->ridx.ptr.p_int[i]||s->idx.ptr.p_int[s->ninitialized-1]vals.ptr.p_double[s->ninitialized] = v; - s->idx.ptr.p_int[s->ninitialized] = j; - s->ninitialized = s->ninitialized+1; - - /* - * If matrix has been created then - * initiale 'S.UIdx' and 'S.DIdx' - */ - if( s->ninitialized==s->ridx.ptr.p_int[s->m] ) - { - sparseinitduidx(s, _state); - } - return; - } - - /* - * SKS matrix - */ - if( s->matrixtype==2 ) - { - b = sparserewriteexisting(s, i, j, v, _state); - ae_assert(b, "SparseSet: an attempt to initialize out-of-band element of the SKS matrix", _state); - return; - } -} - - -/************************************************************************* -This function returns S[i,j] - element of the sparse matrix. Matrix can -be in any mode (Hash-Table, CRS, SKS), but this function is less efficient -for CRS matrices. Hash-Table and SKS matrices can find element in O(1) -time, while CRS matrices need O(log(RS)) time, where RS is an number of -non-zero elements in a row. - -INPUT PARAMETERS - S - sparse M*N matrix - I - row index of the element to modify, 0<=I=0, "SparseGet: I<0", _state); - ae_assert(im, "SparseGet: I>=M", _state); - ae_assert(j>=0, "SparseGet: J<0", _state); - ae_assert(jn, "SparseGet: J>=N", _state); - result = 0.0; - if( s->matrixtype==0 ) - { - - /* - * Hash-based storage - */ - result = (double)(0); - k = s->tablesize; - hashcode = sparse_hash(i, j, k, _state); - for(;;) - { - if( s->idx.ptr.p_int[2*hashcode]==-1 ) - { - return result; - } - if( s->idx.ptr.p_int[2*hashcode]==i&&s->idx.ptr.p_int[2*hashcode+1]==j ) - { - result = s->vals.ptr.p_double[hashcode]; - return result; - } - hashcode = (hashcode+1)%k; - } - } - if( s->matrixtype==1 ) - { - - /* - * CRS - */ - ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseGet: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state); - k0 = s->ridx.ptr.p_int[i]; - k1 = s->ridx.ptr.p_int[i+1]-1; - result = (double)(0); - while(k0<=k1) - { - k = (k0+k1)/2; - if( s->idx.ptr.p_int[k]==j ) - { - result = s->vals.ptr.p_double[k]; - return result; - } - if( s->idx.ptr.p_int[k]matrixtype==2 ) - { - - /* - * SKS - */ - ae_assert(s->m==s->n, "SparseGet: non-square SKS matrix not supported", _state); - result = (double)(0); - if( i==j ) - { - - /* - * Return diagonal element - */ - result = s->vals.ptr.p_double[s->ridx.ptr.p_int[i]+s->didx.ptr.p_int[i]]; - return result; - } - if( jdidx.ptr.p_int[i]; - if( i-j<=k ) - { - result = s->vals.ptr.p_double[s->ridx.ptr.p_int[i]+k+j-i]; - } - } - else - { - - /* - * Return superdiagonal element at J-th "skyline block" - */ - k = s->uidx.ptr.p_int[j]; - if( j-i<=k ) - { - result = s->vals.ptr.p_double[s->ridx.ptr.p_int[j+1]-(j-i)]; - } - return result; - } - return result; - } - ae_assert(ae_false, "SparseGet: unexpected matrix type", _state); - return result; -} - - -/************************************************************************* -This function checks whether S[i,j] is present in the sparse matrix. It -returns True even for elements that are numerically zero (but still -have place allocated for them). - -The matrix can be in any mode (Hash-Table, CRS, SKS), but this function -is less efficient for CRS matrices. Hash-Table and SKS matrices can find -element in O(1) time, while CRS matrices need O(log(RS)) time, where RS -is an number of non-zero elements in a row. - -INPUT PARAMETERS - S - sparse M*N matrix - I - row index of the element to modify, 0<=I=0, "SparseExists: I<0", _state); - ae_assert(im, "SparseExists: I>=M", _state); - ae_assert(j>=0, "SparseExists: J<0", _state); - ae_assert(jn, "SparseExists: J>=N", _state); - result = ae_false; - if( s->matrixtype==0 ) - { - - /* - * Hash-based storage - */ - k = s->tablesize; - hashcode = sparse_hash(i, j, k, _state); - for(;;) - { - if( s->idx.ptr.p_int[2*hashcode]==-1 ) - { - return result; - } - if( s->idx.ptr.p_int[2*hashcode]==i&&s->idx.ptr.p_int[2*hashcode+1]==j ) - { - result = ae_true; - return result; - } - hashcode = (hashcode+1)%k; - } - } - if( s->matrixtype==1 ) - { - - /* - * CRS - */ - ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseExists: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state); - k0 = s->ridx.ptr.p_int[i]; - k1 = s->ridx.ptr.p_int[i+1]-1; - while(k0<=k1) - { - k = (k0+k1)/2; - if( s->idx.ptr.p_int[k]==j ) - { - result = ae_true; - return result; - } - if( s->idx.ptr.p_int[k]matrixtype==2 ) - { - - /* - * SKS - */ - ae_assert(s->m==s->n, "SparseExists: non-square SKS matrix not supported", _state); - if( i==j ) - { - - /* - * Return diagonal element - */ - result = ae_true; - return result; - } - if( jdidx.ptr.p_int[i] ) - { - result = ae_true; - } - } - else - { - - /* - * Return superdiagonal element at J-th "skyline block" - */ - if( j-i<=s->uidx.ptr.p_int[j] ) - { - result = ae_true; - } - return result; - } - return result; - } - ae_assert(ae_false, "SparseExists: unexpected matrix type", _state); - return result; -} - - -/************************************************************************* -This function returns I-th diagonal element of the sparse matrix. - -Matrix can be in any mode (Hash-Table or CRS storage), but this function -is most efficient for CRS matrices - it requires less than 50 CPU cycles -to extract diagonal element. For Hash-Table matrices we still have O(1) -query time, but function is many times slower. - -INPUT PARAMETERS - S - sparse M*N matrix in Hash-Table representation. - Exception will be thrown for CRS matrix. - I - index of the element to modify, 0<=I=0, "SparseGetDiagonal: I<0", _state); - ae_assert(im, "SparseGetDiagonal: I>=M", _state); - ae_assert(in, "SparseGetDiagonal: I>=N", _state); - result = (double)(0); - if( s->matrixtype==0 ) - { - result = sparseget(s, i, i, _state); - return result; - } - if( s->matrixtype==1 ) - { - if( s->didx.ptr.p_int[i]!=s->uidx.ptr.p_int[i] ) - { - result = s->vals.ptr.p_double[s->didx.ptr.p_int[i]]; - } - return result; - } - if( s->matrixtype==2 ) - { - ae_assert(s->m==s->n, "SparseGetDiagonal: non-square SKS matrix not supported", _state); - result = s->vals.ptr.p_double[s->ridx.ptr.p_int[i]+s->didx.ptr.p_int[i]]; - return result; - } - ae_assert(ae_false, "SparseGetDiagonal: unexpected matrix type", _state); - return result; -} - - -/************************************************************************* -This function calculates matrix-vector product S*x. Matrix S must be -stored in CRS or SKS format (exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse M*N matrix in CRS or SKS format. - X - array[N], input vector. For performance reasons we - make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - Y - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - Y - array[M], S*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsemv(sparsematrix* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - double tval; - double v; - double vv; - ae_int_t i; - ae_int_t j; - ae_int_t lt; - ae_int_t rt; - ae_int_t lt1; - ae_int_t rt1; - ae_int_t n; - ae_int_t m; - ae_int_t d; - ae_int_t u; - ae_int_t ri; - ae_int_t ri1; - - - ae_assert(x->cnt>=s->n, "SparseMV: length(X)matrixtype==1||s->matrixtype==2, "SparseMV: incorrect matrix type (convert your matrix to CRS/SKS)", _state); - rvectorsetlengthatleast(y, s->m, _state); - n = s->n; - m = s->m; - if( s->matrixtype==1 ) - { - - /* - * CRS format. - * Perform integrity check. - */ - ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseMV: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state); - - /* - * Try vendor kernels - */ - if( sparsegemvcrsmkl(0, s->m, s->n, 1.0, &s->vals, &s->idx, &s->ridx, x, 0, 0.0, y, 0, _state) ) - { - return; - } - - /* - * Our own implementation - */ - for(i=0; i<=m-1; i++) - { - tval = (double)(0); - lt = s->ridx.ptr.p_int[i]; - rt = s->ridx.ptr.p_int[i+1]-1; - for(j=lt; j<=rt; j++) - { - tval = tval+x->ptr.p_double[s->idx.ptr.p_int[j]]*s->vals.ptr.p_double[j]; - } - y->ptr.p_double[i] = tval; - } - return; - } - if( s->matrixtype==2 ) - { - - /* - * SKS format - */ - ae_assert(s->m==s->n, "SparseMV: non-square SKS matrices are not supported", _state); - for(i=0; i<=n-1; i++) - { - ri = s->ridx.ptr.p_int[i]; - ri1 = s->ridx.ptr.p_int[i+1]; - d = s->didx.ptr.p_int[i]; - u = s->uidx.ptr.p_int[i]; - v = s->vals.ptr.p_double[ri+d]*x->ptr.p_double[i]; - if( d>0 ) - { - lt = ri; - rt = ri+d-1; - lt1 = i-d; - rt1 = i-1; - vv = ae_v_dotproduct(&s->vals.ptr.p_double[lt], 1, &x->ptr.p_double[lt1], 1, ae_v_len(lt,rt)); - v = v+vv; - } - y->ptr.p_double[i] = v; - if( u>0 ) - { - lt = ri1-u; - rt = ri1-1; - lt1 = i-u; - rt1 = i-1; - v = x->ptr.p_double[i]; - ae_v_addd(&y->ptr.p_double[lt1], 1, &s->vals.ptr.p_double[lt], 1, ae_v_len(lt1,rt1), v); - } - } - return; - } -} - - -/************************************************************************* -This function calculates matrix-vector product S^T*x. Matrix S must be -stored in CRS or SKS format (exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse M*N matrix in CRS or SKS format. - X - array[M], input vector. For performance reasons we - make only quick checks - we check that array size is - at least M, but we do not check for NAN's or INF's. - Y - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - Y - array[N], S^T*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsemtv(sparsematrix* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t lt; - ae_int_t rt; - ae_int_t ct; - ae_int_t lt1; - ae_int_t rt1; - double v; - double vv; - ae_int_t n; - ae_int_t m; - ae_int_t ri; - ae_int_t ri1; - ae_int_t d; - ae_int_t u; - - - ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseMTV: incorrect matrix type (convert your matrix to CRS/SKS)", _state); - ae_assert(x->cnt>=s->m, "SparseMTV: Length(X)n; - m = s->m; - rvectorsetlengthatleast(y, n, _state); - for(i=0; i<=n-1; i++) - { - y->ptr.p_double[i] = (double)(0); - } - if( s->matrixtype==1 ) - { - - /* - * CRS format - * Perform integrity check. - */ - ae_assert(s->ninitialized==s->ridx.ptr.p_int[m], "SparseMTV: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state); - - /* - * Try vendor kernels - */ - if( sparsegemvcrsmkl(1, s->m, s->n, 1.0, &s->vals, &s->idx, &s->ridx, x, 0, 0.0, y, 0, _state) ) - { - return; - } - - /* - * Our own implementation - */ - for(i=0; i<=m-1; i++) - { - lt = s->ridx.ptr.p_int[i]; - rt = s->ridx.ptr.p_int[i+1]; - v = x->ptr.p_double[i]; - for(j=lt; j<=rt-1; j++) - { - ct = s->idx.ptr.p_int[j]; - y->ptr.p_double[ct] = y->ptr.p_double[ct]+v*s->vals.ptr.p_double[j]; - } - } - return; - } - if( s->matrixtype==2 ) - { - - /* - * SKS format - */ - ae_assert(s->m==s->n, "SparseMV: non-square SKS matrices are not supported", _state); - for(i=0; i<=n-1; i++) - { - ri = s->ridx.ptr.p_int[i]; - ri1 = s->ridx.ptr.p_int[i+1]; - d = s->didx.ptr.p_int[i]; - u = s->uidx.ptr.p_int[i]; - if( d>0 ) - { - lt = ri; - rt = ri+d-1; - lt1 = i-d; - rt1 = i-1; - v = x->ptr.p_double[i]; - ae_v_addd(&y->ptr.p_double[lt1], 1, &s->vals.ptr.p_double[lt], 1, ae_v_len(lt1,rt1), v); - } - v = s->vals.ptr.p_double[ri+d]*x->ptr.p_double[i]; - if( u>0 ) - { - lt = ri1-u; - rt = ri1-1; - lt1 = i-u; - rt1 = i-1; - vv = ae_v_dotproduct(&s->vals.ptr.p_double[lt], 1, &x->ptr.p_double[lt1], 1, ae_v_len(lt,rt)); - v = v+vv; - } - y->ptr.p_double[i] = v; - } - return; - } -} - - -/************************************************************************* -This function calculates generalized sparse matrix-vector product - - y := alpha*op(S)*x + beta*y - -Matrix S must be stored in CRS or SKS format (exception will be thrown -otherwise). op(S) can be either S or S^T. - -NOTE: this function expects Y to be large enough to store result. No - automatic preallocation happens for smaller arrays. - -INPUT PARAMETERS - S - sparse matrix in CRS or SKS format. - Alpha - source coefficient - OpS - operation type: - * OpS=0 => op(S) = S - * OpS=1 => op(S) = S^T - X - input vector, must have at least Cols(op(S))+IX elements - IX - subvector offset - Beta - destination coefficient - Y - preallocated output array, must have at least Rows(op(S))+IY elements - IY - subvector offset - -OUTPUT PARAMETERS - Y - elements [IY...IY+Rows(op(S))-1] are replaced by result, - other elements are not modified - -HANDLING OF SPECIAL CASES: -* below M=Rows(op(S)) and N=Cols(op(S)). Although current ALGLIB version - does not allow you to create zero-sized sparse matrices, internally - ALGLIB can deal with such matrices. So, comments for M or N equal to - zero are for internal use only. -* if M=0, then subroutine does nothing. It does not even touch arrays. -* if N=0 or Alpha=0.0, then: - * if Beta=0, then Y is filled by zeros. S and X are not referenced at - all. Initial values of Y are ignored (we do not multiply Y by zero, - we just rewrite it by zeros) - * if Beta<>0, then Y is replaced by Beta*Y -* if M>0, N>0, Alpha<>0, but Beta=0, then Y is replaced by alpha*op(S)*x - initial state of Y is ignored (rewritten without initial multiplication - by zeros). - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 10.12.2019 by Bochkanov Sergey -*************************************************************************/ -void sparsegemv(sparsematrix* s, - double alpha, - ae_int_t ops, - /* Real */ ae_vector* x, - ae_int_t ix, - double beta, - /* Real */ ae_vector* y, - ae_int_t iy, - ae_state *_state) -{ - ae_int_t opm; - ae_int_t opn; - ae_int_t rawm; - ae_int_t rawn; - ae_int_t i; - ae_int_t j; - double tval; - ae_int_t lt; - ae_int_t rt; - ae_int_t ct; - ae_int_t d; - ae_int_t u; - ae_int_t ri; - ae_int_t ri1; - double v; - double vv; - ae_int_t lt1; - ae_int_t rt1; - - - ae_assert(ops==0||ops==1, "SparseGEMV: incorrect OpS", _state); - ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseGEMV: incorrect matrix type (convert your matrix to CRS/SKS)", _state); - if( ops==0 ) - { - opm = s->m; - opn = s->n; - } - else - { - opm = s->n; - opn = s->m; - } - ae_assert(opm>=0&&opn>=0, "SparseGEMV: op(S) has negative size", _state); - ae_assert(opn==0||x->cnt+ix>=opn, "SparseGEMV: X is too short", _state); - ae_assert(opm==0||y->cnt+iy>=opm, "SparseGEMV: X is too short", _state); - rawm = s->m; - rawn = s->n; - - /* - * Quick exit strategies - */ - if( opm==0 ) - { - return; - } - if( ae_fp_neq(beta,(double)(0)) ) - { - for(i=0; i<=opm-1; i++) - { - y->ptr.p_double[iy+i] = beta*y->ptr.p_double[iy+i]; - } - } - else - { - for(i=0; i<=opm-1; i++) - { - y->ptr.p_double[iy+i] = 0.0; - } - } - if( opn==0||ae_fp_eq(alpha,(double)(0)) ) - { - return; - } - - /* - * Now we have OpM>=1, OpN>=1, Alpha<>0 - */ - if( ops==0 ) - { - - /* - * Compute generalized product y := alpha*S*x + beta*y - * (with "beta*y" part already computed). - */ - if( s->matrixtype==1 ) - { - - /* - * CRS format. - * Perform integrity check. - */ - ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseGEMV: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state); - - /* - * Try vendor kernels - */ - if( sparsegemvcrsmkl(0, s->m, s->n, alpha, &s->vals, &s->idx, &s->ridx, x, ix, 1.0, y, iy, _state) ) - { - return; - } - - /* - * Our own implementation - */ - for(i=0; i<=rawm-1; i++) - { - tval = (double)(0); - lt = s->ridx.ptr.p_int[i]; - rt = s->ridx.ptr.p_int[i+1]-1; - for(j=lt; j<=rt; j++) - { - tval = tval+x->ptr.p_double[s->idx.ptr.p_int[j]+ix]*s->vals.ptr.p_double[j]; - } - y->ptr.p_double[i+iy] = alpha*tval+y->ptr.p_double[i+iy]; - } - return; - } - if( s->matrixtype==2 ) - { - - /* - * SKS format - */ - ae_assert(s->m==s->n, "SparseMV: non-square SKS matrices are not supported", _state); - for(i=0; i<=rawn-1; i++) - { - ri = s->ridx.ptr.p_int[i]; - ri1 = s->ridx.ptr.p_int[i+1]; - d = s->didx.ptr.p_int[i]; - u = s->uidx.ptr.p_int[i]; - v = s->vals.ptr.p_double[ri+d]*x->ptr.p_double[i+ix]; - if( d>0 ) - { - lt = ri; - rt = ri+d-1; - lt1 = i-d+ix; - rt1 = i-1+ix; - vv = ae_v_dotproduct(&s->vals.ptr.p_double[lt], 1, &x->ptr.p_double[lt1], 1, ae_v_len(lt,rt)); - v = v+vv; - } - y->ptr.p_double[i+iy] = alpha*v+y->ptr.p_double[i+iy]; - if( u>0 ) - { - lt = ri1-u; - rt = ri1-1; - lt1 = i-u+iy; - rt1 = i-1+iy; - v = alpha*x->ptr.p_double[i+ix]; - ae_v_addd(&y->ptr.p_double[lt1], 1, &s->vals.ptr.p_double[lt], 1, ae_v_len(lt1,rt1), v); - } - } - return; - } - } - else - { - - /* - * Compute generalized product y := alpha*S^T*x + beta*y - * (with "beta*y" part already computed). - */ - if( s->matrixtype==1 ) - { - - /* - * CRS format - * Perform integrity check. - */ - ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseGEMV: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state); - - /* - * Try vendor kernels - */ - if( sparsegemvcrsmkl(1, s->m, s->n, alpha, &s->vals, &s->idx, &s->ridx, x, ix, 1.0, y, iy, _state) ) - { - return; - } - - /* - * Our own implementation - */ - for(i=0; i<=rawm-1; i++) - { - lt = s->ridx.ptr.p_int[i]; - rt = s->ridx.ptr.p_int[i+1]; - v = alpha*x->ptr.p_double[i+ix]; - for(j=lt; j<=rt-1; j++) - { - ct = s->idx.ptr.p_int[j]+iy; - y->ptr.p_double[ct] = y->ptr.p_double[ct]+v*s->vals.ptr.p_double[j]; - } - } - return; - } - if( s->matrixtype==2 ) - { - - /* - * SKS format - */ - ae_assert(s->m==s->n, "SparseGEMV: non-square SKS matrices are not supported", _state); - for(i=0; i<=rawn-1; i++) - { - ri = s->ridx.ptr.p_int[i]; - ri1 = s->ridx.ptr.p_int[i+1]; - d = s->didx.ptr.p_int[i]; - u = s->uidx.ptr.p_int[i]; - if( d>0 ) - { - lt = ri; - rt = ri+d-1; - lt1 = i-d+iy; - rt1 = i-1+iy; - v = alpha*x->ptr.p_double[i+ix]; - ae_v_addd(&y->ptr.p_double[lt1], 1, &s->vals.ptr.p_double[lt], 1, ae_v_len(lt1,rt1), v); - } - v = alpha*s->vals.ptr.p_double[ri+d]*x->ptr.p_double[i+ix]; - if( u>0 ) - { - lt = ri1-u; - rt = ri1-1; - lt1 = i-u+ix; - rt1 = i-1+ix; - vv = ae_v_dotproduct(&s->vals.ptr.p_double[lt], 1, &x->ptr.p_double[lt1], 1, ae_v_len(lt,rt)); - v = v+alpha*vv; - } - y->ptr.p_double[i+iy] = v+y->ptr.p_double[i+iy]; - } - return; - } - } -} - - -/************************************************************************* -This function simultaneously calculates two matrix-vector products: - S*x and S^T*x. -S must be square (non-rectangular) matrix stored in CRS or SKS format -(exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse N*N matrix in CRS or SKS format. - X - array[N], input vector. For performance reasons we - make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - Y0 - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - Y1 - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - Y0 - array[N], S*x - Y1 - array[N], S^T*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsemv2(sparsematrix* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y0, - /* Real */ ae_vector* y1, - ae_state *_state) -{ - ae_int_t l; - double tval; - ae_int_t i; - ae_int_t j; - double vx; - double vs; - double v; - double vv; - double vd0; - double vd1; - ae_int_t vi; - ae_int_t j0; - ae_int_t j1; - ae_int_t n; - ae_int_t ri; - ae_int_t ri1; - ae_int_t d; - ae_int_t u; - ae_int_t lt; - ae_int_t rt; - ae_int_t lt1; - ae_int_t rt1; - - - ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseMV2: incorrect matrix type (convert your matrix to CRS/SKS)", _state); - ae_assert(s->m==s->n, "SparseMV2: matrix is non-square", _state); - l = x->cnt; - ae_assert(l>=s->n, "SparseMV2: Length(X)n; - rvectorsetlengthatleast(y0, l, _state); - rvectorsetlengthatleast(y1, l, _state); - for(i=0; i<=n-1; i++) - { - y0->ptr.p_double[i] = (double)(0); - y1->ptr.p_double[i] = (double)(0); - } - if( s->matrixtype==1 ) - { - - /* - * CRS format - */ - ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseMV2: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state); - for(i=0; i<=s->m-1; i++) - { - tval = (double)(0); - vx = x->ptr.p_double[i]; - j0 = s->ridx.ptr.p_int[i]; - j1 = s->ridx.ptr.p_int[i+1]-1; - for(j=j0; j<=j1; j++) - { - vi = s->idx.ptr.p_int[j]; - vs = s->vals.ptr.p_double[j]; - tval = tval+x->ptr.p_double[vi]*vs; - y1->ptr.p_double[vi] = y1->ptr.p_double[vi]+vx*vs; - } - y0->ptr.p_double[i] = tval; - } - return; - } - if( s->matrixtype==2 ) - { - - /* - * SKS format - */ - for(i=0; i<=n-1; i++) - { - ri = s->ridx.ptr.p_int[i]; - ri1 = s->ridx.ptr.p_int[i+1]; - d = s->didx.ptr.p_int[i]; - u = s->uidx.ptr.p_int[i]; - vd0 = s->vals.ptr.p_double[ri+d]*x->ptr.p_double[i]; - vd1 = vd0; - if( d>0 ) - { - lt = ri; - rt = ri+d-1; - lt1 = i-d; - rt1 = i-1; - v = x->ptr.p_double[i]; - ae_v_addd(&y1->ptr.p_double[lt1], 1, &s->vals.ptr.p_double[lt], 1, ae_v_len(lt1,rt1), v); - vv = ae_v_dotproduct(&s->vals.ptr.p_double[lt], 1, &x->ptr.p_double[lt1], 1, ae_v_len(lt,rt)); - vd0 = vd0+vv; - } - if( u>0 ) - { - lt = ri1-u; - rt = ri1-1; - lt1 = i-u; - rt1 = i-1; - v = x->ptr.p_double[i]; - ae_v_addd(&y0->ptr.p_double[lt1], 1, &s->vals.ptr.p_double[lt], 1, ae_v_len(lt1,rt1), v); - vv = ae_v_dotproduct(&s->vals.ptr.p_double[lt], 1, &x->ptr.p_double[lt1], 1, ae_v_len(lt,rt)); - vd1 = vd1+vv; - } - y0->ptr.p_double[i] = vd0; - y1->ptr.p_double[i] = vd1; - } - return; - } -} - - -/************************************************************************* -This function calculates matrix-vector product S*x, when S is symmetric -matrix. Matrix S must be stored in CRS or SKS format (exception will be -thrown otherwise). - -INPUT PARAMETERS - S - sparse M*M matrix in CRS or SKS format. - IsUpper - whether upper or lower triangle of S is given: - * if upper triangle is given, only S[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only S[i,j] for j<=i - are used, and upper triangle is ignored. - X - array[N], input vector. For performance reasons we - make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - Y - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - Y - array[M], S*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsesmv(sparsematrix* s, - ae_bool isupper, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t id; - ae_int_t lt; - ae_int_t rt; - double v; - double vv; - double vy; - double vx; - double vd; - ae_int_t ri; - ae_int_t ri1; - ae_int_t d; - ae_int_t u; - ae_int_t lt1; - ae_int_t rt1; - - - ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseSMV: incorrect matrix type (convert your matrix to CRS/SKS)", _state); - ae_assert(x->cnt>=s->n, "SparseSMV: length(X)m==s->n, "SparseSMV: non-square matrix", _state); - n = s->n; - rvectorsetlengthatleast(y, n, _state); - for(i=0; i<=n-1; i++) - { - y->ptr.p_double[i] = (double)(0); - } - if( s->matrixtype==1 ) - { - - /* - * CRS format - */ - ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseSMV: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state); - for(i=0; i<=n-1; i++) - { - if( s->didx.ptr.p_int[i]!=s->uidx.ptr.p_int[i] ) - { - y->ptr.p_double[i] = y->ptr.p_double[i]+s->vals.ptr.p_double[s->didx.ptr.p_int[i]]*x->ptr.p_double[s->idx.ptr.p_int[s->didx.ptr.p_int[i]]]; - } - if( isupper ) - { - lt = s->uidx.ptr.p_int[i]; - rt = s->ridx.ptr.p_int[i+1]; - vy = (double)(0); - vx = x->ptr.p_double[i]; - for(j=lt; j<=rt-1; j++) - { - id = s->idx.ptr.p_int[j]; - v = s->vals.ptr.p_double[j]; - vy = vy+x->ptr.p_double[id]*v; - y->ptr.p_double[id] = y->ptr.p_double[id]+vx*v; - } - y->ptr.p_double[i] = y->ptr.p_double[i]+vy; - } - else - { - lt = s->ridx.ptr.p_int[i]; - rt = s->didx.ptr.p_int[i]; - vy = (double)(0); - vx = x->ptr.p_double[i]; - for(j=lt; j<=rt-1; j++) - { - id = s->idx.ptr.p_int[j]; - v = s->vals.ptr.p_double[j]; - vy = vy+x->ptr.p_double[id]*v; - y->ptr.p_double[id] = y->ptr.p_double[id]+vx*v; - } - y->ptr.p_double[i] = y->ptr.p_double[i]+vy; - } - } - return; - } - if( s->matrixtype==2 ) - { - - /* - * SKS format - */ - for(i=0; i<=n-1; i++) - { - ri = s->ridx.ptr.p_int[i]; - ri1 = s->ridx.ptr.p_int[i+1]; - d = s->didx.ptr.p_int[i]; - u = s->uidx.ptr.p_int[i]; - vd = s->vals.ptr.p_double[ri+d]*x->ptr.p_double[i]; - if( d>0&&!isupper ) - { - lt = ri; - rt = ri+d-1; - lt1 = i-d; - rt1 = i-1; - v = x->ptr.p_double[i]; - ae_v_addd(&y->ptr.p_double[lt1], 1, &s->vals.ptr.p_double[lt], 1, ae_v_len(lt1,rt1), v); - vv = ae_v_dotproduct(&s->vals.ptr.p_double[lt], 1, &x->ptr.p_double[lt1], 1, ae_v_len(lt,rt)); - vd = vd+vv; - } - if( u>0&&isupper ) - { - lt = ri1-u; - rt = ri1-1; - lt1 = i-u; - rt1 = i-1; - v = x->ptr.p_double[i]; - ae_v_addd(&y->ptr.p_double[lt1], 1, &s->vals.ptr.p_double[lt], 1, ae_v_len(lt1,rt1), v); - vv = ae_v_dotproduct(&s->vals.ptr.p_double[lt], 1, &x->ptr.p_double[lt1], 1, ae_v_len(lt,rt)); - vd = vd+vv; - } - y->ptr.p_double[i] = vd; - } - return; - } -} - - -/************************************************************************* -This function calculates vector-matrix-vector product x'*S*x, where S is -symmetric matrix. Matrix S must be stored in CRS or SKS format (exception -will be thrown otherwise). - -INPUT PARAMETERS - S - sparse M*M matrix in CRS or SKS format. - IsUpper - whether upper or lower triangle of S is given: - * if upper triangle is given, only S[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only S[i,j] for j<=i - are used, and upper triangle is ignored. - X - array[N], input vector. For performance reasons we - make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - -RESULT - x'*S*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 27.01.2014 by Bochkanov Sergey -*************************************************************************/ -double sparsevsmv(sparsematrix* s, - ae_bool isupper, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t id; - ae_int_t lt; - ae_int_t rt; - double v; - double v0; - double v1; - ae_int_t ri; - ae_int_t ri1; - ae_int_t d; - ae_int_t u; - ae_int_t lt1; - double result; - - - ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseVSMV: incorrect matrix type (convert your matrix to CRS/SKS)", _state); - ae_assert(x->cnt>=s->n, "SparseVSMV: length(X)m==s->n, "SparseVSMV: non-square matrix", _state); - n = s->n; - result = 0.0; - if( s->matrixtype==1 ) - { - - /* - * CRS format - */ - ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseVSMV: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state); - for(i=0; i<=n-1; i++) - { - if( s->didx.ptr.p_int[i]!=s->uidx.ptr.p_int[i] ) - { - v = x->ptr.p_double[s->idx.ptr.p_int[s->didx.ptr.p_int[i]]]; - result = result+v*s->vals.ptr.p_double[s->didx.ptr.p_int[i]]*v; - } - if( isupper ) - { - lt = s->uidx.ptr.p_int[i]; - rt = s->ridx.ptr.p_int[i+1]; - } - else - { - lt = s->ridx.ptr.p_int[i]; - rt = s->didx.ptr.p_int[i]; - } - v0 = x->ptr.p_double[i]; - for(j=lt; j<=rt-1; j++) - { - id = s->idx.ptr.p_int[j]; - v1 = x->ptr.p_double[id]; - v = s->vals.ptr.p_double[j]; - result = result+2*v0*v1*v; - } - } - return result; - } - if( s->matrixtype==2 ) - { - - /* - * SKS format - */ - for(i=0; i<=n-1; i++) - { - ri = s->ridx.ptr.p_int[i]; - ri1 = s->ridx.ptr.p_int[i+1]; - d = s->didx.ptr.p_int[i]; - u = s->uidx.ptr.p_int[i]; - v = x->ptr.p_double[i]; - result = result+v*s->vals.ptr.p_double[ri+d]*v; - if( d>0&&!isupper ) - { - lt = ri; - rt = ri+d-1; - lt1 = i-d; - k = d-1; - v0 = x->ptr.p_double[i]; - v = 0.0; - for(j=0; j<=k; j++) - { - v = v+x->ptr.p_double[lt1+j]*s->vals.ptr.p_double[lt+j]; - } - result = result+2*v0*v; - } - if( u>0&&isupper ) - { - lt = ri1-u; - rt = ri1-1; - lt1 = i-u; - k = u-1; - v0 = x->ptr.p_double[i]; - v = 0.0; - for(j=0; j<=k; j++) - { - v = v+x->ptr.p_double[lt1+j]*s->vals.ptr.p_double[lt+j]; - } - result = result+2*v0*v; - } - } - return result; - } - return result; -} - - -/************************************************************************* -This function calculates matrix-matrix product S*A. Matrix S must be -stored in CRS or SKS format (exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse M*N matrix in CRS or SKS format. - A - array[N][K], input dense matrix. For performance reasons - we make only quick checks - we check that array size - is at least N, but we do not check for NAN's or INF's. - K - number of columns of matrix (A). - B - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - B - array[M][K], S*A - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsemm(sparsematrix* s, - /* Real */ ae_matrix* a, - ae_int_t k, - /* Real */ ae_matrix* b, - ae_state *_state) -{ - double tval; - double v; - ae_int_t id; - ae_int_t i; - ae_int_t j; - ae_int_t k0; - ae_int_t k1; - ae_int_t lt; - ae_int_t rt; - ae_int_t m; - ae_int_t n; - ae_int_t ri; - ae_int_t ri1; - ae_int_t lt1; - ae_int_t rt1; - ae_int_t d; - ae_int_t u; - double vd; - - - ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseMM: incorrect matrix type (convert your matrix to CRS/SKS)", _state); - ae_assert(a->rows>=s->n, "SparseMM: Rows(A)0, "SparseMM: K<=0", _state); - m = s->m; - n = s->n; - k1 = k-1; - rmatrixsetlengthatleast(b, m, k, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=k-1; j++) - { - b->ptr.pp_double[i][j] = (double)(0); - } - } - if( s->matrixtype==1 ) - { - - /* - * CRS format - */ - ae_assert(s->ninitialized==s->ridx.ptr.p_int[m], "SparseMM: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state); - if( kridx.ptr.p_int[i]; - rt = s->ridx.ptr.p_int[i+1]; - for(k0=lt; k0<=rt-1; k0++) - { - tval = tval+s->vals.ptr.p_double[k0]*a->ptr.pp_double[s->idx.ptr.p_int[k0]][j]; - } - b->ptr.pp_double[i][j] = tval; - } - } - } - else - { - for(i=0; i<=m-1; i++) - { - lt = s->ridx.ptr.p_int[i]; - rt = s->ridx.ptr.p_int[i+1]; - for(j=lt; j<=rt-1; j++) - { - id = s->idx.ptr.p_int[j]; - v = s->vals.ptr.p_double[j]; - ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[id][0], 1, ae_v_len(0,k-1), v); - } - } - } - return; - } - if( s->matrixtype==2 ) - { - - /* - * SKS format - */ - ae_assert(m==n, "SparseMM: non-square SKS matrices are not supported", _state); - for(i=0; i<=n-1; i++) - { - ri = s->ridx.ptr.p_int[i]; - ri1 = s->ridx.ptr.p_int[i+1]; - d = s->didx.ptr.p_int[i]; - u = s->uidx.ptr.p_int[i]; - if( d>0 ) - { - lt = ri; - rt = ri+d-1; - lt1 = i-d; - rt1 = i-1; - for(j=lt1; j<=rt1; j++) - { - v = s->vals.ptr.p_double[lt+(j-lt1)]; - if( kptr.pp_double[i][k0] = b->ptr.pp_double[i][k0]+v*a->ptr.pp_double[j][k0]; - } - } - else - { - - /* - * Use vector operation - */ - ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[j][0], 1, ae_v_len(0,k-1), v); - } - } - } - if( u>0 ) - { - lt = ri1-u; - rt = ri1-1; - lt1 = i-u; - rt1 = i-1; - for(j=lt1; j<=rt1; j++) - { - v = s->vals.ptr.p_double[lt+(j-lt1)]; - if( kptr.pp_double[j][k0] = b->ptr.pp_double[j][k0]+v*a->ptr.pp_double[i][k0]; - } - } - else - { - - /* - * Use vector operation - */ - ae_v_addd(&b->ptr.pp_double[j][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v); - } - } - } - vd = s->vals.ptr.p_double[ri+d]; - ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), vd); - } - return; - } -} - - -/************************************************************************* -This function calculates matrix-matrix product S^T*A. Matrix S must be -stored in CRS or SKS format (exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse M*N matrix in CRS or SKS format. - A - array[M][K], input dense matrix. For performance reasons - we make only quick checks - we check that array size is - at least M, but we do not check for NAN's or INF's. - K - number of columns of matrix (A). - B - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - B - array[N][K], S^T*A - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsemtm(sparsematrix* s, - /* Real */ ae_matrix* a, - ae_int_t k, - /* Real */ ae_matrix* b, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k0; - ae_int_t k1; - ae_int_t lt; - ae_int_t rt; - ae_int_t ct; - double v; - ae_int_t m; - ae_int_t n; - ae_int_t ri; - ae_int_t ri1; - ae_int_t lt1; - ae_int_t rt1; - ae_int_t d; - ae_int_t u; - - - ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseMTM: incorrect matrix type (convert your matrix to CRS/SKS)", _state); - ae_assert(a->rows>=s->m, "SparseMTM: Rows(A)0, "SparseMTM: K<=0", _state); - m = s->m; - n = s->n; - k1 = k-1; - rmatrixsetlengthatleast(b, n, k, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=k-1; j++) - { - b->ptr.pp_double[i][j] = (double)(0); - } - } - if( s->matrixtype==1 ) - { - - /* - * CRS format - */ - ae_assert(s->ninitialized==s->ridx.ptr.p_int[m], "SparseMTM: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state); - if( kridx.ptr.p_int[i]; - rt = s->ridx.ptr.p_int[i+1]; - for(k0=lt; k0<=rt-1; k0++) - { - v = s->vals.ptr.p_double[k0]; - ct = s->idx.ptr.p_int[k0]; - for(j=0; j<=k-1; j++) - { - b->ptr.pp_double[ct][j] = b->ptr.pp_double[ct][j]+v*a->ptr.pp_double[i][j]; - } - } - } - } - else - { - for(i=0; i<=m-1; i++) - { - lt = s->ridx.ptr.p_int[i]; - rt = s->ridx.ptr.p_int[i+1]; - for(j=lt; j<=rt-1; j++) - { - v = s->vals.ptr.p_double[j]; - ct = s->idx.ptr.p_int[j]; - ae_v_addd(&b->ptr.pp_double[ct][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v); - } - } - } - return; - } - if( s->matrixtype==2 ) - { - - /* - * SKS format - */ - ae_assert(m==n, "SparseMTM: non-square SKS matrices are not supported", _state); - for(i=0; i<=n-1; i++) - { - ri = s->ridx.ptr.p_int[i]; - ri1 = s->ridx.ptr.p_int[i+1]; - d = s->didx.ptr.p_int[i]; - u = s->uidx.ptr.p_int[i]; - if( d>0 ) - { - lt = ri; - rt = ri+d-1; - lt1 = i-d; - rt1 = i-1; - for(j=lt1; j<=rt1; j++) - { - v = s->vals.ptr.p_double[lt+(j-lt1)]; - if( kptr.pp_double[j][k0] = b->ptr.pp_double[j][k0]+v*a->ptr.pp_double[i][k0]; - } - } - else - { - - /* - * Use vector operation - */ - ae_v_addd(&b->ptr.pp_double[j][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v); - } - } - } - if( u>0 ) - { - lt = ri1-u; - rt = ri1-1; - lt1 = i-u; - rt1 = i-1; - for(j=lt1; j<=rt1; j++) - { - v = s->vals.ptr.p_double[lt+(j-lt1)]; - if( kptr.pp_double[i][k0] = b->ptr.pp_double[i][k0]+v*a->ptr.pp_double[j][k0]; - } - } - else - { - - /* - * Use vector operation - */ - ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[j][0], 1, ae_v_len(0,k-1), v); - } - } - } - v = s->vals.ptr.p_double[ri+d]; - ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v); - } - return; - } -} - - -/************************************************************************* -This function simultaneously calculates two matrix-matrix products: - S*A and S^T*A. -S must be square (non-rectangular) matrix stored in CRS or SKS format -(exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse N*N matrix in CRS or SKS format. - A - array[N][K], input dense matrix. For performance reasons - we make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - K - number of columns of matrix (A). - B0 - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - B1 - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - B0 - array[N][K], S*A - B1 - array[N][K], S^T*A - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsemm2(sparsematrix* s, - /* Real */ ae_matrix* a, - ae_int_t k, - /* Real */ ae_matrix* b0, - /* Real */ ae_matrix* b1, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k0; - ae_int_t lt; - ae_int_t rt; - ae_int_t ct; - double v; - double tval; - ae_int_t n; - ae_int_t k1; - ae_int_t ri; - ae_int_t ri1; - ae_int_t lt1; - ae_int_t rt1; - ae_int_t d; - ae_int_t u; - - - ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseMM2: incorrect matrix type (convert your matrix to CRS/SKS)", _state); - ae_assert(s->m==s->n, "SparseMM2: matrix is non-square", _state); - ae_assert(a->rows>=s->n, "SparseMM2: Rows(A)0, "SparseMM2: K<=0", _state); - n = s->n; - k1 = k-1; - rmatrixsetlengthatleast(b0, n, k, _state); - rmatrixsetlengthatleast(b1, n, k, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=k-1; j++) - { - b1->ptr.pp_double[i][j] = (double)(0); - b0->ptr.pp_double[i][j] = (double)(0); - } - } - if( s->matrixtype==1 ) - { - - /* - * CRS format - */ - ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseMM2: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state); - if( kridx.ptr.p_int[i]; - rt = s->ridx.ptr.p_int[i+1]; - v = a->ptr.pp_double[i][j]; - for(k0=lt; k0<=rt-1; k0++) - { - ct = s->idx.ptr.p_int[k0]; - b1->ptr.pp_double[ct][j] = b1->ptr.pp_double[ct][j]+s->vals.ptr.p_double[k0]*v; - tval = tval+s->vals.ptr.p_double[k0]*a->ptr.pp_double[ct][j]; - } - b0->ptr.pp_double[i][j] = tval; - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - lt = s->ridx.ptr.p_int[i]; - rt = s->ridx.ptr.p_int[i+1]; - for(j=lt; j<=rt-1; j++) - { - v = s->vals.ptr.p_double[j]; - ct = s->idx.ptr.p_int[j]; - ae_v_addd(&b0->ptr.pp_double[i][0], 1, &a->ptr.pp_double[ct][0], 1, ae_v_len(0,k-1), v); - ae_v_addd(&b1->ptr.pp_double[ct][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v); - } - } - } - return; - } - if( s->matrixtype==2 ) - { - - /* - * SKS format - */ - ae_assert(s->m==s->n, "SparseMM2: non-square SKS matrices are not supported", _state); - for(i=0; i<=n-1; i++) - { - ri = s->ridx.ptr.p_int[i]; - ri1 = s->ridx.ptr.p_int[i+1]; - d = s->didx.ptr.p_int[i]; - u = s->uidx.ptr.p_int[i]; - if( d>0 ) - { - lt = ri; - rt = ri+d-1; - lt1 = i-d; - rt1 = i-1; - for(j=lt1; j<=rt1; j++) - { - v = s->vals.ptr.p_double[lt+(j-lt1)]; - if( kptr.pp_double[i][k0] = b0->ptr.pp_double[i][k0]+v*a->ptr.pp_double[j][k0]; - b1->ptr.pp_double[j][k0] = b1->ptr.pp_double[j][k0]+v*a->ptr.pp_double[i][k0]; - } - } - else - { - - /* - * Use vector operation - */ - ae_v_addd(&b0->ptr.pp_double[i][0], 1, &a->ptr.pp_double[j][0], 1, ae_v_len(0,k-1), v); - ae_v_addd(&b1->ptr.pp_double[j][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v); - } - } - } - if( u>0 ) - { - lt = ri1-u; - rt = ri1-1; - lt1 = i-u; - rt1 = i-1; - for(j=lt1; j<=rt1; j++) - { - v = s->vals.ptr.p_double[lt+(j-lt1)]; - if( kptr.pp_double[j][k0] = b0->ptr.pp_double[j][k0]+v*a->ptr.pp_double[i][k0]; - b1->ptr.pp_double[i][k0] = b1->ptr.pp_double[i][k0]+v*a->ptr.pp_double[j][k0]; - } - } - else - { - - /* - * Use vector operation - */ - ae_v_addd(&b0->ptr.pp_double[j][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v); - ae_v_addd(&b1->ptr.pp_double[i][0], 1, &a->ptr.pp_double[j][0], 1, ae_v_len(0,k-1), v); - } - } - } - v = s->vals.ptr.p_double[ri+d]; - ae_v_addd(&b0->ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v); - ae_v_addd(&b1->ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v); - } - return; - } -} - - -/************************************************************************* -This function calculates matrix-matrix product S*A, when S is symmetric -matrix. Matrix S must be stored in CRS or SKS format (exception will be -thrown otherwise). - -INPUT PARAMETERS - S - sparse M*M matrix in CRS or SKS format. - IsUpper - whether upper or lower triangle of S is given: - * if upper triangle is given, only S[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only S[i,j] for j<=i - are used, and upper triangle is ignored. - A - array[N][K], input dense matrix. For performance reasons - we make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - K - number of columns of matrix (A). - B - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - B - array[M][K], S*A - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsesmm(sparsematrix* s, - ae_bool isupper, - /* Real */ ae_matrix* a, - ae_int_t k, - /* Real */ ae_matrix* b, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k0; - ae_int_t id; - ae_int_t k1; - ae_int_t lt; - ae_int_t rt; - double v; - double vb; - double va; - ae_int_t n; - ae_int_t ri; - ae_int_t ri1; - ae_int_t lt1; - ae_int_t rt1; - ae_int_t d; - ae_int_t u; - - - ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseSMM: incorrect matrix type (convert your matrix to CRS/SKS)", _state); - ae_assert(a->rows>=s->n, "SparseSMM: Rows(X)m==s->n, "SparseSMM: matrix is non-square", _state); - n = s->n; - k1 = k-1; - rmatrixsetlengthatleast(b, n, k, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=k-1; j++) - { - b->ptr.pp_double[i][j] = (double)(0); - } - } - if( s->matrixtype==1 ) - { - - /* - * CRS format - */ - ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseSMM: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state); - if( k>sparse_linalgswitch ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=k-1; j++) - { - if( s->didx.ptr.p_int[i]!=s->uidx.ptr.p_int[i] ) - { - id = s->didx.ptr.p_int[i]; - b->ptr.pp_double[i][j] = b->ptr.pp_double[i][j]+s->vals.ptr.p_double[id]*a->ptr.pp_double[s->idx.ptr.p_int[id]][j]; - } - if( isupper ) - { - lt = s->uidx.ptr.p_int[i]; - rt = s->ridx.ptr.p_int[i+1]; - vb = (double)(0); - va = a->ptr.pp_double[i][j]; - for(k0=lt; k0<=rt-1; k0++) - { - id = s->idx.ptr.p_int[k0]; - v = s->vals.ptr.p_double[k0]; - vb = vb+a->ptr.pp_double[id][j]*v; - b->ptr.pp_double[id][j] = b->ptr.pp_double[id][j]+va*v; - } - b->ptr.pp_double[i][j] = b->ptr.pp_double[i][j]+vb; - } - else - { - lt = s->ridx.ptr.p_int[i]; - rt = s->didx.ptr.p_int[i]; - vb = (double)(0); - va = a->ptr.pp_double[i][j]; - for(k0=lt; k0<=rt-1; k0++) - { - id = s->idx.ptr.p_int[k0]; - v = s->vals.ptr.p_double[k0]; - vb = vb+a->ptr.pp_double[id][j]*v; - b->ptr.pp_double[id][j] = b->ptr.pp_double[id][j]+va*v; - } - b->ptr.pp_double[i][j] = b->ptr.pp_double[i][j]+vb; - } - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - if( s->didx.ptr.p_int[i]!=s->uidx.ptr.p_int[i] ) - { - id = s->didx.ptr.p_int[i]; - v = s->vals.ptr.p_double[id]; - ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[s->idx.ptr.p_int[id]][0], 1, ae_v_len(0,k-1), v); - } - if( isupper ) - { - lt = s->uidx.ptr.p_int[i]; - rt = s->ridx.ptr.p_int[i+1]; - for(j=lt; j<=rt-1; j++) - { - id = s->idx.ptr.p_int[j]; - v = s->vals.ptr.p_double[j]; - ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[id][0], 1, ae_v_len(0,k-1), v); - ae_v_addd(&b->ptr.pp_double[id][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v); - } - } - else - { - lt = s->ridx.ptr.p_int[i]; - rt = s->didx.ptr.p_int[i]; - for(j=lt; j<=rt-1; j++) - { - id = s->idx.ptr.p_int[j]; - v = s->vals.ptr.p_double[j]; - ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[id][0], 1, ae_v_len(0,k-1), v); - ae_v_addd(&b->ptr.pp_double[id][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v); - } - } - } - } - return; - } - if( s->matrixtype==2 ) - { - - /* - * SKS format - */ - ae_assert(s->m==s->n, "SparseMM2: non-square SKS matrices are not supported", _state); - for(i=0; i<=n-1; i++) - { - ri = s->ridx.ptr.p_int[i]; - ri1 = s->ridx.ptr.p_int[i+1]; - d = s->didx.ptr.p_int[i]; - u = s->uidx.ptr.p_int[i]; - if( d>0&&!isupper ) - { - lt = ri; - rt = ri+d-1; - lt1 = i-d; - rt1 = i-1; - for(j=lt1; j<=rt1; j++) - { - v = s->vals.ptr.p_double[lt+(j-lt1)]; - if( kptr.pp_double[i][k0] = b->ptr.pp_double[i][k0]+v*a->ptr.pp_double[j][k0]; - b->ptr.pp_double[j][k0] = b->ptr.pp_double[j][k0]+v*a->ptr.pp_double[i][k0]; - } - } - else - { - - /* - * Use vector operation - */ - ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[j][0], 1, ae_v_len(0,k-1), v); - ae_v_addd(&b->ptr.pp_double[j][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v); - } - } - } - if( u>0&&isupper ) - { - lt = ri1-u; - rt = ri1-1; - lt1 = i-u; - rt1 = i-1; - for(j=lt1; j<=rt1; j++) - { - v = s->vals.ptr.p_double[lt+(j-lt1)]; - if( kptr.pp_double[j][k0] = b->ptr.pp_double[j][k0]+v*a->ptr.pp_double[i][k0]; - b->ptr.pp_double[i][k0] = b->ptr.pp_double[i][k0]+v*a->ptr.pp_double[j][k0]; - } - } - else - { - - /* - * Use vector operation - */ - ae_v_addd(&b->ptr.pp_double[j][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v); - ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[j][0], 1, ae_v_len(0,k-1), v); - } - } - } - v = s->vals.ptr.p_double[ri+d]; - ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v); - } - return; - } -} - - -/************************************************************************* -This function calculates matrix-vector product op(S)*x, when x is vector, -S is symmetric triangular matrix, op(S) is transposition or no operation. -Matrix S must be stored in CRS or SKS format (exception will be thrown -otherwise). - -INPUT PARAMETERS - S - sparse square matrix in CRS or SKS format. - IsUpper - whether upper or lower triangle of S is used: - * if upper triangle is given, only S[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only S[i,j] for j<=i - are used, and upper triangle is ignored. - IsUnit - unit or non-unit diagonal: - * if True, diagonal elements of triangular matrix are - considered equal to 1.0. Actual elements stored in - S are not referenced at all. - * if False, diagonal stored in S is used - OpType - operation type: - * if 0, S*x is calculated - * if 1, (S^T)*x is calculated (transposition) - X - array[N] which stores input vector. For performance - reasons we make only quick checks - we check that - array size is at least N, but we do not check for - NAN's or INF's. - Y - possibly preallocated input buffer. Automatically - resized if its size is too small. - -OUTPUT PARAMETERS - Y - array[N], op(S)*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 20.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsetrmv(sparsematrix* s, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t j0; - ae_int_t j1; - double v; - ae_int_t ri; - ae_int_t ri1; - ae_int_t d; - ae_int_t u; - ae_int_t lt; - ae_int_t rt; - ae_int_t lt1; - ae_int_t rt1; - - - ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseTRMV: incorrect matrix type (convert your matrix to CRS/SKS)", _state); - ae_assert(optype==0||optype==1, "SparseTRMV: incorrect operation type (must be 0 or 1)", _state); - ae_assert(x->cnt>=s->n, "SparseTRMV: Length(X)m==s->n, "SparseTRMV: matrix is non-square", _state); - n = s->n; - rvectorsetlengthatleast(y, n, _state); - if( isunit ) - { - - /* - * Set initial value of y to x - */ - for(i=0; i<=n-1; i++) - { - y->ptr.p_double[i] = x->ptr.p_double[i]; - } - } - else - { - - /* - * Set initial value of y to 0 - */ - for(i=0; i<=n-1; i++) - { - y->ptr.p_double[i] = (double)(0); - } - } - if( s->matrixtype==1 ) - { - - /* - * CRS format - */ - ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseTRMV: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state); - for(i=0; i<=n-1; i++) - { - - /* - * Depending on IsUpper/IsUnit, select range of indexes to process - */ - if( isupper ) - { - if( isunit||s->didx.ptr.p_int[i]==s->uidx.ptr.p_int[i] ) - { - j0 = s->uidx.ptr.p_int[i]; - } - else - { - j0 = s->didx.ptr.p_int[i]; - } - j1 = s->ridx.ptr.p_int[i+1]-1; - } - else - { - j0 = s->ridx.ptr.p_int[i]; - if( isunit||s->didx.ptr.p_int[i]==s->uidx.ptr.p_int[i] ) - { - j1 = s->didx.ptr.p_int[i]-1; - } - else - { - j1 = s->didx.ptr.p_int[i]; - } - } - - /* - * Depending on OpType, process subset of I-th row of input matrix - */ - if( optype==0 ) - { - v = 0.0; - for(j=j0; j<=j1; j++) - { - v = v+s->vals.ptr.p_double[j]*x->ptr.p_double[s->idx.ptr.p_int[j]]; - } - y->ptr.p_double[i] = y->ptr.p_double[i]+v; - } - else - { - v = x->ptr.p_double[i]; - for(j=j0; j<=j1; j++) - { - k = s->idx.ptr.p_int[j]; - y->ptr.p_double[k] = y->ptr.p_double[k]+v*s->vals.ptr.p_double[j]; - } - } - } - return; - } - if( s->matrixtype==2 ) - { - - /* - * SKS format - */ - ae_assert(s->m==s->n, "SparseTRMV: non-square SKS matrices are not supported", _state); - for(i=0; i<=n-1; i++) - { - ri = s->ridx.ptr.p_int[i]; - ri1 = s->ridx.ptr.p_int[i+1]; - d = s->didx.ptr.p_int[i]; - u = s->uidx.ptr.p_int[i]; - if( !isunit ) - { - y->ptr.p_double[i] = y->ptr.p_double[i]+s->vals.ptr.p_double[ri+d]*x->ptr.p_double[i]; - } - if( d>0&&!isupper ) - { - lt = ri; - rt = ri+d-1; - lt1 = i-d; - rt1 = i-1; - if( optype==0 ) - { - v = ae_v_dotproduct(&s->vals.ptr.p_double[lt], 1, &x->ptr.p_double[lt1], 1, ae_v_len(lt,rt)); - y->ptr.p_double[i] = y->ptr.p_double[i]+v; - } - else - { - v = x->ptr.p_double[i]; - ae_v_addd(&y->ptr.p_double[lt1], 1, &s->vals.ptr.p_double[lt], 1, ae_v_len(lt1,rt1), v); - } - } - if( u>0&&isupper ) - { - lt = ri1-u; - rt = ri1-1; - lt1 = i-u; - rt1 = i-1; - if( optype==0 ) - { - v = x->ptr.p_double[i]; - ae_v_addd(&y->ptr.p_double[lt1], 1, &s->vals.ptr.p_double[lt], 1, ae_v_len(lt1,rt1), v); - } - else - { - v = ae_v_dotproduct(&s->vals.ptr.p_double[lt], 1, &x->ptr.p_double[lt1], 1, ae_v_len(lt,rt)); - y->ptr.p_double[i] = y->ptr.p_double[i]+v; - } - } - } - return; - } -} - - -/************************************************************************* -This function solves linear system op(S)*y=x where x is vector, S is -symmetric triangular matrix, op(S) is transposition or no operation. -Matrix S must be stored in CRS or SKS format (exception will be thrown -otherwise). - -INPUT PARAMETERS - S - sparse square matrix in CRS or SKS format. - IsUpper - whether upper or lower triangle of S is used: - * if upper triangle is given, only S[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only S[i,j] for j<=i - are used, and upper triangle is ignored. - IsUnit - unit or non-unit diagonal: - * if True, diagonal elements of triangular matrix are - considered equal to 1.0. Actual elements stored in - S are not referenced at all. - * if False, diagonal stored in S is used. It is your - responsibility to make sure that diagonal is - non-zero. - OpType - operation type: - * if 0, S*x is calculated - * if 1, (S^T)*x is calculated (transposition) - X - array[N] which stores input vector. For performance - reasons we make only quick checks - we check that - array size is at least N, but we do not check for - NAN's or INF's. - -OUTPUT PARAMETERS - X - array[N], inv(op(S))*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. - You must convert your matrix with SparseConvertToCRS/SKS() before - using this function. - -NOTE: no assertion or tests are done during algorithm operation. It is - your responsibility to provide invertible matrix to algorithm. - - -- ALGLIB PROJECT -- - Copyright 20.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsetrsv(sparsematrix* s, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t n; - ae_int_t fst; - ae_int_t lst; - ae_int_t stp; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double vd; - double v0; - ae_int_t j0; - ae_int_t j1; - ae_int_t ri; - ae_int_t ri1; - ae_int_t d; - ae_int_t u; - ae_int_t lt; - ae_int_t lt1; - - - ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseTRSV: incorrect matrix type (convert your matrix to CRS/SKS)", _state); - ae_assert(optype==0||optype==1, "SparseTRSV: incorrect operation type (must be 0 or 1)", _state); - ae_assert(x->cnt>=s->n, "SparseTRSV: Length(X)m==s->n, "SparseTRSV: matrix is non-square", _state); - n = s->n; - if( s->matrixtype==1 ) - { - - /* - * CRS format. - * - * Several branches for different combinations of IsUpper and OpType - */ - ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseTRSV: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state); - if( optype==0 ) - { - - /* - * No transposition. - * - * S*x=y with upper or lower triangular S. - */ - v0 = (double)(0); - if( isupper ) - { - fst = n-1; - lst = 0; - stp = -1; - } - else - { - fst = 0; - lst = n-1; - stp = 1; - } - i = fst; - while((stp>0&&i<=lst)||(stp<0&&i>=lst)) - { - - /* - * Select range of indexes to process - */ - if( isupper ) - { - j0 = s->uidx.ptr.p_int[i]; - j1 = s->ridx.ptr.p_int[i+1]-1; - } - else - { - j0 = s->ridx.ptr.p_int[i]; - j1 = s->didx.ptr.p_int[i]-1; - } - - /* - * Calculate X[I] - */ - v = 0.0; - for(j=j0; j<=j1; j++) - { - v = v+s->vals.ptr.p_double[j]*x->ptr.p_double[s->idx.ptr.p_int[j]]; - } - if( !isunit ) - { - if( s->didx.ptr.p_int[i]==s->uidx.ptr.p_int[i] ) - { - vd = (double)(0); - } - else - { - vd = s->vals.ptr.p_double[s->didx.ptr.p_int[i]]; - } - } - else - { - vd = 1.0; - } - v = (x->ptr.p_double[i]-v)/vd; - x->ptr.p_double[i] = v; - v0 = 0.25*v0+v; - - /* - * Next I - */ - i = i+stp; - } - ae_assert(ae_isfinite(v0, _state), "SparseTRSV: overflow or division by exact zero", _state); - return; - } - if( optype==1 ) - { - - /* - * Transposition. - * - * (S^T)*x=y with upper or lower triangular S. - */ - if( isupper ) - { - fst = 0; - lst = n-1; - stp = 1; - } - else - { - fst = n-1; - lst = 0; - stp = -1; - } - i = fst; - v0 = (double)(0); - while((stp>0&&i<=lst)||(stp<0&&i>=lst)) - { - v = x->ptr.p_double[i]; - if( v!=0.0 ) - { - - /* - * X[i] already stores A[i,i]*Y[i], the only thing left - * is to divide by diagonal element. - */ - if( !isunit ) - { - if( s->didx.ptr.p_int[i]==s->uidx.ptr.p_int[i] ) - { - vd = (double)(0); - } - else - { - vd = s->vals.ptr.p_double[s->didx.ptr.p_int[i]]; - } - } - else - { - vd = 1.0; - } - v = v/vd; - x->ptr.p_double[i] = v; - v0 = 0.25*v0+v; - - /* - * For upper triangular case: - * subtract X[i]*Ai from X[i+1:N-1] - * - * For lower triangular case: - * subtract X[i]*Ai from X[0:i-1] - * - * (here Ai is I-th row of original, untransposed A). - */ - if( isupper ) - { - j0 = s->uidx.ptr.p_int[i]; - j1 = s->ridx.ptr.p_int[i+1]-1; - } - else - { - j0 = s->ridx.ptr.p_int[i]; - j1 = s->didx.ptr.p_int[i]-1; - } - for(j=j0; j<=j1; j++) - { - k = s->idx.ptr.p_int[j]; - x->ptr.p_double[k] = x->ptr.p_double[k]-s->vals.ptr.p_double[j]*v; - } - } - - /* - * Next I - */ - i = i+stp; - } - ae_assert(ae_isfinite(v0, _state), "SparseTRSV: overflow or division by exact zero", _state); - return; - } - ae_assert(ae_false, "SparseTRSV: internal error", _state); - } - if( s->matrixtype==2 ) - { - - /* - * SKS format - */ - ae_assert(s->m==s->n, "SparseTRSV: non-square SKS matrices are not supported", _state); - if( (optype==0&&!isupper)||(optype==1&&isupper) ) - { - - /* - * Lower triangular op(S) (matrix itself can be upper triangular). - */ - v0 = (double)(0); - for(i=0; i<=n-1; i++) - { - - /* - * Select range of indexes to process - */ - ri = s->ridx.ptr.p_int[i]; - ri1 = s->ridx.ptr.p_int[i+1]; - d = s->didx.ptr.p_int[i]; - u = s->uidx.ptr.p_int[i]; - if( isupper ) - { - lt = i-u; - lt1 = ri1-u; - k = u-1; - } - else - { - lt = i-d; - lt1 = ri; - k = d-1; - } - - /* - * Calculate X[I] - */ - v = 0.0; - for(j=0; j<=k; j++) - { - v = v+s->vals.ptr.p_double[lt1+j]*x->ptr.p_double[lt+j]; - } - if( isunit ) - { - vd = (double)(1); - } - else - { - vd = s->vals.ptr.p_double[ri+d]; - } - v = (x->ptr.p_double[i]-v)/vd; - x->ptr.p_double[i] = v; - v0 = 0.25*v0+v; - } - ae_assert(ae_isfinite(v0, _state), "SparseTRSV: overflow or division by exact zero", _state); - return; - } - if( (optype==1&&!isupper)||(optype==0&&isupper) ) - { - - /* - * Upper triangular op(S) (matrix itself can be lower triangular). - */ - v0 = (double)(0); - for(i=n-1; i>=0; i--) - { - ri = s->ridx.ptr.p_int[i]; - ri1 = s->ridx.ptr.p_int[i+1]; - d = s->didx.ptr.p_int[i]; - u = s->uidx.ptr.p_int[i]; - - /* - * X[i] already stores A[i,i]*Y[i], the only thing left - * is to divide by diagonal element. - */ - if( isunit ) - { - vd = (double)(1); - } - else - { - vd = s->vals.ptr.p_double[ri+d]; - } - v = x->ptr.p_double[i]/vd; - x->ptr.p_double[i] = v; - v0 = 0.25*v0+v; - - /* - * Subtract product of X[i] and I-th column of "effective" A from - * unprocessed variables. - */ - v = x->ptr.p_double[i]; - if( isupper ) - { - lt = i-u; - lt1 = ri1-u; - k = u-1; - } - else - { - lt = i-d; - lt1 = ri; - k = d-1; - } - for(j=0; j<=k; j++) - { - x->ptr.p_double[lt+j] = x->ptr.p_double[lt+j]-v*s->vals.ptr.p_double[lt1+j]; - } - } - ae_assert(ae_isfinite(v0, _state), "SparseTRSV: overflow or division by exact zero", _state); - return; - } - ae_assert(ae_false, "SparseTRSV: internal error", _state); - } - ae_assert(ae_false, "SparseTRSV: internal error", _state); -} - - -/************************************************************************* -This function applies permutation given by permutation table P (as opposed -to product form of permutation) to sparse symmetric matrix A, given by -either upper or lower triangle: B := P*A*P'. - -This function allocates completely new instance of B. Use buffered version -SparseSymmPermTblBuf() if you want to reuse already allocated structure. - -INPUT PARAMETERS - A - sparse square matrix in CRS format. - IsUpper - whether upper or lower triangle of A is used: - * if upper triangle is given, only A[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only A[i,j] for j<=i - are used, and upper triangle is ignored. - P - array[N] which stores permutation table; P[I]=J means - that I-th row/column of matrix A is moved to J-th - position. For performance reasons we do NOT check that - P[] is a correct permutation (that there is no - repetitions, just that all its elements are in [0,N) - range. - -OUTPUT PARAMETERS - B - permuted matrix. Permutation is applied to A from - the both sides, only upper or lower triangle (depending - on IsUpper) is stored. - -NOTE: this function throws exception when called for non-CRS matrix. You - must convert your matrix with SparseConvertToCRS() before using this - function. - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -void sparsesymmpermtbl(sparsematrix* a, - ae_bool isupper, - /* Integer */ ae_vector* p, - sparsematrix* b, - ae_state *_state) -{ - - _sparsematrix_clear(b); - - sparsesymmpermtblbuf(a, isupper, p, b, _state); -} - - -/************************************************************************* -This function is a buffered version of SparseSymmPermTbl() that reuses -previously allocated storage in B as much as possible. - -This function applies permutation given by permutation table P (as opposed -to product form of permutation) to sparse symmetric matrix A, given by -either upper or lower triangle: B := P*A*P'. - -INPUT PARAMETERS - A - sparse square matrix in CRS format. - IsUpper - whether upper or lower triangle of A is used: - * if upper triangle is given, only A[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only A[i,j] for j<=i - are used, and upper triangle is ignored. - P - array[N] which stores permutation table; P[I]=J means - that I-th row/column of matrix A is moved to J-th - position. For performance reasons we do NOT check that - P[] is a correct permutation (that there is no - repetitions, just that all its elements are in [0,N) - range. - B - sparse matrix object that will hold output. - Previously allocated memory will be reused as much as - possible. - -OUTPUT PARAMETERS - B - permuted matrix. Permutation is applied to A from - the both sides, only upper or lower triangle (depending - on IsUpper) is stored. - -NOTE: this function throws exception when called for non-CRS matrix. You - must convert your matrix with SparseConvertToCRS() before using this - function. - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -void sparsesymmpermtblbuf(sparsematrix* a, - ae_bool isupper, - /* Integer */ ae_vector* p, - sparsematrix* b, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t jj; - ae_int_t j0; - ae_int_t j1; - ae_int_t k0; - ae_int_t k1; - ae_int_t kk; - ae_int_t n; - ae_int_t dst; - ae_bool bflag; - - - ae_assert(a->matrixtype==1, "SparseSymmPermTblBuf: incorrect matrix type (convert your matrix to CRS)", _state); - ae_assert(p->cnt>=a->n, "SparseSymmPermTblBuf: Length(P)m==a->n, "SparseSymmPermTblBuf: matrix is non-square", _state); - bflag = ae_true; - for(i=0; i<=a->n-1; i++) - { - bflag = (bflag&&p->ptr.p_int[i]>=0)&&p->ptr.p_int[i]n; - } - ae_assert(bflag, "SparseSymmPermTblBuf: P[] contains values outside of [0,N) range", _state); - n = a->n; - - /* - * Prepare output - */ - ae_assert(a->ninitialized==a->ridx.ptr.p_int[n], "SparseSymmPermTblBuf: integrity check failed", _state); - b->matrixtype = 1; - b->n = n; - b->m = n; - ivectorsetlengthatleast(&b->didx, n, _state); - ivectorsetlengthatleast(&b->uidx, n, _state); - - /* - * Determine row sizes (temporary stored in DIdx) and ranges - */ - isetv(n, 0, &b->didx, _state); - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j0 = a->didx.ptr.p_int[i]; - j1 = a->ridx.ptr.p_int[i+1]-1; - k0 = p->ptr.p_int[i]; - for(jj=j0; jj<=j1; jj++) - { - k1 = p->ptr.p_int[a->idx.ptr.p_int[jj]]; - if( k1didx.ptr.p_int[k1] = b->didx.ptr.p_int[k1]+1; - } - else - { - b->didx.ptr.p_int[k0] = b->didx.ptr.p_int[k0]+1; - } - } - } - else - { - j0 = a->ridx.ptr.p_int[i]; - j1 = a->uidx.ptr.p_int[i]-1; - k0 = p->ptr.p_int[i]; - for(jj=j0; jj<=j1; jj++) - { - k1 = p->ptr.p_int[a->idx.ptr.p_int[jj]]; - if( k1>k0 ) - { - b->didx.ptr.p_int[k1] = b->didx.ptr.p_int[k1]+1; - } - else - { - b->didx.ptr.p_int[k0] = b->didx.ptr.p_int[k0]+1; - } - } - } - } - ivectorsetlengthatleast(&b->ridx, n+1, _state); - b->ridx.ptr.p_int[0] = 0; - for(i=0; i<=n-1; i++) - { - b->ridx.ptr.p_int[i+1] = b->ridx.ptr.p_int[i]+b->didx.ptr.p_int[i]; - } - b->ninitialized = b->ridx.ptr.p_int[n]; - ivectorsetlengthatleast(&b->idx, b->ninitialized, _state); - rvectorsetlengthatleast(&b->vals, b->ninitialized, _state); - - /* - * Process matrix - */ - for(i=0; i<=n-1; i++) - { - b->uidx.ptr.p_int[i] = b->ridx.ptr.p_int[i]; - } - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j0 = a->didx.ptr.p_int[i]; - j1 = a->ridx.ptr.p_int[i+1]-1; - for(jj=j0; jj<=j1; jj++) - { - j = a->idx.ptr.p_int[jj]; - k0 = p->ptr.p_int[i]; - k1 = p->ptr.p_int[j]; - if( k1uidx.ptr.p_int[k0]; - b->idx.ptr.p_int[dst] = k1; - b->vals.ptr.p_double[dst] = a->vals.ptr.p_double[jj]; - b->uidx.ptr.p_int[k0] = dst+1; - } - } - else - { - j0 = a->ridx.ptr.p_int[i]; - j1 = a->uidx.ptr.p_int[i]-1; - for(jj=j0; jj<=j1; jj++) - { - j = a->idx.ptr.p_int[jj]; - k0 = p->ptr.p_int[i]; - k1 = p->ptr.p_int[j]; - if( k1>k0 ) - { - kk = k0; - k0 = k1; - k1 = kk; - } - dst = b->uidx.ptr.p_int[k0]; - b->idx.ptr.p_int[dst] = k1; - b->vals.ptr.p_double[dst] = a->vals.ptr.p_double[jj]; - b->uidx.ptr.p_int[k0] = dst+1; - } - } - } - - /* - * Finalize matrix - */ - for(i=0; i<=n-1; i++) - { - tagsortmiddleir(&b->idx, &b->vals, b->ridx.ptr.p_int[i], b->ridx.ptr.p_int[i+1]-b->ridx.ptr.p_int[i], _state); - } - sparseinitduidx(b, _state); -} - - -/************************************************************************* -This procedure resizes Hash-Table matrix. It can be called when you have -deleted too many elements from the matrix, and you want to free unneeded -memory. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparseresizematrix(sparsematrix* s, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t k; - ae_int_t k1; - ae_int_t i; - ae_vector tvals; - ae_vector tidx; - - ae_frame_make(_state, &_frame_block); - memset(&tvals, 0, sizeof(tvals)); - memset(&tidx, 0, sizeof(tidx)); - ae_vector_init(&tvals, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tidx, 0, DT_INT, _state, ae_true); - - ae_assert(s->matrixtype==0, "SparseResizeMatrix: incorrect matrix type", _state); - - /* - * Initialization for length and number of non-null elementd - */ - k = s->tablesize; - k1 = 0; - - /* - * Calculating number of non-null elements - */ - for(i=0; i<=k-1; i++) - { - if( s->idx.ptr.p_int[2*i]>=0 ) - { - k1 = k1+1; - } - } - - /* - * Initialization value for free space - */ - s->tablesize = ae_round(k1/sparse_desiredloadfactor*sparse_growfactor+sparse_additional, _state); - s->nfree = s->tablesize-k1; - ae_vector_set_length(&tvals, s->tablesize, _state); - ae_vector_set_length(&tidx, 2*s->tablesize, _state); - ae_swap_vectors(&s->vals, &tvals); - ae_swap_vectors(&s->idx, &tidx); - for(i=0; i<=s->tablesize-1; i++) - { - s->idx.ptr.p_int[2*i] = -1; - } - for(i=0; i<=k-1; i++) - { - if( tidx.ptr.p_int[2*i]>=0 ) - { - sparseset(s, tidx.ptr.p_int[2*i], tidx.ptr.p_int[2*i+1], tvals.ptr.p_double[i], _state); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Procedure for initialization 'S.DIdx' and 'S.UIdx' - - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparseinitduidx(sparsematrix* s, ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t lt; - ae_int_t rt; - - - ae_assert(s->matrixtype==1, "SparseInitDUIdx: internal error, incorrect matrix type", _state); - ivectorsetlengthatleast(&s->didx, s->m, _state); - ivectorsetlengthatleast(&s->uidx, s->m, _state); - for(i=0; i<=s->m-1; i++) - { - s->uidx.ptr.p_int[i] = -1; - s->didx.ptr.p_int[i] = -1; - lt = s->ridx.ptr.p_int[i]; - rt = s->ridx.ptr.p_int[i+1]; - for(j=lt; j<=rt-1; j++) - { - k = s->idx.ptr.p_int[j]; - if( k==i ) - { - s->didx.ptr.p_int[i] = j; - } - else - { - if( k>i&&s->uidx.ptr.p_int[i]==-1 ) - { - s->uidx.ptr.p_int[i] = j; - break; - } - } - } - if( s->uidx.ptr.p_int[i]==-1 ) - { - s->uidx.ptr.p_int[i] = s->ridx.ptr.p_int[i+1]; - } - if( s->didx.ptr.p_int[i]==-1 ) - { - s->didx.ptr.p_int[i] = s->uidx.ptr.p_int[i]; - } - } -} - - -/************************************************************************* -This function return average length of chain at hash-table. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -double sparsegetaveragelengthofchain(sparsematrix* s, ae_state *_state) -{ - ae_int_t nchains; - ae_int_t talc; - ae_int_t l; - ae_int_t i; - ae_int_t ind0; - ae_int_t ind1; - ae_int_t hashcode; - double result; - - - - /* - * If matrix represent in CRS then return zero and exit - */ - if( s->matrixtype!=0 ) - { - result = (double)(0); - return result; - } - nchains = 0; - talc = 0; - l = s->tablesize; - for(i=0; i<=l-1; i++) - { - ind0 = 2*i; - if( s->idx.ptr.p_int[ind0]!=-1 ) - { - nchains = nchains+1; - hashcode = sparse_hash(s->idx.ptr.p_int[ind0], s->idx.ptr.p_int[ind0+1], l, _state); - for(;;) - { - talc = talc+1; - ind1 = 2*hashcode; - if( s->idx.ptr.p_int[ind0]==s->idx.ptr.p_int[ind1]&&s->idx.ptr.p_int[ind0+1]==s->idx.ptr.p_int[ind1+1] ) - { - break; - } - hashcode = (hashcode+1)%l; - } - } - } - if( nchains==0 ) - { - result = (double)(0); - } - else - { - result = (double)talc/(double)nchains; - } - return result; -} - - -/************************************************************************* -This function is used to enumerate all elements of the sparse matrix. -Before first call user initializes T0 and T1 counters by zero. These -counters are used to remember current position in a matrix; after each -call they are updated by the function. - -Subsequent calls to this function return non-zero elements of the sparse -matrix, one by one. If you enumerate CRS matrix, matrix is traversed from -left to right, from top to bottom. In case you enumerate matrix stored as -Hash table, elements are returned in random order. - -EXAMPLE - > T0=0 - > T1=0 - > while SparseEnumerate(S,T0,T1,I,J,V) do - > ....do something with I,J,V - -INPUT PARAMETERS - S - sparse M*N matrix in Hash-Table or CRS representation. - T0 - internal counter - T1 - internal counter - -OUTPUT PARAMETERS - T0 - new value of the internal counter - T1 - new value of the internal counter - I - row index of non-zero element, 0<=Imatrixtype!=0&&*t1<0) ) - { - - /* - * Incorrect T0/T1, terminate enumeration - */ - result = ae_false; - return result; - } - if( s->matrixtype==0 ) - { - - /* - * Hash-table matrix - */ - sz = s->tablesize; - for(i0=*t0; i0<=sz-1; i0++) - { - if( s->idx.ptr.p_int[2*i0]==-1||s->idx.ptr.p_int[2*i0]==-2 ) - { - continue; - } - else - { - *i = s->idx.ptr.p_int[2*i0]; - *j = s->idx.ptr.p_int[2*i0+1]; - *v = s->vals.ptr.p_double[i0]; - *t0 = i0+1; - result = ae_true; - return result; - } - } - *t0 = 0; - *t1 = 0; - result = ae_false; - return result; - } - if( s->matrixtype==1 ) - { - - /* - * CRS matrix - */ - ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseEnumerate: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state); - if( *t0>=s->ninitialized ) - { - *t0 = 0; - *t1 = 0; - result = ae_false; - return result; - } - while(*t0>s->ridx.ptr.p_int[*t1+1]-1&&*t1m) - { - *t1 = *t1+1; - } - *i = *t1; - *j = s->idx.ptr.p_int[*t0]; - *v = s->vals.ptr.p_double[*t0]; - *t0 = *t0+1; - result = ae_true; - return result; - } - if( s->matrixtype==2 ) - { - - /* - * SKS matrix: - * * T0 stores current offset in Vals[] array - * * T1 stores index of the diagonal block - */ - ae_assert(s->m==s->n, "SparseEnumerate: non-square SKS matrices are not supported", _state); - if( *t0>=s->ridx.ptr.p_int[s->m] ) - { - *t0 = 0; - *t1 = 0; - result = ae_false; - return result; - } - while(*t0>s->ridx.ptr.p_int[*t1+1]-1&&*t1m) - { - *t1 = *t1+1; - } - i0 = *t0-s->ridx.ptr.p_int[*t1]; - if( i0didx.ptr.p_int[*t1]+1 ) - { - - /* - * subdiagonal or diagonal element, row index is T1. - */ - *i = *t1; - *j = *t1-s->didx.ptr.p_int[*t1]+i0; - } - else - { - - /* - * superdiagonal element, column index is T1. - */ - *i = *t1-(s->ridx.ptr.p_int[*t1+1]-(*t0)); - *j = *t1; - } - *v = s->vals.ptr.p_double[*t0]; - *t0 = *t0+1; - result = ae_true; - return result; - } - ae_assert(ae_false, "SparseEnumerate: unexpected matrix type", _state); - return result; -} - - -/************************************************************************* -This function rewrites existing (non-zero) element. It returns True if -element exists or False, when it is called for non-existing (zero) -element. - -This function works with any kind of the matrix. - -The purpose of this function is to provide convenient thread-safe way to -modify sparse matrix. Such modification (already existing element is -rewritten) is guaranteed to be thread-safe without any synchronization, as -long as different threads modify different elements. - -INPUT PARAMETERS - S - sparse M*N matrix in any kind of representation - (Hash, SKS, CRS). - I - row index of non-zero element to modify, 0<=Im, "SparseRewriteExisting: invalid argument I(either I<0 or I>=S.M)", _state); - ae_assert(0<=j&&jn, "SparseRewriteExisting: invalid argument J(either J<0 or J>=S.N)", _state); - ae_assert(ae_isfinite(v, _state), "SparseRewriteExisting: invalid argument V(either V is infinite or V is NaN)", _state); - result = ae_false; - - /* - * Hash-table matrix - */ - if( s->matrixtype==0 ) - { - k = s->tablesize; - hashcode = sparse_hash(i, j, k, _state); - for(;;) - { - if( s->idx.ptr.p_int[2*hashcode]==-1 ) - { - return result; - } - if( s->idx.ptr.p_int[2*hashcode]==i&&s->idx.ptr.p_int[2*hashcode+1]==j ) - { - s->vals.ptr.p_double[hashcode] = v; - result = ae_true; - return result; - } - hashcode = (hashcode+1)%k; - } - } - - /* - * CRS matrix - */ - if( s->matrixtype==1 ) - { - ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseRewriteExisting: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state); - k0 = s->ridx.ptr.p_int[i]; - k1 = s->ridx.ptr.p_int[i+1]-1; - while(k0<=k1) - { - k = (k0+k1)/2; - if( s->idx.ptr.p_int[k]==j ) - { - s->vals.ptr.p_double[k] = v; - result = ae_true; - return result; - } - if( s->idx.ptr.p_int[k]matrixtype==2 ) - { - ae_assert(s->m==s->n, "SparseRewriteExisting: non-square SKS matrix not supported", _state); - if( i==j ) - { - - /* - * Rewrite diagonal element - */ - result = ae_true; - s->vals.ptr.p_double[s->ridx.ptr.p_int[i]+s->didx.ptr.p_int[i]] = v; - return result; - } - if( jdidx.ptr.p_int[i]; - if( i-j<=k ) - { - s->vals.ptr.p_double[s->ridx.ptr.p_int[i]+k+j-i] = v; - result = ae_true; - } - } - else - { - - /* - * Return superdiagonal element at J-th "skyline block" - */ - k = s->uidx.ptr.p_int[j]; - if( j-i<=k ) - { - s->vals.ptr.p_double[s->ridx.ptr.p_int[j+1]-(j-i)] = v; - result = ae_true; - } - } - return result; - } - return result; -} - - -/************************************************************************* -This function returns I-th row of the sparse matrix. Matrix must be stored -in CRS or SKS format. - -INPUT PARAMETERS: - S - sparse M*N matrix in CRS format - I - row index, 0<=Imatrixtype==1||s->matrixtype==2, "SparseGetRow: S must be CRS/SKS-based matrix", _state); - ae_assert(i>=0&&im, "SparseGetRow: I<0 or I>=M", _state); - - /* - * Prepare output buffer - */ - rvectorsetlengthatleast(irow, s->n, _state); - for(i0=0; i0<=s->n-1; i0++) - { - irow->ptr.p_double[i0] = (double)(0); - } - - /* - * Output - */ - if( s->matrixtype==1 ) - { - for(i0=s->ridx.ptr.p_int[i]; i0<=s->ridx.ptr.p_int[i+1]-1; i0++) - { - irow->ptr.p_double[s->idx.ptr.p_int[i0]] = s->vals.ptr.p_double[i0]; - } - return; - } - if( s->matrixtype==2 ) - { - - /* - * Copy subdiagonal and diagonal parts - */ - ae_assert(s->n==s->m, "SparseGetRow: non-square SKS matrices are not supported", _state); - j0 = i-s->didx.ptr.p_int[i]; - i0 = -j0+s->ridx.ptr.p_int[i]; - for(j=j0; j<=i; j++) - { - irow->ptr.p_double[j] = s->vals.ptr.p_double[j+i0]; - } - - /* - * Copy superdiagonal part - */ - upperprofile = s->uidx.ptr.p_int[s->n]; - j0 = i+1; - j1 = ae_minint(s->n-1, i+upperprofile, _state); - for(j=j0; j<=j1; j++) - { - if( j-i<=s->uidx.ptr.p_int[j] ) - { - irow->ptr.p_double[j] = s->vals.ptr.p_double[s->ridx.ptr.p_int[j+1]-(j-i)]; - } - } - return; - } -} - - -/************************************************************************* -This function returns I-th row of the sparse matrix IN COMPRESSED FORMAT - -only non-zero elements are returned (with their indexes). Matrix must be -stored in CRS or SKS format. - -INPUT PARAMETERS: - S - sparse M*N matrix in CRS format - I - row index, 0<=Imatrixtype==1||s->matrixtype==2, "SparseGetRow: S must be CRS/SKS-based matrix", _state); - ae_assert(i>=0&&im, "SparseGetRow: I<0 or I>=M", _state); - - /* - * Initialize NZCnt - */ - *nzcnt = 0; - - /* - * CRS matrix - just copy data - */ - if( s->matrixtype==1 ) - { - *nzcnt = s->ridx.ptr.p_int[i+1]-s->ridx.ptr.p_int[i]; - ivectorsetlengthatleast(colidx, *nzcnt, _state); - rvectorsetlengthatleast(vals, *nzcnt, _state); - k0 = s->ridx.ptr.p_int[i]; - for(k=0; k<=*nzcnt-1; k++) - { - colidx->ptr.p_int[k] = s->idx.ptr.p_int[k0+k]; - vals->ptr.p_double[k] = s->vals.ptr.p_double[k0+k]; - } - return; - } - - /* - * SKS matrix - a bit more complex sequence - */ - if( s->matrixtype==2 ) - { - ae_assert(s->n==s->m, "SparseGetCompressedRow: non-square SKS matrices are not supported", _state); - - /* - * Allocate enough place for storage - */ - upperprofile = s->uidx.ptr.p_int[s->n]; - ivectorsetlengthatleast(colidx, s->didx.ptr.p_int[i]+1+upperprofile, _state); - rvectorsetlengthatleast(vals, s->didx.ptr.p_int[i]+1+upperprofile, _state); - - /* - * Copy subdiagonal and diagonal parts - */ - j0 = i-s->didx.ptr.p_int[i]; - i0 = -j0+s->ridx.ptr.p_int[i]; - for(j=j0; j<=i; j++) - { - colidx->ptr.p_int[*nzcnt] = j; - vals->ptr.p_double[*nzcnt] = s->vals.ptr.p_double[j+i0]; - *nzcnt = *nzcnt+1; - } - - /* - * Copy superdiagonal part - */ - j0 = i+1; - j1 = ae_minint(s->n-1, i+upperprofile, _state); - for(j=j0; j<=j1; j++) - { - if( j-i<=s->uidx.ptr.p_int[j] ) - { - colidx->ptr.p_int[*nzcnt] = j; - vals->ptr.p_double[*nzcnt] = s->vals.ptr.p_double[s->ridx.ptr.p_int[j+1]-(j-i)]; - *nzcnt = *nzcnt+1; - } - } - return; - } -} - - -/************************************************************************* -This function performs efficient in-place transpose of SKS matrix. No -additional memory is allocated during transposition. - -This function supports only skyline storage format (SKS). - -INPUT PARAMETERS - S - sparse matrix in SKS format. - -OUTPUT PARAMETERS - S - sparse matrix, transposed. - - -- ALGLIB PROJECT -- - Copyright 16.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsetransposesks(sparsematrix* s, ae_state *_state) -{ - ae_int_t n; - ae_int_t d; - ae_int_t u; - ae_int_t i; - ae_int_t k; - ae_int_t t0; - ae_int_t t1; - double v; - - - ae_assert(s->matrixtype==2, "SparseTransposeSKS: only SKS matrices are supported", _state); - ae_assert(s->m==s->n, "SparseTransposeSKS: non-square SKS matrices are not supported", _state); - n = s->n; - for(i=1; i<=n-1; i++) - { - d = s->didx.ptr.p_int[i]; - u = s->uidx.ptr.p_int[i]; - k = s->uidx.ptr.p_int[i]; - s->uidx.ptr.p_int[i] = s->didx.ptr.p_int[i]; - s->didx.ptr.p_int[i] = k; - if( d==u ) - { - - /* - * Upper skyline height equal to lower skyline height, - * simple exchange is needed for transposition - */ - t0 = s->ridx.ptr.p_int[i]; - for(k=0; k<=d-1; k++) - { - v = s->vals.ptr.p_double[t0+k]; - s->vals.ptr.p_double[t0+k] = s->vals.ptr.p_double[t0+d+1+k]; - s->vals.ptr.p_double[t0+d+1+k] = v; - } - } - if( d>u ) - { - - /* - * Upper skyline height is less than lower skyline height. - * - * Transposition becomes a bit tricky: we have to rearrange - * "L0 L1 D U" to "U D L0 L1", where |L0|=|U|=u, |L1|=d-u. - * - * In order to do this we perform a sequence of swaps and - * in-place reversals: - * * swap(L0,U) => "U L1 D L0" - * * reverse("L1 D L0") => "U L0~ D L1~" (where X~ is a reverse of X) - * * reverse("L0~ D") => "U D L0 L1~" - * * reverse("L1") => "U D L0 L1" - */ - t0 = s->ridx.ptr.p_int[i]; - t1 = s->ridx.ptr.p_int[i]+d+1; - for(k=0; k<=u-1; k++) - { - v = s->vals.ptr.p_double[t0+k]; - s->vals.ptr.p_double[t0+k] = s->vals.ptr.p_double[t1+k]; - s->vals.ptr.p_double[t1+k] = v; - } - t0 = s->ridx.ptr.p_int[i]+u; - t1 = s->ridx.ptr.p_int[i+1]-1; - while(t1>t0) - { - v = s->vals.ptr.p_double[t0]; - s->vals.ptr.p_double[t0] = s->vals.ptr.p_double[t1]; - s->vals.ptr.p_double[t1] = v; - t0 = t0+1; - t1 = t1-1; - } - t0 = s->ridx.ptr.p_int[i]+u; - t1 = s->ridx.ptr.p_int[i]+u+u; - while(t1>t0) - { - v = s->vals.ptr.p_double[t0]; - s->vals.ptr.p_double[t0] = s->vals.ptr.p_double[t1]; - s->vals.ptr.p_double[t1] = v; - t0 = t0+1; - t1 = t1-1; - } - t0 = s->ridx.ptr.p_int[i+1]-(d-u); - t1 = s->ridx.ptr.p_int[i+1]-1; - while(t1>t0) - { - v = s->vals.ptr.p_double[t0]; - s->vals.ptr.p_double[t0] = s->vals.ptr.p_double[t1]; - s->vals.ptr.p_double[t1] = v; - t0 = t0+1; - t1 = t1-1; - } - } - if( d "U1 D U0 L" - * * reverse("U1 D U0") => "U0~ D U1~ L" (where X~ is a reverse of X) - * * reverse("U0~") => "U0 D U1~ L" - * * reverse("D U1~") => "U0 U1 D L" - */ - t0 = s->ridx.ptr.p_int[i]; - t1 = s->ridx.ptr.p_int[i+1]-d; - for(k=0; k<=d-1; k++) - { - v = s->vals.ptr.p_double[t0+k]; - s->vals.ptr.p_double[t0+k] = s->vals.ptr.p_double[t1+k]; - s->vals.ptr.p_double[t1+k] = v; - } - t0 = s->ridx.ptr.p_int[i]; - t1 = s->ridx.ptr.p_int[i]+u; - while(t1>t0) - { - v = s->vals.ptr.p_double[t0]; - s->vals.ptr.p_double[t0] = s->vals.ptr.p_double[t1]; - s->vals.ptr.p_double[t1] = v; - t0 = t0+1; - t1 = t1-1; - } - t0 = s->ridx.ptr.p_int[i]; - t1 = s->ridx.ptr.p_int[i]+u-d-1; - while(t1>t0) - { - v = s->vals.ptr.p_double[t0]; - s->vals.ptr.p_double[t0] = s->vals.ptr.p_double[t1]; - s->vals.ptr.p_double[t1] = v; - t0 = t0+1; - t1 = t1-1; - } - t0 = s->ridx.ptr.p_int[i]+u-d; - t1 = s->ridx.ptr.p_int[i+1]-d-1; - while(t1>t0) - { - v = s->vals.ptr.p_double[t0]; - s->vals.ptr.p_double[t0] = s->vals.ptr.p_double[t1]; - s->vals.ptr.p_double[t1] = v; - t0 = t0+1; - t1 = t1-1; - } - } - } - k = s->uidx.ptr.p_int[n]; - s->uidx.ptr.p_int[n] = s->didx.ptr.p_int[n]; - s->didx.ptr.p_int[n] = k; -} - - -/************************************************************************* -This function performs transpose of CRS matrix. - -INPUT PARAMETERS - S - sparse matrix in CRS format. - -OUTPUT PARAMETERS - S - sparse matrix, transposed. - -NOTE: internal temporary copy is allocated for the purposes of - transposition. It is deallocated after transposition. - - -- ALGLIB PROJECT -- - Copyright 30.01.2018 by Bochkanov Sergey -*************************************************************************/ -void sparsetransposecrs(sparsematrix* s, ae_state *_state) -{ - ae_frame _frame_block; - ae_vector oldvals; - ae_vector oldidx; - ae_vector oldridx; - ae_int_t oldn; - ae_int_t oldm; - ae_int_t newn; - ae_int_t newm; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t nonne; - ae_vector counts; - - ae_frame_make(_state, &_frame_block); - memset(&oldvals, 0, sizeof(oldvals)); - memset(&oldidx, 0, sizeof(oldidx)); - memset(&oldridx, 0, sizeof(oldridx)); - memset(&counts, 0, sizeof(counts)); - ae_vector_init(&oldvals, 0, DT_REAL, _state, ae_true); - ae_vector_init(&oldidx, 0, DT_INT, _state, ae_true); - ae_vector_init(&oldridx, 0, DT_INT, _state, ae_true); - ae_vector_init(&counts, 0, DT_INT, _state, ae_true); - - ae_assert(s->matrixtype==1, "SparseTransposeCRS: only CRS matrices are supported", _state); - ae_swap_vectors(&s->vals, &oldvals); - ae_swap_vectors(&s->idx, &oldidx); - ae_swap_vectors(&s->ridx, &oldridx); - oldn = s->n; - oldm = s->m; - newn = oldm; - newm = oldn; - - /* - * Update matrix size - */ - s->n = newn; - s->m = newm; - - /* - * Fill RIdx by number of elements per row: - * RIdx[I+1] stores number of elements in I-th row. - * - * Convert RIdx from row sizes to row offsets. - * Set NInitialized - */ - nonne = 0; - ivectorsetlengthatleast(&s->ridx, newm+1, _state); - for(i=0; i<=newm; i++) - { - s->ridx.ptr.p_int[i] = 0; - } - for(i=0; i<=oldm-1; i++) - { - for(j=oldridx.ptr.p_int[i]; j<=oldridx.ptr.p_int[i+1]-1; j++) - { - k = oldidx.ptr.p_int[j]+1; - s->ridx.ptr.p_int[k] = s->ridx.ptr.p_int[k]+1; - nonne = nonne+1; - } - } - for(i=0; i<=newm-1; i++) - { - s->ridx.ptr.p_int[i+1] = s->ridx.ptr.p_int[i+1]+s->ridx.ptr.p_int[i]; - } - s->ninitialized = s->ridx.ptr.p_int[newm]; - - /* - * Allocate memory and move elements to Vals/Idx. - */ - ae_vector_set_length(&counts, newm, _state); - for(i=0; i<=newm-1; i++) - { - counts.ptr.p_int[i] = 0; - } - rvectorsetlengthatleast(&s->vals, nonne, _state); - ivectorsetlengthatleast(&s->idx, nonne, _state); - for(i=0; i<=oldm-1; i++) - { - for(j=oldridx.ptr.p_int[i]; j<=oldridx.ptr.p_int[i+1]-1; j++) - { - k = oldidx.ptr.p_int[j]; - k = s->ridx.ptr.p_int[k]+counts.ptr.p_int[k]; - s->idx.ptr.p_int[k] = i; - s->vals.ptr.p_double[k] = oldvals.ptr.p_double[j]; - k = oldidx.ptr.p_int[j]; - counts.ptr.p_int[k] = counts.ptr.p_int[k]+1; - } - } - - /* - * Initialization 'S.UIdx' and 'S.DIdx' - */ - sparseinitduidx(s, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function performs copying with transposition of CRS matrix. - -INPUT PARAMETERS - S0 - sparse matrix in CRS format. - -OUTPUT PARAMETERS - S1 - sparse matrix, transposed - - -- ALGLIB PROJECT -- - Copyright 23.07.2018 by Bochkanov Sergey -*************************************************************************/ -void sparsecopytransposecrs(sparsematrix* s0, - sparsematrix* s1, - ae_state *_state) -{ - - _sparsematrix_clear(s1); - - sparsecopytransposecrsbuf(s0, s1, _state); -} - - -/************************************************************************* -This function performs copying with transposition of CRS matrix (buffered -version which reuses memory already allocated by the target as much as -possible). - -INPUT PARAMETERS - S0 - sparse matrix in CRS format. - -OUTPUT PARAMETERS - S1 - sparse matrix, transposed; previously allocated memory is - reused if possible. - - -- ALGLIB PROJECT -- - Copyright 23.07.2018 by Bochkanov Sergey -*************************************************************************/ -void sparsecopytransposecrsbuf(sparsematrix* s0, - sparsematrix* s1, - ae_state *_state) -{ - ae_int_t oldn; - ae_int_t oldm; - ae_int_t newn; - ae_int_t newm; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t kk; - ae_int_t j0; - ae_int_t j1; - - - ae_assert(s0->matrixtype==1, "SparseCopyTransposeCRSBuf: only CRS matrices are supported", _state); - oldn = s0->n; - oldm = s0->m; - newn = oldm; - newm = oldn; - - /* - * Update matrix size - */ - s1->matrixtype = 1; - s1->n = newn; - s1->m = newm; - - /* - * Fill RIdx by number of elements per row: - * RIdx[I+1] stores number of elements in I-th row. - * - * Convert RIdx from row sizes to row offsets. - * Set NInitialized - */ - isetallocv(newm+1, 0, &s1->ridx, _state); - for(i=0; i<=oldm-1; i++) - { - j0 = s0->ridx.ptr.p_int[i]; - j1 = s0->ridx.ptr.p_int[i+1]-1; - for(j=j0; j<=j1; j++) - { - k = s0->idx.ptr.p_int[j]+1; - s1->ridx.ptr.p_int[k] = s1->ridx.ptr.p_int[k]+1; - } - } - for(i=0; i<=newm-1; i++) - { - s1->ridx.ptr.p_int[i+1] = s1->ridx.ptr.p_int[i+1]+s1->ridx.ptr.p_int[i]; - } - s1->ninitialized = s1->ridx.ptr.p_int[newm]; - - /* - * Allocate memory and move elements to Vals/Idx. - */ - ivectorsetlengthatleast(&s1->didx, newm, _state); - for(i=0; i<=newm-1; i++) - { - s1->didx.ptr.p_int[i] = s1->ridx.ptr.p_int[i]; - } - rvectorsetlengthatleast(&s1->vals, s1->ninitialized, _state); - ivectorsetlengthatleast(&s1->idx, s1->ninitialized, _state); - for(i=0; i<=oldm-1; i++) - { - j0 = s0->ridx.ptr.p_int[i]; - j1 = s0->ridx.ptr.p_int[i+1]-1; - for(j=j0; j<=j1; j++) - { - kk = s0->idx.ptr.p_int[j]; - k = s1->didx.ptr.p_int[kk]; - s1->idx.ptr.p_int[k] = i; - s1->vals.ptr.p_double[k] = s0->vals.ptr.p_double[j]; - s1->didx.ptr.p_int[kk] = k+1; - } - } - - /* - * Initialization 'S.UIdx' and 'S.DIdx' - */ - sparseinitduidx(s1, _state); -} - - -/************************************************************************* -This function performs in-place conversion to desired sparse storage -format. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - Fmt - desired storage format of the output, as returned by - SparseGetMatrixType() function: - * 0 for hash-based storage - * 1 for CRS - * 2 for SKS - -OUTPUT PARAMETERS - S0 - sparse matrix in requested format. - -NOTE: in-place conversion wastes a lot of memory which is used to store - temporaries. If you perform a lot of repeated conversions, we - recommend to use out-of-place buffered conversion functions, like - SparseCopyToBuf(), which can reuse already allocated memory. - - -- ALGLIB PROJECT -- - Copyright 16.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparseconvertto(sparsematrix* s0, ae_int_t fmt, ae_state *_state) -{ - - - ae_assert((fmt==0||fmt==1)||fmt==2, "SparseConvertTo: invalid fmt parameter", _state); - if( fmt==0 ) - { - sparseconverttohash(s0, _state); - return; - } - if( fmt==1 ) - { - sparseconverttocrs(s0, _state); - return; - } - if( fmt==2 ) - { - sparseconverttosks(s0, _state); - return; - } - ae_assert(ae_false, "SparseConvertTo: invalid matrix type", _state); -} - - -/************************************************************************* -This function performs out-of-place conversion to desired sparse storage -format. S0 is copied to S1 and converted on-the-fly. Memory allocated in -S1 is reused to maximum extent possible. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - Fmt - desired storage format of the output, as returned by - SparseGetMatrixType() function: - * 0 for hash-based storage - * 1 for CRS - * 2 for SKS - -OUTPUT PARAMETERS - S1 - sparse matrix in requested format. - - -- ALGLIB PROJECT -- - Copyright 16.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsecopytobuf(sparsematrix* s0, - ae_int_t fmt, - sparsematrix* s1, - ae_state *_state) -{ - - - ae_assert((fmt==0||fmt==1)||fmt==2, "SparseCopyToBuf: invalid fmt parameter", _state); - if( fmt==0 ) - { - sparsecopytohashbuf(s0, s1, _state); - return; - } - if( fmt==1 ) - { - sparsecopytocrsbuf(s0, s1, _state); - return; - } - if( fmt==2 ) - { - sparsecopytosksbuf(s0, s1, _state); - return; - } - ae_assert(ae_false, "SparseCopyToBuf: invalid matrix type", _state); -} - - -/************************************************************************* -This function performs in-place conversion to Hash table storage. - -INPUT PARAMETERS - S - sparse matrix in CRS format. - -OUTPUT PARAMETERS - S - sparse matrix in Hash table format. - -NOTE: this function has no effect when called with matrix which is - already in Hash table mode. - -NOTE: in-place conversion involves allocation of temporary arrays. If you - perform a lot of repeated in- place conversions, it may lead to - memory fragmentation. Consider using out-of-place SparseCopyToHashBuf() - function in this case. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -void sparseconverttohash(sparsematrix* s, ae_state *_state) -{ - ae_frame _frame_block; - ae_vector tidx; - ae_vector tridx; - ae_vector tdidx; - ae_vector tuidx; - ae_vector tvals; - ae_int_t n; - ae_int_t m; - ae_int_t offs0; - ae_int_t i; - ae_int_t j; - ae_int_t k; - - ae_frame_make(_state, &_frame_block); - memset(&tidx, 0, sizeof(tidx)); - memset(&tridx, 0, sizeof(tridx)); - memset(&tdidx, 0, sizeof(tdidx)); - memset(&tuidx, 0, sizeof(tuidx)); - memset(&tvals, 0, sizeof(tvals)); - ae_vector_init(&tidx, 0, DT_INT, _state, ae_true); - ae_vector_init(&tridx, 0, DT_INT, _state, ae_true); - ae_vector_init(&tdidx, 0, DT_INT, _state, ae_true); - ae_vector_init(&tuidx, 0, DT_INT, _state, ae_true); - ae_vector_init(&tvals, 0, DT_REAL, _state, ae_true); - - ae_assert((s->matrixtype==0||s->matrixtype==1)||s->matrixtype==2, "SparseConvertToHash: invalid matrix type", _state); - if( s->matrixtype==0 ) - { - - /* - * Already in Hash mode - */ - ae_frame_leave(_state); - return; - } - if( s->matrixtype==1 ) - { - - /* - * From CRS to Hash - */ - s->matrixtype = 0; - m = s->m; - n = s->n; - ae_swap_vectors(&s->idx, &tidx); - ae_swap_vectors(&s->ridx, &tridx); - ae_swap_vectors(&s->vals, &tvals); - sparsecreatebuf(m, n, tridx.ptr.p_int[m], s, _state); - for(i=0; i<=m-1; i++) - { - for(j=tridx.ptr.p_int[i]; j<=tridx.ptr.p_int[i+1]-1; j++) - { - sparseset(s, i, tidx.ptr.p_int[j], tvals.ptr.p_double[j], _state); - } - } - ae_frame_leave(_state); - return; - } - if( s->matrixtype==2 ) - { - - /* - * From SKS to Hash - */ - s->matrixtype = 0; - m = s->m; - n = s->n; - ae_swap_vectors(&s->ridx, &tridx); - ae_swap_vectors(&s->didx, &tdidx); - ae_swap_vectors(&s->uidx, &tuidx); - ae_swap_vectors(&s->vals, &tvals); - sparsecreatebuf(m, n, tridx.ptr.p_int[m], s, _state); - for(i=0; i<=m-1; i++) - { - - /* - * copy subdiagonal and diagonal parts of I-th block - */ - offs0 = tridx.ptr.p_int[i]; - k = tdidx.ptr.p_int[i]+1; - for(j=0; j<=k-1; j++) - { - sparseset(s, i, i-tdidx.ptr.p_int[i]+j, tvals.ptr.p_double[offs0+j], _state); - } - - /* - * Copy superdiagonal part of I-th block - */ - offs0 = tridx.ptr.p_int[i]+tdidx.ptr.p_int[i]+1; - k = tuidx.ptr.p_int[i]; - for(j=0; j<=k-1; j++) - { - sparseset(s, i-k+j, i, tvals.ptr.p_double[offs0+j], _state); - } - } - ae_frame_leave(_state); - return; - } - ae_assert(ae_false, "SparseConvertToHash: invalid matrix type", _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function performs out-of-place conversion to Hash table storage -format. S0 is copied to S1 and converted on-the-fly. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - -OUTPUT PARAMETERS - S1 - sparse matrix in Hash table format. - -NOTE: if S0 is stored as Hash-table, it is just copied without conversion. - -NOTE: this function de-allocates memory occupied by S1 before starting - conversion. If you perform a lot of repeated conversions, it may - lead to memory fragmentation. In this case we recommend you to use - SparseCopyToHashBuf() function which re-uses memory in S1 as much as - possible. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -void sparsecopytohash(sparsematrix* s0, - sparsematrix* s1, - ae_state *_state) -{ - - _sparsematrix_clear(s1); - - ae_assert((s0->matrixtype==0||s0->matrixtype==1)||s0->matrixtype==2, "SparseCopyToHash: invalid matrix type", _state); - sparsecopytohashbuf(s0, s1, _state); -} - - -/************************************************************************* -This function performs out-of-place conversion to Hash table storage -format. S0 is copied to S1 and converted on-the-fly. Memory allocated in -S1 is reused to maximum extent possible. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - -OUTPUT PARAMETERS - S1 - sparse matrix in Hash table format. - -NOTE: if S0 is stored as Hash-table, it is just copied without conversion. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -void sparsecopytohashbuf(sparsematrix* s0, - sparsematrix* s1, - ae_state *_state) -{ - double val; - ae_int_t t0; - ae_int_t t1; - ae_int_t i; - ae_int_t j; - - - ae_assert((s0->matrixtype==0||s0->matrixtype==1)||s0->matrixtype==2, "SparseCopyToHashBuf: invalid matrix type", _state); - if( s0->matrixtype==0 ) - { - - /* - * Already hash, just copy - */ - sparsecopybuf(s0, s1, _state); - return; - } - if( s0->matrixtype==1 ) - { - - /* - * CRS storage - */ - t0 = 0; - t1 = 0; - sparsecreatebuf(s0->m, s0->n, s0->ridx.ptr.p_int[s0->m], s1, _state); - while(sparseenumerate(s0, &t0, &t1, &i, &j, &val, _state)) - { - sparseset(s1, i, j, val, _state); - } - return; - } - if( s0->matrixtype==2 ) - { - - /* - * SKS storage - */ - t0 = 0; - t1 = 0; - sparsecreatebuf(s0->m, s0->n, s0->ridx.ptr.p_int[s0->m], s1, _state); - while(sparseenumerate(s0, &t0, &t1, &i, &j, &val, _state)) - { - sparseset(s1, i, j, val, _state); - } - return; - } - ae_assert(ae_false, "SparseCopyToHashBuf: invalid matrix type", _state); -} - - -/************************************************************************* -This function converts matrix to CRS format. - -Some algorithms (linear algebra ones, for example) require matrices in -CRS format. This function allows to perform in-place conversion. - -INPUT PARAMETERS - S - sparse M*N matrix in any format - -OUTPUT PARAMETERS - S - matrix in CRS format - -NOTE: this function has no effect when called with matrix which is - already in CRS mode. - -NOTE: this function allocates temporary memory to store a copy of the - matrix. If you perform a lot of repeated conversions, we recommend - you to use SparseCopyToCRSBuf() function, which can reuse - previously allocated memory. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparseconverttocrs(sparsematrix* s, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t m; - ae_int_t i; - ae_int_t j; - ae_vector tvals; - ae_vector tidx; - ae_vector temp; - ae_vector tridx; - ae_int_t nonne; - ae_int_t k; - ae_int_t offs0; - ae_int_t offs1; - - ae_frame_make(_state, &_frame_block); - memset(&tvals, 0, sizeof(tvals)); - memset(&tidx, 0, sizeof(tidx)); - memset(&temp, 0, sizeof(temp)); - memset(&tridx, 0, sizeof(tridx)); - ae_vector_init(&tvals, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tidx, 0, DT_INT, _state, ae_true); - ae_vector_init(&temp, 0, DT_INT, _state, ae_true); - ae_vector_init(&tridx, 0, DT_INT, _state, ae_true); - - m = s->m; - if( s->matrixtype==0 ) - { - - /* - * From Hash-table to CRS. - * First, create local copy of the hash table. - */ - s->matrixtype = 1; - k = s->tablesize; - ae_swap_vectors(&s->vals, &tvals); - ae_swap_vectors(&s->idx, &tidx); - - /* - * Fill RIdx by number of elements per row: - * RIdx[I+1] stores number of elements in I-th row. - * - * Convert RIdx from row sizes to row offsets. - * Set NInitialized - */ - nonne = 0; - ivectorsetlengthatleast(&s->ridx, s->m+1, _state); - for(i=0; i<=s->m; i++) - { - s->ridx.ptr.p_int[i] = 0; - } - for(i=0; i<=k-1; i++) - { - if( tidx.ptr.p_int[2*i]>=0 ) - { - s->ridx.ptr.p_int[tidx.ptr.p_int[2*i]+1] = s->ridx.ptr.p_int[tidx.ptr.p_int[2*i]+1]+1; - nonne = nonne+1; - } - } - for(i=0; i<=s->m-1; i++) - { - s->ridx.ptr.p_int[i+1] = s->ridx.ptr.p_int[i+1]+s->ridx.ptr.p_int[i]; - } - s->ninitialized = s->ridx.ptr.p_int[s->m]; - - /* - * Allocate memory and move elements to Vals/Idx. - * Initially, elements are sorted by rows, but unsorted within row. - * After initial insertion we sort elements within row. - */ - ae_vector_set_length(&temp, s->m, _state); - for(i=0; i<=s->m-1; i++) - { - temp.ptr.p_int[i] = 0; - } - rvectorsetlengthatleast(&s->vals, nonne, _state); - ivectorsetlengthatleast(&s->idx, nonne, _state); - for(i=0; i<=k-1; i++) - { - if( tidx.ptr.p_int[2*i]>=0 ) - { - s->vals.ptr.p_double[s->ridx.ptr.p_int[tidx.ptr.p_int[2*i]]+temp.ptr.p_int[tidx.ptr.p_int[2*i]]] = tvals.ptr.p_double[i]; - s->idx.ptr.p_int[s->ridx.ptr.p_int[tidx.ptr.p_int[2*i]]+temp.ptr.p_int[tidx.ptr.p_int[2*i]]] = tidx.ptr.p_int[2*i+1]; - temp.ptr.p_int[tidx.ptr.p_int[2*i]] = temp.ptr.p_int[tidx.ptr.p_int[2*i]]+1; - } - } - for(i=0; i<=s->m-1; i++) - { - tagsortmiddleir(&s->idx, &s->vals, s->ridx.ptr.p_int[i], s->ridx.ptr.p_int[i+1]-s->ridx.ptr.p_int[i], _state); - } - - /* - * Initialization 'S.UIdx' and 'S.DIdx' - */ - sparseinitduidx(s, _state); - ae_frame_leave(_state); - return; - } - if( s->matrixtype==1 ) - { - - /* - * Already CRS - */ - ae_frame_leave(_state); - return; - } - if( s->matrixtype==2 ) - { - ae_assert(s->m==s->n, "SparseConvertToCRS: non-square SKS matrices are not supported", _state); - - /* - * From SKS to CRS. - * - * First, create local copy of the SKS matrix (Vals, - * Idx, RIdx are stored; DIdx/UIdx for some time are - * left in the SparseMatrix structure). - */ - s->matrixtype = 1; - ae_swap_vectors(&s->vals, &tvals); - ae_swap_vectors(&s->idx, &tidx); - ae_swap_vectors(&s->ridx, &tridx); - - /* - * Fill RIdx by number of elements per row: - * RIdx[I+1] stores number of elements in I-th row. - * - * Convert RIdx from row sizes to row offsets. - * Set NInitialized - */ - ivectorsetlengthatleast(&s->ridx, m+1, _state); - s->ridx.ptr.p_int[0] = 0; - for(i=1; i<=m; i++) - { - s->ridx.ptr.p_int[i] = 1; - } - nonne = 0; - for(i=0; i<=m-1; i++) - { - s->ridx.ptr.p_int[i+1] = s->didx.ptr.p_int[i]+s->ridx.ptr.p_int[i+1]; - for(j=i-s->uidx.ptr.p_int[i]; j<=i-1; j++) - { - s->ridx.ptr.p_int[j+1] = s->ridx.ptr.p_int[j+1]+1; - } - nonne = nonne+s->didx.ptr.p_int[i]+1+s->uidx.ptr.p_int[i]; - } - for(i=0; i<=s->m-1; i++) - { - s->ridx.ptr.p_int[i+1] = s->ridx.ptr.p_int[i+1]+s->ridx.ptr.p_int[i]; - } - s->ninitialized = s->ridx.ptr.p_int[s->m]; - - /* - * Allocate memory and move elements to Vals/Idx. - * Initially, elements are sorted by rows, and are sorted within row too. - * No additional post-sorting is required. - */ - ae_vector_set_length(&temp, m, _state); - for(i=0; i<=m-1; i++) - { - temp.ptr.p_int[i] = 0; - } - rvectorsetlengthatleast(&s->vals, nonne, _state); - ivectorsetlengthatleast(&s->idx, nonne, _state); - for(i=0; i<=m-1; i++) - { - - /* - * copy subdiagonal and diagonal parts of I-th block - */ - offs0 = tridx.ptr.p_int[i]; - offs1 = s->ridx.ptr.p_int[i]+temp.ptr.p_int[i]; - k = s->didx.ptr.p_int[i]+1; - for(j=0; j<=k-1; j++) - { - s->vals.ptr.p_double[offs1+j] = tvals.ptr.p_double[offs0+j]; - s->idx.ptr.p_int[offs1+j] = i-s->didx.ptr.p_int[i]+j; - } - temp.ptr.p_int[i] = temp.ptr.p_int[i]+s->didx.ptr.p_int[i]+1; - - /* - * Copy superdiagonal part of I-th block - */ - offs0 = tridx.ptr.p_int[i]+s->didx.ptr.p_int[i]+1; - k = s->uidx.ptr.p_int[i]; - for(j=0; j<=k-1; j++) - { - offs1 = s->ridx.ptr.p_int[i-k+j]+temp.ptr.p_int[i-k+j]; - s->vals.ptr.p_double[offs1] = tvals.ptr.p_double[offs0+j]; - s->idx.ptr.p_int[offs1] = i; - temp.ptr.p_int[i-k+j] = temp.ptr.p_int[i-k+j]+1; - } - } - - /* - * Initialization 'S.UIdx' and 'S.DIdx' - */ - sparseinitduidx(s, _state); - ae_frame_leave(_state); - return; - } - ae_assert(ae_false, "SparseConvertToCRS: invalid matrix type", _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function performs out-of-place conversion to CRS format. S0 is -copied to S1 and converted on-the-fly. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - -OUTPUT PARAMETERS - S1 - sparse matrix in CRS format. - -NOTE: if S0 is stored as CRS, it is just copied without conversion. - -NOTE: this function de-allocates memory occupied by S1 before starting CRS - conversion. If you perform a lot of repeated CRS conversions, it may - lead to memory fragmentation. In this case we recommend you to use - SparseCopyToCRSBuf() function which re-uses memory in S1 as much as - possible. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -void sparsecopytocrs(sparsematrix* s0, sparsematrix* s1, ae_state *_state) -{ - - _sparsematrix_clear(s1); - - ae_assert((s0->matrixtype==0||s0->matrixtype==1)||s0->matrixtype==2, "SparseCopyToCRS: invalid matrix type", _state); - sparsecopytocrsbuf(s0, s1, _state); -} - - -/************************************************************************* -This function performs out-of-place conversion to CRS format. S0 is -copied to S1 and converted on-the-fly. Memory allocated in S1 is reused to -maximum extent possible. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - S1 - matrix which may contain some pre-allocated memory, or - can be just uninitialized structure. - -OUTPUT PARAMETERS - S1 - sparse matrix in CRS format. - -NOTE: if S0 is stored as CRS, it is just copied without conversion. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -void sparsecopytocrsbuf(sparsematrix* s0, - sparsematrix* s1, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector temp; - ae_int_t nonne; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t offs0; - ae_int_t offs1; - ae_int_t m; - - ae_frame_make(_state, &_frame_block); - memset(&temp, 0, sizeof(temp)); - ae_vector_init(&temp, 0, DT_INT, _state, ae_true); - - ae_assert((s0->matrixtype==0||s0->matrixtype==1)||s0->matrixtype==2, "SparseCopyToCRSBuf: invalid matrix type", _state); - m = s0->m; - if( s0->matrixtype==0 ) - { - - /* - * Convert from hash-table to CRS - * Done like ConvertToCRS function - */ - s1->matrixtype = 1; - s1->m = s0->m; - s1->n = s0->n; - s1->nfree = s0->nfree; - nonne = 0; - k = s0->tablesize; - ivectorsetlengthatleast(&s1->ridx, s1->m+1, _state); - for(i=0; i<=s1->m; i++) - { - s1->ridx.ptr.p_int[i] = 0; - } - ae_vector_set_length(&temp, s1->m, _state); - for(i=0; i<=s1->m-1; i++) - { - temp.ptr.p_int[i] = 0; - } - - /* - * Number of elements per row - */ - for(i=0; i<=k-1; i++) - { - if( s0->idx.ptr.p_int[2*i]>=0 ) - { - s1->ridx.ptr.p_int[s0->idx.ptr.p_int[2*i]+1] = s1->ridx.ptr.p_int[s0->idx.ptr.p_int[2*i]+1]+1; - nonne = nonne+1; - } - } - - /* - * Fill RIdx (offsets of rows) - */ - for(i=0; i<=s1->m-1; i++) - { - s1->ridx.ptr.p_int[i+1] = s1->ridx.ptr.p_int[i+1]+s1->ridx.ptr.p_int[i]; - } - - /* - * Allocate memory - */ - rvectorsetlengthatleast(&s1->vals, nonne, _state); - ivectorsetlengthatleast(&s1->idx, nonne, _state); - for(i=0; i<=k-1; i++) - { - if( s0->idx.ptr.p_int[2*i]>=0 ) - { - s1->vals.ptr.p_double[s1->ridx.ptr.p_int[s0->idx.ptr.p_int[2*i]]+temp.ptr.p_int[s0->idx.ptr.p_int[2*i]]] = s0->vals.ptr.p_double[i]; - s1->idx.ptr.p_int[s1->ridx.ptr.p_int[s0->idx.ptr.p_int[2*i]]+temp.ptr.p_int[s0->idx.ptr.p_int[2*i]]] = s0->idx.ptr.p_int[2*i+1]; - temp.ptr.p_int[s0->idx.ptr.p_int[2*i]] = temp.ptr.p_int[s0->idx.ptr.p_int[2*i]]+1; - } - } - - /* - * Set NInitialized - */ - s1->ninitialized = s1->ridx.ptr.p_int[s1->m]; - - /* - * Sorting of elements - */ - for(i=0; i<=s1->m-1; i++) - { - tagsortmiddleir(&s1->idx, &s1->vals, s1->ridx.ptr.p_int[i], s1->ridx.ptr.p_int[i+1]-s1->ridx.ptr.p_int[i], _state); - } - - /* - * Initialization 'S.UIdx' and 'S.DIdx' - */ - sparseinitduidx(s1, _state); - ae_frame_leave(_state); - return; - } - if( s0->matrixtype==1 ) - { - - /* - * Already CRS, just copy - */ - sparsecopybuf(s0, s1, _state); - ae_frame_leave(_state); - return; - } - if( s0->matrixtype==2 ) - { - ae_assert(s0->m==s0->n, "SparseCopyToCRS: non-square SKS matrices are not supported", _state); - - /* - * From SKS to CRS. - */ - s1->m = s0->m; - s1->n = s0->n; - s1->matrixtype = 1; - - /* - * Fill RIdx by number of elements per row: - * RIdx[I+1] stores number of elements in I-th row. - * - * Convert RIdx from row sizes to row offsets. - * Set NInitialized - */ - ivectorsetlengthatleast(&s1->ridx, m+1, _state); - s1->ridx.ptr.p_int[0] = 0; - for(i=1; i<=m; i++) - { - s1->ridx.ptr.p_int[i] = 1; - } - nonne = 0; - for(i=0; i<=m-1; i++) - { - s1->ridx.ptr.p_int[i+1] = s0->didx.ptr.p_int[i]+s1->ridx.ptr.p_int[i+1]; - for(j=i-s0->uidx.ptr.p_int[i]; j<=i-1; j++) - { - s1->ridx.ptr.p_int[j+1] = s1->ridx.ptr.p_int[j+1]+1; - } - nonne = nonne+s0->didx.ptr.p_int[i]+1+s0->uidx.ptr.p_int[i]; - } - for(i=0; i<=m-1; i++) - { - s1->ridx.ptr.p_int[i+1] = s1->ridx.ptr.p_int[i+1]+s1->ridx.ptr.p_int[i]; - } - s1->ninitialized = s1->ridx.ptr.p_int[m]; - - /* - * Allocate memory and move elements to Vals/Idx. - * Initially, elements are sorted by rows, and are sorted within row too. - * No additional post-sorting is required. - */ - ae_vector_set_length(&temp, m, _state); - for(i=0; i<=m-1; i++) - { - temp.ptr.p_int[i] = 0; - } - rvectorsetlengthatleast(&s1->vals, nonne, _state); - ivectorsetlengthatleast(&s1->idx, nonne, _state); - for(i=0; i<=m-1; i++) - { - - /* - * copy subdiagonal and diagonal parts of I-th block - */ - offs0 = s0->ridx.ptr.p_int[i]; - offs1 = s1->ridx.ptr.p_int[i]+temp.ptr.p_int[i]; - k = s0->didx.ptr.p_int[i]+1; - for(j=0; j<=k-1; j++) - { - s1->vals.ptr.p_double[offs1+j] = s0->vals.ptr.p_double[offs0+j]; - s1->idx.ptr.p_int[offs1+j] = i-s0->didx.ptr.p_int[i]+j; - } - temp.ptr.p_int[i] = temp.ptr.p_int[i]+s0->didx.ptr.p_int[i]+1; - - /* - * Copy superdiagonal part of I-th block - */ - offs0 = s0->ridx.ptr.p_int[i]+s0->didx.ptr.p_int[i]+1; - k = s0->uidx.ptr.p_int[i]; - for(j=0; j<=k-1; j++) - { - offs1 = s1->ridx.ptr.p_int[i-k+j]+temp.ptr.p_int[i-k+j]; - s1->vals.ptr.p_double[offs1] = s0->vals.ptr.p_double[offs0+j]; - s1->idx.ptr.p_int[offs1] = i; - temp.ptr.p_int[i-k+j] = temp.ptr.p_int[i-k+j]+1; - } - } - - /* - * Initialization 'S.UIdx' and 'S.DIdx' - */ - sparseinitduidx(s1, _state); - ae_frame_leave(_state); - return; - } - ae_assert(ae_false, "SparseCopyToCRSBuf: unexpected matrix type", _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function performs in-place conversion to SKS format. - -INPUT PARAMETERS - S - sparse matrix in any format. - -OUTPUT PARAMETERS - S - sparse matrix in SKS format. - -NOTE: this function has no effect when called with matrix which is - already in SKS mode. - -NOTE: in-place conversion involves allocation of temporary arrays. If you - perform a lot of repeated in- place conversions, it may lead to - memory fragmentation. Consider using out-of-place SparseCopyToSKSBuf() - function in this case. - - -- ALGLIB PROJECT -- - Copyright 15.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparseconverttosks(sparsematrix* s, ae_state *_state) -{ - ae_frame _frame_block; - ae_vector tridx; - ae_vector tdidx; - ae_vector tuidx; - ae_vector tvals; - ae_int_t n; - ae_int_t t0; - ae_int_t t1; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&tridx, 0, sizeof(tridx)); - memset(&tdidx, 0, sizeof(tdidx)); - memset(&tuidx, 0, sizeof(tuidx)); - memset(&tvals, 0, sizeof(tvals)); - ae_vector_init(&tridx, 0, DT_INT, _state, ae_true); - ae_vector_init(&tdidx, 0, DT_INT, _state, ae_true); - ae_vector_init(&tuidx, 0, DT_INT, _state, ae_true); - ae_vector_init(&tvals, 0, DT_REAL, _state, ae_true); - - ae_assert((s->matrixtype==0||s->matrixtype==1)||s->matrixtype==2, "SparseConvertToSKS: invalid matrix type", _state); - ae_assert(s->m==s->n, "SparseConvertToSKS: rectangular matrices are not supported", _state); - n = s->n; - if( s->matrixtype==2 ) - { - - /* - * Already in SKS mode - */ - ae_frame_leave(_state); - return; - } - - /* - * Generate internal copy of SKS matrix - */ - ivectorsetlengthatleast(&tdidx, n+1, _state); - ivectorsetlengthatleast(&tuidx, n+1, _state); - for(i=0; i<=n; i++) - { - tdidx.ptr.p_int[i] = 0; - tuidx.ptr.p_int[i] = 0; - } - t0 = 0; - t1 = 0; - while(sparseenumerate(s, &t0, &t1, &i, &j, &v, _state)) - { - if( jmatrixtype = 2; - s->ninitialized = 0; - s->nfree = 0; - s->m = n; - s->n = n; - ae_swap_vectors(&s->didx, &tdidx); - ae_swap_vectors(&s->uidx, &tuidx); - ae_swap_vectors(&s->ridx, &tridx); - ae_swap_vectors(&s->vals, &tvals); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function performs out-of-place conversion to SKS storage format. -S0 is copied to S1 and converted on-the-fly. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - -OUTPUT PARAMETERS - S1 - sparse matrix in SKS format. - -NOTE: if S0 is stored as SKS, it is just copied without conversion. - -NOTE: this function de-allocates memory occupied by S1 before starting - conversion. If you perform a lot of repeated conversions, it may - lead to memory fragmentation. In this case we recommend you to use - SparseCopyToSKSBuf() function which re-uses memory in S1 as much as - possible. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -void sparsecopytosks(sparsematrix* s0, sparsematrix* s1, ae_state *_state) -{ - - _sparsematrix_clear(s1); - - ae_assert((s0->matrixtype==0||s0->matrixtype==1)||s0->matrixtype==2, "SparseCopyToSKS: invalid matrix type", _state); - sparsecopytosksbuf(s0, s1, _state); -} - - -/************************************************************************* -This function performs out-of-place conversion to SKS format. S0 is -copied to S1 and converted on-the-fly. Memory allocated in S1 is reused -to maximum extent possible. - -INPUT PARAMETERS - S0 - sparse matrix in any format. - -OUTPUT PARAMETERS - S1 - sparse matrix in SKS format. - -NOTE: if S0 is stored as SKS, it is just copied without conversion. - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -void sparsecopytosksbuf(sparsematrix* s0, - sparsematrix* s1, - ae_state *_state) -{ - double v; - ae_int_t n; - ae_int_t t0; - ae_int_t t1; - ae_int_t i; - ae_int_t j; - ae_int_t k; - - - ae_assert((s0->matrixtype==0||s0->matrixtype==1)||s0->matrixtype==2, "SparseCopyToSKSBuf: invalid matrix type", _state); - ae_assert(s0->m==s0->n, "SparseCopyToSKSBuf: rectangular matrices are not supported", _state); - n = s0->n; - if( s0->matrixtype==2 ) - { - - /* - * Already SKS, just copy - */ - sparsecopybuf(s0, s1, _state); - return; - } - - /* - * Generate copy of matrix in the SKS format - */ - ivectorsetlengthatleast(&s1->didx, n+1, _state); - ivectorsetlengthatleast(&s1->uidx, n+1, _state); - for(i=0; i<=n; i++) - { - s1->didx.ptr.p_int[i] = 0; - s1->uidx.ptr.p_int[i] = 0; - } - t0 = 0; - t1 = 0; - while(sparseenumerate(s0, &t0, &t1, &i, &j, &v, _state)) - { - if( jdidx.ptr.p_int[i] = ae_maxint(s1->didx.ptr.p_int[i], i-j, _state); - } - else - { - s1->uidx.ptr.p_int[j] = ae_maxint(s1->uidx.ptr.p_int[j], j-i, _state); - } - } - ivectorsetlengthatleast(&s1->ridx, n+1, _state); - s1->ridx.ptr.p_int[0] = 0; - for(i=1; i<=n; i++) - { - s1->ridx.ptr.p_int[i] = s1->ridx.ptr.p_int[i-1]+s1->didx.ptr.p_int[i-1]+1+s1->uidx.ptr.p_int[i-1]; - } - rvectorsetlengthatleast(&s1->vals, s1->ridx.ptr.p_int[n], _state); - k = s1->ridx.ptr.p_int[n]; - for(i=0; i<=k-1; i++) - { - s1->vals.ptr.p_double[i] = 0.0; - } - t0 = 0; - t1 = 0; - while(sparseenumerate(s0, &t0, &t1, &i, &j, &v, _state)) - { - if( j<=i ) - { - s1->vals.ptr.p_double[s1->ridx.ptr.p_int[i]+s1->didx.ptr.p_int[i]-(i-j)] = v; - } - else - { - s1->vals.ptr.p_double[s1->ridx.ptr.p_int[j+1]-(j-i)] = v; - } - } - for(i=0; i<=n-1; i++) - { - s1->didx.ptr.p_int[n] = ae_maxint(s1->didx.ptr.p_int[n], s1->didx.ptr.p_int[i], _state); - s1->uidx.ptr.p_int[n] = ae_maxint(s1->uidx.ptr.p_int[n], s1->uidx.ptr.p_int[i], _state); - } - s1->matrixtype = 2; - s1->ninitialized = 0; - s1->nfree = 0; - s1->m = n; - s1->n = n; -} - - -/************************************************************************* -This non-accessible to user function performs in-place creation of CRS -matrix. It is expected that: -* S.M and S.N are initialized -* S.RIdx, S.Idx and S.Vals are loaded with values in CRS format used by - ALGLIB, with elements of S.Idx/S.Vals possibly being unsorted within - each row (this constructor function may post-sort matrix, assuming that - it is sorted by rows). - -Only 5 fields should be set by caller. Other fields will be rewritten by -this constructor function. - -This function performs integrity check on user-specified values, with the -only exception being Vals[] array: -* it does not require values to be non-zero -* it does not checks for element of Vals[] being finite IEEE-754 values - -INPUT PARAMETERS - S - sparse matrix with corresponding fields set by caller - -OUTPUT PARAMETERS - S - sparse matrix in CRS format. - - -- ALGLIB PROJECT -- - Copyright 20.08.2016 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatecrsinplace(sparsematrix* s, ae_state *_state) -{ - ae_int_t m; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t j0; - ae_int_t j1; - - - m = s->m; - n = s->n; - - /* - * Quick exit for M=0 or N=0 - */ - ae_assert(s->m>=0, "SparseCreateCRSInplace: integrity check failed", _state); - ae_assert(s->n>=0, "SparseCreateCRSInplace: integrity check failed", _state); - if( m==0||n==0 ) - { - s->matrixtype = 1; - s->ninitialized = 0; - ivectorsetlengthatleast(&s->ridx, s->m+1, _state); - ivectorsetlengthatleast(&s->didx, s->m, _state); - ivectorsetlengthatleast(&s->uidx, s->m, _state); - for(i=0; i<=s->m-1; i++) - { - s->ridx.ptr.p_int[i] = 0; - s->uidx.ptr.p_int[i] = 0; - s->didx.ptr.p_int[i] = 0; - } - s->ridx.ptr.p_int[s->m] = 0; - return; - } - - /* - * Perform integrity check - */ - ae_assert(s->m>0, "SparseCreateCRSInplace: integrity check failed", _state); - ae_assert(s->n>0, "SparseCreateCRSInplace: integrity check failed", _state); - ae_assert(s->ridx.cnt>=m+1, "SparseCreateCRSInplace: integrity check failed", _state); - for(i=0; i<=m-1; i++) - { - ae_assert(s->ridx.ptr.p_int[i]>=0&&s->ridx.ptr.p_int[i]<=s->ridx.ptr.p_int[i+1], "SparseCreateCRSInplace: integrity check failed", _state); - } - ae_assert(s->ridx.ptr.p_int[m]<=s->idx.cnt, "SparseCreateCRSInplace: integrity check failed", _state); - ae_assert(s->ridx.ptr.p_int[m]<=s->vals.cnt, "SparseCreateCRSInplace: integrity check failed", _state); - for(i=0; i<=m-1; i++) - { - j0 = s->ridx.ptr.p_int[i]; - j1 = s->ridx.ptr.p_int[i+1]-1; - for(j=j0; j<=j1; j++) - { - ae_assert(s->idx.ptr.p_int[j]>=0&&s->idx.ptr.p_int[j]matrixtype = 1; - s->ninitialized = s->ridx.ptr.p_int[m]; - for(i=0; i<=m-1; i++) - { - tagsortmiddleir(&s->idx, &s->vals, s->ridx.ptr.p_int[i], s->ridx.ptr.p_int[i+1]-s->ridx.ptr.p_int[i], _state); - } - sparseinitduidx(s, _state); -} - - -/************************************************************************* -This function returns type of the matrix storage format. - -INPUT PARAMETERS: - S - sparse matrix. - -RESULT: - sparse storage format used by matrix: - 0 - Hash-table - 1 - CRS (compressed row storage) - 2 - SKS (skyline) - -NOTE: future versions of ALGLIB may include additional sparse storage - formats. - - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -ae_int_t sparsegetmatrixtype(sparsematrix* s, ae_state *_state) -{ - ae_int_t result; - - - ae_assert((((s->matrixtype==0||s->matrixtype==1)||s->matrixtype==2)||s->matrixtype==-10081)||s->matrixtype==-10082, "SparseGetMatrixType: invalid matrix type", _state); - result = s->matrixtype; - return result; -} - - -/************************************************************************* -This function checks matrix storage format and returns True when matrix is -stored using Hash table representation. - -INPUT PARAMETERS: - S - sparse matrix. - -RESULT: - True if matrix type is Hash table - False if matrix type is not Hash table - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -ae_bool sparseishash(sparsematrix* s, ae_state *_state) -{ - ae_bool result; - - - ae_assert((((s->matrixtype==0||s->matrixtype==1)||s->matrixtype==2)||s->matrixtype==-10081)||s->matrixtype==-10082, "SparseIsHash: invalid matrix type", _state); - result = s->matrixtype==0; - return result; -} - - -/************************************************************************* -This function checks matrix storage format and returns True when matrix is -stored using CRS representation. - -INPUT PARAMETERS: - S - sparse matrix. - -RESULT: - True if matrix type is CRS - False if matrix type is not CRS - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -ae_bool sparseiscrs(sparsematrix* s, ae_state *_state) -{ - ae_bool result; - - - ae_assert((((s->matrixtype==0||s->matrixtype==1)||s->matrixtype==2)||s->matrixtype==-10081)||s->matrixtype==-10082, "SparseIsCRS: invalid matrix type", _state); - result = s->matrixtype==1; - return result; -} - - -/************************************************************************* -This function checks matrix storage format and returns True when matrix is -stored using SKS representation. - -INPUT PARAMETERS: - S - sparse matrix. - -RESULT: - True if matrix type is SKS - False if matrix type is not SKS - - -- ALGLIB PROJECT -- - Copyright 20.07.2012 by Bochkanov Sergey -*************************************************************************/ -ae_bool sparseissks(sparsematrix* s, ae_state *_state) -{ - ae_bool result; - - - ae_assert((((s->matrixtype==0||s->matrixtype==1)||s->matrixtype==2)||s->matrixtype==-10081)||s->matrixtype==-10082, "SparseIsSKS: invalid matrix type", _state); - result = s->matrixtype==2; - return result; -} - - -/************************************************************************* -The function frees all memory occupied by sparse matrix. Sparse matrix -structure becomes unusable after this call. - -OUTPUT PARAMETERS - S - sparse matrix to delete - - -- ALGLIB PROJECT -- - Copyright 24.07.2012 by Bochkanov Sergey -*************************************************************************/ -void sparsefree(sparsematrix* s, ae_state *_state) -{ - - _sparsematrix_clear(s); - - s->matrixtype = -1; - s->m = 0; - s->n = 0; - s->nfree = 0; - s->ninitialized = 0; - s->tablesize = 0; -} - - -/************************************************************************* -The function returns number of rows of a sparse matrix. - -RESULT: number of rows of a sparse matrix. - - -- ALGLIB PROJECT -- - Copyright 23.08.2012 by Bochkanov Sergey -*************************************************************************/ -ae_int_t sparsegetnrows(sparsematrix* s, ae_state *_state) -{ - ae_int_t result; - - - result = s->m; - return result; -} - - -/************************************************************************* -The function returns number of columns of a sparse matrix. - -RESULT: number of columns of a sparse matrix. - - -- ALGLIB PROJECT -- - Copyright 23.08.2012 by Bochkanov Sergey -*************************************************************************/ -ae_int_t sparsegetncols(sparsematrix* s, ae_state *_state) -{ - ae_int_t result; - - - result = s->n; - return result; -} - - -/************************************************************************* -The function returns number of strictly upper triangular non-zero elements -in the matrix. It counts SYMBOLICALLY non-zero elements, i.e. entries -in the sparse matrix data structure. If some element has zero numerical -value, it is still counted. - -This function has different cost for different types of matrices: -* for hash-based matrices it involves complete pass over entire hash-table - with O(NNZ) cost, where NNZ is number of non-zero elements -* for CRS and SKS matrix types cost of counting is O(N) (N - matrix size). - -RESULT: number of non-zero elements strictly above main diagonal - - -- ALGLIB PROJECT -- - Copyright 12.02.2014 by Bochkanov Sergey -*************************************************************************/ -ae_int_t sparsegetuppercount(sparsematrix* s, ae_state *_state) -{ - ae_int_t sz; - ae_int_t i0; - ae_int_t i; - ae_int_t result; - - - result = -1; - if( s->matrixtype==0 ) - { - - /* - * Hash-table matrix - */ - result = 0; - sz = s->tablesize; - for(i0=0; i0<=sz-1; i0++) - { - i = s->idx.ptr.p_int[2*i0]; - if( i>=0&&s->idx.ptr.p_int[2*i0+1]>i ) - { - result = result+1; - } - } - return result; - } - if( s->matrixtype==1 ) - { - - /* - * CRS matrix - */ - ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseGetUpperCount: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state); - result = 0; - sz = s->m; - for(i=0; i<=sz-1; i++) - { - result = result+(s->ridx.ptr.p_int[i+1]-s->uidx.ptr.p_int[i]); - } - return result; - } - if( s->matrixtype==2 ) - { - - /* - * SKS matrix - */ - ae_assert(s->m==s->n, "SparseGetUpperCount: non-square SKS matrices are not supported", _state); - result = 0; - sz = s->m; - for(i=0; i<=sz-1; i++) - { - result = result+s->uidx.ptr.p_int[i]; - } - return result; - } - ae_assert(ae_false, "SparseGetUpperCount: internal error", _state); - return result; -} - - -/************************************************************************* -The function returns number of strictly lower triangular non-zero elements -in the matrix. It counts SYMBOLICALLY non-zero elements, i.e. entries -in the sparse matrix data structure. If some element has zero numerical -value, it is still counted. - -This function has different cost for different types of matrices: -* for hash-based matrices it involves complete pass over entire hash-table - with O(NNZ) cost, where NNZ is number of non-zero elements -* for CRS and SKS matrix types cost of counting is O(N) (N - matrix size). - -RESULT: number of non-zero elements strictly below main diagonal - - -- ALGLIB PROJECT -- - Copyright 12.02.2014 by Bochkanov Sergey -*************************************************************************/ -ae_int_t sparsegetlowercount(sparsematrix* s, ae_state *_state) -{ - ae_int_t sz; - ae_int_t i0; - ae_int_t i; - ae_int_t result; - - - result = -1; - if( s->matrixtype==0 ) - { - - /* - * Hash-table matrix - */ - result = 0; - sz = s->tablesize; - for(i0=0; i0<=sz-1; i0++) - { - i = s->idx.ptr.p_int[2*i0]; - if( i>=0&&s->idx.ptr.p_int[2*i0+1]matrixtype==1 ) - { - - /* - * CRS matrix - */ - ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseGetUpperCount: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state); - result = 0; - sz = s->m; - for(i=0; i<=sz-1; i++) - { - result = result+(s->didx.ptr.p_int[i]-s->ridx.ptr.p_int[i]); - } - return result; - } - if( s->matrixtype==2 ) - { - - /* - * SKS matrix - */ - ae_assert(s->m==s->n, "SparseGetUpperCount: non-square SKS matrices are not supported", _state); - result = 0; - sz = s->m; - for(i=0; i<=sz-1; i++) - { - result = result+s->didx.ptr.p_int[i]; - } - return result; - } - ae_assert(ae_false, "SparseGetUpperCount: internal error", _state); - return result; -} - - -/************************************************************************* -This is hash function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_int_t sparse_hash(ae_int_t i, - ae_int_t j, - ae_int_t tabsize, - ae_state *_state) -{ - ae_frame _frame_block; - hqrndstate r; - ae_int_t result; - - ae_frame_make(_state, &_frame_block); - memset(&r, 0, sizeof(r)); - _hqrndstate_init(&r, _state, ae_true); - - hqrndseed(i, j, &r, _state); - result = hqrnduniformi(&r, tabsize, _state); - ae_frame_leave(_state); - return result; -} - - -void _sparsematrix_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - sparsematrix *p = (sparsematrix*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->vals, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->idx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->ridx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->didx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->uidx, 0, DT_INT, _state, make_automatic); -} - - -void _sparsematrix_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - sparsematrix *dst = (sparsematrix*)_dst; - sparsematrix *src = (sparsematrix*)_src; - ae_vector_init_copy(&dst->vals, &src->vals, _state, make_automatic); - ae_vector_init_copy(&dst->idx, &src->idx, _state, make_automatic); - ae_vector_init_copy(&dst->ridx, &src->ridx, _state, make_automatic); - ae_vector_init_copy(&dst->didx, &src->didx, _state, make_automatic); - ae_vector_init_copy(&dst->uidx, &src->uidx, _state, make_automatic); - dst->matrixtype = src->matrixtype; - dst->m = src->m; - dst->n = src->n; - dst->nfree = src->nfree; - dst->ninitialized = src->ninitialized; - dst->tablesize = src->tablesize; -} - - -void _sparsematrix_clear(void* _p) -{ - sparsematrix *p = (sparsematrix*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->vals); - ae_vector_clear(&p->idx); - ae_vector_clear(&p->ridx); - ae_vector_clear(&p->didx); - ae_vector_clear(&p->uidx); -} - - -void _sparsematrix_destroy(void* _p) -{ - sparsematrix *p = (sparsematrix*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->vals); - ae_vector_destroy(&p->idx); - ae_vector_destroy(&p->ridx); - ae_vector_destroy(&p->didx); - ae_vector_destroy(&p->uidx); -} - - -void _sparsebuffers_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - sparsebuffers *p = (sparsebuffers*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->d, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->u, 0, DT_INT, _state, make_automatic); - _sparsematrix_init(&p->s, _state, make_automatic); -} - - -void _sparsebuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - sparsebuffers *dst = (sparsebuffers*)_dst; - sparsebuffers *src = (sparsebuffers*)_src; - ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic); - ae_vector_init_copy(&dst->u, &src->u, _state, make_automatic); - _sparsematrix_init_copy(&dst->s, &src->s, _state, make_automatic); -} - - -void _sparsebuffers_clear(void* _p) -{ - sparsebuffers *p = (sparsebuffers*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->d); - ae_vector_clear(&p->u); - _sparsematrix_clear(&p->s); -} - - -void _sparsebuffers_destroy(void* _p) -{ - sparsebuffers *p = (sparsebuffers*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->d); - ae_vector_destroy(&p->u); - _sparsematrix_destroy(&p->s); -} - - -#endif -#if defined(AE_COMPILE_ABLAS) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Splits matrix length in two parts, left part should match ABLAS block size - -INPUT PARAMETERS - A - real matrix, is passed to ensure that we didn't split - complex matrix using real splitting subroutine. - matrix itself is not changed. - N - length, N>0 - -OUTPUT PARAMETERS - N1 - length - N2 - length - -N1+N2=N, N1>=N2, N2 may be zero - - -- ALGLIB routine -- - 15.12.2009 - Bochkanov Sergey -*************************************************************************/ -void ablassplitlength(/* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t* n1, - ae_int_t* n2, - ae_state *_state) -{ - - *n1 = 0; - *n2 = 0; - - if( n>ablasblocksize(a, _state) ) - { - ablas_ablasinternalsplitlength(n, ablasblocksize(a, _state), n1, n2, _state); - } - else - { - ablas_ablasinternalsplitlength(n, ablasmicroblocksize(_state), n1, n2, _state); - } -} - - -/************************************************************************* -Complex ABLASSplitLength - - -- ALGLIB routine -- - 15.12.2009 - Bochkanov Sergey -*************************************************************************/ -void ablascomplexsplitlength(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_int_t* n1, - ae_int_t* n2, - ae_state *_state) -{ - - *n1 = 0; - *n2 = 0; - - if( n>ablascomplexblocksize(a, _state) ) - { - ablas_ablasinternalsplitlength(n, ablascomplexblocksize(a, _state), n1, n2, _state); - } - else - { - ablas_ablasinternalsplitlength(n, ablasmicroblocksize(_state), n1, n2, _state); - } -} - - -/************************************************************************* -Returns switch point for parallelism. - - -- ALGLIB routine -- - 15.12.2009 - Bochkanov Sergey -*************************************************************************/ -ae_int_t gemmparallelsize(ae_state *_state) -{ - ae_int_t result; - - - result = 64; - return result; -} - - -/************************************************************************* -Returns block size - subdivision size where cache-oblivious soubroutines -switch to the optimized kernel. - -INPUT PARAMETERS - A - real matrix, is passed to ensure that we didn't split - complex matrix using real splitting subroutine. - matrix itself is not changed. - - -- ALGLIB routine -- - 15.12.2009 - Bochkanov Sergey -*************************************************************************/ -ae_int_t ablasblocksize(/* Real */ ae_matrix* a, ae_state *_state) -{ - ae_int_t result; - - - result = 32; - return result; -} - - -/************************************************************************* -Block size for complex subroutines. - - -- ALGLIB routine -- - 15.12.2009 - Bochkanov Sergey -*************************************************************************/ -ae_int_t ablascomplexblocksize(/* Complex */ ae_matrix* a, - ae_state *_state) -{ - ae_int_t result; - - - result = 24; - return result; -} - - -/************************************************************************* -Microblock size - - -- ALGLIB routine -- - 15.12.2009 - Bochkanov Sergey -*************************************************************************/ -ae_int_t ablasmicroblocksize(ae_state *_state) -{ - ae_int_t result; - - - result = 8; - return result; -} - - -/************************************************************************* -Generation of an elementary reflection transformation - -The subroutine generates elementary reflection H of order N, so that, for -a given X, the following equality holds true: - - ( X(1) ) ( Beta ) -H * ( .. ) = ( 0 ) - ( X(n) ) ( 0 ) - -where - ( V(1) ) -H = 1 - Tau * ( .. ) * ( V(1), ..., V(n) ) - ( V(n) ) - -where the first component of vector V equals 1. - -Input parameters: - X - vector. Array whose index ranges within [1..N]. - N - reflection order. - -Output parameters: - X - components from 2 to N are replaced with vector V. - The first component is replaced with parameter Beta. - Tau - scalar value Tau. If X is a null vector, Tau equals 0, - otherwise 1 <= Tau <= 2. - -This subroutine is the modification of the DLARFG subroutines from -the LAPACK library. - -MODIFICATIONS: - 24.12.2005 sign(Alpha) was replaced with an analogous to the Fortran SIGN code. - - -- LAPACK auxiliary routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994 -*************************************************************************/ -void generatereflection(/* Real */ ae_vector* x, - ae_int_t n, - double* tau, - ae_state *_state) -{ - ae_int_t j; - double alpha; - double xnorm; - double v; - double beta; - double mx; - double s; - - *tau = 0; - - if( n<=1 ) - { - *tau = (double)(0); - return; - } - - /* - * Scale if needed (to avoid overflow/underflow during intermediate - * calculations). - */ - mx = (double)(0); - for(j=1; j<=n; j++) - { - mx = ae_maxreal(ae_fabs(x->ptr.p_double[j], _state), mx, _state); - } - s = (double)(1); - if( ae_fp_neq(mx,(double)(0)) ) - { - if( ae_fp_less_eq(mx,ae_minrealnumber/ae_machineepsilon) ) - { - s = ae_minrealnumber/ae_machineepsilon; - v = 1/s; - ae_v_muld(&x->ptr.p_double[1], 1, ae_v_len(1,n), v); - mx = mx*v; - } - else - { - if( ae_fp_greater_eq(mx,ae_maxrealnumber*ae_machineepsilon) ) - { - s = ae_maxrealnumber*ae_machineepsilon; - v = 1/s; - ae_v_muld(&x->ptr.p_double[1], 1, ae_v_len(1,n), v); - mx = mx*v; - } - } - } - - /* - * XNORM = DNRM2( N-1, X, INCX ) - */ - alpha = x->ptr.p_double[1]; - xnorm = (double)(0); - if( ae_fp_neq(mx,(double)(0)) ) - { - for(j=2; j<=n; j++) - { - xnorm = xnorm+ae_sqr(x->ptr.p_double[j]/mx, _state); - } - xnorm = ae_sqrt(xnorm, _state)*mx; - } - if( ae_fp_eq(xnorm,(double)(0)) ) - { - - /* - * H = I - */ - *tau = (double)(0); - x->ptr.p_double[1] = x->ptr.p_double[1]*s; - return; - } - - /* - * general case - */ - mx = ae_maxreal(ae_fabs(alpha, _state), ae_fabs(xnorm, _state), _state); - beta = -mx*ae_sqrt(ae_sqr(alpha/mx, _state)+ae_sqr(xnorm/mx, _state), _state); - if( ae_fp_less(alpha,(double)(0)) ) - { - beta = -beta; - } - *tau = (beta-alpha)/beta; - v = 1/(alpha-beta); - ae_v_muld(&x->ptr.p_double[2], 1, ae_v_len(2,n), v); - x->ptr.p_double[1] = beta; - - /* - * Scale back outputs - */ - x->ptr.p_double[1] = x->ptr.p_double[1]*s; -} - - -/************************************************************************* -Application of an elementary reflection to a rectangular matrix of size MxN - -The algorithm pre-multiplies the matrix by an elementary reflection transformation -which is given by column V and scalar Tau (see the description of the -GenerateReflection procedure). Not the whole matrix but only a part of it -is transformed (rows from M1 to M2, columns from N1 to N2). Only the elements -of this submatrix are changed. - -Input parameters: - C - matrix to be transformed. - Tau - scalar defining the transformation. - V - column defining the transformation. - Array whose index ranges within [1..M2-M1+1]. - M1, M2 - range of rows to be transformed. - N1, N2 - range of columns to be transformed. - WORK - working array whose indexes goes from N1 to N2. - -Output parameters: - C - the result of multiplying the input matrix C by the - transformation matrix which is given by Tau and V. - If N1>N2 or M1>M2, C is not modified. - - -- LAPACK auxiliary routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994 -*************************************************************************/ -void applyreflectionfromtheleft(/* Real */ ae_matrix* c, - double tau, - /* Real */ ae_vector* v, - ae_int_t m1, - ae_int_t m2, - ae_int_t n1, - ae_int_t n2, - /* Real */ ae_vector* work, - ae_state *_state) -{ - - - if( (ae_fp_eq(tau,(double)(0))||n1>n2)||m1>m2 ) - { - return; - } - rvectorsetlengthatleast(work, n2-n1+1, _state); - rmatrixgemv(n2-n1+1, m2-m1+1, 1.0, c, m1, n1, 1, v, 1, 0.0, work, 0, _state); - rmatrixger(m2-m1+1, n2-n1+1, c, m1, n1, -tau, v, 1, work, 0, _state); -} - - -/************************************************************************* -Application of an elementary reflection to a rectangular matrix of size MxN - -The algorithm post-multiplies the matrix by an elementary reflection transformation -which is given by column V and scalar Tau (see the description of the -GenerateReflection procedure). Not the whole matrix but only a part of it -is transformed (rows from M1 to M2, columns from N1 to N2). Only the -elements of this submatrix are changed. - -Input parameters: - C - matrix to be transformed. - Tau - scalar defining the transformation. - V - column defining the transformation. - Array whose index ranges within [1..N2-N1+1]. - M1, M2 - range of rows to be transformed. - N1, N2 - range of columns to be transformed. - WORK - working array whose indexes goes from M1 to M2. - -Output parameters: - C - the result of multiplying the input matrix C by the - transformation matrix which is given by Tau and V. - If N1>N2 or M1>M2, C is not modified. - - -- LAPACK auxiliary routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994 -*************************************************************************/ -void applyreflectionfromtheright(/* Real */ ae_matrix* c, - double tau, - /* Real */ ae_vector* v, - ae_int_t m1, - ae_int_t m2, - ae_int_t n1, - ae_int_t n2, - /* Real */ ae_vector* work, - ae_state *_state) -{ - - - if( (ae_fp_eq(tau,(double)(0))||n1>n2)||m1>m2 ) - { - return; - } - rvectorsetlengthatleast(work, m2-m1+1, _state); - rmatrixgemv(m2-m1+1, n2-n1+1, 1.0, c, m1, n1, 0, v, 1, 0.0, work, 0, _state); - rmatrixger(m2-m1+1, n2-n1+1, c, m1, n1, -tau, work, 0, v, 1, _state); -} - - -/************************************************************************* -Cache-oblivous complex "copy-and-transpose" - -Input parameters: - M - number of rows - N - number of columns - A - source matrix, MxN submatrix is copied and transposed - IA - submatrix offset (row index) - JA - submatrix offset (column index) - B - destination matrix, must be large enough to store result - IB - submatrix offset (row index) - JB - submatrix offset (column index) -*************************************************************************/ -void cmatrixtranspose(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Complex */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_state *_state) -{ - ae_int_t i; - ae_int_t s1; - ae_int_t s2; - - - if( m<=2*ablascomplexblocksize(a, _state)&&n<=2*ablascomplexblocksize(a, _state) ) - { - - /* - * base case - */ - for(i=0; i<=m-1; i++) - { - ae_v_cmove(&b->ptr.pp_complex[ib][jb+i], b->stride, &a->ptr.pp_complex[ia+i][ja], 1, "N", ae_v_len(ib,ib+n-1)); - } - } - else - { - - /* - * Cache-oblivious recursion - */ - if( m>n ) - { - ablascomplexsplitlength(a, m, &s1, &s2, _state); - cmatrixtranspose(s1, n, a, ia, ja, b, ib, jb, _state); - cmatrixtranspose(s2, n, a, ia+s1, ja, b, ib, jb+s1, _state); - } - else - { - ablascomplexsplitlength(a, n, &s1, &s2, _state); - cmatrixtranspose(m, s1, a, ia, ja, b, ib, jb, _state); - cmatrixtranspose(m, s2, a, ia, ja+s1, b, ib+s1, jb, _state); - } - } -} - - -/************************************************************************* -Cache-oblivous real "copy-and-transpose" - -Input parameters: - M - number of rows - N - number of columns - A - source matrix, MxN submatrix is copied and transposed - IA - submatrix offset (row index) - JA - submatrix offset (column index) - B - destination matrix, must be large enough to store result - IB - submatrix offset (row index) - JB - submatrix offset (column index) -*************************************************************************/ -void rmatrixtranspose(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_state *_state) -{ - ae_int_t i; - ae_int_t s1; - ae_int_t s2; - - - if( m<=2*ablasblocksize(a, _state)&&n<=2*ablasblocksize(a, _state) ) - { - - /* - * base case - */ - for(i=0; i<=m-1; i++) - { - ae_v_move(&b->ptr.pp_double[ib][jb+i], b->stride, &a->ptr.pp_double[ia+i][ja], 1, ae_v_len(ib,ib+n-1)); - } - } - else - { - - /* - * Cache-oblivious recursion - */ - if( m>n ) - { - ablassplitlength(a, m, &s1, &s2, _state); - rmatrixtranspose(s1, n, a, ia, ja, b, ib, jb, _state); - rmatrixtranspose(s2, n, a, ia+s1, ja, b, ib, jb+s1, _state); - } - else - { - ablassplitlength(a, n, &s1, &s2, _state); - rmatrixtranspose(m, s1, a, ia, ja, b, ib, jb, _state); - rmatrixtranspose(m, s2, a, ia, ja+s1, b, ib+s1, jb, _state); - } - } -} - - -/************************************************************************* -This code enforces symmetricy of the matrix by copying Upper part to lower -one (or vice versa). - -INPUT PARAMETERS: - A - matrix - N - number of rows/columns - IsUpper - whether we want to copy upper triangle to lower one (True) - or vice versa (False). -*************************************************************************/ -void rmatrixenforcesymmetricity(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - if( isupper ) - { - for(i=0; i<=n-1; i++) - { - for(j=i+1; j<=n-1; j++) - { - a->ptr.pp_double[j][i] = a->ptr.pp_double[i][j]; - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=i+1; j<=n-1; j++) - { - a->ptr.pp_double[i][j] = a->ptr.pp_double[j][i]; - } - } - } -} - - -/************************************************************************* -Copy - -Input parameters: - M - number of rows - N - number of columns - A - source matrix, MxN submatrix is copied and transposed - IA - submatrix offset (row index) - JA - submatrix offset (column index) - B - destination matrix, must be large enough to store result - IB - submatrix offset (row index) - JB - submatrix offset (column index) -*************************************************************************/ -void cmatrixcopy(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Complex */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_state *_state) -{ - ae_int_t i; - - - if( m==0||n==0 ) - { - return; - } - for(i=0; i<=m-1; i++) - { - ae_v_cmove(&b->ptr.pp_complex[ib+i][jb], 1, &a->ptr.pp_complex[ia+i][ja], 1, "N", ae_v_len(jb,jb+n-1)); - } -} - - -/************************************************************************* -Copy - -Input parameters: - N - subvector size - A - source vector, N elements are copied - IA - source offset (first element index) - B - destination vector, must be large enough to store result - IB - destination offset (first element index) -*************************************************************************/ -void rvectorcopy(ae_int_t n, - /* Real */ ae_vector* a, - ae_int_t ia, - /* Real */ ae_vector* b, - ae_int_t ib, - ae_state *_state) -{ - ae_int_t i; - - - if( n==0 ) - { - return; - } - for(i=0; i<=n-1; i++) - { - b->ptr.p_double[ib+i] = a->ptr.p_double[ia+i]; - } -} - - -/************************************************************************* -Copy - -Input parameters: - M - number of rows - N - number of columns - A - source matrix, MxN submatrix is copied and transposed - IA - submatrix offset (row index) - JA - submatrix offset (column index) - B - destination matrix, must be large enough to store result - IB - submatrix offset (row index) - JB - submatrix offset (column index) -*************************************************************************/ -void rmatrixcopy(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_state *_state) -{ - ae_int_t i; - - - if( m==0||n==0 ) - { - return; - } - for(i=0; i<=m-1; i++) - { - ae_v_move(&b->ptr.pp_double[ib+i][jb], 1, &a->ptr.pp_double[ia+i][ja], 1, ae_v_len(jb,jb+n-1)); - } -} - - -/************************************************************************* -Performs generalized copy: B := Beta*B + Alpha*A. - -If Beta=0, then previous contents of B is simply ignored. If Alpha=0, then -A is ignored and not referenced. If both Alpha and Beta are zero, B is -filled by zeros. - -Input parameters: - M - number of rows - N - number of columns - Alpha- coefficient - A - source matrix, MxN submatrix is copied and transposed - IA - submatrix offset (row index) - JA - submatrix offset (column index) - Beta- coefficient - B - destination matrix, must be large enough to store result - IB - submatrix offset (row index) - JB - submatrix offset (column index) -*************************************************************************/ -void rmatrixgencopy(ae_int_t m, - ae_int_t n, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - double beta, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - if( m==0||n==0 ) - { - return; - } - - /* - * Zero-fill - */ - if( ae_fp_eq(alpha,(double)(0))&&ae_fp_eq(beta,(double)(0)) ) - { - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - b->ptr.pp_double[ib+i][jb+j] = (double)(0); - } - } - return; - } - - /* - * Inplace multiply - */ - if( ae_fp_eq(alpha,(double)(0)) ) - { - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - b->ptr.pp_double[ib+i][jb+j] = beta*b->ptr.pp_double[ib+i][jb+j]; - } - } - return; - } - - /* - * Multiply and copy - */ - if( ae_fp_eq(beta,(double)(0)) ) - { - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - b->ptr.pp_double[ib+i][jb+j] = alpha*a->ptr.pp_double[ia+i][ja+j]; - } - } - return; - } - - /* - * Generic - */ - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - b->ptr.pp_double[ib+i][jb+j] = alpha*a->ptr.pp_double[ia+i][ja+j]+beta*b->ptr.pp_double[ib+i][jb+j]; - } - } -} - - -/************************************************************************* -Rank-1 correction: A := A + alpha*u*v' - -NOTE: this function expects A to be large enough to store result. No - automatic preallocation happens for smaller arrays. No integrity - checks is performed for sizes of A, u, v. - -INPUT PARAMETERS: - M - number of rows - N - number of columns - A - target matrix, MxN submatrix is updated - IA - submatrix offset (row index) - JA - submatrix offset (column index) - Alpha- coefficient - U - vector #1 - IU - subvector offset - V - vector #2 - IV - subvector offset - - - -- ALGLIB routine -- - - 16.10.2017 - Bochkanov Sergey -*************************************************************************/ -void rmatrixger(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - double alpha, - /* Real */ ae_vector* u, - ae_int_t iu, - /* Real */ ae_vector* v, - ae_int_t iv, - ae_state *_state) -{ - ae_int_t i; - double s; - - - - /* - * Quick exit - */ - if( m<=0||n<=0 ) - { - return; - } - - /* - * Try fast kernels: - * * vendor kernel - * * internal kernel - */ - if( m>ablas_blas2minvendorkernelsize&&n>ablas_blas2minvendorkernelsize ) - { - - /* - * Try MKL kernel first - */ - if( rmatrixgermkl(m, n, a, ia, ja, alpha, u, iu, v, iv, _state) ) - { - return; - } - } - if( rmatrixgerf(m, n, a, ia, ja, alpha, u, iu, v, iv, _state) ) - { - return; - } - - /* - * Generic code - */ - for(i=0; i<=m-1; i++) - { - s = alpha*u->ptr.p_double[iu+i]; - ae_v_addd(&a->ptr.pp_double[ia+i][ja], 1, &v->ptr.p_double[iv], 1, ae_v_len(ja,ja+n-1), s); - } -} - - -/************************************************************************* -Rank-1 correction: A := A + u*v' - -INPUT PARAMETERS: - M - number of rows - N - number of columns - A - target matrix, MxN submatrix is updated - IA - submatrix offset (row index) - JA - submatrix offset (column index) - U - vector #1 - IU - subvector offset - V - vector #2 - IV - subvector offset -*************************************************************************/ -void cmatrixrank1(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Complex */ ae_vector* u, - ae_int_t iu, - /* Complex */ ae_vector* v, - ae_int_t iv, - ae_state *_state) -{ - ae_int_t i; - ae_complex s; - - - - /* - * Quick exit - */ - if( m<=0||n<=0 ) - { - return; - } - - /* - * Try fast kernels: - * * vendor kernel - * * internal kernel - */ - if( m>ablas_blas2minvendorkernelsize&&n>ablas_blas2minvendorkernelsize ) - { - - /* - * Try MKL kernel first - */ - if( cmatrixrank1mkl(m, n, a, ia, ja, u, iu, v, iv, _state) ) - { - return; - } - } - if( cmatrixrank1f(m, n, a, ia, ja, u, iu, v, iv, _state) ) - { - return; - } - - /* - * Generic code - */ - for(i=0; i<=m-1; i++) - { - s = u->ptr.p_complex[iu+i]; - ae_v_caddc(&a->ptr.pp_complex[ia+i][ja], 1, &v->ptr.p_complex[iv], 1, "N", ae_v_len(ja,ja+n-1), s); - } -} - - -/************************************************************************* -IMPORTANT: this function is deprecated since ALGLIB 3.13. Use RMatrixGER() - which is more generic version of this function. - -Rank-1 correction: A := A + u*v' - -INPUT PARAMETERS: - M - number of rows - N - number of columns - A - target matrix, MxN submatrix is updated - IA - submatrix offset (row index) - JA - submatrix offset (column index) - U - vector #1 - IU - subvector offset - V - vector #2 - IV - subvector offset -*************************************************************************/ -void rmatrixrank1(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Real */ ae_vector* u, - ae_int_t iu, - /* Real */ ae_vector* v, - ae_int_t iv, - ae_state *_state) -{ - ae_int_t i; - double s; - - - - /* - * Quick exit - */ - if( m<=0||n<=0 ) - { - return; - } - - /* - * Try fast kernels: - * * vendor kernel - * * internal kernel - */ - if( m>ablas_blas2minvendorkernelsize&&n>ablas_blas2minvendorkernelsize ) - { - - /* - * Try MKL kernel first - */ - if( rmatrixrank1mkl(m, n, a, ia, ja, u, iu, v, iv, _state) ) - { - return; - } - } - if( rmatrixrank1f(m, n, a, ia, ja, u, iu, v, iv, _state) ) - { - return; - } - - /* - * Generic code - */ - for(i=0; i<=m-1; i++) - { - s = u->ptr.p_double[iu+i]; - ae_v_addd(&a->ptr.pp_double[ia+i][ja], 1, &v->ptr.p_double[iv], 1, ae_v_len(ja,ja+n-1), s); - } -} - - -void rmatrixgemv(ae_int_t m, - ae_int_t n, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t opa, - /* Real */ ae_vector* x, - ae_int_t ix, - double beta, - /* Real */ ae_vector* y, - ae_int_t iy, - ae_state *_state) -{ - ae_int_t i; - double v; - - - - /* - * Quick exit for M=0, N=0 or Alpha=0. - * - * After this block we have M>0, N>0, Alpha<>0. - */ - if( m<=0 ) - { - return; - } - if( n<=0||ae_fp_eq(alpha,0.0) ) - { - if( ae_fp_neq(beta,(double)(0)) ) - { - for(i=0; i<=m-1; i++) - { - y->ptr.p_double[iy+i] = beta*y->ptr.p_double[iy+i]; - } - } - else - { - for(i=0; i<=m-1; i++) - { - y->ptr.p_double[iy+i] = 0.0; - } - } - return; - } - - /* - * Try fast kernels - */ - if( m>ablas_blas2minvendorkernelsize&&n>ablas_blas2minvendorkernelsize ) - { - - /* - * Try MKL kernel - */ - if( rmatrixgemvmkl(m, n, alpha, a, ia, ja, opa, x, ix, beta, y, iy, _state) ) - { - return; - } - } - - /* - * Generic code - */ - if( opa==0 ) - { - - /* - * y = A*x - */ - for(i=0; i<=m-1; i++) - { - v = ae_v_dotproduct(&a->ptr.pp_double[ia+i][ja], 1, &x->ptr.p_double[ix], 1, ae_v_len(ja,ja+n-1)); - if( ae_fp_eq(beta,0.0) ) - { - y->ptr.p_double[iy+i] = alpha*v; - } - else - { - y->ptr.p_double[iy+i] = alpha*v+beta*y->ptr.p_double[iy+i]; - } - } - return; - } - if( opa==1 ) - { - - /* - * Prepare output array - */ - if( ae_fp_eq(beta,0.0) ) - { - for(i=0; i<=m-1; i++) - { - y->ptr.p_double[iy+i] = (double)(0); - } - } - else - { - for(i=0; i<=m-1; i++) - { - y->ptr.p_double[iy+i] = beta*y->ptr.p_double[iy+i]; - } - } - - /* - * y += A^T*x - */ - for(i=0; i<=n-1; i++) - { - v = alpha*x->ptr.p_double[ix+i]; - ae_v_addd(&y->ptr.p_double[iy], 1, &a->ptr.pp_double[ia+i][ja], 1, ae_v_len(iy,iy+m-1), v); - } - return; - } -} - - -/************************************************************************* -Matrix-vector product: y := op(A)*x - -INPUT PARAMETERS: - M - number of rows of op(A) - M>=0 - N - number of columns of op(A) - N>=0 - A - target matrix - IA - submatrix offset (row index) - JA - submatrix offset (column index) - OpA - operation type: - * OpA=0 => op(A) = A - * OpA=1 => op(A) = A^T - * OpA=2 => op(A) = A^H - X - input vector - IX - subvector offset - IY - subvector offset - Y - preallocated matrix, must be large enough to store result - -OUTPUT PARAMETERS: - Y - vector which stores result - -if M=0, then subroutine does nothing. -if N=0, Y is filled by zeros. - - - -- ALGLIB routine -- - - 28.01.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixmv(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t opa, - /* Complex */ ae_vector* x, - ae_int_t ix, - /* Complex */ ae_vector* y, - ae_int_t iy, - ae_state *_state) -{ - ae_int_t i; - ae_complex v; - - - - /* - * Quick exit - */ - if( m==0 ) - { - return; - } - if( n==0 ) - { - for(i=0; i<=m-1; i++) - { - y->ptr.p_complex[iy+i] = ae_complex_from_i(0); - } - return; - } - - /* - * Try fast kernels - */ - if( m>ablas_blas2minvendorkernelsize&&n>ablas_blas2minvendorkernelsize ) - { - - /* - * Try MKL kernel - */ - if( cmatrixmvmkl(m, n, a, ia, ja, opa, x, ix, y, iy, _state) ) - { - return; - } - } - - /* - * Generic code - */ - if( opa==0 ) - { - - /* - * y = A*x - */ - for(i=0; i<=m-1; i++) - { - v = ae_v_cdotproduct(&a->ptr.pp_complex[ia+i][ja], 1, "N", &x->ptr.p_complex[ix], 1, "N", ae_v_len(ja,ja+n-1)); - y->ptr.p_complex[iy+i] = v; - } - return; - } - if( opa==1 ) - { - - /* - * y = A^T*x - */ - for(i=0; i<=m-1; i++) - { - y->ptr.p_complex[iy+i] = ae_complex_from_i(0); - } - for(i=0; i<=n-1; i++) - { - v = x->ptr.p_complex[ix+i]; - ae_v_caddc(&y->ptr.p_complex[iy], 1, &a->ptr.pp_complex[ia+i][ja], 1, "N", ae_v_len(iy,iy+m-1), v); - } - return; - } - if( opa==2 ) - { - - /* - * y = A^H*x - */ - for(i=0; i<=m-1; i++) - { - y->ptr.p_complex[iy+i] = ae_complex_from_i(0); - } - for(i=0; i<=n-1; i++) - { - v = x->ptr.p_complex[ix+i]; - ae_v_caddc(&y->ptr.p_complex[iy], 1, &a->ptr.pp_complex[ia+i][ja], 1, "Conj", ae_v_len(iy,iy+m-1), v); - } - return; - } -} - - -/************************************************************************* -IMPORTANT: this function is deprecated since ALGLIB 3.13. Use RMatrixGEMV() - which is more generic version of this function. - -Matrix-vector product: y := op(A)*x - -INPUT PARAMETERS: - M - number of rows of op(A) - N - number of columns of op(A) - A - target matrix - IA - submatrix offset (row index) - JA - submatrix offset (column index) - OpA - operation type: - * OpA=0 => op(A) = A - * OpA=1 => op(A) = A^T - X - input vector - IX - subvector offset - IY - subvector offset - Y - preallocated matrix, must be large enough to store result - -OUTPUT PARAMETERS: - Y - vector which stores result - -if M=0, then subroutine does nothing. -if N=0, Y is filled by zeros. - - - -- ALGLIB routine -- - - 28.01.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixmv(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t opa, - /* Real */ ae_vector* x, - ae_int_t ix, - /* Real */ ae_vector* y, - ae_int_t iy, - ae_state *_state) -{ - ae_int_t i; - double v; - - - - /* - * Quick exit - */ - if( m==0 ) - { - return; - } - if( n==0 ) - { - for(i=0; i<=m-1; i++) - { - y->ptr.p_double[iy+i] = (double)(0); - } - return; - } - - /* - * Try fast kernels - */ - if( m>ablas_blas2minvendorkernelsize&&n>ablas_blas2minvendorkernelsize ) - { - - /* - * Try MKL kernel - */ - if( rmatrixmvmkl(m, n, a, ia, ja, opa, x, ix, y, iy, _state) ) - { - return; - } - } - - /* - * Generic code - */ - if( opa==0 ) - { - - /* - * y = A*x - */ - for(i=0; i<=m-1; i++) - { - v = ae_v_dotproduct(&a->ptr.pp_double[ia+i][ja], 1, &x->ptr.p_double[ix], 1, ae_v_len(ja,ja+n-1)); - y->ptr.p_double[iy+i] = v; - } - return; - } - if( opa==1 ) - { - - /* - * y = A^T*x - */ - for(i=0; i<=m-1; i++) - { - y->ptr.p_double[iy+i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - v = x->ptr.p_double[ix+i]; - ae_v_addd(&y->ptr.p_double[iy], 1, &a->ptr.pp_double[ia+i][ja], 1, ae_v_len(iy,iy+m-1), v); - } - return; - } -} - - -void rmatrixsymv(ae_int_t n, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_bool isupper, - /* Real */ ae_vector* x, - ae_int_t ix, - double beta, - /* Real */ ae_vector* y, - ae_int_t iy, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - double vr; - double vx; - - - - /* - * Quick exit for M=0, N=0 or Alpha=0. - * - * After this block we have M>0, N>0, Alpha<>0. - */ - if( n<=0 ) - { - return; - } - if( ae_fp_eq(alpha,0.0) ) - { - if( ae_fp_neq(beta,(double)(0)) ) - { - for(i=0; i<=n-1; i++) - { - y->ptr.p_double[iy+i] = beta*y->ptr.p_double[iy+i]; - } - } - else - { - for(i=0; i<=n-1; i++) - { - y->ptr.p_double[iy+i] = 0.0; - } - } - return; - } - - /* - * Try fast kernels - */ - if( n>ablas_blas2minvendorkernelsize ) - { - - /* - * Try MKL kernel - */ - if( rmatrixsymvmkl(n, alpha, a, ia, ja, isupper, x, ix, beta, y, iy, _state) ) - { - return; - } - } - - /* - * Generic code - */ - if( ae_fp_neq(beta,(double)(0)) ) - { - for(i=0; i<=n-1; i++) - { - y->ptr.p_double[iy+i] = beta*y->ptr.p_double[iy+i]; - } - } - else - { - for(i=0; i<=n-1; i++) - { - y->ptr.p_double[iy+i] = 0.0; - } - } - if( isupper ) - { - - /* - * Upper triangle of A is stored - */ - for(i=0; i<=n-1; i++) - { - - /* - * Process diagonal element - */ - v = alpha*a->ptr.pp_double[ia+i][ja+i]; - y->ptr.p_double[iy+i] = y->ptr.p_double[iy+i]+v*x->ptr.p_double[ix+i]; - - /* - * Process off-diagonal elements - */ - vr = 0.0; - vx = x->ptr.p_double[ix+i]; - for(j=i+1; j<=n-1; j++) - { - v = alpha*a->ptr.pp_double[ia+i][ja+j]; - y->ptr.p_double[iy+j] = y->ptr.p_double[iy+j]+v*vx; - vr = vr+v*x->ptr.p_double[ix+j]; - } - y->ptr.p_double[iy+i] = y->ptr.p_double[iy+i]+vr; - } - } - else - { - - /* - * Lower triangle of A is stored - */ - for(i=0; i<=n-1; i++) - { - - /* - * Process diagonal element - */ - v = alpha*a->ptr.pp_double[ia+i][ja+i]; - y->ptr.p_double[iy+i] = y->ptr.p_double[iy+i]+v*x->ptr.p_double[ix+i]; - - /* - * Process off-diagonal elements - */ - vr = 0.0; - vx = x->ptr.p_double[ix+i]; - for(j=0; j<=i-1; j++) - { - v = alpha*a->ptr.pp_double[ia+i][ja+j]; - y->ptr.p_double[iy+j] = y->ptr.p_double[iy+j]+v*vx; - vr = vr+v*x->ptr.p_double[ix+j]; - } - y->ptr.p_double[iy+i] = y->ptr.p_double[iy+i]+vr; - } - } -} - - -double rmatrixsyvmv(ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_bool isupper, - /* Real */ ae_vector* x, - ae_int_t ix, - /* Real */ ae_vector* tmp, - ae_state *_state) -{ - ae_int_t i; - double result; - - - - /* - * Quick exit for N=0 - */ - if( n<=0 ) - { - result = (double)(0); - return result; - } - - /* - * Generic code - */ - rmatrixsymv(n, 1.0, a, ia, ja, isupper, x, ix, 0.0, tmp, 0, _state); - result = (double)(0); - for(i=0; i<=n-1; i++) - { - result = result+x->ptr.p_double[ix+i]*tmp->ptr.p_double[i]; - } - return result; -} - - -/************************************************************************* -This subroutine solves linear system op(A)*x=b where: -* A is NxN upper/lower triangular/unitriangular matrix -* X and B are Nx1 vectors -* "op" may be identity transformation, transposition, conjugate transposition - -Solution replaces X. - -IMPORTANT: * no overflow/underflow/denegeracy tests is performed. - * no integrity checks for operand sizes, out-of-bounds accesses - and so on is performed - -INPUT PARAMETERS - N - matrix size, N>=0 - A - matrix, actial matrix is stored in A[IA:IA+N-1,JA:JA+N-1] - IA - submatrix offset - JA - submatrix offset - IsUpper - whether matrix is upper triangular - IsUnit - whether matrix is unitriangular - OpType - transformation type: - * 0 - no transformation - * 1 - transposition - X - right part, actual vector is stored in X[IX:IX+N-1] - IX - offset - -OUTPUT PARAMETERS - X - solution replaces elements X[IX:IX+N-1] - - -- ALGLIB routine / remastering of LAPACK's DTRSV -- - (c) 2017 Bochkanov Sergey - converted to ALGLIB - (c) 2016 Reference BLAS level1 routine (LAPACK version 3.7.0) - Reference BLAS is a software package provided by Univ. of Tennessee, - Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd. -*************************************************************************/ -void rmatrixtrsv(ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_vector* x, - ae_int_t ix, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - - - - /* - * Quick exit - */ - if( n<=0 ) - { - return; - } - - /* - * Try fast kernels - */ - if( n>ablas_blas2minvendorkernelsize ) - { - - /* - * Try MKL kernel - */ - if( rmatrixtrsvmkl(n, a, ia, ja, isupper, isunit, optype, x, ix, _state) ) - { - return; - } - } - - /* - * Generic code - */ - if( optype==0&&isupper ) - { - for(i=n-1; i>=0; i--) - { - v = x->ptr.p_double[ix+i]; - for(j=i+1; j<=n-1; j++) - { - v = v-a->ptr.pp_double[ia+i][ja+j]*x->ptr.p_double[ix+j]; - } - if( !isunit ) - { - v = v/a->ptr.pp_double[ia+i][ja+i]; - } - x->ptr.p_double[ix+i] = v; - } - return; - } - if( optype==0&&!isupper ) - { - for(i=0; i<=n-1; i++) - { - v = x->ptr.p_double[ix+i]; - for(j=0; j<=i-1; j++) - { - v = v-a->ptr.pp_double[ia+i][ja+j]*x->ptr.p_double[ix+j]; - } - if( !isunit ) - { - v = v/a->ptr.pp_double[ia+i][ja+i]; - } - x->ptr.p_double[ix+i] = v; - } - return; - } - if( optype==1&&isupper ) - { - for(i=0; i<=n-1; i++) - { - v = x->ptr.p_double[ix+i]; - if( !isunit ) - { - v = v/a->ptr.pp_double[ia+i][ja+i]; - } - x->ptr.p_double[ix+i] = v; - if( v==0 ) - { - continue; - } - for(j=i+1; j<=n-1; j++) - { - x->ptr.p_double[ix+j] = x->ptr.p_double[ix+j]-v*a->ptr.pp_double[ia+i][ja+j]; - } - } - return; - } - if( optype==1&&!isupper ) - { - for(i=n-1; i>=0; i--) - { - v = x->ptr.p_double[ix+i]; - if( !isunit ) - { - v = v/a->ptr.pp_double[ia+i][ja+i]; - } - x->ptr.p_double[ix+i] = v; - if( v==0 ) - { - continue; - } - for(j=0; j<=i-1; j++) - { - x->ptr.p_double[ix+j] = x->ptr.p_double[ix+j]-v*a->ptr.pp_double[ia+i][ja+j]; - } - } - return; - } - ae_assert(ae_false, "RMatrixTRSV: unexpected operation type", _state); -} - - -/************************************************************************* -This subroutine calculates X*op(A^-1) where: -* X is MxN general matrix -* A is NxN upper/lower triangular/unitriangular matrix -* "op" may be identity transformation, transposition, conjugate transposition -Multiplication result replaces X. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - M - matrix size, N>=0 - A - matrix, actial matrix is stored in A[I1:I1+N-1,J1:J1+N-1] - I1 - submatrix offset - J1 - submatrix offset - IsUpper - whether matrix is upper triangular - IsUnit - whether matrix is unitriangular - OpType - transformation type: - * 0 - no transformation - * 1 - transposition - * 2 - conjugate transposition - X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1] - I2 - submatrix offset - J2 - submatrix offset - - -- ALGLIB routine -- - 20.01.2018 - Bochkanov Sergey -*************************************************************************/ -void cmatrixrighttrsm(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ - ae_int_t s1; - ae_int_t s2; - ae_int_t tsa; - ae_int_t tsb; - ae_int_t tscur; - - - tsa = matrixtilesizea(_state)/2; - tsb = matrixtilesizeb(_state); - tscur = tsb; - if( imax2(m, n, _state)<=tsb ) - { - tscur = tsa; - } - ae_assert(tscur>=1, "CMatrixRightTRSM: integrity check failed", _state); - - /* - * Upper level parallelization: - * * decide whether it is feasible to activate multithreading - * * perform optionally parallelized splits on M - */ - if( m>=2*tsb&&ae_fp_greater_eq(4*rmul3((double)(m), (double)(n), (double)(n), _state),smpactivationlevel(_state)) ) - { - if( _trypexec_cmatrixrighttrsm(m,n,a,i1,j1,isupper,isunit,optype,x,i2,j2, _state) ) - { - return; - } - } - if( m>=2*tsb ) - { - - /* - * Split X: X*A = (X1 X2)^T*A - */ - tiledsplit(m, tsb, &s1, &s2, _state); - cmatrixrighttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - cmatrixrighttrsm(s2, n, a, i1, j1, isupper, isunit, optype, x, i2+s1, j2, _state); - return; - } - - /* - * Basecase: either MKL-supported code or ALGLIB basecase code - */ - if( imax2(m, n, _state)<=tsb ) - { - if( cmatrixrighttrsmmkl(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state) ) - { - return; - } - } - if( imax2(m, n, _state)<=tsa ) - { - ablas_cmatrixrighttrsm2(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - return; - } - - /* - * Recursive subdivision - */ - if( m>=n ) - { - - /* - * Split X: X*A = (X1 X2)^T*A - */ - tiledsplit(m, tscur, &s1, &s2, _state); - cmatrixrighttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - cmatrixrighttrsm(s2, n, a, i1, j1, isupper, isunit, optype, x, i2+s1, j2, _state); - } - else - { - - /* - * Split A: - * (A1 A12) - * X*op(A) = X*op( ) - * ( A2) - * - * Different variants depending on - * IsUpper/OpType combinations - */ - tiledsplit(n, tscur, &s1, &s2, _state); - if( isupper&&optype==0 ) - { - - /* - * (A1 A12)-1 - * X*A^-1 = (X1 X2)*( ) - * ( A2) - */ - cmatrixrighttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - cmatrixgemm(m, s2, s1, ae_complex_from_d(-1.0), x, i2, j2, 0, a, i1, j1+s1, 0, ae_complex_from_d(1.0), x, i2, j2+s1, _state); - cmatrixrighttrsm(m, s2, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2, j2+s1, _state); - } - if( isupper&&optype!=0 ) - { - - /* - * (A1' )-1 - * X*A^-1 = (X1 X2)*( ) - * (A12' A2') - */ - cmatrixrighttrsm(m, s2, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2, j2+s1, _state); - cmatrixgemm(m, s1, s2, ae_complex_from_d(-1.0), x, i2, j2+s1, 0, a, i1, j1+s1, optype, ae_complex_from_d(1.0), x, i2, j2, _state); - cmatrixrighttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - } - if( !isupper&&optype==0 ) - { - - /* - * (A1 )-1 - * X*A^-1 = (X1 X2)*( ) - * (A21 A2) - */ - cmatrixrighttrsm(m, s2, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2, j2+s1, _state); - cmatrixgemm(m, s1, s2, ae_complex_from_d(-1.0), x, i2, j2+s1, 0, a, i1+s1, j1, 0, ae_complex_from_d(1.0), x, i2, j2, _state); - cmatrixrighttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - } - if( !isupper&&optype!=0 ) - { - - /* - * (A1' A21')-1 - * X*A^-1 = (X1 X2)*( ) - * ( A2') - */ - cmatrixrighttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - cmatrixgemm(m, s2, s1, ae_complex_from_d(-1.0), x, i2, j2, 0, a, i1+s1, j1, optype, ae_complex_from_d(1.0), x, i2, j2+s1, _state); - cmatrixrighttrsm(m, s2, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2, j2+s1, _state); - } - } -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_cmatrixrighttrsm(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -This subroutine calculates op(A^-1)*X where: -* X is MxN general matrix -* A is MxM upper/lower triangular/unitriangular matrix -* "op" may be identity transformation, transposition, conjugate transposition -Multiplication result replaces X. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - M - matrix size, N>=0 - A - matrix, actial matrix is stored in A[I1:I1+M-1,J1:J1+M-1] - I1 - submatrix offset - J1 - submatrix offset - IsUpper - whether matrix is upper triangular - IsUnit - whether matrix is unitriangular - OpType - transformation type: - * 0 - no transformation - * 1 - transposition - * 2 - conjugate transposition - X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1] - I2 - submatrix offset - J2 - submatrix offset - - -- ALGLIB routine -- - 15.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -void cmatrixlefttrsm(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ - ae_int_t s1; - ae_int_t s2; - ae_int_t tsa; - ae_int_t tsb; - ae_int_t tscur; - - - tsa = matrixtilesizea(_state)/2; - tsb = matrixtilesizeb(_state); - tscur = tsb; - if( imax2(m, n, _state)<=tsb ) - { - tscur = tsa; - } - ae_assert(tscur>=1, "CMatrixLeftTRSM: integrity check failed", _state); - - /* - * Upper level parallelization: - * * decide whether it is feasible to activate multithreading - * * perform optionally parallelized splits on N - */ - if( n>=2*tsb&&ae_fp_greater_eq(4*rmul3((double)(n), (double)(m), (double)(m), _state),smpactivationlevel(_state)) ) - { - if( _trypexec_cmatrixlefttrsm(m,n,a,i1,j1,isupper,isunit,optype,x,i2,j2, _state) ) - { - return; - } - } - if( n>=2*tsb ) - { - tiledsplit(n, tscur, &s1, &s2, _state); - cmatrixlefttrsm(m, s2, a, i1, j1, isupper, isunit, optype, x, i2, j2+s1, _state); - cmatrixlefttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - return; - } - - /* - * Basecase: either MKL-supported code or ALGLIB basecase code - */ - if( imax2(m, n, _state)<=tsb ) - { - if( cmatrixlefttrsmmkl(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state) ) - { - return; - } - } - if( imax2(m, n, _state)<=tsa ) - { - ablas_cmatrixlefttrsm2(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - return; - } - - /* - * Recursive subdivision - */ - if( n>=m ) - { - - /* - * Split X: op(A)^-1*X = op(A)^-1*(X1 X2) - */ - tiledsplit(n, tscur, &s1, &s2, _state); - cmatrixlefttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - cmatrixlefttrsm(m, s2, a, i1, j1, isupper, isunit, optype, x, i2, j2+s1, _state); - } - else - { - - /* - * Split A - */ - tiledsplit(m, tscur, &s1, &s2, _state); - if( isupper&&optype==0 ) - { - - /* - * (A1 A12)-1 ( X1 ) - * A^-1*X* = ( ) *( ) - * ( A2) ( X2 ) - */ - cmatrixlefttrsm(s2, n, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2+s1, j2, _state); - cmatrixgemm(s1, n, s2, ae_complex_from_d(-1.0), a, i1, j1+s1, 0, x, i2+s1, j2, 0, ae_complex_from_d(1.0), x, i2, j2, _state); - cmatrixlefttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - } - if( isupper&&optype!=0 ) - { - - /* - * (A1' )-1 ( X1 ) - * A^-1*X = ( ) *( ) - * (A12' A2') ( X2 ) - */ - cmatrixlefttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - cmatrixgemm(s2, n, s1, ae_complex_from_d(-1.0), a, i1, j1+s1, optype, x, i2, j2, 0, ae_complex_from_d(1.0), x, i2+s1, j2, _state); - cmatrixlefttrsm(s2, n, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2+s1, j2, _state); - } - if( !isupper&&optype==0 ) - { - - /* - * (A1 )-1 ( X1 ) - * A^-1*X = ( ) *( ) - * (A21 A2) ( X2 ) - */ - cmatrixlefttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - cmatrixgemm(s2, n, s1, ae_complex_from_d(-1.0), a, i1+s1, j1, 0, x, i2, j2, 0, ae_complex_from_d(1.0), x, i2+s1, j2, _state); - cmatrixlefttrsm(s2, n, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2+s1, j2, _state); - } - if( !isupper&&optype!=0 ) - { - - /* - * (A1' A21')-1 ( X1 ) - * A^-1*X = ( ) *( ) - * ( A2') ( X2 ) - */ - cmatrixlefttrsm(s2, n, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2+s1, j2, _state); - cmatrixgemm(s1, n, s2, ae_complex_from_d(-1.0), a, i1+s1, j1, optype, x, i2+s1, j2, 0, ae_complex_from_d(1.0), x, i2, j2, _state); - cmatrixlefttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - } - } -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_cmatrixlefttrsm(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -This subroutine calculates X*op(A^-1) where: -* X is MxN general matrix -* A is NxN upper/lower triangular/unitriangular matrix -* "op" may be identity transformation, transposition -Multiplication result replaces X. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - M - matrix size, N>=0 - A - matrix, actial matrix is stored in A[I1:I1+N-1,J1:J1+N-1] - I1 - submatrix offset - J1 - submatrix offset - IsUpper - whether matrix is upper triangular - IsUnit - whether matrix is unitriangular - OpType - transformation type: - * 0 - no transformation - * 1 - transposition - X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1] - I2 - submatrix offset - J2 - submatrix offset - - -- ALGLIB routine -- - 15.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -void rmatrixrighttrsm(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ - ae_int_t s1; - ae_int_t s2; - ae_int_t tsa; - ae_int_t tsb; - ae_int_t tscur; - - - tsa = matrixtilesizea(_state); - tsb = matrixtilesizeb(_state); - tscur = tsb; - if( imax2(m, n, _state)<=tsb ) - { - tscur = tsa; - } - ae_assert(tscur>=1, "RMatrixRightTRSM: integrity check failed", _state); - - /* - * Upper level parallelization: - * * decide whether it is feasible to activate multithreading - * * perform optionally parallelized splits on M - */ - if( m>=2*tsb&&ae_fp_greater_eq(rmul3((double)(m), (double)(n), (double)(n), _state),smpactivationlevel(_state)) ) - { - if( _trypexec_rmatrixrighttrsm(m,n,a,i1,j1,isupper,isunit,optype,x,i2,j2, _state) ) - { - return; - } - } - if( m>=2*tsb ) - { - - /* - * Split X: X*A = (X1 X2)^T*A - */ - tiledsplit(m, tsb, &s1, &s2, _state); - rmatrixrighttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - rmatrixrighttrsm(s2, n, a, i1, j1, isupper, isunit, optype, x, i2+s1, j2, _state); - return; - } - - /* - * Basecase: MKL or ALGLIB code - */ - if( imax2(m, n, _state)<=tsb ) - { - if( rmatrixrighttrsmmkl(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state) ) - { - return; - } - } - if( imax2(m, n, _state)<=tsa ) - { - ablas_rmatrixrighttrsm2(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - return; - } - - /* - * Recursive subdivision - */ - if( m>=n ) - { - - /* - * Split X: X*A = (X1 X2)^T*A - */ - tiledsplit(m, tscur, &s1, &s2, _state); - rmatrixrighttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - rmatrixrighttrsm(s2, n, a, i1, j1, isupper, isunit, optype, x, i2+s1, j2, _state); - } - else - { - - /* - * Split A: - * (A1 A12) - * X*op(A) = X*op( ) - * ( A2) - * - * Different variants depending on - * IsUpper/OpType combinations - */ - tiledsplit(n, tscur, &s1, &s2, _state); - if( isupper&&optype==0 ) - { - - /* - * (A1 A12)-1 - * X*A^-1 = (X1 X2)*( ) - * ( A2) - */ - rmatrixrighttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - rmatrixgemm(m, s2, s1, -1.0, x, i2, j2, 0, a, i1, j1+s1, 0, 1.0, x, i2, j2+s1, _state); - rmatrixrighttrsm(m, s2, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2, j2+s1, _state); - } - if( isupper&&optype!=0 ) - { - - /* - * (A1' )-1 - * X*A^-1 = (X1 X2)*( ) - * (A12' A2') - */ - rmatrixrighttrsm(m, s2, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2, j2+s1, _state); - rmatrixgemm(m, s1, s2, -1.0, x, i2, j2+s1, 0, a, i1, j1+s1, optype, 1.0, x, i2, j2, _state); - rmatrixrighttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - } - if( !isupper&&optype==0 ) - { - - /* - * (A1 )-1 - * X*A^-1 = (X1 X2)*( ) - * (A21 A2) - */ - rmatrixrighttrsm(m, s2, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2, j2+s1, _state); - rmatrixgemm(m, s1, s2, -1.0, x, i2, j2+s1, 0, a, i1+s1, j1, 0, 1.0, x, i2, j2, _state); - rmatrixrighttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - } - if( !isupper&&optype!=0 ) - { - - /* - * (A1' A21')-1 - * X*A^-1 = (X1 X2)*( ) - * ( A2') - */ - rmatrixrighttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - rmatrixgemm(m, s2, s1, -1.0, x, i2, j2, 0, a, i1+s1, j1, optype, 1.0, x, i2, j2+s1, _state); - rmatrixrighttrsm(m, s2, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2, j2+s1, _state); - } - } -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_rmatrixrighttrsm(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -This subroutine calculates op(A^-1)*X where: -* X is MxN general matrix -* A is MxM upper/lower triangular/unitriangular matrix -* "op" may be identity transformation, transposition -Multiplication result replaces X. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - M - matrix size, N>=0 - A - matrix, actial matrix is stored in A[I1:I1+M-1,J1:J1+M-1] - I1 - submatrix offset - J1 - submatrix offset - IsUpper - whether matrix is upper triangular - IsUnit - whether matrix is unitriangular - OpType - transformation type: - * 0 - no transformation - * 1 - transposition - X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1] - I2 - submatrix offset - J2 - submatrix offset - - -- ALGLIB routine -- - 15.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -void rmatrixlefttrsm(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ - ae_int_t s1; - ae_int_t s2; - ae_int_t tsa; - ae_int_t tsb; - ae_int_t tscur; - - - tsa = matrixtilesizea(_state); - tsb = matrixtilesizeb(_state); - tscur = tsb; - if( imax2(m, n, _state)<=tsb ) - { - tscur = tsa; - } - ae_assert(tscur>=1, "RMatrixLeftTRSMRec: integrity check failed", _state); - - /* - * Upper level parallelization: - * * decide whether it is feasible to activate multithreading - * * perform optionally parallelized splits on N - */ - if( n>=2*tsb&&ae_fp_greater_eq(rmul3((double)(n), (double)(m), (double)(m), _state),smpactivationlevel(_state)) ) - { - if( _trypexec_rmatrixlefttrsm(m,n,a,i1,j1,isupper,isunit,optype,x,i2,j2, _state) ) - { - return; - } - } - if( n>=2*tsb ) - { - tiledsplit(n, tscur, &s1, &s2, _state); - rmatrixlefttrsm(m, s2, a, i1, j1, isupper, isunit, optype, x, i2, j2+s1, _state); - rmatrixlefttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - return; - } - - /* - * Basecase: MKL or ALGLIB code - */ - if( imax2(m, n, _state)<=tsb ) - { - if( rmatrixlefttrsmmkl(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state) ) - { - return; - } - } - if( imax2(m, n, _state)<=tsa ) - { - ablas_rmatrixlefttrsm2(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - return; - } - - /* - * Recursive subdivision - */ - if( n>=m ) - { - - /* - * Split X: op(A)^-1*X = op(A)^-1*(X1 X2) - */ - tiledsplit(n, tscur, &s1, &s2, _state); - rmatrixlefttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - rmatrixlefttrsm(m, s2, a, i1, j1, isupper, isunit, optype, x, i2, j2+s1, _state); - } - else - { - - /* - * Split A - */ - tiledsplit(m, tscur, &s1, &s2, _state); - if( isupper&&optype==0 ) - { - - /* - * (A1 A12)-1 ( X1 ) - * A^-1*X* = ( ) *( ) - * ( A2) ( X2 ) - */ - rmatrixlefttrsm(s2, n, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2+s1, j2, _state); - rmatrixgemm(s1, n, s2, -1.0, a, i1, j1+s1, 0, x, i2+s1, j2, 0, 1.0, x, i2, j2, _state); - rmatrixlefttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - } - if( isupper&&optype!=0 ) - { - - /* - * (A1' )-1 ( X1 ) - * A^-1*X = ( ) *( ) - * (A12' A2') ( X2 ) - */ - rmatrixlefttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - rmatrixgemm(s2, n, s1, -1.0, a, i1, j1+s1, optype, x, i2, j2, 0, 1.0, x, i2+s1, j2, _state); - rmatrixlefttrsm(s2, n, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2+s1, j2, _state); - } - if( !isupper&&optype==0 ) - { - - /* - * (A1 )-1 ( X1 ) - * A^-1*X = ( ) *( ) - * (A21 A2) ( X2 ) - */ - rmatrixlefttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - rmatrixgemm(s2, n, s1, -1.0, a, i1+s1, j1, 0, x, i2, j2, 0, 1.0, x, i2+s1, j2, _state); - rmatrixlefttrsm(s2, n, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2+s1, j2, _state); - } - if( !isupper&&optype!=0 ) - { - - /* - * (A1' A21')-1 ( X1 ) - * A^-1*X = ( ) *( ) - * ( A2') ( X2 ) - */ - rmatrixlefttrsm(s2, n, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2+s1, j2, _state); - rmatrixgemm(s1, n, s2, -1.0, a, i1+s1, j1, optype, x, i2+s1, j2, 0, 1.0, x, i2, j2, _state); - rmatrixlefttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state); - } - } -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_rmatrixlefttrsm(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -This subroutine calculates C=alpha*A*A^H+beta*C or C=alpha*A^H*A+beta*C -where: -* C is NxN Hermitian matrix given by its upper/lower triangle -* A is NxK matrix when A*A^H is calculated, KxN matrix otherwise - -Additional info: -* multiplication result replaces C. If Beta=0, C elements are not used in - calculations (not multiplied by zero - just not referenced) -* if Alpha=0, A is not used (not multiplied by zero - just not referenced) -* if both Beta and Alpha are zero, C is filled by zeros. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - K - matrix size, K>=0 - Alpha - coefficient - A - matrix - IA - submatrix offset (row index) - JA - submatrix offset (column index) - OpTypeA - multiplication type: - * 0 - A*A^H is calculated - * 2 - A^H*A is calculated - Beta - coefficient - C - preallocated input/output matrix - IC - submatrix offset (row index) - JC - submatrix offset (column index) - IsUpper - whether upper or lower triangle of C is updated; - this function updates only one half of C, leaving - other half unchanged (not referenced at all). - - -- ALGLIB routine -- - 16.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -void cmatrixherk(ae_int_t n, - ae_int_t k, - double alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state) -{ - ae_int_t s1; - ae_int_t s2; - ae_int_t tsa; - ae_int_t tsb; - ae_int_t tscur; - - - tsa = matrixtilesizea(_state)/2; - tsb = matrixtilesizeb(_state); - tscur = tsb; - if( imax2(n, k, _state)<=tsb ) - { - tscur = tsa; - } - ae_assert(tscur>=1, "CMatrixHERK: integrity check failed", _state); - - /* - * Decide whether it is feasible to activate multithreading - */ - if( n>=2*tsb&&ae_fp_greater_eq(8*rmul3((double)(k), (double)(n), (double)(n), _state)/2,smpactivationlevel(_state)) ) - { - if( _trypexec_cmatrixherk(n,k,alpha,a,ia,ja,optypea,beta,c,ic,jc,isupper, _state) ) - { - return; - } - } - - /* - * Use MKL or ALGLIB basecase code - */ - if( imax2(n, k, _state)<=tsb ) - { - if( cmatrixherkmkl(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state) ) - { - return; - } - } - if( imax2(n, k, _state)<=tsa ) - { - ablas_cmatrixherk2(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state); - return; - } - - /* - * Recursive division of the problem - */ - if( k>=n ) - { - - /* - * Split K - */ - tiledsplit(k, tscur, &s1, &s2, _state); - if( optypea==0 ) - { - cmatrixherk(n, s1, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state); - cmatrixherk(n, s2, alpha, a, ia, ja+s1, optypea, 1.0, c, ic, jc, isupper, _state); - } - else - { - cmatrixherk(n, s1, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state); - cmatrixherk(n, s2, alpha, a, ia+s1, ja, optypea, 1.0, c, ic, jc, isupper, _state); - } - } - else - { - - /* - * Split N - */ - tiledsplit(n, tscur, &s1, &s2, _state); - if( optypea==0&&isupper ) - { - cmatrixherk(s1, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state); - cmatrixherk(s2, k, alpha, a, ia+s1, ja, optypea, beta, c, ic+s1, jc+s1, isupper, _state); - cmatrixgemm(s1, s2, k, ae_complex_from_d(alpha), a, ia, ja, 0, a, ia+s1, ja, 2, ae_complex_from_d(beta), c, ic, jc+s1, _state); - } - if( optypea==0&&!isupper ) - { - cmatrixherk(s1, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state); - cmatrixherk(s2, k, alpha, a, ia+s1, ja, optypea, beta, c, ic+s1, jc+s1, isupper, _state); - cmatrixgemm(s2, s1, k, ae_complex_from_d(alpha), a, ia+s1, ja, 0, a, ia, ja, 2, ae_complex_from_d(beta), c, ic+s1, jc, _state); - } - if( optypea!=0&&isupper ) - { - cmatrixherk(s1, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state); - cmatrixherk(s2, k, alpha, a, ia, ja+s1, optypea, beta, c, ic+s1, jc+s1, isupper, _state); - cmatrixgemm(s1, s2, k, ae_complex_from_d(alpha), a, ia, ja, 2, a, ia, ja+s1, 0, ae_complex_from_d(beta), c, ic, jc+s1, _state); - } - if( optypea!=0&&!isupper ) - { - cmatrixherk(s1, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state); - cmatrixherk(s2, k, alpha, a, ia, ja+s1, optypea, beta, c, ic+s1, jc+s1, isupper, _state); - cmatrixgemm(s2, s1, k, ae_complex_from_d(alpha), a, ia, ja+s1, 2, a, ia, ja, 0, ae_complex_from_d(beta), c, ic+s1, jc, _state); - } - } -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_cmatrixherk(ae_int_t n, - ae_int_t k, - double alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -This subroutine calculates C=alpha*A*A^T+beta*C or C=alpha*A^T*A+beta*C -where: -* C is NxN symmetric matrix given by its upper/lower triangle -* A is NxK matrix when A*A^T is calculated, KxN matrix otherwise - -Additional info: -* multiplication result replaces C. If Beta=0, C elements are not used in - calculations (not multiplied by zero - just not referenced) -* if Alpha=0, A is not used (not multiplied by zero - just not referenced) -* if both Beta and Alpha are zero, C is filled by zeros. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - K - matrix size, K>=0 - Alpha - coefficient - A - matrix - IA - submatrix offset (row index) - JA - submatrix offset (column index) - OpTypeA - multiplication type: - * 0 - A*A^T is calculated - * 2 - A^T*A is calculated - Beta - coefficient - C - preallocated input/output matrix - IC - submatrix offset (row index) - JC - submatrix offset (column index) - IsUpper - whether C is upper triangular or lower triangular - - -- ALGLIB routine -- - 16.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -void rmatrixsyrk(ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state) -{ - ae_int_t s1; - ae_int_t s2; - ae_int_t tsa; - ae_int_t tsb; - ae_int_t tscur; - - - tsa = matrixtilesizea(_state); - tsb = matrixtilesizeb(_state); - tscur = tsb; - if( imax2(n, k, _state)<=tsb ) - { - tscur = tsa; - } - ae_assert(tscur>=1, "RMatrixSYRK: integrity check failed", _state); - - /* - * Decide whether it is feasible to activate multithreading - */ - if( n>=2*tsb&&ae_fp_greater_eq(2*rmul3((double)(k), (double)(n), (double)(n), _state)/2,smpactivationlevel(_state)) ) - { - if( _trypexec_rmatrixsyrk(n,k,alpha,a,ia,ja,optypea,beta,c,ic,jc,isupper, _state) ) - { - return; - } - } - - /* - * Use MKL or generic basecase code - */ - if( imax2(n, k, _state)<=tsb ) - { - if( rmatrixsyrkmkl(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state) ) - { - return; - } - } - if( imax2(n, k, _state)<=tsa ) - { - ablas_rmatrixsyrk2(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state); - return; - } - - /* - * Recursive subdivision of the problem - */ - if( k>=n ) - { - - /* - * Split K - */ - tiledsplit(k, tscur, &s1, &s2, _state); - if( optypea==0 ) - { - rmatrixsyrk(n, s1, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state); - rmatrixsyrk(n, s2, alpha, a, ia, ja+s1, optypea, 1.0, c, ic, jc, isupper, _state); - } - else - { - rmatrixsyrk(n, s1, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state); - rmatrixsyrk(n, s2, alpha, a, ia+s1, ja, optypea, 1.0, c, ic, jc, isupper, _state); - } - } - else - { - - /* - * Split N - */ - tiledsplit(n, tscur, &s1, &s2, _state); - if( optypea==0&&isupper ) - { - rmatrixsyrk(s1, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state); - rmatrixsyrk(s2, k, alpha, a, ia+s1, ja, optypea, beta, c, ic+s1, jc+s1, isupper, _state); - rmatrixgemm(s1, s2, k, alpha, a, ia, ja, 0, a, ia+s1, ja, 1, beta, c, ic, jc+s1, _state); - } - if( optypea==0&&!isupper ) - { - rmatrixsyrk(s1, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state); - rmatrixsyrk(s2, k, alpha, a, ia+s1, ja, optypea, beta, c, ic+s1, jc+s1, isupper, _state); - rmatrixgemm(s2, s1, k, alpha, a, ia+s1, ja, 0, a, ia, ja, 1, beta, c, ic+s1, jc, _state); - } - if( optypea!=0&&isupper ) - { - rmatrixsyrk(s1, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state); - rmatrixsyrk(s2, k, alpha, a, ia, ja+s1, optypea, beta, c, ic+s1, jc+s1, isupper, _state); - rmatrixgemm(s1, s2, k, alpha, a, ia, ja, 1, a, ia, ja+s1, 0, beta, c, ic, jc+s1, _state); - } - if( optypea!=0&&!isupper ) - { - rmatrixsyrk(s1, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state); - rmatrixsyrk(s2, k, alpha, a, ia, ja+s1, optypea, beta, c, ic+s1, jc+s1, isupper, _state); - rmatrixgemm(s2, s1, k, alpha, a, ia, ja+s1, 1, a, ia, ja, 0, beta, c, ic+s1, jc, _state); - } - } -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_rmatrixsyrk(ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -This subroutine calculates C = alpha*op1(A)*op2(B) +beta*C where: -* C is MxN general matrix -* op1(A) is MxK matrix -* op2(B) is KxN matrix -* "op" may be identity transformation, transposition, conjugate transposition - -Additional info: -* cache-oblivious algorithm is used. -* multiplication result replaces C. If Beta=0, C elements are not used in - calculations (not multiplied by zero - just not referenced) -* if Alpha=0, A is not used (not multiplied by zero - just not referenced) -* if both Beta and Alpha are zero, C is filled by zeros. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -IMPORTANT: - -This function does NOT preallocate output matrix C, it MUST be preallocated -by caller prior to calling this function. In case C does not have enough -space to store result, exception will be generated. - -INPUT PARAMETERS - M - matrix size, M>0 - N - matrix size, N>0 - K - matrix size, K>0 - Alpha - coefficient - A - matrix - IA - submatrix offset - JA - submatrix offset - OpTypeA - transformation type: - * 0 - no transformation - * 1 - transposition - * 2 - conjugate transposition - B - matrix - IB - submatrix offset - JB - submatrix offset - OpTypeB - transformation type: - * 0 - no transformation - * 1 - transposition - * 2 - conjugate transposition - Beta - coefficient - C - matrix (PREALLOCATED, large enough to store result) - IC - submatrix offset - JC - submatrix offset - - -- ALGLIB routine -- - 2009-2019 - Bochkanov Sergey -*************************************************************************/ -void cmatrixgemm(ae_int_t m, - ae_int_t n, - ae_int_t k, - ae_complex alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Complex */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - ae_complex beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state) -{ - ae_int_t ts; - - - ts = matrixtilesizeb(_state); - - /* - * Check input sizes for correctness - */ - ae_assert((optypea==0||optypea==1)||optypea==2, "CMatrixGEMM: incorrect OpTypeA (must be 0 or 1 or 2)", _state); - ae_assert((optypeb==0||optypeb==1)||optypeb==2, "CMatrixGEMM: incorrect OpTypeB (must be 0 or 1 or 2)", _state); - ae_assert(ic+m<=c->rows, "CMatrixGEMM: incorect size of output matrix C", _state); - ae_assert(jc+n<=c->cols, "CMatrixGEMM: incorect size of output matrix C", _state); - - /* - * Decide whether it is feasible to activate multithreading - */ - if( (m>=2*ts||n>=2*ts)&&ae_fp_greater_eq(8*rmul3((double)(m), (double)(n), (double)(k), _state),smpactivationlevel(_state)) ) - { - if( _trypexec_cmatrixgemm(m,n,k,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc, _state) ) - { - return; - } - } - - /* - * Start actual work - */ - ablas_cmatrixgemmrec(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_cmatrixgemm(ae_int_t m, - ae_int_t n, - ae_int_t k, - ae_complex alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Complex */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - ae_complex beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -This subroutine calculates C = alpha*op1(A)*op2(B) +beta*C where: -* C is MxN general matrix -* op1(A) is MxK matrix -* op2(B) is KxN matrix -* "op" may be identity transformation, transposition - -Additional info: -* cache-oblivious algorithm is used. -* multiplication result replaces C. If Beta=0, C elements are not used in - calculations (not multiplied by zero - just not referenced) -* if Alpha=0, A is not used (not multiplied by zero - just not referenced) -* if both Beta and Alpha are zero, C is filled by zeros. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -IMPORTANT: - -This function does NOT preallocate output matrix C, it MUST be preallocated -by caller prior to calling this function. In case C does not have enough -space to store result, exception will be generated. - -INPUT PARAMETERS - M - matrix size, M>0 - N - matrix size, N>0 - K - matrix size, K>0 - Alpha - coefficient - A - matrix - IA - submatrix offset - JA - submatrix offset - OpTypeA - transformation type: - * 0 - no transformation - * 1 - transposition - B - matrix - IB - submatrix offset - JB - submatrix offset - OpTypeB - transformation type: - * 0 - no transformation - * 1 - transposition - Beta - coefficient - C - PREALLOCATED output matrix, large enough to store result - IC - submatrix offset - JC - submatrix offset - - -- ALGLIB routine -- - 2009-2019 - Bochkanov Sergey -*************************************************************************/ -void rmatrixgemm(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state) -{ - ae_int_t ts; - - - ts = matrixtilesizeb(_state); - - /* - * Check input sizes for correctness - */ - ae_assert(optypea==0||optypea==1, "RMatrixGEMM: incorrect OpTypeA (must be 0 or 1)", _state); - ae_assert(optypeb==0||optypeb==1, "RMatrixGEMM: incorrect OpTypeB (must be 0 or 1)", _state); - ae_assert(ic+m<=c->rows, "RMatrixGEMM: incorect size of output matrix C", _state); - ae_assert(jc+n<=c->cols, "RMatrixGEMM: incorect size of output matrix C", _state); - - /* - * Decide whether it is feasible to activate multithreading - */ - if( (m>=2*ts||n>=2*ts)&&ae_fp_greater_eq(2*rmul3((double)(m), (double)(n), (double)(k), _state),smpactivationlevel(_state)) ) - { - if( _trypexec_rmatrixgemm(m,n,k,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc, _state) ) - { - return; - } - } - - /* - * Start actual work - */ - ablas_rmatrixgemmrec(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_rmatrixgemm(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -This subroutine is an older version of CMatrixHERK(), one with wrong name -(it is HErmitian update, not SYmmetric). It is left here for backward -compatibility. - - -- ALGLIB routine -- - 16.12.2009 - Bochkanov Sergey -*************************************************************************/ -void cmatrixsyrk(ae_int_t n, - ae_int_t k, - double alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state) -{ - - - cmatrixherk(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state); -} - - -/************************************************************************* -Performs one step of stable Gram-Schmidt process on vector X[] using -set of orthonormal rows Q[]. - -INPUT PARAMETERS: - Q - array[M,N], matrix with orthonormal rows - M, N - rows/cols - X - array[N], vector to process - NeedQX - whether we need QX or not - -OUTPUT PARAMETERS: - X - stores X - Q'*(Q*X) - QX - if NeedQX is True, array[M] filled with elements of Q*X, - reallocated if length is less than M. - Ignored otherwise. - - -- ALGLIB -- - Copyright 20.01.2020 by Bochkanov Sergey -*************************************************************************/ -void rowwisegramschmidt(/* Real */ ae_matrix* q, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* qx, - ae_bool needqx, - ae_state *_state) -{ - ae_int_t i; - double v; - - - if( needqx ) - { - rvectorsetlengthatleast(qx, m, _state); - } - for(i=0; i<=m-1; i++) - { - v = rdotvr(n, x, q, i, _state); - raddrv(n, -v, q, i, x, _state); - if( needqx ) - { - qx->ptr.p_double[i] = v; - } - } -} - - -/************************************************************************* -Complex ABLASSplitLength - - -- ALGLIB routine -- - 15.12.2009 - Bochkanov Sergey -*************************************************************************/ -static void ablas_ablasinternalsplitlength(ae_int_t n, - ae_int_t nb, - ae_int_t* n1, - ae_int_t* n2, - ae_state *_state) -{ - ae_int_t r; - - *n1 = 0; - *n2 = 0; - - if( n<=nb ) - { - - /* - * Block size, no further splitting - */ - *n1 = n; - *n2 = 0; - } - else - { - - /* - * Greater than block size - */ - if( n%nb!=0 ) - { - - /* - * Split remainder - */ - *n2 = n%nb; - *n1 = n-(*n2); - } - else - { - - /* - * Split on block boundaries - */ - *n2 = n/2; - *n1 = n-(*n2); - if( *n1%nb==0 ) - { - return; - } - r = nb-*n1%nb; - *n1 = *n1+r; - *n2 = *n2-r; - } - } -} - - -/************************************************************************* -Level 2 variant of CMatrixRightTRSM -*************************************************************************/ -static void ablas_cmatrixrighttrsm2(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_complex vc; - ae_complex vd; - - - - /* - * Special case - */ - if( n*m==0 ) - { - return; - } - - /* - * Try to call fast TRSM - */ - if( cmatrixrighttrsmf(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state) ) - { - return; - } - - /* - * General case - */ - if( isupper ) - { - - /* - * Upper triangular matrix - */ - if( optype==0 ) - { - - /* - * X*A^(-1) - */ - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( isunit ) - { - vd = ae_complex_from_i(1); - } - else - { - vd = a->ptr.pp_complex[i1+j][j1+j]; - } - x->ptr.pp_complex[i2+i][j2+j] = ae_c_div(x->ptr.pp_complex[i2+i][j2+j],vd); - if( jptr.pp_complex[i2+i][j2+j]; - ae_v_csubc(&x->ptr.pp_complex[i2+i][j2+j+1], 1, &a->ptr.pp_complex[i1+j][j1+j+1], 1, "N", ae_v_len(j2+j+1,j2+n-1), vc); - } - } - } - return; - } - if( optype==1 ) - { - - /* - * X*A^(-T) - */ - for(i=0; i<=m-1; i++) - { - for(j=n-1; j>=0; j--) - { - vc = ae_complex_from_i(0); - vd = ae_complex_from_i(1); - if( jptr.pp_complex[i2+i][j2+j+1], 1, "N", &a->ptr.pp_complex[i1+j][j1+j+1], 1, "N", ae_v_len(j2+j+1,j2+n-1)); - } - if( !isunit ) - { - vd = a->ptr.pp_complex[i1+j][j1+j]; - } - x->ptr.pp_complex[i2+i][j2+j] = ae_c_div(ae_c_sub(x->ptr.pp_complex[i2+i][j2+j],vc),vd); - } - } - return; - } - if( optype==2 ) - { - - /* - * X*A^(-H) - */ - for(i=0; i<=m-1; i++) - { - for(j=n-1; j>=0; j--) - { - vc = ae_complex_from_i(0); - vd = ae_complex_from_i(1); - if( jptr.pp_complex[i2+i][j2+j+1], 1, "N", &a->ptr.pp_complex[i1+j][j1+j+1], 1, "Conj", ae_v_len(j2+j+1,j2+n-1)); - } - if( !isunit ) - { - vd = ae_c_conj(a->ptr.pp_complex[i1+j][j1+j], _state); - } - x->ptr.pp_complex[i2+i][j2+j] = ae_c_div(ae_c_sub(x->ptr.pp_complex[i2+i][j2+j],vc),vd); - } - } - return; - } - } - else - { - - /* - * Lower triangular matrix - */ - if( optype==0 ) - { - - /* - * X*A^(-1) - */ - for(i=0; i<=m-1; i++) - { - for(j=n-1; j>=0; j--) - { - if( isunit ) - { - vd = ae_complex_from_i(1); - } - else - { - vd = a->ptr.pp_complex[i1+j][j1+j]; - } - x->ptr.pp_complex[i2+i][j2+j] = ae_c_div(x->ptr.pp_complex[i2+i][j2+j],vd); - if( j>0 ) - { - vc = x->ptr.pp_complex[i2+i][j2+j]; - ae_v_csubc(&x->ptr.pp_complex[i2+i][j2], 1, &a->ptr.pp_complex[i1+j][j1], 1, "N", ae_v_len(j2,j2+j-1), vc); - } - } - } - return; - } - if( optype==1 ) - { - - /* - * X*A^(-T) - */ - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - vc = ae_complex_from_i(0); - vd = ae_complex_from_i(1); - if( j>0 ) - { - vc = ae_v_cdotproduct(&x->ptr.pp_complex[i2+i][j2], 1, "N", &a->ptr.pp_complex[i1+j][j1], 1, "N", ae_v_len(j2,j2+j-1)); - } - if( !isunit ) - { - vd = a->ptr.pp_complex[i1+j][j1+j]; - } - x->ptr.pp_complex[i2+i][j2+j] = ae_c_div(ae_c_sub(x->ptr.pp_complex[i2+i][j2+j],vc),vd); - } - } - return; - } - if( optype==2 ) - { - - /* - * X*A^(-H) - */ - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - vc = ae_complex_from_i(0); - vd = ae_complex_from_i(1); - if( j>0 ) - { - vc = ae_v_cdotproduct(&x->ptr.pp_complex[i2+i][j2], 1, "N", &a->ptr.pp_complex[i1+j][j1], 1, "Conj", ae_v_len(j2,j2+j-1)); - } - if( !isunit ) - { - vd = ae_c_conj(a->ptr.pp_complex[i1+j][j1+j], _state); - } - x->ptr.pp_complex[i2+i][j2+j] = ae_c_div(ae_c_sub(x->ptr.pp_complex[i2+i][j2+j],vc),vd); - } - } - return; - } - } -} - - -/************************************************************************* -Level-2 subroutine -*************************************************************************/ -static void ablas_cmatrixlefttrsm2(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_complex vc; - ae_complex vd; - - - - /* - * Special case - */ - if( n*m==0 ) - { - return; - } - - /* - * Try to call fast TRSM - */ - if( cmatrixlefttrsmf(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state) ) - { - return; - } - - /* - * General case - */ - if( isupper ) - { - - /* - * Upper triangular matrix - */ - if( optype==0 ) - { - - /* - * A^(-1)*X - */ - for(i=m-1; i>=0; i--) - { - for(j=i+1; j<=m-1; j++) - { - vc = a->ptr.pp_complex[i1+i][j1+j]; - ae_v_csubc(&x->ptr.pp_complex[i2+i][j2], 1, &x->ptr.pp_complex[i2+j][j2], 1, "N", ae_v_len(j2,j2+n-1), vc); - } - if( !isunit ) - { - vd = ae_c_d_div(1,a->ptr.pp_complex[i1+i][j1+i]); - ae_v_cmulc(&x->ptr.pp_complex[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vd); - } - } - return; - } - if( optype==1 ) - { - - /* - * A^(-T)*X - */ - for(i=0; i<=m-1; i++) - { - if( isunit ) - { - vd = ae_complex_from_i(1); - } - else - { - vd = ae_c_d_div(1,a->ptr.pp_complex[i1+i][j1+i]); - } - ae_v_cmulc(&x->ptr.pp_complex[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vd); - for(j=i+1; j<=m-1; j++) - { - vc = a->ptr.pp_complex[i1+i][j1+j]; - ae_v_csubc(&x->ptr.pp_complex[i2+j][j2], 1, &x->ptr.pp_complex[i2+i][j2], 1, "N", ae_v_len(j2,j2+n-1), vc); - } - } - return; - } - if( optype==2 ) - { - - /* - * A^(-H)*X - */ - for(i=0; i<=m-1; i++) - { - if( isunit ) - { - vd = ae_complex_from_i(1); - } - else - { - vd = ae_c_d_div(1,ae_c_conj(a->ptr.pp_complex[i1+i][j1+i], _state)); - } - ae_v_cmulc(&x->ptr.pp_complex[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vd); - for(j=i+1; j<=m-1; j++) - { - vc = ae_c_conj(a->ptr.pp_complex[i1+i][j1+j], _state); - ae_v_csubc(&x->ptr.pp_complex[i2+j][j2], 1, &x->ptr.pp_complex[i2+i][j2], 1, "N", ae_v_len(j2,j2+n-1), vc); - } - } - return; - } - } - else - { - - /* - * Lower triangular matrix - */ - if( optype==0 ) - { - - /* - * A^(-1)*X - */ - for(i=0; i<=m-1; i++) - { - for(j=0; j<=i-1; j++) - { - vc = a->ptr.pp_complex[i1+i][j1+j]; - ae_v_csubc(&x->ptr.pp_complex[i2+i][j2], 1, &x->ptr.pp_complex[i2+j][j2], 1, "N", ae_v_len(j2,j2+n-1), vc); - } - if( isunit ) - { - vd = ae_complex_from_i(1); - } - else - { - vd = ae_c_d_div(1,a->ptr.pp_complex[i1+j][j1+j]); - } - ae_v_cmulc(&x->ptr.pp_complex[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vd); - } - return; - } - if( optype==1 ) - { - - /* - * A^(-T)*X - */ - for(i=m-1; i>=0; i--) - { - if( isunit ) - { - vd = ae_complex_from_i(1); - } - else - { - vd = ae_c_d_div(1,a->ptr.pp_complex[i1+i][j1+i]); - } - ae_v_cmulc(&x->ptr.pp_complex[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vd); - for(j=i-1; j>=0; j--) - { - vc = a->ptr.pp_complex[i1+i][j1+j]; - ae_v_csubc(&x->ptr.pp_complex[i2+j][j2], 1, &x->ptr.pp_complex[i2+i][j2], 1, "N", ae_v_len(j2,j2+n-1), vc); - } - } - return; - } - if( optype==2 ) - { - - /* - * A^(-H)*X - */ - for(i=m-1; i>=0; i--) - { - if( isunit ) - { - vd = ae_complex_from_i(1); - } - else - { - vd = ae_c_d_div(1,ae_c_conj(a->ptr.pp_complex[i1+i][j1+i], _state)); - } - ae_v_cmulc(&x->ptr.pp_complex[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vd); - for(j=i-1; j>=0; j--) - { - vc = ae_c_conj(a->ptr.pp_complex[i1+i][j1+j], _state); - ae_v_csubc(&x->ptr.pp_complex[i2+j][j2], 1, &x->ptr.pp_complex[i2+i][j2], 1, "N", ae_v_len(j2,j2+n-1), vc); - } - } - return; - } - } -} - - -/************************************************************************* -Level 2 subroutine - - -- ALGLIB routine -- - 15.12.2009 - Bochkanov Sergey -*************************************************************************/ -static void ablas_rmatrixrighttrsm2(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double vr; - double vd; - - - - /* - * Special case - */ - if( n*m==0 ) - { - return; - } - - /* - * Try to use "fast" code - */ - if( rmatrixrighttrsmf(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state) ) - { - return; - } - - /* - * General case - */ - if( isupper ) - { - - /* - * Upper triangular matrix - */ - if( optype==0 ) - { - - /* - * X*A^(-1) - */ - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( isunit ) - { - vd = (double)(1); - } - else - { - vd = a->ptr.pp_double[i1+j][j1+j]; - } - x->ptr.pp_double[i2+i][j2+j] = x->ptr.pp_double[i2+i][j2+j]/vd; - if( jptr.pp_double[i2+i][j2+j]; - ae_v_subd(&x->ptr.pp_double[i2+i][j2+j+1], 1, &a->ptr.pp_double[i1+j][j1+j+1], 1, ae_v_len(j2+j+1,j2+n-1), vr); - } - } - } - return; - } - if( optype==1 ) - { - - /* - * X*A^(-T) - */ - for(i=0; i<=m-1; i++) - { - for(j=n-1; j>=0; j--) - { - vr = (double)(0); - vd = (double)(1); - if( jptr.pp_double[i2+i][j2+j+1], 1, &a->ptr.pp_double[i1+j][j1+j+1], 1, ae_v_len(j2+j+1,j2+n-1)); - } - if( !isunit ) - { - vd = a->ptr.pp_double[i1+j][j1+j]; - } - x->ptr.pp_double[i2+i][j2+j] = (x->ptr.pp_double[i2+i][j2+j]-vr)/vd; - } - } - return; - } - } - else - { - - /* - * Lower triangular matrix - */ - if( optype==0 ) - { - - /* - * X*A^(-1) - */ - for(i=0; i<=m-1; i++) - { - for(j=n-1; j>=0; j--) - { - if( isunit ) - { - vd = (double)(1); - } - else - { - vd = a->ptr.pp_double[i1+j][j1+j]; - } - x->ptr.pp_double[i2+i][j2+j] = x->ptr.pp_double[i2+i][j2+j]/vd; - if( j>0 ) - { - vr = x->ptr.pp_double[i2+i][j2+j]; - ae_v_subd(&x->ptr.pp_double[i2+i][j2], 1, &a->ptr.pp_double[i1+j][j1], 1, ae_v_len(j2,j2+j-1), vr); - } - } - } - return; - } - if( optype==1 ) - { - - /* - * X*A^(-T) - */ - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - vr = (double)(0); - vd = (double)(1); - if( j>0 ) - { - vr = ae_v_dotproduct(&x->ptr.pp_double[i2+i][j2], 1, &a->ptr.pp_double[i1+j][j1], 1, ae_v_len(j2,j2+j-1)); - } - if( !isunit ) - { - vd = a->ptr.pp_double[i1+j][j1+j]; - } - x->ptr.pp_double[i2+i][j2+j] = (x->ptr.pp_double[i2+i][j2+j]-vr)/vd; - } - } - return; - } - } -} - - -/************************************************************************* -Level 2 subroutine -*************************************************************************/ -static void ablas_rmatrixlefttrsm2(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double vr; - double vd; - - - - /* - * Special case - */ - if( n==0||m==0 ) - { - return; - } - - /* - * Try fast code - */ - if( rmatrixlefttrsmf(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state) ) - { - return; - } - - /* - * General case - */ - if( isupper ) - { - - /* - * Upper triangular matrix - */ - if( optype==0 ) - { - - /* - * A^(-1)*X - */ - for(i=m-1; i>=0; i--) - { - for(j=i+1; j<=m-1; j++) - { - vr = a->ptr.pp_double[i1+i][j1+j]; - ae_v_subd(&x->ptr.pp_double[i2+i][j2], 1, &x->ptr.pp_double[i2+j][j2], 1, ae_v_len(j2,j2+n-1), vr); - } - if( !isunit ) - { - vd = 1/a->ptr.pp_double[i1+i][j1+i]; - ae_v_muld(&x->ptr.pp_double[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vd); - } - } - return; - } - if( optype==1 ) - { - - /* - * A^(-T)*X - */ - for(i=0; i<=m-1; i++) - { - if( isunit ) - { - vd = (double)(1); - } - else - { - vd = 1/a->ptr.pp_double[i1+i][j1+i]; - } - ae_v_muld(&x->ptr.pp_double[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vd); - for(j=i+1; j<=m-1; j++) - { - vr = a->ptr.pp_double[i1+i][j1+j]; - ae_v_subd(&x->ptr.pp_double[i2+j][j2], 1, &x->ptr.pp_double[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vr); - } - } - return; - } - } - else - { - - /* - * Lower triangular matrix - */ - if( optype==0 ) - { - - /* - * A^(-1)*X - */ - for(i=0; i<=m-1; i++) - { - for(j=0; j<=i-1; j++) - { - vr = a->ptr.pp_double[i1+i][j1+j]; - ae_v_subd(&x->ptr.pp_double[i2+i][j2], 1, &x->ptr.pp_double[i2+j][j2], 1, ae_v_len(j2,j2+n-1), vr); - } - if( isunit ) - { - vd = (double)(1); - } - else - { - vd = 1/a->ptr.pp_double[i1+j][j1+j]; - } - ae_v_muld(&x->ptr.pp_double[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vd); - } - return; - } - if( optype==1 ) - { - - /* - * A^(-T)*X - */ - for(i=m-1; i>=0; i--) - { - if( isunit ) - { - vd = (double)(1); - } - else - { - vd = 1/a->ptr.pp_double[i1+i][j1+i]; - } - ae_v_muld(&x->ptr.pp_double[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vd); - for(j=i-1; j>=0; j--) - { - vr = a->ptr.pp_double[i1+i][j1+j]; - ae_v_subd(&x->ptr.pp_double[i2+j][j2], 1, &x->ptr.pp_double[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vr); - } - } - return; - } - } -} - - -/************************************************************************* -Level 2 subroutine -*************************************************************************/ -static void ablas_cmatrixherk2(ae_int_t n, - ae_int_t k, - double alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t j1; - ae_int_t j2; - ae_complex v; - - - - /* - * Fast exit (nothing to be done) - */ - if( (ae_fp_eq(alpha,(double)(0))||k==0)&&ae_fp_eq(beta,(double)(1)) ) - { - return; - } - - /* - * Try to call fast SYRK - */ - if( cmatrixherkf(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state) ) - { - return; - } - - /* - * SYRK - */ - if( optypea==0 ) - { - - /* - * C=alpha*A*A^H+beta*C - */ - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j1 = i; - j2 = n-1; - } - else - { - j1 = 0; - j2 = i; - } - for(j=j1; j<=j2; j++) - { - if( ae_fp_neq(alpha,(double)(0))&&k>0 ) - { - v = ae_v_cdotproduct(&a->ptr.pp_complex[ia+i][ja], 1, "N", &a->ptr.pp_complex[ia+j][ja], 1, "Conj", ae_v_len(ja,ja+k-1)); - } - else - { - v = ae_complex_from_i(0); - } - if( ae_fp_eq(beta,(double)(0)) ) - { - c->ptr.pp_complex[ic+i][jc+j] = ae_c_mul_d(v,alpha); - } - else - { - c->ptr.pp_complex[ic+i][jc+j] = ae_c_add(ae_c_mul_d(c->ptr.pp_complex[ic+i][jc+j],beta),ae_c_mul_d(v,alpha)); - } - } - } - return; - } - else - { - - /* - * C=alpha*A^H*A+beta*C - */ - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j1 = i; - j2 = n-1; - } - else - { - j1 = 0; - j2 = i; - } - if( ae_fp_eq(beta,(double)(0)) ) - { - for(j=j1; j<=j2; j++) - { - c->ptr.pp_complex[ic+i][jc+j] = ae_complex_from_i(0); - } - } - else - { - ae_v_cmuld(&c->ptr.pp_complex[ic+i][jc+j1], 1, ae_v_len(jc+j1,jc+j2), beta); - } - } - if( ae_fp_neq(alpha,(double)(0))&&k>0 ) - { - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( isupper ) - { - j1 = j; - j2 = n-1; - } - else - { - j1 = 0; - j2 = j; - } - v = ae_c_mul_d(ae_c_conj(a->ptr.pp_complex[ia+i][ja+j], _state),alpha); - ae_v_caddc(&c->ptr.pp_complex[ic+j][jc+j1], 1, &a->ptr.pp_complex[ia+i][ja+j1], 1, "N", ae_v_len(jc+j1,jc+j2), v); - } - } - } - return; - } -} - - -/************************************************************************* -Level 2 subrotuine -*************************************************************************/ -static void ablas_rmatrixsyrk2(ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t j1; - ae_int_t j2; - double v; - - - - /* - * Fast exit (nothing to be done) - */ - if( (ae_fp_eq(alpha,(double)(0))||k==0)&&ae_fp_eq(beta,(double)(1)) ) - { - return; - } - - /* - * Try to call fast SYRK - */ - if( rmatrixsyrkf(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state) ) - { - return; - } - - /* - * SYRK - */ - if( optypea==0 ) - { - - /* - * C=alpha*A*A^H+beta*C - */ - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j1 = i; - j2 = n-1; - } - else - { - j1 = 0; - j2 = i; - } - for(j=j1; j<=j2; j++) - { - if( ae_fp_neq(alpha,(double)(0))&&k>0 ) - { - v = ae_v_dotproduct(&a->ptr.pp_double[ia+i][ja], 1, &a->ptr.pp_double[ia+j][ja], 1, ae_v_len(ja,ja+k-1)); - } - else - { - v = (double)(0); - } - if( ae_fp_eq(beta,(double)(0)) ) - { - c->ptr.pp_double[ic+i][jc+j] = alpha*v; - } - else - { - c->ptr.pp_double[ic+i][jc+j] = beta*c->ptr.pp_double[ic+i][jc+j]+alpha*v; - } - } - } - return; - } - else - { - - /* - * C=alpha*A^H*A+beta*C - */ - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j1 = i; - j2 = n-1; - } - else - { - j1 = 0; - j2 = i; - } - if( ae_fp_eq(beta,(double)(0)) ) - { - for(j=j1; j<=j2; j++) - { - c->ptr.pp_double[ic+i][jc+j] = (double)(0); - } - } - else - { - ae_v_muld(&c->ptr.pp_double[ic+i][jc+j1], 1, ae_v_len(jc+j1,jc+j2), beta); - } - } - if( ae_fp_neq(alpha,(double)(0))&&k>0 ) - { - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( isupper ) - { - j1 = j; - j2 = n-1; - } - else - { - j1 = 0; - j2 = j; - } - v = alpha*a->ptr.pp_double[ia+i][ja+j]; - ae_v_addd(&c->ptr.pp_double[ic+j][jc+j1], 1, &a->ptr.pp_double[ia+i][ja+j1], 1, ae_v_len(jc+j1,jc+j2), v); - } - } - } - return; - } -} - - -/************************************************************************* -This subroutine is an actual implementation of CMatrixGEMM. It does not -perform some integrity checks performed in the driver function, and it -does not activate multithreading framework (driver decides whether to -activate workers or not). - - -- ALGLIB routine -- - 10.01.2019 - Bochkanov Sergey -*************************************************************************/ -static void ablas_cmatrixgemmrec(ae_int_t m, - ae_int_t n, - ae_int_t k, - ae_complex alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Complex */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - ae_complex beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state) -{ - ae_int_t s1; - ae_int_t s2; - ae_int_t tsa; - ae_int_t tsb; - ae_int_t tscur; - - - - /* - * Tile hierarchy: B -> A -> A/2 - */ - tsa = matrixtilesizea(_state)/2; - tsb = matrixtilesizeb(_state); - tscur = tsb; - if( imax3(m, n, k, _state)<=tsb ) - { - tscur = tsa; - } - ae_assert(tscur>=1, "CMatrixGEMMRec: integrity check failed", _state); - - /* - * Use MKL or ALGLIB basecase code - */ - if( imax3(m, n, k, _state)<=tsb ) - { - if( cmatrixgemmmkl(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state) ) - { - return; - } - } - if( imax3(m, n, k, _state)<=tsa ) - { - cmatrixgemmk(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state); - return; - } - - /* - * Recursive algorithm: parallel splitting on M/N - */ - if( m>=n&&m>=k ) - { - - /* - * A*B = (A1 A2)^T*B - */ - tiledsplit(m, tscur, &s1, &s2, _state); - ablas_cmatrixgemmrec(s1, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state); - if( optypea==0 ) - { - ablas_cmatrixgemmrec(s2, n, k, alpha, a, ia+s1, ja, optypea, b, ib, jb, optypeb, beta, c, ic+s1, jc, _state); - } - else - { - ablas_cmatrixgemmrec(s2, n, k, alpha, a, ia, ja+s1, optypea, b, ib, jb, optypeb, beta, c, ic+s1, jc, _state); - } - return; - } - if( n>=m&&n>=k ) - { - - /* - * A*B = A*(B1 B2) - */ - tiledsplit(n, tscur, &s1, &s2, _state); - if( optypeb==0 ) - { - ablas_cmatrixgemmrec(m, s1, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state); - ablas_cmatrixgemmrec(m, s2, k, alpha, a, ia, ja, optypea, b, ib, jb+s1, optypeb, beta, c, ic, jc+s1, _state); - } - else - { - ablas_cmatrixgemmrec(m, s1, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state); - ablas_cmatrixgemmrec(m, s2, k, alpha, a, ia, ja, optypea, b, ib+s1, jb, optypeb, beta, c, ic, jc+s1, _state); - } - return; - } - - /* - * Recursive algorithm: serial splitting on K - */ - - /* - * A*B = (A1 A2)*(B1 B2)^T - */ - tiledsplit(k, tscur, &s1, &s2, _state); - if( optypea==0&&optypeb==0 ) - { - ablas_cmatrixgemmrec(m, n, s1, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state); - ablas_cmatrixgemmrec(m, n, s2, alpha, a, ia, ja+s1, optypea, b, ib+s1, jb, optypeb, ae_complex_from_d(1.0), c, ic, jc, _state); - } - if( optypea==0&&optypeb!=0 ) - { - ablas_cmatrixgemmrec(m, n, s1, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state); - ablas_cmatrixgemmrec(m, n, s2, alpha, a, ia, ja+s1, optypea, b, ib, jb+s1, optypeb, ae_complex_from_d(1.0), c, ic, jc, _state); - } - if( optypea!=0&&optypeb==0 ) - { - ablas_cmatrixgemmrec(m, n, s1, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state); - ablas_cmatrixgemmrec(m, n, s2, alpha, a, ia+s1, ja, optypea, b, ib+s1, jb, optypeb, ae_complex_from_d(1.0), c, ic, jc, _state); - } - if( optypea!=0&&optypeb!=0 ) - { - ablas_cmatrixgemmrec(m, n, s1, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state); - ablas_cmatrixgemmrec(m, n, s2, alpha, a, ia+s1, ja, optypea, b, ib, jb+s1, optypeb, ae_complex_from_d(1.0), c, ic, jc, _state); - } -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_ablas_cmatrixgemmrec(ae_int_t m, - ae_int_t n, - ae_int_t k, - ae_complex alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Complex */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - ae_complex beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -This subroutine is an actual implementation of RMatrixGEMM. It does not -perform some integrity checks performed in the driver function, and it -does not activate multithreading framework (driver decides whether to -activate workers or not). - - -- ALGLIB routine -- - 10.01.2019 - Bochkanov Sergey -*************************************************************************/ -static void ablas_rmatrixgemmrec(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state) -{ - ae_int_t s1; - ae_int_t s2; - ae_int_t tsa; - ae_int_t tsb; - ae_int_t tscur; - - - tsa = matrixtilesizea(_state); - tsb = matrixtilesizeb(_state); - tscur = tsb; - if( imax3(m, n, k, _state)<=tsb ) - { - tscur = tsa; - } - ae_assert(tscur>=1, "RMatrixGEMMRec: integrity check failed", _state); - - /* - * Use MKL or ALGLIB basecase code - */ - if( (m<=tsb&&n<=tsb)&&k<=tsb ) - { - if( rmatrixgemmmkl(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state) ) - { - return; - } - } - if( (m<=tsa&&n<=tsa)&&k<=tsa ) - { - rmatrixgemmk(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state); - return; - } - - /* - * Recursive algorithm: split on M or N - */ - if( m>=n&&m>=k ) - { - - /* - * A*B = (A1 A2)^T*B - */ - tiledsplit(m, tscur, &s1, &s2, _state); - if( optypea==0 ) - { - ablas_rmatrixgemmrec(s2, n, k, alpha, a, ia+s1, ja, optypea, b, ib, jb, optypeb, beta, c, ic+s1, jc, _state); - ablas_rmatrixgemmrec(s1, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state); - } - else - { - ablas_rmatrixgemmrec(s2, n, k, alpha, a, ia, ja+s1, optypea, b, ib, jb, optypeb, beta, c, ic+s1, jc, _state); - ablas_rmatrixgemmrec(s1, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state); - } - return; - } - if( n>=m&&n>=k ) - { - - /* - * A*B = A*(B1 B2) - */ - tiledsplit(n, tscur, &s1, &s2, _state); - if( optypeb==0 ) - { - ablas_rmatrixgemmrec(m, s2, k, alpha, a, ia, ja, optypea, b, ib, jb+s1, optypeb, beta, c, ic, jc+s1, _state); - ablas_rmatrixgemmrec(m, s1, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state); - } - else - { - ablas_rmatrixgemmrec(m, s2, k, alpha, a, ia, ja, optypea, b, ib+s1, jb, optypeb, beta, c, ic, jc+s1, _state); - ablas_rmatrixgemmrec(m, s1, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state); - } - return; - } - - /* - * Recursive algorithm: split on K - */ - - /* - * A*B = (A1 A2)*(B1 B2)^T - */ - tiledsplit(k, tscur, &s1, &s2, _state); - if( optypea==0&&optypeb==0 ) - { - ablas_rmatrixgemmrec(m, n, s1, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state); - ablas_rmatrixgemmrec(m, n, s2, alpha, a, ia, ja+s1, optypea, b, ib+s1, jb, optypeb, 1.0, c, ic, jc, _state); - } - if( optypea==0&&optypeb!=0 ) - { - ablas_rmatrixgemmrec(m, n, s1, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state); - ablas_rmatrixgemmrec(m, n, s2, alpha, a, ia, ja+s1, optypea, b, ib, jb+s1, optypeb, 1.0, c, ic, jc, _state); - } - if( optypea!=0&&optypeb==0 ) - { - ablas_rmatrixgemmrec(m, n, s1, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state); - ablas_rmatrixgemmrec(m, n, s2, alpha, a, ia+s1, ja, optypea, b, ib+s1, jb, optypeb, 1.0, c, ic, jc, _state); - } - if( optypea!=0&&optypeb!=0 ) - { - ablas_rmatrixgemmrec(m, n, s1, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state); - ablas_rmatrixgemmrec(m, n, s2, alpha, a, ia+s1, ja, optypea, b, ib, jb+s1, optypeb, 1.0, c, ic, jc, _state); - } -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_ablas_rmatrixgemmrec(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state) -{ - return ae_false; -} - - -#endif -#if defined(AE_COMPILE_DLU) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Recurrent complex LU subroutine. -Never call it directly. - - -- ALGLIB routine -- - 04.01.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixluprec(/* Complex */ ae_matrix* a, - ae_int_t offs, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - /* Complex */ ae_vector* tmp, - ae_state *_state) -{ - ae_int_t i; - ae_int_t m1; - ae_int_t m2; - - - if( ae_minint(m, n, _state)<=ablascomplexblocksize(a, _state) ) - { - dlu_cmatrixlup2(a, offs, m, n, pivots, tmp, _state); - return; - } - if( m>n ) - { - cmatrixluprec(a, offs, n, n, pivots, tmp, _state); - for(i=0; i<=n-1; i++) - { - ae_v_cmove(&tmp->ptr.p_complex[0], 1, &a->ptr.pp_complex[offs+n][offs+i], a->stride, "N", ae_v_len(0,m-n-1)); - ae_v_cmove(&a->ptr.pp_complex[offs+n][offs+i], a->stride, &a->ptr.pp_complex[offs+n][pivots->ptr.p_int[offs+i]], a->stride, "N", ae_v_len(offs+n,offs+m-1)); - ae_v_cmove(&a->ptr.pp_complex[offs+n][pivots->ptr.p_int[offs+i]], a->stride, &tmp->ptr.p_complex[0], 1, "N", ae_v_len(offs+n,offs+m-1)); - } - cmatrixrighttrsm(m-n, n, a, offs, offs, ae_true, ae_true, 0, a, offs+n, offs, _state); - return; - } - ablascomplexsplitlength(a, m, &m1, &m2, _state); - cmatrixluprec(a, offs, m1, n, pivots, tmp, _state); - if( m2>0 ) - { - for(i=0; i<=m1-1; i++) - { - if( offs+i!=pivots->ptr.p_int[offs+i] ) - { - ae_v_cmove(&tmp->ptr.p_complex[0], 1, &a->ptr.pp_complex[offs+m1][offs+i], a->stride, "N", ae_v_len(0,m2-1)); - ae_v_cmove(&a->ptr.pp_complex[offs+m1][offs+i], a->stride, &a->ptr.pp_complex[offs+m1][pivots->ptr.p_int[offs+i]], a->stride, "N", ae_v_len(offs+m1,offs+m-1)); - ae_v_cmove(&a->ptr.pp_complex[offs+m1][pivots->ptr.p_int[offs+i]], a->stride, &tmp->ptr.p_complex[0], 1, "N", ae_v_len(offs+m1,offs+m-1)); - } - } - cmatrixrighttrsm(m2, m1, a, offs, offs, ae_true, ae_true, 0, a, offs+m1, offs, _state); - cmatrixgemm(m-m1, n-m1, m1, ae_complex_from_d(-1.0), a, offs+m1, offs, 0, a, offs, offs+m1, 0, ae_complex_from_d(1.0), a, offs+m1, offs+m1, _state); - cmatrixluprec(a, offs+m1, m-m1, n-m1, pivots, tmp, _state); - for(i=0; i<=m2-1; i++) - { - if( offs+m1+i!=pivots->ptr.p_int[offs+m1+i] ) - { - ae_v_cmove(&tmp->ptr.p_complex[0], 1, &a->ptr.pp_complex[offs][offs+m1+i], a->stride, "N", ae_v_len(0,m1-1)); - ae_v_cmove(&a->ptr.pp_complex[offs][offs+m1+i], a->stride, &a->ptr.pp_complex[offs][pivots->ptr.p_int[offs+m1+i]], a->stride, "N", ae_v_len(offs,offs+m1-1)); - ae_v_cmove(&a->ptr.pp_complex[offs][pivots->ptr.p_int[offs+m1+i]], a->stride, &tmp->ptr.p_complex[0], 1, "N", ae_v_len(offs,offs+m1-1)); - } - } - } -} - - -/************************************************************************* -Recurrent real LU subroutine. -Never call it directly. - - -- ALGLIB routine -- - 04.01.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixluprec(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - /* Real */ ae_vector* tmp, - ae_state *_state) -{ - ae_int_t i; - ae_int_t m1; - ae_int_t m2; - - - if( ae_minint(m, n, _state)<=ablasblocksize(a, _state) ) - { - dlu_rmatrixlup2(a, offs, m, n, pivots, tmp, _state); - return; - } - if( m>n ) - { - rmatrixluprec(a, offs, n, n, pivots, tmp, _state); - for(i=0; i<=n-1; i++) - { - if( offs+i!=pivots->ptr.p_int[offs+i] ) - { - ae_v_move(&tmp->ptr.p_double[0], 1, &a->ptr.pp_double[offs+n][offs+i], a->stride, ae_v_len(0,m-n-1)); - ae_v_move(&a->ptr.pp_double[offs+n][offs+i], a->stride, &a->ptr.pp_double[offs+n][pivots->ptr.p_int[offs+i]], a->stride, ae_v_len(offs+n,offs+m-1)); - ae_v_move(&a->ptr.pp_double[offs+n][pivots->ptr.p_int[offs+i]], a->stride, &tmp->ptr.p_double[0], 1, ae_v_len(offs+n,offs+m-1)); - } - } - rmatrixrighttrsm(m-n, n, a, offs, offs, ae_true, ae_true, 0, a, offs+n, offs, _state); - return; - } - ablassplitlength(a, m, &m1, &m2, _state); - rmatrixluprec(a, offs, m1, n, pivots, tmp, _state); - if( m2>0 ) - { - for(i=0; i<=m1-1; i++) - { - if( offs+i!=pivots->ptr.p_int[offs+i] ) - { - ae_v_move(&tmp->ptr.p_double[0], 1, &a->ptr.pp_double[offs+m1][offs+i], a->stride, ae_v_len(0,m2-1)); - ae_v_move(&a->ptr.pp_double[offs+m1][offs+i], a->stride, &a->ptr.pp_double[offs+m1][pivots->ptr.p_int[offs+i]], a->stride, ae_v_len(offs+m1,offs+m-1)); - ae_v_move(&a->ptr.pp_double[offs+m1][pivots->ptr.p_int[offs+i]], a->stride, &tmp->ptr.p_double[0], 1, ae_v_len(offs+m1,offs+m-1)); - } - } - rmatrixrighttrsm(m2, m1, a, offs, offs, ae_true, ae_true, 0, a, offs+m1, offs, _state); - rmatrixgemm(m-m1, n-m1, m1, -1.0, a, offs+m1, offs, 0, a, offs, offs+m1, 0, 1.0, a, offs+m1, offs+m1, _state); - rmatrixluprec(a, offs+m1, m-m1, n-m1, pivots, tmp, _state); - for(i=0; i<=m2-1; i++) - { - if( offs+m1+i!=pivots->ptr.p_int[offs+m1+i] ) - { - ae_v_move(&tmp->ptr.p_double[0], 1, &a->ptr.pp_double[offs][offs+m1+i], a->stride, ae_v_len(0,m1-1)); - ae_v_move(&a->ptr.pp_double[offs][offs+m1+i], a->stride, &a->ptr.pp_double[offs][pivots->ptr.p_int[offs+m1+i]], a->stride, ae_v_len(offs,offs+m1-1)); - ae_v_move(&a->ptr.pp_double[offs][pivots->ptr.p_int[offs+m1+i]], a->stride, &tmp->ptr.p_double[0], 1, ae_v_len(offs,offs+m1-1)); - } - } - } -} - - -/************************************************************************* -Recurrent complex LU subroutine. -Never call it directly. - - -- ALGLIB routine -- - 04.01.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixplurec(/* Complex */ ae_matrix* a, - ae_int_t offs, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - /* Complex */ ae_vector* tmp, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n1; - ae_int_t n2; - ae_int_t tsa; - ae_int_t tsb; - - - tsa = matrixtilesizea(_state)/2; - tsb = matrixtilesizeb(_state); - if( n<=tsa ) - { - dlu_cmatrixplu2(a, offs, m, n, pivots, tmp, _state); - return; - } - if( n>m ) - { - cmatrixplurec(a, offs, m, m, pivots, tmp, _state); - for(i=0; i<=m-1; i++) - { - ae_v_cmove(&tmp->ptr.p_complex[0], 1, &a->ptr.pp_complex[offs+i][offs+m], 1, "N", ae_v_len(0,n-m-1)); - ae_v_cmove(&a->ptr.pp_complex[offs+i][offs+m], 1, &a->ptr.pp_complex[pivots->ptr.p_int[offs+i]][offs+m], 1, "N", ae_v_len(offs+m,offs+n-1)); - ae_v_cmove(&a->ptr.pp_complex[pivots->ptr.p_int[offs+i]][offs+m], 1, &tmp->ptr.p_complex[0], 1, "N", ae_v_len(offs+m,offs+n-1)); - } - cmatrixlefttrsm(m, n-m, a, offs, offs, ae_false, ae_true, 0, a, offs, offs+m, _state); - return; - } - if( n>tsb ) - { - n1 = tsb; - n2 = n-n1; - } - else - { - tiledsplit(n, tsa, &n1, &n2, _state); - } - cmatrixplurec(a, offs, m, n1, pivots, tmp, _state); - if( n2>0 ) - { - for(i=0; i<=n1-1; i++) - { - if( offs+i!=pivots->ptr.p_int[offs+i] ) - { - ae_v_cmove(&tmp->ptr.p_complex[0], 1, &a->ptr.pp_complex[offs+i][offs+n1], 1, "N", ae_v_len(0,n2-1)); - ae_v_cmove(&a->ptr.pp_complex[offs+i][offs+n1], 1, &a->ptr.pp_complex[pivots->ptr.p_int[offs+i]][offs+n1], 1, "N", ae_v_len(offs+n1,offs+n-1)); - ae_v_cmove(&a->ptr.pp_complex[pivots->ptr.p_int[offs+i]][offs+n1], 1, &tmp->ptr.p_complex[0], 1, "N", ae_v_len(offs+n1,offs+n-1)); - } - } - cmatrixlefttrsm(n1, n2, a, offs, offs, ae_false, ae_true, 0, a, offs, offs+n1, _state); - cmatrixgemm(m-n1, n-n1, n1, ae_complex_from_d(-1.0), a, offs+n1, offs, 0, a, offs, offs+n1, 0, ae_complex_from_d(1.0), a, offs+n1, offs+n1, _state); - cmatrixplurec(a, offs+n1, m-n1, n-n1, pivots, tmp, _state); - for(i=0; i<=n2-1; i++) - { - if( offs+n1+i!=pivots->ptr.p_int[offs+n1+i] ) - { - ae_v_cmove(&tmp->ptr.p_complex[0], 1, &a->ptr.pp_complex[offs+n1+i][offs], 1, "N", ae_v_len(0,n1-1)); - ae_v_cmove(&a->ptr.pp_complex[offs+n1+i][offs], 1, &a->ptr.pp_complex[pivots->ptr.p_int[offs+n1+i]][offs], 1, "N", ae_v_len(offs,offs+n1-1)); - ae_v_cmove(&a->ptr.pp_complex[pivots->ptr.p_int[offs+n1+i]][offs], 1, &tmp->ptr.p_complex[0], 1, "N", ae_v_len(offs,offs+n1-1)); - } - } - } -} - - -/************************************************************************* -Recurrent real LU subroutine. -Never call it directly. - - -- ALGLIB routine -- - 04.01.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixplurec(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - /* Real */ ae_vector* tmp, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n1; - ae_int_t n2; - ae_int_t tsa; - ae_int_t tsb; - - - tsa = matrixtilesizea(_state); - tsb = matrixtilesizeb(_state); - if( n<=tsb ) - { - if( rmatrixplumkl(a, offs, m, n, pivots, _state) ) - { - return; - } - } - if( n<=tsa ) - { - dlu_rmatrixplu2(a, offs, m, n, pivots, tmp, _state); - return; - } - if( n>m ) - { - rmatrixplurec(a, offs, m, m, pivots, tmp, _state); - for(i=0; i<=m-1; i++) - { - ae_v_move(&tmp->ptr.p_double[0], 1, &a->ptr.pp_double[offs+i][offs+m], 1, ae_v_len(0,n-m-1)); - ae_v_move(&a->ptr.pp_double[offs+i][offs+m], 1, &a->ptr.pp_double[pivots->ptr.p_int[offs+i]][offs+m], 1, ae_v_len(offs+m,offs+n-1)); - ae_v_move(&a->ptr.pp_double[pivots->ptr.p_int[offs+i]][offs+m], 1, &tmp->ptr.p_double[0], 1, ae_v_len(offs+m,offs+n-1)); - } - rmatrixlefttrsm(m, n-m, a, offs, offs, ae_false, ae_true, 0, a, offs, offs+m, _state); - return; - } - if( n>tsb ) - { - n1 = tsb; - n2 = n-n1; - } - else - { - tiledsplit(n, tsa, &n1, &n2, _state); - } - rmatrixplurec(a, offs, m, n1, pivots, tmp, _state); - if( n2>0 ) - { - for(i=0; i<=n1-1; i++) - { - if( offs+i!=pivots->ptr.p_int[offs+i] ) - { - ae_v_move(&tmp->ptr.p_double[0], 1, &a->ptr.pp_double[offs+i][offs+n1], 1, ae_v_len(0,n2-1)); - ae_v_move(&a->ptr.pp_double[offs+i][offs+n1], 1, &a->ptr.pp_double[pivots->ptr.p_int[offs+i]][offs+n1], 1, ae_v_len(offs+n1,offs+n-1)); - ae_v_move(&a->ptr.pp_double[pivots->ptr.p_int[offs+i]][offs+n1], 1, &tmp->ptr.p_double[0], 1, ae_v_len(offs+n1,offs+n-1)); - } - } - rmatrixlefttrsm(n1, n2, a, offs, offs, ae_false, ae_true, 0, a, offs, offs+n1, _state); - rmatrixgemm(m-n1, n-n1, n1, -1.0, a, offs+n1, offs, 0, a, offs, offs+n1, 0, 1.0, a, offs+n1, offs+n1, _state); - rmatrixplurec(a, offs+n1, m-n1, n-n1, pivots, tmp, _state); - for(i=0; i<=n2-1; i++) - { - if( offs+n1+i!=pivots->ptr.p_int[offs+n1+i] ) - { - ae_v_move(&tmp->ptr.p_double[0], 1, &a->ptr.pp_double[offs+n1+i][offs], 1, ae_v_len(0,n1-1)); - ae_v_move(&a->ptr.pp_double[offs+n1+i][offs], 1, &a->ptr.pp_double[pivots->ptr.p_int[offs+n1+i]][offs], 1, ae_v_len(offs,offs+n1-1)); - ae_v_move(&a->ptr.pp_double[pivots->ptr.p_int[offs+n1+i]][offs], 1, &tmp->ptr.p_double[0], 1, ae_v_len(offs,offs+n1-1)); - } - } - } -} - - -/************************************************************************* -Complex LUP kernel - - -- ALGLIB routine -- - 10.01.2010 - Bochkanov Sergey -*************************************************************************/ -static void dlu_cmatrixlup2(/* Complex */ ae_matrix* a, - ae_int_t offs, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - /* Complex */ ae_vector* tmp, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t jp; - ae_complex s; - - - if( m==0||n==0 ) - { - return; - } - for(j=0; j<=ae_minint(m-1, n-1, _state); j++) - { - jp = j; - for(i=j+1; i<=n-1; i++) - { - if( ae_fp_greater(ae_c_abs(a->ptr.pp_complex[offs+j][offs+i], _state),ae_c_abs(a->ptr.pp_complex[offs+j][offs+jp], _state)) ) - { - jp = i; - } - } - pivots->ptr.p_int[offs+j] = offs+jp; - if( jp!=j ) - { - ae_v_cmove(&tmp->ptr.p_complex[0], 1, &a->ptr.pp_complex[offs][offs+j], a->stride, "N", ae_v_len(0,m-1)); - ae_v_cmove(&a->ptr.pp_complex[offs][offs+j], a->stride, &a->ptr.pp_complex[offs][offs+jp], a->stride, "N", ae_v_len(offs,offs+m-1)); - ae_v_cmove(&a->ptr.pp_complex[offs][offs+jp], a->stride, &tmp->ptr.p_complex[0], 1, "N", ae_v_len(offs,offs+m-1)); - } - if( ae_c_neq_d(a->ptr.pp_complex[offs+j][offs+j],(double)(0))&&j+1<=n-1 ) - { - s = ae_c_d_div(1,a->ptr.pp_complex[offs+j][offs+j]); - ae_v_cmulc(&a->ptr.pp_complex[offs+j][offs+j+1], 1, ae_v_len(offs+j+1,offs+n-1), s); - } - if( jptr.p_complex[0], 1, &a->ptr.pp_complex[offs+j+1][offs+j], a->stride, "N", ae_v_len(0,m-j-2)); - ae_v_cmoveneg(&tmp->ptr.p_complex[m], 1, &a->ptr.pp_complex[offs+j][offs+j+1], 1, "N", ae_v_len(m,m+n-j-2)); - cmatrixrank1(m-j-1, n-j-1, a, offs+j+1, offs+j+1, tmp, 0, tmp, m, _state); - } - } -} - - -/************************************************************************* -Real LUP kernel - - -- ALGLIB routine -- - 10.01.2010 - Bochkanov Sergey -*************************************************************************/ -static void dlu_rmatrixlup2(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - /* Real */ ae_vector* tmp, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t jp; - double s; - - - if( m==0||n==0 ) - { - return; - } - for(j=0; j<=ae_minint(m-1, n-1, _state); j++) - { - jp = j; - for(i=j+1; i<=n-1; i++) - { - if( ae_fp_greater(ae_fabs(a->ptr.pp_double[offs+j][offs+i], _state),ae_fabs(a->ptr.pp_double[offs+j][offs+jp], _state)) ) - { - jp = i; - } - } - pivots->ptr.p_int[offs+j] = offs+jp; - if( jp!=j ) - { - ae_v_move(&tmp->ptr.p_double[0], 1, &a->ptr.pp_double[offs][offs+j], a->stride, ae_v_len(0,m-1)); - ae_v_move(&a->ptr.pp_double[offs][offs+j], a->stride, &a->ptr.pp_double[offs][offs+jp], a->stride, ae_v_len(offs,offs+m-1)); - ae_v_move(&a->ptr.pp_double[offs][offs+jp], a->stride, &tmp->ptr.p_double[0], 1, ae_v_len(offs,offs+m-1)); - } - if( ae_fp_neq(a->ptr.pp_double[offs+j][offs+j],(double)(0))&&j+1<=n-1 ) - { - s = 1/a->ptr.pp_double[offs+j][offs+j]; - ae_v_muld(&a->ptr.pp_double[offs+j][offs+j+1], 1, ae_v_len(offs+j+1,offs+n-1), s); - } - if( jptr.p_double[0], 1, &a->ptr.pp_double[offs+j+1][offs+j], a->stride, ae_v_len(0,m-j-2)); - ae_v_moveneg(&tmp->ptr.p_double[m], 1, &a->ptr.pp_double[offs+j][offs+j+1], 1, ae_v_len(m,m+n-j-2)); - rmatrixrank1(m-j-1, n-j-1, a, offs+j+1, offs+j+1, tmp, 0, tmp, m, _state); - } - } -} - - -/************************************************************************* -Complex PLU kernel - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - June 30, 1992 -*************************************************************************/ -static void dlu_cmatrixplu2(/* Complex */ ae_matrix* a, - ae_int_t offs, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - /* Complex */ ae_vector* tmp, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t jp; - ae_complex s; - - - if( m==0||n==0 ) - { - return; - } - for(j=0; j<=ae_minint(m-1, n-1, _state); j++) - { - jp = j; - for(i=j+1; i<=m-1; i++) - { - if( ae_fp_greater(ae_c_abs(a->ptr.pp_complex[offs+i][offs+j], _state),ae_c_abs(a->ptr.pp_complex[offs+jp][offs+j], _state)) ) - { - jp = i; - } - } - pivots->ptr.p_int[offs+j] = offs+jp; - if( ae_c_neq_d(a->ptr.pp_complex[offs+jp][offs+j],(double)(0)) ) - { - if( jp!=j ) - { - for(i=0; i<=n-1; i++) - { - s = a->ptr.pp_complex[offs+j][offs+i]; - a->ptr.pp_complex[offs+j][offs+i] = a->ptr.pp_complex[offs+jp][offs+i]; - a->ptr.pp_complex[offs+jp][offs+i] = s; - } - } - if( j+1<=m-1 ) - { - s = ae_c_d_div(1,a->ptr.pp_complex[offs+j][offs+j]); - ae_v_cmulc(&a->ptr.pp_complex[offs+j+1][offs+j], a->stride, ae_v_len(offs+j+1,offs+m-1), s); - } - } - if( jptr.p_complex[0], 1, &a->ptr.pp_complex[offs+j+1][offs+j], a->stride, "N", ae_v_len(0,m-j-2)); - ae_v_cmoveneg(&tmp->ptr.p_complex[m], 1, &a->ptr.pp_complex[offs+j][offs+j+1], 1, "N", ae_v_len(m,m+n-j-2)); - cmatrixrank1(m-j-1, n-j-1, a, offs+j+1, offs+j+1, tmp, 0, tmp, m, _state); - } - } -} - - -/************************************************************************* -Real PLU kernel - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - June 30, 1992 -*************************************************************************/ -static void dlu_rmatrixplu2(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - /* Real */ ae_vector* tmp, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t jp; - double s; - - - if( m==0||n==0 ) - { - return; - } - for(j=0; j<=ae_minint(m-1, n-1, _state); j++) - { - jp = j; - for(i=j+1; i<=m-1; i++) - { - if( ae_fp_greater(ae_fabs(a->ptr.pp_double[offs+i][offs+j], _state),ae_fabs(a->ptr.pp_double[offs+jp][offs+j], _state)) ) - { - jp = i; - } - } - pivots->ptr.p_int[offs+j] = offs+jp; - if( ae_fp_neq(a->ptr.pp_double[offs+jp][offs+j],(double)(0)) ) - { - if( jp!=j ) - { - for(i=0; i<=n-1; i++) - { - s = a->ptr.pp_double[offs+j][offs+i]; - a->ptr.pp_double[offs+j][offs+i] = a->ptr.pp_double[offs+jp][offs+i]; - a->ptr.pp_double[offs+jp][offs+i] = s; - } - } - if( j+1<=m-1 ) - { - s = 1/a->ptr.pp_double[offs+j][offs+j]; - ae_v_muld(&a->ptr.pp_double[offs+j+1][offs+j], a->stride, ae_v_len(offs+j+1,offs+m-1), s); - } - } - if( jptr.p_double[0], 1, &a->ptr.pp_double[offs+j+1][offs+j], a->stride, ae_v_len(0,m-j-2)); - ae_v_moveneg(&tmp->ptr.p_double[m], 1, &a->ptr.pp_double[offs+j][offs+j+1], 1, ae_v_len(m,m+n-j-2)); - rmatrixrank1(m-j-1, n-j-1, a, offs+j+1, offs+j+1, tmp, 0, tmp, m, _state); - } - } -} - - -#endif -#if defined(AE_COMPILE_SPTRF) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Sparse LU for square NxN CRS matrix with both row and column permutations. - -Represents A as Pr*L*U*Pc, where: -* Pr is a product of row permutations Pr=Pr(0)*Pr(1)*...*Pr(n-2)*Pr(n-1) -* Pc is a product of col permutations Pc=Pc(n-1)*Pc(n-2)*...*Pc(1)*Pc(0) -* L is lower unitriangular -* U is upper triangular - -INPUT PARAMETERS: - A - sparse square matrix in CRS format - PivotType - pivot type: - * 0 - for best pivoting available - * 1 - row-only pivoting - * 2 - row and column greedy pivoting algorithm (most - sparse pivot column is selected from the trailing - matrix at each step) - Buf - temporary buffer, previously allocated memory is - reused as much as possible - -OUTPUT PARAMETERS: - A - LU decomposition of A - PR - array[N], row pivots - PC - array[N], column pivots - Buf - following fields of Buf are set: - * Buf.RowPermRawIdx[] - contains row permutation, with - RawIdx[I]=J meaning that J-th row of the original - input matrix was moved to Ith position of the output - factorization - -This function always succeeds i.e. it ALWAYS returns valid factorization, -but for your convenience it also returns boolean value which helps to -detect symbolically degenerate matrix: -* function returns TRUE if the matrix was factorized AND symbolically - non-degenerate -* function returns FALSE if the matrix was factorized but U has strictly - zero elements at the diagonal (the factorization is returned anyway). - - -- ALGLIB routine -- - 15.01.2019 - Bochkanov Sergey -*************************************************************************/ -ae_bool sptrflu(sparsematrix* a, - ae_int_t pivottype, - /* Integer */ ae_vector* pr, - /* Integer */ ae_vector* pc, - sluv2buffer* buf, - ae_state *_state) -{ - ae_int_t n; - ae_int_t k; - ae_int_t i; - ae_int_t j; - ae_int_t jp; - ae_int_t i0; - ae_int_t i1; - ae_int_t ibest; - ae_int_t jbest; - double v; - double v0; - ae_int_t nz0; - ae_int_t nz1; - double uu; - ae_int_t offs; - ae_int_t tmpndense; - ae_bool densificationsupported; - ae_int_t densifyabove; - ae_bool result; - - - ae_assert(sparseiscrs(a, _state), "SparseLU: A is not stored in CRS format", _state); - ae_assert(sparsegetnrows(a, _state)==sparsegetncols(a, _state), "SparseLU: non-square A", _state); - ae_assert((pivottype==0||pivottype==1)||pivottype==2, "SparseLU: unexpected pivot type", _state); - result = ae_true; - n = sparsegetnrows(a, _state); - if( pivottype==0 ) - { - pivottype = 2; - } - densificationsupported = pivottype==2; - - /* - * - */ - buf->n = n; - ivectorsetlengthatleast(&buf->rowpermrawidx, n, _state); - for(i=0; i<=n-1; i++) - { - buf->rowpermrawidx.ptr.p_int[i] = i; - } - - /* - * Allocate storage for sparse L and U factors - * - * NOTE: SparseMatrix structure for these factors is only - * partially initialized; we use it just as a temporary - * storage and do not intend to use facilities of the - * 'sparse' subpackage to work with these objects. - */ - buf->sparsel.matrixtype = 1; - buf->sparsel.m = n; - buf->sparsel.n = n; - ivectorsetlengthatleast(&buf->sparsel.ridx, n+1, _state); - buf->sparsel.ridx.ptr.p_int[0] = 0; - buf->sparseut.matrixtype = 1; - buf->sparseut.m = n; - buf->sparseut.n = n; - ivectorsetlengthatleast(&buf->sparseut.ridx, n+1, _state); - buf->sparseut.ridx.ptr.p_int[0] = 0; - - /* - * Allocate unprocessed yet part of the matrix, - * two submatrices: - * * BU, upper J rows of columns [J,N), upper submatrix - * * BL, left J cols of rows [J,N), left submatrix - * * B1, (N-J)*(N-J) square submatrix - */ - sptrf_sluv2list1init(n, &buf->bleft, _state); - sptrf_sluv2list1init(n, &buf->bupper, _state); - ivectorsetlengthatleast(pr, n, _state); - ivectorsetlengthatleast(pc, n, _state); - ivectorsetlengthatleast(&buf->v0i, n, _state); - ivectorsetlengthatleast(&buf->v1i, n, _state); - rvectorsetlengthatleast(&buf->v0r, n, _state); - rvectorsetlengthatleast(&buf->v1r, n, _state); - sptrf_sparsetrailinit(a, &buf->strail, _state); - - /* - * Prepare dense trail, initial densification - */ - sptrf_densetrailinit(&buf->dtrail, n, _state); - densifyabove = ae_round(sptrf_densebnd*n, _state)+1; - if( densificationsupported ) - { - for(i=0; i<=n-1; i++) - { - if( buf->strail.nzc.ptr.p_int[i]>densifyabove ) - { - sptrf_sparsetraildensify(&buf->strail, i, &buf->bupper, &buf->dtrail, _state); - } - } - } - - /* - * Process sparse part - */ - for(k=0; k<=n-1; k++) - { - - /* - * Find pivot column and pivot row - */ - if( !sptrf_sparsetrailfindpivot(&buf->strail, pivottype, &ibest, &jbest, _state) ) - { - - /* - * Only densified columns are left, break sparse iteration - */ - ae_assert(buf->dtrail.ndense+k==n, "SPTRF: integrity check failed (35741)", _state); - break; - } - pc->ptr.p_int[k] = jbest; - pr->ptr.p_int[k] = ibest; - j = buf->rowpermrawidx.ptr.p_int[k]; - buf->rowpermrawidx.ptr.p_int[k] = buf->rowpermrawidx.ptr.p_int[ibest]; - buf->rowpermrawidx.ptr.p_int[ibest] = j; - - /* - * Apply pivoting to BL and BU - */ - sptrf_sluv2list1swap(&buf->bleft, k, ibest, _state); - sptrf_sluv2list1swap(&buf->bupper, k, jbest, _state); - - /* - * Apply pivoting to sparse trail, pivot out - */ - sptrf_sparsetrailpivotout(&buf->strail, ibest, jbest, &uu, &buf->v0i, &buf->v0r, &nz0, &buf->v1i, &buf->v1r, &nz1, _state); - result = result&&uu!=0; - - /* - * Pivot dense trail - */ - tmpndense = buf->dtrail.ndense; - for(i=0; i<=tmpndense-1; i++) - { - v = buf->dtrail.d.ptr.pp_double[k][i]; - buf->dtrail.d.ptr.pp_double[k][i] = buf->dtrail.d.ptr.pp_double[ibest][i]; - buf->dtrail.d.ptr.pp_double[ibest][i] = v; - } - - /* - * Output to LU matrix - */ - sptrf_sluv2list1appendsequencetomatrix(&buf->bupper, k, ae_true, uu, n, &buf->sparseut, k, _state); - sptrf_sluv2list1appendsequencetomatrix(&buf->bleft, k, ae_false, 0.0, n, &buf->sparsel, k, _state); - - /* - * Extract K-th col/row of B1, generate K-th col/row of BL/BU, update NZC - */ - sptrf_sluv2list1pushsparsevector(&buf->bleft, &buf->v0i, &buf->v0r, nz0, _state); - sptrf_sluv2list1pushsparsevector(&buf->bupper, &buf->v1i, &buf->v1r, nz1, _state); - - /* - * Update the rest of the matrix - */ - if( nz0*(nz1+buf->dtrail.ndense)>0 ) - { - - /* - * Update dense trail - * - * NOTE: this update MUST be performed before we update sparse trail, - * because sparse update may move columns to dense storage after - * update is performed on them. Thus, we have to avoid applying - * same update twice. - */ - if( buf->dtrail.ndense>0 ) - { - tmpndense = buf->dtrail.ndense; - for(i=0; i<=nz0-1; i++) - { - i0 = buf->v0i.ptr.p_int[i]; - v0 = buf->v0r.ptr.p_double[i]; - for(j=0; j<=tmpndense-1; j++) - { - buf->dtrail.d.ptr.pp_double[i0][j] = buf->dtrail.d.ptr.pp_double[i0][j]-v0*buf->dtrail.d.ptr.pp_double[k][j]; - } - } - } - - /* - * Update sparse trail - */ - sptrf_sparsetrailupdate(&buf->strail, &buf->v0i, &buf->v0r, nz0, &buf->v1i, &buf->v1r, nz1, &buf->bupper, &buf->dtrail, densificationsupported, _state); - } - } - - /* - * Process densified trail - */ - if( buf->dtrail.ndense>0 ) - { - tmpndense = buf->dtrail.ndense; - - /* - * Generate column pivots to bring actual order of columns in the - * working part of the matrix to one used for dense storage - */ - for(i=n-tmpndense; i<=n-1; i++) - { - k = buf->dtrail.did.ptr.p_int[i-(n-tmpndense)]; - jp = -1; - for(j=i; j<=n-1; j++) - { - if( buf->strail.colid.ptr.p_int[j]==k ) - { - jp = j; - break; - } - } - ae_assert(jp>=0, "SPTRF: integrity check failed during reordering", _state); - k = buf->strail.colid.ptr.p_int[i]; - buf->strail.colid.ptr.p_int[i] = buf->strail.colid.ptr.p_int[jp]; - buf->strail.colid.ptr.p_int[jp] = k; - pc->ptr.p_int[i] = jp; - } - - /* - * Perform dense LU decomposition on dense trail - */ - rmatrixsetlengthatleast(&buf->dbuf, buf->dtrail.ndense, buf->dtrail.ndense, _state); - for(i=0; i<=tmpndense-1; i++) - { - for(j=0; j<=tmpndense-1; j++) - { - buf->dbuf.ptr.pp_double[i][j] = buf->dtrail.d.ptr.pp_double[i+(n-tmpndense)][j]; - } - } - rvectorsetlengthatleast(&buf->tmp0, 2*n, _state); - ivectorsetlengthatleast(&buf->tmpp, n, _state); - rmatrixplurec(&buf->dbuf, 0, tmpndense, tmpndense, &buf->tmpp, &buf->tmp0, _state); - - /* - * Convert indexes of rows pivots, swap elements of BLeft - */ - for(i=0; i<=tmpndense-1; i++) - { - pr->ptr.p_int[i+(n-tmpndense)] = buf->tmpp.ptr.p_int[i]+(n-tmpndense); - sptrf_sluv2list1swap(&buf->bleft, i+(n-tmpndense), pr->ptr.p_int[i+(n-tmpndense)], _state); - j = buf->rowpermrawidx.ptr.p_int[i+(n-tmpndense)]; - buf->rowpermrawidx.ptr.p_int[i+(n-tmpndense)] = buf->rowpermrawidx.ptr.p_int[pr->ptr.p_int[i+(n-tmpndense)]]; - buf->rowpermrawidx.ptr.p_int[pr->ptr.p_int[i+(n-tmpndense)]] = j; - } - - /* - * Convert U-factor - */ - ivectorgrowto(&buf->sparseut.idx, buf->sparseut.ridx.ptr.p_int[n-tmpndense]+n*tmpndense, _state); - rvectorgrowto(&buf->sparseut.vals, buf->sparseut.ridx.ptr.p_int[n-tmpndense]+n*tmpndense, _state); - for(j=0; j<=tmpndense-1; j++) - { - offs = buf->sparseut.ridx.ptr.p_int[j+(n-tmpndense)]; - k = n-tmpndense; - - /* - * Convert leading N-NDense columns - */ - for(i=0; i<=k-1; i++) - { - v = buf->dtrail.d.ptr.pp_double[i][j]; - if( v!=0 ) - { - buf->sparseut.idx.ptr.p_int[offs] = i; - buf->sparseut.vals.ptr.p_double[offs] = v; - offs = offs+1; - } - } - - /* - * Convert upper diagonal elements - */ - for(i=0; i<=j-1; i++) - { - v = buf->dbuf.ptr.pp_double[i][j]; - if( v!=0 ) - { - buf->sparseut.idx.ptr.p_int[offs] = i+(n-tmpndense); - buf->sparseut.vals.ptr.p_double[offs] = v; - offs = offs+1; - } - } - - /* - * Convert diagonal element (always stored) - */ - v = buf->dbuf.ptr.pp_double[j][j]; - buf->sparseut.idx.ptr.p_int[offs] = j+(n-tmpndense); - buf->sparseut.vals.ptr.p_double[offs] = v; - offs = offs+1; - result = result&&v!=0; - - /* - * Column is done - */ - buf->sparseut.ridx.ptr.p_int[j+(n-tmpndense)+1] = offs; - } - - /* - * Convert L-factor - */ - ivectorgrowto(&buf->sparsel.idx, buf->sparsel.ridx.ptr.p_int[n-tmpndense]+n*tmpndense, _state); - rvectorgrowto(&buf->sparsel.vals, buf->sparsel.ridx.ptr.p_int[n-tmpndense]+n*tmpndense, _state); - for(i=0; i<=tmpndense-1; i++) - { - sptrf_sluv2list1appendsequencetomatrix(&buf->bleft, i+(n-tmpndense), ae_false, 0.0, n, &buf->sparsel, i+(n-tmpndense), _state); - offs = buf->sparsel.ridx.ptr.p_int[i+(n-tmpndense)+1]; - for(j=0; j<=i-1; j++) - { - v = buf->dbuf.ptr.pp_double[i][j]; - if( v!=0 ) - { - buf->sparsel.idx.ptr.p_int[offs] = j+(n-tmpndense); - buf->sparsel.vals.ptr.p_double[offs] = v; - offs = offs+1; - } - } - buf->sparsel.ridx.ptr.p_int[i+(n-tmpndense)+1] = offs; - } - } - - /* - * Allocate output - */ - ivectorsetlengthatleast(&buf->tmpi, n, _state); - for(i=0; i<=n-1; i++) - { - buf->tmpi.ptr.p_int[i] = buf->sparsel.ridx.ptr.p_int[i+1]-buf->sparsel.ridx.ptr.p_int[i]; - } - for(i=0; i<=n-1; i++) - { - i0 = buf->sparseut.ridx.ptr.p_int[i]; - i1 = buf->sparseut.ridx.ptr.p_int[i+1]-1; - for(j=i0; j<=i1; j++) - { - k = buf->sparseut.idx.ptr.p_int[j]; - buf->tmpi.ptr.p_int[k] = buf->tmpi.ptr.p_int[k]+1; - } - } - a->matrixtype = 1; - a->ninitialized = buf->sparsel.ridx.ptr.p_int[n]+buf->sparseut.ridx.ptr.p_int[n]; - a->m = n; - a->n = n; - ivectorsetlengthatleast(&a->ridx, n+1, _state); - ivectorsetlengthatleast(&a->idx, a->ninitialized, _state); - rvectorsetlengthatleast(&a->vals, a->ninitialized, _state); - a->ridx.ptr.p_int[0] = 0; - for(i=0; i<=n-1; i++) - { - a->ridx.ptr.p_int[i+1] = a->ridx.ptr.p_int[i]+buf->tmpi.ptr.p_int[i]; - } - for(i=0; i<=n-1; i++) - { - i0 = buf->sparsel.ridx.ptr.p_int[i]; - i1 = buf->sparsel.ridx.ptr.p_int[i+1]-1; - jp = a->ridx.ptr.p_int[i]; - for(j=i0; j<=i1; j++) - { - a->idx.ptr.p_int[jp+(j-i0)] = buf->sparsel.idx.ptr.p_int[j]; - a->vals.ptr.p_double[jp+(j-i0)] = buf->sparsel.vals.ptr.p_double[j]; - } - buf->tmpi.ptr.p_int[i] = buf->sparsel.ridx.ptr.p_int[i+1]-buf->sparsel.ridx.ptr.p_int[i]; - } - ivectorsetlengthatleast(&a->didx, n, _state); - ivectorsetlengthatleast(&a->uidx, n, _state); - for(i=0; i<=n-1; i++) - { - a->didx.ptr.p_int[i] = a->ridx.ptr.p_int[i]+buf->tmpi.ptr.p_int[i]; - a->uidx.ptr.p_int[i] = a->didx.ptr.p_int[i]+1; - buf->tmpi.ptr.p_int[i] = a->didx.ptr.p_int[i]; - } - for(i=0; i<=n-1; i++) - { - i0 = buf->sparseut.ridx.ptr.p_int[i]; - i1 = buf->sparseut.ridx.ptr.p_int[i+1]-1; - for(j=i0; j<=i1; j++) - { - k = buf->sparseut.idx.ptr.p_int[j]; - offs = buf->tmpi.ptr.p_int[k]; - a->idx.ptr.p_int[offs] = i; - a->vals.ptr.p_double[offs] = buf->sparseut.vals.ptr.p_double[j]; - buf->tmpi.ptr.p_int[k] = offs+1; - } - } - return result; -} - - -/************************************************************************* -This function initialized rectangular submatrix structure. - -After initialization this structure stores matrix[N,0], which contains N -rows (sequences), stored as single-linked lists. - - -- ALGLIB routine -- - 15.01.2019 - Bochkanov Sergey -*************************************************************************/ -static void sptrf_sluv2list1init(ae_int_t n, - sluv2list1matrix* a, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(n>=1, "SLUV2List1Init: N<1", _state); - a->nfixed = n; - a->ndynamic = 0; - a->nallocated = n; - a->nused = 0; - ivectorgrowto(&a->idxfirst, n, _state); - ivectorgrowto(&a->strgidx, 2*a->nallocated, _state); - rvectorgrowto(&a->strgval, a->nallocated, _state); - for(i=0; i<=n-1; i++) - { - a->idxfirst.ptr.p_int[i] = -1; - } -} - - -/************************************************************************* -This function swaps sequences #I and #J stored by the structure - - -- ALGLIB routine -- - 15.01.2019 - Bochkanov Sergey -*************************************************************************/ -static void sptrf_sluv2list1swap(sluv2list1matrix* a, - ae_int_t i, - ae_int_t j, - ae_state *_state) -{ - ae_int_t k; - - - k = a->idxfirst.ptr.p_int[i]; - a->idxfirst.ptr.p_int[i] = a->idxfirst.ptr.p_int[j]; - a->idxfirst.ptr.p_int[j] = k; -} - - -/************************************************************************* -This function drops sequence #I from the structure - - -- ALGLIB routine -- - 15.01.2019 - Bochkanov Sergey -*************************************************************************/ -static void sptrf_sluv2list1dropsequence(sluv2list1matrix* a, - ae_int_t i, - ae_state *_state) -{ - - - a->idxfirst.ptr.p_int[i] = -1; -} - - -/************************************************************************* -This function appends sequence from the structure to the sparse matrix. - -It is assumed that S is a lower triangular matrix, and A stores strictly -lower triangular elements (no diagonal ones!). You can explicitly control -whether you want to add diagonal elements or not. - -Output matrix is assumed to be stored in CRS format and to be partially -initialized (up to, but not including, Dst-th row). DIdx and UIdx are NOT -updated by this function as well as NInitialized. - -INPUT PARAMETERS: - A - rectangular matrix structure - Src - sequence (row or column) index in the structure - HasDiagonal - whether we want to add diagonal element - D - diagonal element, if HasDiagonal=True - NZMAX - maximum estimated number of non-zeros in the row, - this function will preallocate storage in the output - matrix. - S - destination matrix in CRS format, partially initialized - Dst - destination row index - - - -- ALGLIB routine -- - 15.01.2019 - Bochkanov Sergey -*************************************************************************/ -static void sptrf_sluv2list1appendsequencetomatrix(sluv2list1matrix* a, - ae_int_t src, - ae_bool hasdiagonal, - double d, - ae_int_t nzmax, - sparsematrix* s, - ae_int_t dst, - ae_state *_state) -{ - ae_int_t i; - ae_int_t i0; - ae_int_t i1; - ae_int_t jp; - ae_int_t nnz; - - - i0 = s->ridx.ptr.p_int[dst]; - ivectorgrowto(&s->idx, i0+nzmax, _state); - rvectorgrowto(&s->vals, i0+nzmax, _state); - if( hasdiagonal ) - { - i1 = i0+nzmax-1; - s->idx.ptr.p_int[i1] = dst; - s->vals.ptr.p_double[i1] = d; - nnz = 1; - } - else - { - i1 = i0+nzmax; - nnz = 0; - } - jp = a->idxfirst.ptr.p_int[src]; - while(jp>=0) - { - i1 = i1-1; - s->idx.ptr.p_int[i1] = a->strgidx.ptr.p_int[2*jp+1]; - s->vals.ptr.p_double[i1] = a->strgval.ptr.p_double[jp]; - nnz = nnz+1; - jp = a->strgidx.ptr.p_int[2*jp+0]; - } - for(i=0; i<=nnz-1; i++) - { - s->idx.ptr.p_int[i0+i] = s->idx.ptr.p_int[i1+i]; - s->vals.ptr.p_double[i0+i] = s->vals.ptr.p_double[i1+i]; - } - s->ridx.ptr.p_int[dst+1] = s->ridx.ptr.p_int[dst]+nnz; -} - - -/************************************************************************* -This function appends sparse column to the matrix, increasing its size -from [N,K] to [N,K+1] - - -- ALGLIB routine -- - 15.01.2019 - Bochkanov Sergey -*************************************************************************/ -static void sptrf_sluv2list1pushsparsevector(sluv2list1matrix* a, - /* Integer */ ae_vector* si, - /* Real */ ae_vector* sv, - ae_int_t nz, - ae_state *_state) -{ - ae_int_t idx; - ae_int_t i; - ae_int_t k; - ae_int_t nused; - double v; - - - - /* - * Fetch matrix size, increase - */ - k = a->ndynamic; - ae_assert(knfixed, "Assertion failed", _state); - a->ndynamic = k+1; - - /* - * Allocate new storage if needed - */ - nused = a->nused; - a->nallocated = ae_maxint(a->nallocated, nused+nz, _state); - ivectorgrowto(&a->strgidx, 2*a->nallocated, _state); - rvectorgrowto(&a->strgval, a->nallocated, _state); - - /* - * Append to list - */ - for(idx=0; idx<=nz-1; idx++) - { - i = si->ptr.p_int[idx]; - v = sv->ptr.p_double[idx]; - a->strgidx.ptr.p_int[2*nused+0] = a->idxfirst.ptr.p_int[i]; - a->strgidx.ptr.p_int[2*nused+1] = k; - a->strgval.ptr.p_double[nused] = v; - a->idxfirst.ptr.p_int[i] = nused; - nused = nused+1; - } - a->nused = nused; -} - - -/************************************************************************* -This function initializes dense trail, by default it is matrix[N,0] - - -- ALGLIB routine -- - 15.01.2019 - Bochkanov Sergey -*************************************************************************/ -static void sptrf_densetrailinit(sluv2densetrail* d, - ae_int_t n, - ae_state *_state) -{ - ae_int_t excessivesize; - - - - /* - * Note: excessive rows are allocated to accomodate for situation when - * this buffer is used to solve successive problems with increasing - * sizes. - */ - excessivesize = ae_maxint(ae_round(1.333*n, _state), n, _state); - d->n = n; - d->ndense = 0; - ivectorsetlengthatleast(&d->did, n, _state); - if( d->d.rows<=excessivesize ) - { - rmatrixsetlengthatleast(&d->d, n, 1, _state); - } - else - { - ae_matrix_set_length(&d->d, excessivesize, 1, _state); - } -} - - -/************************************************************************* -This function appends column with id=ID to the dense trail (column IDs are -integer numbers in [0,N) which can be used to track column permutations). - - -- ALGLIB routine -- - 15.01.2019 - Bochkanov Sergey -*************************************************************************/ -static void sptrf_densetrailappendcolumn(sluv2densetrail* d, - /* Real */ ae_vector* x, - ae_int_t id, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_int_t targetidx; - - - n = d->n; - - /* - * Reallocate storage - */ - rmatrixgrowcolsto(&d->d, d->ndense+1, n, _state); - - /* - * Copy to dense storage: - * * BUpper - * * BTrail - * Remove from sparse storage - */ - targetidx = d->ndense; - for(i=0; i<=n-1; i++) - { - d->d.ptr.pp_double[i][targetidx] = x->ptr.p_double[i]; - } - d->did.ptr.p_int[targetidx] = id; - d->ndense = targetidx+1; -} - - -/************************************************************************* -This function initializes sparse trail from the sparse matrix. By default, -sparse trail spans columns and rows in [0,N) range. Subsequent pivoting -out of rows/columns changes its range to [K,N), [K+1,N) and so on. - - -- ALGLIB routine -- - 15.01.2019 - Bochkanov Sergey -*************************************************************************/ -static void sptrf_sparsetrailinit(sparsematrix* s, - sluv2sparsetrail* a, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t n; - ae_int_t j0; - ae_int_t j1; - ae_int_t jj; - ae_int_t p; - ae_int_t slsused; - - - ae_assert(s->m==s->n, "SparseTrailInit: M<>N", _state); - ae_assert(s->matrixtype==1, "SparseTrailInit: non-CRS input", _state); - n = s->n; - a->n = s->n; - a->k = 0; - ivectorsetlengthatleast(&a->nzc, n, _state); - ivectorsetlengthatleast(&a->colid, n, _state); - rvectorsetlengthatleast(&a->tmp0, n, _state); - for(i=0; i<=n-1; i++) - { - a->colid.ptr.p_int[i] = i; - } - bvectorsetlengthatleast(&a->isdensified, n, _state); - for(i=0; i<=n-1; i++) - { - a->isdensified.ptr.p_bool[i] = ae_false; - } - - /* - * Working set of columns - */ - a->maxwrkcnt = iboundval(ae_round(1+(double)n/(double)3, _state), 1, ae_minint(n, 50, _state), _state); - a->wrkcnt = 0; - ivectorsetlengthatleast(&a->wrkset, a->maxwrkcnt, _state); - - /* - * Sparse linked storage (SLS). Store CRS matrix to SLS format, - * row by row, starting from the last one. - */ - ivectorsetlengthatleast(&a->slscolptr, n, _state); - ivectorsetlengthatleast(&a->slsrowptr, n, _state); - ivectorsetlengthatleast(&a->slsidx, s->ridx.ptr.p_int[n]*sptrf_slswidth, _state); - rvectorsetlengthatleast(&a->slsval, s->ridx.ptr.p_int[n], _state); - for(i=0; i<=n-1; i++) - { - a->nzc.ptr.p_int[i] = 0; - } - for(i=0; i<=n-1; i++) - { - a->slscolptr.ptr.p_int[i] = -1; - a->slsrowptr.ptr.p_int[i] = -1; - } - slsused = 0; - for(i=n-1; i>=0; i--) - { - j0 = s->ridx.ptr.p_int[i]; - j1 = s->ridx.ptr.p_int[i+1]-1; - for(jj=j1; jj>=j0; jj--) - { - j = s->idx.ptr.p_int[jj]; - - /* - * Update non-zero counts for columns - */ - a->nzc.ptr.p_int[j] = a->nzc.ptr.p_int[j]+1; - - /* - * Insert into column list - */ - p = a->slscolptr.ptr.p_int[j]; - if( p>=0 ) - { - a->slsidx.ptr.p_int[p*sptrf_slswidth+0] = slsused; - } - a->slsidx.ptr.p_int[slsused*sptrf_slswidth+0] = -1; - a->slsidx.ptr.p_int[slsused*sptrf_slswidth+1] = p; - a->slscolptr.ptr.p_int[j] = slsused; - - /* - * Insert into row list - */ - p = a->slsrowptr.ptr.p_int[i]; - if( p>=0 ) - { - a->slsidx.ptr.p_int[p*sptrf_slswidth+2] = slsused; - } - a->slsidx.ptr.p_int[slsused*sptrf_slswidth+2] = -1; - a->slsidx.ptr.p_int[slsused*sptrf_slswidth+3] = p; - a->slsrowptr.ptr.p_int[i] = slsused; - - /* - * Store index and value - */ - a->slsidx.ptr.p_int[slsused*sptrf_slswidth+4] = i; - a->slsidx.ptr.p_int[slsused*sptrf_slswidth+5] = j; - a->slsval.ptr.p_double[slsused] = s->vals.ptr.p_double[jj]; - slsused = slsused+1; - } - } - a->slsused = slsused; -} - - -/************************************************************************* -This function searches for a appropriate pivot column/row. - -If there exists non-densified column, it returns indexes of pivot column -and row, with most sparse column selected for column pivoting, and largest -element selected for row pivoting. Function result is True. - -PivotType=1 means that no column pivoting is performed -PivotType=2 means that both column and row pivoting are supported - -If all columns were densified, False is returned. - - -- ALGLIB routine -- - 15.01.2019 - Bochkanov Sergey -*************************************************************************/ -static ae_bool sptrf_sparsetrailfindpivot(sluv2sparsetrail* a, - ae_int_t pivottype, - ae_int_t* ipiv, - ae_int_t* jpiv, - ae_state *_state) -{ - ae_int_t n; - ae_int_t k; - ae_int_t j; - ae_int_t jp; - ae_int_t entry; - ae_int_t nz; - ae_int_t maxwrknz; - ae_int_t nnzbest; - double s; - double bbest; - ae_int_t wrk0; - ae_int_t wrk1; - ae_bool result; - - *ipiv = 0; - *jpiv = 0; - - n = a->n; - k = a->k; - nnzbest = n+1; - *jpiv = -1; - *ipiv = -1; - result = ae_true; - - /* - * Select pivot column - */ - if( pivottype==1 ) - { - - /* - * No column pivoting - */ - ae_assert(!a->isdensified.ptr.p_bool[k], "SparseTrailFindPivot: integrity check failed", _state); - *jpiv = k; - } - else - { - - /* - * Find pivot column - */ - for(;;) - { - - /* - * Scan working set (if non-empty) for good columns - */ - maxwrknz = a->maxwrknz; - for(j=0; j<=a->wrkcnt-1; j++) - { - jp = a->wrkset.ptr.p_int[j]; - if( jpisdensified.ptr.p_bool[jp] ) - { - continue; - } - nz = a->nzc.ptr.p_int[jp]; - if( nz>maxwrknz ) - { - continue; - } - if( *jpiv<0||nz=0 ) - { - break; - } - - /* - * Well, nothing found. Recompute working set: - * * determine most sparse unprocessed yet column - * * gather all columns with density in [Wrk0,Wrk1) range, - * increase range, repeat, until working set is full - */ - a->wrkcnt = 0; - a->maxwrknz = 0; - wrk0 = n+1; - for(jp=k; jp<=n-1; jp++) - { - if( !a->isdensified.ptr.p_bool[jp]&&a->nzc.ptr.p_int[jp]nzc.ptr.p_int[jp]; - } - } - if( wrk0>n ) - { - - /* - * Only densified columns are present, exit. - */ - result = ae_false; - return result; - } - wrk1 = wrk0+1; - while(a->wrkcntmaxwrkcnt&&wrk0<=n) - { - - /* - * Find columns with non-zero count in [Wrk0,Wrk1) range - */ - for(jp=k; jp<=n-1; jp++) - { - if( a->wrkcnt==a->maxwrkcnt ) - { - break; - } - if( a->isdensified.ptr.p_bool[jp] ) - { - continue; - } - if( a->nzc.ptr.p_int[jp]>=wrk0&&a->nzc.ptr.p_int[jp]wrkset.ptr.p_int[a->wrkcnt] = jp; - a->wrkcnt = a->wrkcnt+1; - a->maxwrknz = ae_maxint(a->maxwrknz, a->nzc.ptr.p_int[jp], _state); - } - } - - /* - * Advance scan range - */ - jp = ae_round(1.41*(wrk1-wrk0), _state)+1; - wrk0 = wrk1; - wrk1 = wrk0+jp; - } - } - } - - /* - * Select pivot row - */ - bbest = (double)(0); - entry = a->slscolptr.ptr.p_int[*jpiv]; - while(entry>=0) - { - s = ae_fabs(a->slsval.ptr.p_double[entry], _state); - if( *ipiv<0||ae_fp_greater(s,bbest) ) - { - bbest = s; - *ipiv = a->slsidx.ptr.p_int[entry*sptrf_slswidth+4]; - } - entry = a->slsidx.ptr.p_int[entry*sptrf_slswidth+1]; - } - if( *ipiv<0 ) - { - *ipiv = k; - } - return result; -} - - -/************************************************************************* -This function pivots out specified row and column. - -Sparse trail range changes from [K,N) to [K+1,N). - -V0I, V0R, V1I, V1R must be preallocated arrays[N]. - -Following data are returned: -* UU - diagonal element (pivoted out), can be zero -* V0I, V0R, NZ0 - sparse column pivoted out to the left (after permutation - is applied to its elements) and divided by UU. - V0I is array[NZ0] which stores row indexes in [K+1,N) range, V0R stores - values. -* V1I, V1R, NZ1 - sparse row pivoted out to the top. - - -- ALGLIB routine -- - 15.01.2019 - Bochkanov Sergey -*************************************************************************/ -static void sptrf_sparsetrailpivotout(sluv2sparsetrail* a, - ae_int_t ipiv, - ae_int_t jpiv, - double* uu, - /* Integer */ ae_vector* v0i, - /* Real */ ae_vector* v0r, - ae_int_t* nz0, - /* Integer */ ae_vector* v1i, - /* Real */ ae_vector* v1r, - ae_int_t* nz1, - ae_state *_state) -{ - ae_int_t n; - ae_int_t k; - ae_int_t i; - ae_int_t j; - ae_int_t entry; - double v; - double s; - ae_bool vb; - ae_int_t pos0k; - ae_int_t pos0piv; - ae_int_t pprev; - ae_int_t pnext; - ae_int_t pnextnext; - - *uu = 0; - *nz0 = 0; - *nz1 = 0; - - n = a->n; - k = a->k; - ae_assert(kJPiv - * - * NOTE: this code leaves V0I/V0R/NZ0 in the unfinalized state, - * i.e. these arrays do not account for pivoting performed - * on rows. They will be post-processed later. - */ - *nz0 = 0; - pos0k = -1; - pos0piv = -1; - entry = a->slscolptr.ptr.p_int[jpiv]; - while(entry>=0) - { - - /* - * Offload element - */ - i = a->slsidx.ptr.p_int[entry*sptrf_slswidth+4]; - v0i->ptr.p_int[*nz0] = i; - v0r->ptr.p_double[*nz0] = a->slsval.ptr.p_double[entry]; - if( i==k ) - { - pos0k = *nz0; - } - if( i==ipiv ) - { - pos0piv = *nz0; - } - *nz0 = *nz0+1; - - /* - * Remove element from the row list - */ - pprev = a->slsidx.ptr.p_int[entry*sptrf_slswidth+2]; - pnext = a->slsidx.ptr.p_int[entry*sptrf_slswidth+3]; - if( pprev>=0 ) - { - a->slsidx.ptr.p_int[pprev*sptrf_slswidth+3] = pnext; - } - else - { - a->slsrowptr.ptr.p_int[i] = pnext; - } - if( pnext>=0 ) - { - a->slsidx.ptr.p_int[pnext*sptrf_slswidth+2] = pprev; - } - - /* - * Select next entry - */ - entry = a->slsidx.ptr.p_int[entry*sptrf_slswidth+1]; - } - entry = a->slscolptr.ptr.p_int[k]; - a->slscolptr.ptr.p_int[jpiv] = entry; - while(entry>=0) - { - - /* - * Change column index - */ - a->slsidx.ptr.p_int[entry*sptrf_slswidth+5] = jpiv; - - /* - * Next entry - */ - entry = a->slsidx.ptr.p_int[entry*sptrf_slswidth+1]; - } - - /* - * Post-process V0, account for pivoting. - * Compute diagonal element UU. - */ - *uu = (double)(0); - if( pos0k>=0||pos0piv>=0 ) - { - - /* - * Apply permutation to rows of pivoted out column, specific - * implementation depends on the sparsity at locations #Pos0K - * and #Pos0Piv of the V0 array. - */ - if( pos0k>=0&&pos0piv>=0 ) - { - - /* - * Obtain diagonal element - */ - *uu = v0r->ptr.p_double[pos0piv]; - if( *uu!=0 ) - { - s = 1/(*uu); - } - else - { - s = (double)(1); - } - - /* - * Move pivoted out element, shift array by one in order - * to remove heading diagonal element (not needed here - * anymore). - */ - v0r->ptr.p_double[pos0piv] = v0r->ptr.p_double[pos0k]; - for(i=0; i<=*nz0-2; i++) - { - v0i->ptr.p_int[i] = v0i->ptr.p_int[i+1]; - v0r->ptr.p_double[i] = v0r->ptr.p_double[i+1]*s; - } - *nz0 = *nz0-1; - } - if( pos0k>=0&&pos0piv<0 ) - { - - /* - * Diagonal element is zero - */ - *uu = (double)(0); - - /* - * Pivot out element, reorder array - */ - v0i->ptr.p_int[pos0k] = ipiv; - for(i=pos0k; i<=*nz0-2; i++) - { - if( v0i->ptr.p_int[i]ptr.p_int[i+1] ) - { - break; - } - j = v0i->ptr.p_int[i]; - v0i->ptr.p_int[i] = v0i->ptr.p_int[i+1]; - v0i->ptr.p_int[i+1] = j; - v = v0r->ptr.p_double[i]; - v0r->ptr.p_double[i] = v0r->ptr.p_double[i+1]; - v0r->ptr.p_double[i+1] = v; - } - } - if( pos0k<0&&pos0piv>=0 ) - { - - /* - * Get diagonal element - */ - *uu = v0r->ptr.p_double[pos0piv]; - if( *uu!=0 ) - { - s = 1/(*uu); - } - else - { - s = (double)(1); - } - - /* - * Shift array past the pivoted in element by one - * in order to remove pivot - */ - for(i=0; i<=pos0piv-1; i++) - { - v0r->ptr.p_double[i] = v0r->ptr.p_double[i]*s; - } - for(i=pos0piv; i<=*nz0-2; i++) - { - v0i->ptr.p_int[i] = v0i->ptr.p_int[i+1]; - v0r->ptr.p_double[i] = v0r->ptr.p_double[i+1]*s; - } - *nz0 = *nz0-1; - } - } - - /* - * Pivot out row IPiv from the sparse linked storage: - * * remove row IPiv from the matrix - * * reindex elements of row K after it is permuted to IPiv - * * apply permutation to the cols of the pivoted out row, - * resort columns - */ - *nz1 = 0; - entry = a->slsrowptr.ptr.p_int[ipiv]; - while(entry>=0) - { - - /* - * Offload element - */ - j = a->slsidx.ptr.p_int[entry*sptrf_slswidth+5]; - v1i->ptr.p_int[*nz1] = j; - v1r->ptr.p_double[*nz1] = a->slsval.ptr.p_double[entry]; - *nz1 = *nz1+1; - - /* - * Remove element from the column list - */ - pprev = a->slsidx.ptr.p_int[entry*sptrf_slswidth+0]; - pnext = a->slsidx.ptr.p_int[entry*sptrf_slswidth+1]; - if( pprev>=0 ) - { - a->slsidx.ptr.p_int[pprev*sptrf_slswidth+1] = pnext; - } - else - { - a->slscolptr.ptr.p_int[j] = pnext; - } - if( pnext>=0 ) - { - a->slsidx.ptr.p_int[pnext*sptrf_slswidth+0] = pprev; - } - - /* - * Select next entry - */ - entry = a->slsidx.ptr.p_int[entry*sptrf_slswidth+3]; - } - a->slsrowptr.ptr.p_int[ipiv] = a->slsrowptr.ptr.p_int[k]; - entry = a->slsrowptr.ptr.p_int[ipiv]; - while(entry>=0) - { - - /* - * Change row index - */ - a->slsidx.ptr.p_int[entry*sptrf_slswidth+4] = ipiv; - - /* - * Resort column affected by row pivoting - */ - j = a->slsidx.ptr.p_int[entry*sptrf_slswidth+5]; - pprev = a->slsidx.ptr.p_int[entry*sptrf_slswidth+0]; - pnext = a->slsidx.ptr.p_int[entry*sptrf_slswidth+1]; - while(pnext>=0&&a->slsidx.ptr.p_int[pnext*sptrf_slswidth+4]slsidx.ptr.p_int[pnext*sptrf_slswidth+1]; - - /* - * prev->next - */ - if( pprev>=0 ) - { - a->slsidx.ptr.p_int[pprev*sptrf_slswidth+1] = pnext; - } - else - { - a->slscolptr.ptr.p_int[j] = pnext; - } - - /* - * entry->prev, entry->next - */ - a->slsidx.ptr.p_int[entry*sptrf_slswidth+0] = pnext; - a->slsidx.ptr.p_int[entry*sptrf_slswidth+1] = pnextnext; - - /* - * next->prev, next->next - */ - a->slsidx.ptr.p_int[pnext*sptrf_slswidth+0] = pprev; - a->slsidx.ptr.p_int[pnext*sptrf_slswidth+1] = entry; - - /* - * nextnext->prev - */ - if( pnextnext>=0 ) - { - a->slsidx.ptr.p_int[pnextnext*sptrf_slswidth+0] = entry; - } - - /* - * PPrev, Item, PNext - */ - pprev = pnext; - pnext = pnextnext; - } - - /* - * Next entry - */ - entry = a->slsidx.ptr.p_int[entry*sptrf_slswidth+3]; - } - - /* - * Reorder other structures - */ - i = a->nzc.ptr.p_int[k]; - a->nzc.ptr.p_int[k] = a->nzc.ptr.p_int[jpiv]; - a->nzc.ptr.p_int[jpiv] = i; - i = a->colid.ptr.p_int[k]; - a->colid.ptr.p_int[k] = a->colid.ptr.p_int[jpiv]; - a->colid.ptr.p_int[jpiv] = i; - vb = a->isdensified.ptr.p_bool[k]; - a->isdensified.ptr.p_bool[k] = a->isdensified.ptr.p_bool[jpiv]; - a->isdensified.ptr.p_bool[jpiv] = vb; - - /* - * Handle removal of col/row #K - */ - for(i=0; i<=*nz1-1; i++) - { - j = v1i->ptr.p_int[i]; - a->nzc.ptr.p_int[j] = a->nzc.ptr.p_int[j]-1; - } - a->k = a->k+1; -} - - -/************************************************************************* -This function densifies I1-th column of the sparse trail. - -PARAMETERS: - A - sparse trail - I1 - column index - BUpper - upper rectangular submatrix, updated during densification - of the columns (densified columns are removed) - DTrail - dense trail, receives densified columns from sparse - trail and BUpper - - -- ALGLIB routine -- - 15.01.2019 - Bochkanov Sergey -*************************************************************************/ -static void sptrf_sparsetraildensify(sluv2sparsetrail* a, - ae_int_t i1, - sluv2list1matrix* bupper, - sluv2densetrail* dtrail, - ae_state *_state) -{ - ae_int_t n; - ae_int_t k; - ae_int_t i; - ae_int_t jp; - ae_int_t entry; - ae_int_t pprev; - ae_int_t pnext; - - - n = a->n; - k = a->k; - ae_assert(kisdensified.ptr.p_bool[i1], "SparseTrailDensify: integrity check failed", _state); - - /* - * Offload items [0,K) of densified column from BUpper - */ - for(i=0; i<=n-1; i++) - { - a->tmp0.ptr.p_double[i] = (double)(0); - } - jp = bupper->idxfirst.ptr.p_int[i1]; - while(jp>=0) - { - a->tmp0.ptr.p_double[bupper->strgidx.ptr.p_int[2*jp+1]] = bupper->strgval.ptr.p_double[jp]; - jp = bupper->strgidx.ptr.p_int[2*jp+0]; - } - sptrf_sluv2list1dropsequence(bupper, i1, _state); - - /* - * Offload items [K,N) of densified column from BLeft - */ - entry = a->slscolptr.ptr.p_int[i1]; - while(entry>=0) - { - - /* - * Offload element - */ - i = a->slsidx.ptr.p_int[entry*sptrf_slswidth+4]; - a->tmp0.ptr.p_double[i] = a->slsval.ptr.p_double[entry]; - - /* - * Remove element from the row list - */ - pprev = a->slsidx.ptr.p_int[entry*sptrf_slswidth+2]; - pnext = a->slsidx.ptr.p_int[entry*sptrf_slswidth+3]; - if( pprev>=0 ) - { - a->slsidx.ptr.p_int[pprev*sptrf_slswidth+3] = pnext; - } - else - { - a->slsrowptr.ptr.p_int[i] = pnext; - } - if( pnext>=0 ) - { - a->slsidx.ptr.p_int[pnext*sptrf_slswidth+2] = pprev; - } - - /* - * Select next entry - */ - entry = a->slsidx.ptr.p_int[entry*sptrf_slswidth+1]; - } - - /* - * Densify - */ - a->nzc.ptr.p_int[i1] = 0; - a->isdensified.ptr.p_bool[i1] = ae_true; - a->slscolptr.ptr.p_int[i1] = -1; - sptrf_densetrailappendcolumn(dtrail, &a->tmp0, a->colid.ptr.p_int[i1], _state); -} - - -/************************************************************************* -This function appends rank-1 update to the sparse trail. Dense trail is -not updated here, but we may move some columns to dense trail during -update (i.e. densify them). Thus, you have to update dense trail BEFORE -you start updating sparse one (otherwise, recently densified columns will -be updated twice). - -PARAMETERS: - A - sparse trail - V0I, V0R - update column returned by SparseTrailPivotOut (MUST be - array[N] independently of the NZ0). - NZ0 - non-zero count for update column - V1I, V1R - update row returned by SparseTrailPivotOut - NZ1 - non-zero count for update row - BUpper - upper rectangular submatrix, updated during densification - of the columns (densified columns are removed) - DTrail - dense trail, receives densified columns from sparse - trail and BUpper - DensificationSupported- if False, no densification is performed - - -- ALGLIB routine -- - 15.01.2019 - Bochkanov Sergey -*************************************************************************/ -static void sptrf_sparsetrailupdate(sluv2sparsetrail* a, - /* Integer */ ae_vector* v0i, - /* Real */ ae_vector* v0r, - ae_int_t nz0, - /* Integer */ ae_vector* v1i, - /* Real */ ae_vector* v1r, - ae_int_t nz1, - sluv2list1matrix* bupper, - sluv2densetrail* dtrail, - ae_bool densificationsupported, - ae_state *_state) -{ - ae_int_t n; - ae_int_t k; - ae_int_t i; - ae_int_t j; - ae_int_t i0; - ae_int_t i1; - double v1; - ae_int_t densifyabove; - ae_int_t nnz; - ae_int_t entry; - ae_int_t newentry; - ae_int_t pprev; - ae_int_t pnext; - ae_int_t p; - ae_int_t nexti; - ae_int_t newoffs; - - - n = a->n; - k = a->k; - ae_assert(kcnt>=nz0+1, "SparseTrailUpdate: integrity check failed", _state); - ae_assert(v0r->cnt>=nz0+1, "SparseTrailUpdate: integrity check failed", _state); - v0i->ptr.p_int[nz0] = -1; - v0r->ptr.p_double[nz0] = (double)(0); - - /* - * Update sparse representation - */ - ivectorgrowto(&a->slsidx, (a->slsused+nz0*nz1)*sptrf_slswidth, _state); - rvectorgrowto(&a->slsval, a->slsused+nz0*nz1, _state); - for(j=0; j<=nz1-1; j++) - { - if( nz0==0 ) - { - continue; - } - i1 = v1i->ptr.p_int[j]; - v1 = v1r->ptr.p_double[j]; - - /* - * Update column #I1 - */ - nnz = a->nzc.ptr.p_int[i1]; - i = 0; - i0 = v0i->ptr.p_int[i]; - entry = a->slscolptr.ptr.p_int[i1]; - pprev = -1; - while(i=0 ) - { - nexti = a->slsidx.ptr.p_int[entry*sptrf_slswidth+4]; - } - else - { - nexti = n+1; - } - while(i=nexti ) - { - break; - } - - /* - * Allocate new entry, store column/row/value - */ - newentry = a->slsused; - a->slsused = newentry+1; - nnz = nnz+1; - newoffs = newentry*sptrf_slswidth; - a->slsidx.ptr.p_int[newoffs+4] = i0; - a->slsidx.ptr.p_int[newoffs+5] = i1; - a->slsval.ptr.p_double[newentry] = -v1*v0r->ptr.p_double[i]; - - /* - * Insert entry into column list - */ - a->slsidx.ptr.p_int[newoffs+0] = pprev; - a->slsidx.ptr.p_int[newoffs+1] = pnext; - if( pprev>=0 ) - { - a->slsidx.ptr.p_int[pprev*sptrf_slswidth+1] = newentry; - } - else - { - a->slscolptr.ptr.p_int[i1] = newentry; - } - if( entry>=0 ) - { - a->slsidx.ptr.p_int[entry*sptrf_slswidth+0] = newentry; - } - - /* - * Insert entry into row list - */ - p = a->slsrowptr.ptr.p_int[i0]; - a->slsidx.ptr.p_int[newoffs+2] = -1; - a->slsidx.ptr.p_int[newoffs+3] = p; - if( p>=0 ) - { - a->slsidx.ptr.p_int[p*sptrf_slswidth+2] = newentry; - } - a->slsrowptr.ptr.p_int[i0] = newentry; - - /* - * Advance pointers - */ - pprev = newentry; - i = i+1; - i0 = v0i->ptr.p_int[i]; - } - if( i>=nz0 ) - { - break; - } - - /* - * Update already existing entry of the column list, if needed - */ - if( entry>=0 ) - { - if( i0==nexti ) - { - a->slsval.ptr.p_double[entry] = a->slsval.ptr.p_double[entry]-v1*v0r->ptr.p_double[i]; - i = i+1; - i0 = v0i->ptr.p_int[i]; - } - pprev = entry; - } - - /* - * Advance to the next pre-existing entry (if present) - */ - if( entry>=0 ) - { - entry = a->slsidx.ptr.p_int[entry*sptrf_slswidth+1]; - } - } - a->nzc.ptr.p_int[i1] = nnz; - - /* - * Densify column if needed - */ - if( (densificationsupported&&nnz>densifyabove)&&!a->isdensified.ptr.p_bool[i1] ) - { - sptrf_sparsetraildensify(a, i1, bupper, dtrail, _state); - } - } -} - - -void _sluv2list1matrix_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - sluv2list1matrix *p = (sluv2list1matrix*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->idxfirst, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->strgidx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->strgval, 0, DT_REAL, _state, make_automatic); -} - - -void _sluv2list1matrix_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - sluv2list1matrix *dst = (sluv2list1matrix*)_dst; - sluv2list1matrix *src = (sluv2list1matrix*)_src; - dst->nfixed = src->nfixed; - dst->ndynamic = src->ndynamic; - ae_vector_init_copy(&dst->idxfirst, &src->idxfirst, _state, make_automatic); - ae_vector_init_copy(&dst->strgidx, &src->strgidx, _state, make_automatic); - ae_vector_init_copy(&dst->strgval, &src->strgval, _state, make_automatic); - dst->nallocated = src->nallocated; - dst->nused = src->nused; -} - - -void _sluv2list1matrix_clear(void* _p) -{ - sluv2list1matrix *p = (sluv2list1matrix*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->idxfirst); - ae_vector_clear(&p->strgidx); - ae_vector_clear(&p->strgval); -} - - -void _sluv2list1matrix_destroy(void* _p) -{ - sluv2list1matrix *p = (sluv2list1matrix*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->idxfirst); - ae_vector_destroy(&p->strgidx); - ae_vector_destroy(&p->strgval); -} - - -void _sluv2sparsetrail_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - sluv2sparsetrail *p = (sluv2sparsetrail*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->nzc, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->wrkset, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->colid, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->isdensified, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->slscolptr, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->slsrowptr, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->slsidx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->slsval, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); -} - - -void _sluv2sparsetrail_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - sluv2sparsetrail *dst = (sluv2sparsetrail*)_dst; - sluv2sparsetrail *src = (sluv2sparsetrail*)_src; - dst->n = src->n; - dst->k = src->k; - ae_vector_init_copy(&dst->nzc, &src->nzc, _state, make_automatic); - dst->maxwrkcnt = src->maxwrkcnt; - dst->maxwrknz = src->maxwrknz; - dst->wrkcnt = src->wrkcnt; - ae_vector_init_copy(&dst->wrkset, &src->wrkset, _state, make_automatic); - ae_vector_init_copy(&dst->colid, &src->colid, _state, make_automatic); - ae_vector_init_copy(&dst->isdensified, &src->isdensified, _state, make_automatic); - ae_vector_init_copy(&dst->slscolptr, &src->slscolptr, _state, make_automatic); - ae_vector_init_copy(&dst->slsrowptr, &src->slsrowptr, _state, make_automatic); - ae_vector_init_copy(&dst->slsidx, &src->slsidx, _state, make_automatic); - ae_vector_init_copy(&dst->slsval, &src->slsval, _state, make_automatic); - dst->slsused = src->slsused; - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); -} - - -void _sluv2sparsetrail_clear(void* _p) -{ - sluv2sparsetrail *p = (sluv2sparsetrail*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->nzc); - ae_vector_clear(&p->wrkset); - ae_vector_clear(&p->colid); - ae_vector_clear(&p->isdensified); - ae_vector_clear(&p->slscolptr); - ae_vector_clear(&p->slsrowptr); - ae_vector_clear(&p->slsidx); - ae_vector_clear(&p->slsval); - ae_vector_clear(&p->tmp0); -} - - -void _sluv2sparsetrail_destroy(void* _p) -{ - sluv2sparsetrail *p = (sluv2sparsetrail*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->nzc); - ae_vector_destroy(&p->wrkset); - ae_vector_destroy(&p->colid); - ae_vector_destroy(&p->isdensified); - ae_vector_destroy(&p->slscolptr); - ae_vector_destroy(&p->slsrowptr); - ae_vector_destroy(&p->slsidx); - ae_vector_destroy(&p->slsval); - ae_vector_destroy(&p->tmp0); -} - - -void _sluv2densetrail_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - sluv2densetrail *p = (sluv2densetrail*)_p; - ae_touch_ptr((void*)p); - ae_matrix_init(&p->d, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->did, 0, DT_INT, _state, make_automatic); -} - - -void _sluv2densetrail_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - sluv2densetrail *dst = (sluv2densetrail*)_dst; - sluv2densetrail *src = (sluv2densetrail*)_src; - dst->n = src->n; - dst->ndense = src->ndense; - ae_matrix_init_copy(&dst->d, &src->d, _state, make_automatic); - ae_vector_init_copy(&dst->did, &src->did, _state, make_automatic); -} - - -void _sluv2densetrail_clear(void* _p) -{ - sluv2densetrail *p = (sluv2densetrail*)_p; - ae_touch_ptr((void*)p); - ae_matrix_clear(&p->d); - ae_vector_clear(&p->did); -} - - -void _sluv2densetrail_destroy(void* _p) -{ - sluv2densetrail *p = (sluv2densetrail*)_p; - ae_touch_ptr((void*)p); - ae_matrix_destroy(&p->d); - ae_vector_destroy(&p->did); -} - - -void _sluv2buffer_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - sluv2buffer *p = (sluv2buffer*)_p; - ae_touch_ptr((void*)p); - _sparsematrix_init(&p->sparsel, _state, make_automatic); - _sparsematrix_init(&p->sparseut, _state, make_automatic); - _sluv2list1matrix_init(&p->bleft, _state, make_automatic); - _sluv2list1matrix_init(&p->bupper, _state, make_automatic); - _sluv2sparsetrail_init(&p->strail, _state, make_automatic); - _sluv2densetrail_init(&p->dtrail, _state, make_automatic); - ae_vector_init(&p->rowpermrawidx, 0, DT_INT, _state, make_automatic); - ae_matrix_init(&p->dbuf, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->v0i, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->v1i, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->v0r, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->v1r, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpi, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->tmpp, 0, DT_INT, _state, make_automatic); -} - - -void _sluv2buffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - sluv2buffer *dst = (sluv2buffer*)_dst; - sluv2buffer *src = (sluv2buffer*)_src; - dst->n = src->n; - _sparsematrix_init_copy(&dst->sparsel, &src->sparsel, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparseut, &src->sparseut, _state, make_automatic); - _sluv2list1matrix_init_copy(&dst->bleft, &src->bleft, _state, make_automatic); - _sluv2list1matrix_init_copy(&dst->bupper, &src->bupper, _state, make_automatic); - _sluv2sparsetrail_init_copy(&dst->strail, &src->strail, _state, make_automatic); - _sluv2densetrail_init_copy(&dst->dtrail, &src->dtrail, _state, make_automatic); - ae_vector_init_copy(&dst->rowpermrawidx, &src->rowpermrawidx, _state, make_automatic); - ae_matrix_init_copy(&dst->dbuf, &src->dbuf, _state, make_automatic); - ae_vector_init_copy(&dst->v0i, &src->v0i, _state, make_automatic); - ae_vector_init_copy(&dst->v1i, &src->v1i, _state, make_automatic); - ae_vector_init_copy(&dst->v0r, &src->v0r, _state, make_automatic); - ae_vector_init_copy(&dst->v1r, &src->v1r, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->tmpi, &src->tmpi, _state, make_automatic); - ae_vector_init_copy(&dst->tmpp, &src->tmpp, _state, make_automatic); -} - - -void _sluv2buffer_clear(void* _p) -{ - sluv2buffer *p = (sluv2buffer*)_p; - ae_touch_ptr((void*)p); - _sparsematrix_clear(&p->sparsel); - _sparsematrix_clear(&p->sparseut); - _sluv2list1matrix_clear(&p->bleft); - _sluv2list1matrix_clear(&p->bupper); - _sluv2sparsetrail_clear(&p->strail); - _sluv2densetrail_clear(&p->dtrail); - ae_vector_clear(&p->rowpermrawidx); - ae_matrix_clear(&p->dbuf); - ae_vector_clear(&p->v0i); - ae_vector_clear(&p->v1i); - ae_vector_clear(&p->v0r); - ae_vector_clear(&p->v1r); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->tmpi); - ae_vector_clear(&p->tmpp); -} - - -void _sluv2buffer_destroy(void* _p) -{ - sluv2buffer *p = (sluv2buffer*)_p; - ae_touch_ptr((void*)p); - _sparsematrix_destroy(&p->sparsel); - _sparsematrix_destroy(&p->sparseut); - _sluv2list1matrix_destroy(&p->bleft); - _sluv2list1matrix_destroy(&p->bupper); - _sluv2sparsetrail_destroy(&p->strail); - _sluv2densetrail_destroy(&p->dtrail); - ae_vector_destroy(&p->rowpermrawidx); - ae_matrix_destroy(&p->dbuf); - ae_vector_destroy(&p->v0i); - ae_vector_destroy(&p->v1i); - ae_vector_destroy(&p->v0r); - ae_vector_destroy(&p->v1r); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->tmpi); - ae_vector_destroy(&p->tmpp); -} - - -#endif -#if defined(AE_COMPILE_AMDORDERING) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function generates approximate minimum degree ordering - -INPUT PARAMETERS - A - lower triangular sparse matrix in CRS format - N - problem size - Buf - reusable buffer object, does not need special initialization - -OUTPUT PARAMETERS - Perm - array[N], maps original indexes I to permuted indexes - InvPerm - array[N], maps permuted indexes I to original indexes - -NOTE: definite 'DEBUG.SLOW' trace tag will activate extra-slow (roughly - N^3 ops) integrity checks, in addition to cheap O(1) ones. - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -void generateamdpermutation(sparsematrix* a, - ae_int_t n, - /* Integer */ ae_vector* perm, - /* Integer */ ae_vector* invperm, - amdbuffer* buf, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t p; - ae_int_t setprealloc; - ae_int_t inithashbucketsize; - ae_bool extendeddebug; - ae_int_t nodesize; - ae_int_t cnt0; - ae_int_t cnt1; - - - setprealloc = 3; - inithashbucketsize = 16; - extendeddebug = ae_is_trace_enabled("DEBUG.SLOW"); - buf->n = n; - buf->checkexactdegrees = extendeddebug; - buf->extendeddebug = extendeddebug; - amdordering_mtxinit(n, &buf->mtxl, _state); - amdordering_knsinitfroma(a, n, &buf->seta, _state); - amdordering_knsinit(n, n, setprealloc, &buf->setsuper, _state); - for(i=0; i<=n-1; i++) - { - amdordering_knsaddnewelement(&buf->setsuper, i, i, _state); - } - amdordering_knsinit(n, n, setprealloc, &buf->sete, _state); - amdordering_knsinit(n, n, inithashbucketsize, &buf->hashbuckets, _state); - amdordering_nsinitemptyslow(n, &buf->nonemptybuckets, _state); - ivectorsetlengthatleast(&buf->perm, n, _state); - ivectorsetlengthatleast(&buf->invperm, n, _state); - ivectorsetlengthatleast(&buf->columnswaps, n, _state); - for(i=0; i<=n-1; i++) - { - buf->perm.ptr.p_int[i] = i; - buf->invperm.ptr.p_int[i] = i; - } - amdordering_vtxinit(a, n, buf->checkexactdegrees, &buf->vertexdegrees, _state); - bsetallocv(n, ae_true, &buf->issupernode, _state); - bsetallocv(n, ae_false, &buf->iseliminated, _state); - isetallocv(n, -1, &buf->arrwe, _state); - if( extendeddebug ) - { - ae_matrix_set_length(&buf->dbga, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (j<=i&&sparseexists(a, i, j, _state))||(j>=i&&sparseexists(a, j, i, _state)) ) - { - buf->dbga.ptr.pp_double[i][j] = 0.1/n*(ae_sin(i+0.17, _state)+ae_cos(ae_sqrt(j+0.65, _state), _state)); - } - else - { - buf->dbga.ptr.pp_double[i][j] = (double)(0); - } - } - } - for(i=0; i<=n-1; i++) - { - buf->dbga.ptr.pp_double[i][i] = (double)(1); - } - } - ivectorsetlengthatleast(&buf->ls, n, _state); - amdordering_nsinitemptyslow(n, &buf->lp, _state); - amdordering_nsinitemptyslow(n, &buf->plp, _state); - amdordering_nsinitemptyslow(n, &buf->ep, _state); - amdordering_nsinitemptyslow(n, &buf->exactdegreetmp0, _state); - amdordering_nsinitemptyslow(n, &buf->adji, _state); - amdordering_nsinitemptyslow(n, &buf->adjj, _state); - k = 0; - while(kcheckexactdegrees, "AMD: extended debug needs exact degrees", _state); - for(i=k; i<=k+nodesize-1; i++) - { - if( buf->columnswaps.ptr.p_int[i]!=i ) - { - swaprows(&buf->dbga, i, buf->columnswaps.ptr.p_int[i], n, _state); - swapcols(&buf->dbga, i, buf->columnswaps.ptr.p_int[i], n, _state); - } - } - for(i=0; i<=nodesize-1; i++) - { - rmatrixgemm(n-k-i, n-k-i, k+i, -1.0, &buf->dbga, k+i, 0, 0, &buf->dbga, 0, k+i, 0, 1.0, &buf->dbga, k+i, k+i, _state); - } - cnt0 = amdordering_nscount(&buf->lp, _state); - cnt1 = 0; - for(i=k+1; i<=n-1; i++) - { - if( ae_fp_neq(buf->dbga.ptr.pp_double[i][k],(double)(0)) ) - { - inc(&cnt1, _state); - } - } - ae_assert(cnt0+nodesize-1==cnt1, "AMD: integrity check 7344 failed", _state); - ae_assert(amdordering_vtxgetapprox(&buf->vertexdegrees, p, _state)>=amdordering_vtxgetexact(&buf->vertexdegrees, p, _state), "AMD: integrity check for ApproxD failed", _state); - ae_assert(amdordering_vtxgetexact(&buf->vertexdegrees, p, _state)==cnt0, "AMD: integrity check for ExactD failed", _state); - } - ae_assert(amdordering_vtxgetapprox(&buf->vertexdegrees, p, _state)>=amdordering_nscount(&buf->lp, _state), "AMD: integrity check 7956 failed", _state); - ae_assert(amdordering_knscountkth(&buf->sete, p, _state)>2||amdordering_vtxgetapprox(&buf->vertexdegrees, p, _state)==amdordering_nscount(&buf->lp, _state), "AMD: integrity check 7295 failed", _state); - amdordering_knsstartenumeration(&buf->sete, p, _state); - while(amdordering_knsenumerate(&buf->sete, &j, _state)) - { - amdordering_mtxclearcolumn(&buf->mtxl, j, _state); - } - amdordering_knsstartenumeration(&buf->setsuper, p, _state); - while(amdordering_knsenumerate(&buf->setsuper, &j, _state)) - { - buf->iseliminated.ptr.p_bool[j] = ae_true; - amdordering_mtxclearrow(&buf->mtxl, j, _state); - } - amdordering_knsclearkthreclaim(&buf->seta, p, _state); - amdordering_knsclearkthreclaim(&buf->sete, p, _state); - buf->issupernode.ptr.p_bool[p] = ae_false; - amdordering_vtxremovevertex(&buf->vertexdegrees, p, _state); - k = k+nodesize; - } - ivectorsetlengthatleast(perm, n, _state); - ivectorsetlengthatleast(invperm, n, _state); - for(i=0; i<=n-1; i++) - { - perm->ptr.p_int[i] = buf->perm.ptr.p_int[i]; - invperm->ptr.p_int[i] = buf->invperm.ptr.p_int[i]; - } -} - - -/************************************************************************* -Initializes n-set by empty structure. - -IMPORTANT: this function need O(N) time for initialization. It is recommended - to reduce its usage as much as possible, and use nsClear() - where possible. - -INPUT PARAMETERS - N - possible set size - -OUTPUT PARAMETERS - SA - empty N-set - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_nsinitemptyslow(ae_int_t n, - amdnset* sa, - ae_state *_state) -{ - - - sa->n = n; - sa->nstored = 0; - isetallocv(n, -999999999, &sa->locationof, _state); - isetallocv(n, -999999999, &sa->items, _state); -} - - -/************************************************************************* -Copies n-set to properly initialized target set. The target set has to be -properly initialized, and it can be non-empty. If it is non-empty, its -contents is quickly erased before copying. - -The cost of this function is O(max(SrcSize,DstSize)) - -INPUT PARAMETERS - SSrc - source N-set - SDst - destination N-set (has same size as SSrc) - -OUTPUT PARAMETERS - SDst - copy of SSrc - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_nscopy(amdnset* ssrc, - amdnset* sdst, - ae_state *_state) -{ - ae_int_t ns; - ae_int_t i; - ae_int_t k; - - - amdordering_nsclear(sdst, _state); - ns = ssrc->nstored; - for(i=0; i<=ns-1; i++) - { - k = ssrc->items.ptr.p_int[i]; - sdst->items.ptr.p_int[i] = k; - sdst->locationof.ptr.p_int[k] = i; - } - sdst->nstored = ns; -} - - -/************************************************************************* -Add K-th element to the set. The element may already exist in the set. - -INPUT PARAMETERS - SA - set - K - element to add, 0<=Klocationof.ptr.p_int[k]>=0 ) - { - return; - } - ns = sa->nstored; - sa->locationof.ptr.p_int[k] = ns; - sa->items.ptr.p_int[ns] = k; - sa->nstored = ns+1; -} - - -/************************************************************************* -Add K-th set from the source kn-set - -INPUT PARAMETERS - SA - set - Src, K - source kn-set and set index K - -OUTPUT PARAMETERS - SA - modified SA - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_nsaddkth(amdnset* sa, - amdknset* src, - ae_int_t k, - ae_state *_state) -{ - ae_int_t idxbegin; - ae_int_t idxend; - ae_int_t j; - ae_int_t ns; - - - idxbegin = src->vbegin.ptr.p_int[k]; - idxend = idxbegin+src->vcnt.ptr.p_int[k]; - ns = sa->nstored; - while(idxbegindata.ptr.p_int[idxbegin]; - if( sa->locationof.ptr.p_int[j]<0 ) - { - sa->locationof.ptr.p_int[j] = ns; - sa->items.ptr.p_int[ns] = j; - ns = ns+1; - } - idxbegin = idxbegin+1; - } - sa->nstored = ns; -} - - -/************************************************************************* -Subtracts K-th set from the source structure - -INPUT PARAMETERS - SA - set - Src, K - source kn-set and set index K - -OUTPUT PARAMETERS - SA - modified SA - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_nssubtractkth(amdnset* sa, - amdknset* src, - ae_int_t k, - ae_state *_state) -{ - ae_int_t idxbegin; - ae_int_t idxend; - ae_int_t j; - ae_int_t loc; - ae_int_t ns; - ae_int_t item; - - - idxbegin = src->vbegin.ptr.p_int[k]; - idxend = idxbegin+src->vcnt.ptr.p_int[k]; - ns = sa->nstored; - while(idxbegindata.ptr.p_int[idxbegin]; - loc = sa->locationof.ptr.p_int[j]; - if( loc>=0 ) - { - item = sa->items.ptr.p_int[ns-1]; - sa->items.ptr.p_int[loc] = item; - sa->locationof.ptr.p_int[item] = loc; - sa->locationof.ptr.p_int[j] = -1; - ns = ns-1; - } - idxbegin = idxbegin+1; - } - sa->nstored = ns; -} - - -/************************************************************************* -Clears set - -INPUT PARAMETERS - SA - set to be cleared - - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_nsclear(amdnset* sa, ae_state *_state) -{ - ae_int_t i; - ae_int_t ns; - - - ns = sa->nstored; - for(i=0; i<=ns-1; i++) - { - sa->locationof.ptr.p_int[sa->items.ptr.p_int[i]] = -1; - } - sa->nstored = 0; -} - - -/************************************************************************* -Counts set elements - -INPUT PARAMETERS - SA - set - -RESULT - number of elements in SA - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static ae_int_t amdordering_nscount(amdnset* sa, ae_state *_state) -{ - ae_int_t result; - - - result = sa->nstored; - return result; -} - - -/************************************************************************* -Counts set elements not present in the K-th set of the source structure - -INPUT PARAMETERS - SA - set - Src, K - source kn-set and set index K - -RESULT - number of elements in SA not present in Src[K] - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static ae_int_t amdordering_nscountnotkth(amdnset* sa, - amdknset* src, - ae_int_t k, - ae_state *_state) -{ - ae_int_t idxbegin; - ae_int_t idxend; - ae_int_t intersectcnt; - ae_int_t result; - - - idxbegin = src->vbegin.ptr.p_int[k]; - idxend = idxbegin+src->vcnt.ptr.p_int[k]; - intersectcnt = 0; - while(idxbeginlocationof.ptr.p_int[src->data.ptr.p_int[idxbegin]]>=0 ) - { - intersectcnt = intersectcnt+1; - } - idxbegin = idxbegin+1; - } - result = sa->nstored-intersectcnt; - return result; -} - - -/************************************************************************* -Counts set elements also present in the K-th set of the source structure - -INPUT PARAMETERS - SA - set - Src, K - source kn-set and set index K - -RESULT - number of elements in SA also present in Src[K] - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static ae_int_t amdordering_nscountandkth(amdnset* sa, - amdknset* src, - ae_int_t k, - ae_state *_state) -{ - ae_int_t idxbegin; - ae_int_t idxend; - ae_int_t result; - - - idxbegin = src->vbegin.ptr.p_int[k]; - idxend = idxbegin+src->vcnt.ptr.p_int[k]; - result = 0; - while(idxbeginlocationof.ptr.p_int[src->data.ptr.p_int[idxbegin]]>=0 ) - { - result = result+1; - } - idxbegin = idxbegin+1; - } - return result; -} - - -/************************************************************************* -Compare two sets, returns True for equal sets - -INPUT PARAMETERS - S0 - set 0 - S1 - set 1, must have same parameter N as set 0 - -RESULT - True, if sets are equal - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static ae_bool amdordering_nsequal(amdnset* s0, - amdnset* s1, - ae_state *_state) -{ - ae_int_t i; - ae_int_t ns0; - ae_int_t ns1; - ae_bool result; - - - result = ae_false; - if( s0->n!=s1->n ) - { - return result; - } - if( s0->nstored!=s1->nstored ) - { - return result; - } - ns0 = s0->nstored; - ns1 = s1->nstored; - for(i=0; i<=ns0-1; i++) - { - if( s1->locationof.ptr.p_int[s0->items.ptr.p_int[i]]<0 ) - { - return result; - } - } - for(i=0; i<=ns1-1; i++) - { - if( s0->locationof.ptr.p_int[s1->items.ptr.p_int[i]]<0 ) - { - return result; - } - } - result = ae_true; - return result; -} - - -/************************************************************************* -Prepares iteration over set - -INPUT PARAMETERS - SA - set - -OUTPUT PARAMETERS - SA - SA ready for repeated calls of nsEnumerate() - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_nsstartenumeration(amdnset* sa, ae_state *_state) -{ - - - sa->iteridx = 0; -} - - -/************************************************************************* -Iterates over the set. Subsequent calls return True and set J to new set -item until iteration stops and False is returned. - -INPUT PARAMETERS - SA - n-set - -OUTPUT PARAMETERS - J - if: - * Result=True - index of element in the set - * Result=False - not set - - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static ae_bool amdordering_nsenumerate(amdnset* sa, - ae_int_t* i, - ae_state *_state) -{ - ae_int_t k; - ae_bool result; - - *i = 0; - - k = sa->iteridx; - if( k>=sa->nstored ) - { - result = ae_false; - return result; - } - *i = sa->items.ptr.p_int[k]; - sa->iteridx = k+1; - result = ae_true; - return result; -} - - -/************************************************************************* -Compresses internal storage, reclaiming previously dropped blocks. To be -used internally by kn-set modification functions. - -INPUT PARAMETERS - SA - kn-set to compress - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_knscompressstorage(amdknset* sa, ae_state *_state) -{ - ae_int_t i; - ae_int_t blocklen; - ae_int_t setidx; - ae_int_t srcoffs; - ae_int_t dstoffs; - - - srcoffs = 0; - dstoffs = 0; - while(srcoffsdataused) - { - blocklen = sa->data.ptr.p_int[srcoffs+0]; - setidx = sa->data.ptr.p_int[srcoffs+1]; - ae_assert(blocklen>=amdordering_knsheadersize, "knsCompressStorage: integrity check 6385 failed", _state); - if( setidx<0 ) - { - srcoffs = srcoffs+blocklen; - continue; - } - if( srcoffs!=dstoffs ) - { - for(i=0; i<=blocklen-1; i++) - { - sa->data.ptr.p_int[dstoffs+i] = sa->data.ptr.p_int[srcoffs+i]; - } - sa->vbegin.ptr.p_int[setidx] = dstoffs+amdordering_knsheadersize; - } - dstoffs = dstoffs+blocklen; - srcoffs = srcoffs+blocklen; - } - ae_assert(srcoffs==sa->dataused, "knsCompressStorage: integrity check 9464 failed", _state); - sa->dataused = dstoffs; -} - - -/************************************************************************* -Reallocates internal storage for set #SetIdx, increasing its capacity to -NewAllocated exactly. This function may invalidate internal pointers for -ALL sets in the kn-set structure because it may perform storage -compression in order to reclaim previously freed space. - -INPUT PARAMETERS - SA - kn-set structure - SetIdx - set to reallocate - NewAllocated - new size for the set, must be at least equal to already - allocated - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_knsreallocate(amdknset* sa, - ae_int_t setidx, - ae_int_t newallocated, - ae_state *_state) -{ - ae_int_t oldbegin; - ae_int_t oldcnt; - ae_int_t newbegin; - ae_int_t j; - - - if( sa->data.cntdataused+amdordering_knsheadersize+newallocated ) - { - amdordering_knscompressstorage(sa, _state); - if( sa->data.cntdataused+amdordering_knsheadersize+newallocated ) - { - ivectorgrowto(&sa->data, sa->dataused+amdordering_knsheadersize+newallocated, _state); - } - } - oldbegin = sa->vbegin.ptr.p_int[setidx]; - oldcnt = sa->vcnt.ptr.p_int[setidx]; - newbegin = sa->dataused+amdordering_knsheadersize; - sa->vbegin.ptr.p_int[setidx] = newbegin; - sa->vallocated.ptr.p_int[setidx] = newallocated; - sa->data.ptr.p_int[oldbegin-1] = -1; - sa->data.ptr.p_int[newbegin-2] = amdordering_knsheadersize+newallocated; - sa->data.ptr.p_int[newbegin-1] = setidx; - sa->dataused = sa->dataused+sa->data.ptr.p_int[newbegin-2]; - for(j=0; j<=oldcnt-1; j++) - { - sa->data.ptr.p_int[newbegin+j] = sa->data.ptr.p_int[oldbegin+j]; - } -} - - -/************************************************************************* -Initialize kn-set - -INPUT PARAMETERS - K - sets count - N - set size - kPrealloc - preallocate place per set (can be zero) - -OUTPUT PARAMETERS - SA - K sets of N elements, initially empty - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_knsinit(ae_int_t k, - ae_int_t n, - ae_int_t kprealloc, - amdknset* sa, - ae_state *_state) -{ - ae_int_t i; - - - sa->k = n; - sa->n = n; - isetallocv(n, -1, &sa->flagarray, _state); - isetallocv(n, kprealloc, &sa->vallocated, _state); - ivectorsetlengthatleast(&sa->vbegin, n, _state); - sa->vbegin.ptr.p_int[0] = amdordering_knsheadersize; - for(i=1; i<=n-1; i++) - { - sa->vbegin.ptr.p_int[i] = sa->vbegin.ptr.p_int[i-1]+sa->vallocated.ptr.p_int[i-1]+amdordering_knsheadersize; - } - sa->dataused = sa->vbegin.ptr.p_int[n-1]+sa->vallocated.ptr.p_int[n-1]; - ivectorsetlengthatleast(&sa->data, sa->dataused, _state); - for(i=0; i<=n-1; i++) - { - sa->data.ptr.p_int[sa->vbegin.ptr.p_int[i]-2] = amdordering_knsheadersize+sa->vallocated.ptr.p_int[i]; - sa->data.ptr.p_int[sa->vbegin.ptr.p_int[i]-1] = i; - } - isetallocv(n, 0, &sa->vcnt, _state); -} - - -/************************************************************************* -Initialize kn-set from lower triangle of symmetric A - -INPUT PARAMETERS - A - lower triangular sparse matrix in CRS format - N - problem size - -OUTPUT PARAMETERS - SA - N sets of N elements, reproducing both lower and upper - triangles of A - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_knsinitfroma(sparsematrix* a, - ae_int_t n, - amdknset* sa, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t jj; - ae_int_t j0; - ae_int_t j1; - - - sa->k = n; - sa->n = n; - isetallocv(n, -1, &sa->flagarray, _state); - ivectorsetlengthatleast(&sa->vallocated, n, _state); - for(i=0; i<=n-1; i++) - { - ae_assert(a->didx.ptr.p_int[i]uidx.ptr.p_int[i], "knsInitFromA: integrity check for diagonal of A failed", _state); - j0 = a->ridx.ptr.p_int[i]; - j1 = a->didx.ptr.p_int[i]-1; - sa->vallocated.ptr.p_int[i] = 1+(j1-j0+1); - for(jj=j0; jj<=j1; jj++) - { - j = a->idx.ptr.p_int[jj]; - sa->vallocated.ptr.p_int[j] = sa->vallocated.ptr.p_int[j]+1; - } - } - ivectorsetlengthatleast(&sa->vbegin, n, _state); - sa->vbegin.ptr.p_int[0] = amdordering_knsheadersize; - for(i=1; i<=n-1; i++) - { - sa->vbegin.ptr.p_int[i] = sa->vbegin.ptr.p_int[i-1]+sa->vallocated.ptr.p_int[i-1]+amdordering_knsheadersize; - } - sa->dataused = sa->vbegin.ptr.p_int[n-1]+sa->vallocated.ptr.p_int[n-1]; - ivectorsetlengthatleast(&sa->data, sa->dataused, _state); - for(i=0; i<=n-1; i++) - { - sa->data.ptr.p_int[sa->vbegin.ptr.p_int[i]-2] = amdordering_knsheadersize+sa->vallocated.ptr.p_int[i]; - sa->data.ptr.p_int[sa->vbegin.ptr.p_int[i]-1] = i; - } - isetallocv(n, 0, &sa->vcnt, _state); - for(i=0; i<=n-1; i++) - { - sa->data.ptr.p_int[sa->vbegin.ptr.p_int[i]+sa->vcnt.ptr.p_int[i]] = i; - sa->vcnt.ptr.p_int[i] = sa->vcnt.ptr.p_int[i]+1; - j0 = a->ridx.ptr.p_int[i]; - j1 = a->didx.ptr.p_int[i]-1; - for(jj=j0; jj<=j1; jj++) - { - j = a->idx.ptr.p_int[jj]; - sa->data.ptr.p_int[sa->vbegin.ptr.p_int[i]+sa->vcnt.ptr.p_int[i]] = j; - sa->data.ptr.p_int[sa->vbegin.ptr.p_int[j]+sa->vcnt.ptr.p_int[j]] = i; - sa->vcnt.ptr.p_int[i] = sa->vcnt.ptr.p_int[i]+1; - sa->vcnt.ptr.p_int[j] = sa->vcnt.ptr.p_int[j]+1; - } - } -} - - -/************************************************************************* -Prepares iteration over I-th set - -INPUT PARAMETERS - SA - kn-set - I - set index - -OUTPUT PARAMETERS - SA - SA ready for repeated calls of knsEnumerate() - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_knsstartenumeration(amdknset* sa, - ae_int_t i, - ae_state *_state) -{ - - - sa->iterrow = i; - sa->iteridx = 0; -} - - -/************************************************************************* -Iterates over I-th set (as specified during recent knsStartEnumeration call). -Subsequent calls return True and set J to new set item until iteration -stops and False is returned. - -INPUT PARAMETERS - SA - kn-set - -OUTPUT PARAMETERS - J - if: - * Result=True - index of element in the set - * Result=False - not set - - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static ae_bool amdordering_knsenumerate(amdknset* sa, - ae_int_t* i, - ae_state *_state) -{ - ae_bool result; - - *i = 0; - - if( sa->iteridxvcnt.ptr.p_int[sa->iterrow] ) - { - *i = sa->data.ptr.p_int[sa->vbegin.ptr.p_int[sa->iterrow]+sa->iteridx]; - sa->iteridx = sa->iteridx+1; - result = ae_true; - } - else - { - result = ae_false; - } - return result; -} - - -/************************************************************************* -Allows direct access to internal storage of kn-set structure - returns -range of elements SA.Data[idxBegin...idxEnd-1] used to store K-th set - -INPUT PARAMETERS - SA - kn-set - K - set index - -OUTPUT PARAMETERS - idxBegin, - idxEnd - half-range [idxBegin,idxEnd) of SA.Data that stores - K-th set - - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_knsdirectaccess(amdknset* sa, - ae_int_t k, - ae_int_t* idxbegin, - ae_int_t* idxend, - ae_state *_state) -{ - - *idxbegin = 0; - *idxend = 0; - - *idxbegin = sa->vbegin.ptr.p_int[k]; - *idxend = *idxbegin+sa->vcnt.ptr.p_int[k]; -} - - -/************************************************************************* -Add K-th element to I-th set. The caller guarantees that the element is -not present in the target set. - -INPUT PARAMETERS - SA - kn-set - I - set index - K - element to add - -OUTPUT PARAMETERS - SA - modified SA - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_knsaddnewelement(amdknset* sa, - ae_int_t i, - ae_int_t k, - ae_state *_state) -{ - ae_int_t cnt; - - - cnt = sa->vcnt.ptr.p_int[i]; - if( cnt==sa->vallocated.ptr.p_int[i] ) - { - amdordering_knsreallocate(sa, i, 2*sa->vallocated.ptr.p_int[i]+1, _state); - } - sa->data.ptr.p_int[sa->vbegin.ptr.p_int[i]+cnt] = k; - sa->vcnt.ptr.p_int[i] = cnt+1; -} - - -/************************************************************************* -Subtracts source n-set from the I-th set of the destination kn-set. - -INPUT PARAMETERS - SA - destination kn-set structure - I - set index in the structure - Src - source n-set - -OUTPUT PARAMETERS - SA - I-th set except for elements in Src - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_knssubtract1(amdknset* sa, - ae_int_t i, - amdnset* src, - ae_state *_state) -{ - ae_int_t j; - ae_int_t idxbegin; - ae_int_t idxend; - ae_int_t cnt; - - - cnt = sa->vcnt.ptr.p_int[i]; - idxbegin = sa->vbegin.ptr.p_int[i]; - idxend = idxbegin+cnt; - while(idxbegindata.ptr.p_int[idxbegin]; - if( src->locationof.ptr.p_int[j]>=0 ) - { - sa->data.ptr.p_int[idxbegin] = sa->data.ptr.p_int[idxend-1]; - idxend = idxend-1; - cnt = cnt-1; - } - else - { - idxbegin = idxbegin+1; - } - } - sa->vcnt.ptr.p_int[i] = cnt; -} - - -/************************************************************************* -Adds Kth set of the source kn-set to the I-th destination set. The caller -guarantees that SA[I] and Src[J] do NOT intersect, i.e. do not have shared -elements - it allows to use faster algorithms. - -INPUT PARAMETERS - SA - destination kn-set structure - I - set index in the structure - Src - source kn-set - K - set index - -OUTPUT PARAMETERS - SA - I-th set plus for elements in K-th set of Src - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_knsaddkthdistinct(amdknset* sa, - ae_int_t i, - amdknset* src, - ae_int_t k, - ae_state *_state) -{ - ae_int_t idxdst; - ae_int_t idxsrcbegin; - ae_int_t cnt; - ae_int_t srccnt; - ae_int_t j; - - - cnt = sa->vcnt.ptr.p_int[i]; - srccnt = src->vcnt.ptr.p_int[k]; - if( cnt+srccnt>sa->vallocated.ptr.p_int[i] ) - { - amdordering_knsreallocate(sa, i, 2*(cnt+srccnt)+1, _state); - } - idxsrcbegin = src->vbegin.ptr.p_int[k]; - idxdst = sa->vbegin.ptr.p_int[i]+cnt; - for(j=0; j<=srccnt-1; j++) - { - sa->data.ptr.p_int[idxdst] = src->data.ptr.p_int[idxsrcbegin+j]; - idxdst = idxdst+1; - } - sa->vcnt.ptr.p_int[i] = cnt+srccnt; -} - - -/************************************************************************* -Counts elements of K-th set of S0 - -INPUT PARAMETERS - S0 - kn-set structure - K - set index in the structure S0 - -RESULT - K-th set element count - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static ae_int_t amdordering_knscountkth(amdknset* s0, - ae_int_t k, - ae_state *_state) -{ - ae_int_t result; - - - result = s0->vcnt.ptr.p_int[k]; - return result; -} - - -/************************************************************************* -Counts elements of I-th set of S0 not present in K-th set of S1 - -INPUT PARAMETERS - S0 - kn-set structure - I - set index in the structure S0 - S1 - kn-set to compare against - K - set index in the structure S1 - -RESULT - count - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static ae_int_t amdordering_knscountnotkth(amdknset* s0, - ae_int_t i, - amdknset* s1, - ae_int_t k, - ae_state *_state) -{ - ae_int_t idxbegin0; - ae_int_t idxbegin1; - ae_int_t cnt0; - ae_int_t cnt1; - ae_int_t j; - ae_int_t result; - - - cnt0 = s0->vcnt.ptr.p_int[i]; - cnt1 = s1->vcnt.ptr.p_int[k]; - idxbegin0 = s0->vbegin.ptr.p_int[i]; - idxbegin1 = s1->vbegin.ptr.p_int[k]; - for(j=0; j<=cnt1-1; j++) - { - s0->flagarray.ptr.p_int[s1->data.ptr.p_int[idxbegin1+j]] = 1; - } - result = 0; - for(j=0; j<=cnt0-1; j++) - { - if( s0->flagarray.ptr.p_int[s0->data.ptr.p_int[idxbegin0+j]]<0 ) - { - result = result+1; - } - } - for(j=0; j<=cnt1-1; j++) - { - s0->flagarray.ptr.p_int[s1->data.ptr.p_int[idxbegin1+j]] = -1; - } - return result; -} - - -/************************************************************************* -Counts elements of I-th set of S0 that are also present in K-th set of S1 - -INPUT PARAMETERS - S0 - kn-set structure - I - set index in the structure S0 - S1 - kn-set to compare against - K - set index in the structure S1 - -RESULT - count - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static ae_int_t amdordering_knscountandkth(amdknset* s0, - ae_int_t i, - amdknset* s1, - ae_int_t k, - ae_state *_state) -{ - ae_int_t idxbegin0; - ae_int_t idxbegin1; - ae_int_t cnt0; - ae_int_t cnt1; - ae_int_t j; - ae_int_t result; - - - cnt0 = s0->vcnt.ptr.p_int[i]; - cnt1 = s1->vcnt.ptr.p_int[k]; - idxbegin0 = s0->vbegin.ptr.p_int[i]; - idxbegin1 = s1->vbegin.ptr.p_int[k]; - for(j=0; j<=cnt1-1; j++) - { - s0->flagarray.ptr.p_int[s1->data.ptr.p_int[idxbegin1+j]] = 1; - } - result = 0; - for(j=0; j<=cnt0-1; j++) - { - if( s0->flagarray.ptr.p_int[s0->data.ptr.p_int[idxbegin0+j]]>0 ) - { - result = result+1; - } - } - for(j=0; j<=cnt1-1; j++) - { - s0->flagarray.ptr.p_int[s1->data.ptr.p_int[idxbegin1+j]] = -1; - } - return result; -} - - -/************************************************************************* -Sums elements in I-th set of S0, returns sum. - -INPUT PARAMETERS - S0 - kn-set structure - I - set index in the structure S0 - -RESULT - sum - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static ae_int_t amdordering_knssumkth(amdknset* s0, - ae_int_t i, - ae_state *_state) -{ - ae_int_t idxbegin0; - ae_int_t cnt0; - ae_int_t j; - ae_int_t result; - - - cnt0 = s0->vcnt.ptr.p_int[i]; - idxbegin0 = s0->vbegin.ptr.p_int[i]; - result = 0; - for(j=0; j<=cnt0-1; j++) - { - result = result+s0->data.ptr.p_int[idxbegin0+j]; - } - return result; -} - - -/************************************************************************* -Clear k-th kn-set in collection. - -Freed memory is NOT reclaimed for future garbage collection. - -INPUT PARAMETERS - SA - kn-set structure - K - set index - -OUTPUT PARAMETERS - SA - K-th set was cleared - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_knsclearkthnoreclaim(amdknset* sa, - ae_int_t k, - ae_state *_state) -{ - - - sa->vcnt.ptr.p_int[k] = 0; -} - - -/************************************************************************* -Clear k-th kn-set in collection. - -Freed memory is reclaimed for future garbage collection. This function is -NOT recommended if you intend to add elements to this set in some future, -because every addition will result in reallocation of previously freed -memory. Use knsClearKthNoReclaim(). - -INPUT PARAMETERS - SA - kn-set structure - K - set index - -OUTPUT PARAMETERS - SA - K-th set was cleared - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_knsclearkthreclaim(amdknset* sa, - ae_int_t k, - ae_state *_state) -{ - ae_int_t idxbegin; - ae_int_t allocated; - - - idxbegin = sa->vbegin.ptr.p_int[k]; - allocated = sa->vallocated.ptr.p_int[k]; - sa->vcnt.ptr.p_int[k] = 0; - if( allocated>=amdordering_knsheadersize ) - { - sa->data.ptr.p_int[idxbegin-2] = 2; - sa->data.ptr.p_int[idxbegin+0] = allocated; - sa->data.ptr.p_int[idxbegin+1] = -1; - sa->vallocated.ptr.p_int[k] = 0; - } -} - - -/************************************************************************* -Initialize linked list matrix - -INPUT PARAMETERS - N - matrix size - -OUTPUT PARAMETERS - A - NxN linked list matrix - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_mtxinit(ae_int_t n, - amdllmatrix* a, - ae_state *_state) -{ - - - a->n = n; - isetallocv(2*n+1, -1, &a->vbegin, _state); - isetallocv(n, 0, &a->vcolcnt, _state); - a->entriesinitialized = 0; -} - - -/************************************************************************* -Adds column from matrix to n-set - -INPUT PARAMETERS - A - NxN linked list matrix - J - column index to add - S - target n-set - -OUTPUT PARAMETERS - S - elements from J-th column are added to S - - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_mtxaddcolumnto(amdllmatrix* a, - ae_int_t j, - amdnset* s, - ae_state *_state) -{ - ae_int_t n; - ae_int_t eidx; - - - n = a->n; - eidx = a->vbegin.ptr.p_int[n+j]; - while(eidx>=0) - { - amdordering_nsaddelement(s, a->entries.ptr.p_int[eidx*amdordering_llmentrysize+4], _state); - eidx = a->entries.ptr.p_int[eidx*amdordering_llmentrysize+3]; - } -} - - -/************************************************************************* -Inserts new element into column J, row I. The caller guarantees that the -element being inserted is NOT already present in the matrix. - -INPUT PARAMETERS - A - NxN linked list matrix - I - row index - J - column index - -OUTPUT PARAMETERS - A - element (I,J) added to the list. - - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_mtxinsertnewelement(amdllmatrix* a, - ae_int_t i, - ae_int_t j, - ae_state *_state) -{ - ae_int_t n; - ae_int_t k; - ae_int_t newsize; - ae_int_t eidx; - ae_int_t offs; - - - n = a->n; - if( a->vbegin.ptr.p_int[2*n]<0 ) - { - newsize = 2*a->entriesinitialized+1; - ivectorresize(&a->entries, newsize*amdordering_llmentrysize, _state); - for(k=a->entriesinitialized; k<=newsize-2; k++) - { - a->entries.ptr.p_int[k*amdordering_llmentrysize+0] = k+1; - } - a->entries.ptr.p_int[(newsize-1)*amdordering_llmentrysize+0] = a->vbegin.ptr.p_int[2*n]; - a->vbegin.ptr.p_int[2*n] = a->entriesinitialized; - a->entriesinitialized = newsize; - } - eidx = a->vbegin.ptr.p_int[2*n]; - offs = eidx*amdordering_llmentrysize; - a->vbegin.ptr.p_int[2*n] = a->entries.ptr.p_int[offs+0]; - a->entries.ptr.p_int[offs+0] = -1; - a->entries.ptr.p_int[offs+1] = a->vbegin.ptr.p_int[i]; - if( a->vbegin.ptr.p_int[i]>=0 ) - { - a->entries.ptr.p_int[a->vbegin.ptr.p_int[i]*amdordering_llmentrysize+0] = eidx; - } - a->entries.ptr.p_int[offs+2] = -1; - a->entries.ptr.p_int[offs+3] = a->vbegin.ptr.p_int[j+n]; - if( a->vbegin.ptr.p_int[j+n]>=0 ) - { - a->entries.ptr.p_int[a->vbegin.ptr.p_int[j+n]*amdordering_llmentrysize+2] = eidx; - } - a->entries.ptr.p_int[offs+4] = i; - a->entries.ptr.p_int[offs+5] = j; - a->vbegin.ptr.p_int[i] = eidx; - a->vbegin.ptr.p_int[j+n] = eidx; - a->vcolcnt.ptr.p_int[j] = a->vcolcnt.ptr.p_int[j]+1; -} - - -/************************************************************************* -Counts elements in J-th column - -INPUT PARAMETERS - A - NxN linked list matrix - J - column index - -RESULT - element count - - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static ae_int_t amdordering_mtxcountcolumn(amdllmatrix* a, - ae_int_t j, - ae_state *_state) -{ - ae_int_t result; - - - result = a->vcolcnt.ptr.p_int[j]; - return result; -} - - -/************************************************************************* -Clears K-th column or row - -INPUT PARAMETERS - A - NxN linked list matrix - K - column/row index to clear - IsCol - whether we want to clear row or column - -OUTPUT PARAMETERS - A - K-th column or row is empty - - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_mtxclearx(amdllmatrix* a, - ae_int_t k, - ae_bool iscol, - ae_state *_state) -{ - ae_int_t n; - ae_int_t eidx; - ae_int_t enext; - ae_int_t idxprev; - ae_int_t idxnext; - ae_int_t idxr; - ae_int_t idxc; - - - n = a->n; - if( iscol ) - { - eidx = a->vbegin.ptr.p_int[n+k]; - } - else - { - eidx = a->vbegin.ptr.p_int[k]; - } - while(eidx>=0) - { - idxr = a->entries.ptr.p_int[eidx*amdordering_llmentrysize+4]; - idxc = a->entries.ptr.p_int[eidx*amdordering_llmentrysize+5]; - if( iscol ) - { - enext = a->entries.ptr.p_int[eidx*amdordering_llmentrysize+3]; - } - else - { - enext = a->entries.ptr.p_int[eidx*amdordering_llmentrysize+1]; - } - idxprev = a->entries.ptr.p_int[eidx*amdordering_llmentrysize+0]; - idxnext = a->entries.ptr.p_int[eidx*amdordering_llmentrysize+1]; - if( idxprev>=0 ) - { - a->entries.ptr.p_int[idxprev*amdordering_llmentrysize+1] = idxnext; - } - else - { - a->vbegin.ptr.p_int[idxr] = idxnext; - } - if( idxnext>=0 ) - { - a->entries.ptr.p_int[idxnext*amdordering_llmentrysize+0] = idxprev; - } - idxprev = a->entries.ptr.p_int[eidx*amdordering_llmentrysize+2]; - idxnext = a->entries.ptr.p_int[eidx*amdordering_llmentrysize+3]; - if( idxprev>=0 ) - { - a->entries.ptr.p_int[idxprev*amdordering_llmentrysize+3] = idxnext; - } - else - { - a->vbegin.ptr.p_int[idxc+n] = idxnext; - } - if( idxnext>=0 ) - { - a->entries.ptr.p_int[idxnext*amdordering_llmentrysize+2] = idxprev; - } - a->entries.ptr.p_int[eidx*amdordering_llmentrysize+0] = a->vbegin.ptr.p_int[2*n]; - a->vbegin.ptr.p_int[2*n] = eidx; - eidx = enext; - if( !iscol ) - { - a->vcolcnt.ptr.p_int[idxc] = a->vcolcnt.ptr.p_int[idxc]-1; - } - } - if( iscol ) - { - a->vcolcnt.ptr.p_int[k] = 0; - } -} - - -/************************************************************************* -Clears J-th column - -INPUT PARAMETERS - A - NxN linked list matrix - J - column index to clear - -OUTPUT PARAMETERS - A - J-th column is empty - - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_mtxclearcolumn(amdllmatrix* a, - ae_int_t j, - ae_state *_state) -{ - - - amdordering_mtxclearx(a, j, ae_true, _state); -} - - -/************************************************************************* -Clears J-th row - -INPUT PARAMETERS - A - NxN linked list matrix - J - row index to clear - -OUTPUT PARAMETERS - A - J-th row is empty - - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_mtxclearrow(amdllmatrix* a, - ae_int_t j, - ae_state *_state) -{ - - - amdordering_mtxclearx(a, j, ae_false, _state); -} - - -/************************************************************************* -Initialize vertex storage using A to estimate initial degrees - -INPUT PARAMETERS - A - NxN lower triangular sparse CRS matrix - N - problem size - CheckExactDegrees- - whether we want to maintain additional exact degress - (the search is still done using approximate ones) - -OUTPUT PARAMETERS - S - vertex set - - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_vtxinit(sparsematrix* a, - ae_int_t n, - ae_bool checkexactdegrees, - amdvertexset* s, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t jj; - ae_int_t j0; - ae_int_t j1; - - _amdvertexset_clear(s); - - s->n = n; - s->checkexactdegrees = checkexactdegrees; - s->smallestdegree = 0; - bsetallocv(n, ae_true, &s->isvertex, _state); - isetallocv(n, 0, &s->approxd, _state); - for(i=0; i<=n-1; i++) - { - j0 = a->ridx.ptr.p_int[i]; - j1 = a->didx.ptr.p_int[i]-1; - s->approxd.ptr.p_int[i] = j1-j0+1; - for(jj=j0; jj<=j1; jj++) - { - j = a->idx.ptr.p_int[jj]; - s->approxd.ptr.p_int[j] = s->approxd.ptr.p_int[j]+1; - } - } - if( checkexactdegrees ) - { - icopyallocv(n, &s->approxd, &s->optionalexactd, _state); - } - isetallocv(n, -1, &s->vbegin, _state); - isetallocv(n, -1, &s->vprev, _state); - isetallocv(n, -1, &s->vnext, _state); - for(i=0; i<=n-1; i++) - { - j = s->approxd.ptr.p_int[i]; - j0 = s->vbegin.ptr.p_int[j]; - s->vbegin.ptr.p_int[j] = i; - s->vnext.ptr.p_int[i] = j0; - s->vprev.ptr.p_int[i] = -1; - if( j0>=0 ) - { - s->vprev.ptr.p_int[j0] = i; - } - } -} - - -/************************************************************************* -Removes vertex from the storage - -INPUT PARAMETERS - S - vertex set - P - vertex to be removed - -OUTPUT PARAMETERS - S - modified - - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_vtxremovevertex(amdvertexset* s, - ae_int_t p, - ae_state *_state) -{ - ae_int_t d; - ae_int_t idxprev; - ae_int_t idxnext; - - - d = s->approxd.ptr.p_int[p]; - idxprev = s->vprev.ptr.p_int[p]; - idxnext = s->vnext.ptr.p_int[p]; - if( idxprev>=0 ) - { - s->vnext.ptr.p_int[idxprev] = idxnext; - } - else - { - s->vbegin.ptr.p_int[d] = idxnext; - } - if( idxnext>=0 ) - { - s->vprev.ptr.p_int[idxnext] = idxprev; - } - s->isvertex.ptr.p_bool[p] = ae_false; - s->approxd.ptr.p_int[p] = -9999999; - if( s->checkexactdegrees ) - { - s->optionalexactd.ptr.p_int[p] = -9999999; - } -} - - -/************************************************************************* -Get approximate degree. Result is undefined for removed vertexes. - -INPUT PARAMETERS - S - vertex set - P - vertex index - -RESULT - vertex degree - - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static ae_int_t amdordering_vtxgetapprox(amdvertexset* s, - ae_int_t p, - ae_state *_state) -{ - ae_int_t result; - - - result = s->approxd.ptr.p_int[p]; - return result; -} - - -/************************************************************************* -Get exact degree (or 0, if not supported). Result is undefined for -removed vertexes. - -INPUT PARAMETERS - S - vertex set - P - vertex index - -RESULT - vertex degree - - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static ae_int_t amdordering_vtxgetexact(amdvertexset* s, - ae_int_t p, - ae_state *_state) -{ - ae_int_t result; - - - if( s->checkexactdegrees ) - { - result = s->optionalexactd.ptr.p_int[p]; - } - else - { - result = 0; - } - return result; -} - - -/************************************************************************* -Returns index of vertex with minimum approximate degree, or -1 when there -is no vertex. - -INPUT PARAMETERS - S - vertex set - -RESULT - vertex index, or -1 - - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static ae_int_t amdordering_vtxgetapproxmindegree(amdvertexset* s, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - ae_int_t result; - - - n = s->n; - result = -1; - for(i=s->smallestdegree; i<=n-1; i++) - { - if( s->vbegin.ptr.p_int[i]>=0 ) - { - s->smallestdegree = i; - result = s->vbegin.ptr.p_int[i]; - return result; - } - } - return result; -} - - -/************************************************************************* -Update approximate degree - -INPUT PARAMETERS - S - vertex set - P - vertex to be updated - DNew - new degree - -OUTPUT PARAMETERS - S - modified - - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_vtxupdateapproximatedegree(amdvertexset* s, - ae_int_t p, - ae_int_t dnew, - ae_state *_state) -{ - ae_int_t dold; - ae_int_t idxprev; - ae_int_t idxnext; - ae_int_t oldbegin; - - - dold = s->approxd.ptr.p_int[p]; - if( dold==dnew ) - { - return; - } - idxprev = s->vprev.ptr.p_int[p]; - idxnext = s->vnext.ptr.p_int[p]; - if( idxprev>=0 ) - { - s->vnext.ptr.p_int[idxprev] = idxnext; - } - else - { - s->vbegin.ptr.p_int[dold] = idxnext; - } - if( idxnext>=0 ) - { - s->vprev.ptr.p_int[idxnext] = idxprev; - } - oldbegin = s->vbegin.ptr.p_int[dnew]; - s->vbegin.ptr.p_int[dnew] = p; - s->vnext.ptr.p_int[p] = oldbegin; - s->vprev.ptr.p_int[p] = -1; - if( oldbegin>=0 ) - { - s->vprev.ptr.p_int[oldbegin] = p; - } - s->approxd.ptr.p_int[p] = dnew; - if( dnewsmallestdegree ) - { - s->smallestdegree = dnew; - } -} - - -/************************************************************************* -Update optional exact degree. Silently returns if vertex set does not store -exact degrees. - -INPUT PARAMETERS - S - vertex set - P - vertex to be updated - D - new degree - -OUTPUT PARAMETERS - S - modified - - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_vtxupdateexactdegree(amdvertexset* s, - ae_int_t p, - ae_int_t d, - ae_state *_state) -{ - - - if( !s->checkexactdegrees ) - { - return; - } - s->optionalexactd.ptr.p_int[p] = d; -} - - -/************************************************************************* -This function selects K-th pivot with minimum approximate degree and -generates permutation that reorders variable to the K-th position in the -matrix. - -Due to supernodal structure of the matrix more than one pivot variable can -be selected and moved to the beginning. The actual count of pivots selected -is returned in NodeSize. - -INPUT PARAMETERS - Buf - properly initialized buffer object - K - pivot index - -OUTPUT PARAMETERS - Buf.Perm - entries [K,K+NodeSize) are initialized by permutation - Buf.InvPerm - entries [K,K+NodeSize) are initialized by permutation - Buf.ColumnSwaps-entries [K,K+NodeSize) are initialized by permutation - P - pivot supervariable - NodeSize - supernode size - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_amdselectpivotelement(amdbuffer* buf, - ae_int_t k, - ae_int_t* p, - ae_int_t* nodesize, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - *p = 0; - *nodesize = 0; - - *p = amdordering_vtxgetapproxmindegree(&buf->vertexdegrees, _state); - ae_assert(*p>=0, "GenerateAMDPermutation: integrity check 3634 failed", _state); - ae_assert(amdordering_vtxgetapprox(&buf->vertexdegrees, *p, _state)>=0, "integrity check RDFD2 failed", _state); - *nodesize = 0; - amdordering_knsstartenumeration(&buf->setsuper, *p, _state); - while(amdordering_knsenumerate(&buf->setsuper, &j, _state)) - { - i = buf->perm.ptr.p_int[j]; - buf->columnswaps.ptr.p_int[k+(*nodesize)] = i; - buf->invperm.ptr.p_int[i] = buf->invperm.ptr.p_int[k+(*nodesize)]; - buf->invperm.ptr.p_int[k+(*nodesize)] = j; - buf->perm.ptr.p_int[buf->invperm.ptr.p_int[i]] = i; - buf->perm.ptr.p_int[buf->invperm.ptr.p_int[k+(*nodesize)]] = k+(*nodesize); - inc(nodesize, _state); - } - ae_assert(amdordering_vtxgetapprox(&buf->vertexdegrees, *p, _state)>=0&&(!buf->checkexactdegrees||amdordering_vtxgetexact(&buf->vertexdegrees, *p, _state)>=0), "AMD: integrity check RDFD failed", _state); -} - - -/************************************************************************* -This function computes nonzero pattern of Lp, the column that is added to -the lower triangular Cholesky factor. - -INPUT PARAMETERS - Buf - properly initialized buffer object - P - pivot column - -OUTPUT PARAMETERS - Buf.Lp - initialized with Lp - Buf.PLp - initialized with setSuper[P]+Lp - Buf.Ep - initialized with setE[P] - Buf.mtxL - L := L+Lp - Buf.Ls - first Buf.LSCnt elements contain subset of Lp elements - that are principal nodes in supervariables. - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_amdcomputelp(amdbuffer* buf, - ae_int_t p, - ae_state *_state) -{ - ae_int_t i; - - - amdordering_nsclear(&buf->lp, _state); - amdordering_nsaddkth(&buf->lp, &buf->seta, p, _state); - amdordering_knsstartenumeration(&buf->sete, p, _state); - while(amdordering_knsenumerate(&buf->sete, &i, _state)) - { - amdordering_mtxaddcolumnto(&buf->mtxl, i, &buf->lp, _state); - } - amdordering_nssubtractkth(&buf->lp, &buf->setsuper, p, _state); - buf->lscnt = 0; - amdordering_nsstartenumeration(&buf->lp, _state); - while(amdordering_nsenumerate(&buf->lp, &i, _state)) - { - ae_assert(!buf->iseliminated.ptr.p_bool[i], "AMD: integrity check 0740 failed", _state); - amdordering_mtxinsertnewelement(&buf->mtxl, i, p, _state); - if( buf->issupernode.ptr.p_bool[i] ) - { - buf->ls.ptr.p_int[buf->lscnt] = i; - buf->lscnt = buf->lscnt+1; - } - } - amdordering_nscopy(&buf->lp, &buf->plp, _state); - amdordering_nsaddkth(&buf->plp, &buf->setsuper, p, _state); - amdordering_nsclear(&buf->ep, _state); - amdordering_nsaddkth(&buf->ep, &buf->sete, p, _state); -} - - -/************************************************************************* -Having output of AMDComputeLp() in the Buf object, this function performs -mass elimination in the quotient graph. - -INPUT PARAMETERS - Buf - properly initialized buffer object - P - pivot column - K - number of already eliminated columns (P-th is not counted) - -OUTPUT PARAMETERS - Buf.setA - Lp is eliminated from setA - Buf.setE - Ep is eliminated from setE, P is added - approxD - updated - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_amdmasselimination(amdbuffer* buf, - ae_int_t p, - ae_int_t k, - ae_state *_state) -{ - ae_int_t n; - ae_int_t lidx; - ae_int_t lpi; - ae_int_t cntsuperi; - ae_int_t cntainoti; - ae_int_t cntlpnoti; - ae_int_t cc; - ae_int_t j; - ae_int_t e; - ae_int_t we; - ae_int_t cnttoclean; - ae_int_t idxbegin; - ae_int_t idxend; - ae_int_t jj; - - - n = buf->n; - ivectorsetlengthatleast(&buf->tmp0, n, _state); - cnttoclean = 0; - for(lidx=0; lidx<=buf->lscnt-1; lidx++) - { - lpi = buf->ls.ptr.p_int[lidx]; - cntsuperi = amdordering_knscountkth(&buf->setsuper, lpi, _state); - amdordering_knsdirectaccess(&buf->sete, lpi, &idxbegin, &idxend, _state); - for(jj=idxbegin; jj<=idxend-1; jj++) - { - e = buf->sete.data.ptr.p_int[jj]; - we = buf->arrwe.ptr.p_int[e]; - if( we<0 ) - { - we = amdordering_mtxcountcolumn(&buf->mtxl, e, _state); - buf->tmp0.ptr.p_int[cnttoclean] = e; - cnttoclean = cnttoclean+1; - } - buf->arrwe.ptr.p_int[e] = we-cntsuperi; - } - } - for(lidx=0; lidx<=buf->lscnt-1; lidx++) - { - lpi = buf->ls.ptr.p_int[lidx]; - amdordering_knssubtract1(&buf->seta, lpi, &buf->plp, _state); - amdordering_knssubtract1(&buf->sete, lpi, &buf->ep, _state); - amdordering_knsaddnewelement(&buf->sete, lpi, p, _state); - if( buf->extendeddebug ) - { - ae_assert(amdordering_knscountnotkth(&buf->seta, lpi, &buf->setsuper, lpi, _state)==amdordering_knscountkth(&buf->seta, lpi, _state), "AMD: integrity check 454F failed", _state); - ae_assert(amdordering_knscountandkth(&buf->seta, lpi, &buf->setsuper, lpi, _state)==0, "AMD: integrity check kl5nv failed", _state); - ae_assert(amdordering_nscountandkth(&buf->lp, &buf->setsuper, lpi, _state)==amdordering_knscountkth(&buf->setsuper, lpi, _state), "AMD: integrity check 8463 failed", _state); - } - cntainoti = amdordering_knscountkth(&buf->seta, lpi, _state); - cntlpnoti = amdordering_nscount(&buf->lp, _state)-amdordering_knscountkth(&buf->setsuper, lpi, _state); - cc = 0; - amdordering_knsdirectaccess(&buf->sete, lpi, &idxbegin, &idxend, _state); - for(jj=idxbegin; jj<=idxend-1; jj++) - { - j = buf->sete.data.ptr.p_int[jj]; - if( j==p ) - { - continue; - } - e = buf->arrwe.ptr.p_int[j]; - if( e<0 ) - { - e = amdordering_mtxcountcolumn(&buf->mtxl, j, _state); - } - cc = cc+e; - } - amdordering_vtxupdateapproximatedegree(&buf->vertexdegrees, lpi, imin3(n-k, amdordering_vtxgetapprox(&buf->vertexdegrees, lpi, _state)+cntlpnoti, cntainoti+cntlpnoti+cc, _state), _state); - if( buf->checkexactdegrees ) - { - amdordering_nsclear(&buf->exactdegreetmp0, _state); - amdordering_knsstartenumeration(&buf->sete, lpi, _state); - while(amdordering_knsenumerate(&buf->sete, &j, _state)) - { - amdordering_mtxaddcolumnto(&buf->mtxl, j, &buf->exactdegreetmp0, _state); - } - amdordering_vtxupdateexactdegree(&buf->vertexdegrees, lpi, cntainoti+amdordering_nscountnotkth(&buf->exactdegreetmp0, &buf->setsuper, lpi, _state), _state); - ae_assert(amdordering_knscountkth(&buf->sete, lpi, _state)>2||amdordering_vtxgetapprox(&buf->vertexdegrees, lpi, _state)==amdordering_vtxgetexact(&buf->vertexdegrees, lpi, _state), "AMD: integrity check 7206 failed", _state); - ae_assert(amdordering_vtxgetapprox(&buf->vertexdegrees, lpi, _state)>=amdordering_vtxgetexact(&buf->vertexdegrees, lpi, _state), "AMD: integrity check 8206 failed", _state); - } - } - for(j=0; j<=cnttoclean-1; j++) - { - buf->arrwe.ptr.p_int[buf->tmp0.ptr.p_int[j]] = -1; - } -} - - -/************************************************************************* -After mass elimination, but before removal of vertex P, we may perform -supernode detection. Only variables/supernodes in Lp (P itself is NOT -included) can be merged into larger supernodes. - -INPUT PARAMETERS - Buf - properly initialized buffer object - -OUTPUT PARAMETERS - Buf - following fields of Buf may be modified: - * Buf.setSuper - * Buf.setA - * Buf.setE - * Buf.IsSupernode - * ApproxD and ExactD - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void amdordering_amddetectsupernodes(amdbuffer* buf, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t cnt; - ae_int_t lpi; - ae_int_t lpj; - ae_int_t nj; - ae_int_t hashi; - - - n = buf->n; - ivectorsetlengthatleast(&buf->sncandidates, n, _state); - if( buf->lscnt<2 ) - { - return; - } - for(i=0; i<=buf->lscnt-1; i++) - { - lpi = buf->ls.ptr.p_int[i]; - hashi = (amdordering_knssumkth(&buf->seta, lpi, _state)+amdordering_knssumkth(&buf->sete, lpi, _state))%n; - amdordering_nsaddelement(&buf->nonemptybuckets, hashi, _state); - amdordering_knsaddnewelement(&buf->hashbuckets, hashi, lpi, _state); - } - amdordering_nsstartenumeration(&buf->nonemptybuckets, _state); - while(amdordering_nsenumerate(&buf->nonemptybuckets, &hashi, _state)) - { - if( amdordering_knscountkth(&buf->hashbuckets, hashi, _state)>=2 ) - { - cnt = 0; - amdordering_knsstartenumeration(&buf->hashbuckets, hashi, _state); - while(amdordering_knsenumerate(&buf->hashbuckets, &i, _state)) - { - buf->sncandidates.ptr.p_int[cnt] = i; - cnt = cnt+1; - } - for(i=cnt-1; i>=0; i--) - { - for(j=cnt-1; j>=i+1; j--) - { - if( buf->issupernode.ptr.p_bool[buf->sncandidates.ptr.p_int[i]]&&buf->issupernode.ptr.p_bool[buf->sncandidates.ptr.p_int[j]] ) - { - lpi = buf->sncandidates.ptr.p_int[i]; - lpj = buf->sncandidates.ptr.p_int[j]; - amdordering_nsclear(&buf->adji, _state); - amdordering_nsclear(&buf->adjj, _state); - amdordering_nsaddkth(&buf->adji, &buf->seta, lpi, _state); - amdordering_nsaddkth(&buf->adjj, &buf->seta, lpj, _state); - amdordering_nsaddkth(&buf->adji, &buf->sete, lpi, _state); - amdordering_nsaddkth(&buf->adjj, &buf->sete, lpj, _state); - amdordering_nsaddelement(&buf->adji, lpi, _state); - amdordering_nsaddelement(&buf->adji, lpj, _state); - amdordering_nsaddelement(&buf->adjj, lpi, _state); - amdordering_nsaddelement(&buf->adjj, lpj, _state); - if( !amdordering_nsequal(&buf->adji, &buf->adjj, _state) ) - { - continue; - } - if( buf->extendeddebug ) - { - ae_assert(amdordering_vtxgetapprox(&buf->vertexdegrees, lpi, _state)>=1&&(!buf->checkexactdegrees||amdordering_vtxgetexact(&buf->vertexdegrees, lpi, _state)>=1), "AMD: integrity check &GBFF1 failed", _state); - ae_assert(amdordering_vtxgetapprox(&buf->vertexdegrees, lpj, _state)>=1&&(!buf->checkexactdegrees||amdordering_vtxgetexact(&buf->vertexdegrees, lpj, _state)>=1), "AMD: integrity check &GBFF2 failed", _state); - ae_assert(amdordering_knscountandkth(&buf->setsuper, lpi, &buf->setsuper, lpj, _state)==0, "AMD: integrity check &GBFF3 failed", _state); - } - nj = amdordering_knscountkth(&buf->setsuper, lpj, _state); - amdordering_knsaddkthdistinct(&buf->setsuper, lpi, &buf->setsuper, lpj, _state); - amdordering_knsclearkthreclaim(&buf->setsuper, lpj, _state); - amdordering_knsclearkthreclaim(&buf->seta, lpj, _state); - amdordering_knsclearkthreclaim(&buf->sete, lpj, _state); - buf->issupernode.ptr.p_bool[lpj] = ae_false; - amdordering_vtxremovevertex(&buf->vertexdegrees, lpj, _state); - amdordering_vtxupdateapproximatedegree(&buf->vertexdegrees, lpi, amdordering_vtxgetapprox(&buf->vertexdegrees, lpi, _state)-nj, _state); - if( buf->checkexactdegrees ) - { - amdordering_vtxupdateexactdegree(&buf->vertexdegrees, lpi, amdordering_vtxgetexact(&buf->vertexdegrees, lpi, _state)-nj, _state); - } - } - } - } - } - amdordering_knsclearkthnoreclaim(&buf->hashbuckets, hashi, _state); - } - amdordering_nsclear(&buf->nonemptybuckets, _state); -} - - -void _amdnset_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - amdnset *p = (amdnset*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->items, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->locationof, 0, DT_INT, _state, make_automatic); -} - - -void _amdnset_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - amdnset *dst = (amdnset*)_dst; - amdnset *src = (amdnset*)_src; - dst->n = src->n; - dst->nstored = src->nstored; - ae_vector_init_copy(&dst->items, &src->items, _state, make_automatic); - ae_vector_init_copy(&dst->locationof, &src->locationof, _state, make_automatic); - dst->iteridx = src->iteridx; -} - - -void _amdnset_clear(void* _p) -{ - amdnset *p = (amdnset*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->items); - ae_vector_clear(&p->locationof); -} - - -void _amdnset_destroy(void* _p) -{ - amdnset *p = (amdnset*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->items); - ae_vector_destroy(&p->locationof); -} - - -void _amdknset_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - amdknset *p = (amdknset*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->flagarray, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->vbegin, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->vallocated, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->vcnt, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->data, 0, DT_INT, _state, make_automatic); -} - - -void _amdknset_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - amdknset *dst = (amdknset*)_dst; - amdknset *src = (amdknset*)_src; - dst->k = src->k; - dst->n = src->n; - ae_vector_init_copy(&dst->flagarray, &src->flagarray, _state, make_automatic); - ae_vector_init_copy(&dst->vbegin, &src->vbegin, _state, make_automatic); - ae_vector_init_copy(&dst->vallocated, &src->vallocated, _state, make_automatic); - ae_vector_init_copy(&dst->vcnt, &src->vcnt, _state, make_automatic); - ae_vector_init_copy(&dst->data, &src->data, _state, make_automatic); - dst->dataused = src->dataused; - dst->iterrow = src->iterrow; - dst->iteridx = src->iteridx; -} - - -void _amdknset_clear(void* _p) -{ - amdknset *p = (amdknset*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->flagarray); - ae_vector_clear(&p->vbegin); - ae_vector_clear(&p->vallocated); - ae_vector_clear(&p->vcnt); - ae_vector_clear(&p->data); -} - - -void _amdknset_destroy(void* _p) -{ - amdknset *p = (amdknset*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->flagarray); - ae_vector_destroy(&p->vbegin); - ae_vector_destroy(&p->vallocated); - ae_vector_destroy(&p->vcnt); - ae_vector_destroy(&p->data); -} - - -void _amdvertexset_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - amdvertexset *p = (amdvertexset*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->approxd, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->optionalexactd, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->isvertex, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->vbegin, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->vprev, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->vnext, 0, DT_INT, _state, make_automatic); -} - - -void _amdvertexset_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - amdvertexset *dst = (amdvertexset*)_dst; - amdvertexset *src = (amdvertexset*)_src; - dst->n = src->n; - dst->checkexactdegrees = src->checkexactdegrees; - dst->smallestdegree = src->smallestdegree; - ae_vector_init_copy(&dst->approxd, &src->approxd, _state, make_automatic); - ae_vector_init_copy(&dst->optionalexactd, &src->optionalexactd, _state, make_automatic); - ae_vector_init_copy(&dst->isvertex, &src->isvertex, _state, make_automatic); - ae_vector_init_copy(&dst->vbegin, &src->vbegin, _state, make_automatic); - ae_vector_init_copy(&dst->vprev, &src->vprev, _state, make_automatic); - ae_vector_init_copy(&dst->vnext, &src->vnext, _state, make_automatic); -} - - -void _amdvertexset_clear(void* _p) -{ - amdvertexset *p = (amdvertexset*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->approxd); - ae_vector_clear(&p->optionalexactd); - ae_vector_clear(&p->isvertex); - ae_vector_clear(&p->vbegin); - ae_vector_clear(&p->vprev); - ae_vector_clear(&p->vnext); -} - - -void _amdvertexset_destroy(void* _p) -{ - amdvertexset *p = (amdvertexset*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->approxd); - ae_vector_destroy(&p->optionalexactd); - ae_vector_destroy(&p->isvertex); - ae_vector_destroy(&p->vbegin); - ae_vector_destroy(&p->vprev); - ae_vector_destroy(&p->vnext); -} - - -void _amdllmatrix_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - amdllmatrix *p = (amdllmatrix*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->vbegin, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->vcolcnt, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->entries, 0, DT_INT, _state, make_automatic); -} - - -void _amdllmatrix_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - amdllmatrix *dst = (amdllmatrix*)_dst; - amdllmatrix *src = (amdllmatrix*)_src; - dst->n = src->n; - ae_vector_init_copy(&dst->vbegin, &src->vbegin, _state, make_automatic); - ae_vector_init_copy(&dst->vcolcnt, &src->vcolcnt, _state, make_automatic); - ae_vector_init_copy(&dst->entries, &src->entries, _state, make_automatic); - dst->entriesinitialized = src->entriesinitialized; -} - - -void _amdllmatrix_clear(void* _p) -{ - amdllmatrix *p = (amdllmatrix*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->vbegin); - ae_vector_clear(&p->vcolcnt); - ae_vector_clear(&p->entries); -} - - -void _amdllmatrix_destroy(void* _p) -{ - amdllmatrix *p = (amdllmatrix*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->vbegin); - ae_vector_destroy(&p->vcolcnt); - ae_vector_destroy(&p->entries); -} - - -void _amdbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - amdbuffer *p = (amdbuffer*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->iseliminated, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->issupernode, 0, DT_BOOL, _state, make_automatic); - _amdknset_init(&p->setsuper, _state, make_automatic); - _amdknset_init(&p->seta, _state, make_automatic); - _amdknset_init(&p->sete, _state, make_automatic); - _amdllmatrix_init(&p->mtxl, _state, make_automatic); - _amdvertexset_init(&p->vertexdegrees, _state, make_automatic); - ae_vector_init(&p->perm, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->invperm, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->columnswaps, 0, DT_INT, _state, make_automatic); - _amdnset_init(&p->lp, _state, make_automatic); - _amdnset_init(&p->plp, _state, make_automatic); - _amdnset_init(&p->ep, _state, make_automatic); - _amdnset_init(&p->adji, _state, make_automatic); - _amdnset_init(&p->adjj, _state, make_automatic); - ae_vector_init(&p->ls, 0, DT_INT, _state, make_automatic); - _amdnset_init(&p->exactdegreetmp0, _state, make_automatic); - _amdknset_init(&p->hashbuckets, _state, make_automatic); - _amdnset_init(&p->nonemptybuckets, _state, make_automatic); - ae_vector_init(&p->sncandidates, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->arrwe, 0, DT_INT, _state, make_automatic); - ae_matrix_init(&p->dbga, 0, 0, DT_REAL, _state, make_automatic); -} - - -void _amdbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - amdbuffer *dst = (amdbuffer*)_dst; - amdbuffer *src = (amdbuffer*)_src; - dst->n = src->n; - dst->extendeddebug = src->extendeddebug; - dst->checkexactdegrees = src->checkexactdegrees; - ae_vector_init_copy(&dst->iseliminated, &src->iseliminated, _state, make_automatic); - ae_vector_init_copy(&dst->issupernode, &src->issupernode, _state, make_automatic); - _amdknset_init_copy(&dst->setsuper, &src->setsuper, _state, make_automatic); - _amdknset_init_copy(&dst->seta, &src->seta, _state, make_automatic); - _amdknset_init_copy(&dst->sete, &src->sete, _state, make_automatic); - _amdllmatrix_init_copy(&dst->mtxl, &src->mtxl, _state, make_automatic); - _amdvertexset_init_copy(&dst->vertexdegrees, &src->vertexdegrees, _state, make_automatic); - ae_vector_init_copy(&dst->perm, &src->perm, _state, make_automatic); - ae_vector_init_copy(&dst->invperm, &src->invperm, _state, make_automatic); - ae_vector_init_copy(&dst->columnswaps, &src->columnswaps, _state, make_automatic); - _amdnset_init_copy(&dst->lp, &src->lp, _state, make_automatic); - _amdnset_init_copy(&dst->plp, &src->plp, _state, make_automatic); - _amdnset_init_copy(&dst->ep, &src->ep, _state, make_automatic); - _amdnset_init_copy(&dst->adji, &src->adji, _state, make_automatic); - _amdnset_init_copy(&dst->adjj, &src->adjj, _state, make_automatic); - ae_vector_init_copy(&dst->ls, &src->ls, _state, make_automatic); - dst->lscnt = src->lscnt; - _amdnset_init_copy(&dst->exactdegreetmp0, &src->exactdegreetmp0, _state, make_automatic); - _amdknset_init_copy(&dst->hashbuckets, &src->hashbuckets, _state, make_automatic); - _amdnset_init_copy(&dst->nonemptybuckets, &src->nonemptybuckets, _state, make_automatic); - ae_vector_init_copy(&dst->sncandidates, &src->sncandidates, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->arrwe, &src->arrwe, _state, make_automatic); - ae_matrix_init_copy(&dst->dbga, &src->dbga, _state, make_automatic); -} - - -void _amdbuffer_clear(void* _p) -{ - amdbuffer *p = (amdbuffer*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->iseliminated); - ae_vector_clear(&p->issupernode); - _amdknset_clear(&p->setsuper); - _amdknset_clear(&p->seta); - _amdknset_clear(&p->sete); - _amdllmatrix_clear(&p->mtxl); - _amdvertexset_clear(&p->vertexdegrees); - ae_vector_clear(&p->perm); - ae_vector_clear(&p->invperm); - ae_vector_clear(&p->columnswaps); - _amdnset_clear(&p->lp); - _amdnset_clear(&p->plp); - _amdnset_clear(&p->ep); - _amdnset_clear(&p->adji); - _amdnset_clear(&p->adjj); - ae_vector_clear(&p->ls); - _amdnset_clear(&p->exactdegreetmp0); - _amdknset_clear(&p->hashbuckets); - _amdnset_clear(&p->nonemptybuckets); - ae_vector_clear(&p->sncandidates); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->arrwe); - ae_matrix_clear(&p->dbga); -} - - -void _amdbuffer_destroy(void* _p) -{ - amdbuffer *p = (amdbuffer*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->iseliminated); - ae_vector_destroy(&p->issupernode); - _amdknset_destroy(&p->setsuper); - _amdknset_destroy(&p->seta); - _amdknset_destroy(&p->sete); - _amdllmatrix_destroy(&p->mtxl); - _amdvertexset_destroy(&p->vertexdegrees); - ae_vector_destroy(&p->perm); - ae_vector_destroy(&p->invperm); - ae_vector_destroy(&p->columnswaps); - _amdnset_destroy(&p->lp); - _amdnset_destroy(&p->plp); - _amdnset_destroy(&p->ep); - _amdnset_destroy(&p->adji); - _amdnset_destroy(&p->adjj); - ae_vector_destroy(&p->ls); - _amdnset_destroy(&p->exactdegreetmp0); - _amdknset_destroy(&p->hashbuckets); - _amdnset_destroy(&p->nonemptybuckets); - ae_vector_destroy(&p->sncandidates); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->arrwe); - ae_matrix_destroy(&p->dbga); -} - - -#endif -#if defined(AE_COMPILE_SPCHOL) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Informational function, useful for debugging -*************************************************************************/ -ae_int_t spsymmgetmaxfastkernel(ae_state *_state) -{ - ae_int_t result; - - - result = spchol_maxfastkernel; - return result; -} - - -/************************************************************************* -Symbolic phase of Cholesky decomposition. - -Performs preliminary analysis of Cholesky/LDLT factorization. The latter -is computed with strictly diagonal D (no Bunch-Kauffman pivoting). - -The analysis object produced by this function will be used later to guide -actual decomposition. - -Depending on settings specified during factorization, may produce vanilla -Cholesky or L*D*LT decomposition (with strictly diagonal D), without -permutation or with permutation P (being either topological ordering or -sparsity preserving ordering). - -Thus, A is represented as either L*LT or L*D*LT or P*L*LT*PT or P*L*D*LT*PT. - -NOTE: L*D*LT family of factorization may be used to factorize indefinite - matrices. However, numerical stability is guaranteed ONLY for a class - of quasi-definite matrices. - -INPUT PARAMETERS: - A - sparse square matrix in CRS format, with LOWER triangle - being used to store the matrix. - FactType - factorization type: - * 0 for traditional Cholesky - * 1 for LDLT decomposition with strictly diagonal D - PermType - permutation type: - *-2 for column count ordering (NOT RECOMMENDED!) - *-1 for absence of permutation - * 0 for best permutation available - * 1 for supernodal ordering (improves locality and - performance, but does NOT change fill-in pattern) - * 2 for supernodal AMD ordering (improves fill-in) - Analysis - can be uninitialized instance, or previous analysis - results. Previously allocated memory is reused as much - as possible. - Buf - buffer; may be completely uninitialized, or one remained - from previous calls (including ones with completely - different matrices). Previously allocated temporary - space will be reused as much as possible. - -OUTPUT PARAMETERS: - Analysis - symbolic analysis of the matrix structure which will - be used later to guide numerical factorization. The - numerical values are stored internally in the structure, - but you have to run factorization phase explicitly - with SPSymmAnalyze(). You can also reload another - matrix with same sparsity pattern with SPSymmReload(). - -This function fails if and only if the matrix A is symbolically degenerate -i.e. has diagonal element which is exactly zero. In such case False is -returned. - -NOTE: defining 'SCHOLESKY' trace tag will activate tracing - -NOTE: defining 'DEBUG.SLOW' trace tag will activate extra-slow (roughly - N^3 ops) integrity checks, in addition to cheap O(1) ones. - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -ae_bool spsymmanalyze(sparsematrix* a, - ae_int_t facttype, - ae_int_t permtype, - spcholanalysis* analysis, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_bool permready; - ae_bool result; - - - ae_assert(sparseiscrs(a, _state), "SPSymmAnalyze: A is not stored in CRS format", _state); - ae_assert(sparsegetnrows(a, _state)==sparsegetncols(a, _state), "SPSymmAnalyze: non-square A", _state); - ae_assert(facttype==0||facttype==1, "SPSymmAnalyze: unexpected FactType", _state); - ae_assert((((permtype==0||permtype==1)||permtype==2)||permtype==-1)||permtype==-2, "SPSymmAnalyze: unexpected PermType", _state); - if( permtype==0 ) - { - permtype = 2; - } - result = ae_true; - n = sparsegetnrows(a, _state); - analysis->tasktype = 0; - analysis->n = n; - analysis->unitd = facttype==0; - analysis->permtype = permtype; - analysis->extendeddebug = ae_is_trace_enabled("DEBUG.SLOW"); - analysis->dotrace = ae_is_trace_enabled("SCHOLESKY"); - analysis->istopologicalordering = permtype==-1||permtype==1; - analysis->applypermutationtooutput = permtype==-1; - analysis->modtype = 0; - analysis->modparam0 = 0.0; - analysis->modparam1 = 0.0; - analysis->modparam2 = 0.0; - analysis->modparam3 = 0.0; - - /* - * Initial trace message - */ - if( analysis->dotrace ) - { - ae_trace("\n\n"); - ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n"); - ae_trace("// SPARSE CHOLESKY ANALYSIS STARTED //\n"); - ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n"); - } - - /* - * Initial integrity check - diagonal MUST be symbolically nonzero - */ - for(i=0; i<=n-1; i++) - { - if( a->didx.ptr.p_int[i]==a->uidx.ptr.p_int[i] ) - { - if( analysis->dotrace ) - { - ae_trace("> the matrix diagonal is symbolically zero, stopping"); - } - result = ae_false; - return result; - } - } - - /* - * Allocate temporaries - */ - ivectorsetlengthatleast(&analysis->tmp0, n+1, _state); - ivectorsetlengthatleast(&analysis->tmp1, n+1, _state); - ivectorsetlengthatleast(&analysis->tmp2, n+1, _state); - ivectorsetlengthatleast(&analysis->tmp3, n+1, _state); - ivectorsetlengthatleast(&analysis->tmp4, n+1, _state); - bvectorsetlengthatleast(&analysis->flagarray, n+1, _state); - - /* - * What type of permutation do we have? - */ - if( analysis->istopologicalordering ) - { - ae_assert(permtype==-1||permtype==1, "SPSymmAnalyze: integrity check failed (ihebd)", _state); - - /* - * Build topologically ordered elimination tree - */ - spchol_buildetree(a, n, &analysis->tmpparent, &analysis->superperm, &analysis->invsuperperm, &analysis->tmp0, &analysis->tmp1, &analysis->tmp2, &analysis->flagarray, _state); - ivectorsetlengthatleast(&analysis->fillinperm, n, _state); - ivectorsetlengthatleast(&analysis->invfillinperm, n, _state); - ivectorsetlengthatleast(&analysis->effectiveperm, n, _state); - ivectorsetlengthatleast(&analysis->inveffectiveperm, n, _state); - for(i=0; i<=n-1; i++) - { - analysis->fillinperm.ptr.p_int[i] = i; - analysis->invfillinperm.ptr.p_int[i] = i; - analysis->effectiveperm.ptr.p_int[i] = analysis->superperm.ptr.p_int[i]; - analysis->inveffectiveperm.ptr.p_int[i] = analysis->invsuperperm.ptr.p_int[i]; - } - - /* - * Reorder input matrix - */ - spchol_topologicalpermutation(a, &analysis->superperm, &analysis->wrkat, _state); - - /* - * Analyze etree, build supernodal structure - */ - spchol_createsupernodalstructure(&analysis->wrkat, &analysis->tmpparent, n, analysis, &analysis->node2supernode, &analysis->tmp0, &analysis->tmp1, &analysis->tmp2, &analysis->tmp3, &analysis->tmp4, &analysis->flagarray, _state); - - /* - * Having fully initialized supernodal structure, analyze dependencies - */ - spchol_analyzesupernodaldependencies(analysis, a, &analysis->node2supernode, n, &analysis->tmp0, &analysis->tmp1, &analysis->flagarray, _state); - } - else - { - - /* - * Generate fill-in reducing permutation - */ - permready = ae_false; - if( permtype==-2 ) - { - spchol_generatedbgpermutation(a, n, &analysis->fillinperm, &analysis->invfillinperm, _state); - permready = ae_true; - } - if( permtype==2 ) - { - generateamdpermutation(a, n, &analysis->fillinperm, &analysis->invfillinperm, &analysis->amdtmp, _state); - permready = ae_true; - } - ae_assert(permready, "SPSymmAnalyze: integrity check failed (pp4td)", _state); - - /* - * Apply permutation to the matrix, perform analysis on the initially reordered matrix - * (we may need one more reordering, now topological one, due to supernodal analysis). - * Build topologically ordered elimination tree - */ - sparsesymmpermtblbuf(a, ae_false, &analysis->fillinperm, &analysis->tmpa, _state); - spchol_buildetree(&analysis->tmpa, n, &analysis->tmpparent, &analysis->superperm, &analysis->invsuperperm, &analysis->tmp0, &analysis->tmp1, &analysis->tmp2, &analysis->flagarray, _state); - ivectorsetlengthatleast(&analysis->effectiveperm, n, _state); - ivectorsetlengthatleast(&analysis->inveffectiveperm, n, _state); - for(i=0; i<=n-1; i++) - { - analysis->effectiveperm.ptr.p_int[i] = analysis->superperm.ptr.p_int[analysis->fillinperm.ptr.p_int[i]]; - analysis->inveffectiveperm.ptr.p_int[analysis->effectiveperm.ptr.p_int[i]] = i; - } - - /* - * Reorder input matrix - */ - spchol_topologicalpermutation(&analysis->tmpa, &analysis->superperm, &analysis->wrkat, _state); - - /* - * Analyze etree, build supernodal structure - */ - spchol_createsupernodalstructure(&analysis->wrkat, &analysis->tmpparent, n, analysis, &analysis->node2supernode, &analysis->tmp0, &analysis->tmp1, &analysis->tmp2, &analysis->tmp3, &analysis->tmp4, &analysis->flagarray, _state); - - /* - * Having fully initialized supernodal structure, analyze dependencies - */ - spchol_analyzesupernodaldependencies(analysis, &analysis->tmpa, &analysis->node2supernode, n, &analysis->tmp0, &analysis->tmp1, &analysis->flagarray, _state); - } - return result; -} - - -/************************************************************************* -Sets modified Cholesky type - -INPUT PARAMETERS: - Analysis - symbolic analysis of the matrix structure - ModStrategy - modification type: - * 0 for traditional Cholesky/LDLT (Cholesky fails when - encounters nonpositive pivot, LDLT fails when zero - pivot is encountered, no stability checks for - overflows/underflows) - * 1 for modified Cholesky with additional checks: - * pivots less than ModParam0 are increased; (similar - procedure with proper generalization is applied to - LDLT) - * if, at some moment, sum of absolute values of - elements in column J will become greater than - ModParam1, Cholesky/LDLT will treat it as failure - and will stop immediately - * if ModParam0 is zero, no pivot modification is applied - * if ModParam1 is zero, no overflow check is performed - P0, P1, P2,P3 - modification parameters #0 #1, #2 and #3. - Params #2 and #3 are ignored in current version. - -OUTPUT PARAMETERS: - Analysis - symbolic analysis of the matrix structure, new strategy - (results will be seen with next SPSymmFactorize() call) - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -void spsymmsetmodificationstrategy(spcholanalysis* analysis, - ae_int_t modstrategy, - double p0, - double p1, - double p2, - double p3, - ae_state *_state) -{ - - - ae_assert(modstrategy==0||modstrategy==1, "SPSymmSetModificationStrategy: unexpected ModStrategy", _state); - ae_assert(ae_isfinite(p0, _state)&&ae_fp_greater_eq(p0,(double)(0)), "SPSymmSetModificationStrategy: bad P0", _state); - ae_assert(ae_isfinite(p1, _state), "SPSymmSetModificationStrategy: bad P1", _state); - ae_assert(ae_isfinite(p2, _state), "SPSymmSetModificationStrategy: bad P2", _state); - ae_assert(ae_isfinite(p3, _state), "SPSymmSetModificationStrategy: bad P3", _state); - analysis->modtype = modstrategy; - analysis->modparam0 = p0; - analysis->modparam1 = p1; - analysis->modparam2 = p2; - analysis->modparam3 = p3; -} - - -/************************************************************************* -Updates symmetric matrix internally stored in previously initialized -Analysis object. - -You can use this function to perform multiple factorizations with same -sparsity patterns: perform symbolic analysis once with SPSymmAnalyze(), -then update internal matrix with SPSymmReload() and call SPSymmFactorize(). - -INPUT PARAMETERS: - Analysis - symbolic analysis of the matrix structure - A - sparse square matrix in CRS format with LOWER triangle - being used to store the matrix. The matrix MUST have - sparsity pattern exactly same as one used to - initialize the Analysis object. - The algorithm will fail in an unpredictable way if - something different was passed. - -OUTPUT PARAMETERS: - Analysis - symbolic analysis of the matrix structure which will - be used later to guide numerical factorization. The - numerical values are stored internally in the structure, - but you have to run factorization phase explicitly - with SPSymmAnalyze(). You can also reload another - matrix with same sparsity pattern with SPSymmReload(). - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -void spsymmreload(spcholanalysis* analysis, - sparsematrix* a, - ae_state *_state) -{ - - - ae_assert(sparseiscrs(a, _state), "SPSymmReload: A is not stored in CRS format", _state); - ae_assert(sparsegetnrows(a, _state)==sparsegetncols(a, _state), "SPSymmReload: non-square A", _state); - if( analysis->istopologicalordering ) - { - - /* - * Topological (fill-in preserving) ordering is used, we can copy - * A directly into WrkAT using joint permute+transpose - */ - spchol_topologicalpermutation(a, &analysis->effectiveperm, &analysis->wrkat, _state); - } - else - { - - /* - * Non-topological permutation; first we perform generic symmetric - * permutation, then transpose result - */ - sparsesymmpermtblbuf(a, ae_false, &analysis->effectiveperm, &analysis->tmpa, _state); - sparsecopytransposecrsbuf(&analysis->tmpa, &analysis->wrkat, _state); - } -} - - -/************************************************************************* -Sparse Cholesky factorization of SPD matrix stored in CRS format, using -precomputed analysis of sparsity pattern stored in Analysis object and -the matrix that is presently loaded into A. - -Depending on settings specified during factorization, may produce vanilla -Cholesky or L*D*LT decomposition (with strictly diagonal D), without -permutation or with permutation P (being either topological ordering or -sparsity preserving ordering). - -Thus, A is represented as either L*LT or L*D*LT or P*L*LT*PT or P*L*D*LT*PT. - -NOTE: L*D*LT family of factorization may be used to factorize indefinite - matrices. However, numerical stability is guaranteed ONLY for a class - of quasi-definite matrices. - -INPUT PARAMETERS: - Analysis - prior analysis performed on some sparse matrix, with - matrix being stored in Analysis. This matrix is - destroyed during factorization. - D, P - possibly preallocated buffers - -OUTPUT PARAMETERS: - A - Cholesky decomposition of A stored in CRS format - in LOWER triangle. - D - array[N], diagonal factor. If no diagonal factor was - required during analysis phase, still returned but - filled with units. - P - array[N], pivots. Permutation matrix P is a product of - P(0)*P(1)*...*P(N-1), where P(i) is a permutation of - row/col I and P[I] (with P[I]>=I). - If no permutation was requested during analysis phase, - still returned but filled with unit elements. - -The function returns True when factorization resulted in nondegenerate -matrix. False is returned when factorization fails (Cholesky factorization -of indefinite matrix) or LDLT factorization has exactly zero elements at -the diagonal. - -In the latter case contents of A, D and P is undefined. - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -ae_bool spsymmfactorize(spcholanalysis* analysis, - sparsematrix* a, - /* Real */ ae_vector* d, - /* Integer */ ae_vector* p, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t ii; - ae_int_t i0; - ae_int_t i1; - ae_int_t n; - ae_int_t cols0; - ae_int_t cols1; - ae_int_t offss; - ae_int_t sstride; - ae_int_t blocksize; - ae_int_t sidx; - ae_int_t uidx; - ae_bool result; - - - ae_assert(analysis->tasktype==0, "SPCholFactorize: Analysis type does not match current task", _state); - result = ae_true; - n = analysis->n; - - /* - * Prepare structures: - * * WrkRows[] store pointers to beginnings of the offdiagonal supernode row ranges; - * at the beginning of the work WrkRows[]=0, but as we advance from the column - * range [0,A) to [A,B), to [B,C) and so on, we advance WrkRows[] in order to - * quickly skip parts that are less than A, less than B, less than C and so on. - */ - ivectorsetlengthatleast(&analysis->raw2smap, n, _state); - ivectorsetlengthatleast(&analysis->tmp0, n+1, _state); - bsetallocv(n, ae_false, &analysis->flagarray, _state); - isetallocv(analysis->nsuper, 0, &analysis->wrkrows, _state); - rsetallocv(n, 0.0, &analysis->diagd, _state); - rsetallocv(analysis->rowoffsets.ptr.p_int[analysis->nsuper], 0.0, &analysis->rowstorage, _state); - - /* - * Now we can run actual supernodal Cholesky - */ - for(sidx=0; sidx<=analysis->nsuper-1; sidx++) - { - cols0 = analysis->supercolrange.ptr.p_int[sidx]; - cols1 = analysis->supercolrange.ptr.p_int[sidx+1]; - blocksize = cols1-cols0; - offss = analysis->rowoffsets.ptr.p_int[sidx]; - sstride = analysis->rowstrides.ptr.p_int[sidx]; - - /* - * Prepare mapping of raw (range 0...N-1) indexes into internal (range 0...BlockSize+OffdiagSize-1) ones - */ - if( analysis->extendeddebug ) - { - isetv(n, -1, &analysis->raw2smap, _state); - } - for(i=cols0; i<=cols1-1; i++) - { - analysis->raw2smap.ptr.p_int[i] = i-cols0; - } - for(k=analysis->superrowridx.ptr.p_int[sidx]; k<=analysis->superrowridx.ptr.p_int[sidx+1]-1; k++) - { - analysis->raw2smap.ptr.p_int[analysis->superrowidx.ptr.p_int[k]] = blocksize+(k-analysis->superrowridx.ptr.p_int[sidx]); - } - - /* - * Load supernode #SIdx using Raw2SMap to perform quick transformation between global and local indexing. - */ - for(j=cols0; j<=cols1-1; j++) - { - i0 = analysis->wrkat.ridx.ptr.p_int[j]; - i1 = analysis->wrkat.ridx.ptr.p_int[j+1]-1; - for(ii=i0; ii<=i1; ii++) - { - analysis->rowstorage.ptr.p_double[offss+analysis->raw2smap.ptr.p_int[analysis->wrkat.idx.ptr.p_int[ii]]*sstride+(j-cols0)] = analysis->wrkat.vals.ptr.p_double[ii]; - } - } - - /* - * Update current supernode with nonzeros from the current row - */ - for(ii=analysis->ladjplusr.ptr.p_int[sidx]; ii<=analysis->ladjplusr.ptr.p_int[sidx+1]-1; ii++) - { - uidx = analysis->ladjplus.ptr.p_int[ii]; - analysis->wrkrows.ptr.p_int[uidx] = spchol_updatesupernode(analysis, sidx, cols0, cols1, offss, &analysis->raw2smap, uidx, analysis->wrkrows.ptr.p_int[uidx], &analysis->diagd, analysis->supercolrange.ptr.p_int[uidx], _state); - } - - /* - * Factorize current supernode - */ - if( !spchol_factorizesupernode(analysis, sidx, _state) ) - { - result = ae_false; - return result; - } - } - - /* - * Convert from supernodal storage to SparseMatrix format - */ - spchol_extractmatrix(analysis, &analysis->rowoffsets, &analysis->rowstrides, &analysis->rowstorage, &analysis->diagd, n, a, d, p, &analysis->tmp0, _state); - return result; -} - - -/************************************************************************* -This function generates test reodering used for debug purposes only - -INPUT PARAMETERS - A - lower triangular sparse matrix in CRS format - N - problem size - -OUTPUT PARAMETERS - Perm - array[N], maps original indexes I to permuted indexes - InvPerm - array[N], maps permuted indexes I to original indexes - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void spchol_generatedbgpermutation(sparsematrix* a, - ae_int_t n, - /* Integer */ ae_vector* perm, - /* Integer */ ae_vector* invperm, - ae_state *_state) -{ - ae_int_t i; - - - ivectorsetlengthatleast(perm, n, _state); - ivectorsetlengthatleast(invperm, n, _state); - for(i=0; i<=n-1; i++) - { - perm->ptr.p_int[i] = n-1-i; - invperm->ptr.p_int[i] = n-1-i; - } -} - - -/************************************************************************* -This function builds elimination tree and reorders it according to the -topological post-ordering. - -INPUT PARAMETERS - A - lower triangular sparse matrix in CRS format - N - problem size - - tRawParentOfRawNode, - tRawParentOfReorderedNode, - tTmp, - tFlagArray - preallocated temporary arrays, length at least N+1, no - meaningful output is provided in these variables - -OUTPUT PARAMETERS - Parent - array[N], Parent[I] contains index of parent of I-th - column (after topological reordering). -1 is used to - denote column with no parents. - SupernodalPermutation - - array[N], maps original indexes I to permuted indexes - InvSupernodalPermutation - - array[N], maps permuted indexes I to original indexes - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void spchol_buildetree(sparsematrix* a, - ae_int_t n, - /* Integer */ ae_vector* parent, - /* Integer */ ae_vector* supernodalpermutation, - /* Integer */ ae_vector* invsupernodalpermutation, - /* Integer */ ae_vector* trawparentofrawnode, - /* Integer */ ae_vector* trawparentofreorderednode, - /* Integer */ ae_vector* ttmp, - /* Boolean */ ae_vector* tflagarray, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t sidx; - ae_int_t parentk; - ae_int_t unprocessedchildrencnt; - ae_int_t j0; - ae_int_t j1; - ae_int_t jj; - - - ae_assert(trawparentofrawnode->cnt>=n+1, "BuildETree: input buffer tRawParentOfRawNode is too short", _state); - ae_assert(ttmp->cnt>=n+1, "BuildETree: input buffer tTmp is too short", _state); - ae_assert(trawparentofreorderednode->cnt>=n+1, "BuildETree: input buffer tRawParentOfReorderedNode is too short", _state); - ae_assert(tflagarray->cnt>=n+1, "BuildETree: input buffer tFlagArray is too short", _state); - - /* - * Avoid spurious compiler warnings - */ - unprocessedchildrencnt = 0; - - /* - * Build elimination tree with original column order using path compression: - * tTmp[] array stores indexes of some ancestor of the vertex. - */ - for(i=0; i<=n-1; i++) - { - trawparentofrawnode->ptr.p_int[i] = -1; - ttmp->ptr.p_int[i] = i; - j0 = a->ridx.ptr.p_int[i]; - j1 = a->didx.ptr.p_int[i]-1; - for(jj=j0; jj<=j1; jj++) - { - j = a->idx.ptr.p_int[jj]; - k = ttmp->ptr.p_int[j]; - ttmp->ptr.p_int[j] = i; - parentk = trawparentofrawnode->ptr.p_int[k]; - while(parentk>=0) - { - ttmp->ptr.p_int[k] = i; - k = parentk; - parentk = trawparentofrawnode->ptr.p_int[k]; - } - if( k!=i ) - { - trawparentofrawnode->ptr.p_int[k] = i; - } - } - } - - /* - * Compute topological ordering of the elimination tree, produce: - * * direct and inverse permutations - * * reordered etree stored in Parent[] - */ - isetallocv(n, -1, invsupernodalpermutation, _state); - isetallocv(n, -1, supernodalpermutation, _state); - isetallocv(n, -1, parent, _state); - isetv(n, -1, trawparentofreorderednode, _state); - isetv(n, 0, ttmp, _state); - for(i=0; i<=n-1; i++) - { - k = trawparentofrawnode->ptr.p_int[i]; - if( k>=0 ) - { - ttmp->ptr.p_int[k] = ttmp->ptr.p_int[k]+1; - } - } - bsetv(n, ae_true, tflagarray, _state); - sidx = 0; - for(i=0; i<=n-1; i++) - { - if( tflagarray->ptr.p_bool[i] ) - { - - /* - * Move column I to position SIdx, decrease unprocessed children count - */ - supernodalpermutation->ptr.p_int[i] = sidx; - invsupernodalpermutation->ptr.p_int[sidx] = i; - tflagarray->ptr.p_bool[i] = ae_false; - k = trawparentofrawnode->ptr.p_int[i]; - trawparentofreorderednode->ptr.p_int[sidx] = k; - if( k>=0 ) - { - unprocessedchildrencnt = ttmp->ptr.p_int[k]-1; - ttmp->ptr.p_int[k] = unprocessedchildrencnt; - } - sidx = sidx+1; - - /* - * Add parents (as long as parent has no unprocessed children) - */ - while(k>=0&&unprocessedchildrencnt==0) - { - supernodalpermutation->ptr.p_int[k] = sidx; - invsupernodalpermutation->ptr.p_int[sidx] = k; - tflagarray->ptr.p_bool[k] = ae_false; - k = trawparentofrawnode->ptr.p_int[k]; - trawparentofreorderednode->ptr.p_int[sidx] = k; - if( k>=0 ) - { - unprocessedchildrencnt = ttmp->ptr.p_int[k]-1; - ttmp->ptr.p_int[k] = unprocessedchildrencnt; - } - sidx = sidx+1; - } - } - } - for(i=0; i<=n-1; i++) - { - k = trawparentofreorderednode->ptr.p_int[i]; - if( k>=0 ) - { - parent->ptr.p_int[i] = supernodalpermutation->ptr.p_int[k]; - } - } -} - - -/************************************************************************* -This function analyzes postordered elimination tree and creates supernodal -structure in Analysis object. - -INPUT PARAMETERS - AT - upper triangular CRS matrix, transpose and reordering - of the original input matrix A - Parent - array[N], supernodal etree - N - problem size - - tChildrenR, - tChildrenI, - tParentNodeOfSupernode, - tNode2Supernode, - tTmp0, - tFlagArray - temporary arrays, length at least N+1, simply provide - preallocated place. - -OUTPUT PARAMETERS - Analysis - following fields are initialized: - * Analysis.NSuper - * Analysis.SuperColRange - * Analysis.SuperRowRIdx - * Analysis.SuperRowIdx - * Analysis.ParentSupernode - * Analysis.OutRowCounts - other fields are ignored and not changed. - Node2Supernode- array[N] that maps node indexes to supernode indexes - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void spchol_createsupernodalstructure(sparsematrix* at, - /* Integer */ ae_vector* parent, - ae_int_t n, - spcholanalysis* analysis, - /* Integer */ ae_vector* node2supernode, - /* Integer */ ae_vector* tchildrenr, - /* Integer */ ae_vector* tchildreni, - /* Integer */ ae_vector* tparentnodeofsupernode, - /* Integer */ ae_vector* tfakenonzeros, - /* Integer */ ae_vector* ttmp0, - /* Boolean */ ae_vector* tflagarray, - ae_state *_state) -{ - ae_int_t nsuper; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t sidx; - ae_int_t i0; - ae_int_t ii; - ae_int_t columnidx; - ae_int_t nodeidx; - ae_int_t rfirst; - ae_int_t rlast; - ae_int_t cols0; - ae_int_t cols1; - ae_int_t blocksize; - ae_bool createsupernode; - ae_int_t colcount; - ae_int_t offdiagcnt; - ae_int_t childcolcount; - ae_int_t childoffdiagcnt; - ae_int_t fakezerosinnewsupernode; - double mergeinefficiency; - ae_bool hastheonlychild; - - - ae_assert(ttmp0->cnt>=n+1, "CreateSupernodalStructure: input buffer tTmp0 is too short", _state); - ae_assert(tchildrenr->cnt>=n+1, "CreateSupernodalStructure: input buffer ChildrenR is too short", _state); - ae_assert(tchildreni->cnt>=n+1, "CreateSupernodalStructure: input buffer ChildrenI is too short", _state); - ae_assert(tparentnodeofsupernode->cnt>=n+1, "CreateSupernodalStructure: input buffer tParentNodeOfSupernode is too short", _state); - ae_assert(tfakenonzeros->cnt>=n+1, "CreateSupernodalStructure: input buffer tFakeNonzeros is too short", _state); - ae_assert(tflagarray->cnt>=n+1, "CreateSupernodalStructure: input buffer tFlagArray is too short", _state); - - /* - * Trace - */ - if( analysis->dotrace ) - { - ae_trace("=== GENERATING SUPERNODAL STRUCTURE ================================================================\n"); - } - - /* - * Convert etree from per-column parent array to per-column children list - */ - isetv(n, 0, ttmp0, _state); - for(i=0; i<=n-1; i++) - { - nodeidx = parent->ptr.p_int[i]; - if( nodeidx>=0 ) - { - ttmp0->ptr.p_int[nodeidx] = ttmp0->ptr.p_int[nodeidx]+1; - } - } - tchildrenr->ptr.p_int[0] = 0; - for(i=0; i<=n-1; i++) - { - tchildrenr->ptr.p_int[i+1] = tchildrenr->ptr.p_int[i]+ttmp0->ptr.p_int[i]; - } - isetv(n, 0, ttmp0, _state); - for(i=0; i<=n-1; i++) - { - k = parent->ptr.p_int[i]; - if( k>=0 ) - { - tchildreni->ptr.p_int[tchildrenr->ptr.p_int[k]+ttmp0->ptr.p_int[k]] = i; - ttmp0->ptr.p_int[k] = ttmp0->ptr.p_int[k]+1; - } - } - - /* - * Analyze supernodal structure: - * * determine children count for each node - * * combine chains of children into supernodes - * * generate direct and inverse supernodal (topological) permutations - * * generate column structure of supernodes (after supernodal permutation) - */ - isetallocv(n, -1, node2supernode, _state); - ivectorsetlengthatleast(&analysis->supercolrange, n+1, _state); - ivectorsetlengthatleast(&analysis->superrowridx, n+1, _state); - isetv(n, n+1, tparentnodeofsupernode, _state); - bsetv(n, ae_true, tflagarray, _state); - nsuper = 0; - analysis->supercolrange.ptr.p_int[0] = 0; - analysis->superrowridx.ptr.p_int[0] = 0; - while(analysis->supercolrange.ptr.p_int[nsuper]supercolrange.ptr.p_int[nsuper]; - - /* - * Compute nonzero pattern of the column, create temporary standalone node - * for possible supernodal merge. Newly created node has just one column - * and no fake nonzeros. - */ - rfirst = analysis->superrowridx.ptr.p_int[nsuper]; - rlast = spchol_computenonzeropattern(at, columnidx, n, &analysis->superrowridx, &analysis->superrowidx, nsuper, tchildrenr, tchildreni, node2supernode, tflagarray, ttmp0, _state); - analysis->supercolrange.ptr.p_int[nsuper+1] = columnidx+1; - analysis->superrowridx.ptr.p_int[nsuper+1] = rlast; - node2supernode->ptr.p_int[columnidx] = nsuper; - tparentnodeofsupernode->ptr.p_int[nsuper] = parent->ptr.p_int[columnidx]; - tfakenonzeros->ptr.p_int[nsuper] = 0; - offdiagcnt = rlast-rfirst; - colcount = 1; - nsuper = nsuper+1; - if( analysis->dotrace ) - { - ae_trace("> incoming column %0d\n", - (int)(columnidx)); - ae_trace("offdiagnnz = %0d\n", - (int)(rlast-rfirst)); - ae_trace("children = [ "); - for(i=tchildrenr->ptr.p_int[columnidx]; i<=tchildrenr->ptr.p_int[columnidx+1]-1; i++) - { - ae_trace("S%0d ", - (int)(node2supernode->ptr.p_int[tchildreni->ptr.p_int[i]])); - } - ae_trace("]\n"); - } - - /* - * Decide whether to merge column with previous supernode or not - */ - childcolcount = 0; - childoffdiagcnt = 0; - mergeinefficiency = 0.0; - fakezerosinnewsupernode = 0; - createsupernode = ae_false; - hastheonlychild = ae_false; - if( nsuper>=2&&tparentnodeofsupernode->ptr.p_int[nsuper-2]==columnidx ) - { - childcolcount = analysis->supercolrange.ptr.p_int[nsuper-1]-analysis->supercolrange.ptr.p_int[nsuper-2]; - childoffdiagcnt = analysis->superrowridx.ptr.p_int[nsuper-1]-analysis->superrowridx.ptr.p_int[nsuper-2]; - hastheonlychild = tchildrenr->ptr.p_int[columnidx+1]-tchildrenr->ptr.p_int[columnidx]==1; - if( (hastheonlychild||spchol_relaxedsupernodes)&&colcount+childcolcount<=spchol_maxsupernode ) - { - i = colcount+childcolcount; - k = i*(i+1)/2+offdiagcnt*i; - fakezerosinnewsupernode = tfakenonzeros->ptr.p_int[nsuper-2]+tfakenonzeros->ptr.p_int[nsuper-1]+(offdiagcnt-(childoffdiagcnt-1))*childcolcount; - mergeinefficiency = (double)fakezerosinnewsupernode/(double)k; - if( colcount+childcolcount==2&&fakezerosinnewsupernode<=spchol_smallfakestolerance ) - { - createsupernode = ae_true; - } - if( ae_fp_less_eq(mergeinefficiency,spchol_maxmergeinefficiency) ) - { - createsupernode = ae_true; - } - } - } - - /* - * Create supernode if needed - */ - if( createsupernode ) - { - - /* - * Create supernode from nodes NSuper-2 and NSuper-1. - * Because these nodes are in the child-parent relation, we can simply - * copy nonzero pattern from NSuper-1. - */ - ae_assert(tparentnodeofsupernode->ptr.p_int[nsuper-2]==columnidx, "CreateSupernodalStructure: integrity check 9472 failed", _state); - i0 = analysis->superrowridx.ptr.p_int[nsuper-1]; - ii = analysis->superrowridx.ptr.p_int[nsuper]-analysis->superrowridx.ptr.p_int[nsuper-1]; - rfirst = analysis->superrowridx.ptr.p_int[nsuper-2]; - rlast = rfirst+ii; - for(i=0; i<=ii-1; i++) - { - analysis->superrowidx.ptr.p_int[rfirst+i] = analysis->superrowidx.ptr.p_int[i0+i]; - } - analysis->supercolrange.ptr.p_int[nsuper-1] = columnidx+1; - analysis->superrowridx.ptr.p_int[nsuper-1] = rlast; - node2supernode->ptr.p_int[columnidx] = nsuper-2; - tfakenonzeros->ptr.p_int[nsuper-2] = fakezerosinnewsupernode; - tparentnodeofsupernode->ptr.p_int[nsuper-2] = parent->ptr.p_int[columnidx]; - nsuper = nsuper-1; - - /* - * Trace - */ - if( analysis->dotrace ) - { - ae_trace("> merged with supernode S%0d", - (int)(nsuper-1)); - if( ae_fp_neq(mergeinefficiency,(double)(0)) ) - { - ae_trace(" (%2.0f%% inefficiency)", - (double)(mergeinefficiency*100)); - } - ae_trace("\n*\n"); - } - } - else - { - - /* - * Trace - */ - if( analysis->dotrace ) - { - ae_trace("> standalone node S%0d created\n*\n", - (int)(nsuper-1)); - } - } - } - analysis->nsuper = nsuper; - ae_assert(analysis->nsuper>=1, "SPSymmAnalyze: integrity check failed (95mgd)", _state); - ae_assert(analysis->supercolrange.ptr.p_int[0]==0, "SPCholFactorize: integrity check failed (f446s)", _state); - ae_assert(analysis->supercolrange.ptr.p_int[nsuper]==n, "SPSymmAnalyze: integrity check failed (04ut4)", _state); - isetallocv(nsuper, -1, &analysis->parentsupernode, _state); - for(sidx=0; sidx<=nsuper-1; sidx++) - { - nodeidx = tparentnodeofsupernode->ptr.p_int[sidx]; - if( nodeidx>=0 ) - { - nodeidx = node2supernode->ptr.p_int[nodeidx]; - analysis->parentsupernode.ptr.p_int[sidx] = nodeidx; - } - } - - /* - * Allocate supernodal storage - */ - ivectorsetlengthatleast(&analysis->rowoffsets, analysis->nsuper+1, _state); - ivectorsetlengthatleast(&analysis->rowstrides, analysis->nsuper, _state); - analysis->rowoffsets.ptr.p_int[0] = 0; - for(i=0; i<=analysis->nsuper-1; i++) - { - blocksize = analysis->supercolrange.ptr.p_int[i+1]-analysis->supercolrange.ptr.p_int[i]; - analysis->rowstrides.ptr.p_int[i] = spchol_recommendedstridefor(blocksize, _state); - analysis->rowoffsets.ptr.p_int[i+1] = analysis->rowoffsets.ptr.p_int[i]; - analysis->rowoffsets.ptr.p_int[i+1] = analysis->rowoffsets.ptr.p_int[i+1]+analysis->rowstrides.ptr.p_int[i]*blocksize; - analysis->rowoffsets.ptr.p_int[i+1] = analysis->rowoffsets.ptr.p_int[i+1]+analysis->rowstrides.ptr.p_int[i]*(analysis->superrowridx.ptr.p_int[i+1]-analysis->superrowridx.ptr.p_int[i]); - analysis->rowoffsets.ptr.p_int[i+1] = spchol_alignpositioninarray(analysis->rowoffsets.ptr.p_int[i+1], _state); - } - - /* - * Analyze output structure - */ - isetallocv(n, 0, &analysis->outrowcounts, _state); - for(sidx=0; sidx<=nsuper-1; sidx++) - { - cols0 = analysis->supercolrange.ptr.p_int[sidx]; - cols1 = analysis->supercolrange.ptr.p_int[sidx+1]; - rfirst = analysis->superrowridx.ptr.p_int[sidx]; - rlast = analysis->superrowridx.ptr.p_int[sidx+1]; - blocksize = cols1-cols0; - for(j=cols0; j<=cols1-1; j++) - { - analysis->outrowcounts.ptr.p_int[j] = analysis->outrowcounts.ptr.p_int[j]+(j-cols0+1); - } - for(ii=rfirst; ii<=rlast-1; ii++) - { - i0 = analysis->superrowidx.ptr.p_int[ii]; - analysis->outrowcounts.ptr.p_int[i0] = analysis->outrowcounts.ptr.p_int[i0]+blocksize; - } - } -} - - -/************************************************************************* -This function analyzes supernodal structure and precomputes dependency -matrix LAdj+ - -INPUT PARAMETERS - Analysis - analysis object with completely initialized supernodal - structure - RawA - original (before reordering) input matrix - Node2Supernode- mapping from node to supernode indexes - N - problem size - - tTmp0, - tTmp1, - tFlagArray - temporary arrays, length at least N+1, simply provide - preallocated place. - -OUTPUT PARAMETERS - Analysis - following fields are initialized: - * Analysis.LAdjPlus - * Analysis.LAdjPlusR - Node2Supernode- array[N] that maps node indexes to supernode indexes - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void spchol_analyzesupernodaldependencies(spcholanalysis* analysis, - sparsematrix* rawa, - /* Integer */ ae_vector* node2supernode, - ae_int_t n, - /* Integer */ ae_vector* ttmp0, - /* Integer */ ae_vector* ttmp1, - /* Boolean */ ae_vector* tflagarray, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t rowidx; - ae_int_t j0; - ae_int_t j1; - ae_int_t jj; - ae_int_t rfirst; - ae_int_t rlast; - ae_int_t sidx; - ae_int_t uidx; - ae_int_t dbgrank1nodes; - ae_int_t dbgrank2nodes; - ae_int_t dbgrank3nodes; - ae_int_t dbgrank4nodes; - ae_int_t dbgbignodes; - double dbgtotalflop; - double dbgnoscatterflop; - double dbgnorowscatterflop; - double dbgnocolscatterflop; - double dbgcholeskyflop; - double dbgcholesky4flop; - double dbgrank1flop; - double dbgrank4plusflop; - double dbg444flop; - double dbgxx4flop; - double uflop; - ae_int_t wrkrow; - ae_int_t offdiagrow; - ae_int_t lastrow; - ae_int_t uwidth; - ae_int_t uheight; - ae_int_t urank; - ae_int_t theight; - ae_int_t twidth; - - - ae_assert(ttmp0->cnt>=n+1, "AnalyzeSupernodalDependencies: input buffer tTmp0 is too short", _state); - ae_assert(ttmp1->cnt>=n+1, "AnalyzeSupernodalDependencies: input buffer tTmp1 is too short", _state); - ae_assert(tflagarray->cnt>=n+1, "AnalyzeSupernodalDependencies: input buffer tTmp0 is too short", _state); - ae_assert(sparseiscrs(rawa, _state), "AnalyzeSupernodalDependencies: RawA must be CRS matrix", _state); - - /* - * Determine LAdjPlus - supernodes feeding updates to the SIdx-th one. - * - * Without supernodes we have: K-th row of L (also denoted as ladj+(K)) - * includes original nonzeros from A (also denoted as ladj(K)) as well - * as all elements on paths in elimination tree from ladj(K) to K. - * - * With supernodes: same principle applied. - */ - isetallocv(analysis->nsuper+1, 0, &analysis->ladjplusr, _state); - bsetv(n, ae_true, tflagarray, _state); - analysis->ladjplusr.ptr.p_int[0] = 0; - for(sidx=0; sidx<=analysis->nsuper-1; sidx++) - { - - /* - * Generate list of nodes feeding updates to SIdx-th one - */ - ivectorgrowto(&analysis->ladjplus, analysis->ladjplusr.ptr.p_int[sidx]+analysis->nsuper, _state); - rfirst = analysis->ladjplusr.ptr.p_int[sidx]; - rlast = rfirst; - for(rowidx=analysis->supercolrange.ptr.p_int[sidx]; rowidx<=analysis->supercolrange.ptr.p_int[sidx+1]-1; rowidx++) - { - i = analysis->invsuperperm.ptr.p_int[rowidx]; - j0 = rawa->ridx.ptr.p_int[i]; - j1 = rawa->uidx.ptr.p_int[i]-1; - for(jj=j0; jj<=j1; jj++) - { - j = node2supernode->ptr.p_int[analysis->superperm.ptr.p_int[rawa->idx.ptr.p_int[jj]]]; - if( jptr.p_bool[j] ) - { - analysis->ladjplus.ptr.p_int[rlast] = j; - tflagarray->ptr.p_bool[j] = ae_false; - rlast = rlast+1; - j = analysis->parentsupernode.ptr.p_int[j]; - while((j>=0&&jptr.p_bool[j]) - { - analysis->ladjplus.ptr.p_int[rlast] = j; - tflagarray->ptr.p_bool[j] = ae_false; - rlast = rlast+1; - j = analysis->parentsupernode.ptr.p_int[j]; - } - } - } - } - for(i=rfirst; i<=rlast-1; i++) - { - tflagarray->ptr.p_bool[analysis->ladjplus.ptr.p_int[i]] = ae_true; - } - analysis->ladjplusr.ptr.p_int[sidx+1] = rlast; - } - - /* - * Analyze statistics for trace output - */ - if( analysis->dotrace ) - { - ae_trace("=== ANALYZING SUPERNODAL DEPENDENCIES ==============================================================\n"); - dbgrank1nodes = 0; - dbgrank2nodes = 0; - dbgrank3nodes = 0; - dbgrank4nodes = 0; - dbgbignodes = 0; - dbgtotalflop = (double)(0); - dbgnoscatterflop = (double)(0); - dbgnorowscatterflop = (double)(0); - dbgnocolscatterflop = (double)(0); - dbgrank1flop = (double)(0); - dbgrank4plusflop = (double)(0); - dbg444flop = (double)(0); - dbgxx4flop = (double)(0); - dbgcholeskyflop = (double)(0); - dbgcholesky4flop = (double)(0); - isetv(analysis->nsuper, 0, ttmp0, _state); - for(sidx=0; sidx<=analysis->nsuper-1; sidx++) - { - - /* - * Node sizes - */ - if( analysis->supercolrange.ptr.p_int[sidx+1]-analysis->supercolrange.ptr.p_int[sidx]==1 ) - { - inc(&dbgrank1nodes, _state); - } - if( analysis->supercolrange.ptr.p_int[sidx+1]-analysis->supercolrange.ptr.p_int[sidx]==2 ) - { - inc(&dbgrank2nodes, _state); - } - if( analysis->supercolrange.ptr.p_int[sidx+1]-analysis->supercolrange.ptr.p_int[sidx]==3 ) - { - inc(&dbgrank3nodes, _state); - } - if( analysis->supercolrange.ptr.p_int[sidx+1]-analysis->supercolrange.ptr.p_int[sidx]==4 ) - { - inc(&dbgrank4nodes, _state); - } - if( analysis->supercolrange.ptr.p_int[sidx+1]-analysis->supercolrange.ptr.p_int[sidx]>4 ) - { - inc(&dbgbignodes, _state); - } - - /* - * FLOP counts - */ - twidth = analysis->supercolrange.ptr.p_int[sidx+1]-analysis->supercolrange.ptr.p_int[sidx]; - theight = twidth+(analysis->superrowridx.ptr.p_int[sidx+1]-analysis->superrowridx.ptr.p_int[sidx]); - for(i=analysis->ladjplusr.ptr.p_int[sidx]; i<=analysis->ladjplusr.ptr.p_int[sidx+1]-1; i++) - { - uidx = analysis->ladjplus.ptr.p_int[i]; - - /* - * Determine update width, height, rank - */ - wrkrow = ttmp0->ptr.p_int[uidx]; - offdiagrow = wrkrow; - lastrow = analysis->superrowridx.ptr.p_int[uidx+1]-analysis->superrowridx.ptr.p_int[uidx]; - while(offdiagrowsuperrowidx.ptr.p_int[analysis->superrowridx.ptr.p_int[uidx]+offdiagrow]supercolrange.ptr.p_int[sidx+1]) - { - offdiagrow = offdiagrow+1; - } - uwidth = offdiagrow-wrkrow; - uheight = lastrow-wrkrow; - urank = analysis->supercolrange.ptr.p_int[uidx+1]-analysis->supercolrange.ptr.p_int[uidx]; - ttmp0->ptr.p_int[uidx] = offdiagrow; - - /* - * Compute update FLOP cost - */ - uflop = rmul3((double)(uwidth), (double)(uheight), (double)(urank), _state); - dbgtotalflop = dbgtotalflop+uflop; - if( uheight==theight&&uwidth==twidth ) - { - dbgnoscatterflop = dbgnoscatterflop+uflop; - } - if( uheight==theight ) - { - dbgnorowscatterflop = dbgnorowscatterflop+uflop; - } - if( uwidth==twidth ) - { - dbgnocolscatterflop = dbgnocolscatterflop+uflop; - } - if( urank==1 ) - { - dbgrank1flop = dbgrank1flop+uflop; - } - if( urank>=4 ) - { - dbgrank4plusflop = dbgrank4plusflop+uflop; - } - if( (urank==4&&uwidth==4)&&twidth==4 ) - { - dbg444flop = dbg444flop+uflop; - } - if( twidth==4 ) - { - dbgxx4flop = dbgxx4flop+uflop; - } - } - uflop = (double)(0); - for(i=0; i<=twidth-1; i++) - { - uflop = uflop+(theight-i)*i+(theight-i); - } - dbgtotalflop = dbgtotalflop+uflop; - dbgcholeskyflop = dbgcholeskyflop+uflop; - if( twidth==4 ) - { - dbgcholesky4flop = dbgcholesky4flop+uflop; - } - } - - /* - * Output - */ - ae_trace("> node size statistics:\n"); - ae_trace("rank1 = %6d\n", - (int)(dbgrank1nodes)); - ae_trace("rank2 = %6d\n", - (int)(dbgrank2nodes)); - ae_trace("rank3 = %6d\n", - (int)(dbgrank3nodes)); - ae_trace("rank4 = %6d\n", - (int)(dbgrank4nodes)); - ae_trace("big nodes = %6d\n", - (int)(dbgbignodes)); - ae_trace("> Total FLOP count (fused multiply-adds):\n"); - ae_trace("total = %8.2f MFLOP\n", - (double)(1.0E-6*dbgtotalflop)); - ae_trace("> FLOP counts for updates:\n"); - ae_trace("no-sctr = %8.2f MFLOP (no row scatter, no col scatter, best case)\n", - (double)(1.0E-6*dbgnoscatterflop)); - ae_trace("M4*44->N4 = %8.2f MFLOP (no col scatter, big blocks, good case)\n", - (double)(1.0E-6*dbg444flop)); - ae_trace("no-row-sctr = %8.2f MFLOP (no row scatter, good case for col-wise storage)\n", - (double)(1.0E-6*dbgnorowscatterflop)); - ae_trace("no-col-sctr = %8.2f MFLOP (no col scatter, good case for row-wise storage)\n", - (double)(1.0E-6*dbgnocolscatterflop)); - ae_trace("XX*XX->N4 = %8.2f MFLOP\n", - (double)(1.0E-6*dbgxx4flop)); - ae_trace("rank1 = %8.2f MFLOP\n", - (double)(1.0E-6*dbgrank1flop)); - ae_trace("rank4+ = %8.2f MFLOP\n", - (double)(1.0E-6*dbgrank4plusflop)); - ae_trace("> FLOP counts for Cholesky:\n"); - ae_trace("cholesky = %8.2f MFLOP\n", - (double)(1.0E-6*dbgcholeskyflop)); - ae_trace("cholesky4 = %8.2f MFLOP\n", - (double)(1.0E-6*dbgcholesky4flop)); - } -} - - -/************************************************************************* -This function extracts computed matrix from the supernodal storage. -Depending on settings, a supernodal permutation can be applied to the matrix. - -INPUT PARAMETERS - Analysis - analysis object with completely initialized supernodal - structure - Offsets - offsets for supernodal storage - Strides - row strides for supernodal storage - RowStorage - supernodal storage - DiagD - diagonal factor - N - problem size - - TmpP - preallocated temporary array[N+1] - -OUTPUT PARAMETERS - A - sparse matrix in CRS format: - * for PermType=0, sparse matrix in the original ordering - (i.e. the matrix is reordered prior to output that - may require considerable amount of operations due to - permutation being applied) - * for PermType=1, sparse matrix in the topological - ordering. The least overhead for output. - D - array[N], diagonal - P - output permutation in product form - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void spchol_extractmatrix(spcholanalysis* analysis, - /* Integer */ ae_vector* offsets, - /* Integer */ ae_vector* strides, - /* Real */ ae_vector* rowstorage, - /* Real */ ae_vector* diagd, - ae_int_t n, - sparsematrix* a, - /* Real */ ae_vector* d, - /* Integer */ ae_vector* p, - /* Integer */ ae_vector* tmpp, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t sidx; - ae_int_t i0; - ae_int_t ii; - ae_int_t rfirst; - ae_int_t rlast; - ae_int_t cols0; - ae_int_t cols1; - ae_int_t blocksize; - ae_int_t rowstride; - ae_int_t offdiagsize; - ae_int_t offssdiag; - - - ae_assert(tmpp->cnt>=n+1, "ExtractMatrix: preallocated temporary TmpP is too short", _state); - - /* - * Basic initialization - */ - a->matrixtype = 1; - a->n = n; - a->m = n; - - /* - * Various permutation types - */ - if( analysis->applypermutationtooutput ) - { - ae_assert(analysis->istopologicalordering, "ExtractMatrix: critical integrity check failed (attempt to merge in nontopological permutation)", _state); - - /* - * Output matrix is topologically permuted, so we return A=L*L' instead of A=P*L*L'*P'. - * Somewhat inefficient because we have to apply permutation to L returned by supernodal code. - */ - ivectorsetlengthatleast(&a->ridx, n+1, _state); - ivectorsetlengthatleast(&a->didx, n, _state); - a->ridx.ptr.p_int[0] = 0; - for(i=0; i<=n-1; i++) - { - a->ridx.ptr.p_int[i+1] = a->ridx.ptr.p_int[i]+analysis->outrowcounts.ptr.p_int[analysis->effectiveperm.ptr.p_int[i]]; - } - for(i=0; i<=n-1; i++) - { - a->didx.ptr.p_int[i] = a->ridx.ptr.p_int[i]; - } - a->ninitialized = a->ridx.ptr.p_int[n]; - rvectorsetlengthatleast(&a->vals, a->ninitialized, _state); - ivectorsetlengthatleast(&a->idx, a->ninitialized, _state); - for(sidx=0; sidx<=analysis->nsuper-1; sidx++) - { - cols0 = analysis->supercolrange.ptr.p_int[sidx]; - cols1 = analysis->supercolrange.ptr.p_int[sidx+1]; - rfirst = analysis->superrowridx.ptr.p_int[sidx]; - rlast = analysis->superrowridx.ptr.p_int[sidx+1]; - blocksize = cols1-cols0; - offdiagsize = rlast-rfirst; - rowstride = strides->ptr.p_int[sidx]; - offssdiag = offsets->ptr.p_int[sidx]; - for(i=0; i<=blocksize-1; i++) - { - i0 = analysis->inveffectiveperm.ptr.p_int[cols0+i]; - ii = a->didx.ptr.p_int[i0]; - for(j=0; j<=i; j++) - { - a->idx.ptr.p_int[ii] = analysis->inveffectiveperm.ptr.p_int[cols0+j]; - a->vals.ptr.p_double[ii] = rowstorage->ptr.p_double[offssdiag+i*rowstride+j]; - ii = ii+1; - } - a->didx.ptr.p_int[i0] = ii; - } - for(k=0; k<=offdiagsize-1; k++) - { - i0 = analysis->inveffectiveperm.ptr.p_int[analysis->superrowidx.ptr.p_int[k+rfirst]]; - ii = a->didx.ptr.p_int[i0]; - for(j=0; j<=blocksize-1; j++) - { - a->idx.ptr.p_int[ii] = analysis->inveffectiveperm.ptr.p_int[cols0+j]; - a->vals.ptr.p_double[ii] = rowstorage->ptr.p_double[offssdiag+(blocksize+k)*rowstride+j]; - ii = ii+1; - } - a->didx.ptr.p_int[i0] = ii; - } - } - for(i=0; i<=n-1; i++) - { - ae_assert(a->didx.ptr.p_int[i]==a->ridx.ptr.p_int[i+1], "ExtractMatrix: integrity check failed (9473t)", _state); - tagsortmiddleir(&a->idx, &a->vals, a->ridx.ptr.p_int[i], a->ridx.ptr.p_int[i+1]-a->ridx.ptr.p_int[i], _state); - ae_assert(a->idx.ptr.p_int[a->ridx.ptr.p_int[i+1]-1]==i, "ExtractMatrix: integrity check failed (e4tfd)", _state); - } - sparseinitduidx(a, _state); - - /* - * Prepare D[] and P[] - */ - rvectorsetlengthatleast(d, n, _state); - ivectorsetlengthatleast(p, n, _state); - for(i=0; i<=n-1; i++) - { - d->ptr.p_double[i] = diagd->ptr.p_double[analysis->effectiveperm.ptr.p_int[i]]; - p->ptr.p_int[i] = i; - } - } - else - { - - /* - * The permutation is NOT applied to L prior to extraction, - * we return both L and P: A=P*L*L'*P'. - */ - ivectorsetlengthatleast(&a->ridx, n+1, _state); - ivectorsetlengthatleast(&a->didx, n, _state); - a->ridx.ptr.p_int[0] = 0; - for(i=0; i<=n-1; i++) - { - a->ridx.ptr.p_int[i+1] = a->ridx.ptr.p_int[i]+analysis->outrowcounts.ptr.p_int[i]; - } - for(i=0; i<=n-1; i++) - { - a->didx.ptr.p_int[i] = a->ridx.ptr.p_int[i]; - } - a->ninitialized = a->ridx.ptr.p_int[n]; - rvectorsetlengthatleast(&a->vals, a->ninitialized, _state); - ivectorsetlengthatleast(&a->idx, a->ninitialized, _state); - for(sidx=0; sidx<=analysis->nsuper-1; sidx++) - { - cols0 = analysis->supercolrange.ptr.p_int[sidx]; - cols1 = analysis->supercolrange.ptr.p_int[sidx+1]; - rfirst = analysis->superrowridx.ptr.p_int[sidx]; - rlast = analysis->superrowridx.ptr.p_int[sidx+1]; - blocksize = cols1-cols0; - offdiagsize = rlast-rfirst; - rowstride = strides->ptr.p_int[sidx]; - offssdiag = offsets->ptr.p_int[sidx]; - for(i=0; i<=blocksize-1; i++) - { - i0 = cols0+i; - ii = a->didx.ptr.p_int[i0]; - for(j=0; j<=i; j++) - { - a->idx.ptr.p_int[ii] = cols0+j; - a->vals.ptr.p_double[ii] = rowstorage->ptr.p_double[offssdiag+i*rowstride+j]; - ii = ii+1; - } - a->didx.ptr.p_int[i0] = ii; - } - for(k=0; k<=offdiagsize-1; k++) - { - i0 = analysis->superrowidx.ptr.p_int[k+rfirst]; - ii = a->didx.ptr.p_int[i0]; - for(j=0; j<=blocksize-1; j++) - { - a->idx.ptr.p_int[ii] = cols0+j; - a->vals.ptr.p_double[ii] = rowstorage->ptr.p_double[offssdiag+(blocksize+k)*rowstride+j]; - ii = ii+1; - } - a->didx.ptr.p_int[i0] = ii; - } - } - for(i=0; i<=n-1; i++) - { - ae_assert(a->didx.ptr.p_int[i]==a->ridx.ptr.p_int[i+1], "ExtractMatrix: integrity check failed (34e43)", _state); - ae_assert(a->idx.ptr.p_int[a->ridx.ptr.p_int[i+1]-1]==i, "ExtractMatrix: integrity check failed (k4df5)", _state); - } - sparseinitduidx(a, _state); - - /* - * Extract diagonal - */ - rvectorsetlengthatleast(d, n, _state); - for(i=0; i<=n-1; i++) - { - d->ptr.p_double[i] = diagd->ptr.p_double[i]; - } - - /* - * Convert permutation table into product form - */ - ivectorsetlengthatleast(p, n, _state); - for(i=0; i<=n-1; i++) - { - p->ptr.p_int[i] = i; - tmpp->ptr.p_int[i] = i; - } - for(i=0; i<=n-1; i++) - { - - /* - * We need to move element K to position I. - * J is where K actually stored - */ - k = analysis->inveffectiveperm.ptr.p_int[i]; - j = tmpp->ptr.p_int[k]; - - /* - * Swap elements of P[I:N-1] that is used to store current locations of elements in different way - */ - i0 = p->ptr.p_int[i]; - p->ptr.p_int[i] = p->ptr.p_int[j]; - p->ptr.p_int[j] = i0; - - /* - * record pivoting of positions I and J - */ - p->ptr.p_int[i] = j; - tmpp->ptr.p_int[i0] = j; - } - } -} - - -/************************************************************************* -This function is a specialized version of SparseSymmPermTbl() that takes -into account specifics of topological reorderings (improves performance) -and additionally transposes its output. - -INPUT PARAMETERS - A - sparse lower triangular matrix in CRS format. - P - array[N] which stores permutation table; P[I]=J means - that I-th row/column of matrix A is moved to J-th - position. For performance reasons we do NOT check that - P[] is a correct permutation (that there is no - repetitions, just that all its elements are in [0,N) - range. - B - sparse matrix object that will hold output. - Previously allocated memory will be reused as much as - possible. - -OUTPUT PARAMETERS - B - permuted and transposed upper triangular matrix in the - special internal CRS-like matrix format (MatrixType=-10082). - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -static void spchol_topologicalpermutation(sparsematrix* a, - /* Integer */ ae_vector* p, - sparsematrix* b, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t jj; - ae_int_t j0; - ae_int_t j1; - ae_int_t k; - ae_int_t k0; - ae_int_t n; - ae_bool bflag; - - - ae_assert(a->matrixtype==1, "TopologicalPermutation: incorrect matrix type (convert your matrix to CRS)", _state); - ae_assert(p->cnt>=a->n, "TopologicalPermutation: Length(P)m==a->n, "TopologicalPermutation: matrix is non-square", _state); - ae_assert(a->ninitialized==a->ridx.ptr.p_int[a->n], "TopologicalPermutation: integrity check failed", _state); - bflag = ae_true; - n = a->n; - for(i=0; i<=n-1; i++) - { - j = p->ptr.p_int[i]; - bflag = (bflag&&j>=0)&&jmatrixtype = -10082; - b->n = n; - b->m = n; - ivectorsetlengthatleast(&b->didx, n, _state); - ivectorsetlengthatleast(&b->uidx, n, _state); - - /* - * Determine row sizes (temporary stored in DIdx) and ranges - */ - isetv(n, 0, &b->uidx, _state); - for(i=0; i<=n-1; i++) - { - j0 = a->ridx.ptr.p_int[i]; - j1 = a->uidx.ptr.p_int[i]-1; - for(jj=j0; jj<=j1; jj++) - { - j = a->idx.ptr.p_int[jj]; - b->uidx.ptr.p_int[j] = b->uidx.ptr.p_int[j]+1; - } - } - for(i=0; i<=n-1; i++) - { - b->didx.ptr.p_int[p->ptr.p_int[i]] = b->uidx.ptr.p_int[i]; - } - ivectorsetlengthatleast(&b->ridx, n+1, _state); - b->ridx.ptr.p_int[0] = 0; - for(i=0; i<=n-1; i++) - { - b->ridx.ptr.p_int[i+1] = b->ridx.ptr.p_int[i]+b->didx.ptr.p_int[i]; - b->uidx.ptr.p_int[i] = b->ridx.ptr.p_int[i]; - } - b->ninitialized = b->ridx.ptr.p_int[n]; - ivectorsetlengthatleast(&b->idx, b->ninitialized, _state); - rvectorsetlengthatleast(&b->vals, b->ninitialized, _state); - - /* - * Process matrix - */ - for(i=0; i<=n-1; i++) - { - j0 = a->ridx.ptr.p_int[i]; - j1 = a->uidx.ptr.p_int[i]-1; - k = p->ptr.p_int[i]; - for(jj=j0; jj<=j1; jj++) - { - j = p->ptr.p_int[a->idx.ptr.p_int[jj]]; - k0 = b->uidx.ptr.p_int[j]; - b->idx.ptr.p_int[k0] = k; - b->vals.ptr.p_double[k0] = a->vals.ptr.p_double[jj]; - b->uidx.ptr.p_int[j] = k0+1; - } - } -} - - -/************************************************************************* -Determine nonzero pattern of the column. - -This function takes as input: -* A^T - transpose of original input matrix -* index of column of L being computed -* SuperRowRIdx[] and SuperRowIdx[] - arrays that store row structure of - supernodes, and NSuper - supernodes count -* ChildrenNodesR[], ChildrenNodesI[] - arrays that store children nodes - for each node -* Node2Supernode[] - array that maps node indexes to supernodes -* TrueArray[] - array[N] that has all of its elements set to True (this - invariant is preserved on output) -* Tmp0[] - array[N], temporary array - -As output, it constructs nonzero pattern (diagonal element not included) -of the column #ColumnIdx on top of SuperRowIdx[] array, starting at -location SuperRowIdx[SuperRowRIdx[NSuper]] and till location -SuperRowIdx[Result-1], where Result is a function result. - -The SuperRowIdx[] array is automatically resized as needed. - -It is important that this function computes nonzero pattern, but it does -NOT change other supernodal structures. The caller still has to finalize -the column (setup supernode ranges, mappings, etc). - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -static ae_int_t spchol_computenonzeropattern(sparsematrix* wrkat, - ae_int_t columnidx, - ae_int_t n, - /* Integer */ ae_vector* superrowridx, - /* Integer */ ae_vector* superrowidx, - ae_int_t nsuper, - /* Integer */ ae_vector* childrennodesr, - /* Integer */ ae_vector* childrennodesi, - /* Integer */ ae_vector* node2supernode, - /* Boolean */ ae_vector* truearray, - /* Integer */ ae_vector* tmp0, - ae_state *_state) -{ - ae_int_t i; - ae_int_t ii; - ae_int_t jj; - ae_int_t i0; - ae_int_t i1; - ae_int_t j0; - ae_int_t j1; - ae_int_t cidx; - ae_int_t rfirst; - ae_int_t rlast; - ae_int_t tfirst; - ae_int_t tlast; - ae_int_t supernodalchildrencount; - ae_int_t result; - - - ae_assert(truearray->cnt>=n, "ComputeNonzeroPattern: input temporary is too short", _state); - ae_assert(tmp0->cnt>=n, "ComputeNonzeroPattern: input temporary is too short", _state); - - /* - * Determine supernodal children in Tmp0 - */ - supernodalchildrencount = 0; - i0 = childrennodesr->ptr.p_int[columnidx]; - i1 = childrennodesr->ptr.p_int[columnidx+1]-1; - for(ii=i0; ii<=i1; ii++) - { - i = node2supernode->ptr.p_int[childrennodesi->ptr.p_int[ii]]; - if( truearray->ptr.p_bool[i] ) - { - tmp0->ptr.p_int[supernodalchildrencount] = i; - truearray->ptr.p_bool[i] = ae_false; - supernodalchildrencount = supernodalchildrencount+1; - } - } - for(i=0; i<=supernodalchildrencount-1; i++) - { - truearray->ptr.p_bool[tmp0->ptr.p_int[i]] = ae_true; - } - - /* - * Initialized column by nonzero pattern from A - */ - rfirst = superrowridx->ptr.p_int[nsuper]; - tfirst = rfirst+n; - igrowv(rfirst+2*n, superrowidx, _state); - i0 = wrkat->ridx.ptr.p_int[columnidx]+1; - i1 = wrkat->ridx.ptr.p_int[columnidx+1]; - icopyvx(i1-i0, &wrkat->idx, i0, superrowidx, rfirst, _state); - rlast = rfirst+(i1-i0); - - /* - * For column with small number of children use ordered merge algorithm. - * For column with many children it is better to perform unsorted merge, - * and then sort the sequence. - */ - if( supernodalchildrencount<=4 ) - { - - /* - * Ordered merge. The best approach for small number of children, - * but may have O(N^2) running time when O(N) children are present. - */ - for(cidx=0; cidx<=supernodalchildrencount-1; cidx++) - { - - /* - * Skip initial elements that do not contribute to subdiagonal nonzero pattern - */ - i0 = superrowridx->ptr.p_int[tmp0->ptr.p_int[cidx]]; - i1 = superrowridx->ptr.p_int[tmp0->ptr.p_int[cidx]+1]-1; - while(i0<=i1&&superrowidx->ptr.p_int[i0]<=columnidx) - { - i0 = i0+1; - } - j0 = rfirst; - j1 = rlast-1; - - /* - * Handle degenerate cases: empty merge target or empty merge source. - */ - if( j1ptr.p_int[i0]; - jj = superrowidx->ptr.p_int[j0]; - tlast = tfirst; - for(;;) - { - if( iiptr.p_int[tlast] = ii; - tlast = tlast+1; - i0 = i0+1; - if( i0>i1 ) - { - break; - } - ii = superrowidx->ptr.p_int[i0]; - } - if( jjptr.p_int[tlast] = jj; - tlast = tlast+1; - j0 = j0+1; - if( j0>j1 ) - { - break; - } - jj = superrowidx->ptr.p_int[j0]; - } - if( jj==ii ) - { - superrowidx->ptr.p_int[tlast] = ii; - tlast = tlast+1; - i0 = i0+1; - j0 = j0+1; - if( i0>i1 ) - { - break; - } - if( j0>j1 ) - { - break; - } - ii = superrowidx->ptr.p_int[i0]; - jj = superrowidx->ptr.p_int[j0]; - } - } - for(ii=i0; ii<=i1; ii++) - { - superrowidx->ptr.p_int[tlast] = superrowidx->ptr.p_int[ii]; - tlast = tlast+1; - } - for(jj=j0; jj<=j1; jj++) - { - superrowidx->ptr.p_int[tlast] = superrowidx->ptr.p_int[jj]; - tlast = tlast+1; - } - icopyvx(tlast-tfirst, superrowidx, tfirst, superrowidx, rfirst, _state); - rlast = rfirst+(tlast-tfirst); - } - result = rlast; - } - else - { - - /* - * Unordered merge followed by sort. Guaranteed N*logN worst case. - */ - for(ii=rfirst; ii<=rlast-1; ii++) - { - truearray->ptr.p_bool[superrowidx->ptr.p_int[ii]] = ae_false; - } - for(cidx=0; cidx<=supernodalchildrencount-1; cidx++) - { - - /* - * Skip initial elements that do not contribute to subdiagonal nonzero pattern - */ - i0 = superrowridx->ptr.p_int[tmp0->ptr.p_int[cidx]]; - i1 = superrowridx->ptr.p_int[tmp0->ptr.p_int[cidx]+1]-1; - while(i0<=i1&&superrowidx->ptr.p_int[i0]<=columnidx) - { - i0 = i0+1; - } - - /* - * Append elements not present in the sequence - */ - for(ii=i0; ii<=i1; ii++) - { - i = superrowidx->ptr.p_int[ii]; - if( truearray->ptr.p_bool[i] ) - { - superrowidx->ptr.p_int[rlast] = i; - rlast = rlast+1; - truearray->ptr.p_bool[i] = ae_false; - } - } - } - for(ii=rfirst; ii<=rlast-1; ii++) - { - truearray->ptr.p_bool[superrowidx->ptr.p_int[ii]] = ae_true; - } - tagsortmiddlei(superrowidx, rfirst, rlast-rfirst, _state); - result = rlast; - } - return result; -} - - -/************************************************************************* -Update target supernode with data from one of its children. This operation -is a supernodal equivalent of the column update in the left-looking -Cholesky. - -The generic update has following form: - - S := S - scatter(U*D*Uc') - -where -* S is an tHeight*tWidth rectangular target matrix that is: - * stored with tStride>=tWidth in RowStorage[OffsS:OffsS+tHeight*tStride-1] - * lower trapezoidal i.e. its leading tWidth*tWidth submatrix is lower - triangular. One may update either entire tWidth*tWidth submatrix or - just its lower part, because upper triangle is not referenced anyway. - * the height of S is not given because it is not actually needed -* U is an uHeight*uRank rectangular update matrix tht is: - * stored with row stride uStride>=uRank in RowStorage[OffsU:OffsU+uHeight*uStride-1]. -* Uc is the leading uWidth*uRank submatrix of U -* D is uRank*uRank diagonal matrix that is: - * stored in DiagD[OffsD:OffsD+uRank-1] - * unit, when Analysis.UnitD=True. In this case it can be ignored, although - DiagD still contains 1's in all of its entries -* uHeight<=tHeight, uWidth<=tWidth, so scatter operation is needed to update - S with smaller update. -* scatter() is an operation that extends smaller uHeight*uWidth update - matrix U*Uc' into larger tHeight*tWidth target matrix by adding zero rows - and columns into U*Uc': - * I-th row of update modifies Raw2SMap[SuperRowIdx[URBase+I]]-th row of - the matrix S - * J-th column of update modifies Raw2SMap[SuperRowIdx[URBase+J]]-th col - of the matrix S - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -static ae_int_t spchol_updatesupernode(spcholanalysis* analysis, - ae_int_t sidx, - ae_int_t cols0, - ae_int_t cols1, - ae_int_t offss, - /* Integer */ ae_vector* raw2smap, - ae_int_t uidx, - ae_int_t wrkrow, - /* Real */ ae_vector* diagd, - ae_int_t offsd, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t colu0; - ae_int_t colu1; - ae_int_t urbase; - ae_int_t urlast; - ae_int_t urank; - ae_int_t uwidth; - ae_int_t uheight; - ae_int_t urowstride; - ae_int_t twidth; - ae_int_t trowstride; - ae_int_t targetrow; - ae_int_t targetcol; - ae_int_t offsu; - ae_int_t offdiagrow; - ae_int_t lastrow; - ae_int_t offs0; - ae_int_t offsj; - ae_int_t offsk; - double v; - ae_int_t result; - - - twidth = cols1-cols0; - offsu = analysis->rowoffsets.ptr.p_int[uidx]; - colu0 = analysis->supercolrange.ptr.p_int[uidx]; - colu1 = analysis->supercolrange.ptr.p_int[uidx+1]; - urbase = analysis->superrowridx.ptr.p_int[uidx]; - urlast = analysis->superrowridx.ptr.p_int[uidx+1]; - urank = colu1-colu0; - trowstride = analysis->rowstrides.ptr.p_int[sidx]; - urowstride = analysis->rowstrides.ptr.p_int[uidx]; - - /* - * Skip leading uRank+WrkRow rows of U because they are not used. - */ - offsu = offsu+(colu1-colu0+wrkrow)*urowstride; - - /* - * Analyze range of rows in supernode LAdjPlus[II] and determine two subranges: - * * one with indexes stored at SuperRowIdx[WrkRow:OffdiagRow); - * these indexes are the ones that intersect with range of rows/columns [ColS0,ColS1) - * occupied by diagonal block of the supernode SIdx - * * one with indexes stored at SuperRowIdx[OffdiagRow:LastRow); - * these indexes are ones that intersect with range of rows occupied by - * offdiagonal block of the supernode SIdx - */ - if( analysis->extendeddebug ) - { - ae_assert(analysis->superrowidx.ptr.p_int[urbase+wrkrow]>=cols0, "SPCholFactorize: integrity check 6378 failed", _state); - ae_assert(analysis->superrowidx.ptr.p_int[urbase+wrkrow]superrowidx.ptr.p_int[offdiagrow+urbase]extendeddebug ) - { - - /* - * Extended integrity check (if requested) - */ - ae_assert(wrkrowsuperrowidx.ptr.p_int[wrkrow+urbase]>=cols0, "SPCholFactorize: integrity check failed (44trg6)", _state); - for(i=wrkrow; i<=lastrow-1; i++) - { - ae_assert(raw2smap->ptr.p_int[analysis->superrowidx.ptr.p_int[i+urbase]]>=0, "SPCholFactorize: integrity check failed (43t63)", _state); - } - } - - /* - * Handle special cases - */ - if( trowstride==4 ) - { - - /* - * Target is stride-4 column, try several kernels that may work with tWidth=3 and tWidth=4 - */ - if( ((uwidth==4&&twidth==4)&&urank==4)&&urowstride==4 ) - { - if( spchol_updatekernel4444(&analysis->rowstorage, offss, offsu, uheight, &analysis->diagd, colu0, raw2smap, &analysis->superrowidx, urbase+wrkrow, _state) ) - { - return result; - } - } - if( spchol_updatekernelabc4(&analysis->rowstorage, offss, twidth, offsu, uheight, urank, urowstride, uwidth, &analysis->diagd, colu0, raw2smap, &analysis->superrowidx, urbase+wrkrow, _state) ) - { - return result; - } - } - if( urank==1&&urowstride==1 ) - { - if( spchol_updatekernelrank1(&analysis->rowstorage, offss, twidth, trowstride, offsu, uheight, uwidth, &analysis->diagd, colu0, raw2smap, &analysis->superrowidx, urbase+wrkrow, _state) ) - { - return result; - } - } - if( urank==2&&urowstride==2 ) - { - if( spchol_updatekernelrank2(&analysis->rowstorage, offss, twidth, trowstride, offsu, uheight, uwidth, &analysis->diagd, colu0, raw2smap, &analysis->superrowidx, urbase+wrkrow, _state) ) - { - return result; - } - } - - /* - * Handle general update, rerefence code - */ - ivectorsetlengthatleast(&analysis->u2smap, uheight, _state); - for(i=0; i<=uheight-1; i++) - { - analysis->u2smap.ptr.p_int[i] = raw2smap->ptr.p_int[analysis->superrowidx.ptr.p_int[urbase+wrkrow+i]]; - } - if( analysis->unitd ) - { - - /* - * Unit D, vanilla Cholesky - */ - for(k=0; k<=uheight-1; k++) - { - targetrow = offss+analysis->u2smap.ptr.p_int[k]*trowstride; - for(j=0; j<=uwidth-1; j++) - { - targetcol = analysis->u2smap.ptr.p_int[j]; - offsj = offsu+j*urowstride; - offsk = offsu+k*urowstride; - offs0 = targetrow+targetcol; - v = analysis->rowstorage.ptr.p_double[offs0]; - for(i=0; i<=urank-1; i++) - { - v = v-analysis->rowstorage.ptr.p_double[offsj+i]*analysis->rowstorage.ptr.p_double[offsk+i]; - } - analysis->rowstorage.ptr.p_double[offs0] = v; - } - } - } - else - { - - /* - * Non-unit D, LDLT decomposition - */ - for(k=0; k<=uheight-1; k++) - { - targetrow = offss+analysis->u2smap.ptr.p_int[k]*trowstride; - for(j=0; j<=uwidth-1; j++) - { - targetcol = analysis->u2smap.ptr.p_int[j]; - offsj = offsu+j*urowstride; - offsk = offsu+k*urowstride; - offs0 = targetrow+targetcol; - v = analysis->rowstorage.ptr.p_double[offs0]; - for(i=0; i<=urank-1; i++) - { - v = v-analysis->rowstorage.ptr.p_double[offsj+i]*diagd->ptr.p_double[offsd+i]*analysis->rowstorage.ptr.p_double[offsk+i]; - } - analysis->rowstorage.ptr.p_double[offs0] = v; - } - } - } - return result; -} - - -/************************************************************************* -Factorizes target supernode, returns True on success, False on failure. - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -static ae_bool spchol_factorizesupernode(spcholanalysis* analysis, - ae_int_t sidx, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t cols0; - ae_int_t cols1; - ae_int_t offss; - ae_int_t blocksize; - ae_int_t offdiagsize; - ae_int_t sstride; - double v; - double vs; - double possignvraw; - ae_bool controlpivot; - ae_bool controloverflow; - ae_bool result; - - - cols0 = analysis->supercolrange.ptr.p_int[sidx]; - cols1 = analysis->supercolrange.ptr.p_int[sidx+1]; - offss = analysis->rowoffsets.ptr.p_int[sidx]; - blocksize = cols1-cols0; - offdiagsize = analysis->superrowridx.ptr.p_int[sidx+1]-analysis->superrowridx.ptr.p_int[sidx]; - sstride = analysis->rowstrides.ptr.p_int[sidx]; - controlpivot = analysis->modtype==1&&ae_fp_greater(analysis->modparam0,(double)(0)); - controloverflow = analysis->modtype==1&&ae_fp_greater(analysis->modparam1,(double)(0)); - if( analysis->unitd ) - { - - /* - * Classic Cholesky - */ - for(j=0; j<=blocksize-1; j++) - { - - /* - * Compute J-th column - */ - vs = (double)(0); - for(k=j; k<=blocksize+offdiagsize-1; k++) - { - v = analysis->rowstorage.ptr.p_double[offss+k*sstride+j]; - for(i=0; i<=j-1; i++) - { - v = v-analysis->rowstorage.ptr.p_double[offss+k*sstride+i]*analysis->rowstorage.ptr.p_double[offss+j*sstride+i]; - } - analysis->rowstorage.ptr.p_double[offss+k*sstride+j] = v; - vs = vs+ae_fabs(v, _state); - } - if( controloverflow&&ae_fp_greater(vs,analysis->modparam1) ) - { - - /* - * Possible failure due to accumulation of numerical errors - */ - result = ae_false; - return result; - } - - /* - * Handle pivot element - */ - v = analysis->rowstorage.ptr.p_double[offss+j*sstride+j]; - if( controlpivot&&ae_fp_less_eq(v,analysis->modparam0) ) - { - - /* - * Basic modified Cholesky - */ - v = ae_sqrt(analysis->modparam0, _state); - analysis->diagd.ptr.p_double[cols0+j] = 1.0; - analysis->rowstorage.ptr.p_double[offss+j*sstride+j] = v; - v = 1/v; - for(k=j+1; k<=blocksize+offdiagsize-1; k++) - { - analysis->rowstorage.ptr.p_double[offss+k*sstride+j] = v*analysis->rowstorage.ptr.p_double[offss+k*sstride+j]; - } - } - else - { - - /* - * Default case - */ - if( ae_fp_less_eq(v,(double)(0)) ) - { - result = ae_false; - return result; - } - analysis->diagd.ptr.p_double[cols0+j] = 1.0; - v = 1/ae_sqrt(v, _state); - for(k=j; k<=blocksize+offdiagsize-1; k++) - { - analysis->rowstorage.ptr.p_double[offss+k*sstride+j] = v*analysis->rowstorage.ptr.p_double[offss+k*sstride+j]; - } - } - } - } - else - { - - /* - * LDLT with diagonal D - */ - for(j=0; j<=blocksize-1; j++) - { - - /* - * Compute J-th column - */ - vs = (double)(0); - for(k=j; k<=blocksize+offdiagsize-1; k++) - { - v = analysis->rowstorage.ptr.p_double[offss+k*sstride+j]; - for(i=0; i<=j-1; i++) - { - v = v-analysis->rowstorage.ptr.p_double[offss+k*sstride+i]*analysis->diagd.ptr.p_double[cols0+i]*analysis->rowstorage.ptr.p_double[offss+j*sstride+i]; - } - analysis->rowstorage.ptr.p_double[offss+k*sstride+j] = v; - vs = vs+ae_fabs(v, _state); - } - if( controloverflow&&ae_fp_greater(vs,analysis->modparam1) ) - { - - /* - * Possible failure due to accumulation of numerical errors - */ - result = ae_false; - return result; - } - - /* - * Handle pivot element - */ - ae_assert(analysis->wrkat.idx.ptr.p_int[analysis->wrkat.ridx.ptr.p_int[cols0+j]]==cols0+j, "FactorizeSupernode: integrity check failed", _state); - possignvraw = possign(analysis->wrkat.vals.ptr.p_double[analysis->wrkat.ridx.ptr.p_int[cols0+j]], _state); - v = analysis->rowstorage.ptr.p_double[offss+j*sstride+j]; - if( controlpivot&&ae_fp_less_eq(v/possignvraw,analysis->modparam0) ) - { - - /* - * Basic modified LDLT - */ - v = possignvraw*analysis->modparam0; - analysis->diagd.ptr.p_double[cols0+j] = v; - analysis->rowstorage.ptr.p_double[offss+j*sstride+j] = 1.0; - v = 1/v; - for(k=j+1; k<=blocksize+offdiagsize-1; k++) - { - analysis->rowstorage.ptr.p_double[offss+k*sstride+j] = v*analysis->rowstorage.ptr.p_double[offss+k*sstride+j]; - } - } - else - { - - /* - * Unmodified LDLT - */ - if( ae_fp_eq(v,(double)(0)) ) - { - result = ae_false; - return result; - } - analysis->diagd.ptr.p_double[cols0+j] = v; - v = 1/v; - for(k=j; k<=blocksize+offdiagsize-1; k++) - { - analysis->rowstorage.ptr.p_double[offss+k*sstride+j] = v*analysis->rowstorage.ptr.p_double[offss+k*sstride+j]; - } - } - } - } - result = ae_true; - return result; -} - - -/************************************************************************* -This function returns recommended stride for given row size - - -- ALGLIB routine -- - 20.10.2020 - Bochkanov Sergey -*************************************************************************/ -static ae_int_t spchol_recommendedstridefor(ae_int_t rowsize, - ae_state *_state) -{ - ae_int_t result; - - - result = rowsize; - if( rowsize==3 ) - { - result = 4; - } - return result; -} - - -/************************************************************************* -This function aligns position in array in order to better accommodate to -SIMD specifics. - -NOTE: this function aligns position measured in double precision numbers, - not in bits or bytes. If you want to have 256-bit aligned position, - round Offs to nearest multiple of 4 that is not less than Offs. - - -- ALGLIB routine -- - 20.10.2020 - Bochkanov Sergey -*************************************************************************/ -static ae_int_t spchol_alignpositioninarray(ae_int_t offs, - ae_state *_state) -{ - ae_int_t result; - - - result = offs; - if( offs%4!=0 ) - { - result = result+(4-offs%4); - } - return result; -} - - -/************************************************************************* -Fast kernels for small supernodal updates: special 4x4x4x4 function. - -! See comments on UpdateSupernode() for information on generic supernodal -! updates, including notation used below. - -The generic update has following form: - - S := S - scatter(U*D*Uc') - -This specialized function performs 4x4x4x4 update, i.e.: -* S is a tHeight*4 matrix -* U is a uHeight*4 matrix -* Uc' is a 4*4 matrix -* scatter() scatters rows of U*Uc', but does not scatter columns (they are - densely packed). - -Return value: -* True if update was applied -* False if kernel refused to perform an update. - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -static ae_bool spchol_updatekernel4444(/* Real */ ae_vector* rowstorage, - ae_int_t offss, - ae_int_t offsu, - ae_int_t uheight, - /* Real */ ae_vector* diagd, - ae_int_t offsd, - /* Integer */ ae_vector* raw2smap, - /* Integer */ ae_vector* superrowidx, - ae_int_t urbase, - ae_state *_state) -{ - ae_int_t k; - ae_int_t targetrow; - ae_int_t offsk; - double d0; - double d1; - double d2; - double d3; - double u00; - double u01; - double u02; - double u03; - double u10; - double u11; - double u12; - double u13; - double u20; - double u21; - double u22; - double u23; - double u30; - double u31; - double u32; - double u33; - double uk0; - double uk1; - double uk2; - double uk3; - ae_bool result; - - - d0 = diagd->ptr.p_double[offsd+0]; - d1 = diagd->ptr.p_double[offsd+1]; - d2 = diagd->ptr.p_double[offsd+2]; - d3 = diagd->ptr.p_double[offsd+3]; - u00 = d0*rowstorage->ptr.p_double[offsu+0*4+0]; - u01 = d1*rowstorage->ptr.p_double[offsu+0*4+1]; - u02 = d2*rowstorage->ptr.p_double[offsu+0*4+2]; - u03 = d3*rowstorage->ptr.p_double[offsu+0*4+3]; - u10 = d0*rowstorage->ptr.p_double[offsu+1*4+0]; - u11 = d1*rowstorage->ptr.p_double[offsu+1*4+1]; - u12 = d2*rowstorage->ptr.p_double[offsu+1*4+2]; - u13 = d3*rowstorage->ptr.p_double[offsu+1*4+3]; - u20 = d0*rowstorage->ptr.p_double[offsu+2*4+0]; - u21 = d1*rowstorage->ptr.p_double[offsu+2*4+1]; - u22 = d2*rowstorage->ptr.p_double[offsu+2*4+2]; - u23 = d3*rowstorage->ptr.p_double[offsu+2*4+3]; - u30 = d0*rowstorage->ptr.p_double[offsu+3*4+0]; - u31 = d1*rowstorage->ptr.p_double[offsu+3*4+1]; - u32 = d2*rowstorage->ptr.p_double[offsu+3*4+2]; - u33 = d3*rowstorage->ptr.p_double[offsu+3*4+3]; - for(k=0; k<=uheight-1; k++) - { - targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*4; - offsk = offsu+k*4; - uk0 = rowstorage->ptr.p_double[offsk+0]; - uk1 = rowstorage->ptr.p_double[offsk+1]; - uk2 = rowstorage->ptr.p_double[offsk+2]; - uk3 = rowstorage->ptr.p_double[offsk+3]; - rowstorage->ptr.p_double[targetrow+0] = rowstorage->ptr.p_double[targetrow+0]-u00*uk0-u01*uk1-u02*uk2-u03*uk3; - rowstorage->ptr.p_double[targetrow+1] = rowstorage->ptr.p_double[targetrow+1]-u10*uk0-u11*uk1-u12*uk2-u13*uk3; - rowstorage->ptr.p_double[targetrow+2] = rowstorage->ptr.p_double[targetrow+2]-u20*uk0-u21*uk1-u22*uk2-u23*uk3; - rowstorage->ptr.p_double[targetrow+3] = rowstorage->ptr.p_double[targetrow+3]-u30*uk0-u31*uk1-u32*uk2-u33*uk3; - } - result = ae_true; - return result; -} - - -/************************************************************************* -Fast kernels for small supernodal updates: special 4x4x4x4 function. - -! See comments on UpdateSupernode() for information on generic supernodal -! updates, including notation used below. - -The generic update has following form: - - S := S - scatter(U*D*Uc') - -This specialized function performs AxBxCx4 update, i.e.: -* S is a tHeight*A matrix with row stride equal to 4 (usually it means that - it has 3 or 4 columns) -* U is a uHeight*B matrix -* Uc' is a B*C matrix, with C<=A -* scatter() scatters rows and columns of U*Uc' - -Return value: -* True if update was applied -* False if kernel refused to perform an update (quick exit for unsupported - combinations of input sizes) - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -static ae_bool spchol_updatekernelabc4(/* Real */ ae_vector* rowstorage, - ae_int_t offss, - ae_int_t twidth, - ae_int_t offsu, - ae_int_t uheight, - ae_int_t urank, - ae_int_t urowstride, - ae_int_t uwidth, - /* Real */ ae_vector* diagd, - ae_int_t offsd, - /* Integer */ ae_vector* raw2smap, - /* Integer */ ae_vector* superrowidx, - ae_int_t urbase, - ae_state *_state) -{ - ae_int_t k; - ae_int_t targetrow; - ae_int_t targetcol; - ae_int_t offsk; - double d0; - double d1; - double d2; - double d3; - double u00; - double u01; - double u02; - double u03; - double u10; - double u11; - double u12; - double u13; - double u20; - double u21; - double u22; - double u23; - double u30; - double u31; - double u32; - double u33; - double uk0; - double uk1; - double uk2; - double uk3; - ae_int_t srccol0; - ae_int_t srccol1; - ae_int_t srccol2; - ae_int_t srccol3; - ae_bool result; - - - - /* - * Filter out unsupported combinations (ones that are too sparse for the non-SIMD code) - */ - result = ae_false; - if( twidth<3||twidth>4 ) - { - return result; - } - if( uwidth<3||uwidth>4 ) - { - return result; - } - if( urank>4 ) - { - return result; - } - - /* - * Determine source columns for target columns, -1 if target column - * is not updated. - */ - srccol0 = -1; - srccol1 = -1; - srccol2 = -1; - srccol3 = -1; - for(k=0; k<=uwidth-1; k++) - { - targetcol = raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]; - if( targetcol==0 ) - { - srccol0 = k; - } - if( targetcol==1 ) - { - srccol1 = k; - } - if( targetcol==2 ) - { - srccol2 = k; - } - if( targetcol==3 ) - { - srccol3 = k; - } - } - - /* - * Load update matrix into aligned/rearranged 4x4 storage - */ - d0 = (double)(0); - d1 = (double)(0); - d2 = (double)(0); - d3 = (double)(0); - u00 = (double)(0); - u01 = (double)(0); - u02 = (double)(0); - u03 = (double)(0); - u10 = (double)(0); - u11 = (double)(0); - u12 = (double)(0); - u13 = (double)(0); - u20 = (double)(0); - u21 = (double)(0); - u22 = (double)(0); - u23 = (double)(0); - u30 = (double)(0); - u31 = (double)(0); - u32 = (double)(0); - u33 = (double)(0); - if( urank>=1 ) - { - d0 = diagd->ptr.p_double[offsd+0]; - } - if( urank>=2 ) - { - d1 = diagd->ptr.p_double[offsd+1]; - } - if( urank>=3 ) - { - d2 = diagd->ptr.p_double[offsd+2]; - } - if( urank>=4 ) - { - d3 = diagd->ptr.p_double[offsd+3]; - } - if( srccol0>=0 ) - { - if( urank>=1 ) - { - u00 = d0*rowstorage->ptr.p_double[offsu+srccol0*urowstride+0]; - } - if( urank>=2 ) - { - u01 = d1*rowstorage->ptr.p_double[offsu+srccol0*urowstride+1]; - } - if( urank>=3 ) - { - u02 = d2*rowstorage->ptr.p_double[offsu+srccol0*urowstride+2]; - } - if( urank>=4 ) - { - u03 = d3*rowstorage->ptr.p_double[offsu+srccol0*urowstride+3]; - } - } - if( srccol1>=0 ) - { - if( urank>=1 ) - { - u10 = d0*rowstorage->ptr.p_double[offsu+srccol1*urowstride+0]; - } - if( urank>=2 ) - { - u11 = d1*rowstorage->ptr.p_double[offsu+srccol1*urowstride+1]; - } - if( urank>=3 ) - { - u12 = d2*rowstorage->ptr.p_double[offsu+srccol1*urowstride+2]; - } - if( urank>=4 ) - { - u13 = d3*rowstorage->ptr.p_double[offsu+srccol1*urowstride+3]; - } - } - if( srccol2>=0 ) - { - if( urank>=1 ) - { - u20 = d0*rowstorage->ptr.p_double[offsu+srccol2*urowstride+0]; - } - if( urank>=2 ) - { - u21 = d1*rowstorage->ptr.p_double[offsu+srccol2*urowstride+1]; - } - if( urank>=3 ) - { - u22 = d2*rowstorage->ptr.p_double[offsu+srccol2*urowstride+2]; - } - if( urank>=4 ) - { - u23 = d3*rowstorage->ptr.p_double[offsu+srccol2*urowstride+3]; - } - } - if( srccol3>=0 ) - { - if( urank>=1 ) - { - u30 = d0*rowstorage->ptr.p_double[offsu+srccol3*urowstride+0]; - } - if( urank>=2 ) - { - u31 = d1*rowstorage->ptr.p_double[offsu+srccol3*urowstride+1]; - } - if( urank>=3 ) - { - u32 = d2*rowstorage->ptr.p_double[offsu+srccol3*urowstride+2]; - } - if( urank>=4 ) - { - u33 = d3*rowstorage->ptr.p_double[offsu+srccol3*urowstride+3]; - } - } - - /* - * Run update - */ - if( urank==1 ) - { - for(k=0; k<=uheight-1; k++) - { - targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*4; - offsk = offsu+k*urowstride; - uk0 = rowstorage->ptr.p_double[offsk+0]; - rowstorage->ptr.p_double[targetrow+0] = rowstorage->ptr.p_double[targetrow+0]-u00*uk0; - rowstorage->ptr.p_double[targetrow+1] = rowstorage->ptr.p_double[targetrow+1]-u10*uk0; - rowstorage->ptr.p_double[targetrow+2] = rowstorage->ptr.p_double[targetrow+2]-u20*uk0; - rowstorage->ptr.p_double[targetrow+3] = rowstorage->ptr.p_double[targetrow+3]-u30*uk0; - } - } - if( urank==2 ) - { - for(k=0; k<=uheight-1; k++) - { - targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*4; - offsk = offsu+k*urowstride; - uk0 = rowstorage->ptr.p_double[offsk+0]; - uk1 = rowstorage->ptr.p_double[offsk+1]; - rowstorage->ptr.p_double[targetrow+0] = rowstorage->ptr.p_double[targetrow+0]-u00*uk0-u01*uk1; - rowstorage->ptr.p_double[targetrow+1] = rowstorage->ptr.p_double[targetrow+1]-u10*uk0-u11*uk1; - rowstorage->ptr.p_double[targetrow+2] = rowstorage->ptr.p_double[targetrow+2]-u20*uk0-u21*uk1; - rowstorage->ptr.p_double[targetrow+3] = rowstorage->ptr.p_double[targetrow+3]-u30*uk0-u31*uk1; - } - } - if( urank==3 ) - { - for(k=0; k<=uheight-1; k++) - { - targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*4; - offsk = offsu+k*urowstride; - uk0 = rowstorage->ptr.p_double[offsk+0]; - uk1 = rowstorage->ptr.p_double[offsk+1]; - uk2 = rowstorage->ptr.p_double[offsk+2]; - rowstorage->ptr.p_double[targetrow+0] = rowstorage->ptr.p_double[targetrow+0]-u00*uk0-u01*uk1-u02*uk2; - rowstorage->ptr.p_double[targetrow+1] = rowstorage->ptr.p_double[targetrow+1]-u10*uk0-u11*uk1-u12*uk2; - rowstorage->ptr.p_double[targetrow+2] = rowstorage->ptr.p_double[targetrow+2]-u20*uk0-u21*uk1-u22*uk2; - rowstorage->ptr.p_double[targetrow+3] = rowstorage->ptr.p_double[targetrow+3]-u30*uk0-u31*uk1-u32*uk2; - } - } - if( urank==4 ) - { - for(k=0; k<=uheight-1; k++) - { - targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*4; - offsk = offsu+k*urowstride; - uk0 = rowstorage->ptr.p_double[offsk+0]; - uk1 = rowstorage->ptr.p_double[offsk+1]; - uk2 = rowstorage->ptr.p_double[offsk+2]; - uk3 = rowstorage->ptr.p_double[offsk+3]; - rowstorage->ptr.p_double[targetrow+0] = rowstorage->ptr.p_double[targetrow+0]-u00*uk0-u01*uk1-u02*uk2-u03*uk3; - rowstorage->ptr.p_double[targetrow+1] = rowstorage->ptr.p_double[targetrow+1]-u10*uk0-u11*uk1-u12*uk2-u13*uk3; - rowstorage->ptr.p_double[targetrow+2] = rowstorage->ptr.p_double[targetrow+2]-u20*uk0-u21*uk1-u22*uk2-u23*uk3; - rowstorage->ptr.p_double[targetrow+3] = rowstorage->ptr.p_double[targetrow+3]-u30*uk0-u31*uk1-u32*uk2-u33*uk3; - } - } - result = ae_true; - return result; -} - - -/************************************************************************* -Fast kernels for small supernodal updates: special rank-1 function. - -! See comments on UpdateSupernode() for information on generic supernodal -! updates, including notation used below. - -The generic update has following form: - - S := S - scatter(U*D*Uc') - -This specialized function performs rank-1 update, i.e.: -* S is a tHeight*A matrix, with A<=4 -* U is a uHeight*1 matrix with unit stride -* Uc' is a 1*B matrix, with B<=A -* scatter() scatters rows and columns of U*Uc' - -Return value: -* True if update was applied -* False if kernel refused to perform an update (quick exit for unsupported - combinations of input sizes) - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -static ae_bool spchol_updatekernelrank1(/* Real */ ae_vector* rowstorage, - ae_int_t offss, - ae_int_t twidth, - ae_int_t trowstride, - ae_int_t offsu, - ae_int_t uheight, - ae_int_t uwidth, - /* Real */ ae_vector* diagd, - ae_int_t offsd, - /* Integer */ ae_vector* raw2smap, - /* Integer */ ae_vector* superrowidx, - ae_int_t urbase, - ae_state *_state) -{ - ae_int_t k; - ae_int_t targetrow; - double d0; - double u00; - double u10; - double u20; - double u30; - double uk; - ae_int_t col0; - ae_int_t col1; - ae_int_t col2; - ae_int_t col3; - ae_bool result; - - - - /* - * Filter out unsupported combinations (ones that are too sparse for the non-SIMD code) - */ - result = ae_false; - if( twidth>4 ) - { - return result; - } - if( uwidth>4 ) - { - return result; - } - - /* - * Determine target columns, load update matrix - */ - d0 = diagd->ptr.p_double[offsd]; - col0 = 0; - col1 = 0; - col2 = 0; - col3 = 0; - u00 = (double)(0); - u10 = (double)(0); - u20 = (double)(0); - u30 = (double)(0); - if( uwidth>=1 ) - { - col0 = raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+0]]; - u00 = d0*rowstorage->ptr.p_double[offsu+0]; - } - if( uwidth>=2 ) - { - col1 = raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+1]]; - u10 = d0*rowstorage->ptr.p_double[offsu+1]; - } - if( uwidth>=3 ) - { - col2 = raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+2]]; - u20 = d0*rowstorage->ptr.p_double[offsu+2]; - } - if( uwidth>=4 ) - { - col3 = raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+3]]; - u30 = d0*rowstorage->ptr.p_double[offsu+3]; - } - - /* - * Run update - */ - if( uwidth==1 ) - { - for(k=0; k<=uheight-1; k++) - { - targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*trowstride; - uk = rowstorage->ptr.p_double[offsu+k]; - rowstorage->ptr.p_double[targetrow+col0] = rowstorage->ptr.p_double[targetrow+col0]-u00*uk; - } - } - if( uwidth==2 ) - { - for(k=0; k<=uheight-1; k++) - { - targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*trowstride; - uk = rowstorage->ptr.p_double[offsu+k]; - rowstorage->ptr.p_double[targetrow+col0] = rowstorage->ptr.p_double[targetrow+col0]-u00*uk; - rowstorage->ptr.p_double[targetrow+col1] = rowstorage->ptr.p_double[targetrow+col1]-u10*uk; - } - } - if( uwidth==3 ) - { - for(k=0; k<=uheight-1; k++) - { - targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*trowstride; - uk = rowstorage->ptr.p_double[offsu+k]; - rowstorage->ptr.p_double[targetrow+col0] = rowstorage->ptr.p_double[targetrow+col0]-u00*uk; - rowstorage->ptr.p_double[targetrow+col1] = rowstorage->ptr.p_double[targetrow+col1]-u10*uk; - rowstorage->ptr.p_double[targetrow+col2] = rowstorage->ptr.p_double[targetrow+col2]-u20*uk; - } - } - if( uwidth==4 ) - { - for(k=0; k<=uheight-1; k++) - { - targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*trowstride; - uk = rowstorage->ptr.p_double[offsu+k]; - rowstorage->ptr.p_double[targetrow+col0] = rowstorage->ptr.p_double[targetrow+col0]-u00*uk; - rowstorage->ptr.p_double[targetrow+col1] = rowstorage->ptr.p_double[targetrow+col1]-u10*uk; - rowstorage->ptr.p_double[targetrow+col2] = rowstorage->ptr.p_double[targetrow+col2]-u20*uk; - rowstorage->ptr.p_double[targetrow+col3] = rowstorage->ptr.p_double[targetrow+col3]-u30*uk; - } - } - result = ae_true; - return result; -} - - -/************************************************************************* -Fast kernels for small supernodal updates: special rank-2 function. - -! See comments on UpdateSupernode() for information on generic supernodal -! updates, including notation used below. - -The generic update has following form: - - S := S - scatter(U*D*Uc') - -This specialized function performs rank-2 update, i.e.: -* S is a tHeight*A matrix, with A<=4 -* U is a uHeight*2 matrix with row stride equal to 2 -* Uc' is a 2*B matrix, with B<=A -* scatter() scatters rows and columns of U*Uc - -Return value: -* True if update was applied -* False if kernel refused to perform an update (quick exit for unsupported - combinations of input sizes) - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -static ae_bool spchol_updatekernelrank2(/* Real */ ae_vector* rowstorage, - ae_int_t offss, - ae_int_t twidth, - ae_int_t trowstride, - ae_int_t offsu, - ae_int_t uheight, - ae_int_t uwidth, - /* Real */ ae_vector* diagd, - ae_int_t offsd, - /* Integer */ ae_vector* raw2smap, - /* Integer */ ae_vector* superrowidx, - ae_int_t urbase, - ae_state *_state) -{ - ae_int_t k; - ae_int_t targetrow; - double d0; - double d1; - double u00; - double u10; - double u20; - double u30; - double u01; - double u11; - double u21; - double u31; - double uk0; - double uk1; - ae_int_t col0; - ae_int_t col1; - ae_int_t col2; - ae_int_t col3; - ae_bool result; - - - - /* - * Filter out unsupported combinations (ones that are too sparse for the non-SIMD code) - */ - result = ae_false; - if( twidth>4 ) - { - return result; - } - if( uwidth>4 ) - { - return result; - } - - /* - * Determine target columns, load update matrix - */ - d0 = diagd->ptr.p_double[offsd]; - d1 = diagd->ptr.p_double[offsd+1]; - col0 = 0; - col1 = 0; - col2 = 0; - col3 = 0; - u00 = (double)(0); - u01 = (double)(0); - u10 = (double)(0); - u11 = (double)(0); - u20 = (double)(0); - u21 = (double)(0); - u30 = (double)(0); - u31 = (double)(0); - if( uwidth>=1 ) - { - col0 = raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+0]]; - u00 = d0*rowstorage->ptr.p_double[offsu+0]; - u01 = d1*rowstorage->ptr.p_double[offsu+1]; - } - if( uwidth>=2 ) - { - col1 = raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+1]]; - u10 = d0*rowstorage->ptr.p_double[offsu+1*2+0]; - u11 = d1*rowstorage->ptr.p_double[offsu+1*2+1]; - } - if( uwidth>=3 ) - { - col2 = raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+2]]; - u20 = d0*rowstorage->ptr.p_double[offsu+2*2+0]; - u21 = d1*rowstorage->ptr.p_double[offsu+2*2+1]; - } - if( uwidth>=4 ) - { - col3 = raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+3]]; - u30 = d0*rowstorage->ptr.p_double[offsu+3*2+0]; - u31 = d1*rowstorage->ptr.p_double[offsu+3*2+1]; - } - - /* - * Run update - */ - if( uwidth==1 ) - { - for(k=0; k<=uheight-1; k++) - { - targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*trowstride; - uk0 = rowstorage->ptr.p_double[offsu+2*k+0]; - uk1 = rowstorage->ptr.p_double[offsu+2*k+1]; - rowstorage->ptr.p_double[targetrow+col0] = rowstorage->ptr.p_double[targetrow+col0]-u00*uk0-u01*uk1; - } - } - if( uwidth==2 ) - { - for(k=0; k<=uheight-1; k++) - { - targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*trowstride; - uk0 = rowstorage->ptr.p_double[offsu+2*k+0]; - uk1 = rowstorage->ptr.p_double[offsu+2*k+1]; - rowstorage->ptr.p_double[targetrow+col0] = rowstorage->ptr.p_double[targetrow+col0]-u00*uk0-u01*uk1; - rowstorage->ptr.p_double[targetrow+col1] = rowstorage->ptr.p_double[targetrow+col1]-u10*uk0-u11*uk1; - } - } - if( uwidth==3 ) - { - for(k=0; k<=uheight-1; k++) - { - targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*trowstride; - uk0 = rowstorage->ptr.p_double[offsu+2*k+0]; - uk1 = rowstorage->ptr.p_double[offsu+2*k+1]; - rowstorage->ptr.p_double[targetrow+col0] = rowstorage->ptr.p_double[targetrow+col0]-u00*uk0-u01*uk1; - rowstorage->ptr.p_double[targetrow+col1] = rowstorage->ptr.p_double[targetrow+col1]-u10*uk0-u11*uk1; - rowstorage->ptr.p_double[targetrow+col2] = rowstorage->ptr.p_double[targetrow+col2]-u20*uk0-u21*uk1; - } - } - if( uwidth==4 ) - { - for(k=0; k<=uheight-1; k++) - { - targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*trowstride; - uk0 = rowstorage->ptr.p_double[offsu+2*k+0]; - uk1 = rowstorage->ptr.p_double[offsu+2*k+1]; - rowstorage->ptr.p_double[targetrow+col0] = rowstorage->ptr.p_double[targetrow+col0]-u00*uk0-u01*uk1; - rowstorage->ptr.p_double[targetrow+col1] = rowstorage->ptr.p_double[targetrow+col1]-u10*uk0-u11*uk1; - rowstorage->ptr.p_double[targetrow+col2] = rowstorage->ptr.p_double[targetrow+col2]-u20*uk0-u21*uk1; - rowstorage->ptr.p_double[targetrow+col3] = rowstorage->ptr.p_double[targetrow+col3]-u30*uk0-u31*uk1; - } - } - result = ae_true; - return result; -} - - -void _spcholanalysis_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - spcholanalysis *p = (spcholanalysis*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->parentsupernode, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->supercolrange, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->superrowridx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->superrowidx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->fillinperm, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->invfillinperm, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->superperm, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->invsuperperm, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->effectiveperm, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->inveffectiveperm, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->ladjplusr, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->ladjplus, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->outrowcounts, 0, DT_INT, _state, make_automatic); - _sparsematrix_init(&p->wrkat, _state, make_automatic); - ae_vector_init(&p->rowstorage, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rowstrides, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->rowoffsets, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->diagd, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->wrkrows, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->flagarray, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->tmpparent, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->node2supernode, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->u2smap, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->raw2smap, 0, DT_INT, _state, make_automatic); - _amdbuffer_init(&p->amdtmp, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->tmp1, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->tmp2, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->tmp3, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->tmp4, 0, DT_INT, _state, make_automatic); - _sparsematrix_init(&p->tmpa, _state, make_automatic); -} - - -void _spcholanalysis_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - spcholanalysis *dst = (spcholanalysis*)_dst; - spcholanalysis *src = (spcholanalysis*)_src; - dst->tasktype = src->tasktype; - dst->n = src->n; - dst->permtype = src->permtype; - dst->unitd = src->unitd; - dst->modtype = src->modtype; - dst->modparam0 = src->modparam0; - dst->modparam1 = src->modparam1; - dst->modparam2 = src->modparam2; - dst->modparam3 = src->modparam3; - dst->extendeddebug = src->extendeddebug; - dst->dotrace = src->dotrace; - dst->nsuper = src->nsuper; - ae_vector_init_copy(&dst->parentsupernode, &src->parentsupernode, _state, make_automatic); - ae_vector_init_copy(&dst->supercolrange, &src->supercolrange, _state, make_automatic); - ae_vector_init_copy(&dst->superrowridx, &src->superrowridx, _state, make_automatic); - ae_vector_init_copy(&dst->superrowidx, &src->superrowidx, _state, make_automatic); - ae_vector_init_copy(&dst->fillinperm, &src->fillinperm, _state, make_automatic); - ae_vector_init_copy(&dst->invfillinperm, &src->invfillinperm, _state, make_automatic); - ae_vector_init_copy(&dst->superperm, &src->superperm, _state, make_automatic); - ae_vector_init_copy(&dst->invsuperperm, &src->invsuperperm, _state, make_automatic); - ae_vector_init_copy(&dst->effectiveperm, &src->effectiveperm, _state, make_automatic); - ae_vector_init_copy(&dst->inveffectiveperm, &src->inveffectiveperm, _state, make_automatic); - dst->istopologicalordering = src->istopologicalordering; - dst->applypermutationtooutput = src->applypermutationtooutput; - ae_vector_init_copy(&dst->ladjplusr, &src->ladjplusr, _state, make_automatic); - ae_vector_init_copy(&dst->ladjplus, &src->ladjplus, _state, make_automatic); - ae_vector_init_copy(&dst->outrowcounts, &src->outrowcounts, _state, make_automatic); - _sparsematrix_init_copy(&dst->wrkat, &src->wrkat, _state, make_automatic); - ae_vector_init_copy(&dst->rowstorage, &src->rowstorage, _state, make_automatic); - ae_vector_init_copy(&dst->rowstrides, &src->rowstrides, _state, make_automatic); - ae_vector_init_copy(&dst->rowoffsets, &src->rowoffsets, _state, make_automatic); - ae_vector_init_copy(&dst->diagd, &src->diagd, _state, make_automatic); - ae_vector_init_copy(&dst->wrkrows, &src->wrkrows, _state, make_automatic); - ae_vector_init_copy(&dst->flagarray, &src->flagarray, _state, make_automatic); - ae_vector_init_copy(&dst->tmpparent, &src->tmpparent, _state, make_automatic); - ae_vector_init_copy(&dst->node2supernode, &src->node2supernode, _state, make_automatic); - ae_vector_init_copy(&dst->u2smap, &src->u2smap, _state, make_automatic); - ae_vector_init_copy(&dst->raw2smap, &src->raw2smap, _state, make_automatic); - _amdbuffer_init_copy(&dst->amdtmp, &src->amdtmp, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic); - ae_vector_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic); - ae_vector_init_copy(&dst->tmp3, &src->tmp3, _state, make_automatic); - ae_vector_init_copy(&dst->tmp4, &src->tmp4, _state, make_automatic); - _sparsematrix_init_copy(&dst->tmpa, &src->tmpa, _state, make_automatic); -} - - -void _spcholanalysis_clear(void* _p) -{ - spcholanalysis *p = (spcholanalysis*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->parentsupernode); - ae_vector_clear(&p->supercolrange); - ae_vector_clear(&p->superrowridx); - ae_vector_clear(&p->superrowidx); - ae_vector_clear(&p->fillinperm); - ae_vector_clear(&p->invfillinperm); - ae_vector_clear(&p->superperm); - ae_vector_clear(&p->invsuperperm); - ae_vector_clear(&p->effectiveperm); - ae_vector_clear(&p->inveffectiveperm); - ae_vector_clear(&p->ladjplusr); - ae_vector_clear(&p->ladjplus); - ae_vector_clear(&p->outrowcounts); - _sparsematrix_clear(&p->wrkat); - ae_vector_clear(&p->rowstorage); - ae_vector_clear(&p->rowstrides); - ae_vector_clear(&p->rowoffsets); - ae_vector_clear(&p->diagd); - ae_vector_clear(&p->wrkrows); - ae_vector_clear(&p->flagarray); - ae_vector_clear(&p->tmpparent); - ae_vector_clear(&p->node2supernode); - ae_vector_clear(&p->u2smap); - ae_vector_clear(&p->raw2smap); - _amdbuffer_clear(&p->amdtmp); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->tmp1); - ae_vector_clear(&p->tmp2); - ae_vector_clear(&p->tmp3); - ae_vector_clear(&p->tmp4); - _sparsematrix_clear(&p->tmpa); -} - - -void _spcholanalysis_destroy(void* _p) -{ - spcholanalysis *p = (spcholanalysis*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->parentsupernode); - ae_vector_destroy(&p->supercolrange); - ae_vector_destroy(&p->superrowridx); - ae_vector_destroy(&p->superrowidx); - ae_vector_destroy(&p->fillinperm); - ae_vector_destroy(&p->invfillinperm); - ae_vector_destroy(&p->superperm); - ae_vector_destroy(&p->invsuperperm); - ae_vector_destroy(&p->effectiveperm); - ae_vector_destroy(&p->inveffectiveperm); - ae_vector_destroy(&p->ladjplusr); - ae_vector_destroy(&p->ladjplus); - ae_vector_destroy(&p->outrowcounts); - _sparsematrix_destroy(&p->wrkat); - ae_vector_destroy(&p->rowstorage); - ae_vector_destroy(&p->rowstrides); - ae_vector_destroy(&p->rowoffsets); - ae_vector_destroy(&p->diagd); - ae_vector_destroy(&p->wrkrows); - ae_vector_destroy(&p->flagarray); - ae_vector_destroy(&p->tmpparent); - ae_vector_destroy(&p->node2supernode); - ae_vector_destroy(&p->u2smap); - ae_vector_destroy(&p->raw2smap); - _amdbuffer_destroy(&p->amdtmp); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->tmp1); - ae_vector_destroy(&p->tmp2); - ae_vector_destroy(&p->tmp3); - ae_vector_destroy(&p->tmp4); - _sparsematrix_destroy(&p->tmpa); -} - - -#endif -#if defined(AE_COMPILE_MATGEN) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Generation of a random uniformly distributed (Haar) orthogonal matrix - -INPUT PARAMETERS: - N - matrix size, N>=1 - -OUTPUT PARAMETERS: - A - orthogonal NxN matrix, array[0..N-1,0..N-1] - -NOTE: this function uses algorithm described in Stewart, G. W. (1980), - "The Efficient Generation of Random Orthogonal Matrices with an - Application to Condition Estimators". - - Speaking short, to generate an (N+1)x(N+1) orthogonal matrix, it: - * takes an NxN one - * takes uniformly distributed unit vector of dimension N+1. - * constructs a Householder reflection from the vector, then applies - it to the smaller matrix (embedded in the larger size with a 1 at - the bottom right corner). - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void rmatrixrndorthogonal(ae_int_t n, - /* Real */ ae_matrix* a, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(a); - - ae_assert(n>=1, "RMatrixRndOrthogonal: N<1!", _state); - ae_matrix_set_length(a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - a->ptr.pp_double[i][j] = (double)(1); - } - else - { - a->ptr.pp_double[i][j] = (double)(0); - } - } - } - rmatrixrndorthogonalfromtheright(a, n, n, _state); -} - - -/************************************************************************* -Generation of random NxN matrix with given condition number and norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void rmatrixrndcond(ae_int_t n, - double c, - /* Real */ ae_matrix* a, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - double l1; - double l2; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - ae_matrix_clear(a); - _hqrndstate_init(&rs, _state, ae_true); - - ae_assert(n>=1&&ae_fp_greater_eq(c,(double)(1)), "RMatrixRndCond: N<1 or C<1!", _state); - ae_matrix_set_length(a, n, n, _state); - if( n==1 ) - { - - /* - * special case - */ - a->ptr.pp_double[0][0] = (double)(2*ae_randominteger(2, _state)-1); - ae_frame_leave(_state); - return; - } - hqrndrandomize(&rs, _state); - l1 = (double)(0); - l2 = ae_log(1/c, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a->ptr.pp_double[i][j] = (double)(0); - } - } - a->ptr.pp_double[0][0] = ae_exp(l1, _state); - for(i=1; i<=n-2; i++) - { - a->ptr.pp_double[i][i] = ae_exp(hqrnduniformr(&rs, _state)*(l2-l1)+l1, _state); - } - a->ptr.pp_double[n-1][n-1] = ae_exp(l2, _state); - rmatrixrndorthogonalfromtheleft(a, n, n, _state); - rmatrixrndorthogonalfromtheright(a, n, n, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Generation of a random Haar distributed orthogonal complex matrix - -INPUT PARAMETERS: - N - matrix size, N>=1 - -OUTPUT PARAMETERS: - A - orthogonal NxN matrix, array[0..N-1,0..N-1] - -NOTE: this function uses algorithm described in Stewart, G. W. (1980), - "The Efficient Generation of Random Orthogonal Matrices with an - Application to Condition Estimators". - - Speaking short, to generate an (N+1)x(N+1) orthogonal matrix, it: - * takes an NxN one - * takes uniformly distributed unit vector of dimension N+1. - * constructs a Householder reflection from the vector, then applies - it to the smaller matrix (embedded in the larger size with a 1 at - the bottom right corner). - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void cmatrixrndorthogonal(ae_int_t n, - /* Complex */ ae_matrix* a, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(a); - - ae_assert(n>=1, "CMatrixRndOrthogonal: N<1!", _state); - ae_matrix_set_length(a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - a->ptr.pp_complex[i][j] = ae_complex_from_i(1); - } - else - { - a->ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - } - cmatrixrndorthogonalfromtheright(a, n, n, _state); -} - - -/************************************************************************* -Generation of random NxN complex matrix with given condition number C and -norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void cmatrixrndcond(ae_int_t n, - double c, - /* Complex */ ae_matrix* a, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - double l1; - double l2; - hqrndstate state; - ae_complex v; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - ae_matrix_clear(a); - _hqrndstate_init(&state, _state, ae_true); - - ae_assert(n>=1&&ae_fp_greater_eq(c,(double)(1)), "CMatrixRndCond: N<1 or C<1!", _state); - ae_matrix_set_length(a, n, n, _state); - if( n==1 ) - { - - /* - * special case - */ - hqrndrandomize(&state, _state); - hqrndunit2(&state, &v.x, &v.y, _state); - a->ptr.pp_complex[0][0] = v; - ae_frame_leave(_state); - return; - } - hqrndrandomize(&state, _state); - l1 = (double)(0); - l2 = ae_log(1/c, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a->ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - a->ptr.pp_complex[0][0] = ae_complex_from_d(ae_exp(l1, _state)); - for(i=1; i<=n-2; i++) - { - a->ptr.pp_complex[i][i] = ae_complex_from_d(ae_exp(hqrnduniformr(&state, _state)*(l2-l1)+l1, _state)); - } - a->ptr.pp_complex[n-1][n-1] = ae_complex_from_d(ae_exp(l2, _state)); - cmatrixrndorthogonalfromtheleft(a, n, n, _state); - cmatrixrndorthogonalfromtheright(a, n, n, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Generation of random NxN symmetric matrix with given condition number and -norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void smatrixrndcond(ae_int_t n, - double c, - /* Real */ ae_matrix* a, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - double l1; - double l2; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - ae_matrix_clear(a); - _hqrndstate_init(&rs, _state, ae_true); - - ae_assert(n>=1&&ae_fp_greater_eq(c,(double)(1)), "SMatrixRndCond: N<1 or C<1!", _state); - ae_matrix_set_length(a, n, n, _state); - if( n==1 ) - { - - /* - * special case - */ - a->ptr.pp_double[0][0] = (double)(2*ae_randominteger(2, _state)-1); - ae_frame_leave(_state); - return; - } - - /* - * Prepare matrix - */ - hqrndrandomize(&rs, _state); - l1 = (double)(0); - l2 = ae_log(1/c, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a->ptr.pp_double[i][j] = (double)(0); - } - } - a->ptr.pp_double[0][0] = ae_exp(l1, _state); - for(i=1; i<=n-2; i++) - { - a->ptr.pp_double[i][i] = (2*hqrnduniformi(&rs, 2, _state)-1)*ae_exp(hqrnduniformr(&rs, _state)*(l2-l1)+l1, _state); - } - a->ptr.pp_double[n-1][n-1] = ae_exp(l2, _state); - - /* - * Multiply - */ - smatrixrndmultiply(a, n, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Generation of random NxN symmetric positive definite matrix with given -condition number and norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random SPD matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void spdmatrixrndcond(ae_int_t n, - double c, - /* Real */ ae_matrix* a, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - double l1; - double l2; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - ae_matrix_clear(a); - _hqrndstate_init(&rs, _state, ae_true); - - - /* - * Special cases - */ - if( n<=0||ae_fp_less(c,(double)(1)) ) - { - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(a, n, n, _state); - if( n==1 ) - { - a->ptr.pp_double[0][0] = (double)(1); - ae_frame_leave(_state); - return; - } - - /* - * Prepare matrix - */ - hqrndrandomize(&rs, _state); - l1 = (double)(0); - l2 = ae_log(1/c, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a->ptr.pp_double[i][j] = (double)(0); - } - } - a->ptr.pp_double[0][0] = ae_exp(l1, _state); - for(i=1; i<=n-2; i++) - { - a->ptr.pp_double[i][i] = ae_exp(hqrnduniformr(&rs, _state)*(l2-l1)+l1, _state); - } - a->ptr.pp_double[n-1][n-1] = ae_exp(l2, _state); - - /* - * Multiply - */ - smatrixrndmultiply(a, n, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Generation of random NxN Hermitian matrix with given condition number and -norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void hmatrixrndcond(ae_int_t n, - double c, - /* Complex */ ae_matrix* a, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - double l1; - double l2; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - ae_matrix_clear(a); - _hqrndstate_init(&rs, _state, ae_true); - - ae_assert(n>=1&&ae_fp_greater_eq(c,(double)(1)), "HMatrixRndCond: N<1 or C<1!", _state); - ae_matrix_set_length(a, n, n, _state); - if( n==1 ) - { - - /* - * special case - */ - a->ptr.pp_complex[0][0] = ae_complex_from_i(2*ae_randominteger(2, _state)-1); - ae_frame_leave(_state); - return; - } - - /* - * Prepare matrix - */ - hqrndrandomize(&rs, _state); - l1 = (double)(0); - l2 = ae_log(1/c, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a->ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - a->ptr.pp_complex[0][0] = ae_complex_from_d(ae_exp(l1, _state)); - for(i=1; i<=n-2; i++) - { - a->ptr.pp_complex[i][i] = ae_complex_from_d((2*hqrnduniformi(&rs, 2, _state)-1)*ae_exp(hqrnduniformr(&rs, _state)*(l2-l1)+l1, _state)); - } - a->ptr.pp_complex[n-1][n-1] = ae_complex_from_d(ae_exp(l2, _state)); - - /* - * Multiply - */ - hmatrixrndmultiply(a, n, _state); - - /* - * post-process to ensure that matrix diagonal is real - */ - for(i=0; i<=n-1; i++) - { - a->ptr.pp_complex[i][i].y = (double)(0); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Generation of random NxN Hermitian positive definite matrix with given -condition number and norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random HPD matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void hpdmatrixrndcond(ae_int_t n, - double c, - /* Complex */ ae_matrix* a, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - double l1; - double l2; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - ae_matrix_clear(a); - _hqrndstate_init(&rs, _state, ae_true); - - - /* - * Special cases - */ - if( n<=0||ae_fp_less(c,(double)(1)) ) - { - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(a, n, n, _state); - if( n==1 ) - { - a->ptr.pp_complex[0][0] = ae_complex_from_i(1); - ae_frame_leave(_state); - return; - } - - /* - * Prepare matrix - */ - hqrndrandomize(&rs, _state); - l1 = (double)(0); - l2 = ae_log(1/c, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a->ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - a->ptr.pp_complex[0][0] = ae_complex_from_d(ae_exp(l1, _state)); - for(i=1; i<=n-2; i++) - { - a->ptr.pp_complex[i][i] = ae_complex_from_d(ae_exp(hqrnduniformr(&rs, _state)*(l2-l1)+l1, _state)); - } - a->ptr.pp_complex[n-1][n-1] = ae_complex_from_d(ae_exp(l2, _state)); - - /* - * Multiply - */ - hmatrixrndmultiply(a, n, _state); - - /* - * post-process to ensure that matrix diagonal is real - */ - for(i=0; i<=n-1; i++) - { - a->ptr.pp_complex[i][i].y = (double)(0); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Multiplication of MxN matrix by NxN random Haar distributed orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..M-1, 0..N-1] - M, N- matrix size - -OUTPUT PARAMETERS: - A - A*Q, where Q is random NxN orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void rmatrixrndorthogonalfromtheright(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - double tau; - double lambdav; - ae_int_t s; - ae_int_t i; - double u1; - double u2; - ae_vector w; - ae_vector v; - hqrndstate state; - - ae_frame_make(_state, &_frame_block); - memset(&w, 0, sizeof(w)); - memset(&v, 0, sizeof(v)); - memset(&state, 0, sizeof(state)); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&v, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&state, _state, ae_true); - - ae_assert(n>=1&&m>=1, "RMatrixRndOrthogonalFromTheRight: N<1 or M<1!", _state); - if( n==1 ) - { - - /* - * Special case - */ - tau = (double)(2*ae_randominteger(2, _state)-1); - for(i=0; i<=m-1; i++) - { - a->ptr.pp_double[i][0] = a->ptr.pp_double[i][0]*tau; - } - ae_frame_leave(_state); - return; - } - - /* - * General case. - * First pass. - */ - ae_vector_set_length(&w, m, _state); - ae_vector_set_length(&v, n+1, _state); - hqrndrandomize(&state, _state); - for(s=2; s<=n; s++) - { - - /* - * Prepare random normal v - */ - do - { - i = 1; - while(i<=s) - { - hqrndnormal2(&state, &u1, &u2, _state); - v.ptr.p_double[i] = u1; - if( i+1<=s ) - { - v.ptr.p_double[i+1] = u2; - } - i = i+2; - } - lambdav = ae_v_dotproduct(&v.ptr.p_double[1], 1, &v.ptr.p_double[1], 1, ae_v_len(1,s)); - } - while(ae_fp_eq(lambdav,(double)(0))); - - /* - * Prepare and apply reflection - */ - generatereflection(&v, s, &tau, _state); - v.ptr.p_double[1] = (double)(1); - applyreflectionfromtheright(a, tau, &v, 0, m-1, n-s, n-1, &w, _state); - } - - /* - * Second pass. - */ - for(i=0; i<=n-1; i++) - { - tau = (double)(2*hqrnduniformi(&state, 2, _state)-1); - ae_v_muld(&a->ptr.pp_double[0][i], a->stride, ae_v_len(0,m-1), tau); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Multiplication of MxN matrix by MxM random Haar distributed orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..M-1, 0..N-1] - M, N- matrix size - -OUTPUT PARAMETERS: - A - Q*A, where Q is random MxM orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void rmatrixrndorthogonalfromtheleft(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - double tau; - double lambdav; - ae_int_t s; - ae_int_t i; - ae_int_t j; - double u1; - double u2; - ae_vector w; - ae_vector v; - hqrndstate state; - - ae_frame_make(_state, &_frame_block); - memset(&w, 0, sizeof(w)); - memset(&v, 0, sizeof(v)); - memset(&state, 0, sizeof(state)); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&v, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&state, _state, ae_true); - - ae_assert(n>=1&&m>=1, "RMatrixRndOrthogonalFromTheRight: N<1 or M<1!", _state); - if( m==1 ) - { - - /* - * special case - */ - tau = (double)(2*ae_randominteger(2, _state)-1); - for(j=0; j<=n-1; j++) - { - a->ptr.pp_double[0][j] = a->ptr.pp_double[0][j]*tau; - } - ae_frame_leave(_state); - return; - } - - /* - * General case. - * First pass. - */ - ae_vector_set_length(&w, n, _state); - ae_vector_set_length(&v, m+1, _state); - hqrndrandomize(&state, _state); - for(s=2; s<=m; s++) - { - - /* - * Prepare random normal v - */ - do - { - i = 1; - while(i<=s) - { - hqrndnormal2(&state, &u1, &u2, _state); - v.ptr.p_double[i] = u1; - if( i+1<=s ) - { - v.ptr.p_double[i+1] = u2; - } - i = i+2; - } - lambdav = ae_v_dotproduct(&v.ptr.p_double[1], 1, &v.ptr.p_double[1], 1, ae_v_len(1,s)); - } - while(ae_fp_eq(lambdav,(double)(0))); - - /* - * Prepare and apply reflection - */ - generatereflection(&v, s, &tau, _state); - v.ptr.p_double[1] = (double)(1); - applyreflectionfromtheleft(a, tau, &v, m-s, m-1, 0, n-1, &w, _state); - } - - /* - * Second pass. - */ - for(i=0; i<=m-1; i++) - { - tau = (double)(2*hqrnduniformi(&state, 2, _state)-1); - ae_v_muld(&a->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), tau); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Multiplication of MxN complex matrix by NxN random Haar distributed -complex orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..M-1, 0..N-1] - M, N- matrix size - -OUTPUT PARAMETERS: - A - A*Q, where Q is random NxN orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void cmatrixrndorthogonalfromtheright(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_complex lambdav; - ae_complex tau; - ae_int_t s; - ae_int_t i; - ae_vector w; - ae_vector v; - hqrndstate state; - - ae_frame_make(_state, &_frame_block); - memset(&w, 0, sizeof(w)); - memset(&v, 0, sizeof(v)); - memset(&state, 0, sizeof(state)); - ae_vector_init(&w, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&v, 0, DT_COMPLEX, _state, ae_true); - _hqrndstate_init(&state, _state, ae_true); - - ae_assert(n>=1&&m>=1, "CMatrixRndOrthogonalFromTheRight: N<1 or M<1!", _state); - if( n==1 ) - { - - /* - * Special case - */ - hqrndrandomize(&state, _state); - hqrndunit2(&state, &tau.x, &tau.y, _state); - for(i=0; i<=m-1; i++) - { - a->ptr.pp_complex[i][0] = ae_c_mul(a->ptr.pp_complex[i][0],tau); - } - ae_frame_leave(_state); - return; - } - - /* - * General case. - * First pass. - */ - ae_vector_set_length(&w, m, _state); - ae_vector_set_length(&v, n+1, _state); - hqrndrandomize(&state, _state); - for(s=2; s<=n; s++) - { - - /* - * Prepare random normal v - */ - do - { - for(i=1; i<=s; i++) - { - hqrndnormal2(&state, &tau.x, &tau.y, _state); - v.ptr.p_complex[i] = tau; - } - lambdav = ae_v_cdotproduct(&v.ptr.p_complex[1], 1, "N", &v.ptr.p_complex[1], 1, "Conj", ae_v_len(1,s)); - } - while(ae_c_eq_d(lambdav,(double)(0))); - - /* - * Prepare and apply reflection - */ - complexgeneratereflection(&v, s, &tau, _state); - v.ptr.p_complex[1] = ae_complex_from_i(1); - complexapplyreflectionfromtheright(a, tau, &v, 0, m-1, n-s, n-1, &w, _state); - } - - /* - * Second pass. - */ - for(i=0; i<=n-1; i++) - { - hqrndunit2(&state, &tau.x, &tau.y, _state); - ae_v_cmulc(&a->ptr.pp_complex[0][i], a->stride, ae_v_len(0,m-1), tau); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Multiplication of MxN complex matrix by MxM random Haar distributed -complex orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..M-1, 0..N-1] - M, N- matrix size - -OUTPUT PARAMETERS: - A - Q*A, where Q is random MxM orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void cmatrixrndorthogonalfromtheleft(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_complex tau; - ae_complex lambdav; - ae_int_t s; - ae_int_t i; - ae_int_t j; - ae_vector w; - ae_vector v; - hqrndstate state; - - ae_frame_make(_state, &_frame_block); - memset(&w, 0, sizeof(w)); - memset(&v, 0, sizeof(v)); - memset(&state, 0, sizeof(state)); - ae_vector_init(&w, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&v, 0, DT_COMPLEX, _state, ae_true); - _hqrndstate_init(&state, _state, ae_true); - - ae_assert(n>=1&&m>=1, "CMatrixRndOrthogonalFromTheRight: N<1 or M<1!", _state); - if( m==1 ) - { - - /* - * special case - */ - hqrndrandomize(&state, _state); - hqrndunit2(&state, &tau.x, &tau.y, _state); - for(j=0; j<=n-1; j++) - { - a->ptr.pp_complex[0][j] = ae_c_mul(a->ptr.pp_complex[0][j],tau); - } - ae_frame_leave(_state); - return; - } - - /* - * General case. - * First pass. - */ - ae_vector_set_length(&w, n, _state); - ae_vector_set_length(&v, m+1, _state); - hqrndrandomize(&state, _state); - for(s=2; s<=m; s++) - { - - /* - * Prepare random normal v - */ - do - { - for(i=1; i<=s; i++) - { - hqrndnormal2(&state, &tau.x, &tau.y, _state); - v.ptr.p_complex[i] = tau; - } - lambdav = ae_v_cdotproduct(&v.ptr.p_complex[1], 1, "N", &v.ptr.p_complex[1], 1, "Conj", ae_v_len(1,s)); - } - while(ae_c_eq_d(lambdav,(double)(0))); - - /* - * Prepare and apply reflection - */ - complexgeneratereflection(&v, s, &tau, _state); - v.ptr.p_complex[1] = ae_complex_from_i(1); - complexapplyreflectionfromtheleft(a, tau, &v, m-s, m-1, 0, n-1, &w, _state); - } - - /* - * Second pass. - */ - for(i=0; i<=m-1; i++) - { - hqrndunit2(&state, &tau.x, &tau.y, _state); - ae_v_cmulc(&a->ptr.pp_complex[i][0], 1, ae_v_len(0,n-1), tau); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Symmetric multiplication of NxN matrix by random Haar distributed -orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..N-1, 0..N-1] - N - matrix size - -OUTPUT PARAMETERS: - A - Q'*A*Q, where Q is random NxN orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void smatrixrndmultiply(/* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - double tau; - double lambdav; - ae_int_t s; - ae_int_t i; - double u1; - double u2; - ae_vector w; - ae_vector v; - hqrndstate state; - - ae_frame_make(_state, &_frame_block); - memset(&w, 0, sizeof(w)); - memset(&v, 0, sizeof(v)); - memset(&state, 0, sizeof(state)); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&v, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&state, _state, ae_true); - - - /* - * General case. - */ - ae_vector_set_length(&w, n, _state); - ae_vector_set_length(&v, n+1, _state); - hqrndrandomize(&state, _state); - for(s=2; s<=n; s++) - { - - /* - * Prepare random normal v - */ - do - { - i = 1; - while(i<=s) - { - hqrndnormal2(&state, &u1, &u2, _state); - v.ptr.p_double[i] = u1; - if( i+1<=s ) - { - v.ptr.p_double[i+1] = u2; - } - i = i+2; - } - lambdav = ae_v_dotproduct(&v.ptr.p_double[1], 1, &v.ptr.p_double[1], 1, ae_v_len(1,s)); - } - while(ae_fp_eq(lambdav,(double)(0))); - - /* - * Prepare and apply reflection - */ - generatereflection(&v, s, &tau, _state); - v.ptr.p_double[1] = (double)(1); - applyreflectionfromtheright(a, tau, &v, 0, n-1, n-s, n-1, &w, _state); - applyreflectionfromtheleft(a, tau, &v, n-s, n-1, 0, n-1, &w, _state); - } - - /* - * Second pass. - */ - for(i=0; i<=n-1; i++) - { - tau = (double)(2*hqrnduniformi(&state, 2, _state)-1); - ae_v_muld(&a->ptr.pp_double[0][i], a->stride, ae_v_len(0,n-1), tau); - ae_v_muld(&a->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), tau); - } - - /* - * Copy upper triangle to lower - */ - for(i=0; i<=n-2; i++) - { - ae_v_move(&a->ptr.pp_double[i+1][i], a->stride, &a->ptr.pp_double[i][i+1], 1, ae_v_len(i+1,n-1)); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Hermitian multiplication of NxN matrix by random Haar distributed -complex orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..N-1, 0..N-1] - N - matrix size - -OUTPUT PARAMETERS: - A - Q^H*A*Q, where Q is random NxN orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void hmatrixrndmultiply(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_complex tau; - ae_complex lambdav; - ae_int_t s; - ae_int_t i; - ae_vector w; - ae_vector v; - hqrndstate state; - - ae_frame_make(_state, &_frame_block); - memset(&w, 0, sizeof(w)); - memset(&v, 0, sizeof(v)); - memset(&state, 0, sizeof(state)); - ae_vector_init(&w, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&v, 0, DT_COMPLEX, _state, ae_true); - _hqrndstate_init(&state, _state, ae_true); - - - /* - * General case. - */ - ae_vector_set_length(&w, n, _state); - ae_vector_set_length(&v, n+1, _state); - hqrndrandomize(&state, _state); - for(s=2; s<=n; s++) - { - - /* - * Prepare random normal v - */ - do - { - for(i=1; i<=s; i++) - { - hqrndnormal2(&state, &tau.x, &tau.y, _state); - v.ptr.p_complex[i] = tau; - } - lambdav = ae_v_cdotproduct(&v.ptr.p_complex[1], 1, "N", &v.ptr.p_complex[1], 1, "Conj", ae_v_len(1,s)); - } - while(ae_c_eq_d(lambdav,(double)(0))); - - /* - * Prepare and apply reflection - */ - complexgeneratereflection(&v, s, &tau, _state); - v.ptr.p_complex[1] = ae_complex_from_i(1); - complexapplyreflectionfromtheright(a, tau, &v, 0, n-1, n-s, n-1, &w, _state); - complexapplyreflectionfromtheleft(a, ae_c_conj(tau, _state), &v, n-s, n-1, 0, n-1, &w, _state); - } - - /* - * Second pass. - */ - for(i=0; i<=n-1; i++) - { - hqrndunit2(&state, &tau.x, &tau.y, _state); - ae_v_cmulc(&a->ptr.pp_complex[0][i], a->stride, ae_v_len(0,n-1), tau); - tau = ae_c_conj(tau, _state); - ae_v_cmulc(&a->ptr.pp_complex[i][0], 1, ae_v_len(0,n-1), tau); - } - - /* - * Change all values from lower triangle by complex-conjugate values - * from upper one - */ - for(i=0; i<=n-2; i++) - { - ae_v_cmove(&a->ptr.pp_complex[i+1][i], a->stride, &a->ptr.pp_complex[i][i+1], 1, "N", ae_v_len(i+1,n-1)); - } - for(s=0; s<=n-2; s++) - { - for(i=s+1; i<=n-1; i++) - { - a->ptr.pp_complex[i][s].y = -a->ptr.pp_complex[i][s].y; - } - } - ae_frame_leave(_state); -} - - -#endif -#if defined(AE_COMPILE_TRFAC) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -LU decomposition of a general real matrix with row pivoting - -A is represented as A = P*L*U, where: -* L is lower unitriangular matrix -* U is upper triangular matrix -* P = P0*P1*...*PK, K=min(M,N)-1, - Pi - permutation matrix for I and Pivots[I] - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - array[0..M-1, 0..N-1]. - M - number of rows in matrix A. - N - number of columns in matrix A. - - -OUTPUT PARAMETERS: - A - matrices L and U in compact form: - * L is stored under main diagonal - * U is stored on and above main diagonal - Pivots - permutation matrix in compact form. - array[0..Min(M-1,N-1)]. - - -- ALGLIB routine -- - 10.01.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixlu(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - ae_state *_state) -{ - - ae_vector_clear(pivots); - - ae_assert(m>0, "RMatrixLU: incorrect M!", _state); - ae_assert(n>0, "RMatrixLU: incorrect N!", _state); - rmatrixplu(a, m, n, pivots, _state); -} - - -/************************************************************************* -LU decomposition of a general complex matrix with row pivoting - -A is represented as A = P*L*U, where: -* L is lower unitriangular matrix -* U is upper triangular matrix -* P = P0*P1*...*PK, K=min(M,N)-1, - Pi - permutation matrix for I and Pivots[I] - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - array[0..M-1, 0..N-1]. - M - number of rows in matrix A. - N - number of columns in matrix A. - - -OUTPUT PARAMETERS: - A - matrices L and U in compact form: - * L is stored under main diagonal - * U is stored on and above main diagonal - Pivots - permutation matrix in compact form. - array[0..Min(M-1,N-1)]. - - -- ALGLIB routine -- - 10.01.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixlu(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - ae_state *_state) -{ - - ae_vector_clear(pivots); - - ae_assert(m>0, "CMatrixLU: incorrect M!", _state); - ae_assert(n>0, "CMatrixLU: incorrect N!", _state); - cmatrixplu(a, m, n, pivots, _state); -} - - -/************************************************************************* -Cache-oblivious Cholesky decomposition - -The algorithm computes Cholesky decomposition of a Hermitian positive- -definite matrix. The result of an algorithm is a representation of A as -A=U'*U or A=L*L' (here X' denotes conj(X^T)). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - upper or lower triangle of a factorized matrix. - array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - if IsUpper=True, then A contains an upper triangle of - a symmetric matrix, otherwise A contains a lower one. - -OUTPUT PARAMETERS: - A - the result of factorization. If IsUpper=True, then - the upper triangle contains matrix U, so that A = U'*U, - and the elements below the main diagonal are not modified. - Similarly, if IsUpper = False. - -RESULT: - If the matrix is positive-definite, the function returns True. - Otherwise, the function returns False. Contents of A is not determined - in such case. - - -- ALGLIB routine -- - 15.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -ae_bool hpdmatrixcholesky(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector tmp; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&tmp, 0, sizeof(tmp)); - ae_vector_init(&tmp, 0, DT_COMPLEX, _state, ae_true); - - if( n<1 ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - result = trfac_hpdmatrixcholeskyrec(a, 0, n, isupper, &tmp, _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Cache-oblivious Cholesky decomposition - -The algorithm computes Cholesky decomposition of a symmetric positive- -definite matrix. The result of an algorithm is a representation of A as -A=U^T*U or A=L*L^T - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - upper or lower triangle of a factorized matrix. - array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - if IsUpper=True, then A contains an upper triangle of - a symmetric matrix, otherwise A contains a lower one. - -OUTPUT PARAMETERS: - A - the result of factorization. If IsUpper=True, then - the upper triangle contains matrix U, so that A = U^T*U, - and the elements below the main diagonal are not modified. - Similarly, if IsUpper = False. - -RESULT: - If the matrix is positive-definite, the function returns True. - Otherwise, the function returns False. Contents of A is not determined - in such case. - - -- ALGLIB routine -- - 15.12.2009 - Bochkanov Sergey -*************************************************************************/ -ae_bool spdmatrixcholesky(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector tmp; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&tmp, 0, sizeof(tmp)); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - - if( n<1 ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - result = spdmatrixcholeskyrec(a, 0, n, isupper, &tmp, _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Update of Cholesky decomposition: rank-1 update to original A. "Buffered" -version which uses preallocated buffer which is saved between subsequent -function calls. - -This function uses internally allocated buffer which is not saved between -subsequent calls. So, if you perform a lot of subsequent updates, -we recommend you to use "buffered" version of this function: -SPDMatrixCholeskyUpdateAdd1Buf(). - -INPUT PARAMETERS: - A - upper or lower Cholesky factor. - array with elements [0..N-1, 0..N-1]. - Exception is thrown if array size is too small. - N - size of matrix A, N>0 - IsUpper - if IsUpper=True, then A contains upper Cholesky factor; - otherwise A contains a lower one. - U - array[N], rank-1 update to A: A_mod = A + u*u' - Exception is thrown if array size is too small. - BufR - possibly preallocated buffer; automatically resized if - needed. It is recommended to reuse this buffer if you - perform a lot of subsequent decompositions. - -OUTPUT PARAMETERS: - A - updated factorization. If IsUpper=True, then the upper - triangle contains matrix U, and the elements below the main - diagonal are not modified. Similarly, if IsUpper = False. - -NOTE: this function always succeeds, so it does not return completion code - -NOTE: this function checks sizes of input arrays, but it does NOT checks - for presence of infinities or NAN's. - - -- ALGLIB -- - 03.02.2014 - Sergey Bochkanov -*************************************************************************/ -void spdmatrixcholeskyupdateadd1(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* u, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector bufr; - - ae_frame_make(_state, &_frame_block); - memset(&bufr, 0, sizeof(bufr)); - ae_vector_init(&bufr, 0, DT_REAL, _state, ae_true); - - ae_assert(n>0, "SPDMatrixCholeskyUpdateAdd1: N<=0", _state); - ae_assert(a->rows>=n, "SPDMatrixCholeskyUpdateAdd1: Rows(A)cols>=n, "SPDMatrixCholeskyUpdateAdd1: Cols(A)cnt>=n, "SPDMatrixCholeskyUpdateAdd1: Length(U) ( Af20 0 Af22 Af23 ) - ( A30 A31 A32 A33 ) ( Af30 0 Af32 Af33 ) - - If we have Cholesky decomposition of A, it must be recalculated after - variables were fixed. However, it is possible to use efficient - algorithm, which needs O(K*N^2) time to "fix" K variables, given - Cholesky decomposition of original, "unfixed" A. - -INPUT PARAMETERS: - A - upper or lower Cholesky factor. - array with elements [0..N-1, 0..N-1]. - Exception is thrown if array size is too small. - N - size of matrix A, N>0 - IsUpper - if IsUpper=True, then A contains upper Cholesky factor; - otherwise A contains a lower one. - Fix - array[N], I-th element is True if I-th variable must be - fixed. Exception is thrown if array size is too small. - BufR - possibly preallocated buffer; automatically resized if - needed. It is recommended to reuse this buffer if you - perform a lot of subsequent decompositions. - -OUTPUT PARAMETERS: - A - updated factorization. If IsUpper=True, then the upper - triangle contains matrix U, and the elements below the main - diagonal are not modified. Similarly, if IsUpper = False. - -NOTE: this function always succeeds, so it does not return completion code - -NOTE: this function checks sizes of input arrays, but it does NOT checks - for presence of infinities or NAN's. - -NOTE: this function is efficient only for moderate amount of updated - variables - say, 0.1*N or 0.3*N. For larger amount of variables it - will still work, but you may get better performance with - straightforward Cholesky. - - -- ALGLIB -- - 03.02.2014 - Sergey Bochkanov -*************************************************************************/ -void spdmatrixcholeskyupdatefix(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Boolean */ ae_vector* fix, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector bufr; - - ae_frame_make(_state, &_frame_block); - memset(&bufr, 0, sizeof(bufr)); - ae_vector_init(&bufr, 0, DT_REAL, _state, ae_true); - - ae_assert(n>0, "SPDMatrixCholeskyUpdateFix: N<=0", _state); - ae_assert(a->rows>=n, "SPDMatrixCholeskyUpdateFix: Rows(A)cols>=n, "SPDMatrixCholeskyUpdateFix: Cols(A)cnt>=n, "SPDMatrixCholeskyUpdateFix: Length(Fix)0 - IsUpper - if IsUpper=True, then A contains upper Cholesky factor; - otherwise A contains a lower one. - U - array[N], rank-1 update to A: A_mod = A + u*u' - Exception is thrown if array size is too small. - BufR - possibly preallocated buffer; automatically resized if - needed. It is recommended to reuse this buffer if you - perform a lot of subsequent decompositions. - -OUTPUT PARAMETERS: - A - updated factorization. If IsUpper=True, then the upper - triangle contains matrix U, and the elements below the main - diagonal are not modified. Similarly, if IsUpper = False. - - -- ALGLIB -- - 03.02.2014 - Sergey Bochkanov -*************************************************************************/ -void spdmatrixcholeskyupdateadd1buf(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* u, - /* Real */ ae_vector* bufr, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t nz; - double cs; - double sn; - double v; - double vv; - - - ae_assert(n>0, "SPDMatrixCholeskyUpdateAdd1Buf: N<=0", _state); - ae_assert(a->rows>=n, "SPDMatrixCholeskyUpdateAdd1Buf: Rows(A)cols>=n, "SPDMatrixCholeskyUpdateAdd1Buf: Cols(A)cnt>=n, "SPDMatrixCholeskyUpdateAdd1Buf: Length(U)ptr.p_double[i],(double)(0)) ) - { - nz = i; - break; - } - } - if( nz==n ) - { - - /* - * Nothing to update - */ - return; - } - - /* - * If working with upper triangular matrix - */ - if( isupper ) - { - - /* - * Perform a sequence of updates which fix variables one by one. - * This approach is different from one which is used when we work - * with lower triangular matrix. - */ - rvectorsetlengthatleast(bufr, n, _state); - for(j=nz; j<=n-1; j++) - { - bufr->ptr.p_double[j] = u->ptr.p_double[j]; - } - for(i=nz; i<=n-1; i++) - { - if( ae_fp_neq(bufr->ptr.p_double[i],(double)(0)) ) - { - generaterotation(a->ptr.pp_double[i][i], bufr->ptr.p_double[i], &cs, &sn, &v, _state); - a->ptr.pp_double[i][i] = v; - bufr->ptr.p_double[i] = 0.0; - for(j=i+1; j<=n-1; j++) - { - v = a->ptr.pp_double[i][j]; - vv = bufr->ptr.p_double[j]; - a->ptr.pp_double[i][j] = cs*v+sn*vv; - bufr->ptr.p_double[j] = -sn*v+cs*vv; - } - } - } - } - else - { - - /* - * Calculate rows of modified Cholesky factor, row-by-row - * (updates performed during variable fixing are applied - * simultaneously to each row) - */ - rvectorsetlengthatleast(bufr, 3*n, _state); - for(j=nz; j<=n-1; j++) - { - bufr->ptr.p_double[j] = u->ptr.p_double[j]; - } - for(i=nz; i<=n-1; i++) - { - - /* - * Update all previous updates [Idx+1...I-1] to I-th row - */ - vv = bufr->ptr.p_double[i]; - for(j=nz; j<=i-1; j++) - { - cs = bufr->ptr.p_double[n+2*j+0]; - sn = bufr->ptr.p_double[n+2*j+1]; - v = a->ptr.pp_double[i][j]; - a->ptr.pp_double[i][j] = cs*v+sn*vv; - vv = -sn*v+cs*vv; - } - - /* - * generate rotation applied to I-th element of update vector - */ - generaterotation(a->ptr.pp_double[i][i], vv, &cs, &sn, &v, _state); - a->ptr.pp_double[i][i] = v; - bufr->ptr.p_double[n+2*i+0] = cs; - bufr->ptr.p_double[n+2*i+1] = sn; - } - } -} - - -/************************************************************************* -Update of Cholesky decomposition: "fixing" some variables. "Buffered" -version which uses preallocated buffer which is saved between subsequent -function calls. - -See comments for SPDMatrixCholeskyUpdateFix() for more information. - -INPUT PARAMETERS: - A - upper or lower Cholesky factor. - array with elements [0..N-1, 0..N-1]. - Exception is thrown if array size is too small. - N - size of matrix A, N>0 - IsUpper - if IsUpper=True, then A contains upper Cholesky factor; - otherwise A contains a lower one. - Fix - array[N], I-th element is True if I-th variable must be - fixed. Exception is thrown if array size is too small. - BufR - possibly preallocated buffer; automatically resized if - needed. It is recommended to reuse this buffer if you - perform a lot of subsequent decompositions. - -OUTPUT PARAMETERS: - A - updated factorization. If IsUpper=True, then the upper - triangle contains matrix U, and the elements below the main - diagonal are not modified. Similarly, if IsUpper = False. - - -- ALGLIB -- - 03.02.2014 - Sergey Bochkanov -*************************************************************************/ -void spdmatrixcholeskyupdatefixbuf(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Boolean */ ae_vector* fix, - /* Real */ ae_vector* bufr, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t nfix; - ae_int_t idx; - double cs; - double sn; - double v; - double vv; - - - ae_assert(n>0, "SPDMatrixCholeskyUpdateFixBuf: N<=0", _state); - ae_assert(a->rows>=n, "SPDMatrixCholeskyUpdateFixBuf: Rows(A)cols>=n, "SPDMatrixCholeskyUpdateFixBuf: Cols(A)cnt>=n, "SPDMatrixCholeskyUpdateFixBuf: Length(Fix)ptr.p_bool[i] ) - { - inc(&nfix, _state); - } - } - if( nfix==0 ) - { - - /* - * Nothing to fix - */ - return; - } - if( nfix==n ) - { - - /* - * All variables are fixed. - * Set A to identity and exit. - */ - if( isupper ) - { - for(i=0; i<=n-1; i++) - { - a->ptr.pp_double[i][i] = (double)(1); - for(j=i+1; j<=n-1; j++) - { - a->ptr.pp_double[i][j] = (double)(0); - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i-1; j++) - { - a->ptr.pp_double[i][j] = (double)(0); - } - a->ptr.pp_double[i][i] = (double)(1); - } - } - return; - } - - /* - * If working with upper triangular matrix - */ - if( isupper ) - { - - /* - * Perform a sequence of updates which fix variables one by one. - * This approach is different from one which is used when we work - * with lower triangular matrix. - */ - rvectorsetlengthatleast(bufr, n, _state); - for(k=0; k<=n-1; k++) - { - if( fix->ptr.p_bool[k] ) - { - idx = k; - - /* - * Quick exit if it is last variable - */ - if( idx==n-1 ) - { - for(i=0; i<=idx-1; i++) - { - a->ptr.pp_double[i][idx] = 0.0; - } - a->ptr.pp_double[idx][idx] = 1.0; - continue; - } - - /* - * We have Cholesky decomposition of quadratic term in A, - * with upper triangle being stored as given below: - * - * ( U00 u01 U02 ) - * U = ( u11 u12 ) - * ( U22 ) - * - * Here u11 is diagonal element corresponding to variable K. We - * want to fix this variable, and we do so by modifying U as follows: - * - * ( U00 0 U02 ) - * U_mod = ( 1 0 ) - * ( U_m ) - * - * with U_m = CHOLESKY [ (U22^T)*U22 + (u12^T)*u12 ] - * - * Of course, we can calculate U_m by calculating (U22^T)*U22 explicitly, - * modifying it and performing Cholesky decomposition of modified matrix. - * However, we can treat it as follows: - * * we already have CHOLESKY[(U22^T)*U22], which is equal to U22 - * * we have rank-1 update (u12^T)*u12 applied to (U22^T)*U22 - * * thus, we can calculate updated Cholesky with O(N^2) algorithm - * instead of O(N^3) one - */ - for(j=idx+1; j<=n-1; j++) - { - bufr->ptr.p_double[j] = a->ptr.pp_double[idx][j]; - } - for(i=0; i<=idx-1; i++) - { - a->ptr.pp_double[i][idx] = 0.0; - } - a->ptr.pp_double[idx][idx] = 1.0; - for(i=idx+1; i<=n-1; i++) - { - a->ptr.pp_double[idx][i] = 0.0; - } - for(i=idx+1; i<=n-1; i++) - { - if( ae_fp_neq(bufr->ptr.p_double[i],(double)(0)) ) - { - generaterotation(a->ptr.pp_double[i][i], bufr->ptr.p_double[i], &cs, &sn, &v, _state); - a->ptr.pp_double[i][i] = v; - bufr->ptr.p_double[i] = 0.0; - for(j=i+1; j<=n-1; j++) - { - v = a->ptr.pp_double[i][j]; - vv = bufr->ptr.p_double[j]; - a->ptr.pp_double[i][j] = cs*v+sn*vv; - bufr->ptr.p_double[j] = -sn*v+cs*vv; - } - } - } - } - } - } - else - { - - /* - * Calculate rows of modified Cholesky factor, row-by-row - * (updates performed during variable fixing are applied - * simultaneously to each row) - */ - rvectorsetlengthatleast(bufr, 3*n, _state); - for(k=0; k<=n-1; k++) - { - if( fix->ptr.p_bool[k] ) - { - idx = k; - - /* - * Quick exit if it is last variable - */ - if( idx==n-1 ) - { - for(i=0; i<=idx-1; i++) - { - a->ptr.pp_double[idx][i] = 0.0; - } - a->ptr.pp_double[idx][idx] = 1.0; - continue; - } - - /* - * store column to buffer and clear row/column of A - */ - for(j=idx+1; j<=n-1; j++) - { - bufr->ptr.p_double[j] = a->ptr.pp_double[j][idx]; - } - for(i=0; i<=idx-1; i++) - { - a->ptr.pp_double[idx][i] = 0.0; - } - a->ptr.pp_double[idx][idx] = 1.0; - for(i=idx+1; i<=n-1; i++) - { - a->ptr.pp_double[i][idx] = 0.0; - } - - /* - * Apply update to rows of A - */ - for(i=idx+1; i<=n-1; i++) - { - - /* - * Update all previous updates [Idx+1...I-1] to I-th row - */ - vv = bufr->ptr.p_double[i]; - for(j=idx+1; j<=i-1; j++) - { - cs = bufr->ptr.p_double[n+2*j+0]; - sn = bufr->ptr.p_double[n+2*j+1]; - v = a->ptr.pp_double[i][j]; - a->ptr.pp_double[i][j] = cs*v+sn*vv; - vv = -sn*v+cs*vv; - } - - /* - * generate rotation applied to I-th element of update vector - */ - generaterotation(a->ptr.pp_double[i][i], vv, &cs, &sn, &v, _state); - a->ptr.pp_double[i][i] = v; - bufr->ptr.p_double[n+2*i+0] = cs; - bufr->ptr.p_double[n+2*i+1] = sn; - } - } - } - } -} - - -/************************************************************************* -Sparse LU decomposition with column pivoting for sparsity and row pivoting -for stability. Input must be square sparse matrix stored in CRS format. - -The algorithm computes LU decomposition of a general square matrix -(rectangular ones are not supported). The result of an algorithm is a -representation of A as A = P*L*U*Q, where: -* L is lower unitriangular matrix -* U is upper triangular matrix -* P = P0*P1*...*PK, K=N-1, Pi - permutation matrix for I and P[I] -* Q = QK*...*Q1*Q0, K=N-1, Qi - permutation matrix for I and Q[I] - -This function pivots columns for higher sparsity, and then pivots rows for -stability (larger element at the diagonal). - -INPUT PARAMETERS: - A - sparse NxN matrix in CRS format. An exception is generated - if matrix is non-CRS or non-square. - PivotType- pivoting strategy: - * 0 for best pivoting available (2 in current version) - * 1 for row-only pivoting (NOT RECOMMENDED) - * 2 for complete pivoting which produces most sparse outputs - -OUTPUT PARAMETERS: - A - the result of factorization, matrices L and U stored in - compact form using CRS sparse storage format: - * lower unitriangular L is stored strictly under main diagonal - * upper triangilar U is stored ON and ABOVE main diagonal - P - row permutation matrix in compact form, array[N] - Q - col permutation matrix in compact form, array[N] - -This function always succeeds, i.e. it ALWAYS returns valid factorization, -but for your convenience it also returns boolean value which helps to -detect symbolically degenerate matrices: -* function returns TRUE, if the matrix was factorized AND symbolically - non-degenerate -* function returns FALSE, if the matrix was factorized but U has strictly - zero elements at the diagonal (the factorization is returned anyway). - - - -- ALGLIB routine -- - 03.09.2018 - Bochkanov Sergey -*************************************************************************/ -ae_bool sparselu(sparsematrix* a, - ae_int_t pivottype, - /* Integer */ ae_vector* p, - /* Integer */ ae_vector* q, - ae_state *_state) -{ - ae_frame _frame_block; - sluv2buffer buf2; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&buf2, 0, sizeof(buf2)); - ae_vector_clear(p); - ae_vector_clear(q); - _sluv2buffer_init(&buf2, _state, ae_true); - - ae_assert((pivottype==0||pivottype==1)||pivottype==2, "SparseLU: unexpected pivot type", _state); - ae_assert(sparseiscrs(a, _state), "SparseLU: A is not stored in CRS format", _state); - ae_assert(sparsegetnrows(a, _state)==sparsegetncols(a, _state), "SparseLU: non-square A", _state); - result = sptrflu(a, pivottype, p, q, &buf2, _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Sparse Cholesky decomposition for skyline matrixm using in-place algorithm -without allocating additional storage. - -The algorithm computes Cholesky decomposition of a symmetric positive- -definite sparse matrix. The result of an algorithm is a representation of -A as A=U^T*U or A=L*L^T - -This function allows to perform very efficient decomposition of low-profile -matrices (average bandwidth is ~5-10 elements). For larger matrices it is -recommended to use supernodal Cholesky decomposition: SparseCholeskyP() or -SparseCholeskyAnalyze()/SparseCholeskyFactorize(). - -INPUT PARAMETERS: - A - sparse matrix in skyline storage (SKS) format. - N - size of matrix A (can be smaller than actual size of A) - IsUpper - if IsUpper=True, then factorization is performed on upper - triangle. Another triangle is ignored (it may contant some - data, but it is not changed). - - -OUTPUT PARAMETERS: - A - the result of factorization, stored in SKS. If IsUpper=True, - then the upper triangle contains matrix U, such that - A = U^T*U. Lower triangle is not changed. - Similarly, if IsUpper = False. In this case L is returned, - and we have A = L*(L^T). - Note that THIS function does not perform permutation of - rows to reduce bandwidth. - -RESULT: - If the matrix is positive-definite, the function returns True. - Otherwise, the function returns False. Contents of A is not determined - in such case. - -NOTE: for performance reasons this function does NOT check that input - matrix includes only finite values. It is your responsibility to - make sure that there are no infinite or NAN values in the matrix. - - -- ALGLIB routine -- - 16.01.2014 - Bochkanov Sergey -*************************************************************************/ -ae_bool sparsecholeskyskyline(sparsematrix* a, - ae_int_t n, - ae_bool isupper, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t jnz; - ae_int_t jnza; - ae_int_t jnzl; - double v; - double vv; - double a12; - ae_int_t nready; - ae_int_t nadd; - ae_int_t banda; - ae_int_t offsa; - ae_int_t offsl; - ae_bool result; - - - ae_assert(n>=0, "SparseCholeskySkyline: N<0", _state); - ae_assert(sparsegetnrows(a, _state)>=n, "SparseCholeskySkyline: rows(A)=n, "SparseCholeskySkyline: cols(A)=BANDWIDTH(A1), I-th equation is reduced from - * L[I,0]*A1[0] + L[I,1]*A1[1] + ... + L[I,I]*A1[I] = A[I] - * to - * L[I,JNZ]*A1[JNZ] + ... + L[I,I]*A1[I] = A[I] - * where JNZ = max(NReady-BANDWIDTH(A1),I-BANDWIDTH(L[i])) - * (JNZ is an index of the firts column where both A and L become - * nonzero). - * - * NOTE: we rely on details of SparseMatrix internal storage format. - * This is allowed by SparseMatrix specification. - */ - a12 = 0.0; - if( a->didx.ptr.p_int[nready]>0 ) - { - banda = a->didx.ptr.p_int[nready]; - for(i=nready-banda; i<=nready-1; i++) - { - - /* - * Elements of A1[0:I-1] were computed: - * * A1[0:NReady-BandA-1] are zero (sparse) - * * A1[NReady-BandA:I-1] replaced corresponding elements of A - * - * Now it is time to get I-th one. - * - * First, we calculate: - * * JNZA - index of the first column where A become nonzero - * * JNZL - index of the first column where L become nonzero - * * JNZ - index of the first column where both A and L become nonzero - * * OffsA - offset of A[JNZ] in A.Vals - * * OffsL - offset of L[I,JNZ] in A.Vals - * - * Then, we solve SUM(A1[j]*L[I,j],j=JNZ..I-1) + A1[I]*L[I,I] = A[I], - * with A1[JNZ..I-1] already known, and A1[I] unknown. - */ - jnza = nready-banda; - jnzl = i-a->didx.ptr.p_int[i]; - jnz = ae_maxint(jnza, jnzl, _state); - offsa = a->ridx.ptr.p_int[nready]+(jnz-jnza); - offsl = a->ridx.ptr.p_int[i]+(jnz-jnzl); - v = 0.0; - k = i-1-jnz; - for(j=0; j<=k; j++) - { - v = v+a->vals.ptr.p_double[offsa+j]*a->vals.ptr.p_double[offsl+j]; - } - vv = (a->vals.ptr.p_double[offsa+k+1]-v)/a->vals.ptr.p_double[offsl+k+1]; - a->vals.ptr.p_double[offsa+k+1] = vv; - a12 = a12+vv*vv; - } - } - - /* - * Calculate CHOLESKY(B-A1*A1') - */ - offsa = a->ridx.ptr.p_int[nready]+a->didx.ptr.p_int[nready]; - v = a->vals.ptr.p_double[offsa]; - if( ae_fp_less_eq(v,a12) ) - { - result = ae_false; - return result; - } - a->vals.ptr.p_double[offsa] = ae_sqrt(v-a12, _state); - - /* - * Increase size of the updated matrix - */ - inc(&nready, _state); - } - - /* - * transpose if needed - */ - if( isupper ) - { - sparsetransposesks(a, _state); - } - result = ae_true; - return result; -} - - -/************************************************************************* -Sparse Cholesky decomposition for a matrix stored in any sparse storage, -without rows/cols permutation. - -This function is the most convenient (less parameters to specify), although -less efficient, version of sparse Cholesky. - -Internally it: -* calls SparseCholeskyAnalyze() function to perform symbolic analysis - phase with no permutation being configured. -* calls SparseCholeskyFactorize() function to perform numerical phase of - the factorization - -Following alternatives may result in better performance: -* using SparseCholeskyP(), which selects best pivoting available, which - almost always results in improved sparsity and cache locality -* using SparseCholeskyAnalyze() and SparseCholeskyFactorize() functions - directly, which may improve performance of repetitive factorizations - with same sparsity patterns. - -The latter also allows one to perform LDLT factorization of indefinite -matrix (one with strictly diagonal D, which is known to be stable only -in few special cases, like quasi-definite matrices). - -INPUT PARAMETERS: - A - a square NxN sparse matrix, stored in any storage format. - IsUpper - if IsUpper=True, then factorization is performed on upper - triangle. Another triangle is ignored on input, dropped - on output. Similarly, if IsUpper=False, the lower triangle - is processed. - -OUTPUT PARAMETERS: - A - the result of factorization, stored in CRS format: - * if IsUpper=True, then the upper triangle contains matrix - U such that A = U^T*U and the lower triangle is empty. - * similarly, if IsUpper=False, then lower triangular L is - returned and we have A = L*(L^T). - Note that THIS function does not perform permutation of - the rows to reduce fill-in. - -RESULT: - If the matrix is positive-definite, the function returns True. - Otherwise, the function returns False. Contents of A is undefined - in such case. - -NOTE: for performance reasons this function does NOT check that input - matrix includes only finite values. It is your responsibility to - make sure that there are no infinite or NAN values in the matrix. - - -- ALGLIB routine -- - 16.09.2020 - Bochkanov Sergey -*************************************************************************/ -ae_bool sparsecholesky(sparsematrix* a, ae_bool isupper, ae_state *_state) -{ - ae_frame _frame_block; - sparsedecompositionanalysis analysis; - ae_int_t facttype; - ae_int_t permtype; - ae_vector dummyd; - ae_vector dummyp; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&analysis, 0, sizeof(analysis)); - memset(&dummyd, 0, sizeof(dummyd)); - memset(&dummyp, 0, sizeof(dummyp)); - _sparsedecompositionanalysis_init(&analysis, _state, ae_true); - ae_vector_init(&dummyd, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dummyp, 0, DT_INT, _state, ae_true); - - ae_assert(sparsegetnrows(a, _state)==sparsegetncols(a, _state), "SparseCholesky: A is not square", _state); - - /* - * Quick exit - */ - if( sparsegetnrows(a, _state)==0 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Choose factorization and permutation: vanilla Cholesky and no permutation - */ - facttype = 0; - permtype = -1; - - /* - * Easy case - CRS matrix in lower triangle, no conversion or transposition is needed - */ - if( sparseiscrs(a, _state)&&!isupper ) - { - result = spsymmanalyze(a, facttype, permtype, &analysis.analysis, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - result = spsymmfactorize(&analysis.analysis, a, &dummyd, &dummyp, _state); - ae_frame_leave(_state); - return result; - } - - /* - * A bit more complex - we need conversion and/or transposition - */ - if( isupper ) - { - sparsecopytocrsbuf(a, &analysis.wrkat, _state); - sparsecopytransposecrsbuf(&analysis.wrkat, &analysis.wrka, _state); - } - else - { - sparsecopytocrsbuf(a, &analysis.wrka, _state); - } - result = spsymmanalyze(&analysis.wrka, facttype, permtype, &analysis.analysis, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - result = spsymmfactorize(&analysis.analysis, &analysis.wrka, &dummyd, &dummyp, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - if( isupper ) - { - sparsecopytransposecrsbuf(&analysis.wrka, a, _state); - } - else - { - sparsecopybuf(&analysis.wrka, a, _state); - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Sparse Cholesky decomposition for a matrix stored in any sparse storage -format, with performance-enhancing permutation of rows/cols. - -Present version is configured to perform supernodal permutation which -sparsity reducing ordering. - -This function is a wrapper around generic sparse decomposition functions -that internally: -* calls SparseCholeskyAnalyze() function to perform symbolic analysis - phase with best available permutation being configured. -* calls SparseCholeskyFactorize() function to perform numerical phase of - the factorization. - -NOTE: using SparseCholeskyAnalyze() and SparseCholeskyFactorize() directly - may improve performance of repetitive factorizations with same - sparsity patterns. It also allows one to perform LDLT factorization - of indefinite matrix - a factorization with strictly diagonal D, - which is known to be stable only in few special cases, like quasi- - definite matrices. - -INPUT PARAMETERS: - A - a square NxN sparse matrix, stored in any storage format. - IsUpper - if IsUpper=True, then factorization is performed on upper - triangle. Another triangle is ignored on input, dropped - on output. Similarly, if IsUpper=False, the lower triangle - is processed. - -OUTPUT PARAMETERS: - A - the result of factorization, stored in CRS format: - * if IsUpper=True, then the upper triangle contains matrix - U such that A = U^T*U and the lower triangle is empty. - * similarly, if IsUpper=False, then lower triangular L is - returned and we have A = L*(L^T). - P - a row/column permutation, a product of P0*P1*...*Pk, k=N-1, - with Pi being permutation of rows/cols I and P[I] - -RESULT: - If the matrix is positive-definite, the function returns True. - Otherwise, the function returns False. Contents of A is undefined - in such case. - -NOTE: for performance reasons this function does NOT check that input - matrix includes only finite values. It is your responsibility to - make sure that there are no infinite or NAN values in the matrix. - - -- ALGLIB routine -- - 16.09.2020 - Bochkanov Sergey -*************************************************************************/ -ae_bool sparsecholeskyp(sparsematrix* a, - ae_bool isupper, - /* Integer */ ae_vector* p, - ae_state *_state) -{ - ae_frame _frame_block; - sparsedecompositionanalysis analysis; - ae_vector dummyd; - ae_int_t facttype; - ae_int_t permtype; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&analysis, 0, sizeof(analysis)); - memset(&dummyd, 0, sizeof(dummyd)); - ae_vector_clear(p); - _sparsedecompositionanalysis_init(&analysis, _state, ae_true); - ae_vector_init(&dummyd, 0, DT_REAL, _state, ae_true); - - ae_assert(sparsegetnrows(a, _state)==sparsegetncols(a, _state), "SparseCholeskyP: A is not square", _state); - - /* - * Quick exit - */ - if( sparsegetnrows(a, _state)==0 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Choose factorization and permutation: vanilla Cholesky and best permutation available - */ - facttype = 0; - permtype = 0; - - /* - * Easy case - CRS matrix in lower triangle, no conversion or transposition is needed - */ - if( sparseiscrs(a, _state)&&!isupper ) - { - result = spsymmanalyze(a, facttype, permtype, &analysis.analysis, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - result = spsymmfactorize(&analysis.analysis, a, &dummyd, p, _state); - ae_frame_leave(_state); - return result; - } - - /* - * A bit more complex - we need conversion and/or transposition - */ - if( isupper ) - { - sparsecopytocrsbuf(a, &analysis.wrkat, _state); - sparsecopytransposecrsbuf(&analysis.wrkat, &analysis.wrka, _state); - } - else - { - sparsecopytocrsbuf(a, &analysis.wrka, _state); - } - result = spsymmanalyze(&analysis.wrka, facttype, permtype, &analysis.analysis, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - result = spsymmfactorize(&analysis.analysis, &analysis.wrka, &dummyd, p, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - if( isupper ) - { - sparsecopytransposecrsbuf(&analysis.wrka, a, _state); - } - else - { - sparsecopybuf(&analysis.wrka, a, _state); - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Sparse Cholesky/LDLT decomposition: symbolic analysis phase. - -This function is a part of the 'expert' sparse Cholesky API: -* SparseCholeskyAnalyze(), that performs symbolic analysis phase and loads - matrix to be factorized into internal storage -* SparseCholeskySetModType(), that allows to use modified Cholesky/LDLT - with lower bounds on pivot magnitudes and additional overflow safeguards -* SparseCholeskyFactorize(), that performs numeric factorization using - precomputed symbolic analysis and internally stored matrix - and outputs - result -* SparseCholeskyReload(), that reloads one more matrix with same sparsity - pattern into internal storage so one may reuse previously allocated - temporaries and previously performed symbolic analysis - -This specific function performs preliminary analysis of the Cholesky/LDLT -factorization. It allows to choose different permutation types and to -choose between classic Cholesky and indefinite LDLT factorization (the -latter is computed with strictly diagonal D, i.e. without Bunch-Kauffman -pivoting). - -NOTE: L*D*LT family of factorization may be used to factorize indefinite - matrices. However, numerical stability is guaranteed ONLY for a class - of quasi-definite matrices. - -NOTE: all internal processing is performed with lower triangular matrices - stored in CRS format. Any other storage formats and/or upper - triangular storage means that one format conversion and/or one - transposition will be performed internally for the analysis and - factorization phases. Thus, highest performance is achieved when - input is a lower triangular CRS matrix. - -INPUT PARAMETERS: - A - sparse square matrix in any sparse storage format. - IsUpper - whether upper or lower triangle is decomposed (the - other one is ignored). - FactType - factorization type: - * 0 for traditional Cholesky of SPD matrix - * 1 for LDLT decomposition with strictly diagonal D, - which may have non-positive entries. - PermType - permutation type: - *-1 for absence of permutation - * 0 for best fill-in reducing permutation available - * 1 for supernodal ordering (improves locality and - performance, does NOT change fill-in factor) - * 2 for AMD (approximate minimum degree) ordering - -OUTPUT PARAMETERS: - Analysis - contains: - * symbolic analysis of the matrix structure which will - be used later to guide numerical factorization. - * specific numeric values loaded into internal memory - waiting for the factorization to be performed - -This function fails if and only if the matrix A is symbolically degenerate -i.e. has diagonal element which is exactly zero. In such case False is -returned, contents of Analysis object is undefined. - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -ae_bool sparsecholeskyanalyze(sparsematrix* a, - ae_bool isupper, - ae_int_t facttype, - ae_int_t permtype, - sparsedecompositionanalysis* analysis, - ae_state *_state) -{ - ae_bool result; - - _sparsedecompositionanalysis_clear(analysis); - - ae_assert(sparsegetnrows(a, _state)==sparsegetncols(a, _state), "SparseCholeskyAnalyze: A is not square", _state); - ae_assert(facttype==0||facttype==1, "SparseCholeskyAnalyze: unexpected FactType", _state); - ae_assert((((permtype==0||permtype==1)||permtype==2)||permtype==-1)||permtype==-2, "SparseCholeskyAnalyze: unexpected PermType", _state); - analysis->n = sparsegetnrows(a, _state); - analysis->facttype = facttype; - analysis->permtype = permtype; - if( !sparseiscrs(a, _state) ) - { - - /* - * The matrix is stored in non-CRS format. First, we have to convert - * it to CRS. Then we may need to transpose it in order to get lower - * triangular one (as supported by SPSymmAnalyze). - */ - sparsecopytocrs(a, &analysis->crsa, _state); - if( isupper ) - { - sparsecopytransposecrsbuf(&analysis->crsa, &analysis->crsat, _state); - result = spsymmanalyze(&analysis->crsat, facttype, permtype, &analysis->analysis, _state); - } - else - { - result = spsymmanalyze(&analysis->crsa, facttype, permtype, &analysis->analysis, _state); - } - } - else - { - - /* - * The matrix is stored in CRS format. However we may need to - * transpose it in order to get lower triangular one (as supported - * by SPSymmAnalyze). - */ - if( isupper ) - { - sparsecopytransposecrsbuf(a, &analysis->crsat, _state); - result = spsymmanalyze(&analysis->crsat, facttype, permtype, &analysis->analysis, _state); - } - else - { - result = spsymmanalyze(a, facttype, permtype, &analysis->analysis, _state); - } - } - return result; -} - - -/************************************************************************* -Allows to control stability-improving modification strategy for sparse -Cholesky/LDLT decompositions. Modified Cholesky is more robust than its -unmodified counterpart. - -This function is a part of the 'expert' sparse Cholesky API: -* SparseCholeskyAnalyze(), that performs symbolic analysis phase and loads - matrix to be factorized into internal storage -* SparseCholeskySetModType(), that allows to use modified Cholesky/LDLT - with lower bounds on pivot magnitudes and additional overflow safeguards -* SparseCholeskyFactorize(), that performs numeric factorization using - precomputed symbolic analysis and internally stored matrix - and outputs - result -* SparseCholeskyReload(), that reloads one more matrix with same sparsity - pattern into internal storage so one may reuse previously allocated - temporaries and previously performed symbolic analysis - -INPUT PARAMETERS: - Analysis - symbolic analysis of the matrix structure - ModStrategy - modification type: - * 0 for traditional Cholesky/LDLT (Cholesky fails when - encounters nonpositive pivot, LDLT fails when zero - pivot is encountered, no stability checks for - overflows/underflows) - * 1 for modified Cholesky with additional checks: - * pivots less than ModParam0 are increased; (similar - sign-preserving procedure is applied during LDLT) - * if, at some moment, sum of absolute values of - elements in column J will become greater than - ModParam1, Cholesky/LDLT will treat it as failure - and will stop immediately - P0, P1, P2,P3 - modification parameters #0 #1, #2 and #3. - Params #2 and #3 are ignored in current version. - -OUTPUT PARAMETERS: - Analysis - symbolic analysis of the matrix structure, new strategy - Results will be seen with next SparseCholeskyFactorize() - call. - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -void sparsecholeskysetmodtype(sparsedecompositionanalysis* analysis, - ae_int_t modstrategy, - double p0, - double p1, - double p2, - double p3, - ae_state *_state) -{ - - - spsymmsetmodificationstrategy(&analysis->analysis, modstrategy, p0, p1, p2, p3, _state); -} - - -/************************************************************************* -Sparse Cholesky decomposition: numerical analysis phase. - -This function is a part of the 'expert' sparse Cholesky API: -* SparseCholeskyAnalyze(), that performs symbolic analysis phase and loads - matrix to be factorized into internal storage -* SparseCholeskySetModType(), that allows to use modified Cholesky/LDLT - with lower bounds on pivot magnitudes and additional overflow safeguards -* SparseCholeskyFactorize(), that performs numeric factorization using - precomputed symbolic analysis and internally stored matrix - and outputs - result -* SparseCholeskyReload(), that reloads one more matrix with same sparsity - pattern into internal storage so one may reuse previously allocated - temporaries and previously performed symbolic analysis - -Depending on settings specified during SparseCholeskyAnalyze() call it may -produce classic Cholesky or L*D*LT decomposition (with strictly diagonal -D), without permutation or with performance-enhancing permutation P. - -NOTE: all internal processing is performed with lower triangular matrices - stored in CRS format. Any other storage formats and/or upper - triangular storage means that one format conversion and/or one - transposition will be performed internally for the analysis and - factorization phases. Thus, highest performance is achieved when - input is a lower triangular CRS matrix, and lower triangular output - is requested. - -NOTE: L*D*LT family of factorization may be used to factorize indefinite - matrices. However, numerical stability is guaranteed ONLY for a class - of quasi-definite matrices. - -INPUT PARAMETERS: - Analysis - prior analysis with internally stored matrix which will - be factorized - NeedUpper - whether upper triangular or lower triangular output is - needed - -OUTPUT PARAMETERS: - A - Cholesky decomposition of A stored in lower triangular - CRS format, i.e. A=L*L' (or upper triangular CRS, with - A=U'*U, depending on NeedUpper parameter). - D - array[N], diagonal factor. If no diagonal factor was - required during analysis phase, still returned but - filled with 1's - P - array[N], pivots. Permutation matrix P is a product of - P(0)*P(1)*...*P(N-1), where P(i) is a permutation of - row/col I and P[I] (with P[I]>=I). - If no permutation was requested during analysis phase, - still returned but filled with identity permutation. - -The function returns True when factorization resulted in nondegenerate -matrix. False is returned when factorization fails (Cholesky factorization -of indefinite matrix) or LDLT factorization has exactly zero elements at -the diagonal. In the latter case contents of A, D and P is undefined. - -The analysis object is not changed during the factorization. Subsequent -calls to SparseCholeskyFactorize() will result in same factorization being -performed one more time. - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -ae_bool sparsecholeskyfactorize(sparsedecompositionanalysis* analysis, - ae_bool needupper, - sparsematrix* a, - /* Real */ ae_vector* d, - /* Integer */ ae_vector* p, - ae_state *_state) -{ - ae_bool result; - - _sparsematrix_clear(a); - ae_vector_clear(d); - ae_vector_clear(p); - - if( needupper ) - { - result = spsymmfactorize(&analysis->analysis, &analysis->wrka, d, p, _state); - if( !result ) - { - return result; - } - sparsecopytransposecrsbuf(&analysis->wrka, a, _state); - } - else - { - result = spsymmfactorize(&analysis->analysis, a, d, p, _state); - } - return result; -} - - -/************************************************************************* -Sparse Cholesky decomposition: update internally stored matrix with -another one with exactly same sparsity pattern. - -This function is a part of the 'expert' sparse Cholesky API: -* SparseCholeskyAnalyze(), that performs symbolic analysis phase and loads - matrix to be factorized into internal storage -* SparseCholeskySetModType(), that allows to use modified Cholesky/LDLT - with lower bounds on pivot magnitudes and additional overflow safeguards -* SparseCholeskyFactorize(), that performs numeric factorization using - precomputed symbolic analysis and internally stored matrix - and outputs - result -* SparseCholeskyReload(), that reloads one more matrix with same sparsity - pattern into internal storage so one may reuse previously allocated - temporaries and previously performed symbolic analysis - -This specific function replaces internally stored numerical values with -ones from another sparse matrix (but having exactly same sparsity pattern -as one that was used for initial SparseCholeskyAnalyze() call). - -NOTE: all internal processing is performed with lower triangular matrices - stored in CRS format. Any other storage formats and/or upper - triangular storage means that one format conversion and/or one - transposition will be performed internally for the analysis and - factorization phases. Thus, highest performance is achieved when - input is a lower triangular CRS matrix. - -INPUT PARAMETERS: - Analysis - analysis object - A - sparse square matrix in any sparse storage format. It - MUST have exactly same sparsity pattern as that of the - matrix that was passed to SparseCholeskyAnalyze(). - Any difference (missing elements or additional elements) - may result in unpredictable and undefined behavior - - an algorithm may fail due to memory access violation. - IsUpper - whether upper or lower triangle is decomposed (the - other one is ignored). - -OUTPUT PARAMETERS: - Analysis - contains: - * symbolic analysis of the matrix structure which will - be used later to guide numerical factorization. - * specific numeric values loaded into internal memory - waiting for the factorization to be performed - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -void sparsecholeskyreload(sparsedecompositionanalysis* analysis, - sparsematrix* a, - ae_bool isupper, - ae_state *_state) -{ - - - ae_assert(sparsegetnrows(a, _state)==sparsegetncols(a, _state), "SparseCholeskyReload: A is not square", _state); - ae_assert(sparsegetnrows(a, _state)==analysis->n, "SparseCholeskyReload: size of A does not match that stored in Analysis", _state); - if( !sparseiscrs(a, _state) ) - { - - /* - * The matrix is stored in non-CRS format. First, we have to convert - * it to CRS. Then we may need to transpose it in order to get lower - * triangular one (as supported by SPSymmAnalyze). - */ - sparsecopytocrs(a, &analysis->crsa, _state); - if( isupper ) - { - sparsecopytransposecrsbuf(&analysis->crsa, &analysis->crsat, _state); - spsymmreload(&analysis->analysis, &analysis->crsat, _state); - } - else - { - spsymmreload(&analysis->analysis, &analysis->crsa, _state); - } - } - else - { - - /* - * The matrix is stored in CRS format. However we may need to - * transpose it in order to get lower triangular one (as supported - * by SPSymmAnalyze). - */ - if( isupper ) - { - sparsecopytransposecrsbuf(a, &analysis->crsat, _state); - spsymmreload(&analysis->analysis, &analysis->crsat, _state); - } - else - { - spsymmreload(&analysis->analysis, a, _state); - } - } -} - - -void rmatrixlup(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector tmp; - ae_int_t i; - ae_int_t j; - double mx; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&tmp, 0, sizeof(tmp)); - ae_vector_clear(pivots); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - - - /* - * Internal LU decomposition subroutine. - * Never call it directly. - */ - ae_assert(m>0, "RMatrixLUP: incorrect M!", _state); - ae_assert(n>0, "RMatrixLUP: incorrect N!", _state); - - /* - * Scale matrix to avoid overflows, - * decompose it, then scale back. - */ - mx = (double)(0); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - mx = ae_maxreal(mx, ae_fabs(a->ptr.pp_double[i][j], _state), _state); - } - } - if( ae_fp_neq(mx,(double)(0)) ) - { - v = 1/mx; - for(i=0; i<=m-1; i++) - { - ae_v_muld(&a->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v); - } - } - ae_vector_set_length(pivots, ae_minint(m, n, _state), _state); - ae_vector_set_length(&tmp, 2*ae_maxint(m, n, _state), _state); - rmatrixluprec(a, 0, m, n, pivots, &tmp, _state); - if( ae_fp_neq(mx,(double)(0)) ) - { - v = mx; - for(i=0; i<=m-1; i++) - { - ae_v_muld(&a->ptr.pp_double[i][0], 1, ae_v_len(0,ae_minint(i, n-1, _state)), v); - } - } - ae_frame_leave(_state); -} - - -void cmatrixlup(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector tmp; - ae_int_t i; - ae_int_t j; - double mx; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&tmp, 0, sizeof(tmp)); - ae_vector_clear(pivots); - ae_vector_init(&tmp, 0, DT_COMPLEX, _state, ae_true); - - - /* - * Internal LU decomposition subroutine. - * Never call it directly. - */ - ae_assert(m>0, "CMatrixLUP: incorrect M!", _state); - ae_assert(n>0, "CMatrixLUP: incorrect N!", _state); - - /* - * Scale matrix to avoid overflows, - * decompose it, then scale back. - */ - mx = (double)(0); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - mx = ae_maxreal(mx, ae_c_abs(a->ptr.pp_complex[i][j], _state), _state); - } - } - if( ae_fp_neq(mx,(double)(0)) ) - { - v = 1/mx; - for(i=0; i<=m-1; i++) - { - ae_v_cmuld(&a->ptr.pp_complex[i][0], 1, ae_v_len(0,n-1), v); - } - } - ae_vector_set_length(pivots, ae_minint(m, n, _state), _state); - ae_vector_set_length(&tmp, 2*ae_maxint(m, n, _state), _state); - cmatrixluprec(a, 0, m, n, pivots, &tmp, _state); - if( ae_fp_neq(mx,(double)(0)) ) - { - v = mx; - for(i=0; i<=m-1; i++) - { - ae_v_cmuld(&a->ptr.pp_complex[i][0], 1, ae_v_len(0,ae_minint(i, n-1, _state)), v); - } - } - ae_frame_leave(_state); -} - - -void rmatrixplu(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector tmp; - ae_int_t i; - ae_int_t j; - double mx; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&tmp, 0, sizeof(tmp)); - ae_vector_clear(pivots); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - - - /* - * Internal LU decomposition subroutine. - * Never call it directly. - */ - ae_assert(m>0, "RMatrixPLU: incorrect M!", _state); - ae_assert(n>0, "RMatrixPLU: incorrect N!", _state); - ae_vector_set_length(&tmp, 2*ae_maxint(m, n, _state), _state); - ae_vector_set_length(pivots, ae_minint(m, n, _state), _state); - - /* - * Scale matrix to avoid overflows, - * decompose it, then scale back. - */ - mx = (double)(0); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - mx = ae_maxreal(mx, ae_fabs(a->ptr.pp_double[i][j], _state), _state); - } - } - if( ae_fp_neq(mx,(double)(0)) ) - { - v = 1/mx; - for(i=0; i<=m-1; i++) - { - ae_v_muld(&a->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v); - } - } - rmatrixplurec(a, 0, m, n, pivots, &tmp, _state); - if( ae_fp_neq(mx,(double)(0)) ) - { - v = mx; - for(i=0; i<=ae_minint(m, n, _state)-1; i++) - { - ae_v_muld(&a->ptr.pp_double[i][i], 1, ae_v_len(i,n-1), v); - } - } - ae_frame_leave(_state); -} - - -void cmatrixplu(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector tmp; - ae_int_t i; - ae_int_t j; - double mx; - ae_complex v; - - ae_frame_make(_state, &_frame_block); - memset(&tmp, 0, sizeof(tmp)); - ae_vector_clear(pivots); - ae_vector_init(&tmp, 0, DT_COMPLEX, _state, ae_true); - - - /* - * Internal LU decomposition subroutine. - * Never call it directly. - */ - ae_assert(m>0, "CMatrixPLU: incorrect M!", _state); - ae_assert(n>0, "CMatrixPLU: incorrect N!", _state); - ae_vector_set_length(&tmp, 2*ae_maxint(m, n, _state), _state); - ae_vector_set_length(pivots, ae_minint(m, n, _state), _state); - - /* - * Scale matrix to avoid overflows, - * decompose it, then scale back. - */ - mx = (double)(0); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - mx = ae_maxreal(mx, ae_c_abs(a->ptr.pp_complex[i][j], _state), _state); - } - } - if( ae_fp_neq(mx,(double)(0)) ) - { - v = ae_complex_from_d(1/mx); - for(i=0; i<=m-1; i++) - { - ae_v_cmulc(&a->ptr.pp_complex[i][0], 1, ae_v_len(0,n-1), v); - } - } - cmatrixplurec(a, 0, m, n, pivots, &tmp, _state); - if( ae_fp_neq(mx,(double)(0)) ) - { - v = ae_complex_from_d(mx); - for(i=0; i<=ae_minint(m, n, _state)-1; i++) - { - ae_v_cmulc(&a->ptr.pp_complex[i][i], 1, ae_v_len(i,n-1), v); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Advanced interface for SPDMatrixCholesky, performs no temporary allocations. - -INPUT PARAMETERS: - A - matrix given by upper or lower triangle - Offs - offset of diagonal block to decompose - N - diagonal block size - IsUpper - what half is given - Tmp - temporary array; allocated by function, if its size is too - small; can be reused on subsequent calls. - -OUTPUT PARAMETERS: - A - upper (or lower) triangle contains Cholesky decomposition - -RESULT: - True, on success - False, on failure - - -- ALGLIB routine -- - 15.12.2009 - Bochkanov Sergey -*************************************************************************/ -ae_bool spdmatrixcholeskyrec(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* tmp, - ae_state *_state) -{ - ae_int_t n1; - ae_int_t n2; - ae_int_t tsa; - ae_int_t tsb; - ae_bool result; - - - tsa = matrixtilesizea(_state); - tsb = matrixtilesizeb(_state); - - /* - * Allocate temporaries - */ - if( tmp->cnt<2*n ) - { - ae_vector_set_length(tmp, 2*n, _state); - } - - /* - * Basecases - */ - if( n<1 ) - { - result = ae_false; - return result; - } - if( n==1 ) - { - if( ae_fp_greater(a->ptr.pp_double[offs][offs],(double)(0)) ) - { - a->ptr.pp_double[offs][offs] = ae_sqrt(a->ptr.pp_double[offs][offs], _state); - result = ae_true; - } - else - { - result = ae_false; - } - return result; - } - if( n<=tsb ) - { - if( spdmatrixcholeskymkl(a, offs, n, isupper, &result, _state) ) - { - return result; - } - } - if( n<=tsa ) - { - result = trfac_spdmatrixcholesky2(a, offs, n, isupper, tmp, _state); - return result; - } - - /* - * Split task into smaller ones - */ - if( n>tsb ) - { - - /* - * Split leading B-sized block from the beginning (block-matrix approach) - */ - n1 = tsb; - n2 = n-n1; - } - else - { - - /* - * Smaller than B-size, perform cache-oblivious split - */ - tiledsplit(n, tsa, &n1, &n2, _state); - } - result = spdmatrixcholeskyrec(a, offs, n1, isupper, tmp, _state); - if( !result ) - { - return result; - } - if( n2>0 ) - { - if( isupper ) - { - rmatrixlefttrsm(n1, n2, a, offs, offs, isupper, ae_false, 1, a, offs, offs+n1, _state); - rmatrixsyrk(n2, n1, -1.0, a, offs, offs+n1, 1, 1.0, a, offs+n1, offs+n1, isupper, _state); - } - else - { - rmatrixrighttrsm(n2, n1, a, offs, offs, isupper, ae_false, 1, a, offs+n1, offs, _state); - rmatrixsyrk(n2, n1, -1.0, a, offs+n1, offs, 0, 1.0, a, offs+n1, offs+n1, isupper, _state); - } - result = spdmatrixcholeskyrec(a, offs+n1, n2, isupper, tmp, _state); - if( !result ) - { - return result; - } - } - return result; -} - - -/************************************************************************* -Recursive computational subroutine for HPDMatrixCholesky - - -- ALGLIB routine -- - 15.12.2009 - Bochkanov Sergey -*************************************************************************/ -static ae_bool trfac_hpdmatrixcholeskyrec(/* Complex */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* tmp, - ae_state *_state) -{ - ae_int_t n1; - ae_int_t n2; - ae_int_t tsa; - ae_int_t tsb; - ae_bool result; - - - tsa = matrixtilesizea(_state)/2; - tsb = matrixtilesizeb(_state); - - /* - * check N - */ - if( n<1 ) - { - result = ae_false; - return result; - } - - /* - * Prepare buffer - */ - if( tmp->cnt<2*n ) - { - ae_vector_set_length(tmp, 2*n, _state); - } - - /* - * Basecases - * - * NOTE: we do not use MKL for basecases because their price is only - * minor part of overall running time for N>256. - */ - if( n==1 ) - { - if( ae_fp_greater(a->ptr.pp_complex[offs][offs].x,(double)(0)) ) - { - a->ptr.pp_complex[offs][offs] = ae_complex_from_d(ae_sqrt(a->ptr.pp_complex[offs][offs].x, _state)); - result = ae_true; - } - else - { - result = ae_false; - } - return result; - } - if( n<=tsa ) - { - result = trfac_hpdmatrixcholesky2(a, offs, n, isupper, tmp, _state); - return result; - } - - /* - * Split task into smaller ones - */ - if( n>tsb ) - { - - /* - * Split leading B-sized block from the beginning (block-matrix approach) - */ - n1 = tsb; - n2 = n-n1; - } - else - { - - /* - * Smaller than B-size, perform cache-oblivious split - */ - tiledsplit(n, tsa, &n1, &n2, _state); - } - result = trfac_hpdmatrixcholeskyrec(a, offs, n1, isupper, tmp, _state); - if( !result ) - { - return result; - } - if( n2>0 ) - { - if( isupper ) - { - cmatrixlefttrsm(n1, n2, a, offs, offs, isupper, ae_false, 2, a, offs, offs+n1, _state); - cmatrixherk(n2, n1, -1.0, a, offs, offs+n1, 2, 1.0, a, offs+n1, offs+n1, isupper, _state); - } - else - { - cmatrixrighttrsm(n2, n1, a, offs, offs, isupper, ae_false, 2, a, offs+n1, offs, _state); - cmatrixherk(n2, n1, -1.0, a, offs+n1, offs, 0, 1.0, a, offs+n1, offs+n1, isupper, _state); - } - result = trfac_hpdmatrixcholeskyrec(a, offs+n1, n2, isupper, tmp, _state); - if( !result ) - { - return result; - } - } - return result; -} - - -/************************************************************************* -Level-2 Hermitian Cholesky subroutine. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - February 29, 1992 -*************************************************************************/ -static ae_bool trfac_hpdmatrixcholesky2(/* Complex */ ae_matrix* aaa, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* tmp, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double ajj; - ae_complex v; - double r; - ae_bool result; - - - result = ae_true; - if( n<0 ) - { - result = ae_false; - return result; - } - - /* - * Quick return if possible - */ - if( n==0 ) - { - return result; - } - if( isupper ) - { - - /* - * Compute the Cholesky factorization A = U'*U. - */ - for(j=0; j<=n-1; j++) - { - - /* - * Compute U(J,J) and test for non-positive-definiteness. - */ - v = ae_v_cdotproduct(&aaa->ptr.pp_complex[offs][offs+j], aaa->stride, "Conj", &aaa->ptr.pp_complex[offs][offs+j], aaa->stride, "N", ae_v_len(offs,offs+j-1)); - ajj = ae_c_sub(aaa->ptr.pp_complex[offs+j][offs+j],v).x; - if( ae_fp_less_eq(ajj,(double)(0)) ) - { - aaa->ptr.pp_complex[offs+j][offs+j] = ae_complex_from_d(ajj); - result = ae_false; - return result; - } - ajj = ae_sqrt(ajj, _state); - aaa->ptr.pp_complex[offs+j][offs+j] = ae_complex_from_d(ajj); - - /* - * Compute elements J+1:N-1 of row J. - */ - if( j0 ) - { - ae_v_cmoveneg(&tmp->ptr.p_complex[0], 1, &aaa->ptr.pp_complex[offs][offs+j], aaa->stride, "Conj", ae_v_len(0,j-1)); - cmatrixmv(n-j-1, j, aaa, offs, offs+j+1, 1, tmp, 0, tmp, n, _state); - ae_v_cadd(&aaa->ptr.pp_complex[offs+j][offs+j+1], 1, &tmp->ptr.p_complex[n], 1, "N", ae_v_len(offs+j+1,offs+n-1)); - } - r = 1/ajj; - ae_v_cmuld(&aaa->ptr.pp_complex[offs+j][offs+j+1], 1, ae_v_len(offs+j+1,offs+n-1), r); - } - } - } - else - { - - /* - * Compute the Cholesky factorization A = L*L'. - */ - for(j=0; j<=n-1; j++) - { - - /* - * Compute L(J+1,J+1) and test for non-positive-definiteness. - */ - v = ae_v_cdotproduct(&aaa->ptr.pp_complex[offs+j][offs], 1, "Conj", &aaa->ptr.pp_complex[offs+j][offs], 1, "N", ae_v_len(offs,offs+j-1)); - ajj = ae_c_sub(aaa->ptr.pp_complex[offs+j][offs+j],v).x; - if( ae_fp_less_eq(ajj,(double)(0)) ) - { - aaa->ptr.pp_complex[offs+j][offs+j] = ae_complex_from_d(ajj); - result = ae_false; - return result; - } - ajj = ae_sqrt(ajj, _state); - aaa->ptr.pp_complex[offs+j][offs+j] = ae_complex_from_d(ajj); - - /* - * Compute elements J+1:N of column J. - */ - if( j0 ) - { - ae_v_cmove(&tmp->ptr.p_complex[0], 1, &aaa->ptr.pp_complex[offs+j][offs], 1, "Conj", ae_v_len(0,j-1)); - cmatrixmv(n-j-1, j, aaa, offs+j+1, offs, 0, tmp, 0, tmp, n, _state); - for(i=0; i<=n-j-2; i++) - { - aaa->ptr.pp_complex[offs+j+1+i][offs+j] = ae_c_mul_d(ae_c_sub(aaa->ptr.pp_complex[offs+j+1+i][offs+j],tmp->ptr.p_complex[n+i]),r); - } - } - else - { - for(i=0; i<=n-j-2; i++) - { - aaa->ptr.pp_complex[offs+j+1+i][offs+j] = ae_c_mul_d(aaa->ptr.pp_complex[offs+j+1+i][offs+j],r); - } - } - } - } - } - return result; -} - - -/************************************************************************* -Level-2 Cholesky subroutine - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - February 29, 1992 -*************************************************************************/ -static ae_bool trfac_spdmatrixcholesky2(/* Real */ ae_matrix* aaa, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* tmp, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double ajj; - double v; - double r; - ae_bool result; - - - result = ae_true; - if( n<0 ) - { - result = ae_false; - return result; - } - - /* - * Quick return if possible - */ - if( n==0 ) - { - return result; - } - if( isupper ) - { - - /* - * Compute the Cholesky factorization A = U'*U. - */ - for(j=0; j<=n-1; j++) - { - - /* - * Compute U(J,J) and test for non-positive-definiteness. - */ - v = ae_v_dotproduct(&aaa->ptr.pp_double[offs][offs+j], aaa->stride, &aaa->ptr.pp_double[offs][offs+j], aaa->stride, ae_v_len(offs,offs+j-1)); - ajj = aaa->ptr.pp_double[offs+j][offs+j]-v; - if( ae_fp_less_eq(ajj,(double)(0)) ) - { - aaa->ptr.pp_double[offs+j][offs+j] = ajj; - result = ae_false; - return result; - } - ajj = ae_sqrt(ajj, _state); - aaa->ptr.pp_double[offs+j][offs+j] = ajj; - - /* - * Compute elements J+1:N-1 of row J. - */ - if( j0 ) - { - ae_v_moveneg(&tmp->ptr.p_double[0], 1, &aaa->ptr.pp_double[offs][offs+j], aaa->stride, ae_v_len(0,j-1)); - rmatrixmv(n-j-1, j, aaa, offs, offs+j+1, 1, tmp, 0, tmp, n, _state); - ae_v_add(&aaa->ptr.pp_double[offs+j][offs+j+1], 1, &tmp->ptr.p_double[n], 1, ae_v_len(offs+j+1,offs+n-1)); - } - r = 1/ajj; - ae_v_muld(&aaa->ptr.pp_double[offs+j][offs+j+1], 1, ae_v_len(offs+j+1,offs+n-1), r); - } - } - } - else - { - - /* - * Compute the Cholesky factorization A = L*L'. - */ - for(j=0; j<=n-1; j++) - { - - /* - * Compute L(J+1,J+1) and test for non-positive-definiteness. - */ - v = ae_v_dotproduct(&aaa->ptr.pp_double[offs+j][offs], 1, &aaa->ptr.pp_double[offs+j][offs], 1, ae_v_len(offs,offs+j-1)); - ajj = aaa->ptr.pp_double[offs+j][offs+j]-v; - if( ae_fp_less_eq(ajj,(double)(0)) ) - { - aaa->ptr.pp_double[offs+j][offs+j] = ajj; - result = ae_false; - return result; - } - ajj = ae_sqrt(ajj, _state); - aaa->ptr.pp_double[offs+j][offs+j] = ajj; - - /* - * Compute elements J+1:N of column J. - */ - if( j0 ) - { - ae_v_move(&tmp->ptr.p_double[0], 1, &aaa->ptr.pp_double[offs+j][offs], 1, ae_v_len(0,j-1)); - rmatrixmv(n-j-1, j, aaa, offs+j+1, offs, 0, tmp, 0, tmp, n, _state); - for(i=0; i<=n-j-2; i++) - { - aaa->ptr.pp_double[offs+j+1+i][offs+j] = (aaa->ptr.pp_double[offs+j+1+i][offs+j]-tmp->ptr.p_double[n+i])*r; - } - } - else - { - for(i=0; i<=n-j-2; i++) - { - aaa->ptr.pp_double[offs+j+1+i][offs+j] = aaa->ptr.pp_double[offs+j+1+i][offs+j]*r; - } - } - } - } - } - return result; -} - - -void _sparsedecompositionanalysis_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - sparsedecompositionanalysis *p = (sparsedecompositionanalysis*)_p; - ae_touch_ptr((void*)p); - _spcholanalysis_init(&p->analysis, _state, make_automatic); - _sparsematrix_init(&p->wrka, _state, make_automatic); - _sparsematrix_init(&p->wrkat, _state, make_automatic); - _sparsematrix_init(&p->crsa, _state, make_automatic); - _sparsematrix_init(&p->crsat, _state, make_automatic); -} - - -void _sparsedecompositionanalysis_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - sparsedecompositionanalysis *dst = (sparsedecompositionanalysis*)_dst; - sparsedecompositionanalysis *src = (sparsedecompositionanalysis*)_src; - dst->n = src->n; - dst->facttype = src->facttype; - dst->permtype = src->permtype; - _spcholanalysis_init_copy(&dst->analysis, &src->analysis, _state, make_automatic); - _sparsematrix_init_copy(&dst->wrka, &src->wrka, _state, make_automatic); - _sparsematrix_init_copy(&dst->wrkat, &src->wrkat, _state, make_automatic); - _sparsematrix_init_copy(&dst->crsa, &src->crsa, _state, make_automatic); - _sparsematrix_init_copy(&dst->crsat, &src->crsat, _state, make_automatic); -} - - -void _sparsedecompositionanalysis_clear(void* _p) -{ - sparsedecompositionanalysis *p = (sparsedecompositionanalysis*)_p; - ae_touch_ptr((void*)p); - _spcholanalysis_clear(&p->analysis); - _sparsematrix_clear(&p->wrka); - _sparsematrix_clear(&p->wrkat); - _sparsematrix_clear(&p->crsa); - _sparsematrix_clear(&p->crsat); -} - - -void _sparsedecompositionanalysis_destroy(void* _p) -{ - sparsedecompositionanalysis *p = (sparsedecompositionanalysis*)_p; - ae_touch_ptr((void*)p); - _spcholanalysis_destroy(&p->analysis); - _sparsematrix_destroy(&p->wrka); - _sparsematrix_destroy(&p->wrkat); - _sparsematrix_destroy(&p->crsa); - _sparsematrix_destroy(&p->crsat); -} - - -#endif -#if defined(AE_COMPILE_RCOND) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Estimate of a matrix condition number (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double rmatrixrcond1(/* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_int_t i; - ae_int_t j; - double v; - double nrm; - ae_vector pivots; - ae_vector t; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&pivots, 0, sizeof(pivots)); - memset(&t, 0, sizeof(t)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_vector_init(&pivots, 0, DT_INT, _state, ae_true); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=1, "RMatrixRCond1: N<1!", _state); - ae_vector_set_length(&t, n, _state); - for(i=0; i<=n-1; i++) - { - t.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - t.ptr.p_double[j] = t.ptr.p_double[j]+ae_fabs(a->ptr.pp_double[i][j], _state); - } - } - nrm = (double)(0); - for(i=0; i<=n-1; i++) - { - nrm = ae_maxreal(nrm, t.ptr.p_double[i], _state); - } - rmatrixlu(a, n, n, &pivots, _state); - rcond_rmatrixrcondluinternal(a, n, ae_true, ae_true, nrm, &v, _state); - result = v; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Estimate of a matrix condition number (infinity-norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double rmatrixrcondinf(/* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_int_t i; - ae_int_t j; - double v; - double nrm; - ae_vector pivots; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&pivots, 0, sizeof(pivots)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_vector_init(&pivots, 0, DT_INT, _state, ae_true); - - ae_assert(n>=1, "RMatrixRCondInf: N<1!", _state); - nrm = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+ae_fabs(a->ptr.pp_double[i][j], _state); - } - nrm = ae_maxreal(nrm, v, _state); - } - rmatrixlu(a, n, n, &pivots, _state); - rcond_rmatrixrcondluinternal(a, n, ae_false, ae_true, nrm, &v, _state); - result = v; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Condition number estimate of a symmetric positive definite matrix. - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -It should be noted that 1-norm and inf-norm of condition numbers of symmetric -matrices are equal, so the algorithm doesn't take into account the -differences between these types of norms. - -Input parameters: - A - symmetric positive definite matrix which is given by its - upper or lower triangle depending on the value of - IsUpper. Array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - storage format. - -Result: - 1/LowerBound(cond(A)), if matrix A is positive definite, - -1, if matrix A is not positive definite, and its condition number - could not be found by this algorithm. - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double spdmatrixrcond(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_int_t i; - ae_int_t j; - ae_int_t j1; - ae_int_t j2; - double v; - double nrm; - ae_vector t; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&t, 0, sizeof(t)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&t, n, _state); - for(i=0; i<=n-1; i++) - { - t.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j1 = i; - j2 = n-1; - } - else - { - j1 = 0; - j2 = i; - } - for(j=j1; j<=j2; j++) - { - if( i==j ) - { - t.ptr.p_double[i] = t.ptr.p_double[i]+ae_fabs(a->ptr.pp_double[i][i], _state); - } - else - { - t.ptr.p_double[i] = t.ptr.p_double[i]+ae_fabs(a->ptr.pp_double[i][j], _state); - t.ptr.p_double[j] = t.ptr.p_double[j]+ae_fabs(a->ptr.pp_double[i][j], _state); - } - } - } - nrm = (double)(0); - for(i=0; i<=n-1; i++) - { - nrm = ae_maxreal(nrm, t.ptr.p_double[i], _state); - } - if( spdmatrixcholesky(a, n, isupper, _state) ) - { - rcond_spdmatrixrcondcholeskyinternal(a, n, isupper, ae_true, nrm, &v, _state); - result = v; - } - else - { - result = (double)(-1); - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Triangular matrix: estimate of a condition number (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array[0..N-1, 0..N-1]. - N - size of A. - IsUpper - True, if the matrix is upper triangular. - IsUnit - True, if the matrix has a unit diagonal. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double rmatrixtrrcond1(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - double v; - double nrm; - ae_vector pivots; - ae_vector t; - ae_int_t j1; - ae_int_t j2; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&pivots, 0, sizeof(pivots)); - memset(&t, 0, sizeof(t)); - ae_vector_init(&pivots, 0, DT_INT, _state, ae_true); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=1, "RMatrixTRRCond1: N<1!", _state); - ae_vector_set_length(&t, n, _state); - for(i=0; i<=n-1; i++) - { - t.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j1 = i+1; - j2 = n-1; - } - else - { - j1 = 0; - j2 = i-1; - } - for(j=j1; j<=j2; j++) - { - t.ptr.p_double[j] = t.ptr.p_double[j]+ae_fabs(a->ptr.pp_double[i][j], _state); - } - if( isunit ) - { - t.ptr.p_double[i] = t.ptr.p_double[i]+1; - } - else - { - t.ptr.p_double[i] = t.ptr.p_double[i]+ae_fabs(a->ptr.pp_double[i][i], _state); - } - } - nrm = (double)(0); - for(i=0; i<=n-1; i++) - { - nrm = ae_maxreal(nrm, t.ptr.p_double[i], _state); - } - rcond_rmatrixrcondtrinternal(a, n, isupper, isunit, ae_true, nrm, &v, _state); - result = v; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Triangular matrix: estimate of a matrix condition number (infinity-norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - True, if the matrix is upper triangular. - IsUnit - True, if the matrix has a unit diagonal. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double rmatrixtrrcondinf(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - double v; - double nrm; - ae_vector pivots; - ae_int_t j1; - ae_int_t j2; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&pivots, 0, sizeof(pivots)); - ae_vector_init(&pivots, 0, DT_INT, _state, ae_true); - - ae_assert(n>=1, "RMatrixTRRCondInf: N<1!", _state); - nrm = (double)(0); - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j1 = i+1; - j2 = n-1; - } - else - { - j1 = 0; - j2 = i-1; - } - v = (double)(0); - for(j=j1; j<=j2; j++) - { - v = v+ae_fabs(a->ptr.pp_double[i][j], _state); - } - if( isunit ) - { - v = v+1; - } - else - { - v = v+ae_fabs(a->ptr.pp_double[i][i], _state); - } - nrm = ae_maxreal(nrm, v, _state); - } - rcond_rmatrixrcondtrinternal(a, n, isupper, isunit, ae_false, nrm, &v, _state); - result = v; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Condition number estimate of a Hermitian positive definite matrix. - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -It should be noted that 1-norm and inf-norm of condition numbers of symmetric -matrices are equal, so the algorithm doesn't take into account the -differences between these types of norms. - -Input parameters: - A - Hermitian positive definite matrix which is given by its - upper or lower triangle depending on the value of - IsUpper. Array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - storage format. - -Result: - 1/LowerBound(cond(A)), if matrix A is positive definite, - -1, if matrix A is not positive definite, and its condition number - could not be found by this algorithm. - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double hpdmatrixrcond(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_int_t i; - ae_int_t j; - ae_int_t j1; - ae_int_t j2; - double v; - double nrm; - ae_vector t; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&t, 0, sizeof(t)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&t, n, _state); - for(i=0; i<=n-1; i++) - { - t.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j1 = i; - j2 = n-1; - } - else - { - j1 = 0; - j2 = i; - } - for(j=j1; j<=j2; j++) - { - if( i==j ) - { - t.ptr.p_double[i] = t.ptr.p_double[i]+ae_c_abs(a->ptr.pp_complex[i][i], _state); - } - else - { - t.ptr.p_double[i] = t.ptr.p_double[i]+ae_c_abs(a->ptr.pp_complex[i][j], _state); - t.ptr.p_double[j] = t.ptr.p_double[j]+ae_c_abs(a->ptr.pp_complex[i][j], _state); - } - } - } - nrm = (double)(0); - for(i=0; i<=n-1; i++) - { - nrm = ae_maxreal(nrm, t.ptr.p_double[i], _state); - } - if( hpdmatrixcholesky(a, n, isupper, _state) ) - { - rcond_hpdmatrixrcondcholeskyinternal(a, n, isupper, ae_true, nrm, &v, _state); - result = v; - } - else - { - result = (double)(-1); - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Estimate of a matrix condition number (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double cmatrixrcond1(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_int_t i; - ae_int_t j; - double v; - double nrm; - ae_vector pivots; - ae_vector t; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&pivots, 0, sizeof(pivots)); - memset(&t, 0, sizeof(t)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_vector_init(&pivots, 0, DT_INT, _state, ae_true); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=1, "CMatrixRCond1: N<1!", _state); - ae_vector_set_length(&t, n, _state); - for(i=0; i<=n-1; i++) - { - t.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - t.ptr.p_double[j] = t.ptr.p_double[j]+ae_c_abs(a->ptr.pp_complex[i][j], _state); - } - } - nrm = (double)(0); - for(i=0; i<=n-1; i++) - { - nrm = ae_maxreal(nrm, t.ptr.p_double[i], _state); - } - cmatrixlu(a, n, n, &pivots, _state); - rcond_cmatrixrcondluinternal(a, n, ae_true, ae_true, nrm, &v, _state); - result = v; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Estimate of a matrix condition number (infinity-norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double cmatrixrcondinf(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_int_t i; - ae_int_t j; - double v; - double nrm; - ae_vector pivots; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&pivots, 0, sizeof(pivots)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_vector_init(&pivots, 0, DT_INT, _state, ae_true); - - ae_assert(n>=1, "CMatrixRCondInf: N<1!", _state); - nrm = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+ae_c_abs(a->ptr.pp_complex[i][j], _state); - } - nrm = ae_maxreal(nrm, v, _state); - } - cmatrixlu(a, n, n, &pivots, _state); - rcond_cmatrixrcondluinternal(a, n, ae_false, ae_true, nrm, &v, _state); - result = v; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Estimate of the condition number of a matrix given by its LU decomposition (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - LUA - LU decomposition of a matrix in compact form. Output of - the RMatrixLU subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double rmatrixlurcond1(/* Real */ ae_matrix* lua, - ae_int_t n, - ae_state *_state) -{ - double v; - double result; - - - rcond_rmatrixrcondluinternal(lua, n, ae_true, ae_false, (double)(0), &v, _state); - result = v; - return result; -} - - -/************************************************************************* -Estimate of the condition number of a matrix given by its LU decomposition -(infinity norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - LUA - LU decomposition of a matrix in compact form. Output of - the RMatrixLU subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double rmatrixlurcondinf(/* Real */ ae_matrix* lua, - ae_int_t n, - ae_state *_state) -{ - double v; - double result; - - - rcond_rmatrixrcondluinternal(lua, n, ae_false, ae_false, (double)(0), &v, _state); - result = v; - return result; -} - - -/************************************************************************* -Condition number estimate of a symmetric positive definite matrix given by -Cholesky decomposition. - -The algorithm calculates a lower bound of the condition number. In this -case, the algorithm does not return a lower bound of the condition number, -but an inverse number (to avoid an overflow in case of a singular matrix). - -It should be noted that 1-norm and inf-norm condition numbers of symmetric -matrices are equal, so the algorithm doesn't take into account the -differences between these types of norms. - -Input parameters: - CD - Cholesky decomposition of matrix A, - output of SMatrixCholesky subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double spdmatrixcholeskyrcond(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_state *_state) -{ - double v; - double result; - - - rcond_spdmatrixrcondcholeskyinternal(a, n, isupper, ae_false, (double)(0), &v, _state); - result = v; - return result; -} - - -/************************************************************************* -Condition number estimate of a Hermitian positive definite matrix given by -Cholesky decomposition. - -The algorithm calculates a lower bound of the condition number. In this -case, the algorithm does not return a lower bound of the condition number, -but an inverse number (to avoid an overflow in case of a singular matrix). - -It should be noted that 1-norm and inf-norm condition numbers of symmetric -matrices are equal, so the algorithm doesn't take into account the -differences between these types of norms. - -Input parameters: - CD - Cholesky decomposition of matrix A, - output of SMatrixCholesky subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double hpdmatrixcholeskyrcond(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_state *_state) -{ - double v; - double result; - - - rcond_hpdmatrixrcondcholeskyinternal(a, n, isupper, ae_false, (double)(0), &v, _state); - result = v; - return result; -} - - -/************************************************************************* -Estimate of the condition number of a matrix given by its LU decomposition (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - LUA - LU decomposition of a matrix in compact form. Output of - the CMatrixLU subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double cmatrixlurcond1(/* Complex */ ae_matrix* lua, - ae_int_t n, - ae_state *_state) -{ - double v; - double result; - - - ae_assert(n>=1, "CMatrixLURCond1: N<1!", _state); - rcond_cmatrixrcondluinternal(lua, n, ae_true, ae_false, 0.0, &v, _state); - result = v; - return result; -} - - -/************************************************************************* -Estimate of the condition number of a matrix given by its LU decomposition -(infinity norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - LUA - LU decomposition of a matrix in compact form. Output of - the CMatrixLU subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double cmatrixlurcondinf(/* Complex */ ae_matrix* lua, - ae_int_t n, - ae_state *_state) -{ - double v; - double result; - - - ae_assert(n>=1, "CMatrixLURCondInf: N<1!", _state); - rcond_cmatrixrcondluinternal(lua, n, ae_false, ae_false, 0.0, &v, _state); - result = v; - return result; -} - - -/************************************************************************* -Triangular matrix: estimate of a condition number (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array[0..N-1, 0..N-1]. - N - size of A. - IsUpper - True, if the matrix is upper triangular. - IsUnit - True, if the matrix has a unit diagonal. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double cmatrixtrrcond1(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - double v; - double nrm; - ae_vector pivots; - ae_vector t; - ae_int_t j1; - ae_int_t j2; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&pivots, 0, sizeof(pivots)); - memset(&t, 0, sizeof(t)); - ae_vector_init(&pivots, 0, DT_INT, _state, ae_true); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=1, "RMatrixTRRCond1: N<1!", _state); - ae_vector_set_length(&t, n, _state); - for(i=0; i<=n-1; i++) - { - t.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j1 = i+1; - j2 = n-1; - } - else - { - j1 = 0; - j2 = i-1; - } - for(j=j1; j<=j2; j++) - { - t.ptr.p_double[j] = t.ptr.p_double[j]+ae_c_abs(a->ptr.pp_complex[i][j], _state); - } - if( isunit ) - { - t.ptr.p_double[i] = t.ptr.p_double[i]+1; - } - else - { - t.ptr.p_double[i] = t.ptr.p_double[i]+ae_c_abs(a->ptr.pp_complex[i][i], _state); - } - } - nrm = (double)(0); - for(i=0; i<=n-1; i++) - { - nrm = ae_maxreal(nrm, t.ptr.p_double[i], _state); - } - rcond_cmatrixrcondtrinternal(a, n, isupper, isunit, ae_true, nrm, &v, _state); - result = v; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Triangular matrix: estimate of a matrix condition number (infinity-norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - True, if the matrix is upper triangular. - IsUnit - True, if the matrix has a unit diagonal. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double cmatrixtrrcondinf(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - double v; - double nrm; - ae_vector pivots; - ae_int_t j1; - ae_int_t j2; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&pivots, 0, sizeof(pivots)); - ae_vector_init(&pivots, 0, DT_INT, _state, ae_true); - - ae_assert(n>=1, "RMatrixTRRCondInf: N<1!", _state); - nrm = (double)(0); - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j1 = i+1; - j2 = n-1; - } - else - { - j1 = 0; - j2 = i-1; - } - v = (double)(0); - for(j=j1; j<=j2; j++) - { - v = v+ae_c_abs(a->ptr.pp_complex[i][j], _state); - } - if( isunit ) - { - v = v+1; - } - else - { - v = v+ae_c_abs(a->ptr.pp_complex[i][i], _state); - } - nrm = ae_maxreal(nrm, v, _state); - } - rcond_cmatrixrcondtrinternal(a, n, isupper, isunit, ae_false, nrm, &v, _state); - result = v; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Threshold for rcond: matrices with condition number beyond this threshold -are considered singular. - -Threshold must be far enough from underflow, at least Sqr(Threshold) must -be greater than underflow. -*************************************************************************/ -double rcondthreshold(ae_state *_state) -{ - double result; - - - result = ae_sqrt(ae_sqrt(ae_minrealnumber, _state), _state); - return result; -} - - -/************************************************************************* -Internal subroutine for condition number estimation - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - February 29, 1992 -*************************************************************************/ -static void rcond_rmatrixrcondtrinternal(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - ae_bool onenorm, - double anorm, - double* rc, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector ex; - ae_vector ev; - ae_vector iwork; - ae_vector tmp; - ae_int_t i; - ae_int_t j; - ae_int_t kase; - ae_int_t kase1; - ae_int_t j1; - ae_int_t j2; - double ainvnm; - double maxgrowth; - double s; - - ae_frame_make(_state, &_frame_block); - memset(&ex, 0, sizeof(ex)); - memset(&ev, 0, sizeof(ev)); - memset(&iwork, 0, sizeof(iwork)); - memset(&tmp, 0, sizeof(tmp)); - *rc = 0; - ae_vector_init(&ex, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ev, 0, DT_REAL, _state, ae_true); - ae_vector_init(&iwork, 0, DT_INT, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - - - /* - * RC=0 if something happens - */ - *rc = (double)(0); - - /* - * init - */ - if( onenorm ) - { - kase1 = 1; - } - else - { - kase1 = 2; - } - ae_vector_set_length(&iwork, n+1, _state); - ae_vector_set_length(&tmp, n, _state); - - /* - * prepare parameters for triangular solver - */ - maxgrowth = 1/rcondthreshold(_state); - s = (double)(0); - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j1 = i+1; - j2 = n-1; - } - else - { - j1 = 0; - j2 = i-1; - } - for(j=j1; j<=j2; j++) - { - s = ae_maxreal(s, ae_fabs(a->ptr.pp_double[i][j], _state), _state); - } - if( isunit ) - { - s = ae_maxreal(s, (double)(1), _state); - } - else - { - s = ae_maxreal(s, ae_fabs(a->ptr.pp_double[i][i], _state), _state); - } - } - if( ae_fp_eq(s,(double)(0)) ) - { - s = (double)(1); - } - s = 1/s; - - /* - * Scale according to S - */ - anorm = anorm*s; - - /* - * Quick return if possible - * We assume that ANORM<>0 after this block - */ - if( ae_fp_eq(anorm,(double)(0)) ) - { - ae_frame_leave(_state); - return; - } - if( n==1 ) - { - *rc = (double)(1); - ae_frame_leave(_state); - return; - } - - /* - * Estimate the norm of inv(A). - */ - ainvnm = (double)(0); - kase = 0; - for(;;) - { - rcond_rmatrixestimatenorm(n, &ev, &ex, &iwork, &ainvnm, &kase, _state); - if( kase==0 ) - { - break; - } - - /* - * from 1-based array to 0-based - */ - for(i=0; i<=n-1; i++) - { - ex.ptr.p_double[i] = ex.ptr.p_double[i+1]; - } - - /* - * multiply by inv(A) or inv(A') - */ - if( kase==kase1 ) - { - - /* - * multiply by inv(A) - */ - if( !rmatrixscaledtrsafesolve(a, s, n, &ex, isupper, 0, isunit, maxgrowth, _state) ) - { - ae_frame_leave(_state); - return; - } - } - else - { - - /* - * multiply by inv(A') - */ - if( !rmatrixscaledtrsafesolve(a, s, n, &ex, isupper, 1, isunit, maxgrowth, _state) ) - { - ae_frame_leave(_state); - return; - } - } - - /* - * from 0-based array to 1-based - */ - for(i=n-1; i>=0; i--) - { - ex.ptr.p_double[i+1] = ex.ptr.p_double[i]; - } - } - - /* - * Compute the estimate of the reciprocal condition number. - */ - if( ae_fp_neq(ainvnm,(double)(0)) ) - { - *rc = 1/ainvnm; - *rc = *rc/anorm; - if( ae_fp_less(*rc,rcondthreshold(_state)) ) - { - *rc = (double)(0); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Condition number estimation - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - March 31, 1993 -*************************************************************************/ -static void rcond_cmatrixrcondtrinternal(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - ae_bool onenorm, - double anorm, - double* rc, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector ex; - ae_vector cwork2; - ae_vector cwork3; - ae_vector cwork4; - ae_vector isave; - ae_vector rsave; - ae_int_t kase; - ae_int_t kase1; - double ainvnm; - ae_int_t i; - ae_int_t j; - ae_int_t j1; - ae_int_t j2; - double s; - double maxgrowth; - - ae_frame_make(_state, &_frame_block); - memset(&ex, 0, sizeof(ex)); - memset(&cwork2, 0, sizeof(cwork2)); - memset(&cwork3, 0, sizeof(cwork3)); - memset(&cwork4, 0, sizeof(cwork4)); - memset(&isave, 0, sizeof(isave)); - memset(&rsave, 0, sizeof(rsave)); - *rc = 0; - ae_vector_init(&ex, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&cwork2, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&cwork3, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&cwork4, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&isave, 0, DT_INT, _state, ae_true); - ae_vector_init(&rsave, 0, DT_REAL, _state, ae_true); - - - /* - * RC=0 if something happens - */ - *rc = (double)(0); - - /* - * init - */ - if( n<=0 ) - { - ae_frame_leave(_state); - return; - } - if( n==0 ) - { - *rc = (double)(1); - ae_frame_leave(_state); - return; - } - ae_vector_set_length(&cwork2, n+1, _state); - - /* - * prepare parameters for triangular solver - */ - maxgrowth = 1/rcondthreshold(_state); - s = (double)(0); - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j1 = i+1; - j2 = n-1; - } - else - { - j1 = 0; - j2 = i-1; - } - for(j=j1; j<=j2; j++) - { - s = ae_maxreal(s, ae_c_abs(a->ptr.pp_complex[i][j], _state), _state); - } - if( isunit ) - { - s = ae_maxreal(s, (double)(1), _state); - } - else - { - s = ae_maxreal(s, ae_c_abs(a->ptr.pp_complex[i][i], _state), _state); - } - } - if( ae_fp_eq(s,(double)(0)) ) - { - s = (double)(1); - } - s = 1/s; - - /* - * Scale according to S - */ - anorm = anorm*s; - - /* - * Quick return if possible - */ - if( ae_fp_eq(anorm,(double)(0)) ) - { - ae_frame_leave(_state); - return; - } - - /* - * Estimate the norm of inv(A). - */ - ainvnm = (double)(0); - if( onenorm ) - { - kase1 = 1; - } - else - { - kase1 = 2; - } - kase = 0; - for(;;) - { - rcond_cmatrixestimatenorm(n, &cwork4, &ex, &ainvnm, &kase, &isave, &rsave, _state); - if( kase==0 ) - { - break; - } - - /* - * From 1-based to 0-based - */ - for(i=0; i<=n-1; i++) - { - ex.ptr.p_complex[i] = ex.ptr.p_complex[i+1]; - } - - /* - * multiply by inv(A) or inv(A') - */ - if( kase==kase1 ) - { - - /* - * multiply by inv(A) - */ - if( !cmatrixscaledtrsafesolve(a, s, n, &ex, isupper, 0, isunit, maxgrowth, _state) ) - { - ae_frame_leave(_state); - return; - } - } - else - { - - /* - * multiply by inv(A') - */ - if( !cmatrixscaledtrsafesolve(a, s, n, &ex, isupper, 2, isunit, maxgrowth, _state) ) - { - ae_frame_leave(_state); - return; - } - } - - /* - * from 0-based to 1-based - */ - for(i=n-1; i>=0; i--) - { - ex.ptr.p_complex[i+1] = ex.ptr.p_complex[i]; - } - } - - /* - * Compute the estimate of the reciprocal condition number. - */ - if( ae_fp_neq(ainvnm,(double)(0)) ) - { - *rc = 1/ainvnm; - *rc = *rc/anorm; - if( ae_fp_less(*rc,rcondthreshold(_state)) ) - { - *rc = (double)(0); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal subroutine for condition number estimation - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - February 29, 1992 -*************************************************************************/ -static void rcond_spdmatrixrcondcholeskyinternal(/* Real */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - ae_bool isnormprovided, - double anorm, - double* rc, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t kase; - double ainvnm; - ae_vector ex; - ae_vector ev; - ae_vector tmp; - ae_vector iwork; - double sa; - double v; - double maxgrowth; - - ae_frame_make(_state, &_frame_block); - memset(&ex, 0, sizeof(ex)); - memset(&ev, 0, sizeof(ev)); - memset(&tmp, 0, sizeof(tmp)); - memset(&iwork, 0, sizeof(iwork)); - *rc = 0; - ae_vector_init(&ex, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ev, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&iwork, 0, DT_INT, _state, ae_true); - - ae_assert(n>=1, "Assertion failed", _state); - ae_vector_set_length(&tmp, n, _state); - - /* - * RC=0 if something happens - */ - *rc = (double)(0); - - /* - * prepare parameters for triangular solver - */ - maxgrowth = 1/rcondthreshold(_state); - sa = (double)(0); - if( isupper ) - { - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - sa = ae_maxreal(sa, ae_c_abs(ae_complex_from_d(cha->ptr.pp_double[i][j]), _state), _state); - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i; j++) - { - sa = ae_maxreal(sa, ae_c_abs(ae_complex_from_d(cha->ptr.pp_double[i][j]), _state), _state); - } - } - } - if( ae_fp_eq(sa,(double)(0)) ) - { - sa = (double)(1); - } - sa = 1/sa; - - /* - * Estimate the norm of A. - */ - if( !isnormprovided ) - { - kase = 0; - anorm = (double)(0); - for(;;) - { - rcond_rmatrixestimatenorm(n, &ev, &ex, &iwork, &anorm, &kase, _state); - if( kase==0 ) - { - break; - } - if( isupper ) - { - - /* - * Multiply by U - */ - for(i=1; i<=n; i++) - { - v = ae_v_dotproduct(&cha->ptr.pp_double[i-1][i-1], 1, &ex.ptr.p_double[i], 1, ae_v_len(i-1,n-1)); - ex.ptr.p_double[i] = v; - } - ae_v_muld(&ex.ptr.p_double[1], 1, ae_v_len(1,n), sa); - - /* - * Multiply by U' - */ - for(i=0; i<=n-1; i++) - { - tmp.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - v = ex.ptr.p_double[i+1]; - ae_v_addd(&tmp.ptr.p_double[i], 1, &cha->ptr.pp_double[i][i], 1, ae_v_len(i,n-1), v); - } - ae_v_move(&ex.ptr.p_double[1], 1, &tmp.ptr.p_double[0], 1, ae_v_len(1,n)); - ae_v_muld(&ex.ptr.p_double[1], 1, ae_v_len(1,n), sa); - } - else - { - - /* - * Multiply by L' - */ - for(i=0; i<=n-1; i++) - { - tmp.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - v = ex.ptr.p_double[i+1]; - ae_v_addd(&tmp.ptr.p_double[0], 1, &cha->ptr.pp_double[i][0], 1, ae_v_len(0,i), v); - } - ae_v_move(&ex.ptr.p_double[1], 1, &tmp.ptr.p_double[0], 1, ae_v_len(1,n)); - ae_v_muld(&ex.ptr.p_double[1], 1, ae_v_len(1,n), sa); - - /* - * Multiply by L - */ - for(i=n; i>=1; i--) - { - v = ae_v_dotproduct(&cha->ptr.pp_double[i-1][0], 1, &ex.ptr.p_double[1], 1, ae_v_len(0,i-1)); - ex.ptr.p_double[i] = v; - } - ae_v_muld(&ex.ptr.p_double[1], 1, ae_v_len(1,n), sa); - } - } - } - - /* - * Quick return if possible - */ - if( ae_fp_eq(anorm,(double)(0)) ) - { - ae_frame_leave(_state); - return; - } - if( n==1 ) - { - *rc = (double)(1); - ae_frame_leave(_state); - return; - } - - /* - * Estimate the 1-norm of inv(A). - */ - kase = 0; - for(;;) - { - rcond_rmatrixestimatenorm(n, &ev, &ex, &iwork, &ainvnm, &kase, _state); - if( kase==0 ) - { - break; - } - for(i=0; i<=n-1; i++) - { - ex.ptr.p_double[i] = ex.ptr.p_double[i+1]; - } - if( isupper ) - { - - /* - * Multiply by inv(U'). - */ - if( !rmatrixscaledtrsafesolve(cha, sa, n, &ex, isupper, 1, ae_false, maxgrowth, _state) ) - { - ae_frame_leave(_state); - return; - } - - /* - * Multiply by inv(U). - */ - if( !rmatrixscaledtrsafesolve(cha, sa, n, &ex, isupper, 0, ae_false, maxgrowth, _state) ) - { - ae_frame_leave(_state); - return; - } - } - else - { - - /* - * Multiply by inv(L). - */ - if( !rmatrixscaledtrsafesolve(cha, sa, n, &ex, isupper, 0, ae_false, maxgrowth, _state) ) - { - ae_frame_leave(_state); - return; - } - - /* - * Multiply by inv(L'). - */ - if( !rmatrixscaledtrsafesolve(cha, sa, n, &ex, isupper, 1, ae_false, maxgrowth, _state) ) - { - ae_frame_leave(_state); - return; - } - } - for(i=n-1; i>=0; i--) - { - ex.ptr.p_double[i+1] = ex.ptr.p_double[i]; - } - } - - /* - * Compute the estimate of the reciprocal condition number. - */ - if( ae_fp_neq(ainvnm,(double)(0)) ) - { - v = 1/ainvnm; - *rc = v/anorm; - if( ae_fp_less(*rc,rcondthreshold(_state)) ) - { - *rc = (double)(0); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal subroutine for condition number estimation - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - February 29, 1992 -*************************************************************************/ -static void rcond_hpdmatrixrcondcholeskyinternal(/* Complex */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - ae_bool isnormprovided, - double anorm, - double* rc, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector isave; - ae_vector rsave; - ae_vector ex; - ae_vector ev; - ae_vector tmp; - ae_int_t kase; - double ainvnm; - ae_complex v; - ae_int_t i; - ae_int_t j; - double sa; - double maxgrowth; - - ae_frame_make(_state, &_frame_block); - memset(&isave, 0, sizeof(isave)); - memset(&rsave, 0, sizeof(rsave)); - memset(&ex, 0, sizeof(ex)); - memset(&ev, 0, sizeof(ev)); - memset(&tmp, 0, sizeof(tmp)); - *rc = 0; - ae_vector_init(&isave, 0, DT_INT, _state, ae_true); - ae_vector_init(&rsave, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ex, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&ev, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&tmp, 0, DT_COMPLEX, _state, ae_true); - - ae_assert(n>=1, "Assertion failed", _state); - ae_vector_set_length(&tmp, n, _state); - - /* - * RC=0 if something happens - */ - *rc = (double)(0); - - /* - * prepare parameters for triangular solver - */ - maxgrowth = 1/rcondthreshold(_state); - sa = (double)(0); - if( isupper ) - { - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - sa = ae_maxreal(sa, ae_c_abs(cha->ptr.pp_complex[i][j], _state), _state); - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i; j++) - { - sa = ae_maxreal(sa, ae_c_abs(cha->ptr.pp_complex[i][j], _state), _state); - } - } - } - if( ae_fp_eq(sa,(double)(0)) ) - { - sa = (double)(1); - } - sa = 1/sa; - - /* - * Estimate the norm of A - */ - if( !isnormprovided ) - { - anorm = (double)(0); - kase = 0; - for(;;) - { - rcond_cmatrixestimatenorm(n, &ev, &ex, &anorm, &kase, &isave, &rsave, _state); - if( kase==0 ) - { - break; - } - if( isupper ) - { - - /* - * Multiply by U - */ - for(i=1; i<=n; i++) - { - v = ae_v_cdotproduct(&cha->ptr.pp_complex[i-1][i-1], 1, "N", &ex.ptr.p_complex[i], 1, "N", ae_v_len(i-1,n-1)); - ex.ptr.p_complex[i] = v; - } - ae_v_cmuld(&ex.ptr.p_complex[1], 1, ae_v_len(1,n), sa); - - /* - * Multiply by U' - */ - for(i=0; i<=n-1; i++) - { - tmp.ptr.p_complex[i] = ae_complex_from_i(0); - } - for(i=0; i<=n-1; i++) - { - v = ex.ptr.p_complex[i+1]; - ae_v_caddc(&tmp.ptr.p_complex[i], 1, &cha->ptr.pp_complex[i][i], 1, "Conj", ae_v_len(i,n-1), v); - } - ae_v_cmove(&ex.ptr.p_complex[1], 1, &tmp.ptr.p_complex[0], 1, "N", ae_v_len(1,n)); - ae_v_cmuld(&ex.ptr.p_complex[1], 1, ae_v_len(1,n), sa); - } - else - { - - /* - * Multiply by L' - */ - for(i=0; i<=n-1; i++) - { - tmp.ptr.p_complex[i] = ae_complex_from_i(0); - } - for(i=0; i<=n-1; i++) - { - v = ex.ptr.p_complex[i+1]; - ae_v_caddc(&tmp.ptr.p_complex[0], 1, &cha->ptr.pp_complex[i][0], 1, "Conj", ae_v_len(0,i), v); - } - ae_v_cmove(&ex.ptr.p_complex[1], 1, &tmp.ptr.p_complex[0], 1, "N", ae_v_len(1,n)); - ae_v_cmuld(&ex.ptr.p_complex[1], 1, ae_v_len(1,n), sa); - - /* - * Multiply by L - */ - for(i=n; i>=1; i--) - { - v = ae_v_cdotproduct(&cha->ptr.pp_complex[i-1][0], 1, "N", &ex.ptr.p_complex[1], 1, "N", ae_v_len(0,i-1)); - ex.ptr.p_complex[i] = v; - } - ae_v_cmuld(&ex.ptr.p_complex[1], 1, ae_v_len(1,n), sa); - } - } - } - - /* - * Quick return if possible - * After this block we assume that ANORM<>0 - */ - if( ae_fp_eq(anorm,(double)(0)) ) - { - ae_frame_leave(_state); - return; - } - if( n==1 ) - { - *rc = (double)(1); - ae_frame_leave(_state); - return; - } - - /* - * Estimate the norm of inv(A). - */ - ainvnm = (double)(0); - kase = 0; - for(;;) - { - rcond_cmatrixestimatenorm(n, &ev, &ex, &ainvnm, &kase, &isave, &rsave, _state); - if( kase==0 ) - { - break; - } - for(i=0; i<=n-1; i++) - { - ex.ptr.p_complex[i] = ex.ptr.p_complex[i+1]; - } - if( isupper ) - { - - /* - * Multiply by inv(U'). - */ - if( !cmatrixscaledtrsafesolve(cha, sa, n, &ex, isupper, 2, ae_false, maxgrowth, _state) ) - { - ae_frame_leave(_state); - return; - } - - /* - * Multiply by inv(U). - */ - if( !cmatrixscaledtrsafesolve(cha, sa, n, &ex, isupper, 0, ae_false, maxgrowth, _state) ) - { - ae_frame_leave(_state); - return; - } - } - else - { - - /* - * Multiply by inv(L). - */ - if( !cmatrixscaledtrsafesolve(cha, sa, n, &ex, isupper, 0, ae_false, maxgrowth, _state) ) - { - ae_frame_leave(_state); - return; - } - - /* - * Multiply by inv(L'). - */ - if( !cmatrixscaledtrsafesolve(cha, sa, n, &ex, isupper, 2, ae_false, maxgrowth, _state) ) - { - ae_frame_leave(_state); - return; - } - } - for(i=n-1; i>=0; i--) - { - ex.ptr.p_complex[i+1] = ex.ptr.p_complex[i]; - } - } - - /* - * Compute the estimate of the reciprocal condition number. - */ - if( ae_fp_neq(ainvnm,(double)(0)) ) - { - *rc = 1/ainvnm; - *rc = *rc/anorm; - if( ae_fp_less(*rc,rcondthreshold(_state)) ) - { - *rc = (double)(0); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal subroutine for condition number estimation - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - February 29, 1992 -*************************************************************************/ -static void rcond_rmatrixrcondluinternal(/* Real */ ae_matrix* lua, - ae_int_t n, - ae_bool onenorm, - ae_bool isanormprovided, - double anorm, - double* rc, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector ex; - ae_vector ev; - ae_vector iwork; - ae_vector tmp; - double v; - ae_int_t i; - ae_int_t j; - ae_int_t kase; - ae_int_t kase1; - double ainvnm; - double maxgrowth; - double su; - double sl; - ae_bool mupper; - ae_bool munit; - - ae_frame_make(_state, &_frame_block); - memset(&ex, 0, sizeof(ex)); - memset(&ev, 0, sizeof(ev)); - memset(&iwork, 0, sizeof(iwork)); - memset(&tmp, 0, sizeof(tmp)); - *rc = 0; - ae_vector_init(&ex, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ev, 0, DT_REAL, _state, ae_true); - ae_vector_init(&iwork, 0, DT_INT, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - - - /* - * RC=0 if something happens - */ - *rc = (double)(0); - - /* - * init - */ - if( onenorm ) - { - kase1 = 1; - } - else - { - kase1 = 2; - } - mupper = ae_true; - munit = ae_true; - ae_vector_set_length(&iwork, n+1, _state); - ae_vector_set_length(&tmp, n, _state); - - /* - * prepare parameters for triangular solver - */ - maxgrowth = 1/rcondthreshold(_state); - su = (double)(0); - sl = (double)(1); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i-1; j++) - { - sl = ae_maxreal(sl, ae_fabs(lua->ptr.pp_double[i][j], _state), _state); - } - for(j=i; j<=n-1; j++) - { - su = ae_maxreal(su, ae_fabs(lua->ptr.pp_double[i][j], _state), _state); - } - } - if( ae_fp_eq(su,(double)(0)) ) - { - su = (double)(1); - } - su = 1/su; - sl = 1/sl; - - /* - * Estimate the norm of A. - */ - if( !isanormprovided ) - { - kase = 0; - anorm = (double)(0); - for(;;) - { - rcond_rmatrixestimatenorm(n, &ev, &ex, &iwork, &anorm, &kase, _state); - if( kase==0 ) - { - break; - } - if( kase==kase1 ) - { - - /* - * Multiply by U - */ - for(i=1; i<=n; i++) - { - v = ae_v_dotproduct(&lua->ptr.pp_double[i-1][i-1], 1, &ex.ptr.p_double[i], 1, ae_v_len(i-1,n-1)); - ex.ptr.p_double[i] = v; - } - - /* - * Multiply by L - */ - for(i=n; i>=1; i--) - { - if( i>1 ) - { - v = ae_v_dotproduct(&lua->ptr.pp_double[i-1][0], 1, &ex.ptr.p_double[1], 1, ae_v_len(0,i-2)); - } - else - { - v = (double)(0); - } - ex.ptr.p_double[i] = ex.ptr.p_double[i]+v; - } - } - else - { - - /* - * Multiply by L' - */ - for(i=0; i<=n-1; i++) - { - tmp.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - v = ex.ptr.p_double[i+1]; - if( i>=1 ) - { - ae_v_addd(&tmp.ptr.p_double[0], 1, &lua->ptr.pp_double[i][0], 1, ae_v_len(0,i-1), v); - } - tmp.ptr.p_double[i] = tmp.ptr.p_double[i]+v; - } - ae_v_move(&ex.ptr.p_double[1], 1, &tmp.ptr.p_double[0], 1, ae_v_len(1,n)); - - /* - * Multiply by U' - */ - for(i=0; i<=n-1; i++) - { - tmp.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - v = ex.ptr.p_double[i+1]; - ae_v_addd(&tmp.ptr.p_double[i], 1, &lua->ptr.pp_double[i][i], 1, ae_v_len(i,n-1), v); - } - ae_v_move(&ex.ptr.p_double[1], 1, &tmp.ptr.p_double[0], 1, ae_v_len(1,n)); - } - } - } - - /* - * Scale according to SU/SL - */ - anorm = anorm*su*sl; - - /* - * Quick return if possible - * We assume that ANORM<>0 after this block - */ - if( ae_fp_eq(anorm,(double)(0)) ) - { - ae_frame_leave(_state); - return; - } - if( n==1 ) - { - *rc = (double)(1); - ae_frame_leave(_state); - return; - } - - /* - * Estimate the norm of inv(A). - */ - ainvnm = (double)(0); - kase = 0; - for(;;) - { - rcond_rmatrixestimatenorm(n, &ev, &ex, &iwork, &ainvnm, &kase, _state); - if( kase==0 ) - { - break; - } - - /* - * from 1-based array to 0-based - */ - for(i=0; i<=n-1; i++) - { - ex.ptr.p_double[i] = ex.ptr.p_double[i+1]; - } - - /* - * multiply by inv(A) or inv(A') - */ - if( kase==kase1 ) - { - - /* - * Multiply by inv(L). - */ - if( !rmatrixscaledtrsafesolve(lua, sl, n, &ex, !mupper, 0, munit, maxgrowth, _state) ) - { - ae_frame_leave(_state); - return; - } - - /* - * Multiply by inv(U). - */ - if( !rmatrixscaledtrsafesolve(lua, su, n, &ex, mupper, 0, !munit, maxgrowth, _state) ) - { - ae_frame_leave(_state); - return; - } - } - else - { - - /* - * Multiply by inv(U'). - */ - if( !rmatrixscaledtrsafesolve(lua, su, n, &ex, mupper, 1, !munit, maxgrowth, _state) ) - { - ae_frame_leave(_state); - return; - } - - /* - * Multiply by inv(L'). - */ - if( !rmatrixscaledtrsafesolve(lua, sl, n, &ex, !mupper, 1, munit, maxgrowth, _state) ) - { - ae_frame_leave(_state); - return; - } - } - - /* - * from 0-based array to 1-based - */ - for(i=n-1; i>=0; i--) - { - ex.ptr.p_double[i+1] = ex.ptr.p_double[i]; - } - } - - /* - * Compute the estimate of the reciprocal condition number. - */ - if( ae_fp_neq(ainvnm,(double)(0)) ) - { - *rc = 1/ainvnm; - *rc = *rc/anorm; - if( ae_fp_less(*rc,rcondthreshold(_state)) ) - { - *rc = (double)(0); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Condition number estimation - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - March 31, 1993 -*************************************************************************/ -static void rcond_cmatrixrcondluinternal(/* Complex */ ae_matrix* lua, - ae_int_t n, - ae_bool onenorm, - ae_bool isanormprovided, - double anorm, - double* rc, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector ex; - ae_vector cwork2; - ae_vector cwork3; - ae_vector cwork4; - ae_vector isave; - ae_vector rsave; - ae_int_t kase; - ae_int_t kase1; - double ainvnm; - ae_complex v; - ae_int_t i; - ae_int_t j; - double su; - double sl; - double maxgrowth; - - ae_frame_make(_state, &_frame_block); - memset(&ex, 0, sizeof(ex)); - memset(&cwork2, 0, sizeof(cwork2)); - memset(&cwork3, 0, sizeof(cwork3)); - memset(&cwork4, 0, sizeof(cwork4)); - memset(&isave, 0, sizeof(isave)); - memset(&rsave, 0, sizeof(rsave)); - *rc = 0; - ae_vector_init(&ex, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&cwork2, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&cwork3, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&cwork4, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&isave, 0, DT_INT, _state, ae_true); - ae_vector_init(&rsave, 0, DT_REAL, _state, ae_true); - - if( n<=0 ) - { - ae_frame_leave(_state); - return; - } - ae_vector_set_length(&cwork2, n+1, _state); - *rc = (double)(0); - if( n==0 ) - { - *rc = (double)(1); - ae_frame_leave(_state); - return; - } - - /* - * prepare parameters for triangular solver - */ - maxgrowth = 1/rcondthreshold(_state); - su = (double)(0); - sl = (double)(1); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i-1; j++) - { - sl = ae_maxreal(sl, ae_c_abs(lua->ptr.pp_complex[i][j], _state), _state); - } - for(j=i; j<=n-1; j++) - { - su = ae_maxreal(su, ae_c_abs(lua->ptr.pp_complex[i][j], _state), _state); - } - } - if( ae_fp_eq(su,(double)(0)) ) - { - su = (double)(1); - } - su = 1/su; - sl = 1/sl; - - /* - * Estimate the norm of SU*SL*A. - */ - if( !isanormprovided ) - { - anorm = (double)(0); - if( onenorm ) - { - kase1 = 1; - } - else - { - kase1 = 2; - } - kase = 0; - do - { - rcond_cmatrixestimatenorm(n, &cwork4, &ex, &anorm, &kase, &isave, &rsave, _state); - if( kase!=0 ) - { - if( kase==kase1 ) - { - - /* - * Multiply by U - */ - for(i=1; i<=n; i++) - { - v = ae_v_cdotproduct(&lua->ptr.pp_complex[i-1][i-1], 1, "N", &ex.ptr.p_complex[i], 1, "N", ae_v_len(i-1,n-1)); - ex.ptr.p_complex[i] = v; - } - - /* - * Multiply by L - */ - for(i=n; i>=1; i--) - { - v = ae_complex_from_i(0); - if( i>1 ) - { - v = ae_v_cdotproduct(&lua->ptr.pp_complex[i-1][0], 1, "N", &ex.ptr.p_complex[1], 1, "N", ae_v_len(0,i-2)); - } - ex.ptr.p_complex[i] = ae_c_add(v,ex.ptr.p_complex[i]); - } - } - else - { - - /* - * Multiply by L' - */ - for(i=1; i<=n; i++) - { - cwork2.ptr.p_complex[i] = ae_complex_from_i(0); - } - for(i=1; i<=n; i++) - { - v = ex.ptr.p_complex[i]; - if( i>1 ) - { - ae_v_caddc(&cwork2.ptr.p_complex[1], 1, &lua->ptr.pp_complex[i-1][0], 1, "Conj", ae_v_len(1,i-1), v); - } - cwork2.ptr.p_complex[i] = ae_c_add(cwork2.ptr.p_complex[i],v); - } - - /* - * Multiply by U' - */ - for(i=1; i<=n; i++) - { - ex.ptr.p_complex[i] = ae_complex_from_i(0); - } - for(i=1; i<=n; i++) - { - v = cwork2.ptr.p_complex[i]; - ae_v_caddc(&ex.ptr.p_complex[i], 1, &lua->ptr.pp_complex[i-1][i-1], 1, "Conj", ae_v_len(i,n), v); - } - } - } - } - while(kase!=0); - } - - /* - * Scale according to SU/SL - */ - anorm = anorm*su*sl; - - /* - * Quick return if possible - */ - if( ae_fp_eq(anorm,(double)(0)) ) - { - ae_frame_leave(_state); - return; - } - - /* - * Estimate the norm of inv(A). - */ - ainvnm = (double)(0); - if( onenorm ) - { - kase1 = 1; - } - else - { - kase1 = 2; - } - kase = 0; - for(;;) - { - rcond_cmatrixestimatenorm(n, &cwork4, &ex, &ainvnm, &kase, &isave, &rsave, _state); - if( kase==0 ) - { - break; - } - - /* - * From 1-based to 0-based - */ - for(i=0; i<=n-1; i++) - { - ex.ptr.p_complex[i] = ex.ptr.p_complex[i+1]; - } - - /* - * multiply by inv(A) or inv(A') - */ - if( kase==kase1 ) - { - - /* - * Multiply by inv(L). - */ - if( !cmatrixscaledtrsafesolve(lua, sl, n, &ex, ae_false, 0, ae_true, maxgrowth, _state) ) - { - *rc = (double)(0); - ae_frame_leave(_state); - return; - } - - /* - * Multiply by inv(U). - */ - if( !cmatrixscaledtrsafesolve(lua, su, n, &ex, ae_true, 0, ae_false, maxgrowth, _state) ) - { - *rc = (double)(0); - ae_frame_leave(_state); - return; - } - } - else - { - - /* - * Multiply by inv(U'). - */ - if( !cmatrixscaledtrsafesolve(lua, su, n, &ex, ae_true, 2, ae_false, maxgrowth, _state) ) - { - *rc = (double)(0); - ae_frame_leave(_state); - return; - } - - /* - * Multiply by inv(L'). - */ - if( !cmatrixscaledtrsafesolve(lua, sl, n, &ex, ae_false, 2, ae_true, maxgrowth, _state) ) - { - *rc = (double)(0); - ae_frame_leave(_state); - return; - } - } - - /* - * from 0-based to 1-based - */ - for(i=n-1; i>=0; i--) - { - ex.ptr.p_complex[i+1] = ex.ptr.p_complex[i]; - } - } - - /* - * Compute the estimate of the reciprocal condition number. - */ - if( ae_fp_neq(ainvnm,(double)(0)) ) - { - *rc = 1/ainvnm; - *rc = *rc/anorm; - if( ae_fp_less(*rc,rcondthreshold(_state)) ) - { - *rc = (double)(0); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal subroutine for matrix norm estimation - - -- LAPACK auxiliary routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - February 29, 1992 -*************************************************************************/ -static void rcond_rmatrixestimatenorm(ae_int_t n, - /* Real */ ae_vector* v, - /* Real */ ae_vector* x, - /* Integer */ ae_vector* isgn, - double* est, - ae_int_t* kase, - ae_state *_state) -{ - ae_int_t itmax; - ae_int_t i; - double t; - ae_bool flg; - ae_int_t positer; - ae_int_t posj; - ae_int_t posjlast; - ae_int_t posjump; - ae_int_t posaltsgn; - ae_int_t posestold; - ae_int_t postemp; - - - itmax = 5; - posaltsgn = n+1; - posestold = n+2; - postemp = n+3; - positer = n+1; - posj = n+2; - posjlast = n+3; - posjump = n+4; - if( *kase==0 ) - { - ae_vector_set_length(v, n+4, _state); - ae_vector_set_length(x, n+1, _state); - ae_vector_set_length(isgn, n+5, _state); - t = (double)1/(double)n; - for(i=1; i<=n; i++) - { - x->ptr.p_double[i] = t; - } - *kase = 1; - isgn->ptr.p_int[posjump] = 1; - return; - } - - /* - * ................ ENTRY (JUMP = 1) - * FIRST ITERATION. X HAS BEEN OVERWRITTEN BY A*X. - */ - if( isgn->ptr.p_int[posjump]==1 ) - { - if( n==1 ) - { - v->ptr.p_double[1] = x->ptr.p_double[1]; - *est = ae_fabs(v->ptr.p_double[1], _state); - *kase = 0; - return; - } - *est = (double)(0); - for(i=1; i<=n; i++) - { - *est = *est+ae_fabs(x->ptr.p_double[i], _state); - } - for(i=1; i<=n; i++) - { - if( ae_fp_greater_eq(x->ptr.p_double[i],(double)(0)) ) - { - x->ptr.p_double[i] = (double)(1); - } - else - { - x->ptr.p_double[i] = (double)(-1); - } - isgn->ptr.p_int[i] = ae_sign(x->ptr.p_double[i], _state); - } - *kase = 2; - isgn->ptr.p_int[posjump] = 2; - return; - } - - /* - * ................ ENTRY (JUMP = 2) - * FIRST ITERATION. X HAS BEEN OVERWRITTEN BY TRANDPOSE(A)*X. - */ - if( isgn->ptr.p_int[posjump]==2 ) - { - isgn->ptr.p_int[posj] = 1; - for(i=2; i<=n; i++) - { - if( ae_fp_greater(ae_fabs(x->ptr.p_double[i], _state),ae_fabs(x->ptr.p_double[isgn->ptr.p_int[posj]], _state)) ) - { - isgn->ptr.p_int[posj] = i; - } - } - isgn->ptr.p_int[positer] = 2; - - /* - * MAIN LOOP - ITERATIONS 2,3,...,ITMAX. - */ - for(i=1; i<=n; i++) - { - x->ptr.p_double[i] = (double)(0); - } - x->ptr.p_double[isgn->ptr.p_int[posj]] = (double)(1); - *kase = 1; - isgn->ptr.p_int[posjump] = 3; - return; - } - - /* - * ................ ENTRY (JUMP = 3) - * X HAS BEEN OVERWRITTEN BY A*X. - */ - if( isgn->ptr.p_int[posjump]==3 ) - { - ae_v_move(&v->ptr.p_double[1], 1, &x->ptr.p_double[1], 1, ae_v_len(1,n)); - v->ptr.p_double[posestold] = *est; - *est = (double)(0); - for(i=1; i<=n; i++) - { - *est = *est+ae_fabs(v->ptr.p_double[i], _state); - } - flg = ae_false; - for(i=1; i<=n; i++) - { - if( (ae_fp_greater_eq(x->ptr.p_double[i],(double)(0))&&isgn->ptr.p_int[i]<0)||(ae_fp_less(x->ptr.p_double[i],(double)(0))&&isgn->ptr.p_int[i]>=0) ) - { - flg = ae_true; - } - } - - /* - * REPEATED SIGN VECTOR DETECTED, HENCE ALGORITHM HAS CONVERGED. - * OR MAY BE CYCLING. - */ - if( !flg||ae_fp_less_eq(*est,v->ptr.p_double[posestold]) ) - { - v->ptr.p_double[posaltsgn] = (double)(1); - for(i=1; i<=n; i++) - { - x->ptr.p_double[i] = v->ptr.p_double[posaltsgn]*(1+(double)(i-1)/(double)(n-1)); - v->ptr.p_double[posaltsgn] = -v->ptr.p_double[posaltsgn]; - } - *kase = 1; - isgn->ptr.p_int[posjump] = 5; - return; - } - for(i=1; i<=n; i++) - { - if( ae_fp_greater_eq(x->ptr.p_double[i],(double)(0)) ) - { - x->ptr.p_double[i] = (double)(1); - isgn->ptr.p_int[i] = 1; - } - else - { - x->ptr.p_double[i] = (double)(-1); - isgn->ptr.p_int[i] = -1; - } - } - *kase = 2; - isgn->ptr.p_int[posjump] = 4; - return; - } - - /* - * ................ ENTRY (JUMP = 4) - * X HAS BEEN OVERWRITTEN BY TRANDPOSE(A)*X. - */ - if( isgn->ptr.p_int[posjump]==4 ) - { - isgn->ptr.p_int[posjlast] = isgn->ptr.p_int[posj]; - isgn->ptr.p_int[posj] = 1; - for(i=2; i<=n; i++) - { - if( ae_fp_greater(ae_fabs(x->ptr.p_double[i], _state),ae_fabs(x->ptr.p_double[isgn->ptr.p_int[posj]], _state)) ) - { - isgn->ptr.p_int[posj] = i; - } - } - if( ae_fp_neq(x->ptr.p_double[isgn->ptr.p_int[posjlast]],ae_fabs(x->ptr.p_double[isgn->ptr.p_int[posj]], _state))&&isgn->ptr.p_int[positer]ptr.p_int[positer] = isgn->ptr.p_int[positer]+1; - for(i=1; i<=n; i++) - { - x->ptr.p_double[i] = (double)(0); - } - x->ptr.p_double[isgn->ptr.p_int[posj]] = (double)(1); - *kase = 1; - isgn->ptr.p_int[posjump] = 3; - return; - } - - /* - * ITERATION COMPLETE. FINAL STAGE. - */ - v->ptr.p_double[posaltsgn] = (double)(1); - for(i=1; i<=n; i++) - { - x->ptr.p_double[i] = v->ptr.p_double[posaltsgn]*(1+(double)(i-1)/(double)(n-1)); - v->ptr.p_double[posaltsgn] = -v->ptr.p_double[posaltsgn]; - } - *kase = 1; - isgn->ptr.p_int[posjump] = 5; - return; - } - - /* - * ................ ENTRY (JUMP = 5) - * X HAS BEEN OVERWRITTEN BY A*X. - */ - if( isgn->ptr.p_int[posjump]==5 ) - { - v->ptr.p_double[postemp] = (double)(0); - for(i=1; i<=n; i++) - { - v->ptr.p_double[postemp] = v->ptr.p_double[postemp]+ae_fabs(x->ptr.p_double[i], _state); - } - v->ptr.p_double[postemp] = 2*v->ptr.p_double[postemp]/(3*n); - if( ae_fp_greater(v->ptr.p_double[postemp],*est) ) - { - ae_v_move(&v->ptr.p_double[1], 1, &x->ptr.p_double[1], 1, ae_v_len(1,n)); - *est = v->ptr.p_double[postemp]; - } - *kase = 0; - return; - } -} - - -static void rcond_cmatrixestimatenorm(ae_int_t n, - /* Complex */ ae_vector* v, - /* Complex */ ae_vector* x, - double* est, - ae_int_t* kase, - /* Integer */ ae_vector* isave, - /* Real */ ae_vector* rsave, - ae_state *_state) -{ - ae_int_t itmax; - ae_int_t i; - ae_int_t iter; - ae_int_t j; - ae_int_t jlast; - ae_int_t jump; - double absxi; - double altsgn; - double estold; - double safmin; - double temp; - - - - /* - *Executable Statements .. - */ - itmax = 5; - safmin = ae_minrealnumber; - if( *kase==0 ) - { - ae_vector_set_length(v, n+1, _state); - ae_vector_set_length(x, n+1, _state); - ae_vector_set_length(isave, 5, _state); - ae_vector_set_length(rsave, 4, _state); - for(i=1; i<=n; i++) - { - x->ptr.p_complex[i] = ae_complex_from_d((double)1/(double)n); - } - *kase = 1; - jump = 1; - rcond_internalcomplexrcondsaveall(isave, rsave, &i, &iter, &j, &jlast, &jump, &absxi, &altsgn, &estold, &temp, _state); - return; - } - rcond_internalcomplexrcondloadall(isave, rsave, &i, &iter, &j, &jlast, &jump, &absxi, &altsgn, &estold, &temp, _state); - - /* - * ENTRY (JUMP = 1) - * FIRST ITERATION. X HAS BEEN OVERWRITTEN BY A*X. - */ - if( jump==1 ) - { - if( n==1 ) - { - v->ptr.p_complex[1] = x->ptr.p_complex[1]; - *est = ae_c_abs(v->ptr.p_complex[1], _state); - *kase = 0; - rcond_internalcomplexrcondsaveall(isave, rsave, &i, &iter, &j, &jlast, &jump, &absxi, &altsgn, &estold, &temp, _state); - return; - } - *est = rcond_internalcomplexrcondscsum1(x, n, _state); - for(i=1; i<=n; i++) - { - absxi = ae_c_abs(x->ptr.p_complex[i], _state); - if( ae_fp_greater(absxi,safmin) ) - { - x->ptr.p_complex[i] = ae_c_div_d(x->ptr.p_complex[i],absxi); - } - else - { - x->ptr.p_complex[i] = ae_complex_from_i(1); - } - } - *kase = 2; - jump = 2; - rcond_internalcomplexrcondsaveall(isave, rsave, &i, &iter, &j, &jlast, &jump, &absxi, &altsgn, &estold, &temp, _state); - return; - } - - /* - * ENTRY (JUMP = 2) - * FIRST ITERATION. X HAS BEEN OVERWRITTEN BY CTRANS(A)*X. - */ - if( jump==2 ) - { - j = rcond_internalcomplexrcondicmax1(x, n, _state); - iter = 2; - - /* - * MAIN LOOP - ITERATIONS 2,3,...,ITMAX. - */ - for(i=1; i<=n; i++) - { - x->ptr.p_complex[i] = ae_complex_from_i(0); - } - x->ptr.p_complex[j] = ae_complex_from_i(1); - *kase = 1; - jump = 3; - rcond_internalcomplexrcondsaveall(isave, rsave, &i, &iter, &j, &jlast, &jump, &absxi, &altsgn, &estold, &temp, _state); - return; - } - - /* - * ENTRY (JUMP = 3) - * X HAS BEEN OVERWRITTEN BY A*X. - */ - if( jump==3 ) - { - ae_v_cmove(&v->ptr.p_complex[1], 1, &x->ptr.p_complex[1], 1, "N", ae_v_len(1,n)); - estold = *est; - *est = rcond_internalcomplexrcondscsum1(v, n, _state); - - /* - * TEST FOR CYCLING. - */ - if( ae_fp_less_eq(*est,estold) ) - { - - /* - * ITERATION COMPLETE. FINAL STAGE. - */ - altsgn = (double)(1); - for(i=1; i<=n; i++) - { - x->ptr.p_complex[i] = ae_complex_from_d(altsgn*(1+(double)(i-1)/(double)(n-1))); - altsgn = -altsgn; - } - *kase = 1; - jump = 5; - rcond_internalcomplexrcondsaveall(isave, rsave, &i, &iter, &j, &jlast, &jump, &absxi, &altsgn, &estold, &temp, _state); - return; - } - for(i=1; i<=n; i++) - { - absxi = ae_c_abs(x->ptr.p_complex[i], _state); - if( ae_fp_greater(absxi,safmin) ) - { - x->ptr.p_complex[i] = ae_c_div_d(x->ptr.p_complex[i],absxi); - } - else - { - x->ptr.p_complex[i] = ae_complex_from_i(1); - } - } - *kase = 2; - jump = 4; - rcond_internalcomplexrcondsaveall(isave, rsave, &i, &iter, &j, &jlast, &jump, &absxi, &altsgn, &estold, &temp, _state); - return; - } - - /* - * ENTRY (JUMP = 4) - * X HAS BEEN OVERWRITTEN BY CTRANS(A)*X. - */ - if( jump==4 ) - { - jlast = j; - j = rcond_internalcomplexrcondicmax1(x, n, _state); - if( ae_fp_neq(ae_c_abs(x->ptr.p_complex[jlast], _state),ae_c_abs(x->ptr.p_complex[j], _state))&&iterptr.p_complex[i] = ae_complex_from_i(0); - } - x->ptr.p_complex[j] = ae_complex_from_i(1); - *kase = 1; - jump = 3; - rcond_internalcomplexrcondsaveall(isave, rsave, &i, &iter, &j, &jlast, &jump, &absxi, &altsgn, &estold, &temp, _state); - return; - } - - /* - * ITERATION COMPLETE. FINAL STAGE. - */ - altsgn = (double)(1); - for(i=1; i<=n; i++) - { - x->ptr.p_complex[i] = ae_complex_from_d(altsgn*(1+(double)(i-1)/(double)(n-1))); - altsgn = -altsgn; - } - *kase = 1; - jump = 5; - rcond_internalcomplexrcondsaveall(isave, rsave, &i, &iter, &j, &jlast, &jump, &absxi, &altsgn, &estold, &temp, _state); - return; - } - - /* - * ENTRY (JUMP = 5) - * X HAS BEEN OVERWRITTEN BY A*X. - */ - if( jump==5 ) - { - temp = 2*(rcond_internalcomplexrcondscsum1(x, n, _state)/(3*n)); - if( ae_fp_greater(temp,*est) ) - { - ae_v_cmove(&v->ptr.p_complex[1], 1, &x->ptr.p_complex[1], 1, "N", ae_v_len(1,n)); - *est = temp; - } - *kase = 0; - rcond_internalcomplexrcondsaveall(isave, rsave, &i, &iter, &j, &jlast, &jump, &absxi, &altsgn, &estold, &temp, _state); - return; - } -} - - -static double rcond_internalcomplexrcondscsum1(/* Complex */ ae_vector* x, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - double result; - - - result = (double)(0); - for(i=1; i<=n; i++) - { - result = result+ae_c_abs(x->ptr.p_complex[i], _state); - } - return result; -} - - -static ae_int_t rcond_internalcomplexrcondicmax1(/* Complex */ ae_vector* x, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - double m; - ae_int_t result; - - - result = 1; - m = ae_c_abs(x->ptr.p_complex[1], _state); - for(i=2; i<=n; i++) - { - if( ae_fp_greater(ae_c_abs(x->ptr.p_complex[i], _state),m) ) - { - result = i; - m = ae_c_abs(x->ptr.p_complex[i], _state); - } - } - return result; -} - - -static void rcond_internalcomplexrcondsaveall(/* Integer */ ae_vector* isave, - /* Real */ ae_vector* rsave, - ae_int_t* i, - ae_int_t* iter, - ae_int_t* j, - ae_int_t* jlast, - ae_int_t* jump, - double* absxi, - double* altsgn, - double* estold, - double* temp, - ae_state *_state) -{ - - - isave->ptr.p_int[0] = *i; - isave->ptr.p_int[1] = *iter; - isave->ptr.p_int[2] = *j; - isave->ptr.p_int[3] = *jlast; - isave->ptr.p_int[4] = *jump; - rsave->ptr.p_double[0] = *absxi; - rsave->ptr.p_double[1] = *altsgn; - rsave->ptr.p_double[2] = *estold; - rsave->ptr.p_double[3] = *temp; -} - - -static void rcond_internalcomplexrcondloadall(/* Integer */ ae_vector* isave, - /* Real */ ae_vector* rsave, - ae_int_t* i, - ae_int_t* iter, - ae_int_t* j, - ae_int_t* jlast, - ae_int_t* jump, - double* absxi, - double* altsgn, - double* estold, - double* temp, - ae_state *_state) -{ - - - *i = isave->ptr.p_int[0]; - *iter = isave->ptr.p_int[1]; - *j = isave->ptr.p_int[2]; - *jlast = isave->ptr.p_int[3]; - *jump = isave->ptr.p_int[4]; - *absxi = rsave->ptr.p_double[0]; - *altsgn = rsave->ptr.p_double[1]; - *estold = rsave->ptr.p_double[2]; - *temp = rsave->ptr.p_double[3]; -} - - -#endif -#if defined(AE_COMPILE_MATINV) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Inversion of a matrix given by its LU decomposition. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - LU decomposition of the matrix - (output of RMatrixLU subroutine). - Pivots - table of permutations - (the output of RMatrixLU subroutine). - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - -OUTPUT PARAMETERS: - Info - return code: - * -3 A is singular, or VERY close to singular. - it is filled by zeros in such cases. - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - solver report, see below for more info - A - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - -SOLVER REPORT - -Subroutine sets following fields of the Rep structure: -* R1 reciprocal of condition number: 1/cond(A), 1-norm. -* RInf reciprocal of condition number: 1/cond(A), inf-norm. - - -- ALGLIB routine -- - 05.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixluinverse(/* Real */ ae_matrix* a, - /* Integer */ ae_vector* pivots, - ae_int_t n, - ae_int_t* info, - matinvreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector work; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - sinteger sinfo; - - ae_frame_make(_state, &_frame_block); - memset(&work, 0, sizeof(work)); - memset(&sinfo, 0, sizeof(sinfo)); - *info = 0; - _matinvreport_clear(rep); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - _sinteger_init(&sinfo, _state, ae_true); - - ae_assert(n>0, "RMatrixLUInverse: N<=0!", _state); - ae_assert(a->cols>=n, "RMatrixLUInverse: cols(A)rows>=n, "RMatrixLUInverse: rows(A)cnt>=n, "RMatrixLUInverse: len(Pivots)ptr.p_int[i]>n-1||pivots->ptr.p_int[i]0, "RMatrixLUInverse: incorrect Pivots array!", _state); - - /* - * calculate condition numbers - */ - rep->r1 = rmatrixlurcond1(a, n, _state); - rep->rinf = rmatrixlurcondinf(a, n, _state); - if( ae_fp_less(rep->r1,rcondthreshold(_state))||ae_fp_less(rep->rinf,rcondthreshold(_state)) ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a->ptr.pp_double[i][j] = (double)(0); - } - } - rep->r1 = (double)(0); - rep->rinf = (double)(0); - *info = -3; - ae_frame_leave(_state); - return; - } - - /* - * Call cache-oblivious code - */ - ae_vector_set_length(&work, n, _state); - sinfo.val = 1; - matinv_rmatrixluinverserec(a, 0, n, &work, &sinfo, rep, _state); - *info = sinfo.val; - - /* - * apply permutations - */ - for(i=0; i<=n-1; i++) - { - for(j=n-2; j>=0; j--) - { - k = pivots->ptr.p_int[j]; - v = a->ptr.pp_double[i][j]; - a->ptr.pp_double[i][j] = a->ptr.pp_double[i][k]; - a->ptr.pp_double[i][k] = v; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Inversion of a general matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - -Result: - True, if the matrix is not singular. - False, if the matrix is singular. - - -- ALGLIB -- - Copyright 2005-2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixinverse(/* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t* info, - matinvreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector pivots; - - ae_frame_make(_state, &_frame_block); - memset(&pivots, 0, sizeof(pivots)); - *info = 0; - _matinvreport_clear(rep); - ae_vector_init(&pivots, 0, DT_INT, _state, ae_true); - - ae_assert(n>0, "RMatrixInverse: N<=0!", _state); - ae_assert(a->cols>=n, "RMatrixInverse: cols(A)rows>=n, "RMatrixInverse: rows(A)0, "CMatrixLUInverse: N<=0!", _state); - ae_assert(a->cols>=n, "CMatrixLUInverse: cols(A)rows>=n, "CMatrixLUInverse: rows(A)cnt>=n, "CMatrixLUInverse: len(Pivots)ptr.p_int[i]>n-1||pivots->ptr.p_int[i]0, "CMatrixLUInverse: incorrect Pivots array!", _state); - - /* - * calculate condition numbers - */ - rep->r1 = cmatrixlurcond1(a, n, _state); - rep->rinf = cmatrixlurcondinf(a, n, _state); - if( ae_fp_less(rep->r1,rcondthreshold(_state))||ae_fp_less(rep->rinf,rcondthreshold(_state)) ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a->ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - rep->r1 = (double)(0); - rep->rinf = (double)(0); - *info = -3; - ae_frame_leave(_state); - return; - } - - /* - * Call cache-oblivious code - */ - ae_vector_set_length(&work, n, _state); - sinfo.val = 1; - matinv_cmatrixluinverserec(a, 0, n, &work, &sinfo, rep, _state); - *info = sinfo.val; - - /* - * apply permutations - */ - for(i=0; i<=n-1; i++) - { - for(j=n-2; j>=0; j--) - { - k = pivots->ptr.p_int[j]; - v = a->ptr.pp_complex[i][j]; - a->ptr.pp_complex[i][j] = a->ptr.pp_complex[i][k]; - a->ptr.pp_complex[i][k] = v; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Inversion of a general matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -void cmatrixinverse(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_int_t* info, - matinvreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector pivots; - - ae_frame_make(_state, &_frame_block); - memset(&pivots, 0, sizeof(pivots)); - *info = 0; - _matinvreport_clear(rep); - ae_vector_init(&pivots, 0, DT_INT, _state, ae_true); - - ae_assert(n>0, "CRMatrixInverse: N<=0!", _state); - ae_assert(a->cols>=n, "CRMatrixInverse: cols(A)rows>=n, "CRMatrixInverse: rows(A)0, "SPDMatrixCholeskyInverse: N<=0!", _state); - ae_assert(a->cols>=n, "SPDMatrixCholeskyInverse: cols(A)rows>=n, "SPDMatrixCholeskyInverse: rows(A)ptr.pp_double[i][i], _state); - } - ae_assert(f, "SPDMatrixCholeskyInverse: A contains infinite or NaN values!", _state); - - /* - * calculate condition numbers - */ - rep->r1 = spdmatrixcholeskyrcond(a, n, isupper, _state); - rep->rinf = rep->r1; - if( ae_fp_less(rep->r1,rcondthreshold(_state))||ae_fp_less(rep->rinf,rcondthreshold(_state)) ) - { - if( isupper ) - { - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - a->ptr.pp_double[i][j] = (double)(0); - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i; j++) - { - a->ptr.pp_double[i][j] = (double)(0); - } - } - } - rep->r1 = (double)(0); - rep->rinf = (double)(0); - *info = -3; - ae_frame_leave(_state); - return; - } - - /* - * Inverse - */ - ae_vector_set_length(&tmp, n, _state); - spdmatrixcholeskyinverserec(a, 0, n, isupper, &tmp, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Inversion of a symmetric positive definite matrix. - -Given an upper or lower triangle of a symmetric positive definite matrix, -the algorithm generates matrix A^-1 and saves the upper or lower triangle -depending on the input. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix to be inverted (upper or lower triangle). - Array with elements [0..N-1,0..N-1]. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - storage type (optional): - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, both lower and upper triangles must be - filled. - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 10.02.2010 - Bochkanov Sergey -*************************************************************************/ -void spdmatrixinverse(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_int_t* info, - matinvreport* rep, - ae_state *_state) -{ - - *info = 0; - _matinvreport_clear(rep); - - ae_assert(n>0, "SPDMatrixInverse: N<=0!", _state); - ae_assert(a->cols>=n, "SPDMatrixInverse: cols(A)rows>=n, "SPDMatrixInverse: rows(A)0, "HPDMatrixCholeskyInverse: N<=0!", _state); - ae_assert(a->cols>=n, "HPDMatrixCholeskyInverse: cols(A)rows>=n, "HPDMatrixCholeskyInverse: rows(A)ptr.pp_complex[i][i].x, _state))&&ae_isfinite(a->ptr.pp_complex[i][i].y, _state); - } - ae_assert(f, "HPDMatrixCholeskyInverse: A contains infinite or NaN values!", _state); - *info = 1; - - /* - * calculate condition numbers - */ - rep->r1 = hpdmatrixcholeskyrcond(a, n, isupper, _state); - rep->rinf = rep->r1; - if( ae_fp_less(rep->r1,rcondthreshold(_state))||ae_fp_less(rep->rinf,rcondthreshold(_state)) ) - { - if( isupper ) - { - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - a->ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i; j++) - { - a->ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - } - rep->r1 = (double)(0); - rep->rinf = (double)(0); - *info = -3; - ae_frame_leave(_state); - return; - } - - /* - * Inverse - */ - ae_vector_set_length(&tmp, n, _state); - matinv_hpdmatrixcholeskyinverserec(a, 0, n, isupper, &tmp, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Inversion of a Hermitian positive definite matrix. - -Given an upper or lower triangle of a Hermitian positive definite matrix, -the algorithm generates matrix A^-1 and saves the upper or lower triangle -depending on the input. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix to be inverted (upper or lower triangle). - Array with elements [0..N-1,0..N-1]. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - storage type (optional): - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, both lower and upper triangles must be - filled. - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 10.02.2010 - Bochkanov Sergey -*************************************************************************/ -void hpdmatrixinverse(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_int_t* info, - matinvreport* rep, - ae_state *_state) -{ - - *info = 0; - _matinvreport_clear(rep); - - ae_assert(n>0, "HPDMatrixInverse: N<=0!", _state); - ae_assert(a->cols>=n, "HPDMatrixInverse: cols(A)rows>=n, "HPDMatrixInverse: rows(A)0, "RMatrixTRInverse: N<=0!", _state); - ae_assert(a->cols>=n, "RMatrixTRInverse: cols(A)rows>=n, "RMatrixTRInverse: rows(A)r1 = rmatrixtrrcond1(a, n, isupper, isunit, _state); - rep->rinf = rmatrixtrrcondinf(a, n, isupper, isunit, _state); - if( ae_fp_less(rep->r1,rcondthreshold(_state))||ae_fp_less(rep->rinf,rcondthreshold(_state)) ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a->ptr.pp_double[i][j] = (double)(0); - } - } - rep->r1 = (double)(0); - rep->rinf = (double)(0); - *info = -3; - ae_frame_leave(_state); - return; - } - - /* - * Invert - */ - ae_vector_set_length(&tmp, n, _state); - sinfo.val = 1; - matinv_rmatrixtrinverserec(a, 0, n, isupper, isunit, &tmp, &sinfo, _state); - *info = sinfo.val; - ae_frame_leave(_state); -} - - -/************************************************************************* -Triangular matrix inverse (complex) - -The subroutine inverts the following types of matrices: - * upper triangular - * upper triangular with unit diagonal - * lower triangular - * lower triangular with unit diagonal - -In case of an upper (lower) triangular matrix, the inverse matrix will -also be upper (lower) triangular, and after the end of the algorithm, the -inverse matrix replaces the source matrix. The elements below (above) the -main diagonal are not changed by the algorithm. - -If the matrix has a unit diagonal, the inverse matrix also has a unit -diagonal, and the diagonal elements are not passed to the algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix, array[0..N-1, 0..N-1]. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - True, if the matrix is upper triangular. - IsUnit - diagonal type (optional): - * if True, matrix has unit diagonal (a[i,i] are NOT used) - * if False, matrix diagonal is arbitrary - * if not given, False is assumed - -Output parameters: - Info - same as for RMatrixLUInverse - Rep - same as for RMatrixLUInverse - A - same as for RMatrixLUInverse. - - -- ALGLIB -- - Copyright 05.02.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixtrinverse(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - ae_int_t* info, - matinvreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_vector tmp; - sinteger sinfo; - - ae_frame_make(_state, &_frame_block); - memset(&tmp, 0, sizeof(tmp)); - memset(&sinfo, 0, sizeof(sinfo)); - *info = 0; - _matinvreport_clear(rep); - ae_vector_init(&tmp, 0, DT_COMPLEX, _state, ae_true); - _sinteger_init(&sinfo, _state, ae_true); - - ae_assert(n>0, "CMatrixTRInverse: N<=0!", _state); - ae_assert(a->cols>=n, "CMatrixTRInverse: cols(A)rows>=n, "CMatrixTRInverse: rows(A)r1 = cmatrixtrrcond1(a, n, isupper, isunit, _state); - rep->rinf = cmatrixtrrcondinf(a, n, isupper, isunit, _state); - if( ae_fp_less(rep->r1,rcondthreshold(_state))||ae_fp_less(rep->rinf,rcondthreshold(_state)) ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a->ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - rep->r1 = (double)(0); - rep->rinf = (double)(0); - *info = -3; - ae_frame_leave(_state); - return; - } - - /* - * Invert - */ - ae_vector_set_length(&tmp, n, _state); - sinfo.val = 1; - matinv_cmatrixtrinverserec(a, 0, n, isupper, isunit, &tmp, &sinfo, _state); - *info = sinfo.val; - ae_frame_leave(_state); -} - - -/************************************************************************* -Recursive subroutine for SPD inversion. - -NOTE: this function expects that matris is strictly positive-definite. - - -- ALGLIB routine -- - 10.02.2010 - Bochkanov Sergey -*************************************************************************/ -void spdmatrixcholeskyinverserec(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* tmp, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - double v; - ae_int_t n1; - ae_int_t n2; - sinteger sinfo2; - ae_int_t tsa; - ae_int_t tsb; - ae_int_t tscur; - - ae_frame_make(_state, &_frame_block); - memset(&sinfo2, 0, sizeof(sinfo2)); - _sinteger_init(&sinfo2, _state, ae_true); - - if( n<1 ) - { - ae_frame_leave(_state); - return; - } - tsa = matrixtilesizea(_state); - tsb = matrixtilesizeb(_state); - tscur = tsb; - if( n<=tsb ) - { - tscur = tsa; - } - - /* - * Base case - */ - if( n<=tsa ) - { - sinfo2.val = 1; - matinv_rmatrixtrinverserec(a, offs, n, isupper, ae_false, tmp, &sinfo2, _state); - ae_assert(sinfo2.val>0, "SPDMatrixCholeskyInverseRec: integrity check failed", _state); - if( isupper ) - { - - /* - * Compute the product U * U'. - * NOTE: we never assume that diagonal of U is real - */ - for(i=0; i<=n-1; i++) - { - if( i==0 ) - { - - /* - * 1x1 matrix - */ - a->ptr.pp_double[offs+i][offs+i] = ae_sqr(a->ptr.pp_double[offs+i][offs+i], _state); - } - else - { - - /* - * (I+1)x(I+1) matrix, - * - * ( A11 A12 ) ( A11^H ) ( A11*A11^H+A12*A12^H A12*A22^H ) - * ( ) * ( ) = ( ) - * ( A22 ) ( A12^H A22^H ) ( A22*A12^H A22*A22^H ) - * - * A11 is IxI, A22 is 1x1. - */ - ae_v_move(&tmp->ptr.p_double[0], 1, &a->ptr.pp_double[offs][offs+i], a->stride, ae_v_len(0,i-1)); - for(j=0; j<=i-1; j++) - { - v = a->ptr.pp_double[offs+j][offs+i]; - ae_v_addd(&a->ptr.pp_double[offs+j][offs+j], 1, &tmp->ptr.p_double[j], 1, ae_v_len(offs+j,offs+i-1), v); - } - v = a->ptr.pp_double[offs+i][offs+i]; - ae_v_muld(&a->ptr.pp_double[offs][offs+i], a->stride, ae_v_len(offs,offs+i-1), v); - a->ptr.pp_double[offs+i][offs+i] = ae_sqr(a->ptr.pp_double[offs+i][offs+i], _state); - } - } - } - else - { - - /* - * Compute the product L' * L - * NOTE: we never assume that diagonal of L is real - */ - for(i=0; i<=n-1; i++) - { - if( i==0 ) - { - - /* - * 1x1 matrix - */ - a->ptr.pp_double[offs+i][offs+i] = ae_sqr(a->ptr.pp_double[offs+i][offs+i], _state); - } - else - { - - /* - * (I+1)x(I+1) matrix, - * - * ( A11^H A21^H ) ( A11 ) ( A11^H*A11+A21^H*A21 A21^H*A22 ) - * ( ) * ( ) = ( ) - * ( A22^H ) ( A21 A22 ) ( A22^H*A21 A22^H*A22 ) - * - * A11 is IxI, A22 is 1x1. - */ - ae_v_move(&tmp->ptr.p_double[0], 1, &a->ptr.pp_double[offs+i][offs], 1, ae_v_len(0,i-1)); - for(j=0; j<=i-1; j++) - { - v = a->ptr.pp_double[offs+i][offs+j]; - ae_v_addd(&a->ptr.pp_double[offs+j][offs], 1, &tmp->ptr.p_double[0], 1, ae_v_len(offs,offs+j), v); - } - v = a->ptr.pp_double[offs+i][offs+i]; - ae_v_muld(&a->ptr.pp_double[offs+i][offs], 1, ae_v_len(offs,offs+i-1), v); - a->ptr.pp_double[offs+i][offs+i] = ae_sqr(a->ptr.pp_double[offs+i][offs+i], _state); - } - } - } - ae_frame_leave(_state); - return; - } - - /* - * Recursive code: triangular factor inversion merged with - * UU' or L'L multiplication - */ - tiledsplit(n, tscur, &n1, &n2, _state); - - /* - * form off-diagonal block of trangular inverse - */ - if( isupper ) - { - for(i=0; i<=n1-1; i++) - { - ae_v_muld(&a->ptr.pp_double[offs+i][offs+n1], 1, ae_v_len(offs+n1,offs+n-1), -1); - } - rmatrixlefttrsm(n1, n2, a, offs, offs, isupper, ae_false, 0, a, offs, offs+n1, _state); - rmatrixrighttrsm(n1, n2, a, offs+n1, offs+n1, isupper, ae_false, 0, a, offs, offs+n1, _state); - } - else - { - for(i=0; i<=n2-1; i++) - { - ae_v_muld(&a->ptr.pp_double[offs+n1+i][offs], 1, ae_v_len(offs,offs+n1-1), -1); - } - rmatrixrighttrsm(n2, n1, a, offs, offs, isupper, ae_false, 0, a, offs+n1, offs, _state); - rmatrixlefttrsm(n2, n1, a, offs+n1, offs+n1, isupper, ae_false, 0, a, offs+n1, offs, _state); - } - - /* - * invert first diagonal block - */ - spdmatrixcholeskyinverserec(a, offs, n1, isupper, tmp, _state); - - /* - * update first diagonal block with off-diagonal block, - * update off-diagonal block - */ - if( isupper ) - { - rmatrixsyrk(n1, n2, 1.0, a, offs, offs+n1, 0, 1.0, a, offs, offs, isupper, _state); - rmatrixrighttrsm(n1, n2, a, offs+n1, offs+n1, isupper, ae_false, 1, a, offs, offs+n1, _state); - } - else - { - rmatrixsyrk(n1, n2, 1.0, a, offs+n1, offs, 1, 1.0, a, offs, offs, isupper, _state); - rmatrixlefttrsm(n2, n1, a, offs+n1, offs+n1, isupper, ae_false, 1, a, offs+n1, offs, _state); - } - - /* - * invert second diagonal block - */ - spdmatrixcholeskyinverserec(a, offs+n1, n2, isupper, tmp, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_spdmatrixcholeskyinverserec(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* tmp, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -Triangular matrix inversion, recursive subroutine - -NOTE: this function sets Info on failure, leaves it unchanged on success. - -NOTE: only Tmp[Offs:Offs+N-1] is modified, other entries of the temporary array are not modified - - -- ALGLIB -- - 05.02.2010, Bochkanov Sergey. - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - February 29, 1992. -*************************************************************************/ -static void matinv_rmatrixtrinverserec(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - /* Real */ ae_vector* tmp, - sinteger* info, - ae_state *_state) -{ - ae_int_t n1; - ae_int_t n2; - ae_int_t mn; - ae_int_t i; - ae_int_t j; - double v; - double ajj; - ae_int_t tsa; - ae_int_t tsb; - ae_int_t tscur; - - - if( n<1 ) - { - info->val = -1; - return; - } - tsa = matrixtilesizea(_state); - tsb = matrixtilesizeb(_state); - tscur = tsb; - if( n<=tsb ) - { - tscur = tsa; - } - - /* - * Try to activate parallelism - */ - if( n>=2*tsb&&ae_fp_greater_eq(rmul3((double)(n), (double)(n), (double)(n), _state)*((double)1/(double)3),smpactivationlevel(_state)) ) - { - if( _trypexec_matinv_rmatrixtrinverserec(a,offs,n,isupper,isunit,tmp,info, _state) ) - { - return; - } - } - - /* - * Base case - */ - if( n<=tsa ) - { - if( isupper ) - { - - /* - * Compute inverse of upper triangular matrix. - */ - for(j=0; j<=n-1; j++) - { - if( !isunit ) - { - if( ae_fp_eq(a->ptr.pp_double[offs+j][offs+j],(double)(0)) ) - { - info->val = -3; - return; - } - a->ptr.pp_double[offs+j][offs+j] = 1/a->ptr.pp_double[offs+j][offs+j]; - ajj = -a->ptr.pp_double[offs+j][offs+j]; - } - else - { - ajj = (double)(-1); - } - - /* - * Compute elements 1:j-1 of j-th column. - */ - if( j>0 ) - { - ae_v_move(&tmp->ptr.p_double[offs+0], 1, &a->ptr.pp_double[offs+0][offs+j], a->stride, ae_v_len(offs+0,offs+j-1)); - for(i=0; i<=j-1; i++) - { - if( iptr.pp_double[offs+i][offs+i+1], 1, &tmp->ptr.p_double[offs+i+1], 1, ae_v_len(offs+i+1,offs+j-1)); - } - else - { - v = (double)(0); - } - if( !isunit ) - { - a->ptr.pp_double[offs+i][offs+j] = v+a->ptr.pp_double[offs+i][offs+i]*tmp->ptr.p_double[offs+i]; - } - else - { - a->ptr.pp_double[offs+i][offs+j] = v+tmp->ptr.p_double[offs+i]; - } - } - ae_v_muld(&a->ptr.pp_double[offs+0][offs+j], a->stride, ae_v_len(offs+0,offs+j-1), ajj); - } - } - } - else - { - - /* - * Compute inverse of lower triangular matrix. - */ - for(j=n-1; j>=0; j--) - { - if( !isunit ) - { - if( ae_fp_eq(a->ptr.pp_double[offs+j][offs+j],(double)(0)) ) - { - info->val = -3; - return; - } - a->ptr.pp_double[offs+j][offs+j] = 1/a->ptr.pp_double[offs+j][offs+j]; - ajj = -a->ptr.pp_double[offs+j][offs+j]; - } - else - { - ajj = (double)(-1); - } - if( jptr.p_double[offs+j+1], 1, &a->ptr.pp_double[offs+j+1][offs+j], a->stride, ae_v_len(offs+j+1,offs+n-1)); - for(i=j+1; i<=n-1; i++) - { - if( i>j+1 ) - { - v = ae_v_dotproduct(&a->ptr.pp_double[offs+i][offs+j+1], 1, &tmp->ptr.p_double[offs+j+1], 1, ae_v_len(offs+j+1,offs+i-1)); - } - else - { - v = (double)(0); - } - if( !isunit ) - { - a->ptr.pp_double[offs+i][offs+j] = v+a->ptr.pp_double[offs+i][offs+i]*tmp->ptr.p_double[offs+i]; - } - else - { - a->ptr.pp_double[offs+i][offs+j] = v+tmp->ptr.p_double[offs+i]; - } - } - ae_v_muld(&a->ptr.pp_double[offs+j+1][offs+j], a->stride, ae_v_len(offs+j+1,offs+n-1), ajj); - } - } - } - return; - } - - /* - * Recursive case - */ - tiledsplit(n, tscur, &n1, &n2, _state); - mn = imin2(n1, n2, _state); - touchint(&mn, _state); - if( n2>0 ) - { - if( isupper ) - { - for(i=0; i<=n1-1; i++) - { - ae_v_muld(&a->ptr.pp_double[offs+i][offs+n1], 1, ae_v_len(offs+n1,offs+n-1), -1); - } - rmatrixrighttrsm(n1, n2, a, offs+n1, offs+n1, isupper, isunit, 0, a, offs, offs+n1, _state); - matinv_rmatrixtrinverserec(a, offs+n1, n2, isupper, isunit, tmp, info, _state); - rmatrixlefttrsm(n1, n2, a, offs, offs, isupper, isunit, 0, a, offs, offs+n1, _state); - } - else - { - for(i=0; i<=n2-1; i++) - { - ae_v_muld(&a->ptr.pp_double[offs+n1+i][offs], 1, ae_v_len(offs,offs+n1-1), -1); - } - rmatrixlefttrsm(n2, n1, a, offs+n1, offs+n1, isupper, isunit, 0, a, offs+n1, offs, _state); - matinv_rmatrixtrinverserec(a, offs+n1, n2, isupper, isunit, tmp, info, _state); - rmatrixrighttrsm(n2, n1, a, offs, offs, isupper, isunit, 0, a, offs+n1, offs, _state); - } - } - matinv_rmatrixtrinverserec(a, offs, n1, isupper, isunit, tmp, info, _state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_matinv_rmatrixtrinverserec(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - /* Real */ ae_vector* tmp, - sinteger* info, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -Triangular matrix inversion, recursive subroutine. - -Info is modified on failure, left unchanged on success. - - -- ALGLIB -- - 05.02.2010, Bochkanov Sergey. - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - February 29, 1992. -*************************************************************************/ -static void matinv_cmatrixtrinverserec(/* Complex */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - /* Complex */ ae_vector* tmp, - sinteger* info, - ae_state *_state) -{ - ae_int_t n1; - ae_int_t n2; - ae_int_t i; - ae_int_t j; - ae_complex v; - ae_complex ajj; - ae_int_t tsa; - ae_int_t tsb; - ae_int_t tscur; - ae_int_t mn; - - - if( n<1 ) - { - info->val = -1; - return; - } - tsa = matrixtilesizea(_state)/2; - tsb = matrixtilesizeb(_state); - tscur = tsb; - if( n<=tsb ) - { - tscur = tsa; - } - - /* - * Try to activate parallelism - */ - if( n>=2*tsb&&ae_fp_greater_eq(rmul3((double)(n), (double)(n), (double)(n), _state)*((double)4/(double)3),smpactivationlevel(_state)) ) - { - if( _trypexec_matinv_cmatrixtrinverserec(a,offs,n,isupper,isunit,tmp,info, _state) ) - { - return; - } - } - - /* - * Base case - */ - if( n<=tsa ) - { - if( isupper ) - { - - /* - * Compute inverse of upper triangular matrix. - */ - for(j=0; j<=n-1; j++) - { - if( !isunit ) - { - if( ae_c_eq_d(a->ptr.pp_complex[offs+j][offs+j],(double)(0)) ) - { - info->val = -3; - return; - } - a->ptr.pp_complex[offs+j][offs+j] = ae_c_d_div(1,a->ptr.pp_complex[offs+j][offs+j]); - ajj = ae_c_neg(a->ptr.pp_complex[offs+j][offs+j]); - } - else - { - ajj = ae_complex_from_i(-1); - } - - /* - * Compute elements 1:j-1 of j-th column. - */ - if( j>0 ) - { - ae_v_cmove(&tmp->ptr.p_complex[offs+0], 1, &a->ptr.pp_complex[offs+0][offs+j], a->stride, "N", ae_v_len(offs+0,offs+j-1)); - for(i=0; i<=j-1; i++) - { - if( iptr.pp_complex[offs+i][offs+i+1], 1, "N", &tmp->ptr.p_complex[offs+i+1], 1, "N", ae_v_len(offs+i+1,offs+j-1)); - } - else - { - v = ae_complex_from_i(0); - } - if( !isunit ) - { - a->ptr.pp_complex[offs+i][offs+j] = ae_c_add(v,ae_c_mul(a->ptr.pp_complex[offs+i][offs+i],tmp->ptr.p_complex[offs+i])); - } - else - { - a->ptr.pp_complex[offs+i][offs+j] = ae_c_add(v,tmp->ptr.p_complex[offs+i]); - } - } - ae_v_cmulc(&a->ptr.pp_complex[offs+0][offs+j], a->stride, ae_v_len(offs+0,offs+j-1), ajj); - } - } - } - else - { - - /* - * Compute inverse of lower triangular matrix. - */ - for(j=n-1; j>=0; j--) - { - if( !isunit ) - { - if( ae_c_eq_d(a->ptr.pp_complex[offs+j][offs+j],(double)(0)) ) - { - info->val = -3; - return; - } - a->ptr.pp_complex[offs+j][offs+j] = ae_c_d_div(1,a->ptr.pp_complex[offs+j][offs+j]); - ajj = ae_c_neg(a->ptr.pp_complex[offs+j][offs+j]); - } - else - { - ajj = ae_complex_from_i(-1); - } - if( jptr.p_complex[offs+j+1], 1, &a->ptr.pp_complex[offs+j+1][offs+j], a->stride, "N", ae_v_len(offs+j+1,offs+n-1)); - for(i=j+1; i<=n-1; i++) - { - if( i>j+1 ) - { - v = ae_v_cdotproduct(&a->ptr.pp_complex[offs+i][offs+j+1], 1, "N", &tmp->ptr.p_complex[offs+j+1], 1, "N", ae_v_len(offs+j+1,offs+i-1)); - } - else - { - v = ae_complex_from_i(0); - } - if( !isunit ) - { - a->ptr.pp_complex[offs+i][offs+j] = ae_c_add(v,ae_c_mul(a->ptr.pp_complex[offs+i][offs+i],tmp->ptr.p_complex[offs+i])); - } - else - { - a->ptr.pp_complex[offs+i][offs+j] = ae_c_add(v,tmp->ptr.p_complex[offs+i]); - } - } - ae_v_cmulc(&a->ptr.pp_complex[offs+j+1][offs+j], a->stride, ae_v_len(offs+j+1,offs+n-1), ajj); - } - } - } - return; - } - - /* - * Recursive case - */ - tiledsplit(n, tscur, &n1, &n2, _state); - mn = imin2(n1, n2, _state); - touchint(&mn, _state); - if( n2>0 ) - { - if( isupper ) - { - for(i=0; i<=n1-1; i++) - { - ae_v_cmuld(&a->ptr.pp_complex[offs+i][offs+n1], 1, ae_v_len(offs+n1,offs+n-1), -1); - } - cmatrixrighttrsm(n1, n2, a, offs+n1, offs+n1, isupper, isunit, 0, a, offs, offs+n1, _state); - matinv_cmatrixtrinverserec(a, offs+n1, n2, isupper, isunit, tmp, info, _state); - cmatrixlefttrsm(n1, n2, a, offs, offs, isupper, isunit, 0, a, offs, offs+n1, _state); - } - else - { - for(i=0; i<=n2-1; i++) - { - ae_v_cmuld(&a->ptr.pp_complex[offs+n1+i][offs], 1, ae_v_len(offs,offs+n1-1), -1); - } - cmatrixlefttrsm(n2, n1, a, offs+n1, offs+n1, isupper, isunit, 0, a, offs+n1, offs, _state); - matinv_cmatrixtrinverserec(a, offs+n1, n2, isupper, isunit, tmp, info, _state); - cmatrixrighttrsm(n2, n1, a, offs, offs, isupper, isunit, 0, a, offs+n1, offs, _state); - } - } - matinv_cmatrixtrinverserec(a, offs, n1, isupper, isunit, tmp, info, _state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_matinv_cmatrixtrinverserec(/* Complex */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - /* Complex */ ae_vector* tmp, - sinteger* info, - ae_state *_state) -{ - return ae_false; -} - - -static void matinv_rmatrixluinverserec(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - /* Real */ ae_vector* work, - sinteger* info, - matinvreport* rep, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - ae_int_t n1; - ae_int_t n2; - ae_int_t tsa; - ae_int_t tsb; - ae_int_t tscur; - ae_int_t mn; - - - if( n<1 ) - { - info->val = -1; - return; - } - tsa = matrixtilesizea(_state); - tsb = matrixtilesizeb(_state); - tscur = tsb; - if( n<=tsb ) - { - tscur = tsa; - } - - /* - * Try parallelism - */ - if( n>=2*tsb&&ae_fp_greater_eq((double)8/(double)6*rmul3((double)(n), (double)(n), (double)(n), _state),smpactivationlevel(_state)) ) - { - if( _trypexec_matinv_rmatrixluinverserec(a,offs,n,work,info,rep, _state) ) - { - return; - } - } - - /* - * Base case - */ - if( n<=tsa ) - { - - /* - * Form inv(U) - */ - matinv_rmatrixtrinverserec(a, offs, n, ae_true, ae_false, work, info, _state); - if( info->val<=0 ) - { - return; - } - - /* - * Solve the equation inv(A)*L = inv(U) for inv(A). - */ - for(j=n-1; j>=0; j--) - { - - /* - * Copy current column of L to WORK and replace with zeros. - */ - for(i=j+1; i<=n-1; i++) - { - work->ptr.p_double[i] = a->ptr.pp_double[offs+i][offs+j]; - a->ptr.pp_double[offs+i][offs+j] = (double)(0); - } - - /* - * Compute current column of inv(A). - */ - if( jptr.pp_double[offs+i][offs+j+1], 1, &work->ptr.p_double[j+1], 1, ae_v_len(offs+j+1,offs+n-1)); - a->ptr.pp_double[offs+i][offs+j] = a->ptr.pp_double[offs+i][offs+j]-v; - } - } - } - return; - } - - /* - * Recursive code: - * - * ( L1 ) ( U1 U12 ) - * A = ( ) * ( ) - * ( L12 L2 ) ( U2 ) - * - * ( W X ) - * A^-1 = ( ) - * ( Y Z ) - * - * In-place calculation can be done as follows: - * * X := inv(U1)*U12*inv(U2) - * * Y := inv(L2)*L12*inv(L1) - * * W := inv(L1*U1)+X*Y - * * X := -X*inv(L2) - * * Y := -inv(U2)*Y - * * Z := inv(L2*U2) - * - * Reordering w.r.t. interdependencies gives us: - * - * * X := inv(U1)*U12 \ suitable for parallel execution - * * Y := L12*inv(L1) / - * - * * X := X*inv(U2) \ - * * Y := inv(L2)*Y | suitable for parallel execution - * * W := inv(L1*U1) / - * - * * W := W+X*Y - * - * * X := -X*inv(L2) \ suitable for parallel execution - * * Y := -inv(U2)*Y / - * - * * Z := inv(L2*U2) - */ - tiledsplit(n, tscur, &n1, &n2, _state); - mn = imin2(n1, n2, _state); - touchint(&mn, _state); - ae_assert(n2>0, "LUInverseRec: internal error!", _state); - - /* - * X := inv(U1)*U12 - * Y := L12*inv(L1) - */ - rmatrixlefttrsm(n1, n2, a, offs, offs, ae_true, ae_false, 0, a, offs, offs+n1, _state); - rmatrixrighttrsm(n2, n1, a, offs, offs, ae_false, ae_true, 0, a, offs+n1, offs, _state); - - /* - * X := X*inv(U2) - * Y := inv(L2)*Y - * W := inv(L1*U1) - */ - rmatrixrighttrsm(n1, n2, a, offs+n1, offs+n1, ae_true, ae_false, 0, a, offs, offs+n1, _state); - rmatrixlefttrsm(n2, n1, a, offs+n1, offs+n1, ae_false, ae_true, 0, a, offs+n1, offs, _state); - matinv_rmatrixluinverserec(a, offs, n1, work, info, rep, _state); - if( info->val<=0 ) - { - return; - } - - /* - * W := W+X*Y - */ - rmatrixgemm(n1, n1, n2, 1.0, a, offs, offs+n1, 0, a, offs+n1, offs, 0, 1.0, a, offs, offs, _state); - - /* - * X := -X*inv(L2) - * Y := -inv(U2)*Y - */ - rmatrixrighttrsm(n1, n2, a, offs+n1, offs+n1, ae_false, ae_true, 0, a, offs, offs+n1, _state); - rmatrixlefttrsm(n2, n1, a, offs+n1, offs+n1, ae_true, ae_false, 0, a, offs+n1, offs, _state); - for(i=0; i<=n1-1; i++) - { - ae_v_muld(&a->ptr.pp_double[offs+i][offs+n1], 1, ae_v_len(offs+n1,offs+n-1), -1); - } - for(i=0; i<=n2-1; i++) - { - ae_v_muld(&a->ptr.pp_double[offs+n1+i][offs], 1, ae_v_len(offs,offs+n1-1), -1); - } - - /* - * Z := inv(L2*U2) - */ - matinv_rmatrixluinverserec(a, offs+n1, n2, work, info, rep, _state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_matinv_rmatrixluinverserec(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - /* Real */ ae_vector* work, - sinteger* info, - matinvreport* rep, - ae_state *_state) -{ - return ae_false; -} - - -static void matinv_cmatrixluinverserec(/* Complex */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - /* Complex */ ae_vector* work, - sinteger* ssinfo, - matinvreport* rep, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_complex v; - ae_int_t n1; - ae_int_t n2; - ae_int_t mn; - ae_int_t tsa; - ae_int_t tsb; - ae_int_t tscur; - - - if( n<1 ) - { - ssinfo->val = -1; - return; - } - tsa = matrixtilesizea(_state)/2; - tsb = matrixtilesizeb(_state); - tscur = tsb; - if( n<=tsb ) - { - tscur = tsa; - } - - /* - * Try parallelism - */ - if( n>=2*tsb&&ae_fp_greater_eq((double)32/(double)6*rmul3((double)(n), (double)(n), (double)(n), _state),smpactivationlevel(_state)) ) - { - if( _trypexec_matinv_cmatrixluinverserec(a,offs,n,work,ssinfo,rep, _state) ) - { - return; - } - } - - /* - * Base case - */ - if( n<=tsa ) - { - - /* - * Form inv(U) - */ - matinv_cmatrixtrinverserec(a, offs, n, ae_true, ae_false, work, ssinfo, _state); - if( ssinfo->val<=0 ) - { - return; - } - - /* - * Solve the equation inv(A)*L = inv(U) for inv(A). - */ - for(j=n-1; j>=0; j--) - { - - /* - * Copy current column of L to WORK and replace with zeros. - */ - for(i=j+1; i<=n-1; i++) - { - work->ptr.p_complex[i] = a->ptr.pp_complex[offs+i][offs+j]; - a->ptr.pp_complex[offs+i][offs+j] = ae_complex_from_i(0); - } - - /* - * Compute current column of inv(A). - */ - if( jptr.pp_complex[offs+i][offs+j+1], 1, "N", &work->ptr.p_complex[j+1], 1, "N", ae_v_len(offs+j+1,offs+n-1)); - a->ptr.pp_complex[offs+i][offs+j] = ae_c_sub(a->ptr.pp_complex[offs+i][offs+j],v); - } - } - } - return; - } - - /* - * Recursive code: - * - * ( L1 ) ( U1 U12 ) - * A = ( ) * ( ) - * ( L12 L2 ) ( U2 ) - * - * ( W X ) - * A^-1 = ( ) - * ( Y Z ) - * - * In-place calculation can be done as follows: - * * X := inv(U1)*U12*inv(U2) - * * Y := inv(L2)*L12*inv(L1) - * * W := inv(L1*U1)+X*Y - * * X := -X*inv(L2) - * * Y := -inv(U2)*Y - * * Z := inv(L2*U2) - * - * Reordering w.r.t. interdependencies gives us: - * - * * X := inv(U1)*U12 \ suitable for parallel execution - * * Y := L12*inv(L1) / - * - * * X := X*inv(U2) \ - * * Y := inv(L2)*Y | suitable for parallel execution - * * W := inv(L1*U1) / - * - * * W := W+X*Y - * - * * X := -X*inv(L2) \ suitable for parallel execution - * * Y := -inv(U2)*Y / - * - * * Z := inv(L2*U2) - */ - tiledsplit(n, tscur, &n1, &n2, _state); - mn = imin2(n1, n2, _state); - touchint(&mn, _state); - ae_assert(n2>0, "LUInverseRec: internal error!", _state); - - /* - * X := inv(U1)*U12 - * Y := L12*inv(L1) - */ - cmatrixlefttrsm(n1, n2, a, offs, offs, ae_true, ae_false, 0, a, offs, offs+n1, _state); - cmatrixrighttrsm(n2, n1, a, offs, offs, ae_false, ae_true, 0, a, offs+n1, offs, _state); - - /* - * X := X*inv(U2) - * Y := inv(L2)*Y - * W := inv(L1*U1) - */ - cmatrixrighttrsm(n1, n2, a, offs+n1, offs+n1, ae_true, ae_false, 0, a, offs, offs+n1, _state); - cmatrixlefttrsm(n2, n1, a, offs+n1, offs+n1, ae_false, ae_true, 0, a, offs+n1, offs, _state); - matinv_cmatrixluinverserec(a, offs, n1, work, ssinfo, rep, _state); - if( ssinfo->val<=0 ) - { - return; - } - - /* - * W := W+X*Y - */ - cmatrixgemm(n1, n1, n2, ae_complex_from_d(1.0), a, offs, offs+n1, 0, a, offs+n1, offs, 0, ae_complex_from_d(1.0), a, offs, offs, _state); - - /* - * X := -X*inv(L2) - * Y := -inv(U2)*Y - */ - cmatrixrighttrsm(n1, n2, a, offs+n1, offs+n1, ae_false, ae_true, 0, a, offs, offs+n1, _state); - cmatrixlefttrsm(n2, n1, a, offs+n1, offs+n1, ae_true, ae_false, 0, a, offs+n1, offs, _state); - for(i=0; i<=n1-1; i++) - { - ae_v_cmuld(&a->ptr.pp_complex[offs+i][offs+n1], 1, ae_v_len(offs+n1,offs+n-1), -1); - } - for(i=0; i<=n2-1; i++) - { - ae_v_cmuld(&a->ptr.pp_complex[offs+n1+i][offs], 1, ae_v_len(offs,offs+n1-1), -1); - } - - /* - * Z := inv(L2*U2) - */ - matinv_cmatrixluinverserec(a, offs+n1, n2, work, ssinfo, rep, _state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_matinv_cmatrixluinverserec(/* Complex */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - /* Complex */ ae_vector* work, - sinteger* ssinfo, - matinvreport* rep, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -Recursive subroutine for HPD inversion. - - -- ALGLIB routine -- - 10.02.2010 - Bochkanov Sergey -*************************************************************************/ -static void matinv_hpdmatrixcholeskyinverserec(/* Complex */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* tmp, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_complex v; - ae_int_t n1; - ae_int_t n2; - sinteger sinfo; - ae_int_t tsa; - ae_int_t tsb; - ae_int_t tscur; - - ae_frame_make(_state, &_frame_block); - memset(&sinfo, 0, sizeof(sinfo)); - _sinteger_init(&sinfo, _state, ae_true); - - if( n<1 ) - { - ae_frame_leave(_state); - return; - } - tsa = matrixtilesizea(_state)/2; - tsb = matrixtilesizeb(_state); - tscur = tsb; - if( n<=tsb ) - { - tscur = tsa; - } - - /* - * Base case - */ - if( n<=tsa ) - { - sinfo.val = 1; - matinv_cmatrixtrinverserec(a, offs, n, isupper, ae_false, tmp, &sinfo, _state); - ae_assert(sinfo.val>0, "HPDMatrixCholeskyInverseRec: integrity check failed", _state); - if( isupper ) - { - - /* - * Compute the product U * U'. - * NOTE: we never assume that diagonal of U is real - */ - for(i=0; i<=n-1; i++) - { - if( i==0 ) - { - - /* - * 1x1 matrix - */ - a->ptr.pp_complex[offs+i][offs+i] = ae_complex_from_d(ae_sqr(a->ptr.pp_complex[offs+i][offs+i].x, _state)+ae_sqr(a->ptr.pp_complex[offs+i][offs+i].y, _state)); - } - else - { - - /* - * (I+1)x(I+1) matrix, - * - * ( A11 A12 ) ( A11^H ) ( A11*A11^H+A12*A12^H A12*A22^H ) - * ( ) * ( ) = ( ) - * ( A22 ) ( A12^H A22^H ) ( A22*A12^H A22*A22^H ) - * - * A11 is IxI, A22 is 1x1. - */ - ae_v_cmove(&tmp->ptr.p_complex[0], 1, &a->ptr.pp_complex[offs][offs+i], a->stride, "Conj", ae_v_len(0,i-1)); - for(j=0; j<=i-1; j++) - { - v = a->ptr.pp_complex[offs+j][offs+i]; - ae_v_caddc(&a->ptr.pp_complex[offs+j][offs+j], 1, &tmp->ptr.p_complex[j], 1, "N", ae_v_len(offs+j,offs+i-1), v); - } - v = ae_c_conj(a->ptr.pp_complex[offs+i][offs+i], _state); - ae_v_cmulc(&a->ptr.pp_complex[offs][offs+i], a->stride, ae_v_len(offs,offs+i-1), v); - a->ptr.pp_complex[offs+i][offs+i] = ae_complex_from_d(ae_sqr(a->ptr.pp_complex[offs+i][offs+i].x, _state)+ae_sqr(a->ptr.pp_complex[offs+i][offs+i].y, _state)); - } - } - } - else - { - - /* - * Compute the product L' * L - * NOTE: we never assume that diagonal of L is real - */ - for(i=0; i<=n-1; i++) - { - if( i==0 ) - { - - /* - * 1x1 matrix - */ - a->ptr.pp_complex[offs+i][offs+i] = ae_complex_from_d(ae_sqr(a->ptr.pp_complex[offs+i][offs+i].x, _state)+ae_sqr(a->ptr.pp_complex[offs+i][offs+i].y, _state)); - } - else - { - - /* - * (I+1)x(I+1) matrix, - * - * ( A11^H A21^H ) ( A11 ) ( A11^H*A11+A21^H*A21 A21^H*A22 ) - * ( ) * ( ) = ( ) - * ( A22^H ) ( A21 A22 ) ( A22^H*A21 A22^H*A22 ) - * - * A11 is IxI, A22 is 1x1. - */ - ae_v_cmove(&tmp->ptr.p_complex[0], 1, &a->ptr.pp_complex[offs+i][offs], 1, "N", ae_v_len(0,i-1)); - for(j=0; j<=i-1; j++) - { - v = ae_c_conj(a->ptr.pp_complex[offs+i][offs+j], _state); - ae_v_caddc(&a->ptr.pp_complex[offs+j][offs], 1, &tmp->ptr.p_complex[0], 1, "N", ae_v_len(offs,offs+j), v); - } - v = ae_c_conj(a->ptr.pp_complex[offs+i][offs+i], _state); - ae_v_cmulc(&a->ptr.pp_complex[offs+i][offs], 1, ae_v_len(offs,offs+i-1), v); - a->ptr.pp_complex[offs+i][offs+i] = ae_complex_from_d(ae_sqr(a->ptr.pp_complex[offs+i][offs+i].x, _state)+ae_sqr(a->ptr.pp_complex[offs+i][offs+i].y, _state)); - } - } - } - ae_frame_leave(_state); - return; - } - - /* - * Recursive code: triangular factor inversion merged with - * UU' or L'L multiplication - */ - tiledsplit(n, tscur, &n1, &n2, _state); - - /* - * form off-diagonal block of trangular inverse - */ - if( isupper ) - { - for(i=0; i<=n1-1; i++) - { - ae_v_cmuld(&a->ptr.pp_complex[offs+i][offs+n1], 1, ae_v_len(offs+n1,offs+n-1), -1); - } - cmatrixlefttrsm(n1, n2, a, offs, offs, isupper, ae_false, 0, a, offs, offs+n1, _state); - cmatrixrighttrsm(n1, n2, a, offs+n1, offs+n1, isupper, ae_false, 0, a, offs, offs+n1, _state); - } - else - { - for(i=0; i<=n2-1; i++) - { - ae_v_cmuld(&a->ptr.pp_complex[offs+n1+i][offs], 1, ae_v_len(offs,offs+n1-1), -1); - } - cmatrixrighttrsm(n2, n1, a, offs, offs, isupper, ae_false, 0, a, offs+n1, offs, _state); - cmatrixlefttrsm(n2, n1, a, offs+n1, offs+n1, isupper, ae_false, 0, a, offs+n1, offs, _state); - } - - /* - * invert first diagonal block - */ - matinv_hpdmatrixcholeskyinverserec(a, offs, n1, isupper, tmp, _state); - - /* - * update first diagonal block with off-diagonal block, - * update off-diagonal block - */ - if( isupper ) - { - cmatrixherk(n1, n2, 1.0, a, offs, offs+n1, 0, 1.0, a, offs, offs, isupper, _state); - cmatrixrighttrsm(n1, n2, a, offs+n1, offs+n1, isupper, ae_false, 2, a, offs, offs+n1, _state); - } - else - { - cmatrixherk(n1, n2, 1.0, a, offs+n1, offs, 2, 1.0, a, offs, offs, isupper, _state); - cmatrixlefttrsm(n2, n1, a, offs+n1, offs+n1, isupper, ae_false, 2, a, offs+n1, offs, _state); - } - - /* - * invert second diagonal block - */ - matinv_hpdmatrixcholeskyinverserec(a, offs+n1, n2, isupper, tmp, _state); - ae_frame_leave(_state); -} - - -void _matinvreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - matinvreport *p = (matinvreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _matinvreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - matinvreport *dst = (matinvreport*)_dst; - matinvreport *src = (matinvreport*)_src; - dst->r1 = src->r1; - dst->rinf = src->rinf; -} - - -void _matinvreport_clear(void* _p) -{ - matinvreport *p = (matinvreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _matinvreport_destroy(void* _p) -{ - matinvreport *p = (matinvreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_ORTFAC) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -QR decomposition of a rectangular matrix of size MxN - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix A whose indexes range within [0..M-1, 0..N-1]. - M - number of rows in matrix A. - N - number of columns in matrix A. - -Output parameters: - A - matrices Q and R in compact form (see below). - Tau - array of scalar factors which are used to form - matrix Q. Array whose index ranges within [0.. Min(M-1,N-1)]. - -Matrix A is represented as A = QR, where Q is an orthogonal matrix of size -MxM, R - upper triangular (or upper trapezoid) matrix of size M x N. - -The elements of matrix R are located on and above the main diagonal of -matrix A. The elements which are located in Tau array and below the main -diagonal of matrix A are used to form matrix Q as follows: - -Matrix Q is represented as a product of elementary reflections - -Q = H(0)*H(2)*...*H(k-1), - -where k = min(m,n), and each H(i) is in the form - -H(i) = 1 - tau * v * (v^T) - -where tau is a scalar stored in Tau[I]; v - real vector, -so that v(0:i-1) = 0, v(i) = 1, v(i+1:m-1) stored in A(i+1:m-1,i). - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixqr(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* tau, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector work; - ae_vector t; - ae_vector taubuf; - ae_int_t minmn; - ae_matrix tmpa; - ae_matrix tmpt; - ae_matrix tmpr; - ae_int_t blockstart; - ae_int_t blocksize; - ae_int_t rowscount; - ae_int_t i; - ae_int_t ts; - - ae_frame_make(_state, &_frame_block); - memset(&work, 0, sizeof(work)); - memset(&t, 0, sizeof(t)); - memset(&taubuf, 0, sizeof(taubuf)); - memset(&tmpa, 0, sizeof(tmpa)); - memset(&tmpt, 0, sizeof(tmpt)); - memset(&tmpr, 0, sizeof(tmpr)); - ae_vector_clear(tau); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - ae_vector_init(&taubuf, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&tmpa, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&tmpt, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&tmpr, 0, 0, DT_REAL, _state, ae_true); - - if( m<=0||n<=0 ) - { - ae_frame_leave(_state); - return; - } - minmn = ae_minint(m, n, _state); - ts = matrixtilesizeb(_state); - ae_vector_set_length(&work, ae_maxint(m, n, _state)+1, _state); - ae_vector_set_length(&t, ae_maxint(m, n, _state)+1, _state); - ae_vector_set_length(tau, minmn, _state); - ae_vector_set_length(&taubuf, minmn, _state); - ae_matrix_set_length(&tmpa, m, ts, _state); - ae_matrix_set_length(&tmpt, ts, 2*ts, _state); - ae_matrix_set_length(&tmpr, 2*ts, n, _state); - - /* - * Blocked code - */ - blockstart = 0; - while(blockstart!=minmn) - { - - /* - * Determine block size - */ - blocksize = minmn-blockstart; - if( blocksize>ts ) - { - blocksize = ts; - } - rowscount = m-blockstart; - - /* - * QR decomposition of submatrix. - * Matrix is copied to temporary storage to solve - * some TLB issues arising from non-contiguous memory - * access pattern. - */ - rmatrixcopy(rowscount, blocksize, a, blockstart, blockstart, &tmpa, 0, 0, _state); - rmatrixqrbasecase(&tmpa, rowscount, blocksize, &work, &t, &taubuf, _state); - rmatrixcopy(rowscount, blocksize, &tmpa, 0, 0, a, blockstart, blockstart, _state); - ae_v_move(&tau->ptr.p_double[blockstart], 1, &taubuf.ptr.p_double[0], 1, ae_v_len(blockstart,blockstart+blocksize-1)); - - /* - * Update the rest, choose between: - * a) Level 2 algorithm (when the rest of the matrix is small enough) - * b) blocked algorithm, see algorithm 5 from 'A storage efficient WY - * representation for products of Householder transformations', - * by R. Schreiber and C. Van Loan. - */ - if( blockstart+blocksize<=n-1 ) - { - if( n-blockstart-blocksize>=2*ts||rowscount>=4*ts ) - { - - /* - * Prepare block reflector - */ - ortfac_rmatrixblockreflector(&tmpa, &taubuf, ae_true, rowscount, blocksize, &tmpt, &work, _state); - - /* - * Multiply the rest of A by Q'. - * - * Q = E + Y*T*Y' = E + TmpA*TmpT*TmpA' - * Q' = E + Y*T'*Y' = E + TmpA*TmpT'*TmpA' - */ - rmatrixgemm(blocksize, n-blockstart-blocksize, rowscount, 1.0, &tmpa, 0, 0, 1, a, blockstart, blockstart+blocksize, 0, 0.0, &tmpr, 0, 0, _state); - rmatrixgemm(blocksize, n-blockstart-blocksize, blocksize, 1.0, &tmpt, 0, 0, 1, &tmpr, 0, 0, 0, 0.0, &tmpr, blocksize, 0, _state); - rmatrixgemm(rowscount, n-blockstart-blocksize, blocksize, 1.0, &tmpa, 0, 0, 0, &tmpr, blocksize, 0, 0, 1.0, a, blockstart, blockstart+blocksize, _state); - } - else - { - - /* - * Level 2 algorithm - */ - for(i=0; i<=blocksize-1; i++) - { - ae_v_move(&t.ptr.p_double[1], 1, &tmpa.ptr.pp_double[i][i], tmpa.stride, ae_v_len(1,rowscount-i)); - t.ptr.p_double[1] = (double)(1); - applyreflectionfromtheleft(a, taubuf.ptr.p_double[i], &t, blockstart+i, m-1, blockstart+blocksize, n-1, &work, _state); - } - } - } - - /* - * Advance - */ - blockstart = blockstart+blocksize; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -LQ decomposition of a rectangular matrix of size MxN - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix A whose indexes range within [0..M-1, 0..N-1]. - M - number of rows in matrix A. - N - number of columns in matrix A. - -Output parameters: - A - matrices L and Q in compact form (see below) - Tau - array of scalar factors which are used to form - matrix Q. Array whose index ranges within [0..Min(M,N)-1]. - -Matrix A is represented as A = LQ, where Q is an orthogonal matrix of size -MxM, L - lower triangular (or lower trapezoid) matrix of size M x N. - -The elements of matrix L are located on and below the main diagonal of -matrix A. The elements which are located in Tau array and above the main -diagonal of matrix A are used to form matrix Q as follows: - -Matrix Q is represented as a product of elementary reflections - -Q = H(k-1)*H(k-2)*...*H(1)*H(0), - -where k = min(m,n), and each H(i) is of the form - -H(i) = 1 - tau * v * (v^T) - -where tau is a scalar stored in Tau[I]; v - real vector, so that v(0:i-1)=0, -v(i) = 1, v(i+1:n-1) stored in A(i,i+1:n-1). - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixlq(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* tau, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector work; - ae_vector t; - ae_vector taubuf; - ae_int_t minmn; - ae_matrix tmpa; - ae_matrix tmpt; - ae_matrix tmpr; - ae_int_t blockstart; - ae_int_t blocksize; - ae_int_t columnscount; - ae_int_t i; - ae_int_t ts; - - ae_frame_make(_state, &_frame_block); - memset(&work, 0, sizeof(work)); - memset(&t, 0, sizeof(t)); - memset(&taubuf, 0, sizeof(taubuf)); - memset(&tmpa, 0, sizeof(tmpa)); - memset(&tmpt, 0, sizeof(tmpt)); - memset(&tmpr, 0, sizeof(tmpr)); - ae_vector_clear(tau); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - ae_vector_init(&taubuf, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&tmpa, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&tmpt, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&tmpr, 0, 0, DT_REAL, _state, ae_true); - - if( m<=0||n<=0 ) - { - ae_frame_leave(_state); - return; - } - minmn = ae_minint(m, n, _state); - ts = matrixtilesizeb(_state); - ae_vector_set_length(&work, ae_maxint(m, n, _state)+1, _state); - ae_vector_set_length(&t, ae_maxint(m, n, _state)+1, _state); - ae_vector_set_length(tau, minmn, _state); - ae_vector_set_length(&taubuf, minmn, _state); - ae_matrix_set_length(&tmpa, ts, n, _state); - ae_matrix_set_length(&tmpt, ts, 2*ts, _state); - ae_matrix_set_length(&tmpr, m, 2*ts, _state); - - /* - * Blocked code - */ - blockstart = 0; - while(blockstart!=minmn) - { - - /* - * Determine block size - */ - blocksize = minmn-blockstart; - if( blocksize>ts ) - { - blocksize = ts; - } - columnscount = n-blockstart; - - /* - * LQ decomposition of submatrix. - * Matrix is copied to temporary storage to solve - * some TLB issues arising from non-contiguous memory - * access pattern. - */ - rmatrixcopy(blocksize, columnscount, a, blockstart, blockstart, &tmpa, 0, 0, _state); - rmatrixlqbasecase(&tmpa, blocksize, columnscount, &work, &t, &taubuf, _state); - rmatrixcopy(blocksize, columnscount, &tmpa, 0, 0, a, blockstart, blockstart, _state); - ae_v_move(&tau->ptr.p_double[blockstart], 1, &taubuf.ptr.p_double[0], 1, ae_v_len(blockstart,blockstart+blocksize-1)); - - /* - * Update the rest, choose between: - * a) Level 2 algorithm (when the rest of the matrix is small enough) - * b) blocked algorithm, see algorithm 5 from 'A storage efficient WY - * representation for products of Householder transformations', - * by R. Schreiber and C. Van Loan. - */ - if( blockstart+blocksize<=m-1 ) - { - if( m-blockstart-blocksize>=2*ts ) - { - - /* - * Prepare block reflector - */ - ortfac_rmatrixblockreflector(&tmpa, &taubuf, ae_false, columnscount, blocksize, &tmpt, &work, _state); - - /* - * Multiply the rest of A by Q. - * - * Q = E + Y*T*Y' = E + TmpA'*TmpT*TmpA - */ - rmatrixgemm(m-blockstart-blocksize, blocksize, columnscount, 1.0, a, blockstart+blocksize, blockstart, 0, &tmpa, 0, 0, 1, 0.0, &tmpr, 0, 0, _state); - rmatrixgemm(m-blockstart-blocksize, blocksize, blocksize, 1.0, &tmpr, 0, 0, 0, &tmpt, 0, 0, 0, 0.0, &tmpr, 0, blocksize, _state); - rmatrixgemm(m-blockstart-blocksize, columnscount, blocksize, 1.0, &tmpr, 0, blocksize, 0, &tmpa, 0, 0, 0, 1.0, a, blockstart+blocksize, blockstart, _state); - } - else - { - - /* - * Level 2 algorithm - */ - for(i=0; i<=blocksize-1; i++) - { - ae_v_move(&t.ptr.p_double[1], 1, &tmpa.ptr.pp_double[i][i], 1, ae_v_len(1,columnscount-i)); - t.ptr.p_double[1] = (double)(1); - applyreflectionfromtheright(a, taubuf.ptr.p_double[i], &t, blockstart+blocksize, m-1, blockstart+i, n-1, &work, _state); - } - } - } - - /* - * Advance - */ - blockstart = blockstart+blocksize; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -QR decomposition of a rectangular complex matrix of size MxN - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix A whose indexes range within [0..M-1, 0..N-1] - M - number of rows in matrix A. - N - number of columns in matrix A. - -Output parameters: - A - matrices Q and R in compact form - Tau - array of scalar factors which are used to form matrix Q. Array - whose indexes range within [0.. Min(M,N)-1] - -Matrix A is represented as A = QR, where Q is an orthogonal matrix of size -MxM, R - upper triangular (or upper trapezoid) matrix of size MxN. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994 -*************************************************************************/ -void cmatrixqr(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_vector* tau, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector work; - ae_vector t; - ae_vector taubuf; - ae_int_t minmn; - ae_matrix tmpa; - ae_matrix tmpt; - ae_matrix tmpr; - ae_int_t blockstart; - ae_int_t blocksize; - ae_int_t rowscount; - ae_int_t i; - ae_int_t ts; - - ae_frame_make(_state, &_frame_block); - memset(&work, 0, sizeof(work)); - memset(&t, 0, sizeof(t)); - memset(&taubuf, 0, sizeof(taubuf)); - memset(&tmpa, 0, sizeof(tmpa)); - memset(&tmpt, 0, sizeof(tmpt)); - memset(&tmpr, 0, sizeof(tmpr)); - ae_vector_clear(tau); - ae_vector_init(&work, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&t, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&taubuf, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&tmpa, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&tmpt, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&tmpr, 0, 0, DT_COMPLEX, _state, ae_true); - - if( m<=0||n<=0 ) - { - ae_frame_leave(_state); - return; - } - ts = matrixtilesizeb(_state)/2; - minmn = ae_minint(m, n, _state); - ae_vector_set_length(&work, ae_maxint(m, n, _state)+1, _state); - ae_vector_set_length(&t, ae_maxint(m, n, _state)+1, _state); - ae_vector_set_length(tau, minmn, _state); - ae_vector_set_length(&taubuf, minmn, _state); - ae_matrix_set_length(&tmpa, m, ts, _state); - ae_matrix_set_length(&tmpt, ts, ts, _state); - ae_matrix_set_length(&tmpr, 2*ts, n, _state); - - /* - * Blocked code - */ - blockstart = 0; - while(blockstart!=minmn) - { - - /* - * Determine block size - */ - blocksize = minmn-blockstart; - if( blocksize>ts ) - { - blocksize = ts; - } - rowscount = m-blockstart; - - /* - * QR decomposition of submatrix. - * Matrix is copied to temporary storage to solve - * some TLB issues arising from non-contiguous memory - * access pattern. - */ - cmatrixcopy(rowscount, blocksize, a, blockstart, blockstart, &tmpa, 0, 0, _state); - ortfac_cmatrixqrbasecase(&tmpa, rowscount, blocksize, &work, &t, &taubuf, _state); - cmatrixcopy(rowscount, blocksize, &tmpa, 0, 0, a, blockstart, blockstart, _state); - ae_v_cmove(&tau->ptr.p_complex[blockstart], 1, &taubuf.ptr.p_complex[0], 1, "N", ae_v_len(blockstart,blockstart+blocksize-1)); - - /* - * Update the rest, choose between: - * a) Level 2 algorithm (when the rest of the matrix is small enough) - * b) blocked algorithm, see algorithm 5 from 'A storage efficient WY - * representation for products of Householder transformations', - * by R. Schreiber and C. Van Loan. - */ - if( blockstart+blocksize<=n-1 ) - { - if( n-blockstart-blocksize>=2*ts ) - { - - /* - * Prepare block reflector - */ - ortfac_cmatrixblockreflector(&tmpa, &taubuf, ae_true, rowscount, blocksize, &tmpt, &work, _state); - - /* - * Multiply the rest of A by Q'. - * - * Q = E + Y*T*Y' = E + TmpA*TmpT*TmpA' - * Q' = E + Y*T'*Y' = E + TmpA*TmpT'*TmpA' - */ - cmatrixgemm(blocksize, n-blockstart-blocksize, rowscount, ae_complex_from_d(1.0), &tmpa, 0, 0, 2, a, blockstart, blockstart+blocksize, 0, ae_complex_from_d(0.0), &tmpr, 0, 0, _state); - cmatrixgemm(blocksize, n-blockstart-blocksize, blocksize, ae_complex_from_d(1.0), &tmpt, 0, 0, 2, &tmpr, 0, 0, 0, ae_complex_from_d(0.0), &tmpr, blocksize, 0, _state); - cmatrixgemm(rowscount, n-blockstart-blocksize, blocksize, ae_complex_from_d(1.0), &tmpa, 0, 0, 0, &tmpr, blocksize, 0, 0, ae_complex_from_d(1.0), a, blockstart, blockstart+blocksize, _state); - } - else - { - - /* - * Level 2 algorithm - */ - for(i=0; i<=blocksize-1; i++) - { - ae_v_cmove(&t.ptr.p_complex[1], 1, &tmpa.ptr.pp_complex[i][i], tmpa.stride, "N", ae_v_len(1,rowscount-i)); - t.ptr.p_complex[1] = ae_complex_from_i(1); - complexapplyreflectionfromtheleft(a, ae_c_conj(taubuf.ptr.p_complex[i], _state), &t, blockstart+i, m-1, blockstart+blocksize, n-1, &work, _state); - } - } - } - - /* - * Advance - */ - blockstart = blockstart+blocksize; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -LQ decomposition of a rectangular complex matrix of size MxN - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix A whose indexes range within [0..M-1, 0..N-1] - M - number of rows in matrix A. - N - number of columns in matrix A. - -Output parameters: - A - matrices Q and L in compact form - Tau - array of scalar factors which are used to form matrix Q. Array - whose indexes range within [0.. Min(M,N)-1] - -Matrix A is represented as A = LQ, where Q is an orthogonal matrix of size -MxM, L - lower triangular (or lower trapezoid) matrix of size MxN. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994 -*************************************************************************/ -void cmatrixlq(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_vector* tau, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector work; - ae_vector t; - ae_vector taubuf; - ae_int_t minmn; - ae_matrix tmpa; - ae_matrix tmpt; - ae_matrix tmpr; - ae_int_t blockstart; - ae_int_t blocksize; - ae_int_t columnscount; - ae_int_t i; - ae_int_t ts; - - ae_frame_make(_state, &_frame_block); - memset(&work, 0, sizeof(work)); - memset(&t, 0, sizeof(t)); - memset(&taubuf, 0, sizeof(taubuf)); - memset(&tmpa, 0, sizeof(tmpa)); - memset(&tmpt, 0, sizeof(tmpt)); - memset(&tmpr, 0, sizeof(tmpr)); - ae_vector_clear(tau); - ae_vector_init(&work, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&t, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&taubuf, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&tmpa, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&tmpt, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&tmpr, 0, 0, DT_COMPLEX, _state, ae_true); - - if( m<=0||n<=0 ) - { - ae_frame_leave(_state); - return; - } - ts = matrixtilesizeb(_state)/2; - minmn = ae_minint(m, n, _state); - ae_vector_set_length(&work, ae_maxint(m, n, _state)+1, _state); - ae_vector_set_length(&t, ae_maxint(m, n, _state)+1, _state); - ae_vector_set_length(tau, minmn, _state); - ae_vector_set_length(&taubuf, minmn, _state); - ae_matrix_set_length(&tmpa, ts, n, _state); - ae_matrix_set_length(&tmpt, ts, ts, _state); - ae_matrix_set_length(&tmpr, m, 2*ts, _state); - - /* - * Blocked code - */ - blockstart = 0; - while(blockstart!=minmn) - { - - /* - * Determine block size - */ - blocksize = minmn-blockstart; - if( blocksize>ts ) - { - blocksize = ts; - } - columnscount = n-blockstart; - - /* - * LQ decomposition of submatrix. - * Matrix is copied to temporary storage to solve - * some TLB issues arising from non-contiguous memory - * access pattern. - */ - cmatrixcopy(blocksize, columnscount, a, blockstart, blockstart, &tmpa, 0, 0, _state); - ortfac_cmatrixlqbasecase(&tmpa, blocksize, columnscount, &work, &t, &taubuf, _state); - cmatrixcopy(blocksize, columnscount, &tmpa, 0, 0, a, blockstart, blockstart, _state); - ae_v_cmove(&tau->ptr.p_complex[blockstart], 1, &taubuf.ptr.p_complex[0], 1, "N", ae_v_len(blockstart,blockstart+blocksize-1)); - - /* - * Update the rest, choose between: - * a) Level 2 algorithm (when the rest of the matrix is small enough) - * b) blocked algorithm, see algorithm 5 from 'A storage efficient WY - * representation for products of Householder transformations', - * by R. Schreiber and C. Van Loan. - */ - if( blockstart+blocksize<=m-1 ) - { - if( m-blockstart-blocksize>=2*ts ) - { - - /* - * Prepare block reflector - */ - ortfac_cmatrixblockreflector(&tmpa, &taubuf, ae_false, columnscount, blocksize, &tmpt, &work, _state); - - /* - * Multiply the rest of A by Q. - * - * Q = E + Y*T*Y' = E + TmpA'*TmpT*TmpA - */ - cmatrixgemm(m-blockstart-blocksize, blocksize, columnscount, ae_complex_from_d(1.0), a, blockstart+blocksize, blockstart, 0, &tmpa, 0, 0, 2, ae_complex_from_d(0.0), &tmpr, 0, 0, _state); - cmatrixgemm(m-blockstart-blocksize, blocksize, blocksize, ae_complex_from_d(1.0), &tmpr, 0, 0, 0, &tmpt, 0, 0, 0, ae_complex_from_d(0.0), &tmpr, 0, blocksize, _state); - cmatrixgemm(m-blockstart-blocksize, columnscount, blocksize, ae_complex_from_d(1.0), &tmpr, 0, blocksize, 0, &tmpa, 0, 0, 0, ae_complex_from_d(1.0), a, blockstart+blocksize, blockstart, _state); - } - else - { - - /* - * Level 2 algorithm - */ - for(i=0; i<=blocksize-1; i++) - { - ae_v_cmove(&t.ptr.p_complex[1], 1, &tmpa.ptr.pp_complex[i][i], 1, "Conj", ae_v_len(1,columnscount-i)); - t.ptr.p_complex[1] = ae_complex_from_i(1); - complexapplyreflectionfromtheright(a, taubuf.ptr.p_complex[i], &t, blockstart+blocksize, m-1, blockstart+i, n-1, &work, _state); - } - } - } - - /* - * Advance - */ - blockstart = blockstart+blocksize; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Partial unpacking of matrix Q from the QR decomposition of a matrix A - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrices Q and R in compact form. - Output of RMatrixQR subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - Tau - scalar factors which are used to form Q. - Output of the RMatrixQR subroutine. - QColumns - required number of columns of matrix Q. M>=QColumns>=0. - -Output parameters: - Q - first QColumns columns of matrix Q. - Array whose indexes range within [0..M-1, 0..QColumns-1]. - If QColumns=0, the array remains unchanged. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixqrunpackq(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* tau, - ae_int_t qcolumns, - /* Real */ ae_matrix* q, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector work; - ae_vector t; - ae_vector taubuf; - ae_int_t minmn; - ae_int_t refcnt; - ae_matrix tmpa; - ae_matrix tmpt; - ae_matrix tmpr; - ae_int_t blockstart; - ae_int_t blocksize; - ae_int_t rowscount; - ae_int_t i; - ae_int_t j; - ae_int_t ts; - - ae_frame_make(_state, &_frame_block); - memset(&work, 0, sizeof(work)); - memset(&t, 0, sizeof(t)); - memset(&taubuf, 0, sizeof(taubuf)); - memset(&tmpa, 0, sizeof(tmpa)); - memset(&tmpt, 0, sizeof(tmpt)); - memset(&tmpr, 0, sizeof(tmpr)); - ae_matrix_clear(q); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - ae_vector_init(&taubuf, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&tmpa, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&tmpt, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&tmpr, 0, 0, DT_REAL, _state, ae_true); - - ae_assert(qcolumns<=m, "UnpackQFromQR: QColumns>M!", _state); - if( (m<=0||n<=0)||qcolumns<=0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * init - */ - ts = matrixtilesizeb(_state); - minmn = ae_minint(m, n, _state); - refcnt = ae_minint(minmn, qcolumns, _state); - ae_matrix_set_length(q, m, qcolumns, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=qcolumns-1; j++) - { - if( i==j ) - { - q->ptr.pp_double[i][j] = (double)(1); - } - else - { - q->ptr.pp_double[i][j] = (double)(0); - } - } - } - ae_vector_set_length(&work, ae_maxint(m, qcolumns, _state)+1, _state); - ae_vector_set_length(&t, ae_maxint(m, qcolumns, _state)+1, _state); - ae_vector_set_length(&taubuf, minmn, _state); - ae_matrix_set_length(&tmpa, m, ts, _state); - ae_matrix_set_length(&tmpt, ts, 2*ts, _state); - ae_matrix_set_length(&tmpr, 2*ts, qcolumns, _state); - - /* - * Blocked code - */ - blockstart = ts*(refcnt/ts); - blocksize = refcnt-blockstart; - while(blockstart>=0) - { - rowscount = m-blockstart; - if( blocksize>0 ) - { - - /* - * Copy current block - */ - rmatrixcopy(rowscount, blocksize, a, blockstart, blockstart, &tmpa, 0, 0, _state); - ae_v_move(&taubuf.ptr.p_double[0], 1, &tau->ptr.p_double[blockstart], 1, ae_v_len(0,blocksize-1)); - - /* - * Update, choose between: - * a) Level 2 algorithm (when the rest of the matrix is small enough) - * b) blocked algorithm, see algorithm 5 from 'A storage efficient WY - * representation for products of Householder transformations', - * by R. Schreiber and C. Van Loan. - */ - if( qcolumns>=2*ts ) - { - - /* - * Prepare block reflector - */ - ortfac_rmatrixblockreflector(&tmpa, &taubuf, ae_true, rowscount, blocksize, &tmpt, &work, _state); - - /* - * Multiply matrix by Q. - * - * Q = E + Y*T*Y' = E + TmpA*TmpT*TmpA' - */ - rmatrixgemm(blocksize, qcolumns, rowscount, 1.0, &tmpa, 0, 0, 1, q, blockstart, 0, 0, 0.0, &tmpr, 0, 0, _state); - rmatrixgemm(blocksize, qcolumns, blocksize, 1.0, &tmpt, 0, 0, 0, &tmpr, 0, 0, 0, 0.0, &tmpr, blocksize, 0, _state); - rmatrixgemm(rowscount, qcolumns, blocksize, 1.0, &tmpa, 0, 0, 0, &tmpr, blocksize, 0, 0, 1.0, q, blockstart, 0, _state); - } - else - { - - /* - * Level 2 algorithm - */ - for(i=blocksize-1; i>=0; i--) - { - ae_v_move(&t.ptr.p_double[1], 1, &tmpa.ptr.pp_double[i][i], tmpa.stride, ae_v_len(1,rowscount-i)); - t.ptr.p_double[1] = (double)(1); - applyreflectionfromtheleft(q, taubuf.ptr.p_double[i], &t, blockstart+i, m-1, 0, qcolumns-1, &work, _state); - } - } - } - - /* - * Advance - */ - blockstart = blockstart-ts; - blocksize = ts; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Unpacking of matrix R from the QR decomposition of a matrix A - -Input parameters: - A - matrices Q and R in compact form. - Output of RMatrixQR subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - -Output parameters: - R - matrix R, array[0..M-1, 0..N-1]. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixqrunpackr(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* r, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - - ae_matrix_clear(r); - - if( m<=0||n<=0 ) - { - return; - } - k = ae_minint(m, n, _state); - ae_matrix_set_length(r, m, n, _state); - for(i=0; i<=n-1; i++) - { - r->ptr.pp_double[0][i] = (double)(0); - } - for(i=1; i<=m-1; i++) - { - ae_v_move(&r->ptr.pp_double[i][0], 1, &r->ptr.pp_double[0][0], 1, ae_v_len(0,n-1)); - } - for(i=0; i<=k-1; i++) - { - ae_v_move(&r->ptr.pp_double[i][i], 1, &a->ptr.pp_double[i][i], 1, ae_v_len(i,n-1)); - } -} - - -/************************************************************************* -Partial unpacking of matrix Q from the LQ decomposition of a matrix A - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrices L and Q in compact form. - Output of RMatrixLQ subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - Tau - scalar factors which are used to form Q. - Output of the RMatrixLQ subroutine. - QRows - required number of rows in matrix Q. N>=QRows>=0. - -Output parameters: - Q - first QRows rows of matrix Q. Array whose indexes range - within [0..QRows-1, 0..N-1]. If QRows=0, the array remains - unchanged. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixlqunpackq(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* tau, - ae_int_t qrows, - /* Real */ ae_matrix* q, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector work; - ae_vector t; - ae_vector taubuf; - ae_int_t minmn; - ae_int_t refcnt; - ae_matrix tmpa; - ae_matrix tmpt; - ae_matrix tmpr; - ae_int_t blockstart; - ae_int_t blocksize; - ae_int_t columnscount; - ae_int_t i; - ae_int_t j; - ae_int_t ts; - - ae_frame_make(_state, &_frame_block); - memset(&work, 0, sizeof(work)); - memset(&t, 0, sizeof(t)); - memset(&taubuf, 0, sizeof(taubuf)); - memset(&tmpa, 0, sizeof(tmpa)); - memset(&tmpt, 0, sizeof(tmpt)); - memset(&tmpr, 0, sizeof(tmpr)); - ae_matrix_clear(q); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - ae_vector_init(&taubuf, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&tmpa, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&tmpt, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&tmpr, 0, 0, DT_REAL, _state, ae_true); - - ae_assert(qrows<=n, "RMatrixLQUnpackQ: QRows>N!", _state); - if( (m<=0||n<=0)||qrows<=0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * init - */ - ts = matrixtilesizeb(_state); - minmn = ae_minint(m, n, _state); - refcnt = ae_minint(minmn, qrows, _state); - ae_vector_set_length(&work, ae_maxint(m, n, _state)+1, _state); - ae_vector_set_length(&t, ae_maxint(m, n, _state)+1, _state); - ae_vector_set_length(&taubuf, minmn, _state); - ae_matrix_set_length(&tmpa, ts, n, _state); - ae_matrix_set_length(&tmpt, ts, 2*ts, _state); - ae_matrix_set_length(&tmpr, qrows, 2*ts, _state); - ae_matrix_set_length(q, qrows, n, _state); - for(i=0; i<=qrows-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - q->ptr.pp_double[i][j] = (double)(1); - } - else - { - q->ptr.pp_double[i][j] = (double)(0); - } - } - } - - /* - * Blocked code - */ - blockstart = ts*(refcnt/ts); - blocksize = refcnt-blockstart; - while(blockstart>=0) - { - columnscount = n-blockstart; - if( blocksize>0 ) - { - - /* - * Copy submatrix - */ - rmatrixcopy(blocksize, columnscount, a, blockstart, blockstart, &tmpa, 0, 0, _state); - ae_v_move(&taubuf.ptr.p_double[0], 1, &tau->ptr.p_double[blockstart], 1, ae_v_len(0,blocksize-1)); - - /* - * Update matrix, choose between: - * a) Level 2 algorithm (when the rest of the matrix is small enough) - * b) blocked algorithm, see algorithm 5 from 'A storage efficient WY - * representation for products of Householder transformations', - * by R. Schreiber and C. Van Loan. - */ - if( qrows>=2*ts ) - { - - /* - * Prepare block reflector - */ - ortfac_rmatrixblockreflector(&tmpa, &taubuf, ae_false, columnscount, blocksize, &tmpt, &work, _state); - - /* - * Multiply the rest of A by Q'. - * - * Q' = E + Y*T'*Y' = E + TmpA'*TmpT'*TmpA - */ - rmatrixgemm(qrows, blocksize, columnscount, 1.0, q, 0, blockstart, 0, &tmpa, 0, 0, 1, 0.0, &tmpr, 0, 0, _state); - rmatrixgemm(qrows, blocksize, blocksize, 1.0, &tmpr, 0, 0, 0, &tmpt, 0, 0, 1, 0.0, &tmpr, 0, blocksize, _state); - rmatrixgemm(qrows, columnscount, blocksize, 1.0, &tmpr, 0, blocksize, 0, &tmpa, 0, 0, 0, 1.0, q, 0, blockstart, _state); - } - else - { - - /* - * Level 2 algorithm - */ - for(i=blocksize-1; i>=0; i--) - { - ae_v_move(&t.ptr.p_double[1], 1, &tmpa.ptr.pp_double[i][i], 1, ae_v_len(1,columnscount-i)); - t.ptr.p_double[1] = (double)(1); - applyreflectionfromtheright(q, taubuf.ptr.p_double[i], &t, 0, qrows-1, blockstart+i, n-1, &work, _state); - } - } - } - - /* - * Advance - */ - blockstart = blockstart-ts; - blocksize = ts; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Unpacking of matrix L from the LQ decomposition of a matrix A - -Input parameters: - A - matrices Q and L in compact form. - Output of RMatrixLQ subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - -Output parameters: - L - matrix L, array[0..M-1, 0..N-1]. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixlqunpackl(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* l, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - - ae_matrix_clear(l); - - if( m<=0||n<=0 ) - { - return; - } - ae_matrix_set_length(l, m, n, _state); - for(i=0; i<=n-1; i++) - { - l->ptr.pp_double[0][i] = (double)(0); - } - for(i=1; i<=m-1; i++) - { - ae_v_move(&l->ptr.pp_double[i][0], 1, &l->ptr.pp_double[0][0], 1, ae_v_len(0,n-1)); - } - for(i=0; i<=m-1; i++) - { - k = ae_minint(i, n-1, _state); - ae_v_move(&l->ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k)); - } -} - - -/************************************************************************* -Partial unpacking of matrix Q from QR decomposition of a complex matrix A. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrices Q and R in compact form. - Output of CMatrixQR subroutine . - M - number of rows in matrix A. M>=0. - N - number of columns in matrix A. N>=0. - Tau - scalar factors which are used to form Q. - Output of CMatrixQR subroutine . - QColumns - required number of columns in matrix Q. M>=QColumns>=0. - -Output parameters: - Q - first QColumns columns of matrix Q. - Array whose index ranges within [0..M-1, 0..QColumns-1]. - If QColumns=0, array isn't changed. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixqrunpackq(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_vector* tau, - ae_int_t qcolumns, - /* Complex */ ae_matrix* q, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector work; - ae_vector t; - ae_vector taubuf; - ae_int_t minmn; - ae_int_t refcnt; - ae_matrix tmpa; - ae_matrix tmpt; - ae_matrix tmpr; - ae_int_t blockstart; - ae_int_t blocksize; - ae_int_t rowscount; - ae_int_t i; - ae_int_t j; - ae_int_t ts; - - ae_frame_make(_state, &_frame_block); - memset(&work, 0, sizeof(work)); - memset(&t, 0, sizeof(t)); - memset(&taubuf, 0, sizeof(taubuf)); - memset(&tmpa, 0, sizeof(tmpa)); - memset(&tmpt, 0, sizeof(tmpt)); - memset(&tmpr, 0, sizeof(tmpr)); - ae_matrix_clear(q); - ae_vector_init(&work, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&t, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&taubuf, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&tmpa, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&tmpt, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&tmpr, 0, 0, DT_COMPLEX, _state, ae_true); - - ae_assert(qcolumns<=m, "UnpackQFromQR: QColumns>M!", _state); - if( m<=0||n<=0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * init - */ - ts = matrixtilesizeb(_state)/2; - minmn = ae_minint(m, n, _state); - refcnt = ae_minint(minmn, qcolumns, _state); - ae_vector_set_length(&work, ae_maxint(m, n, _state)+1, _state); - ae_vector_set_length(&t, ae_maxint(m, n, _state)+1, _state); - ae_vector_set_length(&taubuf, minmn, _state); - ae_matrix_set_length(&tmpa, m, ts, _state); - ae_matrix_set_length(&tmpt, ts, ts, _state); - ae_matrix_set_length(&tmpr, 2*ts, qcolumns, _state); - ae_matrix_set_length(q, m, qcolumns, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=qcolumns-1; j++) - { - if( i==j ) - { - q->ptr.pp_complex[i][j] = ae_complex_from_i(1); - } - else - { - q->ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - } - - /* - * Blocked code - */ - blockstart = ts*(refcnt/ts); - blocksize = refcnt-blockstart; - while(blockstart>=0) - { - rowscount = m-blockstart; - if( blocksize>0 ) - { - - /* - * QR decomposition of submatrix. - * Matrix is copied to temporary storage to solve - * some TLB issues arising from non-contiguous memory - * access pattern. - */ - cmatrixcopy(rowscount, blocksize, a, blockstart, blockstart, &tmpa, 0, 0, _state); - ae_v_cmove(&taubuf.ptr.p_complex[0], 1, &tau->ptr.p_complex[blockstart], 1, "N", ae_v_len(0,blocksize-1)); - - /* - * Update matrix, choose between: - * a) Level 2 algorithm (when the rest of the matrix is small enough) - * b) blocked algorithm, see algorithm 5 from 'A storage efficient WY - * representation for products of Householder transformations', - * by R. Schreiber and C. Van Loan. - */ - if( qcolumns>=2*ts ) - { - - /* - * Prepare block reflector - */ - ortfac_cmatrixblockreflector(&tmpa, &taubuf, ae_true, rowscount, blocksize, &tmpt, &work, _state); - - /* - * Multiply the rest of A by Q. - * - * Q = E + Y*T*Y' = E + TmpA*TmpT*TmpA' - */ - cmatrixgemm(blocksize, qcolumns, rowscount, ae_complex_from_d(1.0), &tmpa, 0, 0, 2, q, blockstart, 0, 0, ae_complex_from_d(0.0), &tmpr, 0, 0, _state); - cmatrixgemm(blocksize, qcolumns, blocksize, ae_complex_from_d(1.0), &tmpt, 0, 0, 0, &tmpr, 0, 0, 0, ae_complex_from_d(0.0), &tmpr, blocksize, 0, _state); - cmatrixgemm(rowscount, qcolumns, blocksize, ae_complex_from_d(1.0), &tmpa, 0, 0, 0, &tmpr, blocksize, 0, 0, ae_complex_from_d(1.0), q, blockstart, 0, _state); - } - else - { - - /* - * Level 2 algorithm - */ - for(i=blocksize-1; i>=0; i--) - { - ae_v_cmove(&t.ptr.p_complex[1], 1, &tmpa.ptr.pp_complex[i][i], tmpa.stride, "N", ae_v_len(1,rowscount-i)); - t.ptr.p_complex[1] = ae_complex_from_i(1); - complexapplyreflectionfromtheleft(q, taubuf.ptr.p_complex[i], &t, blockstart+i, m-1, 0, qcolumns-1, &work, _state); - } - } - } - - /* - * Advance - */ - blockstart = blockstart-ts; - blocksize = ts; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Unpacking of matrix R from the QR decomposition of a matrix A - -Input parameters: - A - matrices Q and R in compact form. - Output of CMatrixQR subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - -Output parameters: - R - matrix R, array[0..M-1, 0..N-1]. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixqrunpackr(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* r, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - - ae_matrix_clear(r); - - if( m<=0||n<=0 ) - { - return; - } - k = ae_minint(m, n, _state); - ae_matrix_set_length(r, m, n, _state); - for(i=0; i<=n-1; i++) - { - r->ptr.pp_complex[0][i] = ae_complex_from_i(0); - } - for(i=1; i<=m-1; i++) - { - ae_v_cmove(&r->ptr.pp_complex[i][0], 1, &r->ptr.pp_complex[0][0], 1, "N", ae_v_len(0,n-1)); - } - for(i=0; i<=k-1; i++) - { - ae_v_cmove(&r->ptr.pp_complex[i][i], 1, &a->ptr.pp_complex[i][i], 1, "N", ae_v_len(i,n-1)); - } -} - - -/************************************************************************* -Partial unpacking of matrix Q from LQ decomposition of a complex matrix A. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrices Q and R in compact form. - Output of CMatrixLQ subroutine . - M - number of rows in matrix A. M>=0. - N - number of columns in matrix A. N>=0. - Tau - scalar factors which are used to form Q. - Output of CMatrixLQ subroutine . - QRows - required number of rows in matrix Q. N>=QColumns>=0. - -Output parameters: - Q - first QRows rows of matrix Q. - Array whose index ranges within [0..QRows-1, 0..N-1]. - If QRows=0, array isn't changed. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixlqunpackq(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_vector* tau, - ae_int_t qrows, - /* Complex */ ae_matrix* q, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector work; - ae_vector t; - ae_vector taubuf; - ae_int_t minmn; - ae_int_t refcnt; - ae_matrix tmpa; - ae_matrix tmpt; - ae_matrix tmpr; - ae_int_t blockstart; - ae_int_t blocksize; - ae_int_t columnscount; - ae_int_t i; - ae_int_t j; - ae_int_t ts; - - ae_frame_make(_state, &_frame_block); - memset(&work, 0, sizeof(work)); - memset(&t, 0, sizeof(t)); - memset(&taubuf, 0, sizeof(taubuf)); - memset(&tmpa, 0, sizeof(tmpa)); - memset(&tmpt, 0, sizeof(tmpt)); - memset(&tmpr, 0, sizeof(tmpr)); - ae_matrix_clear(q); - ae_vector_init(&work, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&t, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&taubuf, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&tmpa, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&tmpt, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&tmpr, 0, 0, DT_COMPLEX, _state, ae_true); - - if( m<=0||n<=0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Init - */ - ts = matrixtilesizeb(_state)/2; - minmn = ae_minint(m, n, _state); - refcnt = ae_minint(minmn, qrows, _state); - ae_vector_set_length(&work, ae_maxint(m, n, _state)+1, _state); - ae_vector_set_length(&t, ae_maxint(m, n, _state)+1, _state); - ae_vector_set_length(&taubuf, minmn, _state); - ae_matrix_set_length(&tmpa, ts, n, _state); - ae_matrix_set_length(&tmpt, ts, ts, _state); - ae_matrix_set_length(&tmpr, qrows, 2*ts, _state); - ae_matrix_set_length(q, qrows, n, _state); - for(i=0; i<=qrows-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - q->ptr.pp_complex[i][j] = ae_complex_from_i(1); - } - else - { - q->ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - } - - /* - * Blocked code - */ - blockstart = ts*(refcnt/ts); - blocksize = refcnt-blockstart; - while(blockstart>=0) - { - columnscount = n-blockstart; - if( blocksize>0 ) - { - - /* - * LQ decomposition of submatrix. - * Matrix is copied to temporary storage to solve - * some TLB issues arising from non-contiguous memory - * access pattern. - */ - cmatrixcopy(blocksize, columnscount, a, blockstart, blockstart, &tmpa, 0, 0, _state); - ae_v_cmove(&taubuf.ptr.p_complex[0], 1, &tau->ptr.p_complex[blockstart], 1, "N", ae_v_len(0,blocksize-1)); - - /* - * Update matrix, choose between: - * a) Level 2 algorithm (when the rest of the matrix is small enough) - * b) blocked algorithm, see algorithm 5 from 'A storage efficient WY - * representation for products of Householder transformations', - * by R. Schreiber and C. Van Loan. - */ - if( qrows>=2*ts ) - { - - /* - * Prepare block reflector - */ - ortfac_cmatrixblockreflector(&tmpa, &taubuf, ae_false, columnscount, blocksize, &tmpt, &work, _state); - - /* - * Multiply the rest of A by Q'. - * - * Q' = E + Y*T'*Y' = E + TmpA'*TmpT'*TmpA - */ - cmatrixgemm(qrows, blocksize, columnscount, ae_complex_from_d(1.0), q, 0, blockstart, 0, &tmpa, 0, 0, 2, ae_complex_from_d(0.0), &tmpr, 0, 0, _state); - cmatrixgemm(qrows, blocksize, blocksize, ae_complex_from_d(1.0), &tmpr, 0, 0, 0, &tmpt, 0, 0, 2, ae_complex_from_d(0.0), &tmpr, 0, blocksize, _state); - cmatrixgemm(qrows, columnscount, blocksize, ae_complex_from_d(1.0), &tmpr, 0, blocksize, 0, &tmpa, 0, 0, 0, ae_complex_from_d(1.0), q, 0, blockstart, _state); - } - else - { - - /* - * Level 2 algorithm - */ - for(i=blocksize-1; i>=0; i--) - { - ae_v_cmove(&t.ptr.p_complex[1], 1, &tmpa.ptr.pp_complex[i][i], 1, "Conj", ae_v_len(1,columnscount-i)); - t.ptr.p_complex[1] = ae_complex_from_i(1); - complexapplyreflectionfromtheright(q, ae_c_conj(taubuf.ptr.p_complex[i], _state), &t, 0, qrows-1, blockstart+i, n-1, &work, _state); - } - } - } - - /* - * Advance - */ - blockstart = blockstart-ts; - blocksize = ts; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Unpacking of matrix L from the LQ decomposition of a matrix A - -Input parameters: - A - matrices Q and L in compact form. - Output of CMatrixLQ subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - -Output parameters: - L - matrix L, array[0..M-1, 0..N-1]. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixlqunpackl(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* l, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - - ae_matrix_clear(l); - - if( m<=0||n<=0 ) - { - return; - } - ae_matrix_set_length(l, m, n, _state); - for(i=0; i<=n-1; i++) - { - l->ptr.pp_complex[0][i] = ae_complex_from_i(0); - } - for(i=1; i<=m-1; i++) - { - ae_v_cmove(&l->ptr.pp_complex[i][0], 1, &l->ptr.pp_complex[0][0], 1, "N", ae_v_len(0,n-1)); - } - for(i=0; i<=m-1; i++) - { - k = ae_minint(i, n-1, _state); - ae_v_cmove(&l->ptr.pp_complex[i][0], 1, &a->ptr.pp_complex[i][0], 1, "N", ae_v_len(0,k)); - } -} - - -/************************************************************************* -Base case for real QR - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994. - Sergey Bochkanov, ALGLIB project, translation from FORTRAN to - pseudocode, 2007-2010. -*************************************************************************/ -void rmatrixqrbasecase(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* work, - /* Real */ ae_vector* t, - /* Real */ ae_vector* tau, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - ae_int_t minmn; - double tmp; - - - minmn = ae_minint(m, n, _state); - - /* - * Test the input arguments - */ - k = minmn; - for(i=0; i<=k-1; i++) - { - - /* - * Generate elementary reflector H(i) to annihilate A(i+1:m,i) - */ - ae_v_move(&t->ptr.p_double[1], 1, &a->ptr.pp_double[i][i], a->stride, ae_v_len(1,m-i)); - generatereflection(t, m-i, &tmp, _state); - tau->ptr.p_double[i] = tmp; - ae_v_move(&a->ptr.pp_double[i][i], a->stride, &t->ptr.p_double[1], 1, ae_v_len(i,m-1)); - t->ptr.p_double[1] = (double)(1); - if( iptr.p_double[i], t, i, m-1, i+1, n-1, work, _state); - } - } -} - - -/************************************************************************* -Base case for real LQ - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994. - Sergey Bochkanov, ALGLIB project, translation from FORTRAN to - pseudocode, 2007-2010. -*************************************************************************/ -void rmatrixlqbasecase(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* work, - /* Real */ ae_vector* t, - /* Real */ ae_vector* tau, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - double tmp; - - - k = ae_minint(m, n, _state); - for(i=0; i<=k-1; i++) - { - - /* - * Generate elementary reflector H(i) to annihilate A(i,i+1:n-1) - */ - ae_v_move(&t->ptr.p_double[1], 1, &a->ptr.pp_double[i][i], 1, ae_v_len(1,n-i)); - generatereflection(t, n-i, &tmp, _state); - tau->ptr.p_double[i] = tmp; - ae_v_move(&a->ptr.pp_double[i][i], 1, &t->ptr.p_double[1], 1, ae_v_len(i,n-1)); - t->ptr.p_double[1] = (double)(1); - if( iptr.p_double[i], t, i+1, m-1, i, n-1, work, _state); - } - } -} - - -/************************************************************************* -Reduction of a rectangular matrix to bidiagonal form - -The algorithm reduces the rectangular matrix A to bidiagonal form by -orthogonal transformations P and Q: A = Q*B*(P^T). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - source matrix. array[0..M-1, 0..N-1] - M - number of rows in matrix A. - N - number of columns in matrix A. - -Output parameters: - A - matrices Q, B, P in compact form (see below). - TauQ - scalar factors which are used to form matrix Q. - TauP - scalar factors which are used to form matrix P. - -The main diagonal and one of the secondary diagonals of matrix A are -replaced with bidiagonal matrix B. Other elements contain elementary -reflections which form MxM matrix Q and NxN matrix P, respectively. - -If M>=N, B is the upper bidiagonal MxN matrix and is stored in the -corresponding elements of matrix A. Matrix Q is represented as a -product of elementary reflections Q = H(0)*H(1)*...*H(n-1), where -H(i) = 1-tau*v*v'. Here tau is a scalar which is stored in TauQ[i], and -vector v has the following structure: v(0:i-1)=0, v(i)=1, v(i+1:m-1) is -stored in elements A(i+1:m-1,i). Matrix P is as follows: P = -G(0)*G(1)*...*G(n-2), where G(i) = 1 - tau*u*u'. Tau is stored in TauP[i], -u(0:i)=0, u(i+1)=1, u(i+2:n-1) is stored in elements A(i,i+2:n-1). - -If M n): m=5, n=6 (m < n): - -( d e u1 u1 u1 ) ( d u1 u1 u1 u1 u1 ) -( v1 d e u2 u2 ) ( e d u2 u2 u2 u2 ) -( v1 v2 d e u3 ) ( v1 e d u3 u3 u3 ) -( v1 v2 v3 d e ) ( v1 v2 e d u4 u4 ) -( v1 v2 v3 v4 d ) ( v1 v2 v3 e d u5 ) -( v1 v2 v3 v4 v5 ) - -Here vi and ui are vectors which form H(i) and G(i), and d and e - -are the diagonal and off-diagonal elements of matrix B. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994. - Sergey Bochkanov, ALGLIB project, translation from FORTRAN to - pseudocode, 2007-2010. -*************************************************************************/ -void rmatrixbd(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* tauq, - /* Real */ ae_vector* taup, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector work; - ae_vector t; - ae_int_t maxmn; - ae_int_t i; - double ltau; - - ae_frame_make(_state, &_frame_block); - memset(&work, 0, sizeof(work)); - memset(&t, 0, sizeof(t)); - ae_vector_clear(tauq); - ae_vector_clear(taup); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - - - /* - * Prepare - */ - if( n<=0||m<=0 ) - { - ae_frame_leave(_state); - return; - } - maxmn = ae_maxint(m, n, _state); - ae_vector_set_length(&work, maxmn+1, _state); - ae_vector_set_length(&t, maxmn+1, _state); - if( m>=n ) - { - ae_vector_set_length(tauq, n, _state); - ae_vector_set_length(taup, n, _state); - for(i=0; i<=n-1; i++) - { - tauq->ptr.p_double[i] = 0.0; - taup->ptr.p_double[i] = 0.0; - } - } - else - { - ae_vector_set_length(tauq, m, _state); - ae_vector_set_length(taup, m, _state); - for(i=0; i<=m-1; i++) - { - tauq->ptr.p_double[i] = 0.0; - taup->ptr.p_double[i] = 0.0; - } - } - - /* - * Try to use MKL code - * - * NOTE: buffers Work[] and T[] are used for temporary storage of diagonals; - * because they are present in A[], we do not use them. - */ - if( rmatrixbdmkl(a, m, n, &work, &t, tauq, taup, _state) ) - { - ae_frame_leave(_state); - return; - } - - /* - * ALGLIB code - */ - if( m>=n ) - { - - /* - * Reduce to upper bidiagonal form - */ - for(i=0; i<=n-1; i++) - { - - /* - * Generate elementary reflector H(i) to annihilate A(i+1:m-1,i) - */ - ae_v_move(&t.ptr.p_double[1], 1, &a->ptr.pp_double[i][i], a->stride, ae_v_len(1,m-i)); - generatereflection(&t, m-i, <au, _state); - tauq->ptr.p_double[i] = ltau; - ae_v_move(&a->ptr.pp_double[i][i], a->stride, &t.ptr.p_double[1], 1, ae_v_len(i,m-1)); - t.ptr.p_double[1] = (double)(1); - - /* - * Apply H(i) to A(i:m-1,i+1:n-1) from the left - */ - applyreflectionfromtheleft(a, ltau, &t, i, m-1, i+1, n-1, &work, _state); - if( iptr.pp_double[i][i+1], 1, ae_v_len(1,n-i-1)); - generatereflection(&t, n-1-i, <au, _state); - taup->ptr.p_double[i] = ltau; - ae_v_move(&a->ptr.pp_double[i][i+1], 1, &t.ptr.p_double[1], 1, ae_v_len(i+1,n-1)); - t.ptr.p_double[1] = (double)(1); - - /* - * Apply G(i) to A(i+1:m-1,i+1:n-1) from the right - */ - applyreflectionfromtheright(a, ltau, &t, i+1, m-1, i+1, n-1, &work, _state); - } - else - { - taup->ptr.p_double[i] = (double)(0); - } - } - } - else - { - - /* - * Reduce to lower bidiagonal form - */ - for(i=0; i<=m-1; i++) - { - - /* - * Generate elementary reflector G(i) to annihilate A(i,i+1:n-1) - */ - ae_v_move(&t.ptr.p_double[1], 1, &a->ptr.pp_double[i][i], 1, ae_v_len(1,n-i)); - generatereflection(&t, n-i, <au, _state); - taup->ptr.p_double[i] = ltau; - ae_v_move(&a->ptr.pp_double[i][i], 1, &t.ptr.p_double[1], 1, ae_v_len(i,n-1)); - t.ptr.p_double[1] = (double)(1); - - /* - * Apply G(i) to A(i+1:m-1,i:n-1) from the right - */ - applyreflectionfromtheright(a, ltau, &t, i+1, m-1, i, n-1, &work, _state); - if( iptr.pp_double[i+1][i], a->stride, ae_v_len(1,m-1-i)); - generatereflection(&t, m-1-i, <au, _state); - tauq->ptr.p_double[i] = ltau; - ae_v_move(&a->ptr.pp_double[i+1][i], a->stride, &t.ptr.p_double[1], 1, ae_v_len(i+1,m-1)); - t.ptr.p_double[1] = (double)(1); - - /* - * Apply H(i) to A(i+1:m-1,i+1:n-1) from the left - */ - applyreflectionfromtheleft(a, ltau, &t, i+1, m-1, i+1, n-1, &work, _state); - } - else - { - tauq->ptr.p_double[i] = (double)(0); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Unpacking matrix Q which reduces a matrix to bidiagonal form. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - QP - matrices Q and P in compact form. - Output of ToBidiagonal subroutine. - M - number of rows in matrix A. - N - number of columns in matrix A. - TAUQ - scalar factors which are used to form Q. - Output of ToBidiagonal subroutine. - QColumns - required number of columns in matrix Q. - M>=QColumns>=0. - -Output parameters: - Q - first QColumns columns of matrix Q. - Array[0..M-1, 0..QColumns-1] - If QColumns=0, the array is not modified. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixbdunpackq(/* Real */ ae_matrix* qp, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* tauq, - ae_int_t qcolumns, - /* Real */ ae_matrix* q, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(q); - - ae_assert(qcolumns<=m, "RMatrixBDUnpackQ: QColumns>M!", _state); - ae_assert(qcolumns>=0, "RMatrixBDUnpackQ: QColumns<0!", _state); - if( (m==0||n==0)||qcolumns==0 ) - { - return; - } - - /* - * prepare Q - */ - ae_matrix_set_length(q, m, qcolumns, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=qcolumns-1; j++) - { - if( i==j ) - { - q->ptr.pp_double[i][j] = (double)(1); - } - else - { - q->ptr.pp_double[i][j] = (double)(0); - } - } - } - - /* - * Calculate - */ - rmatrixbdmultiplybyq(qp, m, n, tauq, q, m, qcolumns, ae_false, ae_false, _state); -} - - -/************************************************************************* -Multiplication by matrix Q which reduces matrix A to bidiagonal form. - -The algorithm allows pre- or post-multiply by Q or Q'. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - QP - matrices Q and P in compact form. - Output of ToBidiagonal subroutine. - M - number of rows in matrix A. - N - number of columns in matrix A. - TAUQ - scalar factors which are used to form Q. - Output of ToBidiagonal subroutine. - Z - multiplied matrix. - array[0..ZRows-1,0..ZColumns-1] - ZRows - number of rows in matrix Z. If FromTheRight=False, - ZRows=M, otherwise ZRows can be arbitrary. - ZColumns - number of columns in matrix Z. If FromTheRight=True, - ZColumns=M, otherwise ZColumns can be arbitrary. - FromTheRight - pre- or post-multiply. - DoTranspose - multiply by Q or Q'. - -Output parameters: - Z - product of Z and Q. - Array[0..ZRows-1,0..ZColumns-1] - If ZRows=0 or ZColumns=0, the array is not modified. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixbdmultiplybyq(/* Real */ ae_matrix* qp, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* tauq, - /* Real */ ae_matrix* z, - ae_int_t zrows, - ae_int_t zcolumns, - ae_bool fromtheright, - ae_bool dotranspose, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t i1; - ae_int_t i2; - ae_int_t istep; - ae_vector v; - ae_vector work; - ae_vector dummy; - ae_int_t mx; - - ae_frame_make(_state, &_frame_block); - memset(&v, 0, sizeof(v)); - memset(&work, 0, sizeof(work)); - memset(&dummy, 0, sizeof(dummy)); - ae_vector_init(&v, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dummy, 0, DT_REAL, _state, ae_true); - - if( ((m<=0||n<=0)||zrows<=0)||zcolumns<=0 ) - { - ae_frame_leave(_state); - return; - } - ae_assert((fromtheright&&zcolumns==m)||(!fromtheright&&zrows==m), "RMatrixBDMultiplyByQ: incorrect Z size!", _state); - - /* - * Try to use MKL code - */ - if( rmatrixbdmultiplybymkl(qp, m, n, tauq, &dummy, z, zrows, zcolumns, ae_true, fromtheright, dotranspose, _state) ) - { - ae_frame_leave(_state); - return; - } - - /* - * init - */ - mx = ae_maxint(m, n, _state); - mx = ae_maxint(mx, zrows, _state); - mx = ae_maxint(mx, zcolumns, _state); - ae_vector_set_length(&v, mx+1, _state); - ae_vector_set_length(&work, mx+1, _state); - if( m>=n ) - { - - /* - * setup - */ - if( fromtheright ) - { - i1 = 0; - i2 = n-1; - istep = 1; - } - else - { - i1 = n-1; - i2 = 0; - istep = -1; - } - if( dotranspose ) - { - i = i1; - i1 = i2; - i2 = i; - istep = -istep; - } - - /* - * Process - */ - i = i1; - do - { - ae_v_move(&v.ptr.p_double[1], 1, &qp->ptr.pp_double[i][i], qp->stride, ae_v_len(1,m-i)); - v.ptr.p_double[1] = (double)(1); - if( fromtheright ) - { - applyreflectionfromtheright(z, tauq->ptr.p_double[i], &v, 0, zrows-1, i, m-1, &work, _state); - } - else - { - applyreflectionfromtheleft(z, tauq->ptr.p_double[i], &v, i, m-1, 0, zcolumns-1, &work, _state); - } - i = i+istep; - } - while(i!=i2+istep); - } - else - { - - /* - * setup - */ - if( fromtheright ) - { - i1 = 0; - i2 = m-2; - istep = 1; - } - else - { - i1 = m-2; - i2 = 0; - istep = -1; - } - if( dotranspose ) - { - i = i1; - i1 = i2; - i2 = i; - istep = -istep; - } - - /* - * Process - */ - if( m-1>0 ) - { - i = i1; - do - { - ae_v_move(&v.ptr.p_double[1], 1, &qp->ptr.pp_double[i+1][i], qp->stride, ae_v_len(1,m-i-1)); - v.ptr.p_double[1] = (double)(1); - if( fromtheright ) - { - applyreflectionfromtheright(z, tauq->ptr.p_double[i], &v, 0, zrows-1, i+1, m-1, &work, _state); - } - else - { - applyreflectionfromtheleft(z, tauq->ptr.p_double[i], &v, i+1, m-1, 0, zcolumns-1, &work, _state); - } - i = i+istep; - } - while(i!=i2+istep); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Unpacking matrix P which reduces matrix A to bidiagonal form. -The subroutine returns transposed matrix P. - -Input parameters: - QP - matrices Q and P in compact form. - Output of ToBidiagonal subroutine. - M - number of rows in matrix A. - N - number of columns in matrix A. - TAUP - scalar factors which are used to form P. - Output of ToBidiagonal subroutine. - PTRows - required number of rows of matrix P^T. N >= PTRows >= 0. - -Output parameters: - PT - first PTRows columns of matrix P^T - Array[0..PTRows-1, 0..N-1] - If PTRows=0, the array is not modified. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixbdunpackpt(/* Real */ ae_matrix* qp, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* taup, - ae_int_t ptrows, - /* Real */ ae_matrix* pt, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(pt); - - ae_assert(ptrows<=n, "RMatrixBDUnpackPT: PTRows>N!", _state); - ae_assert(ptrows>=0, "RMatrixBDUnpackPT: PTRows<0!", _state); - if( (m==0||n==0)||ptrows==0 ) - { - return; - } - - /* - * prepare PT - */ - ae_matrix_set_length(pt, ptrows, n, _state); - for(i=0; i<=ptrows-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - pt->ptr.pp_double[i][j] = (double)(1); - } - else - { - pt->ptr.pp_double[i][j] = (double)(0); - } - } - } - - /* - * Calculate - */ - rmatrixbdmultiplybyp(qp, m, n, taup, pt, ptrows, n, ae_true, ae_true, _state); -} - - -/************************************************************************* -Multiplication by matrix P which reduces matrix A to bidiagonal form. - -The algorithm allows pre- or post-multiply by P or P'. - -Input parameters: - QP - matrices Q and P in compact form. - Output of RMatrixBD subroutine. - M - number of rows in matrix A. - N - number of columns in matrix A. - TAUP - scalar factors which are used to form P. - Output of RMatrixBD subroutine. - Z - multiplied matrix. - Array whose indexes range within [0..ZRows-1,0..ZColumns-1]. - ZRows - number of rows in matrix Z. If FromTheRight=False, - ZRows=N, otherwise ZRows can be arbitrary. - ZColumns - number of columns in matrix Z. If FromTheRight=True, - ZColumns=N, otherwise ZColumns can be arbitrary. - FromTheRight - pre- or post-multiply. - DoTranspose - multiply by P or P'. - -Output parameters: - Z - product of Z and P. - Array whose indexes range within [0..ZRows-1,0..ZColumns-1]. - If ZRows=0 or ZColumns=0, the array is not modified. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixbdmultiplybyp(/* Real */ ae_matrix* qp, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* taup, - /* Real */ ae_matrix* z, - ae_int_t zrows, - ae_int_t zcolumns, - ae_bool fromtheright, - ae_bool dotranspose, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_vector v; - ae_vector work; - ae_vector dummy; - ae_int_t mx; - ae_int_t i1; - ae_int_t i2; - ae_int_t istep; - - ae_frame_make(_state, &_frame_block); - memset(&v, 0, sizeof(v)); - memset(&work, 0, sizeof(work)); - memset(&dummy, 0, sizeof(dummy)); - ae_vector_init(&v, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dummy, 0, DT_REAL, _state, ae_true); - - if( ((m<=0||n<=0)||zrows<=0)||zcolumns<=0 ) - { - ae_frame_leave(_state); - return; - } - ae_assert((fromtheright&&zcolumns==n)||(!fromtheright&&zrows==n), "RMatrixBDMultiplyByP: incorrect Z size!", _state); - - /* - * init - */ - mx = ae_maxint(m, n, _state); - mx = ae_maxint(mx, zrows, _state); - mx = ae_maxint(mx, zcolumns, _state); - ae_vector_set_length(&v, mx+1, _state); - ae_vector_set_length(&work, mx+1, _state); - if( m>=n ) - { - - /* - * setup - */ - if( fromtheright ) - { - i1 = n-2; - i2 = 0; - istep = -1; - } - else - { - i1 = 0; - i2 = n-2; - istep = 1; - } - if( !dotranspose ) - { - i = i1; - i1 = i2; - i2 = i; - istep = -istep; - } - - /* - * Process - */ - if( n-1>0 ) - { - i = i1; - do - { - ae_v_move(&v.ptr.p_double[1], 1, &qp->ptr.pp_double[i][i+1], 1, ae_v_len(1,n-1-i)); - v.ptr.p_double[1] = (double)(1); - if( fromtheright ) - { - applyreflectionfromtheright(z, taup->ptr.p_double[i], &v, 0, zrows-1, i+1, n-1, &work, _state); - } - else - { - applyreflectionfromtheleft(z, taup->ptr.p_double[i], &v, i+1, n-1, 0, zcolumns-1, &work, _state); - } - i = i+istep; - } - while(i!=i2+istep); - } - } - else - { - - /* - * setup - */ - if( fromtheright ) - { - i1 = m-1; - i2 = 0; - istep = -1; - } - else - { - i1 = 0; - i2 = m-1; - istep = 1; - } - if( !dotranspose ) - { - i = i1; - i1 = i2; - i2 = i; - istep = -istep; - } - - /* - * Process - */ - i = i1; - do - { - ae_v_move(&v.ptr.p_double[1], 1, &qp->ptr.pp_double[i][i], 1, ae_v_len(1,n-i)); - v.ptr.p_double[1] = (double)(1); - if( fromtheright ) - { - applyreflectionfromtheright(z, taup->ptr.p_double[i], &v, 0, zrows-1, i, n-1, &work, _state); - } - else - { - applyreflectionfromtheleft(z, taup->ptr.p_double[i], &v, i, n-1, 0, zcolumns-1, &work, _state); - } - i = i+istep; - } - while(i!=i2+istep); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Unpacking of the main and secondary diagonals of bidiagonal decomposition -of matrix A. - -Input parameters: - B - output of RMatrixBD subroutine. - M - number of rows in matrix B. - N - number of columns in matrix B. - -Output parameters: - IsUpper - True, if the matrix is upper bidiagonal. - otherwise IsUpper is False. - D - the main diagonal. - Array whose index ranges within [0..Min(M,N)-1]. - E - the secondary diagonal (upper or lower, depending on - the value of IsUpper). - Array index ranges within [0..Min(M,N)-1], the last - element is not used. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixbdunpackdiagonals(/* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t n, - ae_bool* isupper, - /* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_state *_state) -{ - ae_int_t i; - - *isupper = ae_false; - ae_vector_clear(d); - ae_vector_clear(e); - - *isupper = m>=n; - if( m<=0||n<=0 ) - { - return; - } - if( *isupper ) - { - ae_vector_set_length(d, n, _state); - ae_vector_set_length(e, n, _state); - for(i=0; i<=n-2; i++) - { - d->ptr.p_double[i] = b->ptr.pp_double[i][i]; - e->ptr.p_double[i] = b->ptr.pp_double[i][i+1]; - } - d->ptr.p_double[n-1] = b->ptr.pp_double[n-1][n-1]; - } - else - { - ae_vector_set_length(d, m, _state); - ae_vector_set_length(e, m, _state); - for(i=0; i<=m-2; i++) - { - d->ptr.p_double[i] = b->ptr.pp_double[i][i]; - e->ptr.p_double[i] = b->ptr.pp_double[i+1][i]; - } - d->ptr.p_double[m-1] = b->ptr.pp_double[m-1][m-1]; - } -} - - -/************************************************************************* -Reduction of a square matrix to upper Hessenberg form: Q'*A*Q = H, -where Q is an orthogonal matrix, H - Hessenberg matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix A with elements [0..N-1, 0..N-1] - N - size of matrix A. - -Output parameters: - A - matrices Q and P in compact form (see below). - Tau - array of scalar factors which are used to form matrix Q. - Array whose index ranges within [0..N-2] - -Matrix H is located on the main diagonal, on the lower secondary diagonal -and above the main diagonal of matrix A. The elements which are used to -form matrix Q are situated in array Tau and below the lower secondary -diagonal of matrix A as follows: - -Matrix Q is represented as a product of elementary reflections - -Q = H(0)*H(2)*...*H(n-2), - -where each H(i) is given by - -H(i) = 1 - tau * v * (v^T) - -where tau is a scalar stored in Tau[I]; v - is a real vector, -so that v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) stored in A(i+2:n-1,i). - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - October 31, 1992 -*************************************************************************/ -void rmatrixhessenberg(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_vector* tau, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - double v; - ae_vector t; - ae_vector work; - - ae_frame_make(_state, &_frame_block); - memset(&t, 0, sizeof(t)); - memset(&work, 0, sizeof(work)); - ae_vector_clear(tau); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=0, "RMatrixHessenberg: incorrect N!", _state); - - /* - * Quick return if possible - */ - if( n<=1 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Allocate place - */ - ae_vector_set_length(tau, n-2+1, _state); - ae_vector_set_length(&t, n+1, _state); - ae_vector_set_length(&work, n-1+1, _state); - - /* - * MKL version - */ - if( rmatrixhessenbergmkl(a, n, tau, _state) ) - { - ae_frame_leave(_state); - return; - } - - /* - * ALGLIB version - */ - for(i=0; i<=n-2; i++) - { - - /* - * Compute elementary reflector H(i) to annihilate A(i+2:ihi,i) - */ - ae_v_move(&t.ptr.p_double[1], 1, &a->ptr.pp_double[i+1][i], a->stride, ae_v_len(1,n-i-1)); - generatereflection(&t, n-i-1, &v, _state); - ae_v_move(&a->ptr.pp_double[i+1][i], a->stride, &t.ptr.p_double[1], 1, ae_v_len(i+1,n-1)); - tau->ptr.p_double[i] = v; - t.ptr.p_double[1] = (double)(1); - - /* - * Apply H(i) to A(1:ihi,i+1:ihi) from the right - */ - applyreflectionfromtheright(a, v, &t, 0, n-1, i+1, n-1, &work, _state); - - /* - * Apply H(i) to A(i+1:ihi,i+1:n) from the left - */ - applyreflectionfromtheleft(a, v, &t, i+1, n-1, i+1, n-1, &work, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Unpacking matrix Q which reduces matrix A to upper Hessenberg form - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - output of RMatrixHessenberg subroutine. - N - size of matrix A. - Tau - scalar factors which are used to form Q. - Output of RMatrixHessenberg subroutine. - -Output parameters: - Q - matrix Q. - Array whose indexes range within [0..N-1, 0..N-1]. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixhessenbergunpackq(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_vector* tau, - /* Real */ ae_matrix* q, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_vector v; - ae_vector work; - - ae_frame_make(_state, &_frame_block); - memset(&v, 0, sizeof(v)); - memset(&work, 0, sizeof(work)); - ae_matrix_clear(q); - ae_vector_init(&v, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - - if( n==0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * init - */ - ae_matrix_set_length(q, n-1+1, n-1+1, _state); - ae_vector_set_length(&v, n-1+1, _state); - ae_vector_set_length(&work, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - q->ptr.pp_double[i][j] = (double)(1); - } - else - { - q->ptr.pp_double[i][j] = (double)(0); - } - } - } - - /* - * MKL version - */ - if( rmatrixhessenbergunpackqmkl(a, n, tau, q, _state) ) - { - ae_frame_leave(_state); - return; - } - - /* - * ALGLIB version: unpack Q - */ - for(i=0; i<=n-2; i++) - { - - /* - * Apply H(i) - */ - ae_v_move(&v.ptr.p_double[1], 1, &a->ptr.pp_double[i+1][i], a->stride, ae_v_len(1,n-i-1)); - v.ptr.p_double[1] = (double)(1); - applyreflectionfromtheright(q, tau->ptr.p_double[i], &v, 0, n-1, i+1, n-1, &work, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Unpacking matrix H (the result of matrix A reduction to upper Hessenberg form) - -Input parameters: - A - output of RMatrixHessenberg subroutine. - N - size of matrix A. - -Output parameters: - H - matrix H. Array whose indexes range within [0..N-1, 0..N-1]. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixhessenbergunpackh(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_matrix* h, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_vector v; - ae_vector work; - - ae_frame_make(_state, &_frame_block); - memset(&v, 0, sizeof(v)); - memset(&work, 0, sizeof(work)); - ae_matrix_clear(h); - ae_vector_init(&v, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - - if( n==0 ) - { - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(h, n-1+1, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i-2; j++) - { - h->ptr.pp_double[i][j] = (double)(0); - } - j = ae_maxint(0, i-1, _state); - ae_v_move(&h->ptr.pp_double[i][j], 1, &a->ptr.pp_double[i][j], 1, ae_v_len(j,n-1)); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Reduction of a symmetric matrix which is given by its higher or lower -triangular part to a tridiagonal matrix using orthogonal similarity -transformation: Q'*A*Q=T. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix to be transformed - array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - storage format. If IsUpper = True, then matrix A is given - by its upper triangle, and the lower triangle is not used - and not modified by the algorithm, and vice versa - if IsUpper = False. - -Output parameters: - A - matrices T and Q in compact form (see lower) - Tau - array of factors which are forming matrices H(i) - array with elements [0..N-2]. - D - main diagonal of symmetric matrix T. - array with elements [0..N-1]. - E - secondary diagonal of symmetric matrix T. - array with elements [0..N-2]. - - - If IsUpper=True, the matrix Q is represented as a product of elementary - reflectors - - Q = H(n-2) . . . H(2) H(0). - - Each H(i) has the form - - H(i) = I - tau * v * v' - - where tau is a real scalar, and v is a real vector with - v(i+1:n-1) = 0, v(i) = 1, v(0:i-1) is stored on exit in - A(0:i-1,i+1), and tau in TAU(i). - - If IsUpper=False, the matrix Q is represented as a product of elementary - reflectors - - Q = H(0) H(2) . . . H(n-2). - - Each H(i) has the form - - H(i) = I - tau * v * v' - - where tau is a real scalar, and v is a real vector with - v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) is stored on exit in A(i+2:n-1,i), - and tau in TAU(i). - - The contents of A on exit are illustrated by the following examples - with n = 5: - - if UPLO = 'U': if UPLO = 'L': - - ( d e v1 v2 v3 ) ( d ) - ( d e v2 v3 ) ( e d ) - ( d e v3 ) ( v0 e d ) - ( d e ) ( v0 v1 e d ) - ( d ) ( v0 v1 v2 e d ) - - where d and e denote diagonal and off-diagonal elements of T, and vi - denotes an element of the vector defining H(i). - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - October 31, 1992 -*************************************************************************/ -void smatrixtd(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* tau, - /* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - double alpha; - double taui; - double v; - ae_vector t; - ae_vector t2; - ae_vector t3; - - ae_frame_make(_state, &_frame_block); - memset(&t, 0, sizeof(t)); - memset(&t2, 0, sizeof(t2)); - memset(&t3, 0, sizeof(t3)); - ae_vector_clear(tau); - ae_vector_clear(d); - ae_vector_clear(e); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t3, 0, DT_REAL, _state, ae_true); - - if( n<=0 ) - { - ae_frame_leave(_state); - return; - } - ae_vector_set_length(&t, n+1, _state); - ae_vector_set_length(&t2, n+1, _state); - ae_vector_set_length(&t3, n+1, _state); - if( n>1 ) - { - ae_vector_set_length(tau, n-2+1, _state); - } - ae_vector_set_length(d, n-1+1, _state); - if( n>1 ) - { - ae_vector_set_length(e, n-2+1, _state); - } - - /* - * Try to use MKL - */ - if( smatrixtdmkl(a, n, isupper, tau, d, e, _state) ) - { - ae_frame_leave(_state); - return; - } - - /* - * ALGLIB version - */ - if( isupper ) - { - - /* - * Reduce the upper triangle of A - */ - for(i=n-2; i>=0; i--) - { - - /* - * Generate elementary reflector H() = E - tau * v * v' - */ - if( i>=1 ) - { - ae_v_move(&t.ptr.p_double[2], 1, &a->ptr.pp_double[0][i+1], a->stride, ae_v_len(2,i+1)); - } - t.ptr.p_double[1] = a->ptr.pp_double[i][i+1]; - generatereflection(&t, i+1, &taui, _state); - if( i>=1 ) - { - ae_v_move(&a->ptr.pp_double[0][i+1], a->stride, &t.ptr.p_double[2], 1, ae_v_len(0,i-1)); - } - a->ptr.pp_double[i][i+1] = t.ptr.p_double[1]; - e->ptr.p_double[i] = a->ptr.pp_double[i][i+1]; - if( ae_fp_neq(taui,(double)(0)) ) - { - - /* - * Apply H from both sides to A - */ - a->ptr.pp_double[i][i+1] = (double)(1); - - /* - * Compute x := tau * A * v storing x in TAU - */ - ae_v_move(&t.ptr.p_double[1], 1, &a->ptr.pp_double[0][i+1], a->stride, ae_v_len(1,i+1)); - symmetricmatrixvectormultiply(a, isupper, 0, i, &t, taui, &t3, _state); - ae_v_move(&tau->ptr.p_double[0], 1, &t3.ptr.p_double[1], 1, ae_v_len(0,i)); - - /* - * Compute w := x - 1/2 * tau * (x'*v) * v - */ - v = ae_v_dotproduct(&tau->ptr.p_double[0], 1, &a->ptr.pp_double[0][i+1], a->stride, ae_v_len(0,i)); - alpha = -0.5*taui*v; - ae_v_addd(&tau->ptr.p_double[0], 1, &a->ptr.pp_double[0][i+1], a->stride, ae_v_len(0,i), alpha); - - /* - * Apply the transformation as a rank-2 update: - * A := A - v * w' - w * v' - */ - ae_v_move(&t.ptr.p_double[1], 1, &a->ptr.pp_double[0][i+1], a->stride, ae_v_len(1,i+1)); - ae_v_move(&t3.ptr.p_double[1], 1, &tau->ptr.p_double[0], 1, ae_v_len(1,i+1)); - symmetricrank2update(a, isupper, 0, i, &t, &t3, &t2, (double)(-1), _state); - a->ptr.pp_double[i][i+1] = e->ptr.p_double[i]; - } - d->ptr.p_double[i+1] = a->ptr.pp_double[i+1][i+1]; - tau->ptr.p_double[i] = taui; - } - d->ptr.p_double[0] = a->ptr.pp_double[0][0]; - } - else - { - - /* - * Reduce the lower triangle of A - */ - for(i=0; i<=n-2; i++) - { - - /* - * Generate elementary reflector H = E - tau * v * v' - */ - ae_v_move(&t.ptr.p_double[1], 1, &a->ptr.pp_double[i+1][i], a->stride, ae_v_len(1,n-i-1)); - generatereflection(&t, n-i-1, &taui, _state); - ae_v_move(&a->ptr.pp_double[i+1][i], a->stride, &t.ptr.p_double[1], 1, ae_v_len(i+1,n-1)); - e->ptr.p_double[i] = a->ptr.pp_double[i+1][i]; - if( ae_fp_neq(taui,(double)(0)) ) - { - - /* - * Apply H from both sides to A - */ - a->ptr.pp_double[i+1][i] = (double)(1); - - /* - * Compute x := tau * A * v storing y in TAU - */ - ae_v_move(&t.ptr.p_double[1], 1, &a->ptr.pp_double[i+1][i], a->stride, ae_v_len(1,n-i-1)); - symmetricmatrixvectormultiply(a, isupper, i+1, n-1, &t, taui, &t2, _state); - ae_v_move(&tau->ptr.p_double[i], 1, &t2.ptr.p_double[1], 1, ae_v_len(i,n-2)); - - /* - * Compute w := x - 1/2 * tau * (x'*v) * v - */ - v = ae_v_dotproduct(&tau->ptr.p_double[i], 1, &a->ptr.pp_double[i+1][i], a->stride, ae_v_len(i,n-2)); - alpha = -0.5*taui*v; - ae_v_addd(&tau->ptr.p_double[i], 1, &a->ptr.pp_double[i+1][i], a->stride, ae_v_len(i,n-2), alpha); - - /* - * Apply the transformation as a rank-2 update: - * A := A - v * w' - w * v' - * - */ - ae_v_move(&t.ptr.p_double[1], 1, &a->ptr.pp_double[i+1][i], a->stride, ae_v_len(1,n-i-1)); - ae_v_move(&t2.ptr.p_double[1], 1, &tau->ptr.p_double[i], 1, ae_v_len(1,n-i-1)); - symmetricrank2update(a, isupper, i+1, n-1, &t, &t2, &t3, (double)(-1), _state); - a->ptr.pp_double[i+1][i] = e->ptr.p_double[i]; - } - d->ptr.p_double[i] = a->ptr.pp_double[i][i]; - tau->ptr.p_double[i] = taui; - } - d->ptr.p_double[n-1] = a->ptr.pp_double[n-1][n-1]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Unpacking matrix Q which reduces symmetric matrix to a tridiagonal -form. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - the result of a SMatrixTD subroutine - N - size of matrix A. - IsUpper - storage format (a parameter of SMatrixTD subroutine) - Tau - the result of a SMatrixTD subroutine - -Output parameters: - Q - transformation matrix. - array with elements [0..N-1, 0..N-1]. - - -- ALGLIB -- - Copyright 2005-2010 by Bochkanov Sergey -*************************************************************************/ -void smatrixtdunpackq(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* tau, - /* Real */ ae_matrix* q, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_vector v; - ae_vector work; - - ae_frame_make(_state, &_frame_block); - memset(&v, 0, sizeof(v)); - memset(&work, 0, sizeof(work)); - ae_matrix_clear(q); - ae_vector_init(&v, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - - if( n==0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * init - */ - ae_matrix_set_length(q, n-1+1, n-1+1, _state); - ae_vector_set_length(&v, n+1, _state); - ae_vector_set_length(&work, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - q->ptr.pp_double[i][j] = (double)(1); - } - else - { - q->ptr.pp_double[i][j] = (double)(0); - } - } - } - - /* - * MKL version - */ - if( smatrixtdunpackqmkl(a, n, isupper, tau, q, _state) ) - { - ae_frame_leave(_state); - return; - } - - /* - * ALGLIB version: unpack Q - */ - if( isupper ) - { - for(i=0; i<=n-2; i++) - { - - /* - * Apply H(i) - */ - ae_v_move(&v.ptr.p_double[1], 1, &a->ptr.pp_double[0][i+1], a->stride, ae_v_len(1,i+1)); - v.ptr.p_double[i+1] = (double)(1); - applyreflectionfromtheleft(q, tau->ptr.p_double[i], &v, 0, i, 0, n-1, &work, _state); - } - } - else - { - for(i=n-2; i>=0; i--) - { - - /* - * Apply H(i) - */ - ae_v_move(&v.ptr.p_double[1], 1, &a->ptr.pp_double[i+1][i], a->stride, ae_v_len(1,n-i-1)); - v.ptr.p_double[1] = (double)(1); - applyreflectionfromtheleft(q, tau->ptr.p_double[i], &v, i+1, n-1, 0, n-1, &work, _state); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Reduction of a Hermitian matrix which is given by its higher or lower -triangular part to a real tridiagonal matrix using unitary similarity -transformation: Q'*A*Q = T. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix to be transformed - array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - storage format. If IsUpper = True, then matrix A is given - by its upper triangle, and the lower triangle is not used - and not modified by the algorithm, and vice versa - if IsUpper = False. - -Output parameters: - A - matrices T and Q in compact form (see lower) - Tau - array of factors which are forming matrices H(i) - array with elements [0..N-2]. - D - main diagonal of real symmetric matrix T. - array with elements [0..N-1]. - E - secondary diagonal of real symmetric matrix T. - array with elements [0..N-2]. - - - If IsUpper=True, the matrix Q is represented as a product of elementary - reflectors - - Q = H(n-2) . . . H(2) H(0). - - Each H(i) has the form - - H(i) = I - tau * v * v' - - where tau is a complex scalar, and v is a complex vector with - v(i+1:n-1) = 0, v(i) = 1, v(0:i-1) is stored on exit in - A(0:i-1,i+1), and tau in TAU(i). - - If IsUpper=False, the matrix Q is represented as a product of elementary - reflectors - - Q = H(0) H(2) . . . H(n-2). - - Each H(i) has the form - - H(i) = I - tau * v * v' - - where tau is a complex scalar, and v is a complex vector with - v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) is stored on exit in A(i+2:n-1,i), - and tau in TAU(i). - - The contents of A on exit are illustrated by the following examples - with n = 5: - - if UPLO = 'U': if UPLO = 'L': - - ( d e v1 v2 v3 ) ( d ) - ( d e v2 v3 ) ( e d ) - ( d e v3 ) ( v0 e d ) - ( d e ) ( v0 v1 e d ) - ( d ) ( v0 v1 v2 e d ) - -where d and e denote diagonal and off-diagonal elements of T, and vi -denotes an element of the vector defining H(i). - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - October 31, 1992 -*************************************************************************/ -void hmatrixtd(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* tau, - /* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_complex alpha; - ae_complex taui; - ae_complex v; - ae_vector t; - ae_vector t2; - ae_vector t3; - - ae_frame_make(_state, &_frame_block); - memset(&t, 0, sizeof(t)); - memset(&t2, 0, sizeof(t2)); - memset(&t3, 0, sizeof(t3)); - ae_vector_clear(tau); - ae_vector_clear(d); - ae_vector_clear(e); - ae_vector_init(&t, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&t2, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&t3, 0, DT_COMPLEX, _state, ae_true); - - - /* - * Init and test - */ - if( n<=0 ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_assert(ae_fp_eq(a->ptr.pp_complex[i][i].y,(double)(0)), "Assertion failed", _state); - } - if( n>1 ) - { - ae_vector_set_length(tau, n-2+1, _state); - ae_vector_set_length(e, n-2+1, _state); - } - ae_vector_set_length(d, n-1+1, _state); - ae_vector_set_length(&t, n-1+1, _state); - ae_vector_set_length(&t2, n-1+1, _state); - ae_vector_set_length(&t3, n-1+1, _state); - - /* - * MKL version - */ - if( hmatrixtdmkl(a, n, isupper, tau, d, e, _state) ) - { - ae_frame_leave(_state); - return; - } - - /* - * ALGLIB version - */ - if( isupper ) - { - - /* - * Reduce the upper triangle of A - */ - a->ptr.pp_complex[n-1][n-1] = ae_complex_from_d(a->ptr.pp_complex[n-1][n-1].x); - for(i=n-2; i>=0; i--) - { - - /* - * Generate elementary reflector H = I+1 - tau * v * v' - */ - alpha = a->ptr.pp_complex[i][i+1]; - t.ptr.p_complex[1] = alpha; - if( i>=1 ) - { - ae_v_cmove(&t.ptr.p_complex[2], 1, &a->ptr.pp_complex[0][i+1], a->stride, "N", ae_v_len(2,i+1)); - } - complexgeneratereflection(&t, i+1, &taui, _state); - if( i>=1 ) - { - ae_v_cmove(&a->ptr.pp_complex[0][i+1], a->stride, &t.ptr.p_complex[2], 1, "N", ae_v_len(0,i-1)); - } - alpha = t.ptr.p_complex[1]; - e->ptr.p_double[i] = alpha.x; - if( ae_c_neq_d(taui,(double)(0)) ) - { - - /* - * Apply H(I+1) from both sides to A - */ - a->ptr.pp_complex[i][i+1] = ae_complex_from_i(1); - - /* - * Compute x := tau * A * v storing x in TAU - */ - ae_v_cmove(&t.ptr.p_complex[1], 1, &a->ptr.pp_complex[0][i+1], a->stride, "N", ae_v_len(1,i+1)); - hermitianmatrixvectormultiply(a, isupper, 0, i, &t, taui, &t2, _state); - ae_v_cmove(&tau->ptr.p_complex[0], 1, &t2.ptr.p_complex[1], 1, "N", ae_v_len(0,i)); - - /* - * Compute w := x - 1/2 * tau * (x'*v) * v - */ - v = ae_v_cdotproduct(&tau->ptr.p_complex[0], 1, "Conj", &a->ptr.pp_complex[0][i+1], a->stride, "N", ae_v_len(0,i)); - alpha = ae_c_neg(ae_c_mul(ae_c_mul_d(taui,0.5),v)); - ae_v_caddc(&tau->ptr.p_complex[0], 1, &a->ptr.pp_complex[0][i+1], a->stride, "N", ae_v_len(0,i), alpha); - - /* - * Apply the transformation as a rank-2 update: - * A := A - v * w' - w * v' - */ - ae_v_cmove(&t.ptr.p_complex[1], 1, &a->ptr.pp_complex[0][i+1], a->stride, "N", ae_v_len(1,i+1)); - ae_v_cmove(&t3.ptr.p_complex[1], 1, &tau->ptr.p_complex[0], 1, "N", ae_v_len(1,i+1)); - hermitianrank2update(a, isupper, 0, i, &t, &t3, &t2, ae_complex_from_i(-1), _state); - } - else - { - a->ptr.pp_complex[i][i] = ae_complex_from_d(a->ptr.pp_complex[i][i].x); - } - a->ptr.pp_complex[i][i+1] = ae_complex_from_d(e->ptr.p_double[i]); - d->ptr.p_double[i+1] = a->ptr.pp_complex[i+1][i+1].x; - tau->ptr.p_complex[i] = taui; - } - d->ptr.p_double[0] = a->ptr.pp_complex[0][0].x; - } - else - { - - /* - * Reduce the lower triangle of A - */ - a->ptr.pp_complex[0][0] = ae_complex_from_d(a->ptr.pp_complex[0][0].x); - for(i=0; i<=n-2; i++) - { - - /* - * Generate elementary reflector H = I - tau * v * v' - */ - ae_v_cmove(&t.ptr.p_complex[1], 1, &a->ptr.pp_complex[i+1][i], a->stride, "N", ae_v_len(1,n-i-1)); - complexgeneratereflection(&t, n-i-1, &taui, _state); - ae_v_cmove(&a->ptr.pp_complex[i+1][i], a->stride, &t.ptr.p_complex[1], 1, "N", ae_v_len(i+1,n-1)); - e->ptr.p_double[i] = a->ptr.pp_complex[i+1][i].x; - if( ae_c_neq_d(taui,(double)(0)) ) - { - - /* - * Apply H(i) from both sides to A(i+1:n,i+1:n) - */ - a->ptr.pp_complex[i+1][i] = ae_complex_from_i(1); - - /* - * Compute x := tau * A * v storing y in TAU - */ - ae_v_cmove(&t.ptr.p_complex[1], 1, &a->ptr.pp_complex[i+1][i], a->stride, "N", ae_v_len(1,n-i-1)); - hermitianmatrixvectormultiply(a, isupper, i+1, n-1, &t, taui, &t2, _state); - ae_v_cmove(&tau->ptr.p_complex[i], 1, &t2.ptr.p_complex[1], 1, "N", ae_v_len(i,n-2)); - - /* - * Compute w := x - 1/2 * tau * (x'*v) * v - */ - v = ae_v_cdotproduct(&tau->ptr.p_complex[i], 1, "Conj", &a->ptr.pp_complex[i+1][i], a->stride, "N", ae_v_len(i,n-2)); - alpha = ae_c_neg(ae_c_mul(ae_c_mul_d(taui,0.5),v)); - ae_v_caddc(&tau->ptr.p_complex[i], 1, &a->ptr.pp_complex[i+1][i], a->stride, "N", ae_v_len(i,n-2), alpha); - - /* - * Apply the transformation as a rank-2 update: - * A := A - v * w' - w * v' - */ - ae_v_cmove(&t.ptr.p_complex[1], 1, &a->ptr.pp_complex[i+1][i], a->stride, "N", ae_v_len(1,n-i-1)); - ae_v_cmove(&t2.ptr.p_complex[1], 1, &tau->ptr.p_complex[i], 1, "N", ae_v_len(1,n-i-1)); - hermitianrank2update(a, isupper, i+1, n-1, &t, &t2, &t3, ae_complex_from_i(-1), _state); - } - else - { - a->ptr.pp_complex[i+1][i+1] = ae_complex_from_d(a->ptr.pp_complex[i+1][i+1].x); - } - a->ptr.pp_complex[i+1][i] = ae_complex_from_d(e->ptr.p_double[i]); - d->ptr.p_double[i] = a->ptr.pp_complex[i][i].x; - tau->ptr.p_complex[i] = taui; - } - d->ptr.p_double[n-1] = a->ptr.pp_complex[n-1][n-1].x; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Unpacking matrix Q which reduces a Hermitian matrix to a real tridiagonal -form. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - the result of a HMatrixTD subroutine - N - size of matrix A. - IsUpper - storage format (a parameter of HMatrixTD subroutine) - Tau - the result of a HMatrixTD subroutine - -Output parameters: - Q - transformation matrix. - array with elements [0..N-1, 0..N-1]. - - -- ALGLIB -- - Copyright 2005-2010 by Bochkanov Sergey -*************************************************************************/ -void hmatrixtdunpackq(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* tau, - /* Complex */ ae_matrix* q, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_vector v; - ae_vector work; - - ae_frame_make(_state, &_frame_block); - memset(&v, 0, sizeof(v)); - memset(&work, 0, sizeof(work)); - ae_matrix_clear(q); - ae_vector_init(&v, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&work, 0, DT_COMPLEX, _state, ae_true); - - if( n==0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * init - */ - ae_matrix_set_length(q, n-1+1, n-1+1, _state); - ae_vector_set_length(&v, n+1, _state); - ae_vector_set_length(&work, n-1+1, _state); - - /* - * MKL version - */ - if( hmatrixtdunpackqmkl(a, n, isupper, tau, q, _state) ) - { - ae_frame_leave(_state); - return; - } - - /* - * ALGLIB version - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - q->ptr.pp_complex[i][j] = ae_complex_from_i(1); - } - else - { - q->ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - } - if( isupper ) - { - for(i=0; i<=n-2; i++) - { - - /* - * Apply H(i) - */ - ae_v_cmove(&v.ptr.p_complex[1], 1, &a->ptr.pp_complex[0][i+1], a->stride, "N", ae_v_len(1,i+1)); - v.ptr.p_complex[i+1] = ae_complex_from_i(1); - complexapplyreflectionfromtheleft(q, tau->ptr.p_complex[i], &v, 0, i, 0, n-1, &work, _state); - } - } - else - { - for(i=n-2; i>=0; i--) - { - - /* - * Apply H(i) - */ - ae_v_cmove(&v.ptr.p_complex[1], 1, &a->ptr.pp_complex[i+1][i], a->stride, "N", ae_v_len(1,n-i-1)); - v.ptr.p_complex[1] = ae_complex_from_i(1); - complexapplyreflectionfromtheleft(q, tau->ptr.p_complex[i], &v, i+1, n-1, 0, n-1, &work, _state); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Base case for complex QR - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994. - Sergey Bochkanov, ALGLIB project, translation from FORTRAN to - pseudocode, 2007-2010. -*************************************************************************/ -static void ortfac_cmatrixqrbasecase(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_vector* work, - /* Complex */ ae_vector* t, - /* Complex */ ae_vector* tau, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - ae_int_t mmi; - ae_int_t minmn; - ae_complex tmp; - - - minmn = ae_minint(m, n, _state); - if( minmn<=0 ) - { - return; - } - - /* - * Test the input arguments - */ - k = ae_minint(m, n, _state); - for(i=0; i<=k-1; i++) - { - - /* - * Generate elementary reflector H(i) to annihilate A(i+1:m,i) - */ - mmi = m-i; - ae_v_cmove(&t->ptr.p_complex[1], 1, &a->ptr.pp_complex[i][i], a->stride, "N", ae_v_len(1,mmi)); - complexgeneratereflection(t, mmi, &tmp, _state); - tau->ptr.p_complex[i] = tmp; - ae_v_cmove(&a->ptr.pp_complex[i][i], a->stride, &t->ptr.p_complex[1], 1, "N", ae_v_len(i,m-1)); - t->ptr.p_complex[1] = ae_complex_from_i(1); - if( iptr.p_complex[i], _state), t, i, m-1, i+1, n-1, work, _state); - } - } -} - - -/************************************************************************* -Base case for complex LQ - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994. - Sergey Bochkanov, ALGLIB project, translation from FORTRAN to - pseudocode, 2007-2010. -*************************************************************************/ -static void ortfac_cmatrixlqbasecase(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_vector* work, - /* Complex */ ae_vector* t, - /* Complex */ ae_vector* tau, - ae_state *_state) -{ - ae_int_t i; - ae_int_t minmn; - ae_complex tmp; - - - minmn = ae_minint(m, n, _state); - if( minmn<=0 ) - { - return; - } - - /* - * Test the input arguments - */ - for(i=0; i<=minmn-1; i++) - { - - /* - * Generate elementary reflector H(i) - * - * NOTE: ComplexGenerateReflection() generates left reflector, - * i.e. H which reduces x by applyiong from the left, but we - * need RIGHT reflector. So we replace H=E-tau*v*v' by H^H, - * which changes v to conj(v). - */ - ae_v_cmove(&t->ptr.p_complex[1], 1, &a->ptr.pp_complex[i][i], 1, "Conj", ae_v_len(1,n-i)); - complexgeneratereflection(t, n-i, &tmp, _state); - tau->ptr.p_complex[i] = tmp; - ae_v_cmove(&a->ptr.pp_complex[i][i], 1, &t->ptr.p_complex[1], 1, "Conj", ae_v_len(i,n-1)); - t->ptr.p_complex[1] = ae_complex_from_i(1); - if( iptr.p_complex[i], t, i+1, m-1, i, n-1, work, _state); - } - } -} - - -/************************************************************************* -Generate block reflector: -* fill unused parts of reflectors matrix by zeros -* fill diagonal of reflectors matrix by ones -* generate triangular factor T - -PARAMETERS: - A - either LengthA*BlockSize (if ColumnwiseA) or - BlockSize*LengthA (if not ColumnwiseA) matrix of - elementary reflectors. - Modified on exit. - Tau - scalar factors - ColumnwiseA - reflectors are stored in rows or in columns - LengthA - length of largest reflector - BlockSize - number of reflectors - T - array[BlockSize,2*BlockSize]. Left BlockSize*BlockSize - submatrix stores triangular factor on exit. - WORK - array[BlockSize] - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -static void ortfac_rmatrixblockreflector(/* Real */ ae_matrix* a, - /* Real */ ae_vector* tau, - ae_bool columnwisea, - ae_int_t lengtha, - ae_int_t blocksize, - /* Real */ ae_matrix* t, - /* Real */ ae_vector* work, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - - - - /* - * fill beginning of new column with zeros, - * load 1.0 in the first non-zero element - */ - for(k=0; k<=blocksize-1; k++) - { - if( columnwisea ) - { - for(i=0; i<=k-1; i++) - { - a->ptr.pp_double[i][k] = (double)(0); - } - } - else - { - for(i=0; i<=k-1; i++) - { - a->ptr.pp_double[k][i] = (double)(0); - } - } - a->ptr.pp_double[k][k] = (double)(1); - } - - /* - * Calculate Gram matrix of A - */ - for(i=0; i<=blocksize-1; i++) - { - for(j=0; j<=blocksize-1; j++) - { - t->ptr.pp_double[i][blocksize+j] = (double)(0); - } - } - for(k=0; k<=lengtha-1; k++) - { - for(j=1; j<=blocksize-1; j++) - { - if( columnwisea ) - { - v = a->ptr.pp_double[k][j]; - if( ae_fp_neq(v,(double)(0)) ) - { - ae_v_addd(&t->ptr.pp_double[j][blocksize], 1, &a->ptr.pp_double[k][0], 1, ae_v_len(blocksize,blocksize+j-1), v); - } - } - else - { - v = a->ptr.pp_double[j][k]; - if( ae_fp_neq(v,(double)(0)) ) - { - ae_v_addd(&t->ptr.pp_double[j][blocksize], 1, &a->ptr.pp_double[0][k], a->stride, ae_v_len(blocksize,blocksize+j-1), v); - } - } - } - } - - /* - * Prepare Y (stored in TmpA) and T (stored in TmpT) - */ - for(k=0; k<=blocksize-1; k++) - { - - /* - * fill non-zero part of T, use pre-calculated Gram matrix - */ - ae_v_move(&work->ptr.p_double[0], 1, &t->ptr.pp_double[k][blocksize], 1, ae_v_len(0,k-1)); - for(i=0; i<=k-1; i++) - { - v = ae_v_dotproduct(&t->ptr.pp_double[i][i], 1, &work->ptr.p_double[i], 1, ae_v_len(i,k-1)); - t->ptr.pp_double[i][k] = -tau->ptr.p_double[k]*v; - } - t->ptr.pp_double[k][k] = -tau->ptr.p_double[k]; - - /* - * Rest of T is filled by zeros - */ - for(i=k+1; i<=blocksize-1; i++) - { - t->ptr.pp_double[i][k] = (double)(0); - } - } -} - - -/************************************************************************* -Generate block reflector (complex): -* fill unused parts of reflectors matrix by zeros -* fill diagonal of reflectors matrix by ones -* generate triangular factor T - - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -static void ortfac_cmatrixblockreflector(/* Complex */ ae_matrix* a, - /* Complex */ ae_vector* tau, - ae_bool columnwisea, - ae_int_t lengtha, - ae_int_t blocksize, - /* Complex */ ae_matrix* t, - /* Complex */ ae_vector* work, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - ae_complex v; - - - - /* - * Prepare Y (stored in TmpA) and T (stored in TmpT) - */ - for(k=0; k<=blocksize-1; k++) - { - - /* - * fill beginning of new column with zeros, - * load 1.0 in the first non-zero element - */ - if( columnwisea ) - { - for(i=0; i<=k-1; i++) - { - a->ptr.pp_complex[i][k] = ae_complex_from_i(0); - } - } - else - { - for(i=0; i<=k-1; i++) - { - a->ptr.pp_complex[k][i] = ae_complex_from_i(0); - } - } - a->ptr.pp_complex[k][k] = ae_complex_from_i(1); - - /* - * fill non-zero part of T, - */ - for(i=0; i<=k-1; i++) - { - if( columnwisea ) - { - v = ae_v_cdotproduct(&a->ptr.pp_complex[k][i], a->stride, "Conj", &a->ptr.pp_complex[k][k], a->stride, "N", ae_v_len(k,lengtha-1)); - } - else - { - v = ae_v_cdotproduct(&a->ptr.pp_complex[i][k], 1, "N", &a->ptr.pp_complex[k][k], 1, "Conj", ae_v_len(k,lengtha-1)); - } - work->ptr.p_complex[i] = v; - } - for(i=0; i<=k-1; i++) - { - v = ae_v_cdotproduct(&t->ptr.pp_complex[i][i], 1, "N", &work->ptr.p_complex[i], 1, "N", ae_v_len(i,k-1)); - t->ptr.pp_complex[i][k] = ae_c_neg(ae_c_mul(tau->ptr.p_complex[k],v)); - } - t->ptr.pp_complex[k][k] = ae_c_neg(tau->ptr.p_complex[k]); - - /* - * Rest of T is filled by zeros - */ - for(i=k+1; i<=blocksize-1; i++) - { - t->ptr.pp_complex[i][k] = ae_complex_from_i(0); - } - } -} - - -#endif -#if defined(AE_COMPILE_FBLS) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Basic Cholesky solver for ScaleA*Cholesky(A)'*x = y. - -This subroutine assumes that: -* A*ScaleA is well scaled -* A is well-conditioned, so no zero divisions or overflow may occur - -INPUT PARAMETERS: - CHA - Cholesky decomposition of A - SqrtScaleA- square root of scale factor ScaleA - N - matrix size, N>=0. - IsUpper - storage type - XB - right part - Tmp - buffer; function automatically allocates it, if it is too - small. It can be reused if function is called several - times. - -OUTPUT PARAMETERS: - XB - solution - -NOTE 1: no assertion or tests are done during algorithm operation -NOTE 2: N=0 will force algorithm to silently return - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void fblscholeskysolve(/* Real */ ae_matrix* cha, - double sqrtscalea, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* xb, - /* Real */ ae_vector* tmp, - ae_state *_state) -{ - double v; - - - if( n<=0 ) - { - return; - } - if( tmp->cntptr.p_double[0], 1, ae_v_len(0,n-1), v); - - /* - * Solve A = L*L' or A=U'*U - */ - if( isupper ) - { - - /* - * Solve U'*y=b first. - */ - rmatrixtrsv(n, cha, 0, 0, ae_true, ae_false, 1, xb, 0, _state); - - /* - * Solve U*x=y then. - */ - rmatrixtrsv(n, cha, 0, 0, ae_true, ae_false, 0, xb, 0, _state); - } - else - { - - /* - * Solve L*y=b first - */ - rmatrixtrsv(n, cha, 0, 0, ae_false, ae_false, 0, xb, 0, _state); - - /* - * Solve L'*x=y then. - */ - rmatrixtrsv(n, cha, 0, 0, ae_false, ae_false, 1, xb, 0, _state); - } -} - - -/************************************************************************* -Fast basic linear solver: linear SPD CG - -Solves (A^T*A + alpha*I)*x = b where: -* A is MxN matrix -* alpha>0 is a scalar -* I is NxN identity matrix -* b is Nx1 vector -* X is Nx1 unknown vector. - -N iterations of linear conjugate gradient are used to solve problem. - -INPUT PARAMETERS: - A - array[M,N], matrix - M - number of rows - N - number of unknowns - B - array[N], right part - X - initial approxumation, array[N] - Buf - buffer; function automatically allocates it, if it is too - small. It can be reused if function is called several times - with same M and N. - -OUTPUT PARAMETERS: - X - improved solution - -NOTES: -* solver checks quality of improved solution. If (because of problem - condition number, numerical noise, etc.) new solution is WORSE than - original approximation, then original approximation is returned. -* solver assumes that both A, B, Alpha are well scaled (i.e. they are - less than sqrt(overflow) and greater than sqrt(underflow)). - - -- ALGLIB -- - Copyright 20.08.2009 by Bochkanov Sergey -*************************************************************************/ -void fblssolvecgx(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double alpha, - /* Real */ ae_vector* b, - /* Real */ ae_vector* x, - /* Real */ ae_vector* buf, - ae_state *_state) -{ - ae_int_t k; - ae_int_t offsrk; - ae_int_t offsrk1; - ae_int_t offsxk; - ae_int_t offsxk1; - ae_int_t offspk; - ae_int_t offspk1; - ae_int_t offstmp1; - ae_int_t offstmp2; - ae_int_t bs; - double e1; - double e2; - double rk2; - double rk12; - double pap; - double s; - double betak; - double v1; - double v2; - - - - /* - * Test for special case: B=0 - */ - v1 = ae_v_dotproduct(&b->ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( ae_fp_eq(v1,(double)(0)) ) - { - for(k=0; k<=n-1; k++) - { - x->ptr.p_double[k] = (double)(0); - } - return; - } - - /* - * Offsets inside Buf for: - * * R[K], R[K+1] - * * X[K], X[K+1] - * * P[K], P[K+1] - * * Tmp1 - array[M], Tmp2 - array[N] - */ - offsrk = 0; - offsrk1 = offsrk+n; - offsxk = offsrk1+n; - offsxk1 = offsxk+n; - offspk = offsxk1+n; - offspk1 = offspk+n; - offstmp1 = offspk1+n; - offstmp2 = offstmp1+m; - bs = offstmp2+n; - if( buf->cntptr.p_double[offsxk], 1, &x->ptr.p_double[0], 1, ae_v_len(offsxk,offsxk+n-1)); - - /* - * r(0) = b-A*x(0) - * RK2 = r(0)'*r(0) - */ - rmatrixmv(m, n, a, 0, 0, 0, buf, offsxk, buf, offstmp1, _state); - rmatrixmv(n, m, a, 0, 0, 1, buf, offstmp1, buf, offstmp2, _state); - ae_v_addd(&buf->ptr.p_double[offstmp2], 1, &buf->ptr.p_double[offsxk], 1, ae_v_len(offstmp2,offstmp2+n-1), alpha); - ae_v_move(&buf->ptr.p_double[offsrk], 1, &b->ptr.p_double[0], 1, ae_v_len(offsrk,offsrk+n-1)); - ae_v_sub(&buf->ptr.p_double[offsrk], 1, &buf->ptr.p_double[offstmp2], 1, ae_v_len(offsrk,offsrk+n-1)); - rk2 = ae_v_dotproduct(&buf->ptr.p_double[offsrk], 1, &buf->ptr.p_double[offsrk], 1, ae_v_len(offsrk,offsrk+n-1)); - ae_v_move(&buf->ptr.p_double[offspk], 1, &buf->ptr.p_double[offsrk], 1, ae_v_len(offspk,offspk+n-1)); - e1 = ae_sqrt(rk2, _state); - - /* - * Cycle - */ - for(k=0; k<=n-1; k++) - { - - /* - * Calculate A*p(k) - store in Buf[OffsTmp2:OffsTmp2+N-1] - * and p(k)'*A*p(k) - store in PAP - * - * If PAP=0, break (iteration is over) - */ - rmatrixmv(m, n, a, 0, 0, 0, buf, offspk, buf, offstmp1, _state); - v1 = ae_v_dotproduct(&buf->ptr.p_double[offstmp1], 1, &buf->ptr.p_double[offstmp1], 1, ae_v_len(offstmp1,offstmp1+m-1)); - v2 = ae_v_dotproduct(&buf->ptr.p_double[offspk], 1, &buf->ptr.p_double[offspk], 1, ae_v_len(offspk,offspk+n-1)); - pap = v1+alpha*v2; - rmatrixmv(n, m, a, 0, 0, 1, buf, offstmp1, buf, offstmp2, _state); - ae_v_addd(&buf->ptr.p_double[offstmp2], 1, &buf->ptr.p_double[offspk], 1, ae_v_len(offstmp2,offstmp2+n-1), alpha); - if( ae_fp_eq(pap,(double)(0)) ) - { - break; - } - - /* - * S = (r(k)'*r(k))/(p(k)'*A*p(k)) - */ - s = rk2/pap; - - /* - * x(k+1) = x(k) + S*p(k) - */ - ae_v_move(&buf->ptr.p_double[offsxk1], 1, &buf->ptr.p_double[offsxk], 1, ae_v_len(offsxk1,offsxk1+n-1)); - ae_v_addd(&buf->ptr.p_double[offsxk1], 1, &buf->ptr.p_double[offspk], 1, ae_v_len(offsxk1,offsxk1+n-1), s); - - /* - * r(k+1) = r(k) - S*A*p(k) - * RK12 = r(k+1)'*r(k+1) - * - * Break if r(k+1) small enough (when compared to r(k)) - */ - ae_v_move(&buf->ptr.p_double[offsrk1], 1, &buf->ptr.p_double[offsrk], 1, ae_v_len(offsrk1,offsrk1+n-1)); - ae_v_subd(&buf->ptr.p_double[offsrk1], 1, &buf->ptr.p_double[offstmp2], 1, ae_v_len(offsrk1,offsrk1+n-1), s); - rk12 = ae_v_dotproduct(&buf->ptr.p_double[offsrk1], 1, &buf->ptr.p_double[offsrk1], 1, ae_v_len(offsrk1,offsrk1+n-1)); - if( ae_fp_less_eq(ae_sqrt(rk12, _state),100*ae_machineepsilon*ae_sqrt(rk2, _state)) ) - { - - /* - * X(k) = x(k+1) before exit - - * - because we expect to find solution at x(k) - */ - ae_v_move(&buf->ptr.p_double[offsxk], 1, &buf->ptr.p_double[offsxk1], 1, ae_v_len(offsxk,offsxk+n-1)); - break; - } - - /* - * BetaK = RK12/RK2 - * p(k+1) = r(k+1)+betak*p(k) - */ - betak = rk12/rk2; - ae_v_move(&buf->ptr.p_double[offspk1], 1, &buf->ptr.p_double[offsrk1], 1, ae_v_len(offspk1,offspk1+n-1)); - ae_v_addd(&buf->ptr.p_double[offspk1], 1, &buf->ptr.p_double[offspk], 1, ae_v_len(offspk1,offspk1+n-1), betak); - - /* - * r(k) := r(k+1) - * x(k) := x(k+1) - * p(k) := p(k+1) - */ - ae_v_move(&buf->ptr.p_double[offsrk], 1, &buf->ptr.p_double[offsrk1], 1, ae_v_len(offsrk,offsrk+n-1)); - ae_v_move(&buf->ptr.p_double[offsxk], 1, &buf->ptr.p_double[offsxk1], 1, ae_v_len(offsxk,offsxk+n-1)); - ae_v_move(&buf->ptr.p_double[offspk], 1, &buf->ptr.p_double[offspk1], 1, ae_v_len(offspk,offspk+n-1)); - rk2 = rk12; - } - - /* - * Calculate E2 - */ - rmatrixmv(m, n, a, 0, 0, 0, buf, offsxk, buf, offstmp1, _state); - rmatrixmv(n, m, a, 0, 0, 1, buf, offstmp1, buf, offstmp2, _state); - ae_v_addd(&buf->ptr.p_double[offstmp2], 1, &buf->ptr.p_double[offsxk], 1, ae_v_len(offstmp2,offstmp2+n-1), alpha); - ae_v_move(&buf->ptr.p_double[offsrk], 1, &b->ptr.p_double[0], 1, ae_v_len(offsrk,offsrk+n-1)); - ae_v_sub(&buf->ptr.p_double[offsrk], 1, &buf->ptr.p_double[offstmp2], 1, ae_v_len(offsrk,offsrk+n-1)); - v1 = ae_v_dotproduct(&buf->ptr.p_double[offsrk], 1, &buf->ptr.p_double[offsrk], 1, ae_v_len(offsrk,offsrk+n-1)); - e2 = ae_sqrt(v1, _state); - - /* - * Output result (if it was improved) - */ - if( ae_fp_less(e2,e1) ) - { - ae_v_move(&x->ptr.p_double[0], 1, &buf->ptr.p_double[offsxk], 1, ae_v_len(0,n-1)); - } -} - - -/************************************************************************* -Construction of linear conjugate gradient solver. - -State parameter passed using "shared" semantics (i.e. previous state is NOT -erased). When it is already initialized, we can reause prevously allocated -memory. - -INPUT PARAMETERS: - X - initial solution - B - right part - N - system size - State - structure; may be preallocated, if we want to reuse memory - -OUTPUT PARAMETERS: - State - structure which is used by FBLSCGIteration() to store - algorithm state between subsequent calls. - -NOTE: no error checking is done; caller must check all parameters, prevent - overflows, and so on. - - -- ALGLIB -- - Copyright 22.10.2009 by Bochkanov Sergey -*************************************************************************/ -void fblscgcreate(/* Real */ ae_vector* x, - /* Real */ ae_vector* b, - ae_int_t n, - fblslincgstate* state, - ae_state *_state) -{ - - - if( state->b.cntb, n, _state); - } - if( state->rk.cntrk, n, _state); - } - if( state->rk1.cntrk1, n, _state); - } - if( state->xk.cntxk, n, _state); - } - if( state->xk1.cntxk1, n, _state); - } - if( state->pk.cntpk, n, _state); - } - if( state->pk1.cntpk1, n, _state); - } - if( state->tmp2.cnttmp2, n, _state); - } - if( state->x.cntx, n, _state); - } - if( state->ax.cntax, n, _state); - } - state->n = n; - ae_v_move(&state->xk.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->b.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_vector_set_length(&state->rstate.ia, 1+1, _state); - ae_vector_set_length(&state->rstate.ra, 6+1, _state); - state->rstate.stage = -1; -} - - -/************************************************************************* -Linear CG solver, function relying on reverse communication to calculate -matrix-vector products. - -See comments for FBLSLinCGState structure for more info. - - -- ALGLIB -- - Copyright 22.10.2009 by Bochkanov Sergey -*************************************************************************/ -ae_bool fblscgiteration(fblslincgstate* state, ae_state *_state) -{ - ae_int_t n; - ae_int_t k; - double rk2; - double rk12; - double pap; - double s; - double betak; - double v1; - double v2; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - n = state->rstate.ia.ptr.p_int[0]; - k = state->rstate.ia.ptr.p_int[1]; - rk2 = state->rstate.ra.ptr.p_double[0]; - rk12 = state->rstate.ra.ptr.p_double[1]; - pap = state->rstate.ra.ptr.p_double[2]; - s = state->rstate.ra.ptr.p_double[3]; - betak = state->rstate.ra.ptr.p_double[4]; - v1 = state->rstate.ra.ptr.p_double[5]; - v2 = state->rstate.ra.ptr.p_double[6]; - } - else - { - n = 359; - k = -58; - rk2 = -919; - rk12 = -909; - pap = 81; - s = 255; - betak = 74; - v1 = -788; - v2 = 809; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - if( state->rstate.stage==1 ) - { - goto lbl_1; - } - if( state->rstate.stage==2 ) - { - goto lbl_2; - } - - /* - * Routine body - */ - - /* - * prepare locals - */ - n = state->n; - - /* - * Test for special case: B=0 - */ - v1 = ae_v_dotproduct(&state->b.ptr.p_double[0], 1, &state->b.ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( ae_fp_eq(v1,(double)(0)) ) - { - for(k=0; k<=n-1; k++) - { - state->xk.ptr.p_double[k] = (double)(0); - } - result = ae_false; - return result; - } - - /* - * r(0) = b-A*x(0) - * RK2 = r(0)'*r(0) - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - ae_v_move(&state->rk.ptr.p_double[0], 1, &state->b.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_sub(&state->rk.ptr.p_double[0], 1, &state->ax.ptr.p_double[0], 1, ae_v_len(0,n-1)); - rk2 = ae_v_dotproduct(&state->rk.ptr.p_double[0], 1, &state->rk.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->pk.ptr.p_double[0], 1, &state->rk.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->e1 = ae_sqrt(rk2, _state); - - /* - * Cycle - */ - k = 0; -lbl_3: - if( k>n-1 ) - { - goto lbl_5; - } - - /* - * Calculate A*p(k) - store in State.Tmp2 - * and p(k)'*A*p(k) - store in PAP - * - * If PAP=0, break (iteration is over) - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->pk.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->rstate.stage = 1; - goto lbl_rcomm; -lbl_1: - ae_v_move(&state->tmp2.ptr.p_double[0], 1, &state->ax.ptr.p_double[0], 1, ae_v_len(0,n-1)); - pap = state->xax; - if( !ae_isfinite(pap, _state) ) - { - goto lbl_5; - } - if( ae_fp_less_eq(pap,(double)(0)) ) - { - goto lbl_5; - } - - /* - * S = (r(k)'*r(k))/(p(k)'*A*p(k)) - */ - s = rk2/pap; - - /* - * x(k+1) = x(k) + S*p(k) - */ - ae_v_move(&state->xk1.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_addd(&state->xk1.ptr.p_double[0], 1, &state->pk.ptr.p_double[0], 1, ae_v_len(0,n-1), s); - - /* - * r(k+1) = r(k) - S*A*p(k) - * RK12 = r(k+1)'*r(k+1) - * - * Break if r(k+1) small enough (when compared to r(k)) - */ - ae_v_move(&state->rk1.ptr.p_double[0], 1, &state->rk.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_subd(&state->rk1.ptr.p_double[0], 1, &state->tmp2.ptr.p_double[0], 1, ae_v_len(0,n-1), s); - rk12 = ae_v_dotproduct(&state->rk1.ptr.p_double[0], 1, &state->rk1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( ae_fp_less_eq(ae_sqrt(rk12, _state),100*ae_machineepsilon*state->e1) ) - { - - /* - * X(k) = x(k+1) before exit - - * - because we expect to find solution at x(k) - */ - ae_v_move(&state->xk.ptr.p_double[0], 1, &state->xk1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - goto lbl_5; - } - - /* - * BetaK = RK12/RK2 - * p(k+1) = r(k+1)+betak*p(k) - * - * NOTE: we expect that BetaK won't overflow because of - * "Sqrt(RK12)<=100*MachineEpsilon*E1" test above. - */ - betak = rk12/rk2; - ae_v_move(&state->pk1.ptr.p_double[0], 1, &state->rk1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_addd(&state->pk1.ptr.p_double[0], 1, &state->pk.ptr.p_double[0], 1, ae_v_len(0,n-1), betak); - - /* - * r(k) := r(k+1) - * x(k) := x(k+1) - * p(k) := p(k+1) - */ - ae_v_move(&state->rk.ptr.p_double[0], 1, &state->rk1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->xk.ptr.p_double[0], 1, &state->xk1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->pk.ptr.p_double[0], 1, &state->pk1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - rk2 = rk12; - k = k+1; - goto lbl_3; -lbl_5: - - /* - * Calculate E2 - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->rstate.stage = 2; - goto lbl_rcomm; -lbl_2: - ae_v_move(&state->rk.ptr.p_double[0], 1, &state->b.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_sub(&state->rk.ptr.p_double[0], 1, &state->ax.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v1 = ae_v_dotproduct(&state->rk.ptr.p_double[0], 1, &state->rk.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->e2 = ae_sqrt(v1, _state); - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = n; - state->rstate.ia.ptr.p_int[1] = k; - state->rstate.ra.ptr.p_double[0] = rk2; - state->rstate.ra.ptr.p_double[1] = rk12; - state->rstate.ra.ptr.p_double[2] = pap; - state->rstate.ra.ptr.p_double[3] = s; - state->rstate.ra.ptr.p_double[4] = betak; - state->rstate.ra.ptr.p_double[5] = v1; - state->rstate.ra.ptr.p_double[6] = v2; - return result; -} - - -/************************************************************************* -Construction of GMRES(k) solver. - -State parameter passed using "shared" semantics (i.e. previous state is NOT -erased). When it is already initialized, we can reause prevously allocated -memory. - -After (but not before!) initialization you can tweak following fields (they -are initialized by default values, but you can change it): -* State.EpsOrt - stop if norm of new candidate for orthogonalization is below EpsOrt -* State.EpsRes - stop of residual decreased below EpsRes*|B| -* State.EpsRed - stop if relative reduction of residual |R(k+1)|/|R(k)|>EpsRed - -INPUT PARAMETERS: - B - right part - N - system size - K - iterations count, K>=1 - State - structure; may be preallocated, if we want to reuse memory - -OUTPUT PARAMETERS: - State - structure which is used by FBLSGMRESIteration() to store - algorithm state between subsequent calls. - -NOTE: no error checking is done; caller must check all parameters, prevent - overflows, and so on. - - -- ALGLIB -- - Copyright 18.11.2020 by Bochkanov Sergey -*************************************************************************/ -void fblsgmrescreate(/* Real */ ae_vector* b, - ae_int_t n, - ae_int_t k, - fblsgmresstate* state, - ae_state *_state) -{ - - - ae_assert((n>0&&k>0)&&k<=n, "FBLSGMRESCreate: incorrect params", _state); - state->n = n; - state->itscnt = k; - state->epsort = (1000+ae_sqrt((double)(n), _state))*ae_machineepsilon; - state->epsres = (1000+ae_sqrt((double)(n), _state))*ae_machineepsilon; - state->epsred = 1.0; - state->epsdiag = (10000+n)*ae_machineepsilon; - state->itsperformed = 0; - state->retcode = 0; - rcopyallocv(n, b, &state->b, _state); - rallocv(n, &state->x, _state); - rallocv(n, &state->ax, _state); - ae_vector_set_length(&state->rstate.ia, 4+1, _state); - ae_vector_set_length(&state->rstate.ra, 10+1, _state); - state->rstate.stage = -1; -} - - -/************************************************************************* -Linear CG solver, function relying on reverse communication to calculate -matrix-vector products. - -See comments for FBLSLinCGState structure for more info. - - -- ALGLIB -- - Copyright 22.10.2009 by Bochkanov Sergey -*************************************************************************/ -ae_bool fblsgmresiteration(fblsgmresstate* state, ae_state *_state) -{ - ae_int_t n; - ae_int_t itidx; - ae_int_t kdim; - double rmax; - double rmindiag; - double cs; - double sn; - double v; - double vv; - double anrm; - double qnrm; - double bnrm; - double resnrm; - double prevresnrm; - ae_int_t i; - ae_int_t j; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - n = state->rstate.ia.ptr.p_int[0]; - itidx = state->rstate.ia.ptr.p_int[1]; - kdim = state->rstate.ia.ptr.p_int[2]; - i = state->rstate.ia.ptr.p_int[3]; - j = state->rstate.ia.ptr.p_int[4]; - rmax = state->rstate.ra.ptr.p_double[0]; - rmindiag = state->rstate.ra.ptr.p_double[1]; - cs = state->rstate.ra.ptr.p_double[2]; - sn = state->rstate.ra.ptr.p_double[3]; - v = state->rstate.ra.ptr.p_double[4]; - vv = state->rstate.ra.ptr.p_double[5]; - anrm = state->rstate.ra.ptr.p_double[6]; - qnrm = state->rstate.ra.ptr.p_double[7]; - bnrm = state->rstate.ra.ptr.p_double[8]; - resnrm = state->rstate.ra.ptr.p_double[9]; - prevresnrm = state->rstate.ra.ptr.p_double[10]; - } - else - { - n = 205; - itidx = -838; - kdim = 939; - i = -526; - j = 763; - rmax = -541; - rmindiag = -698; - cs = -900; - sn = -318; - v = -940; - vv = 1016; - anrm = -229; - qnrm = -536; - bnrm = 487; - resnrm = -115; - prevresnrm = 886; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - - /* - * Routine body - */ - n = state->n; - state->retcode = 1; - - /* - * Set up Q0 - */ - rsetallocv(n, 0.0, &state->xs, _state); - bnrm = ae_sqrt(rdotv2(n, &state->b, _state), _state); - if( ae_fp_eq(bnrm,(double)(0)) ) - { - result = ae_false; - return result; - } - rallocm(state->itscnt+1, n, &state->qi, _state); - rallocm(state->itscnt, n, &state->aqi, _state); - rcopymulvr(n, 1/bnrm, &state->b, &state->qi, 0, _state); - rsetallocm(state->itscnt+1, state->itscnt, 0.0, &state->h, _state); - rsetallocm(state->itscnt+1, state->itscnt, 0.0, &state->hr, _state); - rsetallocm(state->itscnt+1, state->itscnt+1, 0.0, &state->hq, _state); - for(i=0; i<=state->itscnt; i++) - { - state->hq.ptr.pp_double[i][i] = (double)(1); - } - rsetallocv(state->itscnt+1, 0.0, &state->hqb, _state); - state->hqb.ptr.p_double[0] = bnrm; - - /* - * Perform iteration - */ - resnrm = bnrm; - kdim = 0; - rmax = (double)(0); - rmindiag = 1.0E99; - rsetallocv(state->itscnt, 0.0, &state->ys, _state); - rallocv(ae_maxint(n, state->itscnt+2, _state), &state->tmp0, _state); - rallocv(ae_maxint(n, state->itscnt+2, _state), &state->tmp1, _state); - itidx = 0; -lbl_1: - if( itidx>state->itscnt-1 ) - { - goto lbl_3; - } - prevresnrm = resnrm; - - /* - * Compute A*Qi[ItIdx], then compute Qi[ItIdx+1] - */ - rcopyrv(n, &state->qi, itidx, &state->x, _state); - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - rcopyvr(n, &state->ax, &state->aqi, itidx, _state); - anrm = ae_sqrt(rdotv2(n, &state->ax, _state), _state); - if( ae_fp_eq(anrm,(double)(0)) ) - { - state->retcode = 2; - goto lbl_3; - } - rowwisegramschmidt(&state->qi, itidx+1, n, &state->ax, &state->tmp0, ae_true, _state); - rowwisegramschmidt(&state->qi, itidx+1, n, &state->ax, &state->tmp1, ae_true, _state); - raddvc(itidx+1, 1.0, &state->tmp0, &state->h, itidx, _state); - raddvc(itidx+1, 1.0, &state->tmp1, &state->h, itidx, _state); - qnrm = ae_sqrt(rdotv2(n, &state->ax, _state), _state); - state->h.ptr.pp_double[itidx+1][itidx] = qnrm; - rmulv(n, 1/coalesce(qnrm, (double)(1), _state), &state->ax, _state); - rcopyvr(n, &state->ax, &state->qi, itidx+1, _state); - - /* - * We have QR decomposition of H from the previous iteration: - * * (ItIdx+1)*(ItIdx+1) orthogonal HQ embedded into larger (ItIdx+2)*(ItIdx+2) identity matrix - * * (ItIdx+1)*ItIdx triangular HR embedded into larger (ItIdx+2)*(ItIdx+1) zero matrix - * - * We just have to update QR decomposition after one more column is added to H: - * * multiply this column by HQ to obtain (ItIdx+2)-dimensional vector X - * * generate rotation to nullify last element of X to obtain (ItIdx+1)-dimensional vector Y - * that is copied into (ItIdx+1)-th column of HR - * * apply same rotation to HQ - * * apply same rotation to HQB - current right-hand side - */ - rcopycv(itidx+2, &state->h, itidx, &state->tmp0, _state); - rmatrixgemv(itidx+2, itidx+2, 1.0, &state->hq, 0, 0, 0, &state->tmp0, 0, 0.0, &state->tmp1, 0, _state); - generaterotation(state->tmp1.ptr.p_double[itidx], state->tmp1.ptr.p_double[itidx+1], &cs, &sn, &v, _state); - state->tmp1.ptr.p_double[itidx] = v; - state->tmp1.ptr.p_double[itidx+1] = (double)(0); - rmax = ae_maxreal(rmax, rmaxabsv(itidx+2, &state->tmp1, _state), _state); - rmindiag = ae_minreal(rmindiag, ae_fabs(v, _state), _state); - if( ae_fp_less_eq(rmindiag,rmax*state->epsdiag) ) - { - state->retcode = 3; - goto lbl_3; - } - rcopyvc(itidx+2, &state->tmp1, &state->hr, itidx, _state); - for(j=0; j<=itidx+1; j++) - { - v = state->hq.ptr.pp_double[itidx+0][j]; - vv = state->hq.ptr.pp_double[itidx+1][j]; - state->hq.ptr.pp_double[itidx+0][j] = cs*v+sn*vv; - state->hq.ptr.pp_double[itidx+1][j] = -sn*v+cs*vv; - } - v = state->hqb.ptr.p_double[itidx+0]; - vv = state->hqb.ptr.p_double[itidx+1]; - state->hqb.ptr.p_double[itidx+0] = cs*v+sn*vv; - state->hqb.ptr.p_double[itidx+1] = -sn*v+cs*vv; - resnrm = ae_fabs(state->hqb.ptr.p_double[itidx+1], _state); - - /* - * Previous attempt to extend R was successful (no small diagonal elements). - * Increase Krylov subspace dimensionality. - */ - kdim = kdim+1; - - /* - * Iteration is over. - * Terminate if: - * * last Qi was nearly zero after orthogonalization. - * * sufficient decrease of residual - * * stagnation of residual - */ - state->itsperformed = state->itsperformed+1; - if( ae_fp_less_eq(qnrm,state->epsort*anrm)||ae_fp_eq(qnrm,(double)(0)) ) - { - state->retcode = 4; - goto lbl_3; - } - if( ae_fp_less_eq(resnrm,state->epsres*bnrm) ) - { - state->retcode = 5; - goto lbl_3; - } - if( ae_fp_greater(resnrm/prevresnrm,state->epsred) ) - { - state->retcode = 6; - goto lbl_3; - } - itidx = itidx+1; - goto lbl_1; -lbl_3: - - /* - * Post-solve - */ - if( kdim>0 ) - { - rcopyv(kdim, &state->hqb, &state->ys, _state); - rmatrixtrsv(kdim, &state->hr, 0, 0, ae_true, ae_false, 0, &state->ys, 0, _state); - rmatrixmv(n, kdim, &state->qi, 0, 0, 1, &state->ys, 0, &state->xs, 0, _state); - } - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = n; - state->rstate.ia.ptr.p_int[1] = itidx; - state->rstate.ia.ptr.p_int[2] = kdim; - state->rstate.ia.ptr.p_int[3] = i; - state->rstate.ia.ptr.p_int[4] = j; - state->rstate.ra.ptr.p_double[0] = rmax; - state->rstate.ra.ptr.p_double[1] = rmindiag; - state->rstate.ra.ptr.p_double[2] = cs; - state->rstate.ra.ptr.p_double[3] = sn; - state->rstate.ra.ptr.p_double[4] = v; - state->rstate.ra.ptr.p_double[5] = vv; - state->rstate.ra.ptr.p_double[6] = anrm; - state->rstate.ra.ptr.p_double[7] = qnrm; - state->rstate.ra.ptr.p_double[8] = bnrm; - state->rstate.ra.ptr.p_double[9] = resnrm; - state->rstate.ra.ptr.p_double[10] = prevresnrm; - return result; -} - - -/************************************************************************* -Fast least squares solver, solves well conditioned system without -performing any checks for degeneracy, and using user-provided buffers -(which are automatically reallocated if too small). - -This function is intended for solution of moderately sized systems. It -uses factorization algorithms based on Level 2 BLAS operations, thus it -won't work efficiently on large scale systems. - -INPUT PARAMETERS: - A - array[M,N], system matrix. - Contents of A is destroyed during solution. - B - array[M], right part - M - number of equations - N - number of variables, N<=M - Tmp0, Tmp1, Tmp2- - buffers; function automatically allocates them, if they are - too small. They can be reused if function is called - several times. - -OUTPUT PARAMETERS: - B - solution (first N components, next M-N are zero) - - -- ALGLIB -- - Copyright 20.01.2012 by Bochkanov Sergey -*************************************************************************/ -void fblssolvels(/* Real */ ae_matrix* a, - /* Real */ ae_vector* b, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* tmp0, - /* Real */ ae_vector* tmp1, - /* Real */ ae_vector* tmp2, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - double v; - - - ae_assert(n>0, "FBLSSolveLS: N<=0", _state); - ae_assert(m>=n, "FBLSSolveLS: Mrows>=m, "FBLSSolveLS: Rows(A)cols>=n, "FBLSSolveLS: Cols(A)cnt>=m, "FBLSSolveLS: Length(B)ptr.p_double[i] = (double)(0); - } - ae_v_move(&tmp0->ptr.p_double[k], 1, &a->ptr.pp_double[k][k], a->stride, ae_v_len(k,m-1)); - tmp0->ptr.p_double[k] = (double)(1); - v = ae_v_dotproduct(&tmp0->ptr.p_double[k], 1, &b->ptr.p_double[k], 1, ae_v_len(k,m-1)); - v = v*tmp2->ptr.p_double[k]; - ae_v_subd(&b->ptr.p_double[k], 1, &tmp0->ptr.p_double[k], 1, ae_v_len(k,m-1), v); - } - - /* - * Solve triangular system - */ - b->ptr.p_double[n-1] = b->ptr.p_double[n-1]/a->ptr.pp_double[n-1][n-1]; - for(i=n-2; i>=0; i--) - { - v = ae_v_dotproduct(&a->ptr.pp_double[i][i+1], 1, &b->ptr.p_double[i+1], 1, ae_v_len(i+1,n-1)); - b->ptr.p_double[i] = (b->ptr.p_double[i]-v)/a->ptr.pp_double[i][i]; - } - for(i=n; i<=m-1; i++) - { - b->ptr.p_double[i] = 0.0; - } -} - - -void _fblslincgstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - fblslincgstate *p = (fblslincgstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ax, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rk, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rk1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xk, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xk1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->pk, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->pk1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->b, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); - ae_vector_init(&p->tmp2, 0, DT_REAL, _state, make_automatic); -} - - -void _fblslincgstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - fblslincgstate *dst = (fblslincgstate*)_dst; - fblslincgstate *src = (fblslincgstate*)_src; - dst->e1 = src->e1; - dst->e2 = src->e2; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->ax, &src->ax, _state, make_automatic); - dst->xax = src->xax; - dst->n = src->n; - ae_vector_init_copy(&dst->rk, &src->rk, _state, make_automatic); - ae_vector_init_copy(&dst->rk1, &src->rk1, _state, make_automatic); - ae_vector_init_copy(&dst->xk, &src->xk, _state, make_automatic); - ae_vector_init_copy(&dst->xk1, &src->xk1, _state, make_automatic); - ae_vector_init_copy(&dst->pk, &src->pk, _state, make_automatic); - ae_vector_init_copy(&dst->pk1, &src->pk1, _state, make_automatic); - ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic); - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); - ae_vector_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic); -} - - -void _fblslincgstate_clear(void* _p) -{ - fblslincgstate *p = (fblslincgstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->x); - ae_vector_clear(&p->ax); - ae_vector_clear(&p->rk); - ae_vector_clear(&p->rk1); - ae_vector_clear(&p->xk); - ae_vector_clear(&p->xk1); - ae_vector_clear(&p->pk); - ae_vector_clear(&p->pk1); - ae_vector_clear(&p->b); - _rcommstate_clear(&p->rstate); - ae_vector_clear(&p->tmp2); -} - - -void _fblslincgstate_destroy(void* _p) -{ - fblslincgstate *p = (fblslincgstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->ax); - ae_vector_destroy(&p->rk); - ae_vector_destroy(&p->rk1); - ae_vector_destroy(&p->xk); - ae_vector_destroy(&p->xk1); - ae_vector_destroy(&p->pk); - ae_vector_destroy(&p->pk1); - ae_vector_destroy(&p->b); - _rcommstate_destroy(&p->rstate); - ae_vector_destroy(&p->tmp2); -} - - -void _fblsgmresstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - fblsgmresstate *p = (fblsgmresstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->b, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ax, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xs, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->qi, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->aqi, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->h, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->hq, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->hr, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->hqb, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ys, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); -} - - -void _fblsgmresstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - fblsgmresstate *dst = (fblsgmresstate*)_dst; - fblsgmresstate *src = (fblsgmresstate*)_src; - ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic); - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->ax, &src->ax, _state, make_automatic); - ae_vector_init_copy(&dst->xs, &src->xs, _state, make_automatic); - ae_matrix_init_copy(&dst->qi, &src->qi, _state, make_automatic); - ae_matrix_init_copy(&dst->aqi, &src->aqi, _state, make_automatic); - ae_matrix_init_copy(&dst->h, &src->h, _state, make_automatic); - ae_matrix_init_copy(&dst->hq, &src->hq, _state, make_automatic); - ae_matrix_init_copy(&dst->hr, &src->hr, _state, make_automatic); - ae_vector_init_copy(&dst->hqb, &src->hqb, _state, make_automatic); - ae_vector_init_copy(&dst->ys, &src->ys, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic); - dst->n = src->n; - dst->itscnt = src->itscnt; - dst->epsort = src->epsort; - dst->epsres = src->epsres; - dst->epsred = src->epsred; - dst->epsdiag = src->epsdiag; - dst->itsperformed = src->itsperformed; - dst->retcode = src->retcode; - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); -} - - -void _fblsgmresstate_clear(void* _p) -{ - fblsgmresstate *p = (fblsgmresstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->b); - ae_vector_clear(&p->x); - ae_vector_clear(&p->ax); - ae_vector_clear(&p->xs); - ae_matrix_clear(&p->qi); - ae_matrix_clear(&p->aqi); - ae_matrix_clear(&p->h); - ae_matrix_clear(&p->hq); - ae_matrix_clear(&p->hr); - ae_vector_clear(&p->hqb); - ae_vector_clear(&p->ys); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->tmp1); - _rcommstate_clear(&p->rstate); -} - - -void _fblsgmresstate_destroy(void* _p) -{ - fblsgmresstate *p = (fblsgmresstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->b); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->ax); - ae_vector_destroy(&p->xs); - ae_matrix_destroy(&p->qi); - ae_matrix_destroy(&p->aqi); - ae_matrix_destroy(&p->h); - ae_matrix_destroy(&p->hq); - ae_matrix_destroy(&p->hr); - ae_vector_destroy(&p->hqb); - ae_vector_destroy(&p->ys); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->tmp1); - _rcommstate_destroy(&p->rstate); -} - - -#endif -#if defined(AE_COMPILE_BDSVD) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Singular value decomposition of a bidiagonal matrix (extended algorithm) - -COMMERCIAL EDITION OF ALGLIB: - - ! Commercial version of ALGLIB includes one important improvement of - ! this function, which can be used from C++ and C#: - ! * Intel MKL support (lightweight Intel MKL is shipped with ALGLIB) - ! - ! Intel MKL gives approximately constant (with respect to number of - ! worker threads) acceleration factor which depends on CPU being used, - ! problem size and "baseline" ALGLIB edition which is used for - ! comparison. - ! - ! Generally, commercial ALGLIB is several times faster than open-source - ! generic C edition, and many times faster than open-source C# edition. - ! - ! Multithreaded acceleration is NOT supported for this function. - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -The algorithm performs the singular value decomposition of a bidiagonal -matrix B (upper or lower) representing it as B = Q*S*P^T, where Q and P - -orthogonal matrices, S - diagonal matrix with non-negative elements on the -main diagonal, in descending order. - -The algorithm finds singular values. In addition, the algorithm can -calculate matrices Q and P (more precisely, not the matrices, but their -product with given matrices U and VT - U*Q and (P^T)*VT)). Of course, -matrices U and VT can be of any type, including identity. Furthermore, the -algorithm can calculate Q'*C (this product is calculated more effectively -than U*Q, because this calculation operates with rows instead of matrix -columns). - -The feature of the algorithm is its ability to find all singular values -including those which are arbitrarily close to 0 with relative accuracy -close to machine precision. If the parameter IsFractionalAccuracyRequired -is set to True, all singular values will have high relative accuracy close -to machine precision. If the parameter is set to False, only the biggest -singular value will have relative accuracy close to machine precision. -The absolute error of other singular values is equal to the absolute error -of the biggest singular value. - -Input parameters: - D - main diagonal of matrix B. - Array whose index ranges within [0..N-1]. - E - superdiagonal (or subdiagonal) of matrix B. - Array whose index ranges within [0..N-2]. - N - size of matrix B. - IsUpper - True, if the matrix is upper bidiagonal. - IsFractionalAccuracyRequired - - THIS PARAMETER IS IGNORED SINCE ALGLIB 3.5.0 - SINGULAR VALUES ARE ALWAYS SEARCHED WITH HIGH ACCURACY. - U - matrix to be multiplied by Q. - Array whose indexes range within [0..NRU-1, 0..N-1]. - The matrix can be bigger, in that case only the submatrix - [0..NRU-1, 0..N-1] will be multiplied by Q. - NRU - number of rows in matrix U. - C - matrix to be multiplied by Q'. - Array whose indexes range within [0..N-1, 0..NCC-1]. - The matrix can be bigger, in that case only the submatrix - [0..N-1, 0..NCC-1] will be multiplied by Q'. - NCC - number of columns in matrix C. - VT - matrix to be multiplied by P^T. - Array whose indexes range within [0..N-1, 0..NCVT-1]. - The matrix can be bigger, in that case only the submatrix - [0..N-1, 0..NCVT-1] will be multiplied by P^T. - NCVT - number of columns in matrix VT. - -Output parameters: - D - singular values of matrix B in descending order. - U - if NRU>0, contains matrix U*Q. - VT - if NCVT>0, contains matrix (P^T)*VT. - C - if NCC>0, contains matrix Q'*C. - -Result: - True, if the algorithm has converged. - False, if the algorithm hasn't converged (rare case). - -NOTE: multiplication U*Q is performed by means of transposition to internal - buffer, multiplication and backward transposition. It helps to avoid - costly columnwise operations and speed-up algorithm. - -Additional information: - The type of convergence is controlled by the internal parameter TOL. - If the parameter is greater than 0, the singular values will have - relative accuracy TOL. If TOL<0, the singular values will have - absolute accuracy ABS(TOL)*norm(B). - By default, |TOL| falls within the range of 10*Epsilon and 100*Epsilon, - where Epsilon is the machine precision. It is not recommended to use - TOL less than 10*Epsilon since this will considerably slow down the - algorithm and may not lead to error decreasing. - -History: - * 31 March, 2007. - changed MAXITR from 6 to 12. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - October 31, 1999. -*************************************************************************/ -ae_bool rmatrixbdsvd(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_bool isupper, - ae_bool isfractionalaccuracyrequired, - /* Real */ ae_matrix* u, - ae_int_t nru, - /* Real */ ae_matrix* c, - ae_int_t ncc, - /* Real */ ae_matrix* vt, - ae_int_t ncvt, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _e; - ae_int_t i; - ae_vector en; - ae_vector d1; - ae_vector e1; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_e, 0, sizeof(_e)); - memset(&en, 0, sizeof(en)); - memset(&d1, 0, sizeof(d1)); - memset(&e1, 0, sizeof(e1)); - ae_vector_init_copy(&_e, e, _state, ae_true); - e = &_e; - ae_vector_init(&en, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&e1, 0, DT_REAL, _state, ae_true); - - result = ae_false; - - /* - * Try to use MKL - */ - ae_vector_set_length(&en, n, _state); - for(i=0; i<=n-2; i++) - { - en.ptr.p_double[i] = e->ptr.p_double[i]; - } - en.ptr.p_double[n-1] = 0.0; - if( rmatrixbdsvdmkl(d, &en, n, isupper, u, nru, c, ncc, vt, ncvt, &result, _state) ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Use ALGLIB code - */ - ae_vector_set_length(&d1, n+1, _state); - ae_v_move(&d1.ptr.p_double[1], 1, &d->ptr.p_double[0], 1, ae_v_len(1,n)); - if( n>1 ) - { - ae_vector_set_length(&e1, n-1+1, _state); - ae_v_move(&e1.ptr.p_double[1], 1, &e->ptr.p_double[0], 1, ae_v_len(1,n-1)); - } - result = bdsvd_bidiagonalsvddecompositioninternal(&d1, &e1, n, isupper, isfractionalaccuracyrequired, u, 0, nru, c, 0, ncc, vt, 0, ncvt, _state); - ae_v_move(&d->ptr.p_double[0], 1, &d1.ptr.p_double[1], 1, ae_v_len(0,n-1)); - ae_frame_leave(_state); - return result; -} - - -ae_bool bidiagonalsvddecomposition(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_bool isupper, - ae_bool isfractionalaccuracyrequired, - /* Real */ ae_matrix* u, - ae_int_t nru, - /* Real */ ae_matrix* c, - ae_int_t ncc, - /* Real */ ae_matrix* vt, - ae_int_t ncvt, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _e; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_e, 0, sizeof(_e)); - ae_vector_init_copy(&_e, e, _state, ae_true); - e = &_e; - - result = bdsvd_bidiagonalsvddecompositioninternal(d, e, n, isupper, isfractionalaccuracyrequired, u, 1, nru, c, 1, ncc, vt, 1, ncvt, _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Internal working subroutine for bidiagonal decomposition -*************************************************************************/ -static ae_bool bdsvd_bidiagonalsvddecompositioninternal(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_bool isupper, - ae_bool isfractionalaccuracyrequired, - /* Real */ ae_matrix* uu, - ae_int_t ustart, - ae_int_t nru, - /* Real */ ae_matrix* c, - ae_int_t cstart, - ae_int_t ncc, - /* Real */ ae_matrix* vt, - ae_int_t vstart, - ae_int_t ncvt, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _e; - ae_int_t i; - ae_int_t idir; - ae_int_t isub; - ae_int_t iter; - ae_int_t j; - ae_int_t ll; - ae_int_t lll; - ae_int_t m; - ae_int_t maxit; - ae_int_t oldll; - ae_int_t oldm; - double abse; - double abss; - double cosl; - double cosr; - double cs; - double eps; - double f; - double g; - double h; - double mu; - double oldcs; - double oldsn; - double r; - double shift; - double sigmn; - double sigmx; - double sinl; - double sinr; - double sll; - double smax; - double smin; - double sminl; - double sminoa; - double sn; - double thresh; - double tol; - double tolmul; - double unfl; - ae_vector work0; - ae_vector work1; - ae_vector work2; - ae_vector work3; - ae_int_t maxitr; - ae_bool matrixsplitflag; - ae_bool iterflag; - ae_vector utemp; - ae_vector vttemp; - ae_vector ctemp; - ae_vector etemp; - ae_matrix ut; - ae_bool fwddir; - double tmp; - ae_int_t mm1; - ae_int_t mm0; - ae_bool bchangedir; - ae_int_t uend; - ae_int_t cend; - ae_int_t vend; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_e, 0, sizeof(_e)); - memset(&work0, 0, sizeof(work0)); - memset(&work1, 0, sizeof(work1)); - memset(&work2, 0, sizeof(work2)); - memset(&work3, 0, sizeof(work3)); - memset(&utemp, 0, sizeof(utemp)); - memset(&vttemp, 0, sizeof(vttemp)); - memset(&ctemp, 0, sizeof(ctemp)); - memset(&etemp, 0, sizeof(etemp)); - memset(&ut, 0, sizeof(ut)); - ae_vector_init_copy(&_e, e, _state, ae_true); - e = &_e; - ae_vector_init(&work0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work3, 0, DT_REAL, _state, ae_true); - ae_vector_init(&utemp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vttemp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ctemp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&etemp, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ut, 0, 0, DT_REAL, _state, ae_true); - - result = ae_true; - if( n==0 ) - { - ae_frame_leave(_state); - return result; - } - if( n==1 ) - { - if( ae_fp_less(d->ptr.p_double[1],(double)(0)) ) - { - d->ptr.p_double[1] = -d->ptr.p_double[1]; - if( ncvt>0 ) - { - ae_v_muld(&vt->ptr.pp_double[vstart][vstart], 1, ae_v_len(vstart,vstart+ncvt-1), -1); - } - } - ae_frame_leave(_state); - return result; - } - - /* - * these initializers are not really necessary, - * but without them compiler complains about uninitialized locals - */ - ll = 0; - oldsn = (double)(0); - - /* - * init - */ - ae_vector_set_length(&work0, n-1+1, _state); - ae_vector_set_length(&work1, n-1+1, _state); - ae_vector_set_length(&work2, n-1+1, _state); - ae_vector_set_length(&work3, n-1+1, _state); - uend = ustart+ae_maxint(nru-1, 0, _state); - vend = vstart+ae_maxint(ncvt-1, 0, _state); - cend = cstart+ae_maxint(ncc-1, 0, _state); - ae_vector_set_length(&utemp, uend+1, _state); - ae_vector_set_length(&vttemp, vend+1, _state); - ae_vector_set_length(&ctemp, cend+1, _state); - maxitr = 12; - fwddir = ae_true; - if( nru>0 ) - { - ae_matrix_set_length(&ut, ustart+n, ustart+nru, _state); - rmatrixtranspose(nru, n, uu, ustart, ustart, &ut, ustart, ustart, _state); - } - - /* - * resize E from N-1 to N - */ - ae_vector_set_length(&etemp, n+1, _state); - for(i=1; i<=n-1; i++) - { - etemp.ptr.p_double[i] = e->ptr.p_double[i]; - } - ae_vector_set_length(e, n+1, _state); - for(i=1; i<=n-1; i++) - { - e->ptr.p_double[i] = etemp.ptr.p_double[i]; - } - e->ptr.p_double[n] = (double)(0); - idir = 0; - - /* - * Get machine constants - */ - eps = ae_machineepsilon; - unfl = ae_minrealnumber; - - /* - * If matrix lower bidiagonal, rotate to be upper bidiagonal - * by applying Givens rotations on the left - */ - if( !isupper ) - { - for(i=1; i<=n-1; i++) - { - generaterotation(d->ptr.p_double[i], e->ptr.p_double[i], &cs, &sn, &r, _state); - d->ptr.p_double[i] = r; - e->ptr.p_double[i] = sn*d->ptr.p_double[i+1]; - d->ptr.p_double[i+1] = cs*d->ptr.p_double[i+1]; - work0.ptr.p_double[i] = cs; - work1.ptr.p_double[i] = sn; - } - - /* - * Update singular vectors if desired - */ - if( nru>0 ) - { - applyrotationsfromtheleft(fwddir, 1+ustart-1, n+ustart-1, ustart, uend, &work0, &work1, &ut, &utemp, _state); - } - if( ncc>0 ) - { - applyrotationsfromtheleft(fwddir, 1+cstart-1, n+cstart-1, cstart, cend, &work0, &work1, c, &ctemp, _state); - } - } - - /* - * Compute singular values to relative accuracy TOL - * (By setting TOL to be negative, algorithm will compute - * singular values to absolute accuracy ABS(TOL)*norm(input matrix)) - */ - tolmul = ae_maxreal((double)(10), ae_minreal((double)(100), ae_pow(eps, -0.125, _state), _state), _state); - tol = tolmul*eps; - - /* - * Compute approximate maximum, minimum singular values - */ - smax = (double)(0); - for(i=1; i<=n; i++) - { - smax = ae_maxreal(smax, ae_fabs(d->ptr.p_double[i], _state), _state); - } - for(i=1; i<=n-1; i++) - { - smax = ae_maxreal(smax, ae_fabs(e->ptr.p_double[i], _state), _state); - } - sminl = (double)(0); - if( ae_fp_greater_eq(tol,(double)(0)) ) - { - - /* - * Relative accuracy desired - */ - sminoa = ae_fabs(d->ptr.p_double[1], _state); - if( ae_fp_neq(sminoa,(double)(0)) ) - { - mu = sminoa; - for(i=2; i<=n; i++) - { - mu = ae_fabs(d->ptr.p_double[i], _state)*(mu/(mu+ae_fabs(e->ptr.p_double[i-1], _state))); - sminoa = ae_minreal(sminoa, mu, _state); - if( ae_fp_eq(sminoa,(double)(0)) ) - { - break; - } - } - } - sminoa = sminoa/ae_sqrt((double)(n), _state); - thresh = ae_maxreal(tol*sminoa, maxitr*n*n*unfl, _state); - } - else - { - - /* - * Absolute accuracy desired - */ - thresh = ae_maxreal(ae_fabs(tol, _state)*smax, maxitr*n*n*unfl, _state); - } - - /* - * Prepare for main iteration loop for the singular values - * (MAXIT is the maximum number of passes through the inner - * loop permitted before nonconvergence signalled.) - */ - maxit = maxitr*n*n; - iter = 0; - oldll = -1; - oldm = -1; - - /* - * M points to last element of unconverged part of matrix - */ - m = n; - - /* - * Begin main iteration loop - */ - for(;;) - { - - /* - * Check for convergence or exceeding iteration count - */ - if( m<=1 ) - { - break; - } - if( iter>maxit ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - - /* - * Find diagonal block of matrix to work on - */ - if( ae_fp_less(tol,(double)(0))&&ae_fp_less_eq(ae_fabs(d->ptr.p_double[m], _state),thresh) ) - { - d->ptr.p_double[m] = (double)(0); - } - smax = ae_fabs(d->ptr.p_double[m], _state); - smin = smax; - matrixsplitflag = ae_false; - for(lll=1; lll<=m-1; lll++) - { - ll = m-lll; - abss = ae_fabs(d->ptr.p_double[ll], _state); - abse = ae_fabs(e->ptr.p_double[ll], _state); - if( ae_fp_less(tol,(double)(0))&&ae_fp_less_eq(abss,thresh) ) - { - d->ptr.p_double[ll] = (double)(0); - } - if( ae_fp_less_eq(abse,thresh) ) - { - matrixsplitflag = ae_true; - break; - } - smin = ae_minreal(smin, abss, _state); - smax = ae_maxreal(smax, ae_maxreal(abss, abse, _state), _state); - } - if( !matrixsplitflag ) - { - ll = 0; - } - else - { - - /* - * Matrix splits since E(LL) = 0 - */ - e->ptr.p_double[ll] = (double)(0); - if( ll==m-1 ) - { - - /* - * Convergence of bottom singular value, return to top of loop - */ - m = m-1; - continue; - } - } - ll = ll+1; - - /* - * E(LL) through E(M-1) are nonzero, E(LL-1) is zero - */ - if( ll==m-1 ) - { - - /* - * 2 by 2 block, handle separately - */ - bdsvd_svdv2x2(d->ptr.p_double[m-1], e->ptr.p_double[m-1], d->ptr.p_double[m], &sigmn, &sigmx, &sinr, &cosr, &sinl, &cosl, _state); - d->ptr.p_double[m-1] = sigmx; - e->ptr.p_double[m-1] = (double)(0); - d->ptr.p_double[m] = sigmn; - - /* - * Compute singular vectors, if desired - */ - if( ncvt>0 ) - { - mm0 = m+(vstart-1); - mm1 = m-1+(vstart-1); - ae_v_moved(&vttemp.ptr.p_double[vstart], 1, &vt->ptr.pp_double[mm1][vstart], 1, ae_v_len(vstart,vend), cosr); - ae_v_addd(&vttemp.ptr.p_double[vstart], 1, &vt->ptr.pp_double[mm0][vstart], 1, ae_v_len(vstart,vend), sinr); - ae_v_muld(&vt->ptr.pp_double[mm0][vstart], 1, ae_v_len(vstart,vend), cosr); - ae_v_subd(&vt->ptr.pp_double[mm0][vstart], 1, &vt->ptr.pp_double[mm1][vstart], 1, ae_v_len(vstart,vend), sinr); - ae_v_move(&vt->ptr.pp_double[mm1][vstart], 1, &vttemp.ptr.p_double[vstart], 1, ae_v_len(vstart,vend)); - } - if( nru>0 ) - { - mm0 = m+ustart-1; - mm1 = m-1+ustart-1; - ae_v_moved(&utemp.ptr.p_double[ustart], 1, &ut.ptr.pp_double[mm1][ustart], 1, ae_v_len(ustart,uend), cosl); - ae_v_addd(&utemp.ptr.p_double[ustart], 1, &ut.ptr.pp_double[mm0][ustart], 1, ae_v_len(ustart,uend), sinl); - ae_v_muld(&ut.ptr.pp_double[mm0][ustart], 1, ae_v_len(ustart,uend), cosl); - ae_v_subd(&ut.ptr.pp_double[mm0][ustart], 1, &ut.ptr.pp_double[mm1][ustart], 1, ae_v_len(ustart,uend), sinl); - ae_v_move(&ut.ptr.pp_double[mm1][ustart], 1, &utemp.ptr.p_double[ustart], 1, ae_v_len(ustart,uend)); - } - if( ncc>0 ) - { - mm0 = m+cstart-1; - mm1 = m-1+cstart-1; - ae_v_moved(&ctemp.ptr.p_double[cstart], 1, &c->ptr.pp_double[mm1][cstart], 1, ae_v_len(cstart,cend), cosl); - ae_v_addd(&ctemp.ptr.p_double[cstart], 1, &c->ptr.pp_double[mm0][cstart], 1, ae_v_len(cstart,cend), sinl); - ae_v_muld(&c->ptr.pp_double[mm0][cstart], 1, ae_v_len(cstart,cend), cosl); - ae_v_subd(&c->ptr.pp_double[mm0][cstart], 1, &c->ptr.pp_double[mm1][cstart], 1, ae_v_len(cstart,cend), sinl); - ae_v_move(&c->ptr.pp_double[mm1][cstart], 1, &ctemp.ptr.p_double[cstart], 1, ae_v_len(cstart,cend)); - } - m = m-2; - continue; - } - - /* - * If working on new submatrix, choose shift direction - * (from larger end diagonal element towards smaller) - * - * Previously was - * "if (LL>OLDM) or (M - * Very strange that LAPACK still contains it. - */ - bchangedir = ae_false; - if( idir==1&&ae_fp_less(ae_fabs(d->ptr.p_double[ll], _state),1.0E-3*ae_fabs(d->ptr.p_double[m], _state)) ) - { - bchangedir = ae_true; - } - if( idir==2&&ae_fp_less(ae_fabs(d->ptr.p_double[m], _state),1.0E-3*ae_fabs(d->ptr.p_double[ll], _state)) ) - { - bchangedir = ae_true; - } - if( (ll!=oldll||m!=oldm)||bchangedir ) - { - if( ae_fp_greater_eq(ae_fabs(d->ptr.p_double[ll], _state),ae_fabs(d->ptr.p_double[m], _state)) ) - { - - /* - * Chase bulge from top (big end) to bottom (small end) - */ - idir = 1; - } - else - { - - /* - * Chase bulge from bottom (big end) to top (small end) - */ - idir = 2; - } - } - - /* - * Apply convergence tests - */ - if( idir==1 ) - { - - /* - * Run convergence test in forward direction - * First apply standard test to bottom of matrix - */ - if( ae_fp_less_eq(ae_fabs(e->ptr.p_double[m-1], _state),ae_fabs(tol, _state)*ae_fabs(d->ptr.p_double[m], _state))||(ae_fp_less(tol,(double)(0))&&ae_fp_less_eq(ae_fabs(e->ptr.p_double[m-1], _state),thresh)) ) - { - e->ptr.p_double[m-1] = (double)(0); - continue; - } - if( ae_fp_greater_eq(tol,(double)(0)) ) - { - - /* - * If relative accuracy desired, - * apply convergence criterion forward - */ - mu = ae_fabs(d->ptr.p_double[ll], _state); - sminl = mu; - iterflag = ae_false; - for(lll=ll; lll<=m-1; lll++) - { - if( ae_fp_less_eq(ae_fabs(e->ptr.p_double[lll], _state),tol*mu) ) - { - e->ptr.p_double[lll] = (double)(0); - iterflag = ae_true; - break; - } - mu = ae_fabs(d->ptr.p_double[lll+1], _state)*(mu/(mu+ae_fabs(e->ptr.p_double[lll], _state))); - sminl = ae_minreal(sminl, mu, _state); - } - if( iterflag ) - { - continue; - } - } - } - else - { - - /* - * Run convergence test in backward direction - * First apply standard test to top of matrix - */ - if( ae_fp_less_eq(ae_fabs(e->ptr.p_double[ll], _state),ae_fabs(tol, _state)*ae_fabs(d->ptr.p_double[ll], _state))||(ae_fp_less(tol,(double)(0))&&ae_fp_less_eq(ae_fabs(e->ptr.p_double[ll], _state),thresh)) ) - { - e->ptr.p_double[ll] = (double)(0); - continue; - } - if( ae_fp_greater_eq(tol,(double)(0)) ) - { - - /* - * If relative accuracy desired, - * apply convergence criterion backward - */ - mu = ae_fabs(d->ptr.p_double[m], _state); - sminl = mu; - iterflag = ae_false; - for(lll=m-1; lll>=ll; lll--) - { - if( ae_fp_less_eq(ae_fabs(e->ptr.p_double[lll], _state),tol*mu) ) - { - e->ptr.p_double[lll] = (double)(0); - iterflag = ae_true; - break; - } - mu = ae_fabs(d->ptr.p_double[lll], _state)*(mu/(mu+ae_fabs(e->ptr.p_double[lll], _state))); - sminl = ae_minreal(sminl, mu, _state); - } - if( iterflag ) - { - continue; - } - } - } - oldll = ll; - oldm = m; - - /* - * Compute shift. First, test if shifting would ruin relative - * accuracy, and if so set the shift to zero. - */ - if( ae_fp_greater_eq(tol,(double)(0))&&ae_fp_less_eq(n*tol*(sminl/smax),ae_maxreal(eps, 0.01*tol, _state)) ) - { - - /* - * Use a zero shift to avoid loss of relative accuracy - */ - shift = (double)(0); - } - else - { - - /* - * Compute the shift from 2-by-2 block at end of matrix - */ - if( idir==1 ) - { - sll = ae_fabs(d->ptr.p_double[ll], _state); - bdsvd_svd2x2(d->ptr.p_double[m-1], e->ptr.p_double[m-1], d->ptr.p_double[m], &shift, &r, _state); - } - else - { - sll = ae_fabs(d->ptr.p_double[m], _state); - bdsvd_svd2x2(d->ptr.p_double[ll], e->ptr.p_double[ll], d->ptr.p_double[ll+1], &shift, &r, _state); - } - - /* - * Test if shift negligible, and if so set to zero - */ - if( ae_fp_greater(sll,(double)(0)) ) - { - if( ae_fp_less(ae_sqr(shift/sll, _state),eps) ) - { - shift = (double)(0); - } - } - } - - /* - * Increment iteration count - */ - iter = iter+m-ll; - - /* - * If SHIFT = 0, do simplified QR iteration - */ - if( ae_fp_eq(shift,(double)(0)) ) - { - if( idir==1 ) - { - - /* - * Chase bulge from top to bottom - * Save cosines and sines for later singular vector updates - */ - cs = (double)(1); - oldcs = (double)(1); - for(i=ll; i<=m-1; i++) - { - generaterotation(d->ptr.p_double[i]*cs, e->ptr.p_double[i], &cs, &sn, &r, _state); - if( i>ll ) - { - e->ptr.p_double[i-1] = oldsn*r; - } - generaterotation(oldcs*r, d->ptr.p_double[i+1]*sn, &oldcs, &oldsn, &tmp, _state); - d->ptr.p_double[i] = tmp; - work0.ptr.p_double[i-ll+1] = cs; - work1.ptr.p_double[i-ll+1] = sn; - work2.ptr.p_double[i-ll+1] = oldcs; - work3.ptr.p_double[i-ll+1] = oldsn; - } - h = d->ptr.p_double[m]*cs; - d->ptr.p_double[m] = h*oldcs; - e->ptr.p_double[m-1] = h*oldsn; - - /* - * Update singular vectors - */ - if( ncvt>0 ) - { - applyrotationsfromtheleft(fwddir, ll+vstart-1, m+vstart-1, vstart, vend, &work0, &work1, vt, &vttemp, _state); - } - if( nru>0 ) - { - applyrotationsfromtheleft(fwddir, ll+ustart-1, m+ustart-1, ustart, uend, &work2, &work3, &ut, &utemp, _state); - } - if( ncc>0 ) - { - applyrotationsfromtheleft(fwddir, ll+cstart-1, m+cstart-1, cstart, cend, &work2, &work3, c, &ctemp, _state); - } - - /* - * Test convergence - */ - if( ae_fp_less_eq(ae_fabs(e->ptr.p_double[m-1], _state),thresh) ) - { - e->ptr.p_double[m-1] = (double)(0); - } - } - else - { - - /* - * Chase bulge from bottom to top - * Save cosines and sines for later singular vector updates - */ - cs = (double)(1); - oldcs = (double)(1); - for(i=m; i>=ll+1; i--) - { - generaterotation(d->ptr.p_double[i]*cs, e->ptr.p_double[i-1], &cs, &sn, &r, _state); - if( iptr.p_double[i] = oldsn*r; - } - generaterotation(oldcs*r, d->ptr.p_double[i-1]*sn, &oldcs, &oldsn, &tmp, _state); - d->ptr.p_double[i] = tmp; - work0.ptr.p_double[i-ll] = cs; - work1.ptr.p_double[i-ll] = -sn; - work2.ptr.p_double[i-ll] = oldcs; - work3.ptr.p_double[i-ll] = -oldsn; - } - h = d->ptr.p_double[ll]*cs; - d->ptr.p_double[ll] = h*oldcs; - e->ptr.p_double[ll] = h*oldsn; - - /* - * Update singular vectors - */ - if( ncvt>0 ) - { - applyrotationsfromtheleft(!fwddir, ll+vstart-1, m+vstart-1, vstart, vend, &work2, &work3, vt, &vttemp, _state); - } - if( nru>0 ) - { - applyrotationsfromtheleft(!fwddir, ll+ustart-1, m+ustart-1, ustart, uend, &work0, &work1, &ut, &utemp, _state); - } - if( ncc>0 ) - { - applyrotationsfromtheleft(!fwddir, ll+cstart-1, m+cstart-1, cstart, cend, &work0, &work1, c, &ctemp, _state); - } - - /* - * Test convergence - */ - if( ae_fp_less_eq(ae_fabs(e->ptr.p_double[ll], _state),thresh) ) - { - e->ptr.p_double[ll] = (double)(0); - } - } - } - else - { - - /* - * Use nonzero shift - */ - if( idir==1 ) - { - - /* - * Chase bulge from top to bottom - * Save cosines and sines for later singular vector updates - */ - f = (ae_fabs(d->ptr.p_double[ll], _state)-shift)*(bdsvd_extsignbdsqr((double)(1), d->ptr.p_double[ll], _state)+shift/d->ptr.p_double[ll]); - g = e->ptr.p_double[ll]; - for(i=ll; i<=m-1; i++) - { - generaterotation(f, g, &cosr, &sinr, &r, _state); - if( i>ll ) - { - e->ptr.p_double[i-1] = r; - } - f = cosr*d->ptr.p_double[i]+sinr*e->ptr.p_double[i]; - e->ptr.p_double[i] = cosr*e->ptr.p_double[i]-sinr*d->ptr.p_double[i]; - g = sinr*d->ptr.p_double[i+1]; - d->ptr.p_double[i+1] = cosr*d->ptr.p_double[i+1]; - generaterotation(f, g, &cosl, &sinl, &r, _state); - d->ptr.p_double[i] = r; - f = cosl*e->ptr.p_double[i]+sinl*d->ptr.p_double[i+1]; - d->ptr.p_double[i+1] = cosl*d->ptr.p_double[i+1]-sinl*e->ptr.p_double[i]; - if( iptr.p_double[i+1]; - e->ptr.p_double[i+1] = cosl*e->ptr.p_double[i+1]; - } - work0.ptr.p_double[i-ll+1] = cosr; - work1.ptr.p_double[i-ll+1] = sinr; - work2.ptr.p_double[i-ll+1] = cosl; - work3.ptr.p_double[i-ll+1] = sinl; - } - e->ptr.p_double[m-1] = f; - - /* - * Update singular vectors - */ - if( ncvt>0 ) - { - applyrotationsfromtheleft(fwddir, ll+vstart-1, m+vstart-1, vstart, vend, &work0, &work1, vt, &vttemp, _state); - } - if( nru>0 ) - { - applyrotationsfromtheleft(fwddir, ll+ustart-1, m+ustart-1, ustart, uend, &work2, &work3, &ut, &utemp, _state); - } - if( ncc>0 ) - { - applyrotationsfromtheleft(fwddir, ll+cstart-1, m+cstart-1, cstart, cend, &work2, &work3, c, &ctemp, _state); - } - - /* - * Test convergence - */ - if( ae_fp_less_eq(ae_fabs(e->ptr.p_double[m-1], _state),thresh) ) - { - e->ptr.p_double[m-1] = (double)(0); - } - } - else - { - - /* - * Chase bulge from bottom to top - * Save cosines and sines for later singular vector updates - */ - f = (ae_fabs(d->ptr.p_double[m], _state)-shift)*(bdsvd_extsignbdsqr((double)(1), d->ptr.p_double[m], _state)+shift/d->ptr.p_double[m]); - g = e->ptr.p_double[m-1]; - for(i=m; i>=ll+1; i--) - { - generaterotation(f, g, &cosr, &sinr, &r, _state); - if( iptr.p_double[i] = r; - } - f = cosr*d->ptr.p_double[i]+sinr*e->ptr.p_double[i-1]; - e->ptr.p_double[i-1] = cosr*e->ptr.p_double[i-1]-sinr*d->ptr.p_double[i]; - g = sinr*d->ptr.p_double[i-1]; - d->ptr.p_double[i-1] = cosr*d->ptr.p_double[i-1]; - generaterotation(f, g, &cosl, &sinl, &r, _state); - d->ptr.p_double[i] = r; - f = cosl*e->ptr.p_double[i-1]+sinl*d->ptr.p_double[i-1]; - d->ptr.p_double[i-1] = cosl*d->ptr.p_double[i-1]-sinl*e->ptr.p_double[i-1]; - if( i>ll+1 ) - { - g = sinl*e->ptr.p_double[i-2]; - e->ptr.p_double[i-2] = cosl*e->ptr.p_double[i-2]; - } - work0.ptr.p_double[i-ll] = cosr; - work1.ptr.p_double[i-ll] = -sinr; - work2.ptr.p_double[i-ll] = cosl; - work3.ptr.p_double[i-ll] = -sinl; - } - e->ptr.p_double[ll] = f; - - /* - * Test convergence - */ - if( ae_fp_less_eq(ae_fabs(e->ptr.p_double[ll], _state),thresh) ) - { - e->ptr.p_double[ll] = (double)(0); - } - - /* - * Update singular vectors if desired - */ - if( ncvt>0 ) - { - applyrotationsfromtheleft(!fwddir, ll+vstart-1, m+vstart-1, vstart, vend, &work2, &work3, vt, &vttemp, _state); - } - if( nru>0 ) - { - applyrotationsfromtheleft(!fwddir, ll+ustart-1, m+ustart-1, ustart, uend, &work0, &work1, &ut, &utemp, _state); - } - if( ncc>0 ) - { - applyrotationsfromtheleft(!fwddir, ll+cstart-1, m+cstart-1, cstart, cend, &work0, &work1, c, &ctemp, _state); - } - } - } - - /* - * QR iteration finished, go back and check convergence - */ - continue; - } - - /* - * All singular values converged, so make them positive - */ - for(i=1; i<=n; i++) - { - if( ae_fp_less(d->ptr.p_double[i],(double)(0)) ) - { - d->ptr.p_double[i] = -d->ptr.p_double[i]; - - /* - * Change sign of singular vectors, if desired - */ - if( ncvt>0 ) - { - ae_v_muld(&vt->ptr.pp_double[i+vstart-1][vstart], 1, ae_v_len(vstart,vend), -1); - } - } - } - - /* - * Sort the singular values into decreasing order (insertion sort on - * singular values, but only one transposition per singular vector) - */ - for(i=1; i<=n-1; i++) - { - - /* - * Scan for smallest D(I) - */ - isub = 1; - smin = d->ptr.p_double[1]; - for(j=2; j<=n+1-i; j++) - { - if( ae_fp_less_eq(d->ptr.p_double[j],smin) ) - { - isub = j; - smin = d->ptr.p_double[j]; - } - } - if( isub!=n+1-i ) - { - - /* - * Swap singular values and vectors - */ - d->ptr.p_double[isub] = d->ptr.p_double[n+1-i]; - d->ptr.p_double[n+1-i] = smin; - if( ncvt>0 ) - { - j = n+1-i; - ae_v_move(&vttemp.ptr.p_double[vstart], 1, &vt->ptr.pp_double[isub+vstart-1][vstart], 1, ae_v_len(vstart,vend)); - ae_v_move(&vt->ptr.pp_double[isub+vstart-1][vstart], 1, &vt->ptr.pp_double[j+vstart-1][vstart], 1, ae_v_len(vstart,vend)); - ae_v_move(&vt->ptr.pp_double[j+vstart-1][vstart], 1, &vttemp.ptr.p_double[vstart], 1, ae_v_len(vstart,vend)); - } - if( nru>0 ) - { - j = n+1-i; - ae_v_move(&utemp.ptr.p_double[ustart], 1, &ut.ptr.pp_double[isub+ustart-1][ustart], 1, ae_v_len(ustart,uend)); - ae_v_move(&ut.ptr.pp_double[isub+ustart-1][ustart], 1, &ut.ptr.pp_double[j+ustart-1][ustart], 1, ae_v_len(ustart,uend)); - ae_v_move(&ut.ptr.pp_double[j+ustart-1][ustart], 1, &utemp.ptr.p_double[ustart], 1, ae_v_len(ustart,uend)); - } - if( ncc>0 ) - { - j = n+1-i; - ae_v_move(&ctemp.ptr.p_double[cstart], 1, &c->ptr.pp_double[isub+cstart-1][cstart], 1, ae_v_len(cstart,cend)); - ae_v_move(&c->ptr.pp_double[isub+cstart-1][cstart], 1, &c->ptr.pp_double[j+cstart-1][cstart], 1, ae_v_len(cstart,cend)); - ae_v_move(&c->ptr.pp_double[j+cstart-1][cstart], 1, &ctemp.ptr.p_double[cstart], 1, ae_v_len(cstart,cend)); - } - } - } - - /* - * Copy U back from temporary storage - */ - if( nru>0 ) - { - rmatrixtranspose(n, nru, &ut, ustart, ustart, uu, ustart, ustart, _state); - } - ae_frame_leave(_state); - return result; -} - - -static double bdsvd_extsignbdsqr(double a, double b, ae_state *_state) -{ - double result; - - - if( ae_fp_greater_eq(b,(double)(0)) ) - { - result = ae_fabs(a, _state); - } - else - { - result = -ae_fabs(a, _state); - } - return result; -} - - -static void bdsvd_svd2x2(double f, - double g, - double h, - double* ssmin, - double* ssmax, - ae_state *_state) -{ - double aas; - double at; - double au; - double c; - double fa; - double fhmn; - double fhmx; - double ga; - double ha; - - *ssmin = 0; - *ssmax = 0; - - fa = ae_fabs(f, _state); - ga = ae_fabs(g, _state); - ha = ae_fabs(h, _state); - fhmn = ae_minreal(fa, ha, _state); - fhmx = ae_maxreal(fa, ha, _state); - if( ae_fp_eq(fhmn,(double)(0)) ) - { - *ssmin = (double)(0); - if( ae_fp_eq(fhmx,(double)(0)) ) - { - *ssmax = ga; - } - else - { - *ssmax = ae_maxreal(fhmx, ga, _state)*ae_sqrt(1+ae_sqr(ae_minreal(fhmx, ga, _state)/ae_maxreal(fhmx, ga, _state), _state), _state); - } - } - else - { - if( ae_fp_less(ga,fhmx) ) - { - aas = 1+fhmn/fhmx; - at = (fhmx-fhmn)/fhmx; - au = ae_sqr(ga/fhmx, _state); - c = 2/(ae_sqrt(aas*aas+au, _state)+ae_sqrt(at*at+au, _state)); - *ssmin = fhmn*c; - *ssmax = fhmx/c; - } - else - { - au = fhmx/ga; - if( ae_fp_eq(au,(double)(0)) ) - { - - /* - * Avoid possible harmful underflow if exponent range - * asymmetric (true SSMIN may not underflow even if - * AU underflows) - */ - *ssmin = fhmn*fhmx/ga; - *ssmax = ga; - } - else - { - aas = 1+fhmn/fhmx; - at = (fhmx-fhmn)/fhmx; - c = 1/(ae_sqrt(1+ae_sqr(aas*au, _state), _state)+ae_sqrt(1+ae_sqr(at*au, _state), _state)); - *ssmin = fhmn*c*au; - *ssmin = *ssmin+(*ssmin); - *ssmax = ga/(c+c); - } - } - } -} - - -static void bdsvd_svdv2x2(double f, - double g, - double h, - double* ssmin, - double* ssmax, - double* snr, - double* csr, - double* snl, - double* csl, - ae_state *_state) -{ - ae_bool gasmal; - ae_bool swp; - ae_int_t pmax; - double a; - double clt; - double crt; - double d; - double fa; - double ft; - double ga; - double gt; - double ha; - double ht; - double l; - double m; - double mm; - double r; - double s; - double slt; - double srt; - double t; - double temp; - double tsign; - double tt; - double v; - - *ssmin = 0; - *ssmax = 0; - *snr = 0; - *csr = 0; - *snl = 0; - *csl = 0; - - ft = f; - fa = ae_fabs(ft, _state); - ht = h; - ha = ae_fabs(h, _state); - - /* - * these initializers are not really necessary, - * but without them compiler complains about uninitialized locals - */ - clt = (double)(0); - crt = (double)(0); - slt = (double)(0); - srt = (double)(0); - tsign = (double)(0); - - /* - * PMAX points to the maximum absolute element of matrix - * PMAX = 1 if F largest in absolute values - * PMAX = 2 if G largest in absolute values - * PMAX = 3 if H largest in absolute values - */ - pmax = 1; - swp = ae_fp_greater(ha,fa); - if( swp ) - { - - /* - * Now FA .ge. HA - */ - pmax = 3; - temp = ft; - ft = ht; - ht = temp; - temp = fa; - fa = ha; - ha = temp; - } - gt = g; - ga = ae_fabs(gt, _state); - if( ae_fp_eq(ga,(double)(0)) ) - { - - /* - * Diagonal matrix - */ - *ssmin = ha; - *ssmax = fa; - clt = (double)(1); - crt = (double)(1); - slt = (double)(0); - srt = (double)(0); - } - else - { - gasmal = ae_true; - if( ae_fp_greater(ga,fa) ) - { - pmax = 2; - if( ae_fp_less(fa/ga,ae_machineepsilon) ) - { - - /* - * Case of very large GA - */ - gasmal = ae_false; - *ssmax = ga; - if( ae_fp_greater(ha,(double)(1)) ) - { - v = ga/ha; - *ssmin = fa/v; - } - else - { - v = fa/ga; - *ssmin = v*ha; - } - clt = (double)(1); - slt = ht/gt; - srt = (double)(1); - crt = ft/gt; - } - } - if( gasmal ) - { - - /* - * Normal case - */ - d = fa-ha; - if( ae_fp_eq(d,fa) ) - { - l = (double)(1); - } - else - { - l = d/fa; - } - m = gt/ft; - t = 2-l; - mm = m*m; - tt = t*t; - s = ae_sqrt(tt+mm, _state); - if( ae_fp_eq(l,(double)(0)) ) - { - r = ae_fabs(m, _state); - } - else - { - r = ae_sqrt(l*l+mm, _state); - } - a = 0.5*(s+r); - *ssmin = ha/a; - *ssmax = fa*a; - if( ae_fp_eq(mm,(double)(0)) ) - { - - /* - * Note that M is very tiny - */ - if( ae_fp_eq(l,(double)(0)) ) - { - t = bdsvd_extsignbdsqr((double)(2), ft, _state)*bdsvd_extsignbdsqr((double)(1), gt, _state); - } - else - { - t = gt/bdsvd_extsignbdsqr(d, ft, _state)+m/t; - } - } - else - { - t = (m/(s+t)+m/(r+l))*(1+a); - } - l = ae_sqrt(t*t+4, _state); - crt = 2/l; - srt = t/l; - clt = (crt+srt*m)/a; - v = ht/ft; - slt = v*srt/a; - } - } - if( swp ) - { - *csl = srt; - *snl = crt; - *csr = slt; - *snr = clt; - } - else - { - *csl = clt; - *snl = slt; - *csr = crt; - *snr = srt; - } - - /* - * Correct signs of SSMAX and SSMIN - */ - if( pmax==1 ) - { - tsign = bdsvd_extsignbdsqr((double)(1), *csr, _state)*bdsvd_extsignbdsqr((double)(1), *csl, _state)*bdsvd_extsignbdsqr((double)(1), f, _state); - } - if( pmax==2 ) - { - tsign = bdsvd_extsignbdsqr((double)(1), *snr, _state)*bdsvd_extsignbdsqr((double)(1), *csl, _state)*bdsvd_extsignbdsqr((double)(1), g, _state); - } - if( pmax==3 ) - { - tsign = bdsvd_extsignbdsqr((double)(1), *snr, _state)*bdsvd_extsignbdsqr((double)(1), *snl, _state)*bdsvd_extsignbdsqr((double)(1), h, _state); - } - *ssmax = bdsvd_extsignbdsqr(*ssmax, tsign, _state); - *ssmin = bdsvd_extsignbdsqr(*ssmin, tsign*bdsvd_extsignbdsqr((double)(1), f, _state)*bdsvd_extsignbdsqr((double)(1), h, _state), _state); -} - - -#endif -#if defined(AE_COMPILE_SVD) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Singular value decomposition of a rectangular matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -The algorithm calculates the singular value decomposition of a matrix of -size MxN: A = U * S * V^T - -The algorithm finds the singular values and, optionally, matrices U and V^T. -The algorithm can find both first min(M,N) columns of matrix U and rows of -matrix V^T (singular vectors), and matrices U and V^T wholly (of sizes MxM -and NxN respectively). - -Take into account that the subroutine does not return matrix V but V^T. - -Input parameters: - A - matrix to be decomposed. - Array whose indexes range within [0..M-1, 0..N-1]. - M - number of rows in matrix A. - N - number of columns in matrix A. - UNeeded - 0, 1 or 2. See the description of the parameter U. - VTNeeded - 0, 1 or 2. See the description of the parameter VT. - AdditionalMemory - - If the parameter: - * equals 0, the algorithm doesn't use additional - memory (lower requirements, lower performance). - * equals 1, the algorithm uses additional - memory of size min(M,N)*min(M,N) of real numbers. - It often speeds up the algorithm. - * equals 2, the algorithm uses additional - memory of size M*min(M,N) of real numbers. - It allows to get a maximum performance. - The recommended value of the parameter is 2. - -Output parameters: - W - contains singular values in descending order. - U - if UNeeded=0, U isn't changed, the left singular vectors - are not calculated. - if Uneeded=1, U contains left singular vectors (first - min(M,N) columns of matrix U). Array whose indexes range - within [0..M-1, 0..Min(M,N)-1]. - if UNeeded=2, U contains matrix U wholly. Array whose - indexes range within [0..M-1, 0..M-1]. - VT - if VTNeeded=0, VT isn't changed, the right singular vectors - are not calculated. - if VTNeeded=1, VT contains right singular vectors (first - min(M,N) rows of matrix V^T). Array whose indexes range - within [0..min(M,N)-1, 0..N-1]. - if VTNeeded=2, VT contains matrix V^T wholly. Array whose - indexes range within [0..N-1, 0..N-1]. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -ae_bool rmatrixsvd(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - ae_int_t uneeded, - ae_int_t vtneeded, - ae_int_t additionalmemory, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* u, - /* Real */ ae_matrix* vt, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_vector tauq; - ae_vector taup; - ae_vector tau; - ae_vector e; - ae_vector work; - ae_matrix t2; - ae_bool isupper; - ae_int_t minmn; - ae_int_t ncu; - ae_int_t nrvt; - ae_int_t nru; - ae_int_t ncvt; - ae_int_t i; - ae_int_t j; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&tauq, 0, sizeof(tauq)); - memset(&taup, 0, sizeof(taup)); - memset(&tau, 0, sizeof(tau)); - memset(&e, 0, sizeof(e)); - memset(&work, 0, sizeof(work)); - memset(&t2, 0, sizeof(t2)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_vector_clear(w); - ae_matrix_clear(u); - ae_matrix_clear(vt); - ae_vector_init(&tauq, 0, DT_REAL, _state, ae_true); - ae_vector_init(&taup, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tau, 0, DT_REAL, _state, ae_true); - ae_vector_init(&e, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&t2, 0, 0, DT_REAL, _state, ae_true); - - result = ae_true; - if( m==0||n==0 ) - { - ae_frame_leave(_state); - return result; - } - ae_assert(uneeded>=0&&uneeded<=2, "SVDDecomposition: wrong parameters!", _state); - ae_assert(vtneeded>=0&&vtneeded<=2, "SVDDecomposition: wrong parameters!", _state); - ae_assert(additionalmemory>=0&&additionalmemory<=2, "SVDDecomposition: wrong parameters!", _state); - - /* - * initialize - */ - minmn = ae_minint(m, n, _state); - ae_vector_set_length(w, minmn+1, _state); - ncu = 0; - nru = 0; - if( uneeded==1 ) - { - nru = m; - ncu = minmn; - ae_matrix_set_length(u, nru-1+1, ncu-1+1, _state); - } - if( uneeded==2 ) - { - nru = m; - ncu = m; - ae_matrix_set_length(u, nru-1+1, ncu-1+1, _state); - } - nrvt = 0; - ncvt = 0; - if( vtneeded==1 ) - { - nrvt = minmn; - ncvt = n; - ae_matrix_set_length(vt, nrvt-1+1, ncvt-1+1, _state); - } - if( vtneeded==2 ) - { - nrvt = n; - ncvt = n; - ae_matrix_set_length(vt, nrvt-1+1, ncvt-1+1, _state); - } - - /* - * M much larger than N - * Use bidiagonal reduction with QR-decomposition - */ - if( ae_fp_greater((double)(m),1.6*n) ) - { - if( uneeded==0 ) - { - - /* - * No left singular vectors to be computed - */ - rmatrixqr(a, m, n, &tau, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i-1; j++) - { - a->ptr.pp_double[i][j] = (double)(0); - } - } - rmatrixbd(a, n, n, &tauq, &taup, _state); - rmatrixbdunpackpt(a, n, n, &taup, nrvt, vt, _state); - rmatrixbdunpackdiagonals(a, n, n, &isupper, w, &e, _state); - result = rmatrixbdsvd(w, &e, n, isupper, ae_false, u, 0, a, 0, vt, ncvt, _state); - ae_frame_leave(_state); - return result; - } - else - { - - /* - * Left singular vectors (may be full matrix U) to be computed - */ - rmatrixqr(a, m, n, &tau, _state); - rmatrixqrunpackq(a, m, n, &tau, ncu, u, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i-1; j++) - { - a->ptr.pp_double[i][j] = (double)(0); - } - } - rmatrixbd(a, n, n, &tauq, &taup, _state); - rmatrixbdunpackpt(a, n, n, &taup, nrvt, vt, _state); - rmatrixbdunpackdiagonals(a, n, n, &isupper, w, &e, _state); - if( additionalmemory<1 ) - { - - /* - * No additional memory can be used - */ - rmatrixbdmultiplybyq(a, n, n, &tauq, u, m, n, ae_true, ae_false, _state); - result = rmatrixbdsvd(w, &e, n, isupper, ae_false, u, m, a, 0, vt, ncvt, _state); - } - else - { - - /* - * Large U. Transforming intermediate matrix T2 - */ - ae_vector_set_length(&work, ae_maxint(m, n, _state)+1, _state); - rmatrixbdunpackq(a, n, n, &tauq, n, &t2, _state); - copymatrix(u, 0, m-1, 0, n-1, a, 0, m-1, 0, n-1, _state); - inplacetranspose(&t2, 0, n-1, 0, n-1, &work, _state); - result = rmatrixbdsvd(w, &e, n, isupper, ae_false, u, 0, &t2, n, vt, ncvt, _state); - rmatrixgemm(m, n, n, 1.0, a, 0, 0, 0, &t2, 0, 0, 1, 0.0, u, 0, 0, _state); - } - ae_frame_leave(_state); - return result; - } - } - - /* - * N much larger than M - * Use bidiagonal reduction with LQ-decomposition - */ - if( ae_fp_greater((double)(n),1.6*m) ) - { - if( vtneeded==0 ) - { - - /* - * No right singular vectors to be computed - */ - rmatrixlq(a, m, n, &tau, _state); - for(i=0; i<=m-1; i++) - { - for(j=i+1; j<=m-1; j++) - { - a->ptr.pp_double[i][j] = (double)(0); - } - } - rmatrixbd(a, m, m, &tauq, &taup, _state); - rmatrixbdunpackq(a, m, m, &tauq, ncu, u, _state); - rmatrixbdunpackdiagonals(a, m, m, &isupper, w, &e, _state); - ae_vector_set_length(&work, m+1, _state); - inplacetranspose(u, 0, nru-1, 0, ncu-1, &work, _state); - result = rmatrixbdsvd(w, &e, m, isupper, ae_false, a, 0, u, nru, vt, 0, _state); - inplacetranspose(u, 0, nru-1, 0, ncu-1, &work, _state); - ae_frame_leave(_state); - return result; - } - else - { - - /* - * Right singular vectors (may be full matrix VT) to be computed - */ - rmatrixlq(a, m, n, &tau, _state); - rmatrixlqunpackq(a, m, n, &tau, nrvt, vt, _state); - for(i=0; i<=m-1; i++) - { - for(j=i+1; j<=m-1; j++) - { - a->ptr.pp_double[i][j] = (double)(0); - } - } - rmatrixbd(a, m, m, &tauq, &taup, _state); - rmatrixbdunpackq(a, m, m, &tauq, ncu, u, _state); - rmatrixbdunpackdiagonals(a, m, m, &isupper, w, &e, _state); - ae_vector_set_length(&work, ae_maxint(m, n, _state)+1, _state); - inplacetranspose(u, 0, nru-1, 0, ncu-1, &work, _state); - if( additionalmemory<1 ) - { - - /* - * No additional memory available - */ - rmatrixbdmultiplybyp(a, m, m, &taup, vt, m, n, ae_false, ae_true, _state); - result = rmatrixbdsvd(w, &e, m, isupper, ae_false, a, 0, u, nru, vt, n, _state); - } - else - { - - /* - * Large VT. Transforming intermediate matrix T2 - */ - rmatrixbdunpackpt(a, m, m, &taup, m, &t2, _state); - result = rmatrixbdsvd(w, &e, m, isupper, ae_false, a, 0, u, nru, &t2, m, _state); - copymatrix(vt, 0, m-1, 0, n-1, a, 0, m-1, 0, n-1, _state); - rmatrixgemm(m, n, m, 1.0, &t2, 0, 0, 0, a, 0, 0, 0, 0.0, vt, 0, 0, _state); - } - inplacetranspose(u, 0, nru-1, 0, ncu-1, &work, _state); - ae_frame_leave(_state); - return result; - } - } - - /* - * M<=N - * We can use inplace transposition of U to get rid of columnwise operations - */ - if( m<=n ) - { - rmatrixbd(a, m, n, &tauq, &taup, _state); - rmatrixbdunpackq(a, m, n, &tauq, ncu, u, _state); - rmatrixbdunpackpt(a, m, n, &taup, nrvt, vt, _state); - rmatrixbdunpackdiagonals(a, m, n, &isupper, w, &e, _state); - ae_vector_set_length(&work, m+1, _state); - inplacetranspose(u, 0, nru-1, 0, ncu-1, &work, _state); - result = rmatrixbdsvd(w, &e, minmn, isupper, ae_false, a, 0, u, nru, vt, ncvt, _state); - inplacetranspose(u, 0, nru-1, 0, ncu-1, &work, _state); - ae_frame_leave(_state); - return result; - } - - /* - * Simple bidiagonal reduction - */ - rmatrixbd(a, m, n, &tauq, &taup, _state); - rmatrixbdunpackq(a, m, n, &tauq, ncu, u, _state); - rmatrixbdunpackpt(a, m, n, &taup, nrvt, vt, _state); - rmatrixbdunpackdiagonals(a, m, n, &isupper, w, &e, _state); - if( additionalmemory<2||uneeded==0 ) - { - - /* - * We cant use additional memory or there is no need in such operations - */ - result = rmatrixbdsvd(w, &e, minmn, isupper, ae_false, u, nru, a, 0, vt, ncvt, _state); - } - else - { - - /* - * We can use additional memory - */ - ae_matrix_set_length(&t2, minmn-1+1, m-1+1, _state); - copyandtranspose(u, 0, m-1, 0, minmn-1, &t2, 0, minmn-1, 0, m-1, _state); - result = rmatrixbdsvd(w, &e, minmn, isupper, ae_false, u, 0, &t2, m, vt, ncvt, _state); - copyandtranspose(&t2, 0, minmn-1, 0, m-1, u, 0, m-1, 0, minmn-1, _state); - } - ae_frame_leave(_state); - return result; -} - - -#endif -#if defined(AE_COMPILE_NORMESTIMATOR) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This procedure initializes matrix norm estimator. - -USAGE: -1. User initializes algorithm state with NormEstimatorCreate() call -2. User calls NormEstimatorEstimateSparse() (or NormEstimatorIteration()) -3. User calls NormEstimatorResults() to get solution. - -INPUT PARAMETERS: - M - number of rows in the matrix being estimated, M>0 - N - number of columns in the matrix being estimated, N>0 - NStart - number of random starting vectors - recommended value - at least 5. - NIts - number of iterations to do with best starting vector - recommended value - at least 5. - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -NOTE: this algorithm is effectively deterministic, i.e. it always returns -same result when repeatedly called for the same matrix. In fact, algorithm -uses randomized starting vectors, but internal random numbers generator -always generates same sequence of the random values (it is a feature, not -bug). - -Algorithm can be made non-deterministic with NormEstimatorSetSeed(0) call. - - -- ALGLIB -- - Copyright 06.12.2011 by Bochkanov Sergey -*************************************************************************/ -void normestimatorcreate(ae_int_t m, - ae_int_t n, - ae_int_t nstart, - ae_int_t nits, - normestimatorstate* state, - ae_state *_state) -{ - - _normestimatorstate_clear(state); - - ae_assert(m>0, "NormEstimatorCreate: M<=0", _state); - ae_assert(n>0, "NormEstimatorCreate: N<=0", _state); - ae_assert(nstart>0, "NormEstimatorCreate: NStart<=0", _state); - ae_assert(nits>0, "NormEstimatorCreate: NIts<=0", _state); - state->m = m; - state->n = n; - state->nstart = nstart; - state->nits = nits; - state->seedval = 11; - hqrndrandomize(&state->r, _state); - ae_vector_set_length(&state->x0, state->n, _state); - ae_vector_set_length(&state->t, state->m, _state); - ae_vector_set_length(&state->x1, state->n, _state); - ae_vector_set_length(&state->xbest, state->n, _state); - ae_vector_set_length(&state->x, ae_maxint(state->n, state->m, _state), _state); - ae_vector_set_length(&state->mv, state->m, _state); - ae_vector_set_length(&state->mtv, state->n, _state); - ae_vector_set_length(&state->rstate.ia, 3+1, _state); - ae_vector_set_length(&state->rstate.ra, 2+1, _state); - state->rstate.stage = -1; -} - - -/************************************************************************* -This function changes seed value used by algorithm. In some cases we need -deterministic processing, i.e. subsequent calls must return equal results, -in other cases we need non-deterministic algorithm which returns different -results for the same matrix on every pass. - -Setting zero seed will lead to non-deterministic algorithm, while non-zero -value will make our algorithm deterministic. - -INPUT PARAMETERS: - State - norm estimator state, must be initialized with a call - to NormEstimatorCreate() - SeedVal - seed value, >=0. Zero value = non-deterministic algo. - - -- ALGLIB -- - Copyright 06.12.2011 by Bochkanov Sergey -*************************************************************************/ -void normestimatorsetseed(normestimatorstate* state, - ae_int_t seedval, - ae_state *_state) -{ - - - ae_assert(seedval>=0, "NormEstimatorSetSeed: SeedVal<0", _state); - state->seedval = seedval; -} - - -/************************************************************************* - - -- ALGLIB -- - Copyright 06.12.2011 by Bochkanov Sergey -*************************************************************************/ -ae_bool normestimatoriteration(normestimatorstate* state, - ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - ae_int_t i; - ae_int_t itcnt; - double v; - double growth; - double bestgrowth; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - n = state->rstate.ia.ptr.p_int[0]; - m = state->rstate.ia.ptr.p_int[1]; - i = state->rstate.ia.ptr.p_int[2]; - itcnt = state->rstate.ia.ptr.p_int[3]; - v = state->rstate.ra.ptr.p_double[0]; - growth = state->rstate.ra.ptr.p_double[1]; - bestgrowth = state->rstate.ra.ptr.p_double[2]; - } - else - { - n = 359; - m = -58; - i = -919; - itcnt = -909; - v = 81; - growth = 255; - bestgrowth = 74; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - if( state->rstate.stage==1 ) - { - goto lbl_1; - } - if( state->rstate.stage==2 ) - { - goto lbl_2; - } - if( state->rstate.stage==3 ) - { - goto lbl_3; - } - - /* - * Routine body - */ - n = state->n; - m = state->m; - if( state->seedval>0 ) - { - hqrndseed(state->seedval, state->seedval+2, &state->r, _state); - } - bestgrowth = (double)(0); - state->xbest.ptr.p_double[0] = (double)(1); - for(i=1; i<=n-1; i++) - { - state->xbest.ptr.p_double[i] = (double)(0); - } - itcnt = 0; -lbl_4: - if( itcnt>state->nstart-1 ) - { - goto lbl_6; - } - do - { - v = (double)(0); - for(i=0; i<=n-1; i++) - { - state->x0.ptr.p_double[i] = hqrndnormal(&state->r, _state); - v = v+ae_sqr(state->x0.ptr.p_double[i], _state); - } - } - while(ae_fp_eq(v,(double)(0))); - v = 1/ae_sqrt(v, _state); - ae_v_muld(&state->x0.ptr.p_double[0], 1, ae_v_len(0,n-1), v); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->x0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->needmv = ae_true; - state->needmtv = ae_false; - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - ae_v_move(&state->x.ptr.p_double[0], 1, &state->mv.ptr.p_double[0], 1, ae_v_len(0,m-1)); - state->needmv = ae_false; - state->needmtv = ae_true; - state->rstate.stage = 1; - goto lbl_rcomm; -lbl_1: - ae_v_move(&state->x1.ptr.p_double[0], 1, &state->mtv.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(state->x1.ptr.p_double[i], _state); - } - growth = ae_sqrt(ae_sqrt(v, _state), _state); - if( ae_fp_greater(growth,bestgrowth) ) - { - v = 1/ae_sqrt(v, _state); - ae_v_moved(&state->xbest.ptr.p_double[0], 1, &state->x1.ptr.p_double[0], 1, ae_v_len(0,n-1), v); - bestgrowth = growth; - } - itcnt = itcnt+1; - goto lbl_4; -lbl_6: - ae_v_move(&state->x0.ptr.p_double[0], 1, &state->xbest.ptr.p_double[0], 1, ae_v_len(0,n-1)); - itcnt = 0; -lbl_7: - if( itcnt>state->nits-1 ) - { - goto lbl_9; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->x0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->needmv = ae_true; - state->needmtv = ae_false; - state->rstate.stage = 2; - goto lbl_rcomm; -lbl_2: - ae_v_move(&state->x.ptr.p_double[0], 1, &state->mv.ptr.p_double[0], 1, ae_v_len(0,m-1)); - state->needmv = ae_false; - state->needmtv = ae_true; - state->rstate.stage = 3; - goto lbl_rcomm; -lbl_3: - ae_v_move(&state->x1.ptr.p_double[0], 1, &state->mtv.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(state->x1.ptr.p_double[i], _state); - } - state->repnorm = ae_sqrt(ae_sqrt(v, _state), _state); - if( ae_fp_neq(v,(double)(0)) ) - { - v = 1/ae_sqrt(v, _state); - ae_v_moved(&state->x0.ptr.p_double[0], 1, &state->x1.ptr.p_double[0], 1, ae_v_len(0,n-1), v); - } - itcnt = itcnt+1; - goto lbl_7; -lbl_9: - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = n; - state->rstate.ia.ptr.p_int[1] = m; - state->rstate.ia.ptr.p_int[2] = i; - state->rstate.ia.ptr.p_int[3] = itcnt; - state->rstate.ra.ptr.p_double[0] = v; - state->rstate.ra.ptr.p_double[1] = growth; - state->rstate.ra.ptr.p_double[2] = bestgrowth; - return result; -} - - -/************************************************************************* -This function estimates norm of the sparse M*N matrix A. - -INPUT PARAMETERS: - State - norm estimator state, must be initialized with a call - to NormEstimatorCreate() - A - sparse M*N matrix, must be converted to CRS format - prior to calling this function. - -After this function is over you can call NormEstimatorResults() to get -estimate of the norm(A). - - -- ALGLIB -- - Copyright 06.12.2011 by Bochkanov Sergey -*************************************************************************/ -void normestimatorestimatesparse(normestimatorstate* state, - sparsematrix* a, - ae_state *_state) -{ - - - normestimatorrestart(state, _state); - while(normestimatoriteration(state, _state)) - { - if( state->needmv ) - { - sparsemv(a, &state->x, &state->mv, _state); - continue; - } - if( state->needmtv ) - { - sparsemtv(a, &state->x, &state->mtv, _state); - continue; - } - } -} - - -/************************************************************************* -Matrix norm estimation results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - Nrm - estimate of the matrix norm, Nrm>=0 - - -- ALGLIB -- - Copyright 06.12.2011 by Bochkanov Sergey -*************************************************************************/ -void normestimatorresults(normestimatorstate* state, - double* nrm, - ae_state *_state) -{ - - *nrm = 0; - - *nrm = state->repnorm; -} - - -/************************************************************************* -This function restarts estimator and prepares it for the next estimation -round. - -INPUT PARAMETERS: - State - algorithm state - -- ALGLIB -- - Copyright 06.12.2011 by Bochkanov Sergey -*************************************************************************/ -void normestimatorrestart(normestimatorstate* state, ae_state *_state) -{ - - - ae_vector_set_length(&state->rstate.ia, 3+1, _state); - ae_vector_set_length(&state->rstate.ra, 2+1, _state); - state->rstate.stage = -1; -} - - -void _normestimatorstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - normestimatorstate *p = (normestimatorstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->x0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->x1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->t, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xbest, 0, DT_REAL, _state, make_automatic); - _hqrndstate_init(&p->r, _state, make_automatic); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->mv, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->mtv, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); -} - - -void _normestimatorstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - normestimatorstate *dst = (normestimatorstate*)_dst; - normestimatorstate *src = (normestimatorstate*)_src; - dst->n = src->n; - dst->m = src->m; - dst->nstart = src->nstart; - dst->nits = src->nits; - dst->seedval = src->seedval; - ae_vector_init_copy(&dst->x0, &src->x0, _state, make_automatic); - ae_vector_init_copy(&dst->x1, &src->x1, _state, make_automatic); - ae_vector_init_copy(&dst->t, &src->t, _state, make_automatic); - ae_vector_init_copy(&dst->xbest, &src->xbest, _state, make_automatic); - _hqrndstate_init_copy(&dst->r, &src->r, _state, make_automatic); - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->mv, &src->mv, _state, make_automatic); - ae_vector_init_copy(&dst->mtv, &src->mtv, _state, make_automatic); - dst->needmv = src->needmv; - dst->needmtv = src->needmtv; - dst->repnorm = src->repnorm; - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); -} - - -void _normestimatorstate_clear(void* _p) -{ - normestimatorstate *p = (normestimatorstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->x0); - ae_vector_clear(&p->x1); - ae_vector_clear(&p->t); - ae_vector_clear(&p->xbest); - _hqrndstate_clear(&p->r); - ae_vector_clear(&p->x); - ae_vector_clear(&p->mv); - ae_vector_clear(&p->mtv); - _rcommstate_clear(&p->rstate); -} - - -void _normestimatorstate_destroy(void* _p) -{ - normestimatorstate *p = (normestimatorstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->x0); - ae_vector_destroy(&p->x1); - ae_vector_destroy(&p->t); - ae_vector_destroy(&p->xbest); - _hqrndstate_destroy(&p->r); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->mv); - ae_vector_destroy(&p->mtv); - _rcommstate_destroy(&p->rstate); -} - - -#endif -#if defined(AE_COMPILE_HSSCHUR) || !defined(AE_PARTIAL_BUILD) - - -void rmatrixinternalschurdecomposition(/* Real */ ae_matrix* h, - ae_int_t n, - ae_int_t tneeded, - ae_int_t zneeded, - /* Real */ ae_vector* wr, - /* Real */ ae_vector* wi, - /* Real */ ae_matrix* z, - ae_int_t* info, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_matrix h1; - ae_matrix z1; - ae_vector wr1; - ae_vector wi1; - - ae_frame_make(_state, &_frame_block); - memset(&h1, 0, sizeof(h1)); - memset(&z1, 0, sizeof(z1)); - memset(&wr1, 0, sizeof(wr1)); - memset(&wi1, 0, sizeof(wi1)); - ae_vector_clear(wr); - ae_vector_clear(wi); - *info = 0; - ae_matrix_init(&h1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z1, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wr1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wi1, 0, DT_REAL, _state, ae_true); - - - /* - * Allocate space - */ - ae_vector_set_length(wr, n, _state); - ae_vector_set_length(wi, n, _state); - if( zneeded==2 ) - { - rmatrixsetlengthatleast(z, n, n, _state); - } - - /* - * MKL version - */ - if( rmatrixinternalschurdecompositionmkl(h, n, tneeded, zneeded, wr, wi, z, info, _state) ) - { - ae_frame_leave(_state); - return; - } - - /* - * ALGLIB version - */ - ae_matrix_set_length(&h1, n+1, n+1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - h1.ptr.pp_double[1+i][1+j] = h->ptr.pp_double[i][j]; - } - } - if( zneeded==1 ) - { - ae_matrix_set_length(&z1, n+1, n+1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - z1.ptr.pp_double[1+i][1+j] = z->ptr.pp_double[i][j]; - } - } - } - internalschurdecomposition(&h1, n, tneeded, zneeded, &wr1, &wi1, &z1, info, _state); - for(i=0; i<=n-1; i++) - { - wr->ptr.p_double[i] = wr1.ptr.p_double[i+1]; - wi->ptr.p_double[i] = wi1.ptr.p_double[i+1]; - } - if( tneeded!=0 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - h->ptr.pp_double[i][j] = h1.ptr.pp_double[1+i][1+j]; - } - } - } - if( zneeded!=0 ) - { - rmatrixsetlengthatleast(z, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - z->ptr.pp_double[i][j] = z1.ptr.pp_double[1+i][1+j]; - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Subroutine performing the Schur decomposition of a matrix in upper -Hessenberg form using the QR algorithm with multiple shifts. - -The source matrix H is represented as S'*H*S = T, where H - matrix in -upper Hessenberg form, S - orthogonal matrix (Schur vectors), T - upper -quasi-triangular matrix (with blocks of sizes 1x1 and 2x2 on the main -diagonal). - -Input parameters: - H - matrix to be decomposed. - Array whose indexes range within [1..N, 1..N]. - N - size of H, N>=0. - - -Output parameters: - H - contains the matrix T. - Array whose indexes range within [1..N, 1..N]. - All elements below the blocks on the main diagonal are equal - to 0. - S - contains Schur vectors. - Array whose indexes range within [1..N, 1..N]. - -Note 1: - The block structure of matrix T could be easily recognized: since all - the elements below the blocks are zeros, the elements a[i+1,i] which - are equal to 0 show the block border. - -Note 2: - the algorithm performance depends on the value of the internal - parameter NS of InternalSchurDecomposition subroutine which defines - the number of shifts in the QR algorithm (analog of the block width - in block matrix algorithms in linear algebra). If you require maximum - performance on your machine, it is recommended to adjust this - parameter manually. - -Result: - True, if the algorithm has converged and the parameters H and S contain - the result. - False, if the algorithm has not converged. - -Algorithm implemented on the basis of subroutine DHSEQR (LAPACK 3.0 library). -*************************************************************************/ -ae_bool upperhessenbergschurdecomposition(/* Real */ ae_matrix* h, - ae_int_t n, - /* Real */ ae_matrix* s, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector wi; - ae_vector wr; - ae_int_t info; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&wi, 0, sizeof(wi)); - memset(&wr, 0, sizeof(wr)); - ae_matrix_clear(s); - ae_vector_init(&wi, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wr, 0, DT_REAL, _state, ae_true); - - internalschurdecomposition(h, n, 1, 2, &wr, &wi, s, &info, _state); - result = info==0; - ae_frame_leave(_state); - return result; -} - - -void internalschurdecomposition(/* Real */ ae_matrix* h, - ae_int_t n, - ae_int_t tneeded, - ae_int_t zneeded, - /* Real */ ae_vector* wr, - /* Real */ ae_vector* wi, - /* Real */ ae_matrix* z, - ae_int_t* info, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector work; - ae_int_t i; - ae_int_t i1; - ae_int_t i2; - ae_int_t ierr; - ae_int_t ii; - ae_int_t itemp; - ae_int_t itn; - ae_int_t its; - ae_int_t j; - ae_int_t k; - ae_int_t l; - ae_int_t maxb; - ae_int_t nr; - ae_int_t ns; - ae_int_t nv; - double absw; - double smlnum; - double tau; - double temp; - double tst1; - double ulp; - double unfl; - ae_matrix s; - ae_vector v; - ae_vector vv; - ae_vector workc1; - ae_vector works1; - ae_vector workv3; - ae_vector tmpwr; - ae_vector tmpwi; - ae_bool initz; - ae_bool wantt; - ae_bool wantz; - double cnst; - ae_bool failflag; - ae_int_t p1; - ae_int_t p2; - double vt; - - ae_frame_make(_state, &_frame_block); - memset(&work, 0, sizeof(work)); - memset(&s, 0, sizeof(s)); - memset(&v, 0, sizeof(v)); - memset(&vv, 0, sizeof(vv)); - memset(&workc1, 0, sizeof(workc1)); - memset(&works1, 0, sizeof(works1)); - memset(&workv3, 0, sizeof(workv3)); - memset(&tmpwr, 0, sizeof(tmpwr)); - memset(&tmpwi, 0, sizeof(tmpwi)); - ae_vector_clear(wr); - ae_vector_clear(wi); - *info = 0; - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&s, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&v, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vv, 0, DT_REAL, _state, ae_true); - ae_vector_init(&workc1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&works1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&workv3, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpwr, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpwi, 0, DT_REAL, _state, ae_true); - - - /* - * Set the order of the multi-shift QR algorithm to be used. - * If you want to tune algorithm, change this values - */ - ns = 12; - maxb = 50; - - /* - * Now 2 < NS <= MAXB < NH. - */ - maxb = ae_maxint(3, maxb, _state); - ns = ae_minint(maxb, ns, _state); - - /* - * Initialize - */ - cnst = 1.5; - ae_vector_set_length(&work, ae_maxint(n, 1, _state)+1, _state); - ae_matrix_set_length(&s, ns+1, ns+1, _state); - ae_vector_set_length(&v, ns+1+1, _state); - ae_vector_set_length(&vv, ns+1+1, _state); - ae_vector_set_length(wr, ae_maxint(n, 1, _state)+1, _state); - ae_vector_set_length(wi, ae_maxint(n, 1, _state)+1, _state); - ae_vector_set_length(&workc1, 1+1, _state); - ae_vector_set_length(&works1, 1+1, _state); - ae_vector_set_length(&workv3, 3+1, _state); - ae_vector_set_length(&tmpwr, ae_maxint(n, 1, _state)+1, _state); - ae_vector_set_length(&tmpwi, ae_maxint(n, 1, _state)+1, _state); - ae_assert(n>=0, "InternalSchurDecomposition: incorrect N!", _state); - ae_assert(tneeded==0||tneeded==1, "InternalSchurDecomposition: incorrect TNeeded!", _state); - ae_assert((zneeded==0||zneeded==1)||zneeded==2, "InternalSchurDecomposition: incorrect ZNeeded!", _state); - wantt = tneeded==1; - initz = zneeded==2; - wantz = zneeded!=0; - *info = 0; - - /* - * Initialize Z, if necessary - */ - if( initz ) - { - rmatrixsetlengthatleast(z, n+1, n+1, _state); - for(i=1; i<=n; i++) - { - for(j=1; j<=n; j++) - { - if( i==j ) - { - z->ptr.pp_double[i][j] = (double)(1); - } - else - { - z->ptr.pp_double[i][j] = (double)(0); - } - } - } - } - - /* - * Quick return if possible - */ - if( n==0 ) - { - ae_frame_leave(_state); - return; - } - if( n==1 ) - { - wr->ptr.p_double[1] = h->ptr.pp_double[1][1]; - wi->ptr.p_double[1] = (double)(0); - ae_frame_leave(_state); - return; - } - - /* - * Set rows and columns 1 to N to zero below the first - * subdiagonal. - */ - for(j=1; j<=n-2; j++) - { - for(i=j+2; i<=n; i++) - { - h->ptr.pp_double[i][j] = (double)(0); - } - } - - /* - * Test if N is sufficiently small - */ - if( (ns<=2||ns>n)||maxb>=n ) - { - - /* - * Use the standard double-shift algorithm - */ - hsschur_internalauxschur(wantt, wantz, n, 1, n, h, wr, wi, 1, n, z, &work, &workv3, &workc1, &works1, info, _state); - - /* - * fill entries under diagonal blocks of T with zeros - */ - if( wantt ) - { - j = 1; - while(j<=n) - { - if( ae_fp_eq(wi->ptr.p_double[j],(double)(0)) ) - { - for(i=j+1; i<=n; i++) - { - h->ptr.pp_double[i][j] = (double)(0); - } - j = j+1; - } - else - { - for(i=j+2; i<=n; i++) - { - h->ptr.pp_double[i][j] = (double)(0); - h->ptr.pp_double[i][j+1] = (double)(0); - } - j = j+2; - } - } - } - ae_frame_leave(_state); - return; - } - unfl = ae_minrealnumber; - ulp = 2*ae_machineepsilon; - smlnum = unfl*(n/ulp); - - /* - * I1 and I2 are the indices of the first row and last column of H - * to which transformations must be applied. If eigenvalues only are - * being computed, I1 and I2 are set inside the main loop. - */ - i1 = 1; - i2 = n; - - /* - * ITN is the total number of multiple-shift QR iterations allowed. - */ - itn = 30*n; - - /* - * The main loop begins here. I is the loop index and decreases from - * IHI to ILO in steps of at most MAXB. Each iteration of the loop - * works with the active submatrix in rows and columns L to I. - * Eigenvalues I+1 to IHI have already converged. Either L = ILO or - * H(L,L-1) is negligible so that the matrix splits. - */ - i = n; - for(;;) - { - l = 1; - if( i<1 ) - { - - /* - * fill entries under diagonal blocks of T with zeros - */ - if( wantt ) - { - j = 1; - while(j<=n) - { - if( ae_fp_eq(wi->ptr.p_double[j],(double)(0)) ) - { - for(i=j+1; i<=n; i++) - { - h->ptr.pp_double[i][j] = (double)(0); - } - j = j+1; - } - else - { - for(i=j+2; i<=n; i++) - { - h->ptr.pp_double[i][j] = (double)(0); - h->ptr.pp_double[i][j+1] = (double)(0); - } - j = j+2; - } - } - } - - /* - * Exit - */ - ae_frame_leave(_state); - return; - } - - /* - * Perform multiple-shift QR iterations on rows and columns ILO to I - * until a submatrix of order at most MAXB splits off at the bottom - * because a subdiagonal element has become negligible. - */ - failflag = ae_true; - for(its=0; its<=itn; its++) - { - - /* - * Look for a single small subdiagonal element. - */ - for(k=i; k>=l+1; k--) - { - tst1 = ae_fabs(h->ptr.pp_double[k-1][k-1], _state)+ae_fabs(h->ptr.pp_double[k][k], _state); - if( ae_fp_eq(tst1,(double)(0)) ) - { - tst1 = upperhessenberg1norm(h, l, i, l, i, &work, _state); - } - if( ae_fp_less_eq(ae_fabs(h->ptr.pp_double[k][k-1], _state),ae_maxreal(ulp*tst1, smlnum, _state)) ) - { - break; - } - } - l = k; - if( l>1 ) - { - - /* - * H(L,L-1) is negligible. - */ - h->ptr.pp_double[l][l-1] = (double)(0); - } - - /* - * Exit from loop if a submatrix of order <= MAXB has split off. - */ - if( l>=i-maxb+1 ) - { - failflag = ae_false; - break; - } - - /* - * Now the active submatrix is in rows and columns L to I. If - * eigenvalues only are being computed, only the active submatrix - * need be transformed. - */ - if( its==20||its==30 ) - { - - /* - * Exceptional shifts. - */ - for(ii=i-ns+1; ii<=i; ii++) - { - wr->ptr.p_double[ii] = cnst*(ae_fabs(h->ptr.pp_double[ii][ii-1], _state)+ae_fabs(h->ptr.pp_double[ii][ii], _state)); - wi->ptr.p_double[ii] = (double)(0); - } - } - else - { - - /* - * Use eigenvalues of trailing submatrix of order NS as shifts. - */ - copymatrix(h, i-ns+1, i, i-ns+1, i, &s, 1, ns, 1, ns, _state); - hsschur_internalauxschur(ae_false, ae_false, ns, 1, ns, &s, &tmpwr, &tmpwi, 1, ns, z, &work, &workv3, &workc1, &works1, &ierr, _state); - for(p1=1; p1<=ns; p1++) - { - wr->ptr.p_double[i-ns+p1] = tmpwr.ptr.p_double[p1]; - wi->ptr.p_double[i-ns+p1] = tmpwi.ptr.p_double[p1]; - } - if( ierr>0 ) - { - - /* - * If DLAHQR failed to compute all NS eigenvalues, use the - * unconverged diagonal elements as the remaining shifts. - */ - for(ii=1; ii<=ierr; ii++) - { - wr->ptr.p_double[i-ns+ii] = s.ptr.pp_double[ii][ii]; - wi->ptr.p_double[i-ns+ii] = (double)(0); - } - } - } - - /* - * Form the first column of (G-w(1)) (G-w(2)) . . . (G-w(ns)) - * where G is the Hessenberg submatrix H(L:I,L:I) and w is - * the vector of shifts (stored in WR and WI). The result is - * stored in the local array V. - */ - v.ptr.p_double[1] = (double)(1); - for(ii=2; ii<=ns+1; ii++) - { - v.ptr.p_double[ii] = (double)(0); - } - nv = 1; - for(j=i-ns+1; j<=i; j++) - { - if( ae_fp_greater_eq(wi->ptr.p_double[j],(double)(0)) ) - { - if( ae_fp_eq(wi->ptr.p_double[j],(double)(0)) ) - { - - /* - * real shift - */ - p1 = nv+1; - ae_v_move(&vv.ptr.p_double[1], 1, &v.ptr.p_double[1], 1, ae_v_len(1,p1)); - matrixvectormultiply(h, l, l+nv, l, l+nv-1, ae_false, &vv, 1, nv, 1.0, &v, 1, nv+1, -wr->ptr.p_double[j], _state); - nv = nv+1; - } - else - { - if( ae_fp_greater(wi->ptr.p_double[j],(double)(0)) ) - { - - /* - * complex conjugate pair of shifts - */ - p1 = nv+1; - ae_v_move(&vv.ptr.p_double[1], 1, &v.ptr.p_double[1], 1, ae_v_len(1,p1)); - matrixvectormultiply(h, l, l+nv, l, l+nv-1, ae_false, &v, 1, nv, 1.0, &vv, 1, nv+1, -2*wr->ptr.p_double[j], _state); - itemp = vectoridxabsmax(&vv, 1, nv+1, _state); - temp = 1/ae_maxreal(ae_fabs(vv.ptr.p_double[itemp], _state), smlnum, _state); - p1 = nv+1; - ae_v_muld(&vv.ptr.p_double[1], 1, ae_v_len(1,p1), temp); - absw = pythag2(wr->ptr.p_double[j], wi->ptr.p_double[j], _state); - temp = temp*absw*absw; - matrixvectormultiply(h, l, l+nv+1, l, l+nv, ae_false, &vv, 1, nv+1, 1.0, &v, 1, nv+2, temp, _state); - nv = nv+2; - } - } - - /* - * Scale V(1:NV) so that max(abs(V(i))) = 1. If V is zero, - * reset it to the unit vector. - */ - itemp = vectoridxabsmax(&v, 1, nv, _state); - temp = ae_fabs(v.ptr.p_double[itemp], _state); - if( ae_fp_eq(temp,(double)(0)) ) - { - v.ptr.p_double[1] = (double)(1); - for(ii=2; ii<=nv; ii++) - { - v.ptr.p_double[ii] = (double)(0); - } - } - else - { - temp = ae_maxreal(temp, smlnum, _state); - vt = 1/temp; - ae_v_muld(&v.ptr.p_double[1], 1, ae_v_len(1,nv), vt); - } - } - } - - /* - * Multiple-shift QR step - */ - for(k=l; k<=i-1; k++) - { - - /* - * The first iteration of this loop determines a reflection G - * from the vector V and applies it from left and right to H, - * thus creating a nonzero bulge below the subdiagonal. - * - * Each subsequent iteration determines a reflection G to - * restore the Hessenberg form in the (K-1)th column, and thus - * chases the bulge one step toward the bottom of the active - * submatrix. NR is the order of G. - */ - nr = ae_minint(ns+1, i-k+1, _state); - if( k>l ) - { - p1 = k-1; - p2 = k+nr-1; - ae_v_move(&v.ptr.p_double[1], 1, &h->ptr.pp_double[k][p1], h->stride, ae_v_len(1,nr)); - touchint(&p2, _state); - } - generatereflection(&v, nr, &tau, _state); - if( k>l ) - { - h->ptr.pp_double[k][k-1] = v.ptr.p_double[1]; - for(ii=k+1; ii<=i; ii++) - { - h->ptr.pp_double[ii][k-1] = (double)(0); - } - } - v.ptr.p_double[1] = (double)(1); - - /* - * Apply G from the left to transform the rows of the matrix in - * columns K to I2. - */ - applyreflectionfromtheleft(h, tau, &v, k, k+nr-1, k, i2, &work, _state); - - /* - * Apply G from the right to transform the columns of the - * matrix in rows I1 to min(K+NR,I). - */ - applyreflectionfromtheright(h, tau, &v, i1, ae_minint(k+nr, i, _state), k, k+nr-1, &work, _state); - if( wantz ) - { - - /* - * Accumulate transformations in the matrix Z - */ - applyreflectionfromtheright(z, tau, &v, 1, n, k, k+nr-1, &work, _state); - } - } - } - - /* - * Failure to converge in remaining number of iterations - */ - if( failflag ) - { - *info = i; - ae_frame_leave(_state); - return; - } - - /* - * A submatrix of order <= MAXB in rows and columns L to I has split - * off. Use the double-shift QR algorithm to handle it. - */ - hsschur_internalauxschur(wantt, wantz, n, l, i, h, wr, wi, 1, n, z, &work, &workv3, &workc1, &works1, info, _state); - if( *info>0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Decrement number of remaining iterations, and return to start of - * the main loop with a new value of I. - */ - itn = itn-its; - i = l-1; - - /* - * Block below is never executed; it is necessary just to avoid - * "unreachable code" warning about automatically generated code. - * - * We just need a way to transfer control to the end of the function, - * even a fake way which is never actually traversed. - */ - if( alwaysfalse(_state) ) - { - ae_assert(ae_false, "Assertion failed", _state); - break; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Translation of DLAHQR from LAPACK. -*************************************************************************/ -static void hsschur_internalauxschur(ae_bool wantt, - ae_bool wantz, - ae_int_t n, - ae_int_t ilo, - ae_int_t ihi, - /* Real */ ae_matrix* h, - /* Real */ ae_vector* wr, - /* Real */ ae_vector* wi, - ae_int_t iloz, - ae_int_t ihiz, - /* Real */ ae_matrix* z, - /* Real */ ae_vector* work, - /* Real */ ae_vector* workv3, - /* Real */ ae_vector* workc1, - /* Real */ ae_vector* works1, - ae_int_t* info, - ae_state *_state) -{ - double safmin; - double tst; - double ab; - double ba; - double aa; - double bb; - double rt1r; - double rt1i; - double rt2r; - double rt2i; - double tr; - double det; - double rtdisc; - double h21s; - ae_int_t i; - ae_int_t i1; - ae_int_t i2; - ae_int_t itmax; - ae_int_t its; - ae_int_t j; - ae_int_t k; - ae_int_t l; - ae_int_t m; - ae_int_t nh; - ae_int_t nr; - ae_int_t nz; - double cs; - double h11; - double h12; - double h21; - double h22; - double s; - double smlnum; - double sn; - double sum; - double t1; - double t2; - double t3; - double v2; - double v3; - ae_bool failflag; - double dat1; - double dat2; - ae_int_t p1; - double him1im1; - double him1i; - double hiim1; - double hii; - double wrim1; - double wri; - double wiim1; - double wii; - double ulp; - - *info = 0; - - *info = 0; - dat1 = 0.75; - dat2 = -0.4375; - - /* - * Quick return if possible - */ - if( n==0 ) - { - return; - } - if( ilo==ihi ) - { - wr->ptr.p_double[ilo] = h->ptr.pp_double[ilo][ilo]; - wi->ptr.p_double[ilo] = (double)(0); - return; - } - - /* - * ==== clear out the trash ==== - */ - for(j=ilo; j<=ihi-3; j++) - { - h->ptr.pp_double[j+2][j] = (double)(0); - h->ptr.pp_double[j+3][j] = (double)(0); - } - if( ilo<=ihi-2 ) - { - h->ptr.pp_double[ihi][ihi-2] = (double)(0); - } - nh = ihi-ilo+1; - nz = ihiz-iloz+1; - - /* - * Set machine-dependent constants for the stopping criterion. - */ - safmin = ae_minrealnumber; - ulp = ae_machineepsilon; - smlnum = safmin*(nh/ulp); - - /* - * I1 and I2 are the indices of the first row and last column of H - * to which transformations must be applied. If eigenvalues only are - * being computed, I1 and I2 are set inside the main loop. - * - * Setting them to large negative value helps to debug possible errors - * due to uninitialized variables; also it helps to avoid compiler - * warnings. - */ - i1 = -99999; - i2 = -99999; - if( wantt ) - { - i1 = 1; - i2 = n; - } - - /* - * ITMAX is the total number of QR iterations allowed. - */ - itmax = 30*ae_maxint(10, nh, _state); - - /* - * The main loop begins here. I is the loop index and decreases from - * IHI to ILO in steps of 1 or 2. Each iteration of the loop works - * with the active submatrix in rows and columns L to I. - * Eigenvalues I+1 to IHI have already converged. Either L = ILO or - * H(L,L-1) is negligible so that the matrix splits. - */ - i = ihi; - for(;;) - { - l = ilo; - if( i=l+1; k--) - { - if( ae_fp_less_eq(ae_fabs(h->ptr.pp_double[k][k-1], _state),smlnum) ) - { - break; - } - tst = ae_fabs(h->ptr.pp_double[k-1][k-1], _state)+ae_fabs(h->ptr.pp_double[k][k], _state); - if( ae_fp_eq(tst,(double)(0)) ) - { - if( k-2>=ilo ) - { - tst = tst+ae_fabs(h->ptr.pp_double[k-1][k-2], _state); - } - if( k+1<=ihi ) - { - tst = tst+ae_fabs(h->ptr.pp_double[k+1][k], _state); - } - } - - /* - * ==== The following is a conservative small subdiagonal - * . deflation criterion due to Ahues & Tisseur (LAWN 122, - * . 1997). It has better mathematical foundation and - * . improves accuracy in some cases. ==== - */ - if( ae_fp_less_eq(ae_fabs(h->ptr.pp_double[k][k-1], _state),ulp*tst) ) - { - ab = ae_maxreal(ae_fabs(h->ptr.pp_double[k][k-1], _state), ae_fabs(h->ptr.pp_double[k-1][k], _state), _state); - ba = ae_minreal(ae_fabs(h->ptr.pp_double[k][k-1], _state), ae_fabs(h->ptr.pp_double[k-1][k], _state), _state); - aa = ae_maxreal(ae_fabs(h->ptr.pp_double[k][k], _state), ae_fabs(h->ptr.pp_double[k-1][k-1]-h->ptr.pp_double[k][k], _state), _state); - bb = ae_minreal(ae_fabs(h->ptr.pp_double[k][k], _state), ae_fabs(h->ptr.pp_double[k-1][k-1]-h->ptr.pp_double[k][k], _state), _state); - s = aa+ab; - if( ae_fp_less_eq(ba*(ab/s),ae_maxreal(smlnum, ulp*(bb*(aa/s)), _state)) ) - { - break; - } - } - } - l = k; - if( l>ilo ) - { - - /* - * H(L,L-1) is negligible - */ - h->ptr.pp_double[l][l-1] = (double)(0); - } - - /* - * Exit from loop if a submatrix of order 1 or 2 has split off. - */ - if( l>=i-1 ) - { - failflag = ae_false; - break; - } - - /* - * Now the active submatrix is in rows and columns L to I. If - * eigenvalues only are being computed, only the active submatrix - * need be transformed. - */ - if( !wantt ) - { - i1 = l; - i2 = i; - } - - /* - * Shifts - */ - if( its==10 ) - { - - /* - * Exceptional shift. - */ - s = ae_fabs(h->ptr.pp_double[l+1][l], _state)+ae_fabs(h->ptr.pp_double[l+2][l+1], _state); - h11 = dat1*s+h->ptr.pp_double[l][l]; - h12 = dat2*s; - h21 = s; - h22 = h11; - } - else - { - if( its==20 ) - { - - /* - * Exceptional shift. - */ - s = ae_fabs(h->ptr.pp_double[i][i-1], _state)+ae_fabs(h->ptr.pp_double[i-1][i-2], _state); - h11 = dat1*s+h->ptr.pp_double[i][i]; - h12 = dat2*s; - h21 = s; - h22 = h11; - } - else - { - - /* - * Prepare to use Francis' double shift - * (i.e. 2nd degree generalized Rayleigh quotient) - */ - h11 = h->ptr.pp_double[i-1][i-1]; - h21 = h->ptr.pp_double[i][i-1]; - h12 = h->ptr.pp_double[i-1][i]; - h22 = h->ptr.pp_double[i][i]; - } - } - s = ae_fabs(h11, _state)+ae_fabs(h12, _state)+ae_fabs(h21, _state)+ae_fabs(h22, _state); - if( ae_fp_eq(s,(double)(0)) ) - { - rt1r = (double)(0); - rt1i = (double)(0); - rt2r = (double)(0); - rt2i = (double)(0); - } - else - { - h11 = h11/s; - h21 = h21/s; - h12 = h12/s; - h22 = h22/s; - tr = (h11+h22)/2; - det = (h11-tr)*(h22-tr)-h12*h21; - rtdisc = ae_sqrt(ae_fabs(det, _state), _state); - if( ae_fp_greater_eq(det,(double)(0)) ) - { - - /* - * ==== complex conjugate shifts ==== - */ - rt1r = tr*s; - rt2r = rt1r; - rt1i = rtdisc*s; - rt2i = -rt1i; - } - else - { - - /* - * ==== real shifts (use only one of them) ==== - */ - rt1r = tr+rtdisc; - rt2r = tr-rtdisc; - if( ae_fp_less_eq(ae_fabs(rt1r-h22, _state),ae_fabs(rt2r-h22, _state)) ) - { - rt1r = rt1r*s; - rt2r = rt1r; - } - else - { - rt2r = rt2r*s; - rt1r = rt2r; - } - rt1i = (double)(0); - rt2i = (double)(0); - } - } - - /* - * Look for two consecutive small subdiagonal elements. - */ - for(m=i-2; m>=l; m--) - { - - /* - * Determine the effect of starting the double-shift QR - * iteration at row M, and see if this would make H(M,M-1) - * negligible. (The following uses scaling to avoid - * overflows and most underflows.) - */ - h21s = h->ptr.pp_double[m+1][m]; - s = ae_fabs(h->ptr.pp_double[m][m]-rt2r, _state)+ae_fabs(rt2i, _state)+ae_fabs(h21s, _state); - h21s = h->ptr.pp_double[m+1][m]/s; - workv3->ptr.p_double[1] = h21s*h->ptr.pp_double[m][m+1]+(h->ptr.pp_double[m][m]-rt1r)*((h->ptr.pp_double[m][m]-rt2r)/s)-rt1i*(rt2i/s); - workv3->ptr.p_double[2] = h21s*(h->ptr.pp_double[m][m]+h->ptr.pp_double[m+1][m+1]-rt1r-rt2r); - workv3->ptr.p_double[3] = h21s*h->ptr.pp_double[m+2][m+1]; - s = ae_fabs(workv3->ptr.p_double[1], _state)+ae_fabs(workv3->ptr.p_double[2], _state)+ae_fabs(workv3->ptr.p_double[3], _state); - workv3->ptr.p_double[1] = workv3->ptr.p_double[1]/s; - workv3->ptr.p_double[2] = workv3->ptr.p_double[2]/s; - workv3->ptr.p_double[3] = workv3->ptr.p_double[3]/s; - if( m==l ) - { - break; - } - if( ae_fp_less_eq(ae_fabs(h->ptr.pp_double[m][m-1], _state)*(ae_fabs(workv3->ptr.p_double[2], _state)+ae_fabs(workv3->ptr.p_double[3], _state)),ulp*ae_fabs(workv3->ptr.p_double[1], _state)*(ae_fabs(h->ptr.pp_double[m-1][m-1], _state)+ae_fabs(h->ptr.pp_double[m][m], _state)+ae_fabs(h->ptr.pp_double[m+1][m+1], _state))) ) - { - break; - } - } - - /* - * Double-shift QR step - */ - for(k=m; k<=i-1; k++) - { - - /* - * The first iteration of this loop determines a reflection G - * from the vector V and applies it from left and right to H, - * thus creating a nonzero bulge below the subdiagonal. - * - * Each subsequent iteration determines a reflection G to - * restore the Hessenberg form in the (K-1)th column, and thus - * chases the bulge one step toward the bottom of the active - * submatrix. NR is the order of G. - */ - nr = ae_minint(3, i-k+1, _state); - if( k>m ) - { - for(p1=1; p1<=nr; p1++) - { - workv3->ptr.p_double[p1] = h->ptr.pp_double[k+p1-1][k-1]; - } - } - generatereflection(workv3, nr, &t1, _state); - if( k>m ) - { - h->ptr.pp_double[k][k-1] = workv3->ptr.p_double[1]; - h->ptr.pp_double[k+1][k-1] = (double)(0); - if( kptr.pp_double[k+2][k-1] = (double)(0); - } - } - else - { - if( m>l ) - { - - /* - * ==== Use the following instead of - * H( K, K-1 ) = -H( K, K-1 ) to - * avoid a bug when v(2) and v(3) - * underflow. ==== - */ - h->ptr.pp_double[k][k-1] = h->ptr.pp_double[k][k-1]*(1-t1); - } - } - v2 = workv3->ptr.p_double[2]; - t2 = t1*v2; - if( nr==3 ) - { - v3 = workv3->ptr.p_double[3]; - t3 = t1*v3; - - /* - * Apply G from the left to transform the rows of the matrix - * in columns K to I2. - */ - for(j=k; j<=i2; j++) - { - sum = h->ptr.pp_double[k][j]+v2*h->ptr.pp_double[k+1][j]+v3*h->ptr.pp_double[k+2][j]; - h->ptr.pp_double[k][j] = h->ptr.pp_double[k][j]-sum*t1; - h->ptr.pp_double[k+1][j] = h->ptr.pp_double[k+1][j]-sum*t2; - h->ptr.pp_double[k+2][j] = h->ptr.pp_double[k+2][j]-sum*t3; - } - - /* - * Apply G from the right to transform the columns of the - * matrix in rows I1 to min(K+3,I). - */ - for(j=i1; j<=ae_minint(k+3, i, _state); j++) - { - sum = h->ptr.pp_double[j][k]+v2*h->ptr.pp_double[j][k+1]+v3*h->ptr.pp_double[j][k+2]; - h->ptr.pp_double[j][k] = h->ptr.pp_double[j][k]-sum*t1; - h->ptr.pp_double[j][k+1] = h->ptr.pp_double[j][k+1]-sum*t2; - h->ptr.pp_double[j][k+2] = h->ptr.pp_double[j][k+2]-sum*t3; - } - if( wantz ) - { - - /* - * Accumulate transformations in the matrix Z - */ - for(j=iloz; j<=ihiz; j++) - { - sum = z->ptr.pp_double[j][k]+v2*z->ptr.pp_double[j][k+1]+v3*z->ptr.pp_double[j][k+2]; - z->ptr.pp_double[j][k] = z->ptr.pp_double[j][k]-sum*t1; - z->ptr.pp_double[j][k+1] = z->ptr.pp_double[j][k+1]-sum*t2; - z->ptr.pp_double[j][k+2] = z->ptr.pp_double[j][k+2]-sum*t3; - } - } - } - else - { - if( nr==2 ) - { - - /* - * Apply G from the left to transform the rows of the matrix - * in columns K to I2. - */ - for(j=k; j<=i2; j++) - { - sum = h->ptr.pp_double[k][j]+v2*h->ptr.pp_double[k+1][j]; - h->ptr.pp_double[k][j] = h->ptr.pp_double[k][j]-sum*t1; - h->ptr.pp_double[k+1][j] = h->ptr.pp_double[k+1][j]-sum*t2; - } - - /* - * Apply G from the right to transform the columns of the - * matrix in rows I1 to min(K+3,I). - */ - for(j=i1; j<=i; j++) - { - sum = h->ptr.pp_double[j][k]+v2*h->ptr.pp_double[j][k+1]; - h->ptr.pp_double[j][k] = h->ptr.pp_double[j][k]-sum*t1; - h->ptr.pp_double[j][k+1] = h->ptr.pp_double[j][k+1]-sum*t2; - } - if( wantz ) - { - - /* - * Accumulate transformations in the matrix Z - */ - for(j=iloz; j<=ihiz; j++) - { - sum = z->ptr.pp_double[j][k]+v2*z->ptr.pp_double[j][k+1]; - z->ptr.pp_double[j][k] = z->ptr.pp_double[j][k]-sum*t1; - z->ptr.pp_double[j][k+1] = z->ptr.pp_double[j][k+1]-sum*t2; - } - } - } - } - } - } - - /* - * Failure to converge in remaining number of iterations - */ - if( failflag ) - { - *info = i; - return; - } - - /* - * Convergence - */ - if( l==i ) - { - - /* - * H(I,I-1) is negligible: one eigenvalue has converged. - */ - wr->ptr.p_double[i] = h->ptr.pp_double[i][i]; - wi->ptr.p_double[i] = (double)(0); - } - else - { - if( l==i-1 ) - { - - /* - * H(I-1,I-2) is negligible: a pair of eigenvalues have converged. - * - * Transform the 2-by-2 submatrix to standard Schur form, - * and compute and store the eigenvalues. - */ - him1im1 = h->ptr.pp_double[i-1][i-1]; - him1i = h->ptr.pp_double[i-1][i]; - hiim1 = h->ptr.pp_double[i][i-1]; - hii = h->ptr.pp_double[i][i]; - hsschur_aux2x2schur(&him1im1, &him1i, &hiim1, &hii, &wrim1, &wiim1, &wri, &wii, &cs, &sn, _state); - wr->ptr.p_double[i-1] = wrim1; - wi->ptr.p_double[i-1] = wiim1; - wr->ptr.p_double[i] = wri; - wi->ptr.p_double[i] = wii; - h->ptr.pp_double[i-1][i-1] = him1im1; - h->ptr.pp_double[i-1][i] = him1i; - h->ptr.pp_double[i][i-1] = hiim1; - h->ptr.pp_double[i][i] = hii; - if( wantt ) - { - - /* - * Apply the transformation to the rest of H. - */ - if( i2>i ) - { - workc1->ptr.p_double[1] = cs; - works1->ptr.p_double[1] = sn; - applyrotationsfromtheleft(ae_true, i-1, i, i+1, i2, workc1, works1, h, work, _state); - } - workc1->ptr.p_double[1] = cs; - works1->ptr.p_double[1] = sn; - applyrotationsfromtheright(ae_true, i1, i-2, i-1, i, workc1, works1, h, work, _state); - } - if( wantz ) - { - - /* - * Apply the transformation to Z. - */ - workc1->ptr.p_double[1] = cs; - works1->ptr.p_double[1] = sn; - applyrotationsfromtheright(ae_true, iloz, iloz+nz-1, i-1, i, workc1, works1, z, work, _state); - } - } - } - - /* - * return to start of the main loop with new value of I. - */ - i = l-1; - } -} - - -static void hsschur_aux2x2schur(double* a, - double* b, - double* c, - double* d, - double* rt1r, - double* rt1i, - double* rt2r, - double* rt2i, - double* cs, - double* sn, - ae_state *_state) -{ - double multpl; - double aa; - double bb; - double bcmax; - double bcmis; - double cc; - double cs1; - double dd; - double eps; - double p; - double sab; - double sac; - double scl; - double sigma; - double sn1; - double tau; - double temp; - double z; - - *rt1r = 0; - *rt1i = 0; - *rt2r = 0; - *rt2i = 0; - *cs = 0; - *sn = 0; - - multpl = 4.0; - eps = ae_machineepsilon; - if( ae_fp_eq(*c,(double)(0)) ) - { - *cs = (double)(1); - *sn = (double)(0); - } - else - { - if( ae_fp_eq(*b,(double)(0)) ) - { - - /* - * Swap rows and columns - */ - *cs = (double)(0); - *sn = (double)(1); - temp = *d; - *d = *a; - *a = temp; - *b = -*c; - *c = (double)(0); - } - else - { - if( ae_fp_eq(*a-(*d),(double)(0))&&hsschur_extschursigntoone(*b, _state)!=hsschur_extschursigntoone(*c, _state) ) - { - *cs = (double)(1); - *sn = (double)(0); - } - else - { - temp = *a-(*d); - p = 0.5*temp; - bcmax = ae_maxreal(ae_fabs(*b, _state), ae_fabs(*c, _state), _state); - bcmis = ae_minreal(ae_fabs(*b, _state), ae_fabs(*c, _state), _state)*hsschur_extschursigntoone(*b, _state)*hsschur_extschursigntoone(*c, _state); - scl = ae_maxreal(ae_fabs(p, _state), bcmax, _state); - z = p/scl*p+bcmax/scl*bcmis; - - /* - * If Z is of the order of the machine accuracy, postpone the - * decision on the nature of eigenvalues - */ - if( ae_fp_greater_eq(z,multpl*eps) ) - { - - /* - * Real eigenvalues. Compute A and D. - */ - z = p+hsschur_extschursign(ae_sqrt(scl, _state)*ae_sqrt(z, _state), p, _state); - *a = *d+z; - *d = *d-bcmax/z*bcmis; - - /* - * Compute B and the rotation matrix - */ - tau = pythag2(*c, z, _state); - *cs = z/tau; - *sn = *c/tau; - *b = *b-(*c); - *c = (double)(0); - } - else - { - - /* - * Complex eigenvalues, or real (almost) equal eigenvalues. - * Make diagonal elements equal. - */ - sigma = *b+(*c); - tau = pythag2(sigma, temp, _state); - *cs = ae_sqrt(0.5*(1+ae_fabs(sigma, _state)/tau), _state); - *sn = -p/(tau*(*cs))*hsschur_extschursign((double)(1), sigma, _state); - - /* - * Compute [ AA BB ] = [ A B ] [ CS -SN ] - * [ CC DD ] [ C D ] [ SN CS ] - */ - aa = *a*(*cs)+*b*(*sn); - bb = -*a*(*sn)+*b*(*cs); - cc = *c*(*cs)+*d*(*sn); - dd = -*c*(*sn)+*d*(*cs); - - /* - * Compute [ A B ] = [ CS SN ] [ AA BB ] - * [ C D ] [-SN CS ] [ CC DD ] - */ - *a = aa*(*cs)+cc*(*sn); - *b = bb*(*cs)+dd*(*sn); - *c = -aa*(*sn)+cc*(*cs); - *d = -bb*(*sn)+dd*(*cs); - temp = 0.5*(*a+(*d)); - *a = temp; - *d = temp; - if( ae_fp_neq(*c,(double)(0)) ) - { - if( ae_fp_neq(*b,(double)(0)) ) - { - if( hsschur_extschursigntoone(*b, _state)==hsschur_extschursigntoone(*c, _state) ) - { - - /* - * Real eigenvalues: reduce to upper triangular form - */ - sab = ae_sqrt(ae_fabs(*b, _state), _state); - sac = ae_sqrt(ae_fabs(*c, _state), _state); - p = hsschur_extschursign(sab*sac, *c, _state); - tau = 1/ae_sqrt(ae_fabs(*b+(*c), _state), _state); - *a = temp+p; - *d = temp-p; - *b = *b-(*c); - *c = (double)(0); - cs1 = sab*tau; - sn1 = sac*tau; - temp = *cs*cs1-*sn*sn1; - *sn = *cs*sn1+*sn*cs1; - *cs = temp; - } - } - else - { - *b = -*c; - *c = (double)(0); - temp = *cs; - *cs = -*sn; - *sn = temp; - } - } - } - } - } - } - - /* - * Store eigenvalues in (RT1R,RT1I) and (RT2R,RT2I). - */ - *rt1r = *a; - *rt2r = *d; - if( ae_fp_eq(*c,(double)(0)) ) - { - *rt1i = (double)(0); - *rt2i = (double)(0); - } - else - { - *rt1i = ae_sqrt(ae_fabs(*b, _state), _state)*ae_sqrt(ae_fabs(*c, _state), _state); - *rt2i = -*rt1i; - } -} - - -static double hsschur_extschursign(double a, double b, ae_state *_state) -{ - double result; - - - if( ae_fp_greater_eq(b,(double)(0)) ) - { - result = ae_fabs(a, _state); - } - else - { - result = -ae_fabs(a, _state); - } - return result; -} - - -static ae_int_t hsschur_extschursigntoone(double b, ae_state *_state) -{ - ae_int_t result; - - - if( ae_fp_greater_eq(b,(double)(0)) ) - { - result = 1; - } - else - { - result = -1; - } - return result; -} - - -#endif -#if defined(AE_COMPILE_EVD) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function initializes subspace iteration solver. This solver is used -to solve symmetric real eigenproblems where just a few (top K) eigenvalues -and corresponding eigenvectors is required. - -This solver can be significantly faster than complete EVD decomposition -in the following case: -* when only just a small fraction of top eigenpairs of dense matrix is - required. When K approaches N, this solver is slower than complete dense - EVD -* when problem matrix is sparse (and/or is not known explicitly, i.e. only - matrix-matrix product can be performed) - -USAGE (explicit dense/sparse matrix): -1. User initializes algorithm state with eigsubspacecreate() call -2. [optional] User tunes solver parameters by calling eigsubspacesetcond() - or other functions -3. User calls eigsubspacesolvedense() or eigsubspacesolvesparse() methods, - which take algorithm state and 2D array or alglib.sparsematrix object. - -USAGE (out-of-core mode): -1. User initializes algorithm state with eigsubspacecreate() call -2. [optional] User tunes solver parameters by calling eigsubspacesetcond() - or other functions -3. User activates out-of-core mode of the solver and repeatedly calls - communication functions in a loop like below: - > alglib.eigsubspaceoocstart(state) - > while alglib.eigsubspaceooccontinue(state) do - > alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) - > alglib.eigsubspaceoocgetrequestdata(state, out X) - > [calculate Y=A*X, with X=R^NxM] - > alglib.eigsubspaceoocsendresult(state, in Y) - > alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - N - problem dimensionality, N>0 - K - number of top eigenvector to calculate, 00, "EigSubspaceCreate: N<=0", _state); - ae_assert(k>0, "EigSubspaceCreate: K<=0", _state); - ae_assert(k<=n, "EigSubspaceCreate: K>N", _state); - eigsubspacecreatebuf(n, k, state, _state); -} - - -/************************************************************************* -Buffered version of constructor which aims to reuse previously allocated -memory as much as possible. - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspacecreatebuf(ae_int_t n, - ae_int_t k, - eigsubspacestate* state, - ae_state *_state) -{ - - - ae_assert(n>0, "EigSubspaceCreate: N<=0", _state); - ae_assert(k>0, "EigSubspaceCreate: K<=0", _state); - ae_assert(k<=n, "EigSubspaceCreate: K>N", _state); - - /* - * Initialize algorithm parameters - */ - state->running = ae_false; - state->n = n; - state->k = k; - state->nwork = ae_minint(ae_maxint(2*k, 8, _state), n, _state); - state->eigenvectorsneeded = 1; - state->usewarmstart = ae_false; - state->firstcall = ae_true; - eigsubspacesetcond(state, 0.0, 0, _state); - - /* - * Allocate temporaries - */ - rmatrixsetlengthatleast(&state->x, state->n, state->nwork, _state); - rmatrixsetlengthatleast(&state->ax, state->n, state->nwork, _state); -} - - -/************************************************************************* -This function sets stopping critera for the solver: -* error in eigenvector/value allowed by solver -* maximum number of iterations to perform - -INPUT PARAMETERS: - State - solver structure - Eps - eps>=0, with non-zero value used to tell solver that - it can stop after all eigenvalues converged with - error roughly proportional to eps*MAX(LAMBDA_MAX), - where LAMBDA_MAX is a maximum eigenvalue. - Zero value means that no check for precision is - performed. - MaxIts - maxits>=0, with non-zero value used to tell solver - that it can stop after maxits steps (no matter how - precise current estimate is) - -NOTE: passing eps=0 and maxits=0 results in automatic selection of - moderate eps as stopping criteria (1.0E-6 in current implementation, - but it may change without notice). - -NOTE: very small values of eps are possible (say, 1.0E-12), although the - larger problem you solve (N and/or K), the harder it is to find - precise eigenvectors because rounding errors tend to accumulate. - -NOTE: passing non-zero eps results in some performance penalty, roughly - equal to 2N*(2K)^2 FLOPs per iteration. These additional computations - are required in order to estimate current error in eigenvalues via - Rayleigh-Ritz process. - Most of this additional time is spent in construction of ~2Kx2K - symmetric subproblem whose eigenvalues are checked with exact - eigensolver. - This additional time is negligible if you search for eigenvalues of - the large dense matrix, but may become noticeable on highly sparse - EVD problems, where cost of matrix-matrix product is low. - If you set eps to exactly zero, Rayleigh-Ritz phase is completely - turned off. - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspacesetcond(eigsubspacestate* state, - double eps, - ae_int_t maxits, - ae_state *_state) -{ - - - ae_assert(!state->running, "EigSubspaceSetCond: solver is already running", _state); - ae_assert(ae_isfinite(eps, _state)&&ae_fp_greater_eq(eps,(double)(0)), "EigSubspaceSetCond: Eps<0 or NAN/INF", _state); - ae_assert(maxits>=0, "EigSubspaceSetCond: MaxIts<0", _state); - if( ae_fp_eq(eps,(double)(0))&&maxits==0 ) - { - eps = 1.0E-6; - } - state->eps = eps; - state->maxits = maxits; -} - - -/************************************************************************* -This function sets warm-start mode of the solver: next call to the solver -will reuse previous subspace as warm-start point. It can significantly -speed-up convergence when you solve many similar eigenproblems. - -INPUT PARAMETERS: - State - solver structure - UseWarmStart- either True or False - - -- ALGLIB -- - Copyright 12.11.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspacesetwarmstart(eigsubspacestate* state, - ae_bool usewarmstart, - ae_state *_state) -{ - - - ae_assert(!state->running, "EigSubspaceSetWarmStart: solver is already running", _state); - state->usewarmstart = usewarmstart; -} - - -/************************************************************************* -This function initiates out-of-core mode of subspace eigensolver. It -should be used in conjunction with other out-of-core-related functions of -this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - State - solver object - MType - matrix type: - * 0 for real symmetric matrix (solver assumes that - matrix being processed is symmetric; symmetric - direct eigensolver is used for smaller subproblems - arising during solution of larger "full" task) - Future versions of ALGLIB may introduce support for - other matrix types; for now, only symmetric - eigenproblems are supported. - - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspaceoocstart(eigsubspacestate* state, - ae_int_t mtype, - ae_state *_state) -{ - - - ae_assert(!state->running, "EigSubspaceStart: solver is already running", _state); - ae_assert(mtype==0, "EigSubspaceStart: incorrect mtype parameter", _state); - ae_vector_set_length(&state->rstate.ia, 7+1, _state); - ae_vector_set_length(&state->rstate.ra, 1+1, _state); - state->rstate.stage = -1; - evd_clearrfields(state, _state); - state->running = ae_true; - state->matrixtype = mtype; -} - - -/************************************************************************* -This function performs subspace iteration in the out-of-core mode. It -should be used in conjunction with other out-of-core-related functions of -this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -ae_bool eigsubspaceooccontinue(eigsubspacestate* state, ae_state *_state) -{ - ae_bool result; - - - ae_assert(state->running, "EigSubspaceContinue: solver is not running", _state); - result = eigsubspaceiteration(state, _state); - state->running = result; - return result; -} - - -/************************************************************************* -This function is used to retrieve information about out-of-core request -sent by solver to user code: request type (current version of the solver -sends only requests for matrix-matrix products) and request size (size of -the matrices being multiplied). - -This function returns just request metrics; in order to get contents of -the matrices being multiplied, use eigsubspaceoocgetrequestdata(). - -It should be used in conjunction with other out-of-core-related functions -of this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - State - solver running in out-of-core mode - -OUTPUT PARAMETERS: - RequestType - type of the request to process: - * 0 - for matrix-matrix product A*X, with A being - NxN matrix whose eigenvalues/vectors are needed, - and X being NxREQUESTSIZE one which is returned - by the eigsubspaceoocgetrequestdata(). - RequestSize - size of the X matrix (number of columns), usually - it is several times larger than number of vectors - K requested by user. - - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspaceoocgetrequestinfo(eigsubspacestate* state, - ae_int_t* requesttype, - ae_int_t* requestsize, - ae_state *_state) -{ - - *requesttype = 0; - *requestsize = 0; - - ae_assert(state->running, "EigSubspaceOOCGetRequestInfo: solver is not running", _state); - *requesttype = state->requesttype; - *requestsize = state->requestsize; -} - - -/************************************************************************* -This function is used to retrieve information about out-of-core request -sent by solver to user code: matrix X (array[N,RequestSize) which have to -be multiplied by out-of-core matrix A in a product A*X. - -This function returns just request data; in order to get size of the data -prior to processing requestm, use eigsubspaceoocgetrequestinfo(). - -It should be used in conjunction with other out-of-core-related functions -of this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - State - solver running in out-of-core mode - X - possibly preallocated storage; reallocated if - needed, left unchanged, if large enough to store - request data. - -OUTPUT PARAMETERS: - X - array[N,RequestSize] or larger, leading rectangle - is filled with dense matrix X. - - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspaceoocgetrequestdata(eigsubspacestate* state, - /* Real */ ae_matrix* x, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - ae_assert(state->running, "EigSubspaceOOCGetRequestInfo: solver is not running", _state); - rmatrixsetlengthatleast(x, state->n, state->requestsize, _state); - for(i=0; i<=state->n-1; i++) - { - for(j=0; j<=state->requestsize-1; j++) - { - x->ptr.pp_double[i][j] = state->x.ptr.pp_double[i][j]; - } - } -} - - -/************************************************************************* -This function is used to send user reply to out-of-core request sent by -solver. Usually it is product A*X for returned by solver matrix X. - -It should be used in conjunction with other out-of-core-related functions -of this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - State - solver running in out-of-core mode - AX - array[N,RequestSize] or larger, leading rectangle - is filled with product A*X. - - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspaceoocsendresult(eigsubspacestate* state, - /* Real */ ae_matrix* ax, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - ae_assert(state->running, "EigSubspaceOOCGetRequestInfo: solver is not running", _state); - for(i=0; i<=state->n-1; i++) - { - for(j=0; j<=state->requestsize-1; j++) - { - state->ax.ptr.pp_double[i][j] = ax->ptr.pp_double[i][j]; - } - } -} - - -/************************************************************************* -This function finalizes out-of-core mode of subspace eigensolver. It -should be used in conjunction with other out-of-core-related functions of -this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - State - solver state - -OUTPUT PARAMETERS: - W - array[K], depending on solver settings: - * top K eigenvalues ordered by descending - if - eigenvectors are returned in Z - * zeros - if invariant subspace is returned in Z - Z - array[N,K], depending on solver settings either: - * matrix of eigenvectors found - * orthogonal basis of K-dimensional invariant subspace - Rep - report with additional parameters - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspaceoocstop(eigsubspacestate* state, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* z, - eigsubspacereport* rep, - ae_state *_state) -{ - ae_int_t n; - ae_int_t k; - ae_int_t i; - ae_int_t j; - - ae_vector_clear(w); - ae_matrix_clear(z); - _eigsubspacereport_clear(rep); - - ae_assert(!state->running, "EigSubspaceStop: solver is still running", _state); - n = state->n; - k = state->k; - ae_vector_set_length(w, k, _state); - ae_matrix_set_length(z, n, k, _state); - for(i=0; i<=k-1; i++) - { - w->ptr.p_double[i] = state->rw.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=k-1; j++) - { - z->ptr.pp_double[i][j] = state->rq.ptr.pp_double[i][j]; - } - } - rep->iterationscount = state->repiterationscount; -} - - -/************************************************************************* -This function runs eigensolver for dense NxN symmetric matrix A, given by -upper or lower triangle. - -This function can not process nonsymmetric matrices. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - State - solver state - A - array[N,N], symmetric NxN matrix given by one of its - triangles - IsUpper - whether upper or lower triangle of A is given (the - other one is not referenced at all). - -OUTPUT PARAMETERS: - W - array[K], top K eigenvalues ordered by descending - of their absolute values - Z - array[N,K], matrix of eigenvectors found - Rep - report with additional parameters - -NOTE: internally this function allocates a copy of NxN dense A. You should - take it into account when working with very large matrices occupying - almost all RAM. - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspacesolvedenses(eigsubspacestate* state, - /* Real */ ae_matrix* a, - ae_bool isupper, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* z, - eigsubspacereport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t m; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - ae_matrix acopy; - - ae_frame_make(_state, &_frame_block); - memset(&acopy, 0, sizeof(acopy)); - ae_vector_clear(w); - ae_matrix_clear(z); - _eigsubspacereport_clear(rep); - ae_matrix_init(&acopy, 0, 0, DT_REAL, _state, ae_true); - - ae_assert(!state->running, "EigSubspaceSolveDenseS: solver is still running", _state); - n = state->n; - - /* - * Allocate copy of A, copy one triangle to another - */ - ae_matrix_set_length(&acopy, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - if( isupper ) - { - v = a->ptr.pp_double[i][j]; - } - else - { - v = a->ptr.pp_double[j][i]; - } - acopy.ptr.pp_double[i][j] = v; - acopy.ptr.pp_double[j][i] = v; - } - } - - /* - * Start iterations - */ - state->matrixtype = 0; - ae_vector_set_length(&state->rstate.ia, 7+1, _state); - ae_vector_set_length(&state->rstate.ra, 1+1, _state); - state->rstate.stage = -1; - evd_clearrfields(state, _state); - while(eigsubspaceiteration(state, _state)) - { - - /* - * Calculate A*X with RMatrixGEMM - */ - ae_assert(state->requesttype==0, "EigSubspaceSolveDense: integrity check failed", _state); - ae_assert(state->requestsize>0, "EigSubspaceSolveDense: integrity check failed", _state); - m = state->requestsize; - rmatrixgemm(n, m, n, 1.0, &acopy, 0, 0, 0, &state->x, 0, 0, 0, 0.0, &state->ax, 0, 0, _state); - } - k = state->k; - ae_vector_set_length(w, k, _state); - ae_matrix_set_length(z, n, k, _state); - for(i=0; i<=k-1; i++) - { - w->ptr.p_double[i] = state->rw.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=k-1; j++) - { - z->ptr.pp_double[i][j] = state->rq.ptr.pp_double[i][j]; - } - } - rep->iterationscount = state->repiterationscount; - ae_frame_leave(_state); -} - - -/************************************************************************* -This function runs eigensolver for dense NxN symmetric matrix A, given by -upper or lower triangle. - -This function can not process nonsymmetric matrices. - -INPUT PARAMETERS: - State - solver state - A - NxN symmetric matrix given by one of its triangles - IsUpper - whether upper or lower triangle of A is given (the - other one is not referenced at all). - -OUTPUT PARAMETERS: - W - array[K], top K eigenvalues ordered by descending - of their absolute values - Z - array[N,K], matrix of eigenvectors found - Rep - report with additional parameters - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspacesolvesparses(eigsubspacestate* state, - sparsematrix* a, - ae_bool isupper, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* z, - eigsubspacereport* rep, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t k; - - ae_vector_clear(w); - ae_matrix_clear(z); - _eigsubspacereport_clear(rep); - - ae_assert(!state->running, "EigSubspaceSolveSparseS: solver is still running", _state); - n = state->n; - state->matrixtype = 0; - ae_vector_set_length(&state->rstate.ia, 7+1, _state); - ae_vector_set_length(&state->rstate.ra, 1+1, _state); - state->rstate.stage = -1; - evd_clearrfields(state, _state); - while(eigsubspaceiteration(state, _state)) - { - ae_assert(state->requesttype==0, "EigSubspaceSolveDense: integrity check failed", _state); - ae_assert(state->requestsize>0, "EigSubspaceSolveDense: integrity check failed", _state); - sparsesmm(a, isupper, &state->x, state->requestsize, &state->ax, _state); - } - k = state->k; - ae_vector_set_length(w, k, _state); - ae_matrix_set_length(z, n, k, _state); - for(i=0; i<=k-1; i++) - { - w->ptr.p_double[i] = state->rw.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=k-1; j++) - { - z->ptr.pp_double[i][j] = state->rq.ptr.pp_double[i][j]; - } - } - rep->iterationscount = state->repiterationscount; -} - - -/************************************************************************* -Internal r-comm function. - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -ae_bool eigsubspaceiteration(eigsubspacestate* state, ae_state *_state) -{ - ae_int_t n; - ae_int_t nwork; - ae_int_t k; - ae_int_t cnt; - ae_int_t i; - ae_int_t i1; - ae_int_t j; - double vv; - double v; - ae_int_t convcnt; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - n = state->rstate.ia.ptr.p_int[0]; - nwork = state->rstate.ia.ptr.p_int[1]; - k = state->rstate.ia.ptr.p_int[2]; - cnt = state->rstate.ia.ptr.p_int[3]; - i = state->rstate.ia.ptr.p_int[4]; - i1 = state->rstate.ia.ptr.p_int[5]; - j = state->rstate.ia.ptr.p_int[6]; - convcnt = state->rstate.ia.ptr.p_int[7]; - vv = state->rstate.ra.ptr.p_double[0]; - v = state->rstate.ra.ptr.p_double[1]; - } - else - { - n = 359; - nwork = -58; - k = -919; - cnt = -909; - i = 81; - i1 = 255; - j = 74; - convcnt = -788; - vv = 809; - v = 205; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - - /* - * Routine body - */ - n = state->n; - k = state->k; - nwork = state->nwork; - - /* - * Initialize RNG. Deterministic initialization (with fixed - * seed) is required because we need deterministic behavior - * of the entire solver. - */ - hqrndseed(453, 463664, &state->rs, _state); - - /* - * Prepare iteration - * Initialize QNew with random orthogonal matrix (or reuse its previous value). - */ - state->repiterationscount = 0; - rmatrixsetlengthatleast(&state->qcur, nwork, n, _state); - rmatrixsetlengthatleast(&state->qnew, nwork, n, _state); - rmatrixsetlengthatleast(&state->znew, nwork, n, _state); - rvectorsetlengthatleast(&state->wcur, nwork, _state); - rvectorsetlengthatleast(&state->wprev, nwork, _state); - rvectorsetlengthatleast(&state->wrank, nwork, _state); - rmatrixsetlengthatleast(&state->x, n, nwork, _state); - rmatrixsetlengthatleast(&state->ax, n, nwork, _state); - rmatrixsetlengthatleast(&state->rq, n, k, _state); - rvectorsetlengthatleast(&state->rw, k, _state); - rmatrixsetlengthatleast(&state->rz, nwork, k, _state); - rmatrixsetlengthatleast(&state->r, nwork, nwork, _state); - for(i=0; i<=nwork-1; i++) - { - state->wprev.ptr.p_double[i] = -1.0; - } - if( !state->usewarmstart||state->firstcall ) - { - - /* - * Use Q0 (either no warm start request, or warm start was - * requested by user - but it is first call). - * - */ - if( state->firstcall ) - { - - /* - * First call, generate Q0 - */ - for(i=0; i<=nwork-1; i++) - { - for(j=0; j<=n-1; j++) - { - state->znew.ptr.pp_double[i][j] = hqrnduniformr(&state->rs, _state)-0.5; - } - } - rmatrixlq(&state->znew, nwork, n, &state->tau, _state); - rmatrixlqunpackq(&state->znew, nwork, n, &state->tau, nwork, &state->q0, _state); - state->firstcall = ae_false; - } - rmatrixcopy(nwork, n, &state->q0, 0, 0, &state->qnew, 0, 0, _state); - } - - /* - * Start iteration - */ - state->repiterationscount = 0; - convcnt = 0; -lbl_1: - if( !((state->maxits==0||state->repiterationscountmaxits)&&convcntqnew, 0, 0, &state->qcur, 0, 0, _state); - rmatrixtranspose(nwork, n, &state->qcur, 0, 0, &state->x, 0, 0, _state); - evd_clearrfields(state, _state); - state->requesttype = 0; - state->requestsize = nwork; - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - - /* - * Perform Rayleigh-Ritz step to estimate convergence of diagonal eigenvalues - */ - if( ae_fp_greater(state->eps,(double)(0)) ) - { - ae_assert(state->matrixtype==0, "integrity check failed", _state); - rmatrixsetlengthatleast(&state->r, nwork, nwork, _state); - rmatrixgemm(nwork, nwork, n, 1.0, &state->qcur, 0, 0, 0, &state->ax, 0, 0, 0, 0.0, &state->r, 0, 0, _state); - if( !smatrixevd(&state->r, nwork, 0, ae_true, &state->wcur, &state->dummy, _state) ) - { - ae_assert(ae_false, "EigSubspace: direct eigensolver failed to converge", _state); - } - for(j=0; j<=nwork-1; j++) - { - state->wrank.ptr.p_double[j] = ae_fabs(state->wcur.ptr.p_double[j], _state); - } - rankxuntied(&state->wrank, nwork, &state->buf, _state); - v = (double)(0); - vv = (double)(0); - for(j=0; j<=nwork-1; j++) - { - if( ae_fp_greater_eq(state->wrank.ptr.p_double[j],(double)(nwork-k)) ) - { - v = ae_maxreal(v, ae_fabs(state->wcur.ptr.p_double[j]-state->wprev.ptr.p_double[j], _state), _state); - vv = ae_maxreal(vv, ae_fabs(state->wcur.ptr.p_double[j], _state), _state); - } - } - if( ae_fp_eq(vv,(double)(0)) ) - { - vv = (double)(1); - } - if( ae_fp_less_eq(v,state->eps*vv) ) - { - inc(&convcnt, _state); - } - else - { - convcnt = 0; - } - for(j=0; j<=nwork-1; j++) - { - state->wprev.ptr.p_double[j] = state->wcur.ptr.p_double[j]; - } - } - - /* - * QR renormalization and update of QNew - */ - rmatrixtranspose(n, nwork, &state->ax, 0, 0, &state->znew, 0, 0, _state); - rmatrixlq(&state->znew, nwork, n, &state->tau, _state); - rmatrixlqunpackq(&state->znew, nwork, n, &state->tau, nwork, &state->qnew, _state); - - /* - * Update iteration index - */ - state->repiterationscount = state->repiterationscount+1; - goto lbl_1; -lbl_2: - - /* - * Perform Rayleigh-Ritz step: find true eigenpairs in NWork-dimensional - * subspace. - */ - ae_assert(state->matrixtype==0, "integrity check failed", _state); - ae_assert(state->eigenvectorsneeded==1, "Assertion failed", _state); - rmatrixgemm(nwork, nwork, n, 1.0, &state->qcur, 0, 0, 0, &state->ax, 0, 0, 0, 0.0, &state->r, 0, 0, _state); - if( !smatrixevd(&state->r, nwork, 1, ae_true, &state->tw, &state->tz, _state) ) - { - ae_assert(ae_false, "EigSubspace: direct eigensolver failed to converge", _state); - } - - /* - * Reorder eigenpairs according to their absolute magnitude, select - * K top ones. This reordering algorithm is very inefficient and has - * O(NWork*K) running time, but it is still faster than other parts - * of the solver, so we may use it. - * - * Then, we transform RZ to RQ (full N-dimensional representation). - * After this part is done, RW and RQ contain solution. - */ - for(j=0; j<=nwork-1; j++) - { - state->wrank.ptr.p_double[j] = ae_fabs(state->tw.ptr.p_double[j], _state); - } - rankxuntied(&state->wrank, nwork, &state->buf, _state); - cnt = 0; - for(i=nwork-1; i>=nwork-k; i--) - { - for(i1=0; i1<=nwork-1; i1++) - { - if( ae_fp_eq(state->wrank.ptr.p_double[i1],(double)(i)) ) - { - ae_assert(cntrw.ptr.p_double[cnt] = state->tw.ptr.p_double[i1]; - for(j=0; j<=nwork-1; j++) - { - state->rz.ptr.pp_double[j][cnt] = state->tz.ptr.pp_double[j][i1]; - } - cnt = cnt+1; - } - } - } - ae_assert(cnt==k, "EigSubspace: integrity check failed", _state); - rmatrixgemm(n, k, nwork, 1.0, &state->qcur, 0, 0, 1, &state->rz, 0, 0, 0, 0.0, &state->rq, 0, 0, _state); - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = n; - state->rstate.ia.ptr.p_int[1] = nwork; - state->rstate.ia.ptr.p_int[2] = k; - state->rstate.ia.ptr.p_int[3] = cnt; - state->rstate.ia.ptr.p_int[4] = i; - state->rstate.ia.ptr.p_int[5] = i1; - state->rstate.ia.ptr.p_int[6] = j; - state->rstate.ia.ptr.p_int[7] = convcnt; - state->rstate.ra.ptr.p_double[0] = vv; - state->rstate.ra.ptr.p_double[1] = v; - return result; -} - - -/************************************************************************* -Finding the eigenvalues and eigenvectors of a symmetric matrix - -The algorithm finds eigen pairs of a symmetric matrix by reducing it to -tridiagonal form and using the QL/QR algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - symmetric matrix which is given by its upper or lower - triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - IsUpper - storage format. - -Output parameters: - D - eigenvalues in ascending order. - Array whose index ranges within [0..N-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains the eigenvectors. - Array whose indexes range within [0..N-1, 0..N-1]. - The eigenvectors are stored in the matrix columns. - -Result: - True, if the algorithm has converged. - False, if the algorithm hasn't converged (rare case). - - -- ALGLIB -- - Copyright 2005-2008 by Bochkanov Sergey -*************************************************************************/ -ae_bool smatrixevd(/* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t zneeded, - ae_bool isupper, - /* Real */ ae_vector* d, - /* Real */ ae_matrix* z, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_vector tau; - ae_vector e; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&tau, 0, sizeof(tau)); - memset(&e, 0, sizeof(e)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_vector_clear(d); - ae_matrix_clear(z); - ae_vector_init(&tau, 0, DT_REAL, _state, ae_true); - ae_vector_init(&e, 0, DT_REAL, _state, ae_true); - - ae_assert(zneeded==0||zneeded==1, "SMatrixEVD: incorrect ZNeeded", _state); - smatrixtd(a, n, isupper, &tau, d, &e, _state); - if( zneeded==1 ) - { - smatrixtdunpackq(a, n, isupper, &tau, z, _state); - } - result = smatrixtdevd(d, &e, n, zneeded, z, _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Subroutine for finding the eigenvalues (and eigenvectors) of a symmetric -matrix in a given half open interval (A, B] by using a bisection and -inverse iteration - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - symmetric matrix which is given by its upper or lower - triangular part. Array [0..N-1, 0..N-1]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - IsUpperA - storage format of matrix A. - B1, B2 - half open interval (B1, B2] to search eigenvalues in. - -Output parameters: - M - number of eigenvalues found in a given half-interval (M>=0). - W - array of the eigenvalues found. - Array whose index ranges within [0..M-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains eigenvectors. - Array whose indexes range within [0..N-1, 0..M-1]. - The eigenvectors are stored in the matrix columns. - -Result: - True, if successful. M contains the number of eigenvalues in the given - half-interval (could be equal to 0), W contains the eigenvalues, - Z contains the eigenvectors (if needed). - - False, if the bisection method subroutine wasn't able to find the - eigenvalues in the given interval or if the inverse iteration subroutine - wasn't able to find all the corresponding eigenvectors. - In that case, the eigenvalues and eigenvectors are not returned, - M is equal to 0. - - -- ALGLIB -- - Copyright 07.01.2006 by Bochkanov Sergey -*************************************************************************/ -ae_bool smatrixevdr(/* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t zneeded, - ae_bool isupper, - double b1, - double b2, - ae_int_t* m, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* z, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_vector tau; - ae_vector e; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&tau, 0, sizeof(tau)); - memset(&e, 0, sizeof(e)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - *m = 0; - ae_vector_clear(w); - ae_matrix_clear(z); - ae_vector_init(&tau, 0, DT_REAL, _state, ae_true); - ae_vector_init(&e, 0, DT_REAL, _state, ae_true); - - ae_assert(zneeded==0||zneeded==1, "SMatrixTDEVDR: incorrect ZNeeded", _state); - smatrixtd(a, n, isupper, &tau, w, &e, _state); - if( zneeded==1 ) - { - smatrixtdunpackq(a, n, isupper, &tau, z, _state); - } - result = smatrixtdevdr(w, &e, n, zneeded, b1, b2, m, z, _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Subroutine for finding the eigenvalues and eigenvectors of a symmetric -matrix with given indexes by using bisection and inverse iteration methods. - -Input parameters: - A - symmetric matrix which is given by its upper or lower - triangular part. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - IsUpperA - storage format of matrix A. - I1, I2 - index interval for searching (from I1 to I2). - 0 <= I1 <= I2 <= N-1. - -Output parameters: - W - array of the eigenvalues found. - Array whose index ranges within [0..I2-I1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains eigenvectors. - Array whose indexes range within [0..N-1, 0..I2-I1]. - In that case, the eigenvectors are stored in the matrix columns. - -Result: - True, if successful. W contains the eigenvalues, Z contains the - eigenvectors (if needed). - - False, if the bisection method subroutine wasn't able to find the - eigenvalues in the given interval or if the inverse iteration subroutine - wasn't able to find all the corresponding eigenvectors. - In that case, the eigenvalues and eigenvectors are not returned. - - -- ALGLIB -- - Copyright 07.01.2006 by Bochkanov Sergey -*************************************************************************/ -ae_bool smatrixevdi(/* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t zneeded, - ae_bool isupper, - ae_int_t i1, - ae_int_t i2, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* z, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_vector tau; - ae_vector e; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&tau, 0, sizeof(tau)); - memset(&e, 0, sizeof(e)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_vector_clear(w); - ae_matrix_clear(z); - ae_vector_init(&tau, 0, DT_REAL, _state, ae_true); - ae_vector_init(&e, 0, DT_REAL, _state, ae_true); - - ae_assert(zneeded==0||zneeded==1, "SMatrixEVDI: incorrect ZNeeded", _state); - smatrixtd(a, n, isupper, &tau, w, &e, _state); - if( zneeded==1 ) - { - smatrixtdunpackq(a, n, isupper, &tau, z, _state); - } - result = smatrixtdevdi(w, &e, n, zneeded, i1, i2, z, _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Finding the eigenvalues and eigenvectors of a Hermitian matrix - -The algorithm finds eigen pairs of a Hermitian matrix by reducing it to -real tridiagonal form and using the QL/QR algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - Hermitian matrix which is given by its upper or lower - triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - storage format. - ZNeeded - flag controlling whether the eigenvectors are needed or - not. If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - -Output parameters: - D - eigenvalues in ascending order. - Array whose index ranges within [0..N-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains the eigenvectors. - Array whose indexes range within [0..N-1, 0..N-1]. - The eigenvectors are stored in the matrix columns. - -Result: - True, if the algorithm has converged. - False, if the algorithm hasn't converged (rare case). - -Note: - eigenvectors of Hermitian matrix are defined up to multiplication by - a complex number L, such that |L|=1. - - -- ALGLIB -- - Copyright 2005, 23 March 2007 by Bochkanov Sergey -*************************************************************************/ -ae_bool hmatrixevd(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_int_t zneeded, - ae_bool isupper, - /* Real */ ae_vector* d, - /* Complex */ ae_matrix* z, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_vector tau; - ae_vector e; - ae_matrix t; - ae_matrix qz; - ae_matrix q; - ae_int_t i; - ae_int_t j; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&tau, 0, sizeof(tau)); - memset(&e, 0, sizeof(e)); - memset(&t, 0, sizeof(t)); - memset(&qz, 0, sizeof(qz)); - memset(&q, 0, sizeof(q)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_vector_clear(d); - ae_matrix_clear(z); - ae_vector_init(&tau, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&e, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&t, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&qz, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&q, 0, 0, DT_COMPLEX, _state, ae_true); - - ae_assert(zneeded==0||zneeded==1, "HermitianEVD: incorrect ZNeeded", _state); - - /* - * Reduce to tridiagonal form - */ - hmatrixtd(a, n, isupper, &tau, d, &e, _state); - if( zneeded==1 ) - { - hmatrixtdunpackq(a, n, isupper, &tau, &q, _state); - zneeded = 2; - } - - /* - * TDEVD - */ - result = smatrixtdevd(d, &e, n, zneeded, &t, _state); - - /* - * Eigenvectors are needed - * Calculate Z = Q*T = Re(Q)*T + i*Im(Q)*T - */ - if( result&&zneeded!=0 ) - { - ae_matrix_set_length(z, n, n, _state); - ae_matrix_set_length(&qz, n, 2*n, _state); - - /* - * Calculate Re(Q)*T - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - qz.ptr.pp_double[i][j] = q.ptr.pp_complex[i][j].x; - } - } - rmatrixgemm(n, n, n, 1.0, &qz, 0, 0, 0, &t, 0, 0, 0, 0.0, &qz, 0, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - z->ptr.pp_complex[i][j].x = qz.ptr.pp_double[i][n+j]; - } - } - - /* - * Calculate Im(Q)*T - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - qz.ptr.pp_double[i][j] = q.ptr.pp_complex[i][j].y; - } - } - rmatrixgemm(n, n, n, 1.0, &qz, 0, 0, 0, &t, 0, 0, 0, 0.0, &qz, 0, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - z->ptr.pp_complex[i][j].y = qz.ptr.pp_double[i][n+j]; - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Subroutine for finding the eigenvalues (and eigenvectors) of a Hermitian -matrix in a given half-interval (A, B] by using a bisection and inverse -iteration - -Input parameters: - A - Hermitian matrix which is given by its upper or lower - triangular part. Array whose indexes range within - [0..N-1, 0..N-1]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or - not. If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - IsUpperA - storage format of matrix A. - B1, B2 - half-interval (B1, B2] to search eigenvalues in. - -Output parameters: - M - number of eigenvalues found in a given half-interval, M>=0 - W - array of the eigenvalues found. - Array whose index ranges within [0..M-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains eigenvectors. - Array whose indexes range within [0..N-1, 0..M-1]. - The eigenvectors are stored in the matrix columns. - -Result: - True, if successful. M contains the number of eigenvalues in the given - half-interval (could be equal to 0), W contains the eigenvalues, - Z contains the eigenvectors (if needed). - - False, if the bisection method subroutine wasn't able to find the - eigenvalues in the given interval or if the inverse iteration - subroutine wasn't able to find all the corresponding eigenvectors. - In that case, the eigenvalues and eigenvectors are not returned, M is - equal to 0. - -Note: - eigen vectors of Hermitian matrix are defined up to multiplication by - a complex number L, such as |L|=1. - - -- ALGLIB -- - Copyright 07.01.2006, 24.03.2007 by Bochkanov Sergey. -*************************************************************************/ -ae_bool hmatrixevdr(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_int_t zneeded, - ae_bool isupper, - double b1, - double b2, - ae_int_t* m, - /* Real */ ae_vector* w, - /* Complex */ ae_matrix* z, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_matrix q; - ae_matrix t; - ae_vector tau; - ae_vector e; - ae_vector work; - ae_int_t i; - ae_int_t k; - double v; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&q, 0, sizeof(q)); - memset(&t, 0, sizeof(t)); - memset(&tau, 0, sizeof(tau)); - memset(&e, 0, sizeof(e)); - memset(&work, 0, sizeof(work)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - *m = 0; - ae_vector_clear(w); - ae_matrix_clear(z); - ae_matrix_init(&q, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&t, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tau, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&e, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - - ae_assert(zneeded==0||zneeded==1, "HermitianEigenValuesAndVectorsInInterval: incorrect ZNeeded", _state); - - /* - * Reduce to tridiagonal form - */ - hmatrixtd(a, n, isupper, &tau, w, &e, _state); - if( zneeded==1 ) - { - hmatrixtdunpackq(a, n, isupper, &tau, &q, _state); - zneeded = 2; - } - - /* - * Bisection and inverse iteration - */ - result = smatrixtdevdr(w, &e, n, zneeded, b1, b2, m, &t, _state); - - /* - * Eigenvectors are needed - * Calculate Z = Q*T = Re(Q)*T + i*Im(Q)*T - */ - if( (result&&zneeded!=0)&&*m!=0 ) - { - ae_vector_set_length(&work, *m-1+1, _state); - ae_matrix_set_length(z, n-1+1, *m-1+1, _state); - for(i=0; i<=n-1; i++) - { - - /* - * Calculate real part - */ - for(k=0; k<=*m-1; k++) - { - work.ptr.p_double[k] = (double)(0); - } - for(k=0; k<=n-1; k++) - { - v = q.ptr.pp_complex[i][k].x; - ae_v_addd(&work.ptr.p_double[0], 1, &t.ptr.pp_double[k][0], 1, ae_v_len(0,*m-1), v); - } - for(k=0; k<=*m-1; k++) - { - z->ptr.pp_complex[i][k].x = work.ptr.p_double[k]; - } - - /* - * Calculate imaginary part - */ - for(k=0; k<=*m-1; k++) - { - work.ptr.p_double[k] = (double)(0); - } - for(k=0; k<=n-1; k++) - { - v = q.ptr.pp_complex[i][k].y; - ae_v_addd(&work.ptr.p_double[0], 1, &t.ptr.pp_double[k][0], 1, ae_v_len(0,*m-1), v); - } - for(k=0; k<=*m-1; k++) - { - z->ptr.pp_complex[i][k].y = work.ptr.p_double[k]; - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Subroutine for finding the eigenvalues and eigenvectors of a Hermitian -matrix with given indexes by using bisection and inverse iteration methods - -Input parameters: - A - Hermitian matrix which is given by its upper or lower - triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or - not. If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - IsUpperA - storage format of matrix A. - I1, I2 - index interval for searching (from I1 to I2). - 0 <= I1 <= I2 <= N-1. - -Output parameters: - W - array of the eigenvalues found. - Array whose index ranges within [0..I2-I1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains eigenvectors. - Array whose indexes range within [0..N-1, 0..I2-I1]. - In that case, the eigenvectors are stored in the matrix - columns. - -Result: - True, if successful. W contains the eigenvalues, Z contains the - eigenvectors (if needed). - - False, if the bisection method subroutine wasn't able to find the - eigenvalues in the given interval or if the inverse iteration - subroutine wasn't able to find all the corresponding eigenvectors. - In that case, the eigenvalues and eigenvectors are not returned. - -Note: - eigen vectors of Hermitian matrix are defined up to multiplication by - a complex number L, such as |L|=1. - - -- ALGLIB -- - Copyright 07.01.2006, 24.03.2007 by Bochkanov Sergey. -*************************************************************************/ -ae_bool hmatrixevdi(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_int_t zneeded, - ae_bool isupper, - ae_int_t i1, - ae_int_t i2, - /* Real */ ae_vector* w, - /* Complex */ ae_matrix* z, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_matrix q; - ae_matrix t; - ae_vector tau; - ae_vector e; - ae_vector work; - ae_int_t i; - ae_int_t k; - double v; - ae_int_t m; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&q, 0, sizeof(q)); - memset(&t, 0, sizeof(t)); - memset(&tau, 0, sizeof(tau)); - memset(&e, 0, sizeof(e)); - memset(&work, 0, sizeof(work)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_vector_clear(w); - ae_matrix_clear(z); - ae_matrix_init(&q, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&t, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tau, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&e, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - - ae_assert(zneeded==0||zneeded==1, "HermitianEigenValuesAndVectorsByIndexes: incorrect ZNeeded", _state); - - /* - * Reduce to tridiagonal form - */ - hmatrixtd(a, n, isupper, &tau, w, &e, _state); - if( zneeded==1 ) - { - hmatrixtdunpackq(a, n, isupper, &tau, &q, _state); - zneeded = 2; - } - - /* - * Bisection and inverse iteration - */ - result = smatrixtdevdi(w, &e, n, zneeded, i1, i2, &t, _state); - - /* - * Eigenvectors are needed - * Calculate Z = Q*T = Re(Q)*T + i*Im(Q)*T - */ - m = i2-i1+1; - if( result&&zneeded!=0 ) - { - ae_vector_set_length(&work, m-1+1, _state); - ae_matrix_set_length(z, n-1+1, m-1+1, _state); - for(i=0; i<=n-1; i++) - { - - /* - * Calculate real part - */ - for(k=0; k<=m-1; k++) - { - work.ptr.p_double[k] = (double)(0); - } - for(k=0; k<=n-1; k++) - { - v = q.ptr.pp_complex[i][k].x; - ae_v_addd(&work.ptr.p_double[0], 1, &t.ptr.pp_double[k][0], 1, ae_v_len(0,m-1), v); - } - for(k=0; k<=m-1; k++) - { - z->ptr.pp_complex[i][k].x = work.ptr.p_double[k]; - } - - /* - * Calculate imaginary part - */ - for(k=0; k<=m-1; k++) - { - work.ptr.p_double[k] = (double)(0); - } - for(k=0; k<=n-1; k++) - { - v = q.ptr.pp_complex[i][k].y; - ae_v_addd(&work.ptr.p_double[0], 1, &t.ptr.pp_double[k][0], 1, ae_v_len(0,m-1), v); - } - for(k=0; k<=m-1; k++) - { - z->ptr.pp_complex[i][k].y = work.ptr.p_double[k]; - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Finding the eigenvalues and eigenvectors of a tridiagonal symmetric matrix - -The algorithm finds the eigen pairs of a tridiagonal symmetric matrix by -using an QL/QR algorithm with implicit shifts. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - D - the main diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-1]. - E - the secondary diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-2]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not needed; - * 1, the eigenvectors of a tridiagonal matrix - are multiplied by the square matrix Z. It is used if the - tridiagonal matrix is obtained by the similarity - transformation of a symmetric matrix; - * 2, the eigenvectors of a tridiagonal matrix replace the - square matrix Z; - * 3, matrix Z contains the first row of the eigenvectors - matrix. - Z - if ZNeeded=1, Z contains the square matrix by which the - eigenvectors are multiplied. - Array whose indexes range within [0..N-1, 0..N-1]. - -Output parameters: - D - eigenvalues in ascending order. - Array whose index ranges within [0..N-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains the product of a given matrix (from the left) - and the eigenvectors matrix (from the right); - * 2, Z contains the eigenvectors. - * 3, Z contains the first row of the eigenvectors matrix. - If ZNeeded<3, Z is the array whose indexes range within [0..N-1, 0..N-1]. - In that case, the eigenvectors are stored in the matrix columns. - If ZNeeded=3, Z is the array whose indexes range within [0..0, 0..N-1]. - -Result: - True, if the algorithm has converged. - False, if the algorithm hasn't converged. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994 -*************************************************************************/ -ae_bool smatrixtdevd(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_int_t zneeded, - /* Real */ ae_matrix* z, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _e; - ae_vector d1; - ae_vector e1; - ae_vector ex; - ae_matrix z1; - ae_int_t i; - ae_int_t j; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_e, 0, sizeof(_e)); - memset(&d1, 0, sizeof(d1)); - memset(&e1, 0, sizeof(e1)); - memset(&ex, 0, sizeof(ex)); - memset(&z1, 0, sizeof(z1)); - ae_vector_init_copy(&_e, e, _state, ae_true); - e = &_e; - ae_vector_init(&d1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&e1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ex, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z1, 0, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=1, "SMatrixTDEVD: N<=0", _state); - ae_assert(zneeded>=0&&zneeded<=3, "SMatrixTDEVD: incorrect ZNeeded", _state); - result = ae_false; - - /* - * Preprocess Z: make ZNeeded equal to 0, 1 or 3. - * Ensure that memory for Z is allocated. - */ - if( zneeded==2 ) - { - - /* - * Load identity to Z - */ - rmatrixsetlengthatleast(z, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - z->ptr.pp_double[i][j] = 0.0; - } - z->ptr.pp_double[i][i] = 1.0; - } - zneeded = 1; - } - if( zneeded==3 ) - { - - /* - * Allocate memory - */ - rmatrixsetlengthatleast(z, 1, n, _state); - } - - /* - * Try to solve problem with MKL - */ - ae_vector_set_length(&ex, n, _state); - for(i=0; i<=n-2; i++) - { - ex.ptr.p_double[i] = e->ptr.p_double[i]; - } - if( smatrixtdevdmkl(d, &ex, n, zneeded, z, &result, _state) ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Prepare 1-based task - */ - ae_vector_set_length(&d1, n+1, _state); - ae_vector_set_length(&e1, n+1, _state); - ae_v_move(&d1.ptr.p_double[1], 1, &d->ptr.p_double[0], 1, ae_v_len(1,n)); - if( n>1 ) - { - ae_v_move(&e1.ptr.p_double[1], 1, &e->ptr.p_double[0], 1, ae_v_len(1,n-1)); - } - if( zneeded==1 ) - { - ae_matrix_set_length(&z1, n+1, n+1, _state); - for(i=1; i<=n; i++) - { - ae_v_move(&z1.ptr.pp_double[i][1], 1, &z->ptr.pp_double[i-1][0], 1, ae_v_len(1,n)); - } - } - - /* - * Solve 1-based task - */ - result = evd_tridiagonalevd(&d1, &e1, n, zneeded, &z1, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Convert back to 0-based result - */ - ae_v_move(&d->ptr.p_double[0], 1, &d1.ptr.p_double[1], 1, ae_v_len(0,n-1)); - if( zneeded!=0 ) - { - if( zneeded==1 ) - { - for(i=1; i<=n; i++) - { - ae_v_move(&z->ptr.pp_double[i-1][0], 1, &z1.ptr.pp_double[i][1], 1, ae_v_len(0,n-1)); - } - ae_frame_leave(_state); - return result; - } - if( zneeded==2 ) - { - ae_matrix_set_length(z, n-1+1, n-1+1, _state); - for(i=1; i<=n; i++) - { - ae_v_move(&z->ptr.pp_double[i-1][0], 1, &z1.ptr.pp_double[i][1], 1, ae_v_len(0,n-1)); - } - ae_frame_leave(_state); - return result; - } - if( zneeded==3 ) - { - ae_matrix_set_length(z, 0+1, n-1+1, _state); - ae_v_move(&z->ptr.pp_double[0][0], 1, &z1.ptr.pp_double[1][1], 1, ae_v_len(0,n-1)); - ae_frame_leave(_state); - return result; - } - ae_assert(ae_false, "SMatrixTDEVD: Incorrect ZNeeded!", _state); - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Subroutine for finding the tridiagonal matrix eigenvalues/vectors in a -given half-interval (A, B] by using bisection and inverse iteration. - -Input parameters: - D - the main diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-1]. - E - the secondary diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-2]. - N - size of matrix, N>=0. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not needed; - * 1, the eigenvectors of a tridiagonal matrix are multiplied - by the square matrix Z. It is used if the tridiagonal - matrix is obtained by the similarity transformation - of a symmetric matrix. - * 2, the eigenvectors of a tridiagonal matrix replace matrix Z. - A, B - half-interval (A, B] to search eigenvalues in. - Z - if ZNeeded is equal to: - * 0, Z isn't used and remains unchanged; - * 1, Z contains the square matrix (array whose indexes range - within [0..N-1, 0..N-1]) which reduces the given symmetric - matrix to tridiagonal form; - * 2, Z isn't used (but changed on the exit). - -Output parameters: - D - array of the eigenvalues found. - Array whose index ranges within [0..M-1]. - M - number of eigenvalues found in the given half-interval (M>=0). - Z - if ZNeeded is equal to: - * 0, doesn't contain any information; - * 1, contains the product of a given NxN matrix Z (from the - left) and NxM matrix of the eigenvectors found (from the - right). Array whose indexes range within [0..N-1, 0..M-1]. - * 2, contains the matrix of the eigenvectors found. - Array whose indexes range within [0..N-1, 0..M-1]. - -Result: - - True, if successful. In that case, M contains the number of eigenvalues - in the given half-interval (could be equal to 0), D contains the eigenvalues, - Z contains the eigenvectors (if needed). - It should be noted that the subroutine changes the size of arrays D and Z. - - False, if the bisection method subroutine wasn't able to find the - eigenvalues in the given interval or if the inverse iteration subroutine - wasn't able to find all the corresponding eigenvectors. In that case, - the eigenvalues and eigenvectors are not returned, M is equal to 0. - - -- ALGLIB -- - Copyright 31.03.2008 by Bochkanov Sergey -*************************************************************************/ -ae_bool smatrixtdevdr(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_int_t zneeded, - double a, - double b, - ae_int_t* m, - /* Real */ ae_matrix* z, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t errorcode; - ae_int_t nsplit; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t cr; - ae_vector iblock; - ae_vector isplit; - ae_vector ifail; - ae_vector d1; - ae_vector e1; - ae_vector w; - ae_matrix z2; - ae_matrix z3; - double v; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&iblock, 0, sizeof(iblock)); - memset(&isplit, 0, sizeof(isplit)); - memset(&ifail, 0, sizeof(ifail)); - memset(&d1, 0, sizeof(d1)); - memset(&e1, 0, sizeof(e1)); - memset(&w, 0, sizeof(w)); - memset(&z2, 0, sizeof(z2)); - memset(&z3, 0, sizeof(z3)); - *m = 0; - ae_vector_init(&iblock, 0, DT_INT, _state, ae_true); - ae_vector_init(&isplit, 0, DT_INT, _state, ae_true); - ae_vector_init(&ifail, 0, DT_INT, _state, ae_true); - ae_vector_init(&d1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&e1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z3, 0, 0, DT_REAL, _state, ae_true); - - ae_assert(zneeded>=0&&zneeded<=2, "SMatrixTDEVDR: incorrect ZNeeded!", _state); - - /* - * Special cases - */ - if( ae_fp_less_eq(b,a) ) - { - *m = 0; - result = ae_true; - ae_frame_leave(_state); - return result; - } - if( n<=0 ) - { - *m = 0; - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Copy D,E to D1, E1 - */ - ae_vector_set_length(&d1, n+1, _state); - ae_v_move(&d1.ptr.p_double[1], 1, &d->ptr.p_double[0], 1, ae_v_len(1,n)); - if( n>1 ) - { - ae_vector_set_length(&e1, n-1+1, _state); - ae_v_move(&e1.ptr.p_double[1], 1, &e->ptr.p_double[0], 1, ae_v_len(1,n-1)); - } - - /* - * No eigen vectors - */ - if( zneeded==0 ) - { - result = evd_internalbisectioneigenvalues(&d1, &e1, n, 2, 1, a, b, 0, 0, (double)(-1), &w, m, &nsplit, &iblock, &isplit, &errorcode, _state); - if( !result||*m==0 ) - { - *m = 0; - ae_frame_leave(_state); - return result; - } - ae_vector_set_length(d, *m-1+1, _state); - ae_v_move(&d->ptr.p_double[0], 1, &w.ptr.p_double[1], 1, ae_v_len(0,*m-1)); - ae_frame_leave(_state); - return result; - } - - /* - * Eigen vectors are multiplied by Z - */ - if( zneeded==1 ) - { - - /* - * Find eigen pairs - */ - result = evd_internalbisectioneigenvalues(&d1, &e1, n, 2, 2, a, b, 0, 0, (double)(-1), &w, m, &nsplit, &iblock, &isplit, &errorcode, _state); - if( !result||*m==0 ) - { - *m = 0; - ae_frame_leave(_state); - return result; - } - evd_internaldstein(n, &d1, &e1, *m, &w, &iblock, &isplit, &z2, &ifail, &cr, _state); - if( cr!=0 ) - { - *m = 0; - result = ae_false; - ae_frame_leave(_state); - return result; - } - - /* - * Sort eigen values and vectors - */ - for(i=1; i<=*m; i++) - { - k = i; - for(j=i; j<=*m; j++) - { - if( ae_fp_less(w.ptr.p_double[j],w.ptr.p_double[k]) ) - { - k = j; - } - } - v = w.ptr.p_double[i]; - w.ptr.p_double[i] = w.ptr.p_double[k]; - w.ptr.p_double[k] = v; - for(j=1; j<=n; j++) - { - v = z2.ptr.pp_double[j][i]; - z2.ptr.pp_double[j][i] = z2.ptr.pp_double[j][k]; - z2.ptr.pp_double[j][k] = v; - } - } - - /* - * Transform Z2 and overwrite Z - */ - ae_matrix_set_length(&z3, *m+1, n+1, _state); - for(i=1; i<=*m; i++) - { - ae_v_move(&z3.ptr.pp_double[i][1], 1, &z2.ptr.pp_double[1][i], z2.stride, ae_v_len(1,n)); - } - for(i=1; i<=n; i++) - { - for(j=1; j<=*m; j++) - { - v = ae_v_dotproduct(&z->ptr.pp_double[i-1][0], 1, &z3.ptr.pp_double[j][1], 1, ae_v_len(0,n-1)); - z2.ptr.pp_double[i][j] = v; - } - } - ae_matrix_set_length(z, n-1+1, *m-1+1, _state); - for(i=1; i<=*m; i++) - { - ae_v_move(&z->ptr.pp_double[0][i-1], z->stride, &z2.ptr.pp_double[1][i], z2.stride, ae_v_len(0,n-1)); - } - - /* - * Store W - */ - ae_vector_set_length(d, *m-1+1, _state); - for(i=1; i<=*m; i++) - { - d->ptr.p_double[i-1] = w.ptr.p_double[i]; - } - ae_frame_leave(_state); - return result; - } - - /* - * Eigen vectors are stored in Z - */ - if( zneeded==2 ) - { - - /* - * Find eigen pairs - */ - result = evd_internalbisectioneigenvalues(&d1, &e1, n, 2, 2, a, b, 0, 0, (double)(-1), &w, m, &nsplit, &iblock, &isplit, &errorcode, _state); - if( !result||*m==0 ) - { - *m = 0; - ae_frame_leave(_state); - return result; - } - evd_internaldstein(n, &d1, &e1, *m, &w, &iblock, &isplit, &z2, &ifail, &cr, _state); - if( cr!=0 ) - { - *m = 0; - result = ae_false; - ae_frame_leave(_state); - return result; - } - - /* - * Sort eigen values and vectors - */ - for(i=1; i<=*m; i++) - { - k = i; - for(j=i; j<=*m; j++) - { - if( ae_fp_less(w.ptr.p_double[j],w.ptr.p_double[k]) ) - { - k = j; - } - } - v = w.ptr.p_double[i]; - w.ptr.p_double[i] = w.ptr.p_double[k]; - w.ptr.p_double[k] = v; - for(j=1; j<=n; j++) - { - v = z2.ptr.pp_double[j][i]; - z2.ptr.pp_double[j][i] = z2.ptr.pp_double[j][k]; - z2.ptr.pp_double[j][k] = v; - } - } - - /* - * Store W - */ - ae_vector_set_length(d, *m-1+1, _state); - for(i=1; i<=*m; i++) - { - d->ptr.p_double[i-1] = w.ptr.p_double[i]; - } - ae_matrix_set_length(z, n-1+1, *m-1+1, _state); - for(i=1; i<=*m; i++) - { - ae_v_move(&z->ptr.pp_double[0][i-1], z->stride, &z2.ptr.pp_double[1][i], z2.stride, ae_v_len(0,n-1)); - } - ae_frame_leave(_state); - return result; - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Subroutine for finding tridiagonal matrix eigenvalues/vectors with given -indexes (in ascending order) by using the bisection and inverse iteraion. - -Input parameters: - D - the main diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-1]. - E - the secondary diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-2]. - N - size of matrix. N>=0. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not needed; - * 1, the eigenvectors of a tridiagonal matrix are multiplied - by the square matrix Z. It is used if the - tridiagonal matrix is obtained by the similarity transformation - of a symmetric matrix. - * 2, the eigenvectors of a tridiagonal matrix replace - matrix Z. - I1, I2 - index interval for searching (from I1 to I2). - 0 <= I1 <= I2 <= N-1. - Z - if ZNeeded is equal to: - * 0, Z isn't used and remains unchanged; - * 1, Z contains the square matrix (array whose indexes range within [0..N-1, 0..N-1]) - which reduces the given symmetric matrix to tridiagonal form; - * 2, Z isn't used (but changed on the exit). - -Output parameters: - D - array of the eigenvalues found. - Array whose index ranges within [0..I2-I1]. - Z - if ZNeeded is equal to: - * 0, doesn't contain any information; - * 1, contains the product of a given NxN matrix Z (from the left) and - Nx(I2-I1) matrix of the eigenvectors found (from the right). - Array whose indexes range within [0..N-1, 0..I2-I1]. - * 2, contains the matrix of the eigenvalues found. - Array whose indexes range within [0..N-1, 0..I2-I1]. - - -Result: - - True, if successful. In that case, D contains the eigenvalues, - Z contains the eigenvectors (if needed). - It should be noted that the subroutine changes the size of arrays D and Z. - - False, if the bisection method subroutine wasn't able to find the eigenvalues - in the given interval or if the inverse iteration subroutine wasn't able - to find all the corresponding eigenvectors. In that case, the eigenvalues - and eigenvectors are not returned. - - -- ALGLIB -- - Copyright 25.12.2005 by Bochkanov Sergey -*************************************************************************/ -ae_bool smatrixtdevdi(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_int_t zneeded, - ae_int_t i1, - ae_int_t i2, - /* Real */ ae_matrix* z, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t errorcode; - ae_int_t nsplit; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t m; - ae_int_t cr; - ae_vector iblock; - ae_vector isplit; - ae_vector ifail; - ae_vector w; - ae_vector d1; - ae_vector e1; - ae_matrix z2; - ae_matrix z3; - double v; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&iblock, 0, sizeof(iblock)); - memset(&isplit, 0, sizeof(isplit)); - memset(&ifail, 0, sizeof(ifail)); - memset(&w, 0, sizeof(w)); - memset(&d1, 0, sizeof(d1)); - memset(&e1, 0, sizeof(e1)); - memset(&z2, 0, sizeof(z2)); - memset(&z3, 0, sizeof(z3)); - ae_vector_init(&iblock, 0, DT_INT, _state, ae_true); - ae_vector_init(&isplit, 0, DT_INT, _state, ae_true); - ae_vector_init(&ifail, 0, DT_INT, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&e1, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z3, 0, 0, DT_REAL, _state, ae_true); - - ae_assert((0<=i1&&i1<=i2)&&i2ptr.p_double[0], 1, ae_v_len(1,n)); - if( n>1 ) - { - ae_vector_set_length(&e1, n-1+1, _state); - ae_v_move(&e1.ptr.p_double[1], 1, &e->ptr.p_double[0], 1, ae_v_len(1,n-1)); - } - - /* - * No eigen vectors - */ - if( zneeded==0 ) - { - result = evd_internalbisectioneigenvalues(&d1, &e1, n, 3, 1, (double)(0), (double)(0), i1+1, i2+1, (double)(-1), &w, &m, &nsplit, &iblock, &isplit, &errorcode, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - if( m!=i2-i1+1 ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - ae_vector_set_length(d, m-1+1, _state); - for(i=1; i<=m; i++) - { - d->ptr.p_double[i-1] = w.ptr.p_double[i]; - } - ae_frame_leave(_state); - return result; - } - - /* - * Eigen vectors are multiplied by Z - */ - if( zneeded==1 ) - { - - /* - * Find eigen pairs - */ - result = evd_internalbisectioneigenvalues(&d1, &e1, n, 3, 2, (double)(0), (double)(0), i1+1, i2+1, (double)(-1), &w, &m, &nsplit, &iblock, &isplit, &errorcode, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - if( m!=i2-i1+1 ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - evd_internaldstein(n, &d1, &e1, m, &w, &iblock, &isplit, &z2, &ifail, &cr, _state); - if( cr!=0 ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - - /* - * Sort eigen values and vectors - */ - for(i=1; i<=m; i++) - { - k = i; - for(j=i; j<=m; j++) - { - if( ae_fp_less(w.ptr.p_double[j],w.ptr.p_double[k]) ) - { - k = j; - } - } - v = w.ptr.p_double[i]; - w.ptr.p_double[i] = w.ptr.p_double[k]; - w.ptr.p_double[k] = v; - for(j=1; j<=n; j++) - { - v = z2.ptr.pp_double[j][i]; - z2.ptr.pp_double[j][i] = z2.ptr.pp_double[j][k]; - z2.ptr.pp_double[j][k] = v; - } - } - - /* - * Transform Z2 and overwrite Z - */ - ae_matrix_set_length(&z3, m+1, n+1, _state); - for(i=1; i<=m; i++) - { - ae_v_move(&z3.ptr.pp_double[i][1], 1, &z2.ptr.pp_double[1][i], z2.stride, ae_v_len(1,n)); - } - for(i=1; i<=n; i++) - { - for(j=1; j<=m; j++) - { - v = ae_v_dotproduct(&z->ptr.pp_double[i-1][0], 1, &z3.ptr.pp_double[j][1], 1, ae_v_len(0,n-1)); - z2.ptr.pp_double[i][j] = v; - } - } - ae_matrix_set_length(z, n-1+1, m-1+1, _state); - for(i=1; i<=m; i++) - { - ae_v_move(&z->ptr.pp_double[0][i-1], z->stride, &z2.ptr.pp_double[1][i], z2.stride, ae_v_len(0,n-1)); - } - - /* - * Store W - */ - ae_vector_set_length(d, m-1+1, _state); - for(i=1; i<=m; i++) - { - d->ptr.p_double[i-1] = w.ptr.p_double[i]; - } - ae_frame_leave(_state); - return result; - } - - /* - * Eigen vectors are stored in Z - */ - if( zneeded==2 ) - { - - /* - * Find eigen pairs - */ - result = evd_internalbisectioneigenvalues(&d1, &e1, n, 3, 2, (double)(0), (double)(0), i1+1, i2+1, (double)(-1), &w, &m, &nsplit, &iblock, &isplit, &errorcode, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - if( m!=i2-i1+1 ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - evd_internaldstein(n, &d1, &e1, m, &w, &iblock, &isplit, &z2, &ifail, &cr, _state); - if( cr!=0 ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - - /* - * Sort eigen values and vectors - */ - for(i=1; i<=m; i++) - { - k = i; - for(j=i; j<=m; j++) - { - if( ae_fp_less(w.ptr.p_double[j],w.ptr.p_double[k]) ) - { - k = j; - } - } - v = w.ptr.p_double[i]; - w.ptr.p_double[i] = w.ptr.p_double[k]; - w.ptr.p_double[k] = v; - for(j=1; j<=n; j++) - { - v = z2.ptr.pp_double[j][i]; - z2.ptr.pp_double[j][i] = z2.ptr.pp_double[j][k]; - z2.ptr.pp_double[j][k] = v; - } - } - - /* - * Store Z - */ - ae_matrix_set_length(z, n-1+1, m-1+1, _state); - for(i=1; i<=m; i++) - { - ae_v_move(&z->ptr.pp_double[0][i-1], z->stride, &z2.ptr.pp_double[1][i], z2.stride, ae_v_len(0,n-1)); - } - - /* - * Store W - */ - ae_vector_set_length(d, m-1+1, _state); - for(i=1; i<=m; i++) - { - d->ptr.p_double[i-1] = w.ptr.p_double[i]; - } - ae_frame_leave(_state); - return result; - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Finding eigenvalues and eigenvectors of a general (unsymmetric) matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -The algorithm finds eigenvalues and eigenvectors of a general matrix by -using the QR algorithm with multiple shifts. The algorithm can find -eigenvalues and both left and right eigenvectors. - -The right eigenvector is a vector x such that A*x = w*x, and the left -eigenvector is a vector y such that y'*A = w*y' (here y' implies a complex -conjugate transposition of vector y). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - VNeeded - flag controlling whether eigenvectors are needed or not. - If VNeeded is equal to: - * 0, eigenvectors are not returned; - * 1, right eigenvectors are returned; - * 2, left eigenvectors are returned; - * 3, both left and right eigenvectors are returned. - -Output parameters: - WR - real parts of eigenvalues. - Array whose index ranges within [0..N-1]. - WR - imaginary parts of eigenvalues. - Array whose index ranges within [0..N-1]. - VL, VR - arrays of left and right eigenvectors (if they are needed). - If WI[i]=0, the respective eigenvalue is a real number, - and it corresponds to the column number I of matrices VL/VR. - If WI[i]>0, we have a pair of complex conjugate numbers with - positive and negative imaginary parts: - the first eigenvalue WR[i] + sqrt(-1)*WI[i]; - the second eigenvalue WR[i+1] + sqrt(-1)*WI[i+1]; - WI[i]>0 - WI[i+1] = -WI[i] < 0 - In that case, the eigenvector corresponding to the first - eigenvalue is located in i and i+1 columns of matrices - VL/VR (the column number i contains the real part, and the - column number i+1 contains the imaginary part), and the vector - corresponding to the second eigenvalue is a complex conjugate to - the first vector. - Arrays whose indexes range within [0..N-1, 0..N-1]. - -Result: - True, if the algorithm has converged. - False, if the algorithm has not converged. - -Note 1: - Some users may ask the following question: what if WI[N-1]>0? - WI[N] must contain an eigenvalue which is complex conjugate to the - N-th eigenvalue, but the array has only size N? - The answer is as follows: such a situation cannot occur because the - algorithm finds a pairs of eigenvalues, therefore, if WI[i]>0, I is - strictly less than N-1. - -Note 2: - The algorithm performance depends on the value of the internal parameter - NS of the InternalSchurDecomposition subroutine which defines the number - of shifts in the QR algorithm (similarly to the block width in block-matrix - algorithms of linear algebra). If you require maximum performance - on your machine, it is recommended to adjust this parameter manually. - - -See also the InternalTREVC subroutine. - -The algorithm is based on the LAPACK 3.0 library. -*************************************************************************/ -ae_bool rmatrixevd(/* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t vneeded, - /* Real */ ae_vector* wr, - /* Real */ ae_vector* wi, - /* Real */ ae_matrix* vl, - /* Real */ ae_matrix* vr, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_matrix a1; - ae_matrix vl1; - ae_matrix vr1; - ae_matrix s1; - ae_matrix s; - ae_matrix dummy; - ae_vector wr1; - ae_vector wi1; - ae_vector tau; - ae_int_t i; - ae_int_t info; - ae_vector sel1; - ae_int_t m1; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&a1, 0, sizeof(a1)); - memset(&vl1, 0, sizeof(vl1)); - memset(&vr1, 0, sizeof(vr1)); - memset(&s1, 0, sizeof(s1)); - memset(&s, 0, sizeof(s)); - memset(&dummy, 0, sizeof(dummy)); - memset(&wr1, 0, sizeof(wr1)); - memset(&wi1, 0, sizeof(wi1)); - memset(&tau, 0, sizeof(tau)); - memset(&sel1, 0, sizeof(sel1)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_vector_clear(wr); - ae_vector_clear(wi); - ae_matrix_clear(vl); - ae_matrix_clear(vr); - ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vl1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vr1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&s1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&s, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&dummy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wr1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wi1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tau, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sel1, 0, DT_BOOL, _state, ae_true); - - ae_assert(vneeded>=0&&vneeded<=3, "RMatrixEVD: incorrect VNeeded!", _state); - if( vneeded==0 ) - { - - /* - * Eigen values only - */ - rmatrixhessenberg(a, n, &tau, _state); - rmatrixinternalschurdecomposition(a, n, 0, 0, wr, wi, &dummy, &info, _state); - result = info==0; - ae_frame_leave(_state); - return result; - } - - /* - * Eigen values and vectors - */ - rmatrixhessenberg(a, n, &tau, _state); - rmatrixhessenbergunpackq(a, n, &tau, &s, _state); - rmatrixinternalschurdecomposition(a, n, 1, 1, wr, wi, &s, &info, _state); - result = info==0; - if( !result ) - { - ae_frame_leave(_state); - return result; - } - if( vneeded==1||vneeded==3 ) - { - ae_matrix_set_length(vr, n, n, _state); - for(i=0; i<=n-1; i++) - { - ae_v_move(&vr->ptr.pp_double[i][0], 1, &s.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - } - } - if( vneeded==2||vneeded==3 ) - { - ae_matrix_set_length(vl, n, n, _state); - for(i=0; i<=n-1; i++) - { - ae_v_move(&vl->ptr.pp_double[i][0], 1, &s.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - } - } - evd_rmatrixinternaltrevc(a, n, vneeded, 1, &sel1, vl, vr, &m1, &info, _state); - result = info==0; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Clears request fileds (to be sure that we don't forgot to clear something) -*************************************************************************/ -static void evd_clearrfields(eigsubspacestate* state, ae_state *_state) -{ - - - state->requesttype = -1; - state->requestsize = -1; -} - - -static ae_bool evd_tridiagonalevd(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_int_t zneeded, - /* Real */ ae_matrix* z, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _e; - ae_int_t maxit; - ae_int_t i; - ae_int_t ii; - ae_int_t iscale; - ae_int_t j; - ae_int_t jtot; - ae_int_t k; - ae_int_t t; - ae_int_t l; - ae_int_t l1; - ae_int_t lend; - ae_int_t lendm1; - ae_int_t lendp1; - ae_int_t lendsv; - ae_int_t lm1; - ae_int_t lsv; - ae_int_t m; - ae_int_t mm1; - ae_int_t nm1; - ae_int_t nmaxit; - ae_int_t tmpint; - double anorm; - double b; - double c; - double eps; - double eps2; - double f; - double g; - double p; - double r; - double rt1; - double rt2; - double s; - double safmax; - double safmin; - double ssfmax; - double ssfmin; - double tst; - double tmp; - ae_vector work1; - ae_vector work2; - ae_vector workc; - ae_vector works; - ae_vector wtemp; - ae_bool gotoflag; - ae_int_t zrows; - ae_bool wastranspose; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_e, 0, sizeof(_e)); - memset(&work1, 0, sizeof(work1)); - memset(&work2, 0, sizeof(work2)); - memset(&workc, 0, sizeof(workc)); - memset(&works, 0, sizeof(works)); - memset(&wtemp, 0, sizeof(wtemp)); - ae_vector_init_copy(&_e, e, _state, ae_true); - e = &_e; - ae_vector_init(&work1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&workc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&works, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wtemp, 0, DT_REAL, _state, ae_true); - - ae_assert(zneeded>=0&&zneeded<=3, "TridiagonalEVD: Incorrent ZNeeded", _state); - - /* - * Quick return if possible - */ - if( zneeded<0||zneeded>3 ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - result = ae_true; - if( n==0 ) - { - ae_frame_leave(_state); - return result; - } - if( n==1 ) - { - if( zneeded==2||zneeded==3 ) - { - ae_matrix_set_length(z, 1+1, 1+1, _state); - z->ptr.pp_double[1][1] = (double)(1); - } - ae_frame_leave(_state); - return result; - } - maxit = 30; - - /* - * Initialize arrays - */ - ae_vector_set_length(&wtemp, n+1, _state); - ae_vector_set_length(&work1, n-1+1, _state); - ae_vector_set_length(&work2, n-1+1, _state); - ae_vector_set_length(&workc, n+1, _state); - ae_vector_set_length(&works, n+1, _state); - - /* - * Determine the unit roundoff and over/underflow thresholds. - */ - eps = ae_machineepsilon; - eps2 = ae_sqr(eps, _state); - safmin = ae_minrealnumber; - safmax = ae_maxrealnumber; - ssfmax = ae_sqrt(safmax, _state)/3; - ssfmin = ae_sqrt(safmin, _state)/eps2; - - /* - * Prepare Z - * - * Here we are using transposition to get rid of column operations - * - */ - wastranspose = ae_false; - zrows = 0; - if( zneeded==1 ) - { - zrows = n; - } - if( zneeded==2 ) - { - zrows = n; - } - if( zneeded==3 ) - { - zrows = 1; - } - if( zneeded==1 ) - { - wastranspose = ae_true; - inplacetranspose(z, 1, n, 1, n, &wtemp, _state); - } - if( zneeded==2 ) - { - wastranspose = ae_true; - ae_matrix_set_length(z, n+1, n+1, _state); - for(i=1; i<=n; i++) - { - for(j=1; j<=n; j++) - { - if( i==j ) - { - z->ptr.pp_double[i][j] = (double)(1); - } - else - { - z->ptr.pp_double[i][j] = (double)(0); - } - } - } - } - if( zneeded==3 ) - { - wastranspose = ae_false; - ae_matrix_set_length(z, 1+1, n+1, _state); - for(j=1; j<=n; j++) - { - if( j==1 ) - { - z->ptr.pp_double[1][j] = (double)(1); - } - else - { - z->ptr.pp_double[1][j] = (double)(0); - } - } - } - nmaxit = n*maxit; - jtot = 0; - - /* - * Determine where the matrix splits and choose QL or QR iteration - * for each block, according to whether top or bottom diagonal - * element is smaller. - */ - l1 = 1; - nm1 = n-1; - for(;;) - { - if( l1>n ) - { - break; - } - if( l1>1 ) - { - e->ptr.p_double[l1-1] = (double)(0); - } - gotoflag = ae_false; - m = l1; - if( l1<=nm1 ) - { - for(m=l1; m<=nm1; m++) - { - tst = ae_fabs(e->ptr.p_double[m], _state); - if( ae_fp_eq(tst,(double)(0)) ) - { - gotoflag = ae_true; - break; - } - if( ae_fp_less_eq(tst,ae_sqrt(ae_fabs(d->ptr.p_double[m], _state), _state)*ae_sqrt(ae_fabs(d->ptr.p_double[m+1], _state), _state)*eps) ) - { - e->ptr.p_double[m] = (double)(0); - gotoflag = ae_true; - break; - } - } - } - if( !gotoflag ) - { - m = n; - } - - /* - * label 30: - */ - l = l1; - lsv = l; - lend = m; - lendsv = lend; - l1 = m+1; - if( lend==l ) - { - continue; - } - - /* - * Scale submatrix in rows and columns L to LEND - */ - if( l==lend ) - { - anorm = ae_fabs(d->ptr.p_double[l], _state); - } - else - { - anorm = ae_maxreal(ae_fabs(d->ptr.p_double[l], _state)+ae_fabs(e->ptr.p_double[l], _state), ae_fabs(e->ptr.p_double[lend-1], _state)+ae_fabs(d->ptr.p_double[lend], _state), _state); - for(i=l+1; i<=lend-1; i++) - { - anorm = ae_maxreal(anorm, ae_fabs(d->ptr.p_double[i], _state)+ae_fabs(e->ptr.p_double[i], _state)+ae_fabs(e->ptr.p_double[i-1], _state), _state); - } - } - iscale = 0; - if( ae_fp_eq(anorm,(double)(0)) ) - { - continue; - } - if( ae_fp_greater(anorm,ssfmax) ) - { - iscale = 1; - tmp = ssfmax/anorm; - tmpint = lend-1; - ae_v_muld(&d->ptr.p_double[l], 1, ae_v_len(l,lend), tmp); - ae_v_muld(&e->ptr.p_double[l], 1, ae_v_len(l,tmpint), tmp); - } - if( ae_fp_less(anorm,ssfmin) ) - { - iscale = 2; - tmp = ssfmin/anorm; - tmpint = lend-1; - ae_v_muld(&d->ptr.p_double[l], 1, ae_v_len(l,lend), tmp); - ae_v_muld(&e->ptr.p_double[l], 1, ae_v_len(l,tmpint), tmp); - } - - /* - * Choose between QL and QR iteration - */ - if( ae_fp_less(ae_fabs(d->ptr.p_double[lend], _state),ae_fabs(d->ptr.p_double[l], _state)) ) - { - lend = lsv; - l = lendsv; - } - if( lend>l ) - { - - /* - * QL Iteration - * - * Look for small subdiagonal element. - */ - for(;;) - { - gotoflag = ae_false; - if( l!=lend ) - { - lendm1 = lend-1; - for(m=l; m<=lendm1; m++) - { - tst = ae_sqr(ae_fabs(e->ptr.p_double[m], _state), _state); - if( ae_fp_less_eq(tst,eps2*ae_fabs(d->ptr.p_double[m], _state)*ae_fabs(d->ptr.p_double[m+1], _state)+safmin) ) - { - gotoflag = ae_true; - break; - } - } - } - if( !gotoflag ) - { - m = lend; - } - if( mptr.p_double[m] = (double)(0); - } - p = d->ptr.p_double[l]; - if( m!=l ) - { - - /* - * If remaining matrix is 2-by-2, use DLAE2 or SLAEV2 - * to compute its eigensystem. - */ - if( m==l+1 ) - { - if( zneeded>0 ) - { - evd_tdevdev2(d->ptr.p_double[l], e->ptr.p_double[l], d->ptr.p_double[l+1], &rt1, &rt2, &c, &s, _state); - work1.ptr.p_double[l] = c; - work2.ptr.p_double[l] = s; - workc.ptr.p_double[1] = work1.ptr.p_double[l]; - works.ptr.p_double[1] = work2.ptr.p_double[l]; - if( !wastranspose ) - { - applyrotationsfromtheright(ae_false, 1, zrows, l, l+1, &workc, &works, z, &wtemp, _state); - } - else - { - applyrotationsfromtheleft(ae_false, l, l+1, 1, zrows, &workc, &works, z, &wtemp, _state); - } - } - else - { - evd_tdevde2(d->ptr.p_double[l], e->ptr.p_double[l], d->ptr.p_double[l+1], &rt1, &rt2, _state); - } - d->ptr.p_double[l] = rt1; - d->ptr.p_double[l+1] = rt2; - e->ptr.p_double[l] = (double)(0); - l = l+2; - if( l<=lend ) - { - continue; - } - - /* - * GOTO 140 - */ - break; - } - if( jtot==nmaxit ) - { - - /* - * GOTO 140 - */ - break; - } - jtot = jtot+1; - - /* - * Form shift. - */ - g = (d->ptr.p_double[l+1]-p)/(2*e->ptr.p_double[l]); - r = evd_tdevdpythag(g, (double)(1), _state); - g = d->ptr.p_double[m]-p+e->ptr.p_double[l]/(g+evd_tdevdextsign(r, g, _state)); - s = (double)(1); - c = (double)(1); - p = (double)(0); - - /* - * Inner loop - */ - mm1 = m-1; - for(i=mm1; i>=l; i--) - { - f = s*e->ptr.p_double[i]; - b = c*e->ptr.p_double[i]; - generaterotation(g, f, &c, &s, &r, _state); - if( i!=m-1 ) - { - e->ptr.p_double[i+1] = r; - } - g = d->ptr.p_double[i+1]-p; - r = (d->ptr.p_double[i]-g)*s+2*c*b; - p = s*r; - d->ptr.p_double[i+1] = g+p; - g = c*r-b; - - /* - * If eigenvectors are desired, then save rotations. - */ - if( zneeded>0 ) - { - work1.ptr.p_double[i] = c; - work2.ptr.p_double[i] = -s; - } - } - - /* - * If eigenvectors are desired, then apply saved rotations. - */ - if( zneeded>0 ) - { - for(i=l; i<=m-1; i++) - { - workc.ptr.p_double[i-l+1] = work1.ptr.p_double[i]; - works.ptr.p_double[i-l+1] = work2.ptr.p_double[i]; - } - if( !wastranspose ) - { - applyrotationsfromtheright(ae_false, 1, zrows, l, m, &workc, &works, z, &wtemp, _state); - } - else - { - applyrotationsfromtheleft(ae_false, l, m, 1, zrows, &workc, &works, z, &wtemp, _state); - } - } - d->ptr.p_double[l] = d->ptr.p_double[l]-p; - e->ptr.p_double[l] = g; - continue; - } - - /* - * Eigenvalue found. - */ - d->ptr.p_double[l] = p; - l = l+1; - if( l<=lend ) - { - continue; - } - break; - } - } - else - { - - /* - * QR Iteration - * - * Look for small superdiagonal element. - */ - for(;;) - { - gotoflag = ae_false; - if( l!=lend ) - { - lendp1 = lend+1; - for(m=l; m>=lendp1; m--) - { - tst = ae_sqr(ae_fabs(e->ptr.p_double[m-1], _state), _state); - if( ae_fp_less_eq(tst,eps2*ae_fabs(d->ptr.p_double[m], _state)*ae_fabs(d->ptr.p_double[m-1], _state)+safmin) ) - { - gotoflag = ae_true; - break; - } - } - } - if( !gotoflag ) - { - m = lend; - } - if( m>lend ) - { - e->ptr.p_double[m-1] = (double)(0); - } - p = d->ptr.p_double[l]; - if( m!=l ) - { - - /* - * If remaining matrix is 2-by-2, use DLAE2 or SLAEV2 - * to compute its eigensystem. - */ - if( m==l-1 ) - { - if( zneeded>0 ) - { - evd_tdevdev2(d->ptr.p_double[l-1], e->ptr.p_double[l-1], d->ptr.p_double[l], &rt1, &rt2, &c, &s, _state); - work1.ptr.p_double[m] = c; - work2.ptr.p_double[m] = s; - workc.ptr.p_double[1] = c; - works.ptr.p_double[1] = s; - if( !wastranspose ) - { - applyrotationsfromtheright(ae_true, 1, zrows, l-1, l, &workc, &works, z, &wtemp, _state); - } - else - { - applyrotationsfromtheleft(ae_true, l-1, l, 1, zrows, &workc, &works, z, &wtemp, _state); - } - } - else - { - evd_tdevde2(d->ptr.p_double[l-1], e->ptr.p_double[l-1], d->ptr.p_double[l], &rt1, &rt2, _state); - } - d->ptr.p_double[l-1] = rt1; - d->ptr.p_double[l] = rt2; - e->ptr.p_double[l-1] = (double)(0); - l = l-2; - if( l>=lend ) - { - continue; - } - break; - } - if( jtot==nmaxit ) - { - break; - } - jtot = jtot+1; - - /* - * Form shift. - */ - g = (d->ptr.p_double[l-1]-p)/(2*e->ptr.p_double[l-1]); - r = evd_tdevdpythag(g, (double)(1), _state); - g = d->ptr.p_double[m]-p+e->ptr.p_double[l-1]/(g+evd_tdevdextsign(r, g, _state)); - s = (double)(1); - c = (double)(1); - p = (double)(0); - - /* - * Inner loop - */ - lm1 = l-1; - for(i=m; i<=lm1; i++) - { - f = s*e->ptr.p_double[i]; - b = c*e->ptr.p_double[i]; - generaterotation(g, f, &c, &s, &r, _state); - if( i!=m ) - { - e->ptr.p_double[i-1] = r; - } - g = d->ptr.p_double[i]-p; - r = (d->ptr.p_double[i+1]-g)*s+2*c*b; - p = s*r; - d->ptr.p_double[i] = g+p; - g = c*r-b; - - /* - * If eigenvectors are desired, then save rotations. - */ - if( zneeded>0 ) - { - work1.ptr.p_double[i] = c; - work2.ptr.p_double[i] = s; - } - } - - /* - * If eigenvectors are desired, then apply saved rotations. - */ - if( zneeded>0 ) - { - for(i=m; i<=l-1; i++) - { - workc.ptr.p_double[i-m+1] = work1.ptr.p_double[i]; - works.ptr.p_double[i-m+1] = work2.ptr.p_double[i]; - } - if( !wastranspose ) - { - applyrotationsfromtheright(ae_true, 1, zrows, m, l, &workc, &works, z, &wtemp, _state); - } - else - { - applyrotationsfromtheleft(ae_true, m, l, 1, zrows, &workc, &works, z, &wtemp, _state); - } - } - d->ptr.p_double[l] = d->ptr.p_double[l]-p; - e->ptr.p_double[lm1] = g; - continue; - } - - /* - * Eigenvalue found. - */ - d->ptr.p_double[l] = p; - l = l-1; - if( l>=lend ) - { - continue; - } - break; - } - } - - /* - * Undo scaling if necessary - */ - if( iscale==1 ) - { - tmp = anorm/ssfmax; - tmpint = lendsv-1; - ae_v_muld(&d->ptr.p_double[lsv], 1, ae_v_len(lsv,lendsv), tmp); - ae_v_muld(&e->ptr.p_double[lsv], 1, ae_v_len(lsv,tmpint), tmp); - } - if( iscale==2 ) - { - tmp = anorm/ssfmin; - tmpint = lendsv-1; - ae_v_muld(&d->ptr.p_double[lsv], 1, ae_v_len(lsv,lendsv), tmp); - ae_v_muld(&e->ptr.p_double[lsv], 1, ae_v_len(lsv,tmpint), tmp); - } - - /* - * Check for no convergence to an eigenvalue after a total - * of N*MAXIT iterations. - */ - if( jtot>=nmaxit ) - { - result = ae_false; - if( wastranspose ) - { - inplacetranspose(z, 1, n, 1, n, &wtemp, _state); - } - ae_frame_leave(_state); - return result; - } - } - - /* - * Order eigenvalues and eigenvectors. - */ - if( zneeded==0 ) - { - - /* - * Sort - */ - if( n==1 ) - { - ae_frame_leave(_state); - return result; - } - if( n==2 ) - { - if( ae_fp_greater(d->ptr.p_double[1],d->ptr.p_double[2]) ) - { - tmp = d->ptr.p_double[1]; - d->ptr.p_double[1] = d->ptr.p_double[2]; - d->ptr.p_double[2] = tmp; - } - ae_frame_leave(_state); - return result; - } - i = 2; - do - { - t = i; - while(t!=1) - { - k = t/2; - if( ae_fp_greater_eq(d->ptr.p_double[k],d->ptr.p_double[t]) ) - { - t = 1; - } - else - { - tmp = d->ptr.p_double[k]; - d->ptr.p_double[k] = d->ptr.p_double[t]; - d->ptr.p_double[t] = tmp; - t = k; - } - } - i = i+1; - } - while(i<=n); - i = n-1; - do - { - tmp = d->ptr.p_double[i+1]; - d->ptr.p_double[i+1] = d->ptr.p_double[1]; - d->ptr.p_double[1] = tmp; - t = 1; - while(t!=0) - { - k = 2*t; - if( k>i ) - { - t = 0; - } - else - { - if( kptr.p_double[k+1],d->ptr.p_double[k]) ) - { - k = k+1; - } - } - if( ae_fp_greater_eq(d->ptr.p_double[t],d->ptr.p_double[k]) ) - { - t = 0; - } - else - { - tmp = d->ptr.p_double[k]; - d->ptr.p_double[k] = d->ptr.p_double[t]; - d->ptr.p_double[t] = tmp; - t = k; - } - } - } - i = i-1; - } - while(i>=1); - } - else - { - - /* - * Use Selection Sort to minimize swaps of eigenvectors - */ - for(ii=2; ii<=n; ii++) - { - i = ii-1; - k = i; - p = d->ptr.p_double[i]; - for(j=ii; j<=n; j++) - { - if( ae_fp_less(d->ptr.p_double[j],p) ) - { - k = j; - p = d->ptr.p_double[j]; - } - } - if( k!=i ) - { - d->ptr.p_double[k] = d->ptr.p_double[i]; - d->ptr.p_double[i] = p; - if( wastranspose ) - { - ae_v_move(&wtemp.ptr.p_double[1], 1, &z->ptr.pp_double[i][1], 1, ae_v_len(1,n)); - ae_v_move(&z->ptr.pp_double[i][1], 1, &z->ptr.pp_double[k][1], 1, ae_v_len(1,n)); - ae_v_move(&z->ptr.pp_double[k][1], 1, &wtemp.ptr.p_double[1], 1, ae_v_len(1,n)); - } - else - { - ae_v_move(&wtemp.ptr.p_double[1], 1, &z->ptr.pp_double[1][i], z->stride, ae_v_len(1,zrows)); - ae_v_move(&z->ptr.pp_double[1][i], z->stride, &z->ptr.pp_double[1][k], z->stride, ae_v_len(1,zrows)); - ae_v_move(&z->ptr.pp_double[1][k], z->stride, &wtemp.ptr.p_double[1], 1, ae_v_len(1,zrows)); - } - } - } - if( wastranspose ) - { - inplacetranspose(z, 1, n, 1, n, &wtemp, _state); - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -DLAE2 computes the eigenvalues of a 2-by-2 symmetric matrix - [ A B ] - [ B C ]. -On return, RT1 is the eigenvalue of larger absolute value, and RT2 -is the eigenvalue of smaller absolute value. - - -- LAPACK auxiliary routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - October 31, 1992 -*************************************************************************/ -static void evd_tdevde2(double a, - double b, - double c, - double* rt1, - double* rt2, - ae_state *_state) -{ - double ab; - double acmn; - double acmx; - double adf; - double df; - double rt; - double sm; - double tb; - - *rt1 = 0; - *rt2 = 0; - - sm = a+c; - df = a-c; - adf = ae_fabs(df, _state); - tb = b+b; - ab = ae_fabs(tb, _state); - if( ae_fp_greater(ae_fabs(a, _state),ae_fabs(c, _state)) ) - { - acmx = a; - acmn = c; - } - else - { - acmx = c; - acmn = a; - } - if( ae_fp_greater(adf,ab) ) - { - rt = adf*ae_sqrt(1+ae_sqr(ab/adf, _state), _state); - } - else - { - if( ae_fp_less(adf,ab) ) - { - rt = ab*ae_sqrt(1+ae_sqr(adf/ab, _state), _state); - } - else - { - - /* - * Includes case AB=ADF=0 - */ - rt = ab*ae_sqrt((double)(2), _state); - } - } - if( ae_fp_less(sm,(double)(0)) ) - { - *rt1 = 0.5*(sm-rt); - - /* - * Order of execution important. - * To get fully accurate smaller eigenvalue, - * next line needs to be executed in higher precision. - */ - *rt2 = acmx/(*rt1)*acmn-b/(*rt1)*b; - } - else - { - if( ae_fp_greater(sm,(double)(0)) ) - { - *rt1 = 0.5*(sm+rt); - - /* - * Order of execution important. - * To get fully accurate smaller eigenvalue, - * next line needs to be executed in higher precision. - */ - *rt2 = acmx/(*rt1)*acmn-b/(*rt1)*b; - } - else - { - - /* - * Includes case RT1 = RT2 = 0 - */ - *rt1 = 0.5*rt; - *rt2 = -0.5*rt; - } - } -} - - -/************************************************************************* -DLAEV2 computes the eigendecomposition of a 2-by-2 symmetric matrix - - [ A B ] - [ B C ]. - -On return, RT1 is the eigenvalue of larger absolute value, RT2 is the -eigenvalue of smaller absolute value, and (CS1,SN1) is the unit right -eigenvector for RT1, giving the decomposition - - [ CS1 SN1 ] [ A B ] [ CS1 -SN1 ] = [ RT1 0 ] - [-SN1 CS1 ] [ B C ] [ SN1 CS1 ] [ 0 RT2 ]. - - - -- LAPACK auxiliary routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - October 31, 1992 -*************************************************************************/ -static void evd_tdevdev2(double a, - double b, - double c, - double* rt1, - double* rt2, - double* cs1, - double* sn1, - ae_state *_state) -{ - ae_int_t sgn1; - ae_int_t sgn2; - double ab; - double acmn; - double acmx; - double acs; - double adf; - double cs; - double ct; - double df; - double rt; - double sm; - double tb; - double tn; - - *rt1 = 0; - *rt2 = 0; - *cs1 = 0; - *sn1 = 0; - - - /* - * Compute the eigenvalues - */ - sm = a+c; - df = a-c; - adf = ae_fabs(df, _state); - tb = b+b; - ab = ae_fabs(tb, _state); - if( ae_fp_greater(ae_fabs(a, _state),ae_fabs(c, _state)) ) - { - acmx = a; - acmn = c; - } - else - { - acmx = c; - acmn = a; - } - if( ae_fp_greater(adf,ab) ) - { - rt = adf*ae_sqrt(1+ae_sqr(ab/adf, _state), _state); - } - else - { - if( ae_fp_less(adf,ab) ) - { - rt = ab*ae_sqrt(1+ae_sqr(adf/ab, _state), _state); - } - else - { - - /* - * Includes case AB=ADF=0 - */ - rt = ab*ae_sqrt((double)(2), _state); - } - } - if( ae_fp_less(sm,(double)(0)) ) - { - *rt1 = 0.5*(sm-rt); - sgn1 = -1; - - /* - * Order of execution important. - * To get fully accurate smaller eigenvalue, - * next line needs to be executed in higher precision. - */ - *rt2 = acmx/(*rt1)*acmn-b/(*rt1)*b; - } - else - { - if( ae_fp_greater(sm,(double)(0)) ) - { - *rt1 = 0.5*(sm+rt); - sgn1 = 1; - - /* - * Order of execution important. - * To get fully accurate smaller eigenvalue, - * next line needs to be executed in higher precision. - */ - *rt2 = acmx/(*rt1)*acmn-b/(*rt1)*b; - } - else - { - - /* - * Includes case RT1 = RT2 = 0 - */ - *rt1 = 0.5*rt; - *rt2 = -0.5*rt; - sgn1 = 1; - } - } - - /* - * Compute the eigenvector - */ - if( ae_fp_greater_eq(df,(double)(0)) ) - { - cs = df+rt; - sgn2 = 1; - } - else - { - cs = df-rt; - sgn2 = -1; - } - acs = ae_fabs(cs, _state); - if( ae_fp_greater(acs,ab) ) - { - ct = -tb/cs; - *sn1 = 1/ae_sqrt(1+ct*ct, _state); - *cs1 = ct*(*sn1); - } - else - { - if( ae_fp_eq(ab,(double)(0)) ) - { - *cs1 = (double)(1); - *sn1 = (double)(0); - } - else - { - tn = -cs/tb; - *cs1 = 1/ae_sqrt(1+tn*tn, _state); - *sn1 = tn*(*cs1); - } - } - if( sgn1==sgn2 ) - { - tn = *cs1; - *cs1 = -*sn1; - *sn1 = tn; - } -} - - -/************************************************************************* -Internal routine -*************************************************************************/ -static double evd_tdevdpythag(double a, double b, ae_state *_state) -{ - double result; - - - if( ae_fp_less(ae_fabs(a, _state),ae_fabs(b, _state)) ) - { - result = ae_fabs(b, _state)*ae_sqrt(1+ae_sqr(a/b, _state), _state); - } - else - { - result = ae_fabs(a, _state)*ae_sqrt(1+ae_sqr(b/a, _state), _state); - } - return result; -} - - -/************************************************************************* -Internal routine -*************************************************************************/ -static double evd_tdevdextsign(double a, double b, ae_state *_state) -{ - double result; - - - if( ae_fp_greater_eq(b,(double)(0)) ) - { - result = ae_fabs(a, _state); - } - else - { - result = -ae_fabs(a, _state); - } - return result; -} - - -static ae_bool evd_internalbisectioneigenvalues(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_int_t irange, - ae_int_t iorder, - double vl, - double vu, - ae_int_t il, - ae_int_t iu, - double abstol, - /* Real */ ae_vector* w, - ae_int_t* m, - ae_int_t* nsplit, - /* Integer */ ae_vector* iblock, - /* Integer */ ae_vector* isplit, - ae_int_t* errorcode, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _d; - ae_vector _e; - double fudge; - double relfac; - ae_bool ncnvrg; - ae_bool toofew; - ae_int_t ib; - ae_int_t ibegin; - ae_int_t idiscl; - ae_int_t idiscu; - ae_int_t ie; - ae_int_t iend; - ae_int_t iinfo; - ae_int_t im; - ae_int_t iin; - ae_int_t ioff; - ae_int_t iout; - ae_int_t itmax; - ae_int_t iw; - ae_int_t iwoff; - ae_int_t j; - ae_int_t itmp1; - ae_int_t jb; - ae_int_t jdisc; - ae_int_t je; - ae_int_t nwl; - ae_int_t nwu; - double atoli; - double bnorm; - double gl; - double gu; - double pivmin; - double rtoli; - double safemn; - double tmp1; - double tmp2; - double tnorm; - double ulp; - double wkill; - double wl; - double wlu; - double wu; - double wul; - double scalefactor; - double t; - ae_vector idumma; - ae_vector work; - ae_vector iwork; - ae_vector ia1s2; - ae_vector ra1s2; - ae_matrix ra1s2x2; - ae_matrix ia1s2x2; - ae_vector ra1siin; - ae_vector ra2siin; - ae_vector ra3siin; - ae_vector ra4siin; - ae_matrix ra1siinx2; - ae_matrix ia1siinx2; - ae_vector iworkspace; - ae_vector rworkspace; - ae_int_t tmpi; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_d, 0, sizeof(_d)); - memset(&_e, 0, sizeof(_e)); - memset(&idumma, 0, sizeof(idumma)); - memset(&work, 0, sizeof(work)); - memset(&iwork, 0, sizeof(iwork)); - memset(&ia1s2, 0, sizeof(ia1s2)); - memset(&ra1s2, 0, sizeof(ra1s2)); - memset(&ra1s2x2, 0, sizeof(ra1s2x2)); - memset(&ia1s2x2, 0, sizeof(ia1s2x2)); - memset(&ra1siin, 0, sizeof(ra1siin)); - memset(&ra2siin, 0, sizeof(ra2siin)); - memset(&ra3siin, 0, sizeof(ra3siin)); - memset(&ra4siin, 0, sizeof(ra4siin)); - memset(&ra1siinx2, 0, sizeof(ra1siinx2)); - memset(&ia1siinx2, 0, sizeof(ia1siinx2)); - memset(&iworkspace, 0, sizeof(iworkspace)); - memset(&rworkspace, 0, sizeof(rworkspace)); - ae_vector_init_copy(&_d, d, _state, ae_true); - d = &_d; - ae_vector_init_copy(&_e, e, _state, ae_true); - e = &_e; - ae_vector_clear(w); - *m = 0; - *nsplit = 0; - ae_vector_clear(iblock); - ae_vector_clear(isplit); - *errorcode = 0; - ae_vector_init(&idumma, 0, DT_INT, _state, ae_true); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - ae_vector_init(&iwork, 0, DT_INT, _state, ae_true); - ae_vector_init(&ia1s2, 0, DT_INT, _state, ae_true); - ae_vector_init(&ra1s2, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ra1s2x2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ia1s2x2, 0, 0, DT_INT, _state, ae_true); - ae_vector_init(&ra1siin, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ra2siin, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ra3siin, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ra4siin, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ra1siinx2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ia1siinx2, 0, 0, DT_INT, _state, ae_true); - ae_vector_init(&iworkspace, 0, DT_INT, _state, ae_true); - ae_vector_init(&rworkspace, 0, DT_REAL, _state, ae_true); - - - /* - * Quick return if possible - */ - *m = 0; - if( n==0 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Get machine constants - * NB is the minimum vector length for vector bisection, or 0 - * if only scalar is to be done. - */ - fudge = (double)(2); - relfac = (double)(2); - safemn = ae_minrealnumber; - ulp = 2*ae_machineepsilon; - rtoli = ulp*relfac; - ae_vector_set_length(&idumma, 1+1, _state); - ae_vector_set_length(&work, 4*n+1, _state); - ae_vector_set_length(&iwork, 3*n+1, _state); - ae_vector_set_length(w, n+1, _state); - ae_vector_set_length(iblock, n+1, _state); - ae_vector_set_length(isplit, n+1, _state); - ae_vector_set_length(&ia1s2, 2+1, _state); - ae_vector_set_length(&ra1s2, 2+1, _state); - ae_matrix_set_length(&ra1s2x2, 2+1, 2+1, _state); - ae_matrix_set_length(&ia1s2x2, 2+1, 2+1, _state); - ae_vector_set_length(&ra1siin, n+1, _state); - ae_vector_set_length(&ra2siin, n+1, _state); - ae_vector_set_length(&ra3siin, n+1, _state); - ae_vector_set_length(&ra4siin, n+1, _state); - ae_matrix_set_length(&ra1siinx2, n+1, 2+1, _state); - ae_matrix_set_length(&ia1siinx2, n+1, 2+1, _state); - ae_vector_set_length(&iworkspace, n+1, _state); - ae_vector_set_length(&rworkspace, n+1, _state); - - /* - * these initializers are not really necessary, - * but without them compiler complains about uninitialized locals - */ - wlu = (double)(0); - wul = (double)(0); - - /* - * Check for Errors - */ - result = ae_false; - *errorcode = 0; - if( irange<=0||irange>=4 ) - { - *errorcode = -4; - } - if( iorder<=0||iorder>=3 ) - { - *errorcode = -5; - } - if( n<0 ) - { - *errorcode = -3; - } - if( irange==2&&ae_fp_greater_eq(vl,vu) ) - { - *errorcode = -6; - } - if( irange==3&&(il<1||il>ae_maxint(1, n, _state)) ) - { - *errorcode = -8; - } - if( irange==3&&(iun) ) - { - *errorcode = -9; - } - if( *errorcode!=0 ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Initialize error flags - */ - ncnvrg = ae_false; - toofew = ae_false; - - /* - * Simplifications: - */ - if( (irange==3&&il==1)&&iu==n ) - { - irange = 1; - } - - /* - * Special Case when N=1 - */ - if( n==1 ) - { - *nsplit = 1; - isplit->ptr.p_int[1] = 1; - if( irange==2&&(ae_fp_greater_eq(vl,d->ptr.p_double[1])||ae_fp_less(vu,d->ptr.p_double[1])) ) - { - *m = 0; - } - else - { - w->ptr.p_double[1] = d->ptr.p_double[1]; - iblock->ptr.p_int[1] = 1; - *m = 1; - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Scaling - */ - t = ae_fabs(d->ptr.p_double[n], _state); - for(j=1; j<=n-1; j++) - { - t = ae_maxreal(t, ae_fabs(d->ptr.p_double[j], _state), _state); - t = ae_maxreal(t, ae_fabs(e->ptr.p_double[j], _state), _state); - } - scalefactor = (double)(1); - if( ae_fp_neq(t,(double)(0)) ) - { - if( ae_fp_greater(t,ae_sqrt(ae_sqrt(ae_minrealnumber, _state), _state)*ae_sqrt(ae_maxrealnumber, _state)) ) - { - scalefactor = t; - } - if( ae_fp_less(t,ae_sqrt(ae_sqrt(ae_maxrealnumber, _state), _state)*ae_sqrt(ae_minrealnumber, _state)) ) - { - scalefactor = t; - } - for(j=1; j<=n-1; j++) - { - d->ptr.p_double[j] = d->ptr.p_double[j]/scalefactor; - e->ptr.p_double[j] = e->ptr.p_double[j]/scalefactor; - } - d->ptr.p_double[n] = d->ptr.p_double[n]/scalefactor; - } - - /* - * Compute Splitting Points - */ - *nsplit = 1; - work.ptr.p_double[n] = (double)(0); - pivmin = (double)(1); - for(j=2; j<=n; j++) - { - tmp1 = ae_sqr(e->ptr.p_double[j-1], _state); - if( ae_fp_greater(ae_fabs(d->ptr.p_double[j]*d->ptr.p_double[j-1], _state)*ae_sqr(ulp, _state)+safemn,tmp1) ) - { - isplit->ptr.p_int[*nsplit] = j-1; - *nsplit = *nsplit+1; - work.ptr.p_double[j-1] = (double)(0); - } - else - { - work.ptr.p_double[j-1] = tmp1; - pivmin = ae_maxreal(pivmin, tmp1, _state); - } - } - isplit->ptr.p_int[*nsplit] = n; - pivmin = pivmin*safemn; - - /* - * Compute Interval and ATOLI - */ - if( irange==3 ) - { - - /* - * RANGE='I': Compute the interval containing eigenvalues - * IL through IU. - * - * Compute Gershgorin interval for entire (split) matrix - * and use it as the initial interval - */ - gu = d->ptr.p_double[1]; - gl = d->ptr.p_double[1]; - tmp1 = (double)(0); - for(j=1; j<=n-1; j++) - { - tmp2 = ae_sqrt(work.ptr.p_double[j], _state); - gu = ae_maxreal(gu, d->ptr.p_double[j]+tmp1+tmp2, _state); - gl = ae_minreal(gl, d->ptr.p_double[j]-tmp1-tmp2, _state); - tmp1 = tmp2; - } - gu = ae_maxreal(gu, d->ptr.p_double[n]+tmp1, _state); - gl = ae_minreal(gl, d->ptr.p_double[n]-tmp1, _state); - tnorm = ae_maxreal(ae_fabs(gl, _state), ae_fabs(gu, _state), _state); - gl = gl-fudge*tnorm*ulp*n-fudge*2*pivmin; - gu = gu+fudge*tnorm*ulp*n+fudge*pivmin; - - /* - * Compute Iteration parameters - */ - itmax = ae_iceil((ae_log(tnorm+pivmin, _state)-ae_log(pivmin, _state))/ae_log((double)(2), _state), _state)+2; - if( ae_fp_less_eq(abstol,(double)(0)) ) - { - atoli = ulp*tnorm; - } - else - { - atoli = abstol; - } - work.ptr.p_double[n+1] = gl; - work.ptr.p_double[n+2] = gl; - work.ptr.p_double[n+3] = gu; - work.ptr.p_double[n+4] = gu; - work.ptr.p_double[n+5] = gl; - work.ptr.p_double[n+6] = gu; - iwork.ptr.p_int[1] = -1; - iwork.ptr.p_int[2] = -1; - iwork.ptr.p_int[3] = n+1; - iwork.ptr.p_int[4] = n+1; - iwork.ptr.p_int[5] = il-1; - iwork.ptr.p_int[6] = iu; - - /* - * Calling DLAEBZ - * - * DLAEBZ( 3, ITMAX, N, 2, 2, NB, ATOLI, RTOLI, PIVMIN, D, E, - * WORK, IWORK( 5 ), WORK( N+1 ), WORK( N+5 ), IOUT, - * IWORK, W, IBLOCK, IINFO ) - */ - ia1s2.ptr.p_int[1] = iwork.ptr.p_int[5]; - ia1s2.ptr.p_int[2] = iwork.ptr.p_int[6]; - ra1s2.ptr.p_double[1] = work.ptr.p_double[n+5]; - ra1s2.ptr.p_double[2] = work.ptr.p_double[n+6]; - ra1s2x2.ptr.pp_double[1][1] = work.ptr.p_double[n+1]; - ra1s2x2.ptr.pp_double[2][1] = work.ptr.p_double[n+2]; - ra1s2x2.ptr.pp_double[1][2] = work.ptr.p_double[n+3]; - ra1s2x2.ptr.pp_double[2][2] = work.ptr.p_double[n+4]; - ia1s2x2.ptr.pp_int[1][1] = iwork.ptr.p_int[1]; - ia1s2x2.ptr.pp_int[2][1] = iwork.ptr.p_int[2]; - ia1s2x2.ptr.pp_int[1][2] = iwork.ptr.p_int[3]; - ia1s2x2.ptr.pp_int[2][2] = iwork.ptr.p_int[4]; - evd_internaldlaebz(3, itmax, n, 2, 2, atoli, rtoli, pivmin, d, e, &work, &ia1s2, &ra1s2x2, &ra1s2, &iout, &ia1s2x2, w, iblock, &iinfo, _state); - iwork.ptr.p_int[5] = ia1s2.ptr.p_int[1]; - iwork.ptr.p_int[6] = ia1s2.ptr.p_int[2]; - work.ptr.p_double[n+5] = ra1s2.ptr.p_double[1]; - work.ptr.p_double[n+6] = ra1s2.ptr.p_double[2]; - work.ptr.p_double[n+1] = ra1s2x2.ptr.pp_double[1][1]; - work.ptr.p_double[n+2] = ra1s2x2.ptr.pp_double[2][1]; - work.ptr.p_double[n+3] = ra1s2x2.ptr.pp_double[1][2]; - work.ptr.p_double[n+4] = ra1s2x2.ptr.pp_double[2][2]; - iwork.ptr.p_int[1] = ia1s2x2.ptr.pp_int[1][1]; - iwork.ptr.p_int[2] = ia1s2x2.ptr.pp_int[2][1]; - iwork.ptr.p_int[3] = ia1s2x2.ptr.pp_int[1][2]; - iwork.ptr.p_int[4] = ia1s2x2.ptr.pp_int[2][2]; - if( iwork.ptr.p_int[6]==iu ) - { - wl = work.ptr.p_double[n+1]; - wlu = work.ptr.p_double[n+3]; - nwl = iwork.ptr.p_int[1]; - wu = work.ptr.p_double[n+4]; - wul = work.ptr.p_double[n+2]; - nwu = iwork.ptr.p_int[4]; - } - else - { - wl = work.ptr.p_double[n+2]; - wlu = work.ptr.p_double[n+4]; - nwl = iwork.ptr.p_int[2]; - wu = work.ptr.p_double[n+3]; - wul = work.ptr.p_double[n+1]; - nwu = iwork.ptr.p_int[3]; - } - if( ((nwl<0||nwl>=n)||nwu<1)||nwu>n ) - { - *errorcode = 4; - result = ae_false; - ae_frame_leave(_state); - return result; - } - } - else - { - - /* - * RANGE='A' or 'V' -- Set ATOLI - */ - tnorm = ae_maxreal(ae_fabs(d->ptr.p_double[1], _state)+ae_fabs(e->ptr.p_double[1], _state), ae_fabs(d->ptr.p_double[n], _state)+ae_fabs(e->ptr.p_double[n-1], _state), _state); - for(j=2; j<=n-1; j++) - { - tnorm = ae_maxreal(tnorm, ae_fabs(d->ptr.p_double[j], _state)+ae_fabs(e->ptr.p_double[j-1], _state)+ae_fabs(e->ptr.p_double[j], _state), _state); - } - if( ae_fp_less_eq(abstol,(double)(0)) ) - { - atoli = ulp*tnorm; - } - else - { - atoli = abstol; - } - if( irange==2 ) - { - wl = vl; - wu = vu; - } - else - { - wl = (double)(0); - wu = (double)(0); - } - } - - /* - * Find Eigenvalues -- Loop Over Blocks and recompute NWL and NWU. - * NWL accumulates the number of eigenvalues .le. WL, - * NWU accumulates the number of eigenvalues .le. WU - */ - *m = 0; - iend = 0; - *errorcode = 0; - nwl = 0; - nwu = 0; - for(jb=1; jb<=*nsplit; jb++) - { - ioff = iend; - ibegin = ioff+1; - iend = isplit->ptr.p_int[jb]; - iin = iend-ioff; - if( iin==1 ) - { - - /* - * Special Case -- IIN=1 - */ - if( irange==1||ae_fp_greater_eq(wl,d->ptr.p_double[ibegin]-pivmin) ) - { - nwl = nwl+1; - } - if( irange==1||ae_fp_greater_eq(wu,d->ptr.p_double[ibegin]-pivmin) ) - { - nwu = nwu+1; - } - if( irange==1||(ae_fp_less(wl,d->ptr.p_double[ibegin]-pivmin)&&ae_fp_greater_eq(wu,d->ptr.p_double[ibegin]-pivmin)) ) - { - *m = *m+1; - w->ptr.p_double[*m] = d->ptr.p_double[ibegin]; - iblock->ptr.p_int[*m] = jb; - } - } - else - { - - /* - * General Case -- IIN > 1 - * - * Compute Gershgorin Interval - * and use it as the initial interval - */ - gu = d->ptr.p_double[ibegin]; - gl = d->ptr.p_double[ibegin]; - tmp1 = (double)(0); - for(j=ibegin; j<=iend-1; j++) - { - tmp2 = ae_fabs(e->ptr.p_double[j], _state); - gu = ae_maxreal(gu, d->ptr.p_double[j]+tmp1+tmp2, _state); - gl = ae_minreal(gl, d->ptr.p_double[j]-tmp1-tmp2, _state); - tmp1 = tmp2; - } - gu = ae_maxreal(gu, d->ptr.p_double[iend]+tmp1, _state); - gl = ae_minreal(gl, d->ptr.p_double[iend]-tmp1, _state); - bnorm = ae_maxreal(ae_fabs(gl, _state), ae_fabs(gu, _state), _state); - gl = gl-fudge*bnorm*ulp*iin-fudge*pivmin; - gu = gu+fudge*bnorm*ulp*iin+fudge*pivmin; - - /* - * Compute ATOLI for the current submatrix - */ - if( ae_fp_less_eq(abstol,(double)(0)) ) - { - atoli = ulp*ae_maxreal(ae_fabs(gl, _state), ae_fabs(gu, _state), _state); - } - else - { - atoli = abstol; - } - if( irange>1 ) - { - if( ae_fp_less(gu,wl) ) - { - nwl = nwl+iin; - nwu = nwu+iin; - continue; - } - gl = ae_maxreal(gl, wl, _state); - gu = ae_minreal(gu, wu, _state); - if( ae_fp_greater_eq(gl,gu) ) - { - continue; - } - } - - /* - * Set Up Initial Interval - */ - work.ptr.p_double[n+1] = gl; - work.ptr.p_double[n+iin+1] = gu; - - /* - * Calling DLAEBZ - * - * CALL DLAEBZ( 1, 0, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN, - * D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ), - * IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IM, - * IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO ) - */ - for(tmpi=1; tmpi<=iin; tmpi++) - { - ra1siin.ptr.p_double[tmpi] = d->ptr.p_double[ibegin-1+tmpi]; - if( ibegin-1+tmpiptr.p_double[ibegin-1+tmpi]; - } - ra3siin.ptr.p_double[tmpi] = work.ptr.p_double[ibegin-1+tmpi]; - ra1siinx2.ptr.pp_double[tmpi][1] = work.ptr.p_double[n+tmpi]; - ra1siinx2.ptr.pp_double[tmpi][2] = work.ptr.p_double[n+tmpi+iin]; - ra4siin.ptr.p_double[tmpi] = work.ptr.p_double[n+2*iin+tmpi]; - rworkspace.ptr.p_double[tmpi] = w->ptr.p_double[*m+tmpi]; - iworkspace.ptr.p_int[tmpi] = iblock->ptr.p_int[*m+tmpi]; - ia1siinx2.ptr.pp_int[tmpi][1] = iwork.ptr.p_int[tmpi]; - ia1siinx2.ptr.pp_int[tmpi][2] = iwork.ptr.p_int[tmpi+iin]; - } - evd_internaldlaebz(1, 0, iin, iin, 1, atoli, rtoli, pivmin, &ra1siin, &ra2siin, &ra3siin, &idumma, &ra1siinx2, &ra4siin, &im, &ia1siinx2, &rworkspace, &iworkspace, &iinfo, _state); - for(tmpi=1; tmpi<=iin; tmpi++) - { - work.ptr.p_double[n+tmpi] = ra1siinx2.ptr.pp_double[tmpi][1]; - work.ptr.p_double[n+tmpi+iin] = ra1siinx2.ptr.pp_double[tmpi][2]; - work.ptr.p_double[n+2*iin+tmpi] = ra4siin.ptr.p_double[tmpi]; - w->ptr.p_double[*m+tmpi] = rworkspace.ptr.p_double[tmpi]; - iblock->ptr.p_int[*m+tmpi] = iworkspace.ptr.p_int[tmpi]; - iwork.ptr.p_int[tmpi] = ia1siinx2.ptr.pp_int[tmpi][1]; - iwork.ptr.p_int[tmpi+iin] = ia1siinx2.ptr.pp_int[tmpi][2]; - } - nwl = nwl+iwork.ptr.p_int[1]; - nwu = nwu+iwork.ptr.p_int[iin+1]; - iwoff = *m-iwork.ptr.p_int[1]; - - /* - * Compute Eigenvalues - */ - itmax = ae_iceil((ae_log(gu-gl+pivmin, _state)-ae_log(pivmin, _state))/ae_log((double)(2), _state), _state)+2; - - /* - * Calling DLAEBZ - * - *CALL DLAEBZ( 2, ITMAX, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN, - * D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ), - * IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IOUT, - * IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO ) - */ - for(tmpi=1; tmpi<=iin; tmpi++) - { - ra1siin.ptr.p_double[tmpi] = d->ptr.p_double[ibegin-1+tmpi]; - if( ibegin-1+tmpiptr.p_double[ibegin-1+tmpi]; - } - ra3siin.ptr.p_double[tmpi] = work.ptr.p_double[ibegin-1+tmpi]; - ra1siinx2.ptr.pp_double[tmpi][1] = work.ptr.p_double[n+tmpi]; - ra1siinx2.ptr.pp_double[tmpi][2] = work.ptr.p_double[n+tmpi+iin]; - ra4siin.ptr.p_double[tmpi] = work.ptr.p_double[n+2*iin+tmpi]; - rworkspace.ptr.p_double[tmpi] = w->ptr.p_double[*m+tmpi]; - iworkspace.ptr.p_int[tmpi] = iblock->ptr.p_int[*m+tmpi]; - ia1siinx2.ptr.pp_int[tmpi][1] = iwork.ptr.p_int[tmpi]; - ia1siinx2.ptr.pp_int[tmpi][2] = iwork.ptr.p_int[tmpi+iin]; - } - evd_internaldlaebz(2, itmax, iin, iin, 1, atoli, rtoli, pivmin, &ra1siin, &ra2siin, &ra3siin, &idumma, &ra1siinx2, &ra4siin, &iout, &ia1siinx2, &rworkspace, &iworkspace, &iinfo, _state); - for(tmpi=1; tmpi<=iin; tmpi++) - { - work.ptr.p_double[n+tmpi] = ra1siinx2.ptr.pp_double[tmpi][1]; - work.ptr.p_double[n+tmpi+iin] = ra1siinx2.ptr.pp_double[tmpi][2]; - work.ptr.p_double[n+2*iin+tmpi] = ra4siin.ptr.p_double[tmpi]; - w->ptr.p_double[*m+tmpi] = rworkspace.ptr.p_double[tmpi]; - iblock->ptr.p_int[*m+tmpi] = iworkspace.ptr.p_int[tmpi]; - iwork.ptr.p_int[tmpi] = ia1siinx2.ptr.pp_int[tmpi][1]; - iwork.ptr.p_int[tmpi+iin] = ia1siinx2.ptr.pp_int[tmpi][2]; - } - - /* - * Copy Eigenvalues Into W and IBLOCK - * Use -JB for block number for unconverged eigenvalues. - */ - for(j=1; j<=iout; j++) - { - tmp1 = 0.5*(work.ptr.p_double[j+n]+work.ptr.p_double[j+iin+n]); - - /* - * Flag non-convergence. - */ - if( j>iout-iinfo ) - { - ncnvrg = ae_true; - ib = -jb; - } - else - { - ib = jb; - } - for(je=iwork.ptr.p_int[j]+1+iwoff; je<=iwork.ptr.p_int[j+iin]+iwoff; je++) - { - w->ptr.p_double[je] = tmp1; - iblock->ptr.p_int[je] = ib; - } - } - *m = *m+im; - } - } - - /* - * If RANGE='I', then (WL,WU) contains eigenvalues NWL+1,...,NWU - * If NWL+1 < IL or NWU > IU, discard extra eigenvalues. - */ - if( irange==3 ) - { - im = 0; - idiscl = il-1-nwl; - idiscu = nwu-iu; - if( idiscl>0||idiscu>0 ) - { - for(je=1; je<=*m; je++) - { - if( ae_fp_less_eq(w->ptr.p_double[je],wlu)&&idiscl>0 ) - { - idiscl = idiscl-1; - } - else - { - if( ae_fp_greater_eq(w->ptr.p_double[je],wul)&&idiscu>0 ) - { - idiscu = idiscu-1; - } - else - { - im = im+1; - w->ptr.p_double[im] = w->ptr.p_double[je]; - iblock->ptr.p_int[im] = iblock->ptr.p_int[je]; - } - } - } - *m = im; - } - if( idiscl>0||idiscu>0 ) - { - - /* - * Code to deal with effects of bad arithmetic: - * Some low eigenvalues to be discarded are not in (WL,WLU], - * or high eigenvalues to be discarded are not in (WUL,WU] - * so just kill off the smallest IDISCL/largest IDISCU - * eigenvalues, by simply finding the smallest/largest - * eigenvalue(s). - * - * (If N(w) is monotone non-decreasing, this should never - * happen.) - */ - if( idiscl>0 ) - { - wkill = wu; - for(jdisc=1; jdisc<=idiscl; jdisc++) - { - iw = 0; - for(je=1; je<=*m; je++) - { - if( iblock->ptr.p_int[je]!=0&&(ae_fp_less(w->ptr.p_double[je],wkill)||iw==0) ) - { - iw = je; - wkill = w->ptr.p_double[je]; - } - } - iblock->ptr.p_int[iw] = 0; - } - } - if( idiscu>0 ) - { - wkill = wl; - for(jdisc=1; jdisc<=idiscu; jdisc++) - { - iw = 0; - for(je=1; je<=*m; je++) - { - if( iblock->ptr.p_int[je]!=0&&(ae_fp_greater(w->ptr.p_double[je],wkill)||iw==0) ) - { - iw = je; - wkill = w->ptr.p_double[je]; - } - } - iblock->ptr.p_int[iw] = 0; - } - } - im = 0; - for(je=1; je<=*m; je++) - { - if( iblock->ptr.p_int[je]!=0 ) - { - im = im+1; - w->ptr.p_double[im] = w->ptr.p_double[je]; - iblock->ptr.p_int[im] = iblock->ptr.p_int[je]; - } - } - *m = im; - } - if( idiscl<0||idiscu<0 ) - { - toofew = ae_true; - } - } - - /* - * If ORDER='B', do nothing -- the eigenvalues are already sorted - * by block. - * If ORDER='E', sort the eigenvalues from smallest to largest - */ - if( iorder==1&&*nsplit>1 ) - { - for(je=1; je<=*m-1; je++) - { - ie = 0; - tmp1 = w->ptr.p_double[je]; - for(j=je+1; j<=*m; j++) - { - if( ae_fp_less(w->ptr.p_double[j],tmp1) ) - { - ie = j; - tmp1 = w->ptr.p_double[j]; - } - } - if( ie!=0 ) - { - itmp1 = iblock->ptr.p_int[ie]; - w->ptr.p_double[ie] = w->ptr.p_double[je]; - iblock->ptr.p_int[ie] = iblock->ptr.p_int[je]; - w->ptr.p_double[je] = tmp1; - iblock->ptr.p_int[je] = itmp1; - } - } - } - for(j=1; j<=*m; j++) - { - w->ptr.p_double[j] = w->ptr.p_double[j]*scalefactor; - } - *errorcode = 0; - if( ncnvrg ) - { - *errorcode = *errorcode+1; - } - if( toofew ) - { - *errorcode = *errorcode+2; - } - result = *errorcode==0; - ae_frame_leave(_state); - return result; -} - - -static void evd_internaldstein(ae_int_t n, - /* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t m, - /* Real */ ae_vector* w, - /* Integer */ ae_vector* iblock, - /* Integer */ ae_vector* isplit, - /* Real */ ae_matrix* z, - /* Integer */ ae_vector* ifail, - ae_int_t* info, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _e; - ae_vector _w; - ae_int_t maxits; - ae_int_t extra; - ae_int_t b1; - ae_int_t blksiz; - ae_int_t bn; - ae_int_t gpind; - ae_int_t i; - ae_int_t iinfo; - ae_int_t its; - ae_int_t j; - ae_int_t j1; - ae_int_t jblk; - ae_int_t jmax; - ae_int_t nblk; - ae_int_t nrmchk; - double dtpcrt; - double eps; - double eps1; - double nrm; - double onenrm; - double ortol; - double pertol; - double scl; - double sep; - double tol; - double xj; - double xjm; - double ztr; - ae_vector work1; - ae_vector work2; - ae_vector work3; - ae_vector work4; - ae_vector work5; - ae_vector iwork; - ae_bool tmpcriterion; - ae_int_t ti; - ae_int_t i1; - ae_int_t i2; - double v; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&_e, 0, sizeof(_e)); - memset(&_w, 0, sizeof(_w)); - memset(&work1, 0, sizeof(work1)); - memset(&work2, 0, sizeof(work2)); - memset(&work3, 0, sizeof(work3)); - memset(&work4, 0, sizeof(work4)); - memset(&work5, 0, sizeof(work5)); - memset(&iwork, 0, sizeof(iwork)); - memset(&rs, 0, sizeof(rs)); - ae_vector_init_copy(&_e, e, _state, ae_true); - e = &_e; - ae_vector_init_copy(&_w, w, _state, ae_true); - w = &_w; - ae_matrix_clear(z); - ae_vector_clear(ifail); - *info = 0; - ae_vector_init(&work1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work3, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work4, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work5, 0, DT_REAL, _state, ae_true); - ae_vector_init(&iwork, 0, DT_INT, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndseed(346436, 2434, &rs, _state); - maxits = 5; - extra = 2; - ae_vector_set_length(&work1, ae_maxint(n, 1, _state)+1, _state); - ae_vector_set_length(&work2, ae_maxint(n-1, 1, _state)+1, _state); - ae_vector_set_length(&work3, ae_maxint(n, 1, _state)+1, _state); - ae_vector_set_length(&work4, ae_maxint(n, 1, _state)+1, _state); - ae_vector_set_length(&work5, ae_maxint(n, 1, _state)+1, _state); - ae_vector_set_length(&iwork, ae_maxint(n, 1, _state)+1, _state); - ae_vector_set_length(ifail, ae_maxint(m, 1, _state)+1, _state); - ae_matrix_set_length(z, ae_maxint(n, 1, _state)+1, ae_maxint(m, 1, _state)+1, _state); - - /* - * these initializers are not really necessary, - * but without them compiler complains about uninitialized locals - */ - gpind = 0; - onenrm = (double)(0); - ortol = (double)(0); - dtpcrt = (double)(0); - xjm = (double)(0); - - /* - * Test the input parameters. - */ - *info = 0; - for(i=1; i<=m; i++) - { - ifail->ptr.p_int[i] = 0; - } - if( n<0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - if( m<0||m>n ) - { - *info = -4; - ae_frame_leave(_state); - return; - } - for(j=2; j<=m; j++) - { - if( iblock->ptr.p_int[j]ptr.p_int[j-1] ) - { - *info = -6; - break; - } - if( iblock->ptr.p_int[j]==iblock->ptr.p_int[j-1]&&ae_fp_less(w->ptr.p_double[j],w->ptr.p_double[j-1]) ) - { - *info = -5; - break; - } - } - if( *info!=0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Quick return if possible - */ - if( n==0||m==0 ) - { - ae_frame_leave(_state); - return; - } - if( n==1 ) - { - z->ptr.pp_double[1][1] = (double)(1); - ae_frame_leave(_state); - return; - } - - /* - * Some preparations - */ - ti = n-1; - ae_v_move(&work1.ptr.p_double[1], 1, &e->ptr.p_double[1], 1, ae_v_len(1,ti)); - ae_vector_set_length(e, n+1, _state); - ae_v_move(&e->ptr.p_double[1], 1, &work1.ptr.p_double[1], 1, ae_v_len(1,ti)); - ae_v_move(&work1.ptr.p_double[1], 1, &w->ptr.p_double[1], 1, ae_v_len(1,m)); - ae_vector_set_length(w, n+1, _state); - ae_v_move(&w->ptr.p_double[1], 1, &work1.ptr.p_double[1], 1, ae_v_len(1,m)); - - /* - * Get machine constants. - */ - eps = ae_machineepsilon; - - /* - * Compute eigenvectors of matrix blocks. - */ - j1 = 1; - for(nblk=1; nblk<=iblock->ptr.p_int[m]; nblk++) - { - - /* - * Find starting and ending indices of block nblk. - */ - if( nblk==1 ) - { - b1 = 1; - } - else - { - b1 = isplit->ptr.p_int[nblk-1]+1; - } - bn = isplit->ptr.p_int[nblk]; - blksiz = bn-b1+1; - if( blksiz!=1 ) - { - - /* - * Compute reorthogonalization criterion and stopping criterion. - */ - gpind = b1; - onenrm = ae_fabs(d->ptr.p_double[b1], _state)+ae_fabs(e->ptr.p_double[b1], _state); - onenrm = ae_maxreal(onenrm, ae_fabs(d->ptr.p_double[bn], _state)+ae_fabs(e->ptr.p_double[bn-1], _state), _state); - for(i=b1+1; i<=bn-1; i++) - { - onenrm = ae_maxreal(onenrm, ae_fabs(d->ptr.p_double[i], _state)+ae_fabs(e->ptr.p_double[i-1], _state)+ae_fabs(e->ptr.p_double[i], _state), _state); - } - ortol = 0.001*onenrm; - dtpcrt = ae_sqrt(0.1/blksiz, _state); - } - - /* - * Loop through eigenvalues of block nblk. - */ - jblk = 0; - for(j=j1; j<=m; j++) - { - if( iblock->ptr.p_int[j]!=nblk ) - { - j1 = j; - break; - } - jblk = jblk+1; - xj = w->ptr.p_double[j]; - if( blksiz==1 ) - { - - /* - * Skip all the work if the block size is one. - */ - work1.ptr.p_double[1] = (double)(1); - } - else - { - - /* - * If eigenvalues j and j-1 are too close, add a relatively - * small perturbation. - */ - if( jblk>1 ) - { - eps1 = ae_fabs(eps*xj, _state); - pertol = 10*eps1; - sep = xj-xjm; - if( ae_fp_less(sep,pertol) ) - { - xj = xjm+pertol; - } - } - its = 0; - nrmchk = 0; - - /* - * Get random starting vector. - */ - for(ti=1; ti<=blksiz; ti++) - { - work1.ptr.p_double[ti] = 2*hqrnduniformr(&rs, _state)-1; - } - - /* - * Copy the matrix T so it won't be destroyed in factorization. - */ - for(ti=1; ti<=blksiz-1; ti++) - { - work2.ptr.p_double[ti] = e->ptr.p_double[b1+ti-1]; - work3.ptr.p_double[ti] = e->ptr.p_double[b1+ti-1]; - work4.ptr.p_double[ti] = d->ptr.p_double[b1+ti-1]; - } - work4.ptr.p_double[blksiz] = d->ptr.p_double[b1+blksiz-1]; - - /* - * Compute LU factors with partial pivoting ( PT = LU ) - */ - tol = (double)(0); - evd_tdininternaldlagtf(blksiz, &work4, xj, &work2, &work3, tol, &work5, &iwork, &iinfo, _state); - - /* - * Update iteration count. - */ - do - { - its = its+1; - if( its>maxits ) - { - - /* - * If stopping criterion was not satisfied, update info and - * store eigenvector number in array ifail. - */ - *info = *info+1; - ifail->ptr.p_int[*info] = j; - break; - } - - /* - * Normalize and scale the righthand side vector Pb. - */ - v = (double)(0); - for(ti=1; ti<=blksiz; ti++) - { - v = v+ae_fabs(work1.ptr.p_double[ti], _state); - } - scl = blksiz*onenrm*ae_maxreal(eps, ae_fabs(work4.ptr.p_double[blksiz], _state), _state)/v; - ae_v_muld(&work1.ptr.p_double[1], 1, ae_v_len(1,blksiz), scl); - - /* - * Solve the system LU = Pb. - */ - evd_tdininternaldlagts(blksiz, &work4, &work2, &work3, &work5, &iwork, &work1, &tol, &iinfo, _state); - - /* - * Reorthogonalize by modified Gram-Schmidt if eigenvalues are - * close enough. - */ - if( jblk!=1 ) - { - if( ae_fp_greater(ae_fabs(xj-xjm, _state),ortol) ) - { - gpind = j; - } - if( gpind!=j ) - { - for(i=gpind; i<=j-1; i++) - { - i1 = b1; - i2 = b1+blksiz-1; - ztr = ae_v_dotproduct(&work1.ptr.p_double[1], 1, &z->ptr.pp_double[i1][i], z->stride, ae_v_len(1,blksiz)); - ae_v_subd(&work1.ptr.p_double[1], 1, &z->ptr.pp_double[i1][i], z->stride, ae_v_len(1,blksiz), ztr); - touchint(&i2, _state); - } - } - } - - /* - * Check the infinity norm of the iterate. - */ - jmax = vectoridxabsmax(&work1, 1, blksiz, _state); - nrm = ae_fabs(work1.ptr.p_double[jmax], _state); - - /* - * Continue for additional iterations after norm reaches - * stopping criterion. - */ - tmpcriterion = ae_false; - if( ae_fp_less(nrm,dtpcrt) ) - { - tmpcriterion = ae_true; - } - else - { - nrmchk = nrmchk+1; - if( nrmchkptr.pp_double[i][j] = (double)(0); - } - for(i=1; i<=blksiz; i++) - { - z->ptr.pp_double[b1+i-1][j] = work1.ptr.p_double[i]; - } - - /* - * Save the shift to check eigenvalue spacing at next - * iteration. - */ - xjm = xj; - } - } - ae_frame_leave(_state); -} - - -static void evd_tdininternaldlagtf(ae_int_t n, - /* Real */ ae_vector* a, - double lambdav, - /* Real */ ae_vector* b, - /* Real */ ae_vector* c, - double tol, - /* Real */ ae_vector* d, - /* Integer */ ae_vector* iin, - ae_int_t* info, - ae_state *_state) -{ - ae_int_t k; - double eps; - double mult; - double piv1; - double piv2; - double scale1; - double scale2; - double temp; - double tl; - - *info = 0; - - *info = 0; - if( n<0 ) - { - *info = -1; - return; - } - if( n==0 ) - { - return; - } - a->ptr.p_double[1] = a->ptr.p_double[1]-lambdav; - iin->ptr.p_int[n] = 0; - if( n==1 ) - { - if( ae_fp_eq(a->ptr.p_double[1],(double)(0)) ) - { - iin->ptr.p_int[1] = 1; - } - return; - } - eps = ae_machineepsilon; - tl = ae_maxreal(tol, eps, _state); - scale1 = ae_fabs(a->ptr.p_double[1], _state)+ae_fabs(b->ptr.p_double[1], _state); - for(k=1; k<=n-1; k++) - { - a->ptr.p_double[k+1] = a->ptr.p_double[k+1]-lambdav; - scale2 = ae_fabs(c->ptr.p_double[k], _state)+ae_fabs(a->ptr.p_double[k+1], _state); - if( kptr.p_double[k+1], _state); - } - if( ae_fp_eq(a->ptr.p_double[k],(double)(0)) ) - { - piv1 = (double)(0); - } - else - { - piv1 = ae_fabs(a->ptr.p_double[k], _state)/scale1; - } - if( ae_fp_eq(c->ptr.p_double[k],(double)(0)) ) - { - iin->ptr.p_int[k] = 0; - piv2 = (double)(0); - scale1 = scale2; - if( kptr.p_double[k] = (double)(0); - } - } - else - { - piv2 = ae_fabs(c->ptr.p_double[k], _state)/scale2; - if( ae_fp_less_eq(piv2,piv1) ) - { - iin->ptr.p_int[k] = 0; - scale1 = scale2; - c->ptr.p_double[k] = c->ptr.p_double[k]/a->ptr.p_double[k]; - a->ptr.p_double[k+1] = a->ptr.p_double[k+1]-c->ptr.p_double[k]*b->ptr.p_double[k]; - if( kptr.p_double[k] = (double)(0); - } - } - else - { - iin->ptr.p_int[k] = 1; - mult = a->ptr.p_double[k]/c->ptr.p_double[k]; - a->ptr.p_double[k] = c->ptr.p_double[k]; - temp = a->ptr.p_double[k+1]; - a->ptr.p_double[k+1] = b->ptr.p_double[k]-mult*temp; - if( kptr.p_double[k] = b->ptr.p_double[k+1]; - b->ptr.p_double[k+1] = -mult*d->ptr.p_double[k]; - } - b->ptr.p_double[k] = temp; - c->ptr.p_double[k] = mult; - } - } - if( ae_fp_less_eq(ae_maxreal(piv1, piv2, _state),tl)&&iin->ptr.p_int[n]==0 ) - { - iin->ptr.p_int[n] = k; - } - } - if( ae_fp_less_eq(ae_fabs(a->ptr.p_double[n], _state),scale1*tl)&&iin->ptr.p_int[n]==0 ) - { - iin->ptr.p_int[n] = n; - } -} - - -static void evd_tdininternaldlagts(ae_int_t n, - /* Real */ ae_vector* a, - /* Real */ ae_vector* b, - /* Real */ ae_vector* c, - /* Real */ ae_vector* d, - /* Integer */ ae_vector* iin, - /* Real */ ae_vector* y, - double* tol, - ae_int_t* info, - ae_state *_state) -{ - ae_int_t k; - double absak; - double ak; - double bignum; - double eps; - double pert; - double sfmin; - double temp; - - *info = 0; - - *info = 0; - if( n<0 ) - { - *info = -1; - return; - } - if( n==0 ) - { - return; - } - eps = ae_machineepsilon; - sfmin = ae_minrealnumber; - bignum = 1/sfmin; - if( ae_fp_less_eq(*tol,(double)(0)) ) - { - *tol = ae_fabs(a->ptr.p_double[1], _state); - if( n>1 ) - { - *tol = ae_maxreal(*tol, ae_maxreal(ae_fabs(a->ptr.p_double[2], _state), ae_fabs(b->ptr.p_double[1], _state), _state), _state); - } - for(k=3; k<=n; k++) - { - *tol = ae_maxreal(*tol, ae_maxreal(ae_fabs(a->ptr.p_double[k], _state), ae_maxreal(ae_fabs(b->ptr.p_double[k-1], _state), ae_fabs(d->ptr.p_double[k-2], _state), _state), _state), _state); - } - *tol = *tol*eps; - if( ae_fp_eq(*tol,(double)(0)) ) - { - *tol = eps; - } - } - for(k=2; k<=n; k++) - { - if( iin->ptr.p_int[k-1]==0 ) - { - y->ptr.p_double[k] = y->ptr.p_double[k]-c->ptr.p_double[k-1]*y->ptr.p_double[k-1]; - } - else - { - temp = y->ptr.p_double[k-1]; - y->ptr.p_double[k-1] = y->ptr.p_double[k]; - y->ptr.p_double[k] = temp-c->ptr.p_double[k-1]*y->ptr.p_double[k]; - } - } - for(k=n; k>=1; k--) - { - if( k<=n-2 ) - { - temp = y->ptr.p_double[k]-b->ptr.p_double[k]*y->ptr.p_double[k+1]-d->ptr.p_double[k]*y->ptr.p_double[k+2]; - } - else - { - if( k==n-1 ) - { - temp = y->ptr.p_double[k]-b->ptr.p_double[k]*y->ptr.p_double[k+1]; - } - else - { - temp = y->ptr.p_double[k]; - } - } - ak = a->ptr.p_double[k]; - pert = ae_fabs(*tol, _state); - if( ae_fp_less(ak,(double)(0)) ) - { - pert = -pert; - } - for(;;) - { - absak = ae_fabs(ak, _state); - if( ae_fp_less(absak,(double)(1)) ) - { - if( ae_fp_less(absak,sfmin) ) - { - if( ae_fp_eq(absak,(double)(0))||ae_fp_greater(ae_fabs(temp, _state)*sfmin,absak) ) - { - ak = ak+pert; - pert = 2*pert; - continue; - } - else - { - temp = temp*bignum; - ak = ak*bignum; - } - } - else - { - if( ae_fp_greater(ae_fabs(temp, _state),absak*bignum) ) - { - ak = ak+pert; - pert = 2*pert; - continue; - } - } - } - break; - } - y->ptr.p_double[k] = temp/ak; - } -} - - -static void evd_internaldlaebz(ae_int_t ijob, - ae_int_t nitmax, - ae_int_t n, - ae_int_t mmax, - ae_int_t minp, - double abstol, - double reltol, - double pivmin, - /* Real */ ae_vector* d, - /* Real */ ae_vector* e, - /* Real */ ae_vector* e2, - /* Integer */ ae_vector* nval, - /* Real */ ae_matrix* ab, - /* Real */ ae_vector* c, - ae_int_t* mout, - /* Integer */ ae_matrix* nab, - /* Real */ ae_vector* work, - /* Integer */ ae_vector* iwork, - ae_int_t* info, - ae_state *_state) -{ - ae_int_t itmp1; - ae_int_t itmp2; - ae_int_t j; - ae_int_t ji; - ae_int_t jit; - ae_int_t jp; - ae_int_t kf; - ae_int_t kfnew; - ae_int_t kl; - ae_int_t klnew; - double tmp1; - double tmp2; - - *mout = 0; - *info = 0; - - *info = 0; - if( ijob<1||ijob>3 ) - { - *info = -1; - return; - } - - /* - * Initialize NAB - */ - if( ijob==1 ) - { - - /* - * Compute the number of eigenvalues in the initial intervals. - */ - *mout = 0; - - /* - *DIR$ NOVECTOR - */ - for(ji=1; ji<=minp; ji++) - { - for(jp=1; jp<=2; jp++) - { - tmp1 = d->ptr.p_double[1]-ab->ptr.pp_double[ji][jp]; - if( ae_fp_less(ae_fabs(tmp1, _state),pivmin) ) - { - tmp1 = -pivmin; - } - nab->ptr.pp_int[ji][jp] = 0; - if( ae_fp_less_eq(tmp1,(double)(0)) ) - { - nab->ptr.pp_int[ji][jp] = 1; - } - for(j=2; j<=n; j++) - { - tmp1 = d->ptr.p_double[j]-e2->ptr.p_double[j-1]/tmp1-ab->ptr.pp_double[ji][jp]; - if( ae_fp_less(ae_fabs(tmp1, _state),pivmin) ) - { - tmp1 = -pivmin; - } - if( ae_fp_less_eq(tmp1,(double)(0)) ) - { - nab->ptr.pp_int[ji][jp] = nab->ptr.pp_int[ji][jp]+1; - } - } - } - *mout = *mout+nab->ptr.pp_int[ji][2]-nab->ptr.pp_int[ji][1]; - } - return; - } - - /* - * Initialize for loop - * - * KF and KL have the following meaning: - * Intervals 1,...,KF-1 have converged. - * Intervals KF,...,KL still need to be refined. - */ - kf = 1; - kl = minp; - - /* - * If IJOB=2, initialize C. - * If IJOB=3, use the user-supplied starting point. - */ - if( ijob==2 ) - { - for(ji=1; ji<=minp; ji++) - { - c->ptr.p_double[ji] = 0.5*(ab->ptr.pp_double[ji][1]+ab->ptr.pp_double[ji][2]); - } - } - - /* - * Iteration loop - */ - for(jit=1; jit<=nitmax; jit++) - { - - /* - * Loop over intervals - * - * - * Serial Version of the loop - */ - klnew = kl; - for(ji=kf; ji<=kl; ji++) - { - - /* - * Compute N(w), the number of eigenvalues less than w - */ - tmp1 = c->ptr.p_double[ji]; - tmp2 = d->ptr.p_double[1]-tmp1; - itmp1 = 0; - if( ae_fp_less_eq(tmp2,pivmin) ) - { - itmp1 = 1; - tmp2 = ae_minreal(tmp2, -pivmin, _state); - } - - /* - * A series of compiler directives to defeat vectorization - * for the next loop - * - **$PL$ CMCHAR=' ' - *CDIR$ NEXTSCALAR - *C$DIR SCALAR - *CDIR$ NEXT SCALAR - *CVD$L NOVECTOR - *CDEC$ NOVECTOR - *CVD$ NOVECTOR - **VDIR NOVECTOR - **VOCL LOOP,SCALAR - *CIBM PREFER SCALAR - **$PL$ CMCHAR='*' - */ - for(j=2; j<=n; j++) - { - tmp2 = d->ptr.p_double[j]-e2->ptr.p_double[j-1]/tmp2-tmp1; - if( ae_fp_less_eq(tmp2,pivmin) ) - { - itmp1 = itmp1+1; - tmp2 = ae_minreal(tmp2, -pivmin, _state); - } - } - if( ijob<=2 ) - { - - /* - * IJOB=2: Choose all intervals containing eigenvalues. - * - * Insure that N(w) is monotone - */ - itmp1 = ae_minint(nab->ptr.pp_int[ji][2], ae_maxint(nab->ptr.pp_int[ji][1], itmp1, _state), _state); - - /* - * Update the Queue -- add intervals if both halves - * contain eigenvalues. - */ - if( itmp1==nab->ptr.pp_int[ji][2] ) - { - - /* - * No eigenvalue in the upper interval: - * just use the lower interval. - */ - ab->ptr.pp_double[ji][2] = tmp1; - } - else - { - if( itmp1==nab->ptr.pp_int[ji][1] ) - { - - /* - * No eigenvalue in the lower interval: - * just use the upper interval. - */ - ab->ptr.pp_double[ji][1] = tmp1; - } - else - { - if( klnewptr.pp_double[klnew][2] = ab->ptr.pp_double[ji][2]; - nab->ptr.pp_int[klnew][2] = nab->ptr.pp_int[ji][2]; - ab->ptr.pp_double[klnew][1] = tmp1; - nab->ptr.pp_int[klnew][1] = itmp1; - ab->ptr.pp_double[ji][2] = tmp1; - nab->ptr.pp_int[ji][2] = itmp1; - } - else - { - *info = mmax+1; - return; - } - } - } - } - else - { - - /* - * IJOB=3: Binary search. Keep only the interval - * containing w s.t. N(w) = NVAL - */ - if( itmp1<=nval->ptr.p_int[ji] ) - { - ab->ptr.pp_double[ji][1] = tmp1; - nab->ptr.pp_int[ji][1] = itmp1; - } - if( itmp1>=nval->ptr.p_int[ji] ) - { - ab->ptr.pp_double[ji][2] = tmp1; - nab->ptr.pp_int[ji][2] = itmp1; - } - } - } - kl = klnew; - - /* - * Check for convergence - */ - kfnew = kf; - for(ji=kf; ji<=kl; ji++) - { - tmp1 = ae_fabs(ab->ptr.pp_double[ji][2]-ab->ptr.pp_double[ji][1], _state); - tmp2 = ae_maxreal(ae_fabs(ab->ptr.pp_double[ji][2], _state), ae_fabs(ab->ptr.pp_double[ji][1], _state), _state); - if( ae_fp_less(tmp1,ae_maxreal(abstol, ae_maxreal(pivmin, reltol*tmp2, _state), _state))||nab->ptr.pp_int[ji][1]>=nab->ptr.pp_int[ji][2] ) - { - - /* - * Converged -- Swap with position KFNEW, - * then increment KFNEW - */ - if( ji>kfnew ) - { - tmp1 = ab->ptr.pp_double[ji][1]; - tmp2 = ab->ptr.pp_double[ji][2]; - itmp1 = nab->ptr.pp_int[ji][1]; - itmp2 = nab->ptr.pp_int[ji][2]; - ab->ptr.pp_double[ji][1] = ab->ptr.pp_double[kfnew][1]; - ab->ptr.pp_double[ji][2] = ab->ptr.pp_double[kfnew][2]; - nab->ptr.pp_int[ji][1] = nab->ptr.pp_int[kfnew][1]; - nab->ptr.pp_int[ji][2] = nab->ptr.pp_int[kfnew][2]; - ab->ptr.pp_double[kfnew][1] = tmp1; - ab->ptr.pp_double[kfnew][2] = tmp2; - nab->ptr.pp_int[kfnew][1] = itmp1; - nab->ptr.pp_int[kfnew][2] = itmp2; - if( ijob==3 ) - { - itmp1 = nval->ptr.p_int[ji]; - nval->ptr.p_int[ji] = nval->ptr.p_int[kfnew]; - nval->ptr.p_int[kfnew] = itmp1; - } - } - kfnew = kfnew+1; - } - } - kf = kfnew; - - /* - * Choose Midpoints - */ - for(ji=kf; ji<=kl; ji++) - { - c->ptr.p_double[ji] = 0.5*(ab->ptr.pp_double[ji][1]+ab->ptr.pp_double[ji][2]); - } - - /* - * If no more intervals to refine, quit. - */ - if( kf>kl ) - { - break; - } - } - - /* - * Converged - */ - *info = ae_maxint(kl+1-kf, 0, _state); - *mout = kl; -} - - -/************************************************************************* -Internal subroutine - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - June 30, 1999 -*************************************************************************/ -static void evd_rmatrixinternaltrevc(/* Real */ ae_matrix* t, - ae_int_t n, - ae_int_t side, - ae_int_t howmny, - /* Boolean */ ae_vector* vselect, - /* Real */ ae_matrix* vl, - /* Real */ ae_matrix* vr, - ae_int_t* m, - ae_int_t* info, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _vselect; - ae_int_t i; - ae_int_t j; - ae_matrix t1; - ae_matrix vl1; - ae_matrix vr1; - ae_vector vselect1; - - ae_frame_make(_state, &_frame_block); - memset(&_vselect, 0, sizeof(_vselect)); - memset(&t1, 0, sizeof(t1)); - memset(&vl1, 0, sizeof(vl1)); - memset(&vr1, 0, sizeof(vr1)); - memset(&vselect1, 0, sizeof(vselect1)); - ae_vector_init_copy(&_vselect, vselect, _state, ae_true); - vselect = &_vselect; - *m = 0; - *info = 0; - ae_matrix_init(&t1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vl1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vr1, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vselect1, 0, DT_BOOL, _state, ae_true); - - - /* - * Allocate VL/VR, if needed - */ - if( howmny==2||howmny==3 ) - { - if( side==1||side==3 ) - { - rmatrixsetlengthatleast(vr, n, n, _state); - } - if( side==2||side==3 ) - { - rmatrixsetlengthatleast(vl, n, n, _state); - } - } - - /* - * Try to use MKL kernel - */ - if( rmatrixinternaltrevcmkl(t, n, side, howmny, vl, vr, m, info, _state) ) - { - ae_frame_leave(_state); - return; - } - - /* - * ALGLIB version - */ - ae_matrix_set_length(&t1, n+1, n+1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - t1.ptr.pp_double[i+1][j+1] = t->ptr.pp_double[i][j]; - } - } - if( howmny==3 ) - { - ae_vector_set_length(&vselect1, n+1, _state); - for(i=0; i<=n-1; i++) - { - vselect1.ptr.p_bool[1+i] = vselect->ptr.p_bool[i]; - } - } - if( (side==2||side==3)&&howmny==1 ) - { - ae_matrix_set_length(&vl1, n+1, n+1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - vl1.ptr.pp_double[i+1][j+1] = vl->ptr.pp_double[i][j]; - } - } - } - if( (side==1||side==3)&&howmny==1 ) - { - ae_matrix_set_length(&vr1, n+1, n+1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - vr1.ptr.pp_double[i+1][j+1] = vr->ptr.pp_double[i][j]; - } - } - } - evd_internaltrevc(&t1, n, side, howmny, &vselect1, &vl1, &vr1, m, info, _state); - if( side!=1 ) - { - rmatrixsetlengthatleast(vl, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - vl->ptr.pp_double[i][j] = vl1.ptr.pp_double[i+1][j+1]; - } - } - } - if( side!=2 ) - { - rmatrixsetlengthatleast(vr, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - vr->ptr.pp_double[i][j] = vr1.ptr.pp_double[i+1][j+1]; - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal subroutine - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - June 30, 1999 -*************************************************************************/ -static void evd_internaltrevc(/* Real */ ae_matrix* t, - ae_int_t n, - ae_int_t side, - ae_int_t howmny, - /* Boolean */ ae_vector* vselect, - /* Real */ ae_matrix* vl, - /* Real */ ae_matrix* vr, - ae_int_t* m, - ae_int_t* info, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _vselect; - ae_bool allv; - ae_bool bothv; - ae_bool leftv; - ae_bool over; - ae_bool pair; - ae_bool rightv; - ae_bool somev; - ae_int_t i; - ae_int_t ierr; - ae_int_t ii; - ae_int_t ip; - ae_int_t iis; - ae_int_t j; - ae_int_t j1; - ae_int_t j2; - ae_int_t jnxt; - ae_int_t k; - ae_int_t ki; - ae_int_t n2; - double beta; - double bignum; - double emax; - double rec; - double remax; - double scl; - double smin; - double smlnum; - double ulp; - double unfl; - double vcrit; - double vmax; - double wi; - double wr; - double xnorm; - ae_matrix x; - ae_vector work; - ae_vector temp; - ae_matrix temp11; - ae_matrix temp22; - ae_matrix temp11b; - ae_matrix temp21b; - ae_matrix temp12b; - ae_matrix temp22b; - ae_bool skipflag; - ae_int_t k1; - ae_int_t k2; - ae_int_t k3; - ae_int_t k4; - double vt; - ae_vector rswap4; - ae_vector zswap4; - ae_matrix ipivot44; - ae_vector civ4; - ae_vector crv4; - - ae_frame_make(_state, &_frame_block); - memset(&_vselect, 0, sizeof(_vselect)); - memset(&x, 0, sizeof(x)); - memset(&work, 0, sizeof(work)); - memset(&temp, 0, sizeof(temp)); - memset(&temp11, 0, sizeof(temp11)); - memset(&temp22, 0, sizeof(temp22)); - memset(&temp11b, 0, sizeof(temp11b)); - memset(&temp21b, 0, sizeof(temp21b)); - memset(&temp12b, 0, sizeof(temp12b)); - memset(&temp22b, 0, sizeof(temp22b)); - memset(&rswap4, 0, sizeof(rswap4)); - memset(&zswap4, 0, sizeof(zswap4)); - memset(&ipivot44, 0, sizeof(ipivot44)); - memset(&civ4, 0, sizeof(civ4)); - memset(&crv4, 0, sizeof(crv4)); - ae_vector_init_copy(&_vselect, vselect, _state, ae_true); - vselect = &_vselect; - *m = 0; - *info = 0; - ae_matrix_init(&x, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - ae_vector_init(&temp, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&temp11, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&temp22, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&temp11b, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&temp21b, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&temp12b, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&temp22b, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rswap4, 0, DT_BOOL, _state, ae_true); - ae_vector_init(&zswap4, 0, DT_BOOL, _state, ae_true); - ae_matrix_init(&ipivot44, 0, 0, DT_INT, _state, ae_true); - ae_vector_init(&civ4, 0, DT_REAL, _state, ae_true); - ae_vector_init(&crv4, 0, DT_REAL, _state, ae_true); - - ae_matrix_set_length(&x, 2+1, 2+1, _state); - ae_matrix_set_length(&temp11, 1+1, 1+1, _state); - ae_matrix_set_length(&temp11b, 1+1, 1+1, _state); - ae_matrix_set_length(&temp21b, 2+1, 1+1, _state); - ae_matrix_set_length(&temp12b, 1+1, 2+1, _state); - ae_matrix_set_length(&temp22b, 2+1, 2+1, _state); - ae_matrix_set_length(&temp22, 2+1, 2+1, _state); - ae_vector_set_length(&work, 3*n+1, _state); - ae_vector_set_length(&temp, n+1, _state); - ae_vector_set_length(&rswap4, 4+1, _state); - ae_vector_set_length(&zswap4, 4+1, _state); - ae_matrix_set_length(&ipivot44, 4+1, 4+1, _state); - ae_vector_set_length(&civ4, 4+1, _state); - ae_vector_set_length(&crv4, 4+1, _state); - if( howmny!=1 ) - { - if( side==1||side==3 ) - { - ae_matrix_set_length(vr, n+1, n+1, _state); - } - if( side==2||side==3 ) - { - ae_matrix_set_length(vl, n+1, n+1, _state); - } - } - - /* - * Decode and test the input parameters - */ - bothv = side==3; - rightv = side==1||bothv; - leftv = side==2||bothv; - allv = howmny==2; - over = howmny==1; - somev = howmny==3; - *info = 0; - if( n<0 ) - { - *info = -2; - ae_frame_leave(_state); - return; - } - if( !rightv&&!leftv ) - { - *info = -3; - ae_frame_leave(_state); - return; - } - if( (!allv&&!over)&&!somev ) - { - *info = -4; - ae_frame_leave(_state); - return; - } - - /* - * Set M to the number of columns required to store the selected - * eigenvectors, standardize the array SELECT if necessary, and - * test MM. - */ - if( somev ) - { - *m = 0; - pair = ae_false; - for(j=1; j<=n; j++) - { - if( pair ) - { - pair = ae_false; - vselect->ptr.p_bool[j] = ae_false; - } - else - { - if( jptr.pp_double[j+1][j],(double)(0)) ) - { - if( vselect->ptr.p_bool[j] ) - { - *m = *m+1; - } - } - else - { - pair = ae_true; - if( vselect->ptr.p_bool[j]||vselect->ptr.p_bool[j+1] ) - { - vselect->ptr.p_bool[j] = ae_true; - *m = *m+2; - } - } - } - else - { - if( vselect->ptr.p_bool[n] ) - { - *m = *m+1; - } - } - } - } - } - else - { - *m = n; - } - - /* - * Quick return if possible. - */ - if( n==0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Set the constants to control overflow. - */ - unfl = ae_minrealnumber; - ulp = ae_machineepsilon; - smlnum = unfl*(n/ulp); - bignum = (1-ulp)/smlnum; - - /* - * Compute 1-norm of each column of strictly upper triangular - * part of T to control overflow in triangular solver. - */ - work.ptr.p_double[1] = (double)(0); - for(j=2; j<=n; j++) - { - work.ptr.p_double[j] = (double)(0); - for(i=1; i<=j-1; i++) - { - work.ptr.p_double[j] = work.ptr.p_double[j]+ae_fabs(t->ptr.pp_double[i][j], _state); - } - } - - /* - * Index IP is used to specify the real or complex eigenvalue: - * IP = 0, real eigenvalue, - * 1, first of conjugate complex pair: (wr,wi) - * -1, second of conjugate complex pair: (wr,wi) - */ - n2 = 2*n; - if( rightv ) - { - - /* - * Compute right eigenvectors. - */ - ip = 0; - iis = *m; - for(ki=n; ki>=1; ki--) - { - skipflag = ae_false; - if( ip==1 ) - { - skipflag = ae_true; - } - else - { - if( ki!=1 ) - { - if( ae_fp_neq(t->ptr.pp_double[ki][ki-1],(double)(0)) ) - { - ip = -1; - } - } - if( somev ) - { - if( ip==0 ) - { - if( !vselect->ptr.p_bool[ki] ) - { - skipflag = ae_true; - } - } - else - { - if( !vselect->ptr.p_bool[ki-1] ) - { - skipflag = ae_true; - } - } - } - } - if( !skipflag ) - { - - /* - * Compute the KI-th eigenvalue (WR,WI). - */ - wr = t->ptr.pp_double[ki][ki]; - wi = (double)(0); - if( ip!=0 ) - { - wi = ae_sqrt(ae_fabs(t->ptr.pp_double[ki][ki-1], _state), _state)*ae_sqrt(ae_fabs(t->ptr.pp_double[ki-1][ki], _state), _state); - } - smin = ae_maxreal(ulp*(ae_fabs(wr, _state)+ae_fabs(wi, _state)), smlnum, _state); - if( ip==0 ) - { - - /* - * Real right eigenvector - */ - work.ptr.p_double[ki+n] = (double)(1); - - /* - * Form right-hand side - */ - for(k=1; k<=ki-1; k++) - { - work.ptr.p_double[k+n] = -t->ptr.pp_double[k][ki]; - } - - /* - * Solve the upper quasi-triangular system: - * (T(1:KI-1,1:KI-1) - WR)*X = SCALE*WORK. - */ - jnxt = ki-1; - for(j=ki-1; j>=1; j--) - { - if( j>jnxt ) - { - continue; - } - j1 = j; - j2 = j; - jnxt = j-1; - if( j>1 ) - { - if( ae_fp_neq(t->ptr.pp_double[j][j-1],(double)(0)) ) - { - j1 = j-1; - jnxt = j-2; - } - } - if( j1==j2 ) - { - - /* - * 1-by-1 diagonal block - */ - temp11.ptr.pp_double[1][1] = t->ptr.pp_double[j][j]; - temp11b.ptr.pp_double[1][1] = work.ptr.p_double[j+n]; - evd_internalhsevdlaln2(ae_false, 1, 1, smin, (double)(1), &temp11, 1.0, 1.0, &temp11b, wr, 0.0, &rswap4, &zswap4, &ipivot44, &civ4, &crv4, &x, &scl, &xnorm, &ierr, _state); - - /* - * Scale X(1,1) to avoid overflow when updating - * the right-hand side. - */ - if( ae_fp_greater(xnorm,(double)(1)) ) - { - if( ae_fp_greater(work.ptr.p_double[j],bignum/xnorm) ) - { - x.ptr.pp_double[1][1] = x.ptr.pp_double[1][1]/xnorm; - scl = scl/xnorm; - } - } - - /* - * Scale if necessary - */ - if( ae_fp_neq(scl,(double)(1)) ) - { - k1 = n+1; - k2 = n+ki; - ae_v_muld(&work.ptr.p_double[k1], 1, ae_v_len(k1,k2), scl); - } - work.ptr.p_double[j+n] = x.ptr.pp_double[1][1]; - - /* - * Update right-hand side - */ - k1 = 1+n; - k2 = j-1+n; - k3 = j-1; - vt = -x.ptr.pp_double[1][1]; - ae_v_addd(&work.ptr.p_double[k1], 1, &t->ptr.pp_double[1][j], t->stride, ae_v_len(k1,k2), vt); - } - else - { - - /* - * 2-by-2 diagonal block - */ - temp22.ptr.pp_double[1][1] = t->ptr.pp_double[j-1][j-1]; - temp22.ptr.pp_double[1][2] = t->ptr.pp_double[j-1][j]; - temp22.ptr.pp_double[2][1] = t->ptr.pp_double[j][j-1]; - temp22.ptr.pp_double[2][2] = t->ptr.pp_double[j][j]; - temp21b.ptr.pp_double[1][1] = work.ptr.p_double[j-1+n]; - temp21b.ptr.pp_double[2][1] = work.ptr.p_double[j+n]; - evd_internalhsevdlaln2(ae_false, 2, 1, smin, 1.0, &temp22, 1.0, 1.0, &temp21b, wr, (double)(0), &rswap4, &zswap4, &ipivot44, &civ4, &crv4, &x, &scl, &xnorm, &ierr, _state); - - /* - * Scale X(1,1) and X(2,1) to avoid overflow when - * updating the right-hand side. - */ - if( ae_fp_greater(xnorm,(double)(1)) ) - { - beta = ae_maxreal(work.ptr.p_double[j-1], work.ptr.p_double[j], _state); - if( ae_fp_greater(beta,bignum/xnorm) ) - { - x.ptr.pp_double[1][1] = x.ptr.pp_double[1][1]/xnorm; - x.ptr.pp_double[2][1] = x.ptr.pp_double[2][1]/xnorm; - scl = scl/xnorm; - } - } - - /* - * Scale if necessary - */ - if( ae_fp_neq(scl,(double)(1)) ) - { - k1 = 1+n; - k2 = ki+n; - ae_v_muld(&work.ptr.p_double[k1], 1, ae_v_len(k1,k2), scl); - } - work.ptr.p_double[j-1+n] = x.ptr.pp_double[1][1]; - work.ptr.p_double[j+n] = x.ptr.pp_double[2][1]; - - /* - * Update right-hand side - */ - k1 = 1+n; - k2 = j-2+n; - k3 = j-2; - k4 = j-1; - vt = -x.ptr.pp_double[1][1]; - ae_v_addd(&work.ptr.p_double[k1], 1, &t->ptr.pp_double[1][k4], t->stride, ae_v_len(k1,k2), vt); - vt = -x.ptr.pp_double[2][1]; - ae_v_addd(&work.ptr.p_double[k1], 1, &t->ptr.pp_double[1][j], t->stride, ae_v_len(k1,k2), vt); - } - } - - /* - * Copy the vector x or Q*x to VR and normalize. - */ - if( !over ) - { - k1 = 1+n; - k2 = ki+n; - ae_v_move(&vr->ptr.pp_double[1][iis], vr->stride, &work.ptr.p_double[k1], 1, ae_v_len(1,ki)); - ii = columnidxabsmax(vr, 1, ki, iis, _state); - remax = 1/ae_fabs(vr->ptr.pp_double[ii][iis], _state); - ae_v_muld(&vr->ptr.pp_double[1][iis], vr->stride, ae_v_len(1,ki), remax); - for(k=ki+1; k<=n; k++) - { - vr->ptr.pp_double[k][iis] = (double)(0); - } - } - else - { - if( ki>1 ) - { - ae_v_move(&temp.ptr.p_double[1], 1, &vr->ptr.pp_double[1][ki], vr->stride, ae_v_len(1,n)); - matrixvectormultiply(vr, 1, n, 1, ki-1, ae_false, &work, 1+n, ki-1+n, 1.0, &temp, 1, n, work.ptr.p_double[ki+n], _state); - ae_v_move(&vr->ptr.pp_double[1][ki], vr->stride, &temp.ptr.p_double[1], 1, ae_v_len(1,n)); - } - ii = columnidxabsmax(vr, 1, n, ki, _state); - remax = 1/ae_fabs(vr->ptr.pp_double[ii][ki], _state); - ae_v_muld(&vr->ptr.pp_double[1][ki], vr->stride, ae_v_len(1,n), remax); - } - } - else - { - - /* - * Complex right eigenvector. - * - * Initial solve - * [ (T(KI-1,KI-1) T(KI-1,KI) ) - (WR + I* WI)]*X = 0. - * [ (T(KI,KI-1) T(KI,KI) ) ] - */ - if( ae_fp_greater_eq(ae_fabs(t->ptr.pp_double[ki-1][ki], _state),ae_fabs(t->ptr.pp_double[ki][ki-1], _state)) ) - { - work.ptr.p_double[ki-1+n] = (double)(1); - work.ptr.p_double[ki+n2] = wi/t->ptr.pp_double[ki-1][ki]; - } - else - { - work.ptr.p_double[ki-1+n] = -wi/t->ptr.pp_double[ki][ki-1]; - work.ptr.p_double[ki+n2] = (double)(1); - } - work.ptr.p_double[ki+n] = (double)(0); - work.ptr.p_double[ki-1+n2] = (double)(0); - - /* - * Form right-hand side - */ - for(k=1; k<=ki-2; k++) - { - work.ptr.p_double[k+n] = -work.ptr.p_double[ki-1+n]*t->ptr.pp_double[k][ki-1]; - work.ptr.p_double[k+n2] = -work.ptr.p_double[ki+n2]*t->ptr.pp_double[k][ki]; - } - - /* - * Solve upper quasi-triangular system: - * (T(1:KI-2,1:KI-2) - (WR+i*WI))*X = SCALE*(WORK+i*WORK2) - */ - jnxt = ki-2; - for(j=ki-2; j>=1; j--) - { - if( j>jnxt ) - { - continue; - } - j1 = j; - j2 = j; - jnxt = j-1; - if( j>1 ) - { - if( ae_fp_neq(t->ptr.pp_double[j][j-1],(double)(0)) ) - { - j1 = j-1; - jnxt = j-2; - } - } - if( j1==j2 ) - { - - /* - * 1-by-1 diagonal block - */ - temp11.ptr.pp_double[1][1] = t->ptr.pp_double[j][j]; - temp12b.ptr.pp_double[1][1] = work.ptr.p_double[j+n]; - temp12b.ptr.pp_double[1][2] = work.ptr.p_double[j+n+n]; - evd_internalhsevdlaln2(ae_false, 1, 2, smin, 1.0, &temp11, 1.0, 1.0, &temp12b, wr, wi, &rswap4, &zswap4, &ipivot44, &civ4, &crv4, &x, &scl, &xnorm, &ierr, _state); - - /* - * Scale X(1,1) and X(1,2) to avoid overflow when - * updating the right-hand side. - */ - if( ae_fp_greater(xnorm,(double)(1)) ) - { - if( ae_fp_greater(work.ptr.p_double[j],bignum/xnorm) ) - { - x.ptr.pp_double[1][1] = x.ptr.pp_double[1][1]/xnorm; - x.ptr.pp_double[1][2] = x.ptr.pp_double[1][2]/xnorm; - scl = scl/xnorm; - } - } - - /* - * Scale if necessary - */ - if( ae_fp_neq(scl,(double)(1)) ) - { - k1 = 1+n; - k2 = ki+n; - ae_v_muld(&work.ptr.p_double[k1], 1, ae_v_len(k1,k2), scl); - k1 = 1+n2; - k2 = ki+n2; - ae_v_muld(&work.ptr.p_double[k1], 1, ae_v_len(k1,k2), scl); - } - work.ptr.p_double[j+n] = x.ptr.pp_double[1][1]; - work.ptr.p_double[j+n2] = x.ptr.pp_double[1][2]; - - /* - * Update the right-hand side - */ - k1 = 1+n; - k2 = j-1+n; - k3 = 1; - k4 = j-1; - vt = -x.ptr.pp_double[1][1]; - ae_v_addd(&work.ptr.p_double[k1], 1, &t->ptr.pp_double[k3][j], t->stride, ae_v_len(k1,k2), vt); - k1 = 1+n2; - k2 = j-1+n2; - k3 = 1; - k4 = j-1; - vt = -x.ptr.pp_double[1][2]; - ae_v_addd(&work.ptr.p_double[k1], 1, &t->ptr.pp_double[k3][j], t->stride, ae_v_len(k1,k2), vt); - } - else - { - - /* - * 2-by-2 diagonal block - */ - temp22.ptr.pp_double[1][1] = t->ptr.pp_double[j-1][j-1]; - temp22.ptr.pp_double[1][2] = t->ptr.pp_double[j-1][j]; - temp22.ptr.pp_double[2][1] = t->ptr.pp_double[j][j-1]; - temp22.ptr.pp_double[2][2] = t->ptr.pp_double[j][j]; - temp22b.ptr.pp_double[1][1] = work.ptr.p_double[j-1+n]; - temp22b.ptr.pp_double[1][2] = work.ptr.p_double[j-1+n+n]; - temp22b.ptr.pp_double[2][1] = work.ptr.p_double[j+n]; - temp22b.ptr.pp_double[2][2] = work.ptr.p_double[j+n+n]; - evd_internalhsevdlaln2(ae_false, 2, 2, smin, 1.0, &temp22, 1.0, 1.0, &temp22b, wr, wi, &rswap4, &zswap4, &ipivot44, &civ4, &crv4, &x, &scl, &xnorm, &ierr, _state); - - /* - * Scale X to avoid overflow when updating - * the right-hand side. - */ - if( ae_fp_greater(xnorm,(double)(1)) ) - { - beta = ae_maxreal(work.ptr.p_double[j-1], work.ptr.p_double[j], _state); - if( ae_fp_greater(beta,bignum/xnorm) ) - { - rec = 1/xnorm; - x.ptr.pp_double[1][1] = x.ptr.pp_double[1][1]*rec; - x.ptr.pp_double[1][2] = x.ptr.pp_double[1][2]*rec; - x.ptr.pp_double[2][1] = x.ptr.pp_double[2][1]*rec; - x.ptr.pp_double[2][2] = x.ptr.pp_double[2][2]*rec; - scl = scl*rec; - } - } - - /* - * Scale if necessary - */ - if( ae_fp_neq(scl,(double)(1)) ) - { - ae_v_muld(&work.ptr.p_double[1+n], 1, ae_v_len(1+n,ki+n), scl); - ae_v_muld(&work.ptr.p_double[1+n2], 1, ae_v_len(1+n2,ki+n2), scl); - } - work.ptr.p_double[j-1+n] = x.ptr.pp_double[1][1]; - work.ptr.p_double[j+n] = x.ptr.pp_double[2][1]; - work.ptr.p_double[j-1+n2] = x.ptr.pp_double[1][2]; - work.ptr.p_double[j+n2] = x.ptr.pp_double[2][2]; - - /* - * Update the right-hand side - */ - vt = -x.ptr.pp_double[1][1]; - ae_v_addd(&work.ptr.p_double[n+1], 1, &t->ptr.pp_double[1][j-1], t->stride, ae_v_len(n+1,n+j-2), vt); - vt = -x.ptr.pp_double[2][1]; - ae_v_addd(&work.ptr.p_double[n+1], 1, &t->ptr.pp_double[1][j], t->stride, ae_v_len(n+1,n+j-2), vt); - vt = -x.ptr.pp_double[1][2]; - ae_v_addd(&work.ptr.p_double[n2+1], 1, &t->ptr.pp_double[1][j-1], t->stride, ae_v_len(n2+1,n2+j-2), vt); - vt = -x.ptr.pp_double[2][2]; - ae_v_addd(&work.ptr.p_double[n2+1], 1, &t->ptr.pp_double[1][j], t->stride, ae_v_len(n2+1,n2+j-2), vt); - } - } - - /* - * Copy the vector x or Q*x to VR and normalize. - */ - if( !over ) - { - ae_v_move(&vr->ptr.pp_double[1][iis-1], vr->stride, &work.ptr.p_double[n+1], 1, ae_v_len(1,ki)); - ae_v_move(&vr->ptr.pp_double[1][iis], vr->stride, &work.ptr.p_double[n2+1], 1, ae_v_len(1,ki)); - emax = (double)(0); - for(k=1; k<=ki; k++) - { - emax = ae_maxreal(emax, ae_fabs(vr->ptr.pp_double[k][iis-1], _state)+ae_fabs(vr->ptr.pp_double[k][iis], _state), _state); - } - remax = 1/emax; - ae_v_muld(&vr->ptr.pp_double[1][iis-1], vr->stride, ae_v_len(1,ki), remax); - ae_v_muld(&vr->ptr.pp_double[1][iis], vr->stride, ae_v_len(1,ki), remax); - for(k=ki+1; k<=n; k++) - { - vr->ptr.pp_double[k][iis-1] = (double)(0); - vr->ptr.pp_double[k][iis] = (double)(0); - } - } - else - { - if( ki>2 ) - { - ae_v_move(&temp.ptr.p_double[1], 1, &vr->ptr.pp_double[1][ki-1], vr->stride, ae_v_len(1,n)); - matrixvectormultiply(vr, 1, n, 1, ki-2, ae_false, &work, 1+n, ki-2+n, 1.0, &temp, 1, n, work.ptr.p_double[ki-1+n], _state); - ae_v_move(&vr->ptr.pp_double[1][ki-1], vr->stride, &temp.ptr.p_double[1], 1, ae_v_len(1,n)); - ae_v_move(&temp.ptr.p_double[1], 1, &vr->ptr.pp_double[1][ki], vr->stride, ae_v_len(1,n)); - matrixvectormultiply(vr, 1, n, 1, ki-2, ae_false, &work, 1+n2, ki-2+n2, 1.0, &temp, 1, n, work.ptr.p_double[ki+n2], _state); - ae_v_move(&vr->ptr.pp_double[1][ki], vr->stride, &temp.ptr.p_double[1], 1, ae_v_len(1,n)); - } - else - { - vt = work.ptr.p_double[ki-1+n]; - ae_v_muld(&vr->ptr.pp_double[1][ki-1], vr->stride, ae_v_len(1,n), vt); - vt = work.ptr.p_double[ki+n2]; - ae_v_muld(&vr->ptr.pp_double[1][ki], vr->stride, ae_v_len(1,n), vt); - } - emax = (double)(0); - for(k=1; k<=n; k++) - { - emax = ae_maxreal(emax, ae_fabs(vr->ptr.pp_double[k][ki-1], _state)+ae_fabs(vr->ptr.pp_double[k][ki], _state), _state); - } - remax = 1/emax; - ae_v_muld(&vr->ptr.pp_double[1][ki-1], vr->stride, ae_v_len(1,n), remax); - ae_v_muld(&vr->ptr.pp_double[1][ki], vr->stride, ae_v_len(1,n), remax); - } - } - iis = iis-1; - if( ip!=0 ) - { - iis = iis-1; - } - } - if( ip==1 ) - { - ip = 0; - } - if( ip==-1 ) - { - ip = 1; - } - } - } - if( leftv ) - { - - /* - * Compute left eigenvectors. - */ - ip = 0; - iis = 1; - for(ki=1; ki<=n; ki++) - { - skipflag = ae_false; - if( ip==-1 ) - { - skipflag = ae_true; - } - else - { - if( ki!=n ) - { - if( ae_fp_neq(t->ptr.pp_double[ki+1][ki],(double)(0)) ) - { - ip = 1; - } - } - if( somev ) - { - if( !vselect->ptr.p_bool[ki] ) - { - skipflag = ae_true; - } - } - } - if( !skipflag ) - { - - /* - * Compute the KI-th eigenvalue (WR,WI). - */ - wr = t->ptr.pp_double[ki][ki]; - wi = (double)(0); - if( ip!=0 ) - { - wi = ae_sqrt(ae_fabs(t->ptr.pp_double[ki][ki+1], _state), _state)*ae_sqrt(ae_fabs(t->ptr.pp_double[ki+1][ki], _state), _state); - } - smin = ae_maxreal(ulp*(ae_fabs(wr, _state)+ae_fabs(wi, _state)), smlnum, _state); - if( ip==0 ) - { - - /* - * Real left eigenvector. - */ - work.ptr.p_double[ki+n] = (double)(1); - - /* - * Form right-hand side - */ - for(k=ki+1; k<=n; k++) - { - work.ptr.p_double[k+n] = -t->ptr.pp_double[ki][k]; - } - - /* - * Solve the quasi-triangular system: - * (T(KI+1:N,KI+1:N) - WR)'*X = SCALE*WORK - */ - vmax = (double)(1); - vcrit = bignum; - jnxt = ki+1; - for(j=ki+1; j<=n; j++) - { - if( jptr.pp_double[j+1][j],(double)(0)) ) - { - j2 = j+1; - jnxt = j+2; - } - } - if( j1==j2 ) - { - - /* - * 1-by-1 diagonal block - * - * Scale if necessary to avoid overflow when forming - * the right-hand side. - */ - if( ae_fp_greater(work.ptr.p_double[j],vcrit) ) - { - rec = 1/vmax; - ae_v_muld(&work.ptr.p_double[ki+n], 1, ae_v_len(ki+n,n+n), rec); - vmax = (double)(1); - vcrit = bignum; - } - vt = ae_v_dotproduct(&t->ptr.pp_double[ki+1][j], t->stride, &work.ptr.p_double[ki+1+n], 1, ae_v_len(ki+1,j-1)); - work.ptr.p_double[j+n] = work.ptr.p_double[j+n]-vt; - - /* - * Solve (T(J,J)-WR)'*X = WORK - */ - temp11.ptr.pp_double[1][1] = t->ptr.pp_double[j][j]; - temp11b.ptr.pp_double[1][1] = work.ptr.p_double[j+n]; - evd_internalhsevdlaln2(ae_false, 1, 1, smin, 1.0, &temp11, 1.0, 1.0, &temp11b, wr, (double)(0), &rswap4, &zswap4, &ipivot44, &civ4, &crv4, &x, &scl, &xnorm, &ierr, _state); - - /* - * Scale if necessary - */ - if( ae_fp_neq(scl,(double)(1)) ) - { - ae_v_muld(&work.ptr.p_double[ki+n], 1, ae_v_len(ki+n,n+n), scl); - } - work.ptr.p_double[j+n] = x.ptr.pp_double[1][1]; - vmax = ae_maxreal(ae_fabs(work.ptr.p_double[j+n], _state), vmax, _state); - vcrit = bignum/vmax; - } - else - { - - /* - * 2-by-2 diagonal block - * - * Scale if necessary to avoid overflow when forming - * the right-hand side. - */ - beta = ae_maxreal(work.ptr.p_double[j], work.ptr.p_double[j+1], _state); - if( ae_fp_greater(beta,vcrit) ) - { - rec = 1/vmax; - ae_v_muld(&work.ptr.p_double[ki+n], 1, ae_v_len(ki+n,n+n), rec); - vmax = (double)(1); - vcrit = bignum; - } - vt = ae_v_dotproduct(&t->ptr.pp_double[ki+1][j], t->stride, &work.ptr.p_double[ki+1+n], 1, ae_v_len(ki+1,j-1)); - work.ptr.p_double[j+n] = work.ptr.p_double[j+n]-vt; - vt = ae_v_dotproduct(&t->ptr.pp_double[ki+1][j+1], t->stride, &work.ptr.p_double[ki+1+n], 1, ae_v_len(ki+1,j-1)); - work.ptr.p_double[j+1+n] = work.ptr.p_double[j+1+n]-vt; - - /* - * Solve - * [T(J,J)-WR T(J,J+1) ]'* X = SCALE*( WORK1 ) - * [T(J+1,J) T(J+1,J+1)-WR] ( WORK2 ) - */ - temp22.ptr.pp_double[1][1] = t->ptr.pp_double[j][j]; - temp22.ptr.pp_double[1][2] = t->ptr.pp_double[j][j+1]; - temp22.ptr.pp_double[2][1] = t->ptr.pp_double[j+1][j]; - temp22.ptr.pp_double[2][2] = t->ptr.pp_double[j+1][j+1]; - temp21b.ptr.pp_double[1][1] = work.ptr.p_double[j+n]; - temp21b.ptr.pp_double[2][1] = work.ptr.p_double[j+1+n]; - evd_internalhsevdlaln2(ae_true, 2, 1, smin, 1.0, &temp22, 1.0, 1.0, &temp21b, wr, (double)(0), &rswap4, &zswap4, &ipivot44, &civ4, &crv4, &x, &scl, &xnorm, &ierr, _state); - - /* - * Scale if necessary - */ - if( ae_fp_neq(scl,(double)(1)) ) - { - ae_v_muld(&work.ptr.p_double[ki+n], 1, ae_v_len(ki+n,n+n), scl); - } - work.ptr.p_double[j+n] = x.ptr.pp_double[1][1]; - work.ptr.p_double[j+1+n] = x.ptr.pp_double[2][1]; - vmax = ae_maxreal(ae_fabs(work.ptr.p_double[j+n], _state), ae_maxreal(ae_fabs(work.ptr.p_double[j+1+n], _state), vmax, _state), _state); - vcrit = bignum/vmax; - } - } - - /* - * Copy the vector x or Q*x to VL and normalize. - */ - if( !over ) - { - ae_v_move(&vl->ptr.pp_double[ki][iis], vl->stride, &work.ptr.p_double[ki+n], 1, ae_v_len(ki,n)); - ii = columnidxabsmax(vl, ki, n, iis, _state); - remax = 1/ae_fabs(vl->ptr.pp_double[ii][iis], _state); - ae_v_muld(&vl->ptr.pp_double[ki][iis], vl->stride, ae_v_len(ki,n), remax); - for(k=1; k<=ki-1; k++) - { - vl->ptr.pp_double[k][iis] = (double)(0); - } - } - else - { - if( kiptr.pp_double[1][ki], vl->stride, ae_v_len(1,n)); - matrixvectormultiply(vl, 1, n, ki+1, n, ae_false, &work, ki+1+n, n+n, 1.0, &temp, 1, n, work.ptr.p_double[ki+n], _state); - ae_v_move(&vl->ptr.pp_double[1][ki], vl->stride, &temp.ptr.p_double[1], 1, ae_v_len(1,n)); - } - ii = columnidxabsmax(vl, 1, n, ki, _state); - remax = 1/ae_fabs(vl->ptr.pp_double[ii][ki], _state); - ae_v_muld(&vl->ptr.pp_double[1][ki], vl->stride, ae_v_len(1,n), remax); - } - } - else - { - - /* - * Complex left eigenvector. - * - * Initial solve: - * ((T(KI,KI) T(KI,KI+1) )' - (WR - I* WI))*X = 0. - * ((T(KI+1,KI) T(KI+1,KI+1)) ) - */ - if( ae_fp_greater_eq(ae_fabs(t->ptr.pp_double[ki][ki+1], _state),ae_fabs(t->ptr.pp_double[ki+1][ki], _state)) ) - { - work.ptr.p_double[ki+n] = wi/t->ptr.pp_double[ki][ki+1]; - work.ptr.p_double[ki+1+n2] = (double)(1); - } - else - { - work.ptr.p_double[ki+n] = (double)(1); - work.ptr.p_double[ki+1+n2] = -wi/t->ptr.pp_double[ki+1][ki]; - } - work.ptr.p_double[ki+1+n] = (double)(0); - work.ptr.p_double[ki+n2] = (double)(0); - - /* - * Form right-hand side - */ - for(k=ki+2; k<=n; k++) - { - work.ptr.p_double[k+n] = -work.ptr.p_double[ki+n]*t->ptr.pp_double[ki][k]; - work.ptr.p_double[k+n2] = -work.ptr.p_double[ki+1+n2]*t->ptr.pp_double[ki+1][k]; - } - - /* - * Solve complex quasi-triangular system: - * ( T(KI+2,N:KI+2,N) - (WR-i*WI) )*X = WORK1+i*WORK2 - */ - vmax = (double)(1); - vcrit = bignum; - jnxt = ki+2; - for(j=ki+2; j<=n; j++) - { - if( jptr.pp_double[j+1][j],(double)(0)) ) - { - j2 = j+1; - jnxt = j+2; - } - } - if( j1==j2 ) - { - - /* - * 1-by-1 diagonal block - * - * Scale if necessary to avoid overflow when - * forming the right-hand side elements. - */ - if( ae_fp_greater(work.ptr.p_double[j],vcrit) ) - { - rec = 1/vmax; - ae_v_muld(&work.ptr.p_double[ki+n], 1, ae_v_len(ki+n,n+n), rec); - ae_v_muld(&work.ptr.p_double[ki+n2], 1, ae_v_len(ki+n2,n+n2), rec); - vmax = (double)(1); - vcrit = bignum; - } - vt = ae_v_dotproduct(&t->ptr.pp_double[ki+2][j], t->stride, &work.ptr.p_double[ki+2+n], 1, ae_v_len(ki+2,j-1)); - work.ptr.p_double[j+n] = work.ptr.p_double[j+n]-vt; - vt = ae_v_dotproduct(&t->ptr.pp_double[ki+2][j], t->stride, &work.ptr.p_double[ki+2+n2], 1, ae_v_len(ki+2,j-1)); - work.ptr.p_double[j+n2] = work.ptr.p_double[j+n2]-vt; - - /* - * Solve (T(J,J)-(WR-i*WI))*(X11+i*X12)= WK+I*WK2 - */ - temp11.ptr.pp_double[1][1] = t->ptr.pp_double[j][j]; - temp12b.ptr.pp_double[1][1] = work.ptr.p_double[j+n]; - temp12b.ptr.pp_double[1][2] = work.ptr.p_double[j+n+n]; - evd_internalhsevdlaln2(ae_false, 1, 2, smin, 1.0, &temp11, 1.0, 1.0, &temp12b, wr, -wi, &rswap4, &zswap4, &ipivot44, &civ4, &crv4, &x, &scl, &xnorm, &ierr, _state); - - /* - * Scale if necessary - */ - if( ae_fp_neq(scl,(double)(1)) ) - { - ae_v_muld(&work.ptr.p_double[ki+n], 1, ae_v_len(ki+n,n+n), scl); - ae_v_muld(&work.ptr.p_double[ki+n2], 1, ae_v_len(ki+n2,n+n2), scl); - } - work.ptr.p_double[j+n] = x.ptr.pp_double[1][1]; - work.ptr.p_double[j+n2] = x.ptr.pp_double[1][2]; - vmax = ae_maxreal(ae_fabs(work.ptr.p_double[j+n], _state), ae_maxreal(ae_fabs(work.ptr.p_double[j+n2], _state), vmax, _state), _state); - vcrit = bignum/vmax; - } - else - { - - /* - * 2-by-2 diagonal block - * - * Scale if necessary to avoid overflow when forming - * the right-hand side elements. - */ - beta = ae_maxreal(work.ptr.p_double[j], work.ptr.p_double[j+1], _state); - if( ae_fp_greater(beta,vcrit) ) - { - rec = 1/vmax; - ae_v_muld(&work.ptr.p_double[ki+n], 1, ae_v_len(ki+n,n+n), rec); - ae_v_muld(&work.ptr.p_double[ki+n2], 1, ae_v_len(ki+n2,n+n2), rec); - vmax = (double)(1); - vcrit = bignum; - } - vt = ae_v_dotproduct(&t->ptr.pp_double[ki+2][j], t->stride, &work.ptr.p_double[ki+2+n], 1, ae_v_len(ki+2,j-1)); - work.ptr.p_double[j+n] = work.ptr.p_double[j+n]-vt; - vt = ae_v_dotproduct(&t->ptr.pp_double[ki+2][j], t->stride, &work.ptr.p_double[ki+2+n2], 1, ae_v_len(ki+2,j-1)); - work.ptr.p_double[j+n2] = work.ptr.p_double[j+n2]-vt; - vt = ae_v_dotproduct(&t->ptr.pp_double[ki+2][j+1], t->stride, &work.ptr.p_double[ki+2+n], 1, ae_v_len(ki+2,j-1)); - work.ptr.p_double[j+1+n] = work.ptr.p_double[j+1+n]-vt; - vt = ae_v_dotproduct(&t->ptr.pp_double[ki+2][j+1], t->stride, &work.ptr.p_double[ki+2+n2], 1, ae_v_len(ki+2,j-1)); - work.ptr.p_double[j+1+n2] = work.ptr.p_double[j+1+n2]-vt; - - /* - * Solve 2-by-2 complex linear equation - * ([T(j,j) T(j,j+1) ]'-(wr-i*wi)*I)*X = SCALE*B - * ([T(j+1,j) T(j+1,j+1)] ) - */ - temp22.ptr.pp_double[1][1] = t->ptr.pp_double[j][j]; - temp22.ptr.pp_double[1][2] = t->ptr.pp_double[j][j+1]; - temp22.ptr.pp_double[2][1] = t->ptr.pp_double[j+1][j]; - temp22.ptr.pp_double[2][2] = t->ptr.pp_double[j+1][j+1]; - temp22b.ptr.pp_double[1][1] = work.ptr.p_double[j+n]; - temp22b.ptr.pp_double[1][2] = work.ptr.p_double[j+n+n]; - temp22b.ptr.pp_double[2][1] = work.ptr.p_double[j+1+n]; - temp22b.ptr.pp_double[2][2] = work.ptr.p_double[j+1+n+n]; - evd_internalhsevdlaln2(ae_true, 2, 2, smin, 1.0, &temp22, 1.0, 1.0, &temp22b, wr, -wi, &rswap4, &zswap4, &ipivot44, &civ4, &crv4, &x, &scl, &xnorm, &ierr, _state); - - /* - * Scale if necessary - */ - if( ae_fp_neq(scl,(double)(1)) ) - { - ae_v_muld(&work.ptr.p_double[ki+n], 1, ae_v_len(ki+n,n+n), scl); - ae_v_muld(&work.ptr.p_double[ki+n2], 1, ae_v_len(ki+n2,n+n2), scl); - } - work.ptr.p_double[j+n] = x.ptr.pp_double[1][1]; - work.ptr.p_double[j+n2] = x.ptr.pp_double[1][2]; - work.ptr.p_double[j+1+n] = x.ptr.pp_double[2][1]; - work.ptr.p_double[j+1+n2] = x.ptr.pp_double[2][2]; - vmax = ae_maxreal(ae_fabs(x.ptr.pp_double[1][1], _state), vmax, _state); - vmax = ae_maxreal(ae_fabs(x.ptr.pp_double[1][2], _state), vmax, _state); - vmax = ae_maxreal(ae_fabs(x.ptr.pp_double[2][1], _state), vmax, _state); - vmax = ae_maxreal(ae_fabs(x.ptr.pp_double[2][2], _state), vmax, _state); - vcrit = bignum/vmax; - } - } - - /* - * Copy the vector x or Q*x to VL and normalize. - */ - if( !over ) - { - ae_v_move(&vl->ptr.pp_double[ki][iis], vl->stride, &work.ptr.p_double[ki+n], 1, ae_v_len(ki,n)); - ae_v_move(&vl->ptr.pp_double[ki][iis+1], vl->stride, &work.ptr.p_double[ki+n2], 1, ae_v_len(ki,n)); - emax = (double)(0); - for(k=ki; k<=n; k++) - { - emax = ae_maxreal(emax, ae_fabs(vl->ptr.pp_double[k][iis], _state)+ae_fabs(vl->ptr.pp_double[k][iis+1], _state), _state); - } - remax = 1/emax; - ae_v_muld(&vl->ptr.pp_double[ki][iis], vl->stride, ae_v_len(ki,n), remax); - ae_v_muld(&vl->ptr.pp_double[ki][iis+1], vl->stride, ae_v_len(ki,n), remax); - for(k=1; k<=ki-1; k++) - { - vl->ptr.pp_double[k][iis] = (double)(0); - vl->ptr.pp_double[k][iis+1] = (double)(0); - } - } - else - { - if( kiptr.pp_double[1][ki], vl->stride, ae_v_len(1,n)); - matrixvectormultiply(vl, 1, n, ki+2, n, ae_false, &work, ki+2+n, n+n, 1.0, &temp, 1, n, work.ptr.p_double[ki+n], _state); - ae_v_move(&vl->ptr.pp_double[1][ki], vl->stride, &temp.ptr.p_double[1], 1, ae_v_len(1,n)); - ae_v_move(&temp.ptr.p_double[1], 1, &vl->ptr.pp_double[1][ki+1], vl->stride, ae_v_len(1,n)); - matrixvectormultiply(vl, 1, n, ki+2, n, ae_false, &work, ki+2+n2, n+n2, 1.0, &temp, 1, n, work.ptr.p_double[ki+1+n2], _state); - ae_v_move(&vl->ptr.pp_double[1][ki+1], vl->stride, &temp.ptr.p_double[1], 1, ae_v_len(1,n)); - } - else - { - vt = work.ptr.p_double[ki+n]; - ae_v_muld(&vl->ptr.pp_double[1][ki], vl->stride, ae_v_len(1,n), vt); - vt = work.ptr.p_double[ki+1+n2]; - ae_v_muld(&vl->ptr.pp_double[1][ki+1], vl->stride, ae_v_len(1,n), vt); - } - emax = (double)(0); - for(k=1; k<=n; k++) - { - emax = ae_maxreal(emax, ae_fabs(vl->ptr.pp_double[k][ki], _state)+ae_fabs(vl->ptr.pp_double[k][ki+1], _state), _state); - } - remax = 1/emax; - ae_v_muld(&vl->ptr.pp_double[1][ki], vl->stride, ae_v_len(1,n), remax); - ae_v_muld(&vl->ptr.pp_double[1][ki+1], vl->stride, ae_v_len(1,n), remax); - } - } - iis = iis+1; - if( ip!=0 ) - { - iis = iis+1; - } - } - if( ip==-1 ) - { - ip = 0; - } - if( ip==1 ) - { - ip = -1; - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -DLALN2 solves a system of the form (ca A - w D ) X = s B -or (ca A' - w D) X = s B with possible scaling ("s") and -perturbation of A. (A' means A-transpose.) - -A is an NA x NA real matrix, ca is a real scalar, D is an NA x NA -real diagonal matrix, w is a real or complex value, and X and B are -NA x 1 matrices -- real if w is real, complex if w is complex. NA -may be 1 or 2. - -If w is complex, X and B are represented as NA x 2 matrices, -the first column of each being the real part and the second -being the imaginary part. - -"s" is a scaling factor (.LE. 1), computed by DLALN2, which is -so chosen that X can be computed without overflow. X is further -scaled if necessary to assure that norm(ca A - w D)*norm(X) is less -than overflow. - -If both singular values of (ca A - w D) are less than SMIN, -SMIN*identity will be used instead of (ca A - w D). If only one -singular value is less than SMIN, one element of (ca A - w D) will be -perturbed enough to make the smallest singular value roughly SMIN. -If both singular values are at least SMIN, (ca A - w D) will not be -perturbed. In any case, the perturbation will be at most some small -multiple of max( SMIN, ulp*norm(ca A - w D) ). The singular values -are computed by infinity-norm approximations, and thus will only be -correct to a factor of 2 or so. - -Note: all input quantities are assumed to be smaller than overflow -by a reasonable factor. (See BIGNUM.) - - -- LAPACK auxiliary routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - October 31, 1992 -*************************************************************************/ -static void evd_internalhsevdlaln2(ae_bool ltrans, - ae_int_t na, - ae_int_t nw, - double smin, - double ca, - /* Real */ ae_matrix* a, - double d1, - double d2, - /* Real */ ae_matrix* b, - double wr, - double wi, - /* Boolean */ ae_vector* rswap4, - /* Boolean */ ae_vector* zswap4, - /* Integer */ ae_matrix* ipivot44, - /* Real */ ae_vector* civ4, - /* Real */ ae_vector* crv4, - /* Real */ ae_matrix* x, - double* scl, - double* xnorm, - ae_int_t* info, - ae_state *_state) -{ - ae_int_t icmax; - ae_int_t j; - double bbnd; - double bi1; - double bi2; - double bignum; - double bnorm; - double br1; - double br2; - double ci21; - double ci22; - double cmax; - double cnorm; - double cr21; - double cr22; - double csi; - double csr; - double li21; - double lr21; - double smini; - double smlnum; - double temp; - double u22abs; - double ui11; - double ui11r; - double ui12; - double ui12s; - double ui22; - double ur11; - double ur11r; - double ur12; - double ur12s; - double ur22; - double xi1; - double xi2; - double xr1; - double xr2; - double tmp1; - double tmp2; - - *scl = 0; - *xnorm = 0; - *info = 0; - - zswap4->ptr.p_bool[1] = ae_false; - zswap4->ptr.p_bool[2] = ae_false; - zswap4->ptr.p_bool[3] = ae_true; - zswap4->ptr.p_bool[4] = ae_true; - rswap4->ptr.p_bool[1] = ae_false; - rswap4->ptr.p_bool[2] = ae_true; - rswap4->ptr.p_bool[3] = ae_false; - rswap4->ptr.p_bool[4] = ae_true; - ipivot44->ptr.pp_int[1][1] = 1; - ipivot44->ptr.pp_int[2][1] = 2; - ipivot44->ptr.pp_int[3][1] = 3; - ipivot44->ptr.pp_int[4][1] = 4; - ipivot44->ptr.pp_int[1][2] = 2; - ipivot44->ptr.pp_int[2][2] = 1; - ipivot44->ptr.pp_int[3][2] = 4; - ipivot44->ptr.pp_int[4][2] = 3; - ipivot44->ptr.pp_int[1][3] = 3; - ipivot44->ptr.pp_int[2][3] = 4; - ipivot44->ptr.pp_int[3][3] = 1; - ipivot44->ptr.pp_int[4][3] = 2; - ipivot44->ptr.pp_int[1][4] = 4; - ipivot44->ptr.pp_int[2][4] = 3; - ipivot44->ptr.pp_int[3][4] = 2; - ipivot44->ptr.pp_int[4][4] = 1; - smlnum = 2*ae_minrealnumber; - bignum = 1/smlnum; - smini = ae_maxreal(smin, smlnum, _state); - - /* - * Don't check for input errors - */ - *info = 0; - - /* - * Standard Initializations - */ - *scl = (double)(1); - if( na==1 ) - { - - /* - * 1 x 1 (i.e., scalar) system C X = B - */ - if( nw==1 ) - { - - /* - * Real 1x1 system. - * - * C = ca A - w D - */ - csr = ca*a->ptr.pp_double[1][1]-wr*d1; - cnorm = ae_fabs(csr, _state); - - /* - * If | C | < SMINI, use C = SMINI - */ - if( ae_fp_less(cnorm,smini) ) - { - csr = smini; - cnorm = smini; - *info = 1; - } - - /* - * Check scaling for X = B / C - */ - bnorm = ae_fabs(b->ptr.pp_double[1][1], _state); - if( ae_fp_less(cnorm,(double)(1))&&ae_fp_greater(bnorm,(double)(1)) ) - { - if( ae_fp_greater(bnorm,bignum*cnorm) ) - { - *scl = 1/bnorm; - } - } - - /* - * Compute X - */ - x->ptr.pp_double[1][1] = b->ptr.pp_double[1][1]*(*scl)/csr; - *xnorm = ae_fabs(x->ptr.pp_double[1][1], _state); - } - else - { - - /* - * Complex 1x1 system (w is complex) - * - * C = ca A - w D - */ - csr = ca*a->ptr.pp_double[1][1]-wr*d1; - csi = -wi*d1; - cnorm = ae_fabs(csr, _state)+ae_fabs(csi, _state); - - /* - * If | C | < SMINI, use C = SMINI - */ - if( ae_fp_less(cnorm,smini) ) - { - csr = smini; - csi = (double)(0); - cnorm = smini; - *info = 1; - } - - /* - * Check scaling for X = B / C - */ - bnorm = ae_fabs(b->ptr.pp_double[1][1], _state)+ae_fabs(b->ptr.pp_double[1][2], _state); - if( ae_fp_less(cnorm,(double)(1))&&ae_fp_greater(bnorm,(double)(1)) ) - { - if( ae_fp_greater(bnorm,bignum*cnorm) ) - { - *scl = 1/bnorm; - } - } - - /* - * Compute X - */ - evd_internalhsevdladiv(*scl*b->ptr.pp_double[1][1], *scl*b->ptr.pp_double[1][2], csr, csi, &tmp1, &tmp2, _state); - x->ptr.pp_double[1][1] = tmp1; - x->ptr.pp_double[1][2] = tmp2; - *xnorm = ae_fabs(x->ptr.pp_double[1][1], _state)+ae_fabs(x->ptr.pp_double[1][2], _state); - } - } - else - { - - /* - * 2x2 System - * - * Compute the real part of C = ca A - w D (or ca A' - w D ) - */ - crv4->ptr.p_double[1+0] = ca*a->ptr.pp_double[1][1]-wr*d1; - crv4->ptr.p_double[2+2] = ca*a->ptr.pp_double[2][2]-wr*d2; - if( ltrans ) - { - crv4->ptr.p_double[1+2] = ca*a->ptr.pp_double[2][1]; - crv4->ptr.p_double[2+0] = ca*a->ptr.pp_double[1][2]; - } - else - { - crv4->ptr.p_double[2+0] = ca*a->ptr.pp_double[2][1]; - crv4->ptr.p_double[1+2] = ca*a->ptr.pp_double[1][2]; - } - if( nw==1 ) - { - - /* - * Real 2x2 system (w is real) - * - * Find the largest element in C - */ - cmax = (double)(0); - icmax = 0; - for(j=1; j<=4; j++) - { - if( ae_fp_greater(ae_fabs(crv4->ptr.p_double[j], _state),cmax) ) - { - cmax = ae_fabs(crv4->ptr.p_double[j], _state); - icmax = j; - } - } - - /* - * If norm(C) < SMINI, use SMINI*identity. - */ - if( ae_fp_less(cmax,smini) ) - { - bnorm = ae_maxreal(ae_fabs(b->ptr.pp_double[1][1], _state), ae_fabs(b->ptr.pp_double[2][1], _state), _state); - if( ae_fp_less(smini,(double)(1))&&ae_fp_greater(bnorm,(double)(1)) ) - { - if( ae_fp_greater(bnorm,bignum*smini) ) - { - *scl = 1/bnorm; - } - } - temp = *scl/smini; - x->ptr.pp_double[1][1] = temp*b->ptr.pp_double[1][1]; - x->ptr.pp_double[2][1] = temp*b->ptr.pp_double[2][1]; - *xnorm = temp*bnorm; - *info = 1; - return; - } - - /* - * Gaussian elimination with complete pivoting. - */ - ur11 = crv4->ptr.p_double[icmax]; - cr21 = crv4->ptr.p_double[ipivot44->ptr.pp_int[2][icmax]]; - ur12 = crv4->ptr.p_double[ipivot44->ptr.pp_int[3][icmax]]; - cr22 = crv4->ptr.p_double[ipivot44->ptr.pp_int[4][icmax]]; - ur11r = 1/ur11; - lr21 = ur11r*cr21; - ur22 = cr22-ur12*lr21; - - /* - * If smaller pivot < SMINI, use SMINI - */ - if( ae_fp_less(ae_fabs(ur22, _state),smini) ) - { - ur22 = smini; - *info = 1; - } - if( rswap4->ptr.p_bool[icmax] ) - { - br1 = b->ptr.pp_double[2][1]; - br2 = b->ptr.pp_double[1][1]; - } - else - { - br1 = b->ptr.pp_double[1][1]; - br2 = b->ptr.pp_double[2][1]; - } - br2 = br2-lr21*br1; - bbnd = ae_maxreal(ae_fabs(br1*(ur22*ur11r), _state), ae_fabs(br2, _state), _state); - if( ae_fp_greater(bbnd,(double)(1))&&ae_fp_less(ae_fabs(ur22, _state),(double)(1)) ) - { - if( ae_fp_greater_eq(bbnd,bignum*ae_fabs(ur22, _state)) ) - { - *scl = 1/bbnd; - } - } - xr2 = br2*(*scl)/ur22; - xr1 = *scl*br1*ur11r-xr2*(ur11r*ur12); - if( zswap4->ptr.p_bool[icmax] ) - { - x->ptr.pp_double[1][1] = xr2; - x->ptr.pp_double[2][1] = xr1; - } - else - { - x->ptr.pp_double[1][1] = xr1; - x->ptr.pp_double[2][1] = xr2; - } - *xnorm = ae_maxreal(ae_fabs(xr1, _state), ae_fabs(xr2, _state), _state); - - /* - * Further scaling if norm(A) norm(X) > overflow - */ - if( ae_fp_greater(*xnorm,(double)(1))&&ae_fp_greater(cmax,(double)(1)) ) - { - if( ae_fp_greater(*xnorm,bignum/cmax) ) - { - temp = cmax/bignum; - x->ptr.pp_double[1][1] = temp*x->ptr.pp_double[1][1]; - x->ptr.pp_double[2][1] = temp*x->ptr.pp_double[2][1]; - *xnorm = temp*(*xnorm); - *scl = temp*(*scl); - } - } - } - else - { - - /* - * Complex 2x2 system (w is complex) - * - * Find the largest element in C - */ - civ4->ptr.p_double[1+0] = -wi*d1; - civ4->ptr.p_double[2+0] = (double)(0); - civ4->ptr.p_double[1+2] = (double)(0); - civ4->ptr.p_double[2+2] = -wi*d2; - cmax = (double)(0); - icmax = 0; - for(j=1; j<=4; j++) - { - if( ae_fp_greater(ae_fabs(crv4->ptr.p_double[j], _state)+ae_fabs(civ4->ptr.p_double[j], _state),cmax) ) - { - cmax = ae_fabs(crv4->ptr.p_double[j], _state)+ae_fabs(civ4->ptr.p_double[j], _state); - icmax = j; - } - } - - /* - * If norm(C) < SMINI, use SMINI*identity. - */ - if( ae_fp_less(cmax,smini) ) - { - bnorm = ae_maxreal(ae_fabs(b->ptr.pp_double[1][1], _state)+ae_fabs(b->ptr.pp_double[1][2], _state), ae_fabs(b->ptr.pp_double[2][1], _state)+ae_fabs(b->ptr.pp_double[2][2], _state), _state); - if( ae_fp_less(smini,(double)(1))&&ae_fp_greater(bnorm,(double)(1)) ) - { - if( ae_fp_greater(bnorm,bignum*smini) ) - { - *scl = 1/bnorm; - } - } - temp = *scl/smini; - x->ptr.pp_double[1][1] = temp*b->ptr.pp_double[1][1]; - x->ptr.pp_double[2][1] = temp*b->ptr.pp_double[2][1]; - x->ptr.pp_double[1][2] = temp*b->ptr.pp_double[1][2]; - x->ptr.pp_double[2][2] = temp*b->ptr.pp_double[2][2]; - *xnorm = temp*bnorm; - *info = 1; - return; - } - - /* - * Gaussian elimination with complete pivoting. - */ - ur11 = crv4->ptr.p_double[icmax]; - ui11 = civ4->ptr.p_double[icmax]; - cr21 = crv4->ptr.p_double[ipivot44->ptr.pp_int[2][icmax]]; - ci21 = civ4->ptr.p_double[ipivot44->ptr.pp_int[2][icmax]]; - ur12 = crv4->ptr.p_double[ipivot44->ptr.pp_int[3][icmax]]; - ui12 = civ4->ptr.p_double[ipivot44->ptr.pp_int[3][icmax]]; - cr22 = crv4->ptr.p_double[ipivot44->ptr.pp_int[4][icmax]]; - ci22 = civ4->ptr.p_double[ipivot44->ptr.pp_int[4][icmax]]; - if( icmax==1||icmax==4 ) - { - - /* - * Code when off-diagonals of pivoted C are real - */ - if( ae_fp_greater(ae_fabs(ur11, _state),ae_fabs(ui11, _state)) ) - { - temp = ui11/ur11; - ur11r = 1/(ur11*(1+ae_sqr(temp, _state))); - ui11r = -temp*ur11r; - } - else - { - temp = ur11/ui11; - ui11r = -1/(ui11*(1+ae_sqr(temp, _state))); - ur11r = -temp*ui11r; - } - lr21 = cr21*ur11r; - li21 = cr21*ui11r; - ur12s = ur12*ur11r; - ui12s = ur12*ui11r; - ur22 = cr22-ur12*lr21; - ui22 = ci22-ur12*li21; - } - else - { - - /* - * Code when diagonals of pivoted C are real - */ - ur11r = 1/ur11; - ui11r = (double)(0); - lr21 = cr21*ur11r; - li21 = ci21*ur11r; - ur12s = ur12*ur11r; - ui12s = ui12*ur11r; - ur22 = cr22-ur12*lr21+ui12*li21; - ui22 = -ur12*li21-ui12*lr21; - } - u22abs = ae_fabs(ur22, _state)+ae_fabs(ui22, _state); - - /* - * If smaller pivot < SMINI, use SMINI - */ - if( ae_fp_less(u22abs,smini) ) - { - ur22 = smini; - ui22 = (double)(0); - *info = 1; - } - if( rswap4->ptr.p_bool[icmax] ) - { - br2 = b->ptr.pp_double[1][1]; - br1 = b->ptr.pp_double[2][1]; - bi2 = b->ptr.pp_double[1][2]; - bi1 = b->ptr.pp_double[2][2]; - } - else - { - br1 = b->ptr.pp_double[1][1]; - br2 = b->ptr.pp_double[2][1]; - bi1 = b->ptr.pp_double[1][2]; - bi2 = b->ptr.pp_double[2][2]; - } - br2 = br2-lr21*br1+li21*bi1; - bi2 = bi2-li21*br1-lr21*bi1; - bbnd = ae_maxreal((ae_fabs(br1, _state)+ae_fabs(bi1, _state))*(u22abs*(ae_fabs(ur11r, _state)+ae_fabs(ui11r, _state))), ae_fabs(br2, _state)+ae_fabs(bi2, _state), _state); - if( ae_fp_greater(bbnd,(double)(1))&&ae_fp_less(u22abs,(double)(1)) ) - { - if( ae_fp_greater_eq(bbnd,bignum*u22abs) ) - { - *scl = 1/bbnd; - br1 = *scl*br1; - bi1 = *scl*bi1; - br2 = *scl*br2; - bi2 = *scl*bi2; - } - } - evd_internalhsevdladiv(br2, bi2, ur22, ui22, &xr2, &xi2, _state); - xr1 = ur11r*br1-ui11r*bi1-ur12s*xr2+ui12s*xi2; - xi1 = ui11r*br1+ur11r*bi1-ui12s*xr2-ur12s*xi2; - if( zswap4->ptr.p_bool[icmax] ) - { - x->ptr.pp_double[1][1] = xr2; - x->ptr.pp_double[2][1] = xr1; - x->ptr.pp_double[1][2] = xi2; - x->ptr.pp_double[2][2] = xi1; - } - else - { - x->ptr.pp_double[1][1] = xr1; - x->ptr.pp_double[2][1] = xr2; - x->ptr.pp_double[1][2] = xi1; - x->ptr.pp_double[2][2] = xi2; - } - *xnorm = ae_maxreal(ae_fabs(xr1, _state)+ae_fabs(xi1, _state), ae_fabs(xr2, _state)+ae_fabs(xi2, _state), _state); - - /* - * Further scaling if norm(A) norm(X) > overflow - */ - if( ae_fp_greater(*xnorm,(double)(1))&&ae_fp_greater(cmax,(double)(1)) ) - { - if( ae_fp_greater(*xnorm,bignum/cmax) ) - { - temp = cmax/bignum; - x->ptr.pp_double[1][1] = temp*x->ptr.pp_double[1][1]; - x->ptr.pp_double[2][1] = temp*x->ptr.pp_double[2][1]; - x->ptr.pp_double[1][2] = temp*x->ptr.pp_double[1][2]; - x->ptr.pp_double[2][2] = temp*x->ptr.pp_double[2][2]; - *xnorm = temp*(*xnorm); - *scl = temp*(*scl); - } - } - } - } -} - - -/************************************************************************* -performs complex division in real arithmetic - - a + i*b - p + i*q = --------- - c + i*d - -The algorithm is due to Robert L. Smith and can be found -in D. Knuth, The art of Computer Programming, Vol.2, p.195 - - -- LAPACK auxiliary routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - October 31, 1992 -*************************************************************************/ -static void evd_internalhsevdladiv(double a, - double b, - double c, - double d, - double* p, - double* q, - ae_state *_state) -{ - double e; - double f; - - *p = 0; - *q = 0; - - if( ae_fp_less(ae_fabs(d, _state),ae_fabs(c, _state)) ) - { - e = d/c; - f = c+d*e; - *p = (a+b*e)/f; - *q = (b-a*e)/f; - } - else - { - e = c/d; - f = d+c*e; - *p = (b+a*e)/f; - *q = (-a+b*e)/f; - } -} - - -void _eigsubspacestate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - eigsubspacestate *p = (eigsubspacestate*)_p; - ae_touch_ptr((void*)p); - _hqrndstate_init(&p->rs, _state, make_automatic); - ae_vector_init(&p->tau, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->q0, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->qcur, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->qnew, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->znew, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->r, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->rz, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->tz, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->rq, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->dummy, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rw, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tw, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->wcur, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->wprev, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->wrank, 0, DT_REAL, _state, make_automatic); - _apbuffers_init(&p->buf, _state, make_automatic); - ae_matrix_init(&p->x, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->ax, 0, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); -} - - -void _eigsubspacestate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - eigsubspacestate *dst = (eigsubspacestate*)_dst; - eigsubspacestate *src = (eigsubspacestate*)_src; - dst->n = src->n; - dst->k = src->k; - dst->nwork = src->nwork; - dst->maxits = src->maxits; - dst->eps = src->eps; - dst->eigenvectorsneeded = src->eigenvectorsneeded; - dst->matrixtype = src->matrixtype; - dst->usewarmstart = src->usewarmstart; - dst->firstcall = src->firstcall; - _hqrndstate_init_copy(&dst->rs, &src->rs, _state, make_automatic); - dst->running = src->running; - ae_vector_init_copy(&dst->tau, &src->tau, _state, make_automatic); - ae_matrix_init_copy(&dst->q0, &src->q0, _state, make_automatic); - ae_matrix_init_copy(&dst->qcur, &src->qcur, _state, make_automatic); - ae_matrix_init_copy(&dst->qnew, &src->qnew, _state, make_automatic); - ae_matrix_init_copy(&dst->znew, &src->znew, _state, make_automatic); - ae_matrix_init_copy(&dst->r, &src->r, _state, make_automatic); - ae_matrix_init_copy(&dst->rz, &src->rz, _state, make_automatic); - ae_matrix_init_copy(&dst->tz, &src->tz, _state, make_automatic); - ae_matrix_init_copy(&dst->rq, &src->rq, _state, make_automatic); - ae_matrix_init_copy(&dst->dummy, &src->dummy, _state, make_automatic); - ae_vector_init_copy(&dst->rw, &src->rw, _state, make_automatic); - ae_vector_init_copy(&dst->tw, &src->tw, _state, make_automatic); - ae_vector_init_copy(&dst->wcur, &src->wcur, _state, make_automatic); - ae_vector_init_copy(&dst->wprev, &src->wprev, _state, make_automatic); - ae_vector_init_copy(&dst->wrank, &src->wrank, _state, make_automatic); - _apbuffers_init_copy(&dst->buf, &src->buf, _state, make_automatic); - ae_matrix_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_matrix_init_copy(&dst->ax, &src->ax, _state, make_automatic); - dst->requesttype = src->requesttype; - dst->requestsize = src->requestsize; - dst->repiterationscount = src->repiterationscount; - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); -} - - -void _eigsubspacestate_clear(void* _p) -{ - eigsubspacestate *p = (eigsubspacestate*)_p; - ae_touch_ptr((void*)p); - _hqrndstate_clear(&p->rs); - ae_vector_clear(&p->tau); - ae_matrix_clear(&p->q0); - ae_matrix_clear(&p->qcur); - ae_matrix_clear(&p->qnew); - ae_matrix_clear(&p->znew); - ae_matrix_clear(&p->r); - ae_matrix_clear(&p->rz); - ae_matrix_clear(&p->tz); - ae_matrix_clear(&p->rq); - ae_matrix_clear(&p->dummy); - ae_vector_clear(&p->rw); - ae_vector_clear(&p->tw); - ae_vector_clear(&p->wcur); - ae_vector_clear(&p->wprev); - ae_vector_clear(&p->wrank); - _apbuffers_clear(&p->buf); - ae_matrix_clear(&p->x); - ae_matrix_clear(&p->ax); - _rcommstate_clear(&p->rstate); -} - - -void _eigsubspacestate_destroy(void* _p) -{ - eigsubspacestate *p = (eigsubspacestate*)_p; - ae_touch_ptr((void*)p); - _hqrndstate_destroy(&p->rs); - ae_vector_destroy(&p->tau); - ae_matrix_destroy(&p->q0); - ae_matrix_destroy(&p->qcur); - ae_matrix_destroy(&p->qnew); - ae_matrix_destroy(&p->znew); - ae_matrix_destroy(&p->r); - ae_matrix_destroy(&p->rz); - ae_matrix_destroy(&p->tz); - ae_matrix_destroy(&p->rq); - ae_matrix_destroy(&p->dummy); - ae_vector_destroy(&p->rw); - ae_vector_destroy(&p->tw); - ae_vector_destroy(&p->wcur); - ae_vector_destroy(&p->wprev); - ae_vector_destroy(&p->wrank); - _apbuffers_destroy(&p->buf); - ae_matrix_destroy(&p->x); - ae_matrix_destroy(&p->ax); - _rcommstate_destroy(&p->rstate); -} - - -void _eigsubspacereport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - eigsubspacereport *p = (eigsubspacereport*)_p; - ae_touch_ptr((void*)p); -} - - -void _eigsubspacereport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - eigsubspacereport *dst = (eigsubspacereport*)_dst; - eigsubspacereport *src = (eigsubspacereport*)_src; - dst->iterationscount = src->iterationscount; -} - - -void _eigsubspacereport_clear(void* _p) -{ - eigsubspacereport *p = (eigsubspacereport*)_p; - ae_touch_ptr((void*)p); -} - - -void _eigsubspacereport_destroy(void* _p) -{ - eigsubspacereport *p = (eigsubspacereport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_SCHUR) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Subroutine performing the Schur decomposition of a general matrix by using -the QR algorithm with multiple shifts. - -COMMERCIAL EDITION OF ALGLIB: - - ! Commercial version of ALGLIB includes one important improvement of - ! this function, which can be used from C++ and C#: - ! * Intel MKL support (lightweight Intel MKL is shipped with ALGLIB) - ! - ! Intel MKL gives approximately constant (with respect to number of - ! worker threads) acceleration factor which depends on CPU being used, - ! problem size and "baseline" ALGLIB edition which is used for - ! comparison. - ! - ! Multithreaded acceleration is NOT supported for this function. - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -The source matrix A is represented as S'*A*S = T, where S is an orthogonal -matrix (Schur vectors), T - upper quasi-triangular matrix (with blocks of -sizes 1x1 and 2x2 on the main diagonal). - -Input parameters: - A - matrix to be decomposed. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of A, N>=0. - - -Output parameters: - A - contains matrix T. - Array whose indexes range within [0..N-1, 0..N-1]. - S - contains Schur vectors. - Array whose indexes range within [0..N-1, 0..N-1]. - -Note 1: - The block structure of matrix T can be easily recognized: since all - the elements below the blocks are zeros, the elements a[i+1,i] which - are equal to 0 show the block border. - -Note 2: - The algorithm performance depends on the value of the internal parameter - NS of the InternalSchurDecomposition subroutine which defines the number - of shifts in the QR algorithm (similarly to the block width in block-matrix - algorithms in linear algebra). If you require maximum performance on - your machine, it is recommended to adjust this parameter manually. - -Result: - True, - if the algorithm has converged and parameters A and S contain the result. - False, - if the algorithm has not converged. - -Algorithm implemented on the basis of the DHSEQR subroutine (LAPACK 3.0 library). -*************************************************************************/ -ae_bool rmatrixschur(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_matrix* s, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector tau; - ae_vector wi; - ae_vector wr; - ae_int_t info; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&tau, 0, sizeof(tau)); - memset(&wi, 0, sizeof(wi)); - memset(&wr, 0, sizeof(wr)); - ae_matrix_clear(s); - ae_vector_init(&tau, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wi, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wr, 0, DT_REAL, _state, ae_true); - - - /* - * Upper Hessenberg form of the 0-based matrix - */ - rmatrixhessenberg(a, n, &tau, _state); - rmatrixhessenbergunpackq(a, n, &tau, s, _state); - - /* - * Schur decomposition - */ - rmatrixinternalschurdecomposition(a, n, 1, 1, &wr, &wi, s, &info, _state); - result = info==0; - ae_frame_leave(_state); - return result; -} - - -#endif -#if defined(AE_COMPILE_SPDGEVD) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Algorithm for solving the following generalized symmetric positive-definite -eigenproblem: - A*x = lambda*B*x (1) or - A*B*x = lambda*x (2) or - B*A*x = lambda*x (3). -where A is a symmetric matrix, B - symmetric positive-definite matrix. -The problem is solved by reducing it to an ordinary symmetric eigenvalue -problem. - -Input parameters: - A - symmetric matrix which is given by its upper or lower - triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrices A and B. - IsUpperA - storage format of matrix A. - B - symmetric positive-definite matrix which is given by - its upper or lower triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - IsUpperB - storage format of matrix B. - ZNeeded - if ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - ProblemType - if ProblemType is equal to: - * 1, the following problem is solved: A*x = lambda*B*x; - * 2, the following problem is solved: A*B*x = lambda*x; - * 3, the following problem is solved: B*A*x = lambda*x. - -Output parameters: - D - eigenvalues in ascending order. - Array whose index ranges within [0..N-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains eigenvectors. - Array whose indexes range within [0..N-1, 0..N-1]. - The eigenvectors are stored in matrix columns. It should - be noted that the eigenvectors in such problems do not - form an orthogonal system. - -Result: - True, if the problem was solved successfully. - False, if the error occurred during the Cholesky decomposition of matrix - B (the matrix isn't positive-definite) or during the work of the iterative - algorithm for solving the symmetric eigenproblem. - -See also the GeneralizedSymmetricDefiniteEVDReduce subroutine. - - -- ALGLIB -- - Copyright 1.28.2006 by Bochkanov Sergey -*************************************************************************/ -ae_bool smatrixgevd(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isuppera, - /* Real */ ae_matrix* b, - ae_bool isupperb, - ae_int_t zneeded, - ae_int_t problemtype, - /* Real */ ae_vector* d, - /* Real */ ae_matrix* z, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_matrix r; - ae_matrix t; - ae_bool isupperr; - ae_int_t j1; - ae_int_t j2; - ae_int_t j1inc; - ae_int_t j2inc; - ae_int_t i; - ae_int_t j; - double v; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&r, 0, sizeof(r)); - memset(&t, 0, sizeof(t)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_vector_clear(d); - ae_matrix_clear(z); - ae_matrix_init(&r, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&t, 0, 0, DT_REAL, _state, ae_true); - - - /* - * Reduce and solve - */ - result = smatrixgevdreduce(a, n, isuppera, b, isupperb, problemtype, &r, &isupperr, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - result = smatrixevd(a, n, zneeded, isuppera, d, &t, _state); - if( !result ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Transform eigenvectors if needed - */ - if( zneeded!=0 ) - { - - /* - * fill Z with zeros - */ - ae_matrix_set_length(z, n-1+1, n-1+1, _state); - for(j=0; j<=n-1; j++) - { - z->ptr.pp_double[0][j] = 0.0; - } - for(i=1; i<=n-1; i++) - { - ae_v_move(&z->ptr.pp_double[i][0], 1, &z->ptr.pp_double[0][0], 1, ae_v_len(0,n-1)); - } - - /* - * Setup R properties - */ - if( isupperr ) - { - j1 = 0; - j2 = n-1; - j1inc = 1; - j2inc = 0; - } - else - { - j1 = 0; - j2 = 0; - j1inc = 0; - j2inc = 1; - } - - /* - * Calculate R*Z - */ - for(i=0; i<=n-1; i++) - { - for(j=j1; j<=j2; j++) - { - v = r.ptr.pp_double[i][j]; - ae_v_addd(&z->ptr.pp_double[i][0], 1, &t.ptr.pp_double[j][0], 1, ae_v_len(0,n-1), v); - } - j1 = j1+j1inc; - j2 = j2+j2inc; - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Algorithm for reduction of the following generalized symmetric positive- -definite eigenvalue problem: - A*x = lambda*B*x (1) or - A*B*x = lambda*x (2) or - B*A*x = lambda*x (3) -to the symmetric eigenvalues problem C*y = lambda*y (eigenvalues of this and -the given problems are the same, and the eigenvectors of the given problem -could be obtained by multiplying the obtained eigenvectors by the -transformation matrix x = R*y). - -Here A is a symmetric matrix, B - symmetric positive-definite matrix. - -Input parameters: - A - symmetric matrix which is given by its upper or lower - triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrices A and B. - IsUpperA - storage format of matrix A. - B - symmetric positive-definite matrix which is given by - its upper or lower triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - IsUpperB - storage format of matrix B. - ProblemType - if ProblemType is equal to: - * 1, the following problem is solved: A*x = lambda*B*x; - * 2, the following problem is solved: A*B*x = lambda*x; - * 3, the following problem is solved: B*A*x = lambda*x. - -Output parameters: - A - symmetric matrix which is given by its upper or lower - triangle depending on IsUpperA. Contains matrix C. - Array whose indexes range within [0..N-1, 0..N-1]. - R - upper triangular or low triangular transformation matrix - which is used to obtain the eigenvectors of a given problem - as the product of eigenvectors of C (from the right) and - matrix R (from the left). If the matrix is upper - triangular, the elements below the main diagonal - are equal to 0 (and vice versa). Thus, we can perform - the multiplication without taking into account the - internal structure (which is an easier though less - effective way). - Array whose indexes range within [0..N-1, 0..N-1]. - IsUpperR - type of matrix R (upper or lower triangular). - -Result: - True, if the problem was reduced successfully. - False, if the error occurred during the Cholesky decomposition of - matrix B (the matrix is not positive-definite). - - -- ALGLIB -- - Copyright 1.28.2006 by Bochkanov Sergey -*************************************************************************/ -ae_bool smatrixgevdreduce(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isuppera, - /* Real */ ae_matrix* b, - ae_bool isupperb, - ae_int_t problemtype, - /* Real */ ae_matrix* r, - ae_bool* isupperr, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix t; - ae_vector w1; - ae_vector w2; - ae_vector w3; - ae_int_t i; - ae_int_t j; - double v; - matinvreport rep; - ae_int_t info; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&t, 0, sizeof(t)); - memset(&w1, 0, sizeof(w1)); - memset(&w2, 0, sizeof(w2)); - memset(&w3, 0, sizeof(w3)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_clear(r); - *isupperr = ae_false; - ae_matrix_init(&t, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w3, 0, DT_REAL, _state, ae_true); - _matinvreport_init(&rep, _state, ae_true); - - ae_assert(n>0, "SMatrixGEVDReduce: N<=0!", _state); - ae_assert((problemtype==1||problemtype==2)||problemtype==3, "SMatrixGEVDReduce: incorrect ProblemType!", _state); - result = ae_true; - - /* - * Problem 1: A*x = lambda*B*x - * - * Reducing to: - * C*y = lambda*y - * C = L^(-1) * A * L^(-T) - * x = L^(-T) * y - */ - if( problemtype==1 ) - { - - /* - * Factorize B in T: B = LL' - */ - ae_matrix_set_length(&t, n-1+1, n-1+1, _state); - if( isupperb ) - { - for(i=0; i<=n-1; i++) - { - ae_v_move(&t.ptr.pp_double[i][i], t.stride, &b->ptr.pp_double[i][i], 1, ae_v_len(i,n-1)); - } - } - else - { - for(i=0; i<=n-1; i++) - { - ae_v_move(&t.ptr.pp_double[i][0], 1, &b->ptr.pp_double[i][0], 1, ae_v_len(0,i)); - } - } - if( !spdmatrixcholesky(&t, n, ae_false, _state) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - - /* - * Invert L in T - */ - rmatrixtrinverse(&t, n, ae_false, ae_false, &info, &rep, _state); - if( info<=0 ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - - /* - * Build L^(-1) * A * L^(-T) in R - */ - ae_vector_set_length(&w1, n+1, _state); - ae_vector_set_length(&w2, n+1, _state); - ae_matrix_set_length(r, n-1+1, n-1+1, _state); - for(j=1; j<=n; j++) - { - - /* - * Form w2 = A * l'(j) (here l'(j) is j-th column of L^(-T)) - */ - ae_v_move(&w1.ptr.p_double[1], 1, &t.ptr.pp_double[j-1][0], 1, ae_v_len(1,j)); - symmetricmatrixvectormultiply(a, isuppera, 0, j-1, &w1, 1.0, &w2, _state); - if( isuppera ) - { - matrixvectormultiply(a, 0, j-1, j, n-1, ae_true, &w1, 1, j, 1.0, &w2, j+1, n, 0.0, _state); - } - else - { - matrixvectormultiply(a, j, n-1, 0, j-1, ae_false, &w1, 1, j, 1.0, &w2, j+1, n, 0.0, _state); - } - - /* - * Form l(i)*w2 (here l(i) is i-th row of L^(-1)) - */ - for(i=1; i<=n; i++) - { - v = ae_v_dotproduct(&t.ptr.pp_double[i-1][0], 1, &w2.ptr.p_double[1], 1, ae_v_len(0,i-1)); - r->ptr.pp_double[i-1][j-1] = v; - } - } - - /* - * Copy R to A - */ - for(i=0; i<=n-1; i++) - { - ae_v_move(&a->ptr.pp_double[i][0], 1, &r->ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - } - - /* - * Copy L^(-1) from T to R and transpose - */ - *isupperr = ae_true; - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i-1; j++) - { - r->ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=n-1; i++) - { - ae_v_move(&r->ptr.pp_double[i][i], 1, &t.ptr.pp_double[i][i], t.stride, ae_v_len(i,n-1)); - } - ae_frame_leave(_state); - return result; - } - - /* - * Problem 2: A*B*x = lambda*x - * or - * problem 3: B*A*x = lambda*x - * - * Reducing to: - * C*y = lambda*y - * C = U * A * U' - * B = U'* U - */ - if( problemtype==2||problemtype==3 ) - { - - /* - * Factorize B in T: B = U'*U - */ - ae_matrix_set_length(&t, n-1+1, n-1+1, _state); - if( isupperb ) - { - for(i=0; i<=n-1; i++) - { - ae_v_move(&t.ptr.pp_double[i][i], 1, &b->ptr.pp_double[i][i], 1, ae_v_len(i,n-1)); - } - } - else - { - for(i=0; i<=n-1; i++) - { - ae_v_move(&t.ptr.pp_double[i][i], 1, &b->ptr.pp_double[i][i], b->stride, ae_v_len(i,n-1)); - } - } - if( !spdmatrixcholesky(&t, n, ae_true, _state) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - - /* - * Build U * A * U' in R - */ - ae_vector_set_length(&w1, n+1, _state); - ae_vector_set_length(&w2, n+1, _state); - ae_vector_set_length(&w3, n+1, _state); - ae_matrix_set_length(r, n-1+1, n-1+1, _state); - for(j=1; j<=n; j++) - { - - /* - * Form w2 = A * u'(j) (here u'(j) is j-th column of U') - */ - ae_v_move(&w1.ptr.p_double[1], 1, &t.ptr.pp_double[j-1][j-1], 1, ae_v_len(1,n-j+1)); - symmetricmatrixvectormultiply(a, isuppera, j-1, n-1, &w1, 1.0, &w3, _state); - ae_v_move(&w2.ptr.p_double[j], 1, &w3.ptr.p_double[1], 1, ae_v_len(j,n)); - ae_v_move(&w1.ptr.p_double[j], 1, &t.ptr.pp_double[j-1][j-1], 1, ae_v_len(j,n)); - if( isuppera ) - { - matrixvectormultiply(a, 0, j-2, j-1, n-1, ae_false, &w1, j, n, 1.0, &w2, 1, j-1, 0.0, _state); - } - else - { - matrixvectormultiply(a, j-1, n-1, 0, j-2, ae_true, &w1, j, n, 1.0, &w2, 1, j-1, 0.0, _state); - } - - /* - * Form u(i)*w2 (here u(i) is i-th row of U) - */ - for(i=1; i<=n; i++) - { - v = ae_v_dotproduct(&t.ptr.pp_double[i-1][i-1], 1, &w2.ptr.p_double[i], 1, ae_v_len(i-1,n-1)); - r->ptr.pp_double[i-1][j-1] = v; - } - } - - /* - * Copy R to A - */ - for(i=0; i<=n-1; i++) - { - ae_v_move(&a->ptr.pp_double[i][0], 1, &r->ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - } - if( problemtype==2 ) - { - - /* - * Invert U in T - */ - rmatrixtrinverse(&t, n, ae_true, ae_false, &info, &rep, _state); - if( info<=0 ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - - /* - * Copy U^-1 from T to R - */ - *isupperr = ae_true; - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i-1; j++) - { - r->ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=n-1; i++) - { - ae_v_move(&r->ptr.pp_double[i][i], 1, &t.ptr.pp_double[i][i], 1, ae_v_len(i,n-1)); - } - } - else - { - - /* - * Copy U from T to R and transpose - */ - *isupperr = ae_false; - for(i=0; i<=n-1; i++) - { - for(j=i+1; j<=n-1; j++) - { - r->ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=n-1; i++) - { - ae_v_move(&r->ptr.pp_double[i][i], r->stride, &t.ptr.pp_double[i][i], 1, ae_v_len(i,n-1)); - } - } - } - ae_frame_leave(_state); - return result; -} - - -#endif -#if defined(AE_COMPILE_INVERSEUPDATE) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Inverse matrix update by the Sherman-Morrison formula - -The algorithm updates matrix A^-1 when adding a number to an element -of matrix A. - -Input parameters: - InvA - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - UpdRow - row where the element to be updated is stored. - UpdColumn - column where the element to be updated is stored. - UpdVal - a number to be added to the element. - - -Output parameters: - InvA - inverse of modified matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -void rmatrixinvupdatesimple(/* Real */ ae_matrix* inva, - ae_int_t n, - ae_int_t updrow, - ae_int_t updcolumn, - double updval, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector t1; - ae_vector t2; - ae_int_t i; - double lambdav; - double vt; - - ae_frame_make(_state, &_frame_block); - memset(&t1, 0, sizeof(t1)); - memset(&t2, 0, sizeof(t2)); - ae_vector_init(&t1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t2, 0, DT_REAL, _state, ae_true); - - ae_assert(updrow>=0&&updrow=0&&updcolumnptr.pp_double[0][updrow], inva->stride, ae_v_len(0,n-1)); - - /* - * T2 = v*InvA - */ - ae_v_move(&t2.ptr.p_double[0], 1, &inva->ptr.pp_double[updcolumn][0], 1, ae_v_len(0,n-1)); - - /* - * Lambda = v * InvA * U - */ - lambdav = updval*inva->ptr.pp_double[updcolumn][updrow]; - - /* - * InvA = InvA - correction - */ - for(i=0; i<=n-1; i++) - { - vt = updval*t1.ptr.p_double[i]; - vt = vt/(1+lambdav); - ae_v_subd(&inva->ptr.pp_double[i][0], 1, &t2.ptr.p_double[0], 1, ae_v_len(0,n-1), vt); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Inverse matrix update by the Sherman-Morrison formula - -The algorithm updates matrix A^-1 when adding a vector to a row -of matrix A. - -Input parameters: - InvA - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - UpdRow - the row of A whose vector V was added. - 0 <= Row <= N-1 - V - the vector to be added to a row. - Array whose index ranges within [0..N-1]. - -Output parameters: - InvA - inverse of modified matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -void rmatrixinvupdaterow(/* Real */ ae_matrix* inva, - ae_int_t n, - ae_int_t updrow, - /* Real */ ae_vector* v, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector t1; - ae_vector t2; - ae_int_t i; - ae_int_t j; - double lambdav; - double vt; - - ae_frame_make(_state, &_frame_block); - memset(&t1, 0, sizeof(t1)); - memset(&t2, 0, sizeof(t2)); - ae_vector_init(&t1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t2, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&t1, n-1+1, _state); - ae_vector_set_length(&t2, n-1+1, _state); - - /* - * T1 = InvA * U - */ - ae_v_move(&t1.ptr.p_double[0], 1, &inva->ptr.pp_double[0][updrow], inva->stride, ae_v_len(0,n-1)); - - /* - * T2 = v*InvA - * Lambda = v * InvA * U - */ - for(j=0; j<=n-1; j++) - { - vt = ae_v_dotproduct(&v->ptr.p_double[0], 1, &inva->ptr.pp_double[0][j], inva->stride, ae_v_len(0,n-1)); - t2.ptr.p_double[j] = vt; - } - lambdav = t2.ptr.p_double[updrow]; - - /* - * InvA = InvA - correction - */ - for(i=0; i<=n-1; i++) - { - vt = t1.ptr.p_double[i]/(1+lambdav); - ae_v_subd(&inva->ptr.pp_double[i][0], 1, &t2.ptr.p_double[0], 1, ae_v_len(0,n-1), vt); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Inverse matrix update by the Sherman-Morrison formula - -The algorithm updates matrix A^-1 when adding a vector to a column -of matrix A. - -Input parameters: - InvA - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - UpdColumn - the column of A whose vector U was added. - 0 <= UpdColumn <= N-1 - U - the vector to be added to a column. - Array whose index ranges within [0..N-1]. - -Output parameters: - InvA - inverse of modified matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -void rmatrixinvupdatecolumn(/* Real */ ae_matrix* inva, - ae_int_t n, - ae_int_t updcolumn, - /* Real */ ae_vector* u, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector t1; - ae_vector t2; - ae_int_t i; - double lambdav; - double vt; - - ae_frame_make(_state, &_frame_block); - memset(&t1, 0, sizeof(t1)); - memset(&t2, 0, sizeof(t2)); - ae_vector_init(&t1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t2, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&t1, n-1+1, _state); - ae_vector_set_length(&t2, n-1+1, _state); - - /* - * T1 = InvA * U - * Lambda = v * InvA * U - */ - for(i=0; i<=n-1; i++) - { - vt = ae_v_dotproduct(&inva->ptr.pp_double[i][0], 1, &u->ptr.p_double[0], 1, ae_v_len(0,n-1)); - t1.ptr.p_double[i] = vt; - } - lambdav = t1.ptr.p_double[updcolumn]; - - /* - * T2 = v*InvA - */ - ae_v_move(&t2.ptr.p_double[0], 1, &inva->ptr.pp_double[updcolumn][0], 1, ae_v_len(0,n-1)); - - /* - * InvA = InvA - correction - */ - for(i=0; i<=n-1; i++) - { - vt = t1.ptr.p_double[i]/(1+lambdav); - ae_v_subd(&inva->ptr.pp_double[i][0], 1, &t2.ptr.p_double[0], 1, ae_v_len(0,n-1), vt); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Inverse matrix update by the Sherman-Morrison formula - -The algorithm computes the inverse of matrix A+u*v' by using the given matrix -A^-1 and the vectors u and v. - -Input parameters: - InvA - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - U - the vector modifying the matrix. - Array whose index ranges within [0..N-1]. - V - the vector modifying the matrix. - Array whose index ranges within [0..N-1]. - -Output parameters: - InvA - inverse of matrix A + u*v'. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -void rmatrixinvupdateuv(/* Real */ ae_matrix* inva, - ae_int_t n, - /* Real */ ae_vector* u, - /* Real */ ae_vector* v, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector t1; - ae_vector t2; - ae_int_t i; - ae_int_t j; - double lambdav; - double vt; - - ae_frame_make(_state, &_frame_block); - memset(&t1, 0, sizeof(t1)); - memset(&t2, 0, sizeof(t2)); - ae_vector_init(&t1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t2, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&t1, n-1+1, _state); - ae_vector_set_length(&t2, n-1+1, _state); - - /* - * T1 = InvA * U - * Lambda = v * T1 - */ - for(i=0; i<=n-1; i++) - { - vt = ae_v_dotproduct(&inva->ptr.pp_double[i][0], 1, &u->ptr.p_double[0], 1, ae_v_len(0,n-1)); - t1.ptr.p_double[i] = vt; - } - lambdav = ae_v_dotproduct(&v->ptr.p_double[0], 1, &t1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - - /* - * T2 = v*InvA - */ - for(j=0; j<=n-1; j++) - { - vt = ae_v_dotproduct(&v->ptr.p_double[0], 1, &inva->ptr.pp_double[0][j], inva->stride, ae_v_len(0,n-1)); - t2.ptr.p_double[j] = vt; - } - - /* - * InvA = InvA - correction - */ - for(i=0; i<=n-1; i++) - { - vt = t1.ptr.p_double[i]/(1+lambdav); - ae_v_subd(&inva->ptr.pp_double[i][0], 1, &t2.ptr.p_double[0], 1, ae_v_len(0,n-1), vt); - } - ae_frame_leave(_state); -} - - -#endif -#if defined(AE_COMPILE_MATDET) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Determinant calculation of the matrix given by its LU decomposition. - -Input parameters: - A - LU decomposition of the matrix (output of - RMatrixLU subroutine). - Pivots - table of permutations which were made during - the LU decomposition. - Output of RMatrixLU subroutine. - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -Result: matrix determinant. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -double rmatrixludet(/* Real */ ae_matrix* a, - /* Integer */ ae_vector* pivots, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t s; - double result; - - - ae_assert(n>=1, "RMatrixLUDet: N<1!", _state); - ae_assert(pivots->cnt>=n, "RMatrixLUDet: Pivots array is too short!", _state); - ae_assert(a->rows>=n, "RMatrixLUDet: rows(A)cols>=n, "RMatrixLUDet: cols(A)ptr.pp_double[i][i]; - if( pivots->ptr.p_int[i]!=i ) - { - s = -s; - } - } - result = result*s; - return result; -} - - -/************************************************************************* -Calculation of the determinant of a general matrix - -Input parameters: - A - matrix, array[0..N-1, 0..N-1] - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -Result: determinant of matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -double rmatrixdet(/* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_vector pivots; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&pivots, 0, sizeof(pivots)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_vector_init(&pivots, 0, DT_INT, _state, ae_true); - - ae_assert(n>=1, "RMatrixDet: N<1!", _state); - ae_assert(a->rows>=n, "RMatrixDet: rows(A)cols>=n, "RMatrixDet: cols(A)=1, "CMatrixLUDet: N<1!", _state); - ae_assert(pivots->cnt>=n, "CMatrixLUDet: Pivots array is too short!", _state); - ae_assert(a->rows>=n, "CMatrixLUDet: rows(A)cols>=n, "CMatrixLUDet: cols(A)ptr.pp_complex[i][i]); - if( pivots->ptr.p_int[i]!=i ) - { - s = -s; - } - } - result = ae_c_mul_d(result,(double)(s)); - return result; -} - - -/************************************************************************* -Calculation of the determinant of a general matrix - -Input parameters: - A - matrix, array[0..N-1, 0..N-1] - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -Result: determinant of matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -ae_complex cmatrixdet(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_vector pivots; - ae_complex result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&pivots, 0, sizeof(pivots)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_vector_init(&pivots, 0, DT_INT, _state, ae_true); - - ae_assert(n>=1, "CMatrixDet: N<1!", _state); - ae_assert(a->rows>=n, "CMatrixDet: rows(A)cols>=n, "CMatrixDet: cols(A)=1, "SPDMatrixCholeskyDet: N<1!", _state); - ae_assert(a->rows>=n, "SPDMatrixCholeskyDet: rows(A)cols>=n, "SPDMatrixCholeskyDet: cols(A)ptr.pp_double[i][i], _state); - } - ae_assert(f, "SPDMatrixCholeskyDet: A contains infinite or NaN values!", _state); - result = (double)(1); - for(i=0; i<=n-1; i++) - { - result = result*ae_sqr(a->ptr.pp_double[i][i], _state); - } - return result; -} - - -/************************************************************************* -Determinant calculation of the symmetric positive definite matrix. - -Input parameters: - A - matrix. Array with elements [0..N-1, 0..N-1]. - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - IsUpper - (optional) storage type: - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, both lower and upper triangles must be - filled. - -Result: - determinant of matrix A. - If matrix A is not positive definite, exception is thrown. - - -- ALGLIB -- - Copyright 2005-2008 by Bochkanov Sergey -*************************************************************************/ -double spdmatrixdet(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_bool b; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - - ae_assert(n>=1, "SPDMatrixDet: N<1!", _state); - ae_assert(a->rows>=n, "SPDMatrixDet: rows(A)cols>=n, "SPDMatrixDet: cols(A)>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifndef _linalg_pkg_h -#define _linalg_pkg_h -#include "ap.h" -#include "alglibinternal.h" -#include "alglibmisc.h" - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (DATATYPES) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_SPARSE) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_vector vals; - ae_vector idx; - ae_vector ridx; - ae_vector didx; - ae_vector uidx; - ae_int_t matrixtype; - ae_int_t m; - ae_int_t n; - ae_int_t nfree; - ae_int_t ninitialized; - ae_int_t tablesize; -} sparsematrix; -typedef struct -{ - ae_vector d; - ae_vector u; - sparsematrix s; -} sparsebuffers; -#endif -#if defined(AE_COMPILE_ABLAS) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_DLU) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_SPTRF) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t nfixed; - ae_int_t ndynamic; - ae_vector idxfirst; - ae_vector strgidx; - ae_vector strgval; - ae_int_t nallocated; - ae_int_t nused; -} sluv2list1matrix; -typedef struct -{ - ae_int_t n; - ae_int_t k; - ae_vector nzc; - ae_int_t maxwrkcnt; - ae_int_t maxwrknz; - ae_int_t wrkcnt; - ae_vector wrkset; - ae_vector colid; - ae_vector isdensified; - ae_vector slscolptr; - ae_vector slsrowptr; - ae_vector slsidx; - ae_vector slsval; - ae_int_t slsused; - ae_vector tmp0; -} sluv2sparsetrail; -typedef struct -{ - ae_int_t n; - ae_int_t ndense; - ae_matrix d; - ae_vector did; -} sluv2densetrail; -typedef struct -{ - ae_int_t n; - sparsematrix sparsel; - sparsematrix sparseut; - sluv2list1matrix bleft; - sluv2list1matrix bupper; - sluv2sparsetrail strail; - sluv2densetrail dtrail; - ae_vector rowpermrawidx; - ae_matrix dbuf; - ae_vector v0i; - ae_vector v1i; - ae_vector v0r; - ae_vector v1r; - ae_vector tmp0; - ae_vector tmpi; - ae_vector tmpp; -} sluv2buffer; -#endif -#if defined(AE_COMPILE_AMDORDERING) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t n; - ae_int_t nstored; - ae_vector items; - ae_vector locationof; - ae_int_t iteridx; -} amdnset; -typedef struct -{ - ae_int_t k; - ae_int_t n; - ae_vector flagarray; - ae_vector vbegin; - ae_vector vallocated; - ae_vector vcnt; - ae_vector data; - ae_int_t dataused; - ae_int_t iterrow; - ae_int_t iteridx; -} amdknset; -typedef struct -{ - ae_int_t n; - ae_bool checkexactdegrees; - ae_int_t smallestdegree; - ae_vector approxd; - ae_vector optionalexactd; - ae_vector isvertex; - ae_vector vbegin; - ae_vector vprev; - ae_vector vnext; -} amdvertexset; -typedef struct -{ - ae_int_t n; - ae_vector vbegin; - ae_vector vcolcnt; - ae_vector entries; - ae_int_t entriesinitialized; -} amdllmatrix; -typedef struct -{ - ae_int_t n; - ae_bool extendeddebug; - ae_bool checkexactdegrees; - ae_vector iseliminated; - ae_vector issupernode; - amdknset setsuper; - amdknset seta; - amdknset sete; - amdllmatrix mtxl; - amdvertexset vertexdegrees; - ae_vector perm; - ae_vector invperm; - ae_vector columnswaps; - amdnset lp; - amdnset plp; - amdnset ep; - amdnset adji; - amdnset adjj; - ae_vector ls; - ae_int_t lscnt; - amdnset exactdegreetmp0; - amdknset hashbuckets; - amdnset nonemptybuckets; - ae_vector sncandidates; - ae_vector tmp0; - ae_vector arrwe; - ae_matrix dbga; -} amdbuffer; -#endif -#if defined(AE_COMPILE_SPCHOL) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t tasktype; - ae_int_t n; - ae_int_t permtype; - ae_bool unitd; - ae_int_t modtype; - double modparam0; - double modparam1; - double modparam2; - double modparam3; - ae_bool extendeddebug; - ae_bool dotrace; - ae_int_t nsuper; - ae_vector parentsupernode; - ae_vector supercolrange; - ae_vector superrowridx; - ae_vector superrowidx; - ae_vector fillinperm; - ae_vector invfillinperm; - ae_vector superperm; - ae_vector invsuperperm; - ae_vector effectiveperm; - ae_vector inveffectiveperm; - ae_bool istopologicalordering; - ae_bool applypermutationtooutput; - ae_vector ladjplusr; - ae_vector ladjplus; - ae_vector outrowcounts; - sparsematrix wrkat; - ae_vector rowstorage; - ae_vector rowstrides; - ae_vector rowoffsets; - ae_vector diagd; - ae_vector wrkrows; - ae_vector flagarray; - ae_vector tmpparent; - ae_vector node2supernode; - ae_vector u2smap; - ae_vector raw2smap; - amdbuffer amdtmp; - ae_vector tmp0; - ae_vector tmp1; - ae_vector tmp2; - ae_vector tmp3; - ae_vector tmp4; - sparsematrix tmpa; -} spcholanalysis; -#endif -#if defined(AE_COMPILE_MATGEN) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_TRFAC) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t n; - ae_int_t facttype; - ae_int_t permtype; - spcholanalysis analysis; - sparsematrix wrka; - sparsematrix wrkat; - sparsematrix crsa; - sparsematrix crsat; -} sparsedecompositionanalysis; -#endif -#if defined(AE_COMPILE_RCOND) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_MATINV) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - double r1; - double rinf; -} matinvreport; -#endif -#if defined(AE_COMPILE_ORTFAC) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_FBLS) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - double e1; - double e2; - ae_vector x; - ae_vector ax; - double xax; - ae_int_t n; - ae_vector rk; - ae_vector rk1; - ae_vector xk; - ae_vector xk1; - ae_vector pk; - ae_vector pk1; - ae_vector b; - rcommstate rstate; - ae_vector tmp2; -} fblslincgstate; -typedef struct -{ - ae_vector b; - ae_vector x; - ae_vector ax; - ae_vector xs; - ae_matrix qi; - ae_matrix aqi; - ae_matrix h; - ae_matrix hq; - ae_matrix hr; - ae_vector hqb; - ae_vector ys; - ae_vector tmp0; - ae_vector tmp1; - ae_int_t n; - ae_int_t itscnt; - double epsort; - double epsres; - double epsred; - double epsdiag; - ae_int_t itsperformed; - ae_int_t retcode; - rcommstate rstate; -} fblsgmresstate; -#endif -#if defined(AE_COMPILE_BDSVD) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_SVD) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_NORMESTIMATOR) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t n; - ae_int_t m; - ae_int_t nstart; - ae_int_t nits; - ae_int_t seedval; - ae_vector x0; - ae_vector x1; - ae_vector t; - ae_vector xbest; - hqrndstate r; - ae_vector x; - ae_vector mv; - ae_vector mtv; - ae_bool needmv; - ae_bool needmtv; - double repnorm; - rcommstate rstate; -} normestimatorstate; -#endif -#if defined(AE_COMPILE_HSSCHUR) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_EVD) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t n; - ae_int_t k; - ae_int_t nwork; - ae_int_t maxits; - double eps; - ae_int_t eigenvectorsneeded; - ae_int_t matrixtype; - ae_bool usewarmstart; - ae_bool firstcall; - hqrndstate rs; - ae_bool running; - ae_vector tau; - ae_matrix q0; - ae_matrix qcur; - ae_matrix qnew; - ae_matrix znew; - ae_matrix r; - ae_matrix rz; - ae_matrix tz; - ae_matrix rq; - ae_matrix dummy; - ae_vector rw; - ae_vector tw; - ae_vector wcur; - ae_vector wprev; - ae_vector wrank; - apbuffers buf; - ae_matrix x; - ae_matrix ax; - ae_int_t requesttype; - ae_int_t requestsize; - ae_int_t repiterationscount; - rcommstate rstate; -} eigsubspacestate; -typedef struct -{ - ae_int_t iterationscount; -} eigsubspacereport; -#endif -#if defined(AE_COMPILE_SCHUR) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_SPDGEVD) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_INVERSEUPDATE) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_MATDET) || !defined(AE_PARTIAL_BUILD) -#endif - -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_SPARSE) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Sparse matrix structure. - -You should use ALGLIB functions to work with sparse matrix. Never try to -access its fields directly! - -NOTES ON THE SPARSE STORAGE FORMATS - -Sparse matrices can be stored using several formats: -* Hash-Table representation -* Compressed Row Storage (CRS) -* Skyline matrix storage (SKS) - -Each of the formats has benefits and drawbacks: -* Hash-table is good for dynamic operations (insertion of new elements), - but does not support linear algebra operations -* CRS is good for operations like matrix-vector or matrix-matrix products, - but its initialization is less convenient - you have to tell row sizes - at the initialization, and you have to fill matrix only row by row, - from left to right. -* SKS is a special format which is used to store triangular factors from - Cholesky factorization. It does not support dynamic modification, and - support for linear algebra operations is very limited. - -Tables below outline information about these two formats: - - OPERATIONS WITH MATRIX HASH CRS SKS - creation + + + - SparseGet + + + - SparseExists + + + - SparseRewriteExisting + + + - SparseSet + + + - SparseAdd + - SparseGetRow + + - SparseGetCompressedRow + + - sparse-dense linear algebra + + -*************************************************************************/ -class _sparsematrix_owner -{ -public: - _sparsematrix_owner(); - _sparsematrix_owner(const _sparsematrix_owner &rhs); - _sparsematrix_owner& operator=(const _sparsematrix_owner &rhs); - virtual ~_sparsematrix_owner(); - alglib_impl::sparsematrix* c_ptr(); - alglib_impl::sparsematrix* c_ptr() const; -protected: - alglib_impl::sparsematrix *p_struct; -}; -class sparsematrix : public _sparsematrix_owner -{ -public: - sparsematrix(); - sparsematrix(const sparsematrix &rhs); - sparsematrix& operator=(const sparsematrix &rhs); - virtual ~sparsematrix(); - -}; - - -/************************************************************************* -Temporary buffers for sparse matrix operations. - -You should pass an instance of this structure to factorization functions. -It allows to reuse memory during repeated sparse factorizations. You do -not have to call some initialization function - simply passing an instance -to factorization function is enough. -*************************************************************************/ -class _sparsebuffers_owner -{ -public: - _sparsebuffers_owner(); - _sparsebuffers_owner(const _sparsebuffers_owner &rhs); - _sparsebuffers_owner& operator=(const _sparsebuffers_owner &rhs); - virtual ~_sparsebuffers_owner(); - alglib_impl::sparsebuffers* c_ptr(); - alglib_impl::sparsebuffers* c_ptr() const; -protected: - alglib_impl::sparsebuffers *p_struct; -}; -class sparsebuffers : public _sparsebuffers_owner -{ -public: - sparsebuffers(); - sparsebuffers(const sparsebuffers &rhs); - sparsebuffers& operator=(const sparsebuffers &rhs); - virtual ~sparsebuffers(); - -}; -#endif - -#if defined(AE_COMPILE_ABLAS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_DLU) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPTRF) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_AMDORDERING) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPCHOL) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MATGEN) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_TRFAC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -An analysis of the sparse matrix decomposition, performed prior to actual -numerical factorization. You should not directly access fields of this -object - use appropriate ALGLIB functions to work with this object. -*************************************************************************/ -class _sparsedecompositionanalysis_owner -{ -public: - _sparsedecompositionanalysis_owner(); - _sparsedecompositionanalysis_owner(const _sparsedecompositionanalysis_owner &rhs); - _sparsedecompositionanalysis_owner& operator=(const _sparsedecompositionanalysis_owner &rhs); - virtual ~_sparsedecompositionanalysis_owner(); - alglib_impl::sparsedecompositionanalysis* c_ptr(); - alglib_impl::sparsedecompositionanalysis* c_ptr() const; -protected: - alglib_impl::sparsedecompositionanalysis *p_struct; -}; -class sparsedecompositionanalysis : public _sparsedecompositionanalysis_owner -{ -public: - sparsedecompositionanalysis(); - sparsedecompositionanalysis(const sparsedecompositionanalysis &rhs); - sparsedecompositionanalysis& operator=(const sparsedecompositionanalysis &rhs); - virtual ~sparsedecompositionanalysis(); - -}; -#endif - -#if defined(AE_COMPILE_RCOND) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MATINV) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Matrix inverse report: -* R1 reciprocal of condition number in 1-norm -* RInf reciprocal of condition number in inf-norm -*************************************************************************/ -class _matinvreport_owner -{ -public: - _matinvreport_owner(); - _matinvreport_owner(const _matinvreport_owner &rhs); - _matinvreport_owner& operator=(const _matinvreport_owner &rhs); - virtual ~_matinvreport_owner(); - alglib_impl::matinvreport* c_ptr(); - alglib_impl::matinvreport* c_ptr() const; -protected: - alglib_impl::matinvreport *p_struct; -}; -class matinvreport : public _matinvreport_owner -{ -public: - matinvreport(); - matinvreport(const matinvreport &rhs); - matinvreport& operator=(const matinvreport &rhs); - virtual ~matinvreport(); - double &r1; - double &rinf; - -}; -#endif - -#if defined(AE_COMPILE_ORTFAC) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_FBLS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_BDSVD) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SVD) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_NORMESTIMATOR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores state of the iterative norm estimation algorithm. - -You should use ALGLIB functions to work with this object. -*************************************************************************/ -class _normestimatorstate_owner -{ -public: - _normestimatorstate_owner(); - _normestimatorstate_owner(const _normestimatorstate_owner &rhs); - _normestimatorstate_owner& operator=(const _normestimatorstate_owner &rhs); - virtual ~_normestimatorstate_owner(); - alglib_impl::normestimatorstate* c_ptr(); - alglib_impl::normestimatorstate* c_ptr() const; -protected: - alglib_impl::normestimatorstate *p_struct; -}; -class normestimatorstate : public _normestimatorstate_owner -{ -public: - normestimatorstate(); - normestimatorstate(const normestimatorstate &rhs); - normestimatorstate& operator=(const normestimatorstate &rhs); - virtual ~normestimatorstate(); - -}; -#endif - -#if defined(AE_COMPILE_HSSCHUR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_EVD) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores state of the subspace iteration algorithm. - -You should use ALGLIB functions to work with this object. -*************************************************************************/ -class _eigsubspacestate_owner -{ -public: - _eigsubspacestate_owner(); - _eigsubspacestate_owner(const _eigsubspacestate_owner &rhs); - _eigsubspacestate_owner& operator=(const _eigsubspacestate_owner &rhs); - virtual ~_eigsubspacestate_owner(); - alglib_impl::eigsubspacestate* c_ptr(); - alglib_impl::eigsubspacestate* c_ptr() const; -protected: - alglib_impl::eigsubspacestate *p_struct; -}; -class eigsubspacestate : public _eigsubspacestate_owner -{ -public: - eigsubspacestate(); - eigsubspacestate(const eigsubspacestate &rhs); - eigsubspacestate& operator=(const eigsubspacestate &rhs); - virtual ~eigsubspacestate(); - -}; - - -/************************************************************************* -This object stores state of the subspace iteration algorithm. - -You should use ALGLIB functions to work with this object. -*************************************************************************/ -class _eigsubspacereport_owner -{ -public: - _eigsubspacereport_owner(); - _eigsubspacereport_owner(const _eigsubspacereport_owner &rhs); - _eigsubspacereport_owner& operator=(const _eigsubspacereport_owner &rhs); - virtual ~_eigsubspacereport_owner(); - alglib_impl::eigsubspacereport* c_ptr(); - alglib_impl::eigsubspacereport* c_ptr() const; -protected: - alglib_impl::eigsubspacereport *p_struct; -}; -class eigsubspacereport : public _eigsubspacereport_owner -{ -public: - eigsubspacereport(); - eigsubspacereport(const eigsubspacereport &rhs); - eigsubspacereport& operator=(const eigsubspacereport &rhs); - virtual ~eigsubspacereport(); - ae_int_t &iterationscount; - -}; -#endif - -#if defined(AE_COMPILE_SCHUR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPDGEVD) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_INVERSEUPDATE) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MATDET) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPARSE) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This function creates sparse matrix in a Hash-Table format. - -This function creates Hast-Table matrix, which can be converted to CRS -format after its initialization is over. Typical usage scenario for a -sparse matrix is: -1. creation in a Hash-Table format -2. insertion of the matrix elements -3. conversion to the CRS representation -4. matrix is passed to some linear algebra algorithm - -Some information about different matrix formats can be found below, in -the "NOTES" section. - -INPUT PARAMETERS - M - number of rows in a matrix, M>=1 - N - number of columns in a matrix, N>=1 - K - K>=0, expected number of non-zero elements in a matrix. - K can be inexact approximation, can be less than actual - number of elements (table will grow when needed) or - even zero). - It is important to understand that although hash-table - may grow automatically, it is better to provide good - estimate of data size. - -OUTPUT PARAMETERS - S - sparse M*N matrix in Hash-Table representation. - All elements of the matrix are zero. - -NOTE 1 - -Hash-tables use memory inefficiently, and they have to keep some amount -of the "spare memory" in order to have good performance. Hash table for -matrix with K non-zero elements will need C*K*(8+2*sizeof(int)) bytes, -where C is a small constant, about 1.5-2 in magnitude. - -CRS storage, from the other side, is more memory-efficient, and needs -just K*(8+sizeof(int))+M*sizeof(int) bytes, where M is a number of rows -in a matrix. - -When you convert from the Hash-Table to CRS representation, all unneeded -memory will be freed. - -NOTE 2 - -Comments of SparseMatrix structure outline information about different -sparse storage formats. We recommend you to read them before starting to -use ALGLIB sparse matrices. - -NOTE 3 - -This function completely overwrites S with new sparse matrix. Previously -allocated storage is NOT reused. If you want to reuse already allocated -memory, call SparseCreateBuf function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsecreate(const ae_int_t m, const ae_int_t n, const ae_int_t k, sparsematrix &s, const xparams _xparams = alglib::xdefault); -void sparsecreate(const ae_int_t m, const ae_int_t n, sparsematrix &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This version of SparseCreate function creates sparse matrix in Hash-Table -format, reusing previously allocated storage as much as possible. Read -comments for SparseCreate() for more information. - -INPUT PARAMETERS - M - number of rows in a matrix, M>=1 - N - number of columns in a matrix, N>=1 - K - K>=0, expected number of non-zero elements in a matrix. - K can be inexact approximation, can be less than actual - number of elements (table will grow when needed) or - even zero). - It is important to understand that although hash-table - may grow automatically, it is better to provide good - estimate of data size. - S - SparseMatrix structure which MAY contain some already - allocated storage. - -OUTPUT PARAMETERS - S - sparse M*N matrix in Hash-Table representation. - All elements of the matrix are zero. - Previously allocated storage is reused, if its size - is compatible with expected number of non-zeros K. - - -- ALGLIB PROJECT -- - Copyright 14.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatebuf(const ae_int_t m, const ae_int_t n, const ae_int_t k, const sparsematrix &s, const xparams _xparams = alglib::xdefault); -void sparsecreatebuf(const ae_int_t m, const ae_int_t n, const sparsematrix &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function creates sparse matrix in a CRS format (expert function for -situations when you are running out of memory). - -This function creates CRS matrix. Typical usage scenario for a CRS matrix -is: -1. creation (you have to tell number of non-zero elements at each row at - this moment) -2. insertion of the matrix elements (row by row, from left to right) -3. matrix is passed to some linear algebra algorithm - -This function is a memory-efficient alternative to SparseCreate(), but it -is more complex because it requires you to know in advance how large your -matrix is. Some information about different matrix formats can be found -in comments on SparseMatrix structure. We recommend you to read them -before starting to use ALGLIB sparse matrices.. - -INPUT PARAMETERS - M - number of rows in a matrix, M>=1 - N - number of columns in a matrix, N>=1 - NER - number of elements at each row, array[M], NER[I]>=0 - -OUTPUT PARAMETERS - S - sparse M*N matrix in CRS representation. - You have to fill ALL non-zero elements by calling - SparseSet() BEFORE you try to use this matrix. - -NOTE: this function completely overwrites S with new sparse matrix. - Previously allocated storage is NOT reused. If you want to reuse - already allocated memory, call SparseCreateCRSBuf function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatecrs(const ae_int_t m, const ae_int_t n, const integer_1d_array &ner, sparsematrix &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function creates sparse matrix in a CRS format (expert function for -situations when you are running out of memory). This version of CRS -matrix creation function may reuse memory already allocated in S. - -This function creates CRS matrix. Typical usage scenario for a CRS matrix -is: -1. creation (you have to tell number of non-zero elements at each row at - this moment) -2. insertion of the matrix elements (row by row, from left to right) -3. matrix is passed to some linear algebra algorithm - -This function is a memory-efficient alternative to SparseCreate(), but it -is more complex because it requires you to know in advance how large your -matrix is. Some information about different matrix formats can be found -in comments on SparseMatrix structure. We recommend you to read them -before starting to use ALGLIB sparse matrices.. - -INPUT PARAMETERS - M - number of rows in a matrix, M>=1 - N - number of columns in a matrix, N>=1 - NER - number of elements at each row, array[M], NER[I]>=0 - S - sparse matrix structure with possibly preallocated - memory. - -OUTPUT PARAMETERS - S - sparse M*N matrix in CRS representation. - You have to fill ALL non-zero elements by calling - SparseSet() BEFORE you try to use this matrix. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatecrsbuf(const ae_int_t m, const ae_int_t n, const integer_1d_array &ner, const sparsematrix &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function creates sparse matrix in a SKS format (skyline storage -format). In most cases you do not need this function - CRS format better -suits most use cases. - -INPUT PARAMETERS - M, N - number of rows(M) and columns (N) in a matrix: - * M=N (as for now, ALGLIB supports only square SKS) - * N>=1 - * M>=1 - D - "bottom" bandwidths, array[M], D[I]>=0. - I-th element stores number of non-zeros at I-th row, - below the diagonal (diagonal itself is not included) - U - "top" bandwidths, array[N], U[I]>=0. - I-th element stores number of non-zeros at I-th row, - above the diagonal (diagonal itself is not included) - -OUTPUT PARAMETERS - S - sparse M*N matrix in SKS representation. - All elements are filled by zeros. - You may use sparseset() to change their values. - -NOTE: this function completely overwrites S with new sparse matrix. - Previously allocated storage is NOT reused. If you want to reuse - already allocated memory, call SparseCreateSKSBuf function. - - -- ALGLIB PROJECT -- - Copyright 13.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatesks(const ae_int_t m, const ae_int_t n, const integer_1d_array &d, const integer_1d_array &u, sparsematrix &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is "buffered" version of SparseCreateSKS() which reuses memory -previously allocated in S (of course, memory is reallocated if needed). - -This function creates sparse matrix in a SKS format (skyline storage -format). In most cases you do not need this function - CRS format better -suits most use cases. - -INPUT PARAMETERS - M, N - number of rows(M) and columns (N) in a matrix: - * M=N (as for now, ALGLIB supports only square SKS) - * N>=1 - * M>=1 - D - "bottom" bandwidths, array[M], 0<=D[I]<=I. - I-th element stores number of non-zeros at I-th row, - below the diagonal (diagonal itself is not included) - U - "top" bandwidths, array[N], 0<=U[I]<=I. - I-th element stores number of non-zeros at I-th row, - above the diagonal (diagonal itself is not included) - -OUTPUT PARAMETERS - S - sparse M*N matrix in SKS representation. - All elements are filled by zeros. - You may use sparseset() to change their values. - - -- ALGLIB PROJECT -- - Copyright 13.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatesksbuf(const ae_int_t m, const ae_int_t n, const integer_1d_array &d, const integer_1d_array &u, const sparsematrix &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function creates sparse matrix in a SKS format (skyline storage -format). Unlike more general sparsecreatesks(), this function creates -sparse matrix with constant bandwidth. - -You may want to use this function instead of sparsecreatesks() when your -matrix has constant or nearly-constant bandwidth, and you want to -simplify source code. - -INPUT PARAMETERS - M, N - number of rows(M) and columns (N) in a matrix: - * M=N (as for now, ALGLIB supports only square SKS) - * N>=1 - * M>=1 - BW - matrix bandwidth, BW>=0 - -OUTPUT PARAMETERS - S - sparse M*N matrix in SKS representation. - All elements are filled by zeros. - You may use sparseset() to change their values. - -NOTE: this function completely overwrites S with new sparse matrix. - Previously allocated storage is NOT reused. If you want to reuse - already allocated memory, call sparsecreatesksbandbuf function. - - -- ALGLIB PROJECT -- - Copyright 25.12.2017 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatesksband(const ae_int_t m, const ae_int_t n, const ae_int_t bw, sparsematrix &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is "buffered" version of sparsecreatesksband() which reuses memory -previously allocated in S (of course, memory is reallocated if needed). - -You may want to use this function instead of sparsecreatesksbuf() when -your matrix has constant or nearly-constant bandwidth, and you want to -simplify source code. - -INPUT PARAMETERS - M, N - number of rows(M) and columns (N) in a matrix: - * M=N (as for now, ALGLIB supports only square SKS) - * N>=1 - * M>=1 - BW - bandwidth, BW>=0 - -OUTPUT PARAMETERS - S - sparse M*N matrix in SKS representation. - All elements are filled by zeros. - You may use sparseset() to change their values. - - -- ALGLIB PROJECT -- - Copyright 13.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsecreatesksbandbuf(const ae_int_t m, const ae_int_t n, const ae_int_t bw, const sparsematrix &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function copies S0 to S1. -This function completely deallocates memory owned by S1 before creating a -copy of S0. If you want to reuse memory, use SparseCopyBuf. - -NOTE: this function does not verify its arguments, it just copies all -fields of the structure. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsecopy(const sparsematrix &s0, sparsematrix &s1, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function copies S0 to S1. -Memory already allocated in S1 is reused as much as possible. - -NOTE: this function does not verify its arguments, it just copies all -fields of the structure. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsecopybuf(const sparsematrix &s0, const sparsematrix &s1, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function efficiently swaps contents of S0 and S1. - - -- ALGLIB PROJECT -- - Copyright 16.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparseswap(const sparsematrix &s0, const sparsematrix &s1, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function adds value to S[i,j] - element of the sparse matrix. Matrix -must be in a Hash-Table mode. - -In case S[i,j] already exists in the table, V i added to its value. In -case S[i,j] is non-existent, it is inserted in the table. Table -automatically grows when necessary. - -INPUT PARAMETERS - S - sparse M*N matrix in Hash-Table representation. - Exception will be thrown for CRS matrix. - I - row index of the element to modify, 0<=I op(S) = S - * OpS=1 => op(S) = S^T - X - input vector, must have at least Cols(op(S))+IX elements - IX - subvector offset - Beta - destination coefficient - Y - preallocated output array, must have at least Rows(op(S))+IY elements - IY - subvector offset - -OUTPUT PARAMETERS - Y - elements [IY...IY+Rows(op(S))-1] are replaced by result, - other elements are not modified - -HANDLING OF SPECIAL CASES: -* below M=Rows(op(S)) and N=Cols(op(S)). Although current ALGLIB version - does not allow you to create zero-sized sparse matrices, internally - ALGLIB can deal with such matrices. So, comments for M or N equal to - zero are for internal use only. -* if M=0, then subroutine does nothing. It does not even touch arrays. -* if N=0 or Alpha=0.0, then: - * if Beta=0, then Y is filled by zeros. S and X are not referenced at - all. Initial values of Y are ignored (we do not multiply Y by zero, - we just rewrite it by zeros) - * if Beta<>0, then Y is replaced by Beta*Y -* if M>0, N>0, Alpha<>0, but Beta=0, then Y is replaced by alpha*op(S)*x - initial state of Y is ignored (rewritten without initial multiplication - by zeros). - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 10.12.2019 by Bochkanov Sergey -*************************************************************************/ -void sparsegemv(const sparsematrix &s, const double alpha, const ae_int_t ops, const real_1d_array &x, const ae_int_t ix, const double beta, const real_1d_array &y, const ae_int_t iy, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function simultaneously calculates two matrix-vector products: - S*x and S^T*x. -S must be square (non-rectangular) matrix stored in CRS or SKS format -(exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse N*N matrix in CRS or SKS format. - X - array[N], input vector. For performance reasons we - make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - Y0 - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - Y1 - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - Y0 - array[N], S*x - Y1 - array[N], S^T*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsemv2(const sparsematrix &s, const real_1d_array &x, real_1d_array &y0, real_1d_array &y1, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates matrix-vector product S*x, when S is symmetric -matrix. Matrix S must be stored in CRS or SKS format (exception will be -thrown otherwise). - -INPUT PARAMETERS - S - sparse M*M matrix in CRS or SKS format. - IsUpper - whether upper or lower triangle of S is given: - * if upper triangle is given, only S[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only S[i,j] for j<=i - are used, and upper triangle is ignored. - X - array[N], input vector. For performance reasons we - make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - Y - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - Y - array[M], S*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsesmv(const sparsematrix &s, const bool isupper, const real_1d_array &x, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates vector-matrix-vector product x'*S*x, where S is -symmetric matrix. Matrix S must be stored in CRS or SKS format (exception -will be thrown otherwise). - -INPUT PARAMETERS - S - sparse M*M matrix in CRS or SKS format. - IsUpper - whether upper or lower triangle of S is given: - * if upper triangle is given, only S[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only S[i,j] for j<=i - are used, and upper triangle is ignored. - X - array[N], input vector. For performance reasons we - make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - -RESULT - x'*S*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 27.01.2014 by Bochkanov Sergey -*************************************************************************/ -double sparsevsmv(const sparsematrix &s, const bool isupper, const real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates matrix-matrix product S*A. Matrix S must be -stored in CRS or SKS format (exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse M*N matrix in CRS or SKS format. - A - array[N][K], input dense matrix. For performance reasons - we make only quick checks - we check that array size - is at least N, but we do not check for NAN's or INF's. - K - number of columns of matrix (A). - B - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - B - array[M][K], S*A - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsemm(const sparsematrix &s, const real_2d_array &a, const ae_int_t k, real_2d_array &b, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates matrix-matrix product S^T*A. Matrix S must be -stored in CRS or SKS format (exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse M*N matrix in CRS or SKS format. - A - array[M][K], input dense matrix. For performance reasons - we make only quick checks - we check that array size is - at least M, but we do not check for NAN's or INF's. - K - number of columns of matrix (A). - B - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - B - array[N][K], S^T*A - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsemtm(const sparsematrix &s, const real_2d_array &a, const ae_int_t k, real_2d_array &b, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function simultaneously calculates two matrix-matrix products: - S*A and S^T*A. -S must be square (non-rectangular) matrix stored in CRS or SKS format -(exception will be thrown otherwise). - -INPUT PARAMETERS - S - sparse N*N matrix in CRS or SKS format. - A - array[N][K], input dense matrix. For performance reasons - we make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - K - number of columns of matrix (A). - B0 - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - B1 - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - B0 - array[N][K], S*A - B1 - array[N][K], S^T*A - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsemm2(const sparsematrix &s, const real_2d_array &a, const ae_int_t k, real_2d_array &b0, real_2d_array &b1, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates matrix-matrix product S*A, when S is symmetric -matrix. Matrix S must be stored in CRS or SKS format (exception will be -thrown otherwise). - -INPUT PARAMETERS - S - sparse M*M matrix in CRS or SKS format. - IsUpper - whether upper or lower triangle of S is given: - * if upper triangle is given, only S[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only S[i,j] for j<=i - are used, and upper triangle is ignored. - A - array[N][K], input dense matrix. For performance reasons - we make only quick checks - we check that array size is - at least N, but we do not check for NAN's or INF's. - K - number of columns of matrix (A). - B - output buffer, possibly preallocated. In case buffer - size is too small to store result, this buffer is - automatically resized. - -OUTPUT PARAMETERS - B - array[M][K], S*A - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparsesmm(const sparsematrix &s, const bool isupper, const real_2d_array &a, const ae_int_t k, real_2d_array &b, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function calculates matrix-vector product op(S)*x, when x is vector, -S is symmetric triangular matrix, op(S) is transposition or no operation. -Matrix S must be stored in CRS or SKS format (exception will be thrown -otherwise). - -INPUT PARAMETERS - S - sparse square matrix in CRS or SKS format. - IsUpper - whether upper or lower triangle of S is used: - * if upper triangle is given, only S[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only S[i,j] for j<=i - are used, and upper triangle is ignored. - IsUnit - unit or non-unit diagonal: - * if True, diagonal elements of triangular matrix are - considered equal to 1.0. Actual elements stored in - S are not referenced at all. - * if False, diagonal stored in S is used - OpType - operation type: - * if 0, S*x is calculated - * if 1, (S^T)*x is calculated (transposition) - X - array[N] which stores input vector. For performance - reasons we make only quick checks - we check that - array size is at least N, but we do not check for - NAN's or INF's. - Y - possibly preallocated input buffer. Automatically - resized if its size is too small. - -OUTPUT PARAMETERS - Y - array[N], op(S)*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. -You must convert your matrix with SparseConvertToCRS/SKS() before using -this function. - - -- ALGLIB PROJECT -- - Copyright 20.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsetrmv(const sparsematrix &s, const bool isupper, const bool isunit, const ae_int_t optype, const real_1d_array &x, real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function solves linear system op(S)*y=x where x is vector, S is -symmetric triangular matrix, op(S) is transposition or no operation. -Matrix S must be stored in CRS or SKS format (exception will be thrown -otherwise). - -INPUT PARAMETERS - S - sparse square matrix in CRS or SKS format. - IsUpper - whether upper or lower triangle of S is used: - * if upper triangle is given, only S[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only S[i,j] for j<=i - are used, and upper triangle is ignored. - IsUnit - unit or non-unit diagonal: - * if True, diagonal elements of triangular matrix are - considered equal to 1.0. Actual elements stored in - S are not referenced at all. - * if False, diagonal stored in S is used. It is your - responsibility to make sure that diagonal is - non-zero. - OpType - operation type: - * if 0, S*x is calculated - * if 1, (S^T)*x is calculated (transposition) - X - array[N] which stores input vector. For performance - reasons we make only quick checks - we check that - array size is at least N, but we do not check for - NAN's or INF's. - -OUTPUT PARAMETERS - X - array[N], inv(op(S))*x - -NOTE: this function throws exception when called for non-CRS/SKS matrix. - You must convert your matrix with SparseConvertToCRS/SKS() before - using this function. - -NOTE: no assertion or tests are done during algorithm operation. It is - your responsibility to provide invertible matrix to algorithm. - - -- ALGLIB PROJECT -- - Copyright 20.01.2014 by Bochkanov Sergey -*************************************************************************/ -void sparsetrsv(const sparsematrix &s, const bool isupper, const bool isunit, const ae_int_t optype, const real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function applies permutation given by permutation table P (as opposed -to product form of permutation) to sparse symmetric matrix A, given by -either upper or lower triangle: B := P*A*P'. - -This function allocates completely new instance of B. Use buffered version -SparseSymmPermTblBuf() if you want to reuse already allocated structure. - -INPUT PARAMETERS - A - sparse square matrix in CRS format. - IsUpper - whether upper or lower triangle of A is used: - * if upper triangle is given, only A[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only A[i,j] for j<=i - are used, and upper triangle is ignored. - P - array[N] which stores permutation table; P[I]=J means - that I-th row/column of matrix A is moved to J-th - position. For performance reasons we do NOT check that - P[] is a correct permutation (that there is no - repetitions, just that all its elements are in [0,N) - range. - -OUTPUT PARAMETERS - B - permuted matrix. Permutation is applied to A from - the both sides, only upper or lower triangle (depending - on IsUpper) is stored. - -NOTE: this function throws exception when called for non-CRS matrix. You - must convert your matrix with SparseConvertToCRS() before using this - function. - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -void sparsesymmpermtbl(const sparsematrix &a, const bool isupper, const integer_1d_array &p, sparsematrix &b, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is a buffered version of SparseSymmPermTbl() that reuses -previously allocated storage in B as much as possible. - -This function applies permutation given by permutation table P (as opposed -to product form of permutation) to sparse symmetric matrix A, given by -either upper or lower triangle: B := P*A*P'. - -INPUT PARAMETERS - A - sparse square matrix in CRS format. - IsUpper - whether upper or lower triangle of A is used: - * if upper triangle is given, only A[i,j] for j>=i - are used, and lower triangle is ignored (it can be - empty - these elements are not referenced at all). - * if lower triangle is given, only A[i,j] for j<=i - are used, and upper triangle is ignored. - P - array[N] which stores permutation table; P[I]=J means - that I-th row/column of matrix A is moved to J-th - position. For performance reasons we do NOT check that - P[] is a correct permutation (that there is no - repetitions, just that all its elements are in [0,N) - range. - B - sparse matrix object that will hold output. - Previously allocated memory will be reused as much as - possible. - -OUTPUT PARAMETERS - B - permuted matrix. Permutation is applied to A from - the both sides, only upper or lower triangle (depending - on IsUpper) is stored. - -NOTE: this function throws exception when called for non-CRS matrix. You - must convert your matrix with SparseConvertToCRS() before using this - function. - - -- ALGLIB PROJECT -- - Copyright 05.10.2020 by Bochkanov Sergey. -*************************************************************************/ -void sparsesymmpermtblbuf(const sparsematrix &a, const bool isupper, const integer_1d_array &p, const sparsematrix &b, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This procedure resizes Hash-Table matrix. It can be called when you have -deleted too many elements from the matrix, and you want to free unneeded -memory. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -void sparseresizematrix(const sparsematrix &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is used to enumerate all elements of the sparse matrix. -Before first call user initializes T0 and T1 counters by zero. These -counters are used to remember current position in a matrix; after each -call they are updated by the function. - -Subsequent calls to this function return non-zero elements of the sparse -matrix, one by one. If you enumerate CRS matrix, matrix is traversed from -left to right, from top to bottom. In case you enumerate matrix stored as -Hash table, elements are returned in random order. - -EXAMPLE - > T0=0 - > T1=0 - > while SparseEnumerate(S,T0,T1,I,J,V) do - > ....do something with I,J,V - -INPUT PARAMETERS - S - sparse M*N matrix in Hash-Table or CRS representation. - T0 - internal counter - T1 - internal counter - -OUTPUT PARAMETERS - T0 - new value of the internal counter - T1 - new value of the internal counter - I - row index of non-zero element, 0<=I=0 - N - number of columns of op(A) - N>=0 - A - target matrix - IA - submatrix offset (row index) - JA - submatrix offset (column index) - OpA - operation type: - * OpA=0 => op(A) = A - * OpA=1 => op(A) = A^T - * OpA=2 => op(A) = A^H - X - input vector - IX - subvector offset - IY - subvector offset - Y - preallocated matrix, must be large enough to store result - -OUTPUT PARAMETERS: - Y - vector which stores result - -if M=0, then subroutine does nothing. -if N=0, Y is filled by zeros. - - - -- ALGLIB routine -- - - 28.01.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixmv(const ae_int_t m, const ae_int_t n, const complex_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t opa, const complex_1d_array &x, const ae_int_t ix, complex_1d_array &y, const ae_int_t iy, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -IMPORTANT: this function is deprecated since ALGLIB 3.13. Use RMatrixGEMV() - which is more generic version of this function. - -Matrix-vector product: y := op(A)*x - -INPUT PARAMETERS: - M - number of rows of op(A) - N - number of columns of op(A) - A - target matrix - IA - submatrix offset (row index) - JA - submatrix offset (column index) - OpA - operation type: - * OpA=0 => op(A) = A - * OpA=1 => op(A) = A^T - X - input vector - IX - subvector offset - IY - subvector offset - Y - preallocated matrix, must be large enough to store result - -OUTPUT PARAMETERS: - Y - vector which stores result - -if M=0, then subroutine does nothing. -if N=0, Y is filled by zeros. - - - -- ALGLIB routine -- - - 28.01.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixmv(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t opa, const real_1d_array &x, const ae_int_t ix, const real_1d_array &y, const ae_int_t iy, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* - -*************************************************************************/ -void rmatrixsymv(const ae_int_t n, const double alpha, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const bool isupper, const real_1d_array &x, const ae_int_t ix, const double beta, const real_1d_array &y, const ae_int_t iy, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* - -*************************************************************************/ -double rmatrixsyvmv(const ae_int_t n, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const bool isupper, const real_1d_array &x, const ae_int_t ix, const real_1d_array &tmp, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine solves linear system op(A)*x=b where: -* A is NxN upper/lower triangular/unitriangular matrix -* X and B are Nx1 vectors -* "op" may be identity transformation, transposition, conjugate transposition - -Solution replaces X. - -IMPORTANT: * no overflow/underflow/denegeracy tests is performed. - * no integrity checks for operand sizes, out-of-bounds accesses - and so on is performed - -INPUT PARAMETERS - N - matrix size, N>=0 - A - matrix, actial matrix is stored in A[IA:IA+N-1,JA:JA+N-1] - IA - submatrix offset - JA - submatrix offset - IsUpper - whether matrix is upper triangular - IsUnit - whether matrix is unitriangular - OpType - transformation type: - * 0 - no transformation - * 1 - transposition - X - right part, actual vector is stored in X[IX:IX+N-1] - IX - offset - -OUTPUT PARAMETERS - X - solution replaces elements X[IX:IX+N-1] - - -- ALGLIB routine / remastering of LAPACK's DTRSV -- - (c) 2017 Bochkanov Sergey - converted to ALGLIB - (c) 2016 Reference BLAS level1 routine (LAPACK version 3.7.0) - Reference BLAS is a software package provided by Univ. of Tennessee, - Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd. -*************************************************************************/ -void rmatrixtrsv(const ae_int_t n, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const bool isupper, const bool isunit, const ae_int_t optype, const real_1d_array &x, const ae_int_t ix, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine calculates X*op(A^-1) where: -* X is MxN general matrix -* A is NxN upper/lower triangular/unitriangular matrix -* "op" may be identity transformation, transposition, conjugate transposition -Multiplication result replaces X. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - M - matrix size, N>=0 - A - matrix, actial matrix is stored in A[I1:I1+N-1,J1:J1+N-1] - I1 - submatrix offset - J1 - submatrix offset - IsUpper - whether matrix is upper triangular - IsUnit - whether matrix is unitriangular - OpType - transformation type: - * 0 - no transformation - * 1 - transposition - * 2 - conjugate transposition - X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1] - I2 - submatrix offset - J2 - submatrix offset - - -- ALGLIB routine -- - 20.01.2018 - Bochkanov Sergey -*************************************************************************/ -void cmatrixrighttrsm(const ae_int_t m, const ae_int_t n, const complex_2d_array &a, const ae_int_t i1, const ae_int_t j1, const bool isupper, const bool isunit, const ae_int_t optype, const complex_2d_array &x, const ae_int_t i2, const ae_int_t j2, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine calculates op(A^-1)*X where: -* X is MxN general matrix -* A is MxM upper/lower triangular/unitriangular matrix -* "op" may be identity transformation, transposition, conjugate transposition -Multiplication result replaces X. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - M - matrix size, N>=0 - A - matrix, actial matrix is stored in A[I1:I1+M-1,J1:J1+M-1] - I1 - submatrix offset - J1 - submatrix offset - IsUpper - whether matrix is upper triangular - IsUnit - whether matrix is unitriangular - OpType - transformation type: - * 0 - no transformation - * 1 - transposition - * 2 - conjugate transposition - X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1] - I2 - submatrix offset - J2 - submatrix offset - - -- ALGLIB routine -- - 15.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -void cmatrixlefttrsm(const ae_int_t m, const ae_int_t n, const complex_2d_array &a, const ae_int_t i1, const ae_int_t j1, const bool isupper, const bool isunit, const ae_int_t optype, const complex_2d_array &x, const ae_int_t i2, const ae_int_t j2, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine calculates X*op(A^-1) where: -* X is MxN general matrix -* A is NxN upper/lower triangular/unitriangular matrix -* "op" may be identity transformation, transposition -Multiplication result replaces X. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - M - matrix size, N>=0 - A - matrix, actial matrix is stored in A[I1:I1+N-1,J1:J1+N-1] - I1 - submatrix offset - J1 - submatrix offset - IsUpper - whether matrix is upper triangular - IsUnit - whether matrix is unitriangular - OpType - transformation type: - * 0 - no transformation - * 1 - transposition - X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1] - I2 - submatrix offset - J2 - submatrix offset - - -- ALGLIB routine -- - 15.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -void rmatrixrighttrsm(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const ae_int_t i1, const ae_int_t j1, const bool isupper, const bool isunit, const ae_int_t optype, const real_2d_array &x, const ae_int_t i2, const ae_int_t j2, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine calculates op(A^-1)*X where: -* X is MxN general matrix -* A is MxM upper/lower triangular/unitriangular matrix -* "op" may be identity transformation, transposition -Multiplication result replaces X. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - M - matrix size, N>=0 - A - matrix, actial matrix is stored in A[I1:I1+M-1,J1:J1+M-1] - I1 - submatrix offset - J1 - submatrix offset - IsUpper - whether matrix is upper triangular - IsUnit - whether matrix is unitriangular - OpType - transformation type: - * 0 - no transformation - * 1 - transposition - X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1] - I2 - submatrix offset - J2 - submatrix offset - - -- ALGLIB routine -- - 15.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -void rmatrixlefttrsm(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const ae_int_t i1, const ae_int_t j1, const bool isupper, const bool isunit, const ae_int_t optype, const real_2d_array &x, const ae_int_t i2, const ae_int_t j2, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine calculates C=alpha*A*A^H+beta*C or C=alpha*A^H*A+beta*C -where: -* C is NxN Hermitian matrix given by its upper/lower triangle -* A is NxK matrix when A*A^H is calculated, KxN matrix otherwise - -Additional info: -* multiplication result replaces C. If Beta=0, C elements are not used in - calculations (not multiplied by zero - just not referenced) -* if Alpha=0, A is not used (not multiplied by zero - just not referenced) -* if both Beta and Alpha are zero, C is filled by zeros. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - K - matrix size, K>=0 - Alpha - coefficient - A - matrix - IA - submatrix offset (row index) - JA - submatrix offset (column index) - OpTypeA - multiplication type: - * 0 - A*A^H is calculated - * 2 - A^H*A is calculated - Beta - coefficient - C - preallocated input/output matrix - IC - submatrix offset (row index) - JC - submatrix offset (column index) - IsUpper - whether upper or lower triangle of C is updated; - this function updates only one half of C, leaving - other half unchanged (not referenced at all). - - -- ALGLIB routine -- - 16.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -void cmatrixherk(const ae_int_t n, const ae_int_t k, const double alpha, const complex_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t optypea, const double beta, const complex_2d_array &c, const ae_int_t ic, const ae_int_t jc, const bool isupper, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine calculates C=alpha*A*A^T+beta*C or C=alpha*A^T*A+beta*C -where: -* C is NxN symmetric matrix given by its upper/lower triangle -* A is NxK matrix when A*A^T is calculated, KxN matrix otherwise - -Additional info: -* multiplication result replaces C. If Beta=0, C elements are not used in - calculations (not multiplied by zero - just not referenced) -* if Alpha=0, A is not used (not multiplied by zero - just not referenced) -* if both Beta and Alpha are zero, C is filled by zeros. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - N - matrix size, N>=0 - K - matrix size, K>=0 - Alpha - coefficient - A - matrix - IA - submatrix offset (row index) - JA - submatrix offset (column index) - OpTypeA - multiplication type: - * 0 - A*A^T is calculated - * 2 - A^T*A is calculated - Beta - coefficient - C - preallocated input/output matrix - IC - submatrix offset (row index) - JC - submatrix offset (column index) - IsUpper - whether C is upper triangular or lower triangular - - -- ALGLIB routine -- - 16.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -void rmatrixsyrk(const ae_int_t n, const ae_int_t k, const double alpha, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t optypea, const double beta, const real_2d_array &c, const ae_int_t ic, const ae_int_t jc, const bool isupper, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine calculates C = alpha*op1(A)*op2(B) +beta*C where: -* C is MxN general matrix -* op1(A) is MxK matrix -* op2(B) is KxN matrix -* "op" may be identity transformation, transposition, conjugate transposition - -Additional info: -* cache-oblivious algorithm is used. -* multiplication result replaces C. If Beta=0, C elements are not used in - calculations (not multiplied by zero - just not referenced) -* if Alpha=0, A is not used (not multiplied by zero - just not referenced) -* if both Beta and Alpha are zero, C is filled by zeros. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -IMPORTANT: - -This function does NOT preallocate output matrix C, it MUST be preallocated -by caller prior to calling this function. In case C does not have enough -space to store result, exception will be generated. - -INPUT PARAMETERS - M - matrix size, M>0 - N - matrix size, N>0 - K - matrix size, K>0 - Alpha - coefficient - A - matrix - IA - submatrix offset - JA - submatrix offset - OpTypeA - transformation type: - * 0 - no transformation - * 1 - transposition - * 2 - conjugate transposition - B - matrix - IB - submatrix offset - JB - submatrix offset - OpTypeB - transformation type: - * 0 - no transformation - * 1 - transposition - * 2 - conjugate transposition - Beta - coefficient - C - matrix (PREALLOCATED, large enough to store result) - IC - submatrix offset - JC - submatrix offset - - -- ALGLIB routine -- - 2009-2019 - Bochkanov Sergey -*************************************************************************/ -void cmatrixgemm(const ae_int_t m, const ae_int_t n, const ae_int_t k, const alglib::complex alpha, const complex_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t optypea, const complex_2d_array &b, const ae_int_t ib, const ae_int_t jb, const ae_int_t optypeb, const alglib::complex beta, const complex_2d_array &c, const ae_int_t ic, const ae_int_t jc, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine calculates C = alpha*op1(A)*op2(B) +beta*C where: -* C is MxN general matrix -* op1(A) is MxK matrix -* op2(B) is KxN matrix -* "op" may be identity transformation, transposition - -Additional info: -* cache-oblivious algorithm is used. -* multiplication result replaces C. If Beta=0, C elements are not used in - calculations (not multiplied by zero - just not referenced) -* if Alpha=0, A is not used (not multiplied by zero - just not referenced) -* if both Beta and Alpha are zero, C is filled by zeros. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -IMPORTANT: - -This function does NOT preallocate output matrix C, it MUST be preallocated -by caller prior to calling this function. In case C does not have enough -space to store result, exception will be generated. - -INPUT PARAMETERS - M - matrix size, M>0 - N - matrix size, N>0 - K - matrix size, K>0 - Alpha - coefficient - A - matrix - IA - submatrix offset - JA - submatrix offset - OpTypeA - transformation type: - * 0 - no transformation - * 1 - transposition - B - matrix - IB - submatrix offset - JB - submatrix offset - OpTypeB - transformation type: - * 0 - no transformation - * 1 - transposition - Beta - coefficient - C - PREALLOCATED output matrix, large enough to store result - IC - submatrix offset - JC - submatrix offset - - -- ALGLIB routine -- - 2009-2019 - Bochkanov Sergey -*************************************************************************/ -void rmatrixgemm(const ae_int_t m, const ae_int_t n, const ae_int_t k, const double alpha, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t optypea, const real_2d_array &b, const ae_int_t ib, const ae_int_t jb, const ae_int_t optypeb, const double beta, const real_2d_array &c, const ae_int_t ic, const ae_int_t jc, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine is an older version of CMatrixHERK(), one with wrong name -(it is HErmitian update, not SYmmetric). It is left here for backward -compatibility. - - -- ALGLIB routine -- - 16.12.2009 - Bochkanov Sergey -*************************************************************************/ -void cmatrixsyrk(const ae_int_t n, const ae_int_t k, const double alpha, const complex_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t optypea, const double beta, const complex_2d_array &c, const ae_int_t ic, const ae_int_t jc, const bool isupper, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_DLU) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPTRF) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_AMDORDERING) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SPCHOL) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MATGEN) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Generation of a random uniformly distributed (Haar) orthogonal matrix - -INPUT PARAMETERS: - N - matrix size, N>=1 - -OUTPUT PARAMETERS: - A - orthogonal NxN matrix, array[0..N-1,0..N-1] - -NOTE: this function uses algorithm described in Stewart, G. W. (1980), - "The Efficient Generation of Random Orthogonal Matrices with an - Application to Condition Estimators". - - Speaking short, to generate an (N+1)x(N+1) orthogonal matrix, it: - * takes an NxN one - * takes uniformly distributed unit vector of dimension N+1. - * constructs a Householder reflection from the vector, then applies - it to the smaller matrix (embedded in the larger size with a 1 at - the bottom right corner). - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void rmatrixrndorthogonal(const ae_int_t n, real_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Generation of random NxN matrix with given condition number and norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void rmatrixrndcond(const ae_int_t n, const double c, real_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Generation of a random Haar distributed orthogonal complex matrix - -INPUT PARAMETERS: - N - matrix size, N>=1 - -OUTPUT PARAMETERS: - A - orthogonal NxN matrix, array[0..N-1,0..N-1] - -NOTE: this function uses algorithm described in Stewart, G. W. (1980), - "The Efficient Generation of Random Orthogonal Matrices with an - Application to Condition Estimators". - - Speaking short, to generate an (N+1)x(N+1) orthogonal matrix, it: - * takes an NxN one - * takes uniformly distributed unit vector of dimension N+1. - * constructs a Householder reflection from the vector, then applies - it to the smaller matrix (embedded in the larger size with a 1 at - the bottom right corner). - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void cmatrixrndorthogonal(const ae_int_t n, complex_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Generation of random NxN complex matrix with given condition number C and -norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void cmatrixrndcond(const ae_int_t n, const double c, complex_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Generation of random NxN symmetric matrix with given condition number and -norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void smatrixrndcond(const ae_int_t n, const double c, real_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Generation of random NxN symmetric positive definite matrix with given -condition number and norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random SPD matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void spdmatrixrndcond(const ae_int_t n, const double c, real_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Generation of random NxN Hermitian matrix with given condition number and -norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void hmatrixrndcond(const ae_int_t n, const double c, complex_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Generation of random NxN Hermitian positive definite matrix with given -condition number and norm2(A)=1 - -INPUT PARAMETERS: - N - matrix size - C - condition number (in 2-norm) - -OUTPUT PARAMETERS: - A - random HPD matrix with norm2(A)=1 and cond(A)=C - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void hpdmatrixrndcond(const ae_int_t n, const double c, complex_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Multiplication of MxN matrix by NxN random Haar distributed orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..M-1, 0..N-1] - M, N- matrix size - -OUTPUT PARAMETERS: - A - A*Q, where Q is random NxN orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void rmatrixrndorthogonalfromtheright(real_2d_array &a, const ae_int_t m, const ae_int_t n, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Multiplication of MxN matrix by MxM random Haar distributed orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..M-1, 0..N-1] - M, N- matrix size - -OUTPUT PARAMETERS: - A - Q*A, where Q is random MxM orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void rmatrixrndorthogonalfromtheleft(real_2d_array &a, const ae_int_t m, const ae_int_t n, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Multiplication of MxN complex matrix by NxN random Haar distributed -complex orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..M-1, 0..N-1] - M, N- matrix size - -OUTPUT PARAMETERS: - A - A*Q, where Q is random NxN orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void cmatrixrndorthogonalfromtheright(complex_2d_array &a, const ae_int_t m, const ae_int_t n, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Multiplication of MxN complex matrix by MxM random Haar distributed -complex orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..M-1, 0..N-1] - M, N- matrix size - -OUTPUT PARAMETERS: - A - Q*A, where Q is random MxM orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void cmatrixrndorthogonalfromtheleft(complex_2d_array &a, const ae_int_t m, const ae_int_t n, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Symmetric multiplication of NxN matrix by random Haar distributed -orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..N-1, 0..N-1] - N - matrix size - -OUTPUT PARAMETERS: - A - Q'*A*Q, where Q is random NxN orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void smatrixrndmultiply(real_2d_array &a, const ae_int_t n, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Hermitian multiplication of NxN matrix by random Haar distributed -complex orthogonal matrix - -INPUT PARAMETERS: - A - matrix, array[0..N-1, 0..N-1] - N - matrix size - -OUTPUT PARAMETERS: - A - Q^H*A*Q, where Q is random NxN orthogonal matrix - - -- ALGLIB routine -- - 04.12.2009 - Bochkanov Sergey -*************************************************************************/ -void hmatrixrndmultiply(complex_2d_array &a, const ae_int_t n, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_TRFAC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -LU decomposition of a general real matrix with row pivoting - -A is represented as A = P*L*U, where: -* L is lower unitriangular matrix -* U is upper triangular matrix -* P = P0*P1*...*PK, K=min(M,N)-1, - Pi - permutation matrix for I and Pivots[I] - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - array[0..M-1, 0..N-1]. - M - number of rows in matrix A. - N - number of columns in matrix A. - - -OUTPUT PARAMETERS: - A - matrices L and U in compact form: - * L is stored under main diagonal - * U is stored on and above main diagonal - Pivots - permutation matrix in compact form. - array[0..Min(M-1,N-1)]. - - -- ALGLIB routine -- - 10.01.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixlu(real_2d_array &a, const ae_int_t m, const ae_int_t n, integer_1d_array &pivots, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -LU decomposition of a general complex matrix with row pivoting - -A is represented as A = P*L*U, where: -* L is lower unitriangular matrix -* U is upper triangular matrix -* P = P0*P1*...*PK, K=min(M,N)-1, - Pi - permutation matrix for I and Pivots[I] - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - array[0..M-1, 0..N-1]. - M - number of rows in matrix A. - N - number of columns in matrix A. - - -OUTPUT PARAMETERS: - A - matrices L and U in compact form: - * L is stored under main diagonal - * U is stored on and above main diagonal - Pivots - permutation matrix in compact form. - array[0..Min(M-1,N-1)]. - - -- ALGLIB routine -- - 10.01.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixlu(complex_2d_array &a, const ae_int_t m, const ae_int_t n, integer_1d_array &pivots, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Cache-oblivious Cholesky decomposition - -The algorithm computes Cholesky decomposition of a Hermitian positive- -definite matrix. The result of an algorithm is a representation of A as -A=U'*U or A=L*L' (here X' denotes conj(X^T)). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - upper or lower triangle of a factorized matrix. - array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - if IsUpper=True, then A contains an upper triangle of - a symmetric matrix, otherwise A contains a lower one. - -OUTPUT PARAMETERS: - A - the result of factorization. If IsUpper=True, then - the upper triangle contains matrix U, so that A = U'*U, - and the elements below the main diagonal are not modified. - Similarly, if IsUpper = False. - -RESULT: - If the matrix is positive-definite, the function returns True. - Otherwise, the function returns False. Contents of A is not determined - in such case. - - -- ALGLIB routine -- - 15.12.2009-22.01.2018 - Bochkanov Sergey -*************************************************************************/ -bool hpdmatrixcholesky(complex_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Cache-oblivious Cholesky decomposition - -The algorithm computes Cholesky decomposition of a symmetric positive- -definite matrix. The result of an algorithm is a representation of A as -A=U^T*U or A=L*L^T - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - upper or lower triangle of a factorized matrix. - array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - if IsUpper=True, then A contains an upper triangle of - a symmetric matrix, otherwise A contains a lower one. - -OUTPUT PARAMETERS: - A - the result of factorization. If IsUpper=True, then - the upper triangle contains matrix U, so that A = U^T*U, - and the elements below the main diagonal are not modified. - Similarly, if IsUpper = False. - -RESULT: - If the matrix is positive-definite, the function returns True. - Otherwise, the function returns False. Contents of A is not determined - in such case. - - -- ALGLIB routine -- - 15.12.2009 - Bochkanov Sergey -*************************************************************************/ -bool spdmatrixcholesky(real_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Update of Cholesky decomposition: rank-1 update to original A. "Buffered" -version which uses preallocated buffer which is saved between subsequent -function calls. - -This function uses internally allocated buffer which is not saved between -subsequent calls. So, if you perform a lot of subsequent updates, -we recommend you to use "buffered" version of this function: -SPDMatrixCholeskyUpdateAdd1Buf(). - -INPUT PARAMETERS: - A - upper or lower Cholesky factor. - array with elements [0..N-1, 0..N-1]. - Exception is thrown if array size is too small. - N - size of matrix A, N>0 - IsUpper - if IsUpper=True, then A contains upper Cholesky factor; - otherwise A contains a lower one. - U - array[N], rank-1 update to A: A_mod = A + u*u' - Exception is thrown if array size is too small. - BufR - possibly preallocated buffer; automatically resized if - needed. It is recommended to reuse this buffer if you - perform a lot of subsequent decompositions. - -OUTPUT PARAMETERS: - A - updated factorization. If IsUpper=True, then the upper - triangle contains matrix U, and the elements below the main - diagonal are not modified. Similarly, if IsUpper = False. - -NOTE: this function always succeeds, so it does not return completion code - -NOTE: this function checks sizes of input arrays, but it does NOT checks - for presence of infinities or NAN's. - - -- ALGLIB -- - 03.02.2014 - Sergey Bochkanov -*************************************************************************/ -void spdmatrixcholeskyupdateadd1(const real_2d_array &a, const ae_int_t n, const bool isupper, const real_1d_array &u, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Update of Cholesky decomposition: "fixing" some variables. - -This function uses internally allocated buffer which is not saved between -subsequent calls. So, if you perform a lot of subsequent updates, -we recommend you to use "buffered" version of this function: -SPDMatrixCholeskyUpdateFixBuf(). - -"FIXING" EXPLAINED: - - Suppose we have N*N positive definite matrix A. "Fixing" some variable - means filling corresponding row/column of A by zeros, and setting - diagonal element to 1. - - For example, if we fix 2nd variable in 4*4 matrix A, it becomes Af: - - ( A00 A01 A02 A03 ) ( Af00 0 Af02 Af03 ) - ( A10 A11 A12 A13 ) ( 0 1 0 0 ) - ( A20 A21 A22 A23 ) => ( Af20 0 Af22 Af23 ) - ( A30 A31 A32 A33 ) ( Af30 0 Af32 Af33 ) - - If we have Cholesky decomposition of A, it must be recalculated after - variables were fixed. However, it is possible to use efficient - algorithm, which needs O(K*N^2) time to "fix" K variables, given - Cholesky decomposition of original, "unfixed" A. - -INPUT PARAMETERS: - A - upper or lower Cholesky factor. - array with elements [0..N-1, 0..N-1]. - Exception is thrown if array size is too small. - N - size of matrix A, N>0 - IsUpper - if IsUpper=True, then A contains upper Cholesky factor; - otherwise A contains a lower one. - Fix - array[N], I-th element is True if I-th variable must be - fixed. Exception is thrown if array size is too small. - BufR - possibly preallocated buffer; automatically resized if - needed. It is recommended to reuse this buffer if you - perform a lot of subsequent decompositions. - -OUTPUT PARAMETERS: - A - updated factorization. If IsUpper=True, then the upper - triangle contains matrix U, and the elements below the main - diagonal are not modified. Similarly, if IsUpper = False. - -NOTE: this function always succeeds, so it does not return completion code - -NOTE: this function checks sizes of input arrays, but it does NOT checks - for presence of infinities or NAN's. - -NOTE: this function is efficient only for moderate amount of updated - variables - say, 0.1*N or 0.3*N. For larger amount of variables it - will still work, but you may get better performance with - straightforward Cholesky. - - -- ALGLIB -- - 03.02.2014 - Sergey Bochkanov -*************************************************************************/ -void spdmatrixcholeskyupdatefix(const real_2d_array &a, const ae_int_t n, const bool isupper, const boolean_1d_array &fix, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Update of Cholesky decomposition: rank-1 update to original A. "Buffered" -version which uses preallocated buffer which is saved between subsequent -function calls. - -See comments for SPDMatrixCholeskyUpdateAdd1() for more information. - -INPUT PARAMETERS: - A - upper or lower Cholesky factor. - array with elements [0..N-1, 0..N-1]. - Exception is thrown if array size is too small. - N - size of matrix A, N>0 - IsUpper - if IsUpper=True, then A contains upper Cholesky factor; - otherwise A contains a lower one. - U - array[N], rank-1 update to A: A_mod = A + u*u' - Exception is thrown if array size is too small. - BufR - possibly preallocated buffer; automatically resized if - needed. It is recommended to reuse this buffer if you - perform a lot of subsequent decompositions. - -OUTPUT PARAMETERS: - A - updated factorization. If IsUpper=True, then the upper - triangle contains matrix U, and the elements below the main - diagonal are not modified. Similarly, if IsUpper = False. - - -- ALGLIB -- - 03.02.2014 - Sergey Bochkanov -*************************************************************************/ -void spdmatrixcholeskyupdateadd1buf(const real_2d_array &a, const ae_int_t n, const bool isupper, const real_1d_array &u, real_1d_array &bufr, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Update of Cholesky decomposition: "fixing" some variables. "Buffered" -version which uses preallocated buffer which is saved between subsequent -function calls. - -See comments for SPDMatrixCholeskyUpdateFix() for more information. - -INPUT PARAMETERS: - A - upper or lower Cholesky factor. - array with elements [0..N-1, 0..N-1]. - Exception is thrown if array size is too small. - N - size of matrix A, N>0 - IsUpper - if IsUpper=True, then A contains upper Cholesky factor; - otherwise A contains a lower one. - Fix - array[N], I-th element is True if I-th variable must be - fixed. Exception is thrown if array size is too small. - BufR - possibly preallocated buffer; automatically resized if - needed. It is recommended to reuse this buffer if you - perform a lot of subsequent decompositions. - -OUTPUT PARAMETERS: - A - updated factorization. If IsUpper=True, then the upper - triangle contains matrix U, and the elements below the main - diagonal are not modified. Similarly, if IsUpper = False. - - -- ALGLIB -- - 03.02.2014 - Sergey Bochkanov -*************************************************************************/ -void spdmatrixcholeskyupdatefixbuf(const real_2d_array &a, const ae_int_t n, const bool isupper, const boolean_1d_array &fix, real_1d_array &bufr, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Sparse LU decomposition with column pivoting for sparsity and row pivoting -for stability. Input must be square sparse matrix stored in CRS format. - -The algorithm computes LU decomposition of a general square matrix -(rectangular ones are not supported). The result of an algorithm is a -representation of A as A = P*L*U*Q, where: -* L is lower unitriangular matrix -* U is upper triangular matrix -* P = P0*P1*...*PK, K=N-1, Pi - permutation matrix for I and P[I] -* Q = QK*...*Q1*Q0, K=N-1, Qi - permutation matrix for I and Q[I] - -This function pivots columns for higher sparsity, and then pivots rows for -stability (larger element at the diagonal). - -INPUT PARAMETERS: - A - sparse NxN matrix in CRS format. An exception is generated - if matrix is non-CRS or non-square. - PivotType- pivoting strategy: - * 0 for best pivoting available (2 in current version) - * 1 for row-only pivoting (NOT RECOMMENDED) - * 2 for complete pivoting which produces most sparse outputs - -OUTPUT PARAMETERS: - A - the result of factorization, matrices L and U stored in - compact form using CRS sparse storage format: - * lower unitriangular L is stored strictly under main diagonal - * upper triangilar U is stored ON and ABOVE main diagonal - P - row permutation matrix in compact form, array[N] - Q - col permutation matrix in compact form, array[N] - -This function always succeeds, i.e. it ALWAYS returns valid factorization, -but for your convenience it also returns boolean value which helps to -detect symbolically degenerate matrices: -* function returns TRUE, if the matrix was factorized AND symbolically - non-degenerate -* function returns FALSE, if the matrix was factorized but U has strictly - zero elements at the diagonal (the factorization is returned anyway). - - - -- ALGLIB routine -- - 03.09.2018 - Bochkanov Sergey -*************************************************************************/ -bool sparselu(const sparsematrix &a, const ae_int_t pivottype, integer_1d_array &p, integer_1d_array &q, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Sparse Cholesky decomposition for skyline matrixm using in-place algorithm -without allocating additional storage. - -The algorithm computes Cholesky decomposition of a symmetric positive- -definite sparse matrix. The result of an algorithm is a representation of -A as A=U^T*U or A=L*L^T - -This function allows to perform very efficient decomposition of low-profile -matrices (average bandwidth is ~5-10 elements). For larger matrices it is -recommended to use supernodal Cholesky decomposition: SparseCholeskyP() or -SparseCholeskyAnalyze()/SparseCholeskyFactorize(). - -INPUT PARAMETERS: - A - sparse matrix in skyline storage (SKS) format. - N - size of matrix A (can be smaller than actual size of A) - IsUpper - if IsUpper=True, then factorization is performed on upper - triangle. Another triangle is ignored (it may contant some - data, but it is not changed). - - -OUTPUT PARAMETERS: - A - the result of factorization, stored in SKS. If IsUpper=True, - then the upper triangle contains matrix U, such that - A = U^T*U. Lower triangle is not changed. - Similarly, if IsUpper = False. In this case L is returned, - and we have A = L*(L^T). - Note that THIS function does not perform permutation of - rows to reduce bandwidth. - -RESULT: - If the matrix is positive-definite, the function returns True. - Otherwise, the function returns False. Contents of A is not determined - in such case. - -NOTE: for performance reasons this function does NOT check that input - matrix includes only finite values. It is your responsibility to - make sure that there are no infinite or NAN values in the matrix. - - -- ALGLIB routine -- - 16.01.2014 - Bochkanov Sergey -*************************************************************************/ -bool sparsecholeskyskyline(const sparsematrix &a, const ae_int_t n, const bool isupper, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Sparse Cholesky decomposition for a matrix stored in any sparse storage, -without rows/cols permutation. - -This function is the most convenient (less parameters to specify), although -less efficient, version of sparse Cholesky. - -Internally it: -* calls SparseCholeskyAnalyze() function to perform symbolic analysis - phase with no permutation being configured. -* calls SparseCholeskyFactorize() function to perform numerical phase of - the factorization - -Following alternatives may result in better performance: -* using SparseCholeskyP(), which selects best pivoting available, which - almost always results in improved sparsity and cache locality -* using SparseCholeskyAnalyze() and SparseCholeskyFactorize() functions - directly, which may improve performance of repetitive factorizations - with same sparsity patterns. - -The latter also allows one to perform LDLT factorization of indefinite -matrix (one with strictly diagonal D, which is known to be stable only -in few special cases, like quasi-definite matrices). - -INPUT PARAMETERS: - A - a square NxN sparse matrix, stored in any storage format. - IsUpper - if IsUpper=True, then factorization is performed on upper - triangle. Another triangle is ignored on input, dropped - on output. Similarly, if IsUpper=False, the lower triangle - is processed. - -OUTPUT PARAMETERS: - A - the result of factorization, stored in CRS format: - * if IsUpper=True, then the upper triangle contains matrix - U such that A = U^T*U and the lower triangle is empty. - * similarly, if IsUpper=False, then lower triangular L is - returned and we have A = L*(L^T). - Note that THIS function does not perform permutation of - the rows to reduce fill-in. - -RESULT: - If the matrix is positive-definite, the function returns True. - Otherwise, the function returns False. Contents of A is undefined - in such case. - -NOTE: for performance reasons this function does NOT check that input - matrix includes only finite values. It is your responsibility to - make sure that there are no infinite or NAN values in the matrix. - - -- ALGLIB routine -- - 16.09.2020 - Bochkanov Sergey -*************************************************************************/ -bool sparsecholesky(const sparsematrix &a, const bool isupper, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Sparse Cholesky decomposition for a matrix stored in any sparse storage -format, with performance-enhancing permutation of rows/cols. - -Present version is configured to perform supernodal permutation which -sparsity reducing ordering. - -This function is a wrapper around generic sparse decomposition functions -that internally: -* calls SparseCholeskyAnalyze() function to perform symbolic analysis - phase with best available permutation being configured. -* calls SparseCholeskyFactorize() function to perform numerical phase of - the factorization. - -NOTE: using SparseCholeskyAnalyze() and SparseCholeskyFactorize() directly - may improve performance of repetitive factorizations with same - sparsity patterns. It also allows one to perform LDLT factorization - of indefinite matrix - a factorization with strictly diagonal D, - which is known to be stable only in few special cases, like quasi- - definite matrices. - -INPUT PARAMETERS: - A - a square NxN sparse matrix, stored in any storage format. - IsUpper - if IsUpper=True, then factorization is performed on upper - triangle. Another triangle is ignored on input, dropped - on output. Similarly, if IsUpper=False, the lower triangle - is processed. - -OUTPUT PARAMETERS: - A - the result of factorization, stored in CRS format: - * if IsUpper=True, then the upper triangle contains matrix - U such that A = U^T*U and the lower triangle is empty. - * similarly, if IsUpper=False, then lower triangular L is - returned and we have A = L*(L^T). - P - a row/column permutation, a product of P0*P1*...*Pk, k=N-1, - with Pi being permutation of rows/cols I and P[I] - -RESULT: - If the matrix is positive-definite, the function returns True. - Otherwise, the function returns False. Contents of A is undefined - in such case. - -NOTE: for performance reasons this function does NOT check that input - matrix includes only finite values. It is your responsibility to - make sure that there are no infinite or NAN values in the matrix. - - -- ALGLIB routine -- - 16.09.2020 - Bochkanov Sergey -*************************************************************************/ -bool sparsecholeskyp(const sparsematrix &a, const bool isupper, integer_1d_array &p, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Sparse Cholesky/LDLT decomposition: symbolic analysis phase. - -This function is a part of the 'expert' sparse Cholesky API: -* SparseCholeskyAnalyze(), that performs symbolic analysis phase and loads - matrix to be factorized into internal storage -* SparseCholeskySetModType(), that allows to use modified Cholesky/LDLT - with lower bounds on pivot magnitudes and additional overflow safeguards -* SparseCholeskyFactorize(), that performs numeric factorization using - precomputed symbolic analysis and internally stored matrix - and outputs - result -* SparseCholeskyReload(), that reloads one more matrix with same sparsity - pattern into internal storage so one may reuse previously allocated - temporaries and previously performed symbolic analysis - -This specific function performs preliminary analysis of the Cholesky/LDLT -factorization. It allows to choose different permutation types and to -choose between classic Cholesky and indefinite LDLT factorization (the -latter is computed with strictly diagonal D, i.e. without Bunch-Kauffman -pivoting). - -NOTE: L*D*LT family of factorization may be used to factorize indefinite - matrices. However, numerical stability is guaranteed ONLY for a class - of quasi-definite matrices. - -NOTE: all internal processing is performed with lower triangular matrices - stored in CRS format. Any other storage formats and/or upper - triangular storage means that one format conversion and/or one - transposition will be performed internally for the analysis and - factorization phases. Thus, highest performance is achieved when - input is a lower triangular CRS matrix. - -INPUT PARAMETERS: - A - sparse square matrix in any sparse storage format. - IsUpper - whether upper or lower triangle is decomposed (the - other one is ignored). - FactType - factorization type: - * 0 for traditional Cholesky of SPD matrix - * 1 for LDLT decomposition with strictly diagonal D, - which may have non-positive entries. - PermType - permutation type: - *-1 for absence of permutation - * 0 for best fill-in reducing permutation available - * 1 for supernodal ordering (improves locality and - performance, does NOT change fill-in factor) - * 2 for AMD (approximate minimum degree) ordering - -OUTPUT PARAMETERS: - Analysis - contains: - * symbolic analysis of the matrix structure which will - be used later to guide numerical factorization. - * specific numeric values loaded into internal memory - waiting for the factorization to be performed - -This function fails if and only if the matrix A is symbolically degenerate -i.e. has diagonal element which is exactly zero. In such case False is -returned, contents of Analysis object is undefined. - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -bool sparsecholeskyanalyze(const sparsematrix &a, const bool isupper, const ae_int_t facttype, const ae_int_t permtype, sparsedecompositionanalysis &analysis, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Sparse Cholesky decomposition: numerical analysis phase. - -This function is a part of the 'expert' sparse Cholesky API: -* SparseCholeskyAnalyze(), that performs symbolic analysis phase and loads - matrix to be factorized into internal storage -* SparseCholeskySetModType(), that allows to use modified Cholesky/LDLT - with lower bounds on pivot magnitudes and additional overflow safeguards -* SparseCholeskyFactorize(), that performs numeric factorization using - precomputed symbolic analysis and internally stored matrix - and outputs - result -* SparseCholeskyReload(), that reloads one more matrix with same sparsity - pattern into internal storage so one may reuse previously allocated - temporaries and previously performed symbolic analysis - -Depending on settings specified during SparseCholeskyAnalyze() call it may -produce classic Cholesky or L*D*LT decomposition (with strictly diagonal -D), without permutation or with performance-enhancing permutation P. - -NOTE: all internal processing is performed with lower triangular matrices - stored in CRS format. Any other storage formats and/or upper - triangular storage means that one format conversion and/or one - transposition will be performed internally for the analysis and - factorization phases. Thus, highest performance is achieved when - input is a lower triangular CRS matrix, and lower triangular output - is requested. - -NOTE: L*D*LT family of factorization may be used to factorize indefinite - matrices. However, numerical stability is guaranteed ONLY for a class - of quasi-definite matrices. - -INPUT PARAMETERS: - Analysis - prior analysis with internally stored matrix which will - be factorized - NeedUpper - whether upper triangular or lower triangular output is - needed - -OUTPUT PARAMETERS: - A - Cholesky decomposition of A stored in lower triangular - CRS format, i.e. A=L*L' (or upper triangular CRS, with - A=U'*U, depending on NeedUpper parameter). - D - array[N], diagonal factor. If no diagonal factor was - required during analysis phase, still returned but - filled with 1's - P - array[N], pivots. Permutation matrix P is a product of - P(0)*P(1)*...*P(N-1), where P(i) is a permutation of - row/col I and P[I] (with P[I]>=I). - If no permutation was requested during analysis phase, - still returned but filled with identity permutation. - -The function returns True when factorization resulted in nondegenerate -matrix. False is returned when factorization fails (Cholesky factorization -of indefinite matrix) or LDLT factorization has exactly zero elements at -the diagonal. In the latter case contents of A, D and P is undefined. - -The analysis object is not changed during the factorization. Subsequent -calls to SparseCholeskyFactorize() will result in same factorization being -performed one more time. - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -bool sparsecholeskyfactorize(const sparsedecompositionanalysis &analysis, const bool needupper, sparsematrix &a, real_1d_array &d, integer_1d_array &p, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Sparse Cholesky decomposition: update internally stored matrix with -another one with exactly same sparsity pattern. - -This function is a part of the 'expert' sparse Cholesky API: -* SparseCholeskyAnalyze(), that performs symbolic analysis phase and loads - matrix to be factorized into internal storage -* SparseCholeskySetModType(), that allows to use modified Cholesky/LDLT - with lower bounds on pivot magnitudes and additional overflow safeguards -* SparseCholeskyFactorize(), that performs numeric factorization using - precomputed symbolic analysis and internally stored matrix - and outputs - result -* SparseCholeskyReload(), that reloads one more matrix with same sparsity - pattern into internal storage so one may reuse previously allocated - temporaries and previously performed symbolic analysis - -This specific function replaces internally stored numerical values with -ones from another sparse matrix (but having exactly same sparsity pattern -as one that was used for initial SparseCholeskyAnalyze() call). - -NOTE: all internal processing is performed with lower triangular matrices - stored in CRS format. Any other storage formats and/or upper - triangular storage means that one format conversion and/or one - transposition will be performed internally for the analysis and - factorization phases. Thus, highest performance is achieved when - input is a lower triangular CRS matrix. - -INPUT PARAMETERS: - Analysis - analysis object - A - sparse square matrix in any sparse storage format. It - MUST have exactly same sparsity pattern as that of the - matrix that was passed to SparseCholeskyAnalyze(). - Any difference (missing elements or additional elements) - may result in unpredictable and undefined behavior - - an algorithm may fail due to memory access violation. - IsUpper - whether upper or lower triangle is decomposed (the - other one is ignored). - -OUTPUT PARAMETERS: - Analysis - contains: - * symbolic analysis of the matrix structure which will - be used later to guide numerical factorization. - * specific numeric values loaded into internal memory - waiting for the factorization to be performed - - -- ALGLIB routine -- - 20.09.2020 - Bochkanov Sergey -*************************************************************************/ -void sparsecholeskyreload(const sparsedecompositionanalysis &analysis, const sparsematrix &a, const bool isupper, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_RCOND) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Estimate of a matrix condition number (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double rmatrixrcond1(const real_2d_array &a, const ae_int_t n, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Estimate of a matrix condition number (infinity-norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double rmatrixrcondinf(const real_2d_array &a, const ae_int_t n, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Condition number estimate of a symmetric positive definite matrix. - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -It should be noted that 1-norm and inf-norm of condition numbers of symmetric -matrices are equal, so the algorithm doesn't take into account the -differences between these types of norms. - -Input parameters: - A - symmetric positive definite matrix which is given by its - upper or lower triangle depending on the value of - IsUpper. Array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - storage format. - -Result: - 1/LowerBound(cond(A)), if matrix A is positive definite, - -1, if matrix A is not positive definite, and its condition number - could not be found by this algorithm. - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double spdmatrixrcond(const real_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Triangular matrix: estimate of a condition number (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array[0..N-1, 0..N-1]. - N - size of A. - IsUpper - True, if the matrix is upper triangular. - IsUnit - True, if the matrix has a unit diagonal. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double rmatrixtrrcond1(const real_2d_array &a, const ae_int_t n, const bool isupper, const bool isunit, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Triangular matrix: estimate of a matrix condition number (infinity-norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - True, if the matrix is upper triangular. - IsUnit - True, if the matrix has a unit diagonal. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double rmatrixtrrcondinf(const real_2d_array &a, const ae_int_t n, const bool isupper, const bool isunit, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Condition number estimate of a Hermitian positive definite matrix. - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -It should be noted that 1-norm and inf-norm of condition numbers of symmetric -matrices are equal, so the algorithm doesn't take into account the -differences between these types of norms. - -Input parameters: - A - Hermitian positive definite matrix which is given by its - upper or lower triangle depending on the value of - IsUpper. Array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - storage format. - -Result: - 1/LowerBound(cond(A)), if matrix A is positive definite, - -1, if matrix A is not positive definite, and its condition number - could not be found by this algorithm. - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double hpdmatrixrcond(const complex_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Estimate of a matrix condition number (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double cmatrixrcond1(const complex_2d_array &a, const ae_int_t n, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Estimate of a matrix condition number (infinity-norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double cmatrixrcondinf(const complex_2d_array &a, const ae_int_t n, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Estimate of the condition number of a matrix given by its LU decomposition (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - LUA - LU decomposition of a matrix in compact form. Output of - the RMatrixLU subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double rmatrixlurcond1(const real_2d_array &lua, const ae_int_t n, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Estimate of the condition number of a matrix given by its LU decomposition -(infinity norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - LUA - LU decomposition of a matrix in compact form. Output of - the RMatrixLU subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double rmatrixlurcondinf(const real_2d_array &lua, const ae_int_t n, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Condition number estimate of a symmetric positive definite matrix given by -Cholesky decomposition. - -The algorithm calculates a lower bound of the condition number. In this -case, the algorithm does not return a lower bound of the condition number, -but an inverse number (to avoid an overflow in case of a singular matrix). - -It should be noted that 1-norm and inf-norm condition numbers of symmetric -matrices are equal, so the algorithm doesn't take into account the -differences between these types of norms. - -Input parameters: - CD - Cholesky decomposition of matrix A, - output of SMatrixCholesky subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double spdmatrixcholeskyrcond(const real_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Condition number estimate of a Hermitian positive definite matrix given by -Cholesky decomposition. - -The algorithm calculates a lower bound of the condition number. In this -case, the algorithm does not return a lower bound of the condition number, -but an inverse number (to avoid an overflow in case of a singular matrix). - -It should be noted that 1-norm and inf-norm condition numbers of symmetric -matrices are equal, so the algorithm doesn't take into account the -differences between these types of norms. - -Input parameters: - CD - Cholesky decomposition of matrix A, - output of SMatrixCholesky subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double hpdmatrixcholeskyrcond(const complex_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Estimate of the condition number of a matrix given by its LU decomposition (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - LUA - LU decomposition of a matrix in compact form. Output of - the CMatrixLU subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double cmatrixlurcond1(const complex_2d_array &lua, const ae_int_t n, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Estimate of the condition number of a matrix given by its LU decomposition -(infinity norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - LUA - LU decomposition of a matrix in compact form. Output of - the CMatrixLU subroutine. - N - size of matrix A. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double cmatrixlurcondinf(const complex_2d_array &lua, const ae_int_t n, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Triangular matrix: estimate of a condition number (1-norm) - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array[0..N-1, 0..N-1]. - N - size of A. - IsUpper - True, if the matrix is upper triangular. - IsUnit - True, if the matrix has a unit diagonal. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double cmatrixtrrcond1(const complex_2d_array &a, const ae_int_t n, const bool isupper, const bool isunit, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Triangular matrix: estimate of a matrix condition number (infinity-norm). - -The algorithm calculates a lower bound of the condition number. In this case, -the algorithm does not return a lower bound of the condition number, but an -inverse number (to avoid an overflow in case of a singular matrix). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - True, if the matrix is upper triangular. - IsUnit - True, if the matrix has a unit diagonal. - -Result: 1/LowerBound(cond(A)) - -NOTE: - if k(A) is very large, then matrix is assumed degenerate, k(A)=INF, - 0.0 is returned in such cases. -*************************************************************************/ -double cmatrixtrrcondinf(const complex_2d_array &a, const ae_int_t n, const bool isupper, const bool isunit, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_MATINV) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Inversion of a matrix given by its LU decomposition. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - LU decomposition of the matrix - (output of RMatrixLU subroutine). - Pivots - table of permutations - (the output of RMatrixLU subroutine). - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - -OUTPUT PARAMETERS: - Info - return code: - * -3 A is singular, or VERY close to singular. - it is filled by zeros in such cases. - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - solver report, see below for more info - A - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - -SOLVER REPORT - -Subroutine sets following fields of the Rep structure: -* R1 reciprocal of condition number: 1/cond(A), 1-norm. -* RInf reciprocal of condition number: 1/cond(A), inf-norm. - - -- ALGLIB routine -- - 05.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixluinverse(real_2d_array &a, const integer_1d_array &pivots, const ae_int_t n, ae_int_t &info, matinvreport &rep, const xparams _xparams = alglib::xdefault); -void rmatrixluinverse(real_2d_array &a, const integer_1d_array &pivots, ae_int_t &info, matinvreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Inversion of a general matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - -Result: - True, if the matrix is not singular. - False, if the matrix is singular. - - -- ALGLIB -- - Copyright 2005-2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixinverse(real_2d_array &a, const ae_int_t n, ae_int_t &info, matinvreport &rep, const xparams _xparams = alglib::xdefault); -void rmatrixinverse(real_2d_array &a, ae_int_t &info, matinvreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Inversion of a matrix given by its LU decomposition. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - LU decomposition of the matrix - (output of CMatrixLU subroutine). - Pivots - table of permutations - (the output of CMatrixLU subroutine). - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - -OUTPUT PARAMETERS: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 05.02.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixluinverse(complex_2d_array &a, const integer_1d_array &pivots, const ae_int_t n, ae_int_t &info, matinvreport &rep, const xparams _xparams = alglib::xdefault); -void cmatrixluinverse(complex_2d_array &a, const integer_1d_array &pivots, ae_int_t &info, matinvreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Inversion of a general matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -void cmatrixinverse(complex_2d_array &a, const ae_int_t n, ae_int_t &info, matinvreport &rep, const xparams _xparams = alglib::xdefault); -void cmatrixinverse(complex_2d_array &a, ae_int_t &info, matinvreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Inversion of a symmetric positive definite matrix which is given -by Cholesky decomposition. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - Cholesky decomposition of the matrix to be inverted: - A=U'*U or A = L*L'. - Output of SPDMatrixCholesky subroutine. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - storage type (optional): - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, lower half is used. - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 10.02.2010 - Bochkanov Sergey -*************************************************************************/ -void spdmatrixcholeskyinverse(real_2d_array &a, const ae_int_t n, const bool isupper, ae_int_t &info, matinvreport &rep, const xparams _xparams = alglib::xdefault); -void spdmatrixcholeskyinverse(real_2d_array &a, ae_int_t &info, matinvreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Inversion of a symmetric positive definite matrix. - -Given an upper or lower triangle of a symmetric positive definite matrix, -the algorithm generates matrix A^-1 and saves the upper or lower triangle -depending on the input. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix to be inverted (upper or lower triangle). - Array with elements [0..N-1,0..N-1]. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - storage type (optional): - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, both lower and upper triangles must be - filled. - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 10.02.2010 - Bochkanov Sergey -*************************************************************************/ -void spdmatrixinverse(real_2d_array &a, const ae_int_t n, const bool isupper, ae_int_t &info, matinvreport &rep, const xparams _xparams = alglib::xdefault); -void spdmatrixinverse(real_2d_array &a, ae_int_t &info, matinvreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Inversion of a Hermitian positive definite matrix which is given -by Cholesky decomposition. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - Cholesky decomposition of the matrix to be inverted: - A=U'*U or A = L*L'. - Output of HPDMatrixCholesky subroutine. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - storage type (optional): - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, lower half is used. - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 10.02.2010 - Bochkanov Sergey -*************************************************************************/ -void hpdmatrixcholeskyinverse(complex_2d_array &a, const ae_int_t n, const bool isupper, ae_int_t &info, matinvreport &rep, const xparams _xparams = alglib::xdefault); -void hpdmatrixcholeskyinverse(complex_2d_array &a, ae_int_t &info, matinvreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Inversion of a Hermitian positive definite matrix. - -Given an upper or lower triangle of a Hermitian positive definite matrix, -the algorithm generates matrix A^-1 and saves the upper or lower triangle -depending on the input. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix to be inverted (upper or lower triangle). - Array with elements [0..N-1,0..N-1]. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - storage type (optional): - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, both lower and upper triangles must be - filled. - -Output parameters: - Info - return code, same as in RMatrixLUInverse - Rep - solver report, same as in RMatrixLUInverse - A - inverse of matrix A, same as in RMatrixLUInverse - - -- ALGLIB routine -- - 10.02.2010 - Bochkanov Sergey -*************************************************************************/ -void hpdmatrixinverse(complex_2d_array &a, const ae_int_t n, const bool isupper, ae_int_t &info, matinvreport &rep, const xparams _xparams = alglib::xdefault); -void hpdmatrixinverse(complex_2d_array &a, ae_int_t &info, matinvreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Triangular matrix inverse (real) - -The subroutine inverts the following types of matrices: - * upper triangular - * upper triangular with unit diagonal - * lower triangular - * lower triangular with unit diagonal - -In case of an upper (lower) triangular matrix, the inverse matrix will -also be upper (lower) triangular, and after the end of the algorithm, the -inverse matrix replaces the source matrix. The elements below (above) the -main diagonal are not changed by the algorithm. - -If the matrix has a unit diagonal, the inverse matrix also has a unit -diagonal, and the diagonal elements are not passed to the algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix, array[0..N-1, 0..N-1]. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - True, if the matrix is upper triangular. - IsUnit - diagonal type (optional): - * if True, matrix has unit diagonal (a[i,i] are NOT used) - * if False, matrix diagonal is arbitrary - * if not given, False is assumed - -Output parameters: - Info - same as for RMatrixLUInverse - Rep - same as for RMatrixLUInverse - A - same as for RMatrixLUInverse. - - -- ALGLIB -- - Copyright 05.02.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixtrinverse(real_2d_array &a, const ae_int_t n, const bool isupper, const bool isunit, ae_int_t &info, matinvreport &rep, const xparams _xparams = alglib::xdefault); -void rmatrixtrinverse(real_2d_array &a, const bool isupper, ae_int_t &info, matinvreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Triangular matrix inverse (complex) - -The subroutine inverts the following types of matrices: - * upper triangular - * upper triangular with unit diagonal - * lower triangular - * lower triangular with unit diagonal - -In case of an upper (lower) triangular matrix, the inverse matrix will -also be upper (lower) triangular, and after the end of the algorithm, the -inverse matrix replaces the source matrix. The elements below (above) the -main diagonal are not changed by the algorithm. - -If the matrix has a unit diagonal, the inverse matrix also has a unit -diagonal, and the diagonal elements are not passed to the algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix, array[0..N-1, 0..N-1]. - N - size of matrix A (optional) : - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, size is automatically determined from - matrix size (A must be square matrix) - IsUpper - True, if the matrix is upper triangular. - IsUnit - diagonal type (optional): - * if True, matrix has unit diagonal (a[i,i] are NOT used) - * if False, matrix diagonal is arbitrary - * if not given, False is assumed - -Output parameters: - Info - same as for RMatrixLUInverse - Rep - same as for RMatrixLUInverse - A - same as for RMatrixLUInverse. - - -- ALGLIB -- - Copyright 05.02.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixtrinverse(complex_2d_array &a, const ae_int_t n, const bool isupper, const bool isunit, ae_int_t &info, matinvreport &rep, const xparams _xparams = alglib::xdefault); -void cmatrixtrinverse(complex_2d_array &a, const bool isupper, ae_int_t &info, matinvreport &rep, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_ORTFAC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -QR decomposition of a rectangular matrix of size MxN - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix A whose indexes range within [0..M-1, 0..N-1]. - M - number of rows in matrix A. - N - number of columns in matrix A. - -Output parameters: - A - matrices Q and R in compact form (see below). - Tau - array of scalar factors which are used to form - matrix Q. Array whose index ranges within [0.. Min(M-1,N-1)]. - -Matrix A is represented as A = QR, where Q is an orthogonal matrix of size -MxM, R - upper triangular (or upper trapezoid) matrix of size M x N. - -The elements of matrix R are located on and above the main diagonal of -matrix A. The elements which are located in Tau array and below the main -diagonal of matrix A are used to form matrix Q as follows: - -Matrix Q is represented as a product of elementary reflections - -Q = H(0)*H(2)*...*H(k-1), - -where k = min(m,n), and each H(i) is in the form - -H(i) = 1 - tau * v * (v^T) - -where tau is a scalar stored in Tau[I]; v - real vector, -so that v(0:i-1) = 0, v(i) = 1, v(i+1:m-1) stored in A(i+1:m-1,i). - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixqr(real_2d_array &a, const ae_int_t m, const ae_int_t n, real_1d_array &tau, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -LQ decomposition of a rectangular matrix of size MxN - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix A whose indexes range within [0..M-1, 0..N-1]. - M - number of rows in matrix A. - N - number of columns in matrix A. - -Output parameters: - A - matrices L and Q in compact form (see below) - Tau - array of scalar factors which are used to form - matrix Q. Array whose index ranges within [0..Min(M,N)-1]. - -Matrix A is represented as A = LQ, where Q is an orthogonal matrix of size -MxM, L - lower triangular (or lower trapezoid) matrix of size M x N. - -The elements of matrix L are located on and below the main diagonal of -matrix A. The elements which are located in Tau array and above the main -diagonal of matrix A are used to form matrix Q as follows: - -Matrix Q is represented as a product of elementary reflections - -Q = H(k-1)*H(k-2)*...*H(1)*H(0), - -where k = min(m,n), and each H(i) is of the form - -H(i) = 1 - tau * v * (v^T) - -where tau is a scalar stored in Tau[I]; v - real vector, so that v(0:i-1)=0, -v(i) = 1, v(i+1:n-1) stored in A(i,i+1:n-1). - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixlq(real_2d_array &a, const ae_int_t m, const ae_int_t n, real_1d_array &tau, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -QR decomposition of a rectangular complex matrix of size MxN - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix A whose indexes range within [0..M-1, 0..N-1] - M - number of rows in matrix A. - N - number of columns in matrix A. - -Output parameters: - A - matrices Q and R in compact form - Tau - array of scalar factors which are used to form matrix Q. Array - whose indexes range within [0.. Min(M,N)-1] - -Matrix A is represented as A = QR, where Q is an orthogonal matrix of size -MxM, R - upper triangular (or upper trapezoid) matrix of size MxN. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994 -*************************************************************************/ -void cmatrixqr(complex_2d_array &a, const ae_int_t m, const ae_int_t n, complex_1d_array &tau, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -LQ decomposition of a rectangular complex matrix of size MxN - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix A whose indexes range within [0..M-1, 0..N-1] - M - number of rows in matrix A. - N - number of columns in matrix A. - -Output parameters: - A - matrices Q and L in compact form - Tau - array of scalar factors which are used to form matrix Q. Array - whose indexes range within [0.. Min(M,N)-1] - -Matrix A is represented as A = LQ, where Q is an orthogonal matrix of size -MxM, L - lower triangular (or lower trapezoid) matrix of size MxN. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994 -*************************************************************************/ -void cmatrixlq(complex_2d_array &a, const ae_int_t m, const ae_int_t n, complex_1d_array &tau, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Partial unpacking of matrix Q from the QR decomposition of a matrix A - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrices Q and R in compact form. - Output of RMatrixQR subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - Tau - scalar factors which are used to form Q. - Output of the RMatrixQR subroutine. - QColumns - required number of columns of matrix Q. M>=QColumns>=0. - -Output parameters: - Q - first QColumns columns of matrix Q. - Array whose indexes range within [0..M-1, 0..QColumns-1]. - If QColumns=0, the array remains unchanged. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixqrunpackq(const real_2d_array &a, const ae_int_t m, const ae_int_t n, const real_1d_array &tau, const ae_int_t qcolumns, real_2d_array &q, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Unpacking of matrix R from the QR decomposition of a matrix A - -Input parameters: - A - matrices Q and R in compact form. - Output of RMatrixQR subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - -Output parameters: - R - matrix R, array[0..M-1, 0..N-1]. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixqrunpackr(const real_2d_array &a, const ae_int_t m, const ae_int_t n, real_2d_array &r, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Partial unpacking of matrix Q from the LQ decomposition of a matrix A - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrices L and Q in compact form. - Output of RMatrixLQ subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - Tau - scalar factors which are used to form Q. - Output of the RMatrixLQ subroutine. - QRows - required number of rows in matrix Q. N>=QRows>=0. - -Output parameters: - Q - first QRows rows of matrix Q. Array whose indexes range - within [0..QRows-1, 0..N-1]. If QRows=0, the array remains - unchanged. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixlqunpackq(const real_2d_array &a, const ae_int_t m, const ae_int_t n, const real_1d_array &tau, const ae_int_t qrows, real_2d_array &q, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Unpacking of matrix L from the LQ decomposition of a matrix A - -Input parameters: - A - matrices Q and L in compact form. - Output of RMatrixLQ subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - -Output parameters: - L - matrix L, array[0..M-1, 0..N-1]. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixlqunpackl(const real_2d_array &a, const ae_int_t m, const ae_int_t n, real_2d_array &l, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Partial unpacking of matrix Q from QR decomposition of a complex matrix A. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrices Q and R in compact form. - Output of CMatrixQR subroutine . - M - number of rows in matrix A. M>=0. - N - number of columns in matrix A. N>=0. - Tau - scalar factors which are used to form Q. - Output of CMatrixQR subroutine . - QColumns - required number of columns in matrix Q. M>=QColumns>=0. - -Output parameters: - Q - first QColumns columns of matrix Q. - Array whose index ranges within [0..M-1, 0..QColumns-1]. - If QColumns=0, array isn't changed. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixqrunpackq(const complex_2d_array &a, const ae_int_t m, const ae_int_t n, const complex_1d_array &tau, const ae_int_t qcolumns, complex_2d_array &q, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Unpacking of matrix R from the QR decomposition of a matrix A - -Input parameters: - A - matrices Q and R in compact form. - Output of CMatrixQR subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - -Output parameters: - R - matrix R, array[0..M-1, 0..N-1]. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixqrunpackr(const complex_2d_array &a, const ae_int_t m, const ae_int_t n, complex_2d_array &r, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Partial unpacking of matrix Q from LQ decomposition of a complex matrix A. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrices Q and R in compact form. - Output of CMatrixLQ subroutine . - M - number of rows in matrix A. M>=0. - N - number of columns in matrix A. N>=0. - Tau - scalar factors which are used to form Q. - Output of CMatrixLQ subroutine . - QRows - required number of rows in matrix Q. N>=QColumns>=0. - -Output parameters: - Q - first QRows rows of matrix Q. - Array whose index ranges within [0..QRows-1, 0..N-1]. - If QRows=0, array isn't changed. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixlqunpackq(const complex_2d_array &a, const ae_int_t m, const ae_int_t n, const complex_1d_array &tau, const ae_int_t qrows, complex_2d_array &q, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Unpacking of matrix L from the LQ decomposition of a matrix A - -Input parameters: - A - matrices Q and L in compact form. - Output of CMatrixLQ subroutine. - M - number of rows in given matrix A. M>=0. - N - number of columns in given matrix A. N>=0. - -Output parameters: - L - matrix L, array[0..M-1, 0..N-1]. - - -- ALGLIB routine -- - 17.02.2010 - Bochkanov Sergey -*************************************************************************/ -void cmatrixlqunpackl(const complex_2d_array &a, const ae_int_t m, const ae_int_t n, complex_2d_array &l, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Reduction of a rectangular matrix to bidiagonal form - -The algorithm reduces the rectangular matrix A to bidiagonal form by -orthogonal transformations P and Q: A = Q*B*(P^T). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - source matrix. array[0..M-1, 0..N-1] - M - number of rows in matrix A. - N - number of columns in matrix A. - -Output parameters: - A - matrices Q, B, P in compact form (see below). - TauQ - scalar factors which are used to form matrix Q. - TauP - scalar factors which are used to form matrix P. - -The main diagonal and one of the secondary diagonals of matrix A are -replaced with bidiagonal matrix B. Other elements contain elementary -reflections which form MxM matrix Q and NxN matrix P, respectively. - -If M>=N, B is the upper bidiagonal MxN matrix and is stored in the -corresponding elements of matrix A. Matrix Q is represented as a -product of elementary reflections Q = H(0)*H(1)*...*H(n-1), where -H(i) = 1-tau*v*v'. Here tau is a scalar which is stored in TauQ[i], and -vector v has the following structure: v(0:i-1)=0, v(i)=1, v(i+1:m-1) is -stored in elements A(i+1:m-1,i). Matrix P is as follows: P = -G(0)*G(1)*...*G(n-2), where G(i) = 1 - tau*u*u'. Tau is stored in TauP[i], -u(0:i)=0, u(i+1)=1, u(i+2:n-1) is stored in elements A(i,i+2:n-1). - -If M n): m=5, n=6 (m < n): - -( d e u1 u1 u1 ) ( d u1 u1 u1 u1 u1 ) -( v1 d e u2 u2 ) ( e d u2 u2 u2 u2 ) -( v1 v2 d e u3 ) ( v1 e d u3 u3 u3 ) -( v1 v2 v3 d e ) ( v1 v2 e d u4 u4 ) -( v1 v2 v3 v4 d ) ( v1 v2 v3 e d u5 ) -( v1 v2 v3 v4 v5 ) - -Here vi and ui are vectors which form H(i) and G(i), and d and e - -are the diagonal and off-diagonal elements of matrix B. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994. - Sergey Bochkanov, ALGLIB project, translation from FORTRAN to - pseudocode, 2007-2010. -*************************************************************************/ -void rmatrixbd(real_2d_array &a, const ae_int_t m, const ae_int_t n, real_1d_array &tauq, real_1d_array &taup, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Unpacking matrix Q which reduces a matrix to bidiagonal form. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - QP - matrices Q and P in compact form. - Output of ToBidiagonal subroutine. - M - number of rows in matrix A. - N - number of columns in matrix A. - TAUQ - scalar factors which are used to form Q. - Output of ToBidiagonal subroutine. - QColumns - required number of columns in matrix Q. - M>=QColumns>=0. - -Output parameters: - Q - first QColumns columns of matrix Q. - Array[0..M-1, 0..QColumns-1] - If QColumns=0, the array is not modified. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixbdunpackq(const real_2d_array &qp, const ae_int_t m, const ae_int_t n, const real_1d_array &tauq, const ae_int_t qcolumns, real_2d_array &q, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Multiplication by matrix Q which reduces matrix A to bidiagonal form. - -The algorithm allows pre- or post-multiply by Q or Q'. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - QP - matrices Q and P in compact form. - Output of ToBidiagonal subroutine. - M - number of rows in matrix A. - N - number of columns in matrix A. - TAUQ - scalar factors which are used to form Q. - Output of ToBidiagonal subroutine. - Z - multiplied matrix. - array[0..ZRows-1,0..ZColumns-1] - ZRows - number of rows in matrix Z. If FromTheRight=False, - ZRows=M, otherwise ZRows can be arbitrary. - ZColumns - number of columns in matrix Z. If FromTheRight=True, - ZColumns=M, otherwise ZColumns can be arbitrary. - FromTheRight - pre- or post-multiply. - DoTranspose - multiply by Q or Q'. - -Output parameters: - Z - product of Z and Q. - Array[0..ZRows-1,0..ZColumns-1] - If ZRows=0 or ZColumns=0, the array is not modified. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixbdmultiplybyq(const real_2d_array &qp, const ae_int_t m, const ae_int_t n, const real_1d_array &tauq, real_2d_array &z, const ae_int_t zrows, const ae_int_t zcolumns, const bool fromtheright, const bool dotranspose, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Unpacking matrix P which reduces matrix A to bidiagonal form. -The subroutine returns transposed matrix P. - -Input parameters: - QP - matrices Q and P in compact form. - Output of ToBidiagonal subroutine. - M - number of rows in matrix A. - N - number of columns in matrix A. - TAUP - scalar factors which are used to form P. - Output of ToBidiagonal subroutine. - PTRows - required number of rows of matrix P^T. N >= PTRows >= 0. - -Output parameters: - PT - first PTRows columns of matrix P^T - Array[0..PTRows-1, 0..N-1] - If PTRows=0, the array is not modified. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixbdunpackpt(const real_2d_array &qp, const ae_int_t m, const ae_int_t n, const real_1d_array &taup, const ae_int_t ptrows, real_2d_array &pt, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Multiplication by matrix P which reduces matrix A to bidiagonal form. - -The algorithm allows pre- or post-multiply by P or P'. - -Input parameters: - QP - matrices Q and P in compact form. - Output of RMatrixBD subroutine. - M - number of rows in matrix A. - N - number of columns in matrix A. - TAUP - scalar factors which are used to form P. - Output of RMatrixBD subroutine. - Z - multiplied matrix. - Array whose indexes range within [0..ZRows-1,0..ZColumns-1]. - ZRows - number of rows in matrix Z. If FromTheRight=False, - ZRows=N, otherwise ZRows can be arbitrary. - ZColumns - number of columns in matrix Z. If FromTheRight=True, - ZColumns=N, otherwise ZColumns can be arbitrary. - FromTheRight - pre- or post-multiply. - DoTranspose - multiply by P or P'. - -Output parameters: - Z - product of Z and P. - Array whose indexes range within [0..ZRows-1,0..ZColumns-1]. - If ZRows=0 or ZColumns=0, the array is not modified. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixbdmultiplybyp(const real_2d_array &qp, const ae_int_t m, const ae_int_t n, const real_1d_array &taup, real_2d_array &z, const ae_int_t zrows, const ae_int_t zcolumns, const bool fromtheright, const bool dotranspose, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Unpacking of the main and secondary diagonals of bidiagonal decomposition -of matrix A. - -Input parameters: - B - output of RMatrixBD subroutine. - M - number of rows in matrix B. - N - number of columns in matrix B. - -Output parameters: - IsUpper - True, if the matrix is upper bidiagonal. - otherwise IsUpper is False. - D - the main diagonal. - Array whose index ranges within [0..Min(M,N)-1]. - E - the secondary diagonal (upper or lower, depending on - the value of IsUpper). - Array index ranges within [0..Min(M,N)-1], the last - element is not used. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixbdunpackdiagonals(const real_2d_array &b, const ae_int_t m, const ae_int_t n, bool &isupper, real_1d_array &d, real_1d_array &e, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Reduction of a square matrix to upper Hessenberg form: Q'*A*Q = H, -where Q is an orthogonal matrix, H - Hessenberg matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix A with elements [0..N-1, 0..N-1] - N - size of matrix A. - -Output parameters: - A - matrices Q and P in compact form (see below). - Tau - array of scalar factors which are used to form matrix Q. - Array whose index ranges within [0..N-2] - -Matrix H is located on the main diagonal, on the lower secondary diagonal -and above the main diagonal of matrix A. The elements which are used to -form matrix Q are situated in array Tau and below the lower secondary -diagonal of matrix A as follows: - -Matrix Q is represented as a product of elementary reflections - -Q = H(0)*H(2)*...*H(n-2), - -where each H(i) is given by - -H(i) = 1 - tau * v * (v^T) - -where tau is a scalar stored in Tau[I]; v - is a real vector, -so that v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) stored in A(i+2:n-1,i). - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - October 31, 1992 -*************************************************************************/ -void rmatrixhessenberg(real_2d_array &a, const ae_int_t n, real_1d_array &tau, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Unpacking matrix Q which reduces matrix A to upper Hessenberg form - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - output of RMatrixHessenberg subroutine. - N - size of matrix A. - Tau - scalar factors which are used to form Q. - Output of RMatrixHessenberg subroutine. - -Output parameters: - Q - matrix Q. - Array whose indexes range within [0..N-1, 0..N-1]. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixhessenbergunpackq(const real_2d_array &a, const ae_int_t n, const real_1d_array &tau, real_2d_array &q, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Unpacking matrix H (the result of matrix A reduction to upper Hessenberg form) - -Input parameters: - A - output of RMatrixHessenberg subroutine. - N - size of matrix A. - -Output parameters: - H - matrix H. Array whose indexes range within [0..N-1, 0..N-1]. - - -- ALGLIB -- - 2005-2010 - Bochkanov Sergey -*************************************************************************/ -void rmatrixhessenbergunpackh(const real_2d_array &a, const ae_int_t n, real_2d_array &h, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Reduction of a symmetric matrix which is given by its higher or lower -triangular part to a tridiagonal matrix using orthogonal similarity -transformation: Q'*A*Q=T. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix to be transformed - array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - storage format. If IsUpper = True, then matrix A is given - by its upper triangle, and the lower triangle is not used - and not modified by the algorithm, and vice versa - if IsUpper = False. - -Output parameters: - A - matrices T and Q in compact form (see lower) - Tau - array of factors which are forming matrices H(i) - array with elements [0..N-2]. - D - main diagonal of symmetric matrix T. - array with elements [0..N-1]. - E - secondary diagonal of symmetric matrix T. - array with elements [0..N-2]. - - - If IsUpper=True, the matrix Q is represented as a product of elementary - reflectors - - Q = H(n-2) . . . H(2) H(0). - - Each H(i) has the form - - H(i) = I - tau * v * v' - - where tau is a real scalar, and v is a real vector with - v(i+1:n-1) = 0, v(i) = 1, v(0:i-1) is stored on exit in - A(0:i-1,i+1), and tau in TAU(i). - - If IsUpper=False, the matrix Q is represented as a product of elementary - reflectors - - Q = H(0) H(2) . . . H(n-2). - - Each H(i) has the form - - H(i) = I - tau * v * v' - - where tau is a real scalar, and v is a real vector with - v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) is stored on exit in A(i+2:n-1,i), - and tau in TAU(i). - - The contents of A on exit are illustrated by the following examples - with n = 5: - - if UPLO = 'U': if UPLO = 'L': - - ( d e v1 v2 v3 ) ( d ) - ( d e v2 v3 ) ( e d ) - ( d e v3 ) ( v0 e d ) - ( d e ) ( v0 v1 e d ) - ( d ) ( v0 v1 v2 e d ) - - where d and e denote diagonal and off-diagonal elements of T, and vi - denotes an element of the vector defining H(i). - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - October 31, 1992 -*************************************************************************/ -void smatrixtd(real_2d_array &a, const ae_int_t n, const bool isupper, real_1d_array &tau, real_1d_array &d, real_1d_array &e, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Unpacking matrix Q which reduces symmetric matrix to a tridiagonal -form. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - the result of a SMatrixTD subroutine - N - size of matrix A. - IsUpper - storage format (a parameter of SMatrixTD subroutine) - Tau - the result of a SMatrixTD subroutine - -Output parameters: - Q - transformation matrix. - array with elements [0..N-1, 0..N-1]. - - -- ALGLIB -- - Copyright 2005-2010 by Bochkanov Sergey -*************************************************************************/ -void smatrixtdunpackq(const real_2d_array &a, const ae_int_t n, const bool isupper, const real_1d_array &tau, real_2d_array &q, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Reduction of a Hermitian matrix which is given by its higher or lower -triangular part to a real tridiagonal matrix using unitary similarity -transformation: Q'*A*Q = T. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - matrix to be transformed - array with elements [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - storage format. If IsUpper = True, then matrix A is given - by its upper triangle, and the lower triangle is not used - and not modified by the algorithm, and vice versa - if IsUpper = False. - -Output parameters: - A - matrices T and Q in compact form (see lower) - Tau - array of factors which are forming matrices H(i) - array with elements [0..N-2]. - D - main diagonal of real symmetric matrix T. - array with elements [0..N-1]. - E - secondary diagonal of real symmetric matrix T. - array with elements [0..N-2]. - - - If IsUpper=True, the matrix Q is represented as a product of elementary - reflectors - - Q = H(n-2) . . . H(2) H(0). - - Each H(i) has the form - - H(i) = I - tau * v * v' - - where tau is a complex scalar, and v is a complex vector with - v(i+1:n-1) = 0, v(i) = 1, v(0:i-1) is stored on exit in - A(0:i-1,i+1), and tau in TAU(i). - - If IsUpper=False, the matrix Q is represented as a product of elementary - reflectors - - Q = H(0) H(2) . . . H(n-2). - - Each H(i) has the form - - H(i) = I - tau * v * v' - - where tau is a complex scalar, and v is a complex vector with - v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) is stored on exit in A(i+2:n-1,i), - and tau in TAU(i). - - The contents of A on exit are illustrated by the following examples - with n = 5: - - if UPLO = 'U': if UPLO = 'L': - - ( d e v1 v2 v3 ) ( d ) - ( d e v2 v3 ) ( e d ) - ( d e v3 ) ( v0 e d ) - ( d e ) ( v0 v1 e d ) - ( d ) ( v0 v1 v2 e d ) - -where d and e denote diagonal and off-diagonal elements of T, and vi -denotes an element of the vector defining H(i). - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - October 31, 1992 -*************************************************************************/ -void hmatrixtd(complex_2d_array &a, const ae_int_t n, const bool isupper, complex_1d_array &tau, real_1d_array &d, real_1d_array &e, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Unpacking matrix Q which reduces a Hermitian matrix to a real tridiagonal -form. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - the result of a HMatrixTD subroutine - N - size of matrix A. - IsUpper - storage format (a parameter of HMatrixTD subroutine) - Tau - the result of a HMatrixTD subroutine - -Output parameters: - Q - transformation matrix. - array with elements [0..N-1, 0..N-1]. - - -- ALGLIB -- - Copyright 2005-2010 by Bochkanov Sergey -*************************************************************************/ -void hmatrixtdunpackq(const complex_2d_array &a, const ae_int_t n, const bool isupper, const complex_1d_array &tau, complex_2d_array &q, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_FBLS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_BDSVD) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Singular value decomposition of a bidiagonal matrix (extended algorithm) - -COMMERCIAL EDITION OF ALGLIB: - - ! Commercial version of ALGLIB includes one important improvement of - ! this function, which can be used from C++ and C#: - ! * Intel MKL support (lightweight Intel MKL is shipped with ALGLIB) - ! - ! Intel MKL gives approximately constant (with respect to number of - ! worker threads) acceleration factor which depends on CPU being used, - ! problem size and "baseline" ALGLIB edition which is used for - ! comparison. - ! - ! Generally, commercial ALGLIB is several times faster than open-source - ! generic C edition, and many times faster than open-source C# edition. - ! - ! Multithreaded acceleration is NOT supported for this function. - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -The algorithm performs the singular value decomposition of a bidiagonal -matrix B (upper or lower) representing it as B = Q*S*P^T, where Q and P - -orthogonal matrices, S - diagonal matrix with non-negative elements on the -main diagonal, in descending order. - -The algorithm finds singular values. In addition, the algorithm can -calculate matrices Q and P (more precisely, not the matrices, but their -product with given matrices U and VT - U*Q and (P^T)*VT)). Of course, -matrices U and VT can be of any type, including identity. Furthermore, the -algorithm can calculate Q'*C (this product is calculated more effectively -than U*Q, because this calculation operates with rows instead of matrix -columns). - -The feature of the algorithm is its ability to find all singular values -including those which are arbitrarily close to 0 with relative accuracy -close to machine precision. If the parameter IsFractionalAccuracyRequired -is set to True, all singular values will have high relative accuracy close -to machine precision. If the parameter is set to False, only the biggest -singular value will have relative accuracy close to machine precision. -The absolute error of other singular values is equal to the absolute error -of the biggest singular value. - -Input parameters: - D - main diagonal of matrix B. - Array whose index ranges within [0..N-1]. - E - superdiagonal (or subdiagonal) of matrix B. - Array whose index ranges within [0..N-2]. - N - size of matrix B. - IsUpper - True, if the matrix is upper bidiagonal. - IsFractionalAccuracyRequired - - THIS PARAMETER IS IGNORED SINCE ALGLIB 3.5.0 - SINGULAR VALUES ARE ALWAYS SEARCHED WITH HIGH ACCURACY. - U - matrix to be multiplied by Q. - Array whose indexes range within [0..NRU-1, 0..N-1]. - The matrix can be bigger, in that case only the submatrix - [0..NRU-1, 0..N-1] will be multiplied by Q. - NRU - number of rows in matrix U. - C - matrix to be multiplied by Q'. - Array whose indexes range within [0..N-1, 0..NCC-1]. - The matrix can be bigger, in that case only the submatrix - [0..N-1, 0..NCC-1] will be multiplied by Q'. - NCC - number of columns in matrix C. - VT - matrix to be multiplied by P^T. - Array whose indexes range within [0..N-1, 0..NCVT-1]. - The matrix can be bigger, in that case only the submatrix - [0..N-1, 0..NCVT-1] will be multiplied by P^T. - NCVT - number of columns in matrix VT. - -Output parameters: - D - singular values of matrix B in descending order. - U - if NRU>0, contains matrix U*Q. - VT - if NCVT>0, contains matrix (P^T)*VT. - C - if NCC>0, contains matrix Q'*C. - -Result: - True, if the algorithm has converged. - False, if the algorithm hasn't converged (rare case). - -NOTE: multiplication U*Q is performed by means of transposition to internal - buffer, multiplication and backward transposition. It helps to avoid - costly columnwise operations and speed-up algorithm. - -Additional information: - The type of convergence is controlled by the internal parameter TOL. - If the parameter is greater than 0, the singular values will have - relative accuracy TOL. If TOL<0, the singular values will have - absolute accuracy ABS(TOL)*norm(B). - By default, |TOL| falls within the range of 10*Epsilon and 100*Epsilon, - where Epsilon is the machine precision. It is not recommended to use - TOL less than 10*Epsilon since this will considerably slow down the - algorithm and may not lead to error decreasing. - -History: - * 31 March, 2007. - changed MAXITR from 6 to 12. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - October 31, 1999. -*************************************************************************/ -bool rmatrixbdsvd(real_1d_array &d, const real_1d_array &e, const ae_int_t n, const bool isupper, const bool isfractionalaccuracyrequired, real_2d_array &u, const ae_int_t nru, real_2d_array &c, const ae_int_t ncc, real_2d_array &vt, const ae_int_t ncvt, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_SVD) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Singular value decomposition of a rectangular matrix. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -The algorithm calculates the singular value decomposition of a matrix of -size MxN: A = U * S * V^T - -The algorithm finds the singular values and, optionally, matrices U and V^T. -The algorithm can find both first min(M,N) columns of matrix U and rows of -matrix V^T (singular vectors), and matrices U and V^T wholly (of sizes MxM -and NxN respectively). - -Take into account that the subroutine does not return matrix V but V^T. - -Input parameters: - A - matrix to be decomposed. - Array whose indexes range within [0..M-1, 0..N-1]. - M - number of rows in matrix A. - N - number of columns in matrix A. - UNeeded - 0, 1 or 2. See the description of the parameter U. - VTNeeded - 0, 1 or 2. See the description of the parameter VT. - AdditionalMemory - - If the parameter: - * equals 0, the algorithm doesn't use additional - memory (lower requirements, lower performance). - * equals 1, the algorithm uses additional - memory of size min(M,N)*min(M,N) of real numbers. - It often speeds up the algorithm. - * equals 2, the algorithm uses additional - memory of size M*min(M,N) of real numbers. - It allows to get a maximum performance. - The recommended value of the parameter is 2. - -Output parameters: - W - contains singular values in descending order. - U - if UNeeded=0, U isn't changed, the left singular vectors - are not calculated. - if Uneeded=1, U contains left singular vectors (first - min(M,N) columns of matrix U). Array whose indexes range - within [0..M-1, 0..Min(M,N)-1]. - if UNeeded=2, U contains matrix U wholly. Array whose - indexes range within [0..M-1, 0..M-1]. - VT - if VTNeeded=0, VT isn't changed, the right singular vectors - are not calculated. - if VTNeeded=1, VT contains right singular vectors (first - min(M,N) rows of matrix V^T). Array whose indexes range - within [0..min(M,N)-1, 0..N-1]. - if VTNeeded=2, VT contains matrix V^T wholly. Array whose - indexes range within [0..N-1, 0..N-1]. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -bool rmatrixsvd(const real_2d_array &a, const ae_int_t m, const ae_int_t n, const ae_int_t uneeded, const ae_int_t vtneeded, const ae_int_t additionalmemory, real_1d_array &w, real_2d_array &u, real_2d_array &vt, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_NORMESTIMATOR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This procedure initializes matrix norm estimator. - -USAGE: -1. User initializes algorithm state with NormEstimatorCreate() call -2. User calls NormEstimatorEstimateSparse() (or NormEstimatorIteration()) -3. User calls NormEstimatorResults() to get solution. - -INPUT PARAMETERS: - M - number of rows in the matrix being estimated, M>0 - N - number of columns in the matrix being estimated, N>0 - NStart - number of random starting vectors - recommended value - at least 5. - NIts - number of iterations to do with best starting vector - recommended value - at least 5. - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -NOTE: this algorithm is effectively deterministic, i.e. it always returns -same result when repeatedly called for the same matrix. In fact, algorithm -uses randomized starting vectors, but internal random numbers generator -always generates same sequence of the random values (it is a feature, not -bug). - -Algorithm can be made non-deterministic with NormEstimatorSetSeed(0) call. - - -- ALGLIB -- - Copyright 06.12.2011 by Bochkanov Sergey -*************************************************************************/ -void normestimatorcreate(const ae_int_t m, const ae_int_t n, const ae_int_t nstart, const ae_int_t nits, normestimatorstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function changes seed value used by algorithm. In some cases we need -deterministic processing, i.e. subsequent calls must return equal results, -in other cases we need non-deterministic algorithm which returns different -results for the same matrix on every pass. - -Setting zero seed will lead to non-deterministic algorithm, while non-zero -value will make our algorithm deterministic. - -INPUT PARAMETERS: - State - norm estimator state, must be initialized with a call - to NormEstimatorCreate() - SeedVal - seed value, >=0. Zero value = non-deterministic algo. - - -- ALGLIB -- - Copyright 06.12.2011 by Bochkanov Sergey -*************************************************************************/ -void normestimatorsetseed(const normestimatorstate &state, const ae_int_t seedval, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function estimates norm of the sparse M*N matrix A. - -INPUT PARAMETERS: - State - norm estimator state, must be initialized with a call - to NormEstimatorCreate() - A - sparse M*N matrix, must be converted to CRS format - prior to calling this function. - -After this function is over you can call NormEstimatorResults() to get -estimate of the norm(A). - - -- ALGLIB -- - Copyright 06.12.2011 by Bochkanov Sergey -*************************************************************************/ -void normestimatorestimatesparse(const normestimatorstate &state, const sparsematrix &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Matrix norm estimation results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - Nrm - estimate of the matrix norm, Nrm>=0 - - -- ALGLIB -- - Copyright 06.12.2011 by Bochkanov Sergey -*************************************************************************/ -void normestimatorresults(const normestimatorstate &state, double &nrm, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_HSSCHUR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_EVD) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This function initializes subspace iteration solver. This solver is used -to solve symmetric real eigenproblems where just a few (top K) eigenvalues -and corresponding eigenvectors is required. - -This solver can be significantly faster than complete EVD decomposition -in the following case: -* when only just a small fraction of top eigenpairs of dense matrix is - required. When K approaches N, this solver is slower than complete dense - EVD -* when problem matrix is sparse (and/or is not known explicitly, i.e. only - matrix-matrix product can be performed) - -USAGE (explicit dense/sparse matrix): -1. User initializes algorithm state with eigsubspacecreate() call -2. [optional] User tunes solver parameters by calling eigsubspacesetcond() - or other functions -3. User calls eigsubspacesolvedense() or eigsubspacesolvesparse() methods, - which take algorithm state and 2D array or alglib.sparsematrix object. - -USAGE (out-of-core mode): -1. User initializes algorithm state with eigsubspacecreate() call -2. [optional] User tunes solver parameters by calling eigsubspacesetcond() - or other functions -3. User activates out-of-core mode of the solver and repeatedly calls - communication functions in a loop like below: - > alglib.eigsubspaceoocstart(state) - > while alglib.eigsubspaceooccontinue(state) do - > alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) - > alglib.eigsubspaceoocgetrequestdata(state, out X) - > [calculate Y=A*X, with X=R^NxM] - > alglib.eigsubspaceoocsendresult(state, in Y) - > alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - N - problem dimensionality, N>0 - K - number of top eigenvector to calculate, 0=0, with non-zero value used to tell solver that - it can stop after all eigenvalues converged with - error roughly proportional to eps*MAX(LAMBDA_MAX), - where LAMBDA_MAX is a maximum eigenvalue. - Zero value means that no check for precision is - performed. - MaxIts - maxits>=0, with non-zero value used to tell solver - that it can stop after maxits steps (no matter how - precise current estimate is) - -NOTE: passing eps=0 and maxits=0 results in automatic selection of - moderate eps as stopping criteria (1.0E-6 in current implementation, - but it may change without notice). - -NOTE: very small values of eps are possible (say, 1.0E-12), although the - larger problem you solve (N and/or K), the harder it is to find - precise eigenvectors because rounding errors tend to accumulate. - -NOTE: passing non-zero eps results in some performance penalty, roughly - equal to 2N*(2K)^2 FLOPs per iteration. These additional computations - are required in order to estimate current error in eigenvalues via - Rayleigh-Ritz process. - Most of this additional time is spent in construction of ~2Kx2K - symmetric subproblem whose eigenvalues are checked with exact - eigensolver. - This additional time is negligible if you search for eigenvalues of - the large dense matrix, but may become noticeable on highly sparse - EVD problems, where cost of matrix-matrix product is low. - If you set eps to exactly zero, Rayleigh-Ritz phase is completely - turned off. - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspacesetcond(const eigsubspacestate &state, const double eps, const ae_int_t maxits, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets warm-start mode of the solver: next call to the solver -will reuse previous subspace as warm-start point. It can significantly -speed-up convergence when you solve many similar eigenproblems. - -INPUT PARAMETERS: - State - solver structure - UseWarmStart- either True or False - - -- ALGLIB -- - Copyright 12.11.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspacesetwarmstart(const eigsubspacestate &state, const bool usewarmstart, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function initiates out-of-core mode of subspace eigensolver. It -should be used in conjunction with other out-of-core-related functions of -this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - State - solver object - MType - matrix type: - * 0 for real symmetric matrix (solver assumes that - matrix being processed is symmetric; symmetric - direct eigensolver is used for smaller subproblems - arising during solution of larger "full" task) - Future versions of ALGLIB may introduce support for - other matrix types; for now, only symmetric - eigenproblems are supported. - - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspaceoocstart(const eigsubspacestate &state, const ae_int_t mtype, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function performs subspace iteration in the out-of-core mode. It -should be used in conjunction with other out-of-core-related functions of -this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -bool eigsubspaceooccontinue(const eigsubspacestate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is used to retrieve information about out-of-core request -sent by solver to user code: request type (current version of the solver -sends only requests for matrix-matrix products) and request size (size of -the matrices being multiplied). - -This function returns just request metrics; in order to get contents of -the matrices being multiplied, use eigsubspaceoocgetrequestdata(). - -It should be used in conjunction with other out-of-core-related functions -of this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - State - solver running in out-of-core mode - -OUTPUT PARAMETERS: - RequestType - type of the request to process: - * 0 - for matrix-matrix product A*X, with A being - NxN matrix whose eigenvalues/vectors are needed, - and X being NxREQUESTSIZE one which is returned - by the eigsubspaceoocgetrequestdata(). - RequestSize - size of the X matrix (number of columns), usually - it is several times larger than number of vectors - K requested by user. - - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspaceoocgetrequestinfo(const eigsubspacestate &state, ae_int_t &requesttype, ae_int_t &requestsize, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is used to retrieve information about out-of-core request -sent by solver to user code: matrix X (array[N,RequestSize) which have to -be multiplied by out-of-core matrix A in a product A*X. - -This function returns just request data; in order to get size of the data -prior to processing requestm, use eigsubspaceoocgetrequestinfo(). - -It should be used in conjunction with other out-of-core-related functions -of this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - State - solver running in out-of-core mode - X - possibly preallocated storage; reallocated if - needed, left unchanged, if large enough to store - request data. - -OUTPUT PARAMETERS: - X - array[N,RequestSize] or larger, leading rectangle - is filled with dense matrix X. - - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspaceoocgetrequestdata(const eigsubspacestate &state, real_2d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is used to send user reply to out-of-core request sent by -solver. Usually it is product A*X for returned by solver matrix X. - -It should be used in conjunction with other out-of-core-related functions -of this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - State - solver running in out-of-core mode - AX - array[N,RequestSize] or larger, leading rectangle - is filled with product A*X. - - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspaceoocsendresult(const eigsubspacestate &state, const real_2d_array &ax, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function finalizes out-of-core mode of subspace eigensolver. It -should be used in conjunction with other out-of-core-related functions of -this subspackage in a loop like below: - -> alglib.eigsubspaceoocstart(state) -> while alglib.eigsubspaceooccontinue(state) do -> alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M) -> alglib.eigsubspaceoocgetrequestdata(state, out X) -> [calculate Y=A*X, with X=R^NxM] -> alglib.eigsubspaceoocsendresult(state, in Y) -> alglib.eigsubspaceoocstop(state, out W, out Z, out Report) - -INPUT PARAMETERS: - State - solver state - -OUTPUT PARAMETERS: - W - array[K], depending on solver settings: - * top K eigenvalues ordered by descending - if - eigenvectors are returned in Z - * zeros - if invariant subspace is returned in Z - Z - array[N,K], depending on solver settings either: - * matrix of eigenvectors found - * orthogonal basis of K-dimensional invariant subspace - Rep - report with additional parameters - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspaceoocstop(const eigsubspacestate &state, real_1d_array &w, real_2d_array &z, eigsubspacereport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function runs eigensolver for dense NxN symmetric matrix A, given by -upper or lower triangle. - -This function can not process nonsymmetric matrices. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - State - solver state - A - array[N,N], symmetric NxN matrix given by one of its - triangles - IsUpper - whether upper or lower triangle of A is given (the - other one is not referenced at all). - -OUTPUT PARAMETERS: - W - array[K], top K eigenvalues ordered by descending - of their absolute values - Z - array[N,K], matrix of eigenvectors found - Rep - report with additional parameters - -NOTE: internally this function allocates a copy of NxN dense A. You should - take it into account when working with very large matrices occupying - almost all RAM. - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspacesolvedenses(const eigsubspacestate &state, const real_2d_array &a, const bool isupper, real_1d_array &w, real_2d_array &z, eigsubspacereport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function runs eigensolver for dense NxN symmetric matrix A, given by -upper or lower triangle. - -This function can not process nonsymmetric matrices. - -INPUT PARAMETERS: - State - solver state - A - NxN symmetric matrix given by one of its triangles - IsUpper - whether upper or lower triangle of A is given (the - other one is not referenced at all). - -OUTPUT PARAMETERS: - W - array[K], top K eigenvalues ordered by descending - of their absolute values - Z - array[N,K], matrix of eigenvectors found - Rep - report with additional parameters - - -- ALGLIB -- - Copyright 16.01.2017 by Bochkanov Sergey -*************************************************************************/ -void eigsubspacesolvesparses(const eigsubspacestate &state, const sparsematrix &a, const bool isupper, real_1d_array &w, real_2d_array &z, eigsubspacereport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Finding the eigenvalues and eigenvectors of a symmetric matrix - -The algorithm finds eigen pairs of a symmetric matrix by reducing it to -tridiagonal form and using the QL/QR algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - symmetric matrix which is given by its upper or lower - triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - IsUpper - storage format. - -Output parameters: - D - eigenvalues in ascending order. - Array whose index ranges within [0..N-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains the eigenvectors. - Array whose indexes range within [0..N-1, 0..N-1]. - The eigenvectors are stored in the matrix columns. - -Result: - True, if the algorithm has converged. - False, if the algorithm hasn't converged (rare case). - - -- ALGLIB -- - Copyright 2005-2008 by Bochkanov Sergey -*************************************************************************/ -bool smatrixevd(const real_2d_array &a, const ae_int_t n, const ae_int_t zneeded, const bool isupper, real_1d_array &d, real_2d_array &z, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Subroutine for finding the eigenvalues (and eigenvectors) of a symmetric -matrix in a given half open interval (A, B] by using a bisection and -inverse iteration - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - symmetric matrix which is given by its upper or lower - triangular part. Array [0..N-1, 0..N-1]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - IsUpperA - storage format of matrix A. - B1, B2 - half open interval (B1, B2] to search eigenvalues in. - -Output parameters: - M - number of eigenvalues found in a given half-interval (M>=0). - W - array of the eigenvalues found. - Array whose index ranges within [0..M-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains eigenvectors. - Array whose indexes range within [0..N-1, 0..M-1]. - The eigenvectors are stored in the matrix columns. - -Result: - True, if successful. M contains the number of eigenvalues in the given - half-interval (could be equal to 0), W contains the eigenvalues, - Z contains the eigenvectors (if needed). - - False, if the bisection method subroutine wasn't able to find the - eigenvalues in the given interval or if the inverse iteration subroutine - wasn't able to find all the corresponding eigenvectors. - In that case, the eigenvalues and eigenvectors are not returned, - M is equal to 0. - - -- ALGLIB -- - Copyright 07.01.2006 by Bochkanov Sergey -*************************************************************************/ -bool smatrixevdr(const real_2d_array &a, const ae_int_t n, const ae_int_t zneeded, const bool isupper, const double b1, const double b2, ae_int_t &m, real_1d_array &w, real_2d_array &z, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Subroutine for finding the eigenvalues and eigenvectors of a symmetric -matrix with given indexes by using bisection and inverse iteration methods. - -Input parameters: - A - symmetric matrix which is given by its upper or lower - triangular part. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - IsUpperA - storage format of matrix A. - I1, I2 - index interval for searching (from I1 to I2). - 0 <= I1 <= I2 <= N-1. - -Output parameters: - W - array of the eigenvalues found. - Array whose index ranges within [0..I2-I1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains eigenvectors. - Array whose indexes range within [0..N-1, 0..I2-I1]. - In that case, the eigenvectors are stored in the matrix columns. - -Result: - True, if successful. W contains the eigenvalues, Z contains the - eigenvectors (if needed). - - False, if the bisection method subroutine wasn't able to find the - eigenvalues in the given interval or if the inverse iteration subroutine - wasn't able to find all the corresponding eigenvectors. - In that case, the eigenvalues and eigenvectors are not returned. - - -- ALGLIB -- - Copyright 07.01.2006 by Bochkanov Sergey -*************************************************************************/ -bool smatrixevdi(const real_2d_array &a, const ae_int_t n, const ae_int_t zneeded, const bool isupper, const ae_int_t i1, const ae_int_t i2, real_1d_array &w, real_2d_array &z, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Finding the eigenvalues and eigenvectors of a Hermitian matrix - -The algorithm finds eigen pairs of a Hermitian matrix by reducing it to -real tridiagonal form and using the QL/QR algorithm. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - A - Hermitian matrix which is given by its upper or lower - triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - IsUpper - storage format. - ZNeeded - flag controlling whether the eigenvectors are needed or - not. If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - -Output parameters: - D - eigenvalues in ascending order. - Array whose index ranges within [0..N-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains the eigenvectors. - Array whose indexes range within [0..N-1, 0..N-1]. - The eigenvectors are stored in the matrix columns. - -Result: - True, if the algorithm has converged. - False, if the algorithm hasn't converged (rare case). - -Note: - eigenvectors of Hermitian matrix are defined up to multiplication by - a complex number L, such that |L|=1. - - -- ALGLIB -- - Copyright 2005, 23 March 2007 by Bochkanov Sergey -*************************************************************************/ -bool hmatrixevd(const complex_2d_array &a, const ae_int_t n, const ae_int_t zneeded, const bool isupper, real_1d_array &d, complex_2d_array &z, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Subroutine for finding the eigenvalues (and eigenvectors) of a Hermitian -matrix in a given half-interval (A, B] by using a bisection and inverse -iteration - -Input parameters: - A - Hermitian matrix which is given by its upper or lower - triangular part. Array whose indexes range within - [0..N-1, 0..N-1]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or - not. If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - IsUpperA - storage format of matrix A. - B1, B2 - half-interval (B1, B2] to search eigenvalues in. - -Output parameters: - M - number of eigenvalues found in a given half-interval, M>=0 - W - array of the eigenvalues found. - Array whose index ranges within [0..M-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains eigenvectors. - Array whose indexes range within [0..N-1, 0..M-1]. - The eigenvectors are stored in the matrix columns. - -Result: - True, if successful. M contains the number of eigenvalues in the given - half-interval (could be equal to 0), W contains the eigenvalues, - Z contains the eigenvectors (if needed). - - False, if the bisection method subroutine wasn't able to find the - eigenvalues in the given interval or if the inverse iteration - subroutine wasn't able to find all the corresponding eigenvectors. - In that case, the eigenvalues and eigenvectors are not returned, M is - equal to 0. - -Note: - eigen vectors of Hermitian matrix are defined up to multiplication by - a complex number L, such as |L|=1. - - -- ALGLIB -- - Copyright 07.01.2006, 24.03.2007 by Bochkanov Sergey. -*************************************************************************/ -bool hmatrixevdr(const complex_2d_array &a, const ae_int_t n, const ae_int_t zneeded, const bool isupper, const double b1, const double b2, ae_int_t &m, real_1d_array &w, complex_2d_array &z, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Subroutine for finding the eigenvalues and eigenvectors of a Hermitian -matrix with given indexes by using bisection and inverse iteration methods - -Input parameters: - A - Hermitian matrix which is given by its upper or lower - triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or - not. If ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - IsUpperA - storage format of matrix A. - I1, I2 - index interval for searching (from I1 to I2). - 0 <= I1 <= I2 <= N-1. - -Output parameters: - W - array of the eigenvalues found. - Array whose index ranges within [0..I2-I1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains eigenvectors. - Array whose indexes range within [0..N-1, 0..I2-I1]. - In that case, the eigenvectors are stored in the matrix - columns. - -Result: - True, if successful. W contains the eigenvalues, Z contains the - eigenvectors (if needed). - - False, if the bisection method subroutine wasn't able to find the - eigenvalues in the given interval or if the inverse iteration - subroutine wasn't able to find all the corresponding eigenvectors. - In that case, the eigenvalues and eigenvectors are not returned. - -Note: - eigen vectors of Hermitian matrix are defined up to multiplication by - a complex number L, such as |L|=1. - - -- ALGLIB -- - Copyright 07.01.2006, 24.03.2007 by Bochkanov Sergey. -*************************************************************************/ -bool hmatrixevdi(const complex_2d_array &a, const ae_int_t n, const ae_int_t zneeded, const bool isupper, const ae_int_t i1, const ae_int_t i2, real_1d_array &w, complex_2d_array &z, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Finding the eigenvalues and eigenvectors of a tridiagonal symmetric matrix - -The algorithm finds the eigen pairs of a tridiagonal symmetric matrix by -using an QL/QR algorithm with implicit shifts. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -Input parameters: - D - the main diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-1]. - E - the secondary diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-2]. - N - size of matrix A. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not needed; - * 1, the eigenvectors of a tridiagonal matrix - are multiplied by the square matrix Z. It is used if the - tridiagonal matrix is obtained by the similarity - transformation of a symmetric matrix; - * 2, the eigenvectors of a tridiagonal matrix replace the - square matrix Z; - * 3, matrix Z contains the first row of the eigenvectors - matrix. - Z - if ZNeeded=1, Z contains the square matrix by which the - eigenvectors are multiplied. - Array whose indexes range within [0..N-1, 0..N-1]. - -Output parameters: - D - eigenvalues in ascending order. - Array whose index ranges within [0..N-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains the product of a given matrix (from the left) - and the eigenvectors matrix (from the right); - * 2, Z contains the eigenvectors. - * 3, Z contains the first row of the eigenvectors matrix. - If ZNeeded<3, Z is the array whose indexes range within [0..N-1, 0..N-1]. - In that case, the eigenvectors are stored in the matrix columns. - If ZNeeded=3, Z is the array whose indexes range within [0..0, 0..N-1]. - -Result: - True, if the algorithm has converged. - False, if the algorithm hasn't converged. - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - September 30, 1994 -*************************************************************************/ -bool smatrixtdevd(real_1d_array &d, const real_1d_array &e, const ae_int_t n, const ae_int_t zneeded, real_2d_array &z, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Subroutine for finding the tridiagonal matrix eigenvalues/vectors in a -given half-interval (A, B] by using bisection and inverse iteration. - -Input parameters: - D - the main diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-1]. - E - the secondary diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-2]. - N - size of matrix, N>=0. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not needed; - * 1, the eigenvectors of a tridiagonal matrix are multiplied - by the square matrix Z. It is used if the tridiagonal - matrix is obtained by the similarity transformation - of a symmetric matrix. - * 2, the eigenvectors of a tridiagonal matrix replace matrix Z. - A, B - half-interval (A, B] to search eigenvalues in. - Z - if ZNeeded is equal to: - * 0, Z isn't used and remains unchanged; - * 1, Z contains the square matrix (array whose indexes range - within [0..N-1, 0..N-1]) which reduces the given symmetric - matrix to tridiagonal form; - * 2, Z isn't used (but changed on the exit). - -Output parameters: - D - array of the eigenvalues found. - Array whose index ranges within [0..M-1]. - M - number of eigenvalues found in the given half-interval (M>=0). - Z - if ZNeeded is equal to: - * 0, doesn't contain any information; - * 1, contains the product of a given NxN matrix Z (from the - left) and NxM matrix of the eigenvectors found (from the - right). Array whose indexes range within [0..N-1, 0..M-1]. - * 2, contains the matrix of the eigenvectors found. - Array whose indexes range within [0..N-1, 0..M-1]. - -Result: - - True, if successful. In that case, M contains the number of eigenvalues - in the given half-interval (could be equal to 0), D contains the eigenvalues, - Z contains the eigenvectors (if needed). - It should be noted that the subroutine changes the size of arrays D and Z. - - False, if the bisection method subroutine wasn't able to find the - eigenvalues in the given interval or if the inverse iteration subroutine - wasn't able to find all the corresponding eigenvectors. In that case, - the eigenvalues and eigenvectors are not returned, M is equal to 0. - - -- ALGLIB -- - Copyright 31.03.2008 by Bochkanov Sergey -*************************************************************************/ -bool smatrixtdevdr(real_1d_array &d, const real_1d_array &e, const ae_int_t n, const ae_int_t zneeded, const double a, const double b, ae_int_t &m, real_2d_array &z, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Subroutine for finding tridiagonal matrix eigenvalues/vectors with given -indexes (in ascending order) by using the bisection and inverse iteraion. - -Input parameters: - D - the main diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-1]. - E - the secondary diagonal of a tridiagonal matrix. - Array whose index ranges within [0..N-2]. - N - size of matrix. N>=0. - ZNeeded - flag controlling whether the eigenvectors are needed or not. - If ZNeeded is equal to: - * 0, the eigenvectors are not needed; - * 1, the eigenvectors of a tridiagonal matrix are multiplied - by the square matrix Z. It is used if the - tridiagonal matrix is obtained by the similarity transformation - of a symmetric matrix. - * 2, the eigenvectors of a tridiagonal matrix replace - matrix Z. - I1, I2 - index interval for searching (from I1 to I2). - 0 <= I1 <= I2 <= N-1. - Z - if ZNeeded is equal to: - * 0, Z isn't used and remains unchanged; - * 1, Z contains the square matrix (array whose indexes range within [0..N-1, 0..N-1]) - which reduces the given symmetric matrix to tridiagonal form; - * 2, Z isn't used (but changed on the exit). - -Output parameters: - D - array of the eigenvalues found. - Array whose index ranges within [0..I2-I1]. - Z - if ZNeeded is equal to: - * 0, doesn't contain any information; - * 1, contains the product of a given NxN matrix Z (from the left) and - Nx(I2-I1) matrix of the eigenvectors found (from the right). - Array whose indexes range within [0..N-1, 0..I2-I1]. - * 2, contains the matrix of the eigenvalues found. - Array whose indexes range within [0..N-1, 0..I2-I1]. - - -Result: - - True, if successful. In that case, D contains the eigenvalues, - Z contains the eigenvectors (if needed). - It should be noted that the subroutine changes the size of arrays D and Z. - - False, if the bisection method subroutine wasn't able to find the eigenvalues - in the given interval or if the inverse iteration subroutine wasn't able - to find all the corresponding eigenvectors. In that case, the eigenvalues - and eigenvectors are not returned. - - -- ALGLIB -- - Copyright 25.12.2005 by Bochkanov Sergey -*************************************************************************/ -bool smatrixtdevdi(real_1d_array &d, const real_1d_array &e, const ae_int_t n, const ae_int_t zneeded, const ae_int_t i1, const ae_int_t i2, real_2d_array &z, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Finding eigenvalues and eigenvectors of a general (unsymmetric) matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -The algorithm finds eigenvalues and eigenvectors of a general matrix by -using the QR algorithm with multiple shifts. The algorithm can find -eigenvalues and both left and right eigenvectors. - -The right eigenvector is a vector x such that A*x = w*x, and the left -eigenvector is a vector y such that y'*A = w*y' (here y' implies a complex -conjugate transposition of vector y). - -Input parameters: - A - matrix. Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - VNeeded - flag controlling whether eigenvectors are needed or not. - If VNeeded is equal to: - * 0, eigenvectors are not returned; - * 1, right eigenvectors are returned; - * 2, left eigenvectors are returned; - * 3, both left and right eigenvectors are returned. - -Output parameters: - WR - real parts of eigenvalues. - Array whose index ranges within [0..N-1]. - WR - imaginary parts of eigenvalues. - Array whose index ranges within [0..N-1]. - VL, VR - arrays of left and right eigenvectors (if they are needed). - If WI[i]=0, the respective eigenvalue is a real number, - and it corresponds to the column number I of matrices VL/VR. - If WI[i]>0, we have a pair of complex conjugate numbers with - positive and negative imaginary parts: - the first eigenvalue WR[i] + sqrt(-1)*WI[i]; - the second eigenvalue WR[i+1] + sqrt(-1)*WI[i+1]; - WI[i]>0 - WI[i+1] = -WI[i] < 0 - In that case, the eigenvector corresponding to the first - eigenvalue is located in i and i+1 columns of matrices - VL/VR (the column number i contains the real part, and the - column number i+1 contains the imaginary part), and the vector - corresponding to the second eigenvalue is a complex conjugate to - the first vector. - Arrays whose indexes range within [0..N-1, 0..N-1]. - -Result: - True, if the algorithm has converged. - False, if the algorithm has not converged. - -Note 1: - Some users may ask the following question: what if WI[N-1]>0? - WI[N] must contain an eigenvalue which is complex conjugate to the - N-th eigenvalue, but the array has only size N? - The answer is as follows: such a situation cannot occur because the - algorithm finds a pairs of eigenvalues, therefore, if WI[i]>0, I is - strictly less than N-1. - -Note 2: - The algorithm performance depends on the value of the internal parameter - NS of the InternalSchurDecomposition subroutine which defines the number - of shifts in the QR algorithm (similarly to the block width in block-matrix - algorithms of linear algebra). If you require maximum performance - on your machine, it is recommended to adjust this parameter manually. - - -See also the InternalTREVC subroutine. - -The algorithm is based on the LAPACK 3.0 library. -*************************************************************************/ -bool rmatrixevd(const real_2d_array &a, const ae_int_t n, const ae_int_t vneeded, real_1d_array &wr, real_1d_array &wi, real_2d_array &vl, real_2d_array &vr, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_SCHUR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Subroutine performing the Schur decomposition of a general matrix by using -the QR algorithm with multiple shifts. - -COMMERCIAL EDITION OF ALGLIB: - - ! Commercial version of ALGLIB includes one important improvement of - ! this function, which can be used from C++ and C#: - ! * Intel MKL support (lightweight Intel MKL is shipped with ALGLIB) - ! - ! Intel MKL gives approximately constant (with respect to number of - ! worker threads) acceleration factor which depends on CPU being used, - ! problem size and "baseline" ALGLIB edition which is used for - ! comparison. - ! - ! Multithreaded acceleration is NOT supported for this function. - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -The source matrix A is represented as S'*A*S = T, where S is an orthogonal -matrix (Schur vectors), T - upper quasi-triangular matrix (with blocks of -sizes 1x1 and 2x2 on the main diagonal). - -Input parameters: - A - matrix to be decomposed. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of A, N>=0. - - -Output parameters: - A - contains matrix T. - Array whose indexes range within [0..N-1, 0..N-1]. - S - contains Schur vectors. - Array whose indexes range within [0..N-1, 0..N-1]. - -Note 1: - The block structure of matrix T can be easily recognized: since all - the elements below the blocks are zeros, the elements a[i+1,i] which - are equal to 0 show the block border. - -Note 2: - The algorithm performance depends on the value of the internal parameter - NS of the InternalSchurDecomposition subroutine which defines the number - of shifts in the QR algorithm (similarly to the block width in block-matrix - algorithms in linear algebra). If you require maximum performance on - your machine, it is recommended to adjust this parameter manually. - -Result: - True, - if the algorithm has converged and parameters A and S contain the result. - False, - if the algorithm has not converged. - -Algorithm implemented on the basis of the DHSEQR subroutine (LAPACK 3.0 library). -*************************************************************************/ -bool rmatrixschur(real_2d_array &a, const ae_int_t n, real_2d_array &s, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_SPDGEVD) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Algorithm for solving the following generalized symmetric positive-definite -eigenproblem: - A*x = lambda*B*x (1) or - A*B*x = lambda*x (2) or - B*A*x = lambda*x (3). -where A is a symmetric matrix, B - symmetric positive-definite matrix. -The problem is solved by reducing it to an ordinary symmetric eigenvalue -problem. - -Input parameters: - A - symmetric matrix which is given by its upper or lower - triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrices A and B. - IsUpperA - storage format of matrix A. - B - symmetric positive-definite matrix which is given by - its upper or lower triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - IsUpperB - storage format of matrix B. - ZNeeded - if ZNeeded is equal to: - * 0, the eigenvectors are not returned; - * 1, the eigenvectors are returned. - ProblemType - if ProblemType is equal to: - * 1, the following problem is solved: A*x = lambda*B*x; - * 2, the following problem is solved: A*B*x = lambda*x; - * 3, the following problem is solved: B*A*x = lambda*x. - -Output parameters: - D - eigenvalues in ascending order. - Array whose index ranges within [0..N-1]. - Z - if ZNeeded is equal to: - * 0, Z hasn't changed; - * 1, Z contains eigenvectors. - Array whose indexes range within [0..N-1, 0..N-1]. - The eigenvectors are stored in matrix columns. It should - be noted that the eigenvectors in such problems do not - form an orthogonal system. - -Result: - True, if the problem was solved successfully. - False, if the error occurred during the Cholesky decomposition of matrix - B (the matrix isn't positive-definite) or during the work of the iterative - algorithm for solving the symmetric eigenproblem. - -See also the GeneralizedSymmetricDefiniteEVDReduce subroutine. - - -- ALGLIB -- - Copyright 1.28.2006 by Bochkanov Sergey -*************************************************************************/ -bool smatrixgevd(const real_2d_array &a, const ae_int_t n, const bool isuppera, const real_2d_array &b, const bool isupperb, const ae_int_t zneeded, const ae_int_t problemtype, real_1d_array &d, real_2d_array &z, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Algorithm for reduction of the following generalized symmetric positive- -definite eigenvalue problem: - A*x = lambda*B*x (1) or - A*B*x = lambda*x (2) or - B*A*x = lambda*x (3) -to the symmetric eigenvalues problem C*y = lambda*y (eigenvalues of this and -the given problems are the same, and the eigenvectors of the given problem -could be obtained by multiplying the obtained eigenvectors by the -transformation matrix x = R*y). - -Here A is a symmetric matrix, B - symmetric positive-definite matrix. - -Input parameters: - A - symmetric matrix which is given by its upper or lower - triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrices A and B. - IsUpperA - storage format of matrix A. - B - symmetric positive-definite matrix which is given by - its upper or lower triangular part. - Array whose indexes range within [0..N-1, 0..N-1]. - IsUpperB - storage format of matrix B. - ProblemType - if ProblemType is equal to: - * 1, the following problem is solved: A*x = lambda*B*x; - * 2, the following problem is solved: A*B*x = lambda*x; - * 3, the following problem is solved: B*A*x = lambda*x. - -Output parameters: - A - symmetric matrix which is given by its upper or lower - triangle depending on IsUpperA. Contains matrix C. - Array whose indexes range within [0..N-1, 0..N-1]. - R - upper triangular or low triangular transformation matrix - which is used to obtain the eigenvectors of a given problem - as the product of eigenvectors of C (from the right) and - matrix R (from the left). If the matrix is upper - triangular, the elements below the main diagonal - are equal to 0 (and vice versa). Thus, we can perform - the multiplication without taking into account the - internal structure (which is an easier though less - effective way). - Array whose indexes range within [0..N-1, 0..N-1]. - IsUpperR - type of matrix R (upper or lower triangular). - -Result: - True, if the problem was reduced successfully. - False, if the error occurred during the Cholesky decomposition of - matrix B (the matrix is not positive-definite). - - -- ALGLIB -- - Copyright 1.28.2006 by Bochkanov Sergey -*************************************************************************/ -bool smatrixgevdreduce(real_2d_array &a, const ae_int_t n, const bool isuppera, const real_2d_array &b, const bool isupperb, const ae_int_t problemtype, real_2d_array &r, bool &isupperr, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_INVERSEUPDATE) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Inverse matrix update by the Sherman-Morrison formula - -The algorithm updates matrix A^-1 when adding a number to an element -of matrix A. - -Input parameters: - InvA - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - UpdRow - row where the element to be updated is stored. - UpdColumn - column where the element to be updated is stored. - UpdVal - a number to be added to the element. - - -Output parameters: - InvA - inverse of modified matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -void rmatrixinvupdatesimple(real_2d_array &inva, const ae_int_t n, const ae_int_t updrow, const ae_int_t updcolumn, const double updval, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Inverse matrix update by the Sherman-Morrison formula - -The algorithm updates matrix A^-1 when adding a vector to a row -of matrix A. - -Input parameters: - InvA - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - UpdRow - the row of A whose vector V was added. - 0 <= Row <= N-1 - V - the vector to be added to a row. - Array whose index ranges within [0..N-1]. - -Output parameters: - InvA - inverse of modified matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -void rmatrixinvupdaterow(real_2d_array &inva, const ae_int_t n, const ae_int_t updrow, const real_1d_array &v, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Inverse matrix update by the Sherman-Morrison formula - -The algorithm updates matrix A^-1 when adding a vector to a column -of matrix A. - -Input parameters: - InvA - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - UpdColumn - the column of A whose vector U was added. - 0 <= UpdColumn <= N-1 - U - the vector to be added to a column. - Array whose index ranges within [0..N-1]. - -Output parameters: - InvA - inverse of modified matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -void rmatrixinvupdatecolumn(real_2d_array &inva, const ae_int_t n, const ae_int_t updcolumn, const real_1d_array &u, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Inverse matrix update by the Sherman-Morrison formula - -The algorithm computes the inverse of matrix A+u*v' by using the given matrix -A^-1 and the vectors u and v. - -Input parameters: - InvA - inverse of matrix A. - Array whose indexes range within [0..N-1, 0..N-1]. - N - size of matrix A. - U - the vector modifying the matrix. - Array whose index ranges within [0..N-1]. - V - the vector modifying the matrix. - Array whose index ranges within [0..N-1]. - -Output parameters: - InvA - inverse of matrix A + u*v'. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -void rmatrixinvupdateuv(real_2d_array &inva, const ae_int_t n, const real_1d_array &u, const real_1d_array &v, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_MATDET) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Determinant calculation of the matrix given by its LU decomposition. - -Input parameters: - A - LU decomposition of the matrix (output of - RMatrixLU subroutine). - Pivots - table of permutations which were made during - the LU decomposition. - Output of RMatrixLU subroutine. - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -Result: matrix determinant. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -double rmatrixludet(const real_2d_array &a, const integer_1d_array &pivots, const ae_int_t n, const xparams _xparams = alglib::xdefault); -double rmatrixludet(const real_2d_array &a, const integer_1d_array &pivots, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Calculation of the determinant of a general matrix - -Input parameters: - A - matrix, array[0..N-1, 0..N-1] - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -Result: determinant of matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -double rmatrixdet(const real_2d_array &a, const ae_int_t n, const xparams _xparams = alglib::xdefault); -double rmatrixdet(const real_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Determinant calculation of the matrix given by its LU decomposition. - -Input parameters: - A - LU decomposition of the matrix (output of - RMatrixLU subroutine). - Pivots - table of permutations which were made during - the LU decomposition. - Output of RMatrixLU subroutine. - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -Result: matrix determinant. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -alglib::complex cmatrixludet(const complex_2d_array &a, const integer_1d_array &pivots, const ae_int_t n, const xparams _xparams = alglib::xdefault); -alglib::complex cmatrixludet(const complex_2d_array &a, const integer_1d_array &pivots, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Calculation of the determinant of a general matrix - -Input parameters: - A - matrix, array[0..N-1, 0..N-1] - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -Result: determinant of matrix A. - - -- ALGLIB -- - Copyright 2005 by Bochkanov Sergey -*************************************************************************/ -alglib::complex cmatrixdet(const complex_2d_array &a, const ae_int_t n, const xparams _xparams = alglib::xdefault); -alglib::complex cmatrixdet(const complex_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Determinant calculation of the matrix given by the Cholesky decomposition. - -Input parameters: - A - Cholesky decomposition, - output of SMatrixCholesky subroutine. - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - -As the determinant is equal to the product of squares of diagonal elements, -it's not necessary to specify which triangle - lower or upper - the matrix -is stored in. - -Result: - matrix determinant. - - -- ALGLIB -- - Copyright 2005-2008 by Bochkanov Sergey -*************************************************************************/ -double spdmatrixcholeskydet(const real_2d_array &a, const ae_int_t n, const xparams _xparams = alglib::xdefault); -double spdmatrixcholeskydet(const real_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Determinant calculation of the symmetric positive definite matrix. - -Input parameters: - A - matrix. Array with elements [0..N-1, 0..N-1]. - N - (optional) size of matrix A: - * if given, only principal NxN submatrix is processed and - overwritten. other elements are unchanged. - * if not given, automatically determined from matrix size - (A must be square matrix) - IsUpper - (optional) storage type: - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used/changed by - function - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used/changed by - function - * if not given, both lower and upper triangles must be - filled. - -Result: - determinant of matrix A. - If matrix A is not positive definite, exception is thrown. - - -- ALGLIB -- - Copyright 2005-2008 by Bochkanov Sergey -*************************************************************************/ -double spdmatrixdet(const real_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams = alglib::xdefault); -double spdmatrixdet(const real_2d_array &a, const xparams _xparams = alglib::xdefault); -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (FUNCTIONS) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_SPARSE) || !defined(AE_PARTIAL_BUILD) -void sparsecreate(ae_int_t m, - ae_int_t n, - ae_int_t k, - sparsematrix* s, - ae_state *_state); -void sparsecreatebuf(ae_int_t m, - ae_int_t n, - ae_int_t k, - sparsematrix* s, - ae_state *_state); -void sparsecreatecrs(ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* ner, - sparsematrix* s, - ae_state *_state); -void sparsecreatecrsbuf(ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* ner, - sparsematrix* s, - ae_state *_state); -void sparsecreatesks(ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* d, - /* Integer */ ae_vector* u, - sparsematrix* s, - ae_state *_state); -void sparsecreatesksbuf(ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* d, - /* Integer */ ae_vector* u, - sparsematrix* s, - ae_state *_state); -void sparsecreatesksband(ae_int_t m, - ae_int_t n, - ae_int_t bw, - sparsematrix* s, - ae_state *_state); -void sparsecreatesksbandbuf(ae_int_t m, - ae_int_t n, - ae_int_t bw, - sparsematrix* s, - ae_state *_state); -void sparsecopy(sparsematrix* s0, sparsematrix* s1, ae_state *_state); -void sparsecopybuf(sparsematrix* s0, sparsematrix* s1, ae_state *_state); -void sparseswap(sparsematrix* s0, sparsematrix* s1, ae_state *_state); -void sparseadd(sparsematrix* s, - ae_int_t i, - ae_int_t j, - double v, - ae_state *_state); -void sparseset(sparsematrix* s, - ae_int_t i, - ae_int_t j, - double v, - ae_state *_state); -double sparseget(sparsematrix* s, - ae_int_t i, - ae_int_t j, - ae_state *_state); -ae_bool sparseexists(sparsematrix* s, - ae_int_t i, - ae_int_t j, - ae_state *_state); -double sparsegetdiagonal(sparsematrix* s, ae_int_t i, ae_state *_state); -void sparsemv(sparsematrix* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void sparsemtv(sparsematrix* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void sparsegemv(sparsematrix* s, - double alpha, - ae_int_t ops, - /* Real */ ae_vector* x, - ae_int_t ix, - double beta, - /* Real */ ae_vector* y, - ae_int_t iy, - ae_state *_state); -void sparsemv2(sparsematrix* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y0, - /* Real */ ae_vector* y1, - ae_state *_state); -void sparsesmv(sparsematrix* s, - ae_bool isupper, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -double sparsevsmv(sparsematrix* s, - ae_bool isupper, - /* Real */ ae_vector* x, - ae_state *_state); -void sparsemm(sparsematrix* s, - /* Real */ ae_matrix* a, - ae_int_t k, - /* Real */ ae_matrix* b, - ae_state *_state); -void sparsemtm(sparsematrix* s, - /* Real */ ae_matrix* a, - ae_int_t k, - /* Real */ ae_matrix* b, - ae_state *_state); -void sparsemm2(sparsematrix* s, - /* Real */ ae_matrix* a, - ae_int_t k, - /* Real */ ae_matrix* b0, - /* Real */ ae_matrix* b1, - ae_state *_state); -void sparsesmm(sparsematrix* s, - ae_bool isupper, - /* Real */ ae_matrix* a, - ae_int_t k, - /* Real */ ae_matrix* b, - ae_state *_state); -void sparsetrmv(sparsematrix* s, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -void sparsetrsv(sparsematrix* s, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_vector* x, - ae_state *_state); -void sparsesymmpermtbl(sparsematrix* a, - ae_bool isupper, - /* Integer */ ae_vector* p, - sparsematrix* b, - ae_state *_state); -void sparsesymmpermtblbuf(sparsematrix* a, - ae_bool isupper, - /* Integer */ ae_vector* p, - sparsematrix* b, - ae_state *_state); -void sparseresizematrix(sparsematrix* s, ae_state *_state); -void sparseinitduidx(sparsematrix* s, ae_state *_state); -double sparsegetaveragelengthofchain(sparsematrix* s, ae_state *_state); -ae_bool sparseenumerate(sparsematrix* s, - ae_int_t* t0, - ae_int_t* t1, - ae_int_t* i, - ae_int_t* j, - double* v, - ae_state *_state); -ae_bool sparserewriteexisting(sparsematrix* s, - ae_int_t i, - ae_int_t j, - double v, - ae_state *_state); -void sparsegetrow(sparsematrix* s, - ae_int_t i, - /* Real */ ae_vector* irow, - ae_state *_state); -void sparsegetcompressedrow(sparsematrix* s, - ae_int_t i, - /* Integer */ ae_vector* colidx, - /* Real */ ae_vector* vals, - ae_int_t* nzcnt, - ae_state *_state); -void sparsetransposesks(sparsematrix* s, ae_state *_state); -void sparsetransposecrs(sparsematrix* s, ae_state *_state); -void sparsecopytransposecrs(sparsematrix* s0, - sparsematrix* s1, - ae_state *_state); -void sparsecopytransposecrsbuf(sparsematrix* s0, - sparsematrix* s1, - ae_state *_state); -void sparseconvertto(sparsematrix* s0, ae_int_t fmt, ae_state *_state); -void sparsecopytobuf(sparsematrix* s0, - ae_int_t fmt, - sparsematrix* s1, - ae_state *_state); -void sparseconverttohash(sparsematrix* s, ae_state *_state); -void sparsecopytohash(sparsematrix* s0, - sparsematrix* s1, - ae_state *_state); -void sparsecopytohashbuf(sparsematrix* s0, - sparsematrix* s1, - ae_state *_state); -void sparseconverttocrs(sparsematrix* s, ae_state *_state); -void sparsecopytocrs(sparsematrix* s0, sparsematrix* s1, ae_state *_state); -void sparsecopytocrsbuf(sparsematrix* s0, - sparsematrix* s1, - ae_state *_state); -void sparseconverttosks(sparsematrix* s, ae_state *_state); -void sparsecopytosks(sparsematrix* s0, sparsematrix* s1, ae_state *_state); -void sparsecopytosksbuf(sparsematrix* s0, - sparsematrix* s1, - ae_state *_state); -void sparsecreatecrsinplace(sparsematrix* s, ae_state *_state); -ae_int_t sparsegetmatrixtype(sparsematrix* s, ae_state *_state); -ae_bool sparseishash(sparsematrix* s, ae_state *_state); -ae_bool sparseiscrs(sparsematrix* s, ae_state *_state); -ae_bool sparseissks(sparsematrix* s, ae_state *_state); -void sparsefree(sparsematrix* s, ae_state *_state); -ae_int_t sparsegetnrows(sparsematrix* s, ae_state *_state); -ae_int_t sparsegetncols(sparsematrix* s, ae_state *_state); -ae_int_t sparsegetuppercount(sparsematrix* s, ae_state *_state); -ae_int_t sparsegetlowercount(sparsematrix* s, ae_state *_state); -void _sparsematrix_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _sparsematrix_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _sparsematrix_clear(void* _p); -void _sparsematrix_destroy(void* _p); -void _sparsebuffers_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _sparsebuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _sparsebuffers_clear(void* _p); -void _sparsebuffers_destroy(void* _p); -#endif -#if defined(AE_COMPILE_ABLAS) || !defined(AE_PARTIAL_BUILD) -void ablassplitlength(/* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t* n1, - ae_int_t* n2, - ae_state *_state); -void ablascomplexsplitlength(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_int_t* n1, - ae_int_t* n2, - ae_state *_state); -ae_int_t gemmparallelsize(ae_state *_state); -ae_int_t ablasblocksize(/* Real */ ae_matrix* a, ae_state *_state); -ae_int_t ablascomplexblocksize(/* Complex */ ae_matrix* a, - ae_state *_state); -ae_int_t ablasmicroblocksize(ae_state *_state); -void generatereflection(/* Real */ ae_vector* x, - ae_int_t n, - double* tau, - ae_state *_state); -void applyreflectionfromtheleft(/* Real */ ae_matrix* c, - double tau, - /* Real */ ae_vector* v, - ae_int_t m1, - ae_int_t m2, - ae_int_t n1, - ae_int_t n2, - /* Real */ ae_vector* work, - ae_state *_state); -void applyreflectionfromtheright(/* Real */ ae_matrix* c, - double tau, - /* Real */ ae_vector* v, - ae_int_t m1, - ae_int_t m2, - ae_int_t n1, - ae_int_t n2, - /* Real */ ae_vector* work, - ae_state *_state); -void cmatrixtranspose(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Complex */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_state *_state); -void rmatrixtranspose(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_state *_state); -void rmatrixenforcesymmetricity(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_state *_state); -void cmatrixcopy(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Complex */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_state *_state); -void rvectorcopy(ae_int_t n, - /* Real */ ae_vector* a, - ae_int_t ia, - /* Real */ ae_vector* b, - ae_int_t ib, - ae_state *_state); -void rmatrixcopy(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_state *_state); -void rmatrixgencopy(ae_int_t m, - ae_int_t n, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - double beta, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_state *_state); -void rmatrixger(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - double alpha, - /* Real */ ae_vector* u, - ae_int_t iu, - /* Real */ ae_vector* v, - ae_int_t iv, - ae_state *_state); -void cmatrixrank1(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Complex */ ae_vector* u, - ae_int_t iu, - /* Complex */ ae_vector* v, - ae_int_t iv, - ae_state *_state); -void rmatrixrank1(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - /* Real */ ae_vector* u, - ae_int_t iu, - /* Real */ ae_vector* v, - ae_int_t iv, - ae_state *_state); -void rmatrixgemv(ae_int_t m, - ae_int_t n, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t opa, - /* Real */ ae_vector* x, - ae_int_t ix, - double beta, - /* Real */ ae_vector* y, - ae_int_t iy, - ae_state *_state); -void cmatrixmv(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t opa, - /* Complex */ ae_vector* x, - ae_int_t ix, - /* Complex */ ae_vector* y, - ae_int_t iy, - ae_state *_state); -void rmatrixmv(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t opa, - /* Real */ ae_vector* x, - ae_int_t ix, - /* Real */ ae_vector* y, - ae_int_t iy, - ae_state *_state); -void rmatrixsymv(ae_int_t n, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_bool isupper, - /* Real */ ae_vector* x, - ae_int_t ix, - double beta, - /* Real */ ae_vector* y, - ae_int_t iy, - ae_state *_state); -double rmatrixsyvmv(ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_bool isupper, - /* Real */ ae_vector* x, - ae_int_t ix, - /* Real */ ae_vector* tmp, - ae_state *_state); -void rmatrixtrsv(ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_vector* x, - ae_int_t ix, - ae_state *_state); -void cmatrixrighttrsm(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state); -ae_bool _trypexec_cmatrixrighttrsm(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, ae_state *_state); -void cmatrixlefttrsm(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state); -ae_bool _trypexec_cmatrixlefttrsm(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, ae_state *_state); -void rmatrixrighttrsm(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state); -ae_bool _trypexec_rmatrixrighttrsm(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, ae_state *_state); -void rmatrixlefttrsm(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state); -ae_bool _trypexec_rmatrixlefttrsm(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, ae_state *_state); -void cmatrixherk(ae_int_t n, - ae_int_t k, - double alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state); -ae_bool _trypexec_cmatrixherk(ae_int_t n, - ae_int_t k, - double alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, ae_state *_state); -void rmatrixsyrk(ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state); -ae_bool _trypexec_rmatrixsyrk(ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, ae_state *_state); -void cmatrixgemm(ae_int_t m, - ae_int_t n, - ae_int_t k, - ae_complex alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Complex */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - ae_complex beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state); -ae_bool _trypexec_cmatrixgemm(ae_int_t m, - ae_int_t n, - ae_int_t k, - ae_complex alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Complex */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - ae_complex beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, ae_state *_state); -void rmatrixgemm(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state); -ae_bool _trypexec_rmatrixgemm(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, ae_state *_state); -void cmatrixsyrk(ae_int_t n, - ae_int_t k, - double alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state); -void rowwisegramschmidt(/* Real */ ae_matrix* q, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* qx, - ae_bool needqx, - ae_state *_state); -#endif -#if defined(AE_COMPILE_DLU) || !defined(AE_PARTIAL_BUILD) -void cmatrixluprec(/* Complex */ ae_matrix* a, - ae_int_t offs, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - /* Complex */ ae_vector* tmp, - ae_state *_state); -void rmatrixluprec(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - /* Real */ ae_vector* tmp, - ae_state *_state); -void cmatrixplurec(/* Complex */ ae_matrix* a, - ae_int_t offs, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - /* Complex */ ae_vector* tmp, - ae_state *_state); -void rmatrixplurec(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - /* Real */ ae_vector* tmp, - ae_state *_state); -#endif -#if defined(AE_COMPILE_SPTRF) || !defined(AE_PARTIAL_BUILD) -ae_bool sptrflu(sparsematrix* a, - ae_int_t pivottype, - /* Integer */ ae_vector* pr, - /* Integer */ ae_vector* pc, - sluv2buffer* buf, - ae_state *_state); -void _sluv2list1matrix_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _sluv2list1matrix_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _sluv2list1matrix_clear(void* _p); -void _sluv2list1matrix_destroy(void* _p); -void _sluv2sparsetrail_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _sluv2sparsetrail_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _sluv2sparsetrail_clear(void* _p); -void _sluv2sparsetrail_destroy(void* _p); -void _sluv2densetrail_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _sluv2densetrail_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _sluv2densetrail_clear(void* _p); -void _sluv2densetrail_destroy(void* _p); -void _sluv2buffer_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _sluv2buffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _sluv2buffer_clear(void* _p); -void _sluv2buffer_destroy(void* _p); -#endif -#if defined(AE_COMPILE_AMDORDERING) || !defined(AE_PARTIAL_BUILD) -void generateamdpermutation(sparsematrix* a, - ae_int_t n, - /* Integer */ ae_vector* perm, - /* Integer */ ae_vector* invperm, - amdbuffer* buf, - ae_state *_state); -void _amdnset_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _amdnset_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _amdnset_clear(void* _p); -void _amdnset_destroy(void* _p); -void _amdknset_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _amdknset_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _amdknset_clear(void* _p); -void _amdknset_destroy(void* _p); -void _amdvertexset_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _amdvertexset_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _amdvertexset_clear(void* _p); -void _amdvertexset_destroy(void* _p); -void _amdllmatrix_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _amdllmatrix_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _amdllmatrix_clear(void* _p); -void _amdllmatrix_destroy(void* _p); -void _amdbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _amdbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _amdbuffer_clear(void* _p); -void _amdbuffer_destroy(void* _p); -#endif -#if defined(AE_COMPILE_SPCHOL) || !defined(AE_PARTIAL_BUILD) -ae_int_t spsymmgetmaxfastkernel(ae_state *_state); -ae_bool spsymmanalyze(sparsematrix* a, - ae_int_t facttype, - ae_int_t permtype, - spcholanalysis* analysis, - ae_state *_state); -void spsymmsetmodificationstrategy(spcholanalysis* analysis, - ae_int_t modstrategy, - double p0, - double p1, - double p2, - double p3, - ae_state *_state); -void spsymmreload(spcholanalysis* analysis, - sparsematrix* a, - ae_state *_state); -ae_bool spsymmfactorize(spcholanalysis* analysis, - sparsematrix* a, - /* Real */ ae_vector* d, - /* Integer */ ae_vector* p, - ae_state *_state); -void _spcholanalysis_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _spcholanalysis_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _spcholanalysis_clear(void* _p); -void _spcholanalysis_destroy(void* _p); -#endif -#if defined(AE_COMPILE_MATGEN) || !defined(AE_PARTIAL_BUILD) -void rmatrixrndorthogonal(ae_int_t n, - /* Real */ ae_matrix* a, - ae_state *_state); -void rmatrixrndcond(ae_int_t n, - double c, - /* Real */ ae_matrix* a, - ae_state *_state); -void cmatrixrndorthogonal(ae_int_t n, - /* Complex */ ae_matrix* a, - ae_state *_state); -void cmatrixrndcond(ae_int_t n, - double c, - /* Complex */ ae_matrix* a, - ae_state *_state); -void smatrixrndcond(ae_int_t n, - double c, - /* Real */ ae_matrix* a, - ae_state *_state); -void spdmatrixrndcond(ae_int_t n, - double c, - /* Real */ ae_matrix* a, - ae_state *_state); -void hmatrixrndcond(ae_int_t n, - double c, - /* Complex */ ae_matrix* a, - ae_state *_state); -void hpdmatrixrndcond(ae_int_t n, - double c, - /* Complex */ ae_matrix* a, - ae_state *_state); -void rmatrixrndorthogonalfromtheright(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - ae_state *_state); -void rmatrixrndorthogonalfromtheleft(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - ae_state *_state); -void cmatrixrndorthogonalfromtheright(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - ae_state *_state); -void cmatrixrndorthogonalfromtheleft(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - ae_state *_state); -void smatrixrndmultiply(/* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state); -void hmatrixrndmultiply(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_state *_state); -#endif -#if defined(AE_COMPILE_TRFAC) || !defined(AE_PARTIAL_BUILD) -void rmatrixlu(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - ae_state *_state); -void cmatrixlu(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - ae_state *_state); -ae_bool hpdmatrixcholesky(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_state *_state); -ae_bool spdmatrixcholesky(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_state *_state); -void spdmatrixcholeskyupdateadd1(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* u, - ae_state *_state); -void spdmatrixcholeskyupdatefix(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Boolean */ ae_vector* fix, - ae_state *_state); -void spdmatrixcholeskyupdateadd1buf(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* u, - /* Real */ ae_vector* bufr, - ae_state *_state); -void spdmatrixcholeskyupdatefixbuf(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Boolean */ ae_vector* fix, - /* Real */ ae_vector* bufr, - ae_state *_state); -ae_bool sparselu(sparsematrix* a, - ae_int_t pivottype, - /* Integer */ ae_vector* p, - /* Integer */ ae_vector* q, - ae_state *_state); -ae_bool sparsecholeskyskyline(sparsematrix* a, - ae_int_t n, - ae_bool isupper, - ae_state *_state); -ae_bool sparsecholesky(sparsematrix* a, ae_bool isupper, ae_state *_state); -ae_bool sparsecholeskyp(sparsematrix* a, - ae_bool isupper, - /* Integer */ ae_vector* p, - ae_state *_state); -ae_bool sparsecholeskyanalyze(sparsematrix* a, - ae_bool isupper, - ae_int_t facttype, - ae_int_t permtype, - sparsedecompositionanalysis* analysis, - ae_state *_state); -void sparsecholeskysetmodtype(sparsedecompositionanalysis* analysis, - ae_int_t modstrategy, - double p0, - double p1, - double p2, - double p3, - ae_state *_state); -ae_bool sparsecholeskyfactorize(sparsedecompositionanalysis* analysis, - ae_bool needupper, - sparsematrix* a, - /* Real */ ae_vector* d, - /* Integer */ ae_vector* p, - ae_state *_state); -void sparsecholeskyreload(sparsedecompositionanalysis* analysis, - sparsematrix* a, - ae_bool isupper, - ae_state *_state); -void rmatrixlup(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - ae_state *_state); -void cmatrixlup(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - ae_state *_state); -void rmatrixplu(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - ae_state *_state); -void cmatrixplu(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - ae_state *_state); -ae_bool spdmatrixcholeskyrec(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* tmp, - ae_state *_state); -void _sparsedecompositionanalysis_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _sparsedecompositionanalysis_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _sparsedecompositionanalysis_clear(void* _p); -void _sparsedecompositionanalysis_destroy(void* _p); -#endif -#if defined(AE_COMPILE_RCOND) || !defined(AE_PARTIAL_BUILD) -double rmatrixrcond1(/* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state); -double rmatrixrcondinf(/* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state); -double spdmatrixrcond(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_state *_state); -double rmatrixtrrcond1(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - ae_state *_state); -double rmatrixtrrcondinf(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - ae_state *_state); -double hpdmatrixrcond(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_state *_state); -double cmatrixrcond1(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_state *_state); -double cmatrixrcondinf(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_state *_state); -double rmatrixlurcond1(/* Real */ ae_matrix* lua, - ae_int_t n, - ae_state *_state); -double rmatrixlurcondinf(/* Real */ ae_matrix* lua, - ae_int_t n, - ae_state *_state); -double spdmatrixcholeskyrcond(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_state *_state); -double hpdmatrixcholeskyrcond(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_state *_state); -double cmatrixlurcond1(/* Complex */ ae_matrix* lua, - ae_int_t n, - ae_state *_state); -double cmatrixlurcondinf(/* Complex */ ae_matrix* lua, - ae_int_t n, - ae_state *_state); -double cmatrixtrrcond1(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - ae_state *_state); -double cmatrixtrrcondinf(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - ae_state *_state); -double rcondthreshold(ae_state *_state); -#endif -#if defined(AE_COMPILE_MATINV) || !defined(AE_PARTIAL_BUILD) -void rmatrixluinverse(/* Real */ ae_matrix* a, - /* Integer */ ae_vector* pivots, - ae_int_t n, - ae_int_t* info, - matinvreport* rep, - ae_state *_state); -void rmatrixinverse(/* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t* info, - matinvreport* rep, - ae_state *_state); -void cmatrixluinverse(/* Complex */ ae_matrix* a, - /* Integer */ ae_vector* pivots, - ae_int_t n, - ae_int_t* info, - matinvreport* rep, - ae_state *_state); -void cmatrixinverse(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_int_t* info, - matinvreport* rep, - ae_state *_state); -void spdmatrixcholeskyinverse(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_int_t* info, - matinvreport* rep, - ae_state *_state); -void spdmatrixinverse(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_int_t* info, - matinvreport* rep, - ae_state *_state); -void hpdmatrixcholeskyinverse(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_int_t* info, - matinvreport* rep, - ae_state *_state); -void hpdmatrixinverse(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_int_t* info, - matinvreport* rep, - ae_state *_state); -void rmatrixtrinverse(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - ae_int_t* info, - matinvreport* rep, - ae_state *_state); -void cmatrixtrinverse(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunit, - ae_int_t* info, - matinvreport* rep, - ae_state *_state); -void spdmatrixcholeskyinverserec(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* tmp, - ae_state *_state); -ae_bool _trypexec_spdmatrixcholeskyinverserec(/* Real */ ae_matrix* a, - ae_int_t offs, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* tmp, ae_state *_state); -void _matinvreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _matinvreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _matinvreport_clear(void* _p); -void _matinvreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_ORTFAC) || !defined(AE_PARTIAL_BUILD) -void rmatrixqr(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* tau, - ae_state *_state); -void rmatrixlq(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* tau, - ae_state *_state); -void cmatrixqr(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_vector* tau, - ae_state *_state); -void cmatrixlq(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_vector* tau, - ae_state *_state); -void rmatrixqrunpackq(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* tau, - ae_int_t qcolumns, - /* Real */ ae_matrix* q, - ae_state *_state); -void rmatrixqrunpackr(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* r, - ae_state *_state); -void rmatrixlqunpackq(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* tau, - ae_int_t qrows, - /* Real */ ae_matrix* q, - ae_state *_state); -void rmatrixlqunpackl(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* l, - ae_state *_state); -void cmatrixqrunpackq(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_vector* tau, - ae_int_t qcolumns, - /* Complex */ ae_matrix* q, - ae_state *_state); -void cmatrixqrunpackr(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* r, - ae_state *_state); -void cmatrixlqunpackq(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_vector* tau, - ae_int_t qrows, - /* Complex */ ae_matrix* q, - ae_state *_state); -void cmatrixlqunpackl(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* l, - ae_state *_state); -void rmatrixqrbasecase(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* work, - /* Real */ ae_vector* t, - /* Real */ ae_vector* tau, - ae_state *_state); -void rmatrixlqbasecase(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* work, - /* Real */ ae_vector* t, - /* Real */ ae_vector* tau, - ae_state *_state); -void rmatrixbd(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* tauq, - /* Real */ ae_vector* taup, - ae_state *_state); -void rmatrixbdunpackq(/* Real */ ae_matrix* qp, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* tauq, - ae_int_t qcolumns, - /* Real */ ae_matrix* q, - ae_state *_state); -void rmatrixbdmultiplybyq(/* Real */ ae_matrix* qp, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* tauq, - /* Real */ ae_matrix* z, - ae_int_t zrows, - ae_int_t zcolumns, - ae_bool fromtheright, - ae_bool dotranspose, - ae_state *_state); -void rmatrixbdunpackpt(/* Real */ ae_matrix* qp, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* taup, - ae_int_t ptrows, - /* Real */ ae_matrix* pt, - ae_state *_state); -void rmatrixbdmultiplybyp(/* Real */ ae_matrix* qp, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* taup, - /* Real */ ae_matrix* z, - ae_int_t zrows, - ae_int_t zcolumns, - ae_bool fromtheright, - ae_bool dotranspose, - ae_state *_state); -void rmatrixbdunpackdiagonals(/* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t n, - ae_bool* isupper, - /* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_state *_state); -void rmatrixhessenberg(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_vector* tau, - ae_state *_state); -void rmatrixhessenbergunpackq(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_vector* tau, - /* Real */ ae_matrix* q, - ae_state *_state); -void rmatrixhessenbergunpackh(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_matrix* h, - ae_state *_state); -void smatrixtd(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* tau, - /* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_state *_state); -void smatrixtdunpackq(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* tau, - /* Real */ ae_matrix* q, - ae_state *_state); -void hmatrixtd(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* tau, - /* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_state *_state); -void hmatrixtdunpackq(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* tau, - /* Complex */ ae_matrix* q, - ae_state *_state); -#endif -#if defined(AE_COMPILE_FBLS) || !defined(AE_PARTIAL_BUILD) -void fblscholeskysolve(/* Real */ ae_matrix* cha, - double sqrtscalea, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* xb, - /* Real */ ae_vector* tmp, - ae_state *_state); -void fblssolvecgx(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double alpha, - /* Real */ ae_vector* b, - /* Real */ ae_vector* x, - /* Real */ ae_vector* buf, - ae_state *_state); -void fblscgcreate(/* Real */ ae_vector* x, - /* Real */ ae_vector* b, - ae_int_t n, - fblslincgstate* state, - ae_state *_state); -ae_bool fblscgiteration(fblslincgstate* state, ae_state *_state); -void fblsgmrescreate(/* Real */ ae_vector* b, - ae_int_t n, - ae_int_t k, - fblsgmresstate* state, - ae_state *_state); -ae_bool fblsgmresiteration(fblsgmresstate* state, ae_state *_state); -void fblssolvels(/* Real */ ae_matrix* a, - /* Real */ ae_vector* b, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* tmp0, - /* Real */ ae_vector* tmp1, - /* Real */ ae_vector* tmp2, - ae_state *_state); -void _fblslincgstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _fblslincgstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _fblslincgstate_clear(void* _p); -void _fblslincgstate_destroy(void* _p); -void _fblsgmresstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _fblsgmresstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _fblsgmresstate_clear(void* _p); -void _fblsgmresstate_destroy(void* _p); -#endif -#if defined(AE_COMPILE_BDSVD) || !defined(AE_PARTIAL_BUILD) -ae_bool rmatrixbdsvd(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_bool isupper, - ae_bool isfractionalaccuracyrequired, - /* Real */ ae_matrix* u, - ae_int_t nru, - /* Real */ ae_matrix* c, - ae_int_t ncc, - /* Real */ ae_matrix* vt, - ae_int_t ncvt, - ae_state *_state); -ae_bool bidiagonalsvddecomposition(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_bool isupper, - ae_bool isfractionalaccuracyrequired, - /* Real */ ae_matrix* u, - ae_int_t nru, - /* Real */ ae_matrix* c, - ae_int_t ncc, - /* Real */ ae_matrix* vt, - ae_int_t ncvt, - ae_state *_state); -#endif -#if defined(AE_COMPILE_SVD) || !defined(AE_PARTIAL_BUILD) -ae_bool rmatrixsvd(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - ae_int_t uneeded, - ae_int_t vtneeded, - ae_int_t additionalmemory, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* u, - /* Real */ ae_matrix* vt, - ae_state *_state); -#endif -#if defined(AE_COMPILE_NORMESTIMATOR) || !defined(AE_PARTIAL_BUILD) -void normestimatorcreate(ae_int_t m, - ae_int_t n, - ae_int_t nstart, - ae_int_t nits, - normestimatorstate* state, - ae_state *_state); -void normestimatorsetseed(normestimatorstate* state, - ae_int_t seedval, - ae_state *_state); -ae_bool normestimatoriteration(normestimatorstate* state, - ae_state *_state); -void normestimatorestimatesparse(normestimatorstate* state, - sparsematrix* a, - ae_state *_state); -void normestimatorresults(normestimatorstate* state, - double* nrm, - ae_state *_state); -void normestimatorrestart(normestimatorstate* state, ae_state *_state); -void _normestimatorstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _normestimatorstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _normestimatorstate_clear(void* _p); -void _normestimatorstate_destroy(void* _p); -#endif -#if defined(AE_COMPILE_HSSCHUR) || !defined(AE_PARTIAL_BUILD) -void rmatrixinternalschurdecomposition(/* Real */ ae_matrix* h, - ae_int_t n, - ae_int_t tneeded, - ae_int_t zneeded, - /* Real */ ae_vector* wr, - /* Real */ ae_vector* wi, - /* Real */ ae_matrix* z, - ae_int_t* info, - ae_state *_state); -ae_bool upperhessenbergschurdecomposition(/* Real */ ae_matrix* h, - ae_int_t n, - /* Real */ ae_matrix* s, - ae_state *_state); -void internalschurdecomposition(/* Real */ ae_matrix* h, - ae_int_t n, - ae_int_t tneeded, - ae_int_t zneeded, - /* Real */ ae_vector* wr, - /* Real */ ae_vector* wi, - /* Real */ ae_matrix* z, - ae_int_t* info, - ae_state *_state); -#endif -#if defined(AE_COMPILE_EVD) || !defined(AE_PARTIAL_BUILD) -void eigsubspacecreate(ae_int_t n, - ae_int_t k, - eigsubspacestate* state, - ae_state *_state); -void eigsubspacecreatebuf(ae_int_t n, - ae_int_t k, - eigsubspacestate* state, - ae_state *_state); -void eigsubspacesetcond(eigsubspacestate* state, - double eps, - ae_int_t maxits, - ae_state *_state); -void eigsubspacesetwarmstart(eigsubspacestate* state, - ae_bool usewarmstart, - ae_state *_state); -void eigsubspaceoocstart(eigsubspacestate* state, - ae_int_t mtype, - ae_state *_state); -ae_bool eigsubspaceooccontinue(eigsubspacestate* state, ae_state *_state); -void eigsubspaceoocgetrequestinfo(eigsubspacestate* state, - ae_int_t* requesttype, - ae_int_t* requestsize, - ae_state *_state); -void eigsubspaceoocgetrequestdata(eigsubspacestate* state, - /* Real */ ae_matrix* x, - ae_state *_state); -void eigsubspaceoocsendresult(eigsubspacestate* state, - /* Real */ ae_matrix* ax, - ae_state *_state); -void eigsubspaceoocstop(eigsubspacestate* state, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* z, - eigsubspacereport* rep, - ae_state *_state); -void eigsubspacesolvedenses(eigsubspacestate* state, - /* Real */ ae_matrix* a, - ae_bool isupper, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* z, - eigsubspacereport* rep, - ae_state *_state); -void eigsubspacesolvesparses(eigsubspacestate* state, - sparsematrix* a, - ae_bool isupper, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* z, - eigsubspacereport* rep, - ae_state *_state); -ae_bool eigsubspaceiteration(eigsubspacestate* state, ae_state *_state); -ae_bool smatrixevd(/* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t zneeded, - ae_bool isupper, - /* Real */ ae_vector* d, - /* Real */ ae_matrix* z, - ae_state *_state); -ae_bool smatrixevdr(/* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t zneeded, - ae_bool isupper, - double b1, - double b2, - ae_int_t* m, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* z, - ae_state *_state); -ae_bool smatrixevdi(/* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t zneeded, - ae_bool isupper, - ae_int_t i1, - ae_int_t i2, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* z, - ae_state *_state); -ae_bool hmatrixevd(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_int_t zneeded, - ae_bool isupper, - /* Real */ ae_vector* d, - /* Complex */ ae_matrix* z, - ae_state *_state); -ae_bool hmatrixevdr(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_int_t zneeded, - ae_bool isupper, - double b1, - double b2, - ae_int_t* m, - /* Real */ ae_vector* w, - /* Complex */ ae_matrix* z, - ae_state *_state); -ae_bool hmatrixevdi(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_int_t zneeded, - ae_bool isupper, - ae_int_t i1, - ae_int_t i2, - /* Real */ ae_vector* w, - /* Complex */ ae_matrix* z, - ae_state *_state); -ae_bool smatrixtdevd(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_int_t zneeded, - /* Real */ ae_matrix* z, - ae_state *_state); -ae_bool smatrixtdevdr(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_int_t zneeded, - double a, - double b, - ae_int_t* m, - /* Real */ ae_matrix* z, - ae_state *_state); -ae_bool smatrixtdevdi(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_int_t zneeded, - ae_int_t i1, - ae_int_t i2, - /* Real */ ae_matrix* z, - ae_state *_state); -ae_bool rmatrixevd(/* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t vneeded, - /* Real */ ae_vector* wr, - /* Real */ ae_vector* wi, - /* Real */ ae_matrix* vl, - /* Real */ ae_matrix* vr, - ae_state *_state); -void _eigsubspacestate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _eigsubspacestate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _eigsubspacestate_clear(void* _p); -void _eigsubspacestate_destroy(void* _p); -void _eigsubspacereport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _eigsubspacereport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _eigsubspacereport_clear(void* _p); -void _eigsubspacereport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_SCHUR) || !defined(AE_PARTIAL_BUILD) -ae_bool rmatrixschur(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_matrix* s, - ae_state *_state); -#endif -#if defined(AE_COMPILE_SPDGEVD) || !defined(AE_PARTIAL_BUILD) -ae_bool smatrixgevd(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isuppera, - /* Real */ ae_matrix* b, - ae_bool isupperb, - ae_int_t zneeded, - ae_int_t problemtype, - /* Real */ ae_vector* d, - /* Real */ ae_matrix* z, - ae_state *_state); -ae_bool smatrixgevdreduce(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isuppera, - /* Real */ ae_matrix* b, - ae_bool isupperb, - ae_int_t problemtype, - /* Real */ ae_matrix* r, - ae_bool* isupperr, - ae_state *_state); -#endif -#if defined(AE_COMPILE_INVERSEUPDATE) || !defined(AE_PARTIAL_BUILD) -void rmatrixinvupdatesimple(/* Real */ ae_matrix* inva, - ae_int_t n, - ae_int_t updrow, - ae_int_t updcolumn, - double updval, - ae_state *_state); -void rmatrixinvupdaterow(/* Real */ ae_matrix* inva, - ae_int_t n, - ae_int_t updrow, - /* Real */ ae_vector* v, - ae_state *_state); -void rmatrixinvupdatecolumn(/* Real */ ae_matrix* inva, - ae_int_t n, - ae_int_t updcolumn, - /* Real */ ae_vector* u, - ae_state *_state); -void rmatrixinvupdateuv(/* Real */ ae_matrix* inva, - ae_int_t n, - /* Real */ ae_vector* u, - /* Real */ ae_vector* v, - ae_state *_state); -#endif -#if defined(AE_COMPILE_MATDET) || !defined(AE_PARTIAL_BUILD) -double rmatrixludet(/* Real */ ae_matrix* a, - /* Integer */ ae_vector* pivots, - ae_int_t n, - ae_state *_state); -double rmatrixdet(/* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state); -ae_complex cmatrixludet(/* Complex */ ae_matrix* a, - /* Integer */ ae_vector* pivots, - ae_int_t n, - ae_state *_state); -ae_complex cmatrixdet(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_state *_state); -double spdmatrixcholeskydet(/* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state); -double spdmatrixdet(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_state *_state); -#endif - -} -#endif - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/optimization.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/optimization.cpp deleted file mode 100644 index a9fe3bb..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/optimization.cpp +++ /dev/null @@ -1,81025 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifdef _MSC_VER -#define _CRT_SECURE_NO_WARNINGS -#endif -#include "stdafx.h" -#include "optimization.h" - -// disable some irrelevant warnings -#if (AE_COMPILER==AE_MSVC) && !defined(AE_ALL_WARNINGS) -#pragma warning(disable:4100) -#pragma warning(disable:4127) -#pragma warning(disable:4611) -#pragma warning(disable:4702) -#pragma warning(disable:4996) -#endif - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_CQMODELS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_OPTGUARDAPI) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_OPTSERV) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SNNLS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SACTIVESETS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_QQPSOLVER) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINLBFGS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_LPQPSERV) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_VIPMSOLVER) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_NLCSQP) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_QPDENSEAULSOLVER) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINBLEIC) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_QPBLEICSOLVER) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINQP) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_LPQPPRESOLVE) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_REVISEDDUALSIMPLEX) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINLP) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_NLCSLP) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINNLC) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINBC) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINNS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINCOMP) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINCG) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINLM) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_CQMODELS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_OPTGUARDAPI) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This structure is used to store OptGuard report, i.e. report on the -properties of the nonlinear function being optimized with ALGLIB. - -After you tell your optimizer to activate OptGuard this technology starts -to silently monitor function values and gradients/Jacobians being passed -all around during your optimization session. Depending on specific set of -checks enabled OptGuard may perform additional function evaluations (say, -about 3*N evaluations if you want to check analytic gradient for errors). - -Upon discovering that something strange happens (function values and/or -gradient components change too sharply and/or unexpectedly) OptGuard sets -one of the "suspicion flags" (without interrupting optimization session). -After optimization is done, you can examine OptGuard report. - -Following report fields can be set: -* nonc0suspected -* nonc1suspected -* badgradsuspected - - -=== WHAT CAN BE DETECTED WITH OptGuard INTEGRITY CHECKER ================= - -Following types of errors in your target function (constraints) can be -caught: -a) discontinuous functions ("non-C0" part of the report) -b) functions with discontinuous derivative ("non-C1" part of the report) -c) errors in the analytic gradient provided by user - -These types of errors result in optimizer stopping well before reaching -solution (most often - right after encountering discontinuity). - -Type A errors are usually coding errors during implementation of the -target function. Most "normal" problems involve continuous functions, and -anyway you can't reliably optimize discontinuous function. - -Type B errors are either coding errors or (in case code itself is correct) -evidence of the fact that your problem is an "incorrect" one. Most -optimizers (except for ones provided by MINNS subpackage) do not support -nonsmooth problems. - -Type C errors are coding errors which often prevent optimizer from making -even one step or result in optimizing stopping too early, as soon as -actual descent direction becomes too different from one suggested by user- -supplied gradient. - - -=== WHAT IS REPORTED ===================================================== - -Following set of report fields deals with discontinuous target functions, -ones not belonging to C0 continuity class: - -* nonc0suspected - is a flag which is set upon discovering some indication - of the discontinuity. If this flag is false, the rest of "non-C0" fields - should be ignored -* nonc0fidx - is an index of the function (0 for target function, 1 or - higher for nonlinear constraints) which is suspected of being "non-C0" -* nonc0lipshitzc - a Lipchitz constant for a function which was suspected - of being non-continuous. -* nonc0test0positive - set to indicate specific test which detected - continuity violation (test #0) - -Following set of report fields deals with discontinuous gradient/Jacobian, -i.e. with functions violating C1 continuity: - -* nonc1suspected - is a flag which is set upon discovering some indication - of the discontinuity. If this flag is false, the rest of "non-C1" fields - should be ignored -* nonc1fidx - is an index of the function (0 for target function, 1 or - higher for nonlinear constraints) which is suspected of being "non-C1" -* nonc1lipshitzc - a Lipchitz constant for a function gradient which was - suspected of being non-smooth. -* nonc1test0positive - set to indicate specific test which detected - continuity violation (test #0) -* nonc1test1positive - set to indicate specific test which detected - continuity violation (test #1) - -Following set of report fields deals with errors in the gradient: -* badgradsuspected - is a flad which is set upon discovering an error in - the analytic gradient supplied by user -* badgradfidx - index of the function with bad gradient (0 for target - function, 1 or higher for nonlinear constraints) -* badgradvidx - index of the variable -* badgradxbase - location where Jacobian is tested -* following matrices store user-supplied Jacobian and its numerical - differentiation version (which is assumed to be free from the coding - errors), both of them computed near the initial point: - * badgraduser, an array[K,N], analytic Jacobian supplied by user - * badgradnum, an array[K,N], numeric Jacobian computed by ALGLIB - Here K is a total number of nonlinear functions (target + nonlinear - constraints), N is a variable number. - The element of badgraduser[] with index [badgradfidx,badgradvidx] is - assumed to be wrong. - -More detailed error log can be obtained from optimizer by explicitly -requesting reports for tests C0.0, C1.0, C1.1. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -_optguardreport_owner::_optguardreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_optguardreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::optguardreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::optguardreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::optguardreport)); - alglib_impl::_optguardreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_optguardreport_owner::_optguardreport_owner(const _optguardreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_optguardreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: optguardreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::optguardreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::optguardreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::optguardreport)); - alglib_impl::_optguardreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_optguardreport_owner& _optguardreport_owner::operator=(const _optguardreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: optguardreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: optguardreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_optguardreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::optguardreport)); - alglib_impl::_optguardreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_optguardreport_owner::~_optguardreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_optguardreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::optguardreport* _optguardreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::optguardreport* _optguardreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -optguardreport::optguardreport() : _optguardreport_owner() ,nonc0suspected(p_struct->nonc0suspected),nonc0test0positive(p_struct->nonc0test0positive),nonc0fidx(p_struct->nonc0fidx),nonc0lipschitzc(p_struct->nonc0lipschitzc),nonc1suspected(p_struct->nonc1suspected),nonc1test0positive(p_struct->nonc1test0positive),nonc1test1positive(p_struct->nonc1test1positive),nonc1fidx(p_struct->nonc1fidx),nonc1lipschitzc(p_struct->nonc1lipschitzc),badgradsuspected(p_struct->badgradsuspected),badgradfidx(p_struct->badgradfidx),badgradvidx(p_struct->badgradvidx),badgradxbase(&p_struct->badgradxbase),badgraduser(&p_struct->badgraduser),badgradnum(&p_struct->badgradnum) -{ -} - -optguardreport::optguardreport(const optguardreport &rhs):_optguardreport_owner(rhs) ,nonc0suspected(p_struct->nonc0suspected),nonc0test0positive(p_struct->nonc0test0positive),nonc0fidx(p_struct->nonc0fidx),nonc0lipschitzc(p_struct->nonc0lipschitzc),nonc1suspected(p_struct->nonc1suspected),nonc1test0positive(p_struct->nonc1test0positive),nonc1test1positive(p_struct->nonc1test1positive),nonc1fidx(p_struct->nonc1fidx),nonc1lipschitzc(p_struct->nonc1lipschitzc),badgradsuspected(p_struct->badgradsuspected),badgradfidx(p_struct->badgradfidx),badgradvidx(p_struct->badgradvidx),badgradxbase(&p_struct->badgradxbase),badgraduser(&p_struct->badgraduser),badgradnum(&p_struct->badgradnum) -{ -} - -optguardreport& optguardreport::operator=(const optguardreport &rhs) -{ - if( this==&rhs ) - return *this; - _optguardreport_owner::operator=(rhs); - return *this; -} - -optguardreport::~optguardreport() -{ -} - - -/************************************************************************* -This structure is used for detailed reporting about suspected C0 -continuity violation. - -=== WHAT IS TESTED ======================================================= - -C0 test studies function values (not gradient!) obtained during line -searches and monitors estimate of the Lipschitz constant. Sudden spikes -usually indicate that discontinuity was detected. - - -=== WHAT IS REPORTED ===================================================== - -Actually, report retrieval function returns TWO report structures: - -* one for most suspicious point found so far (one with highest change in - the function value), so called "strongest" report -* another one for most detailed line search (more function evaluations = - easier to understand what's going on) which triggered test #0 criteria, - so called "longest" report - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* fidx - is an index of the function (0 for target function, 1 or higher - for nonlinear constraints) which is suspected of being "non-C1" -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -You can plot function values stored in stp[] and f[] arrays and study -behavior of your function by your own eyes, just to be sure that test -correctly reported C1 violation. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -_optguardnonc0report_owner::_optguardnonc0report_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_optguardnonc0report_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::optguardnonc0report*)alglib_impl::ae_malloc(sizeof(alglib_impl::optguardnonc0report), &_state); - memset(p_struct, 0, sizeof(alglib_impl::optguardnonc0report)); - alglib_impl::_optguardnonc0report_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_optguardnonc0report_owner::_optguardnonc0report_owner(const _optguardnonc0report_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_optguardnonc0report_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: optguardnonc0report copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::optguardnonc0report*)alglib_impl::ae_malloc(sizeof(alglib_impl::optguardnonc0report), &_state); - memset(p_struct, 0, sizeof(alglib_impl::optguardnonc0report)); - alglib_impl::_optguardnonc0report_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_optguardnonc0report_owner& _optguardnonc0report_owner::operator=(const _optguardnonc0report_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: optguardnonc0report assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: optguardnonc0report assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_optguardnonc0report_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::optguardnonc0report)); - alglib_impl::_optguardnonc0report_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_optguardnonc0report_owner::~_optguardnonc0report_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_optguardnonc0report_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::optguardnonc0report* _optguardnonc0report_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::optguardnonc0report* _optguardnonc0report_owner::c_ptr() const -{ - return const_cast(p_struct); -} -optguardnonc0report::optguardnonc0report() : _optguardnonc0report_owner() ,positive(p_struct->positive),fidx(p_struct->fidx),x0(&p_struct->x0),d(&p_struct->d),n(p_struct->n),stp(&p_struct->stp),f(&p_struct->f),cnt(p_struct->cnt),stpidxa(p_struct->stpidxa),stpidxb(p_struct->stpidxb) -{ -} - -optguardnonc0report::optguardnonc0report(const optguardnonc0report &rhs):_optguardnonc0report_owner(rhs) ,positive(p_struct->positive),fidx(p_struct->fidx),x0(&p_struct->x0),d(&p_struct->d),n(p_struct->n),stp(&p_struct->stp),f(&p_struct->f),cnt(p_struct->cnt),stpidxa(p_struct->stpidxa),stpidxb(p_struct->stpidxb) -{ -} - -optguardnonc0report& optguardnonc0report::operator=(const optguardnonc0report &rhs) -{ - if( this==&rhs ) - return *this; - _optguardnonc0report_owner::operator=(rhs); - return *this; -} - -optguardnonc0report::~optguardnonc0report() -{ -} - - -/************************************************************************* -This structure is used for detailed reporting about suspected C1 -continuity violation as flagged by C1 test #0 (OptGuard has several tests -for C1 continuity, this report is used by #0). - -=== WHAT IS TESTED ======================================================= - -C1 test #0 studies function values (not gradient!) obtained during line -searches and monitors behavior of directional derivative estimate. This -test is less powerful than test #1, but it does not depend on gradient -values and thus it is more robust against artifacts introduced by -numerical differentiation. - - -=== WHAT IS REPORTED ===================================================== - -Actually, report retrieval function returns TWO report structures: - -* one for most suspicious point found so far (one with highest change in - the directional derivative), so called "strongest" report -* another one for most detailed line search (more function evaluations = - easier to understand what's going on) which triggered test #0 criteria, - so called "longest" report - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* fidx - is an index of the function (0 for target function, 1 or higher - for nonlinear constraints) which is suspected of being "non-C1" -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -You can plot function values stored in stp[] and f[] arrays and study -behavior of your function by your own eyes, just to be sure that test -correctly reported C1 violation. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -_optguardnonc1test0report_owner::_optguardnonc1test0report_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_optguardnonc1test0report_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::optguardnonc1test0report*)alglib_impl::ae_malloc(sizeof(alglib_impl::optguardnonc1test0report), &_state); - memset(p_struct, 0, sizeof(alglib_impl::optguardnonc1test0report)); - alglib_impl::_optguardnonc1test0report_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_optguardnonc1test0report_owner::_optguardnonc1test0report_owner(const _optguardnonc1test0report_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_optguardnonc1test0report_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: optguardnonc1test0report copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::optguardnonc1test0report*)alglib_impl::ae_malloc(sizeof(alglib_impl::optguardnonc1test0report), &_state); - memset(p_struct, 0, sizeof(alglib_impl::optguardnonc1test0report)); - alglib_impl::_optguardnonc1test0report_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_optguardnonc1test0report_owner& _optguardnonc1test0report_owner::operator=(const _optguardnonc1test0report_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: optguardnonc1test0report assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: optguardnonc1test0report assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_optguardnonc1test0report_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::optguardnonc1test0report)); - alglib_impl::_optguardnonc1test0report_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_optguardnonc1test0report_owner::~_optguardnonc1test0report_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_optguardnonc1test0report_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::optguardnonc1test0report* _optguardnonc1test0report_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::optguardnonc1test0report* _optguardnonc1test0report_owner::c_ptr() const -{ - return const_cast(p_struct); -} -optguardnonc1test0report::optguardnonc1test0report() : _optguardnonc1test0report_owner() ,positive(p_struct->positive),fidx(p_struct->fidx),x0(&p_struct->x0),d(&p_struct->d),n(p_struct->n),stp(&p_struct->stp),f(&p_struct->f),cnt(p_struct->cnt),stpidxa(p_struct->stpidxa),stpidxb(p_struct->stpidxb) -{ -} - -optguardnonc1test0report::optguardnonc1test0report(const optguardnonc1test0report &rhs):_optguardnonc1test0report_owner(rhs) ,positive(p_struct->positive),fidx(p_struct->fidx),x0(&p_struct->x0),d(&p_struct->d),n(p_struct->n),stp(&p_struct->stp),f(&p_struct->f),cnt(p_struct->cnt),stpidxa(p_struct->stpidxa),stpidxb(p_struct->stpidxb) -{ -} - -optguardnonc1test0report& optguardnonc1test0report::operator=(const optguardnonc1test0report &rhs) -{ - if( this==&rhs ) - return *this; - _optguardnonc1test0report_owner::operator=(rhs); - return *this; -} - -optguardnonc1test0report::~optguardnonc1test0report() -{ -} - - -/************************************************************************* -This structure is used for detailed reporting about suspected C1 -continuity violation as flagged by C1 test #1 (OptGuard has several tests -for C1 continuity, this report is used by #1). - -=== WHAT IS TESTED ======================================================= - -C1 test #1 studies individual components of the gradient as recorded -during line searches. Upon discovering discontinuity in the gradient this -test records specific component which was suspected (or one with highest -indication of discontinuity if multiple components are suspected). - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - - -=== WHAT IS REPORTED ===================================================== - -Actually, report retrieval function returns TWO report structures: - -* one for most suspicious point found so far (one with highest change in - the directional derivative), so called "strongest" report -* another one for most detailed line search (more function evaluations = - easier to understand what's going on) which triggered test #1 criteria, - so called "longest" report - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* fidx - is an index of the function (0 for target function, 1 or higher - for nonlinear constraints) which is suspected of being "non-C1" -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -You can plot function values stored in stp[] and g[] arrays and study -behavior of your function by your own eyes, just to be sure that test -correctly reported C1 violation. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -_optguardnonc1test1report_owner::_optguardnonc1test1report_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_optguardnonc1test1report_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::optguardnonc1test1report*)alglib_impl::ae_malloc(sizeof(alglib_impl::optguardnonc1test1report), &_state); - memset(p_struct, 0, sizeof(alglib_impl::optguardnonc1test1report)); - alglib_impl::_optguardnonc1test1report_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_optguardnonc1test1report_owner::_optguardnonc1test1report_owner(const _optguardnonc1test1report_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_optguardnonc1test1report_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: optguardnonc1test1report copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::optguardnonc1test1report*)alglib_impl::ae_malloc(sizeof(alglib_impl::optguardnonc1test1report), &_state); - memset(p_struct, 0, sizeof(alglib_impl::optguardnonc1test1report)); - alglib_impl::_optguardnonc1test1report_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_optguardnonc1test1report_owner& _optguardnonc1test1report_owner::operator=(const _optguardnonc1test1report_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: optguardnonc1test1report assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: optguardnonc1test1report assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_optguardnonc1test1report_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::optguardnonc1test1report)); - alglib_impl::_optguardnonc1test1report_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_optguardnonc1test1report_owner::~_optguardnonc1test1report_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_optguardnonc1test1report_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::optguardnonc1test1report* _optguardnonc1test1report_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::optguardnonc1test1report* _optguardnonc1test1report_owner::c_ptr() const -{ - return const_cast(p_struct); -} -optguardnonc1test1report::optguardnonc1test1report() : _optguardnonc1test1report_owner() ,positive(p_struct->positive),fidx(p_struct->fidx),vidx(p_struct->vidx),x0(&p_struct->x0),d(&p_struct->d),n(p_struct->n),stp(&p_struct->stp),g(&p_struct->g),cnt(p_struct->cnt),stpidxa(p_struct->stpidxa),stpidxb(p_struct->stpidxb) -{ -} - -optguardnonc1test1report::optguardnonc1test1report(const optguardnonc1test1report &rhs):_optguardnonc1test1report_owner(rhs) ,positive(p_struct->positive),fidx(p_struct->fidx),vidx(p_struct->vidx),x0(&p_struct->x0),d(&p_struct->d),n(p_struct->n),stp(&p_struct->stp),g(&p_struct->g),cnt(p_struct->cnt),stpidxa(p_struct->stpidxa),stpidxb(p_struct->stpidxb) -{ -} - -optguardnonc1test1report& optguardnonc1test1report::operator=(const optguardnonc1test1report &rhs) -{ - if( this==&rhs ) - return *this; - _optguardnonc1test1report_owner::operator=(rhs); - return *this; -} - -optguardnonc1test1report::~optguardnonc1test1report() -{ -} -#endif - -#if defined(AE_COMPILE_OPTSERV) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SNNLS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SACTIVESETS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_QQPSOLVER) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINLBFGS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - -*************************************************************************/ -_minlbfgsstate_owner::_minlbfgsstate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minlbfgsstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::minlbfgsstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlbfgsstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minlbfgsstate)); - alglib_impl::_minlbfgsstate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_minlbfgsstate_owner::_minlbfgsstate_owner(const _minlbfgsstate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minlbfgsstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlbfgsstate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::minlbfgsstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlbfgsstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minlbfgsstate)); - alglib_impl::_minlbfgsstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_minlbfgsstate_owner& _minlbfgsstate_owner::operator=(const _minlbfgsstate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minlbfgsstate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlbfgsstate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_minlbfgsstate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::minlbfgsstate)); - alglib_impl::_minlbfgsstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_minlbfgsstate_owner::~_minlbfgsstate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_minlbfgsstate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::minlbfgsstate* _minlbfgsstate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::minlbfgsstate* _minlbfgsstate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -minlbfgsstate::minlbfgsstate() : _minlbfgsstate_owner() ,needf(p_struct->needf),needfg(p_struct->needfg),xupdated(p_struct->xupdated),f(p_struct->f),g(&p_struct->g),x(&p_struct->x) -{ -} - -minlbfgsstate::minlbfgsstate(const minlbfgsstate &rhs):_minlbfgsstate_owner(rhs) ,needf(p_struct->needf),needfg(p_struct->needfg),xupdated(p_struct->xupdated),f(p_struct->f),g(&p_struct->g),x(&p_struct->x) -{ -} - -minlbfgsstate& minlbfgsstate::operator=(const minlbfgsstate &rhs) -{ - if( this==&rhs ) - return *this; - _minlbfgsstate_owner::operator=(rhs); - return *this; -} - -minlbfgsstate::~minlbfgsstate() -{ -} - - -/************************************************************************* -This structure stores optimization report: -* IterationsCount total number of inner iterations -* NFEV number of gradient evaluations -* TerminationType termination type (see below) - -TERMINATION CODES - -TerminationType field contains completion code, which can be: - -8 internal integrity control detected infinite or NAN values in - function/gradient. Abnormal termination signalled. - 1 relative function improvement is no more than EpsF. - 2 relative step is no more than EpsX. - 4 gradient norm is no more than EpsG - 5 MaxIts steps was taken - 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - 8 terminated by user who called minlbfgsrequesttermination(). - X contains point which was "current accepted" when termination - request was submitted. - -Other fields of this structure are not documented and should not be used! -*************************************************************************/ -_minlbfgsreport_owner::_minlbfgsreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minlbfgsreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::minlbfgsreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlbfgsreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minlbfgsreport)); - alglib_impl::_minlbfgsreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_minlbfgsreport_owner::_minlbfgsreport_owner(const _minlbfgsreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minlbfgsreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlbfgsreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::minlbfgsreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlbfgsreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minlbfgsreport)); - alglib_impl::_minlbfgsreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_minlbfgsreport_owner& _minlbfgsreport_owner::operator=(const _minlbfgsreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minlbfgsreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlbfgsreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_minlbfgsreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::minlbfgsreport)); - alglib_impl::_minlbfgsreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_minlbfgsreport_owner::~_minlbfgsreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_minlbfgsreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::minlbfgsreport* _minlbfgsreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::minlbfgsreport* _minlbfgsreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -minlbfgsreport::minlbfgsreport() : _minlbfgsreport_owner() ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),terminationtype(p_struct->terminationtype) -{ -} - -minlbfgsreport::minlbfgsreport(const minlbfgsreport &rhs):_minlbfgsreport_owner(rhs) ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),terminationtype(p_struct->terminationtype) -{ -} - -minlbfgsreport& minlbfgsreport::operator=(const minlbfgsreport &rhs) -{ - if( this==&rhs ) - return *this; - _minlbfgsreport_owner::operator=(rhs); - return *this; -} - -minlbfgsreport::~minlbfgsreport() -{ -} - -/************************************************************************* - LIMITED MEMORY BFGS METHOD FOR LARGE SCALE OPTIMIZATION - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments by using a quasi- -Newton method (LBFGS scheme) which is optimized to use a minimum amount -of memory. -The subroutine generates the approximation of an inverse Hessian matrix by -using information about the last M steps of the algorithm (instead of N). -It lessens a required amount of memory from a value of order N^2 to a -value of order 2*N*M. - - -REQUIREMENTS: -Algorithm will request following information during its operation: -* function value F and its gradient G (simultaneously) at given point X - - -USAGE: -1. User initializes algorithm state with MinLBFGSCreate() call -2. User tunes solver parameters with MinLBFGSSetCond() MinLBFGSSetStpMax() - and other functions -3. User calls MinLBFGSOptimize() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. -4. User calls MinLBFGSResults() to get solution -5. Optionally user may call MinLBFGSRestartFrom() to solve another problem - with same N/M but another starting point and/or another function. - MinLBFGSRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension. N>0 - M - number of corrections in the BFGS scheme of Hessian - approximation update. Recommended value: 3<=M<=7. The smaller - value causes worse convergence, the bigger will not cause a - considerably better convergence, but will cause a fall in the - performance. M<=N. - X - initial solution approximation, array[0..N-1]. - - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -NOTES: -1. you may tune stopping conditions with MinLBFGSSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use MinLBFGSSetStpMax() function to bound algorithm's steps. However, - L-BFGS rarely needs such a tuning. - - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgscreate(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlbfgsstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgscreate(n, m, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* - LIMITED MEMORY BFGS METHOD FOR LARGE SCALE OPTIMIZATION - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments by using a quasi- -Newton method (LBFGS scheme) which is optimized to use a minimum amount -of memory. -The subroutine generates the approximation of an inverse Hessian matrix by -using information about the last M steps of the algorithm (instead of N). -It lessens a required amount of memory from a value of order N^2 to a -value of order 2*N*M. - - -REQUIREMENTS: -Algorithm will request following information during its operation: -* function value F and its gradient G (simultaneously) at given point X - - -USAGE: -1. User initializes algorithm state with MinLBFGSCreate() call -2. User tunes solver parameters with MinLBFGSSetCond() MinLBFGSSetStpMax() - and other functions -3. User calls MinLBFGSOptimize() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. -4. User calls MinLBFGSResults() to get solution -5. Optionally user may call MinLBFGSRestartFrom() to solve another problem - with same N/M but another starting point and/or another function. - MinLBFGSRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension. N>0 - M - number of corrections in the BFGS scheme of Hessian - approximation update. Recommended value: 3<=M<=7. The smaller - value causes worse convergence, the bigger will not cause a - considerably better convergence, but will cause a fall in the - performance. M<=N. - X - initial solution approximation, array[0..N-1]. - - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -NOTES: -1. you may tune stopping conditions with MinLBFGSSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use MinLBFGSSetStpMax() function to bound algorithm's steps. However, - L-BFGS rarely needs such a tuning. - - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minlbfgscreate(const ae_int_t m, const real_1d_array &x, minlbfgsstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgscreate(n, m, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -The subroutine is finite difference variant of MinLBFGSCreate(). It uses -finite differences in order to differentiate target function. - -Description below contains information which is specific to this function -only. We recommend to read comments on MinLBFGSCreate() in order to get -more information about creation of LBFGS optimizer. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - M - number of corrections in the BFGS scheme of Hessian - approximation update. Recommended value: 3<=M<=7. The smaller - value causes worse convergence, the bigger will not cause a - considerably better convergence, but will cause a fall in the - performance. M<=N. - X - starting point, array[0..N-1]. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinLBFGSSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large truncation errors, while too small - step will result in too large numerical errors. 1.0E-6 can be good - value to start with. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. LBFGS needs exact gradient values. - Imprecise gradient may slow down convergence, especially on highly - nonlinear problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -void minlbfgscreatef(const ae_int_t n, const ae_int_t m, const real_1d_array &x, const double diffstep, minlbfgsstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgscreatef(n, m, const_cast(x.c_ptr()), diffstep, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -The subroutine is finite difference variant of MinLBFGSCreate(). It uses -finite differences in order to differentiate target function. - -Description below contains information which is specific to this function -only. We recommend to read comments on MinLBFGSCreate() in order to get -more information about creation of LBFGS optimizer. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - M - number of corrections in the BFGS scheme of Hessian - approximation update. Recommended value: 3<=M<=7. The smaller - value causes worse convergence, the bigger will not cause a - considerably better convergence, but will cause a fall in the - performance. M<=N. - X - starting point, array[0..N-1]. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinLBFGSSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large truncation errors, while too small - step will result in too large numerical errors. 1.0E-6 can be good - value to start with. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. LBFGS needs exact gradient values. - Imprecise gradient may slow down convergence, especially on highly - nonlinear problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minlbfgscreatef(const ae_int_t m, const real_1d_array &x, const double diffstep, minlbfgsstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgscreatef(n, m, const_cast(x.c_ptr()), diffstep, const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets stopping conditions for L-BFGS optimization algorithm. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|=0 - The subroutine finishes its work if on k+1-th iteration - the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - is satisfied. - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - ste pvector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinLBFGSSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to -automatic stopping criterion selection (small EpsX). - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetcond(const minlbfgsstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgssetcond(const_cast(state.c_ptr()), epsg, epsf, epsx, maxits, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinLBFGSOptimize(). - - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetxrep(const minlbfgsstate &state, const bool needxrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgssetxrep(const_cast(state.c_ptr()), needxrep, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0 (default), if - you don't want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which leads to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetstpmax(const minlbfgsstate &state, const double stpmax, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgssetstpmax(const_cast(state.c_ptr()), stpmax, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets scaling coefficients for LBFGS optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of the optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -In most optimizers (and in the LBFGS too) scaling is NOT a form of -preconditioning. It just affects stopping conditions. You should set -preconditioner by separate call to one of the MinLBFGSSetPrec...() -functions. - -There is special preconditioning mode, however, which uses scaling -coefficients to form diagonal preconditioning matrix. You can turn this -mode on, if you want. But you should understand that scaling is not the -same thing as preconditioning - these are two different, although related -forms of tuning solver. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetscale(const minlbfgsstate &state, const real_1d_array &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgssetscale(const_cast(state.c_ptr()), const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Modification of the preconditioner: default preconditioner (simple -scaling, same for all elements of X) is used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetprecdefault(const minlbfgsstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgssetprecdefault(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Modification of the preconditioner: Cholesky factorization of approximate -Hessian is used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - P - triangular preconditioner, Cholesky factorization of - the approximate Hessian. array[0..N-1,0..N-1], - (if larger, only leading N elements are used). - IsUpper - whether upper or lower triangle of P is given - (other triangle is not referenced) - -After call to this function preconditioner is changed to P (P is copied -into the internal buffer). - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - -NOTE 2: P should be nonsingular. Exception will be thrown otherwise. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetpreccholesky(const minlbfgsstate &state, const real_2d_array &p, const bool isupper, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgssetpreccholesky(const_cast(state.c_ptr()), const_cast(p.c_ptr()), isupper, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Modification of the preconditioner: diagonal of approximate Hessian is -used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - D - diagonal of the approximate Hessian, array[0..N-1], - (if larger, only leading N elements are used). - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - -NOTE 2: D[i] should be positive. Exception will be thrown otherwise. - -NOTE 3: you should pass diagonal of approximate Hessian - NOT ITS INVERSE. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetprecdiag(const minlbfgsstate &state, const real_1d_array &d, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgssetprecdiag(const_cast(state.c_ptr()), const_cast(d.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Modification of the preconditioner: scale-based diagonal preconditioning. - -This preconditioning mode can be useful when you don't have approximate -diagonal of Hessian, but you know that your variables are badly scaled -(for example, one variable is in [1,10], and another in [1000,100000]), -and most part of the ill-conditioning comes from different scales of vars. - -In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2), -can greatly improve convergence. - -IMPRTANT: you should set scale of your variables with MinLBFGSSetScale() -call (before or after MinLBFGSSetPrecScale() call). Without knowledge of -the scale of your variables scale-based preconditioner will be just unit -matrix. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetprecscale(const minlbfgsstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgssetprecscale(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool minlbfgsiteration(const minlbfgsstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::minlbfgsiteration(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - - -void minlbfgsoptimize(minlbfgsstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'minlbfgsoptimize()' (func is NULL)", &_alglib_env_state); - while( alglib_impl::minlbfgsiteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needf ) - { - func(state.x, state.f, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.x, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minlbfgsoptimize' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - -void minlbfgsoptimize(minlbfgsstate &state, - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(grad!=NULL, "ALGLIB: error in 'minlbfgsoptimize()' (grad is NULL)", &_alglib_env_state); - while( alglib_impl::minlbfgsiteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needfg ) - { - grad(state.x, state.f, state.g, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.x, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minlbfgsoptimize' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - - -/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic gradient. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function at the initial point -(note: future versions may also perform check at the final point) and -compares numerical gradient with analytic one provided by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both gradients and specific components highlighted as -suspicious by the OptGuard. - -The primary OptGuard report can be retrieved with minlbfgsoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with minlbfgssetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsoptguardgradient(const minlbfgsstate &state, const double teststep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgsoptguardgradient(const_cast(state.c_ptr()), teststep, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) -b) nonsmooth target function (non-C1) - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsoptguardsmoothness(const minlbfgsstate &state, const ae_int_t level, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgsoptguardsmoothness(const_cast(state.c_ptr()), level, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) -b) nonsmooth target function (non-C1) - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minlbfgsoptguardsmoothness(const minlbfgsstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t level; - - level = 1; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgsoptguardsmoothness(const_cast(state.c_ptr()), level, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -=== PRIMARY REPORT ======================================================= - -OptGuard performs several checks which are intended to catch common errors -in the implementation of nonlinear function/gradient: -* incorrect analytic gradient -* discontinuous (non-C0) target functions (constraints) -* nonsmooth (non-C1) target functions (constraints) - -Each of these checks is activated with appropriate function: -* minlbfgsoptguardgradient() for gradient verification -* minlbfgsoptguardsmoothness() for C0/C1 checks - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradvidx for specific variable (gradient element) suspected - * rep.badgradxbase, a point where gradient is tested - * rep.badgraduser, user-provided gradient (stored as 2D matrix with - single row in order to make report structure compatible with more - complex optimizers like MinNLC or MinLM) - * rep.badgradnum, reference gradient obtained via numerical - differentiation (stored as 2D matrix with single row in order to make - report structure compatible with more complex optimizers like MinNLC - or MinLM) -* rep.nonc0suspected -* rep.nonc1suspected - -=== ADDITIONAL REPORTS/LOGS ============================================== - -Several different tests are performed to catch C0/C1 errors, you can find -out specific test signaled error by looking to: -* rep.nonc0test0positive, for non-C0 test #0 -* rep.nonc1test0positive, for non-C1 test #0 -* rep.nonc1test1positive, for non-C1 test #1 - -Additional information (including line search logs) can be obtained by -means of: -* minlbfgsoptguardnonc1test0results() -* minlbfgsoptguardnonc1test1results() -which return detailed error reports, specific points where discontinuities -were found, and so on. - -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - generic OptGuard report; more detailed reports can be - retrieved with other functions. - -NOTE: false negatives (nonsmooth problems are not identified as nonsmooth - ones) are possible although unlikely. - - The reason is that you need to make several evaluations around - nonsmoothness in order to accumulate enough information about - function curvature. Say, if you start right from the nonsmooth point, - optimizer simply won't get enough data to understand what is going - wrong before it terminates due to abrupt changes in the derivative. - It is also possible that "unlucky" step will move us to the - termination too quickly. - - Our current approach is to have less than 0.1% false negatives in - our test examples (measured with multiple restarts from random - points), and to have exactly 0% false positives. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsoptguardresults(const minlbfgsstate &state, optguardreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgsoptguardresults(const_cast(state.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #0 - -Nonsmoothness (non-C1) test #0 studies function values (not gradient!) -obtained during line searches and monitors behavior of the directional -derivative estimate. - -This test is less powerful than test #1, but it does not depend on the -gradient values and thus it is more robust against artifacts introduced by -numerical differentiation. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #0 "strong" report - lngrep - C1 test #0 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsoptguardnonc1test0results(const minlbfgsstate &state, optguardnonc1test0report &strrep, optguardnonc1test0report &lngrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgsoptguardnonc1test0results(const_cast(state.c_ptr()), const_cast(strrep.c_ptr()), const_cast(lngrep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #1 - -Nonsmoothness (non-C1) test #1 studies individual components of the -gradient computed during line search. - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #1 "strong" report - lngrep - C1 test #1 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsoptguardnonc1test1results(const minlbfgsstate &state, optguardnonc1test1report &strrep, optguardnonc1test1report &lngrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgsoptguardnonc1test1results(const_cast(state.c_ptr()), const_cast(strrep.c_ptr()), const_cast(lngrep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -L-BFGS algorithm results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report: - * Rep.TerminationType completetion code: - * -8 internal integrity control detected infinite - or NAN values in function/gradient. Abnormal - termination signalled. - * -2 rounding errors prevent further improvement. - X contains best point found. - * -1 incorrect parameters were specified - * 1 relative function improvement is no more than - EpsF. - * 2 relative step is no more than EpsX. - * 4 gradient norm is no more than EpsG - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible - * 8 terminated by user who called minlbfgsrequesttermination(). - X contains point which was "current accepted" when - termination request was submitted. - * Rep.IterationsCount contains iterations count - * NFEV countains number of function calculations - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsresults(const minlbfgsstate &state, real_1d_array &x, minlbfgsreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgsresults(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -L-BFGS algorithm results - -Buffered implementation of MinLBFGSResults which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 20.08.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsresultsbuf(const minlbfgsstate &state, real_1d_array &x, minlbfgsreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgsresultsbuf(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine restarts LBFGS algorithm from new point. All optimization -parameters are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure used to store algorithm state - X - new starting point. - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsrestartfrom(const minlbfgsstate &state, const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgsrestartfrom(const_cast(state.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsrequesttermination(const minlbfgsstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgsrequesttermination(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_LPQPSERV) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_VIPMSOLVER) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_NLCSQP) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_QPDENSEAULSOLVER) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINBLEIC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores nonlinear optimizer state. -You should use functions provided by MinBLEIC subpackage to work with this -object -*************************************************************************/ -_minbleicstate_owner::_minbleicstate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minbleicstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::minbleicstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minbleicstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minbleicstate)); - alglib_impl::_minbleicstate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_minbleicstate_owner::_minbleicstate_owner(const _minbleicstate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minbleicstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minbleicstate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::minbleicstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minbleicstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minbleicstate)); - alglib_impl::_minbleicstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_minbleicstate_owner& _minbleicstate_owner::operator=(const _minbleicstate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minbleicstate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minbleicstate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_minbleicstate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::minbleicstate)); - alglib_impl::_minbleicstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_minbleicstate_owner::~_minbleicstate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_minbleicstate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::minbleicstate* _minbleicstate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::minbleicstate* _minbleicstate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -minbleicstate::minbleicstate() : _minbleicstate_owner() ,needf(p_struct->needf),needfg(p_struct->needfg),xupdated(p_struct->xupdated),f(p_struct->f),g(&p_struct->g),x(&p_struct->x) -{ -} - -minbleicstate::minbleicstate(const minbleicstate &rhs):_minbleicstate_owner(rhs) ,needf(p_struct->needf),needfg(p_struct->needfg),xupdated(p_struct->xupdated),f(p_struct->f),g(&p_struct->g),x(&p_struct->x) -{ -} - -minbleicstate& minbleicstate::operator=(const minbleicstate &rhs) -{ - if( this==&rhs ) - return *this; - _minbleicstate_owner::operator=(rhs); - return *this; -} - -minbleicstate::~minbleicstate() -{ -} - - -/************************************************************************* -This structure stores optimization report: -* IterationsCount number of iterations -* NFEV number of gradient evaluations -* TerminationType termination type (see below) - -TERMINATION CODES - -TerminationType field contains completion code, which can be: - -8 internal integrity control detected infinite or NAN values in - function/gradient. Abnormal termination signalled. - -3 inconsistent constraints. Feasible point is - either nonexistent or too hard to find. Try to - restart optimizer with better initial approximation - 1 relative function improvement is no more than EpsF. - 2 relative step is no more than EpsX. - 4 gradient norm is no more than EpsG - 5 MaxIts steps was taken - 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - 8 terminated by user who called minbleicrequesttermination(). X contains - point which was "current accepted" when termination request was - submitted. - -ADDITIONAL FIELDS - -There are additional fields which can be used for debugging: -* DebugEqErr error in the equality constraints (2-norm) -* DebugFS f, calculated at projection of initial point - to the feasible set -* DebugFF f, calculated at the final point -* DebugDX |X_start-X_final| -*************************************************************************/ -_minbleicreport_owner::_minbleicreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minbleicreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::minbleicreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minbleicreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minbleicreport)); - alglib_impl::_minbleicreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_minbleicreport_owner::_minbleicreport_owner(const _minbleicreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minbleicreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minbleicreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::minbleicreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minbleicreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minbleicreport)); - alglib_impl::_minbleicreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_minbleicreport_owner& _minbleicreport_owner::operator=(const _minbleicreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minbleicreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minbleicreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_minbleicreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::minbleicreport)); - alglib_impl::_minbleicreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_minbleicreport_owner::~_minbleicreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_minbleicreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::minbleicreport* _minbleicreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::minbleicreport* _minbleicreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -minbleicreport::minbleicreport() : _minbleicreport_owner() ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),varidx(p_struct->varidx),terminationtype(p_struct->terminationtype),debugeqerr(p_struct->debugeqerr),debugfs(p_struct->debugfs),debugff(p_struct->debugff),debugdx(p_struct->debugdx),debugfeasqpits(p_struct->debugfeasqpits),debugfeasgpaits(p_struct->debugfeasgpaits),inneriterationscount(p_struct->inneriterationscount),outeriterationscount(p_struct->outeriterationscount) -{ -} - -minbleicreport::minbleicreport(const minbleicreport &rhs):_minbleicreport_owner(rhs) ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),varidx(p_struct->varidx),terminationtype(p_struct->terminationtype),debugeqerr(p_struct->debugeqerr),debugfs(p_struct->debugfs),debugff(p_struct->debugff),debugdx(p_struct->debugdx),debugfeasqpits(p_struct->debugfeasqpits),debugfeasgpaits(p_struct->debugfeasgpaits),inneriterationscount(p_struct->inneriterationscount),outeriterationscount(p_struct->outeriterationscount) -{ -} - -minbleicreport& minbleicreport::operator=(const minbleicreport &rhs) -{ - if( this==&rhs ) - return *this; - _minbleicreport_owner::operator=(rhs); - return *this; -} - -minbleicreport::~minbleicreport() -{ -} - -/************************************************************************* - BOUND CONSTRAINED OPTIMIZATION - WITH ADDITIONAL LINEAR EQUALITY AND INEQUALITY CONSTRAINTS - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments subject to any -combination of: -* bound constraints -* linear inequality constraints -* linear equality constraints - -REQUIREMENTS: -* user must provide function value and gradient -* starting point X0 must be feasible or - not too far away from the feasible set -* grad(f) must be Lipschitz continuous on a level set: - L = { x : f(x)<=f(x0) } -* function must be defined everywhere on the feasible set F - -USAGE: - -Constrained optimization if far more complex than the unconstrained one. -Here we give very brief outline of the BLEIC optimizer. We strongly recommend -you to read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide -on optimization, which is available at http://www.alglib.net/optimization/ - -1. User initializes algorithm state with MinBLEICCreate() call - -2. USer adds boundary and/or linear constraints by calling - MinBLEICSetBC() and MinBLEICSetLC() functions. - -3. User sets stopping conditions with MinBLEICSetCond(). - -4. User calls MinBLEICOptimize() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. - -5. User calls MinBLEICResults() to get solution - -6. Optionally user may call MinBLEICRestartFrom() to solve another problem - with same N but another starting point. - MinBLEICRestartFrom() allows to reuse already initialized structure. - -NOTE: if you have box-only constraints (no general linear constraints), - then MinBC optimizer can be better option. It uses special, faster - constraint activation method, which performs better on problems with - multiple constraints active at the solution. - - On small-scale problems performance of MinBC is similar to that of - MinBLEIC, but on large-scale ones (hundreds and thousands of active - constraints) it can be several times faster than MinBLEIC. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size ofX - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleiccreate(const ae_int_t n, const real_1d_array &x, minbleicstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleiccreate(n, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* - BOUND CONSTRAINED OPTIMIZATION - WITH ADDITIONAL LINEAR EQUALITY AND INEQUALITY CONSTRAINTS - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments subject to any -combination of: -* bound constraints -* linear inequality constraints -* linear equality constraints - -REQUIREMENTS: -* user must provide function value and gradient -* starting point X0 must be feasible or - not too far away from the feasible set -* grad(f) must be Lipschitz continuous on a level set: - L = { x : f(x)<=f(x0) } -* function must be defined everywhere on the feasible set F - -USAGE: - -Constrained optimization if far more complex than the unconstrained one. -Here we give very brief outline of the BLEIC optimizer. We strongly recommend -you to read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide -on optimization, which is available at http://www.alglib.net/optimization/ - -1. User initializes algorithm state with MinBLEICCreate() call - -2. USer adds boundary and/or linear constraints by calling - MinBLEICSetBC() and MinBLEICSetLC() functions. - -3. User sets stopping conditions with MinBLEICSetCond(). - -4. User calls MinBLEICOptimize() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. - -5. User calls MinBLEICResults() to get solution - -6. Optionally user may call MinBLEICRestartFrom() to solve another problem - with same N but another starting point. - MinBLEICRestartFrom() allows to reuse already initialized structure. - -NOTE: if you have box-only constraints (no general linear constraints), - then MinBC optimizer can be better option. It uses special, faster - constraint activation method, which performs better on problems with - multiple constraints active at the solution. - - On small-scale problems performance of MinBC is similar to that of - MinBLEIC, but on large-scale ones (hundreds and thousands of active - constraints) it can be several times faster than MinBLEIC. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size ofX - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minbleiccreate(const real_1d_array &x, minbleicstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleiccreate(n, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -The subroutine is finite difference variant of MinBLEICCreate(). It uses -finite differences in order to differentiate target function. - -Description below contains information which is specific to this function -only. We recommend to read comments on MinBLEICCreate() in order to get -more information about creation of BLEIC optimizer. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[0..N-1]. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinBLEICSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large truncation errors, while too small - step will result in too large numerical errors. 1.0E-6 can be good - value to start with. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. CG needs exact gradient values. Imprecise - gradient may slow down convergence, especially on highly nonlinear - problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -void minbleiccreatef(const ae_int_t n, const real_1d_array &x, const double diffstep, minbleicstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleiccreatef(n, const_cast(x.c_ptr()), diffstep, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -The subroutine is finite difference variant of MinBLEICCreate(). It uses -finite differences in order to differentiate target function. - -Description below contains information which is specific to this function -only. We recommend to read comments on MinBLEICCreate() in order to get -more information about creation of BLEIC optimizer. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[0..N-1]. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinBLEICSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large truncation errors, while too small - step will result in too large numerical errors. 1.0E-6 can be good - value to start with. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. CG needs exact gradient values. Imprecise - gradient may slow down convergence, especially on highly nonlinear - problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minbleiccreatef(const real_1d_array &x, const double diffstep, minbleicstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleiccreatef(n, const_cast(x.c_ptr()), diffstep, const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets boundary constraints for BLEIC optimizer. - -Boundary constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with MinBLEICRestartFrom(). - -NOTE: if you have box-only constraints (no general linear constraints), - then MinBC optimizer can be better option. It uses special, faster - constraint activation method, which performs better on problems with - multiple constraints active at the solution. - - On small-scale problems performance of MinBC is similar to that of - MinBLEIC, but on large-scale ones (hundreds and thousands of active - constraints) it can be several times faster than MinBLEIC. - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF. - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF. - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - -NOTE 2: this solver has following useful properties: -* bound constraints are always satisfied exactly -* function is evaluated only INSIDE area specified by bound constraints, - even when numerical differentiation is used (algorithm adjusts nodes - according to boundary constraints) - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetbc(const minbleicstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicsetbc(const_cast(state.c_ptr()), const_cast(bndl.c_ptr()), const_cast(bndu.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets linear constraints for BLEIC optimizer. - -Linear constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with MinBLEICRestartFrom(). - -INPUT PARAMETERS: - State - structure previously allocated with MinBLEICCreate call. - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -NOTE 1: linear (non-bound) constraints are satisfied only approximately: -* there always exists some minor violation (about Epsilon in magnitude) - due to rounding errors -* numerical differentiation, if used, may lead to function evaluations - outside of the feasible area, because algorithm does NOT change - numerical differentiation formula according to linear constraints. -If you want constraints to be satisfied exactly, try to reformulate your -problem in such manner that all constraints will become boundary ones -(this kind of constraints is always satisfied exactly, both in the final -solution and in all intermediate points). - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetlc(const minbleicstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicsetlc(const_cast(state.c_ptr()), const_cast(c.c_ptr()), const_cast(ct.c_ptr()), k, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets linear constraints for BLEIC optimizer. - -Linear constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with MinBLEICRestartFrom(). - -INPUT PARAMETERS: - State - structure previously allocated with MinBLEICCreate call. - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -NOTE 1: linear (non-bound) constraints are satisfied only approximately: -* there always exists some minor violation (about Epsilon in magnitude) - due to rounding errors -* numerical differentiation, if used, may lead to function evaluations - outside of the feasible area, because algorithm does NOT change - numerical differentiation formula according to linear constraints. -If you want constraints to be satisfied exactly, try to reformulate your -problem in such manner that all constraints will become boundary ones -(this kind of constraints is always satisfied exactly, both in the final -solution and in all intermediate points). - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minbleicsetlc(const minbleicstate &state, const real_2d_array &c, const integer_1d_array &ct, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t k; - if( (c.rows()!=ct.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'minbleicsetlc': looks like one of arguments has wrong size"); - k = c.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicsetlc(const_cast(state.c_ptr()), const_cast(c.c_ptr()), const_cast(ct.c_ptr()), k, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets stopping conditions for the optimizer. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|=0 - The subroutine finishes its work if on k+1-th iteration - the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - is satisfied. - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - step vector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinBLEICSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead -to automatic stopping criterion selection. - -NOTE: when SetCond() called with non-zero MaxIts, BLEIC solver may perform - slightly more than MaxIts iterations. I.e., MaxIts sets non-strict - limit on iterations count. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetcond(const minbleicstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicsetcond(const_cast(state.c_ptr()), epsg, epsf, epsx, maxits, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets scaling coefficients for BLEIC optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of the optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -In most optimizers (and in the BLEIC too) scaling is NOT a form of -preconditioning. It just affects stopping conditions. You should set -preconditioner by separate call to one of the MinBLEICSetPrec...() -functions. - -There is a special preconditioning mode, however, which uses scaling -coefficients to form diagonal preconditioning matrix. You can turn this -mode on, if you want. But you should understand that scaling is not the -same thing as preconditioning - these are two different, although related -forms of tuning solver. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetscale(const minbleicstate &state, const real_1d_array &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicsetscale(const_cast(state.c_ptr()), const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Modification of the preconditioner: preconditioning is turned off. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetprecdefault(const minbleicstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicsetprecdefault(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Modification of the preconditioner: diagonal of approximate Hessian is -used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - D - diagonal of the approximate Hessian, array[0..N-1], - (if larger, only leading N elements are used). - -NOTE 1: D[i] should be positive. Exception will be thrown otherwise. - -NOTE 2: you should pass diagonal of approximate Hessian - NOT ITS INVERSE. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetprecdiag(const minbleicstate &state, const real_1d_array &d, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicsetprecdiag(const_cast(state.c_ptr()), const_cast(d.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Modification of the preconditioner: scale-based diagonal preconditioning. - -This preconditioning mode can be useful when you don't have approximate -diagonal of Hessian, but you know that your variables are badly scaled -(for example, one variable is in [1,10], and another in [1000,100000]), -and most part of the ill-conditioning comes from different scales of vars. - -In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2), -can greatly improve convergence. - -IMPRTANT: you should set scale of your variables with MinBLEICSetScale() -call (before or after MinBLEICSetPrecScale() call). Without knowledge of -the scale of your variables scale-based preconditioner will be just unit -matrix. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetprecscale(const minbleicstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicsetprecscale(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinBLEICOptimize(). - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetxrep(const minbleicstate &state, const bool needxrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicsetxrep(const_cast(state.c_ptr()), needxrep, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets maximum step length - -IMPORTANT: this feature is hard to combine with preconditioning. You can't -set upper limit on step length, when you solve optimization problem with -linear (non-boundary) constraints AND preconditioner turned on. - -When non-boundary constraints are present, you have to either a) use -preconditioner, or b) use upper limit on step length. YOU CAN'T USE BOTH! -In this case algorithm will terminate with appropriate error code. - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which lead to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetstpmax(const minbleicstate &state, const double stpmax, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicsetstpmax(const_cast(state.c_ptr()), stpmax, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool minbleiciteration(const minbleicstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::minbleiciteration(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - - -void minbleicoptimize(minbleicstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'minbleicoptimize()' (func is NULL)", &_alglib_env_state); - while( alglib_impl::minbleiciteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needf ) - { - func(state.x, state.f, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.x, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minbleicoptimize' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - -void minbleicoptimize(minbleicstate &state, - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(grad!=NULL, "ALGLIB: error in 'minbleicoptimize()' (grad is NULL)", &_alglib_env_state); - while( alglib_impl::minbleiciteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needfg ) - { - grad(state.x, state.f, state.g, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.x, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minbleicoptimize' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - - -/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic gradient. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function at the initial point -(note: future versions may also perform check at the final point) and -compares numerical gradient with analytic one provided by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both gradients and specific components highlighted as -suspicious by the OptGuard. - -The primary OptGuard report can be retrieved with minbleicoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with minbleicsetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minbleicoptguardgradient(const minbleicstate &state, const double teststep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicoptguardgradient(const_cast(state.c_ptr()), teststep, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) -b) nonsmooth target function (non-C1) - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbleicoptguardsmoothness(const minbleicstate &state, const ae_int_t level, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicoptguardsmoothness(const_cast(state.c_ptr()), level, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) -b) nonsmooth target function (non-C1) - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minbleicoptguardsmoothness(const minbleicstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t level; - - level = 1; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicoptguardsmoothness(const_cast(state.c_ptr()), level, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -=== PRIMARY REPORT ======================================================= - -OptGuard performs several checks which are intended to catch common errors -in the implementation of nonlinear function/gradient: -* incorrect analytic gradient -* discontinuous (non-C0) target functions (constraints) -* nonsmooth (non-C1) target functions (constraints) - -Each of these checks is activated with appropriate function: -* minbleicoptguardgradient() for gradient verification -* minbleicoptguardsmoothness() for C0/C1 checks - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradvidx for specific variable (gradient element) suspected - * rep.badgradxbase, a point where gradient is tested - * rep.badgraduser, user-provided gradient (stored as 2D matrix with - single row in order to make report structure compatible with more - complex optimizers like MinNLC or MinLM) - * rep.badgradnum, reference gradient obtained via numerical - differentiation (stored as 2D matrix with single row in order to make - report structure compatible with more complex optimizers like MinNLC - or MinLM) -* rep.nonc0suspected -* rep.nonc1suspected - -=== ADDITIONAL REPORTS/LOGS ============================================== - -Several different tests are performed to catch C0/C1 errors, you can find -out specific test signaled error by looking to: -* rep.nonc0test0positive, for non-C0 test #0 -* rep.nonc1test0positive, for non-C1 test #0 -* rep.nonc1test1positive, for non-C1 test #1 - -Additional information (including line search logs) can be obtained by -means of: -* minbleicoptguardnonc1test0results() -* minbleicoptguardnonc1test1results() -which return detailed error reports, specific points where discontinuities -were found, and so on. - -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - generic OptGuard report; more detailed reports can be - retrieved with other functions. - -NOTE: false negatives (nonsmooth problems are not identified as nonsmooth - ones) are possible although unlikely. - - The reason is that you need to make several evaluations around - nonsmoothness in order to accumulate enough information about - function curvature. Say, if you start right from the nonsmooth point, - optimizer simply won't get enough data to understand what is going - wrong before it terminates due to abrupt changes in the derivative. - It is also possible that "unlucky" step will move us to the - termination too quickly. - - Our current approach is to have less than 0.1% false negatives in - our test examples (measured with multiple restarts from random - points), and to have exactly 0% false positives. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbleicoptguardresults(const minbleicstate &state, optguardreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicoptguardresults(const_cast(state.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #0 - -Nonsmoothness (non-C1) test #0 studies function values (not gradient!) -obtained during line searches and monitors behavior of the directional -derivative estimate. - -This test is less powerful than test #1, but it does not depend on the -gradient values and thus it is more robust against artifacts introduced by -numerical differentiation. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #0 "strong" report - lngrep - C1 test #0 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbleicoptguardnonc1test0results(const minbleicstate &state, optguardnonc1test0report &strrep, optguardnonc1test0report &lngrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicoptguardnonc1test0results(const_cast(state.c_ptr()), const_cast(strrep.c_ptr()), const_cast(lngrep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #1 - -Nonsmoothness (non-C1) test #1 studies individual components of the -gradient computed during line search. - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #1 "strong" report - lngrep - C1 test #1 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbleicoptguardnonc1test1results(const minbleicstate &state, optguardnonc1test1report &strrep, optguardnonc1test1report &lngrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicoptguardnonc1test1results(const_cast(state.c_ptr()), const_cast(strrep.c_ptr()), const_cast(lngrep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -BLEIC results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report. You should check Rep.TerminationType - in order to distinguish successful termination from - unsuccessful one: - * -8 internal integrity control detected infinite or - NAN values in function/gradient. Abnormal - termination signalled. - * -3 inconsistent constraints. Feasible point is - either nonexistent or too hard to find. Try to - restart optimizer with better initial approximation - * 1 relative function improvement is no more than EpsF. - * 2 scaled step is no more than EpsX. - * 4 scaled gradient norm is no more than EpsG. - * 5 MaxIts steps was taken - * 8 terminated by user who called minbleicrequesttermination(). - X contains point which was "current accepted" when - termination request was submitted. - More information about fields of this structure can be - found in the comments on MinBLEICReport datatype. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicresults(const minbleicstate &state, real_1d_array &x, minbleicreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicresults(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -BLEIC results - -Buffered implementation of MinBLEICResults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicresultsbuf(const minbleicstate &state, real_1d_array &x, minbleicreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicresultsbuf(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine restarts algorithm from new point. -All optimization parameters (including constraints) are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure previously allocated with MinBLEICCreate call. - X - new starting point. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicrestartfrom(const minbleicstate &state, const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicrestartfrom(const_cast(state.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void minbleicrequesttermination(const minbleicstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicrequesttermination(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_QPBLEICSOLVER) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINQP) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores nonlinear optimizer state. -You should use functions provided by MinQP subpackage to work with this -object -*************************************************************************/ -_minqpstate_owner::_minqpstate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minqpstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::minqpstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minqpstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minqpstate)); - alglib_impl::_minqpstate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_minqpstate_owner::_minqpstate_owner(const _minqpstate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minqpstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minqpstate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::minqpstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minqpstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minqpstate)); - alglib_impl::_minqpstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_minqpstate_owner& _minqpstate_owner::operator=(const _minqpstate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minqpstate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minqpstate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_minqpstate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::minqpstate)); - alglib_impl::_minqpstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_minqpstate_owner::~_minqpstate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_minqpstate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::minqpstate* _minqpstate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::minqpstate* _minqpstate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -minqpstate::minqpstate() : _minqpstate_owner() -{ -} - -minqpstate::minqpstate(const minqpstate &rhs):_minqpstate_owner(rhs) -{ -} - -minqpstate& minqpstate::operator=(const minqpstate &rhs) -{ - if( this==&rhs ) - return *this; - _minqpstate_owner::operator=(rhs); - return *this; -} - -minqpstate::~minqpstate() -{ -} - - -/************************************************************************* -This structure stores optimization report: -* InnerIterationsCount number of inner iterations -* OuterIterationsCount number of outer iterations -* NCholesky number of Cholesky decomposition -* NMV number of matrix-vector products - (only products calculated as part of iterative - process are counted) -* TerminationType completion code (see below) -* LagBC Lagrange multipliers for box constraints, - array[N], not filled by QP-BLEIC solver -* LagLC Lagrange multipliers for linear constraints, - array[MSparse+MDense], ignored by QP-BLEIC solver - -=== COMPLETION CODES ===================================================== - -Completion codes: -* -9 failure of the automatic scale evaluation: one of the diagonal - elements of the quadratic term is non-positive. Specify variable - scales manually! -* -5 inappropriate solver was used: - * QuickQP solver for problem with general linear constraints (dense/sparse) -* -4 BLEIC-QP or QuickQP solver found unconstrained direction - of negative curvature (function is unbounded from - below even under constraints), no meaningful - minimum can be found. -* -3 inconsistent constraints (or, maybe, feasible point is - too hard to find). If you are sure that constraints are feasible, - try to restart optimizer with better initial approximation. -* -2 IPM solver has difficulty finding primal/dual feasible point. - It is likely that the problem is either infeasible or unbounded, - but it is difficult to determine exact reason for termination. - X contains best point found so far. -* 1..4 successful completion -* 5 MaxIts steps was taken -* 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - -=== LAGRANGE MULTIPLIERS ================================================= - -Some optimizers report values of Lagrange multipliers on successful -completion (positive completion code): -* DENSE-IPM-QP and SPARSE-IPM-QP return very precise Lagrange multipliers - as determined during solution process. -* DENSE-AUL-QP returns approximate Lagrange multipliers (which are very - close to "true" Lagrange multipliers except for overconstrained or - degenerate problems) - -Two arrays of multipliers are returned: -* LagBC is array[N] which is loaded with multipliers from box constraints; - LagBC[i]>0 means that I-th constraint is at the upper bound, LagBC[I]<0 - means that I-th constraint is at the lower bound, LagBC[I]=0 means that - I-th box constraint is inactive. -* LagLC is array[MSparse+MDense] which is loaded with multipliers from - general linear constraints (former MSparse elements corresponds to - sparse part of the constraint matrix, latter MDense are for the dense - constraints, as was specified by user). - LagLC[i]>0 means that I-th constraint at the upper bound, LagLC[i]<0 - means that I-th constraint is at the lower bound, LagLC[i]=0 means that - I-th linear constraint is inactive. - -On failure (or when optimizer does not support Lagrange multipliers) these -arrays are zero-filled. - -It is expected that at solution the dual feasibility condition holds: - - C+H*(Xs-X0) + SUM(Ei*LagBC[i],i=0..n-1) + SUM(Ai*LagLC[i],i=0..m-1) ~ 0 - -where -* C is a linear term -* H is a quadratic term -* Xs is a solution, and X0 is an origin term (zero by default) -* Ei is a vector with 1.0 at position I and 0 in other positions -* Ai is an I-th row of linear constraint matrix - -NOTE: methods from IPM family may also return meaningful Lagrange - multipliers on completion with code -2 (infeasibility or - unboundedness detected). -*************************************************************************/ -_minqpreport_owner::_minqpreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minqpreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::minqpreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minqpreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minqpreport)); - alglib_impl::_minqpreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_minqpreport_owner::_minqpreport_owner(const _minqpreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minqpreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minqpreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::minqpreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minqpreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minqpreport)); - alglib_impl::_minqpreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_minqpreport_owner& _minqpreport_owner::operator=(const _minqpreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minqpreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minqpreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_minqpreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::minqpreport)); - alglib_impl::_minqpreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_minqpreport_owner::~_minqpreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_minqpreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::minqpreport* _minqpreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::minqpreport* _minqpreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -minqpreport::minqpreport() : _minqpreport_owner() ,inneriterationscount(p_struct->inneriterationscount),outeriterationscount(p_struct->outeriterationscount),nmv(p_struct->nmv),ncholesky(p_struct->ncholesky),terminationtype(p_struct->terminationtype),lagbc(&p_struct->lagbc),laglc(&p_struct->laglc) -{ -} - -minqpreport::minqpreport(const minqpreport &rhs):_minqpreport_owner(rhs) ,inneriterationscount(p_struct->inneriterationscount),outeriterationscount(p_struct->outeriterationscount),nmv(p_struct->nmv),ncholesky(p_struct->ncholesky),terminationtype(p_struct->terminationtype),lagbc(&p_struct->lagbc),laglc(&p_struct->laglc) -{ -} - -minqpreport& minqpreport::operator=(const minqpreport &rhs) -{ - if( this==&rhs ) - return *this; - _minqpreport_owner::operator=(rhs); - return *this; -} - -minqpreport::~minqpreport() -{ -} - -/************************************************************************* - CONSTRAINED QUADRATIC PROGRAMMING - -The subroutine creates QP optimizer. After initial creation, it contains -default optimization problem with zero quadratic and linear terms and no -constraints. - -In order to actually solve something you should: -* set cost vector with minqpsetlinearterm() -* set variable bounds with minqpsetbc() or minqpsetbcall() -* specify constraint matrix with one of the following functions: - * modern API: - * minqpsetlc2() for sparse two-sided constraints AL <= A*x <= AU - * minqpsetlc2dense() for dense two-sided constraints AL <= A*x <= AU - * minqpsetlc2mixed() for mixed two-sided constraints AL <= A*x <= AU - * minqpaddlc2dense() to add one dense row to dense constraint submatrix - * minqpaddlc2() to add one sparse row to sparse constraint submatrix - * legacy API: - * minqpsetlc() for dense one-sided equality/inequality constraints - * minqpsetlcsparse() for sparse one-sided equality/inequality constraints - * minqpsetlcmixed() for mixed dense/sparse one-sided equality/inequality constraints -* choose appropriate QP solver and set it and its stopping criteria by - means of minqpsetalgo??????() function -* call minqpoptimize() to run the solver and minqpresults() to get the - solution vector and additional information. - -Following solvers are recommended for convex and semidefinite problems: -* QuickQP for dense problems with box-only constraints (or no constraints - at all) -* DENSE-IPM-QP for convex or semidefinite problems with medium (up - to several thousands) variable count, dense/sparse quadratic term and - any number (up to many thousands) of dense/sparse general linear - constraints -* SPARSE-IPM-QP for convex or semidefinite problems with large (many - thousands) variable count, sparse quadratic term AND linear constraints. - -If your problem happens to be nonconvex, but either (a) is effectively -convexified under constraints, or (b) has unique solution even with -nonconvex target, then you can use: -* QuickQP for dense nonconvex problems with box-only constraints -* DENSE-AUL-QP for dense nonconvex problems which are effectively - convexified under constraints with up to several thousands of variables - and any (small or large) number of general linear constraints -* QP-BLEIC for dense/sparse problems with small (up to several hundreds) - number of general linear constraints and arbitrarily large variable - count. - -INPUT PARAMETERS: - N - problem size - -OUTPUT PARAMETERS: - State - optimizer with zero quadratic/linear terms - and no constraints - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpcreate(const ae_int_t n, minqpstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpcreate(n, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets linear term for QP solver. - -By default, linear term is zero. - -INPUT PARAMETERS: - State - structure which stores algorithm state - B - linear term, array[N]. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlinearterm(const minqpstate &state, const real_1d_array &b, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetlinearterm(const_cast(state.c_ptr()), const_cast(b.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets dense quadratic term for QP solver. By default, -quadratic term is zero. - -IMPORTANT: - -This solver minimizes following function: - f(x) = 0.5*x'*A*x + b'*x. -Note that quadratic term has 0.5 before it. So if you want to minimize - f(x) = x^2 + x -you should rewrite your problem as follows: - f(x) = 0.5*(2*x^2) + x -and your matrix A will be equal to [[2.0]], not to [[1.0]] - -INPUT PARAMETERS: - State - structure which stores algorithm state - A - matrix, array[N,N] - IsUpper - (optional) storage type: - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used - * if not given, both lower and upper triangles must be - filled. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetquadraticterm(const minqpstate &state, const real_2d_array &a, const bool isupper, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetquadraticterm(const_cast(state.c_ptr()), const_cast(a.c_ptr()), isupper, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets dense quadratic term for QP solver. By default, -quadratic term is zero. - -IMPORTANT: - -This solver minimizes following function: - f(x) = 0.5*x'*A*x + b'*x. -Note that quadratic term has 0.5 before it. So if you want to minimize - f(x) = x^2 + x -you should rewrite your problem as follows: - f(x) = 0.5*(2*x^2) + x -and your matrix A will be equal to [[2.0]], not to [[1.0]] - -INPUT PARAMETERS: - State - structure which stores algorithm state - A - matrix, array[N,N] - IsUpper - (optional) storage type: - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used - * if not given, both lower and upper triangles must be - filled. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minqpsetquadraticterm(const minqpstate &state, const real_2d_array &a, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - bool isupper; - if( !alglib_impl::ae_is_symmetric(const_cast(a.c_ptr())) ) - _ALGLIB_CPP_EXCEPTION("'a' parameter is not symmetric matrix"); - isupper = false; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetquadraticterm(const_cast(state.c_ptr()), const_cast(a.c_ptr()), isupper, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets sparse quadratic term for QP solver. By default, -quadratic term is zero. This function overrides previous calls to -minqpsetquadraticterm() or minqpsetquadratictermsparse(). - -NOTE: dense solvers like DENSE-AUL-QP or DENSE-IPM-QP will convert this - matrix to dense storage anyway. - -IMPORTANT: - -This solver minimizes following function: - f(x) = 0.5*x'*A*x + b'*x. -Note that quadratic term has 0.5 before it. So if you want to minimize - f(x) = x^2 + x -you should rewrite your problem as follows: - f(x) = 0.5*(2*x^2) + x -and your matrix A will be equal to [[2.0]], not to [[1.0]] - -INPUT PARAMETERS: - State - structure which stores algorithm state - A - matrix, array[N,N] - IsUpper - (optional) storage type: - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used - * if not given, both lower and upper triangles must be - filled. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetquadratictermsparse(const minqpstate &state, const sparsematrix &a, const bool isupper, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetquadratictermsparse(const_cast(state.c_ptr()), const_cast(a.c_ptr()), isupper, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets starting point for QP solver. It is useful to have good -initial approximation to the solution, because it will increase speed of -convergence and identification of active constraints. - -NOTE: interior point solvers ignore initial point provided by user. - -INPUT PARAMETERS: - State - structure which stores algorithm state - X - starting point, array[N]. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetstartingpoint(const minqpstate &state, const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetstartingpoint(const_cast(state.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets origin for QP solver. By default, following QP program -is solved: - - min(0.5*x'*A*x+b'*x) - -This function allows to solve different problem: - - min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin)) - -Specification of non-zero origin affects function being minimized, but not -constraints. Box and linear constraints are still calculated without -origin. - -INPUT PARAMETERS: - State - structure which stores algorithm state - XOrigin - origin, array[N]. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetorigin(const minqpstate &state, const real_1d_array &xorigin, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetorigin(const_cast(state.c_ptr()), const_cast(xorigin.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets scaling coefficients. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances) and as -preconditioner. - -Scale of the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the - function - -If you do not know how to choose scales of your variables, you can: -* read www.alglib.net/optimization/scaling.php article -* use minqpsetscaleautodiag(), which calculates scale using diagonal of - the quadratic term: S is set to 1/sqrt(diag(A)), which works well - sometimes. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetscale(const minqpstate &state, const real_1d_array &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetscale(const_cast(state.c_ptr()), const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets automatic evaluation of variable scaling. - -IMPORTANT: this function works only for matrices with positive diagonal - elements! Zero or negative elements will result in -9 error - code being returned. Specify scale vector manually with - minqpsetscale() in such cases. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances) and as -preconditioner. - -The best way to set scaling is to manually specify variable scales. -However, sometimes you just need quick-and-dirty solution - either when -you perform fast prototyping, or when you know your problem well and you -are 100% sure that this quick solution is robust enough in your case. - -One such solution is to evaluate scale of I-th variable as 1/Sqrt(A[i,i]), -where A[i,i] is an I-th diagonal element of the quadratic term. - -Such approach works well sometimes, but you have to be careful here. - -INPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -void minqpsetscaleautodiag(const minqpstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetscaleautodiag(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function tells solver to use BLEIC-based algorithm and sets stopping -criteria for the algorithm. - -This algorithm is intended for large-scale problems, possibly nonconvex, -with small number of general linear constraints. Feasible initial point is -essential for good performance. - -IMPORTANT: when DENSE-IPM (or DENSE-AUL for nonconvex problems) solvers - are applicable, their performance is much better than that of - BLEIC-QP. - We recommend you to use BLEIC only when other solvers can not - be used. - -ALGORITHM FEATURES: - -* supports dense and sparse QP problems -* supports box and general linear equality/inequality constraints -* can solve all types of problems (convex, semidefinite, nonconvex) as - long as they are bounded from below under constraints. - Say, it is possible to solve "min{-x^2} subject to -1<=x<=+1". - Of course, global minimum is found only for positive definite and - semidefinite problems. As for indefinite ones - only local minimum is - found. - -ALGORITHM OUTLINE: - -* BLEIC-QP solver is just a driver function for MinBLEIC solver; it solves - quadratic programming problem as general linearly constrained - optimization problem, which is solved by means of BLEIC solver (part of - ALGLIB, active set method). - -ALGORITHM LIMITATIONS: -* This algorithm is inefficient on problems with hundreds and thousands - of general inequality constraints and infeasible initial point. Initial - feasibility detection stage may take too long on such constraint sets. - Consider using DENSE-IPM or DENSE-AUL instead. -* unlike QuickQP solver, this algorithm does not perform Newton steps and - does not use Level 3 BLAS. Being general-purpose active set method, it - can activate constraints only one-by-one. Thus, its performance is lower - than that of QuickQP. -* its precision is also a bit inferior to that of QuickQP. BLEIC-QP - performs only LBFGS steps (no Newton steps), which are good at detecting - neighborhood of the solution, buy needs many iterations to find solution - with more than 6 digits of precision. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|=0 - The subroutine finishes its work if exploratory steepest - descent step on k+1-th iteration satisfies following - condition: |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - EpsX - >=0 - The subroutine finishes its work if exploratory steepest - descent step on k+1-th iteration satisfies following - condition: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - step vector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinQPSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. NOTE: this algorithm uses LBFGS - iterations, which are relatively cheap, but improve - function value only a bit. So you will need many iterations - to converge - from 0.1*N to 10*N, depending on problem's - condition number. - -IT IS VERY IMPORTANT TO CALL MinQPSetScale() WHEN YOU USE THIS ALGORITHM -BECAUSE ITS STOPPING CRITERIA ARE SCALE-DEPENDENT! - -Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead -to automatic stopping criterion selection (presently it is small step -length, but it may change in the future versions of ALGLIB). - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetalgobleic(const minqpstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetalgobleic(const_cast(state.c_ptr()), epsg, epsf, epsx, maxits, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function tells QP solver to use DENSE-AUL algorithm and sets stopping -criteria for the algorithm. - -This algorithm is intended for non-convex problems with moderate (up -to several thousands) variable count and arbitrary number of constraints -which are either (a) effectively convexified under constraints or (b) have -unique solution even with nonconvex target. - -IMPORTANT: when DENSE-IPM solver is applicable, its performance is usually - much better than that of DENSE-AUL. - We recommend you to use DENSE-AUL only when other solvers can - not be used. - -ALGORITHM FEATURES: - -* supports box and dense/sparse general linear equality/inequality - constraints -* convergence is theoretically proved for positive-definite (convex) QP - problems. Semidefinite and non-convex problems can be solved as long as - they are bounded from below under constraints, although without - theoretical guarantees. - -ALGORITHM OUTLINE: - -* this algorithm is an augmented Lagrangian method with dense - preconditioner (hence its name). -* it performs several outer iterations in order to refine values of the - Lagrange multipliers. Single outer iteration is a solution of some - unconstrained optimization problem: first it performs dense Cholesky - factorization of the Hessian in order to build preconditioner (adaptive - regularization is applied to enforce positive definiteness), and then - it uses L-BFGS optimizer to solve optimization problem. -* typically you need about 5-10 outer iterations to converge to solution - -ALGORITHM LIMITATIONS: - -* because dense Cholesky driver is used, this algorithm has O(N^2) memory - requirements and O(OuterIterations*N^3) minimum running time. From the - practical point of view, it limits its applicability by several - thousands of variables. - From the other side, variables count is the most limiting factor, - and dependence on constraint count is much more lower. Assuming that - constraint matrix is sparse, it may handle tens of thousands of general - linear constraints. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsX - >=0, stopping criteria for inner optimizer. - Inner iterations are stopped when step length (with - variable scaling being applied) is less than EpsX. - See minqpsetscale() for more information on variable - scaling. - Rho - penalty coefficient, Rho>0: - * large enough that algorithm converges with desired - precision. - * not TOO large to prevent ill-conditioning - * recommended values are 100, 1000 or 10000 - ItsCnt - number of outer iterations: - * recommended values: 10-15 (although in most cases it - converges within 5 iterations, you may need a few more - to be sure). - * ItsCnt=0 means that small number of outer iterations is - automatically chosen (10 iterations in current version). - * ItsCnt=1 means that AUL algorithm performs just as usual - penalty method. - * ItsCnt>1 means that AUL algorithm performs specified - number of outer iterations - -IT IS VERY IMPORTANT TO CALL minqpsetscale() WHEN YOU USE THIS ALGORITHM -BECAUSE ITS CONVERGENCE PROPERTIES AND STOPPING CRITERIA ARE SCALE-DEPENDENT! - -NOTE: Passing EpsX=0 will lead to automatic step length selection - (specific step length chosen may change in the future versions of - ALGLIB, so it is better to specify step length explicitly). - - -- ALGLIB -- - Copyright 20.08.2016 by Bochkanov Sergey -*************************************************************************/ -void minqpsetalgodenseaul(const minqpstate &state, const double epsx, const double rho, const ae_int_t itscnt, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetalgodenseaul(const_cast(state.c_ptr()), epsx, rho, itscnt, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function tells QP solver to use DENSE-IPM QP algorithm and sets -stopping criteria for the algorithm. - -This algorithm is intended for convex and semidefinite problems with -moderate (up to several thousands) variable count and arbitrary number of -constraints. - -IMPORTANT: this algorithm won't work for nonconvex problems, use DENSE-AUL - or BLEIC-QP instead. If you try to run DENSE-IPM on problem - with indefinite matrix (matrix having at least one negative - eigenvalue) then depending on circumstances it may either (a) - stall at some arbitrary point, or (b) throw exception on - failure of Cholesky decomposition. - -ALGORITHM FEATURES: - -* supports box and dense/sparse general linear equality/inequality - constraints - -ALGORITHM OUTLINE: - -* this algorithm is our implementation of interior point method as - formulated by R.J.Vanderbei, with minor modifications to the algorithm - (damped Newton directions are extensively used) -* like all interior point methods, this algorithm tends to converge in - roughly same number of iterations (between 15 and 50) independently from - the problem dimensionality - -ALGORITHM LIMITATIONS: - -* because dense Cholesky driver is used, for N-dimensional problem with - M dense constaints this algorithm has O(N^2+N*M) memory requirements and - O(N^3+N*M^2) running time. - Having sparse constraints with Z nonzeros per row relaxes storage and - running time down to O(N^2+M*Z) and O(N^3+N*Z^2) - From the practical point of view, it limits its applicability by - several thousands of variables. - From the other side, variables count is the most limiting factor, - and dependence on constraint count is much more lower. Assuming that - constraint matrix is sparse, it may handle tens of thousands of general - linear constraints. - -INPUT PARAMETERS: - State - structure which stores algorithm state - Eps - >=0, stopping criteria. The algorithm stops when primal - and dual infeasiblities as well as complementarity gap are - less than Eps. - -IT IS VERY IMPORTANT TO CALL minqpsetscale() WHEN YOU USE THIS ALGORITHM -BECAUSE ITS CONVERGENCE PROPERTIES AND STOPPING CRITERIA ARE SCALE-DEPENDENT! - -NOTE: Passing EpsX=0 will lead to automatic selection of small epsilon. - -===== TRACING IPM SOLVER ================================================= - -IPM solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'IPM' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. -* 'IPM.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'IPM'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("IPM,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void minqpsetalgodenseipm(const minqpstate &state, const double eps, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetalgodenseipm(const_cast(state.c_ptr()), eps, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function tells QP solver to use SPARSE-IPM QP algorithm and sets -stopping criteria for the algorithm. - -This algorithm is intended for convex and semidefinite problems with -large variable and constraint count and sparse quadratic term and -constraints. It is possible to have some limited set of dense linear -constraints - they will be handled separately by dense BLAS - but the more -dense constraints you have, the more time solver needs. - -IMPORTANT: internally this solver performs large and sparse (N+M)x(N+M) - triangular factorization. So it expects both quadratic term and - constraints to be highly sparse. However, its running time is - influenced by BOTH fill factor and sparsity pattern. - - Generally we expect that no more than few nonzero elements per - row are present. However different sparsity patterns may result - in completely different running times even given same fill - factor. - - In many cases this algorithm outperforms DENSE-IPM by order of - magnitude. However, in some cases you may get better results - with DENSE-IPM even when solving sparse task. - -IMPORTANT: this algorithm won't work for nonconvex problems, use DENSE-AUL - or BLEIC-QP instead. If you try to run DENSE-IPM on problem - with indefinite matrix (matrix having at least one negative - eigenvalue) then depending on circumstances it may either (a) - stall at some arbitrary point, or (b) throw exception on - failure of Cholesky decomposition. - -ALGORITHM FEATURES: - -* supports box and dense/sparse general linear equality/inequality - constraints -* specializes on large-scale sparse problems - -ALGORITHM OUTLINE: - -* this algorithm is our implementation of interior point method as - formulated by R.J.Vanderbei, with minor modifications to the algorithm - (damped Newton directions are extensively used) -* like all interior point methods, this algorithm tends to converge in - roughly same number of iterations (between 15 and 50) independently from - the problem dimensionality - -ALGORITHM LIMITATIONS: - -* this algorithm may handle moderate number of dense constraints, usually - no more than a thousand of dense ones without losing its efficiency. - -INPUT PARAMETERS: - State - structure which stores algorithm state - Eps - >=0, stopping criteria. The algorithm stops when primal - and dual infeasiblities as well as complementarity gap are - less than Eps. - -IT IS VERY IMPORTANT TO CALL minqpsetscale() WHEN YOU USE THIS ALGORITHM -BECAUSE ITS CONVERGENCE PROPERTIES AND STOPPING CRITERIA ARE SCALE-DEPENDENT! - -NOTE: Passing EpsX=0 will lead to automatic selection of small epsilon. - -===== TRACING IPM SOLVER ================================================= - -IPM solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'IPM' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. -* 'IPM.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'IPM'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("IPM,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void minqpsetalgosparseipm(const minqpstate &state, const double eps, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetalgosparseipm(const_cast(state.c_ptr()), eps, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function tells solver to use QuickQP algorithm: special extra-fast -algorithm for problems with box-only constrants. It may solve non-convex -problems as long as they are bounded from below under constraints. - -ALGORITHM FEATURES: -* several times faster than DENSE-IPM when running on box-only problem -* utilizes accelerated methods for activation of constraints. -* supports dense and sparse QP problems -* supports ONLY box constraints; general linear constraints are NOT - supported by this solver -* can solve all types of problems (convex, semidefinite, nonconvex) as - long as they are bounded from below under constraints. - Say, it is possible to solve "min{-x^2} subject to -1<=x<=+1". - In convex/semidefinite case global minimum is returned, in nonconvex - case - algorithm returns one of the local minimums. - -ALGORITHM OUTLINE: - -* algorithm performs two kinds of iterations: constrained CG iterations - and constrained Newton iterations -* initially it performs small number of constrained CG iterations, which - can efficiently activate/deactivate multiple constraints -* after CG phase algorithm tries to calculate Cholesky decomposition and - to perform several constrained Newton steps. If Cholesky decomposition - failed (matrix is indefinite even under constraints), we perform more - CG iterations until we converge to such set of constraints that system - matrix becomes positive definite. Constrained Newton steps greatly - increase convergence speed and precision. -* algorithm interleaves CG and Newton iterations which allows to handle - indefinite matrices (CG phase) and quickly converge after final set of - constraints is found (Newton phase). Combination of CG and Newton phases - is called "outer iteration". -* it is possible to turn off Newton phase (beneficial for semidefinite - problems - Cholesky decomposition will fail too often) - -ALGORITHM LIMITATIONS: - -* algorithm does not support general linear constraints; only box ones - are supported -* Cholesky decomposition for sparse problems is performed with Skyline - Cholesky solver, which is intended for low-profile matrices. No profile- - reducing reordering of variables is performed in this version of ALGLIB. -* problems with near-zero negative eigenvalues (or exacty zero ones) may - experience about 2-3x performance penalty. The reason is that Cholesky - decomposition can not be performed until we identify directions of zero - and negative curvature and activate corresponding boundary constraints - - but we need a lot of trial and errors because these directions are hard - to notice in the matrix spectrum. - In this case you may turn off Newton phase of algorithm. - Large negative eigenvalues are not an issue, so highly non-convex - problems can be solved very efficiently. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|=0 - The subroutine finishes its work if exploratory steepest - descent step on k+1-th iteration satisfies following - condition: |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - EpsX - >=0 - The subroutine finishes its work if exploratory steepest - descent step on k+1-th iteration satisfies following - condition: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - step vector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinQPSetScale() - MaxOuterIts-maximum number of OUTER iterations. One outer iteration - includes some amount of CG iterations (from 5 to ~N) and - one or several (usually small amount) Newton steps. Thus, - one outer iteration has high cost, but can greatly reduce - funcation value. - Use 0 if you do not want to limit number of outer iterations. - UseNewton- use Newton phase or not: - * Newton phase improves performance of positive definite - dense problems (about 2 times improvement can be observed) - * can result in some performance penalty on semidefinite - or slightly negative definite problems - each Newton - phase will bring no improvement (Cholesky failure), but - still will require computational time. - * if you doubt, you can turn off this phase - optimizer - will retain its most of its high speed. - -IT IS VERY IMPORTANT TO CALL MinQPSetScale() WHEN YOU USE THIS ALGORITHM -BECAUSE ITS STOPPING CRITERIA ARE SCALE-DEPENDENT! - -Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead -to automatic stopping criterion selection (presently it is small step -length, but it may change in the future versions of ALGLIB). - - -- ALGLIB -- - Copyright 22.05.2014 by Bochkanov Sergey -*************************************************************************/ -void minqpsetalgoquickqp(const minqpstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxouterits, const bool usenewton, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetalgoquickqp(const_cast(state.c_ptr()), epsg, epsf, epsx, maxouterits, usenewton, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets box constraints for QP solver - -Box constraints are inactive by default (after initial creation). After -being set, they are preserved until explicitly overwritten with another -minqpsetbc() or minqpsetbcall() call, or partially overwritten with -minqpsetbci() call. - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd[i] BndL[i]=BndU[i] - lower bound BndL[i]<=x[i] BndU[i]=+INF - upper bound x[i]<=BndU[i] BndL[i]=-INF - range BndL[i]<=x[i]<=BndU[i] ... - free variable - BndL[I]=-INF, BndU[I]+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF (latter is recommended because - it will allow solver to use better algorithm). - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF (latter is recommended because - it will allow solver to use better algorithm). - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: if constraints for all variables are same you may use minqpsetbcall() - which allows to specify constraints without using arrays. - -NOTE: BndL>BndU will result in QP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetbc(const minqpstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetbc(const_cast(state.c_ptr()), const_cast(bndl.c_ptr()), const_cast(bndu.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets box constraints for QP solver (all variables at once, -same constraints for all variables) - -Box constraints are inactive by default (after initial creation). After -being set, they are preserved until explicitly overwritten with another -minqpsetbc() or minqpsetbcall() call, or partially overwritten with -minqpsetbci() call. - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd BndL=BndU - lower bound BndL<=x[i] BndU=+INF - upper bound x[i]<=BndU BndL=-INF - range BndL<=x[i]<=BndU ... - free variable - BndL=-INF, BndU+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bound, same for all variables - BndU - upper bound, same for all variables - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: BndL>BndU will result in QP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetbcall(const minqpstate &state, const double bndl, const double bndu, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetbcall(const_cast(state.c_ptr()), bndl, bndu, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets box constraints for I-th variable (other variables are -not modified). - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd BndL=BndU - lower bound BndL<=x[i] BndU=+INF - upper bound x[i]<=BndU BndL=-INF - range BndL<=x[i]<=BndU ... - free variable - BndL=-INF, BndU+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bound - BndU - upper bound - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: BndL>BndU will result in QP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetbci(const minqpstate &state, const ae_int_t i, const double bndl, const double bndu, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetbci(const_cast(state.c_ptr()), i, bndl, bndu, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets dense linear constraints for QP optimizer. - -This function overrides results of previous calls to minqpsetlc(), -minqpsetlcsparse() and minqpsetlcmixed(). After call to this function -all non-box constraints are dropped, and you have only those constraints -which were specified in the present call. - -If you want to specify mixed (with dense and sparse terms) linear -constraints, you should call minqpsetlcmixed(). - -INPUT PARAMETERS: - State - structure previously allocated with MinQPCreate call. - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -NOTE 1: linear (non-bound) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations (BLEIC-QP solver is most precise, AUL-QP - solver is less precise). - - -- ALGLIB -- - Copyright 19.06.2012 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlc(const minqpstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetlc(const_cast(state.c_ptr()), const_cast(c.c_ptr()), const_cast(ct.c_ptr()), k, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets dense linear constraints for QP optimizer. - -This function overrides results of previous calls to minqpsetlc(), -minqpsetlcsparse() and minqpsetlcmixed(). After call to this function -all non-box constraints are dropped, and you have only those constraints -which were specified in the present call. - -If you want to specify mixed (with dense and sparse terms) linear -constraints, you should call minqpsetlcmixed(). - -INPUT PARAMETERS: - State - structure previously allocated with MinQPCreate call. - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -NOTE 1: linear (non-bound) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations (BLEIC-QP solver is most precise, AUL-QP - solver is less precise). - - -- ALGLIB -- - Copyright 19.06.2012 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minqpsetlc(const minqpstate &state, const real_2d_array &c, const integer_1d_array &ct, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t k; - if( (c.rows()!=ct.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'minqpsetlc': looks like one of arguments has wrong size"); - k = c.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetlc(const_cast(state.c_ptr()), const_cast(c.c_ptr()), const_cast(ct.c_ptr()), k, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets sparse linear constraints for QP optimizer. - -This function overrides results of previous calls to minqpsetlc(), -minqpsetlcsparse() and minqpsetlcmixed(). After call to this function -all non-box constraints are dropped, and you have only those constraints -which were specified in the present call. - -If you want to specify mixed (with dense and sparse terms) linear -constraints, you should call minqpsetlcmixed(). - -INPUT PARAMETERS: - State - structure previously allocated with MinQPCreate call. - C - linear constraints, sparse matrix with dimensions at - least [K,N+1]. If matrix has larger size, only leading - Kx(N+1) rectangle is used. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0 - -NOTE 1: linear (non-bound) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations (BLEIC-QP solver is most precise, AUL-QP - solver is less precise). - - -- ALGLIB -- - Copyright 22.08.2016 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlcsparse(const minqpstate &state, const sparsematrix &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetlcsparse(const_cast(state.c_ptr()), const_cast(c.c_ptr()), const_cast(ct.c_ptr()), k, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets mixed linear constraints, which include a set of dense -rows, and a set of sparse rows. - -This function overrides results of previous calls to minqpsetlc(), -minqpsetlcsparse() and minqpsetlcmixed(). - -This function may be useful if constraint matrix includes large number of -both types of rows - dense and sparse. If you have just a few sparse rows, -you may represent them in dense format without losing performance. -Similarly, if you have just a few dense rows, you may store them in sparse -format with almost same performance. - -INPUT PARAMETERS: - State - structure previously allocated with MinQPCreate call. - SparseC - linear constraints, sparse matrix with dimensions EXACTLY - EQUAL TO [SparseK,N+1]. Each row of C represents one - constraint, either equality or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - SparseCT- type of sparse constraints, array[K]: - * if SparseCT[i]>0, then I-th constraint is SparseC[i,*]*x >= SparseC[i,n+1] - * if SparseCT[i]=0, then I-th constraint is SparseC[i,*]*x = SparseC[i,n+1] - * if SparseCT[i]<0, then I-th constraint is SparseC[i,*]*x <= SparseC[i,n+1] - SparseK - number of sparse equality/inequality constraints, K>=0 - DenseC - dense linear constraints, array[K,N+1]. - Each row of DenseC represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of DenseC (including right part) must be finite. - DenseCT - type of constraints, array[K]: - * if DenseCT[i]>0, then I-th constraint is DenseC[i,*]*x >= DenseC[i,n+1] - * if DenseCT[i]=0, then I-th constraint is DenseC[i,*]*x = DenseC[i,n+1] - * if DenseCT[i]<0, then I-th constraint is DenseC[i,*]*x <= DenseC[i,n+1] - DenseK - number of equality/inequality constraints, DenseK>=0 - -NOTE 1: linear (non-box) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations (BLEIC-QP solver is most precise, AUL-QP - solver is less precise). - -NOTE 2: due to backward compatibility reasons SparseC can be larger than - [SparseK,N+1]. In this case only leading [SparseK,N+1] submatrix - will be used. However, the rest of ALGLIB has more strict - requirements on the input size, so we recommend you to pass sparse - term whose size exactly matches algorithm expectations. - - -- ALGLIB -- - Copyright 22.08.2016 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlcmixed(const minqpstate &state, const sparsematrix &sparsec, const integer_1d_array &sparsect, const ae_int_t sparsek, const real_2d_array &densec, const integer_1d_array &densect, const ae_int_t densek, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetlcmixed(const_cast(state.c_ptr()), const_cast(sparsec.c_ptr()), const_cast(sparsect.c_ptr()), sparsek, const_cast(densec.c_ptr()), const_cast(densect.c_ptr()), densek, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function provides legacy API for specification of mixed dense/sparse -linear constraints. - -New conventions used by ALGLIB since release 3.16.0 state that set of -sparse constraints comes first, followed by set of dense ones. This -convention is essential when you talk about things like order of Lagrange -multipliers. - -However, legacy API accepted mixed constraints in reverse order. This -function is here to simplify situation with code relying on legacy API. It -simply accepts constraints in one order (old) and passes them to new API, -now in correct order. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlcmixedlegacy(const minqpstate &state, const real_2d_array &densec, const integer_1d_array &densect, const ae_int_t densek, const sparsematrix &sparsec, const integer_1d_array &sparsect, const ae_int_t sparsek, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetlcmixedlegacy(const_cast(state.c_ptr()), const_cast(densec.c_ptr()), const_cast(densect.c_ptr()), densek, const_cast(sparsec.c_ptr()), const_cast(sparsect.c_ptr()), sparsek, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU with dense -constraint matrix A. - -NOTE: knowing that constraint matrix is dense helps some QP solvers - (especially modern IPM method) to utilize efficient dense Level 3 - BLAS for dense parts of the problem. If your problem has both dense - and sparse constraints, you can use minqpsetlc2mixed() function, - which will result in dense algebra being applied to dense terms, and - sparse sparse linear algebra applied to sparse terms. - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - A - linear constraints, array[K,N]. Each row of A represents - one constraint. One-sided inequality constraints, two- - sided inequality constraints, equality constraints are - supported (see below) - AL, AU - lower and upper bounds, array[K]; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i] two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0; if not - given, inferred from sizes of A, AL, AU. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlc2dense(const minqpstate &state, const real_2d_array &a, const real_1d_array &al, const real_1d_array &au, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetlc2dense(const_cast(state.c_ptr()), const_cast(a.c_ptr()), const_cast(al.c_ptr()), const_cast(au.c_ptr()), k, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU with dense -constraint matrix A. - -NOTE: knowing that constraint matrix is dense helps some QP solvers - (especially modern IPM method) to utilize efficient dense Level 3 - BLAS for dense parts of the problem. If your problem has both dense - and sparse constraints, you can use minqpsetlc2mixed() function, - which will result in dense algebra being applied to dense terms, and - sparse sparse linear algebra applied to sparse terms. - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - A - linear constraints, array[K,N]. Each row of A represents - one constraint. One-sided inequality constraints, two- - sided inequality constraints, equality constraints are - supported (see below) - AL, AU - lower and upper bounds, array[K]; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i] two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0; if not - given, inferred from sizes of A, AL, AU. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minqpsetlc2dense(const minqpstate &state, const real_2d_array &a, const real_1d_array &al, const real_1d_array &au, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t k; - if( (a.rows()!=al.length()) || (a.rows()!=au.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'minqpsetlc2dense': looks like one of arguments has wrong size"); - k = a.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetlc2dense(const_cast(state.c_ptr()), const_cast(a.c_ptr()), const_cast(al.c_ptr()), const_cast(au.c_ptr()), k, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU with -sparse constraining matrix A. Recommended for large-scale problems. - -This function overwrites linear (non-box) constraints set by previous -calls (if such calls were made). - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - A - sparse matrix with size [K,N] (exactly!). - Each row of A represents one general linear constraint. - A can be stored in any sparse storage format. - AL, AU - lower and upper bounds, array[K]; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i] two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0. If K=0 - is specified, A, AL, AU are ignored. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlc2(const minqpstate &state, const sparsematrix &a, const real_1d_array &al, const real_1d_array &au, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetlc2(const_cast(state.c_ptr()), const_cast(a.c_ptr()), const_cast(al.c_ptr()), const_cast(au.c_ptr()), k, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU with -mixed constraining matrix A including sparse part (first SparseK rows) and -dense part (last DenseK rows). Recommended for large-scale problems. - -This function overwrites linear (non-box) constraints set by previous -calls (if such calls were made). - -This function may be useful if constraint matrix includes large number of -both types of rows - dense and sparse. If you have just a few sparse rows, -you may represent them in dense format without losing performance. -Similarly, if you have just a few dense rows, you may store them in sparse -format with almost same performance. - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - SparseA - sparse matrix with size [K,N] (exactly!). - Each row of A represents one general linear constraint. - A can be stored in any sparse storage format. - SparseK - number of sparse constraints, SparseK>=0 - DenseA - linear constraints, array[K,N], set of dense constraints. - Each row of A represents one general linear constraint. - DenseK - number of dense constraints, DenseK>=0 - AL, AU - lower and upper bounds, array[SparseK+DenseK], with former - SparseK elements corresponding to sparse constraints, and - latter DenseK elements corresponding to dense constraints; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i] two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0. If K=0 - is specified, A, AL, AU are ignored. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlc2mixed(const minqpstate &state, const sparsematrix &sparsea, const ae_int_t ksparse, const real_2d_array &densea, const ae_int_t kdense, const real_1d_array &al, const real_1d_array &au, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpsetlc2mixed(const_cast(state.c_ptr()), const_cast(sparsea.c_ptr()), ksparse, const_cast(densea.c_ptr()), kdense, const_cast(al.c_ptr()), const_cast(au.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function appends two-sided linear constraint AL <= A*x <= AU to the -list of currently present dense constraints. - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - A - linear constraint coefficient, array[N], right side is NOT - included. - AL, AU - lower and upper bounds; - * AL=AU => equality constraint Ai*x - * AL two-sided constraint AL<=A*x<=AU - * AL=-INF => one-sided constraint Ai*x<=AU - * AU=+INF => one-sided constraint AL<=Ai*x - * AL=-INF, AU=+INF => constraint is ignored - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minqpaddlc2dense(const minqpstate &state, const real_1d_array &a, const double al, const double au, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpaddlc2dense(const_cast(state.c_ptr()), const_cast(a.c_ptr()), al, au, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function appends two-sided linear constraint AL <= A*x <= AU to the -list of currently present sparse constraints. - -Constraint is passed in compressed format: as list of non-zero entries of -coefficient vector A. Such approach is more efficient than dense storage -for highly sparse constraint vectors. - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - IdxA - array[NNZ], indexes of non-zero elements of A: - * can be unsorted - * can include duplicate indexes (corresponding entries of - ValA[] will be summed) - ValA - array[NNZ], values of non-zero elements of A - NNZ - number of non-zero coefficients in A - AL, AU - lower and upper bounds; - * AL=AU => equality constraint A*x - * AL two-sided constraint AL<=A*x<=AU - * AL=-INF => one-sided constraint A*x<=AU - * AU=+INF => one-sided constraint AL<=A*x - * AL=-INF, AU=+INF => constraint is ignored - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minqpaddlc2(const minqpstate &state, const integer_1d_array &idxa, const real_1d_array &vala, const ae_int_t nnz, const double al, const double au, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpaddlc2(const_cast(state.c_ptr()), const_cast(idxa.c_ptr()), const_cast(vala.c_ptr()), nnz, al, au, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function solves quadratic programming problem. - -Prior to calling this function you should choose solver by means of one of -the following functions: - -* minqpsetalgoquickqp() - for QuickQP solver -* minqpsetalgobleic() - for BLEIC-QP solver -* minqpsetalgodenseaul() - for Dense-AUL-QP solver -* minqpsetalgodenseipm() - for Dense-IPM-QP solver - -These functions also allow you to control stopping criteria of the solver. -If you did not set solver, MinQP subpackage will automatically select -solver for your problem and will run it with default stopping criteria. - -However, it is better to set explicitly solver and its stopping criteria. - -INPUT PARAMETERS: - State - algorithm state - -You should use MinQPResults() function to access results after calls -to this function. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey. - Special thanks to Elvira Illarionova for important suggestions on - the linearly constrained QP algorithm. -*************************************************************************/ -void minqpoptimize(const minqpstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpoptimize(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -QP solver results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution (on failure - the best point found - so far). - Rep - optimization report, contains: - * completion code in Rep.TerminationType (positive values - denote some kind of success, negative - failures) - * Lagrange multipliers - for QP solvers which support them - * other statistics - See comments on minqpreport structure for more information - -Following completion codes are returned in Rep.TerminationType: -* -9 failure of the automatic scale evaluation: one of the diagonal - elements of the quadratic term is non-positive. Specify variable - scales manually! -* -5 inappropriate solver was used: - * QuickQP solver for problem with general linear constraints -* -4 the function is unbounded from below even under constraints, - no meaningful minimum can be found. -* -3 inconsistent constraints (or, maybe, feasible point is too hard to - find). -* -2 IPM solver has difficulty finding primal/dual feasible point. - It is likely that the problem is either infeasible or unbounded, - but it is difficult to determine exact reason for termination. - X contains best point found so far. -* >0 success -* 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpresults(const minqpstate &state, real_1d_array &x, minqpreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpresults(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -QP results - -Buffered implementation of MinQPResults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpresultsbuf(const minqpstate &state, real_1d_array &x, minqpreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minqpresultsbuf(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_LPQPPRESOLVE) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_REVISEDDUALSIMPLEX) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINLP) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores linear solver state. -You should use functions provided by MinLP subpackage to work with this -object -*************************************************************************/ -_minlpstate_owner::_minlpstate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minlpstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::minlpstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlpstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minlpstate)); - alglib_impl::_minlpstate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_minlpstate_owner::_minlpstate_owner(const _minlpstate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minlpstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlpstate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::minlpstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlpstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minlpstate)); - alglib_impl::_minlpstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_minlpstate_owner& _minlpstate_owner::operator=(const _minlpstate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minlpstate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlpstate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_minlpstate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::minlpstate)); - alglib_impl::_minlpstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_minlpstate_owner::~_minlpstate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_minlpstate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::minlpstate* _minlpstate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::minlpstate* _minlpstate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -minlpstate::minlpstate() : _minlpstate_owner() -{ -} - -minlpstate::minlpstate(const minlpstate &rhs):_minlpstate_owner(rhs) -{ -} - -minlpstate& minlpstate::operator=(const minlpstate &rhs) -{ - if( this==&rhs ) - return *this; - _minlpstate_owner::operator=(rhs); - return *this; -} - -minlpstate::~minlpstate() -{ -} - - -/************************************************************************* -This structure stores optimization report: -* f target function value -* lagbc Lagrange coefficients for box constraints -* laglc Lagrange coefficients for linear constraints -* y dual variables -* stats array[N+M], statuses of box (N) and linear (M) - constraints. This array is filled only by DSS - algorithm because IPM always stops at INTERIOR - point: - * stats[i]>0 => constraint at upper bound - (also used for free non-basic - variables set to zero) - * stats[i]<0 => constraint at lower bound - * stats[i]=0 => constraint is inactive, basic - variable -* primalerror primal feasibility error -* dualerror dual feasibility error -* slackerror complementary slackness error -* iterationscount iteration count -* terminationtype completion code (see below) - -COMPLETION CODES - -Completion codes: -* -4 LP problem is primal unbounded (dual infeasible) -* -3 LP problem is primal infeasible (dual unbounded) -* 1..4 successful completion -* 5 MaxIts steps was taken -* 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - -LAGRANGE COEFFICIENTS - -Positive Lagrange coefficient means that constraint is at its upper bound. -Negative coefficient means that constraint is at its lower bound. It is -expected that at solution the dual feasibility condition holds: - - C + SUM(Ei*LagBC[i],i=0..n-1) + SUM(Ai*LagLC[i],i=0..m-1) ~ 0 - -where -* C is a cost vector (linear term) -* Ei is a vector with 1.0 at position I and 0 in other positions -* Ai is an I-th row of linear constraint matrix -*************************************************************************/ -_minlpreport_owner::_minlpreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minlpreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::minlpreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlpreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minlpreport)); - alglib_impl::_minlpreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_minlpreport_owner::_minlpreport_owner(const _minlpreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minlpreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlpreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::minlpreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlpreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minlpreport)); - alglib_impl::_minlpreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_minlpreport_owner& _minlpreport_owner::operator=(const _minlpreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minlpreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlpreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_minlpreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::minlpreport)); - alglib_impl::_minlpreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_minlpreport_owner::~_minlpreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_minlpreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::minlpreport* _minlpreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::minlpreport* _minlpreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -minlpreport::minlpreport() : _minlpreport_owner() ,f(p_struct->f),lagbc(&p_struct->lagbc),laglc(&p_struct->laglc),y(&p_struct->y),stats(&p_struct->stats),primalerror(p_struct->primalerror),dualerror(p_struct->dualerror),slackerror(p_struct->slackerror),iterationscount(p_struct->iterationscount),terminationtype(p_struct->terminationtype) -{ -} - -minlpreport::minlpreport(const minlpreport &rhs):_minlpreport_owner(rhs) ,f(p_struct->f),lagbc(&p_struct->lagbc),laglc(&p_struct->laglc),y(&p_struct->y),stats(&p_struct->stats),primalerror(p_struct->primalerror),dualerror(p_struct->dualerror),slackerror(p_struct->slackerror),iterationscount(p_struct->iterationscount),terminationtype(p_struct->terminationtype) -{ -} - -minlpreport& minlpreport::operator=(const minlpreport &rhs) -{ - if( this==&rhs ) - return *this; - _minlpreport_owner::operator=(rhs); - return *this; -} - -minlpreport::~minlpreport() -{ -} - -/************************************************************************* - LINEAR PROGRAMMING - -The subroutine creates LP solver. After initial creation it contains -default optimization problem with zero cost vector and all variables being -fixed to zero values and no constraints. - -In order to actually solve something you should: -* set cost vector with minlpsetcost() -* set variable bounds with minlpsetbc() or minlpsetbcall() -* specify constraint matrix with one of the following functions: - [*] minlpsetlc() for dense one-sided constraints - [*] minlpsetlc2dense() for dense two-sided constraints - [*] minlpsetlc2() for sparse two-sided constraints - [*] minlpaddlc2dense() to add one dense row to constraint matrix - [*] minlpaddlc2() to add one row to constraint matrix (compressed format) -* call minlpoptimize() to run the solver and minlpresults() to get the - solution vector and additional information. - -By default, LP solver uses best algorithm available. As of ALGLIB 3.17, -sparse interior point (barrier) solver is used. Future releases of ALGLIB -may introduce other solvers. - -User may choose specific LP algorithm by calling: -* minlpsetalgodss() for revised dual simplex method with DSE pricing and - bounds flipping ratio test (aka long dual step). Large-scale sparse LU - solverwith Forest-Tomlin update is used internally as linear algebra - driver. -* minlpsetalgoipm() for sparse interior point method - -INPUT PARAMETERS: - N - problem size - -OUTPUT PARAMETERS: - State - optimizer in the default state - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpcreate(const ae_int_t n, minlpstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlpcreate(n, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets LP algorithm to revised dual simplex method. - -ALGLIB implementation of dual simplex method supports advanced performance -and stability improvements like DSE pricing , bounds flipping ratio test -(aka long dual step), Forest-Tomlin update, shifting. - -INPUT PARAMETERS: - State - optimizer - Eps - stopping condition, Eps>=0: - * should be small number about 1E-6 or 1E-7. - * zero value means that solver automatically selects good - value (can be different in different ALGLIB versions) - * default value is zero - Algorithm stops when relative error is less than Eps. - -===== TRACING DSS SOLVER ================================================= - -DSS solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'DSS' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. -* 'DSS.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'DSS'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("DSS,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 08.11.2020 by Bochkanov Sergey -*************************************************************************/ -void minlpsetalgodss(const minlpstate &state, const double eps, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlpsetalgodss(const_cast(state.c_ptr()), eps, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets LP algorithm to sparse interior point method. - -ALGORITHM INFORMATION: - -* this algorithm is our implementation of interior point method as - formulated by R.J.Vanderbei, with minor modifications to the algorithm - (damped Newton directions are extensively used) -* like all interior point methods, this algorithm tends to converge in - roughly same number of iterations (between 15 and 50) independently from - the problem dimensionality - -INPUT PARAMETERS: - State - optimizer - Eps - stopping condition, Eps>=0: - * should be small number about 1E-7 or 1E-8. - * zero value means that solver automatically selects good - value (can be different in different ALGLIB versions) - * default value is zero - Algorithm stops when primal error AND dual error AND - duality gap are less than Eps. - -===== TRACING IPM SOLVER ================================================= - -IPM solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'IPM' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. -* 'IPM.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'IPM'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("IPM,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 08.11.2020 by Bochkanov Sergey -*************************************************************************/ -void minlpsetalgoipm(const minlpstate &state, const double eps, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlpsetalgoipm(const_cast(state.c_ptr()), eps, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets LP algorithm to sparse interior point method. - -ALGORITHM INFORMATION: - -* this algorithm is our implementation of interior point method as - formulated by R.J.Vanderbei, with minor modifications to the algorithm - (damped Newton directions are extensively used) -* like all interior point methods, this algorithm tends to converge in - roughly same number of iterations (between 15 and 50) independently from - the problem dimensionality - -INPUT PARAMETERS: - State - optimizer - Eps - stopping condition, Eps>=0: - * should be small number about 1E-7 or 1E-8. - * zero value means that solver automatically selects good - value (can be different in different ALGLIB versions) - * default value is zero - Algorithm stops when primal error AND dual error AND - duality gap are less than Eps. - -===== TRACING IPM SOLVER ================================================= - -IPM solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'IPM' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. -* 'IPM.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'IPM'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("IPM,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 08.11.2020 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minlpsetalgoipm(const minlpstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - double eps; - - eps = 0; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlpsetalgoipm(const_cast(state.c_ptr()), eps, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets cost term for LP solver. - -By default, cost term is zero. - -INPUT PARAMETERS: - State - structure which stores algorithm state - C - cost term, array[N]. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetcost(const minlpstate &state, const real_1d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlpsetcost(const_cast(state.c_ptr()), const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets scaling coefficients. - -ALGLIB optimizers use scaling matrices to test stopping conditions and as -preconditioner. - -Scale of the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the - function - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetscale(const minlpstate &state, const real_1d_array &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlpsetscale(const_cast(state.c_ptr()), const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets box constraints for LP solver (all variables at once, -different constraints for different variables). - -The default state of constraints is to have all variables fixed at zero. -You have to overwrite it by your own constraint vector. Constraint status -is preserved until constraints are explicitly overwritten with another -minlpsetbc() call, overwritten with minlpsetbcall(), or partially -overwritten with minlmsetbci() call. - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd[i] BndL[i]=BndU[i] - lower bound BndL[i]<=x[i] BndU[i]=+INF - upper bound x[i]<=BndU[i] BndL[i]=-INF - range BndL[i]<=x[i]<=BndU[i] ... - free variable - BndL[I]=-INF, BndU[I]+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - BndU - upper bounds, array[N]. - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: if constraints for all variables are same you may use minlpsetbcall() - which allows to specify constraints without using arrays. - -NOTE: BndL>BndU will result in LP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetbc(const minlpstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlpsetbc(const_cast(state.c_ptr()), const_cast(bndl.c_ptr()), const_cast(bndu.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets box constraints for LP solver (all variables at once, -same constraints for all variables) - -The default state of constraints is to have all variables fixed at zero. -You have to overwrite it by your own constraint vector. Constraint status -is preserved until constraints are explicitly overwritten with another -minlpsetbc() call or partially overwritten with minlpsetbcall(). - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd[i] BndL[i]=BndU[i] - lower bound BndL[i]<=x[i] BndU[i]=+INF - upper bound x[i]<=BndU[i] BndL[i]=-INF - range BndL[i]<=x[i]<=BndU[i] ... - free variable - BndL[I]=-INF, BndU[I]+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bound, same for all variables - BndU - upper bound, same for all variables - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: minlpsetbc() can be used to specify different constraints for - different variables. - -NOTE: BndL>BndU will result in LP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetbcall(const minlpstate &state, const double bndl, const double bndu, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlpsetbcall(const_cast(state.c_ptr()), bndl, bndu, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets box constraints for I-th variable (other variables are -not modified). - -The default state of constraints is to have all variables fixed at zero. -You have to overwrite it by your own constraint vector. - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd[i] BndL[i]=BndU[i] - lower bound BndL[i]<=x[i] BndU[i]=+INF - upper bound x[i]<=BndU[i] BndL[i]=-INF - range BndL[i]<=x[i]<=BndU[i] ... - free variable - BndL[I]=-INF, BndU[I]+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - I - variable index, in [0,N) - BndL - lower bound for I-th variable - BndU - upper bound for I-th variable - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: minlpsetbc() can be used to specify different constraints for - different variables. - -NOTE: BndL>BndU will result in LP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetbci(const minlpstate &state, const ae_int_t i, const double bndl, const double bndu, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlpsetbci(const_cast(state.c_ptr()), i, bndl, bndu, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets one-sided linear constraints A*x ~ AU, where "~" can be -a mix of "<=", "=" and ">=". - -IMPORTANT: this function is provided here for compatibility with the rest - of ALGLIB optimizers which accept constraints in format like - this one. Many real-life problems feature two-sided constraints - like a0 <= a*x <= a1. It is really inefficient to add them as a - pair of one-sided constraints. - - Use minlpsetlc2dense(), minlpsetlc2(), minlpaddlc2() (or its - sparse version) wherever possible. - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - A - linear constraints, array[K,N+1]. Each row of A represents - one constraint, with first N elements being linear coefficients, - and last element being right side. - CT - constraint types, array[K]: - * if CT[i]>0, then I-th constraint is A[i,*]*x >= A[i,n] - * if CT[i]=0, then I-th constraint is A[i,*]*x = A[i,n] - * if CT[i]<0, then I-th constraint is A[i,*]*x <= A[i,n] - K - number of equality/inequality constraints, K>=0; if not - given, inferred from sizes of A and CT. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetlc(const minlpstate &state, const real_2d_array &a, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlpsetlc(const_cast(state.c_ptr()), const_cast(a.c_ptr()), const_cast(ct.c_ptr()), k, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets one-sided linear constraints A*x ~ AU, where "~" can be -a mix of "<=", "=" and ">=". - -IMPORTANT: this function is provided here for compatibility with the rest - of ALGLIB optimizers which accept constraints in format like - this one. Many real-life problems feature two-sided constraints - like a0 <= a*x <= a1. It is really inefficient to add them as a - pair of one-sided constraints. - - Use minlpsetlc2dense(), minlpsetlc2(), minlpaddlc2() (or its - sparse version) wherever possible. - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - A - linear constraints, array[K,N+1]. Each row of A represents - one constraint, with first N elements being linear coefficients, - and last element being right side. - CT - constraint types, array[K]: - * if CT[i]>0, then I-th constraint is A[i,*]*x >= A[i,n] - * if CT[i]=0, then I-th constraint is A[i,*]*x = A[i,n] - * if CT[i]<0, then I-th constraint is A[i,*]*x <= A[i,n] - K - number of equality/inequality constraints, K>=0; if not - given, inferred from sizes of A and CT. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minlpsetlc(const minlpstate &state, const real_2d_array &a, const integer_1d_array &ct, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t k; - if( (a.rows()!=ct.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'minlpsetlc': looks like one of arguments has wrong size"); - k = a.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlpsetlc(const_cast(state.c_ptr()), const_cast(a.c_ptr()), const_cast(ct.c_ptr()), k, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU. - -This version accepts dense matrix as input; internally LP solver uses -sparse storage anyway (most LP problems are sparse), but for your -convenience it may accept dense inputs. This function overwrites linear -constraints set by previous calls (if such calls were made). - -We recommend you to use sparse version of this function unless you solve -small-scale LP problem (less than few hundreds of variables). - -NOTE: there also exist several versions of this function: - * one-sided dense version which accepts constraints in the same - format as one used by QP and NLP solvers - * two-sided sparse version which accepts sparse matrix - * two-sided dense version which allows you to add constraints row by row - * two-sided sparse version which allows you to add constraints row by row - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - A - linear constraints, array[K,N]. Each row of A represents - one constraint. One-sided inequality constraints, two- - sided inequality constraints, equality constraints are - supported (see below) - AL, AU - lower and upper bounds, array[K]; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i] two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0; if not - given, inferred from sizes of A, AL, AU. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetlc2dense(const minlpstate &state, const real_2d_array &a, const real_1d_array &al, const real_1d_array &au, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlpsetlc2dense(const_cast(state.c_ptr()), const_cast(a.c_ptr()), const_cast(al.c_ptr()), const_cast(au.c_ptr()), k, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU. - -This version accepts dense matrix as input; internally LP solver uses -sparse storage anyway (most LP problems are sparse), but for your -convenience it may accept dense inputs. This function overwrites linear -constraints set by previous calls (if such calls were made). - -We recommend you to use sparse version of this function unless you solve -small-scale LP problem (less than few hundreds of variables). - -NOTE: there also exist several versions of this function: - * one-sided dense version which accepts constraints in the same - format as one used by QP and NLP solvers - * two-sided sparse version which accepts sparse matrix - * two-sided dense version which allows you to add constraints row by row - * two-sided sparse version which allows you to add constraints row by row - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - A - linear constraints, array[K,N]. Each row of A represents - one constraint. One-sided inequality constraints, two- - sided inequality constraints, equality constraints are - supported (see below) - AL, AU - lower and upper bounds, array[K]; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i] two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0; if not - given, inferred from sizes of A, AL, AU. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minlpsetlc2dense(const minlpstate &state, const real_2d_array &a, const real_1d_array &al, const real_1d_array &au, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t k; - if( (a.rows()!=al.length()) || (a.rows()!=au.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'minlpsetlc2dense': looks like one of arguments has wrong size"); - k = a.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlpsetlc2dense(const_cast(state.c_ptr()), const_cast(a.c_ptr()), const_cast(al.c_ptr()), const_cast(au.c_ptr()), k, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU with -sparse constraining matrix A. Recommended for large-scale problems. - -This function overwrites linear (non-box) constraints set by previous -calls (if such calls were made). - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - A - sparse matrix with size [K,N] (exactly!). - Each row of A represents one general linear constraint. - A can be stored in any sparse storage format. - AL, AU - lower and upper bounds, array[K]; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i] two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0. If K=0 - is specified, A, AL, AU are ignored. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetlc2(const minlpstate &state, const sparsematrix &a, const real_1d_array &al, const real_1d_array &au, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlpsetlc2(const_cast(state.c_ptr()), const_cast(a.c_ptr()), const_cast(al.c_ptr()), const_cast(au.c_ptr()), k, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function appends two-sided linear constraint AL <= A*x <= AU to the -list of currently present constraints. - -This version accepts dense constraint vector as input, but sparsifies it -for internal storage and processing. Thus, time to add one constraint in -is O(N) - we have to scan entire array of length N. Sparse version of this -function is order of magnitude faster for constraints with just a few -nonzeros per row. - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - A - linear constraint coefficient, array[N], right side is NOT - included. - AL, AU - lower and upper bounds; - * AL=AU => equality constraint Ai*x - * AL two-sided constraint AL<=A*x<=AU - * AL=-INF => one-sided constraint Ai*x<=AU - * AU=+INF => one-sided constraint AL<=Ai*x - * AL=-INF, AU=+INF => constraint is ignored - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpaddlc2dense(const minlpstate &state, const real_1d_array &a, const double al, const double au, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlpaddlc2dense(const_cast(state.c_ptr()), const_cast(a.c_ptr()), al, au, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function appends two-sided linear constraint AL <= A*x <= AU to the -list of currently present constraints. - -Constraint is passed in compressed format: as list of non-zero entries of -coefficient vector A. Such approach is more efficient than dense storage -for highly sparse constraint vectors. - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - IdxA - array[NNZ], indexes of non-zero elements of A: - * can be unsorted - * can include duplicate indexes (corresponding entries of - ValA[] will be summed) - ValA - array[NNZ], values of non-zero elements of A - NNZ - number of non-zero coefficients in A - AL, AU - lower and upper bounds; - * AL=AU => equality constraint A*x - * AL two-sided constraint AL<=A*x<=AU - * AL=-INF => one-sided constraint A*x<=AU - * AU=+INF => one-sided constraint AL<=A*x - * AL=-INF, AU=+INF => constraint is ignored - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpaddlc2(const minlpstate &state, const integer_1d_array &idxa, const real_1d_array &vala, const ae_int_t nnz, const double al, const double au, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlpaddlc2(const_cast(state.c_ptr()), const_cast(idxa.c_ptr()), const_cast(vala.c_ptr()), nnz, al, au, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function solves LP problem. - -INPUT PARAMETERS: - State - algorithm state - -You should use minlpresults() function to access results after calls to -this function. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey. -*************************************************************************/ -void minlpoptimize(const minlpstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlpoptimize(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -LP solver results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[N], solution (on failure: last trial point) - Rep - optimization report. You should check Rep.TerminationType, - which contains completion code, and you may check another - fields which contain another information about algorithm - functioning. - - Failure codes returned by algorithm are: - * -4 LP problem is primal unbounded (dual infeasible) - * -3 LP problem is primal infeasible (dual unbounded) - * -2 IPM solver detected that problem is either - infeasible or unbounded - - Success codes: - * 1..4 successful completion - * 5 MaxIts steps was taken - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minlpresults(const minlpstate &state, real_1d_array &x, minlpreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlpresults(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -LP results - -Buffered implementation of MinLPResults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minlpresultsbuf(const minlpstate &state, real_1d_array &x, minlpreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlpresultsbuf(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_NLCSLP) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINNLC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores nonlinear optimizer state. -You should use functions provided by MinNLC subpackage to work with this -object -*************************************************************************/ -_minnlcstate_owner::_minnlcstate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minnlcstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::minnlcstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minnlcstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minnlcstate)); - alglib_impl::_minnlcstate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_minnlcstate_owner::_minnlcstate_owner(const _minnlcstate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minnlcstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minnlcstate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::minnlcstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minnlcstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minnlcstate)); - alglib_impl::_minnlcstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_minnlcstate_owner& _minnlcstate_owner::operator=(const _minnlcstate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minnlcstate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minnlcstate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_minnlcstate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::minnlcstate)); - alglib_impl::_minnlcstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_minnlcstate_owner::~_minnlcstate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_minnlcstate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::minnlcstate* _minnlcstate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::minnlcstate* _minnlcstate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -minnlcstate::minnlcstate() : _minnlcstate_owner() ,needfi(p_struct->needfi),needfij(p_struct->needfij),xupdated(p_struct->xupdated),f(p_struct->f),fi(&p_struct->fi),j(&p_struct->j),x(&p_struct->x) -{ -} - -minnlcstate::minnlcstate(const minnlcstate &rhs):_minnlcstate_owner(rhs) ,needfi(p_struct->needfi),needfij(p_struct->needfij),xupdated(p_struct->xupdated),f(p_struct->f),fi(&p_struct->fi),j(&p_struct->j),x(&p_struct->x) -{ -} - -minnlcstate& minnlcstate::operator=(const minnlcstate &rhs) -{ - if( this==&rhs ) - return *this; - _minnlcstate_owner::operator=(rhs); - return *this; -} - -minnlcstate::~minnlcstate() -{ -} - - -/************************************************************************* -These fields store optimization report: -* iterationscount total number of inner iterations -* nfev number of gradient evaluations -* terminationtype termination type (see below) - -Scaled constraint violations are reported: -* bcerr maximum violation of the box constraints -* bcidx index of the most violated box constraint (or - -1, if all box constraints are satisfied or - there is no box constraint) -* lcerr maximum violation of the linear constraints, - computed as maximum scaled distance between - final point and constraint boundary. -* lcidx index of the most violated linear constraint - (or -1, if all constraints are satisfied or - there is no general linear constraints) -* nlcerr maximum violation of the nonlinear constraints -* nlcidx index of the most violated nonlinear constraint - (or -1, if all constraints are satisfied or - there is no nonlinear constraints) - -Violations of box constraints are scaled on per-component basis according -to the scale vector s[] as specified by minnlcsetscale(). Violations of -the general linear constraints are also computed using user-supplied -variable scaling. Violations of nonlinear constraints are computed "as is" - -TERMINATION CODES - -TerminationType field contains completion code, which can be either: - -=== FAILURE CODE === - -8 internal integrity control detected infinite or NAN values in - function/gradient. Abnormal termination signaled. - -3 box constraints are infeasible. Note: infeasibility of non-box - constraints does NOT trigger emergency completion; you have to - examine bcerr/lcerr/nlcerr to detect possibly inconsistent - constraints. - -=== SUCCESS CODE === - 2 relative step is no more than EpsX. - 5 MaxIts steps was taken - 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - 8 user requested algorithm termination via minnlcrequesttermination(), - last accepted point is returned - -Other fields of this structure are not documented and should not be used! -*************************************************************************/ -_minnlcreport_owner::_minnlcreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minnlcreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::minnlcreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minnlcreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minnlcreport)); - alglib_impl::_minnlcreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_minnlcreport_owner::_minnlcreport_owner(const _minnlcreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minnlcreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minnlcreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::minnlcreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minnlcreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minnlcreport)); - alglib_impl::_minnlcreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_minnlcreport_owner& _minnlcreport_owner::operator=(const _minnlcreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minnlcreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minnlcreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_minnlcreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::minnlcreport)); - alglib_impl::_minnlcreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_minnlcreport_owner::~_minnlcreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_minnlcreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::minnlcreport* _minnlcreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::minnlcreport* _minnlcreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -minnlcreport::minnlcreport() : _minnlcreport_owner() ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),terminationtype(p_struct->terminationtype),bcerr(p_struct->bcerr),bcidx(p_struct->bcidx),lcerr(p_struct->lcerr),lcidx(p_struct->lcidx),nlcerr(p_struct->nlcerr),nlcidx(p_struct->nlcidx),dbgphase0its(p_struct->dbgphase0its) -{ -} - -minnlcreport::minnlcreport(const minnlcreport &rhs):_minnlcreport_owner(rhs) ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),terminationtype(p_struct->terminationtype),bcerr(p_struct->bcerr),bcidx(p_struct->bcidx),lcerr(p_struct->lcerr),lcidx(p_struct->lcidx),nlcerr(p_struct->nlcerr),nlcidx(p_struct->nlcidx),dbgphase0its(p_struct->dbgphase0its) -{ -} - -minnlcreport& minnlcreport::operator=(const minnlcreport &rhs) -{ - if( this==&rhs ) - return *this; - _minnlcreport_owner::operator=(rhs); - return *this; -} - -minnlcreport::~minnlcreport() -{ -} - -/************************************************************************* - NONLINEARLY CONSTRAINED OPTIMIZATION - WITH PRECONDITIONED AUGMENTED LAGRANGIAN ALGORITHM - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments subject to any -combination of: -* bound constraints -* linear inequality constraints -* linear equality constraints -* nonlinear equality constraints Gi(x)=0 -* nonlinear inequality constraints Hi(x)<=0 - -REQUIREMENTS: -* user must provide function value and gradient for F(), H(), G() -* starting point X0 must be feasible or not too far away from the feasible - set -* F(), G(), H() are continuously differentiable on the feasible set and - its neighborhood -* nonlinear constraints G() and H() must have non-zero gradient at G(x)=0 - and at H(x)=0. Say, constraint like x^2>=1 is supported, but x^2>=0 is - NOT supported. - -USAGE: - -Constrained optimization if far more complex than the unconstrained one. -Nonlinearly constrained optimization is one of the most esoteric numerical -procedures. - -Here we give very brief outline of the MinNLC optimizer. We strongly -recommend you to study examples in the ALGLIB Reference Manual and to read -ALGLIB User Guide on optimization, which is available at -http://www.alglib.net/optimization/ - -1. User initializes algorithm state with MinNLCCreate() call and chooses - what NLC solver to use. There is some solver which is used by default, - with default settings, but you should NOT rely on default choice. It - may change in future releases of ALGLIB without notice, and no one can - guarantee that new solver will be able to solve your problem with - default settings. - - From the other side, if you choose solver explicitly, you can be pretty - sure that it will work with new ALGLIB releases. - - In the current release following solvers can be used: - * SQP solver, recommended for medium-scale problems (less than thousand - of variables) with hard-to-evaluate target functions. Requires less - function evaluations than other solvers but each step involves - solution of QP subproblem, so running time may be higher than that of - AUL (another recommended option). Activated with minnlcsetalgosqp() - function. - * AUL solver with dense preconditioner, recommended for large-scale - problems or for problems with cheap target function. Needs more - function evaluations that SQP (about 5x-10x times more), but its - iterations are much cheaper that that of SQP. Activated with - minnlcsetalgoaul() function. - * SLP solver, successive linear programming. The slowest one, requires - more target function evaluations that SQP and AUL. However, it is - somewhat more robust in tricky cases, so it can be used as a backup - plan. Activated with minnlcsetalgoslp() function. - -2. [optional] user activates OptGuard integrity checker which tries to - detect possible errors in the user-supplied callbacks: - * discontinuity/nonsmoothness of the target/nonlinear constraints - * errors in the analytic gradient provided by user - This feature is essential for early prototyping stages because it helps - to catch common coding and problem statement errors. - OptGuard can be activated with following functions (one per each check - performed): - * minnlcoptguardsmoothness() - * minnlcoptguardgradient() - -3. User adds boundary and/or linear and/or nonlinear constraints by means - of calling one of the following functions: - a) minnlcsetbc() for boundary constraints - b) minnlcsetlc() for linear constraints - c) minnlcsetnlc() for nonlinear constraints - You may combine (a), (b) and (c) in one optimization problem. - -4. User sets scale of the variables with minnlcsetscale() function. It is - VERY important to set scale of the variables, because nonlinearly - constrained problems are hard to solve when variables are badly scaled. - -5. User sets stopping conditions with minnlcsetcond(). If NLC solver - uses inner/outer iteration layout, this function sets stopping - conditions for INNER iterations. - -6. Finally, user calls minnlcoptimize() function which takes algorithm - state and pointer (delegate, etc.) to callback function which calculates - F/G/H. - -7. User calls minnlcresults() to get solution; additionally you can - retrieve OptGuard report with minnlcoptguardresults(), and get detailed - report about purported errors in the target function with: - * minnlcoptguardnonc1test0results() - * minnlcoptguardnonc1test1results() - -8. Optionally user may call minnlcrestartfrom() to solve another problem - with same N but another starting point. minnlcrestartfrom() allows to - reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size ofX - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlccreate(const ae_int_t n, const real_1d_array &x, minnlcstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlccreate(n, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* - NONLINEARLY CONSTRAINED OPTIMIZATION - WITH PRECONDITIONED AUGMENTED LAGRANGIAN ALGORITHM - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments subject to any -combination of: -* bound constraints -* linear inequality constraints -* linear equality constraints -* nonlinear equality constraints Gi(x)=0 -* nonlinear inequality constraints Hi(x)<=0 - -REQUIREMENTS: -* user must provide function value and gradient for F(), H(), G() -* starting point X0 must be feasible or not too far away from the feasible - set -* F(), G(), H() are continuously differentiable on the feasible set and - its neighborhood -* nonlinear constraints G() and H() must have non-zero gradient at G(x)=0 - and at H(x)=0. Say, constraint like x^2>=1 is supported, but x^2>=0 is - NOT supported. - -USAGE: - -Constrained optimization if far more complex than the unconstrained one. -Nonlinearly constrained optimization is one of the most esoteric numerical -procedures. - -Here we give very brief outline of the MinNLC optimizer. We strongly -recommend you to study examples in the ALGLIB Reference Manual and to read -ALGLIB User Guide on optimization, which is available at -http://www.alglib.net/optimization/ - -1. User initializes algorithm state with MinNLCCreate() call and chooses - what NLC solver to use. There is some solver which is used by default, - with default settings, but you should NOT rely on default choice. It - may change in future releases of ALGLIB without notice, and no one can - guarantee that new solver will be able to solve your problem with - default settings. - - From the other side, if you choose solver explicitly, you can be pretty - sure that it will work with new ALGLIB releases. - - In the current release following solvers can be used: - * SQP solver, recommended for medium-scale problems (less than thousand - of variables) with hard-to-evaluate target functions. Requires less - function evaluations than other solvers but each step involves - solution of QP subproblem, so running time may be higher than that of - AUL (another recommended option). Activated with minnlcsetalgosqp() - function. - * AUL solver with dense preconditioner, recommended for large-scale - problems or for problems with cheap target function. Needs more - function evaluations that SQP (about 5x-10x times more), but its - iterations are much cheaper that that of SQP. Activated with - minnlcsetalgoaul() function. - * SLP solver, successive linear programming. The slowest one, requires - more target function evaluations that SQP and AUL. However, it is - somewhat more robust in tricky cases, so it can be used as a backup - plan. Activated with minnlcsetalgoslp() function. - -2. [optional] user activates OptGuard integrity checker which tries to - detect possible errors in the user-supplied callbacks: - * discontinuity/nonsmoothness of the target/nonlinear constraints - * errors in the analytic gradient provided by user - This feature is essential for early prototyping stages because it helps - to catch common coding and problem statement errors. - OptGuard can be activated with following functions (one per each check - performed): - * minnlcoptguardsmoothness() - * minnlcoptguardgradient() - -3. User adds boundary and/or linear and/or nonlinear constraints by means - of calling one of the following functions: - a) minnlcsetbc() for boundary constraints - b) minnlcsetlc() for linear constraints - c) minnlcsetnlc() for nonlinear constraints - You may combine (a), (b) and (c) in one optimization problem. - -4. User sets scale of the variables with minnlcsetscale() function. It is - VERY important to set scale of the variables, because nonlinearly - constrained problems are hard to solve when variables are badly scaled. - -5. User sets stopping conditions with minnlcsetcond(). If NLC solver - uses inner/outer iteration layout, this function sets stopping - conditions for INNER iterations. - -6. Finally, user calls minnlcoptimize() function which takes algorithm - state and pointer (delegate, etc.) to callback function which calculates - F/G/H. - -7. User calls minnlcresults() to get solution; additionally you can - retrieve OptGuard report with minnlcoptguardresults(), and get detailed - report about purported errors in the target function with: - * minnlcoptguardnonc1test0results() - * minnlcoptguardnonc1test1results() - -8. Optionally user may call minnlcrestartfrom() to solve another problem - with same N but another starting point. minnlcrestartfrom() allows to - reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size ofX - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minnlccreate(const real_1d_array &x, minnlcstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlccreate(n, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This subroutine is a finite difference variant of MinNLCCreate(). It uses -finite differences in order to differentiate target function. - -Description below contains information which is specific to this function -only. We recommend to read comments on MinNLCCreate() in order to get more -information about creation of NLC optimizer. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size ofX - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinNLCSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large TRUNCATION errors, while too small - step will result in too large NUMERICAL errors. 1.0E-4 can be good - value to start from. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. Imprecise gradient may slow down - convergence, especially on highly nonlinear problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlccreatef(const ae_int_t n, const real_1d_array &x, const double diffstep, minnlcstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlccreatef(n, const_cast(x.c_ptr()), diffstep, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine is a finite difference variant of MinNLCCreate(). It uses -finite differences in order to differentiate target function. - -Description below contains information which is specific to this function -only. We recommend to read comments on MinNLCCreate() in order to get more -information about creation of NLC optimizer. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size ofX - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinNLCSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large TRUNCATION errors, while too small - step will result in too large NUMERICAL errors. 1.0E-4 can be good - value to start from. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. Imprecise gradient may slow down - convergence, especially on highly nonlinear problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minnlccreatef(const real_1d_array &x, const double diffstep, minnlcstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlccreatef(n, const_cast(x.c_ptr()), diffstep, const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets boundary constraints for NLC optimizer. - -Boundary constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with MinNLCRestartFrom(). - -You may combine boundary constraints with general linear ones - and with -nonlinear ones! Boundary constraints are handled more efficiently than -other types. Thus, if your problem has mixed constraints, you may -explicitly specify some of them as boundary and save some time/space. - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF. - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF. - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - -NOTE 2: when you solve your problem with augmented Lagrangian solver, - boundary constraints are satisfied only approximately! It is - possible that algorithm will evaluate function outside of - feasible area! - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetbc(const minnlcstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcsetbc(const_cast(state.c_ptr()), const_cast(bndl.c_ptr()), const_cast(bndu.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets linear constraints for MinNLC optimizer. - -Linear constraints are inactive by default (after initial creation). They -are preserved after algorithm restart with MinNLCRestartFrom(). - -You may combine linear constraints with boundary ones - and with nonlinear -ones! If your problem has mixed constraints, you may explicitly specify -some of them as linear. It may help optimizer to handle them more -efficiently. - -INPUT PARAMETERS: - State - structure previously allocated with MinNLCCreate call. - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -NOTE 1: when you solve your problem with augmented Lagrangian solver, - linear constraints are satisfied only approximately! It is - possible that algorithm will evaluate function outside of - feasible area! - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetlc(const minnlcstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcsetlc(const_cast(state.c_ptr()), const_cast(c.c_ptr()), const_cast(ct.c_ptr()), k, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets linear constraints for MinNLC optimizer. - -Linear constraints are inactive by default (after initial creation). They -are preserved after algorithm restart with MinNLCRestartFrom(). - -You may combine linear constraints with boundary ones - and with nonlinear -ones! If your problem has mixed constraints, you may explicitly specify -some of them as linear. It may help optimizer to handle them more -efficiently. - -INPUT PARAMETERS: - State - structure previously allocated with MinNLCCreate call. - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -NOTE 1: when you solve your problem with augmented Lagrangian solver, - linear constraints are satisfied only approximately! It is - possible that algorithm will evaluate function outside of - feasible area! - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minnlcsetlc(const minnlcstate &state, const real_2d_array &c, const integer_1d_array &ct, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t k; - if( (c.rows()!=ct.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'minnlcsetlc': looks like one of arguments has wrong size"); - k = c.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcsetlc(const_cast(state.c_ptr()), const_cast(c.c_ptr()), const_cast(ct.c_ptr()), k, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets nonlinear constraints for MinNLC optimizer. - -In fact, this function sets NUMBER of nonlinear constraints. Constraints -itself (constraint functions) are passed to MinNLCOptimize() method. This -method requires user-defined vector function F[] and its Jacobian J[], -where: -* first component of F[] and first row of Jacobian J[] corresponds to - function being minimized -* next NLEC components of F[] (and rows of J) correspond to nonlinear - equality constraints G_i(x)=0 -* next NLIC components of F[] (and rows of J) correspond to nonlinear - inequality constraints H_i(x)<=0 - -NOTE: you may combine nonlinear constraints with linear/boundary ones. If - your problem has mixed constraints, you may explicitly specify some - of them as linear ones. It may help optimizer to handle them more - efficiently. - -INPUT PARAMETERS: - State - structure previously allocated with MinNLCCreate call. - NLEC - number of Non-Linear Equality Constraints (NLEC), >=0 - NLIC - number of Non-Linear Inquality Constraints (NLIC), >=0 - -NOTE 1: when you solve your problem with augmented Lagrangian solver, - nonlinear constraints are satisfied only approximately! It is - possible that algorithm will evaluate function outside of - feasible area! - -NOTE 2: algorithm scales variables according to scale specified by - MinNLCSetScale() function, so it can handle problems with badly - scaled variables (as long as we KNOW their scales). - - However, there is no way to automatically scale nonlinear - constraints Gi(x) and Hi(x). Inappropriate scaling of Gi/Hi may - ruin convergence. Solving problem with constraint "1000*G0(x)=0" - is NOT same as solving it with constraint "0.001*G0(x)=0". - - It means that YOU are the one who is responsible for correct - scaling of nonlinear constraints Gi(x) and Hi(x). We recommend you - to scale nonlinear constraints in such way that I-th component of - dG/dX (or dH/dx) has approximately unit magnitude (for problems - with unit scale) or has magnitude approximately equal to 1/S[i] - (where S is a scale set by MinNLCSetScale() function). - - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetnlc(const minnlcstate &state, const ae_int_t nlec, const ae_int_t nlic, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcsetnlc(const_cast(state.c_ptr()), nlec, nlic, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets stopping conditions for inner iterations of optimizer. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - step vector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinNLCSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic -selection of the stopping condition. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetcond(const minnlcstate &state, const double epsx, const ae_int_t maxits, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcsetcond(const_cast(state.c_ptr()), epsx, maxits, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets scaling coefficients for NLC optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of the optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetscale(const minnlcstate &state, const real_1d_array &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcsetscale(const_cast(state.c_ptr()), const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets preconditioner to "inexact LBFGS-based" mode. - -Preconditioning is very important for convergence of Augmented Lagrangian -algorithm because presence of penalty term makes problem ill-conditioned. -Difference between performance of preconditioned and unpreconditioned -methods can be as large as 100x! - -MinNLC optimizer may use following preconditioners, each with its own -benefits and drawbacks: - a) inexact LBFGS-based, with O(N*K) evaluation time - b) exact low rank one, with O(N*K^2) evaluation time - c) exact robust one, with O(N^3+K*N^2) evaluation time -where K is a total number of general linear and nonlinear constraints (box -ones are not counted). - -Inexact LBFGS-based preconditioner uses L-BFGS formula combined with -orthogonality assumption to perform very fast updates. For a N-dimensional -problem with K general linear or nonlinear constraints (boundary ones are -not counted) it has O(N*K) cost per iteration. This preconditioner has -best quality (less iterations) when general linear and nonlinear -constraints are orthogonal to each other (orthogonality with respect to -boundary constraints is not required). Number of iterations increases when -constraints are non-orthogonal, because algorithm assumes orthogonality, -but still it is better than no preconditioner at all. - -INPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 26.09.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetprecinexact(const minnlcstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcsetprecinexact(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets preconditioner to "exact low rank" mode. - -Preconditioning is very important for convergence of Augmented Lagrangian -algorithm because presence of penalty term makes problem ill-conditioned. -Difference between performance of preconditioned and unpreconditioned -methods can be as large as 100x! - -MinNLC optimizer may use following preconditioners, each with its own -benefits and drawbacks: - a) inexact LBFGS-based, with O(N*K) evaluation time - b) exact low rank one, with O(N*K^2) evaluation time - c) exact robust one, with O(N^3+K*N^2) evaluation time -where K is a total number of general linear and nonlinear constraints (box -ones are not counted). - -It also provides special unpreconditioned mode of operation which can be -used for test purposes. Comments below discuss low rank preconditioner. - -Exact low-rank preconditioner uses Woodbury matrix identity to build -quadratic model of the penalized function. It has following features: -* no special assumptions about orthogonality of constraints -* preconditioner evaluation is optimized for K<=N. -* finally, stability of the process is guaranteed only for K<=N due to degeneracy of intermediate matrices. - That's why we recommend to use "exact robust" preconditioner for such - cases. - -RECOMMENDATIONS - -We recommend to choose between "exact low rank" and "exact robust" -preconditioners, with "low rank" version being chosen when you know in -advance that total count of non-box constraints won't exceed N, and "robust" -version being chosen when you need bulletproof solution. - -INPUT PARAMETERS: - State - structure stores algorithm state - UpdateFreq- update frequency. Preconditioner is rebuilt after every - UpdateFreq iterations. Recommended value: 10 or higher. - Zero value means that good default value will be used. - - -- ALGLIB -- - Copyright 26.09.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetprecexactlowrank(const minnlcstate &state, const ae_int_t updatefreq, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcsetprecexactlowrank(const_cast(state.c_ptr()), updatefreq, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets preconditioner to "exact robust" mode. - -Preconditioning is very important for convergence of Augmented Lagrangian -algorithm because presence of penalty term makes problem ill-conditioned. -Difference between performance of preconditioned and unpreconditioned -methods can be as large as 100x! - -MinNLC optimizer may use following preconditioners, each with its own -benefits and drawbacks: - a) inexact LBFGS-based, with O(N*K) evaluation time - b) exact low rank one, with O(N*K^2) evaluation time - c) exact robust one, with O(N^3+K*N^2) evaluation time -where K is a total number of general linear and nonlinear constraints (box -ones are not counted). - -It also provides special unpreconditioned mode of operation which can be -used for test purposes. Comments below discuss robust preconditioner. - -Exact robust preconditioner uses Cholesky decomposition to invert -approximate Hessian matrix H=D+W'*C*W (where D stands for diagonal terms -of Hessian, combined result of initial scaling matrix and penalty from box -constraints; W stands for general linear constraints and linearization of -nonlinear ones; C stands for diagonal matrix of penalty coefficients). - -This preconditioner has following features: -* no special assumptions about constraint structure -* preconditioner is optimized for stability; unlike "exact low rank" - version which fails for K>=N, this one works well for any value of K. -* the only drawback is that is takes O(N^3+K*N^2) time to build it. No - economical Woodbury update is applied even when it makes sense, thus - there are exist situations (K<(state.c_ptr()), updatefreq, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets preconditioner to "turned off" mode. - -Preconditioning is very important for convergence of Augmented Lagrangian -algorithm because presence of penalty term makes problem ill-conditioned. -Difference between performance of preconditioned and unpreconditioned -methods can be as large as 100x! - -MinNLC optimizer may utilize two preconditioners, each with its own -benefits and drawbacks: a) inexact LBFGS-based, and b) exact low rank one. -It also provides special unpreconditioned mode of operation which can be -used for test purposes. - -This function activates this test mode. Do not use it in production code -to solve real-life problems. - -INPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 26.09.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetprecnone(const minnlcstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcsetprecnone(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets maximum step length (after scaling of step vector with -respect to variable scales specified by minnlcsetscale() call). - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0 (default), if - you don't want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which leads to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - -NOTE: different solvers employed by MinNLC optimizer use different norms - for step; AUL solver uses 2-norm, whilst SLP solver uses INF-norm. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetstpmax(const minnlcstate &state, const double stpmax, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcsetstpmax(const_cast(state.c_ptr()), stpmax, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function tells MinNLC unit to use Augmented Lagrangian algorithm -for nonlinearly constrained optimization. This algorithm is a slight -modification of one described in "A Modified Barrier-Augmented Lagrangian -Method for Constrained Minimization (1999)" by D.GOLDFARB, R.POLYAK, -K. SCHEINBERG, I.YUZEFOVICH. - -AUL solver can be significantly faster than SQP on easy problems due to -cheaper iterations, although it needs more function evaluations. - -Augmented Lagrangian algorithm works by converting problem of minimizing -F(x) subject to equality/inequality constraints to unconstrained problem -of the form - - min[ f(x) + - + Rho*PENALTY_EQ(x) + SHIFT_EQ(x,Nu1) + - + Rho*PENALTY_INEQ(x) + SHIFT_INEQ(x,Nu2) ] - -where: -* Rho is a fixed penalization coefficient -* PENALTY_EQ(x) is a penalty term, which is used to APPROXIMATELY enforce - equality constraints -* SHIFT_EQ(x) is a special "shift" term which is used to "fine-tune" - equality constraints, greatly increasing precision -* PENALTY_INEQ(x) is a penalty term which is used to approximately enforce - inequality constraints -* SHIFT_INEQ(x) is a special "shift" term which is used to "fine-tune" - inequality constraints, greatly increasing precision -* Nu1/Nu2 are vectors of Lagrange coefficients which are fine-tuned during - outer iterations of algorithm - -This version of AUL algorithm uses preconditioner, which greatly -accelerates convergence. Because this algorithm is similar to penalty -methods, it may perform steps into infeasible area. All kinds of -constraints (boundary, linear and nonlinear ones) may be violated in -intermediate points - and in the solution. However, properly configured -AUL method is significantly better at handling constraints than barrier -and/or penalty methods. - -The very basic outline of algorithm is given below: -1) first outer iteration is performed with "default" values of Lagrange - multipliers Nu1/Nu2. Solution quality is low (candidate point can be - too far away from true solution; large violation of constraints is - possible) and is comparable with that of penalty methods. -2) subsequent outer iterations refine Lagrange multipliers and improve - quality of the solution. - -INPUT PARAMETERS: - State - structure which stores algorithm state - Rho - penalty coefficient, Rho>0: - * large enough that algorithm converges with desired - precision. Minimum value is 10*max(S'*diag(H)*S), where - S is a scale matrix (set by MinNLCSetScale) and H is a - Hessian of the function being minimized. If you can not - easily estimate Hessian norm, see our recommendations - below. - * not TOO large to prevent ill-conditioning - * for unit-scale problems (variables and Hessian have unit - magnitude), Rho=100 or Rho=1000 can be used. - * it is important to note that Rho is internally multiplied - by scaling matrix, i.e. optimum value of Rho depends on - scale of variables specified by MinNLCSetScale(). - ItsCnt - number of outer iterations: - * ItsCnt=0 means that small number of outer iterations is - automatically chosen (10 iterations in current version). - * ItsCnt=1 means that AUL algorithm performs just as usual - barrier method. - * ItsCnt>1 means that AUL algorithm performs specified - number of outer iterations - -HOW TO CHOOSE PARAMETERS - -Nonlinear optimization is a tricky area and Augmented Lagrangian algorithm -is sometimes hard to tune. Good values of Rho and ItsCnt are problem- -specific. In order to help you we prepared following set of -recommendations: - -* for unit-scale problems (variables and Hessian have unit magnitude), - Rho=100 or Rho=1000 can be used. - -* start from some small value of Rho and solve problem with just one - outer iteration (ItcCnt=1). In this case algorithm behaves like penalty - method. Increase Rho in 2x or 10x steps until you see that one outer - iteration returns point which is "rough approximation to solution". - - It is very important to have Rho so large that penalty term becomes - constraining i.e. modified function becomes highly convex in constrained - directions. - - From the other side, too large Rho may prevent you from converging to - the solution. You can diagnose it by studying number of inner iterations - performed by algorithm: too few (5-10 on 1000-dimensional problem) or - too many (orders of magnitude more than dimensionality) usually means - that Rho is too large. - -* with just one outer iteration you usually have low-quality solution. - Some constraints can be violated with very large margin, while other - ones (which are NOT violated in the true solution) can push final point - too far in the inner area of the feasible set. - - For example, if you have constraint x0>=0 and true solution x0=1, then - merely a presence of "x0>=0" will introduce a bias towards larger values - of x0. Say, algorithm may stop at x0=1.5 instead of 1.0. - -* after you found good Rho, you may increase number of outer iterations. - ItsCnt=10 is a good value. Subsequent outer iteration will refine values - of Lagrange multipliers. Constraints which were violated will be - enforced, inactive constraints will be dropped (corresponding multipliers - will be decreased). Ideally, you should see 10-1000x improvement in - constraint handling (constraint violation is reduced). - -* if you see that algorithm converges to vicinity of solution, but - additional outer iterations do not refine solution, it may mean that - algorithm is unstable - it wanders around true solution, but can not - approach it. Sometimes algorithm may be stabilized by increasing Rho one - more time, making it 5x or 10x larger. - -SCALING OF CONSTRAINTS [IMPORTANT] - -AUL optimizer scales variables according to scale specified by -MinNLCSetScale() function, so it can handle problems with badly scaled -variables (as long as we KNOW their scales). However, because function -being optimized is a mix of original function and constraint-dependent -penalty functions, it is important to rescale both variables AND -constraints. - -Say, if you minimize f(x)=x^2 subject to 1000000*x>=0, then you have -constraint whose scale is different from that of target function (another -example is 0.000001*x>=0). It is also possible to have constraints whose -scales are misaligned: 1000000*x0>=0, 0.000001*x1<=0. Inappropriate -scaling may ruin convergence because minimizing x^2 subject to x>=0 is NOT -same as minimizing it subject to 1000000*x>=0. - -Because we know coefficients of boundary/linear constraints, we can -automatically rescale and normalize them. However, there is no way to -automatically rescale nonlinear constraints Gi(x) and Hi(x) - they are -black boxes. - -It means that YOU are the one who is responsible for correct scaling of -nonlinear constraints Gi(x) and Hi(x). We recommend you to rescale -nonlinear constraints in such way that I-th component of dG/dX (or dH/dx) -has magnitude approximately equal to 1/S[i] (where S is a scale set by -MinNLCSetScale() function). - -WHAT IF IT DOES NOT CONVERGE? - -It is possible that AUL algorithm fails to converge to precise values of -Lagrange multipliers. It stops somewhere around true solution, but candidate -point is still too far from solution, and some constraints are violated. -Such kind of failure is specific for Lagrangian algorithms - technically, -they stop at some point, but this point is not constrained solution. - -There are exist several reasons why algorithm may fail to converge: -a) too loose stopping criteria for inner iteration -b) degenerate, redundant constraints -c) target function has unconstrained extremum exactly at the boundary of - some constraint -d) numerical noise in the target function - -In all these cases algorithm is unstable - each outer iteration results in -large and almost random step which improves handling of some constraints, -but violates other ones (ideally outer iterations should form a sequence -of progressively decreasing steps towards solution). - -First reason possible is that too loose stopping criteria for inner -iteration were specified. Augmented Lagrangian algorithm solves a sequence -of intermediate problems, and requries each of them to be solved with high -precision. Insufficient precision results in incorrect update of Lagrange -multipliers. - -Another reason is that you may have specified degenerate constraints: say, -some constraint was repeated twice. In most cases AUL algorithm gracefully -handles such situations, but sometimes it may spend too much time figuring -out subtle degeneracies in constraint matrix. - -Third reason is tricky and hard to diagnose. Consider situation when you -minimize f=x^2 subject to constraint x>=0. Unconstrained extremum is -located exactly at the boundary of constrained area. In this case -algorithm will tend to oscillate between negative and positive x. Each -time it stops at x<0 it "reinforces" constraint x>=0, and each time it is -bounced to x>0 it "relaxes" constraint (and is attracted to x<0). - -Such situation sometimes happens in problems with hidden symetries. -Algorithm is got caught in a loop with Lagrange multipliers being -continuously increased/decreased. Luckily, such loop forms after at least -three iterations, so this problem can be solved by DECREASING number of -outer iterations down to 1-2 and increasing penalty coefficient Rho as -much as possible. - -Final reason is numerical noise. AUL algorithm is robust against moderate -noise (more robust than, say, active set methods), but large noise may -destabilize algorithm. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetalgoaul(const minnlcstate &state, const double rho, const ae_int_t itscnt, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcsetalgoaul(const_cast(state.c_ptr()), rho, itscnt, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function tells MinNLC optimizer to use SLP (Successive Linear -Programming) algorithm for nonlinearly constrained optimization. This -algorithm is a slight modification of one described in "A Linear -programming-based optimization algorithm for solving nonlinear programming -problems" (2010) by Claus Still and Tapio Westerlund. - -This solver is the slowest one in ALGLIB, it requires more target function -evaluations that SQP and AUL. However it is somewhat more robust in tricky -cases, so it can be used as a backup plan. We recommend to use this algo -when SQP/AUL do not work (does not return the solution you expect). If -trying different approach gives same results, then MAYBE something is -wrong with your optimization problem. - -Despite its name ("linear" = "first order method") this algorithm performs -steps similar to that of conjugate gradients method; internally it uses -orthogonality/conjugacy requirement for subsequent steps which makes it -closer to second order methods in terms of convergence speed. - -Convergence is proved for the following case: -* function and constraints are continuously differentiable (C1 class) -* extended Mangasarian–Fromovitz constraint qualification (EMFCQ) holds; - in the context of this algorithm EMFCQ means that one can, for any - infeasible point, find a search direction such that the constraint - infeasibilities are reduced. - -This algorithm has following nice properties: -* no parameters to tune -* no convexity requirements for target function or constraints -* initial point can be infeasible -* algorithm respects box constraints in all intermediate points (it does - not even evaluate function outside of box constrained area) -* once linear constraints are enforced, algorithm will not violate them -* no such guarantees can be provided for nonlinear constraints, but once - nonlinear constraints are enforced, algorithm will try to respect them - as much as possible -* numerical differentiation does not violate box constraints (although - general linear and nonlinear ones can be violated during differentiation) -* from our experience, this algorithm is somewhat more robust in really - difficult cases - -INPUT PARAMETERS: - State - structure which stores algorithm state - -===== TRACING SLP SOLVER ================================================= - -SLP solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'SLP' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. - It also prints OptGuard integrity checker report when - nonsmoothness of target/constraints is suspected. -* 'SLP.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'SLP'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format -* 'SLP.PROBING' - to let algorithm insert additional function evaluations - before line search in order to build human-readable - chart of the raw Lagrangian (~40 additional function - evaluations is performed for each line search). This - symbol also implicitly defines 'SLP'. -* 'OPTGUARD' - for report of smoothness/continuity violations in target - and/or constraints. This kind of reporting is included - in 'SLP', but it comes with lots of additional info. If - you need just smoothness monitoring, specify this - setting. - - NOTE: this tag merely directs OptGuard output to log - file. Even if you specify it, you still have to - configure OptGuard by calling minnlcoptguard...() - family of functions. - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. Specifying 'SLP.PROBING' adds even larger -overhead due to additional function evaluations being performed. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("SLP,SLP.PROBING,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 02.04.2018 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetalgoslp(const minnlcstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcsetalgoslp(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function tells MinNLC optimizer to use SQP (Successive Quadratic -Programming) algorithm for nonlinearly constrained optimization. - -This algorithm needs order of magnitude (5x-10x) less function evaluations -than AUL solver, but has higher overhead because each iteration involves -solution of quadratic programming problem. - -Convergence is proved for the following case: -* function and constraints are continuously differentiable (C1 class) - -This algorithm has following nice properties: -* no parameters to tune -* no convexity requirements for target function or constraints -* initial point can be infeasible -* algorithm respects box constraints in all intermediate points (it does - not even evaluate function outside of box constrained area) -* once linear constraints are enforced, algorithm will not violate them -* no such guarantees can be provided for nonlinear constraints, but once - nonlinear constraints are enforced, algorithm will try to respect them - as much as possible -* numerical differentiation does not violate box constraints (although - general linear and nonlinear ones can be violated during differentiation) - -We recommend this algorithm as a default option for medium-scale problems -(less than thousand of variables) or problems with target function being -hard to evaluate. - -For large-scale problems or ones with very cheap target function -AUL solver can be better option. - -INPUT PARAMETERS: - State - structure which stores algorithm state - -===== INTERACTION WITH OPTGUARD ========================================== - -OptGuard integrity checker allows us to catch problems like errors in -gradients and discontinuity/nonsmoothness of the target/constraints. -Latter kind of problems can be detected by looking upon line searches -performed during optimization and searching for signs of nonsmoothness. - -The problem with SQP is that it is too good for OptGuard to work - it does -not perform line searches. It typically needs 1-2 function evaluations -per step, and it is not enough for OptGuard to detect nonsmoothness. - -So, if you suspect that your problem is nonsmooth, we recommend you to use -AUL or SLP solvers. - -===== TRACING SQP SOLVER ================================================= - -SQP solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'SQP' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. - It also prints OptGuard integrity checker report when - nonsmoothness of target/constraints is suspected. -* 'SQP.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'SQP'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format -* 'SQP.PROBING' - to let algorithm insert additional function evaluations - before line search in order to build human-readable - chart of the raw Lagrangian (~40 additional function - evaluations is performed for each line search). This - symbol also implicitly defines 'SQP' and activates - OptGuard integrity checker which detects continuity and - smoothness violations. An OptGuard log is printed at the - end of the file. - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. Specifying 'SQP.PROBING' adds even larger -overhead due to additional function evaluations being performed. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("SQP,SQP.PROBING,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 02.12.2019 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetalgosqp(const minnlcstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcsetalgosqp(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinNLCOptimize(). - -NOTE: algorithm passes two parameters to rep() callback - current point - and penalized function value at current point. Important - function - value which is returned is NOT function being minimized. It is sum - of the value of the function being minimized - and penalty term. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetxrep(const minnlcstate &state, const bool needxrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcsetxrep(const_cast(state.c_ptr()), needxrep, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool minnlciteration(const minnlcstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::minnlciteration(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - - -void minnlcoptimize(minnlcstate &state, - void (*fvec)(const real_1d_array &x, real_1d_array &fi, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(fvec!=NULL, "ALGLIB: error in 'minnlcoptimize()' (fvec is NULL)", &_alglib_env_state); - while( alglib_impl::minnlciteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needfi ) - { - fvec(state.x, state.fi, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.x, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minnlcoptimize' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - -void minnlcoptimize(minnlcstate &state, - void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(jac!=NULL, "ALGLIB: error in 'minnlcoptimize()' (jac is NULL)", &_alglib_env_state); - while( alglib_impl::minnlciteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needfij ) - { - jac(state.x, state.fi, state.j, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.x, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minnlcoptimize' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - - -/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic gradient/Jacobian. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function (constraints) at the -initial point (note: future versions may also perform check at the final -point) and compares numerical gradient/Jacobian with analytic one provided -by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both gradients/Jacobians, and specific components highlighted -as suspicious by the OptGuard. - -The primary OptGuard report can be retrieved with minnlcoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with minnlcsetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcoptguardgradient(const minnlcstate &state, const double teststep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcoptguardgradient(const_cast(state.c_ptr()), teststep, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) and/or constraints -b) nonsmooth target function (non-C1) and/or constraints - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - This kind of monitoring does not work well with SQP - because SQP solver needs just 1-2 function evaluations - per step, which is not enough for OptGuard to make - any conclusions. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minnlcoptguardsmoothness(const minnlcstate &state, const ae_int_t level, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcoptguardsmoothness(const_cast(state.c_ptr()), level, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) and/or constraints -b) nonsmooth target function (non-C1) and/or constraints - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - This kind of monitoring does not work well with SQP - because SQP solver needs just 1-2 function evaluations - per step, which is not enough for OptGuard to make - any conclusions. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minnlcoptguardsmoothness(const minnlcstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t level; - - level = 1; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcoptguardsmoothness(const_cast(state.c_ptr()), level, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -=== PRIMARY REPORT ======================================================= - -OptGuard performs several checks which are intended to catch common errors -in the implementation of nonlinear function/gradient: -* incorrect analytic gradient -* discontinuous (non-C0) target functions (constraints) -* nonsmooth (non-C1) target functions (constraints) - -Each of these checks is activated with appropriate function: -* minnlcoptguardgradient() for gradient verification -* minnlcoptguardsmoothness() for C0/C1 checks - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradfidx for specific function (Jacobian row) suspected - * rep.badgradvidx for specific variable (Jacobian column) suspected - * rep.badgradxbase, a point where gradient/Jacobian is tested - * rep.badgraduser, user-provided gradient/Jacobian - * rep.badgradnum, reference gradient/Jacobian obtained via numerical - differentiation -* rep.nonc0suspected, and additionally: - * rep.nonc0fidx - an index of specific function violating C0 continuity -* rep.nonc1suspected, and additionally - * rep.nonc1fidx - an index of specific function violating C1 continuity -Here function index 0 means target function, index 1 or higher denotes -nonlinear constraints. - -=== ADDITIONAL REPORTS/LOGS ============================================== - -Several different tests are performed to catch C0/C1 errors, you can find -out specific test signaled error by looking to: -* rep.nonc0test0positive, for non-C0 test #0 -* rep.nonc1test0positive, for non-C1 test #0 -* rep.nonc1test1positive, for non-C1 test #1 - -Additional information (including line search logs) can be obtained by -means of: -* minnlcoptguardnonc1test0results() -* minnlcoptguardnonc1test1results() -which return detailed error reports, specific points where discontinuities -were found, and so on. - -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - generic OptGuard report; more detailed reports can be - retrieved with other functions. - -NOTE: false negatives (nonsmooth problems are not identified as nonsmooth - ones) are possible although unlikely. - - The reason is that you need to make several evaluations around - nonsmoothness in order to accumulate enough information about - function curvature. Say, if you start right from the nonsmooth point, - optimizer simply won't get enough data to understand what is going - wrong before it terminates due to abrupt changes in the derivative. - It is also possible that "unlucky" step will move us to the - termination too quickly. - - Our current approach is to have less than 0.1% false negatives in - our test examples (measured with multiple restarts from random - points), and to have exactly 0% false positives. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minnlcoptguardresults(const minnlcstate &state, optguardreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcoptguardresults(const_cast(state.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #0 - -Nonsmoothness (non-C1) test #0 studies function values (not gradient!) -obtained during line searches and monitors behavior of the directional -derivative estimate. - -This test is less powerful than test #1, but it does not depend on the -gradient values and thus it is more robust against artifacts introduced by -numerical differentiation. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* fidx - is an index of the function (0 for target function, 1 or higher - for nonlinear constraints) which is suspected of being "non-C1" -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #0 "strong" report - lngrep - C1 test #0 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minnlcoptguardnonc1test0results(const minnlcstate &state, optguardnonc1test0report &strrep, optguardnonc1test0report &lngrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcoptguardnonc1test0results(const_cast(state.c_ptr()), const_cast(strrep.c_ptr()), const_cast(lngrep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #1 - -Nonsmoothness (non-C1) test #1 studies individual components of the -gradient computed during line search. - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* fidx - is an index of the function (0 for target function, 1 or higher - for nonlinear constraints) which is suspected of being "non-C1" -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #1 "strong" report - lngrep - C1 test #1 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minnlcoptguardnonc1test1results(const minnlcstate &state, optguardnonc1test1report &strrep, optguardnonc1test1report &lngrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcoptguardnonc1test1results(const_cast(state.c_ptr()), const_cast(strrep.c_ptr()), const_cast(lngrep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -MinNLC results: the solution found, completion codes and additional -information. - -If you activated OptGuard integrity checking functionality and want to get -OptGuard report, it can be retrieved with: -* minnlcoptguardresults() - for a primary report about (a) suspected C0/C1 - continuity violations and (b) errors in the analytic gradient. -* minnlcoptguardnonc1test0results() - for C1 continuity violation test #0, - detailed line search log -* minnlcoptguardnonc1test1results() - for C1 continuity violation test #1, - detailed line search log - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report, contains information about completion - code, constraint violation at the solution and so on. - - You should check rep.terminationtype in order to - distinguish successful termination from unsuccessful one: - - === FAILURE CODES === - * -8 internal integrity control detected infinite or - NAN values in function/gradient. Abnormal - termination signalled. - * -3 box constraints are infeasible. - Note: infeasibility of non-box constraints does - NOT trigger emergency completion; you have - to examine rep.bcerr/rep.lcerr/rep.nlcerr to - detect possibly inconsistent constraints. - - === SUCCESS CODES === - * 2 scaled step is no more than EpsX. - * 5 MaxIts steps were taken. - * 8 user requested algorithm termination via - minnlcrequesttermination(), last accepted point is - returned. - - More information about fields of this structure can be - found in the comments on minnlcreport datatype. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcresults(const minnlcstate &state, real_1d_array &x, minnlcreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcresults(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -NLC results - -Buffered implementation of MinNLCResults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minnlcresultsbuf(const minnlcstate &state, real_1d_array &x, minnlcreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcresultsbuf(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcrequesttermination(const minnlcstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcrequesttermination(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine restarts algorithm from new point. -All optimization parameters (including constraints) are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure previously allocated with MinNLCCreate call. - X - new starting point. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minnlcrestartfrom(const minnlcstate &state, const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnlcrestartfrom(const_cast(state.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_MINBC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores nonlinear optimizer state. -You should use functions provided by MinBC subpackage to work with this -object -*************************************************************************/ -_minbcstate_owner::_minbcstate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minbcstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::minbcstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minbcstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minbcstate)); - alglib_impl::_minbcstate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_minbcstate_owner::_minbcstate_owner(const _minbcstate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minbcstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minbcstate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::minbcstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minbcstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minbcstate)); - alglib_impl::_minbcstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_minbcstate_owner& _minbcstate_owner::operator=(const _minbcstate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minbcstate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minbcstate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_minbcstate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::minbcstate)); - alglib_impl::_minbcstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_minbcstate_owner::~_minbcstate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_minbcstate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::minbcstate* _minbcstate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::minbcstate* _minbcstate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -minbcstate::minbcstate() : _minbcstate_owner() ,needf(p_struct->needf),needfg(p_struct->needfg),xupdated(p_struct->xupdated),f(p_struct->f),g(&p_struct->g),x(&p_struct->x) -{ -} - -minbcstate::minbcstate(const minbcstate &rhs):_minbcstate_owner(rhs) ,needf(p_struct->needf),needfg(p_struct->needfg),xupdated(p_struct->xupdated),f(p_struct->f),g(&p_struct->g),x(&p_struct->x) -{ -} - -minbcstate& minbcstate::operator=(const minbcstate &rhs) -{ - if( this==&rhs ) - return *this; - _minbcstate_owner::operator=(rhs); - return *this; -} - -minbcstate::~minbcstate() -{ -} - - -/************************************************************************* -This structure stores optimization report: -* iterationscount number of iterations -* nfev number of gradient evaluations -* terminationtype termination type (see below) - -TERMINATION CODES - -terminationtype field contains completion code, which can be: - -8 internal integrity control detected infinite or NAN values in - function/gradient. Abnormal termination signalled. - -3 inconsistent constraints. - 1 relative function improvement is no more than EpsF. - 2 relative step is no more than EpsX. - 4 gradient norm is no more than EpsG - 5 MaxIts steps was taken - 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - 8 terminated by user who called minbcrequesttermination(). X contains - point which was "current accepted" when termination request was - submitted. -*************************************************************************/ -_minbcreport_owner::_minbcreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minbcreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::minbcreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minbcreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minbcreport)); - alglib_impl::_minbcreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_minbcreport_owner::_minbcreport_owner(const _minbcreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minbcreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minbcreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::minbcreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minbcreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minbcreport)); - alglib_impl::_minbcreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_minbcreport_owner& _minbcreport_owner::operator=(const _minbcreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minbcreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minbcreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_minbcreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::minbcreport)); - alglib_impl::_minbcreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_minbcreport_owner::~_minbcreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_minbcreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::minbcreport* _minbcreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::minbcreport* _minbcreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -minbcreport::minbcreport() : _minbcreport_owner() ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),varidx(p_struct->varidx),terminationtype(p_struct->terminationtype) -{ -} - -minbcreport::minbcreport(const minbcreport &rhs):_minbcreport_owner(rhs) ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),varidx(p_struct->varidx),terminationtype(p_struct->terminationtype) -{ -} - -minbcreport& minbcreport::operator=(const minbcreport &rhs) -{ - if( this==&rhs ) - return *this; - _minbcreport_owner::operator=(rhs); - return *this; -} - -minbcreport::~minbcreport() -{ -} - -/************************************************************************* - BOX CONSTRAINED OPTIMIZATION - WITH FAST ACTIVATION OF MULTIPLE BOX CONSTRAINTS - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments subject to box -constraints (with some of box constraints actually being equality ones). - -This optimizer uses algorithm similar to that of MinBLEIC (optimizer with -general linear constraints), but presence of box-only constraints allows -us to use faster constraint activation strategies. On large-scale problems, -with multiple constraints active at the solution, this optimizer can be -several times faster than BLEIC. - -REQUIREMENTS: -* user must provide function value and gradient -* starting point X0 must be feasible or - not too far away from the feasible set -* grad(f) must be Lipschitz continuous on a level set: - L = { x : f(x)<=f(x0) } -* function must be defined everywhere on the feasible set F - -USAGE: - -Constrained optimization if far more complex than the unconstrained one. -Here we give very brief outline of the BC optimizer. We strongly recommend -you to read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide -on optimization, which is available at http://www.alglib.net/optimization/ - -1. User initializes algorithm state with MinBCCreate() call - -2. USer adds box constraints by calling MinBCSetBC() function. - -3. User sets stopping conditions with MinBCSetCond(). - -4. User calls MinBCOptimize() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. - -5. User calls MinBCResults() to get solution - -6. Optionally user may call MinBCRestartFrom() to solve another problem - with same N but another starting point. - MinBCRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size ofX - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbccreate(const ae_int_t n, const real_1d_array &x, minbcstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbccreate(n, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* - BOX CONSTRAINED OPTIMIZATION - WITH FAST ACTIVATION OF MULTIPLE BOX CONSTRAINTS - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments subject to box -constraints (with some of box constraints actually being equality ones). - -This optimizer uses algorithm similar to that of MinBLEIC (optimizer with -general linear constraints), but presence of box-only constraints allows -us to use faster constraint activation strategies. On large-scale problems, -with multiple constraints active at the solution, this optimizer can be -several times faster than BLEIC. - -REQUIREMENTS: -* user must provide function value and gradient -* starting point X0 must be feasible or - not too far away from the feasible set -* grad(f) must be Lipschitz continuous on a level set: - L = { x : f(x)<=f(x0) } -* function must be defined everywhere on the feasible set F - -USAGE: - -Constrained optimization if far more complex than the unconstrained one. -Here we give very brief outline of the BC optimizer. We strongly recommend -you to read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide -on optimization, which is available at http://www.alglib.net/optimization/ - -1. User initializes algorithm state with MinBCCreate() call - -2. USer adds box constraints by calling MinBCSetBC() function. - -3. User sets stopping conditions with MinBCSetCond(). - -4. User calls MinBCOptimize() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. - -5. User calls MinBCResults() to get solution - -6. Optionally user may call MinBCRestartFrom() to solve another problem - with same N but another starting point. - MinBCRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size ofX - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minbccreate(const real_1d_array &x, minbcstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbccreate(n, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -The subroutine is finite difference variant of MinBCCreate(). It uses -finite differences in order to differentiate target function. - -Description below contains information which is specific to this function -only. We recommend to read comments on MinBCCreate() in order to get -more information about creation of BC optimizer. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[0..N-1]. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinBCSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large truncation errors, while too small - step will result in too large numerical errors. 1.0E-6 can be good - value to start with. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. CG needs exact gradient values. Imprecise - gradient may slow down convergence, especially on highly nonlinear - problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -void minbccreatef(const ae_int_t n, const real_1d_array &x, const double diffstep, minbcstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbccreatef(n, const_cast(x.c_ptr()), diffstep, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -The subroutine is finite difference variant of MinBCCreate(). It uses -finite differences in order to differentiate target function. - -Description below contains information which is specific to this function -only. We recommend to read comments on MinBCCreate() in order to get -more information about creation of BC optimizer. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[0..N-1]. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinBCSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large truncation errors, while too small - step will result in too large numerical errors. 1.0E-6 can be good - value to start with. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. CG needs exact gradient values. Imprecise - gradient may slow down convergence, especially on highly nonlinear - problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minbccreatef(const real_1d_array &x, const double diffstep, minbcstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbccreatef(n, const_cast(x.c_ptr()), diffstep, const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets boundary constraints for BC optimizer. - -Boundary constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with MinBCRestartFrom(). - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF. - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF. - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - -NOTE 2: this solver has following useful properties: -* bound constraints are always satisfied exactly -* function is evaluated only INSIDE area specified by bound constraints, - even when numerical differentiation is used (algorithm adjusts nodes - according to boundary constraints) - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcsetbc(const minbcstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbcsetbc(const_cast(state.c_ptr()), const_cast(bndl.c_ptr()), const_cast(bndu.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets stopping conditions for the optimizer. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|=0 - The subroutine finishes its work if on k+1-th iteration - the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - is satisfied. - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - step vector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinBCSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead -to automatic stopping criterion selection. - -NOTE: when SetCond() called with non-zero MaxIts, BC solver may perform - slightly more than MaxIts iterations. I.e., MaxIts sets non-strict - limit on iterations count. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcsetcond(const minbcstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbcsetcond(const_cast(state.c_ptr()), epsg, epsf, epsx, maxits, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets scaling coefficients for BC optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of the optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -In most optimizers (and in the BC too) scaling is NOT a form of -preconditioning. It just affects stopping conditions. You should set -preconditioner by separate call to one of the MinBCSetPrec...() -functions. - -There is a special preconditioning mode, however, which uses scaling -coefficients to form diagonal preconditioning matrix. You can turn this -mode on, if you want. But you should understand that scaling is not the -same thing as preconditioning - these are two different, although related -forms of tuning solver. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minbcsetscale(const minbcstate &state, const real_1d_array &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbcsetscale(const_cast(state.c_ptr()), const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Modification of the preconditioner: preconditioning is turned off. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcsetprecdefault(const minbcstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbcsetprecdefault(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Modification of the preconditioner: diagonal of approximate Hessian is -used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - D - diagonal of the approximate Hessian, array[0..N-1], - (if larger, only leading N elements are used). - -NOTE 1: D[i] should be positive. Exception will be thrown otherwise. - -NOTE 2: you should pass diagonal of approximate Hessian - NOT ITS INVERSE. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcsetprecdiag(const minbcstate &state, const real_1d_array &d, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbcsetprecdiag(const_cast(state.c_ptr()), const_cast(d.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Modification of the preconditioner: scale-based diagonal preconditioning. - -This preconditioning mode can be useful when you don't have approximate -diagonal of Hessian, but you know that your variables are badly scaled -(for example, one variable is in [1,10], and another in [1000,100000]), -and most part of the ill-conditioning comes from different scales of vars. - -In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2), -can greatly improve convergence. - -IMPRTANT: you should set scale of your variables with MinBCSetScale() -call (before or after MinBCSetPrecScale() call). Without knowledge of -the scale of your variables scale-based preconditioner will be just unit -matrix. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcsetprecscale(const minbcstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbcsetprecscale(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinBCOptimize(). - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcsetxrep(const minbcstate &state, const bool needxrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbcsetxrep(const_cast(state.c_ptr()), needxrep, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which lead to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcsetstpmax(const minbcstate &state, const double stpmax, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbcsetstpmax(const_cast(state.c_ptr()), stpmax, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool minbciteration(const minbcstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::minbciteration(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - - -void minbcoptimize(minbcstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'minbcoptimize()' (func is NULL)", &_alglib_env_state); - while( alglib_impl::minbciteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needf ) - { - func(state.x, state.f, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.x, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minbcoptimize' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - -void minbcoptimize(minbcstate &state, - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(grad!=NULL, "ALGLIB: error in 'minbcoptimize()' (grad is NULL)", &_alglib_env_state); - while( alglib_impl::minbciteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needfg ) - { - grad(state.x, state.f, state.g, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.x, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minbcoptimize' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - - -/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic gradient. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function at the initial point -(note: future versions may also perform check at the final point) and -compares numerical gradient with analytic one provided by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both gradients and specific components highlighted as -suspicious by the OptGuard. - -The primary OptGuard report can be retrieved with minbcoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with minbcsetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minbcoptguardgradient(const minbcstate &state, const double teststep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbcoptguardgradient(const_cast(state.c_ptr()), teststep, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) -b) nonsmooth target function (non-C1) - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbcoptguardsmoothness(const minbcstate &state, const ae_int_t level, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbcoptguardsmoothness(const_cast(state.c_ptr()), level, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) -b) nonsmooth target function (non-C1) - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minbcoptguardsmoothness(const minbcstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t level; - - level = 1; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbcoptguardsmoothness(const_cast(state.c_ptr()), level, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -=== PRIMARY REPORT ======================================================= - -OptGuard performs several checks which are intended to catch common errors -in the implementation of nonlinear function/gradient: -* incorrect analytic gradient -* discontinuous (non-C0) target functions (constraints) -* nonsmooth (non-C1) target functions (constraints) - -Each of these checks is activated with appropriate function: -* minbcoptguardgradient() for gradient verification -* minbcoptguardsmoothness() for C0/C1 checks - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradvidx for specific variable (gradient element) suspected - * rep.badgradxbase, a point where gradient is tested - * rep.badgraduser, user-provided gradient (stored as 2D matrix with - single row in order to make report structure compatible with more - complex optimizers like MinNLC or MinLM) - * rep.badgradnum, reference gradient obtained via numerical - differentiation (stored as 2D matrix with single row in order to make - report structure compatible with more complex optimizers like MinNLC - or MinLM) -* rep.nonc0suspected -* rep.nonc1suspected - -=== ADDITIONAL REPORTS/LOGS ============================================== - -Several different tests are performed to catch C0/C1 errors, you can find -out specific test signaled error by looking to: -* rep.nonc0test0positive, for non-C0 test #0 -* rep.nonc1test0positive, for non-C1 test #0 -* rep.nonc1test1positive, for non-C1 test #1 - -Additional information (including line search logs) can be obtained by -means of: -* minbcoptguardnonc1test0results() -* minbcoptguardnonc1test1results() -which return detailed error reports, specific points where discontinuities -were found, and so on. - -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - generic OptGuard report; more detailed reports can be - retrieved with other functions. - -NOTE: false negatives (nonsmooth problems are not identified as nonsmooth - ones) are possible although unlikely. - - The reason is that you need to make several evaluations around - nonsmoothness in order to accumulate enough information about - function curvature. Say, if you start right from the nonsmooth point, - optimizer simply won't get enough data to understand what is going - wrong before it terminates due to abrupt changes in the derivative. - It is also possible that "unlucky" step will move us to the - termination too quickly. - - Our current approach is to have less than 0.1% false negatives in - our test examples (measured with multiple restarts from random - points), and to have exactly 0% false positives. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbcoptguardresults(const minbcstate &state, optguardreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbcoptguardresults(const_cast(state.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #0 - -Nonsmoothness (non-C1) test #0 studies function values (not gradient!) -obtained during line searches and monitors behavior of the directional -derivative estimate. - -This test is less powerful than test #1, but it does not depend on the -gradient values and thus it is more robust against artifacts introduced by -numerical differentiation. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #0 "strong" report - lngrep - C1 test #0 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbcoptguardnonc1test0results(const minbcstate &state, optguardnonc1test0report &strrep, optguardnonc1test0report &lngrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbcoptguardnonc1test0results(const_cast(state.c_ptr()), const_cast(strrep.c_ptr()), const_cast(lngrep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #1 - -Nonsmoothness (non-C1) test #1 studies individual components of the -gradient computed during line search. - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #1 "strong" report - lngrep - C1 test #1 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbcoptguardnonc1test1results(const minbcstate &state, optguardnonc1test1report &strrep, optguardnonc1test1report &lngrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbcoptguardnonc1test1results(const_cast(state.c_ptr()), const_cast(strrep.c_ptr()), const_cast(lngrep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -BC results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report. You should check Rep.TerminationType - in order to distinguish successful termination from - unsuccessful one: - * -8 internal integrity control detected infinite or - NAN values in function/gradient. Abnormal - termination signalled. - * -3 inconsistent constraints. - * 1 relative function improvement is no more than EpsF. - * 2 scaled step is no more than EpsX. - * 4 scaled gradient norm is no more than EpsG. - * 5 MaxIts steps was taken - * 8 terminated by user who called minbcrequesttermination(). - X contains point which was "current accepted" when - termination request was submitted. - More information about fields of this structure can be - found in the comments on MinBCReport datatype. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcresults(const minbcstate &state, real_1d_array &x, minbcreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbcresults(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -BC results - -Buffered implementation of MinBCResults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcresultsbuf(const minbcstate &state, real_1d_array &x, minbcreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbcresultsbuf(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine restarts algorithm from new point. -All optimization parameters (including constraints) are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure previously allocated with MinBCCreate call. - X - new starting point. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcrestartfrom(const minbcstate &state, const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbcrestartfrom(const_cast(state.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void minbcrequesttermination(const minbcstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbcrequesttermination(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_MINNS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores nonlinear optimizer state. -You should use functions provided by MinNS subpackage to work with this -object -*************************************************************************/ -_minnsstate_owner::_minnsstate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minnsstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::minnsstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minnsstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minnsstate)); - alglib_impl::_minnsstate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_minnsstate_owner::_minnsstate_owner(const _minnsstate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minnsstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minnsstate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::minnsstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minnsstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minnsstate)); - alglib_impl::_minnsstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_minnsstate_owner& _minnsstate_owner::operator=(const _minnsstate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minnsstate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minnsstate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_minnsstate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::minnsstate)); - alglib_impl::_minnsstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_minnsstate_owner::~_minnsstate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_minnsstate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::minnsstate* _minnsstate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::minnsstate* _minnsstate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -minnsstate::minnsstate() : _minnsstate_owner() ,needfi(p_struct->needfi),needfij(p_struct->needfij),xupdated(p_struct->xupdated),f(p_struct->f),fi(&p_struct->fi),j(&p_struct->j),x(&p_struct->x) -{ -} - -minnsstate::minnsstate(const minnsstate &rhs):_minnsstate_owner(rhs) ,needfi(p_struct->needfi),needfij(p_struct->needfij),xupdated(p_struct->xupdated),f(p_struct->f),fi(&p_struct->fi),j(&p_struct->j),x(&p_struct->x) -{ -} - -minnsstate& minnsstate::operator=(const minnsstate &rhs) -{ - if( this==&rhs ) - return *this; - _minnsstate_owner::operator=(rhs); - return *this; -} - -minnsstate::~minnsstate() -{ -} - - -/************************************************************************* -This structure stores optimization report: -* IterationsCount total number of inner iterations -* NFEV number of gradient evaluations -* TerminationType termination type (see below) -* CErr maximum violation of all types of constraints -* LCErr maximum violation of linear constraints -* NLCErr maximum violation of nonlinear constraints - -TERMINATION CODES - -TerminationType field contains completion code, which can be: - -8 internal integrity control detected infinite or NAN values in - function/gradient. Abnormal termination signalled. - -3 box constraints are inconsistent - -1 inconsistent parameters were passed: - * penalty parameter for minnssetalgoags() is zero, - but we have nonlinear constraints set by minnssetnlc() - 2 sampling radius decreased below epsx - 5 MaxIts steps was taken - 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - 8 User requested termination via MinNSRequestTermination() - -Other fields of this structure are not documented and should not be used! -*************************************************************************/ -_minnsreport_owner::_minnsreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minnsreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::minnsreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minnsreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minnsreport)); - alglib_impl::_minnsreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_minnsreport_owner::_minnsreport_owner(const _minnsreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minnsreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minnsreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::minnsreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minnsreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minnsreport)); - alglib_impl::_minnsreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_minnsreport_owner& _minnsreport_owner::operator=(const _minnsreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minnsreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minnsreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_minnsreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::minnsreport)); - alglib_impl::_minnsreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_minnsreport_owner::~_minnsreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_minnsreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::minnsreport* _minnsreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::minnsreport* _minnsreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -minnsreport::minnsreport() : _minnsreport_owner() ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),cerr(p_struct->cerr),lcerr(p_struct->lcerr),nlcerr(p_struct->nlcerr),terminationtype(p_struct->terminationtype),varidx(p_struct->varidx),funcidx(p_struct->funcidx) -{ -} - -minnsreport::minnsreport(const minnsreport &rhs):_minnsreport_owner(rhs) ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),cerr(p_struct->cerr),lcerr(p_struct->lcerr),nlcerr(p_struct->nlcerr),terminationtype(p_struct->terminationtype),varidx(p_struct->varidx),funcidx(p_struct->funcidx) -{ -} - -minnsreport& minnsreport::operator=(const minnsreport &rhs) -{ - if( this==&rhs ) - return *this; - _minnsreport_owner::operator=(rhs); - return *this; -} - -minnsreport::~minnsreport() -{ -} - -/************************************************************************* - NONSMOOTH NONCONVEX OPTIMIZATION - SUBJECT TO BOX/LINEAR/NONLINEAR-NONSMOOTH CONSTRAINTS - -DESCRIPTION: - -The subroutine minimizes function F(x) of N arguments subject to any -combination of: -* bound constraints -* linear inequality constraints -* linear equality constraints -* nonlinear equality constraints Gi(x)=0 -* nonlinear inequality constraints Hi(x)<=0 - -IMPORTANT: see MinNSSetAlgoAGS for important information on performance - restrictions of AGS solver. - -REQUIREMENTS: -* starting point X0 must be feasible or not too far away from the feasible - set -* F(), G(), H() are continuous, locally Lipschitz and continuously (but - not necessarily twice) differentiable in an open dense subset of R^N. - Functions F(), G() and H() may be nonsmooth and non-convex. - Informally speaking, it means that functions are composed of large - differentiable "patches" with nonsmoothness having place only at the - boundaries between these "patches". - Most real-life nonsmooth functions satisfy these requirements. Say, - anything which involves finite number of abs(), min() and max() is very - likely to pass the test. - Say, it is possible to optimize anything of the following: - * f=abs(x0)+2*abs(x1) - * f=max(x0,x1) - * f=sin(max(x0,x1)+abs(x2)) -* for nonlinearly constrained problems: F() must be bounded from below - without nonlinear constraints (this requirement is due to the fact that, - contrary to box and linear constraints, nonlinear ones require special - handling). -* user must provide function value and gradient for F(), H(), G() at all - points where function/gradient can be calculated. If optimizer requires - value exactly at the boundary between "patches" (say, at x=0 for f=abs(x)), - where gradient is not defined, user may resolve tie arbitrarily (in our - case - return +1 or -1 at its discretion). -* NS solver supports numerical differentiation, i.e. it may differentiate - your function for you, but it results in 2N increase of function - evaluations. Not recommended unless you solve really small problems. See - minnscreatef() for more information on this functionality. - -USAGE: - -1. User initializes algorithm state with MinNSCreate() call and chooses - what NLC solver to use. There is some solver which is used by default, - with default settings, but you should NOT rely on default choice. It - may change in future releases of ALGLIB without notice, and no one can - guarantee that new solver will be able to solve your problem with - default settings. - - From the other side, if you choose solver explicitly, you can be pretty - sure that it will work with new ALGLIB releases. - - In the current release following solvers can be used: - * AGS solver (activated with MinNSSetAlgoAGS() function) - -2. User adds boundary and/or linear and/or nonlinear constraints by means - of calling one of the following functions: - a) MinNSSetBC() for boundary constraints - b) MinNSSetLC() for linear constraints - c) MinNSSetNLC() for nonlinear constraints - You may combine (a), (b) and (c) in one optimization problem. - -3. User sets scale of the variables with MinNSSetScale() function. It is - VERY important to set scale of the variables, because nonlinearly - constrained problems are hard to solve when variables are badly scaled. - -4. User sets stopping conditions with MinNSSetCond(). - -5. Finally, user calls MinNSOptimize() function which takes algorithm - state and pointer (delegate, etc) to callback function which calculates - F/G/H. - -7. User calls MinNSResults() to get solution - -8. Optionally user may call MinNSRestartFrom() to solve another problem - with same N but another starting point. MinNSRestartFrom() allows to - reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - -NOTE: minnscreatef() function may be used if you do not have analytic - gradient. This function creates solver which uses numerical - differentiation with user-specified step. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnscreate(const ae_int_t n, const real_1d_array &x, minnsstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnscreate(n, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* - NONSMOOTH NONCONVEX OPTIMIZATION - SUBJECT TO BOX/LINEAR/NONLINEAR-NONSMOOTH CONSTRAINTS - -DESCRIPTION: - -The subroutine minimizes function F(x) of N arguments subject to any -combination of: -* bound constraints -* linear inequality constraints -* linear equality constraints -* nonlinear equality constraints Gi(x)=0 -* nonlinear inequality constraints Hi(x)<=0 - -IMPORTANT: see MinNSSetAlgoAGS for important information on performance - restrictions of AGS solver. - -REQUIREMENTS: -* starting point X0 must be feasible or not too far away from the feasible - set -* F(), G(), H() are continuous, locally Lipschitz and continuously (but - not necessarily twice) differentiable in an open dense subset of R^N. - Functions F(), G() and H() may be nonsmooth and non-convex. - Informally speaking, it means that functions are composed of large - differentiable "patches" with nonsmoothness having place only at the - boundaries between these "patches". - Most real-life nonsmooth functions satisfy these requirements. Say, - anything which involves finite number of abs(), min() and max() is very - likely to pass the test. - Say, it is possible to optimize anything of the following: - * f=abs(x0)+2*abs(x1) - * f=max(x0,x1) - * f=sin(max(x0,x1)+abs(x2)) -* for nonlinearly constrained problems: F() must be bounded from below - without nonlinear constraints (this requirement is due to the fact that, - contrary to box and linear constraints, nonlinear ones require special - handling). -* user must provide function value and gradient for F(), H(), G() at all - points where function/gradient can be calculated. If optimizer requires - value exactly at the boundary between "patches" (say, at x=0 for f=abs(x)), - where gradient is not defined, user may resolve tie arbitrarily (in our - case - return +1 or -1 at its discretion). -* NS solver supports numerical differentiation, i.e. it may differentiate - your function for you, but it results in 2N increase of function - evaluations. Not recommended unless you solve really small problems. See - minnscreatef() for more information on this functionality. - -USAGE: - -1. User initializes algorithm state with MinNSCreate() call and chooses - what NLC solver to use. There is some solver which is used by default, - with default settings, but you should NOT rely on default choice. It - may change in future releases of ALGLIB without notice, and no one can - guarantee that new solver will be able to solve your problem with - default settings. - - From the other side, if you choose solver explicitly, you can be pretty - sure that it will work with new ALGLIB releases. - - In the current release following solvers can be used: - * AGS solver (activated with MinNSSetAlgoAGS() function) - -2. User adds boundary and/or linear and/or nonlinear constraints by means - of calling one of the following functions: - a) MinNSSetBC() for boundary constraints - b) MinNSSetLC() for linear constraints - c) MinNSSetNLC() for nonlinear constraints - You may combine (a), (b) and (c) in one optimization problem. - -3. User sets scale of the variables with MinNSSetScale() function. It is - VERY important to set scale of the variables, because nonlinearly - constrained problems are hard to solve when variables are badly scaled. - -4. User sets stopping conditions with MinNSSetCond(). - -5. Finally, user calls MinNSOptimize() function which takes algorithm - state and pointer (delegate, etc) to callback function which calculates - F/G/H. - -7. User calls MinNSResults() to get solution - -8. Optionally user may call MinNSRestartFrom() to solve another problem - with same N but another starting point. MinNSRestartFrom() allows to - reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - -NOTE: minnscreatef() function may be used if you do not have analytic - gradient. This function creates solver which uses numerical - differentiation with user-specified step. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minnscreate(const real_1d_array &x, minnsstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnscreate(n, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Version of minnscreatef() which uses numerical differentiation. I.e., you -do not have to calculate derivatives yourself. However, this version needs -2N times more function evaluations. - -2-point differentiation formula is used, because more precise 4-point -formula is unstable when used on non-smooth functions. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - DiffStep- differentiation step, DiffStep>0. Algorithm performs - numerical differentiation with step for I-th variable - being equal to DiffStep*S[I] (here S[] is a scale vector, - set by minnssetscale() function). - Do not use too small steps, because it may lead to - catastrophic cancellation during intermediate calculations. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnscreatef(const ae_int_t n, const real_1d_array &x, const double diffstep, minnsstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnscreatef(n, const_cast(x.c_ptr()), diffstep, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Version of minnscreatef() which uses numerical differentiation. I.e., you -do not have to calculate derivatives yourself. However, this version needs -2N times more function evaluations. - -2-point differentiation formula is used, because more precise 4-point -formula is unstable when used on non-smooth functions. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - DiffStep- differentiation step, DiffStep>0. Algorithm performs - numerical differentiation with step for I-th variable - being equal to DiffStep*S[I] (here S[] is a scale vector, - set by minnssetscale() function). - Do not use too small steps, because it may lead to - catastrophic cancellation during intermediate calculations. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minnscreatef(const real_1d_array &x, const double diffstep, minnsstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnscreatef(n, const_cast(x.c_ptr()), diffstep, const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets boundary constraints. - -Boundary constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with minnsrestartfrom(). - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF. - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF. - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - -NOTE 2: AGS solver has following useful properties: -* bound constraints are always satisfied exactly -* function is evaluated only INSIDE area specified by bound constraints, - even when numerical differentiation is used (algorithm adjusts nodes - according to boundary constraints) - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnssetbc(const minnsstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnssetbc(const_cast(state.c_ptr()), const_cast(bndl.c_ptr()), const_cast(bndu.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets linear constraints. - -Linear constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with minnsrestartfrom(). - -INPUT PARAMETERS: - State - structure previously allocated with minnscreate() call. - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -NOTE: linear (non-bound) constraints are satisfied only approximately: - -* there always exists some minor violation (about current sampling radius - in magnitude during optimization, about EpsX in the solution) due to use - of penalty method to handle constraints. -* numerical differentiation, if used, may lead to function evaluations - outside of the feasible area, because algorithm does NOT change - numerical differentiation formula according to linear constraints. - -If you want constraints to be satisfied exactly, try to reformulate your -problem in such manner that all constraints will become boundary ones -(this kind of constraints is always satisfied exactly, both in the final -solution and in all intermediate points). - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnssetlc(const minnsstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnssetlc(const_cast(state.c_ptr()), const_cast(c.c_ptr()), const_cast(ct.c_ptr()), k, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets linear constraints. - -Linear constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with minnsrestartfrom(). - -INPUT PARAMETERS: - State - structure previously allocated with minnscreate() call. - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -NOTE: linear (non-bound) constraints are satisfied only approximately: - -* there always exists some minor violation (about current sampling radius - in magnitude during optimization, about EpsX in the solution) due to use - of penalty method to handle constraints. -* numerical differentiation, if used, may lead to function evaluations - outside of the feasible area, because algorithm does NOT change - numerical differentiation formula according to linear constraints. - -If you want constraints to be satisfied exactly, try to reformulate your -problem in such manner that all constraints will become boundary ones -(this kind of constraints is always satisfied exactly, both in the final -solution and in all intermediate points). - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minnssetlc(const minnsstate &state, const real_2d_array &c, const integer_1d_array &ct, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t k; - if( (c.rows()!=ct.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'minnssetlc': looks like one of arguments has wrong size"); - k = c.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnssetlc(const_cast(state.c_ptr()), const_cast(c.c_ptr()), const_cast(ct.c_ptr()), k, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets nonlinear constraints. - -In fact, this function sets NUMBER of nonlinear constraints. Constraints -itself (constraint functions) are passed to minnsoptimize() method. This -method requires user-defined vector function F[] and its Jacobian J[], -where: -* first component of F[] and first row of Jacobian J[] correspond to - function being minimized -* next NLEC components of F[] (and rows of J) correspond to nonlinear - equality constraints G_i(x)=0 -* next NLIC components of F[] (and rows of J) correspond to nonlinear - inequality constraints H_i(x)<=0 - -NOTE: you may combine nonlinear constraints with linear/boundary ones. If - your problem has mixed constraints, you may explicitly specify some - of them as linear ones. It may help optimizer to handle them more - efficiently. - -INPUT PARAMETERS: - State - structure previously allocated with minnscreate() call. - NLEC - number of Non-Linear Equality Constraints (NLEC), >=0 - NLIC - number of Non-Linear Inquality Constraints (NLIC), >=0 - -NOTE 1: nonlinear constraints are satisfied only approximately! It is - possible that algorithm will evaluate function outside of - the feasible area! - -NOTE 2: algorithm scales variables according to scale specified by - minnssetscale() function, so it can handle problems with badly - scaled variables (as long as we KNOW their scales). - - However, there is no way to automatically scale nonlinear - constraints Gi(x) and Hi(x). Inappropriate scaling of Gi/Hi may - ruin convergence. Solving problem with constraint "1000*G0(x)=0" - is NOT same as solving it with constraint "0.001*G0(x)=0". - - It means that YOU are the one who is responsible for correct - scaling of nonlinear constraints Gi(x) and Hi(x). We recommend you - to scale nonlinear constraints in such way that I-th component of - dG/dX (or dH/dx) has approximately unit magnitude (for problems - with unit scale) or has magnitude approximately equal to 1/S[i] - (where S is a scale set by minnssetscale() function). - -NOTE 3: nonlinear constraints are always hard to handle, no matter what - algorithm you try to use. Even basic box/linear constraints modify - function curvature by adding valleys and ridges. However, - nonlinear constraints add valleys which are very hard to follow - due to their "curved" nature. - - It means that optimization with single nonlinear constraint may be - significantly slower than optimization with multiple linear ones. - It is normal situation, and we recommend you to carefully choose - Rho parameter of minnssetalgoags(), because too large value may - slow down convergence. - - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnssetnlc(const minnsstate &state, const ae_int_t nlec, const ae_int_t nlic, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnssetnlc(const_cast(state.c_ptr()), nlec, nlic, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets stopping conditions for iterations of optimizer. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsX - >=0 - The AGS solver finishes its work if on k+1-th iteration - sampling radius decreases below EpsX. - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic -stopping criterion selection. We do not recommend you to rely on default -choice in production code. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnssetcond(const minnsstate &state, const double epsx, const ae_int_t maxits, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnssetcond(const_cast(state.c_ptr()), epsx, maxits, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets scaling coefficients for NLC optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of the optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnssetscale(const minnsstate &state, const real_1d_array &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnssetscale(const_cast(state.c_ptr()), const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function tells MinNS unit to use AGS (adaptive gradient sampling) -algorithm for nonsmooth constrained optimization. This algorithm is a -slight modification of one described in "An Adaptive Gradient Sampling -Algorithm for Nonsmooth Optimization" by Frank E. Curtisy and Xiaocun Quez. - -This optimizer has following benefits and drawbacks: -+ robustness; it can be used with nonsmooth and nonconvex functions. -+ relatively easy tuning; most of the metaparameters are easy to select. -- it has convergence of steepest descent, slower than CG/LBFGS. -- each iteration involves evaluation of ~2N gradient values and solution - of 2Nx2N quadratic programming problem, which limits applicability of - algorithm by small-scale problems (up to 50-100). - -IMPORTANT: this algorithm has convergence guarantees, i.e. it will - steadily move towards some stationary point of the function. - - However, "stationary point" does not always mean "solution". - Nonsmooth problems often have "flat spots", i.e. areas where - function do not change at all. Such "flat spots" are stationary - points by definition, and algorithm may be caught here. - - Nonsmooth CONVEX tasks are not prone to this problem. Say, if - your function has form f()=MAX(f0,f1,...), and f_i are convex, - then f() is convex too and you have guaranteed convergence to - solution. - -INPUT PARAMETERS: - State - structure which stores algorithm state - Radius - initial sampling radius, >=0. - - Internally multiplied by vector of per-variable scales - specified by minnssetscale()). - - You should select relatively large sampling radius, roughly - proportional to scaled length of the first steps of the - algorithm. Something close to 0.1 in magnitude should be - good for most problems. - - AGS solver can automatically decrease radius, so too large - radius is not a problem (assuming that you won't choose - so large radius that algorithm will sample function in - too far away points, where gradient value is irrelevant). - - Too small radius won't cause algorithm to fail, but it may - slow down algorithm (it may have to perform too short - steps). - Penalty - penalty coefficient for nonlinear constraints: - * for problem with nonlinear constraints should be some - problem-specific positive value, large enough that - penalty term changes shape of the function. - Starting from some problem-specific value penalty - coefficient becomes large enough to exactly enforce - nonlinear constraints; larger values do not improve - precision. - Increasing it too much may slow down convergence, so you - should choose it carefully. - * can be zero for problems WITHOUT nonlinear constraints - (i.e. for unconstrained ones or ones with just box or - linear constraints) - * if you specify zero value for problem with at least one - nonlinear constraint, algorithm will terminate with - error code -1. - -ALGORITHM OUTLINE - -The very basic outline of unconstrained AGS algorithm is given below: - -0. If sampling radius is below EpsX or we performed more then MaxIts - iterations - STOP. -1. sample O(N) gradient values at random locations around current point; - informally speaking, this sample is an implicit piecewise linear model - of the function, although algorithm formulation does not mention that - explicitly -2. solve quadratic programming problem in order to find descent direction -3. if QP solver tells us that we are near solution, decrease sampling - radius and move to (0) -4. perform backtracking line search -5. after moving to new point, goto (0) - -As for the constraints: -* box constraints are handled exactly by modification of the function - being minimized -* linear/nonlinear constraints are handled by adding L1 penalty. Because - our solver can handle nonsmoothness, we can use L1 penalty function, - which is an exact one (i.e. exact solution is returned under such - penalty). -* penalty coefficient for linear constraints is chosen automatically; - however, penalty coefficient for nonlinear constraints must be specified - by user. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnssetalgoags(const minnsstate &state, const double radius, const double penalty, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnssetalgoags(const_cast(state.c_ptr()), radius, penalty, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to minnsoptimize(). - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minnssetxrep(const minnsstate &state, const bool needxrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnssetxrep(const_cast(state.c_ptr()), needxrep, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnsrequesttermination(const minnsstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnsrequesttermination(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool minnsiteration(const minnsstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::minnsiteration(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - - -void minnsoptimize(minnsstate &state, - void (*fvec)(const real_1d_array &x, real_1d_array &fi, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(fvec!=NULL, "ALGLIB: error in 'minnsoptimize()' (fvec is NULL)", &_alglib_env_state); - while( alglib_impl::minnsiteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needfi ) - { - fvec(state.x, state.fi, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.x, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minnsoptimize' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - -void minnsoptimize(minnsstate &state, - void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(jac!=NULL, "ALGLIB: error in 'minnsoptimize()' (jac is NULL)", &_alglib_env_state); - while( alglib_impl::minnsiteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needfij ) - { - jac(state.x, state.fi, state.j, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.x, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minnsoptimize' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - - -/************************************************************************* -MinNS results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report. You should check Rep.TerminationType - in order to distinguish successful termination from - unsuccessful one: - * -8 internal integrity control detected infinite or - NAN values in function/gradient. Abnormal - termination signalled. - * -3 box constraints are inconsistent - * -1 inconsistent parameters were passed: - * penalty parameter for minnssetalgoags() is zero, - but we have nonlinear constraints set by minnssetnlc() - * 2 sampling radius decreased below epsx - * 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - * 8 User requested termination via minnsrequesttermination() - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnsresults(const minnsstate &state, real_1d_array &x, minnsreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnsresults(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* - -Buffered implementation of minnsresults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnsresultsbuf(const minnsstate &state, real_1d_array &x, minnsreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnsresultsbuf(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine restarts algorithm from new point. -All optimization parameters (including constraints) are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure previously allocated with minnscreate() call. - X - new starting point. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnsrestartfrom(const minnsstate &state, const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minnsrestartfrom(const_cast(state.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_MINCOMP) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - -*************************************************************************/ -_minasastate_owner::_minasastate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minasastate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::minasastate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minasastate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minasastate)); - alglib_impl::_minasastate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_minasastate_owner::_minasastate_owner(const _minasastate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minasastate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minasastate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::minasastate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minasastate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minasastate)); - alglib_impl::_minasastate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_minasastate_owner& _minasastate_owner::operator=(const _minasastate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minasastate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minasastate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_minasastate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::minasastate)); - alglib_impl::_minasastate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_minasastate_owner::~_minasastate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_minasastate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::minasastate* _minasastate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::minasastate* _minasastate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -minasastate::minasastate() : _minasastate_owner() ,needfg(p_struct->needfg),xupdated(p_struct->xupdated),f(p_struct->f),g(&p_struct->g),x(&p_struct->x) -{ -} - -minasastate::minasastate(const minasastate &rhs):_minasastate_owner(rhs) ,needfg(p_struct->needfg),xupdated(p_struct->xupdated),f(p_struct->f),g(&p_struct->g),x(&p_struct->x) -{ -} - -minasastate& minasastate::operator=(const minasastate &rhs) -{ - if( this==&rhs ) - return *this; - _minasastate_owner::operator=(rhs); - return *this; -} - -minasastate::~minasastate() -{ -} - - -/************************************************************************* - -*************************************************************************/ -_minasareport_owner::_minasareport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minasareport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::minasareport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minasareport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minasareport)); - alglib_impl::_minasareport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_minasareport_owner::_minasareport_owner(const _minasareport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minasareport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minasareport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::minasareport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minasareport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minasareport)); - alglib_impl::_minasareport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_minasareport_owner& _minasareport_owner::operator=(const _minasareport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minasareport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minasareport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_minasareport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::minasareport)); - alglib_impl::_minasareport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_minasareport_owner::~_minasareport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_minasareport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::minasareport* _minasareport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::minasareport* _minasareport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -minasareport::minasareport() : _minasareport_owner() ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),terminationtype(p_struct->terminationtype),activeconstraints(p_struct->activeconstraints) -{ -} - -minasareport::minasareport(const minasareport &rhs):_minasareport_owner(rhs) ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),terminationtype(p_struct->terminationtype),activeconstraints(p_struct->activeconstraints) -{ -} - -minasareport& minasareport::operator=(const minasareport &rhs) -{ - if( this==&rhs ) - return *this; - _minasareport_owner::operator=(rhs); - return *this; -} - -minasareport::~minasareport() -{ -} - -/************************************************************************* -Obsolete function, use MinLBFGSSetPrecDefault() instead. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetdefaultpreconditioner(const minlbfgsstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgssetdefaultpreconditioner(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Obsolete function, use MinLBFGSSetCholeskyPreconditioner() instead. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetcholeskypreconditioner(const minlbfgsstate &state, const real_2d_array &p, const bool isupper, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlbfgssetcholeskypreconditioner(const_cast(state.c_ptr()), const_cast(p.c_ptr()), isupper, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is obsolete function which was used by previous version of the BLEIC -optimizer. It does nothing in the current version of BLEIC. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetbarrierwidth(const minbleicstate &state, const double mu, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicsetbarrierwidth(const_cast(state.c_ptr()), mu, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is obsolete function which was used by previous version of the BLEIC -optimizer. It does nothing in the current version of BLEIC. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetbarrierdecay(const minbleicstate &state, const double mudecay, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minbleicsetbarrierdecay(const_cast(state.c_ptr()), mudecay, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 25.03.2010 by Bochkanov Sergey -*************************************************************************/ -void minasacreate(const ae_int_t n, const real_1d_array &x, const real_1d_array &bndl, const real_1d_array &bndu, minasastate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minasacreate(n, const_cast(x.c_ptr()), const_cast(bndl.c_ptr()), const_cast(bndu.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 25.03.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minasacreate(const real_1d_array &x, const real_1d_array &bndl, const real_1d_array &bndu, minasastate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (x.length()!=bndl.length()) || (x.length()!=bndu.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'minasacreate': looks like one of arguments has wrong size"); - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minasacreate(n, const_cast(x.c_ptr()), const_cast(bndl.c_ptr()), const_cast(bndu.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minasasetcond(const minasastate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minasasetcond(const_cast(state.c_ptr()), epsg, epsf, epsx, maxits, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minasasetxrep(const minasastate &state, const bool needxrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minasasetxrep(const_cast(state.c_ptr()), needxrep, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minasasetalgorithm(const minasastate &state, const ae_int_t algotype, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minasasetalgorithm(const_cast(state.c_ptr()), algotype, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minasasetstpmax(const minasastate &state, const double stpmax, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minasasetstpmax(const_cast(state.c_ptr()), stpmax, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool minasaiteration(const minasastate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::minasaiteration(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - - -void minasaoptimize(minasastate &state, - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(grad!=NULL, "ALGLIB: error in 'minasaoptimize()' (grad is NULL)", &_alglib_env_state); - while( alglib_impl::minasaiteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needfg ) - { - grad(state.x, state.f, state.g, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.x, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minasaoptimize' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minasaresults(const minasastate &state, real_1d_array &x, minasareport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minasaresults(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minasaresultsbuf(const minasastate &state, real_1d_array &x, minasareport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minasaresultsbuf(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -void minasarestartfrom(const minasastate &state, const real_1d_array &x, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minasarestartfrom(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(bndl.c_ptr()), const_cast(bndu.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_MINCG) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores state of the nonlinear CG optimizer. - -You should use ALGLIB functions to work with this object. -*************************************************************************/ -_mincgstate_owner::_mincgstate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_mincgstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::mincgstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::mincgstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::mincgstate)); - alglib_impl::_mincgstate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_mincgstate_owner::_mincgstate_owner(const _mincgstate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_mincgstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mincgstate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::mincgstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::mincgstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::mincgstate)); - alglib_impl::_mincgstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_mincgstate_owner& _mincgstate_owner::operator=(const _mincgstate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: mincgstate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mincgstate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_mincgstate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::mincgstate)); - alglib_impl::_mincgstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_mincgstate_owner::~_mincgstate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_mincgstate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::mincgstate* _mincgstate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::mincgstate* _mincgstate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -mincgstate::mincgstate() : _mincgstate_owner() ,needf(p_struct->needf),needfg(p_struct->needfg),xupdated(p_struct->xupdated),f(p_struct->f),g(&p_struct->g),x(&p_struct->x) -{ -} - -mincgstate::mincgstate(const mincgstate &rhs):_mincgstate_owner(rhs) ,needf(p_struct->needf),needfg(p_struct->needfg),xupdated(p_struct->xupdated),f(p_struct->f),g(&p_struct->g),x(&p_struct->x) -{ -} - -mincgstate& mincgstate::operator=(const mincgstate &rhs) -{ - if( this==&rhs ) - return *this; - _mincgstate_owner::operator=(rhs); - return *this; -} - -mincgstate::~mincgstate() -{ -} - - -/************************************************************************* -This structure stores optimization report: -* IterationsCount total number of inner iterations -* NFEV number of gradient evaluations -* TerminationType termination type (see below) - -TERMINATION CODES - -TerminationType field contains completion code, which can be: - -8 internal integrity control detected infinite or NAN values in - function/gradient. Abnormal termination signalled. - 1 relative function improvement is no more than EpsF. - 2 relative step is no more than EpsX. - 4 gradient norm is no more than EpsG - 5 MaxIts steps was taken - 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - 8 terminated by user who called mincgrequesttermination(). X contains - point which was "current accepted" when termination request was - submitted. - -Other fields of this structure are not documented and should not be used! -*************************************************************************/ -_mincgreport_owner::_mincgreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_mincgreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::mincgreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::mincgreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::mincgreport)); - alglib_impl::_mincgreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_mincgreport_owner::_mincgreport_owner(const _mincgreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_mincgreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mincgreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::mincgreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::mincgreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::mincgreport)); - alglib_impl::_mincgreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_mincgreport_owner& _mincgreport_owner::operator=(const _mincgreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: mincgreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mincgreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_mincgreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::mincgreport)); - alglib_impl::_mincgreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_mincgreport_owner::~_mincgreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_mincgreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::mincgreport* _mincgreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::mincgreport* _mincgreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -mincgreport::mincgreport() : _mincgreport_owner() ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),terminationtype(p_struct->terminationtype) -{ -} - -mincgreport::mincgreport(const mincgreport &rhs):_mincgreport_owner(rhs) ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),terminationtype(p_struct->terminationtype) -{ -} - -mincgreport& mincgreport::operator=(const mincgreport &rhs) -{ - if( this==&rhs ) - return *this; - _mincgreport_owner::operator=(rhs); - return *this; -} - -mincgreport::~mincgreport() -{ -} - -/************************************************************************* - NONLINEAR CONJUGATE GRADIENT METHOD - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments by using one of the -nonlinear conjugate gradient methods. - -These CG methods are globally convergent (even on non-convex functions) as -long as grad(f) is Lipschitz continuous in a some neighborhood of the -L = { x : f(x)<=f(x0) }. - - -REQUIREMENTS: -Algorithm will request following information during its operation: -* function value F and its gradient G (simultaneously) at given point X - - -USAGE: -1. User initializes algorithm state with MinCGCreate() call -2. User tunes solver parameters with MinCGSetCond(), MinCGSetStpMax() and - other functions -3. User calls MinCGOptimize() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. -4. User calls MinCGResults() to get solution -5. Optionally, user may call MinCGRestartFrom() to solve another problem - with same N but another starting point and/or another function. - MinCGRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[0..N-1]. - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 25.03.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgcreate(const ae_int_t n, const real_1d_array &x, mincgstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgcreate(n, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* - NONLINEAR CONJUGATE GRADIENT METHOD - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments by using one of the -nonlinear conjugate gradient methods. - -These CG methods are globally convergent (even on non-convex functions) as -long as grad(f) is Lipschitz continuous in a some neighborhood of the -L = { x : f(x)<=f(x0) }. - - -REQUIREMENTS: -Algorithm will request following information during its operation: -* function value F and its gradient G (simultaneously) at given point X - - -USAGE: -1. User initializes algorithm state with MinCGCreate() call -2. User tunes solver parameters with MinCGSetCond(), MinCGSetStpMax() and - other functions -3. User calls MinCGOptimize() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. -4. User calls MinCGResults() to get solution -5. Optionally, user may call MinCGRestartFrom() to solve another problem - with same N but another starting point and/or another function. - MinCGRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[0..N-1]. - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 25.03.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void mincgcreate(const real_1d_array &x, mincgstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgcreate(n, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -The subroutine is finite difference variant of MinCGCreate(). It uses -finite differences in order to differentiate target function. - -Description below contains information which is specific to this function -only. We recommend to read comments on MinCGCreate() in order to get more -information about creation of CG optimizer. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[0..N-1]. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinCGSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large truncation errors, while too small - step will result in too large numerical errors. 1.0E-6 can be good - value to start with. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. L-BFGS needs exact gradient values. - Imprecise gradient may slow down convergence, especially on highly - nonlinear problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -void mincgcreatef(const ae_int_t n, const real_1d_array &x, const double diffstep, mincgstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgcreatef(n, const_cast(x.c_ptr()), diffstep, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -The subroutine is finite difference variant of MinCGCreate(). It uses -finite differences in order to differentiate target function. - -Description below contains information which is specific to this function -only. We recommend to read comments on MinCGCreate() in order to get more -information about creation of CG optimizer. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[0..N-1]. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinCGSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large truncation errors, while too small - step will result in too large numerical errors. 1.0E-6 can be good - value to start with. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. L-BFGS needs exact gradient values. - Imprecise gradient may slow down convergence, especially on highly - nonlinear problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void mincgcreatef(const real_1d_array &x, const double diffstep, mincgstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgcreatef(n, const_cast(x.c_ptr()), diffstep, const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets stopping conditions for CG optimization algorithm. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|=0 - The subroutine finishes its work if on k+1-th iteration - the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - is satisfied. - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - ste pvector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinCGSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to -automatic stopping criterion selection (small EpsX). - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetcond(const mincgstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgsetcond(const_cast(state.c_ptr()), epsg, epsf, epsx, maxits, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets scaling coefficients for CG optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of CG optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -In most optimizers (and in the CG too) scaling is NOT a form of -preconditioning. It just affects stopping conditions. You should set -preconditioner by separate call to one of the MinCGSetPrec...() functions. - -There is special preconditioning mode, however, which uses scaling -coefficients to form diagonal preconditioning matrix. You can turn this -mode on, if you want. But you should understand that scaling is not the -same thing as preconditioning - these are two different, although related -forms of tuning solver. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void mincgsetscale(const mincgstate &state, const real_1d_array &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgsetscale(const_cast(state.c_ptr()), const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinCGOptimize(). - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetxrep(const mincgstate &state, const bool needxrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgsetxrep(const_cast(state.c_ptr()), needxrep, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets CG algorithm. - -INPUT PARAMETERS: - State - structure which stores algorithm state - CGType - algorithm type: - * -1 automatic selection of the best algorithm - * 0 DY (Dai and Yuan) algorithm - * 1 Hybrid DY-HS algorithm - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetcgtype(const mincgstate &state, const ae_int_t cgtype, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgsetcgtype(const_cast(state.c_ptr()), cgtype, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which leads to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetstpmax(const mincgstate &state, const double stpmax, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgsetstpmax(const_cast(state.c_ptr()), stpmax, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function allows to suggest initial step length to the CG algorithm. - -Suggested step length is used as starting point for the line search. It -can be useful when you have badly scaled problem, i.e. when ||grad|| -(which is used as initial estimate for the first step) is many orders of -magnitude different from the desired step. - -Line search may fail on such problems without good estimate of initial -step length. Imagine, for example, problem with ||grad||=10^50 and desired -step equal to 0.1 Line search function will use 10^50 as initial step, -then it will decrease step length by 2 (up to 20 attempts) and will get -10^44, which is still too large. - -This function allows us to tell than line search should be started from -some moderate step length, like 1.0, so algorithm will be able to detect -desired step length in a several searches. - -Default behavior (when no step is suggested) is to use preconditioner, if -it is available, to generate initial estimate of step length. - -This function influences only first iteration of algorithm. It should be -called between MinCGCreate/MinCGRestartFrom() call and MinCGOptimize call. -Suggested step is ignored if you have preconditioner. - -INPUT PARAMETERS: - State - structure used to store algorithm state. - Stp - initial estimate of the step length. - Can be zero (no estimate). - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsuggeststep(const mincgstate &state, const double stp, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgsuggeststep(const_cast(state.c_ptr()), stp, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Modification of the preconditioner: preconditioning is turned off. - -INPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetprecdefault(const mincgstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgsetprecdefault(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Modification of the preconditioner: diagonal of approximate Hessian is -used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - D - diagonal of the approximate Hessian, array[0..N-1], - (if larger, only leading N elements are used). - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - -NOTE 2: D[i] should be positive. Exception will be thrown otherwise. - -NOTE 3: you should pass diagonal of approximate Hessian - NOT ITS INVERSE. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetprecdiag(const mincgstate &state, const real_1d_array &d, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgsetprecdiag(const_cast(state.c_ptr()), const_cast(d.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Modification of the preconditioner: scale-based diagonal preconditioning. - -This preconditioning mode can be useful when you don't have approximate -diagonal of Hessian, but you know that your variables are badly scaled -(for example, one variable is in [1,10], and another in [1000,100000]), -and most part of the ill-conditioning comes from different scales of vars. - -In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2), -can greatly improve convergence. - -IMPRTANT: you should set scale of your variables with MinCGSetScale() call -(before or after MinCGSetPrecScale() call). Without knowledge of the scale -of your variables scale-based preconditioner will be just unit matrix. - -INPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetprecscale(const mincgstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgsetprecscale(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool mincgiteration(const mincgstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::mincgiteration(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - - -void mincgoptimize(mincgstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'mincgoptimize()' (func is NULL)", &_alglib_env_state); - while( alglib_impl::mincgiteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needf ) - { - func(state.x, state.f, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.x, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'mincgoptimize' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - -void mincgoptimize(mincgstate &state, - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(grad!=NULL, "ALGLIB: error in 'mincgoptimize()' (grad is NULL)", &_alglib_env_state); - while( alglib_impl::mincgiteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needfg ) - { - grad(state.x, state.f, state.g, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.x, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'mincgoptimize' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - - -/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic gradient. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function at the initial point -(note: future versions may also perform check at the final point) and -compares numerical gradient with analytic one provided by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both gradients and specific components highlighted as -suspicious by the OptGuard. - -The primary OptGuard report can be retrieved with mincgoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with mincgsetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -void mincgoptguardgradient(const mincgstate &state, const double teststep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgoptguardgradient(const_cast(state.c_ptr()), teststep, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) -b) nonsmooth target function (non-C1) - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void mincgoptguardsmoothness(const mincgstate &state, const ae_int_t level, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgoptguardsmoothness(const_cast(state.c_ptr()), level, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) -b) nonsmooth target function (non-C1) - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void mincgoptguardsmoothness(const mincgstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t level; - - level = 1; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgoptguardsmoothness(const_cast(state.c_ptr()), level, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -=== PRIMARY REPORT ======================================================= - -OptGuard performs several checks which are intended to catch common errors -in the implementation of nonlinear function/gradient: -* incorrect analytic gradient -* discontinuous (non-C0) target functions (constraints) -* nonsmooth (non-C1) target functions (constraints) - -Each of these checks is activated with appropriate function: -* mincgoptguardgradient() for gradient verification -* mincgoptguardsmoothness() for C0/C1 checks - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradvidx for specific variable (gradient element) suspected - * rep.badgradxbase, a point where gradient is tested - * rep.badgraduser, user-provided gradient (stored as 2D matrix with - single row in order to make report structure compatible with more - complex optimizers like MinNLC or MinLM) - * rep.badgradnum, reference gradient obtained via numerical - differentiation (stored as 2D matrix with single row in order to make - report structure compatible with more complex optimizers like MinNLC - or MinLM) -* rep.nonc0suspected -* rep.nonc1suspected - -=== ADDITIONAL REPORTS/LOGS ============================================== - -Several different tests are performed to catch C0/C1 errors, you can find -out specific test signaled error by looking to: -* rep.nonc0test0positive, for non-C0 test #0 -* rep.nonc1test0positive, for non-C1 test #0 -* rep.nonc1test1positive, for non-C1 test #1 - -Additional information (including line search logs) can be obtained by -means of: -* mincgoptguardnonc1test0results() -* mincgoptguardnonc1test1results() -which return detailed error reports, specific points where discontinuities -were found, and so on. - -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - generic OptGuard report; more detailed reports can be - retrieved with other functions. - -NOTE: false negatives (nonsmooth problems are not identified as nonsmooth - ones) are possible although unlikely. - - The reason is that you need to make several evaluations around - nonsmoothness in order to accumulate enough information about - function curvature. Say, if you start right from the nonsmooth point, - optimizer simply won't get enough data to understand what is going - wrong before it terminates due to abrupt changes in the derivative. - It is also possible that "unlucky" step will move us to the - termination too quickly. - - Our current approach is to have less than 0.1% false negatives in - our test examples (measured with multiple restarts from random - points), and to have exactly 0% false positives. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void mincgoptguardresults(const mincgstate &state, optguardreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgoptguardresults(const_cast(state.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #0 - -Nonsmoothness (non-C1) test #0 studies function values (not gradient!) -obtained during line searches and monitors behavior of the directional -derivative estimate. - -This test is less powerful than test #1, but it does not depend on the -gradient values and thus it is more robust against artifacts introduced by -numerical differentiation. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #0 "strong" report - lngrep - C1 test #0 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void mincgoptguardnonc1test0results(const mincgstate &state, optguardnonc1test0report &strrep, optguardnonc1test0report &lngrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgoptguardnonc1test0results(const_cast(state.c_ptr()), const_cast(strrep.c_ptr()), const_cast(lngrep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #1 - -Nonsmoothness (non-C1) test #1 studies individual components of the -gradient computed during line search. - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #1 "strong" report - lngrep - C1 test #1 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void mincgoptguardnonc1test1results(const mincgstate &state, optguardnonc1test1report &strrep, optguardnonc1test1report &lngrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgoptguardnonc1test1results(const_cast(state.c_ptr()), const_cast(strrep.c_ptr()), const_cast(lngrep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Conjugate gradient results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report: - * Rep.TerminationType completetion code: - * -8 internal integrity control detected infinite - or NAN values in function/gradient. Abnormal - termination signalled. - * -7 gradient verification failed. - See MinCGSetGradientCheck() for more information. - * 1 relative function improvement is no more than - EpsF. - * 2 relative step is no more than EpsX. - * 4 gradient norm is no more than EpsG - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible, - we return best X found so far - * 8 terminated by user - * Rep.IterationsCount contains iterations count - * NFEV countains number of function calculations - - -- ALGLIB -- - Copyright 20.04.2009 by Bochkanov Sergey -*************************************************************************/ -void mincgresults(const mincgstate &state, real_1d_array &x, mincgreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgresults(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Conjugate gradient results - -Buffered implementation of MinCGResults(), which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 20.04.2009 by Bochkanov Sergey -*************************************************************************/ -void mincgresultsbuf(const mincgstate &state, real_1d_array &x, mincgreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgresultsbuf(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine restarts CG algorithm from new point. All optimization -parameters are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure used to store algorithm state. - X - new starting point. - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgrestartfrom(const mincgstate &state, const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgrestartfrom(const_cast(state.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void mincgrequesttermination(const mincgstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mincgrequesttermination(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_MINLM) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Levenberg-Marquardt optimizer. - -This structure should be created using one of the MinLMCreate???() -functions. You should not access its fields directly; use ALGLIB functions -to work with it. -*************************************************************************/ -_minlmstate_owner::_minlmstate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minlmstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::minlmstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlmstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minlmstate)); - alglib_impl::_minlmstate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_minlmstate_owner::_minlmstate_owner(const _minlmstate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minlmstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlmstate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::minlmstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlmstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minlmstate)); - alglib_impl::_minlmstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_minlmstate_owner& _minlmstate_owner::operator=(const _minlmstate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minlmstate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlmstate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_minlmstate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::minlmstate)); - alglib_impl::_minlmstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_minlmstate_owner::~_minlmstate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_minlmstate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::minlmstate* _minlmstate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::minlmstate* _minlmstate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -minlmstate::minlmstate() : _minlmstate_owner() ,needf(p_struct->needf),needfg(p_struct->needfg),needfgh(p_struct->needfgh),needfi(p_struct->needfi),needfij(p_struct->needfij),xupdated(p_struct->xupdated),f(p_struct->f),fi(&p_struct->fi),g(&p_struct->g),h(&p_struct->h),j(&p_struct->j),x(&p_struct->x) -{ -} - -minlmstate::minlmstate(const minlmstate &rhs):_minlmstate_owner(rhs) ,needf(p_struct->needf),needfg(p_struct->needfg),needfgh(p_struct->needfgh),needfi(p_struct->needfi),needfij(p_struct->needfij),xupdated(p_struct->xupdated),f(p_struct->f),fi(&p_struct->fi),g(&p_struct->g),h(&p_struct->h),j(&p_struct->j),x(&p_struct->x) -{ -} - -minlmstate& minlmstate::operator=(const minlmstate &rhs) -{ - if( this==&rhs ) - return *this; - _minlmstate_owner::operator=(rhs); - return *this; -} - -minlmstate::~minlmstate() -{ -} - - -/************************************************************************* -Optimization report, filled by MinLMResults() function - -FIELDS: -* TerminationType, completetion code: - * -8 optimizer detected NAN/INF values either in the function itself, - or in its Jacobian - * -5 inappropriate solver was used: - * solver created with minlmcreatefgh() used on problem with - general linear constraints (set with minlmsetlc() call). - * -3 constraints are inconsistent - * 2 relative step is no more than EpsX. - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible - * 8 terminated by user who called MinLMRequestTermination(). - X contains point which was "current accepted" when termination - request was submitted. -* IterationsCount, contains iterations count -* NFunc, number of function calculations -* NJac, number of Jacobi matrix calculations -* NGrad, number of gradient calculations -* NHess, number of Hessian calculations -* NCholesky, number of Cholesky decomposition calculations -*************************************************************************/ -_minlmreport_owner::_minlmreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minlmreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::minlmreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlmreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minlmreport)); - alglib_impl::_minlmreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_minlmreport_owner::_minlmreport_owner(const _minlmreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_minlmreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlmreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::minlmreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlmreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::minlmreport)); - alglib_impl::_minlmreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_minlmreport_owner& _minlmreport_owner::operator=(const _minlmreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minlmreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlmreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_minlmreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::minlmreport)); - alglib_impl::_minlmreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_minlmreport_owner::~_minlmreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_minlmreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::minlmreport* _minlmreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::minlmreport* _minlmreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -minlmreport::minlmreport() : _minlmreport_owner() ,iterationscount(p_struct->iterationscount),terminationtype(p_struct->terminationtype),nfunc(p_struct->nfunc),njac(p_struct->njac),ngrad(p_struct->ngrad),nhess(p_struct->nhess),ncholesky(p_struct->ncholesky) -{ -} - -minlmreport::minlmreport(const minlmreport &rhs):_minlmreport_owner(rhs) ,iterationscount(p_struct->iterationscount),terminationtype(p_struct->terminationtype),nfunc(p_struct->nfunc),njac(p_struct->njac),ngrad(p_struct->ngrad),nhess(p_struct->nhess),ncholesky(p_struct->ncholesky) -{ -} - -minlmreport& minlmreport::operator=(const minlmreport &rhs) -{ - if( this==&rhs ) - return *this; - _minlmreport_owner::operator=(rhs); - return *this; -} - -minlmreport::~minlmreport() -{ -} - -/************************************************************************* - IMPROVED LEVENBERG-MARQUARDT METHOD FOR - NON-LINEAR LEAST SQUARES OPTIMIZATION - -DESCRIPTION: -This function is used to find minimum of function which is represented as -sum of squares: - F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1]) -using value of function vector f[] and Jacobian of f[]. - - -REQUIREMENTS: -This algorithm will request following information during its operation: - -* function vector f[] at given point X -* function vector f[] and Jacobian of f[] (simultaneously) at given point - -There are several overloaded versions of MinLMOptimize() function which -correspond to different LM-like optimization algorithms provided by this -unit. You should choose version which accepts fvec() and jac() callbacks. -First one is used to calculate f[] at given point, second one calculates -f[] and Jacobian df[i]/dx[j]. - -You can try to initialize MinLMState structure with VJ function and then -use incorrect version of MinLMOptimize() (for example, version which -works with general form function and does not provide Jacobian), but it -will lead to exception being thrown after first attempt to calculate -Jacobian. - - -USAGE: -1. User initializes algorithm state with MinLMCreateVJ() call -2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and - other functions -3. User calls MinLMOptimize() function which takes algorithm state and - callback functions. -4. User calls MinLMResults() to get solution -5. Optionally, user may call MinLMRestartFrom() to solve another problem - with same N/M but another starting point and/or another function. - MinLMRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - dimension, N>1 - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - M - number of functions f[i] - X - initial solution, array[0..N-1] - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. you may tune stopping conditions with MinLMSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use MinLMSetStpMax() function to bound algorithm's steps. - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmcreatevj(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmcreatevj(n, m, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* - IMPROVED LEVENBERG-MARQUARDT METHOD FOR - NON-LINEAR LEAST SQUARES OPTIMIZATION - -DESCRIPTION: -This function is used to find minimum of function which is represented as -sum of squares: - F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1]) -using value of function vector f[] and Jacobian of f[]. - - -REQUIREMENTS: -This algorithm will request following information during its operation: - -* function vector f[] at given point X -* function vector f[] and Jacobian of f[] (simultaneously) at given point - -There are several overloaded versions of MinLMOptimize() function which -correspond to different LM-like optimization algorithms provided by this -unit. You should choose version which accepts fvec() and jac() callbacks. -First one is used to calculate f[] at given point, second one calculates -f[] and Jacobian df[i]/dx[j]. - -You can try to initialize MinLMState structure with VJ function and then -use incorrect version of MinLMOptimize() (for example, version which -works with general form function and does not provide Jacobian), but it -will lead to exception being thrown after first attempt to calculate -Jacobian. - - -USAGE: -1. User initializes algorithm state with MinLMCreateVJ() call -2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and - other functions -3. User calls MinLMOptimize() function which takes algorithm state and - callback functions. -4. User calls MinLMResults() to get solution -5. Optionally, user may call MinLMRestartFrom() to solve another problem - with same N/M but another starting point and/or another function. - MinLMRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - dimension, N>1 - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - M - number of functions f[i] - X - initial solution, array[0..N-1] - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. you may tune stopping conditions with MinLMSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use MinLMSetStpMax() function to bound algorithm's steps. - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minlmcreatevj(const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmcreatevj(n, m, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* - IMPROVED LEVENBERG-MARQUARDT METHOD FOR - NON-LINEAR LEAST SQUARES OPTIMIZATION - -DESCRIPTION: -This function is used to find minimum of function which is represented as -sum of squares: - F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1]) -using value of function vector f[] only. Finite differences are used to -calculate Jacobian. - - -REQUIREMENTS: -This algorithm will request following information during its operation: -* function vector f[] at given point X - -There are several overloaded versions of MinLMOptimize() function which -correspond to different LM-like optimization algorithms provided by this -unit. You should choose version which accepts fvec() callback. - -You can try to initialize MinLMState structure with VJ function and then -use incorrect version of MinLMOptimize() (for example, version which -works with general form function and does not accept function vector), but -it will lead to exception being thrown after first attempt to calculate -Jacobian. - - -USAGE: -1. User initializes algorithm state with MinLMCreateV() call -2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and - other functions -3. User calls MinLMOptimize() function which takes algorithm state and - callback functions. -4. User calls MinLMResults() to get solution -5. Optionally, user may call MinLMRestartFrom() to solve another problem - with same N/M but another starting point and/or another function. - MinLMRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - dimension, N>1 - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - M - number of functions f[i] - X - initial solution, array[0..N-1] - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -See also MinLMIteration, MinLMResults. - -NOTES: -1. you may tune stopping conditions with MinLMSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use MinLMSetStpMax() function to bound algorithm's steps. - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmcreatev(const ae_int_t n, const ae_int_t m, const real_1d_array &x, const double diffstep, minlmstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmcreatev(n, m, const_cast(x.c_ptr()), diffstep, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* - IMPROVED LEVENBERG-MARQUARDT METHOD FOR - NON-LINEAR LEAST SQUARES OPTIMIZATION - -DESCRIPTION: -This function is used to find minimum of function which is represented as -sum of squares: - F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1]) -using value of function vector f[] only. Finite differences are used to -calculate Jacobian. - - -REQUIREMENTS: -This algorithm will request following information during its operation: -* function vector f[] at given point X - -There are several overloaded versions of MinLMOptimize() function which -correspond to different LM-like optimization algorithms provided by this -unit. You should choose version which accepts fvec() callback. - -You can try to initialize MinLMState structure with VJ function and then -use incorrect version of MinLMOptimize() (for example, version which -works with general form function and does not accept function vector), but -it will lead to exception being thrown after first attempt to calculate -Jacobian. - - -USAGE: -1. User initializes algorithm state with MinLMCreateV() call -2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and - other functions -3. User calls MinLMOptimize() function which takes algorithm state and - callback functions. -4. User calls MinLMResults() to get solution -5. Optionally, user may call MinLMRestartFrom() to solve another problem - with same N/M but another starting point and/or another function. - MinLMRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - dimension, N>1 - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - M - number of functions f[i] - X - initial solution, array[0..N-1] - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -See also MinLMIteration, MinLMResults. - -NOTES: -1. you may tune stopping conditions with MinLMSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use MinLMSetStpMax() function to bound algorithm's steps. - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minlmcreatev(const ae_int_t m, const real_1d_array &x, const double diffstep, minlmstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmcreatev(n, m, const_cast(x.c_ptr()), diffstep, const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* - LEVENBERG-MARQUARDT-LIKE METHOD FOR NON-LINEAR OPTIMIZATION - -DESCRIPTION: -This function is used to find minimum of general form (not "sum-of- --squares") function - F = F(x[0], ..., x[n-1]) -using its gradient and Hessian. Levenberg-Marquardt modification with -L-BFGS pre-optimization and internal pre-conditioned L-BFGS optimization -after each Levenberg-Marquardt step is used. - - -REQUIREMENTS: -This algorithm will request following information during its operation: - -* function value F at given point X -* F and gradient G (simultaneously) at given point X -* F, G and Hessian H (simultaneously) at given point X - -There are several overloaded versions of MinLMOptimize() function which -correspond to different LM-like optimization algorithms provided by this -unit. You should choose version which accepts func(), grad() and hess() -function pointers. First pointer is used to calculate F at given point, -second one calculates F(x) and grad F(x), third one calculates F(x), -grad F(x), hess F(x). - -You can try to initialize MinLMState structure with FGH-function and then -use incorrect version of MinLMOptimize() (for example, version which does -not provide Hessian matrix), but it will lead to exception being thrown -after first attempt to calculate Hessian. - - -USAGE: -1. User initializes algorithm state with MinLMCreateFGH() call -2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and - other functions -3. User calls MinLMOptimize() function which takes algorithm state and - pointers (delegates, etc.) to callback functions. -4. User calls MinLMResults() to get solution -5. Optionally, user may call MinLMRestartFrom() to solve another problem - with same N but another starting point and/or another function. - MinLMRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - dimension, N>1 - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - initial solution, array[0..N-1] - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. you may tune stopping conditions with MinLMSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use MinLMSetStpMax() function to bound algorithm's steps. - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmcreatefgh(const ae_int_t n, const real_1d_array &x, minlmstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmcreatefgh(n, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* - LEVENBERG-MARQUARDT-LIKE METHOD FOR NON-LINEAR OPTIMIZATION - -DESCRIPTION: -This function is used to find minimum of general form (not "sum-of- --squares") function - F = F(x[0], ..., x[n-1]) -using its gradient and Hessian. Levenberg-Marquardt modification with -L-BFGS pre-optimization and internal pre-conditioned L-BFGS optimization -after each Levenberg-Marquardt step is used. - - -REQUIREMENTS: -This algorithm will request following information during its operation: - -* function value F at given point X -* F and gradient G (simultaneously) at given point X -* F, G and Hessian H (simultaneously) at given point X - -There are several overloaded versions of MinLMOptimize() function which -correspond to different LM-like optimization algorithms provided by this -unit. You should choose version which accepts func(), grad() and hess() -function pointers. First pointer is used to calculate F at given point, -second one calculates F(x) and grad F(x), third one calculates F(x), -grad F(x), hess F(x). - -You can try to initialize MinLMState structure with FGH-function and then -use incorrect version of MinLMOptimize() (for example, version which does -not provide Hessian matrix), but it will lead to exception being thrown -after first attempt to calculate Hessian. - - -USAGE: -1. User initializes algorithm state with MinLMCreateFGH() call -2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and - other functions -3. User calls MinLMOptimize() function which takes algorithm state and - pointers (delegates, etc.) to callback functions. -4. User calls MinLMResults() to get solution -5. Optionally, user may call MinLMRestartFrom() to solve another problem - with same N but another starting point and/or another function. - MinLMRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - dimension, N>1 - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - initial solution, array[0..N-1] - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. you may tune stopping conditions with MinLMSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use MinLMSetStpMax() function to bound algorithm's steps. - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minlmcreatefgh(const real_1d_array &x, minlmstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmcreatefgh(n, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets stopping conditions for Levenberg-Marquardt optimization -algorithm. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - ste pvector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinLMSetScale() - Recommended values: 1E-9 ... 1E-12. - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. Only Levenberg-Marquardt - iterations are counted (L-BFGS/CG iterations are NOT - counted because their cost is very low compared to that of - LM). - -Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic -stopping criterion selection (small EpsX). - -NOTE: it is not recommended to set large EpsX (say, 0.001). Because LM is - a second-order method, it performs very precise steps anyway. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlmsetcond(const minlmstate &state, const double epsx, const ae_int_t maxits, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmsetcond(const_cast(state.c_ptr()), epsx, maxits, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinLMOptimize(). Both Levenberg-Marquardt and internal L-BFGS -iterations are reported. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlmsetxrep(const minlmstate &state, const bool needxrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmsetxrep(const_cast(state.c_ptr()), needxrep, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which leads to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - -NOTE: non-zero StpMax leads to moderate performance degradation because -intermediate step of preconditioned L-BFGS optimization is incompatible -with limits on step size. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlmsetstpmax(const minlmstate &state, const double stpmax, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmsetstpmax(const_cast(state.c_ptr()), stpmax, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets scaling coefficients for LM optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Generally, scale is NOT considered to be a form of preconditioner. But LM -optimizer is unique in that it uses scaling matrix both in the stopping -condition tests and as Marquardt damping factor. - -Proper scaling is very important for the algorithm performance. It is less -important for the quality of results, but still has some influence (it is -easier to converge when variables are properly scaled, so premature -stopping is possible when very badly scalled variables are combined with -relaxed stopping conditions). - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minlmsetscale(const minlmstate &state, const real_1d_array &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmsetscale(const_cast(state.c_ptr()), const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets boundary constraints for LM optimizer - -Boundary constraints are inactive by default (after initial creation). -They are preserved until explicitly turned off with another SetBC() call. - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF (latter is recommended because - it will allow solver to use better algorithm). - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF (latter is recommended because - it will allow solver to use better algorithm). - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - -NOTE 2: this solver has following useful properties: -* bound constraints are always satisfied exactly -* function is evaluated only INSIDE area specified by bound constraints - or at its boundary - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minlmsetbc(const minlmstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmsetbc(const_cast(state.c_ptr()), const_cast(bndl.c_ptr()), const_cast(bndu.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets general linear constraints for LM optimizer - -Linear constraints are inactive by default (after initial creation). They -are preserved until explicitly turned off with another minlmsetlc() call. - -INPUT PARAMETERS: - State - structure stores algorithm state - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -IMPORTANT: if you have linear constraints, it is strongly recommended to - set scale of variables with minlmsetscale(). QP solver which is - used to calculate linearly constrained steps heavily relies on - good scaling of input problems. - -IMPORTANT: solvers created with minlmcreatefgh() do not support linear - constraints. - -NOTE: linear (non-bound) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations. - -NOTE: general linear constraints add significant overhead to solution - process. Although solver performs roughly same amount of iterations - (when compared with similar box-only constrained problem), each - iteration now involves solution of linearly constrained QP - subproblem, which requires ~3-5 times more Cholesky decompositions. - Thus, if you can reformulate your problem in such way this it has - only box constraints, it may be beneficial to do so. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minlmsetlc(const minlmstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmsetlc(const_cast(state.c_ptr()), const_cast(c.c_ptr()), const_cast(ct.c_ptr()), k, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets general linear constraints for LM optimizer - -Linear constraints are inactive by default (after initial creation). They -are preserved until explicitly turned off with another minlmsetlc() call. - -INPUT PARAMETERS: - State - structure stores algorithm state - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -IMPORTANT: if you have linear constraints, it is strongly recommended to - set scale of variables with minlmsetscale(). QP solver which is - used to calculate linearly constrained steps heavily relies on - good scaling of input problems. - -IMPORTANT: solvers created with minlmcreatefgh() do not support linear - constraints. - -NOTE: linear (non-bound) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations. - -NOTE: general linear constraints add significant overhead to solution - process. Although solver performs roughly same amount of iterations - (when compared with similar box-only constrained problem), each - iteration now involves solution of linearly constrained QP - subproblem, which requires ~3-5 times more Cholesky decompositions. - Thus, if you can reformulate your problem in such way this it has - only box constraints, it may be beneficial to do so. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minlmsetlc(const minlmstate &state, const real_2d_array &c, const integer_1d_array &ct, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t k; - if( (c.rows()!=ct.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'minlmsetlc': looks like one of arguments has wrong size"); - k = c.rows(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmsetlc(const_cast(state.c_ptr()), const_cast(c.c_ptr()), const_cast(ct.c_ptr()), k, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function is used to change acceleration settings - -You can choose between three acceleration strategies: -* AccType=0, no acceleration. -* AccType=1, secant updates are used to update quadratic model after each - iteration. After fixed number of iterations (or after model breakdown) - we recalculate quadratic model using analytic Jacobian or finite - differences. Number of secant-based iterations depends on optimization - settings: about 3 iterations - when we have analytic Jacobian, up to 2*N - iterations - when we use finite differences to calculate Jacobian. - -AccType=1 is recommended when Jacobian calculation cost is prohibitively -high (several Mx1 function vector calculations followed by several NxN -Cholesky factorizations are faster than calculation of one M*N Jacobian). -It should also be used when we have no Jacobian, because finite difference -approximation takes too much time to compute. - -Table below list optimization protocols (XYZ protocol corresponds to -MinLMCreateXYZ) and acceleration types they support (and use by default). - -ACCELERATION TYPES SUPPORTED BY OPTIMIZATION PROTOCOLS: - -protocol 0 1 comment -V + + -VJ + + -FGH + - -DEFAULT VALUES: - -protocol 0 1 comment -V x without acceleration it is so slooooooooow -VJ x -FGH x - -NOTE: this function should be called before optimization. Attempt to call -it during algorithm iterations may result in unexpected behavior. - -NOTE: attempt to call this function with unsupported protocol/acceleration -combination will result in exception being thrown. - - -- ALGLIB -- - Copyright 14.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlmsetacctype(const minlmstate &state, const ae_int_t acctype, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmsetacctype(const_cast(state.c_ptr()), acctype, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool minlmiteration(const minlmstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::minlmiteration(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - - -void minlmoptimize(minlmstate &state, - void (*fvec)(const real_1d_array &x, real_1d_array &fi, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(fvec!=NULL, "ALGLIB: error in 'minlmoptimize()' (fvec is NULL)", &_alglib_env_state); - while( alglib_impl::minlmiteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needfi ) - { - fvec(state.x, state.fi, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.x, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - -void minlmoptimize(minlmstate &state, - void (*fvec)(const real_1d_array &x, real_1d_array &fi, void *ptr), - void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(fvec!=NULL, "ALGLIB: error in 'minlmoptimize()' (fvec is NULL)", &_alglib_env_state); - alglib_impl::ae_assert(jac!=NULL, "ALGLIB: error in 'minlmoptimize()' (jac is NULL)", &_alglib_env_state); - while( alglib_impl::minlmiteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needfi ) - { - fvec(state.x, state.fi, ptr); - continue; - } - if( state.needfij ) - { - jac(state.x, state.fi, state.j, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.x, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - -void minlmoptimize(minlmstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*hess)(const real_1d_array &x, double &func, real_1d_array &grad, real_2d_array &hess, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'minlmoptimize()' (func is NULL)", &_alglib_env_state); - alglib_impl::ae_assert(grad!=NULL, "ALGLIB: error in 'minlmoptimize()' (grad is NULL)", &_alglib_env_state); - alglib_impl::ae_assert(hess!=NULL, "ALGLIB: error in 'minlmoptimize()' (hess is NULL)", &_alglib_env_state); - while( alglib_impl::minlmiteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needf ) - { - func(state.x, state.f, ptr); - continue; - } - if( state.needfg ) - { - grad(state.x, state.f, state.g, ptr); - continue; - } - if( state.needfgh ) - { - hess(state.x, state.f, state.g, state.h, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.x, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - -void minlmoptimize(minlmstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'minlmoptimize()' (func is NULL)", &_alglib_env_state); - alglib_impl::ae_assert(jac!=NULL, "ALGLIB: error in 'minlmoptimize()' (jac is NULL)", &_alglib_env_state); - while( alglib_impl::minlmiteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needf ) - { - func(state.x, state.f, ptr); - continue; - } - if( state.needfij ) - { - jac(state.x, state.fi, state.j, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.x, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - -void minlmoptimize(minlmstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'minlmoptimize()' (func is NULL)", &_alglib_env_state); - alglib_impl::ae_assert(grad!=NULL, "ALGLIB: error in 'minlmoptimize()' (grad is NULL)", &_alglib_env_state); - alglib_impl::ae_assert(jac!=NULL, "ALGLIB: error in 'minlmoptimize()' (jac is NULL)", &_alglib_env_state); - while( alglib_impl::minlmiteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needf ) - { - func(state.x, state.f, ptr); - continue; - } - if( state.needfg ) - { - grad(state.x, state.f, state.g, ptr); - continue; - } - if( state.needfij ) - { - jac(state.x, state.fi, state.j, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.x, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - - -/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic Jacobian. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function vector at the initial -point (note: future versions may also perform check at the final point) -and compares numerical Jacobian with analytic one provided by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both Jacobians, and specific components highlighted as -suspicious by the OptGuard. - -The OptGuard report can be retrieved with minlmoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with minlmsetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minlmoptguardgradient(const minlmstate &state, const double teststep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmoptguardgradient(const_cast(state.c_ptr()), teststep, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -OptGuard checks analytic Jacobian against reference value obtained by -numerical differentiation with user-specified step. - -NOTE: other optimizers perform additional OptGuard checks for things like - C0/C1-continuity violations. However, LM optimizer can check only - for incorrect Jacobian. - - The reason is that unlike line search methods LM optimizer does not - perform extensive evaluations along the line. Thus, we simply do not - have enough data to catch C0/C1-violations. - -This check is activated with minlmoptguardgradient() function. - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradfidx for specific function (Jacobian row) suspected - * rep.badgradvidx for specific variable (Jacobian column) suspected - * rep.badgradxbase, a point where gradient/Jacobian is tested - * rep.badgraduser, user-provided gradient/Jacobian - * rep.badgradnum, reference gradient/Jacobian obtained via numerical - differentiation - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - OptGuard report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minlmoptguardresults(const minlmstate &state, optguardreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmoptguardresults(const_cast(state.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Levenberg-Marquardt algorithm results - -NOTE: if you activated OptGuard integrity checking functionality and want - to get OptGuard report, it can be retrieved with the help of - minlmoptguardresults() function. - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report; includes termination codes and - additional information. Termination codes are listed below, - see comments for this structure for more info. - Termination code is stored in rep.terminationtype field: - * -8 optimizer detected NAN/INF values either in the - function itself, or in its Jacobian - * -3 constraints are inconsistent - * 2 relative step is no more than EpsX. - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible - * 8 terminated by user who called minlmrequesttermination(). - X contains point which was "current accepted" when - termination request was submitted. - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmresults(const minlmstate &state, real_1d_array &x, minlmreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmresults(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Levenberg-Marquardt algorithm results - -Buffered implementation of MinLMResults(), which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmresultsbuf(const minlmstate &state, real_1d_array &x, minlmreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmresultsbuf(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine restarts LM algorithm from new point. All optimization -parameters are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure used for reverse communication previously - allocated with MinLMCreateXXX call. - X - new starting point. - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -void minlmrestartfrom(const minlmstate &state, const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmrestartfrom(const_cast(state.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void minlmrequesttermination(const minlmstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmrequesttermination(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is obsolete function. - -Since ALGLIB 3.3 it is equivalent to MinLMCreateVJ(). - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmcreatevgj(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmcreatevgj(n, m, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is obsolete function. - -Since ALGLIB 3.3 it is equivalent to MinLMCreateVJ(). - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minlmcreatevgj(const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmcreatevgj(n, m, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This is obsolete function. - -Since ALGLIB 3.3 it is equivalent to MinLMCreateFJ(). - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmcreatefgj(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmcreatefgj(n, m, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This is obsolete function. - -Since ALGLIB 3.3 it is equivalent to MinLMCreateFJ(). - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minlmcreatefgj(const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmcreatefgj(n, m, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function is considered obsolete since ALGLIB 3.1.0 and is present for -backward compatibility only. We recommend to use MinLMCreateVJ, which -provides similar, but more consistent and feature-rich interface. - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmcreatefj(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmcreatefj(n, m, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is considered obsolete since ALGLIB 3.1.0 and is present for -backward compatibility only. We recommend to use MinLMCreateVJ, which -provides similar, but more consistent and feature-rich interface. - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void minlmcreatefj(const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::minlmcreatefj(n, m, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF COMPUTATIONAL CORE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_CQMODELS) || !defined(AE_PARTIAL_BUILD) -static ae_int_t cqmodels_newtonrefinementits = 3; -static ae_bool cqmodels_cqmrebuild(convexquadraticmodel* s, - ae_state *_state); -static void cqmodels_cqmsolveea(convexquadraticmodel* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* tmp, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_OPTGUARDAPI) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_OPTSERV) || !defined(AE_PARTIAL_BUILD) -static double optserv_ognoiselevelf = 1.0E2*ae_machineepsilon; -static double optserv_ognoiselevelg = 1.0E4*ae_machineepsilon; -static double optserv_ogminrating0 = 50.0; -static double optserv_ogminrating1 = 50.0; -static double optserv_feasibilityerror(/* Real */ ae_matrix* ce, - /* Real */ ae_vector* x, - ae_int_t nmain, - ae_int_t nslack, - ae_int_t k, - /* Real */ ae_vector* tmp0, - ae_state *_state); -static void optserv_feasibilityerrorgrad(/* Real */ ae_matrix* ce, - /* Real */ ae_vector* x, - ae_int_t nmain, - ae_int_t nslack, - ae_int_t k, - double* err, - /* Real */ ae_vector* grad, - /* Real */ ae_vector* tmp0, - ae_state *_state); -static void optserv_testc0continuity(double f0, - double f1, - double f2, - double f3, - double noise0, - double noise1, - double noise2, - double noise3, - double delta0, - double delta1, - double delta2, - ae_bool applyspecialcorrection, - double* rating, - double* lipschitz, - ae_state *_state); -static void optserv_c1continuitytest0(smoothnessmonitor* monitor, - ae_int_t funcidx, - ae_int_t stpidx, - ae_int_t sortedcnt, - ae_state *_state); -static void optserv_c1continuitytest1(smoothnessmonitor* monitor, - ae_int_t funcidx, - ae_int_t stpidx, - ae_int_t sortedcnt, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_SNNLS) || !defined(AE_PARTIAL_BUILD) -static void snnls_funcgradu(snnlssolver* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* r, - /* Real */ ae_vector* g, - double* f, - ae_state *_state); -static void snnls_func(snnlssolver* s, - /* Real */ ae_vector* x, - double* f, - ae_state *_state); -static void snnls_trdprepare(snnlssolver* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* diag, - double lambdav, - /* Real */ ae_vector* trdd, - /* Real */ ae_matrix* trda, - /* Real */ ae_vector* tmp0, - /* Real */ ae_vector* tmp1, - /* Real */ ae_vector* tmp2, - /* Real */ ae_matrix* tmplq, - ae_state *_state); -static void snnls_trdsolve(/* Real */ ae_vector* trdd, - /* Real */ ae_matrix* trda, - ae_int_t ns, - ae_int_t nd, - /* Real */ ae_vector* d, - ae_state *_state); -static void snnls_trdfixvariable(/* Real */ ae_vector* trdd, - /* Real */ ae_matrix* trda, - ae_int_t ns, - ae_int_t nd, - ae_int_t idx, - /* Real */ ae_vector* tmp, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_SACTIVESETS) || !defined(AE_PARTIAL_BUILD) -static ae_int_t sactivesets_maxbasisage = 5; -static double sactivesets_maxbasisdecay = 0.01; -static double sactivesets_minnormseparation = 0.25; -static void sactivesets_constraineddescent(sactiveset* state, - /* Real */ ae_vector* g, - /* Real */ ae_vector* h, - /* Real */ ae_matrix* ha, - ae_bool normalize, - /* Real */ ae_vector* d, - ae_state *_state); -static void sactivesets_reactivateconstraints(sactiveset* state, - /* Real */ ae_vector* gc, - /* Real */ ae_vector* h, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_QQPSOLVER) || !defined(AE_PARTIAL_BUILD) -static ae_int_t qqpsolver_quickqprestartcg = 50; -static double qqpsolver_regz = 1.0E-9; -static double qqpsolver_projectedtargetfunction(qqpbuffers* sstate, - /* Real */ ae_vector* x, - /* Real */ ae_vector* d, - double stp, - /* Real */ ae_vector* tmp0, - /* Real */ ae_vector* tmp1, - ae_state *_state); -static void qqpsolver_targetgradient(qqpbuffers* sstate, - /* Real */ ae_vector* x, - /* Real */ ae_vector* g, - ae_state *_state); -static void qqpsolver_quadraticmodel(qqpbuffers* sstate, - /* Real */ ae_vector* x, - /* Real */ ae_vector* d, - /* Real */ ae_vector* g, - double* d1, - ae_int_t* d1est, - double* d2, - ae_int_t* d2est, - /* Real */ ae_vector* tmp0, - ae_state *_state); -static void qqpsolver_findbeststepandmove(qqpbuffers* sstate, - sactiveset* sas, - /* Real */ ae_vector* d, - double stp, - ae_bool needact, - ae_int_t cidx, - double cval, - /* Real */ ae_vector* addsteps, - ae_int_t addstepscnt, - /* Boolean */ ae_vector* activated, - /* Real */ ae_vector* tmp0, - /* Real */ ae_vector* tmp1, - ae_state *_state); -static ae_bool qqpsolver_cnewtonbuild(qqpbuffers* sstate, - ae_int_t sparsesolver, - ae_int_t* ncholesky, - ae_state *_state); -static ae_bool qqpsolver_cnewtonupdate(qqpbuffers* sstate, - qqpsettings* settings, - ae_int_t* ncupdates, - ae_state *_state); -static ae_bool qqpsolver_cnewtonstep(qqpbuffers* sstate, - qqpsettings* settings, - /* Real */ ae_vector* gc, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_MINLBFGS) || !defined(AE_PARTIAL_BUILD) -static double minlbfgs_gtol = 0.4; -static void minlbfgs_clearrequestfields(minlbfgsstate* state, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_LPQPSERV) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_VIPMSOLVER) || !defined(AE_PARTIAL_BUILD) -static ae_int_t vipmsolver_maxipmits = 200; -static double vipmsolver_initslackval = 100.0; -static double vipmsolver_steplengthdecay = 0.95; -static double vipmsolver_stagnationdelta = 0.99999; -static double vipmsolver_primalinfeasible1 = 1.0E-3; -static double vipmsolver_dualinfeasible1 = 1.0E-3; -static double vipmsolver_bigy = 1.0E8; -static double vipmsolver_ygrowth = 1.0E6; -static ae_int_t vipmsolver_itersfortoostringentcond = 25; -static ae_int_t vipmsolver_minitersbeforedroppingbounds = 3; -static ae_int_t vipmsolver_minitersbeforeinfeasible = 3; -static ae_int_t vipmsolver_minitersbeforestagnation = 5; -static ae_int_t vipmsolver_minitersbeforeeworststagnation = 50; -static ae_int_t vipmsolver_primalstagnationlen = 5; -static ae_int_t vipmsolver_dualstagnationlen = 7; -static double vipmsolver_bigconstrxtol = 1.0E-5; -static double vipmsolver_bigconstrmag = 1.0E3; -static double vipmsolver_minitersbeforesafeguards = 5; -static double vipmsolver_badsteplength = 1.0E-3; -static void vipmsolver_varsinitbyzero(vipmvars* vstate, - ae_int_t n, - ae_int_t m, - ae_state *_state); -static void vipmsolver_varsinitfrom(vipmvars* vstate, - vipmvars* vsrc, - ae_state *_state); -static void vipmsolver_varsaddstep(vipmvars* vstate, - vipmvars* vdir, - double stpp, - double stpd, - ae_state *_state); -static double vipmsolver_varscomputecomplementaritygap(vipmvars* vstate, - ae_state *_state); -static double vipmsolver_varscomputemu(vipmvars* vstate, ae_state *_state); -static void vipmsolver_vipminit(vipmstate* state, - /* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - ae_int_t n, - ae_int_t nmain, - ae_int_t ftype, - ae_state *_state); -static double vipmsolver_vipmtarget(vipmstate* state, - /* Real */ ae_vector* x, - ae_state *_state); -static void vipmsolver_multiplygeax(vipmstate* state, - double alpha, - /* Real */ ae_vector* x, - ae_int_t offsx, - double beta, - /* Real */ ae_vector* y, - ae_int_t offsax, - ae_state *_state); -static void vipmsolver_multiplygeatx(vipmstate* state, - double alpha, - /* Real */ ae_vector* x, - ae_int_t offsx, - double beta, - /* Real */ ae_vector* y, - ae_int_t offsy, - ae_state *_state); -static void vipmsolver_multiplyhx(vipmstate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* hx, - ae_state *_state); -static void vipmsolver_vipmmultiply(vipmstate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* hx, - /* Real */ ae_vector* ax, - /* Real */ ae_vector* aty, - ae_state *_state); -static void vipmsolver_vipmpowerup(vipmstate* state, - double regfree, - ae_state *_state); -static ae_bool vipmsolver_vipmfactorize(vipmstate* state, - double alpha0, - /* Real */ ae_vector* d, - double beta0, - /* Real */ ae_vector* e, - double alpha11, - double beta11, - double modeps, - double dampeps, - ae_state *_state); -static void vipmsolver_solvereducedkktsystem(vipmstate* state, - /* Real */ ae_vector* deltaxy, - ae_state *_state); -static ae_bool vipmsolver_vipmprecomputenewtonfactorization(vipmstate* state, - vipmvars* v0, - double regeps, - double modeps, - double dampeps, - double dampfree, - ae_state *_state); -static void vipmsolver_solvekktsystem(vipmstate* state, - vipmrighthandside* rhs, - vipmvars* sol, - ae_state *_state); -static ae_bool vipmsolver_vipmcomputestepdirection(vipmstate* state, - vipmvars* v0, - double muestimate, - vipmvars* vdestimate, - vipmvars* vdresult, - double reg, - ae_bool isdampepslarge, - ae_state *_state); -static void vipmsolver_vipmcomputesteplength(vipmstate* state, - vipmvars* v0, - vipmvars* vs, - double stepdecay, - double* alphap, - double* alphad, - ae_state *_state); -static void vipmsolver_vipmperformstep(vipmstate* state, - double alphap, - double alphad, - ae_state *_state); -static void vipmsolver_computeerrors(vipmstate* state, - double* errp2, - double* errd2, - double* errpinf, - double* errdinf, - double* egap, - ae_state *_state); -static void vipmsolver_runintegritychecks(vipmstate* state, - vipmvars* v0, - vipmvars* vd, - double alphap, - double alphad, - ae_state *_state); -static void vipmsolver_traceprogress(vipmstate* state, - double mu, - double muaff, - double sigma, - double alphap, - double alphad, - ae_state *_state); -static void vipmsolver_rhscompute(vipmstate* state, - vipmvars* v0, - double muestimate, - vipmvars* direstimate, - vipmrighthandside* rhs, - double reg, - ae_state *_state); -static void vipmsolver_rhssubtract(vipmstate* state, - vipmrighthandside* rhs, - vipmvars* v0, - vipmvars* vdcandidate, - double reg, - ae_state *_state); -static double vipmsolver_rhsprimal2(vipmrighthandside* rhs, - ae_int_t n, - ae_int_t m, - ae_state *_state); -static double vipmsolver_rhsdual2(vipmrighthandside* rhs, - ae_int_t n, - ae_int_t m, - ae_state *_state); -static double vipmsolver_rhsprimalinf(vipmrighthandside* rhs, - ae_int_t n, - ae_int_t m, - ae_state *_state); -static double vipmsolver_rhsdualinf(vipmrighthandside* rhs, - ae_int_t n, - ae_int_t m, - ae_state *_state); -static double vipmsolver_rhscompl2(vipmrighthandside* rhs, - ae_int_t n, - ae_int_t m, - ae_state *_state); -static double vipmsolver_minnz(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state); -static double vipmsolver_minprodnz(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_state *_state); -static double vipmsolver_maxprodnz(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_NLCSQP) || !defined(AE_PARTIAL_BUILD) -static double nlcsqp_sqpdeltadecrease = 0.20; -static double nlcsqp_sqpdeltaincrease = 0.80; -static double nlcsqp_maxtrustraddecay = 0.1; -static double nlcsqp_maxtrustradgrowth = 1.333; -static double nlcsqp_maxbigc = 1.0E5; -static double nlcsqp_meritfunctionbase = 0.0; -static double nlcsqp_meritfunctiongain = 2.0; -static double nlcsqp_augmentationfactor = 10.0; -static double nlcsqp_inittrustrad = 0.1; -static double nlcsqp_stagnationepsf = 1.0E-12; -static ae_int_t nlcsqp_fstagnationlimit = 20; -static ae_int_t nlcsqp_trustradstagnationlimit = 10; -static double nlcsqp_sqpbigscale = 5.0; -static double nlcsqp_sqpsmallscale = 0.2; -static ae_int_t nlcsqp_penaltymemlen = 5; -static void nlcsqp_initqpsubsolver(minsqpstate* sstate, - minsqpsubsolver* subsolver, - ae_state *_state); -static void nlcsqp_qpsubsolversetalgoipm(minsqpsubsolver* subsolver, - ae_state *_state); -static ae_bool nlcsqp_qpsubproblemupdatehessian(minsqpstate* sstate, - minsqpsubsolver* subsolver, - /* Real */ ae_vector* x0, - /* Real */ ae_vector* g0, - /* Real */ ae_vector* x1, - /* Real */ ae_vector* g1, - ae_state *_state); -static void nlcsqp_fassolve(minsqpsubsolver* subsolver, - /* Real */ ae_vector* d0, - /* Real */ ae_matrix* h, - ae_int_t nq, - /* Real */ ae_vector* b, - ae_int_t n, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - sparsematrix* a, - ae_int_t m, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - double trustrad, - ae_int_t* terminationtype, - /* Real */ ae_vector* d, - /* Real */ ae_vector* lagmult, - ae_state *_state); -static ae_bool nlcsqp_qpsubproblemsolve(minsqpstate* state, - minsqpsubsolver* subsolver, - /* Real */ ae_vector* x, - /* Real */ ae_vector* fi, - /* Real */ ae_matrix* jac, - /* Real */ ae_vector* d, - /* Real */ ae_vector* lagmult, - ae_int_t* terminationtype, - ae_state *_state); -static void nlcsqp_meritphaseinit(minsqpmeritphasestate* meritstate, - /* Real */ ae_vector* curx, - /* Real */ ae_vector* curfi, - /* Real */ ae_matrix* curj, - ae_int_t n, - ae_int_t nec, - ae_int_t nic, - ae_int_t nlec, - ae_int_t nlic, - /* Real */ ae_matrix* abslagmemory, - ae_int_t memlen, - ae_state *_state); -static ae_bool nlcsqp_meritphaseiteration(minsqpstate* state, - minsqpmeritphasestate* meritstate, - smoothnessmonitor* smonitor, - ae_bool userterminationneeded, - ae_state *_state); -static void nlcsqp_meritphaseresults(minsqpmeritphasestate* meritstate, - /* Real */ ae_vector* curx, - /* Real */ ae_vector* curfi, - /* Real */ ae_matrix* curj, - /* Real */ ae_vector* lagmult, - ae_bool* increasebigc, - ae_int_t* status, - ae_state *_state); -static void nlcsqp_sqpsendx(minsqpstate* state, - /* Real */ ae_vector* xs, - ae_state *_state); -static ae_bool nlcsqp_sqpretrievefij(minsqpstate* state, - /* Real */ ae_vector* fis, - /* Real */ ae_matrix* js, - ae_state *_state); -static void nlcsqp_sqpcopystate(minsqpstate* state, - /* Real */ ae_vector* x0, - /* Real */ ae_vector* fi0, - /* Real */ ae_matrix* j0, - /* Real */ ae_vector* x1, - /* Real */ ae_vector* fi1, - /* Real */ ae_matrix* j1, - ae_state *_state); -static void nlcsqp_lagrangianfg(minsqpstate* state, - /* Real */ ae_vector* x, - double trustrad, - /* Real */ ae_vector* fi, - /* Real */ ae_matrix* j, - /* Real */ ae_vector* lagmult, - minsqptmplagrangian* tmp, - double* f, - /* Real */ ae_vector* g, - ae_state *_state); -static double nlcsqp_meritfunction(minsqpstate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* fi, - /* Real */ ae_vector* lagmult, - /* Real */ ae_vector* penalties, - minsqptmpmerit* tmp, - ae_state *_state); -static double nlcsqp_rawlagrangian(minsqpstate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* fi, - /* Real */ ae_vector* lagmult, - /* Real */ ae_vector* penalties, - minsqptmpmerit* tmp, - ae_state *_state); -static void nlcsqp_meritfunctionandrawlagrangian(minsqpstate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* fi, - /* Real */ ae_vector* lagmult, - /* Real */ ae_vector* penalties, - minsqptmpmerit* tmp, - double* meritf, - double* rawlag, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_QPDENSEAULSOLVER) || !defined(AE_PARTIAL_BUILD) -static double qpdenseaulsolver_evictionlevel = -0.01; -static double qpdenseaulsolver_expansionratio = 0.20; -static void qpdenseaulsolver_generateexmodel(/* Real */ ae_matrix* sclsfta, - /* Real */ ae_vector* sclsftb, - ae_int_t nmain, - /* Real */ ae_vector* sclsftbndl, - /* Boolean */ ae_vector* sclsfthasbndl, - /* Real */ ae_vector* sclsftbndu, - /* Boolean */ ae_vector* sclsfthasbndu, - /* Real */ ae_matrix* sclsftcleic, - ae_int_t sclsftnec, - ae_int_t sclsftnic, - /* Real */ ae_vector* nulc, - double rho, - /* Real */ ae_matrix* exa, - /* Real */ ae_vector* exb, - /* Real */ ae_vector* exbndl, - /* Real */ ae_vector* exbndu, - /* Real */ ae_matrix* tmp2, - ae_state *_state); -static void qpdenseaulsolver_generateexinitialpoint(/* Real */ ae_vector* sclsftxc, - ae_int_t nmain, - ae_int_t nslack, - /* Real */ ae_vector* exxc, - ae_state *_state); -static void qpdenseaulsolver_updatelagrangemultipliers(/* Real */ ae_matrix* sclsfta, - /* Real */ ae_vector* sclsftb, - ae_int_t nmain, - /* Real */ ae_vector* sclsftbndl, - /* Boolean */ ae_vector* sclsfthasbndl, - /* Real */ ae_vector* sclsftbndu, - /* Boolean */ ae_vector* sclsfthasbndu, - /* Real */ ae_matrix* sclsftcleic, - ae_int_t sclsftnec, - ae_int_t sclsftnic, - /* Real */ ae_vector* exxc, - /* Real */ ae_vector* nulcest, - qpdenseaulbuffers* buffers, - ae_state *_state); -static void qpdenseaulsolver_scaleshiftoriginalproblem(convexquadraticmodel* a, - sparsematrix* sparsea, - ae_int_t akind, - ae_bool sparseaupper, - /* Real */ ae_vector* b, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - ae_int_t nmain, - /* Real */ ae_matrix* cleic, - ae_int_t dnec, - ae_int_t dnic, - sparsematrix* scleic, - ae_int_t snec, - ae_int_t snic, - ae_bool renormlc, - qpdenseaulbuffers* state, - /* Real */ ae_vector* xs, - ae_state *_state); -static double qpdenseaulsolver_normalizequadraticterm(/* Real */ ae_matrix* a, - /* Real */ ae_vector* b, - ae_int_t n, - /* Real */ ae_matrix* cleic, - ae_int_t nec, - ae_int_t nic, - ae_bool usecleic, - /* Real */ ae_matrix* tmp2, - ae_state *_state); -static void qpdenseaulsolver_selectinitialworkingset(/* Real */ ae_matrix* a, - ae_int_t nmain, - /* Real */ ae_matrix* cleic, - ae_int_t nec, - ae_int_t nic, - /* Real */ ae_vector* tmp0, - /* Real */ ae_matrix* tmp2, - ae_int_t* nicwork, - ae_bool* allowwseviction, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_MINBLEIC) || !defined(AE_PARTIAL_BUILD) -static double minbleic_gtol = 0.4; -static double minbleic_maxnonmonotoniclen = 1.0E-7; -static double minbleic_nmstol = 1.0E2; -static double minbleic_initialdecay = 0.5; -static double minbleic_mindecay = 0.1; -static double minbleic_decaycorrection = 0.8; -static double minbleic_penaltyfactor = 100; -static void minbleic_clearrequestfields(minbleicstate* state, - ae_state *_state); -static void minbleic_minbleicinitinternal(ae_int_t n, - /* Real */ ae_vector* x, - double diffstep, - minbleicstate* state, - ae_state *_state); -static void minbleic_updateestimateofgoodstep(double* estimate, - double newstep, - ae_state *_state); -static double minbleic_feasibilityerror(/* Real */ ae_vector* x, - /* Real */ ae_vector* s, - ae_int_t n, - /* Real */ ae_matrix* cleic, - ae_int_t nec, - ae_int_t nic, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_QPBLEICSOLVER) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_MINQP) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_LPQPPRESOLVE) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_REVISEDDUALSIMPLEX) || !defined(AE_PARTIAL_BUILD) -static ae_int_t reviseddualsimplex_maxforcedrestarts = 1; -static ae_int_t reviseddualsimplex_safetrfage = 5; -static ae_int_t reviseddualsimplex_defaultmaxtrfage = 100; -static double reviseddualsimplex_minbeta = 1.0E-4; -static double reviseddualsimplex_maxudecay = 0.001; -static double reviseddualsimplex_shiftlen = 1.0E-12; -static double reviseddualsimplex_alphatrigger = 1.0E8*ae_machineepsilon; -static double reviseddualsimplex_alphatrigger2 = 0.001; -static ae_int_t reviseddualsimplex_ssinvalid = 0; -static ae_int_t reviseddualsimplex_ssvalidxn = 1; -static ae_int_t reviseddualsimplex_ssvalid = 2; -static ae_int_t reviseddualsimplex_ccfixed = 0; -static ae_int_t reviseddualsimplex_cclower = 1; -static ae_int_t reviseddualsimplex_ccupper = 2; -static ae_int_t reviseddualsimplex_ccrange = 3; -static ae_int_t reviseddualsimplex_ccfree = 4; -static ae_int_t reviseddualsimplex_ccinfeasible = 5; -static void reviseddualsimplex_subprobleminit(ae_int_t n, - dualsimplexsubproblem* s, - ae_state *_state); -static void reviseddualsimplex_subprobleminitphase1(dualsimplexsubproblem* s0, - dualsimplexbasis* basis, - dualsimplexsubproblem* s1, - ae_state *_state); -static void reviseddualsimplex_subprobleminitphase3(dualsimplexsubproblem* s0, - dualsimplexsubproblem* s1, - ae_state *_state); -static void reviseddualsimplex_subprobleminferinitialxn(dualsimplexstate* state, - dualsimplexsubproblem* s, - ae_state *_state); -static void reviseddualsimplex_subproblemhandlexnupdate(dualsimplexstate* state, - dualsimplexsubproblem* s, - ae_state *_state); -static double reviseddualsimplex_initialdualfeasibilitycorrection(dualsimplexstate* state, - dualsimplexsubproblem* s, - dualsimplexsettings* settings, - ae_state *_state); -static void reviseddualsimplex_shifting(dualsimplexstate* state, - dualsimplexsubproblem* s, - dssvector* alphar, - double delta, - ae_int_t q, - double alpharpiv, - double* thetad, - dualsimplexsettings* settings, - ae_state *_state); -static void reviseddualsimplex_pricingstep(dualsimplexstate* state, - dualsimplexsubproblem* s, - ae_bool phase1pricing, - ae_int_t* p, - ae_int_t* r, - double* delta, - dualsimplexsettings* settings, - ae_state *_state); -static void reviseddualsimplex_btranstep(dualsimplexstate* state, - dualsimplexsubproblem* s, - ae_int_t r, - dssvector* rhor, - dualsimplexsettings* settings, - ae_state *_state); -static void reviseddualsimplex_pivotrowstep(dualsimplexstate* state, - dualsimplexsubproblem* s, - dssvector* rhor, - dssvector* alphar, - dualsimplexsettings* settings, - ae_state *_state); -static void reviseddualsimplex_ftranstep(dualsimplexstate* state, - dualsimplexsubproblem* s, - dssvector* rhor, - ae_int_t q, - /* Real */ ae_vector* alphaq, - /* Real */ ae_vector* alphaqim, - /* Real */ ae_vector* tau, - dualsimplexsettings* settings, - ae_state *_state); -static void reviseddualsimplex_ratiotest(dualsimplexstate* state, - dualsimplexsubproblem* s, - dssvector* alphar, - double delta, - ae_int_t p, - ae_int_t* q, - double* alpharpiv, - double* thetad, - /* Integer */ ae_vector* possibleflips, - ae_int_t* possibleflipscnt, - dualsimplexsettings* settings, - ae_state *_state); -static void reviseddualsimplex_updatestep(dualsimplexstate* state, - dualsimplexsubproblem* s, - ae_int_t p, - ae_int_t q, - ae_int_t r, - double delta, - double alphapiv, - double thetap, - double thetad, - /* Real */ ae_vector* alphaq, - /* Real */ ae_vector* alphaqim, - dssvector* alphar, - /* Real */ ae_vector* tau, - /* Integer */ ae_vector* possiblealpharflips, - ae_int_t possiblealpharflipscnt, - dualsimplexsettings* settings, - ae_state *_state); -static ae_bool reviseddualsimplex_refactorizationrequired(dualsimplexstate* state, - dualsimplexsubproblem* s, - ae_int_t q, - double alpharpiv, - ae_int_t r, - double alphaqpiv, - ae_state *_state); -static void reviseddualsimplex_cacheboundinfo(dualsimplexsubproblem* s, - ae_int_t i, - ae_int_t k, - dualsimplexsettings* settings, - ae_state *_state); -static void reviseddualsimplex_solvesubproblemdual(dualsimplexstate* state, - dualsimplexsubproblem* s, - ae_bool isphase1, - dualsimplexsettings* settings, - ae_int_t* info, - ae_state *_state); -static void reviseddualsimplex_solvesubproblemprimal(dualsimplexstate* state, - dualsimplexsubproblem* s, - dualsimplexsettings* settings, - ae_int_t* info, - ae_state *_state); -static void reviseddualsimplex_invokephase1(dualsimplexstate* state, - dualsimplexsettings* settings, - ae_state *_state); -static void reviseddualsimplex_dssoptimizewrk(dualsimplexstate* state, - dualsimplexsettings* settings, - ae_state *_state); -static void reviseddualsimplex_solveboxonly(dualsimplexstate* state, - ae_state *_state); -static void reviseddualsimplex_setzeroxystats(dualsimplexstate* state, - ae_state *_state); -static void reviseddualsimplex_basisinit(ae_int_t ns, - ae_int_t m, - dualsimplexbasis* s, - ae_state *_state); -static void reviseddualsimplex_basisclearstats(dualsimplexbasis* s, - ae_state *_state); -static ae_bool reviseddualsimplex_basistryresize(dualsimplexbasis* s, - ae_int_t newm, - sparsematrix* at, - dualsimplexsettings* settings, - ae_state *_state); -static double reviseddualsimplex_basisminimumdiagonalelement(dualsimplexbasis* s, - ae_state *_state); -static void reviseddualsimplex_basisexportto(dualsimplexbasis* s0, - dualsimplexbasis* s1, - ae_state *_state); -static ae_bool reviseddualsimplex_basistryimportfrom(dualsimplexbasis* s0, - dualsimplexbasis* s1, - sparsematrix* at, - dualsimplexsettings* settings, - ae_state *_state); -static void reviseddualsimplex_basisfreshtrf(dualsimplexbasis* s, - sparsematrix* at, - dualsimplexsettings* settings, - ae_state *_state); -static double reviseddualsimplex_basisfreshtrfunsafe(dualsimplexbasis* s, - sparsematrix* at, - dualsimplexsettings* settings, - ae_state *_state); -static void reviseddualsimplex_basisrequestweights(dualsimplexbasis* s, - dualsimplexsettings* settings, - ae_state *_state); -static void reviseddualsimplex_basisupdatetrf(dualsimplexbasis* s, - sparsematrix* at, - ae_int_t p, - ae_int_t q, - /* Real */ ae_vector* alphaq, - /* Real */ ae_vector* alphaqim, - ae_int_t r, - /* Real */ ae_vector* tau, - dualsimplexsettings* settings, - ae_state *_state); -static void reviseddualsimplex_basissolve(dualsimplexbasis* s, - /* Real */ ae_vector* r, - /* Real */ ae_vector* x, - /* Real */ ae_vector* tmpx, - ae_state *_state); -static void reviseddualsimplex_basissolvex(dualsimplexbasis* s, - /* Real */ ae_vector* r, - /* Real */ ae_vector* x, - /* Real */ ae_vector* xim, - ae_bool needintermediate, - /* Real */ ae_vector* tx, - ae_state *_state); -static void reviseddualsimplex_basissolvet(dualsimplexbasis* s, - /* Real */ ae_vector* r, - /* Real */ ae_vector* x, - /* Real */ ae_vector* tx, - ae_state *_state); -static void reviseddualsimplex_computeanxn(dualsimplexstate* state, - dualsimplexsubproblem* subproblem, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -static void reviseddualsimplex_computeantv(dualsimplexstate* state, - /* Real */ ae_vector* y, - /* Real */ ae_vector* r, - ae_state *_state); -static ae_bool reviseddualsimplex_hasbndl(dualsimplexsubproblem* subproblem, - ae_int_t i, - ae_state *_state); -static ae_bool reviseddualsimplex_hasbndu(dualsimplexsubproblem* subproblem, - ae_int_t i, - ae_state *_state); -static ae_bool reviseddualsimplex_isfree(dualsimplexsubproblem* subproblem, - ae_int_t i, - ae_state *_state); -static void reviseddualsimplex_downgradestate(dualsimplexsubproblem* subproblem, - ae_int_t s, - ae_state *_state); -static double reviseddualsimplex_dualfeasibilityerror(dualsimplexstate* state, - dualsimplexsubproblem* s, - ae_state *_state); -static ae_bool reviseddualsimplex_isdualfeasible(dualsimplexstate* state, - dualsimplexsubproblem* s, - dualsimplexsettings* settings, - ae_state *_state); -static void reviseddualsimplex_pivottobwd(/* Integer */ ae_vector* p, - ae_int_t m, - /* Integer */ ae_vector* bwd, - ae_state *_state); -static void reviseddualsimplex_inversecyclicpermutation(/* Integer */ ae_vector* bwd, - ae_int_t m, - ae_int_t d, - /* Integer */ ae_vector* tmpi, - ae_state *_state); -static void reviseddualsimplex_offloadbasiccomponents(dualsimplexsubproblem* s, - dualsimplexbasis* basis, - dualsimplexsettings* settings, - ae_state *_state); -static void reviseddualsimplex_recombinebasicnonbasicx(dualsimplexsubproblem* s, - dualsimplexbasis* basis, - ae_state *_state); -static void reviseddualsimplex_setxydstats(dualsimplexstate* state, - dualsimplexsubproblem* s, - dualsimplexbasis* basis, - apbuffers* buffers, - /* Real */ ae_vector* x, - /* Real */ ae_vector* lagbc, - /* Real */ ae_vector* laglc, - /* Integer */ ae_vector* stats, - ae_state *_state); -static void reviseddualsimplex_dvalloc(dssvector* x, - ae_int_t n, - ae_state *_state); -static void reviseddualsimplex_dvinit(dssvector* x, - ae_int_t n, - ae_state *_state); -static void reviseddualsimplex_dvdensetosparse(dssvector* x, - ae_state *_state); -static void reviseddualsimplex_dvsparsetodense(dssvector* x, - ae_state *_state); -static double reviseddualsimplex_sparsityof(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state); -static void reviseddualsimplex_updateavgcounter(double v, - double* acc, - ae_int_t* cnt, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_MINLP) || !defined(AE_PARTIAL_BUILD) -static ae_int_t minlp_alllogicalsbasis = 0; -static void minlp_clearreportfields(minlpstate* state, ae_state *_state); - - -#endif -#if defined(AE_COMPILE_NLCSLP) || !defined(AE_PARTIAL_BUILD) -static double nlcslp_slpstpclosetozero = 0.001; -static double nlcslp_slpdeltadecrease = 0.20; -static double nlcslp_slpdeltaincrease = 0.80; -static double nlcslp_slpstpclosetoone = 0.95; -static double nlcslp_maxtrustraddecay = 0.1; -static double nlcslp_maxtrustradgrowth = 1.333; -static double nlcslp_slpgtol = 0.4; -static double nlcslp_bigc = 500.0; -static double nlcslp_bfgstol = 1.0E-5; -static double nlcslp_meritfunctionbase = 0.0; -static double nlcslp_meritfunctiongain = 2.0; -static double nlcslp_inequalitydampingfactor = 10.0; -static double nlcslp_augmentationfactor = 10.0; -static double nlcslp_inittrustrad = 0.1; -static double nlcslp_stagnationepsf = 1.0E-12; -static ae_int_t nlcslp_lpfailureslimit = 20; -static ae_int_t nlcslp_fstagnationlimit = 20; -static ae_int_t nlcslp_nondescentlimit = 99999; -static ae_int_t nlcslp_nonmonotonicphase2limit = 5; -static double nlcslp_slpbigscale = 5.0; -static double nlcslp_slpsmallscale = 0.2; -static void nlcslp_initlpsubsolver(minslpstate* sstate, - minslpsubsolver* subsolver, - ae_int_t hessiantype, - ae_state *_state); -static void nlcslp_lpsubproblemrestart(minslpstate* sstate, - minslpsubsolver* subsolver, - ae_state *_state); -static void nlcslp_lpsubproblemupdatehessian(minslpstate* sstate, - minslpsubsolver* subsolver, - /* Real */ ae_vector* x0, - /* Real */ ae_vector* g0, - /* Real */ ae_vector* x1, - /* Real */ ae_vector* g1, - ae_state *_state); -static ae_bool nlcslp_lpsubproblemsolve(minslpstate* state, - minslpsubsolver* subsolver, - /* Real */ ae_vector* x, - /* Real */ ae_vector* fi, - /* Real */ ae_matrix* jac, - ae_int_t innerk, - /* Real */ ae_vector* d, - /* Real */ ae_vector* lagmult, - ae_state *_state); -static void nlcslp_lpsubproblemappendconjugacyconstraint(minslpstate* state, - minslpsubsolver* subsolver, - /* Real */ ae_vector* d, - ae_state *_state); -static void nlcslp_phase13init(minslpphase13state* state13, - ae_int_t n, - ae_int_t nec, - ae_int_t nic, - ae_int_t nlec, - ae_int_t nlic, - ae_bool usecorrection, - ae_state *_state); -static ae_bool nlcslp_phase13iteration(minslpstate* state, - minslpphase13state* state13, - smoothnessmonitor* smonitor, - ae_bool userterminationneeded, - /* Real */ ae_vector* curx, - /* Real */ ae_vector* curfi, - /* Real */ ae_matrix* curj, - /* Real */ ae_vector* lagmult, - ae_int_t* status, - double* stp, - ae_state *_state); -static void nlcslp_phase2init(minslpphase2state* state2, - ae_int_t n, - ae_int_t nec, - ae_int_t nic, - ae_int_t nlec, - ae_int_t nlic, - /* Real */ ae_vector* meritlagmult, - ae_state *_state); -static ae_bool nlcslp_phase2iteration(minslpstate* state, - minslpphase2state* state2, - smoothnessmonitor* smonitor, - ae_bool userterminationneeded, - /* Real */ ae_vector* curx, - /* Real */ ae_vector* curfi, - /* Real */ ae_matrix* curj, - /* Real */ ae_vector* lagmult, - double* gammamax, - ae_int_t* status, - ae_state *_state); -static void nlcslp_slpsendx(minslpstate* state, - /* Real */ ae_vector* xs, - ae_state *_state); -static ae_bool nlcslp_slpretrievefij(minslpstate* state, - /* Real */ ae_vector* fis, - /* Real */ ae_matrix* js, - ae_state *_state); -static void nlcslp_slpcopystate(minslpstate* state, - /* Real */ ae_vector* x0, - /* Real */ ae_vector* fi0, - /* Real */ ae_matrix* j0, - /* Real */ ae_vector* x1, - /* Real */ ae_vector* fi1, - /* Real */ ae_matrix* j1, - ae_state *_state); -static void nlcslp_lagrangianfg(minslpstate* state, - /* Real */ ae_vector* x, - double trustrad, - /* Real */ ae_vector* fi, - /* Real */ ae_matrix* j, - /* Real */ ae_vector* lagmult, - minslptmplagrangian* tmp, - double* f, - /* Real */ ae_vector* g, - double* lcerr, - ae_int_t* lcidx, - double* nlcerr, - ae_int_t* nlcidx, - ae_state *_state); -static double nlcslp_meritfunction(minslpstate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* fi, - /* Real */ ae_vector* lagmult, - minslptmpmerit* tmp, - ae_state *_state); -static double nlcslp_rawlagrangian(minslpstate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* fi, - /* Real */ ae_vector* lagmult, - minslptmpmerit* tmp, - ae_state *_state); -static void nlcslp_meritfunctionandrawlagrangian(minslpstate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* fi, - /* Real */ ae_vector* lagmult, - minslptmpmerit* tmp, - double* meritf, - double* rawlag, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_MINNLC) || !defined(AE_PARTIAL_BUILD) -static double minnlc_aulmaxgrowth = 10.0; -static double minnlc_maxlagmult = 1.0E7; -static ae_int_t minnlc_lbfgsfactor = 10; -static double minnlc_hessesttol = 1.0E-6; -static double minnlc_initgamma = 1.0E-6; -static double minnlc_regprec = 1.0E-6; -static void minnlc_clearrequestfields(minnlcstate* state, - ae_state *_state); -static void minnlc_minnlcinitinternal(ae_int_t n, - /* Real */ ae_vector* x, - double diffstep, - minnlcstate* state, - ae_state *_state); -static void minnlc_clearpreconditioner(minlbfgsstate* auloptimizer, - ae_state *_state); -static void minnlc_updatepreconditioner(ae_int_t prectype, - ae_int_t updatefreq, - ae_int_t* preccounter, - minlbfgsstate* auloptimizer, - /* Real */ ae_vector* x, - double rho, - double gammak, - /* Real */ ae_vector* bndl, - /* Boolean */ ae_vector* hasbndl, - /* Real */ ae_vector* bndu, - /* Boolean */ ae_vector* hasbndu, - /* Real */ ae_vector* nubc, - /* Real */ ae_matrix* cleic, - /* Real */ ae_vector* nulc, - /* Real */ ae_vector* fi, - /* Real */ ae_matrix* jac, - /* Real */ ae_vector* nunlc, - /* Real */ ae_vector* bufd, - /* Real */ ae_vector* bufc, - /* Real */ ae_matrix* bufw, - /* Real */ ae_matrix* bufz, - /* Real */ ae_vector* tmp0, - ae_int_t n, - ae_int_t nec, - ae_int_t nic, - ae_int_t ng, - ae_int_t nh, - ae_state *_state); -static void minnlc_penaltybc(/* Real */ ae_vector* x, - /* Real */ ae_vector* bndl, - /* Boolean */ ae_vector* hasbndl, - /* Real */ ae_vector* bndu, - /* Boolean */ ae_vector* hasbndu, - /* Real */ ae_vector* nubc, - ae_int_t n, - double rho, - double stabilizingpoint, - double* f, - /* Real */ ae_vector* g, - ae_state *_state); -static void minnlc_penaltylc(/* Real */ ae_vector* x, - /* Real */ ae_matrix* cleic, - /* Real */ ae_vector* nulc, - ae_int_t n, - ae_int_t nec, - ae_int_t nic, - double rho, - double stabilizingpoint, - double* f, - /* Real */ ae_vector* g, - ae_state *_state); -static void minnlc_penaltynlc(/* Real */ ae_vector* fi, - /* Real */ ae_matrix* j, - /* Real */ ae_vector* nunlc, - ae_int_t n, - ae_int_t ng, - ae_int_t nh, - double rho, - double stabilizingpoint, - double* f, - /* Real */ ae_vector* g, - ae_state *_state); -static ae_bool minnlc_auliteration(minnlcstate* state, - smoothnessmonitor* smonitor, - ae_state *_state); -static void minnlc_unscale(minnlcstate* state, - /* Real */ ae_vector* xs, - /* Real */ ae_vector* scaledbndl, - /* Real */ ae_vector* scaledbndu, - /* Real */ ae_vector* xu, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_MINBC) || !defined(AE_PARTIAL_BUILD) -static double minbc_gtol = 0.4; -static double minbc_maxnonmonotoniclen = 1.0E-5; -static double minbc_initialdecay = 0.5; -static double minbc_mindecay = 0.1; -static double minbc_decaycorrection = 0.8; -static void minbc_clearrequestfields(minbcstate* state, ae_state *_state); -static void minbc_minbcinitinternal(ae_int_t n, - /* Real */ ae_vector* x, - double diffstep, - minbcstate* state, - ae_state *_state); -static void minbc_updateestimateofgoodstep(double* estimate, - double newstep, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_MINNS) || !defined(AE_PARTIAL_BUILD) -static void minns_clearrequestfields(minnsstate* state, ae_state *_state); -static void minns_minnsinitinternal(ae_int_t n, - /* Real */ ae_vector* x, - double diffstep, - minnsstate* state, - ae_state *_state); -static ae_bool minns_agsiteration(minnsstate* state, ae_state *_state); -static void minns_generatemeritfunction(minnsstate* state, - ae_int_t sampleidx, - ae_state *_state); -static void minns_unscalepointbc(minnsstate* state, - /* Real */ ae_vector* x, - ae_state *_state); -static void minns_solveqp(/* Real */ ae_matrix* sampleg, - /* Real */ ae_vector* diagh, - ae_int_t nsample, - ae_int_t nvars, - /* Real */ ae_vector* coeffs, - ae_int_t* dbgncholesky, - minnsqp* state, - ae_state *_state); -static void minns_qpcalculategradfunc(/* Real */ ae_matrix* sampleg, - /* Real */ ae_vector* diagh, - ae_int_t nsample, - ae_int_t nvars, - /* Real */ ae_vector* coeffs, - /* Real */ ae_vector* g, - double* f, - /* Real */ ae_vector* tmp, - ae_state *_state); -static void minns_qpcalculatefunc(/* Real */ ae_matrix* sampleg, - /* Real */ ae_vector* diagh, - ae_int_t nsample, - ae_int_t nvars, - /* Real */ ae_vector* coeffs, - double* f, - /* Real */ ae_vector* tmp, - ae_state *_state); -static void minns_qpsolveu(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_vector* x, - ae_state *_state); -static void minns_qpsolveut(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_vector* x, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_MINCOMP) || !defined(AE_PARTIAL_BUILD) -static ae_int_t mincomp_n1 = 2; -static ae_int_t mincomp_n2 = 2; -static double mincomp_stpmin = 1.0E-300; -static double mincomp_gtol = 0.3; -static double mincomp_gpaftol = 0.0001; -static double mincomp_gpadecay = 0.5; -static double mincomp_asarho = 0.5; -static double mincomp_asaboundedantigradnorm(minasastate* state, - ae_state *_state); -static double mincomp_asaginorm(minasastate* state, ae_state *_state); -static double mincomp_asad1norm(minasastate* state, ae_state *_state); -static ae_bool mincomp_asauisempty(minasastate* state, ae_state *_state); -static void mincomp_clearrequestfields(minasastate* state, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_MINCG) || !defined(AE_PARTIAL_BUILD) -static ae_int_t mincg_rscountdownlen = 10; -static double mincg_gtol = 0.3; -static void mincg_clearrequestfields(mincgstate* state, ae_state *_state); -static void mincg_preconditionedmultiply(mincgstate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* work0, - /* Real */ ae_vector* work1, - ae_state *_state); -static double mincg_preconditionedmultiply2(mincgstate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* work0, - /* Real */ ae_vector* work1, - ae_state *_state); -static void mincg_mincginitinternal(ae_int_t n, - double diffstep, - mincgstate* state, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_MINLM) || !defined(AE_PARTIAL_BUILD) -static double minlm_lambdaup = 2.0; -static double minlm_lambdadown = 0.33; -static double minlm_suspiciousnu = 16; -static ae_int_t minlm_smallmodelage = 3; -static ae_int_t minlm_additers = 5; -static void minlm_lmprepare(ae_int_t n, - ae_int_t m, - ae_bool havegrad, - minlmstate* state, - ae_state *_state); -static void minlm_clearrequestfields(minlmstate* state, ae_state *_state); -static ae_bool minlm_increaselambda(double* lambdav, - double* nu, - ae_state *_state); -static void minlm_decreaselambda(double* lambdav, - double* nu, - ae_state *_state); -static ae_int_t minlm_checkdecrease(/* Real */ ae_matrix* quadraticmodel, - /* Real */ ae_vector* gbase, - double fbase, - ae_int_t n, - /* Real */ ae_vector* deltax, - double fnew, - double* lambdav, - double* nu, - ae_state *_state); -static ae_bool minlm_minlmstepfinderinit(minlmstepfinder* state, - ae_int_t n, - ae_int_t m, - ae_int_t maxmodelage, - ae_bool hasfi, - /* Real */ ae_vector* xbase, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_matrix* cleic, - ae_int_t nec, - ae_int_t nic, - /* Real */ ae_vector* s, - double stpmax, - double epsx, - ae_state *_state); -static void minlm_minlmstepfinderstart(minlmstepfinder* state, - /* Real */ ae_matrix* quadraticmodel, - /* Real */ ae_vector* gbase, - double fbase, - /* Real */ ae_vector* xbase, - /* Real */ ae_vector* fibase, - ae_int_t modelage, - ae_state *_state); -static ae_bool minlm_minlmstepfinderiteration(minlmstepfinder* state, - double* lambdav, - double* nu, - /* Real */ ae_vector* xnew, - /* Real */ ae_vector* deltax, - ae_bool* deltaxready, - /* Real */ ae_vector* deltaf, - ae_bool* deltafready, - ae_int_t* iflag, - double* fnew, - ae_int_t* ncholesky, - ae_state *_state); - - -#endif - -#if defined(AE_COMPILE_CQMODELS) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This subroutine is used to initialize CQM. By default, empty NxN model is -generated, with Alpha=Lambda=Theta=0.0 and zero b. - -Previously allocated buffer variables are reused as much as possible. - - -- ALGLIB -- - Copyright 12.06.2012 by Bochkanov Sergey -*************************************************************************/ -void cqminit(ae_int_t n, convexquadraticmodel* s, ae_state *_state) -{ - ae_int_t i; - - - s->n = n; - s->k = 0; - s->nfree = n; - s->ecakind = -1; - s->alpha = 0.0; - s->tau = 0.0; - s->theta = 0.0; - s->ismaintermchanged = ae_true; - s->issecondarytermchanged = ae_true; - s->islineartermchanged = ae_true; - s->isactivesetchanged = ae_true; - bvectorsetlengthatleast(&s->activeset, n, _state); - rvectorsetlengthatleast(&s->xc, n, _state); - rvectorsetlengthatleast(&s->eb, n, _state); - rvectorsetlengthatleast(&s->tq1, n, _state); - rvectorsetlengthatleast(&s->txc, n, _state); - rvectorsetlengthatleast(&s->tb, n, _state); - rvectorsetlengthatleast(&s->b, s->n, _state); - rvectorsetlengthatleast(&s->tk1, s->n, _state); - for(i=0; i<=n-1; i++) - { - s->activeset.ptr.p_bool[i] = ae_false; - s->xc.ptr.p_double[i] = 0.0; - s->b.ptr.p_double[i] = 0.0; - } -} - - -/************************************************************************* -This subroutine changes main quadratic term of the model. - -INPUT PARAMETERS: - S - model - A - NxN matrix, only upper or lower triangle is referenced - IsUpper - True, when matrix is stored in upper triangle - Alpha - multiplier; when Alpha=0, A is not referenced at all - - -- ALGLIB -- - Copyright 12.06.2012 by Bochkanov Sergey -*************************************************************************/ -void cqmseta(convexquadraticmodel* s, - /* Real */ ae_matrix* a, - ae_bool isupper, - double alpha, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - - - ae_assert(ae_isfinite(alpha, _state)&&ae_fp_greater_eq(alpha,(double)(0)), "CQMSetA: Alpha<0 or is not finite number", _state); - ae_assert(ae_fp_eq(alpha,(double)(0))||isfinitertrmatrix(a, s->n, isupper, _state), "CQMSetA: A is not finite NxN matrix", _state); - s->alpha = alpha; - if( ae_fp_greater(alpha,(double)(0)) ) - { - rmatrixsetlengthatleast(&s->a, s->n, s->n, _state); - rmatrixsetlengthatleast(&s->ecadense, s->n, s->n, _state); - rmatrixsetlengthatleast(&s->tq2dense, s->n, s->n, _state); - for(i=0; i<=s->n-1; i++) - { - for(j=i; j<=s->n-1; j++) - { - if( isupper ) - { - v = a->ptr.pp_double[i][j]; - } - else - { - v = a->ptr.pp_double[j][i]; - } - s->a.ptr.pp_double[i][j] = v; - s->a.ptr.pp_double[j][i] = v; - } - } - } - s->ismaintermchanged = ae_true; -} - - -/************************************************************************* -This subroutine changes main quadratic term of the model. - -INPUT PARAMETERS: - S - model - A - possibly preallocated buffer - -OUTPUT PARAMETERS: - A - NxN matrix, full matrix is returned. - Zero matrix is returned if model is empty. - - -- ALGLIB -- - Copyright 12.06.2012 by Bochkanov Sergey -*************************************************************************/ -void cqmgeta(convexquadraticmodel* s, - /* Real */ ae_matrix* a, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - ae_int_t n; - - - n = s->n; - rmatrixsetlengthatleast(a, n, n, _state); - if( ae_fp_greater(s->alpha,(double)(0)) ) - { - v = s->alpha; - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a->ptr.pp_double[i][j] = v*s->a.ptr.pp_double[i][j]; - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a->ptr.pp_double[i][j] = 0.0; - } - } - } -} - - -/************************************************************************* -This subroutine rewrites diagonal of the main quadratic term of the model -(dense A) by vector Z/Alpha (current value of the Alpha coefficient is -used). - -IMPORTANT: in case model has no dense quadratic term, this function - allocates N*N dense matrix of zeros, and fills its diagonal by - non-zero values. - -INPUT PARAMETERS: - S - model - Z - new diagonal, array[N] - - -- ALGLIB -- - Copyright 12.06.2012 by Bochkanov Sergey -*************************************************************************/ -void cqmrewritedensediagonal(convexquadraticmodel* s, - /* Real */ ae_vector* z, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_int_t j; - - - n = s->n; - if( ae_fp_eq(s->alpha,(double)(0)) ) - { - rmatrixsetlengthatleast(&s->a, s->n, s->n, _state); - rmatrixsetlengthatleast(&s->ecadense, s->n, s->n, _state); - rmatrixsetlengthatleast(&s->tq2dense, s->n, s->n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - s->a.ptr.pp_double[i][j] = 0.0; - } - } - s->alpha = 1.0; - } - for(i=0; i<=s->n-1; i++) - { - s->a.ptr.pp_double[i][i] = z->ptr.p_double[i]/s->alpha; - } - s->ismaintermchanged = ae_true; -} - - -/************************************************************************* -This subroutine changes diagonal quadratic term of the model. - -INPUT PARAMETERS: - S - model - D - array[N], semidefinite diagonal matrix - Tau - multiplier; when Tau=0, D is not referenced at all - - -- ALGLIB -- - Copyright 12.06.2012 by Bochkanov Sergey -*************************************************************************/ -void cqmsetd(convexquadraticmodel* s, - /* Real */ ae_vector* d, - double tau, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(ae_isfinite(tau, _state)&&ae_fp_greater_eq(tau,(double)(0)), "CQMSetD: Tau<0 or is not finite number", _state); - ae_assert(ae_fp_eq(tau,(double)(0))||isfinitevector(d, s->n, _state), "CQMSetD: D is not finite Nx1 vector", _state); - s->tau = tau; - if( ae_fp_greater(tau,(double)(0)) ) - { - rvectorsetlengthatleast(&s->d, s->n, _state); - rvectorsetlengthatleast(&s->ecadiag, s->n, _state); - rvectorsetlengthatleast(&s->tq2diag, s->n, _state); - for(i=0; i<=s->n-1; i++) - { - ae_assert(ae_fp_greater_eq(d->ptr.p_double[i],(double)(0)), "CQMSetD: D[i]<0", _state); - s->d.ptr.p_double[i] = d->ptr.p_double[i]; - } - } - s->ismaintermchanged = ae_true; -} - - -/************************************************************************* -This subroutine drops main quadratic term A from the model. It is same as -call to CQMSetA() with zero A, but gives better performance because -algorithm knows that matrix is zero and can optimize subsequent -calculations. - -INPUT PARAMETERS: - S - model - - -- ALGLIB -- - Copyright 12.06.2012 by Bochkanov Sergey -*************************************************************************/ -void cqmdropa(convexquadraticmodel* s, ae_state *_state) -{ - - - s->alpha = 0.0; - s->ismaintermchanged = ae_true; -} - - -/************************************************************************* -This subroutine changes linear term of the model - - -- ALGLIB -- - Copyright 12.06.2012 by Bochkanov Sergey -*************************************************************************/ -void cqmsetb(convexquadraticmodel* s, - /* Real */ ae_vector* b, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(isfinitevector(b, s->n, _state), "CQMSetB: B is not finite vector", _state); - rvectorsetlengthatleast(&s->b, s->n, _state); - for(i=0; i<=s->n-1; i++) - { - s->b.ptr.p_double[i] = b->ptr.p_double[i]; - } - s->islineartermchanged = ae_true; -} - - -/************************************************************************* -This subroutine changes linear term of the model - - -- ALGLIB -- - Copyright 12.06.2012 by Bochkanov Sergey -*************************************************************************/ -void cqmsetq(convexquadraticmodel* s, - /* Real */ ae_matrix* q, - /* Real */ ae_vector* r, - ae_int_t k, - double theta, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - ae_assert(k>=0, "CQMSetQ: K<0", _state); - ae_assert((k==0||ae_fp_eq(theta,(double)(0)))||apservisfinitematrix(q, k, s->n, _state), "CQMSetQ: Q is not finite matrix", _state); - ae_assert((k==0||ae_fp_eq(theta,(double)(0)))||isfinitevector(r, k, _state), "CQMSetQ: R is not finite vector", _state); - ae_assert(ae_isfinite(theta, _state)&&ae_fp_greater_eq(theta,(double)(0)), "CQMSetQ: Theta<0 or is not finite number", _state); - - /* - * degenerate case: K=0 or Theta=0 - */ - if( k==0||ae_fp_eq(theta,(double)(0)) ) - { - s->k = 0; - s->theta = (double)(0); - s->issecondarytermchanged = ae_true; - return; - } - - /* - * General case: both Theta>0 and K>0 - */ - s->k = k; - s->theta = theta; - rmatrixsetlengthatleast(&s->q, s->k, s->n, _state); - rvectorsetlengthatleast(&s->r, s->k, _state); - rmatrixsetlengthatleast(&s->eq, s->k, s->n, _state); - rmatrixsetlengthatleast(&s->eccm, s->k, s->k, _state); - rmatrixsetlengthatleast(&s->tk2, s->k, s->n, _state); - for(i=0; i<=s->k-1; i++) - { - for(j=0; j<=s->n-1; j++) - { - s->q.ptr.pp_double[i][j] = q->ptr.pp_double[i][j]; - } - s->r.ptr.p_double[i] = r->ptr.p_double[i]; - } - s->issecondarytermchanged = ae_true; -} - - -/************************************************************************* -This subroutine changes active set - -INPUT PARAMETERS - S - model - X - array[N], constraint values - ActiveSet- array[N], active set. If ActiveSet[I]=True, then I-th - variables is constrained to X[I]. - - -- ALGLIB -- - Copyright 12.06.2012 by Bochkanov Sergey -*************************************************************************/ -void cqmsetactiveset(convexquadraticmodel* s, - /* Real */ ae_vector* x, - /* Boolean */ ae_vector* activeset, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(x->cnt>=s->n, "CQMSetActiveSet: Length(X)cnt>=s->n, "CQMSetActiveSet: Length(ActiveSet)n-1; i++) - { - s->isactivesetchanged = s->isactivesetchanged||(s->activeset.ptr.p_bool[i]&&!activeset->ptr.p_bool[i]); - s->isactivesetchanged = s->isactivesetchanged||(activeset->ptr.p_bool[i]&&!s->activeset.ptr.p_bool[i]); - s->activeset.ptr.p_bool[i] = activeset->ptr.p_bool[i]; - if( activeset->ptr.p_bool[i] ) - { - ae_assert(ae_isfinite(x->ptr.p_double[i], _state), "CQMSetActiveSet: X[] contains infinite constraints", _state); - s->isactivesetchanged = s->isactivesetchanged||ae_fp_neq(s->xc.ptr.p_double[i],x->ptr.p_double[i]); - s->xc.ptr.p_double[i] = x->ptr.p_double[i]; - } - } -} - - -/************************************************************************* -This subroutine evaluates model at X. Active constraints are ignored. - - -- ALGLIB -- - Copyright 12.06.2012 by Bochkanov Sergey -*************************************************************************/ -double cqmeval(convexquadraticmodel* s, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_int_t j; - double v; - double result; - - - n = s->n; - ae_assert(isfinitevector(x, n, _state), "CQMEval: X is not finite vector", _state); - result = 0.0; - - /* - * main quadratic term - */ - if( ae_fp_greater(s->alpha,(double)(0)) ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - result = result+s->alpha*0.5*x->ptr.p_double[i]*s->a.ptr.pp_double[i][j]*x->ptr.p_double[j]; - } - } - } - if( ae_fp_greater(s->tau,(double)(0)) ) - { - for(i=0; i<=n-1; i++) - { - result = result+0.5*ae_sqr(x->ptr.p_double[i], _state)*s->tau*s->d.ptr.p_double[i]; - } - } - - /* - * secondary quadratic term - */ - if( ae_fp_greater(s->theta,(double)(0)) ) - { - for(i=0; i<=s->k-1; i++) - { - v = ae_v_dotproduct(&s->q.ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - result = result+0.5*s->theta*ae_sqr(v-s->r.ptr.p_double[i], _state); - } - } - - /* - * linear term - */ - for(i=0; i<=s->n-1; i++) - { - result = result+x->ptr.p_double[i]*s->b.ptr.p_double[i]; - } - return result; -} - - -/************************************************************************* -This subroutine evaluates model at X. Active constraints are ignored. -It returns: - R - model value - Noise- estimate of the numerical noise in data - - -- ALGLIB -- - Copyright 12.06.2012 by Bochkanov Sergey -*************************************************************************/ -void cqmevalx(convexquadraticmodel* s, - /* Real */ ae_vector* x, - double* r, - double* noise, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_int_t j; - double v; - double v2; - double mxq; - double eps; - - *r = 0; - *noise = 0; - - n = s->n; - ae_assert(isfinitevector(x, n, _state), "CQMEval: X is not finite vector", _state); - *r = 0.0; - *noise = 0.0; - eps = 2*ae_machineepsilon; - mxq = 0.0; - - /* - * Main quadratic term. - * - * Noise from the main quadratic term is equal to the - * maximum summand in the term. - */ - if( ae_fp_greater(s->alpha,(double)(0)) ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = s->alpha*0.5*x->ptr.p_double[i]*s->a.ptr.pp_double[i][j]*x->ptr.p_double[j]; - *r = *r+v; - *noise = ae_maxreal(*noise, eps*ae_fabs(v, _state), _state); - } - } - } - if( ae_fp_greater(s->tau,(double)(0)) ) - { - for(i=0; i<=n-1; i++) - { - v = 0.5*ae_sqr(x->ptr.p_double[i], _state)*s->tau*s->d.ptr.p_double[i]; - *r = *r+v; - *noise = ae_maxreal(*noise, eps*ae_fabs(v, _state), _state); - } - } - - /* - * secondary quadratic term - * - * Noise from the secondary quadratic term is estimated as follows: - * * noise in qi*x-r[i] is estimated as - * Eps*MXQ = Eps*max(|r[i]|, |q[i,j]*x[j]|) - * * noise in (qi*x-r[i])^2 is estimated as - * NOISE = (|qi*x-r[i]|+Eps*MXQ)^2-(|qi*x-r[i]|)^2 - * = Eps*MXQ*(2*|qi*x-r[i]|+Eps*MXQ) - */ - if( ae_fp_greater(s->theta,(double)(0)) ) - { - for(i=0; i<=s->k-1; i++) - { - v = 0.0; - mxq = ae_fabs(s->r.ptr.p_double[i], _state); - for(j=0; j<=n-1; j++) - { - v2 = s->q.ptr.pp_double[i][j]*x->ptr.p_double[j]; - v = v+v2; - mxq = ae_maxreal(mxq, ae_fabs(v2, _state), _state); - } - *r = *r+0.5*s->theta*ae_sqr(v-s->r.ptr.p_double[i], _state); - *noise = ae_maxreal(*noise, eps*mxq*(2*ae_fabs(v-s->r.ptr.p_double[i], _state)+eps*mxq), _state); - } - } - - /* - * linear term - */ - for(i=0; i<=s->n-1; i++) - { - *r = *r+x->ptr.p_double[i]*s->b.ptr.p_double[i]; - *noise = ae_maxreal(*noise, eps*ae_fabs(x->ptr.p_double[i]*s->b.ptr.p_double[i], _state), _state); - } - - /* - * Final update of the noise - */ - *noise = n*(*noise); -} - - -/************************************************************************* -This subroutine evaluates gradient of the model; active constraints are -ignored. - -INPUT PARAMETERS: - S - convex model - X - point, array[N] - G - possibly preallocated buffer; resized, if too small - - -- ALGLIB -- - Copyright 12.06.2012 by Bochkanov Sergey -*************************************************************************/ -void cqmgradunconstrained(convexquadraticmodel* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* g, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_int_t j; - double v; - - - n = s->n; - ae_assert(isfinitevector(x, n, _state), "CQMEvalGradUnconstrained: X is not finite vector", _state); - rvectorsetlengthatleast(g, n, _state); - for(i=0; i<=n-1; i++) - { - g->ptr.p_double[i] = (double)(0); - } - - /* - * main quadratic term - */ - if( ae_fp_greater(s->alpha,(double)(0)) ) - { - for(i=0; i<=n-1; i++) - { - v = 0.0; - for(j=0; j<=n-1; j++) - { - v = v+s->alpha*s->a.ptr.pp_double[i][j]*x->ptr.p_double[j]; - } - g->ptr.p_double[i] = g->ptr.p_double[i]+v; - } - } - if( ae_fp_greater(s->tau,(double)(0)) ) - { - for(i=0; i<=n-1; i++) - { - g->ptr.p_double[i] = g->ptr.p_double[i]+x->ptr.p_double[i]*s->tau*s->d.ptr.p_double[i]; - } - } - - /* - * secondary quadratic term - */ - if( ae_fp_greater(s->theta,(double)(0)) ) - { - for(i=0; i<=s->k-1; i++) - { - v = ae_v_dotproduct(&s->q.ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = s->theta*(v-s->r.ptr.p_double[i]); - ae_v_addd(&g->ptr.p_double[0], 1, &s->q.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v); - } - } - - /* - * linear term - */ - for(i=0; i<=n-1; i++) - { - g->ptr.p_double[i] = g->ptr.p_double[i]+s->b.ptr.p_double[i]; - } -} - - -/************************************************************************* -This subroutine evaluates x'*(0.5*alpha*A+tau*D)*x - -NOTE: Tmp[] must be preallocated array whose length is at least N - - -- ALGLIB -- - Copyright 12.06.2012 by Bochkanov Sergey -*************************************************************************/ -double cqmxtadx2(convexquadraticmodel* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* tmp, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - double result; - - - n = s->n; - ae_assert(isfinitevector(x, n, _state), "CQMXTADX2: X is not finite vector", _state); - ae_assert(tmp->cnt>=n, "CQMXTADX2: Length(Tmp)alpha,(double)(0)) ) - { - result = result+s->alpha*0.5*rmatrixsyvmv(n, &s->a, 0, 0, ae_true, x, 0, tmp, _state); - } - if( ae_fp_greater(s->tau,(double)(0)) ) - { - for(i=0; i<=n-1; i++) - { - result = result+0.5*ae_sqr(x->ptr.p_double[i], _state)*s->tau*s->d.ptr.p_double[i]; - } - } - return result; -} - - -/************************************************************************* -This subroutine evaluates (0.5*alpha*A+tau*D)*x - -Y is automatically resized if needed - - -- ALGLIB -- - Copyright 12.06.2012 by Bochkanov Sergey -*************************************************************************/ -void cqmadx(convexquadraticmodel* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - - - n = s->n; - ae_assert(isfinitevector(x, n, _state), "CQMEval: X is not finite vector", _state); - rvectorsetlengthatleast(y, n, _state); - - /* - * main quadratic term - */ - for(i=0; i<=n-1; i++) - { - y->ptr.p_double[i] = (double)(0); - } - if( ae_fp_greater(s->alpha,(double)(0)) ) - { - rmatrixsymv(n, s->alpha, &s->a, 0, 0, ae_true, x, 0, 1.0, y, 0, _state); - } - if( ae_fp_greater(s->tau,(double)(0)) ) - { - for(i=0; i<=n-1; i++) - { - y->ptr.p_double[i] = y->ptr.p_double[i]+x->ptr.p_double[i]*s->tau*s->d.ptr.p_double[i]; - } - } -} - - -/************************************************************************* -This subroutine finds optimum of the model. It returns False on failure -(indefinite/semidefinite matrix). Optimum is found subject to active -constraints. - -INPUT PARAMETERS - S - model - X - possibly preallocated buffer; automatically resized, if - too small enough. - - -- ALGLIB -- - Copyright 12.06.2012 by Bochkanov Sergey -*************************************************************************/ -ae_bool cqmconstrainedoptimum(convexquadraticmodel* s, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nfree; - ae_int_t k; - ae_int_t i; - double v; - ae_int_t cidx0; - ae_int_t itidx; - ae_bool result; - - - - /* - * Rebuild internal structures - */ - if( !cqmodels_cqmrebuild(s, _state) ) - { - result = ae_false; - return result; - } - n = s->n; - k = s->k; - nfree = s->nfree; - result = ae_true; - - /* - * Calculate initial point for the iterative refinement: - * * free components are set to zero - * * constrained components are set to their constrained values - */ - rvectorsetlengthatleast(x, n, _state); - for(i=0; i<=n-1; i++) - { - if( s->activeset.ptr.p_bool[i] ) - { - x->ptr.p_double[i] = s->xc.ptr.p_double[i]; - } - else - { - x->ptr.p_double[i] = (double)(0); - } - } - - /* - * Iterative refinement. - * - * In an ideal world without numerical errors it would be enough - * to make just one Newton step from initial point: - * x_new = -H^(-1)*grad(x=0) - * However, roundoff errors can significantly deteriorate quality - * of the solution. So we have to recalculate gradient and to - * perform Newton steps several times. - * - * Below we perform fixed number of Newton iterations. - */ - for(itidx=0; itidx<=cqmodels_newtonrefinementits-1; itidx++) - { - - /* - * Calculate gradient at the current point. - * Move free components of the gradient in the beginning. - */ - cqmgradunconstrained(s, x, &s->tmpg, _state); - cidx0 = 0; - for(i=0; i<=n-1; i++) - { - if( !s->activeset.ptr.p_bool[i] ) - { - s->tmpg.ptr.p_double[cidx0] = s->tmpg.ptr.p_double[i]; - cidx0 = cidx0+1; - } - } - - /* - * Free components of the extrema are calculated in the first NFree elements of TXC. - * - * First, we have to calculate original Newton step, without rank-K perturbations - */ - ae_v_moveneg(&s->txc.ptr.p_double[0], 1, &s->tmpg.ptr.p_double[0], 1, ae_v_len(0,nfree-1)); - cqmodels_cqmsolveea(s, &s->txc, &s->tmp0, _state); - - /* - * Then, we account for rank-K correction. - * Woodbury matrix identity is used. - */ - if( s->k>0&&ae_fp_greater(s->theta,(double)(0)) ) - { - rvectorsetlengthatleast(&s->tmp0, ae_maxint(nfree, k, _state), _state); - rvectorsetlengthatleast(&s->tmp1, ae_maxint(nfree, k, _state), _state); - ae_v_moveneg(&s->tmp1.ptr.p_double[0], 1, &s->tmpg.ptr.p_double[0], 1, ae_v_len(0,nfree-1)); - cqmodels_cqmsolveea(s, &s->tmp1, &s->tmp0, _state); - for(i=0; i<=k-1; i++) - { - v = ae_v_dotproduct(&s->eq.ptr.pp_double[i][0], 1, &s->tmp1.ptr.p_double[0], 1, ae_v_len(0,nfree-1)); - s->tmp0.ptr.p_double[i] = v; - } - fblscholeskysolve(&s->eccm, 1.0, k, ae_true, &s->tmp0, &s->tmp1, _state); - for(i=0; i<=nfree-1; i++) - { - s->tmp1.ptr.p_double[i] = 0.0; - } - for(i=0; i<=k-1; i++) - { - v = s->tmp0.ptr.p_double[i]; - ae_v_addd(&s->tmp1.ptr.p_double[0], 1, &s->eq.ptr.pp_double[i][0], 1, ae_v_len(0,nfree-1), v); - } - cqmodels_cqmsolveea(s, &s->tmp1, &s->tmp0, _state); - ae_v_sub(&s->txc.ptr.p_double[0], 1, &s->tmp1.ptr.p_double[0], 1, ae_v_len(0,nfree-1)); - } - - /* - * Unpack components from TXC into X. We pass through all - * free components of X and add our step. - */ - cidx0 = 0; - for(i=0; i<=n-1; i++) - { - if( !s->activeset.ptr.p_bool[i] ) - { - x->ptr.p_double[i] = x->ptr.p_double[i]+s->txc.ptr.p_double[cidx0]; - cidx0 = cidx0+1; - } - } - } - return result; -} - - -/************************************************************************* -This function scales vector by multiplying it by inverse of the diagonal -of the Hessian matrix. It should be used to accelerate steepest descent -phase of the QP solver. - -Although it is called "scale-grad", it can be called for any vector, -whether it is gradient, anti-gradient, or just some vector. - -This function does NOT takes into account current set of constraints, it -just performs matrix-vector multiplication without taking into account -constraints. - -INPUT PARAMETERS: - S - model - X - vector to scale - -OUTPUT PARAMETERS: - X - scaled vector - -NOTE: - when called for non-SPD matrices, it silently skips components of X - which correspond to zero or negative diagonal elements. - -NOTE: - this function uses diagonals of A and D; it ignores Q - rank-K term of - the quadratic model. - - -- ALGLIB -- - Copyright 12.06.2012 by Bochkanov Sergey -*************************************************************************/ -void cqmscalevector(convexquadraticmodel* s, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - double v; - - - n = s->n; - for(i=0; i<=n-1; i++) - { - v = 0.0; - if( ae_fp_greater(s->alpha,(double)(0)) ) - { - v = v+s->a.ptr.pp_double[i][i]; - } - if( ae_fp_greater(s->tau,(double)(0)) ) - { - v = v+s->d.ptr.p_double[i]; - } - if( ae_fp_greater(v,(double)(0)) ) - { - x->ptr.p_double[i] = x->ptr.p_double[i]/v; - } - } -} - - -/************************************************************************* -This function returns diagonal of the A-term. - -INPUT PARAMETERS: - S - model - -OUTPUT PARAMETERS: - D - diagonal of the A (or zero) - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -void cqmgetdiaga(convexquadraticmodel* s, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - - - n = s->n; - rvectorsetlengthatleast(x, n, _state); - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(s->alpha,(double)(0)) ) - { - x->ptr.p_double[i] = s->a.ptr.pp_double[i][i]; - } - else - { - x->ptr.p_double[i] = (double)(0); - } - } -} - - -/************************************************************************* -This subroutine calls CQMRebuild() and evaluates model at X subject to -active constraints. - -It is intended for debug purposes only, because it evaluates model by -means of temporaries, which were calculated by CQMRebuild(). The only -purpose of this function is to check correctness of CQMRebuild() by -comparing results of this function with ones obtained by CQMEval(), which -is used as reference point. The idea is that significant deviation in -results of these two functions is evidence of some error in the -CQMRebuild(). - -NOTE: suffix T denotes that temporaries marked by T-prefix are used. There - is one more variant of this function, which uses "effective" model - built by CQMRebuild(). - -NOTE2: in case CQMRebuild() fails (due to model non-convexity), this - function returns NAN. - - -- ALGLIB -- - Copyright 12.06.2012 by Bochkanov Sergey -*************************************************************************/ -double cqmdebugconstrainedevalt(convexquadraticmodel* s, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nfree; - ae_int_t i; - ae_int_t j; - double v; - double result; - - - n = s->n; - ae_assert(isfinitevector(x, n, _state), "CQMDebugConstrainedEvalT: X is not finite vector", _state); - if( !cqmodels_cqmrebuild(s, _state) ) - { - result = _state->v_nan; - return result; - } - result = 0.0; - nfree = s->nfree; - - /* - * Reorder variables - */ - j = 0; - for(i=0; i<=n-1; i++) - { - if( !s->activeset.ptr.p_bool[i] ) - { - ae_assert(jtxc.ptr.p_double[j] = x->ptr.p_double[i]; - j = j+1; - } - } - - /* - * TQ2, TQ1, TQ0 - * - */ - if( ae_fp_greater(s->alpha,(double)(0)) ) - { - - /* - * Dense TQ2 - */ - for(i=0; i<=nfree-1; i++) - { - for(j=0; j<=nfree-1; j++) - { - result = result+0.5*s->txc.ptr.p_double[i]*s->tq2dense.ptr.pp_double[i][j]*s->txc.ptr.p_double[j]; - } - } - } - else - { - - /* - * Diagonal TQ2 - */ - for(i=0; i<=nfree-1; i++) - { - result = result+0.5*s->tq2diag.ptr.p_double[i]*ae_sqr(s->txc.ptr.p_double[i], _state); - } - } - for(i=0; i<=nfree-1; i++) - { - result = result+s->tq1.ptr.p_double[i]*s->txc.ptr.p_double[i]; - } - result = result+s->tq0; - - /* - * TK2, TK1, TK0 - */ - if( s->k>0&&ae_fp_greater(s->theta,(double)(0)) ) - { - for(i=0; i<=s->k-1; i++) - { - v = (double)(0); - for(j=0; j<=nfree-1; j++) - { - v = v+s->tk2.ptr.pp_double[i][j]*s->txc.ptr.p_double[j]; - } - result = result+0.5*ae_sqr(v, _state); - } - for(i=0; i<=nfree-1; i++) - { - result = result+s->tk1.ptr.p_double[i]*s->txc.ptr.p_double[i]; - } - result = result+s->tk0; - } - - /* - * TB (Bf and Bc parts) - */ - for(i=0; i<=n-1; i++) - { - result = result+s->tb.ptr.p_double[i]*s->txc.ptr.p_double[i]; - } - return result; -} - - -/************************************************************************* -This subroutine calls CQMRebuild() and evaluates model at X subject to -active constraints. - -It is intended for debug purposes only, because it evaluates model by -means of "effective" matrices built by CQMRebuild(). The only purpose of -this function is to check correctness of CQMRebuild() by comparing results -of this function with ones obtained by CQMEval(), which is used as -reference point. The idea is that significant deviation in results of -these two functions is evidence of some error in the CQMRebuild(). - -NOTE: suffix E denotes that effective matrices. There is one more variant - of this function, which uses temporary matrices built by - CQMRebuild(). - -NOTE2: in case CQMRebuild() fails (due to model non-convexity), this - function returns NAN. - - -- ALGLIB -- - Copyright 12.06.2012 by Bochkanov Sergey -*************************************************************************/ -double cqmdebugconstrainedevale(convexquadraticmodel* s, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nfree; - ae_int_t i; - ae_int_t j; - double v; - double result; - - - n = s->n; - ae_assert(isfinitevector(x, n, _state), "CQMDebugConstrainedEvalE: X is not finite vector", _state); - if( !cqmodels_cqmrebuild(s, _state) ) - { - result = _state->v_nan; - return result; - } - result = 0.0; - nfree = s->nfree; - - /* - * Reorder variables - */ - j = 0; - for(i=0; i<=n-1; i++) - { - if( !s->activeset.ptr.p_bool[i] ) - { - ae_assert(jtxc.ptr.p_double[j] = x->ptr.p_double[i]; - j = j+1; - } - } - - /* - * ECA - */ - ae_assert((s->ecakind==0||s->ecakind==1)||(s->ecakind==-1&&nfree==0), "CQMDebugConstrainedEvalE: unexpected ECAKind", _state); - if( s->ecakind==0 ) - { - - /* - * Dense ECA - */ - for(i=0; i<=nfree-1; i++) - { - v = 0.0; - for(j=i; j<=nfree-1; j++) - { - v = v+s->ecadense.ptr.pp_double[i][j]*s->txc.ptr.p_double[j]; - } - result = result+0.5*ae_sqr(v, _state); - } - } - if( s->ecakind==1 ) - { - - /* - * Diagonal ECA - */ - for(i=0; i<=nfree-1; i++) - { - result = result+0.5*ae_sqr(s->ecadiag.ptr.p_double[i]*s->txc.ptr.p_double[i], _state); - } - } - - /* - * EQ - */ - for(i=0; i<=s->k-1; i++) - { - v = 0.0; - for(j=0; j<=nfree-1; j++) - { - v = v+s->eq.ptr.pp_double[i][j]*s->txc.ptr.p_double[j]; - } - result = result+0.5*ae_sqr(v, _state); - } - - /* - * EB - */ - for(i=0; i<=nfree-1; i++) - { - result = result+s->eb.ptr.p_double[i]*s->txc.ptr.p_double[i]; - } - - /* - * EC - */ - result = result+s->ec; - return result; -} - - -/************************************************************************* -Internal function, rebuilds "effective" model subject to constraints. -Returns False on failure (non-SPD main quadratic term) - - -- ALGLIB -- - Copyright 10.05.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool cqmodels_cqmrebuild(convexquadraticmodel* s, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nfree; - ae_int_t k; - ae_int_t i; - ae_int_t j; - ae_int_t ridx0; - ae_int_t ridx1; - ae_int_t cidx0; - ae_int_t cidx1; - double v; - ae_bool result; - - - if( ae_fp_eq(s->alpha,(double)(0))&&ae_fp_eq(s->tau,(double)(0)) ) - { - - /* - * Non-SPD model, quick exit - */ - result = ae_false; - return result; - } - result = ae_true; - n = s->n; - k = s->k; - - /* - * Determine number of free variables. - * Fill TXC - array whose last N-NFree elements store constraints. - */ - if( s->isactivesetchanged ) - { - s->nfree = 0; - for(i=0; i<=n-1; i++) - { - if( !s->activeset.ptr.p_bool[i] ) - { - s->nfree = s->nfree+1; - } - } - j = s->nfree; - for(i=0; i<=n-1; i++) - { - if( s->activeset.ptr.p_bool[i] ) - { - s->txc.ptr.p_double[j] = s->xc.ptr.p_double[i]; - j = j+1; - } - } - } - nfree = s->nfree; - - /* - * Re-evaluate TQ2/TQ1/TQ0, if needed - */ - if( s->isactivesetchanged||s->ismaintermchanged ) - { - - /* - * Handle cases Alpha>0 and Alpha=0 separately: - * * in the first case we have dense matrix - * * in the second one we have diagonal matrix, which can be - * handled more efficiently - */ - if( ae_fp_greater(s->alpha,(double)(0)) ) - { - - /* - * Alpha>0, dense QP - * - * Split variables into two groups - free (F) and constrained (C). Reorder - * variables in such way that free vars come first, constrained are last: - * x = [xf, xc]. - * - * Main quadratic term x'*(alpha*A+tau*D)*x now splits into quadratic part, - * linear part and constant part: - * ( alpha*Aff+tau*Df alpha*Afc ) ( xf ) - * 0.5*( xf' xc' )*( )*( ) = - * ( alpha*Acf alpha*Acc+tau*Dc ) ( xc ) - * - * = 0.5*xf'*(alpha*Aff+tau*Df)*xf + (alpha*Afc*xc)'*xf + 0.5*xc'(alpha*Acc+tau*Dc)*xc - * - * We store these parts into temporary variables: - * * alpha*Aff+tau*Df, alpha*Afc, alpha*Acc+tau*Dc are stored into upper - * triangle of TQ2 - * * alpha*Afc*xc is stored into TQ1 - * * 0.5*xc'(alpha*Acc+tau*Dc)*xc is stored into TQ0 - * - * Below comes first part of the work - generation of TQ2: - * * we pass through rows of A and copy I-th row into upper block (Aff/Afc) or - * lower one (Acf/Acc) of TQ2, depending on presence of X[i] in the active set. - * RIdx0 variable contains current position for insertion into upper block, - * RIdx1 contains current position for insertion into lower one. - * * within each row, we copy J-th element into left half (Aff/Acf) or right - * one (Afc/Acc), depending on presence of X[j] in the active set. CIdx0 - * contains current position for insertion into left block, CIdx1 contains - * position for insertion into right one. - * * during copying, we multiply elements by alpha and add diagonal matrix D. - */ - ridx0 = 0; - ridx1 = s->nfree; - for(i=0; i<=n-1; i++) - { - cidx0 = 0; - cidx1 = s->nfree; - for(j=0; j<=n-1; j++) - { - if( !s->activeset.ptr.p_bool[i]&&!s->activeset.ptr.p_bool[j] ) - { - - /* - * Element belongs to Aff - */ - v = s->alpha*s->a.ptr.pp_double[i][j]; - if( i==j&&ae_fp_greater(s->tau,(double)(0)) ) - { - v = v+s->tau*s->d.ptr.p_double[i]; - } - s->tq2dense.ptr.pp_double[ridx0][cidx0] = v; - } - if( !s->activeset.ptr.p_bool[i]&&s->activeset.ptr.p_bool[j] ) - { - - /* - * Element belongs to Afc - */ - s->tq2dense.ptr.pp_double[ridx0][cidx1] = s->alpha*s->a.ptr.pp_double[i][j]; - } - if( s->activeset.ptr.p_bool[i]&&!s->activeset.ptr.p_bool[j] ) - { - - /* - * Element belongs to Acf - */ - s->tq2dense.ptr.pp_double[ridx1][cidx0] = s->alpha*s->a.ptr.pp_double[i][j]; - } - if( s->activeset.ptr.p_bool[i]&&s->activeset.ptr.p_bool[j] ) - { - - /* - * Element belongs to Acc - */ - v = s->alpha*s->a.ptr.pp_double[i][j]; - if( i==j&&ae_fp_greater(s->tau,(double)(0)) ) - { - v = v+s->tau*s->d.ptr.p_double[i]; - } - s->tq2dense.ptr.pp_double[ridx1][cidx1] = v; - } - if( s->activeset.ptr.p_bool[j] ) - { - cidx1 = cidx1+1; - } - else - { - cidx0 = cidx0+1; - } - } - if( s->activeset.ptr.p_bool[i] ) - { - ridx1 = ridx1+1; - } - else - { - ridx0 = ridx0+1; - } - } - - /* - * Now we have TQ2, and we can evaluate TQ1. - * In the special case when we have Alpha=0, NFree=0 or NFree=N, - * TQ1 is filled by zeros. - */ - for(i=0; i<=n-1; i++) - { - s->tq1.ptr.p_double[i] = 0.0; - } - if( s->nfree>0&&s->nfreenfree, n-s->nfree, &s->tq2dense, 0, s->nfree, 0, &s->txc, s->nfree, &s->tq1, 0, _state); - } - - /* - * And finally, we evaluate TQ0. - */ - v = 0.0; - for(i=s->nfree; i<=n-1; i++) - { - for(j=s->nfree; j<=n-1; j++) - { - v = v+0.5*s->txc.ptr.p_double[i]*s->tq2dense.ptr.pp_double[i][j]*s->txc.ptr.p_double[j]; - } - } - s->tq0 = v; - } - else - { - - /* - * Alpha=0, diagonal QP - * - * Split variables into two groups - free (F) and constrained (C). Reorder - * variables in such way that free vars come first, constrained are last: - * x = [xf, xc]. - * - * Main quadratic term x'*(tau*D)*x now splits into quadratic and constant - * parts: - * ( tau*Df ) ( xf ) - * 0.5*( xf' xc' )*( )*( ) = - * ( tau*Dc ) ( xc ) - * - * = 0.5*xf'*(tau*Df)*xf + 0.5*xc'(tau*Dc)*xc - * - * We store these parts into temporary variables: - * * tau*Df is stored in TQ2Diag - * * 0.5*xc'(tau*Dc)*xc is stored into TQ0 - */ - s->tq0 = 0.0; - ridx0 = 0; - for(i=0; i<=n-1; i++) - { - if( !s->activeset.ptr.p_bool[i] ) - { - s->tq2diag.ptr.p_double[ridx0] = s->tau*s->d.ptr.p_double[i]; - ridx0 = ridx0+1; - } - else - { - s->tq0 = s->tq0+0.5*s->tau*s->d.ptr.p_double[i]*ae_sqr(s->xc.ptr.p_double[i], _state); - } - } - for(i=0; i<=n-1; i++) - { - s->tq1.ptr.p_double[i] = 0.0; - } - } - } - - /* - * Re-evaluate TK2/TK1/TK0, if needed - */ - if( s->isactivesetchanged||s->issecondarytermchanged ) - { - - /* - * Split variables into two groups - free (F) and constrained (C). Reorder - * variables in such way that free vars come first, constrained are last: - * x = [xf, xc]. - * - * Secondary term theta*(Q*x-r)'*(Q*x-r) now splits into quadratic part, - * linear part and constant part: - * ( ( xf ) )' ( ( xf ) ) - * 0.5*theta*( (Qf Qc)'*( ) - r ) * ( (Qf Qc)'*( ) - r ) = - * ( ( xc ) ) ( ( xc ) ) - * - * = 0.5*theta*xf'*(Qf'*Qf)*xf + theta*((Qc*xc-r)'*Qf)*xf + - * + theta*(-r'*(Qc*xc-r)-0.5*r'*r+0.5*xc'*Qc'*Qc*xc) - * - * We store these parts into temporary variables: - * * sqrt(theta)*Qf is stored into TK2 - * * theta*((Qc*xc-r)'*Qf) is stored into TK1 - * * theta*(-r'*(Qc*xc-r)-0.5*r'*r+0.5*xc'*Qc'*Qc*xc) is stored into TK0 - * - * We use several other temporaries to store intermediate results: - * * Tmp0 - to store Qc*xc-r - * * Tmp1 - to store Qc*xc - * - * Generation of TK2/TK1/TK0 is performed as follows: - * * we fill TK2/TK1/TK0 (to handle K=0 or Theta=0) - * * other steps are performed only for K>0 and Theta>0 - * * we pass through columns of Q and copy I-th column into left block (Qf) or - * right one (Qc) of TK2, depending on presence of X[i] in the active set. - * CIdx0 variable contains current position for insertion into upper block, - * CIdx1 contains current position for insertion into lower one. - * * we calculate Qc*xc-r and store it into Tmp0 - * * we calculate TK0 and TK1 - * * we multiply leading part of TK2 which stores Qf by sqrt(theta) - * it is important to perform this step AFTER calculation of TK0 and TK1, - * because we need original (non-modified) Qf to calculate TK0 and TK1. - */ - for(j=0; j<=n-1; j++) - { - for(i=0; i<=k-1; i++) - { - s->tk2.ptr.pp_double[i][j] = 0.0; - } - s->tk1.ptr.p_double[j] = 0.0; - } - s->tk0 = 0.0; - if( s->k>0&&ae_fp_greater(s->theta,(double)(0)) ) - { - - /* - * Split Q into Qf and Qc - * Calculate Qc*xc-r, store in Tmp0 - */ - rvectorsetlengthatleast(&s->tmp0, k, _state); - rvectorsetlengthatleast(&s->tmp1, k, _state); - cidx0 = 0; - cidx1 = nfree; - for(i=0; i<=k-1; i++) - { - s->tmp1.ptr.p_double[i] = 0.0; - } - for(j=0; j<=n-1; j++) - { - if( s->activeset.ptr.p_bool[j] ) - { - for(i=0; i<=k-1; i++) - { - s->tk2.ptr.pp_double[i][cidx1] = s->q.ptr.pp_double[i][j]; - s->tmp1.ptr.p_double[i] = s->tmp1.ptr.p_double[i]+s->q.ptr.pp_double[i][j]*s->txc.ptr.p_double[cidx1]; - } - cidx1 = cidx1+1; - } - else - { - for(i=0; i<=k-1; i++) - { - s->tk2.ptr.pp_double[i][cidx0] = s->q.ptr.pp_double[i][j]; - } - cidx0 = cidx0+1; - } - } - for(i=0; i<=k-1; i++) - { - s->tmp0.ptr.p_double[i] = s->tmp1.ptr.p_double[i]-s->r.ptr.p_double[i]; - } - - /* - * Calculate TK0 - */ - v = 0.0; - for(i=0; i<=k-1; i++) - { - v = v+s->theta*(0.5*ae_sqr(s->tmp1.ptr.p_double[i], _state)-s->r.ptr.p_double[i]*s->tmp0.ptr.p_double[i]-0.5*ae_sqr(s->r.ptr.p_double[i], _state)); - } - s->tk0 = v; - - /* - * Calculate TK1 - */ - if( nfree>0 ) - { - for(i=0; i<=k-1; i++) - { - v = s->theta*s->tmp0.ptr.p_double[i]; - ae_v_addd(&s->tk1.ptr.p_double[0], 1, &s->tk2.ptr.pp_double[i][0], 1, ae_v_len(0,nfree-1), v); - } - } - - /* - * Calculate TK2 - */ - if( nfree>0 ) - { - v = ae_sqrt(s->theta, _state); - for(i=0; i<=k-1; i++) - { - ae_v_muld(&s->tk2.ptr.pp_double[i][0], 1, ae_v_len(0,nfree-1), v); - } - } - } - } - - /* - * Re-evaluate TB - */ - if( s->isactivesetchanged||s->islineartermchanged ) - { - ridx0 = 0; - ridx1 = nfree; - for(i=0; i<=n-1; i++) - { - if( s->activeset.ptr.p_bool[i] ) - { - s->tb.ptr.p_double[ridx1] = s->b.ptr.p_double[i]; - ridx1 = ridx1+1; - } - else - { - s->tb.ptr.p_double[ridx0] = s->b.ptr.p_double[i]; - ridx0 = ridx0+1; - } - } - } - - /* - * Compose ECA: either dense ECA or diagonal ECA - */ - if( (s->isactivesetchanged||s->ismaintermchanged)&&nfree>0 ) - { - if( ae_fp_greater(s->alpha,(double)(0)) ) - { - - /* - * Dense ECA - */ - s->ecakind = 0; - for(i=0; i<=nfree-1; i++) - { - for(j=i; j<=nfree-1; j++) - { - s->ecadense.ptr.pp_double[i][j] = s->tq2dense.ptr.pp_double[i][j]; - } - } - if( !spdmatrixcholeskyrec(&s->ecadense, 0, nfree, ae_true, &s->tmp0, _state) ) - { - result = ae_false; - return result; - } - } - else - { - - /* - * Diagonal ECA - */ - s->ecakind = 1; - for(i=0; i<=nfree-1; i++) - { - if( ae_fp_less(s->tq2diag.ptr.p_double[i],(double)(0)) ) - { - result = ae_false; - return result; - } - s->ecadiag.ptr.p_double[i] = ae_sqrt(s->tq2diag.ptr.p_double[i], _state); - } - } - } - - /* - * Compose EQ - */ - if( s->isactivesetchanged||s->issecondarytermchanged ) - { - for(i=0; i<=k-1; i++) - { - for(j=0; j<=nfree-1; j++) - { - s->eq.ptr.pp_double[i][j] = s->tk2.ptr.pp_double[i][j]; - } - } - } - - /* - * Calculate ECCM - */ - if( ((((s->isactivesetchanged||s->ismaintermchanged)||s->issecondarytermchanged)&&s->k>0)&&ae_fp_greater(s->theta,(double)(0)))&&nfree>0 ) - { - - /* - * Calculate ECCM - Cholesky factor of the "effective" capacitance - * matrix CM = I + EQ*inv(EffectiveA)*EQ'. - * - * We calculate CM as follows: - * CM = I + EQ*inv(EffectiveA)*EQ' - * = I + EQ*ECA^(-1)*ECA^(-T)*EQ' - * = I + (EQ*ECA^(-1))*(EQ*ECA^(-1))' - * - * Then we perform Cholesky decomposition of CM. - */ - rmatrixsetlengthatleast(&s->tmp2, k, n, _state); - rmatrixcopy(k, nfree, &s->eq, 0, 0, &s->tmp2, 0, 0, _state); - ae_assert(s->ecakind==0||s->ecakind==1, "CQMRebuild: unexpected ECAKind", _state); - if( s->ecakind==0 ) - { - rmatrixrighttrsm(k, nfree, &s->ecadense, 0, 0, ae_true, ae_false, 0, &s->tmp2, 0, 0, _state); - } - if( s->ecakind==1 ) - { - for(i=0; i<=k-1; i++) - { - for(j=0; j<=nfree-1; j++) - { - s->tmp2.ptr.pp_double[i][j] = s->tmp2.ptr.pp_double[i][j]/s->ecadiag.ptr.p_double[j]; - } - } - } - for(i=0; i<=k-1; i++) - { - for(j=0; j<=k-1; j++) - { - s->eccm.ptr.pp_double[i][j] = 0.0; - } - s->eccm.ptr.pp_double[i][i] = 1.0; - } - rmatrixsyrk(k, nfree, 1.0, &s->tmp2, 0, 0, 0, 1.0, &s->eccm, 0, 0, ae_true, _state); - if( !spdmatrixcholeskyrec(&s->eccm, 0, k, ae_true, &s->tmp0, _state) ) - { - result = ae_false; - return result; - } - } - - /* - * Compose EB and EC - * - * NOTE: because these quantities are cheap to compute, we do not - * use caching here. - */ - for(i=0; i<=nfree-1; i++) - { - s->eb.ptr.p_double[i] = s->tq1.ptr.p_double[i]+s->tk1.ptr.p_double[i]+s->tb.ptr.p_double[i]; - } - s->ec = s->tq0+s->tk0; - for(i=nfree; i<=n-1; i++) - { - s->ec = s->ec+s->tb.ptr.p_double[i]*s->txc.ptr.p_double[i]; - } - - /* - * Change cache status - everything is cached - */ - s->ismaintermchanged = ae_false; - s->issecondarytermchanged = ae_false; - s->islineartermchanged = ae_false; - s->isactivesetchanged = ae_false; - return result; -} - - -/************************************************************************* -Internal function, solves system Effective_A*x = b. -It should be called after successful completion of CQMRebuild(). - -INPUT PARAMETERS: - S - quadratic model, after call to CQMRebuild() - X - right part B, array[S.NFree] - Tmp - temporary array, automatically reallocated if needed - -OUTPUT PARAMETERS: - X - solution, array[S.NFree] - -NOTE: when called with zero S.NFree, returns silently -NOTE: this function assumes that EA is non-degenerate - - -- ALGLIB -- - Copyright 10.05.2011 by Bochkanov Sergey -*************************************************************************/ -static void cqmodels_cqmsolveea(convexquadraticmodel* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* tmp, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert((s->ecakind==0||s->ecakind==1)||(s->ecakind==-1&&s->nfree==0), "CQMSolveEA: unexpected ECAKind", _state); - if( s->ecakind==0 ) - { - - /* - * Dense ECA, use FBLSCholeskySolve() dense solver. - */ - fblscholeskysolve(&s->ecadense, 1.0, s->nfree, ae_true, x, tmp, _state); - } - if( s->ecakind==1 ) - { - - /* - * Diagonal ECA - */ - for(i=0; i<=s->nfree-1; i++) - { - x->ptr.p_double[i] = x->ptr.p_double[i]/ae_sqr(s->ecadiag.ptr.p_double[i], _state); - } - } -} - - -void _convexquadraticmodel_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - convexquadraticmodel *p = (convexquadraticmodel*)_p; - ae_touch_ptr((void*)p); - ae_matrix_init(&p->a, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->q, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->b, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->r, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->activeset, 0, DT_BOOL, _state, make_automatic); - ae_matrix_init(&p->tq2dense, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->tk2, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tq2diag, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tq1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tk1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->txc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tb, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->ecadense, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->eq, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->eccm, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ecadiag, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->eb, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpg, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->tmp2, 0, 0, DT_REAL, _state, make_automatic); -} - - -void _convexquadraticmodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - convexquadraticmodel *dst = (convexquadraticmodel*)_dst; - convexquadraticmodel *src = (convexquadraticmodel*)_src; - dst->n = src->n; - dst->k = src->k; - dst->alpha = src->alpha; - dst->tau = src->tau; - dst->theta = src->theta; - ae_matrix_init_copy(&dst->a, &src->a, _state, make_automatic); - ae_matrix_init_copy(&dst->q, &src->q, _state, make_automatic); - ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic); - ae_vector_init_copy(&dst->r, &src->r, _state, make_automatic); - ae_vector_init_copy(&dst->xc, &src->xc, _state, make_automatic); - ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic); - ae_vector_init_copy(&dst->activeset, &src->activeset, _state, make_automatic); - ae_matrix_init_copy(&dst->tq2dense, &src->tq2dense, _state, make_automatic); - ae_matrix_init_copy(&dst->tk2, &src->tk2, _state, make_automatic); - ae_vector_init_copy(&dst->tq2diag, &src->tq2diag, _state, make_automatic); - ae_vector_init_copy(&dst->tq1, &src->tq1, _state, make_automatic); - ae_vector_init_copy(&dst->tk1, &src->tk1, _state, make_automatic); - dst->tq0 = src->tq0; - dst->tk0 = src->tk0; - ae_vector_init_copy(&dst->txc, &src->txc, _state, make_automatic); - ae_vector_init_copy(&dst->tb, &src->tb, _state, make_automatic); - dst->nfree = src->nfree; - dst->ecakind = src->ecakind; - ae_matrix_init_copy(&dst->ecadense, &src->ecadense, _state, make_automatic); - ae_matrix_init_copy(&dst->eq, &src->eq, _state, make_automatic); - ae_matrix_init_copy(&dst->eccm, &src->eccm, _state, make_automatic); - ae_vector_init_copy(&dst->ecadiag, &src->ecadiag, _state, make_automatic); - ae_vector_init_copy(&dst->eb, &src->eb, _state, make_automatic); - dst->ec = src->ec; - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic); - ae_vector_init_copy(&dst->tmpg, &src->tmpg, _state, make_automatic); - ae_matrix_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic); - dst->ismaintermchanged = src->ismaintermchanged; - dst->issecondarytermchanged = src->issecondarytermchanged; - dst->islineartermchanged = src->islineartermchanged; - dst->isactivesetchanged = src->isactivesetchanged; -} - - -void _convexquadraticmodel_clear(void* _p) -{ - convexquadraticmodel *p = (convexquadraticmodel*)_p; - ae_touch_ptr((void*)p); - ae_matrix_clear(&p->a); - ae_matrix_clear(&p->q); - ae_vector_clear(&p->b); - ae_vector_clear(&p->r); - ae_vector_clear(&p->xc); - ae_vector_clear(&p->d); - ae_vector_clear(&p->activeset); - ae_matrix_clear(&p->tq2dense); - ae_matrix_clear(&p->tk2); - ae_vector_clear(&p->tq2diag); - ae_vector_clear(&p->tq1); - ae_vector_clear(&p->tk1); - ae_vector_clear(&p->txc); - ae_vector_clear(&p->tb); - ae_matrix_clear(&p->ecadense); - ae_matrix_clear(&p->eq); - ae_matrix_clear(&p->eccm); - ae_vector_clear(&p->ecadiag); - ae_vector_clear(&p->eb); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->tmp1); - ae_vector_clear(&p->tmpg); - ae_matrix_clear(&p->tmp2); -} - - -void _convexquadraticmodel_destroy(void* _p) -{ - convexquadraticmodel *p = (convexquadraticmodel*)_p; - ae_touch_ptr((void*)p); - ae_matrix_destroy(&p->a); - ae_matrix_destroy(&p->q); - ae_vector_destroy(&p->b); - ae_vector_destroy(&p->r); - ae_vector_destroy(&p->xc); - ae_vector_destroy(&p->d); - ae_vector_destroy(&p->activeset); - ae_matrix_destroy(&p->tq2dense); - ae_matrix_destroy(&p->tk2); - ae_vector_destroy(&p->tq2diag); - ae_vector_destroy(&p->tq1); - ae_vector_destroy(&p->tk1); - ae_vector_destroy(&p->txc); - ae_vector_destroy(&p->tb); - ae_matrix_destroy(&p->ecadense); - ae_matrix_destroy(&p->eq); - ae_matrix_destroy(&p->eccm); - ae_vector_destroy(&p->ecadiag); - ae_vector_destroy(&p->eb); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->tmp1); - ae_vector_destroy(&p->tmpg); - ae_matrix_destroy(&p->tmp2); -} - - -#endif -#if defined(AE_COMPILE_OPTGUARDAPI) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This subroutine initializes "internal" OptGuard report, i.e. one intended -for internal use by optimizers. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -void optguardinitinternal(optguardreport* rep, - ae_int_t n, - ae_int_t k, - ae_state *_state) -{ - - - rep->nonc0suspected = ae_false; - rep->nonc0test0positive = ae_false; - rep->nonc0lipschitzc = (double)(0); - rep->nonc0fidx = -1; - rep->nonc1suspected = ae_false; - rep->nonc1test0positive = ae_false; - rep->nonc1test1positive = ae_false; - rep->nonc1lipschitzc = (double)(0); - rep->nonc1fidx = -1; - rep->badgradsuspected = ae_false; - rep->badgradfidx = -1; - rep->badgradvidx = -1; -} - - -/************************************************************************* -This subroutine exports report to user-readable representation (all arrays -are forced to have exactly same size as needed; unused arrays are set to -zero length). - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -void optguardexportreport(optguardreport* srcrep, - ae_int_t n, - ae_int_t k, - ae_bool badgradhasxj, - optguardreport* dstrep, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - dstrep->nonc0suspected = srcrep->nonc0suspected; - dstrep->nonc0test0positive = srcrep->nonc0test0positive; - if( srcrep->nonc0suspected ) - { - dstrep->nonc0lipschitzc = srcrep->nonc0lipschitzc; - dstrep->nonc0fidx = srcrep->nonc0fidx; - } - else - { - dstrep->nonc0lipschitzc = (double)(0); - dstrep->nonc0fidx = -1; - } - dstrep->nonc1suspected = srcrep->nonc1suspected; - dstrep->nonc1test0positive = srcrep->nonc1test0positive; - dstrep->nonc1test1positive = srcrep->nonc1test1positive; - if( srcrep->nonc1suspected ) - { - dstrep->nonc1lipschitzc = srcrep->nonc1lipschitzc; - dstrep->nonc1fidx = srcrep->nonc1fidx; - } - else - { - dstrep->nonc1lipschitzc = (double)(0); - dstrep->nonc1fidx = -1; - } - dstrep->badgradsuspected = srcrep->badgradsuspected; - if( srcrep->badgradsuspected ) - { - dstrep->badgradfidx = srcrep->badgradfidx; - dstrep->badgradvidx = srcrep->badgradvidx; - } - else - { - dstrep->badgradfidx = -1; - dstrep->badgradvidx = -1; - } - if( badgradhasxj ) - { - ae_vector_set_length(&dstrep->badgradxbase, n, _state); - for(j=0; j<=n-1; j++) - { - dstrep->badgradxbase.ptr.p_double[j] = srcrep->badgradxbase.ptr.p_double[j]; - } - ae_matrix_set_length(&dstrep->badgraduser, k, n, _state); - ae_matrix_set_length(&dstrep->badgradnum, k, n, _state); - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - dstrep->badgraduser.ptr.pp_double[i][j] = srcrep->badgraduser.ptr.pp_double[i][j]; - dstrep->badgradnum.ptr.pp_double[i][j] = srcrep->badgradnum.ptr.pp_double[i][j]; - } - } - } - else - { - ae_vector_set_length(&dstrep->badgradxbase, 0, _state); - ae_matrix_set_length(&dstrep->badgraduser, 0, 0, _state); - ae_matrix_set_length(&dstrep->badgradnum, 0, 0, _state); - } -} - - -/************************************************************************* -This subroutine exports report to user-readable representation (all arrays -are forced to have exactly same size as needed; unused arrays are set to -zero length). - -NOTE: we assume that SrcRep contains scaled X0[] and D[], i.e. explicit - variable scaling was applied. We need to rescale them during export, - that's why we need S[] parameter. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -void smoothnessmonitorexportc1test0report(optguardnonc1test0report* srcrep, - /* Real */ ae_vector* s, - optguardnonc1test0report* dstrep, - ae_state *_state) -{ - ae_int_t i; - - - dstrep->positive = srcrep->positive; - if( srcrep->positive ) - { - dstrep->stpidxa = srcrep->stpidxa; - dstrep->stpidxb = srcrep->stpidxb; - dstrep->fidx = srcrep->fidx; - dstrep->cnt = srcrep->cnt; - dstrep->n = srcrep->n; - ae_vector_set_length(&dstrep->x0, srcrep->n, _state); - ae_vector_set_length(&dstrep->d, srcrep->n, _state); - for(i=0; i<=srcrep->n-1; i++) - { - dstrep->x0.ptr.p_double[i] = srcrep->x0.ptr.p_double[i]*s->ptr.p_double[i]; - dstrep->d.ptr.p_double[i] = srcrep->d.ptr.p_double[i]*s->ptr.p_double[i]; - } - ae_vector_set_length(&dstrep->stp, srcrep->cnt, _state); - ae_vector_set_length(&dstrep->f, srcrep->cnt, _state); - for(i=0; i<=srcrep->cnt-1; i++) - { - dstrep->stp.ptr.p_double[i] = srcrep->stp.ptr.p_double[i]; - dstrep->f.ptr.p_double[i] = srcrep->f.ptr.p_double[i]; - } - } - else - { - dstrep->stpidxa = -1; - dstrep->stpidxb = -1; - dstrep->fidx = -1; - dstrep->cnt = 0; - dstrep->n = 0; - ae_vector_set_length(&dstrep->x0, 0, _state); - ae_vector_set_length(&dstrep->d, 0, _state); - ae_vector_set_length(&dstrep->stp, 0, _state); - ae_vector_set_length(&dstrep->f, 0, _state); - } -} - - -/************************************************************************* -This subroutine exports report to user-readable representation (all arrays -are forced to have exactly same size as needed; unused arrays are set to -zero length). - -NOTE: we assume that SrcRep contains scaled X0[], D[] and G[], i.e. explicit - variable scaling was applied. We need to rescale them during export, - that's why we need S[] parameter. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -void smoothnessmonitorexportc1test1report(optguardnonc1test1report* srcrep, - /* Real */ ae_vector* s, - optguardnonc1test1report* dstrep, - ae_state *_state) -{ - ae_int_t i; - - - dstrep->positive = srcrep->positive; - if( srcrep->positive ) - { - ae_assert(srcrep->vidx>=0&&srcrep->vidxn, "SmoothnessMonitorExportC1Test1Report: integrity check failed", _state); - dstrep->stpidxa = srcrep->stpidxa; - dstrep->stpidxb = srcrep->stpidxb; - dstrep->fidx = srcrep->fidx; - dstrep->vidx = srcrep->vidx; - dstrep->cnt = srcrep->cnt; - dstrep->n = srcrep->n; - ae_vector_set_length(&dstrep->x0, srcrep->n, _state); - ae_vector_set_length(&dstrep->d, srcrep->n, _state); - for(i=0; i<=srcrep->n-1; i++) - { - dstrep->x0.ptr.p_double[i] = srcrep->x0.ptr.p_double[i]*s->ptr.p_double[i]; - dstrep->d.ptr.p_double[i] = srcrep->d.ptr.p_double[i]*s->ptr.p_double[i]; - } - ae_vector_set_length(&dstrep->stp, srcrep->cnt, _state); - ae_vector_set_length(&dstrep->g, srcrep->cnt, _state); - for(i=0; i<=srcrep->cnt-1; i++) - { - dstrep->stp.ptr.p_double[i] = srcrep->stp.ptr.p_double[i]; - dstrep->g.ptr.p_double[i] = srcrep->g.ptr.p_double[i]/s->ptr.p_double[srcrep->vidx]; - } - } - else - { - dstrep->stpidxa = -1; - dstrep->stpidxb = -1; - dstrep->fidx = -1; - dstrep->vidx = -1; - dstrep->cnt = 0; - dstrep->n = 0; - ae_vector_set_length(&dstrep->x0, 0, _state); - ae_vector_set_length(&dstrep->d, 0, _state); - ae_vector_set_length(&dstrep->stp, 0, _state); - ae_vector_set_length(&dstrep->g, 0, _state); - } -} - - -/************************************************************************* -Returns True when all flags are clear. Intended for easy coding of unit -tests. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -ae_bool optguardallclear(optguardreport* rep, ae_state *_state) -{ - ae_bool result; - - - result = !((rep->badgradsuspected||rep->nonc0suspected)||rep->nonc1suspected); - return result; -} - - -void _optguardreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - optguardreport *p = (optguardreport*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->badgradxbase, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->badgraduser, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->badgradnum, 0, 0, DT_REAL, _state, make_automatic); -} - - -void _optguardreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - optguardreport *dst = (optguardreport*)_dst; - optguardreport *src = (optguardreport*)_src; - dst->nonc0suspected = src->nonc0suspected; - dst->nonc0test0positive = src->nonc0test0positive; - dst->nonc0fidx = src->nonc0fidx; - dst->nonc0lipschitzc = src->nonc0lipschitzc; - dst->nonc1suspected = src->nonc1suspected; - dst->nonc1test0positive = src->nonc1test0positive; - dst->nonc1test1positive = src->nonc1test1positive; - dst->nonc1fidx = src->nonc1fidx; - dst->nonc1lipschitzc = src->nonc1lipschitzc; - dst->badgradsuspected = src->badgradsuspected; - dst->badgradfidx = src->badgradfidx; - dst->badgradvidx = src->badgradvidx; - ae_vector_init_copy(&dst->badgradxbase, &src->badgradxbase, _state, make_automatic); - ae_matrix_init_copy(&dst->badgraduser, &src->badgraduser, _state, make_automatic); - ae_matrix_init_copy(&dst->badgradnum, &src->badgradnum, _state, make_automatic); -} - - -void _optguardreport_clear(void* _p) -{ - optguardreport *p = (optguardreport*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->badgradxbase); - ae_matrix_clear(&p->badgraduser); - ae_matrix_clear(&p->badgradnum); -} - - -void _optguardreport_destroy(void* _p) -{ - optguardreport *p = (optguardreport*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->badgradxbase); - ae_matrix_destroy(&p->badgraduser); - ae_matrix_destroy(&p->badgradnum); -} - - -void _optguardnonc0report_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - optguardnonc0report *p = (optguardnonc0report*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->x0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stp, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->f, 0, DT_REAL, _state, make_automatic); -} - - -void _optguardnonc0report_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - optguardnonc0report *dst = (optguardnonc0report*)_dst; - optguardnonc0report *src = (optguardnonc0report*)_src; - dst->positive = src->positive; - dst->fidx = src->fidx; - ae_vector_init_copy(&dst->x0, &src->x0, _state, make_automatic); - ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic); - dst->n = src->n; - ae_vector_init_copy(&dst->stp, &src->stp, _state, make_automatic); - ae_vector_init_copy(&dst->f, &src->f, _state, make_automatic); - dst->cnt = src->cnt; - dst->stpidxa = src->stpidxa; - dst->stpidxb = src->stpidxb; -} - - -void _optguardnonc0report_clear(void* _p) -{ - optguardnonc0report *p = (optguardnonc0report*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->x0); - ae_vector_clear(&p->d); - ae_vector_clear(&p->stp); - ae_vector_clear(&p->f); -} - - -void _optguardnonc0report_destroy(void* _p) -{ - optguardnonc0report *p = (optguardnonc0report*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->x0); - ae_vector_destroy(&p->d); - ae_vector_destroy(&p->stp); - ae_vector_destroy(&p->f); -} - - -void _optguardnonc1test0report_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - optguardnonc1test0report *p = (optguardnonc1test0report*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->x0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stp, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->f, 0, DT_REAL, _state, make_automatic); -} - - -void _optguardnonc1test0report_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - optguardnonc1test0report *dst = (optguardnonc1test0report*)_dst; - optguardnonc1test0report *src = (optguardnonc1test0report*)_src; - dst->positive = src->positive; - dst->fidx = src->fidx; - ae_vector_init_copy(&dst->x0, &src->x0, _state, make_automatic); - ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic); - dst->n = src->n; - ae_vector_init_copy(&dst->stp, &src->stp, _state, make_automatic); - ae_vector_init_copy(&dst->f, &src->f, _state, make_automatic); - dst->cnt = src->cnt; - dst->stpidxa = src->stpidxa; - dst->stpidxb = src->stpidxb; -} - - -void _optguardnonc1test0report_clear(void* _p) -{ - optguardnonc1test0report *p = (optguardnonc1test0report*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->x0); - ae_vector_clear(&p->d); - ae_vector_clear(&p->stp); - ae_vector_clear(&p->f); -} - - -void _optguardnonc1test0report_destroy(void* _p) -{ - optguardnonc1test0report *p = (optguardnonc1test0report*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->x0); - ae_vector_destroy(&p->d); - ae_vector_destroy(&p->stp); - ae_vector_destroy(&p->f); -} - - -void _optguardnonc1test1report_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - optguardnonc1test1report *p = (optguardnonc1test1report*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->x0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stp, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic); -} - - -void _optguardnonc1test1report_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - optguardnonc1test1report *dst = (optguardnonc1test1report*)_dst; - optguardnonc1test1report *src = (optguardnonc1test1report*)_src; - dst->positive = src->positive; - dst->fidx = src->fidx; - dst->vidx = src->vidx; - ae_vector_init_copy(&dst->x0, &src->x0, _state, make_automatic); - ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic); - dst->n = src->n; - ae_vector_init_copy(&dst->stp, &src->stp, _state, make_automatic); - ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic); - dst->cnt = src->cnt; - dst->stpidxa = src->stpidxa; - dst->stpidxb = src->stpidxb; -} - - -void _optguardnonc1test1report_clear(void* _p) -{ - optguardnonc1test1report *p = (optguardnonc1test1report*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->x0); - ae_vector_clear(&p->d); - ae_vector_clear(&p->stp); - ae_vector_clear(&p->g); -} - - -void _optguardnonc1test1report_destroy(void* _p) -{ - optguardnonc1test1report *p = (optguardnonc1test1report*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->x0); - ae_vector_destroy(&p->d); - ae_vector_destroy(&p->stp); - ae_vector_destroy(&p->g); -} - - -#endif -#if defined(AE_COMPILE_OPTSERV) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This subroutine checks violation of the box constraints. On output it sets -bcerr to the maximum scaled violation, bcidx to the index of the violating -constraint. - -if bcerr=0 (say, if no constraints are violated) then bcidx=-1. - -If nonunits=false then s[] is not referenced at all (assumed unit). - - -- ALGLIB -- - Copyright 7.11.2018 by Bochkanov Sergey -*************************************************************************/ -void checkbcviolation(/* Boolean */ ae_vector* hasbndl, - /* Real */ ae_vector* bndl, - /* Boolean */ ae_vector* hasbndu, - /* Real */ ae_vector* bndu, - /* Real */ ae_vector* x, - ae_int_t n, - /* Real */ ae_vector* s, - ae_bool nonunits, - double* bcerr, - ae_int_t* bcidx, - ae_state *_state) -{ - ae_int_t i; - double vs; - double ve; - - *bcerr = 0; - *bcidx = 0; - - *bcerr = (double)(0); - *bcidx = -1; - for(i=0; i<=n-1; i++) - { - - /* - * Fetch scale - */ - if( nonunits ) - { - vs = 1/s->ptr.p_double[i]; - } - else - { - vs = (double)(1); - } - - /* - * Check lower bound - */ - if( hasbndl->ptr.p_bool[i]&&x->ptr.p_double[i]ptr.p_double[i] ) - { - ve = (bndl->ptr.p_double[i]-x->ptr.p_double[i])*vs; - if( ve>*bcerr ) - { - *bcerr = ve; - *bcidx = i; - } - } - - /* - * Check upper bound - */ - if( hasbndu->ptr.p_bool[i]&&x->ptr.p_double[i]>bndu->ptr.p_double[i] ) - { - ve = (x->ptr.p_double[i]-bndu->ptr.p_double[i])*vs; - if( ve>*bcerr ) - { - *bcerr = ve; - *bcidx = i; - } - } - } -} - - -/************************************************************************* -This subroutine checks violation of the general linear constraints. - -Constraints are assumed to be un-normalized and stored in the format "NEC -equality ones followed by NIC inequality ones". - -On output it sets lcerr to the maximum scaled violation, lcidx to the source -index of the most violating constraint (row indexes of CLEIC are mapped to -the indexes of the "original" constraints via LCSrcIdx[] array. - -if lcerr=0 (say, if no constraints are violated) then lcidx=-1. - -If nonunits=false then s[] is not referenced at all (assumed unit). - - -- ALGLIB -- - Copyright 7.11.2018 by Bochkanov Sergey -*************************************************************************/ -void checklcviolation(/* Real */ ae_matrix* cleic, - /* Integer */ ae_vector* lcsrcidx, - ae_int_t nec, - ae_int_t nic, - /* Real */ ae_vector* x, - ae_int_t n, - double* lcerr, - ae_int_t* lcidx, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double cx; - double cnrm; - double v; - - *lcerr = 0; - *lcidx = 0; - - *lcerr = (double)(0); - *lcidx = -1; - for(i=0; i<=nec+nic-1; i++) - { - cx = -cleic->ptr.pp_double[i][n]; - cnrm = (double)(0); - for(j=0; j<=n-1; j++) - { - v = cleic->ptr.pp_double[i][j]; - cx = cx+v*x->ptr.p_double[j]; - cnrm = cnrm+v*v; - } - cnrm = ae_sqrt(cnrm, _state); - cx = cx/coalesce(cnrm, (double)(1), _state); - if( i*lcerr ) - { - *lcerr = cx; - *lcidx = lcsrcidx->ptr.p_int[i]; - } - } -} - - -/************************************************************************* -This subroutine checks violation of the nonlinear constraints. Fi[0] is the -target value (ignored), Fi[1:NG+NH] are values of nonlinear constraints. - -On output it sets nlcerr to the scaled violation, nlcidx to the index -of the most violating constraint in [0,NG+NH-1] range. - -if nlcerr=0 (say, if no constraints are violated) then nlcidx=-1. - -If nonunits=false then s[] is not referenced at all (assumed unit). - - -- ALGLIB -- - Copyright 7.11.2018 by Bochkanov Sergey -*************************************************************************/ -void checknlcviolation(/* Real */ ae_vector* fi, - ae_int_t ng, - ae_int_t nh, - double* nlcerr, - ae_int_t* nlcidx, - ae_state *_state) -{ - ae_int_t i; - double v; - - *nlcerr = 0; - *nlcidx = 0; - - *nlcerr = (double)(0); - *nlcidx = -1; - for(i=0; i<=ng+nh-1; i++) - { - v = fi->ptr.p_double[i+1]; - if( i*nlcerr ) - { - *nlcerr = v; - *nlcidx = i; - } - } -} - - -/************************************************************************* -This subroutine is same as CheckNLCViolation, but is works with scaled -constraints: it assumes that Fi[] were divided by FScales[] vector BEFORE -passing them to this function. - -The function checks scaled values, but reports unscaled errors. - - -- ALGLIB -- - Copyright 7.11.2018 by Bochkanov Sergey -*************************************************************************/ -void unscaleandchecknlcviolation(/* Real */ ae_vector* fi, - /* Real */ ae_vector* fscales, - ae_int_t ng, - ae_int_t nh, - double* nlcerr, - ae_int_t* nlcidx, - ae_state *_state) -{ - ae_int_t i; - double v; - - *nlcerr = 0; - *nlcidx = 0; - - *nlcerr = (double)(0); - *nlcidx = -1; - for(i=0; i<=ng+nh-1; i++) - { - ae_assert(ae_fp_greater(fscales->ptr.p_double[i+1],(double)(0)), "UnscaleAndCheckNLCViolation: integrity check failed", _state); - v = fi->ptr.p_double[i+1]*fscales->ptr.p_double[i+1]; - if( i*nlcerr ) - { - *nlcerr = v; - *nlcidx = i; - } - } -} - - -/************************************************************************* -This subroutine is used to prepare threshold value which will be used for -trimming of the target function (see comments on TrimFunction() for more -information). - -This function accepts only one parameter: function value at the starting -point. It returns threshold which will be used for trimming. - - -- ALGLIB -- - Copyright 10.05.2011 by Bochkanov Sergey -*************************************************************************/ -void trimprepare(double f, double* threshold, ae_state *_state) -{ - - *threshold = 0; - - *threshold = 10*(ae_fabs(f, _state)+1); -} - - -/************************************************************************* -This subroutine is used to "trim" target function, i.e. to do following -transformation: - - { {F,G} if F=Threshold - -Such transformation allows us to solve problems with singularities by -redefining function in such way that it becomes bounded from above. - - -- ALGLIB -- - Copyright 10.05.2011 by Bochkanov Sergey -*************************************************************************/ -void trimfunction(double* f, - /* Real */ ae_vector* g, - ae_int_t n, - double threshold, - ae_state *_state) -{ - ae_int_t i; - - - if( ae_fp_greater_eq(*f,threshold) ) - { - *f = threshold; - for(i=0; i<=n-1; i++) - { - g->ptr.p_double[i] = 0.0; - } - } -} - - -/************************************************************************* -This function enforces boundary constraints in the X. - -This function correctly (although a bit inefficient) handles BL[i] which -are -INF and BU[i] which are +INF. - -We have NMain+NSlack dimensional X, with first NMain components bounded -by BL/BU, and next NSlack ones bounded by non-negativity constraints. - -INPUT PARAMETERS - X - array[NMain+NSlack], point - BL - array[NMain], lower bounds - (may contain -INF, when bound is not present) - HaveBL - array[NMain], if HaveBL[i] is False, - then i-th bound is not present - BU - array[NMain], upper bounds - (may contain +INF, when bound is not present) - HaveBU - array[NMain], if HaveBU[i] is False, - then i-th bound is not present - -OUTPUT PARAMETERS - X - X with all constraints being enforced - -It returns True when constraints are consistent, -False - when constraints are inconsistent. - - -- ALGLIB -- - Copyright 10.01.2012 by Bochkanov Sergey -*************************************************************************/ -ae_bool enforceboundaryconstraints(/* Real */ ae_vector* x, - /* Real */ ae_vector* bl, - /* Boolean */ ae_vector* havebl, - /* Real */ ae_vector* bu, - /* Boolean */ ae_vector* havebu, - ae_int_t nmain, - ae_int_t nslack, - ae_state *_state) -{ - ae_int_t i; - ae_bool result; - - - result = ae_false; - for(i=0; i<=nmain-1; i++) - { - if( (havebl->ptr.p_bool[i]&&havebu->ptr.p_bool[i])&&ae_fp_greater(bl->ptr.p_double[i],bu->ptr.p_double[i]) ) - { - return result; - } - if( havebl->ptr.p_bool[i]&&ae_fp_less(x->ptr.p_double[i],bl->ptr.p_double[i]) ) - { - x->ptr.p_double[i] = bl->ptr.p_double[i]; - } - if( havebu->ptr.p_bool[i]&&ae_fp_greater(x->ptr.p_double[i],bu->ptr.p_double[i]) ) - { - x->ptr.p_double[i] = bu->ptr.p_double[i]; - } - } - for(i=0; i<=nslack-1; i++) - { - if( ae_fp_less(x->ptr.p_double[nmain+i],(double)(0)) ) - { - x->ptr.p_double[nmain+i] = (double)(0); - } - } - result = ae_true; - return result; -} - - -/************************************************************************* -This function projects gradient into feasible area of boundary constrained -optimization problem. X can be infeasible with respect to boundary -constraints. We have NMain+NSlack dimensional X, with first NMain -components bounded by BL/BU, and next NSlack ones bounded by non-negativity -constraints. - -INPUT PARAMETERS - X - array[NMain+NSlack], point - G - array[NMain+NSlack], gradient - BL - lower bounds (may contain -INF, when bound is not present) - HaveBL - if HaveBL[i] is False, then i-th bound is not present - BU - upper bounds (may contain +INF, when bound is not present) - HaveBU - if HaveBU[i] is False, then i-th bound is not present - -OUTPUT PARAMETERS - G - projection of G. Components of G which satisfy one of the - following - (1) (X[I]<=BndL[I]) and (G[I]>0), OR - (2) (X[I]>=BndU[I]) and (G[I]<0) - are replaced by zeros. - -NOTE 1: this function assumes that constraints are feasible. It throws -exception otherwise. - -NOTE 2: in fact, projection of ANTI-gradient is calculated, because this -function trims components of -G which points outside of the feasible area. -However, working with -G is considered confusing, because all optimization -source work with G. - - -- ALGLIB -- - Copyright 10.01.2012 by Bochkanov Sergey -*************************************************************************/ -void projectgradientintobc(/* Real */ ae_vector* x, - /* Real */ ae_vector* g, - /* Real */ ae_vector* bl, - /* Boolean */ ae_vector* havebl, - /* Real */ ae_vector* bu, - /* Boolean */ ae_vector* havebu, - ae_int_t nmain, - ae_int_t nslack, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=nmain-1; i++) - { - ae_assert((!havebl->ptr.p_bool[i]||!havebu->ptr.p_bool[i])||ae_fp_less_eq(bl->ptr.p_double[i],bu->ptr.p_double[i]), "ProjectGradientIntoBC: internal error (infeasible constraints)", _state); - if( (havebl->ptr.p_bool[i]&&ae_fp_less_eq(x->ptr.p_double[i],bl->ptr.p_double[i]))&&ae_fp_greater(g->ptr.p_double[i],(double)(0)) ) - { - g->ptr.p_double[i] = (double)(0); - } - if( (havebu->ptr.p_bool[i]&&ae_fp_greater_eq(x->ptr.p_double[i],bu->ptr.p_double[i]))&&ae_fp_less(g->ptr.p_double[i],(double)(0)) ) - { - g->ptr.p_double[i] = (double)(0); - } - } - for(i=0; i<=nslack-1; i++) - { - if( ae_fp_less_eq(x->ptr.p_double[nmain+i],(double)(0))&&ae_fp_greater(g->ptr.p_double[nmain+i],(double)(0)) ) - { - g->ptr.p_double[nmain+i] = (double)(0); - } - } -} - - -/************************************************************************* -Given - a) initial point X0[NMain+NSlack] - (feasible with respect to bound constraints) - b) step vector alpha*D[NMain+NSlack] - c) boundary constraints BndL[NMain], BndU[NMain] - d) implicit non-negativity constraints for slack variables -this function calculates bound on the step length subject to boundary -constraints. - -It returns: - * MaxStepLen - such step length that X0+MaxStepLen*alpha*D is exactly - at the boundary given by constraints - * VariableToFreeze - index of the constraint to be activated, - 0 <= VariableToFreeze < NMain+NSlack - * ValueToFreeze - value of the corresponding constraint. - -Notes: - * it is possible that several constraints can be activated by the step - at once. In such cases only one constraint is returned. It is caller - responsibility to check other constraints. This function makes sure - that we activate at least one constraint, and everything else is the - responsibility of the caller. - * steps smaller than MaxStepLen still can activate constraints due to - numerical errors. Thus purpose of this function is not to guard - against accidental activation of the constraints - quite the reverse, - its purpose is to activate at least constraint upon performing step - which is too long. - * in case there is no constraints to activate, we return negative - VariableToFreeze and zero MaxStepLen and ValueToFreeze. - * this function assumes that constraints are consistent; it throws - exception otherwise. - -INPUT PARAMETERS - X - array[NMain+NSlack], point. Must be feasible with respect - to bound constraints (exception will be thrown otherwise) - D - array[NMain+NSlack], step direction - alpha - scalar multiplier before D, alpha<>0 - BndL - lower bounds, array[NMain] - (may contain -INF, when bound is not present) - HaveBndL - array[NMain], if HaveBndL[i] is False, - then i-th bound is not present - BndU - array[NMain], upper bounds - (may contain +INF, when bound is not present) - HaveBndU - array[NMain], if HaveBndU[i] is False, - then i-th bound is not present - NMain - number of main variables - NSlack - number of slack variables - -OUTPUT PARAMETERS - VariableToFreeze: - * negative value = step is unbounded, ValueToFreeze=0, - MaxStepLen=0. - * non-negative value = at least one constraint, given by - this parameter, will be activated - upon performing maximum step. - ValueToFreeze- value of the variable which will be constrained - MaxStepLen - maximum length of the step. Can be zero when step vector - looks outside of the feasible area. - - -- ALGLIB -- - Copyright 10.01.2012 by Bochkanov Sergey -*************************************************************************/ -void calculatestepbound(/* Real */ ae_vector* x, - /* Real */ ae_vector* d, - double alpha, - /* Real */ ae_vector* bndl, - /* Boolean */ ae_vector* havebndl, - /* Real */ ae_vector* bndu, - /* Boolean */ ae_vector* havebndu, - ae_int_t nmain, - ae_int_t nslack, - ae_int_t* variabletofreeze, - double* valuetofreeze, - double* maxsteplen, - ae_state *_state) -{ - ae_int_t i; - double prevmax; - double initval; - - *variabletofreeze = 0; - *valuetofreeze = 0; - *maxsteplen = 0; - - ae_assert(ae_fp_neq(alpha,(double)(0)), "CalculateStepBound: zero alpha", _state); - *variabletofreeze = -1; - initval = ae_maxrealnumber; - *maxsteplen = initval; - for(i=0; i<=nmain-1; i++) - { - if( havebndl->ptr.p_bool[i]&&ae_fp_less(alpha*d->ptr.p_double[i],(double)(0)) ) - { - ae_assert(ae_fp_greater_eq(x->ptr.p_double[i],bndl->ptr.p_double[i]), "CalculateStepBound: infeasible X", _state); - prevmax = *maxsteplen; - *maxsteplen = safeminposrv(x->ptr.p_double[i]-bndl->ptr.p_double[i], -alpha*d->ptr.p_double[i], *maxsteplen, _state); - if( ae_fp_less(*maxsteplen,prevmax) ) - { - *variabletofreeze = i; - *valuetofreeze = bndl->ptr.p_double[i]; - } - } - if( havebndu->ptr.p_bool[i]&&ae_fp_greater(alpha*d->ptr.p_double[i],(double)(0)) ) - { - ae_assert(ae_fp_less_eq(x->ptr.p_double[i],bndu->ptr.p_double[i]), "CalculateStepBound: infeasible X", _state); - prevmax = *maxsteplen; - *maxsteplen = safeminposrv(bndu->ptr.p_double[i]-x->ptr.p_double[i], alpha*d->ptr.p_double[i], *maxsteplen, _state); - if( ae_fp_less(*maxsteplen,prevmax) ) - { - *variabletofreeze = i; - *valuetofreeze = bndu->ptr.p_double[i]; - } - } - } - for(i=0; i<=nslack-1; i++) - { - if( ae_fp_less(alpha*d->ptr.p_double[nmain+i],(double)(0)) ) - { - ae_assert(ae_fp_greater_eq(x->ptr.p_double[nmain+i],(double)(0)), "CalculateStepBound: infeasible X", _state); - prevmax = *maxsteplen; - *maxsteplen = safeminposrv(x->ptr.p_double[nmain+i], -alpha*d->ptr.p_double[nmain+i], *maxsteplen, _state); - if( ae_fp_less(*maxsteplen,prevmax) ) - { - *variabletofreeze = nmain+i; - *valuetofreeze = (double)(0); - } - } - } - if( ae_fp_eq(*maxsteplen,initval) ) - { - *valuetofreeze = (double)(0); - *maxsteplen = (double)(0); - } -} - - -/************************************************************************* -This function postprocesses bounded step by: -* analysing step length (whether it is equal to MaxStepLen) and activating - constraint given by VariableToFreeze if needed -* checking for additional bound constraints to activate - -This function uses final point of the step, quantities calculated by the -CalculateStepBound() function. As result, it returns point which is -exactly feasible with respect to boundary constraints. - -NOTE 1: this function does NOT handle and check linear equality constraints -NOTE 2: when StepTaken=MaxStepLen we always activate at least one constraint - -INPUT PARAMETERS - X - array[NMain+NSlack], final point to postprocess - XPrev - array[NMain+NSlack], initial point - BndL - lower bounds, array[NMain] - (may contain -INF, when bound is not present) - HaveBndL - array[NMain], if HaveBndL[i] is False, - then i-th bound is not present - BndU - array[NMain], upper bounds - (may contain +INF, when bound is not present) - HaveBndU - array[NMain], if HaveBndU[i] is False, - then i-th bound is not present - NMain - number of main variables - NSlack - number of slack variables - VariableToFreeze-result of CalculateStepBound() - ValueToFreeze- result of CalculateStepBound() - StepTaken - actual step length (actual step is equal to the possibly - non-unit step direction vector times this parameter). - StepTaken<=MaxStepLen. - MaxStepLen - result of CalculateStepBound() - -OUTPUT PARAMETERS - X - point bounded with respect to constraints. - components corresponding to active constraints are exactly - equal to the boundary values. - -RESULT: - number of constraints activated in addition to previously active ones. - Constraints which were DEACTIVATED are ignored (do not influence - function value). - - -- ALGLIB -- - Copyright 10.01.2012 by Bochkanov Sergey -*************************************************************************/ -ae_int_t postprocessboundedstep(/* Real */ ae_vector* x, - /* Real */ ae_vector* xprev, - /* Real */ ae_vector* bndl, - /* Boolean */ ae_vector* havebndl, - /* Real */ ae_vector* bndu, - /* Boolean */ ae_vector* havebndu, - ae_int_t nmain, - ae_int_t nslack, - ae_int_t variabletofreeze, - double valuetofreeze, - double steptaken, - double maxsteplen, - ae_state *_state) -{ - ae_int_t i; - ae_bool wasactivated; - ae_int_t result; - - - ae_assert(variabletofreeze<0||ae_fp_less_eq(steptaken,maxsteplen), "Assertion failed", _state); - - /* - * Activate constraints - */ - if( variabletofreeze>=0&&ae_fp_eq(steptaken,maxsteplen) ) - { - x->ptr.p_double[variabletofreeze] = valuetofreeze; - } - for(i=0; i<=nmain-1; i++) - { - if( havebndl->ptr.p_bool[i]&&ae_fp_less(x->ptr.p_double[i],bndl->ptr.p_double[i]) ) - { - x->ptr.p_double[i] = bndl->ptr.p_double[i]; - } - if( havebndu->ptr.p_bool[i]&&ae_fp_greater(x->ptr.p_double[i],bndu->ptr.p_double[i]) ) - { - x->ptr.p_double[i] = bndu->ptr.p_double[i]; - } - } - for(i=0; i<=nslack-1; i++) - { - if( ae_fp_less_eq(x->ptr.p_double[nmain+i],(double)(0)) ) - { - x->ptr.p_double[nmain+i] = (double)(0); - } - } - - /* - * Calculate number of constraints being activated - */ - result = 0; - for(i=0; i<=nmain-1; i++) - { - wasactivated = ae_fp_neq(x->ptr.p_double[i],xprev->ptr.p_double[i])&&((havebndl->ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],bndl->ptr.p_double[i]))||(havebndu->ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],bndu->ptr.p_double[i]))); - wasactivated = wasactivated||variabletofreeze==i; - if( wasactivated ) - { - result = result+1; - } - } - for(i=0; i<=nslack-1; i++) - { - wasactivated = ae_fp_neq(x->ptr.p_double[nmain+i],xprev->ptr.p_double[nmain+i])&&ae_fp_eq(x->ptr.p_double[nmain+i],0.0); - wasactivated = wasactivated||variabletofreeze==nmain+i; - if( wasactivated ) - { - result = result+1; - } - } - return result; -} - - -/************************************************************************* -The purpose of this function is to prevent algorithm from "unsticking" -from the active bound constraints because of numerical noise in the -gradient or Hessian. - -It is done by zeroing some components of the search direction D. D[i] is -zeroed when both (a) and (b) are true: -a) corresponding X[i] is exactly at the boundary -b) |D[i]*S[i]| <= DropTol*Sqrt(SUM(D[i]^2*S[I]^2)) - -D can be step direction , antigradient, gradient, or anything similar. -Sign of D does not matter, nor matters step length. - -NOTE 1: boundary constraints are expected to be consistent, as well as X - is expected to be feasible. Exception will be thrown otherwise. - -INPUT PARAMETERS - D - array[NMain+NSlack], direction - X - array[NMain+NSlack], current point - BndL - lower bounds, array[NMain] - (may contain -INF, when bound is not present) - HaveBndL - array[NMain], if HaveBndL[i] is False, - then i-th bound is not present - BndU - array[NMain], upper bounds - (may contain +INF, when bound is not present) - HaveBndU - array[NMain], if HaveBndU[i] is False, - then i-th bound is not present - S - array[NMain+NSlack], scaling of the variables - NMain - number of main variables - NSlack - number of slack variables - DropTol - drop tolerance, >=0 - -OUTPUT PARAMETERS - X - point bounded with respect to constraints. - components corresponding to active constraints are exactly - equal to the boundary values. - - -- ALGLIB -- - Copyright 10.01.2012 by Bochkanov Sergey -*************************************************************************/ -void filterdirection(/* Real */ ae_vector* d, - /* Real */ ae_vector* x, - /* Real */ ae_vector* bndl, - /* Boolean */ ae_vector* havebndl, - /* Real */ ae_vector* bndu, - /* Boolean */ ae_vector* havebndu, - /* Real */ ae_vector* s, - ae_int_t nmain, - ae_int_t nslack, - double droptol, - ae_state *_state) -{ - ae_int_t i; - double scalednorm; - ae_bool isactive; - - - scalednorm = 0.0; - for(i=0; i<=nmain+nslack-1; i++) - { - scalednorm = scalednorm+ae_sqr(d->ptr.p_double[i]*s->ptr.p_double[i], _state); - } - scalednorm = ae_sqrt(scalednorm, _state); - for(i=0; i<=nmain-1; i++) - { - ae_assert(!havebndl->ptr.p_bool[i]||ae_fp_greater_eq(x->ptr.p_double[i],bndl->ptr.p_double[i]), "FilterDirection: infeasible point", _state); - ae_assert(!havebndu->ptr.p_bool[i]||ae_fp_less_eq(x->ptr.p_double[i],bndu->ptr.p_double[i]), "FilterDirection: infeasible point", _state); - isactive = (havebndl->ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],bndl->ptr.p_double[i]))||(havebndu->ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],bndu->ptr.p_double[i])); - if( isactive&&ae_fp_less_eq(ae_fabs(d->ptr.p_double[i]*s->ptr.p_double[i], _state),droptol*scalednorm) ) - { - d->ptr.p_double[i] = 0.0; - } - } - for(i=0; i<=nslack-1; i++) - { - ae_assert(ae_fp_greater_eq(x->ptr.p_double[nmain+i],(double)(0)), "FilterDirection: infeasible point", _state); - if( ae_fp_eq(x->ptr.p_double[nmain+i],(double)(0))&&ae_fp_less_eq(ae_fabs(d->ptr.p_double[nmain+i]*s->ptr.p_double[nmain+i], _state),droptol*scalednorm) ) - { - d->ptr.p_double[nmain+i] = 0.0; - } - } -} - - -/************************************************************************* -This function returns number of bound constraints whose state was changed -(either activated or deactivated) when making step from XPrev to X. - -Constraints are considered: -* active - when we are exactly at the boundary -* inactive - when we are not at the boundary - -You should note that antigradient direction is NOT taken into account when -we make decions on the constraint status. - -INPUT PARAMETERS - X - array[NMain+NSlack], final point. - Must be feasible with respect to bound constraints. - XPrev - array[NMain+NSlack], initial point. - Must be feasible with respect to bound constraints. - BndL - lower bounds, array[NMain] - (may contain -INF, when bound is not present) - HaveBndL - array[NMain], if HaveBndL[i] is False, - then i-th bound is not present - BndU - array[NMain], upper bounds - (may contain +INF, when bound is not present) - HaveBndU - array[NMain], if HaveBndU[i] is False, - then i-th bound is not present - NMain - number of main variables - NSlack - number of slack variables - -RESULT: - number of constraints whose state was changed. - - -- ALGLIB -- - Copyright 10.01.2012 by Bochkanov Sergey -*************************************************************************/ -ae_int_t numberofchangedconstraints(/* Real */ ae_vector* x, - /* Real */ ae_vector* xprev, - /* Real */ ae_vector* bndl, - /* Boolean */ ae_vector* havebndl, - /* Real */ ae_vector* bndu, - /* Boolean */ ae_vector* havebndu, - ae_int_t nmain, - ae_int_t nslack, - ae_state *_state) -{ - ae_int_t i; - ae_bool statuschanged; - ae_int_t result; - - - result = 0; - for(i=0; i<=nmain-1; i++) - { - if( ae_fp_neq(x->ptr.p_double[i],xprev->ptr.p_double[i]) ) - { - statuschanged = ae_false; - if( havebndl->ptr.p_bool[i]&&(ae_fp_eq(x->ptr.p_double[i],bndl->ptr.p_double[i])||ae_fp_eq(xprev->ptr.p_double[i],bndl->ptr.p_double[i])) ) - { - statuschanged = ae_true; - } - if( havebndu->ptr.p_bool[i]&&(ae_fp_eq(x->ptr.p_double[i],bndu->ptr.p_double[i])||ae_fp_eq(xprev->ptr.p_double[i],bndu->ptr.p_double[i])) ) - { - statuschanged = ae_true; - } - if( statuschanged ) - { - result = result+1; - } - } - } - for(i=0; i<=nslack-1; i++) - { - if( ae_fp_neq(x->ptr.p_double[nmain+i],xprev->ptr.p_double[nmain+i])&&(ae_fp_eq(x->ptr.p_double[nmain+i],(double)(0))||ae_fp_eq(xprev->ptr.p_double[nmain+i],(double)(0))) ) - { - result = result+1; - } - } - return result; -} - - -/************************************************************************* -This function finds feasible point of (NMain+NSlack)-dimensional problem -subject to NMain explicit boundary constraints (some constraints can be -omitted), NSlack implicit non-negativity constraints, K linear equality -constraints. - -INPUT PARAMETERS - X - array[NMain+NSlack], initial point. - BndL - lower bounds, array[NMain] - (may contain -INF, when bound is not present) - HaveBndL - array[NMain], if HaveBndL[i] is False, - then i-th bound is not present - BndU - array[NMain], upper bounds - (may contain +INF, when bound is not present) - HaveBndU - array[NMain], if HaveBndU[i] is False, - then i-th bound is not present - NMain - number of main variables - NSlack - number of slack variables - CE - array[K,NMain+NSlack+1], equality constraints CE*x=b. - Rows contain constraints, first NMain+NSlack columns - contain coefficients before X[], last column contain - right part. - K - number of linear constraints - EpsI - infeasibility (error in the right part) allowed in the - solution - -OUTPUT PARAMETERS: - X - feasible point or best infeasible point found before - algorithm termination - QPIts - number of QP iterations (for debug purposes) - GPAIts - number of GPA iterations (for debug purposes) - -RESULT: - True in case X is feasible, False - if it is infeasible. - - -- ALGLIB -- - Copyright 20.01.2012 by Bochkanov Sergey -*************************************************************************/ -ae_bool findfeasiblepoint(/* Real */ ae_vector* x, - /* Real */ ae_vector* bndl, - /* Boolean */ ae_vector* havebndl, - /* Real */ ae_vector* bndu, - /* Boolean */ ae_vector* havebndu, - ae_int_t nmain, - ae_int_t nslack, - /* Real */ ae_matrix* ce, - ae_int_t k, - double epsi, - ae_int_t* qpits, - ae_int_t* gpaits, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _ce; - ae_int_t i; - ae_int_t j; - ae_int_t idx0; - ae_int_t idx1; - ae_vector permx; - ae_vector xn; - ae_vector xa; - ae_vector newtonstep; - ae_vector g; - ae_vector pg; - ae_vector tau; - ae_vector s; - double armijostep; - double armijobeststep; - double armijobestfeas; - double v; - double vv; - double mx; - double feaserr; - double feaserr0; - double feaserr1; - double feasold; - double feasnew; - double pgnorm; - double vn; - double vd; - double stp; - ae_int_t vartofreeze; - double valtofreeze; - double maxsteplen; - ae_bool werechangesinconstraints; - ae_bool stage1isover; - ae_bool converged; - ae_vector activeconstraints; - ae_vector tmpk; - ae_vector colnorms; - ae_int_t nactive; - ae_int_t nfree; - ae_vector p1; - ae_vector p2; - apbuffers buf; - ae_int_t itscount; - ae_int_t itswithintolerance; - ae_int_t maxitswithintolerance; - ae_int_t badits; - ae_int_t maxbadits; - ae_int_t gparuns; - ae_int_t maxarmijoruns; - ae_matrix permce; - ae_matrix q; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_ce, 0, sizeof(_ce)); - memset(&permx, 0, sizeof(permx)); - memset(&xn, 0, sizeof(xn)); - memset(&xa, 0, sizeof(xa)); - memset(&newtonstep, 0, sizeof(newtonstep)); - memset(&g, 0, sizeof(g)); - memset(&pg, 0, sizeof(pg)); - memset(&tau, 0, sizeof(tau)); - memset(&s, 0, sizeof(s)); - memset(&activeconstraints, 0, sizeof(activeconstraints)); - memset(&tmpk, 0, sizeof(tmpk)); - memset(&colnorms, 0, sizeof(colnorms)); - memset(&p1, 0, sizeof(p1)); - memset(&p2, 0, sizeof(p2)); - memset(&buf, 0, sizeof(buf)); - memset(&permce, 0, sizeof(permce)); - memset(&q, 0, sizeof(q)); - ae_matrix_init_copy(&_ce, ce, _state, ae_true); - ce = &_ce; - *qpits = 0; - *gpaits = 0; - ae_vector_init(&permx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xn, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xa, 0, DT_REAL, _state, ae_true); - ae_vector_init(&newtonstep, 0, DT_REAL, _state, ae_true); - ae_vector_init(&g, 0, DT_REAL, _state, ae_true); - ae_vector_init(&pg, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tau, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&activeconstraints, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpk, 0, DT_REAL, _state, ae_true); - ae_vector_init(&colnorms, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p1, 0, DT_INT, _state, ae_true); - ae_vector_init(&p2, 0, DT_INT, _state, ae_true); - _apbuffers_init(&buf, _state, ae_true); - ae_matrix_init(&permce, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true); - - maxitswithintolerance = 3; - maxbadits = 3; - maxarmijoruns = 5; - *qpits = 0; - *gpaits = 0; - - /* - * Initial enforcement of the feasibility with respect to boundary constraints - * NOTE: after this block we assume that boundary constraints are consistent. - */ - if( !enforceboundaryconstraints(x, bndl, havebndl, bndu, havebndu, nmain, nslack, _state) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - if( k==0 ) - { - - /* - * No linear constraints, we can exit right now - */ - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Scale rows of CE in such way that max(CE[i,0..nmain+nslack-1])=1 for any i=0..k-1 - */ - for(i=0; i<=k-1; i++) - { - v = 0.0; - for(j=0; j<=nmain+nslack-1; j++) - { - v = ae_maxreal(v, ae_fabs(ce->ptr.pp_double[i][j], _state), _state); - } - if( ae_fp_neq(v,(double)(0)) ) - { - v = 1/v; - ae_v_muld(&ce->ptr.pp_double[i][0], 1, ae_v_len(0,nmain+nslack), v); - } - } - - /* - * Allocate temporaries - */ - ae_vector_set_length(&xn, nmain+nslack, _state); - ae_vector_set_length(&xa, nmain+nslack, _state); - ae_vector_set_length(&permx, nmain+nslack, _state); - ae_vector_set_length(&g, nmain+nslack, _state); - ae_vector_set_length(&pg, nmain+nslack, _state); - ae_vector_set_length(&tmpk, k, _state); - ae_matrix_set_length(&permce, k, nmain+nslack, _state); - ae_vector_set_length(&activeconstraints, nmain+nslack, _state); - ae_vector_set_length(&newtonstep, nmain+nslack, _state); - ae_vector_set_length(&s, nmain+nslack, _state); - ae_vector_set_length(&colnorms, nmain+nslack, _state); - for(i=0; i<=nmain+nslack-1; i++) - { - s.ptr.p_double[i] = 1.0; - colnorms.ptr.p_double[i] = 0.0; - for(j=0; j<=k-1; j++) - { - colnorms.ptr.p_double[i] = colnorms.ptr.p_double[i]+ae_sqr(ce->ptr.pp_double[j][i], _state); - } - } - - /* - * K>0, we have linear equality constraints combined with bound constraints. - * - * Try to find feasible point as minimizer of the quadratic function - * F(x) = 0.5*||CE*x-b||^2 = 0.5*x'*(CE'*CE)*x - (b'*CE)*x + 0.5*b'*b - * subject to boundary constraints given by BL, BU and non-negativity of - * the slack variables. BTW, we drop constant term because it does not - * actually influences on the solution. - * - * Below we will assume that K>0. - */ - itswithintolerance = 0; - badits = 0; - itscount = 0; - for(;;) - { - - /* - * Stage 0: check for exact convergence - */ - converged = ae_true; - feaserr = optserv_feasibilityerror(ce, x, nmain, nslack, k, &tmpk, _state); - for(i=0; i<=k-1; i++) - { - - /* - * Calculate MX - maximum term in the left part - * - * Terminate if error in the right part is not greater than 100*Eps*MX. - * - * IMPORTANT: we must perform check for non-strict inequality, i.e. to use <= instead of <. - * it will allow us to easily handle situations with zero rows of CE. - * - * NOTE: it is important to calculate feasibility error with dedicated - * function. Once we had a situation when usage of "inline" code - * resulted in different numerical values calculated at different - * parts of program for exactly same X. However, this value is - * essential for algorithm's ability to terminate before entering - * infinite loop, so reproducibility of numerical results is very - * important. - */ - mx = (double)(0); - v = -ce->ptr.pp_double[i][nmain+nslack]; - for(j=0; j<=nmain+nslack-1; j++) - { - mx = ae_maxreal(mx, ae_fabs(ce->ptr.pp_double[i][j]*x->ptr.p_double[j], _state), _state); - v = v+ce->ptr.pp_double[i][j]*x->ptr.p_double[j]; - } - converged = converged&&ae_fp_less_eq(ae_fabs(v, _state),100*ae_machineepsilon*mx); - } - feaserr0 = feaserr; - if( converged ) - { - result = ae_fp_less_eq(feaserr,epsi); - ae_frame_leave(_state); - return result; - } - - /* - * Stage 1: equality constrained quadratic programming - * - * * treat active bound constraints as equality ones (constraint is considered - * active when we are at the boundary, independently of the antigradient direction) - * * calculate unrestricted Newton step to point XM (which may be infeasible) - * calculate MaxStepLen = largest step in direction of XM which retains feasibility. - * * perform bounded step from X to XN: - * a) XN=XM (if XM is feasible) - * b) XN=X-MaxStepLen*(XM-X) (otherwise) - * * X := XN - * * if XM (Newton step subject to currently active constraints) was feasible, goto Stage 2 - * * repeat Stage 1 - * - * NOTE 1: in order to solve constrained qudratic subproblem we will have to reorder - * variables in such way that ones corresponding to inactive constraints will - * be first, and active ones will be last in the list. CE and X are now - * [ xi ] - * separated into two parts: CE = [CEi CEa], x = [ ], where CEi/Xi correspond - * [ xa ] - * to INACTIVE constraints, and CEa/Xa correspond to the ACTIVE ones. - * - * Now, instead of F=0.5*x'*(CE'*CE)*x - (b'*CE)*x + 0.5*b'*b, we have - * F(xi) = 0.5*(CEi*xi,CEi*xi) + (CEa*xa-b,CEi*xi) + (0.5*CEa*xa-b,CEa*xa). - * Here xa is considered constant, i.e. we optimize with respect to xi, leaving xa fixed. - * - * We can solve it by performing SVD of CEi and calculating pseudoinverse of the - * Hessian matrix. Of course, we do NOT calculate pseudoinverse explicitly - we - * just use singular vectors to perform implicit multiplication by it. - * - */ - for(;;) - { - - /* - * Calculate G - gradient subject to equality constraints, - * multiply it by inverse of the Hessian diagonal to obtain initial - * step vector. - * - * Bound step subject to constraints which can be activated, - * run Armijo search with increasing step size. - * Search is terminated when feasibility error stops to decrease. - * - * NOTE: it is important to test for "stops to decrease" instead - * of "starts to increase" in order to correctly handle cases with - * zero CE. - */ - armijobeststep = 0.0; - optserv_feasibilityerrorgrad(ce, x, nmain, nslack, k, &armijobestfeas, &g, &tmpk, _state); - for(i=0; i<=nmain-1; i++) - { - if( havebndl->ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],bndl->ptr.p_double[i]) ) - { - g.ptr.p_double[i] = 0.0; - } - if( havebndu->ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],bndu->ptr.p_double[i]) ) - { - g.ptr.p_double[i] = 0.0; - } - } - for(i=0; i<=nslack-1; i++) - { - if( ae_fp_eq(x->ptr.p_double[nmain+i],0.0) ) - { - g.ptr.p_double[nmain+i] = 0.0; - } - } - v = 0.0; - for(i=0; i<=nmain+nslack-1; i++) - { - if( ae_fp_neq(ae_sqr(colnorms.ptr.p_double[i], _state),(double)(0)) ) - { - newtonstep.ptr.p_double[i] = -g.ptr.p_double[i]/ae_sqr(colnorms.ptr.p_double[i], _state); - } - else - { - newtonstep.ptr.p_double[i] = 0.0; - } - v = v+ae_sqr(newtonstep.ptr.p_double[i], _state); - } - if( ae_fp_eq(v,(double)(0)) ) - { - - /* - * Constrained gradient is zero, QP iterations are over - */ - break; - } - calculatestepbound(x, &newtonstep, 1.0, bndl, havebndl, bndu, havebndu, nmain, nslack, &vartofreeze, &valtofreeze, &maxsteplen, _state); - if( vartofreeze>=0&&ae_fp_eq(maxsteplen,(double)(0)) ) - { - - /* - * Can not perform step, QP iterations are over - */ - break; - } - if( vartofreeze>=0 ) - { - armijostep = ae_minreal(1.0, maxsteplen, _state); - } - else - { - armijostep = (double)(1); - } - for(;;) - { - ae_v_move(&xa.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1)); - ae_v_addd(&xa.ptr.p_double[0], 1, &newtonstep.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1), armijostep); - enforceboundaryconstraints(&xa, bndl, havebndl, bndu, havebndu, nmain, nslack, _state); - feaserr = optserv_feasibilityerror(ce, &xa, nmain, nslack, k, &tmpk, _state); - if( ae_fp_greater_eq(feaserr,armijobestfeas) ) - { - break; - } - armijobestfeas = feaserr; - armijobeststep = armijostep; - armijostep = 2.0*armijostep; - } - ae_v_addd(&x->ptr.p_double[0], 1, &newtonstep.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1), armijobeststep); - enforceboundaryconstraints(x, bndl, havebndl, bndu, havebndu, nmain, nslack, _state); - - /* - * Determine number of active and free constraints - */ - nactive = 0; - for(i=0; i<=nmain-1; i++) - { - activeconstraints.ptr.p_double[i] = (double)(0); - if( havebndl->ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],bndl->ptr.p_double[i]) ) - { - activeconstraints.ptr.p_double[i] = (double)(1); - } - if( havebndu->ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],bndu->ptr.p_double[i]) ) - { - activeconstraints.ptr.p_double[i] = (double)(1); - } - if( ae_fp_greater(activeconstraints.ptr.p_double[i],(double)(0)) ) - { - nactive = nactive+1; - } - } - for(i=0; i<=nslack-1; i++) - { - activeconstraints.ptr.p_double[nmain+i] = (double)(0); - if( ae_fp_eq(x->ptr.p_double[nmain+i],0.0) ) - { - activeconstraints.ptr.p_double[nmain+i] = (double)(1); - } - if( ae_fp_greater(activeconstraints.ptr.p_double[nmain+i],(double)(0)) ) - { - nactive = nactive+1; - } - } - nfree = nmain+nslack-nactive; - if( nfree==0 ) - { - break; - } - *qpits = *qpits+1; - - /* - * Reorder variables: CE is reordered to PermCE, X is reordered to PermX - */ - tagsortbuf(&activeconstraints, nmain+nslack, &p1, &p2, &buf, _state); - for(i=0; i<=k-1; i++) - { - for(j=0; j<=nmain+nslack-1; j++) - { - permce.ptr.pp_double[i][j] = ce->ptr.pp_double[i][j]; - } - } - for(j=0; j<=nmain+nslack-1; j++) - { - permx.ptr.p_double[j] = x->ptr.p_double[j]; - } - for(j=0; j<=nmain+nslack-1; j++) - { - if( p2.ptr.p_int[j]!=j ) - { - idx0 = p2.ptr.p_int[j]; - idx1 = j; - for(i=0; i<=k-1; i++) - { - v = permce.ptr.pp_double[i][idx0]; - permce.ptr.pp_double[i][idx0] = permce.ptr.pp_double[i][idx1]; - permce.ptr.pp_double[i][idx1] = v; - } - v = permx.ptr.p_double[idx0]; - permx.ptr.p_double[idx0] = permx.ptr.p_double[idx1]; - permx.ptr.p_double[idx1] = v; - } - } - - /* - * Calculate (unprojected) gradient: - * G(xi) = CEi'*(CEi*xi + CEa*xa - b) - */ - for(i=0; i<=nfree-1; i++) - { - g.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=k-1; i++) - { - v = ae_v_dotproduct(&permce.ptr.pp_double[i][0], 1, &permx.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1)); - tmpk.ptr.p_double[i] = v-ce->ptr.pp_double[i][nmain+nslack]; - } - for(i=0; i<=k-1; i++) - { - v = tmpk.ptr.p_double[i]; - ae_v_addd(&g.ptr.p_double[0], 1, &permce.ptr.pp_double[i][0], 1, ae_v_len(0,nfree-1), v); - } - - /* - * Calculate Newton step using pseudoinverse PermCE: - * F(xi) = 0.5*xi'*H*xi + g'*xi (Taylor decomposition) - * XN = -H^(-1)*g (new point, solution of the QP subproblem) - * H = CEi'*CEi - * H^(-1) can be calculated via QR or LQ decomposition (see below) - * step = -H^(-1)*g - * - * NOTE: PermCE is destroyed after this block - */ - for(i=0; i<=nmain+nslack-1; i++) - { - newtonstep.ptr.p_double[i] = (double)(0); - } - if( k<=nfree ) - { - - /* - * CEi = L*Q - * H = Q'*L'*L*Q - * inv(H) = Q'*inv(L)*inv(L')*Q - * - * NOTE: we apply minor regularizing perturbation to diagonal of L, - * which is equal to 10*K*Eps - */ - rmatrixlq(&permce, k, nfree, &tau, _state); - rmatrixlqunpackq(&permce, k, nfree, &tau, k, &q, _state); - v = (double)(0); - for(i=0; i<=k-1; i++) - { - v = ae_maxreal(v, ae_fabs(permce.ptr.pp_double[i][i], _state), _state); - } - v = coalesce(v, (double)(1), _state); - for(i=0; i<=k-1; i++) - { - permce.ptr.pp_double[i][i] = permce.ptr.pp_double[i][i]+10*k*ae_machineepsilon*v; - } - rmatrixgemv(k, nfree, 1.0, &q, 0, 0, 0, &g, 0, 0.0, &tmpk, 0, _state); - rmatrixtrsv(k, &permce, 0, 0, ae_false, ae_false, 1, &tmpk, 0, _state); - rmatrixtrsv(k, &permce, 0, 0, ae_false, ae_false, 0, &tmpk, 0, _state); - rmatrixgemv(nfree, k, -1.0, &q, 0, 0, 1, &tmpk, 0, 0.0, &newtonstep, 0, _state); - } - else - { - - /* - * CEi = Q*R - * H = R'*R - * inv(H) = inv(R)*inv(R') - * - * NOTE: we apply minor regularizing perturbation to diagonal of R, - * which is equal to 10*K*Eps - */ - rmatrixqr(&permce, k, nfree, &tau, _state); - v = (double)(0); - for(i=0; i<=nfree-1; i++) - { - v = ae_maxreal(v, ae_fabs(permce.ptr.pp_double[i][i], _state), _state); - } - v = coalesce(v, (double)(1), _state); - for(i=0; i<=nfree-1; i++) - { - vv = 10*nfree*ae_machineepsilon*v; - if( ae_fp_less(permce.ptr.pp_double[i][i],(double)(0)) ) - { - vv = -vv; - } - permce.ptr.pp_double[i][i] = permce.ptr.pp_double[i][i]+vv; - } - ae_v_moveneg(&newtonstep.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,nfree-1)); - rmatrixtrsv(nfree, &permce, 0, 0, ae_true, ae_false, 1, &newtonstep, 0, _state); - rmatrixtrsv(nfree, &permce, 0, 0, ae_true, ae_false, 0, &newtonstep, 0, _state); - } - - /* - * Post-reordering of Newton step - */ - for(j=nmain+nslack-1; j>=0; j--) - { - if( p2.ptr.p_int[j]!=j ) - { - idx0 = p2.ptr.p_int[j]; - idx1 = j; - v = newtonstep.ptr.p_double[idx0]; - newtonstep.ptr.p_double[idx0] = newtonstep.ptr.p_double[idx1]; - newtonstep.ptr.p_double[idx1] = v; - } - } - - /* - * NewtonStep contains Newton step subject to active bound constraints. - * - * Such step leads us to the minimizer of the equality constrained F, - * but such minimizer may be infeasible because some constraints which - * are inactive at the initial point can be violated at the solution. - * - * Thus, we perform optimization in two stages: - * a) perform bounded Newton step, i.e. step in the Newton direction - * until activation of the first constraint - * b) in case (MaxStepLen>0)and(MaxStepLen<1), perform additional iteration - * of the Armijo line search in the rest of the Newton direction. - */ - calculatestepbound(x, &newtonstep, 1.0, bndl, havebndl, bndu, havebndu, nmain, nslack, &vartofreeze, &valtofreeze, &maxsteplen, _state); - if( vartofreeze>=0&&ae_fp_eq(maxsteplen,(double)(0)) ) - { - - /* - * Activation of the constraints prevent us from performing step, - * QP iterations are over - */ - break; - } - if( vartofreeze>=0 ) - { - v = ae_minreal(1.0, maxsteplen, _state); - } - else - { - v = 1.0; - } - ae_v_moved(&xn.ptr.p_double[0], 1, &newtonstep.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1), v); - ae_v_add(&xn.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1)); - postprocessboundedstep(&xn, x, bndl, havebndl, bndu, havebndu, nmain, nslack, vartofreeze, valtofreeze, v, maxsteplen, _state); - if( ae_fp_greater(maxsteplen,(double)(0))&&ae_fp_less(maxsteplen,(double)(1)) ) - { - - /* - * Newton step was restricted by activation of the constraints, - * perform Armijo iteration. - * - * Initial estimate for best step is zero step. We try different - * step sizes, from the 1-MaxStepLen (residual of the full Newton - * step) to progressively smaller and smaller steps. - */ - armijobeststep = 0.0; - armijobestfeas = optserv_feasibilityerror(ce, &xn, nmain, nslack, k, &tmpk, _state); - armijostep = 1-maxsteplen; - for(j=0; j<=maxarmijoruns-1; j++) - { - ae_v_move(&xa.ptr.p_double[0], 1, &xn.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1)); - ae_v_addd(&xa.ptr.p_double[0], 1, &newtonstep.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1), armijostep); - enforceboundaryconstraints(&xa, bndl, havebndl, bndu, havebndu, nmain, nslack, _state); - feaserr = optserv_feasibilityerror(ce, &xa, nmain, nslack, k, &tmpk, _state); - if( ae_fp_less(feaserr,armijobestfeas) ) - { - armijobestfeas = feaserr; - armijobeststep = armijostep; - } - armijostep = 0.5*armijostep; - } - ae_v_move(&xa.ptr.p_double[0], 1, &xn.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1)); - ae_v_addd(&xa.ptr.p_double[0], 1, &newtonstep.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1), armijobeststep); - enforceboundaryconstraints(&xa, bndl, havebndl, bndu, havebndu, nmain, nslack, _state); - } - else - { - - /* - * Armijo iteration is not performed - */ - ae_v_move(&xa.ptr.p_double[0], 1, &xn.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1)); - } - stage1isover = ae_fp_greater_eq(maxsteplen,(double)(1))||ae_fp_eq(maxsteplen,(double)(0)); - - /* - * Calculate feasibility errors for old and new X. - * These quantinies are used for debugging purposes only. - * However, we can leave them in release code because performance impact is insignificant. - * - * Update X. Exit if needed. - */ - feasold = optserv_feasibilityerror(ce, x, nmain, nslack, k, &tmpk, _state); - feasnew = optserv_feasibilityerror(ce, &xa, nmain, nslack, k, &tmpk, _state); - if( ae_fp_greater_eq(feasnew,feasold) ) - { - break; - } - ae_v_move(&x->ptr.p_double[0], 1, &xa.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1)); - if( stage1isover ) - { - break; - } - } - - /* - * Stage 2: gradient projection algorithm (GPA) - * - * * calculate feasibility error (with respect to linear equality constraints) - * * calculate gradient G of F, project it into feasible area (G => PG) - * * exit if norm(PG) is exactly zero or feasibility error is smaller than EpsC - * * let XM be exact minimum of F along -PG (XM may be infeasible). - * calculate MaxStepLen = largest step in direction of -PG which retains feasibility. - * * perform bounded step from X to XN: - * a) XN=XM (if XM is feasible) - * b) XN=X-MaxStepLen*PG (otherwise) - * * X := XN - * * stop after specified number of iterations or when no new constraints was activated - * - * NOTES: - * * grad(F) = (CE'*CE)*x - (b'*CE)^T - * * CE[i] denotes I-th row of CE - * * XM = X+stp*(-PG) where stp=(grad(F(X)),PG)/(CE*PG,CE*PG). - * Here PG is a projected gradient, but in fact it can be arbitrary non-zero - * direction vector - formula for minimum of F along PG still will be correct. - */ - werechangesinconstraints = ae_false; - for(gparuns=1; gparuns<=k; gparuns++) - { - - /* - * calculate feasibility error and G - */ - optserv_feasibilityerrorgrad(ce, x, nmain, nslack, k, &feaserr, &g, &tmpk, _state); - - /* - * project G, filter it (strip numerical noise) - */ - ae_v_move(&pg.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1)); - projectgradientintobc(x, &pg, bndl, havebndl, bndu, havebndu, nmain, nslack, _state); - filterdirection(&pg, x, bndl, havebndl, bndu, havebndu, &s, nmain, nslack, 1.0E-9, _state); - for(i=0; i<=nmain+nslack-1; i++) - { - if( ae_fp_neq(ae_sqr(colnorms.ptr.p_double[i], _state),(double)(0)) ) - { - pg.ptr.p_double[i] = pg.ptr.p_double[i]/ae_sqr(colnorms.ptr.p_double[i], _state); - } - else - { - pg.ptr.p_double[i] = 0.0; - } - } - - /* - * Check GNorm and feasibility. - * Exit when GNorm is exactly zero. - */ - pgnorm = ae_v_dotproduct(&pg.ptr.p_double[0], 1, &pg.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1)); - pgnorm = ae_sqrt(pgnorm, _state); - if( ae_fp_eq(pgnorm,(double)(0)) ) - { - result = ae_fp_less_eq(feaserr,epsi); - ae_frame_leave(_state); - return result; - } - - /* - * calculate planned step length - */ - vn = ae_v_dotproduct(&g.ptr.p_double[0], 1, &pg.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1)); - vd = (double)(0); - rmatrixgemv(k, nmain+nslack, 1.0, ce, 0, 0, 0, &pg, 0, 0.0, &tmpk, 0, _state); - for(i=0; i<=k-1; i++) - { - vd = vd+ae_sqr(tmpk.ptr.p_double[i], _state); - } - stp = vn/vd; - - /* - * Calculate step bound. - * Perform bounded step and post-process it - */ - calculatestepbound(x, &pg, -1.0, bndl, havebndl, bndu, havebndu, nmain, nslack, &vartofreeze, &valtofreeze, &maxsteplen, _state); - if( vartofreeze>=0&&ae_fp_eq(maxsteplen,(double)(0)) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - if( vartofreeze>=0 ) - { - v = ae_minreal(stp, maxsteplen, _state); - } - else - { - v = stp; - } - ae_v_move(&xn.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1)); - ae_v_subd(&xn.ptr.p_double[0], 1, &pg.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1), v); - postprocessboundedstep(&xn, x, bndl, havebndl, bndu, havebndu, nmain, nslack, vartofreeze, valtofreeze, v, maxsteplen, _state); - - /* - * update X - * check stopping criteria - */ - werechangesinconstraints = werechangesinconstraints||numberofchangedconstraints(&xn, x, bndl, havebndl, bndu, havebndu, nmain, nslack, _state)>0; - ae_v_move(&x->ptr.p_double[0], 1, &xn.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1)); - *gpaits = *gpaits+1; - if( !werechangesinconstraints ) - { - break; - } - } - - /* - * Stage 3: decide to stop algorithm or not to stop - * - * 1. we can stop when last GPA run did NOT changed constraints status. - * It means that we've found final set of the active constraints even - * before GPA made its run. And it means that Newton step moved us to - * the minimum subject to the present constraints. - * Depending on feasibility error, True or False is returned. - */ - feaserr = optserv_feasibilityerror(ce, x, nmain, nslack, k, &tmpk, _state); - feaserr1 = feaserr; - if( ae_fp_greater_eq(feaserr1,feaserr0*(1-1000*ae_machineepsilon)) ) - { - inc(&badits, _state); - } - else - { - badits = 0; - } - if( ae_fp_less_eq(feaserr,epsi) ) - { - inc(&itswithintolerance, _state); - } - else - { - itswithintolerance = 0; - } - if( (!werechangesinconstraints||itswithintolerance>=maxitswithintolerance)||badits>=maxbadits ) - { - result = ae_fp_less_eq(feaserr,epsi); - ae_frame_leave(_state); - return result; - } - itscount = itscount+1; - - /* - * Block below is never executed; it is necessary just to avoid - * "unreachable code" warning about automatically generated code. - * - * We just need a way to transfer control to the end of the function, - * even a fake way which is never actually traversed. - */ - if( alwaysfalse(_state) ) - { - result = ae_false; - ae_assert(ae_false, "Assertion failed", _state); - break; - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* - This function checks that input derivatives are right. First it scales -parameters DF0 and DF1 from segment [A;B] to [0;1]. Then it builds Hermite -spline and derivative of it in 0.5. Search scale as Max(DF0,DF1, |F0-F1|). -Right derivative has to satisfy condition: - |H-F|/S<=0,001, |H'-F'|/S<=0,001. - -INPUT PARAMETERS: - F0 - function's value in X-TestStep point; - DF0 - derivative's value in X-TestStep point; - F1 - function's value in X+TestStep point; - DF1 - derivative's value in X+TestStep point; - F - testing function's value; - DF - testing derivative's value; - Width- width of verification segment. - -RESULT: - If input derivatives is right then function returns true, else - function returns false. - - -- ALGLIB -- - Copyright 29.05.2012 by Bochkanov Sergey -*************************************************************************/ -ae_bool derivativecheck(double f0, - double df0, - double f1, - double df1, - double f, - double df, - double width, - ae_state *_state) -{ - double s; - double h; - double dh; - ae_bool result; - - - - /* - * Rescale input data to [0,1] - */ - df = width*df; - df0 = width*df0; - df1 = width*df1; - - /* - * Compute error scale, two sources are used: - * * magnitudes of derivatives and secants - * * magnitudes of input data times sqrt(machine_epsilon) - */ - s = 0.0; - s = ae_maxreal(s, ae_fabs(df0, _state), _state); - s = ae_maxreal(s, ae_fabs(df1, _state), _state); - s = ae_maxreal(s, ae_fabs(f1-f0, _state), _state); - s = ae_maxreal(s, ae_sqrt(ae_machineepsilon, _state)*ae_fabs(f0, _state), _state); - s = ae_maxreal(s, ae_sqrt(ae_machineepsilon, _state)*ae_fabs(f1, _state), _state); - - /* - * Compute H and dH/dX at the middle of interval - */ - h = 0.5*(f0+f1)+0.125*(df0-df1); - dh = 1.5*(f1-f0)-0.250*(df0+df1); - - /* - * Check - */ - if( ae_fp_neq(s,(double)(0)) ) - { - if( ae_fp_greater(ae_fabs(h-f, _state)/s,0.001)||ae_fp_greater(ae_fabs(dh-df, _state)/s,0.001) ) - { - result = ae_false; - return result; - } - } - else - { - if( ae_fp_neq(h-f,0.0)||ae_fp_neq(dh-df,0.0) ) - { - result = ae_false; - return result; - } - } - result = ae_true; - return result; -} - - -/************************************************************************* -Having quadratic target function - - f(x) = 0.5*x'*A*x + b'*x + penaltyfactor*0.5*(C*x-b)'*(C*x-b) - -and its parabolic model along direction D - - F(x0+alpha*D) = D2*alpha^2 + D1*alpha - -this function estimates numerical errors in the coefficients of the model. - -It is important that this function does NOT calculate D1/D2 - it only -estimates numerical errors introduced during evaluation and compares their -magnitudes against magnitudes of numerical errors. As result, one of three -outcomes is returned for each coefficient: - * "true" coefficient is almost surely positive - * "true" coefficient is almost surely negative - * numerical errors in coefficient are so large that it can not be - reliably distinguished from zero - -INPUT PARAMETERS: - AbsASum - SUM(|A[i,j]|) - AbsASum2- SUM(A[i,j]^2) - MB - max(|B|) - MX - max(|X|) - MD - max(|D|) - D1 - linear coefficient - D2 - quadratic coefficient - -OUTPUT PARAMETERS: - D1Est - estimate of D1 sign, accounting for possible numerical - errors: - * >0 means "almost surely positive" (D1>0 and large) - * <0 means "almost surely negative" (D1<0 and large) - * =0 means "pessimistic estimate of numerical errors - in D1 is larger than magnitude of D1 itself; it is - impossible to reliably distinguish D1 from zero". - D2Est - estimate of D2 sign, accounting for possible numerical - errors: - * >0 means "almost surely positive" (D2>0 and large) - * <0 means "almost surely negative" (D2<0 and large) - * =0 means "pessimistic estimate of numerical errors - in D2 is larger than magnitude of D2 itself; it is - impossible to reliably distinguish D2 from zero". - - -- ALGLIB -- - Copyright 14.05.2014 by Bochkanov Sergey -*************************************************************************/ -void estimateparabolicmodel(double absasum, - double absasum2, - double mx, - double mb, - double md, - double d1, - double d2, - ae_int_t* d1est, - ae_int_t* d2est, - ae_state *_state) -{ - double d1esterror; - double d2esterror; - double eps; - double e1; - double e2; - - *d1est = 0; - *d2est = 0; - - - /* - * Error estimates: - * - * * error in D1=d'*(A*x+b) is estimated as - * ED1 = eps*MAX_ABS(D)*(MAX_ABS(X)*ENORM(A)+MAX_ABS(B)) - * * error in D2=0.5*d'*A*d is estimated as - * ED2 = eps*MAX_ABS(D)^2*ENORM(A) - * - * Here ENORM(A) is some pseudo-norm which reflects the way numerical - * error accumulates during addition. Two ways of accumulation are - * possible - worst case (errors always increase) and mean-case (errors - * may cancel each other). We calculate geometrical average of both: - * * ENORM_WORST(A) = SUM(|A[i,j]|) error in N-term sum grows as O(N) - * * ENORM_MEAN(A) = SQRT(SUM(A[i,j]^2)) error in N-term sum grows as O(sqrt(N)) - * * ENORM(A) = SQRT(ENORM_WORST(A),ENORM_MEAN(A)) - */ - eps = 4*ae_machineepsilon; - e1 = eps*md*(mx*absasum+mb); - e2 = eps*md*(mx*ae_sqrt(absasum2, _state)+mb); - d1esterror = ae_sqrt(e1*e2, _state); - if( ae_fp_less_eq(ae_fabs(d1, _state),d1esterror) ) - { - *d1est = 0; - } - else - { - *d1est = ae_sign(d1, _state); - } - e1 = eps*md*md*absasum; - e2 = eps*md*md*ae_sqrt(absasum2, _state); - d2esterror = ae_sqrt(e1*e2, _state); - if( ae_fp_less_eq(ae_fabs(d2, _state),d2esterror) ) - { - *d2est = 0; - } - else - { - *d2est = ae_sign(d2, _state); - } -} - - -/************************************************************************* -This function calculates inexact rank-K preconditioner for Hessian matrix -H=D+W'*C*W, where: -* H is a Hessian matrix, which is approximated by D/W/C -* D is a diagonal matrix with positive entries -* W is a rank-K correction -* C is a diagonal factor of rank-K correction - -This preconditioner is inexact but fast - it requires O(N*K) time to be -applied. Its main purpose - to be used in barrier/penalty/AUL methods, -where ill-conditioning is created by combination of two factors: -* simple bounds on variables => ill-conditioned D -* general barrier/penalty => correction W with large coefficient C (makes - problem ill-conditioned) but W itself is well conditioned. - -Preconditioner P is calculated by artificially constructing a set of BFGS -updates which tries to reproduce behavior of H: -* Sk = Wk (k-th row of W) -* Yk = (D+Wk'*Ck*Wk)*Sk -* Yk/Sk are reordered by ascending of C[k]*norm(Wk)^2 - -Here we assume that rows of Wk are orthogonal or nearly orthogonal, which -allows us to have O(N*K+K^2) update instead of O(N*K^2) one. Reordering of -updates is essential for having good performance on non-orthogonal problems -(updates which do not add much of curvature are added first, and updates -which add very large eigenvalues are added last and override effect of the -first updates). - -On input this function takes direction S and components of H. -On output it returns inv(H)*S - - -- ALGLIB -- - Copyright 30.06.2014 by Bochkanov Sergey -*************************************************************************/ -void inexactlbfgspreconditioner(/* Real */ ae_vector* s, - ae_int_t n, - /* Real */ ae_vector* d, - /* Real */ ae_vector* c, - /* Real */ ae_matrix* w, - ae_int_t k, - precbuflbfgs* buf, - ae_state *_state) -{ - ae_int_t idx; - ae_int_t i; - ae_int_t j; - double v; - double v0; - double v1; - double vx; - double vy; - - - rvectorsetlengthatleast(&buf->norms, k, _state); - rvectorsetlengthatleast(&buf->alpha, k, _state); - rvectorsetlengthatleast(&buf->rho, k, _state); - rmatrixsetlengthatleast(&buf->yk, k, n, _state); - ivectorsetlengthatleast(&buf->idx, k, _state); - - /* - * Check inputs - */ - for(i=0; i<=n-1; i++) - { - ae_assert(ae_fp_greater(d->ptr.p_double[i],(double)(0)), "InexactLBFGSPreconditioner: D[]<=0", _state); - } - for(i=0; i<=k-1; i++) - { - ae_assert(ae_fp_greater_eq(c->ptr.p_double[i],(double)(0)), "InexactLBFGSPreconditioner: C[]<0", _state); - } - - /* - * Reorder linear terms according to increase of second derivative. - * Fill Norms[] array. - */ - for(idx=0; idx<=k-1; idx++) - { - v = ae_v_dotproduct(&w->ptr.pp_double[idx][0], 1, &w->ptr.pp_double[idx][0], 1, ae_v_len(0,n-1)); - buf->norms.ptr.p_double[idx] = v*c->ptr.p_double[idx]; - buf->idx.ptr.p_int[idx] = idx; - } - tagsortfasti(&buf->norms, &buf->idx, &buf->bufa, &buf->bufb, k, _state); - - /* - * Apply updates - */ - for(idx=0; idx<=k-1; idx++) - { - - /* - * Select update to perform (ordered by ascending of second derivative) - */ - i = buf->idx.ptr.p_int[idx]; - - /* - * Calculate YK and Rho - */ - v = ae_v_dotproduct(&w->ptr.pp_double[i][0], 1, &w->ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - v = v*c->ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - buf->yk.ptr.pp_double[i][j] = (d->ptr.p_double[j]+v)*w->ptr.pp_double[i][j]; - } - v = 0.0; - v0 = 0.0; - v1 = 0.0; - for(j=0; j<=n-1; j++) - { - vx = w->ptr.pp_double[i][j]; - vy = buf->yk.ptr.pp_double[i][j]; - v = v+vx*vy; - v0 = v0+vx*vx; - v1 = v1+vy*vy; - } - if( (ae_fp_greater(v,(double)(0))&&ae_fp_greater(v0*v1,(double)(0)))&&ae_fp_greater(v/ae_sqrt(v0*v1, _state),n*10*ae_machineepsilon) ) - { - buf->rho.ptr.p_double[i] = 1/v; - } - else - { - buf->rho.ptr.p_double[i] = 0.0; - } - } - for(idx=k-1; idx>=0; idx--) - { - - /* - * Select update to perform (ordered by ascending of second derivative) - */ - i = buf->idx.ptr.p_int[idx]; - - /* - * Calculate Alpha[] according to L-BFGS algorithm - * and update S[] - */ - v = ae_v_dotproduct(&w->ptr.pp_double[i][0], 1, &s->ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = buf->rho.ptr.p_double[i]*v; - buf->alpha.ptr.p_double[i] = v; - ae_v_subd(&s->ptr.p_double[0], 1, &buf->yk.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v); - } - for(j=0; j<=n-1; j++) - { - s->ptr.p_double[j] = s->ptr.p_double[j]/d->ptr.p_double[j]; - } - for(idx=0; idx<=k-1; idx++) - { - - /* - * Select update to perform (ordered by ascending of second derivative) - */ - i = buf->idx.ptr.p_int[idx]; - - /* - * Calculate Beta according to L-BFGS algorithm - * and update S[] - */ - v = ae_v_dotproduct(&buf->yk.ptr.pp_double[i][0], 1, &s->ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = buf->alpha.ptr.p_double[i]-buf->rho.ptr.p_double[i]*v; - ae_v_addd(&s->ptr.p_double[0], 1, &w->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v); - } -} - - -/************************************************************************* -This function prepares exact low-rank preconditioner for Hessian matrix -H=D+W'*C*W, where: -* H is a Hessian matrix, which is approximated by D/W/C -* D is a diagonal matrix with positive entries -* W is a rank-K correction -* C is a diagonal factor of rank-K correction, positive semidefinite - -This preconditioner is exact but relatively slow - it requires O(N*K^2) -time to be prepared and O(N*K) time to be applied. It is calculated with -the help of Woodbury matrix identity. - -It should be used as follows: -* PrepareLowRankPreconditioner() call PREPARES data structure -* subsequent calls to ApplyLowRankPreconditioner() APPLY preconditioner to - user-specified search direction. - - -- ALGLIB -- - Copyright 30.06.2014 by Bochkanov Sergey -*************************************************************************/ -void preparelowrankpreconditioner(/* Real */ ae_vector* d, - /* Real */ ae_vector* c, - /* Real */ ae_matrix* w, - ae_int_t n, - ae_int_t k, - precbuflowrank* buf, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - ae_bool b; - - - - /* - * Check inputs - */ - ae_assert(n>0, "PrepareLowRankPreconditioner: N<=0", _state); - ae_assert(k>=0, "PrepareLowRankPreconditioner: N<=0", _state); - for(i=0; i<=n-1; i++) - { - ae_assert(ae_fp_greater(d->ptr.p_double[i],(double)(0)), "PrepareLowRankPreconditioner: D[]<=0", _state); - } - for(i=0; i<=k-1; i++) - { - ae_assert(ae_fp_greater_eq(c->ptr.p_double[i],(double)(0)), "PrepareLowRankPreconditioner: C[]<0", _state); - } - - /* - * Prepare buffer structure; skip zero entries of update. - */ - rvectorsetlengthatleast(&buf->d, n, _state); - rmatrixsetlengthatleast(&buf->v, k, n, _state); - rvectorsetlengthatleast(&buf->bufc, k, _state); - rmatrixsetlengthatleast(&buf->bufw, k+1, n, _state); - buf->n = n; - buf->k = 0; - for(i=0; i<=k-1; i++) - { - - /* - * Estimate magnitude of update row; skip zero rows (either W or C are zero) - */ - v = 0.0; - for(j=0; j<=n-1; j++) - { - v = v+w->ptr.pp_double[i][j]*w->ptr.pp_double[i][j]; - } - v = v*c->ptr.p_double[i]; - if( ae_fp_eq(v,(double)(0)) ) - { - continue; - } - ae_assert(ae_fp_greater(v,(double)(0)), "PrepareLowRankPreconditioner: internal error", _state); - - /* - * Copy non-zero update to buffer - */ - buf->bufc.ptr.p_double[buf->k] = c->ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - buf->v.ptr.pp_double[buf->k][j] = w->ptr.pp_double[i][j]; - buf->bufw.ptr.pp_double[buf->k][j] = w->ptr.pp_double[i][j]; - } - inc(&buf->k, _state); - } - - /* - * Reset K (for convenience) - */ - k = buf->k; - - /* - * Prepare diagonal factor; quick exit for K=0 - */ - for(i=0; i<=n-1; i++) - { - buf->d.ptr.p_double[i] = 1/d->ptr.p_double[i]; - } - if( k==0 ) - { - return; - } - - /* - * Use Woodbury matrix identity - */ - rmatrixsetlengthatleast(&buf->bufz, k, k, _state); - for(i=0; i<=k-1; i++) - { - for(j=0; j<=k-1; j++) - { - buf->bufz.ptr.pp_double[i][j] = 0.0; - } - } - for(i=0; i<=k-1; i++) - { - buf->bufz.ptr.pp_double[i][i] = 1/buf->bufc.ptr.p_double[i]; - } - for(j=0; j<=n-1; j++) - { - buf->bufw.ptr.pp_double[k][j] = 1/ae_sqrt(d->ptr.p_double[j], _state); - } - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - buf->bufw.ptr.pp_double[i][j] = buf->bufw.ptr.pp_double[i][j]*buf->bufw.ptr.pp_double[k][j]; - } - } - rmatrixgemm(k, k, n, 1.0, &buf->bufw, 0, 0, 0, &buf->bufw, 0, 0, 1, 1.0, &buf->bufz, 0, 0, _state); - b = spdmatrixcholeskyrec(&buf->bufz, 0, k, ae_true, &buf->tmp, _state); - ae_assert(b, "PrepareLowRankPreconditioner: internal error (Cholesky failure)", _state); - rmatrixlefttrsm(k, n, &buf->bufz, 0, 0, ae_true, ae_false, 1, &buf->v, 0, 0, _state); - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - buf->v.ptr.pp_double[i][j] = buf->v.ptr.pp_double[i][j]*buf->d.ptr.p_double[j]; - } - } -} - - -/************************************************************************* -This function apply exact low-rank preconditioner prepared by -PrepareLowRankPreconditioner function (see its comments for more information). - - -- ALGLIB -- - Copyright 30.06.2014 by Bochkanov Sergey -*************************************************************************/ -void applylowrankpreconditioner(/* Real */ ae_vector* s, - precbuflowrank* buf, - ae_state *_state) -{ - ae_int_t n; - ae_int_t k; - ae_int_t i; - ae_int_t j; - double v; - - - n = buf->n; - k = buf->k; - rvectorsetlengthatleast(&buf->tmp, n, _state); - for(j=0; j<=n-1; j++) - { - buf->tmp.ptr.p_double[j] = buf->d.ptr.p_double[j]*s->ptr.p_double[j]; - } - for(i=0; i<=k-1; i++) - { - v = 0.0; - for(j=0; j<=n-1; j++) - { - v = v+buf->v.ptr.pp_double[i][j]*s->ptr.p_double[j]; - } - for(j=0; j<=n-1; j++) - { - buf->tmp.ptr.p_double[j] = buf->tmp.ptr.p_double[j]-v*buf->v.ptr.pp_double[i][j]; - } - } - for(i=0; i<=n-1; i++) - { - s->ptr.p_double[i] = buf->tmp.ptr.p_double[i]; - } -} - - -/************************************************************************* -This subroutine initializes smoothness monitor at the beginning of the -optimization session. It requires variable scales to be passed. - -It is possible to perform "dummy" initialization with N=K=0. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -void smoothnessmonitorinit(smoothnessmonitor* monitor, - /* Real */ ae_vector* s, - ae_int_t n, - ae_int_t k, - ae_bool checksmoothness, - ae_state *_state) -{ - ae_int_t i; - - - monitor->n = n; - monitor->k = k; - monitor->checksmoothness = checksmoothness; - monitor->linesearchspoiled = ae_false; - monitor->linesearchstarted = ae_false; - monitor->enqueuedcnt = 0; - monitor->sortedcnt = 0; - rvectorsetlengthatleast(&monitor->s, n, _state); - for(i=0; i<=n-1; i++) - { - monitor->s.ptr.p_double[i] = s->ptr.p_double[i]; - } - monitor->nonc0currentrating = 0.0; - monitor->nonc1currentrating = 0.0; - optguardinitinternal(&monitor->rep, n, k, _state); - monitor->nonc0strrating = 0.0; - monitor->nonc0lngrating = -ae_maxrealnumber; - monitor->nonc0strrep.positive = ae_false; - monitor->nonc0lngrep.positive = ae_false; - monitor->nonc1test0strrating = 0.0; - monitor->nonc1test0lngrating = -ae_maxrealnumber; - monitor->nonc1test0strrep.positive = ae_false; - monitor->nonc1test0lngrep.positive = ae_false; - monitor->nonc1test1strrating = 0.0; - monitor->nonc1test1lngrating = -ae_maxrealnumber; - monitor->nonc1test1strrep.positive = ae_false; - monitor->nonc1test1lngrep.positive = ae_false; - monitor->badgradhasxj = ae_false; - ae_vector_set_length(&monitor->rstateg0.ia, 4+1, _state); - ae_vector_set_length(&monitor->rstateg0.ra, 3+1, _state); - monitor->rstateg0.stage = -1; -} - - -/************************************************************************* -This subroutine starts line search - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -void smoothnessmonitorstartlinesearch(smoothnessmonitor* monitor, - /* Real */ ae_vector* x, - /* Real */ ae_vector* fi, - /* Real */ ae_matrix* jac, - ae_state *_state) -{ - ae_int_t n; - ae_int_t k; - ae_int_t i; - ae_int_t j; - double v; - - - n = monitor->n; - k = monitor->k; - - /* - * Skip if inactive or spoiled by NAN - */ - if( !monitor->checksmoothness ) - { - return; - } - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = 0.5*v+x->ptr.p_double[i]; - } - for(i=0; i<=k-1; i++) - { - v = 0.5*v+fi->ptr.p_double[i]; - } - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = 0.5*v+jac->ptr.pp_double[i][j]; - } - } - if( !ae_isfinite(v, _state) ) - { - monitor->linesearchspoiled = ae_true; - return; - } - - /* - * Finalize previous line search - */ - if( monitor->enqueuedcnt>0 ) - { - smoothnessmonitorfinalizelinesearch(monitor, _state); - } - - /* - * Store initial point - */ - monitor->linesearchstarted = ae_true; - monitor->enqueuedcnt = 1; - rvectorgrowto(&monitor->enqueuedstp, monitor->enqueuedcnt, _state); - rvectorgrowto(&monitor->enqueuedx, monitor->enqueuedcnt*n, _state); - rvectorgrowto(&monitor->enqueuedfunc, monitor->enqueuedcnt*k, _state); - rmatrixgrowrowsto(&monitor->enqueuedjac, monitor->enqueuedcnt*k, n, _state); - monitor->enqueuedstp.ptr.p_double[0] = 0.0; - for(j=0; j<=n-1; j++) - { - monitor->enqueuedx.ptr.p_double[j] = x->ptr.p_double[j]; - } - for(i=0; i<=k-1; i++) - { - monitor->enqueuedfunc.ptr.p_double[i] = fi->ptr.p_double[i]; - } - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - monitor->enqueuedjac.ptr.pp_double[i][j] = jac->ptr.pp_double[i][j]; - } - } - - /* - * Initialize sorted representation - */ - rvectorgrowto(&monitor->sortedstp, 1, _state); - ivectorgrowto(&monitor->sortedidx, 1, _state); - monitor->sortedstp.ptr.p_double[0] = 0.0; - monitor->sortedidx.ptr.p_int[0] = 0; - monitor->sortedcnt = 1; -} - - -/************************************************************************* -This subroutine starts line search for a scalar function - convenience -wrapper for ....StartLineSearch() with unscaled variables. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -void smoothnessmonitorstartlinesearch1u(smoothnessmonitor* monitor, - /* Real */ ae_vector* s, - /* Real */ ae_vector* invs, - /* Real */ ae_vector* x, - double f0, - /* Real */ ae_vector* j0, - ae_state *_state) -{ - ae_int_t n; - ae_int_t k; - ae_int_t i; - - - n = monitor->n; - k = monitor->k; - if( !monitor->checksmoothness ) - { - return; - } - ae_assert(k==1, "SmoothnessMonitorStartLineSearch1: K<>1", _state); - rvectorsetlengthatleast(&monitor->xu, n, _state); - rvectorsetlengthatleast(&monitor->f0, 1, _state); - rmatrixsetlengthatleast(&monitor->j0, 1, n, _state); - monitor->f0.ptr.p_double[0] = f0; - for(i=0; i<=n-1; i++) - { - monitor->xu.ptr.p_double[i] = x->ptr.p_double[i]*invs->ptr.p_double[i]; - monitor->j0.ptr.pp_double[0][i] = j0->ptr.p_double[i]*s->ptr.p_double[i]; - } - smoothnessmonitorstartlinesearch(monitor, &monitor->xu, &monitor->f0, &monitor->j0, _state); -} - - -/************************************************************************* -This subroutine enqueues one more trial point - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -void smoothnessmonitorenqueuepoint(smoothnessmonitor* monitor, - /* Real */ ae_vector* d, - double stp, - /* Real */ ae_vector* x, - /* Real */ ae_vector* fi, - /* Real */ ae_matrix* jac, - ae_state *_state) -{ - ae_int_t n; - ae_int_t k; - ae_int_t i; - ae_int_t j; - double v; - ae_int_t enqueuedcnt; - ae_int_t sortedcnt; - ae_bool hasduplicates; - ae_int_t funcidx; - ae_int_t stpidx; - double f0; - double f1; - double f2; - double f3; - double f4; - double noise0; - double noise1; - double noise2; - double noise3; - double rating; - double lipschitz; - double nrm; - double lengthrating; - - - n = monitor->n; - k = monitor->k; - - /* - * Skip if inactive or spoiled by NAN - */ - if( (!monitor->checksmoothness||monitor->linesearchspoiled)||!monitor->linesearchstarted ) - { - return; - } - v = stp; - for(i=0; i<=n-1; i++) - { - v = 0.5*v+x->ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - v = 0.5*v+d->ptr.p_double[i]; - } - for(i=0; i<=k-1; i++) - { - v = 0.5*v+fi->ptr.p_double[i]; - } - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = 0.5*v+jac->ptr.pp_double[i][j]; - } - } - if( !ae_isfinite(v, _state) ) - { - monitor->linesearchspoiled = ae_true; - return; - } - - /* - * Enqueue - */ - inc(&monitor->enqueuedcnt, _state); - enqueuedcnt = monitor->enqueuedcnt; - rvectorgrowto(&monitor->dcur, n, _state); - rvectorgrowto(&monitor->enqueuedstp, enqueuedcnt, _state); - rvectorgrowto(&monitor->enqueuedx, enqueuedcnt*n, _state); - rvectorgrowto(&monitor->enqueuedfunc, enqueuedcnt*k, _state); - rmatrixgrowrowsto(&monitor->enqueuedjac, enqueuedcnt*k, n, _state); - monitor->enqueuedstp.ptr.p_double[enqueuedcnt-1] = stp; - for(j=0; j<=n-1; j++) - { - monitor->dcur.ptr.p_double[j] = d->ptr.p_double[j]; - } - for(j=0; j<=n-1; j++) - { - monitor->enqueuedx.ptr.p_double[(enqueuedcnt-1)*n+j] = x->ptr.p_double[j]; - } - for(i=0; i<=k-1; i++) - { - monitor->enqueuedfunc.ptr.p_double[(enqueuedcnt-1)*k+i] = fi->ptr.p_double[i]; - } - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - monitor->enqueuedjac.ptr.pp_double[(enqueuedcnt-1)*k+i][j] = jac->ptr.pp_double[i][j]; - } - } - - /* - * Update sorted representation: insert to the end, reorder - */ - sortedcnt = monitor->sortedcnt; - hasduplicates = ae_false; - for(i=0; i<=sortedcnt-1; i++) - { - hasduplicates = hasduplicates||monitor->sortedstp.ptr.p_double[i]==stp; - } - if( !hasduplicates ) - { - inc(&monitor->sortedcnt, _state); - sortedcnt = monitor->sortedcnt; - rvectorgrowto(&monitor->sortedstp, sortedcnt, _state); - ivectorgrowto(&monitor->sortedidx, sortedcnt, _state); - monitor->sortedstp.ptr.p_double[sortedcnt-1] = stp; - monitor->sortedidx.ptr.p_int[sortedcnt-1] = enqueuedcnt-1; - for(i=sortedcnt-2; i>=0; i--) - { - if( monitor->sortedstp.ptr.p_double[i]<=monitor->sortedstp.ptr.p_double[i+1] ) - { - break; - } - v = monitor->sortedstp.ptr.p_double[i]; - monitor->sortedstp.ptr.p_double[i] = monitor->sortedstp.ptr.p_double[i+1]; - monitor->sortedstp.ptr.p_double[i+1] = v; - j = monitor->sortedidx.ptr.p_int[i]; - monitor->sortedidx.ptr.p_int[i] = monitor->sortedidx.ptr.p_int[i+1]; - monitor->sortedidx.ptr.p_int[i+1] = j; - } - } - - /* - * Scan sorted representation, check for C0 and C1 continuity - * violations. - */ - rvectorsetlengthatleast(&monitor->f, sortedcnt, _state); - rvectorsetlengthatleast(&monitor->g, sortedcnt*n, _state); - for(funcidx=0; funcidx<=k-1; funcidx++) - { - - /* - * Fetch current function and its gradient to the contiguous storage - */ - for(i=0; i<=sortedcnt-1; i++) - { - monitor->f.ptr.p_double[i] = monitor->enqueuedfunc.ptr.p_double[monitor->sortedidx.ptr.p_int[i]*k+funcidx]; - for(j=0; j<=n-1; j++) - { - monitor->g.ptr.p_double[i*n+j] = monitor->enqueuedjac.ptr.pp_double[monitor->sortedidx.ptr.p_int[i]*k+funcidx][j]; - } - } - - /* - * Check C0 continuity. - * - * The basis approach is that we find appropriate candidate point - * (either a local minimum along the line - for target; or an interval - * where function sign is changed - for constraints), calculate left - * and right estimates of the Lipschitz constant (slopes between points - * #0 and #1, #2 and #3), and then calculate slope between points #1 and - * #2 and compare it with left/right estimates. - * - * The actual approach is a bit more complex to account for different - * sources of numerical noise and different false positive scenarios. - */ - if( funcidx==0 ) - { - for(stpidx=0; stpidx<=sortedcnt-4; stpidx++) - { - f0 = monitor->f.ptr.p_double[stpidx+0]; - f1 = monitor->f.ptr.p_double[stpidx+1]; - f2 = monitor->f.ptr.p_double[stpidx+2]; - f3 = monitor->f.ptr.p_double[stpidx+3]; - noise0 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f0, _state), 1.0, _state); - noise1 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f1, _state), 1.0, _state); - noise2 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f2, _state), 1.0, _state); - noise3 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f3, _state), 1.0, _state); - if( !(f1sortedstp.ptr.p_double[stpidx+1]-monitor->sortedstp.ptr.p_double[stpidx+0], monitor->sortedstp.ptr.p_double[stpidx+2]-monitor->sortedstp.ptr.p_double[stpidx+1], monitor->sortedstp.ptr.p_double[stpidx+3]-monitor->sortedstp.ptr.p_double[stpidx+2], ae_false, &rating, &lipschitz, _state); - if( rating>optserv_ogminrating0 ) - { - - /* - * Store to total report - */ - monitor->rep.nonc0suspected = ae_true; - monitor->rep.nonc0test0positive = ae_true; - if( rating>monitor->nonc0currentrating ) - { - monitor->nonc0currentrating = rating; - monitor->rep.nonc0lipschitzc = lipschitz; - monitor->rep.nonc0fidx = funcidx; - } - - /* - * Store to "strongest" report - */ - if( rating>monitor->nonc0strrating ) - { - monitor->nonc0strrating = rating; - monitor->nonc0strrep.positive = ae_true; - monitor->nonc0strrep.fidx = funcidx; - monitor->nonc0strrep.n = n; - monitor->nonc0strrep.cnt = sortedcnt; - monitor->nonc0strrep.stpidxa = stpidx+0; - monitor->nonc0strrep.stpidxb = stpidx+3; - rvectorsetlengthatleast(&monitor->nonc0strrep.x0, n, _state); - rvectorsetlengthatleast(&monitor->nonc0strrep.d, n, _state); - for(i=0; i<=n-1; i++) - { - monitor->nonc0strrep.x0.ptr.p_double[i] = monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[0]*n+i]; - monitor->nonc0strrep.d.ptr.p_double[i] = monitor->dcur.ptr.p_double[i]; - } - rvectorsetlengthatleast(&monitor->nonc0strrep.stp, sortedcnt, _state); - rvectorsetlengthatleast(&monitor->nonc0strrep.f, sortedcnt, _state); - for(i=0; i<=sortedcnt-1; i++) - { - monitor->nonc0strrep.stp.ptr.p_double[i] = monitor->sortedstp.ptr.p_double[i]; - monitor->nonc0strrep.f.ptr.p_double[i] = monitor->f.ptr.p_double[i]; - } - } - - /* - * Store to "longest" report - */ - nrm = (double)(0); - for(i=0; i<=n-1; i++) - { - nrm = nrm+ae_sqr(monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[0]*n+i]-monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[sortedcnt-1]*n+i], _state); - } - nrm = ae_sqrt(nrm, _state); - nrm = ae_minreal(nrm, 1.0, _state); - nrm = coalesce(nrm, ae_machineepsilon, _state); - lengthrating = sortedcnt+ae_log(nrm, _state)/ae_log((double)(100), _state); - if( lengthrating>monitor->nonc0lngrating ) - { - monitor->nonc0lngrating = lengthrating; - monitor->nonc0lngrep.positive = ae_true; - monitor->nonc0lngrep.fidx = funcidx; - monitor->nonc0lngrep.n = n; - monitor->nonc0lngrep.cnt = sortedcnt; - monitor->nonc0lngrep.stpidxa = stpidx+0; - monitor->nonc0lngrep.stpidxb = stpidx+3; - rvectorsetlengthatleast(&monitor->nonc0lngrep.x0, n, _state); - rvectorsetlengthatleast(&monitor->nonc0lngrep.d, n, _state); - for(i=0; i<=n-1; i++) - { - monitor->nonc0lngrep.x0.ptr.p_double[i] = monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[0]*n+i]; - monitor->nonc0lngrep.d.ptr.p_double[i] = monitor->dcur.ptr.p_double[i]; - } - rvectorsetlengthatleast(&monitor->nonc0lngrep.stp, sortedcnt, _state); - rvectorsetlengthatleast(&monitor->nonc0lngrep.f, sortedcnt, _state); - for(i=0; i<=sortedcnt-1; i++) - { - monitor->nonc0lngrep.stp.ptr.p_double[i] = monitor->sortedstp.ptr.p_double[i]; - monitor->nonc0lngrep.f.ptr.p_double[i] = monitor->f.ptr.p_double[i]; - } - } - } - } - } - - /* - * C1 continuity test #0 - */ - for(stpidx=0; stpidx<=sortedcnt-7; stpidx++) - { - - /* - * Fetch function values - */ - f2 = monitor->f.ptr.p_double[stpidx+2]; - f3 = monitor->f.ptr.p_double[stpidx+3]; - f4 = monitor->f.ptr.p_double[stpidx+4]; - noise2 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f2, _state), 1.0, _state); - noise3 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f3, _state), 1.0, _state); - - /* - * Decide whether we want to test this interval or not; for target - * function we test intervals around minimum, for constraints we - * test intervals of sign change. - */ - if( funcidx==0 ) - { - - /* - * Skip if not minimum - */ - if( !(f30 ) - { - continue; - } - } - optserv_c1continuitytest0(monitor, funcidx, stpidx+0, sortedcnt, _state); - optserv_c1continuitytest0(monitor, funcidx, stpidx+1, sortedcnt, _state); - } - - /* - * C1 continuity test #1 - */ - for(stpidx=0; stpidx<=sortedcnt-4; stpidx++) - { - - /* - * Fetch function values from the interval being tested - */ - f0 = monitor->f.ptr.p_double[stpidx+0]; - f1 = monitor->f.ptr.p_double[stpidx+1]; - f2 = monitor->f.ptr.p_double[stpidx+2]; - f3 = monitor->f.ptr.p_double[stpidx+3]; - noise0 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f0, _state), 1.0, _state); - noise1 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f1, _state), 1.0, _state); - noise2 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f2, _state), 1.0, _state); - noise3 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f3, _state), 1.0, _state); - - /* - * Decide whether we want to test this interval or not; for target - * function we test intervals around minimum, for constraints we - * test intervals of sign change. - */ - if( funcidx==0 ) - { - - /* - * Skip if not minimum - */ - if( !(f10 ) - { - continue; - } - } - optserv_c1continuitytest1(monitor, funcidx, stpidx, sortedcnt, _state); - } - } -} - - -/************************************************************************* -This subroutine enqueues one more trial point for a task with scalar -function with unscaled variables - a convenience wrapper for more general -EnqueuePoint() - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -void smoothnessmonitorenqueuepoint1u(smoothnessmonitor* monitor, - /* Real */ ae_vector* s, - /* Real */ ae_vector* invs, - /* Real */ ae_vector* d, - double stp, - /* Real */ ae_vector* x, - double f0, - /* Real */ ae_vector* j0, - ae_state *_state) -{ - ae_int_t n; - ae_int_t k; - ae_int_t i; - - - n = monitor->n; - k = monitor->k; - if( !monitor->checksmoothness ) - { - return; - } - ae_assert(k==1, "SmoothnessMonitorEnqueuePoint1: K<>1", _state); - rvectorsetlengthatleast(&monitor->xu, n, _state); - rvectorsetlengthatleast(&monitor->du, n, _state); - rvectorsetlengthatleast(&monitor->f0, 1, _state); - rmatrixsetlengthatleast(&monitor->j0, 1, n, _state); - monitor->f0.ptr.p_double[0] = f0; - for(i=0; i<=n-1; i++) - { - monitor->xu.ptr.p_double[i] = x->ptr.p_double[i]*invs->ptr.p_double[i]; - monitor->du.ptr.p_double[i] = d->ptr.p_double[i]*invs->ptr.p_double[i]; - monitor->j0.ptr.pp_double[0][i] = j0->ptr.p_double[i]*s->ptr.p_double[i]; - } - smoothnessmonitorenqueuepoint(monitor, &monitor->du, stp, &monitor->xu, &monitor->f0, &monitor->j0, _state); -} - - -/************************************************************************* -This subroutine finalizes line search - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -void smoothnessmonitorfinalizelinesearch(smoothnessmonitor* monitor, - ae_state *_state) -{ - - - - /* - * As for now - nothing to be done. - */ -} - - -/************************************************************************* -This function starts aggressive probing for a range of step lengths [0,StpMax]. - -This function stores NValues values per step, with the first one (index 0) -value being "primary" one (target function / merit function) and the rest -being supplementary ones. - - -- ALGLIB -- - Copyright 10.10.2019 by Bochkanov Sergey -*************************************************************************/ -void smoothnessmonitorstartprobing(smoothnessmonitor* monitor, - double stpmax, - ae_int_t nvalues, - double stepscale, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(stpmax, _state)&&ae_fp_greater(stpmax,(double)(0)), "SmoothnessMonitorStartProbing: StpMax<=0", _state); - ae_assert(nvalues>=1, "SmoothnessMonitorStartProbing: NValues<1", _state); - ae_assert(ae_isfinite(stepscale, _state)&&ae_fp_greater_eq(stepscale,(double)(0)), "SmoothnessMonitorStartProbing: StepScale<0", _state); - monitor->probingnvalues = nvalues; - monitor->probingnstepsstored = 0; - monitor->probingstepmax = stpmax; - monitor->probingstepscale = stepscale; - rvectorsetlengthatleast(&monitor->probingf, nvalues, _state); - ae_vector_set_length(&monitor->probingrcomm.ia, 2+1, _state); - ae_vector_set_length(&monitor->probingrcomm.ra, 3+1, _state); - monitor->probingrcomm.stage = -1; -} - - -/************************************************************************* -This function performs aggressive probing. - -After each call it returns step to evaluate in Monitor.ProbingStp. Load -values being probed into Monitor.ProbingF and continue iteration. - -Monitor.ProbingF[0] is a special value which is used to guide probing process -towards discontinuities and nonsmooth points. - - -- ALGLIB -- - Copyright 10.10.2019 by Bochkanov Sergey -*************************************************************************/ -ae_bool smoothnessmonitorprobe(smoothnessmonitor* monitor, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t idx; - double vlargest; - double v; - double v0; - double v1; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( monitor->probingrcomm.stage>=0 ) - { - i = monitor->probingrcomm.ia.ptr.p_int[0]; - j = monitor->probingrcomm.ia.ptr.p_int[1]; - idx = monitor->probingrcomm.ia.ptr.p_int[2]; - vlargest = monitor->probingrcomm.ra.ptr.p_double[0]; - v = monitor->probingrcomm.ra.ptr.p_double[1]; - v0 = monitor->probingrcomm.ra.ptr.p_double[2]; - v1 = monitor->probingrcomm.ra.ptr.p_double[3]; - } - else - { - i = 359; - j = -58; - idx = -919; - vlargest = -909; - v = 81; - v0 = 255; - v1 = 74; - } - if( monitor->probingrcomm.stage==0 ) - { - goto lbl_0; - } - - /* - * Routine body - */ - i = 0; -lbl_1: - if( i>40 ) - { - goto lbl_3; - } - - /* - * Increase storage size - */ - rvectorgrowto(&monitor->probingsteps, monitor->probingnstepsstored+1, _state); - rmatrixgrowrowsto(&monitor->probingvalues, monitor->probingnstepsstored+1, monitor->probingnvalues, _state); - rmatrixgrowrowsto(&monitor->probingslopes, monitor->probingnstepsstored+1, monitor->probingnvalues, _state); - - /* - * Determine probing step length, save step to the end of the storage - */ - if( i<=10 ) - { - - /* - * First 11 steps are performed over equidistant grid - */ - monitor->probingstp = (double)i/(double)10*monitor->probingstepmax; - } - else - { - - /* - * Subsequent steps target either points with maximum change in F[0] - * (search for discontinuity) or maximum change in slope of F[0] (search - * for nonsmoothness) - */ - ae_assert(monitor->probingnstepsstored>=3, "SMonitor: critical integrity check failed", _state); - if( i%2==0 ) - { - - /* - * Target interval with maximum change in F[0] - */ - idx = -1; - vlargest = (double)(0); - for(j=0; j<=monitor->probingnstepsstored-2; j++) - { - v = ae_fabs(monitor->probingvalues.ptr.pp_double[j+1][0]-monitor->probingvalues.ptr.pp_double[j][0], _state); - if( idx<0||ae_fp_greater(v,vlargest) ) - { - idx = j; - vlargest = v; - } - } - monitor->probingstp = 0.5*(monitor->probingsteps.ptr.p_double[idx]+monitor->probingsteps.ptr.p_double[idx+1]); - } - else - { - - /* - * Target interval [J,J+2] with maximum change in slope of F[0], select - * subinterval [J,J+1] or [J+1,J+2] with maximum length. - */ - idx = -1; - vlargest = (double)(0); - for(j=0; j<=monitor->probingnstepsstored-3; j++) - { - v0 = (monitor->probingvalues.ptr.pp_double[j+1][0]-monitor->probingvalues.ptr.pp_double[j+0][0])/(monitor->probingsteps.ptr.p_double[j+1]-monitor->probingsteps.ptr.p_double[j+0]+ae_machineepsilon); - v1 = (monitor->probingvalues.ptr.pp_double[j+2][0]-monitor->probingvalues.ptr.pp_double[j+1][0])/(monitor->probingsteps.ptr.p_double[j+2]-monitor->probingsteps.ptr.p_double[j+1]+ae_machineepsilon); - v = ae_fabs(v0-v1, _state); - if( idx<0||ae_fp_greater(v,vlargest) ) - { - idx = j; - vlargest = v; - } - } - if( ae_fp_greater(monitor->probingsteps.ptr.p_double[idx+2]-monitor->probingsteps.ptr.p_double[idx+1],monitor->probingsteps.ptr.p_double[idx+1]-monitor->probingsteps.ptr.p_double[idx+0]) ) - { - monitor->probingstp = 0.5*(monitor->probingsteps.ptr.p_double[idx+2]+monitor->probingsteps.ptr.p_double[idx+1]); - } - else - { - monitor->probingstp = 0.5*(monitor->probingsteps.ptr.p_double[idx+1]+monitor->probingsteps.ptr.p_double[idx+0]); - } - } - } - monitor->probingsteps.ptr.p_double[monitor->probingnstepsstored] = monitor->probingstp; - - /* - * Retrieve user values - */ - monitor->probingrcomm.stage = 0; - goto lbl_rcomm; -lbl_0: - for(j=0; j<=monitor->probingnvalues-1; j++) - { - monitor->probingvalues.ptr.pp_double[monitor->probingnstepsstored][j] = monitor->probingf.ptr.p_double[j]; - monitor->probingslopes.ptr.pp_double[monitor->probingnstepsstored][j] = (double)(0); - } - inc(&monitor->probingnstepsstored, _state); - - /* - * Resort - */ - for(j=monitor->probingnstepsstored-1; j>=1; j--) - { - if( ae_fp_less_eq(monitor->probingsteps.ptr.p_double[j-1],monitor->probingsteps.ptr.p_double[j]) ) - { - break; - } - swapelements(&monitor->probingsteps, j-1, j, _state); - swaprows(&monitor->probingvalues, j-1, j, monitor->probingnvalues, _state); - } - i = i+1; - goto lbl_1; -lbl_3: - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - monitor->probingrcomm.ia.ptr.p_int[0] = i; - monitor->probingrcomm.ia.ptr.p_int[1] = j; - monitor->probingrcomm.ia.ptr.p_int[2] = idx; - monitor->probingrcomm.ra.ptr.p_double[0] = vlargest; - monitor->probingrcomm.ra.ptr.p_double[1] = v; - monitor->probingrcomm.ra.ptr.p_double[2] = v0; - monitor->probingrcomm.ra.ptr.p_double[3] = v1; - return result; -} - - -/************************************************************************* -This function prints probing results to trace log. - -Tracing is performed using fixed width for all columns, so you may print -a header before printing trace - and reasonably expect that its width will -match that of the trace. This function promises that it wont change trace -output format without introducing breaking changes into its signature. - -NOTE: this function ALWAYS tries to print results; it is caller's responsibility - to decide whether he needs tracing or not. - - -- ALGLIB -- - Copyright 10.10.2019 by Bochkanov Sergey -*************************************************************************/ -void smoothnessmonitortraceprobingresults(smoothnessmonitor* monitor, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double steplen; - - - - /* - * Compute slopes - */ - for(i=0; i<=monitor->probingnstepsstored-2; i++) - { - for(j=0; j<=monitor->probingnvalues-1; j++) - { - steplen = (monitor->probingsteps.ptr.p_double[i+1]-monitor->probingsteps.ptr.p_double[i]+100*ae_machineepsilon)*(monitor->probingstepscale+ae_machineepsilon); - monitor->probingslopes.ptr.pp_double[i][j] = (monitor->probingvalues.ptr.pp_double[i+1][j]-monitor->probingvalues.ptr.pp_double[i][j])/steplen; - } - } - if( monitor->probingnstepsstored>=1 ) - { - for(j=0; j<=monitor->probingnvalues-1; j++) - { - monitor->probingslopes.ptr.pp_double[monitor->probingnstepsstored-1][j] = monitor->probingslopes.ptr.pp_double[ae_maxint(monitor->probingnstepsstored-2, 0, _state)][j]; - } - } - - /* - * Print to trace log - */ - ae_trace("*** ----------"); - for(j=0; j<=monitor->probingnvalues-1; j++) - { - ae_trace("-------------------------"); - } - ae_trace("\n"); - for(i=0; i<=monitor->probingnstepsstored-1; i++) - { - ae_trace("*** | %0.4f |", - (double)(monitor->probingsteps.ptr.p_double[i])); - for(j=0; j<=monitor->probingnvalues-1; j++) - { - ae_trace(" %11.3e %10.2e |", - (double)(monitor->probingvalues.ptr.pp_double[i][j]-monitor->probingvalues.ptr.pp_double[0][j]), - (double)(monitor->probingslopes.ptr.pp_double[i][j])); - } - ae_trace("\n"); - } - ae_trace("*** ----------"); - for(j=0; j<=monitor->probingnvalues-1; j++) - { - ae_trace("-------------------------"); - } - ae_trace("\n"); -} - - -/************************************************************************* -This subroutine tells monitor to output trace info. - -If CallerSuggestsTrace=True, monitor ALWAYS prints trace, even if no -suspicions were raised during optimization. If CallerSuggestsTrace=False, -the monitor will print trace only if: -* trace was requested by trace tag 'OPTGUARD' AND suspicious points were - found during optimization -* trace was requested by trace tag 'OPTGUARD.ALWAYS' - always - - -- ALGLIB -- - Copyright 11.10.2019 by Bochkanov Sergey -*************************************************************************/ -void smoothnessmonitortracestatus(smoothnessmonitor* monitor, - ae_bool callersuggeststrace, - ae_state *_state) -{ - ae_bool needreport; - ae_bool needxdreport; - ae_bool suspicionsraised; - ae_int_t i; - double slope; - - - - /* - * Do we need trace report? - */ - suspicionsraised = (monitor->rep.nonc0suspected||monitor->rep.nonc1suspected)||monitor->rep.badgradsuspected; - needreport = ae_false; - needreport = needreport||callersuggeststrace; - needreport = needreport||ae_is_trace_enabled("OPTGUARD.ALWAYS"); - needreport = needreport||(ae_is_trace_enabled("OPTGUARD")&&suspicionsraised); - if( !needreport ) - { - return; - } - needxdreport = needreport&&ae_is_trace_enabled("OPTIMIZERS.X"); - - /* - * - */ - ae_trace("\n"); - ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n"); - ae_trace("// OPTGUARD INTEGRITY CHECKER REPORT //\n"); - ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n"); - if( !suspicionsraised ) - { - ae_trace("> no discontinuity/nonsmoothness/bad-gradient suspicions were raised during optimization\n"); - return; - } - if( monitor->rep.nonc0suspected ) - { - ae_trace("> [WARNING] suspected discontinuity (aka C0-discontinuity)\n"); - } - if( monitor->rep.nonc1suspected ) - { - ae_trace("> [WARNING] suspected nonsmoothness (aka C1-discontinuity)\n"); - } - ae_trace("> printing out test reports...\n"); - if( monitor->rep.nonc0suspected&&monitor->rep.nonc0test0positive ) - { - ae_trace("> printing out discontinuity test #0 report:\n"); - ae_trace("*** -------------------------------------------------------\n"); - ae_trace("*** | Test #0 for discontinuity was triggered (this test |\n"); - ae_trace("*** | analyzes changes in function values). See below for |\n"); - ae_trace("*** | detailed info: |\n"); - ae_trace("*** | * function index: %10d", - (int)(monitor->nonc0lngrep.fidx)); - if( monitor->nonc0lngrep.fidx==0 ) - { - ae_trace(" (target) |\n"); - } - else - { - ae_trace(" (constraint) |\n"); - } - ae_trace("*** | * F() Lipschitz const: %10.2e |\n", - (double)(monitor->rep.nonc0lipschitzc)); - ae_trace("*** | Printing out log of suspicious line search XK+Stp*D |\n"); - ae_trace("*** | Look for abrupt changes in slope. |\n"); - if( !needxdreport ) - { - ae_trace("*** | NOTE: XK and D are not printed by default. If you |\n"); - ae_trace("*** | need them, add trace tag OPTIMIZERS.X |\n"); - } - ae_trace("*** -------------------------------------------------------\n"); - ae_trace("*** | step along D | delta F | slope |\n"); - ae_trace("*** ------------------------------------------------------|\n"); - for(i=0; i<=monitor->nonc0lngrep.cnt-1; i++) - { - slope = monitor->nonc0lngrep.f.ptr.p_double[ae_minint(i+1, monitor->nonc0lngrep.cnt-1, _state)]-monitor->nonc0lngrep.f.ptr.p_double[i]; - slope = slope/(1.0e-15+monitor->nonc0lngrep.stp.ptr.p_double[ae_minint(i+1, monitor->nonc0lngrep.cnt-1, _state)]-monitor->nonc0lngrep.stp.ptr.p_double[i]); - ae_trace("*** | %13.5e | %13.5e | %11.3e |", - (double)(monitor->nonc0lngrep.stp.ptr.p_double[i]), - (double)(monitor->nonc0lngrep.f.ptr.p_double[i]-monitor->nonc0lngrep.f.ptr.p_double[0]), - (double)(slope)); - if( i>=monitor->nonc0lngrep.stpidxa&&i<=monitor->nonc0lngrep.stpidxb ) - { - ae_trace(" <---"); - } - ae_trace("\n"); - } - ae_trace("*** ------------------------------------------------------|\n"); - if( needxdreport ) - { - ae_trace("*** > printing raw variables\n"); - ae_trace("*** XK = "); - tracevectorunscaledunshiftedautoprec(&monitor->nonc0lngrep.x0, monitor->n, &monitor->s, ae_true, &monitor->s, ae_false, _state); - ae_trace("\n"); - ae_trace("*** D = "); - tracevectorunscaledunshiftedautoprec(&monitor->nonc0lngrep.d, monitor->n, &monitor->s, ae_true, &monitor->s, ae_false, _state); - ae_trace("\n"); - ae_trace("*** > printing scaled variables (values are divided by user-specified scales)\n"); - ae_trace("*** XK = "); - tracevectorautoprec(&monitor->nonc0lngrep.x0, 0, monitor->n, _state); - ae_trace("\n"); - ae_trace("*** D = "); - tracevectorautoprec(&monitor->nonc0lngrep.d, 0, monitor->n, _state); - ae_trace("\n"); - } - } - if( monitor->rep.nonc1suspected&&monitor->rep.nonc1test0positive ) - { - ae_trace("> printing out nonsmoothness test #0 report:\n"); - ae_trace("*** -------------------------------------------------------\n"); - ae_trace("*** | Test #0 for nonsmoothness was triggered (this test |\n"); - ae_trace("*** | analyzes changes in function values and ignores |\n"); - ae_trace("*** | gradient info). See below for detailed info: |\n"); - ae_trace("*** | * function index: %10d", - (int)(monitor->nonc1test0lngrep.fidx)); - if( monitor->nonc1test0lngrep.fidx==0 ) - { - ae_trace(" (target) |\n"); - } - else - { - ae_trace(" (constraint) |\n"); - } - ae_trace("*** | * dF/dX Lipschitz const: %10.2e |\n", - (double)(monitor->rep.nonc1lipschitzc)); - ae_trace("*** | Printing out log of suspicious line search XK+Stp*D |\n"); - ae_trace("*** | Look for abrupt changes in slope. |\n"); - if( !needxdreport ) - { - ae_trace("*** | NOTE: XK and D are not printed by default. If you |\n"); - ae_trace("*** | need them, add trace tag OPTIMIZERS.X |\n"); - } - ae_trace("*** -------------------------------------------------------\n"); - ae_trace("*** | step along D | delta F | slope |\n"); - ae_trace("*** ------------------------------------------------------|\n"); - for(i=0; i<=monitor->nonc1test0lngrep.cnt-1; i++) - { - slope = monitor->nonc1test0lngrep.f.ptr.p_double[ae_minint(i+1, monitor->nonc1test0lngrep.cnt-1, _state)]-monitor->nonc1test0lngrep.f.ptr.p_double[i]; - slope = slope/(1.0e-15+monitor->nonc1test0lngrep.stp.ptr.p_double[ae_minint(i+1, monitor->nonc1test0lngrep.cnt-1, _state)]-monitor->nonc1test0lngrep.stp.ptr.p_double[i]); - ae_trace("*** | %13.5e | %13.5e | %11.3e |", - (double)(monitor->nonc1test0lngrep.stp.ptr.p_double[i]), - (double)(monitor->nonc1test0lngrep.f.ptr.p_double[i]-monitor->nonc1test0lngrep.f.ptr.p_double[0]), - (double)(slope)); - if( i>=monitor->nonc1test0lngrep.stpidxa&&i<=monitor->nonc1test0lngrep.stpidxb ) - { - ae_trace(" <---"); - } - ae_trace("\n"); - } - ae_trace("*** ------------------------------------------------------|\n"); - if( needxdreport ) - { - ae_trace("*** > printing raw variables\n"); - ae_trace("*** XK = "); - tracevectorunscaledunshiftedautoprec(&monitor->nonc1test0lngrep.x0, monitor->n, &monitor->s, ae_true, &monitor->s, ae_false, _state); - ae_trace("\n"); - ae_trace("*** D = "); - tracevectorunscaledunshiftedautoprec(&monitor->nonc1test0lngrep.d, monitor->n, &monitor->s, ae_true, &monitor->s, ae_false, _state); - ae_trace("\n"); - ae_trace("*** > printing scaled variables (values are divided by user-specified scales)\n"); - ae_trace("*** XK = "); - tracevectorautoprec(&monitor->nonc1test0lngrep.x0, 0, monitor->n, _state); - ae_trace("\n"); - ae_trace("*** D = "); - tracevectorautoprec(&monitor->nonc1test0lngrep.d, 0, monitor->n, _state); - ae_trace("\n"); - } - } - if( monitor->rep.nonc1suspected&&monitor->rep.nonc1test1positive ) - { - ae_trace("> printing out nonsmoothness test #1 report:\n"); - ae_trace("*** -------------------------------------------------------\n"); - ae_trace("*** | Test #1 for nonsmoothness was triggered (this test |\n"); - ae_trace("*** | analyzes changes in gradient components). See below |\n"); - ae_trace("*** | for detailed info: |\n"); - ae_trace("*** | * function index: %10d", - (int)(monitor->nonc1test1lngrep.fidx)); - if( monitor->nonc1test1lngrep.fidx==0 ) - { - ae_trace(" (target) |\n"); - } - else - { - ae_trace(" (constraint) |\n"); - } - ae_trace("*** | * variable index I: %10d |\n", - (int)(monitor->nonc1test1lngrep.vidx)); - ae_trace("*** | * dF/dX Lipschitz const: %10.2e |\n", - (double)(monitor->rep.nonc1lipschitzc)); - ae_trace("*** | Printing out log of suspicious line search XK+Stp*D |\n"); - ae_trace("*** | Look for abrupt changes in slope. |\n"); - if( !needxdreport ) - { - ae_trace("*** | NOTE: XK and D are not printed by default. If you |\n"); - ae_trace("*** | need them, add trace tag OPTIMIZERS.X |\n"); - } - ae_trace("*** -------------------------------------------------------\n"); - ae_trace("*** | step along D | delta Gi | slope |\n"); - ae_trace("*** ------------------------------------------------------|\n"); - for(i=0; i<=monitor->nonc1test1lngrep.cnt-1; i++) - { - slope = monitor->nonc1test1lngrep.g.ptr.p_double[ae_minint(i+1, monitor->nonc1test1lngrep.cnt-1, _state)]-monitor->nonc1test1lngrep.g.ptr.p_double[i]; - slope = slope/(1.0e-15+monitor->nonc1test1lngrep.stp.ptr.p_double[ae_minint(i+1, monitor->nonc1test1lngrep.cnt-1, _state)]-monitor->nonc1test1lngrep.stp.ptr.p_double[i]); - ae_trace("*** | %13.5e | %13.5e | %11.3e |", - (double)(monitor->nonc1test1lngrep.stp.ptr.p_double[i]), - (double)(monitor->nonc1test1lngrep.g.ptr.p_double[i]-monitor->nonc1test1lngrep.g.ptr.p_double[0]), - (double)(slope)); - if( i>=monitor->nonc1test1lngrep.stpidxa&&i<=monitor->nonc1test1lngrep.stpidxb ) - { - ae_trace(" <---"); - } - ae_trace("\n"); - } - ae_trace("*** ------------------------------------------------------|\n"); - if( needxdreport ) - { - ae_trace("*** > printing raw variables\n"); - ae_trace("*** XK = "); - tracevectorunscaledunshiftedautoprec(&monitor->nonc1test1lngrep.x0, monitor->n, &monitor->s, ae_true, &monitor->s, ae_false, _state); - ae_trace("\n"); - ae_trace("*** D = "); - tracevectorunscaledunshiftedautoprec(&monitor->nonc1test1lngrep.d, monitor->n, &monitor->s, ae_true, &monitor->s, ae_false, _state); - ae_trace("\n"); - ae_trace("*** > printing scaled variables (values are divided by user-specified scales)\n"); - ae_trace("*** XK = "); - tracevectorautoprec(&monitor->nonc1test1lngrep.x0, 0, monitor->n, _state); - ae_trace("\n"); - ae_trace("*** D = "); - tracevectorautoprec(&monitor->nonc1test1lngrep.d, 0, monitor->n, _state); - ae_trace("\n"); - } - } -} - - -/************************************************************************* -This subroutine exports report to user-readable representation (all arrays -are forced to have exactly same size as needed; unused arrays are set to -zero length). - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -void smoothnessmonitorexportreport(smoothnessmonitor* monitor, - optguardreport* rep, - ae_state *_state) -{ - - - - /* - * Finalize last line search, just to be sure - */ - if( monitor->enqueuedcnt>0 ) - { - smoothnessmonitorfinalizelinesearch(monitor, _state); - } - - /* - * Export report - */ - optguardexportreport(&monitor->rep, monitor->n, monitor->k, monitor->badgradhasxj, rep, _state); -} - - -/************************************************************************* -Check numerical gradient at point X0 (unscaled variables!), with optional -box constraints [BndL,BndU] (if HasBoxConstraints=True) and with scale -vector S[]. - -Step S[i]*TestStep is performed along I-th variable. - -NeedFiJ rcomm protocol is used to request derivative information. - -Box constraints BndL/BndU are expected to be feasible. It is possible to -have BndL=BndU. - - -- ALGLIB -- - Copyright 06.12.2018 by Bochkanov Sergey -*************************************************************************/ -ae_bool smoothnessmonitorcheckgradientatx0(smoothnessmonitor* monitor, - /* Real */ ae_vector* unscaledx0, - /* Real */ ae_vector* s, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_bool hasboxconstraints, - double teststep, - ae_state *_state) -{ - ae_int_t n; - ae_int_t k; - ae_int_t i; - ae_int_t j; - ae_int_t varidx; - double v; - double vp; - double vm; - double vc; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( monitor->rstateg0.stage>=0 ) - { - n = monitor->rstateg0.ia.ptr.p_int[0]; - k = monitor->rstateg0.ia.ptr.p_int[1]; - i = monitor->rstateg0.ia.ptr.p_int[2]; - j = monitor->rstateg0.ia.ptr.p_int[3]; - varidx = monitor->rstateg0.ia.ptr.p_int[4]; - v = monitor->rstateg0.ra.ptr.p_double[0]; - vp = monitor->rstateg0.ra.ptr.p_double[1]; - vm = monitor->rstateg0.ra.ptr.p_double[2]; - vc = monitor->rstateg0.ra.ptr.p_double[3]; - } - else - { - n = -788; - k = 809; - i = 205; - j = -838; - varidx = 939; - v = -526; - vp = 763; - vm = -541; - vc = -698; - } - if( monitor->rstateg0.stage==0 ) - { - goto lbl_0; - } - if( monitor->rstateg0.stage==1 ) - { - goto lbl_1; - } - if( monitor->rstateg0.stage==2 ) - { - goto lbl_2; - } - if( monitor->rstateg0.stage==3 ) - { - goto lbl_3; - } - - /* - * Routine body - */ - n = monitor->n; - k = monitor->k; - monitor->needfij = ae_false; - - /* - * Quick exit - */ - if( ((n<=0||k<=0)||!ae_isfinite(teststep, _state))||ae_fp_eq(teststep,(double)(0)) ) - { - result = ae_false; - return result; - } - teststep = ae_fabs(teststep, _state); - - /* - * Allocate storage - */ - rvectorsetlengthatleast(&monitor->x, n, _state); - rvectorsetlengthatleast(&monitor->fi, k, _state); - rmatrixsetlengthatleast(&monitor->j, k, n, _state); - rvectorsetlengthatleast(&monitor->xbase, n, _state); - rvectorsetlengthatleast(&monitor->fbase, k, _state); - rvectorsetlengthatleast(&monitor->fm, k, _state); - rvectorsetlengthatleast(&monitor->fc, k, _state); - rvectorsetlengthatleast(&monitor->fp, k, _state); - rvectorsetlengthatleast(&monitor->jm, k, _state); - rvectorsetlengthatleast(&monitor->jc, k, _state); - rvectorsetlengthatleast(&monitor->jp, k, _state); - rmatrixsetlengthatleast(&monitor->jbaseusr, k, n, _state); - rmatrixsetlengthatleast(&monitor->jbasenum, k, n, _state); - rvectorsetlengthatleast(&monitor->rep.badgradxbase, n, _state); - rmatrixsetlengthatleast(&monitor->rep.badgraduser, k, n, _state); - rmatrixsetlengthatleast(&monitor->rep.badgradnum, k, n, _state); - - /* - * Set XBase/Jacobian presence flag - */ - monitor->badgradhasxj = ae_true; - - /* - * Determine reference point, compute function vector and user-supplied Jacobian - */ - for(i=0; i<=n-1; i++) - { - v = unscaledx0->ptr.p_double[i]; - if( (hasboxconstraints&&ae_isfinite(bndl->ptr.p_double[i], _state))&&ae_fp_less(v,bndl->ptr.p_double[i]) ) - { - v = bndl->ptr.p_double[i]; - } - if( (hasboxconstraints&&ae_isfinite(bndu->ptr.p_double[i], _state))&&ae_fp_greater(v,bndu->ptr.p_double[i]) ) - { - v = bndu->ptr.p_double[i]; - } - monitor->xbase.ptr.p_double[i] = v; - monitor->rep.badgradxbase.ptr.p_double[i] = v; - monitor->x.ptr.p_double[i] = v; - } - monitor->needfij = ae_true; - monitor->rstateg0.stage = 0; - goto lbl_rcomm; -lbl_0: - monitor->needfij = ae_false; - for(i=0; i<=k-1; i++) - { - monitor->fbase.ptr.p_double[i] = monitor->fi.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - monitor->jbaseusr.ptr.pp_double[i][j] = monitor->j.ptr.pp_double[i][j]; - monitor->rep.badgraduser.ptr.pp_double[i][j] = monitor->j.ptr.pp_double[i][j]; - } - } - - /* - * Check Jacobian column by column - */ - varidx = 0; -lbl_4: - if( varidx>n-1 ) - { - goto lbl_6; - } - - /* - * Determine test location. - */ - v = monitor->xbase.ptr.p_double[varidx]; - vm = v-s->ptr.p_double[varidx]*teststep; - vp = v+s->ptr.p_double[varidx]*teststep; - if( (hasboxconstraints&&ae_isfinite(bndl->ptr.p_double[varidx], _state))&&ae_fp_less(vm,bndl->ptr.p_double[varidx]) ) - { - vm = bndl->ptr.p_double[varidx]; - } - if( (hasboxconstraints&&ae_isfinite(bndu->ptr.p_double[varidx], _state))&&ae_fp_greater(vp,bndu->ptr.p_double[varidx]) ) - { - vp = bndu->ptr.p_double[varidx]; - } - vc = vm+(vp-vm)/2; - - /* - * Quickly skip fixed variables - */ - if( (ae_fp_eq(vm,vp)||ae_fp_eq(vc,vm))||ae_fp_eq(vc,vp) ) - { - for(i=0; i<=k-1; i++) - { - monitor->rep.badgradnum.ptr.pp_double[i][varidx] = (double)(0); - } - goto lbl_5; - } - - /* - * Compute F/J at three trial points - */ - for(i=0; i<=n-1; i++) - { - monitor->x.ptr.p_double[i] = monitor->xbase.ptr.p_double[i]; - } - monitor->x.ptr.p_double[varidx] = vm; - monitor->needfij = ae_true; - monitor->rstateg0.stage = 1; - goto lbl_rcomm; -lbl_1: - monitor->needfij = ae_false; - for(i=0; i<=k-1; i++) - { - monitor->fm.ptr.p_double[i] = monitor->fi.ptr.p_double[i]; - monitor->jm.ptr.p_double[i] = monitor->j.ptr.pp_double[i][varidx]; - } - for(i=0; i<=n-1; i++) - { - monitor->x.ptr.p_double[i] = monitor->xbase.ptr.p_double[i]; - } - monitor->x.ptr.p_double[varidx] = vc; - monitor->needfij = ae_true; - monitor->rstateg0.stage = 2; - goto lbl_rcomm; -lbl_2: - monitor->needfij = ae_false; - for(i=0; i<=k-1; i++) - { - monitor->fc.ptr.p_double[i] = monitor->fi.ptr.p_double[i]; - monitor->jc.ptr.p_double[i] = monitor->j.ptr.pp_double[i][varidx]; - } - for(i=0; i<=n-1; i++) - { - monitor->x.ptr.p_double[i] = monitor->xbase.ptr.p_double[i]; - } - monitor->x.ptr.p_double[varidx] = vp; - monitor->needfij = ae_true; - monitor->rstateg0.stage = 3; - goto lbl_rcomm; -lbl_3: - monitor->needfij = ae_false; - for(i=0; i<=k-1; i++) - { - monitor->fp.ptr.p_double[i] = monitor->fi.ptr.p_double[i]; - monitor->jp.ptr.p_double[i] = monitor->j.ptr.pp_double[i][varidx]; - } - - /* - * Check derivative - */ - for(i=0; i<=k-1; i++) - { - monitor->rep.badgradnum.ptr.pp_double[i][varidx] = (monitor->fp.ptr.p_double[i]-monitor->fm.ptr.p_double[i])/(vp-vm); - if( !derivativecheck(monitor->fm.ptr.p_double[i], monitor->jm.ptr.p_double[i]*s->ptr.p_double[varidx], monitor->fp.ptr.p_double[i], monitor->jp.ptr.p_double[i]*s->ptr.p_double[varidx], monitor->fc.ptr.p_double[i], monitor->jc.ptr.p_double[i]*s->ptr.p_double[varidx], (vp-vm)/s->ptr.p_double[varidx], _state) ) - { - monitor->rep.badgradsuspected = ae_true; - monitor->rep.badgradfidx = i; - monitor->rep.badgradvidx = varidx; - } - } -lbl_5: - varidx = varidx+1; - goto lbl_4; -lbl_6: - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - monitor->rstateg0.ia.ptr.p_int[0] = n; - monitor->rstateg0.ia.ptr.p_int[1] = k; - monitor->rstateg0.ia.ptr.p_int[2] = i; - monitor->rstateg0.ia.ptr.p_int[3] = j; - monitor->rstateg0.ia.ptr.p_int[4] = varidx; - monitor->rstateg0.ra.ptr.p_double[0] = v; - monitor->rstateg0.ra.ptr.p_double[1] = vp; - monitor->rstateg0.ra.ptr.p_double[2] = vm; - monitor->rstateg0.ra.ptr.p_double[3] = vc; - return result; -} - - -/************************************************************************* -This function calculates feasibility error (square root of sum of squared -errors) for a Kx(NMain+NSlack) system of linear equalities. - -INPUT PARAMETERS: - CE - set of K equality constraints, array[K,NMain+NSlack+1] - X - candidate point, array [NMain+NSlack] - NMain - number of primary variables - NSlack - number of slack variables - K - number of constraints - Tmp0 - possible preallocated buffer, automatically resized - -RESULT: - Sqrt(SUM(Err^2)) - - -- ALGLIB -- - Copyright 17.09.2015 by Bochkanov Sergey -*************************************************************************/ -static double optserv_feasibilityerror(/* Real */ ae_matrix* ce, - /* Real */ ae_vector* x, - ae_int_t nmain, - ae_int_t nslack, - ae_int_t k, - /* Real */ ae_vector* tmp0, - ae_state *_state) -{ - ae_int_t i; - double result; - - - rvectorsetlengthatleast(tmp0, k, _state); - for(i=0; i<=k-1; i++) - { - tmp0->ptr.p_double[i] = -ce->ptr.pp_double[i][nmain+nslack]; - } - rmatrixgemv(k, nmain+nslack, 1.0, ce, 0, 0, 0, x, 0, 1.0, tmp0, 0, _state); - result = 0.0; - for(i=0; i<=k-1; i++) - { - result = result+tmp0->ptr.p_double[i]*tmp0->ptr.p_double[i]; - } - result = ae_sqrt(result, _state); - return result; -} - - -/************************************************************************* -This function calculates feasibility error (square root of sum of squared -errors) for a Kx(NMain+NSlack) system of linear equalities and error -gradient (with respect to x) - -INPUT PARAMETERS: - CE - set of K equality constraints, array[K,NMain+NSlack+1] - X - candidate point, array [NMain+NSlack] - NMain - number of primary variables - NSlack - number of slack variables - K - number of constraints - Grad - preallocated array[NMain+NSlack] - Tmp0 - possible preallocated buffer, automatically resized - -RESULT: - Err - Sqrt(SUM(Err^2)) - Grad - error gradient with respect to X, array[NMain+NSlack] - - -- ALGLIB -- - Copyright 17.09.2015 by Bochkanov Sergey -*************************************************************************/ -static void optserv_feasibilityerrorgrad(/* Real */ ae_matrix* ce, - /* Real */ ae_vector* x, - ae_int_t nmain, - ae_int_t nslack, - ae_int_t k, - double* err, - /* Real */ ae_vector* grad, - /* Real */ ae_vector* tmp0, - ae_state *_state) -{ - ae_int_t i; - double v; - - *err = 0; - - ae_assert(grad->cnt>=nmain+nslack, "FeasibilityErrorGrad: integrity check failed", _state); - rvectorsetlengthatleast(tmp0, k, _state); - rmatrixgemv(k, nmain+nslack, 1.0, ce, 0, 0, 0, x, 0, 0.0, tmp0, 0, _state); - *err = 0.0; - for(i=0; i<=k-1; i++) - { - v = tmp0->ptr.p_double[i]-ce->ptr.pp_double[i][nmain+nslack]; - tmp0->ptr.p_double[i] = v; - *err = *err+v*v; - } - *err = ae_sqrt(*err, _state); - rmatrixgemv(nmain+nslack, k, 1.0, ce, 0, 0, 1, tmp0, 0, 0.0, grad, 0, _state); -} - - -/************************************************************************* -This subroutine checks C0 continuity and returns continuity rating -(normalized value, with values above 50-500 being good indication of the -discontinuity) and Lipschitz constant. - -An interval between F1 and F2 is tested for (dis)continuity. Per-point -noise estimates are provided. Delta[i] is a step from F[i] to F[i+1]. - -ApplySpecialCorrection parameter should be set to True if you use this -function to estimate continuity of the model around minimum; it adds -special correction which helps to detect "max(0,1/x)"-like discontinuities. -Without this correction algorithm will still work, but will be a bit less -powerful. Do not use this correction for situations when you want to -estimate continuity around some non-extremal point - it may result in -spurious discontinuities being reported. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -static void optserv_testc0continuity(double f0, - double f1, - double f2, - double f3, - double noise0, - double noise1, - double noise2, - double noise3, - double delta0, - double delta1, - double delta2, - ae_bool applyspecialcorrection, - double* rating, - double* lipschitz, - ae_state *_state) -{ - double lipschitz01; - double lipschitz12; - double lipschitz23; - - *rating = 0; - *lipschitz = 0; - - - /* - * Compute Lipschitz constant for the interval [0,1], - * add noise correction in order to get increased estimate (makes - * comparison below more conservative). - */ - lipschitz01 = (ae_fabs(f1-f0, _state)+(noise0+noise1))/delta0; - - /* - * Compute Lipschitz constant for the interval [StpIdx+1,StpIdx+2], - * SUBTRACT noise correction in order to get decreased estimate (makes - * comparison below more conservative). - */ - lipschitz12 = ae_maxreal(ae_fabs(f2-f1, _state)-(noise1+noise2), 0.0, _state)/delta1; - - /* - * Compute Lipschitz constant for the interval [StpIdx+2,StpIdx+3] - * using special algorithm: - * a) if F30, "OptGuard: integrity check failed", _state); - *rating = lipschitz12/ae_maxreal(lipschitz01, lipschitz23, _state); - *lipschitz = lipschitz12; -} - - -/************************************************************************* -This subroutine checks C1 continuity using test #0 (function values from -the line search log are studied, gradient is not used). - -An interval between F[StpIdx+0] and F[StpIdx+5]is tested for continuity. -An normalized error metric (Lipschitz constant growth for the derivative) -for the interval in question is calculated. Values above 50 are a good -indication of the discontinuity. - -A six-point algorithm is used for testing, so we expect that Monitor.F and -Monitor.Stp have enough points for this test. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -static void optserv_c1continuitytest0(smoothnessmonitor* monitor, - ae_int_t funcidx, - ae_int_t stpidx, - ae_int_t sortedcnt, - ae_state *_state) -{ - double f0; - double f1; - double f2; - double f3; - double f4; - double f5; - double noise0; - double noise1; - double noise2; - double noise3; - double noise4; - double noise5; - double delta0; - double delta1; - double delta2; - double delta3; - double delta4; - double d0; - double d1; - double d2; - double d3; - double newnoise0; - double newnoise1; - double newnoise2; - double newnoise3; - double newdelta0; - double newdelta1; - double newdelta2; - double rating; - double lipschitz; - double lengthrating; - ae_int_t i; - ae_int_t n; - double nrm; - - - n = monitor->n; - ae_assert(stpidx+5sortedstp.ptr.p_double[0],(double)(0)), "C1ContinuityTest0: integrity check failed", _state); - ae_assert(ae_fp_greater(monitor->sortedstp.ptr.p_double[sortedcnt-1],(double)(0)), "C1ContinuityTest0: integrity check failed", _state); - - /* - * Fetch F, noise, Delta's - */ - f0 = monitor->f.ptr.p_double[stpidx+0]; - f1 = monitor->f.ptr.p_double[stpidx+1]; - f2 = monitor->f.ptr.p_double[stpidx+2]; - f3 = monitor->f.ptr.p_double[stpidx+3]; - f4 = monitor->f.ptr.p_double[stpidx+4]; - f5 = monitor->f.ptr.p_double[stpidx+5]; - noise0 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f0, _state), 1.0, _state); - noise1 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f1, _state), 1.0, _state); - noise2 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f2, _state), 1.0, _state); - noise3 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f3, _state), 1.0, _state); - noise4 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f4, _state), 1.0, _state); - noise5 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f5, _state), 1.0, _state); - delta0 = monitor->sortedstp.ptr.p_double[stpidx+1]-monitor->sortedstp.ptr.p_double[stpidx+0]; - delta1 = monitor->sortedstp.ptr.p_double[stpidx+2]-monitor->sortedstp.ptr.p_double[stpidx+1]; - delta2 = monitor->sortedstp.ptr.p_double[stpidx+3]-monitor->sortedstp.ptr.p_double[stpidx+2]; - delta3 = monitor->sortedstp.ptr.p_double[stpidx+4]-monitor->sortedstp.ptr.p_double[stpidx+3]; - delta4 = monitor->sortedstp.ptr.p_double[stpidx+5]-monitor->sortedstp.ptr.p_double[stpidx+4]; - - /* - * Differentiate functions, get derivative values and noise - * estimates at points (0+1)/2, (1+2)/2, (3+4)/2, (3+4)/2, - * (4+5)/2. Compute new step values NewDelta[i] and new - * noise estimates. - */ - d0 = (f1-f0)/delta0; - d1 = (f2-f1)/delta1; - d2 = (f4-f3)/delta3; - d3 = (f5-f4)/delta4; - newnoise0 = (noise0+noise1)/delta0; - newnoise1 = (noise1+noise2)/delta1; - newnoise2 = (noise3+noise4)/delta3; - newnoise3 = (noise4+noise5)/delta4; - newdelta0 = 0.5*(delta0+delta1); - newdelta1 = 0.5*delta1+delta2+0.5*delta3; - newdelta2 = 0.5*(delta3+delta4); - - /* - * Test with C0 continuity tester. "Special correction" is - * turned off for this test. - */ - optserv_testc0continuity(d0, d1, d2, d3, newnoise0, newnoise1, newnoise2, newnoise3, newdelta0, newdelta1, newdelta2, ae_false, &rating, &lipschitz, _state); - - /* - * Store results - */ - if( rating>optserv_ogminrating1 ) - { - - /* - * Store to total report - */ - monitor->rep.nonc1test0positive = ae_true; - if( rating>monitor->nonc1currentrating ) - { - monitor->nonc1currentrating = rating; - monitor->rep.nonc1suspected = ae_true; - monitor->rep.nonc1lipschitzc = lipschitz; - monitor->rep.nonc1fidx = funcidx; - } - - /* - * Store to "strongest" report - */ - if( rating>monitor->nonc1test0strrating ) - { - monitor->nonc1test0strrating = rating; - monitor->nonc1test0strrep.positive = ae_true; - monitor->nonc1test0strrep.fidx = funcidx; - monitor->nonc1test0strrep.n = n; - monitor->nonc1test0strrep.cnt = sortedcnt; - monitor->nonc1test0strrep.stpidxa = stpidx+1; - monitor->nonc1test0strrep.stpidxb = stpidx+4; - rvectorsetlengthatleast(&monitor->nonc1test0strrep.x0, n, _state); - rvectorsetlengthatleast(&monitor->nonc1test0strrep.d, n, _state); - for(i=0; i<=n-1; i++) - { - monitor->nonc1test0strrep.x0.ptr.p_double[i] = monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[0]*n+i]; - monitor->nonc1test0strrep.d.ptr.p_double[i] = monitor->dcur.ptr.p_double[i]; - } - rvectorsetlengthatleast(&monitor->nonc1test0strrep.stp, sortedcnt, _state); - rvectorsetlengthatleast(&monitor->nonc1test0strrep.f, sortedcnt, _state); - for(i=0; i<=sortedcnt-1; i++) - { - monitor->nonc1test0strrep.stp.ptr.p_double[i] = monitor->sortedstp.ptr.p_double[i]; - monitor->nonc1test0strrep.f.ptr.p_double[i] = monitor->f.ptr.p_double[i]; - } - } - - /* - * Store to "longest" report - */ - nrm = (double)(0); - for(i=0; i<=n-1; i++) - { - nrm = nrm+ae_sqr(monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[0]*n+i]-monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[sortedcnt-1]*n+i], _state); - } - nrm = ae_sqrt(nrm, _state); - nrm = ae_minreal(nrm, 1.0, _state); - nrm = coalesce(nrm, ae_machineepsilon, _state); - lengthrating = sortedcnt+ae_log(nrm, _state)/ae_log((double)(100), _state); - if( lengthrating>monitor->nonc1test0lngrating ) - { - monitor->nonc1test0lngrating = lengthrating; - monitor->nonc1test0lngrep.positive = ae_true; - monitor->nonc1test0lngrep.fidx = funcidx; - monitor->nonc1test0lngrep.n = n; - monitor->nonc1test0lngrep.cnt = sortedcnt; - monitor->nonc1test0lngrep.stpidxa = stpidx+1; - monitor->nonc1test0lngrep.stpidxb = stpidx+4; - rvectorsetlengthatleast(&monitor->nonc1test0lngrep.x0, n, _state); - rvectorsetlengthatleast(&monitor->nonc1test0lngrep.d, n, _state); - for(i=0; i<=n-1; i++) - { - monitor->nonc1test0lngrep.x0.ptr.p_double[i] = monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[0]*n+i]; - monitor->nonc1test0lngrep.d.ptr.p_double[i] = monitor->dcur.ptr.p_double[i]; - } - rvectorsetlengthatleast(&monitor->nonc1test0lngrep.stp, sortedcnt, _state); - rvectorsetlengthatleast(&monitor->nonc1test0lngrep.f, sortedcnt, _state); - for(i=0; i<=sortedcnt-1; i++) - { - monitor->nonc1test0lngrep.stp.ptr.p_double[i] = monitor->sortedstp.ptr.p_double[i]; - monitor->nonc1test0lngrep.f.ptr.p_double[i] = monitor->f.ptr.p_double[i]; - } - } - } -} - - -/************************************************************************* -This subroutine checks C1 continuity using test #1 (individual gradient -components from the line search log are studied for continuity). - -An interval between F[StpIdx+0] and F[StpIdx+3]is tested for continuity. -An normalized error metric (Lipschitz constant growth for the derivative) -for the interval in question is calculated. Values above 50 are a good -indication of the discontinuity. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -static void optserv_c1continuitytest1(smoothnessmonitor* monitor, - ae_int_t funcidx, - ae_int_t stpidx, - ae_int_t sortedcnt, - ae_state *_state) -{ - ae_int_t i; - ae_int_t varidx; - ae_int_t n; - double f0; - double f1; - double f2; - double f3; - double noise0; - double noise1; - double noise2; - double noise3; - double nrm; - double rating; - double lengthrating; - double lipschitz; - - - n = monitor->n; - ae_assert(stpidx+3sortedstp.ptr.p_double[0],(double)(0)), "C1ContinuityTest1: integrity check failed", _state); - ae_assert(ae_fp_greater(monitor->sortedstp.ptr.p_double[sortedcnt-1],(double)(0)), "C1ContinuityTest1: integrity check failed", _state); - - /* - * Study each component of the gradient in the interval in question - */ - for(varidx=0; varidx<=n-1; varidx++) - { - f0 = monitor->g.ptr.p_double[(stpidx+0)*n+varidx]; - f1 = monitor->g.ptr.p_double[(stpidx+1)*n+varidx]; - f2 = monitor->g.ptr.p_double[(stpidx+2)*n+varidx]; - f3 = monitor->g.ptr.p_double[(stpidx+3)*n+varidx]; - noise0 = optserv_ognoiselevelg*ae_maxreal(ae_fabs(f0, _state), 1.0, _state); - noise1 = optserv_ognoiselevelg*ae_maxreal(ae_fabs(f1, _state), 1.0, _state); - noise2 = optserv_ognoiselevelg*ae_maxreal(ae_fabs(f2, _state), 1.0, _state); - noise3 = optserv_ognoiselevelg*ae_maxreal(ae_fabs(f3, _state), 1.0, _state); - optserv_testc0continuity(f0, f1, f2, f3, noise0, noise1, noise2, noise3, monitor->sortedstp.ptr.p_double[stpidx+1]-monitor->sortedstp.ptr.p_double[stpidx+0], monitor->sortedstp.ptr.p_double[stpidx+2]-monitor->sortedstp.ptr.p_double[stpidx+1], monitor->sortedstp.ptr.p_double[stpidx+3]-monitor->sortedstp.ptr.p_double[stpidx+2], ae_false, &rating, &lipschitz, _state); - - /* - * Store results - */ - if( rating>optserv_ogminrating1 ) - { - - /* - * Store to total report - */ - monitor->rep.nonc1test1positive = ae_true; - if( rating>monitor->nonc1currentrating ) - { - monitor->nonc1currentrating = rating; - monitor->rep.nonc1suspected = ae_true; - monitor->rep.nonc1lipschitzc = lipschitz; - monitor->rep.nonc1fidx = funcidx; - } - - /* - * Store to "strongest" report - */ - if( rating>monitor->nonc1test1strrating ) - { - monitor->nonc1test1strrating = rating; - monitor->nonc1test1strrep.positive = ae_true; - monitor->nonc1test1strrep.fidx = funcidx; - monitor->nonc1test1strrep.vidx = varidx; - monitor->nonc1test1strrep.n = n; - monitor->nonc1test1strrep.cnt = sortedcnt; - monitor->nonc1test1strrep.stpidxa = stpidx+0; - monitor->nonc1test1strrep.stpidxb = stpidx+3; - rvectorsetlengthatleast(&monitor->nonc1test1strrep.x0, n, _state); - rvectorsetlengthatleast(&monitor->nonc1test1strrep.d, n, _state); - for(i=0; i<=n-1; i++) - { - monitor->nonc1test1strrep.x0.ptr.p_double[i] = monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[0]*n+i]; - monitor->nonc1test1strrep.d.ptr.p_double[i] = monitor->dcur.ptr.p_double[i]; - } - rvectorsetlengthatleast(&monitor->nonc1test1strrep.stp, sortedcnt, _state); - rvectorsetlengthatleast(&monitor->nonc1test1strrep.g, sortedcnt, _state); - for(i=0; i<=sortedcnt-1; i++) - { - monitor->nonc1test1strrep.stp.ptr.p_double[i] = monitor->sortedstp.ptr.p_double[i]; - monitor->nonc1test1strrep.g.ptr.p_double[i] = monitor->g.ptr.p_double[i*n+varidx]; - } - } - - /* - * Store to "longest" report - */ - nrm = (double)(0); - for(i=0; i<=n-1; i++) - { - nrm = nrm+ae_sqr(monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[0]*n+i]-monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[sortedcnt-1]*n+i], _state); - } - nrm = ae_sqrt(nrm, _state); - nrm = ae_minreal(nrm, 1.0, _state); - nrm = coalesce(nrm, ae_machineepsilon, _state); - lengthrating = sortedcnt+ae_log(nrm, _state)/ae_log((double)(100), _state); - if( lengthrating>monitor->nonc1test1lngrating ) - { - monitor->nonc1test1lngrating = lengthrating; - monitor->nonc1test1lngrep.positive = ae_true; - monitor->nonc1test1lngrep.fidx = funcidx; - monitor->nonc1test1lngrep.vidx = varidx; - monitor->nonc1test1lngrep.n = n; - monitor->nonc1test1lngrep.cnt = sortedcnt; - monitor->nonc1test1lngrep.stpidxa = stpidx+0; - monitor->nonc1test1lngrep.stpidxb = stpidx+3; - rvectorsetlengthatleast(&monitor->nonc1test1lngrep.x0, n, _state); - rvectorsetlengthatleast(&monitor->nonc1test1lngrep.d, n, _state); - for(i=0; i<=n-1; i++) - { - monitor->nonc1test1lngrep.x0.ptr.p_double[i] = monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[0]*n+i]; - monitor->nonc1test1lngrep.d.ptr.p_double[i] = monitor->dcur.ptr.p_double[i]; - } - rvectorsetlengthatleast(&monitor->nonc1test1lngrep.stp, sortedcnt, _state); - rvectorsetlengthatleast(&monitor->nonc1test1lngrep.g, sortedcnt, _state); - for(i=0; i<=sortedcnt-1; i++) - { - monitor->nonc1test1lngrep.stp.ptr.p_double[i] = monitor->sortedstp.ptr.p_double[i]; - monitor->nonc1test1lngrep.g.ptr.p_double[i] = monitor->g.ptr.p_double[i*n+varidx]; - } - } - } - } -} - - -void _precbuflbfgs_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - precbuflbfgs *p = (precbuflbfgs*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->norms, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->alpha, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rho, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->yk, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->idx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->bufa, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bufb, 0, DT_INT, _state, make_automatic); -} - - -void _precbuflbfgs_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - precbuflbfgs *dst = (precbuflbfgs*)_dst; - precbuflbfgs *src = (precbuflbfgs*)_src; - ae_vector_init_copy(&dst->norms, &src->norms, _state, make_automatic); - ae_vector_init_copy(&dst->alpha, &src->alpha, _state, make_automatic); - ae_vector_init_copy(&dst->rho, &src->rho, _state, make_automatic); - ae_matrix_init_copy(&dst->yk, &src->yk, _state, make_automatic); - ae_vector_init_copy(&dst->idx, &src->idx, _state, make_automatic); - ae_vector_init_copy(&dst->bufa, &src->bufa, _state, make_automatic); - ae_vector_init_copy(&dst->bufb, &src->bufb, _state, make_automatic); -} - - -void _precbuflbfgs_clear(void* _p) -{ - precbuflbfgs *p = (precbuflbfgs*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->norms); - ae_vector_clear(&p->alpha); - ae_vector_clear(&p->rho); - ae_matrix_clear(&p->yk); - ae_vector_clear(&p->idx); - ae_vector_clear(&p->bufa); - ae_vector_clear(&p->bufb); -} - - -void _precbuflbfgs_destroy(void* _p) -{ - precbuflbfgs *p = (precbuflbfgs*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->norms); - ae_vector_destroy(&p->alpha); - ae_vector_destroy(&p->rho); - ae_matrix_destroy(&p->yk); - ae_vector_destroy(&p->idx); - ae_vector_destroy(&p->bufa); - ae_vector_destroy(&p->bufb); -} - - -void _precbuflowrank_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - precbuflowrank *p = (precbuflowrank*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->v, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bufc, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->bufz, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->bufw, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp, 0, DT_REAL, _state, make_automatic); -} - - -void _precbuflowrank_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - precbuflowrank *dst = (precbuflowrank*)_dst; - precbuflowrank *src = (precbuflowrank*)_src; - dst->n = src->n; - dst->k = src->k; - ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic); - ae_matrix_init_copy(&dst->v, &src->v, _state, make_automatic); - ae_vector_init_copy(&dst->bufc, &src->bufc, _state, make_automatic); - ae_matrix_init_copy(&dst->bufz, &src->bufz, _state, make_automatic); - ae_matrix_init_copy(&dst->bufw, &src->bufw, _state, make_automatic); - ae_vector_init_copy(&dst->tmp, &src->tmp, _state, make_automatic); -} - - -void _precbuflowrank_clear(void* _p) -{ - precbuflowrank *p = (precbuflowrank*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->d); - ae_matrix_clear(&p->v); - ae_vector_clear(&p->bufc); - ae_matrix_clear(&p->bufz); - ae_matrix_clear(&p->bufw); - ae_vector_clear(&p->tmp); -} - - -void _precbuflowrank_destroy(void* _p) -{ - precbuflowrank *p = (precbuflowrank*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->d); - ae_matrix_destroy(&p->v); - ae_vector_destroy(&p->bufc); - ae_matrix_destroy(&p->bufz); - ae_matrix_destroy(&p->bufw); - ae_vector_destroy(&p->tmp); -} - - -void _smoothnessmonitor_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - smoothnessmonitor *p = (smoothnessmonitor*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dcur, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->enqueuedstp, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->enqueuedx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->enqueuedfunc, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->enqueuedjac, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->sortedstp, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->sortedidx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->probingf, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->probingsteps, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->probingvalues, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->probingslopes, 0, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->probingrcomm, _state, make_automatic); - _optguardreport_init(&p->rep, _state, make_automatic); - _optguardnonc0report_init(&p->nonc0strrep, _state, make_automatic); - _optguardnonc0report_init(&p->nonc0lngrep, _state, make_automatic); - _optguardnonc1test0report_init(&p->nonc1test0strrep, _state, make_automatic); - _optguardnonc1test0report_init(&p->nonc1test0lngrep, _state, make_automatic); - _optguardnonc1test1report_init(&p->nonc1test1strrep, _state, make_automatic); - _optguardnonc1test1report_init(&p->nonc1test1lngrep, _state, make_automatic); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fi, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->j, 0, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rstateg0, _state, make_automatic); - ae_vector_init(&p->xbase, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fbase, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fm, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fp, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->jm, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->jc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->jp, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->jbaseusr, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->jbasenum, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stp, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bufr, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->f, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->deltax, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpidx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->bufi, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->xu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->du, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->f0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->j0, 0, 0, DT_REAL, _state, make_automatic); -} - - -void _smoothnessmonitor_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - smoothnessmonitor *dst = (smoothnessmonitor*)_dst; - smoothnessmonitor *src = (smoothnessmonitor*)_src; - dst->n = src->n; - dst->k = src->k; - dst->checksmoothness = src->checksmoothness; - ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic); - ae_vector_init_copy(&dst->dcur, &src->dcur, _state, make_automatic); - dst->enqueuedcnt = src->enqueuedcnt; - ae_vector_init_copy(&dst->enqueuedstp, &src->enqueuedstp, _state, make_automatic); - ae_vector_init_copy(&dst->enqueuedx, &src->enqueuedx, _state, make_automatic); - ae_vector_init_copy(&dst->enqueuedfunc, &src->enqueuedfunc, _state, make_automatic); - ae_matrix_init_copy(&dst->enqueuedjac, &src->enqueuedjac, _state, make_automatic); - ae_vector_init_copy(&dst->sortedstp, &src->sortedstp, _state, make_automatic); - ae_vector_init_copy(&dst->sortedidx, &src->sortedidx, _state, make_automatic); - dst->sortedcnt = src->sortedcnt; - dst->probingstp = src->probingstp; - ae_vector_init_copy(&dst->probingf, &src->probingf, _state, make_automatic); - dst->probingnvalues = src->probingnvalues; - dst->probingstepmax = src->probingstepmax; - dst->probingstepscale = src->probingstepscale; - dst->probingnstepsstored = src->probingnstepsstored; - ae_vector_init_copy(&dst->probingsteps, &src->probingsteps, _state, make_automatic); - ae_matrix_init_copy(&dst->probingvalues, &src->probingvalues, _state, make_automatic); - ae_matrix_init_copy(&dst->probingslopes, &src->probingslopes, _state, make_automatic); - _rcommstate_init_copy(&dst->probingrcomm, &src->probingrcomm, _state, make_automatic); - dst->linesearchspoiled = src->linesearchspoiled; - dst->linesearchstarted = src->linesearchstarted; - dst->nonc0currentrating = src->nonc0currentrating; - dst->nonc1currentrating = src->nonc1currentrating; - dst->badgradhasxj = src->badgradhasxj; - _optguardreport_init_copy(&dst->rep, &src->rep, _state, make_automatic); - dst->nonc0strrating = src->nonc0strrating; - dst->nonc0lngrating = src->nonc0lngrating; - _optguardnonc0report_init_copy(&dst->nonc0strrep, &src->nonc0strrep, _state, make_automatic); - _optguardnonc0report_init_copy(&dst->nonc0lngrep, &src->nonc0lngrep, _state, make_automatic); - dst->nonc1test0strrating = src->nonc1test0strrating; - dst->nonc1test0lngrating = src->nonc1test0lngrating; - _optguardnonc1test0report_init_copy(&dst->nonc1test0strrep, &src->nonc1test0strrep, _state, make_automatic); - _optguardnonc1test0report_init_copy(&dst->nonc1test0lngrep, &src->nonc1test0lngrep, _state, make_automatic); - dst->nonc1test1strrating = src->nonc1test1strrating; - dst->nonc1test1lngrating = src->nonc1test1lngrating; - _optguardnonc1test1report_init_copy(&dst->nonc1test1strrep, &src->nonc1test1strrep, _state, make_automatic); - _optguardnonc1test1report_init_copy(&dst->nonc1test1lngrep, &src->nonc1test1lngrep, _state, make_automatic); - dst->needfij = src->needfij; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->fi, &src->fi, _state, make_automatic); - ae_matrix_init_copy(&dst->j, &src->j, _state, make_automatic); - _rcommstate_init_copy(&dst->rstateg0, &src->rstateg0, _state, make_automatic); - ae_vector_init_copy(&dst->xbase, &src->xbase, _state, make_automatic); - ae_vector_init_copy(&dst->fbase, &src->fbase, _state, make_automatic); - ae_vector_init_copy(&dst->fm, &src->fm, _state, make_automatic); - ae_vector_init_copy(&dst->fc, &src->fc, _state, make_automatic); - ae_vector_init_copy(&dst->fp, &src->fp, _state, make_automatic); - ae_vector_init_copy(&dst->jm, &src->jm, _state, make_automatic); - ae_vector_init_copy(&dst->jc, &src->jc, _state, make_automatic); - ae_vector_init_copy(&dst->jp, &src->jp, _state, make_automatic); - ae_matrix_init_copy(&dst->jbaseusr, &src->jbaseusr, _state, make_automatic); - ae_matrix_init_copy(&dst->jbasenum, &src->jbasenum, _state, make_automatic); - ae_vector_init_copy(&dst->stp, &src->stp, _state, make_automatic); - ae_vector_init_copy(&dst->bufr, &src->bufr, _state, make_automatic); - ae_vector_init_copy(&dst->f, &src->f, _state, make_automatic); - ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic); - ae_vector_init_copy(&dst->deltax, &src->deltax, _state, make_automatic); - ae_vector_init_copy(&dst->tmpidx, &src->tmpidx, _state, make_automatic); - ae_vector_init_copy(&dst->bufi, &src->bufi, _state, make_automatic); - ae_vector_init_copy(&dst->xu, &src->xu, _state, make_automatic); - ae_vector_init_copy(&dst->du, &src->du, _state, make_automatic); - ae_vector_init_copy(&dst->f0, &src->f0, _state, make_automatic); - ae_matrix_init_copy(&dst->j0, &src->j0, _state, make_automatic); -} - - -void _smoothnessmonitor_clear(void* _p) -{ - smoothnessmonitor *p = (smoothnessmonitor*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->s); - ae_vector_clear(&p->dcur); - ae_vector_clear(&p->enqueuedstp); - ae_vector_clear(&p->enqueuedx); - ae_vector_clear(&p->enqueuedfunc); - ae_matrix_clear(&p->enqueuedjac); - ae_vector_clear(&p->sortedstp); - ae_vector_clear(&p->sortedidx); - ae_vector_clear(&p->probingf); - ae_vector_clear(&p->probingsteps); - ae_matrix_clear(&p->probingvalues); - ae_matrix_clear(&p->probingslopes); - _rcommstate_clear(&p->probingrcomm); - _optguardreport_clear(&p->rep); - _optguardnonc0report_clear(&p->nonc0strrep); - _optguardnonc0report_clear(&p->nonc0lngrep); - _optguardnonc1test0report_clear(&p->nonc1test0strrep); - _optguardnonc1test0report_clear(&p->nonc1test0lngrep); - _optguardnonc1test1report_clear(&p->nonc1test1strrep); - _optguardnonc1test1report_clear(&p->nonc1test1lngrep); - ae_vector_clear(&p->x); - ae_vector_clear(&p->fi); - ae_matrix_clear(&p->j); - _rcommstate_clear(&p->rstateg0); - ae_vector_clear(&p->xbase); - ae_vector_clear(&p->fbase); - ae_vector_clear(&p->fm); - ae_vector_clear(&p->fc); - ae_vector_clear(&p->fp); - ae_vector_clear(&p->jm); - ae_vector_clear(&p->jc); - ae_vector_clear(&p->jp); - ae_matrix_clear(&p->jbaseusr); - ae_matrix_clear(&p->jbasenum); - ae_vector_clear(&p->stp); - ae_vector_clear(&p->bufr); - ae_vector_clear(&p->f); - ae_vector_clear(&p->g); - ae_vector_clear(&p->deltax); - ae_vector_clear(&p->tmpidx); - ae_vector_clear(&p->bufi); - ae_vector_clear(&p->xu); - ae_vector_clear(&p->du); - ae_vector_clear(&p->f0); - ae_matrix_clear(&p->j0); -} - - -void _smoothnessmonitor_destroy(void* _p) -{ - smoothnessmonitor *p = (smoothnessmonitor*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->s); - ae_vector_destroy(&p->dcur); - ae_vector_destroy(&p->enqueuedstp); - ae_vector_destroy(&p->enqueuedx); - ae_vector_destroy(&p->enqueuedfunc); - ae_matrix_destroy(&p->enqueuedjac); - ae_vector_destroy(&p->sortedstp); - ae_vector_destroy(&p->sortedidx); - ae_vector_destroy(&p->probingf); - ae_vector_destroy(&p->probingsteps); - ae_matrix_destroy(&p->probingvalues); - ae_matrix_destroy(&p->probingslopes); - _rcommstate_destroy(&p->probingrcomm); - _optguardreport_destroy(&p->rep); - _optguardnonc0report_destroy(&p->nonc0strrep); - _optguardnonc0report_destroy(&p->nonc0lngrep); - _optguardnonc1test0report_destroy(&p->nonc1test0strrep); - _optguardnonc1test0report_destroy(&p->nonc1test0lngrep); - _optguardnonc1test1report_destroy(&p->nonc1test1strrep); - _optguardnonc1test1report_destroy(&p->nonc1test1lngrep); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->fi); - ae_matrix_destroy(&p->j); - _rcommstate_destroy(&p->rstateg0); - ae_vector_destroy(&p->xbase); - ae_vector_destroy(&p->fbase); - ae_vector_destroy(&p->fm); - ae_vector_destroy(&p->fc); - ae_vector_destroy(&p->fp); - ae_vector_destroy(&p->jm); - ae_vector_destroy(&p->jc); - ae_vector_destroy(&p->jp); - ae_matrix_destroy(&p->jbaseusr); - ae_matrix_destroy(&p->jbasenum); - ae_vector_destroy(&p->stp); - ae_vector_destroy(&p->bufr); - ae_vector_destroy(&p->f); - ae_vector_destroy(&p->g); - ae_vector_destroy(&p->deltax); - ae_vector_destroy(&p->tmpidx); - ae_vector_destroy(&p->bufi); - ae_vector_destroy(&p->xu); - ae_vector_destroy(&p->du); - ae_vector_destroy(&p->f0); - ae_matrix_destroy(&p->j0); -} - - -#endif -#if defined(AE_COMPILE_SNNLS) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This subroutine is used to initialize SNNLS solver. - -By default, empty NNLS problem is produced, but we allocated enough space -to store problems with NSMax+NDMax columns and NRMax rows. It is good -place to provide algorithm with initial estimate of the space requirements, -although you may underestimate problem size or even pass zero estimates - -in this case buffer variables will be resized automatically when you set -NNLS problem. - -Previously allocated buffer variables are reused as much as possible. This -function does not clear structure completely, it tries to preserve as much -dynamically allocated memory as possible. - - -- ALGLIB -- - Copyright 10.10.2012 by Bochkanov Sergey -*************************************************************************/ -void snnlsinit(ae_int_t nsmax, - ae_int_t ndmax, - ae_int_t nrmax, - snnlssolver* s, - ae_state *_state) -{ - - - s->ns = 0; - s->nd = 0; - s->nr = 0; - rmatrixsetlengthatleast(&s->densea, nrmax, ndmax, _state); - rmatrixsetlengthatleast(&s->tmpca, nrmax, ndmax, _state); - rvectorsetlengthatleast(&s->b, nrmax, _state); - bvectorsetlengthatleast(&s->nnc, nsmax+ndmax, _state); - s->debugflops = 0.0; - s->debugmaxinnerits = 0; -} - - -/************************************************************************* -This subroutine is used to set NNLS problem: - - ( [ 1 | ] [ ] [ ] )^2 - ( [ 1 | ] [ ] [ ] ) - min ( [ 1 | Ad ] * [ x ] - [ b ] ) s.t. x>=0 - ( [ | ] [ ] [ ] ) - ( [ | ] [ ] [ ] ) - -where: -* identity matrix has NS*NS size (NS<=NR, NS can be zero) -* dense matrix Ad has NR*ND size -* b is NR*1 vector -* x is (NS+ND)*1 vector -* all elements of x are non-negative (this constraint can be removed later - by calling SNNLSDropNNC() function) - -Previously allocated buffer variables are reused as much as possible. -After you set problem, you can solve it with SNNLSSolve(). - -INPUT PARAMETERS: - S - SNNLS solver, must be initialized with SNNLSInit() call - A - array[NR,ND], dense part of the system - B - array[NR], right part - NS - size of the sparse part of the system, 0<=NS<=NR - ND - size of the dense part of the system, ND>=0 - NR - rows count, NR>0 - -NOTE: - 1. You can have NS+ND=0, solver will correctly accept such combination - and return empty array as problem solution. - - -- ALGLIB -- - Copyright 10.10.2012 by Bochkanov Sergey -*************************************************************************/ -void snnlssetproblem(snnlssolver* s, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* b, - ae_int_t ns, - ae_int_t nd, - ae_int_t nr, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(nd>=0, "SNNLSSetProblem: ND<0", _state); - ae_assert(ns>=0, "SNNLSSetProblem: NS<0", _state); - ae_assert(nr>0, "SNNLSSetProblem: NR<=0", _state); - ae_assert(ns<=nr, "SNNLSSetProblem: NS>NR", _state); - ae_assert(a->rows>=nr||nd==0, "SNNLSSetProblem: rows(A)cols>=nd, "SNNLSSetProblem: cols(A)cnt>=nr, "SNNLSSetProblem: length(B)ns = ns; - s->nd = nd; - s->nr = nr; - if( nd>0 ) - { - rmatrixsetlengthatleast(&s->densea, nr, nd, _state); - for(i=0; i<=nr-1; i++) - { - ae_v_move(&s->densea.ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,nd-1)); - } - } - rvectorsetlengthatleast(&s->b, nr, _state); - ae_v_move(&s->b.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,nr-1)); - bvectorsetlengthatleast(&s->nnc, ns+nd, _state); - for(i=0; i<=ns+nd-1; i++) - { - s->nnc.ptr.p_bool[i] = ae_true; - } -} - - -/************************************************************************* -This subroutine drops non-negativity constraint from the problem set by -SNNLSSetProblem() call. This function must be called AFTER problem is set, -because each SetProblem() call resets constraints to their default state -(all constraints are present). - -INPUT PARAMETERS: - S - SNNLS solver, must be initialized with SNNLSInit() call, - problem must be set with SNNLSSetProblem() call. - Idx - constraint index, 0<=IDX=0, "SNNLSDropNNC: Idx<0", _state); - ae_assert(idxns+s->nd, "SNNLSDropNNC: Idx>=NS+ND", _state); - s->nnc.ptr.p_bool[idx] = ae_false; -} - - -/************************************************************************* -This subroutine is used to solve NNLS problem. - -INPUT PARAMETERS: - S - SNNLS solver, must be initialized with SNNLSInit() call and - problem must be set up with SNNLSSetProblem() call. - X - possibly preallocated buffer, automatically resized if needed - -OUTPUT PARAMETERS: - X - array[NS+ND], solution - -NOTE: - 1. You can have NS+ND=0, solver will correctly accept such combination - and return empty array as problem solution. - - 2. Internal field S.DebugFLOPS contains rough estimate of FLOPs used - to solve problem. It can be used for debugging purposes. This field - is real-valued. - - -- ALGLIB -- - Copyright 10.10.2012 by Bochkanov Sergey -*************************************************************************/ -void snnlssolve(snnlssolver* s, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t i; - ae_int_t ns; - ae_int_t nd; - ae_int_t nr; - ae_bool wasactivation; - double lambdav; - double v0; - double v1; - double v; - ae_int_t outerits; - ae_int_t innerits; - ae_int_t maxouterits; - double xtol; - double kicklength; - ae_bool kickneeded; - double f0; - double f1; - double dnrm; - ae_int_t actidx; - double stp; - double stpmax; - - - - /* - * Prepare - */ - ns = s->ns; - nd = s->nd; - nr = s->nr; - s->debugflops = 0.0; - - /* - * Handle special cases: - * * NS+ND=0 - * * ND=0 - */ - if( ns+nd==0 ) - { - return; - } - if( nd==0 ) - { - rvectorsetlengthatleast(x, ns, _state); - for(i=0; i<=ns-1; i++) - { - x->ptr.p_double[i] = s->b.ptr.p_double[i]; - if( s->nnc.ptr.p_bool[i] ) - { - x->ptr.p_double[i] = ae_maxreal(x->ptr.p_double[i], 0.0, _state); - } - } - return; - } - - /* - * Main cycle of BLEIC-SNNLS algorithm. - * Below we assume that ND>0. - */ - rvectorsetlengthatleast(x, ns+nd, _state); - rvectorsetlengthatleast(&s->xn, ns+nd, _state); - rvectorsetlengthatleast(&s->xp, ns+nd, _state); - rvectorsetlengthatleast(&s->g, ns+nd, _state); - rvectorsetlengthatleast(&s->d, ns+nd, _state); - rvectorsetlengthatleast(&s->r, nr, _state); - rvectorsetlengthatleast(&s->diagaa, nd, _state); - rvectorsetlengthatleast(&s->regdiag, ns+nd, _state); - rvectorsetlengthatleast(&s->dx, ns+nd, _state); - for(i=0; i<=ns+nd-1; i++) - { - x->ptr.p_double[i] = 0.0; - s->regdiag.ptr.p_double[i] = 1.0; - } - lambdav = 1.0E6*ae_machineepsilon; - maxouterits = 10; - outerits = 0; - innerits = 0; - xtol = 1.0E3*ae_machineepsilon; - kicklength = ae_sqrt(ae_minrealnumber, _state); - for(;;) - { - - /* - * Initial check for correctness of X - */ - for(i=0; i<=ns+nd-1; i++) - { - ae_assert(!s->nnc.ptr.p_bool[i]||ae_fp_greater_eq(x->ptr.p_double[i],(double)(0)), "SNNLS: integrity check failed", _state); - } - - /* - * Calculate gradient G and constrained descent direction D - */ - snnls_funcgradu(s, x, &s->r, &s->g, &f0, _state); - for(i=0; i<=ns+nd-1; i++) - { - if( (s->nnc.ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],(double)(0)))&&ae_fp_greater(s->g.ptr.p_double[i],(double)(0)) ) - { - s->d.ptr.p_double[i] = 0.0; - } - else - { - s->d.ptr.p_double[i] = -s->g.ptr.p_double[i]; - } - } - - /* - * Decide whether we need "kick" stage: special stage - * that moves us away from boundary constraints which are - * not strictly active (i.e. such constraints that x[i]=0.0 and d[i]>0). - * - * If we need kick stage, we make a kick - and restart iteration. - * If not, after this block we can rely on the fact that - * for all x[i]=0.0 we have d[i]=0.0 - * - * NOTE: we do not increase outer iterations counter here - */ - kickneeded = ae_false; - for(i=0; i<=ns+nd-1; i++) - { - if( (s->nnc.ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],0.0))&&ae_fp_greater(s->d.ptr.p_double[i],0.0) ) - { - kickneeded = ae_true; - } - } - if( kickneeded ) - { - - /* - * Perform kick. - * Restart. - * Do not increase iterations counter. - */ - for(i=0; i<=ns+nd-1; i++) - { - if( ae_fp_eq(x->ptr.p_double[i],0.0)&&ae_fp_greater(s->d.ptr.p_double[i],0.0) ) - { - x->ptr.p_double[i] = x->ptr.p_double[i]+kicklength; - } - } - continue; - } - - /* - * Newton phase - * Reduce problem to constrained triangular form and perform Newton - * steps with quick activation of constrants (triangular form is - * updated in order to handle changed constraints). - */ - for(i=0; i<=ns+nd-1; i++) - { - s->xp.ptr.p_double[i] = x->ptr.p_double[i]; - } - snnls_trdprepare(s, x, &s->regdiag, lambdav, &s->trdd, &s->trda, &s->tmp0, &s->tmp1, &s->tmp2, &s->tmplq, _state); - for(;;) - { - - /* - * Skip if debug limit on inner iterations count is turned on. - */ - if( s->debugmaxinnerits>0&&innerits>=s->debugmaxinnerits ) - { - break; - } - - /* - * Prepare step vector. - */ - snnls_funcgradu(s, x, &s->r, &s->g, &f0, _state); - for(i=0; i<=ns+nd-1; i++) - { - s->d.ptr.p_double[i] = -s->g.ptr.p_double[i]; - if( s->nnc.ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],0.0) ) - { - s->d.ptr.p_double[i] = 0.0; - } - } - snnls_trdsolve(&s->trdd, &s->trda, ns, nd, &s->d, _state); - - /* - * Perform unconstrained trial step and compare function values. - */ - for(i=0; i<=ns+nd-1; i++) - { - s->xn.ptr.p_double[i] = x->ptr.p_double[i]+s->d.ptr.p_double[i]; - } - snnls_func(s, &s->xn, &f1, _state); - if( ae_fp_greater_eq(f1,f0) ) - { - break; - } - - /* - * Calculate length of D, maximum step and component which is - * activated by this step. Break if D is exactly zero. - */ - dnrm = 0.0; - for(i=0; i<=ns+nd-1; i++) - { - dnrm = dnrm+ae_sqr(s->d.ptr.p_double[i], _state); - } - dnrm = ae_sqrt(dnrm, _state); - actidx = -1; - stpmax = 1.0E50; - for(i=0; i<=ns+nd-1; i++) - { - if( s->nnc.ptr.p_bool[i]&&ae_fp_less(s->d.ptr.p_double[i],0.0) ) - { - v = stpmax; - stpmax = safeminposrv(x->ptr.p_double[i], -s->d.ptr.p_double[i], stpmax, _state); - if( ae_fp_less(stpmax,v) ) - { - actidx = i; - } - } - } - if( ae_fp_eq(dnrm,0.0) ) - { - break; - } - - /* - * Perform constrained step and update X - * and triangular model. - */ - stp = ae_minreal(1.0, stpmax, _state); - for(i=0; i<=ns+nd-1; i++) - { - v = x->ptr.p_double[i]+stp*s->d.ptr.p_double[i]; - if( s->nnc.ptr.p_bool[i] ) - { - v = ae_maxreal(v, 0.0, _state); - } - s->xn.ptr.p_double[i] = v; - } - if( ae_fp_eq(stp,stpmax)&&actidx>=0 ) - { - s->xn.ptr.p_double[actidx] = 0.0; - } - wasactivation = ae_false; - for(i=0; i<=ns+nd-1; i++) - { - if( ae_fp_eq(s->xn.ptr.p_double[i],0.0)&&ae_fp_neq(x->ptr.p_double[i],0.0) ) - { - wasactivation = ae_true; - snnls_trdfixvariable(&s->trdd, &s->trda, ns, nd, i, &s->tmpcholesky, _state); - } - } - for(i=0; i<=ns+nd-1; i++) - { - x->ptr.p_double[i] = s->xn.ptr.p_double[i]; - } - - /* - * Increment iterations counter. - * Terminate if no constraint was activated. - */ - inc(&innerits, _state); - if( !wasactivation ) - { - break; - } - } - - /* - * Update outer iterations counter. - * - * Break if necessary: - * * maximum number of outer iterations performed - * * relative change in X is small enough - */ - inc(&outerits, _state); - if( outerits>=maxouterits ) - { - break; - } - v = (double)(0); - for(i=0; i<=ns+nd-1; i++) - { - v0 = ae_fabs(s->xp.ptr.p_double[i], _state); - v1 = ae_fabs(x->ptr.p_double[i], _state); - if( ae_fp_neq(v0,(double)(0))||ae_fp_neq(v1,(double)(0)) ) - { - v = ae_maxreal(v, ae_fabs(x->ptr.p_double[i]-s->xp.ptr.p_double[i], _state)/ae_maxreal(v0, v1, _state), _state); - } - } - if( ae_fp_less_eq(v,xtol) ) - { - break; - } - } -} - - -/************************************************************************* -This function calculates: -* residual vector R = A*x-b -* unconstrained gradient vector G -* function value F = 0.5*|R|^2 - -R and G must have at least N elements. - - -- ALGLIB -- - Copyright 15.07.2015 by Bochkanov Sergey -*************************************************************************/ -static void snnls_funcgradu(snnlssolver* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* r, - /* Real */ ae_vector* g, - double* f, - ae_state *_state) -{ - ae_int_t i; - ae_int_t nr; - ae_int_t nd; - ae_int_t ns; - double v; - - *f = 0; - - nr = s->nr; - nd = s->nd; - ns = s->ns; - *f = 0.0; - for(i=0; i<=nr-1; i++) - { - v = ae_v_dotproduct(&s->densea.ptr.pp_double[i][0], 1, &x->ptr.p_double[ns], 1, ae_v_len(0,nd-1)); - if( iptr.p_double[i]; - } - v = v-s->b.ptr.p_double[i]; - r->ptr.p_double[i] = v; - *f = *f+0.5*v*v; - } - for(i=0; i<=ns-1; i++) - { - g->ptr.p_double[i] = r->ptr.p_double[i]; - } - for(i=ns; i<=ns+nd-1; i++) - { - g->ptr.p_double[i] = 0.0; - } - for(i=0; i<=nr-1; i++) - { - v = r->ptr.p_double[i]; - ae_v_addd(&g->ptr.p_double[ns], 1, &s->densea.ptr.pp_double[i][0], 1, ae_v_len(ns,ns+nd-1), v); - } -} - - -/************************************************************************* -This function calculates function value F = 0.5*|R|^2 at X. - - -- ALGLIB -- - Copyright 15.07.2015 by Bochkanov Sergey -*************************************************************************/ -static void snnls_func(snnlssolver* s, - /* Real */ ae_vector* x, - double* f, - ae_state *_state) -{ - ae_int_t i; - ae_int_t nr; - ae_int_t nd; - ae_int_t ns; - double v; - - *f = 0; - - nr = s->nr; - nd = s->nd; - ns = s->ns; - *f = 0.0; - for(i=0; i<=nr-1; i++) - { - v = ae_v_dotproduct(&s->densea.ptr.pp_double[i][0], 1, &x->ptr.p_double[ns], 1, ae_v_len(0,nd-1)); - if( iptr.p_double[i]; - } - v = v-s->b.ptr.p_double[i]; - *f = *f+0.5*v*v; - } -} - - -static void snnls_trdprepare(snnlssolver* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* diag, - double lambdav, - /* Real */ ae_vector* trdd, - /* Real */ ae_matrix* trda, - /* Real */ ae_vector* tmp0, - /* Real */ ae_vector* tmp1, - /* Real */ ae_vector* tmp2, - /* Real */ ae_matrix* tmplq, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t ns; - ae_int_t nd; - ae_int_t nr; - double v; - double cs; - double sn; - double r; - - - - /* - * Prepare - */ - ns = s->ns; - nd = s->nd; - nr = s->nr; - - /* - * Triangular reduction - */ - rvectorsetlengthatleast(trdd, ns, _state); - rmatrixsetlengthatleast(trda, ns+nd, nd, _state); - rmatrixsetlengthatleast(tmplq, nd, nr+nd, _state); - for(i=0; i<=ns-1; i++) - { - - /* - * Apply rotation to I-th row and corresponding row of - * regularizer. Here V is diagonal element of I-th row, - * which is set to 1.0 or 0.0 depending on variable - * status (constrained or not). - */ - v = 1.0; - if( s->nnc.ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],0.0) ) - { - v = 0.0; - } - generaterotation(v, lambdav, &cs, &sn, &r, _state); - trdd->ptr.p_double[i] = cs*v+sn*lambdav; - for(j=0; j<=nd-1; j++) - { - v = s->densea.ptr.pp_double[i][j]; - trda->ptr.pp_double[i][j] = cs*v; - tmplq->ptr.pp_double[j][i] = -sn*v; - } - } - for(j=0; j<=nd-1; j++) - { - for(i=ns; i<=nr-1; i++) - { - tmplq->ptr.pp_double[j][i] = s->densea.ptr.pp_double[i][j]; - } - } - for(j=0; j<=nd-1; j++) - { - if( s->nnc.ptr.p_bool[ns+j]&&ae_fp_eq(x->ptr.p_double[ns+j],0.0) ) - { - - /* - * Variable is constrained, entire row is set to zero. - */ - for(i=0; i<=nr-1; i++) - { - tmplq->ptr.pp_double[j][i] = 0.0; - } - for(i=0; i<=ns-1; i++) - { - trda->ptr.pp_double[i][j] = 0.0; - } - } - } - for(i=0; i<=nd-1; i++) - { - for(j=0; j<=nd-1; j++) - { - tmplq->ptr.pp_double[j][nr+i] = 0.0; - } - tmplq->ptr.pp_double[i][nr+i] = lambdav*diag->ptr.p_double[i]; - } - rvectorsetlengthatleast(tmp0, nr+nd+1, _state); - rvectorsetlengthatleast(tmp1, nr+nd+1, _state); - rvectorsetlengthatleast(tmp2, nr+nd+1, _state); - rmatrixlqbasecase(tmplq, nd, nr+nd, tmp0, tmp1, tmp2, _state); - for(i=0; i<=nd-1; i++) - { - if( ae_fp_less(tmplq->ptr.pp_double[i][i],0.0) ) - { - for(j=i; j<=nd-1; j++) - { - tmplq->ptr.pp_double[j][i] = -tmplq->ptr.pp_double[j][i]; - } - } - } - for(i=0; i<=nd-1; i++) - { - for(j=0; j<=i; j++) - { - trda->ptr.pp_double[ns+j][i] = tmplq->ptr.pp_double[i][j]; - } - } -} - - -static void snnls_trdsolve(/* Real */ ae_vector* trdd, - /* Real */ ae_matrix* trda, - ae_int_t ns, - ae_int_t nd, - /* Real */ ae_vector* d, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - - - - /* - * Solve U'*y=d first. - * - * This section includes two parts: - * * solve diagonal part of U' - * * solve dense part of U' - */ - for(i=0; i<=ns-1; i++) - { - d->ptr.p_double[i] = d->ptr.p_double[i]/trdd->ptr.p_double[i]; - v = d->ptr.p_double[i]; - for(j=0; j<=nd-1; j++) - { - d->ptr.p_double[ns+j] = d->ptr.p_double[ns+j]-v*trda->ptr.pp_double[i][j]; - } - } - for(i=0; i<=nd-1; i++) - { - d->ptr.p_double[ns+i] = d->ptr.p_double[ns+i]/trda->ptr.pp_double[ns+i][i]; - v = d->ptr.p_double[ns+i]; - for(j=i+1; j<=nd-1; j++) - { - d->ptr.p_double[ns+j] = d->ptr.p_double[ns+j]-v*trda->ptr.pp_double[ns+i][j]; - } - } - - /* - * Solve U*x=y then. - * - * This section includes two parts: - * * solve trailing triangular part of U - * * solve combination of diagonal and dense parts of U - */ - for(i=nd-1; i>=0; i--) - { - v = 0.0; - for(j=i+1; j<=nd-1; j++) - { - v = v+trda->ptr.pp_double[ns+i][j]*d->ptr.p_double[ns+j]; - } - d->ptr.p_double[ns+i] = (d->ptr.p_double[ns+i]-v)/trda->ptr.pp_double[ns+i][i]; - } - for(i=ns-1; i>=0; i--) - { - v = 0.0; - for(j=0; j<=nd-1; j++) - { - v = v+trda->ptr.pp_double[i][j]*d->ptr.p_double[ns+j]; - } - d->ptr.p_double[i] = (d->ptr.p_double[i]-v)/trdd->ptr.p_double[i]; - } -} - - -static void snnls_trdfixvariable(/* Real */ ae_vector* trdd, - /* Real */ ae_matrix* trda, - ae_int_t ns, - ae_int_t nd, - ae_int_t idx, - /* Real */ ae_vector* tmp, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double cs; - double sn; - double r; - double v; - double vv; - - - ae_assert(ns>=0, "TRDFixVariable: integrity error", _state); - ae_assert(nd>=0, "TRDFixVariable: integrity error", _state); - ae_assert(ns+nd>0, "TRDFixVariable: integrity error", _state); - ae_assert(idx>=0, "TRDFixVariable: integrity error", _state); - ae_assert(idxptr.p_double[idx] = 1.0; - return; - } - for(j=0; j<=nd-1; j++) - { - - /* - * Apply first rotation - */ - tmp->ptr.p_double[j] = trda->ptr.pp_double[idx][j]; - trda->ptr.pp_double[idx][j] = 0.0; - } - trdd->ptr.p_double[idx] = 1.0; - for(i=0; i<=nd-1; i++) - { - if( ae_fp_neq(tmp->ptr.p_double[i],(double)(0)) ) - { - - /* - * Apply subsequent rotations with bottom triangular part of A - */ - generaterotation(trda->ptr.pp_double[ns+i][i], tmp->ptr.p_double[i], &cs, &sn, &r, _state); - for(j=i; j<=nd-1; j++) - { - v = trda->ptr.pp_double[ns+i][j]; - vv = tmp->ptr.p_double[j]; - trda->ptr.pp_double[ns+i][j] = v*cs+vv*sn; - tmp->ptr.p_double[j] = vv*cs-v*sn; - } - } - } - } - else - { - - /* - * We fix variable in the dense part of the model. It means - * that prior to fixing we have: - * - * ( | ) - * ( D | ) - * ( | ) - * (-----| A ) - * ( |0 ) - * ( |00 ) - * ( |000 ) - * ( |0000 ) - * ( |00000) - * - * then we replace idx-th column by zeros: - * - * ( | 0 ) - * ( D | 0 ) - * ( | 0 ) - * (-----|A 0 A) - * ( | 0 ) - * ( | 0 ) - * ( | 0 ) - * - * and append row with unit element to bottom, in order to - * regularize problem - * - * ( | 0 ) - * ( D | 0 ) - * ( | 0 ) - * (-----|A 0 A) - * ( | 0 ) - * ( | 0 ) - * ( | 0 ) - * (00000|00100) <- appended - * - * and then we nullify this row by applying rotations: - * - * (D 0 | ) - * ( 0 | ) - * ( 0 D| ) - * (-----| A ) - * ( | ) - * ( | ) <- first rotation is applied here - * ( | ) <- subsequent rotations are applied to rows below - * ( 0 | 0 ) <- as result, row becomes zero - * - * and triangular structure is preserved. - */ - k = idx-ns; - for(i=0; i<=ns+nd-1; i++) - { - trda->ptr.pp_double[i][k] = 0.0; - } - for(j=k+1; j<=nd-1; j++) - { - - /* - * Apply first rotation - */ - tmp->ptr.p_double[j] = trda->ptr.pp_double[idx][j]; - trda->ptr.pp_double[idx][j] = 0.0; - } - trda->ptr.pp_double[idx][k] = 1.0; - for(i=k+1; i<=nd-1; i++) - { - if( ae_fp_neq(tmp->ptr.p_double[i],(double)(0)) ) - { - - /* - * Apply subsequent rotations with bottom triangular part of A - */ - generaterotation(trda->ptr.pp_double[ns+i][i], tmp->ptr.p_double[i], &cs, &sn, &r, _state); - for(j=i; j<=nd-1; j++) - { - v = trda->ptr.pp_double[ns+i][j]; - vv = tmp->ptr.p_double[j]; - trda->ptr.pp_double[ns+i][j] = v*cs+vv*sn; - tmp->ptr.p_double[j] = vv*cs-v*sn; - } - } - } - } -} - - -void _snnlssolver_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - snnlssolver *p = (snnlssolver*)_p; - ae_touch_ptr((void*)p); - ae_matrix_init(&p->densea, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->b, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->nnc, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->xn, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xp, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->tmpca, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->tmplq, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->trda, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->trdd, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->crb, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->diagaa, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cb, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cborg, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpcholesky, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->r, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->regdiag, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp2, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rdtmprowmap, 0, DT_INT, _state, make_automatic); -} - - -void _snnlssolver_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - snnlssolver *dst = (snnlssolver*)_dst; - snnlssolver *src = (snnlssolver*)_src; - dst->ns = src->ns; - dst->nd = src->nd; - dst->nr = src->nr; - ae_matrix_init_copy(&dst->densea, &src->densea, _state, make_automatic); - ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic); - ae_vector_init_copy(&dst->nnc, &src->nnc, _state, make_automatic); - dst->debugflops = src->debugflops; - dst->debugmaxinnerits = src->debugmaxinnerits; - ae_vector_init_copy(&dst->xn, &src->xn, _state, make_automatic); - ae_vector_init_copy(&dst->xp, &src->xp, _state, make_automatic); - ae_matrix_init_copy(&dst->tmpca, &src->tmpca, _state, make_automatic); - ae_matrix_init_copy(&dst->tmplq, &src->tmplq, _state, make_automatic); - ae_matrix_init_copy(&dst->trda, &src->trda, _state, make_automatic); - ae_vector_init_copy(&dst->trdd, &src->trdd, _state, make_automatic); - ae_vector_init_copy(&dst->crb, &src->crb, _state, make_automatic); - ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic); - ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic); - ae_vector_init_copy(&dst->dx, &src->dx, _state, make_automatic); - ae_vector_init_copy(&dst->diagaa, &src->diagaa, _state, make_automatic); - ae_vector_init_copy(&dst->cb, &src->cb, _state, make_automatic); - ae_vector_init_copy(&dst->cx, &src->cx, _state, make_automatic); - ae_vector_init_copy(&dst->cborg, &src->cborg, _state, make_automatic); - ae_vector_init_copy(&dst->tmpcholesky, &src->tmpcholesky, _state, make_automatic); - ae_vector_init_copy(&dst->r, &src->r, _state, make_automatic); - ae_vector_init_copy(&dst->regdiag, &src->regdiag, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic); - ae_vector_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic); - ae_vector_init_copy(&dst->rdtmprowmap, &src->rdtmprowmap, _state, make_automatic); -} - - -void _snnlssolver_clear(void* _p) -{ - snnlssolver *p = (snnlssolver*)_p; - ae_touch_ptr((void*)p); - ae_matrix_clear(&p->densea); - ae_vector_clear(&p->b); - ae_vector_clear(&p->nnc); - ae_vector_clear(&p->xn); - ae_vector_clear(&p->xp); - ae_matrix_clear(&p->tmpca); - ae_matrix_clear(&p->tmplq); - ae_matrix_clear(&p->trda); - ae_vector_clear(&p->trdd); - ae_vector_clear(&p->crb); - ae_vector_clear(&p->g); - ae_vector_clear(&p->d); - ae_vector_clear(&p->dx); - ae_vector_clear(&p->diagaa); - ae_vector_clear(&p->cb); - ae_vector_clear(&p->cx); - ae_vector_clear(&p->cborg); - ae_vector_clear(&p->tmpcholesky); - ae_vector_clear(&p->r); - ae_vector_clear(&p->regdiag); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->tmp1); - ae_vector_clear(&p->tmp2); - ae_vector_clear(&p->rdtmprowmap); -} - - -void _snnlssolver_destroy(void* _p) -{ - snnlssolver *p = (snnlssolver*)_p; - ae_touch_ptr((void*)p); - ae_matrix_destroy(&p->densea); - ae_vector_destroy(&p->b); - ae_vector_destroy(&p->nnc); - ae_vector_destroy(&p->xn); - ae_vector_destroy(&p->xp); - ae_matrix_destroy(&p->tmpca); - ae_matrix_destroy(&p->tmplq); - ae_matrix_destroy(&p->trda); - ae_vector_destroy(&p->trdd); - ae_vector_destroy(&p->crb); - ae_vector_destroy(&p->g); - ae_vector_destroy(&p->d); - ae_vector_destroy(&p->dx); - ae_vector_destroy(&p->diagaa); - ae_vector_destroy(&p->cb); - ae_vector_destroy(&p->cx); - ae_vector_destroy(&p->cborg); - ae_vector_destroy(&p->tmpcholesky); - ae_vector_destroy(&p->r); - ae_vector_destroy(&p->regdiag); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->tmp1); - ae_vector_destroy(&p->tmp2); - ae_vector_destroy(&p->rdtmprowmap); -} - - -#endif -#if defined(AE_COMPILE_SACTIVESETS) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This subroutine is used to initialize active set. By default, empty -N-variable model with no constraints is generated. Previously allocated -buffer variables are reused as much as possible. - -Two use cases for this object are described below. - -CASE 1 - STEEPEST DESCENT: - - SASInit() - repeat: - SASReactivateConstraints() - SASDescentDirection() - SASExploreDirection() - SASMoveTo() - until convergence - -CASE 1 - PRECONDITIONED STEEPEST DESCENT: - - SASInit() - repeat: - SASReactivateConstraintsPrec() - SASDescentDirectionPrec() - SASExploreDirection() - SASMoveTo() - until convergence - - -- ALGLIB -- - Copyright 21.12.2012 by Bochkanov Sergey -*************************************************************************/ -void sasinit(ae_int_t n, sactiveset* s, ae_state *_state) -{ - ae_int_t i; - - - s->n = n; - s->algostate = 0; - - /* - * Constraints - */ - s->constraintschanged = ae_true; - s->nec = 0; - s->nic = 0; - rvectorsetlengthatleast(&s->bndl, n, _state); - bvectorsetlengthatleast(&s->hasbndl, n, _state); - rvectorsetlengthatleast(&s->bndu, n, _state); - bvectorsetlengthatleast(&s->hasbndu, n, _state); - for(i=0; i<=n-1; i++) - { - s->bndl.ptr.p_double[i] = _state->v_neginf; - s->bndu.ptr.p_double[i] = _state->v_posinf; - s->hasbndl.ptr.p_bool[i] = ae_false; - s->hasbndu.ptr.p_bool[i] = ae_false; - } - - /* - * current point, scale - */ - s->hasxc = ae_false; - rvectorsetlengthatleast(&s->xc, n, _state); - rvectorsetlengthatleast(&s->s, n, _state); - rvectorsetlengthatleast(&s->h, n, _state); - for(i=0; i<=n-1; i++) - { - s->xc.ptr.p_double[i] = 0.0; - s->s.ptr.p_double[i] = 1.0; - s->h.ptr.p_double[i] = 1.0; - } - - /* - * Other - */ - rvectorsetlengthatleast(&s->unitdiagonal, n, _state); - for(i=0; i<=n-1; i++) - { - s->unitdiagonal.ptr.p_double[i] = 1.0; - } -} - - -/************************************************************************* -This function sets scaling coefficients for SAS object. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -During orthogonalization phase, scale is used to calculate drop tolerances -(whether vector is significantly non-zero or not). - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 21.12.2012 by Bochkanov Sergey -*************************************************************************/ -void sassetscale(sactiveset* state, - /* Real */ ae_vector* s, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(state->algostate==0, "SASSetScale: you may change scale only in modification mode", _state); - ae_assert(s->cnt>=state->n, "SASSetScale: Length(S)n-1; i++) - { - ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "SASSetScale: S contains infinite or NAN elements", _state); - ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "SASSetScale: S contains zero elements", _state); - } - for(i=0; i<=state->n-1; i++) - { - state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state); - } -} - - -/************************************************************************* -Modification of the preconditioner: diagonal of approximate Hessian is -used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - D - diagonal of the approximate Hessian, array[0..N-1], - (if larger, only leading N elements are used). - -NOTE 1: D[i] should be positive. Exception will be thrown otherwise. - -NOTE 2: you should pass diagonal of approximate Hessian - NOT ITS INVERSE. - - -- ALGLIB -- - Copyright 21.12.2012 by Bochkanov Sergey -*************************************************************************/ -void sassetprecdiag(sactiveset* state, - /* Real */ ae_vector* d, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(state->algostate==0, "SASSetPrecDiag: you may change preconditioner only in modification mode", _state); - ae_assert(d->cnt>=state->n, "SASSetPrecDiag: D is too short", _state); - for(i=0; i<=state->n-1; i++) - { - ae_assert(ae_isfinite(d->ptr.p_double[i], _state), "SASSetPrecDiag: D contains infinite or NAN elements", _state); - ae_assert(ae_fp_greater(d->ptr.p_double[i],(double)(0)), "SASSetPrecDiag: D contains non-positive elements", _state); - } - for(i=0; i<=state->n-1; i++) - { - state->h.ptr.p_double[i] = d->ptr.p_double[i]; - } -} - - -/************************************************************************* -This function sets/changes boundary constraints. - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF. - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF. - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - - -- ALGLIB -- - Copyright 21.12.2012 by Bochkanov Sergey -*************************************************************************/ -void sassetbc(sactiveset* state, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - - - ae_assert(state->algostate==0, "SASSetBC: you may change constraints only in modification mode", _state); - n = state->n; - ae_assert(bndl->cnt>=n, "SASSetBC: Length(BndL)cnt>=n, "SASSetBC: Length(BndU)ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "SASSetBC: BndL contains NAN or +INF", _state); - ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "SASSetBC: BndL contains NAN or -INF", _state); - state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i]; - state->hasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state); - state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i]; - state->hasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state); - } - state->constraintschanged = ae_true; -} - - -/************************************************************************* -This function sets linear constraints for SAS object. - -Linear constraints are inactive by default (after initial creation). - -INPUT PARAMETERS: - State - SAS structure - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0 - -NOTE 1: linear (non-bound) constraints are satisfied only approximately: -* there always exists some minor violation (about Epsilon in magnitude) - due to rounding errors -* numerical differentiation, if used, may lead to function evaluations - outside of the feasible area, because algorithm does NOT change - numerical differentiation formula according to linear constraints. -If you want constraints to be satisfied exactly, try to reformulate your -problem in such manner that all constraints will become boundary ones -(this kind of constraints is always satisfied exactly, both in the final -solution and in all intermediate points). - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void sassetlc(sactiveset* state, - /* Real */ ae_matrix* c, - /* Integer */ ae_vector* ct, - ae_int_t k, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - - - ae_assert(state->algostate==0, "SASSetLC: you may change constraints only in modification mode", _state); - n = state->n; - - /* - * First, check for errors in the inputs - */ - ae_assert(k>=0, "SASSetLC: K<0", _state); - ae_assert(c->cols>=n+1||k==0, "SASSetLC: Cols(C)rows>=k, "SASSetLC: Rows(C)cnt>=k, "SASSetLC: Length(CT)nec = 0; - state->nic = 0; - state->constraintschanged = ae_true; - return; - } - - /* - * Equality constraints are stored first, in the upper - * NEC rows of State.CLEIC matrix. Inequality constraints - * are stored in the next NIC rows. - * - * NOTE: we convert inequality constraints to the form - * A*x<=b before copying them. - */ - rmatrixsetlengthatleast(&state->cleic, k, n+1, _state); - state->nec = 0; - state->nic = 0; - for(i=0; i<=k-1; i++) - { - if( ct->ptr.p_int[i]==0 ) - { - ae_v_move(&state->cleic.ptr.pp_double[state->nec][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n)); - state->nec = state->nec+1; - } - } - for(i=0; i<=k-1; i++) - { - if( ct->ptr.p_int[i]!=0 ) - { - if( ct->ptr.p_int[i]>0 ) - { - ae_v_moveneg(&state->cleic.ptr.pp_double[state->nec+state->nic][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n)); - } - else - { - ae_v_move(&state->cleic.ptr.pp_double[state->nec+state->nic][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n)); - } - state->nic = state->nic+1; - } - } - - /* - * Mark state as changed - */ - state->constraintschanged = ae_true; -} - - -/************************************************************************* -Another variation of SASSetLC(), which accepts linear constraints using -another representation. - -Linear constraints are inactive by default (after initial creation). - -INPUT PARAMETERS: - State - SAS structure - CLEIC - linear constraints, array[NEC+NIC,N+1]. - Each row of C represents one constraint: - * first N elements correspond to coefficients, - * last element corresponds to the right part. - First NEC rows store equality constraints, next NIC - are - inequality ones. - All elements of C (including right part) must be finite. - NEC - number of equality constraints, NEC>=0 - NIC - number of inequality constraints, NIC>=0 - -NOTE 1: linear (non-bound) constraints are satisfied only approximately: -* there always exists some minor violation (about Epsilon in magnitude) - due to rounding errors -* numerical differentiation, if used, may lead to function evaluations - outside of the feasible area, because algorithm does NOT change - numerical differentiation formula according to linear constraints. -If you want constraints to be satisfied exactly, try to reformulate your -problem in such manner that all constraints will become boundary ones -(this kind of constraints is always satisfied exactly, both in the final -solution and in all intermediate points). - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void sassetlcx(sactiveset* state, - /* Real */ ae_matrix* cleic, - ae_int_t nec, - ae_int_t nic, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_int_t j; - - - ae_assert(state->algostate==0, "SASSetLCX: you may change constraints only in modification mode", _state); - n = state->n; - - /* - * First, check for errors in the inputs - */ - ae_assert(nec>=0, "SASSetLCX: NEC<0", _state); - ae_assert(nic>=0, "SASSetLCX: NIC<0", _state); - ae_assert(cleic->cols>=n+1||nec+nic==0, "SASSetLCX: Cols(CLEIC)rows>=nec+nic, "SASSetLCX: Rows(CLEIC)cleic, nec+nic, n+1, _state); - state->nec = nec; - state->nic = nic; - for(i=0; i<=nec+nic-1; i++) - { - for(j=0; j<=n; j++) - { - state->cleic.ptr.pp_double[i][j] = cleic->ptr.pp_double[i][j]; - } - } - - /* - * Mark state as changed - */ - state->constraintschanged = ae_true; -} - - -/************************************************************************* -This subroutine turns on optimization mode: -1. feasibility in X is enforced (in case X=S.XC and constraints have not - changed, algorithm just uses X without any modifications at all) -2. constraints are marked as "candidate" or "inactive" - -INPUT PARAMETERS: - S - active set object - X - initial point (candidate), array[N]. It is expected that X - contains only finite values (we do not check it). - -OUTPUT PARAMETERS: - S - state is changed - X - initial point can be changed to enforce feasibility - -RESULT: - True in case feasible point was found (mode was changed to "optimization") - False in case no feasible point was found (mode was not changed) - - -- ALGLIB -- - Copyright 21.12.2012 by Bochkanov Sergey -*************************************************************************/ -ae_bool sasstartoptimization(sactiveset* state, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nec; - ae_int_t nic; - ae_int_t i; - ae_int_t j; - double v; - double v0; - double v1; - double vv; - double vc; - double vx; - ae_bool result; - - - ae_assert(state->algostate==0, "SASStartOptimization: already in optimization mode", _state); - result = ae_false; - n = state->n; - nec = state->nec; - nic = state->nic; - - /* - * Enforce feasibility and calculate set of "candidate"/"active" constraints. - * Always active equality constraints are marked as "active", all other constraints - * are marked as "candidate". - */ - ivectorsetlengthatleast(&state->cstatus, n+nec+nic, _state); - for(i=0; i<=n-1; i++) - { - if( state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i] ) - { - if( ae_fp_greater(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - return result; - } - } - } - ae_v_move(&state->xc.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( state->nec+state->nic>0 ) - { - - /* - * General linear constraints are present. - * Try to use fast code for feasible initial point with modest - * memory requirements. - */ - rvectorsetlengthatleast(&state->tmp0, n, _state); - state->feasinitpt = ae_true; - for(i=0; i<=n-1; i++) - { - state->tmp0.ptr.p_double[i] = x->ptr.p_double[i]; - state->cstatus.ptr.p_int[i] = -1; - if( (state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_eq(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->tmp0.ptr.p_double[i] = state->bndl.ptr.p_double[i]; - state->cstatus.ptr.p_int[i] = 1; - continue; - } - if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(state->tmp0.ptr.p_double[i],state->bndl.ptr.p_double[i]) ) - { - state->cstatus.ptr.p_int[i] = 0; - state->tmp0.ptr.p_double[i] = state->bndl.ptr.p_double[i]; - } - if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(state->tmp0.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->cstatus.ptr.p_int[i] = 0; - state->tmp0.ptr.p_double[i] = state->bndu.ptr.p_double[i]; - } - } - for(i=0; i<=state->nec+state->nic-1; i++) - { - v = -state->cleic.ptr.pp_double[i][n]; - v0 = (double)(0); - v1 = (double)(0); - for(j=0; j<=n-1; j++) - { - vx = state->tmp0.ptr.p_double[j]/state->s.ptr.p_double[j]; - vc = state->cleic.ptr.pp_double[i][j]*state->s.ptr.p_double[j]; - v = v+vx*vc; - v0 = v0+ae_sqr(vx, _state); - v1 = v1+ae_sqr(vc, _state); - } - vv = ae_sqrt(v0, _state)*ae_sqrt(v1, _state)*1000*ae_machineepsilon; - if( inec ) - { - state->cstatus.ptr.p_int[n+i] = 1; - state->feasinitpt = state->feasinitpt&&ae_fp_less(ae_fabs(v, _state),vv); - } - else - { - state->feasinitpt = state->feasinitpt&&ae_fp_less(v,vv); - if( ae_fp_less(v,-vv) ) - { - state->cstatus.ptr.p_int[n+i] = -1; - } - else - { - state->cstatus.ptr.p_int[n+i] = 0; - } - } - } - if( state->feasinitpt ) - { - ae_v_move(&state->xc.ptr.p_double[0], 1, &state->tmp0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - } - - /* - * Fast code failed? Use general code with ~(N+NIC)^2 memory requirements - */ - if( !state->feasinitpt ) - { - rvectorsetlengthatleast(&state->tmp0, n, _state); - rvectorsetlengthatleast(&state->tmpfeas, n+state->nic, _state); - rmatrixsetlengthatleast(&state->tmpm0, state->nec+state->nic, n+state->nic+1, _state); - for(i=0; i<=state->nec+state->nic-1; i++) - { - ae_v_move(&state->tmpm0.ptr.pp_double[i][0], 1, &state->cleic.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - for(j=n; j<=n+state->nic-1; j++) - { - state->tmpm0.ptr.pp_double[i][j] = (double)(0); - } - if( i>=state->nec ) - { - state->tmpm0.ptr.pp_double[i][n+i-state->nec] = 1.0; - } - state->tmpm0.ptr.pp_double[i][n+state->nic] = state->cleic.ptr.pp_double[i][n]; - } - ae_v_move(&state->tmpfeas.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=state->nic-1; i++) - { - v = ae_v_dotproduct(&state->cleic.ptr.pp_double[i+state->nec][0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->tmpfeas.ptr.p_double[i+n] = ae_maxreal(state->cleic.ptr.pp_double[i+state->nec][n]-v, 0.0, _state); - } - if( !findfeasiblepoint(&state->tmpfeas, &state->bndl, &state->hasbndl, &state->bndu, &state->hasbndu, n, state->nic, &state->tmpm0, state->nec+state->nic, 1.0E-6, &i, &j, _state) ) - { - return result; - } - ae_v_move(&state->xc.ptr.p_double[0], 1, &state->tmpfeas.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - if( (state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_eq(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->cstatus.ptr.p_int[i] = 1; - continue; - } - if( (state->hasbndl.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]))||(state->hasbndu.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i])) ) - { - state->cstatus.ptr.p_int[i] = 0; - continue; - } - state->cstatus.ptr.p_int[i] = -1; - } - for(i=0; i<=state->nec-1; i++) - { - state->cstatus.ptr.p_int[n+i] = 1; - } - for(i=0; i<=state->nic-1; i++) - { - if( ae_fp_eq(state->tmpfeas.ptr.p_double[n+i],(double)(0)) ) - { - state->cstatus.ptr.p_int[n+state->nec+i] = 0; - } - else - { - state->cstatus.ptr.p_int[n+state->nec+i] = -1; - } - } - } - } - else - { - - /* - * Only box constraints are present, quick code can be used - */ - for(i=0; i<=n-1; i++) - { - state->cstatus.ptr.p_int[i] = -1; - if( (state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_eq(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->cstatus.ptr.p_int[i] = 1; - state->xc.ptr.p_double[i] = state->bndl.ptr.p_double[i]; - continue; - } - if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]) ) - { - state->xc.ptr.p_double[i] = state->bndl.ptr.p_double[i]; - state->cstatus.ptr.p_int[i] = 0; - continue; - } - if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->xc.ptr.p_double[i] = state->bndu.ptr.p_double[i]; - state->cstatus.ptr.p_int[i] = 0; - continue; - } - } - state->feasinitpt = ae_true; - } - - /* - * Change state, allocate temporaries - */ - result = ae_true; - state->algostate = 1; - state->basisisready = ae_false; - state->hasxc = ae_true; - return result; -} - - -/************************************************************************* -This function explores search direction and calculates bound for step as -well as information for activation of constraints. - -INPUT PARAMETERS: - State - SAS structure which stores current point and all other - active set related information - D - descent direction to explore - -OUTPUT PARAMETERS: - StpMax - upper limit on step length imposed by yet inactive - constraints. Can be zero in case some constraints - can be activated by zero step. Equal to some large - value in case step is unlimited. - CIdx - -1 for unlimited step, in [0,N+NEC+NIC) in case of - limited step. - VVal - value which is assigned to X[CIdx] during activation. - For CIdx<0 or CIdx>=N some dummy value is assigned to - this parameter. -*************************************************************************/ -void sasexploredirection(sactiveset* state, - /* Real */ ae_vector* d, - double* stpmax, - ae_int_t* cidx, - double* vval, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nec; - ae_int_t nic; - ae_int_t i; - double prevmax; - double vc; - double vd; - - *stpmax = 0; - *cidx = 0; - *vval = 0; - - ae_assert(state->algostate==1, "SASExploreDirection: is not in optimization mode", _state); - n = state->n; - nec = state->nec; - nic = state->nic; - *cidx = -1; - *vval = (double)(0); - *stpmax = 1.0E50; - for(i=0; i<=n-1; i++) - { - if( state->cstatus.ptr.p_int[i]<=0 ) - { - ae_assert(!state->hasbndl.ptr.p_bool[i]||ae_fp_greater_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]), "SASExploreDirection: internal error - infeasible X", _state); - ae_assert(!state->hasbndu.ptr.p_bool[i]||ae_fp_less_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]), "SASExploreDirection: internal error - infeasible X", _state); - if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(d->ptr.p_double[i],(double)(0)) ) - { - prevmax = *stpmax; - *stpmax = safeminposrv(state->xc.ptr.p_double[i]-state->bndl.ptr.p_double[i], -d->ptr.p_double[i], *stpmax, _state); - if( ae_fp_less(*stpmax,prevmax) ) - { - *cidx = i; - *vval = state->bndl.ptr.p_double[i]; - } - } - if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(d->ptr.p_double[i],(double)(0)) ) - { - prevmax = *stpmax; - *stpmax = safeminposrv(state->bndu.ptr.p_double[i]-state->xc.ptr.p_double[i], d->ptr.p_double[i], *stpmax, _state); - if( ae_fp_less(*stpmax,prevmax) ) - { - *cidx = i; - *vval = state->bndu.ptr.p_double[i]; - } - } - } - } - for(i=nec; i<=nec+nic-1; i++) - { - if( state->cstatus.ptr.p_int[n+i]<=0 ) - { - vc = ae_v_dotproduct(&state->cleic.ptr.pp_double[i][0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - vc = vc-state->cleic.ptr.pp_double[i][n]; - vd = ae_v_dotproduct(&state->cleic.ptr.pp_double[i][0], 1, &d->ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( ae_fp_less_eq(vd,(double)(0)) ) - { - continue; - } - if( ae_fp_less(vc,(double)(0)) ) - { - - /* - * XC is strictly feasible with respect to I-th constraint, - * we can perform non-zero step because there is non-zero distance - * between XC and bound. - */ - prevmax = *stpmax; - *stpmax = safeminposrv(-vc, vd, *stpmax, _state); - if( ae_fp_less(*stpmax,prevmax) ) - { - *cidx = n+i; - } - } - else - { - - /* - * XC is at the boundary (or slightly beyond it), and step vector - * points beyond the boundary. - * - * The only thing we can do is to perform zero step and activate - * I-th constraint. - */ - *stpmax = (double)(0); - *cidx = n+i; - } - } - } -} - - -/************************************************************************* -This subroutine moves current point to XN, which can be: -a) point in the direction previously explored with SASExploreDirection() - function (in this case NeedAct/CIdx/CVal are used) -b) point in arbitrary direction, not necessarily previously checked with - SASExploreDirection() function. - -Step may activate one constraint. It is assumed than XN is approximately -feasible (small error as large as several ulps is possible). Strict -feasibility with respect to bound constraints is enforced during -activation, feasibility with respect to general linear constraints is not -enforced. - -This function activates boundary constraints, such that both is True: -1) XC[I] is not at the boundary -2) XN[I] is at the boundary or beyond it - -INPUT PARAMETERS: - S - active set object - XN - new point. - NeedAct - True in case one constraint needs activation - CIdx - index of constraint, in [0,N+NEC+NIC). - Ignored if NeedAct is false. - This value is calculated by SASExploreDirection(). - CVal - for CIdx in [0,N) this field stores value which is - assigned to XC[CIdx] during activation. CVal is ignored in - other cases. - This value is calculated by SASExploreDirection(). - -OUTPUT PARAMETERS: - S - current point and list of active constraints are changed. - -RESULT: - >0, in case at least one inactive non-candidate constraint was activated - =0, in case only "candidate" constraints were activated - <0, in case no constraints were activated by the step - -NOTE: in general case State.XC<>XN because activation of constraints may - slightly change current point (to enforce feasibility). - - -- ALGLIB -- - Copyright 21.12.2012 by Bochkanov Sergey -*************************************************************************/ -ae_int_t sasmoveto(sactiveset* state, - /* Real */ ae_vector* xn, - ae_bool needact, - ae_int_t cidx, - double cval, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nec; - ae_int_t nic; - ae_int_t i; - ae_bool wasactivation; - ae_int_t result; - - - ae_assert(state->algostate==1, "SASMoveTo: is not in optimization mode", _state); - n = state->n; - nec = state->nec; - nic = state->nic; - - /* - * Save previous state, update current point - */ - rvectorsetlengthatleast(&state->mtx, n, _state); - ivectorsetlengthatleast(&state->mtas, n+nec+nic, _state); - for(i=0; i<=n-1; i++) - { - state->mtx.ptr.p_double[i] = state->xc.ptr.p_double[i]; - state->xc.ptr.p_double[i] = xn->ptr.p_double[i]; - } - for(i=0; i<=n+nec+nic-1; i++) - { - state->mtas.ptr.p_int[i] = state->cstatus.ptr.p_int[i]; - } - - /* - * Activate constraints - */ - bvectorsetlengthatleast(&state->mtnew, n+nec+nic, _state); - wasactivation = ae_false; - for(i=0; i<=n+nec+nic-1; i++) - { - state->mtnew.ptr.p_bool[i] = ae_false; - } - if( needact ) - { - - /* - * Activation - */ - ae_assert(cidx>=0&&cidxxc.ptr.p_double[cidx] = cval; - } - state->cstatus.ptr.p_int[cidx] = 1; - state->mtnew.ptr.p_bool[cidx] = ae_true; - wasactivation = ae_true; - } - for(i=0; i<=n-1; i++) - { - - /* - * Post-check (some constraints may be activated because of numerical errors) - */ - if( (state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]))&&ae_fp_neq(state->xc.ptr.p_double[i],state->mtx.ptr.p_double[i]) ) - { - state->xc.ptr.p_double[i] = state->bndl.ptr.p_double[i]; - state->cstatus.ptr.p_int[i] = 1; - state->mtnew.ptr.p_bool[i] = ae_true; - wasactivation = ae_true; - } - if( (state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]))&&ae_fp_neq(state->xc.ptr.p_double[i],state->mtx.ptr.p_double[i]) ) - { - state->xc.ptr.p_double[i] = state->bndu.ptr.p_double[i]; - state->cstatus.ptr.p_int[i] = 1; - state->mtnew.ptr.p_bool[i] = ae_true; - wasactivation = ae_true; - } - } - - /* - * Determine return status: - * * -1 in case no constraints were activated - * * 0 in case only "candidate" constraints were activated - * * +1 in case at least one "non-candidate" constraint was activated - */ - if( wasactivation ) - { - - /* - * Step activated one/several constraints, but sometimes it is spurious - * activation - RecalculateConstraints() tells us that constraint is - * inactive (negative Largrange multiplier), but step activates it - * because of numerical noise. - * - * This block of code checks whether step activated truly new constraints - * (ones which were not in the active set at the solution): - * - * * for non-boundary constraint it is enough to check that previous value - * of CStatus[i] is negative (=far from boundary), and new one is - * positive (=we are at the boundary, constraint is activated). - * - * * for boundary constraints previous criterion won't work. Each variable - * has two constraints, and simply checking their status is not enough - - * we have to correctly identify cases when we leave one boundary - * (PrevActiveSet[i]=0) and move to another boundary (CStatus[i]>0). - * Such cases can be identified if we compare previous X with new X. - * - * In case only "candidate" constraints were activated, result variable - * is set to 0. In case at least one new constraint was activated, result - * is set to 1. - */ - result = 0; - for(i=0; i<=n-1; i++) - { - if( state->cstatus.ptr.p_int[i]>0&&ae_fp_neq(state->xc.ptr.p_double[i],state->mtx.ptr.p_double[i]) ) - { - result = 1; - } - } - for(i=n; i<=n+state->nec+state->nic-1; i++) - { - if( state->mtas.ptr.p_int[i]<0&&state->cstatus.ptr.p_int[i]>0 ) - { - result = 1; - } - } - } - else - { - - /* - * No activation, return -1 - */ - result = -1; - } - - /* - * Update basis - */ - sasappendtobasis(state, &state->mtnew, _state); - return result; -} - - -/************************************************************************* -This subroutine performs immediate activation of one constraint: -* "immediate" means that we do not have to move to activate it -* in case boundary constraint is activated, we enforce current point to be - exactly at the boundary - -INPUT PARAMETERS: - S - active set object - CIdx - index of constraint, in [0,N+NEC+NIC). - This value is calculated by SASExploreDirection(). - CVal - for CIdx in [0,N) this field stores value which is - assigned to XC[CIdx] during activation. CVal is ignored in - other cases. - This value is calculated by SASExploreDirection(). - - -- ALGLIB -- - Copyright 21.12.2012 by Bochkanov Sergey -*************************************************************************/ -void sasimmediateactivation(sactiveset* state, - ae_int_t cidx, - double cval, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(state->algostate==1, "SASMoveTo: is not in optimization mode", _state); - if( cidxn ) - { - state->xc.ptr.p_double[cidx] = cval; - } - state->cstatus.ptr.p_int[cidx] = 1; - bvectorsetlengthatleast(&state->mtnew, state->n+state->nec+state->nic, _state); - for(i=0; i<=state->n+state->nec+state->nic-1; i++) - { - state->mtnew.ptr.p_bool[i] = ae_false; - } - state->mtnew.ptr.p_bool[cidx] = ae_true; - sasappendtobasis(state, &state->mtnew, _state); -} - - -/************************************************************************* -This subroutine calculates descent direction subject to current active set. - -INPUT PARAMETERS: - S - active set object - G - array[N], gradient - D - possibly prealocated buffer; - automatically resized if needed. - -OUTPUT PARAMETERS: - D - descent direction projected onto current active set. - Components of D which correspond to active boundary - constraints are forced to be exactly zero. - In case D is non-zero, it is normalized to have unit norm. - -NOTE: in case active set has N active constraints (or more), descent - direction is forced to be exactly zero. - - -- ALGLIB -- - Copyright 21.12.2012 by Bochkanov Sergey -*************************************************************************/ -void sasconstraineddescent(sactiveset* state, - /* Real */ ae_vector* g, - /* Real */ ae_vector* d, - ae_state *_state) -{ - - - ae_assert(state->algostate==1, "SASConstrainedDescent: is not in optimization mode", _state); - sasrebuildbasis(state, _state); - sactivesets_constraineddescent(state, g, &state->unitdiagonal, &state->idensebatch, ae_true, d, _state); -} - - -/************************************************************************* -This subroutine calculates preconditioned descent direction subject to -current active set. - -INPUT PARAMETERS: - S - active set object - G - array[N], gradient - D - possibly prealocated buffer; - automatically resized if needed. - -OUTPUT PARAMETERS: - D - descent direction projected onto current active set. - Components of D which correspond to active boundary - constraints are forced to be exactly zero. - In case D is non-zero, it is normalized to have unit norm. - -NOTE: in case active set has N active constraints (or more), descent - direction is forced to be exactly zero. - - -- ALGLIB -- - Copyright 21.12.2012 by Bochkanov Sergey -*************************************************************************/ -void sasconstraineddescentprec(sactiveset* state, - /* Real */ ae_vector* g, - /* Real */ ae_vector* d, - ae_state *_state) -{ - - - ae_assert(state->algostate==1, "SASConstrainedDescentPrec: is not in optimization mode", _state); - sasrebuildbasis(state, _state); - sactivesets_constraineddescent(state, g, &state->h, &state->pdensebatch, ae_true, d, _state); -} - - -/************************************************************************* -This subroutine calculates projection of direction vector to current -active set. - -INPUT PARAMETERS: - S - active set object - D - array[N], direction - -OUTPUT PARAMETERS: - D - direction projected onto current active set. - Components of D which correspond to active boundary - constraints are forced to be exactly zero. - -NOTE: in case active set has N active constraints (or more), descent - direction is forced to be exactly zero. - - -- ALGLIB -- - Copyright 21.12.2012 by Bochkanov Sergey -*************************************************************************/ -void sasconstraineddirection(sactiveset* state, - /* Real */ ae_vector* d, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(state->algostate==1, "SASConstrainedAntigradientPrec: is not in optimization mode", _state); - sasrebuildbasis(state, _state); - sactivesets_constraineddescent(state, d, &state->unitdiagonal, &state->idensebatch, ae_false, &state->cdtmp, _state); - for(i=0; i<=state->n-1; i++) - { - d->ptr.p_double[i] = -state->cdtmp.ptr.p_double[i]; - } -} - - -/************************************************************************* -This subroutine calculates product of direction vector and preconditioner -multiplied subject to current active set. - -INPUT PARAMETERS: - S - active set object - D - array[N], direction - -OUTPUT PARAMETERS: - D - preconditioned direction projected onto current active set. - Components of D which correspond to active boundary - constraints are forced to be exactly zero. - -NOTE: in case active set has N active constraints (or more), descent - direction is forced to be exactly zero. - - -- ALGLIB -- - Copyright 21.12.2012 by Bochkanov Sergey -*************************************************************************/ -void sasconstraineddirectionprec(sactiveset* state, - /* Real */ ae_vector* d, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(state->algostate==1, "SASConstrainedAntigradientPrec: is not in optimization mode", _state); - sasrebuildbasis(state, _state); - sactivesets_constraineddescent(state, d, &state->h, &state->pdensebatch, ae_false, &state->cdtmp, _state); - for(i=0; i<=state->n-1; i++) - { - d->ptr.p_double[i] = -state->cdtmp.ptr.p_double[i]; - } -} - - -/************************************************************************* -This subroutine performs correction of some (possibly infeasible) point -with respect to a) current active set, b) all boundary constraints, both -active and inactive: - -0) we calculate L1 penalty term for violation of active linear constraints - (one which is returned by SASActiveLCPenalty1() function). -1) first, it performs projection (orthogonal with respect to scale matrix - S) of X into current active set: X -> X1. -2) next, we perform projection with respect to ALL boundary constraints - which are violated at X1: X1 -> X2. -3) X is replaced by X2. - -The idea is that this function can preserve and enforce feasibility during -optimization, and additional penalty parameter can be used to prevent algo -from leaving feasible set because of rounding errors. - -INPUT PARAMETERS: - S - active set object - X - array[N], candidate point - -OUTPUT PARAMETERS: - X - "improved" candidate point: - a) feasible with respect to all boundary constraints - b) feasibility with respect to active set is retained at - good level. - Penalty - penalty term, which can be added to function value if user - wants to penalize violation of constraints (recommended). - -NOTE: this function is not intended to find exact projection (i.e. best - approximation) of X into feasible set. It just improves situation a - bit. - Regular use of this function will help you to retain feasibility - - if you already have something to start with and constrain your - steps is such way that the only source of infeasibility are roundoff - errors. - - -- ALGLIB -- - Copyright 21.12.2012 by Bochkanov Sergey -*************************************************************************/ -void sascorrection(sactiveset* state, - /* Real */ ae_vector* x, - double* penalty, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t n; - double v; - - *penalty = 0; - - ae_assert(state->algostate==1, "SASCorrection: is not in optimization mode", _state); - sasrebuildbasis(state, _state); - n = state->n; - rvectorsetlengthatleast(&state->corrtmp, n, _state); - - /* - * Calculate penalty term. - */ - *penalty = sasactivelcpenalty1(state, x, _state); - - /* - * Perform projection 1. - * - * This projecton is given by: - * - * x_proj = x - S*S*As'*(As*x-b) - * - * where x is original x before projection, S is a scale matrix, - * As is a matrix of equality constraints (active set) which were - * orthogonalized with respect to inner product given by S (i.e. we - * have As*S*S'*As'=I), b is a right part of the orthogonalized - * constraints. - * - * NOTE: you can verify that x_proj is strictly feasible w.r.t. - * active set by multiplying it by As - you will get - * As*x_proj = As*x - As*x + b = b. - * - * This formula for projection can be obtained by solving - * following minimization problem. - * - * min ||inv(S)*(x_proj-x)||^2 s.t. As*x_proj=b - * - * NOTE: we apply sparse batch by examining CStatus[]; it is guaranteed - * to contain sparse batch, but avoids roundoff errors associated - * with the fact that some box constraints were moved to sparse - * storage - * - */ - ae_v_move(&state->corrtmp.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=state->densebatchsize-1; i++) - { - v = -state->sdensebatch.ptr.pp_double[i][n]; - for(j=0; j<=n-1; j++) - { - v = v+state->sdensebatch.ptr.pp_double[i][j]*state->corrtmp.ptr.p_double[j]; - } - for(j=0; j<=n-1; j++) - { - state->corrtmp.ptr.p_double[j] = state->corrtmp.ptr.p_double[j]-v*state->sdensebatch.ptr.pp_double[i][j]*ae_sqr(state->s.ptr.p_double[j], _state); - } - } - for(i=0; i<=n-1; i++) - { - if( state->cstatus.ptr.p_int[i]>0 ) - { - state->corrtmp.ptr.p_double[i] = state->xc.ptr.p_double[i]; - } - } - - /* - * Perform projection 2 - */ - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = state->corrtmp.ptr.p_double[i]; - if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(x->ptr.p_double[i],state->bndl.ptr.p_double[i]) ) - { - x->ptr.p_double[i] = state->bndl.ptr.p_double[i]; - } - if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(x->ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - x->ptr.p_double[i] = state->bndu.ptr.p_double[i]; - } - } -} - - -/************************************************************************* -This subroutine returns L1 penalty for violation of active general linear -constraints (violation of boundary or inactive linear constraints is not -added to penalty). - -Penalty term is equal to: - - Penalty = SUM( Abs((C_i*x-R_i)/Alpha_i) ) - -Here: -* summation is performed for I=0...NEC+NIC-1, CStatus[N+I]>0 - (only for rows of CLEIC which are in active set) -* C_i is I-th row of CLEIC -* R_i is corresponding right part -* S is a scale matrix -* Alpha_i = ||S*C_i|| - is a scaling coefficient which "normalizes" - I-th summation term according to its scale. - -INPUT PARAMETERS: - S - active set object - X - array[N], candidate point - - -- ALGLIB -- - Copyright 21.12.2012 by Bochkanov Sergey -*************************************************************************/ -double sasactivelcpenalty1(sactiveset* state, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t n; - ae_int_t nec; - ae_int_t nic; - double v; - double alpha; - double p; - double result; - - - ae_assert(state->algostate==1, "SASActiveLCPenalty1: is not in optimization mode", _state); - sasrebuildbasis(state, _state); - n = state->n; - nec = state->nec; - nic = state->nic; - - /* - * Calculate penalty term. - */ - result = (double)(0); - for(i=0; i<=nec+nic-1; i++) - { - if( state->cstatus.ptr.p_int[n+i]>0 ) - { - alpha = (double)(0); - p = -state->cleic.ptr.pp_double[i][n]; - for(j=0; j<=n-1; j++) - { - v = state->cleic.ptr.pp_double[i][j]; - p = p+v*x->ptr.p_double[j]; - alpha = alpha+ae_sqr(v*state->s.ptr.p_double[j], _state); - } - alpha = ae_sqrt(alpha, _state); - if( ae_fp_neq(alpha,(double)(0)) ) - { - result = result+ae_fabs(p/alpha, _state); - } - } - } - return result; -} - - -/************************************************************************* -This subroutine calculates scaled norm of vector after projection onto -subspace of active constraints. Most often this function is used to test -stopping conditions. - -INPUT PARAMETERS: - S - active set object - D - vector whose norm is calculated - -RESULT: - Vector norm (after projection and scaling) - -NOTE: projection is performed first, scaling is performed after projection - -NOTE: if we have N active constraints, zero value (exact zero) is returned - - -- ALGLIB -- - Copyright 21.12.2012 by Bochkanov Sergey -*************************************************************************/ -double sasscaledconstrainednorm(sactiveset* state, - /* Real */ ae_vector* d, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - double v; - double result; - - - ae_assert(state->algostate==1, "SASMoveTo: is not in optimization mode", _state); - n = state->n; - rvectorsetlengthatleast(&state->scntmp, n, _state); - - /* - * Prepare basis (if needed) - */ - sasrebuildbasis(state, _state); - - /* - * Calculate descent direction - */ - if( state->sparsebatchsize+state->densebatchsize>=n ) - { - - /* - * Quick exit if number of active constraints is N or larger - */ - result = 0.0; - return result; - } - for(i=0; i<=n-1; i++) - { - state->scntmp.ptr.p_double[i] = d->ptr.p_double[i]; - } - for(i=0; i<=state->densebatchsize-1; i++) - { - v = ae_v_dotproduct(&state->idensebatch.ptr.pp_double[i][0], 1, &state->scntmp.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_subd(&state->scntmp.ptr.p_double[0], 1, &state->idensebatch.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v); - } - for(i=0; i<=n-1; i++) - { - if( state->cstatus.ptr.p_int[i]>0 ) - { - state->scntmp.ptr.p_double[i] = (double)(0); - } - } - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(state->s.ptr.p_double[i]*state->scntmp.ptr.p_double[i], _state); - } - result = ae_sqrt(v, _state); - return result; -} - - -/************************************************************************* -This subroutine turns off optimization mode. - -INPUT PARAMETERS: - S - active set object - -OUTPUT PARAMETERS: - S - state is changed - -NOTE: this function can be called many times for optimizer which was - already stopped. - - -- ALGLIB -- - Copyright 21.12.2012 by Bochkanov Sergey -*************************************************************************/ -void sasstopoptimization(sactiveset* state, ae_state *_state) -{ - - - state->algostate = 0; -} - - -/************************************************************************* -This function recalculates constraints - activates and deactivates them -according to gradient value at current point. Algorithm assumes that we -want to make steepest descent step from current point; constraints are -activated and deactivated in such way that we won't violate any constraint -by steepest descent step. - -After call to this function active set is ready to try steepest descent -step (SASDescentDirection-SASExploreDirection-SASMoveTo). - -Only already "active" and "candidate" elements of ActiveSet are examined; -constraints which are not active are not examined. - -INPUT PARAMETERS: - State - active set object - GC - array[N], gradient at XC - -OUTPUT PARAMETERS: - State - active set object, with new set of constraint - - -- ALGLIB -- - Copyright 26.09.2012 by Bochkanov Sergey -*************************************************************************/ -void sasreactivateconstraints(sactiveset* state, - /* Real */ ae_vector* gc, - ae_state *_state) -{ - - - ae_assert(state->algostate==1, "SASReactivateConstraints: must be in optimization mode", _state); - sactivesets_reactivateconstraints(state, gc, &state->unitdiagonal, _state); -} - - -/************************************************************************* -This function recalculates constraints - activates and deactivates them -according to gradient value at current point. - -Algorithm assumes that we want to make Quasi-Newton step from current -point with diagonal Quasi-Newton matrix H. Constraints are activated and -deactivated in such way that we won't violate any constraint by step. - -After call to this function active set is ready to try preconditioned -steepest descent step (SASDescentDirection-SASExploreDirection-SASMoveTo). - -Only already "active" and "candidate" elements of ActiveSet are examined; -constraints which are not active are not examined. - -INPUT PARAMETERS: - State - active set object - GC - array[N], gradient at XC - -OUTPUT PARAMETERS: - State - active set object, with new set of constraint - - -- ALGLIB -- - Copyright 26.09.2012 by Bochkanov Sergey -*************************************************************************/ -void sasreactivateconstraintsprec(sactiveset* state, - /* Real */ ae_vector* gc, - ae_state *_state) -{ - - - ae_assert(state->algostate==1, "SASReactivateConstraintsPrec: must be in optimization mode", _state); - sactivesets_reactivateconstraints(state, gc, &state->h, _state); -} - - -/************************************************************************* -This function builds three orthonormal basises for current active set: -* P-orthogonal one, which is orthogonalized with inner product - (x,y) = x'*P*y, where P=inv(H) is current preconditioner -* S-orthogonal one, which is orthogonalized with inner product - (x,y) = x'*S'*S*y, where S is diagonal scaling matrix -* I-orthogonal one, which is orthogonalized with standard dot product - -NOTE: all sets of orthogonal vectors are guaranteed to have same size. - P-orthogonal basis is built first, I/S-orthogonal basises are forced - to have same number of vectors as P-orthogonal one (padded by zero - vectors if needed). - -NOTE: this function tracks changes in active set; first call will result - in reorthogonalization - -INPUT PARAMETERS: - State - active set object - H - diagonal preconditioner, H[i]>0 - -OUTPUT PARAMETERS: - State - active set object with new basis - - -- ALGLIB -- - Copyright 20.06.2012 by Bochkanov Sergey -*************************************************************************/ -void sasrebuildbasis(sactiveset* state, ae_state *_state) -{ - ae_int_t n; - ae_int_t nec; - ae_int_t nic; - ae_int_t i; - ae_int_t j; - ae_bool hasactivelin; - ae_int_t candidatescnt; - double v; - double vv; - double vmax; - ae_int_t kmax; - - - if( state->basisisready ) - { - return; - } - n = state->n; - nec = state->nec; - nic = state->nic; - rvectorsetlengthatleast(&state->tmp0, n, _state); - rvectorsetlengthatleast(&state->tmpprodp, n, _state); - rvectorsetlengthatleast(&state->tmpprods, n, _state); - rvectorsetlengthatleast(&state->tmpcp, n+1, _state); - rvectorsetlengthatleast(&state->tmpcs, n+1, _state); - rvectorsetlengthatleast(&state->tmpci, n+1, _state); - rmatrixsetlengthatleast(&state->tmpbasis, nec+nic, n+1, _state); - rmatrixsetlengthatleast(&state->pdensebatch, nec+nic, n+1, _state); - rmatrixsetlengthatleast(&state->idensebatch, nec+nic, n+1, _state); - rmatrixsetlengthatleast(&state->sdensebatch, nec+nic, n+1, _state); - ivectorsetlengthatleast(&state->sparsebatch, n, _state); - state->sparsebatchsize = 0; - state->densebatchsize = 0; - state->basisage = 0; - state->basisisready = ae_true; - - /* - * Determine number of active boundary and non-boundary - * constraints, move them to TmpBasis. Quick exit if no - * non-boundary constraints were detected. - */ - hasactivelin = ae_false; - for(i=0; i<=nec+nic-1; i++) - { - if( state->cstatus.ptr.p_int[n+i]>0 ) - { - hasactivelin = ae_true; - } - } - for(j=0; j<=n-1; j++) - { - if( state->cstatus.ptr.p_int[j]>0 ) - { - state->sparsebatch.ptr.p_int[state->sparsebatchsize] = j; - state->sparsebatchsize = state->sparsebatchsize+1; - } - } - if( !hasactivelin ) - { - return; - } - - /* - * Prepare precomputed values - */ - rvectorsetlengthatleast(&state->tmpreciph, n, _state); - for(i=0; i<=n-1; i++) - { - state->tmpreciph.ptr.p_double[i] = 1/state->h.ptr.p_double[i]; - } - - /* - * Prepare initial candidate set: - * * select active constraints - * * normalize (inner product is given by preconditioner) - * * orthogonalize with respect to active box constraints - * * copy normalized/orthogonalized candidates to PBasis/SBasis/IBasis - */ - candidatescnt = 0; - for(i=0; i<=nec+nic-1; i++) - { - if( state->cstatus.ptr.p_int[n+i]>0 ) - { - ae_v_move(&state->tmpbasis.ptr.pp_double[candidatescnt][0], 1, &state->cleic.ptr.pp_double[i][0], 1, ae_v_len(0,n)); - inc(&candidatescnt, _state); - } - } - for(i=0; i<=candidatescnt-1; i++) - { - v = 0.0; - for(j=0; j<=n-1; j++) - { - v = v+ae_sqr(state->tmpbasis.ptr.pp_double[i][j], _state)*state->tmpreciph.ptr.p_double[j]; - } - if( ae_fp_greater(v,(double)(0)) ) - { - v = 1/ae_sqrt(v, _state); - for(j=0; j<=n; j++) - { - state->tmpbasis.ptr.pp_double[i][j] = state->tmpbasis.ptr.pp_double[i][j]*v; - } - } - } - for(j=0; j<=n-1; j++) - { - if( state->cstatus.ptr.p_int[j]>0 ) - { - for(i=0; i<=candidatescnt-1; i++) - { - state->tmpbasis.ptr.pp_double[i][n] = state->tmpbasis.ptr.pp_double[i][n]-state->tmpbasis.ptr.pp_double[i][j]*state->xc.ptr.p_double[j]; - state->tmpbasis.ptr.pp_double[i][j] = 0.0; - } - } - } - for(i=0; i<=candidatescnt-1; i++) - { - for(j=0; j<=n; j++) - { - state->pdensebatch.ptr.pp_double[i][j] = state->tmpbasis.ptr.pp_double[i][j]; - state->sdensebatch.ptr.pp_double[i][j] = state->tmpbasis.ptr.pp_double[i][j]; - state->idensebatch.ptr.pp_double[i][j] = state->tmpbasis.ptr.pp_double[i][j]; - } - } - - /* - * Perform orthogonalization of general linear constraints with respect - * to each other (constraints in P/S/IBasis are already normalized w.r.t. - * box constraints). During this process we select strictly active constraints - * from the candidate set, and drop ones which were detected as redundant - * during orthogonalization. - * - * Orthogonalization is performed with the help of Gram-Schmidt process. - * Due to accumulation of round-off errors it is beneficial to perform - * pivoting, i.e. to select candidate vector with largest norm at each - * step. - * - * First (basic) version of the algorithm is: - * 0. split all constraints into two sets: basis ones (initially empty) - * and candidate ones (all constraints) - * 1. fill PBasis with H-normalized candidate constraints, fill - * corresponding entries of S/IBasis with corresponding - * (non-normalized) constraints - * 2. select row of PBasis with largest norm, move it (and its S/IBasis - * counterparts) to the beginning of the candidate set, H-normalize - * this row (rows of S/IBasis are normalized using corresponding norms). - * Stop if largest row is nearly (or exactly) zero. - * 3. orthogonalize remaining rows of P/S/IBasis with respect to - * one chosen at step (2). It can be done efficiently using - * combination of DGEMV/DGER BLAS calls. - * 4. increase basis size by one, decrease candidate set size by one, - * goto (2) - * - * However, naive implementation of the algorithm above spends significant - * amount of time in step (2) - selection of row with largest H-norm. Step - * (3) can be efficiently implemented with optimized BLAS, but we have no - * optimized BLAS kernels for step(2). And because step (3) changes row norms, - * step (2) have to be re-calculated every time, which is quite slow. - * - * We can save significant amount of calculations by noticing that: - * * step (3) DECREASES row norms, but never increases it - * * we can maintain upper bounds for row H-norms is a separate array, - * use them for initial evaluation of best candidates, and update them - * after we find some promising row (all bounds are invalidated after - * step 3, but their old values still carry some information) - * * it is beneficial re-evaluate bounds only for rows which are - * significantly (at least few percents) larger than best one found so far - * * because rows are initially normalized, initial values for upper bounds - * can be set to 1.0 - */ - ae_assert(state->densebatchsize==0, "SAS: integrity check failed", _state); - ae_assert(ae_fp_greater(sactivesets_minnormseparation,(double)(0)), "SAS: integrity check failed", _state); - rvectorsetlengthatleast(&state->tmpnormestimates, candidatescnt, _state); - for(i=0; i<=candidatescnt-1; i++) - { - state->tmpnormestimates.ptr.p_double[i] = 1.0; - } - while(state->sparsebatchsize+state->densebatchsizedensebatchsize; i<=state->densebatchsize+candidatescnt-1; i++) - { - - /* - * Use upper bound for row norm for initial evaluation. - * Skip rows whose upper bound is less than best candidate - * found so far. - * - * NOTE: in fact, we may skip rows whose upper bound is - * marginally higher than that of best candidate. - * No need to perform costly re-evaluation in order - * to get just few percents of improvement. - */ - if( ae_fp_less(state->tmpnormestimates.ptr.p_double[i],vmax*(1+sactivesets_minnormseparation)) ) - { - continue; - } - - /* - * OK, upper bound is large enough... lets perform full - * re-evaluation and update of the estimate. - */ - v = 0.0; - for(j=0; j<=n-1; j++) - { - vv = state->pdensebatch.ptr.pp_double[i][j]; - v = v+vv*vv*state->tmpreciph.ptr.p_double[j]; - } - v = ae_sqrt(v, _state); - state->tmpnormestimates.ptr.p_double[i] = v; - - /* - * Now compare with best candidate so far - */ - if( ae_fp_greater(v,vmax) ) - { - vmax = v; - kmax = i; - } - } - if( ae_fp_less(vmax,1.0E4*ae_machineepsilon)||kmax<0 ) - { - - /* - * All candidates are either zero or too small (after orthogonalization) - */ - candidatescnt = 0; - break; - } - - /* - * Candidate is selected for inclusion into basis set. - * - * Move candidate row to the beginning of candidate array (which is - * right past the end of the approved basis). Normalize (for P-basis - * we perform preconditioner-based normalization, for S-basis - scale - * based, for I-basis - identity based). - */ - swaprows(&state->pdensebatch, state->densebatchsize, kmax, n+1, _state); - swaprows(&state->sdensebatch, state->densebatchsize, kmax, n+1, _state); - swaprows(&state->idensebatch, state->densebatchsize, kmax, n+1, _state); - swapelements(&state->tmpnormestimates, state->densebatchsize, kmax, _state); - v = 1/vmax; - ae_v_muld(&state->pdensebatch.ptr.pp_double[state->densebatchsize][0], 1, ae_v_len(0,n), v); - v = (double)(0); - for(j=0; j<=n-1; j++) - { - vv = state->sdensebatch.ptr.pp_double[state->densebatchsize][j]*state->s.ptr.p_double[j]; - v = v+vv*vv; - } - ae_assert(ae_fp_greater(v,(double)(0)), "SActiveSet.RebuildBasis(): integrity check failed, SNorm=0", _state); - v = 1/ae_sqrt(v, _state); - ae_v_muld(&state->sdensebatch.ptr.pp_double[state->densebatchsize][0], 1, ae_v_len(0,n), v); - v = (double)(0); - for(j=0; j<=n-1; j++) - { - vv = state->idensebatch.ptr.pp_double[state->densebatchsize][j]; - v = v+vv*vv; - } - ae_assert(ae_fp_greater(v,(double)(0)), "SActiveSet.RebuildBasis(): integrity check failed, INorm=0", _state); - v = 1/ae_sqrt(v, _state); - ae_v_muld(&state->idensebatch.ptr.pp_double[state->densebatchsize][0], 1, ae_v_len(0,n), v); - - /* - * Reorthogonalize other candidates with respect to candidate #0: - * * calculate projections en masse with GEMV() - * * subtract projections with GER() - */ - rvectorsetlengthatleast(&state->tmp0, candidatescnt-1, _state); - for(j=0; j<=n-1; j++) - { - state->tmpprodp.ptr.p_double[j] = state->pdensebatch.ptr.pp_double[state->densebatchsize][j]/state->h.ptr.p_double[j]; - state->tmpprods.ptr.p_double[j] = state->sdensebatch.ptr.pp_double[state->densebatchsize][j]*ae_sqr(state->s.ptr.p_double[j], _state); - } - for(j=0; j<=n; j++) - { - state->tmpcp.ptr.p_double[j] = state->pdensebatch.ptr.pp_double[state->densebatchsize][j]; - state->tmpcs.ptr.p_double[j] = state->sdensebatch.ptr.pp_double[state->densebatchsize][j]; - state->tmpci.ptr.p_double[j] = state->idensebatch.ptr.pp_double[state->densebatchsize][j]; - } - rmatrixgemv(candidatescnt-1, n, 1.0, &state->pdensebatch, state->densebatchsize+1, 0, 0, &state->tmpprodp, 0, 0.0, &state->tmp0, 0, _state); - rmatrixger(candidatescnt-1, n+1, &state->pdensebatch, state->densebatchsize+1, 0, -1.0, &state->tmp0, 0, &state->tmpcp, 0, _state); - rmatrixgemv(candidatescnt-1, n, 1.0, &state->sdensebatch, state->densebatchsize+1, 0, 0, &state->tmpprods, 0, 0.0, &state->tmp0, 0, _state); - rmatrixger(candidatescnt-1, n+1, &state->sdensebatch, state->densebatchsize+1, 0, -1.0, &state->tmp0, 0, &state->tmpcs, 0, _state); - rmatrixgemv(candidatescnt-1, n, 1.0, &state->idensebatch, state->densebatchsize+1, 0, 0, &state->tmpci, 0, 0.0, &state->tmp0, 0, _state); - rmatrixger(candidatescnt-1, n+1, &state->idensebatch, state->densebatchsize+1, 0, -1.0, &state->tmp0, 0, &state->tmpci, 0, _state); - - /* - * Increase basis, decrease candidates count - */ - inc(&state->densebatchsize, _state); - dec(&candidatescnt, _state); - } -} - - -/************************************************************************* -This function appends new constraints (if possible; sometimes it isn't!) -to three orthonormal basises for current active set: -* P-orthogonal one, which is orthogonalized with inner product - (x,y) = x'*P*y, where P=inv(H) is current preconditioner -* S-orthogonal one, which is orthogonalized with inner product - (x,y) = x'*S'*S*y, where S is diagonal scaling matrix -* I-orthogonal one, which is orthogonalized with standard dot product - -NOTE: all sets of orthogonal vectors are guaranteed to have same size. - P-orthogonal basis is built first, I/S-orthogonal basises are forced - to have same number of vectors as P-orthogonal one (padded by zero - vectors if needed). - -NOTE: this function may fail to update basis without full recalculation; - in such case it will set BasisIsReady to False and silently return; - if it succeeds, it will increase BasisSize. - -INPUT PARAMETERS: - State - active set object - NewEntries - array[N+NEC+NIC], indexes of constraints being added - are marked as True; it is responsibility of the caller - to specify only those constraints which were previously - inactive; when some constraint is already in the - active set, algorithm behavior is undefined. - -OUTPUT PARAMETERS: - State - active set object with new basis - - -- ALGLIB -- - Copyright 03.10.2017 by Bochkanov Sergey -*************************************************************************/ -void sasappendtobasis(sactiveset* state, - /* Boolean */ ae_vector* newentries, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nec; - ae_int_t nic; - ae_int_t i; - ae_int_t j; - ae_int_t t; - ae_int_t nact; - double v; - double vp; - double vs; - double vi; - double initnormp; - double projnormp; - double projnorms; - double projnormi; - - - if( !state->basisisready ) - { - return; - } - n = state->n; - nec = state->nec; - nic = state->nic; - - /* - * Count number of constraints to activate; - * perform integrity check. - */ - nact = 0; - for(i=0; i<=n-1; i++) - { - if( newentries->ptr.p_bool[i] ) - { - nact = nact+1; - } - } - for(i=n; i<=n+nec-1; i++) - { - ae_assert(!newentries->ptr.p_bool[i], "SAS: integrity check failed (appendtobasis.0)", _state); - } - for(i=n+nec; i<=n+nec+nic-1; i++) - { - if( newentries->ptr.p_bool[i] ) - { - nact = nact+1; - } - } - if( nact+state->basisage>sactivesets_maxbasisage ) - { - state->basisisready = ae_false; - return; - } - - /* - * Resize basis matrices if needed - */ - rmatrixgrowrowsto(&state->pdensebatch, state->densebatchsize+nact, n+1, _state); - rmatrixgrowrowsto(&state->sdensebatch, state->densebatchsize+nact, n+1, _state); - rmatrixgrowrowsto(&state->idensebatch, state->densebatchsize+nact, n+1, _state); - - /* - * Try adding recommended entries to basis. - * If reorthogonalization removes too much of candidate constraint, - * we will invalidate basis and try to rebuild it from scratch. - */ - rvectorsetlengthatleast(&state->tmp0, n+1, _state); - rvectorsetlengthatleast(&state->tmpcp, n+1, _state); - rvectorsetlengthatleast(&state->tmpcs, n+1, _state); - rvectorsetlengthatleast(&state->tmpci, n+1, _state); - rvectorsetlengthatleast(&state->tmpprodp, n, _state); - rvectorsetlengthatleast(&state->tmpprods, n, _state); - for(t=0; t<=n+nec+nic-1; t++) - { - if( newentries->ptr.p_bool[t] ) - { - - /* - * Basis is full? Quick skip! - */ - if( state->sparsebatchsize+state->densebatchsize>=n ) - { - ae_assert(state->sparsebatchsize+state->densebatchsize==n, "SAS: integrity check failed (sasappendtobasis)", _state); - break; - } - - /* - * Copy constraint to temporary storage. - */ - if( ttmp0.ptr.p_double[j] = (double)(0); - } - state->tmp0.ptr.p_double[t] = 1.0; - state->tmp0.ptr.p_double[n] = state->xc.ptr.p_double[t]; - } - else - { - - /* - * Copy general linear constraint - */ - for(j=0; j<=n; j++) - { - state->tmp0.ptr.p_double[j] = state->cleic.ptr.pp_double[t-n][j]; - } - } - - /* - * Calculate initial norm (preconditioner is used for norm calculation). - */ - initnormp = 0.0; - for(j=0; j<=n-1; j++) - { - v = state->tmp0.ptr.p_double[j]; - initnormp = initnormp+v*v/state->h.ptr.p_double[j]; - } - initnormp = ae_sqrt(initnormp, _state); - if( ae_fp_eq(initnormp,(double)(0)) ) - { - - /* - * Well, it is not expected. Let's just rebuild basis - * from scratch and forget about this strange situation... - */ - state->basisisready = ae_false; - return; - } - - /* - * Orthogonalize Tmp0 w.r.t. sparse batch (box constraints stored in sparse storage). - * - * Copy to TmpCP/TmpCS/TmpCI (P for preconditioner-based inner product - * used for orthogonalization, S for scale-based orthogonalization, - * I for "traditional" inner product used for Gram-Schmidt orthogonalization). - */ - for(i=0; i<=state->sparsebatchsize-1; i++) - { - j = state->sparsebatch.ptr.p_int[i]; - state->tmp0.ptr.p_double[n] = state->tmp0.ptr.p_double[n]-state->tmp0.ptr.p_double[j]*state->xc.ptr.p_double[j]; - state->tmp0.ptr.p_double[j] = 0.0; - } - for(j=0; j<=n; j++) - { - state->tmpcp.ptr.p_double[j] = state->tmp0.ptr.p_double[j]; - state->tmpcs.ptr.p_double[j] = state->tmp0.ptr.p_double[j]; - state->tmpci.ptr.p_double[j] = state->tmp0.ptr.p_double[j]; - } - - /* - * Orthogonalize TmpCP/S/I with respect to active linear constraints from dense batch. - * Corresponding norm (preconditioner, scale, identity) is used in each case. - */ - for(j=0; j<=n-1; j++) - { - state->tmpprodp.ptr.p_double[j] = 1/state->h.ptr.p_double[j]; - state->tmpprods.ptr.p_double[j] = ae_sqr(state->s.ptr.p_double[j], _state); - } - for(i=0; i<=state->densebatchsize-1; i++) - { - vp = (double)(0); - vs = (double)(0); - vi = (double)(0); - for(j=0; j<=n-1; j++) - { - vp = vp+state->pdensebatch.ptr.pp_double[i][j]*state->tmpcp.ptr.p_double[j]*state->tmpprodp.ptr.p_double[j]; - vs = vs+state->sdensebatch.ptr.pp_double[i][j]*state->tmpcs.ptr.p_double[j]*state->tmpprods.ptr.p_double[j]; - vi = vi+state->idensebatch.ptr.pp_double[i][j]*state->tmpci.ptr.p_double[j]; - } - ae_v_subd(&state->tmpcp.ptr.p_double[0], 1, &state->pdensebatch.ptr.pp_double[i][0], 1, ae_v_len(0,n), vp); - ae_v_subd(&state->tmpcs.ptr.p_double[0], 1, &state->sdensebatch.ptr.pp_double[i][0], 1, ae_v_len(0,n), vs); - ae_v_subd(&state->tmpci.ptr.p_double[0], 1, &state->idensebatch.ptr.pp_double[i][0], 1, ae_v_len(0,n), vi); - } - projnormp = 0.0; - projnorms = 0.0; - projnormi = 0.0; - for(j=0; j<=n-1; j++) - { - projnormp = projnormp+ae_sqr(state->tmpcp.ptr.p_double[j], _state)/state->h.ptr.p_double[j]; - projnorms = projnorms+ae_sqr(state->tmpcs.ptr.p_double[j], _state)*ae_sqr(state->s.ptr.p_double[j], _state); - projnormi = projnormi+ae_sqr(state->tmpci.ptr.p_double[j], _state); - } - projnormp = ae_sqrt(projnormp, _state); - projnorms = ae_sqrt(projnorms, _state); - projnormi = ae_sqrt(projnormi, _state); - if( ae_fp_less_eq(projnormp,sactivesets_maxbasisdecay*initnormp) ) - { - state->basisisready = ae_false; - return; - - /* - * Nearly zero row, skip - */ - } - ae_assert(ae_fp_greater(projnormp,(double)(0)), "SAS: integrity check failed, ProjNormP=0", _state); - ae_assert(ae_fp_greater(projnorms,(double)(0)), "SAS: integrity check failed, ProjNormS=0", _state); - ae_assert(ae_fp_greater(projnormi,(double)(0)), "SAS: integrity check failed, ProjNormI=0", _state); - v = 1/projnormp; - ae_v_moved(&state->pdensebatch.ptr.pp_double[state->densebatchsize][0], 1, &state->tmpcp.ptr.p_double[0], 1, ae_v_len(0,n), v); - v = 1/projnorms; - ae_v_moved(&state->sdensebatch.ptr.pp_double[state->densebatchsize][0], 1, &state->tmpcs.ptr.p_double[0], 1, ae_v_len(0,n), v); - v = 1/projnormi; - ae_v_moved(&state->idensebatch.ptr.pp_double[state->densebatchsize][0], 1, &state->tmpci.ptr.p_double[0], 1, ae_v_len(0,n), v); - - /* - * Increase set size - */ - inc(&state->densebatchsize, _state); - inc(&state->basisage, _state); - } - } -} - - -/************************************************************************* -This subroutine calculates preconditioned descent direction subject to -current active set. - -INPUT PARAMETERS: - State - active set object - G - array[N], gradient - H - array[N], Hessian matrix - HA - active constraints orthogonalized in such way - that HA*inv(H)*HA'= I. - Normalize- whether we need normalized descent or not - D - possibly preallocated buffer; automatically resized. - -OUTPUT PARAMETERS: - D - descent direction projected onto current active set. - Components of D which correspond to active boundary - constraints are forced to be exactly zero. - In case D is non-zero and Normalize is True, it is - normalized to have unit norm. - -NOTE: if we have N active constraints, D is explicitly set to zero. - - -- ALGLIB -- - Copyright 21.12.2012 by Bochkanov Sergey -*************************************************************************/ -static void sactivesets_constraineddescent(sactiveset* state, - /* Real */ ae_vector* g, - /* Real */ ae_vector* h, - /* Real */ ae_matrix* ha, - ae_bool normalize, - /* Real */ ae_vector* d, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t n; - double v; - - - ae_assert(state->algostate==1, "SAS: internal error in ConstrainedDescent() - not in optimization mode", _state); - ae_assert(state->basisisready, "SAS: internal error in ConstrainedDescent() - no basis", _state); - n = state->n; - rvectorsetlengthatleast(d, n, _state); - - /* - * Calculate preconditioned constrained descent direction: - * - * d := -inv(H)*( g - HA'*(HA*inv(H)*g) ) - * - * Formula above always gives direction which is orthogonal to rows of HA. - * You can verify it by multiplication of both sides by HA[i] (I-th row), - * taking into account that HA*inv(H)*HA'= I (by definition of HA - it is - * orthogonal basis with inner product given by inv(H)). - */ - for(i=0; i<=n-1; i++) - { - d->ptr.p_double[i] = g->ptr.p_double[i]; - } - for(i=0; i<=state->densebatchsize-1; i++) - { - v = 0.0; - for(j=0; j<=n-1; j++) - { - v = v+ha->ptr.pp_double[i][j]*d->ptr.p_double[j]/h->ptr.p_double[j]; - } - ae_v_subd(&d->ptr.p_double[0], 1, &ha->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v); - } - for(i=0; i<=n-1; i++) - { - if( state->cstatus.ptr.p_int[i]>0 ) - { - d->ptr.p_double[i] = (double)(0); - } - } - v = 0.0; - for(i=0; i<=n-1; i++) - { - d->ptr.p_double[i] = -d->ptr.p_double[i]/h->ptr.p_double[i]; - v = v+ae_sqr(d->ptr.p_double[i], _state); - } - v = ae_sqrt(v, _state); - if( state->sparsebatchsize+state->densebatchsize>=n ) - { - v = (double)(0); - for(i=0; i<=n-1; i++) - { - d->ptr.p_double[i] = (double)(0); - } - } - if( normalize&&ae_fp_greater(v,(double)(0)) ) - { - for(i=0; i<=n-1; i++) - { - d->ptr.p_double[i] = d->ptr.p_double[i]/v; - } - } -} - - -/************************************************************************* -This function recalculates constraints - activates and deactivates them -according to gradient value at current point. - -Algorithm assumes that we want to make Quasi-Newton step from current -point with diagonal Quasi-Newton matrix H. Constraints are activated and -deactivated in such way that we won't violate any constraint by step. - -Only already "active" and "candidate" elements of ActiveSet are examined; -constraints which are not active are not examined. - -INPUT PARAMETERS: - State - active set object - GC - array[N], gradient at XC - H - array[N], Hessian matrix - -OUTPUT PARAMETERS: - State - active set object, with new set of constraint - - -- ALGLIB -- - Copyright 26.09.2012 by Bochkanov Sergey -*************************************************************************/ -static void sactivesets_reactivateconstraints(sactiveset* state, - /* Real */ ae_vector* gc, - /* Real */ ae_vector* h, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nec; - ae_int_t nic; - ae_int_t i; - ae_int_t j; - ae_int_t idx0; - ae_int_t idx1; - double v; - ae_int_t nactivebnd; - ae_int_t nactivelin; - ae_int_t nactiveconstraints; - double rowscale; - - - ae_assert(state->algostate==1, "SASReactivateConstraintsPrec: must be in optimization mode", _state); - - /* - * Prepare - */ - n = state->n; - nec = state->nec; - nic = state->nic; - state->basisisready = ae_false; - - /* - * Handle important special case - no linear constraints, - * only boundary constraints are present - */ - if( nec+nic==0 ) - { - for(i=0; i<=n-1; i++) - { - if( (state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_eq(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->cstatus.ptr.p_int[i] = 1; - continue; - } - if( (state->hasbndl.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]))&&ae_fp_greater_eq(gc->ptr.p_double[i],(double)(0)) ) - { - state->cstatus.ptr.p_int[i] = 1; - continue; - } - if( (state->hasbndu.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]))&&ae_fp_less_eq(gc->ptr.p_double[i],(double)(0)) ) - { - state->cstatus.ptr.p_int[i] = 1; - continue; - } - state->cstatus.ptr.p_int[i] = -1; - } - return; - } - - /* - * General case. - * Allocate temporaries. - */ - rvectorsetlengthatleast(&state->rctmpg, n, _state); - rvectorsetlengthatleast(&state->rctmprightpart, n, _state); - rvectorsetlengthatleast(&state->rctmps, n, _state); - rmatrixsetlengthatleast(&state->rctmpdense0, n, nec+nic, _state); - rmatrixsetlengthatleast(&state->rctmpdense1, n, nec+nic, _state); - bvectorsetlengthatleast(&state->rctmpisequality, n+nec+nic, _state); - ivectorsetlengthatleast(&state->rctmpconstraintidx, n+nec+nic, _state); - - /* - * Calculate descent direction - */ - ae_v_moveneg(&state->rctmpg.ptr.p_double[0], 1, &gc->ptr.p_double[0], 1, ae_v_len(0,n-1)); - - /* - * Determine candidates to the active set. - * - * After this block constraints become either "inactive" (CStatus[i]<0) - * or "candidates" (CStatus[i]=0). Previously active constraints always - * become "candidates". - */ - for(i=0; i<=n-1; i++) - { - state->cstatus.ptr.p_int[i] = -1; - } - for(i=n; i<=n+nec+nic-1; i++) - { - if( state->cstatus.ptr.p_int[i]>0 ) - { - state->cstatus.ptr.p_int[i] = 0; - } - else - { - state->cstatus.ptr.p_int[i] = -1; - } - } - nactiveconstraints = 0; - nactivebnd = 0; - nactivelin = 0; - for(i=0; i<=n-1; i++) - { - - /* - * Activate boundary constraints: - * * copy constraint index to RCTmpConstraintIdx - * * set corresponding element of CStatus[] to "candidate" - * * fill RCTmpS by either +1 (lower bound) or -1 (upper bound) - * * set RCTmpIsEquality to False (BndLhasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_eq(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - - /* - * Equality constraint is activated - */ - state->rctmpconstraintidx.ptr.p_int[nactiveconstraints] = i; - state->cstatus.ptr.p_int[i] = 0; - state->rctmps.ptr.p_double[i] = 1.0; - state->rctmpisequality.ptr.p_bool[nactiveconstraints] = ae_true; - nactiveconstraints = nactiveconstraints+1; - nactivebnd = nactivebnd+1; - continue; - } - if( state->hasbndl.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]) ) - { - - /* - * Lower bound is activated - */ - state->rctmpconstraintidx.ptr.p_int[nactiveconstraints] = i; - state->cstatus.ptr.p_int[i] = 0; - state->rctmps.ptr.p_double[i] = -1.0; - state->rctmpisequality.ptr.p_bool[nactiveconstraints] = ae_false; - nactiveconstraints = nactiveconstraints+1; - nactivebnd = nactivebnd+1; - continue; - } - if( state->hasbndu.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - - /* - * Upper bound is activated - */ - state->rctmpconstraintidx.ptr.p_int[nactiveconstraints] = i; - state->cstatus.ptr.p_int[i] = 0; - state->rctmps.ptr.p_double[i] = 1.0; - state->rctmpisequality.ptr.p_bool[nactiveconstraints] = ae_false; - nactiveconstraints = nactiveconstraints+1; - nactivebnd = nactivebnd+1; - continue; - } - } - for(i=0; i<=nec+nic-1; i++) - { - if( i>=nec&&state->cstatus.ptr.p_int[n+i]<0 ) - { - - /* - * Inequality constraints are skipped if both (a) constraint was - * not active, and (b) we are too far away from the boundary. - */ - rowscale = 0.0; - v = -state->cleic.ptr.pp_double[i][n]; - for(j=0; j<=n-1; j++) - { - v = v+state->cleic.ptr.pp_double[i][j]*state->xc.ptr.p_double[j]; - rowscale = ae_maxreal(rowscale, ae_fabs(state->cleic.ptr.pp_double[i][j]*state->s.ptr.p_double[j], _state), _state); - } - if( ae_fp_less_eq(v,-1.0E5*ae_machineepsilon*rowscale) ) - { - - /* - * NOTE: it is important to check for non-strict inequality - * because we have to correctly handle zero constraint - * 0*x<=0 - */ - continue; - } - } - ae_v_move(&state->rctmpdense0.ptr.pp_double[0][nactivelin], state->rctmpdense0.stride, &state->cleic.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - state->rctmpconstraintidx.ptr.p_int[nactiveconstraints] = n+i; - state->cstatus.ptr.p_int[n+i] = 0; - state->rctmpisequality.ptr.p_bool[nactiveconstraints] = ihasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_eq(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->cstatus.ptr.p_int[i] = 1; - continue; - } - if( (state->hasbndl.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]))&&ae_fp_greater_eq(gc->ptr.p_double[i],(double)(0)) ) - { - state->cstatus.ptr.p_int[i] = 1; - continue; - } - if( (state->hasbndu.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]))&&ae_fp_less_eq(gc->ptr.p_double[i],(double)(0)) ) - { - state->cstatus.ptr.p_int[i] = 1; - continue; - } - } - return; - } - - /* - * General case. - * - * APPROACH TO CONSTRAINTS ACTIVATION/DEACTIVATION - * - * We have NActiveConstraints "candidates": NActiveBnd boundary candidates, - * NActiveLin linear candidates. Indexes of boundary constraints are stored - * in RCTmpConstraintIdx[0:NActiveBnd-1], indexes of linear ones are stored - * in RCTmpConstraintIdx[NActiveBnd:NActiveBnd+NActiveLin-1]. Some of the - * constraints are equality ones, some are inequality - as specified by - * RCTmpIsEquality[i]. - * - * Now we have to determine active subset of "candidates" set. In order to - * do so we solve following constrained minimization problem: - * ( )^2 - * min ( SUM(lambda[i]*A[i]) + G ) - * ( ) - * Here: - * * G is a gradient (column vector) - * * A[i] is a column vector, linear (left) part of I-th constraint. - * I=0..NActiveConstraints-1, first NActiveBnd elements of A are just - * subset of identity matrix (boundary constraints), next NActiveLin - * elements are subset of rows of the matrix of general linear constraints. - * * lambda[i] is a Lagrange multiplier corresponding to I-th constraint - * - * NOTE: for preconditioned setting A is replaced by A*H^(-0.5), G is - * replaced by G*H^(-0.5). We apply this scaling at the last stage, - * before passing data to NNLS solver. - * - * Minimization is performed subject to non-negativity constraints on - * lambda[i] corresponding to inequality constraints. Inequality constraints - * which correspond to non-zero lambda are activated, equality constraints - * are always considered active. - * - * Informally speaking, we "decompose" descent direction -G and represent - * it as sum of constraint vectors and "residual" part (which is equal to - * the actual descent direction subject to constraints). - * - * SOLUTION OF THE NNLS PROBLEM - * - * We solve this optimization problem with Non-Negative Least Squares solver, - * which can efficiently solve least squares problems of the form - * - * ( [ I | AU ] )^2 - * min ( [ | ]*x-b ) s.t. non-negativity constraints on some x[i] - * ( [ 0 | AL ] ) - * - * In order to use this solver we have to rearrange rows of A[] and G in - * such way that first NActiveBnd columns of A store identity matrix (before - * sorting non-zero elements are randomly distributed in the first NActiveBnd - * columns of A, during sorting we move them to first NActiveBnd rows). - * - * Then we create instance of NNLS solver (we reuse instance left from the - * previous run of the optimization problem) and solve NNLS problem. - */ - idx0 = 0; - idx1 = nactivebnd; - for(i=0; i<=n-1; i++) - { - if( state->cstatus.ptr.p_int[i]>=0 ) - { - v = 1/ae_sqrt(h->ptr.p_double[i], _state); - for(j=0; j<=nactivelin-1; j++) - { - state->rctmpdense1.ptr.pp_double[idx0][j] = state->rctmpdense0.ptr.pp_double[i][j]/state->rctmps.ptr.p_double[i]*v; - } - state->rctmprightpart.ptr.p_double[idx0] = state->rctmpg.ptr.p_double[i]/state->rctmps.ptr.p_double[i]*v; - idx0 = idx0+1; - } - else - { - v = 1/ae_sqrt(h->ptr.p_double[i], _state); - for(j=0; j<=nactivelin-1; j++) - { - state->rctmpdense1.ptr.pp_double[idx1][j] = state->rctmpdense0.ptr.pp_double[i][j]*v; - } - state->rctmprightpart.ptr.p_double[idx1] = state->rctmpg.ptr.p_double[i]*v; - idx1 = idx1+1; - } - } - snnlsinit(n, ae_minint(nec+nic, n, _state), n, &state->solver, _state); - snnlssetproblem(&state->solver, &state->rctmpdense1, &state->rctmprightpart, nactivebnd, nactiveconstraints-nactivebnd, n, _state); - for(i=0; i<=nactiveconstraints-1; i++) - { - if( state->rctmpisequality.ptr.p_bool[i] ) - { - snnlsdropnnc(&state->solver, i, _state); - } - } - snnlssolve(&state->solver, &state->rctmplambdas, _state); - - /* - * After solution of the problem we activate equality constraints (always active) - * and inequality constraints with non-zero Lagrange multipliers. Then we reorthogonalize - * active constraints. - */ - for(i=0; i<=n+nec+nic-1; i++) - { - state->cstatus.ptr.p_int[i] = -1; - } - for(i=0; i<=nactiveconstraints-1; i++) - { - if( state->rctmpisequality.ptr.p_bool[i]||ae_fp_greater(state->rctmplambdas.ptr.p_double[i],(double)(0)) ) - { - state->cstatus.ptr.p_int[state->rctmpconstraintidx.ptr.p_int[i]] = 1; - } - else - { - state->cstatus.ptr.p_int[state->rctmpconstraintidx.ptr.p_int[i]] = 0; - } - } - sasrebuildbasis(state, _state); -} - - -void _sactiveset_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - sactiveset *p = (sactiveset*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->xc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->h, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cstatus, 0, DT_INT, _state, make_automatic); - ae_matrix_init(&p->sdensebatch, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->pdensebatch, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->idensebatch, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->sparsebatch, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->hasbndl, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->hasbndu, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->cleic, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->mtnew, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->mtx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->mtas, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->cdtmp, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->corrtmp, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->unitdiagonal, 0, DT_REAL, _state, make_automatic); - _snnlssolver_init(&p->solver, _state, make_automatic); - ae_vector_init(&p->scntmp, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpfeas, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->tmpm0, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rctmps, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rctmpg, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rctmprightpart, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->rctmpdense0, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->rctmpdense1, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rctmpisequality, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->rctmpconstraintidx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->rctmplambdas, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->tmpbasis, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpnormestimates, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpreciph, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpprodp, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpprods, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpcp, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpcs, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpci, 0, DT_REAL, _state, make_automatic); -} - - -void _sactiveset_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - sactiveset *dst = (sactiveset*)_dst; - sactiveset *src = (sactiveset*)_src; - dst->n = src->n; - dst->algostate = src->algostate; - ae_vector_init_copy(&dst->xc, &src->xc, _state, make_automatic); - dst->hasxc = src->hasxc; - ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic); - ae_vector_init_copy(&dst->h, &src->h, _state, make_automatic); - ae_vector_init_copy(&dst->cstatus, &src->cstatus, _state, make_automatic); - dst->basisisready = src->basisisready; - ae_matrix_init_copy(&dst->sdensebatch, &src->sdensebatch, _state, make_automatic); - ae_matrix_init_copy(&dst->pdensebatch, &src->pdensebatch, _state, make_automatic); - ae_matrix_init_copy(&dst->idensebatch, &src->idensebatch, _state, make_automatic); - dst->densebatchsize = src->densebatchsize; - ae_vector_init_copy(&dst->sparsebatch, &src->sparsebatch, _state, make_automatic); - dst->sparsebatchsize = src->sparsebatchsize; - dst->basisage = src->basisage; - dst->feasinitpt = src->feasinitpt; - dst->constraintschanged = src->constraintschanged; - ae_vector_init_copy(&dst->hasbndl, &src->hasbndl, _state, make_automatic); - ae_vector_init_copy(&dst->hasbndu, &src->hasbndu, _state, make_automatic); - ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic); - ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic); - ae_matrix_init_copy(&dst->cleic, &src->cleic, _state, make_automatic); - dst->nec = src->nec; - dst->nic = src->nic; - ae_vector_init_copy(&dst->mtnew, &src->mtnew, _state, make_automatic); - ae_vector_init_copy(&dst->mtx, &src->mtx, _state, make_automatic); - ae_vector_init_copy(&dst->mtas, &src->mtas, _state, make_automatic); - ae_vector_init_copy(&dst->cdtmp, &src->cdtmp, _state, make_automatic); - ae_vector_init_copy(&dst->corrtmp, &src->corrtmp, _state, make_automatic); - ae_vector_init_copy(&dst->unitdiagonal, &src->unitdiagonal, _state, make_automatic); - _snnlssolver_init_copy(&dst->solver, &src->solver, _state, make_automatic); - ae_vector_init_copy(&dst->scntmp, &src->scntmp, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->tmpfeas, &src->tmpfeas, _state, make_automatic); - ae_matrix_init_copy(&dst->tmpm0, &src->tmpm0, _state, make_automatic); - ae_vector_init_copy(&dst->rctmps, &src->rctmps, _state, make_automatic); - ae_vector_init_copy(&dst->rctmpg, &src->rctmpg, _state, make_automatic); - ae_vector_init_copy(&dst->rctmprightpart, &src->rctmprightpart, _state, make_automatic); - ae_matrix_init_copy(&dst->rctmpdense0, &src->rctmpdense0, _state, make_automatic); - ae_matrix_init_copy(&dst->rctmpdense1, &src->rctmpdense1, _state, make_automatic); - ae_vector_init_copy(&dst->rctmpisequality, &src->rctmpisequality, _state, make_automatic); - ae_vector_init_copy(&dst->rctmpconstraintidx, &src->rctmpconstraintidx, _state, make_automatic); - ae_vector_init_copy(&dst->rctmplambdas, &src->rctmplambdas, _state, make_automatic); - ae_matrix_init_copy(&dst->tmpbasis, &src->tmpbasis, _state, make_automatic); - ae_vector_init_copy(&dst->tmpnormestimates, &src->tmpnormestimates, _state, make_automatic); - ae_vector_init_copy(&dst->tmpreciph, &src->tmpreciph, _state, make_automatic); - ae_vector_init_copy(&dst->tmpprodp, &src->tmpprodp, _state, make_automatic); - ae_vector_init_copy(&dst->tmpprods, &src->tmpprods, _state, make_automatic); - ae_vector_init_copy(&dst->tmpcp, &src->tmpcp, _state, make_automatic); - ae_vector_init_copy(&dst->tmpcs, &src->tmpcs, _state, make_automatic); - ae_vector_init_copy(&dst->tmpci, &src->tmpci, _state, make_automatic); -} - - -void _sactiveset_clear(void* _p) -{ - sactiveset *p = (sactiveset*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->xc); - ae_vector_clear(&p->s); - ae_vector_clear(&p->h); - ae_vector_clear(&p->cstatus); - ae_matrix_clear(&p->sdensebatch); - ae_matrix_clear(&p->pdensebatch); - ae_matrix_clear(&p->idensebatch); - ae_vector_clear(&p->sparsebatch); - ae_vector_clear(&p->hasbndl); - ae_vector_clear(&p->hasbndu); - ae_vector_clear(&p->bndl); - ae_vector_clear(&p->bndu); - ae_matrix_clear(&p->cleic); - ae_vector_clear(&p->mtnew); - ae_vector_clear(&p->mtx); - ae_vector_clear(&p->mtas); - ae_vector_clear(&p->cdtmp); - ae_vector_clear(&p->corrtmp); - ae_vector_clear(&p->unitdiagonal); - _snnlssolver_clear(&p->solver); - ae_vector_clear(&p->scntmp); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->tmpfeas); - ae_matrix_clear(&p->tmpm0); - ae_vector_clear(&p->rctmps); - ae_vector_clear(&p->rctmpg); - ae_vector_clear(&p->rctmprightpart); - ae_matrix_clear(&p->rctmpdense0); - ae_matrix_clear(&p->rctmpdense1); - ae_vector_clear(&p->rctmpisequality); - ae_vector_clear(&p->rctmpconstraintidx); - ae_vector_clear(&p->rctmplambdas); - ae_matrix_clear(&p->tmpbasis); - ae_vector_clear(&p->tmpnormestimates); - ae_vector_clear(&p->tmpreciph); - ae_vector_clear(&p->tmpprodp); - ae_vector_clear(&p->tmpprods); - ae_vector_clear(&p->tmpcp); - ae_vector_clear(&p->tmpcs); - ae_vector_clear(&p->tmpci); -} - - -void _sactiveset_destroy(void* _p) -{ - sactiveset *p = (sactiveset*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->xc); - ae_vector_destroy(&p->s); - ae_vector_destroy(&p->h); - ae_vector_destroy(&p->cstatus); - ae_matrix_destroy(&p->sdensebatch); - ae_matrix_destroy(&p->pdensebatch); - ae_matrix_destroy(&p->idensebatch); - ae_vector_destroy(&p->sparsebatch); - ae_vector_destroy(&p->hasbndl); - ae_vector_destroy(&p->hasbndu); - ae_vector_destroy(&p->bndl); - ae_vector_destroy(&p->bndu); - ae_matrix_destroy(&p->cleic); - ae_vector_destroy(&p->mtnew); - ae_vector_destroy(&p->mtx); - ae_vector_destroy(&p->mtas); - ae_vector_destroy(&p->cdtmp); - ae_vector_destroy(&p->corrtmp); - ae_vector_destroy(&p->unitdiagonal); - _snnlssolver_destroy(&p->solver); - ae_vector_destroy(&p->scntmp); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->tmpfeas); - ae_matrix_destroy(&p->tmpm0); - ae_vector_destroy(&p->rctmps); - ae_vector_destroy(&p->rctmpg); - ae_vector_destroy(&p->rctmprightpart); - ae_matrix_destroy(&p->rctmpdense0); - ae_matrix_destroy(&p->rctmpdense1); - ae_vector_destroy(&p->rctmpisequality); - ae_vector_destroy(&p->rctmpconstraintidx); - ae_vector_destroy(&p->rctmplambdas); - ae_matrix_destroy(&p->tmpbasis); - ae_vector_destroy(&p->tmpnormestimates); - ae_vector_destroy(&p->tmpreciph); - ae_vector_destroy(&p->tmpprodp); - ae_vector_destroy(&p->tmpprods); - ae_vector_destroy(&p->tmpcp); - ae_vector_destroy(&p->tmpcs); - ae_vector_destroy(&p->tmpci); -} - - -#endif -#if defined(AE_COMPILE_QQPSOLVER) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function initializes QQPSettings structure with default settings. - -Newly created structure MUST be initialized by default settings - or by -copy of the already initialized structure. - - -- ALGLIB -- - Copyright 14.05.2011 by Bochkanov Sergey -*************************************************************************/ -void qqploaddefaults(ae_int_t n, qqpsettings* s, ae_state *_state) -{ - - - s->epsg = 0.0; - s->epsf = 0.0; - s->epsx = 1.0E-6; - s->maxouterits = 0; - s->cgphase = ae_true; - s->cnphase = ae_true; - s->cgminits = 5; - s->cgmaxits = ae_maxint(s->cgminits, ae_round(1+0.33*n, _state), _state); - s->sparsesolver = 0; - s->cnmaxupdates = ae_round(1+0.1*n, _state); -} - - -/************************************************************************* -This function initializes QQPSettings structure with copy of another, -already initialized structure. - - -- ALGLIB -- - Copyright 14.05.2011 by Bochkanov Sergey -*************************************************************************/ -void qqpcopysettings(qqpsettings* src, qqpsettings* dst, ae_state *_state) -{ - - - dst->epsg = src->epsg; - dst->epsf = src->epsf; - dst->epsx = src->epsx; - dst->maxouterits = src->maxouterits; - dst->cgphase = src->cgphase; - dst->cnphase = src->cnphase; - dst->cgminits = src->cgminits; - dst->cgmaxits = src->cgmaxits; - dst->sparsesolver = src->sparsesolver; - dst->cnmaxupdates = src->cnmaxupdates; -} - - -/************************************************************************* -This function performs preallocation of internal 2D matrices. If matrix -size is less than expected, we grow to some larger value (specified by user). - -It can be useful in cases when we solve many subsequent QP problems with -increasing sizes - helps to avoid multiple allocations. - -INPUT PARAMETERS: - SState - object which stores temporaries: - * uninitialized object is automatically initialized - * previously allocated memory is reused as much - as possible - NExpected - if internal buffers have size enough for NExpected, - no preallocation happens. If size is less than NExpected, - buffers are preallocated up to NGrowTo*NGrowTo - NGrowTo - new size - - -OUTPUT PARAMETERS: - SState - temporary buffers, some of them are preallocated - - -- ALGLIB -- - Copyright 09.10.2017 by Bochkanov Sergey -*************************************************************************/ -void qqppreallocategrowdense(qqpbuffers* sstate, - ae_int_t nexpected, - ae_int_t ngrowto, - ae_state *_state) -{ - - - if( sstate->densea.rowsdensea.colsdensea, ngrowto, ngrowto, _state); - } - if( sstate->densez.rowsdensez.colsdensez, ngrowto, ngrowto, _state); - } -} - - -/************************************************************************* -This function runs QQP solver; it returns after optimization process was -completed. Following QP problem is solved: - - min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin)) - -subject to boundary constraints. - -IMPORTANT: UNLIKE MANY OTHER SOLVERS, THIS FUNCTION DOES NOT REQUIRE YOU - TO INITIALIZE STATE OBJECT. IT CAN BE AUTOMATICALLY INITIALIZED - DURING SOLUTION PROCESS. - -INPUT PARAMETERS: - AC - for dense problems given by CQM model (AKind=0) A-term - of CQM object contains system matrix. Other terms are - unspecified and should not be referenced. - SparseAC - for sparse problems (AKind=1) - DenseAC - for traditional dense matrices (AKind=2) - AKind - matrix term to use: - * 0 for dense CQM (CQMAC) - * 1 for sparse matrix (SparseAC) - * 2 for dense matrix (DenseAC) - IsUpper - which triangle of SparseAC/DenseAC stores matrix - - upper or lower one (for dense matrices this parameter - is not actual). - BC - linear term, array[NC] - BndLC - lower bound, array[NC] - BndUC - upper bound, array[NC] - SC - scale vector, array[NC]: - * I-th element contains scale of I-th variable, - * SC[I]>0 - XOriginC - origin term, array[NC]. Can be zero. - NC - number of variables in the original formulation (no - slack variables). - CLEICC - linear equality/inequality constraints. Present version - of this function does NOT provide publicly available - support for linear constraints. This feature will be - introduced in the future versions of the function. - NEC, NIC - number of equality/inequality constraints. - MUST BE ZERO IN THE CURRENT VERSION!!! - Settings - QQPSettings object initialized by one of the initialization - functions. - SState - object which stores temporaries: - * uninitialized object is automatically initialized - * previously allocated memory is reused as much - as possible - XS - initial point, array[NC] - - -OUTPUT PARAMETERS: - XS - last point - TerminationType-termination type: - * - * - * - - -- ALGLIB -- - Copyright 14.05.2011 by Bochkanov Sergey -*************************************************************************/ -void qqpoptimize(convexquadraticmodel* cqmac, - sparsematrix* sparseac, - /* Real */ ae_matrix* denseac, - ae_int_t akind, - ae_bool isupper, - /* Real */ ae_vector* bc, - /* Real */ ae_vector* bndlc, - /* Real */ ae_vector* bnduc, - /* Real */ ae_vector* sc, - /* Real */ ae_vector* xoriginc, - ae_int_t nc, - qqpsettings* settings, - qqpbuffers* sstate, - /* Real */ ae_vector* xs, - ae_int_t* terminationtype, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double vv; - double d2; - double d1; - ae_int_t d1est; - ae_int_t d2est; - ae_bool needact; - double reststp; - double fullstp; - double stpmax; - double stp; - ae_int_t stpcnt; - ae_int_t cidx; - double cval; - ae_int_t cgcnt; - ae_int_t cgmax; - ae_int_t newtcnt; - ae_int_t sparsesolver; - double beta; - ae_bool b; - double fprev; - double fcur; - ae_bool problemsolved; - ae_bool isconstrained; - double f0; - double f1; - - *terminationtype = 0; - - - /* - * Primary checks - */ - ae_assert((akind==0||akind==1)||akind==2, "QQPOptimize: incorrect AKind", _state); - sstate->n = nc; - n = sstate->n; - *terminationtype = 0; - sstate->repinneriterationscount = 0; - sstate->repouteriterationscount = 0; - sstate->repncholesky = 0; - sstate->repncupdates = 0; - - /* - * Several checks - * * matrix size - * * scale vector - * * consistency of bound constraints - * * consistency of settings - */ - if( akind==1 ) - { - ae_assert(sparsegetnrows(sparseac, _state)==n, "QQPOptimize: rows(SparseAC)<>N", _state); - ae_assert(sparsegetncols(sparseac, _state)==n, "QQPOptimize: cols(SparseAC)<>N", _state); - } - for(i=0; i<=n-1; i++) - { - ae_assert(ae_isfinite(sc->ptr.p_double[i], _state)&&ae_fp_greater(sc->ptr.p_double[i],(double)(0)), "QQPOptimize: incorrect scale", _state); - } - for(i=0; i<=n-1; i++) - { - if( ae_isfinite(bndlc->ptr.p_double[i], _state)&&ae_isfinite(bnduc->ptr.p_double[i], _state) ) - { - if( ae_fp_greater(bndlc->ptr.p_double[i],bnduc->ptr.p_double[i]) ) - { - *terminationtype = -3; - return; - } - } - } - ae_assert(settings->cgphase||settings->cnphase, "QQPOptimize: both phases (CG and Newton) are inactive", _state); - - /* - * Allocate data structures - */ - rvectorsetlengthatleast(&sstate->bndl, n, _state); - rvectorsetlengthatleast(&sstate->bndu, n, _state); - bvectorsetlengthatleast(&sstate->havebndl, n, _state); - bvectorsetlengthatleast(&sstate->havebndu, n, _state); - rvectorsetlengthatleast(&sstate->xs, n, _state); - rvectorsetlengthatleast(&sstate->xf, n, _state); - rvectorsetlengthatleast(&sstate->xp, n, _state); - rvectorsetlengthatleast(&sstate->gc, n, _state); - rvectorsetlengthatleast(&sstate->cgc, n, _state); - rvectorsetlengthatleast(&sstate->cgp, n, _state); - rvectorsetlengthatleast(&sstate->dc, n, _state); - rvectorsetlengthatleast(&sstate->dp, n, _state); - rvectorsetlengthatleast(&sstate->tmp0, n, _state); - rvectorsetlengthatleast(&sstate->tmp1, n, _state); - rvectorsetlengthatleast(&sstate->stpbuf, 15, _state); - sasinit(n, &sstate->sas, _state); - - /* - * Scale/shift problem coefficients: - * - * min { 0.5*(x-x0)'*A*(x-x0) + b'*(x-x0) } - * - * becomes (after transformation "x = S*y+x0") - * - * min { 0.5*y'*(S*A*S)*y + (S*b)'*y - * - * Modified A_mod=S*A*S and b_mod=S*(b+A*x0) are - * stored into SState.DenseA and SState.B. - * - */ - rvectorsetlengthatleast(&sstate->b, n, _state); - for(i=0; i<=n-1; i++) - { - sstate->b.ptr.p_double[i] = sc->ptr.p_double[i]*bc->ptr.p_double[i]; - } - sstate->akind = -99; - if( akind==0 ) - { - - /* - * Dense QP problem - just copy and scale. - */ - rmatrixsetlengthatleast(&sstate->densea, n, n, _state); - cqmgeta(cqmac, &sstate->densea, _state); - sstate->akind = 0; - sstate->absamax = (double)(0); - sstate->absasum = (double)(0); - sstate->absasum2 = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = sc->ptr.p_double[i]*sstate->densea.ptr.pp_double[i][j]*sc->ptr.p_double[j]; - vv = ae_fabs(v, _state); - sstate->densea.ptr.pp_double[i][j] = v; - sstate->absamax = ae_maxreal(sstate->absamax, vv, _state); - sstate->absasum = sstate->absasum+vv; - sstate->absasum2 = sstate->absasum2+vv*vv; - } - } - } - if( akind==1 ) - { - - /* - * Sparse QP problem - a bit tricky. Depending on format of the - * input we use different strategies for copying matrix: - * * SKS matrices are copied to SKS format - * * anything else is copied to CRS format - */ - sparsecopytosksbuf(sparseac, &sstate->sparsea, _state); - if( isupper ) - { - sparsetransposesks(&sstate->sparsea, _state); - } - sstate->akind = 1; - sstate->sparseupper = ae_false; - sstate->absamax = (double)(0); - sstate->absasum = (double)(0); - sstate->absasum2 = (double)(0); - for(i=0; i<=n-1; i++) - { - k = sstate->sparsea.ridx.ptr.p_int[i]; - for(j=i-sstate->sparsea.didx.ptr.p_int[i]; j<=i; j++) - { - v = sc->ptr.p_double[i]*sstate->sparsea.vals.ptr.p_double[k]*sc->ptr.p_double[j]; - vv = ae_fabs(v, _state); - sstate->sparsea.vals.ptr.p_double[k] = v; - if( i==j ) - { - - /* - * Diagonal terms are counted only once - */ - sstate->absamax = ae_maxreal(sstate->absamax, vv, _state); - sstate->absasum = sstate->absasum+vv; - sstate->absasum2 = sstate->absasum2+vv*vv; - } - else - { - - /* - * Offdiagonal terms are counted twice - */ - sstate->absamax = ae_maxreal(sstate->absamax, vv, _state); - sstate->absasum = sstate->absasum+2*vv; - sstate->absasum2 = sstate->absasum2+2*vv*vv; - } - k = k+1; - } - } - } - if( akind==2 ) - { - - /* - * Dense QP problem - just copy and scale. - */ - rmatrixsetlengthatleast(&sstate->densea, n, n, _state); - sstate->akind = 0; - sstate->absamax = (double)(0); - sstate->absasum = (double)(0); - sstate->absasum2 = (double)(0); - if( isupper ) - { - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - v = sc->ptr.p_double[i]*denseac->ptr.pp_double[i][j]*sc->ptr.p_double[j]; - vv = ae_fabs(v, _state); - sstate->densea.ptr.pp_double[i][j] = v; - sstate->densea.ptr.pp_double[j][i] = v; - if( ae_fp_eq((double)(i),v) ) - { - k = 1; - } - else - { - k = 2; - } - sstate->absamax = ae_maxreal(sstate->absamax, vv, _state); - sstate->absasum = sstate->absasum+vv*k; - sstate->absasum2 = sstate->absasum2+vv*vv*k; - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i; j++) - { - v = sc->ptr.p_double[i]*denseac->ptr.pp_double[i][j]*sc->ptr.p_double[j]; - vv = ae_fabs(v, _state); - sstate->densea.ptr.pp_double[i][j] = v; - sstate->densea.ptr.pp_double[j][i] = v; - if( ae_fp_eq((double)(i),v) ) - { - k = 1; - } - else - { - k = 2; - } - sstate->absamax = ae_maxreal(sstate->absamax, vv, _state); - sstate->absasum = sstate->absasum+vv*k; - sstate->absasum2 = sstate->absasum2+vv*vv*k; - } - } - } - } - ae_assert(sstate->akind>=0, "QQP: integrity check failed", _state); - - /* - * Load box constraints into State structure. - * - * We apply transformation to variables: y=(x-x_origin)/s, - * each of the constraints is appropriately shifted/scaled. - */ - for(i=0; i<=n-1; i++) - { - sstate->havebndl.ptr.p_bool[i] = ae_isfinite(bndlc->ptr.p_double[i], _state); - if( sstate->havebndl.ptr.p_bool[i] ) - { - sstate->bndl.ptr.p_double[i] = (bndlc->ptr.p_double[i]-xoriginc->ptr.p_double[i])/sc->ptr.p_double[i]; - } - else - { - ae_assert(ae_isneginf(bndlc->ptr.p_double[i], _state), "QQPOptimize: incorrect lower bound", _state); - sstate->bndl.ptr.p_double[i] = _state->v_neginf; - } - sstate->havebndu.ptr.p_bool[i] = ae_isfinite(bnduc->ptr.p_double[i], _state); - if( sstate->havebndu.ptr.p_bool[i] ) - { - sstate->bndu.ptr.p_double[i] = (bnduc->ptr.p_double[i]-xoriginc->ptr.p_double[i])/sc->ptr.p_double[i]; - } - else - { - ae_assert(ae_isposinf(bnduc->ptr.p_double[i], _state), "QQPOptimize: incorrect upper bound", _state); - sstate->bndu.ptr.p_double[i] = _state->v_posinf; - } - } - - /* - * Process initial point: - * * set it to XS-XOriginC - * * make sure that boundary constraints are preserved by transformation - */ - for(i=0; i<=n-1; i++) - { - sstate->xs.ptr.p_double[i] = (xs->ptr.p_double[i]-xoriginc->ptr.p_double[i])/sc->ptr.p_double[i]; - if( sstate->havebndl.ptr.p_bool[i]&&ae_fp_less(sstate->xs.ptr.p_double[i],sstate->bndl.ptr.p_double[i]) ) - { - sstate->xs.ptr.p_double[i] = sstate->bndl.ptr.p_double[i]; - } - if( sstate->havebndu.ptr.p_bool[i]&&ae_fp_greater(sstate->xs.ptr.p_double[i],sstate->bndu.ptr.p_double[i]) ) - { - sstate->xs.ptr.p_double[i] = sstate->bndu.ptr.p_double[i]; - } - if( sstate->havebndl.ptr.p_bool[i]&&ae_fp_eq(xs->ptr.p_double[i],bndlc->ptr.p_double[i]) ) - { - sstate->xs.ptr.p_double[i] = sstate->bndl.ptr.p_double[i]; - } - if( sstate->havebndu.ptr.p_bool[i]&&ae_fp_eq(xs->ptr.p_double[i],bnduc->ptr.p_double[i]) ) - { - sstate->xs.ptr.p_double[i] = sstate->bndu.ptr.p_double[i]; - } - } - - /* - * Select sparse direct solver - */ - if( akind==1 ) - { - sparsesolver = settings->sparsesolver; - if( sparsesolver==0 ) - { - sparsesolver = 1; - } - if( sparseissks(&sstate->sparsea, _state) ) - { - sparsesolver = 2; - } - sparsesolver = 2; - ae_assert(sparsesolver==1||sparsesolver==2, "QQPOptimize: incorrect SparseSolver", _state); - } - else - { - sparsesolver = 0; - } - - /* - * For unconstrained problems - try to use fast approach which requires - * just one unregularized Cholesky decomposition for solution. If it fails, - * switch to general QQP code. - */ - problemsolved = ae_false; - isconstrained = ae_false; - for(i=0; i<=n-1; i++) - { - isconstrained = (isconstrained||sstate->havebndl.ptr.p_bool[i])||sstate->havebndu.ptr.p_bool[i]; - } - if( (!isconstrained&&settings->cnphase)&&akind==0 ) - { - rmatrixsetlengthatleast(&sstate->densez, n, n, _state); - rvectorsetlengthatleast(&sstate->tmpcn, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - sstate->densez.ptr.pp_double[i][j] = sstate->densea.ptr.pp_double[i][j]; - } - } - inc(&sstate->repncholesky, _state); - if( spdmatrixcholeskyrec(&sstate->densez, 0, n, ae_true, &sstate->tmpcn, _state) ) - { - ae_v_move(&sstate->xf.ptr.p_double[0], 1, &sstate->xs.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - sstate->dc.ptr.p_double[i] = (double)(0); - } - f0 = qqpsolver_projectedtargetfunction(sstate, &sstate->xf, &sstate->dc, 0.0, &sstate->tmpcn, &sstate->tmp1, _state); - for(k=0; k<=3; k++) - { - rmatrixmv(n, n, &sstate->densea, 0, 0, 0, &sstate->xf, 0, &sstate->gc, 0, _state); - ae_v_add(&sstate->gc.ptr.p_double[0], 1, &sstate->b.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - sstate->dc.ptr.p_double[i] = -sstate->gc.ptr.p_double[i]; - } - fblscholeskysolve(&sstate->densez, 1.0, n, ae_true, &sstate->dc, &sstate->tmpcn, _state); - f1 = qqpsolver_projectedtargetfunction(sstate, &sstate->xf, &sstate->dc, 1.0, &sstate->tmpcn, &sstate->tmp1, _state); - if( ae_fp_greater_eq(f1,f0) ) - { - break; - } - ae_v_add(&sstate->xf.ptr.p_double[0], 1, &sstate->dc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - f0 = f1; - } - *terminationtype = 2; - problemsolved = ae_true; - } - } - - /* - * Attempt to solve problem with fast approach failed, use generic QQP - */ - if( !problemsolved ) - { - - /* - * Prepare "active set" structure - */ - sassetbc(&sstate->sas, &sstate->bndl, &sstate->bndu, _state); - if( !sasstartoptimization(&sstate->sas, &sstate->xs, _state) ) - { - *terminationtype = -3; - return; - } - - /* - * Main loop. - * - * Following variables are used: - * * GC stores current gradient (unconstrained) - * * CGC stores current gradient (constrained) - * * DC stores current search direction - * * CGP stores constrained gradient at previous point - * (zero on initial entry) - * * DP stores previous search direction - * (zero on initial entry) - */ - cgmax = settings->cgminits; - sstate->repinneriterationscount = 0; - sstate->repouteriterationscount = 0; - for(;;) - { - if( settings->maxouterits>0&&sstate->repouteriterationscount>=settings->maxouterits ) - { - *terminationtype = 5; - break; - } - if( sstate->repouteriterationscount>0 ) - { - - /* - * Check EpsF- and EpsX-based stopping criteria. - * Because problem was already scaled, we do not scale step before checking its length. - * NOTE: these checks are performed only after at least one outer iteration was made. - */ - if( ae_fp_greater(settings->epsf,(double)(0)) ) - { - - /* - * NOTE 1: here we rely on the fact that ProjectedTargetFunction() ignore D when Stp=0 - * NOTE 2: code below handles situation when update increases function value instead - * of decreasing it. - */ - fprev = qqpsolver_projectedtargetfunction(sstate, &sstate->xp, &sstate->dc, 0.0, &sstate->tmp0, &sstate->tmp1, _state); - fcur = qqpsolver_projectedtargetfunction(sstate, &sstate->sas.xc, &sstate->dc, 0.0, &sstate->tmp0, &sstate->tmp1, _state); - if( ae_fp_less_eq(fprev-fcur,settings->epsf*ae_maxreal(ae_fabs(fprev, _state), ae_maxreal(ae_fabs(fcur, _state), 1.0, _state), _state)) ) - { - *terminationtype = 1; - break; - } - } - if( ae_fp_greater(settings->epsx,(double)(0)) ) - { - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(sstate->xp.ptr.p_double[i]-sstate->sas.xc.ptr.p_double[i], _state); - } - if( ae_fp_less_eq(ae_sqrt(v, _state),settings->epsx) ) - { - *terminationtype = 2; - break; - } - } - } - inc(&sstate->repouteriterationscount, _state); - ae_v_move(&sstate->xp.ptr.p_double[0], 1, &sstate->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( !settings->cgphase ) - { - cgmax = 0; - } - for(i=0; i<=n-1; i++) - { - sstate->cgp.ptr.p_double[i] = 0.0; - sstate->dp.ptr.p_double[i] = 0.0; - } - for(cgcnt=0; cgcnt<=cgmax-1; cgcnt++) - { - - /* - * Calculate unconstrained gradient GC for "extended" QP problem - * Determine active set, current constrained gradient CGC. - * Check gradient-based stopping condition. - * - * NOTE: because problem was scaled, we do not have to apply scaling - * to gradient before checking stopping condition. - */ - qqpsolver_targetgradient(sstate, &sstate->sas.xc, &sstate->gc, _state); - sasreactivateconstraints(&sstate->sas, &sstate->gc, _state); - ae_v_move(&sstate->cgc.ptr.p_double[0], 1, &sstate->gc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - sasconstraineddirection(&sstate->sas, &sstate->cgc, _state); - v = ae_v_dotproduct(&sstate->cgc.ptr.p_double[0], 1, &sstate->cgc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( ae_fp_less_eq(ae_sqrt(v, _state),settings->epsg) ) - { - *terminationtype = 4; - break; - } - - /* - * Prepare search direction DC and explore it. - * - * We try to use CGP/DP to prepare conjugate gradient step, - * but we resort to steepest descent step (Beta=0) in case - * we are at I-th boundary, but DP[I]<>0. - * - * Such approach allows us to ALWAYS have feasible DC, with - * guaranteed compatibility with both feasible area and current - * active set. - * - * Automatic CG reset performed every time DP is incompatible - * with current active set and/or feasible area. We also - * perform reset every QuickQPRestartCG iterations. - */ - ae_v_moveneg(&sstate->dc.ptr.p_double[0], 1, &sstate->cgc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = 0.0; - vv = 0.0; - b = ae_false; - for(i=0; i<=n-1; i++) - { - v = v+sstate->cgc.ptr.p_double[i]*sstate->cgc.ptr.p_double[i]; - vv = vv+sstate->cgp.ptr.p_double[i]*sstate->cgp.ptr.p_double[i]; - b = b||((sstate->havebndl.ptr.p_bool[i]&&ae_fp_eq(sstate->sas.xc.ptr.p_double[i],sstate->bndl.ptr.p_double[i]))&&ae_fp_neq(sstate->dp.ptr.p_double[i],(double)(0))); - b = b||((sstate->havebndu.ptr.p_bool[i]&&ae_fp_eq(sstate->sas.xc.ptr.p_double[i],sstate->bndu.ptr.p_double[i]))&&ae_fp_neq(sstate->dp.ptr.p_double[i],(double)(0))); - } - b = b||ae_fp_eq(vv,(double)(0)); - b = b||cgcnt%qqpsolver_quickqprestartcg==0; - if( !b ) - { - beta = v/vv; - } - else - { - beta = 0.0; - } - ae_v_addd(&sstate->dc.ptr.p_double[0], 1, &sstate->dp.ptr.p_double[0], 1, ae_v_len(0,n-1), beta); - sasconstraineddirection(&sstate->sas, &sstate->dc, _state); - sasexploredirection(&sstate->sas, &sstate->dc, &stpmax, &cidx, &cval, _state); - - /* - * Build quadratic model of F along descent direction: - * - * F(xc+alpha*D) = D2*alpha^2 + D1*alpha - * - * Terminate algorithm if needed. - * - * NOTE: we do not maintain constant term D0 - */ - qqpsolver_quadraticmodel(sstate, &sstate->sas.xc, &sstate->dc, &sstate->gc, &d1, &d1est, &d2, &d2est, &sstate->tmp0, _state); - if( ae_fp_eq(d1,(double)(0))&&ae_fp_eq(d2,(double)(0)) ) - { - - /* - * D1 and D2 are exactly zero, success. - * After this if-then we assume that D is non-zero. - */ - *terminationtype = 4; - break; - } - if( d1est>=0 ) - { - - /* - * Numerical noise is too large, it means that we are close - * to minimum - and that further improvement is impossible. - * - * After this if-then we assume that D1 is definitely negative - * (even under presence of numerical errors). - */ - *terminationtype = 7; - break; - } - if( d2est<=0&&cidx<0 ) - { - - /* - * Function is unbounded from below: - * * D1<0 (verified by previous block) - * * D2Est<=0, which means that either D2<0 - or it can not - * be reliably distinguished from zero. - * * step is unconstrained - * - * If these conditions are true, we abnormally terminate QP - * algorithm with return code -4 - */ - *terminationtype = -4; - break; - } - - /* - * Perform step along DC. - * - * In this block of code we maintain two step length: - * * RestStp - restricted step, maximum step length along DC which does - * not violate constraints - * * FullStp - step length along DC which minimizes quadratic function - * without taking constraints into account. If problem is - * unbounded from below without constraints, FullStp is - * forced to be RestStp. - * - * So, if function is convex (D2>0): - * * FullStp = -D1/(2*D2) - * * RestStp = restricted FullStp - * * 0<=RestStp<=FullStp - * - * If function is non-convex, but bounded from below under constraints: - * * RestStp = step length subject to constraints - * * FullStp = RestStp - * - * After RestStp and FullStp are initialized, we generate several trial - * steps which are different multiples of RestStp and FullStp. - */ - if( d2est>0 ) - { - ae_assert(ae_fp_less(d1,(double)(0)), "QQPOptimize: internal error", _state); - fullstp = -d1/(2*d2); - needact = ae_fp_greater_eq(fullstp,stpmax); - if( needact ) - { - ae_assert(sstate->stpbuf.cnt>=3, "QQPOptimize: StpBuf overflow", _state); - reststp = stpmax; - stp = reststp; - sstate->stpbuf.ptr.p_double[0] = reststp*4; - sstate->stpbuf.ptr.p_double[1] = fullstp; - sstate->stpbuf.ptr.p_double[2] = fullstp/4; - stpcnt = 3; - } - else - { - reststp = fullstp; - stp = fullstp; - stpcnt = 0; - } - } - else - { - ae_assert(cidx>=0, "QQPOptimize: internal error", _state); - ae_assert(sstate->stpbuf.cnt>=2, "QQPOptimize: StpBuf overflow", _state); - reststp = stpmax; - fullstp = stpmax; - stp = reststp; - needact = ae_true; - sstate->stpbuf.ptr.p_double[0] = 4*reststp; - stpcnt = 1; - } - qqpsolver_findbeststepandmove(sstate, &sstate->sas, &sstate->dc, stp, needact, cidx, cval, &sstate->stpbuf, stpcnt, &sstate->activated, &sstate->tmp0, &sstate->tmp1, _state); - - /* - * Update CG information. - */ - ae_v_move(&sstate->dp.ptr.p_double[0], 1, &sstate->dc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&sstate->cgp.ptr.p_double[0], 1, &sstate->cgc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - - /* - * Update iterations counter - */ - sstate->repinneriterationscount = sstate->repinneriterationscount+1; - } - if( *terminationtype!=0 ) - { - break; - } - cgmax = settings->cgmaxits; - - /* - * Generate YIdx - reordering of variables for constrained Newton phase. - * Free variables come first, fixed are last ones. - */ - newtcnt = 0; - for(;;) - { - - /* - * Skip iteration if constrained Newton is turned off. - */ - if( !settings->cnphase ) - { - break; - } - - /* - * At the first iteration - build Cholesky decomposition of Hessian. - * At subsequent iterations - refine Hessian by adding new constraints. - * - * Loop is terminated in following cases: - * * Hessian is not positive definite subject to current constraints - * (termination during initial decomposition) - * * there were no new constraints being activated - * (termination during update) - * * all constraints were activated during last step - * (termination during update) - * * CNMaxUpdates were performed on matrix - * (termination during update) - */ - if( newtcnt==0 ) - { - - /* - * Perform initial Newton step. If Cholesky decomposition fails, - * increase number of CG iterations to CGMaxIts - it should help - * us to find set of constraints which will make matrix positive - * definite. - */ - b = qqpsolver_cnewtonbuild(sstate, sparsesolver, &sstate->repncholesky, _state); - if( b ) - { - cgmax = settings->cgminits; - } - } - else - { - b = qqpsolver_cnewtonupdate(sstate, settings, &sstate->repncupdates, _state); - } - if( !b ) - { - break; - } - inc(&newtcnt, _state); - - /* - * Calculate gradient GC. - */ - qqpsolver_targetgradient(sstate, &sstate->sas.xc, &sstate->gc, _state); - - /* - * Bound-constrained Newton step - */ - for(i=0; i<=n-1; i++) - { - sstate->dc.ptr.p_double[i] = sstate->gc.ptr.p_double[i]; - } - if( !qqpsolver_cnewtonstep(sstate, settings, &sstate->dc, _state) ) - { - break; - } - qqpsolver_quadraticmodel(sstate, &sstate->sas.xc, &sstate->dc, &sstate->gc, &d1, &d1est, &d2, &d2est, &sstate->tmp0, _state); - if( d1est>=0 ) - { - - /* - * We are close to minimum, derivative is nearly zero, break Newton iteration - */ - break; - } - if( d2est>0 ) - { - - /* - * Positive definite matrix, we can perform Newton step - */ - ae_assert(ae_fp_less(d1,(double)(0)), "QQPOptimize: internal error", _state); - fullstp = -d1/(2*d2); - sasexploredirection(&sstate->sas, &sstate->dc, &stpmax, &cidx, &cval, _state); - needact = ae_fp_greater_eq(fullstp,stpmax); - if( needact ) - { - ae_assert(sstate->stpbuf.cnt>=3, "QQPOptimize: StpBuf overflow", _state); - reststp = stpmax; - stp = reststp; - sstate->stpbuf.ptr.p_double[0] = reststp*4; - sstate->stpbuf.ptr.p_double[1] = fullstp; - sstate->stpbuf.ptr.p_double[2] = fullstp/4; - stpcnt = 3; - } - else - { - reststp = fullstp; - stp = fullstp; - stpcnt = 0; - } - qqpsolver_findbeststepandmove(sstate, &sstate->sas, &sstate->dc, stp, needact, cidx, cval, &sstate->stpbuf, stpcnt, &sstate->activated, &sstate->tmp0, &sstate->tmp1, _state); - } - else - { - - /* - * Matrix is semi-definite or indefinite, but regularized - * Cholesky succeeded and gave us descent direction in DC. - * - * We will investigate it and try to perform descent step: - * * first, we explore direction: - * * if it is unbounded, we stop algorithm with - * appropriate termination code -4. - * * if StpMax=0, we break Newton phase and return to - * CG phase - constraint geometry is complicated near - * current point, so it is better to use simpler algo. - * * second, we check that bounded step decreases function; - * if not, we again skip to CG phase - * * finally, we use FindBestStep...() function to choose - * between bounded step and projection of full-length step - * (latter may give additional decrease in - */ - sasexploredirection(&sstate->sas, &sstate->dc, &stpmax, &cidx, &cval, _state); - if( cidx<0 ) - { - - /* - * Function is unbounded from below: - * * D1<0 (verified by previous block) - * * D2Est<=0, which means that either D2<0 - or it can not - * be reliably distinguished from zero. - * * step is unconstrained - * - * If these conditions are true, we abnormally terminate QP - * algorithm with return code -4 - */ - *terminationtype = -4; - break; - } - if( ae_fp_eq(stpmax,(double)(0)) ) - { - - /* - * Resort to CG phase. - * Increase number of CG iterations. - */ - cgmax = settings->cgmaxits; - break; - } - ae_assert(ae_fp_greater(stpmax,(double)(0)), "QQPOptimize: internal error", _state); - f0 = qqpsolver_projectedtargetfunction(sstate, &sstate->sas.xc, &sstate->dc, 0.0, &sstate->tmp0, &sstate->tmp1, _state); - f1 = qqpsolver_projectedtargetfunction(sstate, &sstate->sas.xc, &sstate->dc, stpmax, &sstate->tmp0, &sstate->tmp1, _state); - if( ae_fp_greater_eq(f1,f0) ) - { - - /* - * Descent direction does not actually decrease function value. - * Resort to CG phase - * Increase number of CG iterations. - */ - cgmax = settings->cgmaxits; - break; - } - ae_assert(sstate->stpbuf.cnt>=3, "QQPOptimize: StpBuf overflow", _state); - reststp = stpmax; - stp = reststp; - sstate->stpbuf.ptr.p_double[0] = reststp*4; - sstate->stpbuf.ptr.p_double[1] = 1.00; - sstate->stpbuf.ptr.p_double[2] = 0.25; - stpcnt = 3; - qqpsolver_findbeststepandmove(sstate, &sstate->sas, &sstate->dc, stp, ae_true, cidx, cval, &sstate->stpbuf, stpcnt, &sstate->activated, &sstate->tmp0, &sstate->tmp1, _state); - } - } - if( *terminationtype!=0 ) - { - break; - } - } - sasstopoptimization(&sstate->sas, _state); - ae_v_move(&sstate->xf.ptr.p_double[0], 1, &sstate->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - } - - /* - * Stop optimization and unpack results. - * - * Add XOriginC to XS and make sure that boundary constraints are - * both (a) satisfied, (b) preserved. Former means that "shifted" - * point is feasible, while latter means that point which was exactly - * at the boundary before shift will be exactly at the boundary - * after shift. - */ - for(i=0; i<=n-1; i++) - { - xs->ptr.p_double[i] = sc->ptr.p_double[i]*sstate->xf.ptr.p_double[i]+xoriginc->ptr.p_double[i]; - if( sstate->havebndl.ptr.p_bool[i]&&ae_fp_less(xs->ptr.p_double[i],bndlc->ptr.p_double[i]) ) - { - xs->ptr.p_double[i] = bndlc->ptr.p_double[i]; - } - if( sstate->havebndu.ptr.p_bool[i]&&ae_fp_greater(xs->ptr.p_double[i],bnduc->ptr.p_double[i]) ) - { - xs->ptr.p_double[i] = bnduc->ptr.p_double[i]; - } - if( sstate->havebndl.ptr.p_bool[i]&&ae_fp_eq(sstate->xf.ptr.p_double[i],sstate->bndl.ptr.p_double[i]) ) - { - xs->ptr.p_double[i] = bndlc->ptr.p_double[i]; - } - if( sstate->havebndu.ptr.p_bool[i]&&ae_fp_eq(sstate->xf.ptr.p_double[i],sstate->bndu.ptr.p_double[i]) ) - { - xs->ptr.p_double[i] = bnduc->ptr.p_double[i]; - } - } -} - - -/************************************************************************* -Target function at point PROJ(X+Stp*D), where PROJ(.) is a projection into -feasible set. - -NOTE: if Stp=0, D is not referenced at all. Thus, there is no need to - fill it by some meaningful values for Stp=0. - -This subroutine uses temporary buffers Tmp0/1, which are automatically -resized if needed. - - -- ALGLIB -- - Copyright 21.12.2013 by Bochkanov Sergey -*************************************************************************/ -static double qqpsolver_projectedtargetfunction(qqpbuffers* sstate, - /* Real */ ae_vector* x, - /* Real */ ae_vector* d, - double stp, - /* Real */ ae_vector* tmp0, - /* Real */ ae_vector* tmp1, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - double v; - double result; - - - n = sstate->n; - rvectorsetlengthatleast(tmp0, n, _state); - rvectorsetlengthatleast(tmp1, n, _state); - - /* - * Calculate projected point - */ - for(i=0; i<=n-1; i++) - { - if( ae_fp_neq(stp,(double)(0)) ) - { - v = x->ptr.p_double[i]+stp*d->ptr.p_double[i]; - } - else - { - v = x->ptr.p_double[i]; - } - if( sstate->havebndl.ptr.p_bool[i]&&ae_fp_less(v,sstate->bndl.ptr.p_double[i]) ) - { - v = sstate->bndl.ptr.p_double[i]; - } - if( sstate->havebndu.ptr.p_bool[i]&&ae_fp_greater(v,sstate->bndu.ptr.p_double[i]) ) - { - v = sstate->bndu.ptr.p_double[i]; - } - tmp0->ptr.p_double[i] = v; - } - - /* - * Function value at the Tmp0: - * - * f(x) = 0.5*x'*A*x + b'*x - */ - result = 0.0; - for(i=0; i<=n-1; i++) - { - result = result+sstate->b.ptr.p_double[i]*tmp0->ptr.p_double[i]; - } - if( sstate->akind==0 ) - { - - /* - * Dense matrix A - */ - result = result+0.5*rmatrixsyvmv(n, &sstate->densea, 0, 0, ae_true, tmp0, 0, tmp1, _state); - } - else - { - - /* - * sparse matrix A - */ - ae_assert(sstate->akind==1, "QQPOptimize: unexpected AKind in ProjectedTargetFunction", _state); - result = result+0.5*sparsevsmv(&sstate->sparsea, sstate->sparseupper, tmp0, _state); - } - return result; -} - - -/************************************************************************* -Gradient of the target function: - - f(x) = 0.5*x'*A*x + b'*x - -which is equal to - - grad = A*x + b - -Here: -* x is array[N] -* A is array[N,N] -* b is array[N] - -INPUT PARAMETERS: - SState - structure which stores function terms (not modified) - X - location - G - possibly preallocated buffer - -OUTPUT PARAMETERS: - G - array[N], gradient - - -- ALGLIB -- - Copyright 21.12.2013 by Bochkanov Sergey -*************************************************************************/ -static void qqpsolver_targetgradient(qqpbuffers* sstate, - /* Real */ ae_vector* x, - /* Real */ ae_vector* g, - ae_state *_state) -{ - ae_int_t n; - - - n = sstate->n; - rvectorsetlengthatleast(g, n, _state); - if( sstate->akind==0 ) - { - - /* - * Dense matrix A - */ - rmatrixsymv(n, 1.0, &sstate->densea, 0, 0, ae_true, x, 0, 0.0, g, 0, _state); - } - else - { - - /* - * Sparse matrix A - */ - ae_assert(sstate->akind==1, "QQPOptimize: unexpected AKind in TargetGradient", _state); - sparsesmv(&sstate->sparsea, sstate->sparseupper, x, g, _state); - } - ae_v_add(&g->ptr.p_double[0], 1, &sstate->b.ptr.p_double[0], 1, ae_v_len(0,n-1)); -} - - -/************************************************************************* -First and second derivatives of the "extended" target function along -specified direction. Target function is called "extended" because of -additional slack variables and has form: - - f(x) = 0.5*x'*A*x + b'*x + penaltyfactor*0.5*(C*x-b)'*(C*x-b) - -with gradient - - grad = A*x + b + penaltyfactor*C'*(C*x-b) - -Quadratic model has form - - F(x0+alpha*D) = D2*alpha^2 + D1*alpha - -INPUT PARAMETERS: - SState - structure which is used to obtain quadratic term of the model - X - current point, array[N] - D - direction across which derivatives are calculated, array[N] - G - gradient at current point (pre-calculated by caller), array[N] - -OUTPUT PARAMETERS: - D1 - linear coefficient - D1Est - estimate of D1 sign, accounting for possible numerical - errors: - * >0 means "almost surely positive" - * <0 means "almost surely negative" - * =0 means "pessimistic estimate of numerical errors - in D1 is larger than magnitude of D1 itself; it is - impossible to reliably distinguish D1 from zero". - D2 - quadratic coefficient - D2Est - estimate of D2 sign, accounting for possible numerical - errors: - * >0 means "almost surely positive" - * <0 means "almost surely negative" - * =0 means "pessimistic estimate of numerical errors - in D2 is larger than magnitude of D2 itself; it is - impossible to reliably distinguish D2 from zero". - - -- ALGLIB -- - Copyright 14.05.2014 by Bochkanov Sergey -*************************************************************************/ -static void qqpsolver_quadraticmodel(qqpbuffers* sstate, - /* Real */ ae_vector* x, - /* Real */ ae_vector* d, - /* Real */ ae_vector* g, - double* d1, - ae_int_t* d1est, - double* d2, - ae_int_t* d2est, - /* Real */ ae_vector* tmp0, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - double v; - double mx; - double mb; - double md; - - *d1 = 0; - *d1est = 0; - *d2 = 0; - *d2est = 0; - - n = sstate->n; - - /* - * Maximums - */ - mx = 0.0; - md = 0.0; - mb = 0.0; - for(i=0; i<=n-1; i++) - { - mx = ae_maxreal(mx, ae_fabs(x->ptr.p_double[i], _state), _state); - md = ae_maxreal(md, ae_fabs(d->ptr.p_double[i], _state), _state); - } - for(i=0; i<=n-1; i++) - { - mb = ae_maxreal(mb, ae_fabs(sstate->b.ptr.p_double[i], _state), _state); - } - - /* - * D2 - */ - if( sstate->akind==0 ) - { - - /* - * Dense matrix A - */ - *d2 = 0.5*rmatrixsyvmv(n, &sstate->densea, 0, 0, ae_true, d, 0, tmp0, _state); - } - else - { - - /* - * Sparse matrix A - */ - ae_assert(sstate->akind==1, "QQPOptimize: unexpected AKind in TargetGradient", _state); - *d2 = 0.5*sparsevsmv(&sstate->sparsea, sstate->sparseupper, d, _state); - } - v = ae_v_dotproduct(&d->ptr.p_double[0], 1, &g->ptr.p_double[0], 1, ae_v_len(0,n-1)); - *d1 = v; - - /* - * Error estimates - */ - estimateparabolicmodel(sstate->absasum, sstate->absasum2, mx, mb, md, *d1, *d2, d1est, d2est, _state); -} - - -/************************************************************************* -This function accepts quadratic model of the form - - f(x) = 0.5*x'*A*x + b'*x + penaltyfactor*0.5*(C*x-b)'*(C*x-b) - -and list of possible steps along direction D. It chooses best step (one -which achieves minimum value of the target function) and moves current -point (given by SAS object) to the new location. Step is bounded subject -to boundary constraints. - -Candidate steps are divided into two groups: -* "default" step, which is always performed when no candidate steps LONGER - THAN THE DEFAULT ONE is given. This candidate MUST reduce target - function value; it is responsibility of caller to provide default - candidate which reduces target function. -* "additional candidates", which may be shorter or longer than the default - step. Candidates which are shorter that the default step are ignored; - candidates which are longer than the "default" step are tested. - -The idea is that we ALWAYS try "default" step, and it is responsibility of -the caller to provide us with something which is worth trying. This step -may activate some constraint - that's why we stopped at "default" step -size. However, we may also try longer steps which may activate additional -constraints and further reduce function value. - -INPUT PARAMETERS: - SState - structure which stores model - SAS - active set structure which stores current point in SAS.XC - D - direction for step - Stp - step length for "default" candidate - NeedAct - whether default candidate activates some constraint; - if NeedAct is True, constraint given by CIdc/CVal is - GUARANTEED to be activated in the final point. - CIdx - if NeedAct is True, stores index of the constraint to activate - CVal - if NeedAct is True, stores constrained value; - SAS.XC[CIdx] is forced to be equal to CVal. - AddSteps- array[AddStepsCnt] of additional steps: - * AddSteps[]<=Stp are ignored - * AddSteps[]>Stp are tried - Activated- possibly preallocated buffer; previously allocated memory - will be reused. - Tmp0/1 - possibly preallocated buffers; previously allocated memory - will be reused. - -OUTPUT PARAMETERS: - SAS - SAS.XC is set to new point; if there was a constraint - specified by NeedAct/CIdx/CVal, it will be activated - (other constraints may be activated too, but this one is - guaranteed to be active in the final point). - Activated- elements of this array are set to True, if I-th constraint - as inactive at previous point, but become active in the - new one. - Situations when we deactivate xi>=0 and activate xi<=1 are - considered as activation of previously inactive constraint - - -- ALGLIB -- - Copyright 14.05.2014 by Bochkanov Sergey -*************************************************************************/ -static void qqpsolver_findbeststepandmove(qqpbuffers* sstate, - sactiveset* sas, - /* Real */ ae_vector* d, - double stp, - ae_bool needact, - ae_int_t cidx, - double cval, - /* Real */ ae_vector* addsteps, - ae_int_t addstepscnt, - /* Boolean */ ae_vector* activated, - /* Real */ ae_vector* tmp0, - /* Real */ ae_vector* tmp1, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_int_t k; - double v; - double stpbest; - double fbest; - double fcand; - - - n = sstate->n; - rvectorsetlengthatleast(tmp0, n, _state); - bvectorsetlengthatleast(activated, n, _state); - - /* - * Calculate initial step, store to Tmp0 - * - * NOTE: Tmp0 is guaranteed to be feasible w.r.t. boundary constraints - */ - for(i=0; i<=n-1; i++) - { - v = sas->xc.ptr.p_double[i]+stp*d->ptr.p_double[i]; - if( sstate->havebndl.ptr.p_bool[i]&&ae_fp_less(v,sstate->bndl.ptr.p_double[i]) ) - { - v = sstate->bndl.ptr.p_double[i]; - } - if( sstate->havebndu.ptr.p_bool[i]&&ae_fp_greater(v,sstate->bndu.ptr.p_double[i]) ) - { - v = sstate->bndu.ptr.p_double[i]; - } - tmp0->ptr.p_double[i] = v; - } - if( needact ) - { - tmp0->ptr.p_double[cidx] = cval; - } - - /* - * Try additional steps, if AddStepsCnt>0 - */ - if( addstepscnt>0 ) - { - - /* - * Find best step - */ - stpbest = stp; - fbest = qqpsolver_projectedtargetfunction(sstate, &sas->xc, d, stpbest, tmp0, tmp1, _state); - for(k=0; k<=addstepscnt-1; k++) - { - if( ae_fp_greater(addsteps->ptr.p_double[k],stp) ) - { - fcand = qqpsolver_projectedtargetfunction(sstate, &sas->xc, d, addsteps->ptr.p_double[k], tmp0, tmp1, _state); - if( ae_fp_less(fcand,fbest) ) - { - fbest = fcand; - stpbest = addsteps->ptr.p_double[k]; - } - } - } - - /* - * Prepare best step - * - * NOTE: because only AddSteps[]>Stp were checked, - * this step will activate constraint CIdx. - */ - for(i=0; i<=n-1; i++) - { - v = sas->xc.ptr.p_double[i]+stpbest*d->ptr.p_double[i]; - if( sstate->havebndl.ptr.p_bool[i]&&ae_fp_less(v,sstate->bndl.ptr.p_double[i]) ) - { - v = sstate->bndl.ptr.p_double[i]; - } - if( sstate->havebndu.ptr.p_bool[i]&&ae_fp_greater(v,sstate->bndu.ptr.p_double[i]) ) - { - v = sstate->bndu.ptr.p_double[i]; - } - tmp0->ptr.p_double[i] = v; - } - if( needact ) - { - tmp0->ptr.p_double[cidx] = cval; - } - } - - /* - * Fill Activated array by information about activated constraints. - * Perform step - */ - for(i=0; i<=n-1; i++) - { - activated->ptr.p_bool[i] = ae_false; - v = tmp0->ptr.p_double[i]; - if( ae_fp_eq(v,sas->xc.ptr.p_double[i]) ) - { - continue; - } - if( sstate->havebndl.ptr.p_bool[i]&&ae_fp_eq(v,sstate->bndl.ptr.p_double[i]) ) - { - activated->ptr.p_bool[i] = ae_true; - } - if( sstate->havebndu.ptr.p_bool[i]&&ae_fp_eq(v,sstate->bndu.ptr.p_double[i]) ) - { - activated->ptr.p_bool[i] = ae_true; - } - } - sasmoveto(sas, tmp0, needact, cidx, cval, _state); -} - - -/************************************************************************* -This function prepares data for constrained Newton step for penalized -quadratic model of the form - - f(x) = 0.5*x'*A*x + b'*x + penaltyfactor*0.5*(C*x-b)'*(C*x-b) - -where A can be dense or sparse, and model is considered subject to equality -constraints specified by SState.SAS.XC object. Constraint is considered -active if XC[i] is exactly BndL[i] or BndU[i], i.e. we ignore internal -list of constraints monitored by SAS object. Our own set of constraints -includes all constraints stored by SAS, but also may include some -constraints which are inactive in SAS. - -"Preparation" means that Cholesky decomposition of the effective system -matrix is performed, and we can perform constrained Newton step. - -This function works as black box. It uses fields of SState which are marked -as "Variables for constrained Newton phase", and only this function and -its friends know about these variables. Everyone else should use: -* CNewtonBuild() to prepare initial Cholesky decomposition for step -* CNewtonStep() to perform constrained Newton step -* CNewtonUpdate() to update Cholesky matrix after point was moved and - constraints were updated. In some cases it is possible to efficiently - re-calculate Cholesky decomposition if you know which constraints were - activated. If efficient re-calculation is impossible, this function - returns False. - -INPUT PARAMETERS: - SState - structure which stores model and temporaries for CN phase; - in particular, SAS.XC stores current point. - SparseSolver-which sparse solver to use for sparse model; ignored for - dense QP. Can be: - * 2 - SKS-based Cholesky - NCholesky- counter which is incremented after Cholesky (successful or - failed one) - -OUTPUT PARAMETERS: - NCholesky- possibly updated counter - -RESULT: - True, if Cholesky decomposition was successfully performed. - False, if a) matrix was semi-definite or indefinite, or b) particular - combination of matrix type (sparse) and constraints (general linear) - is not supported. - -NOTE: this function may routinely return False, for indefinite matrices or - for sparse problems with general linear constraints. You should be - able to handle such situations. - - -- ALGLIB -- - Copyright 14.05.2014 by Bochkanov Sergey -*************************************************************************/ -static ae_bool qqpsolver_cnewtonbuild(qqpbuffers* sstate, - ae_int_t sparsesolver, - ae_int_t* ncholesky, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - ae_bool b; - ae_int_t ridx0; - ae_int_t ridx1; - ae_int_t nfree; - ae_bool result; - - - result = ae_false; - - /* - * Fetch often used fields - */ - n = sstate->n; - - /* - * 1. Set CNModelAge to zero - * 2. Generate YIdx - reordering of variables such that free variables - * come first and are ordered by ascending, fixed are last ones and - * have no particular ordering. - * - * This step is same for dense and sparse problems. - */ - sstate->cnmodelage = 0; - ivectorsetlengthatleast(&sstate->yidx, n, _state); - ridx0 = 0; - ridx1 = n-1; - for(i=0; i<=n-1; i++) - { - sstate->yidx.ptr.p_int[i] = -1; - } - for(i=0; i<=n-1; i++) - { - ae_assert(!sstate->havebndl.ptr.p_bool[i]||ae_fp_greater_eq(sstate->sas.xc.ptr.p_double[i],sstate->bndl.ptr.p_double[i]), "CNewtonBuild: internal error", _state); - ae_assert(!sstate->havebndu.ptr.p_bool[i]||ae_fp_less_eq(sstate->sas.xc.ptr.p_double[i],sstate->bndu.ptr.p_double[i]), "CNewtonBuild: internal error", _state); - b = ae_false; - b = b||(sstate->havebndl.ptr.p_bool[i]&&ae_fp_eq(sstate->sas.xc.ptr.p_double[i],sstate->bndl.ptr.p_double[i])); - b = b||(sstate->havebndu.ptr.p_bool[i]&&ae_fp_eq(sstate->sas.xc.ptr.p_double[i],sstate->bndu.ptr.p_double[i])); - if( b ) - { - sstate->yidx.ptr.p_int[ridx1] = i; - ridx1 = ridx1-1; - } - else - { - sstate->yidx.ptr.p_int[ridx0] = i; - ridx0 = ridx0+1; - } - } - ae_assert(ridx0==ridx1+1, "CNewtonBuild: internal error", _state); - nfree = ridx0; - sstate->nfree = nfree; - if( nfree==0 ) - { - return result; - } - - /* - * Constrained Newton matrix: dense version - */ - if( sstate->akind==0 ) - { - rmatrixsetlengthatleast(&sstate->densez, n, n, _state); - rvectorsetlengthatleast(&sstate->tmpcn, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - sstate->densez.ptr.pp_double[i][j] = sstate->densea.ptr.pp_double[i][j]; - } - } - for(i=1; i<=nfree-1; i++) - { - ae_assert(sstate->yidx.ptr.p_int[i]>sstate->yidx.ptr.p_int[i-1], "CNewtonBuild: integrity check failed", _state); - } - for(i=0; i<=nfree-1; i++) - { - k = sstate->yidx.ptr.p_int[i]; - for(j=i; j<=nfree-1; j++) - { - sstate->densez.ptr.pp_double[i][j] = sstate->densez.ptr.pp_double[k][sstate->yidx.ptr.p_int[j]]; - } - } - rvectorsetlengthatleast(&sstate->regdiag, n, _state); - for(i=0; i<=nfree-1; i++) - { - v = 0.0; - for(j=0; j<=i-1; j++) - { - v = v+ae_fabs(sstate->densez.ptr.pp_double[j][i], _state); - } - for(j=i; j<=nfree-1; j++) - { - v = v+ae_fabs(sstate->densez.ptr.pp_double[i][j], _state); - } - if( ae_fp_eq(v,(double)(0)) ) - { - v = 1.0; - } - sstate->regdiag.ptr.p_double[i] = qqpsolver_regz*v; - } - for(i=0; i<=nfree-1; i++) - { - sstate->densez.ptr.pp_double[i][i] = sstate->densez.ptr.pp_double[i][i]+sstate->regdiag.ptr.p_double[i]; - } - inc(ncholesky, _state); - if( !spdmatrixcholeskyrec(&sstate->densez, 0, nfree, ae_true, &sstate->tmpcn, _state) ) - { - return result; - } - for(i=nfree-1; i>=0; i--) - { - ae_v_move(&sstate->tmpcn.ptr.p_double[i], 1, &sstate->densez.ptr.pp_double[i][i], 1, ae_v_len(i,nfree-1)); - k = sstate->yidx.ptr.p_int[i]; - for(j=k; j<=n-1; j++) - { - sstate->densez.ptr.pp_double[k][j] = (double)(0); - } - for(j=i; j<=nfree-1; j++) - { - sstate->densez.ptr.pp_double[k][sstate->yidx.ptr.p_int[j]] = sstate->tmpcn.ptr.p_double[j]; - } - } - for(i=nfree; i<=n-1; i++) - { - k = sstate->yidx.ptr.p_int[i]; - sstate->densez.ptr.pp_double[k][k] = 1.0; - for(j=k+1; j<=n-1; j++) - { - sstate->densez.ptr.pp_double[k][j] = (double)(0); - } - } - result = ae_true; - return result; - } - - /* - * Constrained Newton matrix: sparse version - */ - if( sstate->akind==1 ) - { - ae_assert(sparsesolver==2, "CNewtonBuild: internal error", _state); - - /* - * Copy sparse A to Z and fill rows/columns corresponding to active - * constraints by zeros. Diagonal elements corresponding to active - * constraints are filled by unit values. - */ - sparsecopytosksbuf(&sstate->sparsea, &sstate->sparsecca, _state); - rvectorsetlengthatleast(&sstate->tmpcn, n, _state); - for(i=0; i<=n-1; i++) - { - sstate->tmpcn.ptr.p_double[i] = (double)(0); - } - for(i=nfree; i<=n-1; i++) - { - sstate->tmpcn.ptr.p_double[sstate->yidx.ptr.p_int[i]] = (double)(1); - } - for(i=0; i<=n-1; i++) - { - k = sstate->sparsecca.ridx.ptr.p_int[i]; - for(j=i-sstate->sparsecca.didx.ptr.p_int[i]; j<=i; j++) - { - if( ae_fp_neq(sstate->tmpcn.ptr.p_double[i],(double)(0))||ae_fp_neq(sstate->tmpcn.ptr.p_double[j],(double)(0)) ) - { - - /* - * I-th or J-th variable is in active set (constrained) - */ - if( i==j ) - { - sstate->sparsecca.vals.ptr.p_double[k] = 1.0; - } - else - { - sstate->sparsecca.vals.ptr.p_double[k] = 0.0; - } - } - k = k+1; - } - } - - /* - * Perform sparse Cholesky - */ - inc(ncholesky, _state); - if( !sparsecholeskyskyline(&sstate->sparsecca, n, sstate->sparseupper, _state) ) - { - return result; - } - result = ae_true; - return result; - } - - /* - * Unexpected :) - */ - ae_assert(ae_false, "CNewtonBuild: internal error", _state); - return result; -} - - -/************************************************************************* -This function updates equality-constrained Cholesky matrix after -activation of the new equality constraints. Matrix being updated is -quadratic term of the function below - - f(x) = 0.5*x'*A*x + b'*x + penaltyfactor*0.5*(C*x-b)'*(C*x-b) - -where A can be dense or sparse. - -This function uses YIdx[] array (set by CNewtonBuild() function) to -distinguish between active and inactive constraints. - -This function works as black box. It uses fields of SState which are marked -as "Variables for constrained Newton phase", and only this function and -its friends know about these variables. Everyone else should use: -* CNewtonBuild() to prepare initial Cholesky decomposition for step -* CNewtonStep() to perform constrained Newton step -* CNewtonUpdate() to update Cholesky matrix after point was moved and - constraints were updated. In some cases it is possible to efficiently - re-calculate Cholesky decomposition if you know which constraints were - activated. If efficient re-calculation is impossible, this function - returns False. - -INPUT PARAMETERS: - SState - structure which stores model and temporaries for CN phase; - in particular, SAS.XC stores current point. - Settings - QQPSettings object which was initialized by appropriate - construction function. - NCUpdates- counter which is incremented after each update (one update - means one variable being fixed) - -OUTPUT PARAMETERS: - NCUpdates- possibly updated counter - -RESULT: - True, if Cholesky decomposition was successfully performed. - False, if a) model age was too high, or b) particular combination of - matrix type (sparse) and constraints (general linear) is not supported - -NOTE: this function may routinely return False. - You should be able to handle such situations. - - -- ALGLIB -- - Copyright 14.05.2014 by Bochkanov Sergey -*************************************************************************/ -static ae_bool qqpsolver_cnewtonupdate(qqpbuffers* sstate, - qqpsettings* settings, - ae_int_t* ncupdates, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nfree; - ae_int_t ntofix; - ae_bool b; - ae_int_t ridx0; - ae_int_t ridx1; - ae_int_t i; - ae_int_t k; - ae_bool result; - - - result = ae_false; - - /* - * Cholesky updates for sparse problems are not supported - */ - if( sstate->akind==1 ) - { - return result; - } - - /* - * Fetch often used fields - */ - n = sstate->n; - nfree = sstate->nfree; - - /* - * Determine variables to fix and move them to YIdx[NFree-NToFix:NFree-1] - * Exit if CNModelAge increased too much. - */ - ivectorsetlengthatleast(&sstate->tmpcni, n, _state); - ridx0 = 0; - ridx1 = nfree-1; - for(i=0; i<=nfree-1; i++) - { - sstate->tmpcni.ptr.p_int[i] = -1; - } - for(k=0; k<=nfree-1; k++) - { - i = sstate->yidx.ptr.p_int[k]; - ae_assert(!sstate->havebndl.ptr.p_bool[i]||ae_fp_greater_eq(sstate->sas.xc.ptr.p_double[i],sstate->bndl.ptr.p_double[i]), "CNewtonUpdate: internal error", _state); - ae_assert(!sstate->havebndu.ptr.p_bool[i]||ae_fp_less_eq(sstate->sas.xc.ptr.p_double[i],sstate->bndu.ptr.p_double[i]), "CNewtonUpdate: internal error", _state); - b = ae_false; - b = b||(sstate->havebndl.ptr.p_bool[i]&&ae_fp_eq(sstate->sas.xc.ptr.p_double[i],sstate->bndl.ptr.p_double[i])); - b = b||(sstate->havebndu.ptr.p_bool[i]&&ae_fp_eq(sstate->sas.xc.ptr.p_double[i],sstate->bndu.ptr.p_double[i])); - if( b ) - { - sstate->tmpcni.ptr.p_int[ridx1] = i; - ridx1 = ridx1-1; - } - else - { - sstate->tmpcni.ptr.p_int[ridx0] = i; - ridx0 = ridx0+1; - } - } - ae_assert(ridx0==ridx1+1, "CNewtonUpdate: internal error", _state); - ntofix = nfree-ridx0; - if( ntofix==0||ntofix==nfree ) - { - return result; - } - if( sstate->cnmodelage+ntofix>settings->cnmaxupdates ) - { - return result; - } - for(i=0; i<=nfree-1; i++) - { - sstate->yidx.ptr.p_int[i] = sstate->tmpcni.ptr.p_int[i]; - } - - /* - * Constrained Newton matrix: dense version. - */ - if( sstate->akind==0 ) - { - - /* - * Update Cholesky matrix with SPDMatrixCholeskyUpdateFixBuf() - */ - bvectorsetlengthatleast(&sstate->tmpcnb, n, _state); - for(i=0; i<=n-1; i++) - { - sstate->tmpcnb.ptr.p_bool[i] = ae_false; - } - for(i=nfree-ntofix; i<=nfree-1; i++) - { - sstate->tmpcnb.ptr.p_bool[sstate->yidx.ptr.p_int[i]] = ae_true; - } - spdmatrixcholeskyupdatefixbuf(&sstate->densez, n, ae_true, &sstate->tmpcnb, &sstate->tmpcn, _state); - - /* - * Update information stored in State and exit - */ - sstate->nfree = nfree-ntofix; - sstate->cnmodelage = sstate->cnmodelage+ntofix; - *ncupdates = *ncupdates+ntofix; - result = ae_true; - return result; - } - - /* - * Unexpected :) - */ - ae_assert(ae_false, "CNewtonUpdate: internal error", _state); - return result; -} - - -/************************************************************************* -This function prepares equality-constrained Newton step using previously -calculated constrained Cholesky matrix of the problem - - f(x) = 0.5*x'*A*x + b'*x + penaltyfactor*0.5*(C*x-b)'*(C*x-b) - -where A can be dense or sparse. - -As input, this function accepts gradient at the current location. As -output, it returns step vector (replaces gradient). - -This function works as black box. It uses fields of SState which are marked -as "Variables for constrained Newton phase", and only this function and -its friends know about these variables. Everyone else should use: -* CNewtonBuild() to prepare initial Cholesky decomposition for step -* CNewtonStep() to perform constrained Newton step -* CNewtonUpdate() to update Cholesky matrix after point was moved and - constraints were updated. In some cases it is possible to efficiently - re-calculate Cholesky decomposition if you know which constraints were - activated. If efficient re-calculation is impossible, this function - returns False. - -INPUT PARAMETERS: - SState - structure which stores model and temporaries for CN phase; - in particular, SAS.XC stores current point. - Settings - QQPSettings object which was initialized by appropriate - construction function. - GC - array[N], gradient of the target function - -OUTPUT PARAMETERS: - GC - array[N], step vector (on success) - -RESULT: - True, if step was successfully calculated. - False, if step calculation failed: - a) gradient was exactly zero, - b) gradient norm was smaller than EpsG (stopping condition) - c) all variables were equality-constrained - -NOTE: this function may routinely return False. - You should be able to handle such situations. - - -- ALGLIB -- - Copyright 14.05.2014 by Bochkanov Sergey -*************************************************************************/ -static ae_bool qqpsolver_cnewtonstep(qqpbuffers* sstate, - qqpsettings* settings, - /* Real */ ae_vector* gc, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - ae_int_t nfree; - double v; - ae_bool result; - - - result = ae_false; - n = sstate->n; - nfree = sstate->nfree; - for(i=nfree; i<=n-1; i++) - { - gc->ptr.p_double[sstate->yidx.ptr.p_int[i]] = 0.0; - } - v = ae_v_dotproduct(&gc->ptr.p_double[0], 1, &gc->ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( ae_fp_less_eq(ae_sqrt(v, _state),settings->epsg) ) - { - return result; - } - for(i=0; i<=n-1; i++) - { - gc->ptr.p_double[i] = -gc->ptr.p_double[i]; - } - if( sstate->akind==0 ) - { - - /* - * Dense Newton step. - * Use straightforward Cholesky solver. - */ - fblscholeskysolve(&sstate->densez, 1.0, n, ae_true, gc, &sstate->tmpcn, _state); - result = ae_true; - return result; - } - if( sstate->akind==1 ) - { - - /* - * Sparse Newton step. - * - * We have T*T' = L*L' = U'*U (depending on specific triangle stored in SparseCCA). - */ - if( sstate->sparseupper ) - { - sparsetrsv(&sstate->sparsecca, sstate->sparseupper, ae_false, 1, gc, _state); - sparsetrsv(&sstate->sparsecca, sstate->sparseupper, ae_false, 0, gc, _state); - } - else - { - sparsetrsv(&sstate->sparsecca, sstate->sparseupper, ae_false, 0, gc, _state); - sparsetrsv(&sstate->sparsecca, sstate->sparseupper, ae_false, 1, gc, _state); - } - result = ae_true; - return result; - } - ae_assert(ae_false, "CNewtonStep: internal error", _state); - return result; -} - - -void _qqpsettings_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - qqpsettings *p = (qqpsettings*)_p; - ae_touch_ptr((void*)p); -} - - -void _qqpsettings_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - qqpsettings *dst = (qqpsettings*)_dst; - qqpsettings *src = (qqpsettings*)_src; - dst->epsg = src->epsg; - dst->epsf = src->epsf; - dst->epsx = src->epsx; - dst->maxouterits = src->maxouterits; - dst->cgphase = src->cgphase; - dst->cnphase = src->cnphase; - dst->cgminits = src->cgminits; - dst->cgmaxits = src->cgmaxits; - dst->cnmaxupdates = src->cnmaxupdates; - dst->sparsesolver = src->sparsesolver; -} - - -void _qqpsettings_clear(void* _p) -{ - qqpsettings *p = (qqpsettings*)_p; - ae_touch_ptr((void*)p); -} - - -void _qqpsettings_destroy(void* _p) -{ - qqpsettings *p = (qqpsettings*)_p; - ae_touch_ptr((void*)p); -} - - -void _qqpbuffers_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - qqpbuffers *p = (qqpbuffers*)_p; - ae_touch_ptr((void*)p); - ae_matrix_init(&p->densea, 0, 0, DT_REAL, _state, make_automatic); - _sparsematrix_init(&p->sparsea, _state, make_automatic); - ae_vector_init(&p->b, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->havebndl, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->havebndu, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->xs, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xf, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->gc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xp, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dp, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cgc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cgp, 0, DT_REAL, _state, make_automatic); - _sactiveset_init(&p->sas, _state, make_automatic); - ae_vector_init(&p->activated, 0, DT_BOOL, _state, make_automatic); - ae_matrix_init(&p->densez, 0, 0, DT_REAL, _state, make_automatic); - _sparsematrix_init(&p->sparsecca, _state, make_automatic); - ae_vector_init(&p->yidx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->regdiag, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->regx0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpcn, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpcni, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->tmpcnb, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stpbuf, 0, DT_REAL, _state, make_automatic); - _sparsebuffers_init(&p->sbuf, _state, make_automatic); -} - - -void _qqpbuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - qqpbuffers *dst = (qqpbuffers*)_dst; - qqpbuffers *src = (qqpbuffers*)_src; - dst->n = src->n; - dst->akind = src->akind; - ae_matrix_init_copy(&dst->densea, &src->densea, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparsea, &src->sparsea, _state, make_automatic); - dst->sparseupper = src->sparseupper; - dst->absamax = src->absamax; - dst->absasum = src->absasum; - dst->absasum2 = src->absasum2; - ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic); - ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic); - ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic); - ae_vector_init_copy(&dst->havebndl, &src->havebndl, _state, make_automatic); - ae_vector_init_copy(&dst->havebndu, &src->havebndu, _state, make_automatic); - ae_vector_init_copy(&dst->xs, &src->xs, _state, make_automatic); - ae_vector_init_copy(&dst->xf, &src->xf, _state, make_automatic); - ae_vector_init_copy(&dst->gc, &src->gc, _state, make_automatic); - ae_vector_init_copy(&dst->xp, &src->xp, _state, make_automatic); - ae_vector_init_copy(&dst->dc, &src->dc, _state, make_automatic); - ae_vector_init_copy(&dst->dp, &src->dp, _state, make_automatic); - ae_vector_init_copy(&dst->cgc, &src->cgc, _state, make_automatic); - ae_vector_init_copy(&dst->cgp, &src->cgp, _state, make_automatic); - _sactiveset_init_copy(&dst->sas, &src->sas, _state, make_automatic); - ae_vector_init_copy(&dst->activated, &src->activated, _state, make_automatic); - dst->nfree = src->nfree; - dst->cnmodelage = src->cnmodelage; - ae_matrix_init_copy(&dst->densez, &src->densez, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparsecca, &src->sparsecca, _state, make_automatic); - ae_vector_init_copy(&dst->yidx, &src->yidx, _state, make_automatic); - ae_vector_init_copy(&dst->regdiag, &src->regdiag, _state, make_automatic); - ae_vector_init_copy(&dst->regx0, &src->regx0, _state, make_automatic); - ae_vector_init_copy(&dst->tmpcn, &src->tmpcn, _state, make_automatic); - ae_vector_init_copy(&dst->tmpcni, &src->tmpcni, _state, make_automatic); - ae_vector_init_copy(&dst->tmpcnb, &src->tmpcnb, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic); - ae_vector_init_copy(&dst->stpbuf, &src->stpbuf, _state, make_automatic); - _sparsebuffers_init_copy(&dst->sbuf, &src->sbuf, _state, make_automatic); - dst->repinneriterationscount = src->repinneriterationscount; - dst->repouteriterationscount = src->repouteriterationscount; - dst->repncholesky = src->repncholesky; - dst->repncupdates = src->repncupdates; -} - - -void _qqpbuffers_clear(void* _p) -{ - qqpbuffers *p = (qqpbuffers*)_p; - ae_touch_ptr((void*)p); - ae_matrix_clear(&p->densea); - _sparsematrix_clear(&p->sparsea); - ae_vector_clear(&p->b); - ae_vector_clear(&p->bndl); - ae_vector_clear(&p->bndu); - ae_vector_clear(&p->havebndl); - ae_vector_clear(&p->havebndu); - ae_vector_clear(&p->xs); - ae_vector_clear(&p->xf); - ae_vector_clear(&p->gc); - ae_vector_clear(&p->xp); - ae_vector_clear(&p->dc); - ae_vector_clear(&p->dp); - ae_vector_clear(&p->cgc); - ae_vector_clear(&p->cgp); - _sactiveset_clear(&p->sas); - ae_vector_clear(&p->activated); - ae_matrix_clear(&p->densez); - _sparsematrix_clear(&p->sparsecca); - ae_vector_clear(&p->yidx); - ae_vector_clear(&p->regdiag); - ae_vector_clear(&p->regx0); - ae_vector_clear(&p->tmpcn); - ae_vector_clear(&p->tmpcni); - ae_vector_clear(&p->tmpcnb); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->tmp1); - ae_vector_clear(&p->stpbuf); - _sparsebuffers_clear(&p->sbuf); -} - - -void _qqpbuffers_destroy(void* _p) -{ - qqpbuffers *p = (qqpbuffers*)_p; - ae_touch_ptr((void*)p); - ae_matrix_destroy(&p->densea); - _sparsematrix_destroy(&p->sparsea); - ae_vector_destroy(&p->b); - ae_vector_destroy(&p->bndl); - ae_vector_destroy(&p->bndu); - ae_vector_destroy(&p->havebndl); - ae_vector_destroy(&p->havebndu); - ae_vector_destroy(&p->xs); - ae_vector_destroy(&p->xf); - ae_vector_destroy(&p->gc); - ae_vector_destroy(&p->xp); - ae_vector_destroy(&p->dc); - ae_vector_destroy(&p->dp); - ae_vector_destroy(&p->cgc); - ae_vector_destroy(&p->cgp); - _sactiveset_destroy(&p->sas); - ae_vector_destroy(&p->activated); - ae_matrix_destroy(&p->densez); - _sparsematrix_destroy(&p->sparsecca); - ae_vector_destroy(&p->yidx); - ae_vector_destroy(&p->regdiag); - ae_vector_destroy(&p->regx0); - ae_vector_destroy(&p->tmpcn); - ae_vector_destroy(&p->tmpcni); - ae_vector_destroy(&p->tmpcnb); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->tmp1); - ae_vector_destroy(&p->stpbuf); - _sparsebuffers_destroy(&p->sbuf); -} - - -#endif -#if defined(AE_COMPILE_MINLBFGS) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* - LIMITED MEMORY BFGS METHOD FOR LARGE SCALE OPTIMIZATION - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments by using a quasi- -Newton method (LBFGS scheme) which is optimized to use a minimum amount -of memory. -The subroutine generates the approximation of an inverse Hessian matrix by -using information about the last M steps of the algorithm (instead of N). -It lessens a required amount of memory from a value of order N^2 to a -value of order 2*N*M. - - -REQUIREMENTS: -Algorithm will request following information during its operation: -* function value F and its gradient G (simultaneously) at given point X - - -USAGE: -1. User initializes algorithm state with MinLBFGSCreate() call -2. User tunes solver parameters with MinLBFGSSetCond() MinLBFGSSetStpMax() - and other functions -3. User calls MinLBFGSOptimize() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. -4. User calls MinLBFGSResults() to get solution -5. Optionally user may call MinLBFGSRestartFrom() to solve another problem - with same N/M but another starting point and/or another function. - MinLBFGSRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension. N>0 - M - number of corrections in the BFGS scheme of Hessian - approximation update. Recommended value: 3<=M<=7. The smaller - value causes worse convergence, the bigger will not cause a - considerably better convergence, but will cause a fall in the - performance. M<=N. - X - initial solution approximation, array[0..N-1]. - - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -NOTES: -1. you may tune stopping conditions with MinLBFGSSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use MinLBFGSSetStpMax() function to bound algorithm's steps. However, - L-BFGS rarely needs such a tuning. - - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgscreate(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* x, - minlbfgsstate* state, - ae_state *_state) -{ - - _minlbfgsstate_clear(state); - - ae_assert(n>=1, "MinLBFGSCreate: N<1!", _state); - ae_assert(m>=1, "MinLBFGSCreate: M<1", _state); - ae_assert(m<=n, "MinLBFGSCreate: M>N", _state); - ae_assert(x->cnt>=n, "MinLBFGSCreate: Length(X)0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - M - number of corrections in the BFGS scheme of Hessian - approximation update. Recommended value: 3<=M<=7. The smaller - value causes worse convergence, the bigger will not cause a - considerably better convergence, but will cause a fall in the - performance. M<=N. - X - starting point, array[0..N-1]. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinLBFGSSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large truncation errors, while too small - step will result in too large numerical errors. 1.0E-6 can be good - value to start with. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. LBFGS needs exact gradient values. - Imprecise gradient may slow down convergence, especially on highly - nonlinear problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -void minlbfgscreatef(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* x, - double diffstep, - minlbfgsstate* state, - ae_state *_state) -{ - - _minlbfgsstate_clear(state); - - ae_assert(n>=1, "MinLBFGSCreateF: N too small!", _state); - ae_assert(m>=1, "MinLBFGSCreateF: M<1", _state); - ae_assert(m<=n, "MinLBFGSCreateF: M>N", _state); - ae_assert(x->cnt>=n, "MinLBFGSCreateF: Length(X)=0 - The subroutine finishes its work if the condition - |v|=0 - The subroutine finishes its work if on k+1-th iteration - the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - is satisfied. - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - ste pvector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinLBFGSSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to -automatic stopping criterion selection (small EpsX). - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetcond(minlbfgsstate* state, - double epsg, - double epsf, - double epsx, - ae_int_t maxits, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(epsg, _state), "MinLBFGSSetCond: EpsG is not finite number!", _state); - ae_assert(ae_fp_greater_eq(epsg,(double)(0)), "MinLBFGSSetCond: negative EpsG!", _state); - ae_assert(ae_isfinite(epsf, _state), "MinLBFGSSetCond: EpsF is not finite number!", _state); - ae_assert(ae_fp_greater_eq(epsf,(double)(0)), "MinLBFGSSetCond: negative EpsF!", _state); - ae_assert(ae_isfinite(epsx, _state), "MinLBFGSSetCond: EpsX is not finite number!", _state); - ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinLBFGSSetCond: negative EpsX!", _state); - ae_assert(maxits>=0, "MinLBFGSSetCond: negative MaxIts!", _state); - if( ((ae_fp_eq(epsg,(double)(0))&&ae_fp_eq(epsf,(double)(0)))&&ae_fp_eq(epsx,(double)(0)))&&maxits==0 ) - { - epsx = 1.0E-6; - } - state->epsg = epsg; - state->epsf = epsf; - state->epsx = epsx; - state->maxits = maxits; -} - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinLBFGSOptimize(). - - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetxrep(minlbfgsstate* state, - ae_bool needxrep, - ae_state *_state) -{ - - - state->xrep = needxrep; -} - - -/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0 (default), if - you don't want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which leads to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetstpmax(minlbfgsstate* state, - double stpmax, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(stpmax, _state), "MinLBFGSSetStpMax: StpMax is not finite!", _state); - ae_assert(ae_fp_greater_eq(stpmax,(double)(0)), "MinLBFGSSetStpMax: StpMax<0!", _state); - state->stpmax = stpmax; -} - - -/************************************************************************* -This function sets scaling coefficients for LBFGS optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of the optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -In most optimizers (and in the LBFGS too) scaling is NOT a form of -preconditioning. It just affects stopping conditions. You should set -preconditioner by separate call to one of the MinLBFGSSetPrec...() -functions. - -There is special preconditioning mode, however, which uses scaling -coefficients to form diagonal preconditioning matrix. You can turn this -mode on, if you want. But you should understand that scaling is not the -same thing as preconditioning - these are two different, although related -forms of tuning solver. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetscale(minlbfgsstate* state, - /* Real */ ae_vector* s, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(s->cnt>=state->n, "MinLBFGSSetScale: Length(S)n-1; i++) - { - ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinLBFGSSetScale: S contains infinite or NAN elements", _state); - ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "MinLBFGSSetScale: S contains zero elements", _state); - state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state); - } -} - - -/************************************************************************* -Extended subroutine for internal use only. - -Accepts additional parameters: - - Flags - additional settings: - * Flags = 0 means no additional settings - * Flags = 1 "do not allocate memory". used when solving - a many subsequent tasks with same N/M values. - First call MUST be without this flag bit set, - subsequent calls of MinLBFGS with same - MinLBFGSState structure can set Flags to 1. - DiffStep - numerical differentiation step - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgscreatex(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* x, - ae_int_t flags, - double diffstep, - minlbfgsstate* state, - ae_state *_state) -{ - ae_bool allocatemem; - ae_int_t i; - - - ae_assert(n>=1, "MinLBFGS: N too small!", _state); - ae_assert(m>=1, "MinLBFGS: M too small!", _state); - ae_assert(m<=n, "MinLBFGS: M too large!", _state); - - /* - * Initialize - */ - state->teststep = (double)(0); - state->smoothnessguardlevel = 0; - smoothnessmonitorinit(&state->smonitor, &state->s, 0, 0, ae_false, _state); - state->diffstep = diffstep; - state->n = n; - state->m = m; - allocatemem = flags%2==0; - flags = flags/2; - if( allocatemem ) - { - rvectorsetlengthatleast(&state->rho, m, _state); - rvectorsetlengthatleast(&state->theta, m, _state); - rmatrixsetlengthatleast(&state->yk, m, n, _state); - rmatrixsetlengthatleast(&state->sk, m, n, _state); - rvectorsetlengthatleast(&state->d, n, _state); - rvectorsetlengthatleast(&state->xp, n, _state); - rvectorsetlengthatleast(&state->x, n, _state); - rvectorsetlengthatleast(&state->xbase, n, _state); - rvectorsetlengthatleast(&state->s, n, _state); - rvectorsetlengthatleast(&state->invs, n, _state); - rvectorsetlengthatleast(&state->lastscaleused, n, _state); - rvectorsetlengthatleast(&state->g, n, _state); - rvectorsetlengthatleast(&state->work, n, _state); - } - for(i=0; i<=n-1; i++) - { - state->s.ptr.p_double[i] = 1.0; - state->invs.ptr.p_double[i] = 1.0; - state->lastscaleused.ptr.p_double[i] = 1.0; - } - state->prectype = 0; - minlbfgssetcond(state, (double)(0), (double)(0), (double)(0), 0, _state); - minlbfgssetxrep(state, ae_false, _state); - minlbfgssetstpmax(state, (double)(0), _state); - minlbfgsrestartfrom(state, x, _state); -} - - -/************************************************************************* -Modification of the preconditioner: default preconditioner (simple -scaling, same for all elements of X) is used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetprecdefault(minlbfgsstate* state, ae_state *_state) -{ - - - state->prectype = 0; -} - - -/************************************************************************* -Modification of the preconditioner: Cholesky factorization of approximate -Hessian is used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - P - triangular preconditioner, Cholesky factorization of - the approximate Hessian. array[0..N-1,0..N-1], - (if larger, only leading N elements are used). - IsUpper - whether upper or lower triangle of P is given - (other triangle is not referenced) - -After call to this function preconditioner is changed to P (P is copied -into the internal buffer). - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - -NOTE 2: P should be nonsingular. Exception will be thrown otherwise. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetpreccholesky(minlbfgsstate* state, - /* Real */ ae_matrix* p, - ae_bool isupper, - ae_state *_state) -{ - ae_int_t i; - double mx; - - - ae_assert(isfinitertrmatrix(p, state->n, isupper, _state), "MinLBFGSSetPrecCholesky: P contains infinite or NAN values!", _state); - mx = (double)(0); - for(i=0; i<=state->n-1; i++) - { - mx = ae_maxreal(mx, ae_fabs(p->ptr.pp_double[i][i], _state), _state); - } - ae_assert(ae_fp_greater(mx,(double)(0)), "MinLBFGSSetPrecCholesky: P is strictly singular!", _state); - if( state->denseh.rowsn||state->denseh.colsn ) - { - ae_matrix_set_length(&state->denseh, state->n, state->n, _state); - } - state->prectype = 1; - if( isupper ) - { - rmatrixcopy(state->n, state->n, p, 0, 0, &state->denseh, 0, 0, _state); - } - else - { - rmatrixtranspose(state->n, state->n, p, 0, 0, &state->denseh, 0, 0, _state); - } -} - - -/************************************************************************* -Modification of the preconditioner: diagonal of approximate Hessian is -used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - D - diagonal of the approximate Hessian, array[0..N-1], - (if larger, only leading N elements are used). - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - -NOTE 2: D[i] should be positive. Exception will be thrown otherwise. - -NOTE 3: you should pass diagonal of approximate Hessian - NOT ITS INVERSE. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetprecdiag(minlbfgsstate* state, - /* Real */ ae_vector* d, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(d->cnt>=state->n, "MinLBFGSSetPrecDiag: D is too short", _state); - for(i=0; i<=state->n-1; i++) - { - ae_assert(ae_isfinite(d->ptr.p_double[i], _state), "MinLBFGSSetPrecDiag: D contains infinite or NAN elements", _state); - ae_assert(ae_fp_greater(d->ptr.p_double[i],(double)(0)), "MinLBFGSSetPrecDiag: D contains non-positive elements", _state); - } - rvectorsetlengthatleast(&state->diagh, state->n, _state); - state->prectype = 2; - for(i=0; i<=state->n-1; i++) - { - state->diagh.ptr.p_double[i] = d->ptr.p_double[i]; - } -} - - -/************************************************************************* -Modification of the preconditioner: scale-based diagonal preconditioning. - -This preconditioning mode can be useful when you don't have approximate -diagonal of Hessian, but you know that your variables are badly scaled -(for example, one variable is in [1,10], and another in [1000,100000]), -and most part of the ill-conditioning comes from different scales of vars. - -In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2), -can greatly improve convergence. - -IMPRTANT: you should set scale of your variables with MinLBFGSSetScale() -call (before or after MinLBFGSSetPrecScale() call). Without knowledge of -the scale of your variables scale-based preconditioner will be just unit -matrix. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetprecscale(minlbfgsstate* state, ae_state *_state) -{ - - - state->prectype = 3; -} - - -/************************************************************************* -This function sets low-rank preconditioner for Hessian matrix H=D+W'*C*W, -where: -* H is a Hessian matrix, which is approximated by D/W/C -* D is a NxN diagonal positive definite matrix -* W is a KxN low-rank correction -* C is a KxK positive definite diagonal factor of low-rank correction - -This preconditioner is inexact but fast - it requires O(N*K) time to be -applied. Preconditioner P is calculated by artificially constructing a set -of BFGS updates which tries to reproduce behavior of H: -* Sk = Wk (k-th row of W) -* Yk = (D+Wk'*Ck*Wk)*Sk -* Yk/Sk are reordered by ascending of C[k]*norm(Wk)^2 - -Here we assume that rows of Wk are orthogonal or nearly orthogonal, which -allows us to have O(N*K+K^2) update instead of O(N*K^2) one. Reordering of -updates is essential for having good performance on non-orthogonal problems -(updates which do not add much of curvature are added first, and updates -which add very large eigenvalues are added last and override effect of the -first updates). - -In practice, this preconditioner is perfect when ortogonal correction is -applied; on non-orthogonal problems sometimes it allows to achieve 5x -speedup (when compared to non-preconditioned solver). - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetprecrankklbfgsfast(minlbfgsstate* state, - /* Real */ ae_vector* d, - /* Real */ ae_vector* c, - /* Real */ ae_matrix* w, - ae_int_t cnt, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t n; - - - n = state->n; - state->prectype = 4; - state->preck = cnt; - rvectorsetlengthatleast(&state->precc, cnt, _state); - rvectorsetlengthatleast(&state->precd, n, _state); - rmatrixsetlengthatleast(&state->precw, cnt, n, _state); - for(i=0; i<=n-1; i++) - { - state->precd.ptr.p_double[i] = d->ptr.p_double[i]; - } - for(i=0; i<=cnt-1; i++) - { - state->precc.ptr.p_double[i] = c->ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state->precw.ptr.pp_double[i][j] = w->ptr.pp_double[i][j]; - } - } -} - - -/************************************************************************* -This function sets exact low-rank preconditioner for Hessian matrix -H=D+W'*C*W, where: -* H is a Hessian matrix, which is approximated by D/W/C -* D is a NxN diagonal positive definite matrix -* W is a KxN low-rank correction -* C is a KxK semidefinite diagonal factor of low-rank correction - -This preconditioner is exact but slow - it requires O(N*K^2) time to be -built and O(N*K) time to be applied. Woodbury matrix identity is used to -build inverse matrix. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetpreclowrankexact(minlbfgsstate* state, - /* Real */ ae_vector* d, - /* Real */ ae_vector* c, - /* Real */ ae_matrix* w, - ae_int_t cnt, - ae_state *_state) -{ - - - state->prectype = 5; - preparelowrankpreconditioner(d, c, w, state->n, cnt, &state->lowrankbuf, _state); -} - - -/************************************************************************* -NOTES: - -1. This function has two different implementations: one which uses exact - (analytical) user-supplied gradient, and one which uses function value - only and numerically differentiates function in order to obtain - gradient. - - Depending on the specific function used to create optimizer object - (either MinLBFGSCreate() for analytical gradient or MinLBFGSCreateF() - for numerical differentiation) you should choose appropriate variant of - MinLBFGSOptimize() - one which accepts function AND gradient or one - which accepts function ONLY. - - Be careful to choose variant of MinLBFGSOptimize() which corresponds to - your optimization scheme! Table below lists different combinations of - callback (function/gradient) passed to MinLBFGSOptimize() and specific - function used to create optimizer. - - - | USER PASSED TO MinLBFGSOptimize() - CREATED WITH | function only | function and gradient - ------------------------------------------------------------ - MinLBFGSCreateF() | work FAIL - MinLBFGSCreate() | FAIL work - - Here "FAIL" denotes inappropriate combinations of optimizer creation - function and MinLBFGSOptimize() version. Attemps to use such - combination (for example, to create optimizer with MinLBFGSCreateF() and - to pass gradient information to MinCGOptimize()) will lead to exception - being thrown. Either you did not pass gradient when it WAS needed or - you passed gradient when it was NOT needed. - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -ae_bool minlbfgsiteration(minlbfgsstate* state, ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - ae_int_t i; - ae_int_t j; - ae_int_t ic; - ae_int_t mcinfo; - double v; - double vv; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - n = state->rstate.ia.ptr.p_int[0]; - m = state->rstate.ia.ptr.p_int[1]; - i = state->rstate.ia.ptr.p_int[2]; - j = state->rstate.ia.ptr.p_int[3]; - ic = state->rstate.ia.ptr.p_int[4]; - mcinfo = state->rstate.ia.ptr.p_int[5]; - v = state->rstate.ra.ptr.p_double[0]; - vv = state->rstate.ra.ptr.p_double[1]; - } - else - { - n = 359; - m = -58; - i = -919; - j = -909; - ic = 81; - mcinfo = 255; - v = 74; - vv = -788; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - if( state->rstate.stage==1 ) - { - goto lbl_1; - } - if( state->rstate.stage==2 ) - { - goto lbl_2; - } - if( state->rstate.stage==3 ) - { - goto lbl_3; - } - if( state->rstate.stage==4 ) - { - goto lbl_4; - } - if( state->rstate.stage==5 ) - { - goto lbl_5; - } - if( state->rstate.stage==6 ) - { - goto lbl_6; - } - if( state->rstate.stage==7 ) - { - goto lbl_7; - } - if( state->rstate.stage==8 ) - { - goto lbl_8; - } - if( state->rstate.stage==9 ) - { - goto lbl_9; - } - if( state->rstate.stage==10 ) - { - goto lbl_10; - } - if( state->rstate.stage==11 ) - { - goto lbl_11; - } - if( state->rstate.stage==12 ) - { - goto lbl_12; - } - if( state->rstate.stage==13 ) - { - goto lbl_13; - } - if( state->rstate.stage==14 ) - { - goto lbl_14; - } - - /* - * Routine body - */ - - /* - * Unload frequently used variables from State structure - * (just for typing convinience) - */ - n = state->n; - m = state->m; - - /* - * Init - */ - state->userterminationneeded = ae_false; - state->repterminationtype = 0; - state->repiterationscount = 0; - state->repnfev = 0; - smoothnessmonitorinit(&state->smonitor, &state->s, n, 1, state->smoothnessguardlevel>0, _state); - rvectorsetlengthatleast(&state->invs, n, _state); - for(i=0; i<=n-1; i++) - { - state->lastscaleused.ptr.p_double[i] = state->s.ptr.p_double[i]; - state->invs.ptr.p_double[i] = 1/state->s.ptr.p_double[i]; - } - - /* - * Check, that transferred derivative value is right - */ - state->stp = (double)(0); - minlbfgs_clearrequestfields(state, _state); - if( !(ae_fp_eq(state->diffstep,(double)(0))&&ae_fp_greater(state->teststep,(double)(0))) ) - { - goto lbl_15; - } -lbl_17: - if( !smoothnessmonitorcheckgradientatx0(&state->smonitor, &state->xbase, &state->s, &state->s, &state->s, ae_false, state->teststep, _state) ) - { - goto lbl_18; - } - for(i=0; i<=n-1; i++) - { - state->x.ptr.p_double[i] = state->smonitor.x.ptr.p_double[i]; - } - state->needfg = ae_true; - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - state->needfg = ae_false; - state->smonitor.fi.ptr.p_double[0] = state->f; - for(i=0; i<=n-1; i++) - { - state->smonitor.j.ptr.pp_double[0][i] = state->g.ptr.p_double[i]; - } - goto lbl_17; -lbl_18: -lbl_15: - - /* - * Calculate F/G at the initial point - */ - for(i=0; i<=n-1; i++) - { - state->x.ptr.p_double[i] = state->xbase.ptr.p_double[i]; - } - state->stp = (double)(0); - minlbfgs_clearrequestfields(state, _state); - if( ae_fp_neq(state->diffstep,(double)(0)) ) - { - goto lbl_19; - } - state->needfg = ae_true; - state->rstate.stage = 1; - goto lbl_rcomm; -lbl_1: - state->needfg = ae_false; - goto lbl_20; -lbl_19: - state->needf = ae_true; - state->rstate.stage = 2; - goto lbl_rcomm; -lbl_2: - state->fbase = state->f; - i = 0; -lbl_21: - if( i>n-1 ) - { - goto lbl_23; - } - v = state->x.ptr.p_double[i]; - state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 3; - goto lbl_rcomm; -lbl_3: - state->fm2 = state->f; - state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 4; - goto lbl_rcomm; -lbl_4: - state->fm1 = state->f; - state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 5; - goto lbl_rcomm; -lbl_5: - state->fp1 = state->f; - state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 6; - goto lbl_rcomm; -lbl_6: - state->fp2 = state->f; - state->x.ptr.p_double[i] = v; - state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]); - i = i+1; - goto lbl_21; -lbl_23: - state->f = state->fbase; - state->needf = ae_false; -lbl_20: - trimprepare(state->f, &state->trimthreshold, _state); - if( !state->xrep ) - { - goto lbl_24; - } - minlbfgs_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 7; - goto lbl_rcomm; -lbl_7: - state->xupdated = ae_false; -lbl_24: - if( state->userterminationneeded ) - { - - /* - * User requested termination - */ - state->repterminationtype = 8; - result = ae_false; - return result; - } - state->repnfev = 1; - state->fold = state->f; - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(state->g.ptr.p_double[i]*state->s.ptr.p_double[i], _state); - } - if( ae_fp_less_eq(ae_sqrt(v, _state),state->epsg) ) - { - state->repterminationtype = 4; - result = ae_false; - return result; - } - - /* - * Choose initial step and direction. - * Apply preconditioner, if we have something other than default. - */ - ae_v_moveneg(&state->d.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( state->prectype==0 ) - { - - /* - * Default preconditioner is used, but we can't use it before iterations will start - */ - v = ae_v_dotproduct(&state->g.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = ae_sqrt(v, _state); - if( ae_fp_eq(state->stpmax,(double)(0)) ) - { - state->stp = ae_minreal(1.0/v, (double)(1), _state); - } - else - { - state->stp = ae_minreal(1.0/v, state->stpmax, _state); - } - } - if( state->prectype==1 ) - { - - /* - * Cholesky preconditioner is used - */ - fblscholeskysolve(&state->denseh, 1.0, n, ae_true, &state->d, &state->autobuf, _state); - state->stp = (double)(1); - } - if( state->prectype==2 ) - { - - /* - * diagonal approximation is used - */ - for(i=0; i<=n-1; i++) - { - state->d.ptr.p_double[i] = state->d.ptr.p_double[i]/state->diagh.ptr.p_double[i]; - } - state->stp = (double)(1); - } - if( state->prectype==3 ) - { - - /* - * scale-based preconditioner is used - */ - for(i=0; i<=n-1; i++) - { - state->d.ptr.p_double[i] = state->d.ptr.p_double[i]*state->s.ptr.p_double[i]*state->s.ptr.p_double[i]; - } - state->stp = (double)(1); - } - if( state->prectype==4 ) - { - - /* - * rank-k BFGS-based preconditioner is used - */ - inexactlbfgspreconditioner(&state->d, n, &state->precd, &state->precc, &state->precw, state->preck, &state->precbuf, _state); - state->stp = (double)(1); - } - if( state->prectype==5 ) - { - - /* - * exact low-rank preconditioner is used - */ - applylowrankpreconditioner(&state->d, &state->lowrankbuf, _state); - state->stp = (double)(1); - } - - /* - * Main cycle - */ - state->k = 0; -lbl_26: - if( ae_false ) - { - goto lbl_27; - } - - /* - * Main cycle: prepare to 1-D line search - */ - state->p = state->k%m; - state->q = ae_minint(state->k, m-1, _state); - - /* - * Store X[k], G[k] - */ - ae_v_move(&state->xp.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_moveneg(&state->sk.ptr.pp_double[state->p][0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_moveneg(&state->yk.ptr.pp_double[state->p][0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - - /* - * Minimize F(x+alpha*d) - * Calculate S[k], Y[k] - */ - state->mcstage = 0; - if( state->k!=0 ) - { - state->stp = 1.0; - } - linminnormalized(&state->d, &state->stp, n, _state); - smoothnessmonitorstartlinesearch1u(&state->smonitor, &state->s, &state->invs, &state->x, state->f, &state->g, _state); - mcsrch(n, &state->x, &state->f, &state->g, &state->d, &state->stp, state->stpmax, minlbfgs_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state); -lbl_28: - if( state->mcstage==0 ) - { - goto lbl_29; - } - minlbfgs_clearrequestfields(state, _state); - if( ae_fp_neq(state->diffstep,(double)(0)) ) - { - goto lbl_30; - } - state->needfg = ae_true; - state->rstate.stage = 8; - goto lbl_rcomm; -lbl_8: - state->needfg = ae_false; - goto lbl_31; -lbl_30: - state->needf = ae_true; - state->rstate.stage = 9; - goto lbl_rcomm; -lbl_9: - state->fbase = state->f; - i = 0; -lbl_32: - if( i>n-1 ) - { - goto lbl_34; - } - v = state->x.ptr.p_double[i]; - state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 10; - goto lbl_rcomm; -lbl_10: - state->fm2 = state->f; - state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 11; - goto lbl_rcomm; -lbl_11: - state->fm1 = state->f; - state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 12; - goto lbl_rcomm; -lbl_12: - state->fp1 = state->f; - state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 13; - goto lbl_rcomm; -lbl_13: - state->fp2 = state->f; - state->x.ptr.p_double[i] = v; - state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]); - i = i+1; - goto lbl_32; -lbl_34: - state->f = state->fbase; - state->needf = ae_false; -lbl_31: - smoothnessmonitorenqueuepoint1u(&state->smonitor, &state->s, &state->invs, &state->d, state->stp, &state->x, state->f, &state->g, _state); - trimfunction(&state->f, &state->g, n, state->trimthreshold, _state); - mcsrch(n, &state->x, &state->f, &state->g, &state->d, &state->stp, state->stpmax, minlbfgs_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state); - goto lbl_28; -lbl_29: - smoothnessmonitorfinalizelinesearch(&state->smonitor, _state); - if( state->userterminationneeded ) - { - - /* - * User requested termination. - * Restore previous point and return. - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xp.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->repterminationtype = 8; - result = ae_false; - return result; - } - if( !state->xrep ) - { - goto lbl_35; - } - - /* - * report - */ - minlbfgs_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 14; - goto lbl_rcomm; -lbl_14: - state->xupdated = ae_false; -lbl_35: - state->repnfev = state->repnfev+state->nfev; - state->repiterationscount = state->repiterationscount+1; - ae_v_add(&state->sk.ptr.pp_double[state->p][0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_add(&state->yk.ptr.pp_double[state->p][0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - - /* - * Stopping conditions - */ - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(state->g.ptr.p_double[i]*state->s.ptr.p_double[i], _state); - } - if( !ae_isfinite(v, _state)||!ae_isfinite(state->f, _state) ) - { - - /* - * Abnormal termination - infinities in function/gradient - */ - state->repterminationtype = -8; - result = ae_false; - return result; - } - if( state->repiterationscount>=state->maxits&&state->maxits>0 ) - { - - /* - * Too many iterations - */ - state->repterminationtype = 5; - result = ae_false; - return result; - } - if( ae_fp_less_eq(ae_sqrt(v, _state),state->epsg) ) - { - - /* - * Gradient is small enough - */ - state->repterminationtype = 4; - result = ae_false; - return result; - } - if( ae_fp_less_eq(state->fold-state->f,state->epsf*ae_maxreal(ae_fabs(state->fold, _state), ae_maxreal(ae_fabs(state->f, _state), 1.0, _state), _state)) ) - { - - /* - * F(k+1)-F(k) is small enough - */ - state->repterminationtype = 1; - result = ae_false; - return result; - } - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(state->sk.ptr.pp_double[state->p][i]/state->s.ptr.p_double[i], _state); - } - if( ae_fp_less_eq(ae_sqrt(v, _state),state->epsx) ) - { - - /* - * X(k+1)-X(k) is small enough - */ - state->repterminationtype = 2; - result = ae_false; - return result; - } - - /* - * If Wolfe conditions are satisfied, we can update - * limited memory model. - * - * However, if conditions are not satisfied (NFEV limit is met, - * function is too wild, ...), we'll skip L-BFGS update - */ - if( mcinfo!=1 ) - { - - /* - * Skip update. - * - * In such cases we'll initialize search direction by - * antigradient vector, because it leads to more - * transparent code with less number of special cases - */ - state->fold = state->f; - ae_v_moveneg(&state->d.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - } - else - { - - /* - * Calculate Rho[k], GammaK - */ - v = ae_v_dotproduct(&state->yk.ptr.pp_double[state->p][0], 1, &state->sk.ptr.pp_double[state->p][0], 1, ae_v_len(0,n-1)); - vv = ae_v_dotproduct(&state->yk.ptr.pp_double[state->p][0], 1, &state->yk.ptr.pp_double[state->p][0], 1, ae_v_len(0,n-1)); - if( ae_fp_eq(v,(double)(0))||ae_fp_eq(vv,(double)(0)) ) - { - - /* - * Rounding errors make further iterations impossible. - */ - state->repterminationtype = -2; - result = ae_false; - return result; - } - state->rho.ptr.p_double[state->p] = 1/v; - state->gammak = v/vv; - - /* - * Calculate d(k+1) = -H(k+1)*g(k+1) - * - * for I:=K downto K-Q do - * V = s(i)^T * work(iteration:I) - * theta(i) = V - * work(iteration:I+1) = work(iteration:I) - V*Rho(i)*y(i) - * work(last iteration) = H0*work(last iteration) - preconditioner - * for I:=K-Q to K do - * V = y(i)^T*work(iteration:I) - * work(iteration:I+1) = work(iteration:I) +(-V+theta(i))*Rho(i)*s(i) - * - * NOW WORK CONTAINS d(k+1) - */ - ae_v_move(&state->work.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=state->k; i>=state->k-state->q; i--) - { - ic = i%m; - v = ae_v_dotproduct(&state->sk.ptr.pp_double[ic][0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->theta.ptr.p_double[ic] = v; - vv = v*state->rho.ptr.p_double[ic]; - ae_v_subd(&state->work.ptr.p_double[0], 1, &state->yk.ptr.pp_double[ic][0], 1, ae_v_len(0,n-1), vv); - } - if( state->prectype==0 ) - { - - /* - * Simple preconditioner is used - */ - v = state->gammak; - ae_v_muld(&state->work.ptr.p_double[0], 1, ae_v_len(0,n-1), v); - } - if( state->prectype==1 ) - { - - /* - * Cholesky preconditioner is used - */ - fblscholeskysolve(&state->denseh, (double)(1), n, ae_true, &state->work, &state->autobuf, _state); - } - if( state->prectype==2 ) - { - - /* - * diagonal approximation is used - */ - for(i=0; i<=n-1; i++) - { - state->work.ptr.p_double[i] = state->work.ptr.p_double[i]/state->diagh.ptr.p_double[i]; - } - } - if( state->prectype==3 ) - { - - /* - * scale-based preconditioner is used - */ - for(i=0; i<=n-1; i++) - { - state->work.ptr.p_double[i] = state->work.ptr.p_double[i]*state->s.ptr.p_double[i]*state->s.ptr.p_double[i]; - } - } - if( state->prectype==4 ) - { - - /* - * Rank-K BFGS-based preconditioner is used - */ - inexactlbfgspreconditioner(&state->work, n, &state->precd, &state->precc, &state->precw, state->preck, &state->precbuf, _state); - } - if( state->prectype==5 ) - { - - /* - * Exact low-rank preconditioner is used - */ - applylowrankpreconditioner(&state->work, &state->lowrankbuf, _state); - } - for(i=state->k-state->q; i<=state->k; i++) - { - ic = i%m; - v = ae_v_dotproduct(&state->yk.ptr.pp_double[ic][0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1)); - vv = state->rho.ptr.p_double[ic]*(-v+state->theta.ptr.p_double[ic]); - ae_v_addd(&state->work.ptr.p_double[0], 1, &state->sk.ptr.pp_double[ic][0], 1, ae_v_len(0,n-1), vv); - } - ae_v_moveneg(&state->d.ptr.p_double[0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1)); - - /* - * Next step - */ - state->fold = state->f; - state->k = state->k+1; - } - goto lbl_26; -lbl_27: - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = n; - state->rstate.ia.ptr.p_int[1] = m; - state->rstate.ia.ptr.p_int[2] = i; - state->rstate.ia.ptr.p_int[3] = j; - state->rstate.ia.ptr.p_int[4] = ic; - state->rstate.ia.ptr.p_int[5] = mcinfo; - state->rstate.ra.ptr.p_double[0] = v; - state->rstate.ra.ptr.p_double[1] = vv; - return result; -} - - -/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic gradient. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function at the initial point -(note: future versions may also perform check at the final point) and -compares numerical gradient with analytic one provided by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both gradients and specific components highlighted as -suspicious by the OptGuard. - -The primary OptGuard report can be retrieved with minlbfgsoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with minlbfgssetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsoptguardgradient(minlbfgsstate* state, - double teststep, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(teststep, _state), "MinLBFGSOptGuardGradient: TestStep contains NaN or INF", _state); - ae_assert(ae_fp_greater_eq(teststep,(double)(0)), "MinLBFGSOptGuardGradient: invalid argument TestStep(TestStep<0)", _state); - state->teststep = teststep; -} - - -/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) -b) nonsmooth target function (non-C1) - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsoptguardsmoothness(minlbfgsstate* state, - ae_int_t level, - ae_state *_state) -{ - - - ae_assert(level==0||level==1, "MinLBFGSOptGuardSmoothness: unexpected value of level parameter", _state); - state->smoothnessguardlevel = level; -} - - -/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -=== PRIMARY REPORT ======================================================= - -OptGuard performs several checks which are intended to catch common errors -in the implementation of nonlinear function/gradient: -* incorrect analytic gradient -* discontinuous (non-C0) target functions (constraints) -* nonsmooth (non-C1) target functions (constraints) - -Each of these checks is activated with appropriate function: -* minlbfgsoptguardgradient() for gradient verification -* minlbfgsoptguardsmoothness() for C0/C1 checks - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradvidx for specific variable (gradient element) suspected - * rep.badgradxbase, a point where gradient is tested - * rep.badgraduser, user-provided gradient (stored as 2D matrix with - single row in order to make report structure compatible with more - complex optimizers like MinNLC or MinLM) - * rep.badgradnum, reference gradient obtained via numerical - differentiation (stored as 2D matrix with single row in order to make - report structure compatible with more complex optimizers like MinNLC - or MinLM) -* rep.nonc0suspected -* rep.nonc1suspected - -=== ADDITIONAL REPORTS/LOGS ============================================== - -Several different tests are performed to catch C0/C1 errors, you can find -out specific test signaled error by looking to: -* rep.nonc0test0positive, for non-C0 test #0 -* rep.nonc1test0positive, for non-C1 test #0 -* rep.nonc1test1positive, for non-C1 test #1 - -Additional information (including line search logs) can be obtained by -means of: -* minlbfgsoptguardnonc1test0results() -* minlbfgsoptguardnonc1test1results() -which return detailed error reports, specific points where discontinuities -were found, and so on. - -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - generic OptGuard report; more detailed reports can be - retrieved with other functions. - -NOTE: false negatives (nonsmooth problems are not identified as nonsmooth - ones) are possible although unlikely. - - The reason is that you need to make several evaluations around - nonsmoothness in order to accumulate enough information about - function curvature. Say, if you start right from the nonsmooth point, - optimizer simply won't get enough data to understand what is going - wrong before it terminates due to abrupt changes in the derivative. - It is also possible that "unlucky" step will move us to the - termination too quickly. - - Our current approach is to have less than 0.1% false negatives in - our test examples (measured with multiple restarts from random - points), and to have exactly 0% false positives. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsoptguardresults(minlbfgsstate* state, - optguardreport* rep, - ae_state *_state) -{ - - _optguardreport_clear(rep); - - smoothnessmonitorexportreport(&state->smonitor, rep, _state); -} - - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #0 - -Nonsmoothness (non-C1) test #0 studies function values (not gradient!) -obtained during line searches and monitors behavior of the directional -derivative estimate. - -This test is less powerful than test #1, but it does not depend on the -gradient values and thus it is more robust against artifacts introduced by -numerical differentiation. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #0 "strong" report - lngrep - C1 test #0 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsoptguardnonc1test0results(minlbfgsstate* state, - optguardnonc1test0report* strrep, - optguardnonc1test0report* lngrep, - ae_state *_state) -{ - - _optguardnonc1test0report_clear(strrep); - _optguardnonc1test0report_clear(lngrep); - - smoothnessmonitorexportc1test0report(&state->smonitor.nonc1test0strrep, &state->lastscaleused, strrep, _state); - smoothnessmonitorexportc1test0report(&state->smonitor.nonc1test0lngrep, &state->lastscaleused, lngrep, _state); -} - - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #1 - -Nonsmoothness (non-C1) test #1 studies individual components of the -gradient computed during line search. - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #1 "strong" report - lngrep - C1 test #1 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsoptguardnonc1test1results(minlbfgsstate* state, - optguardnonc1test1report* strrep, - optguardnonc1test1report* lngrep, - ae_state *_state) -{ - - _optguardnonc1test1report_clear(strrep); - _optguardnonc1test1report_clear(lngrep); - - smoothnessmonitorexportc1test1report(&state->smonitor.nonc1test1strrep, &state->lastscaleused, strrep, _state); - smoothnessmonitorexportc1test1report(&state->smonitor.nonc1test1lngrep, &state->lastscaleused, lngrep, _state); -} - - -/************************************************************************* -L-BFGS algorithm results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report: - * Rep.TerminationType completetion code: - * -8 internal integrity control detected infinite - or NAN values in function/gradient. Abnormal - termination signalled. - * -2 rounding errors prevent further improvement. - X contains best point found. - * -1 incorrect parameters were specified - * 1 relative function improvement is no more than - EpsF. - * 2 relative step is no more than EpsX. - * 4 gradient norm is no more than EpsG - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible - * 8 terminated by user who called minlbfgsrequesttermination(). - X contains point which was "current accepted" when - termination request was submitted. - * Rep.IterationsCount contains iterations count - * NFEV countains number of function calculations - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsresults(minlbfgsstate* state, - /* Real */ ae_vector* x, - minlbfgsreport* rep, - ae_state *_state) -{ - - ae_vector_clear(x); - _minlbfgsreport_clear(rep); - - minlbfgsresultsbuf(state, x, rep, _state); -} - - -/************************************************************************* -L-BFGS algorithm results - -Buffered implementation of MinLBFGSResults which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 20.08.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsresultsbuf(minlbfgsstate* state, - /* Real */ ae_vector* x, - minlbfgsreport* rep, - ae_state *_state) -{ - - - if( x->cntn ) - { - ae_vector_set_length(x, state->n, _state); - } - ae_v_move(&x->ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - rep->iterationscount = state->repiterationscount; - rep->nfev = state->repnfev; - rep->terminationtype = state->repterminationtype; -} - - -/************************************************************************* -This subroutine restarts LBFGS algorithm from new point. All optimization -parameters are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure used to store algorithm state - X - new starting point. - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsrestartfrom(minlbfgsstate* state, - /* Real */ ae_vector* x, - ae_state *_state) -{ - - - ae_assert(x->cnt>=state->n, "MinLBFGSRestartFrom: Length(X)n, _state), "MinLBFGSRestartFrom: X contains infinite or NaN values!", _state); - ae_v_move(&state->xbase.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - ae_vector_set_length(&state->rstate.ia, 5+1, _state); - ae_vector_set_length(&state->rstate.ra, 1+1, _state); - state->rstate.stage = -1; - minlbfgs_clearrequestfields(state, _state); -} - - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsrequesttermination(minlbfgsstate* state, ae_state *_state) -{ - - - state->userterminationneeded = ae_true; -} - - -/************************************************************************* -Clears request fileds (to be sure that we don't forgot to clear something) -*************************************************************************/ -static void minlbfgs_clearrequestfields(minlbfgsstate* state, - ae_state *_state) -{ - - - state->needf = ae_false; - state->needfg = ae_false; - state->xupdated = ae_false; -} - - -void _minlbfgsstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minlbfgsstate *p = (minlbfgsstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rho, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->yk, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->sk, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xp, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->theta, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->work, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xbase, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->denseh, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->diagh, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->precc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->precd, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->precw, 0, 0, DT_REAL, _state, make_automatic); - _precbuflbfgs_init(&p->precbuf, _state, make_automatic); - _precbuflowrank_init(&p->lowrankbuf, _state, make_automatic); - ae_vector_init(&p->autobuf, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->invs, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); - _linminstate_init(&p->lstate, _state, make_automatic); - _smoothnessmonitor_init(&p->smonitor, _state, make_automatic); - ae_vector_init(&p->lastscaleused, 0, DT_REAL, _state, make_automatic); -} - - -void _minlbfgsstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minlbfgsstate *dst = (minlbfgsstate*)_dst; - minlbfgsstate *src = (minlbfgsstate*)_src; - dst->n = src->n; - dst->m = src->m; - dst->epsg = src->epsg; - dst->epsf = src->epsf; - dst->epsx = src->epsx; - dst->maxits = src->maxits; - dst->xrep = src->xrep; - dst->stpmax = src->stpmax; - ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic); - dst->diffstep = src->diffstep; - dst->nfev = src->nfev; - dst->mcstage = src->mcstage; - dst->k = src->k; - dst->q = src->q; - dst->p = src->p; - ae_vector_init_copy(&dst->rho, &src->rho, _state, make_automatic); - ae_matrix_init_copy(&dst->yk, &src->yk, _state, make_automatic); - ae_matrix_init_copy(&dst->sk, &src->sk, _state, make_automatic); - ae_vector_init_copy(&dst->xp, &src->xp, _state, make_automatic); - ae_vector_init_copy(&dst->theta, &src->theta, _state, make_automatic); - ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic); - dst->stp = src->stp; - ae_vector_init_copy(&dst->work, &src->work, _state, make_automatic); - dst->fold = src->fold; - dst->trimthreshold = src->trimthreshold; - ae_vector_init_copy(&dst->xbase, &src->xbase, _state, make_automatic); - dst->prectype = src->prectype; - dst->gammak = src->gammak; - ae_matrix_init_copy(&dst->denseh, &src->denseh, _state, make_automatic); - ae_vector_init_copy(&dst->diagh, &src->diagh, _state, make_automatic); - ae_vector_init_copy(&dst->precc, &src->precc, _state, make_automatic); - ae_vector_init_copy(&dst->precd, &src->precd, _state, make_automatic); - ae_matrix_init_copy(&dst->precw, &src->precw, _state, make_automatic); - dst->preck = src->preck; - _precbuflbfgs_init_copy(&dst->precbuf, &src->precbuf, _state, make_automatic); - _precbuflowrank_init_copy(&dst->lowrankbuf, &src->lowrankbuf, _state, make_automatic); - dst->fbase = src->fbase; - dst->fm2 = src->fm2; - dst->fm1 = src->fm1; - dst->fp1 = src->fp1; - dst->fp2 = src->fp2; - ae_vector_init_copy(&dst->autobuf, &src->autobuf, _state, make_automatic); - ae_vector_init_copy(&dst->invs, &src->invs, _state, make_automatic); - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - dst->f = src->f; - ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic); - dst->needf = src->needf; - dst->needfg = src->needfg; - dst->xupdated = src->xupdated; - dst->userterminationneeded = src->userterminationneeded; - dst->teststep = src->teststep; - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); - dst->repiterationscount = src->repiterationscount; - dst->repnfev = src->repnfev; - dst->repterminationtype = src->repterminationtype; - _linminstate_init_copy(&dst->lstate, &src->lstate, _state, make_automatic); - dst->smoothnessguardlevel = src->smoothnessguardlevel; - _smoothnessmonitor_init_copy(&dst->smonitor, &src->smonitor, _state, make_automatic); - ae_vector_init_copy(&dst->lastscaleused, &src->lastscaleused, _state, make_automatic); -} - - -void _minlbfgsstate_clear(void* _p) -{ - minlbfgsstate *p = (minlbfgsstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->s); - ae_vector_clear(&p->rho); - ae_matrix_clear(&p->yk); - ae_matrix_clear(&p->sk); - ae_vector_clear(&p->xp); - ae_vector_clear(&p->theta); - ae_vector_clear(&p->d); - ae_vector_clear(&p->work); - ae_vector_clear(&p->xbase); - ae_matrix_clear(&p->denseh); - ae_vector_clear(&p->diagh); - ae_vector_clear(&p->precc); - ae_vector_clear(&p->precd); - ae_matrix_clear(&p->precw); - _precbuflbfgs_clear(&p->precbuf); - _precbuflowrank_clear(&p->lowrankbuf); - ae_vector_clear(&p->autobuf); - ae_vector_clear(&p->invs); - ae_vector_clear(&p->x); - ae_vector_clear(&p->g); - _rcommstate_clear(&p->rstate); - _linminstate_clear(&p->lstate); - _smoothnessmonitor_clear(&p->smonitor); - ae_vector_clear(&p->lastscaleused); -} - - -void _minlbfgsstate_destroy(void* _p) -{ - minlbfgsstate *p = (minlbfgsstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->s); - ae_vector_destroy(&p->rho); - ae_matrix_destroy(&p->yk); - ae_matrix_destroy(&p->sk); - ae_vector_destroy(&p->xp); - ae_vector_destroy(&p->theta); - ae_vector_destroy(&p->d); - ae_vector_destroy(&p->work); - ae_vector_destroy(&p->xbase); - ae_matrix_destroy(&p->denseh); - ae_vector_destroy(&p->diagh); - ae_vector_destroy(&p->precc); - ae_vector_destroy(&p->precd); - ae_matrix_destroy(&p->precw); - _precbuflbfgs_destroy(&p->precbuf); - _precbuflowrank_destroy(&p->lowrankbuf); - ae_vector_destroy(&p->autobuf); - ae_vector_destroy(&p->invs); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->g); - _rcommstate_destroy(&p->rstate); - _linminstate_destroy(&p->lstate); - _smoothnessmonitor_destroy(&p->smonitor); - ae_vector_destroy(&p->lastscaleused); -} - - -void _minlbfgsreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minlbfgsreport *p = (minlbfgsreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _minlbfgsreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minlbfgsreport *dst = (minlbfgsreport*)_dst; - minlbfgsreport *src = (minlbfgsreport*)_src; - dst->iterationscount = src->iterationscount; - dst->nfev = src->nfev; - dst->terminationtype = src->terminationtype; -} - - -void _minlbfgsreport_clear(void* _p) -{ - minlbfgsreport *p = (minlbfgsreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _minlbfgsreport_destroy(void* _p) -{ - minlbfgsreport *p = (minlbfgsreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_LPQPSERV) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function generates scaled (by S) and shifted (by XC) reformulation of -the box constraints. - -INPUT PARAMETERS: - S - scale vector, array[N]: - * I-th element contains scale of I-th variable, - * SC[I]>0 - XOrigin - origin term, array[N]. Can be zero. - BndL - raw lower bounds, array[N] - BndU - raw upper bounds, array[N] - N - number of variables. - -OUTPUT PARAMETERS: - BndL - replaced by scaled/shifted lower bounds, array[N] - BndU - replaced by scaled/shifted upper bounds, array[N] - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void scaleshiftbcinplace(/* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_bool hasbndl; - ae_bool hasbndu; - - - for(i=0; i<=n-1; i++) - { - ae_assert(ae_isfinite(s->ptr.p_double[i], _state)&&s->ptr.p_double[i]>0.0, "ScaleShiftBC: S[i] is nonpositive", _state); - ae_assert(ae_isfinite(bndl->ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "ScaleShiftBC: BndL[i] is +INF or NAN", _state); - ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "ScaleShiftBC: BndU[i] is -INF or NAN", _state); - hasbndl = ae_isfinite(bndl->ptr.p_double[i], _state); - hasbndu = ae_isfinite(bndu->ptr.p_double[i], _state); - if( (hasbndl&&hasbndu)&&ae_fp_eq(bndl->ptr.p_double[i],bndu->ptr.p_double[i]) ) - { - - /* - * Make sure that BndL[I]=BndU[I] bit-to-bit - * even with CRAZY optimizing compiler. - */ - bndu->ptr.p_double[i] = (bndu->ptr.p_double[i]-xorigin->ptr.p_double[i])/s->ptr.p_double[i]; - bndl->ptr.p_double[i] = bndu->ptr.p_double[i]; - continue; - } - if( hasbndl ) - { - bndl->ptr.p_double[i] = (bndl->ptr.p_double[i]-xorigin->ptr.p_double[i])/s->ptr.p_double[i]; - } - if( hasbndu ) - { - bndu->ptr.p_double[i] = (bndu->ptr.p_double[i]-xorigin->ptr.p_double[i])/s->ptr.p_double[i]; - } - } -} - - -/************************************************************************* -This function generates scaled (by S) and shifted (by XC) reformulation of -two-sided "lower-bound/range" constraints stored in dense format. - -INPUT PARAMETERS: - S - scale vector, array[N]: - * I-th element contains scale of I-th variable, - * SC[I]>0 - XOrigin - origin term, array[N]. Can be zero. - N - number of variables. - DenseA - array[M,N], constraint matrix - AB - lower bounds for constraints, always present and - finite, array[M] - AR - ranges for constraints, can be zero (equality - constraint), positive (range constraint) or +INF - (lower bound constraint), array[M] - M - constraint count, M>=0 - -OUTPUT PARAMETERS: - DenseA - replaced by scaled/shifted constraints, array[M,N] - AB - replaced by scaled/shifted lower bounds, array[M] - AR - replaced by scaled/shifted ranges, array[M] - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void scaleshiftdensebrlcinplace(/* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - ae_int_t n, - /* Real */ ae_matrix* densea, - /* Real */ ae_vector* ab, - /* Real */ ae_vector* ar, - ae_int_t m, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - double vv; - - - for(i=0; i<=m-1; i++) - { - - /* - * Scale/shift constraint; shift its lower bound - * - * NOTE: range is NOT scaled or shifted - */ - v = 0.0; - for(j=0; j<=n-1; j++) - { - vv = densea->ptr.pp_double[i][j]; - v = v+vv*xorigin->ptr.p_double[j]; - densea->ptr.pp_double[i][j] = vv*s->ptr.p_double[j]; - } - ab->ptr.p_double[i] = ab->ptr.p_double[i]-v; - } -} - - -/************************************************************************* -This function generates scaled (by S) and shifted (by XC) reformulation of -two-sided "lower-bound/range" constraints stored in dense format. - -INPUT PARAMETERS: - S - scale vector, array[N]: - * I-th element contains scale of I-th variable, - * SC[I]>0 - XOrigin - origin term, array[N]. Can be zero. - N - number of variables. - SparseA - sparse MSparse*N constraint matrix in CRS format; - ignored if MSparse=0. - MSparse - dense constraint count, MSparse>=0 - DenseA - array[MDense,N], constraint matrix; - ignored if MDense=0. - MDense - dense constraint count, MDense>=0 - AB - lower bounds for constraints, always present and - finite, array[MSparse+MDense] - AR - ranges for constraints, can be zero (equality - constraint), positive (range constraint) or +INF - (lower bound constraint), array[MSparse+MDense] - -OUTPUT PARAMETERS: - DenseA - replaced by scaled/shifted constraints, array[MDense,N] - SparseA - replaced by scaled/shifted constraints, array[MSparse,N] - AB - replaced by scaled/shifted lower bounds, array[MDense+MSparse] - AR - replaced by scaled/shifted ranges, array[MDense+MSparse] - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void scaleshiftmixedbrlcinplace(/* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - ae_int_t n, - sparsematrix* sparsea, - ae_int_t msparse, - /* Real */ ae_matrix* densea, - ae_int_t mdense, - /* Real */ ae_vector* ab, - /* Real */ ae_vector* ar, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t k0; - ae_int_t k1; - double v; - double vv; - - - ae_assert(msparse==0||((sparsea->matrixtype==1&&sparsea->m==msparse)&&sparsea->n==n), "ScaleShiftMixedBRLCInplace: non-CRS sparse constraint matrix!", _state); - for(i=0; i<=msparse-1; i++) - { - - /* - * Scale/shift constraint; shift its lower bound - * - * NOTE: range is NOT scaled or shifted - */ - v = 0.0; - k0 = sparsea->ridx.ptr.p_int[i]; - k1 = sparsea->ridx.ptr.p_int[i+1]-1; - for(k=k0; k<=k1; k++) - { - j = sparsea->idx.ptr.p_int[k]; - vv = sparsea->vals.ptr.p_double[k]; - v = v+vv*xorigin->ptr.p_double[j]; - sparsea->vals.ptr.p_double[k] = vv*s->ptr.p_double[j]; - } - ab->ptr.p_double[i] = ab->ptr.p_double[i]-v; - } - for(i=0; i<=mdense-1; i++) - { - - /* - * Scale/shift constraint; shift its lower bound - * - * NOTE: range is NOT scaled or shifted - */ - v = 0.0; - for(j=0; j<=n-1; j++) - { - vv = densea->ptr.pp_double[i][j]; - v = v+vv*xorigin->ptr.p_double[j]; - densea->ptr.pp_double[i][j] = vv*s->ptr.p_double[j]; - } - ab->ptr.p_double[msparse+i] = ab->ptr.p_double[msparse+i]-v; - } -} - - -/************************************************************************* -This function generates scaled (by S) reformulation of dense quadratic and -linear terms in QP problem. - -INPUT PARAMETERS: - N - number of variables. - DenseA - array[NMain,NMain], quadratic term - IsUpper - whether upper or lower triangle is present - NMain - number of nonslack vars, 1<=NMain<=NTotal - DenseB - array[NTotal], linear term - NTotal - total number of variables, NTotal>=1 - S - scale vector, array[NTotal]: - * I-th element contains scale of I-th variable, - * SC[I]>0 - -OUTPUT PARAMETERS: - DenseA - replaced by scaled term, array[N,N] - DenseB - replaced by scaled term, array[N] - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void scaledenseqpinplace(/* Real */ ae_matrix* densea, - ae_bool isupper, - ae_int_t nmain, - /* Real */ ae_vector* denseb, - ae_int_t ntotal, - /* Real */ ae_vector* s, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t j0; - ae_int_t j1; - double si; - - - for(i=0; i<=nmain-1; i++) - { - si = s->ptr.p_double[i]; - if( isupper ) - { - j0 = i; - j1 = nmain-1; - } - else - { - j0 = 0; - j1 = i; - } - for(j=j0; j<=j1; j++) - { - densea->ptr.pp_double[i][j] = densea->ptr.pp_double[i][j]*si*s->ptr.p_double[j]; - } - } - for(i=0; i<=ntotal-1; i++) - { - denseb->ptr.p_double[i] = denseb->ptr.p_double[i]*s->ptr.p_double[i]; - } -} - - -/************************************************************************* -This function generates scaled (by S) reformulation of sparse quadratic and -linear terms in QP problem. - -INPUT PARAMETERS: - S - scale vector, array[N]: - * I-th element contains scale of I-th variable, - * SC[I]>0 - N - number of variables. - SparseA - NxN SparseMatrix in CRS format (any triangle can - be present, we will scale everything) - DenseB - array[N], linear term - -OUTPUT PARAMETERS: - SparseA - replaced by scaled term - DenseB - replaced by scaled term - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void scalesparseqpinplace(/* Real */ ae_vector* s, - ae_int_t n, - sparsematrix* sparsea, - /* Real */ ae_vector* denseb, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k0; - ae_int_t k1; - ae_int_t k; - double si; - - - ae_assert((sparsea->matrixtype==1&&sparsea->m==n)&&sparsea->n==n, "ScaleSparseQPInplace: SparseA in unexpected format", _state); - for(i=0; i<=n-1; i++) - { - si = s->ptr.p_double[i]; - k0 = sparsea->ridx.ptr.p_int[i]; - k1 = sparsea->ridx.ptr.p_int[i+1]-1; - for(k=k0; k<=k1; k++) - { - sparsea->vals.ptr.p_double[k] = sparsea->vals.ptr.p_double[k]*si*s->ptr.p_double[sparsea->idx.ptr.p_int[k]]; - } - denseb->ptr.p_double[i] = denseb->ptr.p_double[i]*si; - } -} - - -/************************************************************************* -This function normalizes two-sided "lower-bound/range" constraints stored -in dense format in such a way that L2 norms of rows (right hand side NOT -included) become equal to 1.0. Exactly zero rows are handled correctly. - -INPUT PARAMETERS: - DenseA - array[M,N], constraint matrix - AB - lower bounds for constraints, always present and - finite, array[M] - AR - ranges for constraints, can be zero (equality - constraint), positive (range constraint) or +INF - (lower bound constraint), array[M] - N - number of variables, N>=1. - M - constraint count, M>=0 - NeedNorms - whether we need row norms or not - -OUTPUT PARAMETERS: - DenseA - replaced by normalized constraints, array[M,N] - AB - replaced by normalized lower bounds, array[M] - AR - replaced by normalized ranges, array[M] - RowNorms - if NeedNorms is true, leading M elements (resized - if length is less than M) are filled by row norms - before normalization was performed. - - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void normalizedensebrlcinplace(/* Real */ ae_matrix* densea, - /* Real */ ae_vector* ab, - /* Real */ ae_vector* ar, - ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* rownorms, - ae_bool neednorms, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - double vv; - - - if( neednorms ) - { - rvectorsetlengthatleast(rownorms, m, _state); - } - for(i=0; i<=m-1; i++) - { - vv = 0.0; - for(j=0; j<=n-1; j++) - { - v = densea->ptr.pp_double[i][j]; - vv = vv+v*v; - } - vv = ae_sqrt(vv, _state); - if( neednorms ) - { - rownorms->ptr.p_double[i] = vv; - } - if( ae_fp_greater(vv,(double)(0)) ) - { - vv = 1/vv; - for(j=0; j<=n-1; j++) - { - densea->ptr.pp_double[i][j] = densea->ptr.pp_double[i][j]*vv; - } - ab->ptr.p_double[i] = ab->ptr.p_double[i]*vv; - if( ae_isfinite(ar->ptr.p_double[i], _state) ) - { - ar->ptr.p_double[i] = ar->ptr.p_double[i]*vv; - } - } - } -} - - -/************************************************************************* -This function normalizes two-sided "lower-bound/range" constraints stored -in dense format in such a way that L2 norms of rows (right hand side NOT -included) become equal to 1.0. Exactly zero rows are handled correctly. - -INPUT PARAMETERS: - SparseA - sparse MSparse*N constraint matrix in CRS format; - ignored if MSparse=0. - MSparse - dense constraint count, MSparse>=0 - DenseA - array[MDense,N], constraint matrix; - ignored if MDense=0. - MDense - dense constraint count, MDense>=0 - AB - lower bounds for constraints, always present and - finite, array[MSparse+MDense] - AR - ranges for constraints, can be zero (equality - constraint), positive (range constraint) or +INF - (lower bound constraint), array[MSparse+MDense] - N - number of variables, N>=1. - LimitedAmplification- whether row amplification is limited or not: - * if False, rows with small norms (less than 1.0) - are always normalized - * if True, we do not increase individual row norms - during normalization - only decrease. However, - we may apply one amplification rount to entire - constraint matrix, i.e. amplify all rows by same - coefficient. As result, we do not overamplify - any single row, but still make sure than entire - problem is well scaled. - If True, only large rows are normalized. - NeedNorms - whether we need row norms or not - -OUTPUT PARAMETERS: - DenseA - replaced by normalized constraints, array[M,N] - AB - replaced by normalized lower bounds, array[M] - AR - replaced by normalized ranges, array[M] - RowNorms - if NeedNorms is true, leading M elements (resized - if length is less than M) are filled by row norms - before normalization was performed. - - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void normalizemixedbrlcinplace(sparsematrix* sparsea, - ae_int_t msparse, - /* Real */ ae_matrix* densea, - ae_int_t mdense, - /* Real */ ae_vector* ab, - /* Real */ ae_vector* ar, - ae_int_t n, - ae_bool limitedamplification, - /* Real */ ae_vector* rownorms, - ae_bool neednorms, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t k0; - ae_int_t k1; - double v; - double vv; - double maxnrm2; - - - ae_assert(msparse==0||((sparsea->matrixtype==1&&sparsea->m==msparse)&&sparsea->n==n), "ScaleShiftMixedBRLCInplace: non-CRS sparse constraint matrix!", _state); - if( neednorms ) - { - rvectorsetlengthatleast(rownorms, mdense+msparse, _state); - } - - /* - * First round of normalization - normalize row 2-norms subject to limited amplification status - */ - maxnrm2 = (double)(0); - for(i=0; i<=msparse-1; i++) - { - vv = 0.0; - k0 = sparsea->ridx.ptr.p_int[i]; - k1 = sparsea->ridx.ptr.p_int[i+1]-1; - for(k=k0; k<=k1; k++) - { - v = sparsea->vals.ptr.p_double[k]; - vv = vv+v*v; - } - vv = ae_sqrt(vv, _state); - maxnrm2 = ae_maxreal(maxnrm2, vv, _state); - if( limitedamplification ) - { - vv = ae_maxreal(vv, 1.0, _state); - } - if( neednorms ) - { - rownorms->ptr.p_double[i] = vv; - } - if( ae_fp_greater(vv,(double)(0)) ) - { - vv = 1/vv; - for(k=k0; k<=k1; k++) - { - sparsea->vals.ptr.p_double[k] = sparsea->vals.ptr.p_double[k]*vv; - } - ab->ptr.p_double[i] = ab->ptr.p_double[i]*vv; - if( ae_isfinite(ar->ptr.p_double[i], _state) ) - { - ar->ptr.p_double[i] = ar->ptr.p_double[i]*vv; - } - } - } - for(i=0; i<=mdense-1; i++) - { - vv = 0.0; - for(j=0; j<=n-1; j++) - { - v = densea->ptr.pp_double[i][j]; - vv = vv+v*v; - } - vv = ae_sqrt(vv, _state); - maxnrm2 = ae_maxreal(maxnrm2, vv, _state); - if( limitedamplification ) - { - vv = ae_maxreal(vv, 1.0, _state); - } - if( neednorms ) - { - rownorms->ptr.p_double[msparse+i] = vv; - } - if( ae_fp_greater(vv,(double)(0)) ) - { - vv = 1/vv; - for(j=0; j<=n-1; j++) - { - densea->ptr.pp_double[i][j] = densea->ptr.pp_double[i][j]*vv; - } - ab->ptr.p_double[msparse+i] = ab->ptr.p_double[msparse+i]*vv; - if( ae_isfinite(ar->ptr.p_double[msparse+i], _state) ) - { - ar->ptr.p_double[msparse+i] = ar->ptr.p_double[msparse+i]*vv; - } - } - } - - /* - * If amplification was limited, perform second round of normalization - */ - if( (limitedamplification&&ae_fp_less(maxnrm2,1.0))&&ae_fp_greater(maxnrm2,(double)(0)) ) - { - if( neednorms ) - { - rmulv(mdense+msparse, maxnrm2, rownorms, _state); - } - vv = 1/maxnrm2; - for(i=0; i<=msparse-1; i++) - { - k0 = sparsea->ridx.ptr.p_int[i]; - k1 = sparsea->ridx.ptr.p_int[i+1]-1; - for(k=k0; k<=k1; k++) - { - sparsea->vals.ptr.p_double[k] = sparsea->vals.ptr.p_double[k]*vv; - } - ab->ptr.p_double[i] = ab->ptr.p_double[i]*vv; - if( ae_isfinite(ar->ptr.p_double[i], _state) ) - { - ar->ptr.p_double[i] = ar->ptr.p_double[i]*vv; - } - } - for(i=0; i<=mdense-1; i++) - { - rmulr(n, vv, densea, i, _state); - ab->ptr.p_double[msparse+i] = ab->ptr.p_double[msparse+i]*vv; - if( ae_isfinite(ar->ptr.p_double[msparse+i], _state) ) - { - ar->ptr.p_double[msparse+i] = ar->ptr.p_double[msparse+i]*vv; - } - } - } -} - - -/************************************************************************* -This function normalizes dense QP problem in such a way that maximum over -its linear/quadratic coefficients max(max(A),max(B)) becomes equal to 1.0. - -NOTE: completely zero A and B are handled correctly. - -INPUT PARAMETERS: - DenseA - array[NMain,NMain], quadratic term - IsUpper - whether upper or lower triangle is present - NMain - number of nonslack vars, 1<=NMain<=NTotal - DenseB - array[NTotal], linear term - NTotal - total number of variables. - -OUTPUT PARAMETERS: - DenseA - replaced by normalized term - DenseB - replaced by normalized term - -RESULT: - max(max(A),max(B)) is returned - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -double normalizedenseqpinplace(/* Real */ ae_matrix* densea, - ae_bool isupper, - ae_int_t nmain, - /* Real */ ae_vector* denseb, - ae_int_t ntotal, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t j0; - ae_int_t j1; - double mx; - double v; - double result; - - - mx = (double)(0); - for(i=0; i<=nmain-1; i++) - { - if( isupper ) - { - j0 = i; - j1 = nmain-1; - } - else - { - j0 = 0; - j1 = i; - } - for(j=j0; j<=j1; j++) - { - mx = ae_maxreal(mx, ae_fabs(densea->ptr.pp_double[i][j], _state), _state); - } - } - for(i=0; i<=ntotal-1; i++) - { - mx = ae_maxreal(mx, ae_fabs(denseb->ptr.p_double[i], _state), _state); - } - result = mx; - if( ae_fp_eq(mx,(double)(0)) ) - { - return result; - } - v = 1/mx; - for(i=0; i<=nmain-1; i++) - { - if( isupper ) - { - j0 = i; - j1 = nmain-1; - } - else - { - j0 = 0; - j1 = i; - } - for(j=j0; j<=j1; j++) - { - densea->ptr.pp_double[i][j] = densea->ptr.pp_double[i][j]*v; - } - } - for(i=0; i<=ntotal-1; i++) - { - denseb->ptr.p_double[i] = denseb->ptr.p_double[i]*v; - } - return result; -} - - -/************************************************************************* -This function normalizes sparse QP problem in such a way that maximum over -its linear/quadratic coefficients max(max(A),max(B)) becomes equal to 1.0. - -NOTE: completely zero A and B are handled correctly. - -INPUT PARAMETERS: - SparseA - Sparse NxN matrix, either upper or lower triangle, - diagonal MUST be present - IsUpper - which triangle is present (other one is ignored) - DenseB - array[N], linear term - N - number of variables. - -OUTPUT PARAMETERS: - DenseA - replaced by normalized term, array[N,N] - DenseB - replaced by normalized term, array[N] - -RESULT: - max(max(A),max(B)) is returned - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -double normalizesparseqpinplace(sparsematrix* sparsea, - ae_bool isupper, - /* Real */ ae_vector* denseb, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - ae_int_t k0; - ae_int_t k1; - double mx; - double v; - double result; - - - ae_assert((sparsea->matrixtype==1&&sparsea->m==n)&&sparsea->n==n, "ScaleSparseQPInplace: SparseA in unexpected format", _state); - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - ae_assert(sparsea->didx.ptr.p_int[i]+1==sparsea->uidx.ptr.p_int[i], "NormalizeSparseQPInplace: critical integrity check failed, sparse diagonal not found", _state); - if( isupper ) - { - k0 = sparsea->didx.ptr.p_int[i]; - k1 = sparsea->ridx.ptr.p_int[i+1]-1; - } - else - { - k0 = sparsea->ridx.ptr.p_int[i]; - k1 = sparsea->didx.ptr.p_int[i]; - } - for(k=k0; k<=k1; k++) - { - mx = ae_maxreal(mx, ae_fabs(sparsea->vals.ptr.p_double[k], _state), _state); - } - mx = ae_maxreal(mx, ae_fabs(denseb->ptr.p_double[i], _state), _state); - } - result = mx; - if( ae_fp_eq(mx,(double)(0)) ) - { - return result; - } - v = 1/mx; - for(i=0; i<=n-1; i++) - { - k0 = sparsea->ridx.ptr.p_int[i]; - k1 = sparsea->ridx.ptr.p_int[i+1]-1; - for(k=k0; k<=k1; k++) - { - sparsea->vals.ptr.p_double[k] = sparsea->vals.ptr.p_double[k]*v; - } - denseb->ptr.p_double[i] = denseb->ptr.p_double[i]*v; - } - return result; -} - - -/************************************************************************* -This function performs transformation of X from scaled/shifted coordinates -to unscaled/unshifted ones, paying special attention to box constraints: -* points which were exactly at the boundary before scaling will be mapped - to corresponding boundary after scaling -* in any case, unscaled box constraints will be satisfied - - -- ALGLIB -- - Copyright 02.06.2015 by Bochkanov Sergey -*************************************************************************/ -void unscaleunshiftpointbc(/* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - /* Real */ ae_vector* rawbndl, - /* Real */ ae_vector* rawbndu, - /* Real */ ae_vector* sclsftbndl, - /* Real */ ae_vector* sclsftbndu, - /* Boolean */ ae_vector* hasbndl, - /* Boolean */ ae_vector* hasbndu, - /* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=n-1; i++) - { - if( hasbndl->ptr.p_bool[i]&&ae_fp_less_eq(x->ptr.p_double[i],sclsftbndl->ptr.p_double[i]) ) - { - x->ptr.p_double[i] = rawbndl->ptr.p_double[i]; - continue; - } - if( hasbndu->ptr.p_bool[i]&&ae_fp_greater_eq(x->ptr.p_double[i],sclsftbndu->ptr.p_double[i]) ) - { - x->ptr.p_double[i] = rawbndu->ptr.p_double[i]; - continue; - } - x->ptr.p_double[i] = x->ptr.p_double[i]*s->ptr.p_double[i]+xorigin->ptr.p_double[i]; - if( hasbndl->ptr.p_bool[i]&&ae_fp_less_eq(x->ptr.p_double[i],rawbndl->ptr.p_double[i]) ) - { - x->ptr.p_double[i] = rawbndl->ptr.p_double[i]; - } - if( hasbndu->ptr.p_bool[i]&&ae_fp_greater_eq(x->ptr.p_double[i],rawbndu->ptr.p_double[i]) ) - { - x->ptr.p_double[i] = rawbndu->ptr.p_double[i]; - } - } -} - - -#endif -#if defined(AE_COMPILE_VIPMSOLVER) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Initializes QP-IPM state and prepares it to receive quadratic/linear terms -and constraints. - -The solver is configured to work internally with dense NxN factorization, -no matter what exactly is passed - dense or sparse matrices. - -INPUT PARAMETERS: - State - solver state to be configured; previously allocated - memory is reused as much as possible - S - scale vector, array[N]: - * I-th element contains scale of I-th variable, - * S[I]>0 - XOrigin - origin term, array[N]. Can be zero. The solver solves - problem of the form - - > - > min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin)) - > - - The terms A and b (as well as constraints) will be - specified later with separate calls. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void vipminitdense(vipmstate* state, - /* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - ae_int_t n, - ae_state *_state) -{ - - - ae_assert(n>=1, "VIPMInitDense: N<1", _state); - ae_assert(isfinitevector(s, n, _state), "VIPMInitDense: S contains infinite or NaN elements", _state); - ae_assert(isfinitevector(xorigin, n, _state), "VIPMInitDense: XOrigin contains infinite or NaN elements", _state); - vipmsolver_vipminit(state, s, xorigin, n, n, 0, _state); -} - - -/************************************************************************* -Initializes QP-IPM state and prepares it to receive quadratic/linear terms -and constraints. - -The solver is configured to work internally with dense NxN problem divided -into two distinct parts - "main" and slack one: -* dense quadratic term is a NMain*NMain matrix (NMain<=N), quadratic - coefficients are zero for variables outside of [0,NMain) range) -* linear term is general vector of length N -* linear constraints have special structure for variable with indexes in - [NMain,N) range: at most one element per column can be nonzero. - -This mode is intended for problems arising during SL1QP nonlinear programming. - -INPUT PARAMETERS: - State - solver state to be configured; previously allocated - memory is reused as much as possible - S - scale vector, array[N]: - * I-th element contains scale of I-th variable, - * S[I]>0 - XOrigin - origin term, array[N]. Can be zero. The solver solves - problem of the form - - > - > min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin)) - > - - The terms A and b (as well as constraints) will be - specified later with separate calls. - NMain - number of "main" variables, 1<=NMain<=N - N - total number of variables including slack ones - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void vipminitdensewithslacks(vipmstate* state, - /* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - ae_int_t nmain, - ae_int_t n, - ae_state *_state) -{ - - - ae_assert(nmain>=1, "VIPMInitDense: NMain<1", _state); - ae_assert(n>=1, "VIPMInitDense: N<1", _state); - ae_assert(nmain<=n, "VIPMInitDense: NMain>N", _state); - ae_assert(isfinitevector(s, n, _state), "VIPMInitDense: S contains infinite or NaN elements", _state); - ae_assert(isfinitevector(xorigin, n, _state), "VIPMInitDense: XOrigin contains infinite or NaN elements", _state); - vipmsolver_vipminit(state, s, xorigin, n, nmain, 0, _state); -} - - -/************************************************************************* -Initializes QP-IPM state and prepares it to receive quadratic/linear terms -and constraints. - -The solver is configured to work internally with sparse (N+M)x(N+M) -factorization no matter what exactly is passed - dense or sparse matrices. -Dense quadratic term will be sparsified prior to storage. - -INPUT PARAMETERS: - State - solver state to be configured; previously allocated - memory is reused as much as possible - S - scale vector, array[N]: - * I-th element contains scale of I-th variable, - * S[I]>0 - XOrigin - origin term, array[N]. Can be zero. The solver solves - problem of the form - > - > min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin)) - > - The terms A and b (as well as constraints) will be - specified later with separate calls. - N - total number of variables, N>=1 - -This optimization mode assumes that no slack variables is present. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void vipminitsparse(vipmstate* state, - /* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - ae_int_t n, - ae_state *_state) -{ - - - ae_assert(n>=1, "VIPMInitSparse: N<1", _state); - ae_assert(isfinitevector(s, n, _state), "VIPMInitSparse: S contains infinite or NaN elements", _state); - ae_assert(isfinitevector(xorigin, n, _state), "VIPMInitSparse: XOrigin contains infinite or NaN elements", _state); - vipmsolver_vipminit(state, s, xorigin, n, n, 1, _state); -} - - -/************************************************************************* -Sets linear/quadratic terms for QP-IPM solver - -If you initialized solver with VIMPInitDenseWithSlacks(), NMain below is a -number of non-slack variables. In other cases, NMain=N. - -INPUT PARAMETERS: - State - instance initialized with one of the initialization - functions - DenseH - if HKind=0: array[NMain,NMain], dense quadratic term - (either upper or lower triangle) - SparseH - if HKind=1: array[NMain,NMain], sparse quadratic term - (either upper or lower triangle) - HKind - 0 or 1, quadratic term format - IsUpper - whether dense/sparse H contains lower or upper - triangle of the quadratic term - C - array[N], linear term - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void vipmsetquadraticlinear(vipmstate* state, - /* Real */ ae_matrix* denseh, - sparsematrix* sparseh, - ae_int_t hkind, - ae_bool isupper, - /* Real */ ae_vector* c, - ae_state *_state) -{ - ae_int_t nmain; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t j0; - ae_int_t j1; - double v; - double vv; - ae_int_t nnz; - ae_int_t offs; - - - nmain = state->nmain; - n = state->n; - ae_assert(hkind==0||hkind==1, "VIPMSetQuadraticLinear: incorrect HKind", _state); - ae_assert(isfinitevector(c, n, _state), "VIPMSetQuadraticLinear: C contains infinite or NaN elements", _state); - ae_assert(state->factorizationtype==0||state->factorizationtype==1, "VIPMSetQuadraticLinear: unexpected factorization type", _state); - - /* - * Set problem info, reset factorization flag - */ - state->islinear = ae_false; - state->factorizationpresent = ae_false; - state->factorizationpoweredup = ae_false; - - /* - * Linear term - */ - rvectorsetlengthatleast(&state->c, n, _state); - rvectorcopy(n, c, 0, &state->c, 0, _state); - - /* - * Quadratic term and normalization - * - * NOTE: we perform integrity check for inifinities/NANs by - * computing sum of all matrix elements and checking its - * value for being finite. It is a bit faster than checking - * each element individually. - */ - state->hkind = -1; - state->targetscale = 1.0; - if( state->factorizationtype==0 ) - { - - /* - * Quadratic term is stored in dense format: either copy dense - * term of densify sparse one - */ - state->hkind = 0; - rmatrixsetlengthatleast(&state->denseh, nmain, nmain, _state); - if( hkind==0 ) - { - - /* - * Copy dense quadratic term - */ - if( isupper ) - { - rmatrixtranspose(nmain, nmain, denseh, 0, 0, &state->denseh, 0, 0, _state); - } - else - { - rmatrixcopy(nmain, nmain, denseh, 0, 0, &state->denseh, 0, 0, _state); - } - } - if( hkind==1 ) - { - - /* - * Extract sparse quadratic term - */ - ae_assert(sparseh->matrixtype==1, "VIPMSetQuadraticLinear: unexpected sparse matrix format", _state); - ae_assert(sparseh->m==nmain, "VIPMSetQuadraticLinear: unexpected sparse matrix size", _state); - ae_assert(sparseh->n==nmain, "VIPMSetQuadraticLinear: unexpected sparse matrix size", _state); - for(i=0; i<=nmain-1; i++) - { - for(j=0; j<=i; j++) - { - state->denseh.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=nmain-1; i++) - { - - /* - * diagonal element - */ - if( sparseh->didx.ptr.p_int[i]!=sparseh->uidx.ptr.p_int[i] ) - { - state->denseh.ptr.pp_double[i][i] = sparseh->vals.ptr.p_double[sparseh->didx.ptr.p_int[i]]; - } - - /* - * Off-diagonal elements - */ - if( isupper ) - { - - /* - * superdiagonal elements are moved to subdiagonal part - */ - j0 = sparseh->uidx.ptr.p_int[i]; - j1 = sparseh->ridx.ptr.p_int[i+1]-1; - for(j=j0; j<=j1; j++) - { - state->denseh.ptr.pp_double[sparseh->idx.ptr.p_int[j]][i] = sparseh->vals.ptr.p_double[j]; - } - } - else - { - - /* - * subdiagonal elements are moved to subdiagonal part - */ - j0 = sparseh->ridx.ptr.p_int[i]; - j1 = sparseh->didx.ptr.p_int[i]-1; - for(j=j0; j<=j1; j++) - { - state->denseh.ptr.pp_double[i][sparseh->idx.ptr.p_int[j]] = sparseh->vals.ptr.p_double[j]; - } - } - } - } - vv = (double)(0); - for(i=0; i<=nmain-1; i++) - { - for(j=0; j<=i; j++) - { - vv = vv+state->denseh.ptr.pp_double[i][j]; - } - } - ae_assert(ae_isfinite(vv, _state), "VIPMSetQuadraticLinear: DenseH contains infinite or NaN values!", _state); - scaledenseqpinplace(&state->denseh, ae_false, nmain, &state->c, n, &state->scl, _state); - state->targetscale = normalizedenseqpinplace(&state->denseh, ae_false, nmain, &state->c, n, _state); - } - if( state->factorizationtype==1 ) - { - ae_assert(nmain==n, "VIPMSetQuadraticLinear: critical integrity check failed, NMain!=N", _state); - - /* - * Quadratic term is stored in sparse format: either sparsify dense - * term of copy sparse one - */ - state->hkind = 1; - state->sparseh.matrixtype = 1; - state->sparseh.m = n; - state->sparseh.n = n; - if( hkind==0 ) - { - - /* - * Sparsify dense term - */ - nnz = 0; - for(i=0; i<=n-1; i++) - { - nnz = nnz+1; - if( isupper ) - { - j0 = i+1; - j1 = n-1; - } - else - { - j0 = 0; - j1 = i-1; - } - for(j=j0; j<=j1; j++) - { - if( denseh->ptr.pp_double[i][j]!=0 ) - { - nnz = nnz+1; - } - } - } - ivectorsetlengthatleast(&state->sparseh.ridx, n+1, _state); - ivectorsetlengthatleast(&state->sparseh.idx, nnz, _state); - rvectorsetlengthatleast(&state->sparseh.vals, nnz, _state); - state->sparseh.ridx.ptr.p_int[0] = 0; - offs = 0; - vv = (double)(0); - for(i=0; i<=n-1; i++) - { - - /* - * Off-diagonal elements are copied only when nonzero - */ - if( !isupper ) - { - for(j=0; j<=i-1; j++) - { - if( denseh->ptr.pp_double[i][j]!=0 ) - { - v = denseh->ptr.pp_double[i][j]; - state->sparseh.idx.ptr.p_int[offs] = j; - state->sparseh.vals.ptr.p_double[offs] = v; - vv = vv+v; - offs = offs+1; - } - } - } - - /* - * Diagonal element is always copied - */ - v = denseh->ptr.pp_double[i][i]; - state->sparseh.idx.ptr.p_int[offs] = i; - state->sparseh.vals.ptr.p_double[offs] = v; - vv = vv+v; - offs = offs+1; - - /* - * Off-diagonal elements are copied only when nonzero - */ - if( isupper ) - { - for(j=i+1; j<=n-1; j++) - { - if( denseh->ptr.pp_double[i][j]!=0 ) - { - v = denseh->ptr.pp_double[i][j]; - state->sparseh.idx.ptr.p_int[offs] = j; - state->sparseh.vals.ptr.p_double[offs] = v; - vv = vv+v; - offs = offs+1; - } - } - } - - /* - * Finalize row - */ - state->sparseh.ridx.ptr.p_int[i+1] = offs; - } - ae_assert(ae_isfinite(vv, _state), "VIPMSetQuadraticLinear: DenseH contains infinite or NaN values!", _state); - ae_assert(offs==nnz, "VIPMSetQuadraticLinear: integrity check failed", _state); - sparsecreatecrsinplace(&state->sparseh, _state); - } - if( hkind==1 ) - { - - /* - * Copy sparse quadratic term, but make sure that we have diagonal elements - * present (we add diagonal if it is not present) - */ - ae_assert(sparseh->matrixtype==1, "VIPMSetQuadraticLinear: unexpected sparse matrix format", _state); - ae_assert(sparseh->m==n, "VIPMSetQuadraticLinear: unexpected sparse matrix size", _state); - ae_assert(sparseh->n==n, "VIPMSetQuadraticLinear: unexpected sparse matrix size", _state); - ivectorsetlengthatleast(&state->sparseh.ridx, n+1, _state); - ivectorsetlengthatleast(&state->sparseh.idx, sparseh->ridx.ptr.p_int[n]+n, _state); - rvectorsetlengthatleast(&state->sparseh.vals, sparseh->ridx.ptr.p_int[n]+n, _state); - state->sparseh.ridx.ptr.p_int[0] = 0; - offs = 0; - vv = (double)(0); - for(i=0; i<=n-1; i++) - { - - /* - * Copy subdiagonal elements (if needed) - */ - if( !isupper ) - { - j0 = sparseh->ridx.ptr.p_int[i]; - j1 = sparseh->didx.ptr.p_int[i]-1; - for(k=j0; k<=j1; k++) - { - v = sparseh->vals.ptr.p_double[k]; - state->sparseh.idx.ptr.p_int[offs] = sparseh->idx.ptr.p_int[k]; - state->sparseh.vals.ptr.p_double[offs] = v; - vv = vv+v; - offs = offs+1; - } - } - - /* - * Diagonal element is always copied - */ - v = (double)(0); - if( sparseh->uidx.ptr.p_int[i]!=sparseh->didx.ptr.p_int[i] ) - { - v = sparseh->vals.ptr.p_double[sparseh->didx.ptr.p_int[i]]; - } - state->sparseh.idx.ptr.p_int[offs] = i; - state->sparseh.vals.ptr.p_double[offs] = v; - vv = vv+v; - offs = offs+1; - - /* - * Copy superdiagonal elements (if needed) - */ - if( isupper ) - { - j0 = sparseh->uidx.ptr.p_int[i]; - j1 = sparseh->ridx.ptr.p_int[i+1]-1; - for(k=j0; k<=j1; k++) - { - v = sparseh->vals.ptr.p_double[k]; - state->sparseh.idx.ptr.p_int[offs] = sparseh->idx.ptr.p_int[k]; - state->sparseh.vals.ptr.p_double[offs] = v; - vv = vv+v; - offs = offs+1; - } - } - - /* - * Finalize row - */ - state->sparseh.ridx.ptr.p_int[i+1] = offs; - } - ae_assert(ae_isfinite(vv, _state), "VIPMSetQuadraticLinear: SparseH contains infinite or NaN values!", _state); - ae_assert(offs<=state->sparseh.vals.cnt&&offs<=state->sparseh.idx.cnt, "VIPMSetQuadraticLinear: integrity check failed", _state); - sparsecreatecrsinplace(&state->sparseh, _state); - if( isupper ) - { - sparsecopytransposecrsbuf(&state->sparseh, &state->tmpsparse0, _state); - sparsecopybuf(&state->tmpsparse0, &state->sparseh, _state); - } - } - scalesparseqpinplace(&state->scl, n, &state->sparseh, &state->c, _state); - state->targetscale = normalizesparseqpinplace(&state->sparseh, ae_false, &state->c, n, _state); - } - ae_assert(state->hkind>=0, "VIPMSetQuadraticLinear: integrity check failed", _state); -} - - -/************************************************************************* -Sets constraints for QP-IPM solver - -INPUT PARAMETERS: - State - instance initialized with one of the initialization - functions - BndL, BndU - lower and upper bound. BndL[] can be -INF, - BndU[] can be +INF. - SparseA - sparse constraint matrix, CRS format - MSparse - number of sparse constraints - DenseA - array[MDense,N], dense part of the constraints - MDense - number of dense constraints - CL, CU - lower and upper bounds for constraints, first - MSparse are bounds for sparse part, following - MDense ones are bounds for dense part, - MSparse+MDense in total. - -INF <= CL[I] <= CU[I] <= +INF. - -This function throws exception if constraints have inconsistent bounds, i.e. -either BndL[I]>BndU[I] or CL[I]>CU[I]. In all other cases it succeeds. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void vipmsetconstraints(vipmstate* state, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - sparsematrix* sparsea, - ae_int_t msparse, - /* Real */ ae_matrix* densea, - ae_int_t mdense, - /* Real */ ae_vector* cl, - /* Real */ ae_vector* cu, - ae_state *_state) -{ - ae_int_t m; - ae_int_t n; - ae_int_t nmain; - ae_int_t nslack; - ae_int_t i; - ae_int_t j; - ae_int_t j0; - ae_int_t j1; - ae_int_t k; - ae_int_t offsmain; - ae_int_t offscombined; - double vs; - double v; - - - n = state->n; - nmain = state->nmain; - nslack = n-nmain; - ae_assert(mdense>=0, "VIPMSetConstraints: MDense<0", _state); - ae_assert(msparse>=0, "VIPMSetConstraints: MSparse<0", _state); - ae_assert(apservisfinitematrix(densea, mdense, n, _state), "VIPMSetConstraints: DenseA contains infinite or NaN values!", _state); - ae_assert(msparse==0||sparsea->matrixtype==1, "VIPMSetConstraints: non-CRS constraint matrix!", _state); - ae_assert(msparse==0||(sparsea->m==msparse&&sparsea->n==n), "VIPMSetConstraints: constraint matrix has incorrect size", _state); - ae_assert(cl->cnt>=mdense+msparse, "VIPMSetConstraints: CL is too short!", _state); - ae_assert(cu->cnt>=mdense+msparse, "VIPMSetConstraints: CU is too short!", _state); - - /* - * Reset factorization flag - */ - state->factorizationpresent = ae_false; - state->factorizationpoweredup = ae_false; - - /* - * Box constraints - */ - rvectorsetlengthatleast(&state->bndl, n, _state); - rvectorsetlengthatleast(&state->bndu, n, _state); - rvectorsetlengthatleast(&state->rawbndl, n, _state); - rvectorsetlengthatleast(&state->rawbndu, n, _state); - bvectorsetlengthatleast(&state->hasbndl, n, _state); - bvectorsetlengthatleast(&state->hasbndu, n, _state); - for(i=0; i<=n-1; i++) - { - state->hasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state); - state->hasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state); - ae_assert(!((state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_greater(bndl->ptr.p_double[i],bndu->ptr.p_double[i])), "VIPMInitDenseQuadratic: inconsistent range for box constraints", _state); - state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i]; - state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i]; - state->rawbndl.ptr.p_double[i] = bndl->ptr.p_double[i]; - state->rawbndu.ptr.p_double[i] = bndu->ptr.p_double[i]; - } - scaleshiftbcinplace(&state->scl, &state->xorigin, &state->bndl, &state->bndu, n, _state); - - /* - * Linear constraints (full matrices) - */ - m = mdense+msparse; - rvectorsetlengthatleast(&state->b, m, _state); - rvectorsetlengthatleast(&state->r, m, _state); - rvectorsetlengthatleast(&state->ascales, m, _state); - bvectorsetlengthatleast(&state->aflips, m, _state); - bvectorsetlengthatleast(&state->hasr, m, _state); - rmatrixsetlengthatleast(&state->denseafull, mdense, n, _state); - if( msparse>0 ) - { - sparsecopytocrsbuf(sparsea, &state->sparseafull, _state); - } - if( mdense>0 ) - { - rmatrixcopy(mdense, n, densea, 0, 0, &state->denseafull, 0, 0, _state); - } - for(i=0; i<=m-1; i++) - { - ae_assert(ae_isfinite(cl->ptr.p_double[i], _state)||ae_isneginf(cl->ptr.p_double[i], _state), "VIPMInitDenseQuadratic: CL is not finite number or -INF", _state); - ae_assert(ae_isfinite(cu->ptr.p_double[i], _state)||ae_isposinf(cu->ptr.p_double[i], _state), "VIPMInitDenseQuadratic: CU is not finite number or +INF", _state); - - /* - * Store range - */ - if( ae_isfinite(cl->ptr.p_double[i], _state)||ae_isfinite(cu->ptr.p_double[i], _state) ) - { - - /* - * Non-degenerate constraint, at least one of bounds is present - */ - if( ae_isfinite(cl->ptr.p_double[i], _state) ) - { - ae_assert(!ae_isfinite(cu->ptr.p_double[i], _state)||ae_fp_greater_eq(cu->ptr.p_double[i],cl->ptr.p_double[i]), "VIPMInitDenseQuadratic: inconsistent range (right-hand side) for linear constraint", _state); - if( ae_isfinite(cu->ptr.p_double[i], _state) ) - { - - /* - * We have both CL and CU, i.e. CL <= A*x <= CU. - * - * It can be either equality constraint (no slacks) or range constraint - * (two pairs of slacks variables). - * - * Try to arrange things in such a way that |CU|>=|CL| (it can be done - * by multiplication by -1 and boundaries swap). - * - * Having |CU|>=|CL| will allow us to drop huge irrelevant bound CU, - * if we find it irrelevant during computations. Due to limitations - * of our slack variable substitution, it can be done only for CU. - */ - if( ae_fp_greater_eq(ae_fabs(cu->ptr.p_double[i], _state),ae_fabs(cl->ptr.p_double[i], _state)) ) - { - state->b.ptr.p_double[i] = cl->ptr.p_double[i]; - state->r.ptr.p_double[i] = cu->ptr.p_double[i]-cl->ptr.p_double[i]; - state->hasr.ptr.p_bool[i] = ae_true; - state->aflips.ptr.p_bool[i] = ae_false; - vs = (double)(1); - } - else - { - state->b.ptr.p_double[i] = -cu->ptr.p_double[i]; - state->r.ptr.p_double[i] = cu->ptr.p_double[i]-cl->ptr.p_double[i]; - state->hasr.ptr.p_bool[i] = ae_true; - state->aflips.ptr.p_bool[i] = ae_true; - vs = (double)(-1); - } - } - else - { - - /* - * Only lower bound: CL <= A*x. - * - * One pair of slack variables added. - */ - state->b.ptr.p_double[i] = cl->ptr.p_double[i]; - state->r.ptr.p_double[i] = _state->v_posinf; - state->hasr.ptr.p_bool[i] = ae_false; - state->aflips.ptr.p_bool[i] = ae_false; - vs = (double)(1); - } - } - else - { - - /* - * Only upper bound: A*x <= CU - * - * One pair of slack variables added. - */ - state->b.ptr.p_double[i] = -cu->ptr.p_double[i]; - state->r.ptr.p_double[i] = _state->v_posinf; - state->hasr.ptr.p_bool[i] = ae_false; - state->aflips.ptr.p_bool[i] = ae_true; - vs = (double)(-1); - } - } - else - { - - /* - * Degenerate constraint -inf <= Ax <= +inf. - * Generate dummy formulation. - */ - state->b.ptr.p_double[i] = (double)(-1); - state->r.ptr.p_double[i] = (double)(2); - state->hasr.ptr.p_bool[i] = ae_true; - state->aflips.ptr.p_bool[i] = ae_false; - vs = (double)(0); - } - - /* - * Store matrix row and its scaling coefficient - */ - if( isparseafull.ridx.ptr.p_int[i]; - j1 = state->sparseafull.ridx.ptr.p_int[i+1]-1; - for(j=j0; j<=j1; j++) - { - state->sparseafull.vals.ptr.p_double[j] = state->sparseafull.vals.ptr.p_double[j]*vs; - } - } - else - { - for(j=0; j<=n-1; j++) - { - state->denseafull.ptr.pp_double[i-msparse][j] = state->denseafull.ptr.pp_double[i-msparse][j]*vs; - } - } - state->ascales.ptr.p_double[i] = vs; - } - scaleshiftmixedbrlcinplace(&state->scl, &state->xorigin, n, &state->sparseafull, msparse, &state->denseafull, mdense, &state->b, &state->r, _state); - normalizemixedbrlcinplace(&state->sparseafull, msparse, &state->denseafull, mdense, &state->b, &state->r, n, ae_true, &state->tmp0, ae_true, _state); - for(i=0; i<=m-1; i++) - { - state->ascales.ptr.p_double[i] = state->ascales.ptr.p_double[i]*state->tmp0.ptr.p_double[i]; - } - state->mdense = mdense; - state->msparse = msparse; - - /* - * Separate main and slack parts of the constraint matrices - */ - ivectorsetlengthatleast(&state->tmpi, nslack, _state); - for(i=0; i<=nslack-1; i++) - { - state->tmpi.ptr.p_int[i] = 0; - } - state->combinedaslack.m = mdense+msparse; - state->combinedaslack.n = nslack; - ivectorsetlengthatleast(&state->combinedaslack.ridx, mdense+msparse+1, _state); - ivectorsetlengthatleast(&state->combinedaslack.idx, nslack, _state); - rvectorsetlengthatleast(&state->combinedaslack.vals, nslack, _state); - state->combinedaslack.ridx.ptr.p_int[0] = 0; - state->sparseamain.m = msparse; - state->sparseamain.n = nmain; - if( msparse>0 ) - { - ivectorsetlengthatleast(&state->sparseamain.ridx, msparse+1, _state); - ivectorsetlengthatleast(&state->sparseamain.idx, sparsea->ridx.ptr.p_int[msparse], _state); - rvectorsetlengthatleast(&state->sparseamain.vals, sparsea->ridx.ptr.p_int[msparse], _state); - state->sparseamain.ridx.ptr.p_int[0] = 0; - for(i=0; i<=msparse-1; i++) - { - offsmain = state->sparseamain.ridx.ptr.p_int[i]; - offscombined = state->combinedaslack.ridx.ptr.p_int[i]; - j0 = state->sparseafull.ridx.ptr.p_int[i]; - j1 = state->sparseafull.ridx.ptr.p_int[i+1]-1; - for(j=j0; j<=j1; j++) - { - v = state->sparseafull.vals.ptr.p_double[j]; - k = state->sparseafull.idx.ptr.p_int[j]; - if( ksparseamain.idx.ptr.p_int[offsmain] = k; - state->sparseamain.vals.ptr.p_double[offsmain] = v; - offsmain = offsmain+1; - } - else - { - ae_assert(state->tmpi.ptr.p_int[k-nmain]==0, "VIPMSetConstraints: slack column contains more than one nonzero element", _state); - state->combinedaslack.idx.ptr.p_int[offscombined] = k-nmain; - state->combinedaslack.vals.ptr.p_double[offscombined] = v; - state->tmpi.ptr.p_int[k-nmain] = state->tmpi.ptr.p_int[k-nmain]+1; - offscombined = offscombined+1; - } - } - state->sparseamain.ridx.ptr.p_int[i+1] = offsmain; - state->combinedaslack.ridx.ptr.p_int[i+1] = offscombined; - } - } - sparsecreatecrsinplace(&state->sparseamain, _state); - if( mdense>0 ) - { - rmatrixsetlengthatleast(&state->denseamain, mdense, nmain, _state); - rmatrixcopy(mdense, nmain, &state->denseafull, 0, 0, &state->denseamain, 0, 0, _state); - for(i=0; i<=mdense-1; i++) - { - offscombined = state->combinedaslack.ridx.ptr.p_int[msparse+i]; - for(k=nmain; k<=n-1; k++) - { - if( state->denseafull.ptr.pp_double[i][k]!=0 ) - { - ae_assert(state->tmpi.ptr.p_int[k-nmain]==0, "VIPMSetConstraints: slack column contains more than one nonzero element", _state); - state->combinedaslack.idx.ptr.p_int[offscombined] = k-nmain; - state->combinedaslack.vals.ptr.p_double[offscombined] = state->denseafull.ptr.pp_double[i][k]; - state->tmpi.ptr.p_int[k-nmain] = state->tmpi.ptr.p_int[k-nmain]+1; - offscombined = offscombined+1; - } - } - state->combinedaslack.ridx.ptr.p_int[msparse+i+1] = offscombined; - } - } - sparsecreatecrsinplace(&state->combinedaslack, _state); -} - - -/************************************************************************* -Sets stopping criteria for QP-IPM solver. - -You can set all epsilon-values to one small value, about 1.0E-6. - -INPUT PARAMETERS: - State - instance initialized with one of the initialization - functions - EpsP - maximum primal error allowed in the solution, - EpsP>=0. Zero will be automatically replaced - by recommended default value, which is equal - to 10*Sqrt(Epsilon) in the current version - EpsD - maximum dual error allowed in the solution, - EpsP>=0. Zero will be automatically replaced - by recommended default value, which is equal - to 10*Sqrt(Epsilon) in the current version - EpsGap - maximum duality gap allowed in the solution, - EpsP>=0. Zero will be automatically replaced - by recommended default value, which is equal - to 10*Sqrt(Epsilon) in the current version - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void vipmsetcond(vipmstate* state, - double epsp, - double epsd, - double epsgap, - ae_state *_state) -{ - double sml; - - - ae_assert(ae_isfinite(epsp, _state)&&ae_fp_greater_eq(epsp,(double)(0)), "VIPMSetCond: EpsP is infinite or negative", _state); - ae_assert(ae_isfinite(epsd, _state)&&ae_fp_greater_eq(epsd,(double)(0)), "VIPMSetCond: EpsD is infinite or negative", _state); - ae_assert(ae_isfinite(epsgap, _state)&&ae_fp_greater_eq(epsgap,(double)(0)), "VIPMSetCond: EpsP is infinite or negative", _state); - sml = ae_sqrt(ae_machineepsilon, _state); - state->epsp = coalesce(epsp, sml, _state); - state->epsd = coalesce(epsd, sml, _state); - state->epsgap = coalesce(epsgap, sml, _state); -} - - -/************************************************************************* -Solve QP problem. - -INPUT PARAMETERS: - State - solver instance - DropBigBounds - If True, algorithm may drop box and linear constraints - with huge bound values that destabilize algorithm. - -OUTPUT PARAMETERS: - XS - array[N], solution - LagBC - array[N], Lagrange multipliers for box constraints - LagLC - array[M], Lagrange multipliers for linear constraints - TerminationType - completion code, positive values for success, - negative for failures (XS constrains best point - found so far): - * -2 the task is either unbounded or infeasible; - the IPM solver has difficulty distinguishing between these two. - * +1 stopping criteria are met - * +7 stopping criteria are too stringent - -RESULT: - -This function ALWAYS returns something meaningful in XS, LagBC, LagLC - -either solution or the best point so far, even for negative TerminationType. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void vipmoptimize(vipmstate* state, - ae_bool dropbigbounds, - /* Real */ ae_vector* xs, - /* Real */ ae_vector* lagbc, - /* Real */ ae_vector* laglc, - ae_int_t* terminationtype, - ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - ae_int_t i; - ae_int_t iteridx; - double mu; - double muaff; - double sigma; - double alphaaffp; - double alphaaffd; - double alphap; - double alphad; - ae_int_t primalstagnationcnt; - ae_int_t dualstagnationcnt; - double regeps; - double dampeps; - double safedampeps; - double modeps; - double maxdampeps; - double regfree; - double dampfree; - ae_int_t droppedbounds; - double primalxscale; - double errp2; - double errd2; - double errpinf; - double errdinf; - double preverrp2; - double preverrd2; - double errgap; - double eprimal; - double edual; - double egap; - double mumin; - double mustop; - double y0nrm; - double bady; - double mxprimal; - double mxdeltaprimal; - ae_int_t bestiteridx; - double besterr; - double bestegap; - double besteprimal; - double bestedual; - ae_bool loadbest; - - *terminationtype = 0; - - n = state->n; - m = state->mdense+state->msparse; - state->dotrace = ae_is_trace_enabled("IPM"); - state->dodetailedtrace = state->dotrace&&ae_is_trace_enabled("IPM.DETAILED"); - - /* - * Prepare outputs - */ - rsetallocv(n, 0.0, xs, _state); - rsetallocv(n, 0.0, lagbc, _state); - rsetallocv(m, 0.0, laglc, _state); - - /* - * Some integrity checks: - * * we need PrimalStagnationLendotrace ) - { - ae_trace("\n\n"); - ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n"); - ae_trace("// IPM SOLVER STARTED //\n"); - ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n"); - } - - /* - * Prepare regularization coefficients: - * * RegEps - one that is applied to initial (5N+5M)x(5N+5M) KKT system. This one has to be - * small because it perturbs solution returned by the algorithm. Essential in order to - * avoid stalling at extremely large points. - * * ModEps - small modification applied to LDLT decomposition in order to preserve sign - * of diagonal elements - * * DampEps - damping coefficient for damped Newton step. Comes along with SafeDampEps - * (threshold value when some safeguards are turned off in order to preserve convergence - * speed) and MaxDampEps - threshold value when we consider problem overregularized and stop. - * * DampFree - additional damping coefficient for free variables - */ - regfree = ae_pow(ae_machineepsilon, 0.75, _state); - dampfree = (double)(0); - regeps = 100*ae_machineepsilon; - modeps = (100+ae_sqrt((double)(n), _state))*ae_machineepsilon; - dampeps = (100+ae_sqrt((double)(n), _state))*ae_machineepsilon; - safedampeps = ae_sqrt(ae_machineepsilon, _state); - maxdampeps = ae_sqrt(ae_sqrt(ae_machineepsilon, _state), _state); - - /* - * Set up initial state - */ - state->repiterationscount = 0; - state->repncholesky = 0; - mustop = (100+ae_sqrt((double)(n), _state))*ae_machineepsilon; - mumin = 0.01*mustop; - vipmsolver_vipmpowerup(state, regfree, _state); - vipmsolver_varsinitfrom(&state->x0, &state->current, _state); - vipmsolver_varsinitfrom(&state->best, &state->current, _state); - vipmsolver_varsinitbyzero(&state->zerovars, n, m, _state); - bestiteridx = -1; - besterr = ae_maxrealnumber; - bestegap = ae_maxrealnumber; - besteprimal = ae_maxrealnumber; - bestedual = ae_maxrealnumber; - vipmsolver_traceprogress(state, 0.0, 0.0, 0.0, 0.0, 0.0, _state); - y0nrm = (double)(0); - y0nrm = ae_maxreal(y0nrm, rmaxabsv(m, &state->current.y, _state), _state); - y0nrm = ae_maxreal(y0nrm, rmaxabsv(m, &state->current.v, _state), _state); - y0nrm = ae_maxreal(y0nrm, rmaxabsv(m, &state->current.q, _state), _state); - y0nrm = ae_maxreal(y0nrm, rmaxabsv(n, &state->current.z, _state), _state); - y0nrm = ae_maxreal(y0nrm, rmaxabsv(n, &state->current.s, _state), _state); - - /* - * Start iteration - */ - loadbest = ae_true; - primalstagnationcnt = 0; - dualstagnationcnt = 0; - *terminationtype = 7; - errp2 = ae_maxrealnumber; - errd2 = ae_maxrealnumber; - for(iteridx=0; iteridx<=vipmsolver_maxipmits-1; iteridx++) - { - vipmsolver_varsinitfrom(&state->x0, &state->current, _state); - - /* - * Trace beginning - */ - if( state->dotrace ) - { - ae_trace("=== PREDICTOR-CORRECTOR STEP %2d ====================================================================\n", - (int)(iteridx)); - } - - /* - * Check regularization status, terminate if overregularized - */ - if( ae_fp_greater_eq(dampeps,maxdampeps) ) - { - if( state->dotrace ) - { - ae_trace("> tried to increase regularization parameter, but it is too large\n"); - ae_trace("> it is likely that stopping conditions are too stringent, stopping at the best point found so far\n"); - } - *terminationtype = 7; - break; - } - - /* - * Precompute factorization - * - * NOTE: we use "solver" regularization coefficient at this moment - */ - if( !vipmsolver_vipmprecomputenewtonfactorization(state, &state->current, regeps, modeps, dampeps, dampfree, _state) ) - { - - /* - * KKT factorization failed. - * Increase regularization parameter and skip this iteration. - */ - dampeps = 10*dampeps; - if( state->dotrace ) - { - ae_trace("> LDLT factorization failed due to rounding errors\n"); - ae_trace("> increasing damping coefficient to %0.2e, skipping iteration\n", - (double)(dampeps)); - } - continue; - } - - /* - * Compute Mu - */ - mu = vipmsolver_varscomputemu(&state->current, _state); - - /* - * Compute affine scaling step for Mehrotra's predictor-corrector algorithm - */ - vipmsolver_varsinitbyzero(&state->deltaaff, n, m, _state); - if( !vipmsolver_vipmcomputestepdirection(state, &state->current, 0.0, &state->zerovars, &state->deltaaff, regeps, ae_fp_greater_eq(dampeps,safedampeps), _state) ) - { - - /* - * Affine scaling step failed due to numerical errors. - * Increase regularization parameter and skip this iteration. - */ - dampeps = 10*dampeps; - if( state->dotrace ) - { - ae_trace("> affine scaling step failed to decrease residual due to rounding errors\n"); - ae_trace("> increasing damping coefficient to %0.2e, skipping iteration\n", - (double)(dampeps)); - } - continue; - } - vipmsolver_vipmcomputesteplength(state, &state->current, &state->deltaaff, vipmsolver_steplengthdecay, &alphaaffp, &alphaaffd, _state); - - /* - * Compute MuAff and centering parameter - */ - vipmsolver_varsinitfrom(&state->trial, &state->current, _state); - vipmsolver_varsaddstep(&state->trial, &state->deltaaff, alphaaffp, alphaaffd, _state); - muaff = vipmsolver_varscomputemu(&state->trial, _state); - sigma = ae_minreal(ae_pow((muaff+mumin)/(mu+mumin), (double)(3), _state), 1.0, _state); - ae_assert(ae_isfinite(sigma, _state)&&ae_fp_less_eq(sigma,(double)(1)), "VIPMOptimize: critical integrity check failed for Sigma (infinite or greater than 1)", _state); - - /* - * Compute corrector step - */ - vipmsolver_varsinitbyzero(&state->deltacorr, n, m, _state); - if( !vipmsolver_vipmcomputestepdirection(state, &state->current, sigma*mu+mumin, &state->deltaaff, &state->deltacorr, regeps, ae_fp_greater_eq(dampeps,safedampeps), _state) ) - { - - /* - * Affine scaling step failed due to numerical errors. - * Increase regularization parameter and skip this iteration. - */ - dampeps = 10*dampeps; - if( state->dotrace ) - { - ae_trace("> corrector step failed to decrease residual due to rounding errors\n"); - ae_trace("> increasing damping coefficient to %0.2e, skipping iteration\n", - (double)(dampeps)); - } - continue; - } - vipmsolver_vipmcomputesteplength(state, &state->current, &state->deltacorr, vipmsolver_steplengthdecay, &alphap, &alphad, _state); - if( ae_fp_greater_eq((double)(iteridx),vipmsolver_minitersbeforesafeguards)&&(ae_fp_less_eq(alphap,vipmsolver_badsteplength)||ae_fp_less_eq(alphad,vipmsolver_badsteplength)) ) - { - - /* - * Affine scaling step failed due to numerical errors. - * Increase regularization parameter and skip this iteration. - */ - dampeps = 10*dampeps; - if( state->dotrace ) - { - ae_trace("> step length is too short, suspecting rounding errors\n"); - ae_trace("> increasing damping coefficient to %0.2e, skipping iteration\n", - (double)(dampeps)); - } - continue; - } - - /* - * Perform a step - */ - vipmsolver_runintegritychecks(state, &state->current, &state->deltacorr, alphap, alphad, _state); - vipmsolver_vipmperformstep(state, alphap, alphad, _state); - vipmsolver_traceprogress(state, mu, muaff, sigma, alphap, alphad, _state); - - /* - * Check for excessive bounds (one that are so large that they are both irrelevant - * and destabilizing due to their magnitude) - */ - if( dropbigbounds&&iteridx>=vipmsolver_minitersbeforedroppingbounds ) - { - ae_assert(ae_fp_less_eq(10*vipmsolver_bigconstrmag,1/vipmsolver_bigconstrxtol), "VIPMOptimize: integrity check failed (incorrect BigConstr settings)", _state); - droppedbounds = 0; - - /* - * Determine variable and step scales. - * Both quantities are bounded from below by 1.0 - */ - mxprimal = 1.0; - mxprimal = ae_maxreal(mxprimal, rmaxabsv(n, &state->current.x, _state), _state); - mxprimal = ae_maxreal(mxprimal, rmaxabsv(n, &state->current.g, _state), _state); - mxprimal = ae_maxreal(mxprimal, rmaxabsv(n, &state->current.t, _state), _state); - mxprimal = ae_maxreal(mxprimal, rmaxabsv(m, &state->current.w, _state), _state); - mxprimal = ae_maxreal(mxprimal, rmaxabsv(m, &state->current.p, _state), _state); - mxdeltaprimal = 1.0; - mxdeltaprimal = ae_maxreal(mxdeltaprimal, alphap*rmaxabsv(n, &state->deltacorr.x, _state), _state); - mxdeltaprimal = ae_maxreal(mxdeltaprimal, alphap*rmaxabsv(n, &state->deltacorr.g, _state), _state); - mxdeltaprimal = ae_maxreal(mxdeltaprimal, alphap*rmaxabsv(n, &state->deltacorr.t, _state), _state); - mxdeltaprimal = ae_maxreal(mxdeltaprimal, alphap*rmaxabsv(m, &state->deltacorr.w, _state), _state); - mxdeltaprimal = ae_maxreal(mxdeltaprimal, alphap*rmaxabsv(m, &state->deltacorr.p, _state), _state); - - /* - * If changes in primal variables are small enough, try dropping too large bounds - */ - if( ae_fp_less(mxdeltaprimal,mxprimal*vipmsolver_bigconstrxtol) ) - { - - /* - * Drop irrelevant box constraints - */ - primalxscale = 1.0; - primalxscale = ae_maxreal(primalxscale, rmaxabsv(n, &state->current.x, _state), _state); - for(i=0; i<=n-1; i++) - { - if( (state->hasbndl.ptr.p_bool[i]&&state->hasgz.ptr.p_bool[i])&&ae_fp_greater(ae_fabs(state->bndl.ptr.p_double[i], _state),vipmsolver_bigconstrmag*primalxscale) ) - { - state->hasgz.ptr.p_bool[i] = ae_false; - state->current.g.ptr.p_double[i] = (double)(0); - state->current.z.ptr.p_double[i] = (double)(0); - inc(&droppedbounds, _state); - } - if( (state->hasbndu.ptr.p_bool[i]&&state->hasts.ptr.p_bool[i])&&ae_fp_greater(ae_fabs(state->bndu.ptr.p_double[i], _state),vipmsolver_bigconstrmag*primalxscale) ) - { - state->hasts.ptr.p_bool[i] = ae_false; - state->current.t.ptr.p_double[i] = (double)(0); - state->current.s.ptr.p_double[i] = (double)(0); - inc(&droppedbounds, _state); - } - } - - /* - * Drop irrelevant linear constraints. Due to specifics of the solver - * we can drop only right part part of b<=Ax<=b+r. - * - * We can't drop b<=A from b<=A<=b+r because it impossible with our choice of - * slack variables. Usually we do not need to do so because we reorder constraints - * during initialization in such a way that |b+r|>|b| and because typical - * applications do not have excessively large lower AND upper bound (user may - * specify large value for 'absent' bound, but usually he does not mark both bounds as absent). - */ - vipmsolver_multiplygeax(state, 1.0, &state->current.x, 0, 0.0, &state->tmpax, 0, _state); - primalxscale = 1.0; - primalxscale = ae_maxreal(primalxscale, rmaxabsv(n, &state->current.x, _state), _state); - primalxscale = ae_maxreal(primalxscale, rmaxabsv(m, &state->tmpax, _state), _state); - for(i=0; i<=m-1; i++) - { - if( ((state->hasr.ptr.p_bool[i]&&state->haspq.ptr.p_bool[i])&&ae_fp_greater(ae_fabs(state->b.ptr.p_double[i]+state->r.ptr.p_double[i], _state),vipmsolver_bigconstrmag*primalxscale))&&ae_fp_less(ae_fabs(state->b.ptr.p_double[i], _state),vipmsolver_bigconstrmag*primalxscale) ) - { - ae_assert(state->haswv.ptr.p_bool[i]&&state->haspq.ptr.p_bool[i], "VIPMOptimize: unexpected integrity check failure (4y64)", _state); - state->haspq.ptr.p_bool[i] = ae_false; - state->current.p.ptr.p_double[i] = (double)(0); - state->current.q.ptr.p_double[i] = (double)(0); - inc(&droppedbounds, _state); - } - } - - /* - * Trace output - */ - if( droppedbounds>0 ) - { - if( state->dotrace ) - { - ae_trace("[NOTICE] detected %0d irrelevant constraints with huge bounds, X converged to values well below them, dropping...\n", - (int)(droppedbounds)); - } - } - } - } - - /* - * Check stopping criteria - * * primal and dual stagnation are checked only when following criteria are met: - * 1) Mu is smaller than 1 (we already converged close enough) - * 2) we performed more than MinItersBeforeStagnation iterations - */ - preverrp2 = errp2; - preverrd2 = errd2; - vipmsolver_computeerrors(state, &errp2, &errd2, &errpinf, &errdinf, &errgap, _state); - mu = vipmsolver_varscomputemu(&state->current, _state); - egap = errgap; - eprimal = errpinf; - edual = errdinf; - if( ae_fp_less(rmax3(egap, eprimal, edual, _state),besterr) ) - { - - /* - * Save best point found so far - */ - vipmsolver_varsinitfrom(&state->best, &state->current, _state); - bestiteridx = iteridx; - besterr = rmax3(egap, eprimal, edual, _state); - bestegap = egap; - besteprimal = eprimal; - bestedual = edual; - } - if( bestiteridx>0&&iteridx>bestiteridx+vipmsolver_minitersbeforeeworststagnation ) - { - if( state->dotrace ) - { - ae_trace("> worst of primal/dual/gap errors stagnated for %0d its, stopping at the best point found so far\n", - (int)(vipmsolver_minitersbeforeeworststagnation)); - } - break; - } - if( ((ae_fp_less_eq(egap,state->epsgap)&&ae_fp_greater_eq(errp2,vipmsolver_stagnationdelta*preverrp2))&&ae_fp_greater_eq(errpinf,vipmsolver_primalinfeasible1))&&iteridx>=vipmsolver_minitersbeforestagnation ) - { - inc(&primalstagnationcnt, _state); - if( primalstagnationcnt>=vipmsolver_primalstagnationlen ) - { - if( state->dotrace ) - { - ae_trace("> primal error stagnated for %0d its, stopping at the best point found so far\n", - (int)(vipmsolver_primalstagnationlen)); - } - break; - } - } - else - { - primalstagnationcnt = 0; - } - if( ((ae_fp_less_eq(egap,state->epsgap)&&ae_fp_greater_eq(errd2,vipmsolver_stagnationdelta*preverrd2))&&ae_fp_greater_eq(errdinf,vipmsolver_dualinfeasible1))&&iteridx>=vipmsolver_minitersbeforestagnation ) - { - inc(&dualstagnationcnt, _state); - if( dualstagnationcnt>=vipmsolver_dualstagnationlen ) - { - if( state->dotrace ) - { - ae_trace("> dual error stagnated for %0d its, stopping at the best point found so far\n", - (int)(vipmsolver_dualstagnationlen)); - } - break; - } - } - else - { - dualstagnationcnt = 0; - } - if( ae_fp_less_eq(mu,mustop)&&iteridx>=vipmsolver_itersfortoostringentcond ) - { - if( state->dotrace ) - { - ae_trace("> stopping conditions are too stringent, stopping at the best point found so far\n"); - } - *terminationtype = 7; - break; - } - if( (ae_fp_less_eq(egap,state->epsgap)&&ae_fp_less_eq(eprimal,state->epsp))&&ae_fp_less_eq(edual,state->epsd) ) - { - if( state->dotrace ) - { - ae_trace("> stopping criteria are met\n"); - } - *terminationtype = 1; - loadbest = ae_false; - break; - } - bady = vipmsolver_bigy; - bady = ae_maxreal(bady, vipmsolver_ygrowth*y0nrm, _state); - bady = ae_maxreal(bady, vipmsolver_ygrowth*rmaxabsv(n, &state->current.x, _state), _state); - bady = ae_maxreal(bady, vipmsolver_ygrowth*rmaxabsv(n, &state->current.g, _state), _state); - bady = ae_maxreal(bady, vipmsolver_ygrowth*rmaxabsv(n, &state->current.t, _state), _state); - bady = ae_maxreal(bady, vipmsolver_ygrowth*rmaxabsv(m, &state->current.w, _state), _state); - bady = ae_maxreal(bady, vipmsolver_ygrowth*rmaxabsv(m, &state->current.p, _state), _state); - if( ae_fp_greater_eq(rmaxabsv(m, &state->current.y, _state),bady)&&iteridx>=vipmsolver_minitersbeforeinfeasible ) - { - if( state->dotrace ) - { - ae_trace("> |Y| increased beyond %0.1e, stopping at the best point found so far\n", - (double)(bady)); - } - break; - } - } - - /* - * Load best point, perform some checks - */ - if( loadbest ) - { - - /* - * Load best point - * - * NOTE: TouchReal() is used to avoid spurious compiler warnings about 'set but unused' - */ - if( state->dotrace ) - { - ae_trace("> the best point so far is one from iteration %0d\n", - (int)(bestiteridx)); - } - vipmsolver_varsinitfrom(&state->current, &state->best, _state); - touchreal(&besteprimal, _state); - touchreal(&bestedual, _state); - touchreal(&bestegap, _state); - - /* - * If no error flags were set yet, check solution quality - */ - bady = vipmsolver_bigy; - bady = ae_maxreal(bady, vipmsolver_ygrowth*y0nrm, _state); - bady = ae_maxreal(bady, vipmsolver_ygrowth*rmaxabsv(n, &state->current.x, _state), _state); - bady = ae_maxreal(bady, vipmsolver_ygrowth*rmaxabsv(n, &state->current.g, _state), _state); - bady = ae_maxreal(bady, vipmsolver_ygrowth*rmaxabsv(n, &state->current.t, _state), _state); - bady = ae_maxreal(bady, vipmsolver_ygrowth*rmaxabsv(m, &state->current.w, _state), _state); - bady = ae_maxreal(bady, vipmsolver_ygrowth*rmaxabsv(m, &state->current.p, _state), _state); - if( *terminationtype>0&&ae_fp_greater_eq(rmaxabsv(m, &state->current.y, _state),bady) ) - { - *terminationtype = -2; - if( state->dotrace ) - { - ae_trace("> |Y| increased beyond %0.1e, declaring infeasibility/unboundedness\n", - (double)(bady)); - } - } - if( *terminationtype>0&&ae_fp_greater_eq(besteprimal,vipmsolver_primalinfeasible1) ) - { - *terminationtype = -2; - if( state->dotrace ) - { - ae_trace("> primal error at the best point is too high, declaring infeasibility/unboundedness\n"); - } - } - if( *terminationtype>0&&ae_fp_greater_eq(bestedual,vipmsolver_dualinfeasible1) ) - { - *terminationtype = -2; - if( state->dotrace ) - { - ae_trace("> dual error at the best point is too high, declaring infeasibility/unboundedness\n"); - } - } - } - - /* - * Output - */ - vipmsolver_multiplyhx(state, &state->current.x, &state->tmp0, _state); - raddv(n, 1.0, &state->c, &state->tmp0, _state); - vipmsolver_multiplygeatx(state, -1.0, &state->current.y, 0, 1.0, &state->tmp0, 0, _state); - for(i=0; i<=n-1; i++) - { - if( state->isfrozen.ptr.p_bool[i] ) - { - - /* - * I-th variable is frozen, use its frozen value. - * By the definition, I-th Lagrangian multiplier is an I-th component of Lagrangian gradient - */ - xs->ptr.p_double[i] = state->current.x.ptr.p_double[i]; - lagbc->ptr.p_double[i] = -state->tmp0.ptr.p_double[i]; - } - else - { - xs->ptr.p_double[i] = state->current.x.ptr.p_double[i]; - lagbc->ptr.p_double[i] = 0.0; - if( state->hasgz.ptr.p_bool[i] ) - { - lagbc->ptr.p_double[i] = lagbc->ptr.p_double[i]-state->current.z.ptr.p_double[i]; - } - if( state->hasts.ptr.p_bool[i] ) - { - lagbc->ptr.p_double[i] = lagbc->ptr.p_double[i]+state->current.s.ptr.p_double[i]; - } - } - } - for(i=0; i<=m-1; i++) - { - laglc->ptr.p_double[i] = -state->current.y.ptr.p_double[i]; - } - - /* - * Unscale point and Lagrange multipliers - */ - unscaleunshiftpointbc(&state->scl, &state->xorigin, &state->rawbndl, &state->rawbndu, &state->bndl, &state->bndu, &state->hasbndl, &state->hasbndu, xs, n, _state); - for(i=0; i<=n-1; i++) - { - lagbc->ptr.p_double[i] = lagbc->ptr.p_double[i]*state->targetscale/state->scl.ptr.p_double[i]; - } - for(i=0; i<=m-1; i++) - { - laglc->ptr.p_double[i] = laglc->ptr.p_double[i]*state->targetscale/coalesce(state->ascales.ptr.p_double[i], 1.0, _state); - } -} - - -/************************************************************************* -Allocates place for variables of IPM and fills by zeros. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static void vipmsolver_varsinitbyzero(vipmvars* vstate, - ae_int_t n, - ae_int_t m, - ae_state *_state) -{ - - - ae_assert(n>=1, "VarsInitByZero: N<1", _state); - ae_assert(m>=0, "VarsInitByZero: M<0", _state); - vstate->n = n; - vstate->m = m; - rsetallocv(n, 0.0, &vstate->x, _state); - rsetallocv(n, 0.0, &vstate->g, _state); - rsetallocv(n, 0.0, &vstate->t, _state); - rsetallocv(n, 0.0, &vstate->z, _state); - rsetallocv(n, 0.0, &vstate->s, _state); - rsetallocv(m, 0.0, &vstate->y, _state); - rsetallocv(m, 0.0, &vstate->w, _state); - rsetallocv(m, 0.0, &vstate->p, _state); - rsetallocv(m, 0.0, &vstate->v, _state); - rsetallocv(m, 0.0, &vstate->q, _state); -} - - -/************************************************************************* -Allocates place for variables of IPM and fills them by values of -the source - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static void vipmsolver_varsinitfrom(vipmvars* vstate, - vipmvars* vsrc, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - ae_int_t m; - - - n = vsrc->n; - m = vsrc->m; - ae_assert(n>=1, "VarsInitFrom: N<1", _state); - ae_assert(m>=0, "VarsInitFrom: M<0", _state); - vstate->n = n; - vstate->m = m; - rvectorsetlengthatleast(&vstate->x, n, _state); - rvectorsetlengthatleast(&vstate->g, n, _state); - rvectorsetlengthatleast(&vstate->t, n, _state); - rvectorsetlengthatleast(&vstate->w, m, _state); - rvectorsetlengthatleast(&vstate->p, m, _state); - rvectorsetlengthatleast(&vstate->z, n, _state); - rvectorsetlengthatleast(&vstate->s, n, _state); - rvectorsetlengthatleast(&vstate->y, m, _state); - rvectorsetlengthatleast(&vstate->v, m, _state); - rvectorsetlengthatleast(&vstate->q, m, _state); - for(i=0; i<=n-1; i++) - { - vstate->x.ptr.p_double[i] = vsrc->x.ptr.p_double[i]; - vstate->g.ptr.p_double[i] = vsrc->g.ptr.p_double[i]; - vstate->t.ptr.p_double[i] = vsrc->t.ptr.p_double[i]; - vstate->z.ptr.p_double[i] = vsrc->z.ptr.p_double[i]; - vstate->s.ptr.p_double[i] = vsrc->s.ptr.p_double[i]; - } - for(i=0; i<=m-1; i++) - { - vstate->w.ptr.p_double[i] = vsrc->w.ptr.p_double[i]; - vstate->p.ptr.p_double[i] = vsrc->p.ptr.p_double[i]; - vstate->y.ptr.p_double[i] = vsrc->y.ptr.p_double[i]; - vstate->v.ptr.p_double[i] = vsrc->v.ptr.p_double[i]; - vstate->q.ptr.p_double[i] = vsrc->q.ptr.p_double[i]; - } -} - - -/************************************************************************* -Adds to variables direction vector times step length. Different -lengths are used for primal and dual steps. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static void vipmsolver_varsaddstep(vipmvars* vstate, - vipmvars* vdir, - double stpp, - double stpd, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - ae_int_t m; - - - n = vstate->n; - m = vstate->m; - ae_assert(n>=1, "VarsAddStep: N<1", _state); - ae_assert(m>=0, "VarsAddStep: M<0", _state); - ae_assert(n==vdir->n, "VarsAddStep: sizes mismatch", _state); - ae_assert(m==vdir->m, "VarsAddStep: sizes mismatch", _state); - for(i=0; i<=n-1; i++) - { - vstate->x.ptr.p_double[i] = vstate->x.ptr.p_double[i]+stpp*vdir->x.ptr.p_double[i]; - vstate->g.ptr.p_double[i] = vstate->g.ptr.p_double[i]+stpp*vdir->g.ptr.p_double[i]; - vstate->t.ptr.p_double[i] = vstate->t.ptr.p_double[i]+stpp*vdir->t.ptr.p_double[i]; - vstate->z.ptr.p_double[i] = vstate->z.ptr.p_double[i]+stpd*vdir->z.ptr.p_double[i]; - vstate->s.ptr.p_double[i] = vstate->s.ptr.p_double[i]+stpd*vdir->s.ptr.p_double[i]; - } - for(i=0; i<=m-1; i++) - { - vstate->w.ptr.p_double[i] = vstate->w.ptr.p_double[i]+stpp*vdir->w.ptr.p_double[i]; - vstate->p.ptr.p_double[i] = vstate->p.ptr.p_double[i]+stpp*vdir->p.ptr.p_double[i]; - vstate->y.ptr.p_double[i] = vstate->y.ptr.p_double[i]+stpd*vdir->y.ptr.p_double[i]; - vstate->v.ptr.p_double[i] = vstate->v.ptr.p_double[i]+stpd*vdir->v.ptr.p_double[i]; - vstate->q.ptr.p_double[i] = vstate->q.ptr.p_double[i]+stpd*vdir->q.ptr.p_double[i]; - } -} - - -/************************************************************************* -Computes complementarity gap - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static double vipmsolver_varscomputecomplementaritygap(vipmvars* vstate, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - ae_int_t m; - double result; - - - n = vstate->n; - m = vstate->m; - result = (double)(0); - for(i=0; i<=n-1; i++) - { - result = result+vstate->z.ptr.p_double[i]*vstate->g.ptr.p_double[i]+vstate->s.ptr.p_double[i]*vstate->t.ptr.p_double[i]; - } - for(i=0; i<=m-1; i++) - { - result = result+vstate->v.ptr.p_double[i]*vstate->w.ptr.p_double[i]+vstate->p.ptr.p_double[i]*vstate->q.ptr.p_double[i]; - } - return result; -} - - -/************************************************************************* -Computes empirical value of the barrier parameter Mu - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static double vipmsolver_varscomputemu(vipmvars* vstate, ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - double result; - - - k = 0; - result = (double)(0); - for(i=0; i<=vstate->n-1; i++) - { - result = result+vstate->z.ptr.p_double[i]*vstate->g.ptr.p_double[i]+vstate->s.ptr.p_double[i]*vstate->t.ptr.p_double[i]; - if( !(vstate->z.ptr.p_double[i]*vstate->g.ptr.p_double[i]==0.0) ) - { - k = k+1; - } - if( !(vstate->s.ptr.p_double[i]*vstate->t.ptr.p_double[i]==0.0) ) - { - k = k+1; - } - } - for(i=0; i<=vstate->m-1; i++) - { - result = result+vstate->v.ptr.p_double[i]*vstate->w.ptr.p_double[i]+vstate->p.ptr.p_double[i]*vstate->q.ptr.p_double[i]; - if( !(vstate->v.ptr.p_double[i]*vstate->w.ptr.p_double[i]==0.0) ) - { - k = k+1; - } - if( !(vstate->p.ptr.p_double[i]*vstate->q.ptr.p_double[i]==0.0) ) - { - k = k+1; - } - } - result = result/coalesce((double)(k), (double)(1), _state); - return result; -} - - -/************************************************************************* -Initializes QP-IPM state and prepares it to receive quadratic/linear terms -and constraints. - -The solver is configured to work internally with factorization FType - -INPUT PARAMETERS: - State - solver state to be configured; previously allocated - memory is reused as much as possible - S - scale vector, array[N]: - * I-th element contains scale of I-th variable, - * S[I]>0 - XOrigin - origin term, array[N]. Can be zero. The solver solves - problem of the form - - > - > min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin)) - > - - The terms A and b (as well as constraints) will be - specified later with separate calls. - FType - factorization type: - * 0 for dense NxN factorization (normal equations) - * 1 for sparse (N+M)x(N+M) factorization - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static void vipmsolver_vipminit(vipmstate* state, - /* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - ae_int_t n, - ae_int_t nmain, - ae_int_t ftype, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t nslack; - - - ae_assert(n>=1, "VIPMInit: N<1", _state); - ae_assert(isfinitevector(s, n, _state), "VIPMInit: S contains infinite or NaN elements", _state); - ae_assert(isfinitevector(xorigin, n, _state), "VIPMInit: XOrigin contains infinite or NaN elements", _state); - ae_assert(ftype==0||ftype==1, "VIPMInit: unexpected FType", _state); - ae_assert(nmain>=1, "VIPMInit: NMain<1", _state); - ae_assert(nmain<=n, "VIPMInit: NMain>N", _state); - nslack = n-nmain; - - /* - * Problem metrics, settings and type - */ - state->n = n; - state->nmain = nmain; - state->islinear = ae_true; - state->factorizationtype = ftype; - state->factorizationpresent = ae_false; - state->factorizationpoweredup = ae_false; - vipmsetcond(state, 0.0, 0.0, 0.0, _state); - state->slacksforequalityconstraints = ae_true; - - /* - * Reports - */ - state->repiterationscount = 0; - state->repncholesky = 0; - - /* - * Trace - */ - state->dotrace = ae_false; - state->dodetailedtrace = ae_false; - - /* - * Scale and origin - */ - rvectorsetlengthatleast(&state->scl, n, _state); - rvectorsetlengthatleast(&state->invscl, n, _state); - rvectorsetlengthatleast(&state->xorigin, n, _state); - for(i=0; i<=n-1; i++) - { - ae_assert(s->ptr.p_double[i]>0.0, "VIPMInit: S[i] is non-positive", _state); - state->scl.ptr.p_double[i] = s->ptr.p_double[i]; - state->invscl.ptr.p_double[i] = 1/s->ptr.p_double[i]; - state->xorigin.ptr.p_double[i] = xorigin->ptr.p_double[i]; - } - state->targetscale = 1.0; - - /* - * Linear and quadratic terms - default value - */ - rvectorsetlengthatleast(&state->c, n, _state); - for(i=0; i<=n-1; i++) - { - state->c.ptr.p_double[i] = (double)(0); - } - state->hkind = -1; - if( ftype==0 ) - { - - /* - * Dense quadratic term - */ - rmatrixsetlengthatleast(&state->denseh, nmain, nmain, _state); - for(i=0; i<=nmain-1; i++) - { - for(j=0; j<=i; j++) - { - state->denseh.ptr.pp_double[i][j] = (double)(0); - } - } - state->hkind = 0; - } - if( ftype==1 ) - { - - /* - * Sparse quadratic term - */ - state->sparseh.matrixtype = 1; - state->sparseh.m = n; - state->sparseh.n = n; - state->sparseh.ninitialized = n; - ivectorsetlengthatleast(&state->sparseh.idx, n, _state); - rvectorsetlengthatleast(&state->sparseh.vals, n, _state); - ivectorsetlengthatleast(&state->sparseh.ridx, n+1, _state); - for(i=0; i<=n-1; i++) - { - state->sparseh.idx.ptr.p_int[i] = i; - state->sparseh.vals.ptr.p_double[i] = 0.0; - state->sparseh.ridx.ptr.p_int[i] = i; - } - state->sparseh.ridx.ptr.p_int[n] = n; - sparsecreatecrsinplace(&state->sparseh, _state); - state->hkind = 1; - } - ae_assert(state->hkind>=0, "VIPMInit: integrity check failed", _state); - - /* - * Box constraints - default values - */ - rvectorsetlengthatleast(&state->bndl, n, _state); - rvectorsetlengthatleast(&state->bndu, n, _state); - bvectorsetlengthatleast(&state->hasbndl, n, _state); - bvectorsetlengthatleast(&state->hasbndu, n, _state); - for(i=0; i<=n-1; i++) - { - state->hasbndl.ptr.p_bool[i] = ae_false; - state->hasbndu.ptr.p_bool[i] = ae_false; - state->bndl.ptr.p_double[i] = _state->v_neginf; - state->bndu.ptr.p_double[i] = _state->v_posinf; - } - - /* - * Linear constraints - empty - */ - state->mdense = 0; - state->msparse = 0; - state->combinedaslack.m = 0; - state->combinedaslack.n = nslack; - state->sparseamain.m = 0; - state->sparseamain.n = nmain; - sparsecreatecrsinplace(&state->sparseamain, _state); - sparsecreatecrsinplace(&state->combinedaslack, _state); -} - - -/************************************************************************* -Computes target function 0.5*x'*H*x+c'*x - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static double vipmsolver_vipmtarget(vipmstate* state, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nmain; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t j0; - ae_int_t j1; - double v; - double result; - - - n = state->n; - nmain = state->nmain; - ae_assert(state->hkind==0||state->hkind==1, "VIPMTarget: unexpected HKind", _state); - result = (double)(0); - - /* - * Dense - */ - if( state->hkind==0 ) - { - for(i=0; i<=nmain-1; i++) - { - for(j=0; j<=i-1; j++) - { - result = result+x->ptr.p_double[i]*state->denseh.ptr.pp_double[i][j]*x->ptr.p_double[j]; - } - result = result+0.5*x->ptr.p_double[i]*x->ptr.p_double[i]*state->denseh.ptr.pp_double[i][i]; - } - for(i=0; i<=n-1; i++) - { - result = result+state->c.ptr.p_double[i]*x->ptr.p_double[i]; - } - return result; - } - - /* - * Sparse - */ - if( state->hkind==1 ) - { - for(i=0; i<=n-1; i++) - { - result = result+state->c.ptr.p_double[i]*x->ptr.p_double[i]; - j0 = state->sparseh.ridx.ptr.p_int[i]; - j1 = state->sparseh.didx.ptr.p_int[i]-1; - for(k=j0; k<=j1; k++) - { - v = state->sparseh.vals.ptr.p_double[k]; - j = state->sparseh.idx.ptr.p_int[k]; - result = result+v*x->ptr.p_double[i]*x->ptr.p_double[j]; - } - ae_assert(state->sparseh.uidx.ptr.p_int[i]!=state->sparseh.didx.ptr.p_int[i], "VIPMTarget: sparse diagonal not found", _state); - v = state->sparseh.vals.ptr.p_double[state->sparseh.didx.ptr.p_int[i]]; - result = result+0.5*v*x->ptr.p_double[i]*x->ptr.p_double[i]; - } - return result; - } - return result; -} - - -/************************************************************************* -Computes - - Y := alpha*A*x + beta*Y - -where A is constraint matrix, X is user-specified source, Y is target. - -Beta can be zero (in this case original contents of Y is ignored). -If Beta is nonzero, we expect that Y contains preallocated array. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static void vipmsolver_multiplygeax(vipmstate* state, - double alpha, - /* Real */ ae_vector* x, - ae_int_t offsx, - double beta, - /* Real */ ae_vector* y, - ae_int_t offsax, - ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - ae_int_t mdense; - ae_int_t msparse; - - - n = state->n; - m = state->mdense+state->msparse; - mdense = state->mdense; - msparse = state->msparse; - if( ae_fp_eq(beta,(double)(0)) ) - { - rallocv(offsax+m, y, _state); - } - else - { - ae_assert(y->cnt>=offsax+m, "MultiplyGEAX: Y is too short", _state); - } - if( msparse>0 ) - { - sparsegemv(&state->sparseafull, alpha, 0, x, offsx, beta, y, offsax, _state); - } - if( mdense>0 ) - { - rmatrixgemv(mdense, n, alpha, &state->denseafull, 0, 0, 0, x, offsx, beta, y, offsax+msparse, _state); - } -} - - -/************************************************************************* -Computes - - Y := alpha*A'*x + beta*Y - -where A is constraint matrix, X is user-specified source, Y is target. - -Beta can be zero, in this case we automatically reallocate target if it is -too short (but do NOT reallocate it if its size is large enough). -If Beta is nonzero, we expect that Y contains preallocated array. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static void vipmsolver_multiplygeatx(vipmstate* state, - double alpha, - /* Real */ ae_vector* x, - ae_int_t offsx, - double beta, - /* Real */ ae_vector* y, - ae_int_t offsy, - ae_state *_state) -{ - ae_int_t n; - ae_int_t mdense; - ae_int_t msparse; - - - n = state->n; - mdense = state->mdense; - msparse = state->msparse; - if( ae_fp_eq(beta,(double)(0)) ) - { - rallocv(offsy+n, y, _state); - rsetvx(n, 0.0, y, offsy, _state); - } - else - { - ae_assert(y->cnt>=offsy+n, "MultiplyGEATX: Y is too short", _state); - rmulvx(n, beta, y, offsy, _state); - } - if( msparse>0 ) - { - sparsegemv(&state->sparseafull, alpha, 1, x, offsx, 1.0, y, offsy, _state); - } - if( mdense>0 ) - { - rmatrixgemv(n, mdense, alpha, &state->denseafull, 0, 0, 1, x, offsx+msparse, 1.0, y, offsy, _state); - } -} - - -/************************************************************************* -Computes H*x, does not support advanced functionality of GEAX/GEATX - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static void vipmsolver_multiplyhx(vipmstate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* hx, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nmain; - ae_int_t i; - - - n = state->n; - nmain = state->nmain; - rvectorsetlengthatleast(hx, n, _state); - ae_assert(state->hkind==0||state->hkind==1, "VIPMMultiplyHX: unexpected HKind", _state); - if( state->hkind==0 ) - { - rmatrixsymv(nmain, 1.0, &state->denseh, 0, 0, ae_false, x, 0, 0.0, hx, 0, _state); - for(i=nmain; i<=n-1; i++) - { - hx->ptr.p_double[i] = (double)(0); - } - } - if( state->hkind==1 ) - { - ae_assert(state->sparseh.n==n&&state->sparseh.m==n, "VIPMMultiplyHX: sparse H has incorrect size", _state); - sparsesmv(&state->sparseh, ae_false, x, hx, _state); - } - for(i=0; i<=n-1; i++) - { - hx->ptr.p_double[i] = hx->ptr.p_double[i]+x->ptr.p_double[i]*state->diagr.ptr.p_double[i]; - } -} - - -/************************************************************************* -Computes products H*x, A*x, A^T*y - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static void vipmsolver_vipmmultiply(vipmstate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* hx, - /* Real */ ae_vector* ax, - /* Real */ ae_vector* aty, - ae_state *_state) -{ - - - vipmsolver_multiplygeax(state, 1.0, x, 0, 0.0, ax, 0, _state); - vipmsolver_multiplygeatx(state, 1.0, y, 0, 0.0, aty, 0, _state); - vipmsolver_multiplyhx(state, x, hx, _state); -} - - -/************************************************************************* -This function "powers up" factorization, i.e. prepares some important -temporaries. It should be called once prior to the first call to -VIPMInitialPoint() or VIPMFactorize(). - -Parameters: - RegFree - regularization for free variables; - good value sqrt(MachineEpsilon) - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static void vipmsolver_vipmpowerup(vipmstate* state, - double regfree, - ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - ae_int_t nnzmax; - ae_int_t offs; - ae_int_t rowoffs; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t k0; - ae_int_t k1; - double v; - double vrhs; - ae_int_t factldlt; - ae_int_t permauto; - double maxinitialnoncentrality; - double maxinitialimbalance; - double priorcoeff; - double initprimslack; - double initdualslack; - double mu0; - double mumin; - ae_bool success; - - - ae_assert(state->factorizationtype==0||state->factorizationtype==1, "VIPMPowerUp: unexpected factorization type", _state); - n = state->n; - m = state->mdense+state->msparse; - ae_assert(!state->factorizationpoweredup, "VIPMPowerUp: repeated call", _state); - maxinitialnoncentrality = 1.0E-6; - maxinitialimbalance = 1.0E-6; - - /* - * Set up information about presence of slack variables. - * Decide which components of X should be frozen. - * Compute diagonal regularization matrix R. - */ - bcopyallocv(n, &state->hasbndl, &state->hasgz, _state); - bcopyallocv(n, &state->hasbndu, &state->hasts, _state); - bsetallocv(n, ae_false, &state->isfrozen, _state); - rsetallocv(n, 0.0, &state->diagr, _state); - vipmsolver_varsinitbyzero(&state->current, n, m, _state); - for(i=0; i<=n-1; i++) - { - if( (state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_eq(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->isfrozen.ptr.p_bool[i] = ae_true; - state->hasgz.ptr.p_bool[i] = ae_false; - state->hasts.ptr.p_bool[i] = ae_false; - state->current.x.ptr.p_double[i] = state->bndl.ptr.p_double[i]; - } - if( !state->hasbndl.ptr.p_bool[i]&&!state->hasbndu.ptr.p_bool[i] ) - { - state->diagr.ptr.p_double[i] = regfree; - } - } - ballocv(m, &state->haspq, _state); - ballocv(m, &state->haswv, _state); - for(i=0; i<=m-1; i++) - { - state->haswv.ptr.p_bool[i] = (state->slacksforequalityconstraints||!state->hasr.ptr.p_bool[i])||ae_fp_greater(state->r.ptr.p_double[i],(double)(0)); - state->haspq.ptr.p_bool[i] = state->hasr.ptr.p_bool[i]&&state->haswv.ptr.p_bool[i]; - } - - /* - * Only sparse factorization needs special powering up - */ - if( state->factorizationtype==1 ) - { - ae_assert(state->hkind==1, "VIPMPowerUp: unexpected HKind", _state); - nnzmax = state->sparseh.ridx.ptr.p_int[n]; - if( state->msparse>0 ) - { - nnzmax = nnzmax+state->sparseafull.ridx.ptr.p_int[state->msparse]; - } - if( state->mdense>0 ) - { - nnzmax = nnzmax+n*state->mdense; - } - nnzmax = nnzmax+(n+m); - - /* - * Prepare strictly lower triangle of template KKT matrix (KKT system without D and E - * terms being added to diagonals) - */ - state->factsparsekkttmpl.m = n+m; - state->factsparsekkttmpl.n = n+m; - ivectorsetlengthatleast(&state->factsparsekkttmpl.idx, nnzmax, _state); - rvectorsetlengthatleast(&state->factsparsekkttmpl.vals, nnzmax, _state); - ivectorsetlengthatleast(&state->factsparsekkttmpl.ridx, n+m+1, _state); - state->factsparsekkttmpl.ridx.ptr.p_int[0] = 0; - offs = 0; - rowoffs = 0; - for(i=0; i<=n-1; i++) - { - ae_assert(state->sparseh.didx.ptr.p_int[i]+1==state->sparseh.uidx.ptr.p_int[i], "VIPMPowerUp: critical integrity check failed for diagonal of H", _state); - if( !state->isfrozen.ptr.p_bool[i] ) - { - - /* - * Entire row is not frozen, but some of its entries can be. - * Output non-frozen offdiagonal entries. - */ - k0 = state->sparseh.ridx.ptr.p_int[i]; - k1 = state->sparseh.didx.ptr.p_int[i]-1; - for(k=k0; k<=k1; k++) - { - j = state->sparseh.idx.ptr.p_int[k]; - if( !state->isfrozen.ptr.p_bool[j] ) - { - state->factsparsekkttmpl.idx.ptr.p_int[offs] = j; - state->factsparsekkttmpl.vals.ptr.p_double[offs] = -state->sparseh.vals.ptr.p_double[k]; - offs = offs+1; - } - } - - /* - * Output diagonal entry (it is always not frozen) - */ - state->factsparsekkttmpl.idx.ptr.p_int[offs] = i; - state->factsparsekkttmpl.vals.ptr.p_double[offs] = -state->sparseh.vals.ptr.p_double[state->sparseh.didx.ptr.p_int[i]]; - offs = offs+1; - } - else - { - - /* - * Entire row is frozen, output just -1 - */ - state->factsparsekkttmpl.idx.ptr.p_int[offs] = i; - state->factsparsekkttmpl.vals.ptr.p_double[offs] = -1.0; - offs = offs+1; - } - rowoffs = rowoffs+1; - state->factsparsekkttmpl.ridx.ptr.p_int[rowoffs] = offs; - } - for(i=0; i<=state->msparse-1; i++) - { - k0 = state->sparseafull.ridx.ptr.p_int[i]; - k1 = state->sparseafull.ridx.ptr.p_int[i+1]-1; - for(k=k0; k<=k1; k++) - { - j = state->sparseafull.idx.ptr.p_int[k]; - if( !state->isfrozen.ptr.p_bool[j] ) - { - state->factsparsekkttmpl.idx.ptr.p_int[offs] = j; - state->factsparsekkttmpl.vals.ptr.p_double[offs] = state->sparseafull.vals.ptr.p_double[k]; - offs = offs+1; - } - } - state->factsparsekkttmpl.idx.ptr.p_int[offs] = rowoffs; - state->factsparsekkttmpl.vals.ptr.p_double[offs] = 0.0; - offs = offs+1; - rowoffs = rowoffs+1; - state->factsparsekkttmpl.ridx.ptr.p_int[rowoffs] = offs; - } - for(i=0; i<=state->mdense-1; i++) - { - for(k=0; k<=n-1; k++) - { - if( state->denseafull.ptr.pp_double[i][k]!=0.0&&!state->isfrozen.ptr.p_bool[k] ) - { - state->factsparsekkttmpl.idx.ptr.p_int[offs] = k; - state->factsparsekkttmpl.vals.ptr.p_double[offs] = state->denseafull.ptr.pp_double[i][k]; - offs = offs+1; - } - } - state->factsparsekkttmpl.idx.ptr.p_int[offs] = rowoffs; - state->factsparsekkttmpl.vals.ptr.p_double[offs] = 0.0; - offs = offs+1; - rowoffs = rowoffs+1; - state->factsparsekkttmpl.ridx.ptr.p_int[rowoffs] = offs; - } - ae_assert(rowoffs==m+n, "VIPMPowerUp: critical integrity check failed", _state); - ae_assert(offs<=nnzmax, "VIPMPowerUp: critical integrity check failed", _state); - sparsecreatecrsinplace(&state->factsparsekkttmpl, _state); - factldlt = 1; - permauto = 0; - if( !spsymmanalyze(&state->factsparsekkttmpl, factldlt, permauto, &state->ldltanalysis, _state) ) - { - ae_assert(ae_false, "VIPMPowerUp: critical integrity check failed, symbolically degenerate KKT system encountered", _state); - } - } - state->factorizationpoweredup = ae_true; - - /* - * Set up initial values of primal and dual variables X and Y by solving - * modified KKT system which tries to enforce linear constraints (ignoring - * box constraints for a while) subject to minimization of additional prior - * term which moves solution towards some interior point. - * - * Here we expect that State.Current.X contains zeros in non-fixed variables - * and their fixed values for fixed ones. - */ - priorcoeff = 1.0; - success = vipmsolver_vipmfactorize(state, 0.0, &state->diagddr, 0.0, &state->diagder, priorcoeff, priorcoeff, ae_machineepsilon, ae_machineepsilon, _state); - ae_assert(success, "VIPMInitialPoint: impossible failure of LDLT factorization", _state); - vipmsolver_multiplyhx(state, &state->current.x, &state->tmp0, _state); - vipmsolver_multiplygeax(state, 1.0, &state->current.x, 0, 0.0, &state->tmp1, 0, _state); - rallocv(n+m, &state->deltaxy, _state); - for(i=0; i<=n-1; i++) - { - state->deltaxy.ptr.p_double[i] = state->c.ptr.p_double[i]+state->tmp0.ptr.p_double[i]; - } - for(i=0; i<=m-1; i++) - { - - /* - * We need to specify target right-hand sides for constraints. - * - * Ether zero, b or b+r is used (depending on presence of r and - * magnitudes of b and b+r, and subject to current state of frozen - * variables). - */ - vrhs = state->b.ptr.p_double[i]-state->tmp1.ptr.p_double[i]; - if( state->hasr.ptr.p_bool[i] ) - { - - /* - * Range constraint b<=Ax<=b+r - */ - if( ae_fp_greater_eq(vrhs,(double)(0)) ) - { - - /* - * 0<=b<=b+r, select target at lower bound - */ - v = vrhs; - } - else - { - - /* - * b<=0, b+r can have any sign. - * Select zero target if possible, if not - one with smallest absolute value. - */ - v = ae_minreal(vrhs+state->r.ptr.p_double[i], 0.0, _state); - } - } - else - { - - /* - * Single-sided constraint Ax>=b. - * Select zero target if possible, if not - one with smallest absolute value. - */ - v = ae_maxreal(vrhs, 0.0, _state); - } - state->deltaxy.ptr.p_double[n+i] = v; - } - vipmsolver_solvereducedkktsystem(state, &state->deltaxy, _state); - for(i=0; i<=n-1; i++) - { - if( !state->isfrozen.ptr.p_bool[i] ) - { - state->current.x.ptr.p_double[i] = state->deltaxy.ptr.p_double[i]; - } - } - for(i=0; i<=m-1; i++) - { - state->current.y.ptr.p_double[i] = state->deltaxy.ptr.p_double[n+i]; - } - - /* - * Set up slacks according to our own heuristic - */ - initprimslack = ae_maxreal(vipmsolver_initslackval, rmaxabsv(n, &state->current.x, _state), _state); - initdualslack = ae_maxreal(vipmsolver_initslackval, rmaxabsv(m, &state->current.y, _state), _state); - vipmsolver_multiplygeax(state, 1.0, &state->current.x, 0, 0.0, &state->tmpax, 0, _state); - mu0 = 1.0; - for(i=0; i<=n-1; i++) - { - if( state->hasgz.ptr.p_bool[i] ) - { - state->current.g.ptr.p_double[i] = ae_maxreal(ae_fabs(state->current.x.ptr.p_double[i]-state->bndl.ptr.p_double[i], _state), initprimslack, _state); - state->current.z.ptr.p_double[i] = ae_maxreal(state->current.g.ptr.p_double[i]*maxinitialimbalance, initdualslack, _state); - mu0 = ae_maxreal(mu0, state->current.g.ptr.p_double[i]*state->current.z.ptr.p_double[i], _state); - } - if( state->hasts.ptr.p_bool[i] ) - { - state->current.t.ptr.p_double[i] = ae_maxreal(ae_fabs(state->current.x.ptr.p_double[i]-state->bndu.ptr.p_double[i], _state), initprimslack, _state); - state->current.s.ptr.p_double[i] = ae_maxreal(state->current.t.ptr.p_double[i]*maxinitialimbalance, initdualslack, _state); - mu0 = ae_maxreal(mu0, state->current.t.ptr.p_double[i]*state->current.s.ptr.p_double[i], _state); - } - } - for(i=0; i<=m-1; i++) - { - if( state->haswv.ptr.p_bool[i] ) - { - state->current.w.ptr.p_double[i] = ae_maxreal(ae_fabs(state->tmpax.ptr.p_double[i]-state->b.ptr.p_double[i], _state), initprimslack, _state); - state->current.v.ptr.p_double[i] = rmax3(state->current.w.ptr.p_double[i]*maxinitialimbalance, ae_fabs(state->current.y.ptr.p_double[i], _state), vipmsolver_initslackval, _state); - mu0 = ae_maxreal(mu0, state->current.w.ptr.p_double[i]*state->current.v.ptr.p_double[i], _state); - } - if( state->haspq.ptr.p_bool[i] ) - { - state->current.p.ptr.p_double[i] = ae_maxreal(ae_fabs(state->r.ptr.p_double[i]-state->current.w.ptr.p_double[i], _state), initprimslack, _state); - state->current.q.ptr.p_double[i] = rmax3(state->current.p.ptr.p_double[i]*maxinitialimbalance, ae_fabs(state->current.y.ptr.p_double[i], _state), vipmsolver_initslackval, _state); - mu0 = ae_maxreal(mu0, state->current.p.ptr.p_double[i]*state->current.q.ptr.p_double[i], _state); - } - } - - /* - * Additional shift to ensure that initial point is not too non-centered - */ - mumin = mu0*maxinitialnoncentrality; - for(i=0; i<=n-1; i++) - { - if( state->hasgz.ptr.p_bool[i]&&ae_fp_less(state->current.g.ptr.p_double[i]*state->current.z.ptr.p_double[i],mumin) ) - { - v = ae_sqrt(mumin/(state->current.g.ptr.p_double[i]*state->current.z.ptr.p_double[i]), _state); - state->current.g.ptr.p_double[i] = state->current.g.ptr.p_double[i]*v; - state->current.z.ptr.p_double[i] = state->current.z.ptr.p_double[i]*v; - } - if( state->hasts.ptr.p_bool[i]&&ae_fp_less(state->current.t.ptr.p_double[i]*state->current.s.ptr.p_double[i],mumin) ) - { - v = ae_sqrt(mumin/(state->current.t.ptr.p_double[i]*state->current.s.ptr.p_double[i]), _state); - state->current.t.ptr.p_double[i] = state->current.t.ptr.p_double[i]*v; - state->current.s.ptr.p_double[i] = state->current.s.ptr.p_double[i]*v; - } - } - for(i=0; i<=m-1; i++) - { - if( state->haswv.ptr.p_bool[i]&&ae_fp_less(state->current.w.ptr.p_double[i]*state->current.v.ptr.p_double[i],mumin) ) - { - v = ae_sqrt(mumin/(state->current.w.ptr.p_double[i]*state->current.v.ptr.p_double[i]), _state); - state->current.w.ptr.p_double[i] = state->current.w.ptr.p_double[i]*v; - state->current.v.ptr.p_double[i] = state->current.v.ptr.p_double[i]*v; - } - if( state->haspq.ptr.p_bool[i]&&ae_fp_less(state->current.p.ptr.p_double[i]*state->current.q.ptr.p_double[i],mumin) ) - { - v = ae_sqrt(mumin/(state->current.p.ptr.p_double[i]*state->current.q.ptr.p_double[i]), _state); - state->current.p.ptr.p_double[i] = state->current.p.ptr.p_double[i]*v; - state->current.q.ptr.p_double[i] = state->current.q.ptr.p_double[i]*v; - } - } - - /* - * Almost done - */ - if( state->dotrace ) - { - ae_trace("> initial point was generated\n"); - } -} - - -/************************************************************************* -This function performs factorization of modified KKT system - - ( | ) - ( -(H+alpha0*D+alpha1*I) | A^T ) - ( | ) - (------------------------|-----------------) - ( | ) - ( A | beta0*E+beta1*I ) - ( | ) - -where: -* H is an NxN quadratic term -* A is an MxN matrix of linear constraint -* alpha0, alpha1, beta0, beta1 are nonnegative scalars -* D and E are diagonal matrices with nonnegative entries (which are ignored - if alpha0 and beta0 are zero - arrays are not referenced at all) -* I is an NxN or MxM identity matrix - -Additionally, regularizing term - - ( | ) - ( -reg*I | ) - ( | ) - (--------|--------) - ( | ) - ( | +reg*I ) - ( | ) - -is added to the entire KKT system prior to factorization in order to -improve its numerical stability. - -Returns True on success, False on falure of factorization (it is recommended -to increase regularization parameter and try one more time). - - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static ae_bool vipmsolver_vipmfactorize(vipmstate* state, - double alpha0, - /* Real */ ae_vector* d, - double beta0, - /* Real */ ae_vector* e, - double alpha11, - double beta11, - double modeps, - double dampeps, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nmain; - ae_int_t nslack; - ae_int_t m; - ae_int_t mdense; - ae_int_t msparse; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t k0; - ae_int_t k1; - ae_int_t ka; - ae_int_t kb; - ae_int_t ja; - ae_int_t jb; - double va; - double vb; - double v; - double vv; - double badchol; - double sumsq; - double errsq; - ae_bool result; - - - ae_assert(ae_isfinite(alpha0, _state)&&ae_fp_greater_eq(alpha0,(double)(0)), "VIPMFactorize: Alpha0 is infinite or negative", _state); - ae_assert(ae_isfinite(alpha11, _state)&&ae_fp_greater_eq(alpha11,(double)(0)), "VIPMFactorize: Alpha1 is infinite or negative", _state); - ae_assert(ae_isfinite(beta0, _state)&&ae_fp_greater_eq(beta0,(double)(0)), "VIPMFactorize: Beta0 is infinite or negative", _state); - ae_assert(ae_isfinite(beta11, _state)&&ae_fp_greater_eq(beta11,(double)(0)), "VIPMFactorize: Beta1 is infinite or negative", _state); - ae_assert(state->factorizationtype==0||state->factorizationtype==1, "VIPMFactorize: unexpected factorization type", _state); - ae_assert(state->factorizationpoweredup, "VIPMFactorize: critical integrity check failed (no powerup stage)", _state); - n = state->n; - nmain = state->nmain; - nslack = n-nmain; - m = state->mdense+state->msparse; - mdense = state->mdense; - msparse = state->msparse; - state->factorizationpresent = ae_false; - badchol = 1.0E50; - result = ae_true; - - /* - * Dense NxN normal equations approach - */ - if( state->factorizationtype==0 ) - { - - /* - * A problem formulation with possible slacks. - * - * === A FORMULATION WITHOUT FROZEN VARIABLES === - * - * We have to solve following system: - * - * [ -(H+Dh+Rh) Ah' ] [ Xh ] [ Bh ] - * [ -(Dz+Rz) Az' ] [ Xz ] = [ Bz ] - * [ Ah Az E ] [ Y ] [ By ] - * - * with Xh being NMain-dimensional vector, Xz being NSlack-dimensional vector, constraint - * matrix A being divided into non-slack and slack parts Ah and Az (and Ah, in turn, being - * divided into sparse and dense parts), Rh and Rz being diagonal regularization matrix, - * Y being M-dimensional vector. - * - * NOTE: due to definition of slack variables following holds: for any diagonal matrix W - * a product Az*W*Az' is a diagonal matrix. - * - * From the second line we get - * - * Xz = inv(Dz+Rz)*Az'*y - inv(Dz+Rz)*Bz - * = inv(Dz+Rz)*Az'*y - BzWave - * - * Using this value for Zx, third line gives us - * - * Y = inv(E+Az*inv(Dz+Rz)*Az')*(By+Az*BzWave-Ah*Xh) - * = inv(EWave)*(ByWave-Ah*Xh) - * with EWave = E+Az*inv(Dz+Rz)*Az' and ByWave = By+Az*BzWave - * - * Finally, first line gives us - * - * Xh = -inv(H+Dh+Rh+Ah'*inv(EWave)*Ah)*(Bh-Ah'*inv(EWave)*ByWave) - * = -inv(HWave)*BhWave - * with HWave = H+Dh+Rh+Ah'*inv(EWave)*Ah and BhWave = Bh-Ah'*inv(EWave)*ByWave - * - * In order to prepare factorization we need to compute: - * (a) diagonal matrices Dh, Rh, Dz and Rz (and precomputed inverse of Dz+Rz) - * (b) EWave - * (c) HWave - * - * === SPECIAL HANDLING OF FROZEN VARIABLES === - * - * Frozen variables result in zero steps, i.e. zero components of Xh and Xz. - * It could be implemented by explicit modification of KKT system (zeroing out - * columns/rows of KKT matrix, rows of right part, putting 1's to diagonal). - * - * However, it is possible to do without actually modifying quadratic term and - * constraints: - * * freezing elements of Xz can be implemented by zeroing out corresponding - * columns of inv(Dz+Rz) because Az always appears in computations along with diagonal Dz+Rz. - * * freezing elements of Xh is a bit more complex - it needs: - * * zeroing out columns/rows of HWave and setting up unit diagonal prior to solving for Xh - * * explicitly zeroing out computed elements of Xh prior to computing Y and Xz - */ - rvectorsetlengthatleast(&state->factregdhrh, nmain, _state); - rvectorsetlengthatleast(&state->factinvregdzrz, nslack, _state); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - if( ae_fp_greater(alpha0,(double)(0)) ) - { - v = v+alpha0*d->ptr.p_double[i]; - } - if( ae_fp_greater(alpha11,(double)(0)) ) - { - v = v+alpha11; - } - v = v+state->diagr.ptr.p_double[i]; - v = v+dampeps; - ae_assert(ae_fp_greater(v,(double)(0)), "VIPMFactorize: integrity check failed, degenerate diagonal matrix", _state); - if( i>=nmain ) - { - if( !state->isfrozen.ptr.p_bool[i] ) - { - state->factinvregdzrz.ptr.p_double[i-nmain] = 1/v; - } - else - { - state->factinvregdzrz.ptr.p_double[i-nmain] = 0.0; - } - } - else - { - state->factregdhrh.ptr.p_double[i] = v; - } - } - - /* - * Now we are ready to compute EWave - */ - rvectorsetlengthatleast(&state->factregewave, m, _state); - for(i=0; i<=m-1; i++) - { - - /* - * Compute diagonal element of E - */ - v = (double)(0); - if( ae_fp_greater(beta0,(double)(0)) ) - { - v = v+beta0*e->ptr.p_double[i]; - } - if( ae_fp_greater(beta11,(double)(0)) ) - { - v = v+beta11; - } - v = v+dampeps; - ae_assert(ae_fp_greater(v,(double)(0)), "VIPMFactorize: integrity check failed, degenerate diagonal matrix", _state); - - /* - * Compute diagonal modification Az*inv(Dz)*Az' - */ - k0 = state->combinedaslack.ridx.ptr.p_int[i]; - k1 = state->combinedaslack.ridx.ptr.p_int[i+1]-1; - for(k=k0; k<=k1; k++) - { - vv = state->combinedaslack.vals.ptr.p_double[k]; - v = v+vv*vv*state->factinvregdzrz.ptr.p_double[state->combinedaslack.idx.ptr.p_int[k]]; - } - - /* - * Save EWave - */ - state->factregewave.ptr.p_double[i] = v; - } - - /* - * Now we are ready to compute HWave: - * * store H - * * add Dh - * * add Ah'*inv(EWave)*Ah - */ - rmatrixsetlengthatleast(&state->factdensehaug, nmain, nmain, _state); - ae_assert(state->hkind==0, "VIPMFactorize: unexpected HKind", _state); - rmatrixcopy(nmain, nmain, &state->denseh, 0, 0, &state->factdensehaug, 0, 0, _state); - for(i=0; i<=nmain-1; i++) - { - state->factdensehaug.ptr.pp_double[i][i] = state->factdensehaug.ptr.pp_double[i][i]+state->factregdhrh.ptr.p_double[i]; - } - if( msparse>0 ) - { - - /* - * Handle sparse part of Ah in Ah'*inv(EWave)*Ah - */ - for(i=0; i<=msparse-1; i++) - { - v = 1.0/state->factregewave.ptr.p_double[i]; - k0 = state->sparseamain.ridx.ptr.p_int[i]; - k1 = state->sparseamain.ridx.ptr.p_int[i+1]-1; - for(ka=k0; ka<=k1; ka++) - { - ja = state->sparseamain.idx.ptr.p_int[ka]; - va = state->sparseamain.vals.ptr.p_double[ka]; - for(kb=k0; kb<=ka; kb++) - { - jb = state->sparseamain.idx.ptr.p_int[kb]; - vb = state->sparseamain.vals.ptr.p_double[kb]; - state->factdensehaug.ptr.pp_double[ja][jb] = state->factdensehaug.ptr.pp_double[ja][jb]+v*va*vb; - } - } - } - } - if( mdense>0 ) - { - - /* - * Handle dense part of Ah in Ah'*inv(EWave)*Ah - */ - rmatrixsetlengthatleast(&state->tmpr2, mdense, nmain, _state); - rmatrixcopy(mdense, nmain, &state->denseamain, 0, 0, &state->tmpr2, 0, 0, _state); - for(i=0; i<=mdense-1; i++) - { - v = 1.0/ae_sqrt(state->factregewave.ptr.p_double[msparse+i], _state); - for(j=0; j<=nmain-1; j++) - { - state->tmpr2.ptr.pp_double[i][j] = v*state->tmpr2.ptr.pp_double[i][j]; - } - } - rmatrixsyrk(nmain, mdense, 1.0, &state->tmpr2, 0, 0, 2, 1.0, &state->factdensehaug, 0, 0, ae_false, _state); - } - - /* - * Zero out rows/cols of HWave corresponding to frozen variables, set up unit diagonal - */ - rsetallocv(nmain, 1.0, &state->tmp0, _state); - for(i=0; i<=nmain-1; i++) - { - if( state->isfrozen.ptr.p_bool[i] ) - { - state->tmp0.ptr.p_double[i] = 0.0; - } - } - for(i=0; i<=nmain-1; i++) - { - if( state->isfrozen.ptr.p_bool[i] ) - { - - /* - * Entire row is nullified except for diagonal element - */ - rsetr(i+1, 0.0, &state->factdensehaug, i, _state); - state->factdensehaug.ptr.pp_double[i][i] = 1.0; - } - else - { - - /* - * Only some components are nullified - */ - rmergemulvr(i+1, &state->tmp0, &state->factdensehaug, i, _state); - } - } - - /* - * Compute Cholesky factorization of HWave - */ - if( !spdmatrixcholesky(&state->factdensehaug, nmain, ae_false, _state) ) - { - result = ae_false; - return result; - } - v = (double)(0); - for(i=0; i<=nmain-1; i++) - { - v = v+state->factdensehaug.ptr.pp_double[i][i]; - } - if( !ae_isfinite(v, _state)||ae_fp_greater(v,badchol) ) - { - result = ae_false; - return result; - } - state->factorizationpresent = ae_true; - } - - /* - * Sparse (M+N)x(M+N) factorization - */ - if( state->factorizationtype==1 ) - { - - /* - * Generate reduced KKT matrix - */ - rallocv(n+m, &state->facttmpdiag, _state); - sparsecopybuf(&state->factsparsekkttmpl, &state->factsparsekkt, _state); - for(i=0; i<=n-1; i++) - { - ae_assert(state->factsparsekkt.didx.ptr.p_int[i]+1==state->factsparsekkt.uidx.ptr.p_int[i], "VIPMFactorize: integrity check failed, no diagonal element", _state); - v = state->factsparsekkt.vals.ptr.p_double[state->factsparsekkt.didx.ptr.p_int[i]]; - vv = (double)(0); - if( ae_fp_greater(alpha0,(double)(0)) ) - { - vv = vv+alpha0*d->ptr.p_double[i]; - } - if( ae_fp_greater(alpha11,(double)(0)) ) - { - vv = vv+alpha11; - } - vv = vv+state->diagr.ptr.p_double[i]; - vv = vv+dampeps; - v = v-vv; - state->factsparsekkt.vals.ptr.p_double[state->factsparsekkt.didx.ptr.p_int[i]] = v; - state->facttmpdiag.ptr.p_double[i] = v; - ae_assert(ae_fp_less(v,(double)(0)), "VIPMFactorize: integrity check failed, degenerate diagonal matrix", _state); - } - for(i=0; i<=msparse+mdense-1; i++) - { - ae_assert(state->factsparsekkt.didx.ptr.p_int[n+i]+1==state->factsparsekkt.uidx.ptr.p_int[n+i], "VIPMFactorize: integrity check failed, no diagonal element", _state); - v = state->factsparsekkt.vals.ptr.p_double[state->factsparsekkt.didx.ptr.p_int[n+i]]; - vv = (double)(0); - if( ae_fp_greater(beta0,(double)(0)) ) - { - vv = vv+beta0*e->ptr.p_double[i]; - } - if( ae_fp_greater(beta11,(double)(0)) ) - { - vv = vv+beta11; - } - vv = vv+dampeps; - v = v+vv; - state->factsparsekkt.vals.ptr.p_double[state->factsparsekkt.didx.ptr.p_int[n+i]] = v; - state->facttmpdiag.ptr.p_double[n+i] = v; - ae_assert(ae_fp_greater(v,(double)(0)), "VIPMFactorize: integrity check failed, degenerate diagonal matrix", _state); - } - - /* - * Perform factorization - * Perform additional integrity check: LDLT should reproduce diagonal of initial KKT system with good precision - */ - spsymmreload(&state->ldltanalysis, &state->factsparsekkt, _state); - spsymmsetmodificationstrategy(&state->ldltanalysis, 1, modeps, badchol, 0.0, 0.0, _state); - if( !spsymmfactorize(&state->ldltanalysis, &state->factsparsekkt, &state->factsparsediagd, &state->factsparsekktpivp, _state) ) - { - result = ae_false; - return result; - } - for(i=0; i<=n+m-1; i++) - { - v = state->facttmpdiag.ptr.p_double[i]; - state->facttmpdiag.ptr.p_double[i] = state->facttmpdiag.ptr.p_double[state->factsparsekktpivp.ptr.p_int[i]]; - state->facttmpdiag.ptr.p_double[state->factsparsekktpivp.ptr.p_int[i]] = v; - } - sumsq = rdotv2(n+m, &state->facttmpdiag, _state); - errsq = (double)(0); - for(i=0; i<=n+m-1; i++) - { - v = (double)(0); - k0 = state->factsparsekkt.ridx.ptr.p_int[i]; - k1 = state->factsparsekkt.didx.ptr.p_int[i]; - for(k=k0; k<=k1; k++) - { - vv = state->factsparsekkt.vals.ptr.p_double[k]; - v = v+state->factsparsediagd.ptr.p_double[state->factsparsekkt.idx.ptr.p_int[k]]*vv*vv; - } - errsq = errsq+ae_sqr(v-state->facttmpdiag.ptr.p_double[i], _state); - } - if( ae_fp_greater(ae_sqrt(errsq/(1+sumsq), _state),ae_sqrt(ae_machineepsilon, _state)) ) - { - if( state->dotrace ) - { - ae_trace("LDLT-diag-err= %0.3e (diagonal reproduction error)\n", - (double)(ae_sqrt(errsq/(1+sumsq), _state))); - } - result = ae_false; - return result; - } - state->factorizationpresent = ae_true; - - /* - * Trace - */ - if( state->dotrace ) - { - ae_trace("--- sparse KKT factorization report ----------------------------------------------------------------\n"); - ae_trace("> diagonal terms D and E\n"); - if( ae_fp_neq(alpha0,(double)(0)) ) - { - v = ae_fabs(d->ptr.p_double[0], _state); - vv = ae_fabs(d->ptr.p_double[0], _state); - for(i=1; i<=n-1; i++) - { - v = ae_minreal(v, ae_fabs(d->ptr.p_double[i], _state), _state); - vv = ae_maxreal(vv, ae_fabs(d->ptr.p_double[i], _state), _state); - } - ae_trace("diagD = %0.3e (min) ... %0.3e (max)\n", - (double)(v), - (double)(vv)); - } - if( m>0&&ae_fp_neq(beta0,(double)(0)) ) - { - v = ae_fabs(e->ptr.p_double[0], _state); - vv = ae_fabs(e->ptr.p_double[0], _state); - for(i=1; i<=m-1; i++) - { - v = ae_minreal(v, ae_fabs(e->ptr.p_double[i], _state), _state); - vv = ae_maxreal(vv, ae_fabs(e->ptr.p_double[i], _state), _state); - } - ae_trace("diagE = %0.3e (min) ... %0.3e (max)\n", - (double)(v), - (double)(vv)); - } - ae_trace("> LDLT factorization of entire KKT matrix\n"); - v = ae_fabs(state->factsparsediagd.ptr.p_double[0], _state); - vv = ae_fabs(state->factsparsediagd.ptr.p_double[0], _state); - for(i=0; i<=n+m-1; i++) - { - v = ae_maxreal(v, ae_fabs(state->factsparsediagd.ptr.p_double[i], _state), _state); - vv = ae_minreal(vv, ae_fabs(state->factsparsediagd.ptr.p_double[i], _state), _state); - } - ae_trace("|D| = %0.3e (min) ... %0.3e (max)\n", - (double)(vv), - (double)(v)); - v = 0.0; - for(i=0; i<=n+m-1; i++) - { - k0 = state->factsparsekkt.ridx.ptr.p_int[i]; - k1 = state->factsparsekkt.didx.ptr.p_int[i]; - for(k=k0; k<=k1; k++) - { - v = ae_maxreal(v, ae_fabs(state->factsparsekkt.vals.ptr.p_double[k], _state), _state); - } - } - ae_trace("max(|L|) = %0.3e\n", - (double)(v)); - ae_trace("diag-err = %0.3e (diagonal reproduction error)\n", - (double)(ae_sqrt(errsq/(1+sumsq), _state))); - } - } - - /* - * Done, integrity control - */ - ae_assert(state->factorizationpresent, "VIPMFactorize: integrity check failed", _state); - inc(&state->repncholesky, _state); - return result; -} - - -/************************************************************************* -A low-level function which solves KKT system whose regularized (!) -factorization was prepared by VIPMFactorize(). No iterative refinement is -performed. - -On input, right-hand-side is stored in DeltaXY; on output, solution replaces -DeltaXY. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static void vipmsolver_solvereducedkktsystem(vipmstate* state, - /* Real */ ae_vector* deltaxy, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nmain; - ae_int_t nslack; - ae_int_t m; - ae_int_t mdense; - ae_int_t msparse; - ae_int_t i; - ae_int_t j; - double v; - - - ae_assert(state->factorizationpresent, "VIPMSolve: integrity check failed - factorization is not present", _state); - ae_assert(state->factorizationtype==0||state->factorizationtype==1, "VIPMSolve: unexpected factorization type", _state); - n = state->n; - nmain = state->nmain; - nslack = n-nmain; - m = state->mdense+state->msparse; - mdense = state->mdense; - msparse = state->msparse; - - /* - * Dense solving - */ - if( state->factorizationtype==0 ) - { - - /* - * Compute - * - * BzWave = inv(Dz+Rz)*Bz - * ByWave = By+Az*BzWave - * BhWave = Bh-Ah'*inv(EWave)*ByWave - */ - for(i=0; i<=nslack-1; i++) - { - deltaxy->ptr.p_double[nmain+i] = deltaxy->ptr.p_double[nmain+i]*state->factinvregdzrz.ptr.p_double[i]; - } - sparsegemv(&state->combinedaslack, 1.0, 0, deltaxy, nmain, 1.0, deltaxy, n, _state); - rvectorsetlengthatleast(&state->tmp1, m, _state); - for(i=0; i<=m-1; i++) - { - state->tmp1.ptr.p_double[i] = deltaxy->ptr.p_double[n+i]/state->factregewave.ptr.p_double[i]; - } - sparsegemv(&state->sparseamain, -1.0, 1, &state->tmp1, 0, 1.0, deltaxy, 0, _state); - rmatrixgemv(nmain, mdense, -1.0, &state->denseamain, 0, 0, 1, &state->tmp1, msparse, 1.0, deltaxy, 0, _state); - - /* - * Compute Xh = -inv(HWave)*BhWave. - * Zero out components corresponding to frozen variables. - */ - for(i=0; i<=nmain-1; i++) - { - deltaxy->ptr.p_double[i] = -deltaxy->ptr.p_double[i]; - } - rmatrixtrsv(nmain, &state->factdensehaug, 0, 0, ae_false, ae_false, 0, deltaxy, 0, _state); - rmatrixtrsv(nmain, &state->factdensehaug, 0, 0, ae_false, ae_false, 1, deltaxy, 0, _state); - for(i=0; i<=n-1; i++) - { - if( state->isfrozen.ptr.p_bool[i] ) - { - deltaxy->ptr.p_double[i] = (double)(0); - } - } - - /* - * Compute Y = inv(EWave)*(ByWave-Ah*Xh) - */ - sparsegemv(&state->sparseamain, -1.0, 0, deltaxy, 0, 1.0, deltaxy, n, _state); - rmatrixgemv(mdense, nmain, -1.0, &state->denseamain, 0, 0, 0, deltaxy, 0, 1.0, deltaxy, n+msparse, _state); - for(i=0; i<=m-1; i++) - { - deltaxy->ptr.p_double[n+i] = deltaxy->ptr.p_double[n+i]/state->factregewave.ptr.p_double[i]; - } - - /* - * Compute Xz = -(BzWave - inv(Dz+Rz)*Az'*y) - */ - rvectorsetlengthatleast(&state->tmp0, nslack, _state); - for(i=0; i<=nslack-1; i++) - { - state->tmp0.ptr.p_double[i] = (double)(0); - } - sparsegemv(&state->combinedaslack, 1.0, 1, deltaxy, n, 1.0, &state->tmp0, 0, _state); - for(i=0; i<=nslack-1; i++) - { - deltaxy->ptr.p_double[nmain+i] = -(deltaxy->ptr.p_double[nmain+i]-state->factinvregdzrz.ptr.p_double[i]*state->tmp0.ptr.p_double[i]); - } - - /* - * Done - */ - return; - } - - /* - * Sparse solving - */ - if( state->factorizationtype==1 ) - { - - /* - * Solve sparse KKT system given by its triangular factorization - */ - for(i=0; i<=n-1; i++) - { - ae_assert(state->factsparsekkt.didx.ptr.p_int[i]+1==state->factsparsekkt.uidx.ptr.p_int[i]&&state->factsparsekkt.vals.ptr.p_double[state->factsparsekkt.didx.ptr.p_int[i]]!=0.0, "VIPMSolve: degenerate KKT system encountered", _state); - } - for(i=0; i<=n+m-1; i++) - { - j = state->factsparsekktpivp.ptr.p_int[i]; - v = deltaxy->ptr.p_double[i]; - deltaxy->ptr.p_double[i] = deltaxy->ptr.p_double[j]; - deltaxy->ptr.p_double[j] = v; - } - sparsetrsv(&state->factsparsekkt, ae_false, ae_false, 0, deltaxy, _state); - for(i=0; i<=n+m-1; i++) - { - if( ae_fp_neq(state->factsparsediagd.ptr.p_double[i],(double)(0)) ) - { - deltaxy->ptr.p_double[i] = deltaxy->ptr.p_double[i]/state->factsparsediagd.ptr.p_double[i]; - } - else - { - deltaxy->ptr.p_double[i] = 0.0; - } - } - sparsetrsv(&state->factsparsekkt, ae_false, ae_false, 1, deltaxy, _state); - for(i=n+m-1; i>=0; i--) - { - j = state->factsparsekktpivp.ptr.p_int[i]; - v = deltaxy->ptr.p_double[i]; - deltaxy->ptr.p_double[i] = deltaxy->ptr.p_double[j]; - deltaxy->ptr.p_double[j] = v; - } - for(i=0; i<=n-1; i++) - { - if( state->isfrozen.ptr.p_bool[i] ) - { - deltaxy->ptr.p_double[i] = (double)(0); - } - } - - /* - * Done - */ - return; - } - - /* - * - */ - ae_assert(ae_false, "VIPMSolve: integrity check failed - unexpected factorization", _state); -} - - -/************************************************************************* -Generates precomputed temporary vectors and KKT factorization at the -beginning of the current iteration. - -This function uses representation of KKT system inspired by Vanderbei -slack variable approach, but with additional regularization being applied -all along computations. - -On successful factorization returns True; on failure returns False - it is -recommended to increase regularization parameter and try one more time. - ---- DESCRIPTION ---------------------------------------------------------- - -Initial KKT system proposed by Vanderbei has following structure: - - (1) -DS*deltaT - I*deltaS = -mu/T + s + DELTAT*DELTAS/T = -GammaS - (2) -DZ*deltaG - I*deltaZ = -mu/G + z + DELTAG*DELTAZ/G = -GammaZ - (3) -DQ*deltaP - I*deltaQ = -mu/P + q + DELTAP*DELTAQ/P = -GammaQ - (4) -DW*deltaV - I*deltaW = -mu/V + w + DELTAV*DELTAW/V = -GammaW - (5) -I*deltaY - I*deltaQ + I*deltaV = y-q+v = Beta - (6) -H*deltaX +A'*deltaY + I*deltaZ - I*deltaS = c-A'*y-z+s+H*x = Sigma - (7) A*deltaX - I*deltaW = b-A*x+w = Rho - (8) I*deltaX - I*deltaG = l-x+g = Nu - (9) -I*deltaX - I*deltaT = -u+x+t = -Tau - (10) -I*deltaW - I*deltaP = -r+w+p = -Alpha - -where - - DS = diag(S/T) - DZ = diag(Z/G) - DQ = diag(Q/P) - DW = diag(W/V) - -This linear system is actually symmetric indefinite one, that can be -regularized by modifying equations (5), (6), (7), (8), (9), (10): - - (5) -I*deltaY - I*deltaQ + I*deltaV -REG*deltaW= y+q-v+REG*w = Beta - (6) -(H+REG)*deltaX +A'*deltaY + I*deltaZ - I*deltaS = c-A'*y-z+s+(H+REG)*x = Sigma - (7) A*deltaX - I*deltaW +REG*deltaY= b-A*x+w-REG*y = Rho - (8) I*deltaX - I*deltaG +REG*deltaZ= l-x+g-REG*z = Nu - (9) -I*deltaX - I*deltaT +REG*deltaS= -u+x+t-REG*s = -Tau - (10) -I*deltaW - I*deltaP +REG*deltaQ= -r+w+p-REG*q = -Alpha - -NOTE: regularizing equations (5)-(10) seems to be beneficial because their - coefficients are well-normalized, usually having unit scale. Contrary - to that, equations (1)-(4) are wildly nonnormalized, and regularization - ruins algorithm convergence. - -From (1), (2), (3) and (4) we obtain - - deltaT = (GammaS-I*deltaS)/DS - deltaG = (GammaZ-I*deltaZ)/DZ - deltaP = (GammaQ-I*deltaQ)/DQ - deltaV = (GammaW-I*deltaW)/DW - -and substitute them to equations to obtain - - (5) -I*deltaY - I*deltaQ - (inv(DW)+REG)*deltaW = Beta-inv(DW)*GammaW = BetaCap - (8) I*deltaX + (inv(DZ)+REG)*deltaZ = Nu+inv(DZ)*GammaZ = NuCap - (9) -I*deltaX + (inv(DS)+REG)*deltaS = -(Tau-inv(DS)*GammaS) = -TauCap - (10) -I*deltaW + (inv(DQ)+REG)*deltaQ = -(Alpha-inv(DQ)*GammaQ) = -AlphaCap - (6) A'*deltaY + I*deltaZ - I*deltaS - (H+REG)*deltaX = c-A'*y-z+s+(H+REG)*x = Sigma - (7) REG*deltaY + A*deltaX - I*deltaW = b-A*x+w-REG*y = Rho - -then, we obtain (here IRI stands for Invert-Regularize-Invert) - - DQIRI = inv(inv(DQ)+REG) - DZIRI = inv(inv(DZ)+REG) - DSIRI = inv(inv(DS)+REG) - - deltaQ = (I*deltaW-AlphaCap)*DQIRI - deltaZ = (NuCap-I*deltaX)*DZIRI - deltaS = (I*deltaX-TauCap)*DSIRI - - DWIR = inv(DW)+REG - -and after substitution - - (5) -I*deltaY - (DQIRI+DWIR)*deltaW = BetaCap-DQIRI*AlphaCap - (6) A'*deltaY - (H+REG+DSIRI+DZIRI)*deltaX = Sigma-DSIRI*TauCap-DZIRI*NuCap - (7) REG*deltaY + A*deltaX - I*deltaW = Rho - -finally, we obtain - - DE = inv(DQIRI+DWIR) - DER = DE+REG - DDR = DSIRI+DZIRI+REG - deltaW = -(BetaCap-DQIRI*AlphaCap+I*deltaY)*DE - -and after substitution - - (6) -(H+DDR)*deltaX + A'*deltaY = Sigma-DSIRI*TauCap-DZIRI*NuCap - (7) A*deltaX + DER*deltaY = Rho-DE*(BetaCap-DQIRI*AlphaCap) - - -- ALGLIB -- - Copyright 01.11.2020 by Bochkanov Sergey -*************************************************************************/ -static ae_bool vipmsolver_vipmprecomputenewtonfactorization(vipmstate* state, - vipmvars* v0, - double regeps, - double modeps, - double dampeps, - double dampfree, - ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - ae_int_t i; - ae_bool result; - - - n = state->n; - m = state->mdense+state->msparse; - rsetallocv(n, 0.0, &state->diagdz, _state); - rsetallocv(n, 0.0, &state->diagdzi, _state); - rsetallocv(n, 0.0, &state->diagdziri, _state); - rsetallocv(n, 0.0, &state->diagds, _state); - rsetallocv(n, 0.0, &state->diagdsi, _state); - rsetallocv(n, 0.0, &state->diagdsiri, _state); - rsetallocv(m, 0.0, &state->diagdw, _state); - rsetallocv(m, 0.0, &state->diagdwi, _state); - rsetallocv(m, 0.0, &state->diagdwir, _state); - rsetallocv(m, 0.0, &state->diagdq, _state); - rsetallocv(m, 0.0, &state->diagdqi, _state); - rsetallocv(m, 0.0, &state->diagdqiri, _state); - rallocv(n, &state->diagddr, _state); - rallocv(m, &state->diagde, _state); - rallocv(m, &state->diagder, _state); - - /* - * Handle temporary matrices arising due to box constraints - */ - for(i=0; i<=n-1; i++) - { - - /* - * Lower bound: G*inv(Z) and Z*inv(G) - */ - if( state->hasgz.ptr.p_bool[i] ) - { - ae_assert(v0->g.ptr.p_double[i]>0.0&&v0->z.ptr.p_double[i]>0.0, "VIPMPrecomputeNewtonFactorization: integrity failure - G[i]<=0 or Z[i]<=0", _state); - state->diagdz.ptr.p_double[i] = v0->z.ptr.p_double[i]/v0->g.ptr.p_double[i]; - state->diagdzi.ptr.p_double[i] = 1/state->diagdz.ptr.p_double[i]; - state->diagdziri.ptr.p_double[i] = 1/(state->diagdzi.ptr.p_double[i]+regeps); - } - else - { - ae_assert(v0->g.ptr.p_double[i]==0.0&&v0->z.ptr.p_double[i]==0.0, "VIPMPrecomputeNewtonFactorization: integrity failure - G[i]<>0 or Z[i]<>0 for absent lower bound", _state); - } - - /* - * Upper bound: T*inv(S) and S*inv(T) - */ - if( state->hasts.ptr.p_bool[i] ) - { - ae_assert(v0->t.ptr.p_double[i]>0.0&&v0->s.ptr.p_double[i]>0.0, "VIPMPrecomputeNewtonFactorization: integrity failure - T[i]<=0 or S[i]<=0", _state); - state->diagds.ptr.p_double[i] = v0->s.ptr.p_double[i]/v0->t.ptr.p_double[i]; - state->diagdsi.ptr.p_double[i] = 1/state->diagds.ptr.p_double[i]; - state->diagdsiri.ptr.p_double[i] = 1/(state->diagdsi.ptr.p_double[i]+regeps); - } - else - { - ae_assert(v0->t.ptr.p_double[i]==0.0&&v0->s.ptr.p_double[i]==0.0, "VIPMPrecomputeNewtonFactorization: integrity failure - T[i]<>0 or S[i]<>0 for absent upper bound", _state); - } - - /* - * Diagonal term D - */ - state->diagddr.ptr.p_double[i] = state->diagdziri.ptr.p_double[i]+state->diagdsiri.ptr.p_double[i]+regeps; - if( !state->hasgz.ptr.p_bool[i]&&!state->hasts.ptr.p_bool[i] ) - { - state->diagddr.ptr.p_double[i] = state->diagddr.ptr.p_double[i]+dampfree; - } - } - - /* - * Handle temporary matrices arising due to linear constraints: with lower bound B[] - * or with lower and upper bounds. - */ - for(i=0; i<=m-1; i++) - { - - /* - * Lower bound - */ - if( state->haswv.ptr.p_bool[i] ) - { - ae_assert(v0->v.ptr.p_double[i]>0.0&&v0->w.ptr.p_double[i]>0.0, "VIPMPrecomputeNewtonFactorization: integrity failure - V[i]<=0 or W[i]<=0", _state); - state->diagdw.ptr.p_double[i] = v0->w.ptr.p_double[i]/v0->v.ptr.p_double[i]; - state->diagdwi.ptr.p_double[i] = 1/state->diagdw.ptr.p_double[i]; - state->diagdwir.ptr.p_double[i] = state->diagdwi.ptr.p_double[i]+regeps; - } - else - { - ae_assert(v0->v.ptr.p_double[i]==0.0&&v0->w.ptr.p_double[i]==0.0, "VIPMPrecomputeNewtonFactorization: integrity failure - V[i]<>0 or W[i]<>0 for linear equality constraint", _state); - } - - /* - * Upper bound - */ - if( state->haspq.ptr.p_bool[i] ) - { - ae_assert(v0->p.ptr.p_double[i]>0.0&&v0->q.ptr.p_double[i]>0.0, "VIPMPrecomputeNewtonFactorization: integrity failure - P[i]<=0 or Q[i]<=0", _state); - state->diagdq.ptr.p_double[i] = v0->q.ptr.p_double[i]/v0->p.ptr.p_double[i]; - state->diagdqi.ptr.p_double[i] = 1/state->diagdq.ptr.p_double[i]; - state->diagdqiri.ptr.p_double[i] = 1/(state->diagdqi.ptr.p_double[i]+regeps); - } - else - { - ae_assert(v0->p.ptr.p_double[i]==0.0&&v0->q.ptr.p_double[i]==0.0, "VIPMPrecomputeNewtonFactorization: integrity failure - P[i]<>0 or Q[i]<>0 for absent linear constraint", _state); - } - - /* - * Diagonal term E - */ - if( state->haswv.ptr.p_bool[i]||state->haspq.ptr.p_bool[i] ) - { - state->diagde.ptr.p_double[i] = 1/(state->diagdwir.ptr.p_double[i]+state->diagdqiri.ptr.p_double[i]); - } - else - { - state->diagde.ptr.p_double[i] = 0.0; - } - state->diagder.ptr.p_double[i] = state->diagde.ptr.p_double[i]+regeps; - } - - /* - * Perform factorization - */ - result = vipmsolver_vipmfactorize(state, 1.0, &state->diagddr, 1.0, &state->diagder, 0.0, 0.0, modeps, dampeps, _state); - return result; -} - - -/************************************************************************* -Solves KKT system stored in VIPMState with user-passed RHS. The solution -X is either copied to Sol (AlphaSol=0) or added Sol:=AlphaSol*Sol+X. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static void vipmsolver_solvekktsystem(vipmstate* state, - vipmrighthandside* rhs, - vipmvars* sol, - ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - ae_int_t i; - - - n = state->n; - m = state->mdense+state->msparse; - - /* - * Compute elimination temporaries - * - * RhsAlphaCap = RhsAlpha - InvDQ*GammaQ - * RhsNuCap = RhsNu + InvDZ*GammaZ - * RhsTauCap = RhsTau - InvDS*GammaS - * RhsBetaCap = RhsBeta - InvDW*GammaW - */ - rallocv(n, &state->rhsnucap, _state); - rallocv(n, &state->rhstaucap, _state); - rallocv(m, &state->rhsbetacap, _state); - rallocv(m, &state->rhsalphacap, _state); - for(i=0; i<=m-1; i++) - { - state->rhsalphacap.ptr.p_double[i] = rhs->alpha.ptr.p_double[i]-state->diagdqi.ptr.p_double[i]*rhs->gammaq.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - state->rhsnucap.ptr.p_double[i] = rhs->nu.ptr.p_double[i]+state->diagdzi.ptr.p_double[i]*rhs->gammaz.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - state->rhstaucap.ptr.p_double[i] = rhs->tau.ptr.p_double[i]-state->diagdsi.ptr.p_double[i]*rhs->gammas.ptr.p_double[i]; - } - for(i=0; i<=m-1; i++) - { - state->rhsbetacap.ptr.p_double[i] = rhs->beta.ptr.p_double[i]-state->diagdwi.ptr.p_double[i]*rhs->gammaw.ptr.p_double[i]; - } - - /* - * Solve reduced KKT system - */ - rvectorsetlengthatleast(&state->deltaxy, n+m, _state); - for(i=0; i<=n-1; i++) - { - state->deltaxy.ptr.p_double[i] = rhs->sigma.ptr.p_double[i]-state->diagdziri.ptr.p_double[i]*state->rhsnucap.ptr.p_double[i]-state->diagdsiri.ptr.p_double[i]*state->rhstaucap.ptr.p_double[i]; - } - for(i=0; i<=m-1; i++) - { - state->deltaxy.ptr.p_double[n+i] = rhs->rho.ptr.p_double[i]-state->diagde.ptr.p_double[i]*(state->rhsbetacap.ptr.p_double[i]-state->diagdqiri.ptr.p_double[i]*state->rhsalphacap.ptr.p_double[i]); - } - vipmsolver_solvereducedkktsystem(state, &state->deltaxy, _state); - - /* - * Perform backsubstitution - */ - for(i=0; i<=n-1; i++) - { - sol->x.ptr.p_double[i] = state->deltaxy.ptr.p_double[i]; - sol->s.ptr.p_double[i] = state->diagdsiri.ptr.p_double[i]*(sol->x.ptr.p_double[i]-state->rhstaucap.ptr.p_double[i]); - sol->z.ptr.p_double[i] = state->diagdziri.ptr.p_double[i]*(state->rhsnucap.ptr.p_double[i]-sol->x.ptr.p_double[i]); - sol->g.ptr.p_double[i] = state->diagdzi.ptr.p_double[i]*(rhs->gammaz.ptr.p_double[i]-sol->z.ptr.p_double[i]); - sol->t.ptr.p_double[i] = state->diagdsi.ptr.p_double[i]*(rhs->gammas.ptr.p_double[i]-sol->s.ptr.p_double[i]); - } - for(i=0; i<=m-1; i++) - { - sol->y.ptr.p_double[i] = state->deltaxy.ptr.p_double[n+i]; - sol->w.ptr.p_double[i] = -state->diagde.ptr.p_double[i]*(state->rhsbetacap.ptr.p_double[i]-state->diagdqiri.ptr.p_double[i]*state->rhsalphacap.ptr.p_double[i]+sol->y.ptr.p_double[i]); - sol->q.ptr.p_double[i] = state->diagdqiri.ptr.p_double[i]*(sol->w.ptr.p_double[i]-state->rhsalphacap.ptr.p_double[i]); - sol->v.ptr.p_double[i] = state->diagdwi.ptr.p_double[i]*(rhs->gammaw.ptr.p_double[i]-sol->w.ptr.p_double[i]); - sol->p.ptr.p_double[i] = state->diagdqi.ptr.p_double[i]*(rhs->gammaq.ptr.p_double[i]-sol->q.ptr.p_double[i]); - } -} - - -/************************************************************************* -Compute VIPM step by solving KKT system. - -Returns False on failure to compute step direction with reasonable accuracy -(it is advised to terminate iterations immediately). - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static ae_bool vipmsolver_vipmcomputestepdirection(vipmstate* state, - vipmvars* v0, - double muestimate, - vipmvars* vdestimate, - vipmvars* vdresult, - double reg, - ae_bool isdampepslarge, - ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - double vrhsprim2; - double vrhsdual2; - double vrhscmpl2; - double vresprim2; - double vresdual2; - double vrescmpl2; - double vrhspriminf; - double vrhsdualinf; - double vrespriminf; - double vresdualinf; - double badres; - double verybadres; - double residualgrowth; - ae_bool primaldestabilized; - ae_bool dualdestabilized; - ae_bool result; - - - n = state->n; - m = state->mdense+state->msparse; - badres = 1.01; - verybadres = 1.0E3; - result = ae_true; - - /* - * Initial solver report - */ - if( state->dotrace ) - { - ae_trace("--- detailed KKT solver report ---------------------------------------------------------------------\n"); - } - - /* - * Solve KKT system with right-hand sides coming from primal, dual - * and complementary slackness conditions. Analyze solution, - * terminate immediately if primal/dual residuals are way too high. - */ - vipmsolver_varsinitbyzero(vdresult, n, m, _state); - vipmsolver_rhscompute(state, v0, muestimate, vdestimate, &state->rhs, reg, _state); - vrhsprim2 = vipmsolver_rhsprimal2(&state->rhs, n, m, _state); - vrhsdual2 = vipmsolver_rhsdual2(&state->rhs, n, m, _state); - vrhscmpl2 = vipmsolver_rhscompl2(&state->rhs, n, m, _state); - vrhspriminf = vipmsolver_rhsprimalinf(&state->rhs, n, m, _state); - vrhsdualinf = vipmsolver_rhsdualinf(&state->rhs, n, m, _state); - if( state->dotrace ) - { - ae_trace("> primal/dual/complementarity right-hand-side\n"); - ae_trace("rhs-prim = %0.3e (2-norm)\n", - (double)(ae_sqrt(vrhsprim2, _state))); - ae_trace("rhs-dual = %0.3e (2-norm)\n", - (double)(ae_sqrt(vrhsdual2, _state))); - ae_trace("rhs-cmpl = %0.3e (2-norm)\n", - (double)(ae_sqrt(vrhscmpl2, _state))); - } - vipmsolver_solvekktsystem(state, &state->rhs, vdresult, _state); - vipmsolver_rhssubtract(state, &state->rhs, v0, vdresult, reg, _state); - vresprim2 = vipmsolver_rhsprimal2(&state->rhs, n, m, _state); - vresdual2 = vipmsolver_rhsdual2(&state->rhs, n, m, _state); - vrescmpl2 = vipmsolver_rhscompl2(&state->rhs, n, m, _state); - vrespriminf = vipmsolver_rhsprimalinf(&state->rhs, n, m, _state); - vresdualinf = vipmsolver_rhsdualinf(&state->rhs, n, m, _state); - if( state->dotrace ) - { - ae_trace("> primal/dual/complementarity residuals compared with RHS\n"); - ae_trace("res/rhs prim = %0.3e\n", - (double)(ae_sqrt(vresprim2/coalesce(vrhsprim2, (double)(1), _state), _state))); - ae_trace("res/rhs dual = %0.3e\n", - (double)(ae_sqrt(vresdual2/coalesce(vrhsdual2, (double)(1), _state), _state))); - ae_trace("res/rhs cmpl = %0.3e\n", - (double)(ae_sqrt(vrescmpl2/coalesce(vrhscmpl2, (double)(1), _state), _state))); - ae_trace("res/rhs all = %0.3e\n", - (double)(ae_sqrt((vresprim2+vresdual2+vrescmpl2)/coalesce(vrhsprim2+vrhsdual2+vrhscmpl2, (double)(1), _state), _state))); - } - primaldestabilized = ae_fp_less_eq(vrhspriminf,state->epsp)&&ae_fp_greater_eq(vrespriminf,ae_maxreal(verybadres*vrhspriminf, state->epsp, _state)); - dualdestabilized = ae_fp_less_eq(vrhsdualinf,state->epsd)&&ae_fp_greater_eq(vresdualinf,ae_maxreal(verybadres*vrhsdualinf, state->epsd, _state)); - residualgrowth = ae_sqrt((vresprim2+vresdual2+vrescmpl2)/coalesce(vrhsprim2+vrhsdual2+vrhscmpl2, (double)(1), _state), _state); - if( ((primaldestabilized||dualdestabilized)&&ae_fp_greater(residualgrowth,0.01*ae_sqrt(ae_machineepsilon, _state)))&&!isdampepslarge ) - { - if( state->dotrace ) - { - ae_trace("> primal/dual residual growth is too high, signaling presence of numerical errors\n"); - } - result = ae_false; - return result; - } - if( ae_fp_greater(residualgrowth,badres) ) - { - if( state->dotrace ) - { - ae_trace("> total residual is too high, signaling presence of numerical errors\n"); - } - result = ae_false; - return result; - } - return result; -} - - -/************************************************************************* -This function estimates primal and dual step lengths (subject to step -decay parameter, which should be in [0,1] range). - -Current version returns same step lengths for primal and dual steps. - -INPUT PARAMETERS: - State - solver state - V0 - current point (we ignore one stored in State.Current) - VS - step direction - StepDecay - decay parameter, the step is multiplied by this - coefficient. 1.0 corresponds to full step - length being returned. Values in (0,1] range. - -OUTPUT PARAMETERS: - AlphaP - primal step (after applying decay coefficient) - AlphaD - dual step (after applying decay coefficient) - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static void vipmsolver_vipmcomputesteplength(vipmstate* state, - vipmvars* v0, - vipmvars* vs, - double stepdecay, - double* alphap, - double* alphad, - ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - ae_int_t i; - double alpha; - - *alphap = 0; - *alphad = 0; - - n = state->n; - m = state->mdense+state->msparse; - ae_assert(n==v0->n&&m==v0->m, "VIPMComputeStepLength: sizes mismatch", _state); - *alphap = (double)(1); - *alphad = (double)(1); - for(i=0; i<=n-1; i++) - { - - /* - * Primal - */ - if( vs->g.ptr.p_double[i]<0.0 ) - { - *alphap = safeminposrv(v0->g.ptr.p_double[i], -vs->g.ptr.p_double[i], *alphap, _state); - } - if( vs->t.ptr.p_double[i]<0.0 ) - { - *alphap = safeminposrv(v0->t.ptr.p_double[i], -vs->t.ptr.p_double[i], *alphap, _state); - } - - /* - * Dual - */ - if( vs->z.ptr.p_double[i]<0.0 ) - { - *alphad = safeminposrv(v0->z.ptr.p_double[i], -vs->z.ptr.p_double[i], *alphad, _state); - } - if( vs->s.ptr.p_double[i]<0.0 ) - { - *alphad = safeminposrv(v0->s.ptr.p_double[i], -vs->s.ptr.p_double[i], *alphad, _state); - } - } - for(i=0; i<=m-1; i++) - { - - /* - * Primal - */ - if( vs->w.ptr.p_double[i]<0.0 ) - { - *alphap = safeminposrv(v0->w.ptr.p_double[i], -vs->w.ptr.p_double[i], *alphap, _state); - } - if( vs->p.ptr.p_double[i]<0.0 ) - { - *alphap = safeminposrv(v0->p.ptr.p_double[i], -vs->p.ptr.p_double[i], *alphap, _state); - } - - /* - * Dual - */ - if( vs->v.ptr.p_double[i]<0.0 ) - { - *alphad = safeminposrv(v0->v.ptr.p_double[i], -vs->v.ptr.p_double[i], *alphad, _state); - } - if( vs->q.ptr.p_double[i]<0.0 ) - { - *alphad = safeminposrv(v0->q.ptr.p_double[i], -vs->q.ptr.p_double[i], *alphad, _state); - } - } - - /* - * Because we may solve QP problem, step length has to be same for primal and dual variables - */ - alpha = ae_minreal(*alphap, *alphad, _state); - - /* - * Apply decay - */ - *alphap = stepdecay*alpha; - *alphad = stepdecay*alpha; -} - - -/************************************************************************* -This function performs IPM step, updates iteration counts and performs -following additional checks: -* it monitors status of box/linear constraints and smoothly drops ones - with too large bounds (a variable or linear sum is well below constraint - bound for several iterations) - -INPUT PARAMETERS: - State - solver state - AlphaP - primal step to perform - AlphaD - dual step to perform - -OUTPUT PARAMETERS: - - -- ALGLIB -- - Copyright 01.08.2020 by Bochkanov Sergey -*************************************************************************/ -static void vipmsolver_vipmperformstep(vipmstate* state, - double alphap, - double alphad, - ae_state *_state) -{ - - - - /* - * Perform step - */ - vipmsolver_varsaddstep(&state->current, &state->deltacorr, alphap, alphad, _state); - - /* - * Update iterations count - */ - inc(&state->repiterationscount, _state); -} - - -/************************************************************************* -Compute primal/dual errors and complementarity gap - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static void vipmsolver_computeerrors(vipmstate* state, - double* errp2, - double* errd2, - double* errpinf, - double* errdinf, - double* egap, - ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - ae_int_t i; - ae_int_t cntp2; - ae_int_t cntd2; - double v; - - *errp2 = 0; - *errd2 = 0; - *errpinf = 0; - *errdinf = 0; - *egap = 0; - - n = state->n; - m = state->mdense+state->msparse; - - /* - * Compute primal and dual infeasibilities - */ - vipmsolver_vipmmultiply(state, &state->current.x, &state->current.y, &state->tmphx, &state->tmpax, &state->tmpaty, _state); - cntp2 = 0; - *errp2 = (double)(0); - *errpinf = (double)(0); - for(i=0; i<=m-1; i++) - { - v = state->tmpax.ptr.p_double[i]-state->current.w.ptr.p_double[i]-state->b.ptr.p_double[i]; - *errp2 = *errp2+v*v; - *errpinf = ae_maxreal(*errpinf, ae_fabs(v, _state), _state); - inc(&cntp2, _state); - if( state->haspq.ptr.p_bool[i] ) - { - v = state->current.w.ptr.p_double[i]+state->current.p.ptr.p_double[i]-state->r.ptr.p_double[i]; - *errp2 = *errp2+v*v; - *errpinf = ae_maxreal(*errpinf, ae_fabs(v, _state), _state); - inc(&cntp2, _state); - } - } - for(i=0; i<=n-1; i++) - { - if( state->hasgz.ptr.p_bool[i] ) - { - v = state->current.x.ptr.p_double[i]-state->current.g.ptr.p_double[i]-state->bndl.ptr.p_double[i]; - *errp2 = *errp2+v*v; - *errpinf = ae_maxreal(*errpinf, ae_fabs(v, _state), _state); - inc(&cntp2, _state); - } - if( state->hasts.ptr.p_bool[i] ) - { - v = state->current.x.ptr.p_double[i]+state->current.t.ptr.p_double[i]-state->bndu.ptr.p_double[i]; - *errp2 = *errp2+v*v; - *errpinf = ae_maxreal(*errpinf, ae_fabs(v, _state), _state); - inc(&cntp2, _state); - } - } - *errp2 = ae_sqrt(*errp2/coalesce((double)(cntp2), (double)(1), _state), _state); - cntd2 = 0; - *errd2 = (double)(0); - *errdinf = (double)(0); - for(i=0; i<=n-1; i++) - { - if( !state->isfrozen.ptr.p_bool[i] ) - { - v = state->tmphx.ptr.p_double[i]+state->c.ptr.p_double[i]-state->tmpaty.ptr.p_double[i]; - if( state->hasgz.ptr.p_bool[i] ) - { - v = v-state->current.z.ptr.p_double[i]; - } - if( state->hasts.ptr.p_bool[i] ) - { - v = v+state->current.s.ptr.p_double[i]; - } - *errd2 = *errd2+v*v; - *errdinf = ae_maxreal(*errdinf, ae_fabs(v, _state), _state); - inc(&cntd2, _state); - } - } - for(i=0; i<=m-1; i++) - { - v = (double)(0); - if( state->haswv.ptr.p_bool[i] ) - { - v = state->current.y.ptr.p_double[i]-state->current.v.ptr.p_double[i]; - } - if( state->haspq.ptr.p_bool[i] ) - { - v = v+state->current.q.ptr.p_double[i]; - } - *errd2 = *errd2+v*v; - *errdinf = ae_maxreal(*errdinf, ae_fabs(v, _state), _state); - if( state->haswv.ptr.p_bool[i]||state->haspq.ptr.p_bool[i] ) - { - inc(&cntd2, _state); - } - } - *errd2 = ae_sqrt(*errd2/coalesce((double)(cntd2), (double)(1), _state), _state); - *egap = vipmsolver_varscomputecomplementaritygap(&state->current, _state)/(1.0+ae_fabs(vipmsolver_vipmtarget(state, &state->current.x, _state), _state)); -} - - -/************************************************************************* -Performs integrity checks for current point and step - - -- ALGLIB -- - Copyright 01.11.2020 by Bochkanov Sergey -*************************************************************************/ -static void vipmsolver_runintegritychecks(vipmstate* state, - vipmvars* v0, - vipmvars* vd, - double alphap, - double alphad, - ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - ae_int_t i; - - - n = state->n; - m = state->mdense+state->msparse; - ae_assert(ae_isfinite(alphap, _state)&&ae_fp_greater_eq(alphap,(double)(0)), "[VIPM]RunIntegrityChecks: bad AlphaP", _state); - ae_assert(ae_isfinite(alphad, _state)&&ae_fp_greater_eq(alphad,(double)(0)), "[VIPM]RunIntegrityChecks: bad AlphaD", _state); - for(i=0; i<=n-1; i++) - { - if( state->hasgz.ptr.p_bool[i] ) - { - ae_assert(!state->isfrozen.ptr.p_bool[i], "[VIPM]RunIntegrityChecks: integrity failure - X[I] is frozen", _state); - ae_assert(v0->g.ptr.p_double[i]>0.0&&v0->z.ptr.p_double[i]>0.0, "[VIPM]RunIntegrityChecks: integrity failure - G[i]<=0 or Z[i]<=0", _state); - } - else - { - ae_assert(v0->g.ptr.p_double[i]==0.0&&v0->z.ptr.p_double[i]==0.0, "[VIPM]RunIntegrityChecks: integrity failure - G[i]<>0 or Z[i]<>0 for absent lower bound", _state); - ae_assert(vd->g.ptr.p_double[i]==0.0&&vd->z.ptr.p_double[i]==0.0, "[VIPM]RunIntegrityChecks: integrity failure - G[i]<>0 or Z[i]<>0 for absent lower bound", _state); - } - if( state->hasts.ptr.p_bool[i] ) - { - ae_assert(!state->isfrozen.ptr.p_bool[i], "[VIPM]RunIntegrityChecks: integrity failure - X[I] is frozen", _state); - ae_assert(v0->t.ptr.p_double[i]>0.0&&v0->s.ptr.p_double[i]>0.0, "[VIPM]RunIntegrityChecks: integrity failure - T[i]<=0 or S[i]<=0", _state); - } - else - { - ae_assert(v0->t.ptr.p_double[i]==0.0&&v0->s.ptr.p_double[i]==0.0, "[VIPM]RunIntegrityChecks: integrity failure - T[i]<>0 or S[i]<>0 for absent upper bound", _state); - ae_assert(vd->t.ptr.p_double[i]==0.0&&vd->s.ptr.p_double[i]==0.0, "[VIPM]RunIntegrityChecks: integrity failure - T[i]<>0 or S[i]<>0 for absent upper bound", _state); - } - } - for(i=0; i<=m-1; i++) - { - ae_assert(state->haswv.ptr.p_bool[i]||!state->haspq.ptr.p_bool[i], "[VIPM]RunIntegrityChecks: inconsistent HasWV/HasPQ", _state); - if( state->haswv.ptr.p_bool[i] ) - { - ae_assert(v0->v.ptr.p_double[i]>0.0&&v0->w.ptr.p_double[i]>0.0, "[VIPM]RunIntegrityChecks: integrity failure - V[i]<=0 or W[i]<=0", _state); - } - else - { - ae_assert(v0->v.ptr.p_double[i]==0.0&&v0->w.ptr.p_double[i]==0.0, "[VIPM]RunIntegrityChecks: integrity failure - V[i]<>0 or W[i]<>0 for linear equality constraint", _state); - ae_assert(vd->v.ptr.p_double[i]==0.0&&vd->w.ptr.p_double[i]==0.0, "[VIPM]RunIntegrityChecks: integrity failure - V[i]<>0 or W[i]<>0 for linear equality constraint", _state); - } - if( state->haspq.ptr.p_bool[i] ) - { - ae_assert(v0->p.ptr.p_double[i]>0.0&&v0->q.ptr.p_double[i]>0.0, "[VIPM]RunIntegrityChecks: integrity failure - P[i]<=0 or Q[i]<=0", _state); - } - else - { - ae_assert(v0->p.ptr.p_double[i]==0.0&&v0->q.ptr.p_double[i]==0.0, "[VIPM]RunIntegrityChecks: integrity failure - P[i]<>0 or Q[i]<>0 for absent range of linear constraint", _state); - ae_assert(vd->p.ptr.p_double[i]==0.0&&vd->q.ptr.p_double[i]==0.0, "[VIPM]RunIntegrityChecks: integrity failure - P[i]<>0 or Q[i]<>0 for absent range of linear constraint", _state); - } - } -} - - -/************************************************************************* -Evaluate progress so far, outputs trace data, if requested to do so. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static void vipmsolver_traceprogress(vipmstate* state, - double mu, - double muaff, - double sigma, - double alphap, - double alphad, - ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - ae_int_t i; - double v; - double errp2; - double errd2; - double errpinf; - double errdinf; - double errgap; - - - n = state->n; - m = state->mdense+state->msparse; - if( !state->dotrace ) - { - return; - } - - /* - * Print high-level information - */ - vipmsolver_computeerrors(state, &errp2, &errd2, &errpinf, &errdinf, &errgap, _state); - ae_trace("--- step report ------------------------------------------------------------------------------------\n"); - ae_trace("> step information\n"); - ae_trace("mu_init = %0.3e (at the beginning)\n", - (double)(mu)); - ae_trace("mu_aff = %0.3e (by affine scaling step)\n", - (double)(muaff)); - ae_trace("sigma = %0.3e (centering parameter)\n", - (double)(sigma)); - ae_trace("alphaP = %0.3e (primal step)\n", - (double)(alphap)); - ae_trace("alphaD = %0.3e (dual step)\n", - (double)(alphad)); - ae_trace("mu_cur = %0.3e (after the step)\n", - (double)(vipmsolver_varscomputemu(&state->current, _state))); - ae_trace("> errors\n"); - ae_trace("errP = %0.3e (primal infeasibility, inf-norm)\n", - (double)(errpinf)); - ae_trace("errD = %0.3e (dual infeasibility, inf-norm)\n", - (double)(errdinf)); - ae_trace("errGap = %0.3e (complementarity gap)\n", - (double)(errgap)); - ae_trace("> current point information (inf-norm)\n"); - ae_trace("|X|=%8.1e, |G|=%8.1e, |T|=%8.1e, |W|=%8.1e, |P|=%8.1e\n", - (double)(rmaxabsv(n, &state->current.x, _state)), - (double)(rmaxabsv(n, &state->current.g, _state)), - (double)(rmaxabsv(n, &state->current.t, _state)), - (double)(rmaxabsv(m, &state->current.w, _state)), - (double)(rmaxabsv(m, &state->current.p, _state))); - ae_trace("|Y|=%8.1e, |Z|=%8.1e, |S|=%8.1e, |V|=%8.1e, |Q|=%8.1e\n", - (double)(rmaxabsv(m, &state->current.y, _state)), - (double)(rmaxabsv(n, &state->current.z, _state)), - (double)(rmaxabsv(n, &state->current.s, _state)), - (double)(rmaxabsv(m, &state->current.v, _state)), - (double)(rmaxabsv(m, &state->current.q, _state))); - - /* - * Print variable stats, if required - */ - if( state->dotrace ) - { - ae_trace("--- variable statistics ----------------------------------------------------------------------------\n"); - ae_trace("> smallest values for nonnegative vars\n"); - ae_trace("primal: minG=%8.1e minT=%8.1e minW=%8.1e minP=%8.1e\n", - (double)(vipmsolver_minnz(&state->current.g, n, _state)), - (double)(vipmsolver_minnz(&state->current.t, n, _state)), - (double)(vipmsolver_minnz(&state->current.w, m, _state)), - (double)(vipmsolver_minnz(&state->current.p, m, _state))); - ae_trace("dual: minZ=%8.1e minS=%8.1e minV=%8.1e minQ=%8.1e\n", - (double)(vipmsolver_minnz(&state->current.z, n, _state)), - (double)(vipmsolver_minnz(&state->current.s, n, _state)), - (double)(vipmsolver_minnz(&state->current.v, m, _state)), - (double)(vipmsolver_minnz(&state->current.q, m, _state))); - ae_trace("> min and max complementary slackness\n"); - ae_trace("min: GZ=%8.1e TS=%8.1e WV=%8.1e PQ=%8.1e\n", - (double)(vipmsolver_minprodnz(&state->current.g, &state->current.z, n, _state)), - (double)(vipmsolver_minprodnz(&state->current.t, &state->current.s, n, _state)), - (double)(vipmsolver_minprodnz(&state->current.w, &state->current.v, m, _state)), - (double)(vipmsolver_minprodnz(&state->current.p, &state->current.q, m, _state))); - ae_trace("max: GZ=%8.1e TS=%8.1e WV=%8.1e PQ=%8.1e\n", - (double)(vipmsolver_maxprodnz(&state->current.g, &state->current.z, n, _state)), - (double)(vipmsolver_maxprodnz(&state->current.t, &state->current.s, n, _state)), - (double)(vipmsolver_maxprodnz(&state->current.w, &state->current.v, m, _state)), - (double)(vipmsolver_maxprodnz(&state->current.p, &state->current.q, m, _state))); - } - - /* - * Detailed output (all variables values, not suited for high-dimensional problems) - */ - if( state->dodetailedtrace ) - { - vipmsolver_vipmmultiply(state, &state->current.x, &state->current.y, &state->tmphx, &state->tmpax, &state->tmpaty, _state); - rsetallocv(n, 0.0, &state->tmplaggrad, _state); - for(i=0; i<=n-1; i++) - { - if( !state->isfrozen.ptr.p_bool[i] ) - { - v = state->tmphx.ptr.p_double[i]+state->c.ptr.p_double[i]-state->tmpaty.ptr.p_double[i]; - if( state->hasgz.ptr.p_bool[i] ) - { - v = v-state->current.z.ptr.p_double[i]; - } - if( state->hasts.ptr.p_bool[i] ) - { - v = v+state->current.s.ptr.p_double[i]; - } - state->tmplaggrad.ptr.p_double[i] = v; - } - } - ae_trace("--- printing raw data (prior to applying variable scales and shifting by XOrigin) ------------------\n"); - ae_trace("X (raw) = "); - tracevectorunscaledunshiftedautoprec(&state->current.x, n, &state->scl, ae_true, &state->xorigin, ae_true, _state); - ae_trace("\n"); - ae_trace("--- printing scaled data (after applying variable scales and shifting by XOrigin) ------------------\n"); - ae_trace("> reporting X, Lagrangian gradient\n"); - ae_trace("Xnew = "); - tracevectorautoprec(&state->current.x, 0, n, _state); - ae_trace("\n"); - ae_trace("Lag-grad = "); - tracevectorautoprec(&state->tmplaggrad, 0, n, _state); - ae_trace("\n"); - ae_trace("--- printing new point -----------------------------------------------------------------------------\n"); - ae_trace("> primal slacks and dual multipliers for box constraints\n"); - ae_trace("G (L prim slck) = "); - tracevectorautoprec(&state->current.g, 0, n, _state); - ae_trace("\n"); - ae_trace("Z (L dual mult) = "); - tracevectorautoprec(&state->current.z, 0, n, _state); - ae_trace("\n"); - ae_trace("T (U prim slck) = "); - tracevectorautoprec(&state->current.t, 0, n, _state); - ae_trace("\n"); - ae_trace("S (U dual mult) = "); - tracevectorautoprec(&state->current.s, 0, n, _state); - ae_trace("\n"); - ae_trace("> primal slacks and dual multipliers for linear constraints, B/R stand for B<=Ax<=B+R\n"); - ae_trace("Y (lag mult) = "); - tracevectorautoprec(&state->current.y, 0, m, _state); - ae_trace("\n"); - ae_trace("W (B prim slck) = "); - tracevectorautoprec(&state->current.w, 0, m, _state); - ae_trace("\n"); - ae_trace("V (B dual mult) = "); - tracevectorautoprec(&state->current.v, 0, m, _state); - ae_trace("\n"); - ae_trace("P (R prim slck) = "); - tracevectorautoprec(&state->current.p, 0, m, _state); - ae_trace("\n"); - ae_trace("Q (R dual mult) = "); - tracevectorautoprec(&state->current.q, 0, m, _state); - ae_trace("\n"); - } - ae_trace("\n"); -} - - -/************************************************************************* -Compute right-hand side for KKT system. - -INPUT PARAMETERS: - State - IPM state - V0 - current point (used to compute RHS) - MuEstimate - estimate of Mu (can be zero) - DirEstimate - estimate of delta's (can be zero) - -OUTPUT PARAMETERS: - Rhs - RHS - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static void vipmsolver_rhscompute(vipmstate* state, - vipmvars* v0, - double muestimate, - vipmvars* direstimate, - vipmrighthandside* rhs, - double reg, - ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - ae_int_t i; - - - n = state->n; - m = state->mdense+state->msparse; - - /* - * Allocate - */ - rvectorsetlengthatleast(&rhs->sigma, n, _state); - rvectorsetlengthatleast(&rhs->nu, n, _state); - rvectorsetlengthatleast(&rhs->tau, n, _state); - rvectorsetlengthatleast(&rhs->gammaz, n, _state); - rvectorsetlengthatleast(&rhs->gammas, n, _state); - rvectorsetlengthatleast(&rhs->gammaw, m, _state); - rvectorsetlengthatleast(&rhs->gammaq, m, _state); - rsetallocv(m, 0.0, &rhs->beta, _state); - rsetallocv(m, 0.0, &rhs->rho, _state); - rsetallocv(m, 0.0, &rhs->alpha, _state); - - /* - * Compute products H*x, A*x, A^T*y - * We compute these products in one location for the sake of simplicity. - */ - vipmsolver_vipmmultiply(state, &v0->x, &v0->y, &state->tmphx, &state->tmpax, &state->tmpaty, _state); - - /* - * Compute right-hand side: - * Rho = b - A*x + w - * Nu = l - x + g - * Tau = u - x - t - * Alpha = r - w - p - * Sigma = c - A^T*y - z + s + (H+REG)*x - * Beta = y + q - v - */ - for(i=0; i<=m-1; i++) - { - rhs->rho.ptr.p_double[i] = state->b.ptr.p_double[i]-state->tmpax.ptr.p_double[i]-reg*v0->y.ptr.p_double[i]; - if( state->haswv.ptr.p_bool[i] ) - { - - /* - * Inequality/range constraint - */ - rhs->rho.ptr.p_double[i] = rhs->rho.ptr.p_double[i]+v0->w.ptr.p_double[i]; - } - else - { - - /* - * Equality constraint without slack variables, W[i]=0 - */ - ae_assert(v0->w.ptr.p_double[i]==0.0, "RhsCompute: W[i]<>0 for linear equality constraint", _state); - } - } - for(i=0; i<=n-1; i++) - { - if( state->hasgz.ptr.p_bool[i] ) - { - - /* - * Lower bound is present - */ - rhs->nu.ptr.p_double[i] = state->bndl.ptr.p_double[i]-v0->x.ptr.p_double[i]+v0->g.ptr.p_double[i]-reg*v0->z.ptr.p_double[i]; - } - else - { - - /* - * Lower bound is absent, g[i] = 0 - */ - ae_assert(v0->g.ptr.p_double[i]==0.0, "RhsCompute: G[i]<>0 for absent constraint", _state); - rhs->nu.ptr.p_double[i] = (double)(0); - } - } - for(i=0; i<=n-1; i++) - { - if( state->hasts.ptr.p_bool[i] ) - { - - /* - * Upper bound is present - */ - rhs->tau.ptr.p_double[i] = state->bndu.ptr.p_double[i]-v0->x.ptr.p_double[i]-v0->t.ptr.p_double[i]+reg*v0->s.ptr.p_double[i]; - } - else - { - - /* - * Upper bound is absent, t[i] = 0 - */ - ae_assert(v0->t.ptr.p_double[i]==0.0, "RhsCompute: T[i]<>0 for absent constraint", _state); - rhs->tau.ptr.p_double[i] = (double)(0); - } - } - for(i=0; i<=m-1; i++) - { - if( state->haspq.ptr.p_bool[i] ) - { - rhs->alpha.ptr.p_double[i] = state->r.ptr.p_double[i]-v0->w.ptr.p_double[i]-v0->p.ptr.p_double[i]+reg*v0->q.ptr.p_double[i]; - } - } - for(i=0; i<=n-1; i++) - { - if( !state->isfrozen.ptr.p_bool[i] ) - { - rhs->sigma.ptr.p_double[i] = state->c.ptr.p_double[i]-state->tmpaty.ptr.p_double[i]+state->tmphx.ptr.p_double[i]+reg*v0->x.ptr.p_double[i]; - if( state->hasgz.ptr.p_bool[i] ) - { - rhs->sigma.ptr.p_double[i] = rhs->sigma.ptr.p_double[i]-v0->z.ptr.p_double[i]; - } - if( state->hasts.ptr.p_bool[i] ) - { - rhs->sigma.ptr.p_double[i] = rhs->sigma.ptr.p_double[i]+v0->s.ptr.p_double[i]; - } - } - else - { - rhs->sigma.ptr.p_double[i] = (double)(0); - } - } - for(i=0; i<=m-1; i++) - { - if( state->haswv.ptr.p_bool[i] ) - { - rhs->beta.ptr.p_double[i] = rhs->beta.ptr.p_double[i]+v0->y.ptr.p_double[i]-v0->v.ptr.p_double[i]+reg*v0->w.ptr.p_double[i]; - } - if( state->haspq.ptr.p_bool[i] ) - { - rhs->beta.ptr.p_double[i] = rhs->beta.ptr.p_double[i]+v0->q.ptr.p_double[i]; - } - } - - /* - * Compute right-hand side: - * GammaZ = mu*inv(G)*e - z - inv(G)*DELTAG*deltaZ - * GammaW = mu*inv(V)*e - w - inv(V)*DELTAV*deltaW - * GammaS = mu*inv(T)*e - s - inv(T)*DELTAT*deltaS - * GammaQ = mu*inv(P)*e - q - inv(P)*DELTAP*deltaQ - */ - for(i=0; i<=n-1; i++) - { - if( state->hasgz.ptr.p_bool[i] ) - { - ae_assert(v0->g.ptr.p_double[i]>0.0, "RhsCompute: G[i]<=0", _state); - rhs->gammaz.ptr.p_double[i] = muestimate/v0->g.ptr.p_double[i]-v0->z.ptr.p_double[i]-direstimate->g.ptr.p_double[i]*direstimate->z.ptr.p_double[i]/v0->g.ptr.p_double[i]; - } - else - { - ae_assert(v0->g.ptr.p_double[i]==0.0, "RhsCompute: G[i]<>0 for absent constraint", _state); - ae_assert(v0->z.ptr.p_double[i]==0.0, "RhsCompute: Z[i]<>0 for absent constraint", _state); - rhs->gammaz.ptr.p_double[i] = (double)(0); - } - } - for(i=0; i<=m-1; i++) - { - if( state->haswv.ptr.p_bool[i] ) - { - - /* - * Inequality/range constraint - */ - ae_assert(v0->v.ptr.p_double[i]>0.0, "RhsCompute: V[i]<=0", _state); - rhs->gammaw.ptr.p_double[i] = muestimate/v0->v.ptr.p_double[i]-v0->w.ptr.p_double[i]-direstimate->v.ptr.p_double[i]*direstimate->w.ptr.p_double[i]/v0->v.ptr.p_double[i]; - } - else - { - - /* - * Equality constraint - */ - ae_assert(v0->v.ptr.p_double[i]==0.0, "RhsCompute: V[i]<>0 for equality constraint", _state); - ae_assert(v0->w.ptr.p_double[i]==0.0, "RhsCompute: W[i]<>0 for equality constraint", _state); - rhs->gammaw.ptr.p_double[i] = (double)(0); - } - } - for(i=0; i<=n-1; i++) - { - if( state->hasts.ptr.p_bool[i] ) - { - - /* - * Upper bound is present - */ - ae_assert(v0->t.ptr.p_double[i]>0.0, "RhsCompute: T[i]<=0", _state); - rhs->gammas.ptr.p_double[i] = muestimate/v0->t.ptr.p_double[i]-v0->s.ptr.p_double[i]-direstimate->t.ptr.p_double[i]*direstimate->s.ptr.p_double[i]/v0->t.ptr.p_double[i]; - } - else - { - - /* - * Upper bound is absent - */ - ae_assert(v0->t.ptr.p_double[i]==0.0, "RhsCompute: T[i]<>0 for absent constraint", _state); - ae_assert(v0->s.ptr.p_double[i]==0.0, "RhsCompute: S[i]<>0 for absent constraint", _state); - rhs->gammas.ptr.p_double[i] = (double)(0); - } - } - for(i=0; i<=m-1; i++) - { - if( state->haspq.ptr.p_bool[i] ) - { - ae_assert(v0->p.ptr.p_double[i]>0.0, "RhsCompute: P[i]<=0", _state); - rhs->gammaq.ptr.p_double[i] = muestimate/v0->p.ptr.p_double[i]-v0->q.ptr.p_double[i]-direstimate->p.ptr.p_double[i]*direstimate->q.ptr.p_double[i]/v0->p.ptr.p_double[i]; - } - else - { - ae_assert(v0->p.ptr.p_double[i]==0.0, "RhsCompute: P[i]<>0 for absent range", _state); - ae_assert(v0->q.ptr.p_double[i]==0.0, "RhsCompute: Q[i]<>0 for absent range", _state); - rhs->gammaq.ptr.p_double[i] = (double)(0); - } - } -} - - -/************************************************************************* -Subtracts KKT*cand from already computed RHS. - -A pair of RhsCompute/RhsSubtract calls results in residual being loaded -into the RHS structure. - -INPUT PARAMETERS: - State - IPM state - V0 - current point (used to compute RHS) - MuEstimate - estimate of Mu (can be zero) - DirEstimate - estimate of delta's (can be zero) - ResidualFrom - whether we want to compute RHS or residual computed - using VDCandidate - VDCandidate - solution candidate - -OUTPUT PARAMETERS: - Rhs - either RHS or residual RHS-KKT*Cand - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static void vipmsolver_rhssubtract(vipmstate* state, - vipmrighthandside* rhs, - vipmvars* v0, - vipmvars* vdcandidate, - double reg, - ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - ae_int_t i; - - - n = state->n; - m = state->mdense+state->msparse; - vipmsolver_vipmmultiply(state, &vdcandidate->x, &vdcandidate->y, &state->tmphx, &state->tmpax, &state->tmpaty, _state); - - /* - * Residual for Rho, Nu, Tau, Alpha, Sigma, Beta - */ - for(i=0; i<=m-1; i++) - { - if( state->haswv.ptr.p_bool[i] ) - { - rhs->rho.ptr.p_double[i] = rhs->rho.ptr.p_double[i]-(state->tmpax.ptr.p_double[i]-vdcandidate->w.ptr.p_double[i]+reg*vdcandidate->y.ptr.p_double[i]); - } - else - { - rhs->rho.ptr.p_double[i] = rhs->rho.ptr.p_double[i]-(state->tmpax.ptr.p_double[i]+reg*vdcandidate->y.ptr.p_double[i]); - } - } - for(i=0; i<=n-1; i++) - { - if( state->hasgz.ptr.p_bool[i] ) - { - rhs->nu.ptr.p_double[i] = rhs->nu.ptr.p_double[i]-(vdcandidate->x.ptr.p_double[i]-vdcandidate->g.ptr.p_double[i]+reg*vdcandidate->z.ptr.p_double[i]); - } - } - for(i=0; i<=n-1; i++) - { - if( state->hasts.ptr.p_bool[i] ) - { - rhs->tau.ptr.p_double[i] = rhs->tau.ptr.p_double[i]-(vdcandidate->x.ptr.p_double[i]+vdcandidate->t.ptr.p_double[i]-reg*vdcandidate->s.ptr.p_double[i]); - } - } - for(i=0; i<=m-1; i++) - { - if( state->haspq.ptr.p_bool[i] ) - { - rhs->alpha.ptr.p_double[i] = rhs->alpha.ptr.p_double[i]-(vdcandidate->w.ptr.p_double[i]+vdcandidate->p.ptr.p_double[i]-reg*vdcandidate->q.ptr.p_double[i]); - } - } - for(i=0; i<=n-1; i++) - { - if( !state->isfrozen.ptr.p_bool[i] ) - { - rhs->sigma.ptr.p_double[i] = rhs->sigma.ptr.p_double[i]-(state->tmpaty.ptr.p_double[i]-state->tmphx.ptr.p_double[i]-reg*vdcandidate->x.ptr.p_double[i]); - if( state->hasgz.ptr.p_bool[i] ) - { - rhs->sigma.ptr.p_double[i] = rhs->sigma.ptr.p_double[i]-vdcandidate->z.ptr.p_double[i]; - } - if( state->hasts.ptr.p_bool[i] ) - { - rhs->sigma.ptr.p_double[i] = rhs->sigma.ptr.p_double[i]+vdcandidate->s.ptr.p_double[i]; - } - } - } - for(i=0; i<=m-1; i++) - { - if( state->haswv.ptr.p_bool[i] ) - { - rhs->beta.ptr.p_double[i] = rhs->beta.ptr.p_double[i]-(-vdcandidate->y.ptr.p_double[i]+vdcandidate->v.ptr.p_double[i]-reg*vdcandidate->w.ptr.p_double[i]); - } - if( state->haspq.ptr.p_bool[i] ) - { - rhs->beta.ptr.p_double[i] = rhs->beta.ptr.p_double[i]+vdcandidate->q.ptr.p_double[i]; - } - } - - /* - * Residual for GammaZ, GammaW, GammaS, GammaQ - */ - for(i=0; i<=n-1; i++) - { - if( state->hasgz.ptr.p_bool[i] ) - { - rhs->gammaz.ptr.p_double[i] = rhs->gammaz.ptr.p_double[i]-(v0->z.ptr.p_double[i]/v0->g.ptr.p_double[i]*vdcandidate->g.ptr.p_double[i]+vdcandidate->z.ptr.p_double[i]); - } - } - for(i=0; i<=m-1; i++) - { - if( state->haswv.ptr.p_bool[i] ) - { - rhs->gammaw.ptr.p_double[i] = rhs->gammaw.ptr.p_double[i]-(v0->w.ptr.p_double[i]/v0->v.ptr.p_double[i]*vdcandidate->v.ptr.p_double[i]+vdcandidate->w.ptr.p_double[i]); - } - } - for(i=0; i<=n-1; i++) - { - if( state->hasts.ptr.p_bool[i] ) - { - rhs->gammas.ptr.p_double[i] = rhs->gammas.ptr.p_double[i]-(v0->s.ptr.p_double[i]/v0->t.ptr.p_double[i]*vdcandidate->t.ptr.p_double[i]+vdcandidate->s.ptr.p_double[i]); - } - } - for(i=0; i<=m-1; i++) - { - if( state->haspq.ptr.p_bool[i] ) - { - rhs->gammaq.ptr.p_double[i] = rhs->gammaq.ptr.p_double[i]-(v0->q.ptr.p_double[i]/v0->p.ptr.p_double[i]*vdcandidate->p.ptr.p_double[i]+vdcandidate->q.ptr.p_double[i]); - } - } -} - - -/************************************************************************* -Computes sum of squared primal terms of RHS - -INPUT PARAMETERS: - Rhs - RHS structure - N, M - problem metrics - -RESULT: - sum(sqr()) computed over primal terms (Rho, Nu, Tau, Alpha) - - -- ALGLIB -- - Copyright 01.11.2020 by Bochkanov Sergey -*************************************************************************/ -static double vipmsolver_rhsprimal2(vipmrighthandside* rhs, - ae_int_t n, - ae_int_t m, - ae_state *_state) -{ - double result; - - - result = (double)(0); - result = result+rdotv2(m, &rhs->rho, _state); - result = result+rdotv2(n, &rhs->nu, _state); - result = result+rdotv2(n, &rhs->tau, _state); - result = result+rdotv2(m, &rhs->alpha, _state); - return result; -} - - -/************************************************************************* -Computes sum of squared dual terms of RHS - -INPUT PARAMETERS: - Rhs - RHS structure - N, M - problem metrics - -RESULT: - sum(sqr()) computed over dual terms (Sigma, Beta) - - -- ALGLIB -- - Copyright 01.11.2020 by Bochkanov Sergey -*************************************************************************/ -static double vipmsolver_rhsdual2(vipmrighthandside* rhs, - ae_int_t n, - ae_int_t m, - ae_state *_state) -{ - double result; - - - result = (double)(0); - result = result+rdotv2(n, &rhs->sigma, _state); - result = result+rdotv2(m, &rhs->beta, _state); - return result; -} - - -/************************************************************************* -Computes inf-norm of primal terms of RHS - -INPUT PARAMETERS: - Rhs - RHS structure - N, M - problem metrics - -RESULT: - max(abs()) computed over primal terms (Rho, Nu, Tau, Alpha) - - -- ALGLIB -- - Copyright 01.11.2020 by Bochkanov Sergey -*************************************************************************/ -static double vipmsolver_rhsprimalinf(vipmrighthandside* rhs, - ae_int_t n, - ae_int_t m, - ae_state *_state) -{ - double result; - - - result = (double)(0); - result = ae_maxreal(result, rmaxabsv(m, &rhs->rho, _state), _state); - result = ae_maxreal(result, rmaxabsv(n, &rhs->nu, _state), _state); - result = ae_maxreal(result, rmaxabsv(n, &rhs->tau, _state), _state); - result = ae_maxreal(result, rmaxabsv(m, &rhs->alpha, _state), _state); - return result; -} - - -/************************************************************************* -Computes inf-norm of dual terms of RHS - -INPUT PARAMETERS: - Rhs - RHS structure - N, M - problem metrics - -RESULT: - max(abs()) computed over dual terms (Sigma, Beta) - - -- ALGLIB -- - Copyright 01.11.2020 by Bochkanov Sergey -*************************************************************************/ -static double vipmsolver_rhsdualinf(vipmrighthandside* rhs, - ae_int_t n, - ae_int_t m, - ae_state *_state) -{ - double result; - - - result = (double)(0); - result = ae_maxreal(result, rmaxabsv(n, &rhs->sigma, _state), _state); - result = ae_maxreal(result, rmaxabsv(m, &rhs->beta, _state), _state); - return result; -} - - -/************************************************************************* -Computes maximum over complementarity slackness terms of RHS - -INPUT PARAMETERS: - Rhs - RHS structure - N, M - problem metrics - -RESULT: - max(abs()) computed over complementarity terms (GammaZ, GammaS, GammaW, GammaQ) - - -- ALGLIB -- - Copyright 01.11.2020 by Bochkanov Sergey -*************************************************************************/ -static double vipmsolver_rhscompl2(vipmrighthandside* rhs, - ae_int_t n, - ae_int_t m, - ae_state *_state) -{ - double result; - - - result = (double)(0); - result = result+rdotv2(n, &rhs->gammaz, _state); - result = result+rdotv2(n, &rhs->gammas, _state); - result = result+rdotv2(m, &rhs->gammaw, _state); - result = result+rdotv2(m, &rhs->gammaq, _state); - return result; -} - - -/************************************************************************* -Computes minimum nonzero value of the vector. Returns 0 if all components -are nonpositive. - -INPUT PARAMETERS: - X - vector - N - length - - -- ALGLIB -- - Copyright 01.11.2020 by Bochkanov Sergey -*************************************************************************/ -static double vipmsolver_minnz(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_bool nz; - double result; - - - result = (double)(0); - nz = ae_false; - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(x->ptr.p_double[i],(double)(0)) ) - { - if( !nz ) - { - result = x->ptr.p_double[i]; - nz = ae_true; - } - else - { - result = ae_minreal(result, x->ptr.p_double[i], _state); - } - } - } - return result; -} - - -/************************************************************************* -Computes minimum product of nonzero components. -Returns 0 if all components are nonpositive. - -INPUT PARAMETERS: - X - vector - Y - vector - N - length - - -- ALGLIB -- - Copyright 01.11.2020 by Bochkanov Sergey -*************************************************************************/ -static double vipmsolver_minprodnz(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_bool nz; - double result; - - - result = (double)(0); - nz = ae_false; - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(x->ptr.p_double[i],(double)(0))&&ae_fp_greater(y->ptr.p_double[i],(double)(0)) ) - { - if( !nz ) - { - result = x->ptr.p_double[i]*y->ptr.p_double[i]; - nz = ae_true; - } - else - { - result = ae_minreal(result, x->ptr.p_double[i]*y->ptr.p_double[i], _state); - } - } - } - return result; -} - - -/************************************************************************* -Computes maximum product of nonzero components. -Returns 0 if all components are nonpositive. - -INPUT PARAMETERS: - X - vector - Y - vector - N - length - - -- ALGLIB -- - Copyright 01.11.2020 by Bochkanov Sergey -*************************************************************************/ -static double vipmsolver_maxprodnz(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_bool nz; - double result; - - - result = (double)(0); - nz = ae_false; - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(x->ptr.p_double[i],(double)(0))&&ae_fp_greater(y->ptr.p_double[i],(double)(0)) ) - { - if( !nz ) - { - result = x->ptr.p_double[i]*y->ptr.p_double[i]; - nz = ae_true; - } - else - { - result = ae_maxreal(result, x->ptr.p_double[i]*y->ptr.p_double[i], _state); - } - } - } - return result; -} - - -void _vipmvars_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - vipmvars *p = (vipmvars*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->w, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->t, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->p, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->z, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->v, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->q, 0, DT_REAL, _state, make_automatic); -} - - -void _vipmvars_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - vipmvars *dst = (vipmvars*)_dst; - vipmvars *src = (vipmvars*)_src; - dst->n = src->n; - dst->m = src->m; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic); - ae_vector_init_copy(&dst->w, &src->w, _state, make_automatic); - ae_vector_init_copy(&dst->t, &src->t, _state, make_automatic); - ae_vector_init_copy(&dst->p, &src->p, _state, make_automatic); - ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic); - ae_vector_init_copy(&dst->z, &src->z, _state, make_automatic); - ae_vector_init_copy(&dst->v, &src->v, _state, make_automatic); - ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic); - ae_vector_init_copy(&dst->q, &src->q, _state, make_automatic); -} - - -void _vipmvars_clear(void* _p) -{ - vipmvars *p = (vipmvars*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->x); - ae_vector_clear(&p->g); - ae_vector_clear(&p->w); - ae_vector_clear(&p->t); - ae_vector_clear(&p->p); - ae_vector_clear(&p->y); - ae_vector_clear(&p->z); - ae_vector_clear(&p->v); - ae_vector_clear(&p->s); - ae_vector_clear(&p->q); -} - - -void _vipmvars_destroy(void* _p) -{ - vipmvars *p = (vipmvars*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->g); - ae_vector_destroy(&p->w); - ae_vector_destroy(&p->t); - ae_vector_destroy(&p->p); - ae_vector_destroy(&p->y); - ae_vector_destroy(&p->z); - ae_vector_destroy(&p->v); - ae_vector_destroy(&p->s); - ae_vector_destroy(&p->q); -} - - -void _vipmrighthandside_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - vipmrighthandside *p = (vipmrighthandside*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->sigma, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->beta, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rho, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->nu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tau, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->alpha, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->gammaz, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->gammas, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->gammaw, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->gammaq, 0, DT_REAL, _state, make_automatic); -} - - -void _vipmrighthandside_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - vipmrighthandside *dst = (vipmrighthandside*)_dst; - vipmrighthandside *src = (vipmrighthandside*)_src; - ae_vector_init_copy(&dst->sigma, &src->sigma, _state, make_automatic); - ae_vector_init_copy(&dst->beta, &src->beta, _state, make_automatic); - ae_vector_init_copy(&dst->rho, &src->rho, _state, make_automatic); - ae_vector_init_copy(&dst->nu, &src->nu, _state, make_automatic); - ae_vector_init_copy(&dst->tau, &src->tau, _state, make_automatic); - ae_vector_init_copy(&dst->alpha, &src->alpha, _state, make_automatic); - ae_vector_init_copy(&dst->gammaz, &src->gammaz, _state, make_automatic); - ae_vector_init_copy(&dst->gammas, &src->gammas, _state, make_automatic); - ae_vector_init_copy(&dst->gammaw, &src->gammaw, _state, make_automatic); - ae_vector_init_copy(&dst->gammaq, &src->gammaq, _state, make_automatic); -} - - -void _vipmrighthandside_clear(void* _p) -{ - vipmrighthandside *p = (vipmrighthandside*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->sigma); - ae_vector_clear(&p->beta); - ae_vector_clear(&p->rho); - ae_vector_clear(&p->nu); - ae_vector_clear(&p->tau); - ae_vector_clear(&p->alpha); - ae_vector_clear(&p->gammaz); - ae_vector_clear(&p->gammas); - ae_vector_clear(&p->gammaw); - ae_vector_clear(&p->gammaq); -} - - -void _vipmrighthandside_destroy(void* _p) -{ - vipmrighthandside *p = (vipmrighthandside*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->sigma); - ae_vector_destroy(&p->beta); - ae_vector_destroy(&p->rho); - ae_vector_destroy(&p->nu); - ae_vector_destroy(&p->tau); - ae_vector_destroy(&p->alpha); - ae_vector_destroy(&p->gammaz); - ae_vector_destroy(&p->gammas); - ae_vector_destroy(&p->gammaw); - ae_vector_destroy(&p->gammaq); -} - - -void _vipmstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - vipmstate *p = (vipmstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->scl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->invscl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xorigin, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->c, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->denseh, 0, 0, DT_REAL, _state, make_automatic); - _sparsematrix_init(&p->sparseh, _state, make_automatic); - ae_vector_init(&p->diagr, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rawbndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rawbndu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->hasbndl, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->hasbndu, 0, DT_BOOL, _state, make_automatic); - ae_matrix_init(&p->denseafull, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->denseamain, 0, 0, DT_REAL, _state, make_automatic); - _sparsematrix_init(&p->sparseafull, _state, make_automatic); - _sparsematrix_init(&p->sparseamain, _state, make_automatic); - _sparsematrix_init(&p->combinedaslack, _state, make_automatic); - ae_vector_init(&p->ascales, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->aflips, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->b, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->r, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->hasr, 0, DT_BOOL, _state, make_automatic); - _vipmvars_init(&p->x0, _state, make_automatic); - _vipmvars_init(&p->current, _state, make_automatic); - _vipmvars_init(&p->best, _state, make_automatic); - _vipmvars_init(&p->trial, _state, make_automatic); - _vipmvars_init(&p->deltaaff, _state, make_automatic); - _vipmvars_init(&p->deltacorr, _state, make_automatic); - ae_vector_init(&p->isfrozen, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->hasgz, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->hasts, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->haswv, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->haspq, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->diagdz, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->diagdzi, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->diagdziri, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->diagds, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->diagdsi, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->diagdsiri, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->diagdw, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->diagdwi, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->diagdwir, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->diagdq, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->diagdqi, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->diagdqiri, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->diagddr, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->diagde, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->diagder, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->factdensehaug, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->factregdhrh, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->factinvregdzrz, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->factregewave, 0, DT_REAL, _state, make_automatic); - _sparsematrix_init(&p->factsparsekkttmpl, _state, make_automatic); - _sparsematrix_init(&p->factsparsekkt, _state, make_automatic); - ae_vector_init(&p->factsparsekktpivp, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->facttmpdiag, 0, DT_REAL, _state, make_automatic); - _spcholanalysis_init(&p->ldltanalysis, _state, make_automatic); - ae_vector_init(&p->factsparsediagd, 0, DT_REAL, _state, make_automatic); - _vipmrighthandside_init(&p->rhs, _state, make_automatic); - ae_vector_init(&p->rhsalphacap, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rhsbetacap, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rhsnucap, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rhstaucap, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->deltaxy, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmphx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpax, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpaty, 0, DT_REAL, _state, make_automatic); - _vipmvars_init(&p->zerovars, _state, make_automatic); - ae_vector_init(&p->dummyr, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpy, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp2, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->tmpr2, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmplaggrad, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpi, 0, DT_INT, _state, make_automatic); - _sparsematrix_init(&p->tmpsparse0, _state, make_automatic); -} - - -void _vipmstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - vipmstate *dst = (vipmstate*)_dst; - vipmstate *src = (vipmstate*)_src; - dst->slacksforequalityconstraints = src->slacksforequalityconstraints; - dst->n = src->n; - dst->nmain = src->nmain; - dst->epsp = src->epsp; - dst->epsd = src->epsd; - dst->epsgap = src->epsgap; - dst->islinear = src->islinear; - ae_vector_init_copy(&dst->scl, &src->scl, _state, make_automatic); - ae_vector_init_copy(&dst->invscl, &src->invscl, _state, make_automatic); - ae_vector_init_copy(&dst->xorigin, &src->xorigin, _state, make_automatic); - dst->targetscale = src->targetscale; - ae_vector_init_copy(&dst->c, &src->c, _state, make_automatic); - ae_matrix_init_copy(&dst->denseh, &src->denseh, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparseh, &src->sparseh, _state, make_automatic); - ae_vector_init_copy(&dst->diagr, &src->diagr, _state, make_automatic); - dst->hkind = src->hkind; - ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic); - ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic); - ae_vector_init_copy(&dst->rawbndl, &src->rawbndl, _state, make_automatic); - ae_vector_init_copy(&dst->rawbndu, &src->rawbndu, _state, make_automatic); - ae_vector_init_copy(&dst->hasbndl, &src->hasbndl, _state, make_automatic); - ae_vector_init_copy(&dst->hasbndu, &src->hasbndu, _state, make_automatic); - ae_matrix_init_copy(&dst->denseafull, &src->denseafull, _state, make_automatic); - ae_matrix_init_copy(&dst->denseamain, &src->denseamain, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparseafull, &src->sparseafull, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparseamain, &src->sparseamain, _state, make_automatic); - _sparsematrix_init_copy(&dst->combinedaslack, &src->combinedaslack, _state, make_automatic); - ae_vector_init_copy(&dst->ascales, &src->ascales, _state, make_automatic); - ae_vector_init_copy(&dst->aflips, &src->aflips, _state, make_automatic); - ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic); - ae_vector_init_copy(&dst->r, &src->r, _state, make_automatic); - ae_vector_init_copy(&dst->hasr, &src->hasr, _state, make_automatic); - dst->mdense = src->mdense; - dst->msparse = src->msparse; - _vipmvars_init_copy(&dst->x0, &src->x0, _state, make_automatic); - _vipmvars_init_copy(&dst->current, &src->current, _state, make_automatic); - _vipmvars_init_copy(&dst->best, &src->best, _state, make_automatic); - _vipmvars_init_copy(&dst->trial, &src->trial, _state, make_automatic); - _vipmvars_init_copy(&dst->deltaaff, &src->deltaaff, _state, make_automatic); - _vipmvars_init_copy(&dst->deltacorr, &src->deltacorr, _state, make_automatic); - ae_vector_init_copy(&dst->isfrozen, &src->isfrozen, _state, make_automatic); - ae_vector_init_copy(&dst->hasgz, &src->hasgz, _state, make_automatic); - ae_vector_init_copy(&dst->hasts, &src->hasts, _state, make_automatic); - ae_vector_init_copy(&dst->haswv, &src->haswv, _state, make_automatic); - ae_vector_init_copy(&dst->haspq, &src->haspq, _state, make_automatic); - dst->repiterationscount = src->repiterationscount; - dst->repncholesky = src->repncholesky; - dst->dotrace = src->dotrace; - dst->dodetailedtrace = src->dodetailedtrace; - dst->factorizationtype = src->factorizationtype; - dst->factorizationpoweredup = src->factorizationpoweredup; - dst->factorizationpresent = src->factorizationpresent; - ae_vector_init_copy(&dst->diagdz, &src->diagdz, _state, make_automatic); - ae_vector_init_copy(&dst->diagdzi, &src->diagdzi, _state, make_automatic); - ae_vector_init_copy(&dst->diagdziri, &src->diagdziri, _state, make_automatic); - ae_vector_init_copy(&dst->diagds, &src->diagds, _state, make_automatic); - ae_vector_init_copy(&dst->diagdsi, &src->diagdsi, _state, make_automatic); - ae_vector_init_copy(&dst->diagdsiri, &src->diagdsiri, _state, make_automatic); - ae_vector_init_copy(&dst->diagdw, &src->diagdw, _state, make_automatic); - ae_vector_init_copy(&dst->diagdwi, &src->diagdwi, _state, make_automatic); - ae_vector_init_copy(&dst->diagdwir, &src->diagdwir, _state, make_automatic); - ae_vector_init_copy(&dst->diagdq, &src->diagdq, _state, make_automatic); - ae_vector_init_copy(&dst->diagdqi, &src->diagdqi, _state, make_automatic); - ae_vector_init_copy(&dst->diagdqiri, &src->diagdqiri, _state, make_automatic); - ae_vector_init_copy(&dst->diagddr, &src->diagddr, _state, make_automatic); - ae_vector_init_copy(&dst->diagde, &src->diagde, _state, make_automatic); - ae_vector_init_copy(&dst->diagder, &src->diagder, _state, make_automatic); - ae_matrix_init_copy(&dst->factdensehaug, &src->factdensehaug, _state, make_automatic); - ae_vector_init_copy(&dst->factregdhrh, &src->factregdhrh, _state, make_automatic); - ae_vector_init_copy(&dst->factinvregdzrz, &src->factinvregdzrz, _state, make_automatic); - ae_vector_init_copy(&dst->factregewave, &src->factregewave, _state, make_automatic); - _sparsematrix_init_copy(&dst->factsparsekkttmpl, &src->factsparsekkttmpl, _state, make_automatic); - _sparsematrix_init_copy(&dst->factsparsekkt, &src->factsparsekkt, _state, make_automatic); - ae_vector_init_copy(&dst->factsparsekktpivp, &src->factsparsekktpivp, _state, make_automatic); - ae_vector_init_copy(&dst->facttmpdiag, &src->facttmpdiag, _state, make_automatic); - _spcholanalysis_init_copy(&dst->ldltanalysis, &src->ldltanalysis, _state, make_automatic); - ae_vector_init_copy(&dst->factsparsediagd, &src->factsparsediagd, _state, make_automatic); - _vipmrighthandside_init_copy(&dst->rhs, &src->rhs, _state, make_automatic); - ae_vector_init_copy(&dst->rhsalphacap, &src->rhsalphacap, _state, make_automatic); - ae_vector_init_copy(&dst->rhsbetacap, &src->rhsbetacap, _state, make_automatic); - ae_vector_init_copy(&dst->rhsnucap, &src->rhsnucap, _state, make_automatic); - ae_vector_init_copy(&dst->rhstaucap, &src->rhstaucap, _state, make_automatic); - ae_vector_init_copy(&dst->deltaxy, &src->deltaxy, _state, make_automatic); - ae_vector_init_copy(&dst->tmphx, &src->tmphx, _state, make_automatic); - ae_vector_init_copy(&dst->tmpax, &src->tmpax, _state, make_automatic); - ae_vector_init_copy(&dst->tmpaty, &src->tmpaty, _state, make_automatic); - _vipmvars_init_copy(&dst->zerovars, &src->zerovars, _state, make_automatic); - ae_vector_init_copy(&dst->dummyr, &src->dummyr, _state, make_automatic); - ae_vector_init_copy(&dst->tmpy, &src->tmpy, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic); - ae_vector_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic); - ae_matrix_init_copy(&dst->tmpr2, &src->tmpr2, _state, make_automatic); - ae_vector_init_copy(&dst->tmplaggrad, &src->tmplaggrad, _state, make_automatic); - ae_vector_init_copy(&dst->tmpi, &src->tmpi, _state, make_automatic); - _sparsematrix_init_copy(&dst->tmpsparse0, &src->tmpsparse0, _state, make_automatic); -} - - -void _vipmstate_clear(void* _p) -{ - vipmstate *p = (vipmstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->scl); - ae_vector_clear(&p->invscl); - ae_vector_clear(&p->xorigin); - ae_vector_clear(&p->c); - ae_matrix_clear(&p->denseh); - _sparsematrix_clear(&p->sparseh); - ae_vector_clear(&p->diagr); - ae_vector_clear(&p->bndl); - ae_vector_clear(&p->bndu); - ae_vector_clear(&p->rawbndl); - ae_vector_clear(&p->rawbndu); - ae_vector_clear(&p->hasbndl); - ae_vector_clear(&p->hasbndu); - ae_matrix_clear(&p->denseafull); - ae_matrix_clear(&p->denseamain); - _sparsematrix_clear(&p->sparseafull); - _sparsematrix_clear(&p->sparseamain); - _sparsematrix_clear(&p->combinedaslack); - ae_vector_clear(&p->ascales); - ae_vector_clear(&p->aflips); - ae_vector_clear(&p->b); - ae_vector_clear(&p->r); - ae_vector_clear(&p->hasr); - _vipmvars_clear(&p->x0); - _vipmvars_clear(&p->current); - _vipmvars_clear(&p->best); - _vipmvars_clear(&p->trial); - _vipmvars_clear(&p->deltaaff); - _vipmvars_clear(&p->deltacorr); - ae_vector_clear(&p->isfrozen); - ae_vector_clear(&p->hasgz); - ae_vector_clear(&p->hasts); - ae_vector_clear(&p->haswv); - ae_vector_clear(&p->haspq); - ae_vector_clear(&p->diagdz); - ae_vector_clear(&p->diagdzi); - ae_vector_clear(&p->diagdziri); - ae_vector_clear(&p->diagds); - ae_vector_clear(&p->diagdsi); - ae_vector_clear(&p->diagdsiri); - ae_vector_clear(&p->diagdw); - ae_vector_clear(&p->diagdwi); - ae_vector_clear(&p->diagdwir); - ae_vector_clear(&p->diagdq); - ae_vector_clear(&p->diagdqi); - ae_vector_clear(&p->diagdqiri); - ae_vector_clear(&p->diagddr); - ae_vector_clear(&p->diagde); - ae_vector_clear(&p->diagder); - ae_matrix_clear(&p->factdensehaug); - ae_vector_clear(&p->factregdhrh); - ae_vector_clear(&p->factinvregdzrz); - ae_vector_clear(&p->factregewave); - _sparsematrix_clear(&p->factsparsekkttmpl); - _sparsematrix_clear(&p->factsparsekkt); - ae_vector_clear(&p->factsparsekktpivp); - ae_vector_clear(&p->facttmpdiag); - _spcholanalysis_clear(&p->ldltanalysis); - ae_vector_clear(&p->factsparsediagd); - _vipmrighthandside_clear(&p->rhs); - ae_vector_clear(&p->rhsalphacap); - ae_vector_clear(&p->rhsbetacap); - ae_vector_clear(&p->rhsnucap); - ae_vector_clear(&p->rhstaucap); - ae_vector_clear(&p->deltaxy); - ae_vector_clear(&p->tmphx); - ae_vector_clear(&p->tmpax); - ae_vector_clear(&p->tmpaty); - _vipmvars_clear(&p->zerovars); - ae_vector_clear(&p->dummyr); - ae_vector_clear(&p->tmpy); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->tmp1); - ae_vector_clear(&p->tmp2); - ae_matrix_clear(&p->tmpr2); - ae_vector_clear(&p->tmplaggrad); - ae_vector_clear(&p->tmpi); - _sparsematrix_clear(&p->tmpsparse0); -} - - -void _vipmstate_destroy(void* _p) -{ - vipmstate *p = (vipmstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->scl); - ae_vector_destroy(&p->invscl); - ae_vector_destroy(&p->xorigin); - ae_vector_destroy(&p->c); - ae_matrix_destroy(&p->denseh); - _sparsematrix_destroy(&p->sparseh); - ae_vector_destroy(&p->diagr); - ae_vector_destroy(&p->bndl); - ae_vector_destroy(&p->bndu); - ae_vector_destroy(&p->rawbndl); - ae_vector_destroy(&p->rawbndu); - ae_vector_destroy(&p->hasbndl); - ae_vector_destroy(&p->hasbndu); - ae_matrix_destroy(&p->denseafull); - ae_matrix_destroy(&p->denseamain); - _sparsematrix_destroy(&p->sparseafull); - _sparsematrix_destroy(&p->sparseamain); - _sparsematrix_destroy(&p->combinedaslack); - ae_vector_destroy(&p->ascales); - ae_vector_destroy(&p->aflips); - ae_vector_destroy(&p->b); - ae_vector_destroy(&p->r); - ae_vector_destroy(&p->hasr); - _vipmvars_destroy(&p->x0); - _vipmvars_destroy(&p->current); - _vipmvars_destroy(&p->best); - _vipmvars_destroy(&p->trial); - _vipmvars_destroy(&p->deltaaff); - _vipmvars_destroy(&p->deltacorr); - ae_vector_destroy(&p->isfrozen); - ae_vector_destroy(&p->hasgz); - ae_vector_destroy(&p->hasts); - ae_vector_destroy(&p->haswv); - ae_vector_destroy(&p->haspq); - ae_vector_destroy(&p->diagdz); - ae_vector_destroy(&p->diagdzi); - ae_vector_destroy(&p->diagdziri); - ae_vector_destroy(&p->diagds); - ae_vector_destroy(&p->diagdsi); - ae_vector_destroy(&p->diagdsiri); - ae_vector_destroy(&p->diagdw); - ae_vector_destroy(&p->diagdwi); - ae_vector_destroy(&p->diagdwir); - ae_vector_destroy(&p->diagdq); - ae_vector_destroy(&p->diagdqi); - ae_vector_destroy(&p->diagdqiri); - ae_vector_destroy(&p->diagddr); - ae_vector_destroy(&p->diagde); - ae_vector_destroy(&p->diagder); - ae_matrix_destroy(&p->factdensehaug); - ae_vector_destroy(&p->factregdhrh); - ae_vector_destroy(&p->factinvregdzrz); - ae_vector_destroy(&p->factregewave); - _sparsematrix_destroy(&p->factsparsekkttmpl); - _sparsematrix_destroy(&p->factsparsekkt); - ae_vector_destroy(&p->factsparsekktpivp); - ae_vector_destroy(&p->facttmpdiag); - _spcholanalysis_destroy(&p->ldltanalysis); - ae_vector_destroy(&p->factsparsediagd); - _vipmrighthandside_destroy(&p->rhs); - ae_vector_destroy(&p->rhsalphacap); - ae_vector_destroy(&p->rhsbetacap); - ae_vector_destroy(&p->rhsnucap); - ae_vector_destroy(&p->rhstaucap); - ae_vector_destroy(&p->deltaxy); - ae_vector_destroy(&p->tmphx); - ae_vector_destroy(&p->tmpax); - ae_vector_destroy(&p->tmpaty); - _vipmvars_destroy(&p->zerovars); - ae_vector_destroy(&p->dummyr); - ae_vector_destroy(&p->tmpy); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->tmp1); - ae_vector_destroy(&p->tmp2); - ae_matrix_destroy(&p->tmpr2); - ae_vector_destroy(&p->tmplaggrad); - ae_vector_destroy(&p->tmpi); - _sparsematrix_destroy(&p->tmpsparse0); -} - - -#endif -#if defined(AE_COMPILE_NLCSQP) || !defined(AE_PARTIAL_BUILD) - - -void minsqpinitbuf(/* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_vector* s, - /* Real */ ae_vector* x0, - ae_int_t n, - /* Real */ ae_matrix* cleic, - /* Integer */ ae_vector* lcsrcidx, - ae_int_t nec, - ae_int_t nic, - ae_int_t nlec, - ae_int_t nlic, - double epsx, - ae_int_t maxits, - minsqpstate* state, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - double vv; - - - state->n = n; - state->nec = nec; - state->nic = nic; - state->nlec = nlec; - state->nlic = nlic; - - /* - * Prepare RCOMM state - */ - ae_vector_set_length(&state->rstate.ia, 9+1, _state); - ae_vector_set_length(&state->rstate.ba, 3+1, _state); - ae_vector_set_length(&state->rstate.ra, 6+1, _state); - state->rstate.stage = -1; - state->needfij = ae_false; - state->xupdated = ae_false; - ae_vector_set_length(&state->x, n, _state); - ae_vector_set_length(&state->fi, 1+nlec+nlic, _state); - ae_matrix_set_length(&state->j, 1+nlec+nlic, n, _state); - - /* - * Allocate memory. - */ - rvectorsetlengthatleast(&state->s, n, _state); - rvectorsetlengthatleast(&state->step0x, n, _state); - rvectorsetlengthatleast(&state->stepkx, n, _state); - rvectorsetlengthatleast(&state->backupx, n, _state); - rvectorsetlengthatleast(&state->step0fi, 1+nlec+nlic, _state); - rvectorsetlengthatleast(&state->stepkfi, 1+nlec+nlic, _state); - rvectorsetlengthatleast(&state->backupfi, 1+nlec+nlic, _state); - rmatrixsetlengthatleast(&state->step0j, 1+nlec+nlic, n, _state); - rmatrixsetlengthatleast(&state->stepkj, 1+nlec+nlic, n, _state); - rvectorsetlengthatleast(&state->fscales, 1+nlec+nlic, _state); - rvectorsetlengthatleast(&state->tracegamma, 1+nlec+nlic, _state); - rvectorsetlengthatleast(&state->dummylagmult, nec+nic+nlec+nlic, _state); - bvectorsetlengthatleast(&state->hasbndl, n, _state); - bvectorsetlengthatleast(&state->hasbndu, n, _state); - rvectorsetlengthatleast(&state->scaledbndl, n, _state); - rvectorsetlengthatleast(&state->scaledbndu, n, _state); - rmatrixsetlengthatleast(&state->scaledcleic, nec+nic, n+1, _state); - ivectorsetlengthatleast(&state->lcsrcidx, nec+nic, _state); - rallocv(nec+nic+nlec+nlic, &state->meritlagmult, _state); - rsetallocm(nlcsqp_penaltymemlen, nec+nic+nlec+nlic, 0.0, &state->abslagmemory, _state); - - /* - * Prepare scaled problem - */ - for(i=0; i<=n-1; i++) - { - state->hasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state); - state->hasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state); - if( state->hasbndl.ptr.p_bool[i] ) - { - state->scaledbndl.ptr.p_double[i] = bndl->ptr.p_double[i]/s->ptr.p_double[i]; - } - if( state->hasbndu.ptr.p_bool[i] ) - { - state->scaledbndu.ptr.p_double[i] = bndu->ptr.p_double[i]/s->ptr.p_double[i]; - } - if( state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i] ) - { - ae_assert(ae_fp_less_eq(bndl->ptr.p_double[i],bndu->ptr.p_double[i]), "SQP: integrity check failed, box constraints are inconsistent", _state); - } - state->step0x.ptr.p_double[i] = x0->ptr.p_double[i]/s->ptr.p_double[i]; - state->s.ptr.p_double[i] = s->ptr.p_double[i]; - } - for(i=0; i<=nec+nic-1; i++) - { - - /* - * Permutation - */ - state->lcsrcidx.ptr.p_int[i] = lcsrcidx->ptr.p_int[i]; - - /* - * Scale and normalize linear constraints - */ - vv = 0.0; - for(j=0; j<=n-1; j++) - { - v = cleic->ptr.pp_double[i][j]*s->ptr.p_double[j]; - state->scaledcleic.ptr.pp_double[i][j] = v; - vv = vv+v*v; - } - vv = ae_sqrt(vv, _state); - state->scaledcleic.ptr.pp_double[i][n] = cleic->ptr.pp_double[i][n]; - if( ae_fp_greater(vv,(double)(0)) ) - { - for(j=0; j<=n; j++) - { - state->scaledcleic.ptr.pp_double[i][j] = state->scaledcleic.ptr.pp_double[i][j]/vv; - } - } - } - - /* - * Initial enforcement of box constraints - */ - for(i=0; i<=n-1; i++) - { - if( state->hasbndl.ptr.p_bool[i] ) - { - state->step0x.ptr.p_double[i] = ae_maxreal(state->step0x.ptr.p_double[i], state->scaledbndl.ptr.p_double[i], _state); - } - if( state->hasbndu.ptr.p_bool[i] ) - { - state->step0x.ptr.p_double[i] = ae_minreal(state->step0x.ptr.p_double[i], state->scaledbndu.ptr.p_double[i], _state); - } - } - - /* - * Stopping criteria - */ - state->epsx = epsx; - state->maxits = maxits; - - /* - * Report fields - */ - state->repsimplexiterations = 0; - state->repsimplexiterations1 = 0; - state->repsimplexiterations2 = 0; - state->repsimplexiterations3 = 0; - state->repterminationtype = 0; - state->repbcerr = (double)(0); - state->repbcidx = -1; - state->replcerr = (double)(0); - state->replcidx = -1; - state->repnlcerr = (double)(0); - state->repnlcidx = -1; - state->repiterationscount = 0; - - /* - * Integrity checks - */ - ae_assert(ae_fp_less(nlcsqp_sqpdeltadecrease,nlcsqp_sqpdeltaincrease), "MinSQP: integrity check failed", _state); -} - - -/************************************************************************* -This function performs actual processing for SQP algorithm. It expects -that caller redirects its reverse communication requests NeedFiJ/XUpdated -to external user who will provide analytic derivative (or handle reports -about progress). - -In case external user does not have analytic derivative, it is responsibility -of caller to intercept NeedFiJ request and replace it with appropriate -numerical differentiation scheme. - -Results are stored: -* point - in State.StepKX - -IMPORTANT: this function works with scaled problem formulation; it is - responsibility of the caller to unscale request and scale - Jacobian. - -NOTE: SMonitor is expected to be correctly initialized smoothness monitor. - - -- ALGLIB -- - Copyright 05.03.2018 by Bochkanov Sergey -*************************************************************************/ -ae_bool minsqpiteration(minsqpstate* state, - smoothnessmonitor* smonitor, - ae_bool userterminationneeded, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nslack; - ae_int_t nec; - ae_int_t nic; - ae_int_t nlec; - ae_int_t nlic; - ae_int_t i; - ae_int_t j; - double v; - double vv; - double mx; - ae_int_t status; - double deltamax; - double multiplyby; - double setscaleto; - double prevtrustrad; - ae_int_t subiterationidx; - ae_bool trustradstagnated; - ae_bool dotrace; - ae_bool dodetailedtrace; - ae_bool increasebigc; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - n = state->rstate.ia.ptr.p_int[0]; - nslack = state->rstate.ia.ptr.p_int[1]; - nec = state->rstate.ia.ptr.p_int[2]; - nic = state->rstate.ia.ptr.p_int[3]; - nlec = state->rstate.ia.ptr.p_int[4]; - nlic = state->rstate.ia.ptr.p_int[5]; - i = state->rstate.ia.ptr.p_int[6]; - j = state->rstate.ia.ptr.p_int[7]; - status = state->rstate.ia.ptr.p_int[8]; - subiterationidx = state->rstate.ia.ptr.p_int[9]; - trustradstagnated = state->rstate.ba.ptr.p_bool[0]; - dotrace = state->rstate.ba.ptr.p_bool[1]; - dodetailedtrace = state->rstate.ba.ptr.p_bool[2]; - increasebigc = state->rstate.ba.ptr.p_bool[3]; - v = state->rstate.ra.ptr.p_double[0]; - vv = state->rstate.ra.ptr.p_double[1]; - mx = state->rstate.ra.ptr.p_double[2]; - deltamax = state->rstate.ra.ptr.p_double[3]; - multiplyby = state->rstate.ra.ptr.p_double[4]; - setscaleto = state->rstate.ra.ptr.p_double[5]; - prevtrustrad = state->rstate.ra.ptr.p_double[6]; - } - else - { - n = 359; - nslack = -58; - nec = -919; - nic = -909; - nlec = 81; - nlic = 255; - i = 74; - j = -788; - status = 809; - subiterationidx = 205; - trustradstagnated = ae_false; - dotrace = ae_true; - dodetailedtrace = ae_false; - increasebigc = ae_true; - v = -541; - vv = -698; - mx = -900; - deltamax = -318; - multiplyby = -940; - setscaleto = 1016; - prevtrustrad = -229; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - if( state->rstate.stage==1 ) - { - goto lbl_1; - } - if( state->rstate.stage==2 ) - { - goto lbl_2; - } - - /* - * Routine body - */ - n = state->n; - nec = state->nec; - nic = state->nic; - nlec = state->nlec; - nlic = state->nlic; - nslack = n+2*(nec+nlec)+(nic+nlic); - dotrace = ae_is_trace_enabled("SQP"); - dodetailedtrace = dotrace&&ae_is_trace_enabled("SQP.DETAILED"); - - /* - * Prepare rcomm interface - */ - state->needfij = ae_false; - state->xupdated = ae_false; - - /* - * Initialize algorithm data: - * * Lagrangian and "Big C" estimates - * * trust region - * * initial function scales (vector of 1's) - * * current approximation of the Hessian matrix H (unit matrix) - * * initial linearized constraints - * * initial violation of linear/nonlinear constraints - */ - state->fstagnationcnt = 0; - state->trustradstagnationcnt = 0; - state->trustrad = nlcsqp_inittrustrad; - for(i=0; i<=nlec+nlic; i++) - { - state->fscales.ptr.p_double[i] = 1.0; - state->tracegamma.ptr.p_double[i] = 0.0; - } - state->haslagmult = ae_false; - - /* - * Avoid spurious warnings about possibly uninitialized vars - */ - status = 0; - - /* - * Evaluate function vector and Jacobian at Step0X, send first location report. - * Compute initial violation of constraints. - */ - nlcsqp_sqpsendx(state, &state->step0x, _state); - state->needfij = ae_true; - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - state->needfij = ae_false; - if( !nlcsqp_sqpretrievefij(state, &state->step0fi, &state->step0j, _state) ) - { - - /* - * Failed to retrieve function/Jaconian, infinities detected! - */ - for(i=0; i<=n-1; i++) - { - state->stepkx.ptr.p_double[i] = state->step0x.ptr.p_double[i]; - } - state->repterminationtype = -8; - result = ae_false; - return result; - } - nlcsqp_sqpcopystate(state, &state->step0x, &state->step0fi, &state->step0j, &state->stepkx, &state->stepkfi, &state->stepkj, _state); - nlcsqp_sqpsendx(state, &state->stepkx, _state); - state->f = state->stepkfi.ptr.p_double[0]*state->fscales.ptr.p_double[0]; - state->xupdated = ae_true; - state->rstate.stage = 1; - goto lbl_rcomm; -lbl_1: - state->xupdated = ae_false; - checklcviolation(&state->scaledcleic, &state->lcsrcidx, nec, nic, &state->stepkx, n, &state->replcerr, &state->replcidx, _state); - unscaleandchecknlcviolation(&state->stepkfi, &state->fscales, nlec, nlic, &state->repnlcerr, &state->repnlcidx, _state); - - /* - * Trace output (if needed) - */ - if( dotrace ) - { - ae_trace("\n\n"); - ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n"); - ae_trace("// SQP SOLVER STARTED //\n"); - ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n"); - } - - /* - * Perform outer (NLC) iterations - */ - state->bigc = (double)(500); - nlcsqp_initqpsubsolver(state, &state->subsolver, _state); -lbl_3: - if( ae_false ) - { - goto lbl_4; - } - - /* - * Before beginning new outer iteration: - * * renormalize target function and/or constraints, if some of them have too large magnitudes - * * save initial point for the outer iteration - */ - for(i=0; i<=nlec+nlic; i++) - { - - /* - * Determine (a) multiplicative coefficient applied to function value - * and Jacobian row, and (b) new value of the function scale. - */ - mx = (double)(0); - for(j=0; j<=n-1; j++) - { - mx = ae_maxreal(mx, ae_fabs(state->stepkj.ptr.pp_double[i][j], _state), _state); - } - multiplyby = 1.0; - setscaleto = state->fscales.ptr.p_double[i]; - if( ae_fp_greater_eq(mx,nlcsqp_sqpbigscale) ) - { - multiplyby = 1/mx; - setscaleto = state->fscales.ptr.p_double[i]*mx; - } - if( ae_fp_less_eq(mx,nlcsqp_sqpsmallscale)&&ae_fp_greater(state->fscales.ptr.p_double[i],1.0) ) - { - if( ae_fp_greater(state->fscales.ptr.p_double[i]*mx,(double)(1)) ) - { - multiplyby = 1/mx; - setscaleto = state->fscales.ptr.p_double[i]*mx; - } - else - { - multiplyby = state->fscales.ptr.p_double[i]; - setscaleto = 1.0; - } - } - if( ae_fp_neq(multiplyby,1.0) ) - { - - /* - * Function #I needs renormalization: - * * update function vector element and Jacobian matrix row - * * update FScales[] and TraceGamma[] arrays - */ - state->stepkfi.ptr.p_double[i] = state->stepkfi.ptr.p_double[i]*multiplyby; - for(j=0; j<=n-1; j++) - { - state->stepkj.ptr.pp_double[i][j] = state->stepkj.ptr.pp_double[i][j]*multiplyby; - } - state->fscales.ptr.p_double[i] = setscaleto; - state->tracegamma.ptr.p_double[i] = state->tracegamma.ptr.p_double[i]*multiplyby; - } - } - - /* - * Trace output (if needed) - */ - if( dotrace ) - { - ae_trace("\n=== OUTER ITERATION %5d STARTED ==================================================================\n", - (int)(state->repiterationscount)); - if( dodetailedtrace ) - { - ae_trace("> printing raw data (prior to applying variable and function scales)\n"); - ae_trace("X (raw) = "); - tracevectorunscaledunshiftedautoprec(&state->step0x, n, &state->s, ae_true, &state->s, ae_false, _state); - ae_trace("\n"); - ae_trace("> printing scaled data (after applying variable and function scales)\n"); - ae_trace("X (scaled) = "); - tracevectorautoprec(&state->step0x, 0, n, _state); - ae_trace("\n"); - ae_trace("FScales = "); - tracevectorautoprec(&state->fscales, 0, 1+nlec+nlic, _state); - ae_trace("\n"); - ae_trace("GammaScl = "); - tracevectorautoprec(&state->tracegamma, 0, 1+nlec+nlic, _state); - ae_trace("\n"); - ae_trace("Fi (scaled) = "); - tracevectorautoprec(&state->stepkfi, 0, 1+nlec+nlic, _state); - ae_trace("\n"); - ae_trace("|Ji| (scaled) = "); - tracerownrm1autoprec(&state->stepkj, 0, 1+nlec+nlic, 0, n, _state); - ae_trace("\n"); - } - mx = (double)(0); - for(i=1; i<=nlec; i++) - { - mx = ae_maxreal(mx, ae_fabs(state->stepkfi.ptr.p_double[i], _state), _state); - } - for(i=nlec+1; i<=nlec+nlic; i++) - { - mx = ae_maxreal(mx, state->stepkfi.ptr.p_double[i], _state); - } - ae_trace("trustRad = %0.3e\n", - (double)(state->trustrad)); - ae_trace("lin.violation = %0.3e (scaled violation of linear constraints)\n", - (double)(state->replcerr)); - ae_trace("nlc.violation = %0.3e (scaled violation of nonlinear constraints)\n", - (double)(mx)); - ae_trace("gamma0 = %0.3e (Hessian 2-norm estimate for target)\n", - (double)(state->tracegamma.ptr.p_double[0])); - j = 0; - for(i=0; i<=nlec+nlic; i++) - { - if( ae_fp_greater(state->tracegamma.ptr.p_double[i],state->tracegamma.ptr.p_double[j]) ) - { - j = i; - } - } - ae_trace("gammaMax = %0.3e (maximum over Hessian 2-norm estimates for target/constraints)\n", - (double)(state->tracegamma.ptr.p_double[j])); - ae_trace("arg(gammaMax) = %0d (function index; 0 for target, >0 for nonlinear constraints)\n", - (int)(j)); - } - - /* - * PHASE 2 - * - * This phase is a primary part of the algorithm which is responsible for its - * convergence properties. - * - * It solves QP subproblem with possible activation and deactivation of constraints - * and then starts backtracking (step length is bounded by 1.0) merit function search - * (with second-order correction to deal with Maratos effect) on the direction produced - * by QP subproblem. - * - * This phase is everything we need to in order to have convergence; however, - * it has one performance-related issue: using "general" interior point QP solver - * results in slow solution times. Fast equality-constrained phase is essential for - * the quick convergence. - */ - nlcsqp_qpsubsolversetalgoipm(&state->subsolver, _state); - nlcsqp_sqpcopystate(state, &state->stepkx, &state->stepkfi, &state->stepkj, &state->step0x, &state->step0fi, &state->step0j, _state); - nlcsqp_meritphaseinit(&state->meritstate, &state->stepkx, &state->stepkfi, &state->stepkj, n, nec, nic, nlec, nlic, &state->abslagmemory, nlcsqp_penaltymemlen, _state); -lbl_5: - if( !nlcsqp_meritphaseiteration(state, &state->meritstate, smonitor, userterminationneeded, _state) ) - { - goto lbl_6; - } - state->rstate.stage = 2; - goto lbl_rcomm; -lbl_2: - goto lbl_5; -lbl_6: - nlcsqp_meritphaseresults(&state->meritstate, &state->stepkx, &state->stepkfi, &state->stepkj, &state->meritlagmult, &increasebigc, &status, _state); - if( status==0 ) - { - goto lbl_4; - } - ae_assert(status>0, "MinSQPIteration: integrity check failed", _state); - state->haslagmult = ae_true; - for(i=nlcsqp_penaltymemlen-1; i>=1; i--) - { - rcopyrr(nec+nic+nlec+nlic, &state->abslagmemory, i-1, &state->abslagmemory, i, _state); - } - for(i=0; i<=nec+nic+nlec+nlic-1; i++) - { - state->abslagmemory.ptr.pp_double[0][i] = ae_fabs(state->meritlagmult.ptr.p_double[i], _state); - } - - /* - * Caller requested to update BigC - L1 penalty coefficient for linearized constraint violation - */ - if( increasebigc ) - { - state->bigc = ae_minreal(10*state->bigc, nlcsqp_maxbigc, _state); - } - - /* - * Update trust region. - * - * NOTE: when trust region radius remains fixed for a long time it may mean that we - * stagnated in eternal loop. In such cases we decrease it slightly in order - * to break possible loop. If such decrease was unnecessary, it may be easily - * fixed within few iterations. - */ - deltamax = (double)(0); - for(i=0; i<=n-1; i++) - { - deltamax = ae_maxreal(deltamax, ae_fabs(state->step0x.ptr.p_double[i]-state->stepkx.ptr.p_double[i], _state)/state->trustrad, _state); - } - trustradstagnated = ae_false; - inc(&state->trustradstagnationcnt, _state); - prevtrustrad = state->trustrad; - if( ae_fp_less_eq(deltamax,nlcsqp_sqpdeltadecrease) ) - { - state->trustrad = state->trustrad*ae_maxreal(deltamax/nlcsqp_sqpdeltadecrease, nlcsqp_maxtrustraddecay, _state); - state->trustradstagnationcnt = 0; - } - if( ae_fp_greater_eq(deltamax,nlcsqp_sqpdeltaincrease) ) - { - state->trustrad = state->trustrad*ae_minreal(deltamax/nlcsqp_sqpdeltaincrease, nlcsqp_maxtrustradgrowth, _state); - state->trustradstagnationcnt = 0; - } - if( state->trustradstagnationcnt>=nlcsqp_trustradstagnationlimit ) - { - state->trustrad = 0.5*state->trustrad; - state->trustradstagnationcnt = 0; - trustradstagnated = ae_true; - } - - /* - * Trace - */ - if( dotrace ) - { - ae_trace("\n--- outer iteration ends ---------------------------------------------------------------------------\n"); - ae_trace("deltaMax = %0.3f (ratio of step length to trust radius)\n", - (double)(deltamax)); - ae_trace("newTrustRad = %0.3e", - (double)(state->trustrad)); - if( !trustradstagnated ) - { - if( ae_fp_greater(state->trustrad,prevtrustrad) ) - { - ae_trace(", trust radius increased"); - } - if( ae_fp_less(state->trustrad,prevtrustrad) ) - { - ae_trace(", trust radius decreased"); - } - } - else - { - ae_trace(", trust radius forcibly decreased due to stagnation for %0d iterations", - (int)(nlcsqp_trustradstagnationlimit)); - } - ae_trace("\n"); - if( increasebigc ) - { - ae_trace("BigC = %0.3e (short step was performed, but some constraints are still infeasible - increasing)\n", - (double)(state->bigc)); - } - } - - /* - * Advance outer iteration counter, test stopping criteria - */ - inc(&state->repiterationscount, _state); - if( ae_fp_less_eq(ae_fabs(state->stepkfi.ptr.p_double[0]-state->step0fi.ptr.p_double[0], _state),nlcsqp_stagnationepsf*ae_fabs(state->step0fi.ptr.p_double[0], _state)) ) - { - inc(&state->fstagnationcnt, _state); - } - else - { - state->fstagnationcnt = 0; - } - if( ae_fp_less_eq(state->trustrad,state->epsx) ) - { - state->repterminationtype = 2; - if( dotrace ) - { - ae_trace("> stopping condition met: trust radius is smaller than %0.3e\n", - (double)(state->epsx)); - } - goto lbl_4; - } - if( state->maxits>0&&state->repiterationscount>=state->maxits ) - { - state->repterminationtype = 5; - if( dotrace ) - { - ae_trace("> stopping condition met: %0d iterations performed\n", - (int)(state->repiterationscount)); - } - goto lbl_4; - } - if( state->fstagnationcnt>=nlcsqp_fstagnationlimit ) - { - state->repterminationtype = 7; - if( dotrace ) - { - ae_trace("> stopping criteria are too stringent: F stagnated for %0d its, stopping\n", - (int)(state->fstagnationcnt)); - } - goto lbl_4; - } - goto lbl_3; -lbl_4: - smoothnessmonitortracestatus(smonitor, dotrace, _state); - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = n; - state->rstate.ia.ptr.p_int[1] = nslack; - state->rstate.ia.ptr.p_int[2] = nec; - state->rstate.ia.ptr.p_int[3] = nic; - state->rstate.ia.ptr.p_int[4] = nlec; - state->rstate.ia.ptr.p_int[5] = nlic; - state->rstate.ia.ptr.p_int[6] = i; - state->rstate.ia.ptr.p_int[7] = j; - state->rstate.ia.ptr.p_int[8] = status; - state->rstate.ia.ptr.p_int[9] = subiterationidx; - state->rstate.ba.ptr.p_bool[0] = trustradstagnated; - state->rstate.ba.ptr.p_bool[1] = dotrace; - state->rstate.ba.ptr.p_bool[2] = dodetailedtrace; - state->rstate.ba.ptr.p_bool[3] = increasebigc; - state->rstate.ra.ptr.p_double[0] = v; - state->rstate.ra.ptr.p_double[1] = vv; - state->rstate.ra.ptr.p_double[2] = mx; - state->rstate.ra.ptr.p_double[3] = deltamax; - state->rstate.ra.ptr.p_double[4] = multiplyby; - state->rstate.ra.ptr.p_double[5] = setscaleto; - state->rstate.ra.ptr.p_double[6] = prevtrustrad; - return result; -} - - -/************************************************************************* -This function initializes SQP subproblem. -Should be called once in the beginning of the optimization. - -INPUT PARAMETERS: - SState - solver state - Subsolver - SQP subproblem to initialize - - -RETURN VALUE: - True on success - False on failure of the QP solver (unexpected... but possible due to numerical errors) - - - -- ALGLIB -- - Copyright 05.03.2018 by Bochkanov Sergey -*************************************************************************/ -static void nlcsqp_initqpsubsolver(minsqpstate* sstate, - minsqpsubsolver* subsolver, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nslack; - ae_int_t nec; - ae_int_t nic; - ae_int_t nlec; - ae_int_t nlic; - ae_int_t lccnt; - ae_int_t nnz; - ae_int_t offs; - ae_int_t i; - ae_int_t j; - - - n = sstate->n; - nec = sstate->nec; - nic = sstate->nic; - nlec = sstate->nlec; - nlic = sstate->nlic; - nslack = n+2*(nec+nlec)+(nic+nlic); - lccnt = nec+nic+nlec+nlic; - - /* - * Allocate temporaries - */ - rvectorsetlengthatleast(&subsolver->cural, lccnt, _state); - rvectorsetlengthatleast(&subsolver->curau, lccnt, _state); - rvectorsetlengthatleast(&subsolver->curbndl, nslack, _state); - rvectorsetlengthatleast(&subsolver->curbndu, nslack, _state); - rvectorsetlengthatleast(&subsolver->curb, nslack, _state); - rvectorsetlengthatleast(&subsolver->sk, n, _state); - rvectorsetlengthatleast(&subsolver->yk, n, _state); - - /* - * Initial state - */ - subsolver->algokind = 0; - rmatrixsetlengthatleast(&subsolver->h, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - subsolver->h.ptr.pp_double[i][j] = (double)(0); - } - subsolver->h.ptr.pp_double[i][i] = (double)(1); - } - - /* - * Linear constraints do not change across subiterations, that's - * why we allocate storage for them at the start of the program. - * - * A full set of "raw" constraints is stored; later we will filter - * out inequality ones which are inactive anywhere in the current - * trust region. - * - * NOTE: because sparserawlc object stores only linear constraint - * (linearizations of nonlinear ones are not stored) we - * allocate only minimum necessary space. - */ - nnz = 0; - for(i=0; i<=nec+nic-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( sstate->scaledcleic.ptr.pp_double[i][j]!=0.0 ) - { - nnz = nnz+1; - } - } - } - ivectorsetlengthatleast(&subsolver->sparserawlc.ridx, nec+nic+1, _state); - rvectorsetlengthatleast(&subsolver->sparserawlc.vals, nnz, _state); - ivectorsetlengthatleast(&subsolver->sparserawlc.idx, nnz, _state); - ivectorsetlengthatleast(&subsolver->sparserawlc.didx, nec+nic, _state); - ivectorsetlengthatleast(&subsolver->sparserawlc.uidx, nec+nic, _state); - offs = 0; - subsolver->sparserawlc.ridx.ptr.p_int[0] = 0; - for(i=0; i<=nec+nic-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( sstate->scaledcleic.ptr.pp_double[i][j]!=0.0 ) - { - - /* - * Primary part of the matrix - */ - subsolver->sparserawlc.vals.ptr.p_double[offs] = sstate->scaledcleic.ptr.pp_double[i][j]; - subsolver->sparserawlc.idx.ptr.p_int[offs] = j; - offs = offs+1; - } - } - subsolver->sparserawlc.ridx.ptr.p_int[i+1] = offs; - } - subsolver->sparserawlc.matrixtype = 1; - subsolver->sparserawlc.ninitialized = subsolver->sparserawlc.ridx.ptr.p_int[nec+nic]; - subsolver->sparserawlc.m = nec+nic; - subsolver->sparserawlc.n = n; - sparseinitduidx(&subsolver->sparserawlc, _state); -} - - -/************************************************************************* -This function sets subsolver algorithm to interior point method (IPM) - - -- ALGLIB -- - Copyright 05.03.2018 by Bochkanov Sergey -*************************************************************************/ -static void nlcsqp_qpsubsolversetalgoipm(minsqpsubsolver* subsolver, - ae_state *_state) -{ - - - subsolver->algokind = 0; -} - - -/************************************************************************* -Updates Hessian estimate, uses regularized formula which prevents Hessian -eigenvalues from decreasing below sqrt(Eps) and rejects updates larger -than 1/sqrt(Eps) in magnitude. - -INPUT PARAMETERS: - SState - solver state - Subsolver - SQP subproblem to initialize - X0, G0 - point #0 and gradient at #0, array[N] - X1, G1 - point #1 and gradient at #1, array[N] - - - -- ALGLIB -- - Copyright 05.03.2018 by Bochkanov Sergey -*************************************************************************/ -static ae_bool nlcsqp_qpsubproblemupdatehessian(minsqpstate* sstate, - minsqpsubsolver* subsolver, - /* Real */ ae_vector* x0, - /* Real */ ae_vector* g0, - /* Real */ ae_vector* x1, - /* Real */ ae_vector* g1, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - double shs; - double rawsy; - double sy; - double snrm2; - double ynrm2; - double v2; - double gk; - double sk; - double yk; - double mxs; - double mxy; - double mxhs; - double reg; - double big; - double growth; - double eigold; - double eignew; - double eigcorrection; - ae_bool result; - - - - /* - * Algorithm parameters - */ - reg = 100*ae_sqrt(ae_machineepsilon, _state); - big = 1/reg; - growth = 100.0; - - /* - * Proceed - */ - result = ae_false; - n = sstate->n; - rvectorsetlengthatleast(&subsolver->tmp0, n, _state); - rawsy = (double)(0); - sy = (double)(0); - snrm2 = (double)(0); - ynrm2 = (double)(0); - v2 = (double)(0); - mxs = (double)(0); - mxy = (double)(0); - for(i=0; i<=n-1; i++) - { - - /* - * Fetch components - */ - sk = x1->ptr.p_double[i]-x0->ptr.p_double[i]; - yk = g1->ptr.p_double[i]-g0->ptr.p_double[i]; - gk = g0->ptr.p_double[i]; - - /* - * Compute raw (S,Y) without regularization (to be used later - * during comparison with zero) - */ - rawsy = rawsy+sk*yk; - - /* - * Convexify Y - */ - yk = yk+reg*sk; - - /* - * Compute various coefficients using regularized values - */ - sy = sy+sk*yk; - snrm2 = snrm2+sk*sk; - ynrm2 = ynrm2+yk*yk; - v2 = v2+gk*gk; - mxs = ae_maxreal(mxs, ae_fabs(sk, _state), _state); - mxy = ae_maxreal(mxy, ae_fabs(yk, _state), _state); - subsolver->sk.ptr.p_double[i] = sk; - subsolver->yk.ptr.p_double[i] = yk; - } - shs = rmatrixsyvmv(n, &subsolver->h, 0, 0, ae_true, &subsolver->sk, 0, &subsolver->tmp0, _state); - rmatrixgemv(n, n, 1.0, &subsolver->h, 0, 0, 0, &subsolver->sk, 0, 0.0, &subsolver->tmp0, 0, _state); - mxhs = (double)(0); - for(i=0; i<=n-1; i++) - { - mxhs = ae_maxreal(mxhs, ae_fabs(subsolver->tmp0.ptr.p_double[i], _state), _state); - } - - /* - * Skip updates if (Sk,Yk)<=0 or Sk*H*Sk<=0 - * - * NOTE: we use 0.5*(SY+RawSY) in place of (Sk,Yk) which allows us to have slight - * nonconvexity due to numerical noise. - */ - if( ae_fp_less_eq(0.5*(sy+rawsy),(double)(0)) ) - { - return result; - } - if( ae_fp_less_eq(shs,(double)(0)) ) - { - return result; - } - if( ae_fp_less_eq(snrm2,(double)(0)) ) - { - return result; - } - ae_assert(ae_fp_greater(sy,(double)(0)), "UpdateHessian: integrity check failed", _state); - - /* - * Skip updates with too short steps - * - * NOTE: may prevent us from updating Hessian near the solution - */ - if( ae_fp_less_eq(mxs,coalesce(sstate->epsx, ae_sqrt(ae_machineepsilon, _state), _state)) ) - { - return result; - } - - /* - * Too large Hessian updates sometimes may come from noisy or nonsmooth problems. - * - * Skip updates with max(Yk)^2/(Yk,Sk)>=BIG or max(H*Sk)^2/(Sk*H*Sk)>=BIG - */ - if( ae_fp_greater_eq(ae_sqr(mxy, _state)/sy,big) ) - { - return result; - } - if( ae_fp_greater_eq(ae_sqr(mxhs, _state)/shs,big) ) - { - return result; - } - - /* - * Compare eigenvalues of H: old one removed by update, and new one. - * We require that new eigenvalue is not much larger/smaller than the old one. - * In order to enforce this condition we compute correction coefficient and - * multiply one of the rank-1 updates by this coefficient. - */ - eigold = shs/snrm2; - eignew = ynrm2/sy; - eigcorrection = 1.0; - if( ae_fp_greater(eignew,eigold*growth) ) - { - eigcorrection = 1/(eignew/(eigold*growth)); - } - if( ae_fp_less(eignew,eigold/growth) ) - { - eigcorrection = 1/(eignew/(eigold/growth)); - } - - /* - * Update Hessian - */ - rmatrixger(n, n, &subsolver->h, 0, 0, -1/shs, &subsolver->tmp0, 0, &subsolver->tmp0, 0, _state); - rmatrixger(n, n, &subsolver->h, 0, 0, eigcorrection*(1/sy), &subsolver->yk, 0, &subsolver->yk, 0, _state); - result = ae_true; - return result; -} - - -/************************************************************************* -This function solves QP subproblem given by initial point X, function vector Fi -and Jacobian Jac, and returns estimates of Lagrangian multipliers and search direction D[]. - - -- ALGLIB -- - Copyright 05.03.2018 by Bochkanov Sergey -*************************************************************************/ -static void nlcsqp_fassolve(minsqpsubsolver* subsolver, - /* Real */ ae_vector* d0, - /* Real */ ae_matrix* h, - ae_int_t nq, - /* Real */ ae_vector* b, - ae_int_t n, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - sparsematrix* a, - ae_int_t m, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - double trustrad, - ae_int_t* terminationtype, - /* Real */ ae_vector* d, - /* Real */ ae_vector* lagmult, - ae_state *_state) -{ - ae_int_t i; - - - *terminationtype = 1; - - /* - * Initial point, integrity check for constraints - */ - bvectorsetlengthatleast(&subsolver->hasbndl, n, _state); - bvectorsetlengthatleast(&subsolver->hasbndu, n, _state); - for(i=0; i<=n-1; i++) - { - subsolver->hasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state); - subsolver->hasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state); - ae_assert(!subsolver->hasbndl.ptr.p_bool[i]||ae_fp_less_eq(bndl->ptr.p_double[i],d0->ptr.p_double[i]), "FASSolve: integrity check failed", _state); - ae_assert(!subsolver->hasbndu.ptr.p_bool[i]||ae_fp_greater_eq(bndu->ptr.p_double[i],d0->ptr.p_double[i]), "FASSolve: integrity check failed", _state); - d->ptr.p_double[i] = d0->ptr.p_double[i]; - } - bvectorsetlengthatleast(&subsolver->hasal, m, _state); - bvectorsetlengthatleast(&subsolver->hasau, m, _state); - for(i=0; i<=m-1; i++) - { - subsolver->hasal.ptr.p_bool[i] = ae_isfinite(al->ptr.p_double[i], _state); - subsolver->hasau.ptr.p_bool[i] = ae_isfinite(au->ptr.p_double[i], _state); - if( subsolver->hasal.ptr.p_bool[i]&&subsolver->hasau.ptr.p_bool[i] ) - { - ae_assert(ae_fp_less_eq(al->ptr.p_double[i],au->ptr.p_double[i]), "FASSolve: integrity check failed", _state); - } - } - rmatrixsetlengthatleast(&subsolver->activea, n, n, _state); - rvectorsetlengthatleast(&subsolver->activerhs, n, _state); - ivectorsetlengthatleast(&subsolver->activeidx, n, _state); - subsolver->activesetsize = 0; - - /* - * Activate equality constraints (at most N) - */ - for(i=0; i<=m-1; i++) - { - if( (subsolver->hasal.ptr.p_bool[i]&&subsolver->hasau.ptr.p_bool[i])&&ae_fp_eq(al->ptr.p_double[i],au->ptr.p_double[i]) ) - { - - /* - * Stop if full set of constraints is activated - */ - if( subsolver->activesetsize>=n ) - { - break; - } - } - } - rvectorsetlengthatleast(&subsolver->tmp0, n, _state); - rvectorsetlengthatleast(&subsolver->tmp1, n, _state); - for(i=0; i<=n-1; i++) - { - subsolver->tmp0.ptr.p_double[i] = trustrad; - subsolver->tmp1.ptr.p_double[i] = 0.0; - } - vipminitdensewithslacks(&subsolver->ipmsolver, &subsolver->tmp0, &subsolver->tmp1, nq, n, _state); - vipmsetquadraticlinear(&subsolver->ipmsolver, h, &subsolver->sparsedummy, 0, ae_true, b, _state); - vipmsetconstraints(&subsolver->ipmsolver, bndl, bndu, a, m, &subsolver->densedummy, 0, al, au, _state); - vipmoptimize(&subsolver->ipmsolver, ae_false, &subsolver->tmp0, &subsolver->tmp1, &subsolver->tmp2, terminationtype, _state); - if( *terminationtype<=0 ) - { - return; - } - for(i=0; i<=n-1; i++) - { - d->ptr.p_double[i] = subsolver->tmp0.ptr.p_double[i]; - } - for(i=0; i<=m-1; i++) - { - lagmult->ptr.p_double[i] = subsolver->tmp2.ptr.p_double[i]; - } -} - - -/************************************************************************* -This function solves QP subproblem given by initial point X, function vector Fi -and Jacobian Jac, and returns estimates of Lagrangian multipliers and search direction D[]. - - -- ALGLIB -- - Copyright 05.03.2018 by Bochkanov Sergey -*************************************************************************/ -static ae_bool nlcsqp_qpsubproblemsolve(minsqpstate* state, - minsqpsubsolver* subsolver, - /* Real */ ae_vector* x, - /* Real */ ae_vector* fi, - /* Real */ ae_matrix* jac, - /* Real */ ae_vector* d, - /* Real */ ae_vector* lagmult, - ae_int_t* terminationtype, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nslack; - ae_int_t nec; - ae_int_t nic; - ae_int_t nlec; - ae_int_t nlic; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double vv; - double vright; - double vmax; - ae_int_t lccnt; - ae_int_t offsslackec; - ae_int_t offsslacknlec; - ae_int_t offsslackic; - ae_int_t offsslacknlic; - ae_int_t offs; - ae_int_t nnz; - ae_int_t j0; - ae_int_t j1; - ae_bool result; - - *terminationtype = 0; - - n = state->n; - nec = state->nec; - nic = state->nic; - nlec = state->nlec; - nlic = state->nlic; - nslack = n+2*(nec+nlec)+(nic+nlic); - lccnt = nec+nic+nlec+nlic; - - /* - * Locations of slack variables - */ - offsslackec = n; - offsslacknlec = n+2*nec; - offsslackic = n+2*nec+2*nlec; - offsslacknlic = n+2*(nec+nlec)+nic; - - /* - * Prepare temporary structures - */ - rvectorgrowto(&subsolver->cural, lccnt, _state); - rvectorgrowto(&subsolver->curau, lccnt, _state); - rvectorsetlengthatleast(&subsolver->d0, nslack, _state); - - /* - * Prepare default solution: all zeros - */ - result = ae_true; - *terminationtype = 0; - for(i=0; i<=nslack-1; i++) - { - d->ptr.p_double[i] = 0.0; - subsolver->d0.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=lccnt-1; i++) - { - lagmult->ptr.p_double[i] = (double)(0); - } - - /* - * Linear term B - * - * NOTE: elements [N,NSlack) are equal to bigC + perturbation to improve numeric properties of QP problem - */ - for(i=0; i<=n-1; i++) - { - subsolver->curb.ptr.p_double[i] = jac->ptr.pp_double[0][i]; - } - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(jac->ptr.pp_double[0][i], _state); - } - v = coalesce(ae_sqrt(v, _state), 1.0, _state); - for(i=n; i<=nslack-1; i++) - { - subsolver->curb.ptr.p_double[i] = (state->bigc+1.0/(1+i))*v; - } - - /* - * Trust radius constraints for primary variables - */ - for(i=0; i<=n-1; i++) - { - subsolver->curbndl.ptr.p_double[i] = -state->trustrad; - subsolver->curbndu.ptr.p_double[i] = state->trustrad; - if( state->hasbndl.ptr.p_bool[i] ) - { - subsolver->curbndl.ptr.p_double[i] = ae_maxreal(subsolver->curbndl.ptr.p_double[i], state->scaledbndl.ptr.p_double[i]-x->ptr.p_double[i], _state); - } - if( state->hasbndu.ptr.p_bool[i] ) - { - subsolver->curbndu.ptr.p_double[i] = ae_minreal(subsolver->curbndu.ptr.p_double[i], state->scaledbndu.ptr.p_double[i]-x->ptr.p_double[i], _state); - } - } - - /* - * Prepare storage for "effective" constraining matrix - */ - nnz = subsolver->sparserawlc.ridx.ptr.p_int[nec+nic]; - for(i=0; i<=nlec+nlic-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( jac->ptr.pp_double[1+i][j]!=0.0 ) - { - nnz = nnz+1; - } - } - } - nnz = nnz+2*nec+nic; - nnz = nnz+2*nlec+nlic; - ivectorgrowto(&subsolver->sparseefflc.ridx, lccnt+1, _state); - rvectorgrowto(&subsolver->sparseefflc.vals, nnz, _state); - ivectorgrowto(&subsolver->sparseefflc.idx, nnz, _state); - ivectorsetlengthatleast(&subsolver->sparseefflc.didx, lccnt, _state); - ivectorsetlengthatleast(&subsolver->sparseefflc.uidx, lccnt, _state); - subsolver->sparseefflc.m = 0; - subsolver->sparseefflc.n = nslack; - subsolver->sparseefflc.matrixtype = 1; - - /* - * Append linear equality/inequality constraints - * - * Scan sparsified linear constraints stored in sparserawlc[], skip ones - * which are inactive anywhere in the trust region. - */ - rvectorsetlengthatleast(&subsolver->tmp0, nslack, _state); - for(i=0; i<=n-1; i++) - { - subsolver->tmp0.ptr.p_double[i] = x->ptr.p_double[i]; - } - for(i=n; i<=nslack-1; i++) - { - subsolver->tmp0.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=nec+nic-1; i++) - { - - /* - * Calculate: - * * VRight - product of X[] (extended with zeros up to NSlack elements) - * and AR[i] - Ith row of sparserawlc matrix. - * * VMax - maximum value of X*ARi computed over trust region - */ - vright = (double)(0); - vmax = (double)(0); - j0 = subsolver->sparserawlc.ridx.ptr.p_int[i]; - j1 = subsolver->sparserawlc.ridx.ptr.p_int[i+1]-1; - for(k=j0; k<=j1; k++) - { - j = subsolver->sparserawlc.idx.ptr.p_int[k]; - v = subsolver->tmp0.ptr.p_double[j]; - vv = subsolver->sparserawlc.vals.ptr.p_double[k]; - vright = vright+vv*v; - if( vv>=0 ) - { - vmax = vmax+vv*(v+subsolver->curbndu.ptr.p_double[j]); - } - else - { - vmax = vmax+vv*(v+subsolver->curbndl.ptr.p_double[j]); - } - } - - /* - * If constraint is an inequality one and guaranteed to be inactive - * within trust region, it is skipped (row itself is retained but - * filled by zeros). - */ - if( i>=nec&&vmax<=state->scaledcleic.ptr.pp_double[i][n] ) - { - offs = subsolver->sparseefflc.ridx.ptr.p_int[i]; - subsolver->sparseefflc.vals.ptr.p_double[offs] = (double)(-1); - subsolver->sparseefflc.idx.ptr.p_int[offs] = offsslackic+(i-nec); - subsolver->sparseefflc.ridx.ptr.p_int[i+1] = offs+1; - subsolver->cural.ptr.p_double[i] = 0.0; - subsolver->curau.ptr.p_double[i] = 0.0; - subsolver->curbndl.ptr.p_double[offsslackic+(i-nec)] = (double)(0); - subsolver->curbndu.ptr.p_double[offsslackic+(i-nec)] = (double)(0); - continue; - } - - /* - * Start working on row I - */ - offs = subsolver->sparseefflc.ridx.ptr.p_int[i]; - - /* - * Copy constraint from sparserawlc[] to sparseefflc[] - */ - j0 = subsolver->sparserawlc.ridx.ptr.p_int[i]; - j1 = subsolver->sparserawlc.ridx.ptr.p_int[i+1]-1; - for(k=j0; k<=j1; k++) - { - subsolver->sparseefflc.idx.ptr.p_int[offs] = subsolver->sparserawlc.idx.ptr.p_int[k]; - subsolver->sparseefflc.vals.ptr.p_double[offs] = subsolver->sparserawlc.vals.ptr.p_double[k]; - offs = offs+1; - } - - /* - * Set up slack variables - */ - if( isparseefflc.vals.ptr.p_double[offs+0] = (double)(-1); - subsolver->sparseefflc.vals.ptr.p_double[offs+1] = (double)(1); - subsolver->sparseefflc.idx.ptr.p_int[offs+0] = offsslackec+2*i+0; - subsolver->sparseefflc.idx.ptr.p_int[offs+1] = offsslackec+2*i+1; - offs = offs+2; - } - else - { - - /* - * Slack variables for inequality constraints - */ - subsolver->sparseefflc.vals.ptr.p_double[offs] = (double)(-1); - subsolver->sparseefflc.idx.ptr.p_int[offs] = offsslackic+(i-nec); - offs = offs+1; - } - - /* - * Finalize row - */ - subsolver->sparseefflc.ridx.ptr.p_int[i+1] = offs; - - /* - * Set up bounds and slack part of D0. - * - * NOTE: bounds for equality and inequality constraints are - * handled differently - */ - v = vright-state->scaledcleic.ptr.pp_double[i][n]; - if( icural.ptr.p_double[i] = -v; - subsolver->curau.ptr.p_double[i] = -v; - subsolver->curbndl.ptr.p_double[offsslackec+2*i+0] = (double)(0); - subsolver->curbndl.ptr.p_double[offsslackec+2*i+1] = (double)(0); - subsolver->curbndu.ptr.p_double[offsslackec+2*i+0] = ae_fabs(v, _state); - subsolver->curbndu.ptr.p_double[offsslackec+2*i+1] = ae_fabs(v, _state); - if( ae_fp_greater_eq(v,(double)(0)) ) - { - subsolver->d0.ptr.p_double[offsslackec+2*i+0] = ae_fabs(v, _state); - subsolver->d0.ptr.p_double[offsslackec+2*i+1] = (double)(0); - } - else - { - subsolver->d0.ptr.p_double[offsslackec+2*i+0] = (double)(0); - subsolver->d0.ptr.p_double[offsslackec+2*i+1] = ae_fabs(v, _state); - } - } - else - { - subsolver->cural.ptr.p_double[i] = _state->v_neginf; - subsolver->curau.ptr.p_double[i] = -v; - subsolver->curbndl.ptr.p_double[offsslackic+(i-nec)] = (double)(0); - subsolver->curbndu.ptr.p_double[offsslackic+(i-nec)] = ae_maxreal(v, (double)(0), _state); - subsolver->d0.ptr.p_double[offsslackic+(i-nec)] = ae_maxreal(v, (double)(0), _state); - } - } - subsolver->sparseefflc.m = subsolver->sparseefflc.m+(nec+nic); - - /* - * Append nonlinear equality/inequality constraints - */ - for(i=0; i<=nlec+nlic-1; i++) - { - - /* - * Calculate scale coefficient - */ - vv = (double)(0); - for(j=0; j<=n-1; j++) - { - v = jac->ptr.pp_double[1+i][j]; - vv = vv+v*v; - } - vv = 1/coalesce(ae_sqrt(vv, _state), (double)(1), _state); - - /* - * Copy scaled row - */ - offs = subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m+i]; - for(j=0; j<=n-1; j++) - { - if( jac->ptr.pp_double[1+i][j]!=0.0 ) - { - subsolver->sparseefflc.vals.ptr.p_double[offs] = vv*jac->ptr.pp_double[1+i][j]; - subsolver->sparseefflc.idx.ptr.p_int[offs] = j; - offs = offs+1; - } - } - if( isparseefflc.vals.ptr.p_double[offs+0] = (double)(-1); - subsolver->sparseefflc.vals.ptr.p_double[offs+1] = (double)(1); - subsolver->sparseefflc.idx.ptr.p_int[offs+0] = offsslacknlec+2*i+0; - subsolver->sparseefflc.idx.ptr.p_int[offs+1] = offsslacknlec+2*i+1; - offs = offs+2; - } - else - { - - /* - * Add slack terms for inequality constraints - */ - subsolver->sparseefflc.vals.ptr.p_double[offs] = (double)(-1); - subsolver->sparseefflc.idx.ptr.p_int[offs] = offsslacknlic+(i-nlec); - offs = offs+1; - } - subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m+i+1] = offs; - - /* - * Set box constraints on slack variables and bounds on linear equality/inequality constraints - */ - v = vv*fi->ptr.p_double[1+i]; - if( icural.ptr.p_double[subsolver->sparseefflc.m+i] = -v; - subsolver->curau.ptr.p_double[subsolver->sparseefflc.m+i] = -v; - subsolver->curbndl.ptr.p_double[offsslacknlec+2*i+0] = (double)(0); - subsolver->curbndl.ptr.p_double[offsslacknlec+2*i+1] = (double)(0); - subsolver->curbndu.ptr.p_double[offsslacknlec+2*i+0] = ae_fabs(v, _state); - subsolver->curbndu.ptr.p_double[offsslacknlec+2*i+1] = ae_fabs(v, _state); - if( ae_fp_greater_eq(v,(double)(0)) ) - { - subsolver->d0.ptr.p_double[offsslacknlec+2*i+0] = ae_fabs(v, _state); - subsolver->d0.ptr.p_double[offsslacknlec+2*i+1] = (double)(0); - } - else - { - subsolver->d0.ptr.p_double[offsslacknlec+2*i+0] = (double)(0); - subsolver->d0.ptr.p_double[offsslacknlec+2*i+1] = ae_fabs(v, _state); - } - } - else - { - - /* - * Inequality constraint - */ - subsolver->cural.ptr.p_double[subsolver->sparseefflc.m+i] = _state->v_neginf; - subsolver->curau.ptr.p_double[subsolver->sparseefflc.m+i] = -v; - subsolver->curbndl.ptr.p_double[offsslacknlic+(i-nlec)] = (double)(0); - subsolver->curbndu.ptr.p_double[offsslacknlic+(i-nlec)] = ae_maxreal(v, (double)(0), _state); - subsolver->d0.ptr.p_double[offsslacknlic+(i-nlec)] = ae_maxreal(v, (double)(0), _state); - } - } - subsolver->sparseefflc.m = subsolver->sparseefflc.m+(nlec+nlic); - - /* - * Finalize sparse matrix structure - */ - ae_assert(subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m]<=subsolver->sparseefflc.idx.cnt, "QPSubproblemSolve: critical integrity check failed", _state); - ae_assert(subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m]<=subsolver->sparseefflc.vals.cnt, "QPSubproblemSolve: critical integrity check failed", _state); - subsolver->sparseefflc.ninitialized = subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m]; - sparseinitduidx(&subsolver->sparseefflc, _state); - - /* - * Solve quadratic program - */ - if( subsolver->algokind==0 ) - { - - /* - * Use dense IPM. - * - * We always treat its result as a valid solution, even for TerminationType<=0. - * In case anything is wrong with solution vector, we will detect it during line - * search phase (merit function does not increase). - * - * NOTE: because we cleaned up constraints that are DEFINITELY inactive within - * trust region, we do not have to worry about StopOnExcessiveBounds option. - */ - rvectorsetlengthatleast(&subsolver->tmp0, nslack, _state); - rvectorsetlengthatleast(&subsolver->tmp1, nslack, _state); - for(i=0; i<=nslack-1; i++) - { - subsolver->tmp0.ptr.p_double[i] = state->trustrad; - subsolver->tmp1.ptr.p_double[i] = 0.0; - } - vipminitdensewithslacks(&subsolver->ipmsolver, &subsolver->tmp0, &subsolver->tmp1, n, nslack, _state); - vipmsetquadraticlinear(&subsolver->ipmsolver, &subsolver->h, &subsolver->sparsedummy, 0, ae_true, &subsolver->curb, _state); - vipmsetconstraints(&subsolver->ipmsolver, &subsolver->curbndl, &subsolver->curbndu, &subsolver->sparseefflc, subsolver->sparseefflc.m, &subsolver->densedummy, 0, &subsolver->cural, &subsolver->curau, _state); - vipmoptimize(&subsolver->ipmsolver, ae_false, &subsolver->tmp0, &subsolver->tmp1, &subsolver->tmp2, terminationtype, _state); - for(i=0; i<=nslack-1; i++) - { - d->ptr.p_double[i] = subsolver->tmp0.ptr.p_double[i]; - } - for(i=0; i<=lccnt-1; i++) - { - lagmult->ptr.p_double[i] = subsolver->tmp2.ptr.p_double[i]; - } - return result; - } - if( subsolver->algokind==1 ) - { - - /* - * Use fast active set - */ - nlcsqp_fassolve(subsolver, &subsolver->d0, &subsolver->h, n, &subsolver->curb, nslack, &subsolver->curbndl, &subsolver->curbndu, &subsolver->sparseefflc, subsolver->sparseefflc.m, &subsolver->cural, &subsolver->curau, state->trustrad, terminationtype, d, lagmult, _state); - if( *terminationtype<=0 ) - { - - /* - * QP solver failed due to numerical errors; exit - */ - result = ae_false; - return result; - } - return result; - } - - /* - * Unexpected - */ - ae_assert(ae_false, "SQP: unexpected subsolver type", _state); - return result; -} - - -/************************************************************************* -This function initializes MeritPhase temporaries. It should be called before -beginning of each new iteration. You may call it multiple times for the -same instance of MeritPhase temporaries. - -INPUT PARAMETERS: - MeritState - instance to be initialized. - N - problem dimensionality - NEC, NIC - linear equality/inequality constraint count - NLEC, NLIC - nonlinear equality/inequality constraint count - AbsLagMemory - array[MemLen,NEC+NIC+NLEC+NLIC], stores absolute - values of Lagrange multipliers for the last MemLen - iterations - MemLen - memory length - -OUTPUT PARAMETERS: - MeritState - instance being initialized - - -- ALGLIB -- - Copyright 05.02.2019 by Bochkanov Sergey -*************************************************************************/ -static void nlcsqp_meritphaseinit(minsqpmeritphasestate* meritstate, - /* Real */ ae_vector* curx, - /* Real */ ae_vector* curfi, - /* Real */ ae_matrix* curj, - ae_int_t n, - ae_int_t nec, - ae_int_t nic, - ae_int_t nlec, - ae_int_t nlic, - /* Real */ ae_matrix* abslagmemory, - ae_int_t memlen, - ae_state *_state) -{ - ae_int_t i; - ae_int_t nslack; - - - nslack = n+2*(nec+nlec)+(nic+nlic); - meritstate->n = n; - meritstate->nec = nec; - meritstate->nic = nic; - meritstate->nlec = nlec; - meritstate->nlic = nlic; - rvectorsetlengthatleast(&meritstate->d, nslack, _state); - rvectorsetlengthatleast(&meritstate->dx, nslack, _state); - rvectorsetlengthatleast(&meritstate->stepkx, n, _state); - rvectorsetlengthatleast(&meritstate->stepkxc, n, _state); - rvectorsetlengthatleast(&meritstate->stepkxn, n, _state); - rvectorsetlengthatleast(&meritstate->stepkfi, 1+nlec+nlic, _state); - rvectorsetlengthatleast(&meritstate->stepkfic, 1+nlec+nlic, _state); - rvectorsetlengthatleast(&meritstate->stepkfin, 1+nlec+nlic, _state); - rmatrixsetlengthatleast(&meritstate->stepkj, 1+nlec+nlic, n, _state); - rmatrixsetlengthatleast(&meritstate->stepkjc, 1+nlec+nlic, n, _state); - rmatrixsetlengthatleast(&meritstate->stepkjn, 1+nlec+nlic, n, _state); - rvectorsetlengthatleast(&meritstate->stepklaggrad, n, _state); - rvectorsetlengthatleast(&meritstate->stepknlaggrad, n, _state); - rvectorsetlengthatleast(&meritstate->lagmult, nec+nic+nlec+nlic, _state); - rvectorsetlengthatleast(&meritstate->dummylagmult, nec+nic+nlec+nlic, _state); - rsetallocv(nec+nic+nlec+nlic, 0.0, &meritstate->penalties, _state); - for(i=0; i<=memlen-1; i++) - { - rmergemaxrv(nec+nic+nlec+nlic, abslagmemory, i, &meritstate->penalties, _state); - } - rcopyv(n, curx, &meritstate->stepkx, _state); - rcopyv(1+nlec+nlic, curfi, &meritstate->stepkfi, _state); - for(i=0; i<=nlec+nlic; i++) - { - rcopyrr(n, curj, i, &meritstate->stepkj, i, _state); - } - ae_vector_set_length(&meritstate->rmeritphasestate.ia, 7+1, _state); - ae_vector_set_length(&meritstate->rmeritphasestate.ba, 3+1, _state); - ae_vector_set_length(&meritstate->rmeritphasestate.ra, 9+1, _state); - meritstate->rmeritphasestate.stage = -1; -} - - -/************************************************************************* -This function tries to perform either phase #1 or phase #3 step. - -Former corresponds to linear model step (without conjugacy constraints) with -correction for nonlinearity ("second order correction"). Such correction -helps to overcome Maratos effect (a tendency of L1 penalized merit -functions to reject nonzero steps). - -Latter is a step using linear model with no second order correction. - -INPUT PARAMETERS: - State - SQP solver state - SMonitor - smoothness monitor - UserTerminationNeeded-True if user requested termination - -OUTPUT PARAMETERS: - State - RepTerminationType is set to current termination code (if Status=0). - Status - when reverse communication is done, Status is set to: - * positive value, if we can proceed to the next stage - of the outer iteration - * zero, if algorithm is terminated (RepTerminationType - is set to appropriate value) - - -- ALGLIB -- - Copyright 05.02.2019 by Bochkanov Sergey -*************************************************************************/ -static ae_bool nlcsqp_meritphaseiteration(minsqpstate* state, - minsqpmeritphasestate* meritstate, - smoothnessmonitor* smonitor, - ae_bool userterminationneeded, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nslack; - ae_int_t nec; - ae_int_t nic; - ae_int_t nlec; - ae_int_t nlic; - ae_int_t i; - ae_int_t j; - double v; - double vv; - double mx; - double f0; - double f1; - double nu; - double localstp; - double stepklagval; - double stepknlagval; - ae_bool hessianupdateperformed; - ae_bool dotrace; - ae_bool doprobing; - ae_bool dotracexd; - double stp; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( meritstate->rmeritphasestate.stage>=0 ) - { - n = meritstate->rmeritphasestate.ia.ptr.p_int[0]; - nslack = meritstate->rmeritphasestate.ia.ptr.p_int[1]; - nec = meritstate->rmeritphasestate.ia.ptr.p_int[2]; - nic = meritstate->rmeritphasestate.ia.ptr.p_int[3]; - nlec = meritstate->rmeritphasestate.ia.ptr.p_int[4]; - nlic = meritstate->rmeritphasestate.ia.ptr.p_int[5]; - i = meritstate->rmeritphasestate.ia.ptr.p_int[6]; - j = meritstate->rmeritphasestate.ia.ptr.p_int[7]; - hessianupdateperformed = meritstate->rmeritphasestate.ba.ptr.p_bool[0]; - dotrace = meritstate->rmeritphasestate.ba.ptr.p_bool[1]; - doprobing = meritstate->rmeritphasestate.ba.ptr.p_bool[2]; - dotracexd = meritstate->rmeritphasestate.ba.ptr.p_bool[3]; - v = meritstate->rmeritphasestate.ra.ptr.p_double[0]; - vv = meritstate->rmeritphasestate.ra.ptr.p_double[1]; - mx = meritstate->rmeritphasestate.ra.ptr.p_double[2]; - f0 = meritstate->rmeritphasestate.ra.ptr.p_double[3]; - f1 = meritstate->rmeritphasestate.ra.ptr.p_double[4]; - nu = meritstate->rmeritphasestate.ra.ptr.p_double[5]; - localstp = meritstate->rmeritphasestate.ra.ptr.p_double[6]; - stepklagval = meritstate->rmeritphasestate.ra.ptr.p_double[7]; - stepknlagval = meritstate->rmeritphasestate.ra.ptr.p_double[8]; - stp = meritstate->rmeritphasestate.ra.ptr.p_double[9]; - } - else - { - n = -536; - nslack = 487; - nec = -115; - nic = 886; - nlec = 346; - nlic = -722; - i = -413; - j = -461; - hessianupdateperformed = ae_true; - dotrace = ae_true; - doprobing = ae_false; - dotracexd = ae_false; - v = 306; - vv = -1011; - mx = 951; - f0 = -463; - f1 = 88; - nu = -861; - localstp = -678; - stepklagval = -731; - stepknlagval = -675; - stp = -763; - } - if( meritstate->rmeritphasestate.stage==0 ) - { - goto lbl_0; - } - if( meritstate->rmeritphasestate.stage==1 ) - { - goto lbl_1; - } - if( meritstate->rmeritphasestate.stage==2 ) - { - goto lbl_2; - } - if( meritstate->rmeritphasestate.stage==3 ) - { - goto lbl_3; - } - - /* - * Routine body - */ - n = state->n; - nec = state->nec; - nic = state->nic; - nlec = state->nlec; - nlic = state->nlic; - nslack = n+2*(nec+nlec)+(nic+nlic); - dotrace = ae_is_trace_enabled("SQP"); - dotracexd = dotrace&&ae_is_trace_enabled("SQP.DETAILED"); - doprobing = ae_is_trace_enabled("SQP.PROBING"); - ae_assert(meritstate->lagmult.cnt>=nec+nic+nlec+nlic, "MeritPhaseIteration: integrity check failed", _state); - - /* - * Report iteration beginning - */ - if( dotrace ) - { - ae_trace("\n--- quadratic step ---------------------------------------------------------------------------------\n"); - } - - /* - * Default decision is to continue algorithm - */ - meritstate->status = 1; - meritstate->increasebigc = ae_false; - stp = (double)(0); - - /* - * Determine step direction using initial quadratic model. - * Update penalties vector with current Lagrange multipliers. - */ - if( !nlcsqp_qpsubproblemsolve(state, &state->subsolver, &meritstate->stepkx, &meritstate->stepkfi, &meritstate->stepkj, &meritstate->d, &meritstate->lagmult, &j, _state) ) - { - if( dotrace ) - { - ae_trace("> [WARNING] QP subproblem failed with TerminationType=%0d\n", - (int)(j)); - } - result = ae_false; - return result; - } - if( dotrace ) - { - ae_trace("> QP subproblem solved with TerminationType=%0d\n", - (int)(j)); - } - for(i=0; i<=nec+nic+nlec+nlic-1; i++) - { - meritstate->penalties.ptr.p_double[i] = ae_maxreal(meritstate->penalties.ptr.p_double[i], ae_fabs(meritstate->lagmult.ptr.p_double[i], _state), _state); - } - - /* - * Perform merit function line search. - * - * First, we try unit step. If it does not decrease merit function, - * a second-order correction is tried (helps to combat Maratos effect). - */ - localstp = 1.0; - f0 = nlcsqp_meritfunction(state, &meritstate->stepkx, &meritstate->stepkfi, &meritstate->lagmult, &meritstate->penalties, &meritstate->tmpmerit, _state); - for(i=0; i<=n-1; i++) - { - meritstate->stepkxn.ptr.p_double[i] = meritstate->stepkx.ptr.p_double[i]+localstp*meritstate->d.ptr.p_double[i]; - } - nlcsqp_sqpsendx(state, &meritstate->stepkxn, _state); - state->needfij = ae_true; - meritstate->rmeritphasestate.stage = 0; - goto lbl_rcomm; -lbl_0: - state->needfij = ae_false; - if( !nlcsqp_sqpretrievefij(state, &meritstate->stepkfin, &meritstate->stepkjn, _state) ) - { - - /* - * Failed to retrieve func/Jac, infinities detected - */ - state->repterminationtype = -8; - meritstate->status = 0; - if( dotrace ) - { - ae_trace("[ERROR] infinities in target/constraints are detected\n"); - } - result = ae_false; - return result; - } - f1 = nlcsqp_meritfunction(state, &meritstate->stepkxn, &meritstate->stepkfin, &meritstate->lagmult, &meritstate->penalties, &meritstate->tmpmerit, _state); - if( ae_fp_less(f1,f0) ) - { - goto lbl_4; - } - - /* - * Full step increases merit function. Let's compute second order - * correction to the constraint model and recompute trial step D: - * * use original model of the target - * * extrapolate model of nonlinear constraints at StepKX+D back to origin - * - */ - if( dotrace ) - { - ae_trace("> preparing second-order correction\n"); - } - meritstate->stepkfic.ptr.p_double[0] = meritstate->stepkfi.ptr.p_double[0]; - for(j=0; j<=n-1; j++) - { - meritstate->stepkjc.ptr.pp_double[0][j] = meritstate->stepkj.ptr.pp_double[0][j]; - } - for(i=1; i<=nlec+nlic; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+meritstate->d.ptr.p_double[j]*meritstate->stepkj.ptr.pp_double[i][j]; - meritstate->stepkjc.ptr.pp_double[i][j] = meritstate->stepkj.ptr.pp_double[i][j]; - } - meritstate->stepkfic.ptr.p_double[i] = meritstate->stepkfin.ptr.p_double[i]-v; - } - if( !nlcsqp_qpsubproblemsolve(state, &state->subsolver, &meritstate->stepkx, &meritstate->stepkfic, &meritstate->stepkjc, &meritstate->dx, &meritstate->dummylagmult, &j, _state) ) - { - if( dotrace ) - { - ae_trace("> [WARNING] second-order QP subproblem failed\n"); - } - result = ae_false; - return result; - } - if( dotrace ) - { - ae_trace("> second-order QP subproblem solved with TerminationType=%0d\n", - (int)(j)); - } - for(i=0; i<=n-1; i++) - { - meritstate->d.ptr.p_double[i] = meritstate->dx.ptr.p_double[i]; - } - - /* - * Perform line search, we again try full step (maybe it will work after SOC) - */ - localstp = 1.0; - nu = 0.5; - f1 = f0; - smoothnessmonitorstartlinesearch(smonitor, &meritstate->stepkx, &meritstate->stepkfi, &meritstate->stepkj, _state); -lbl_6: - if( ae_false ) - { - goto lbl_7; - } - for(i=0; i<=n-1; i++) - { - meritstate->stepkxn.ptr.p_double[i] = meritstate->stepkx.ptr.p_double[i]+localstp*meritstate->d.ptr.p_double[i]; - } - nlcsqp_sqpsendx(state, &meritstate->stepkxn, _state); - state->needfij = ae_true; - meritstate->rmeritphasestate.stage = 1; - goto lbl_rcomm; -lbl_1: - state->needfij = ae_false; - if( !nlcsqp_sqpretrievefij(state, &meritstate->stepkfin, &meritstate->stepkjn, _state) ) - { - - /* - * Failed to retrieve func/Jac, infinities detected - */ - state->repterminationtype = -8; - meritstate->status = 0; - if( dotrace ) - { - ae_trace("[ERROR] infinities in target/constraints are detected\n"); - } - result = ae_false; - return result; - } - smoothnessmonitorenqueuepoint(smonitor, &meritstate->d, localstp, &meritstate->stepkxn, &meritstate->stepkfin, &meritstate->stepkjn, _state); - f1 = nlcsqp_meritfunction(state, &meritstate->stepkxn, &meritstate->stepkfin, &meritstate->lagmult, &meritstate->penalties, &meritstate->tmpmerit, _state); - if( ae_fp_less(f1,f0) ) - { - - /* - * Step is found! - */ - goto lbl_7; - } - if( ae_fp_less(localstp,0.001) ) - { - - /* - * Step is shorter than 0.001 times current search direction, - * it means that no good step can be found. - */ - localstp = (double)(0); - nlcsqp_sqpcopystate(state, &meritstate->stepkx, &meritstate->stepkfi, &meritstate->stepkj, &meritstate->stepkxn, &meritstate->stepkfin, &meritstate->stepkjn, _state); - goto lbl_7; - } - localstp = nu*localstp; - nu = ae_maxreal(0.1, 0.5*nu, _state); - goto lbl_6; -lbl_7: - smoothnessmonitorfinalizelinesearch(smonitor, _state); -lbl_4: - for(i=0; i<=n-1; i++) - { - if( state->hasbndl.ptr.p_bool[i] ) - { - meritstate->stepkxn.ptr.p_double[i] = ae_maxreal(meritstate->stepkxn.ptr.p_double[i], state->scaledbndl.ptr.p_double[i], _state); - } - if( state->hasbndu.ptr.p_bool[i] ) - { - meritstate->stepkxn.ptr.p_double[i] = ae_minreal(meritstate->stepkxn.ptr.p_double[i], state->scaledbndu.ptr.p_double[i], _state); - } - } - if( userterminationneeded ) - { - - /* - * User requested termination, break before we move to new point - */ - state->repterminationtype = 8; - meritstate->status = 0; - if( dotrace ) - { - ae_trace("> user requested termination\n"); - } - result = ae_false; - return result; - } - nlcsqp_lagrangianfg(state, &meritstate->stepkx, state->trustrad, &meritstate->stepkfi, &meritstate->stepkj, &meritstate->lagmult, &meritstate->tmplagrangianfg, &stepklagval, &meritstate->stepklaggrad, _state); - nlcsqp_lagrangianfg(state, &meritstate->stepkxn, state->trustrad, &meritstate->stepkfin, &meritstate->stepkjn, &meritstate->lagmult, &meritstate->tmplagrangianfg, &stepknlagval, &meritstate->stepknlaggrad, _state); - - /* - * Decide whether we want to request increase BigC (a constraint enforcing multiplier for L1 penalized - * QP subproblem) or not. - * - * An increase is NOT needed if at least one of the following holds: - * * a long step was performed - * * any single constraint can be made feasible within trust region - * - * Thus, BigC is requested to be increased if a short step was made, but there are some - * constraints that are infeasible within trust region. - */ - if( ae_fp_less(rmaxabsv(n, &meritstate->d, _state),0.9*state->trustrad) ) - { - for(i=0; i<=nec+nic-1; i++) - { - v = (double)(0); - vv = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state->scaledcleic.ptr.pp_double[i][j]*state->stepkx.ptr.p_double[j]; - vv = vv+ae_fabs(state->scaledcleic.ptr.pp_double[i][j]*state->trustrad, _state); - } - v = v-state->scaledcleic.ptr.pp_double[i][n]; - if( i>=nec ) - { - v = ae_maxreal(v, 0.0, _state); - } - meritstate->increasebigc = meritstate->increasebigc||ae_fp_greater(ae_fabs(v, _state),vv); - } - for(i=1; i<=nlec+nlic-1; i++) - { - v = state->stepkfi.ptr.p_double[i]; - vv = (double)(0); - for(j=0; j<=n-1; j++) - { - vv = vv+ae_fabs(state->stepkj.ptr.pp_double[i][j]*state->trustrad, _state); - } - if( i>=nlec+1 ) - { - v = ae_maxreal(v, 0.0, _state); - } - meritstate->increasebigc = meritstate->increasebigc||ae_fp_greater(ae_fabs(v, _state),vv); - } - } - - /* - * Trace - */ - if( !dotrace ) - { - goto lbl_8; - } - - /* - * Perform agressive probing of the search direction - additional function evaluations - * which help us to determine possible discontinuity and nonsmoothness of the problem - */ - if( !doprobing ) - { - goto lbl_10; - } - smoothnessmonitorstartprobing(smonitor, 1.0, 2, state->trustrad, _state); - smoothnessmonitorstartlinesearch(smonitor, &meritstate->stepkx, &meritstate->stepkfi, &meritstate->stepkj, _state); -lbl_12: - if( !smoothnessmonitorprobe(smonitor, _state) ) - { - goto lbl_13; - } - for(j=0; j<=n-1; j++) - { - meritstate->stepkxc.ptr.p_double[j] = meritstate->stepkx.ptr.p_double[j]+smonitor->probingstp*meritstate->d.ptr.p_double[j]; - if( state->hasbndl.ptr.p_bool[j] ) - { - meritstate->stepkxc.ptr.p_double[j] = ae_maxreal(meritstate->stepkxc.ptr.p_double[j], state->scaledbndl.ptr.p_double[j], _state); - } - if( state->hasbndu.ptr.p_bool[j] ) - { - meritstate->stepkxc.ptr.p_double[j] = ae_minreal(meritstate->stepkxc.ptr.p_double[j], state->scaledbndu.ptr.p_double[j], _state); - } - } - nlcsqp_sqpsendx(state, &meritstate->stepkxc, _state); - state->needfij = ae_true; - meritstate->rmeritphasestate.stage = 2; - goto lbl_rcomm; -lbl_2: - state->needfij = ae_false; - if( !nlcsqp_sqpretrievefij(state, &meritstate->stepkfic, &meritstate->stepkjc, _state) ) - { - goto lbl_13; - } - smonitor->probingf.ptr.p_double[0] = nlcsqp_rawlagrangian(state, &meritstate->stepkxc, &meritstate->stepkfic, &meritstate->lagmult, &meritstate->penalties, &meritstate->tmpmerit, _state); - smonitor->probingf.ptr.p_double[1] = meritstate->stepkfic.ptr.p_double[0]; - smoothnessmonitorenqueuepoint(smonitor, &meritstate->d, smonitor->probingstp, &meritstate->stepkxc, &meritstate->stepkfic, &meritstate->stepkjc, _state); - goto lbl_12; -lbl_13: - smoothnessmonitorfinalizelinesearch(smonitor, _state); - ae_trace("*** ------------------------------------------------------------\n"); - ae_trace("*** | probing search direction suggested by QP subproblem |\n"); - ae_trace("*** ------------------------------------------------------------\n"); - ae_trace("*** | Step | Lagrangian (unaugmentd)| Target function |\n"); - ae_trace("*** |along D| must be smooth | must be smooth |\n"); - ae_trace("*** | | function | slope | function | slope |\n"); - smoothnessmonitortraceprobingresults(smonitor, _state); -lbl_10: - - /* - * Update debug curvature information - TraceGamma[] - */ - v = (double)(0); - mx = (double)(0); - for(j=0; j<=n-1; j++) - { - vv = meritstate->stepkxn.ptr.p_double[j]-meritstate->stepkx.ptr.p_double[j]; - mx = ae_maxreal(mx, ae_fabs(vv, _state), _state); - v = v+vv*vv; - } - if( ae_fp_greater(v,(double)(0)) ) - { - - /* - * Step is long enough, update curvature information (used for debugging) - */ - for(i=0; i<=nlec+nlic; i++) - { - vv = (double)(0); - for(j=0; j<=n-1; j++) - { - vv = vv+(meritstate->stepkjn.ptr.pp_double[i][j]-meritstate->stepkj.ptr.pp_double[i][j])*(meritstate->stepkxn.ptr.p_double[j]-meritstate->stepkx.ptr.p_double[j]); - } - state->tracegamma.ptr.p_double[i] = ae_maxreal(state->tracegamma.ptr.p_double[i], ae_fabs(vv/(v+100*n*ae_machineepsilon*ae_machineepsilon), _state), _state); - } - } - - /* - * Output other information - */ - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - mx = ae_maxreal(mx, ae_fabs(meritstate->d.ptr.p_double[i], _state)/state->trustrad, _state); - } - if( ae_fp_greater(localstp,(double)(0)) ) - { - ae_trace("> nonzero linear step was performed\n"); - } - else - { - ae_trace("> zero linear step was performed\n"); - } - ae_trace("max(|Di|)/TrustRad = %0.6f\n", - (double)(mx)); - ae_trace("stp = %0.6f\n", - (double)(localstp)); - if( dotracexd ) - { - ae_trace("X0 (scaled) = "); - tracevectorautoprec(&meritstate->stepkx, 0, n, _state); - ae_trace("\n"); - ae_trace("D (scaled) = "); - tracevectorautoprec(&meritstate->d, 0, n, _state); - ae_trace("\n"); - ae_trace("X1 (scaled) = "); - tracevectorautoprec(&meritstate->stepkxn, 0, n, _state); - ae_trace("\n"); - } - ae_trace("meritF: %14.6e -> %14.6e (delta=%11.3e)\n", - (double)(f0), - (double)(f1), - (double)(f1-f0)); - ae_trace("scaled-targetF: %14.6e -> %14.6e (delta=%11.3e)\n", - (double)(meritstate->stepkfi.ptr.p_double[0]), - (double)(meritstate->stepkfin.ptr.p_double[0]), - (double)(meritstate->stepkfin.ptr.p_double[0]-meritstate->stepkfi.ptr.p_double[0])); - ae_trace("> evaluating possible Hessian update\n"); - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+(meritstate->stepkxn.ptr.p_double[i]-meritstate->stepkx.ptr.p_double[i])*(meritstate->stepknlaggrad.ptr.p_double[i]-meritstate->stepklaggrad.ptr.p_double[i]); - } - ae_trace("(Sk,Yk) = %0.3e\n", - (double)(v)); - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(meritstate->stepkxn.ptr.p_double[i]-meritstate->stepkx.ptr.p_double[i], _state); - } - ae_trace("(Sk,Sk) = %0.3e\n", - (double)(v)); - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(meritstate->stepknlaggrad.ptr.p_double[i]-meritstate->stepklaggrad.ptr.p_double[i], _state); - } - ae_trace("(Yk,Yk) = %0.3e\n", - (double)(v)); - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(meritstate->stepkxn.ptr.p_double[i]-meritstate->stepkx.ptr.p_double[i], _state)*state->subsolver.h.ptr.pp_double[i][i]; - for(j=i+1; j<=n-1; j++) - { - v = v+2*(meritstate->stepkxn.ptr.p_double[i]-meritstate->stepkx.ptr.p_double[i])*state->subsolver.h.ptr.pp_double[i][j]*(meritstate->stepkxn.ptr.p_double[j]-meritstate->stepkx.ptr.p_double[j]); - } - } - ae_trace("Sk*Bk*Sk = %0.3e\n", - (double)(v)); - v = state->subsolver.h.ptr.pp_double[0][0]; - for(i=0; i<=n-1; i++) - { - v = ae_minreal(v, state->subsolver.h.ptr.pp_double[i][i], _state); - } - ae_trace("mindiag(Bk) = %0.3e\n", - (double)(v)); - v = state->subsolver.h.ptr.pp_double[0][0]; - for(i=0; i<=n-1; i++) - { - v = ae_maxreal(v, state->subsolver.h.ptr.pp_double[i][i], _state); - } - ae_trace("maxdiag(Bk) = %0.3e\n", - (double)(v)); -lbl_8: - - /* - * Perform Hessian update - */ - hessianupdateperformed = ae_false; - if( ae_fp_greater(localstp,(double)(0)) ) - { - hessianupdateperformed = nlcsqp_qpsubproblemupdatehessian(state, &state->subsolver, &meritstate->stepkx, &meritstate->stepklaggrad, &meritstate->stepkxn, &meritstate->stepknlaggrad, _state); - } - if( dotrace ) - { - if( hessianupdateperformed ) - { - ae_trace("> Hessian updated\n"); - v = state->subsolver.h.ptr.pp_double[0][0]; - for(i=0; i<=n-1; i++) - { - v = ae_minreal(v, state->subsolver.h.ptr.pp_double[i][i], _state); - } - ae_trace("mindiag(Bk) = %0.3e\n", - (double)(v)); - v = state->subsolver.h.ptr.pp_double[0][0]; - for(i=0; i<=n-1; i++) - { - v = ae_maxreal(v, state->subsolver.h.ptr.pp_double[i][i], _state); - } - ae_trace("maxdiag(Bk) = %0.3e\n", - (double)(v)); - } - else - { - ae_trace("> skipping Hessian update\n"); - } - } - - /* - * Move to new point - */ - stp = localstp; - nlcsqp_sqpcopystate(state, &meritstate->stepkxn, &meritstate->stepkfin, &meritstate->stepkjn, &meritstate->stepkx, &meritstate->stepkfi, &meritstate->stepkj, _state); - if( ae_fp_less_eq(localstp,(double)(0)) ) - { - goto lbl_14; - } - - /* - * Report one more inner iteration - */ - nlcsqp_sqpsendx(state, &meritstate->stepkx, _state); - state->f = meritstate->stepkfi.ptr.p_double[0]*state->fscales.ptr.p_double[0]; - state->xupdated = ae_true; - meritstate->rmeritphasestate.stage = 3; - goto lbl_rcomm; -lbl_3: - state->xupdated = ae_false; - - /* - * Update constraint violations - */ - checklcviolation(&state->scaledcleic, &state->lcsrcidx, nec, nic, &meritstate->stepkx, n, &state->replcerr, &state->replcidx, _state); - unscaleandchecknlcviolation(&meritstate->stepkfi, &state->fscales, nlec, nlic, &state->repnlcerr, &state->repnlcidx, _state); -lbl_14: - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - meritstate->rmeritphasestate.ia.ptr.p_int[0] = n; - meritstate->rmeritphasestate.ia.ptr.p_int[1] = nslack; - meritstate->rmeritphasestate.ia.ptr.p_int[2] = nec; - meritstate->rmeritphasestate.ia.ptr.p_int[3] = nic; - meritstate->rmeritphasestate.ia.ptr.p_int[4] = nlec; - meritstate->rmeritphasestate.ia.ptr.p_int[5] = nlic; - meritstate->rmeritphasestate.ia.ptr.p_int[6] = i; - meritstate->rmeritphasestate.ia.ptr.p_int[7] = j; - meritstate->rmeritphasestate.ba.ptr.p_bool[0] = hessianupdateperformed; - meritstate->rmeritphasestate.ba.ptr.p_bool[1] = dotrace; - meritstate->rmeritphasestate.ba.ptr.p_bool[2] = doprobing; - meritstate->rmeritphasestate.ba.ptr.p_bool[3] = dotracexd; - meritstate->rmeritphasestate.ra.ptr.p_double[0] = v; - meritstate->rmeritphasestate.ra.ptr.p_double[1] = vv; - meritstate->rmeritphasestate.ra.ptr.p_double[2] = mx; - meritstate->rmeritphasestate.ra.ptr.p_double[3] = f0; - meritstate->rmeritphasestate.ra.ptr.p_double[4] = f1; - meritstate->rmeritphasestate.ra.ptr.p_double[5] = nu; - meritstate->rmeritphasestate.ra.ptr.p_double[6] = localstp; - meritstate->rmeritphasestate.ra.ptr.p_double[7] = stepklagval; - meritstate->rmeritphasestate.ra.ptr.p_double[8] = stepknlagval; - meritstate->rmeritphasestate.ra.ptr.p_double[9] = stp; - return result; -} - - -/************************************************************************* -This function initializes MeritPhase temporaries. It should be called before -beginning of each new iteration. You may call it multiple times for the -same instance of MeritPhase temporaries. - -INPUT PARAMETERS: - MeritState - instance to be initialized. - N - problem dimensionality - NEC, NIC - linear equality/inequality constraint count - NLEC, NLIC - nonlinear equality/inequality constraint count - -OUTPUT PARAMETERS: - IncreaseBigC - whether increasing BigC is suggested (we detected - infeasible constraints that are NOT improved) - or not. - MeritState - instance being initialized - - -- ALGLIB -- - Copyright 05.02.2019 by Bochkanov Sergey -*************************************************************************/ -static void nlcsqp_meritphaseresults(minsqpmeritphasestate* meritstate, - /* Real */ ae_vector* curx, - /* Real */ ae_vector* curfi, - /* Real */ ae_matrix* curj, - /* Real */ ae_vector* lagmult, - ae_bool* increasebigc, - ae_int_t* status, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - *increasebigc = meritstate->increasebigc; - *status = meritstate->status; - for(i=0; i<=meritstate->n-1; i++) - { - curx->ptr.p_double[i] = meritstate->stepkx.ptr.p_double[i]; - } - for(i=0; i<=meritstate->nlec+meritstate->nlic; i++) - { - curfi->ptr.p_double[i] = meritstate->stepkfi.ptr.p_double[i]; - for(j=0; j<=meritstate->n-1; j++) - { - curj->ptr.pp_double[i][j] = meritstate->stepkj.ptr.pp_double[i][j]; - } - } - ae_assert(lagmult->cnt>=meritstate->nec+meritstate->nic+meritstate->nlec+meritstate->nlic, "MeritPhaseResults: LagMult too short", _state); - for(i=0; i<=meritstate->nec+meritstate->nic+meritstate->nlec+meritstate->nlic-1; i++) - { - lagmult->ptr.p_double[i] = meritstate->lagmult.ptr.p_double[i]; - } -} - - -/************************************************************************* -Copies X to State.X -*************************************************************************/ -static void nlcsqp_sqpsendx(minsqpstate* state, - /* Real */ ae_vector* xs, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - - - n = state->n; - for(i=0; i<=n-1; i++) - { - if( state->hasbndl.ptr.p_bool[i]&&xs->ptr.p_double[i]<=state->scaledbndl.ptr.p_double[i] ) - { - state->x.ptr.p_double[i] = state->scaledbndl.ptr.p_double[i]; - continue; - } - if( state->hasbndu.ptr.p_bool[i]&&xs->ptr.p_double[i]>=state->scaledbndu.ptr.p_double[i] ) - { - state->x.ptr.p_double[i] = state->scaledbndu.ptr.p_double[i]; - continue; - } - state->x.ptr.p_double[i] = xs->ptr.p_double[i]; - } -} - - -/************************************************************************* -Retrieves F-vector and scaled Jacobian, copies them to FiS and JS. - -Returns True on success, False on failure (when F or J are not finite numbers). -*************************************************************************/ -static ae_bool nlcsqp_sqpretrievefij(minsqpstate* state, - /* Real */ ae_vector* fis, - /* Real */ ae_matrix* js, - ae_state *_state) -{ - ae_int_t nlec; - ae_int_t nlic; - ae_int_t n; - ae_int_t i; - ae_int_t j; - double v; - double vv; - ae_bool result; - - - n = state->n; - nlec = state->nlec; - nlic = state->nlic; - v = (double)(0); - for(i=0; i<=nlec+nlic; i++) - { - vv = 1/state->fscales.ptr.p_double[i]; - fis->ptr.p_double[i] = vv*state->fi.ptr.p_double[i]; - v = 0.1*v+fis->ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - js->ptr.pp_double[i][j] = vv*state->j.ptr.pp_double[i][j]; - v = 0.1*v+js->ptr.pp_double[i][j]; - } - } - result = ae_isfinite(v, _state); - return result; -} - - -/************************************************************************* -Copies state (X point, Fi vector, J jacobian) to preallocated storage. -*************************************************************************/ -static void nlcsqp_sqpcopystate(minsqpstate* state, - /* Real */ ae_vector* x0, - /* Real */ ae_vector* fi0, - /* Real */ ae_matrix* j0, - /* Real */ ae_vector* x1, - /* Real */ ae_vector* fi1, - /* Real */ ae_matrix* j1, - ae_state *_state) -{ - ae_int_t nlec; - ae_int_t nlic; - ae_int_t n; - ae_int_t i; - ae_int_t j; - - - n = state->n; - nlec = state->nlec; - nlic = state->nlic; - for(i=0; i<=n-1; i++) - { - x1->ptr.p_double[i] = x0->ptr.p_double[i]; - } - for(i=0; i<=nlec+nlic; i++) - { - fi1->ptr.p_double[i] = fi0->ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - j1->ptr.pp_double[i][j] = j0->ptr.pp_double[i][j]; - } - } -} - - -/************************************************************************* -This function calculates Lagrangian of the problem (in scaled variables): -its value and gradient. - -Additionally it also estimates violation of linear constraints at the point -as well as index of the most violated constraint -*************************************************************************/ -static void nlcsqp_lagrangianfg(minsqpstate* state, - /* Real */ ae_vector* x, - double trustrad, - /* Real */ ae_vector* fi, - /* Real */ ae_matrix* j, - /* Real */ ae_vector* lagmult, - minsqptmplagrangian* tmp, - double* f, - /* Real */ ae_vector* g, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - ae_int_t nec; - ae_int_t nic; - ae_int_t nlec; - ae_int_t nlic; - double v; - double vlag; - double vact; - double vd; - ae_bool usesparsegemv; - - *f = 0; - - n = state->n; - nec = state->nec; - nic = state->nic; - nlec = state->nlec; - nlic = state->nlic; - - /* - * Target function - */ - *f = fi->ptr.p_double[0]; - for(i=0; i<=n-1; i++) - { - g->ptr.p_double[i] = j->ptr.pp_double[0][i]; - } - - /* - * Lagrangian terms for linear constraints, constraint violations - */ - if( nec+nic>0 ) - { - usesparsegemv = state->subsolver.sparserawlc.ridx.ptr.p_int[nec+nic]sclagtmp0, ae_maxint(nec+nic, n, _state), _state); - rvectorsetlengthatleast(&tmp->sclagtmp1, ae_maxint(nec+nic, n, _state), _state); - if( usesparsegemv ) - { - sparsemv(&state->subsolver.sparserawlc, x, &tmp->sclagtmp0, _state); - } - else - { - rmatrixgemv(nec+nic, n, 1.0, &state->scaledcleic, 0, 0, 0, x, 0, 0.0, &tmp->sclagtmp0, 0, _state); - } - for(i=0; i<=nec+nic-1; i++) - { - - /* - * Prepare - */ - v = tmp->sclagtmp0.ptr.p_double[i]-state->scaledcleic.ptr.pp_double[i][n]; - vlag = lagmult->ptr.p_double[i]; - tmp->sclagtmp1.ptr.p_double[i] = (double)(0); - - /* - * Primary Lagrangian term - */ - vact = v; - vd = (double)(1); - *f = *f+vlag*vact; - tmp->sclagtmp1.ptr.p_double[i] = tmp->sclagtmp1.ptr.p_double[i]+vlag*vd; - - /* - * Quadratic augmentation term - */ - if( i0 ) - { - vact = v; - } - else - { - vact = (double)(0); - } - *f = *f+0.5*nlcsqp_augmentationfactor*vact*vact; - tmp->sclagtmp1.ptr.p_double[i] = tmp->sclagtmp1.ptr.p_double[i]+nlcsqp_augmentationfactor*vact; - } - if( usesparsegemv ) - { - sparsemtv(&state->subsolver.sparserawlc, &tmp->sclagtmp1, &tmp->sclagtmp0, _state); - for(i=0; i<=n-1; i++) - { - g->ptr.p_double[i] = g->ptr.p_double[i]+tmp->sclagtmp0.ptr.p_double[i]; - } - } - else - { - rmatrixgemv(n, nec+nic, 1.0, &state->scaledcleic, 0, 0, 1, &tmp->sclagtmp1, 0, 1.0, g, 0, _state); - } - } - - /* - * Lagrangian terms for nonlinear constraints - */ - rvectorsetlengthatleast(&tmp->sclagtmp1, nlec+nlic, _state); - for(i=0; i<=nlec+nlic-1; i++) - { - v = fi->ptr.p_double[1+i]; - vlag = lagmult->ptr.p_double[nec+nic+i]; - tmp->sclagtmp1.ptr.p_double[i] = (double)(0); - - /* - * Lagrangian term - */ - vact = v; - vd = (double)(1); - *f = *f+vlag*vact; - tmp->sclagtmp1.ptr.p_double[i] = tmp->sclagtmp1.ptr.p_double[i]+vlag*vd; - - /* - * Augmentation term - */ - if( i0 ) - { - vact = v; - } - else - { - vact = (double)(0); - } - *f = *f+0.5*nlcsqp_augmentationfactor*vact*vact; - tmp->sclagtmp1.ptr.p_double[i] = tmp->sclagtmp1.ptr.p_double[i]+nlcsqp_augmentationfactor*vact; - } - rmatrixgemv(n, nlec+nlic, 1.0, j, 1, 0, 1, &tmp->sclagtmp1, 0, 1.0, g, 0, _state); -} - - -/************************************************************************* -This function calculates L1-penalized merit function -*************************************************************************/ -static double nlcsqp_meritfunction(minsqpstate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* fi, - /* Real */ ae_vector* lagmult, - /* Real */ ae_vector* penalties, - minsqptmpmerit* tmp, - ae_state *_state) -{ - double tmp0; - double tmp1; - double result; - - - nlcsqp_meritfunctionandrawlagrangian(state, x, fi, lagmult, penalties, tmp, &tmp0, &tmp1, _state); - result = tmp0; - return result; -} - - -/************************************************************************* -This function calculates raw (unaugmented and smooth) Lagrangian -*************************************************************************/ -static double nlcsqp_rawlagrangian(minsqpstate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* fi, - /* Real */ ae_vector* lagmult, - /* Real */ ae_vector* penalties, - minsqptmpmerit* tmp, - ae_state *_state) -{ - double tmp0; - double tmp1; - double result; - - - nlcsqp_meritfunctionandrawlagrangian(state, x, fi, lagmult, penalties, tmp, &tmp0, &tmp1, _state); - result = tmp1; - return result; -} - - -/************************************************************************* -This function calculates L1-penalized merit function and raw (smooth and -un-augmented) Lagrangian -*************************************************************************/ -static void nlcsqp_meritfunctionandrawlagrangian(minsqpstate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* fi, - /* Real */ ae_vector* lagmult, - /* Real */ ae_vector* penalties, - minsqptmpmerit* tmp, - double* meritf, - double* rawlag, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - ae_int_t nec; - ae_int_t nic; - ae_int_t nlec; - ae_int_t nlic; - double v; - - *meritf = 0; - *rawlag = 0; - - n = state->n; - nec = state->nec; - nic = state->nic; - nlec = state->nlec; - nlic = state->nlic; - - /* - * Merit function and Lagrangian: primary term - */ - *meritf = fi->ptr.p_double[0]; - *rawlag = fi->ptr.p_double[0]; - - /* - * Merit function: augmentation and penalty for linear constraints - */ - rvectorsetlengthatleast(&tmp->mftmp0, nec+nic, _state); - rmatrixgemv(nec+nic, n, 1.0, &state->scaledcleic, 0, 0, 0, x, 0, 0.0, &tmp->mftmp0, 0, _state); - for(i=0; i<=nec+nic-1; i++) - { - v = tmp->mftmp0.ptr.p_double[i]-state->scaledcleic.ptr.pp_double[i][n]; - if( iptr.p_double[i], _state)*ae_fabs(v, _state); - - /* - * Raw Lagrangian - */ - *rawlag = *rawlag+lagmult->ptr.p_double[i]*v; - } - else - { - - /* - * Merit function: augmentation term + L1 penalty term - */ - *meritf = *meritf+0.5*nlcsqp_augmentationfactor*ae_sqr(ae_maxreal(v, (double)(0), _state), _state); - *meritf = *meritf+nlcsqp_meritfunctionbase*ae_maxreal(v, (double)(0), _state)+nlcsqp_meritfunctiongain*ae_fabs(1+penalties->ptr.p_double[i], _state)*ae_maxreal(v, (double)(0), _state); - - /* - * Raw Lagrangian - */ - *rawlag = *rawlag+lagmult->ptr.p_double[i]*v; - } - } - - /* - * Merit function: augmentation and penalty for nonlinear constraints - */ - for(i=0; i<=nlec+nlic-1; i++) - { - v = fi->ptr.p_double[1+i]; - if( iptr.p_double[nec+nic+i], _state)*ae_fabs(v, _state); - - /* - * Raw Lagrangian - */ - *rawlag = *rawlag+lagmult->ptr.p_double[nec+nic+i]*v; - } - else - { - - /* - * Merit function: augmentation term + L1 penalty term - */ - *meritf = *meritf+0.5*nlcsqp_augmentationfactor*ae_sqr(ae_maxreal(v, (double)(0), _state), _state); - *meritf = *meritf+nlcsqp_meritfunctionbase*ae_maxreal(v, (double)(0), _state)+nlcsqp_meritfunctiongain*ae_fabs(1+penalties->ptr.p_double[nec+nic+i], _state)*ae_maxreal(v, (double)(0), _state); - - /* - * Raw Lagrangian - */ - *rawlag = *rawlag+lagmult->ptr.p_double[nec+nic+i]*v; - } - } -} - - -void _minsqpsubsolver_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minsqpsubsolver *p = (minsqpsubsolver*)_p; - ae_touch_ptr((void*)p); - _vipmstate_init(&p->ipmsolver, _state, make_automatic); - ae_vector_init(&p->curb, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->curbndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->curbndu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cural, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->curau, 0, DT_REAL, _state, make_automatic); - _sparsematrix_init(&p->sparserawlc, _state, make_automatic); - _sparsematrix_init(&p->sparseefflc, _state, make_automatic); - ae_vector_init(&p->d0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->h, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->densedummy, 0, 0, DT_REAL, _state, make_automatic); - _sparsematrix_init(&p->sparsedummy, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp2, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->sk, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->yk, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->hasbndl, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->hasbndu, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->hasal, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->hasau, 0, DT_BOOL, _state, make_automatic); - ae_matrix_init(&p->activea, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->activerhs, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->activeidx, 0, DT_INT, _state, make_automatic); -} - - -void _minsqpsubsolver_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minsqpsubsolver *dst = (minsqpsubsolver*)_dst; - minsqpsubsolver *src = (minsqpsubsolver*)_src; - dst->algokind = src->algokind; - _vipmstate_init_copy(&dst->ipmsolver, &src->ipmsolver, _state, make_automatic); - ae_vector_init_copy(&dst->curb, &src->curb, _state, make_automatic); - ae_vector_init_copy(&dst->curbndl, &src->curbndl, _state, make_automatic); - ae_vector_init_copy(&dst->curbndu, &src->curbndu, _state, make_automatic); - ae_vector_init_copy(&dst->cural, &src->cural, _state, make_automatic); - ae_vector_init_copy(&dst->curau, &src->curau, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparserawlc, &src->sparserawlc, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparseefflc, &src->sparseefflc, _state, make_automatic); - ae_vector_init_copy(&dst->d0, &src->d0, _state, make_automatic); - ae_matrix_init_copy(&dst->h, &src->h, _state, make_automatic); - ae_matrix_init_copy(&dst->densedummy, &src->densedummy, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparsedummy, &src->sparsedummy, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic); - ae_vector_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic); - ae_vector_init_copy(&dst->sk, &src->sk, _state, make_automatic); - ae_vector_init_copy(&dst->yk, &src->yk, _state, make_automatic); - ae_vector_init_copy(&dst->hasbndl, &src->hasbndl, _state, make_automatic); - ae_vector_init_copy(&dst->hasbndu, &src->hasbndu, _state, make_automatic); - ae_vector_init_copy(&dst->hasal, &src->hasal, _state, make_automatic); - ae_vector_init_copy(&dst->hasau, &src->hasau, _state, make_automatic); - ae_matrix_init_copy(&dst->activea, &src->activea, _state, make_automatic); - ae_vector_init_copy(&dst->activerhs, &src->activerhs, _state, make_automatic); - ae_vector_init_copy(&dst->activeidx, &src->activeidx, _state, make_automatic); - dst->activesetsize = src->activesetsize; -} - - -void _minsqpsubsolver_clear(void* _p) -{ - minsqpsubsolver *p = (minsqpsubsolver*)_p; - ae_touch_ptr((void*)p); - _vipmstate_clear(&p->ipmsolver); - ae_vector_clear(&p->curb); - ae_vector_clear(&p->curbndl); - ae_vector_clear(&p->curbndu); - ae_vector_clear(&p->cural); - ae_vector_clear(&p->curau); - _sparsematrix_clear(&p->sparserawlc); - _sparsematrix_clear(&p->sparseefflc); - ae_vector_clear(&p->d0); - ae_matrix_clear(&p->h); - ae_matrix_clear(&p->densedummy); - _sparsematrix_clear(&p->sparsedummy); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->tmp1); - ae_vector_clear(&p->tmp2); - ae_vector_clear(&p->sk); - ae_vector_clear(&p->yk); - ae_vector_clear(&p->hasbndl); - ae_vector_clear(&p->hasbndu); - ae_vector_clear(&p->hasal); - ae_vector_clear(&p->hasau); - ae_matrix_clear(&p->activea); - ae_vector_clear(&p->activerhs); - ae_vector_clear(&p->activeidx); -} - - -void _minsqpsubsolver_destroy(void* _p) -{ - minsqpsubsolver *p = (minsqpsubsolver*)_p; - ae_touch_ptr((void*)p); - _vipmstate_destroy(&p->ipmsolver); - ae_vector_destroy(&p->curb); - ae_vector_destroy(&p->curbndl); - ae_vector_destroy(&p->curbndu); - ae_vector_destroy(&p->cural); - ae_vector_destroy(&p->curau); - _sparsematrix_destroy(&p->sparserawlc); - _sparsematrix_destroy(&p->sparseefflc); - ae_vector_destroy(&p->d0); - ae_matrix_destroy(&p->h); - ae_matrix_destroy(&p->densedummy); - _sparsematrix_destroy(&p->sparsedummy); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->tmp1); - ae_vector_destroy(&p->tmp2); - ae_vector_destroy(&p->sk); - ae_vector_destroy(&p->yk); - ae_vector_destroy(&p->hasbndl); - ae_vector_destroy(&p->hasbndu); - ae_vector_destroy(&p->hasal); - ae_vector_destroy(&p->hasau); - ae_matrix_destroy(&p->activea); - ae_vector_destroy(&p->activerhs); - ae_vector_destroy(&p->activeidx); -} - - -void _minsqptmplagrangian_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minsqptmplagrangian *p = (minsqptmplagrangian*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->sclagtmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->sclagtmp1, 0, DT_REAL, _state, make_automatic); -} - - -void _minsqptmplagrangian_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minsqptmplagrangian *dst = (minsqptmplagrangian*)_dst; - minsqptmplagrangian *src = (minsqptmplagrangian*)_src; - ae_vector_init_copy(&dst->sclagtmp0, &src->sclagtmp0, _state, make_automatic); - ae_vector_init_copy(&dst->sclagtmp1, &src->sclagtmp1, _state, make_automatic); -} - - -void _minsqptmplagrangian_clear(void* _p) -{ - minsqptmplagrangian *p = (minsqptmplagrangian*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->sclagtmp0); - ae_vector_clear(&p->sclagtmp1); -} - - -void _minsqptmplagrangian_destroy(void* _p) -{ - minsqptmplagrangian *p = (minsqptmplagrangian*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->sclagtmp0); - ae_vector_destroy(&p->sclagtmp1); -} - - -void _minsqptmpmerit_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minsqptmpmerit *p = (minsqptmpmerit*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->mftmp0, 0, DT_REAL, _state, make_automatic); -} - - -void _minsqptmpmerit_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minsqptmpmerit *dst = (minsqptmpmerit*)_dst; - minsqptmpmerit *src = (minsqptmpmerit*)_src; - ae_vector_init_copy(&dst->mftmp0, &src->mftmp0, _state, make_automatic); -} - - -void _minsqptmpmerit_clear(void* _p) -{ - minsqptmpmerit *p = (minsqptmpmerit*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->mftmp0); -} - - -void _minsqptmpmerit_destroy(void* _p) -{ - minsqptmpmerit *p = (minsqptmpmerit*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->mftmp0); -} - - -void _minsqpmeritphasestate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minsqpmeritphasestate *p = (minsqpmeritphasestate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepkx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepkxc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepkxn, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepkfi, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepkfic, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepkfin, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->stepkj, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->stepkjc, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->stepkjn, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->lagmult, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dummylagmult, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->penalties, 0, DT_REAL, _state, make_automatic); - _minsqptmpmerit_init(&p->tmpmerit, _state, make_automatic); - _minsqptmplagrangian_init(&p->tmplagrangianfg, _state, make_automatic); - ae_vector_init(&p->stepklaggrad, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepknlaggrad, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rmeritphasestate, _state, make_automatic); -} - - -void _minsqpmeritphasestate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minsqpmeritphasestate *dst = (minsqpmeritphasestate*)_dst; - minsqpmeritphasestate *src = (minsqpmeritphasestate*)_src; - dst->n = src->n; - dst->nec = src->nec; - dst->nic = src->nic; - dst->nlec = src->nlec; - dst->nlic = src->nlic; - ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic); - ae_vector_init_copy(&dst->dx, &src->dx, _state, make_automatic); - ae_vector_init_copy(&dst->stepkx, &src->stepkx, _state, make_automatic); - ae_vector_init_copy(&dst->stepkxc, &src->stepkxc, _state, make_automatic); - ae_vector_init_copy(&dst->stepkxn, &src->stepkxn, _state, make_automatic); - ae_vector_init_copy(&dst->stepkfi, &src->stepkfi, _state, make_automatic); - ae_vector_init_copy(&dst->stepkfic, &src->stepkfic, _state, make_automatic); - ae_vector_init_copy(&dst->stepkfin, &src->stepkfin, _state, make_automatic); - ae_matrix_init_copy(&dst->stepkj, &src->stepkj, _state, make_automatic); - ae_matrix_init_copy(&dst->stepkjc, &src->stepkjc, _state, make_automatic); - ae_matrix_init_copy(&dst->stepkjn, &src->stepkjn, _state, make_automatic); - ae_vector_init_copy(&dst->lagmult, &src->lagmult, _state, make_automatic); - ae_vector_init_copy(&dst->dummylagmult, &src->dummylagmult, _state, make_automatic); - ae_vector_init_copy(&dst->penalties, &src->penalties, _state, make_automatic); - _minsqptmpmerit_init_copy(&dst->tmpmerit, &src->tmpmerit, _state, make_automatic); - _minsqptmplagrangian_init_copy(&dst->tmplagrangianfg, &src->tmplagrangianfg, _state, make_automatic); - ae_vector_init_copy(&dst->stepklaggrad, &src->stepklaggrad, _state, make_automatic); - ae_vector_init_copy(&dst->stepknlaggrad, &src->stepknlaggrad, _state, make_automatic); - dst->status = src->status; - dst->increasebigc = src->increasebigc; - _rcommstate_init_copy(&dst->rmeritphasestate, &src->rmeritphasestate, _state, make_automatic); -} - - -void _minsqpmeritphasestate_clear(void* _p) -{ - minsqpmeritphasestate *p = (minsqpmeritphasestate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->d); - ae_vector_clear(&p->dx); - ae_vector_clear(&p->stepkx); - ae_vector_clear(&p->stepkxc); - ae_vector_clear(&p->stepkxn); - ae_vector_clear(&p->stepkfi); - ae_vector_clear(&p->stepkfic); - ae_vector_clear(&p->stepkfin); - ae_matrix_clear(&p->stepkj); - ae_matrix_clear(&p->stepkjc); - ae_matrix_clear(&p->stepkjn); - ae_vector_clear(&p->lagmult); - ae_vector_clear(&p->dummylagmult); - ae_vector_clear(&p->penalties); - _minsqptmpmerit_clear(&p->tmpmerit); - _minsqptmplagrangian_clear(&p->tmplagrangianfg); - ae_vector_clear(&p->stepklaggrad); - ae_vector_clear(&p->stepknlaggrad); - _rcommstate_clear(&p->rmeritphasestate); -} - - -void _minsqpmeritphasestate_destroy(void* _p) -{ - minsqpmeritphasestate *p = (minsqpmeritphasestate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->d); - ae_vector_destroy(&p->dx); - ae_vector_destroy(&p->stepkx); - ae_vector_destroy(&p->stepkxc); - ae_vector_destroy(&p->stepkxn); - ae_vector_destroy(&p->stepkfi); - ae_vector_destroy(&p->stepkfic); - ae_vector_destroy(&p->stepkfin); - ae_matrix_destroy(&p->stepkj); - ae_matrix_destroy(&p->stepkjc); - ae_matrix_destroy(&p->stepkjn); - ae_vector_destroy(&p->lagmult); - ae_vector_destroy(&p->dummylagmult); - ae_vector_destroy(&p->penalties); - _minsqptmpmerit_destroy(&p->tmpmerit); - _minsqptmplagrangian_destroy(&p->tmplagrangianfg); - ae_vector_destroy(&p->stepklaggrad); - ae_vector_destroy(&p->stepknlaggrad); - _rcommstate_destroy(&p->rmeritphasestate); -} - - -void _minsqpstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minsqpstate *p = (minsqpstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->scaledcleic, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->lcsrcidx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->hasbndl, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->hasbndu, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->scaledbndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->scaledbndu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fi, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->j, 0, 0, DT_REAL, _state, make_automatic); - _minsqpmeritphasestate_init(&p->meritstate, _state, make_automatic); - ae_vector_init(&p->step0x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepkx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->backupx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->step0fi, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepkfi, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->backupfi, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->step0j, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->stepkj, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->meritlagmult, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dummylagmult, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->abslagmemory, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fscales, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tracegamma, 0, DT_REAL, _state, make_automatic); - _minsqpsubsolver_init(&p->subsolver, _state, make_automatic); - _minsqptmpmerit_init(&p->tmpmerit, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); -} - - -void _minsqpstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minsqpstate *dst = (minsqpstate*)_dst; - minsqpstate *src = (minsqpstate*)_src; - dst->n = src->n; - dst->nec = src->nec; - dst->nic = src->nic; - dst->nlec = src->nlec; - dst->nlic = src->nlic; - ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic); - ae_matrix_init_copy(&dst->scaledcleic, &src->scaledcleic, _state, make_automatic); - ae_vector_init_copy(&dst->lcsrcidx, &src->lcsrcidx, _state, make_automatic); - ae_vector_init_copy(&dst->hasbndl, &src->hasbndl, _state, make_automatic); - ae_vector_init_copy(&dst->hasbndu, &src->hasbndu, _state, make_automatic); - ae_vector_init_copy(&dst->scaledbndl, &src->scaledbndl, _state, make_automatic); - ae_vector_init_copy(&dst->scaledbndu, &src->scaledbndu, _state, make_automatic); - dst->epsx = src->epsx; - dst->maxits = src->maxits; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->fi, &src->fi, _state, make_automatic); - ae_matrix_init_copy(&dst->j, &src->j, _state, make_automatic); - dst->f = src->f; - dst->needfij = src->needfij; - dst->xupdated = src->xupdated; - _minsqpmeritphasestate_init_copy(&dst->meritstate, &src->meritstate, _state, make_automatic); - dst->bigc = src->bigc; - dst->trustrad = src->trustrad; - dst->trustradstagnationcnt = src->trustradstagnationcnt; - dst->fstagnationcnt = src->fstagnationcnt; - ae_vector_init_copy(&dst->step0x, &src->step0x, _state, make_automatic); - ae_vector_init_copy(&dst->stepkx, &src->stepkx, _state, make_automatic); - ae_vector_init_copy(&dst->backupx, &src->backupx, _state, make_automatic); - ae_vector_init_copy(&dst->step0fi, &src->step0fi, _state, make_automatic); - ae_vector_init_copy(&dst->stepkfi, &src->stepkfi, _state, make_automatic); - ae_vector_init_copy(&dst->backupfi, &src->backupfi, _state, make_automatic); - ae_matrix_init_copy(&dst->step0j, &src->step0j, _state, make_automatic); - ae_matrix_init_copy(&dst->stepkj, &src->stepkj, _state, make_automatic); - dst->haslagmult = src->haslagmult; - ae_vector_init_copy(&dst->meritlagmult, &src->meritlagmult, _state, make_automatic); - ae_vector_init_copy(&dst->dummylagmult, &src->dummylagmult, _state, make_automatic); - ae_matrix_init_copy(&dst->abslagmemory, &src->abslagmemory, _state, make_automatic); - ae_vector_init_copy(&dst->fscales, &src->fscales, _state, make_automatic); - ae_vector_init_copy(&dst->tracegamma, &src->tracegamma, _state, make_automatic); - _minsqpsubsolver_init_copy(&dst->subsolver, &src->subsolver, _state, make_automatic); - _minsqptmpmerit_init_copy(&dst->tmpmerit, &src->tmpmerit, _state, make_automatic); - dst->repsimplexiterations = src->repsimplexiterations; - dst->repsimplexiterations1 = src->repsimplexiterations1; - dst->repsimplexiterations2 = src->repsimplexiterations2; - dst->repsimplexiterations3 = src->repsimplexiterations3; - dst->repiterationscount = src->repiterationscount; - dst->repterminationtype = src->repterminationtype; - dst->repbcerr = src->repbcerr; - dst->repbcidx = src->repbcidx; - dst->replcerr = src->replcerr; - dst->replcidx = src->replcidx; - dst->repnlcerr = src->repnlcerr; - dst->repnlcidx = src->repnlcidx; - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); -} - - -void _minsqpstate_clear(void* _p) -{ - minsqpstate *p = (minsqpstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->s); - ae_matrix_clear(&p->scaledcleic); - ae_vector_clear(&p->lcsrcidx); - ae_vector_clear(&p->hasbndl); - ae_vector_clear(&p->hasbndu); - ae_vector_clear(&p->scaledbndl); - ae_vector_clear(&p->scaledbndu); - ae_vector_clear(&p->x); - ae_vector_clear(&p->fi); - ae_matrix_clear(&p->j); - _minsqpmeritphasestate_clear(&p->meritstate); - ae_vector_clear(&p->step0x); - ae_vector_clear(&p->stepkx); - ae_vector_clear(&p->backupx); - ae_vector_clear(&p->step0fi); - ae_vector_clear(&p->stepkfi); - ae_vector_clear(&p->backupfi); - ae_matrix_clear(&p->step0j); - ae_matrix_clear(&p->stepkj); - ae_vector_clear(&p->meritlagmult); - ae_vector_clear(&p->dummylagmult); - ae_matrix_clear(&p->abslagmemory); - ae_vector_clear(&p->fscales); - ae_vector_clear(&p->tracegamma); - _minsqpsubsolver_clear(&p->subsolver); - _minsqptmpmerit_clear(&p->tmpmerit); - _rcommstate_clear(&p->rstate); -} - - -void _minsqpstate_destroy(void* _p) -{ - minsqpstate *p = (minsqpstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->s); - ae_matrix_destroy(&p->scaledcleic); - ae_vector_destroy(&p->lcsrcidx); - ae_vector_destroy(&p->hasbndl); - ae_vector_destroy(&p->hasbndu); - ae_vector_destroy(&p->scaledbndl); - ae_vector_destroy(&p->scaledbndu); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->fi); - ae_matrix_destroy(&p->j); - _minsqpmeritphasestate_destroy(&p->meritstate); - ae_vector_destroy(&p->step0x); - ae_vector_destroy(&p->stepkx); - ae_vector_destroy(&p->backupx); - ae_vector_destroy(&p->step0fi); - ae_vector_destroy(&p->stepkfi); - ae_vector_destroy(&p->backupfi); - ae_matrix_destroy(&p->step0j); - ae_matrix_destroy(&p->stepkj); - ae_vector_destroy(&p->meritlagmult); - ae_vector_destroy(&p->dummylagmult); - ae_matrix_destroy(&p->abslagmemory); - ae_vector_destroy(&p->fscales); - ae_vector_destroy(&p->tracegamma); - _minsqpsubsolver_destroy(&p->subsolver); - _minsqptmpmerit_destroy(&p->tmpmerit); - _rcommstate_destroy(&p->rstate); -} - - -#endif -#if defined(AE_COMPILE_QPDENSEAULSOLVER) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function initializes QPDENSEAULSettings structure with default settings. - -Newly created structure MUST be initialized by default settings - or by -copy of the already initialized structure. - - -- ALGLIB -- - Copyright 14.05.2011 by Bochkanov Sergey -*************************************************************************/ -void qpdenseaulloaddefaults(ae_int_t nmain, - qpdenseaulsettings* s, - ae_state *_state) -{ - - - s->epsx = 1.0E-6; - s->outerits = 5; - s->rho = 100.0; -} - - -/************************************************************************* -This function runs Dense-AUL solver; it returns after optimization process -was completed. Following QP problem is solved: - - min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin)) - -subject to combination of box and general linear dense/sparse constraints. - -INPUT PARAMETERS: - DenseA - for dense problems (AKind=0), A-term of CQM object - contains system matrix. Other terms are unspecified - and should not be referenced. - SparseA - for sparse problems (AKind=1), CRS format - AKind - sparse matrix format: - * 0 for dense matrix - * 1 for sparse matrix - SparseUpper - which triangle of SparseAC stores matrix - upper or - lower one (for dense matrices this parameter is not - actual). - B - linear term, array[N] - BndL - lower bound, array[N] - BndU - upper bound, array[N] - S - scale vector, array[NC]: - * I-th element contains scale of I-th variable, - * SC[I]>0 - XOrigin - origin term, array[NC]. Can be zero. - N - number of variables in the original formulation (no - slack variables). - CLEIC - dense linear equality/inequality constraints. Equality - constraints come first. - NEC, NIC - number of dense equality/inequality constraints. - SCLEIC - sparse linear equality/inequality constraints. Equality - constraints come first. - SNEC, SNIC - number of sparse equality/inequality constraints. - RenormLC - whether constraints should be renormalized (recommended) - or used "as is". - Settings - QPDENSEAULSettings object initialized by one of the initialization - functions. - State - object which stores temporaries - XS - initial point, array[NC] - - -OUTPUT PARAMETERS: - XS - last point - TerminationType-termination type: - * - * - * - - -- ALGLIB -- - Copyright 2017 by Bochkanov Sergey -*************************************************************************/ -void qpdenseauloptimize(convexquadraticmodel* a, - sparsematrix* sparsea, - ae_int_t akind, - ae_bool sparseaupper, - /* Real */ ae_vector* b, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - ae_int_t nn, - /* Real */ ae_matrix* cleic, - ae_int_t dnec, - ae_int_t dnic, - sparsematrix* scleic, - ae_int_t snec, - ae_int_t snic, - ae_bool renormlc, - qpdenseaulsettings* settings, - qpdenseaulbuffers* state, - /* Real */ ae_vector* xs, - /* Real */ ae_vector* lagbc, - /* Real */ ae_vector* laglc, - ae_int_t* terminationtype, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double vv; - double rho; - double epsx; - ae_int_t outeridx; - ae_int_t nmain; - ae_int_t nslack; - ae_int_t ntotal; - ae_int_t ktotal; - double maxrho; - double feaserr; - double feaserrprev; - double requestedfeasdecrease; - ae_int_t goodcounter; - ae_int_t stagnationcounter; - ae_int_t nectotal; - ae_int_t nictotal; - ae_int_t nicwork; - ae_int_t kwork; - ae_int_t nwork; - ae_bool allowwseviction; - ae_bool workingsetextended; - double targetscale; - - *terminationtype = 0; - - nmain = nn; - nslack = dnic+snic; - ntotal = nmain+nslack; - nectotal = dnec+snec; - nictotal = dnic+snic; - ktotal = dnec+dnic+snec+snic; - rho = settings->rho; - epsx = settings->epsx; - requestedfeasdecrease = 0.33; - maxrho = 1.0E12; - if( ae_fp_less_eq(epsx,(double)(0)) ) - { - epsx = 1.0E-9; - } - - /* - * Integrity checks - */ - if( snec+snic>0 ) - { - ae_assert(scleic->matrixtype==1, "QPDENSEAULOptimize: unexpected sparse matrix format", _state); - ae_assert(scleic->m==snec+snic, "QPDENSEAULOptimize: unexpected sparse matrix size", _state); - ae_assert(scleic->n==nmain+1, "QPDENSEAULOptimize: unexpected sparse matrix size", _state); - } - - /* - * Prepare - */ - state->repinneriterationscount = 0; - state->repouteriterationscount = 0; - state->repncholesky = 0; - state->repnmv = 0; - state->repnwrkchanges = 0; - state->repnwrk0 = 0; - state->repnwrk1 = 0; - state->repnwrkf = 0; - *terminationtype = 0; - ivectorsetlengthatleast(&state->cidx, ktotal, _state); - rvectorsetlengthatleast(&state->nulc, ktotal, _state); - rvectorsetlengthatleast(&state->nulcest, ktotal, _state); - rvectorsetlengthatleast(&state->exb, ntotal, _state); - rvectorsetlengthatleast(&state->exxc, ntotal, _state); - rvectorsetlengthatleast(&state->exxorigin, ntotal, _state); - rvectorsetlengthatleast(&state->exbndl, ntotal, _state); - rvectorsetlengthatleast(&state->exbndu, ntotal, _state); - rvectorsetlengthatleast(&state->exscale, ntotal, _state); - rvectorsetlengthatleast(&state->tmp0, ntotal, _state); - rvectorsetlengthatleast(&state->nicerr, nictotal, _state); - ivectorsetlengthatleast(&state->nicnact, nictotal, _state); - - /* - * Allocate Lagrange multipliers, fill by default values (zeros) - */ - rvectorsetlengthatleast(lagbc, nmain, _state); - rvectorsetlengthatleast(laglc, ktotal, _state); - for(i=0; i<=nmain-1; i++) - { - lagbc->ptr.p_double[i] = 0.0; - } - for(i=0; i<=ktotal-1; i++) - { - laglc->ptr.p_double[i] = 0.0; - } - - /* - * Prepare scaled/shifted model in dense format - input parameters - * are converted and stored in State.SclSftA/B/HasBndL/HasBndU/BndL/BndU/CLEIC/XC/CScales - */ - qpdenseaulsolver_scaleshiftoriginalproblem(a, sparsea, akind, sparseaupper, b, bndl, bndu, s, xorigin, nmain, cleic, dnec, dnic, scleic, snec, snic, renormlc, state, xs, _state); - - /* - * Normalize model in such way that norm(A)~1 (very roughly) - * - * We have two lower bounds for sigma_max(A): - * * first estimate is provided by Frobenius norm, it is equal to ANorm/NMain - * * second estimate is provided by max(CAC) - * - * We select largest one of these estimates, because using just one - * of them is prone to different failure modes. Then, we divide A and B - * by this estimate. - */ - targetscale = qpdenseaulsolver_normalizequadraticterm(&state->sclsfta, &state->sclsftb, nmain, &state->sclsftcleic, nectotal, nictotal, renormlc, &state->tmp2, _state); - - /* - * Select working set of inequality constraints. - * - * Although it is possible to process all inequality constraints - * at once, in one large batch, some QP problems have NIC>>N constraints, - * but only minor fraction of them is inactive in the solution. - * - * Because algorithm running time is O((N+NEC+NIC)^3), we can - * save a lot of time if we process only those inequality constraints - * which need activation. Generally, NECsclsfta, nmain, &state->sclsftcleic, nectotal, nictotal, &state->tmp0, &state->tmp2, &nicwork, &allowwseviction, _state); - kwork = nectotal+nicwork; - nwork = nmain+nicwork; - state->repnwrk0 = nicwork; - for(i=0; i<=nicwork-1; i++) - { - state->nicnact.ptr.p_int[i] = 1; - } - for(i=nicwork; i<=nictotal-1; i++) - { - state->nicnact.ptr.p_int[i] = 0; - } - for(i=0; i<=ktotal-1; i++) - { - state->cidx.ptr.p_int[i] = i; - } - - /* - * Perform outer iteration - */ - for(i=0; i<=ktotal-1; i++) - { - state->nulc.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=ntotal-1; i++) - { - state->exscale.ptr.p_double[i] = 1.0; - state->exxorigin.ptr.p_double[i] = 0.0; - } - qpdenseaulsolver_generateexinitialpoint(&state->sclsftxc, nmain, nslack, &state->exxc, _state); - goodcounter = 0; - stagnationcounter = 0; - feaserr = ae_maxrealnumber; - for(outeridx=0; outeridx<=settings->outerits-1; outeridx++) - { - - /* - * Repeat loop until working set stabilizes. - */ - do - { - - /* - * Preallocate space for ExA and for QQP solver; we do not allocate - * array[NTotal,NTotal] from the start because NTotal can be much - * larger than NMain for problems with large amount of inequality - * constraints, and we usually need NWork=O(NMain). - * - * NOTE: for the sake of simplicity, 1-dimensional arrays were - * preallocated to the maximum size required (NTotal). - */ - if( state->exa.rowsexa.colsexa, i, i, _state); - } - qqppreallocategrowdense(&state->qqpbuf, nwork, i, _state); - - /* - * Generate penalized quadratic model - */ - qpdenseaulsolver_generateexmodel(&state->sclsfta, &state->sclsftb, nmain, &state->sclsftbndl, &state->sclsfthasbndl, &state->sclsftbndu, &state->sclsfthasbndu, &state->sclsftcleic, nectotal, nicwork, &state->nulc, rho, &state->exa, &state->exb, &state->exbndl, &state->exbndu, &state->tmp2, _state); - - /* - * Solve extended QP problem subject to current working set of general - * inequality constraints. - */ - qqploaddefaults(nwork, &state->qqpsettingsuser, _state); - state->qqpsettingsuser.maxouterits = 50; - state->qqpsettingsuser.epsg = 0.0; - state->qqpsettingsuser.epsf = 0.0; - state->qqpsettingsuser.epsx = 0.01*epsx; - state->qqpsettingsuser.cnphase = ae_true; - qqpoptimize(&state->dummycqm, &state->dummysparse, &state->exa, 2, ae_true, &state->exb, &state->exbndl, &state->exbndu, &state->exscale, &state->exxorigin, nwork, &state->qqpsettingsuser, &state->qqpbuf, &state->exxc, &k, _state); - state->repncholesky = state->repncholesky+state->qqpbuf.repncholesky; - - /* - * Evaluate violation of constraints - */ - for(i=0; i<=nictotal-1; i++) - { - v = ae_v_dotproduct(&state->sclsftcleic.ptr.pp_double[nectotal+i][0], 1, &state->exxc.ptr.p_double[0], 1, ae_v_len(0,nmain-1)); - v = v-state->sclsftcleic.ptr.pp_double[nectotal+i][nmain]; - state->nicerr.ptr.p_double[i] = v; - } - - /* - * Working set expansion: - * * select limited amount of most violated constraints - * * perform permutation of non-work constraints such that - * candidate constraint is first the list (update XC and NuLC) - * * increase working set size by 1 - * * increase activation count for new constraint by 1 (this count - * is used later by working set eviction phase) - * * repeat - * - * NOTE: we use selection sort algorithm because its O(NAdded*NWork) cost - * is still comparable to the cost of constraints evaluation - */ - workingsetextended = ae_false; - i = 0; - while(ae_fp_less((double)(i),1+qpdenseaulsolver_expansionratio*nmain)&&nicworknicerr.ptr.p_double[j],state->nicerr.ptr.p_double[k]) ) - { - k = j; - } - } - - /* - * If violation is positive, add it - */ - if( ae_fp_greater(state->nicerr.ptr.p_double[k],(double)(0)) ) - { - swaprows(&state->sclsftcleic, nectotal+nicwork, nectotal+k, -1, _state); - swapelements(&state->nicerr, nicwork, k, _state); - swapelementsi(&state->nicnact, nicwork, k, _state); - swapelementsi(&state->cidx, nectotal+nicwork, nectotal+k, _state); - swapelements(&state->cscales, nectotal+nicwork, nectotal+k, _state); - state->exxc.ptr.p_double[nmain+nicwork] = 0.0; - state->nulc.ptr.p_double[nectotal+nicwork] = 0.0; - state->nicnact.ptr.p_int[nicwork] = state->nicnact.ptr.p_int[nicwork]+1; - inc(&nicwork, _state); - inc(&nwork, _state); - inc(&kwork, _state); - inc(&i, _state); - workingsetextended = ae_true; - } - else - { - break; - } - } - - /* - * Working set eviction: - * * select constraints which are (1) far away from the - * boundary, AND (2) has less than two activation attempts - * (if constraint is regularly activated/deactivated, we keep - * it in the working set no matter what) - * * remove such constraints from the working set one by one - */ - if( allowwseviction ) - { - for(k=nicwork-1; k>=0; k--) - { - if( ae_fp_less(state->nicerr.ptr.p_double[k],qpdenseaulsolver_evictionlevel)&&state->nicnact.ptr.p_int[k]<=1 ) - { - swaprows(&state->sclsftcleic, nectotal+nicwork-1, nectotal+k, -1, _state); - swapelementsi(&state->cidx, nectotal+nicwork-1, nectotal+k, _state); - swapelements(&state->cscales, nectotal+nicwork-1, nectotal+k, _state); - swapelements(&state->nicerr, nicwork-1, k, _state); - swapelementsi(&state->nicnact, nicwork-1, k, _state); - swapelements(&state->exxc, nmain+nicwork-1, nmain+k, _state); - swapelements(&state->nulc, nectotal+nicwork-1, nectotal+k, _state); - dec(&nicwork, _state); - dec(&nwork, _state); - dec(&kwork, _state); - } - } - } - - /* - * Report working set statistics - */ - if( state->repnwrk1==0 ) - { - state->repnwrk1 = nicwork; - } - state->repnwrkf = nicwork; - if( workingsetextended ) - { - inc(&state->repnwrkchanges, _state); - } - } - while(workingsetextended); - - /* - * Estimate Lagrange multipliers using alternative algorithm - */ - ae_v_move(&state->nulcest.ptr.p_double[0], 1, &state->nulc.ptr.p_double[0], 1, ae_v_len(0,kwork-1)); - qpdenseaulsolver_updatelagrangemultipliers(&state->sclsfta, &state->sclsftb, nmain, &state->sclsftbndl, &state->sclsfthasbndl, &state->sclsftbndu, &state->sclsfthasbndu, &state->sclsftcleic, nectotal, nicwork, &state->exxc, &state->nulcest, state, _state); - - /* - * Update XC and Lagrange multipliers - */ - feaserrprev = feaserr; - feaserr = (double)(0); - for(i=0; i<=kwork-1; i++) - { - - /* - * Calculate I-th feasibility error in V using formula for distance - * between point and line (here we calculate actual distance between - * XN and hyperplane Ci'*XN=Bi, which is different from error Ci'*XN-Bi). - */ - v = (double)(0); - vv = (double)(0); - for(j=0; j<=nmain-1; j++) - { - v = v+state->sclsftcleic.ptr.pp_double[i][j]*state->exxc.ptr.p_double[j]; - vv = vv+ae_sqr(state->sclsftcleic.ptr.pp_double[i][j], _state); - } - if( i>=nectotal ) - { - v = v+state->exxc.ptr.p_double[nmain+(i-nectotal)]; - vv = vv+ae_sqr((double)(1), _state); - } - v = v-state->sclsftcleic.ptr.pp_double[i][nmain]; - vv = coalesce(vv, (double)(1), _state); - v = v/ae_sqrt(vv, _state); - - /* - * Calculate magnitude of Lagrangian update (and Lagrangian parameters themselves) - */ - feaserr = feaserr+ae_sqr(v, _state); - state->nulc.ptr.p_double[i] = state->nulcest.ptr.p_double[i]; - } - feaserr = ae_sqrt(feaserr, _state); - if( ae_fp_less(feaserr,epsx) ) - { - inc(&goodcounter, _state); - } - else - { - goodcounter = 0; - } - if( ae_fp_greater(feaserr,feaserrprev*requestedfeasdecrease) ) - { - inc(&stagnationcounter, _state); - } - else - { - stagnationcounter = 0; - } - if( goodcounter>=2 ) - { - break; - } - if( stagnationcounter>=2 ) - { - rho = ae_minreal(rho*10.0, maxrho, _state); - } - else - { - rho = ae_minreal(rho*1.41, maxrho, _state); - } - } - - /* - * Convert Lagrange multipliers from internal format to one expected - * by caller: - * * reorder multipliers for linear constraints - * * compute residual from gradient+linearconstraints - * * compute multipliers for box constraints from residual - * * rescale everything - */ - for(i=0; i<=nectotal+nicwork-1; i++) - { - laglc->ptr.p_double[state->cidx.ptr.p_int[i]] = -state->nulc.ptr.p_double[i]*targetscale/state->cscales.ptr.p_double[i]; - } - rvectorsetlengthatleast(&state->tmpg, nmain, _state); - for(i=0; i<=nmain-1; i++) - { - v = state->sclsftb.ptr.p_double[i]; - for(j=0; j<=nmain-1; j++) - { - v = v+state->sclsfta.ptr.pp_double[i][j]*state->exxc.ptr.p_double[j]; - } - state->tmpg.ptr.p_double[i] = v; - } - rmatrixgemv(nmain, nectotal+nicwork, -1.0, &state->sclsftcleic, 0, 0, 1, &state->nulc, 0, 1.0, &state->tmpg, 0, _state); - for(i=0; i<=nmain-1; i++) - { - if( (state->sclsfthasbndl.ptr.p_bool[i]&&ae_fp_eq(state->exxc.ptr.p_double[i],state->sclsftbndl.ptr.p_double[i]))||(state->sclsfthasbndu.ptr.p_bool[i]&&ae_fp_eq(state->exxc.ptr.p_double[i],state->sclsftbndu.ptr.p_double[i])) ) - { - lagbc->ptr.p_double[i] = -state->tmpg.ptr.p_double[i]; - } - } - for(i=0; i<=nmain-1; i++) - { - lagbc->ptr.p_double[i] = lagbc->ptr.p_double[i]*targetscale/s->ptr.p_double[i]; - } - - /* - * Unpack results. - * - * Add XOrigin to XC and make sure that boundary constraints are - * satisfied. - */ - for(i=0; i<=nmain-1; i++) - { - - /* - * Unscale/unshift - */ - xs->ptr.p_double[i] = s->ptr.p_double[i]*state->exxc.ptr.p_double[i]+xorigin->ptr.p_double[i]; - - /* - * Make sure that point is feasible w.r.t. box constraints. - * Enforce box constraints which were active in the scaled/shifted solution. - */ - if( state->sclsfthasbndl.ptr.p_bool[i] ) - { - if( ae_fp_less(xs->ptr.p_double[i],bndl->ptr.p_double[i]) ) - { - xs->ptr.p_double[i] = bndl->ptr.p_double[i]; - } - if( ae_fp_eq(state->exxc.ptr.p_double[i],state->sclsftbndl.ptr.p_double[i]) ) - { - xs->ptr.p_double[i] = bndl->ptr.p_double[i]; - } - } - if( state->sclsfthasbndu.ptr.p_bool[i] ) - { - if( ae_fp_greater(xs->ptr.p_double[i],bndu->ptr.p_double[i]) ) - { - xs->ptr.p_double[i] = bndu->ptr.p_double[i]; - } - if( ae_fp_eq(state->exxc.ptr.p_double[i],state->sclsftbndu.ptr.p_double[i]) ) - { - xs->ptr.p_double[i] = bndu->ptr.p_double[i]; - } - } - } - *terminationtype = 2; -} - - -/************************************************************************* -This function generates box-constrained QP problem, which is penalized and -augmented formulation of original linearly constrained problem - - -- ALGLIB -- - Copyright 23.02.2017 by Bochkanov Sergey -*************************************************************************/ -static void qpdenseaulsolver_generateexmodel(/* Real */ ae_matrix* sclsfta, - /* Real */ ae_vector* sclsftb, - ae_int_t nmain, - /* Real */ ae_vector* sclsftbndl, - /* Boolean */ ae_vector* sclsfthasbndl, - /* Real */ ae_vector* sclsftbndu, - /* Boolean */ ae_vector* sclsfthasbndu, - /* Real */ ae_matrix* sclsftcleic, - ae_int_t sclsftnec, - ae_int_t sclsftnic, - /* Real */ ae_vector* nulc, - double rho, - /* Real */ ae_matrix* exa, - /* Real */ ae_vector* exb, - /* Real */ ae_vector* exbndl, - /* Real */ ae_vector* exbndu, - /* Real */ ae_matrix* tmp2, - ae_state *_state) -{ - ae_int_t nslack; - ae_int_t ntotal; - ae_int_t i; - ae_int_t j; - double v; - - - nslack = sclsftnic; - ntotal = nmain+nslack; - - /* - * Integrity check for properly preallocated storage - */ - ae_assert(exa->rows>=ntotal&&exa->cols>=ntotal, "QPDenseAUL.GenerateExModel - integrity check failed", _state); - ae_assert((exb->cnt>=ntotal&&exbndl->cnt>=ntotal)&&exbndu->cnt>=ntotal, "QPDenseAUL.GenerateExModel - integrity check failed", _state); - - /* - * Primary quadratic term - */ - for(i=0; i<=ntotal-1; i++) - { - for(j=i; j<=ntotal-1; j++) - { - exa->ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=nmain-1; i++) - { - for(j=i; j<=nmain-1; j++) - { - exa->ptr.pp_double[i][j] = sclsfta->ptr.pp_double[i][j]; - } - } - - /* - * Primary linear term - */ - for(i=0; i<=ntotal-1; i++) - { - exb->ptr.p_double[i] = (double)(0); - } - for(i=0; i<=nmain-1; i++) - { - exb->ptr.p_double[i] = sclsftb->ptr.p_double[i]; - } - - /* - * Box constraints - move primary, add slack - */ - for(i=0; i<=nmain-1; i++) - { - if( sclsfthasbndl->ptr.p_bool[i] ) - { - exbndl->ptr.p_double[i] = sclsftbndl->ptr.p_double[i]; - } - else - { - exbndl->ptr.p_double[i] = _state->v_neginf; - } - if( sclsfthasbndu->ptr.p_bool[i] ) - { - exbndu->ptr.p_double[i] = sclsftbndu->ptr.p_double[i]; - } - else - { - exbndu->ptr.p_double[i] = _state->v_posinf; - } - } - for(i=nmain; i<=ntotal-1; i++) - { - exbndl->ptr.p_double[i] = (double)(0); - exbndu->ptr.p_double[i] = _state->v_posinf; - } - - /* - * Handle equality constraints: - * * modify quadratic term - * * modify linear term - * * add Lagrangian term - */ - rmatrixsetlengthatleast(tmp2, sclsftnec+sclsftnic, ntotal, _state); - for(i=0; i<=sclsftnec+sclsftnic-1; i++) - { - - /* - * Given constraint row ci and right hand side ri, - * I-th quadratic constraint adds penalty term - * - * 0.5*Rho*(ci'*x-ri)^2 = - * = 0.5*Rho*(ci'*x-ri)^T*(ci'*x-ri) = - * = 0.5*Rho*(x'*ci-ri')*(ci'*x-ri) = - * = 0.5*Rho*(x'*ci*ci'*x - ri'*ci'*x - x'*ci*ri + ri'*ri ) - * = 0.5*Rho*(x'*(ci*ci')*x - 2*ri*(ci'*x) + ri^2 ) - * - * Thus, quadratic term is updated by - * - * 0.5*Rho*(ci*ci') - * - * (with actual update to ExA being performed without 0.5 - * multiplier because entire matrix is post-multipliead by 0.5) - * and linear term receives update - * - * -Rho*ri*ci - * - * Similaryly, lagrangian term is -NUi*(ci'*x-ri), - * so linear term is updated by - * - * -NUi*ci - * - * Because our model does not take into account constant term, - * we calculate just quadratic and linear terms. - */ - ae_v_move(&tmp2->ptr.pp_double[i][0], 1, &sclsftcleic->ptr.pp_double[i][0], 1, ae_v_len(0,nmain-1)); - for(j=nmain; j<=ntotal-1; j++) - { - tmp2->ptr.pp_double[i][j] = (double)(0); - } - if( i>=sclsftnec ) - { - tmp2->ptr.pp_double[i][nmain+i-sclsftnec] = 1.0; - } - v = -rho*sclsftcleic->ptr.pp_double[i][nmain]; - ae_v_addd(&exb->ptr.p_double[0], 1, &tmp2->ptr.pp_double[i][0], 1, ae_v_len(0,ntotal-1), v); - v = -nulc->ptr.p_double[i]; - ae_v_addd(&exb->ptr.p_double[0], 1, &tmp2->ptr.pp_double[i][0], 1, ae_v_len(0,ntotal-1), v); - } - rmatrixsyrk(ntotal, sclsftnec+sclsftnic, rho, tmp2, 0, 0, 2, 1.0, exa, 0, 0, ae_true, _state); -} - - -/************************************************************************* -This function generates initial point for "extended" box-constrained QP -problem. - - -- ALGLIB -- - Copyright 23.02.2017 by Bochkanov Sergey -*************************************************************************/ -static void qpdenseaulsolver_generateexinitialpoint(/* Real */ ae_vector* sclsftxc, - ae_int_t nmain, - ae_int_t nslack, - /* Real */ ae_vector* exxc, - ae_state *_state) -{ - ae_int_t ntotal; - ae_int_t i; - - - ntotal = nmain+nslack; - for(i=0; i<=ntotal-1; i++) - { - exxc->ptr.p_double[i] = (double)(0); - } - for(i=0; i<=nmain-1; i++) - { - exxc->ptr.p_double[i] = sclsftxc->ptr.p_double[i]; - } -} - - -/************************************************************************* -This function estimates Lagrange multipliers for scaled-shifted QP problem -(here "scaled-shifted" means that we performed variable scaling and -subtracted origin) given by quadratic term A, linear term B, box constraints -and linear constraint matrix. - -It is assumed that all linear constraints are equality ones, with first -NEC ones being constraints without slack variables, and next NIC ones -having slack variables. The only inequality constraints we have are box -ones, with first NMain ones being "general" box constraints, and next NIC -ones being non-negativity constraints (not specified explicitly). - -We also make use of the current point XC, which is used to determine active -box constraints. - -Actual QP problem size is NMain+NIC, but some parameters have lower -dimensionality. - -Parameters sizes are: -* A is assumed to be array[NMain,NMain] -* B is assumed to be array[NMain] -* BndL, BndU are array[NMain] -* CLEIC is array[NEC+NIC,NMain+1] (last item in a row containts right part) -* ExXC is array[NMain+NIC], holds current point -* NuLCEst is array[NEC+NIC], holds initial values of Lagrange coeffs - -On exit NuLCEst is updated with new estimate of Lagrange multipliers. - - -- ALGLIB -- - Copyright 23.02.2017 by Bochkanov Sergey -*************************************************************************/ -static void qpdenseaulsolver_updatelagrangemultipliers(/* Real */ ae_matrix* sclsfta, - /* Real */ ae_vector* sclsftb, - ae_int_t nmain, - /* Real */ ae_vector* sclsftbndl, - /* Boolean */ ae_vector* sclsfthasbndl, - /* Real */ ae_vector* sclsftbndu, - /* Boolean */ ae_vector* sclsfthasbndu, - /* Real */ ae_matrix* sclsftcleic, - ae_int_t sclsftnec, - ae_int_t sclsftnic, - /* Real */ ae_vector* exxc, - /* Real */ ae_vector* nulcest, - qpdenseaulbuffers* buffers, - ae_state *_state) -{ - ae_int_t nslack; - ae_int_t ntotal; - ae_int_t ktotal; - ae_int_t nqrrows; - ae_int_t nqrcols; - ae_int_t i; - ae_int_t j; - double lambdareg; - double mxdiag; - double v; - ae_bool isactive; - - - nslack = sclsftnic; - ntotal = nmain+nslack; - ktotal = sclsftnec+sclsftnic; - - /* - * Given current point ExXC, we can determine active and inactive - * constraints. After we drop inactive inequality constraints, we - * have equality-only constrained QP problem, with mix of general - * linear equality constraints and "simple" constraints Xi=Ci. - * - * Problem min(0.5*x'*A*x + b'*x) s.t. C*x=d (general linear - * constraints) can be solved by explicitly writing out Lagrange - * equations: - * - * [ A C' ] [ X ] [ -b] - * [ ] [ ] = [ ] - * [ C ] [ L ] [ d ] - * - * or - * - * [ X ] - * A1* [ ] = b1 - * [ L ] - * - * where X stands for solution itself, and L stands for Lagrange - * multipliers. It can be easily solved with direct linear solver. - * However, such formulation does not account for "simple" equality - * constraints on variables. It is possible to include "simple" - * constraints into "general" ones (i.e. append (0 ... 0 -1 0 ... 0)' - * to the constraint matrix), but it will increase problem - * size. - * - * Another approach is to use initial values of X and L (X0 and L0) - * as starting point, and to solve for "offset" from (X0, L0): - * - * [ X0+X1 ] - * A1*[ ] = b1 - * [ L0+L1 ] - * - * or - * - * [ X1 ] [ X0 ] - * A1*[ ] = b1 - A1*[ ] - * [ L1 ] [ L0 ] - * - * In such formulation components of X1 which correspond to active - * constraints on variables are "frozen" at value 0 (because we have - * equality constraint, offset from constrained value have to be zero). - * - * Thus, we can rewrite corresponding columns of A1 with zeros - and - * use this space to store (0 ... 0 -1 0 ... 0)', which is used to - * account for Lagrange multipliers for "simple" constraints. - */ - nqrcols = ntotal+ktotal; - nqrrows = nqrcols; - rvectorsetlengthatleast(&buffers->qrsv0, nqrcols, _state); - rvectorsetlengthatleast(&buffers->qrsvx1, nqrcols, _state); - for(i=0; i<=ntotal-1; i++) - { - buffers->qrsv0.ptr.p_double[i] = exxc->ptr.p_double[i]; - } - for(i=0; i<=ktotal-1; i++) - { - buffers->qrsv0.ptr.p_double[ntotal+i] = nulcest->ptr.p_double[i]; - } - rmatrixsetlengthatleast(&buffers->qrkkt, nqrcols+nqrcols, nqrcols+1, _state); - rvectorsetlengthatleast(&buffers->qrrightpart, nqrcols+nqrcols, _state); - lambdareg = 1.0E-8; - for(;;) - { - - /* - * Initialize matrix A1 and right part b1 with zeros - */ - for(i=0; i<=buffers->qrkkt.rows-1; i++) - { - for(j=0; j<=buffers->qrkkt.cols-1; j++) - { - buffers->qrkkt.ptr.pp_double[i][j] = (double)(0); - } - buffers->qrrightpart.ptr.p_double[i] = (double)(0); - } - - /* - * Append quadratic term (note: we implicitly add NSlack zeros to - * A and b). - */ - mxdiag = (double)(0); - for(i=0; i<=nmain-1; i++) - { - for(j=0; j<=nmain-1; j++) - { - buffers->qrkkt.ptr.pp_double[i][j] = sclsfta->ptr.pp_double[i][j]; - } - buffers->qrrightpart.ptr.p_double[i] = -sclsftb->ptr.p_double[i]; - mxdiag = ae_maxreal(mxdiag, ae_fabs(sclsfta->ptr.pp_double[i][i], _state), _state); - } - mxdiag = coalesce(mxdiag, (double)(1), _state); - - /* - * Append general linear constraints - */ - for(i=0; i<=ktotal-1; i++) - { - for(j=0; j<=nmain-1; j++) - { - buffers->qrkkt.ptr.pp_double[ntotal+i][j] = -sclsftcleic->ptr.pp_double[i][j]; - buffers->qrkkt.ptr.pp_double[j][ntotal+i] = -sclsftcleic->ptr.pp_double[i][j]; - } - if( i>=sclsftnec ) - { - buffers->qrkkt.ptr.pp_double[ntotal+i][nmain+(i-sclsftnec)] = (double)(-1); - buffers->qrkkt.ptr.pp_double[nmain+(i-sclsftnec)][ntotal+i] = (double)(-1); - } - buffers->qrrightpart.ptr.p_double[ntotal+i] = -sclsftcleic->ptr.pp_double[i][nmain]; - } - - /* - * Append regularizer to the bottom of the matrix - * (it will be factored in during QR decomposition) - */ - if( ae_fp_greater(lambdareg,(double)(0)) ) - { - nqrrows = nqrcols+nqrcols; - for(i=0; i<=nqrcols-1; i++) - { - buffers->qrkkt.ptr.pp_double[nqrcols+i][i] = lambdareg*mxdiag; - } - } - - /* - * Subtract reference point (X0,L0) from the system - */ - for(i=0; i<=nqrcols-1; i++) - { - v = ae_v_dotproduct(&buffers->qrkkt.ptr.pp_double[i][0], 1, &buffers->qrsv0.ptr.p_double[0], 1, ae_v_len(0,nqrcols-1)); - buffers->qrrightpart.ptr.p_double[i] = buffers->qrrightpart.ptr.p_double[i]-v; - } - - /* - * Handle active "simple" equality constraints - */ - for(i=0; i<=ntotal-1; i++) - { - isactive = ae_false; - if( iptr.p_bool[i]&&ae_fp_eq(exxc->ptr.p_double[i],sclsftbndl->ptr.p_double[i]))||(sclsfthasbndu->ptr.p_bool[i]&&ae_fp_eq(exxc->ptr.p_double[i],sclsftbndu->ptr.p_double[i]))) ) - { - isactive = ae_true; - } - if( i>=nmain&&ae_fp_eq(exxc->ptr.p_double[i],0.0) ) - { - isactive = ae_true; - } - if( !isactive ) - { - continue; - } - for(j=0; j<=nqrrows-1; j++) - { - buffers->qrkkt.ptr.pp_double[j][i] = (double)(0); - } - buffers->qrkkt.ptr.pp_double[i][i] = (double)(-1); - } - - /* - * Solve via QR decomposition: - * * append right part to the system matrix - * * perform QR decomposition of the extended matrix (right part is implicitly - * multiplied by Q during decomposition; believe me, it works!) - * * check condition number, increase regularization value if necessary and retry - * * solve triangular system, break iteration - */ - for(i=0; i<=nqrrows-1; i++) - { - buffers->qrkkt.ptr.pp_double[i][nqrcols] = buffers->qrrightpart.ptr.p_double[i]; - } - rmatrixqr(&buffers->qrkkt, nqrrows, nqrcols+1, &buffers->qrtau, _state); - if( ae_fp_less_eq(rmatrixtrrcond1(&buffers->qrkkt, nqrcols, ae_true, ae_false, _state),1000*ae_machineepsilon) ) - { - lambdareg = coalesce(10*lambdareg, 1.0E-13, _state); - continue; - } - for(i=nqrcols-1; i>=0; i--) - { - v = buffers->qrkkt.ptr.pp_double[i][nqrcols]; - for(j=i+1; j<=nqrcols-1; j++) - { - v = v-buffers->qrkkt.ptr.pp_double[i][j]*buffers->qrsvx1.ptr.p_double[j]; - } - buffers->qrsvx1.ptr.p_double[i] = v/buffers->qrkkt.ptr.pp_double[i][i]; - } - break; - } - - /* - * Update Lagrange coefficients - */ - for(i=0; i<=ktotal-1; i++) - { - nulcest->ptr.p_double[i] = buffers->qrsv0.ptr.p_double[ntotal+i]+buffers->qrsvx1.ptr.p_double[ntotal+i]; - } -} - - -/************************************************************************* -This function generates scaled (by S) and shifted (by XC) reformulation of -the original problem. - -INPUT PARAMETERS: - DenseA - for dense problems (AKind=0), A-term of CQM object - contains system matrix. Other terms are unspecified - and should not be referenced. - SparseA - for sparse problems (AKind=1), CRS format - AKind - sparse matrix format: - * 0 for dense matrix - * 1 for sparse matrix - SparseUpper - which triangle of SparseAC stores matrix - upper or - lower one (for dense matrices this parameter is not - actual). - B - linear term, array[N] - BndL - lower bound, array[N] - BndU - upper bound, array[N] - S - scale vector, array[NC]: - * I-th element contains scale of I-th variable, - * SC[I]>0 - XOrigin - origin term, array[NC]. Can be zero. - N - number of variables in the original formulation (no - slack variables). - CLEIC - dense linear equality/inequality constraints. Equality - constraints come first. - NEC, NIC - number of dense equality/inequality constraints. - SCLEIC - sparse linear equality/inequality constraints. Equality - constraints come first. - SNEC, SNIC - number of sparse equality/inequality constraints. - RenormLC - whether constraints should be renormalized (recommended) - or used "as is". - Settings - QPDENSEAULSettings object initialized by one of the initialization - functions. - State - object which stores temporaries - XS - initial point, array[NC] - - -On output, following fields of the State structure are modified: -* SclSftA - array[NMain,NMain], quadratic term, both triangles -* SclSftB - array[NMain], linear term -* SclSftXC - array[NMain], initial point -* SclSftHasBndL, - SclSftHasBndU, - SclSftBndL, - SclSftBndU - array[NMain], lower/upper bounds -* SclSftCLEIC - array[KTotal,NMain+1], general linear constraints - -NOTE: State.Tmp2 is used to store temporary array[NMain,NMain] - - -- ALGLIB -- - Copyright 01.10.2017 by Bochkanov Sergey -*************************************************************************/ -static void qpdenseaulsolver_scaleshiftoriginalproblem(convexquadraticmodel* a, - sparsematrix* sparsea, - ae_int_t akind, - ae_bool sparseaupper, - /* Real */ ae_vector* b, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - ae_int_t nmain, - /* Real */ ae_matrix* cleic, - ae_int_t dnec, - ae_int_t dnic, - sparsematrix* scleic, - ae_int_t snec, - ae_int_t snic, - ae_bool renormlc, - qpdenseaulbuffers* state, - /* Real */ ae_vector* xs, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t j0; - ae_int_t j1; - double v; - double vv; - ae_int_t ktotal; - - - ae_assert(akind==0||akind==1, "QPDENSEAULOptimize: unexpected AKind", _state); - ktotal = dnec+dnic+snec+snic; - rmatrixsetlengthatleast(&state->sclsfta, nmain, nmain, _state); - rvectorsetlengthatleast(&state->sclsftb, nmain, _state); - rvectorsetlengthatleast(&state->sclsftxc, nmain, _state); - rvectorsetlengthatleast(&state->sclsftbndl, nmain, _state); - rvectorsetlengthatleast(&state->sclsftbndu, nmain, _state); - bvectorsetlengthatleast(&state->sclsfthasbndl, nmain, _state); - bvectorsetlengthatleast(&state->sclsfthasbndu, nmain, _state); - rmatrixsetlengthatleast(&state->sclsftcleic, ktotal, nmain+1, _state); - rvectorsetlengthatleast(&state->cscales, ktotal, _state); - if( akind==0 ) - { - - /* - * Extract dense A and scale - */ - cqmgeta(a, &state->tmp2, _state); - for(i=0; i<=nmain-1; i++) - { - for(j=0; j<=nmain-1; j++) - { - state->sclsfta.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=nmain-1; i++) - { - for(j=i; j<=nmain-1; j++) - { - v = state->tmp2.ptr.pp_double[i][j]*s->ptr.p_double[i]*s->ptr.p_double[j]; - state->sclsfta.ptr.pp_double[i][j] = v; - state->sclsfta.ptr.pp_double[j][i] = v; - } - } - } - if( akind==1 ) - { - - /* - * Extract sparse A and scale - */ - ae_assert(sparsea->matrixtype==1, "QPDENSEAULOptimize: unexpected sparse matrix format", _state); - ae_assert(sparsea->m==nmain, "QPDENSEAULOptimize: unexpected sparse matrix size", _state); - ae_assert(sparsea->n==nmain, "QPDENSEAULOptimize: unexpected sparse matrix size", _state); - for(i=0; i<=nmain-1; i++) - { - for(j=0; j<=nmain-1; j++) - { - state->sclsfta.ptr.pp_double[i][j] = (double)(0); - } - } - if( sparseaupper ) - { - for(i=0; i<=nmain-1; i++) - { - if( sparsea->didx.ptr.p_int[i]!=sparsea->uidx.ptr.p_int[i] ) - { - state->sclsfta.ptr.pp_double[i][i] = sparsea->vals.ptr.p_double[sparsea->didx.ptr.p_int[i]]*s->ptr.p_double[i]*s->ptr.p_double[i]; - } - j0 = sparsea->uidx.ptr.p_int[i]; - j1 = sparsea->ridx.ptr.p_int[i+1]-1; - for(j=j0; j<=j1; j++) - { - k = sparsea->idx.ptr.p_int[j]; - v = sparsea->vals.ptr.p_double[j]*s->ptr.p_double[i]*s->ptr.p_double[k]; - state->sclsfta.ptr.pp_double[i][k] = v; - state->sclsfta.ptr.pp_double[k][i] = v; - } - } - } - else - { - for(i=0; i<=nmain-1; i++) - { - if( sparsea->didx.ptr.p_int[i]!=sparsea->uidx.ptr.p_int[i] ) - { - state->sclsfta.ptr.pp_double[i][i] = sparsea->vals.ptr.p_double[sparsea->didx.ptr.p_int[i]]*s->ptr.p_double[i]*s->ptr.p_double[i]; - } - j0 = sparsea->ridx.ptr.p_int[i]; - j1 = sparsea->didx.ptr.p_int[i]-1; - for(j=j0; j<=j1; j++) - { - k = sparsea->idx.ptr.p_int[j]; - v = sparsea->vals.ptr.p_double[j]*s->ptr.p_double[i]*s->ptr.p_double[k]; - state->sclsfta.ptr.pp_double[i][k] = v; - state->sclsfta.ptr.pp_double[k][i] = v; - } - } - } - } - for(i=0; i<=nmain-1; i++) - { - state->sclsftb.ptr.p_double[i] = b->ptr.p_double[i]*s->ptr.p_double[i]; - state->sclsftxc.ptr.p_double[i] = (xs->ptr.p_double[i]-xorigin->ptr.p_double[i])/s->ptr.p_double[i]; - state->sclsfthasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state); - state->sclsfthasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state); - state->sclsftbndl.ptr.p_double[i] = bndl->ptr.p_double[i]; - state->sclsftbndu.ptr.p_double[i] = bndu->ptr.p_double[i]; - } - scaleshiftbcinplace(s, xorigin, &state->sclsftbndl, &state->sclsftbndu, nmain, _state); - for(i=0; i<=ktotal-1; i++) - { - for(j=0; j<=nmain; j++) - { - state->sclsftcleic.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=dnec-1; i++) - { - for(j=0; j<=nmain-1; j++) - { - v = cleic->ptr.pp_double[i][j]*s->ptr.p_double[j]; - state->sclsftcleic.ptr.pp_double[i][j] = v; - } - state->sclsftcleic.ptr.pp_double[i][nmain] = cleic->ptr.pp_double[i][nmain]; - } - for(i=0; i<=dnic-1; i++) - { - for(j=0; j<=nmain-1; j++) - { - v = cleic->ptr.pp_double[dnec+i][j]*s->ptr.p_double[j]; - state->sclsftcleic.ptr.pp_double[dnec+snec+i][j] = v; - } - state->sclsftcleic.ptr.pp_double[dnec+snec+i][nmain] = cleic->ptr.pp_double[dnec+i][nmain]; - } - for(i=0; i<=snec-1; i++) - { - - /* - * Because constraints are sparse, everything is a bit tricky - - * it is possible that N-th element of the row is zero and not - * stored; it is also possible that entire row is empty. - */ - j0 = scleic->ridx.ptr.p_int[i]; - j1 = scleic->ridx.ptr.p_int[i+1]-1; - if( j1>=j0&&scleic->idx.ptr.p_int[j1]==nmain ) - { - state->sclsftcleic.ptr.pp_double[dnec+i][nmain] = scleic->vals.ptr.p_double[j1]; - j1 = j1-1; - } - for(j=j0; j<=j1; j++) - { - k = scleic->idx.ptr.p_int[j]; - v = scleic->vals.ptr.p_double[j]*s->ptr.p_double[k]; - state->sclsftcleic.ptr.pp_double[dnec+i][k] = v; - } - } - for(i=0; i<=snic-1; i++) - { - - /* - * Because constraints are sparse, everything is a bit tricky - - * it is possible that N-th element of the row is zero and not - * stored; it is also possible that entire row is empty. - */ - j0 = scleic->ridx.ptr.p_int[snec+i]; - j1 = scleic->ridx.ptr.p_int[snec+i+1]-1; - if( j1>=j0&&scleic->idx.ptr.p_int[j1]==nmain ) - { - state->sclsftcleic.ptr.pp_double[dnec+snec+dnic+i][nmain] = scleic->vals.ptr.p_double[j1]; - j1 = j1-1; - } - for(j=j0; j<=j1; j++) - { - k = scleic->idx.ptr.p_int[j]; - v = scleic->vals.ptr.p_double[j]*s->ptr.p_double[k]; - state->sclsftcleic.ptr.pp_double[dnec+snec+dnic+i][k] = v; - } - } - if( renormlc&&ktotal>0 ) - { - - /* - * Normalize linear constraints in such way that they have unit norm - * (after variable scaling) - */ - for(i=0; i<=ktotal-1; i++) - { - vv = 0.0; - for(j=0; j<=nmain-1; j++) - { - v = state->sclsftcleic.ptr.pp_double[i][j]; - vv = vv+v*v; - } - vv = ae_sqrt(vv, _state); - state->cscales.ptr.p_double[i] = vv; - if( ae_fp_greater(vv,(double)(0)) ) - { - vv = 1/vv; - for(j=0; j<=nmain; j++) - { - state->sclsftcleic.ptr.pp_double[i][j] = state->sclsftcleic.ptr.pp_double[i][j]*vv; - } - } - } - } - else - { - - /* - * Load unit scales - */ - for(i=0; i<=ktotal-1; i++) - { - state->cscales.ptr.p_double[i] = 1.0; - } - } - for(i=0; i<=ktotal-1; i++) - { - - /* - * Apply XOrigin - */ - v = 0.0; - for(j=0; j<=nmain-1; j++) - { - v = v+state->sclsftcleic.ptr.pp_double[i][j]*(xorigin->ptr.p_double[j]/s->ptr.p_double[j]); - } - state->sclsftcleic.ptr.pp_double[i][nmain] = state->sclsftcleic.ptr.pp_double[i][nmain]-v; - } -} - - -/************************************************************************* -Normalize model in such way that norm(A)~1 (very roughly) - -We have two lower bounds for sigma_max(A): -* first estimate is provided by Frobenius norm, it is equal to ANorm/NMain -* second estimate is provided by max(CAC) - -We select largest one of these estimates, because using just one -of them is prone to different failure modes. Then, we divide A and B -by this estimate. - -INPUT PARAMETERS: - A - array[N,N], quadratic term, full triangle is given - B - array[N], linear term - N - problem size - CLEIC- array[NEC+NIC,N+1], linear equality/inequality constraints - NEC - number of equality constraints - NIC - number of inequality constraints - UseCLEIC- additional normalization of A in such way that CLEIC*A*CLEIC'~1: - * if False, CLEIC is ignored - * if True, CLEIC rows MUST have unit norm (we check it) - Tmp2- additional buffer, possibly preallocated - -OUTPUT PARAMETERS: - A, B - appropriately rescaled by 1/SCL - -RESULT: - multiplier SCL - - -- ALGLIB -- - Copyright 01.10.2017 by Bochkanov Sergey -*************************************************************************/ -static double qpdenseaulsolver_normalizequadraticterm(/* Real */ ae_matrix* a, - /* Real */ ae_vector* b, - ae_int_t n, - /* Real */ ae_matrix* cleic, - ae_int_t nec, - ae_int_t nic, - ae_bool usecleic, - /* Real */ ae_matrix* tmp2, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double anorm; - double maxcac; - double v; - double vv; - ae_int_t ktotal; - ae_int_t nmain; - double result; - - - nmain = n; - ktotal = nec+nic; - anorm = (double)(0); - for(i=0; i<=nmain-1; i++) - { - for(j=0; j<=nmain-1; j++) - { - anorm = anorm+ae_sqr(a->ptr.pp_double[i][j], _state); - } - } - anorm = ae_sqrt(anorm, _state); - if( usecleic&&ktotal>0 ) - { - - /* - * Calculate max(|diag(C*A*C')|), where C is constraint matrix - */ - rmatrixsetlengthatleast(tmp2, ktotal, nmain, _state); - rmatrixgemm(ktotal, nmain, nmain, 1.0, cleic, 0, 0, 0, a, 0, 0, 0, 0.0, tmp2, 0, 0, _state); - maxcac = 0.0; - for(i=0; i<=ktotal-1; i++) - { - v = (double)(0); - vv = (double)(0); - for(j=0; j<=nmain-1; j++) - { - v = v+tmp2->ptr.pp_double[i][j]*cleic->ptr.pp_double[i][j]; - vv = vv+ae_sqr(cleic->ptr.pp_double[i][j], _state); - } - ae_assert(ae_fp_less(ae_fabs(vv-1, _state),1.0E-9)||ae_fp_eq(vv,(double)(0)), "DENSE-AUL: integrity check failed", _state); - maxcac = ae_maxreal(maxcac, ae_fabs(v, _state), _state); - } - } - else - { - maxcac = (double)(0); - } - result = coalesce(ae_maxreal(maxcac, anorm/nmain, _state), (double)(1), _state); - v = 1/result; - for(i=0; i<=nmain-1; i++) - { - for(j=0; j<=nmain-1; j++) - { - a->ptr.pp_double[i][j] = a->ptr.pp_double[i][j]*v; - } - } - for(i=0; i<=nmain-1; i++) - { - b->ptr.p_double[i] = b->ptr.p_double[i]*v; - } - return result; -} - - -/************************************************************************* -This function selects initial working set of general inequality constraints -for QP problem: -* for non-convex QP problems - NICWork=NIC is returned -* otherwise - NICWork=0 is returned (we have to - determine working set iteratively) - -INPUT PARAMETERS: - A - array[NMain], quadratic term, full matrix is stored - NMain - number of variables in the "original" QP problem - CLEIC - array[NEC+NIC,NMain+1], constraint matrix - NEC - number of equality constraints - NIC - number of inequality constraints - -OUTPUT PARAMETERS: - NICWork - recommended size of working set; in current version - either all (NICWork=NIC) or none (NICWork=0) constraints - are included. - AllowWSEviction-whether problem properties allow eviction of constraints - from working set or not. Non-convex problems do not - allow eviction, convex ones do. - - -- ALGLIB -- - Copyright 02.10.2017 by Bochkanov Sergey -*************************************************************************/ -static void qpdenseaulsolver_selectinitialworkingset(/* Real */ ae_matrix* a, - ae_int_t nmain, - /* Real */ ae_matrix* cleic, - ae_int_t nec, - ae_int_t nic, - /* Real */ ae_vector* tmp0, - /* Real */ ae_matrix* tmp2, - ae_int_t* nicwork, - ae_bool* allowwseviction, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - *nicwork = 0; - *allowwseviction = ae_false; - - rmatrixsetlengthatleast(tmp2, nmain, nmain, _state); - rvectorsetlengthatleast(tmp0, nmain, _state); - for(i=0; i<=nmain-1; i++) - { - for(j=i; j<=nmain-1; j++) - { - tmp2->ptr.pp_double[i][j] = a->ptr.pp_double[i][j]; - } - } - if( !spdmatrixcholeskyrec(tmp2, 0, nmain, ae_true, tmp0, _state) ) - { - - /* - * Matrix is indefinite. - * - * We have to select full working set, otherwise algorithm may fail - * because problem with reduced working set can be unbounded from below. - */ - *nicwork = nic; - *allowwseviction = ae_false; - } - else - { - - /* - * Positive definite matrix. - * - * We can select zero initial working set and expand it later. - */ - *nicwork = 0; - *allowwseviction = ae_true; - } -} - - -void _qpdenseaulsettings_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - qpdenseaulsettings *p = (qpdenseaulsettings*)_p; - ae_touch_ptr((void*)p); -} - - -void _qpdenseaulsettings_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - qpdenseaulsettings *dst = (qpdenseaulsettings*)_dst; - qpdenseaulsettings *src = (qpdenseaulsettings*)_src; - dst->epsx = src->epsx; - dst->outerits = src->outerits; - dst->rho = src->rho; -} - - -void _qpdenseaulsettings_clear(void* _p) -{ - qpdenseaulsettings *p = (qpdenseaulsettings*)_p; - ae_touch_ptr((void*)p); -} - - -void _qpdenseaulsettings_destroy(void* _p) -{ - qpdenseaulsettings *p = (qpdenseaulsettings*)_p; - ae_touch_ptr((void*)p); -} - - -void _qpdenseaulbuffers_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - qpdenseaulbuffers *p = (qpdenseaulbuffers*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->nulc, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->sclsfta, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->sclsftb, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->sclsfthasbndl, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->sclsfthasbndu, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->sclsftbndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->sclsftbndu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->sclsftxc, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->sclsftcleic, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cidx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->cscales, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->exa, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->exb, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->exxc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->exbndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->exbndu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->exscale, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->exxorigin, 0, DT_REAL, _state, make_automatic); - _qqpsettings_init(&p->qqpsettingsuser, _state, make_automatic); - _qqpbuffers_init(&p->qqpbuf, _state, make_automatic); - ae_vector_init(&p->nulcest, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpg, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->tmp2, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->modelg, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->deltax, 0, DT_REAL, _state, make_automatic); - _convexquadraticmodel_init(&p->dummycqm, _state, make_automatic); - _sparsematrix_init(&p->dummysparse, _state, make_automatic); - ae_matrix_init(&p->qrkkt, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->qrrightpart, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->qrtau, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->qrsv0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->qrsvx1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->nicerr, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->nicnact, 0, DT_INT, _state, make_automatic); -} - - -void _qpdenseaulbuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - qpdenseaulbuffers *dst = (qpdenseaulbuffers*)_dst; - qpdenseaulbuffers *src = (qpdenseaulbuffers*)_src; - ae_vector_init_copy(&dst->nulc, &src->nulc, _state, make_automatic); - ae_matrix_init_copy(&dst->sclsfta, &src->sclsfta, _state, make_automatic); - ae_vector_init_copy(&dst->sclsftb, &src->sclsftb, _state, make_automatic); - ae_vector_init_copy(&dst->sclsfthasbndl, &src->sclsfthasbndl, _state, make_automatic); - ae_vector_init_copy(&dst->sclsfthasbndu, &src->sclsfthasbndu, _state, make_automatic); - ae_vector_init_copy(&dst->sclsftbndl, &src->sclsftbndl, _state, make_automatic); - ae_vector_init_copy(&dst->sclsftbndu, &src->sclsftbndu, _state, make_automatic); - ae_vector_init_copy(&dst->sclsftxc, &src->sclsftxc, _state, make_automatic); - ae_matrix_init_copy(&dst->sclsftcleic, &src->sclsftcleic, _state, make_automatic); - ae_vector_init_copy(&dst->cidx, &src->cidx, _state, make_automatic); - ae_vector_init_copy(&dst->cscales, &src->cscales, _state, make_automatic); - ae_matrix_init_copy(&dst->exa, &src->exa, _state, make_automatic); - ae_vector_init_copy(&dst->exb, &src->exb, _state, make_automatic); - ae_vector_init_copy(&dst->exxc, &src->exxc, _state, make_automatic); - ae_vector_init_copy(&dst->exbndl, &src->exbndl, _state, make_automatic); - ae_vector_init_copy(&dst->exbndu, &src->exbndu, _state, make_automatic); - ae_vector_init_copy(&dst->exscale, &src->exscale, _state, make_automatic); - ae_vector_init_copy(&dst->exxorigin, &src->exxorigin, _state, make_automatic); - _qqpsettings_init_copy(&dst->qqpsettingsuser, &src->qqpsettingsuser, _state, make_automatic); - _qqpbuffers_init_copy(&dst->qqpbuf, &src->qqpbuf, _state, make_automatic); - ae_vector_init_copy(&dst->nulcest, &src->nulcest, _state, make_automatic); - ae_vector_init_copy(&dst->tmpg, &src->tmpg, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_matrix_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic); - ae_vector_init_copy(&dst->modelg, &src->modelg, _state, make_automatic); - ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic); - ae_vector_init_copy(&dst->deltax, &src->deltax, _state, make_automatic); - _convexquadraticmodel_init_copy(&dst->dummycqm, &src->dummycqm, _state, make_automatic); - _sparsematrix_init_copy(&dst->dummysparse, &src->dummysparse, _state, make_automatic); - ae_matrix_init_copy(&dst->qrkkt, &src->qrkkt, _state, make_automatic); - ae_vector_init_copy(&dst->qrrightpart, &src->qrrightpart, _state, make_automatic); - ae_vector_init_copy(&dst->qrtau, &src->qrtau, _state, make_automatic); - ae_vector_init_copy(&dst->qrsv0, &src->qrsv0, _state, make_automatic); - ae_vector_init_copy(&dst->qrsvx1, &src->qrsvx1, _state, make_automatic); - ae_vector_init_copy(&dst->nicerr, &src->nicerr, _state, make_automatic); - ae_vector_init_copy(&dst->nicnact, &src->nicnact, _state, make_automatic); - dst->repinneriterationscount = src->repinneriterationscount; - dst->repouteriterationscount = src->repouteriterationscount; - dst->repncholesky = src->repncholesky; - dst->repnwrkchanges = src->repnwrkchanges; - dst->repnwrk0 = src->repnwrk0; - dst->repnwrk1 = src->repnwrk1; - dst->repnwrkf = src->repnwrkf; - dst->repnmv = src->repnmv; -} - - -void _qpdenseaulbuffers_clear(void* _p) -{ - qpdenseaulbuffers *p = (qpdenseaulbuffers*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->nulc); - ae_matrix_clear(&p->sclsfta); - ae_vector_clear(&p->sclsftb); - ae_vector_clear(&p->sclsfthasbndl); - ae_vector_clear(&p->sclsfthasbndu); - ae_vector_clear(&p->sclsftbndl); - ae_vector_clear(&p->sclsftbndu); - ae_vector_clear(&p->sclsftxc); - ae_matrix_clear(&p->sclsftcleic); - ae_vector_clear(&p->cidx); - ae_vector_clear(&p->cscales); - ae_matrix_clear(&p->exa); - ae_vector_clear(&p->exb); - ae_vector_clear(&p->exxc); - ae_vector_clear(&p->exbndl); - ae_vector_clear(&p->exbndu); - ae_vector_clear(&p->exscale); - ae_vector_clear(&p->exxorigin); - _qqpsettings_clear(&p->qqpsettingsuser); - _qqpbuffers_clear(&p->qqpbuf); - ae_vector_clear(&p->nulcest); - ae_vector_clear(&p->tmpg); - ae_vector_clear(&p->tmp0); - ae_matrix_clear(&p->tmp2); - ae_vector_clear(&p->modelg); - ae_vector_clear(&p->d); - ae_vector_clear(&p->deltax); - _convexquadraticmodel_clear(&p->dummycqm); - _sparsematrix_clear(&p->dummysparse); - ae_matrix_clear(&p->qrkkt); - ae_vector_clear(&p->qrrightpart); - ae_vector_clear(&p->qrtau); - ae_vector_clear(&p->qrsv0); - ae_vector_clear(&p->qrsvx1); - ae_vector_clear(&p->nicerr); - ae_vector_clear(&p->nicnact); -} - - -void _qpdenseaulbuffers_destroy(void* _p) -{ - qpdenseaulbuffers *p = (qpdenseaulbuffers*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->nulc); - ae_matrix_destroy(&p->sclsfta); - ae_vector_destroy(&p->sclsftb); - ae_vector_destroy(&p->sclsfthasbndl); - ae_vector_destroy(&p->sclsfthasbndu); - ae_vector_destroy(&p->sclsftbndl); - ae_vector_destroy(&p->sclsftbndu); - ae_vector_destroy(&p->sclsftxc); - ae_matrix_destroy(&p->sclsftcleic); - ae_vector_destroy(&p->cidx); - ae_vector_destroy(&p->cscales); - ae_matrix_destroy(&p->exa); - ae_vector_destroy(&p->exb); - ae_vector_destroy(&p->exxc); - ae_vector_destroy(&p->exbndl); - ae_vector_destroy(&p->exbndu); - ae_vector_destroy(&p->exscale); - ae_vector_destroy(&p->exxorigin); - _qqpsettings_destroy(&p->qqpsettingsuser); - _qqpbuffers_destroy(&p->qqpbuf); - ae_vector_destroy(&p->nulcest); - ae_vector_destroy(&p->tmpg); - ae_vector_destroy(&p->tmp0); - ae_matrix_destroy(&p->tmp2); - ae_vector_destroy(&p->modelg); - ae_vector_destroy(&p->d); - ae_vector_destroy(&p->deltax); - _convexquadraticmodel_destroy(&p->dummycqm); - _sparsematrix_destroy(&p->dummysparse); - ae_matrix_destroy(&p->qrkkt); - ae_vector_destroy(&p->qrrightpart); - ae_vector_destroy(&p->qrtau); - ae_vector_destroy(&p->qrsv0); - ae_vector_destroy(&p->qrsvx1); - ae_vector_destroy(&p->nicerr); - ae_vector_destroy(&p->nicnact); -} - - -#endif -#if defined(AE_COMPILE_MINBLEIC) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* - BOUND CONSTRAINED OPTIMIZATION - WITH ADDITIONAL LINEAR EQUALITY AND INEQUALITY CONSTRAINTS - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments subject to any -combination of: -* bound constraints -* linear inequality constraints -* linear equality constraints - -REQUIREMENTS: -* user must provide function value and gradient -* starting point X0 must be feasible or - not too far away from the feasible set -* grad(f) must be Lipschitz continuous on a level set: - L = { x : f(x)<=f(x0) } -* function must be defined everywhere on the feasible set F - -USAGE: - -Constrained optimization if far more complex than the unconstrained one. -Here we give very brief outline of the BLEIC optimizer. We strongly recommend -you to read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide -on optimization, which is available at http://www.alglib.net/optimization/ - -1. User initializes algorithm state with MinBLEICCreate() call - -2. USer adds boundary and/or linear constraints by calling - MinBLEICSetBC() and MinBLEICSetLC() functions. - -3. User sets stopping conditions with MinBLEICSetCond(). - -4. User calls MinBLEICOptimize() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. - -5. User calls MinBLEICResults() to get solution - -6. Optionally user may call MinBLEICRestartFrom() to solve another problem - with same N but another starting point. - MinBLEICRestartFrom() allows to reuse already initialized structure. - -NOTE: if you have box-only constraints (no general linear constraints), - then MinBC optimizer can be better option. It uses special, faster - constraint activation method, which performs better on problems with - multiple constraints active at the solution. - - On small-scale problems performance of MinBC is similar to that of - MinBLEIC, but on large-scale ones (hundreds and thousands of active - constraints) it can be several times faster than MinBLEIC. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size ofX - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleiccreate(ae_int_t n, - /* Real */ ae_vector* x, - minbleicstate* state, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix c; - ae_vector ct; - - ae_frame_make(_state, &_frame_block); - memset(&c, 0, sizeof(c)); - memset(&ct, 0, sizeof(ct)); - _minbleicstate_clear(state); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - - ae_assert(n>=1, "MinBLEICCreate: N<1", _state); - ae_assert(x->cnt>=n, "MinBLEICCreate: Length(X)0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[0..N-1]. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinBLEICSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large truncation errors, while too small - step will result in too large numerical errors. 1.0E-6 can be good - value to start with. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. CG needs exact gradient values. Imprecise - gradient may slow down convergence, especially on highly nonlinear - problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -void minbleiccreatef(ae_int_t n, - /* Real */ ae_vector* x, - double diffstep, - minbleicstate* state, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix c; - ae_vector ct; - - ae_frame_make(_state, &_frame_block); - memset(&c, 0, sizeof(c)); - memset(&ct, 0, sizeof(ct)); - _minbleicstate_clear(state); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - - ae_assert(n>=1, "MinBLEICCreateF: N<1", _state); - ae_assert(x->cnt>=n, "MinBLEICCreateF: Length(X)nmain; - ae_assert(bndl->cnt>=n, "MinBLEICSetBC: Length(BndL)cnt>=n, "MinBLEICSetBC: Length(BndU)ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "MinBLEICSetBC: BndL contains NAN or +INF", _state); - ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "MinBLEICSetBC: BndL contains NAN or -INF", _state); - state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i]; - state->hasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state); - state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i]; - state->hasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state); - } - sassetbc(&state->sas, bndl, bndu, _state); -} - - -/************************************************************************* -This function sets linear constraints for BLEIC optimizer. - -Linear constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with MinBLEICRestartFrom(). - -INPUT PARAMETERS: - State - structure previously allocated with MinBLEICCreate call. - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -NOTE 1: linear (non-bound) constraints are satisfied only approximately: -* there always exists some minor violation (about Epsilon in magnitude) - due to rounding errors -* numerical differentiation, if used, may lead to function evaluations - outside of the feasible area, because algorithm does NOT change - numerical differentiation formula according to linear constraints. -If you want constraints to be satisfied exactly, try to reformulate your -problem in such manner that all constraints will become boundary ones -(this kind of constraints is always satisfied exactly, both in the final -solution and in all intermediate points). - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetlc(minbleicstate* state, - /* Real */ ae_matrix* c, - /* Integer */ ae_vector* ct, - ae_int_t k, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_int_t j; - double v; - - - n = state->nmain; - - /* - * First, check for errors in the inputs - */ - ae_assert(k>=0, "MinBLEICSetLC: K<0", _state); - ae_assert(c->cols>=n+1||k==0, "MinBLEICSetLC: Cols(C)rows>=k, "MinBLEICSetLC: Rows(C)cnt>=k, "MinBLEICSetLC: Length(CT)nec = 0; - state->nic = 0; - sassetlc(&state->sas, c, ct, 0, _state); - return; - } - - /* - * Equality constraints are stored first, in the upper - * NEC rows of State.CLEIC matrix. Inequality constraints - * are stored in the next NIC rows. - * - * NOTE: we convert inequality constraints to the form - * A*x<=b before copying them. - */ - rmatrixsetlengthatleast(&state->cleic, k, n+1, _state); - state->nec = 0; - state->nic = 0; - for(i=0; i<=k-1; i++) - { - if( ct->ptr.p_int[i]==0 ) - { - ae_v_move(&state->cleic.ptr.pp_double[state->nec][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n)); - state->nec = state->nec+1; - } - } - for(i=0; i<=k-1; i++) - { - if( ct->ptr.p_int[i]!=0 ) - { - if( ct->ptr.p_int[i]>0 ) - { - ae_v_moveneg(&state->cleic.ptr.pp_double[state->nec+state->nic][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n)); - } - else - { - ae_v_move(&state->cleic.ptr.pp_double[state->nec+state->nic][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n)); - } - state->nic = state->nic+1; - } - } - - /* - * Normalize rows of State.CLEIC: each row must have unit norm. - * Norm is calculated using first N elements (i.e. right part is - * not counted when we calculate norm). - */ - for(i=0; i<=k-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+ae_sqr(state->cleic.ptr.pp_double[i][j], _state); - } - if( ae_fp_eq(v,(double)(0)) ) - { - continue; - } - v = 1/ae_sqrt(v, _state); - ae_v_muld(&state->cleic.ptr.pp_double[i][0], 1, ae_v_len(0,n), v); - } - sassetlc(&state->sas, c, ct, k, _state); -} - - -/************************************************************************* -This function sets stopping conditions for the optimizer. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|=0 - The subroutine finishes its work if on k+1-th iteration - the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - is satisfied. - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - step vector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinBLEICSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead -to automatic stopping criterion selection. - -NOTE: when SetCond() called with non-zero MaxIts, BLEIC solver may perform - slightly more than MaxIts iterations. I.e., MaxIts sets non-strict - limit on iterations count. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetcond(minbleicstate* state, - double epsg, - double epsf, - double epsx, - ae_int_t maxits, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(epsg, _state), "MinBLEICSetCond: EpsG is not finite number", _state); - ae_assert(ae_fp_greater_eq(epsg,(double)(0)), "MinBLEICSetCond: negative EpsG", _state); - ae_assert(ae_isfinite(epsf, _state), "MinBLEICSetCond: EpsF is not finite number", _state); - ae_assert(ae_fp_greater_eq(epsf,(double)(0)), "MinBLEICSetCond: negative EpsF", _state); - ae_assert(ae_isfinite(epsx, _state), "MinBLEICSetCond: EpsX is not finite number", _state); - ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinBLEICSetCond: negative EpsX", _state); - ae_assert(maxits>=0, "MinBLEICSetCond: negative MaxIts!", _state); - if( ((ae_fp_eq(epsg,(double)(0))&&ae_fp_eq(epsf,(double)(0)))&&ae_fp_eq(epsx,(double)(0)))&&maxits==0 ) - { - epsx = 1.0E-6; - } - state->epsg = epsg; - state->epsf = epsf; - state->epsx = epsx; - state->maxits = maxits; -} - - -/************************************************************************* -This function sets scaling coefficients for BLEIC optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of the optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -In most optimizers (and in the BLEIC too) scaling is NOT a form of -preconditioning. It just affects stopping conditions. You should set -preconditioner by separate call to one of the MinBLEICSetPrec...() -functions. - -There is a special preconditioning mode, however, which uses scaling -coefficients to form diagonal preconditioning matrix. You can turn this -mode on, if you want. But you should understand that scaling is not the -same thing as preconditioning - these are two different, although related -forms of tuning solver. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetscale(minbleicstate* state, - /* Real */ ae_vector* s, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(s->cnt>=state->nmain, "MinBLEICSetScale: Length(S)nmain-1; i++) - { - ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinBLEICSetScale: S contains infinite or NAN elements", _state); - ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "MinBLEICSetScale: S contains zero elements", _state); - state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state); - } - sassetscale(&state->sas, s, _state); -} - - -/************************************************************************* -Modification of the preconditioner: preconditioning is turned off. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetprecdefault(minbleicstate* state, ae_state *_state) -{ - - - state->prectype = 0; -} - - -/************************************************************************* -Modification of the preconditioner: diagonal of approximate Hessian is -used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - D - diagonal of the approximate Hessian, array[0..N-1], - (if larger, only leading N elements are used). - -NOTE 1: D[i] should be positive. Exception will be thrown otherwise. - -NOTE 2: you should pass diagonal of approximate Hessian - NOT ITS INVERSE. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetprecdiag(minbleicstate* state, - /* Real */ ae_vector* d, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(d->cnt>=state->nmain, "MinBLEICSetPrecDiag: D is too short", _state); - for(i=0; i<=state->nmain-1; i++) - { - ae_assert(ae_isfinite(d->ptr.p_double[i], _state), "MinBLEICSetPrecDiag: D contains infinite or NAN elements", _state); - ae_assert(ae_fp_greater(d->ptr.p_double[i],(double)(0)), "MinBLEICSetPrecDiag: D contains non-positive elements", _state); - } - rvectorsetlengthatleast(&state->diagh, state->nmain, _state); - state->prectype = 2; - for(i=0; i<=state->nmain-1; i++) - { - state->diagh.ptr.p_double[i] = d->ptr.p_double[i]; - } -} - - -/************************************************************************* -Modification of the preconditioner: scale-based diagonal preconditioning. - -This preconditioning mode can be useful when you don't have approximate -diagonal of Hessian, but you know that your variables are badly scaled -(for example, one variable is in [1,10], and another in [1000,100000]), -and most part of the ill-conditioning comes from different scales of vars. - -In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2), -can greatly improve convergence. - -IMPRTANT: you should set scale of your variables with MinBLEICSetScale() -call (before or after MinBLEICSetPrecScale() call). Without knowledge of -the scale of your variables scale-based preconditioner will be just unit -matrix. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetprecscale(minbleicstate* state, ae_state *_state) -{ - - - state->prectype = 3; -} - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinBLEICOptimize(). - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetxrep(minbleicstate* state, - ae_bool needxrep, - ae_state *_state) -{ - - - state->xrep = needxrep; -} - - -/************************************************************************* -This function turns on/off line search reports. -These reports are described in more details in developer-only comments on -MinBLEICState object. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedDRep- whether line search reports are needed or not - -This function is intended for private use only. Turning it on artificially -may cause program failure. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetdrep(minbleicstate* state, - ae_bool needdrep, - ae_state *_state) -{ - - - state->drep = needdrep; -} - - -/************************************************************************* -This function sets maximum step length - -IMPORTANT: this feature is hard to combine with preconditioning. You can't -set upper limit on step length, when you solve optimization problem with -linear (non-boundary) constraints AND preconditioner turned on. - -When non-boundary constraints are present, you have to either a) use -preconditioner, or b) use upper limit on step length. YOU CAN'T USE BOTH! -In this case algorithm will terminate with appropriate error code. - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which lead to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetstpmax(minbleicstate* state, - double stpmax, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(stpmax, _state), "MinBLEICSetStpMax: StpMax is not finite!", _state); - ae_assert(ae_fp_greater_eq(stpmax,(double)(0)), "MinBLEICSetStpMax: StpMax<0!", _state); - state->stpmax = stpmax; -} - - -/************************************************************************* -NOTES: - -1. This function has two different implementations: one which uses exact - (analytical) user-supplied gradient, and one which uses function value - only and numerically differentiates function in order to obtain - gradient. - - Depending on the specific function used to create optimizer object - (either MinBLEICCreate() for analytical gradient or MinBLEICCreateF() - for numerical differentiation) you should choose appropriate variant of - MinBLEICOptimize() - one which accepts function AND gradient or one - which accepts function ONLY. - - Be careful to choose variant of MinBLEICOptimize() which corresponds to - your optimization scheme! Table below lists different combinations of - callback (function/gradient) passed to MinBLEICOptimize() and specific - function used to create optimizer. - - - | USER PASSED TO MinBLEICOptimize() - CREATED WITH | function only | function and gradient - ------------------------------------------------------------ - MinBLEICCreateF() | work FAIL - MinBLEICCreate() | FAIL work - - Here "FAIL" denotes inappropriate combinations of optimizer creation - function and MinBLEICOptimize() version. Attemps to use such - combination (for example, to create optimizer with MinBLEICCreateF() - and to pass gradient information to MinBLEICOptimize()) will lead to - exception being thrown. Either you did not pass gradient when it WAS - needed or you passed gradient when it was NOT needed. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -ae_bool minbleiciteration(minbleicstate* state, ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - ae_int_t i; - ae_int_t j; - double v; - double vv; - double v0; - ae_bool b; - ae_int_t mcinfo; - ae_int_t actstatus; - ae_int_t itidx; - double penalty; - double ginit; - double gdecay; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - n = state->rstate.ia.ptr.p_int[0]; - m = state->rstate.ia.ptr.p_int[1]; - i = state->rstate.ia.ptr.p_int[2]; - j = state->rstate.ia.ptr.p_int[3]; - mcinfo = state->rstate.ia.ptr.p_int[4]; - actstatus = state->rstate.ia.ptr.p_int[5]; - itidx = state->rstate.ia.ptr.p_int[6]; - b = state->rstate.ba.ptr.p_bool[0]; - v = state->rstate.ra.ptr.p_double[0]; - vv = state->rstate.ra.ptr.p_double[1]; - v0 = state->rstate.ra.ptr.p_double[2]; - penalty = state->rstate.ra.ptr.p_double[3]; - ginit = state->rstate.ra.ptr.p_double[4]; - gdecay = state->rstate.ra.ptr.p_double[5]; - } - else - { - n = 359; - m = -58; - i = -919; - j = -909; - mcinfo = 81; - actstatus = 255; - itidx = 74; - b = ae_false; - v = 809; - vv = 205; - v0 = -838; - penalty = 939; - ginit = -526; - gdecay = 763; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - if( state->rstate.stage==1 ) - { - goto lbl_1; - } - if( state->rstate.stage==2 ) - { - goto lbl_2; - } - if( state->rstate.stage==3 ) - { - goto lbl_3; - } - if( state->rstate.stage==4 ) - { - goto lbl_4; - } - if( state->rstate.stage==5 ) - { - goto lbl_5; - } - if( state->rstate.stage==6 ) - { - goto lbl_6; - } - if( state->rstate.stage==7 ) - { - goto lbl_7; - } - if( state->rstate.stage==8 ) - { - goto lbl_8; - } - if( state->rstate.stage==9 ) - { - goto lbl_9; - } - if( state->rstate.stage==10 ) - { - goto lbl_10; - } - if( state->rstate.stage==11 ) - { - goto lbl_11; - } - if( state->rstate.stage==12 ) - { - goto lbl_12; - } - if( state->rstate.stage==13 ) - { - goto lbl_13; - } - if( state->rstate.stage==14 ) - { - goto lbl_14; - } - if( state->rstate.stage==15 ) - { - goto lbl_15; - } - if( state->rstate.stage==16 ) - { - goto lbl_16; - } - if( state->rstate.stage==17 ) - { - goto lbl_17; - } - if( state->rstate.stage==18 ) - { - goto lbl_18; - } - if( state->rstate.stage==19 ) - { - goto lbl_19; - } - if( state->rstate.stage==20 ) - { - goto lbl_20; - } - if( state->rstate.stage==21 ) - { - goto lbl_21; - } - - /* - * Routine body - */ - - /* - * Algorithm parameters: - * * M number of L-BFGS corrections. - * This coefficient remains fixed during iterations. - * * GDecay desired decrease of constrained gradient during L-BFGS iterations. - * This coefficient is decreased after each L-BFGS round until - * it reaches minimum decay. - */ - m = ae_minint(5, state->nmain, _state); - gdecay = minbleic_initialdecay; - - /* - * Init - */ - n = state->nmain; - state->steepestdescentstep = ae_false; - state->userterminationneeded = ae_false; - state->repterminationtype = 0; - state->repinneriterationscount = 0; - state->repouteriterationscount = 0; - state->repnfev = 0; - state->repvaridx = -1; - state->repdebugeqerr = 0.0; - state->repdebugfs = _state->v_nan; - state->repdebugff = _state->v_nan; - state->repdebugdx = _state->v_nan; - if( ae_fp_neq(state->stpmax,(double)(0))&&state->prectype!=0 ) - { - state->repterminationtype = -10; - result = ae_false; - return result; - } - rmatrixsetlengthatleast(&state->bufyk, m+1, n, _state); - rmatrixsetlengthatleast(&state->bufsk, m+1, n, _state); - rvectorsetlengthatleast(&state->bufrho, m, _state); - rvectorsetlengthatleast(&state->buftheta, m, _state); - rvectorsetlengthatleast(&state->tmp0, n, _state); - smoothnessmonitorinit(&state->smonitor, &state->s, n, 1, state->smoothnessguardlevel>0, _state); - for(i=0; i<=n-1; i++) - { - state->lastscaleused.ptr.p_double[i] = state->s.ptr.p_double[i]; - state->invs.ptr.p_double[i] = 1/state->s.ptr.p_double[i]; - } - - /* - * Check analytic derivative - */ - minbleic_clearrequestfields(state, _state); - if( !(ae_fp_eq(state->diffstep,(double)(0))&&ae_fp_greater(state->teststep,(double)(0))) ) - { - goto lbl_22; - } -lbl_24: - if( !smoothnessmonitorcheckgradientatx0(&state->smonitor, &state->xstart, &state->s, &state->bndl, &state->bndu, ae_true, state->teststep, _state) ) - { - goto lbl_25; - } - for(i=0; i<=n-1; i++) - { - state->x.ptr.p_double[i] = state->smonitor.x.ptr.p_double[i]; - } - state->needfg = ae_true; - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - state->needfg = ae_false; - state->smonitor.fi.ptr.p_double[0] = state->f; - for(i=0; i<=n-1; i++) - { - state->smonitor.j.ptr.pp_double[0][i] = state->g.ptr.p_double[i]; - } - goto lbl_24; -lbl_25: -lbl_22: - - /* - * Fill TmpPrec with current preconditioner - */ - rvectorsetlengthatleast(&state->tmpprec, n, _state); - for(i=0; i<=n-1; i++) - { - if( state->prectype==2 ) - { - state->tmpprec.ptr.p_double[i] = state->diagh.ptr.p_double[i]; - continue; - } - if( state->prectype==3 ) - { - state->tmpprec.ptr.p_double[i] = 1/ae_sqr(state->s.ptr.p_double[i], _state); - continue; - } - state->tmpprec.ptr.p_double[i] = (double)(1); - } - sassetprecdiag(&state->sas, &state->tmpprec, _state); - - /* - * Start optimization - */ - if( !sasstartoptimization(&state->sas, &state->xstart, _state) ) - { - state->repterminationtype = -3; - result = ae_false; - return result; - } - - /* - * Main cycle of BLEIC-PG algorithm - */ - state->repterminationtype = 0; - state->lastgoodstep = (double)(0); - state->lastscaledgoodstep = (double)(0); - state->maxscaledgrad = (double)(0); - state->nonmonotoniccnt = ae_round(1.5*(n+state->nic), _state)+5; - ae_v_move(&state->x.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minbleic_clearrequestfields(state, _state); - if( ae_fp_neq(state->diffstep,(double)(0)) ) - { - goto lbl_26; - } - state->needfg = ae_true; - state->rstate.stage = 1; - goto lbl_rcomm; -lbl_1: - state->needfg = ae_false; - goto lbl_27; -lbl_26: - state->needf = ae_true; - state->rstate.stage = 2; - goto lbl_rcomm; -lbl_2: - state->needf = ae_false; -lbl_27: - state->fc = state->f; - trimprepare(state->f, &state->trimthreshold, _state); - state->repnfev = state->repnfev+1; - if( !state->xrep ) - { - goto lbl_28; - } - - /* - * Report current point - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->f = state->fc; - state->xupdated = ae_true; - state->rstate.stage = 3; - goto lbl_rcomm; -lbl_3: - state->xupdated = ae_false; -lbl_28: - if( state->userterminationneeded ) - { - - /* - * User requested termination - */ - sasstopoptimization(&state->sas, _state); - state->repterminationtype = 8; - result = ae_false; - return result; - } -lbl_30: - if( ae_false ) - { - goto lbl_31; - } - - /* - * Preparations - * - * (a) calculate unconstrained gradient - * (b) determine initial active set - * (c) update MaxScaledGrad - * (d) check F/G for NAN/INF, abnormally terminate algorithm if needed - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minbleic_clearrequestfields(state, _state); - if( ae_fp_neq(state->diffstep,(double)(0)) ) - { - goto lbl_32; - } - - /* - * Analytic gradient - */ - state->needfg = ae_true; - state->rstate.stage = 4; - goto lbl_rcomm; -lbl_4: - state->needfg = ae_false; - goto lbl_33; -lbl_32: - - /* - * Numerical differentiation - */ - state->needf = ae_true; - state->rstate.stage = 5; - goto lbl_rcomm; -lbl_5: - state->fbase = state->f; - i = 0; -lbl_34: - if( i>n-1 ) - { - goto lbl_36; - } - v = state->x.ptr.p_double[i]; - b = ae_false; - if( state->hasbndl.ptr.p_bool[i] ) - { - b = b||ae_fp_less(v-state->diffstep*state->s.ptr.p_double[i],state->bndl.ptr.p_double[i]); - } - if( state->hasbndu.ptr.p_bool[i] ) - { - b = b||ae_fp_greater(v+state->diffstep*state->s.ptr.p_double[i],state->bndu.ptr.p_double[i]); - } - if( b ) - { - goto lbl_37; - } - state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 6; - goto lbl_rcomm; -lbl_6: - state->fm2 = state->f; - state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 7; - goto lbl_rcomm; -lbl_7: - state->fm1 = state->f; - state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 8; - goto lbl_rcomm; -lbl_8: - state->fp1 = state->f; - state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 9; - goto lbl_rcomm; -lbl_9: - state->fp2 = state->f; - state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]); - goto lbl_38; -lbl_37: - state->xm1 = v-state->diffstep*state->s.ptr.p_double[i]; - state->xp1 = v+state->diffstep*state->s.ptr.p_double[i]; - if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(state->xm1,state->bndl.ptr.p_double[i]) ) - { - state->xm1 = state->bndl.ptr.p_double[i]; - } - if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(state->xp1,state->bndu.ptr.p_double[i]) ) - { - state->xp1 = state->bndu.ptr.p_double[i]; - } - state->x.ptr.p_double[i] = state->xm1; - state->rstate.stage = 10; - goto lbl_rcomm; -lbl_10: - state->fm1 = state->f; - state->x.ptr.p_double[i] = state->xp1; - state->rstate.stage = 11; - goto lbl_rcomm; -lbl_11: - state->fp1 = state->f; - if( ae_fp_neq(state->xm1,state->xp1) ) - { - state->g.ptr.p_double[i] = (state->fp1-state->fm1)/(state->xp1-state->xm1); - } - else - { - state->g.ptr.p_double[i] = (double)(0); - } -lbl_38: - state->x.ptr.p_double[i] = v; - i = i+1; - goto lbl_34; -lbl_36: - state->f = state->fbase; - state->needf = ae_false; -lbl_33: - state->fc = state->f; - ae_v_move(&state->ugc.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->cgc.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - sasreactivateconstraintsprec(&state->sas, &state->ugc, _state); - sasconstraineddirection(&state->sas, &state->cgc, _state); - ginit = 0.0; - for(i=0; i<=n-1; i++) - { - ginit = ginit+ae_sqr(state->cgc.ptr.p_double[i]*state->s.ptr.p_double[i], _state); - } - ginit = ae_sqrt(ginit, _state); - state->maxscaledgrad = ae_maxreal(state->maxscaledgrad, ginit, _state); - if( !ae_isfinite(ginit, _state)||!ae_isfinite(state->fc, _state) ) - { - - /* - * Abnormal termination - infinities in function/gradient - */ - sasstopoptimization(&state->sas, _state); - state->repterminationtype = -8; - result = ae_false; - return result; - } - if( state->userterminationneeded ) - { - - /* - * User requested termination - */ - sasstopoptimization(&state->sas, _state); - state->repterminationtype = 8; - result = ae_false; - return result; - } - - /* - * LBFGS stage: - * * during LBFGS iterations we activate new constraints, but never - * deactivate already active ones. - * * we perform at most N iterations of LBFGS before re-evaluating - * active set and restarting LBFGS. - * * first iteration of LBFGS is a special - it is performed with - * minimum set of active constraints, algorithm termination can - * be performed only at this state. We call this iteration - * "steepest descent step". - * - * About termination: - * * LBFGS iterations can be terminated because of two reasons: - * * "termination" - non-zero termination code in RepTerminationType, - * which means that optimization is done - * * "restart" - zero RepTerminationType, which means that we - * have to re-evaluate active set and resume LBFGS stage. - * * one more option is "refresh" - to continue LBFGS iterations, - * but with all BFGS updates (Sk/Yk pairs) being dropped; - * it happens after changes in active set - */ - state->bufsize = 0; - state->steepestdescentstep = ae_true; - itidx = -1; -lbl_39: - if( itidx>=n-1 ) - { - goto lbl_40; - } - - /* - * Increment iterations counter - * - * NOTE: we have strong reasons to use such complex scheme - * instead of just for() loop - this counter may be - * decreased at some occasions to perform "restart" - * of an iteration. - */ - itidx = itidx+1; - - /* - * At the beginning of each iteration: - * * SAS.XC stores current point - * * FC stores current function value - * * UGC stores current unconstrained gradient - * * CGC stores current constrained gradient - * * D stores constrained step direction (calculated at this block) - * - * - * Check gradient-based stopping criteria - * - * This stopping condition is tested only for step which is the - * first step of LBFGS (subsequent steps may accumulate active - * constraints thus they should NOT be used for stopping - gradient - * may be small when constrained, but these constraints may be - * deactivated by the subsequent steps) - */ - if( state->steepestdescentstep&&ae_fp_less_eq(sasscaledconstrainednorm(&state->sas, &state->ugc, _state),state->epsg) ) - { - - /* - * Gradient is small enough. - * Optimization is terminated - */ - state->repterminationtype = 4; - goto lbl_40; - } - - /* - * 1. Calculate search direction D according to L-BFGS algorithm - * using constrained preconditioner to perform inner multiplication. - * 2. Evaluate scaled length of direction D; restart LBFGS if D is zero - * (it may be possible that we found minimum, but it is also possible - * that some constraints need deactivation) - * 3. If D is non-zero, try to use previous scaled step length as initial estimate for new step. - */ - ae_v_move(&state->work.ptr.p_double[0], 1, &state->cgc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=state->bufsize-1; i>=0; i--) - { - v = ae_v_dotproduct(&state->bufsk.ptr.pp_double[i][0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->buftheta.ptr.p_double[i] = v; - vv = v*state->bufrho.ptr.p_double[i]; - ae_v_subd(&state->work.ptr.p_double[0], 1, &state->bufyk.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), vv); - } - sasconstraineddirectionprec(&state->sas, &state->work, _state); - for(i=0; i<=state->bufsize-1; i++) - { - v = ae_v_dotproduct(&state->bufyk.ptr.pp_double[i][0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1)); - vv = state->bufrho.ptr.p_double[i]*(-v+state->buftheta.ptr.p_double[i]); - ae_v_addd(&state->work.ptr.p_double[0], 1, &state->bufsk.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), vv); - } - sasconstraineddirection(&state->sas, &state->work, _state); - ae_v_moveneg(&state->d.ptr.p_double[0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(state->d.ptr.p_double[i]/state->s.ptr.p_double[i], _state); - } - v = ae_sqrt(v, _state); - if( ae_fp_eq(v,(double)(0)) ) - { - - /* - * Search direction is zero. - * If we perform "steepest descent step", algorithm is terminated. - * Otherwise we just restart LBFGS. - */ - if( state->steepestdescentstep ) - { - state->repterminationtype = 4; - } - goto lbl_40; - } - ae_assert(ae_fp_greater(v,(double)(0)), "MinBLEIC: internal error", _state); - if( ae_fp_greater(state->lastscaledgoodstep,(double)(0))&&ae_fp_greater(v,(double)(0)) ) - { - state->stp = state->lastscaledgoodstep/v; - } - else - { - state->stp = 1.0/v; - } - - /* - * Calculate bound on step length. - * Step direction is stored - */ - sasexploredirection(&state->sas, &state->d, &state->curstpmax, &state->cidx, &state->cval, _state); - state->activationstep = state->curstpmax; - if( state->cidx>=0&&ae_fp_eq(state->activationstep,(double)(0)) ) - { - - /* - * We are exactly at the boundary, immediate activation - * of constraint is required. LBFGS stage is continued - * with "refreshed" model. - * - * ! IMPORTANT: we do not clear SteepestDescent flag here, - * ! it is very important for correct stopping - * ! of algorithm. - * - * ! IMPORTANT: we decrease iteration counter in order to - * preserve computational budget for iterations. - */ - sasimmediateactivation(&state->sas, state->cidx, state->cval, _state); - state->bufsize = 0; - itidx = itidx-1; - goto lbl_39; - } - if( ae_fp_greater(state->stpmax,(double)(0)) ) - { - v = ae_v_dotproduct(&state->d.ptr.p_double[0], 1, &state->d.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = ae_sqrt(v, _state); - if( ae_fp_greater(v,(double)(0)) ) - { - state->curstpmax = ae_minreal(state->curstpmax, state->stpmax/v, _state); - } - } - - /* - * Report beginning of line search (if requested by caller). - * See description of the MinBLEICState for more information - * about fields accessible to caller. - * - * Caller may do following: - * * change State.Stp and load better initial estimate of - * the step length. - * Caller may not terminate algorithm. - */ - if( !state->drep ) - { - goto lbl_41; - } - minbleic_clearrequestfields(state, _state); - state->lsstart = ae_true; - state->boundedstep = state->cidx>=0; - ae_v_move(&state->x.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->rstate.stage = 12; - goto lbl_rcomm; -lbl_12: - state->lsstart = ae_false; -lbl_41: - - /* - * Minimize F(x+alpha*d) - */ - ae_v_move(&state->xn.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->cgn.ptr.p_double[0], 1, &state->cgc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->ugn.ptr.p_double[0], 1, &state->ugc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->fn = state->fc; - state->mcstage = 0; - smoothnessmonitorstartlinesearch1u(&state->smonitor, &state->s, &state->invs, &state->xn, state->fn, &state->ugn, _state); - mcsrch(n, &state->xn, &state->fn, &state->ugn, &state->d, &state->stp, state->curstpmax, minbleic_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state); -lbl_43: - if( state->mcstage==0 ) - { - goto lbl_44; - } - - /* - * Perform correction (constraints are enforced) - * Copy XN to X - */ - sascorrection(&state->sas, &state->xn, &penalty, _state); - for(i=0; i<=n-1; i++) - { - state->x.ptr.p_double[i] = state->xn.ptr.p_double[i]; - } - - /* - * Gradient, either user-provided or numerical differentiation - */ - minbleic_clearrequestfields(state, _state); - if( ae_fp_neq(state->diffstep,(double)(0)) ) - { - goto lbl_45; - } - - /* - * Analytic gradient - */ - state->needfg = ae_true; - state->rstate.stage = 13; - goto lbl_rcomm; -lbl_13: - state->needfg = ae_false; - state->repnfev = state->repnfev+1; - goto lbl_46; -lbl_45: - - /* - * Numerical differentiation - */ - state->needf = ae_true; - state->rstate.stage = 14; - goto lbl_rcomm; -lbl_14: - state->fbase = state->f; - i = 0; -lbl_47: - if( i>n-1 ) - { - goto lbl_49; - } - v = state->x.ptr.p_double[i]; - b = ae_false; - if( state->hasbndl.ptr.p_bool[i] ) - { - b = b||ae_fp_less(v-state->diffstep*state->s.ptr.p_double[i],state->bndl.ptr.p_double[i]); - } - if( state->hasbndu.ptr.p_bool[i] ) - { - b = b||ae_fp_greater(v+state->diffstep*state->s.ptr.p_double[i],state->bndu.ptr.p_double[i]); - } - if( b ) - { - goto lbl_50; - } - state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 15; - goto lbl_rcomm; -lbl_15: - state->fm2 = state->f; - state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 16; - goto lbl_rcomm; -lbl_16: - state->fm1 = state->f; - state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 17; - goto lbl_rcomm; -lbl_17: - state->fp1 = state->f; - state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 18; - goto lbl_rcomm; -lbl_18: - state->fp2 = state->f; - state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]); - state->repnfev = state->repnfev+4; - goto lbl_51; -lbl_50: - state->xm1 = v-state->diffstep*state->s.ptr.p_double[i]; - state->xp1 = v+state->diffstep*state->s.ptr.p_double[i]; - if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(state->xm1,state->bndl.ptr.p_double[i]) ) - { - state->xm1 = state->bndl.ptr.p_double[i]; - } - if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(state->xp1,state->bndu.ptr.p_double[i]) ) - { - state->xp1 = state->bndu.ptr.p_double[i]; - } - state->x.ptr.p_double[i] = state->xm1; - state->rstate.stage = 19; - goto lbl_rcomm; -lbl_19: - state->fm1 = state->f; - state->x.ptr.p_double[i] = state->xp1; - state->rstate.stage = 20; - goto lbl_rcomm; -lbl_20: - state->fp1 = state->f; - if( ae_fp_neq(state->xm1,state->xp1) ) - { - state->g.ptr.p_double[i] = (state->fp1-state->fm1)/(state->xp1-state->xm1); - } - else - { - state->g.ptr.p_double[i] = (double)(0); - } - state->repnfev = state->repnfev+2; -lbl_51: - state->x.ptr.p_double[i] = v; - i = i+1; - goto lbl_47; -lbl_49: - state->f = state->fbase; - state->needf = ae_false; -lbl_46: - - /* - * Back to MCSRCH - * - * NOTE: penalty term from correction is added to FN in order - * to penalize increase in infeasibility. - */ - smoothnessmonitorenqueuepoint1u(&state->smonitor, &state->s, &state->invs, &state->d, state->stp, &state->x, state->f, &state->g, _state); - state->fn = state->f+minbleic_penaltyfactor*state->maxscaledgrad*penalty; - ae_v_move(&state->cgn.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->ugn.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - sasconstraineddirection(&state->sas, &state->cgn, _state); - trimfunction(&state->fn, &state->cgn, n, state->trimthreshold, _state); - mcsrch(n, &state->xn, &state->fn, &state->ugn, &state->d, &state->stp, state->curstpmax, minbleic_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state); - goto lbl_43; -lbl_44: - ae_v_moveneg(&state->bufsk.ptr.pp_double[state->bufsize][0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_moveneg(&state->bufyk.ptr.pp_double[state->bufsize][0], 1, &state->cgc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_add(&state->bufsk.ptr.pp_double[state->bufsize][0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_add(&state->bufyk.ptr.pp_double[state->bufsize][0], 1, &state->cgn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - smoothnessmonitorfinalizelinesearch(&state->smonitor, _state); - - /* - * Check for presence of NAN/INF in function/gradient - */ - v = state->fn; - for(i=0; i<=n-1; i++) - { - v = 0.1*v+state->ugn.ptr.p_double[i]; - } - if( !ae_isfinite(v, _state) ) - { - - /* - * Abnormal termination - infinities in function/gradient - */ - state->repterminationtype = -8; - goto lbl_40; - } - - /* - * Handle possible failure of the line search or request for termination - */ - if( mcinfo!=1&&mcinfo!=5 ) - { - - /* - * We can not find step which decreases function value. We have - * two possibilities: - * (a) numerical properties of the function do not allow us to - * find good step. - * (b) we are close to activation of some constraint, and it is - * so close that step which activates it leads to change in - * target function which is smaller than numerical noise. - * - * Optimization algorithm must be able to handle case (b), because - * inability to handle it will cause failure when algorithm - * started very close to boundary of the feasible area. - * - * In order to correctly handle such cases we allow limited amount - * of small steps which increase function value. - */ - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(state->d.ptr.p_double[i]*state->curstpmax/state->s.ptr.p_double[i], _state); - } - v = ae_sqrt(v, _state); - b = ae_false; - if( (state->cidx>=0&&ae_fp_less_eq(v,minbleic_maxnonmonotoniclen))&&state->nonmonotoniccnt>0 ) - { - - /* - * We try to enforce non-monotonic step: - * * Stp := CurStpMax - * * MCINFO := 5 - * * XN := XC+CurStpMax*D - * * non-monotonic counter is decreased - * - * NOTE: UGN/CGN are not updated because step is so short that we assume that - * GN is approximately equal to GC. - * - * NOTE: prior to enforcing such step we check that it does not increase infeasibility - * of constraints beyond tolerable level - */ - v = state->curstpmax; - ae_v_move(&state->tmp0.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_addd(&state->tmp0.ptr.p_double[0], 1, &state->d.ptr.p_double[0], 1, ae_v_len(0,n-1), v); - if( ae_fp_less_eq(minbleic_feasibilityerror(&state->tmp0, &state->s, n, &state->cleic, state->nec, state->nic, _state),minbleic_nmstol*ae_sqrt((double)(n), _state)*ae_machineepsilon) ) - { - state->stp = state->curstpmax; - mcinfo = 5; - ae_v_move(&state->xn.ptr.p_double[0], 1, &state->tmp0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->nonmonotoniccnt = state->nonmonotoniccnt-1; - b = ae_true; - } - } - if( !b ) - { - - /* - * Numerical properties of the function do not allow - * us to solve problem. Here we have two possibilities: - * * if it is "steepest descent" step, we can terminate - * algorithm because we are close to minimum - * * if it is NOT "steepest descent" step, we should restart - * LBFGS iterations. - */ - if( state->steepestdescentstep ) - { - - /* - * Algorithm is terminated - */ - state->repterminationtype = 7; - goto lbl_40; - } - else - { - - /* - * Re-evaluate active set and restart LBFGS - */ - goto lbl_40; - } - } - } - if( state->userterminationneeded ) - { - goto lbl_40; - } - - /* - * Current point is updated: - * * move XC/FC/GC to XP/FP/GP - * * change current point remembered by SAS structure - * * move XN/FN/GN to XC/FC/GC - * * report current point and update iterations counter - * * if MCINFO=1, push new pair SK/YK to LBFGS buffer - */ - state->fp = state->fc; - ae_v_move(&state->xp.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->fc = state->fn; - ae_v_move(&state->cgc.ptr.p_double[0], 1, &state->cgn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->ugc.ptr.p_double[0], 1, &state->ugn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - actstatus = sasmoveto(&state->sas, &state->xn, state->cidx>=0&&ae_fp_greater_eq(state->stp,state->activationstep), state->cidx, state->cval, _state); - if( !state->xrep ) - { - goto lbl_52; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minbleic_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 21; - goto lbl_rcomm; -lbl_21: - state->xupdated = ae_false; -lbl_52: - state->repinneriterationscount = state->repinneriterationscount+1; - if( mcinfo==1 ) - { - - /* - * Accept new LBFGS update given by Sk,Yk - */ - if( state->bufsize==m ) - { - - /* - * Buffer is full, shift contents by one row - */ - for(i=0; i<=state->bufsize-1; i++) - { - ae_v_move(&state->bufsk.ptr.pp_double[i][0], 1, &state->bufsk.ptr.pp_double[i+1][0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->bufyk.ptr.pp_double[i][0], 1, &state->bufyk.ptr.pp_double[i+1][0], 1, ae_v_len(0,n-1)); - } - for(i=0; i<=state->bufsize-2; i++) - { - state->bufrho.ptr.p_double[i] = state->bufrho.ptr.p_double[i+1]; - state->buftheta.ptr.p_double[i] = state->buftheta.ptr.p_double[i+1]; - } - } - else - { - - /* - * Buffer is not full, increase buffer size by 1 - */ - state->bufsize = state->bufsize+1; - } - v = ae_v_dotproduct(&state->bufyk.ptr.pp_double[state->bufsize-1][0], 1, &state->bufsk.ptr.pp_double[state->bufsize-1][0], 1, ae_v_len(0,n-1)); - vv = ae_v_dotproduct(&state->bufyk.ptr.pp_double[state->bufsize-1][0], 1, &state->bufyk.ptr.pp_double[state->bufsize-1][0], 1, ae_v_len(0,n-1)); - if( ae_fp_eq(v,(double)(0))||ae_fp_eq(vv,(double)(0)) ) - { - - /* - * Strange internal error in LBFGS - either YK=0 - * (which should not have been) or (SK,YK)=0 (again, - * unexpected). It should not take place because - * MCINFO=1, which signals "good" step. But just - * to be sure we have special branch of code which - * restarts LBFGS - */ - goto lbl_40; - } - state->bufrho.ptr.p_double[state->bufsize-1] = 1/v; - ae_assert(state->bufsize<=m, "MinBLEIC: internal error", _state); - - /* - * Update length of the good step - */ - v = (double)(0); - vv = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr((state->sas.xc.ptr.p_double[i]-state->xp.ptr.p_double[i])/state->s.ptr.p_double[i], _state); - vv = vv+ae_sqr(state->sas.xc.ptr.p_double[i]-state->xp.ptr.p_double[i], _state); - } - state->lastgoodstep = ae_sqrt(vv, _state); - minbleic_updateestimateofgoodstep(&state->lastscaledgoodstep, ae_sqrt(v, _state), _state); - } - - /* - * Check stopping criteria - * - * Step size and function-based stopping criteria are tested only - * for step which satisfies Wolfe conditions and is the first step of - * LBFGS (subsequent steps may accumulate active constraints thus - * they should NOT be used for stopping; step size or function change - * may be small when constrained, but these constraints may be - * deactivated by the subsequent steps). - * - * MaxIts-based stopping condition is checked for all kinds of steps. - */ - if( mcinfo==1&&state->steepestdescentstep ) - { - - /* - * Step is small enough - */ - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr((state->sas.xc.ptr.p_double[i]-state->xp.ptr.p_double[i])/state->s.ptr.p_double[i], _state); - } - v = ae_sqrt(v, _state); - if( ae_fp_less_eq(v,state->epsx) ) - { - state->repterminationtype = 2; - goto lbl_40; - } - - /* - * Function change is small enough - */ - if( ae_fp_less_eq(ae_fabs(state->fp-state->fc, _state),state->epsf*ae_maxreal(ae_fabs(state->fc, _state), ae_maxreal(ae_fabs(state->fp, _state), 1.0, _state), _state)) ) - { - state->repterminationtype = 1; - goto lbl_40; - } - } - if( state->maxits>0&&state->repinneriterationscount>=state->maxits ) - { - state->repterminationtype = 5; - goto lbl_40; - } - - /* - * Clear "steepest descent" flag. - */ - state->steepestdescentstep = ae_false; - - /* - * Smooth reset (LBFGS memory model is refreshed) or hard restart: - * * LBFGS model is refreshed, if line search was performed with activation of constraints - * * algorithm is restarted if scaled gradient decreased below GDecay - */ - if( actstatus>=0 ) - { - state->bufsize = 0; - goto lbl_39; - } - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(state->cgc.ptr.p_double[i]*state->s.ptr.p_double[i], _state); - } - if( ae_fp_less(ae_sqrt(v, _state),gdecay*ginit) ) - { - goto lbl_40; - } - goto lbl_39; -lbl_40: - if( state->userterminationneeded ) - { - - /* - * User requested termination - */ - state->repterminationtype = 8; - goto lbl_31; - } - if( state->repterminationtype!=0 ) - { - - /* - * Algorithm terminated - */ - goto lbl_31; - } - - /* - * Decrease decay coefficient. Subsequent L-BFGS stages will - * have more stringent stopping criteria. - */ - gdecay = ae_maxreal(gdecay*minbleic_decaycorrection, minbleic_mindecay, _state); - goto lbl_30; -lbl_31: - sasstopoptimization(&state->sas, _state); - state->repouteriterationscount = 1; - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = n; - state->rstate.ia.ptr.p_int[1] = m; - state->rstate.ia.ptr.p_int[2] = i; - state->rstate.ia.ptr.p_int[3] = j; - state->rstate.ia.ptr.p_int[4] = mcinfo; - state->rstate.ia.ptr.p_int[5] = actstatus; - state->rstate.ia.ptr.p_int[6] = itidx; - state->rstate.ba.ptr.p_bool[0] = b; - state->rstate.ra.ptr.p_double[0] = v; - state->rstate.ra.ptr.p_double[1] = vv; - state->rstate.ra.ptr.p_double[2] = v0; - state->rstate.ra.ptr.p_double[3] = penalty; - state->rstate.ra.ptr.p_double[4] = ginit; - state->rstate.ra.ptr.p_double[5] = gdecay; - return result; -} - - -/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic gradient. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function at the initial point -(note: future versions may also perform check at the final point) and -compares numerical gradient with analytic one provided by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both gradients and specific components highlighted as -suspicious by the OptGuard. - -The primary OptGuard report can be retrieved with minbleicoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with minbleicsetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minbleicoptguardgradient(minbleicstate* state, - double teststep, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(teststep, _state), "MinBLEICOptGuardGradient: TestStep contains NaN or INF", _state); - ae_assert(ae_fp_greater_eq(teststep,(double)(0)), "MinBLEICOptGuardGradient: invalid argument TestStep(TestStep<0)", _state); - state->teststep = teststep; -} - - -/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) -b) nonsmooth target function (non-C1) - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbleicoptguardsmoothness(minbleicstate* state, - ae_int_t level, - ae_state *_state) -{ - - - ae_assert(level==0||level==1, "MinBLEICOptGuardSmoothness: unexpected value of level parameter", _state); - state->smoothnessguardlevel = level; -} - - -/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -=== PRIMARY REPORT ======================================================= - -OptGuard performs several checks which are intended to catch common errors -in the implementation of nonlinear function/gradient: -* incorrect analytic gradient -* discontinuous (non-C0) target functions (constraints) -* nonsmooth (non-C1) target functions (constraints) - -Each of these checks is activated with appropriate function: -* minbleicoptguardgradient() for gradient verification -* minbleicoptguardsmoothness() for C0/C1 checks - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradvidx for specific variable (gradient element) suspected - * rep.badgradxbase, a point where gradient is tested - * rep.badgraduser, user-provided gradient (stored as 2D matrix with - single row in order to make report structure compatible with more - complex optimizers like MinNLC or MinLM) - * rep.badgradnum, reference gradient obtained via numerical - differentiation (stored as 2D matrix with single row in order to make - report structure compatible with more complex optimizers like MinNLC - or MinLM) -* rep.nonc0suspected -* rep.nonc1suspected - -=== ADDITIONAL REPORTS/LOGS ============================================== - -Several different tests are performed to catch C0/C1 errors, you can find -out specific test signaled error by looking to: -* rep.nonc0test0positive, for non-C0 test #0 -* rep.nonc1test0positive, for non-C1 test #0 -* rep.nonc1test1positive, for non-C1 test #1 - -Additional information (including line search logs) can be obtained by -means of: -* minbleicoptguardnonc1test0results() -* minbleicoptguardnonc1test1results() -which return detailed error reports, specific points where discontinuities -were found, and so on. - -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - generic OptGuard report; more detailed reports can be - retrieved with other functions. - -NOTE: false negatives (nonsmooth problems are not identified as nonsmooth - ones) are possible although unlikely. - - The reason is that you need to make several evaluations around - nonsmoothness in order to accumulate enough information about - function curvature. Say, if you start right from the nonsmooth point, - optimizer simply won't get enough data to understand what is going - wrong before it terminates due to abrupt changes in the derivative. - It is also possible that "unlucky" step will move us to the - termination too quickly. - - Our current approach is to have less than 0.1% false negatives in - our test examples (measured with multiple restarts from random - points), and to have exactly 0% false positives. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbleicoptguardresults(minbleicstate* state, - optguardreport* rep, - ae_state *_state) -{ - - _optguardreport_clear(rep); - - smoothnessmonitorexportreport(&state->smonitor, rep, _state); -} - - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #0 - -Nonsmoothness (non-C1) test #0 studies function values (not gradient!) -obtained during line searches and monitors behavior of the directional -derivative estimate. - -This test is less powerful than test #1, but it does not depend on the -gradient values and thus it is more robust against artifacts introduced by -numerical differentiation. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #0 "strong" report - lngrep - C1 test #0 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbleicoptguardnonc1test0results(minbleicstate* state, - optguardnonc1test0report* strrep, - optguardnonc1test0report* lngrep, - ae_state *_state) -{ - - _optguardnonc1test0report_clear(strrep); - _optguardnonc1test0report_clear(lngrep); - - smoothnessmonitorexportc1test0report(&state->smonitor.nonc1test0strrep, &state->lastscaleused, strrep, _state); - smoothnessmonitorexportc1test0report(&state->smonitor.nonc1test0lngrep, &state->lastscaleused, lngrep, _state); -} - - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #1 - -Nonsmoothness (non-C1) test #1 studies individual components of the -gradient computed during line search. - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #1 "strong" report - lngrep - C1 test #1 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbleicoptguardnonc1test1results(minbleicstate* state, - optguardnonc1test1report* strrep, - optguardnonc1test1report* lngrep, - ae_state *_state) -{ - - _optguardnonc1test1report_clear(strrep); - _optguardnonc1test1report_clear(lngrep); - - smoothnessmonitorexportc1test1report(&state->smonitor.nonc1test1strrep, &state->lastscaleused, strrep, _state); - smoothnessmonitorexportc1test1report(&state->smonitor.nonc1test1lngrep, &state->lastscaleused, lngrep, _state); -} - - -/************************************************************************* -BLEIC results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report. You should check Rep.TerminationType - in order to distinguish successful termination from - unsuccessful one: - * -8 internal integrity control detected infinite or - NAN values in function/gradient. Abnormal - termination signalled. - * -3 inconsistent constraints. Feasible point is - either nonexistent or too hard to find. Try to - restart optimizer with better initial approximation - * 1 relative function improvement is no more than EpsF. - * 2 scaled step is no more than EpsX. - * 4 scaled gradient norm is no more than EpsG. - * 5 MaxIts steps was taken - * 8 terminated by user who called minbleicrequesttermination(). - X contains point which was "current accepted" when - termination request was submitted. - More information about fields of this structure can be - found in the comments on MinBLEICReport datatype. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicresults(minbleicstate* state, - /* Real */ ae_vector* x, - minbleicreport* rep, - ae_state *_state) -{ - - ae_vector_clear(x); - _minbleicreport_clear(rep); - - minbleicresultsbuf(state, x, rep, _state); -} - - -/************************************************************************* -BLEIC results - -Buffered implementation of MinBLEICResults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicresultsbuf(minbleicstate* state, - /* Real */ ae_vector* x, - minbleicreport* rep, - ae_state *_state) -{ - ae_int_t i; - - - if( x->cntnmain ) - { - ae_vector_set_length(x, state->nmain, _state); - } - rep->iterationscount = state->repinneriterationscount; - rep->inneriterationscount = state->repinneriterationscount; - rep->outeriterationscount = state->repouteriterationscount; - rep->nfev = state->repnfev; - rep->varidx = state->repvaridx; - rep->terminationtype = state->repterminationtype; - if( state->repterminationtype>0 ) - { - ae_v_move(&x->ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,state->nmain-1)); - } - else - { - for(i=0; i<=state->nmain-1; i++) - { - x->ptr.p_double[i] = _state->v_nan; - } - } - rep->debugeqerr = state->repdebugeqerr; - rep->debugfs = state->repdebugfs; - rep->debugff = state->repdebugff; - rep->debugdx = state->repdebugdx; - rep->debugfeasqpits = state->repdebugfeasqpits; - rep->debugfeasgpaits = state->repdebugfeasgpaits; -} - - -/************************************************************************* -This subroutine restarts algorithm from new point. -All optimization parameters (including constraints) are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure previously allocated with MinBLEICCreate call. - X - new starting point. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicrestartfrom(minbleicstate* state, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t n; - - - n = state->nmain; - - /* - * First, check for errors in the inputs - */ - ae_assert(x->cnt>=n, "MinBLEICRestartFrom: Length(X)xstart.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - - /* - * prepare RComm facilities - */ - ae_vector_set_length(&state->rstate.ia, 6+1, _state); - ae_vector_set_length(&state->rstate.ba, 0+1, _state); - ae_vector_set_length(&state->rstate.ra, 5+1, _state); - state->rstate.stage = -1; - minbleic_clearrequestfields(state, _state); - sasstopoptimization(&state->sas, _state); -} - - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void minbleicrequesttermination(minbleicstate* state, ae_state *_state) -{ - - - state->userterminationneeded = ae_true; -} - - -/************************************************************************* -This subroutine finalizes internal structures after emergency termination -from State.LSStart report (see comments on MinBLEICState for more information). - -INPUT PARAMETERS: - State - structure after exit from LSStart report - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicemergencytermination(minbleicstate* state, ae_state *_state) -{ - - - sasstopoptimization(&state->sas, _state); -} - - -/************************************************************************* -Clears request fileds (to be sure that we don't forget to clear something) -*************************************************************************/ -static void minbleic_clearrequestfields(minbleicstate* state, - ae_state *_state) -{ - - - state->needf = ae_false; - state->needfg = ae_false; - state->xupdated = ae_false; - state->lsstart = ae_false; -} - - -/************************************************************************* -Internal initialization subroutine -*************************************************************************/ -static void minbleic_minbleicinitinternal(ae_int_t n, - /* Real */ ae_vector* x, - double diffstep, - minbleicstate* state, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_matrix c; - ae_vector ct; - - ae_frame_make(_state, &_frame_block); - memset(&c, 0, sizeof(c)); - memset(&ct, 0, sizeof(ct)); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - - - /* - * Initialize - */ - state->teststep = (double)(0); - state->smoothnessguardlevel = 0; - smoothnessmonitorinit(&state->smonitor, &state->s, 0, 0, ae_false, _state); - state->nmain = n; - state->diffstep = diffstep; - sasinit(n, &state->sas, _state); - ae_vector_set_length(&state->bndl, n, _state); - ae_vector_set_length(&state->hasbndl, n, _state); - ae_vector_set_length(&state->bndu, n, _state); - ae_vector_set_length(&state->hasbndu, n, _state); - ae_vector_set_length(&state->xstart, n, _state); - ae_vector_set_length(&state->cgc, n, _state); - ae_vector_set_length(&state->ugc, n, _state); - ae_vector_set_length(&state->xn, n, _state); - ae_vector_set_length(&state->cgn, n, _state); - ae_vector_set_length(&state->ugn, n, _state); - ae_vector_set_length(&state->xp, n, _state); - ae_vector_set_length(&state->d, n, _state); - ae_vector_set_length(&state->s, n, _state); - ae_vector_set_length(&state->invs, n, _state); - ae_vector_set_length(&state->lastscaleused, n, _state); - ae_vector_set_length(&state->x, n, _state); - ae_vector_set_length(&state->g, n, _state); - ae_vector_set_length(&state->work, n, _state); - for(i=0; i<=n-1; i++) - { - state->bndl.ptr.p_double[i] = _state->v_neginf; - state->hasbndl.ptr.p_bool[i] = ae_false; - state->bndu.ptr.p_double[i] = _state->v_posinf; - state->hasbndu.ptr.p_bool[i] = ae_false; - state->s.ptr.p_double[i] = 1.0; - state->invs.ptr.p_double[i] = 1.0; - state->lastscaleused.ptr.p_double[i] = 1.0; - } - minbleicsetlc(state, &c, &ct, 0, _state); - minbleicsetcond(state, 0.0, 0.0, 0.0, 0, _state); - minbleicsetxrep(state, ae_false, _state); - minbleicsetdrep(state, ae_false, _state); - minbleicsetstpmax(state, 0.0, _state); - minbleicsetprecdefault(state, _state); - minbleicrestartfrom(state, x, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This subroutine updates estimate of the good step length given: -1) previous estimate -2) new length of the good step - -It makes sure that estimate does not change too rapidly - ratio of new and -old estimates will be at least 0.01, at most 100.0 - -In case previous estimate of good step is zero (no estimate), new estimate -is used unconditionally. - - -- ALGLIB -- - Copyright 16.01.2013 by Bochkanov Sergey -*************************************************************************/ -static void minbleic_updateestimateofgoodstep(double* estimate, - double newstep, - ae_state *_state) -{ - - - if( ae_fp_eq(*estimate,(double)(0)) ) - { - *estimate = newstep; - return; - } - if( ae_fp_less(newstep,*estimate*0.01) ) - { - *estimate = *estimate*0.01; - return; - } - if( ae_fp_greater(newstep,*estimate*100) ) - { - *estimate = *estimate*100; - return; - } - *estimate = newstep; -} - - -/************************************************************************* -This subroutine estimates relative feasibility error of the point. - -INPUT PARAMETERS: - X - current point (unscaled) - S - scale vector - N - dimensionality - CLEIC - array[NEC+NIC,N+1], constraint matrix, may be unnormalized - NEC - number of equality constraints (come first) - NIC - number of inequality constraints (come last) - -RESULT - feasibility error, good value is ~1E-16...1E-14 - - -- ALGLIB -- - Copyright 16.01.2013 by Bochkanov Sergey -*************************************************************************/ -static double minbleic_feasibilityerror(/* Real */ ae_vector* x, - /* Real */ ae_vector* s, - ae_int_t n, - /* Real */ ae_matrix* cleic, - ae_int_t nec, - ae_int_t nic, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - double v0; - double v1; - double vc; - double vx; - double result; - - - result = (double)(0); - for(i=0; i<=nec+nic-1; i++) - { - v = -cleic->ptr.pp_double[i][n]; - v0 = (double)(0); - v1 = (double)(0); - for(j=0; j<=n-1; j++) - { - vc = cleic->ptr.pp_double[i][j]*s->ptr.p_double[j]; - vx = x->ptr.p_double[j]/s->ptr.p_double[j]; - v = v+vc*vx; - v0 = v0+ae_sqr(vc, _state); - v1 = v1+ae_sqr(vx, _state); - } - v0 = coalesce(ae_sqrt(v0, _state), (double)(1), _state); - v1 = ae_maxreal(ae_sqrt(v1, _state), (double)(1), _state); - if( isas, _state, make_automatic); - ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->diagh, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); - ae_vector_init(&p->ugc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cgc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xn, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ugn, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cgn, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xp, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->cleic, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->hasbndl, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->hasbndu, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xstart, 0, DT_REAL, _state, make_automatic); - _snnlssolver_init(&p->solver, _state, make_automatic); - ae_vector_init(&p->tmpprec, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->work, 0, DT_REAL, _state, make_automatic); - _linminstate_init(&p->lstate, _state, make_automatic); - ae_matrix_init(&p->bufyk, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->bufsk, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bufrho, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->buftheta, 0, DT_REAL, _state, make_automatic); - _smoothnessmonitor_init(&p->smonitor, _state, make_automatic); - ae_vector_init(&p->lastscaleused, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->invs, 0, DT_REAL, _state, make_automatic); -} - - -void _minbleicstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minbleicstate *dst = (minbleicstate*)_dst; - minbleicstate *src = (minbleicstate*)_src; - dst->nmain = src->nmain; - dst->nslack = src->nslack; - dst->epsg = src->epsg; - dst->epsf = src->epsf; - dst->epsx = src->epsx; - dst->maxits = src->maxits; - dst->xrep = src->xrep; - dst->drep = src->drep; - dst->stpmax = src->stpmax; - dst->diffstep = src->diffstep; - _sactiveset_init_copy(&dst->sas, &src->sas, _state, make_automatic); - ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic); - dst->prectype = src->prectype; - ae_vector_init_copy(&dst->diagh, &src->diagh, _state, make_automatic); - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - dst->f = src->f; - ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic); - dst->needf = src->needf; - dst->needfg = src->needfg; - dst->xupdated = src->xupdated; - dst->lsstart = src->lsstart; - dst->steepestdescentstep = src->steepestdescentstep; - dst->boundedstep = src->boundedstep; - dst->userterminationneeded = src->userterminationneeded; - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); - ae_vector_init_copy(&dst->ugc, &src->ugc, _state, make_automatic); - ae_vector_init_copy(&dst->cgc, &src->cgc, _state, make_automatic); - ae_vector_init_copy(&dst->xn, &src->xn, _state, make_automatic); - ae_vector_init_copy(&dst->ugn, &src->ugn, _state, make_automatic); - ae_vector_init_copy(&dst->cgn, &src->cgn, _state, make_automatic); - ae_vector_init_copy(&dst->xp, &src->xp, _state, make_automatic); - dst->fc = src->fc; - dst->fn = src->fn; - dst->fp = src->fp; - ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic); - ae_matrix_init_copy(&dst->cleic, &src->cleic, _state, make_automatic); - dst->nec = src->nec; - dst->nic = src->nic; - dst->lastgoodstep = src->lastgoodstep; - dst->lastscaledgoodstep = src->lastscaledgoodstep; - dst->maxscaledgrad = src->maxscaledgrad; - ae_vector_init_copy(&dst->hasbndl, &src->hasbndl, _state, make_automatic); - ae_vector_init_copy(&dst->hasbndu, &src->hasbndu, _state, make_automatic); - ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic); - ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic); - dst->repinneriterationscount = src->repinneriterationscount; - dst->repouteriterationscount = src->repouteriterationscount; - dst->repnfev = src->repnfev; - dst->repvaridx = src->repvaridx; - dst->repterminationtype = src->repterminationtype; - dst->repdebugeqerr = src->repdebugeqerr; - dst->repdebugfs = src->repdebugfs; - dst->repdebugff = src->repdebugff; - dst->repdebugdx = src->repdebugdx; - dst->repdebugfeasqpits = src->repdebugfeasqpits; - dst->repdebugfeasgpaits = src->repdebugfeasgpaits; - ae_vector_init_copy(&dst->xstart, &src->xstart, _state, make_automatic); - _snnlssolver_init_copy(&dst->solver, &src->solver, _state, make_automatic); - dst->fbase = src->fbase; - dst->fm2 = src->fm2; - dst->fm1 = src->fm1; - dst->fp1 = src->fp1; - dst->fp2 = src->fp2; - dst->xm1 = src->xm1; - dst->xp1 = src->xp1; - dst->gm1 = src->gm1; - dst->gp1 = src->gp1; - dst->cidx = src->cidx; - dst->cval = src->cval; - ae_vector_init_copy(&dst->tmpprec, &src->tmpprec, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - dst->nfev = src->nfev; - dst->mcstage = src->mcstage; - dst->stp = src->stp; - dst->curstpmax = src->curstpmax; - dst->activationstep = src->activationstep; - ae_vector_init_copy(&dst->work, &src->work, _state, make_automatic); - _linminstate_init_copy(&dst->lstate, &src->lstate, _state, make_automatic); - dst->trimthreshold = src->trimthreshold; - dst->nonmonotoniccnt = src->nonmonotoniccnt; - ae_matrix_init_copy(&dst->bufyk, &src->bufyk, _state, make_automatic); - ae_matrix_init_copy(&dst->bufsk, &src->bufsk, _state, make_automatic); - ae_vector_init_copy(&dst->bufrho, &src->bufrho, _state, make_automatic); - ae_vector_init_copy(&dst->buftheta, &src->buftheta, _state, make_automatic); - dst->bufsize = src->bufsize; - dst->teststep = src->teststep; - dst->smoothnessguardlevel = src->smoothnessguardlevel; - _smoothnessmonitor_init_copy(&dst->smonitor, &src->smonitor, _state, make_automatic); - ae_vector_init_copy(&dst->lastscaleused, &src->lastscaleused, _state, make_automatic); - ae_vector_init_copy(&dst->invs, &src->invs, _state, make_automatic); -} - - -void _minbleicstate_clear(void* _p) -{ - minbleicstate *p = (minbleicstate*)_p; - ae_touch_ptr((void*)p); - _sactiveset_clear(&p->sas); - ae_vector_clear(&p->s); - ae_vector_clear(&p->diagh); - ae_vector_clear(&p->x); - ae_vector_clear(&p->g); - _rcommstate_clear(&p->rstate); - ae_vector_clear(&p->ugc); - ae_vector_clear(&p->cgc); - ae_vector_clear(&p->xn); - ae_vector_clear(&p->ugn); - ae_vector_clear(&p->cgn); - ae_vector_clear(&p->xp); - ae_vector_clear(&p->d); - ae_matrix_clear(&p->cleic); - ae_vector_clear(&p->hasbndl); - ae_vector_clear(&p->hasbndu); - ae_vector_clear(&p->bndl); - ae_vector_clear(&p->bndu); - ae_vector_clear(&p->xstart); - _snnlssolver_clear(&p->solver); - ae_vector_clear(&p->tmpprec); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->work); - _linminstate_clear(&p->lstate); - ae_matrix_clear(&p->bufyk); - ae_matrix_clear(&p->bufsk); - ae_vector_clear(&p->bufrho); - ae_vector_clear(&p->buftheta); - _smoothnessmonitor_clear(&p->smonitor); - ae_vector_clear(&p->lastscaleused); - ae_vector_clear(&p->invs); -} - - -void _minbleicstate_destroy(void* _p) -{ - minbleicstate *p = (minbleicstate*)_p; - ae_touch_ptr((void*)p); - _sactiveset_destroy(&p->sas); - ae_vector_destroy(&p->s); - ae_vector_destroy(&p->diagh); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->g); - _rcommstate_destroy(&p->rstate); - ae_vector_destroy(&p->ugc); - ae_vector_destroy(&p->cgc); - ae_vector_destroy(&p->xn); - ae_vector_destroy(&p->ugn); - ae_vector_destroy(&p->cgn); - ae_vector_destroy(&p->xp); - ae_vector_destroy(&p->d); - ae_matrix_destroy(&p->cleic); - ae_vector_destroy(&p->hasbndl); - ae_vector_destroy(&p->hasbndu); - ae_vector_destroy(&p->bndl); - ae_vector_destroy(&p->bndu); - ae_vector_destroy(&p->xstart); - _snnlssolver_destroy(&p->solver); - ae_vector_destroy(&p->tmpprec); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->work); - _linminstate_destroy(&p->lstate); - ae_matrix_destroy(&p->bufyk); - ae_matrix_destroy(&p->bufsk); - ae_vector_destroy(&p->bufrho); - ae_vector_destroy(&p->buftheta); - _smoothnessmonitor_destroy(&p->smonitor); - ae_vector_destroy(&p->lastscaleused); - ae_vector_destroy(&p->invs); -} - - -void _minbleicreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minbleicreport *p = (minbleicreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _minbleicreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minbleicreport *dst = (minbleicreport*)_dst; - minbleicreport *src = (minbleicreport*)_src; - dst->iterationscount = src->iterationscount; - dst->nfev = src->nfev; - dst->varidx = src->varidx; - dst->terminationtype = src->terminationtype; - dst->debugeqerr = src->debugeqerr; - dst->debugfs = src->debugfs; - dst->debugff = src->debugff; - dst->debugdx = src->debugdx; - dst->debugfeasqpits = src->debugfeasqpits; - dst->debugfeasgpaits = src->debugfeasgpaits; - dst->inneriterationscount = src->inneriterationscount; - dst->outeriterationscount = src->outeriterationscount; -} - - -void _minbleicreport_clear(void* _p) -{ - minbleicreport *p = (minbleicreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _minbleicreport_destroy(void* _p) -{ - minbleicreport *p = (minbleicreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_QPBLEICSOLVER) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function initializes QPBLEICSettings structure with default settings. - -Newly created structure MUST be initialized by default settings - or by -copy of the already initialized structure. - - -- ALGLIB -- - Copyright 14.05.2011 by Bochkanov Sergey -*************************************************************************/ -void qpbleicloaddefaults(ae_int_t nmain, - qpbleicsettings* s, - ae_state *_state) -{ - - - s->epsg = 0.0; - s->epsf = 0.0; - s->epsx = 1.0E-6; - s->maxits = 0; -} - - -/************************************************************************* -This function initializes QPBLEICSettings structure with copy of another, -already initialized structure. - - -- ALGLIB -- - Copyright 14.05.2011 by Bochkanov Sergey -*************************************************************************/ -void qpbleiccopysettings(qpbleicsettings* src, - qpbleicsettings* dst, - ae_state *_state) -{ - - - dst->epsg = src->epsg; - dst->epsf = src->epsf; - dst->epsx = src->epsx; - dst->maxits = src->maxits; -} - - -/************************************************************************* -This function runs QPBLEIC solver; it returns after optimization process -was completed. Following QP problem is solved: - - min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin)) - -subject to boundary constraints. - -INPUT PARAMETERS: - AC - for dense problems (AKind=0), A-term of CQM object - contains system matrix. Other terms are unspecified - and should not be referenced. - SparseAC - for sparse problems (AKind=1 - AKind - sparse matrix format: - * 0 for dense matrix - * 1 for sparse matrix - SparseUpper - which triangle of SparseAC stores matrix - upper or - lower one (for dense matrices this parameter is not - actual). - AbsASum - SUM(|A[i,j]|) - AbsASum2 - SUM(A[i,j]^2) - BC - linear term, array[NC] - BndLC - lower bound, array[NC] - BndUC - upper bound, array[NC] - SC - scale vector, array[NC]: - * I-th element contains scale of I-th variable, - * SC[I]>0 - XOriginC - origin term, array[NC]. Can be zero. - NC - number of variables in the original formulation (no - slack variables). - CLEICC - linear equality/inequality constraints. Present version - of this function does NOT provide publicly available - support for linear constraints. This feature will be - introduced in the future versions of the function. - NEC, NIC - number of equality/inequality constraints. - MUST BE ZERO IN THE CURRENT VERSION!!! - Settings - QPBLEICSettings object initialized by one of the initialization - functions. - SState - object which stores temporaries: - * if uninitialized object was passed, FirstCall parameter MUST - be set to True; object will be automatically initialized by the - function, and FirstCall will be set to False. - * if FirstCall=False, it is assumed that this parameter was already - initialized by previous call to this function with same - problem dimensions (variable count N). - FirstCall - whether it is first call of this function for this specific - instance of SState, with this number of variables N specified. - XS - initial point, array[NC] - - -OUTPUT PARAMETERS: - XS - last point - FirstCall - uncondtionally set to False - TerminationType-termination type: - * - * - * - - -- ALGLIB -- - Copyright 14.05.2011 by Bochkanov Sergey -*************************************************************************/ -void qpbleicoptimize(convexquadraticmodel* a, - sparsematrix* sparsea, - ae_int_t akind, - ae_bool sparseaupper, - double absasum, - double absasum2, - /* Real */ ae_vector* b, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - ae_int_t n, - /* Real */ ae_matrix* cleic, - ae_int_t nec, - ae_int_t nic, - qpbleicsettings* settings, - qpbleicbuffers* sstate, - ae_bool* firstcall, - /* Real */ ae_vector* xs, - ae_int_t* terminationtype, - ae_state *_state) -{ - ae_int_t i; - double d2; - double d1; - double d0; - double v; - double v0; - double v1; - double md; - double mx; - double mb; - ae_int_t d1est; - ae_int_t d2est; - - *terminationtype = 0; - - ae_assert(akind==0||akind==1, "QPBLEICOptimize: unexpected AKind", _state); - sstate->repinneriterationscount = 0; - sstate->repouteriterationscount = 0; - *terminationtype = 0; - - /* - * Prepare solver object, if needed - */ - if( *firstcall ) - { - minbleiccreate(n, xs, &sstate->solver, _state); - *firstcall = ae_false; - } - - /* - * Prepare max(|B|) - */ - mb = 0.0; - for(i=0; i<=n-1; i++) - { - mb = ae_maxreal(mb, ae_fabs(b->ptr.p_double[i], _state), _state); - } - - /* - * Temporaries - */ - ivectorsetlengthatleast(&sstate->tmpi, nec+nic, _state); - rvectorsetlengthatleast(&sstate->tmp0, n, _state); - rvectorsetlengthatleast(&sstate->tmp1, n, _state); - for(i=0; i<=nec-1; i++) - { - sstate->tmpi.ptr.p_int[i] = 0; - } - for(i=0; i<=nic-1; i++) - { - sstate->tmpi.ptr.p_int[nec+i] = -1; - } - minbleicsetlc(&sstate->solver, cleic, &sstate->tmpi, nec+nic, _state); - minbleicsetbc(&sstate->solver, bndl, bndu, _state); - minbleicsetdrep(&sstate->solver, ae_true, _state); - minbleicsetcond(&sstate->solver, ae_minrealnumber, 0.0, 0.0, settings->maxits, _state); - minbleicsetscale(&sstate->solver, s, _state); - minbleicsetprecscale(&sstate->solver, _state); - minbleicrestartfrom(&sstate->solver, xs, _state); - while(minbleiciteration(&sstate->solver, _state)) - { - - /* - * Line search started - */ - if( sstate->solver.lsstart ) - { - - /* - * Iteration counters: - * * inner iterations count is increased on every line search - * * outer iterations count is increased only at steepest descent line search - */ - inc(&sstate->repinneriterationscount, _state); - if( sstate->solver.steepestdescentstep ) - { - inc(&sstate->repouteriterationscount, _state); - } - - /* - * Build quadratic model of F along descent direction: - * - * F(x+alpha*d) = D2*alpha^2 + D1*alpha + D0 - * - * Calculate estimates of linear and quadratic term - * (term magnitude is compared with magnitude of numerical errors) - */ - d0 = sstate->solver.f; - d1 = ae_v_dotproduct(&sstate->solver.d.ptr.p_double[0], 1, &sstate->solver.g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - d2 = (double)(0); - if( akind==0 ) - { - d2 = cqmxtadx2(a, &sstate->solver.d, &sstate->tmp0, _state); - } - if( akind==1 ) - { - sparsesmv(sparsea, sparseaupper, &sstate->solver.d, &sstate->tmp0, _state); - d2 = 0.0; - for(i=0; i<=n-1; i++) - { - d2 = d2+sstate->solver.d.ptr.p_double[i]*sstate->tmp0.ptr.p_double[i]; - } - d2 = 0.5*d2; - } - mx = 0.0; - md = 0.0; - for(i=0; i<=n-1; i++) - { - mx = ae_maxreal(mx, ae_fabs(sstate->solver.x.ptr.p_double[i], _state), _state); - md = ae_maxreal(md, ae_fabs(sstate->solver.d.ptr.p_double[i], _state), _state); - } - estimateparabolicmodel(absasum, absasum2, mx, mb, md, d1, d2, &d1est, &d2est, _state); - - /* - * Tests for "normal" convergence. - * - * This line search may be started from steepest descent - * stage (stage 2) or from L-BFGS stage (stage 3) of the - * BLEIC algorithm. Depending on stage type, different - * checks are performed. - * - * Say, L-BFGS stage is an equality-constrained refinement - * stage of BLEIC. This stage refines current iterate - * under "frozen" equality constraints. We can terminate - * iterations at this stage only when we encounter - * unconstrained direction of negative curvature. In all - * other cases (say, when constrained gradient is zero) - * we should not terminate algorithm because everything may - * change after de-activating presently active constraints. - * - * Tests for convergence are performed only at "steepest descent" stage - * of the BLEIC algorithm, and only when function is non-concave - * (D2 is positive or approximately zero) along direction D. - * - * NOTE: we do not test iteration count (MaxIts) here, because - * this stopping condition is tested by BLEIC itself. - */ - if( sstate->solver.steepestdescentstep&&d2est>=0 ) - { - if( d1est>=0 ) - { - - /* - * "Emergency" stopping condition: D is non-descent direction. - * Sometimes it is possible because of numerical noise in the - * target function. - */ - *terminationtype = 4; - for(i=0; i<=n-1; i++) - { - xs->ptr.p_double[i] = sstate->solver.x.ptr.p_double[i]; - } - break; - } - if( d2est>0 ) - { - - /* - * Stopping condition #4 - gradient norm is small: - * - * 1. rescale State.Solver.D and State.Solver.G according to - * current scaling, store results to Tmp0 and Tmp1. - * 2. Normalize Tmp0 (scaled direction vector). - * 3. compute directional derivative (in scaled variables), - * which is equal to DOTPRODUCT(Tmp0,Tmp1). - */ - v = (double)(0); - for(i=0; i<=n-1; i++) - { - sstate->tmp0.ptr.p_double[i] = sstate->solver.d.ptr.p_double[i]/s->ptr.p_double[i]; - sstate->tmp1.ptr.p_double[i] = sstate->solver.g.ptr.p_double[i]*s->ptr.p_double[i]; - v = v+ae_sqr(sstate->tmp0.ptr.p_double[i], _state); - } - ae_assert(ae_fp_greater(v,(double)(0)), "QPBLEICOptimize: inernal errror (scaled direction is zero)", _state); - v = 1/ae_sqrt(v, _state); - ae_v_muld(&sstate->tmp0.ptr.p_double[0], 1, ae_v_len(0,n-1), v); - v = ae_v_dotproduct(&sstate->tmp0.ptr.p_double[0], 1, &sstate->tmp1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( ae_fp_less_eq(ae_fabs(v, _state),settings->epsg) ) - { - *terminationtype = 4; - for(i=0; i<=n-1; i++) - { - xs->ptr.p_double[i] = sstate->solver.x.ptr.p_double[i]; - } - break; - } - - /* - * Stopping condition #1 - relative function improvement is small: - * - * 1. calculate steepest descent step: V = -D1/(2*D2) - * 2. calculate function change: V1= D2*V^2 + D1*V - * 3. stop if function change is small enough - */ - v = -d1/(2*d2); - v1 = d2*v*v+d1*v; - if( ae_fp_less_eq(ae_fabs(v1, _state),settings->epsf*ae_maxreal(d0, 1.0, _state)) ) - { - *terminationtype = 1; - for(i=0; i<=n-1; i++) - { - xs->ptr.p_double[i] = sstate->solver.x.ptr.p_double[i]; - } - break; - } - - /* - * Stopping condition #2 - scaled step is small: - * - * 1. calculate step multiplier V0 (step itself is D*V0) - * 2. calculate scaled step length V - * 3. stop if step is small enough - */ - v0 = -d1/(2*d2); - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(v0*sstate->solver.d.ptr.p_double[i]/s->ptr.p_double[i], _state); - } - if( ae_fp_less_eq(ae_sqrt(v, _state),settings->epsx) ) - { - *terminationtype = 2; - for(i=0; i<=n-1; i++) - { - xs->ptr.p_double[i] = sstate->solver.x.ptr.p_double[i]; - } - break; - } - } - } - - /* - * Test for unconstrained direction of negative curvature - */ - if( (d2est<0||(d2est==0&&d1est<0))&&!sstate->solver.boundedstep ) - { - - /* - * Function is unbounded from below: - * * function will decrease along D, i.e. either: - * * D2<0 - * * D2=0 and D1<0 - * * step is unconstrained - * - * If these conditions are true, we abnormally terminate QP - * algorithm with return code -4 (we can do so at any stage - * of BLEIC - whether it is L-BFGS or steepest descent one). - */ - *terminationtype = -4; - for(i=0; i<=n-1; i++) - { - xs->ptr.p_double[i] = sstate->solver.x.ptr.p_double[i]; - } - break; - } - - /* - * Suggest new step (only if D1 is negative far away from zero, - * D2 is positive far away from zero). - */ - if( d1est<0&&d2est>0 ) - { - sstate->solver.stp = safeminposrv(-d1, 2*d2, sstate->solver.curstpmax, _state); - } - } - - /* - * Gradient evaluation - */ - if( sstate->solver.needfg ) - { - for(i=0; i<=n-1; i++) - { - sstate->tmp0.ptr.p_double[i] = sstate->solver.x.ptr.p_double[i]-xorigin->ptr.p_double[i]; - } - if( akind==0 ) - { - cqmadx(a, &sstate->tmp0, &sstate->tmp1, _state); - } - if( akind==1 ) - { - sparsesmv(sparsea, sparseaupper, &sstate->tmp0, &sstate->tmp1, _state); - } - v0 = ae_v_dotproduct(&sstate->tmp0.ptr.p_double[0], 1, &sstate->tmp1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v1 = ae_v_dotproduct(&sstate->tmp0.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,n-1)); - sstate->solver.f = 0.5*v0+v1; - ae_v_move(&sstate->solver.g.ptr.p_double[0], 1, &sstate->tmp1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_add(&sstate->solver.g.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,n-1)); - } - } - if( *terminationtype==0 ) - { - - /* - * BLEIC optimizer was terminated by one of its inner stopping - * conditions. Usually it is iteration counter (if such - * stopping condition was specified by user). - */ - minbleicresultsbuf(&sstate->solver, xs, &sstate->solverrep, _state); - *terminationtype = sstate->solverrep.terminationtype; - } - else - { - - /* - * BLEIC optimizer was terminated in "emergency" mode by QP - * solver. - * - * NOTE: such termination is "emergency" only when viewed from - * BLEIC's position. QP solver sees such termination as - * routine one, triggered by QP's stopping criteria. - */ - minbleicemergencytermination(&sstate->solver, _state); - } -} - - -void _qpbleicsettings_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - qpbleicsettings *p = (qpbleicsettings*)_p; - ae_touch_ptr((void*)p); -} - - -void _qpbleicsettings_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - qpbleicsettings *dst = (qpbleicsettings*)_dst; - qpbleicsettings *src = (qpbleicsettings*)_src; - dst->epsg = src->epsg; - dst->epsf = src->epsf; - dst->epsx = src->epsx; - dst->maxits = src->maxits; -} - - -void _qpbleicsettings_clear(void* _p) -{ - qpbleicsettings *p = (qpbleicsettings*)_p; - ae_touch_ptr((void*)p); -} - - -void _qpbleicsettings_destroy(void* _p) -{ - qpbleicsettings *p = (qpbleicsettings*)_p; - ae_touch_ptr((void*)p); -} - - -void _qpbleicbuffers_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - qpbleicbuffers *p = (qpbleicbuffers*)_p; - ae_touch_ptr((void*)p); - _minbleicstate_init(&p->solver, _state, make_automatic); - _minbleicreport_init(&p->solverrep, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpi, 0, DT_INT, _state, make_automatic); -} - - -void _qpbleicbuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - qpbleicbuffers *dst = (qpbleicbuffers*)_dst; - qpbleicbuffers *src = (qpbleicbuffers*)_src; - _minbleicstate_init_copy(&dst->solver, &src->solver, _state, make_automatic); - _minbleicreport_init_copy(&dst->solverrep, &src->solverrep, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic); - ae_vector_init_copy(&dst->tmpi, &src->tmpi, _state, make_automatic); - dst->repinneriterationscount = src->repinneriterationscount; - dst->repouteriterationscount = src->repouteriterationscount; -} - - -void _qpbleicbuffers_clear(void* _p) -{ - qpbleicbuffers *p = (qpbleicbuffers*)_p; - ae_touch_ptr((void*)p); - _minbleicstate_clear(&p->solver); - _minbleicreport_clear(&p->solverrep); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->tmp1); - ae_vector_clear(&p->tmpi); -} - - -void _qpbleicbuffers_destroy(void* _p) -{ - qpbleicbuffers *p = (qpbleicbuffers*)_p; - ae_touch_ptr((void*)p); - _minbleicstate_destroy(&p->solver); - _minbleicreport_destroy(&p->solverrep); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->tmp1); - ae_vector_destroy(&p->tmpi); -} - - -#endif -#if defined(AE_COMPILE_MINQP) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* - CONSTRAINED QUADRATIC PROGRAMMING - -The subroutine creates QP optimizer. After initial creation, it contains -default optimization problem with zero quadratic and linear terms and no -constraints. - -In order to actually solve something you should: -* set cost vector with minqpsetlinearterm() -* set variable bounds with minqpsetbc() or minqpsetbcall() -* specify constraint matrix with one of the following functions: - * modern API: - * minqpsetlc2() for sparse two-sided constraints AL <= A*x <= AU - * minqpsetlc2dense() for dense two-sided constraints AL <= A*x <= AU - * minqpsetlc2mixed() for mixed two-sided constraints AL <= A*x <= AU - * minqpaddlc2dense() to add one dense row to dense constraint submatrix - * minqpaddlc2() to add one sparse row to sparse constraint submatrix - * legacy API: - * minqpsetlc() for dense one-sided equality/inequality constraints - * minqpsetlcsparse() for sparse one-sided equality/inequality constraints - * minqpsetlcmixed() for mixed dense/sparse one-sided equality/inequality constraints -* choose appropriate QP solver and set it and its stopping criteria by - means of minqpsetalgo??????() function -* call minqpoptimize() to run the solver and minqpresults() to get the - solution vector and additional information. - -Following solvers are recommended for convex and semidefinite problems: -* QuickQP for dense problems with box-only constraints (or no constraints - at all) -* DENSE-IPM-QP for convex or semidefinite problems with medium (up - to several thousands) variable count, dense/sparse quadratic term and - any number (up to many thousands) of dense/sparse general linear - constraints -* SPARSE-IPM-QP for convex or semidefinite problems with large (many - thousands) variable count, sparse quadratic term AND linear constraints. - -If your problem happens to be nonconvex, but either (a) is effectively -convexified under constraints, or (b) has unique solution even with -nonconvex target, then you can use: -* QuickQP for dense nonconvex problems with box-only constraints -* DENSE-AUL-QP for dense nonconvex problems which are effectively - convexified under constraints with up to several thousands of variables - and any (small or large) number of general linear constraints -* QP-BLEIC for dense/sparse problems with small (up to several hundreds) - number of general linear constraints and arbitrarily large variable - count. - -INPUT PARAMETERS: - N - problem size - -OUTPUT PARAMETERS: - State - optimizer with zero quadratic/linear terms - and no constraints - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpcreate(ae_int_t n, minqpstate* state, ae_state *_state) -{ - ae_int_t i; - - _minqpstate_clear(state); - - ae_assert(n>=1, "MinQPCreate: N<1", _state); - - /* - * initialize QP solver - */ - state->n = n; - state->mdense = 0; - state->msparse = 0; - state->repterminationtype = 0; - state->absamax = (double)(1); - state->absasum = (double)(1); - state->absasum2 = (double)(1); - state->akind = 0; - state->sparseaupper = ae_false; - cqminit(n, &state->a, _state); - ae_vector_set_length(&state->b, n, _state); - ae_vector_set_length(&state->bndl, n, _state); - ae_vector_set_length(&state->bndu, n, _state); - ae_vector_set_length(&state->havebndl, n, _state); - ae_vector_set_length(&state->havebndu, n, _state); - ae_vector_set_length(&state->s, n, _state); - ae_vector_set_length(&state->startx, n, _state); - ae_vector_set_length(&state->xorigin, n, _state); - ae_vector_set_length(&state->xs, n, _state); - rvectorsetlengthatleast(&state->replagbc, n, _state); - for(i=0; i<=n-1; i++) - { - state->bndl.ptr.p_double[i] = _state->v_neginf; - state->bndu.ptr.p_double[i] = _state->v_posinf; - state->havebndl.ptr.p_bool[i] = ae_false; - state->havebndu.ptr.p_bool[i] = ae_false; - state->b.ptr.p_double[i] = 0.0; - state->startx.ptr.p_double[i] = 0.0; - state->xorigin.ptr.p_double[i] = 0.0; - state->s.ptr.p_double[i] = 1.0; - state->replagbc.ptr.p_double[i] = 0.0; - } - state->stype = 0; - state->havex = ae_false; - minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0, _state); - qqploaddefaults(n, &state->qqpsettingsuser, _state); - qpbleicloaddefaults(n, &state->qpbleicsettingsuser, _state); - qpdenseaulloaddefaults(n, &state->qpdenseaulsettingsuser, _state); - state->qpbleicfirstcall = ae_true; - state->dbgskipconstraintnormalization = ae_false; - state->veps = 0.0; -} - - -/************************************************************************* -This function sets linear term for QP solver. - -By default, linear term is zero. - -INPUT PARAMETERS: - State - structure which stores algorithm state - B - linear term, array[N]. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlinearterm(minqpstate* state, - /* Real */ ae_vector* b, - ae_state *_state) -{ - ae_int_t n; - - - n = state->n; - ae_assert(b->cnt>=n, "MinQPSetLinearTerm: Length(B)n; - ae_assert(a->rows>=n, "MinQPSetQuadraticTerm: Rows(A)cols>=n, "MinQPSetQuadraticTerm: Cols(A)n; - ae_assert(sparsegetnrows(a, _state)==n, "MinQPSetQuadraticTermSparse: Rows(A)<>N", _state); - ae_assert(sparsegetncols(a, _state)==n, "MinQPSetQuadraticTermSparse: Cols(A)<>N", _state); - sparsecopytocrsbuf(a, &state->sparsea, _state); - state->sparseaupper = isupper; - state->akind = 1; - - /* - * Estimate norm of A - * (it will be used later in the quadratic penalty function) - */ - state->absamax = (double)(0); - state->absasum = (double)(0); - state->absasum2 = (double)(0); - t0 = 0; - t1 = 0; - while(sparseenumerate(a, &t0, &t1, &i, &j, &v, _state)) - { - if( i==j ) - { - - /* - * Diagonal terms are counted only once - */ - state->absamax = ae_maxreal(state->absamax, v, _state); - state->absasum = state->absasum+v; - state->absasum2 = state->absasum2+v*v; - } - if( (j>i&&isupper)||(jabsamax = ae_maxreal(state->absamax, v, _state); - state->absasum = state->absasum+2*v; - state->absasum2 = state->absasum2+2*v*v; - } - } -} - - -/************************************************************************* -This function sets starting point for QP solver. It is useful to have good -initial approximation to the solution, because it will increase speed of -convergence and identification of active constraints. - -NOTE: interior point solvers ignore initial point provided by user. - -INPUT PARAMETERS: - State - structure which stores algorithm state - X - starting point, array[N]. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetstartingpoint(minqpstate* state, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t n; - - - n = state->n; - ae_assert(x->cnt>=n, "MinQPSetStartingPoint: Length(B)n; - ae_assert(xorigin->cnt>=n, "MinQPSetOrigin: Length(B)cnt>=state->n, "MinQPSetScale: Length(S)n-1; i++) - { - ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinQPSetScale: S contains infinite or NAN elements", _state); - ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "MinQPSetScale: S contains zero elements", _state); - } - for(i=0; i<=state->n-1; i++) - { - state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state); - } - state->stype = 0; -} - - -/************************************************************************* -This function sets automatic evaluation of variable scaling. - -IMPORTANT: this function works only for matrices with positive diagonal - elements! Zero or negative elements will result in -9 error - code being returned. Specify scale vector manually with - minqpsetscale() in such cases. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances) and as -preconditioner. - -The best way to set scaling is to manually specify variable scales. -However, sometimes you just need quick-and-dirty solution - either when -you perform fast prototyping, or when you know your problem well and you -are 100% sure that this quick solution is robust enough in your case. - -One such solution is to evaluate scale of I-th variable as 1/Sqrt(A[i,i]), -where A[i,i] is an I-th diagonal element of the quadratic term. - -Such approach works well sometimes, but you have to be careful here. - -INPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -void minqpsetscaleautodiag(minqpstate* state, ae_state *_state) -{ - - - state->stype = 1; -} - - -/************************************************************************* -This function tells solver to use BLEIC-based algorithm and sets stopping -criteria for the algorithm. - -This algorithm is intended for large-scale problems, possibly nonconvex, -with small number of general linear constraints. Feasible initial point is -essential for good performance. - -IMPORTANT: when DENSE-IPM (or DENSE-AUL for nonconvex problems) solvers - are applicable, their performance is much better than that of - BLEIC-QP. - We recommend you to use BLEIC only when other solvers can not - be used. - -ALGORITHM FEATURES: - -* supports dense and sparse QP problems -* supports box and general linear equality/inequality constraints -* can solve all types of problems (convex, semidefinite, nonconvex) as - long as they are bounded from below under constraints. - Say, it is possible to solve "min{-x^2} subject to -1<=x<=+1". - Of course, global minimum is found only for positive definite and - semidefinite problems. As for indefinite ones - only local minimum is - found. - -ALGORITHM OUTLINE: - -* BLEIC-QP solver is just a driver function for MinBLEIC solver; it solves - quadratic programming problem as general linearly constrained - optimization problem, which is solved by means of BLEIC solver (part of - ALGLIB, active set method). - -ALGORITHM LIMITATIONS: -* This algorithm is inefficient on problems with hundreds and thousands - of general inequality constraints and infeasible initial point. Initial - feasibility detection stage may take too long on such constraint sets. - Consider using DENSE-IPM or DENSE-AUL instead. -* unlike QuickQP solver, this algorithm does not perform Newton steps and - does not use Level 3 BLAS. Being general-purpose active set method, it - can activate constraints only one-by-one. Thus, its performance is lower - than that of QuickQP. -* its precision is also a bit inferior to that of QuickQP. BLEIC-QP - performs only LBFGS steps (no Newton steps), which are good at detecting - neighborhood of the solution, buy needs many iterations to find solution - with more than 6 digits of precision. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|=0 - The subroutine finishes its work if exploratory steepest - descent step on k+1-th iteration satisfies following - condition: |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - EpsX - >=0 - The subroutine finishes its work if exploratory steepest - descent step on k+1-th iteration satisfies following - condition: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - step vector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinQPSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. NOTE: this algorithm uses LBFGS - iterations, which are relatively cheap, but improve - function value only a bit. So you will need many iterations - to converge - from 0.1*N to 10*N, depending on problem's - condition number. - -IT IS VERY IMPORTANT TO CALL MinQPSetScale() WHEN YOU USE THIS ALGORITHM -BECAUSE ITS STOPPING CRITERIA ARE SCALE-DEPENDENT! - -Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead -to automatic stopping criterion selection (presently it is small step -length, but it may change in the future versions of ALGLIB). - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetalgobleic(minqpstate* state, - double epsg, - double epsf, - double epsx, - ae_int_t maxits, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(epsg, _state), "MinQPSetAlgoBLEIC: EpsG is not finite number", _state); - ae_assert(ae_fp_greater_eq(epsg,(double)(0)), "MinQPSetAlgoBLEIC: negative EpsG", _state); - ae_assert(ae_isfinite(epsf, _state), "MinQPSetAlgoBLEIC: EpsF is not finite number", _state); - ae_assert(ae_fp_greater_eq(epsf,(double)(0)), "MinQPSetAlgoBLEIC: negative EpsF", _state); - ae_assert(ae_isfinite(epsx, _state), "MinQPSetAlgoBLEIC: EpsX is not finite number", _state); - ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinQPSetAlgoBLEIC: negative EpsX", _state); - ae_assert(maxits>=0, "MinQPSetAlgoBLEIC: negative MaxIts!", _state); - state->algokind = 2; - if( ((ae_fp_eq(epsg,(double)(0))&&ae_fp_eq(epsf,(double)(0)))&&ae_fp_eq(epsx,(double)(0)))&&maxits==0 ) - { - epsx = 1.0E-6; - } - state->qpbleicsettingsuser.epsg = epsg; - state->qpbleicsettingsuser.epsf = epsf; - state->qpbleicsettingsuser.epsx = epsx; - state->qpbleicsettingsuser.maxits = maxits; -} - - -/************************************************************************* -This function tells QP solver to use DENSE-AUL algorithm and sets stopping -criteria for the algorithm. - -This algorithm is intended for non-convex problems with moderate (up -to several thousands) variable count and arbitrary number of constraints -which are either (a) effectively convexified under constraints or (b) have -unique solution even with nonconvex target. - -IMPORTANT: when DENSE-IPM solver is applicable, its performance is usually - much better than that of DENSE-AUL. - We recommend you to use DENSE-AUL only when other solvers can - not be used. - -ALGORITHM FEATURES: - -* supports box and dense/sparse general linear equality/inequality - constraints -* convergence is theoretically proved for positive-definite (convex) QP - problems. Semidefinite and non-convex problems can be solved as long as - they are bounded from below under constraints, although without - theoretical guarantees. - -ALGORITHM OUTLINE: - -* this algorithm is an augmented Lagrangian method with dense - preconditioner (hence its name). -* it performs several outer iterations in order to refine values of the - Lagrange multipliers. Single outer iteration is a solution of some - unconstrained optimization problem: first it performs dense Cholesky - factorization of the Hessian in order to build preconditioner (adaptive - regularization is applied to enforce positive definiteness), and then - it uses L-BFGS optimizer to solve optimization problem. -* typically you need about 5-10 outer iterations to converge to solution - -ALGORITHM LIMITATIONS: - -* because dense Cholesky driver is used, this algorithm has O(N^2) memory - requirements and O(OuterIterations*N^3) minimum running time. From the - practical point of view, it limits its applicability by several - thousands of variables. - From the other side, variables count is the most limiting factor, - and dependence on constraint count is much more lower. Assuming that - constraint matrix is sparse, it may handle tens of thousands of general - linear constraints. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsX - >=0, stopping criteria for inner optimizer. - Inner iterations are stopped when step length (with - variable scaling being applied) is less than EpsX. - See minqpsetscale() for more information on variable - scaling. - Rho - penalty coefficient, Rho>0: - * large enough that algorithm converges with desired - precision. - * not TOO large to prevent ill-conditioning - * recommended values are 100, 1000 or 10000 - ItsCnt - number of outer iterations: - * recommended values: 10-15 (although in most cases it - converges within 5 iterations, you may need a few more - to be sure). - * ItsCnt=0 means that small number of outer iterations is - automatically chosen (10 iterations in current version). - * ItsCnt=1 means that AUL algorithm performs just as usual - penalty method. - * ItsCnt>1 means that AUL algorithm performs specified - number of outer iterations - -IT IS VERY IMPORTANT TO CALL minqpsetscale() WHEN YOU USE THIS ALGORITHM -BECAUSE ITS CONVERGENCE PROPERTIES AND STOPPING CRITERIA ARE SCALE-DEPENDENT! - -NOTE: Passing EpsX=0 will lead to automatic step length selection - (specific step length chosen may change in the future versions of - ALGLIB, so it is better to specify step length explicitly). - - -- ALGLIB -- - Copyright 20.08.2016 by Bochkanov Sergey -*************************************************************************/ -void minqpsetalgodenseaul(minqpstate* state, - double epsx, - double rho, - ae_int_t itscnt, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(epsx, _state), "MinQPSetAlgoDenseAUL: EpsX is not finite number", _state); - ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinQPSetAlgoDenseAUL: negative EpsX", _state); - ae_assert(ae_isfinite(rho, _state), "MinQPSetAlgoDenseAUL: Rho is not finite number", _state); - ae_assert(ae_fp_greater(rho,(double)(0)), "MinQPSetAlgoDenseAUL: non-positive Rho", _state); - ae_assert(itscnt>=0, "MinQPSetAlgoDenseAUL: negative ItsCnt!", _state); - state->algokind = 4; - if( ae_fp_eq(epsx,(double)(0)) ) - { - epsx = 1.0E-8; - } - if( itscnt==0 ) - { - itscnt = 10; - } - state->qpdenseaulsettingsuser.epsx = epsx; - state->qpdenseaulsettingsuser.outerits = itscnt; - state->qpdenseaulsettingsuser.rho = rho; -} - - -/************************************************************************* -This function tells QP solver to use DENSE-IPM QP algorithm and sets -stopping criteria for the algorithm. - -This algorithm is intended for convex and semidefinite problems with -moderate (up to several thousands) variable count and arbitrary number of -constraints. - -IMPORTANT: this algorithm won't work for nonconvex problems, use DENSE-AUL - or BLEIC-QP instead. If you try to run DENSE-IPM on problem - with indefinite matrix (matrix having at least one negative - eigenvalue) then depending on circumstances it may either (a) - stall at some arbitrary point, or (b) throw exception on - failure of Cholesky decomposition. - -ALGORITHM FEATURES: - -* supports box and dense/sparse general linear equality/inequality - constraints - -ALGORITHM OUTLINE: - -* this algorithm is our implementation of interior point method as - formulated by R.J.Vanderbei, with minor modifications to the algorithm - (damped Newton directions are extensively used) -* like all interior point methods, this algorithm tends to converge in - roughly same number of iterations (between 15 and 50) independently from - the problem dimensionality - -ALGORITHM LIMITATIONS: - -* because dense Cholesky driver is used, for N-dimensional problem with - M dense constaints this algorithm has O(N^2+N*M) memory requirements and - O(N^3+N*M^2) running time. - Having sparse constraints with Z nonzeros per row relaxes storage and - running time down to O(N^2+M*Z) and O(N^3+N*Z^2) - From the practical point of view, it limits its applicability by - several thousands of variables. - From the other side, variables count is the most limiting factor, - and dependence on constraint count is much more lower. Assuming that - constraint matrix is sparse, it may handle tens of thousands of general - linear constraints. - -INPUT PARAMETERS: - State - structure which stores algorithm state - Eps - >=0, stopping criteria. The algorithm stops when primal - and dual infeasiblities as well as complementarity gap are - less than Eps. - -IT IS VERY IMPORTANT TO CALL minqpsetscale() WHEN YOU USE THIS ALGORITHM -BECAUSE ITS CONVERGENCE PROPERTIES AND STOPPING CRITERIA ARE SCALE-DEPENDENT! - -NOTE: Passing EpsX=0 will lead to automatic selection of small epsilon. - -===== TRACING IPM SOLVER ================================================= - -IPM solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'IPM' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. -* 'IPM.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'IPM'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("IPM,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void minqpsetalgodenseipm(minqpstate* state, double eps, ae_state *_state) -{ - - - ae_assert(ae_isfinite(eps, _state), "MinQPSetAlgoDenseIPM: Eps is not finite number", _state); - ae_assert(ae_fp_greater_eq(eps,(double)(0)), "MinQPSetAlgoDenseIPM: negative Eps", _state); - state->algokind = 5; - state->veps = eps; -} - - -/************************************************************************* -This function tells QP solver to use SPARSE-IPM QP algorithm and sets -stopping criteria for the algorithm. - -This algorithm is intended for convex and semidefinite problems with -large variable and constraint count and sparse quadratic term and -constraints. It is possible to have some limited set of dense linear -constraints - they will be handled separately by dense BLAS - but the more -dense constraints you have, the more time solver needs. - -IMPORTANT: internally this solver performs large and sparse (N+M)x(N+M) - triangular factorization. So it expects both quadratic term and - constraints to be highly sparse. However, its running time is - influenced by BOTH fill factor and sparsity pattern. - - Generally we expect that no more than few nonzero elements per - row are present. However different sparsity patterns may result - in completely different running times even given same fill - factor. - - In many cases this algorithm outperforms DENSE-IPM by order of - magnitude. However, in some cases you may get better results - with DENSE-IPM even when solving sparse task. - -IMPORTANT: this algorithm won't work for nonconvex problems, use DENSE-AUL - or BLEIC-QP instead. If you try to run DENSE-IPM on problem - with indefinite matrix (matrix having at least one negative - eigenvalue) then depending on circumstances it may either (a) - stall at some arbitrary point, or (b) throw exception on - failure of Cholesky decomposition. - -ALGORITHM FEATURES: - -* supports box and dense/sparse general linear equality/inequality - constraints -* specializes on large-scale sparse problems - -ALGORITHM OUTLINE: - -* this algorithm is our implementation of interior point method as - formulated by R.J.Vanderbei, with minor modifications to the algorithm - (damped Newton directions are extensively used) -* like all interior point methods, this algorithm tends to converge in - roughly same number of iterations (between 15 and 50) independently from - the problem dimensionality - -ALGORITHM LIMITATIONS: - -* this algorithm may handle moderate number of dense constraints, usually - no more than a thousand of dense ones without losing its efficiency. - -INPUT PARAMETERS: - State - structure which stores algorithm state - Eps - >=0, stopping criteria. The algorithm stops when primal - and dual infeasiblities as well as complementarity gap are - less than Eps. - -IT IS VERY IMPORTANT TO CALL minqpsetscale() WHEN YOU USE THIS ALGORITHM -BECAUSE ITS CONVERGENCE PROPERTIES AND STOPPING CRITERIA ARE SCALE-DEPENDENT! - -NOTE: Passing EpsX=0 will lead to automatic selection of small epsilon. - -===== TRACING IPM SOLVER ================================================= - -IPM solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'IPM' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. -* 'IPM.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'IPM'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("IPM,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void minqpsetalgosparseipm(minqpstate* state, - double eps, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(eps, _state), "MinQPSetAlgoSparseIPM: Eps is not finite number", _state); - ae_assert(ae_fp_greater_eq(eps,(double)(0)), "MinQPSetAlgoSparseIPM: negative Eps", _state); - state->algokind = 6; - state->veps = eps; -} - - -/************************************************************************* -This function tells solver to use QuickQP algorithm: special extra-fast -algorithm for problems with box-only constrants. It may solve non-convex -problems as long as they are bounded from below under constraints. - -ALGORITHM FEATURES: -* several times faster than DENSE-IPM when running on box-only problem -* utilizes accelerated methods for activation of constraints. -* supports dense and sparse QP problems -* supports ONLY box constraints; general linear constraints are NOT - supported by this solver -* can solve all types of problems (convex, semidefinite, nonconvex) as - long as they are bounded from below under constraints. - Say, it is possible to solve "min{-x^2} subject to -1<=x<=+1". - In convex/semidefinite case global minimum is returned, in nonconvex - case - algorithm returns one of the local minimums. - -ALGORITHM OUTLINE: - -* algorithm performs two kinds of iterations: constrained CG iterations - and constrained Newton iterations -* initially it performs small number of constrained CG iterations, which - can efficiently activate/deactivate multiple constraints -* after CG phase algorithm tries to calculate Cholesky decomposition and - to perform several constrained Newton steps. If Cholesky decomposition - failed (matrix is indefinite even under constraints), we perform more - CG iterations until we converge to such set of constraints that system - matrix becomes positive definite. Constrained Newton steps greatly - increase convergence speed and precision. -* algorithm interleaves CG and Newton iterations which allows to handle - indefinite matrices (CG phase) and quickly converge after final set of - constraints is found (Newton phase). Combination of CG and Newton phases - is called "outer iteration". -* it is possible to turn off Newton phase (beneficial for semidefinite - problems - Cholesky decomposition will fail too often) - -ALGORITHM LIMITATIONS: - -* algorithm does not support general linear constraints; only box ones - are supported -* Cholesky decomposition for sparse problems is performed with Skyline - Cholesky solver, which is intended for low-profile matrices. No profile- - reducing reordering of variables is performed in this version of ALGLIB. -* problems with near-zero negative eigenvalues (or exacty zero ones) may - experience about 2-3x performance penalty. The reason is that Cholesky - decomposition can not be performed until we identify directions of zero - and negative curvature and activate corresponding boundary constraints - - but we need a lot of trial and errors because these directions are hard - to notice in the matrix spectrum. - In this case you may turn off Newton phase of algorithm. - Large negative eigenvalues are not an issue, so highly non-convex - problems can be solved very efficiently. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|=0 - The subroutine finishes its work if exploratory steepest - descent step on k+1-th iteration satisfies following - condition: |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - EpsX - >=0 - The subroutine finishes its work if exploratory steepest - descent step on k+1-th iteration satisfies following - condition: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - step vector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinQPSetScale() - MaxOuterIts-maximum number of OUTER iterations. One outer iteration - includes some amount of CG iterations (from 5 to ~N) and - one or several (usually small amount) Newton steps. Thus, - one outer iteration has high cost, but can greatly reduce - funcation value. - Use 0 if you do not want to limit number of outer iterations. - UseNewton- use Newton phase or not: - * Newton phase improves performance of positive definite - dense problems (about 2 times improvement can be observed) - * can result in some performance penalty on semidefinite - or slightly negative definite problems - each Newton - phase will bring no improvement (Cholesky failure), but - still will require computational time. - * if you doubt, you can turn off this phase - optimizer - will retain its most of its high speed. - -IT IS VERY IMPORTANT TO CALL MinQPSetScale() WHEN YOU USE THIS ALGORITHM -BECAUSE ITS STOPPING CRITERIA ARE SCALE-DEPENDENT! - -Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead -to automatic stopping criterion selection (presently it is small step -length, but it may change in the future versions of ALGLIB). - - -- ALGLIB -- - Copyright 22.05.2014 by Bochkanov Sergey -*************************************************************************/ -void minqpsetalgoquickqp(minqpstate* state, - double epsg, - double epsf, - double epsx, - ae_int_t maxouterits, - ae_bool usenewton, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(epsg, _state), "MinQPSetAlgoQuickQP: EpsG is not finite number", _state); - ae_assert(ae_fp_greater_eq(epsg,(double)(0)), "MinQPSetAlgoQuickQP: negative EpsG", _state); - ae_assert(ae_isfinite(epsf, _state), "MinQPSetAlgoQuickQP: EpsF is not finite number", _state); - ae_assert(ae_fp_greater_eq(epsf,(double)(0)), "MinQPSetAlgoQuickQP: negative EpsF", _state); - ae_assert(ae_isfinite(epsx, _state), "MinQPSetAlgoQuickQP: EpsX is not finite number", _state); - ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinQPSetAlgoQuickQP: negative EpsX", _state); - ae_assert(maxouterits>=0, "MinQPSetAlgoQuickQP: negative MaxOuterIts!", _state); - state->algokind = 3; - if( ((ae_fp_eq(epsg,(double)(0))&&ae_fp_eq(epsf,(double)(0)))&&ae_fp_eq(epsx,(double)(0)))&&maxouterits==0 ) - { - epsx = 1.0E-6; - } - state->qqpsettingsuser.maxouterits = maxouterits; - state->qqpsettingsuser.epsg = epsg; - state->qqpsettingsuser.epsf = epsf; - state->qqpsettingsuser.epsx = epsx; - state->qqpsettingsuser.cnphase = usenewton; -} - - -/************************************************************************* -This function sets box constraints for QP solver - -Box constraints are inactive by default (after initial creation). After -being set, they are preserved until explicitly overwritten with another -minqpsetbc() or minqpsetbcall() call, or partially overwritten with -minqpsetbci() call. - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd[i] BndL[i]=BndU[i] - lower bound BndL[i]<=x[i] BndU[i]=+INF - upper bound x[i]<=BndU[i] BndL[i]=-INF - range BndL[i]<=x[i]<=BndU[i] ... - free variable - BndL[I]=-INF, BndU[I]+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF (latter is recommended because - it will allow solver to use better algorithm). - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF (latter is recommended because - it will allow solver to use better algorithm). - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: if constraints for all variables are same you may use minqpsetbcall() - which allows to specify constraints without using arrays. - -NOTE: BndL>BndU will result in QP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetbc(minqpstate* state, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - - - n = state->n; - ae_assert(bndl->cnt>=n, "MinQPSetBC: Length(BndL)cnt>=n, "MinQPSetBC: Length(BndU)ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "MinQPSetBC: BndL contains NAN or +INF", _state); - ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "MinQPSetBC: BndU contains NAN or -INF", _state); - state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i]; - state->havebndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state); - state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i]; - state->havebndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state); - } -} - - -/************************************************************************* -This function sets box constraints for QP solver (all variables at once, -same constraints for all variables) - -Box constraints are inactive by default (after initial creation). After -being set, they are preserved until explicitly overwritten with another -minqpsetbc() or minqpsetbcall() call, or partially overwritten with -minqpsetbci() call. - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd BndL=BndU - lower bound BndL<=x[i] BndU=+INF - upper bound x[i]<=BndU BndL=-INF - range BndL<=x[i]<=BndU ... - free variable - BndL=-INF, BndU+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bound, same for all variables - BndU - upper bound, same for all variables - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: BndL>BndU will result in QP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetbcall(minqpstate* state, - double bndl, - double bndu, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - - - n = state->n; - ae_assert(ae_isfinite(bndl, _state)||ae_isneginf(bndl, _state), "MinQPSetBCAll: BndL is NAN or +INF", _state); - ae_assert(ae_isfinite(bndu, _state)||ae_isposinf(bndu, _state), "MinQPSetBCAll: BndU is NAN or -INF", _state); - for(i=0; i<=n-1; i++) - { - state->bndl.ptr.p_double[i] = bndl; - state->bndu.ptr.p_double[i] = bndu; - state->havebndl.ptr.p_bool[i] = ae_isfinite(bndl, _state); - state->havebndu.ptr.p_bool[i] = ae_isfinite(bndu, _state); - } -} - - -/************************************************************************* -This function sets box constraints for I-th variable (other variables are -not modified). - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd BndL=BndU - lower bound BndL<=x[i] BndU=+INF - upper bound x[i]<=BndU BndL=-INF - range BndL<=x[i]<=BndU ... - free variable - BndL=-INF, BndU+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bound - BndU - upper bound - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: BndL>BndU will result in QP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetbci(minqpstate* state, - ae_int_t i, - double bndl, - double bndu, - ae_state *_state) -{ - - - ae_assert(i>=0&&in, "MinQPSetBCi: I is outside of [0,N)", _state); - ae_assert(ae_isfinite(bndl, _state)||ae_isneginf(bndl, _state), "MinQPSetBCi: BndL is NAN or +INF", _state); - ae_assert(ae_isfinite(bndu, _state)||ae_isposinf(bndu, _state), "MinQPSetBCi: BndU is NAN or -INF", _state); - state->bndl.ptr.p_double[i] = bndl; - state->bndu.ptr.p_double[i] = bndu; - state->havebndl.ptr.p_bool[i] = ae_isfinite(bndl, _state); - state->havebndu.ptr.p_bool[i] = ae_isfinite(bndu, _state); -} - - -/************************************************************************* -This function sets dense linear constraints for QP optimizer. - -This function overrides results of previous calls to minqpsetlc(), -minqpsetlcsparse() and minqpsetlcmixed(). After call to this function -all non-box constraints are dropped, and you have only those constraints -which were specified in the present call. - -If you want to specify mixed (with dense and sparse terms) linear -constraints, you should call minqpsetlcmixed(). - -INPUT PARAMETERS: - State - structure previously allocated with MinQPCreate call. - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -NOTE 1: linear (non-bound) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations (BLEIC-QP solver is most precise, AUL-QP - solver is less precise). - - -- ALGLIB -- - Copyright 19.06.2012 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlc(minqpstate* state, - /* Real */ ae_matrix* c, - /* Integer */ ae_vector* ct, - ae_int_t k, - ae_state *_state) -{ - ae_frame _frame_block; - sparsematrix dummyc; - ae_vector dummyct; - - ae_frame_make(_state, &_frame_block); - memset(&dummyc, 0, sizeof(dummyc)); - memset(&dummyct, 0, sizeof(dummyct)); - _sparsematrix_init(&dummyc, _state, ae_true); - ae_vector_init(&dummyct, 0, DT_INT, _state, ae_true); - - minqpsetlcmixed(state, &dummyc, &dummyct, 0, c, ct, k, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function sets sparse linear constraints for QP optimizer. - -This function overrides results of previous calls to minqpsetlc(), -minqpsetlcsparse() and minqpsetlcmixed(). After call to this function -all non-box constraints are dropped, and you have only those constraints -which were specified in the present call. - -If you want to specify mixed (with dense and sparse terms) linear -constraints, you should call minqpsetlcmixed(). - -INPUT PARAMETERS: - State - structure previously allocated with MinQPCreate call. - C - linear constraints, sparse matrix with dimensions at - least [K,N+1]. If matrix has larger size, only leading - Kx(N+1) rectangle is used. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0 - -NOTE 1: linear (non-bound) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations (BLEIC-QP solver is most precise, AUL-QP - solver is less precise). - - -- ALGLIB -- - Copyright 22.08.2016 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlcsparse(minqpstate* state, - sparsematrix* c, - /* Integer */ ae_vector* ct, - ae_int_t k, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix dummyc; - ae_vector dummyct; - - ae_frame_make(_state, &_frame_block); - memset(&dummyc, 0, sizeof(dummyc)); - memset(&dummyct, 0, sizeof(dummyct)); - ae_matrix_init(&dummyc, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dummyct, 0, DT_INT, _state, ae_true); - - minqpsetlcmixed(state, c, ct, k, &dummyc, &dummyct, 0, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function sets mixed linear constraints, which include a set of dense -rows, and a set of sparse rows. - -This function overrides results of previous calls to minqpsetlc(), -minqpsetlcsparse() and minqpsetlcmixed(). - -This function may be useful if constraint matrix includes large number of -both types of rows - dense and sparse. If you have just a few sparse rows, -you may represent them in dense format without losing performance. -Similarly, if you have just a few dense rows, you may store them in sparse -format with almost same performance. - -INPUT PARAMETERS: - State - structure previously allocated with MinQPCreate call. - SparseC - linear constraints, sparse matrix with dimensions EXACTLY - EQUAL TO [SparseK,N+1]. Each row of C represents one - constraint, either equality or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - SparseCT- type of sparse constraints, array[K]: - * if SparseCT[i]>0, then I-th constraint is SparseC[i,*]*x >= SparseC[i,n+1] - * if SparseCT[i]=0, then I-th constraint is SparseC[i,*]*x = SparseC[i,n+1] - * if SparseCT[i]<0, then I-th constraint is SparseC[i,*]*x <= SparseC[i,n+1] - SparseK - number of sparse equality/inequality constraints, K>=0 - DenseC - dense linear constraints, array[K,N+1]. - Each row of DenseC represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of DenseC (including right part) must be finite. - DenseCT - type of constraints, array[K]: - * if DenseCT[i]>0, then I-th constraint is DenseC[i,*]*x >= DenseC[i,n+1] - * if DenseCT[i]=0, then I-th constraint is DenseC[i,*]*x = DenseC[i,n+1] - * if DenseCT[i]<0, then I-th constraint is DenseC[i,*]*x <= DenseC[i,n+1] - DenseK - number of equality/inequality constraints, DenseK>=0 - -NOTE 1: linear (non-box) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations (BLEIC-QP solver is most precise, AUL-QP - solver is less precise). - -NOTE 2: due to backward compatibility reasons SparseC can be larger than - [SparseK,N+1]. In this case only leading [SparseK,N+1] submatrix - will be used. However, the rest of ALGLIB has more strict - requirements on the input size, so we recommend you to pass sparse - term whose size exactly matches algorithm expectations. - - -- ALGLIB -- - Copyright 22.08.2016 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlcmixed(minqpstate* state, - sparsematrix* sparsec, - /* Integer */ ae_vector* sparsect, - ae_int_t sparsek, - /* Real */ ae_matrix* densec, - /* Integer */ ae_vector* densect, - ae_int_t densek, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t j0; - double v; - ae_vector srcidx; - ae_vector dstidx; - ae_vector s; - ae_vector rs; - ae_vector eoffs; - ae_vector roffs; - ae_vector v2; - ae_vector eidx; - ae_vector eval; - ae_int_t t0; - ae_int_t t1; - ae_int_t nnz; - - ae_frame_make(_state, &_frame_block); - memset(&srcidx, 0, sizeof(srcidx)); - memset(&dstidx, 0, sizeof(dstidx)); - memset(&s, 0, sizeof(s)); - memset(&rs, 0, sizeof(rs)); - memset(&eoffs, 0, sizeof(eoffs)); - memset(&roffs, 0, sizeof(roffs)); - memset(&v2, 0, sizeof(v2)); - memset(&eidx, 0, sizeof(eidx)); - memset(&eval, 0, sizeof(eval)); - ae_vector_init(&srcidx, 0, DT_INT, _state, ae_true); - ae_vector_init(&dstidx, 0, DT_INT, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rs, 0, DT_INT, _state, ae_true); - ae_vector_init(&eoffs, 0, DT_INT, _state, ae_true); - ae_vector_init(&roffs, 0, DT_INT, _state, ae_true); - ae_vector_init(&v2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&eidx, 0, DT_INT, _state, ae_true); - ae_vector_init(&eval, 0, DT_REAL, _state, ae_true); - - n = state->n; - - /* - * First, check for errors in the inputs - */ - ae_assert(densek>=0, "MinQPSetLCMixed: K<0", _state); - ae_assert(densek==0||densec->cols>=n+1, "MinQPSetLCMixed: Cols(C)rows>=densek, "MinQPSetLCMixed: Rows(DenseC)cnt>=densek, "MinQPSetLCMixed: Length(DenseCT)=0, "MinQPSetLCMixed: SparseK<0", _state); - ae_assert(sparsek==0||sparsegetncols(sparsec, _state)>=n+1, "MinQPSetLCMixed: Cols(SparseC)=sparsek, "MinQPSetLCMixed: Rows(SparseC)cnt>=sparsek, "MinQPSetLCMixed: Length(SparseCT)replaglc, densek+sparsek, _state); - for(i=0; i<=densek+sparsek-1; i++) - { - state->replaglc.ptr.p_double[i] = 0.0; - } - - /* - * Init - */ - ae_vector_set_length(&state->cl, densek+sparsek, _state); - ae_vector_set_length(&state->cu, densek+sparsek, _state); - state->mdense = densek; - state->msparse = sparsek; - if( sparsek>0 ) - { - - /* - * Evaluate row sizes for new storage - */ - ae_vector_set_length(&rs, sparsek, _state); - for(i=0; i<=sparsek-1; i++) - { - rs.ptr.p_int[i] = 0; - } - t0 = 0; - t1 = 0; - nnz = 0; - while(sparseenumerate(sparsec, &t0, &t1, &i, &j, &v, _state)) - { - if( i>sparsek-1||j>n-1 ) - { - continue; - } - ae_assert(ae_isfinite(v, _state), "MinQPSetLCSparse: C contains infinite or NAN values", _state); - nnz = nnz+1; - rs.ptr.p_int[i] = rs.ptr.p_int[i]+1; - } - - /* - * Prepare new sparse CRS storage, copy leading SparseK*N submatrix into the storage - */ - for(i=0; i<=sparsek-1; i++) - { - state->cl.ptr.p_double[i] = (double)(0); - state->cu.ptr.p_double[i] = (double)(0); - } - state->sparsec.m = sparsek; - state->sparsec.n = n; - ivectorsetlengthatleast(&state->sparsec.ridx, sparsek+1, _state); - ivectorsetlengthatleast(&state->sparsec.idx, nnz, _state); - rvectorsetlengthatleast(&state->sparsec.vals, nnz, _state); - ae_vector_set_length(&eoffs, sparsek+1, _state); - state->sparsec.ridx.ptr.p_int[0] = 0; - eoffs.ptr.p_int[0] = 0; - for(i=1; i<=sparsek; i++) - { - state->sparsec.ridx.ptr.p_int[i] = state->sparsec.ridx.ptr.p_int[i-1]+rs.ptr.p_int[i-1]; - eoffs.ptr.p_int[i] = state->sparsec.ridx.ptr.p_int[i]; - } - t0 = 0; - t1 = 0; - while(sparseenumerate(sparsec, &t0, &t1, &i, &j, &v, _state)) - { - if( i>sparsek-1||j>n ) - { - continue; - } - if( jsparsec.idx.ptr.p_int[j0] = j; - state->sparsec.vals.ptr.p_double[j0] = v; - eoffs.ptr.p_int[i] = j0+1; - } - else - { - - /* - * Handle right part of the constraint - */ - state->cl.ptr.p_double[i] = v; - state->cu.ptr.p_double[i] = v; - } - } - for(i=0; i<=sparsek-1; i++) - { - ae_assert(eoffs.ptr.p_int[i]==state->sparsec.ridx.ptr.p_int[i+1], "MinQP: critical integrity check failed (sparse copying)", _state); - } - sparsecreatecrsinplace(&state->sparsec, _state); - for(i=0; i<=sparsek-1; i++) - { - if( sparsect->ptr.p_int[i]>0 ) - { - state->cu.ptr.p_double[i] = _state->v_posinf; - } - if( sparsect->ptr.p_int[i]<0 ) - { - state->cl.ptr.p_double[i] = _state->v_neginf; - } - } - } - if( densek>0 ) - { - - /* - * Copy dense constraints - */ - rmatrixsetlengthatleast(&state->densec, densek, n, _state); - for(i=0; i<=densek-1; i++) - { - for(j=0; j<=n-1; j++) - { - state->densec.ptr.pp_double[i][j] = densec->ptr.pp_double[i][j]; - } - if( densect->ptr.p_int[i]>0 ) - { - state->cl.ptr.p_double[sparsek+i] = densec->ptr.pp_double[i][n]; - state->cu.ptr.p_double[sparsek+i] = _state->v_posinf; - continue; - } - if( densect->ptr.p_int[i]<0 ) - { - state->cl.ptr.p_double[sparsek+i] = _state->v_neginf; - state->cu.ptr.p_double[sparsek+i] = densec->ptr.pp_double[i][n]; - continue; - } - state->cl.ptr.p_double[sparsek+i] = densec->ptr.pp_double[i][n]; - state->cu.ptr.p_double[sparsek+i] = densec->ptr.pp_double[i][n]; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function provides legacy API for specification of mixed dense/sparse -linear constraints. - -New conventions used by ALGLIB since release 3.16.0 state that set of -sparse constraints comes first, followed by set of dense ones. This -convention is essential when you talk about things like order of Lagrange -multipliers. - -However, legacy API accepted mixed constraints in reverse order. This -function is here to simplify situation with code relying on legacy API. It -simply accepts constraints in one order (old) and passes them to new API, -now in correct order. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlcmixedlegacy(minqpstate* state, - /* Real */ ae_matrix* densec, - /* Integer */ ae_vector* densect, - ae_int_t densek, - sparsematrix* sparsec, - /* Integer */ ae_vector* sparsect, - ae_int_t sparsek, - ae_state *_state) -{ - - - minqpsetlcmixed(state, sparsec, sparsect, sparsek, densec, densect, densek, _state); -} - - -/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU with dense -constraint matrix A. - -NOTE: knowing that constraint matrix is dense helps some QP solvers - (especially modern IPM method) to utilize efficient dense Level 3 - BLAS for dense parts of the problem. If your problem has both dense - and sparse constraints, you can use minqpsetlc2mixed() function, - which will result in dense algebra being applied to dense terms, and - sparse sparse linear algebra applied to sparse terms. - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - A - linear constraints, array[K,N]. Each row of A represents - one constraint. One-sided inequality constraints, two- - sided inequality constraints, equality constraints are - supported (see below) - AL, AU - lower and upper bounds, array[K]; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i] two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0; if not - given, inferred from sizes of A, AL, AU. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlc2dense(minqpstate* state, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t k, - ae_state *_state) -{ - - - minqpsetlc2mixed(state, &state->dummysparse, 0, a, k, al, au, _state); -} - - -/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU with -sparse constraining matrix A. Recommended for large-scale problems. - -This function overwrites linear (non-box) constraints set by previous -calls (if such calls were made). - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - A - sparse matrix with size [K,N] (exactly!). - Each row of A represents one general linear constraint. - A can be stored in any sparse storage format. - AL, AU - lower and upper bounds, array[K]; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i] two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0. If K=0 - is specified, A, AL, AU are ignored. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlc2(minqpstate* state, - sparsematrix* a, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t k, - ae_state *_state) -{ - - - minqpsetlc2mixed(state, a, k, &state->dummyr2, 0, al, au, _state); -} - - -/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU with -mixed constraining matrix A including sparse part (first SparseK rows) and -dense part (last DenseK rows). Recommended for large-scale problems. - -This function overwrites linear (non-box) constraints set by previous -calls (if such calls were made). - -This function may be useful if constraint matrix includes large number of -both types of rows - dense and sparse. If you have just a few sparse rows, -you may represent them in dense format without losing performance. -Similarly, if you have just a few dense rows, you may store them in sparse -format with almost same performance. - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - SparseA - sparse matrix with size [K,N] (exactly!). - Each row of A represents one general linear constraint. - A can be stored in any sparse storage format. - SparseK - number of sparse constraints, SparseK>=0 - DenseA - linear constraints, array[K,N], set of dense constraints. - Each row of A represents one general linear constraint. - DenseK - number of dense constraints, DenseK>=0 - AL, AU - lower and upper bounds, array[SparseK+DenseK], with former - SparseK elements corresponding to sparse constraints, and - latter DenseK elements corresponding to dense constraints; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i] two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0. If K=0 - is specified, A, AL, AU are ignored. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlc2mixed(minqpstate* state, - sparsematrix* sparsea, - ae_int_t ksparse, - /* Real */ ae_matrix* densea, - ae_int_t kdense, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - ae_int_t i; - - - n = state->n; - m = kdense+ksparse; - - /* - * Check input arguments - */ - ae_assert(ksparse>=0, "MinQPSetLC2Mixed: KSparse<0", _state); - ae_assert(ksparse==0||sparsegetncols(sparsea, _state)==n, "MinQPSetLC2: Cols(SparseA)<>N", _state); - ae_assert(ksparse==0||sparsegetnrows(sparsea, _state)==ksparse, "MinQPSetLC2: Rows(SparseA)<>K", _state); - ae_assert(kdense>=0, "MinQPSetLC2Mixed: KDense<0", _state); - ae_assert(kdense==0||densea->cols>=n, "MinQPSetLC2Mixed: Cols(DenseA)rows>=kdense, "MinQPSetLC2Mixed: Rows(DenseA)cnt>=kdense+ksparse, "MinQPSetLC2Mixed: Length(AL)cnt>=kdense+ksparse, "MinQPSetLC2Mixed: Length(AU)ptr.p_double[i], _state)||ae_isneginf(al->ptr.p_double[i], _state), "MinQPSetLC2Mixed: AL contains NAN or +INF", _state); - ae_assert(ae_isfinite(au->ptr.p_double[i], _state)||ae_isposinf(au->ptr.p_double[i], _state), "MinQPSetLC2Mixed: AU contains NAN or -INF", _state); - } - - /* - * Allocate place for Lagrange multipliers, fill by zero - */ - rvectorsetlengthatleast(&state->replaglc, kdense+ksparse, _state); - for(i=0; i<=kdense+ksparse-1; i++) - { - state->replaglc.ptr.p_double[i] = 0.0; - } - - /* - * Quick exit if needed - */ - if( m==0 ) - { - state->mdense = 0; - state->msparse = 0; - return; - } - - /* - * Prepare - */ - rvectorsetlengthatleast(&state->cl, m, _state); - rvectorsetlengthatleast(&state->cu, m, _state); - for(i=0; i<=m-1; i++) - { - state->cl.ptr.p_double[i] = al->ptr.p_double[i]; - state->cu.ptr.p_double[i] = au->ptr.p_double[i]; - } - state->mdense = kdense; - state->msparse = ksparse; - - /* - * Copy dense and sparse terms - */ - if( ksparse>0 ) - { - sparsecopytocrsbuf(sparsea, &state->sparsec, _state); - } - if( kdense>0 ) - { - rmatrixsetlengthatleast(&state->densec, kdense, n, _state); - rmatrixcopy(kdense, n, densea, 0, 0, &state->densec, 0, 0, _state); - } -} - - -/************************************************************************* -This function appends two-sided linear constraint AL <= A*x <= AU to the -list of currently present dense constraints. - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - A - linear constraint coefficient, array[N], right side is NOT - included. - AL, AU - lower and upper bounds; - * AL=AU => equality constraint Ai*x - * AL two-sided constraint AL<=A*x<=AU - * AL=-INF => one-sided constraint Ai*x<=AU - * AU=+INF => one-sided constraint AL<=Ai*x - * AL=-INF, AU=+INF => constraint is ignored - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minqpaddlc2dense(minqpstate* state, - /* Real */ ae_vector* a, - double al, - double au, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - - - n = state->n; - ae_assert(a->cnt>=n, "MinQPAddLC2Dense: Length(A)cl, state->msparse+state->mdense+1, _state); - rvectorgrowto(&state->cu, state->msparse+state->mdense+1, _state); - rvectorgrowto(&state->replaglc, state->msparse+state->mdense+1, _state); - rmatrixgrowrowsto(&state->densec, state->mdense+1, n, _state); - for(i=0; i<=n-1; i++) - { - state->densec.ptr.pp_double[state->mdense][i] = a->ptr.p_double[i]; - } - state->cl.ptr.p_double[state->msparse+state->mdense] = al; - state->cu.ptr.p_double[state->msparse+state->mdense] = au; - state->replaglc.ptr.p_double[state->msparse+state->mdense] = 0.0; - inc(&state->mdense, _state); -} - - -/************************************************************************* -This function appends two-sided linear constraint AL <= A*x <= AU to the -list of currently present sparse constraints. - -Constraint is passed in compressed format: as list of non-zero entries of -coefficient vector A. Such approach is more efficient than dense storage -for highly sparse constraint vectors. - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - IdxA - array[NNZ], indexes of non-zero elements of A: - * can be unsorted - * can include duplicate indexes (corresponding entries of - ValA[] will be summed) - ValA - array[NNZ], values of non-zero elements of A - NNZ - number of non-zero coefficients in A - AL, AU - lower and upper bounds; - * AL=AU => equality constraint A*x - * AL two-sided constraint AL<=A*x<=AU - * AL=-INF => one-sided constraint A*x<=AU - * AU=+INF => one-sided constraint AL<=A*x - * AL=-INF, AU=+INF => constraint is ignored - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minqpaddlc2(minqpstate* state, - /* Integer */ ae_vector* idxa, - /* Real */ ae_vector* vala, - ae_int_t nnz, - double al, - double au, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t offs; - ae_int_t offsdst; - ae_int_t n; - ae_int_t didx; - ae_int_t uidx; - - - n = state->n; - - /* - * Check inputs - */ - ae_assert(nnz>=0, "MinQPAddLC2: NNZ<0", _state); - ae_assert(idxa->cnt>=nnz, "MinQPAddLC2: Length(IdxA)cnt>=nnz, "MinQPAddLC2: Length(ValA)ptr.p_int[i]>=0&&idxa->ptr.p_int[i]msparse==0 ) - { - state->sparsec.matrixtype = 1; - state->sparsec.m = 0; - state->sparsec.n = n; - state->sparsec.ninitialized = 0; - ivectorsetlengthatleast(&state->sparsec.ridx, 1, _state); - state->sparsec.ridx.ptr.p_int[0] = 0; - } - ae_assert(state->sparsec.matrixtype==1&&state->sparsec.m==state->msparse, "MinQPAddLC2Dense: integrity check failed!", _state); - - /* - * Reallocate inequality bounds - */ - rvectorgrowto(&state->cl, state->msparse+state->mdense+1, _state); - rvectorgrowto(&state->cu, state->msparse+state->mdense+1, _state); - rvectorgrowto(&state->replaglc, state->msparse+state->mdense+1, _state); - for(i=state->msparse+state->mdense; i>=state->msparse+1; i--) - { - state->cl.ptr.p_double[i] = state->cl.ptr.p_double[i-1]; - state->cu.ptr.p_double[i] = state->cu.ptr.p_double[i-1]; - state->replaglc.ptr.p_double[i] = state->replaglc.ptr.p_double[i-1]; - } - state->cl.ptr.p_double[state->msparse] = al; - state->cu.ptr.p_double[state->msparse] = au; - state->replaglc.ptr.p_double[state->msparse] = 0.0; - - /* - * Reallocate sparse storage - */ - offs = state->sparsec.ridx.ptr.p_int[state->msparse]; - ivectorgrowto(&state->sparsec.idx, offs+nnz, _state); - rvectorgrowto(&state->sparsec.vals, offs+nnz, _state); - ivectorgrowto(&state->sparsec.didx, state->msparse+1, _state); - ivectorgrowto(&state->sparsec.uidx, state->msparse+1, _state); - ivectorgrowto(&state->sparsec.ridx, state->msparse+2, _state); - - /* - * If NNZ=0, perform quick and simple row append. - */ - if( nnz==0 ) - { - state->sparsec.didx.ptr.p_int[state->msparse] = state->sparsec.ridx.ptr.p_int[state->msparse]; - state->sparsec.uidx.ptr.p_int[state->msparse] = state->sparsec.ridx.ptr.p_int[state->msparse]; - state->sparsec.ridx.ptr.p_int[state->msparse+1] = state->sparsec.ridx.ptr.p_int[state->msparse]; - inc(&state->sparsec.m, _state); - inc(&state->msparse, _state); - return; - } - - /* - * Now we are sure that SparseC contains properly initialized sparse - * matrix (or some appropriate dummy for M=0) and we have NNZ>0 - * (no need to care about degenerate cases). - * - * Append rows to SparseC: - * * append data - * * sort in place - * * merge duplicate indexes - * * compute DIdx and UIdx - * - */ - for(i=0; i<=nnz-1; i++) - { - state->sparsec.idx.ptr.p_int[offs+i] = idxa->ptr.p_int[i]; - state->sparsec.vals.ptr.p_double[offs+i] = vala->ptr.p_double[i]; - } - tagsortmiddleir(&state->sparsec.idx, &state->sparsec.vals, offs, nnz, _state); - offsdst = offs; - for(i=1; i<=nnz-1; i++) - { - if( state->sparsec.idx.ptr.p_int[offsdst]!=state->sparsec.idx.ptr.p_int[offs+i] ) - { - offsdst = offsdst+1; - state->sparsec.idx.ptr.p_int[offsdst] = state->sparsec.idx.ptr.p_int[offs+i]; - state->sparsec.vals.ptr.p_double[offsdst] = state->sparsec.vals.ptr.p_double[offs+i]; - } - else - { - state->sparsec.vals.ptr.p_double[offsdst] = state->sparsec.vals.ptr.p_double[offsdst]+state->sparsec.vals.ptr.p_double[offs+i]; - } - } - nnz = offsdst-offs+1; - uidx = -1; - didx = -1; - for(j=offs; j<=offsdst; j++) - { - k = state->sparsec.idx.ptr.p_int[j]; - if( k==state->msparse ) - { - didx = j; - } - else - { - if( k>state->msparse&&uidx==-1 ) - { - uidx = j; - break; - } - } - } - if( uidx==-1 ) - { - uidx = offsdst+1; - } - if( didx==-1 ) - { - didx = uidx; - } - state->sparsec.didx.ptr.p_int[state->msparse] = didx; - state->sparsec.uidx.ptr.p_int[state->msparse] = uidx; - state->sparsec.ridx.ptr.p_int[state->msparse+1] = offsdst+1; - state->sparsec.ninitialized = state->sparsec.ridx.ptr.p_int[state->msparse+1]; - inc(&state->sparsec.m, _state); - inc(&state->msparse, _state); -} - - -/************************************************************************* -This function solves quadratic programming problem. - -Prior to calling this function you should choose solver by means of one of -the following functions: - -* minqpsetalgoquickqp() - for QuickQP solver -* minqpsetalgobleic() - for BLEIC-QP solver -* minqpsetalgodenseaul() - for Dense-AUL-QP solver -* minqpsetalgodenseipm() - for Dense-IPM-QP solver - -These functions also allow you to control stopping criteria of the solver. -If you did not set solver, MinQP subpackage will automatically select -solver for your problem and will run it with default stopping criteria. - -However, it is better to set explicitly solver and its stopping criteria. - -INPUT PARAMETERS: - State - algorithm state - -You should use MinQPResults() function to access results after calls -to this function. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey. - Special thanks to Elvira Illarionova for important suggestions on - the linearly constrained QP algorithm. -*************************************************************************/ -void minqpoptimize(minqpstate* state, ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - ae_int_t i; - ae_int_t j; - ae_int_t j0; - ae_int_t j1; - ae_int_t nbc; - ae_int_t neq; - ae_int_t nineq; - ae_int_t curecpos; - ae_int_t curicpos; - - - n = state->n; - m = state->mdense+state->msparse; - state->repterminationtype = -5; - state->repinneriterationscount = 0; - state->repouteriterationscount = 0; - state->repncholesky = 0; - state->repnmv = 0; - - /* - * Zero-fill Lagrange multipliers (their initial value) - */ - for(i=0; i<=n-1; i++) - { - state->replagbc.ptr.p_double[i] = 0.0; - } - for(i=0; i<=m-1; i++) - { - state->replaglc.ptr.p_double[i] = 0.0; - } - - /* - * Initial point: - * * if we have starting point in StartX, we just have to bound it - * * if we do not have StartX, deduce initial point from boundary constraints - */ - if( state->havex ) - { - for(i=0; i<=n-1; i++) - { - state->xs.ptr.p_double[i] = state->startx.ptr.p_double[i]; - if( state->havebndl.ptr.p_bool[i]&&ae_fp_less(state->xs.ptr.p_double[i],state->bndl.ptr.p_double[i]) ) - { - state->xs.ptr.p_double[i] = state->bndl.ptr.p_double[i]; - } - if( state->havebndu.ptr.p_bool[i]&&ae_fp_greater(state->xs.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->xs.ptr.p_double[i] = state->bndu.ptr.p_double[i]; - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - if( state->havebndl.ptr.p_bool[i]&&state->havebndu.ptr.p_bool[i] ) - { - state->xs.ptr.p_double[i] = 0.5*(state->bndl.ptr.p_double[i]+state->bndu.ptr.p_double[i]); - continue; - } - if( state->havebndl.ptr.p_bool[i] ) - { - state->xs.ptr.p_double[i] = state->bndl.ptr.p_double[i]; - continue; - } - if( state->havebndu.ptr.p_bool[i] ) - { - state->xs.ptr.p_double[i] = state->bndu.ptr.p_double[i]; - continue; - } - state->xs.ptr.p_double[i] = (double)(0); - } - } - - /* - * check correctness of constraints - */ - for(i=0; i<=n-1; i++) - { - if( state->havebndl.ptr.p_bool[i]&&state->havebndu.ptr.p_bool[i] ) - { - if( ae_fp_greater(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->repterminationtype = -3; - return; - } - } - } - - /* - * count number of bound and linear constraints - */ - nbc = 0; - for(i=0; i<=n-1; i++) - { - if( state->havebndl.ptr.p_bool[i] ) - { - nbc = nbc+1; - } - if( state->havebndu.ptr.p_bool[i] ) - { - nbc = nbc+1; - } - } - - /* - * Effective scale - */ - rvectorsetlengthatleast(&state->effectives, n, _state); - if( state->stype==0 ) - { - - /* - * User scale (or default one) - */ - for(i=0; i<=n-1; i++) - { - state->effectives.ptr.p_double[i] = state->s.ptr.p_double[i]; - } - } - else - { - if( state->stype==1 ) - { - - /* - * Diagonal is used for scaling: - * * unpack - * * convert to scale, return error on failure - */ - if( state->akind==0 ) - { - - /* - * Unpack CQM structure - */ - cqmgetdiaga(&state->a, &state->effectives, _state); - } - else - { - if( state->akind==1 ) - { - for(i=0; i<=n-1; i++) - { - state->effectives.ptr.p_double[i] = sparseget(&state->sparsea, i, i, _state); - } - } - else - { - ae_assert(ae_false, "MinQPOptimize: integrity check failed", _state); - } - } - for(i=0; i<=n-1; i++) - { - if( ae_fp_less_eq(state->effectives.ptr.p_double[i],(double)(0)) ) - { - state->repterminationtype = -9; - return; - } - state->effectives.ptr.p_double[i] = 1/ae_sqrt(state->effectives.ptr.p_double[i], _state); - } - } - else - { - ae_assert(ae_false, "MinQPOptimize: integrity check failed", _state); - } - } - - /* - * Solvers which can not handle new two-sided constraints need them to be - * converted into legacy equality/inequality one-sided format - */ - if( state->algokind==2||state->algokind==4 ) - { - - /* - * Scan constraint left/right sides, count equality ones and one/two-sided inequality ones - */ - neq = 0; - nineq = 0; - for(i=0; i<=m-1; i++) - { - if( (ae_isfinite(state->cl.ptr.p_double[i], _state)&&ae_isfinite(state->cu.ptr.p_double[i], _state))&&ae_fp_eq(state->cl.ptr.p_double[i],state->cu.ptr.p_double[i]) ) - { - inc(&neq, _state); - continue; - } - if( ae_isfinite(state->cl.ptr.p_double[i], _state) ) - { - inc(&nineq, _state); - } - if( ae_isfinite(state->cu.ptr.p_double[i], _state) ) - { - inc(&nineq, _state); - } - } - - /* - * Perform conversion - */ - rmatrixsetlengthatleast(&state->ecleic, neq+nineq, n+1, _state); - rvectorsetlengthatleast(&state->elagmlt, neq+nineq, _state); - ivectorsetlengthatleast(&state->elagidx, neq+nineq, _state); - curecpos = 0; - curicpos = neq; - for(i=0; i<=m-1; i++) - { - if( (ae_isfinite(state->cl.ptr.p_double[i], _state)&&ae_isfinite(state->cu.ptr.p_double[i], _state))&&ae_fp_eq(state->cl.ptr.p_double[i],state->cu.ptr.p_double[i]) ) - { - - /* - * Offload equality constraint - */ - if( imsparse ) - { - for(j=0; j<=n-1; j++) - { - state->ecleic.ptr.pp_double[curecpos][j] = (double)(0); - } - j0 = state->sparsec.ridx.ptr.p_int[i]; - j1 = state->sparsec.ridx.ptr.p_int[i+1]-1; - for(j=j0; j<=j1; j++) - { - state->ecleic.ptr.pp_double[curecpos][state->sparsec.idx.ptr.p_int[j]] = state->sparsec.vals.ptr.p_double[j]; - } - } - else - { - for(j=0; j<=n-1; j++) - { - state->ecleic.ptr.pp_double[curecpos][j] = state->densec.ptr.pp_double[i-state->msparse][j]; - } - } - state->ecleic.ptr.pp_double[curecpos][n] = state->cu.ptr.p_double[i]; - state->elagidx.ptr.p_int[curecpos] = i; - state->elagmlt.ptr.p_double[curecpos] = 1.0; - inc(&curecpos, _state); - continue; - } - if( ae_isfinite(state->cl.ptr.p_double[i], _state) ) - { - - /* - * Offload inequality constraint of the form CL<=C*x, convert it to -C*x<=-CL - */ - if( imsparse ) - { - for(j=0; j<=n-1; j++) - { - state->ecleic.ptr.pp_double[curicpos][j] = (double)(0); - } - j0 = state->sparsec.ridx.ptr.p_int[i]; - j1 = state->sparsec.ridx.ptr.p_int[i+1]-1; - for(j=j0; j<=j1; j++) - { - state->ecleic.ptr.pp_double[curicpos][state->sparsec.idx.ptr.p_int[j]] = -state->sparsec.vals.ptr.p_double[j]; - } - } - else - { - for(j=0; j<=n-1; j++) - { - state->ecleic.ptr.pp_double[curicpos][j] = -state->densec.ptr.pp_double[i-state->msparse][j]; - } - } - state->ecleic.ptr.pp_double[curicpos][n] = -state->cl.ptr.p_double[i]; - state->elagidx.ptr.p_int[curicpos] = i; - state->elagmlt.ptr.p_double[curicpos] = -1.0; - inc(&curicpos, _state); - } - if( ae_isfinite(state->cu.ptr.p_double[i], _state) ) - { - - /* - * Offload inequality constraint of the form C*x<=CU - */ - if( imsparse ) - { - for(j=0; j<=n-1; j++) - { - state->ecleic.ptr.pp_double[curicpos][j] = (double)(0); - } - j0 = state->sparsec.ridx.ptr.p_int[i]; - j1 = state->sparsec.ridx.ptr.p_int[i+1]-1; - for(j=j0; j<=j1; j++) - { - state->ecleic.ptr.pp_double[curicpos][state->sparsec.idx.ptr.p_int[j]] = state->sparsec.vals.ptr.p_double[j]; - } - } - else - { - for(j=0; j<=n-1; j++) - { - state->ecleic.ptr.pp_double[curicpos][j] = state->densec.ptr.pp_double[i-state->msparse][j]; - } - } - state->ecleic.ptr.pp_double[curicpos][n] = state->cu.ptr.p_double[i]; - state->elagidx.ptr.p_int[curicpos] = i; - state->elagmlt.ptr.p_double[curicpos] = 1.0; - inc(&curicpos, _state); - } - } - ae_assert(curecpos==neq&&curicpos==neq+nineq, "MinQPOptimize: critical integrity check failed (ECLEIC conversion)", _state); - - /* - * Run solvers - */ - if( state->algokind==2 ) - { - qpbleicoptimize(&state->a, &state->sparsea, state->akind, state->sparseaupper, state->absasum, state->absasum2, &state->b, &state->bndl, &state->bndu, &state->effectives, &state->xorigin, n, &state->ecleic, neq, nineq, &state->qpbleicsettingsuser, &state->qpbleicbuf, &state->qpbleicfirstcall, &state->xs, &state->repterminationtype, _state); - state->repinneriterationscount = state->qpbleicbuf.repinneriterationscount; - state->repouteriterationscount = state->qpbleicbuf.repouteriterationscount; - return; - } - if( state->algokind==4 ) - { - qpdenseauloptimize(&state->a, &state->sparsea, state->akind, state->sparseaupper, &state->b, &state->bndl, &state->bndu, &state->effectives, &state->xorigin, n, &state->ecleic, neq, nineq, &state->dummysparse, 0, 0, !state->dbgskipconstraintnormalization, &state->qpdenseaulsettingsuser, &state->qpdenseaulbuf, &state->xs, &state->replagbc, &state->elaglc, &state->repterminationtype, _state); - for(i=0; i<=neq+nineq-1; i++) - { - state->replaglc.ptr.p_double[state->elagidx.ptr.p_int[i]] = state->replaglc.ptr.p_double[state->elagidx.ptr.p_int[i]]+state->elaglc.ptr.p_double[i]*state->elagmlt.ptr.p_double[i]; - } - state->repinneriterationscount = state->qpdenseaulbuf.repinneriterationscount; - state->repouteriterationscount = state->qpdenseaulbuf.repouteriterationscount; - state->repncholesky = state->qpdenseaulbuf.repncholesky; - return; - } - ae_assert(ae_false, "MinQPOptimize: integrity check failed - unknown solver", _state); - } - - /* - * QuickQP solver - */ - if( state->algokind==3 ) - { - if( state->mdense+state->msparse>0 ) - { - state->repterminationtype = -5; - return; - } - qqpoptimize(&state->a, &state->sparsea, &state->dummyr2, state->akind, state->sparseaupper, &state->b, &state->bndl, &state->bndu, &state->effectives, &state->xorigin, n, &state->qqpsettingsuser, &state->qqpbuf, &state->xs, &state->repterminationtype, _state); - state->repinneriterationscount = state->qqpbuf.repinneriterationscount; - state->repouteriterationscount = state->qqpbuf.repouteriterationscount; - state->repncholesky = state->qqpbuf.repncholesky; - return; - } - - /* - * QP-DENSE-IPM and QP-SPARSE-IPM solvers - */ - if( state->algokind==5||state->algokind==6 ) - { - - /* - * Prepare working versions of constraints; these versions may be modified - * when we detect that some bounds are irrelevant. - */ - rcopyallocv(n, &state->bndl, &state->wrkbndl, _state); - rcopyallocv(n, &state->bndu, &state->wrkbndu, _state); - if( state->msparse>0 ) - { - sparsecopybuf(&state->sparsec, &state->wrksparsec, _state); - } - if( state->mdense>0 ) - { - rcopyallocm(state->mdense, n, &state->densec, &state->wrkdensec, _state); - } - rcopyallocv(m, &state->cl, &state->wrkcl, _state); - rcopyallocv(m, &state->cu, &state->wrkcu, _state); - - /* - * Solve - */ - ae_assert(state->akind==0||state->akind==1, "MinQPOptimize: unexpected AKind", _state); - if( state->akind==0 ) - { - cqmgeta(&state->a, &state->tmpr2, _state); - } - if( state->algokind==5 ) - { - vipminitdense(&state->vsolver, &state->effectives, &state->xorigin, n, _state); - } - if( state->algokind==6 ) - { - vipminitsparse(&state->vsolver, &state->effectives, &state->xorigin, n, _state); - } - vipmsetquadraticlinear(&state->vsolver, &state->tmpr2, &state->sparsea, state->akind, state->sparseaupper, &state->b, _state); - vipmsetconstraints(&state->vsolver, &state->wrkbndl, &state->wrkbndu, &state->wrksparsec, state->msparse, &state->wrkdensec, state->mdense, &state->wrkcl, &state->wrkcu, _state); - vipmsetcond(&state->vsolver, state->veps, state->veps, state->veps, _state); - vipmoptimize(&state->vsolver, ae_true, &state->xs, &state->replagbc, &state->replaglc, &state->repterminationtype, _state); - state->repinneriterationscount = state->vsolver.repiterationscount; - state->repouteriterationscount = state->repinneriterationscount; - state->repncholesky = state->vsolver.repncholesky; - return; - } - - /* - * Integrity check failed - unknown solver - */ - ae_assert(ae_false, "MinQPOptimize: integrity check failed - unknown solver", _state); -} - - -/************************************************************************* -QP solver results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution (on failure - the best point found - so far). - Rep - optimization report, contains: - * completion code in Rep.TerminationType (positive values - denote some kind of success, negative - failures) - * Lagrange multipliers - for QP solvers which support them - * other statistics - See comments on minqpreport structure for more information - -Following completion codes are returned in Rep.TerminationType: -* -9 failure of the automatic scale evaluation: one of the diagonal - elements of the quadratic term is non-positive. Specify variable - scales manually! -* -5 inappropriate solver was used: - * QuickQP solver for problem with general linear constraints -* -4 the function is unbounded from below even under constraints, - no meaningful minimum can be found. -* -3 inconsistent constraints (or, maybe, feasible point is too hard to - find). -* -2 IPM solver has difficulty finding primal/dual feasible point. - It is likely that the problem is either infeasible or unbounded, - but it is difficult to determine exact reason for termination. - X contains best point found so far. -* >0 success -* 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpresults(minqpstate* state, - /* Real */ ae_vector* x, - minqpreport* rep, - ae_state *_state) -{ - - ae_vector_clear(x); - _minqpreport_clear(rep); - - minqpresultsbuf(state, x, rep, _state); -} - - -/************************************************************************* -QP results - -Buffered implementation of MinQPResults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpresultsbuf(minqpstate* state, - /* Real */ ae_vector* x, - minqpreport* rep, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(state->xs.cnt>=state->n, "MinQPResultsBuf: integrity check failed", _state); - ae_assert(state->replagbc.cnt>=state->n, "MinQPResultsBuf: integrity check failed", _state); - ae_assert(state->replaglc.cnt>=state->mdense+state->msparse, "MinQPResultsBuf: integrity check failed", _state); - rvectorsetlengthatleast(x, state->n, _state); - rvectorsetlengthatleast(&rep->lagbc, state->n, _state); - rvectorsetlengthatleast(&rep->laglc, state->mdense+state->msparse, _state); - for(i=0; i<=state->n-1; i++) - { - x->ptr.p_double[i] = state->xs.ptr.p_double[i]; - rep->lagbc.ptr.p_double[i] = state->replagbc.ptr.p_double[i]; - } - for(i=0; i<=state->mdense+state->msparse-1; i++) - { - rep->laglc.ptr.p_double[i] = state->replaglc.ptr.p_double[i]; - } - rep->inneriterationscount = state->repinneriterationscount; - rep->outeriterationscount = state->repouteriterationscount; - rep->nmv = state->repnmv; - rep->ncholesky = state->repncholesky; - rep->terminationtype = state->repterminationtype; -} - - -/************************************************************************* -Fast version of MinQPSetLinearTerm(), which doesn't check its arguments. -For internal use only. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlineartermfast(minqpstate* state, - /* Real */ ae_vector* b, - ae_state *_state) -{ - - - ae_v_move(&state->b.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,state->n-1)); -} - - -/************************************************************************* -Fast version of MinQPSetQuadraticTerm(), which doesn't check its arguments. - -It accepts additional parameter - shift S, which allows to "shift" matrix -A by adding s*I to A. S must be positive (although it is not checked). - -For internal use only. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetquadratictermfast(minqpstate* state, - /* Real */ ae_matrix* a, - ae_bool isupper, - double s, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t n; - double v; - ae_int_t j0; - ae_int_t j1; - - - n = state->n; - state->akind = 0; - cqmseta(&state->a, a, isupper, 1.0, _state); - if( ae_fp_greater(s,(double)(0)) ) - { - rvectorsetlengthatleast(&state->tmp0, n, _state); - for(i=0; i<=n-1; i++) - { - state->tmp0.ptr.p_double[i] = a->ptr.pp_double[i][i]+s; - } - cqmrewritedensediagonal(&state->a, &state->tmp0, _state); - } - - /* - * Estimate norm of A - * (it will be used later in the quadratic penalty function) - */ - state->absamax = (double)(0); - state->absasum = (double)(0); - state->absasum2 = (double)(0); - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j0 = i; - j1 = n-1; - } - else - { - j0 = 0; - j1 = i; - } - for(j=j0; j<=j1; j++) - { - v = ae_fabs(a->ptr.pp_double[i][j], _state); - state->absamax = ae_maxreal(state->absamax, v, _state); - state->absasum = state->absasum+v; - state->absasum2 = state->absasum2+v*v; - } - } -} - - -/************************************************************************* -Internal function which allows to rewrite diagonal of quadratic term. -For internal use only. - -This function can be used only when you have dense A and already made -MinQPSetQuadraticTerm(Fast) call. - - -- ALGLIB -- - Copyright 16.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqprewritediagonal(minqpstate* state, - /* Real */ ae_vector* s, - ae_state *_state) -{ - - - cqmrewritedensediagonal(&state->a, s, _state); -} - - -/************************************************************************* -Fast version of MinQPSetStartingPoint(), which doesn't check its arguments. -For internal use only. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetstartingpointfast(minqpstate* state, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t n; - - - n = state->n; - ae_v_move(&state->startx.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->havex = ae_true; -} - - -/************************************************************************* -Fast version of MinQPSetOrigin(), which doesn't check its arguments. -For internal use only. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetoriginfast(minqpstate* state, - /* Real */ ae_vector* xorigin, - ae_state *_state) -{ - ae_int_t n; - - - n = state->n; - ae_v_move(&state->xorigin.ptr.p_double[0], 1, &xorigin->ptr.p_double[0], 1, ae_v_len(0,n-1)); -} - - -void _minqpstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minqpstate *p = (minqpstate*)_p; - ae_touch_ptr((void*)p); - _qqpsettings_init(&p->qqpsettingsuser, _state, make_automatic); - _qpbleicsettings_init(&p->qpbleicsettingsuser, _state, make_automatic); - _qpdenseaulsettings_init(&p->qpdenseaulsettingsuser, _state, make_automatic); - _convexquadraticmodel_init(&p->a, _state, make_automatic); - _sparsematrix_init(&p->sparsea, _state, make_automatic); - ae_vector_init(&p->b, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->havebndl, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->havebndu, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->xorigin, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->startx, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->densec, 0, 0, DT_REAL, _state, make_automatic); - _sparsematrix_init(&p->sparsec, _state, make_automatic); - ae_vector_init(&p->cl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xs, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->replagbc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->replaglc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->effectives, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->ecleic, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->elaglc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->elagmlt, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->elagidx, 0, DT_INT, _state, make_automatic); - ae_matrix_init(&p->dummyr2, 0, 0, DT_REAL, _state, make_automatic); - _sparsematrix_init(&p->dummysparse, _state, make_automatic); - ae_matrix_init(&p->tmpr2, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->wrkbndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->wrkbndu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->wrkcl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->wrkcu, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->wrkdensec, 0, 0, DT_REAL, _state, make_automatic); - _sparsematrix_init(&p->wrksparsec, _state, make_automatic); - _qpbleicbuffers_init(&p->qpbleicbuf, _state, make_automatic); - _qqpbuffers_init(&p->qqpbuf, _state, make_automatic); - _qpdenseaulbuffers_init(&p->qpdenseaulbuf, _state, make_automatic); - _vipmstate_init(&p->vsolver, _state, make_automatic); -} - - -void _minqpstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minqpstate *dst = (minqpstate*)_dst; - minqpstate *src = (minqpstate*)_src; - dst->n = src->n; - _qqpsettings_init_copy(&dst->qqpsettingsuser, &src->qqpsettingsuser, _state, make_automatic); - _qpbleicsettings_init_copy(&dst->qpbleicsettingsuser, &src->qpbleicsettingsuser, _state, make_automatic); - _qpdenseaulsettings_init_copy(&dst->qpdenseaulsettingsuser, &src->qpdenseaulsettingsuser, _state, make_automatic); - dst->veps = src->veps; - dst->dbgskipconstraintnormalization = src->dbgskipconstraintnormalization; - dst->algokind = src->algokind; - dst->akind = src->akind; - _convexquadraticmodel_init_copy(&dst->a, &src->a, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparsea, &src->sparsea, _state, make_automatic); - dst->sparseaupper = src->sparseaupper; - dst->absamax = src->absamax; - dst->absasum = src->absasum; - dst->absasum2 = src->absasum2; - ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic); - ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic); - ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic); - dst->stype = src->stype; - ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic); - ae_vector_init_copy(&dst->havebndl, &src->havebndl, _state, make_automatic); - ae_vector_init_copy(&dst->havebndu, &src->havebndu, _state, make_automatic); - ae_vector_init_copy(&dst->xorigin, &src->xorigin, _state, make_automatic); - ae_vector_init_copy(&dst->startx, &src->startx, _state, make_automatic); - dst->havex = src->havex; - ae_matrix_init_copy(&dst->densec, &src->densec, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparsec, &src->sparsec, _state, make_automatic); - ae_vector_init_copy(&dst->cl, &src->cl, _state, make_automatic); - ae_vector_init_copy(&dst->cu, &src->cu, _state, make_automatic); - dst->mdense = src->mdense; - dst->msparse = src->msparse; - ae_vector_init_copy(&dst->xs, &src->xs, _state, make_automatic); - dst->repinneriterationscount = src->repinneriterationscount; - dst->repouteriterationscount = src->repouteriterationscount; - dst->repncholesky = src->repncholesky; - dst->repnmv = src->repnmv; - dst->repterminationtype = src->repterminationtype; - ae_vector_init_copy(&dst->replagbc, &src->replagbc, _state, make_automatic); - ae_vector_init_copy(&dst->replaglc, &src->replaglc, _state, make_automatic); - ae_vector_init_copy(&dst->effectives, &src->effectives, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_matrix_init_copy(&dst->ecleic, &src->ecleic, _state, make_automatic); - ae_vector_init_copy(&dst->elaglc, &src->elaglc, _state, make_automatic); - ae_vector_init_copy(&dst->elagmlt, &src->elagmlt, _state, make_automatic); - ae_vector_init_copy(&dst->elagidx, &src->elagidx, _state, make_automatic); - ae_matrix_init_copy(&dst->dummyr2, &src->dummyr2, _state, make_automatic); - _sparsematrix_init_copy(&dst->dummysparse, &src->dummysparse, _state, make_automatic); - ae_matrix_init_copy(&dst->tmpr2, &src->tmpr2, _state, make_automatic); - ae_vector_init_copy(&dst->wrkbndl, &src->wrkbndl, _state, make_automatic); - ae_vector_init_copy(&dst->wrkbndu, &src->wrkbndu, _state, make_automatic); - ae_vector_init_copy(&dst->wrkcl, &src->wrkcl, _state, make_automatic); - ae_vector_init_copy(&dst->wrkcu, &src->wrkcu, _state, make_automatic); - ae_matrix_init_copy(&dst->wrkdensec, &src->wrkdensec, _state, make_automatic); - _sparsematrix_init_copy(&dst->wrksparsec, &src->wrksparsec, _state, make_automatic); - dst->qpbleicfirstcall = src->qpbleicfirstcall; - _qpbleicbuffers_init_copy(&dst->qpbleicbuf, &src->qpbleicbuf, _state, make_automatic); - _qqpbuffers_init_copy(&dst->qqpbuf, &src->qqpbuf, _state, make_automatic); - _qpdenseaulbuffers_init_copy(&dst->qpdenseaulbuf, &src->qpdenseaulbuf, _state, make_automatic); - _vipmstate_init_copy(&dst->vsolver, &src->vsolver, _state, make_automatic); -} - - -void _minqpstate_clear(void* _p) -{ - minqpstate *p = (minqpstate*)_p; - ae_touch_ptr((void*)p); - _qqpsettings_clear(&p->qqpsettingsuser); - _qpbleicsettings_clear(&p->qpbleicsettingsuser); - _qpdenseaulsettings_clear(&p->qpdenseaulsettingsuser); - _convexquadraticmodel_clear(&p->a); - _sparsematrix_clear(&p->sparsea); - ae_vector_clear(&p->b); - ae_vector_clear(&p->bndl); - ae_vector_clear(&p->bndu); - ae_vector_clear(&p->s); - ae_vector_clear(&p->havebndl); - ae_vector_clear(&p->havebndu); - ae_vector_clear(&p->xorigin); - ae_vector_clear(&p->startx); - ae_matrix_clear(&p->densec); - _sparsematrix_clear(&p->sparsec); - ae_vector_clear(&p->cl); - ae_vector_clear(&p->cu); - ae_vector_clear(&p->xs); - ae_vector_clear(&p->replagbc); - ae_vector_clear(&p->replaglc); - ae_vector_clear(&p->effectives); - ae_vector_clear(&p->tmp0); - ae_matrix_clear(&p->ecleic); - ae_vector_clear(&p->elaglc); - ae_vector_clear(&p->elagmlt); - ae_vector_clear(&p->elagidx); - ae_matrix_clear(&p->dummyr2); - _sparsematrix_clear(&p->dummysparse); - ae_matrix_clear(&p->tmpr2); - ae_vector_clear(&p->wrkbndl); - ae_vector_clear(&p->wrkbndu); - ae_vector_clear(&p->wrkcl); - ae_vector_clear(&p->wrkcu); - ae_matrix_clear(&p->wrkdensec); - _sparsematrix_clear(&p->wrksparsec); - _qpbleicbuffers_clear(&p->qpbleicbuf); - _qqpbuffers_clear(&p->qqpbuf); - _qpdenseaulbuffers_clear(&p->qpdenseaulbuf); - _vipmstate_clear(&p->vsolver); -} - - -void _minqpstate_destroy(void* _p) -{ - minqpstate *p = (minqpstate*)_p; - ae_touch_ptr((void*)p); - _qqpsettings_destroy(&p->qqpsettingsuser); - _qpbleicsettings_destroy(&p->qpbleicsettingsuser); - _qpdenseaulsettings_destroy(&p->qpdenseaulsettingsuser); - _convexquadraticmodel_destroy(&p->a); - _sparsematrix_destroy(&p->sparsea); - ae_vector_destroy(&p->b); - ae_vector_destroy(&p->bndl); - ae_vector_destroy(&p->bndu); - ae_vector_destroy(&p->s); - ae_vector_destroy(&p->havebndl); - ae_vector_destroy(&p->havebndu); - ae_vector_destroy(&p->xorigin); - ae_vector_destroy(&p->startx); - ae_matrix_destroy(&p->densec); - _sparsematrix_destroy(&p->sparsec); - ae_vector_destroy(&p->cl); - ae_vector_destroy(&p->cu); - ae_vector_destroy(&p->xs); - ae_vector_destroy(&p->replagbc); - ae_vector_destroy(&p->replaglc); - ae_vector_destroy(&p->effectives); - ae_vector_destroy(&p->tmp0); - ae_matrix_destroy(&p->ecleic); - ae_vector_destroy(&p->elaglc); - ae_vector_destroy(&p->elagmlt); - ae_vector_destroy(&p->elagidx); - ae_matrix_destroy(&p->dummyr2); - _sparsematrix_destroy(&p->dummysparse); - ae_matrix_destroy(&p->tmpr2); - ae_vector_destroy(&p->wrkbndl); - ae_vector_destroy(&p->wrkbndu); - ae_vector_destroy(&p->wrkcl); - ae_vector_destroy(&p->wrkcu); - ae_matrix_destroy(&p->wrkdensec); - _sparsematrix_destroy(&p->wrksparsec); - _qpbleicbuffers_destroy(&p->qpbleicbuf); - _qqpbuffers_destroy(&p->qqpbuf); - _qpdenseaulbuffers_destroy(&p->qpdenseaulbuf); - _vipmstate_destroy(&p->vsolver); -} - - -void _minqpreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minqpreport *p = (minqpreport*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->lagbc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->laglc, 0, DT_REAL, _state, make_automatic); -} - - -void _minqpreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minqpreport *dst = (minqpreport*)_dst; - minqpreport *src = (minqpreport*)_src; - dst->inneriterationscount = src->inneriterationscount; - dst->outeriterationscount = src->outeriterationscount; - dst->nmv = src->nmv; - dst->ncholesky = src->ncholesky; - dst->terminationtype = src->terminationtype; - ae_vector_init_copy(&dst->lagbc, &src->lagbc, _state, make_automatic); - ae_vector_init_copy(&dst->laglc, &src->laglc, _state, make_automatic); -} - - -void _minqpreport_clear(void* _p) -{ - minqpreport *p = (minqpreport*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->lagbc); - ae_vector_clear(&p->laglc); -} - - -void _minqpreport_destroy(void* _p) -{ - minqpreport *p = (minqpreport*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->lagbc); - ae_vector_destroy(&p->laglc); -} - - -#endif -#if defined(AE_COMPILE_LPQPPRESOLVE) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -No presolve, just user-supplied scaling + constraint and cost vector -normalization. - -INPUT PARAMETERS: - S - array[N], user-supplied scale vector, S[I]>0 - C - array[N], costs - BndL - array[N], lower bounds (may contain -INF) - BndU - array[N], upper bounds (may contain +INF) - N - variable count, N>0 - SparseA - matrix[K,N], sparse constraints - AL - array[K], lower constraint bounds (may contain -INF) - AU - array[K], upper constraint bounds (may contain +INF) - K - constraint count, K>=0 - Info - presolve info structure; temporaries allocated during - previous calls may be reused by this function. - -OUTPUT PARAMETERS: - Info - contains transformed C, BndL, bndU, SparseA, AL, AU - and information necessary to perform backward - transformation. - Following fields can be acessed: - * Info.NewN>0 for transformed problem size - * Info.NewM>=0 for transformed constraint count - * always: Info.C, Info.BndL, Info.BndU - array[NewN] - * for Info.NewM>0: Info.SparseA, Info.AL, Info.AU - -NOTE: this routine does not reallocate arrays if NNew<=NOld and/or KNew<=KOld. - - -- ALGLIB -- - Copyright 01.07.2020 by Bochkanov Sergey -*************************************************************************/ -void presolvenonescaleuser(/* Real */ ae_vector* s, - /* Real */ ae_vector* c, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_int_t n, - sparsematrix* sparsea, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t k, - presolveinfo* info, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t j0; - ae_int_t j1; - double v; - double avgln; - - - - /* - * Integrity checks - */ - ae_assert(bndl->cnt>=n, "PresolveNoneScaleUser: Length(BndL)cnt>=n, "PresolveNoneScaleUser: Length(BndU)cnt>=n, "PresolveNoneScaleUser: Length(S)cnt>=n, "PresolveNoneScaleUser: Length(C)=0, "PresolveNoneScaleUser: K<0", _state); - ae_assert(k==0||sparseiscrs(sparsea, _state), "PresolveNoneScaleUser: A is not CRS", _state); - ae_assert(k==0||sparsea->m==k, "PresolveNoneScaleUser: rows(A)<>K", _state); - ae_assert(k==0||sparsea->n==n, "PresolveNoneScaleUser: cols(A)<>N", _state); - - /* - * Reallocate storage - */ - rvectorgrowto(&info->rawbndl, n, _state); - rvectorgrowto(&info->rawbndu, n, _state); - rvectorgrowto(&info->colscales, n, _state); - rvectorgrowto(&info->rowscales, k, _state); - - /* - * Save original problem formulation - */ - info->newn = n; - info->oldn = n; - info->newm = k; - info->oldm = k; - for(i=0; i<=n-1; i++) - { - ae_assert(s->ptr.p_double[i]>0, "PresolveNoneScaleUser: S<=0", _state); - ae_assert(ae_isfinite(bndl->ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "PresolveNoneScaleUser: BndL contains NAN or +INF", _state); - ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "PresolveNoneScaleUser: BndU contains NAN or -INF", _state); - info->colscales.ptr.p_double[i] = s->ptr.p_double[i]; - info->rawbndl.ptr.p_double[i] = bndl->ptr.p_double[i]; - info->rawbndu.ptr.p_double[i] = bndu->ptr.p_double[i]; - } - - /* - * Scale cost and box constraints - */ - rvectorsetlengthatleast(&info->c, n, _state); - rvectorsetlengthatleast(&info->bndl, n, _state); - rvectorsetlengthatleast(&info->bndu, n, _state); - for(i=0; i<=n-1; i++) - { - info->c.ptr.p_double[i] = c->ptr.p_double[i]*s->ptr.p_double[i]; - info->bndl.ptr.p_double[i] = bndl->ptr.p_double[i]/s->ptr.p_double[i]; - info->bndu.ptr.p_double[i] = bndu->ptr.p_double[i]/s->ptr.p_double[i]; - } - avgln = (double)(0); - for(i=0; i<=n-1; i++) - { - avgln = avgln+ae_log(1+ae_fabs(info->c.ptr.p_double[i], _state), _state); - } - info->costscale = ae_exp(avgln/n, _state); - rmulv(n, 1/info->costscale, &info->c, _state); - - /* - * Quick exit if no linear constraints is present - */ - if( k==0 ) - { - return; - } - - /* - * Scale constraint matrix - */ - rcopyallocv(k, al, &info->al, _state); - rcopyallocv(k, au, &info->au, _state); - sparsecopybuf(sparsea, &info->sparsea, _state); - for(i=0; i<=k-1; i++) - { - ae_assert(ae_isfinite(info->al.ptr.p_double[i], _state)||ae_isneginf(info->al.ptr.p_double[i], _state), "PresolveNoneScaleUser: AL contains NAN or +INF", _state); - ae_assert(ae_isfinite(info->au.ptr.p_double[i], _state)||ae_isposinf(info->au.ptr.p_double[i], _state), "PresolveNoneScaleUser: AU contains NAN or -INF", _state); - info->rowscales.ptr.p_double[i] = (double)(0); - j0 = info->sparsea.ridx.ptr.p_int[i]; - j1 = info->sparsea.ridx.ptr.p_int[i+1]-1; - for(j=j0; j<=j1; j++) - { - v = s->ptr.p_double[info->sparsea.idx.ptr.p_int[j]]*info->sparsea.vals.ptr.p_double[j]; - info->sparsea.vals.ptr.p_double[j] = v; - info->rowscales.ptr.p_double[i] = ae_maxreal(info->rowscales.ptr.p_double[i], v, _state); - } - info->rowscales.ptr.p_double[i] = ae_maxreal(info->rowscales.ptr.p_double[i], 1.0, _state); - v = 1/info->rowscales.ptr.p_double[i]; - for(j=j0; j<=j1; j++) - { - info->sparsea.vals.ptr.p_double[j] = v*info->sparsea.vals.ptr.p_double[j]; - } - info->al.ptr.p_double[i] = info->al.ptr.p_double[i]*v; - info->au.ptr.p_double[i] = info->au.ptr.p_double[i]*v; - } -} - - -/************************************************************************* -Backward transformation which extracts original solution from that of the -converted problem. - -Below NNew/KNew correspond to transformed problem size (as returned by the -presolve routine) and NOld/KOld correspond to original problem size (as -specified by caller). We expect that caller knows these sizes, so this -routine does not report them. - -INPUT PARAMETERS: - Info - presolve info structure - X - array[NNew], transformed solution (primal variables) - Stats - array[NNew+MNew], transformed constraint status (negative - - at lower bound, positive - at upper bound, zero - - inactive). - LagBC - array[NNew], transformed Lagrange multipliers - LagLC - array[KNew], transformed Lagrange multipliers - -OUTPUT PARAMETERS: - X - array[NOld], original solution (primal variables) - Stats - array[NOld+MOld], original constraint status - LagBC - array[NOld], Lagrange multipliers - LagLC - array[KOld], Lagrange multipliers - -NOTE: this routine does not reallocate arrays if NOld<=NNew and/or KOld<=KNew. - - -- ALGLIB -- - Copyright 01.07.2020 by Bochkanov Sergey -*************************************************************************/ -void presolvebwd(presolveinfo* info, - /* Real */ ae_vector* x, - /* Integer */ ae_vector* stats, - /* Real */ ae_vector* lagbc, - /* Real */ ae_vector* laglc, - ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - ae_int_t i; - - - ae_assert(info->oldn==info->newn, "PresolveBwd: integrity check failed", _state); - ae_assert(info->oldm==info->newm, "PresolveBwd: integrity check failed", _state); - n = info->oldn; - m = info->oldm; - for(i=0; i<=n-1; i++) - { - if( stats->ptr.p_int[i]<0 ) - { - x->ptr.p_double[i] = info->rawbndl.ptr.p_double[i]; - continue; - } - if( stats->ptr.p_int[i]>0 ) - { - x->ptr.p_double[i] = info->rawbndu.ptr.p_double[i]; - continue; - } - x->ptr.p_double[i] = x->ptr.p_double[i]*info->colscales.ptr.p_double[i]; - if( ae_isfinite(info->rawbndl.ptr.p_double[i], _state) ) - { - x->ptr.p_double[i] = ae_maxreal(x->ptr.p_double[i], info->rawbndl.ptr.p_double[i], _state); - } - if( ae_isfinite(info->rawbndu.ptr.p_double[i], _state) ) - { - x->ptr.p_double[i] = ae_minreal(x->ptr.p_double[i], info->rawbndu.ptr.p_double[i], _state); - } - } - for(i=0; i<=n-1; i++) - { - lagbc->ptr.p_double[i] = lagbc->ptr.p_double[i]*info->costscale/info->colscales.ptr.p_double[i]; - } - for(i=0; i<=m-1; i++) - { - laglc->ptr.p_double[i] = laglc->ptr.p_double[i]*info->costscale/info->rowscales.ptr.p_double[i]; - } -} - - -void _presolveinfo_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - presolveinfo *p = (presolveinfo*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->rawbndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rawbndu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->colscales, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rowscales, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->c, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic); - _sparsematrix_init(&p->sparsea, _state, make_automatic); - ae_vector_init(&p->al, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->au, 0, DT_REAL, _state, make_automatic); -} - - -void _presolveinfo_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - presolveinfo *dst = (presolveinfo*)_dst; - presolveinfo *src = (presolveinfo*)_src; - dst->newn = src->newn; - dst->oldn = src->oldn; - dst->newm = src->newm; - dst->oldm = src->oldm; - ae_vector_init_copy(&dst->rawbndl, &src->rawbndl, _state, make_automatic); - ae_vector_init_copy(&dst->rawbndu, &src->rawbndu, _state, make_automatic); - ae_vector_init_copy(&dst->colscales, &src->colscales, _state, make_automatic); - ae_vector_init_copy(&dst->rowscales, &src->rowscales, _state, make_automatic); - dst->costscale = src->costscale; - ae_vector_init_copy(&dst->c, &src->c, _state, make_automatic); - ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic); - ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparsea, &src->sparsea, _state, make_automatic); - ae_vector_init_copy(&dst->al, &src->al, _state, make_automatic); - ae_vector_init_copy(&dst->au, &src->au, _state, make_automatic); -} - - -void _presolveinfo_clear(void* _p) -{ - presolveinfo *p = (presolveinfo*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->rawbndl); - ae_vector_clear(&p->rawbndu); - ae_vector_clear(&p->colscales); - ae_vector_clear(&p->rowscales); - ae_vector_clear(&p->c); - ae_vector_clear(&p->bndl); - ae_vector_clear(&p->bndu); - _sparsematrix_clear(&p->sparsea); - ae_vector_clear(&p->al); - ae_vector_clear(&p->au); -} - - -void _presolveinfo_destroy(void* _p) -{ - presolveinfo *p = (presolveinfo*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->rawbndl); - ae_vector_destroy(&p->rawbndu); - ae_vector_destroy(&p->colscales); - ae_vector_destroy(&p->rowscales); - ae_vector_destroy(&p->c); - ae_vector_destroy(&p->bndl); - ae_vector_destroy(&p->bndu); - _sparsematrix_destroy(&p->sparsea); - ae_vector_destroy(&p->al); - ae_vector_destroy(&p->au); -} - - -#endif -#if defined(AE_COMPILE_REVISEDDUALSIMPLEX) || !defined(AE_PARTIAL_BUILD) - - -void dsssettingsinit(dualsimplexsettings* settings, ae_state *_state) -{ - - - settings->xtolabs = 1.0E-6; - settings->dtolabs = 1.0E-6; - settings->xtolrelabs = 0.01; - settings->pivottol = 10*ae_sqrt(ae_machineepsilon, _state); - settings->perturbmag = 10*settings->pivottol; - settings->maxtrfage = reviseddualsimplex_defaultmaxtrfage; - settings->trftype = 3; - settings->ratiotest = 1; - settings->pricing = 1; - settings->shifting = 2; -} - - -/************************************************************************* -This function initializes DSS structure. Previously allocated memory is -reused as much as possible. - -Default state of the problem is zero cost vector, all variables are fixed -at zero. - - -- ALGLIB -- - Copyright 01.07.2018 by Bochkanov Sergey -*************************************************************************/ -void dssinit(ae_int_t n, dualsimplexstate* s, ae_state *_state) -{ - ae_int_t i; - - - ae_assert(n>0, "DSSInit: N<=0", _state); - s->ns = n; - s->m = 0; - rvectorgrowto(&s->rawbndl, n, _state); - rvectorgrowto(&s->rawbndu, n, _state); - for(i=0; i<=n-1; i++) - { - s->rawbndl.ptr.p_double[i] = 0.0; - s->rawbndu.ptr.p_double[i] = 0.0; - } - reviseddualsimplex_subprobleminit(n, &s->primary, _state); - reviseddualsimplex_basisinit(n, 0, &s->basis, _state); - rvectorgrowto(&s->repx, n, _state); - rvectorgrowto(&s->replagbc, n, _state); - ivectorgrowto(&s->repstats, n, _state); - for(i=0; i<=n-1; i++) - { - s->repx.ptr.p_double[i] = 0.0; - s->repstats.ptr.p_int[i] = 1; - } - s->dotrace = ae_false; - s->dodetailedtrace = ae_false; - s->dotimers = ae_false; -} - - -/************************************************************************* -This function specifies LP problem - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - - BndL - lower bounds, array[N]. - BndU - upper bounds, array[N]. - - DenseA - dense array[K,N], dense linear constraints (not supported - in present version) - SparseA - sparse linear constraints, sparsematrix[K,N] in CRS format - AKind - type of A: 0 for dense, 1 for sparse - AL, AU - lower and upper bounds, array[K] - K - number of equality/inequality constraints, K>=0. - - ProposedBasis- basis to import from (if BasisType=2) - BasisInitType- what to do with basis: - * 0 - set new basis to all-logicals - * 1 - try to reuse previous basis as much as possible - * 2 - try to import basis from ProposedBasis - Settings- algorithm settings - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void dsssetproblem(dualsimplexstate* state, - /* Real */ ae_vector* c, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_matrix* densea, - sparsematrix* sparsea, - ae_int_t akind, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t k, - dualsimplexbasis* proposedbasis, - ae_int_t basisinittype, - dualsimplexsettings* settings, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t jj; - ae_int_t offs; - ae_int_t ns; - ae_int_t j0; - ae_int_t j1; - ae_bool processed; - ae_int_t oldm; - ae_bool basisinitialized; - double v; - - - ns = state->primary.ns; - oldm = state->primary.m; - - /* - * Integrity checks - */ - ae_assert(bndl->cnt>=ns, "DSSSetProblem: Length(BndL)cnt>=ns, "DSSSetProblem: Length(BndU)cnt>=ns, "SubproblemSetCost: Length(C)=0, "DSSSetProblem: K<0", _state); - if( k>0&&akind==1 ) - { - ae_assert(sparsea->m==k, "DSSSetProblem: rows(A)<>K", _state); - ae_assert(sparsea->n==ns, "DSSSetProblem: cols(A)<>N", _state); - } - - /* - * Downgrade state - */ - reviseddualsimplex_downgradestate(&state->primary, reviseddualsimplex_ssinvalid, _state); - - /* - * Reallocate storage - */ - rvectorgrowto(&state->primary.bndl, ns+k, _state); - rvectorgrowto(&state->primary.bndu, ns+k, _state); - ivectorgrowto(&state->primary.bndt, ns+k, _state); - rvectorgrowto(&state->primary.rawc, ns+k, _state); - rvectorgrowto(&state->primary.effc, ns+k, _state); - rvectorgrowto(&state->primary.xa, ns+k, _state); - rvectorgrowto(&state->primary.d, ns+k, _state); - rvectorgrowto(&state->primary.xb, k, _state); - rvectorgrowto(&state->primary.bndlb, k, _state); - rvectorgrowto(&state->primary.bndub, k, _state); - ivectorgrowto(&state->primary.bndtb, k, _state); - rvectorgrowto(&state->primary.bndtollb, k, _state); - rvectorgrowto(&state->primary.bndtolub, k, _state); - - /* - * Save original problem formulation - */ - state->ns = ns; - state->m = k; - for(i=0; i<=ns-1; i++) - { - state->rawbndl.ptr.p_double[i] = bndl->ptr.p_double[i]; - state->rawbndu.ptr.p_double[i] = bndu->ptr.p_double[i]; - } - - /* - * Setup cost, scale and box constraints - */ - rsetv(ns+k, 0.0, &state->primary.rawc, _state); - rsetv(ns+k, 0.0, &state->primary.effc, _state); - for(i=0; i<=ns-1; i++) - { - state->primary.rawc.ptr.p_double[i] = c->ptr.p_double[i]; - state->primary.effc.ptr.p_double[i] = c->ptr.p_double[i]; - } - for(i=0; i<=ns-1; i++) - { - ae_assert(ae_isfinite(bndl->ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "DSSSetProblem: BndL contains NAN or +INF", _state); - ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "DSSSetProblem: BndU contains NAN or -INF", _state); - state->primary.bndl.ptr.p_double[i] = bndl->ptr.p_double[i]; - state->primary.bndu.ptr.p_double[i] = bndu->ptr.p_double[i]; - - /* - * Set bound type - */ - if( ae_isfinite(bndl->ptr.p_double[i], _state)&&ae_isfinite(bndu->ptr.p_double[i], _state) ) - { - if( ae_fp_greater(bndl->ptr.p_double[i],bndu->ptr.p_double[i]) ) - { - state->primary.bndt.ptr.p_int[i] = reviseddualsimplex_ccinfeasible; - } - if( ae_fp_less(bndl->ptr.p_double[i],bndu->ptr.p_double[i]) ) - { - state->primary.bndt.ptr.p_int[i] = reviseddualsimplex_ccrange; - } - if( ae_fp_eq(bndl->ptr.p_double[i],bndu->ptr.p_double[i]) ) - { - state->primary.bndt.ptr.p_int[i] = reviseddualsimplex_ccfixed; - } - continue; - } - if( ae_isfinite(bndl->ptr.p_double[i], _state)&&!ae_isfinite(bndu->ptr.p_double[i], _state) ) - { - state->primary.bndt.ptr.p_int[i] = reviseddualsimplex_cclower; - continue; - } - if( !ae_isfinite(bndl->ptr.p_double[i], _state)&&ae_isfinite(bndu->ptr.p_double[i], _state) ) - { - state->primary.bndt.ptr.p_int[i] = reviseddualsimplex_ccupper; - continue; - } - ae_assert(ae_isneginf(bndl->ptr.p_double[i], _state)&&ae_isposinf(bndu->ptr.p_double[i], _state), "DSSSetProblem: integrity check failed", _state); - state->primary.bndt.ptr.p_int[i] = reviseddualsimplex_ccfree; - } - - /* - * Quick exit if no linear constraints is present - */ - if( k==0 ) - { - state->primary.m = 0; - reviseddualsimplex_basisinit(state->primary.ns, state->primary.m, &state->basis, _state); - return; - } - - /* - * Extend A with structural terms and transpose it: - * * allocate place for A^T extended with logical part. - * * copy with transposition - * * perform integrity check for array sizes - * * manually append new items - * * update DIdx/UIdx - */ - processed = ae_false; - state->primary.m = k; - if( akind==0 ) - { - ae_assert(ae_false, "DSSSetProblem: does not support dense inputs yet", _state); - } - if( akind==1 ) - { - - /* - * Transpose constraints matrix, apply column and row scaling. - * Extend it with identity submatrix. - * - * NOTE: in order to improve stability of LU factorization we - * normalize rows using 2-norm, not INF-norm. Having rows - * normalized with 2-norm makes every element less than - * 1.0 in magnitude, which allows us later to move logical - * columns to the beginning of LU factors without loosing - * stability. - */ - rvectorsetlengthatleast(&state->at.vals, sparsea->ridx.ptr.p_int[k]+k, _state); - ivectorsetlengthatleast(&state->at.idx, sparsea->ridx.ptr.p_int[k]+k, _state); - ivectorsetlengthatleast(&state->at.ridx, ns+k+1, _state); - ivectorsetlengthatleast(&state->at.didx, ns+k, _state); - ivectorsetlengthatleast(&state->at.uidx, ns+k, _state); - sparsecopytransposecrsbuf(sparsea, &state->at, _state); - rvectorsetlengthatleast(&state->rowscales, k, _state); - for(i=0; i<=k-1; i++) - { - state->rowscales.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=ns-1; i++) - { - j0 = state->at.ridx.ptr.p_int[i]; - j1 = state->at.ridx.ptr.p_int[i+1]-1; - for(j=j0; j<=j1; j++) - { - v = state->at.vals.ptr.p_double[j]; - jj = state->at.idx.ptr.p_int[j]; - state->at.vals.ptr.p_double[j] = v; - state->rowscales.ptr.p_double[jj] = state->rowscales.ptr.p_double[jj]+v*v; - } - } - rvectorsetlengthatleast(&state->tmp0, k, _state); - for(i=0; i<=k-1; i++) - { - state->rowscales.ptr.p_double[i] = coalesce(ae_sqrt(state->rowscales.ptr.p_double[i], _state), (double)(1), _state); - state->tmp0.ptr.p_double[i] = 1/state->rowscales.ptr.p_double[i]; - } - for(i=0; i<=ns-1; i++) - { - j0 = state->at.ridx.ptr.p_int[i]; - j1 = state->at.ridx.ptr.p_int[i+1]-1; - for(j=j0; j<=j1; j++) - { - state->at.vals.ptr.p_double[j] = state->at.vals.ptr.p_double[j]*state->tmp0.ptr.p_double[state->at.idx.ptr.p_int[j]]; - } - } - ae_assert(state->at.vals.cnt>=sparsea->ridx.ptr.p_int[k]+k, "DSSSetProblem: integrity check failed", _state); - ae_assert(state->at.idx.cnt>=sparsea->ridx.ptr.p_int[k]+k, "DSSSetProblem: integrity check failed", _state); - ae_assert(state->at.ridx.cnt>=ns+k+1, "DSSSetProblem: integrity check failed", _state); - ae_assert(state->at.didx.cnt>=ns+k, "DSSSetProblem: integrity check failed", _state); - ae_assert(state->at.uidx.cnt>=ns+k, "DSSSetProblem: integrity check failed", _state); - offs = state->at.ridx.ptr.p_int[ns]; - for(i=0; i<=k-1; i++) - { - state->at.vals.ptr.p_double[offs+i] = -1.0; - state->at.idx.ptr.p_int[offs+i] = i; - state->at.ridx.ptr.p_int[ns+i+1] = state->at.ridx.ptr.p_int[ns+i]+1; - state->at.ninitialized = state->at.ninitialized+1; - } - state->at.m = state->at.m+k; - sparseinitduidx(&state->at, _state); - sparsecopytransposecrsbuf(&state->at, &state->a, _state); - processed = ae_true; - } - ae_assert(processed, "DSSSetProblem: integrity check failed (akind)", _state); - - /* - * Copy AL, AU to BndL/BndT - */ - for(i=0; i<=k-1; i++) - { - ae_assert(ae_isfinite(al->ptr.p_double[i], _state)||ae_isneginf(al->ptr.p_double[i], _state), "DSSSetProblem: AL contains NAN or +INF", _state); - ae_assert(ae_isfinite(au->ptr.p_double[i], _state)||ae_isposinf(au->ptr.p_double[i], _state), "DSSSetProblem: AU contains NAN or -INF", _state); - state->primary.bndl.ptr.p_double[ns+i] = al->ptr.p_double[i]/state->rowscales.ptr.p_double[i]; - state->primary.bndu.ptr.p_double[ns+i] = au->ptr.p_double[i]/state->rowscales.ptr.p_double[i]; - - /* - * Set bound type - */ - if( ae_isfinite(al->ptr.p_double[i], _state)&&ae_isfinite(au->ptr.p_double[i], _state) ) - { - if( ae_fp_greater(al->ptr.p_double[i],au->ptr.p_double[i]) ) - { - state->primary.bndt.ptr.p_int[ns+i] = reviseddualsimplex_ccinfeasible; - } - if( ae_fp_less(al->ptr.p_double[i],au->ptr.p_double[i]) ) - { - state->primary.bndt.ptr.p_int[ns+i] = reviseddualsimplex_ccrange; - } - if( ae_fp_eq(al->ptr.p_double[i],au->ptr.p_double[i]) ) - { - state->primary.bndt.ptr.p_int[ns+i] = reviseddualsimplex_ccfixed; - } - continue; - } - if( ae_isfinite(al->ptr.p_double[i], _state)&&!ae_isfinite(au->ptr.p_double[i], _state) ) - { - state->primary.bndt.ptr.p_int[ns+i] = reviseddualsimplex_cclower; - continue; - } - if( !ae_isfinite(al->ptr.p_double[i], _state)&&ae_isfinite(au->ptr.p_double[i], _state) ) - { - state->primary.bndt.ptr.p_int[ns+i] = reviseddualsimplex_ccupper; - continue; - } - ae_assert(ae_isneginf(al->ptr.p_double[i], _state)&&ae_isposinf(au->ptr.p_double[i], _state), "DSSSetProblem: integrity check faoled", _state); - state->primary.bndt.ptr.p_int[ns+i] = reviseddualsimplex_ccfree; - } - - /* - * Depending on BasisInitType either start from all-logical basis - * or try to reuse already existing basis. - * - * NOTE: current version does not support basis shrinkage, only - * growing basis can be reused. - */ - basisinitialized = ae_false; - if( basisinittype==2 ) - { - - /* - * Import basis from one proposed by caller - */ - ae_assert(proposedbasis->ns==state->primary.ns, "DSSSetProblemX: unable to import basis, sizes do not match", _state); - ae_assert(proposedbasis->m==state->primary.m, "DSSSetProblemX: unable to import basis, sizes do not match", _state); - basisinitialized = reviseddualsimplex_basistryimportfrom(&state->basis, proposedbasis, &state->at, settings, _state); - } - if( basisinittype==1&&state->primary.m>=oldm ) - { - - /* - * New rows were added, try to reuse previous basis - */ - for(i=oldm; i<=state->primary.m-1; i++) - { - state->primary.rawc.ptr.p_double[ns+i] = 0.0; - state->primary.effc.ptr.p_double[ns+i] = 0.0; - state->primary.xa.ptr.p_double[ns+i] = 0.0; - state->primary.d.ptr.p_double[ns+i] = 0.0; - } - basisinitialized = reviseddualsimplex_basistryresize(&state->basis, state->primary.m, &state->at, settings, _state); - } - if( !basisinitialized ) - { - - /* - * Straightforward code for all-logicals basis - */ - for(i=0; i<=k-1; i++) - { - state->primary.rawc.ptr.p_double[ns+i] = 0.0; - state->primary.effc.ptr.p_double[ns+i] = 0.0; - state->primary.xa.ptr.p_double[ns+i] = 0.0; - state->primary.d.ptr.p_double[ns+i] = 0.0; - } - reviseddualsimplex_basisinit(state->primary.ns, state->primary.m, &state->basis, _state); - reviseddualsimplex_basisfreshtrf(&state->basis, &state->at, settings, _state); - } - rvectorgrowto(&state->replaglc, state->primary.m, _state); - ivectorgrowto(&state->repstats, state->primary.ns+state->primary.m, _state); -} - - -/************************************************************************* -This function exports basis from the primary (phase II) subproblem. - -INPUT PARAMETERS: - State - structure - -OUTPUT PARAMETERS - Basis - current basis exported (no factorization, only set of - basis/nonbasic variables) - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void dssexportbasis(dualsimplexstate* state, - dualsimplexbasis* basis, - ae_state *_state) -{ - - - reviseddualsimplex_basisexportto(&state->basis, basis, _state); -} - - -/************************************************************************* -This function solves LP problem with dual simplex solver. - -INPUT PARAMETERS: - State - state - -Solution results can be found in fields of State which are explicitly -declared as accessible by external code. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void dssoptimize(dualsimplexstate* state, - dualsimplexsettings* settings, - ae_state *_state) -{ - ae_int_t i; - ae_int_t nx; - double v; - ae_int_t cnt1; - ae_int_t cnt2; - ae_int_t cntfx; - ae_int_t cntfr; - ae_int_t cntif; - ae_int_t ttotal; - - - nx = state->primary.ns+state->primary.m; - ttotal = 0; - - /* - * Trace settings - */ - state->dotrace = ae_is_trace_enabled("DUALSIMPLEX"); - state->dodetailedtrace = state->dotrace&&ae_is_trace_enabled("DUALSIMPLEX.DETAILED"); - state->dotimers = ae_is_trace_enabled("TIMERS.DUALSIMPLEX"); - - /* - * Init report fields - */ - state->repiterationscount = 0; - state->repiterationscount1 = 0; - state->repiterationscount2 = 0; - state->repiterationscount3 = 0; - state->repterminationtype = 1; - state->repphase1time = 0; - state->repphase2time = 0; - state->repphase3time = 0; - state->repdualpricingtime = 0; - state->repdualbtrantime = 0; - state->repdualpivotrowtime = 0; - state->repdualratiotesttime = 0; - state->repdualftrantime = 0; - state->repdualupdatesteptime = 0; - state->repfillpivotrow = (double)(0); - state->repfillpivotrowcnt = 0; - state->repfillrhor = (double)(0); - state->repfillrhorcnt = 0; - state->repfilldensemu = (double)(0); - state->repfilldensemucnt = 0; - reviseddualsimplex_basisclearstats(&state->basis, _state); - - /* - * Setup timer (if needed) - */ - if( state->dotimers ) - { - ttotal = ae_tickcount(); - } - - /* - * Trace output (if needed) - */ - if( state->dotrace||state->dotimers ) - { - ae_trace("\n\n"); - ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n"); - ae_trace("// DUAL SIMPLEX SOLVER STARTED //\n"); - ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n"); - ae_trace("> problem size:\n"); - ae_trace("N = %12d (variables)\n", - (int)(state->primary.ns)); - ae_trace("M = %12d (constraints)\n", - (int)(state->primary.m)); - } - if( state->dotrace ) - { - ae_trace("> variable stats:\n"); - if( state->dodetailedtrace ) - { - } - cnt1 = 0; - cnt2 = 0; - cntfx = 0; - cntfr = 0; - cntif = 0; - for(i=0; i<=state->primary.ns-1; i++) - { - if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_cclower||state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccupper ) - { - inc(&cnt1, _state); - } - if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccrange ) - { - inc(&cnt2, _state); - } - if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccfixed ) - { - inc(&cntfx, _state); - } - if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccfree ) - { - inc(&cntfr, _state); - } - if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccinfeasible ) - { - inc(&cntif, _state); - } - } - ae_trace("UBnd/LBnd = %12d\n", - (int)(cnt1)); - ae_trace("Range = %12d\n", - (int)(cnt2)); - ae_trace("Fixed = %12d\n", - (int)(cntfx)); - ae_trace("Free = %12d\n", - (int)(cntfr)); - ae_trace("Infeas = %12d\n", - (int)(cntif)); - ae_trace("> constraint stats:\n"); - if( state->dodetailedtrace ) - { - } - cnt1 = 0; - cnt2 = 0; - cntfx = 0; - cntfr = 0; - cntif = 0; - for(i=state->primary.ns-1; i<=nx-1; i++) - { - if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_cclower||state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccupper ) - { - inc(&cnt1, _state); - } - if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccrange ) - { - inc(&cnt2, _state); - } - if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccfixed ) - { - inc(&cntfx, _state); - } - if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccfree ) - { - inc(&cntfr, _state); - } - if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccinfeasible ) - { - inc(&cntif, _state); - } - } - ae_trace("ubnd/lbnd = %12d\n", - (int)(cnt1)); - ae_trace("range = %12d\n", - (int)(cnt2)); - ae_trace("fixed = %12d\n", - (int)(cntfx)); - ae_trace("free = %12d\n", - (int)(cntfr)); - ae_trace("infeas = %12d\n", - (int)(cntif)); - v = (double)(0); - for(i=0; i<=state->primary.ns-1; i++) - { - if( ae_isfinite(state->primary.bndl.ptr.p_double[i], _state) ) - { - v = ae_maxreal(v, ae_fabs(state->primary.bndl.ptr.p_double[i], _state), _state); - } - } - ae_trace("|BndL| = %0.3e\n", - (double)(v)); - v = (double)(0); - for(i=0; i<=state->primary.ns-1; i++) - { - if( ae_isfinite(state->primary.bndu.ptr.p_double[i], _state) ) - { - v = ae_maxreal(v, ae_fabs(state->primary.bndu.ptr.p_double[i], _state), _state); - } - } - ae_trace("|BndU| = %0.3e\n", - (double)(v)); - v = (double)(0); - for(i=state->primary.ns; i<=nx-1; i++) - { - if( ae_isfinite(state->primary.bndl.ptr.p_double[i], _state) ) - { - v = ae_maxreal(v, ae_fabs(state->primary.bndl.ptr.p_double[i], _state), _state); - } - } - ae_trace("|AL| = %0.3e\n", - (double)(v)); - v = (double)(0); - for(i=state->primary.ns; i<=nx-1; i++) - { - if( ae_isfinite(state->primary.bndu.ptr.p_double[i], _state) ) - { - v = ae_maxreal(v, ae_fabs(state->primary.bndu.ptr.p_double[i], _state), _state); - } - } - ae_trace("|AU| = %0.3e\n", - (double)(v)); - } - - /* - * Call actual workhorse function - */ - reviseddualsimplex_dssoptimizewrk(state, settings, _state); - - /* - * Print reports - */ - if( state->dotrace ) - { - ae_trace("\n"); - ae_trace("****************************************************************************************************\n"); - ae_trace("* PRINTING ITERATION STATISTICS *\n"); - ae_trace("****************************************************************************************************\n"); - ae_trace("> iteration counts:\n"); - ae_trace("Phase 1 = %12d\n", - (int)(state->repiterationscount1)); - ae_trace("Phase 2 = %12d\n", - (int)(state->repiterationscount2)); - ae_trace("Phase 3 = %12d\n", - (int)(state->repiterationscount3)); - ae_trace("> factorization statistics:\n"); - ae_trace("FactCnt = %12d (LU factorizations)\n", - (int)(state->basis.statfact)); - ae_trace("UpdtCnt = %12d (LU updates)\n", - (int)(state->basis.statupdt)); - ae_trace("RefactPeriod= %12.1f (average refactorization interval)\n", - (double)((state->basis.statfact+state->basis.statupdt)/coalesce((double)(state->basis.statfact), (double)(1), _state))); - ae_trace("LU-NZR = %12.1f (average LU nonzeros per row)\n", - (double)(state->basis.statoffdiag/(coalesce((double)(state->m), (double)(1), _state)*coalesce((double)(state->basis.statfact+state->basis.statupdt), (double)(1), _state)))); - ae_trace("> sparsity counters (average fill factors):\n"); - if( state->dodetailedtrace ) - { - ae_trace("RhoR = %12.4f (BTran result)\n", - (double)(state->repfillrhor/coalesce((double)(state->repfillrhorcnt), (double)(1), _state))); - ae_trace("AlphaR = %12.4f (pivot row)\n", - (double)(state->repfillpivotrow/coalesce((double)(state->repfillpivotrowcnt), (double)(1), _state))); - if( state->basis.trftype==3 ) - { - ae_trace("Mu = %12.4f (Forest-Tomlin factor)\n", - (double)(state->repfilldensemu/coalesce((double)(state->repfilldensemucnt), (double)(1), _state))); - } - } - else - { - ae_trace("...skipped, need DUALSIMPLEX.DETAILED trace tag\n"); - } - } - if( state->dotimers ) - { - ttotal = ae_tickcount()-ttotal; - ae_trace("\n"); - ae_trace("****************************************************************************************************\n"); - ae_trace("* PRINTING DUAL SIMPLEX TIMERS *\n"); - ae_trace("****************************************************************************************************\n"); - ae_trace("> total time:\n"); - ae_trace("Time = %12d ms\n", - (int)(ttotal)); - ae_trace("> time by phase:\n"); - ae_trace("Phase 1 = %12d ms\n", - (int)(state->repphase1time)); - ae_trace("Phase 2 = %12d ms\n", - (int)(state->repphase2time)); - ae_trace("Phase 3 = %12d ms\n", - (int)(state->repphase3time)); - ae_trace("> time by step (dual phases 1 and 2):\n"); - ae_trace("Pricing = %12d ms\n", - (int)(state->repdualpricingtime)); - ae_trace("BTran = %12d ms\n", - (int)(state->repdualbtrantime)); - ae_trace("PivotRow = %12d ms\n", - (int)(state->repdualpivotrowtime)); - ae_trace("RatioTest = %12d ms\n", - (int)(state->repdualratiotesttime)); - ae_trace("FTran = %12d ms\n", - (int)(state->repdualftrantime)); - ae_trace("Update = %12d ms\n", - (int)(state->repdualupdatesteptime)); - } -} - - -/************************************************************************* -This function initializes subproblem structure. Previously allocated memory -is reused as much as possible. - -Default state of the problem is zero cost vector, all variables are fixed -at zero, linear constraint matrix is zero. - - -- ALGLIB -- - Copyright 01.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_subprobleminit(ae_int_t n, - dualsimplexsubproblem* s, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(n>0, "SubproblemInit: N<=0", _state); - s->ns = n; - s->m = 0; - s->state = reviseddualsimplex_ssinvalid; - rvectorsetlengthatleast(&s->xa, n, _state); - rvectorsetlengthatleast(&s->xb, 0, _state); - rvectorsetlengthatleast(&s->d, n, _state); - rvectorsetlengthatleast(&s->rawc, n, _state); - rvectorsetlengthatleast(&s->effc, n, _state); - rvectorsetlengthatleast(&s->bndl, n, _state); - rvectorsetlengthatleast(&s->bndu, n, _state); - ivectorsetlengthatleast(&s->bndt, n, _state); - for(i=0; i<=n-1; i++) - { - s->rawc.ptr.p_double[i] = (double)(0); - s->effc.ptr.p_double[i] = (double)(0); - s->bndl.ptr.p_double[i] = (double)(0); - s->bndu.ptr.p_double[i] = (double)(0); - s->bndt.ptr.p_int[i] = reviseddualsimplex_ccfixed; - s->xa.ptr.p_double[i] = 0.0; - s->d.ptr.p_double[i] = 0.0; - } -} - - -/************************************************************************* -This function initializes phase #1 subproblem which minimizes sum of dual -infeasibilities. It is required that total count of non-boxed non-fixed -variables is at least M. - -It splits out basic components of XA[] to XB[] - - -- ALGLIB -- - Copyright 01.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_subprobleminitphase1(dualsimplexsubproblem* s0, - dualsimplexbasis* basis, - dualsimplexsubproblem* s1, - ae_state *_state) -{ - ae_int_t i; - - - s1->ns = s0->ns; - s1->m = s0->m; - copyrealarray(&s0->rawc, &s1->rawc, _state); - copyrealarray(&s0->effc, &s1->effc, _state); - copyrealarray(&s0->bndl, &s1->bndl, _state); - copyrealarray(&s0->bndu, &s1->bndu, _state); - copyintegerarray(&s0->bndt, &s1->bndt, _state); - copyrealarray(&s0->xa, &s1->xa, _state); - copyrealarray(&s0->xb, &s1->xb, _state); - copyrealarray(&s0->bndlb, &s1->bndlb, _state); - copyrealarray(&s0->bndub, &s1->bndub, _state); - copyintegerarray(&s0->bndtb, &s1->bndtb, _state); - copyrealarray(&s0->bndtollb, &s1->bndtollb, _state); - copyrealarray(&s0->bndtolub, &s1->bndtolub, _state); - copyrealarray(&s0->d, &s1->d, _state); - for(i=0; i<=s1->ns+s1->m-1; i++) - { - if( s1->bndt.ptr.p_int[i]==reviseddualsimplex_cclower ) - { - s1->bndt.ptr.p_int[i] = reviseddualsimplex_ccrange; - s1->bndl.ptr.p_double[i] = (double)(0); - s1->bndu.ptr.p_double[i] = (double)(1); - s1->xa.ptr.p_double[i] = (double)(0); - continue; - } - if( s1->bndt.ptr.p_int[i]==reviseddualsimplex_ccupper ) - { - s1->bndt.ptr.p_int[i] = reviseddualsimplex_ccrange; - s1->bndl.ptr.p_double[i] = (double)(-1); - s1->bndu.ptr.p_double[i] = (double)(0); - s1->xa.ptr.p_double[i] = (double)(0); - continue; - } - if( s1->bndt.ptr.p_int[i]==reviseddualsimplex_ccfree ) - { - s1->bndt.ptr.p_int[i] = reviseddualsimplex_ccrange; - s1->bndl.ptr.p_double[i] = (double)(-1); - s1->bndu.ptr.p_double[i] = (double)(1); - if( ae_fp_greater_eq(s1->effc.ptr.p_double[i],(double)(0)) ) - { - s1->xa.ptr.p_double[i] = (double)(-1); - } - else - { - s1->xa.ptr.p_double[i] = (double)(1); - } - continue; - } - s1->bndt.ptr.p_int[i] = reviseddualsimplex_ccfixed; - s1->bndl.ptr.p_double[i] = (double)(0); - s1->bndu.ptr.p_double[i] = (double)(0); - s1->xa.ptr.p_double[i] = (double)(0); - } - s1->state = reviseddualsimplex_ssvalidxn; -} - - -/************************************************************************* -This function initializes phase #3 subproblem which applies primal simplex -method to the result of the phase #2. - -It also performs modification of the subproblem in order to ensure that -initial point is primal feasible. - -NOTE: this function expects that all components (basic and nonbasic ones) - are stored in XA[] - - -- ALGLIB -- - Copyright 01.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_subprobleminitphase3(dualsimplexsubproblem* s0, - dualsimplexsubproblem* s1, - ae_state *_state) -{ - - - s1->ns = s0->ns; - s1->m = s0->m; - copyrealarray(&s0->rawc, &s1->rawc, _state); - copyrealarray(&s0->effc, &s1->effc, _state); - copyrealarray(&s0->bndl, &s1->bndl, _state); - copyrealarray(&s0->bndu, &s1->bndu, _state); - copyintegerarray(&s0->bndt, &s1->bndt, _state); - copyrealarray(&s0->xa, &s1->xa, _state); - copyrealarray(&s0->xb, &s1->xb, _state); - copyrealarray(&s0->bndlb, &s1->bndlb, _state); - copyrealarray(&s0->bndub, &s1->bndub, _state); - copyintegerarray(&s0->bndtb, &s1->bndtb, _state); - copyrealarray(&s0->bndtollb, &s1->bndtollb, _state); - copyrealarray(&s0->bndtolub, &s1->bndtolub, _state); - copyrealarray(&s0->d, &s1->d, _state); - s1->state = reviseddualsimplex_ssvalidxn; -} - - -/************************************************************************* -This function infers nonbasic variables of X using sign of effective C[]. - -Only non-basic components of XN are changed; everything else is NOT updated. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_subprobleminferinitialxn(dualsimplexstate* state, - dualsimplexsubproblem* s, - ae_state *_state) -{ - ae_int_t i; - ae_int_t ii; - ae_int_t bndt; - - - for(ii=0; ii<=s->ns-1; ii++) - { - i = state->basis.nidx.ptr.p_int[ii]; - bndt = s->bndt.ptr.p_int[i]; - if( bndt==reviseddualsimplex_ccfixed||bndt==reviseddualsimplex_ccrange ) - { - if( s->effc.ptr.p_double[i]>=0 ) - { - s->xa.ptr.p_double[i] = s->bndl.ptr.p_double[i]; - } - else - { - s->xa.ptr.p_double[i] = s->bndu.ptr.p_double[i]; - } - continue; - } - if( bndt==reviseddualsimplex_cclower ) - { - s->xa.ptr.p_double[i] = s->bndl.ptr.p_double[i]; - continue; - } - if( bndt==reviseddualsimplex_ccupper ) - { - s->xa.ptr.p_double[i] = s->bndu.ptr.p_double[i]; - continue; - } - if( bndt==reviseddualsimplex_ccfree ) - { - s->xa.ptr.p_double[i] = 0.0; - continue; - } - ae_assert(ae_false, "SubproblemInferInitialXN: integrity check failed (infeasible constraint)", _state); - } - s->state = reviseddualsimplex_ssvalidxn; -} - - -/************************************************************************* -This function infers basic variables of X using values of non-basic vars -and updates reduced cost vector D and target function Z. Sets state age -to zero. - -D[] is allocated during computations. - -Temporary vectors Tmp0 and Tmp1 are used (reallocated as needed). - -NOTE: this function expects that both nonbasic and basic components are - stored in XA[]. XB[] array is not referenced. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_subproblemhandlexnupdate(dualsimplexstate* state, - dualsimplexsubproblem* s, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t m; - ae_int_t nn; - - - ae_assert(s->state>=reviseddualsimplex_ssvalidxn, "SubproblemHandleXNUpdate: integrity check failed (XN is not valid)", _state); - nn = s->ns; - m = s->m; - - /* - * Compute nonbasic components - */ - reviseddualsimplex_computeanxn(state, s, &s->xa, &state->tmp0, _state); - reviseddualsimplex_basissolve(&state->basis, &state->tmp0, &state->tmp1, &state->tmp2, _state); - for(i=0; i<=m-1; i++) - { - s->xa.ptr.p_double[state->basis.idx.ptr.p_int[i]] = -state->tmp1.ptr.p_double[i]; - } - - /* - * Compute D - */ - for(i=0; i<=m-1; i++) - { - state->tmp0.ptr.p_double[i] = s->effc.ptr.p_double[state->basis.idx.ptr.p_int[i]]; - } - reviseddualsimplex_basissolvet(&state->basis, &state->tmp0, &state->tmp1, &state->tmp2, _state); - reviseddualsimplex_computeantv(state, &state->tmp1, &s->d, _state); - for(i=0; i<=nn-1; i++) - { - j = state->basis.nidx.ptr.p_int[i]; - s->d.ptr.p_double[j] = s->effc.ptr.p_double[j]-s->d.ptr.p_double[j]; - } - - /* - * Update state validity/age - */ - s->state = reviseddualsimplex_ssvalid; -} - - -/************************************************************************* -This function performs initial dual feasibility correction on the subproblem. -It assumes that problem state is at least ssValidXN. After call to this -function the problem state is set to ssValid. - -This function returns dual feasibility error after dual feasibility correction. - -NOTE: this function expects that both nonbasic and basic components are - stored in XA[]. XB[] array is not referenced. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static double reviseddualsimplex_initialdualfeasibilitycorrection(dualsimplexstate* state, - dualsimplexsubproblem* s, - dualsimplexsettings* settings, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector dummy; - ae_int_t nn; - ae_int_t m; - ae_int_t ii; - ae_int_t i; - ae_int_t j; - ae_bool flipped; - double v; - double dj; - double xj; - ae_int_t bndt; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&dummy, 0, sizeof(dummy)); - ae_vector_init(&dummy, 0, DT_REAL, _state, ae_true); - - nn = s->ns; - m = s->m; - ae_assert(s->state>=reviseddualsimplex_ssvalidxn, "InitialDualFeasibilityCorrection: XN is invalid", _state); - - /* - * Prepare - */ - rvectorsetlengthatleast(&state->dfctmp0, m, _state); - rvectorsetlengthatleast(&state->dfctmp1, m, _state); - - /* - * Recompute D[] using fresh factorization - */ - reviseddualsimplex_basisfreshtrf(&state->basis, &state->at, settings, _state); - for(i=0; i<=m-1; i++) - { - state->dfctmp0.ptr.p_double[i] = s->effc.ptr.p_double[state->basis.idx.ptr.p_int[i]]; - } - reviseddualsimplex_basissolvet(&state->basis, &state->dfctmp0, &state->dfctmp1, &state->dfctmp2, _state); - reviseddualsimplex_computeantv(state, &state->dfctmp1, &s->d, _state); - for(i=0; i<=nn-1; i++) - { - j = state->basis.nidx.ptr.p_int[i]; - s->d.ptr.p_double[j] = s->effc.ptr.p_double[j]-s->d.ptr.p_double[j]; - } - - /* - * Perform flips for dual-infeasible boxed variables - */ - result = (double)(0); - flipped = ae_false; - for(ii=0; ii<=nn-1; ii++) - { - j = state->basis.nidx.ptr.p_int[ii]; - bndt = s->bndt.ptr.p_int[j]; - - /* - * Boxed variables, perform DFC - */ - if( bndt==reviseddualsimplex_ccrange ) - { - dj = s->d.ptr.p_double[j]; - xj = s->xa.ptr.p_double[j]; - if( xj==s->bndl.ptr.p_double[j]&&dj<0 ) - { - s->xa.ptr.p_double[j] = s->bndu.ptr.p_double[j]; - flipped = ae_true; - continue; - } - if( xj==s->bndu.ptr.p_double[j]&&dj>0 ) - { - s->xa.ptr.p_double[j] = s->bndl.ptr.p_double[j]; - flipped = ae_true; - continue; - } - continue; - } - - /* - * Non-boxed variables, compute dual feasibility error - */ - if( bndt==reviseddualsimplex_ccfixed ) - { - continue; - } - if( bndt==reviseddualsimplex_cclower ) - { - v = -s->d.ptr.p_double[j]; - if( v>result ) - { - result = v; - } - continue; - } - if( bndt==reviseddualsimplex_ccupper ) - { - v = s->d.ptr.p_double[j]; - if( v>result ) - { - result = v; - } - continue; - } - if( bndt==reviseddualsimplex_ccfree ) - { - result = ae_maxreal(result, ae_fabs(s->d.ptr.p_double[j], _state), _state); - continue; - } - } - - /* - * Recompute basic components of X[] - */ - if( flipped||s->statexa, &state->dfctmp0, _state); - reviseddualsimplex_basissolve(&state->basis, &state->dfctmp0, &state->dfctmp1, &state->dfctmp2, _state); - for(i=0; i<=m-1; i++) - { - s->xa.ptr.p_double[state->basis.idx.ptr.p_int[i]] = -state->dfctmp1.ptr.p_double[i]; - } - } - - /* - * Update state validity/age - */ - s->state = reviseddualsimplex_ssvalid; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function performs shifting using current algorithm as specified by -settings.shifting. - -It accepts following parameters: -* AlphaR - pivot row -* Delta - delta from pricing step -* Q - variable selected by ratio test -* AlphaRPiv - pivot element, Q-th element of AlphaR (because alphaR is - stored in compressed format, we can't extract it easily) -* ThetaD - dual step length - -If no shifts are necessary, it silently returns. If shifts are necessary, -it modifies ThetaD, S.D, S.EffC according to shifting algorithm. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_shifting(dualsimplexstate* state, - dualsimplexsubproblem* s, - dssvector* alphar, - double delta, - ae_int_t q, - double alpharpiv, - double* thetad, - dualsimplexsettings* settings, - ae_state *_state) -{ - ae_int_t dir; - double sft; - ae_int_t ii; - ae_int_t j; - ae_int_t bndt; - - - - /* - * No shifts - */ - if( settings->shifting==0 ) - { - return; - } - if( q<0 ) - { - return; - } - - /* - * EXPAND with ThetaD=0 - */ - if( settings->shifting==1 ) - { - dir = ae_sign(delta, _state); - if( ae_fp_greater_eq(*thetad*dir,(double)(0)) ) - { - return; - } - s->effc.ptr.p_double[q] = s->effc.ptr.p_double[q]-s->d.ptr.p_double[q]; - s->d.ptr.p_double[q] = (double)(0); - *thetad = (double)(0); - return; - } - - /* - * EXPAND with ThetaD=ShiftLen - */ - if( settings->shifting==2 ) - { - dir = ae_sign(delta, _state); - if( ae_fp_greater(*thetad*dir,(double)(0)) ) - { - return; - } - - /* - * Ensure that non-zero step is performed - */ - *thetad = dir*reviseddualsimplex_shiftlen; - - /* - * Shift Q-th coefficient - */ - sft = *thetad*(dir*alpharpiv)-s->d.ptr.p_double[q]; - s->effc.ptr.p_double[q] = s->effc.ptr.p_double[q]+sft; - s->d.ptr.p_double[q] = s->d.ptr.p_double[q]+sft; - - /* - * Shift other coefficients - */ - for(ii=0; ii<=alphar->k-1; ii++) - { - j = alphar->idx.ptr.p_int[ii]; - bndt = s->bndt.ptr.p_int[j]; - if( (j==q||bndt==reviseddualsimplex_ccfixed)||bndt==reviseddualsimplex_ccfree ) - { - continue; - } - sft = *thetad*(dir*alphar->vals.ptr.p_double[ii])-s->d.ptr.p_double[j]; - - /* - * Handle variables at lower bound - */ - if( bndt==reviseddualsimplex_cclower||(bndt==reviseddualsimplex_ccrange&&s->xa.ptr.p_double[j]==s->bndl.ptr.p_double[j]) ) - { - sft = sft-settings->dtolabs; - if( sft>0 ) - { - s->effc.ptr.p_double[j] = s->effc.ptr.p_double[j]+sft; - s->d.ptr.p_double[j] = s->d.ptr.p_double[j]+sft; - } - continue; - } - if( bndt==reviseddualsimplex_ccupper||(bndt==reviseddualsimplex_ccrange&&s->xa.ptr.p_double[j]==s->bndu.ptr.p_double[j]) ) - { - sft = sft+settings->dtolabs; - if( sft<0 ) - { - s->effc.ptr.p_double[j] = s->effc.ptr.p_double[j]+sft; - s->d.ptr.p_double[j] = s->d.ptr.p_double[j]+sft; - } - continue; - } - } - - /* - * Done - */ - return; - } - ae_assert(ae_false, "Shifting: unexpected shifting type", _state); -} - - -/************************************************************************* -This function performs pricing step - -Additional parameters: -* Phase1Pricing - if True, then special Phase #1 restriction is applied to - leaving variables: only those are eligible which will move to zero bound - after basis change. - - This trick allows to accelerate and stabilize phase #1. See Robert Fourer, - 'Notes on the dual simplex method', draft report, 1994, for more info. - -Returns: -* leaving variable index P -* its index R in the basis, in [0,M) range -* Delta - difference between variable value and corresponding bound - -NOTE: this function expects that basic components are stored in XB[]; - corresponding entries of XA[] are ignored. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_pricingstep(dualsimplexstate* state, - dualsimplexsubproblem* s, - ae_bool phase1pricing, - ae_int_t* p, - ae_int_t* r, - double* delta, - dualsimplexsettings* settings, - ae_state *_state) -{ - ae_int_t m; - ae_int_t i; - ae_int_t bi; - double v; - double vtarget; - double xbi; - double bndl; - double bndu; - double vdiff; - double vtest; - double invw; - ae_int_t bndt; - ae_bool hasboth; - ae_bool hasl; - ae_bool hasu; - ae_int_t t0; - - *p = 0; - *r = 0; - *delta = 0; - - m = s->m; - - /* - * Integrity checks - */ - ae_assert(s->state==reviseddualsimplex_ssvalid, "PricingStep: invalid X", _state); - ae_assert(m>0, "PricingStep: M<=0", _state); - - /* - * Timers - */ - t0 = 0; - if( state->dotimers ) - { - t0 = ae_tickcount(); - } - - /* - * Pricing - */ - if( settings->pricing==0 ) - { - - /* - * "Most infeasible" pricing - */ - *p = -1; - *r = -1; - *delta = (double)(0); - vtarget = (double)(0); - for(i=0; i<=m-1; i++) - { - bndt = s->bndtb.ptr.p_int[i]; - hasboth = bndt==3||bndt==0; - hasl = hasboth||bndt==1; - hasu = hasboth||bndt==2; - xbi = s->xb.ptr.p_double[i]; - if( hasl ) - { - bndl = s->bndlb.ptr.p_double[i]; - vdiff = xbi-bndl; - v = -vdiff; - if( v>s->bndtollb.ptr.p_double[i]&&v>vtarget ) - { - - /* - * Special phase 1 pricing: do not choose variables which move to non-zero bound - */ - if( phase1pricing&&!(bndl==0.0) ) - { - continue; - } - - /* - * Proceed as usual - */ - *p = state->basis.idx.ptr.p_int[i]; - *r = i; - *delta = vdiff; - vtarget = v; - continue; - } - } - if( hasu ) - { - bndu = s->bndub.ptr.p_double[i]; - vdiff = xbi-bndu; - v = vdiff; - if( v>s->bndtolub.ptr.p_double[i]&&v>vtarget ) - { - - /* - * Special phase 1 pricing: do not choose variables which move to non-zero bound - */ - if( phase1pricing&&!(bndu==0.0) ) - { - continue; - } - - /* - * Proceed as usual - */ - *p = state->basis.idx.ptr.p_int[i]; - *r = i; - *delta = vdiff; - vtarget = v; - continue; - } - } - } - - /* - * Trace/profile - */ - if( state->dotrace ) - { - ae_trace("> pricing: most infeasible variable removed\n"); - ae_trace("P = %12d (R=%0d)\n", - (int)(*p), - (int)(*r)); - ae_trace("Delta = %12.3e\n", - (double)(*delta)); - } - if( state->dotimers ) - { - state->repdualpricingtime = state->repdualpricingtime+(ae_tickcount()-t0); - } - - /* - * Done - */ - return; - } - if( settings->pricing==-1||settings->pricing==1 ) - { - - /* - * Dual steepest edge pricing - */ - reviseddualsimplex_basisrequestweights(&state->basis, settings, _state); - *p = -1; - *r = -1; - *delta = (double)(0); - vtarget = (double)(0); - for(i=0; i<=m-1; i++) - { - bi = state->basis.idx.ptr.p_int[i]; - bndt = s->bndtb.ptr.p_int[i]; - hasboth = bndt==3||bndt==0; - hasl = hasboth||bndt==1; - hasu = hasboth||bndt==2; - xbi = s->xb.ptr.p_double[i]; - invw = 1/state->basis.dseweights.ptr.p_double[i]; - if( hasl ) - { - bndl = s->bndlb.ptr.p_double[i]; - vdiff = xbi-bndl; - vtest = vdiff*vdiff*invw; - if( vdiff<-s->bndtollb.ptr.p_double[i]&&(*p<0||vtest>vtarget) ) - { - - /* - * Special phase 1 pricing: do not choose variables which move to non-zero bound - */ - if( phase1pricing&&!(bndl==0.0) ) - { - continue; - } - - /* - * Proceed as usual - */ - *p = bi; - *r = i; - *delta = vdiff; - vtarget = vtest; - continue; - } - } - if( hasu ) - { - bndu = s->bndub.ptr.p_double[i]; - vdiff = xbi-bndu; - vtest = vdiff*vdiff*invw; - if( vdiff>s->bndtolub.ptr.p_double[i]&&(*p<0||vtest>vtarget) ) - { - - /* - * Special phase 1 pricing: do not choose variables which move to non-zero bound - */ - if( phase1pricing&&!(bndu==0.0) ) - { - continue; - } - - /* - * Proceed as usual - */ - *p = bi; - *r = i; - *delta = vdiff; - vtarget = vtest; - continue; - } - } - } - - /* - * Trace/profile - */ - if( state->dotrace ) - { - ae_trace("> dual steepest edge pricing: leaving variable found\n"); - ae_trace("P = %12d (variable index)\n", - (int)(*p)); - ae_trace("R = %12d (variable index in basis)\n", - (int)(*r)); - ae_trace("Delta = %12.3e (primal infeasibility removed)\n", - (double)(*delta)); - } - if( state->dotimers ) - { - state->repdualpricingtime = state->repdualpricingtime+(ae_tickcount()-t0); - } - - /* - * Done - */ - return; - } - ae_assert(ae_false, "PricingStep: unknown pricing type", _state); -} - - -/************************************************************************* -This function performs BTran step - -Accepts: -* R, index of the leaving variable in the basis, in [0,M) range - -Returns: -* RhoR, array[M], BTran result - - -- ALGLIB -- - Copyright 19.07.2020 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_btranstep(dualsimplexstate* state, - dualsimplexsubproblem* s, - ae_int_t r, - dssvector* rhor, - dualsimplexsettings* settings, - ae_state *_state) -{ - ae_int_t m; - ae_int_t i; - ae_int_t t0; - - - m = s->m; - - /* - * Integrity checks - */ - ae_assert(m>0, "BTranStep: M<=0", _state); - - /* - * Timers - */ - t0 = 0; - if( state->dotimers ) - { - t0 = ae_tickcount(); - } - - /* - * BTran - */ - rvectorsetlengthatleast(&state->btrantmp0, m, _state); - rvectorsetlengthatleast(&state->btrantmp1, m, _state); - rvectorsetlengthatleast(&state->btrantmp2, m, _state); - for(i=0; i<=m-1; i++) - { - state->btrantmp0.ptr.p_double[i] = (double)(0); - } - state->btrantmp0.ptr.p_double[r] = (double)(1); - reviseddualsimplex_dvalloc(rhor, m, _state); - reviseddualsimplex_basissolvet(&state->basis, &state->btrantmp0, &rhor->dense, &state->btrantmp1, _state); - reviseddualsimplex_dvdensetosparse(rhor, _state); - - /* - * Timers - */ - if( state->dotimers ) - { - state->repdualbtrantime = state->repdualbtrantime+(ae_tickcount()-t0); - } -} - - -/************************************************************************* -This function performs PivotRow step - -Accepts: -* RhoR, BTRan result - -Returns: -* AlphaR, array[N+M], pivot row - - -- ALGLIB -- - Copyright 19.07.2020 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_pivotrowstep(dualsimplexstate* state, - dualsimplexsubproblem* s, - dssvector* rhor, - dssvector* alphar, - dualsimplexsettings* settings, - ae_state *_state) -{ - ae_int_t m; - ae_int_t ns; - ae_int_t nx; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t jj; - ae_int_t j0; - ae_int_t j1; - ae_int_t alphark; - double v; - ae_int_t t0; - double avgcolwise; - double avgrowwise; - - - m = s->m; - ns = s->ns; - nx = s->ns+s->m; - - /* - * Integrity checks - */ - ae_assert(m>0, "BTranStep: M<=0", _state); - - /* - * Timers - */ - t0 = 0; - if( state->dotimers ) - { - t0 = ae_tickcount(); - } - - /* - * Determine operation counts for columnwise and rowwise approaches - */ - avgrowwise = rhor->k*((double)state->at.ridx.ptr.p_int[nx]/(double)m); - avgcolwise = ns*((double)state->at.ridx.ptr.p_int[nx]/(double)nx); - - /* - * Pivot row - */ - if( ae_fp_less(avgrowwise,avgcolwise) ) - { - - /* - * Use rowwise algorithm - */ - reviseddualsimplex_dvinit(alphar, nx, _state); - for(i=0; i<=rhor->k-1; i++) - { - k = rhor->idx.ptr.p_int[i]; - v = rhor->vals.ptr.p_double[i]; - j0 = state->a.ridx.ptr.p_int[k]; - j1 = state->a.ridx.ptr.p_int[k+1]-1; - for(j=j0; j<=j1; j++) - { - jj = state->a.idx.ptr.p_int[j]; - alphar->dense.ptr.p_double[jj] = alphar->dense.ptr.p_double[jj]+v*state->a.vals.ptr.p_double[j]; - } - } - alphark = 0; - for(i=0; i<=nx-1; i++) - { - if( !state->basis.isbasic.ptr.p_bool[i] ) - { - - /* - * Fetch nonbasic nonzeros to sparse part - */ - v = alphar->dense.ptr.p_double[i]; - if( v!=0.0 ) - { - alphar->idx.ptr.p_int[alphark] = i; - alphar->vals.ptr.p_double[alphark] = v; - alphark = alphark+1; - } - } - else - { - - /* - * Enforce condition that basic elements of AlphaR are exactly zero - */ - alphar->dense.ptr.p_double[i] = (double)(0); - } - } - alphar->k = alphark; - } - else - { - - /* - * Use colwise algorithm - */ - reviseddualsimplex_dvalloc(alphar, nx, _state); - alphark = 0; - for(i=0; i<=ns-1; i++) - { - k = state->basis.nidx.ptr.p_int[i]; - j0 = state->at.ridx.ptr.p_int[k]; - j1 = state->at.ridx.ptr.p_int[k+1]-1; - v = (double)(0); - for(j=j0; j<=j1; j++) - { - v = v+state->at.vals.ptr.p_double[j]*rhor->dense.ptr.p_double[state->at.idx.ptr.p_int[j]]; - } - if( v!=0.0 ) - { - alphar->idx.ptr.p_int[alphark] = k; - alphar->vals.ptr.p_double[alphark] = v; - alphark = alphark+1; - } - } - alphar->k = alphark; - reviseddualsimplex_dvsparsetodense(alphar, _state); - } - - /* - * Timers and tracing - */ - if( state->dodetailedtrace ) - { - reviseddualsimplex_updateavgcounter(rhor->k/coalesce((double)(rhor->n), (double)(1), _state), &state->repfillrhor, &state->repfillrhorcnt, _state); - reviseddualsimplex_updateavgcounter(alphar->k/coalesce((double)(alphar->n), (double)(1), _state), &state->repfillpivotrow, &state->repfillpivotrowcnt, _state); - } - if( state->dotimers ) - { - state->repdualpivotrowtime = state->repdualpivotrowtime+(ae_tickcount()-t0); - } -} - - -/************************************************************************* -This function performs FTran step - -Accepts: -* RhoR, array[M] -* Q, index of the entering variable, in [0,NX) range - -Returns: -* AlphaQ, array[M], FTran result -* AlphaQim, array[M], intermediate FTran result used by Forest-Tomlin update -* Tau, array[M], used to compute DSE temporaries - - -- ALGLIB -- - Copyright 19.07.2020 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_ftranstep(dualsimplexstate* state, - dualsimplexsubproblem* s, - dssvector* rhor, - ae_int_t q, - /* Real */ ae_vector* alphaq, - /* Real */ ae_vector* alphaqim, - /* Real */ ae_vector* tau, - dualsimplexsettings* settings, - ae_state *_state) -{ - ae_int_t m; - ae_int_t i; - ae_int_t j; - ae_int_t j0; - ae_int_t j1; - ae_int_t t0; - - - m = s->m; - - /* - * Integrity checks - */ - ae_assert(m>0, "BTranStep: M<=0", _state); - - /* - * Timers - */ - t0 = 0; - if( state->dotimers ) - { - t0 = ae_tickcount(); - } - - /* - * FTran - */ - rvectorsetlengthatleast(&state->ftrantmp0, m, _state); - for(i=0; i<=m-1; i++) - { - state->ftrantmp0.ptr.p_double[i] = (double)(0); - } - j0 = state->at.ridx.ptr.p_int[q]; - j1 = state->at.ridx.ptr.p_int[q+1]-1; - for(j=j0; j<=j1; j++) - { - state->ftrantmp0.ptr.p_double[state->at.idx.ptr.p_int[j]] = state->at.vals.ptr.p_double[j]; - } - reviseddualsimplex_basissolvex(&state->basis, &state->ftrantmp0, alphaq, alphaqim, ae_true, &state->ftrantmp1, _state); - ae_assert((settings->pricing==-1||settings->pricing==0)||settings->pricing==1, "FTran: unexpected Settings.Pricing", _state); - if( settings->pricing==1 ) - { - reviseddualsimplex_basissolve(&state->basis, &rhor->dense, tau, &state->ftrantmp1, _state); - } - - /* - * Timers - */ - if( state->dotimers ) - { - state->repdualftrantime = state->repdualftrantime+(ae_tickcount()-t0); - } -} - - -/************************************************************************* -This function performs ratio test, either simple one or BFRT. - -It accepts following parameters: -* AlphaR - pivot row -* Delta - delta from pricing step -* P - index of leaving variable from pricing step - -It returns following results: -* Q - non-negative value for success, negative for primal infeasible problem -* AlphaRPiv - AlphaR[Q] (due to AlphaR being stored in sparse format this - value is difficult to extract by index Q). -* ThetaD - dual step length -* PossibleFlips[PossibleFlipsCnt] - for possible flip indexes (for BFRT - this set coincides with actual flips, but stabilizing BFRT is a bit more - complex - some variables in PossibleFlips[] may need flipping and some not) - -Internally it uses following fields of State for temporaries: -* EligibleAlphaR - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_ratiotest(dualsimplexstate* state, - dualsimplexsubproblem* s, - dssvector* alphar, - double delta, - ae_int_t p, - ae_int_t* q, - double* alpharpiv, - double* thetad, - /* Integer */ ae_vector* possibleflips, - ae_int_t* possibleflipscnt, - dualsimplexsettings* settings, - ae_state *_state) -{ - ae_int_t nx; - ae_int_t j; - ae_int_t nj; - ae_int_t dir; - double vx; - double vp; - ae_int_t ej; - double alpharej; - double vtarget; - double vtest; - ae_int_t eligiblecnt; - ae_int_t originaleligiblecnt; - ae_int_t bndt; - double alphawaver; - double adelta; - ae_int_t idx; - double vtheta; - ae_int_t t0; - - *q = 0; - *alpharpiv = 0; - *thetad = 0; - - nx = s->ns+s->m; - ae_assert(ae_fp_neq(delta,(double)(0)), "RatioTest: zero delta", _state); - ae_assert(s->state==reviseddualsimplex_ssvalid, "RatioTest: invalid X", _state); - - /* - * Timers - */ - t0 = 0; - if( state->dotimers ) - { - t0 = ae_tickcount(); - } - - /* - * Clear output - */ - *q = -1; - *alpharpiv = (double)(0); - *thetad = (double)(0); - *possibleflipscnt = 0; - - /* - * Prepare temporaries - * - * Scaled tolerances are used to test AlphaWaveR for positivity/negativity, - * scale of I-th tolerance is calculated as ratio of ColScale[I] and ColScale[P]. - */ - dir = ae_sign(delta, _state); - ivectorsetlengthatleast(possibleflips, nx, _state); - - /* - * Prepare set of eligible variables - * - * NOTE: free variables are immediately chosen at this stage - */ - ivectorsetlengthatleast(&state->eligiblealphar, alphar->k, _state); - eligiblecnt = 0; - for(j=0; j<=alphar->k-1; j++) - { - nj = alphar->idx.ptr.p_int[j]; - bndt = s->bndt.ptr.p_int[nj]; - - /* - * Handle fixed and free variables: fixed ones are not eligible, - * free non-basic variables are always and immediately eligible - */ - if( bndt==reviseddualsimplex_ccfixed ) - { - continue; - } - if( bndt==reviseddualsimplex_ccfree ) - { - *q = nj; - *thetad = (double)(0); - *alpharpiv = alphar->vals.ptr.p_double[j]; - if( state->dotrace ) - { - ae_trace("> ratio test: quick exit, found free nonbasic variable\n"); - ae_trace("Q = %12d (variable selected)\n", - (int)(*q)); - ae_trace("ThetaD = %12.3e (dual step length)\n", - (double)(*thetad)); - } - if( state->dotimers ) - { - state->repdualratiotesttime = state->repdualratiotesttime+(ae_tickcount()-t0); - } - return; - } - - /* - * Handle lower/upper/range constraints - */ - vx = s->xa.ptr.p_double[nj]; - vp = settings->pivottol; - alphawaver = dir*alphar->vals.ptr.p_double[j]; - if( bndt==reviseddualsimplex_cclower||(bndt==reviseddualsimplex_ccrange&&vx==s->bndl.ptr.p_double[nj]) ) - { - if( alphawaver>vp ) - { - state->eligiblealphar.ptr.p_int[eligiblecnt] = j; - eligiblecnt = eligiblecnt+1; - continue; - } - } - if( bndt==reviseddualsimplex_ccupper||(bndt==reviseddualsimplex_ccrange&&vx==s->bndu.ptr.p_double[nj]) ) - { - if( alphawaver<-vp ) - { - state->eligiblealphar.ptr.p_int[eligiblecnt] = j; - eligiblecnt = eligiblecnt+1; - continue; - } - } - } - originaleligiblecnt = eligiblecnt; - - /* - * Simple ratio test. - */ - if( settings->ratiotest==0 ) - { - - /* - * Ratio test - */ - vtarget = (double)(0); - for(j=0; j<=eligiblecnt-1; j++) - { - ej = state->eligiblealphar.ptr.p_int[j]; - nj = alphar->idx.ptr.p_int[ej]; - alpharej = alphar->vals.ptr.p_double[ej]; - - /* - * More general case - */ - alphawaver = dir*alpharej; - vtest = s->d.ptr.p_double[nj]/alphawaver; - if( *q<0||vtestd.ptr.p_double[nj]/alpharej; - } - } - reviseddualsimplex_shifting(state, s, alphar, delta, *q, *alpharpiv, thetad, settings, _state); - - /* - * Trace - */ - if( state->dotrace ) - { - ae_trace("> dual ratio test:\n"); - ae_trace("|E| = %12d (eligible set size)\n", - (int)(originaleligiblecnt)); - ae_trace("Q = %12d (variable selected)\n", - (int)(*q)); - ae_trace("ThetaD = %12.3e (dual step length)\n", - (double)(*thetad)); - } - if( state->dotimers ) - { - state->repdualratiotesttime = state->repdualratiotesttime+(ae_tickcount()-t0); - } - - /* - * Done - */ - return; - } - - /* - * Bounds flipping ratio test - */ - if( settings->ratiotest==1 ) - { - adelta = ae_fabs(delta, _state); - - /* - * Quick exit - */ - if( eligiblecnt==0 ) - { - if( state->dotrace ) - { - ae_trace("> ratio test: quick exit, no eligible variables\n"); - } - return; - } - - /* - * BFRT - */ - while(eligiblecnt>0) - { - - /* - * Find Q satisfying BFRT criteria - */ - idx = -1; - *q = -1; - *alpharpiv = (double)(0); - vtarget = (double)(0); - for(j=0; j<=eligiblecnt-1; j++) - { - ej = state->eligiblealphar.ptr.p_int[j]; - nj = alphar->idx.ptr.p_int[ej]; - alpharej = alphar->vals.ptr.p_double[ej]; - vtheta = s->d.ptr.p_double[nj]/alpharej; - vtest = dir*vtheta; - if( *q<0||vtest=0, "RatioTest: integrity check failed (BFRT)", _state); - - /* - * BFRT mini-iterations will be terminated upon discovery - * of non-boxed variable or upon exhausting of eligible set. - */ - if( s->bndt.ptr.p_int[*q]!=reviseddualsimplex_ccrange ) - { - break; - } - if( eligiblecnt==1 ) - { - break; - } - - /* - * Update and test ADelta. Break BFRT mini-iterations once - * we get negative slope. - */ - adelta = adelta-(s->bndu.ptr.p_double[*q]-s->bndl.ptr.p_double[*q])*ae_fabs(*alpharpiv, _state); - if( ae_fp_less_eq(adelta,(double)(0)) ) - { - break; - } - - /* - * Update eligible set, record flip - */ - possibleflips->ptr.p_int[*possibleflipscnt] = state->eligiblealphar.ptr.p_int[idx]; - *possibleflipscnt = *possibleflipscnt+1; - state->eligiblealphar.ptr.p_int[idx] = state->eligiblealphar.ptr.p_int[eligiblecnt-1]; - eligiblecnt = eligiblecnt-1; - } - ae_assert(*q>=0, "RatioTest: unexpected failure", _state); - *thetad = s->d.ptr.p_double[*q]/(*alpharpiv); - reviseddualsimplex_shifting(state, s, alphar, delta, *q, *alpharpiv, thetad, settings, _state); - - /* - * Trace - */ - if( state->dotrace ) - { - ae_trace("> dual bounds flipping ratio test:\n"); - ae_trace("|E| = %12d (eligible set size)\n", - (int)(originaleligiblecnt)); - ae_trace("Q = %12d (variable selected)\n", - (int)(*q)); - ae_trace("ThetaD = %12.3e (dual step length)\n", - (double)(*thetad)); - ae_trace("Flips = %12d (possible bound flips)\n", - (int)(state->possibleflipscnt)); - } - if( state->dotimers ) - { - state->repdualratiotesttime = state->repdualratiotesttime+(ae_tickcount()-t0); - } - - /* - * Done - */ - return; - } - - /* - * Unknown test type - */ - ae_assert(ae_false, "RatioTest: integrity check failed, unknown test type", _state); -} - - -/************************************************************************* -This function performs update of XB, XN, D and Z during final step of revised -dual simplex method. - -It also updates basis cache of the subproblem (s.bcache field). - -Depending on Settings.RatioTest, following operations are performed: -* Settings.RatioTest=0 -> simple update is performed -* Settings.RatioTest=1 -> bounds flipping ratio test update is performed -* Settings.RatioTest=2 -> stabilizing bounds flipping ratio test update is performed - -It accepts following parameters: -* P - index of leaving variable from pricing step -* Q - index of entering variable. -* R - index of leaving variable in AlphaQ -* Delta - delta from pricing step -* AlphaPiv - pivot element (in absence of numerical rounding it is AlphaR[Q]=AlphaQ[R]) -* ThetaP - primal step length -* ThetaD - dual step length -* AlphaQ - pivot column -* AlphaQim - intermediate result from Ftran for AlphaQ, used for - Forest-Tomlin update, not referenced when other update scheme is set -* AlphaR - pivot row -* Tau - tau-vector for DSE pricing (ignored if simple pricing is used) -* PossibleAlphaRFlips, PossibleAlphaRFlipsCnt - outputs of the RatioTest() - information about possible variable flips - indexes of AlphaR positions - which are considered for flipping due to BFRT (however, we have to check - residual costs before actually flipping variables - it is possible that some variables - in this set actually do not need flipping) - -It performs following operations: -* basis update -* update of XB/BndTB/BndLB/BndUB[] and XA[] (basic and nonbasic components), D -* update of pricing weights - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_updatestep(dualsimplexstate* state, - dualsimplexsubproblem* s, - ae_int_t p, - ae_int_t q, - ae_int_t r, - double delta, - double alphapiv, - double thetap, - double thetad, - /* Real */ ae_vector* alphaq, - /* Real */ ae_vector* alphaqim, - dssvector* alphar, - /* Real */ ae_vector* tau, - /* Integer */ ae_vector* possiblealpharflips, - ae_int_t possiblealpharflipscnt, - dualsimplexsettings* settings, - ae_state *_state) -{ - ae_int_t nx; - ae_int_t m; - ae_int_t ii; - ae_int_t j; - ae_int_t k; - ae_int_t aj; - ae_int_t k0; - ae_int_t k1; - double bndl; - double bndu; - ae_bool flipped; - double flip; - double dj; - ae_int_t dir; - ae_int_t idx; - ae_int_t actualflipscnt; - ae_int_t t0; - ae_int_t alpharlen; - - - nx = s->ns+s->m; - m = s->m; - - /* - * Integrity checks - */ - ae_assert((settings->ratiotest==0||settings->ratiotest==1)||settings->ratiotest==2, "UpdateStep: invalid X", _state); - ae_assert(s->state==reviseddualsimplex_ssvalid, "UpdateStep: invalid X", _state); - ae_assert(p>=0&&q>=0, "UpdateStep: invalid P/Q", _state); - ae_assert(ae_fp_neq(delta,(double)(0)), "UpdateStep: Delta=0", _state); - ae_assert(ae_fp_neq(alphapiv,(double)(0)), "UpdateStep: AlphaPiv=0", _state); - - /* - * Timers - */ - t0 = 0; - if( state->dotimers ) - { - t0 = ae_tickcount(); - } - - /* - * Prepare - */ - dir = ae_sign(delta, _state); - alpharlen = alphar->k; - flip = (double)(0); - rvectorsetlengthatleast(&state->tmp0, m, _state); - for(k=0; k<=m-1; k++) - { - state->tmp0.ptr.p_double[k] = (double)(0); - } - ivectorsetlengthatleast(&state->ustmpi, nx, _state); - actualflipscnt = 0; - - /* - * Evaluate and update non-basic elements of D - */ - for(ii=0; ii<=alpharlen-1; ii++) - { - j = alphar->idx.ptr.p_int[ii]; - s->d.ptr.p_double[j] = s->d.ptr.p_double[j]-thetad*alphar->vals.ptr.p_double[ii]; - } - for(ii=0; ii<=possiblealpharflipscnt-1; ii++) - { - aj = possiblealpharflips->ptr.p_int[ii]; - j = alphar->idx.ptr.p_int[aj]; - dj = s->d.ptr.p_double[j]; - bndl = s->bndl.ptr.p_double[j]; - bndu = s->bndu.ptr.p_double[j]; - flipped = ae_false; - if( s->xa.ptr.p_double[j]==bndl&&dj<0 ) - { - flip = bndu-bndl; - flipped = ae_true; - } - else - { - if( s->xa.ptr.p_double[j]==bndu&&dj>0 ) - { - flip = bndl-bndu; - flipped = ae_true; - } - } - if( flipped ) - { - delta = delta-dir*(bndu-bndl)*ae_fabs(alphar->vals.ptr.p_double[aj], _state); - state->ustmpi.ptr.p_int[actualflipscnt] = j; - actualflipscnt = actualflipscnt+1; - k0 = state->at.ridx.ptr.p_int[j]; - k1 = state->at.ridx.ptr.p_int[j+1]-1; - for(k=k0; k<=k1; k++) - { - idx = state->at.idx.ptr.p_int[k]; - state->tmp0.ptr.p_double[idx] = state->tmp0.ptr.p_double[idx]+flip*state->at.vals.ptr.p_double[k]; - } - } - } - s->d.ptr.p_double[p] = -thetad; - s->d.ptr.p_double[q] = 0.0; - - /* - * Apply BFRT update (aka long dual step) or simple ratio update - */ - if( actualflipscnt>0 ) - { - thetap = delta/alphapiv; - k0 = state->at.ridx.ptr.p_int[q]; - k1 = state->at.ridx.ptr.p_int[q+1]-1; - for(k=k0; k<=k1; k++) - { - idx = state->at.idx.ptr.p_int[k]; - state->tmp0.ptr.p_double[idx] = state->tmp0.ptr.p_double[idx]+thetap*state->at.vals.ptr.p_double[k]; - } - reviseddualsimplex_basissolve(&state->basis, &state->tmp0, &state->tmp1, &state->tmp2, _state); - for(j=0; j<=m-1; j++) - { - s->xb.ptr.p_double[j] = s->xb.ptr.p_double[j]-state->tmp1.ptr.p_double[j]; - } - for(ii=0; ii<=actualflipscnt-1; ii++) - { - j = state->ustmpi.ptr.p_int[ii]; - if( s->xa.ptr.p_double[j]==s->bndl.ptr.p_double[j] ) - { - s->xa.ptr.p_double[j] = s->bndu.ptr.p_double[j]; - } - else - { - s->xa.ptr.p_double[j] = s->bndl.ptr.p_double[j]; - } - } - s->xb.ptr.p_double[r] = s->xa.ptr.p_double[q]+thetap; - if( dir<0 ) - { - s->xa.ptr.p_double[p] = s->bndl.ptr.p_double[p]; - } - else - { - s->xa.ptr.p_double[p] = s->bndu.ptr.p_double[p]; - } - } - else - { - for(j=0; j<=m-1; j++) - { - s->xb.ptr.p_double[j] = s->xb.ptr.p_double[j]-thetap*alphaq->ptr.p_double[j]; - } - s->xb.ptr.p_double[r] = s->xa.ptr.p_double[q]+thetap; - if( dir<0 ) - { - s->xa.ptr.p_double[p] = s->bndl.ptr.p_double[p]; - } - else - { - s->xa.ptr.p_double[p] = s->bndu.ptr.p_double[p]; - } - } - - /* - * Update basis - */ - reviseddualsimplex_basisupdatetrf(&state->basis, &state->at, p, q, alphaq, alphaqim, r, tau, settings, _state); - - /* - * Update cached variables - */ - reviseddualsimplex_cacheboundinfo(s, r, q, settings, _state); - - /* - * Tracing and timers - */ - if( state->dodetailedtrace ) - { - if( state->basis.trftype==3 ) - { - reviseddualsimplex_updateavgcounter(reviseddualsimplex_sparsityof(&state->basis.densemu, state->basis.trfage*m, _state), &state->repfilldensemu, &state->repfilldensemucnt, _state); - } - } - if( state->dotimers ) - { - state->repdualupdatesteptime = state->repdualupdatesteptime+(ae_tickcount()-t0); - } -} - - -/************************************************************************* -This function performs several checks for accumulation of errors during -factorization update. It returns True if refactorization is advised. - - -- ALGLIB -- - Copyright 24.01.2019 by Bochkanov Sergey -*************************************************************************/ -static ae_bool reviseddualsimplex_refactorizationrequired(dualsimplexstate* state, - dualsimplexsubproblem* s, - ae_int_t q, - double alpharpiv, - ae_int_t r, - double alphaqpiv, - ae_state *_state) -{ - ae_int_t m; - ae_int_t i; - double mx; - double v; - ae_bool result; - - - m = s->m; - result = ae_false; - - /* - * Quick exit - */ - if( state->basis.trfage<=reviseddualsimplex_safetrfage ) - { - return result; - } - - /* - * Compare Q-th entry of the pivot row AlphaR with R-th entry of the AlphaQ; - * ideally, both should match exactly. The difference is a rough estimate - * of the magnitude of the numerical errors. - */ - mx = 0.0; - for(i=0; i<=m-1; i++) - { - v = state->alphaq.ptr.p_double[i]; - v = v*v; - if( v>mx ) - { - mx = v; - } - } - mx = ae_sqrt(mx, _state); - result = result||ae_fp_greater(ae_fabs(alphaqpiv-alpharpiv, _state),reviseddualsimplex_alphatrigger*(1.0+mx)); - result = result||ae_fp_greater(ae_fabs(alphaqpiv-alpharpiv, _state),reviseddualsimplex_alphatrigger2*ae_fabs(alpharpiv, _state)); - return result; -} - - -/************************************************************************* -This function caches information for I-th column of the basis, which is -assumed to store variable K: -* lower bound in S.BndLB[I]=S.BndL[K] -* upper bound in S.BndUB[I]=S.BndU[K] -* bound type in S.BndTB[I]=S.BndT[K] -* lower bound primal error tolerance in S.BndTolLB[I] (nonnegative) -* upper bound primal error tolerance in S.BndTolLB[I] (nonnegative). - - -- ALGLIB -- - Copyright 18.07.2020 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_cacheboundinfo(dualsimplexsubproblem* s, - ae_int_t i, - ae_int_t k, - dualsimplexsettings* settings, - ae_state *_state) -{ - - - s->bndlb.ptr.p_double[i] = s->bndl.ptr.p_double[k]; - s->bndub.ptr.p_double[i] = s->bndu.ptr.p_double[k]; - s->bndtb.ptr.p_int[i] = s->bndt.ptr.p_int[k]; - s->bndtollb.ptr.p_double[i] = settings->xtolabs+settings->xtolrelabs*settings->xtolabs*ae_fabs(s->bndlb.ptr.p_double[i], _state); - s->bndtolub.ptr.p_double[i] = settings->xtolabs+settings->xtolrelabs*settings->xtolabs*ae_fabs(s->bndub.ptr.p_double[i], _state); -} - - -/************************************************************************* -This function performs actual solution of dual simplex subproblem (either -primary one or phase 1 one). - -A problem with following properties is expected: -* M>0 -* feasible box constraints -* dual feasible initial basis -* actual initial point XC and target value Z -* actual reduced cost vector D -* pricing weights being set to 1.0 or copied from previous problem - -Returns: - * Info = +1 for success, -3 for infeasible - * IterationsCount is increased by amount of iterations performed - -NOTE: this function internally uses separate storage of basic and nonbasic - components; however, all inputs and outputs use single array S.XA[] - to store both basic and nonbasic variables. It transparently splits - variables on input and recombines them on output. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_solvesubproblemdual(dualsimplexstate* state, - dualsimplexsubproblem* s, - ae_bool isphase1, - dualsimplexsettings* settings, - ae_int_t* info, - ae_state *_state) -{ - ae_int_t nx; - ae_int_t m; - ae_int_t i; - ae_int_t p; - ae_int_t r; - ae_int_t q; - double alpharpiv; - double alphaqpiv; - double thetad; - double thetap; - double delta; - ae_int_t forcedrestarts; - - *info = 0; - - nx = s->ns+s->m; - m = s->m; - forcedrestarts = 0; - - /* - * Integrity checks - */ - ae_assert(s->state==reviseddualsimplex_ssvalid, "SolveSubproblemDual: X is not valid", _state); - ae_assert(m>0, "SolveSubproblemDual: M<=0", _state); - for(i=0; i<=nx-1; i++) - { - ae_assert(s->bndt.ptr.p_int[i]!=reviseddualsimplex_ccinfeasible, "SolveSubproblemDual: infeasible box constraints", _state); - } - ae_assert(reviseddualsimplex_isdualfeasible(state, s, settings, _state), "SolveSubproblemDual: dual infeasible initial basis", _state); - - /* - * Actual processing - */ - reviseddualsimplex_offloadbasiccomponents(s, &state->basis, settings, _state); - *info = 0; - rvectorsetlengthatleast(&state->tmp0, m, _state); - for(;;) - { - - /* - * Iteration report - */ - if( state->dotrace ) - { - i = state->repiterationscount2; - if( isphase1 ) - { - i = state->repiterationscount1; - } - ae_trace("=== ITERATION %5d STARTED ========================================================================\n", - (int)(i)); - if( state->dodetailedtrace ) - { - } - } - - /* - * Pricing - */ - reviseddualsimplex_pricingstep(state, s, isphase1, &p, &r, &delta, settings, _state); - if( ae_fp_eq(delta,(double)(0)) ) - { - - /* - * Solved! Feasible and bounded! - */ - if( state->dotrace ) - { - ae_trace("> pricing: feasible point found\n"); - } - reviseddualsimplex_recombinebasicnonbasicx(s, &state->basis, _state); - *info = 1; - return; - } - - /* - * BTran - */ - reviseddualsimplex_btranstep(state, s, r, &state->rhor, settings, _state); - - /* - * Pivot row - */ - reviseddualsimplex_pivotrowstep(state, s, &state->rhor, &state->alphar, settings, _state); - - /* - * Ratio test - */ - reviseddualsimplex_ratiotest(state, s, &state->alphar, delta, p, &q, &alpharpiv, &thetad, &state->possibleflips, &state->possibleflipscnt, settings, _state); - if( q<0 ) - { - - /* - * Do we have fresh factorization and state? If not, - * refresh them prior to declaring that we have no solution. - */ - if( state->basis.trfage>0&&forcedrestartsdotrace ) - { - ae_trace("> ratio test: failed, basis is old (age=%0d), forcing restart (%0d of %0d)\n", - (int)(state->basis.trfage), - (int)(forcedrestarts), - (int)(reviseddualsimplex_maxforcedrestarts-1)); - } - reviseddualsimplex_basisfreshtrf(&state->basis, &state->at, settings, _state); - reviseddualsimplex_subproblemhandlexnupdate(state, s, _state); - reviseddualsimplex_offloadbasiccomponents(s, &state->basis, settings, _state); - inc(&forcedrestarts, _state); - continue; - } - - /* - * Dual unbounded, primal infeasible - */ - if( state->dotrace ) - { - ae_trace("> ratio test: failed, results are accepted\n"); - } - reviseddualsimplex_recombinebasicnonbasicx(s, &state->basis, _state); - *info = -3; - return; - } - thetap = delta/alpharpiv; - - /* - * FTran, including additional FTran for DSE weights (if needed) - * - * NOTE: AlphaQim is filled by intermediate FTran result which is useful - * for Forest-Tomlin update scheme. If not Forest-Tomlin update is - * used, then it is not set. - */ - reviseddualsimplex_ftranstep(state, s, &state->rhor, q, &state->alphaq, &state->alphaqim, &state->tau, settings, _state); - alphaqpiv = state->alphaq.ptr.p_double[r]; - - /* - * Check numerical accuracy, trigger refactorization if needed - */ - if( reviseddualsimplex_refactorizationrequired(state, s, q, alpharpiv, r, alphaqpiv, _state) ) - { - if( state->dotrace ) - { - ae_trace("> refactorization test: numerical errors are too large, forcing refactorization and restart\n"); - } - reviseddualsimplex_basisfreshtrf(&state->basis, &state->at, settings, _state); - reviseddualsimplex_subproblemhandlexnupdate(state, s, _state); - reviseddualsimplex_offloadbasiccomponents(s, &state->basis, settings, _state); - continue; - } - - /* - * Basis change and update - */ - reviseddualsimplex_updatestep(state, s, p, q, r, delta, alpharpiv, thetap, thetad, &state->alphaq, &state->alphaqim, &state->alphar, &state->tau, &state->possibleflips, state->possibleflipscnt, settings, _state); - inc(&state->repiterationscount, _state); - if( isphase1 ) - { - inc(&state->repiterationscount1, _state); - } - else - { - inc(&state->repiterationscount2, _state); - } - } -} - - -/************************************************************************* -This function solves simplex subproblem using primal simplex method. - -A problem with following properties is expected: -* M>0 -* feasible box constraints -* primal feasible initial basis -* actual initial point XC and target value Z -* actual reduced cost vector D -* pricing weights being set to 1.0 or copied from previous problem - -Returns: - * Info = +1 for success, -3 for infeasible - * IterationsCount is increased by amount of iterations performed - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_solvesubproblemprimal(dualsimplexstate* state, - dualsimplexsubproblem* s, - dualsimplexsettings* settings, - ae_int_t* info, - ae_state *_state) -{ - ae_int_t nn; - ae_int_t nx; - ae_int_t m; - ae_int_t i; - ae_int_t j; - double v; - double vmax; - ae_int_t bi; - double dj; - ae_int_t bndt; - ae_int_t q; - ae_int_t p; - ae_int_t r; - ae_int_t dir; - double lim; - ae_bool haslim; - double thetap; - double xbnd; - double flip; - ae_int_t canddir; - double candlim; - double candflip; - ae_int_t j0; - ae_int_t j1; - double alphawave; - double vp; - double vb; - double vx; - double vtest; - double vv; - - *info = 0; - - nn = s->ns; - nx = s->ns+s->m; - m = s->m; - - /* - * Integrity checks - */ - ae_assert(s->state==reviseddualsimplex_ssvalid, "SolveSubproblemPrimal: X is not valid", _state); - ae_assert(m>0, "SolveSubproblemPrimal: M<=0", _state); - for(i=0; i<=nx-1; i++) - { - ae_assert(s->bndt.ptr.p_int[i]!=reviseddualsimplex_ccinfeasible, "SolveSubproblemPrimal: infeasible box constraints", _state); - } - - /* - * Actual processing - */ - *info = 1; - rvectorsetlengthatleast(&state->tmp0, m, _state); - for(;;) - { - - /* - * Iteration report - */ - if( state->dotrace ) - { - i = state->repiterationscount3; - ae_trace("=== ITERATION %5d STARTED ========================================================================\n", - (int)(i)); - if( state->dodetailedtrace ) - { - } - } - - /* - * Primal simplex pricing step: we implement the very basic version - * of the pricing step because it is expected that primal simplex method - * is used just to apply quick correction after removal of the perturbation. - */ - q = -1; - vmax = (double)(0); - dir = 0; - lim = ae_maxrealnumber; - haslim = ae_false; - flip = (double)(0); - canddir = 0; - for(i=0; i<=nn-1; i++) - { - j = state->basis.nidx.ptr.p_int[i]; - dj = s->d.ptr.p_double[j]; - bndt = s->bndt.ptr.p_int[j]; - if( bndt==reviseddualsimplex_ccfixed ) - { - continue; - } - if( bndt==reviseddualsimplex_ccrange ) - { - v = (double)(0); - candlim = s->bndu.ptr.p_double[j]-s->bndl.ptr.p_double[j]; - candflip = (double)(0); - if( s->xa.ptr.p_double[j]==s->bndl.ptr.p_double[j] ) - { - v = -dj; - canddir = 1; - candflip = s->bndu.ptr.p_double[j]; - } - if( s->xa.ptr.p_double[j]==s->bndu.ptr.p_double[j] ) - { - v = dj; - canddir = -1; - candflip = s->bndl.ptr.p_double[j]; - } - if( v>vmax ) - { - vmax = v; - dir = canddir; - lim = candlim; - haslim = ae_true; - flip = candflip; - q = j; - } - continue; - } - v = (double)(0); - canddir = 0; - if( bndt==reviseddualsimplex_cclower ) - { - v = -dj; - canddir = 1; - } - if( bndt==reviseddualsimplex_ccupper ) - { - v = dj; - canddir = -1; - } - if( bndt==reviseddualsimplex_ccfree ) - { - v = ae_fabs(dj, _state); - canddir = -ae_sign(dj, _state); - } - if( v>vmax ) - { - vmax = v; - dir = canddir; - lim = ae_maxrealnumber; - haslim = ae_false; - q = j; - } - continue; - } - if( vmax<=settings->dtolabs ) - { - - /* - * Solved: primal and dual feasible! - */ - if( state->dotrace ) - { - ae_trace("> primal pricing: feasible point found\n"); - } - return; - } - ae_assert(q>=0, "SolveSubproblemPrimal: integrity check failed", _state); - if( state->dotrace ) - { - ae_trace("> primal pricing: found entering variable\n"); - ae_trace("Q = %12d (variable selected)\n", - (int)(q)); - ae_trace("|D| = %12.3e (dual infeasibility)\n", - (double)(vmax)); - } - - /* - * FTran and textbook ratio test (again, we expect primal phase to terminate quickly) - * - * NOTE: AlphaQim is filled by intermediate FTran result which is useful - * for Forest-Tomlin update scheme. If not Forest-Tomlin update is - * used, then it is not set. - */ - for(i=0; i<=m-1; i++) - { - state->tmp0.ptr.p_double[i] = (double)(0); - } - j0 = state->at.ridx.ptr.p_int[q]; - j1 = state->at.ridx.ptr.p_int[q+1]-1; - for(j=j0; j<=j1; j++) - { - state->tmp0.ptr.p_double[state->at.idx.ptr.p_int[j]] = state->at.vals.ptr.p_double[j]; - } - reviseddualsimplex_basissolvex(&state->basis, &state->tmp0, &state->alphaq, &state->alphaqim, ae_true, &state->tmp2, _state); - vp = settings->pivottol; - p = -1; - r = -1; - thetap = (double)(0); - xbnd = (double)(0); - for(i=0; i<=m-1; i++) - { - bi = state->basis.idx.ptr.p_int[i]; - alphawave = -dir*state->alphaq.ptr.p_double[i]; - vx = s->xa.ptr.p_double[bi]; - if( alphawave<-vp&&reviseddualsimplex_hasbndl(s, bi, _state) ) - { - vb = s->bndl.ptr.p_double[bi]; - if( vx<=vb ) - { - - /* - * X[Bi] is already out of bounds due to rounding errors, perform shifting - */ - vb = vx-reviseddualsimplex_shiftlen; - s->bndl.ptr.p_double[bi] = vx; - } - vtest = (vb-vx)/alphawave; - if( p<0||vtestvp&&reviseddualsimplex_hasbndu(s, bi, _state) ) - { - vb = s->bndu.ptr.p_double[bi]; - if( vx>=vb ) - { - - /* - * X[Bi] is already out of bounds due to rounding errors, perform shifting - */ - vb = vx+reviseddualsimplex_shiftlen; - s->bndu.ptr.p_double[bi] = vb; - } - vtest = (vb-vx)/alphawave; - if( p<0||vtestdotrace ) - { - ae_trace("> primal ratio test: dual infeasible, primal unbounded\n"); - } - return; - } - if( state->dotrace ) - { - ae_trace("> primal ratio test: found leaving variable\n"); - ae_trace("P = %12d (variable index)\n", - (int)(p)); - ae_trace("R = %12d (variable index in basis)\n", - (int)(r)); - ae_trace("ThetaP = %12.3e (primal step length)\n", - (double)(thetap)); - } - - /* - * Update step - */ - if( p>=0&&(!haslim||thetaptmp0, m, _state); - for(i=0; i<=m-1; i++) - { - bi = state->basis.idx.ptr.p_int[i]; - vv = thetap*(dir*state->alphaq.ptr.p_double[i]); - s->xa.ptr.p_double[bi] = s->xa.ptr.p_double[bi]-vv; - } - s->xa.ptr.p_double[p] = xbnd; - s->xa.ptr.p_double[q] = s->xa.ptr.p_double[q]+dir*thetap; - for(i=0; i<=m-1; i++) - { - state->tmp0.ptr.p_double[i] = (double)(0); - } - reviseddualsimplex_basisupdatetrf(&state->basis, &state->at, p, q, &state->alphaq, &state->alphaqim, r, &state->tmp0, settings, _state); - for(i=0; i<=m-1; i++) - { - state->tmp0.ptr.p_double[i] = s->effc.ptr.p_double[state->basis.idx.ptr.p_int[i]]; - } - reviseddualsimplex_basissolvet(&state->basis, &state->tmp0, &state->tmp1, &state->tmp2, _state); - reviseddualsimplex_computeantv(state, &state->tmp1, &s->d, _state); - for(i=0; i<=nn-1; i++) - { - j = state->basis.nidx.ptr.p_int[i]; - s->d.ptr.p_double[j] = s->effc.ptr.p_double[j]-s->d.ptr.p_double[j]; - } - } - else - { - - /* - * Basis does not change because Qth variable flips from one bound - * to another one long before we encounter the boundary - */ - s->xa.ptr.p_double[q] = flip; - for(i=0; i<=m-1; i++) - { - bi = state->basis.idx.ptr.p_int[i]; - vv = lim*(dir*state->alphaq.ptr.p_double[i]); - s->xa.ptr.p_double[bi] = s->xa.ptr.p_double[bi]-vv; - } - } - inc(&state->repiterationscount, _state); - inc(&state->repiterationscount3, _state); - } -} - - -/************************************************************************* -This function estimates feasibility properties of the current basis and -invokes phase 1 if necessary. - -A problem with following properties is expected: -* M>0 -* feasible box constraints -* some initial basis (can be dual infeasible) with actual factorization -* actual initial point XC and target value Z -* actual reduced cost vector D - -It returns: -* +1 if dual feasible basis was found -* -4 if problem is dual infeasible - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_invokephase1(dualsimplexstate* state, - dualsimplexsettings* settings, - ae_state *_state) -{ - ae_int_t m; - double dualerr; - - - m = state->primary.m; - state->repterminationtype = 0; - - /* - * Integrity checks - */ - ae_assert(state->primary.state==reviseddualsimplex_ssvalid, "InvokePhase1: invalid primary X", _state); - ae_assert(m>0, "InvokePhase1: M<=0", _state); - - /* - * Is it dual feasible from the very beginning (or maybe after initial DFC)? - */ - if( state->dotrace ) - { - ae_trace("> performing initial dual feasibility correction...\n"); - } - dualerr = reviseddualsimplex_initialdualfeasibilitycorrection(state, &state->primary, settings, _state); - if( state->dotrace ) - { - ae_trace("> initial dual feasibility correction done\ndualErr = %0.3e\n", - (double)(dualerr)); - } - if( ae_fp_less_eq(dualerr,settings->dtolabs) ) - { - if( state->dotrace ) - { - ae_trace("> solution is dual feasible, phase 1 is done\n"); - } - state->repterminationtype = 1; - return; - } - if( state->dotrace ) - { - ae_trace("> solution is not dual feasible, proceeding to full-scale phase 1\n"); - ae_trace("\n"); - ae_trace("****************************************************************************************************\n"); - ae_trace("* PHASE 1 OF DUAL SIMPLEX SOLVER *\n"); - ae_trace("****************************************************************************************************\n"); - } - - /* - * Solve phase #1 subproblem - */ - reviseddualsimplex_subprobleminitphase1(&state->primary, &state->basis, &state->phase1, _state); - if( state->dotrace ) - { - ae_trace("> performing phase 1 dual feasibility correction...\n"); - } - dualerr = reviseddualsimplex_initialdualfeasibilitycorrection(state, &state->phase1, settings, _state); - if( state->dotrace ) - { - ae_trace("> phase 1 dual feasibility correction done\ndualErr = %0.3e\n", - (double)(dualerr)); - } - reviseddualsimplex_solvesubproblemdual(state, &state->phase1, ae_true, settings, &state->repterminationtype, _state); - ae_assert(state->repterminationtype>0, "DualSimplexSolver: unexpected failure of phase #1", _state); - state->repterminationtype = 1; - - /* - * Setup initial basis for phase #2 using solution of phase #1 - */ - if( state->dotrace ) - { - ae_trace("> setting up phase 2 initial solution\n"); - } - reviseddualsimplex_subprobleminferinitialxn(state, &state->primary, _state); - dualerr = reviseddualsimplex_initialdualfeasibilitycorrection(state, &state->primary, settings, _state); - if( ae_fp_greater(dualerr,settings->dtolabs) ) - { - if( state->dotrace ) - { - ae_trace("> initial dual feasibility correction failed! terminating...\n"); - } - state->repterminationtype = -4; - return; - } - state->repterminationtype = 1; -} - - -/************************************************************************* -This function performs actual solution. - -INPUT PARAMETERS: - State - state - -Solution results can be found in fields of State which are explicitly -declared as accessible by external code. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_dssoptimizewrk(dualsimplexstate* state, - dualsimplexsettings* settings, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nx; - ae_int_t m; - ae_int_t i; - ae_int_t j; - double v; - hqrndstate rs; - ae_int_t t0; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - _hqrndstate_init(&rs, _state, ae_true); - - nx = state->primary.ns+state->primary.m; - m = state->primary.m; - t0 = 0; - - /* - * Handle case when M=0; after this block we assume that M>0. - */ - if( m==0 ) - { - - /* - * Trace - */ - if( state->dotrace ) - { - ae_trace("> box-only LP problem, quick solution\n"); - } - - /* - * Solve - */ - reviseddualsimplex_solveboxonly(state, _state); - ae_frame_leave(_state); - return; - } - - /* - * Most basic check for correctness of box and/or linear constraints - */ - for(j=0; j<=nx-1; j++) - { - if( state->primary.bndt.ptr.p_int[j]==reviseddualsimplex_ccinfeasible ) - { - - /* - * Set error flag and generate some point to return - */ - if( state->dotrace ) - { - ae_trace("[WARNING] infeasible box constraint (or range constraint with AL>AU) found, terminating\n"); - } - state->repterminationtype = -3; - reviseddualsimplex_setzeroxystats(state, _state); - ae_frame_leave(_state); - return; - } - } - - /* - * Initialization: - * * initial perturbed C[] - */ - hqrndseed(7456, 2355, &rs, _state); - for(i=0; i<=nx-1; i++) - { - if( !reviseddualsimplex_isfree(&state->primary, i, _state) ) - { - - /* - * apply perturbation - */ - v = settings->perturbmag*(1+ae_fabs(state->primary.rawc.ptr.p_double[i], _state))*(1+hqrnduniformr(&rs, _state)); - if( !reviseddualsimplex_hasbndl(&state->primary, i, _state) ) - { - v = -v; - } - state->primary.effc.ptr.p_double[i] = state->primary.rawc.ptr.p_double[i]+v; - } - } - - /* - * Solve phase 1 subproblem, then perturbed subproblem - */ - reviseddualsimplex_basisfreshtrf(&state->basis, &state->at, settings, _state); - if( state->primary.state==reviseddualsimplex_ssinvalid ) - { - reviseddualsimplex_subprobleminferinitialxn(state, &state->primary, _state); - } - if( state->primary.state==reviseddualsimplex_ssvalidxn ) - { - reviseddualsimplex_subproblemhandlexnupdate(state, &state->primary, _state); - } - ae_assert(state->primary.state==reviseddualsimplex_ssvalid, "DSS: integrity check failed (init)", _state); - if( state->dotimers ) - { - t0 = ae_tickcount(); - } - reviseddualsimplex_invokephase1(state, settings, _state); - if( state->dotimers ) - { - state->repphase1time = ae_tickcount()-t0; - } - if( state->repterminationtype<=0 ) - { - - /* - * Primal unbounded, dual infeasible - */ - ae_assert(state->repterminationtype==-4, "DSS: integrity check for InvokePhase1() result failed", _state); - if( state->dotrace ) - { - ae_trace("> the problem is dual infeasible, primal unbounded\n> done\n"); - } - reviseddualsimplex_setxydstats(state, &state->primary, &state->basis, &state->xydsbuf, &state->repx, &state->replagbc, &state->replaglc, &state->repstats, _state); - ae_frame_leave(_state); - return; - } - if( state->dotrace ) - { - ae_trace("\n"); - ae_trace("****************************************************************************************************\n"); - ae_trace("* PHASE 2 OF DUAL SIMPLEX SOLVER *\n"); - ae_trace("****************************************************************************************************\n"); - } - if( state->dotimers ) - { - t0 = ae_tickcount(); - } - reviseddualsimplex_solvesubproblemdual(state, &state->primary, ae_false, settings, &state->repterminationtype, _state); - if( state->dotimers ) - { - state->repphase2time = ae_tickcount()-t0; - } - if( state->repterminationtype<=0 ) - { - - /* - * Primal infeasible - */ - ae_assert(state->repterminationtype==-3, "DSS: integrity check for SolveSubproblemDual() result failed", _state); - if( state->dotrace ) - { - ae_trace("> the problem is primal infeasible\n> done\n"); - } - reviseddualsimplex_setxydstats(state, &state->primary, &state->basis, &state->xydsbuf, &state->repx, &state->replagbc, &state->replaglc, &state->repstats, _state); - ae_frame_leave(_state); - return; - } - - /* - * Remove perturbation from the cost vector, - * then use primal simplex to enforce dual feasibility - * after removal of the perturbation (if necessary). - */ - if( state->dotrace ) - { - ae_trace("\n"); - ae_trace("****************************************************************************************************\n"); - ae_trace("* PHASE 3 OF DUAL SIMPLEX SOLVER (perturbation removed from cost vector) *\n"); - ae_trace("****************************************************************************************************\n"); - } - if( state->dotimers ) - { - t0 = ae_tickcount(); - } - reviseddualsimplex_subprobleminitphase3(&state->primary, &state->phase3, _state); - for(i=0; i<=nx-1; i++) - { - state->phase3.effc.ptr.p_double[i] = state->primary.rawc.ptr.p_double[i]; - } - ae_assert(state->phase3.state>=reviseddualsimplex_ssvalidxn, "DSS: integrity check failed (remove perturbation)", _state); - reviseddualsimplex_subproblemhandlexnupdate(state, &state->phase3, _state); - reviseddualsimplex_solvesubproblemprimal(state, &state->phase3, settings, &state->repterminationtype, _state); - if( state->dotimers ) - { - state->repphase3time = ae_tickcount()-t0; - } - if( state->repterminationtype<=0 ) - { - - /* - * Dual infeasible, primal unbounded - */ - ae_assert(state->repterminationtype==-4, "DSS: integrity check for SolveSubproblemPrimal() result failed", _state); - if( state->dotrace ) - { - ae_trace("> the problem is primal unbounded\n> done\n"); - } - reviseddualsimplex_setxydstats(state, &state->phase3, &state->basis, &state->xydsbuf, &state->repx, &state->replagbc, &state->replaglc, &state->repstats, _state); - ae_frame_leave(_state); - return; - } - for(i=0; i<=nx-1; i++) - { - state->primary.xa.ptr.p_double[i] = state->phase3.xa.ptr.p_double[i]; - if( reviseddualsimplex_hasbndl(&state->primary, i, _state) ) - { - state->primary.xa.ptr.p_double[i] = ae_maxreal(state->primary.xa.ptr.p_double[i], state->primary.bndl.ptr.p_double[i], _state); - } - if( reviseddualsimplex_hasbndu(&state->primary, i, _state) ) - { - state->primary.xa.ptr.p_double[i] = ae_minreal(state->primary.xa.ptr.p_double[i], state->primary.bndu.ptr.p_double[i], _state); - } - } - - /* - * Primal and dual feasible, problem solved - */ - state->repterminationtype = 1; - reviseddualsimplex_setxydstats(state, &state->primary, &state->basis, &state->xydsbuf, &state->repx, &state->replagbc, &state->replaglc, &state->repstats, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Box-constrained solver; sets State.RepX, State.RepStats and State.RepTerminationType, -does not change other fields. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_solveboxonly(dualsimplexstate* state, - ae_state *_state) -{ - ae_int_t i; - ae_int_t ns; - - - ns = state->primary.ns; - ae_assert(state->primary.m==0, "SolveBoxOnly: integrity check failed", _state); - rsetv(ns, 0.0, &state->replagbc, _state); - for(i=0; i<=ns-1; i++) - { - - /* - * Handle infeasible variable - */ - if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccinfeasible ) - { - state->repterminationtype = -3; - state->repx.ptr.p_double[i] = 0.5*(state->primary.bndl.ptr.p_double[i]+state->primary.bndu.ptr.p_double[i]); - state->repstats.ptr.p_int[i] = 0; - continue; - } - - /* - * Handle fixed variable - */ - if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccfixed ) - { - state->repx.ptr.p_double[i] = state->primary.bndl.ptr.p_double[i]; - state->repstats.ptr.p_int[i] = -1; - state->replagbc.ptr.p_double[i] = -state->primary.rawc.ptr.p_double[i]; - continue; - } - - /* - * Handle non-zero cost component - */ - if( ae_fp_greater(state->primary.rawc.ptr.p_double[i],(double)(0)) ) - { - if( state->primary.bndt.ptr.p_int[i]!=reviseddualsimplex_ccrange&&state->primary.bndt.ptr.p_int[i]!=reviseddualsimplex_cclower ) - { - if( state->repterminationtype>0 ) - { - state->repterminationtype = -4; - } - if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccupper ) - { - state->repx.ptr.p_double[i] = state->primary.bndu.ptr.p_double[i]; - state->repstats.ptr.p_int[i] = 1; - } - else - { - state->repx.ptr.p_double[i] = (double)(0); - state->repstats.ptr.p_int[i] = 0; - } - state->replagbc.ptr.p_double[i] = (double)(0); - } - else - { - state->repx.ptr.p_double[i] = state->primary.bndl.ptr.p_double[i]; - state->repstats.ptr.p_int[i] = -1; - state->replagbc.ptr.p_double[i] = -state->primary.rawc.ptr.p_double[i]; - } - continue; - } - if( ae_fp_less(state->primary.rawc.ptr.p_double[i],(double)(0)) ) - { - if( state->primary.bndt.ptr.p_int[i]!=reviseddualsimplex_ccrange&&state->primary.bndt.ptr.p_int[i]!=reviseddualsimplex_ccupper ) - { - if( state->repterminationtype>0 ) - { - state->repterminationtype = -4; - } - if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_cclower ) - { - state->repx.ptr.p_double[i] = state->primary.bndl.ptr.p_double[i]; - state->repstats.ptr.p_int[i] = -1; - } - else - { - state->repx.ptr.p_double[i] = (double)(0); - state->repstats.ptr.p_int[i] = 0; - } - state->replagbc.ptr.p_double[i] = (double)(0); - } - else - { - state->repx.ptr.p_double[i] = state->primary.bndu.ptr.p_double[i]; - state->repstats.ptr.p_int[i] = 1; - state->replagbc.ptr.p_double[i] = -state->primary.rawc.ptr.p_double[i]; - } - continue; - } - - /* - * Handle non-free variable with zero cost component - */ - if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccupper||state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccrange ) - { - state->repx.ptr.p_double[i] = state->primary.bndu.ptr.p_double[i]; - state->repstats.ptr.p_int[i] = 1; - state->replagbc.ptr.p_double[i] = (double)(0); - continue; - } - if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_cclower ) - { - state->repx.ptr.p_double[i] = state->primary.bndl.ptr.p_double[i]; - state->repstats.ptr.p_int[i] = -1; - state->replagbc.ptr.p_double[i] = (double)(0); - continue; - } - - /* - * Free variable, zero cost component - */ - ae_assert(state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccfree, "DSSOptimize: integrity check failed", _state); - state->repx.ptr.p_double[i] = (double)(0); - state->repstats.ptr.p_int[i] = 0; - state->replagbc.ptr.p_double[i] = (double)(0); - } -} - - -/************************************************************************* -Zero-fill RepX, RepLagBC, RepLagLC, RepStats. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_setzeroxystats(dualsimplexstate* state, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=state->primary.ns-1; i++) - { - state->repx.ptr.p_double[i] = (double)(0); - state->replagbc.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=state->primary.m-1; i++) - { - state->replaglc.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=state->primary.ns+state->primary.m-1; i++) - { - state->repstats.ptr.p_int[i] = 0; - } -} - - -/************************************************************************* -This function initializes basis structure; no triangular factorization is -prepared yet. Previously allocated memory is reused. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_basisinit(ae_int_t ns, - ae_int_t m, - dualsimplexbasis* s, - ae_state *_state) -{ - ae_int_t i; - - - s->ns = ns; - s->m = m; - ivectorgrowto(&s->idx, m, _state); - ivectorgrowto(&s->nidx, ns, _state); - bvectorgrowto(&s->isbasic, ns+m, _state); - for(i=0; i<=ns-1; i++) - { - s->nidx.ptr.p_int[i] = i; - s->isbasic.ptr.p_bool[i] = ae_false; - } - for(i=0; i<=m-1; i++) - { - s->idx.ptr.p_int[i] = ns+i; - s->isbasic.ptr.p_bool[ns+i] = ae_true; - } - s->trftype = 3; - s->trfage = 0; - s->isvalidtrf = ae_false; - rvectorsetlengthatleast(&s->dseweights, m, _state); - for(i=0; i<=m-1; i++) - { - s->dseweights.ptr.p_double[i] = 1.0; - } - s->dsevalid = ae_false; - reviseddualsimplex_basisclearstats(s, _state); -} - - -/************************************************************************* -This function clears internal performance counters of the basis - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_basisclearstats(dualsimplexbasis* s, - ae_state *_state) -{ - - - s->statfact = 0; - s->statupdt = 0; - s->statoffdiag = (double)(0); -} - - -/************************************************************************* -This function resizes basis. It is assumed that constraint matrix is -completely overwritten by new one, but both matrices are similar enough -so we can reuse previous basis. - -Dual steepest edge weights are invalidated by this function. - -This function: -* tries to resize basis -* if possible, returns True and valid basis with valid factorization -* if resize is impossible (or abandoned due to stability reasons), it - returns False and basis object is left in the invalid state (you have - to reinitialize it by all-logicals basis) - -Following types of resize are supported: -* new basis size is larger than previous one => logical elements are - added to the new basis -* basis sizes match => no operation is performed -* new basis size is zero => basis is set to zero - -This function: -* requires valid triangular factorization at S on entry -* replaces it by another, valid factorization -* checks that new factorization deviates from the previous one not too much - by comparing magnitudes of min[abs(u_ii)] in both factorization (sharp - decrease results in attempt to resize being abandoned - -IMPORTANT: if smooth resize is not possible, this function throws an - exception! It is responsibility of the caller to check that - smooth resize is possible - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static ae_bool reviseddualsimplex_basistryresize(dualsimplexbasis* s, - ae_int_t newm, - sparsematrix* at, - dualsimplexsettings* settings, - ae_state *_state) -{ - ae_int_t ns; - ae_int_t oldm; - ae_int_t i; - double oldminu; - double newminu; - ae_bool result; - - - ns = s->ns; - oldm = s->m; - result = ae_false; - - /* - * Quick exit strategies - */ - if( newm==0 ) - { - reviseddualsimplex_basisinit(ns, 0, s, _state); - result = ae_true; - return result; - } - - /* - * Same size or larger - */ - if( newm>=oldm ) - { - ae_assert(s->isvalidtrf||oldm==0, "BasisTryResize: needs valid TRF in S", _state); - - /* - * Save information about matrix conditioning - */ - oldminu = reviseddualsimplex_basisminimumdiagonalelement(s, _state); - - /* - * Growth if needed - */ - s->m = newm; - ivectorgrowto(&s->idx, newm, _state); - bvectorgrowto(&s->isbasic, ns+newm, _state); - for(i=oldm; i<=newm-1; i++) - { - s->idx.ptr.p_int[i] = ns+i; - s->isbasic.ptr.p_bool[ns+i] = ae_true; - } - - /* - * DSE weights are invalid and filled by 1.0 - */ - rvectorgrowto(&s->dseweights, newm, _state); - for(i=0; i<=newm-1; i++) - { - s->dseweights.ptr.p_double[i] = 1.0; - } - s->dsevalid = ae_false; - - /* - * Invalidate TRF. - * Try to refactorize. - */ - s->isvalidtrf = ae_false; - newminu = reviseddualsimplex_basisfreshtrfunsafe(s, at, settings, _state); - result = ae_fp_greater_eq(newminu,reviseddualsimplex_maxudecay*oldminu); - return result; - } - ae_assert(ae_false, "BasisTryResize: unexpected branch", _state); - return result; -} - - -/************************************************************************* -This function returns minimum diagonal element of S. Result=1 is returned -for M=0. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static double reviseddualsimplex_basisminimumdiagonalelement(dualsimplexbasis* s, - ae_state *_state) -{ - double v; - double vv; - ae_int_t i; - ae_int_t m; - double result; - - - m = s->m; - if( m==0 ) - { - result = (double)(1); - return result; - } - ae_assert(((s->trftype==0||s->trftype==1)||s->trftype==2)||s->trftype==3, "BasisMinimumDiagonalElement: unexpected TRF type", _state); - ae_assert(s->isvalidtrf, "BasisMinimumDiagonalElement: TRF is invalid", _state); - v = ae_maxrealnumber; - for(i=0; i<=m-1; i++) - { - vv = (double)(0); - if( s->trftype==0||s->trftype==1 ) - { - vv = s->denselu.ptr.pp_double[i][i]; - } - if( s->trftype==2||s->trftype==3 ) - { - vv = sparsegetdiagonal(&s->sparseu, i, _state); - } - if( vv<0 ) - { - vv = -vv; - } - if( vvns = s0->ns; - s1->m = s0->m; - copyintegerarray(&s0->idx, &s1->idx, _state); - copyintegerarray(&s0->nidx, &s1->nidx, _state); - copybooleanarray(&s0->isbasic, &s1->isbasic, _state); - s1->isvalidtrf = ae_false; - s1->trftype = -1; - s1->dsevalid = ae_false; - if( s0->m>0 ) - { - ae_assert(s0->isvalidtrf, "BasisExport: valid factorization is required for source basis", _state); - s1->eminu = reviseddualsimplex_basisminimumdiagonalelement(s0, _state); - } - else - { - s1->eminu = (double)(1); - } -} - - -/************************************************************************* -This function imports from S1 to S0 a division of variables into -basic/nonbasic ones; only basic/nonbasic sets are imported. - -Triangular factorization is not imported; however, this function checks -that new factorization deviates from the previous one not too much by -comparing magnitudes of min[abs(u_ii)] in both factorization (basis being -imported stores statistics about U). Sharp decrease of diagonal elements -means that we have too unstable situation which results in import being -abandoned. In this case False is returned, and the basis S0 is left in the -indeterminate invalid state (you have to reinitialize it by all-logicals). - -IMPORTANT: if metrics of S0 and S1 do not match, an exception will be generated. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static ae_bool reviseddualsimplex_basistryimportfrom(dualsimplexbasis* s0, - dualsimplexbasis* s1, - sparsematrix* at, - dualsimplexsettings* settings, - ae_state *_state) -{ - ae_int_t i; - double newminu; - ae_bool result; - - - ae_assert(s0->ns==s1->ns, "BasisImportFrom: structural variable counts do not match", _state); - reviseddualsimplex_basisclearstats(s0, _state); - s0->m = s1->m; - for(i=0; i<=s0->m-1; i++) - { - s0->idx.ptr.p_int[i] = s1->idx.ptr.p_int[i]; - } - for(i=0; i<=s0->ns-1; i++) - { - s0->nidx.ptr.p_int[i] = s1->nidx.ptr.p_int[i]; - } - for(i=0; i<=s0->m+s0->ns-1; i++) - { - s0->isbasic.ptr.p_bool[i] = s1->isbasic.ptr.p_bool[i]; - } - s0->isvalidtrf = ae_false; - rvectorsetlengthatleast(&s0->dseweights, s1->m, _state); - for(i=0; i<=s1->m-1; i++) - { - s0->dseweights.ptr.p_double[i] = 1.0; - } - s0->dsevalid = ae_false; - newminu = reviseddualsimplex_basisfreshtrfunsafe(s0, at, settings, _state); - result = ae_fp_greater_eq(newminu,reviseddualsimplex_maxudecay*s1->eminu); - if( !result ) - { - s0->isvalidtrf = ae_false; - s0->trftype = -1; - } - return result; -} - - -/************************************************************************* -This function computes fresh triangular factorization. - -If TRF of age 0 (fresh) is already present, no new factorization is calculated. -If factorization has exactly zero element along diagonal, this function -generates exception. - - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_basisfreshtrf(dualsimplexbasis* s, - sparsematrix* at, - dualsimplexsettings* settings, - ae_state *_state) -{ - double v; - - - v = reviseddualsimplex_basisfreshtrfunsafe(s, at, settings, _state); - ae_assert(ae_fp_greater(v,(double)(0)), "BasisFreshTrf: degeneracy of B is detected", _state); -} - - -/************************************************************************* -This function computes fresh triangular factorization. - -If TRF of age 0 (fresh) is already present, no new factorization is calculated. - -It returns min[abs(u[i,i])] which can be used to determine whether factorization -is degenerate or not (it will factorize anything, the question is whether -it is possible to use factorization) - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static double reviseddualsimplex_basisfreshtrfunsafe(dualsimplexbasis* s, - sparsematrix* at, - dualsimplexsettings* settings, - ae_state *_state) -{ - ae_int_t m; - ae_int_t ns; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t j0; - ae_int_t j1; - ae_int_t k1; - ae_int_t nzl; - ae_int_t nzu; - ae_int_t nlogical; - ae_int_t nstructural; - ae_int_t offs; - ae_int_t offs1; - ae_int_t offs2; - double result; - - - m = s->m; - ns = s->ns; - result = (double)(0); - - /* - * Compare TRF type with one required by settings, invalidation and refresh otherwise - */ - if( s->trftype!=settings->trftype ) - { - s->trftype = settings->trftype; - s->isvalidtrf = ae_false; - result = reviseddualsimplex_basisfreshtrfunsafe(s, at, settings, _state); - return result; - } - - /* - * Is it valid and fresh? - */ - if( s->isvalidtrf&&s->trfage==0 ) - { - result = reviseddualsimplex_basisminimumdiagonalelement(s, _state); - return result; - } - - /* - * Dense TRF - */ - if( s->trftype==0||s->trftype==1 ) - { - ivectorsetlengthatleast(&s->colpermbwd, m, _state); - for(i=0; i<=m-1; i++) - { - s->colpermbwd.ptr.p_int[i] = i; - } - rmatrixsetlengthatleast(&s->denselu, m, m, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - s->denselu.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=m-1; i++) - { - j0 = at->ridx.ptr.p_int[s->idx.ptr.p_int[i]]; - j1 = at->ridx.ptr.p_int[s->idx.ptr.p_int[i]+1]-1; - for(j=j0; j<=j1; j++) - { - s->denselu.ptr.pp_double[i][at->idx.ptr.p_int[j]] = at->vals.ptr.p_double[j]; - } - } - rmatrixlu(&s->denselu, m, m, &s->tmpi, _state); - reviseddualsimplex_pivottobwd(&s->tmpi, m, &s->rowpermbwd, _state); - s->isvalidtrf = ae_true; - s->trfage = 0; - s->statfact = s->statfact+1; - s->statoffdiag = s->statoffdiag+ae_sqr((double)(m-1), _state); - result = reviseddualsimplex_basisminimumdiagonalelement(s, _state); - return result; - } - - /* - * Sparse TRF (with either PFI or Forest-Tomlin) - */ - if( s->trftype==2||s->trftype==3 ) - { - - /* - * Determine permutation which moves logical variables - * to the beginning. - * - * NOTE: this reordering results in stable factorization - * because we prenormalized constraints with 2-norm, - * all elements in the logical columns are less than - * 1.0 in magnitude. - * - * After this block is done we have following arrays: - * * tCInvIdx[j], which is an inverse of ColPermBwf[] - */ - ivectorsetlengthatleast(&s->tcinvidx, m, _state); - ivectorsetlengthatleast(&s->rowpermbwd, m, _state); - ivectorsetlengthatleast(&s->colpermbwd, m, _state); - for(i=0; i<=m-1; i++) - { - s->tcinvidx.ptr.p_int[i] = i; - s->rowpermbwd.ptr.p_int[i] = i; - s->colpermbwd.ptr.p_int[i] = i; - } - nlogical = 0; - for(i=0; i<=m-1; i++) - { - if( s->idx.ptr.p_int[i]>=ns ) - { - j = s->rowpermbwd.ptr.p_int[nlogical]; - s->rowpermbwd.ptr.p_int[nlogical] = s->rowpermbwd.ptr.p_int[i]; - s->rowpermbwd.ptr.p_int[i] = j; - j1 = s->tcinvidx.ptr.p_int[s->idx.ptr.p_int[i]-ns]; - j = s->colpermbwd.ptr.p_int[j1]; - s->colpermbwd.ptr.p_int[j1] = s->colpermbwd.ptr.p_int[nlogical]; - s->colpermbwd.ptr.p_int[nlogical] = j; - s->tcinvidx.ptr.p_int[s->colpermbwd.ptr.p_int[nlogical]] = nlogical; - s->tcinvidx.ptr.p_int[s->colpermbwd.ptr.p_int[j1]] = j1; - nlogical = nlogical+1; - } - } - sortmiddlei(&s->colpermbwd, nlogical, m-nlogical, _state); - for(i=0; i<=m-1; i++) - { - s->tcinvidx.ptr.p_int[s->colpermbwd.ptr.p_int[i]] = i; - } - nstructural = m-nlogical; - - /* - * Prepare SparseLU1 to receive factored out logical part of the matrix - * and SparseLU2 to receive structural part of the matrix. - */ - ivectorsetlengthatleast(&s->sparselu1.ridx, nstructural+1, _state); - ivectorsetlengthatleast(&s->sparselu1.didx, nstructural, _state); - ivectorsetlengthatleast(&s->sparselu1.uidx, nstructural, _state); - s->sparselu1.matrixtype = 1; - s->sparselu1.m = nstructural; - s->sparselu1.n = nlogical; - s->sparselu1.ridx.ptr.p_int[0] = 0; - ivectorsetlengthatleast(&s->sparselu2.ridx, nstructural+1, _state); - ivectorsetlengthatleast(&s->sparselu2.didx, nstructural, _state); - ivectorsetlengthatleast(&s->sparselu2.uidx, nstructural, _state); - s->sparselu2.matrixtype = 1; - s->sparselu2.m = nstructural; - s->sparselu2.n = nstructural; - s->sparselu2.ridx.ptr.p_int[0] = 0; - - /* - * Reorder array, perform LU factorization - */ - for(k=0; k<=nstructural-1; k++) - { - - /* - * Make sure SparseLU1 and SparseLU2 have enough place. - */ - offs1 = s->sparselu1.ridx.ptr.p_int[k]; - offs2 = s->sparselu2.ridx.ptr.p_int[k]; - ivectorgrowto(&s->sparselu1.idx, offs1+m, _state); - rvectorgrowto(&s->sparselu1.vals, offs1+m, _state); - ivectorgrowto(&s->sparselu2.idx, offs2+m, _state); - rvectorgrowto(&s->sparselu2.vals, offs2+m, _state); - - /* - * Extract K-th row of the SparseLU1/2 (I-th row of the original matrix) - */ - i = s->rowpermbwd.ptr.p_int[k+nlogical]; - j0 = at->ridx.ptr.p_int[s->idx.ptr.p_int[i]]; - j1 = at->ridx.ptr.p_int[s->idx.ptr.p_int[i]+1]-1; - for(j=j0; j<=j1; j++) - { - k1 = s->tcinvidx.ptr.p_int[at->idx.ptr.p_int[j]]; - if( k1sparselu1.idx.ptr.p_int[offs1] = k1; - s->sparselu1.vals.ptr.p_double[offs1] = at->vals.ptr.p_double[j]; - offs1 = offs1+1; - } - else - { - - /* - * Append element to SparseLU2 - */ - s->sparselu2.idx.ptr.p_int[offs2] = k1-nlogical; - s->sparselu2.vals.ptr.p_double[offs2] = at->vals.ptr.p_double[j]; - offs2 = offs2+1; - } - } - - /* - * Elements added to the last row of LU1 can be unordered, - * so it needs resorting. - * - * LU2 does NOT need resorting because trailing NStructural - * elements of permutation were post-sorted to produce - * already sorted results. - */ - tagsortmiddleir(&s->sparselu1.idx, &s->sparselu1.vals, s->sparselu1.ridx.ptr.p_int[k], offs1-s->sparselu1.ridx.ptr.p_int[k], _state); - s->sparselu1.ridx.ptr.p_int[k+1] = offs1; - s->sparselu2.ridx.ptr.p_int[k+1] = offs2; - } - s->sparselu1.ninitialized = s->sparselu1.ridx.ptr.p_int[nstructural]; - s->sparselu2.ninitialized = s->sparselu2.ridx.ptr.p_int[nstructural]; - sparseinitduidx(&s->sparselu1, _state); - sparseinitduidx(&s->sparselu2, _state); - if( nstructural>0 ) - { - sptrflu(&s->sparselu2, 2, &s->densep2, &s->densep2c, &s->lubuf2, _state); - for(i=0; i<=nstructural-1; i++) - { - j = s->rowpermbwd.ptr.p_int[i+nlogical]; - s->rowpermbwd.ptr.p_int[i+nlogical] = s->rowpermbwd.ptr.p_int[s->densep2.ptr.p_int[i]+nlogical]; - s->rowpermbwd.ptr.p_int[s->densep2.ptr.p_int[i]+nlogical] = j; - j = s->colpermbwd.ptr.p_int[i+nlogical]; - s->colpermbwd.ptr.p_int[i+nlogical] = s->colpermbwd.ptr.p_int[s->densep2c.ptr.p_int[i]+nlogical]; - s->colpermbwd.ptr.p_int[s->densep2c.ptr.p_int[i]+nlogical] = j; - } - - /* - * Process L factor: - * - * 1. count number of non-zeros in the L factor, - * 2. fill NLogical*NLogical leading block - * 3. NStructural*M bottom block - */ - nzl = nlogical; - for(i=0; i<=nstructural-1; i++) - { - k = s->lubuf2.rowpermrawidx.ptr.p_int[i]; - nzl = nzl+(s->sparselu1.ridx.ptr.p_int[k+1]-s->sparselu1.ridx.ptr.p_int[k]); - nzl = nzl+1+(s->sparselu2.didx.ptr.p_int[i]-s->sparselu2.ridx.ptr.p_int[i]); - } - rvectorsetlengthatleast(&s->sparsel.vals, nzl, _state); - ivectorsetlengthatleast(&s->sparsel.idx, nzl, _state); - ivectorsetlengthatleast(&s->sparsel.ridx, m+1, _state); - ivectorsetlengthatleast(&s->sparsel.didx, m, _state); - ivectorsetlengthatleast(&s->sparsel.uidx, m, _state); - s->sparsel.matrixtype = 1; - s->sparsel.m = m; - s->sparsel.n = m; - s->sparsel.ninitialized = nzl; - s->sparsel.ridx.ptr.p_int[0] = 0; - for(i=0; i<=nlogical-1; i++) - { - s->sparsel.idx.ptr.p_int[i] = i; - s->sparsel.vals.ptr.p_double[i] = 1.0; - s->sparsel.ridx.ptr.p_int[i+1] = i+1; - } - for(i=0; i<=nstructural-1; i++) - { - offs = s->sparsel.ridx.ptr.p_int[nlogical+i]; - k = s->lubuf2.rowpermrawidx.ptr.p_int[i]; - j0 = s->sparselu1.ridx.ptr.p_int[k]; - j1 = s->sparselu1.ridx.ptr.p_int[k+1]-1; - for(j=j0; j<=j1; j++) - { - s->sparsel.idx.ptr.p_int[offs] = s->sparselu1.idx.ptr.p_int[j]; - s->sparsel.vals.ptr.p_double[offs] = -s->sparselu1.vals.ptr.p_double[j]; - offs = offs+1; - } - j0 = s->sparselu2.ridx.ptr.p_int[i]; - j1 = s->sparselu2.didx.ptr.p_int[i]-1; - for(j=j0; j<=j1; j++) - { - s->sparsel.idx.ptr.p_int[offs] = nlogical+s->sparselu2.idx.ptr.p_int[j]; - s->sparsel.vals.ptr.p_double[offs] = s->sparselu2.vals.ptr.p_double[j]; - offs = offs+1; - } - s->sparsel.idx.ptr.p_int[offs] = nlogical+i; - s->sparsel.vals.ptr.p_double[offs] = 1.0; - offs = offs+1; - s->sparsel.ridx.ptr.p_int[nlogical+i+1] = offs; - } - ae_assert(s->sparsel.ninitialized==s->sparsel.ridx.ptr.p_int[m], "BasisFreshTrf: integrity check failed", _state); - sparseinitduidx(&s->sparsel, _state); - - /* - * Process U factor: - * - * 1. count number of non-zeros in the U factor, - * 2. fill NLogical*NLogical leading block - * 3. NStructural*NStructural bottom block - */ - nzu = nlogical; - for(i=0; i<=nstructural-1; i++) - { - nzu = nzu+1+(s->sparselu2.ridx.ptr.p_int[i+1]-s->sparselu2.uidx.ptr.p_int[i]); - } - rvectorsetlengthatleast(&s->sparseu.vals, nzu, _state); - ivectorsetlengthatleast(&s->sparseu.idx, nzu, _state); - ivectorsetlengthatleast(&s->sparseu.ridx, m+1, _state); - ivectorsetlengthatleast(&s->sparseu.didx, m, _state); - ivectorsetlengthatleast(&s->sparseu.uidx, m, _state); - s->sparseu.matrixtype = 1; - s->sparseu.m = m; - s->sparseu.n = m; - s->sparseu.ninitialized = nzu; - s->sparseu.ridx.ptr.p_int[0] = 0; - for(i=0; i<=nlogical-1; i++) - { - s->sparseu.idx.ptr.p_int[i] = i; - s->sparseu.vals.ptr.p_double[i] = -1.0; - s->sparseu.ridx.ptr.p_int[i+1] = i+1; - } - for(i=0; i<=nstructural-1; i++) - { - offs = s->sparseu.ridx.ptr.p_int[nlogical+i]; - s->sparseu.idx.ptr.p_int[offs] = nlogical+i; - j = s->sparselu2.didx.ptr.p_int[i]; - if( jsparselu2.uidx.ptr.p_int[i] ) - { - ae_assert(s->sparselu2.idx.ptr.p_int[j]==i, "BasisFreshTrf: integrity check failed", _state); - s->sparseu.vals.ptr.p_double[offs] = s->sparselu2.vals.ptr.p_double[j]; - } - else - { - s->sparseu.vals.ptr.p_double[offs] = (double)(0); - } - offs = offs+1; - j0 = s->sparselu2.uidx.ptr.p_int[i]; - j1 = s->sparselu2.ridx.ptr.p_int[i+1]-1; - for(j=j0; j<=j1; j++) - { - s->sparseu.idx.ptr.p_int[offs] = nlogical+s->sparselu2.idx.ptr.p_int[j]; - s->sparseu.vals.ptr.p_double[offs] = s->sparselu2.vals.ptr.p_double[j]; - offs = offs+1; - } - s->sparseu.ridx.ptr.p_int[nlogical+i+1] = offs; - } - ae_assert(s->sparseu.ninitialized==s->sparseu.ridx.ptr.p_int[m], "BasisFreshTrf: integrity check failed", _state); - sparseinitduidx(&s->sparseu, _state); - } - else - { - ivectorsetlengthatleast(&s->nrs, m, _state); - for(i=0; i<=m-1; i++) - { - s->nrs.ptr.p_int[i] = 1; - } - sparsecreatecrsbuf(m, m, &s->nrs, &s->sparsel, _state); - for(i=0; i<=nlogical-1; i++) - { - sparseset(&s->sparsel, i, i, 1.0, _state); - } - sparsecreatecrsbuf(m, m, &s->nrs, &s->sparseu, _state); - for(i=0; i<=nlogical-1; i++) - { - sparseset(&s->sparseu, i, i, -1.0, _state); - } - } - sparsecopytransposecrsbuf(&s->sparseu, &s->sparseut, _state); - s->isvalidtrf = ae_true; - s->trfage = 0; - s->statfact = s->statfact+1; - s->statoffdiag = s->statoffdiag+(s->sparsel.ridx.ptr.p_int[m]-m)+(s->sparseu.ridx.ptr.p_int[m]-m); - result = reviseddualsimplex_basisminimumdiagonalelement(s, _state); - return result; - } - - /* - * - */ - ae_assert(ae_false, "BasisFreshTrf: unexpected TRF type", _state); - return result; -} - - -/************************************************************************* -This function fills S.DSEWeights by actual weights according to current -settings and sets validity flag. - -Basis object MUST store valid triangular factorization, otherwise this -function throws an exception. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_basisrequestweights(dualsimplexbasis* s, - dualsimplexsettings* settings, - ae_state *_state) -{ - ae_int_t m; - ae_int_t ns; - ae_int_t i; - ae_int_t j; - double v; - double vv; - - - m = s->m; - ns = s->ns; - ae_assert((settings->pricing==-1||settings->pricing==0)||settings->pricing==1, "BasisRequestWeights: unknown pricing type", _state); - ae_assert(s->isvalidtrf, "BasisRequestWeights: factorization is not computed prior to calling this function", _state); - - /* - * If weights are valid, return immediately - */ - if( s->dsevalid ) - { - return; - } - - /* - * Compute weights from scratch - */ - if( settings->pricing==-1||settings->pricing==1 ) - { - for(i=0; i<=m-1; i++) - { - if( s->idx.ptr.p_int[i]wtmp0, m, _state); - rvectorsetlengthatleast(&s->wtmp1, m, _state); - for(j=0; j<=m-1; j++) - { - s->wtmp0.ptr.p_double[j] = (double)(0); - } - s->wtmp0.ptr.p_double[i] = (double)(1); - reviseddualsimplex_basissolvet(s, &s->wtmp0, &s->wtmp1, &s->wtmp2, _state); - v = (double)(0); - for(j=0; j<=m-1; j++) - { - vv = s->wtmp1.ptr.p_double[j]; - v = v+vv*vv; - } - s->dseweights.ptr.p_double[i] = v; - } - else - { - - /* - * Logical variable, weight can be set to 1.0 - */ - s->dseweights.ptr.p_double[i] = 1.0; - } - } - s->dsevalid = ae_true; - return; - } - - /* - * Compute weights from scratch - */ - if( settings->pricing==0 ) - { - for(i=0; i<=m-1; i++) - { - s->dseweights.ptr.p_double[i] = 1.0; - } - s->dsevalid = ae_true; - return; - } - ae_assert(ae_false, "BasisRequestWeights: unexpected pricing type", _state); -} - - -/************************************************************************* -This function updates triangular factorization by adding Q to basis and -removing P from basis. It also updates index tables IsBasic[], BasicIdx[], -Basis.NIdx[]. - -AlphaQim contains intermediate result from Ftran for AlphaQ, it is used -by Forest-Tomlin update scheme. If other update is used, it is not referenced -at all. - -X[], D[], Z are NOT recomputed. - -Tau is used if Settings.Pricing=1, ignored otherwise. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_basisupdatetrf(dualsimplexbasis* s, - sparsematrix* at, - ae_int_t p, - ae_int_t q, - /* Real */ ae_vector* alphaq, - /* Real */ ae_vector* alphaqim, - ae_int_t r, - /* Real */ ae_vector* tau, - dualsimplexsettings* settings, - ae_state *_state) -{ - ae_int_t m; - ae_int_t nn; - ae_int_t i; - ae_int_t j; - ae_bool processed; - double invaq; - ae_int_t dstoffs; - ae_int_t srcoffs; - ae_int_t srcidx; - double srcval; - double vcorner; - ae_int_t idxd; - double v; - - - m = s->m; - nn = s->ns; - - /* - * Update index tables - * - * TODO: better code!!!!!!!!!!!!!!!!!!!!!!! - */ - s->isbasic.ptr.p_bool[p] = ae_false; - s->isbasic.ptr.p_bool[q] = ae_true; - for(i=0; i<=m-1; i++) - { - if( s->idx.ptr.p_int[i]==p ) - { - s->idx.ptr.p_int[i] = q; - break; - } - } - for(i=0; i<=nn-1; i++) - { - if( s->nidx.ptr.p_int[i]==q ) - { - s->nidx.ptr.p_int[i] = p; - break; - } - } - - /* - * Update dense factorization - */ - if( ((s->trftype!=settings->trftype||s->trftype==0)||!s->isvalidtrf)||s->trfage>=settings->maxtrfage ) - { - - /* - * Complete refresh is needed for factorization - */ - s->isvalidtrf = ae_false; - reviseddualsimplex_basisfreshtrf(s, at, settings, _state); - } - else - { - processed = ae_false; - if( (s->trftype==0||s->trftype==1)||s->trftype==2 ) - { - - /* - * Dense/sparse factorizations with dense PFI - */ - ae_assert(ae_fp_neq(alphaq->ptr.p_double[r],(double)(0)), "BasisUpdateTrf: integrity check failed, AlphaQ[R]=0", _state); - rvectorgrowto(&s->densepfieta, (s->trfage+1)*m, _state); - ivectorgrowto(&s->rk, s->trfage+1, _state); - s->rk.ptr.p_int[s->trfage] = r; - invaq = 1.0/alphaq->ptr.p_double[r]; - for(i=0; i<=m-1; i++) - { - if( i!=r ) - { - s->densepfieta.ptr.p_double[s->trfage*m+i] = -alphaq->ptr.p_double[i]*invaq; - } - else - { - s->densepfieta.ptr.p_double[s->trfage*m+i] = invaq; - } - } - inc(&s->trfage, _state); - s->statupdt = s->statupdt+1; - s->statoffdiag = s->statoffdiag+ae_sqr((double)(m-1), _state); - processed = ae_true; - } - if( s->trftype==3 ) - { - - /* - * Sparse factorization with Forest-Tomlin update - */ - ae_assert(ae_fp_neq(alphaq->ptr.p_double[r],(double)(0)), "BasisUpdateTrf: integrity check failed, AlphaQ[R]=0", _state); - rvectorgrowto(&s->densemu, (s->trfage+1)*m, _state); - ivectorgrowto(&s->rk, s->trfage+1, _state); - ivectorgrowto(&s->dk, s->trfage+1, _state); - rvectorsetlengthatleast(&s->utmp0, m, _state); - - /* - * Determine D - index of row being overwritten by Forest-Tomlin update - */ - idxd = -1; - for(i=0; i<=m-1; i++) - { - if( s->rowpermbwd.ptr.p_int[i]==r ) - { - idxd = i; - break; - } - } - ae_assert(idxd>=0, "BasisUpdateTrf: unexpected integrity check failure", _state); - s->rk.ptr.p_int[s->trfage] = r; - s->dk.ptr.p_int[s->trfage] = idxd; - - /* - * Modify L with permutation which moves D-th row/column to the end: - * * rows 0...D-1 are left intact - * * rows D+1...M-1 are moved one position up, with columns 0..D-1 - * retained as is, and columns D+1...M-1 being moved one position left. - * * last row is filled by permutation/modification of AlphaQim - * Determine FT update coefficients in the process. - */ - ivectorgrowto(&s->sparsel.idx, s->sparsel.ridx.ptr.p_int[m]+m, _state); - rvectorgrowto(&s->sparsel.vals, s->sparsel.ridx.ptr.p_int[m]+m, _state); - for(i=0; i<=m-1; i++) - { - s->utmp0.ptr.p_double[i] = (double)(0); - } - for(i=idxd+1; i<=m-1; i++) - { - j = s->sparsel.ridx.ptr.p_int[i+1]-1; - if( s->sparsel.idx.ptr.p_int[j]!=i||s->sparsel.vals.ptr.p_double[j]!=1 ) - { - ae_assert(ae_false, "UpdateTrf: integrity check failed for sparse L", _state); - } - dstoffs = s->sparsel.ridx.ptr.p_int[i-1]; - srcoffs = s->sparsel.ridx.ptr.p_int[i]; - - /* - * Read first element in the row (it has at least one - unit diagonal) - */ - srcidx = s->sparsel.idx.ptr.p_int[srcoffs]; - srcval = s->sparsel.vals.ptr.p_double[srcoffs]; - - /* - * Read/write columns 0...D-1 - */ - while(srcidxsparsel.idx.ptr.p_int[dstoffs] = srcidx; - s->sparsel.vals.ptr.p_double[dstoffs] = srcval; - dstoffs = dstoffs+1; - srcoffs = srcoffs+1; - srcidx = s->sparsel.idx.ptr.p_int[srcoffs]; - srcval = s->sparsel.vals.ptr.p_double[srcoffs]; - } - - /* - * If we have non-zero element in column D, use it as - * right-hand side of intermediate linear system which - * is used to determine coefficients of update matrix. - */ - if( srcidx==idxd ) - { - s->utmp0.ptr.p_double[i-1] = srcval; - srcoffs = srcoffs+1; - srcidx = s->sparsel.idx.ptr.p_int[srcoffs]; - srcval = s->sparsel.vals.ptr.p_double[srcoffs]; - } - - /* - * Process columns D+1...I-1 - */ - v = s->utmp0.ptr.p_double[i-1]; - while(srcidxsparsel.idx.ptr.p_int[dstoffs] = srcidx-1; - s->sparsel.vals.ptr.p_double[dstoffs] = srcval; - v = v-srcval*s->utmp0.ptr.p_double[srcidx-1]; - dstoffs = dstoffs+1; - srcoffs = srcoffs+1; - srcidx = s->sparsel.idx.ptr.p_int[srcoffs]; - srcval = s->sparsel.vals.ptr.p_double[srcoffs]; - } - s->utmp0.ptr.p_double[i-1] = v; - - /* - * Write out unit diagonal, finalize row - */ - s->sparsel.idx.ptr.p_int[dstoffs] = i-1; - s->sparsel.vals.ptr.p_double[dstoffs] = (double)(1); - dstoffs = dstoffs+1; - s->sparsel.ridx.ptr.p_int[i] = dstoffs; - } - s->utmp0.ptr.p_double[m-1] = (double)(1); - dstoffs = s->sparsel.ridx.ptr.p_int[m-1]; - for(j=0; j<=idxd-1; j++) - { - v = alphaqim->ptr.p_double[j]; - if( v!=0 ) - { - s->sparsel.idx.ptr.p_int[dstoffs] = j; - s->sparsel.vals.ptr.p_double[dstoffs] = v; - dstoffs = dstoffs+1; - } - } - vcorner = alphaqim->ptr.p_double[idxd]; - for(j=idxd+1; j<=m-1; j++) - { - v = alphaqim->ptr.p_double[j]; - if( v!=0 ) - { - s->sparsel.idx.ptr.p_int[dstoffs] = j-1; - s->sparsel.vals.ptr.p_double[dstoffs] = v; - dstoffs = dstoffs+1; - vcorner = vcorner-v*s->utmp0.ptr.p_double[j-1]; - } - } - s->sparsel.idx.ptr.p_int[dstoffs] = m-1; - s->sparsel.vals.ptr.p_double[dstoffs] = (double)(1); - dstoffs = dstoffs+1; - s->sparsel.ridx.ptr.p_int[m] = dstoffs; - s->sparsel.ninitialized = s->sparsel.ridx.ptr.p_int[m]; - for(i=0; i<=m-1; i++) - { - j = s->sparsel.ridx.ptr.p_int[i+1]; - s->sparsel.didx.ptr.p_int[i] = j-1; - s->sparsel.uidx.ptr.p_int[i] = j; - } - ae_assert(vcorner!=0, "UpdateTrf: corner element is zero, degeneracy detected", _state); - v = 1/vcorner; - for(i=0; i<=m-2; i++) - { - s->densemu.ptr.p_double[s->trfage*m+i] = -s->utmp0.ptr.p_double[i]*v; - } - s->densemu.ptr.p_double[s->trfage*m+m-1] = v; - - /* - * Multiply row permutation matrix by cyclic permutation applied to L - */ - reviseddualsimplex_inversecyclicpermutation(&s->rowpermbwd, m, idxd, &s->utmpi, _state); - - /* - * Done - */ - inc(&s->trfage, _state); - s->statupdt = s->statupdt+1; - s->statoffdiag = s->statoffdiag+(s->sparsel.ridx.ptr.p_int[m]-m)+(s->sparseu.ridx.ptr.p_int[m]-m); - processed = ae_true; - } - ae_assert(processed, "BasisUpdateTrf: unexpected TRF type", _state); - } - - /* - * Update pricing weights - */ - ae_assert((settings->pricing==-1||settings->pricing==0)||settings->pricing==1, "BasisUpdateTrf: unexpected Settings.Pricing", _state); - processed = ae_false; - if( settings->pricing==-1 ) - { - - /* - * Weights are recomputed from scratch at every step. - * VERY, VERY time consuming, used only for debug purposes. - */ - s->dsevalid = ae_false; - reviseddualsimplex_basisrequestweights(s, settings, _state); - processed = ae_true; - } - if( settings->pricing==0 ) - { - - /* - * Weights are filled by 1.0 - */ - if( !s->dsevalid ) - { - for(i=0; i<=m-1; i++) - { - s->dseweights.ptr.p_double[i] = 1.0; - } - s->dsevalid = ae_true; - } - processed = ae_true; - } - if( settings->pricing==1 ) - { - - /* - * Weights are computed using DSE update formula. - */ - if( s->dsevalid ) - { - - /* - * Compute using update formula - */ - for(i=0; i<=m-1; i++) - { - if( i!=r ) - { - s->dseweights.ptr.p_double[i] = s->dseweights.ptr.p_double[i]-2*(alphaq->ptr.p_double[i]/alphaq->ptr.p_double[r])*tau->ptr.p_double[i]+s->dseweights.ptr.p_double[r]*ae_sqr(alphaq->ptr.p_double[i]/alphaq->ptr.p_double[r], _state); - s->dseweights.ptr.p_double[i] = ae_maxreal(s->dseweights.ptr.p_double[i], reviseddualsimplex_minbeta, _state); - } - } - s->dseweights.ptr.p_double[r] = s->dseweights.ptr.p_double[r]/(alphaq->ptr.p_double[r]*alphaq->ptr.p_double[r]); - } - else - { - - /* - * No prior values, compute from scratch (usually it is done only once) - */ - reviseddualsimplex_basisrequestweights(s, settings, _state); - } - processed = ae_true; - } - ae_assert(processed, "BasisUpdateTrf: unexpected pricing type", _state); -} - - -/************************************************************************* -This function computes solution to B*x=r. - -Output array is reallocated if needed. Temporary array TmpX[] is used and -reallocated if necessary. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_basissolve(dualsimplexbasis* s, - /* Real */ ae_vector* r, - /* Real */ ae_vector* x, - /* Real */ ae_vector* tmpx, - ae_state *_state) -{ - - - reviseddualsimplex_basissolvex(s, r, x, x, ae_false, tmpx, _state); -} - - -/************************************************************************* -This function computes solution to B*x=r. It also additionally outputs -intermediate result of multiplication by inv(DS)*inv(U)*inv(colPerm), a -value essential for Forest-Tomlin update. - -Output arrays are reallocated if needed. Temporary array TX[] can be -used/reallocated. - -If NeedIntermediate is False or Forest-Tomlin updates are not used, -then Xim[] is not referenced at all. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_basissolvex(dualsimplexbasis* s, - /* Real */ ae_vector* r, - /* Real */ ae_vector* x, - /* Real */ ae_vector* xim, - ae_bool needintermediate, - /* Real */ ae_vector* tx, - ae_state *_state) -{ - ae_int_t m; - ae_int_t i; - ae_int_t d; - ae_int_t k; - double v; - double vd; - double vv; - ae_bool processed; - - - ae_assert(s->isvalidtrf, "BasisSolve: integrity check failed", _state); - m = s->m; - processed = ae_false; - rvectorsetlengthatleast(tx, m, _state); - - /* - * Dense/sparse factorizations with dense PFI - * - * NOTE: although we solve B*x=r, internally we store factorization of B^T - */ - if( (s->trftype==0||s->trftype==1)||s->trftype==2 ) - { - ae_assert(s->trfage==0||s->trftype!=0, "BasisSolve: integrity check failed TrfAge vs TrfType", _state); - rvectorsetlengthatleast(x, m, _state); - for(i=0; i<=m-1; i++) - { - x->ptr.p_double[i] = r->ptr.p_double[s->colpermbwd.ptr.p_int[i]]; - } - if( s->trftype==0||s->trftype==1 ) - { - - /* - * Dense TRF - */ - rmatrixtrsv(m, &s->denselu, 0, 0, ae_true, ae_false, 1, x, 0, _state); - rmatrixtrsv(m, &s->denselu, 0, 0, ae_false, ae_true, 1, x, 0, _state); - } - else - { - - /* - * Sparse TRF - */ - sparsetrsv(&s->sparseu, ae_true, ae_false, 1, x, _state); - sparsetrsv(&s->sparsel, ae_false, ae_false, 1, x, _state); - } - for(i=0; i<=m-1; i++) - { - tx->ptr.p_double[s->rowpermbwd.ptr.p_int[i]] = x->ptr.p_double[i]; - } - for(i=0; i<=m-1; i++) - { - x->ptr.p_double[i] = tx->ptr.p_double[i]; - } - for(k=0; k<=s->trfage-1; k++) - { - v = x->ptr.p_double[s->rk.ptr.p_int[k]]; - for(i=0; i<=m-1; i++) - { - x->ptr.p_double[i] = x->ptr.p_double[i]+s->densepfieta.ptr.p_double[k*m+i]*v; - } - x->ptr.p_double[s->rk.ptr.p_int[k]] = x->ptr.p_double[s->rk.ptr.p_int[k]]-v; - } - processed = ae_true; - } - - /* - * Sparse factorization with Forest-Tomlin update - * - * NOTE: although we solve B*x=r, internally we store factorization of B^T - */ - if( s->trftype==3 ) - { - rvectorsetlengthatleast(x, m, _state); - for(i=0; i<=m-1; i++) - { - x->ptr.p_double[i] = r->ptr.p_double[s->colpermbwd.ptr.p_int[i]]; - } - sparsetrsv(&s->sparseu, ae_true, ae_false, 1, x, _state); - for(k=0; k<=s->trfage-1; k++) - { - - /* - * The code below is an amalgamation of two parts: - * - * cyclic permutation - * V:=X[D]; - * for I:=D to M-2 do - * X[I]:=X[I+1]; - * X[M-1]:=V; - * - * and triangular factor - * V:=0; - * for I:=D to M-1 do - * V:=V+X[I]*S.DenseMu[K*M+I]; - * X[M-1]:=V; - */ - d = s->dk.ptr.p_int[k]; - vv = (double)(0); - vd = x->ptr.p_double[d]; - for(i=d; i<=m-2; i++) - { - v = x->ptr.p_double[i+1]; - x->ptr.p_double[i] = v; - vv = vv+v*s->densemu.ptr.p_double[k*m+i]; - } - x->ptr.p_double[m-1] = vv+vd*s->densemu.ptr.p_double[k*m+m-1]; - } - if( needintermediate ) - { - rvectorsetlengthatleast(xim, m, _state); - for(i=0; i<=m-1; i++) - { - xim->ptr.p_double[i] = x->ptr.p_double[i]; - } - } - sparsetrsv(&s->sparsel, ae_false, ae_false, 1, x, _state); - for(i=0; i<=m-1; i++) - { - tx->ptr.p_double[s->rowpermbwd.ptr.p_int[i]] = x->ptr.p_double[i]; - } - for(i=0; i<=m-1; i++) - { - x->ptr.p_double[i] = tx->ptr.p_double[i]; - } - processed = ae_true; - } - - /* - * Integrity check - */ - ae_assert(processed, "BasisSolve: unsupported TRF type", _state); - v = (double)(0); - for(i=0; i<=m-1; i++) - { - v = v+x->ptr.p_double[i]; - } - ae_assert(ae_isfinite(v, _state), "BasisSolve: integrity check failed (degeneracy in B?)", _state); -} - - -/************************************************************************* -This function computes solution to (B^T)*x=r. - -Output array is reallocated if needed. TX[] temporary is reallocated if -needed - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_basissolvet(dualsimplexbasis* s, - /* Real */ ae_vector* r, - /* Real */ ae_vector* x, - /* Real */ ae_vector* tx, - ae_state *_state) -{ - ae_int_t m; - ae_int_t i; - ae_int_t d; - ae_int_t k; - double v; - double vm; - ae_bool processed; - - - ae_assert(s->isvalidtrf, "BasisSolveT: integrity check failed", _state); - m = s->m; - processed = ae_false; - rvectorsetlengthatleast(tx, m, _state); - - /* - * Dense factorizations - */ - if( (s->trftype==0||s->trftype==1)||s->trftype==2 ) - { - ae_assert(s->trfage==0||s->trftype!=0, "BasisSolveT: integrity check failed TrfAge vs TrfType", _state); - rvectorsetlengthatleast(x, m, _state); - for(i=0; i<=m-1; i++) - { - x->ptr.p_double[i] = r->ptr.p_double[i]; - } - for(k=s->trfage-1; k>=0; k--) - { - v = (double)(0); - for(i=0; i<=m-1; i++) - { - v = v+s->densepfieta.ptr.p_double[k*m+i]*x->ptr.p_double[i]; - } - x->ptr.p_double[s->rk.ptr.p_int[k]] = v; - } - for(i=0; i<=m-1; i++) - { - tx->ptr.p_double[i] = x->ptr.p_double[s->rowpermbwd.ptr.p_int[i]]; - } - for(i=0; i<=m-1; i++) - { - x->ptr.p_double[i] = tx->ptr.p_double[i]; - } - if( s->trftype==0||s->trftype==1 ) - { - - /* - * Dense TRF - */ - rmatrixtrsv(m, &s->denselu, 0, 0, ae_false, ae_true, 0, x, 0, _state); - rmatrixtrsv(m, &s->denselu, 0, 0, ae_true, ae_false, 0, x, 0, _state); - } - else - { - - /* - * Sparse TRF - */ - sparsetrsv(&s->sparsel, ae_false, ae_false, 0, x, _state); - sparsetrsv(&s->sparseu, ae_true, ae_false, 0, x, _state); - } - for(i=0; i<=m-1; i++) - { - tx->ptr.p_double[s->colpermbwd.ptr.p_int[i]] = x->ptr.p_double[i]; - } - for(i=0; i<=m-1; i++) - { - x->ptr.p_double[i] = tx->ptr.p_double[i]; - } - processed = ae_true; - } - - /* - * Sparse factorization with Forest-Tomlin update - */ - if( s->trftype==3 ) - { - rvectorsetlengthatleast(x, m, _state); - for(i=0; i<=m-1; i++) - { - x->ptr.p_double[i] = r->ptr.p_double[i]; - } - for(i=0; i<=m-1; i++) - { - tx->ptr.p_double[i] = x->ptr.p_double[s->rowpermbwd.ptr.p_int[i]]; - } - for(i=0; i<=m-1; i++) - { - x->ptr.p_double[i] = tx->ptr.p_double[i]; - } - sparsetrsv(&s->sparsel, ae_false, ae_false, 0, x, _state); - for(k=s->trfage-1; k>=0; k--) - { - - /* - * The code below is an amalgamation of two parts: - * - * triangular factor - * V:=X[M-1]; - * for I:=D to M-2 do - * X[I]:=X[I]+S.DenseMu[K*M+I]*V; - * X[M-1]:=S.DenseMu[K*M+(M-1)]*V; - * - * inverse of cyclic permutation - * V:=X[M-1]; - * for I:=M-1 downto D+1 do - * X[I]:=X[I-1]; - * X[D]:=V; - */ - d = s->dk.ptr.p_int[k]; - vm = x->ptr.p_double[m-1]; - v = s->densemu.ptr.p_double[k*m+(m-1)]*vm; - if( vm!=0 ) - { - - /* - * X[M-1] is non-zero, apply update - */ - for(i=m-2; i>=d; i--) - { - x->ptr.p_double[i+1] = x->ptr.p_double[i]+s->densemu.ptr.p_double[k*m+i]*vm; - } - } - else - { - - /* - * X[M-1] is zero, just cyclic permutation - */ - for(i=m-2; i>=d; i--) - { - x->ptr.p_double[i+1] = x->ptr.p_double[i]; - } - } - x->ptr.p_double[d] = v; - } - sparsetrsv(&s->sparseut, ae_false, ae_false, 1, x, _state); - for(i=0; i<=m-1; i++) - { - tx->ptr.p_double[s->colpermbwd.ptr.p_int[i]] = x->ptr.p_double[i]; - } - for(i=0; i<=m-1; i++) - { - x->ptr.p_double[i] = tx->ptr.p_double[i]; - } - processed = ae_true; - } - - /* - * Integrity check - */ - ae_assert(processed, "BasisSolveT: unsupported TRF type", _state); - v = (double)(0); - for(i=0; i<=m-1; i++) - { - v = v+x->ptr.p_double[i]; - } - ae_assert(ae_isfinite(v, _state), "BasisSolveT: integrity check failed (degeneracy in B?)", _state); -} - - -/************************************************************************* -This function computes product AN*XN, where AN is a non-basic subset of -columns of A, and XN is a non-basic subset of columns of X. - -Output array is reallocated if its size is too small. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_computeanxn(dualsimplexstate* state, - dualsimplexsubproblem* subproblem, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state) -{ - ae_int_t nn; - ae_int_t nx; - ae_int_t m; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t j0; - ae_int_t j1; - double v; - - - nx = subproblem->ns+subproblem->m; - m = subproblem->m; - nn = nx-m; - - /* - * Integrity check - */ - ae_assert(subproblem->state>=reviseddualsimplex_ssvalidxn, "ComputeANXN: XN is invalid", _state); - - /* - * Compute - */ - rvectorsetlengthatleast(y, m, _state); - for(i=0; i<=m-1; i++) - { - y->ptr.p_double[i] = (double)(0); - } - for(i=0; i<=nn-1; i++) - { - j0 = state->at.ridx.ptr.p_int[state->basis.nidx.ptr.p_int[i]]; - j1 = state->at.ridx.ptr.p_int[state->basis.nidx.ptr.p_int[i]+1]-1; - v = x->ptr.p_double[state->basis.nidx.ptr.p_int[i]]; - for(j=j0; j<=j1; j++) - { - k = state->at.idx.ptr.p_int[j]; - y->ptr.p_double[k] = y->ptr.p_double[k]+v*state->at.vals.ptr.p_double[j]; - } - } -} - - -/************************************************************************* -This function computes product (AN^T)*y, where AN is a non-basic subset of -columns of A, and y is some vector. - -Output array is set to full NX-sized length, with basic components of the -output being set to zeros. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_computeantv(dualsimplexstate* state, - /* Real */ ae_vector* y, - /* Real */ ae_vector* r, - ae_state *_state) -{ - ae_int_t nn; - ae_int_t nx; - ae_int_t m; - ae_int_t i; - ae_int_t j; - ae_int_t j0; - ae_int_t j1; - double v; - - - nx = state->ns+state->m; - m = state->m; - nn = nx-m; - - /* - * Allocate output, set to zero - */ - rvectorsetlengthatleast(r, nx, _state); - for(i=0; i<=nx-1; i++) - { - r->ptr.p_double[i] = (double)(0); - } - for(i=0; i<=nn-1; i++) - { - j0 = state->at.ridx.ptr.p_int[state->basis.nidx.ptr.p_int[i]]; - j1 = state->at.ridx.ptr.p_int[state->basis.nidx.ptr.p_int[i]+1]-1; - v = (double)(0); - for(j=j0; j<=j1; j++) - { - v = v+state->at.vals.ptr.p_double[j]*y->ptr.p_double[state->at.idx.ptr.p_int[j]]; - } - r->ptr.p_double[state->basis.nidx.ptr.p_int[i]] = v; - } -} - - -/************************************************************************* -Returns True if I-th lower bound is present - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static ae_bool reviseddualsimplex_hasbndl(dualsimplexsubproblem* subproblem, - ae_int_t i, - ae_state *_state) -{ - ae_int_t k; - ae_bool result; - - - k = subproblem->bndt.ptr.p_int[i]; - result = ae_false; - if( (k==0||k==1)||k==3 ) - { - result = ae_true; - return result; - } - if( k==2||k==4 ) - { - result = ae_false; - return result; - } - ae_assert(ae_false, "HasBndL: integrity check failed", _state); - return result; -} - - -/************************************************************************* -Returns True if I-th upper bound is present - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static ae_bool reviseddualsimplex_hasbndu(dualsimplexsubproblem* subproblem, - ae_int_t i, - ae_state *_state) -{ - ae_int_t k; - ae_bool result; - - - k = subproblem->bndt.ptr.p_int[i]; - result = ae_false; - if( (k==0||k==2)||k==3 ) - { - result = ae_true; - return result; - } - if( k==1||k==4 ) - { - result = ae_false; - return result; - } - ae_assert(ae_false, "HasBndL: integrity check failed", _state); - return result; -} - - -/************************************************************************* -Returns True if I-th variable if free - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static ae_bool reviseddualsimplex_isfree(dualsimplexsubproblem* subproblem, - ae_int_t i, - ae_state *_state) -{ - ae_int_t k; - ae_bool result; - - - k = subproblem->bndt.ptr.p_int[i]; - result = ae_false; - if( ((k==0||k==1)||k==2)||k==3 ) - { - result = ae_false; - return result; - } - if( k==4 ) - { - result = ae_true; - return result; - } - ae_assert(ae_false, "IsFree: integrity check failed", _state); - return result; -} - - -/************************************************************************* -Downgrades problem state to the specified one (if status is lower than one -specified by user, nothing is changed) - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_downgradestate(dualsimplexsubproblem* subproblem, - ae_int_t s, - ae_state *_state) -{ - - - subproblem->state = ae_minint(subproblem->state, s, _state); -} - - -/************************************************************************* -Returns maximum dual infeasibility (only non-basic variables are checked, -we assume that basic variables are good enough). - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static double reviseddualsimplex_dualfeasibilityerror(dualsimplexstate* state, - dualsimplexsubproblem* s, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t nn; - ae_int_t bndt; - double result; - - - nn = s->ns; - ae_assert(s->state==reviseddualsimplex_ssvalid, "DualFeasibilityError: invalid X", _state); - result = (double)(0); - for(i=0; i<=nn-1; i++) - { - j = state->basis.nidx.ptr.p_int[i]; - bndt = s->bndt.ptr.p_int[j]; - if( bndt==reviseddualsimplex_ccfixed ) - { - continue; - } - if( bndt==reviseddualsimplex_ccrange ) - { - if( s->xa.ptr.p_double[j]==s->bndl.ptr.p_double[j] ) - { - result = ae_maxreal(result, -s->d.ptr.p_double[j], _state); - continue; - } - if( s->xa.ptr.p_double[j]==s->bndu.ptr.p_double[j] ) - { - result = ae_maxreal(result, s->d.ptr.p_double[j], _state); - continue; - } - ae_assert(ae_false, "DualFeasibilityError: integrity check failed", _state); - } - if( bndt==reviseddualsimplex_cclower ) - { - ae_assert(s->xa.ptr.p_double[j]==s->bndl.ptr.p_double[j], "DualFeasibilityError: integrity check failed", _state); - result = ae_maxreal(result, -s->d.ptr.p_double[j], _state); - continue; - } - if( bndt==reviseddualsimplex_ccupper ) - { - ae_assert(s->xa.ptr.p_double[j]==s->bndu.ptr.p_double[j], "DualFeasibilityError: integrity check failed", _state); - result = ae_maxreal(result, s->d.ptr.p_double[j], _state); - continue; - } - if( bndt==reviseddualsimplex_ccfree ) - { - result = ae_maxreal(result, ae_fabs(s->d.ptr.p_double[j], _state), _state); - continue; - } - ae_assert(ae_false, "DSSOptimize: integrity check failed (infeasible constraint)", _state); - } - return result; -} - - -/************************************************************************* -Returns True for dual feasible basis (some minor dual feasibility error is -allowed), False otherwise - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -static ae_bool reviseddualsimplex_isdualfeasible(dualsimplexstate* state, - dualsimplexsubproblem* s, - dualsimplexsettings* settings, - ae_state *_state) -{ - ae_bool result; - - - result = ae_fp_less_eq(reviseddualsimplex_dualfeasibilityerror(state, s, _state),settings->dtolabs); - return result; -} - - -/************************************************************************* -Transforms sequence of pivot permutations P0*P1*...*Pm to forward/backward -permutation representation. - - -- ALGLIB -- - Copyright 12.09.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_pivottobwd(/* Integer */ ae_vector* p, - ae_int_t m, - /* Integer */ ae_vector* bwd, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - ae_int_t t; - - - ivectorsetlengthatleast(bwd, m, _state); - for(i=0; i<=m-1; i++) - { - bwd->ptr.p_int[i] = i; - } - for(i=0; i<=m-1; i++) - { - k = p->ptr.p_int[i]; - if( k!=i ) - { - t = bwd->ptr.p_int[i]; - bwd->ptr.p_int[i] = bwd->ptr.p_int[k]; - bwd->ptr.p_int[k] = t; - } - } -} - - -/************************************************************************* -Applies inverse cyclic permutation of [D,M-1) (element D is moved to the end, the -rest of elements is shifted one position backward) to the already existing -permutation. - - -- ALGLIB -- - Copyright 12.09.2018 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_inversecyclicpermutation(/* Integer */ ae_vector* bwd, - ae_int_t m, - ae_int_t d, - /* Integer */ ae_vector* tmpi, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - - - - /* - * update Bwd[] - */ - k = bwd->ptr.p_int[d]; - for(i=d; i<=m-2; i++) - { - bwd->ptr.p_int[i] = bwd->ptr.p_int[i+1]; - } - bwd->ptr.p_int[m-1] = k; -} - - -/************************************************************************* -Offloads basic components of X[], BndT[], BndL[], BndU[] to XB/BndTB/BndLB/BndUB. - - -- ALGLIB -- - Copyright 24.01.2019 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_offloadbasiccomponents(dualsimplexsubproblem* s, - dualsimplexbasis* basis, - dualsimplexsettings* settings, - ae_state *_state) -{ - ae_int_t i; - ae_int_t m; - - - m = basis->m; - for(i=0; i<=m-1; i++) - { - s->xb.ptr.p_double[i] = s->xa.ptr.p_double[basis->idx.ptr.p_int[i]]; - reviseddualsimplex_cacheboundinfo(s, i, basis->idx.ptr.p_int[i], settings, _state); - } -} - - -/************************************************************************* -Recombines basic and non-basic components in X[] - - -- ALGLIB -- - Copyright 24.01.2019 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_recombinebasicnonbasicx(dualsimplexsubproblem* s, - dualsimplexbasis* basis, - ae_state *_state) -{ - ae_int_t m; - ae_int_t i; - - - m = basis->m; - for(i=0; i<=m-1; i++) - { - s->xa.ptr.p_double[basis->idx.ptr.p_int[i]] = s->xb.ptr.p_double[i]; - } -} - - -/************************************************************************* -Computes Stats array - -INPUT PARAMETERS: - S - problem, contains current solution at S.XA - Basis - basis - X - possibly preallocated output buffer - LagBC - possibly preallocated output buffer - LagLC - possibly preallocated output buffer - Stats - possibly preallocated output buffer - Buffers - temporary buffers - -OUTPUT PARAMETERS: - X - array[NS], solution - LagBC - array[NS], Lagrange multipliers for box constraints - LagLC - array[M], Lagrange multipliers for linear constraints - Stats - array[NS+M], primary/slack variable stats: - * -1 = variable at lower bound - * +1 = variable at upper bound - * 0 = basic or free (possibly nonbasic) variable - fixed variables may be set to +1 or -1 - - -- ALGLIB -- - Copyright 24.01.2019 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_setxydstats(dualsimplexstate* state, - dualsimplexsubproblem* s, - dualsimplexbasis* basis, - apbuffers* buffers, - /* Real */ ae_vector* x, - /* Real */ ae_vector* lagbc, - /* Real */ ae_vector* laglc, - /* Integer */ ae_vector* stats, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t m; - ae_int_t ns; - ae_int_t nx; - - - - /* - * Prepare - */ - m = s->m; - ns = s->ns; - nx = s->ns+s->m; - rvectorsetlengthatleast(x, ns, _state); - rvectorsetlengthatleast(laglc, m, _state); - ivectorsetlengthatleast(stats, nx, _state); - rsetallocv(ns, 0.0, lagbc, _state); - - /* - * Compute Y (in Buffers.RA1) and D (in Buffers.RA3) - */ - rvectorsetlengthatleast(&buffers->ra0, m, _state); - rvectorsetlengthatleast(&buffers->ra1, m, _state); - rvectorsetlengthatleast(&buffers->ra3, nx, _state); - for(i=0; i<=m-1; i++) - { - buffers->ra0.ptr.p_double[i] = s->rawc.ptr.p_double[basis->idx.ptr.p_int[i]]; - } - reviseddualsimplex_basissolvet(basis, &buffers->ra0, &buffers->ra1, &buffers->ra2, _state); - reviseddualsimplex_computeantv(state, &buffers->ra1, &buffers->ra3, _state); - for(i=0; i<=ns-1; i++) - { - j = state->basis.nidx.ptr.p_int[i]; - buffers->ra3.ptr.p_double[j] = state->primary.rawc.ptr.p_double[j]-buffers->ra3.ptr.p_double[j]; - if( jptr.p_double[j] = -buffers->ra3.ptr.p_double[j]; - } - } - for(i=0; i<=m-1; i++) - { - buffers->ra3.ptr.p_double[state->basis.idx.ptr.p_int[i]] = (double)(0); - } - - /* - * Compute X, Y, Stats - */ - for(i=0; i<=ns-1; i++) - { - x->ptr.p_double[i] = s->xa.ptr.p_double[i]; - if( ae_isfinite(state->rawbndl.ptr.p_double[i], _state) ) - { - x->ptr.p_double[i] = ae_maxreal(x->ptr.p_double[i], state->rawbndl.ptr.p_double[i], _state); - } - if( ae_isfinite(state->rawbndu.ptr.p_double[i], _state) ) - { - x->ptr.p_double[i] = ae_minreal(x->ptr.p_double[i], state->rawbndu.ptr.p_double[i], _state); - } - } - for(i=0; i<=ns-1; i++) - { - if( basis->isbasic.ptr.p_bool[i] ) - { - lagbc->ptr.p_double[i] = (double)(0); - continue; - } - if( s->bndt.ptr.p_int[i]==reviseddualsimplex_ccfixed ) - { - continue; - } - if( reviseddualsimplex_hasbndl(s, i, _state)&&ae_fp_eq(s->xa.ptr.p_double[i],s->bndl.ptr.p_double[i]) ) - { - lagbc->ptr.p_double[i] = ae_minreal(lagbc->ptr.p_double[i], 0.0, _state); - continue; - } - if( reviseddualsimplex_hasbndu(s, i, _state)&&ae_fp_eq(s->xa.ptr.p_double[i],s->bndu.ptr.p_double[i]) ) - { - lagbc->ptr.p_double[i] = ae_maxreal(lagbc->ptr.p_double[i], 0.0, _state); - continue; - } - ae_assert(!reviseddualsimplex_hasbndl(s, i, _state)&&!reviseddualsimplex_hasbndu(s, i, _state), "SetStats: integrity check failed (zetta5)", _state); - lagbc->ptr.p_double[i] = (double)(0); - } - for(i=0; i<=m-1; i++) - { - laglc->ptr.p_double[i] = -buffers->ra1.ptr.p_double[i]/state->rowscales.ptr.p_double[i]; - } - for(i=0; i<=nx-1; i++) - { - if( basis->isbasic.ptr.p_bool[i] ) - { - stats->ptr.p_int[i] = 0; - continue; - } - if( reviseddualsimplex_hasbndl(s, i, _state)&&ae_fp_eq(s->xa.ptr.p_double[i],s->bndl.ptr.p_double[i]) ) - { - stats->ptr.p_int[i] = -1; - continue; - } - if( reviseddualsimplex_hasbndu(s, i, _state)&&ae_fp_eq(s->xa.ptr.p_double[i],s->bndu.ptr.p_double[i]) ) - { - stats->ptr.p_int[i] = 1; - continue; - } - ae_assert(!reviseddualsimplex_hasbndl(s, i, _state)&&!reviseddualsimplex_hasbndu(s, i, _state), "SetStats: integrity check failed (zetta5)", _state); - stats->ptr.p_int[i] = 0; - } -} - - -/************************************************************************* -Initializes vector, sets all internal arrays to length N (so that we may -store any vector without reallocation). Previously allocated memory is -reused as much as possible. - -No zero-filling is performed, X.K is undefined. Only X.N is set. - -INPUT PARAMETERS: - X - temporary buffers - -OUTPUT PARAMETERS: - X - preallocated vector, X.N=N, contents undefined - - -- ALGLIB -- - Copyright 24.07.2020 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_dvalloc(dssvector* x, - ae_int_t n, - ae_state *_state) -{ - - - ivectorsetlengthatleast(&x->idx, n, _state); - rvectorsetlengthatleast(&x->vals, n, _state); - rvectorsetlengthatleast(&x->dense, n, _state); - x->n = n; -} - - -/************************************************************************* -Initializes vector, sets all internal arrays to length N and zero-fills -them. Previously allocated memory is reused as much as possible. - -INPUT PARAMETERS: - X - temporary buffers - -OUTPUT PARAMETERS: - X - preallocated vector: - * X.N=N - * X.K=0 - * X.Dense is zero-filled. - - -- ALGLIB -- - Copyright 24.07.2020 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_dvinit(dssvector* x, - ae_int_t n, - ae_state *_state) -{ - - - ivectorsetlengthatleast(&x->idx, n, _state); - rvectorsetlengthatleast(&x->vals, n, _state); - rvectorsetlengthatleast(&x->dense, n, _state); - rsetv(n, 0.0, &x->dense, _state); - x->n = n; - x->k = 0; -} - - -/************************************************************************* -Copies dense part to sparse one. - -INPUT PARAMETERS: - X - allocated vector; dense part must be valid - -OUTPUT PARAMETERS: - X - both dense and sparse parts are valid. - - -- ALGLIB -- - Copyright 24.07.2020 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_dvdensetosparse(dssvector* x, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - ae_int_t k; - double v; - - - n = x->n; - ivectorsetlengthatleast(&x->idx, n, _state); - rvectorsetlengthatleast(&x->vals, n, _state); - k = 0; - for(i=0; i<=n-1; i++) - { - v = x->dense.ptr.p_double[i]; - if( v!=0.0 ) - { - x->idx.ptr.p_int[k] = i; - x->vals.ptr.p_double[k] = v; - k = k+1; - } - } - x->k = k; -} - - -/************************************************************************* -Copies sparse part to dense one. - -INPUT PARAMETERS: - X - allocated vector; sparse part must be valid - -OUTPUT PARAMETERS: - X - both dense and sparse parts are valid. - - -- ALGLIB -- - Copyright 24.07.2020 by Bochkanov Sergey -*************************************************************************/ -static void reviseddualsimplex_dvsparsetodense(dssvector* x, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - ae_int_t k; - - - n = x->n; - k = x->k; - rsetv(n, 0.0, &x->dense, _state); - for(i=0; i<=k-1; i++) - { - x->dense.ptr.p_double[x->idx.ptr.p_int[i]] = x->vals.ptr.p_double[i]; - } -} - - -static double reviseddualsimplex_sparsityof(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - double mx; - double result; - - - if( n<=1 ) - { - result = (double)(0); - return result; - } - mx = 1.0; - for(i=0; i<=n-1; i++) - { - mx = ae_maxreal(mx, ae_fabs(x->ptr.p_double[i], _state), _state); - } - mx = 1.0E5*ae_machineepsilon*mx; - k = 0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(ae_fabs(x->ptr.p_double[i], _state),mx) ) - { - k = k+1; - } - } - result = (double)k/(double)n; - return result; -} - - -static void reviseddualsimplex_updateavgcounter(double v, - double* acc, - ae_int_t* cnt, - ae_state *_state) -{ - - - *acc = *acc+v; - *cnt = *cnt+1; -} - - -void _dualsimplexsettings_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - dualsimplexsettings *p = (dualsimplexsettings*)_p; - ae_touch_ptr((void*)p); -} - - -void _dualsimplexsettings_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - dualsimplexsettings *dst = (dualsimplexsettings*)_dst; - dualsimplexsettings *src = (dualsimplexsettings*)_src; - dst->pivottol = src->pivottol; - dst->perturbmag = src->perturbmag; - dst->maxtrfage = src->maxtrfage; - dst->trftype = src->trftype; - dst->ratiotest = src->ratiotest; - dst->pricing = src->pricing; - dst->shifting = src->shifting; - dst->xtolabs = src->xtolabs; - dst->xtolrelabs = src->xtolrelabs; - dst->dtolabs = src->dtolabs; -} - - -void _dualsimplexsettings_clear(void* _p) -{ - dualsimplexsettings *p = (dualsimplexsettings*)_p; - ae_touch_ptr((void*)p); -} - - -void _dualsimplexsettings_destroy(void* _p) -{ - dualsimplexsettings *p = (dualsimplexsettings*)_p; - ae_touch_ptr((void*)p); -} - - -void _dssvector_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - dssvector *p = (dssvector*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->idx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->vals, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dense, 0, DT_REAL, _state, make_automatic); -} - - -void _dssvector_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - dssvector *dst = (dssvector*)_dst; - dssvector *src = (dssvector*)_src; - dst->n = src->n; - dst->k = src->k; - ae_vector_init_copy(&dst->idx, &src->idx, _state, make_automatic); - ae_vector_init_copy(&dst->vals, &src->vals, _state, make_automatic); - ae_vector_init_copy(&dst->dense, &src->dense, _state, make_automatic); -} - - -void _dssvector_clear(void* _p) -{ - dssvector *p = (dssvector*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->idx); - ae_vector_clear(&p->vals); - ae_vector_clear(&p->dense); -} - - -void _dssvector_destroy(void* _p) -{ - dssvector *p = (dssvector*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->idx); - ae_vector_destroy(&p->vals); - ae_vector_destroy(&p->dense); -} - - -void _dualsimplexbasis_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - dualsimplexbasis *p = (dualsimplexbasis*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->idx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->nidx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->isbasic, 0, DT_BOOL, _state, make_automatic); - ae_matrix_init(&p->denselu, 0, 0, DT_REAL, _state, make_automatic); - _sparsematrix_init(&p->sparsel, _state, make_automatic); - _sparsematrix_init(&p->sparseu, _state, make_automatic); - _sparsematrix_init(&p->sparseut, _state, make_automatic); - ae_vector_init(&p->rowpermbwd, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->colpermbwd, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->densepfieta, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->densemu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rk, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->dk, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->dseweights, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->wtmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->wtmp1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->wtmp2, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->nrs, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->tcinvidx, 0, DT_INT, _state, make_automatic); - ae_matrix_init(&p->denselu2, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->densep2, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->densep2c, 0, DT_INT, _state, make_automatic); - _sparsematrix_init(&p->sparselu1, _state, make_automatic); - _sparsematrix_init(&p->sparselu2, _state, make_automatic); - _sluv2buffer_init(&p->lubuf2, _state, make_automatic); - ae_vector_init(&p->tmpi, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->utmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->utmpi, 0, DT_INT, _state, make_automatic); - _sparsematrix_init(&p->sparseludbg, _state, make_automatic); -} - - -void _dualsimplexbasis_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - dualsimplexbasis *dst = (dualsimplexbasis*)_dst; - dualsimplexbasis *src = (dualsimplexbasis*)_src; - dst->ns = src->ns; - dst->m = src->m; - ae_vector_init_copy(&dst->idx, &src->idx, _state, make_automatic); - ae_vector_init_copy(&dst->nidx, &src->nidx, _state, make_automatic); - ae_vector_init_copy(&dst->isbasic, &src->isbasic, _state, make_automatic); - dst->trftype = src->trftype; - dst->isvalidtrf = src->isvalidtrf; - dst->trfage = src->trfage; - ae_matrix_init_copy(&dst->denselu, &src->denselu, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparsel, &src->sparsel, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparseu, &src->sparseu, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparseut, &src->sparseut, _state, make_automatic); - ae_vector_init_copy(&dst->rowpermbwd, &src->rowpermbwd, _state, make_automatic); - ae_vector_init_copy(&dst->colpermbwd, &src->colpermbwd, _state, make_automatic); - ae_vector_init_copy(&dst->densepfieta, &src->densepfieta, _state, make_automatic); - ae_vector_init_copy(&dst->densemu, &src->densemu, _state, make_automatic); - ae_vector_init_copy(&dst->rk, &src->rk, _state, make_automatic); - ae_vector_init_copy(&dst->dk, &src->dk, _state, make_automatic); - ae_vector_init_copy(&dst->dseweights, &src->dseweights, _state, make_automatic); - dst->dsevalid = src->dsevalid; - dst->eminu = src->eminu; - dst->statfact = src->statfact; - dst->statupdt = src->statupdt; - dst->statoffdiag = src->statoffdiag; - ae_vector_init_copy(&dst->wtmp0, &src->wtmp0, _state, make_automatic); - ae_vector_init_copy(&dst->wtmp1, &src->wtmp1, _state, make_automatic); - ae_vector_init_copy(&dst->wtmp2, &src->wtmp2, _state, make_automatic); - ae_vector_init_copy(&dst->nrs, &src->nrs, _state, make_automatic); - ae_vector_init_copy(&dst->tcinvidx, &src->tcinvidx, _state, make_automatic); - ae_matrix_init_copy(&dst->denselu2, &src->denselu2, _state, make_automatic); - ae_vector_init_copy(&dst->densep2, &src->densep2, _state, make_automatic); - ae_vector_init_copy(&dst->densep2c, &src->densep2c, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparselu1, &src->sparselu1, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparselu2, &src->sparselu2, _state, make_automatic); - _sluv2buffer_init_copy(&dst->lubuf2, &src->lubuf2, _state, make_automatic); - ae_vector_init_copy(&dst->tmpi, &src->tmpi, _state, make_automatic); - ae_vector_init_copy(&dst->utmp0, &src->utmp0, _state, make_automatic); - ae_vector_init_copy(&dst->utmpi, &src->utmpi, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparseludbg, &src->sparseludbg, _state, make_automatic); -} - - -void _dualsimplexbasis_clear(void* _p) -{ - dualsimplexbasis *p = (dualsimplexbasis*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->idx); - ae_vector_clear(&p->nidx); - ae_vector_clear(&p->isbasic); - ae_matrix_clear(&p->denselu); - _sparsematrix_clear(&p->sparsel); - _sparsematrix_clear(&p->sparseu); - _sparsematrix_clear(&p->sparseut); - ae_vector_clear(&p->rowpermbwd); - ae_vector_clear(&p->colpermbwd); - ae_vector_clear(&p->densepfieta); - ae_vector_clear(&p->densemu); - ae_vector_clear(&p->rk); - ae_vector_clear(&p->dk); - ae_vector_clear(&p->dseweights); - ae_vector_clear(&p->wtmp0); - ae_vector_clear(&p->wtmp1); - ae_vector_clear(&p->wtmp2); - ae_vector_clear(&p->nrs); - ae_vector_clear(&p->tcinvidx); - ae_matrix_clear(&p->denselu2); - ae_vector_clear(&p->densep2); - ae_vector_clear(&p->densep2c); - _sparsematrix_clear(&p->sparselu1); - _sparsematrix_clear(&p->sparselu2); - _sluv2buffer_clear(&p->lubuf2); - ae_vector_clear(&p->tmpi); - ae_vector_clear(&p->utmp0); - ae_vector_clear(&p->utmpi); - _sparsematrix_clear(&p->sparseludbg); -} - - -void _dualsimplexbasis_destroy(void* _p) -{ - dualsimplexbasis *p = (dualsimplexbasis*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->idx); - ae_vector_destroy(&p->nidx); - ae_vector_destroy(&p->isbasic); - ae_matrix_destroy(&p->denselu); - _sparsematrix_destroy(&p->sparsel); - _sparsematrix_destroy(&p->sparseu); - _sparsematrix_destroy(&p->sparseut); - ae_vector_destroy(&p->rowpermbwd); - ae_vector_destroy(&p->colpermbwd); - ae_vector_destroy(&p->densepfieta); - ae_vector_destroy(&p->densemu); - ae_vector_destroy(&p->rk); - ae_vector_destroy(&p->dk); - ae_vector_destroy(&p->dseweights); - ae_vector_destroy(&p->wtmp0); - ae_vector_destroy(&p->wtmp1); - ae_vector_destroy(&p->wtmp2); - ae_vector_destroy(&p->nrs); - ae_vector_destroy(&p->tcinvidx); - ae_matrix_destroy(&p->denselu2); - ae_vector_destroy(&p->densep2); - ae_vector_destroy(&p->densep2c); - _sparsematrix_destroy(&p->sparselu1); - _sparsematrix_destroy(&p->sparselu2); - _sluv2buffer_destroy(&p->lubuf2); - ae_vector_destroy(&p->tmpi); - ae_vector_destroy(&p->utmp0); - ae_vector_destroy(&p->utmpi); - _sparsematrix_destroy(&p->sparseludbg); -} - - -void _dualsimplexsubproblem_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - dualsimplexsubproblem *p = (dualsimplexsubproblem*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->rawc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndt, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->xa, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xb, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndlb, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndub, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndtb, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->bndtollb, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndtolub, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->effc, 0, DT_REAL, _state, make_automatic); -} - - -void _dualsimplexsubproblem_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - dualsimplexsubproblem *dst = (dualsimplexsubproblem*)_dst; - dualsimplexsubproblem *src = (dualsimplexsubproblem*)_src; - dst->ns = src->ns; - dst->m = src->m; - ae_vector_init_copy(&dst->rawc, &src->rawc, _state, make_automatic); - ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic); - ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic); - ae_vector_init_copy(&dst->bndt, &src->bndt, _state, make_automatic); - ae_vector_init_copy(&dst->xa, &src->xa, _state, make_automatic); - ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic); - dst->state = src->state; - ae_vector_init_copy(&dst->xb, &src->xb, _state, make_automatic); - ae_vector_init_copy(&dst->bndlb, &src->bndlb, _state, make_automatic); - ae_vector_init_copy(&dst->bndub, &src->bndub, _state, make_automatic); - ae_vector_init_copy(&dst->bndtb, &src->bndtb, _state, make_automatic); - ae_vector_init_copy(&dst->bndtollb, &src->bndtollb, _state, make_automatic); - ae_vector_init_copy(&dst->bndtolub, &src->bndtolub, _state, make_automatic); - ae_vector_init_copy(&dst->effc, &src->effc, _state, make_automatic); -} - - -void _dualsimplexsubproblem_clear(void* _p) -{ - dualsimplexsubproblem *p = (dualsimplexsubproblem*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->rawc); - ae_vector_clear(&p->bndl); - ae_vector_clear(&p->bndu); - ae_vector_clear(&p->bndt); - ae_vector_clear(&p->xa); - ae_vector_clear(&p->d); - ae_vector_clear(&p->xb); - ae_vector_clear(&p->bndlb); - ae_vector_clear(&p->bndub); - ae_vector_clear(&p->bndtb); - ae_vector_clear(&p->bndtollb); - ae_vector_clear(&p->bndtolub); - ae_vector_clear(&p->effc); -} - - -void _dualsimplexsubproblem_destroy(void* _p) -{ - dualsimplexsubproblem *p = (dualsimplexsubproblem*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->rawc); - ae_vector_destroy(&p->bndl); - ae_vector_destroy(&p->bndu); - ae_vector_destroy(&p->bndt); - ae_vector_destroy(&p->xa); - ae_vector_destroy(&p->d); - ae_vector_destroy(&p->xb); - ae_vector_destroy(&p->bndlb); - ae_vector_destroy(&p->bndub); - ae_vector_destroy(&p->bndtb); - ae_vector_destroy(&p->bndtollb); - ae_vector_destroy(&p->bndtolub); - ae_vector_destroy(&p->effc); -} - - -void _dualsimplexstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - dualsimplexstate *p = (dualsimplexstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->rowscales, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rawbndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rawbndu, 0, DT_REAL, _state, make_automatic); - _sparsematrix_init(&p->a, _state, make_automatic); - _sparsematrix_init(&p->at, _state, make_automatic); - _dualsimplexbasis_init(&p->basis, _state, make_automatic); - _dualsimplexsubproblem_init(&p->primary, _state, make_automatic); - _dualsimplexsubproblem_init(&p->phase1, _state, make_automatic); - _dualsimplexsubproblem_init(&p->phase3, _state, make_automatic); - ae_vector_init(&p->repx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->replagbc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->replaglc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->repstats, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->btrantmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->btrantmp1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->btrantmp2, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ftrantmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ftrantmp1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->possibleflips, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->dfctmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dfctmp1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dfctmp2, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ustmpi, 0, DT_INT, _state, make_automatic); - _apbuffers_init(&p->xydsbuf, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp2, 0, DT_REAL, _state, make_automatic); - _dssvector_init(&p->alphar, _state, make_automatic); - _dssvector_init(&p->rhor, _state, make_automatic); - ae_vector_init(&p->tau, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->alphaq, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->alphaqim, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->eligiblealphar, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->harrisset, 0, DT_INT, _state, make_automatic); -} - - -void _dualsimplexstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - dualsimplexstate *dst = (dualsimplexstate*)_dst; - dualsimplexstate *src = (dualsimplexstate*)_src; - ae_vector_init_copy(&dst->rowscales, &src->rowscales, _state, make_automatic); - ae_vector_init_copy(&dst->rawbndl, &src->rawbndl, _state, make_automatic); - ae_vector_init_copy(&dst->rawbndu, &src->rawbndu, _state, make_automatic); - dst->ns = src->ns; - dst->m = src->m; - _sparsematrix_init_copy(&dst->a, &src->a, _state, make_automatic); - _sparsematrix_init_copy(&dst->at, &src->at, _state, make_automatic); - _dualsimplexbasis_init_copy(&dst->basis, &src->basis, _state, make_automatic); - _dualsimplexsubproblem_init_copy(&dst->primary, &src->primary, _state, make_automatic); - _dualsimplexsubproblem_init_copy(&dst->phase1, &src->phase1, _state, make_automatic); - _dualsimplexsubproblem_init_copy(&dst->phase3, &src->phase3, _state, make_automatic); - ae_vector_init_copy(&dst->repx, &src->repx, _state, make_automatic); - ae_vector_init_copy(&dst->replagbc, &src->replagbc, _state, make_automatic); - ae_vector_init_copy(&dst->replaglc, &src->replaglc, _state, make_automatic); - ae_vector_init_copy(&dst->repstats, &src->repstats, _state, make_automatic); - dst->repterminationtype = src->repterminationtype; - dst->repiterationscount = src->repiterationscount; - dst->repiterationscount1 = src->repiterationscount1; - dst->repiterationscount2 = src->repiterationscount2; - dst->repiterationscount3 = src->repiterationscount3; - dst->repphase1time = src->repphase1time; - dst->repphase2time = src->repphase2time; - dst->repphase3time = src->repphase3time; - dst->repdualpricingtime = src->repdualpricingtime; - dst->repdualbtrantime = src->repdualbtrantime; - dst->repdualpivotrowtime = src->repdualpivotrowtime; - dst->repdualratiotesttime = src->repdualratiotesttime; - dst->repdualftrantime = src->repdualftrantime; - dst->repdualupdatesteptime = src->repdualupdatesteptime; - dst->repfillpivotrow = src->repfillpivotrow; - dst->repfillpivotrowcnt = src->repfillpivotrowcnt; - dst->repfillrhor = src->repfillrhor; - dst->repfillrhorcnt = src->repfillrhorcnt; - dst->repfilldensemu = src->repfilldensemu; - dst->repfilldensemucnt = src->repfilldensemucnt; - dst->dotrace = src->dotrace; - dst->dodetailedtrace = src->dodetailedtrace; - dst->dotimers = src->dotimers; - ae_vector_init_copy(&dst->btrantmp0, &src->btrantmp0, _state, make_automatic); - ae_vector_init_copy(&dst->btrantmp1, &src->btrantmp1, _state, make_automatic); - ae_vector_init_copy(&dst->btrantmp2, &src->btrantmp2, _state, make_automatic); - ae_vector_init_copy(&dst->ftrantmp0, &src->ftrantmp0, _state, make_automatic); - ae_vector_init_copy(&dst->ftrantmp1, &src->ftrantmp1, _state, make_automatic); - ae_vector_init_copy(&dst->possibleflips, &src->possibleflips, _state, make_automatic); - dst->possibleflipscnt = src->possibleflipscnt; - ae_vector_init_copy(&dst->dfctmp0, &src->dfctmp0, _state, make_automatic); - ae_vector_init_copy(&dst->dfctmp1, &src->dfctmp1, _state, make_automatic); - ae_vector_init_copy(&dst->dfctmp2, &src->dfctmp2, _state, make_automatic); - ae_vector_init_copy(&dst->ustmpi, &src->ustmpi, _state, make_automatic); - _apbuffers_init_copy(&dst->xydsbuf, &src->xydsbuf, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic); - ae_vector_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic); - _dssvector_init_copy(&dst->alphar, &src->alphar, _state, make_automatic); - _dssvector_init_copy(&dst->rhor, &src->rhor, _state, make_automatic); - ae_vector_init_copy(&dst->tau, &src->tau, _state, make_automatic); - ae_vector_init_copy(&dst->alphaq, &src->alphaq, _state, make_automatic); - ae_vector_init_copy(&dst->alphaqim, &src->alphaqim, _state, make_automatic); - ae_vector_init_copy(&dst->eligiblealphar, &src->eligiblealphar, _state, make_automatic); - ae_vector_init_copy(&dst->harrisset, &src->harrisset, _state, make_automatic); -} - - -void _dualsimplexstate_clear(void* _p) -{ - dualsimplexstate *p = (dualsimplexstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->rowscales); - ae_vector_clear(&p->rawbndl); - ae_vector_clear(&p->rawbndu); - _sparsematrix_clear(&p->a); - _sparsematrix_clear(&p->at); - _dualsimplexbasis_clear(&p->basis); - _dualsimplexsubproblem_clear(&p->primary); - _dualsimplexsubproblem_clear(&p->phase1); - _dualsimplexsubproblem_clear(&p->phase3); - ae_vector_clear(&p->repx); - ae_vector_clear(&p->replagbc); - ae_vector_clear(&p->replaglc); - ae_vector_clear(&p->repstats); - ae_vector_clear(&p->btrantmp0); - ae_vector_clear(&p->btrantmp1); - ae_vector_clear(&p->btrantmp2); - ae_vector_clear(&p->ftrantmp0); - ae_vector_clear(&p->ftrantmp1); - ae_vector_clear(&p->possibleflips); - ae_vector_clear(&p->dfctmp0); - ae_vector_clear(&p->dfctmp1); - ae_vector_clear(&p->dfctmp2); - ae_vector_clear(&p->ustmpi); - _apbuffers_clear(&p->xydsbuf); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->tmp1); - ae_vector_clear(&p->tmp2); - _dssvector_clear(&p->alphar); - _dssvector_clear(&p->rhor); - ae_vector_clear(&p->tau); - ae_vector_clear(&p->alphaq); - ae_vector_clear(&p->alphaqim); - ae_vector_clear(&p->eligiblealphar); - ae_vector_clear(&p->harrisset); -} - - -void _dualsimplexstate_destroy(void* _p) -{ - dualsimplexstate *p = (dualsimplexstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->rowscales); - ae_vector_destroy(&p->rawbndl); - ae_vector_destroy(&p->rawbndu); - _sparsematrix_destroy(&p->a); - _sparsematrix_destroy(&p->at); - _dualsimplexbasis_destroy(&p->basis); - _dualsimplexsubproblem_destroy(&p->primary); - _dualsimplexsubproblem_destroy(&p->phase1); - _dualsimplexsubproblem_destroy(&p->phase3); - ae_vector_destroy(&p->repx); - ae_vector_destroy(&p->replagbc); - ae_vector_destroy(&p->replaglc); - ae_vector_destroy(&p->repstats); - ae_vector_destroy(&p->btrantmp0); - ae_vector_destroy(&p->btrantmp1); - ae_vector_destroy(&p->btrantmp2); - ae_vector_destroy(&p->ftrantmp0); - ae_vector_destroy(&p->ftrantmp1); - ae_vector_destroy(&p->possibleflips); - ae_vector_destroy(&p->dfctmp0); - ae_vector_destroy(&p->dfctmp1); - ae_vector_destroy(&p->dfctmp2); - ae_vector_destroy(&p->ustmpi); - _apbuffers_destroy(&p->xydsbuf); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->tmp1); - ae_vector_destroy(&p->tmp2); - _dssvector_destroy(&p->alphar); - _dssvector_destroy(&p->rhor); - ae_vector_destroy(&p->tau); - ae_vector_destroy(&p->alphaq); - ae_vector_destroy(&p->alphaqim); - ae_vector_destroy(&p->eligiblealphar); - ae_vector_destroy(&p->harrisset); -} - - -#endif -#if defined(AE_COMPILE_MINLP) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* - LINEAR PROGRAMMING - -The subroutine creates LP solver. After initial creation it contains -default optimization problem with zero cost vector and all variables being -fixed to zero values and no constraints. - -In order to actually solve something you should: -* set cost vector with minlpsetcost() -* set variable bounds with minlpsetbc() or minlpsetbcall() -* specify constraint matrix with one of the following functions: - [*] minlpsetlc() for dense one-sided constraints - [*] minlpsetlc2dense() for dense two-sided constraints - [*] minlpsetlc2() for sparse two-sided constraints - [*] minlpaddlc2dense() to add one dense row to constraint matrix - [*] minlpaddlc2() to add one row to constraint matrix (compressed format) -* call minlpoptimize() to run the solver and minlpresults() to get the - solution vector and additional information. - -By default, LP solver uses best algorithm available. As of ALGLIB 3.17, -sparse interior point (barrier) solver is used. Future releases of ALGLIB -may introduce other solvers. - -User may choose specific LP algorithm by calling: -* minlpsetalgodss() for revised dual simplex method with DSE pricing and - bounds flipping ratio test (aka long dual step). Large-scale sparse LU - solverwith Forest-Tomlin update is used internally as linear algebra - driver. -* minlpsetalgoipm() for sparse interior point method - -INPUT PARAMETERS: - N - problem size - -OUTPUT PARAMETERS: - State - optimizer in the default state - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpcreate(ae_int_t n, minlpstate* state, ae_state *_state) -{ - ae_int_t i; - - _minlpstate_clear(state); - - ae_assert(n>=1, "MinLPCreate: N<1", _state); - - /* - * Initialize - */ - state->n = n; - state->m = 0; - minlpsetalgoipm(state, 0.0, _state); - state->ipmlambda = (double)(0); - ae_vector_set_length(&state->c, n, _state); - ae_vector_set_length(&state->s, n, _state); - ae_vector_set_length(&state->bndl, n, _state); - ae_vector_set_length(&state->bndu, n, _state); - ae_vector_set_length(&state->xs, n, _state); - for(i=0; i<=n-1; i++) - { - state->bndl.ptr.p_double[i] = (double)(0); - state->bndu.ptr.p_double[i] = (double)(0); - state->c.ptr.p_double[i] = 0.0; - state->s.ptr.p_double[i] = 1.0; - state->xs.ptr.p_double[i] = 1.0; - } - minlp_clearreportfields(state, _state); -} - - -/************************************************************************* -This function sets LP algorithm to revised dual simplex method. - -ALGLIB implementation of dual simplex method supports advanced performance -and stability improvements like DSE pricing , bounds flipping ratio test -(aka long dual step), Forest-Tomlin update, shifting. - -INPUT PARAMETERS: - State - optimizer - Eps - stopping condition, Eps>=0: - * should be small number about 1E-6 or 1E-7. - * zero value means that solver automatically selects good - value (can be different in different ALGLIB versions) - * default value is zero - Algorithm stops when relative error is less than Eps. - -===== TRACING DSS SOLVER ================================================= - -DSS solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'DSS' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. -* 'DSS.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'DSS'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("DSS,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 08.11.2020 by Bochkanov Sergey -*************************************************************************/ -void minlpsetalgodss(minlpstate* state, double eps, ae_state *_state) -{ - - - ae_assert(ae_isfinite(eps, _state), "MinLPSetAlgoDSS: Eps is not finite number", _state); - ae_assert(ae_fp_greater_eq(eps,(double)(0)), "MinLPSetAlgoDSS: Eps<0", _state); - state->algokind = 1; - if( ae_fp_eq(eps,(double)(0)) ) - { - eps = 1.0E-6; - } - state->dsseps = eps; -} - - -/************************************************************************* -This function sets LP algorithm to sparse interior point method. - -ALGORITHM INFORMATION: - -* this algorithm is our implementation of interior point method as - formulated by R.J.Vanderbei, with minor modifications to the algorithm - (damped Newton directions are extensively used) -* like all interior point methods, this algorithm tends to converge in - roughly same number of iterations (between 15 and 50) independently from - the problem dimensionality - -INPUT PARAMETERS: - State - optimizer - Eps - stopping condition, Eps>=0: - * should be small number about 1E-7 or 1E-8. - * zero value means that solver automatically selects good - value (can be different in different ALGLIB versions) - * default value is zero - Algorithm stops when primal error AND dual error AND - duality gap are less than Eps. - -===== TRACING IPM SOLVER ================================================= - -IPM solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'IPM' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. -* 'IPM.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'IPM'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("IPM,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 08.11.2020 by Bochkanov Sergey -*************************************************************************/ -void minlpsetalgoipm(minlpstate* state, double eps, ae_state *_state) -{ - - - ae_assert(ae_isfinite(eps, _state), "MinLPSetAlgoIPM: Eps is not finite number", _state); - ae_assert(ae_fp_greater_eq(eps,(double)(0)), "MinLPSetAlgoIPM: Eps<0", _state); - state->algokind = 2; - state->ipmeps = eps; - state->ipmlambda = 0.0; -} - - -/************************************************************************* -This function sets cost term for LP solver. - -By default, cost term is zero. - -INPUT PARAMETERS: - State - structure which stores algorithm state - C - cost term, array[N]. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetcost(minlpstate* state, - /* Real */ ae_vector* c, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - - - n = state->n; - ae_assert(c->cnt>=n, "MinLPSetCost: Length(C)c.ptr.p_double[i] = c->ptr.p_double[i]; - } -} - - -/************************************************************************* -This function sets scaling coefficients. - -ALGLIB optimizers use scaling matrices to test stopping conditions and as -preconditioner. - -Scale of the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the - function - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetscale(minlpstate* state, - /* Real */ ae_vector* s, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(s->cnt>=state->n, "MinLPSetScale: Length(S)n-1; i++) - { - ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinLPSetScale: S contains infinite or NAN elements", _state); - ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "MinLPSetScale: S contains zero elements", _state); - } - for(i=0; i<=state->n-1; i++) - { - state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state); - } -} - - -/************************************************************************* -This function sets box constraints for LP solver (all variables at once, -different constraints for different variables). - -The default state of constraints is to have all variables fixed at zero. -You have to overwrite it by your own constraint vector. Constraint status -is preserved until constraints are explicitly overwritten with another -minlpsetbc() call, overwritten with minlpsetbcall(), or partially -overwritten with minlmsetbci() call. - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd[i] BndL[i]=BndU[i] - lower bound BndL[i]<=x[i] BndU[i]=+INF - upper bound x[i]<=BndU[i] BndL[i]=-INF - range BndL[i]<=x[i]<=BndU[i] ... - free variable - BndL[I]=-INF, BndU[I]+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - BndU - upper bounds, array[N]. - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: if constraints for all variables are same you may use minlpsetbcall() - which allows to specify constraints without using arrays. - -NOTE: BndL>BndU will result in LP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetbc(minlpstate* state, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - - - n = state->n; - ae_assert(bndl->cnt>=n, "MinLPSetBC: Length(BndL)cnt>=n, "MinLPSetBC: Length(BndU)ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "MinLPSetBC: BndL contains NAN or +INF", _state); - ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "MinLPSetBC: BndU contains NAN or -INF", _state); - state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i]; - state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i]; - } -} - - -/************************************************************************* -This function sets box constraints for LP solver (all variables at once, -same constraints for all variables) - -The default state of constraints is to have all variables fixed at zero. -You have to overwrite it by your own constraint vector. Constraint status -is preserved until constraints are explicitly overwritten with another -minlpsetbc() call or partially overwritten with minlpsetbcall(). - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd[i] BndL[i]=BndU[i] - lower bound BndL[i]<=x[i] BndU[i]=+INF - upper bound x[i]<=BndU[i] BndL[i]=-INF - range BndL[i]<=x[i]<=BndU[i] ... - free variable - BndL[I]=-INF, BndU[I]+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bound, same for all variables - BndU - upper bound, same for all variables - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: minlpsetbc() can be used to specify different constraints for - different variables. - -NOTE: BndL>BndU will result in LP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetbcall(minlpstate* state, - double bndl, - double bndu, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - - - n = state->n; - ae_assert(ae_isfinite(bndl, _state)||ae_isneginf(bndl, _state), "MinLPSetBCAll: BndL is NAN or +INF", _state); - ae_assert(ae_isfinite(bndu, _state)||ae_isposinf(bndu, _state), "MinLPSetBCAll: BndU is NAN or -INF", _state); - for(i=0; i<=n-1; i++) - { - state->bndl.ptr.p_double[i] = bndl; - state->bndu.ptr.p_double[i] = bndu; - } -} - - -/************************************************************************* -This function sets box constraints for I-th variable (other variables are -not modified). - -The default state of constraints is to have all variables fixed at zero. -You have to overwrite it by your own constraint vector. - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd[i] BndL[i]=BndU[i] - lower bound BndL[i]<=x[i] BndU[i]=+INF - upper bound x[i]<=BndU[i] BndL[i]=-INF - range BndL[i]<=x[i]<=BndU[i] ... - free variable - BndL[I]=-INF, BndU[I]+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - I - variable index, in [0,N) - BndL - lower bound for I-th variable - BndU - upper bound for I-th variable - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: minlpsetbc() can be used to specify different constraints for - different variables. - -NOTE: BndL>BndU will result in LP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetbci(minlpstate* state, - ae_int_t i, - double bndl, - double bndu, - ae_state *_state) -{ - ae_int_t n; - - - n = state->n; - ae_assert(i>=0&&ibndl.ptr.p_double[i] = bndl; - state->bndu.ptr.p_double[i] = bndu; -} - - -/************************************************************************* -This function sets one-sided linear constraints A*x ~ AU, where "~" can be -a mix of "<=", "=" and ">=". - -IMPORTANT: this function is provided here for compatibility with the rest - of ALGLIB optimizers which accept constraints in format like - this one. Many real-life problems feature two-sided constraints - like a0 <= a*x <= a1. It is really inefficient to add them as a - pair of one-sided constraints. - - Use minlpsetlc2dense(), minlpsetlc2(), minlpaddlc2() (or its - sparse version) wherever possible. - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - A - linear constraints, array[K,N+1]. Each row of A represents - one constraint, with first N elements being linear coefficients, - and last element being right side. - CT - constraint types, array[K]: - * if CT[i]>0, then I-th constraint is A[i,*]*x >= A[i,n] - * if CT[i]=0, then I-th constraint is A[i,*]*x = A[i,n] - * if CT[i]<0, then I-th constraint is A[i,*]*x <= A[i,n] - K - number of equality/inequality constraints, K>=0; if not - given, inferred from sizes of A and CT. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetlc(minlpstate* state, - /* Real */ ae_matrix* a, - /* Integer */ ae_vector* ct, - ae_int_t k, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector al; - ae_vector au; - ae_int_t n; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&al, 0, sizeof(al)); - memset(&au, 0, sizeof(au)); - ae_vector_init(&al, 0, DT_REAL, _state, ae_true); - ae_vector_init(&au, 0, DT_REAL, _state, ae_true); - - n = state->n; - ae_assert(k>=0, "MinLPSetLC: K<0", _state); - ae_assert(k==0||a->cols>=n+1, "MinLPSetLC: Cols(A)rows>=k, "MinLPSetLC: Rows(A)cnt>=k, "MinLPSetLC: Length(CT)m = 0; - ae_frame_leave(_state); - return; - } - - /* - * Convert constraints to two-sided storage format, call another function - */ - ae_vector_set_length(&al, k, _state); - ae_vector_set_length(&au, k, _state); - for(i=0; i<=k-1; i++) - { - if( ct->ptr.p_int[i]>0 ) - { - al.ptr.p_double[i] = a->ptr.pp_double[i][n]; - au.ptr.p_double[i] = _state->v_posinf; - continue; - } - if( ct->ptr.p_int[i]<0 ) - { - al.ptr.p_double[i] = _state->v_neginf; - au.ptr.p_double[i] = a->ptr.pp_double[i][n]; - continue; - } - al.ptr.p_double[i] = a->ptr.pp_double[i][n]; - au.ptr.p_double[i] = a->ptr.pp_double[i][n]; - } - minlpsetlc2dense(state, a, &al, &au, k, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU. - -This version accepts dense matrix as input; internally LP solver uses -sparse storage anyway (most LP problems are sparse), but for your -convenience it may accept dense inputs. This function overwrites linear -constraints set by previous calls (if such calls were made). - -We recommend you to use sparse version of this function unless you solve -small-scale LP problem (less than few hundreds of variables). - -NOTE: there also exist several versions of this function: - * one-sided dense version which accepts constraints in the same - format as one used by QP and NLP solvers - * two-sided sparse version which accepts sparse matrix - * two-sided dense version which allows you to add constraints row by row - * two-sided sparse version which allows you to add constraints row by row - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - A - linear constraints, array[K,N]. Each row of A represents - one constraint. One-sided inequality constraints, two- - sided inequality constraints, equality constraints are - supported (see below) - AL, AU - lower and upper bounds, array[K]; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i] two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0; if not - given, inferred from sizes of A, AL, AU. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetlc2dense(minlpstate* state, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t k, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t n; - ae_int_t nz; - ae_vector nrs; - - ae_frame_make(_state, &_frame_block); - memset(&nrs, 0, sizeof(nrs)); - ae_vector_init(&nrs, 0, DT_INT, _state, ae_true); - - n = state->n; - ae_assert(k>=0, "MinLPSetLC2Dense: K<0", _state); - ae_assert(k==0||a->cols>=n, "MinLPSetLC2Dense: Cols(A)rows>=k, "MinLPSetLC2Dense: Rows(A)cnt>=k, "MinLPSetLC2Dense: Length(AL)cnt>=k, "MinLPSetLC2Dense: Length(AU)m = k; - if( state->m==0 ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=k-1; i++) - { - ae_assert(ae_isfinite(al->ptr.p_double[i], _state)||ae_isneginf(al->ptr.p_double[i], _state), "MinLPSetLC2Dense: AL contains NAN or +INF", _state); - ae_assert(ae_isfinite(au->ptr.p_double[i], _state)||ae_isposinf(au->ptr.p_double[i], _state), "MinLPSetLC2Dense: AU contains NAN or -INF", _state); - nz = 0; - for(j=0; j<=n-1; j++) - { - if( ae_fp_neq(a->ptr.pp_double[i][j],(double)(0)) ) - { - inc(&nz, _state); - } - } - nrs.ptr.p_int[i] = nz; - } - - /* - * Allocate storage, copy - */ - rvectorsetlengthatleast(&state->al, state->m, _state); - rvectorsetlengthatleast(&state->au, state->m, _state); - sparsecreatecrsbuf(state->m, n, &nrs, &state->a, _state); - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_neq(a->ptr.pp_double[i][j],(double)(0)) ) - { - sparseset(&state->a, i, j, a->ptr.pp_double[i][j], _state); - } - } - state->al.ptr.p_double[i] = al->ptr.p_double[i]; - state->au.ptr.p_double[i] = au->ptr.p_double[i]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU with -sparse constraining matrix A. Recommended for large-scale problems. - -This function overwrites linear (non-box) constraints set by previous -calls (if such calls were made). - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - A - sparse matrix with size [K,N] (exactly!). - Each row of A represents one general linear constraint. - A can be stored in any sparse storage format. - AL, AU - lower and upper bounds, array[K]; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i] two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0. If K=0 - is specified, A, AL, AU are ignored. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetlc2(minlpstate* state, - sparsematrix* a, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t k, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - - - n = state->n; - - /* - * Quick exit - */ - if( k==0 ) - { - state->m = 0; - return; - } - - /* - * Integrity checks - */ - ae_assert(k>0, "MinLPSetLC2: K<0", _state); - ae_assert(sparsegetncols(a, _state)==n, "MinLPSetLC2: Cols(A)<>N", _state); - ae_assert(sparsegetnrows(a, _state)==k, "MinLPSetLC2: Rows(A)<>K", _state); - ae_assert(al->cnt>=k, "MinLPSetLC2: Length(AL)cnt>=k, "MinLPSetLC2: Length(AU)ptr.p_double[i], _state)||ae_isneginf(al->ptr.p_double[i], _state), "MinLPSetLC2: AL contains NAN or +INF", _state); - ae_assert(ae_isfinite(au->ptr.p_double[i], _state)||ae_isposinf(au->ptr.p_double[i], _state), "MinLPSetLC2: AU contains NAN or -INF", _state); - } - - /* - * Copy - */ - state->m = k; - sparsecopytocrsbuf(a, &state->a, _state); - rvectorsetlengthatleast(&state->al, k, _state); - rvectorsetlengthatleast(&state->au, k, _state); - for(i=0; i<=k-1; i++) - { - state->al.ptr.p_double[i] = al->ptr.p_double[i]; - state->au.ptr.p_double[i] = au->ptr.p_double[i]; - } -} - - -/************************************************************************* -This function appends two-sided linear constraint AL <= A*x <= AU to the -list of currently present constraints. - -This version accepts dense constraint vector as input, but sparsifies it -for internal storage and processing. Thus, time to add one constraint in -is O(N) - we have to scan entire array of length N. Sparse version of this -function is order of magnitude faster for constraints with just a few -nonzeros per row. - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - A - linear constraint coefficient, array[N], right side is NOT - included. - AL, AU - lower and upper bounds; - * AL=AU => equality constraint Ai*x - * AL two-sided constraint AL<=A*x<=AU - * AL=-INF => one-sided constraint Ai*x<=AU - * AU=+INF => one-sided constraint AL<=Ai*x - * AL=-INF, AU=+INF => constraint is ignored - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpaddlc2dense(minlpstate* state, - /* Real */ ae_vector* a, - double al, - double au, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - ae_int_t nnz; - - - n = state->n; - ae_assert(a->cnt>=n, "MinLPAddLC2Dense: Length(A)adddtmpi, n, _state); - rvectorsetlengthatleast(&state->adddtmpr, n, _state); - nnz = 0; - for(i=0; i<=n-1; i++) - { - if( a->ptr.p_double[i]!=0.0 ) - { - state->adddtmpi.ptr.p_int[nnz] = i; - state->adddtmpr.ptr.p_double[nnz] = a->ptr.p_double[i]; - nnz = nnz+1; - } - } - minlpaddlc2(state, &state->adddtmpi, &state->adddtmpr, nnz, al, au, _state); -} - - -/************************************************************************* -This function appends two-sided linear constraint AL <= A*x <= AU to the -list of currently present constraints. - -Constraint is passed in compressed format: as list of non-zero entries of -coefficient vector A. Such approach is more efficient than dense storage -for highly sparse constraint vectors. - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - IdxA - array[NNZ], indexes of non-zero elements of A: - * can be unsorted - * can include duplicate indexes (corresponding entries of - ValA[] will be summed) - ValA - array[NNZ], values of non-zero elements of A - NNZ - number of non-zero coefficients in A - AL, AU - lower and upper bounds; - * AL=AU => equality constraint A*x - * AL two-sided constraint AL<=A*x<=AU - * AL=-INF => one-sided constraint A*x<=AU - * AU=+INF => one-sided constraint AL<=A*x - * AL=-INF, AU=+INF => constraint is ignored - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpaddlc2(minlpstate* state, - /* Integer */ ae_vector* idxa, - /* Real */ ae_vector* vala, - ae_int_t nnz, - double al, - double au, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t offs; - ae_int_t offsdst; - ae_int_t m; - ae_int_t n; - ae_int_t didx; - ae_int_t uidx; - - - m = state->m; - n = state->n; - - /* - * Check inputs - */ - ae_assert(nnz>=0, "MinLPAddLC2: NNZ<0", _state); - ae_assert(idxa->cnt>=nnz, "MinLPAddLC2: Length(IdxA)cnt>=nnz, "MinLPAddLC2: Length(ValA)ptr.p_int[i]>=0&&idxa->ptr.p_int[i]a.matrixtype = 1; - state->a.m = 0; - state->a.n = n; - state->a.ninitialized = 0; - ivectorsetlengthatleast(&state->a.ridx, 1, _state); - state->a.ridx.ptr.p_int[0] = 0; - } - - /* - * Reallocate storage - */ - offs = state->a.ridx.ptr.p_int[m]; - ivectorgrowto(&state->a.idx, offs+nnz, _state); - rvectorgrowto(&state->a.vals, offs+nnz, _state); - ivectorgrowto(&state->a.didx, m+1, _state); - ivectorgrowto(&state->a.uidx, m+1, _state); - ivectorgrowto(&state->a.ridx, m+2, _state); - rvectorgrowto(&state->al, m+1, _state); - rvectorgrowto(&state->au, m+1, _state); - - /* - * If NNZ=0, perform quick and simple row append. - */ - if( nnz==0 ) - { - state->a.didx.ptr.p_int[m] = state->a.ridx.ptr.p_int[m]; - state->a.uidx.ptr.p_int[m] = state->a.ridx.ptr.p_int[m]; - state->a.ridx.ptr.p_int[m+1] = state->a.ridx.ptr.p_int[m]; - state->al.ptr.p_double[m] = al; - state->au.ptr.p_double[m] = au; - state->a.m = m+1; - state->m = m+1; - return; - } - - /* - * Now we are sure that A contains properly initialized sparse - * matrix (or some appropriate dummy for M=0) and we have NNZ>0 - * (no need to care about degenerate cases). - * - * Append rows to A: - * * append data - * * sort in place - * * merge duplicate indexes - * * compute DIdx and UIdx - * - */ - for(i=0; i<=nnz-1; i++) - { - state->a.idx.ptr.p_int[offs+i] = idxa->ptr.p_int[i]; - state->a.vals.ptr.p_double[offs+i] = vala->ptr.p_double[i]; - } - tagsortmiddleir(&state->a.idx, &state->a.vals, offs, nnz, _state); - offsdst = offs; - for(i=1; i<=nnz-1; i++) - { - if( state->a.idx.ptr.p_int[offsdst]!=state->a.idx.ptr.p_int[offs+i] ) - { - offsdst = offsdst+1; - state->a.idx.ptr.p_int[offsdst] = state->a.idx.ptr.p_int[offs+i]; - state->a.vals.ptr.p_double[offsdst] = state->a.vals.ptr.p_double[offs+i]; - } - else - { - state->a.vals.ptr.p_double[offsdst] = state->a.vals.ptr.p_double[offsdst]+state->a.vals.ptr.p_double[offs+i]; - } - } - nnz = offsdst-offs+1; - uidx = -1; - didx = -1; - for(j=offs; j<=offsdst; j++) - { - k = state->a.idx.ptr.p_int[j]; - if( k==m ) - { - didx = j; - } - else - { - if( k>m&&uidx==-1 ) - { - uidx = j; - break; - } - } - } - if( uidx==-1 ) - { - uidx = offsdst+1; - } - if( didx==-1 ) - { - didx = uidx; - } - state->a.didx.ptr.p_int[m] = didx; - state->a.uidx.ptr.p_int[m] = uidx; - state->a.ridx.ptr.p_int[m+1] = offsdst+1; - state->a.m = m+1; - state->a.ninitialized = state->a.ninitialized+nnz; - state->al.ptr.p_double[m] = al; - state->au.ptr.p_double[m] = au; - state->m = m+1; -} - - -/************************************************************************* -This function solves LP problem. - -INPUT PARAMETERS: - State - algorithm state - -You should use minlpresults() function to access results after calls to -this function. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey. -*************************************************************************/ -void minlpoptimize(minlpstate* state, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t m; - ae_int_t i; - double v; - dualsimplexsettings settings; - ae_matrix dummy; - dualsimplexbasis dummybasis; - ae_bool badconstr; - - ae_frame_make(_state, &_frame_block); - memset(&settings, 0, sizeof(settings)); - memset(&dummy, 0, sizeof(dummy)); - memset(&dummybasis, 0, sizeof(dummybasis)); - _dualsimplexsettings_init(&settings, _state, ae_true); - ae_matrix_init(&dummy, 0, 0, DT_REAL, _state, ae_true); - _dualsimplexbasis_init(&dummybasis, _state, ae_true); - - n = state->n; - m = state->m; - minlp_clearreportfields(state, _state); - - /* - * Most basic check for correctness of constraints - */ - badconstr = ae_false; - for(i=0; i<=n-1; i++) - { - if( (ae_isfinite(state->bndl.ptr.p_double[i], _state)&&ae_isfinite(state->bndu.ptr.p_double[i], _state))&&ae_fp_greater(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - badconstr = ae_true; - } - } - for(i=0; i<=m-1; i++) - { - if( (ae_isfinite(state->al.ptr.p_double[i], _state)&&ae_isfinite(state->au.ptr.p_double[i], _state))&&ae_fp_greater(state->al.ptr.p_double[i],state->au.ptr.p_double[i]) ) - { - badconstr = ae_true; - } - } - if( badconstr ) - { - state->repterminationtype = -3; - state->repn = n; - state->repm = m; - rsetallocv(n, 0.0, &state->xs, _state); - rsetallocv(n, 0.0, &state->lagbc, _state); - rsetallocv(m, 0.0, &state->laglc, _state); - isetallocv(n+m, 0, &state->cs, _state); - state->repf = (double)(0); - state->repprimalerror = (double)(0); - for(i=0; i<=n-1; i++) - { - if( ae_isfinite(state->bndl.ptr.p_double[i], _state) ) - { - state->repprimalerror = ae_maxreal(state->repprimalerror, state->bndl.ptr.p_double[i]-0, _state); - } - if( ae_isfinite(state->bndu.ptr.p_double[i], _state) ) - { - state->repprimalerror = ae_maxreal(state->repprimalerror, 0-state->bndu.ptr.p_double[i], _state); - } - } - for(i=0; i<=m-1; i++) - { - if( ae_isfinite(state->al.ptr.p_double[i], _state) ) - { - state->repprimalerror = ae_maxreal(state->repprimalerror, state->al.ptr.p_double[i]-0, _state); - } - if( ae_isfinite(state->au.ptr.p_double[i], _state) ) - { - state->repprimalerror = ae_maxreal(state->repprimalerror, 0-state->au.ptr.p_double[i], _state); - } - } - state->repdualerror = (double)(0); - for(i=0; i<=n-1; i++) - { - state->repdualerror = ae_maxreal(state->repdualerror, ae_fabs(state->c.ptr.p_double[i], _state), _state); - } - state->repslackerror = (double)(0); - ae_frame_leave(_state); - return; - } - - /* - * Call current solver - */ - if( state->algokind==1||state->algokind==2 ) - { - - /* - * Call the solver - */ - if( state->algokind==1 ) - { - - /* - * Dual simplex method with presolve - */ - presolvenonescaleuser(&state->s, &state->c, &state->bndl, &state->bndu, n, &state->a, &state->al, &state->au, m, &state->presolver, _state); - dsssettingsinit(&settings, _state); - settings.xtolabs = state->dsseps; - settings.dtolabs = state->dsseps; - dssinit(state->presolver.newn, &state->dss, _state); - dsssetproblem(&state->dss, &state->presolver.c, &state->presolver.bndl, &state->presolver.bndu, &dummy, &state->presolver.sparsea, 1, &state->presolver.al, &state->presolver.au, state->presolver.newm, &dummybasis, minlp_alllogicalsbasis, &settings, _state); - dssoptimize(&state->dss, &settings, _state); - - /* - * Export results, convert from presolve - */ - rvectorsetlengthatleast(&state->xs, state->presolver.newn, _state); - rvectorsetlengthatleast(&state->lagbc, state->presolver.newn, _state); - rvectorsetlengthatleast(&state->laglc, state->presolver.newm, _state); - ivectorsetlengthatleast(&state->cs, state->presolver.newn+state->presolver.newm, _state); - for(i=0; i<=state->presolver.newn-1; i++) - { - state->xs.ptr.p_double[i] = state->dss.repx.ptr.p_double[i]; - state->lagbc.ptr.p_double[i] = state->dss.replagbc.ptr.p_double[i]; - } - for(i=0; i<=state->presolver.newm-1; i++) - { - state->laglc.ptr.p_double[i] = state->dss.replaglc.ptr.p_double[i]; - } - for(i=0; i<=state->presolver.newn+state->presolver.newm-1; i++) - { - state->cs.ptr.p_int[i] = state->dss.repstats.ptr.p_int[i]; - } - state->repiterationscount = state->dss.repiterationscount; - state->repterminationtype = state->dss.repterminationtype; - presolvebwd(&state->presolver, &state->xs, &state->cs, &state->lagbc, &state->laglc, _state); - state->repn = n; - state->repm = m; - } - if( state->algokind==2 ) - { - - /* - * Interior point method with presolve - */ - presolvenonescaleuser(&state->s, &state->c, &state->bndl, &state->bndu, n, &state->a, &state->al, &state->au, m, &state->presolver, _state); - rsetallocv(state->presolver.newn, 1.0, &state->units, _state); - rsetallocv(state->presolver.newn, 0.0, &state->zeroorigin, _state); - sparsecreatesksbandbuf(state->presolver.newn, state->presolver.newn, 0, &state->ipmquadratic, _state); - for(i=0; i<=state->presolver.newn-1; i++) - { - sparseset(&state->ipmquadratic, i, i, state->ipmlambda, _state); - } - sparseconverttocrs(&state->ipmquadratic, _state); - vipminitsparse(&state->ipm, &state->units, &state->zeroorigin, state->presolver.newn, _state); - vipmsetquadraticlinear(&state->ipm, &dummy, &state->ipmquadratic, 1, ae_false, &state->presolver.c, _state); - vipmsetconstraints(&state->ipm, &state->presolver.bndl, &state->presolver.bndu, &state->presolver.sparsea, state->presolver.newm, &dummy, 0, &state->presolver.al, &state->presolver.au, _state); - vipmsetcond(&state->ipm, state->ipmeps, state->ipmeps, state->ipmeps, _state); - vipmoptimize(&state->ipm, ae_true, &state->xs, &state->lagbc, &state->laglc, &state->repterminationtype, _state); - - /* - * Export results, convert from presolve - */ - isetallocv(state->presolver.newn+state->presolver.newm, 0, &state->cs, _state); - presolvebwd(&state->presolver, &state->xs, &state->cs, &state->lagbc, &state->laglc, _state); - state->repn = n; - state->repm = m; - } - - /* - * Compute F, primal and dual errors - */ - state->repf = rdotv(n, &state->xs, &state->c, _state); - state->repprimalerror = (double)(0); - state->repdualerror = (double)(0); - state->repslackerror = (double)(0); - rcopyallocv(n, &state->c, &state->tmpg, _state); - if( m>0 ) - { - sparsemv(&state->a, &state->xs, &state->tmpax, _state); - sparsegemv(&state->a, 1.0, 1, &state->laglc, 0, 1.0, &state->tmpg, 0, _state); - } - raddv(n, 1.0, &state->lagbc, &state->tmpg, _state); - for(i=0; i<=n-1; i++) - { - if( ae_isfinite(state->bndl.ptr.p_double[i], _state) ) - { - state->repprimalerror = ae_maxreal(state->repprimalerror, state->bndl.ptr.p_double[i]-state->xs.ptr.p_double[i], _state); - state->repslackerror = ae_maxreal(state->repslackerror, ae_maxreal(state->xs.ptr.p_double[i]-state->bndl.ptr.p_double[i], 0.0, _state)*ae_maxreal(-state->lagbc.ptr.p_double[i], 0.0, _state), _state); - } - if( ae_isfinite(state->bndu.ptr.p_double[i], _state) ) - { - state->repprimalerror = ae_maxreal(state->repprimalerror, state->xs.ptr.p_double[i]-state->bndu.ptr.p_double[i], _state); - state->repslackerror = ae_maxreal(state->repslackerror, ae_maxreal(state->bndu.ptr.p_double[i]-state->xs.ptr.p_double[i], 0.0, _state)*ae_maxreal(state->lagbc.ptr.p_double[i], 0.0, _state), _state); - } - state->repdualerror = ae_maxreal(state->repdualerror, ae_fabs(state->tmpg.ptr.p_double[i], _state), _state); - } - for(i=0; i<=m-1; i++) - { - v = state->tmpax.ptr.p_double[i]; - if( ae_isfinite(state->al.ptr.p_double[i], _state) ) - { - state->repprimalerror = ae_maxreal(state->repprimalerror, state->al.ptr.p_double[i]-v, _state); - state->repslackerror = ae_maxreal(state->repslackerror, ae_maxreal(v-state->al.ptr.p_double[i], 0.0, _state)*ae_maxreal(-state->laglc.ptr.p_double[i], 0.0, _state), _state); - } - if( ae_isfinite(state->au.ptr.p_double[i], _state) ) - { - state->repprimalerror = ae_maxreal(state->repprimalerror, v-state->au.ptr.p_double[i], _state); - state->repslackerror = ae_maxreal(state->repslackerror, ae_maxreal(state->au.ptr.p_double[i]-v, 0.0, _state)*ae_maxreal(state->laglc.ptr.p_double[i], 0.0, _state), _state); - } - } - ae_frame_leave(_state); - return; - } - - /* - * Integrity check failed - unknown solver - */ - ae_assert(ae_false, "MinQPOptimize: integrity check failed - unknown solver", _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -LP solver results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[N], solution (on failure: last trial point) - Rep - optimization report. You should check Rep.TerminationType, - which contains completion code, and you may check another - fields which contain another information about algorithm - functioning. - - Failure codes returned by algorithm are: - * -4 LP problem is primal unbounded (dual infeasible) - * -3 LP problem is primal infeasible (dual unbounded) - * -2 IPM solver detected that problem is either - infeasible or unbounded - - Success codes: - * 1..4 successful completion - * 5 MaxIts steps was taken - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minlpresults(minlpstate* state, - /* Real */ ae_vector* x, - minlpreport* rep, - ae_state *_state) -{ - - ae_vector_clear(x); - _minlpreport_clear(rep); - - minlpresultsbuf(state, x, rep, _state); -} - - -/************************************************************************* -LP results - -Buffered implementation of MinLPResults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minlpresultsbuf(minlpstate* state, - /* Real */ ae_vector* x, - minlpreport* rep, - ae_state *_state) -{ - ae_int_t i; - ae_int_t repn; - ae_int_t repm; - - - repn = state->repn; - repm = state->repm; - if( x->cnty, repm, _state); - ae_vector_set_length(&rep->stats, repn+repm, _state); - rep->f = state->repf; - rep->primalerror = state->repprimalerror; - rep->dualerror = state->repdualerror; - rep->slackerror = state->repslackerror; - rep->iterationscount = state->repiterationscount; - rep->terminationtype = state->repterminationtype; - rcopyallocv(repm, &state->laglc, &rep->laglc, _state); - rcopyallocv(repn, &state->lagbc, &rep->lagbc, _state); - for(i=0; i<=repn-1; i++) - { - x->ptr.p_double[i] = state->xs.ptr.p_double[i]; - } - for(i=0; i<=repm-1; i++) - { - rep->y.ptr.p_double[i] = -rep->laglc.ptr.p_double[i]; - } - for(i=0; i<=repn+repm-1; i++) - { - rep->stats.ptr.p_int[i] = state->cs.ptr.p_int[i]; - } -} - - -/************************************************************************* -Clear report fields prior to the optimization. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey. -*************************************************************************/ -static void minlp_clearreportfields(minlpstate* state, ae_state *_state) -{ - - - state->repf = 0.0; - state->repprimalerror = 0.0; - state->repdualerror = 0.0; - state->repiterationscount = 0; - state->repterminationtype = 0; - state->repn = 0; - state->repm = 0; -} - - -void _minlpstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minlpstate *p = (minlpstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->c, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic); - _sparsematrix_init(&p->a, _state, make_automatic); - ae_vector_init(&p->al, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->au, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xs, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->lagbc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->laglc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cs, 0, DT_INT, _state, make_automatic); - _dualsimplexstate_init(&p->dss, _state, make_automatic); - _vipmstate_init(&p->ipm, _state, make_automatic); - ae_vector_init(&p->adddtmpi, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->adddtmpr, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpax, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpg, 0, DT_REAL, _state, make_automatic); - _presolveinfo_init(&p->presolver, _state, make_automatic); - ae_vector_init(&p->zeroorigin, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->units, 0, DT_REAL, _state, make_automatic); - _sparsematrix_init(&p->ipmquadratic, _state, make_automatic); -} - - -void _minlpstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minlpstate *dst = (minlpstate*)_dst; - minlpstate *src = (minlpstate*)_src; - dst->n = src->n; - dst->algokind = src->algokind; - dst->ipmlambda = src->ipmlambda; - ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic); - ae_vector_init_copy(&dst->c, &src->c, _state, make_automatic); - ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic); - ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic); - dst->m = src->m; - _sparsematrix_init_copy(&dst->a, &src->a, _state, make_automatic); - ae_vector_init_copy(&dst->al, &src->al, _state, make_automatic); - ae_vector_init_copy(&dst->au, &src->au, _state, make_automatic); - ae_vector_init_copy(&dst->xs, &src->xs, _state, make_automatic); - ae_vector_init_copy(&dst->lagbc, &src->lagbc, _state, make_automatic); - ae_vector_init_copy(&dst->laglc, &src->laglc, _state, make_automatic); - ae_vector_init_copy(&dst->cs, &src->cs, _state, make_automatic); - dst->repf = src->repf; - dst->repprimalerror = src->repprimalerror; - dst->repdualerror = src->repdualerror; - dst->repslackerror = src->repslackerror; - dst->repiterationscount = src->repiterationscount; - dst->repterminationtype = src->repterminationtype; - dst->repn = src->repn; - dst->repm = src->repm; - dst->dsseps = src->dsseps; - dst->ipmeps = src->ipmeps; - _dualsimplexstate_init_copy(&dst->dss, &src->dss, _state, make_automatic); - _vipmstate_init_copy(&dst->ipm, &src->ipm, _state, make_automatic); - ae_vector_init_copy(&dst->adddtmpi, &src->adddtmpi, _state, make_automatic); - ae_vector_init_copy(&dst->adddtmpr, &src->adddtmpr, _state, make_automatic); - ae_vector_init_copy(&dst->tmpax, &src->tmpax, _state, make_automatic); - ae_vector_init_copy(&dst->tmpg, &src->tmpg, _state, make_automatic); - _presolveinfo_init_copy(&dst->presolver, &src->presolver, _state, make_automatic); - ae_vector_init_copy(&dst->zeroorigin, &src->zeroorigin, _state, make_automatic); - ae_vector_init_copy(&dst->units, &src->units, _state, make_automatic); - _sparsematrix_init_copy(&dst->ipmquadratic, &src->ipmquadratic, _state, make_automatic); -} - - -void _minlpstate_clear(void* _p) -{ - minlpstate *p = (minlpstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->s); - ae_vector_clear(&p->c); - ae_vector_clear(&p->bndl); - ae_vector_clear(&p->bndu); - _sparsematrix_clear(&p->a); - ae_vector_clear(&p->al); - ae_vector_clear(&p->au); - ae_vector_clear(&p->xs); - ae_vector_clear(&p->lagbc); - ae_vector_clear(&p->laglc); - ae_vector_clear(&p->cs); - _dualsimplexstate_clear(&p->dss); - _vipmstate_clear(&p->ipm); - ae_vector_clear(&p->adddtmpi); - ae_vector_clear(&p->adddtmpr); - ae_vector_clear(&p->tmpax); - ae_vector_clear(&p->tmpg); - _presolveinfo_clear(&p->presolver); - ae_vector_clear(&p->zeroorigin); - ae_vector_clear(&p->units); - _sparsematrix_clear(&p->ipmquadratic); -} - - -void _minlpstate_destroy(void* _p) -{ - minlpstate *p = (minlpstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->s); - ae_vector_destroy(&p->c); - ae_vector_destroy(&p->bndl); - ae_vector_destroy(&p->bndu); - _sparsematrix_destroy(&p->a); - ae_vector_destroy(&p->al); - ae_vector_destroy(&p->au); - ae_vector_destroy(&p->xs); - ae_vector_destroy(&p->lagbc); - ae_vector_destroy(&p->laglc); - ae_vector_destroy(&p->cs); - _dualsimplexstate_destroy(&p->dss); - _vipmstate_destroy(&p->ipm); - ae_vector_destroy(&p->adddtmpi); - ae_vector_destroy(&p->adddtmpr); - ae_vector_destroy(&p->tmpax); - ae_vector_destroy(&p->tmpg); - _presolveinfo_destroy(&p->presolver); - ae_vector_destroy(&p->zeroorigin); - ae_vector_destroy(&p->units); - _sparsematrix_destroy(&p->ipmquadratic); -} - - -void _minlpreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minlpreport *p = (minlpreport*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->lagbc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->laglc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stats, 0, DT_INT, _state, make_automatic); -} - - -void _minlpreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minlpreport *dst = (minlpreport*)_dst; - minlpreport *src = (minlpreport*)_src; - dst->f = src->f; - ae_vector_init_copy(&dst->lagbc, &src->lagbc, _state, make_automatic); - ae_vector_init_copy(&dst->laglc, &src->laglc, _state, make_automatic); - ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic); - ae_vector_init_copy(&dst->stats, &src->stats, _state, make_automatic); - dst->primalerror = src->primalerror; - dst->dualerror = src->dualerror; - dst->slackerror = src->slackerror; - dst->iterationscount = src->iterationscount; - dst->terminationtype = src->terminationtype; -} - - -void _minlpreport_clear(void* _p) -{ - minlpreport *p = (minlpreport*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->lagbc); - ae_vector_clear(&p->laglc); - ae_vector_clear(&p->y); - ae_vector_clear(&p->stats); -} - - -void _minlpreport_destroy(void* _p) -{ - minlpreport *p = (minlpreport*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->lagbc); - ae_vector_destroy(&p->laglc); - ae_vector_destroy(&p->y); - ae_vector_destroy(&p->stats); -} - - -#endif -#if defined(AE_COMPILE_NLCSLP) || !defined(AE_PARTIAL_BUILD) - - -void minslpinitbuf(/* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_vector* s, - /* Real */ ae_vector* x0, - ae_int_t n, - /* Real */ ae_matrix* cleic, - /* Integer */ ae_vector* lcsrcidx, - ae_int_t nec, - ae_int_t nic, - ae_int_t nlec, - ae_int_t nlic, - double epsx, - ae_int_t maxits, - minslpstate* state, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - double vv; - - - state->n = n; - state->nec = nec; - state->nic = nic; - state->nlec = nlec; - state->nlic = nlic; - - /* - * Settings - */ - state->hessiantype = 2; - - /* - * Prepare RCOMM state - */ - ae_vector_set_length(&state->rstate.ia, 9+1, _state); - ae_vector_set_length(&state->rstate.ba, 2+1, _state); - ae_vector_set_length(&state->rstate.ra, 10+1, _state); - state->rstate.stage = -1; - state->needfij = ae_false; - state->xupdated = ae_false; - ae_vector_set_length(&state->x, n, _state); - ae_vector_set_length(&state->fi, 1+nlec+nlic, _state); - ae_matrix_set_length(&state->j, 1+nlec+nlic, n, _state); - - /* - * Allocate memory. - */ - rvectorsetlengthatleast(&state->s, n, _state); - rvectorsetlengthatleast(&state->step0x, n, _state); - rvectorsetlengthatleast(&state->stepkx, n, _state); - rvectorsetlengthatleast(&state->backupx, n, _state); - rvectorsetlengthatleast(&state->step0fi, 1+nlec+nlic, _state); - rvectorsetlengthatleast(&state->stepkfi, 1+nlec+nlic, _state); - rvectorsetlengthatleast(&state->backupfi, 1+nlec+nlic, _state); - rmatrixsetlengthatleast(&state->step0j, 1+nlec+nlic, n, _state); - rmatrixsetlengthatleast(&state->stepkj, 1+nlec+nlic, n, _state); - rmatrixsetlengthatleast(&state->backupj, 1+nlec+nlic, n, _state); - rvectorsetlengthatleast(&state->fscales, 1+nlec+nlic, _state); - rvectorsetlengthatleast(&state->meritlagmult, nec+nic+nlec+nlic, _state); - rvectorsetlengthatleast(&state->dummylagmult, nec+nic+nlec+nlic, _state); - bvectorsetlengthatleast(&state->hasbndl, n, _state); - bvectorsetlengthatleast(&state->hasbndu, n, _state); - rvectorsetlengthatleast(&state->scaledbndl, n, _state); - rvectorsetlengthatleast(&state->scaledbndu, n, _state); - rmatrixsetlengthatleast(&state->scaledcleic, nec+nic, n+1, _state); - ivectorsetlengthatleast(&state->lcsrcidx, nec+nic, _state); - rvectorsetlengthatleast(&state->meritfunctionhistory, nlcslp_nonmonotonicphase2limit+1, _state); - - /* - * Prepare scaled problem - */ - for(i=0; i<=n-1; i++) - { - state->hasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state); - state->hasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state); - if( state->hasbndl.ptr.p_bool[i] ) - { - state->scaledbndl.ptr.p_double[i] = bndl->ptr.p_double[i]/s->ptr.p_double[i]; - } - if( state->hasbndu.ptr.p_bool[i] ) - { - state->scaledbndu.ptr.p_double[i] = bndu->ptr.p_double[i]/s->ptr.p_double[i]; - } - if( state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i] ) - { - ae_assert(ae_fp_less_eq(bndl->ptr.p_double[i],bndu->ptr.p_double[i]), "SLP: integrity check failed, box constraints are inconsistent", _state); - } - state->step0x.ptr.p_double[i] = x0->ptr.p_double[i]/s->ptr.p_double[i]; - state->s.ptr.p_double[i] = s->ptr.p_double[i]; - } - for(i=0; i<=nec+nic-1; i++) - { - - /* - * Permutation - */ - state->lcsrcidx.ptr.p_int[i] = lcsrcidx->ptr.p_int[i]; - - /* - * Scale and normalize linear constraints - */ - vv = 0.0; - for(j=0; j<=n-1; j++) - { - v = cleic->ptr.pp_double[i][j]*s->ptr.p_double[j]; - state->scaledcleic.ptr.pp_double[i][j] = v; - vv = vv+v*v; - } - vv = ae_sqrt(vv, _state); - state->scaledcleic.ptr.pp_double[i][n] = cleic->ptr.pp_double[i][n]; - if( ae_fp_greater(vv,(double)(0)) ) - { - for(j=0; j<=n; j++) - { - state->scaledcleic.ptr.pp_double[i][j] = state->scaledcleic.ptr.pp_double[i][j]/vv; - } - } - } - - /* - * Initial enforcement of box constraints - */ - for(i=0; i<=n-1; i++) - { - if( state->hasbndl.ptr.p_bool[i] ) - { - state->step0x.ptr.p_double[i] = ae_maxreal(state->step0x.ptr.p_double[i], state->scaledbndl.ptr.p_double[i], _state); - } - if( state->hasbndu.ptr.p_bool[i] ) - { - state->step0x.ptr.p_double[i] = ae_minreal(state->step0x.ptr.p_double[i], state->scaledbndu.ptr.p_double[i], _state); - } - } - - /* - * Stopping criteria - */ - state->epsx = epsx; - state->maxits = maxits; - - /* - * Report fields - */ - state->repsimplexiterations = 0; - state->repsimplexiterations1 = 0; - state->repsimplexiterations2 = 0; - state->repsimplexiterations3 = 0; - state->repterminationtype = 0; - state->repbcerr = (double)(0); - state->repbcidx = -1; - state->replcerr = (double)(0); - state->replcidx = -1; - state->repnlcerr = (double)(0); - state->repnlcidx = -1; - state->repinneriterationscount = 0; - state->repouteriterationscount = 0; - - /* - * Integrity checks: - * * it is important that significant step length is large enough that - * we do not decrease trust regiod radius; it should also be small, - * so we won't treat large steps as insignificant - */ - ae_assert(ae_fp_less(nlcslp_slpstpclosetozero,nlcslp_slpdeltadecrease), "MinSLP: integrity check failed", _state); - ae_assert(ae_fp_less(nlcslp_slpdeltadecrease,nlcslp_slpdeltaincrease), "MinSLP: integrity check failed", _state); - ae_assert(ae_fp_less(nlcslp_slpdeltaincrease,nlcslp_slpstpclosetoone), "MinSLP: integrity check failed", _state); -} - - -/************************************************************************* -This function performs actual processing for SLP algorithm. It expects -that caller redirects its reverse communication requests NeedFiJ/XUpdated -to external user who will provide analytic derivative (or handle reports -about progress). - -In case external user does not have analytic derivative, it is responsibility -of caller to intercept NeedFiJ request and replace it with appropriate -numerical differentiation scheme. - -Results are stored: -* point - in State.StepKX - -IMPORTANT: this function works with scaled problem formulation; it is - responsibility of the caller to unscale request and scale - Jacobian. - -NOTE: SMonitor is expected to be correctly initialized smoothness monitor. - - -- ALGLIB -- - Copyright 05.03.2018 by Bochkanov Sergey -*************************************************************************/ -ae_bool minslpiteration(minslpstate* state, - smoothnessmonitor* smonitor, - ae_bool userterminationneeded, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nslack; - ae_int_t nec; - ae_int_t nic; - ae_int_t nlec; - ae_int_t nlic; - ae_int_t i; - ae_int_t j; - ae_int_t innerk; - double v; - double vv; - double mx; - ae_bool lpstagesuccess; - double gammamax; - double f1; - double f2; - ae_int_t status; - double stp; - double deltamax; - double multiplyby; - double setscaleto; - double prevtrustrad; - ae_bool dotrace; - ae_bool dodetailedtrace; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - n = state->rstate.ia.ptr.p_int[0]; - nslack = state->rstate.ia.ptr.p_int[1]; - nec = state->rstate.ia.ptr.p_int[2]; - nic = state->rstate.ia.ptr.p_int[3]; - nlec = state->rstate.ia.ptr.p_int[4]; - nlic = state->rstate.ia.ptr.p_int[5]; - i = state->rstate.ia.ptr.p_int[6]; - j = state->rstate.ia.ptr.p_int[7]; - innerk = state->rstate.ia.ptr.p_int[8]; - status = state->rstate.ia.ptr.p_int[9]; - lpstagesuccess = state->rstate.ba.ptr.p_bool[0]; - dotrace = state->rstate.ba.ptr.p_bool[1]; - dodetailedtrace = state->rstate.ba.ptr.p_bool[2]; - v = state->rstate.ra.ptr.p_double[0]; - vv = state->rstate.ra.ptr.p_double[1]; - mx = state->rstate.ra.ptr.p_double[2]; - gammamax = state->rstate.ra.ptr.p_double[3]; - f1 = state->rstate.ra.ptr.p_double[4]; - f2 = state->rstate.ra.ptr.p_double[5]; - stp = state->rstate.ra.ptr.p_double[6]; - deltamax = state->rstate.ra.ptr.p_double[7]; - multiplyby = state->rstate.ra.ptr.p_double[8]; - setscaleto = state->rstate.ra.ptr.p_double[9]; - prevtrustrad = state->rstate.ra.ptr.p_double[10]; - } - else - { - n = 359; - nslack = -58; - nec = -919; - nic = -909; - nlec = 81; - nlic = 255; - i = 74; - j = -788; - innerk = 809; - status = 205; - lpstagesuccess = ae_false; - dotrace = ae_true; - dodetailedtrace = ae_false; - v = 763; - vv = -541; - mx = -698; - gammamax = -900; - f1 = -318; - f2 = -940; - stp = 1016; - deltamax = -229; - multiplyby = -536; - setscaleto = 487; - prevtrustrad = -115; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - if( state->rstate.stage==1 ) - { - goto lbl_1; - } - if( state->rstate.stage==2 ) - { - goto lbl_2; - } - if( state->rstate.stage==3 ) - { - goto lbl_3; - } - if( state->rstate.stage==4 ) - { - goto lbl_4; - } - - /* - * Routine body - */ - n = state->n; - nec = state->nec; - nic = state->nic; - nlec = state->nlec; - nlic = state->nlic; - nslack = n+2*(nec+nlec)+(nic+nlic); - dotrace = ae_is_trace_enabled("SLP"); - dodetailedtrace = dotrace&&ae_is_trace_enabled("SLP.DETAILED"); - - /* - * Prepare rcomm interface - */ - state->needfij = ae_false; - state->xupdated = ae_false; - - /* - * Initialize algorithm data: - * * Lagrangian and "Big C" estimates - * * trust region - * * initial function scales (vector of 1's) - * * current approximation of the Hessian matrix H (unit matrix) - * * initial linearized constraints - * * initial violation of linear/nonlinear constraints - */ - state->lpfailurecnt = 0; - state->fstagnationcnt = 0; - state->trustrad = nlcslp_inittrustrad; - for(i=0; i<=nlec+nlic; i++) - { - state->fscales.ptr.p_double[i] = 1.0; - } - for(i=0; i<=nlcslp_nonmonotonicphase2limit; i++) - { - state->meritfunctionhistory.ptr.p_double[i] = ae_maxrealnumber; - } - state->historylen = 0; - gammamax = 0.0; - - /* - * Avoid spurious warnings about possibly uninitialized vars - */ - status = 0; - stp = (double)(0); - - /* - * Evaluate function vector and Jacobian at Step0X, send first location report. - * Compute initial violation of constraints. - */ - nlcslp_slpsendx(state, &state->step0x, _state); - state->needfij = ae_true; - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - state->needfij = ae_false; - if( !nlcslp_slpretrievefij(state, &state->step0fi, &state->step0j, _state) ) - { - - /* - * Failed to retrieve function/Jaconian, infinities detected! - */ - for(i=0; i<=n-1; i++) - { - state->stepkx.ptr.p_double[i] = state->step0x.ptr.p_double[i]; - } - state->repterminationtype = -8; - result = ae_false; - return result; - } - nlcslp_slpcopystate(state, &state->step0x, &state->step0fi, &state->step0j, &state->stepkx, &state->stepkfi, &state->stepkj, _state); - nlcslp_slpsendx(state, &state->stepkx, _state); - state->f = state->stepkfi.ptr.p_double[0]*state->fscales.ptr.p_double[0]; - state->xupdated = ae_true; - state->rstate.stage = 1; - goto lbl_rcomm; -lbl_1: - state->xupdated = ae_false; - checklcviolation(&state->scaledcleic, &state->lcsrcidx, nec, nic, &state->stepkx, n, &state->replcerr, &state->replcidx, _state); - unscaleandchecknlcviolation(&state->stepkfi, &state->fscales, nlec, nlic, &state->repnlcerr, &state->repnlcidx, _state); - - /* - * Trace output (if needed) - */ - if( dotrace ) - { - ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n"); - ae_trace("// SLP SOLVER STARTED //\n"); - ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n"); - } - - /* - * Perform outer (NLC) iterations - */ - nlcslp_initlpsubsolver(state, &state->subsolver, state->hessiantype, _state); -lbl_5: - if( ae_false ) - { - goto lbl_6; - } - - /* - * Before beginning new outer iteration: - * * renormalize target function and/or constraints, if some of them have too large magnitudes - * * save initial point for the outer iteration - */ - for(i=0; i<=nlec+nlic; i++) - { - - /* - * Determine (a) multiplicative coefficient applied to function value - * and Jacobian row, and (b) new value of the function scale. - */ - mx = (double)(0); - for(j=0; j<=n-1; j++) - { - mx = ae_maxreal(mx, ae_fabs(state->stepkj.ptr.pp_double[i][j], _state), _state); - } - multiplyby = 1.0; - setscaleto = state->fscales.ptr.p_double[i]; - if( ae_fp_greater_eq(mx,nlcslp_slpbigscale) ) - { - multiplyby = 1/mx; - setscaleto = state->fscales.ptr.p_double[i]*mx; - } - if( ae_fp_less_eq(mx,nlcslp_slpsmallscale)&&ae_fp_greater(state->fscales.ptr.p_double[i],1.0) ) - { - if( ae_fp_greater(state->fscales.ptr.p_double[i]*mx,(double)(1)) ) - { - multiplyby = 1/mx; - setscaleto = state->fscales.ptr.p_double[i]*mx; - } - else - { - multiplyby = state->fscales.ptr.p_double[i]; - setscaleto = 1.0; - } - } - if( ae_fp_neq(multiplyby,1.0) ) - { - - /* - * Function #I needs renormalization: - * * update function vector element and Jacobian matrix row - * * update FScales[] array - */ - state->stepkfi.ptr.p_double[i] = state->stepkfi.ptr.p_double[i]*multiplyby; - for(j=0; j<=n-1; j++) - { - state->stepkj.ptr.pp_double[i][j] = state->stepkj.ptr.pp_double[i][j]*multiplyby; - } - state->fscales.ptr.p_double[i] = setscaleto; - } - } - - /* - * Save initial point for the outer iteration - */ - nlcslp_slpcopystate(state, &state->stepkx, &state->stepkfi, &state->stepkj, &state->step0x, &state->step0fi, &state->step0j, _state); - - /* - * Trace output (if needed) - */ - if( dotrace ) - { - ae_trace("\n=== OUTER ITERATION %5d STARTED ==================================================================\n", - (int)(state->repouteriterationscount)); - if( dodetailedtrace ) - { - ae_trace("> printing raw data (prior to applying variable and function scales)\n"); - ae_trace("X (raw) = "); - tracevectorunscaledunshiftedautoprec(&state->step0x, n, &state->s, ae_true, &state->s, ae_false, _state); - ae_trace("\n"); - ae_trace("> printing scaled data (after applying variable and function scales)\n"); - ae_trace("X (scaled) = "); - tracevectorautoprec(&state->step0x, 0, n, _state); - ae_trace("\n"); - ae_trace("FScales = "); - tracevectorautoprec(&state->fscales, 0, 1+nlec+nlic, _state); - ae_trace("\n"); - ae_trace("Fi (scaled) = "); - tracevectorautoprec(&state->stepkfi, 0, 1+nlec+nlic, _state); - ae_trace("\n"); - ae_trace("|Ji| (scaled) = "); - tracerownrm1autoprec(&state->stepkj, 0, 1+nlec+nlic, 0, n, _state); - ae_trace("\n"); - } - mx = (double)(0); - for(i=1; i<=nlec; i++) - { - mx = ae_maxreal(mx, ae_fabs(state->stepkfi.ptr.p_double[i], _state), _state); - } - for(i=nlec+1; i<=nlec+nlic; i++) - { - mx = ae_maxreal(mx, state->stepkfi.ptr.p_double[i], _state); - } - ae_trace("trustRad = %0.3e\n", - (double)(state->trustrad)); - ae_trace("lin.violation = %0.3e (scaled violation of linear constraints)\n", - (double)(state->replcerr)); - ae_trace("nlc.violation = %0.3e (scaled violation of nonlinear constraints)\n", - (double)(mx)); - ae_trace("gammaMax = %0.3e\n", - (double)(gammamax)); - } - - /* - * PHASE 1: - * - * * perform step using linear model with second order correction - * * compute "reference" Lagrange multipliers - * * compute merit function at the end of the phase 1 and push it to the history queue - * - * NOTE: a second order correction helps to overcome Maratos effect - a tendency - * of L1 penalized merit function to reject nonzero steps along steepest - * descent direction. - * - * The idea (explained in more details in the Phase13Iteration() body) - * is to perform one look-ahead step and use updated constraint values - * back at the initial point. - */ - nlcslp_phase13init(&state->state13, n, nec, nic, nlec, nlic, ae_false, _state); -lbl_7: - if( !nlcslp_phase13iteration(state, &state->state13, smonitor, userterminationneeded, &state->stepkx, &state->stepkfi, &state->stepkj, &state->meritlagmult, &status, &stp, _state) ) - { - goto lbl_8; - } - state->rstate.stage = 2; - goto lbl_rcomm; -lbl_2: - goto lbl_7; -lbl_8: - if( status<0 ) - { - goto lbl_5; - } - if( status==0 ) - { - goto lbl_6; - } - for(i=state->historylen; i>=1; i--) - { - state->meritfunctionhistory.ptr.p_double[i] = state->meritfunctionhistory.ptr.p_double[i-1]; - } - state->meritfunctionhistory.ptr.p_double[0] = nlcslp_meritfunction(state, &state->stepkx, &state->stepkfi, &state->meritlagmult, &state->tmpmerit, _state); - state->historylen = ae_minint(state->historylen+1, nlcslp_nonmonotonicphase2limit, _state); - - /* - * PHASE 2: conjugate subiterations - * - * If step with second order correction is shorter than 1.0, it means - * that target is sufficiently nonlinear to use advanced iterations. - * * perform inner LP subiterations with additional conjugacy constraints - * * check changes in merit function, discard iteration results if merit function increased - */ - if( ae_fp_greater_eq(stp,nlcslp_slpstpclosetoone) ) - { - goto lbl_9; - } - if( dotrace ) - { - ae_trace("> linear model produced short step, starting conjugate-gradient-like phase\n"); - } - nlcslp_slpcopystate(state, &state->stepkx, &state->stepkfi, &state->stepkj, &state->backupx, &state->backupfi, &state->backupj, _state); - - /* - * LP subiterations - */ - nlcslp_phase2init(&state->state2, n, nec, nic, nlec, nlic, &state->meritlagmult, _state); -lbl_11: - if( !nlcslp_phase2iteration(state, &state->state2, smonitor, userterminationneeded, &state->stepkx, &state->stepkfi, &state->stepkj, &state->dummylagmult, &gammamax, &status, _state) ) - { - goto lbl_12; - } - state->rstate.stage = 3; - goto lbl_rcomm; -lbl_3: - goto lbl_11; -lbl_12: - if( status==0 ) - { - - /* - * Save progress so far and stop - */ - goto lbl_6; - } - - /* - * Evaluating step - * - * This step is essential because previous step (which minimizes Lagrangian) may fail - * to produce descent direction for L1-penalized merit function and will increase it - * instead of decreasing. - * - * During evaluation we compare merit function at new location with maximum computed - * over last NonmonotonicPhase2Limit+1 previous ones (as suggested in 'A Sequential - * Quadratic Programming Algorithm with Non-Monotone Line Search' by Yu-Hong Dai). - * - * Settings NonmonotonicPhase2Limit to 0 will result in strictly monotonic line search, - * whilst having nonzero limits means that we perform more robust nonmonotonic search. - */ - f1 = state->meritfunctionhistory.ptr.p_double[0]; - for(i=1; i<=state->historylen; i++) - { - f1 = ae_maxreal(f1, state->meritfunctionhistory.ptr.p_double[i], _state); - } - f2 = nlcslp_meritfunction(state, &state->stepkx, &state->stepkfi, &state->meritlagmult, &state->tmpmerit, _state); - if( dotrace ) - { - ae_trace("> evaluating changes in merit function (max over last %0d values is used for reference):\n", - (int)(nlcslp_nonmonotonicphase2limit+1)); - ae_trace("meritF: %14.6e -> %14.6e (delta=%11.3e)\n", - (double)(f1), - (double)(f2), - (double)(f2-f1)); - } - if( ae_fp_less(f2,f1) ) - { - goto lbl_13; - } - - /* - * Merit function does not decrease, discard phase results and report is as one - * more "fake" inner iteration. - * - * NOTE: it is important that F2=F1 is considered as "does not decrease" - */ - if( dotrace ) - { - ae_trace("> CG-like phase increased merit function, completely discarding phase (happens sometimes, but not too often)\n"); - } - nlcslp_slpcopystate(state, &state->backupx, &state->backupfi, &state->backupj, &state->stepkx, &state->stepkfi, &state->stepkj, _state); - inc(&state->repinneriterationscount, _state); - nlcslp_slpsendx(state, &state->stepkx, _state); - state->f = state->stepkfi.ptr.p_double[0]*state->fscales.ptr.p_double[0]; - state->xupdated = ae_true; - state->rstate.stage = 4; - goto lbl_rcomm; -lbl_4: - state->xupdated = ae_false; - checklcviolation(&state->scaledcleic, &state->lcsrcidx, nec, nic, &state->stepkx, n, &state->replcerr, &state->replcidx, _state); - unscaleandchecknlcviolation(&state->stepkfi, &state->fscales, nlec, nlic, &state->repnlcerr, &state->repnlcidx, _state); - goto lbl_14; -lbl_13: - - /* - * Merit function decreased, accept phase - */ - state->meritfunctionhistory.ptr.p_double[0] = f2; - if( dotrace ) - { - ae_trace("> CG-like phase decreased merit function, CG-like step accepted\n"); - } -lbl_14: - goto lbl_10; -lbl_9: - - /* - * No phase #2 - */ - if( dotrace ) - { - if( ae_fp_greater(stp,(double)(0)) ) - { - ae_trace("> linear model produced long step, no need to start CG-like iterations\n"); - } - else - { - ae_trace("> linear model produced zero step, maybe trust radius is too large\n"); - } - } -lbl_10: - - /* - * Update trust region - */ - prevtrustrad = state->trustrad; - deltamax = (double)(0); - for(i=0; i<=n-1; i++) - { - deltamax = ae_maxreal(deltamax, ae_fabs(state->step0x.ptr.p_double[i]-state->stepkx.ptr.p_double[i], _state)/state->trustrad, _state); - } - if( ae_fp_less_eq(deltamax,nlcslp_slpdeltadecrease) ) - { - state->trustrad = state->trustrad*ae_maxreal(deltamax/nlcslp_slpdeltadecrease, nlcslp_maxtrustraddecay, _state); - } - if( ae_fp_greater_eq(deltamax,nlcslp_slpdeltaincrease) ) - { - state->trustrad = state->trustrad*ae_minreal(deltamax/nlcslp_slpdeltaincrease, nlcslp_maxtrustradgrowth, _state); - } - - /* - * Trace - */ - if( dotrace ) - { - ae_trace("\n--- outer iteration ends ---------------------------------------------------------------------------\n"); - ae_trace("deltaMax = %0.3f (ratio of step length to trust radius)\n", - (double)(deltamax)); - ae_trace("newTrustRad = %0.3e", - (double)(state->trustrad)); - if( ae_fp_greater(state->trustrad,prevtrustrad) ) - { - ae_trace(", trust radius increased"); - } - if( ae_fp_less(state->trustrad,prevtrustrad) ) - { - ae_trace(", trust radius decreased"); - } - ae_trace("\n"); - } - - /* - * Advance outer iteration counter, test stopping criteria - */ - inc(&state->repouteriterationscount, _state); - if( ae_fp_less_eq(ae_fabs(state->stepkfi.ptr.p_double[0]-state->step0fi.ptr.p_double[0], _state),nlcslp_stagnationepsf*ae_fabs(state->step0fi.ptr.p_double[0], _state)) ) - { - inc(&state->fstagnationcnt, _state); - } - else - { - state->fstagnationcnt = 0; - } - if( ae_fp_less_eq(state->trustrad,state->epsx) ) - { - state->repterminationtype = 2; - if( dotrace ) - { - ae_trace("> stopping condition met: trust radius is smaller than %0.3e\n", - (double)(state->epsx)); - } - goto lbl_6; - } - if( state->maxits>0&&state->repinneriterationscount>=state->maxits ) - { - state->repterminationtype = 5; - if( dotrace ) - { - ae_trace("> stopping condition met: %0d iterations performed\n", - (int)(state->repinneriterationscount)); - } - goto lbl_6; - } - if( state->fstagnationcnt>=nlcslp_fstagnationlimit ) - { - state->repterminationtype = 7; - if( dotrace ) - { - ae_trace("> stopping criteria are too stringent: F stagnated for %0d its, stopping\n", - (int)(state->fstagnationcnt)); - } - goto lbl_6; - } - goto lbl_5; -lbl_6: - smoothnessmonitortracestatus(smonitor, dotrace, _state); - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = n; - state->rstate.ia.ptr.p_int[1] = nslack; - state->rstate.ia.ptr.p_int[2] = nec; - state->rstate.ia.ptr.p_int[3] = nic; - state->rstate.ia.ptr.p_int[4] = nlec; - state->rstate.ia.ptr.p_int[5] = nlic; - state->rstate.ia.ptr.p_int[6] = i; - state->rstate.ia.ptr.p_int[7] = j; - state->rstate.ia.ptr.p_int[8] = innerk; - state->rstate.ia.ptr.p_int[9] = status; - state->rstate.ba.ptr.p_bool[0] = lpstagesuccess; - state->rstate.ba.ptr.p_bool[1] = dotrace; - state->rstate.ba.ptr.p_bool[2] = dodetailedtrace; - state->rstate.ra.ptr.p_double[0] = v; - state->rstate.ra.ptr.p_double[1] = vv; - state->rstate.ra.ptr.p_double[2] = mx; - state->rstate.ra.ptr.p_double[3] = gammamax; - state->rstate.ra.ptr.p_double[4] = f1; - state->rstate.ra.ptr.p_double[5] = f2; - state->rstate.ra.ptr.p_double[6] = stp; - state->rstate.ra.ptr.p_double[7] = deltamax; - state->rstate.ra.ptr.p_double[8] = multiplyby; - state->rstate.ra.ptr.p_double[9] = setscaleto; - state->rstate.ra.ptr.p_double[10] = prevtrustrad; - return result; -} - - -/************************************************************************* -This function initializes SLP subproblem. -Should be called once in the beginning of the optimization. - -INPUT PARAMETERS: - SState - solver state - Subsolver - SLP subproblem to initialize - HessianType - 0 for identity Hessian, 1 for BFGS update - - -RETURN VALUE: - True on success - False on failure of the LP solver (unexpected... but possible due to numerical errors) - - - -- ALGLIB -- - Copyright 05.03.2018 by Bochkanov Sergey -*************************************************************************/ -static void nlcslp_initlpsubsolver(minslpstate* sstate, - minslpsubsolver* subsolver, - ae_int_t hessiantype, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nslack; - ae_int_t nec; - ae_int_t nic; - ae_int_t nlec; - ae_int_t nlic; - ae_int_t lccnt; - ae_int_t nnz; - ae_int_t offs; - ae_int_t i; - ae_int_t j; - - - n = sstate->n; - nec = sstate->nec; - nic = sstate->nic; - nlec = sstate->nlec; - nlic = sstate->nlic; - nslack = n+2*(nec+nlec)+(nic+nlic); - lccnt = nec+nic+nlec+nlic; - - /* - * Create simplex solver. - * - * NOTE: we disable DSE pricing because it interferes with our - * warm-start strategy. - */ - dsssettingsinit(&subsolver->dsssettings, _state); - subsolver->dsssettings.pricing = 0; - - /* - * Allocate temporaries - */ - rvectorsetlengthatleast(&subsolver->cural, lccnt+n, _state); - rvectorsetlengthatleast(&subsolver->curau, lccnt+n, _state); - rmatrixsetlengthatleast(&subsolver->curd, n, n, _state); - rmatrixsetlengthatleast(&subsolver->curhd, n, n, _state); - rvectorsetlengthatleast(&subsolver->curbndl, nslack, _state); - rvectorsetlengthatleast(&subsolver->curbndu, nslack, _state); - rvectorsetlengthatleast(&subsolver->curb, nslack, _state); - rvectorsetlengthatleast(&subsolver->sk, n, _state); - rvectorsetlengthatleast(&subsolver->yk, n, _state); - - /* - * Initial state - */ - subsolver->basispresent = ae_false; - subsolver->curdcnt = 0; - subsolver->hessiantype = hessiantype; - if( hessiantype==1||hessiantype==2 ) - { - - /* - * Prepare Hessian matrix - */ - rmatrixsetlengthatleast(&subsolver->h, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - subsolver->h.ptr.pp_double[i][j] = (double)(0); - } - subsolver->h.ptr.pp_double[i][i] = (double)(1); - } - } - - /* - * Linear constraints do not change across subiterations, that's - * why we allocate storage for them at the start of the program. - * - * A full set of "raw" constraints is stored; later we will filter - * out inequality ones which are inactive anywhere in the current - * trust region. - * - * NOTE: because sparserawlc object stores only linear constraint - * (linearizations of nonlinear ones are not stored) we - * allocate only minimum necessary space. - */ - nnz = 0; - for(i=0; i<=nec+nic-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( sstate->scaledcleic.ptr.pp_double[i][j]!=0.0 ) - { - nnz = nnz+1; - } - } - } - ivectorsetlengthatleast(&subsolver->sparserawlc.ridx, nec+nic+1, _state); - rvectorsetlengthatleast(&subsolver->sparserawlc.vals, nnz, _state); - ivectorsetlengthatleast(&subsolver->sparserawlc.idx, nnz, _state); - ivectorsetlengthatleast(&subsolver->sparserawlc.didx, nec+nic, _state); - ivectorsetlengthatleast(&subsolver->sparserawlc.uidx, nec+nic, _state); - offs = 0; - subsolver->sparserawlc.ridx.ptr.p_int[0] = 0; - for(i=0; i<=nec+nic-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( sstate->scaledcleic.ptr.pp_double[i][j]!=0.0 ) - { - - /* - * Primary part of the matrix - */ - subsolver->sparserawlc.vals.ptr.p_double[offs] = sstate->scaledcleic.ptr.pp_double[i][j]; - subsolver->sparserawlc.idx.ptr.p_int[offs] = j; - offs = offs+1; - } - } - subsolver->sparserawlc.ridx.ptr.p_int[i+1] = offs; - } - subsolver->sparserawlc.matrixtype = 1; - subsolver->sparserawlc.ninitialized = subsolver->sparserawlc.ridx.ptr.p_int[nec+nic]; - subsolver->sparserawlc.m = nec+nic; - subsolver->sparserawlc.n = n; - sparseinitduidx(&subsolver->sparserawlc, _state); -} - - -/************************************************************************* -Restarts LP subproblem (cleans the matrix of internally stored directions) - -INPUT PARAMETERS: - SState - solver state - Subsolver - SLP subproblem to initialize - - -- ALGLIB -- - Copyright 05.03.2018 by Bochkanov Sergey -*************************************************************************/ -static void nlcslp_lpsubproblemrestart(minslpstate* sstate, - minslpsubsolver* subsolver, - ae_state *_state) -{ - - - subsolver->curdcnt = 0; -} - - -/************************************************************************* -Updates Hessian estimate - -INPUT PARAMETERS: - SState - solver state - Subsolver - SLP subproblem to initialize - - - -- ALGLIB -- - Copyright 05.03.2018 by Bochkanov Sergey -*************************************************************************/ -static void nlcslp_lpsubproblemupdatehessian(minslpstate* sstate, - minslpsubsolver* subsolver, - /* Real */ ae_vector* x0, - /* Real */ ae_vector* g0, - /* Real */ ae_vector* x1, - /* Real */ ae_vector* g1, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - double vv; - double v; - double v0; - double v1; - double v2; - double gk; - double sk; - double yk; - - - n = sstate->n; - if( subsolver->hessiantype==1||subsolver->hessiantype==2 ) - { - rvectorsetlengthatleast(&subsolver->tmp0, n, _state); - v = (double)(0); - v0 = (double)(0); - v1 = (double)(0); - v2 = (double)(0); - for(i=0; i<=n-1; i++) - { - sk = x1->ptr.p_double[i]-x0->ptr.p_double[i]; - yk = g1->ptr.p_double[i]-g0->ptr.p_double[i]; - gk = g0->ptr.p_double[i]; - v = v+sk*yk; - v0 = v0+sk*sk; - v1 = v1+yk*yk; - v2 = v2+gk*gk; - subsolver->sk.ptr.p_double[i] = sk; - subsolver->yk.ptr.p_double[i] = yk; - } - if( (ae_fp_greater(ae_sqrt(v0, _state),ae_maxreal(sstate->epsx, nlcslp_bfgstol, _state))&&ae_fp_greater(ae_sqrt(v1, _state),nlcslp_bfgstol*ae_sqrt(v2, _state)))&&ae_fp_greater(v,nlcslp_bfgstol*ae_sqrt(v0, _state)*ae_sqrt(v1, _state)) ) - { - - /* - * Update Hessian if following criteria hold: - * * MCINFO=1 (good step) - * * step length is large enough - * * |Yk| is large enough when compared with |G| - * * (Sk,Yk) is large enough when compared with |S| and |G| - */ - vv = rmatrixsyvmv(n, &subsolver->h, 0, 0, ae_true, &subsolver->sk, 0, &subsolver->tmp0, _state); - rmatrixgemv(n, n, 1.0, &subsolver->h, 0, 0, 0, &subsolver->sk, 0, 0.0, &subsolver->tmp0, 0, _state); - rmatrixger(n, n, &subsolver->h, 0, 0, 1/v, &subsolver->yk, 0, &subsolver->yk, 0, _state); - rmatrixger(n, n, &subsolver->h, 0, 0, -1/vv, &subsolver->tmp0, 0, &subsolver->tmp0, 0, _state); - } - } -} - - -/************************************************************************* -This function solves LP subproblem given by initial point X, function vector Fi -and Jacobian Jac, and returns estimates of Lagrangian multipliers and search direction D[]. - -This function does NOT append search direction D to conjugacy constraints, -you have to use LPSubproblemAppendConjugacyConstraint(). - - -- ALGLIB -- - Copyright 05.03.2018 by Bochkanov Sergey -*************************************************************************/ -static ae_bool nlcslp_lpsubproblemsolve(minslpstate* state, - minslpsubsolver* subsolver, - /* Real */ ae_vector* x, - /* Real */ ae_vector* fi, - /* Real */ ae_matrix* jac, - ae_int_t innerk, - /* Real */ ae_vector* d, - /* Real */ ae_vector* lagmult, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nslack; - ae_int_t nec; - ae_int_t nic; - ae_int_t nlec; - ae_int_t nlic; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double vv; - double vright; - double vmax; - ae_int_t basisinittype; - ae_int_t lccnt; - ae_int_t offsslackec; - ae_int_t offsslacknlec; - ae_int_t offsslackic; - ae_int_t offsslacknlic; - ae_int_t offs; - ae_int_t nnz; - ae_int_t j0; - ae_int_t j1; - ae_bool result; - - - n = state->n; - nec = state->nec; - nic = state->nic; - nlec = state->nlec; - nlic = state->nlic; - nslack = n+2*(nec+nlec)+(nic+nlic); - lccnt = nec+nic+nlec+nlic; - - /* - * Locations of slack variables - */ - offsslackec = n; - offsslacknlec = n+2*nec; - offsslackic = n+2*nec+2*nlec; - offsslacknlic = n+2*(nec+nlec)+nic; - - /* - * Prepare temporary structures - */ - rvectorgrowto(&subsolver->cural, lccnt+subsolver->curdcnt, _state); - rvectorgrowto(&subsolver->curau, lccnt+subsolver->curdcnt, _state); - - /* - * Prepare default solution: all zeros - */ - result = ae_true; - for(i=0; i<=nslack-1; i++) - { - d->ptr.p_double[i] = 0.0; - } - for(i=0; i<=lccnt-1; i++) - { - lagmult->ptr.p_double[i] = (double)(0); - } - - /* - * Linear term B - * - * NOTE: elements [N,NSlack) are equal to bigC + perturbation to improve numeric properties of LP problem - */ - for(i=0; i<=n-1; i++) - { - subsolver->curb.ptr.p_double[i] = jac->ptr.pp_double[0][i]; - } - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(jac->ptr.pp_double[0][i], _state); - } - v = coalesce(ae_sqrt(v, _state), 1.0, _state); - for(i=n; i<=nslack-1; i++) - { - subsolver->curb.ptr.p_double[i] = (nlcslp_bigc+1.0/(1+i))*v; - } - - /* - * Trust radius constraints for primary variables - */ - for(i=0; i<=n-1; i++) - { - subsolver->curbndl.ptr.p_double[i] = -state->trustrad; - subsolver->curbndu.ptr.p_double[i] = state->trustrad; - if( state->hasbndl.ptr.p_bool[i] ) - { - subsolver->curbndl.ptr.p_double[i] = ae_maxreal(subsolver->curbndl.ptr.p_double[i], state->scaledbndl.ptr.p_double[i]-x->ptr.p_double[i], _state); - } - if( state->hasbndu.ptr.p_bool[i] ) - { - subsolver->curbndu.ptr.p_double[i] = ae_minreal(subsolver->curbndu.ptr.p_double[i], state->scaledbndu.ptr.p_double[i]-x->ptr.p_double[i], _state); - } - } - - /* - * Prepare storage for "effective" constraining matrix - */ - nnz = subsolver->sparserawlc.ridx.ptr.p_int[nec+nic]; - for(i=0; i<=nlec+nlic-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( jac->ptr.pp_double[1+i][j]!=0.0 ) - { - nnz = nnz+1; - } - } - } - nnz = nnz+2*nec+nic; - nnz = nnz+2*nlec+nlic; - nnz = nnz+subsolver->curdcnt*n; - ivectorgrowto(&subsolver->sparseefflc.ridx, lccnt+n+1, _state); - rvectorgrowto(&subsolver->sparseefflc.vals, nnz, _state); - ivectorgrowto(&subsolver->sparseefflc.idx, nnz, _state); - ivectorsetlengthatleast(&subsolver->sparseefflc.didx, lccnt+n, _state); - ivectorsetlengthatleast(&subsolver->sparseefflc.uidx, lccnt+n, _state); - subsolver->sparseefflc.m = 0; - subsolver->sparseefflc.n = nslack; - subsolver->sparseefflc.matrixtype = 1; - - /* - * Append linear equality/inequality constraints - * - * Scan sparsified linear constraints stored in sparserawlc[], skip ones - * which are inactive anywhere in the trust region. - */ - rvectorsetlengthatleast(&subsolver->tmp0, nslack, _state); - for(i=0; i<=n-1; i++) - { - subsolver->tmp0.ptr.p_double[i] = x->ptr.p_double[i]; - } - for(i=n; i<=nslack-1; i++) - { - subsolver->tmp0.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=nec+nic-1; i++) - { - - /* - * Calculate: - * * VRight - product of X[] (extended with zeros up to NSlack elements) - * and AR[i] - Ith row of sparserawlc matrix. - * * VMax - maximum value of X*ARi computed over trust region - */ - vright = (double)(0); - vmax = (double)(0); - j0 = subsolver->sparserawlc.ridx.ptr.p_int[i]; - j1 = subsolver->sparserawlc.ridx.ptr.p_int[i+1]-1; - for(k=j0; k<=j1; k++) - { - j = subsolver->sparserawlc.idx.ptr.p_int[k]; - v = subsolver->tmp0.ptr.p_double[j]; - vv = subsolver->sparserawlc.vals.ptr.p_double[k]; - vright = vright+vv*v; - if( vv>=0 ) - { - vmax = vmax+vv*(v+subsolver->curbndu.ptr.p_double[j]); - } - else - { - vmax = vmax+vv*(v+subsolver->curbndl.ptr.p_double[j]); - } - } - - /* - * If constraint is an inequality one and guaranteed to be inactive - * within trust region, it is skipped (row itself is retained but - * filled by zeros). - */ - if( i>=nec&&vmax<=state->scaledcleic.ptr.pp_double[i][n] ) - { - offs = subsolver->sparseefflc.ridx.ptr.p_int[i]; - subsolver->sparseefflc.vals.ptr.p_double[offs] = (double)(-1); - subsolver->sparseefflc.idx.ptr.p_int[offs] = offsslackic+(i-nec); - subsolver->sparseefflc.ridx.ptr.p_int[i+1] = offs+1; - subsolver->cural.ptr.p_double[i] = 0.0; - subsolver->curau.ptr.p_double[i] = 0.0; - subsolver->curbndl.ptr.p_double[offsslackic+(i-nec)] = (double)(0); - subsolver->curbndu.ptr.p_double[offsslackic+(i-nec)] = (double)(0); - continue; - } - - /* - * Start working on row I - */ - offs = subsolver->sparseefflc.ridx.ptr.p_int[i]; - - /* - * Copy constraint from sparserawlc[] to sparseefflc[] - */ - j0 = subsolver->sparserawlc.ridx.ptr.p_int[i]; - j1 = subsolver->sparserawlc.ridx.ptr.p_int[i+1]-1; - for(k=j0; k<=j1; k++) - { - subsolver->sparseefflc.idx.ptr.p_int[offs] = subsolver->sparserawlc.idx.ptr.p_int[k]; - subsolver->sparseefflc.vals.ptr.p_double[offs] = subsolver->sparserawlc.vals.ptr.p_double[k]; - offs = offs+1; - } - - /* - * Set up slack variables - */ - if( isparseefflc.vals.ptr.p_double[offs+0] = (double)(-1); - subsolver->sparseefflc.vals.ptr.p_double[offs+1] = (double)(1); - subsolver->sparseefflc.idx.ptr.p_int[offs+0] = offsslackec+2*i+0; - subsolver->sparseefflc.idx.ptr.p_int[offs+1] = offsslackec+2*i+1; - offs = offs+2; - } - else - { - - /* - * Slack variables for inequality constraints - */ - subsolver->sparseefflc.vals.ptr.p_double[offs] = (double)(-1); - subsolver->sparseefflc.idx.ptr.p_int[offs] = offsslackic+(i-nec); - offs = offs+1; - } - - /* - * Finalize row - */ - subsolver->sparseefflc.ridx.ptr.p_int[i+1] = offs; - - /* - * Set up bounds. - * - * NOTE: bounds for equality and inequality constraints are - * handled differently - */ - v = vright-state->scaledcleic.ptr.pp_double[i][n]; - if( icural.ptr.p_double[i] = -v; - subsolver->curau.ptr.p_double[i] = -v; - subsolver->curbndl.ptr.p_double[offsslackec+2*i+0] = (double)(0); - subsolver->curbndl.ptr.p_double[offsslackec+2*i+1] = (double)(0); - subsolver->curbndu.ptr.p_double[offsslackec+2*i+0] = ae_fabs(v, _state); - subsolver->curbndu.ptr.p_double[offsslackec+2*i+1] = ae_fabs(v, _state); - } - else - { - subsolver->cural.ptr.p_double[i] = _state->v_neginf; - subsolver->curau.ptr.p_double[i] = -v; - subsolver->curbndl.ptr.p_double[offsslackic+(i-nec)] = (double)(0); - subsolver->curbndu.ptr.p_double[offsslackic+(i-nec)] = ae_maxreal(v, (double)(0), _state); - } - } - subsolver->sparseefflc.m = subsolver->sparseefflc.m+(nec+nic); - - /* - * Append nonlinear equality/inequality constraints - */ - for(i=0; i<=nlec+nlic-1; i++) - { - - /* - * Calculate scale coefficient - */ - vv = (double)(0); - for(j=0; j<=n-1; j++) - { - v = jac->ptr.pp_double[1+i][j]; - vv = vv+v*v; - } - vv = 1/coalesce(ae_sqrt(vv, _state), (double)(1), _state); - - /* - * Copy scaled row - */ - offs = subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m+i]; - for(j=0; j<=n-1; j++) - { - if( jac->ptr.pp_double[1+i][j]!=0.0 ) - { - subsolver->sparseefflc.vals.ptr.p_double[offs] = vv*jac->ptr.pp_double[1+i][j]; - subsolver->sparseefflc.idx.ptr.p_int[offs] = j; - offs = offs+1; - } - } - if( isparseefflc.vals.ptr.p_double[offs+0] = (double)(-1); - subsolver->sparseefflc.vals.ptr.p_double[offs+1] = (double)(1); - subsolver->sparseefflc.idx.ptr.p_int[offs+0] = offsslacknlec+2*i+0; - subsolver->sparseefflc.idx.ptr.p_int[offs+1] = offsslacknlec+2*i+1; - offs = offs+2; - } - else - { - - /* - * Add slack terms for inequality constraints - */ - subsolver->sparseefflc.vals.ptr.p_double[offs] = (double)(-1); - subsolver->sparseefflc.idx.ptr.p_int[offs] = offsslacknlic+(i-nlec); - offs = offs+1; - } - subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m+i+1] = offs; - - /* - * Set box constraints on slack variables and bounds on linear equality/inequality constraints - */ - v = vv*fi->ptr.p_double[1+i]; - if( icural.ptr.p_double[subsolver->sparseefflc.m+i] = -v; - subsolver->curau.ptr.p_double[subsolver->sparseefflc.m+i] = -v; - subsolver->curbndl.ptr.p_double[offsslacknlec+2*i+0] = (double)(0); - subsolver->curbndl.ptr.p_double[offsslacknlec+2*i+1] = (double)(0); - subsolver->curbndu.ptr.p_double[offsslacknlec+2*i+0] = ae_fabs(v, _state); - subsolver->curbndu.ptr.p_double[offsslacknlec+2*i+1] = ae_fabs(v, _state); - } - else - { - - /* - * Inequality constraint - */ - subsolver->cural.ptr.p_double[subsolver->sparseefflc.m+i] = _state->v_neginf; - subsolver->curau.ptr.p_double[subsolver->sparseefflc.m+i] = -v; - subsolver->curbndl.ptr.p_double[offsslacknlic+(i-nlec)] = (double)(0); - subsolver->curbndu.ptr.p_double[offsslacknlic+(i-nlec)] = ae_maxreal(v, (double)(0), _state); - } - } - subsolver->sparseefflc.m = subsolver->sparseefflc.m+(nlec+nlic); - - /* - * Append conjugacy constraints - */ - for(i=0; i<=subsolver->curdcnt-1; i++) - { - - /* - * Copy N elements of CurHD - * - * NOTE: we expect product of D and H to be dense, so we copy all N elements - */ - v = (double)(0); - for(j=0; j<=n-1; j++) - { - vv = subsolver->curhd.ptr.pp_double[i][j]; - v = v+vv*vv; - } - v = 1.0/coalesce(ae_sqrt(v, _state), 1.0, _state); - offs = subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m]; - for(j=0; j<=n-1; j++) - { - vv = subsolver->curhd.ptr.pp_double[i][j]; - subsolver->sparseefflc.vals.ptr.p_double[offs] = v*vv; - subsolver->sparseefflc.idx.ptr.p_int[offs] = j; - offs = offs+1; - } - subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m+1] = offs; - - /* - * Set bounds on linear constraints - */ - subsolver->cural.ptr.p_double[subsolver->sparseefflc.m] = (double)(0); - subsolver->curau.ptr.p_double[subsolver->sparseefflc.m] = (double)(0); - - /* - * Increase row count - */ - subsolver->sparseefflc.m = subsolver->sparseefflc.m+1; - } - - /* - * Finalize sparse matrix structure - */ - ae_assert(subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m]<=subsolver->sparseefflc.idx.cnt, "LPSubproblemSolve: critical integrity check failed", _state); - ae_assert(subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m]<=subsolver->sparseefflc.vals.cnt, "LPSubproblemSolve: critical integrity check failed", _state); - subsolver->sparseefflc.ninitialized = subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m]; - sparseinitduidx(&subsolver->sparseefflc, _state); - - /* - * Choose dual simplex method basis initialization type - */ - if( innerk==1&&subsolver->basispresent ) - { - basisinittype = 2; - } - else - { - basisinittype = 1; - } - - /* - * Solve linear program - */ - rvectorsetlengthatleast(&subsolver->tmp0, nslack, _state); - for(i=0; i<=nslack-1; i++) - { - subsolver->tmp0.ptr.p_double[i] = state->trustrad; - } - presolvenonescaleuser(&subsolver->tmp0, &subsolver->curb, &subsolver->curbndl, &subsolver->curbndu, nslack, &subsolver->sparseefflc, &subsolver->cural, &subsolver->curau, subsolver->sparseefflc.m, &subsolver->presolver, _state); - dssinit(subsolver->presolver.newn, &subsolver->dss, _state); - dsssetproblem(&subsolver->dss, &subsolver->presolver.c, &subsolver->presolver.bndl, &subsolver->presolver.bndu, &subsolver->densedummy, &subsolver->presolver.sparsea, 1, &subsolver->presolver.al, &subsolver->presolver.au, subsolver->presolver.newm, &subsolver->lastbasis, basisinittype, &subsolver->dsssettings, _state); - dssoptimize(&subsolver->dss, &subsolver->dsssettings, _state); - rcopyallocv(subsolver->presolver.newn, &subsolver->dss.repx, &subsolver->xs, _state); - rcopyallocv(subsolver->presolver.newn, &subsolver->dss.replagbc, &subsolver->lagbc, _state); - rcopyallocv(subsolver->presolver.newm, &subsolver->dss.replaglc, &subsolver->laglc, _state); - icopyallocv(subsolver->presolver.newn+subsolver->presolver.newm, &subsolver->dss.repstats, &subsolver->cs, _state); - presolvebwd(&subsolver->presolver, &subsolver->xs, &subsolver->cs, &subsolver->lagbc, &subsolver->laglc, _state); - state->repsimplexiterations = state->repsimplexiterations+subsolver->dss.repiterationscount; - state->repsimplexiterations1 = state->repsimplexiterations1+subsolver->dss.repiterationscount1; - state->repsimplexiterations2 = state->repsimplexiterations2+subsolver->dss.repiterationscount2; - state->repsimplexiterations3 = state->repsimplexiterations3+subsolver->dss.repiterationscount3; - if( subsolver->dss.repterminationtype<=0 ) - { - - /* - * LP solver failed due to numerical errors; exit - */ - result = ae_false; - return result; - } - if( innerk==1 ) - { - - /* - * Store basis - */ - dssexportbasis(&subsolver->dss, &subsolver->lastbasis, _state); - subsolver->basispresent = ae_true; - } - - /* - * Extract direction D[] and Lagrange multipliers - */ - for(i=0; i<=nslack-1; i++) - { - d->ptr.p_double[i] = subsolver->xs.ptr.p_double[i]; - } - for(i=0; i<=lccnt-1; i++) - { - lagmult->ptr.p_double[i] = subsolver->laglc.ptr.p_double[i]; - } - return result; -} - - -/************************************************************************* -This function appends last search direction D to conjugacy constraints of -the LP subproblem. - - -- ALGLIB -- - Copyright 05.03.2018 by Bochkanov Sergey -*************************************************************************/ -static void nlcslp_lpsubproblemappendconjugacyconstraint(minslpstate* state, - minslpsubsolver* subsolver, - /* Real */ ae_vector* d, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_int_t j; - - - n = state->n; - - /* - * Update matrix of products H*Dprev - */ - ae_assert(subsolver->curdcntcurd.rows, "SLP: CurD is too small", _state); - for(i=0; i<=n-1; i++) - { - - /* - * Store direction and default conjugacy constraint d'*I*Dprev=0 - */ - subsolver->curd.ptr.pp_double[subsolver->curdcnt][i] = d->ptr.p_double[i]; - subsolver->curhd.ptr.pp_double[subsolver->curdcnt][i] = d->ptr.p_double[i]; - } - inc(&subsolver->curdcnt, _state); - if( state->hessiantype==1 ) - { - - /* - * Conjugacy constraint d*H*Dprev=0, full recomputation of (H*Dprev) - */ - rmatrixgemm(subsolver->curdcnt, n, n, 1.0, &subsolver->curd, 0, 0, 0, &subsolver->h, 0, 0, 0, 0.0, &subsolver->curhd, 0, 0, _state); - } - if( state->hessiantype==2 ) - { - - /* - * Conjugacy constraint d*H*Dprev=0, only last row of (H*Dprev) is recomputed - */ - rvectorsetlengthatleast(&subsolver->tmp0, n, _state); - rmatrixgemv(n, n, 1.0, &subsolver->h, 0, 0, 0, d, 0, 0.0, &subsolver->tmp0, 0, _state); - for(j=0; j<=n-1; j++) - { - subsolver->curhd.ptr.pp_double[subsolver->curdcnt-1][j] = subsolver->tmp0.ptr.p_double[j]; - } - } -} - - -/************************************************************************* -This function initializes Phase13 temporaries. It should be called before -beginning of each new iteration. You may call it multiple times for the -same instance of Phase13 temporaries. - -INPUT PARAMETERS: - State13 - instance to be initialized. - N - problem dimensionality - NEC, NIC - linear equality/inequality constraint count - NLEC, NLIC - nonlinear equality/inequality constraint count - UseCorrection - True if we want to perform second order correction - -OUTPUT PARAMETERS: - State13 - instance being initialized - - -- ALGLIB -- - Copyright 05.02.2019 by Bochkanov Sergey -*************************************************************************/ -static void nlcslp_phase13init(minslpphase13state* state13, - ae_int_t n, - ae_int_t nec, - ae_int_t nic, - ae_int_t nlec, - ae_int_t nlic, - ae_bool usecorrection, - ae_state *_state) -{ - ae_int_t nslack; - - - nslack = n+2*(nec+nlec)+(nic+nlic); - state13->usecorrection = usecorrection; - rvectorsetlengthatleast(&state13->d, nslack, _state); - rvectorsetlengthatleast(&state13->dx, nslack, _state); - rvectorsetlengthatleast(&state13->stepkxc, n, _state); - rvectorsetlengthatleast(&state13->stepkxn, n, _state); - rvectorsetlengthatleast(&state13->stepkfic, 1+nlec+nlic, _state); - rvectorsetlengthatleast(&state13->stepkfin, 1+nlec+nlic, _state); - rmatrixsetlengthatleast(&state13->stepkjc, 1+nlec+nlic, n, _state); - rmatrixsetlengthatleast(&state13->stepkjn, 1+nlec+nlic, n, _state); - rvectorsetlengthatleast(&state13->dummylagmult, nec+nic+nlec+nlic, _state); - ae_vector_set_length(&state13->rphase13state.ia, 8+1, _state); - ae_vector_set_length(&state13->rphase13state.ba, 2+1, _state); - ae_vector_set_length(&state13->rphase13state.ra, 5+1, _state); - state13->rphase13state.stage = -1; -} - - -/************************************************************************* -This function tries to perform either phase #1 or phase #3 step. - -Former corresponds to linear model step (without conjugacy constraints) with -correction for nonlinearity ("second order correction"). Such correction -helps to overcome Maratos effect (a tendency of L1 penalized merit -functions to reject nonzero steps). - -Latter is a step using linear model with no second order correction. - -INPUT PARAMETERS: - State - SLP solver state - SMonitor - smoothness monitor - UserTerminationNeeded-True if user requested termination - CurX - current point, array[N] - CurFi - function vector at CurX, array[1+NLEC+NLIC] - CurJ - Jacobian at CurX, array[1+NLEC+NLIC,N] - LagMult - array[NEC+NIC+NLEC+NLIC], contents ignored on input. - -OUTPUT PARAMETERS: - State - RepTerminationType is set to current termination code (if Status=0). - CurX - advanced to new point - CurFi - updated with function vector at CurX[] - CurJ - updated with Jacobian at CurX[] - LagMult - filled with current Lagrange multipliers - Status - when reverse communication is done, Status is set to: - * negative value, if we have to restart outer - iteration - * positive value, if we can proceed to the next stage - of the outer iteration - * zero, if algorithm is terminated (RepTerminationType - is set to appropriate value) - Stp - step length, in [0,1] - - -- ALGLIB -- - Copyright 05.02.2019 by Bochkanov Sergey -*************************************************************************/ -static ae_bool nlcslp_phase13iteration(minslpstate* state, - minslpphase13state* state13, - smoothnessmonitor* smonitor, - ae_bool userterminationneeded, - /* Real */ ae_vector* curx, - /* Real */ ae_vector* curfi, - /* Real */ ae_matrix* curj, - /* Real */ ae_vector* lagmult, - ae_int_t* status, - double* stp, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nslack; - ae_int_t nec; - ae_int_t nic; - ae_int_t nlec; - ae_int_t nlic; - ae_int_t innerk; - ae_int_t i; - ae_int_t j; - double v; - double mx; - double f0; - double f1; - double nu; - double localstp; - ae_bool dotrace; - ae_bool doprobing; - ae_bool dotracexd; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state13->rphase13state.stage>=0 ) - { - n = state13->rphase13state.ia.ptr.p_int[0]; - nslack = state13->rphase13state.ia.ptr.p_int[1]; - nec = state13->rphase13state.ia.ptr.p_int[2]; - nic = state13->rphase13state.ia.ptr.p_int[3]; - nlec = state13->rphase13state.ia.ptr.p_int[4]; - nlic = state13->rphase13state.ia.ptr.p_int[5]; - innerk = state13->rphase13state.ia.ptr.p_int[6]; - i = state13->rphase13state.ia.ptr.p_int[7]; - j = state13->rphase13state.ia.ptr.p_int[8]; - dotrace = state13->rphase13state.ba.ptr.p_bool[0]; - doprobing = state13->rphase13state.ba.ptr.p_bool[1]; - dotracexd = state13->rphase13state.ba.ptr.p_bool[2]; - v = state13->rphase13state.ra.ptr.p_double[0]; - mx = state13->rphase13state.ra.ptr.p_double[1]; - f0 = state13->rphase13state.ra.ptr.p_double[2]; - f1 = state13->rphase13state.ra.ptr.p_double[3]; - nu = state13->rphase13state.ra.ptr.p_double[4]; - localstp = state13->rphase13state.ra.ptr.p_double[5]; - } - else - { - n = 886; - nslack = 346; - nec = -722; - nic = -413; - nlec = -461; - nlic = 927; - innerk = 201; - i = 922; - j = -154; - dotrace = ae_false; - doprobing = ae_true; - dotracexd = ae_true; - v = -463; - mx = 88; - f0 = -861; - f1 = -678; - nu = -731; - localstp = -675; - } - if( state13->rphase13state.stage==0 ) - { - goto lbl_0; - } - if( state13->rphase13state.stage==1 ) - { - goto lbl_1; - } - if( state13->rphase13state.stage==2 ) - { - goto lbl_2; - } - if( state13->rphase13state.stage==3 ) - { - goto lbl_3; - } - - /* - * Routine body - */ - n = state->n; - nec = state->nec; - nic = state->nic; - nlec = state->nlec; - nlic = state->nlic; - nslack = n+2*(nec+nlec)+(nic+nlic); - innerk = 1; - dotrace = ae_is_trace_enabled("SLP"); - dotracexd = dotrace&&ae_is_trace_enabled("SLP.DETAILED"); - doprobing = ae_is_trace_enabled("SLP.PROBING"); - ae_assert(lagmult->cnt>=nec+nic+nlec+nlic, "Phase13Iteration: integrity check failed", _state); - - /* - * Report iteration beginning - */ - if( dotrace ) - { - if( state13->usecorrection ) - { - ae_trace("\n--- linear step with second-order correction -------------------------------------------------------\n"); - } - else - { - ae_trace("\n--- linear step without second-order correction ----------------------------------------------------\n"); - } - } - - /* - * Default decision is to continue algorithm - */ - *status = 1; - *stp = (double)(0); - - /* - * Determine step direction using linearized model with no conjugacy terms - */ - nlcslp_lpsubproblemrestart(state, &state->subsolver, _state); - if( !nlcslp_lpsubproblemsolve(state, &state->subsolver, curx, curfi, curj, innerk, &state13->d, lagmult, _state) ) - { - if( dotrace ) - { - ae_trace("> [WARNING] initial phase #1 LP subproblem failed\n"); - } - - /* - * Increase failures counter. - * Stop after too many subsequent failures - */ - inc(&state->lpfailurecnt, _state); - if( state->lpfailurecnt>=nlcslp_lpfailureslimit ) - { - state->repterminationtype = 7; - *status = 0; - if( dotrace ) - { - ae_trace("> stopping condition met: too many phase #1 LP failures\n"); - } - result = ae_false; - return result; - } - - /* - * Can not solve LP subproblem, decrease trust radius - */ - state->trustrad = 0.5*state->trustrad; - if( dotrace ) - { - ae_trace("> trust radius was decreased to %0.4e\n", - (double)(state->trustrad)); - } - if( ae_fp_less(state->trustrad,state->epsx) ) - { - state->repterminationtype = 2; - *status = 0; - if( dotrace ) - { - ae_trace("> stopping condition met: trust radius is smaller than %0.3e\n", - (double)(state->epsx)); - } - } - else - { - *status = -1; - } - result = ae_false; - return result; - } - nlcslp_lpsubproblemappendconjugacyconstraint(state, &state->subsolver, &state13->d, _state); - - /* - * Compute second order correction if required. The issue we address here - * is a tendency of L1 penalized function to reject steps built using simple - * linearized model when nonlinear constraints change faster than the target. - * - * The idea is that we perform trial step (stp=1) using simple linearized model, - * compute constraint vector at the new trial point - and use these updated - * constraint linearizations back at the initial point. - */ - if( !state13->usecorrection ) - { - goto lbl_4; - } - - /* - * Perform trial step using vector D to StepKXC - */ - for(i=0; i<=n-1; i++) - { - state13->stepkxc.ptr.p_double[i] = curx->ptr.p_double[i]+state13->d.ptr.p_double[i]; - } - nlcslp_slpsendx(state, &state13->stepkxc, _state); - state->needfij = ae_true; - state13->rphase13state.stage = 0; - goto lbl_rcomm; -lbl_0: - state->needfij = ae_false; - if( !nlcslp_slpretrievefij(state, &state13->stepkfic, &state13->stepkjc, _state) ) - { - - /* - * Failed to retrieve func/Jac, infinities detected - */ - state->repterminationtype = -8; - *status = 0; - if( dotrace ) - { - ae_trace("[ERROR] infinities in target/constraints are detected\n"); - } - result = ae_false; - return result; - } - - /* - * Move back to point CurX[], restore original linearization of the target - */ - state13->stepkfic.ptr.p_double[0] = curfi->ptr.p_double[0]; - for(j=0; j<=n-1; j++) - { - state13->stepkxc.ptr.p_double[j] = curx->ptr.p_double[j]; - state13->stepkjc.ptr.pp_double[0][j] = curj->ptr.pp_double[0][j]; - } - - /* - * Extrapolate linearization of nonlinear constraints back to origin - */ - for(i=1; i<=nlec+nlic; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state13->d.ptr.p_double[j]*state13->stepkjc.ptr.pp_double[i][j]; - } - state13->stepkfic.ptr.p_double[i] = state13->stepkfic.ptr.p_double[i]-v; - } - - /* - * Solve linearized problem one more time, now with new linearization of constraints - * (but still old linearization of the target), obtain DX - * - * NOTE: because lpsubproblemrestart() call resets set of conjugate constraints, we - * have to re-add it after solve. - */ - nlcslp_lpsubproblemrestart(state, &state->subsolver, _state); - if( !nlcslp_lpsubproblemsolve(state, &state->subsolver, &state13->stepkxc, &state13->stepkfic, &state13->stepkjc, innerk, &state13->dx, &state13->dummylagmult, _state) ) - { - - /* - * Second LP subproblem failed. - * Noncritical failure, can be ignored, - */ - if( dotrace ) - { - ae_trace("> [WARNING] second phase #1 LP subproblem failed\n"); - } - if( dotrace ) - { - ae_trace("> using step without second order correction\n"); - } - } - else - { - - /* - * Set D to new direction - */ - for(i=0; i<=n-1; i++) - { - state13->d.ptr.p_double[i] = state13->dx.ptr.p_double[i]; - } - } - nlcslp_lpsubproblemappendconjugacyconstraint(state, &state->subsolver, &state13->d, _state); -lbl_4: - - /* - * Perform merit function backtracking line search, with trial point being - * computed as XN = XK + Stp*D, with Stp in [0,1] - * - * NOTE: we use MeritLagMult - Lagrange multipliers computed for initial, - * uncorrected task - for the merit function model. - * Using DummyLagMult can destabilize algorithm. - */ - localstp = 1.0; - nu = 0.5; - f0 = nlcslp_meritfunction(state, curx, curfi, lagmult, &state13->tmpmerit, _state); - f1 = f0; - smoothnessmonitorstartlinesearch(smonitor, curx, curfi, curj, _state); -lbl_6: - if( ae_false ) - { - goto lbl_7; - } - for(i=0; i<=n-1; i++) - { - state13->stepkxn.ptr.p_double[i] = curx->ptr.p_double[i]+localstp*state13->d.ptr.p_double[i]; - } - nlcslp_slpsendx(state, &state13->stepkxn, _state); - state->needfij = ae_true; - state13->rphase13state.stage = 1; - goto lbl_rcomm; -lbl_1: - state->needfij = ae_false; - if( !nlcslp_slpretrievefij(state, &state13->stepkfin, &state13->stepkjn, _state) ) - { - - /* - * Failed to retrieve func/Jac, infinities detected - */ - state->repterminationtype = -8; - *status = 0; - if( dotrace ) - { - ae_trace("[ERROR] infinities in target/constraints are detected\n"); - } - result = ae_false; - return result; - } - smoothnessmonitorenqueuepoint(smonitor, &state13->d, localstp, &state13->stepkxn, &state13->stepkfin, &state13->stepkjn, _state); - f1 = nlcslp_meritfunction(state, &state13->stepkxn, &state13->stepkfin, lagmult, &state13->tmpmerit, _state); - if( ae_fp_less(f1,f0) ) - { - - /* - * Step is found! - */ - goto lbl_7; - } - if( ae_fp_less(localstp,0.001) ) - { - - /* - * Step is shorter than 0.001 times current search direction, - * it means that no good step can be found. - */ - localstp = (double)(0); - nlcslp_slpcopystate(state, curx, curfi, curj, &state13->stepkxn, &state13->stepkfin, &state13->stepkjn, _state); - goto lbl_7; - } - localstp = nu*localstp; - nu = ae_maxreal(0.1, 0.5*nu, _state); - goto lbl_6; -lbl_7: - smoothnessmonitorfinalizelinesearch(smonitor, _state); - for(i=0; i<=n-1; i++) - { - if( state->hasbndl.ptr.p_bool[i] ) - { - state13->stepkxn.ptr.p_double[i] = ae_maxreal(state13->stepkxn.ptr.p_double[i], state->scaledbndl.ptr.p_double[i], _state); - } - if( state->hasbndu.ptr.p_bool[i] ) - { - state13->stepkxn.ptr.p_double[i] = ae_minreal(state13->stepkxn.ptr.p_double[i], state->scaledbndu.ptr.p_double[i], _state); - } - } - if( userterminationneeded ) - { - - /* - * User requested termination, break before we move to new point - */ - state->repterminationtype = 8; - *status = 0; - if( dotrace ) - { - ae_trace("> user requested termination\n"); - } - result = ae_false; - return result; - } - - /* - * Trace - */ - if( !dotrace ) - { - goto lbl_8; - } - if( !doprobing ) - { - goto lbl_10; - } - smoothnessmonitorstartprobing(smonitor, 1.0, 2, state->trustrad, _state); -lbl_12: - if( !smoothnessmonitorprobe(smonitor, _state) ) - { - goto lbl_13; - } - for(j=0; j<=n-1; j++) - { - state13->stepkxc.ptr.p_double[j] = curx->ptr.p_double[j]+smonitor->probingstp*state13->d.ptr.p_double[j]; - if( state->hasbndl.ptr.p_bool[j] ) - { - state13->stepkxc.ptr.p_double[j] = ae_maxreal(state13->stepkxc.ptr.p_double[j], state->scaledbndl.ptr.p_double[j], _state); - } - if( state->hasbndu.ptr.p_bool[j] ) - { - state13->stepkxc.ptr.p_double[j] = ae_minreal(state13->stepkxc.ptr.p_double[j], state->scaledbndu.ptr.p_double[j], _state); - } - } - nlcslp_slpsendx(state, &state13->stepkxc, _state); - state->needfij = ae_true; - state13->rphase13state.stage = 2; - goto lbl_rcomm; -lbl_2: - state->needfij = ae_false; - if( !nlcslp_slpretrievefij(state, &state13->stepkfic, &state13->stepkjc, _state) ) - { - goto lbl_13; - } - smonitor->probingf.ptr.p_double[0] = nlcslp_rawlagrangian(state, &state13->stepkxc, &state13->stepkfic, lagmult, &state13->tmpmerit, _state); - smonitor->probingf.ptr.p_double[1] = state13->stepkfic.ptr.p_double[0]; - goto lbl_12; -lbl_13: - ae_trace("*** ------------------------------------------------------------\n"); - ae_trace("*** | probing search direction suggested by LP subproblem |\n"); - ae_trace("*** ------------------------------------------------------------\n"); - ae_trace("*** | Step | Lagrangian (unaugmentd)| Target function |\n"); - ae_trace("*** |along D| must be smooth | must be smooth |\n"); - ae_trace("*** | | function | slope | function | slope |\n"); - smoothnessmonitortraceprobingresults(smonitor, _state); -lbl_10: - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - mx = ae_maxreal(mx, ae_fabs(state13->d.ptr.p_double[i], _state)/state->trustrad, _state); - } - if( ae_fp_greater(localstp,(double)(0)) ) - { - ae_trace("> nonzero linear step was performed\n"); - } - else - { - ae_trace("> zero linear step was performed\n"); - } - ae_trace("max(|Di|)/TrustRad = %0.6f\n", - (double)(mx)); - ae_trace("stp = %0.6f\n", - (double)(localstp)); - if( dotracexd ) - { - ae_trace("X0 (scaled) = "); - tracevectorautoprec(curx, 0, n, _state); - ae_trace("\n"); - ae_trace("D (scaled) = "); - tracevectorautoprec(&state13->d, 0, n, _state); - ae_trace("\n"); - ae_trace("X1 (scaled) = "); - tracevectorautoprec(&state13->stepkxn, 0, n, _state); - ae_trace("\n"); - } - ae_trace("meritF: %14.6e -> %14.6e (delta=%11.3e)\n", - (double)(f0), - (double)(f1), - (double)(f1-f0)); - ae_trace("scaled-targetF: %14.6e -> %14.6e (delta=%11.3e)\n", - (double)(curfi->ptr.p_double[0]), - (double)(state13->stepkfin.ptr.p_double[0]), - (double)(state13->stepkfin.ptr.p_double[0]-curfi->ptr.p_double[0])); -lbl_8: - - /* - * Move to new point - */ - *stp = localstp; - nlcslp_slpcopystate(state, &state13->stepkxn, &state13->stepkfin, &state13->stepkjn, curx, curfi, curj, _state); - if( ae_fp_less_eq(localstp,(double)(0)) ) - { - goto lbl_14; - } - - /* - * Report one more inner iteration - */ - inc(&state->repinneriterationscount, _state); - nlcslp_slpsendx(state, curx, _state); - state->f = curfi->ptr.p_double[0]*state->fscales.ptr.p_double[0]; - state->xupdated = ae_true; - state13->rphase13state.stage = 3; - goto lbl_rcomm; -lbl_3: - state->xupdated = ae_false; - - /* - * Update constraint violations - */ - checklcviolation(&state->scaledcleic, &state->lcsrcidx, nec, nic, curx, n, &state->replcerr, &state->replcidx, _state); - unscaleandchecknlcviolation(curfi, &state->fscales, nlec, nlic, &state->repnlcerr, &state->repnlcidx, _state); -lbl_14: - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state13->rphase13state.ia.ptr.p_int[0] = n; - state13->rphase13state.ia.ptr.p_int[1] = nslack; - state13->rphase13state.ia.ptr.p_int[2] = nec; - state13->rphase13state.ia.ptr.p_int[3] = nic; - state13->rphase13state.ia.ptr.p_int[4] = nlec; - state13->rphase13state.ia.ptr.p_int[5] = nlic; - state13->rphase13state.ia.ptr.p_int[6] = innerk; - state13->rphase13state.ia.ptr.p_int[7] = i; - state13->rphase13state.ia.ptr.p_int[8] = j; - state13->rphase13state.ba.ptr.p_bool[0] = dotrace; - state13->rphase13state.ba.ptr.p_bool[1] = doprobing; - state13->rphase13state.ba.ptr.p_bool[2] = dotracexd; - state13->rphase13state.ra.ptr.p_double[0] = v; - state13->rphase13state.ra.ptr.p_double[1] = mx; - state13->rphase13state.ra.ptr.p_double[2] = f0; - state13->rphase13state.ra.ptr.p_double[3] = f1; - state13->rphase13state.ra.ptr.p_double[4] = nu; - state13->rphase13state.ra.ptr.p_double[5] = localstp; - return result; -} - - -/************************************************************************* -This function initializes Phase2 temporaries. It should be called before -beginning of each new iteration. You may call it multiple times for the -same instance of Phase2 temporaries. - -INPUT PARAMETERS: - State2 - instance to be initialized. - N - problem dimensionality - NEC, NIC - linear equality/inequality constraint count - NLEC, NLIC - nonlinear equality/inequality constraint count - MeritLagMult - Lagrange multiplier estimates used by merit function - (we could use ones computed during phase #2, - but these may differ from ones computed - initially at the beginning of the outer - iteration, so it may confuse algorithm) - -OUTPUT PARAMETERS: - State2 - instance being initialized - - -- ALGLIB -- - Copyright 05.02.2019 by Bochkanov Sergey -*************************************************************************/ -static void nlcslp_phase2init(minslpphase2state* state2, - ae_int_t n, - ae_int_t nec, - ae_int_t nic, - ae_int_t nlec, - ae_int_t nlic, - /* Real */ ae_vector* meritlagmult, - ae_state *_state) -{ - ae_int_t i; - ae_int_t nslack; - - - nslack = n+2*(nec+nlec)+(nic+nlic); - rvectorsetlengthatleast(&state2->d, nslack, _state); - rvectorsetlengthatleast(&state2->tmp0, nslack, _state); - rvectorsetlengthatleast(&state2->stepkxn, n, _state); - rvectorsetlengthatleast(&state2->stepkxc, n, _state); - rvectorsetlengthatleast(&state2->stepkfin, 1+nlec+nlic, _state); - rvectorsetlengthatleast(&state2->stepkfic, 1+nlec+nlic, _state); - rmatrixsetlengthatleast(&state2->stepkjn, 1+nlec+nlic, n, _state); - rmatrixsetlengthatleast(&state2->stepkjc, 1+nlec+nlic, n, _state); - rvectorsetlengthatleast(&state2->stepklaggrad, n, _state); - rvectorsetlengthatleast(&state2->stepknlaggrad, n, _state); - rvectorsetlengthatleast(&state2->stepknlagmult, nec+nic+nlec+nlic, _state); - rvectorsetlengthatleast(&state2->meritlagmult, nec+nic+nlec+nlic, _state); - for(i=0; i<=nec+nic+nlec+nlic-1; i++) - { - state2->meritlagmult.ptr.p_double[i] = meritlagmult->ptr.p_double[i]; - } - ae_vector_set_length(&state2->rphase2state.ia, 12+1, _state); - ae_vector_set_length(&state2->rphase2state.ba, 2+1, _state); - ae_vector_set_length(&state2->rphase2state.ra, 8+1, _state); - state2->rphase2state.stage = -1; -} - - -/************************************************************************* -This function tries to perform phase #2 iterations. - -Phase #2 is a sequence of linearized steps minimizing L2-penalized -Lagrangian performed with successively increasing set of conjugacy -constraints (which make algorithm behavior similar to that of CG). - -INPUT PARAMETERS: - State - SLP solver state - SMonitor - smoothness monitor - UserTerminationNeeded-True if user requested termination - CurX - current point, array[N] - CurFi - function vector at CurX, array[1+NLEC+NLIC] - CurJ - Jacobian at CurX, array[1+NLEC+NLIC,N] - LagMult - array[NEC+NIC+NLEC+NLIC], contents ignored on input. - GammaMax - current estimate of the Hessian norm - -OUTPUT PARAMETERS: - State - RepTerminationType is set to current termination code (if Status=0). - CurX - advanced to new point - CurFi - updated with function vector at CurX[] - CurJ - updated with Jacobian at CurX[] - LagMult - filled with current Lagrange multipliers - GammaMax - updated estimate of the Hessian norm - Status - when reverse communication is done, Status is set to: - * negative value, if we have to restart outer - iteration - * positive value, if we can proceed to the next stage - of the outer iteration - * zero, if algorithm is terminated (RepTerminationType - is set to appropriate value) - - -- ALGLIB -- - Copyright 05.02.2019 by Bochkanov Sergey -*************************************************************************/ -static ae_bool nlcslp_phase2iteration(minslpstate* state, - minslpphase2state* state2, - smoothnessmonitor* smonitor, - ae_bool userterminationneeded, - /* Real */ ae_vector* curx, - /* Real */ ae_vector* curfi, - /* Real */ ae_matrix* curj, - /* Real */ ae_vector* lagmult, - double* gammamax, - ae_int_t* status, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nslack; - ae_int_t nec; - ae_int_t nic; - ae_int_t nlec; - ae_int_t nlic; - double stp; - ae_int_t mcinfo; - ae_int_t mcnfev; - ae_int_t mcstage; - ae_int_t i; - ae_int_t j; - ae_int_t innerk; - double v; - double vv; - double mx; - ae_int_t nondescentcnt; - double stepklagval; - double stepknlagval; - double gammaprev; - double f0; - double f1; - ae_bool dotrace; - ae_bool doprobing; - ae_bool dotracexd; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state2->rphase2state.stage>=0 ) - { - n = state2->rphase2state.ia.ptr.p_int[0]; - nslack = state2->rphase2state.ia.ptr.p_int[1]; - nec = state2->rphase2state.ia.ptr.p_int[2]; - nic = state2->rphase2state.ia.ptr.p_int[3]; - nlec = state2->rphase2state.ia.ptr.p_int[4]; - nlic = state2->rphase2state.ia.ptr.p_int[5]; - mcinfo = state2->rphase2state.ia.ptr.p_int[6]; - mcnfev = state2->rphase2state.ia.ptr.p_int[7]; - mcstage = state2->rphase2state.ia.ptr.p_int[8]; - i = state2->rphase2state.ia.ptr.p_int[9]; - j = state2->rphase2state.ia.ptr.p_int[10]; - innerk = state2->rphase2state.ia.ptr.p_int[11]; - nondescentcnt = state2->rphase2state.ia.ptr.p_int[12]; - dotrace = state2->rphase2state.ba.ptr.p_bool[0]; - doprobing = state2->rphase2state.ba.ptr.p_bool[1]; - dotracexd = state2->rphase2state.ba.ptr.p_bool[2]; - stp = state2->rphase2state.ra.ptr.p_double[0]; - v = state2->rphase2state.ra.ptr.p_double[1]; - vv = state2->rphase2state.ra.ptr.p_double[2]; - mx = state2->rphase2state.ra.ptr.p_double[3]; - stepklagval = state2->rphase2state.ra.ptr.p_double[4]; - stepknlagval = state2->rphase2state.ra.ptr.p_double[5]; - gammaprev = state2->rphase2state.ra.ptr.p_double[6]; - f0 = state2->rphase2state.ra.ptr.p_double[7]; - f1 = state2->rphase2state.ra.ptr.p_double[8]; - } - else - { - n = -763; - nslack = -233; - nec = -936; - nic = -279; - nlec = 94; - nlic = -812; - mcinfo = 427; - mcnfev = 178; - mcstage = -819; - i = -826; - j = 667; - innerk = 692; - nondescentcnt = 84; - dotrace = ae_true; - doprobing = ae_false; - dotracexd = ae_false; - stp = -908; - v = 577; - vv = 289; - mx = 317; - stepklagval = 476; - stepknlagval = -889; - gammaprev = -400; - f0 = 489; - f1 = -962; - } - if( state2->rphase2state.stage==0 ) - { - goto lbl_0; - } - if( state2->rphase2state.stage==1 ) - { - goto lbl_1; - } - if( state2->rphase2state.stage==2 ) - { - goto lbl_2; - } - - /* - * Routine body - */ - n = state->n; - nec = state->nec; - nic = state->nic; - nlec = state->nlec; - nlic = state->nlic; - nslack = n+2*(nec+nlec)+(nic+nlic); - dotrace = ae_is_trace_enabled("SLP"); - dotracexd = dotrace&&ae_is_trace_enabled("SLP.DETAILED"); - doprobing = ae_is_trace_enabled("SLP.PROBING"); - ae_assert(lagmult->cnt>=nec+nic+nlec+nlic, "Phase13Iteration: integrity check failed", _state); - - /* - * Report iteration beginning - */ - if( dotrace ) - { - ae_trace("\n--- linear step with conjugate constraints (CG-like convergence) -----------------------------------\n"); - } - - /* - * The default decision is to continue iterations - */ - *status = 1; - - /* - * Perform inner LP subiterations. - * - * During this process we maintain information about several points: - * * point #0, initial one, with "step0" prefix - * * point #K, last one of current LP session, with "stepk" prefix - * * additionally we have point #KN, current candidate during line search at step K. - * - * For each point we store: - * * location X (scaled coordinates) - * * function vector Fi (target function + nonlinear constraints) - * * scaled Jacobian J - */ - nondescentcnt = 0; - nlcslp_lpsubproblemrestart(state, &state->subsolver, _state); - innerk = 1; -lbl_3: - if( innerk>n ) - { - goto lbl_5; - } - - /* - * Formulate LP subproblem and solve it - */ - if( !nlcslp_lpsubproblemsolve(state, &state->subsolver, curx, curfi, curj, innerk, &state2->d, lagmult, _state) ) - { - - /* - * LP solver failed due to numerical errors; exit. - * It may happen when we solve problem with LOTS of conjugacy constraints. - */ - if( innerk==1 ) - { - - /* - * The very first iteration failed, really strange. - */ - if( dotrace ) - { - ae_trace("[WARNING] the very first LP subproblem failed to produce descent direction\n"); - } - } - else - { - - /* - * Quite a normal, the problem is overconstrained by conjugacy constraints now - */ - if( dotrace ) - { - ae_trace("> LP subproblem is overconstrained (happens after too many iterations), time to stop\n"); - } - } - result = ae_false; - return result; - } - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - mx = ae_maxreal(mx, ae_fabs(state2->d.ptr.p_double[i], _state)/state->trustrad, _state); - } - if( ae_fp_eq(mx,(double)(0)) ) - { - - /* - * Nearly-zero direction is suggested (maybe we arrived exactly to the solution), stop iterations - */ - *status = 1; - nlcslp_slpcopystate(state, curx, curfi, curj, &state2->stepkxn, &state2->stepkfin, &state2->stepkjn, _state); - if( dotrace ) - { - ae_trace("> LP subproblem suggested nearly zero step\n"); - } - if( dotrace ) - { - ae_trace("max(|Di|)/TrustRad = %0.6f\n", - (double)(mx)); - } - if( dotrace ) - { - ae_trace("> stopping CG-like iterations\n"); - } - result = ae_false; - return result; - } - nlcslp_lpsubproblemappendconjugacyconstraint(state, &state->subsolver, &state2->d, _state); - - /* - * Perform line search to minimize Lagrangian along D. - * Post-normalize StepKXN with respect to box constraints. - * - * MCSRCH can fail in the following cases: - * * rounding errors prevent optimization - * * non-descent direction is specified (MCINFO=0 is returned) - * In the latter case we proceed to minimization of merit function. - * - * NOTE: constraint violation reports are updated during Lagrangian computation - */ - state2->lastlcerr = (double)(0); - state2->lastlcidx = -1; - state2->lastnlcerr = (double)(0); - state2->lastnlcidx = -1; - rvectorsetlengthatleast(&state2->tmp0, n, _state); - nlcslp_lagrangianfg(state, curx, state->trustrad, curfi, curj, lagmult, &state2->tmplagrangianfg, &stepklagval, &state2->stepklaggrad, &state2->lastlcerr, &state2->lastlcidx, &state2->lastnlcerr, &state2->lastnlcidx, _state); - nlcslp_slpcopystate(state, curx, curfi, curj, &state2->stepkxn, &state2->stepkfin, &state2->stepkjn, _state); - v = (double)(0); - for(i=0; i<=n-1; i++) - { - state2->stepknlaggrad.ptr.p_double[i] = state2->stepklaggrad.ptr.p_double[i]; - v = v+state2->d.ptr.p_double[i]*state2->stepklaggrad.ptr.p_double[i]; - } - if( ae_fp_greater_eq(v,(double)(0)) ) - { - - /* - * Non-descent direction D was specified; it may happen because LP subproblem favors - * directions which decrease L1 penalty and default augmentation of Lagrangian involves - * only L2 term. - * - * Append direction to the conjugacy constraints and retry direction generation. - * - * We make several retries with conjugate directions before giving up. - */ - if( dotrace ) - { - ae_trace("> LP subproblem suggested nondescent step, skipping it (dLag=%0.3e)\n", - (double)(v)); - } - inc(&nondescentcnt, _state); - if( nlcslp_nondescentlimit>0&&nondescentcnt>nlcslp_nondescentlimit ) - { - if( dotrace ) - { - ae_trace("> too many nondescent steps, stopping CG-like iterations\n"); - } - *status = 1; - result = ae_false; - return result; - } - goto lbl_4; - } - smoothnessmonitorstartlinesearch(smonitor, curx, curfi, curj, _state); - stepknlagval = stepklagval; - mcnfev = 0; - mcstage = 0; - stp = 1.0; - mcsrch(n, &state2->stepkxn, &stepknlagval, &state2->stepknlaggrad, &state2->d, &stp, 1.0, nlcslp_slpgtol, &mcinfo, &mcnfev, &state2->tmp0, &state2->mcstate, &mcstage, _state); -lbl_6: - if( mcstage==0 ) - { - goto lbl_7; - } - nlcslp_slpsendx(state, &state2->stepkxn, _state); - state->needfij = ae_true; - state2->rphase2state.stage = 0; - goto lbl_rcomm; -lbl_0: - state->needfij = ae_false; - if( !nlcslp_slpretrievefij(state, &state2->stepkfin, &state2->stepkjn, _state) ) - { - - /* - * Failed to retrieve func/Jac, infinities detected - */ - *status = 0; - state->repterminationtype = -8; - if( dotrace ) - { - ae_trace("[ERROR] infinities in target/constraints are detected\n"); - } - result = ae_false; - return result; - } - smoothnessmonitorenqueuepoint(smonitor, &state2->d, stp, &state2->stepkxn, &state2->stepkfin, &state2->stepkjn, _state); - nlcslp_lagrangianfg(state, &state2->stepkxn, state->trustrad, &state2->stepkfin, &state2->stepkjn, lagmult, &state2->tmplagrangianfg, &stepknlagval, &state2->stepknlaggrad, &state2->lastlcerr, &state2->lastlcidx, &state2->lastnlcerr, &state2->lastnlcidx, _state); - mcsrch(n, &state2->stepkxn, &stepknlagval, &state2->stepknlaggrad, &state2->d, &stp, 1.0, nlcslp_slpgtol, &mcinfo, &mcnfev, &state2->tmp0, &state2->mcstate, &mcstage, _state); - goto lbl_6; -lbl_7: - smoothnessmonitorfinalizelinesearch(smonitor, _state); - for(i=0; i<=n-1; i++) - { - if( state->hasbndl.ptr.p_bool[i] ) - { - state2->stepkxn.ptr.p_double[i] = ae_maxreal(state2->stepkxn.ptr.p_double[i], state->scaledbndl.ptr.p_double[i], _state); - } - if( state->hasbndu.ptr.p_bool[i] ) - { - state2->stepkxn.ptr.p_double[i] = ae_minreal(state2->stepkxn.ptr.p_double[i], state->scaledbndu.ptr.p_double[i], _state); - } - } - if( mcinfo<=0 ) - { - - /* - * Line search failed miserably, terminate - */ - *status = 1; - if( innerk==1 ) - { - - /* - * The very first iteration failed, really strange. - * Let's decrease trust radius and try one more time. - */ - state->trustrad = 0.5*state->trustrad; - if( dotrace ) - { - ae_trace("> line search failed miserably for unknown reason, decreasing trust radius\n"); - } - if( ae_fp_less(state->trustrad,state->epsx) ) - { - state->repterminationtype = 2; - *status = 0; - if( dotrace ) - { - ae_trace("> stopping condition met: trust radius is smaller than %0.3e\n", - (double)(state->epsx)); - } - } - } - else - { - - /* - * Well, it can be normal - */ - if( dotrace ) - { - ae_trace("> line search failed miserably for unknown reason, proceeding further\n"); - } - } - result = ae_false; - return result; - } - if( mcinfo==1 ) - { - nlcslp_lpsubproblemupdatehessian(state, &state->subsolver, curx, &state2->stepklaggrad, &state2->stepkxn, &state2->stepknlaggrad, _state); - } - - /* - * Update GammaMax - estimate of the function Hessian norm - */ - v = (double)(0); - vv = (double)(0); - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - mx = ae_maxreal(mx, ae_fabs(state2->stepkxn.ptr.p_double[i]-curx->ptr.p_double[i], _state), _state); - v = v+ae_sqr(state2->stepkxn.ptr.p_double[i]-curx->ptr.p_double[i], _state); - vv = vv+(state2->stepkjn.ptr.pp_double[0][i]-curj->ptr.pp_double[0][i])*(state2->stepkxn.ptr.p_double[i]-curx->ptr.p_double[i]); - } - gammaprev = *gammamax; - if( ae_fp_greater(mx,nlcslp_bfgstol) ) - { - *gammamax = ae_maxreal(*gammamax, ae_fabs(vv/v, _state), _state); - } - - /* - * Trace - */ - if( !dotrace ) - { - goto lbl_8; - } - if( !doprobing ) - { - goto lbl_10; - } - smoothnessmonitorstartprobing(smonitor, 1.0, 2, state->trustrad, _state); -lbl_12: - if( !smoothnessmonitorprobe(smonitor, _state) ) - { - goto lbl_13; - } - for(j=0; j<=n-1; j++) - { - state2->stepkxc.ptr.p_double[j] = curx->ptr.p_double[j]+smonitor->probingstp*state2->d.ptr.p_double[j]; - if( state->hasbndl.ptr.p_bool[j] ) - { - state2->stepkxc.ptr.p_double[j] = ae_maxreal(state2->stepkxc.ptr.p_double[j], state->scaledbndl.ptr.p_double[j], _state); - } - if( state->hasbndu.ptr.p_bool[j] ) - { - state2->stepkxc.ptr.p_double[j] = ae_minreal(state2->stepkxc.ptr.p_double[j], state->scaledbndu.ptr.p_double[j], _state); - } - } - nlcslp_slpsendx(state, &state2->stepkxc, _state); - state->needfij = ae_true; - state2->rphase2state.stage = 1; - goto lbl_rcomm; -lbl_1: - state->needfij = ae_false; - if( !nlcslp_slpretrievefij(state, &state2->stepkfic, &state2->stepkjc, _state) ) - { - goto lbl_13; - } - smonitor->probingf.ptr.p_double[0] = nlcslp_rawlagrangian(state, &state2->stepkxc, &state2->stepkfic, lagmult, &state2->tmpmerit, _state); - smonitor->probingf.ptr.p_double[1] = state2->stepkfic.ptr.p_double[0]; - goto lbl_12; -lbl_13: - ae_trace("*** ------------------------------------------------------------\n"); - ae_trace("*** | probing search direction suggested by LP subproblem |\n"); - ae_trace("*** ------------------------------------------------------------\n"); - ae_trace("*** | Step | Lagrangian (unaugmentd)| Target function |\n"); - ae_trace("*** |along D| must be smooth | must be smooth |\n"); - ae_trace("*** | | function | slope | function | slope |\n"); - smoothnessmonitortraceprobingresults(smonitor, _state); -lbl_10: - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - mx = ae_maxreal(mx, ae_fabs(state2->d.ptr.p_double[i], _state)/state->trustrad, _state); - } - f0 = nlcslp_meritfunction(state, curx, curfi, &state2->meritlagmult, &state2->tmpmerit, _state); - f1 = nlcslp_meritfunction(state, &state2->stepkxn, &state2->stepkfin, &state2->meritlagmult, &state2->tmpmerit, _state); - ae_trace("> LP subproblem produced good direction, minimization was performed\n"); - ae_trace("max(|Di|)/TrustRad = %0.6f\n", - (double)(mx)); - ae_trace("stp = %0.6f\n", - (double)(stp)); - if( dotracexd ) - { - ae_trace("X0 = "); - tracevectorautoprec(curx, 0, n, _state); - ae_trace("\n"); - ae_trace("D = "); - tracevectorautoprec(&state2->d, 0, n, _state); - ae_trace("\n"); - ae_trace("X1 = X0 + stp*D\n"); - ae_trace(" = "); - tracevectorautoprec(&state2->stepkxn, 0, n, _state); - ae_trace("\n"); - } - ae_trace("meritF: %14.6e -> %14.6e (delta=%11.3e)\n", - (double)(f0), - (double)(f1), - (double)(f1-f0)); - ae_trace("scaled-targetF: %14.6e -> %14.6e (delta=%11.3e)\n", - (double)(curfi->ptr.p_double[0]), - (double)(state2->stepkfin.ptr.p_double[0]), - (double)(state2->stepkfin.ptr.p_double[0]-curfi->ptr.p_double[0])); - ae_trace("aug.Lagrangian: %14.6e -> %14.6e (delta=%11.3e)\n", - (double)(stepklagval), - (double)(stepknlagval), - (double)(stepknlagval-stepklagval)); - if( ae_fp_greater(*gammamax,gammaprev) ) - { - ae_trace("|H| = %0.3e (Hessian norm increased)\n", - (double)(*gammamax)); - } -lbl_8: - - /* - * Check status of the termination request - * Update current point - * Update constraint status. - * Report iteration. - */ - if( userterminationneeded ) - { - - /* - * User requested termination, break before we move to new point - */ - *status = 0; - state->repterminationtype = 8; - if( dotrace ) - { - ae_trace("# user requested termination\n"); - } - result = ae_false; - return result; - } - nlcslp_slpcopystate(state, &state2->stepkxn, &state2->stepkfin, &state2->stepkjn, curx, curfi, curj, _state); - state->replcerr = state2->lastlcerr; - state->replcidx = state2->lastlcidx; - state->repnlcerr = state2->lastnlcerr; - state->repnlcidx = state2->lastnlcidx; - inc(&state->repinneriterationscount, _state); - nlcslp_slpsendx(state, curx, _state); - state->f = curfi->ptr.p_double[0]*state->fscales.ptr.p_double[0]; - state->xupdated = ae_true; - state2->rphase2state.stage = 2; - goto lbl_rcomm; -lbl_2: - state->xupdated = ae_false; - - /* - * Terminate inner LP subiterations - */ - if( state->maxits>0&&state->repinneriterationscount>=state->maxits ) - { - - /* - * Iteration limit exhausted - */ - *status = 1; - if( dotrace ) - { - ae_trace("# stopping criteria met (MaxIts iterations performed)\n"); - } - result = ae_false; - return result; - } - if( ae_fp_greater_eq(stp,nlcslp_slpstpclosetoone) ) - { - - /* - * Step is close to 1.0, either of two is likely: - * * we move through nearly linear region of F() - * * we try to enforce some strongly violated constraint - * - * In any case, authors of the original algorithm recommend to break inner LP - * iteration and proceed to test of sufficient decrease of merit function. - */ - *status = 1; - if( dotrace ) - { - ae_trace("> step is close to 1, stopping iterations\n"); - } - result = ae_false; - return result; - } - if( (mcinfo!=1&&mcinfo!=3)&&mcinfo!=5 ) - { - - /* - * Line search ended with "bad" MCINFO - * (neither sufficient decrease, neither maximum step); - * terminate. - */ - *status = 1; - if( dotrace ) - { - ae_trace("> line search ended with bad MCINFO, no more CG-like iterations\n"); - } - result = ae_false; - return result; - } -lbl_4: - innerk = innerk+1; - goto lbl_3; -lbl_5: - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state2->rphase2state.ia.ptr.p_int[0] = n; - state2->rphase2state.ia.ptr.p_int[1] = nslack; - state2->rphase2state.ia.ptr.p_int[2] = nec; - state2->rphase2state.ia.ptr.p_int[3] = nic; - state2->rphase2state.ia.ptr.p_int[4] = nlec; - state2->rphase2state.ia.ptr.p_int[5] = nlic; - state2->rphase2state.ia.ptr.p_int[6] = mcinfo; - state2->rphase2state.ia.ptr.p_int[7] = mcnfev; - state2->rphase2state.ia.ptr.p_int[8] = mcstage; - state2->rphase2state.ia.ptr.p_int[9] = i; - state2->rphase2state.ia.ptr.p_int[10] = j; - state2->rphase2state.ia.ptr.p_int[11] = innerk; - state2->rphase2state.ia.ptr.p_int[12] = nondescentcnt; - state2->rphase2state.ba.ptr.p_bool[0] = dotrace; - state2->rphase2state.ba.ptr.p_bool[1] = doprobing; - state2->rphase2state.ba.ptr.p_bool[2] = dotracexd; - state2->rphase2state.ra.ptr.p_double[0] = stp; - state2->rphase2state.ra.ptr.p_double[1] = v; - state2->rphase2state.ra.ptr.p_double[2] = vv; - state2->rphase2state.ra.ptr.p_double[3] = mx; - state2->rphase2state.ra.ptr.p_double[4] = stepklagval; - state2->rphase2state.ra.ptr.p_double[5] = stepknlagval; - state2->rphase2state.ra.ptr.p_double[6] = gammaprev; - state2->rphase2state.ra.ptr.p_double[7] = f0; - state2->rphase2state.ra.ptr.p_double[8] = f1; - return result; -} - - -/************************************************************************* -Copies X to State.X -*************************************************************************/ -static void nlcslp_slpsendx(minslpstate* state, - /* Real */ ae_vector* xs, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - - - n = state->n; - for(i=0; i<=n-1; i++) - { - if( state->hasbndl.ptr.p_bool[i]&&xs->ptr.p_double[i]<=state->scaledbndl.ptr.p_double[i] ) - { - state->x.ptr.p_double[i] = state->scaledbndl.ptr.p_double[i]; - continue; - } - if( state->hasbndu.ptr.p_bool[i]&&xs->ptr.p_double[i]>=state->scaledbndu.ptr.p_double[i] ) - { - state->x.ptr.p_double[i] = state->scaledbndu.ptr.p_double[i]; - continue; - } - state->x.ptr.p_double[i] = xs->ptr.p_double[i]; - } -} - - -/************************************************************************* -Retrieves F-vector and scaled Jacobian, copies them to FiS and JS. - -Returns True on success, False on failure (when F or J are not finite numbers). -*************************************************************************/ -static ae_bool nlcslp_slpretrievefij(minslpstate* state, - /* Real */ ae_vector* fis, - /* Real */ ae_matrix* js, - ae_state *_state) -{ - ae_int_t nlec; - ae_int_t nlic; - ae_int_t n; - ae_int_t i; - ae_int_t j; - double v; - double vv; - ae_bool result; - - - n = state->n; - nlec = state->nlec; - nlic = state->nlic; - v = (double)(0); - for(i=0; i<=nlec+nlic; i++) - { - vv = 1/state->fscales.ptr.p_double[i]; - fis->ptr.p_double[i] = vv*state->fi.ptr.p_double[i]; - v = 0.1*v+fis->ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - js->ptr.pp_double[i][j] = vv*state->j.ptr.pp_double[i][j]; - v = 0.1*v+js->ptr.pp_double[i][j]; - } - } - result = ae_isfinite(v, _state); - return result; -} - - -/************************************************************************* -Copies state (X point, Fi vector, J jacobian) to preallocated storage. -*************************************************************************/ -static void nlcslp_slpcopystate(minslpstate* state, - /* Real */ ae_vector* x0, - /* Real */ ae_vector* fi0, - /* Real */ ae_matrix* j0, - /* Real */ ae_vector* x1, - /* Real */ ae_vector* fi1, - /* Real */ ae_matrix* j1, - ae_state *_state) -{ - ae_int_t nlec; - ae_int_t nlic; - ae_int_t n; - ae_int_t i; - ae_int_t j; - - - n = state->n; - nlec = state->nlec; - nlic = state->nlic; - for(i=0; i<=n-1; i++) - { - x1->ptr.p_double[i] = x0->ptr.p_double[i]; - } - for(i=0; i<=nlec+nlic; i++) - { - fi1->ptr.p_double[i] = fi0->ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - j1->ptr.pp_double[i][j] = j0->ptr.pp_double[i][j]; - } - } -} - - -/************************************************************************* -This function calculates Lagrangian of the problem (in scaled variables): -its value and gradient. - -Additionally it also estimates violation of linear constraints at the point -as well as index of the most violated constraint -*************************************************************************/ -static void nlcslp_lagrangianfg(minslpstate* state, - /* Real */ ae_vector* x, - double trustrad, - /* Real */ ae_vector* fi, - /* Real */ ae_matrix* j, - /* Real */ ae_vector* lagmult, - minslptmplagrangian* tmp, - double* f, - /* Real */ ae_vector* g, - double* lcerr, - ae_int_t* lcidx, - double* nlcerr, - ae_int_t* nlcidx, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - ae_int_t nec; - ae_int_t nic; - ae_int_t nlec; - ae_int_t nlic; - double v; - double vlag; - double vact; - double vd; - double vviolate; - ae_bool usesparsegemv; - double dampingfactor; - - *f = 0; - *lcerr = 0; - *lcidx = 0; - *nlcerr = 0; - *nlcidx = 0; - - n = state->n; - nec = state->nec; - nic = state->nic; - nlec = state->nlec; - nlic = state->nlic; - dampingfactor = nlcslp_inequalitydampingfactor/trustrad; - - /* - * Prepare constraint violation report - */ - *lcerr = (double)(0); - *lcidx = -1; - *nlcerr = (double)(0); - *nlcidx = -1; - - /* - * Target function - */ - *f = fi->ptr.p_double[0]; - for(i=0; i<=n-1; i++) - { - g->ptr.p_double[i] = j->ptr.pp_double[0][i]; - } - - /* - * Lagrangian terms for linear constraints, constraint violations - */ - if( nec+nic>0 ) - { - usesparsegemv = state->subsolver.sparserawlc.ridx.ptr.p_int[nec+nic]sclagtmp0, ae_maxint(nec+nic, n, _state), _state); - rvectorsetlengthatleast(&tmp->sclagtmp1, ae_maxint(nec+nic, n, _state), _state); - if( usesparsegemv ) - { - sparsemv(&state->subsolver.sparserawlc, x, &tmp->sclagtmp0, _state); - } - else - { - rmatrixgemv(nec+nic, n, 1.0, &state->scaledcleic, 0, 0, 0, x, 0, 0.0, &tmp->sclagtmp0, 0, _state); - } - for(i=0; i<=nec+nic-1; i++) - { - - /* - * Estimate constraint value at the point, update violation info - * - * NOTE: here we expect that scaledCLEIC[] has normalized rows - */ - v = tmp->sclagtmp0.ptr.p_double[i]-state->scaledcleic.ptr.pp_double[i][n]; - if( i0 ) - { - - /* - * Either equality constraint or violated inequality one. - * Update violation report. - */ - vviolate = ae_fabs(v, _state); - if( vviolate>*lcerr ) - { - *lcerr = vviolate; - *lcidx = state->lcsrcidx.ptr.p_int[i]; - } - } - - /* - * Prepare - */ - vlag = lagmult->ptr.p_double[i]; - tmp->sclagtmp1.ptr.p_double[i] = (double)(0); - - /* - * Primary Lagrangian term - */ - if( i0 ) - { - vact = v; - vd = (double)(1); - } - else - { - vd = 1/(1-dampingfactor*v); - vact = v*vd; - vd = vd*vd; - } - *f = *f+vlag*vact; - tmp->sclagtmp1.ptr.p_double[i] = tmp->sclagtmp1.ptr.p_double[i]+vlag*vd; - - /* - * Quadratic augmentation term - */ - if( i0 ) - { - vact = v; - } - else - { - vact = (double)(0); - } - *f = *f+0.5*nlcslp_augmentationfactor*vact*vact; - tmp->sclagtmp1.ptr.p_double[i] = tmp->sclagtmp1.ptr.p_double[i]+nlcslp_augmentationfactor*vact; - } - if( usesparsegemv ) - { - sparsemtv(&state->subsolver.sparserawlc, &tmp->sclagtmp1, &tmp->sclagtmp0, _state); - for(i=0; i<=n-1; i++) - { - g->ptr.p_double[i] = g->ptr.p_double[i]+tmp->sclagtmp0.ptr.p_double[i]; - } - } - else - { - rmatrixgemv(n, nec+nic, 1.0, &state->scaledcleic, 0, 0, 1, &tmp->sclagtmp1, 0, 1.0, g, 0, _state); - } - } - - /* - * Lagrangian terms for nonlinear constraints - */ - rvectorsetlengthatleast(&tmp->sclagtmp1, nlec+nlic, _state); - for(i=0; i<=nlec+nlic-1; i++) - { - v = fi->ptr.p_double[1+i]; - if( i0 ) - { - - /* - * Either equality constraint or violated inequality one. - * Update violation report. - */ - vviolate = ae_fabs(v, _state)*state->fscales.ptr.p_double[1+i]; - if( vviolate>*nlcerr ) - { - *nlcerr = vviolate; - *nlcidx = i; - } - } - vlag = lagmult->ptr.p_double[nec+nic+i]; - tmp->sclagtmp1.ptr.p_double[i] = (double)(0); - - /* - * Lagrangian term - */ - if( i0 ) - { - vact = v; - vd = (double)(1); - } - else - { - vd = 1/(1-dampingfactor*v); - vact = v*vd; - vd = vd*vd; - } - *f = *f+vlag*vact; - tmp->sclagtmp1.ptr.p_double[i] = tmp->sclagtmp1.ptr.p_double[i]+vlag*vd; - - /* - * Augmentation term - */ - if( i0 ) - { - vact = v; - } - else - { - vact = (double)(0); - } - *f = *f+0.5*nlcslp_augmentationfactor*vact*vact; - tmp->sclagtmp1.ptr.p_double[i] = tmp->sclagtmp1.ptr.p_double[i]+nlcslp_augmentationfactor*vact; - } - rmatrixgemv(n, nlec+nlic, 1.0, j, 1, 0, 1, &tmp->sclagtmp1, 0, 1.0, g, 0, _state); -} - - -/************************************************************************* -This function calculates L1-penalized merit function -*************************************************************************/ -static double nlcslp_meritfunction(minslpstate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* fi, - /* Real */ ae_vector* lagmult, - minslptmpmerit* tmp, - ae_state *_state) -{ - double tmp0; - double tmp1; - double result; - - - nlcslp_meritfunctionandrawlagrangian(state, x, fi, lagmult, tmp, &tmp0, &tmp1, _state); - result = tmp0; - return result; -} - - -/************************************************************************* -This function calculates raw (unaugmented and smooth) Lagrangian -*************************************************************************/ -static double nlcslp_rawlagrangian(minslpstate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* fi, - /* Real */ ae_vector* lagmult, - minslptmpmerit* tmp, - ae_state *_state) -{ - double tmp0; - double tmp1; - double result; - - - nlcslp_meritfunctionandrawlagrangian(state, x, fi, lagmult, tmp, &tmp0, &tmp1, _state); - result = tmp1; - return result; -} - - -/************************************************************************* -This function calculates L1-penalized merit function and raw (smooth and -un-augmented) Lagrangian -*************************************************************************/ -static void nlcslp_meritfunctionandrawlagrangian(minslpstate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* fi, - /* Real */ ae_vector* lagmult, - minslptmpmerit* tmp, - double* meritf, - double* rawlag, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - ae_int_t nec; - ae_int_t nic; - ae_int_t nlec; - ae_int_t nlic; - double v; - - *meritf = 0; - *rawlag = 0; - - n = state->n; - nec = state->nec; - nic = state->nic; - nlec = state->nlec; - nlic = state->nlic; - - /* - * Merit function and Lagrangian: primary term - */ - *meritf = fi->ptr.p_double[0]; - *rawlag = fi->ptr.p_double[0]; - - /* - * Merit function: augmentation and penalty for linear constraints - */ - rvectorsetlengthatleast(&tmp->mftmp0, nec+nic, _state); - rmatrixgemv(nec+nic, n, 1.0, &state->scaledcleic, 0, 0, 0, x, 0, 0.0, &tmp->mftmp0, 0, _state); - for(i=0; i<=nec+nic-1; i++) - { - v = tmp->mftmp0.ptr.p_double[i]-state->scaledcleic.ptr.pp_double[i][n]; - if( iptr.p_double[i], _state)*ae_fabs(v, _state); - - /* - * Raw Lagrangian - */ - *rawlag = *rawlag+lagmult->ptr.p_double[i]*v; - } - else - { - - /* - * Merit function: augmentation term + L1 penalty term - */ - *meritf = *meritf+0.5*nlcslp_augmentationfactor*ae_sqr(ae_maxreal(v, (double)(0), _state), _state); - *meritf = *meritf+nlcslp_meritfunctionbase*ae_maxreal(v, (double)(0), _state)+nlcslp_meritfunctiongain*ae_maxreal(lagmult->ptr.p_double[i]*v, (double)(0), _state); - - /* - * Raw Lagrangian - */ - *rawlag = *rawlag+lagmult->ptr.p_double[i]*v; - } - } - - /* - * Merit function: augmentation and penalty for nonlinear constraints - */ - for(i=0; i<=nlec+nlic-1; i++) - { - v = fi->ptr.p_double[1+i]; - if( iptr.p_double[nec+nic+i]*v, _state); - - /* - * Raw Lagrangian - */ - *rawlag = *rawlag+lagmult->ptr.p_double[nec+nic+i]*v; - } - else - { - - /* - * Merit function: augmentation term + L1 penalty term - */ - *meritf = *meritf+0.5*nlcslp_augmentationfactor*ae_sqr(ae_maxreal(v, (double)(0), _state), _state); - *meritf = *meritf+nlcslp_meritfunctionbase*ae_maxreal(v, (double)(0), _state)+nlcslp_meritfunctiongain*ae_maxreal(lagmult->ptr.p_double[nec+nic+i]*v, (double)(0), _state); - - /* - * Raw Lagrangian - */ - *rawlag = *rawlag+lagmult->ptr.p_double[nec+nic+i]*v; - } - } -} - - -void _minslpsubsolver_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minslpsubsolver *p = (minslpsubsolver*)_p; - ae_touch_ptr((void*)p); - _presolveinfo_init(&p->presolver, _state, make_automatic); - _dualsimplexstate_init(&p->dss, _state, make_automatic); - _dualsimplexsettings_init(&p->dsssettings, _state, make_automatic); - _dualsimplexbasis_init(&p->lastbasis, _state, make_automatic); - ae_matrix_init(&p->curd, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->curb, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->curbndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->curbndu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cural, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->curau, 0, DT_REAL, _state, make_automatic); - _sparsematrix_init(&p->sparserawlc, _state, make_automatic); - _sparsematrix_init(&p->sparseefflc, _state, make_automatic); - ae_matrix_init(&p->h, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->curhd, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->densedummy, 0, 0, DT_REAL, _state, make_automatic); - _sparsematrix_init(&p->sparsedummy, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->sk, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->yk, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xs, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->laglc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->lagbc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cs, 0, DT_INT, _state, make_automatic); -} - - -void _minslpsubsolver_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minslpsubsolver *dst = (minslpsubsolver*)_dst; - minslpsubsolver *src = (minslpsubsolver*)_src; - _presolveinfo_init_copy(&dst->presolver, &src->presolver, _state, make_automatic); - _dualsimplexstate_init_copy(&dst->dss, &src->dss, _state, make_automatic); - _dualsimplexsettings_init_copy(&dst->dsssettings, &src->dsssettings, _state, make_automatic); - _dualsimplexbasis_init_copy(&dst->lastbasis, &src->lastbasis, _state, make_automatic); - dst->basispresent = src->basispresent; - ae_matrix_init_copy(&dst->curd, &src->curd, _state, make_automatic); - dst->curdcnt = src->curdcnt; - ae_vector_init_copy(&dst->curb, &src->curb, _state, make_automatic); - ae_vector_init_copy(&dst->curbndl, &src->curbndl, _state, make_automatic); - ae_vector_init_copy(&dst->curbndu, &src->curbndu, _state, make_automatic); - ae_vector_init_copy(&dst->cural, &src->cural, _state, make_automatic); - ae_vector_init_copy(&dst->curau, &src->curau, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparserawlc, &src->sparserawlc, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparseefflc, &src->sparseefflc, _state, make_automatic); - dst->hessiantype = src->hessiantype; - ae_matrix_init_copy(&dst->h, &src->h, _state, make_automatic); - ae_matrix_init_copy(&dst->curhd, &src->curhd, _state, make_automatic); - ae_matrix_init_copy(&dst->densedummy, &src->densedummy, _state, make_automatic); - _sparsematrix_init_copy(&dst->sparsedummy, &src->sparsedummy, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic); - ae_vector_init_copy(&dst->sk, &src->sk, _state, make_automatic); - ae_vector_init_copy(&dst->yk, &src->yk, _state, make_automatic); - ae_vector_init_copy(&dst->xs, &src->xs, _state, make_automatic); - ae_vector_init_copy(&dst->laglc, &src->laglc, _state, make_automatic); - ae_vector_init_copy(&dst->lagbc, &src->lagbc, _state, make_automatic); - ae_vector_init_copy(&dst->cs, &src->cs, _state, make_automatic); -} - - -void _minslpsubsolver_clear(void* _p) -{ - minslpsubsolver *p = (minslpsubsolver*)_p; - ae_touch_ptr((void*)p); - _presolveinfo_clear(&p->presolver); - _dualsimplexstate_clear(&p->dss); - _dualsimplexsettings_clear(&p->dsssettings); - _dualsimplexbasis_clear(&p->lastbasis); - ae_matrix_clear(&p->curd); - ae_vector_clear(&p->curb); - ae_vector_clear(&p->curbndl); - ae_vector_clear(&p->curbndu); - ae_vector_clear(&p->cural); - ae_vector_clear(&p->curau); - _sparsematrix_clear(&p->sparserawlc); - _sparsematrix_clear(&p->sparseefflc); - ae_matrix_clear(&p->h); - ae_matrix_clear(&p->curhd); - ae_matrix_clear(&p->densedummy); - _sparsematrix_clear(&p->sparsedummy); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->tmp1); - ae_vector_clear(&p->sk); - ae_vector_clear(&p->yk); - ae_vector_clear(&p->xs); - ae_vector_clear(&p->laglc); - ae_vector_clear(&p->lagbc); - ae_vector_clear(&p->cs); -} - - -void _minslpsubsolver_destroy(void* _p) -{ - minslpsubsolver *p = (minslpsubsolver*)_p; - ae_touch_ptr((void*)p); - _presolveinfo_destroy(&p->presolver); - _dualsimplexstate_destroy(&p->dss); - _dualsimplexsettings_destroy(&p->dsssettings); - _dualsimplexbasis_destroy(&p->lastbasis); - ae_matrix_destroy(&p->curd); - ae_vector_destroy(&p->curb); - ae_vector_destroy(&p->curbndl); - ae_vector_destroy(&p->curbndu); - ae_vector_destroy(&p->cural); - ae_vector_destroy(&p->curau); - _sparsematrix_destroy(&p->sparserawlc); - _sparsematrix_destroy(&p->sparseefflc); - ae_matrix_destroy(&p->h); - ae_matrix_destroy(&p->curhd); - ae_matrix_destroy(&p->densedummy); - _sparsematrix_destroy(&p->sparsedummy); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->tmp1); - ae_vector_destroy(&p->sk); - ae_vector_destroy(&p->yk); - ae_vector_destroy(&p->xs); - ae_vector_destroy(&p->laglc); - ae_vector_destroy(&p->lagbc); - ae_vector_destroy(&p->cs); -} - - -void _minslptmplagrangian_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minslptmplagrangian *p = (minslptmplagrangian*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->sclagtmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->sclagtmp1, 0, DT_REAL, _state, make_automatic); -} - - -void _minslptmplagrangian_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minslptmplagrangian *dst = (minslptmplagrangian*)_dst; - minslptmplagrangian *src = (minslptmplagrangian*)_src; - ae_vector_init_copy(&dst->sclagtmp0, &src->sclagtmp0, _state, make_automatic); - ae_vector_init_copy(&dst->sclagtmp1, &src->sclagtmp1, _state, make_automatic); -} - - -void _minslptmplagrangian_clear(void* _p) -{ - minslptmplagrangian *p = (minslptmplagrangian*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->sclagtmp0); - ae_vector_clear(&p->sclagtmp1); -} - - -void _minslptmplagrangian_destroy(void* _p) -{ - minslptmplagrangian *p = (minslptmplagrangian*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->sclagtmp0); - ae_vector_destroy(&p->sclagtmp1); -} - - -void _minslptmpmerit_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minslptmpmerit *p = (minslptmpmerit*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->mftmp0, 0, DT_REAL, _state, make_automatic); -} - - -void _minslptmpmerit_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minslptmpmerit *dst = (minslptmpmerit*)_dst; - minslptmpmerit *src = (minslptmpmerit*)_src; - ae_vector_init_copy(&dst->mftmp0, &src->mftmp0, _state, make_automatic); -} - - -void _minslptmpmerit_clear(void* _p) -{ - minslptmpmerit *p = (minslptmpmerit*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->mftmp0); -} - - -void _minslptmpmerit_destroy(void* _p) -{ - minslptmpmerit *p = (minslptmpmerit*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->mftmp0); -} - - -void _minslpphase13state_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minslpphase13state *p = (minslpphase13state*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepkxc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepkxn, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepkfic, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepkfin, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->stepkjc, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->stepkjn, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dummylagmult, 0, DT_REAL, _state, make_automatic); - _minslptmpmerit_init(&p->tmpmerit, _state, make_automatic); - _rcommstate_init(&p->rphase13state, _state, make_automatic); -} - - -void _minslpphase13state_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minslpphase13state *dst = (minslpphase13state*)_dst; - minslpphase13state *src = (minslpphase13state*)_src; - dst->usecorrection = src->usecorrection; - ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic); - ae_vector_init_copy(&dst->dx, &src->dx, _state, make_automatic); - ae_vector_init_copy(&dst->stepkxc, &src->stepkxc, _state, make_automatic); - ae_vector_init_copy(&dst->stepkxn, &src->stepkxn, _state, make_automatic); - ae_vector_init_copy(&dst->stepkfic, &src->stepkfic, _state, make_automatic); - ae_vector_init_copy(&dst->stepkfin, &src->stepkfin, _state, make_automatic); - ae_matrix_init_copy(&dst->stepkjc, &src->stepkjc, _state, make_automatic); - ae_matrix_init_copy(&dst->stepkjn, &src->stepkjn, _state, make_automatic); - ae_vector_init_copy(&dst->dummylagmult, &src->dummylagmult, _state, make_automatic); - _minslptmpmerit_init_copy(&dst->tmpmerit, &src->tmpmerit, _state, make_automatic); - _rcommstate_init_copy(&dst->rphase13state, &src->rphase13state, _state, make_automatic); -} - - -void _minslpphase13state_clear(void* _p) -{ - minslpphase13state *p = (minslpphase13state*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->d); - ae_vector_clear(&p->dx); - ae_vector_clear(&p->stepkxc); - ae_vector_clear(&p->stepkxn); - ae_vector_clear(&p->stepkfic); - ae_vector_clear(&p->stepkfin); - ae_matrix_clear(&p->stepkjc); - ae_matrix_clear(&p->stepkjn); - ae_vector_clear(&p->dummylagmult); - _minslptmpmerit_clear(&p->tmpmerit); - _rcommstate_clear(&p->rphase13state); -} - - -void _minslpphase13state_destroy(void* _p) -{ - minslpphase13state *p = (minslpphase13state*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->d); - ae_vector_destroy(&p->dx); - ae_vector_destroy(&p->stepkxc); - ae_vector_destroy(&p->stepkxn); - ae_vector_destroy(&p->stepkfic); - ae_vector_destroy(&p->stepkfin); - ae_matrix_destroy(&p->stepkjc); - ae_matrix_destroy(&p->stepkjn); - ae_vector_destroy(&p->dummylagmult); - _minslptmpmerit_destroy(&p->tmpmerit); - _rcommstate_destroy(&p->rphase13state); -} - - -void _minslpphase2state_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minslpphase2state *p = (minslpphase2state*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->stepkxn, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepkxc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepkfin, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepkfic, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->stepkjn, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->stepkjc, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepklaggrad, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepknlaggrad, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepknlagmult, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->meritlagmult, 0, DT_REAL, _state, make_automatic); - _minslptmplagrangian_init(&p->tmplagrangianfg, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic); - _linminstate_init(&p->mcstate, _state, make_automatic); - _minslptmpmerit_init(&p->tmpmerit, _state, make_automatic); - _rcommstate_init(&p->rphase2state, _state, make_automatic); -} - - -void _minslpphase2state_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minslpphase2state *dst = (minslpphase2state*)_dst; - minslpphase2state *src = (minslpphase2state*)_src; - ae_vector_init_copy(&dst->stepkxn, &src->stepkxn, _state, make_automatic); - ae_vector_init_copy(&dst->stepkxc, &src->stepkxc, _state, make_automatic); - ae_vector_init_copy(&dst->stepkfin, &src->stepkfin, _state, make_automatic); - ae_vector_init_copy(&dst->stepkfic, &src->stepkfic, _state, make_automatic); - ae_matrix_init_copy(&dst->stepkjn, &src->stepkjn, _state, make_automatic); - ae_matrix_init_copy(&dst->stepkjc, &src->stepkjc, _state, make_automatic); - ae_vector_init_copy(&dst->stepklaggrad, &src->stepklaggrad, _state, make_automatic); - ae_vector_init_copy(&dst->stepknlaggrad, &src->stepknlaggrad, _state, make_automatic); - ae_vector_init_copy(&dst->stepknlagmult, &src->stepknlagmult, _state, make_automatic); - ae_vector_init_copy(&dst->meritlagmult, &src->meritlagmult, _state, make_automatic); - _minslptmplagrangian_init_copy(&dst->tmplagrangianfg, &src->tmplagrangianfg, _state, make_automatic); - dst->lastlcerr = src->lastlcerr; - dst->lastlcidx = src->lastlcidx; - dst->lastnlcerr = src->lastnlcerr; - dst->lastnlcidx = src->lastnlcidx; - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic); - _linminstate_init_copy(&dst->mcstate, &src->mcstate, _state, make_automatic); - _minslptmpmerit_init_copy(&dst->tmpmerit, &src->tmpmerit, _state, make_automatic); - _rcommstate_init_copy(&dst->rphase2state, &src->rphase2state, _state, make_automatic); -} - - -void _minslpphase2state_clear(void* _p) -{ - minslpphase2state *p = (minslpphase2state*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->stepkxn); - ae_vector_clear(&p->stepkxc); - ae_vector_clear(&p->stepkfin); - ae_vector_clear(&p->stepkfic); - ae_matrix_clear(&p->stepkjn); - ae_matrix_clear(&p->stepkjc); - ae_vector_clear(&p->stepklaggrad); - ae_vector_clear(&p->stepknlaggrad); - ae_vector_clear(&p->stepknlagmult); - ae_vector_clear(&p->meritlagmult); - _minslptmplagrangian_clear(&p->tmplagrangianfg); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->d); - _linminstate_clear(&p->mcstate); - _minslptmpmerit_clear(&p->tmpmerit); - _rcommstate_clear(&p->rphase2state); -} - - -void _minslpphase2state_destroy(void* _p) -{ - minslpphase2state *p = (minslpphase2state*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->stepkxn); - ae_vector_destroy(&p->stepkxc); - ae_vector_destroy(&p->stepkfin); - ae_vector_destroy(&p->stepkfic); - ae_matrix_destroy(&p->stepkjn); - ae_matrix_destroy(&p->stepkjc); - ae_vector_destroy(&p->stepklaggrad); - ae_vector_destroy(&p->stepknlaggrad); - ae_vector_destroy(&p->stepknlagmult); - ae_vector_destroy(&p->meritlagmult); - _minslptmplagrangian_destroy(&p->tmplagrangianfg); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->d); - _linminstate_destroy(&p->mcstate); - _minslptmpmerit_destroy(&p->tmpmerit); - _rcommstate_destroy(&p->rphase2state); -} - - -void _minslpstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minslpstate *p = (minslpstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->scaledcleic, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->lcsrcidx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->hasbndl, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->hasbndu, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->scaledbndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->scaledbndu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fi, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->j, 0, 0, DT_REAL, _state, make_automatic); - _minslpphase13state_init(&p->state13, _state, make_automatic); - _minslpphase2state_init(&p->state2, _state, make_automatic); - ae_vector_init(&p->step0x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepkx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->backupx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->step0fi, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->stepkfi, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->backupfi, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->step0j, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->stepkj, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->backupj, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->meritlagmult, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dummylagmult, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fscales, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->meritfunctionhistory, 0, DT_REAL, _state, make_automatic); - _minslpsubsolver_init(&p->subsolver, _state, make_automatic); - _minslptmpmerit_init(&p->tmpmerit, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); -} - - -void _minslpstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minslpstate *dst = (minslpstate*)_dst; - minslpstate *src = (minslpstate*)_src; - dst->n = src->n; - dst->nec = src->nec; - dst->nic = src->nic; - dst->nlec = src->nlec; - dst->nlic = src->nlic; - ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic); - ae_matrix_init_copy(&dst->scaledcleic, &src->scaledcleic, _state, make_automatic); - ae_vector_init_copy(&dst->lcsrcidx, &src->lcsrcidx, _state, make_automatic); - ae_vector_init_copy(&dst->hasbndl, &src->hasbndl, _state, make_automatic); - ae_vector_init_copy(&dst->hasbndu, &src->hasbndu, _state, make_automatic); - ae_vector_init_copy(&dst->scaledbndl, &src->scaledbndl, _state, make_automatic); - ae_vector_init_copy(&dst->scaledbndu, &src->scaledbndu, _state, make_automatic); - dst->epsx = src->epsx; - dst->maxits = src->maxits; - dst->hessiantype = src->hessiantype; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->fi, &src->fi, _state, make_automatic); - ae_matrix_init_copy(&dst->j, &src->j, _state, make_automatic); - dst->f = src->f; - dst->needfij = src->needfij; - dst->xupdated = src->xupdated; - _minslpphase13state_init_copy(&dst->state13, &src->state13, _state, make_automatic); - _minslpphase2state_init_copy(&dst->state2, &src->state2, _state, make_automatic); - dst->trustrad = src->trustrad; - dst->lpfailurecnt = src->lpfailurecnt; - dst->fstagnationcnt = src->fstagnationcnt; - ae_vector_init_copy(&dst->step0x, &src->step0x, _state, make_automatic); - ae_vector_init_copy(&dst->stepkx, &src->stepkx, _state, make_automatic); - ae_vector_init_copy(&dst->backupx, &src->backupx, _state, make_automatic); - ae_vector_init_copy(&dst->step0fi, &src->step0fi, _state, make_automatic); - ae_vector_init_copy(&dst->stepkfi, &src->stepkfi, _state, make_automatic); - ae_vector_init_copy(&dst->backupfi, &src->backupfi, _state, make_automatic); - ae_matrix_init_copy(&dst->step0j, &src->step0j, _state, make_automatic); - ae_matrix_init_copy(&dst->stepkj, &src->stepkj, _state, make_automatic); - ae_matrix_init_copy(&dst->backupj, &src->backupj, _state, make_automatic); - ae_vector_init_copy(&dst->meritlagmult, &src->meritlagmult, _state, make_automatic); - ae_vector_init_copy(&dst->dummylagmult, &src->dummylagmult, _state, make_automatic); - ae_vector_init_copy(&dst->fscales, &src->fscales, _state, make_automatic); - ae_vector_init_copy(&dst->meritfunctionhistory, &src->meritfunctionhistory, _state, make_automatic); - dst->historylen = src->historylen; - _minslpsubsolver_init_copy(&dst->subsolver, &src->subsolver, _state, make_automatic); - _minslptmpmerit_init_copy(&dst->tmpmerit, &src->tmpmerit, _state, make_automatic); - dst->repsimplexiterations = src->repsimplexiterations; - dst->repsimplexiterations1 = src->repsimplexiterations1; - dst->repsimplexiterations2 = src->repsimplexiterations2; - dst->repsimplexiterations3 = src->repsimplexiterations3; - dst->repinneriterationscount = src->repinneriterationscount; - dst->repouteriterationscount = src->repouteriterationscount; - dst->repterminationtype = src->repterminationtype; - dst->repbcerr = src->repbcerr; - dst->repbcidx = src->repbcidx; - dst->replcerr = src->replcerr; - dst->replcidx = src->replcidx; - dst->repnlcerr = src->repnlcerr; - dst->repnlcidx = src->repnlcidx; - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); -} - - -void _minslpstate_clear(void* _p) -{ - minslpstate *p = (minslpstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->s); - ae_matrix_clear(&p->scaledcleic); - ae_vector_clear(&p->lcsrcidx); - ae_vector_clear(&p->hasbndl); - ae_vector_clear(&p->hasbndu); - ae_vector_clear(&p->scaledbndl); - ae_vector_clear(&p->scaledbndu); - ae_vector_clear(&p->x); - ae_vector_clear(&p->fi); - ae_matrix_clear(&p->j); - _minslpphase13state_clear(&p->state13); - _minslpphase2state_clear(&p->state2); - ae_vector_clear(&p->step0x); - ae_vector_clear(&p->stepkx); - ae_vector_clear(&p->backupx); - ae_vector_clear(&p->step0fi); - ae_vector_clear(&p->stepkfi); - ae_vector_clear(&p->backupfi); - ae_matrix_clear(&p->step0j); - ae_matrix_clear(&p->stepkj); - ae_matrix_clear(&p->backupj); - ae_vector_clear(&p->meritlagmult); - ae_vector_clear(&p->dummylagmult); - ae_vector_clear(&p->fscales); - ae_vector_clear(&p->meritfunctionhistory); - _minslpsubsolver_clear(&p->subsolver); - _minslptmpmerit_clear(&p->tmpmerit); - _rcommstate_clear(&p->rstate); -} - - -void _minslpstate_destroy(void* _p) -{ - minslpstate *p = (minslpstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->s); - ae_matrix_destroy(&p->scaledcleic); - ae_vector_destroy(&p->lcsrcidx); - ae_vector_destroy(&p->hasbndl); - ae_vector_destroy(&p->hasbndu); - ae_vector_destroy(&p->scaledbndl); - ae_vector_destroy(&p->scaledbndu); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->fi); - ae_matrix_destroy(&p->j); - _minslpphase13state_destroy(&p->state13); - _minslpphase2state_destroy(&p->state2); - ae_vector_destroy(&p->step0x); - ae_vector_destroy(&p->stepkx); - ae_vector_destroy(&p->backupx); - ae_vector_destroy(&p->step0fi); - ae_vector_destroy(&p->stepkfi); - ae_vector_destroy(&p->backupfi); - ae_matrix_destroy(&p->step0j); - ae_matrix_destroy(&p->stepkj); - ae_matrix_destroy(&p->backupj); - ae_vector_destroy(&p->meritlagmult); - ae_vector_destroy(&p->dummylagmult); - ae_vector_destroy(&p->fscales); - ae_vector_destroy(&p->meritfunctionhistory); - _minslpsubsolver_destroy(&p->subsolver); - _minslptmpmerit_destroy(&p->tmpmerit); - _rcommstate_destroy(&p->rstate); -} - - -#endif -#if defined(AE_COMPILE_MINNLC) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* - NONLINEARLY CONSTRAINED OPTIMIZATION - WITH PRECONDITIONED AUGMENTED LAGRANGIAN ALGORITHM - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments subject to any -combination of: -* bound constraints -* linear inequality constraints -* linear equality constraints -* nonlinear equality constraints Gi(x)=0 -* nonlinear inequality constraints Hi(x)<=0 - -REQUIREMENTS: -* user must provide function value and gradient for F(), H(), G() -* starting point X0 must be feasible or not too far away from the feasible - set -* F(), G(), H() are continuously differentiable on the feasible set and - its neighborhood -* nonlinear constraints G() and H() must have non-zero gradient at G(x)=0 - and at H(x)=0. Say, constraint like x^2>=1 is supported, but x^2>=0 is - NOT supported. - -USAGE: - -Constrained optimization if far more complex than the unconstrained one. -Nonlinearly constrained optimization is one of the most esoteric numerical -procedures. - -Here we give very brief outline of the MinNLC optimizer. We strongly -recommend you to study examples in the ALGLIB Reference Manual and to read -ALGLIB User Guide on optimization, which is available at -http://www.alglib.net/optimization/ - -1. User initializes algorithm state with MinNLCCreate() call and chooses - what NLC solver to use. There is some solver which is used by default, - with default settings, but you should NOT rely on default choice. It - may change in future releases of ALGLIB without notice, and no one can - guarantee that new solver will be able to solve your problem with - default settings. - - From the other side, if you choose solver explicitly, you can be pretty - sure that it will work with new ALGLIB releases. - - In the current release following solvers can be used: - * SQP solver, recommended for medium-scale problems (less than thousand - of variables) with hard-to-evaluate target functions. Requires less - function evaluations than other solvers but each step involves - solution of QP subproblem, so running time may be higher than that of - AUL (another recommended option). Activated with minnlcsetalgosqp() - function. - * AUL solver with dense preconditioner, recommended for large-scale - problems or for problems with cheap target function. Needs more - function evaluations that SQP (about 5x-10x times more), but its - iterations are much cheaper that that of SQP. Activated with - minnlcsetalgoaul() function. - * SLP solver, successive linear programming. The slowest one, requires - more target function evaluations that SQP and AUL. However, it is - somewhat more robust in tricky cases, so it can be used as a backup - plan. Activated with minnlcsetalgoslp() function. - -2. [optional] user activates OptGuard integrity checker which tries to - detect possible errors in the user-supplied callbacks: - * discontinuity/nonsmoothness of the target/nonlinear constraints - * errors in the analytic gradient provided by user - This feature is essential for early prototyping stages because it helps - to catch common coding and problem statement errors. - OptGuard can be activated with following functions (one per each check - performed): - * minnlcoptguardsmoothness() - * minnlcoptguardgradient() - -3. User adds boundary and/or linear and/or nonlinear constraints by means - of calling one of the following functions: - a) minnlcsetbc() for boundary constraints - b) minnlcsetlc() for linear constraints - c) minnlcsetnlc() for nonlinear constraints - You may combine (a), (b) and (c) in one optimization problem. - -4. User sets scale of the variables with minnlcsetscale() function. It is - VERY important to set scale of the variables, because nonlinearly - constrained problems are hard to solve when variables are badly scaled. - -5. User sets stopping conditions with minnlcsetcond(). If NLC solver - uses inner/outer iteration layout, this function sets stopping - conditions for INNER iterations. - -6. Finally, user calls minnlcoptimize() function which takes algorithm - state and pointer (delegate, etc.) to callback function which calculates - F/G/H. - -7. User calls minnlcresults() to get solution; additionally you can - retrieve OptGuard report with minnlcoptguardresults(), and get detailed - report about purported errors in the target function with: - * minnlcoptguardnonc1test0results() - * minnlcoptguardnonc1test1results() - -8. Optionally user may call minnlcrestartfrom() to solve another problem - with same N but another starting point. minnlcrestartfrom() allows to - reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size ofX - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlccreate(ae_int_t n, - /* Real */ ae_vector* x, - minnlcstate* state, - ae_state *_state) -{ - - _minnlcstate_clear(state); - - ae_assert(n>=1, "MinNLCCreate: N<1", _state); - ae_assert(x->cnt>=n, "MinNLCCreate: Length(X)0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size ofX - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinNLCSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large TRUNCATION errors, while too small - step will result in too large NUMERICAL errors. 1.0E-4 can be good - value to start from. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. Imprecise gradient may slow down - convergence, especially on highly nonlinear problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlccreatef(ae_int_t n, - /* Real */ ae_vector* x, - double diffstep, - minnlcstate* state, - ae_state *_state) -{ - - _minnlcstate_clear(state); - - ae_assert(n>=1, "MinNLCCreateF: N<1", _state); - ae_assert(x->cnt>=n, "MinNLCCreateF: Length(X)n; - ae_assert(bndl->cnt>=n, "MinNLCSetBC: Length(BndL)cnt>=n, "MinNLCSetBC: Length(BndU)ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "MinNLCSetBC: BndL contains NAN or +INF", _state); - ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "MinNLCSetBC: BndL contains NAN or -INF", _state); - state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i]; - state->hasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state); - state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i]; - state->hasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state); - } -} - - -/************************************************************************* -This function sets linear constraints for MinNLC optimizer. - -Linear constraints are inactive by default (after initial creation). They -are preserved after algorithm restart with MinNLCRestartFrom(). - -You may combine linear constraints with boundary ones - and with nonlinear -ones! If your problem has mixed constraints, you may explicitly specify -some of them as linear. It may help optimizer to handle them more -efficiently. - -INPUT PARAMETERS: - State - structure previously allocated with MinNLCCreate call. - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -NOTE 1: when you solve your problem with augmented Lagrangian solver, - linear constraints are satisfied only approximately! It is - possible that algorithm will evaluate function outside of - feasible area! - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetlc(minnlcstate* state, - /* Real */ ae_matrix* c, - /* Integer */ ae_vector* ct, - ae_int_t k, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - - - n = state->n; - - /* - * First, check for errors in the inputs - */ - ae_assert(k>=0, "MinNLCSetLC: K<0", _state); - ae_assert(c->cols>=n+1||k==0, "MinNLCSetLC: Cols(C)rows>=k, "MinNLCSetLC: Rows(C)cnt>=k, "MinNLCSetLC: Length(CT)nec = 0; - state->nic = 0; - return; - } - - /* - * Equality constraints are stored first, in the upper - * NEC rows of State.CLEIC matrix. Inequality constraints - * are stored in the next NIC rows. - * - * NOTE: we convert inequality constraints to the form - * A*x<=b before copying them. - */ - rmatrixsetlengthatleast(&state->cleic, k, n+1, _state); - ivectorsetlengthatleast(&state->lcsrcidx, k, _state); - state->nec = 0; - state->nic = 0; - for(i=0; i<=k-1; i++) - { - if( ct->ptr.p_int[i]==0 ) - { - ae_v_move(&state->cleic.ptr.pp_double[state->nec][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n)); - state->lcsrcidx.ptr.p_int[state->nec] = i; - state->nec = state->nec+1; - } - } - for(i=0; i<=k-1; i++) - { - if( ct->ptr.p_int[i]!=0 ) - { - if( ct->ptr.p_int[i]>0 ) - { - ae_v_moveneg(&state->cleic.ptr.pp_double[state->nec+state->nic][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n)); - } - else - { - ae_v_move(&state->cleic.ptr.pp_double[state->nec+state->nic][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n)); - } - state->lcsrcidx.ptr.p_int[state->nec+state->nic] = i; - state->nic = state->nic+1; - } - } -} - - -/************************************************************************* -This function sets nonlinear constraints for MinNLC optimizer. - -In fact, this function sets NUMBER of nonlinear constraints. Constraints -itself (constraint functions) are passed to MinNLCOptimize() method. This -method requires user-defined vector function F[] and its Jacobian J[], -where: -* first component of F[] and first row of Jacobian J[] corresponds to - function being minimized -* next NLEC components of F[] (and rows of J) correspond to nonlinear - equality constraints G_i(x)=0 -* next NLIC components of F[] (and rows of J) correspond to nonlinear - inequality constraints H_i(x)<=0 - -NOTE: you may combine nonlinear constraints with linear/boundary ones. If - your problem has mixed constraints, you may explicitly specify some - of them as linear ones. It may help optimizer to handle them more - efficiently. - -INPUT PARAMETERS: - State - structure previously allocated with MinNLCCreate call. - NLEC - number of Non-Linear Equality Constraints (NLEC), >=0 - NLIC - number of Non-Linear Inquality Constraints (NLIC), >=0 - -NOTE 1: when you solve your problem with augmented Lagrangian solver, - nonlinear constraints are satisfied only approximately! It is - possible that algorithm will evaluate function outside of - feasible area! - -NOTE 2: algorithm scales variables according to scale specified by - MinNLCSetScale() function, so it can handle problems with badly - scaled variables (as long as we KNOW their scales). - - However, there is no way to automatically scale nonlinear - constraints Gi(x) and Hi(x). Inappropriate scaling of Gi/Hi may - ruin convergence. Solving problem with constraint "1000*G0(x)=0" - is NOT same as solving it with constraint "0.001*G0(x)=0". - - It means that YOU are the one who is responsible for correct - scaling of nonlinear constraints Gi(x) and Hi(x). We recommend you - to scale nonlinear constraints in such way that I-th component of - dG/dX (or dH/dx) has approximately unit magnitude (for problems - with unit scale) or has magnitude approximately equal to 1/S[i] - (where S is a scale set by MinNLCSetScale() function). - - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetnlc(minnlcstate* state, - ae_int_t nlec, - ae_int_t nlic, - ae_state *_state) -{ - - - ae_assert(nlec>=0, "MinNLCSetNLC: NLEC<0", _state); - ae_assert(nlic>=0, "MinNLCSetNLC: NLIC<0", _state); - state->ng = nlec; - state->nh = nlic; - ae_vector_set_length(&state->fi, 1+state->ng+state->nh, _state); - ae_matrix_set_length(&state->j, 1+state->ng+state->nh, state->n, _state); -} - - -/************************************************************************* -This function sets stopping conditions for inner iterations of optimizer. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - step vector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinNLCSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic -selection of the stopping condition. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetcond(minnlcstate* state, - double epsx, - ae_int_t maxits, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(epsx, _state), "MinNLCSetCond: EpsX is not finite number", _state); - ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinNLCSetCond: negative EpsX", _state); - ae_assert(maxits>=0, "MinNLCSetCond: negative MaxIts!", _state); - if( ae_fp_eq(epsx,(double)(0))&&maxits==0 ) - { - epsx = 1.0E-8; - } - state->epsx = epsx; - state->maxits = maxits; -} - - -/************************************************************************* -This function sets scaling coefficients for NLC optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of the optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetscale(minnlcstate* state, - /* Real */ ae_vector* s, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(s->cnt>=state->n, "MinNLCSetScale: Length(S)n-1; i++) - { - ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinNLCSetScale: S contains infinite or NAN elements", _state); - ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "MinNLCSetScale: S contains zero elements", _state); - state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state); - } -} - - -/************************************************************************* -This function sets preconditioner to "inexact LBFGS-based" mode. - -Preconditioning is very important for convergence of Augmented Lagrangian -algorithm because presence of penalty term makes problem ill-conditioned. -Difference between performance of preconditioned and unpreconditioned -methods can be as large as 100x! - -MinNLC optimizer may use following preconditioners, each with its own -benefits and drawbacks: - a) inexact LBFGS-based, with O(N*K) evaluation time - b) exact low rank one, with O(N*K^2) evaluation time - c) exact robust one, with O(N^3+K*N^2) evaluation time -where K is a total number of general linear and nonlinear constraints (box -ones are not counted). - -Inexact LBFGS-based preconditioner uses L-BFGS formula combined with -orthogonality assumption to perform very fast updates. For a N-dimensional -problem with K general linear or nonlinear constraints (boundary ones are -not counted) it has O(N*K) cost per iteration. This preconditioner has -best quality (less iterations) when general linear and nonlinear -constraints are orthogonal to each other (orthogonality with respect to -boundary constraints is not required). Number of iterations increases when -constraints are non-orthogonal, because algorithm assumes orthogonality, -but still it is better than no preconditioner at all. - -INPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 26.09.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetprecinexact(minnlcstate* state, ae_state *_state) -{ - - - state->updatefreq = 0; - state->prectype = 1; -} - - -/************************************************************************* -This function sets preconditioner to "exact low rank" mode. - -Preconditioning is very important for convergence of Augmented Lagrangian -algorithm because presence of penalty term makes problem ill-conditioned. -Difference between performance of preconditioned and unpreconditioned -methods can be as large as 100x! - -MinNLC optimizer may use following preconditioners, each with its own -benefits and drawbacks: - a) inexact LBFGS-based, with O(N*K) evaluation time - b) exact low rank one, with O(N*K^2) evaluation time - c) exact robust one, with O(N^3+K*N^2) evaluation time -where K is a total number of general linear and nonlinear constraints (box -ones are not counted). - -It also provides special unpreconditioned mode of operation which can be -used for test purposes. Comments below discuss low rank preconditioner. - -Exact low-rank preconditioner uses Woodbury matrix identity to build -quadratic model of the penalized function. It has following features: -* no special assumptions about orthogonality of constraints -* preconditioner evaluation is optimized for K<=N. -* finally, stability of the process is guaranteed only for K<=N due to degeneracy of intermediate matrices. - That's why we recommend to use "exact robust" preconditioner for such - cases. - -RECOMMENDATIONS - -We recommend to choose between "exact low rank" and "exact robust" -preconditioners, with "low rank" version being chosen when you know in -advance that total count of non-box constraints won't exceed N, and "robust" -version being chosen when you need bulletproof solution. - -INPUT PARAMETERS: - State - structure stores algorithm state - UpdateFreq- update frequency. Preconditioner is rebuilt after every - UpdateFreq iterations. Recommended value: 10 or higher. - Zero value means that good default value will be used. - - -- ALGLIB -- - Copyright 26.09.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetprecexactlowrank(minnlcstate* state, - ae_int_t updatefreq, - ae_state *_state) -{ - - - ae_assert(updatefreq>=0, "MinNLCSetPrecExactLowRank: UpdateFreq<0", _state); - if( updatefreq==0 ) - { - updatefreq = 10; - } - state->prectype = 2; - state->updatefreq = updatefreq; -} - - -/************************************************************************* -This function sets preconditioner to "exact robust" mode. - -Preconditioning is very important for convergence of Augmented Lagrangian -algorithm because presence of penalty term makes problem ill-conditioned. -Difference between performance of preconditioned and unpreconditioned -methods can be as large as 100x! - -MinNLC optimizer may use following preconditioners, each with its own -benefits and drawbacks: - a) inexact LBFGS-based, with O(N*K) evaluation time - b) exact low rank one, with O(N*K^2) evaluation time - c) exact robust one, with O(N^3+K*N^2) evaluation time -where K is a total number of general linear and nonlinear constraints (box -ones are not counted). - -It also provides special unpreconditioned mode of operation which can be -used for test purposes. Comments below discuss robust preconditioner. - -Exact robust preconditioner uses Cholesky decomposition to invert -approximate Hessian matrix H=D+W'*C*W (where D stands for diagonal terms -of Hessian, combined result of initial scaling matrix and penalty from box -constraints; W stands for general linear constraints and linearization of -nonlinear ones; C stands for diagonal matrix of penalty coefficients). - -This preconditioner has following features: -* no special assumptions about constraint structure -* preconditioner is optimized for stability; unlike "exact low rank" - version which fails for K>=N, this one works well for any value of K. -* the only drawback is that is takes O(N^3+K*N^2) time to build it. No - economical Woodbury update is applied even when it makes sense, thus - there are exist situations (K<=0, "MinNLCSetPrecExactLowRank: UpdateFreq<0", _state); - if( updatefreq==0 ) - { - updatefreq = 10; - } - state->prectype = 3; - state->updatefreq = updatefreq; -} - - -/************************************************************************* -This function sets preconditioner to "turned off" mode. - -Preconditioning is very important for convergence of Augmented Lagrangian -algorithm because presence of penalty term makes problem ill-conditioned. -Difference between performance of preconditioned and unpreconditioned -methods can be as large as 100x! - -MinNLC optimizer may utilize two preconditioners, each with its own -benefits and drawbacks: a) inexact LBFGS-based, and b) exact low rank one. -It also provides special unpreconditioned mode of operation which can be -used for test purposes. - -This function activates this test mode. Do not use it in production code -to solve real-life problems. - -INPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 26.09.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetprecnone(minnlcstate* state, ae_state *_state) -{ - - - state->updatefreq = 0; - state->prectype = 0; -} - - -/************************************************************************* -This function sets maximum step length (after scaling of step vector with -respect to variable scales specified by minnlcsetscale() call). - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0 (default), if - you don't want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which leads to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - -NOTE: different solvers employed by MinNLC optimizer use different norms - for step; AUL solver uses 2-norm, whilst SLP solver uses INF-norm. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetstpmax(minnlcstate* state, double stpmax, ae_state *_state) -{ - - - ae_assert(ae_isfinite(stpmax, _state), "MinNLCSetStpMax: StpMax is not finite!", _state); - ae_assert(ae_fp_greater_eq(stpmax,(double)(0)), "MinNLCSetStpMax: StpMax<0!", _state); - state->stpmax = stpmax; -} - - -/************************************************************************* -This function tells MinNLC unit to use Augmented Lagrangian algorithm -for nonlinearly constrained optimization. This algorithm is a slight -modification of one described in "A Modified Barrier-Augmented Lagrangian -Method for Constrained Minimization (1999)" by D.GOLDFARB, R.POLYAK, -K. SCHEINBERG, I.YUZEFOVICH. - -AUL solver can be significantly faster than SQP on easy problems due to -cheaper iterations, although it needs more function evaluations. - -Augmented Lagrangian algorithm works by converting problem of minimizing -F(x) subject to equality/inequality constraints to unconstrained problem -of the form - - min[ f(x) + - + Rho*PENALTY_EQ(x) + SHIFT_EQ(x,Nu1) + - + Rho*PENALTY_INEQ(x) + SHIFT_INEQ(x,Nu2) ] - -where: -* Rho is a fixed penalization coefficient -* PENALTY_EQ(x) is a penalty term, which is used to APPROXIMATELY enforce - equality constraints -* SHIFT_EQ(x) is a special "shift" term which is used to "fine-tune" - equality constraints, greatly increasing precision -* PENALTY_INEQ(x) is a penalty term which is used to approximately enforce - inequality constraints -* SHIFT_INEQ(x) is a special "shift" term which is used to "fine-tune" - inequality constraints, greatly increasing precision -* Nu1/Nu2 are vectors of Lagrange coefficients which are fine-tuned during - outer iterations of algorithm - -This version of AUL algorithm uses preconditioner, which greatly -accelerates convergence. Because this algorithm is similar to penalty -methods, it may perform steps into infeasible area. All kinds of -constraints (boundary, linear and nonlinear ones) may be violated in -intermediate points - and in the solution. However, properly configured -AUL method is significantly better at handling constraints than barrier -and/or penalty methods. - -The very basic outline of algorithm is given below: -1) first outer iteration is performed with "default" values of Lagrange - multipliers Nu1/Nu2. Solution quality is low (candidate point can be - too far away from true solution; large violation of constraints is - possible) and is comparable with that of penalty methods. -2) subsequent outer iterations refine Lagrange multipliers and improve - quality of the solution. - -INPUT PARAMETERS: - State - structure which stores algorithm state - Rho - penalty coefficient, Rho>0: - * large enough that algorithm converges with desired - precision. Minimum value is 10*max(S'*diag(H)*S), where - S is a scale matrix (set by MinNLCSetScale) and H is a - Hessian of the function being minimized. If you can not - easily estimate Hessian norm, see our recommendations - below. - * not TOO large to prevent ill-conditioning - * for unit-scale problems (variables and Hessian have unit - magnitude), Rho=100 or Rho=1000 can be used. - * it is important to note that Rho is internally multiplied - by scaling matrix, i.e. optimum value of Rho depends on - scale of variables specified by MinNLCSetScale(). - ItsCnt - number of outer iterations: - * ItsCnt=0 means that small number of outer iterations is - automatically chosen (10 iterations in current version). - * ItsCnt=1 means that AUL algorithm performs just as usual - barrier method. - * ItsCnt>1 means that AUL algorithm performs specified - number of outer iterations - -HOW TO CHOOSE PARAMETERS - -Nonlinear optimization is a tricky area and Augmented Lagrangian algorithm -is sometimes hard to tune. Good values of Rho and ItsCnt are problem- -specific. In order to help you we prepared following set of -recommendations: - -* for unit-scale problems (variables and Hessian have unit magnitude), - Rho=100 or Rho=1000 can be used. - -* start from some small value of Rho and solve problem with just one - outer iteration (ItcCnt=1). In this case algorithm behaves like penalty - method. Increase Rho in 2x or 10x steps until you see that one outer - iteration returns point which is "rough approximation to solution". - - It is very important to have Rho so large that penalty term becomes - constraining i.e. modified function becomes highly convex in constrained - directions. - - From the other side, too large Rho may prevent you from converging to - the solution. You can diagnose it by studying number of inner iterations - performed by algorithm: too few (5-10 on 1000-dimensional problem) or - too many (orders of magnitude more than dimensionality) usually means - that Rho is too large. - -* with just one outer iteration you usually have low-quality solution. - Some constraints can be violated with very large margin, while other - ones (which are NOT violated in the true solution) can push final point - too far in the inner area of the feasible set. - - For example, if you have constraint x0>=0 and true solution x0=1, then - merely a presence of "x0>=0" will introduce a bias towards larger values - of x0. Say, algorithm may stop at x0=1.5 instead of 1.0. - -* after you found good Rho, you may increase number of outer iterations. - ItsCnt=10 is a good value. Subsequent outer iteration will refine values - of Lagrange multipliers. Constraints which were violated will be - enforced, inactive constraints will be dropped (corresponding multipliers - will be decreased). Ideally, you should see 10-1000x improvement in - constraint handling (constraint violation is reduced). - -* if you see that algorithm converges to vicinity of solution, but - additional outer iterations do not refine solution, it may mean that - algorithm is unstable - it wanders around true solution, but can not - approach it. Sometimes algorithm may be stabilized by increasing Rho one - more time, making it 5x or 10x larger. - -SCALING OF CONSTRAINTS [IMPORTANT] - -AUL optimizer scales variables according to scale specified by -MinNLCSetScale() function, so it can handle problems with badly scaled -variables (as long as we KNOW their scales). However, because function -being optimized is a mix of original function and constraint-dependent -penalty functions, it is important to rescale both variables AND -constraints. - -Say, if you minimize f(x)=x^2 subject to 1000000*x>=0, then you have -constraint whose scale is different from that of target function (another -example is 0.000001*x>=0). It is also possible to have constraints whose -scales are misaligned: 1000000*x0>=0, 0.000001*x1<=0. Inappropriate -scaling may ruin convergence because minimizing x^2 subject to x>=0 is NOT -same as minimizing it subject to 1000000*x>=0. - -Because we know coefficients of boundary/linear constraints, we can -automatically rescale and normalize them. However, there is no way to -automatically rescale nonlinear constraints Gi(x) and Hi(x) - they are -black boxes. - -It means that YOU are the one who is responsible for correct scaling of -nonlinear constraints Gi(x) and Hi(x). We recommend you to rescale -nonlinear constraints in such way that I-th component of dG/dX (or dH/dx) -has magnitude approximately equal to 1/S[i] (where S is a scale set by -MinNLCSetScale() function). - -WHAT IF IT DOES NOT CONVERGE? - -It is possible that AUL algorithm fails to converge to precise values of -Lagrange multipliers. It stops somewhere around true solution, but candidate -point is still too far from solution, and some constraints are violated. -Such kind of failure is specific for Lagrangian algorithms - technically, -they stop at some point, but this point is not constrained solution. - -There are exist several reasons why algorithm may fail to converge: -a) too loose stopping criteria for inner iteration -b) degenerate, redundant constraints -c) target function has unconstrained extremum exactly at the boundary of - some constraint -d) numerical noise in the target function - -In all these cases algorithm is unstable - each outer iteration results in -large and almost random step which improves handling of some constraints, -but violates other ones (ideally outer iterations should form a sequence -of progressively decreasing steps towards solution). - -First reason possible is that too loose stopping criteria for inner -iteration were specified. Augmented Lagrangian algorithm solves a sequence -of intermediate problems, and requries each of them to be solved with high -precision. Insufficient precision results in incorrect update of Lagrange -multipliers. - -Another reason is that you may have specified degenerate constraints: say, -some constraint was repeated twice. In most cases AUL algorithm gracefully -handles such situations, but sometimes it may spend too much time figuring -out subtle degeneracies in constraint matrix. - -Third reason is tricky and hard to diagnose. Consider situation when you -minimize f=x^2 subject to constraint x>=0. Unconstrained extremum is -located exactly at the boundary of constrained area. In this case -algorithm will tend to oscillate between negative and positive x. Each -time it stops at x<0 it "reinforces" constraint x>=0, and each time it is -bounced to x>0 it "relaxes" constraint (and is attracted to x<0). - -Such situation sometimes happens in problems with hidden symetries. -Algorithm is got caught in a loop with Lagrange multipliers being -continuously increased/decreased. Luckily, such loop forms after at least -three iterations, so this problem can be solved by DECREASING number of -outer iterations down to 1-2 and increasing penalty coefficient Rho as -much as possible. - -Final reason is numerical noise. AUL algorithm is robust against moderate -noise (more robust than, say, active set methods), but large noise may -destabilize algorithm. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetalgoaul(minnlcstate* state, - double rho, - ae_int_t itscnt, - ae_state *_state) -{ - - - ae_assert(itscnt>=0, "MinNLCSetAlgoAUL: negative ItsCnt", _state); - ae_assert(ae_isfinite(rho, _state), "MinNLCSetAlgoAUL: Rho is not finite", _state); - ae_assert(ae_fp_greater(rho,(double)(0)), "MinNLCSetAlgoAUL: Rho<=0", _state); - if( itscnt==0 ) - { - itscnt = 10; - } - state->aulitscnt = itscnt; - state->rho = rho; - state->solvertype = 0; -} - - -/************************************************************************* -This function tells MinNLC optimizer to use SLP (Successive Linear -Programming) algorithm for nonlinearly constrained optimization. This -algorithm is a slight modification of one described in "A Linear -programming-based optimization algorithm for solving nonlinear programming -problems" (2010) by Claus Still and Tapio Westerlund. - -This solver is the slowest one in ALGLIB, it requires more target function -evaluations that SQP and AUL. However it is somewhat more robust in tricky -cases, so it can be used as a backup plan. We recommend to use this algo -when SQP/AUL do not work (does not return the solution you expect). If -trying different approach gives same results, then MAYBE something is -wrong with your optimization problem. - -Despite its name ("linear" = "first order method") this algorithm performs -steps similar to that of conjugate gradients method; internally it uses -orthogonality/conjugacy requirement for subsequent steps which makes it -closer to second order methods in terms of convergence speed. - -Convergence is proved for the following case: -* function and constraints are continuously differentiable (C1 class) -* extended Mangasarian–Fromovitz constraint qualification (EMFCQ) holds; - in the context of this algorithm EMFCQ means that one can, for any - infeasible point, find a search direction such that the constraint - infeasibilities are reduced. - -This algorithm has following nice properties: -* no parameters to tune -* no convexity requirements for target function or constraints -* initial point can be infeasible -* algorithm respects box constraints in all intermediate points (it does - not even evaluate function outside of box constrained area) -* once linear constraints are enforced, algorithm will not violate them -* no such guarantees can be provided for nonlinear constraints, but once - nonlinear constraints are enforced, algorithm will try to respect them - as much as possible -* numerical differentiation does not violate box constraints (although - general linear and nonlinear ones can be violated during differentiation) -* from our experience, this algorithm is somewhat more robust in really - difficult cases - -INPUT PARAMETERS: - State - structure which stores algorithm state - -===== TRACING SLP SOLVER ================================================= - -SLP solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'SLP' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. - It also prints OptGuard integrity checker report when - nonsmoothness of target/constraints is suspected. -* 'SLP.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'SLP'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format -* 'SLP.PROBING' - to let algorithm insert additional function evaluations - before line search in order to build human-readable - chart of the raw Lagrangian (~40 additional function - evaluations is performed for each line search). This - symbol also implicitly defines 'SLP'. -* 'OPTGUARD' - for report of smoothness/continuity violations in target - and/or constraints. This kind of reporting is included - in 'SLP', but it comes with lots of additional info. If - you need just smoothness monitoring, specify this - setting. - - NOTE: this tag merely directs OptGuard output to log - file. Even if you specify it, you still have to - configure OptGuard by calling minnlcoptguard...() - family of functions. - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. Specifying 'SLP.PROBING' adds even larger -overhead due to additional function evaluations being performed. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("SLP,SLP.PROBING,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 02.04.2018 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetalgoslp(minnlcstate* state, ae_state *_state) -{ - - - state->solvertype = 1; -} - - -/************************************************************************* -This function tells MinNLC optimizer to use SQP (Successive Quadratic -Programming) algorithm for nonlinearly constrained optimization. - -This algorithm needs order of magnitude (5x-10x) less function evaluations -than AUL solver, but has higher overhead because each iteration involves -solution of quadratic programming problem. - -Convergence is proved for the following case: -* function and constraints are continuously differentiable (C1 class) - -This algorithm has following nice properties: -* no parameters to tune -* no convexity requirements for target function or constraints -* initial point can be infeasible -* algorithm respects box constraints in all intermediate points (it does - not even evaluate function outside of box constrained area) -* once linear constraints are enforced, algorithm will not violate them -* no such guarantees can be provided for nonlinear constraints, but once - nonlinear constraints are enforced, algorithm will try to respect them - as much as possible -* numerical differentiation does not violate box constraints (although - general linear and nonlinear ones can be violated during differentiation) - -We recommend this algorithm as a default option for medium-scale problems -(less than thousand of variables) or problems with target function being -hard to evaluate. - -For large-scale problems or ones with very cheap target function -AUL solver can be better option. - -INPUT PARAMETERS: - State - structure which stores algorithm state - -===== INTERACTION WITH OPTGUARD ========================================== - -OptGuard integrity checker allows us to catch problems like errors in -gradients and discontinuity/nonsmoothness of the target/constraints. -Latter kind of problems can be detected by looking upon line searches -performed during optimization and searching for signs of nonsmoothness. - -The problem with SQP is that it is too good for OptGuard to work - it does -not perform line searches. It typically needs 1-2 function evaluations -per step, and it is not enough for OptGuard to detect nonsmoothness. - -So, if you suspect that your problem is nonsmooth, we recommend you to use -AUL or SLP solvers. - -===== TRACING SQP SOLVER ================================================= - -SQP solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'SQP' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. - It also prints OptGuard integrity checker report when - nonsmoothness of target/constraints is suspected. -* 'SQP.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'SQP'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format -* 'SQP.PROBING' - to let algorithm insert additional function evaluations - before line search in order to build human-readable - chart of the raw Lagrangian (~40 additional function - evaluations is performed for each line search). This - symbol also implicitly defines 'SQP' and activates - OptGuard integrity checker which detects continuity and - smoothness violations. An OptGuard log is printed at the - end of the file. - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. Specifying 'SQP.PROBING' adds even larger -overhead due to additional function evaluations being performed. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("SQP,SQP.PROBING,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 02.12.2019 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetalgosqp(minnlcstate* state, ae_state *_state) -{ - - - state->solvertype = 2; -} - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinNLCOptimize(). - -NOTE: algorithm passes two parameters to rep() callback - current point - and penalized function value at current point. Important - function - value which is returned is NOT function being minimized. It is sum - of the value of the function being minimized - and penalty term. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetxrep(minnlcstate* state, ae_bool needxrep, ae_state *_state) -{ - - - state->xrep = needxrep; -} - - -/************************************************************************* - -NOTES: - -1. This function has two different implementations: one which uses exact - (analytical) user-supplied Jacobian, and one which uses only function - vector and numerically differentiates function in order to obtain - gradient. - - Depending on the specific function used to create optimizer object - you should choose appropriate variant of MinNLCOptimize() - one which - accepts function AND Jacobian or one which accepts ONLY function. - - Be careful to choose variant of MinNLCOptimize() which corresponds to - your optimization scheme! Table below lists different combinations of - callback (function/gradient) passed to MinNLCOptimize() and specific - function used to create optimizer. - - - | USER PASSED TO MinNLCOptimize() - CREATED WITH | function only | function and gradient - ------------------------------------------------------------ - MinNLCCreateF() | works FAILS - MinNLCCreate() | FAILS works - - Here "FAILS" denotes inappropriate combinations of optimizer creation - function and MinNLCOptimize() version. Attemps to use such - combination will lead to exception. Either you did not pass gradient - when it WAS needed or you passed gradient when it was NOT needed. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -ae_bool minnlciteration(minnlcstate* state, ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - ae_int_t n; - ae_int_t ng; - ae_int_t nh; - double vleft; - double vright; - ae_bool b; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - i = state->rstate.ia.ptr.p_int[0]; - k = state->rstate.ia.ptr.p_int[1]; - n = state->rstate.ia.ptr.p_int[2]; - ng = state->rstate.ia.ptr.p_int[3]; - nh = state->rstate.ia.ptr.p_int[4]; - b = state->rstate.ba.ptr.p_bool[0]; - vleft = state->rstate.ra.ptr.p_double[0]; - vright = state->rstate.ra.ptr.p_double[1]; - } - else - { - i = 359; - k = -58; - n = -919; - ng = -909; - nh = 81; - b = ae_true; - vleft = 74; - vright = -788; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - if( state->rstate.stage==1 ) - { - goto lbl_1; - } - if( state->rstate.stage==2 ) - { - goto lbl_2; - } - if( state->rstate.stage==3 ) - { - goto lbl_3; - } - if( state->rstate.stage==4 ) - { - goto lbl_4; - } - if( state->rstate.stage==5 ) - { - goto lbl_5; - } - if( state->rstate.stage==6 ) - { - goto lbl_6; - } - if( state->rstate.stage==7 ) - { - goto lbl_7; - } - if( state->rstate.stage==8 ) - { - goto lbl_8; - } - if( state->rstate.stage==9 ) - { - goto lbl_9; - } - if( state->rstate.stage==10 ) - { - goto lbl_10; - } - if( state->rstate.stage==11 ) - { - goto lbl_11; - } - if( state->rstate.stage==12 ) - { - goto lbl_12; - } - if( state->rstate.stage==13 ) - { - goto lbl_13; - } - if( state->rstate.stage==14 ) - { - goto lbl_14; - } - if( state->rstate.stage==15 ) - { - goto lbl_15; - } - if( state->rstate.stage==16 ) - { - goto lbl_16; - } - if( state->rstate.stage==17 ) - { - goto lbl_17; - } - if( state->rstate.stage==18 ) - { - goto lbl_18; - } - if( state->rstate.stage==19 ) - { - goto lbl_19; - } - if( state->rstate.stage==20 ) - { - goto lbl_20; - } - if( state->rstate.stage==21 ) - { - goto lbl_21; - } - if( state->rstate.stage==22 ) - { - goto lbl_22; - } - if( state->rstate.stage==23 ) - { - goto lbl_23; - } - if( state->rstate.stage==24 ) - { - goto lbl_24; - } - - /* - * Routine body - */ - - /* - * Init - */ - state->userterminationneeded = ae_false; - state->repterminationtype = 0; - state->repinneriterationscount = 0; - state->repouteriterationscount = 0; - state->repnfev = 0; - state->repdbgphase0its = 0; - state->repbcerr = (double)(0); - state->repbcidx = -1; - state->replcerr = (double)(0); - state->replcidx = -1; - state->repnlcerr = (double)(0); - state->repnlcidx = -1; - n = state->n; - ng = state->ng; - nh = state->nh; - minnlc_clearrequestfields(state, _state); - ae_assert(state->smoothnessguardlevel==0||state->smoothnessguardlevel==1, "MinNLCIteration: integrity check failed", _state); - b = state->smoothnessguardlevel>0; - b = b||(state->solvertype==1&&ae_is_trace_enabled("SLP.PROBING")); - b = b||(state->solvertype==2&&ae_is_trace_enabled("SQP.PROBING")); - smoothnessmonitorinit(&state->smonitor, &state->s, n, 1+ng+nh, b, _state); - for(i=0; i<=n-1; i++) - { - state->lastscaleused.ptr.p_double[i] = state->s.ptr.p_double[i]; - } - - /* - * Check correctness of box constraints - */ - for(i=0; i<=n-1; i++) - { - if( state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i] ) - { - if( ae_fp_greater(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->repterminationtype = -3; - state->repbcerr = state->bndl.ptr.p_double[i]-state->bndu.ptr.p_double[i]; - state->repbcidx = i; - result = ae_false; - return result; - } - } - } - - /* - * Test gradient - */ - if( !(ae_fp_eq(state->diffstep,(double)(0))&&ae_fp_greater(state->teststep,(double)(0))) ) - { - goto lbl_25; - } -lbl_27: - if( !smoothnessmonitorcheckgradientatx0(&state->smonitor, &state->xstart, &state->s, &state->bndl, &state->bndu, ae_true, state->teststep, _state) ) - { - goto lbl_28; - } - for(i=0; i<=n-1; i++) - { - state->x.ptr.p_double[i] = state->smonitor.x.ptr.p_double[i]; - } - state->needfij = ae_true; - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - state->needfij = ae_false; - for(i=0; i<=ng+nh; i++) - { - state->smonitor.fi.ptr.p_double[i] = state->fi.ptr.p_double[i]; - for(k=0; k<=n-1; k++) - { - state->smonitor.j.ptr.pp_double[i][k] = state->j.ptr.pp_double[i][k]; - } - } - goto lbl_27; -lbl_28: -lbl_25: - - /* - * AUL solver - */ - if( state->solvertype!=0 ) - { - goto lbl_29; - } - if( ae_fp_neq(state->diffstep,(double)(0)) ) - { - rvectorsetlengthatleast(&state->xbase, n, _state); - rvectorsetlengthatleast(&state->fbase, 1+ng+nh, _state); - rvectorsetlengthatleast(&state->fm2, 1+ng+nh, _state); - rvectorsetlengthatleast(&state->fm1, 1+ng+nh, _state); - rvectorsetlengthatleast(&state->fp1, 1+ng+nh, _state); - rvectorsetlengthatleast(&state->fp2, 1+ng+nh, _state); - } - ae_vector_set_length(&state->rstateaul.ia, 8+1, _state); - ae_vector_set_length(&state->rstateaul.ra, 7+1, _state); - state->rstateaul.stage = -1; -lbl_31: - if( !minnlc_auliteration(state, &state->smonitor, _state) ) - { - goto lbl_32; - } - - /* - * Numerical differentiation (if needed) - intercept NeedFiJ - * request and replace it by sequence of NeedFi requests - */ - if( !(ae_fp_neq(state->diffstep,(double)(0))&&state->needfij) ) - { - goto lbl_33; - } - state->needfij = ae_false; - state->needfi = ae_true; - ae_v_move(&state->xbase.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - k = 0; -lbl_35: - if( k>n-1 ) - { - goto lbl_37; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = state->x.ptr.p_double[k]-state->s.ptr.p_double[k]*state->diffstep; - state->rstate.stage = 1; - goto lbl_rcomm; -lbl_1: - ae_v_move(&state->fm2.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = state->x.ptr.p_double[k]-0.5*state->s.ptr.p_double[k]*state->diffstep; - state->rstate.stage = 2; - goto lbl_rcomm; -lbl_2: - ae_v_move(&state->fm1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = state->x.ptr.p_double[k]+0.5*state->s.ptr.p_double[k]*state->diffstep; - state->rstate.stage = 3; - goto lbl_rcomm; -lbl_3: - ae_v_move(&state->fp1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = state->x.ptr.p_double[k]+state->s.ptr.p_double[k]*state->diffstep; - state->rstate.stage = 4; - goto lbl_rcomm; -lbl_4: - ae_v_move(&state->fp2.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh)); - for(i=0; i<=ng+nh; i++) - { - state->j.ptr.pp_double[i][k] = (8*(state->fp1.ptr.p_double[i]-state->fm1.ptr.p_double[i])-(state->fp2.ptr.p_double[i]-state->fm2.ptr.p_double[i]))/(6*state->diffstep*state->s.ptr.p_double[i]); - } - k = k+1; - goto lbl_35; -lbl_37: - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->rstate.stage = 5; - goto lbl_rcomm; -lbl_5: - - /* - * Restore previous values of fields and continue - */ - state->needfi = ae_false; - state->needfij = ae_true; - goto lbl_31; -lbl_33: - - /* - * Forward request to caller - */ - state->rstate.stage = 6; - goto lbl_rcomm; -lbl_6: - goto lbl_31; -lbl_32: - result = ae_false; - return result; -lbl_29: - - /* - * SLP solver - */ - if( state->solvertype!=1 ) - { - goto lbl_38; - } - if( ae_fp_neq(state->diffstep,(double)(0)) ) - { - rvectorsetlengthatleast(&state->xbase, n, _state); - rvectorsetlengthatleast(&state->fbase, 1+ng+nh, _state); - rvectorsetlengthatleast(&state->fm2, 1+ng+nh, _state); - rvectorsetlengthatleast(&state->fm1, 1+ng+nh, _state); - rvectorsetlengthatleast(&state->fp1, 1+ng+nh, _state); - rvectorsetlengthatleast(&state->fp2, 1+ng+nh, _state); - } - minslpinitbuf(&state->bndl, &state->bndu, &state->s, &state->xstart, n, &state->cleic, &state->lcsrcidx, state->nec, state->nic, state->ng, state->nh, state->epsx, state->maxits, &state->slpsolverstate, _state); -lbl_40: - if( !minslpiteration(&state->slpsolverstate, &state->smonitor, state->userterminationneeded, _state) ) - { - goto lbl_41; - } - - /* - * Forward request to caller - */ - if( !state->slpsolverstate.needfij ) - { - goto lbl_42; - } - - /* - * Evaluate target function/Jacobian - */ - if( ae_fp_neq(state->diffstep,(double)(0)) ) - { - goto lbl_44; - } - - /* - * Analytic Jacobian is provided - */ - minnlc_unscale(state, &state->slpsolverstate.x, &state->slpsolverstate.scaledbndl, &state->slpsolverstate.scaledbndu, &state->x, _state); - state->needfij = ae_true; - state->rstate.stage = 7; - goto lbl_rcomm; -lbl_7: - state->needfij = ae_false; - for(i=0; i<=ng+nh; i++) - { - state->slpsolverstate.fi.ptr.p_double[i] = state->fi.ptr.p_double[i]; - for(k=0; k<=n-1; k++) - { - state->slpsolverstate.j.ptr.pp_double[i][k] = state->j.ptr.pp_double[i][k]*state->s.ptr.p_double[k]; - } - } - goto lbl_45; -lbl_44: - - /* - * Numerical differentiation - */ - state->needfij = ae_false; - state->needfi = ae_true; - minnlc_unscale(state, &state->slpsolverstate.x, &state->slpsolverstate.scaledbndl, &state->slpsolverstate.scaledbndu, &state->xbase, _state); - k = 0; -lbl_46: - if( k>n-1 ) - { - goto lbl_48; - } - vleft = state->xbase.ptr.p_double[k]-state->s.ptr.p_double[k]*state->diffstep; - vright = state->xbase.ptr.p_double[k]+state->s.ptr.p_double[k]*state->diffstep; - if( !((state->hasbndl.ptr.p_bool[k]&&ae_fp_less(vleft,state->bndl.ptr.p_double[k]))||(state->hasbndu.ptr.p_bool[k]&&ae_fp_greater(vright,state->bndu.ptr.p_double[k]))) ) - { - goto lbl_49; - } - - /* - * Box constraint is violated by 4-point centered formula, use 2-point uncentered one - */ - if( state->hasbndl.ptr.p_bool[k]&&ae_fp_less(vleft,state->bndl.ptr.p_double[k]) ) - { - vleft = state->bndl.ptr.p_double[k]; - } - if( state->hasbndu.ptr.p_bool[k]&&ae_fp_greater(vright,state->bndu.ptr.p_double[k]) ) - { - vright = state->bndu.ptr.p_double[k]; - } - ae_assert(ae_fp_less_eq(vleft,vright), "MinNLC: integrity check failed", _state); - if( ae_fp_eq(vleft,vright) ) - { - - /* - * Fixed variable - */ - for(i=0; i<=ng+nh; i++) - { - state->j.ptr.pp_double[i][k] = (double)(0); - } - goto lbl_47; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = vleft; - state->rstate.stage = 8; - goto lbl_rcomm; -lbl_8: - ae_v_move(&state->fm1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = vright; - state->rstate.stage = 9; - goto lbl_rcomm; -lbl_9: - ae_v_move(&state->fp1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh)); - for(i=0; i<=ng+nh; i++) - { - state->j.ptr.pp_double[i][k] = (state->fp1.ptr.p_double[i]-state->fm1.ptr.p_double[i])/(vright-vleft); - } - goto lbl_50; -lbl_49: - - /* - * 4-point centered formula does not violate box constraints - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = state->x.ptr.p_double[k]-state->s.ptr.p_double[k]*state->diffstep; - state->rstate.stage = 10; - goto lbl_rcomm; -lbl_10: - ae_v_move(&state->fm2.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = state->x.ptr.p_double[k]-0.5*state->s.ptr.p_double[k]*state->diffstep; - state->rstate.stage = 11; - goto lbl_rcomm; -lbl_11: - ae_v_move(&state->fm1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = state->x.ptr.p_double[k]+0.5*state->s.ptr.p_double[k]*state->diffstep; - state->rstate.stage = 12; - goto lbl_rcomm; -lbl_12: - ae_v_move(&state->fp1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = state->x.ptr.p_double[k]+state->s.ptr.p_double[k]*state->diffstep; - state->rstate.stage = 13; - goto lbl_rcomm; -lbl_13: - ae_v_move(&state->fp2.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh)); - for(i=0; i<=ng+nh; i++) - { - state->j.ptr.pp_double[i][k] = (8*(state->fp1.ptr.p_double[i]-state->fm1.ptr.p_double[i])-(state->fp2.ptr.p_double[i]-state->fm2.ptr.p_double[i]))/(6*state->diffstep*state->s.ptr.p_double[k]); - } -lbl_50: -lbl_47: - k = k+1; - goto lbl_46; -lbl_48: - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->rstate.stage = 14; - goto lbl_rcomm; -lbl_14: - state->needfi = ae_false; - state->needfij = ae_true; - for(i=0; i<=ng+nh; i++) - { - state->slpsolverstate.fi.ptr.p_double[i] = state->fi.ptr.p_double[i]; - for(k=0; k<=n-1; k++) - { - state->slpsolverstate.j.ptr.pp_double[i][k] = state->j.ptr.pp_double[i][k]*state->s.ptr.p_double[k]; - } - } -lbl_45: - inc(&state->repnfev, _state); - goto lbl_40; -lbl_42: - if( !state->slpsolverstate.xupdated ) - { - goto lbl_51; - } - - /* - * Report current point - */ - if( !state->xrep ) - { - goto lbl_53; - } - minnlc_unscale(state, &state->slpsolverstate.x, &state->slpsolverstate.scaledbndl, &state->slpsolverstate.scaledbndu, &state->x, _state); - state->f = state->slpsolverstate.f; - state->xupdated = ae_true; - state->rstate.stage = 15; - goto lbl_rcomm; -lbl_15: - state->xupdated = ae_false; -lbl_53: - goto lbl_40; -lbl_51: - ae_assert(state->slpsolverstate.needfij, "NLC:SLP:request", _state); - goto lbl_40; -lbl_41: - state->repterminationtype = state->slpsolverstate.repterminationtype; - state->repouteriterationscount = state->slpsolverstate.repouteriterationscount; - state->repinneriterationscount = state->slpsolverstate.repinneriterationscount; - state->repbcerr = state->slpsolverstate.repbcerr; - state->repbcidx = state->slpsolverstate.repbcidx; - state->replcerr = state->slpsolverstate.replcerr; - state->replcidx = state->slpsolverstate.replcidx; - state->repnlcerr = state->slpsolverstate.repnlcerr; - state->repnlcidx = state->slpsolverstate.repnlcidx; - minnlc_unscale(state, &state->slpsolverstate.stepkx, &state->slpsolverstate.scaledbndl, &state->slpsolverstate.scaledbndu, &state->xc, _state); - result = ae_false; - return result; -lbl_38: - - /* - * SQP solver - */ - if( state->solvertype!=2 ) - { - goto lbl_55; - } - if( ae_fp_neq(state->diffstep,(double)(0)) ) - { - rvectorsetlengthatleast(&state->xbase, n, _state); - rvectorsetlengthatleast(&state->fbase, 1+ng+nh, _state); - rvectorsetlengthatleast(&state->fm2, 1+ng+nh, _state); - rvectorsetlengthatleast(&state->fm1, 1+ng+nh, _state); - rvectorsetlengthatleast(&state->fp1, 1+ng+nh, _state); - rvectorsetlengthatleast(&state->fp2, 1+ng+nh, _state); - } - minsqpinitbuf(&state->bndl, &state->bndu, &state->s, &state->xstart, n, &state->cleic, &state->lcsrcidx, state->nec, state->nic, state->ng, state->nh, state->epsx, state->maxits, &state->sqpsolverstate, _state); -lbl_57: - if( !minsqpiteration(&state->sqpsolverstate, &state->smonitor, state->userterminationneeded, _state) ) - { - goto lbl_58; - } - - /* - * Forward request to caller - */ - if( !state->sqpsolverstate.needfij ) - { - goto lbl_59; - } - - /* - * Evaluate target function/Jacobian - */ - if( ae_fp_neq(state->diffstep,(double)(0)) ) - { - goto lbl_61; - } - - /* - * Analytic Jacobian is provided - */ - minnlc_unscale(state, &state->sqpsolverstate.x, &state->sqpsolverstate.scaledbndl, &state->sqpsolverstate.scaledbndu, &state->x, _state); - state->needfij = ae_true; - state->rstate.stage = 16; - goto lbl_rcomm; -lbl_16: - state->needfij = ae_false; - for(i=0; i<=ng+nh; i++) - { - state->sqpsolverstate.fi.ptr.p_double[i] = state->fi.ptr.p_double[i]; - for(k=0; k<=n-1; k++) - { - state->sqpsolverstate.j.ptr.pp_double[i][k] = state->j.ptr.pp_double[i][k]*state->s.ptr.p_double[k]; - } - } - goto lbl_62; -lbl_61: - - /* - * Numerical differentiation - */ - state->needfij = ae_false; - state->needfi = ae_true; - minnlc_unscale(state, &state->sqpsolverstate.x, &state->sqpsolverstate.scaledbndl, &state->sqpsolverstate.scaledbndu, &state->xbase, _state); - k = 0; -lbl_63: - if( k>n-1 ) - { - goto lbl_65; - } - vleft = state->xbase.ptr.p_double[k]-state->s.ptr.p_double[k]*state->diffstep; - vright = state->xbase.ptr.p_double[k]+state->s.ptr.p_double[k]*state->diffstep; - if( !((state->hasbndl.ptr.p_bool[k]&&ae_fp_less(vleft,state->bndl.ptr.p_double[k]))||(state->hasbndu.ptr.p_bool[k]&&ae_fp_greater(vright,state->bndu.ptr.p_double[k]))) ) - { - goto lbl_66; - } - - /* - * Box constraint is violated by 4-point centered formula, use 2-point uncentered one - */ - if( state->hasbndl.ptr.p_bool[k]&&ae_fp_less(vleft,state->bndl.ptr.p_double[k]) ) - { - vleft = state->bndl.ptr.p_double[k]; - } - if( state->hasbndu.ptr.p_bool[k]&&ae_fp_greater(vright,state->bndu.ptr.p_double[k]) ) - { - vright = state->bndu.ptr.p_double[k]; - } - ae_assert(ae_fp_less_eq(vleft,vright), "MinNLC: integrity check failed", _state); - if( ae_fp_eq(vleft,vright) ) - { - - /* - * Fixed variable - */ - for(i=0; i<=ng+nh; i++) - { - state->j.ptr.pp_double[i][k] = (double)(0); - } - goto lbl_64; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = vleft; - state->rstate.stage = 17; - goto lbl_rcomm; -lbl_17: - ae_v_move(&state->fm1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = vright; - state->rstate.stage = 18; - goto lbl_rcomm; -lbl_18: - ae_v_move(&state->fp1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh)); - for(i=0; i<=ng+nh; i++) - { - state->j.ptr.pp_double[i][k] = (state->fp1.ptr.p_double[i]-state->fm1.ptr.p_double[i])/(vright-vleft); - } - goto lbl_67; -lbl_66: - - /* - * 4-point centered formula does not violate box constraints - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = state->x.ptr.p_double[k]-state->s.ptr.p_double[k]*state->diffstep; - state->rstate.stage = 19; - goto lbl_rcomm; -lbl_19: - ae_v_move(&state->fm2.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = state->x.ptr.p_double[k]-0.5*state->s.ptr.p_double[k]*state->diffstep; - state->rstate.stage = 20; - goto lbl_rcomm; -lbl_20: - ae_v_move(&state->fm1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = state->x.ptr.p_double[k]+0.5*state->s.ptr.p_double[k]*state->diffstep; - state->rstate.stage = 21; - goto lbl_rcomm; -lbl_21: - ae_v_move(&state->fp1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = state->x.ptr.p_double[k]+state->s.ptr.p_double[k]*state->diffstep; - state->rstate.stage = 22; - goto lbl_rcomm; -lbl_22: - ae_v_move(&state->fp2.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh)); - for(i=0; i<=ng+nh; i++) - { - state->j.ptr.pp_double[i][k] = (8*(state->fp1.ptr.p_double[i]-state->fm1.ptr.p_double[i])-(state->fp2.ptr.p_double[i]-state->fm2.ptr.p_double[i]))/(6*state->diffstep*state->s.ptr.p_double[k]); - } -lbl_67: -lbl_64: - k = k+1; - goto lbl_63; -lbl_65: - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->rstate.stage = 23; - goto lbl_rcomm; -lbl_23: - state->needfi = ae_false; - state->needfij = ae_true; - for(i=0; i<=ng+nh; i++) - { - state->sqpsolverstate.fi.ptr.p_double[i] = state->fi.ptr.p_double[i]; - for(k=0; k<=n-1; k++) - { - state->sqpsolverstate.j.ptr.pp_double[i][k] = state->j.ptr.pp_double[i][k]*state->s.ptr.p_double[k]; - } - } -lbl_62: - inc(&state->repnfev, _state); - goto lbl_57; -lbl_59: - if( !state->sqpsolverstate.xupdated ) - { - goto lbl_68; - } - - /* - * Report current point - */ - if( !state->xrep ) - { - goto lbl_70; - } - minnlc_unscale(state, &state->sqpsolverstate.x, &state->sqpsolverstate.scaledbndl, &state->sqpsolverstate.scaledbndu, &state->x, _state); - state->f = state->sqpsolverstate.f; - state->xupdated = ae_true; - state->rstate.stage = 24; - goto lbl_rcomm; -lbl_24: - state->xupdated = ae_false; -lbl_70: - goto lbl_57; -lbl_68: - ae_assert(state->sqpsolverstate.needfij, "NLC:SQP:request", _state); - goto lbl_57; -lbl_58: - state->repterminationtype = state->sqpsolverstate.repterminationtype; - state->repouteriterationscount = state->sqpsolverstate.repiterationscount; - state->repinneriterationscount = state->sqpsolverstate.repiterationscount; - state->repbcerr = state->sqpsolverstate.repbcerr; - state->repbcidx = state->sqpsolverstate.repbcidx; - state->replcerr = state->sqpsolverstate.replcerr; - state->replcidx = state->sqpsolverstate.replcidx; - state->repnlcerr = state->sqpsolverstate.repnlcerr; - state->repnlcidx = state->sqpsolverstate.repnlcidx; - minnlc_unscale(state, &state->sqpsolverstate.stepkx, &state->sqpsolverstate.scaledbndl, &state->sqpsolverstate.scaledbndu, &state->xc, _state); - result = ae_false; - return result; -lbl_55: - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = i; - state->rstate.ia.ptr.p_int[1] = k; - state->rstate.ia.ptr.p_int[2] = n; - state->rstate.ia.ptr.p_int[3] = ng; - state->rstate.ia.ptr.p_int[4] = nh; - state->rstate.ba.ptr.p_bool[0] = b; - state->rstate.ra.ptr.p_double[0] = vleft; - state->rstate.ra.ptr.p_double[1] = vright; - return result; -} - - -/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic gradient/Jacobian. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function (constraints) at the -initial point (note: future versions may also perform check at the final -point) and compares numerical gradient/Jacobian with analytic one provided -by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both gradients/Jacobians, and specific components highlighted -as suspicious by the OptGuard. - -The primary OptGuard report can be retrieved with minnlcoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with minnlcsetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcoptguardgradient(minnlcstate* state, - double teststep, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(teststep, _state), "MinNLCOptGuardGradient: TestStep contains NaN or INF", _state); - ae_assert(ae_fp_greater_eq(teststep,(double)(0)), "MinNLCOptGuardGradient: invalid argument TestStep(TestStep<0)", _state); - state->teststep = teststep; -} - - -/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) and/or constraints -b) nonsmooth target function (non-C1) and/or constraints - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - This kind of monitoring does not work well with SQP - because SQP solver needs just 1-2 function evaluations - per step, which is not enough for OptGuard to make - any conclusions. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minnlcoptguardsmoothness(minnlcstate* state, - ae_int_t level, - ae_state *_state) -{ - - - ae_assert(level==0||level==1, "MinNLCOptGuardSmoothness: unexpected value of level parameter", _state); - state->smoothnessguardlevel = level; -} - - -/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -=== PRIMARY REPORT ======================================================= - -OptGuard performs several checks which are intended to catch common errors -in the implementation of nonlinear function/gradient: -* incorrect analytic gradient -* discontinuous (non-C0) target functions (constraints) -* nonsmooth (non-C1) target functions (constraints) - -Each of these checks is activated with appropriate function: -* minnlcoptguardgradient() for gradient verification -* minnlcoptguardsmoothness() for C0/C1 checks - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradfidx for specific function (Jacobian row) suspected - * rep.badgradvidx for specific variable (Jacobian column) suspected - * rep.badgradxbase, a point where gradient/Jacobian is tested - * rep.badgraduser, user-provided gradient/Jacobian - * rep.badgradnum, reference gradient/Jacobian obtained via numerical - differentiation -* rep.nonc0suspected, and additionally: - * rep.nonc0fidx - an index of specific function violating C0 continuity -* rep.nonc1suspected, and additionally - * rep.nonc1fidx - an index of specific function violating C1 continuity -Here function index 0 means target function, index 1 or higher denotes -nonlinear constraints. - -=== ADDITIONAL REPORTS/LOGS ============================================== - -Several different tests are performed to catch C0/C1 errors, you can find -out specific test signaled error by looking to: -* rep.nonc0test0positive, for non-C0 test #0 -* rep.nonc1test0positive, for non-C1 test #0 -* rep.nonc1test1positive, for non-C1 test #1 - -Additional information (including line search logs) can be obtained by -means of: -* minnlcoptguardnonc1test0results() -* minnlcoptguardnonc1test1results() -which return detailed error reports, specific points where discontinuities -were found, and so on. - -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - generic OptGuard report; more detailed reports can be - retrieved with other functions. - -NOTE: false negatives (nonsmooth problems are not identified as nonsmooth - ones) are possible although unlikely. - - The reason is that you need to make several evaluations around - nonsmoothness in order to accumulate enough information about - function curvature. Say, if you start right from the nonsmooth point, - optimizer simply won't get enough data to understand what is going - wrong before it terminates due to abrupt changes in the derivative. - It is also possible that "unlucky" step will move us to the - termination too quickly. - - Our current approach is to have less than 0.1% false negatives in - our test examples (measured with multiple restarts from random - points), and to have exactly 0% false positives. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minnlcoptguardresults(minnlcstate* state, - optguardreport* rep, - ae_state *_state) -{ - - _optguardreport_clear(rep); - - smoothnessmonitorexportreport(&state->smonitor, rep, _state); -} - - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #0 - -Nonsmoothness (non-C1) test #0 studies function values (not gradient!) -obtained during line searches and monitors behavior of the directional -derivative estimate. - -This test is less powerful than test #1, but it does not depend on the -gradient values and thus it is more robust against artifacts introduced by -numerical differentiation. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* fidx - is an index of the function (0 for target function, 1 or higher - for nonlinear constraints) which is suspected of being "non-C1" -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #0 "strong" report - lngrep - C1 test #0 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minnlcoptguardnonc1test0results(minnlcstate* state, - optguardnonc1test0report* strrep, - optguardnonc1test0report* lngrep, - ae_state *_state) -{ - - _optguardnonc1test0report_clear(strrep); - _optguardnonc1test0report_clear(lngrep); - - smoothnessmonitorexportc1test0report(&state->smonitor.nonc1test0strrep, &state->lastscaleused, strrep, _state); - smoothnessmonitorexportc1test0report(&state->smonitor.nonc1test0lngrep, &state->lastscaleused, lngrep, _state); -} - - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #1 - -Nonsmoothness (non-C1) test #1 studies individual components of the -gradient computed during line search. - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* fidx - is an index of the function (0 for target function, 1 or higher - for nonlinear constraints) which is suspected of being "non-C1" -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #1 "strong" report - lngrep - C1 test #1 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minnlcoptguardnonc1test1results(minnlcstate* state, - optguardnonc1test1report* strrep, - optguardnonc1test1report* lngrep, - ae_state *_state) -{ - - _optguardnonc1test1report_clear(strrep); - _optguardnonc1test1report_clear(lngrep); - - smoothnessmonitorexportc1test1report(&state->smonitor.nonc1test1strrep, &state->lastscaleused, strrep, _state); - smoothnessmonitorexportc1test1report(&state->smonitor.nonc1test1lngrep, &state->lastscaleused, lngrep, _state); -} - - -/************************************************************************* -MinNLC results: the solution found, completion codes and additional -information. - -If you activated OptGuard integrity checking functionality and want to get -OptGuard report, it can be retrieved with: -* minnlcoptguardresults() - for a primary report about (a) suspected C0/C1 - continuity violations and (b) errors in the analytic gradient. -* minnlcoptguardnonc1test0results() - for C1 continuity violation test #0, - detailed line search log -* minnlcoptguardnonc1test1results() - for C1 continuity violation test #1, - detailed line search log - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report, contains information about completion - code, constraint violation at the solution and so on. - - You should check rep.terminationtype in order to - distinguish successful termination from unsuccessful one: - - === FAILURE CODES === - * -8 internal integrity control detected infinite or - NAN values in function/gradient. Abnormal - termination signalled. - * -3 box constraints are infeasible. - Note: infeasibility of non-box constraints does - NOT trigger emergency completion; you have - to examine rep.bcerr/rep.lcerr/rep.nlcerr to - detect possibly inconsistent constraints. - - === SUCCESS CODES === - * 2 scaled step is no more than EpsX. - * 5 MaxIts steps were taken. - * 8 user requested algorithm termination via - minnlcrequesttermination(), last accepted point is - returned. - - More information about fields of this structure can be - found in the comments on minnlcreport datatype. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcresults(minnlcstate* state, - /* Real */ ae_vector* x, - minnlcreport* rep, - ae_state *_state) -{ - - ae_vector_clear(x); - _minnlcreport_clear(rep); - - minnlcresultsbuf(state, x, rep, _state); -} - - -/************************************************************************* -NLC results - -Buffered implementation of MinNLCResults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minnlcresultsbuf(minnlcstate* state, - /* Real */ ae_vector* x, - minnlcreport* rep, - ae_state *_state) -{ - ae_int_t i; - - - if( x->cntn ) - { - ae_vector_set_length(x, state->n, _state); - } - rep->iterationscount = state->repinneriterationscount; - rep->nfev = state->repnfev; - rep->terminationtype = state->repterminationtype; - rep->bcerr = state->repbcerr; - rep->bcidx = state->repbcidx; - rep->lcerr = state->replcerr; - rep->lcidx = state->replcidx; - rep->nlcerr = state->repnlcerr; - rep->nlcidx = state->repnlcidx; - rep->dbgphase0its = state->repdbgphase0its; - if( state->repterminationtype>0 ) - { - ae_v_move(&x->ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - } - else - { - for(i=0; i<=state->n-1; i++) - { - x->ptr.p_double[i] = _state->v_nan; - } - } -} - - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcrequesttermination(minnlcstate* state, ae_state *_state) -{ - - - state->userterminationneeded = ae_true; -} - - -/************************************************************************* -This subroutine restarts algorithm from new point. -All optimization parameters (including constraints) are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure previously allocated with MinNLCCreate call. - X - new starting point. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minnlcrestartfrom(minnlcstate* state, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t n; - - - n = state->n; - - /* - * First, check for errors in the inputs - */ - ae_assert(x->cnt>=n, "MinNLCRestartFrom: Length(X)xstart.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - - /* - * prepare RComm facilities - */ - ae_vector_set_length(&state->rstate.ia, 4+1, _state); - ae_vector_set_length(&state->rstate.ba, 0+1, _state); - ae_vector_set_length(&state->rstate.ra, 1+1, _state); - state->rstate.stage = -1; - minnlc_clearrequestfields(state, _state); -} - - -/************************************************************************* -Penalty function for equality constraints. -INPUT PARAMETERS: - Alpha - function argument. Penalty function becomes large when - Alpha approaches -1 or +1. It is defined for Alpha<=-1 or - Alpha>=+1 - in this case infinite value is returned. - -OUTPUT PARAMETERS: - F - depending on Alpha: - * for Alpha in (-1+eps,+1-eps), F=F(Alpha) - * for Alpha outside of interval, F is some very large number - DF - depending on Alpha: - * for Alpha in (-1+eps,+1-eps), DF=dF(Alpha)/dAlpha, exact - numerical derivative. - * otherwise, it is zero - D2F - second derivative - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcequalitypenaltyfunction(double alpha, - double* f, - double* df, - double* d2f, - ae_state *_state) -{ - - *f = 0; - *df = 0; - *d2f = 0; - - *f = 0.5*alpha*alpha; - *df = alpha; - *d2f = 1.0; -} - - -/************************************************************************* -"Penalty" function for inequality constraints, which is multiplied by -penalty coefficient Rho. - -"Penalty" function plays only supplementary role - it helps to stabilize -algorithm when solving non-convex problems. Because it is multiplied by -fixed and large Rho - not Lagrange multiplier Nu which may become -arbitrarily small! - it enforces convexity of the problem behind the -boundary of the feasible area. - -This function is zero at the feasible area and in the close neighborhood, -it becomes non-zero only at some distance (scaling is essential!) and grows -quadratically. - -Penalty function must enter augmented Lagrangian as - Rho*PENALTY(x-lowerbound) -with corresponding changes being made for upper bound or other kinds of -constraints. - -INPUT PARAMETERS: - Alpha - function argument. Typically, if we have active constraint - with precise Lagrange multiplier, we have Alpha around 1. - Large positive Alpha's correspond to inner area of the - feasible set. Alpha<1 corresponds to outer area of the - feasible set. - StabilizingPoint- point where F becomes non-zero. Must be negative - value, at least -1, large values (hundreds) are possible. - -OUTPUT PARAMETERS: - F - F(Alpha) - DF - DF=dF(Alpha)/dAlpha, exact derivative - D2F - second derivative - -NOTE: it is important to have significantly non-zero StabilizingPoint, - because when it is large, shift term does not interfere with - Lagrange multipliers converging to their final values. Thus, - convergence of such modified AUL algorithm is still guaranteed by - same set of theorems. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcinequalitypenaltyfunction(double alpha, - double stabilizingpoint, - double* f, - double* df, - double* d2f, - ae_state *_state) -{ - - *f = 0; - *df = 0; - *d2f = 0; - - if( ae_fp_greater_eq(alpha,stabilizingpoint) ) - { - *f = 0.0; - *df = 0.0; - *d2f = 0.0; - } - else - { - alpha = alpha-stabilizingpoint; - *f = 0.5*alpha*alpha; - *df = alpha; - *d2f = 1.0; - } -} - - -/************************************************************************* -"Shift" function for inequality constraints, which is multiplied by -corresponding Lagrange multiplier. - -"Shift" function is a main factor which enforces inequality constraints. -Inequality penalty function plays only supplementary role - it prevents -accidental step deep into infeasible area when working with non-convex -problems (read comments on corresponding function for more information). - -Shift function must enter augmented Lagrangian as - Nu/Rho*SHIFT((x-lowerbound)*Rho+1) -with corresponding changes being made for upper bound or other kinds of -constraints. - -INPUT PARAMETERS: - Alpha - function argument. Typically, if we have active constraint - with precise Lagrange multiplier, we have Alpha around 1. - Large positive Alpha's correspond to inner area of the - feasible set. Alpha<1 corresponds to outer area of the - feasible set. - -OUTPUT PARAMETERS: - F - F(Alpha) - DF - DF=dF(Alpha)/dAlpha, exact derivative - D2F - second derivative - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcinequalityshiftfunction(double alpha, - double* f, - double* df, - double* d2f, - ae_state *_state) -{ - - *f = 0; - *df = 0; - *d2f = 0; - - if( ae_fp_greater_eq(alpha,0.5) ) - { - *f = -ae_log(alpha, _state); - *df = -1/alpha; - *d2f = 1/(alpha*alpha); - } - else - { - *f = 2*alpha*alpha-4*alpha+(ae_log((double)(2), _state)+1.5); - *df = 4*alpha-4; - *d2f = (double)(4); - } -} - - -/************************************************************************* -Clears request fileds (to be sure that we don't forget to clear something) -*************************************************************************/ -static void minnlc_clearrequestfields(minnlcstate* state, - ae_state *_state) -{ - - - state->needfi = ae_false; - state->needfij = ae_false; - state->xupdated = ae_false; -} - - -/************************************************************************* -Internal initialization subroutine. -Sets default NLC solver with default criteria. -*************************************************************************/ -static void minnlc_minnlcinitinternal(ae_int_t n, - /* Real */ ae_vector* x, - double diffstep, - minnlcstate* state, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_matrix c; - ae_vector ct; - - ae_frame_make(_state, &_frame_block); - memset(&c, 0, sizeof(c)); - memset(&ct, 0, sizeof(ct)); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - - - /* - * Default params - */ - state->stabilizingpoint = -2.0; - state->initialinequalitymultiplier = 1.0; - - /* - * Smoothness monitor, default init - */ - state->teststep = (double)(0); - state->smoothnessguardlevel = 0; - smoothnessmonitorinit(&state->smonitor, &state->s, 0, 0, ae_false, _state); - - /* - * Initialize other params - */ - state->n = n; - state->diffstep = diffstep; - state->userterminationneeded = ae_false; - ae_vector_set_length(&state->bndl, n, _state); - ae_vector_set_length(&state->hasbndl, n, _state); - ae_vector_set_length(&state->bndu, n, _state); - ae_vector_set_length(&state->hasbndu, n, _state); - ae_vector_set_length(&state->s, n, _state); - ae_vector_set_length(&state->lastscaleused, n, _state); - ae_vector_set_length(&state->xstart, n, _state); - ae_vector_set_length(&state->xc, n, _state); - ae_vector_set_length(&state->x, n, _state); - for(i=0; i<=n-1; i++) - { - state->bndl.ptr.p_double[i] = _state->v_neginf; - state->hasbndl.ptr.p_bool[i] = ae_false; - state->bndu.ptr.p_double[i] = _state->v_posinf; - state->hasbndu.ptr.p_bool[i] = ae_false; - state->s.ptr.p_double[i] = 1.0; - state->lastscaleused.ptr.p_double[i] = 1.0; - state->xstart.ptr.p_double[i] = x->ptr.p_double[i]; - state->xc.ptr.p_double[i] = x->ptr.p_double[i]; - } - minnlcsetlc(state, &c, &ct, 0, _state); - minnlcsetnlc(state, 0, 0, _state); - minnlcsetcond(state, 0.0, 0, _state); - minnlcsetxrep(state, ae_false, _state); - minnlcsetalgosqp(state, _state); - minnlcsetprecexactrobust(state, 0, _state); - minnlcsetstpmax(state, 0.0, _state); - minlbfgscreate(n, ae_minint(minnlc_lbfgsfactor, n, _state), x, &state->auloptimizer, _state); - minnlcrestartfrom(state, x, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function clears preconditioner for L-BFGS optimizer (sets it do default -state); - -Parameters: - AULOptimizer - optimizer to tune - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -static void minnlc_clearpreconditioner(minlbfgsstate* auloptimizer, - ae_state *_state) -{ - - - minlbfgssetprecdefault(auloptimizer, _state); -} - - -/************************************************************************* -This function updates preconditioner for L-BFGS optimizer. - -Parameters: - PrecType - preconditioner type: - * 0 for unpreconditioned iterations - * 1 for inexact LBFGS - * 2 for exact low rank preconditioner update after each UpdateFreq its - * 3 for exact robust preconditioner update after each UpdateFreq its - UpdateFreq - update frequency - PrecCounter - iterations counter, must be zero on the first call, - automatically increased by this function. This - counter is used to implement "update-once-in-X-iterations" - scheme. - AULOptimizer - optimizer to tune - X - current point - Rho - penalty term - GammaK - current estimate of Hessian norm (used for - initialization of preconditioner). Can be zero, in - which case Hessian is assumed to be unit. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -static void minnlc_updatepreconditioner(ae_int_t prectype, - ae_int_t updatefreq, - ae_int_t* preccounter, - minlbfgsstate* auloptimizer, - /* Real */ ae_vector* x, - double rho, - double gammak, - /* Real */ ae_vector* bndl, - /* Boolean */ ae_vector* hasbndl, - /* Real */ ae_vector* bndu, - /* Boolean */ ae_vector* hasbndu, - /* Real */ ae_vector* nubc, - /* Real */ ae_matrix* cleic, - /* Real */ ae_vector* nulc, - /* Real */ ae_vector* fi, - /* Real */ ae_matrix* jac, - /* Real */ ae_vector* nunlc, - /* Real */ ae_vector* bufd, - /* Real */ ae_vector* bufc, - /* Real */ ae_matrix* bufw, - /* Real */ ae_matrix* bufz, - /* Real */ ae_vector* tmp0, - ae_int_t n, - ae_int_t nec, - ae_int_t nic, - ae_int_t ng, - ae_int_t nh, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double p; - double dp; - double d2p; - ae_bool bflag; - - - ae_assert(ae_fp_greater(rho,(double)(0)), "MinNLC: integrity check failed", _state); - rvectorsetlengthatleast(bufd, n, _state); - rvectorsetlengthatleast(bufc, nec+nic+ng+nh, _state); - rmatrixsetlengthatleast(bufw, nec+nic+ng+nh, n, _state); - rvectorsetlengthatleast(tmp0, n, _state); - - /* - * Preconditioner before update from barrier/penalty functions - */ - if( ae_fp_eq(gammak,(double)(0)) ) - { - gammak = (double)(1); - } - for(i=0; i<=n-1; i++) - { - bufd->ptr.p_double[i] = gammak; - } - - /* - * Update diagonal Hessian using nonlinearity from boundary constraints: - * * penalty term from equality constraints - * * shift term from inequality constraints - * - * NOTE: penalty term for inequality constraints is ignored because it - * is large only in exceptional cases. - */ - for(i=0; i<=n-1; i++) - { - if( (hasbndl->ptr.p_bool[i]&&hasbndu->ptr.p_bool[i])&&ae_fp_eq(bndl->ptr.p_double[i],bndu->ptr.p_double[i]) ) - { - minnlcequalitypenaltyfunction((x->ptr.p_double[i]-bndl->ptr.p_double[i])*rho, &p, &dp, &d2p, _state); - bufd->ptr.p_double[i] = bufd->ptr.p_double[i]+d2p*rho; - continue; - } - if( hasbndl->ptr.p_bool[i] ) - { - minnlcinequalityshiftfunction((x->ptr.p_double[i]-bndl->ptr.p_double[i])*rho+1, &p, &dp, &d2p, _state); - bufd->ptr.p_double[i] = bufd->ptr.p_double[i]+nubc->ptr.p_double[2*i+0]*d2p*rho; - } - if( hasbndu->ptr.p_bool[i] ) - { - minnlcinequalityshiftfunction((bndu->ptr.p_double[i]-x->ptr.p_double[i])*rho+1, &p, &dp, &d2p, _state); - bufd->ptr.p_double[i] = bufd->ptr.p_double[i]+nubc->ptr.p_double[2*i+1]*d2p*rho; - } - } - - /* - * Process linear constraints - */ - for(i=0; i<=nec+nic-1; i++) - { - ae_v_move(&bufw->ptr.pp_double[i][0], 1, &cleic->ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - v = ae_v_dotproduct(&cleic->ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = v-cleic->ptr.pp_double[i][n]; - if( iptr.p_double[i] = d2p*rho; - } - else - { - - /* - * Inequality constraint - */ - minnlcinequalityshiftfunction(-v*rho+1, &p, &dp, &d2p, _state); - bufc->ptr.p_double[i] = nulc->ptr.p_double[i]*d2p*rho; - } - } - - /* - * Process nonlinear constraints - */ - for(i=0; i<=ng+nh-1; i++) - { - ae_v_move(&bufw->ptr.pp_double[nec+nic+i][0], 1, &jac->ptr.pp_double[1+i][0], 1, ae_v_len(0,n-1)); - v = fi->ptr.p_double[1+i]; - if( iptr.p_double[nec+nic+i] = d2p*rho; - } - else - { - - /* - * Inequality constraint - */ - minnlcinequalityshiftfunction(-v*rho+1, &p, &dp, &d2p, _state); - bufc->ptr.p_double[nec+nic+i] = nunlc->ptr.p_double[i]*d2p*rho; - } - } - - /* - * Add regularizer (large Rho often result in nearly-degenerate matrices; - * sometimes Cholesky decomposition fails without regularization). - * - * We use RegPrec*diag(W'*W) as preconditioner. - */ - k = nec+nic+ng+nh; - for(j=0; j<=n-1; j++) - { - tmp0->ptr.p_double[j] = 0.0; - } - for(i=0; i<=k-1; i++) - { - v = bufc->ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - tmp0->ptr.p_double[j] = tmp0->ptr.p_double[j]+v*bufw->ptr.pp_double[i][j]*bufw->ptr.pp_double[i][j]; - } - } - for(j=0; j<=n-1; j++) - { - bufd->ptr.p_double[j] = bufd->ptr.p_double[j]+minnlc_regprec*tmp0->ptr.p_double[j]; - } - - /* - * Apply preconditioner - */ - if( prectype==1 ) - { - minlbfgssetprecrankklbfgsfast(auloptimizer, bufd, bufc, bufw, nec+nic+ng+nh, _state); - } - if( prectype==2&&*preccounter%updatefreq==0 ) - { - minlbfgssetpreclowrankexact(auloptimizer, bufd, bufc, bufw, nec+nic+ng+nh, _state); - } - if( prectype==3&&*preccounter%updatefreq==0 ) - { - - /* - * Generate full NxN dense Hessian - */ - rmatrixsetlengthatleast(bufz, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - bufz->ptr.pp_double[i][j] = (double)(0); - } - bufz->ptr.pp_double[i][i] = bufd->ptr.p_double[i]; - } - if( nec+nic+ng+nh>0 ) - { - for(i=0; i<=nec+nic+ng+nh-1; i++) - { - ae_assert(ae_fp_greater_eq(bufc->ptr.p_double[i],(double)(0)), "MinNLC: updatepreconditioner() integrity failure", _state); - v = ae_sqrt(bufc->ptr.p_double[i], _state); - for(j=0; j<=n-1; j++) - { - bufw->ptr.pp_double[i][j] = bufw->ptr.pp_double[i][j]*v; - } - } - rmatrixsyrk(n, nec+nic+ng+nh, 1.0, bufw, 0, 0, 2, 1.0, bufz, 0, 0, ae_true, _state); - } - - /* - * Evaluate Cholesky decomposition, set preconditioner - */ - bflag = spdmatrixcholeskyrec(bufz, 0, n, ae_true, bufd, _state); - ae_assert(bflag, "MinNLC: updatepreconditioner() failure, Cholesky failed", _state); - minlbfgssetpreccholesky(auloptimizer, bufz, ae_true, _state); - } - inc(preccounter, _state); -} - - -/************************************************************************* -This subroutine adds penalty from boundary constraints to target function -and its gradient. Penalty function is one which is used for main AUL cycle -- with Lagrange multipliers and infinite at the barrier and beyond. - -Parameters: - X[] - current point - BndL[], BndU[] - boundary constraints - HasBndL[], HasBndU[] - I-th element is True if corresponding constraint is present - NuBC[] - Lagrange multipliers corresponding to constraints - Rho - penalty term - StabilizingPoint - branch point for inequality stabilizing term - F - function value to modify - G - gradient to modify - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -static void minnlc_penaltybc(/* Real */ ae_vector* x, - /* Real */ ae_vector* bndl, - /* Boolean */ ae_vector* hasbndl, - /* Real */ ae_vector* bndu, - /* Boolean */ ae_vector* hasbndu, - /* Real */ ae_vector* nubc, - ae_int_t n, - double rho, - double stabilizingpoint, - double* f, - /* Real */ ae_vector* g, - ae_state *_state) -{ - ae_int_t i; - double p; - double dp; - double d2p; - - - for(i=0; i<=n-1; i++) - { - if( (hasbndl->ptr.p_bool[i]&&hasbndu->ptr.p_bool[i])&&ae_fp_eq(bndl->ptr.p_double[i],bndu->ptr.p_double[i]) ) - { - - /* - * I-th boundary constraint is of equality-type - */ - minnlcequalitypenaltyfunction((x->ptr.p_double[i]-bndl->ptr.p_double[i])*rho, &p, &dp, &d2p, _state); - *f = *f+p/rho-nubc->ptr.p_double[2*i+0]*(x->ptr.p_double[i]-bndl->ptr.p_double[i]); - g->ptr.p_double[i] = g->ptr.p_double[i]+dp-nubc->ptr.p_double[2*i+0]; - continue; - } - if( hasbndl->ptr.p_bool[i] ) - { - - /* - * Handle lower bound - */ - minnlcinequalitypenaltyfunction(x->ptr.p_double[i]-bndl->ptr.p_double[i], stabilizingpoint, &p, &dp, &d2p, _state); - *f = *f+rho*p; - g->ptr.p_double[i] = g->ptr.p_double[i]+rho*dp; - minnlcinequalityshiftfunction((x->ptr.p_double[i]-bndl->ptr.p_double[i])*rho+1, &p, &dp, &d2p, _state); - *f = *f+p/rho*nubc->ptr.p_double[2*i+0]; - g->ptr.p_double[i] = g->ptr.p_double[i]+dp*nubc->ptr.p_double[2*i+0]; - } - if( hasbndu->ptr.p_bool[i] ) - { - - /* - * Handle upper bound - */ - minnlcinequalitypenaltyfunction(bndu->ptr.p_double[i]-x->ptr.p_double[i], stabilizingpoint, &p, &dp, &d2p, _state); - *f = *f+rho*p; - g->ptr.p_double[i] = g->ptr.p_double[i]-rho*dp; - minnlcinequalityshiftfunction((bndu->ptr.p_double[i]-x->ptr.p_double[i])*rho+1, &p, &dp, &d2p, _state); - *f = *f+p/rho*nubc->ptr.p_double[2*i+1]; - g->ptr.p_double[i] = g->ptr.p_double[i]-dp*nubc->ptr.p_double[2*i+1]; - } - } -} - - -/************************************************************************* -This subroutine adds penalty from linear constraints to target function -and its gradient. Penalty function is one which is used for main AUL cycle -- with Lagrange multipliers and infinite at the barrier and beyond. - -Parameters: - X[] - current point - CLEIC[] - constraints matrix, first NEC rows are equality ones, next - NIC rows are inequality ones. array[NEC+NIC,N+1] - NuLC[] - Lagrange multipliers corresponding to constraints, - array[NEC+NIC] - N - dimensionalty - NEC - number of equality constraints - NIC - number of inequality constraints. - Rho - penalty term - StabilizingPoint - branch point for inequality stabilizing term - F - function value to modify - G - gradient to modify - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -static void minnlc_penaltylc(/* Real */ ae_vector* x, - /* Real */ ae_matrix* cleic, - /* Real */ ae_vector* nulc, - ae_int_t n, - ae_int_t nec, - ae_int_t nic, - double rho, - double stabilizingpoint, - double* f, - /* Real */ ae_vector* g, - ae_state *_state) -{ - ae_int_t i; - double v; - double p; - double dp; - double d2p; - double fupd; - double gupd; - - - for(i=0; i<=nec+nic-1; i++) - { - v = ae_v_dotproduct(&cleic->ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = v-cleic->ptr.pp_double[i][n]; - fupd = (double)(0); - gupd = (double)(0); - if( iptr.p_double[i]*v; - gupd = gupd-nulc->ptr.p_double[i]; - } - else - { - - /* - * Inequality constraint - */ - minnlcinequalitypenaltyfunction(-v, stabilizingpoint, &p, &dp, &d2p, _state); - fupd = fupd+p*rho; - gupd = gupd-dp*rho; - minnlcinequalityshiftfunction(-v*rho+1, &p, &dp, &d2p, _state); - fupd = fupd+p/rho*nulc->ptr.p_double[i]; - gupd = gupd-dp*nulc->ptr.p_double[i]; - } - *f = *f+fupd; - ae_v_addd(&g->ptr.p_double[0], 1, &cleic->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), gupd); - } -} - - -/************************************************************************* -This subroutine adds penalty from nonlinear constraints to target function -and its gradient. Penalty function is one which is used for main AUL cycle -- with Lagrange multipliers and infinite at the barrier and beyond. - -Parameters: - Fi[] - function vector: - * 1 component for function being minimized - * NG components for equality constraints G_i(x)=0 - * NH components for inequality constraints H_i(x)<=0 - J[] - Jacobian matrix, array[1+NG+NH,N] - NuNLC[] - Lagrange multipliers corresponding to constraints, - array[NG+NH] - N - number of dimensions - NG - number of equality constraints - NH - number of inequality constraints - Rho - penalty term - StabilizingPoint - branch point for inequality stabilizing term - F - function value to modify - G - gradient to modify - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -static void minnlc_penaltynlc(/* Real */ ae_vector* fi, - /* Real */ ae_matrix* j, - /* Real */ ae_vector* nunlc, - ae_int_t n, - ae_int_t ng, - ae_int_t nh, - double rho, - double stabilizingpoint, - double* f, - /* Real */ ae_vector* g, - ae_state *_state) -{ - ae_int_t i; - double v; - double p; - double dp; - double d2p; - double fupd; - double gupd; - - - - /* - * IMPORTANT: loop starts from 1, not zero! - */ - for(i=1; i<=ng+nh; i++) - { - v = fi->ptr.p_double[i]; - fupd = (double)(0); - gupd = (double)(0); - if( i<=ng ) - { - - /* - * Equality constraint - */ - minnlcequalitypenaltyfunction(v*rho, &p, &dp, &d2p, _state); - fupd = fupd+p/rho; - gupd = gupd+dp; - fupd = fupd-nunlc->ptr.p_double[i-1]*v; - gupd = gupd-nunlc->ptr.p_double[i-1]; - } - else - { - - /* - * Inequality constraint - */ - minnlcinequalitypenaltyfunction(-v, stabilizingpoint, &p, &dp, &d2p, _state); - fupd = fupd+p*rho; - gupd = gupd-dp*rho; - minnlcinequalityshiftfunction(-v*rho+1, &p, &dp, &d2p, _state); - fupd = fupd+p/rho*nunlc->ptr.p_double[i-1]; - gupd = gupd-dp*nunlc->ptr.p_double[i-1]; - } - *f = *f+fupd; - ae_v_addd(&g->ptr.p_double[0], 1, &j->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), gupd); - } -} - - -/************************************************************************* -This function performs actual processing for AUL algorithm. It expects that -caller redirects its reverse communication requests NeedFiJ/XUpdated to -external user who will provide analytic derivative (or handle reports about -progress). - -In case external user does not have analytic derivative, it is responsibility -of caller to intercept NeedFiJ request and replace it with appropriate -numerical differentiation scheme. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -static ae_bool minnlc_auliteration(minnlcstate* state, - smoothnessmonitor* smonitor, - ae_state *_state) -{ - ae_int_t n; - ae_int_t nec; - ae_int_t nic; - ae_int_t ng; - ae_int_t nh; - ae_int_t i; - ae_int_t j; - ae_int_t outerit; - ae_int_t preccounter; - double v; - double vv; - double p; - double dp; - double d2p; - double v0; - double v1; - double v2; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstateaul.stage>=0 ) - { - n = state->rstateaul.ia.ptr.p_int[0]; - nec = state->rstateaul.ia.ptr.p_int[1]; - nic = state->rstateaul.ia.ptr.p_int[2]; - ng = state->rstateaul.ia.ptr.p_int[3]; - nh = state->rstateaul.ia.ptr.p_int[4]; - i = state->rstateaul.ia.ptr.p_int[5]; - j = state->rstateaul.ia.ptr.p_int[6]; - outerit = state->rstateaul.ia.ptr.p_int[7]; - preccounter = state->rstateaul.ia.ptr.p_int[8]; - v = state->rstateaul.ra.ptr.p_double[0]; - vv = state->rstateaul.ra.ptr.p_double[1]; - p = state->rstateaul.ra.ptr.p_double[2]; - dp = state->rstateaul.ra.ptr.p_double[3]; - d2p = state->rstateaul.ra.ptr.p_double[4]; - v0 = state->rstateaul.ra.ptr.p_double[5]; - v1 = state->rstateaul.ra.ptr.p_double[6]; - v2 = state->rstateaul.ra.ptr.p_double[7]; - } - else - { - n = 809; - nec = 205; - nic = -838; - ng = 939; - nh = -526; - i = 763; - j = -541; - outerit = -698; - preccounter = -900; - v = -318; - vv = -940; - p = 1016; - dp = -229; - d2p = -536; - v0 = 487; - v1 = -115; - v2 = 886; - } - if( state->rstateaul.stage==0 ) - { - goto lbl_0; - } - if( state->rstateaul.stage==1 ) - { - goto lbl_1; - } - if( state->rstateaul.stage==2 ) - { - goto lbl_2; - } - - /* - * Routine body - */ - ae_assert(state->solvertype==0, "MinNLC: internal error", _state); - n = state->n; - nec = state->nec; - nic = state->nic; - ng = state->ng; - nh = state->nh; - - /* - * Prepare scaled problem - */ - rvectorsetlengthatleast(&state->scaledbndl, n, _state); - rvectorsetlengthatleast(&state->scaledbndu, n, _state); - rmatrixsetlengthatleast(&state->scaledcleic, nec+nic, n+1, _state); - for(i=0; i<=n-1; i++) - { - if( state->hasbndl.ptr.p_bool[i] ) - { - state->scaledbndl.ptr.p_double[i] = state->bndl.ptr.p_double[i]/state->s.ptr.p_double[i]; - } - if( state->hasbndu.ptr.p_bool[i] ) - { - state->scaledbndu.ptr.p_double[i] = state->bndu.ptr.p_double[i]/state->s.ptr.p_double[i]; - } - state->xc.ptr.p_double[i] = state->xstart.ptr.p_double[i]/state->s.ptr.p_double[i]; - } - for(i=0; i<=nec+nic-1; i++) - { - - /* - * Scale and normalize linear constraints - */ - vv = 0.0; - for(j=0; j<=n-1; j++) - { - v = state->cleic.ptr.pp_double[i][j]*state->s.ptr.p_double[j]; - state->scaledcleic.ptr.pp_double[i][j] = v; - vv = vv+v*v; - } - vv = ae_sqrt(vv, _state); - state->scaledcleic.ptr.pp_double[i][n] = state->cleic.ptr.pp_double[i][n]; - if( ae_fp_greater(vv,(double)(0)) ) - { - for(j=0; j<=n; j++) - { - state->scaledcleic.ptr.pp_double[i][j] = state->scaledcleic.ptr.pp_double[i][j]/vv; - } - } - } - - /* - * Prepare stopping criteria - */ - minlbfgssetcond(&state->auloptimizer, (double)(0), (double)(0), state->epsx, state->maxits, _state); - minlbfgssetstpmax(&state->auloptimizer, state->stpmax, _state); - - /* - * Main AUL cycle: - * * prepare Lagrange multipliers NuNB/NuLC - * * set GammaK (current estimate of Hessian norm) to InitGamma and XKPresent to False - */ - rvectorsetlengthatleast(&state->nubc, 2*n, _state); - rvectorsetlengthatleast(&state->nulc, nec+nic, _state); - rvectorsetlengthatleast(&state->nunlc, ng+nh, _state); - rvectorsetlengthatleast(&state->xk, n, _state); - rvectorsetlengthatleast(&state->gk, n, _state); - rvectorsetlengthatleast(&state->xk1, n, _state); - rvectorsetlengthatleast(&state->gk1, n, _state); - for(i=0; i<=n-1; i++) - { - state->nubc.ptr.p_double[2*i+0] = 0.0; - state->nubc.ptr.p_double[2*i+1] = 0.0; - if( (state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_eq(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - continue; - } - if( state->hasbndl.ptr.p_bool[i] ) - { - state->nubc.ptr.p_double[2*i+0] = state->initialinequalitymultiplier; - } - if( state->hasbndu.ptr.p_bool[i] ) - { - state->nubc.ptr.p_double[2*i+1] = state->initialinequalitymultiplier; - } - } - for(i=0; i<=nec-1; i++) - { - state->nulc.ptr.p_double[i] = 0.0; - } - for(i=0; i<=nic-1; i++) - { - state->nulc.ptr.p_double[nec+i] = state->initialinequalitymultiplier; - } - for(i=0; i<=ng-1; i++) - { - state->nunlc.ptr.p_double[i] = 0.0; - } - for(i=0; i<=nh-1; i++) - { - state->nunlc.ptr.p_double[ng+i] = state->initialinequalitymultiplier; - } - state->gammak = minnlc_initgamma; - state->xkpresent = ae_false; - ae_assert(state->aulitscnt>0, "MinNLC: integrity check failed", _state); - minnlc_clearpreconditioner(&state->auloptimizer, _state); - outerit = 0; -lbl_3: - if( outerit>state->aulitscnt-1 ) - { - goto lbl_5; - } - - /* - * Optimize with current Lagrange multipliers - * - * NOTE: this code expects and checks that line search ends in the - * point which is used as beginning for the next search. Such - * guarantee is given by MCSRCH function. L-BFGS optimizer - * does not formally guarantee it, but it follows same rule. - * Below we a) rely on such property of the optimizer, and b) - * assert that it is true, in order to fail loudly if it is - * not true. - * - * NOTE: security check for NAN/INF in F/G is responsibility of - * LBFGS optimizer. AUL optimizer checks for NAN/INF only - * when we update Lagrange multipliers. - */ - preccounter = 0; - minlbfgssetxrep(&state->auloptimizer, ae_true, _state); - minlbfgsrestartfrom(&state->auloptimizer, &state->xc, _state); -lbl_6: - if( !minlbfgsiteration(&state->auloptimizer, _state) ) - { - goto lbl_7; - } - if( !state->auloptimizer.needfg ) - { - goto lbl_8; - } - - /* - * Un-scale X, evaluate F/G/H, re-scale Jacobian - */ - for(i=0; i<=n-1; i++) - { - state->x.ptr.p_double[i] = state->auloptimizer.x.ptr.p_double[i]*state->s.ptr.p_double[i]; - } - state->needfij = ae_true; - state->rstateaul.stage = 0; - goto lbl_rcomm; -lbl_0: - state->needfij = ae_false; - for(i=0; i<=ng+nh; i++) - { - for(j=0; j<=n-1; j++) - { - state->j.ptr.pp_double[i][j] = state->j.ptr.pp_double[i][j]*state->s.ptr.p_double[j]; - } - } - - /* - * Store data for estimation of Hessian norm: - * * current point (re-scaled) - * * gradient of the target function (re-scaled, unmodified) - */ - ae_v_move(&state->xk1.ptr.p_double[0], 1, &state->auloptimizer.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->gk1.ptr.p_double[0], 1, &state->j.ptr.pp_double[0][0], 1, ae_v_len(0,n-1)); - - /* - * Function being optimized - */ - state->auloptimizer.f = state->fi.ptr.p_double[0]; - for(i=0; i<=n-1; i++) - { - state->auloptimizer.g.ptr.p_double[i] = state->j.ptr.pp_double[0][i]; - } - - /* - * Send information to OptGuard monitor - */ - smoothnessmonitorenqueuepoint(smonitor, &state->auloptimizer.d, state->auloptimizer.stp, &state->auloptimizer.x, &state->fi, &state->j, _state); - - /* - * Penalty for violation of boundary/linear/nonlinear constraints - */ - minnlc_penaltybc(&state->auloptimizer.x, &state->scaledbndl, &state->hasbndl, &state->scaledbndu, &state->hasbndu, &state->nubc, n, state->rho, state->stabilizingpoint, &state->auloptimizer.f, &state->auloptimizer.g, _state); - minnlc_penaltylc(&state->auloptimizer.x, &state->scaledcleic, &state->nulc, n, nec, nic, state->rho, state->stabilizingpoint, &state->auloptimizer.f, &state->auloptimizer.g, _state); - minnlc_penaltynlc(&state->fi, &state->j, &state->nunlc, n, ng, nh, state->rho, state->stabilizingpoint, &state->auloptimizer.f, &state->auloptimizer.g, _state); - - /* - * Forward termination request if needed - */ - if( state->userterminationneeded ) - { - minlbfgsrequesttermination(&state->auloptimizer, _state); - } - - /* - * To optimizer - */ - goto lbl_6; -lbl_8: - if( !state->auloptimizer.xupdated ) - { - goto lbl_10; - } - - /* - * Report current point (if needed) - */ - if( !state->xrep ) - { - goto lbl_12; - } - for(i=0; i<=n-1; i++) - { - state->x.ptr.p_double[i] = state->auloptimizer.x.ptr.p_double[i]*state->s.ptr.p_double[i]; - } - state->f = state->auloptimizer.f; - state->xupdated = ae_true; - state->rstateaul.stage = 1; - goto lbl_rcomm; -lbl_1: - state->xupdated = ae_false; -lbl_12: - - /* - * Send information to OptGuard monitor - */ - smoothnessmonitorfinalizelinesearch(smonitor, _state); - smoothnessmonitorstartlinesearch(smonitor, &state->auloptimizer.x, &state->fi, &state->j, _state); - - /* - * Forward termination request if needed - */ - if( state->userterminationneeded ) - { - minlbfgsrequesttermination(&state->auloptimizer, _state); - } - - /* - * Update constraints violation - */ - checkbcviolation(&state->hasbndl, &state->scaledbndl, &state->hasbndu, &state->scaledbndu, &state->auloptimizer.x, n, &state->s, ae_false, &state->repbcerr, &state->repbcidx, _state); - checklcviolation(&state->scaledcleic, &state->lcsrcidx, nec, nic, &state->auloptimizer.x, n, &state->replcerr, &state->replcidx, _state); - checknlcviolation(&state->fi, ng, nh, &state->repnlcerr, &state->repnlcidx, _state); - - /* - * Update GammaK - */ - if( state->xkpresent ) - { - - /* - * XK/GK store beginning of current line search, and XK1/GK1 - * store data for the end of the line search: - * * first, we Assert() that XK1 (last point where function - * was evaluated) is same as AULOptimizer.X (what is - * reported by RComm interface - * * calculate step length V2. - * - * If V2>HessEstTol, then: - * * calculate V0 - directional derivative at XK, - * and V1 - directional derivative at XK1 - * * set GammaK to Max(GammaK, |V1-V0|/V2) - */ - for(i=0; i<=n-1; i++) - { - ae_assert(ae_fp_less_eq(ae_fabs(state->auloptimizer.x.ptr.p_double[i]-state->xk1.ptr.p_double[i], _state),100*ae_machineepsilon)||!(ae_isfinite(state->auloptimizer.x.ptr.p_double[i], _state)&&ae_isfinite(state->xk1.ptr.p_double[i], _state)), "MinNLC: integrity check failed, unexpected behavior of LBFGS optimizer", _state); - } - v2 = 0.0; - for(i=0; i<=n-1; i++) - { - v2 = v2+ae_sqr(state->xk.ptr.p_double[i]-state->xk1.ptr.p_double[i], _state); - } - v2 = ae_sqrt(v2, _state); - if( ae_fp_greater(v2,minnlc_hessesttol) ) - { - v0 = 0.0; - v1 = 0.0; - for(i=0; i<=n-1; i++) - { - v = (state->xk.ptr.p_double[i]-state->xk1.ptr.p_double[i])/v2; - v0 = v0+state->gk.ptr.p_double[i]*v; - v1 = v1+state->gk1.ptr.p_double[i]*v; - } - state->gammak = ae_maxreal(state->gammak, ae_fabs(v1-v0, _state)/v2, _state); - } - } - else - { - - /* - * Beginning of the first line search, XK is not yet initialized. - */ - ae_v_move(&state->xk.ptr.p_double[0], 1, &state->xk1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->gk.ptr.p_double[0], 1, &state->gk1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->xkpresent = ae_true; - } - - /* - * Update preconsitioner using current GammaK - */ - minnlc_updatepreconditioner(state->prectype, state->updatefreq, &preccounter, &state->auloptimizer, &state->auloptimizer.x, state->rho, state->gammak, &state->scaledbndl, &state->hasbndl, &state->scaledbndu, &state->hasbndu, &state->nubc, &state->scaledcleic, &state->nulc, &state->fi, &state->j, &state->nunlc, &state->bufd, &state->bufc, &state->bufw, &state->bufz, &state->tmp0, n, nec, nic, ng, nh, _state); - goto lbl_6; -lbl_10: - ae_assert(ae_false, "MinNLC: integrity check failed", _state); - goto lbl_6; -lbl_7: - minlbfgsresultsbuf(&state->auloptimizer, &state->xc, &state->aulreport, _state); - state->repinneriterationscount = state->repinneriterationscount+state->aulreport.iterationscount; - state->repnfev = state->repnfev+state->aulreport.nfev; - state->repterminationtype = state->aulreport.terminationtype; - inc(&state->repouteriterationscount, _state); - if( state->repterminationtype<=0||state->repterminationtype==8 ) - { - goto lbl_5; - } - - /* - * 1. Evaluate F/J - * 2. Check for NAN/INF in F/J: we just calculate sum of their - * components, it should be enough to reduce vector/matrix to - * just one value which either "normal" (all summands were "normal") - * or NAN/INF (at least one summand was NAN/INF). - * 3. Update Lagrange multipliers - */ - for(i=0; i<=n-1; i++) - { - state->x.ptr.p_double[i] = state->xc.ptr.p_double[i]*state->s.ptr.p_double[i]; - } - state->needfij = ae_true; - state->rstateaul.stage = 2; - goto lbl_rcomm; -lbl_2: - state->needfij = ae_false; - v = 0.0; - for(i=0; i<=ng+nh; i++) - { - v = 0.1*v+state->fi.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - v = 0.1*v+state->j.ptr.pp_double[i][j]; - } - } - if( !ae_isfinite(v, _state) ) - { - - /* - * Abnormal termination - infinities in function/gradient - */ - state->repterminationtype = -8; - result = ae_false; - return result; - } - for(i=0; i<=ng+nh; i++) - { - for(j=0; j<=n-1; j++) - { - state->j.ptr.pp_double[i][j] = state->j.ptr.pp_double[i][j]*state->s.ptr.p_double[j]; - } - } - for(i=0; i<=n-1; i++) - { - - /* - * Process coefficients corresponding to equality-type - * constraints. - */ - if( (state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_eq(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - minnlcequalitypenaltyfunction((state->xc.ptr.p_double[i]-state->scaledbndl.ptr.p_double[i])*state->rho, &p, &dp, &d2p, _state); - state->nubc.ptr.p_double[2*i+0] = boundval(state->nubc.ptr.p_double[2*i+0]-dp, -minnlc_maxlagmult, minnlc_maxlagmult, _state); - continue; - } - - /* - * Process coefficients corresponding to inequality-type - * constraints. These coefficients have limited growth/decay - * per iteration which helps to stabilize algorithm. - */ - ae_assert(ae_fp_greater(minnlc_aulmaxgrowth,1.0), "MinNLC: integrity error", _state); - if( state->hasbndl.ptr.p_bool[i] ) - { - minnlcinequalityshiftfunction((state->xc.ptr.p_double[i]-state->scaledbndl.ptr.p_double[i])*state->rho+1, &p, &dp, &d2p, _state); - v = ae_fabs(dp, _state); - v = ae_minreal(v, minnlc_aulmaxgrowth, _state); - v = ae_maxreal(v, 1/minnlc_aulmaxgrowth, _state); - state->nubc.ptr.p_double[2*i+0] = boundval(state->nubc.ptr.p_double[2*i+0]*v, -minnlc_maxlagmult, minnlc_maxlagmult, _state); - } - if( state->hasbndu.ptr.p_bool[i] ) - { - minnlcinequalityshiftfunction((state->scaledbndu.ptr.p_double[i]-state->xc.ptr.p_double[i])*state->rho+1, &p, &dp, &d2p, _state); - v = ae_fabs(dp, _state); - v = ae_minreal(v, minnlc_aulmaxgrowth, _state); - v = ae_maxreal(v, 1/minnlc_aulmaxgrowth, _state); - state->nubc.ptr.p_double[2*i+1] = boundval(state->nubc.ptr.p_double[2*i+1]*v, -minnlc_maxlagmult, minnlc_maxlagmult, _state); - } - } - for(i=0; i<=nec+nic-1; i++) - { - v = ae_v_dotproduct(&state->scaledcleic.ptr.pp_double[i][0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = v-state->scaledcleic.ptr.pp_double[i][n]; - if( irho, &p, &dp, &d2p, _state); - state->nulc.ptr.p_double[i] = boundval(state->nulc.ptr.p_double[i]-dp, -minnlc_maxlagmult, minnlc_maxlagmult, _state); - } - else - { - minnlcinequalityshiftfunction(-v*state->rho+1, &p, &dp, &d2p, _state); - v = ae_fabs(dp, _state); - v = ae_minreal(v, minnlc_aulmaxgrowth, _state); - v = ae_maxreal(v, 1/minnlc_aulmaxgrowth, _state); - state->nulc.ptr.p_double[i] = boundval(state->nulc.ptr.p_double[i]*v, -minnlc_maxlagmult, minnlc_maxlagmult, _state); - } - } - for(i=1; i<=ng+nh; i++) - { - - /* - * NOTE: loop index must start from 1, not zero! - */ - v = state->fi.ptr.p_double[i]; - if( i<=ng ) - { - minnlcequalitypenaltyfunction(v*state->rho, &p, &dp, &d2p, _state); - state->nunlc.ptr.p_double[i-1] = boundval(state->nunlc.ptr.p_double[i-1]-dp, -minnlc_maxlagmult, minnlc_maxlagmult, _state); - } - else - { - minnlcinequalityshiftfunction(-v*state->rho+1, &p, &dp, &d2p, _state); - v = ae_fabs(dp, _state); - v = ae_minreal(v, minnlc_aulmaxgrowth, _state); - v = ae_maxreal(v, 1/minnlc_aulmaxgrowth, _state); - state->nunlc.ptr.p_double[i-1] = boundval(state->nunlc.ptr.p_double[i-1]*v, -minnlc_maxlagmult, minnlc_maxlagmult, _state); - } - } - outerit = outerit+1; - goto lbl_3; -lbl_5: - for(i=0; i<=n-1; i++) - { - state->xc.ptr.p_double[i] = state->xc.ptr.p_double[i]*state->s.ptr.p_double[i]; - } - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstateaul.ia.ptr.p_int[0] = n; - state->rstateaul.ia.ptr.p_int[1] = nec; - state->rstateaul.ia.ptr.p_int[2] = nic; - state->rstateaul.ia.ptr.p_int[3] = ng; - state->rstateaul.ia.ptr.p_int[4] = nh; - state->rstateaul.ia.ptr.p_int[5] = i; - state->rstateaul.ia.ptr.p_int[6] = j; - state->rstateaul.ia.ptr.p_int[7] = outerit; - state->rstateaul.ia.ptr.p_int[8] = preccounter; - state->rstateaul.ra.ptr.p_double[0] = v; - state->rstateaul.ra.ptr.p_double[1] = vv; - state->rstateaul.ra.ptr.p_double[2] = p; - state->rstateaul.ra.ptr.p_double[3] = dp; - state->rstateaul.ra.ptr.p_double[4] = d2p; - state->rstateaul.ra.ptr.p_double[5] = v0; - state->rstateaul.ra.ptr.p_double[6] = v1; - state->rstateaul.ra.ptr.p_double[7] = v2; - return result; -} - - -/************************************************************************* -Unscales X (converts from scaled variables to original ones), paying special -attention to box constraints (output is always feasible; active constraints -are mapped to active ones). -*************************************************************************/ -static void minnlc_unscale(minnlcstate* state, - /* Real */ ae_vector* xs, - /* Real */ ae_vector* scaledbndl, - /* Real */ ae_vector* scaledbndu, - /* Real */ ae_vector* xu, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - - - n = state->n; - for(i=0; i<=n-1; i++) - { - if( state->hasbndl.ptr.p_bool[i]&&xs->ptr.p_double[i]<=scaledbndl->ptr.p_double[i] ) - { - xu->ptr.p_double[i] = state->bndl.ptr.p_double[i]; - continue; - } - if( state->hasbndu.ptr.p_bool[i]&&xs->ptr.p_double[i]>=scaledbndu->ptr.p_double[i] ) - { - xu->ptr.p_double[i] = state->bndu.ptr.p_double[i]; - continue; - } - xu->ptr.p_double[i] = xs->ptr.p_double[i]*state->s.ptr.p_double[i]; - if( state->hasbndl.ptr.p_bool[i]&&xu->ptr.p_double[i]bndl.ptr.p_double[i] ) - { - xu->ptr.p_double[i] = state->bndl.ptr.p_double[i]; - } - if( state->hasbndu.ptr.p_bool[i]&&xu->ptr.p_double[i]>state->bndu.ptr.p_double[i] ) - { - xu->ptr.p_double[i] = state->bndu.ptr.p_double[i]; - } - } -} - - -void _minnlcstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minnlcstate *p = (minnlcstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->hasbndl, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->hasbndu, 0, DT_BOOL, _state, make_automatic); - ae_matrix_init(&p->cleic, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->lcsrcidx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fi, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->j, 0, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); - _rcommstate_init(&p->rstateaul, _state, make_automatic); - _rcommstate_init(&p->rstateslp, _state, make_automatic); - ae_vector_init(&p->scaledbndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->scaledbndu, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->scaledcleic, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xstart, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xbase, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fbase, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dfbase, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fm2, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fm1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fp1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fp2, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dfm1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dfp1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bufd, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bufc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->bufw, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->bufz, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xk, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xk1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->gk, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->gk1, 0, DT_REAL, _state, make_automatic); - _minlbfgsstate_init(&p->auloptimizer, _state, make_automatic); - _minlbfgsreport_init(&p->aulreport, _state, make_automatic); - ae_vector_init(&p->nubc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->nulc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->nunlc, 0, DT_REAL, _state, make_automatic); - _minslpstate_init(&p->slpsolverstate, _state, make_automatic); - _minsqpstate_init(&p->sqpsolverstate, _state, make_automatic); - _smoothnessmonitor_init(&p->smonitor, _state, make_automatic); - ae_vector_init(&p->lastscaleused, 0, DT_REAL, _state, make_automatic); -} - - -void _minnlcstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minnlcstate *dst = (minnlcstate*)_dst; - minnlcstate *src = (minnlcstate*)_src; - dst->stabilizingpoint = src->stabilizingpoint; - dst->initialinequalitymultiplier = src->initialinequalitymultiplier; - dst->solvertype = src->solvertype; - dst->prectype = src->prectype; - dst->updatefreq = src->updatefreq; - dst->rho = src->rho; - dst->n = src->n; - dst->epsx = src->epsx; - dst->maxits = src->maxits; - dst->aulitscnt = src->aulitscnt; - dst->xrep = src->xrep; - dst->stpmax = src->stpmax; - dst->diffstep = src->diffstep; - dst->teststep = src->teststep; - ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic); - ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic); - ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic); - ae_vector_init_copy(&dst->hasbndl, &src->hasbndl, _state, make_automatic); - ae_vector_init_copy(&dst->hasbndu, &src->hasbndu, _state, make_automatic); - dst->nec = src->nec; - dst->nic = src->nic; - ae_matrix_init_copy(&dst->cleic, &src->cleic, _state, make_automatic); - ae_vector_init_copy(&dst->lcsrcidx, &src->lcsrcidx, _state, make_automatic); - dst->ng = src->ng; - dst->nh = src->nh; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - dst->f = src->f; - ae_vector_init_copy(&dst->fi, &src->fi, _state, make_automatic); - ae_matrix_init_copy(&dst->j, &src->j, _state, make_automatic); - dst->needfij = src->needfij; - dst->needfi = src->needfi; - dst->xupdated = src->xupdated; - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); - _rcommstate_init_copy(&dst->rstateaul, &src->rstateaul, _state, make_automatic); - _rcommstate_init_copy(&dst->rstateslp, &src->rstateslp, _state, make_automatic); - ae_vector_init_copy(&dst->scaledbndl, &src->scaledbndl, _state, make_automatic); - ae_vector_init_copy(&dst->scaledbndu, &src->scaledbndu, _state, make_automatic); - ae_matrix_init_copy(&dst->scaledcleic, &src->scaledcleic, _state, make_automatic); - ae_vector_init_copy(&dst->xc, &src->xc, _state, make_automatic); - ae_vector_init_copy(&dst->xstart, &src->xstart, _state, make_automatic); - ae_vector_init_copy(&dst->xbase, &src->xbase, _state, make_automatic); - ae_vector_init_copy(&dst->fbase, &src->fbase, _state, make_automatic); - ae_vector_init_copy(&dst->dfbase, &src->dfbase, _state, make_automatic); - ae_vector_init_copy(&dst->fm2, &src->fm2, _state, make_automatic); - ae_vector_init_copy(&dst->fm1, &src->fm1, _state, make_automatic); - ae_vector_init_copy(&dst->fp1, &src->fp1, _state, make_automatic); - ae_vector_init_copy(&dst->fp2, &src->fp2, _state, make_automatic); - ae_vector_init_copy(&dst->dfm1, &src->dfm1, _state, make_automatic); - ae_vector_init_copy(&dst->dfp1, &src->dfp1, _state, make_automatic); - ae_vector_init_copy(&dst->bufd, &src->bufd, _state, make_automatic); - ae_vector_init_copy(&dst->bufc, &src->bufc, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_matrix_init_copy(&dst->bufw, &src->bufw, _state, make_automatic); - ae_matrix_init_copy(&dst->bufz, &src->bufz, _state, make_automatic); - ae_vector_init_copy(&dst->xk, &src->xk, _state, make_automatic); - ae_vector_init_copy(&dst->xk1, &src->xk1, _state, make_automatic); - ae_vector_init_copy(&dst->gk, &src->gk, _state, make_automatic); - ae_vector_init_copy(&dst->gk1, &src->gk1, _state, make_automatic); - dst->gammak = src->gammak; - dst->xkpresent = src->xkpresent; - _minlbfgsstate_init_copy(&dst->auloptimizer, &src->auloptimizer, _state, make_automatic); - _minlbfgsreport_init_copy(&dst->aulreport, &src->aulreport, _state, make_automatic); - ae_vector_init_copy(&dst->nubc, &src->nubc, _state, make_automatic); - ae_vector_init_copy(&dst->nulc, &src->nulc, _state, make_automatic); - ae_vector_init_copy(&dst->nunlc, &src->nunlc, _state, make_automatic); - dst->userterminationneeded = src->userterminationneeded; - _minslpstate_init_copy(&dst->slpsolverstate, &src->slpsolverstate, _state, make_automatic); - _minsqpstate_init_copy(&dst->sqpsolverstate, &src->sqpsolverstate, _state, make_automatic); - dst->smoothnessguardlevel = src->smoothnessguardlevel; - _smoothnessmonitor_init_copy(&dst->smonitor, &src->smonitor, _state, make_automatic); - ae_vector_init_copy(&dst->lastscaleused, &src->lastscaleused, _state, make_automatic); - dst->repinneriterationscount = src->repinneriterationscount; - dst->repouteriterationscount = src->repouteriterationscount; - dst->repnfev = src->repnfev; - dst->repterminationtype = src->repterminationtype; - dst->repbcerr = src->repbcerr; - dst->repbcidx = src->repbcidx; - dst->replcerr = src->replcerr; - dst->replcidx = src->replcidx; - dst->repnlcerr = src->repnlcerr; - dst->repnlcidx = src->repnlcidx; - dst->repdbgphase0its = src->repdbgphase0its; -} - - -void _minnlcstate_clear(void* _p) -{ - minnlcstate *p = (minnlcstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->s); - ae_vector_clear(&p->bndl); - ae_vector_clear(&p->bndu); - ae_vector_clear(&p->hasbndl); - ae_vector_clear(&p->hasbndu); - ae_matrix_clear(&p->cleic); - ae_vector_clear(&p->lcsrcidx); - ae_vector_clear(&p->x); - ae_vector_clear(&p->fi); - ae_matrix_clear(&p->j); - _rcommstate_clear(&p->rstate); - _rcommstate_clear(&p->rstateaul); - _rcommstate_clear(&p->rstateslp); - ae_vector_clear(&p->scaledbndl); - ae_vector_clear(&p->scaledbndu); - ae_matrix_clear(&p->scaledcleic); - ae_vector_clear(&p->xc); - ae_vector_clear(&p->xstart); - ae_vector_clear(&p->xbase); - ae_vector_clear(&p->fbase); - ae_vector_clear(&p->dfbase); - ae_vector_clear(&p->fm2); - ae_vector_clear(&p->fm1); - ae_vector_clear(&p->fp1); - ae_vector_clear(&p->fp2); - ae_vector_clear(&p->dfm1); - ae_vector_clear(&p->dfp1); - ae_vector_clear(&p->bufd); - ae_vector_clear(&p->bufc); - ae_vector_clear(&p->tmp0); - ae_matrix_clear(&p->bufw); - ae_matrix_clear(&p->bufz); - ae_vector_clear(&p->xk); - ae_vector_clear(&p->xk1); - ae_vector_clear(&p->gk); - ae_vector_clear(&p->gk1); - _minlbfgsstate_clear(&p->auloptimizer); - _minlbfgsreport_clear(&p->aulreport); - ae_vector_clear(&p->nubc); - ae_vector_clear(&p->nulc); - ae_vector_clear(&p->nunlc); - _minslpstate_clear(&p->slpsolverstate); - _minsqpstate_clear(&p->sqpsolverstate); - _smoothnessmonitor_clear(&p->smonitor); - ae_vector_clear(&p->lastscaleused); -} - - -void _minnlcstate_destroy(void* _p) -{ - minnlcstate *p = (minnlcstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->s); - ae_vector_destroy(&p->bndl); - ae_vector_destroy(&p->bndu); - ae_vector_destroy(&p->hasbndl); - ae_vector_destroy(&p->hasbndu); - ae_matrix_destroy(&p->cleic); - ae_vector_destroy(&p->lcsrcidx); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->fi); - ae_matrix_destroy(&p->j); - _rcommstate_destroy(&p->rstate); - _rcommstate_destroy(&p->rstateaul); - _rcommstate_destroy(&p->rstateslp); - ae_vector_destroy(&p->scaledbndl); - ae_vector_destroy(&p->scaledbndu); - ae_matrix_destroy(&p->scaledcleic); - ae_vector_destroy(&p->xc); - ae_vector_destroy(&p->xstart); - ae_vector_destroy(&p->xbase); - ae_vector_destroy(&p->fbase); - ae_vector_destroy(&p->dfbase); - ae_vector_destroy(&p->fm2); - ae_vector_destroy(&p->fm1); - ae_vector_destroy(&p->fp1); - ae_vector_destroy(&p->fp2); - ae_vector_destroy(&p->dfm1); - ae_vector_destroy(&p->dfp1); - ae_vector_destroy(&p->bufd); - ae_vector_destroy(&p->bufc); - ae_vector_destroy(&p->tmp0); - ae_matrix_destroy(&p->bufw); - ae_matrix_destroy(&p->bufz); - ae_vector_destroy(&p->xk); - ae_vector_destroy(&p->xk1); - ae_vector_destroy(&p->gk); - ae_vector_destroy(&p->gk1); - _minlbfgsstate_destroy(&p->auloptimizer); - _minlbfgsreport_destroy(&p->aulreport); - ae_vector_destroy(&p->nubc); - ae_vector_destroy(&p->nulc); - ae_vector_destroy(&p->nunlc); - _minslpstate_destroy(&p->slpsolverstate); - _minsqpstate_destroy(&p->sqpsolverstate); - _smoothnessmonitor_destroy(&p->smonitor); - ae_vector_destroy(&p->lastscaleused); -} - - -void _minnlcreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minnlcreport *p = (minnlcreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _minnlcreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minnlcreport *dst = (minnlcreport*)_dst; - minnlcreport *src = (minnlcreport*)_src; - dst->iterationscount = src->iterationscount; - dst->nfev = src->nfev; - dst->terminationtype = src->terminationtype; - dst->bcerr = src->bcerr; - dst->bcidx = src->bcidx; - dst->lcerr = src->lcerr; - dst->lcidx = src->lcidx; - dst->nlcerr = src->nlcerr; - dst->nlcidx = src->nlcidx; - dst->dbgphase0its = src->dbgphase0its; -} - - -void _minnlcreport_clear(void* _p) -{ - minnlcreport *p = (minnlcreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _minnlcreport_destroy(void* _p) -{ - minnlcreport *p = (minnlcreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_MINBC) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* - BOX CONSTRAINED OPTIMIZATION - WITH FAST ACTIVATION OF MULTIPLE BOX CONSTRAINTS - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments subject to box -constraints (with some of box constraints actually being equality ones). - -This optimizer uses algorithm similar to that of MinBLEIC (optimizer with -general linear constraints), but presence of box-only constraints allows -us to use faster constraint activation strategies. On large-scale problems, -with multiple constraints active at the solution, this optimizer can be -several times faster than BLEIC. - -REQUIREMENTS: -* user must provide function value and gradient -* starting point X0 must be feasible or - not too far away from the feasible set -* grad(f) must be Lipschitz continuous on a level set: - L = { x : f(x)<=f(x0) } -* function must be defined everywhere on the feasible set F - -USAGE: - -Constrained optimization if far more complex than the unconstrained one. -Here we give very brief outline of the BC optimizer. We strongly recommend -you to read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide -on optimization, which is available at http://www.alglib.net/optimization/ - -1. User initializes algorithm state with MinBCCreate() call - -2. USer adds box constraints by calling MinBCSetBC() function. - -3. User sets stopping conditions with MinBCSetCond(). - -4. User calls MinBCOptimize() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. - -5. User calls MinBCResults() to get solution - -6. Optionally user may call MinBCRestartFrom() to solve another problem - with same N but another starting point. - MinBCRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size ofX - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbccreate(ae_int_t n, - /* Real */ ae_vector* x, - minbcstate* state, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix c; - ae_vector ct; - - ae_frame_make(_state, &_frame_block); - memset(&c, 0, sizeof(c)); - memset(&ct, 0, sizeof(ct)); - _minbcstate_clear(state); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - - ae_assert(n>=1, "MinBCCreate: N<1", _state); - ae_assert(x->cnt>=n, "MinBCCreate: Length(X)0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[0..N-1]. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinBCSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large truncation errors, while too small - step will result in too large numerical errors. 1.0E-6 can be good - value to start with. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. CG needs exact gradient values. Imprecise - gradient may slow down convergence, especially on highly nonlinear - problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -void minbccreatef(ae_int_t n, - /* Real */ ae_vector* x, - double diffstep, - minbcstate* state, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix c; - ae_vector ct; - - ae_frame_make(_state, &_frame_block); - memset(&c, 0, sizeof(c)); - memset(&ct, 0, sizeof(ct)); - _minbcstate_clear(state); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - - ae_assert(n>=1, "MinBCCreateF: N<1", _state); - ae_assert(x->cnt>=n, "MinBCCreateF: Length(X)nmain; - ae_assert(bndl->cnt>=n, "MinBCSetBC: Length(BndL)cnt>=n, "MinBCSetBC: Length(BndU)ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "MinBCSetBC: BndL contains NAN or +INF", _state); - ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "MinBCSetBC: BndL contains NAN or -INF", _state); - state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i]; - state->hasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state); - state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i]; - state->hasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state); - } -} - - -/************************************************************************* -This function sets stopping conditions for the optimizer. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|=0 - The subroutine finishes its work if on k+1-th iteration - the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - is satisfied. - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - step vector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinBCSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead -to automatic stopping criterion selection. - -NOTE: when SetCond() called with non-zero MaxIts, BC solver may perform - slightly more than MaxIts iterations. I.e., MaxIts sets non-strict - limit on iterations count. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcsetcond(minbcstate* state, - double epsg, - double epsf, - double epsx, - ae_int_t maxits, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(epsg, _state), "MinBCSetCond: EpsG is not finite number", _state); - ae_assert(ae_fp_greater_eq(epsg,(double)(0)), "MinBCSetCond: negative EpsG", _state); - ae_assert(ae_isfinite(epsf, _state), "MinBCSetCond: EpsF is not finite number", _state); - ae_assert(ae_fp_greater_eq(epsf,(double)(0)), "MinBCSetCond: negative EpsF", _state); - ae_assert(ae_isfinite(epsx, _state), "MinBCSetCond: EpsX is not finite number", _state); - ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinBCSetCond: negative EpsX", _state); - ae_assert(maxits>=0, "MinBCSetCond: negative MaxIts!", _state); - if( ((ae_fp_eq(epsg,(double)(0))&&ae_fp_eq(epsf,(double)(0)))&&ae_fp_eq(epsx,(double)(0)))&&maxits==0 ) - { - epsx = 1.0E-6; - } - state->epsg = epsg; - state->epsf = epsf; - state->epsx = epsx; - state->maxits = maxits; -} - - -/************************************************************************* -This function sets scaling coefficients for BC optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of the optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -In most optimizers (and in the BC too) scaling is NOT a form of -preconditioning. It just affects stopping conditions. You should set -preconditioner by separate call to one of the MinBCSetPrec...() -functions. - -There is a special preconditioning mode, however, which uses scaling -coefficients to form diagonal preconditioning matrix. You can turn this -mode on, if you want. But you should understand that scaling is not the -same thing as preconditioning - these are two different, although related -forms of tuning solver. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minbcsetscale(minbcstate* state, - /* Real */ ae_vector* s, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(s->cnt>=state->nmain, "MinBCSetScale: Length(S)nmain-1; i++) - { - ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinBCSetScale: S contains infinite or NAN elements", _state); - ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "MinBCSetScale: S contains zero elements", _state); - state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state); - } -} - - -/************************************************************************* -Modification of the preconditioner: preconditioning is turned off. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcsetprecdefault(minbcstate* state, ae_state *_state) -{ - - - state->prectype = 0; -} - - -/************************************************************************* -Modification of the preconditioner: diagonal of approximate Hessian is -used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - D - diagonal of the approximate Hessian, array[0..N-1], - (if larger, only leading N elements are used). - -NOTE 1: D[i] should be positive. Exception will be thrown otherwise. - -NOTE 2: you should pass diagonal of approximate Hessian - NOT ITS INVERSE. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcsetprecdiag(minbcstate* state, - /* Real */ ae_vector* d, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(d->cnt>=state->nmain, "MinBCSetPrecDiag: D is too short", _state); - for(i=0; i<=state->nmain-1; i++) - { - ae_assert(ae_isfinite(d->ptr.p_double[i], _state), "MinBCSetPrecDiag: D contains infinite or NAN elements", _state); - ae_assert(ae_fp_greater(d->ptr.p_double[i],(double)(0)), "MinBCSetPrecDiag: D contains non-positive elements", _state); - } - rvectorsetlengthatleast(&state->diagh, state->nmain, _state); - state->prectype = 2; - for(i=0; i<=state->nmain-1; i++) - { - state->diagh.ptr.p_double[i] = d->ptr.p_double[i]; - } -} - - -/************************************************************************* -Modification of the preconditioner: scale-based diagonal preconditioning. - -This preconditioning mode can be useful when you don't have approximate -diagonal of Hessian, but you know that your variables are badly scaled -(for example, one variable is in [1,10], and another in [1000,100000]), -and most part of the ill-conditioning comes from different scales of vars. - -In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2), -can greatly improve convergence. - -IMPRTANT: you should set scale of your variables with MinBCSetScale() -call (before or after MinBCSetPrecScale() call). Without knowledge of -the scale of your variables scale-based preconditioner will be just unit -matrix. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcsetprecscale(minbcstate* state, ae_state *_state) -{ - - - state->prectype = 3; -} - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinBCOptimize(). - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcsetxrep(minbcstate* state, ae_bool needxrep, ae_state *_state) -{ - - - state->xrep = needxrep; -} - - -/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which lead to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcsetstpmax(minbcstate* state, double stpmax, ae_state *_state) -{ - - - ae_assert(ae_isfinite(stpmax, _state), "MinBCSetStpMax: StpMax is not finite!", _state); - ae_assert(ae_fp_greater_eq(stpmax,(double)(0)), "MinBCSetStpMax: StpMax<0!", _state); - state->stpmax = stpmax; -} - - -/************************************************************************* -NOTES: - -1. This function has two different implementations: one which uses exact - (analytical) user-supplied gradient, and one which uses function value - only and numerically differentiates function in order to obtain - gradient. - - Depending on the specific function used to create optimizer object - (either MinBCCreate() for analytical gradient or MinBCCreateF() - for numerical differentiation) you should choose appropriate variant of - MinBCOptimize() - one which accepts function AND gradient or one - which accepts function ONLY. - - Be careful to choose variant of MinBCOptimize() which corresponds to - your optimization scheme! Table below lists different combinations of - callback (function/gradient) passed to MinBCOptimize() and specific - function used to create optimizer. - - - | USER PASSED TO MinBCOptimize() - CREATED WITH | function only | function and gradient - ------------------------------------------------------------ - MinBCCreateF() | works FAILS - MinBCCreate() | FAILS works - - Here "FAIL" denotes inappropriate combinations of optimizer creation - function and MinBCOptimize() version. Attemps to use such - combination (for example, to create optimizer with MinBCCreateF() - and to pass gradient information to MinCGOptimize()) will lead to - exception being thrown. Either you did not pass gradient when it WAS - needed or you passed gradient when it was NOT needed. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -ae_bool minbciteration(minbcstate* state, ae_state *_state) -{ - ae_int_t freezeidx; - double freezeval; - double scaleddnorm; - ae_int_t n; - ae_int_t m; - ae_int_t i; - ae_int_t j; - double v; - double vv; - double v0; - ae_bool b; - ae_int_t mcinfo; - ae_int_t itidx; - double ginit; - double gdecay; - ae_bool activationstatus; - double activationstep; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - freezeidx = state->rstate.ia.ptr.p_int[0]; - n = state->rstate.ia.ptr.p_int[1]; - m = state->rstate.ia.ptr.p_int[2]; - i = state->rstate.ia.ptr.p_int[3]; - j = state->rstate.ia.ptr.p_int[4]; - mcinfo = state->rstate.ia.ptr.p_int[5]; - itidx = state->rstate.ia.ptr.p_int[6]; - b = state->rstate.ba.ptr.p_bool[0]; - activationstatus = state->rstate.ba.ptr.p_bool[1]; - freezeval = state->rstate.ra.ptr.p_double[0]; - scaleddnorm = state->rstate.ra.ptr.p_double[1]; - v = state->rstate.ra.ptr.p_double[2]; - vv = state->rstate.ra.ptr.p_double[3]; - v0 = state->rstate.ra.ptr.p_double[4]; - ginit = state->rstate.ra.ptr.p_double[5]; - gdecay = state->rstate.ra.ptr.p_double[6]; - activationstep = state->rstate.ra.ptr.p_double[7]; - } - else - { - freezeidx = 359; - n = -58; - m = -919; - i = -909; - j = 81; - mcinfo = 255; - itidx = 74; - b = ae_false; - activationstatus = ae_true; - freezeval = 205; - scaleddnorm = -838; - v = 939; - vv = -526; - v0 = 763; - ginit = -541; - gdecay = -698; - activationstep = -900; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - if( state->rstate.stage==1 ) - { - goto lbl_1; - } - if( state->rstate.stage==2 ) - { - goto lbl_2; - } - if( state->rstate.stage==3 ) - { - goto lbl_3; - } - if( state->rstate.stage==4 ) - { - goto lbl_4; - } - if( state->rstate.stage==5 ) - { - goto lbl_5; - } - if( state->rstate.stage==6 ) - { - goto lbl_6; - } - if( state->rstate.stage==7 ) - { - goto lbl_7; - } - if( state->rstate.stage==8 ) - { - goto lbl_8; - } - if( state->rstate.stage==9 ) - { - goto lbl_9; - } - if( state->rstate.stage==10 ) - { - goto lbl_10; - } - if( state->rstate.stage==11 ) - { - goto lbl_11; - } - if( state->rstate.stage==12 ) - { - goto lbl_12; - } - if( state->rstate.stage==13 ) - { - goto lbl_13; - } - if( state->rstate.stage==14 ) - { - goto lbl_14; - } - if( state->rstate.stage==15 ) - { - goto lbl_15; - } - if( state->rstate.stage==16 ) - { - goto lbl_16; - } - if( state->rstate.stage==17 ) - { - goto lbl_17; - } - if( state->rstate.stage==18 ) - { - goto lbl_18; - } - if( state->rstate.stage==19 ) - { - goto lbl_19; - } - if( state->rstate.stage==20 ) - { - goto lbl_20; - } - if( state->rstate.stage==21 ) - { - goto lbl_21; - } - if( state->rstate.stage==22 ) - { - goto lbl_22; - } - if( state->rstate.stage==23 ) - { - goto lbl_23; - } - if( state->rstate.stage==24 ) - { - goto lbl_24; - } - if( state->rstate.stage==25 ) - { - goto lbl_25; - } - if( state->rstate.stage==26 ) - { - goto lbl_26; - } - if( state->rstate.stage==27 ) - { - goto lbl_27; - } - if( state->rstate.stage==28 ) - { - goto lbl_28; - } - if( state->rstate.stage==29 ) - { - goto lbl_29; - } - - /* - * Routine body - */ - - /* - * Algorithm parameters: - * * M number of L-BFGS corrections. - * This coefficient remains fixed during iterations. - * * GDecay desired decrease of constrained gradient during L-BFGS iterations. - * This coefficient is decreased after each L-BFGS round until - * it reaches minimum decay. - */ - m = ae_minint(5, state->nmain, _state); - gdecay = minbc_initialdecay; - - /* - * Init - */ - n = state->nmain; - for(i=0; i<=n-1; i++) - { - state->xc.ptr.p_double[i] = state->xstart.ptr.p_double[i]; - } - if( !enforceboundaryconstraints(&state->xc, &state->bndl, &state->hasbndl, &state->bndu, &state->hasbndu, n, 0, _state) ) - { - - /* - * Inconsistent constraints - */ - state->repterminationtype = -3; - result = ae_false; - return result; - } - state->userterminationneeded = ae_false; - state->repterminationtype = 0; - state->repiterationscount = 0; - state->repnfev = 0; - state->repvaridx = -1; - rmatrixsetlengthatleast(&state->bufyk, m+1, n, _state); - rmatrixsetlengthatleast(&state->bufsk, m+1, n, _state); - rvectorsetlengthatleast(&state->bufrho, m, _state); - rvectorsetlengthatleast(&state->buftheta, m, _state); - rvectorsetlengthatleast(&state->tmp0, n, _state); - smoothnessmonitorinit(&state->smonitor, &state->s, n, 1, state->smoothnessguardlevel>0, _state); - for(i=0; i<=n-1; i++) - { - state->lastscaleused.ptr.p_double[i] = state->s.ptr.p_double[i]; - state->invs.ptr.p_double[i] = 1/state->s.ptr.p_double[i]; - } - - /* - * Fill TmpPrec with current preconditioner - */ - rvectorsetlengthatleast(&state->tmpprec, n, _state); - for(i=0; i<=n-1; i++) - { - if( state->prectype==2 ) - { - state->tmpprec.ptr.p_double[i] = 1/state->diagh.ptr.p_double[i]; - continue; - } - if( state->prectype==3 ) - { - state->tmpprec.ptr.p_double[i] = ae_sqr(state->s.ptr.p_double[i], _state); - continue; - } - state->tmpprec.ptr.p_double[i] = (double)(1); - } - - /* - * Check correctness of user-supplied gradient - */ - minbc_clearrequestfields(state, _state); - if( !(ae_fp_eq(state->diffstep,(double)(0))&&ae_fp_greater(state->teststep,(double)(0))) ) - { - goto lbl_30; - } -lbl_32: - if( !smoothnessmonitorcheckgradientatx0(&state->smonitor, &state->xc, &state->s, &state->bndl, &state->bndu, ae_true, state->teststep, _state) ) - { - goto lbl_33; - } - for(i=0; i<=n-1; i++) - { - state->x.ptr.p_double[i] = state->smonitor.x.ptr.p_double[i]; - } - state->needfg = ae_true; - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - state->needfg = ae_false; - state->smonitor.fi.ptr.p_double[0] = state->f; - for(i=0; i<=n-1; i++) - { - state->smonitor.j.ptr.pp_double[0][i] = state->g.ptr.p_double[i]; - } - goto lbl_32; -lbl_33: -lbl_30: - - /* - * Main cycle of BC-PG algorithm - */ - state->repterminationtype = 0; - state->lastscaledgoodstep = (double)(0); - state->nonmonotoniccnt = ae_round(1.5*n, _state)+5; - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minbc_clearrequestfields(state, _state); - if( ae_fp_neq(state->diffstep,(double)(0)) ) - { - goto lbl_34; - } - state->needfg = ae_true; - state->rstate.stage = 1; - goto lbl_rcomm; -lbl_1: - state->needfg = ae_false; - goto lbl_35; -lbl_34: - state->needf = ae_true; - state->rstate.stage = 2; - goto lbl_rcomm; -lbl_2: - state->needf = ae_false; -lbl_35: - state->fc = state->f; - trimprepare(state->f, &state->trimthreshold, _state); - state->repnfev = state->repnfev+1; - if( !state->xrep ) - { - goto lbl_36; - } - - /* - * Report current point - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->f = state->fc; - state->xupdated = ae_true; - state->rstate.stage = 3; - goto lbl_rcomm; -lbl_3: - state->xupdated = ae_false; -lbl_36: - if( state->userterminationneeded ) - { - - /* - * User requested termination - */ - state->repterminationtype = 8; - result = ae_false; - return result; - } -lbl_38: - if( ae_false ) - { - goto lbl_39; - } - - /* - * Steepest descent phase - * - * (a) calculate unconstrained gradient - * (b) check F/G for NAN/INF, abnormally terminate algorithm if needed - * (c) perform one steepest descent step, activating only those constraints - * which prevent us from moving outside of box-constrained area - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minbc_clearrequestfields(state, _state); - if( ae_fp_neq(state->diffstep,(double)(0)) ) - { - goto lbl_40; - } - - /* - * Analytic gradient - */ - state->needfg = ae_true; - state->rstate.stage = 4; - goto lbl_rcomm; -lbl_4: - state->needfg = ae_false; - goto lbl_41; -lbl_40: - - /* - * Numerical differentiation - */ - state->needf = ae_true; - state->rstate.stage = 5; - goto lbl_rcomm; -lbl_5: - state->fbase = state->f; - i = 0; -lbl_42: - if( i>n-1 ) - { - goto lbl_44; - } - v = state->x.ptr.p_double[i]; - b = ae_false; - if( state->hasbndl.ptr.p_bool[i] ) - { - b = b||ae_fp_less(v-state->diffstep*state->s.ptr.p_double[i],state->bndl.ptr.p_double[i]); - } - if( state->hasbndu.ptr.p_bool[i] ) - { - b = b||ae_fp_greater(v+state->diffstep*state->s.ptr.p_double[i],state->bndu.ptr.p_double[i]); - } - if( b ) - { - goto lbl_45; - } - state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 6; - goto lbl_rcomm; -lbl_6: - state->fm2 = state->f; - state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 7; - goto lbl_rcomm; -lbl_7: - state->fm1 = state->f; - state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 8; - goto lbl_rcomm; -lbl_8: - state->fp1 = state->f; - state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 9; - goto lbl_rcomm; -lbl_9: - state->fp2 = state->f; - state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]); - goto lbl_46; -lbl_45: - state->xm1 = v-state->diffstep*state->s.ptr.p_double[i]; - state->xp1 = v+state->diffstep*state->s.ptr.p_double[i]; - if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(state->xm1,state->bndl.ptr.p_double[i]) ) - { - state->xm1 = state->bndl.ptr.p_double[i]; - } - if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(state->xp1,state->bndu.ptr.p_double[i]) ) - { - state->xp1 = state->bndu.ptr.p_double[i]; - } - state->x.ptr.p_double[i] = state->xm1; - state->rstate.stage = 10; - goto lbl_rcomm; -lbl_10: - state->fm1 = state->f; - state->x.ptr.p_double[i] = state->xp1; - state->rstate.stage = 11; - goto lbl_rcomm; -lbl_11: - state->fp1 = state->f; - if( ae_fp_neq(state->xm1,state->xp1) ) - { - state->g.ptr.p_double[i] = (state->fp1-state->fm1)/(state->xp1-state->xm1); - } - else - { - state->g.ptr.p_double[i] = (double)(0); - } -lbl_46: - state->x.ptr.p_double[i] = v; - i = i+1; - goto lbl_42; -lbl_44: - state->f = state->fbase; - state->needf = ae_false; -lbl_41: - state->fc = state->f; - ae_v_move(&state->ugc.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->cgc.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - projectgradientintobc(&state->xc, &state->cgc, &state->bndl, &state->hasbndl, &state->bndu, &state->hasbndu, n, 0, _state); - ginit = 0.0; - for(i=0; i<=n-1; i++) - { - ginit = ginit+ae_sqr(state->cgc.ptr.p_double[i]*state->s.ptr.p_double[i], _state); - } - ginit = ae_sqrt(ginit, _state); - if( !ae_isfinite(ginit, _state)||!ae_isfinite(state->fc, _state) ) - { - - /* - * Abnormal termination - infinities in function/gradient - */ - state->repterminationtype = -8; - result = ae_false; - return result; - } - if( state->userterminationneeded ) - { - - /* - * User requested termination - */ - state->repterminationtype = 8; - result = ae_false; - return result; - } - if( ae_fp_less_eq(ginit,state->epsg) ) - { - - /* - * Gradient is small enough. - * Optimization is terminated - */ - state->repterminationtype = 4; - result = ae_false; - return result; - } - for(i=0; i<=n-1; i++) - { - state->d.ptr.p_double[i] = -state->tmpprec.ptr.p_double[i]*state->cgc.ptr.p_double[i]; - } - scaleddnorm = (double)(0); - for(i=0; i<=n-1; i++) - { - scaleddnorm = scaleddnorm+ae_sqr(state->d.ptr.p_double[i]/state->s.ptr.p_double[i], _state); - } - scaleddnorm = ae_sqrt(scaleddnorm, _state); - ae_assert(ae_fp_greater(scaleddnorm,(double)(0)), "MinBC: integrity check failed", _state); - if( ae_fp_greater(state->lastscaledgoodstep,(double)(0)) ) - { - state->stp = state->lastscaledgoodstep/scaleddnorm; - } - else - { - state->stp = 1.0/scaleddnorm; - } - calculatestepbound(&state->xc, &state->d, 1.0, &state->bndl, &state->hasbndl, &state->bndu, &state->hasbndu, n, 0, &freezeidx, &freezeval, &state->curstpmax, _state); - activationstep = state->curstpmax; - if( freezeidx<0||ae_fp_greater(state->curstpmax,1.0E50) ) - { - state->curstpmax = 1.0E50; - } - if( ae_fp_greater(state->stpmax,(double)(0)) ) - { - state->curstpmax = ae_minreal(state->curstpmax, state->stpmax/scaleddnorm, _state); - } - ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->cgn.ptr.p_double[0], 1, &state->cgc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->ugn.ptr.p_double[0], 1, &state->ugc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->fn = state->fc; - state->mcstage = 0; - smoothnessmonitorstartlinesearch1u(&state->smonitor, &state->s, &state->invs, &state->xn, state->fn, &state->ugn, _state); - mcsrch(n, &state->xn, &state->fn, &state->cgn, &state->d, &state->stp, state->curstpmax, minbc_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state); -lbl_47: - if( state->mcstage==0 ) - { - goto lbl_48; - } - - /* - * Copy XN to X, perform on-the-fly correction w.r.t box - * constraints (projection onto feasible set). - */ - for(i=0; i<=n-1; i++) - { - state->x.ptr.p_double[i] = state->xn.ptr.p_double[i]; - if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(state->xn.ptr.p_double[i],state->bndl.ptr.p_double[i]) ) - { - state->x.ptr.p_double[i] = state->bndl.ptr.p_double[i]; - } - if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(state->xn.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->x.ptr.p_double[i] = state->bndu.ptr.p_double[i]; - } - } - - /* - * Gradient, either user-provided or numerical differentiation - */ - minbc_clearrequestfields(state, _state); - if( ae_fp_neq(state->diffstep,(double)(0)) ) - { - goto lbl_49; - } - - /* - * Analytic gradient - */ - state->needfg = ae_true; - state->rstate.stage = 12; - goto lbl_rcomm; -lbl_12: - state->needfg = ae_false; - state->repnfev = state->repnfev+1; - goto lbl_50; -lbl_49: - - /* - * Numerical differentiation - */ - state->needf = ae_true; - state->rstate.stage = 13; - goto lbl_rcomm; -lbl_13: - state->fbase = state->f; - i = 0; -lbl_51: - if( i>n-1 ) - { - goto lbl_53; - } - v = state->x.ptr.p_double[i]; - b = ae_false; - if( state->hasbndl.ptr.p_bool[i] ) - { - b = b||ae_fp_less(v-state->diffstep*state->s.ptr.p_double[i],state->bndl.ptr.p_double[i]); - } - if( state->hasbndu.ptr.p_bool[i] ) - { - b = b||ae_fp_greater(v+state->diffstep*state->s.ptr.p_double[i],state->bndu.ptr.p_double[i]); - } - if( b ) - { - goto lbl_54; - } - state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 14; - goto lbl_rcomm; -lbl_14: - state->fm2 = state->f; - state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 15; - goto lbl_rcomm; -lbl_15: - state->fm1 = state->f; - state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 16; - goto lbl_rcomm; -lbl_16: - state->fp1 = state->f; - state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 17; - goto lbl_rcomm; -lbl_17: - state->fp2 = state->f; - state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]); - state->repnfev = state->repnfev+4; - goto lbl_55; -lbl_54: - state->xm1 = v-state->diffstep*state->s.ptr.p_double[i]; - state->xp1 = v+state->diffstep*state->s.ptr.p_double[i]; - if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(state->xm1,state->bndl.ptr.p_double[i]) ) - { - state->xm1 = state->bndl.ptr.p_double[i]; - } - if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(state->xp1,state->bndu.ptr.p_double[i]) ) - { - state->xp1 = state->bndu.ptr.p_double[i]; - } - state->x.ptr.p_double[i] = state->xm1; - state->rstate.stage = 18; - goto lbl_rcomm; -lbl_18: - state->fm1 = state->f; - state->x.ptr.p_double[i] = state->xp1; - state->rstate.stage = 19; - goto lbl_rcomm; -lbl_19: - state->fp1 = state->f; - if( ae_fp_neq(state->xm1,state->xp1) ) - { - state->g.ptr.p_double[i] = (state->fp1-state->fm1)/(state->xp1-state->xm1); - } - else - { - state->g.ptr.p_double[i] = (double)(0); - } - state->repnfev = state->repnfev+2; -lbl_55: - state->x.ptr.p_double[i] = v; - i = i+1; - goto lbl_51; -lbl_53: - state->f = state->fbase; - state->needf = ae_false; -lbl_50: - - /* - * Back to MCSRCH - */ - smoothnessmonitorenqueuepoint1u(&state->smonitor, &state->s, &state->invs, &state->d, state->stp, &state->x, state->f, &state->g, _state); - trimfunction(&state->f, &state->g, n, state->trimthreshold, _state); - state->fn = state->f; - ae_v_move(&state->cgn.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->ugn.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - if( ae_fp_eq(state->d.ptr.p_double[i],(double)(0)) ) - { - state->cgn.ptr.p_double[i] = (double)(0); - } - } - mcsrch(n, &state->xn, &state->fn, &state->cgn, &state->d, &state->stp, state->curstpmax, minbc_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state); - goto lbl_47; -lbl_48: - smoothnessmonitorfinalizelinesearch(&state->smonitor, _state); - v = state->fn; - for(i=0; i<=n-1; i++) - { - v = 0.1*v+state->ugn.ptr.p_double[i]; - } - if( !ae_isfinite(v, _state) ) - { - - /* - * Abnormal termination - infinities in function/gradient - */ - state->repterminationtype = -8; - result = ae_false; - return result; - } - if( mcinfo!=1&&mcinfo!=5 ) - { - - /* - * We can not find step which decreases function value. We have - * two possibilities: - * (a) numerical properties of the function do not allow us to - * find good step. - * (b) we are close to activation of some constraint, and it is - * so close that step which activates it leads to change in - * target function which is smaller than numerical noise. - * - * Optimization algorithm must be able to handle case (b), because - * inability to handle it will cause failure when algorithm - * started very close to boundary of the feasible area. - * - * In order to correctly handle such cases we allow limited amount - * of small steps which increase function value. - */ - if( (freezeidx>=0&&ae_fp_less_eq(scaleddnorm*state->curstpmax,minbc_maxnonmonotoniclen))&&state->nonmonotoniccnt>0 ) - { - - /* - * We enforce non-monotonic step: - * * Stp := CurStpMax - * * MCINFO := 5 - * * XN := XC+CurStpMax*D - * * non-monotonic counter is decreased - * - * NOTE: UGN/CGN are not updated because step is so short that we assume that - * GN is approximately equal to GC. - */ - state->stp = state->curstpmax; - mcinfo = 5; - v = state->curstpmax; - ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_addd(&state->xn.ptr.p_double[0], 1, &state->d.ptr.p_double[0], 1, ae_v_len(0,n-1), v); - state->nonmonotoniccnt = state->nonmonotoniccnt-1; - } - else - { - - /* - * Numerical properties of the function does not allow - * us to solve problem. Algorithm is terminated - */ - state->repterminationtype = 7; - result = ae_false; - return result; - } - } - if( state->userterminationneeded ) - { - - /* - * User requested termination - */ - state->repterminationtype = 8; - result = ae_false; - return result; - } - ae_assert(mcinfo!=5||ae_fp_eq(state->stp,state->curstpmax), "MinBC: integrity check failed", _state); - postprocessboundedstep(&state->xn, &state->xc, &state->bndl, &state->hasbndl, &state->bndu, &state->hasbndu, n, 0, freezeidx, freezeval, state->stp, activationstep, _state); - state->fp = state->fc; - state->fc = state->fn; - ae_v_move(&state->xp.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->xc.ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->cgc.ptr.p_double[0], 1, &state->cgn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->ugc.ptr.p_double[0], 1, &state->ugn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( !state->xrep ) - { - goto lbl_56; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minbc_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 20; - goto lbl_rcomm; -lbl_20: - state->xupdated = ae_false; -lbl_56: - state->repiterationscount = state->repiterationscount+1; - if( mcinfo==1 ) - { - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr((state->xc.ptr.p_double[i]-state->xp.ptr.p_double[i])/state->s.ptr.p_double[i], _state); - } - v = ae_sqrt(v, _state); - if( ae_fp_less_eq(v,state->epsx) ) - { - - /* - * Step is small enough - */ - state->repterminationtype = 2; - result = ae_false; - return result; - } - if( ae_fp_less_eq(ae_fabs(state->fp-state->fc, _state),state->epsf*ae_maxreal(ae_fabs(state->fc, _state), ae_maxreal(ae_fabs(state->fp, _state), 1.0, _state), _state)) ) - { - - /* - * Function change is small enough - */ - state->repterminationtype = 1; - result = ae_false; - return result; - } - } - if( state->maxits>0&&state->repiterationscount>=state->maxits ) - { - - /* - * Iteration counter exceeded limit - */ - state->repterminationtype = 5; - result = ae_false; - return result; - } - - /* - * LBFGS stage: - * * during LBFGS iterations we activate new constraints, but never - * deactivate already active ones. - * * we perform at most N iterations of LBFGS before re-evaluating - * active set and restarting LBFGS. - * - * About termination: - * * LBFGS iterations can be terminated because of two reasons: - * * "termination" - non-zero termination code in RepTerminationType, - * which means that optimization is done - * * "restart" - zero RepTerminationType, which means that we - * have to re-evaluate active set and resume LBFGS stage. - * * one more option is "refresh" - to continue LBFGS iterations, - * but with all BFGS updates (Sk/Yk pairs) being dropped; - * it happens after changes in active set - */ - ginit = 0.0; - for(i=0; i<=n-1; i++) - { - state->cgc.ptr.p_double[i] = state->ugc.ptr.p_double[i]; - if( state->hasbndl.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]) ) - { - state->cgc.ptr.p_double[i] = (double)(0); - } - if( state->hasbndu.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->cgc.ptr.p_double[i] = (double)(0); - } - ginit = ginit+ae_sqr(state->cgc.ptr.p_double[i]*state->s.ptr.p_double[i], _state); - } - ginit = ae_sqrt(ginit, _state); - state->bufsize = 0; - itidx = 0; -lbl_58: - if( itidx>n-1 ) - { - goto lbl_60; - } - - /* - * At the beginning of each iteration: - * * XC stores current point - * * FC stores current function value - * * UGC stores current unconstrained gradient - * * CGC stores current constrained gradient - * * D stores constrained step direction (calculated at this block) - * - * 1. Calculate search direction D according to L-BFGS algorithm - * using constrained preconditioner to perform inner multiplication. - * 2. Evaluate scaled length of direction D; restart LBFGS if D is zero - * (it may be possible that we found minimum, but it is also possible - * that some constraints need deactivation) - * 3. If D is non-zero, try to use previous scaled step length as initial estimate for new step. - * 4. Calculate bound on step length. - */ - ae_v_move(&state->work.ptr.p_double[0], 1, &state->cgc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=state->bufsize-1; i>=0; i--) - { - v = ae_v_dotproduct(&state->bufsk.ptr.pp_double[i][0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->buftheta.ptr.p_double[i] = v; - vv = v*state->bufrho.ptr.p_double[i]; - ae_v_subd(&state->work.ptr.p_double[0], 1, &state->bufyk.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), vv); - } - for(i=0; i<=n-1; i++) - { - state->work.ptr.p_double[i] = state->tmpprec.ptr.p_double[i]*state->work.ptr.p_double[i]; - } - for(i=0; i<=state->bufsize-1; i++) - { - v = ae_v_dotproduct(&state->bufyk.ptr.pp_double[i][0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1)); - vv = state->bufrho.ptr.p_double[i]*(-v+state->buftheta.ptr.p_double[i]); - ae_v_addd(&state->work.ptr.p_double[0], 1, &state->bufsk.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), vv); - } - ae_v_moveneg(&state->d.ptr.p_double[0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1)); - b = ae_false; - for(i=0; i<=n-1; i++) - { - b = b||((state->hasbndl.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]))&&ae_fp_neq(state->d.ptr.p_double[i],(double)(0))); - b = b||((state->hasbndu.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]))&&ae_fp_neq(state->d.ptr.p_double[i],(double)(0))); - } - ae_assert(!b, "MinBC: integrity check failed (q)", _state); - scaleddnorm = (double)(0); - for(i=0; i<=n-1; i++) - { - scaleddnorm = scaleddnorm+ae_sqr(state->d.ptr.p_double[i]/state->s.ptr.p_double[i], _state); - } - scaleddnorm = ae_sqrt(scaleddnorm, _state); - if( ae_fp_eq(scaleddnorm,(double)(0)) ) - { - - /* - * Search direction is zero. - * Skip back to steepest descent phase. - */ - goto lbl_60; - } - if( ae_fp_greater(state->lastscaledgoodstep,(double)(0)) ) - { - state->stp = state->lastscaledgoodstep/scaleddnorm; - } - else - { - state->stp = 1.0/scaleddnorm; - } - state->curstpmax = 1.0E50; - if( ae_fp_greater(state->stpmax,(double)(0)) ) - { - state->curstpmax = ae_minreal(state->curstpmax, state->stpmax/scaleddnorm, _state); - } - - /* - * Minimize G(t) = F(CONSTRAIN(XC + t*D)), with t being scalar, XC and D being vectors. - */ - ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->cgn.ptr.p_double[0], 1, &state->cgc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->ugn.ptr.p_double[0], 1, &state->ugc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->fn = state->fc; - state->mcstage = 0; - smoothnessmonitorstartlinesearch1u(&state->smonitor, &state->s, &state->invs, &state->xn, state->fn, &state->ugn, _state); - mcsrch(n, &state->xn, &state->fn, &state->cgn, &state->d, &state->stp, state->curstpmax, minbc_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state); -lbl_61: - if( state->mcstage==0 ) - { - goto lbl_62; - } - - /* - * Copy XN to X, perform on-the-fly correction w.r.t box - * constraints (projection onto feasible set). - */ - for(i=0; i<=n-1; i++) - { - state->x.ptr.p_double[i] = state->xn.ptr.p_double[i]; - if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(state->xn.ptr.p_double[i],state->bndl.ptr.p_double[i]) ) - { - state->x.ptr.p_double[i] = state->bndl.ptr.p_double[i]; - } - if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(state->xn.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->x.ptr.p_double[i] = state->bndu.ptr.p_double[i]; - } - } - - /* - * Gradient, either user-provided or numerical differentiation - */ - minbc_clearrequestfields(state, _state); - if( ae_fp_neq(state->diffstep,(double)(0)) ) - { - goto lbl_63; - } - - /* - * Analytic gradient - */ - state->needfg = ae_true; - state->rstate.stage = 21; - goto lbl_rcomm; -lbl_21: - state->needfg = ae_false; - state->repnfev = state->repnfev+1; - goto lbl_64; -lbl_63: - - /* - * Numerical differentiation - */ - state->needf = ae_true; - state->rstate.stage = 22; - goto lbl_rcomm; -lbl_22: - state->fbase = state->f; - i = 0; -lbl_65: - if( i>n-1 ) - { - goto lbl_67; - } - v = state->x.ptr.p_double[i]; - b = ae_false; - if( state->hasbndl.ptr.p_bool[i] ) - { - b = b||ae_fp_less(v-state->diffstep*state->s.ptr.p_double[i],state->bndl.ptr.p_double[i]); - } - if( state->hasbndu.ptr.p_bool[i] ) - { - b = b||ae_fp_greater(v+state->diffstep*state->s.ptr.p_double[i],state->bndu.ptr.p_double[i]); - } - if( b ) - { - goto lbl_68; - } - state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 23; - goto lbl_rcomm; -lbl_23: - state->fm2 = state->f; - state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 24; - goto lbl_rcomm; -lbl_24: - state->fm1 = state->f; - state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 25; - goto lbl_rcomm; -lbl_25: - state->fp1 = state->f; - state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 26; - goto lbl_rcomm; -lbl_26: - state->fp2 = state->f; - state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]); - state->repnfev = state->repnfev+4; - goto lbl_69; -lbl_68: - state->xm1 = v-state->diffstep*state->s.ptr.p_double[i]; - state->xp1 = v+state->diffstep*state->s.ptr.p_double[i]; - if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(state->xm1,state->bndl.ptr.p_double[i]) ) - { - state->xm1 = state->bndl.ptr.p_double[i]; - } - if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(state->xp1,state->bndu.ptr.p_double[i]) ) - { - state->xp1 = state->bndu.ptr.p_double[i]; - } - state->x.ptr.p_double[i] = state->xm1; - state->rstate.stage = 27; - goto lbl_rcomm; -lbl_27: - state->fm1 = state->f; - state->x.ptr.p_double[i] = state->xp1; - state->rstate.stage = 28; - goto lbl_rcomm; -lbl_28: - state->fp1 = state->f; - if( ae_fp_neq(state->xm1,state->xp1) ) - { - state->g.ptr.p_double[i] = (state->fp1-state->fm1)/(state->xp1-state->xm1); - } - else - { - state->g.ptr.p_double[i] = (double)(0); - } - state->repnfev = state->repnfev+2; -lbl_69: - state->x.ptr.p_double[i] = v; - i = i+1; - goto lbl_65; -lbl_67: - state->f = state->fbase; - state->needf = ae_false; -lbl_64: - - /* - * Back to MCSRCH - */ - smoothnessmonitorenqueuepoint1u(&state->smonitor, &state->s, &state->invs, &state->d, state->stp, &state->x, state->f, &state->g, _state); - trimfunction(&state->f, &state->g, n, state->trimthreshold, _state); - state->fn = state->f; - for(i=0; i<=n-1; i++) - { - state->ugn.ptr.p_double[i] = state->g.ptr.p_double[i]; - state->cgn.ptr.p_double[i] = state->g.ptr.p_double[i]; - if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(state->xn.ptr.p_double[i],state->bndl.ptr.p_double[i]) ) - { - state->cgn.ptr.p_double[i] = (double)(0); - } - if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(state->xn.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->cgn.ptr.p_double[i] = (double)(0); - } - } - mcsrch(n, &state->xn, &state->fn, &state->cgn, &state->d, &state->stp, state->curstpmax, minbc_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state); - goto lbl_61; -lbl_62: - smoothnessmonitorfinalizelinesearch(&state->smonitor, _state); - for(i=0; i<=n-1; i++) - { - if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(state->xn.ptr.p_double[i],state->bndl.ptr.p_double[i]) ) - { - state->xn.ptr.p_double[i] = state->bndl.ptr.p_double[i]; - } - if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(state->xn.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->xn.ptr.p_double[i] = state->bndu.ptr.p_double[i]; - } - } - ae_v_moveneg(&state->bufsk.ptr.pp_double[state->bufsize][0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_moveneg(&state->bufyk.ptr.pp_double[state->bufsize][0], 1, &state->cgc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_add(&state->bufsk.ptr.pp_double[state->bufsize][0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_add(&state->bufyk.ptr.pp_double[state->bufsize][0], 1, &state->cgn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - - /* - * Handle special situations: - * * check for presence of NAN/INF in function/gradient - * * handle failure of line search - */ - v = state->fn; - for(i=0; i<=n-1; i++) - { - v = 0.1*v+state->ugn.ptr.p_double[i]; - } - if( !ae_isfinite(v, _state) ) - { - - /* - * Abnormal termination - infinities in function/gradient - */ - state->repterminationtype = -8; - result = ae_false; - return result; - } - if( state->userterminationneeded ) - { - - /* - * User requested termination - */ - state->repterminationtype = 8; - result = ae_false; - return result; - } - if( mcinfo!=1 ) - { - - /* - * Terminate LBFGS phase - */ - goto lbl_60; - } - - /* - * Current point is updated: - * * move XC/FC/GC to XP/FP/GP - * * move XN/FN/GN to XC/FC/GC - * * report current point and update iterations counter - * * push new pair SK/YK to LBFGS buffer - * * update length of the good step - */ - activationstatus = ae_false; - for(i=0; i<=n-1; i++) - { - if( (state->hasbndl.ptr.p_bool[i]&&ae_fp_eq(state->xn.ptr.p_double[i],state->bndl.ptr.p_double[i]))&&ae_fp_neq(state->xn.ptr.p_double[i],state->xc.ptr.p_double[i]) ) - { - activationstatus = ae_true; - } - if( (state->hasbndu.ptr.p_bool[i]&&ae_fp_eq(state->xn.ptr.p_double[i],state->bndu.ptr.p_double[i]))&&ae_fp_neq(state->xn.ptr.p_double[i],state->xc.ptr.p_double[i]) ) - { - activationstatus = ae_true; - } - } - state->fp = state->fc; - state->fc = state->fn; - ae_v_move(&state->xp.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->xc.ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->cgc.ptr.p_double[0], 1, &state->cgn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->ugc.ptr.p_double[0], 1, &state->ugn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( !state->xrep ) - { - goto lbl_70; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minbc_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 29; - goto lbl_rcomm; -lbl_29: - state->xupdated = ae_false; -lbl_70: - state->repiterationscount = state->repiterationscount+1; - if( state->bufsize==m ) - { - - /* - * Buffer is full, shift contents by one row - */ - for(i=0; i<=state->bufsize-1; i++) - { - ae_v_move(&state->bufsk.ptr.pp_double[i][0], 1, &state->bufsk.ptr.pp_double[i+1][0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->bufyk.ptr.pp_double[i][0], 1, &state->bufyk.ptr.pp_double[i+1][0], 1, ae_v_len(0,n-1)); - } - for(i=0; i<=state->bufsize-2; i++) - { - state->bufrho.ptr.p_double[i] = state->bufrho.ptr.p_double[i+1]; - state->buftheta.ptr.p_double[i] = state->buftheta.ptr.p_double[i+1]; - } - } - else - { - - /* - * Buffer is not full, increase buffer size by 1 - */ - state->bufsize = state->bufsize+1; - } - v = ae_v_dotproduct(&state->bufyk.ptr.pp_double[state->bufsize-1][0], 1, &state->bufsk.ptr.pp_double[state->bufsize-1][0], 1, ae_v_len(0,n-1)); - vv = ae_v_dotproduct(&state->bufyk.ptr.pp_double[state->bufsize-1][0], 1, &state->bufyk.ptr.pp_double[state->bufsize-1][0], 1, ae_v_len(0,n-1)); - if( ae_fp_eq(v,(double)(0))||ae_fp_eq(vv,(double)(0)) ) - { - - /* - * Strange internal error in LBFGS - either YK=0 - * (which should not have been) or (SK,YK)=0 (again, - * unexpected). It should not take place because - * MCINFO=1, which signals "good" step. But just - * to be sure we have special branch of code which - * restarts LBFGS - */ - goto lbl_60; - } - state->bufrho.ptr.p_double[state->bufsize-1] = 1/v; - ae_assert(state->bufsize<=m, "MinBC: internal error", _state); - v = (double)(0); - vv = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr((state->xc.ptr.p_double[i]-state->xp.ptr.p_double[i])/state->s.ptr.p_double[i], _state); - vv = vv+ae_sqr(state->xc.ptr.p_double[i]-state->xp.ptr.p_double[i], _state); - } - minbc_updateestimateofgoodstep(&state->lastscaledgoodstep, ae_sqrt(v, _state), _state); - - /* - * Check MaxIts-based stopping condition. - */ - if( state->maxits>0&&state->repiterationscount>=state->maxits ) - { - state->repterminationtype = 5; - result = ae_false; - return result; - } - - /* - * Smooth reset (LBFGS memory model is refreshed) or hard restart: - * * LBFGS model is refreshed, if line search was performed with activation of constraints - * * algorithm is restarted if scaled gradient decreased below GDecay - */ - if( activationstatus ) - { - state->bufsize = 0; - goto lbl_59; - } - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(state->cgc.ptr.p_double[i]*state->s.ptr.p_double[i], _state); - } - if( ae_fp_less(ae_sqrt(v, _state),gdecay*ginit) ) - { - goto lbl_60; - } -lbl_59: - itidx = itidx+1; - goto lbl_58; -lbl_60: - - /* - * Decrease decay coefficient. Subsequent L-BFGS stages will - * have more stringent stopping criteria. - */ - gdecay = ae_maxreal(gdecay*minbc_decaycorrection, minbc_mindecay, _state); - goto lbl_38; -lbl_39: - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = freezeidx; - state->rstate.ia.ptr.p_int[1] = n; - state->rstate.ia.ptr.p_int[2] = m; - state->rstate.ia.ptr.p_int[3] = i; - state->rstate.ia.ptr.p_int[4] = j; - state->rstate.ia.ptr.p_int[5] = mcinfo; - state->rstate.ia.ptr.p_int[6] = itidx; - state->rstate.ba.ptr.p_bool[0] = b; - state->rstate.ba.ptr.p_bool[1] = activationstatus; - state->rstate.ra.ptr.p_double[0] = freezeval; - state->rstate.ra.ptr.p_double[1] = scaleddnorm; - state->rstate.ra.ptr.p_double[2] = v; - state->rstate.ra.ptr.p_double[3] = vv; - state->rstate.ra.ptr.p_double[4] = v0; - state->rstate.ra.ptr.p_double[5] = ginit; - state->rstate.ra.ptr.p_double[6] = gdecay; - state->rstate.ra.ptr.p_double[7] = activationstep; - return result; -} - - -/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic gradient. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function at the initial point -(note: future versions may also perform check at the final point) and -compares numerical gradient with analytic one provided by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both gradients and specific components highlighted as -suspicious by the OptGuard. - -The primary OptGuard report can be retrieved with minbcoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with minbcsetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minbcoptguardgradient(minbcstate* state, - double teststep, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(teststep, _state), "MinBCOptGuardGradient: TestStep contains NaN or INF", _state); - ae_assert(ae_fp_greater_eq(teststep,(double)(0)), "MinBCOptGuardGradient: invalid argument TestStep(TestStep<0)", _state); - state->teststep = teststep; -} - - -/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) -b) nonsmooth target function (non-C1) - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbcoptguardsmoothness(minbcstate* state, - ae_int_t level, - ae_state *_state) -{ - - - ae_assert(level==0||level==1, "MinBCOptGuardSmoothness: unexpected value of level parameter", _state); - state->smoothnessguardlevel = level; -} - - -/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -=== PRIMARY REPORT ======================================================= - -OptGuard performs several checks which are intended to catch common errors -in the implementation of nonlinear function/gradient: -* incorrect analytic gradient -* discontinuous (non-C0) target functions (constraints) -* nonsmooth (non-C1) target functions (constraints) - -Each of these checks is activated with appropriate function: -* minbcoptguardgradient() for gradient verification -* minbcoptguardsmoothness() for C0/C1 checks - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradvidx for specific variable (gradient element) suspected - * rep.badgradxbase, a point where gradient is tested - * rep.badgraduser, user-provided gradient (stored as 2D matrix with - single row in order to make report structure compatible with more - complex optimizers like MinNLC or MinLM) - * rep.badgradnum, reference gradient obtained via numerical - differentiation (stored as 2D matrix with single row in order to make - report structure compatible with more complex optimizers like MinNLC - or MinLM) -* rep.nonc0suspected -* rep.nonc1suspected - -=== ADDITIONAL REPORTS/LOGS ============================================== - -Several different tests are performed to catch C0/C1 errors, you can find -out specific test signaled error by looking to: -* rep.nonc0test0positive, for non-C0 test #0 -* rep.nonc1test0positive, for non-C1 test #0 -* rep.nonc1test1positive, for non-C1 test #1 - -Additional information (including line search logs) can be obtained by -means of: -* minbcoptguardnonc1test0results() -* minbcoptguardnonc1test1results() -which return detailed error reports, specific points where discontinuities -were found, and so on. - -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - generic OptGuard report; more detailed reports can be - retrieved with other functions. - -NOTE: false negatives (nonsmooth problems are not identified as nonsmooth - ones) are possible although unlikely. - - The reason is that you need to make several evaluations around - nonsmoothness in order to accumulate enough information about - function curvature. Say, if you start right from the nonsmooth point, - optimizer simply won't get enough data to understand what is going - wrong before it terminates due to abrupt changes in the derivative. - It is also possible that "unlucky" step will move us to the - termination too quickly. - - Our current approach is to have less than 0.1% false negatives in - our test examples (measured with multiple restarts from random - points), and to have exactly 0% false positives. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbcoptguardresults(minbcstate* state, - optguardreport* rep, - ae_state *_state) -{ - - _optguardreport_clear(rep); - - smoothnessmonitorexportreport(&state->smonitor, rep, _state); -} - - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #0 - -Nonsmoothness (non-C1) test #0 studies function values (not gradient!) -obtained during line searches and monitors behavior of the directional -derivative estimate. - -This test is less powerful than test #1, but it does not depend on the -gradient values and thus it is more robust against artifacts introduced by -numerical differentiation. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #0 "strong" report - lngrep - C1 test #0 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbcoptguardnonc1test0results(minbcstate* state, - optguardnonc1test0report* strrep, - optguardnonc1test0report* lngrep, - ae_state *_state) -{ - - _optguardnonc1test0report_clear(strrep); - _optguardnonc1test0report_clear(lngrep); - - smoothnessmonitorexportc1test0report(&state->smonitor.nonc1test0strrep, &state->lastscaleused, strrep, _state); - smoothnessmonitorexportc1test0report(&state->smonitor.nonc1test0lngrep, &state->lastscaleused, lngrep, _state); -} - - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #1 - -Nonsmoothness (non-C1) test #1 studies individual components of the -gradient computed during line search. - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #1 "strong" report - lngrep - C1 test #1 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbcoptguardnonc1test1results(minbcstate* state, - optguardnonc1test1report* strrep, - optguardnonc1test1report* lngrep, - ae_state *_state) -{ - - _optguardnonc1test1report_clear(strrep); - _optguardnonc1test1report_clear(lngrep); - - smoothnessmonitorexportc1test1report(&state->smonitor.nonc1test1strrep, &state->lastscaleused, strrep, _state); - smoothnessmonitorexportc1test1report(&state->smonitor.nonc1test1lngrep, &state->lastscaleused, lngrep, _state); -} - - -/************************************************************************* -BC results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report. You should check Rep.TerminationType - in order to distinguish successful termination from - unsuccessful one: - * -8 internal integrity control detected infinite or - NAN values in function/gradient. Abnormal - termination signalled. - * -3 inconsistent constraints. - * 1 relative function improvement is no more than EpsF. - * 2 scaled step is no more than EpsX. - * 4 scaled gradient norm is no more than EpsG. - * 5 MaxIts steps was taken - * 8 terminated by user who called minbcrequesttermination(). - X contains point which was "current accepted" when - termination request was submitted. - More information about fields of this structure can be - found in the comments on MinBCReport datatype. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcresults(minbcstate* state, - /* Real */ ae_vector* x, - minbcreport* rep, - ae_state *_state) -{ - - ae_vector_clear(x); - _minbcreport_clear(rep); - - minbcresultsbuf(state, x, rep, _state); -} - - -/************************************************************************* -BC results - -Buffered implementation of MinBCResults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcresultsbuf(minbcstate* state, - /* Real */ ae_vector* x, - minbcreport* rep, - ae_state *_state) -{ - ae_int_t i; - - - if( x->cntnmain ) - { - ae_vector_set_length(x, state->nmain, _state); - } - rep->iterationscount = state->repiterationscount; - rep->nfev = state->repnfev; - rep->varidx = state->repvaridx; - rep->terminationtype = state->repterminationtype; - if( state->repterminationtype>0 ) - { - ae_v_move(&x->ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,state->nmain-1)); - } - else - { - for(i=0; i<=state->nmain-1; i++) - { - x->ptr.p_double[i] = _state->v_nan; - } - } -} - - -/************************************************************************* -This subroutine restarts algorithm from new point. -All optimization parameters (including constraints) are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure previously allocated with MinBCCreate call. - X - new starting point. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcrestartfrom(minbcstate* state, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t n; - - - n = state->nmain; - - /* - * First, check for errors in the inputs - */ - ae_assert(x->cnt>=n, "MinBCRestartFrom: Length(X)xstart.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - - /* - * prepare RComm facilities - */ - ae_vector_set_length(&state->rstate.ia, 6+1, _state); - ae_vector_set_length(&state->rstate.ba, 1+1, _state); - ae_vector_set_length(&state->rstate.ra, 7+1, _state); - state->rstate.stage = -1; - minbc_clearrequestfields(state, _state); -} - - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void minbcrequesttermination(minbcstate* state, ae_state *_state) -{ - - - state->userterminationneeded = ae_true; -} - - -/************************************************************************* -Clears request fileds (to be sure that we don't forget to clear something) -*************************************************************************/ -static void minbc_clearrequestfields(minbcstate* state, ae_state *_state) -{ - - - state->needf = ae_false; - state->needfg = ae_false; - state->xupdated = ae_false; -} - - -/************************************************************************* -Internal initialization subroutine. -*************************************************************************/ -static void minbc_minbcinitinternal(ae_int_t n, - /* Real */ ae_vector* x, - double diffstep, - minbcstate* state, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_matrix c; - ae_vector ct; - - ae_frame_make(_state, &_frame_block); - memset(&c, 0, sizeof(c)); - memset(&ct, 0, sizeof(ct)); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - - - /* - * Initialize - */ - state->teststep = (double)(0); - state->smoothnessguardlevel = 0; - smoothnessmonitorinit(&state->smonitor, &state->s, 0, 0, ae_false, _state); - state->nmain = n; - state->diffstep = diffstep; - rvectorsetlengthatleast(&state->bndl, n, _state); - bvectorsetlengthatleast(&state->hasbndl, n, _state); - rvectorsetlengthatleast(&state->bndu, n, _state); - bvectorsetlengthatleast(&state->hasbndu, n, _state); - rvectorsetlengthatleast(&state->xstart, n, _state); - rvectorsetlengthatleast(&state->xc, n, _state); - rvectorsetlengthatleast(&state->cgc, n, _state); - rvectorsetlengthatleast(&state->ugc, n, _state); - rvectorsetlengthatleast(&state->xn, n, _state); - rvectorsetlengthatleast(&state->cgn, n, _state); - rvectorsetlengthatleast(&state->ugn, n, _state); - rvectorsetlengthatleast(&state->xp, n, _state); - rvectorsetlengthatleast(&state->d, n, _state); - rvectorsetlengthatleast(&state->s, n, _state); - rvectorsetlengthatleast(&state->invs, n, _state); - rvectorsetlengthatleast(&state->lastscaleused, n, _state); - rvectorsetlengthatleast(&state->x, n, _state); - rvectorsetlengthatleast(&state->g, n, _state); - rvectorsetlengthatleast(&state->work, n, _state); - for(i=0; i<=n-1; i++) - { - state->bndl.ptr.p_double[i] = _state->v_neginf; - state->hasbndl.ptr.p_bool[i] = ae_false; - state->bndu.ptr.p_double[i] = _state->v_posinf; - state->hasbndu.ptr.p_bool[i] = ae_false; - state->s.ptr.p_double[i] = 1.0; - state->invs.ptr.p_double[i] = 1.0; - state->lastscaleused.ptr.p_double[i] = 1.0; - } - minbcsetcond(state, 0.0, 0.0, 0.0, 0, _state); - minbcsetxrep(state, ae_false, _state); - minbcsetstpmax(state, 0.0, _state); - minbcsetprecdefault(state, _state); - minbcrestartfrom(state, x, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This subroutine updates estimate of the good step length given: -1) previous estimate -2) new length of the good step - -It makes sure that estimate does not change too rapidly - ratio of new and -old estimates will be at least 0.01, at most 100.0 - -In case previous estimate of good step is zero (no estimate), new estimate -is used unconditionally. - - -- ALGLIB -- - Copyright 16.01.2013 by Bochkanov Sergey -*************************************************************************/ -static void minbc_updateestimateofgoodstep(double* estimate, - double newstep, - ae_state *_state) -{ - - - if( ae_fp_eq(*estimate,(double)(0)) ) - { - *estimate = newstep; - return; - } - if( ae_fp_less(newstep,*estimate*0.01) ) - { - *estimate = *estimate*0.01; - return; - } - if( ae_fp_greater(newstep,*estimate*100) ) - { - *estimate = *estimate*100; - return; - } - *estimate = newstep; -} - - -void _minbcstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minbcstate *p = (minbcstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->diagh, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); - ae_vector_init(&p->xc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ugc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cgc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xn, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ugn, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cgn, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xp, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->hasbndl, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->hasbndu, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xstart, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpprec, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->work, 0, DT_REAL, _state, make_automatic); - _linminstate_init(&p->lstate, _state, make_automatic); - ae_matrix_init(&p->bufyk, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->bufsk, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bufrho, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->buftheta, 0, DT_REAL, _state, make_automatic); - _smoothnessmonitor_init(&p->smonitor, _state, make_automatic); - ae_vector_init(&p->lastscaleused, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->invs, 0, DT_REAL, _state, make_automatic); -} - - -void _minbcstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minbcstate *dst = (minbcstate*)_dst; - minbcstate *src = (minbcstate*)_src; - dst->nmain = src->nmain; - dst->epsg = src->epsg; - dst->epsf = src->epsf; - dst->epsx = src->epsx; - dst->maxits = src->maxits; - dst->xrep = src->xrep; - dst->stpmax = src->stpmax; - dst->diffstep = src->diffstep; - ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic); - dst->prectype = src->prectype; - ae_vector_init_copy(&dst->diagh, &src->diagh, _state, make_automatic); - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - dst->f = src->f; - ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic); - dst->needf = src->needf; - dst->needfg = src->needfg; - dst->xupdated = src->xupdated; - dst->userterminationneeded = src->userterminationneeded; - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); - ae_vector_init_copy(&dst->xc, &src->xc, _state, make_automatic); - ae_vector_init_copy(&dst->ugc, &src->ugc, _state, make_automatic); - ae_vector_init_copy(&dst->cgc, &src->cgc, _state, make_automatic); - ae_vector_init_copy(&dst->xn, &src->xn, _state, make_automatic); - ae_vector_init_copy(&dst->ugn, &src->ugn, _state, make_automatic); - ae_vector_init_copy(&dst->cgn, &src->cgn, _state, make_automatic); - ae_vector_init_copy(&dst->xp, &src->xp, _state, make_automatic); - dst->fc = src->fc; - dst->fn = src->fn; - dst->fp = src->fp; - ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic); - dst->lastscaledgoodstep = src->lastscaledgoodstep; - ae_vector_init_copy(&dst->hasbndl, &src->hasbndl, _state, make_automatic); - ae_vector_init_copy(&dst->hasbndu, &src->hasbndu, _state, make_automatic); - ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic); - ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic); - dst->repiterationscount = src->repiterationscount; - dst->repnfev = src->repnfev; - dst->repvaridx = src->repvaridx; - dst->repterminationtype = src->repterminationtype; - ae_vector_init_copy(&dst->xstart, &src->xstart, _state, make_automatic); - dst->fbase = src->fbase; - dst->fm2 = src->fm2; - dst->fm1 = src->fm1; - dst->fp1 = src->fp1; - dst->fp2 = src->fp2; - dst->xm1 = src->xm1; - dst->xp1 = src->xp1; - dst->gm1 = src->gm1; - dst->gp1 = src->gp1; - ae_vector_init_copy(&dst->tmpprec, &src->tmpprec, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - dst->nfev = src->nfev; - dst->mcstage = src->mcstage; - dst->stp = src->stp; - dst->curstpmax = src->curstpmax; - ae_vector_init_copy(&dst->work, &src->work, _state, make_automatic); - _linminstate_init_copy(&dst->lstate, &src->lstate, _state, make_automatic); - dst->trimthreshold = src->trimthreshold; - dst->nonmonotoniccnt = src->nonmonotoniccnt; - ae_matrix_init_copy(&dst->bufyk, &src->bufyk, _state, make_automatic); - ae_matrix_init_copy(&dst->bufsk, &src->bufsk, _state, make_automatic); - ae_vector_init_copy(&dst->bufrho, &src->bufrho, _state, make_automatic); - ae_vector_init_copy(&dst->buftheta, &src->buftheta, _state, make_automatic); - dst->bufsize = src->bufsize; - dst->teststep = src->teststep; - dst->smoothnessguardlevel = src->smoothnessguardlevel; - _smoothnessmonitor_init_copy(&dst->smonitor, &src->smonitor, _state, make_automatic); - ae_vector_init_copy(&dst->lastscaleused, &src->lastscaleused, _state, make_automatic); - ae_vector_init_copy(&dst->invs, &src->invs, _state, make_automatic); -} - - -void _minbcstate_clear(void* _p) -{ - minbcstate *p = (minbcstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->s); - ae_vector_clear(&p->diagh); - ae_vector_clear(&p->x); - ae_vector_clear(&p->g); - _rcommstate_clear(&p->rstate); - ae_vector_clear(&p->xc); - ae_vector_clear(&p->ugc); - ae_vector_clear(&p->cgc); - ae_vector_clear(&p->xn); - ae_vector_clear(&p->ugn); - ae_vector_clear(&p->cgn); - ae_vector_clear(&p->xp); - ae_vector_clear(&p->d); - ae_vector_clear(&p->hasbndl); - ae_vector_clear(&p->hasbndu); - ae_vector_clear(&p->bndl); - ae_vector_clear(&p->bndu); - ae_vector_clear(&p->xstart); - ae_vector_clear(&p->tmpprec); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->work); - _linminstate_clear(&p->lstate); - ae_matrix_clear(&p->bufyk); - ae_matrix_clear(&p->bufsk); - ae_vector_clear(&p->bufrho); - ae_vector_clear(&p->buftheta); - _smoothnessmonitor_clear(&p->smonitor); - ae_vector_clear(&p->lastscaleused); - ae_vector_clear(&p->invs); -} - - -void _minbcstate_destroy(void* _p) -{ - minbcstate *p = (minbcstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->s); - ae_vector_destroy(&p->diagh); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->g); - _rcommstate_destroy(&p->rstate); - ae_vector_destroy(&p->xc); - ae_vector_destroy(&p->ugc); - ae_vector_destroy(&p->cgc); - ae_vector_destroy(&p->xn); - ae_vector_destroy(&p->ugn); - ae_vector_destroy(&p->cgn); - ae_vector_destroy(&p->xp); - ae_vector_destroy(&p->d); - ae_vector_destroy(&p->hasbndl); - ae_vector_destroy(&p->hasbndu); - ae_vector_destroy(&p->bndl); - ae_vector_destroy(&p->bndu); - ae_vector_destroy(&p->xstart); - ae_vector_destroy(&p->tmpprec); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->work); - _linminstate_destroy(&p->lstate); - ae_matrix_destroy(&p->bufyk); - ae_matrix_destroy(&p->bufsk); - ae_vector_destroy(&p->bufrho); - ae_vector_destroy(&p->buftheta); - _smoothnessmonitor_destroy(&p->smonitor); - ae_vector_destroy(&p->lastscaleused); - ae_vector_destroy(&p->invs); -} - - -void _minbcreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minbcreport *p = (minbcreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _minbcreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minbcreport *dst = (minbcreport*)_dst; - minbcreport *src = (minbcreport*)_src; - dst->iterationscount = src->iterationscount; - dst->nfev = src->nfev; - dst->varidx = src->varidx; - dst->terminationtype = src->terminationtype; -} - - -void _minbcreport_clear(void* _p) -{ - minbcreport *p = (minbcreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _minbcreport_destroy(void* _p) -{ - minbcreport *p = (minbcreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_MINNS) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* - NONSMOOTH NONCONVEX OPTIMIZATION - SUBJECT TO BOX/LINEAR/NONLINEAR-NONSMOOTH CONSTRAINTS - -DESCRIPTION: - -The subroutine minimizes function F(x) of N arguments subject to any -combination of: -* bound constraints -* linear inequality constraints -* linear equality constraints -* nonlinear equality constraints Gi(x)=0 -* nonlinear inequality constraints Hi(x)<=0 - -IMPORTANT: see MinNSSetAlgoAGS for important information on performance - restrictions of AGS solver. - -REQUIREMENTS: -* starting point X0 must be feasible or not too far away from the feasible - set -* F(), G(), H() are continuous, locally Lipschitz and continuously (but - not necessarily twice) differentiable in an open dense subset of R^N. - Functions F(), G() and H() may be nonsmooth and non-convex. - Informally speaking, it means that functions are composed of large - differentiable "patches" with nonsmoothness having place only at the - boundaries between these "patches". - Most real-life nonsmooth functions satisfy these requirements. Say, - anything which involves finite number of abs(), min() and max() is very - likely to pass the test. - Say, it is possible to optimize anything of the following: - * f=abs(x0)+2*abs(x1) - * f=max(x0,x1) - * f=sin(max(x0,x1)+abs(x2)) -* for nonlinearly constrained problems: F() must be bounded from below - without nonlinear constraints (this requirement is due to the fact that, - contrary to box and linear constraints, nonlinear ones require special - handling). -* user must provide function value and gradient for F(), H(), G() at all - points where function/gradient can be calculated. If optimizer requires - value exactly at the boundary between "patches" (say, at x=0 for f=abs(x)), - where gradient is not defined, user may resolve tie arbitrarily (in our - case - return +1 or -1 at its discretion). -* NS solver supports numerical differentiation, i.e. it may differentiate - your function for you, but it results in 2N increase of function - evaluations. Not recommended unless you solve really small problems. See - minnscreatef() for more information on this functionality. - -USAGE: - -1. User initializes algorithm state with MinNSCreate() call and chooses - what NLC solver to use. There is some solver which is used by default, - with default settings, but you should NOT rely on default choice. It - may change in future releases of ALGLIB without notice, and no one can - guarantee that new solver will be able to solve your problem with - default settings. - - From the other side, if you choose solver explicitly, you can be pretty - sure that it will work with new ALGLIB releases. - - In the current release following solvers can be used: - * AGS solver (activated with MinNSSetAlgoAGS() function) - -2. User adds boundary and/or linear and/or nonlinear constraints by means - of calling one of the following functions: - a) MinNSSetBC() for boundary constraints - b) MinNSSetLC() for linear constraints - c) MinNSSetNLC() for nonlinear constraints - You may combine (a), (b) and (c) in one optimization problem. - -3. User sets scale of the variables with MinNSSetScale() function. It is - VERY important to set scale of the variables, because nonlinearly - constrained problems are hard to solve when variables are badly scaled. - -4. User sets stopping conditions with MinNSSetCond(). - -5. Finally, user calls MinNSOptimize() function which takes algorithm - state and pointer (delegate, etc) to callback function which calculates - F/G/H. - -7. User calls MinNSResults() to get solution - -8. Optionally user may call MinNSRestartFrom() to solve another problem - with same N but another starting point. MinNSRestartFrom() allows to - reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - -NOTE: minnscreatef() function may be used if you do not have analytic - gradient. This function creates solver which uses numerical - differentiation with user-specified step. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnscreate(ae_int_t n, - /* Real */ ae_vector* x, - minnsstate* state, - ae_state *_state) -{ - - _minnsstate_clear(state); - - ae_assert(n>=1, "MinNSCreate: N<1", _state); - ae_assert(x->cnt>=n, "MinNSCreate: Length(X)0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - DiffStep- differentiation step, DiffStep>0. Algorithm performs - numerical differentiation with step for I-th variable - being equal to DiffStep*S[I] (here S[] is a scale vector, - set by minnssetscale() function). - Do not use too small steps, because it may lead to - catastrophic cancellation during intermediate calculations. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnscreatef(ae_int_t n, - /* Real */ ae_vector* x, - double diffstep, - minnsstate* state, - ae_state *_state) -{ - - _minnsstate_clear(state); - - ae_assert(n>=1, "MinNSCreateF: N<1", _state); - ae_assert(x->cnt>=n, "MinNSCreateF: Length(X)n; - ae_assert(bndl->cnt>=n, "MinNSSetBC: Length(BndL)cnt>=n, "MinNSSetBC: Length(BndU)ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "MinNSSetBC: BndL contains NAN or +INF", _state); - ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "MinNSSetBC: BndL contains NAN or -INF", _state); - state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i]; - state->hasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state); - state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i]; - state->hasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state); - } -} - - -/************************************************************************* -This function sets linear constraints. - -Linear constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with minnsrestartfrom(). - -INPUT PARAMETERS: - State - structure previously allocated with minnscreate() call. - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -NOTE: linear (non-bound) constraints are satisfied only approximately: - -* there always exists some minor violation (about current sampling radius - in magnitude during optimization, about EpsX in the solution) due to use - of penalty method to handle constraints. -* numerical differentiation, if used, may lead to function evaluations - outside of the feasible area, because algorithm does NOT change - numerical differentiation formula according to linear constraints. - -If you want constraints to be satisfied exactly, try to reformulate your -problem in such manner that all constraints will become boundary ones -(this kind of constraints is always satisfied exactly, both in the final -solution and in all intermediate points). - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnssetlc(minnsstate* state, - /* Real */ ae_matrix* c, - /* Integer */ ae_vector* ct, - ae_int_t k, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - - - n = state->n; - - /* - * First, check for errors in the inputs - */ - ae_assert(k>=0, "MinNSSetLC: K<0", _state); - ae_assert(c->cols>=n+1||k==0, "MinNSSetLC: Cols(C)rows>=k, "MinNSSetLC: Rows(C)cnt>=k, "MinNSSetLC: Length(CT)nec = 0; - state->nic = 0; - return; - } - - /* - * Equality constraints are stored first, in the upper - * NEC rows of State.CLEIC matrix. Inequality constraints - * are stored in the next NIC rows. - * - * NOTE: we convert inequality constraints to the form - * A*x<=b before copying them. - */ - rmatrixsetlengthatleast(&state->cleic, k, n+1, _state); - state->nec = 0; - state->nic = 0; - for(i=0; i<=k-1; i++) - { - if( ct->ptr.p_int[i]==0 ) - { - ae_v_move(&state->cleic.ptr.pp_double[state->nec][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n)); - state->nec = state->nec+1; - } - } - for(i=0; i<=k-1; i++) - { - if( ct->ptr.p_int[i]!=0 ) - { - if( ct->ptr.p_int[i]>0 ) - { - ae_v_moveneg(&state->cleic.ptr.pp_double[state->nec+state->nic][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n)); - } - else - { - ae_v_move(&state->cleic.ptr.pp_double[state->nec+state->nic][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n)); - } - state->nic = state->nic+1; - } - } -} - - -/************************************************************************* -This function sets nonlinear constraints. - -In fact, this function sets NUMBER of nonlinear constraints. Constraints -itself (constraint functions) are passed to minnsoptimize() method. This -method requires user-defined vector function F[] and its Jacobian J[], -where: -* first component of F[] and first row of Jacobian J[] correspond to - function being minimized -* next NLEC components of F[] (and rows of J) correspond to nonlinear - equality constraints G_i(x)=0 -* next NLIC components of F[] (and rows of J) correspond to nonlinear - inequality constraints H_i(x)<=0 - -NOTE: you may combine nonlinear constraints with linear/boundary ones. If - your problem has mixed constraints, you may explicitly specify some - of them as linear ones. It may help optimizer to handle them more - efficiently. - -INPUT PARAMETERS: - State - structure previously allocated with minnscreate() call. - NLEC - number of Non-Linear Equality Constraints (NLEC), >=0 - NLIC - number of Non-Linear Inquality Constraints (NLIC), >=0 - -NOTE 1: nonlinear constraints are satisfied only approximately! It is - possible that algorithm will evaluate function outside of - the feasible area! - -NOTE 2: algorithm scales variables according to scale specified by - minnssetscale() function, so it can handle problems with badly - scaled variables (as long as we KNOW their scales). - - However, there is no way to automatically scale nonlinear - constraints Gi(x) and Hi(x). Inappropriate scaling of Gi/Hi may - ruin convergence. Solving problem with constraint "1000*G0(x)=0" - is NOT same as solving it with constraint "0.001*G0(x)=0". - - It means that YOU are the one who is responsible for correct - scaling of nonlinear constraints Gi(x) and Hi(x). We recommend you - to scale nonlinear constraints in such way that I-th component of - dG/dX (or dH/dx) has approximately unit magnitude (for problems - with unit scale) or has magnitude approximately equal to 1/S[i] - (where S is a scale set by minnssetscale() function). - -NOTE 3: nonlinear constraints are always hard to handle, no matter what - algorithm you try to use. Even basic box/linear constraints modify - function curvature by adding valleys and ridges. However, - nonlinear constraints add valleys which are very hard to follow - due to their "curved" nature. - - It means that optimization with single nonlinear constraint may be - significantly slower than optimization with multiple linear ones. - It is normal situation, and we recommend you to carefully choose - Rho parameter of minnssetalgoags(), because too large value may - slow down convergence. - - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnssetnlc(minnsstate* state, - ae_int_t nlec, - ae_int_t nlic, - ae_state *_state) -{ - - - ae_assert(nlec>=0, "MinNSSetNLC: NLEC<0", _state); - ae_assert(nlic>=0, "MinNSSetNLC: NLIC<0", _state); - state->ng = nlec; - state->nh = nlic; - ae_vector_set_length(&state->fi, 1+state->ng+state->nh, _state); - ae_matrix_set_length(&state->j, 1+state->ng+state->nh, state->n, _state); -} - - -/************************************************************************* -This function sets stopping conditions for iterations of optimizer. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsX - >=0 - The AGS solver finishes its work if on k+1-th iteration - sampling radius decreases below EpsX. - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic -stopping criterion selection. We do not recommend you to rely on default -choice in production code. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnssetcond(minnsstate* state, - double epsx, - ae_int_t maxits, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(epsx, _state), "MinNSSetCond: EpsX is not finite number", _state); - ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinNSSetCond: negative EpsX", _state); - ae_assert(maxits>=0, "MinNSSetCond: negative MaxIts!", _state); - if( ae_fp_eq(epsx,(double)(0))&&maxits==0 ) - { - epsx = 1.0E-6; - } - state->epsx = epsx; - state->maxits = maxits; -} - - -/************************************************************************* -This function sets scaling coefficients for NLC optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of the optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnssetscale(minnsstate* state, - /* Real */ ae_vector* s, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(s->cnt>=state->n, "MinNSSetScale: Length(S)n-1; i++) - { - ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinNSSetScale: S contains infinite or NAN elements", _state); - ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "MinNSSetScale: S contains zero elements", _state); - state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state); - } -} - - -/************************************************************************* -This function tells MinNS unit to use AGS (adaptive gradient sampling) -algorithm for nonsmooth constrained optimization. This algorithm is a -slight modification of one described in "An Adaptive Gradient Sampling -Algorithm for Nonsmooth Optimization" by Frank E. Curtisy and Xiaocun Quez. - -This optimizer has following benefits and drawbacks: -+ robustness; it can be used with nonsmooth and nonconvex functions. -+ relatively easy tuning; most of the metaparameters are easy to select. -- it has convergence of steepest descent, slower than CG/LBFGS. -- each iteration involves evaluation of ~2N gradient values and solution - of 2Nx2N quadratic programming problem, which limits applicability of - algorithm by small-scale problems (up to 50-100). - -IMPORTANT: this algorithm has convergence guarantees, i.e. it will - steadily move towards some stationary point of the function. - - However, "stationary point" does not always mean "solution". - Nonsmooth problems often have "flat spots", i.e. areas where - function do not change at all. Such "flat spots" are stationary - points by definition, and algorithm may be caught here. - - Nonsmooth CONVEX tasks are not prone to this problem. Say, if - your function has form f()=MAX(f0,f1,...), and f_i are convex, - then f() is convex too and you have guaranteed convergence to - solution. - -INPUT PARAMETERS: - State - structure which stores algorithm state - Radius - initial sampling radius, >=0. - - Internally multiplied by vector of per-variable scales - specified by minnssetscale()). - - You should select relatively large sampling radius, roughly - proportional to scaled length of the first steps of the - algorithm. Something close to 0.1 in magnitude should be - good for most problems. - - AGS solver can automatically decrease radius, so too large - radius is not a problem (assuming that you won't choose - so large radius that algorithm will sample function in - too far away points, where gradient value is irrelevant). - - Too small radius won't cause algorithm to fail, but it may - slow down algorithm (it may have to perform too short - steps). - Penalty - penalty coefficient for nonlinear constraints: - * for problem with nonlinear constraints should be some - problem-specific positive value, large enough that - penalty term changes shape of the function. - Starting from some problem-specific value penalty - coefficient becomes large enough to exactly enforce - nonlinear constraints; larger values do not improve - precision. - Increasing it too much may slow down convergence, so you - should choose it carefully. - * can be zero for problems WITHOUT nonlinear constraints - (i.e. for unconstrained ones or ones with just box or - linear constraints) - * if you specify zero value for problem with at least one - nonlinear constraint, algorithm will terminate with - error code -1. - -ALGORITHM OUTLINE - -The very basic outline of unconstrained AGS algorithm is given below: - -0. If sampling radius is below EpsX or we performed more then MaxIts - iterations - STOP. -1. sample O(N) gradient values at random locations around current point; - informally speaking, this sample is an implicit piecewise linear model - of the function, although algorithm formulation does not mention that - explicitly -2. solve quadratic programming problem in order to find descent direction -3. if QP solver tells us that we are near solution, decrease sampling - radius and move to (0) -4. perform backtracking line search -5. after moving to new point, goto (0) - -As for the constraints: -* box constraints are handled exactly by modification of the function - being minimized -* linear/nonlinear constraints are handled by adding L1 penalty. Because - our solver can handle nonsmoothness, we can use L1 penalty function, - which is an exact one (i.e. exact solution is returned under such - penalty). -* penalty coefficient for linear constraints is chosen automatically; - however, penalty coefficient for nonlinear constraints must be specified - by user. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnssetalgoags(minnsstate* state, - double radius, - double penalty, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(radius, _state), "MinNSSetAlgoAGS: Radius is not finite", _state); - ae_assert(ae_fp_greater(radius,(double)(0)), "MinNSSetAlgoAGS: Radius<=0", _state); - ae_assert(ae_isfinite(penalty, _state), "MinNSSetAlgoAGS: Penalty is not finite", _state); - ae_assert(ae_fp_greater_eq(penalty,0.0), "MinNSSetAlgoAGS: Penalty<0", _state); - state->agsrhononlinear = penalty; - state->agsradius = radius; - state->solvertype = 0; -} - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to minnsoptimize(). - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minnssetxrep(minnsstate* state, ae_bool needxrep, ae_state *_state) -{ - - - state->xrep = needxrep; -} - - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnsrequesttermination(minnsstate* state, ae_state *_state) -{ - - - state->userterminationneeded = ae_true; -} - - -/************************************************************************* - -NOTES: - -1. This function has two different implementations: one which uses exact - (analytical) user-supplied Jacobian, and one which uses only function - vector and numerically differentiates function in order to obtain - gradient. - - Depending on the specific function used to create optimizer object - you should choose appropriate variant of minnsoptimize() - one which - accepts function AND Jacobian or one which accepts ONLY function. - - Be careful to choose variant of minnsoptimize() which corresponds to - your optimization scheme! Table below lists different combinations of - callback (function/gradient) passed to minnsoptimize() and specific - function used to create optimizer. - - - | USER PASSED TO minnsoptimize() - CREATED WITH | function only | function and gradient - ------------------------------------------------------------ - minnscreatef() | works FAILS - minnscreate() | FAILS works - - Here "FAILS" denotes inappropriate combinations of optimizer creation - function and minnsoptimize() version. Attemps to use such - combination will lead to exception. Either you did not pass gradient - when it WAS needed or you passed gradient when it was NOT needed. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -ae_bool minnsiteration(minnsstate* state, ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - ae_int_t n; - ae_int_t ng; - ae_int_t nh; - double v; - double xp; - double xm; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - i = state->rstate.ia.ptr.p_int[0]; - k = state->rstate.ia.ptr.p_int[1]; - n = state->rstate.ia.ptr.p_int[2]; - ng = state->rstate.ia.ptr.p_int[3]; - nh = state->rstate.ia.ptr.p_int[4]; - v = state->rstate.ra.ptr.p_double[0]; - xp = state->rstate.ra.ptr.p_double[1]; - xm = state->rstate.ra.ptr.p_double[2]; - } - else - { - i = 359; - k = -58; - n = -919; - ng = -909; - nh = 81; - v = 255; - xp = 74; - xm = -788; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - if( state->rstate.stage==1 ) - { - goto lbl_1; - } - if( state->rstate.stage==2 ) - { - goto lbl_2; - } - if( state->rstate.stage==3 ) - { - goto lbl_3; - } - - /* - * Routine body - */ - - /* - * Init - */ - state->replcerr = 0.0; - state->repnlcerr = 0.0; - state->repterminationtype = 0; - state->repinneriterationscount = 0; - state->repouteriterationscount = 0; - state->repnfev = 0; - state->repvaridx = 0; - state->repfuncidx = 0; - state->userterminationneeded = ae_false; - state->dbgncholesky = 0; - n = state->n; - ng = state->ng; - nh = state->nh; - minns_clearrequestfields(state, _state); - - /* - * AGS solver - */ - if( state->solvertype!=0 ) - { - goto lbl_4; - } - if( ae_fp_neq(state->diffstep,(double)(0)) ) - { - rvectorsetlengthatleast(&state->xbase, n, _state); - rvectorsetlengthatleast(&state->fm, 1+ng+nh, _state); - rvectorsetlengthatleast(&state->fp, 1+ng+nh, _state); - } - ae_vector_set_length(&state->rstateags.ia, 13+1, _state); - ae_vector_set_length(&state->rstateags.ba, 3+1, _state); - ae_vector_set_length(&state->rstateags.ra, 9+1, _state); - state->rstateags.stage = -1; -lbl_6: - if( !minns_agsiteration(state, _state) ) - { - goto lbl_7; - } - - /* - * Numerical differentiation (if needed) - intercept NeedFiJ - * request and replace it by sequence of NeedFi requests - */ - if( !(ae_fp_neq(state->diffstep,(double)(0))&&state->needfij) ) - { - goto lbl_8; - } - state->needfij = ae_false; - state->needfi = ae_true; - ae_v_move(&state->xbase.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - k = 0; -lbl_10: - if( k>n-1 ) - { - goto lbl_12; - } - v = state->xbase.ptr.p_double[k]; - xm = v-state->diffstep*state->s.ptr.p_double[k]; - xp = v+state->diffstep*state->s.ptr.p_double[k]; - if( state->hasbndl.ptr.p_bool[k]&&ae_fp_less(xm,state->bndl.ptr.p_double[k]) ) - { - xm = state->bndl.ptr.p_double[k]; - } - if( state->hasbndu.ptr.p_bool[k]&&ae_fp_greater(xp,state->bndu.ptr.p_double[k]) ) - { - xp = state->bndu.ptr.p_double[k]; - } - ae_assert(ae_fp_less_eq(xm,xp), "MinNS: integrity check failed", _state); - if( ae_fp_eq(xm,xp) ) - { - goto lbl_13; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = xm; - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - ae_v_move(&state->fm.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = xp; - state->rstate.stage = 1; - goto lbl_rcomm; -lbl_1: - ae_v_move(&state->fp.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh)); - ae_v_move(&state->j.ptr.pp_double[0][k], state->j.stride, &state->fp.ptr.p_double[0], 1, ae_v_len(0,ng+nh)); - ae_v_sub(&state->j.ptr.pp_double[0][k], state->j.stride, &state->fm.ptr.p_double[0], 1, ae_v_len(0,ng+nh)); - v = 1/(xp-xm); - ae_v_muld(&state->j.ptr.pp_double[0][k], state->j.stride, ae_v_len(0,ng+nh), v); - state->repnfev = state->repnfev+2; - goto lbl_14; -lbl_13: - for(i=0; i<=ng+nh; i++) - { - state->j.ptr.pp_double[i][k] = 0.0; - } -lbl_14: - k = k+1; - goto lbl_10; -lbl_12: - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->rstate.stage = 2; - goto lbl_rcomm; -lbl_2: - - /* - * Restore previous values of fields and continue - */ - state->needfi = ae_false; - state->needfij = ae_true; - goto lbl_6; -lbl_8: - - /* - * Forward request to caller - */ - state->rstate.stage = 3; - goto lbl_rcomm; -lbl_3: - inc(&state->repnfev, _state); - goto lbl_6; -lbl_7: - result = ae_false; - return result; -lbl_4: - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = i; - state->rstate.ia.ptr.p_int[1] = k; - state->rstate.ia.ptr.p_int[2] = n; - state->rstate.ia.ptr.p_int[3] = ng; - state->rstate.ia.ptr.p_int[4] = nh; - state->rstate.ra.ptr.p_double[0] = v; - state->rstate.ra.ptr.p_double[1] = xp; - state->rstate.ra.ptr.p_double[2] = xm; - return result; -} - - -/************************************************************************* -MinNS results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report. You should check Rep.TerminationType - in order to distinguish successful termination from - unsuccessful one: - * -8 internal integrity control detected infinite or - NAN values in function/gradient. Abnormal - termination signalled. - * -3 box constraints are inconsistent - * -1 inconsistent parameters were passed: - * penalty parameter for minnssetalgoags() is zero, - but we have nonlinear constraints set by minnssetnlc() - * 2 sampling radius decreased below epsx - * 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - * 8 User requested termination via minnsrequesttermination() - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnsresults(minnsstate* state, - /* Real */ ae_vector* x, - minnsreport* rep, - ae_state *_state) -{ - - ae_vector_clear(x); - _minnsreport_clear(rep); - - minnsresultsbuf(state, x, rep, _state); -} - - -/************************************************************************* - -Buffered implementation of minnsresults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnsresultsbuf(minnsstate* state, - /* Real */ ae_vector* x, - minnsreport* rep, - ae_state *_state) -{ - ae_int_t i; - - - if( x->cntn ) - { - ae_vector_set_length(x, state->n, _state); - } - rep->iterationscount = state->repinneriterationscount; - rep->nfev = state->repnfev; - rep->varidx = state->repvaridx; - rep->funcidx = state->repfuncidx; - rep->terminationtype = state->repterminationtype; - rep->cerr = ae_maxreal(state->replcerr, state->repnlcerr, _state); - rep->lcerr = state->replcerr; - rep->nlcerr = state->repnlcerr; - if( state->repterminationtype>0 ) - { - ae_v_move(&x->ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - } - else - { - for(i=0; i<=state->n-1; i++) - { - x->ptr.p_double[i] = _state->v_nan; - } - } -} - - -/************************************************************************* -This subroutine restarts algorithm from new point. -All optimization parameters (including constraints) are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure previously allocated with minnscreate() call. - X - new starting point. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnsrestartfrom(minnsstate* state, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t n; - - - n = state->n; - - /* - * First, check for errors in the inputs - */ - ae_assert(x->cnt>=n, "MinNSRestartFrom: Length(X)xstart.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - - /* - * prepare RComm facilities - */ - ae_vector_set_length(&state->rstate.ia, 4+1, _state); - ae_vector_set_length(&state->rstate.ra, 2+1, _state); - state->rstate.stage = -1; - minns_clearrequestfields(state, _state); -} - - -/************************************************************************* -Clears request fileds (to be sure that we don't forget to clear something) -*************************************************************************/ -static void minns_clearrequestfields(minnsstate* state, ae_state *_state) -{ - - - state->needfi = ae_false; - state->needfij = ae_false; - state->xupdated = ae_false; -} - - -/************************************************************************* -Internal initialization subroutine. -Sets default NLC solver with default criteria. -*************************************************************************/ -static void minns_minnsinitinternal(ae_int_t n, - /* Real */ ae_vector* x, - double diffstep, - minnsstate* state, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_matrix c; - ae_vector ct; - - ae_frame_make(_state, &_frame_block); - memset(&c, 0, sizeof(c)); - memset(&ct, 0, sizeof(ct)); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - - state->agsinitstp = 0.2; - state->agsstattold = 1.0E-10; - state->agsshortstpabs = 1.0E-10; - state->agsshortstprel = 0.75; - state->agsshortf = 10*ae_machineepsilon; - state->agsrhononlinear = 0.0; - state->agsraddecay = 0.2; - state->agsalphadecay = 0.5; - state->agsdecrease = 0.1; - state->agsmaxraddecays = 50; - state->agsmaxbacktrack = 20; - state->agsmaxbacktracknonfull = 8; - state->agspenaltylevel = 50.0; - state->agspenaltyincrease = 100.0; - state->agsminupdate = ae_maxint(5, n/2, _state); - state->agssamplesize = ae_maxint(2*n+1, state->agsminupdate+1, _state); - state->agsshortlimit = 4+state->agssamplesize/state->agsminupdate; - - /* - * Initialize other params - */ - state->n = n; - state->diffstep = diffstep; - ae_vector_set_length(&state->bndl, n, _state); - ae_vector_set_length(&state->hasbndl, n, _state); - ae_vector_set_length(&state->bndu, n, _state); - ae_vector_set_length(&state->hasbndu, n, _state); - ae_vector_set_length(&state->s, n, _state); - ae_vector_set_length(&state->xstart, n, _state); - ae_vector_set_length(&state->xc, n, _state); - ae_vector_set_length(&state->xn, n, _state); - ae_vector_set_length(&state->d, n, _state); - ae_vector_set_length(&state->x, n, _state); - for(i=0; i<=n-1; i++) - { - state->bndl.ptr.p_double[i] = _state->v_neginf; - state->hasbndl.ptr.p_bool[i] = ae_false; - state->bndu.ptr.p_double[i] = _state->v_posinf; - state->hasbndu.ptr.p_bool[i] = ae_false; - state->s.ptr.p_double[i] = 1.0; - state->xstart.ptr.p_double[i] = x->ptr.p_double[i]; - state->xc.ptr.p_double[i] = x->ptr.p_double[i]; - } - minnssetlc(state, &c, &ct, 0, _state); - minnssetnlc(state, 0, 0, _state); - minnssetcond(state, 0.0, 0, _state); - minnssetxrep(state, ae_false, _state); - minnssetalgoags(state, 0.1, 1000.0, _state); - minnsrestartfrom(state, x, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function performs actual processing for AUL algorith. It expects that -caller redirects its reverse communication requests NeedFiJ/XUpdated to -external user who will provide analytic derivative (or handle reports about -progress). - -In case external user does not have analytic derivative, it is responsibility -of caller to intercept NeedFiJ request and replace it with appropriate -numerical differentiation scheme. - - -- ALGLIB -- - Copyright 06.06.2015 by Bochkanov Sergey -*************************************************************************/ -static ae_bool minns_agsiteration(minnsstate* state, ae_state *_state) -{ - ae_int_t n; - ae_int_t nec; - ae_int_t nic; - ae_int_t ng; - ae_int_t nh; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double radius0; - double radius; - ae_int_t radiusdecays; - double alpha; - double recommendedstep; - double dnrm; - double dg; - double v; - double vv; - ae_int_t maxsamplesize; - ae_int_t cursamplesize; - double v0; - double v1; - ae_bool restartneeded; - ae_bool b; - ae_bool alphadecreased; - ae_int_t shortstepscnt; - ae_int_t backtrackits; - ae_int_t maxbacktrackits; - ae_bool fullsample; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstateags.stage>=0 ) - { - n = state->rstateags.ia.ptr.p_int[0]; - nec = state->rstateags.ia.ptr.p_int[1]; - nic = state->rstateags.ia.ptr.p_int[2]; - ng = state->rstateags.ia.ptr.p_int[3]; - nh = state->rstateags.ia.ptr.p_int[4]; - i = state->rstateags.ia.ptr.p_int[5]; - j = state->rstateags.ia.ptr.p_int[6]; - k = state->rstateags.ia.ptr.p_int[7]; - radiusdecays = state->rstateags.ia.ptr.p_int[8]; - maxsamplesize = state->rstateags.ia.ptr.p_int[9]; - cursamplesize = state->rstateags.ia.ptr.p_int[10]; - shortstepscnt = state->rstateags.ia.ptr.p_int[11]; - backtrackits = state->rstateags.ia.ptr.p_int[12]; - maxbacktrackits = state->rstateags.ia.ptr.p_int[13]; - restartneeded = state->rstateags.ba.ptr.p_bool[0]; - b = state->rstateags.ba.ptr.p_bool[1]; - alphadecreased = state->rstateags.ba.ptr.p_bool[2]; - fullsample = state->rstateags.ba.ptr.p_bool[3]; - radius0 = state->rstateags.ra.ptr.p_double[0]; - radius = state->rstateags.ra.ptr.p_double[1]; - alpha = state->rstateags.ra.ptr.p_double[2]; - recommendedstep = state->rstateags.ra.ptr.p_double[3]; - dnrm = state->rstateags.ra.ptr.p_double[4]; - dg = state->rstateags.ra.ptr.p_double[5]; - v = state->rstateags.ra.ptr.p_double[6]; - vv = state->rstateags.ra.ptr.p_double[7]; - v0 = state->rstateags.ra.ptr.p_double[8]; - v1 = state->rstateags.ra.ptr.p_double[9]; - } - else - { - n = 809; - nec = 205; - nic = -838; - ng = 939; - nh = -526; - i = 763; - j = -541; - k = -698; - radiusdecays = -900; - maxsamplesize = -318; - cursamplesize = -940; - shortstepscnt = 1016; - backtrackits = -229; - maxbacktrackits = -536; - restartneeded = ae_true; - b = ae_true; - alphadecreased = ae_false; - fullsample = ae_false; - radius0 = -722; - radius = -413; - alpha = -461; - recommendedstep = 927; - dnrm = 201; - dg = 922; - v = -154; - vv = 306; - v0 = -1011; - v1 = 951; - } - if( state->rstateags.stage==0 ) - { - goto lbl_0; - } - if( state->rstateags.stage==1 ) - { - goto lbl_1; - } - if( state->rstateags.stage==2 ) - { - goto lbl_2; - } - if( state->rstateags.stage==3 ) - { - goto lbl_3; - } - - /* - * Routine body - */ - ae_assert(state->solvertype==0, "MinNS: internal error", _state); - n = state->n; - nec = state->nec; - nic = state->nic; - ng = state->ng; - nh = state->nh; - - /* - * Check consistency of parameters - */ - if( ng+nh>0&&ae_fp_eq(state->agsrhononlinear,(double)(0)) ) - { - state->repterminationtype = -1; - result = ae_false; - return result; - } - - /* - * Allocate arrays. - */ - rvectorsetlengthatleast(&state->colmax, n, _state); - rvectorsetlengthatleast(&state->diagh, n, _state); - rvectorsetlengthatleast(&state->signmin, n, _state); - rvectorsetlengthatleast(&state->signmax, n, _state); - maxsamplesize = state->agssamplesize; - rmatrixsetlengthatleast(&state->samplex, maxsamplesize+1, n, _state); - rmatrixsetlengthatleast(&state->samplegm, maxsamplesize+1, n, _state); - rmatrixsetlengthatleast(&state->samplegmbc, maxsamplesize+1, n, _state); - rvectorsetlengthatleast(&state->samplef, maxsamplesize+1, _state); - rvectorsetlengthatleast(&state->samplef0, maxsamplesize+1, _state); - rvectorsetlengthatleast(&state->grs, n, _state); - - /* - * Prepare optimizer - */ - rvectorsetlengthatleast(&state->tmp0, maxsamplesize, _state); - rvectorsetlengthatleast(&state->tmp1, maxsamplesize, _state); - ivectorsetlengthatleast(&state->tmp3, 1, _state); - rmatrixsetlengthatleast(&state->tmp2, 1, maxsamplesize+1, _state); - for(i=0; i<=maxsamplesize-1; i++) - { - state->tmp0.ptr.p_double[i] = 0.0; - state->tmp1.ptr.p_double[i] = _state->v_posinf; - } - - /* - * Prepare RNG, seed it with fixed values so - * that each run on same problem yeilds same results - */ - hqrndseed(7235, 98532, &state->agsrs, _state); - - /* - * Prepare initial point subject to current bound constraints and - * perform scaling of bound constraints, linear constraints, point itself - */ - rvectorsetlengthatleast(&state->scaledbndl, n, _state); - rvectorsetlengthatleast(&state->scaledbndu, n, _state); - for(i=0; i<=n-1; i++) - { - - /* - * Check and scale constraints - */ - if( (state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_less(state->bndu.ptr.p_double[i],state->bndl.ptr.p_double[i]) ) - { - state->repterminationtype = -3; - result = ae_false; - return result; - } - if( state->hasbndl.ptr.p_bool[i] ) - { - state->scaledbndl.ptr.p_double[i] = state->bndl.ptr.p_double[i]/state->s.ptr.p_double[i]; - } - else - { - state->scaledbndl.ptr.p_double[i] = _state->v_neginf; - } - if( state->hasbndu.ptr.p_bool[i] ) - { - state->scaledbndu.ptr.p_double[i] = state->bndu.ptr.p_double[i]/state->s.ptr.p_double[i]; - } - else - { - state->scaledbndu.ptr.p_double[i] = _state->v_posinf; - } - if( state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i] ) - { - ae_assert(ae_fp_less_eq(state->scaledbndl.ptr.p_double[i],state->scaledbndu.ptr.p_double[i]), "MinNS: integrity check failed", _state); - } - if( (state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_eq(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - ae_assert(ae_fp_eq(state->scaledbndl.ptr.p_double[i],state->scaledbndu.ptr.p_double[i]), "MinNS: integrity check failed", _state); - } - - /* - * Scale and constrain point - */ - state->xc.ptr.p_double[i] = state->xstart.ptr.p_double[i]; - if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]) ) - { - state->xc.ptr.p_double[i] = state->scaledbndl.ptr.p_double[i]; - continue; - } - if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->xc.ptr.p_double[i] = state->scaledbndu.ptr.p_double[i]; - continue; - } - state->xc.ptr.p_double[i] = state->xc.ptr.p_double[i]/state->s.ptr.p_double[i]; - if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(state->xc.ptr.p_double[i],state->scaledbndl.ptr.p_double[i]) ) - { - state->xc.ptr.p_double[i] = state->scaledbndl.ptr.p_double[i]; - } - if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(state->xc.ptr.p_double[i],state->scaledbndu.ptr.p_double[i]) ) - { - state->xc.ptr.p_double[i] = state->scaledbndu.ptr.p_double[i]; - } - } - rmatrixsetlengthatleast(&state->scaledcleic, nec+nic, n+1, _state); - rvectorsetlengthatleast(&state->rholinear, nec+nic, _state); - for(i=0; i<=nec+nic-1; i++) - { - - /* - * Initial value of penalty coefficient is zero - */ - state->rholinear.ptr.p_double[i] = 0.0; - - /* - * Scale and normalize linear constraints - */ - vv = 0.0; - for(j=0; j<=n-1; j++) - { - v = state->cleic.ptr.pp_double[i][j]*state->s.ptr.p_double[j]; - state->scaledcleic.ptr.pp_double[i][j] = v; - vv = vv+v*v; - } - vv = ae_sqrt(vv, _state); - state->scaledcleic.ptr.pp_double[i][n] = state->cleic.ptr.pp_double[i][n]; - if( ae_fp_greater(vv,(double)(0)) ) - { - for(j=0; j<=n; j++) - { - state->scaledcleic.ptr.pp_double[i][j] = state->scaledcleic.ptr.pp_double[i][j]/vv; - } - } - } - - /* - * Main cycle - * - * We maintain several variables during iteration: - * * RecommendedStep- current estimate of recommended step length; - * must be Radius0 on first entry - * * Radius - current sampling radius - * * CurSampleSize - current sample size (may change in future versions) - * * FullSample - whether we have full sample, or only partial one - * * RadiusDecays - total number of decreases performed for sampling radius - */ - radius = state->agsradius; - radius0 = radius; - recommendedstep = ae_minreal(radius0, state->agsinitstp, _state); - cursamplesize = 1; - radiusdecays = 0; - shortstepscnt = 0; - fullsample = ae_false; -lbl_4: - if( ae_false ) - { - goto lbl_5; - } - - /* - * First phase of iteration - central point: - * - * 1. evaluate function at central point - first entry in sample. - * Its status is ignored, it is always recalculated. - * 2. report point and check gradient/function value for NAN/INF - * 3. check penalty coefficients for linear terms; increase them - * if directional derivative of function being optimized (not - * merit function!) is larger than derivative of penalty. - * 4. update report on constraint violation - */ - cursamplesize = ae_maxint(cursamplesize, 1, _state); - ae_v_move(&state->samplex.ptr.pp_double[0][0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minns_unscalepointbc(state, &state->x, _state); - minns_clearrequestfields(state, _state); - state->needfij = ae_true; - state->rstateags.stage = 0; - goto lbl_rcomm; -lbl_0: - state->needfij = ae_false; - state->replcerr = 0.0; - for(i=0; i<=nec+nic-1; i++) - { - v = -state->scaledcleic.ptr.pp_double[i][n]; - for(j=0; j<=n-1; j++) - { - v = v+state->scaledcleic.ptr.pp_double[i][j]*state->xc.ptr.p_double[j]; - } - if( i>=nec&&ae_fp_less_eq(v,(double)(0)) ) - { - continue; - } - state->replcerr = ae_maxreal(state->replcerr, ae_fabs(v, _state), _state); - } - state->repnlcerr = 0.0; - for(i=1; i<=ng+nh; i++) - { - v = state->fi.ptr.p_double[i]; - if( i>ng&&ae_fp_less_eq(v,(double)(0)) ) - { - continue; - } - state->repnlcerr = ae_maxreal(state->repnlcerr, ae_fabs(v, _state), _state); - } - for(j=0; j<=n-1; j++) - { - state->grs.ptr.p_double[j] = state->j.ptr.pp_double[0][j]*state->s.ptr.p_double[j]; - } - minns_generatemeritfunction(state, 0, _state); - if( !state->xrep ) - { - goto lbl_6; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->f = state->samplef0.ptr.p_double[0]; - minns_unscalepointbc(state, &state->x, _state); - minns_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstateags.stage = 1; - goto lbl_rcomm; -lbl_1: - state->xupdated = ae_false; -lbl_6: - if( state->userterminationneeded ) - { - - /* - * User requested termination - */ - state->repterminationtype = 8; - goto lbl_5; - } - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(state->samplegm.ptr.pp_double[0][i], _state); - } - if( !ae_isfinite(v, _state)||!ae_isfinite(state->samplef.ptr.p_double[0], _state) ) - { - - /* - * Abnormal termination - infinities in function/gradient - */ - state->repterminationtype = -8; - goto lbl_5; - } - restartneeded = ae_false; - for(i=0; i<=nec+nic-1; i++) - { - - /* - * Evaluate penalty function. - * - * Skip update if penalty is satisfied exactly (this check - * also covers situations when I-th row is exactly zero). - */ - v = -state->scaledcleic.ptr.pp_double[i][n]; - for(j=0; j<=n-1; j++) - { - v = v+state->scaledcleic.ptr.pp_double[i][j]*state->xc.ptr.p_double[j]; - } - if( i=nec&&ae_fp_less_eq(v,(double)(0)) ) - { - continue; - } - - /* - * Calculate directional derivative, compare it with threshold. - * - * NOTE: we rely on the fact that ScaledCLEIC is normalized - */ - ae_assert(ae_fp_greater(state->agspenaltylevel,1.0), "MinNS: integrity error", _state); - ae_assert(ae_fp_greater(state->agspenaltyincrease,state->agspenaltylevel), "MinNS: integrity error", _state); - v = 0.0; - for(j=0; j<=n-1; j++) - { - v = v+state->grs.ptr.p_double[j]*state->scaledcleic.ptr.pp_double[i][j]; - } - v = ae_fabs(v, _state); - if( ae_fp_greater(v*state->agspenaltylevel,state->rholinear.ptr.p_double[i]) ) - { - state->rholinear.ptr.p_double[i] = v*state->agspenaltyincrease; - restartneeded = ae_true; - } - } - if( restartneeded ) - { - cursamplesize = 0; - goto lbl_4; - } - - /* - * Check stopping conditions. - */ - if( radiusdecays>=state->agsmaxraddecays ) - { - - /* - * Too many attempts to decrease radius - */ - state->repterminationtype = 7; - goto lbl_5; - } - if( state->repinneriterationscount>=state->maxits&&state->maxits>0 ) - { - - /* - * Too many iterations - */ - state->repterminationtype = 5; - goto lbl_5; - } - if( ae_fp_less_eq(radius,state->epsx*state->agsraddecay) ) - { - - /* - * Radius is smaller than required step tolerance multiplied by radius decay. - * - * Additional decay is required in order to make sure that optimization session - * with radius equal to EpsX was successfully done. - */ - state->repterminationtype = 2; - goto lbl_5; - } - - /* - * Update sample: - * - * 1. invalidate entries which are too far away from XC - * and move all valid entries to beginning of the sample. - * 2. add new entries until we have AGSSampleSize - * items in our sample. We remove oldest entries from - * sample until we have enough place to add at least - * AGSMinUpdate items. - * 3. prepare "modified" gradient sample with respect to - * boundary constraints. - */ - ae_assert(cursamplesize>=1, "MinNS: integrity check failed", _state); - k = 1; - for(i=1; i<=cursamplesize-1; i++) - { - - /* - * If entry is outside of Radius-ball around XC, discard it. - */ - v = 0.0; - for(j=0; j<=n-1; j++) - { - v = ae_maxreal(v, ae_fabs(state->samplex.ptr.pp_double[i][j]-state->xc.ptr.p_double[j], _state), _state); - } - if( ae_fp_greater(v,radius) ) - { - continue; - } - - /* - * If central point is exactly at boundary, and corresponding - * component of entry is OUT of boundary, entry is discarded. - */ - b = ae_false; - for(j=0; j<=n-1; j++) - { - b = b||((state->hasbndl.ptr.p_bool[j]&&ae_fp_eq(state->xc.ptr.p_double[j],state->scaledbndl.ptr.p_double[j]))&&ae_fp_neq(state->samplex.ptr.pp_double[i][j],state->scaledbndl.ptr.p_double[j])); - b = b||((state->hasbndu.ptr.p_bool[j]&&ae_fp_eq(state->xc.ptr.p_double[j],state->scaledbndu.ptr.p_double[j]))&&ae_fp_neq(state->samplex.ptr.pp_double[i][j],state->scaledbndu.ptr.p_double[j])); - } - if( b ) - { - continue; - } - - /* - * Move to the beginning - */ - ae_v_move(&state->samplex.ptr.pp_double[k][0], 1, &state->samplex.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->samplegm.ptr.pp_double[k][0], 1, &state->samplegm.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - state->samplef.ptr.p_double[k] = state->samplef.ptr.p_double[i]; - state->samplef0.ptr.p_double[k] = state->samplef0.ptr.p_double[i]; - k = k+1; - } - cursamplesize = k; - if( state->agssamplesize-cursamplesizeagsminupdate ) - { - - /* - * Remove oldest entries - */ - k = state->agsminupdate-(state->agssamplesize-cursamplesize); - ae_assert(k<=cursamplesize-1, "MinNS: integrity check failed", _state); - for(i=1; i<=cursamplesize-k-1; i++) - { - ae_v_move(&state->samplex.ptr.pp_double[i][0], 1, &state->samplex.ptr.pp_double[i+k][0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->samplegm.ptr.pp_double[i][0], 1, &state->samplegm.ptr.pp_double[i+k][0], 1, ae_v_len(0,n-1)); - state->samplef.ptr.p_double[i] = state->samplef.ptr.p_double[i+k]; - state->samplef0.ptr.p_double[i] = state->samplef0.ptr.p_double[i+k]; - } - cursamplesize = cursamplesize-k; - } - k = 0; - i = cursamplesize; -lbl_8: - if( i>ae_minint(cursamplesize+state->agsminupdate, state->agssamplesize, _state)-1 ) - { - goto lbl_10; - } - for(j=0; j<=n-1; j++) - { - - /* - * Undistorted position - */ - state->samplex.ptr.pp_double[i][j] = state->xc.ptr.p_double[j]; - - /* - * Do not apply distortion, if we are exactly at boundary constraint. - */ - if( (state->hasbndl.ptr.p_bool[j]&&state->hasbndu.ptr.p_bool[j])&&ae_fp_eq(state->scaledbndl.ptr.p_double[j],state->scaledbndu.ptr.p_double[j]) ) - { - continue; - } - if( state->hasbndl.ptr.p_bool[j]&&ae_fp_eq(state->samplex.ptr.pp_double[i][j],state->scaledbndl.ptr.p_double[j]) ) - { - continue; - } - if( state->hasbndu.ptr.p_bool[j]&&ae_fp_eq(state->samplex.ptr.pp_double[i][j],state->scaledbndu.ptr.p_double[j]) ) - { - continue; - } - - /* - * Apply distortion - */ - if( ae_fp_greater_eq(hqrnduniformr(&state->agsrs, _state),0.5) ) - { - - /* - * Sample at the left side with 50% probability - */ - v0 = state->samplex.ptr.pp_double[i][j]-radius; - v1 = state->samplex.ptr.pp_double[i][j]; - if( state->hasbndl.ptr.p_bool[j] ) - { - v0 = ae_maxreal(state->scaledbndl.ptr.p_double[j], v0, _state); - } - } - else - { - - /* - * Sample at the right side with 50% probability - */ - v0 = state->samplex.ptr.pp_double[i][j]; - v1 = state->samplex.ptr.pp_double[i][j]+radius; - if( state->hasbndu.ptr.p_bool[j] ) - { - v1 = ae_minreal(state->scaledbndu.ptr.p_double[j], v1, _state); - } - } - ae_assert(ae_fp_greater_eq(v1,v0), "MinNS: integrity check failed", _state); - state->samplex.ptr.pp_double[i][j] = boundval(v0+(v1-v0)*hqrnduniformr(&state->agsrs, _state), v0, v1, _state); - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->samplex.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - minns_unscalepointbc(state, &state->x, _state); - minns_clearrequestfields(state, _state); - state->needfij = ae_true; - state->rstateags.stage = 2; - goto lbl_rcomm; -lbl_2: - state->needfij = ae_false; - minns_generatemeritfunction(state, i, _state); - k = k+1; - i = i+1; - goto lbl_8; -lbl_10: - cursamplesize = cursamplesize+k; - fullsample = cursamplesize==state->agssamplesize; - for(j=0; j<=cursamplesize-1; j++) - { - - /* - * For J-th element in gradient sample, process all of its components - * and modify them according to status of box constraints - */ - for(i=0; i<=n-1; i++) - { - ae_assert(!state->hasbndl.ptr.p_bool[i]||ae_fp_greater_eq(state->xc.ptr.p_double[i],state->scaledbndl.ptr.p_double[i]), "MinNS: integrity error", _state); - ae_assert(!state->hasbndu.ptr.p_bool[i]||ae_fp_less_eq(state->xc.ptr.p_double[i],state->scaledbndu.ptr.p_double[i]), "MinNS: integrity error", _state); - state->samplegmbc.ptr.pp_double[j][i] = state->samplegm.ptr.pp_double[j][i]; - if( (state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_eq(state->scaledbndl.ptr.p_double[i],state->scaledbndu.ptr.p_double[i]) ) - { - - /* - * I-th box constraint is of equality type (lower bound matches upper one). - * Simplest case, always active. - */ - state->samplegmbc.ptr.pp_double[j][i] = 0.0; - continue; - } - if( state->hasbndl.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->scaledbndl.ptr.p_double[i]) ) - { - - /* - * We are at lower bound. - * - * A bit more complex: - * * first, we have to activate/deactivate constraint depending on gradient at XC - * * second, in any case, I-th column of gradient sample must be non-positive - */ - if( ae_fp_greater_eq(state->samplegm.ptr.pp_double[0][i],0.0) ) - { - state->samplegmbc.ptr.pp_double[j][i] = 0.0; - } - state->samplegmbc.ptr.pp_double[j][i] = ae_minreal(state->samplegmbc.ptr.pp_double[j][i], 0.0, _state); - continue; - } - if( state->hasbndu.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->scaledbndu.ptr.p_double[i]) ) - { - - /* - * We are at upper bound. - * - * A bit more complex: - * * first, we have to activate/deactivate constraint depending on gradient at XC - * * second, in any case, I-th column of gradient sample must be non-negative - */ - if( ae_fp_less_eq(state->samplegm.ptr.pp_double[0][i],0.0) ) - { - state->samplegmbc.ptr.pp_double[j][i] = 0.0; - } - state->samplegmbc.ptr.pp_double[j][i] = ae_maxreal(state->samplegmbc.ptr.pp_double[j][i], 0.0, _state); - continue; - } - } - } - - /* - * Calculate diagonal Hessian. - * - * This Hessian serves two purposes: - * * first, it improves performance of gradient descent step - * * second, it improves condition number of QP subproblem - * solved to determine step - * - * The idea is that for each variable we check whether sample - * includes entries with alternating sign of gradient: - * * if gradients with different signs are present, Hessian - * component is set to M/R, where M is a maximum magnitude - * of corresponding gradient component, R is a sampling radius. - * Note that sign=0 and sign=1 are treated as different ones - * * if all gradients have same sign, Hessian component is - * set to M/R0, where R0 is initial sampling radius. - */ - for(j=0; j<=n-1; j++) - { - state->colmax.ptr.p_double[j] = 0.0; - state->signmin.ptr.p_double[j] = (double)(1); - state->signmax.ptr.p_double[j] = (double)(-1); - } - for(i=0; i<=cursamplesize-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = state->samplegmbc.ptr.pp_double[i][j]; - state->colmax.ptr.p_double[j] = ae_maxreal(state->colmax.ptr.p_double[j], ae_fabs(v, _state), _state); - state->signmin.ptr.p_double[j] = ae_minreal(state->signmin.ptr.p_double[j], (double)(ae_sign(v, _state)), _state); - state->signmax.ptr.p_double[j] = ae_maxreal(state->signmax.ptr.p_double[j], (double)(ae_sign(v, _state)), _state); - } - } - for(j=0; j<=n-1; j++) - { - if( ae_fp_neq(state->signmin.ptr.p_double[j],state->signmax.ptr.p_double[j]) ) - { - - /* - * Alternating signs of gradient - step is proportional to current sampling radius - */ - ae_assert(ae_fp_neq(state->colmax.ptr.p_double[j],(double)(0)), "MinNS: integrity check failed", _state); - ae_assert(ae_fp_neq(radius,(double)(0)), "MinNS: integrity check failed", _state); - state->diagh.ptr.p_double[j] = state->colmax.ptr.p_double[j]/radius; - continue; - } - if( ae_fp_neq(state->colmax.ptr.p_double[j],(double)(0)) ) - { - - /* - * Non-alternating sign of gradient, but non-zero. - * Step is proportional to initial sampling radius - */ - ae_assert(ae_fp_neq(radius0,(double)(0)), "MinNS: integrity check failed", _state); - state->diagh.ptr.p_double[j] = state->colmax.ptr.p_double[j]/radius0; - continue; - } - state->diagh.ptr.p_double[j] = (double)(1); - } - - /* - * PROJECTION PHASE - * - * We project zero vector on convex hull of gradient sample. - * If projection is small enough, we decrease radius and restart. - * Otherwise, this phase returns search direction in State.D. - * - * NOTE: because we use iterative solver, it may have trouble - * dealing with ill-conditioned problems. So we also employ - * second, backup test for stationarity - when too many - * subsequent backtracking searches resulted in short steps. - */ - minns_solveqp(&state->samplegmbc, &state->diagh, cursamplesize, n, &state->tmp0, &state->dbgncholesky, &state->nsqp, _state); - for(j=0; j<=n-1; j++) - { - state->d.ptr.p_double[j] = 0.0; - } - for(i=0; i<=cursamplesize-1; i++) - { - v = state->tmp0.ptr.p_double[i]; - ae_v_addd(&state->d.ptr.p_double[0], 1, &state->samplegmbc.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v); - } - v = 0.0; - for(j=0; j<=n-1; j++) - { - v = ae_maxreal(v, ae_fabs(state->d.ptr.p_double[j]/coalesce(state->colmax.ptr.p_double[j], 1.0, _state), _state), _state); - } - if( ae_fp_less_eq(v,state->agsstattold) ) - { - - /* - * Stationarity test succeded. - * Decrease radius and restart. - * - * NOTE: we also clear ShortStepsCnt on restart - */ - radius = radius*state->agsraddecay; - shortstepscnt = 0; - inc(&radiusdecays, _state); - inc(&state->repinneriterationscount, _state); - goto lbl_4; - } - for(i=0; i<=n-1; i++) - { - state->d.ptr.p_double[i] = -state->d.ptr.p_double[i]/state->diagh.ptr.p_double[i]; - } - - /* - * Perform backtracking line search. - * Update initial step length depending on search results. - * Here we assume that D is non-zero. - * - * NOTE: if AGSShortLimit subsequent line searches resulted - * in steps shorter than AGSStatTolStp, we decrease radius. - */ - dnrm = 0.0; - dg = 0.0; - for(i=0; i<=n-1; i++) - { - dnrm = dnrm+ae_sqr(state->d.ptr.p_double[i], _state); - dg = dg+state->d.ptr.p_double[i]*state->samplegmbc.ptr.pp_double[0][i]; - } - dnrm = ae_sqrt(dnrm, _state); - ae_assert(ae_fp_greater(dnrm,(double)(0)), "MinNS: integrity error", _state); - alpha = recommendedstep/dnrm; - alphadecreased = ae_false; - backtrackits = 0; - if( fullsample ) - { - maxbacktrackits = state->agsmaxbacktrack; - } - else - { - maxbacktrackits = state->agsmaxbacktracknonfull; - } -lbl_11: - if( ae_false ) - { - goto lbl_12; - } - - /* - * Prepare XN and evaluate merit function at XN - */ - ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_addd(&state->xn.ptr.p_double[0], 1, &state->d.ptr.p_double[0], 1, ae_v_len(0,n-1), alpha); - enforceboundaryconstraints(&state->xn, &state->scaledbndl, &state->hasbndl, &state->scaledbndu, &state->hasbndu, n, 0, _state); - ae_v_move(&state->samplex.ptr.pp_double[maxsamplesize][0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minns_unscalepointbc(state, &state->x, _state); - minns_clearrequestfields(state, _state); - state->needfij = ae_true; - state->rstateags.stage = 3; - goto lbl_rcomm; -lbl_3: - state->needfij = ae_false; - minns_generatemeritfunction(state, maxsamplesize, _state); - - /* - * Check sufficient decrease condition - */ - ae_assert(ae_fp_greater(dnrm,(double)(0)), "MinNS: integrity error", _state); - if( ae_fp_less_eq(state->samplef.ptr.p_double[maxsamplesize],state->samplef.ptr.p_double[0]+alpha*state->agsdecrease*dg) ) - { - goto lbl_12; - } - - /* - * Decrease Alpha - */ - alpha = alpha*state->agsalphadecay; - alphadecreased = ae_true; - - /* - * Update and check iterations counter. - */ - inc(&backtrackits, _state); - if( backtrackits>=maxbacktrackits ) - { - - /* - * Too many backtracking searches performed without success. - * Terminate iterations. - */ - alpha = 0.0; - alphadecreased = ae_true; - ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - goto lbl_12; - } - goto lbl_11; -lbl_12: - if( (ae_fp_less_eq(alpha*dnrm,state->agsshortstpabs)||ae_fp_less_eq(alpha*dnrm,state->agsshortstprel*radius))||ae_fp_less_eq(ae_fabs(state->samplef.ptr.p_double[0]-state->samplef.ptr.p_double[maxsamplesize], _state),state->agsshortf) ) - { - inc(&shortstepscnt, _state); - } - else - { - shortstepscnt = 0; - } - if( shortstepscnt>=state->agsshortlimit ) - { - - /* - * Too many subsequent short steps. - * - * It may be possible that optimizer is unable to find out - * that we have to decrease radius because of ill-conditioned - * gradients. - * - * Decrease radius and restart. - */ - radius = radius*state->agsraddecay; - shortstepscnt = 0; - inc(&radiusdecays, _state); - inc(&state->repinneriterationscount, _state); - goto lbl_4; - } - if( !alphadecreased ) - { - recommendedstep = recommendedstep*2.0; - } - if( alphadecreased&&fullsample ) - { - recommendedstep = recommendedstep*0.5; - } - - /* - * Next iteration - */ - ae_v_move(&state->xc.ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - inc(&state->repinneriterationscount, _state); - goto lbl_4; -lbl_5: - - /* - * Convert back from scaled to unscaled representation - */ - minns_unscalepointbc(state, &state->xc, _state); - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstateags.ia.ptr.p_int[0] = n; - state->rstateags.ia.ptr.p_int[1] = nec; - state->rstateags.ia.ptr.p_int[2] = nic; - state->rstateags.ia.ptr.p_int[3] = ng; - state->rstateags.ia.ptr.p_int[4] = nh; - state->rstateags.ia.ptr.p_int[5] = i; - state->rstateags.ia.ptr.p_int[6] = j; - state->rstateags.ia.ptr.p_int[7] = k; - state->rstateags.ia.ptr.p_int[8] = radiusdecays; - state->rstateags.ia.ptr.p_int[9] = maxsamplesize; - state->rstateags.ia.ptr.p_int[10] = cursamplesize; - state->rstateags.ia.ptr.p_int[11] = shortstepscnt; - state->rstateags.ia.ptr.p_int[12] = backtrackits; - state->rstateags.ia.ptr.p_int[13] = maxbacktrackits; - state->rstateags.ba.ptr.p_bool[0] = restartneeded; - state->rstateags.ba.ptr.p_bool[1] = b; - state->rstateags.ba.ptr.p_bool[2] = alphadecreased; - state->rstateags.ba.ptr.p_bool[3] = fullsample; - state->rstateags.ra.ptr.p_double[0] = radius0; - state->rstateags.ra.ptr.p_double[1] = radius; - state->rstateags.ra.ptr.p_double[2] = alpha; - state->rstateags.ra.ptr.p_double[3] = recommendedstep; - state->rstateags.ra.ptr.p_double[4] = dnrm; - state->rstateags.ra.ptr.p_double[5] = dg; - state->rstateags.ra.ptr.p_double[6] = v; - state->rstateags.ra.ptr.p_double[7] = vv; - state->rstateags.ra.ptr.p_double[8] = v0; - state->rstateags.ra.ptr.p_double[9] = v1; - return result; -} - - -/************************************************************************* -This function calculates merit function (target function + penalties for -violation of non-box constraints), using State.X (unscaled), State.Fi, -State.J (unscaled) and State.SampleX (scaled) as inputs. - -Results are loaded: -* target function value - to State.SampleF0[SampleIdx] -* merit function value - to State.SampleF[SampleIdx] -* gradient of merit function - to State.SampleGM[SampleIdx] - - -- ALGLIB -- - Copyright 02.06.2015 by Bochkanov Sergey -*************************************************************************/ -static void minns_generatemeritfunction(minnsstate* state, - ae_int_t sampleidx, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t nec; - ae_int_t nic; - ae_int_t ng; - ae_int_t nh; - double v; - double s; - - - n = state->n; - nec = state->nec; - nic = state->nic; - ng = state->ng; - nh = state->nh; - - /* - * Integrity check - */ - for(i=0; i<=n-1; i++) - { - ae_assert(!state->hasbndl.ptr.p_bool[i]||ae_fp_greater_eq(state->x.ptr.p_double[i],state->bndl.ptr.p_double[i]), "MinNS: integrity error", _state); - ae_assert(!state->hasbndu.ptr.p_bool[i]||ae_fp_less_eq(state->x.ptr.p_double[i],state->bndu.ptr.p_double[i]), "MinNS: integrity error", _state); - } - - /* - * Prepare "raw" function - */ - state->samplef.ptr.p_double[sampleidx] = state->fi.ptr.p_double[0]; - state->samplef0.ptr.p_double[sampleidx] = state->fi.ptr.p_double[0]; - for(j=0; j<=n-1; j++) - { - state->samplegm.ptr.pp_double[sampleidx][j] = state->j.ptr.pp_double[0][j]*state->s.ptr.p_double[j]; - } - - /* - * Modify merit function with linear constraints - */ - for(i=0; i<=nec+nic-1; i++) - { - v = -state->scaledcleic.ptr.pp_double[i][n]; - for(j=0; j<=n-1; j++) - { - v = v+state->scaledcleic.ptr.pp_double[i][j]*state->samplex.ptr.pp_double[sampleidx][j]; - } - if( i>=nec&&ae_fp_less(v,(double)(0)) ) - { - continue; - } - state->samplef.ptr.p_double[sampleidx] = state->samplef.ptr.p_double[sampleidx]+state->rholinear.ptr.p_double[i]*ae_fabs(v, _state); - s = (double)(ae_sign(v, _state)); - for(j=0; j<=n-1; j++) - { - state->samplegm.ptr.pp_double[sampleidx][j] = state->samplegm.ptr.pp_double[sampleidx][j]+state->rholinear.ptr.p_double[i]*s*state->scaledcleic.ptr.pp_double[i][j]; - } - } - - /* - * Modify merit function with nonlinear constraints - */ - for(i=1; i<=ng+nh; i++) - { - v = state->fi.ptr.p_double[i]; - if( i<=ng&&ae_fp_eq(v,(double)(0)) ) - { - continue; - } - if( i>ng&&ae_fp_less_eq(v,(double)(0)) ) - { - continue; - } - state->samplef.ptr.p_double[sampleidx] = state->samplef.ptr.p_double[sampleidx]+state->agsrhononlinear*ae_fabs(v, _state); - s = (double)(ae_sign(v, _state)); - for(j=0; j<=n-1; j++) - { - state->samplegm.ptr.pp_double[sampleidx][j] = state->samplegm.ptr.pp_double[sampleidx][j]+state->agsrhononlinear*s*state->j.ptr.pp_double[i][j]*state->s.ptr.p_double[j]; - } - } -} - - -/************************************************************************* -This function performs transformation of X from scaled coordinates to -unscaled ones, paying special attention to box constraints: -* points which were exactly at the boundary before scaling will be mapped - to corresponding boundary after scaling -* in any case, unscaled box constraints will be satisfied - - -- ALGLIB -- - Copyright 02.06.2015 by Bochkanov Sergey -*************************************************************************/ -static void minns_unscalepointbc(minnsstate* state, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=state->n-1; i++) - { - if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(x->ptr.p_double[i],state->scaledbndl.ptr.p_double[i]) ) - { - x->ptr.p_double[i] = state->bndl.ptr.p_double[i]; - continue; - } - if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(x->ptr.p_double[i],state->scaledbndu.ptr.p_double[i]) ) - { - x->ptr.p_double[i] = state->bndu.ptr.p_double[i]; - continue; - } - x->ptr.p_double[i] = x->ptr.p_double[i]*state->s.ptr.p_double[i]; - if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(x->ptr.p_double[i],state->bndl.ptr.p_double[i]) ) - { - x->ptr.p_double[i] = state->bndl.ptr.p_double[i]; - } - if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(x->ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - x->ptr.p_double[i] = state->bndu.ptr.p_double[i]; - } - } -} - - -/************************************************************************* -This function solves QP problem of the form - - [ ] - min [ 0.5*c'*(G*inv(H)*G')*c ] s.t. c[i]>=0, SUM(c[i])=1.0 - [ ] - -where G is stored in SampleG[] array, diagonal H is stored in DiagH[]. - -DbgNCholesky is incremented every time we perform Cholesky decomposition. - - -- ALGLIB -- - Copyright 02.06.2015 by Bochkanov Sergey -*************************************************************************/ -static void minns_solveqp(/* Real */ ae_matrix* sampleg, - /* Real */ ae_vector* diagh, - ae_int_t nsample, - ae_int_t nvars, - /* Real */ ae_vector* coeffs, - ae_int_t* dbgncholesky, - minnsqp* state, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double vv; - ae_int_t n; - ae_int_t idx0; - ae_int_t idx1; - ae_int_t ncandbnd; - ae_int_t innerits; - ae_int_t outerits; - double dnrm; - double stp; - double stpmax; - ae_int_t actidx; - double dtol; - ae_bool kickneeded; - double kicklength; - double lambdav; - double maxdiag; - ae_bool wasactivation; - ae_bool werechanges; - ae_int_t termcnt; - - - n = nsample; - - /* - * Allocate arrays, prepare data - */ - rvectorsetlengthatleast(coeffs, n, _state); - rvectorsetlengthatleast(&state->xc, n, _state); - rvectorsetlengthatleast(&state->xn, n, _state); - rvectorsetlengthatleast(&state->x0, n, _state); - rvectorsetlengthatleast(&state->gc, n, _state); - rvectorsetlengthatleast(&state->d, n, _state); - rmatrixsetlengthatleast(&state->uh, n, n, _state); - rmatrixsetlengthatleast(&state->ch, n, n, _state); - rmatrixsetlengthatleast(&state->rk, nsample, nvars, _state); - rvectorsetlengthatleast(&state->invutc, n, _state); - rvectorsetlengthatleast(&state->tmp0, n, _state); - bvectorsetlengthatleast(&state->tmpb, n, _state); - for(i=0; i<=n-1; i++) - { - state->xc.ptr.p_double[i] = 1.0/n; - coeffs->ptr.p_double[i] = 1.0/n; - } - for(i=0; i<=nsample-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - state->rk.ptr.pp_double[i][j] = sampleg->ptr.pp_double[i][j]/ae_sqrt(diagh->ptr.p_double[j], _state); - } - } - rmatrixsyrk(nsample, nvars, 1.0, &state->rk, 0, 0, 0, 0.0, &state->uh, 0, 0, ae_true, _state); - maxdiag = 0.0; - for(i=0; i<=nsample-1; i++) - { - maxdiag = ae_maxreal(maxdiag, state->uh.ptr.pp_double[i][i], _state); - } - maxdiag = coalesce(maxdiag, 1.0, _state); - - /* - * Main cycle: - */ - innerits = 0; - outerits = 0; - dtol = 1.0E5*ae_machineepsilon; - kicklength = ae_machineepsilon; - lambdav = 1.0E5*ae_machineepsilon; - termcnt = 0; - for(;;) - { - - /* - * Save current point to X0 - */ - ae_v_move(&state->x0.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - - /* - * Calculate gradient at initial point, solve NNLS problem - * to determine descent direction D subject to constraints. - * - * In order to do so we solve following constrained - * minimization problem: - * ( )^2 - * min ( SUM(lambda[i]*A[i]) + G ) - * ( ) - * Here: - * * G is a gradient (column vector) - * * A[i] is a column vector of I-th constraint - * * lambda[i] is a Lagrange multiplier corresponding to I-th constraint - * - * NOTE: all A[i] except for last one have only one element being set, - * so we rely on sparse capabilities of NNLS solver. However, - * in order to use these capabilities we have to reorder variables - * in such way that sparse ones come first. - * - * After finding lambda[] coefficients, we can find constrained descent - * direction by subtracting lambda[i]*A[i] from D=-G. We make use of the - * fact that first NCandBnd columns are just columns of identity matrix, - * so we can perform exact projection by explicitly setting elements of D - * to zeros. - */ - minns_qpcalculategradfunc(sampleg, diagh, nsample, nvars, &state->xc, &state->gc, &state->fc, &state->tmp0, _state); - ivectorsetlengthatleast(&state->tmpidx, n, _state); - rvectorsetlengthatleast(&state->tmpd, n, _state); - rmatrixsetlengthatleast(&state->tmpc2, n, 1, _state); - idx0 = 0; - ncandbnd = 0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_eq(state->xc.ptr.p_double[i],0.0) ) - { - ncandbnd = ncandbnd+1; - } - } - idx1 = ncandbnd; - for(i=0; i<=n-1; i++) - { - if( ae_fp_eq(state->xc.ptr.p_double[i],0.0) ) - { - - /* - * Candidate for activation of boundary constraint, - * comes first. - * - * NOTE: multiplication by -1 is due to the fact that - * it is lower bound, and has specific direction - * of constraint gradient. - */ - state->tmpidx.ptr.p_int[idx0] = i; - state->tmpd.ptr.p_double[idx0] = (-state->gc.ptr.p_double[i])*(-1); - state->tmpc2.ptr.pp_double[idx0][0] = 1.0*(-1); - idx0 = idx0+1; - } - else - { - - /* - * We are far away from boundary. - */ - state->tmpidx.ptr.p_int[idx1] = i; - state->tmpd.ptr.p_double[idx1] = -state->gc.ptr.p_double[i]; - state->tmpc2.ptr.pp_double[idx1][0] = 1.0; - idx1 = idx1+1; - } - } - ae_assert(idx0==ncandbnd, "MinNSQP: integrity check failed", _state); - ae_assert(idx1==n, "MinNSQP: integrity check failed", _state); - snnlsinit(n, 1, n, &state->nnls, _state); - snnlssetproblem(&state->nnls, &state->tmpc2, &state->tmpd, ncandbnd, 1, n, _state); - snnlsdropnnc(&state->nnls, ncandbnd, _state); - snnlssolve(&state->nnls, &state->tmplambdas, _state); - for(i=0; i<=n-1; i++) - { - state->d.ptr.p_double[i] = -state->gc.ptr.p_double[i]-state->tmplambdas.ptr.p_double[ncandbnd]; - } - for(i=0; i<=ncandbnd-1; i++) - { - if( ae_fp_greater(state->tmplambdas.ptr.p_double[i],(double)(0)) ) - { - state->d.ptr.p_double[state->tmpidx.ptr.p_int[i]] = 0.0; - } - } - - /* - * Additional stage to "polish" D (improve situation - * with sum-to-one constraint and boundary constraints) - * and to perform additional integrity check. - * - * After this stage we are pretty sure that: - * * if x[i]=0.0, then d[i]>=0.0 - * * if d[i]<0.0, then x[i]>0.0 - */ - v = 0.0; - vv = 0.0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_eq(state->xc.ptr.p_double[i],0.0)&&ae_fp_less(state->d.ptr.p_double[i],0.0) ) - { - state->d.ptr.p_double[i] = 0.0; - } - v = v+state->d.ptr.p_double[i]; - vv = ae_maxreal(vv, ae_fabs(state->gc.ptr.p_double[i], _state), _state); - } - ae_assert(ae_fp_less(ae_fabs(v, _state),1.0E5*ae_sqrt((double)(n), _state)*ae_machineepsilon*ae_maxreal(vv, 1.0, _state)), "MinNSQP: integrity check failed", _state); - - /* - * Decide whether we need "kick" stage: special stage - * that moves us away from boundary constraints which are - * not strictly active (i.e. such constraints that x[i]=0.0 and d[i]>0). - * - * If we need kick stage, we make a kick - and restart iteration. - * If not, after this block we can rely on the fact that - * for all x[i]=0.0 we have d[i]=0.0 - */ - kickneeded = ae_false; - for(i=0; i<=n-1; i++) - { - if( ae_fp_eq(state->xc.ptr.p_double[i],0.0)&&ae_fp_greater(state->d.ptr.p_double[i],0.0) ) - { - kickneeded = ae_true; - } - } - if( kickneeded ) - { - - /* - * Perform kick. - * Restart. - * Do not increase outer iterations counter. - */ - v = 0.0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_eq(state->xc.ptr.p_double[i],0.0)&&ae_fp_greater(state->d.ptr.p_double[i],0.0) ) - { - state->xc.ptr.p_double[i] = state->xc.ptr.p_double[i]+kicklength; - } - v = v+state->xc.ptr.p_double[i]; - } - ae_assert(ae_fp_greater(v,0.0), "MinNSQP: integrity check failed", _state); - for(i=0; i<=n-1; i++) - { - state->xc.ptr.p_double[i] = state->xc.ptr.p_double[i]/v; - } - inc(&innerits, _state); - continue; - } - - /* - * Calculate Cholesky decomposition of constrained Hessian - * for Newton phase. - */ - for(;;) - { - for(i=0; i<=n-1; i++) - { - - /* - * Diagonal element - */ - if( ae_fp_greater(state->xc.ptr.p_double[i],0.0) ) - { - state->ch.ptr.pp_double[i][i] = state->uh.ptr.pp_double[i][i]+lambdav*maxdiag; - } - else - { - state->ch.ptr.pp_double[i][i] = 1.0; - } - - /* - * Offdiagonal elements - */ - for(j=i+1; j<=n-1; j++) - { - if( ae_fp_greater(state->xc.ptr.p_double[i],0.0)&&ae_fp_greater(state->xc.ptr.p_double[j],0.0) ) - { - state->ch.ptr.pp_double[i][j] = state->uh.ptr.pp_double[i][j]; - } - else - { - state->ch.ptr.pp_double[i][j] = 0.0; - } - } - } - inc(dbgncholesky, _state); - if( !spdmatrixcholeskyrec(&state->ch, 0, n, ae_true, &state->tmp0, _state) ) - { - - /* - * Cholesky decomposition failed. - * Increase LambdaV and repeat iteration. - * Do not increase outer iterations counter. - */ - lambdav = lambdav*10; - continue; - } - break; - } - - /* - * Newton phase - */ - for(;;) - { - - /* - * Calculate constrained (equality and sum-to-one) descent direction D. - * - * Here we use Sherman-Morrison update to calculate direction subject to - * sum-to-one constraint. - */ - minns_qpcalculategradfunc(sampleg, diagh, nsample, nvars, &state->xc, &state->gc, &state->fc, &state->tmp0, _state); - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(state->xc.ptr.p_double[i],0.0) ) - { - state->invutc.ptr.p_double[i] = 1.0; - state->d.ptr.p_double[i] = -state->gc.ptr.p_double[i]; - } - else - { - state->invutc.ptr.p_double[i] = 0.0; - state->d.ptr.p_double[i] = 0.0; - } - } - minns_qpsolveut(&state->ch, n, &state->invutc, _state); - minns_qpsolveut(&state->ch, n, &state->d, _state); - v = 0.0; - vv = 0.0; - for(i=0; i<=n-1; i++) - { - vv = vv+ae_sqr(state->invutc.ptr.p_double[i], _state); - v = v+state->invutc.ptr.p_double[i]*state->d.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - state->d.ptr.p_double[i] = state->d.ptr.p_double[i]-v/vv*state->invutc.ptr.p_double[i]; - } - minns_qpsolveu(&state->ch, n, &state->d, _state); - v = 0.0; - k = 0; - for(i=0; i<=n-1; i++) - { - v = v+state->d.ptr.p_double[i]; - if( ae_fp_neq(state->d.ptr.p_double[i],0.0) ) - { - k = k+1; - } - } - if( k>0&&ae_fp_greater(v,0.0) ) - { - vv = v/k; - for(i=0; i<=n-1; i++) - { - if( ae_fp_neq(state->d.ptr.p_double[i],0.0) ) - { - state->d.ptr.p_double[i] = state->d.ptr.p_double[i]-vv; - } - } - } - - /* - * Calculate length of D, maximum step and component which is - * activated by this step. - * - * Break if D is exactly zero. We do not break here if DNrm is - * small - this check is performed later. It is important to - * perform last step with nearly-zero D, it allows us to have - * extra-precision in solution which is often needed for convergence - * of AGS algorithm. - */ - dnrm = 0.0; - for(i=0; i<=n-1; i++) - { - dnrm = dnrm+ae_sqr(state->d.ptr.p_double[i], _state); - } - dnrm = ae_sqrt(dnrm, _state); - actidx = -1; - stpmax = 1.0E50; - for(i=0; i<=n-1; i++) - { - if( ae_fp_less(state->d.ptr.p_double[i],0.0) ) - { - v = stpmax; - stpmax = safeminposrv(state->xc.ptr.p_double[i], -state->d.ptr.p_double[i], stpmax, _state); - if( ae_fp_less(stpmax,v) ) - { - actidx = i; - } - } - } - if( ae_fp_eq(dnrm,0.0) ) - { - break; - } - - /* - * Calculate trial function value at unconstrained full step. - * If trial value is greater or equal to FC, terminate iterations. - */ - for(i=0; i<=n-1; i++) - { - state->xn.ptr.p_double[i] = state->xc.ptr.p_double[i]+1.0*state->d.ptr.p_double[i]; - } - minns_qpcalculatefunc(sampleg, diagh, nsample, nvars, &state->xn, &state->fn, &state->tmp0, _state); - if( ae_fp_greater_eq(state->fn,state->fc) ) - { - break; - } - - /* - * Perform step - * Update Hessian - * Update XC - * - * Break if: - * a) no constraint was activated - * b) norm of D is small enough - */ - stp = ae_minreal(1.0, stpmax, _state); - for(i=0; i<=n-1; i++) - { - state->xn.ptr.p_double[i] = ae_maxreal(state->xc.ptr.p_double[i]+stp*state->d.ptr.p_double[i], 0.0, _state); - } - if( ae_fp_eq(stp,stpmax)&&actidx>=0 ) - { - state->xn.ptr.p_double[actidx] = 0.0; - } - wasactivation = ae_false; - for(i=0; i<=n-1; i++) - { - state->tmpb.ptr.p_bool[i] = ae_fp_eq(state->xn.ptr.p_double[i],0.0)&&ae_fp_neq(state->xc.ptr.p_double[i],0.0); - wasactivation = wasactivation||state->tmpb.ptr.p_bool[i]; - } - ae_v_move(&state->xc.ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( !wasactivation ) - { - break; - } - if( ae_fp_less_eq(dnrm,dtol) ) - { - break; - } - spdmatrixcholeskyupdatefixbuf(&state->ch, n, ae_true, &state->tmpb, &state->tmp0, _state); - } - - /* - * Compare status of boundary constraints - if nothing changed during - * last outer iteration, TermCnt is increased. Otherwise it is reset - * to zero. - * - * When TermCnt is large enough, we terminate algorithm. - */ - werechanges = ae_false; - for(i=0; i<=n-1; i++) - { - werechanges = werechanges||ae_sign(state->x0.ptr.p_double[i], _state)!=ae_sign(state->xc.ptr.p_double[i], _state); - } - if( !werechanges ) - { - inc(&termcnt, _state); - } - else - { - termcnt = 0; - } - if( termcnt>=2 ) - { - break; - } - - /* - * Increase number of outer iterations. - * Break if we performed too many. - */ - inc(&outerits, _state); - if( outerits==10 ) - { - break; - } - } - - /* - * Store result - */ - for(i=0; i<=n-1; i++) - { - coeffs->ptr.p_double[i] = state->xc.ptr.p_double[i]; - } -} - - -/************************************************************************* -Function/gradient calculation for QP solver. - - -- ALGLIB -- - Copyright 02.06.2015 by Bochkanov Sergey -*************************************************************************/ -static void minns_qpcalculategradfunc(/* Real */ ae_matrix* sampleg, - /* Real */ ae_vector* diagh, - ae_int_t nsample, - ae_int_t nvars, - /* Real */ ae_vector* coeffs, - /* Real */ ae_vector* g, - double* f, - /* Real */ ae_vector* tmp, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - - *f = 0; - - rvectorsetlengthatleast(g, nsample, _state); - rvectorsetlengthatleast(tmp, nvars, _state); - - /* - * Calculate GS*p - */ - for(j=0; j<=nvars-1; j++) - { - tmp->ptr.p_double[j] = 0.0; - } - for(i=0; i<=nsample-1; i++) - { - v = coeffs->ptr.p_double[i]; - ae_v_addd(&tmp->ptr.p_double[0], 1, &sampleg->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1), v); - } - - /* - * Calculate F - */ - *f = 0.0; - for(i=0; i<=nvars-1; i++) - { - *f = *f+0.5*ae_sqr(tmp->ptr.p_double[i], _state)/diagh->ptr.p_double[i]; - } - - /* - * Multiply by inverse Hessian - */ - for(i=0; i<=nvars-1; i++) - { - tmp->ptr.p_double[i] = tmp->ptr.p_double[i]/diagh->ptr.p_double[i]; - } - - /* - * Function gradient - */ - for(i=0; i<=nsample-1; i++) - { - v = ae_v_dotproduct(&sampleg->ptr.pp_double[i][0], 1, &tmp->ptr.p_double[0], 1, ae_v_len(0,nvars-1)); - g->ptr.p_double[i] = v; - } -} - - -/************************************************************************* -Function calculation for QP solver. - - -- ALGLIB -- - Copyright 02.06.2015 by Bochkanov Sergey -*************************************************************************/ -static void minns_qpcalculatefunc(/* Real */ ae_matrix* sampleg, - /* Real */ ae_vector* diagh, - ae_int_t nsample, - ae_int_t nvars, - /* Real */ ae_vector* coeffs, - double* f, - /* Real */ ae_vector* tmp, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - - *f = 0; - - rvectorsetlengthatleast(tmp, nvars, _state); - - /* - * Calculate GS*p - */ - for(j=0; j<=nvars-1; j++) - { - tmp->ptr.p_double[j] = 0.0; - } - for(i=0; i<=nsample-1; i++) - { - v = coeffs->ptr.p_double[i]; - ae_v_addd(&tmp->ptr.p_double[0], 1, &sampleg->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1), v); - } - - /* - * Calculate F - */ - *f = 0.0; - for(i=0; i<=nvars-1; i++) - { - *f = *f+0.5*ae_sqr(tmp->ptr.p_double[i], _state)/diagh->ptr.p_double[i]; - } -} - - -/************************************************************************* -Triangular solver for QP solver. - - -- ALGLIB -- - Copyright 02.06.2015 by Bochkanov Sergey -*************************************************************************/ -static void minns_qpsolveu(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - - - - /* - * A^(-1)*X - */ - for(i=n-1; i>=0; i--) - { - v = x->ptr.p_double[i]; - for(j=i+1; j<=n-1; j++) - { - v = v-a->ptr.pp_double[i][j]*x->ptr.p_double[j]; - } - x->ptr.p_double[i] = v/a->ptr.pp_double[i][i]; - } -} - - -/************************************************************************* -Triangular solver for QP solver. - - -- ALGLIB -- - Copyright 02.06.2015 by Bochkanov Sergey -*************************************************************************/ -static void minns_qpsolveut(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - - - - /* - * A^(-T)*X - */ - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = x->ptr.p_double[i]/a->ptr.pp_double[i][i]; - v = x->ptr.p_double[i]; - for(j=i+1; j<=n-1; j++) - { - x->ptr.p_double[j] = x->ptr.p_double[j]-a->ptr.pp_double[i][j]*v; - } - } -} - - -void _minnsqp_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minnsqp *p = (minnsqp*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->xc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xn, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->x0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->gc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->uh, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->ch, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->rk, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->invutc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpidx, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->tmpd, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmplambdas, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->tmpc2, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpb, 0, DT_BOOL, _state, make_automatic); - _snnlssolver_init(&p->nnls, _state, make_automatic); -} - - -void _minnsqp_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minnsqp *dst = (minnsqp*)_dst; - minnsqp *src = (minnsqp*)_src; - dst->fc = src->fc; - dst->fn = src->fn; - ae_vector_init_copy(&dst->xc, &src->xc, _state, make_automatic); - ae_vector_init_copy(&dst->xn, &src->xn, _state, make_automatic); - ae_vector_init_copy(&dst->x0, &src->x0, _state, make_automatic); - ae_vector_init_copy(&dst->gc, &src->gc, _state, make_automatic); - ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic); - ae_matrix_init_copy(&dst->uh, &src->uh, _state, make_automatic); - ae_matrix_init_copy(&dst->ch, &src->ch, _state, make_automatic); - ae_matrix_init_copy(&dst->rk, &src->rk, _state, make_automatic); - ae_vector_init_copy(&dst->invutc, &src->invutc, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->tmpidx, &src->tmpidx, _state, make_automatic); - ae_vector_init_copy(&dst->tmpd, &src->tmpd, _state, make_automatic); - ae_vector_init_copy(&dst->tmpc, &src->tmpc, _state, make_automatic); - ae_vector_init_copy(&dst->tmplambdas, &src->tmplambdas, _state, make_automatic); - ae_matrix_init_copy(&dst->tmpc2, &src->tmpc2, _state, make_automatic); - ae_vector_init_copy(&dst->tmpb, &src->tmpb, _state, make_automatic); - _snnlssolver_init_copy(&dst->nnls, &src->nnls, _state, make_automatic); -} - - -void _minnsqp_clear(void* _p) -{ - minnsqp *p = (minnsqp*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->xc); - ae_vector_clear(&p->xn); - ae_vector_clear(&p->x0); - ae_vector_clear(&p->gc); - ae_vector_clear(&p->d); - ae_matrix_clear(&p->uh); - ae_matrix_clear(&p->ch); - ae_matrix_clear(&p->rk); - ae_vector_clear(&p->invutc); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->tmpidx); - ae_vector_clear(&p->tmpd); - ae_vector_clear(&p->tmpc); - ae_vector_clear(&p->tmplambdas); - ae_matrix_clear(&p->tmpc2); - ae_vector_clear(&p->tmpb); - _snnlssolver_clear(&p->nnls); -} - - -void _minnsqp_destroy(void* _p) -{ - minnsqp *p = (minnsqp*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->xc); - ae_vector_destroy(&p->xn); - ae_vector_destroy(&p->x0); - ae_vector_destroy(&p->gc); - ae_vector_destroy(&p->d); - ae_matrix_destroy(&p->uh); - ae_matrix_destroy(&p->ch); - ae_matrix_destroy(&p->rk); - ae_vector_destroy(&p->invutc); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->tmpidx); - ae_vector_destroy(&p->tmpd); - ae_vector_destroy(&p->tmpc); - ae_vector_destroy(&p->tmplambdas); - ae_matrix_destroy(&p->tmpc2); - ae_vector_destroy(&p->tmpb); - _snnlssolver_destroy(&p->nnls); -} - - -void _minnsstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minnsstate *p = (minnsstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->hasbndl, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->hasbndu, 0, DT_BOOL, _state, make_automatic); - ae_matrix_init(&p->cleic, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fi, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->j, 0, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); - _rcommstate_init(&p->rstateags, _state, make_automatic); - _hqrndstate_init(&p->agsrs, _state, make_automatic); - ae_vector_init(&p->xstart, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xn, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->grs, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->colmax, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->diagh, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->signmin, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->signmax, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->scaledbndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->scaledbndu, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->scaledcleic, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rholinear, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->samplex, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->samplegm, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->samplegmbc, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->samplef, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->samplef0, 0, DT_REAL, _state, make_automatic); - _minnsqp_init(&p->nsqp, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->tmp2, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp3, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->xbase, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fp, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fm, 0, DT_REAL, _state, make_automatic); -} - - -void _minnsstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minnsstate *dst = (minnsstate*)_dst; - minnsstate *src = (minnsstate*)_src; - dst->solvertype = src->solvertype; - dst->n = src->n; - dst->epsx = src->epsx; - dst->maxits = src->maxits; - dst->xrep = src->xrep; - dst->diffstep = src->diffstep; - ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic); - ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic); - ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic); - ae_vector_init_copy(&dst->hasbndl, &src->hasbndl, _state, make_automatic); - ae_vector_init_copy(&dst->hasbndu, &src->hasbndu, _state, make_automatic); - dst->nec = src->nec; - dst->nic = src->nic; - ae_matrix_init_copy(&dst->cleic, &src->cleic, _state, make_automatic); - dst->ng = src->ng; - dst->nh = src->nh; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - dst->f = src->f; - ae_vector_init_copy(&dst->fi, &src->fi, _state, make_automatic); - ae_matrix_init_copy(&dst->j, &src->j, _state, make_automatic); - dst->needfij = src->needfij; - dst->needfi = src->needfi; - dst->xupdated = src->xupdated; - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); - _rcommstate_init_copy(&dst->rstateags, &src->rstateags, _state, make_automatic); - _hqrndstate_init_copy(&dst->agsrs, &src->agsrs, _state, make_automatic); - dst->agsradius = src->agsradius; - dst->agssamplesize = src->agssamplesize; - dst->agsraddecay = src->agsraddecay; - dst->agsalphadecay = src->agsalphadecay; - dst->agsdecrease = src->agsdecrease; - dst->agsinitstp = src->agsinitstp; - dst->agsstattold = src->agsstattold; - dst->agsshortstpabs = src->agsshortstpabs; - dst->agsshortstprel = src->agsshortstprel; - dst->agsshortf = src->agsshortf; - dst->agsshortlimit = src->agsshortlimit; - dst->agsrhononlinear = src->agsrhononlinear; - dst->agsminupdate = src->agsminupdate; - dst->agsmaxraddecays = src->agsmaxraddecays; - dst->agsmaxbacktrack = src->agsmaxbacktrack; - dst->agsmaxbacktracknonfull = src->agsmaxbacktracknonfull; - dst->agspenaltylevel = src->agspenaltylevel; - dst->agspenaltyincrease = src->agspenaltyincrease; - ae_vector_init_copy(&dst->xstart, &src->xstart, _state, make_automatic); - ae_vector_init_copy(&dst->xc, &src->xc, _state, make_automatic); - ae_vector_init_copy(&dst->xn, &src->xn, _state, make_automatic); - ae_vector_init_copy(&dst->grs, &src->grs, _state, make_automatic); - ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic); - ae_vector_init_copy(&dst->colmax, &src->colmax, _state, make_automatic); - ae_vector_init_copy(&dst->diagh, &src->diagh, _state, make_automatic); - ae_vector_init_copy(&dst->signmin, &src->signmin, _state, make_automatic); - ae_vector_init_copy(&dst->signmax, &src->signmax, _state, make_automatic); - dst->userterminationneeded = src->userterminationneeded; - ae_vector_init_copy(&dst->scaledbndl, &src->scaledbndl, _state, make_automatic); - ae_vector_init_copy(&dst->scaledbndu, &src->scaledbndu, _state, make_automatic); - ae_matrix_init_copy(&dst->scaledcleic, &src->scaledcleic, _state, make_automatic); - ae_vector_init_copy(&dst->rholinear, &src->rholinear, _state, make_automatic); - ae_matrix_init_copy(&dst->samplex, &src->samplex, _state, make_automatic); - ae_matrix_init_copy(&dst->samplegm, &src->samplegm, _state, make_automatic); - ae_matrix_init_copy(&dst->samplegmbc, &src->samplegmbc, _state, make_automatic); - ae_vector_init_copy(&dst->samplef, &src->samplef, _state, make_automatic); - ae_vector_init_copy(&dst->samplef0, &src->samplef0, _state, make_automatic); - _minnsqp_init_copy(&dst->nsqp, &src->nsqp, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic); - ae_matrix_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic); - ae_vector_init_copy(&dst->tmp3, &src->tmp3, _state, make_automatic); - ae_vector_init_copy(&dst->xbase, &src->xbase, _state, make_automatic); - ae_vector_init_copy(&dst->fp, &src->fp, _state, make_automatic); - ae_vector_init_copy(&dst->fm, &src->fm, _state, make_automatic); - dst->repinneriterationscount = src->repinneriterationscount; - dst->repouteriterationscount = src->repouteriterationscount; - dst->repnfev = src->repnfev; - dst->repvaridx = src->repvaridx; - dst->repfuncidx = src->repfuncidx; - dst->repterminationtype = src->repterminationtype; - dst->replcerr = src->replcerr; - dst->repnlcerr = src->repnlcerr; - dst->dbgncholesky = src->dbgncholesky; -} - - -void _minnsstate_clear(void* _p) -{ - minnsstate *p = (minnsstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->s); - ae_vector_clear(&p->bndl); - ae_vector_clear(&p->bndu); - ae_vector_clear(&p->hasbndl); - ae_vector_clear(&p->hasbndu); - ae_matrix_clear(&p->cleic); - ae_vector_clear(&p->x); - ae_vector_clear(&p->fi); - ae_matrix_clear(&p->j); - _rcommstate_clear(&p->rstate); - _rcommstate_clear(&p->rstateags); - _hqrndstate_clear(&p->agsrs); - ae_vector_clear(&p->xstart); - ae_vector_clear(&p->xc); - ae_vector_clear(&p->xn); - ae_vector_clear(&p->grs); - ae_vector_clear(&p->d); - ae_vector_clear(&p->colmax); - ae_vector_clear(&p->diagh); - ae_vector_clear(&p->signmin); - ae_vector_clear(&p->signmax); - ae_vector_clear(&p->scaledbndl); - ae_vector_clear(&p->scaledbndu); - ae_matrix_clear(&p->scaledcleic); - ae_vector_clear(&p->rholinear); - ae_matrix_clear(&p->samplex); - ae_matrix_clear(&p->samplegm); - ae_matrix_clear(&p->samplegmbc); - ae_vector_clear(&p->samplef); - ae_vector_clear(&p->samplef0); - _minnsqp_clear(&p->nsqp); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->tmp1); - ae_matrix_clear(&p->tmp2); - ae_vector_clear(&p->tmp3); - ae_vector_clear(&p->xbase); - ae_vector_clear(&p->fp); - ae_vector_clear(&p->fm); -} - - -void _minnsstate_destroy(void* _p) -{ - minnsstate *p = (minnsstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->s); - ae_vector_destroy(&p->bndl); - ae_vector_destroy(&p->bndu); - ae_vector_destroy(&p->hasbndl); - ae_vector_destroy(&p->hasbndu); - ae_matrix_destroy(&p->cleic); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->fi); - ae_matrix_destroy(&p->j); - _rcommstate_destroy(&p->rstate); - _rcommstate_destroy(&p->rstateags); - _hqrndstate_destroy(&p->agsrs); - ae_vector_destroy(&p->xstart); - ae_vector_destroy(&p->xc); - ae_vector_destroy(&p->xn); - ae_vector_destroy(&p->grs); - ae_vector_destroy(&p->d); - ae_vector_destroy(&p->colmax); - ae_vector_destroy(&p->diagh); - ae_vector_destroy(&p->signmin); - ae_vector_destroy(&p->signmax); - ae_vector_destroy(&p->scaledbndl); - ae_vector_destroy(&p->scaledbndu); - ae_matrix_destroy(&p->scaledcleic); - ae_vector_destroy(&p->rholinear); - ae_matrix_destroy(&p->samplex); - ae_matrix_destroy(&p->samplegm); - ae_matrix_destroy(&p->samplegmbc); - ae_vector_destroy(&p->samplef); - ae_vector_destroy(&p->samplef0); - _minnsqp_destroy(&p->nsqp); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->tmp1); - ae_matrix_destroy(&p->tmp2); - ae_vector_destroy(&p->tmp3); - ae_vector_destroy(&p->xbase); - ae_vector_destroy(&p->fp); - ae_vector_destroy(&p->fm); -} - - -void _minnsreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minnsreport *p = (minnsreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _minnsreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minnsreport *dst = (minnsreport*)_dst; - minnsreport *src = (minnsreport*)_src; - dst->iterationscount = src->iterationscount; - dst->nfev = src->nfev; - dst->cerr = src->cerr; - dst->lcerr = src->lcerr; - dst->nlcerr = src->nlcerr; - dst->terminationtype = src->terminationtype; - dst->varidx = src->varidx; - dst->funcidx = src->funcidx; -} - - -void _minnsreport_clear(void* _p) -{ - minnsreport *p = (minnsreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _minnsreport_destroy(void* _p) -{ - minnsreport *p = (minnsreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_MINCOMP) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Obsolete function, use MinLBFGSSetPrecDefault() instead. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetdefaultpreconditioner(minlbfgsstate* state, - ae_state *_state) -{ - - - minlbfgssetprecdefault(state, _state); -} - - -/************************************************************************* -Obsolete function, use MinLBFGSSetCholeskyPreconditioner() instead. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetcholeskypreconditioner(minlbfgsstate* state, - /* Real */ ae_matrix* p, - ae_bool isupper, - ae_state *_state) -{ - - - minlbfgssetpreccholesky(state, p, isupper, _state); -} - - -/************************************************************************* -This is obsolete function which was used by previous version of the BLEIC -optimizer. It does nothing in the current version of BLEIC. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetbarrierwidth(minbleicstate* state, - double mu, - ae_state *_state) -{ - - -} - - -/************************************************************************* -This is obsolete function which was used by previous version of the BLEIC -optimizer. It does nothing in the current version of BLEIC. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetbarrierdecay(minbleicstate* state, - double mudecay, - ae_state *_state) -{ - - -} - - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 25.03.2010 by Bochkanov Sergey -*************************************************************************/ -void minasacreate(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - minasastate* state, - ae_state *_state) -{ - ae_int_t i; - - _minasastate_clear(state); - - ae_assert(n>=1, "MinASA: N too small!", _state); - ae_assert(x->cnt>=n, "MinCGCreate: Length(X)cnt>=n, "MinCGCreate: Length(BndL)cnt>=n, "MinCGCreate: Length(BndU)ptr.p_double[i],bndu->ptr.p_double[i]), "MinASA: inconsistent bounds!", _state); - ae_assert(ae_fp_less_eq(bndl->ptr.p_double[i],x->ptr.p_double[i]), "MinASA: infeasible X!", _state); - ae_assert(ae_fp_less_eq(x->ptr.p_double[i],bndu->ptr.p_double[i]), "MinASA: infeasible X!", _state); - } - - /* - * Initialize - */ - state->n = n; - minasasetcond(state, (double)(0), (double)(0), (double)(0), 0, _state); - minasasetxrep(state, ae_false, _state); - minasasetstpmax(state, (double)(0), _state); - minasasetalgorithm(state, -1, _state); - ae_vector_set_length(&state->bndl, n, _state); - ae_vector_set_length(&state->bndu, n, _state); - ae_vector_set_length(&state->ak, n, _state); - ae_vector_set_length(&state->xk, n, _state); - ae_vector_set_length(&state->dk, n, _state); - ae_vector_set_length(&state->an, n, _state); - ae_vector_set_length(&state->xn, n, _state); - ae_vector_set_length(&state->dn, n, _state); - ae_vector_set_length(&state->x, n, _state); - ae_vector_set_length(&state->d, n, _state); - ae_vector_set_length(&state->g, n, _state); - ae_vector_set_length(&state->gc, n, _state); - ae_vector_set_length(&state->work, n, _state); - ae_vector_set_length(&state->yk, n, _state); - minasarestartfrom(state, x, bndl, bndu, _state); -} - - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minasasetcond(minasastate* state, - double epsg, - double epsf, - double epsx, - ae_int_t maxits, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(epsg, _state), "MinASASetCond: EpsG is not finite number!", _state); - ae_assert(ae_fp_greater_eq(epsg,(double)(0)), "MinASASetCond: negative EpsG!", _state); - ae_assert(ae_isfinite(epsf, _state), "MinASASetCond: EpsF is not finite number!", _state); - ae_assert(ae_fp_greater_eq(epsf,(double)(0)), "MinASASetCond: negative EpsF!", _state); - ae_assert(ae_isfinite(epsx, _state), "MinASASetCond: EpsX is not finite number!", _state); - ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinASASetCond: negative EpsX!", _state); - ae_assert(maxits>=0, "MinASASetCond: negative MaxIts!", _state); - if( ((ae_fp_eq(epsg,(double)(0))&&ae_fp_eq(epsf,(double)(0)))&&ae_fp_eq(epsx,(double)(0)))&&maxits==0 ) - { - epsx = 1.0E-6; - } - state->epsg = epsg; - state->epsf = epsf; - state->epsx = epsx; - state->maxits = maxits; -} - - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minasasetxrep(minasastate* state, ae_bool needxrep, ae_state *_state) -{ - - - state->xrep = needxrep; -} - - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minasasetalgorithm(minasastate* state, - ae_int_t algotype, - ae_state *_state) -{ - - - ae_assert(algotype>=-1&&algotype<=1, "MinASASetAlgorithm: incorrect AlgoType!", _state); - if( algotype==-1 ) - { - algotype = 1; - } - state->cgtype = algotype; -} - - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minasasetstpmax(minasastate* state, double stpmax, ae_state *_state) -{ - - - ae_assert(ae_isfinite(stpmax, _state), "MinASASetStpMax: StpMax is not finite!", _state); - ae_assert(ae_fp_greater_eq(stpmax,(double)(0)), "MinASASetStpMax: StpMax<0!", _state); - state->stpmax = stpmax; -} - - -/************************************************************************* - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -ae_bool minasaiteration(minasastate* state, ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - double betak; - double v; - double vv; - ae_int_t mcinfo; - ae_bool b; - ae_bool stepfound; - ae_int_t diffcnt; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - n = state->rstate.ia.ptr.p_int[0]; - i = state->rstate.ia.ptr.p_int[1]; - mcinfo = state->rstate.ia.ptr.p_int[2]; - diffcnt = state->rstate.ia.ptr.p_int[3]; - b = state->rstate.ba.ptr.p_bool[0]; - stepfound = state->rstate.ba.ptr.p_bool[1]; - betak = state->rstate.ra.ptr.p_double[0]; - v = state->rstate.ra.ptr.p_double[1]; - vv = state->rstate.ra.ptr.p_double[2]; - } - else - { - n = 359; - i = -58; - mcinfo = -919; - diffcnt = -909; - b = ae_true; - stepfound = ae_true; - betak = 74; - v = -788; - vv = 809; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - if( state->rstate.stage==1 ) - { - goto lbl_1; - } - if( state->rstate.stage==2 ) - { - goto lbl_2; - } - if( state->rstate.stage==3 ) - { - goto lbl_3; - } - if( state->rstate.stage==4 ) - { - goto lbl_4; - } - if( state->rstate.stage==5 ) - { - goto lbl_5; - } - if( state->rstate.stage==6 ) - { - goto lbl_6; - } - if( state->rstate.stage==7 ) - { - goto lbl_7; - } - if( state->rstate.stage==8 ) - { - goto lbl_8; - } - if( state->rstate.stage==9 ) - { - goto lbl_9; - } - if( state->rstate.stage==10 ) - { - goto lbl_10; - } - if( state->rstate.stage==11 ) - { - goto lbl_11; - } - if( state->rstate.stage==12 ) - { - goto lbl_12; - } - if( state->rstate.stage==13 ) - { - goto lbl_13; - } - if( state->rstate.stage==14 ) - { - goto lbl_14; - } - - /* - * Routine body - */ - - /* - * Prepare - */ - n = state->n; - state->repterminationtype = 0; - state->repiterationscount = 0; - state->repnfev = 0; - state->debugrestartscount = 0; - state->cgtype = 1; - ae_v_move(&state->xk.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - if( ae_fp_eq(state->xk.ptr.p_double[i],state->bndl.ptr.p_double[i])||ae_fp_eq(state->xk.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->ak.ptr.p_double[i] = (double)(0); - } - else - { - state->ak.ptr.p_double[i] = (double)(1); - } - } - state->mu = 0.1; - state->curalgo = 0; - - /* - * Calculate F/G, initialize algorithm - */ - mincomp_clearrequestfields(state, _state); - state->needfg = ae_true; - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - state->needfg = ae_false; - if( !state->xrep ) - { - goto lbl_15; - } - - /* - * progress report - */ - mincomp_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 1; - goto lbl_rcomm; -lbl_1: - state->xupdated = ae_false; -lbl_15: - if( ae_fp_less_eq(mincomp_asaboundedantigradnorm(state, _state),state->epsg) ) - { - state->repterminationtype = 4; - result = ae_false; - return result; - } - state->repnfev = state->repnfev+1; - - /* - * Main cycle - * - * At the beginning of new iteration: - * * CurAlgo stores current algorithm selector - * * State.XK, State.F and State.G store current X/F/G - * * State.AK stores current set of active constraints - */ -lbl_17: - if( ae_false ) - { - goto lbl_18; - } - - /* - * GPA algorithm - */ - if( state->curalgo!=0 ) - { - goto lbl_19; - } - state->k = 0; - state->acount = 0; -lbl_21: - if( ae_false ) - { - goto lbl_22; - } - - /* - * Determine Dk = proj(xk - gk)-xk - */ - for(i=0; i<=n-1; i++) - { - state->d.ptr.p_double[i] = boundval(state->xk.ptr.p_double[i]-state->g.ptr.p_double[i], state->bndl.ptr.p_double[i], state->bndu.ptr.p_double[i], _state)-state->xk.ptr.p_double[i]; - } - - /* - * Armijo line search. - * * exact search with alpha=1 is tried first, - * 'exact' means that we evaluate f() EXACTLY at - * bound(x-g,bndl,bndu), without intermediate floating - * point operations. - * * alpha<1 are tried if explicit search wasn't successful - * Result is placed into XN. - * - * Two types of search are needed because we can't - * just use second type with alpha=1 because in finite - * precision arithmetics (x1-x0)+x0 may differ from x1. - * So while x1 is correctly bounded (it lie EXACTLY on - * boundary, if it is active), (x1-x0)+x0 may be - * not bounded. - */ - v = ae_v_dotproduct(&state->d.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->dginit = v; - state->finit = state->f; - if( !(ae_fp_less_eq(mincomp_asad1norm(state, _state),state->stpmax)||ae_fp_eq(state->stpmax,(double)(0))) ) - { - goto lbl_23; - } - - /* - * Try alpha=1 step first - */ - for(i=0; i<=n-1; i++) - { - state->x.ptr.p_double[i] = boundval(state->xk.ptr.p_double[i]-state->g.ptr.p_double[i], state->bndl.ptr.p_double[i], state->bndu.ptr.p_double[i], _state); - } - mincomp_clearrequestfields(state, _state); - state->needfg = ae_true; - state->rstate.stage = 2; - goto lbl_rcomm; -lbl_2: - state->needfg = ae_false; - state->repnfev = state->repnfev+1; - stepfound = ae_fp_less_eq(state->f,state->finit+mincomp_gpaftol*state->dginit); - goto lbl_24; -lbl_23: - stepfound = ae_false; -lbl_24: - if( !stepfound ) - { - goto lbl_25; - } - - /* - * we are at the boundary(ies) - */ - ae_v_move(&state->xn.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->stp = (double)(1); - goto lbl_26; -lbl_25: - - /* - * alpha=1 is too large, try smaller values - */ - state->stp = (double)(1); - linminnormalized(&state->d, &state->stp, n, _state); - state->dginit = state->dginit/state->stp; - state->stp = mincomp_gpadecay*state->stp; - if( ae_fp_greater(state->stpmax,(double)(0)) ) - { - state->stp = ae_minreal(state->stp, state->stpmax, _state); - } -lbl_27: - if( ae_false ) - { - goto lbl_28; - } - v = state->stp; - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_addd(&state->x.ptr.p_double[0], 1, &state->d.ptr.p_double[0], 1, ae_v_len(0,n-1), v); - mincomp_clearrequestfields(state, _state); - state->needfg = ae_true; - state->rstate.stage = 3; - goto lbl_rcomm; -lbl_3: - state->needfg = ae_false; - state->repnfev = state->repnfev+1; - if( ae_fp_less_eq(state->stp,mincomp_stpmin) ) - { - goto lbl_28; - } - if( ae_fp_less_eq(state->f,state->finit+state->stp*mincomp_gpaftol*state->dginit) ) - { - goto lbl_28; - } - state->stp = state->stp*mincomp_gpadecay; - goto lbl_27; -lbl_28: - ae_v_move(&state->xn.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1)); -lbl_26: - state->repiterationscount = state->repiterationscount+1; - if( !state->xrep ) - { - goto lbl_29; - } - - /* - * progress report - */ - mincomp_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 4; - goto lbl_rcomm; -lbl_4: - state->xupdated = ae_false; -lbl_29: - - /* - * Calculate new set of active constraints. - * Reset counter if active set was changed. - * Prepare for the new iteration - */ - for(i=0; i<=n-1; i++) - { - if( ae_fp_eq(state->xn.ptr.p_double[i],state->bndl.ptr.p_double[i])||ae_fp_eq(state->xn.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->an.ptr.p_double[i] = (double)(0); - } - else - { - state->an.ptr.p_double[i] = (double)(1); - } - } - for(i=0; i<=n-1; i++) - { - if( ae_fp_neq(state->ak.ptr.p_double[i],state->an.ptr.p_double[i]) ) - { - state->acount = -1; - break; - } - } - state->acount = state->acount+1; - ae_v_move(&state->xk.ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->ak.ptr.p_double[0], 1, &state->an.ptr.p_double[0], 1, ae_v_len(0,n-1)); - - /* - * Stopping conditions - */ - if( !(state->repiterationscount>=state->maxits&&state->maxits>0) ) - { - goto lbl_31; - } - - /* - * Too many iterations - */ - state->repterminationtype = 5; - if( !state->xrep ) - { - goto lbl_33; - } - mincomp_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 5; - goto lbl_rcomm; -lbl_5: - state->xupdated = ae_false; -lbl_33: - result = ae_false; - return result; -lbl_31: - if( ae_fp_greater(mincomp_asaboundedantigradnorm(state, _state),state->epsg) ) - { - goto lbl_35; - } - - /* - * Gradient is small enough - */ - state->repterminationtype = 4; - if( !state->xrep ) - { - goto lbl_37; - } - mincomp_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 6; - goto lbl_rcomm; -lbl_6: - state->xupdated = ae_false; -lbl_37: - result = ae_false; - return result; -lbl_35: - v = ae_v_dotproduct(&state->d.ptr.p_double[0], 1, &state->d.ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( ae_fp_greater(ae_sqrt(v, _state)*state->stp,state->epsx) ) - { - goto lbl_39; - } - - /* - * Step size is too small, no further improvement is - * possible - */ - state->repterminationtype = 2; - if( !state->xrep ) - { - goto lbl_41; - } - mincomp_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 7; - goto lbl_rcomm; -lbl_7: - state->xupdated = ae_false; -lbl_41: - result = ae_false; - return result; -lbl_39: - if( ae_fp_greater(state->finit-state->f,state->epsf*ae_maxreal(ae_fabs(state->finit, _state), ae_maxreal(ae_fabs(state->f, _state), 1.0, _state), _state)) ) - { - goto lbl_43; - } - - /* - * F(k+1)-F(k) is small enough - */ - state->repterminationtype = 1; - if( !state->xrep ) - { - goto lbl_45; - } - mincomp_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 8; - goto lbl_rcomm; -lbl_8: - state->xupdated = ae_false; -lbl_45: - result = ae_false; - return result; -lbl_43: - - /* - * Decide - should we switch algorithm or not - */ - if( mincomp_asauisempty(state, _state) ) - { - if( ae_fp_greater_eq(mincomp_asaginorm(state, _state),state->mu*mincomp_asad1norm(state, _state)) ) - { - state->curalgo = 1; - goto lbl_22; - } - else - { - state->mu = state->mu*mincomp_asarho; - } - } - else - { - if( state->acount==mincomp_n1 ) - { - if( ae_fp_greater_eq(mincomp_asaginorm(state, _state),state->mu*mincomp_asad1norm(state, _state)) ) - { - state->curalgo = 1; - goto lbl_22; - } - } - } - - /* - * Next iteration - */ - state->k = state->k+1; - goto lbl_21; -lbl_22: -lbl_19: - - /* - * CG algorithm - */ - if( state->curalgo!=1 ) - { - goto lbl_47; - } - - /* - * first, check that there are non-active constraints. - * move to GPA algorithm, if all constraints are active - */ - b = ae_true; - for(i=0; i<=n-1; i++) - { - if( ae_fp_neq(state->ak.ptr.p_double[i],(double)(0)) ) - { - b = ae_false; - break; - } - } - if( b ) - { - state->curalgo = 0; - goto lbl_17; - } - - /* - * CG iterations - */ - state->fold = state->f; - ae_v_move(&state->xk.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - state->dk.ptr.p_double[i] = -state->g.ptr.p_double[i]*state->ak.ptr.p_double[i]; - state->gc.ptr.p_double[i] = state->g.ptr.p_double[i]*state->ak.ptr.p_double[i]; - } -lbl_49: - if( ae_false ) - { - goto lbl_50; - } - - /* - * Store G[k] for later calculation of Y[k] - */ - for(i=0; i<=n-1; i++) - { - state->yk.ptr.p_double[i] = -state->gc.ptr.p_double[i]; - } - - /* - * Make a CG step in direction given by DK[]: - * * calculate step. Step projection into feasible set - * is used. It has several benefits: a) step may be - * found with usual line search, b) multiple constraints - * may be activated with one step, c) activated constraints - * are detected in a natural way - just compare x[i] with - * bounds - * * update active set, set B to True, if there - * were changes in the set. - */ - ae_v_move(&state->d.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->mcstage = 0; - state->stp = (double)(1); - linminnormalized(&state->d, &state->stp, n, _state); - if( ae_fp_neq(state->laststep,(double)(0)) ) - { - state->stp = state->laststep; - } - mcsrch(n, &state->xn, &state->f, &state->gc, &state->d, &state->stp, state->stpmax, mincomp_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state); -lbl_51: - if( state->mcstage==0 ) - { - goto lbl_52; - } - - /* - * preprocess data: bound State.XN so it belongs to the - * feasible set and store it in the State.X - */ - for(i=0; i<=n-1; i++) - { - state->x.ptr.p_double[i] = boundval(state->xn.ptr.p_double[i], state->bndl.ptr.p_double[i], state->bndu.ptr.p_double[i], _state); - } - - /* - * RComm - */ - mincomp_clearrequestfields(state, _state); - state->needfg = ae_true; - state->rstate.stage = 9; - goto lbl_rcomm; -lbl_9: - state->needfg = ae_false; - - /* - * postprocess data: zero components of G corresponding to - * the active constraints - */ - for(i=0; i<=n-1; i++) - { - if( ae_fp_eq(state->x.ptr.p_double[i],state->bndl.ptr.p_double[i])||ae_fp_eq(state->x.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->gc.ptr.p_double[i] = (double)(0); - } - else - { - state->gc.ptr.p_double[i] = state->g.ptr.p_double[i]; - } - } - mcsrch(n, &state->xn, &state->f, &state->gc, &state->d, &state->stp, state->stpmax, mincomp_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state); - goto lbl_51; -lbl_52: - diffcnt = 0; - for(i=0; i<=n-1; i++) - { - - /* - * XN contains unprojected result, project it, - * save copy to X (will be used for progress reporting) - */ - state->xn.ptr.p_double[i] = boundval(state->xn.ptr.p_double[i], state->bndl.ptr.p_double[i], state->bndu.ptr.p_double[i], _state); - - /* - * update active set - */ - if( ae_fp_eq(state->xn.ptr.p_double[i],state->bndl.ptr.p_double[i])||ae_fp_eq(state->xn.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - state->an.ptr.p_double[i] = (double)(0); - } - else - { - state->an.ptr.p_double[i] = (double)(1); - } - if( ae_fp_neq(state->an.ptr.p_double[i],state->ak.ptr.p_double[i]) ) - { - diffcnt = diffcnt+1; - } - state->ak.ptr.p_double[i] = state->an.ptr.p_double[i]; - } - ae_v_move(&state->xk.ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->repnfev = state->repnfev+state->nfev; - state->repiterationscount = state->repiterationscount+1; - if( !state->xrep ) - { - goto lbl_53; - } - - /* - * progress report - */ - mincomp_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 10; - goto lbl_rcomm; -lbl_10: - state->xupdated = ae_false; -lbl_53: - - /* - * Update info about step length - */ - v = ae_v_dotproduct(&state->d.ptr.p_double[0], 1, &state->d.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->laststep = ae_sqrt(v, _state)*state->stp; - - /* - * Check stopping conditions. - */ - if( ae_fp_greater(mincomp_asaboundedantigradnorm(state, _state),state->epsg) ) - { - goto lbl_55; - } - - /* - * Gradient is small enough - */ - state->repterminationtype = 4; - if( !state->xrep ) - { - goto lbl_57; - } - mincomp_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 11; - goto lbl_rcomm; -lbl_11: - state->xupdated = ae_false; -lbl_57: - result = ae_false; - return result; -lbl_55: - if( !(state->repiterationscount>=state->maxits&&state->maxits>0) ) - { - goto lbl_59; - } - - /* - * Too many iterations - */ - state->repterminationtype = 5; - if( !state->xrep ) - { - goto lbl_61; - } - mincomp_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 12; - goto lbl_rcomm; -lbl_12: - state->xupdated = ae_false; -lbl_61: - result = ae_false; - return result; -lbl_59: - if( !(ae_fp_greater_eq(mincomp_asaginorm(state, _state),state->mu*mincomp_asad1norm(state, _state))&&diffcnt==0) ) - { - goto lbl_63; - } - - /* - * These conditions (EpsF/EpsX) are explicitly or implicitly - * related to the current step size and influenced - * by changes in the active constraints. - * - * For these reasons they are checked only when we don't - * want to 'unstick' at the end of the iteration and there - * were no changes in the active set. - * - * NOTE: consition |G|>=Mu*|D1| must be exactly opposite - * to the condition used to switch back to GPA. At least - * one inequality must be strict, otherwise infinite cycle - * may occur when |G|=Mu*|D1| (we DON'T test stopping - * conditions and we DON'T switch to GPA, so we cycle - * indefinitely). - */ - if( ae_fp_greater(state->fold-state->f,state->epsf*ae_maxreal(ae_fabs(state->fold, _state), ae_maxreal(ae_fabs(state->f, _state), 1.0, _state), _state)) ) - { - goto lbl_65; - } - - /* - * F(k+1)-F(k) is small enough - */ - state->repterminationtype = 1; - if( !state->xrep ) - { - goto lbl_67; - } - mincomp_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 13; - goto lbl_rcomm; -lbl_13: - state->xupdated = ae_false; -lbl_67: - result = ae_false; - return result; -lbl_65: - if( ae_fp_greater(state->laststep,state->epsx) ) - { - goto lbl_69; - } - - /* - * X(k+1)-X(k) is small enough - */ - state->repterminationtype = 2; - if( !state->xrep ) - { - goto lbl_71; - } - mincomp_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 14; - goto lbl_rcomm; -lbl_14: - state->xupdated = ae_false; -lbl_71: - result = ae_false; - return result; -lbl_69: -lbl_63: - - /* - * Check conditions for switching - */ - if( ae_fp_less(mincomp_asaginorm(state, _state),state->mu*mincomp_asad1norm(state, _state)) ) - { - state->curalgo = 0; - goto lbl_50; - } - if( diffcnt>0 ) - { - if( mincomp_asauisempty(state, _state)||diffcnt>=mincomp_n2 ) - { - state->curalgo = 1; - } - else - { - state->curalgo = 0; - } - goto lbl_50; - } - - /* - * Calculate D(k+1) - * - * Line search may result in: - * * maximum feasible step being taken (already processed) - * * point satisfying Wolfe conditions - * * some kind of error (CG is restarted by assigning 0.0 to Beta) - */ - if( mcinfo==1 ) - { - - /* - * Standard Wolfe conditions are satisfied: - * * calculate Y[K] and BetaK - */ - ae_v_add(&state->yk.ptr.p_double[0], 1, &state->gc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - vv = ae_v_dotproduct(&state->yk.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = ae_v_dotproduct(&state->gc.ptr.p_double[0], 1, &state->gc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->betady = v/vv; - v = ae_v_dotproduct(&state->gc.ptr.p_double[0], 1, &state->yk.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->betahs = v/vv; - if( state->cgtype==0 ) - { - betak = state->betady; - } - if( state->cgtype==1 ) - { - betak = ae_maxreal((double)(0), ae_minreal(state->betady, state->betahs, _state), _state); - } - } - else - { - - /* - * Something is wrong (may be function is too wild or too flat). - * - * We'll set BetaK=0, which will restart CG algorithm. - * We can stop later (during normal checks) if stopping conditions are met. - */ - betak = (double)(0); - state->debugrestartscount = state->debugrestartscount+1; - } - ae_v_moveneg(&state->dn.ptr.p_double[0], 1, &state->gc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_addd(&state->dn.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1), betak); - ae_v_move(&state->dk.ptr.p_double[0], 1, &state->dn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - - /* - * update other information - */ - state->fold = state->f; - state->k = state->k+1; - goto lbl_49; -lbl_50: -lbl_47: - goto lbl_17; -lbl_18: - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = n; - state->rstate.ia.ptr.p_int[1] = i; - state->rstate.ia.ptr.p_int[2] = mcinfo; - state->rstate.ia.ptr.p_int[3] = diffcnt; - state->rstate.ba.ptr.p_bool[0] = b; - state->rstate.ba.ptr.p_bool[1] = stepfound; - state->rstate.ra.ptr.p_double[0] = betak; - state->rstate.ra.ptr.p_double[1] = v; - state->rstate.ra.ptr.p_double[2] = vv; - return result; -} - - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minasaresults(minasastate* state, - /* Real */ ae_vector* x, - minasareport* rep, - ae_state *_state) -{ - - ae_vector_clear(x); - _minasareport_clear(rep); - - minasaresultsbuf(state, x, rep, _state); -} - - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minasaresultsbuf(minasastate* state, - /* Real */ ae_vector* x, - minasareport* rep, - ae_state *_state) -{ - ae_int_t i; - - - if( x->cntn ) - { - ae_vector_set_length(x, state->n, _state); - } - ae_v_move(&x->ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - rep->iterationscount = state->repiterationscount; - rep->nfev = state->repnfev; - rep->terminationtype = state->repterminationtype; - rep->activeconstraints = 0; - for(i=0; i<=state->n-1; i++) - { - if( ae_fp_eq(state->ak.ptr.p_double[i],(double)(0)) ) - { - rep->activeconstraints = rep->activeconstraints+1; - } - } -} - - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -void minasarestartfrom(minasastate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_state *_state) -{ - - - ae_assert(x->cnt>=state->n, "MinASARestartFrom: Length(X)n, _state), "MinASARestartFrom: X contains infinite or NaN values!", _state); - ae_assert(bndl->cnt>=state->n, "MinASARestartFrom: Length(BndL)n, _state), "MinASARestartFrom: BndL contains infinite or NaN values!", _state); - ae_assert(bndu->cnt>=state->n, "MinASARestartFrom: Length(BndU)n, _state), "MinASARestartFrom: BndU contains infinite or NaN values!", _state); - ae_v_move(&state->x.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - ae_v_move(&state->bndl.ptr.p_double[0], 1, &bndl->ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - ae_v_move(&state->bndu.ptr.p_double[0], 1, &bndu->ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - state->laststep = (double)(0); - ae_vector_set_length(&state->rstate.ia, 3+1, _state); - ae_vector_set_length(&state->rstate.ba, 1+1, _state); - ae_vector_set_length(&state->rstate.ra, 2+1, _state); - state->rstate.stage = -1; - mincomp_clearrequestfields(state, _state); -} - - -/************************************************************************* -Returns norm of bounded anti-gradient. - -Bounded antigradient is a vector obtained from anti-gradient by zeroing -components which point outwards: - result = norm(v) - v[i]=0 if ((-g[i]<0)and(x[i]=bndl[i])) or - ((-g[i]>0)and(x[i]=bndu[i])) - v[i]=-g[i] otherwise - -This function may be used to check a stopping criterion. - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -static double mincomp_asaboundedantigradnorm(minasastate* state, - ae_state *_state) -{ - ae_int_t i; - double v; - double result; - - - result = (double)(0); - for(i=0; i<=state->n-1; i++) - { - v = -state->g.ptr.p_double[i]; - if( ae_fp_eq(state->x.ptr.p_double[i],state->bndl.ptr.p_double[i])&&ae_fp_less(-state->g.ptr.p_double[i],(double)(0)) ) - { - v = (double)(0); - } - if( ae_fp_eq(state->x.ptr.p_double[i],state->bndu.ptr.p_double[i])&&ae_fp_greater(-state->g.ptr.p_double[i],(double)(0)) ) - { - v = (double)(0); - } - result = result+ae_sqr(v, _state); - } - result = ae_sqrt(result, _state); - return result; -} - - -/************************************************************************* -Returns norm of GI(x). - -GI(x) is a gradient vector whose components associated with active -constraints are zeroed. It differs from bounded anti-gradient because -components of GI(x) are zeroed independently of sign(g[i]), and -anti-gradient's components are zeroed with respect to both constraint and -sign. - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -static double mincomp_asaginorm(minasastate* state, ae_state *_state) -{ - ae_int_t i; - double result; - - - result = (double)(0); - for(i=0; i<=state->n-1; i++) - { - if( ae_fp_neq(state->x.ptr.p_double[i],state->bndl.ptr.p_double[i])&&ae_fp_neq(state->x.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - result = result+ae_sqr(state->g.ptr.p_double[i], _state); - } - } - result = ae_sqrt(result, _state); - return result; -} - - -/************************************************************************* -Returns norm(D1(State.X)) - -For a meaning of D1 see 'NEW ACTIVE SET ALGORITHM FOR BOX CONSTRAINED -OPTIMIZATION' by WILLIAM W. HAGER AND HONGCHAO ZHANG. - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -static double mincomp_asad1norm(minasastate* state, ae_state *_state) -{ - ae_int_t i; - double result; - - - result = (double)(0); - for(i=0; i<=state->n-1; i++) - { - result = result+ae_sqr(boundval(state->x.ptr.p_double[i]-state->g.ptr.p_double[i], state->bndl.ptr.p_double[i], state->bndu.ptr.p_double[i], _state)-state->x.ptr.p_double[i], _state); - } - result = ae_sqrt(result, _state); - return result; -} - - -/************************************************************************* -Returns True, if U set is empty. - -* State.X is used as point, -* State.G - as gradient, -* D is calculated within function (because State.D may have different - meaning depending on current optimization algorithm) - -For a meaning of U see 'NEW ACTIVE SET ALGORITHM FOR BOX CONSTRAINED -OPTIMIZATION' by WILLIAM W. HAGER AND HONGCHAO ZHANG. - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -static ae_bool mincomp_asauisempty(minasastate* state, ae_state *_state) -{ - ae_int_t i; - double d; - double d2; - double d32; - ae_bool result; - - - d = mincomp_asad1norm(state, _state); - d2 = ae_sqrt(d, _state); - d32 = d*d2; - result = ae_true; - for(i=0; i<=state->n-1; i++) - { - if( ae_fp_greater_eq(ae_fabs(state->g.ptr.p_double[i], _state),d2)&&ae_fp_greater_eq(ae_minreal(state->x.ptr.p_double[i]-state->bndl.ptr.p_double[i], state->bndu.ptr.p_double[i]-state->x.ptr.p_double[i], _state),d32) ) - { - result = ae_false; - return result; - } - } - return result; -} - - -/************************************************************************* -Clears request fileds (to be sure that we don't forgot to clear something) -*************************************************************************/ -static void mincomp_clearrequestfields(minasastate* state, - ae_state *_state) -{ - - - state->needfg = ae_false; - state->xupdated = ae_false; -} - - -void _minasastate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minasastate *p = (minasastate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ak, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xk, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dk, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->an, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xn, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dn, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->work, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->yk, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->gc, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); - _linminstate_init(&p->lstate, _state, make_automatic); -} - - -void _minasastate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minasastate *dst = (minasastate*)_dst; - minasastate *src = (minasastate*)_src; - dst->n = src->n; - dst->epsg = src->epsg; - dst->epsf = src->epsf; - dst->epsx = src->epsx; - dst->maxits = src->maxits; - dst->xrep = src->xrep; - dst->stpmax = src->stpmax; - dst->cgtype = src->cgtype; - dst->k = src->k; - dst->nfev = src->nfev; - dst->mcstage = src->mcstage; - ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic); - ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic); - dst->curalgo = src->curalgo; - dst->acount = src->acount; - dst->mu = src->mu; - dst->finit = src->finit; - dst->dginit = src->dginit; - ae_vector_init_copy(&dst->ak, &src->ak, _state, make_automatic); - ae_vector_init_copy(&dst->xk, &src->xk, _state, make_automatic); - ae_vector_init_copy(&dst->dk, &src->dk, _state, make_automatic); - ae_vector_init_copy(&dst->an, &src->an, _state, make_automatic); - ae_vector_init_copy(&dst->xn, &src->xn, _state, make_automatic); - ae_vector_init_copy(&dst->dn, &src->dn, _state, make_automatic); - ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic); - dst->fold = src->fold; - dst->stp = src->stp; - ae_vector_init_copy(&dst->work, &src->work, _state, make_automatic); - ae_vector_init_copy(&dst->yk, &src->yk, _state, make_automatic); - ae_vector_init_copy(&dst->gc, &src->gc, _state, make_automatic); - dst->laststep = src->laststep; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - dst->f = src->f; - ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic); - dst->needfg = src->needfg; - dst->xupdated = src->xupdated; - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); - dst->repiterationscount = src->repiterationscount; - dst->repnfev = src->repnfev; - dst->repterminationtype = src->repterminationtype; - dst->debugrestartscount = src->debugrestartscount; - _linminstate_init_copy(&dst->lstate, &src->lstate, _state, make_automatic); - dst->betahs = src->betahs; - dst->betady = src->betady; -} - - -void _minasastate_clear(void* _p) -{ - minasastate *p = (minasastate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->bndl); - ae_vector_clear(&p->bndu); - ae_vector_clear(&p->ak); - ae_vector_clear(&p->xk); - ae_vector_clear(&p->dk); - ae_vector_clear(&p->an); - ae_vector_clear(&p->xn); - ae_vector_clear(&p->dn); - ae_vector_clear(&p->d); - ae_vector_clear(&p->work); - ae_vector_clear(&p->yk); - ae_vector_clear(&p->gc); - ae_vector_clear(&p->x); - ae_vector_clear(&p->g); - _rcommstate_clear(&p->rstate); - _linminstate_clear(&p->lstate); -} - - -void _minasastate_destroy(void* _p) -{ - minasastate *p = (minasastate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->bndl); - ae_vector_destroy(&p->bndu); - ae_vector_destroy(&p->ak); - ae_vector_destroy(&p->xk); - ae_vector_destroy(&p->dk); - ae_vector_destroy(&p->an); - ae_vector_destroy(&p->xn); - ae_vector_destroy(&p->dn); - ae_vector_destroy(&p->d); - ae_vector_destroy(&p->work); - ae_vector_destroy(&p->yk); - ae_vector_destroy(&p->gc); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->g); - _rcommstate_destroy(&p->rstate); - _linminstate_destroy(&p->lstate); -} - - -void _minasareport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minasareport *p = (minasareport*)_p; - ae_touch_ptr((void*)p); -} - - -void _minasareport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minasareport *dst = (minasareport*)_dst; - minasareport *src = (minasareport*)_src; - dst->iterationscount = src->iterationscount; - dst->nfev = src->nfev; - dst->terminationtype = src->terminationtype; - dst->activeconstraints = src->activeconstraints; -} - - -void _minasareport_clear(void* _p) -{ - minasareport *p = (minasareport*)_p; - ae_touch_ptr((void*)p); -} - - -void _minasareport_destroy(void* _p) -{ - minasareport *p = (minasareport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_MINCG) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* - NONLINEAR CONJUGATE GRADIENT METHOD - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments by using one of the -nonlinear conjugate gradient methods. - -These CG methods are globally convergent (even on non-convex functions) as -long as grad(f) is Lipschitz continuous in a some neighborhood of the -L = { x : f(x)<=f(x0) }. - - -REQUIREMENTS: -Algorithm will request following information during its operation: -* function value F and its gradient G (simultaneously) at given point X - - -USAGE: -1. User initializes algorithm state with MinCGCreate() call -2. User tunes solver parameters with MinCGSetCond(), MinCGSetStpMax() and - other functions -3. User calls MinCGOptimize() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. -4. User calls MinCGResults() to get solution -5. Optionally, user may call MinCGRestartFrom() to solve another problem - with same N but another starting point and/or another function. - MinCGRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[0..N-1]. - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 25.03.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgcreate(ae_int_t n, - /* Real */ ae_vector* x, - mincgstate* state, - ae_state *_state) -{ - - _mincgstate_clear(state); - - ae_assert(n>=1, "MinCGCreate: N too small!", _state); - ae_assert(x->cnt>=n, "MinCGCreate: Length(X)0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[0..N-1]. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinCGSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large truncation errors, while too small - step will result in too large numerical errors. 1.0E-6 can be good - value to start with. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. L-BFGS needs exact gradient values. - Imprecise gradient may slow down convergence, especially on highly - nonlinear problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -void mincgcreatef(ae_int_t n, - /* Real */ ae_vector* x, - double diffstep, - mincgstate* state, - ae_state *_state) -{ - - _mincgstate_clear(state); - - ae_assert(n>=1, "MinCGCreateF: N too small!", _state); - ae_assert(x->cnt>=n, "MinCGCreateF: Length(X)=0 - The subroutine finishes its work if the condition - |v|=0 - The subroutine finishes its work if on k+1-th iteration - the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - is satisfied. - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - ste pvector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinCGSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to -automatic stopping criterion selection (small EpsX). - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetcond(mincgstate* state, - double epsg, - double epsf, - double epsx, - ae_int_t maxits, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(epsg, _state), "MinCGSetCond: EpsG is not finite number!", _state); - ae_assert(ae_fp_greater_eq(epsg,(double)(0)), "MinCGSetCond: negative EpsG!", _state); - ae_assert(ae_isfinite(epsf, _state), "MinCGSetCond: EpsF is not finite number!", _state); - ae_assert(ae_fp_greater_eq(epsf,(double)(0)), "MinCGSetCond: negative EpsF!", _state); - ae_assert(ae_isfinite(epsx, _state), "MinCGSetCond: EpsX is not finite number!", _state); - ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinCGSetCond: negative EpsX!", _state); - ae_assert(maxits>=0, "MinCGSetCond: negative MaxIts!", _state); - if( ((ae_fp_eq(epsg,(double)(0))&&ae_fp_eq(epsf,(double)(0)))&&ae_fp_eq(epsx,(double)(0)))&&maxits==0 ) - { - epsx = 1.0E-6; - } - state->epsg = epsg; - state->epsf = epsf; - state->epsx = epsx; - state->maxits = maxits; -} - - -/************************************************************************* -This function sets scaling coefficients for CG optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of CG optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -In most optimizers (and in the CG too) scaling is NOT a form of -preconditioning. It just affects stopping conditions. You should set -preconditioner by separate call to one of the MinCGSetPrec...() functions. - -There is special preconditioning mode, however, which uses scaling -coefficients to form diagonal preconditioning matrix. You can turn this -mode on, if you want. But you should understand that scaling is not the -same thing as preconditioning - these are two different, although related -forms of tuning solver. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void mincgsetscale(mincgstate* state, - /* Real */ ae_vector* s, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(s->cnt>=state->n, "MinCGSetScale: Length(S)n-1; i++) - { - ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinCGSetScale: S contains infinite or NAN elements", _state); - ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "MinCGSetScale: S contains zero elements", _state); - state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state); - } -} - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinCGOptimize(). - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetxrep(mincgstate* state, ae_bool needxrep, ae_state *_state) -{ - - - state->xrep = needxrep; -} - - -/************************************************************************* -This function turns on/off line search reports. -These reports are described in more details in developer-only comments on -MinCGState object. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedDRep- whether line search reports are needed or not - -This function is intended for private use only. Turning it on artificially -may cause program failure. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetdrep(mincgstate* state, ae_bool needdrep, ae_state *_state) -{ - - - state->drep = needdrep; -} - - -/************************************************************************* -This function sets CG algorithm. - -INPUT PARAMETERS: - State - structure which stores algorithm state - CGType - algorithm type: - * -1 automatic selection of the best algorithm - * 0 DY (Dai and Yuan) algorithm - * 1 Hybrid DY-HS algorithm - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetcgtype(mincgstate* state, ae_int_t cgtype, ae_state *_state) -{ - - - ae_assert(cgtype>=-1&&cgtype<=1, "MinCGSetCGType: incorrect CGType!", _state); - if( cgtype==-1 ) - { - cgtype = 1; - } - state->cgtype = cgtype; -} - - -/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which leads to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetstpmax(mincgstate* state, double stpmax, ae_state *_state) -{ - - - ae_assert(ae_isfinite(stpmax, _state), "MinCGSetStpMax: StpMax is not finite!", _state); - ae_assert(ae_fp_greater_eq(stpmax,(double)(0)), "MinCGSetStpMax: StpMax<0!", _state); - state->stpmax = stpmax; -} - - -/************************************************************************* -This function allows to suggest initial step length to the CG algorithm. - -Suggested step length is used as starting point for the line search. It -can be useful when you have badly scaled problem, i.e. when ||grad|| -(which is used as initial estimate for the first step) is many orders of -magnitude different from the desired step. - -Line search may fail on such problems without good estimate of initial -step length. Imagine, for example, problem with ||grad||=10^50 and desired -step equal to 0.1 Line search function will use 10^50 as initial step, -then it will decrease step length by 2 (up to 20 attempts) and will get -10^44, which is still too large. - -This function allows us to tell than line search should be started from -some moderate step length, like 1.0, so algorithm will be able to detect -desired step length in a several searches. - -Default behavior (when no step is suggested) is to use preconditioner, if -it is available, to generate initial estimate of step length. - -This function influences only first iteration of algorithm. It should be -called between MinCGCreate/MinCGRestartFrom() call and MinCGOptimize call. -Suggested step is ignored if you have preconditioner. - -INPUT PARAMETERS: - State - structure used to store algorithm state. - Stp - initial estimate of the step length. - Can be zero (no estimate). - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsuggeststep(mincgstate* state, double stp, ae_state *_state) -{ - - - ae_assert(ae_isfinite(stp, _state), "MinCGSuggestStep: Stp is infinite or NAN", _state); - ae_assert(ae_fp_greater_eq(stp,(double)(0)), "MinCGSuggestStep: Stp<0", _state); - state->suggestedstep = stp; -} - - -/************************************************************************* -This developer-only function allows to retrieve unscaled (!) length of -last good step (i.e. step which resulted in sufficient decrease of target -function). - -It can be used in for solution of sequential optimization subproblems, -where MinCGSuggestStep() is called with length of previous step as -parameter. - -INPUT PARAMETERS: - State - structure used to store algorithm state. - -RESULT: - length of last good step being accepted - -NOTE: - result of this function is undefined if you called it before - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -double mincglastgoodstep(mincgstate* state, ae_state *_state) -{ - double result; - - - result = state->lastgoodstep; - return result; -} - - -/************************************************************************* -Modification of the preconditioner: preconditioning is turned off. - -INPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetprecdefault(mincgstate* state, ae_state *_state) -{ - - - state->prectype = 0; - state->innerresetneeded = ae_true; -} - - -/************************************************************************* -Modification of the preconditioner: diagonal of approximate Hessian is -used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - D - diagonal of the approximate Hessian, array[0..N-1], - (if larger, only leading N elements are used). - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - -NOTE 2: D[i] should be positive. Exception will be thrown otherwise. - -NOTE 3: you should pass diagonal of approximate Hessian - NOT ITS INVERSE. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetprecdiag(mincgstate* state, - /* Real */ ae_vector* d, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(d->cnt>=state->n, "MinCGSetPrecDiag: D is too short", _state); - for(i=0; i<=state->n-1; i++) - { - ae_assert(ae_isfinite(d->ptr.p_double[i], _state), "MinCGSetPrecDiag: D contains infinite or NAN elements", _state); - ae_assert(ae_fp_greater(d->ptr.p_double[i],(double)(0)), "MinCGSetPrecDiag: D contains non-positive elements", _state); - } - mincgsetprecdiagfast(state, d, _state); -} - - -/************************************************************************* -Modification of the preconditioner: scale-based diagonal preconditioning. - -This preconditioning mode can be useful when you don't have approximate -diagonal of Hessian, but you know that your variables are badly scaled -(for example, one variable is in [1,10], and another in [1000,100000]), -and most part of the ill-conditioning comes from different scales of vars. - -In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2), -can greatly improve convergence. - -IMPRTANT: you should set scale of your variables with MinCGSetScale() call -(before or after MinCGSetPrecScale() call). Without knowledge of the scale -of your variables scale-based preconditioner will be just unit matrix. - -INPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetprecscale(mincgstate* state, ae_state *_state) -{ - - - state->prectype = 3; - state->innerresetneeded = ae_true; -} - - -/************************************************************************* -NOTES: - -1. This function has two different implementations: one which uses exact - (analytical) user-supplied gradient, and one which uses function value - only and numerically differentiates function in order to obtain - gradient. - - Depending on the specific function used to create optimizer object - (either MinCGCreate() for analytical gradient or MinCGCreateF() for - numerical differentiation) you should choose appropriate variant of - MinCGOptimize() - one which accepts function AND gradient or one which - accepts function ONLY. - - Be careful to choose variant of MinCGOptimize() which corresponds to - your optimization scheme! Table below lists different combinations of - callback (function/gradient) passed to MinCGOptimize() and specific - function used to create optimizer. - - - | USER PASSED TO MinCGOptimize() - CREATED WITH | function only | function and gradient - ------------------------------------------------------------ - MinCGCreateF() | work FAIL - MinCGCreate() | FAIL work - - Here "FAIL" denotes inappropriate combinations of optimizer creation - function and MinCGOptimize() version. Attemps to use such combination - (for example, to create optimizer with MinCGCreateF() and to pass - gradient information to MinCGOptimize()) will lead to exception being - thrown. Either you did not pass gradient when it WAS needed or you - passed gradient when it was NOT needed. - - -- ALGLIB -- - Copyright 20.04.2009 by Bochkanov Sergey -*************************************************************************/ -ae_bool mincgiteration(mincgstate* state, ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - double betak; - double v; - double vv; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - n = state->rstate.ia.ptr.p_int[0]; - i = state->rstate.ia.ptr.p_int[1]; - betak = state->rstate.ra.ptr.p_double[0]; - v = state->rstate.ra.ptr.p_double[1]; - vv = state->rstate.ra.ptr.p_double[2]; - } - else - { - n = 359; - i = -58; - betak = -919; - v = -909; - vv = 81; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - if( state->rstate.stage==1 ) - { - goto lbl_1; - } - if( state->rstate.stage==2 ) - { - goto lbl_2; - } - if( state->rstate.stage==3 ) - { - goto lbl_3; - } - if( state->rstate.stage==4 ) - { - goto lbl_4; - } - if( state->rstate.stage==5 ) - { - goto lbl_5; - } - if( state->rstate.stage==6 ) - { - goto lbl_6; - } - if( state->rstate.stage==7 ) - { - goto lbl_7; - } - if( state->rstate.stage==8 ) - { - goto lbl_8; - } - if( state->rstate.stage==9 ) - { - goto lbl_9; - } - if( state->rstate.stage==10 ) - { - goto lbl_10; - } - if( state->rstate.stage==11 ) - { - goto lbl_11; - } - if( state->rstate.stage==12 ) - { - goto lbl_12; - } - if( state->rstate.stage==13 ) - { - goto lbl_13; - } - if( state->rstate.stage==14 ) - { - goto lbl_14; - } - if( state->rstate.stage==15 ) - { - goto lbl_15; - } - if( state->rstate.stage==16 ) - { - goto lbl_16; - } - if( state->rstate.stage==17 ) - { - goto lbl_17; - } - - /* - * Routine body - */ - - /* - * Prepare - */ - n = state->n; - state->terminationneeded = ae_false; - state->userterminationneeded = ae_false; - state->repterminationtype = 0; - state->repiterationscount = 0; - state->repnfev = 0; - state->debugrestartscount = 0; - smoothnessmonitorinit(&state->smonitor, &state->s, n, 1, state->smoothnessguardlevel>0, _state); - rvectorsetlengthatleast(&state->invs, n, _state); - for(i=0; i<=n-1; i++) - { - state->lastscaleused.ptr.p_double[i] = state->s.ptr.p_double[i]; - state->invs.ptr.p_double[i] = 1/state->s.ptr.p_double[i]; - } - - /* - * Check, that transferred derivative value is right - */ - mincg_clearrequestfields(state, _state); - if( !(ae_fp_eq(state->diffstep,(double)(0))&&ae_fp_greater(state->teststep,(double)(0))) ) - { - goto lbl_18; - } -lbl_20: - if( !smoothnessmonitorcheckgradientatx0(&state->smonitor, &state->xbase, &state->s, &state->s, &state->s, ae_false, state->teststep, _state) ) - { - goto lbl_21; - } - for(i=0; i<=n-1; i++) - { - state->x.ptr.p_double[i] = state->smonitor.x.ptr.p_double[i]; - } - state->needfg = ae_true; - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - state->needfg = ae_false; - state->smonitor.fi.ptr.p_double[0] = state->f; - for(i=0; i<=n-1; i++) - { - state->smonitor.j.ptr.pp_double[0][i] = state->g.ptr.p_double[i]; - } - goto lbl_20; -lbl_21: -lbl_18: - - /* - * Preparations continue: - * * set XK - * * calculate F/G - * * set DK to -G - * * powerup algo (it may change preconditioner) - * * apply preconditioner to DK - * * report update of X - * * check stopping conditions for G - */ - for(i=0; i<=n-1; i++) - { - state->x.ptr.p_double[i] = state->xbase.ptr.p_double[i]; - } - ae_v_move(&state->xk.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - mincg_clearrequestfields(state, _state); - if( ae_fp_neq(state->diffstep,(double)(0)) ) - { - goto lbl_22; - } - state->needfg = ae_true; - state->rstate.stage = 1; - goto lbl_rcomm; -lbl_1: - state->needfg = ae_false; - goto lbl_23; -lbl_22: - state->needf = ae_true; - state->rstate.stage = 2; - goto lbl_rcomm; -lbl_2: - state->fbase = state->f; - i = 0; -lbl_24: - if( i>n-1 ) - { - goto lbl_26; - } - v = state->x.ptr.p_double[i]; - state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 3; - goto lbl_rcomm; -lbl_3: - state->fm2 = state->f; - state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 4; - goto lbl_rcomm; -lbl_4: - state->fm1 = state->f; - state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 5; - goto lbl_rcomm; -lbl_5: - state->fp1 = state->f; - state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 6; - goto lbl_rcomm; -lbl_6: - state->fp2 = state->f; - state->x.ptr.p_double[i] = v; - state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]); - i = i+1; - goto lbl_24; -lbl_26: - state->f = state->fbase; - state->needf = ae_false; -lbl_23: - if( !state->drep ) - { - goto lbl_27; - } - - /* - * Report algorithm powerup (if needed) - */ - mincg_clearrequestfields(state, _state); - state->algpowerup = ae_true; - state->rstate.stage = 7; - goto lbl_rcomm; -lbl_7: - state->algpowerup = ae_false; -lbl_27: - trimprepare(state->f, &state->trimthreshold, _state); - ae_v_moveneg(&state->dk.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - mincg_preconditionedmultiply(state, &state->dk, &state->work0, &state->work1, _state); - if( !state->xrep ) - { - goto lbl_29; - } - mincg_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 8; - goto lbl_rcomm; -lbl_8: - state->xupdated = ae_false; -lbl_29: - if( state->terminationneeded||state->userterminationneeded ) - { - - /* - * Combined termination point for "internal" termination by TerminationNeeded flag - * and for "user" termination by MinCGRequestTermination() (UserTerminationNeeded flag). - * In this location rules for both of methods are same, thus only one exit point is needed. - */ - ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->repterminationtype = 8; - result = ae_false; - return result; - } - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(state->g.ptr.p_double[i]*state->s.ptr.p_double[i], _state); - } - if( ae_fp_less_eq(ae_sqrt(v, _state),state->epsg) ) - { - ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->repterminationtype = 4; - result = ae_false; - return result; - } - state->repnfev = 1; - state->k = 0; - state->fold = state->f; - - /* - * Choose initial step. - * Apply preconditioner, if we have something other than default. - */ - if( state->prectype==2||state->prectype==3 ) - { - - /* - * because we use preconditioner, step length must be equal - * to the norm of DK - */ - v = ae_v_dotproduct(&state->dk.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->lastgoodstep = ae_sqrt(v, _state); - } - else - { - - /* - * No preconditioner is used, we try to use suggested step - */ - if( ae_fp_greater(state->suggestedstep,(double)(0)) ) - { - state->lastgoodstep = state->suggestedstep; - } - else - { - state->lastgoodstep = 1.0; - } - } - - /* - * Main cycle - */ - state->rstimer = mincg_rscountdownlen; -lbl_31: - if( ae_false ) - { - goto lbl_32; - } - - /* - * * clear reset flag - * * clear termination flag - * * store G[k] for later calculation of Y[k] - * * prepare starting point and direction and step length for line search - */ - state->innerresetneeded = ae_false; - state->terminationneeded = ae_false; - ae_v_moveneg(&state->yk.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->d.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->mcstage = 0; - state->stp = 1.0; - linminnormalized(&state->d, &state->stp, n, _state); - if( ae_fp_neq(state->lastgoodstep,(double)(0)) ) - { - state->stp = state->lastgoodstep; - } - state->curstpmax = state->stpmax; - - /* - * Report beginning of line search (if needed) - * Terminate algorithm, if user request was detected - */ - if( !state->drep ) - { - goto lbl_33; - } - mincg_clearrequestfields(state, _state); - state->lsstart = ae_true; - state->rstate.stage = 9; - goto lbl_rcomm; -lbl_9: - state->lsstart = ae_false; -lbl_33: - if( state->terminationneeded ) - { - ae_v_move(&state->xn.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->repterminationtype = 8; - result = ae_false; - return result; - } - - /* - * Minimization along D - */ - smoothnessmonitorstartlinesearch1u(&state->smonitor, &state->s, &state->invs, &state->x, state->f, &state->g, _state); - mcsrch(n, &state->x, &state->f, &state->g, &state->d, &state->stp, state->curstpmax, mincg_gtol, &state->mcinfo, &state->nfev, &state->work0, &state->lstate, &state->mcstage, _state); -lbl_35: - if( state->mcstage==0 ) - { - goto lbl_36; - } - - /* - * Calculate function/gradient using either - * analytical gradient supplied by user - * or finite difference approximation. - * - * "Trim" function in order to handle near-singularity points. - */ - mincg_clearrequestfields(state, _state); - if( ae_fp_neq(state->diffstep,(double)(0)) ) - { - goto lbl_37; - } - state->needfg = ae_true; - state->rstate.stage = 10; - goto lbl_rcomm; -lbl_10: - state->needfg = ae_false; - goto lbl_38; -lbl_37: - state->needf = ae_true; - state->rstate.stage = 11; - goto lbl_rcomm; -lbl_11: - state->fbase = state->f; - i = 0; -lbl_39: - if( i>n-1 ) - { - goto lbl_41; - } - v = state->x.ptr.p_double[i]; - state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 12; - goto lbl_rcomm; -lbl_12: - state->fm2 = state->f; - state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 13; - goto lbl_rcomm; -lbl_13: - state->fm1 = state->f; - state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 14; - goto lbl_rcomm; -lbl_14: - state->fp1 = state->f; - state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i]; - state->rstate.stage = 15; - goto lbl_rcomm; -lbl_15: - state->fp2 = state->f; - state->x.ptr.p_double[i] = v; - state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]); - i = i+1; - goto lbl_39; -lbl_41: - state->f = state->fbase; - state->needf = ae_false; -lbl_38: - smoothnessmonitorenqueuepoint1u(&state->smonitor, &state->s, &state->invs, &state->d, state->stp, &state->x, state->f, &state->g, _state); - trimfunction(&state->f, &state->g, n, state->trimthreshold, _state); - - /* - * Call MCSRCH again - */ - mcsrch(n, &state->x, &state->f, &state->g, &state->d, &state->stp, state->curstpmax, mincg_gtol, &state->mcinfo, &state->nfev, &state->work0, &state->lstate, &state->mcstage, _state); - goto lbl_35; -lbl_36: - smoothnessmonitorfinalizelinesearch(&state->smonitor, _state); - - /* - * * terminate algorithm if "user" request for detected - * * report end of line search - * * store current point to XN - * * report iteration - * * terminate algorithm if "internal" request was detected - */ - if( state->userterminationneeded ) - { - ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->repterminationtype = 8; - result = ae_false; - return result; - } - if( !state->drep ) - { - goto lbl_42; - } - - /* - * Report end of line search (if needed) - */ - mincg_clearrequestfields(state, _state); - state->lsend = ae_true; - state->rstate.stage = 16; - goto lbl_rcomm; -lbl_16: - state->lsend = ae_false; -lbl_42: - ae_v_move(&state->xn.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( !state->xrep ) - { - goto lbl_44; - } - mincg_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 17; - goto lbl_rcomm; -lbl_17: - state->xupdated = ae_false; -lbl_44: - if( state->terminationneeded ) - { - ae_v_move(&state->xn.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->repterminationtype = 8; - result = ae_false; - return result; - } - - /* - * Line search is finished. - * * calculate BetaK - * * calculate DN - * * update timers - * * calculate step length: - * * LastScaledStep is ALWAYS calculated because it is used in the stopping criteria - * * LastGoodStep is updated only when MCINFO is equal to 1 (Wolfe conditions hold). - * See below for more explanation. - */ - if( state->mcinfo==1&&!state->innerresetneeded ) - { - - /* - * Standard Wolfe conditions hold - * Calculate Y[K] and D[K]'*Y[K] - */ - ae_v_add(&state->yk.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - vv = ae_v_dotproduct(&state->yk.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1)); - - /* - * Calculate BetaK according to DY formula - */ - v = mincg_preconditionedmultiply2(state, &state->g, &state->g, &state->work0, &state->work1, _state); - state->betady = v/vv; - - /* - * Calculate BetaK according to HS formula - */ - v = mincg_preconditionedmultiply2(state, &state->g, &state->yk, &state->work0, &state->work1, _state); - state->betahs = v/vv; - - /* - * Choose BetaK - */ - if( state->cgtype==0 ) - { - betak = state->betady; - } - if( state->cgtype==1 ) - { - betak = ae_maxreal((double)(0), ae_minreal(state->betady, state->betahs, _state), _state); - } - } - else - { - - /* - * Something is wrong (may be function is too wild or too flat) - * or we just have to restart algo. - * - * We'll set BetaK=0, which will restart CG algorithm. - * We can stop later (during normal checks) if stopping conditions are met. - */ - betak = (double)(0); - state->debugrestartscount = state->debugrestartscount+1; - } - if( state->repiterationscount>0&&state->repiterationscount%(3+n)==0 ) - { - - /* - * clear Beta every N iterations - */ - betak = (double)(0); - } - if( state->mcinfo==1||state->mcinfo==5 ) - { - state->rstimer = mincg_rscountdownlen; - } - else - { - state->rstimer = state->rstimer-1; - } - ae_v_moveneg(&state->dn.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - mincg_preconditionedmultiply(state, &state->dn, &state->work0, &state->work1, _state); - ae_v_addd(&state->dn.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1), betak); - state->lastscaledstep = 0.0; - for(i=0; i<=n-1; i++) - { - state->lastscaledstep = state->lastscaledstep+ae_sqr(state->d.ptr.p_double[i]/state->s.ptr.p_double[i], _state); - } - state->lastscaledstep = state->stp*ae_sqrt(state->lastscaledstep, _state); - if( state->mcinfo==1 ) - { - - /* - * Step is good (Wolfe conditions hold), update LastGoodStep. - * - * This check for MCINFO=1 is essential because sometimes in the - * constrained optimization setting we may take very short steps - * (like 1E-15) because we were very close to boundary of the - * feasible area. Such short step does not mean that we've converged - * to the solution - it was so short because we were close to the - * boundary and there was a limit on step length. - * - * So having such short step is quite normal situation. However, we - * should NOT start next iteration from step whose initial length is - * estimated as 1E-15 because it may lead to the failure of the - * linear minimizer (step is too short, function does not changes, - * line search stagnates). - */ - state->lastgoodstep = (double)(0); - for(i=0; i<=n-1; i++) - { - state->lastgoodstep = state->lastgoodstep+ae_sqr(state->d.ptr.p_double[i], _state); - } - state->lastgoodstep = state->stp*ae_sqrt(state->lastgoodstep, _state); - } - - /* - * Update information. - * Check stopping conditions. - */ - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(state->g.ptr.p_double[i]*state->s.ptr.p_double[i], _state); - } - if( !ae_isfinite(v, _state)||!ae_isfinite(state->f, _state) ) - { - - /* - * Abnormal termination - infinities in function/gradient - */ - state->repterminationtype = -8; - result = ae_false; - return result; - } - state->repnfev = state->repnfev+state->nfev; - state->repiterationscount = state->repiterationscount+1; - if( state->repiterationscount>=state->maxits&&state->maxits>0 ) - { - - /* - * Too many iterations - */ - state->repterminationtype = 5; - result = ae_false; - return result; - } - if( ae_fp_less_eq(ae_sqrt(v, _state),state->epsg) ) - { - - /* - * Gradient is small enough - */ - state->repterminationtype = 4; - result = ae_false; - return result; - } - if( !state->innerresetneeded ) - { - - /* - * These conditions are checked only when no inner reset was requested by user - */ - if( ae_fp_less_eq(state->fold-state->f,state->epsf*ae_maxreal(ae_fabs(state->fold, _state), ae_maxreal(ae_fabs(state->f, _state), 1.0, _state), _state)) ) - { - - /* - * F(k+1)-F(k) is small enough - */ - state->repterminationtype = 1; - result = ae_false; - return result; - } - if( ae_fp_less_eq(state->lastscaledstep,state->epsx) ) - { - - /* - * X(k+1)-X(k) is small enough - */ - state->repterminationtype = 2; - result = ae_false; - return result; - } - } - if( state->rstimer<=0 ) - { - - /* - * Too many subsequent restarts - */ - state->repterminationtype = 7; - result = ae_false; - return result; - } - - /* - * Shift Xk/Dk, update other information - */ - ae_v_move(&state->xk.ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&state->dk.ptr.p_double[0], 1, &state->dn.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->fold = state->f; - state->k = state->k+1; - goto lbl_31; -lbl_32: - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = n; - state->rstate.ia.ptr.p_int[1] = i; - state->rstate.ra.ptr.p_double[0] = betak; - state->rstate.ra.ptr.p_double[1] = v; - state->rstate.ra.ptr.p_double[2] = vv; - return result; -} - - -/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic gradient. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function at the initial point -(note: future versions may also perform check at the final point) and -compares numerical gradient with analytic one provided by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both gradients and specific components highlighted as -suspicious by the OptGuard. - -The primary OptGuard report can be retrieved with mincgoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with mincgsetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -void mincgoptguardgradient(mincgstate* state, - double teststep, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(teststep, _state), "MinCGOptGuardGradient: TestStep contains NaN or INF", _state); - ae_assert(ae_fp_greater_eq(teststep,(double)(0)), "MinCGOptGuardGradient: invalid argument TestStep(TestStep<0)", _state); - state->teststep = teststep; -} - - -/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) -b) nonsmooth target function (non-C1) - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void mincgoptguardsmoothness(mincgstate* state, - ae_int_t level, - ae_state *_state) -{ - - - ae_assert(level==0||level==1, "MinCGOptGuardSmoothness: unexpected value of level parameter", _state); - state->smoothnessguardlevel = level; -} - - -/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -=== PRIMARY REPORT ======================================================= - -OptGuard performs several checks which are intended to catch common errors -in the implementation of nonlinear function/gradient: -* incorrect analytic gradient -* discontinuous (non-C0) target functions (constraints) -* nonsmooth (non-C1) target functions (constraints) - -Each of these checks is activated with appropriate function: -* mincgoptguardgradient() for gradient verification -* mincgoptguardsmoothness() for C0/C1 checks - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradvidx for specific variable (gradient element) suspected - * rep.badgradxbase, a point where gradient is tested - * rep.badgraduser, user-provided gradient (stored as 2D matrix with - single row in order to make report structure compatible with more - complex optimizers like MinNLC or MinLM) - * rep.badgradnum, reference gradient obtained via numerical - differentiation (stored as 2D matrix with single row in order to make - report structure compatible with more complex optimizers like MinNLC - or MinLM) -* rep.nonc0suspected -* rep.nonc1suspected - -=== ADDITIONAL REPORTS/LOGS ============================================== - -Several different tests are performed to catch C0/C1 errors, you can find -out specific test signaled error by looking to: -* rep.nonc0test0positive, for non-C0 test #0 -* rep.nonc1test0positive, for non-C1 test #0 -* rep.nonc1test1positive, for non-C1 test #1 - -Additional information (including line search logs) can be obtained by -means of: -* mincgoptguardnonc1test0results() -* mincgoptguardnonc1test1results() -which return detailed error reports, specific points where discontinuities -were found, and so on. - -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - generic OptGuard report; more detailed reports can be - retrieved with other functions. - -NOTE: false negatives (nonsmooth problems are not identified as nonsmooth - ones) are possible although unlikely. - - The reason is that you need to make several evaluations around - nonsmoothness in order to accumulate enough information about - function curvature. Say, if you start right from the nonsmooth point, - optimizer simply won't get enough data to understand what is going - wrong before it terminates due to abrupt changes in the derivative. - It is also possible that "unlucky" step will move us to the - termination too quickly. - - Our current approach is to have less than 0.1% false negatives in - our test examples (measured with multiple restarts from random - points), and to have exactly 0% false positives. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void mincgoptguardresults(mincgstate* state, - optguardreport* rep, - ae_state *_state) -{ - - _optguardreport_clear(rep); - - smoothnessmonitorexportreport(&state->smonitor, rep, _state); -} - - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #0 - -Nonsmoothness (non-C1) test #0 studies function values (not gradient!) -obtained during line searches and monitors behavior of the directional -derivative estimate. - -This test is less powerful than test #1, but it does not depend on the -gradient values and thus it is more robust against artifacts introduced by -numerical differentiation. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #0 "strong" report - lngrep - C1 test #0 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void mincgoptguardnonc1test0results(mincgstate* state, - optguardnonc1test0report* strrep, - optguardnonc1test0report* lngrep, - ae_state *_state) -{ - - _optguardnonc1test0report_clear(strrep); - _optguardnonc1test0report_clear(lngrep); - - smoothnessmonitorexportc1test0report(&state->smonitor.nonc1test0strrep, &state->lastscaleused, strrep, _state); - smoothnessmonitorexportc1test0report(&state->smonitor.nonc1test0lngrep, &state->lastscaleused, lngrep, _state); -} - - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #1 - -Nonsmoothness (non-C1) test #1 studies individual components of the -gradient computed during line search. - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #1 "strong" report - lngrep - C1 test #1 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void mincgoptguardnonc1test1results(mincgstate* state, - optguardnonc1test1report* strrep, - optguardnonc1test1report* lngrep, - ae_state *_state) -{ - - _optguardnonc1test1report_clear(strrep); - _optguardnonc1test1report_clear(lngrep); - - smoothnessmonitorexportc1test1report(&state->smonitor.nonc1test1strrep, &state->lastscaleused, strrep, _state); - smoothnessmonitorexportc1test1report(&state->smonitor.nonc1test1lngrep, &state->lastscaleused, lngrep, _state); -} - - -/************************************************************************* -Conjugate gradient results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report: - * Rep.TerminationType completetion code: - * -8 internal integrity control detected infinite - or NAN values in function/gradient. Abnormal - termination signalled. - * -7 gradient verification failed. - See MinCGSetGradientCheck() for more information. - * 1 relative function improvement is no more than - EpsF. - * 2 relative step is no more than EpsX. - * 4 gradient norm is no more than EpsG - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible, - we return best X found so far - * 8 terminated by user - * Rep.IterationsCount contains iterations count - * NFEV countains number of function calculations - - -- ALGLIB -- - Copyright 20.04.2009 by Bochkanov Sergey -*************************************************************************/ -void mincgresults(mincgstate* state, - /* Real */ ae_vector* x, - mincgreport* rep, - ae_state *_state) -{ - - ae_vector_clear(x); - _mincgreport_clear(rep); - - mincgresultsbuf(state, x, rep, _state); -} - - -/************************************************************************* -Conjugate gradient results - -Buffered implementation of MinCGResults(), which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 20.04.2009 by Bochkanov Sergey -*************************************************************************/ -void mincgresultsbuf(mincgstate* state, - /* Real */ ae_vector* x, - mincgreport* rep, - ae_state *_state) -{ - - - if( x->cntn ) - { - ae_vector_set_length(x, state->n, _state); - } - ae_v_move(&x->ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - rep->iterationscount = state->repiterationscount; - rep->nfev = state->repnfev; - rep->terminationtype = state->repterminationtype; -} - - -/************************************************************************* -This subroutine restarts CG algorithm from new point. All optimization -parameters are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure used to store algorithm state. - X - new starting point. - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgrestartfrom(mincgstate* state, - /* Real */ ae_vector* x, - ae_state *_state) -{ - - - ae_assert(x->cnt>=state->n, "MinCGRestartFrom: Length(X)n, _state), "MinCGCreate: X contains infinite or NaN values!", _state); - ae_v_move(&state->xbase.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - mincgsuggeststep(state, 0.0, _state); - ae_vector_set_length(&state->rstate.ia, 1+1, _state); - ae_vector_set_length(&state->rstate.ra, 2+1, _state); - state->rstate.stage = -1; - mincg_clearrequestfields(state, _state); -} - - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void mincgrequesttermination(mincgstate* state, ae_state *_state) -{ - - - state->userterminationneeded = ae_true; -} - - -/************************************************************************* -Faster version of MinCGSetPrecDiag(), for time-critical parts of code, -without safety checks. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetprecdiagfast(mincgstate* state, - /* Real */ ae_vector* d, - ae_state *_state) -{ - ae_int_t i; - - - rvectorsetlengthatleast(&state->diagh, state->n, _state); - rvectorsetlengthatleast(&state->diaghl2, state->n, _state); - state->prectype = 2; - state->vcnt = 0; - state->innerresetneeded = ae_true; - for(i=0; i<=state->n-1; i++) - { - state->diagh.ptr.p_double[i] = d->ptr.p_double[i]; - state->diaghl2.ptr.p_double[i] = 0.0; - } -} - - -/************************************************************************* -This function sets low-rank preconditioner for Hessian matrix H=D+V'*C*V, -where: -* H is a Hessian matrix, which is approximated by D/V/C -* D=D1+D2 is a diagonal matrix, which includes two positive definite terms: - * constant term D1 (is not updated or infrequently updated) - * variable term D2 (can be cheaply updated from iteration to iteration) -* V is a low-rank correction -* C is a diagonal factor of low-rank correction - -Preconditioner P is calculated using approximate Woodburry formula: - P = D^(-1) - D^(-1)*V'*(C^(-1)+V*D1^(-1)*V')^(-1)*V*D^(-1) - = D^(-1) - D^(-1)*VC'*VC*D^(-1), -where - VC = sqrt(B)*V - B = (C^(-1)+V*D1^(-1)*V')^(-1) - -Note that B is calculated using constant term (D1) only, which allows us -to update D2 without recalculation of B or VC. Such preconditioner is -exact when D2 is zero. When D2 is non-zero, it is only approximation, but -very good and cheap one. - -This function accepts D1, V, C. -D2 is set to zero by default. - -Cost of this update is O(N*VCnt*VCnt), but D2 can be updated in just O(N) -by MinCGSetPrecVarPart. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetpreclowrankfast(mincgstate* state, - /* Real */ ae_vector* d1, - /* Real */ ae_vector* c, - /* Real */ ae_matrix* v, - ae_int_t vcnt, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t n; - double t; - ae_matrix b; - - ae_frame_make(_state, &_frame_block); - memset(&b, 0, sizeof(b)); - ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true); - - if( vcnt==0 ) - { - mincgsetprecdiagfast(state, d1, _state); - ae_frame_leave(_state); - return; - } - n = state->n; - ae_matrix_set_length(&b, vcnt, vcnt, _state); - rvectorsetlengthatleast(&state->diagh, n, _state); - rvectorsetlengthatleast(&state->diaghl2, n, _state); - rmatrixsetlengthatleast(&state->vcorr, vcnt, n, _state); - state->prectype = 2; - state->vcnt = vcnt; - state->innerresetneeded = ae_true; - for(i=0; i<=n-1; i++) - { - state->diagh.ptr.p_double[i] = d1->ptr.p_double[i]; - state->diaghl2.ptr.p_double[i] = 0.0; - } - for(i=0; i<=vcnt-1; i++) - { - for(j=i; j<=vcnt-1; j++) - { - t = (double)(0); - for(k=0; k<=n-1; k++) - { - t = t+v->ptr.pp_double[i][k]*v->ptr.pp_double[j][k]/d1->ptr.p_double[k]; - } - b.ptr.pp_double[i][j] = t; - } - b.ptr.pp_double[i][i] = b.ptr.pp_double[i][i]+1.0/c->ptr.p_double[i]; - } - if( !spdmatrixcholeskyrec(&b, 0, vcnt, ae_true, &state->work0, _state) ) - { - state->vcnt = 0; - ae_frame_leave(_state); - return; - } - for(i=0; i<=vcnt-1; i++) - { - ae_v_move(&state->vcorr.ptr.pp_double[i][0], 1, &v->ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - for(j=0; j<=i-1; j++) - { - t = b.ptr.pp_double[j][i]; - ae_v_subd(&state->vcorr.ptr.pp_double[i][0], 1, &state->vcorr.ptr.pp_double[j][0], 1, ae_v_len(0,n-1), t); - } - t = 1/b.ptr.pp_double[i][i]; - ae_v_muld(&state->vcorr.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), t); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function updates variable part (diagonal matrix D2) -of low-rank preconditioner. - -This update is very cheap and takes just O(N) time. - -It has no effect with default preconditioner. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetprecvarpart(mincgstate* state, - /* Real */ ae_vector* d2, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - - - n = state->n; - for(i=0; i<=n-1; i++) - { - state->diaghl2.ptr.p_double[i] = d2->ptr.p_double[i]; - } -} - - -/************************************************************************* -Clears request fileds (to be sure that we don't forgot to clear something) -*************************************************************************/ -static void mincg_clearrequestfields(mincgstate* state, ae_state *_state) -{ - - - state->needf = ae_false; - state->needfg = ae_false; - state->xupdated = ae_false; - state->lsstart = ae_false; - state->lsend = ae_false; - state->algpowerup = ae_false; -} - - -/************************************************************************* -This function calculates preconditioned product H^(-1)*x and stores result -back into X. Work0[] and Work1[] are used as temporaries (size must be at -least N; this function doesn't allocate arrays). - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -static void mincg_preconditionedmultiply(mincgstate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* work0, - /* Real */ ae_vector* work1, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - ae_int_t vcnt; - double v; - - - n = state->n; - vcnt = state->vcnt; - if( state->prectype==0 ) - { - return; - } - if( state->prectype==3 ) - { - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = x->ptr.p_double[i]*state->s.ptr.p_double[i]*state->s.ptr.p_double[i]; - } - return; - } - ae_assert(state->prectype==2, "MinCG: internal error (unexpected PrecType)", _state); - - /* - * handle part common for VCnt=0 and VCnt<>0 - */ - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = x->ptr.p_double[i]/(state->diagh.ptr.p_double[i]+state->diaghl2.ptr.p_double[i]); - } - - /* - * if VCnt>0 - */ - if( vcnt>0 ) - { - for(i=0; i<=vcnt-1; i++) - { - v = ae_v_dotproduct(&state->vcorr.ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - work0->ptr.p_double[i] = v; - } - for(i=0; i<=n-1; i++) - { - work1->ptr.p_double[i] = (double)(0); - } - for(i=0; i<=vcnt-1; i++) - { - v = work0->ptr.p_double[i]; - ae_v_addd(&state->work1.ptr.p_double[0], 1, &state->vcorr.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v); - } - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = x->ptr.p_double[i]-state->work1.ptr.p_double[i]/(state->diagh.ptr.p_double[i]+state->diaghl2.ptr.p_double[i]); - } - } -} - - -/************************************************************************* -This function calculates preconditioned product x'*H^(-1)*y. Work0[] and -Work1[] are used as temporaries (size must be at least N; this function -doesn't allocate arrays). - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -static double mincg_preconditionedmultiply2(mincgstate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* work0, - /* Real */ ae_vector* work1, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - ae_int_t vcnt; - double v0; - double v1; - double result; - - - n = state->n; - vcnt = state->vcnt; - - /* - * no preconditioning - */ - if( state->prectype==0 ) - { - v0 = ae_v_dotproduct(&x->ptr.p_double[0], 1, &y->ptr.p_double[0], 1, ae_v_len(0,n-1)); - result = v0; - return result; - } - if( state->prectype==3 ) - { - result = (double)(0); - for(i=0; i<=n-1; i++) - { - result = result+x->ptr.p_double[i]*state->s.ptr.p_double[i]*state->s.ptr.p_double[i]*y->ptr.p_double[i]; - } - return result; - } - ae_assert(state->prectype==2, "MinCG: internal error (unexpected PrecType)", _state); - - /* - * low rank preconditioning - */ - result = 0.0; - for(i=0; i<=n-1; i++) - { - result = result+x->ptr.p_double[i]*y->ptr.p_double[i]/(state->diagh.ptr.p_double[i]+state->diaghl2.ptr.p_double[i]); - } - if( vcnt>0 ) - { - for(i=0; i<=n-1; i++) - { - work0->ptr.p_double[i] = x->ptr.p_double[i]/(state->diagh.ptr.p_double[i]+state->diaghl2.ptr.p_double[i]); - work1->ptr.p_double[i] = y->ptr.p_double[i]/(state->diagh.ptr.p_double[i]+state->diaghl2.ptr.p_double[i]); - } - for(i=0; i<=vcnt-1; i++) - { - v0 = ae_v_dotproduct(&work0->ptr.p_double[0], 1, &state->vcorr.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - v1 = ae_v_dotproduct(&work1->ptr.p_double[0], 1, &state->vcorr.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - result = result-v0*v1; - } - } - return result; -} - - -/************************************************************************* -Internal initialization subroutine - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -static void mincg_mincginitinternal(ae_int_t n, - double diffstep, - mincgstate* state, - ae_state *_state) -{ - ae_int_t i; - - - - /* - * Initialize - */ - state->teststep = (double)(0); - state->smoothnessguardlevel = 0; - smoothnessmonitorinit(&state->smonitor, &state->s, 0, 0, ae_false, _state); - state->n = n; - state->diffstep = diffstep; - state->lastgoodstep = (double)(0); - mincgsetcond(state, (double)(0), (double)(0), (double)(0), 0, _state); - mincgsetxrep(state, ae_false, _state); - mincgsetdrep(state, ae_false, _state); - mincgsetstpmax(state, (double)(0), _state); - mincgsetcgtype(state, -1, _state); - mincgsetprecdefault(state, _state); - ae_vector_set_length(&state->xk, n, _state); - ae_vector_set_length(&state->dk, n, _state); - ae_vector_set_length(&state->xn, n, _state); - ae_vector_set_length(&state->dn, n, _state); - ae_vector_set_length(&state->x, n, _state); - ae_vector_set_length(&state->d, n, _state); - ae_vector_set_length(&state->g, n, _state); - ae_vector_set_length(&state->work0, n, _state); - ae_vector_set_length(&state->work1, n, _state); - ae_vector_set_length(&state->yk, n, _state); - ae_vector_set_length(&state->s, n, _state); - ae_vector_set_length(&state->invs, n, _state); - ae_vector_set_length(&state->lastscaleused, n, _state); - rvectorsetlengthatleast(&state->xbase, n, _state); - for(i=0; i<=n-1; i++) - { - state->s.ptr.p_double[i] = 1.0; - state->invs.ptr.p_double[i] = 1.0; - state->lastscaleused.ptr.p_double[i] = 1.0; - } -} - - -void _mincgstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - mincgstate *p = (mincgstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->diagh, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->diaghl2, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->vcorr, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xk, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dk, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xn, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->dn, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->yk, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xbase, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); - _linminstate_init(&p->lstate, _state, make_automatic); - ae_vector_init(&p->work0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->work1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->invs, 0, DT_REAL, _state, make_automatic); - _smoothnessmonitor_init(&p->smonitor, _state, make_automatic); - ae_vector_init(&p->lastscaleused, 0, DT_REAL, _state, make_automatic); -} - - -void _mincgstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - mincgstate *dst = (mincgstate*)_dst; - mincgstate *src = (mincgstate*)_src; - dst->n = src->n; - dst->epsg = src->epsg; - dst->epsf = src->epsf; - dst->epsx = src->epsx; - dst->maxits = src->maxits; - dst->stpmax = src->stpmax; - dst->suggestedstep = src->suggestedstep; - dst->xrep = src->xrep; - dst->drep = src->drep; - dst->cgtype = src->cgtype; - dst->prectype = src->prectype; - ae_vector_init_copy(&dst->diagh, &src->diagh, _state, make_automatic); - ae_vector_init_copy(&dst->diaghl2, &src->diaghl2, _state, make_automatic); - ae_matrix_init_copy(&dst->vcorr, &src->vcorr, _state, make_automatic); - dst->vcnt = src->vcnt; - ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic); - dst->diffstep = src->diffstep; - dst->nfev = src->nfev; - dst->mcstage = src->mcstage; - dst->k = src->k; - ae_vector_init_copy(&dst->xk, &src->xk, _state, make_automatic); - ae_vector_init_copy(&dst->dk, &src->dk, _state, make_automatic); - ae_vector_init_copy(&dst->xn, &src->xn, _state, make_automatic); - ae_vector_init_copy(&dst->dn, &src->dn, _state, make_automatic); - ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic); - dst->fold = src->fold; - dst->stp = src->stp; - dst->curstpmax = src->curstpmax; - ae_vector_init_copy(&dst->yk, &src->yk, _state, make_automatic); - dst->lastgoodstep = src->lastgoodstep; - dst->lastscaledstep = src->lastscaledstep; - dst->mcinfo = src->mcinfo; - dst->innerresetneeded = src->innerresetneeded; - dst->terminationneeded = src->terminationneeded; - dst->trimthreshold = src->trimthreshold; - ae_vector_init_copy(&dst->xbase, &src->xbase, _state, make_automatic); - dst->rstimer = src->rstimer; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - dst->f = src->f; - ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic); - dst->needf = src->needf; - dst->needfg = src->needfg; - dst->xupdated = src->xupdated; - dst->algpowerup = src->algpowerup; - dst->lsstart = src->lsstart; - dst->lsend = src->lsend; - dst->userterminationneeded = src->userterminationneeded; - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); - dst->repiterationscount = src->repiterationscount; - dst->repnfev = src->repnfev; - dst->repterminationtype = src->repterminationtype; - dst->debugrestartscount = src->debugrestartscount; - _linminstate_init_copy(&dst->lstate, &src->lstate, _state, make_automatic); - dst->fbase = src->fbase; - dst->fm2 = src->fm2; - dst->fm1 = src->fm1; - dst->fp1 = src->fp1; - dst->fp2 = src->fp2; - dst->betahs = src->betahs; - dst->betady = src->betady; - ae_vector_init_copy(&dst->work0, &src->work0, _state, make_automatic); - ae_vector_init_copy(&dst->work1, &src->work1, _state, make_automatic); - ae_vector_init_copy(&dst->invs, &src->invs, _state, make_automatic); - dst->teststep = src->teststep; - dst->smoothnessguardlevel = src->smoothnessguardlevel; - _smoothnessmonitor_init_copy(&dst->smonitor, &src->smonitor, _state, make_automatic); - ae_vector_init_copy(&dst->lastscaleused, &src->lastscaleused, _state, make_automatic); -} - - -void _mincgstate_clear(void* _p) -{ - mincgstate *p = (mincgstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->diagh); - ae_vector_clear(&p->diaghl2); - ae_matrix_clear(&p->vcorr); - ae_vector_clear(&p->s); - ae_vector_clear(&p->xk); - ae_vector_clear(&p->dk); - ae_vector_clear(&p->xn); - ae_vector_clear(&p->dn); - ae_vector_clear(&p->d); - ae_vector_clear(&p->yk); - ae_vector_clear(&p->xbase); - ae_vector_clear(&p->x); - ae_vector_clear(&p->g); - _rcommstate_clear(&p->rstate); - _linminstate_clear(&p->lstate); - ae_vector_clear(&p->work0); - ae_vector_clear(&p->work1); - ae_vector_clear(&p->invs); - _smoothnessmonitor_clear(&p->smonitor); - ae_vector_clear(&p->lastscaleused); -} - - -void _mincgstate_destroy(void* _p) -{ - mincgstate *p = (mincgstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->diagh); - ae_vector_destroy(&p->diaghl2); - ae_matrix_destroy(&p->vcorr); - ae_vector_destroy(&p->s); - ae_vector_destroy(&p->xk); - ae_vector_destroy(&p->dk); - ae_vector_destroy(&p->xn); - ae_vector_destroy(&p->dn); - ae_vector_destroy(&p->d); - ae_vector_destroy(&p->yk); - ae_vector_destroy(&p->xbase); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->g); - _rcommstate_destroy(&p->rstate); - _linminstate_destroy(&p->lstate); - ae_vector_destroy(&p->work0); - ae_vector_destroy(&p->work1); - ae_vector_destroy(&p->invs); - _smoothnessmonitor_destroy(&p->smonitor); - ae_vector_destroy(&p->lastscaleused); -} - - -void _mincgreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - mincgreport *p = (mincgreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _mincgreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - mincgreport *dst = (mincgreport*)_dst; - mincgreport *src = (mincgreport*)_src; - dst->iterationscount = src->iterationscount; - dst->nfev = src->nfev; - dst->terminationtype = src->terminationtype; -} - - -void _mincgreport_clear(void* _p) -{ - mincgreport *p = (mincgreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _mincgreport_destroy(void* _p) -{ - mincgreport *p = (mincgreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_MINLM) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* - IMPROVED LEVENBERG-MARQUARDT METHOD FOR - NON-LINEAR LEAST SQUARES OPTIMIZATION - -DESCRIPTION: -This function is used to find minimum of function which is represented as -sum of squares: - F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1]) -using value of function vector f[] and Jacobian of f[]. - - -REQUIREMENTS: -This algorithm will request following information during its operation: - -* function vector f[] at given point X -* function vector f[] and Jacobian of f[] (simultaneously) at given point - -There are several overloaded versions of MinLMOptimize() function which -correspond to different LM-like optimization algorithms provided by this -unit. You should choose version which accepts fvec() and jac() callbacks. -First one is used to calculate f[] at given point, second one calculates -f[] and Jacobian df[i]/dx[j]. - -You can try to initialize MinLMState structure with VJ function and then -use incorrect version of MinLMOptimize() (for example, version which -works with general form function and does not provide Jacobian), but it -will lead to exception being thrown after first attempt to calculate -Jacobian. - - -USAGE: -1. User initializes algorithm state with MinLMCreateVJ() call -2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and - other functions -3. User calls MinLMOptimize() function which takes algorithm state and - callback functions. -4. User calls MinLMResults() to get solution -5. Optionally, user may call MinLMRestartFrom() to solve another problem - with same N/M but another starting point and/or another function. - MinLMRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - dimension, N>1 - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - M - number of functions f[i] - X - initial solution, array[0..N-1] - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. you may tune stopping conditions with MinLMSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use MinLMSetStpMax() function to bound algorithm's steps. - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmcreatevj(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* x, - minlmstate* state, - ae_state *_state) -{ - - _minlmstate_clear(state); - - ae_assert(n>=1, "MinLMCreateVJ: N<1!", _state); - ae_assert(m>=1, "MinLMCreateVJ: M<1!", _state); - ae_assert(x->cnt>=n, "MinLMCreateVJ: Length(X)teststep = (double)(0); - state->n = n; - state->m = m; - state->algomode = 1; - state->hasf = ae_false; - state->hasfi = ae_true; - state->hasg = ae_false; - - /* - * second stage of initialization - */ - minlm_lmprepare(n, m, ae_false, state, _state); - minlmsetacctype(state, 0, _state); - minlmsetcond(state, (double)(0), 0, _state); - minlmsetxrep(state, ae_false, _state); - minlmsetstpmax(state, (double)(0), _state); - minlmrestartfrom(state, x, _state); -} - - -/************************************************************************* - IMPROVED LEVENBERG-MARQUARDT METHOD FOR - NON-LINEAR LEAST SQUARES OPTIMIZATION - -DESCRIPTION: -This function is used to find minimum of function which is represented as -sum of squares: - F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1]) -using value of function vector f[] only. Finite differences are used to -calculate Jacobian. - - -REQUIREMENTS: -This algorithm will request following information during its operation: -* function vector f[] at given point X - -There are several overloaded versions of MinLMOptimize() function which -correspond to different LM-like optimization algorithms provided by this -unit. You should choose version which accepts fvec() callback. - -You can try to initialize MinLMState structure with VJ function and then -use incorrect version of MinLMOptimize() (for example, version which -works with general form function and does not accept function vector), but -it will lead to exception being thrown after first attempt to calculate -Jacobian. - - -USAGE: -1. User initializes algorithm state with MinLMCreateV() call -2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and - other functions -3. User calls MinLMOptimize() function which takes algorithm state and - callback functions. -4. User calls MinLMResults() to get solution -5. Optionally, user may call MinLMRestartFrom() to solve another problem - with same N/M but another starting point and/or another function. - MinLMRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - dimension, N>1 - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - M - number of functions f[i] - X - initial solution, array[0..N-1] - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -See also MinLMIteration, MinLMResults. - -NOTES: -1. you may tune stopping conditions with MinLMSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use MinLMSetStpMax() function to bound algorithm's steps. - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmcreatev(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* x, - double diffstep, - minlmstate* state, - ae_state *_state) -{ - - _minlmstate_clear(state); - - ae_assert(ae_isfinite(diffstep, _state), "MinLMCreateV: DiffStep is not finite!", _state); - ae_assert(ae_fp_greater(diffstep,(double)(0)), "MinLMCreateV: DiffStep<=0!", _state); - ae_assert(n>=1, "MinLMCreateV: N<1!", _state); - ae_assert(m>=1, "MinLMCreateV: M<1!", _state); - ae_assert(x->cnt>=n, "MinLMCreateV: Length(X)teststep = (double)(0); - state->n = n; - state->m = m; - state->algomode = 0; - state->hasf = ae_false; - state->hasfi = ae_true; - state->hasg = ae_false; - state->diffstep = diffstep; - - /* - * Second stage of initialization - */ - minlm_lmprepare(n, m, ae_false, state, _state); - minlmsetacctype(state, 1, _state); - minlmsetcond(state, (double)(0), 0, _state); - minlmsetxrep(state, ae_false, _state); - minlmsetstpmax(state, (double)(0), _state); - minlmrestartfrom(state, x, _state); -} - - -/************************************************************************* - LEVENBERG-MARQUARDT-LIKE METHOD FOR NON-LINEAR OPTIMIZATION - -DESCRIPTION: -This function is used to find minimum of general form (not "sum-of- --squares") function - F = F(x[0], ..., x[n-1]) -using its gradient and Hessian. Levenberg-Marquardt modification with -L-BFGS pre-optimization and internal pre-conditioned L-BFGS optimization -after each Levenberg-Marquardt step is used. - - -REQUIREMENTS: -This algorithm will request following information during its operation: - -* function value F at given point X -* F and gradient G (simultaneously) at given point X -* F, G and Hessian H (simultaneously) at given point X - -There are several overloaded versions of MinLMOptimize() function which -correspond to different LM-like optimization algorithms provided by this -unit. You should choose version which accepts func(), grad() and hess() -function pointers. First pointer is used to calculate F at given point, -second one calculates F(x) and grad F(x), third one calculates F(x), -grad F(x), hess F(x). - -You can try to initialize MinLMState structure with FGH-function and then -use incorrect version of MinLMOptimize() (for example, version which does -not provide Hessian matrix), but it will lead to exception being thrown -after first attempt to calculate Hessian. - - -USAGE: -1. User initializes algorithm state with MinLMCreateFGH() call -2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and - other functions -3. User calls MinLMOptimize() function which takes algorithm state and - pointers (delegates, etc.) to callback functions. -4. User calls MinLMResults() to get solution -5. Optionally, user may call MinLMRestartFrom() to solve another problem - with same N but another starting point and/or another function. - MinLMRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - dimension, N>1 - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - initial solution, array[0..N-1] - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. you may tune stopping conditions with MinLMSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use MinLMSetStpMax() function to bound algorithm's steps. - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmcreatefgh(ae_int_t n, - /* Real */ ae_vector* x, - minlmstate* state, - ae_state *_state) -{ - - _minlmstate_clear(state); - - ae_assert(n>=1, "MinLMCreateFGH: N<1!", _state); - ae_assert(x->cnt>=n, "MinLMCreateFGH: Length(X)teststep = (double)(0); - state->n = n; - state->m = 0; - state->algomode = 2; - state->hasf = ae_true; - state->hasfi = ae_false; - state->hasg = ae_true; - - /* - * init2 - */ - minlm_lmprepare(n, 0, ae_true, state, _state); - minlmsetacctype(state, 2, _state); - minlmsetcond(state, (double)(0), 0, _state); - minlmsetxrep(state, ae_false, _state); - minlmsetstpmax(state, (double)(0), _state); - minlmrestartfrom(state, x, _state); -} - - -/************************************************************************* -This function sets stopping conditions for Levenberg-Marquardt optimization -algorithm. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - ste pvector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinLMSetScale() - Recommended values: 1E-9 ... 1E-12. - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. Only Levenberg-Marquardt - iterations are counted (L-BFGS/CG iterations are NOT - counted because their cost is very low compared to that of - LM). - -Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic -stopping criterion selection (small EpsX). - -NOTE: it is not recommended to set large EpsX (say, 0.001). Because LM is - a second-order method, it performs very precise steps anyway. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlmsetcond(minlmstate* state, - double epsx, - ae_int_t maxits, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(epsx, _state), "MinLMSetCond: EpsX is not finite number!", _state); - ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinLMSetCond: negative EpsX!", _state); - ae_assert(maxits>=0, "MinLMSetCond: negative MaxIts!", _state); - if( ae_fp_eq(epsx,(double)(0))&&maxits==0 ) - { - epsx = 1.0E-9; - } - state->epsx = epsx; - state->maxits = maxits; -} - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinLMOptimize(). Both Levenberg-Marquardt and internal L-BFGS -iterations are reported. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlmsetxrep(minlmstate* state, ae_bool needxrep, ae_state *_state) -{ - - - state->xrep = needxrep; -} - - -/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which leads to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - -NOTE: non-zero StpMax leads to moderate performance degradation because -intermediate step of preconditioned L-BFGS optimization is incompatible -with limits on step size. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlmsetstpmax(minlmstate* state, double stpmax, ae_state *_state) -{ - - - ae_assert(ae_isfinite(stpmax, _state), "MinLMSetStpMax: StpMax is not finite!", _state); - ae_assert(ae_fp_greater_eq(stpmax,(double)(0)), "MinLMSetStpMax: StpMax<0!", _state); - state->stpmax = stpmax; -} - - -/************************************************************************* -This function sets scaling coefficients for LM optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Generally, scale is NOT considered to be a form of preconditioner. But LM -optimizer is unique in that it uses scaling matrix both in the stopping -condition tests and as Marquardt damping factor. - -Proper scaling is very important for the algorithm performance. It is less -important for the quality of results, but still has some influence (it is -easier to converge when variables are properly scaled, so premature -stopping is possible when very badly scalled variables are combined with -relaxed stopping conditions). - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minlmsetscale(minlmstate* state, - /* Real */ ae_vector* s, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(s->cnt>=state->n, "MinLMSetScale: Length(S)n-1; i++) - { - ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinLMSetScale: S contains infinite or NAN elements", _state); - ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "MinLMSetScale: S contains zero elements", _state); - state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state); - } -} - - -/************************************************************************* -This function sets boundary constraints for LM optimizer - -Boundary constraints are inactive by default (after initial creation). -They are preserved until explicitly turned off with another SetBC() call. - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF (latter is recommended because - it will allow solver to use better algorithm). - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF (latter is recommended because - it will allow solver to use better algorithm). - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - -NOTE 2: this solver has following useful properties: -* bound constraints are always satisfied exactly -* function is evaluated only INSIDE area specified by bound constraints - or at its boundary - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minlmsetbc(minlmstate* state, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - - - n = state->n; - ae_assert(bndl->cnt>=n, "MinLMSetBC: Length(BndL)cnt>=n, "MinLMSetBC: Length(BndU)ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "MinLMSetBC: BndL contains NAN or +INF", _state); - ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "MinLMSetBC: BndU contains NAN or -INF", _state); - state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i]; - state->havebndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state); - state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i]; - state->havebndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state); - } -} - - -/************************************************************************* -This function sets general linear constraints for LM optimizer - -Linear constraints are inactive by default (after initial creation). They -are preserved until explicitly turned off with another minlmsetlc() call. - -INPUT PARAMETERS: - State - structure stores algorithm state - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -IMPORTANT: if you have linear constraints, it is strongly recommended to - set scale of variables with minlmsetscale(). QP solver which is - used to calculate linearly constrained steps heavily relies on - good scaling of input problems. - -IMPORTANT: solvers created with minlmcreatefgh() do not support linear - constraints. - -NOTE: linear (non-bound) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations. - -NOTE: general linear constraints add significant overhead to solution - process. Although solver performs roughly same amount of iterations - (when compared with similar box-only constrained problem), each - iteration now involves solution of linearly constrained QP - subproblem, which requires ~3-5 times more Cholesky decompositions. - Thus, if you can reformulate your problem in such way this it has - only box constraints, it may be beneficial to do so. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minlmsetlc(minlmstate* state, - /* Real */ ae_matrix* c, - /* Integer */ ae_vector* ct, - ae_int_t k, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - - - n = state->n; - - /* - * First, check for errors in the inputs - */ - ae_assert(k>=0, "MinLMSetLC: K<0", _state); - ae_assert(c->cols>=n+1||k==0, "MinLMSetLC: Cols(C)rows>=k, "MinLMSetLC: Rows(C)cnt>=k, "MinLMSetLC: Length(CT)nec = 0; - state->nic = 0; - return; - } - - /* - * Equality constraints are stored first, in the upper - * NEC rows of State.CLEIC matrix. Inequality constraints - * are stored in the next NIC rows. - * - * NOTE: we convert inequality constraints to the form - * A*x<=b before copying them. - */ - rmatrixsetlengthatleast(&state->cleic, k, n+1, _state); - state->nec = 0; - state->nic = 0; - for(i=0; i<=k-1; i++) - { - if( ct->ptr.p_int[i]==0 ) - { - ae_v_move(&state->cleic.ptr.pp_double[state->nec][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n)); - state->nec = state->nec+1; - } - } - for(i=0; i<=k-1; i++) - { - if( ct->ptr.p_int[i]!=0 ) - { - if( ct->ptr.p_int[i]>0 ) - { - ae_v_moveneg(&state->cleic.ptr.pp_double[state->nec+state->nic][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n)); - } - else - { - ae_v_move(&state->cleic.ptr.pp_double[state->nec+state->nic][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n)); - } - state->nic = state->nic+1; - } - } -} - - -/************************************************************************* -This function is used to change acceleration settings - -You can choose between three acceleration strategies: -* AccType=0, no acceleration. -* AccType=1, secant updates are used to update quadratic model after each - iteration. After fixed number of iterations (or after model breakdown) - we recalculate quadratic model using analytic Jacobian or finite - differences. Number of secant-based iterations depends on optimization - settings: about 3 iterations - when we have analytic Jacobian, up to 2*N - iterations - when we use finite differences to calculate Jacobian. - -AccType=1 is recommended when Jacobian calculation cost is prohibitively -high (several Mx1 function vector calculations followed by several NxN -Cholesky factorizations are faster than calculation of one M*N Jacobian). -It should also be used when we have no Jacobian, because finite difference -approximation takes too much time to compute. - -Table below list optimization protocols (XYZ protocol corresponds to -MinLMCreateXYZ) and acceleration types they support (and use by default). - -ACCELERATION TYPES SUPPORTED BY OPTIMIZATION PROTOCOLS: - -protocol 0 1 comment -V + + -VJ + + -FGH + - -DEFAULT VALUES: - -protocol 0 1 comment -V x without acceleration it is so slooooooooow -VJ x -FGH x - -NOTE: this function should be called before optimization. Attempt to call -it during algorithm iterations may result in unexpected behavior. - -NOTE: attempt to call this function with unsupported protocol/acceleration -combination will result in exception being thrown. - - -- ALGLIB -- - Copyright 14.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlmsetacctype(minlmstate* state, - ae_int_t acctype, - ae_state *_state) -{ - - - ae_assert((acctype==0||acctype==1)||acctype==2, "MinLMSetAccType: incorrect AccType!", _state); - if( acctype==2 ) - { - acctype = 0; - } - if( acctype==0 ) - { - state->maxmodelage = 0; - state->makeadditers = ae_false; - return; - } - if( acctype==1 ) - { - ae_assert(state->hasfi, "MinLMSetAccType: AccType=1 is incompatible with current protocol!", _state); - if( state->algomode==0 ) - { - state->maxmodelage = 2*state->n; - } - else - { - state->maxmodelage = minlm_smallmodelage; - } - state->makeadditers = ae_false; - return; - } -} - - -/************************************************************************* -NOTES: - -1. Depending on function used to create state structure, this algorithm - may accept Jacobian and/or Hessian and/or gradient. According to the - said above, there ase several versions of this function, which accept - different sets of callbacks. - - This flexibility opens way to subtle errors - you may create state with - MinLMCreateFGH() (optimization using Hessian), but call function which - does not accept Hessian. So when algorithm will request Hessian, there - will be no callback to call. In this case exception will be thrown. - - Be careful to avoid such errors because there is no way to find them at - compile time - you can see them at runtime only. - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -ae_bool minlmiteration(minlmstate* state, ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - ae_bool bflag; - ae_int_t iflag; - double v; - double s; - double t; - double fnew; - ae_int_t i; - ae_int_t k; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - n = state->rstate.ia.ptr.p_int[0]; - m = state->rstate.ia.ptr.p_int[1]; - iflag = state->rstate.ia.ptr.p_int[2]; - i = state->rstate.ia.ptr.p_int[3]; - k = state->rstate.ia.ptr.p_int[4]; - bflag = state->rstate.ba.ptr.p_bool[0]; - v = state->rstate.ra.ptr.p_double[0]; - s = state->rstate.ra.ptr.p_double[1]; - t = state->rstate.ra.ptr.p_double[2]; - fnew = state->rstate.ra.ptr.p_double[3]; - } - else - { - n = 359; - m = -58; - iflag = -919; - i = -909; - k = 81; - bflag = ae_true; - v = 74; - s = -788; - t = 809; - fnew = 205; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - if( state->rstate.stage==1 ) - { - goto lbl_1; - } - if( state->rstate.stage==2 ) - { - goto lbl_2; - } - if( state->rstate.stage==3 ) - { - goto lbl_3; - } - if( state->rstate.stage==4 ) - { - goto lbl_4; - } - if( state->rstate.stage==5 ) - { - goto lbl_5; - } - if( state->rstate.stage==6 ) - { - goto lbl_6; - } - if( state->rstate.stage==7 ) - { - goto lbl_7; - } - if( state->rstate.stage==8 ) - { - goto lbl_8; - } - if( state->rstate.stage==9 ) - { - goto lbl_9; - } - if( state->rstate.stage==10 ) - { - goto lbl_10; - } - if( state->rstate.stage==11 ) - { - goto lbl_11; - } - if( state->rstate.stage==12 ) - { - goto lbl_12; - } - if( state->rstate.stage==13 ) - { - goto lbl_13; - } - if( state->rstate.stage==14 ) - { - goto lbl_14; - } - if( state->rstate.stage==15 ) - { - goto lbl_15; - } - if( state->rstate.stage==16 ) - { - goto lbl_16; - } - if( state->rstate.stage==17 ) - { - goto lbl_17; - } - if( state->rstate.stage==18 ) - { - goto lbl_18; - } - if( state->rstate.stage==19 ) - { - goto lbl_19; - } - if( state->rstate.stage==20 ) - { - goto lbl_20; - } - if( state->rstate.stage==21 ) - { - goto lbl_21; - } - if( state->rstate.stage==22 ) - { - goto lbl_22; - } - if( state->rstate.stage==23 ) - { - goto lbl_23; - } - if( state->rstate.stage==24 ) - { - goto lbl_24; - } - if( state->rstate.stage==25 ) - { - goto lbl_25; - } - if( state->rstate.stage==26 ) - { - goto lbl_26; - } - if( state->rstate.stage==27 ) - { - goto lbl_27; - } - - /* - * Routine body - */ - - /* - * prepare - */ - n = state->n; - m = state->m; - state->repiterationscount = 0; - state->repterminationtype = 0; - state->repnfunc = 0; - state->repnjac = 0; - state->repngrad = 0; - state->repnhess = 0; - state->repncholesky = 0; - state->userterminationneeded = ae_false; - if( m>0 ) - { - smoothnessmonitorinit(&state->smonitor, &state->s, n, m, ae_false, _state); - } - for(i=0; i<=n-1; i++) - { - state->lastscaleused.ptr.p_double[i] = state->s.ptr.p_double[i]; - } - - /* - * Prepare LM step finder and enforce/check feasibility of constraints - */ - if( !minlm_minlmstepfinderinit(&state->finderstate, n, m, state->maxmodelage, state->hasfi, &state->xbase, &state->bndl, &state->bndu, &state->cleic, state->nec, state->nic, &state->s, state->stpmax, state->epsx, _state) ) - { - state->repterminationtype = -3; - result = ae_false; - return result; - } - - /* - * set constraints for obsolete QP solver - */ - minqpsetbc(&state->qpstate, &state->bndl, &state->bndu, _state); - - /* - * Check correctness of the analytic Jacobian - */ - minlm_clearrequestfields(state, _state); - if( !(state->algomode==1&&ae_fp_greater(state->teststep,(double)(0))) ) - { - goto lbl_28; - } - ae_assert(m>0, "MinLM: integrity check failed", _state); -lbl_30: - if( !smoothnessmonitorcheckgradientatx0(&state->smonitor, &state->xbase, &state->s, &state->bndl, &state->bndu, ae_true, state->teststep, _state) ) - { - goto lbl_31; - } - for(i=0; i<=n-1; i++) - { - state->x.ptr.p_double[i] = state->smonitor.x.ptr.p_double[i]; - } - state->needfij = ae_true; - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - state->needfij = ae_false; - for(i=0; i<=m-1; i++) - { - state->smonitor.fi.ptr.p_double[i] = state->fi.ptr.p_double[i]; - for(k=0; k<=n-1; k++) - { - state->smonitor.j.ptr.pp_double[i][k] = state->j.ptr.pp_double[i][k]; - } - } - goto lbl_30; -lbl_31: -lbl_28: - - /* - * Initial report of current point - * - * Note 1: we rewrite State.X twice because - * user may accidentally change it after first call. - * - * Note 2: we set NeedF or NeedFI depending on what - * information about function we have. - */ - if( !state->xrep ) - { - goto lbl_32; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minlm_clearrequestfields(state, _state); - if( !state->hasf ) - { - goto lbl_34; - } - state->needf = ae_true; - state->rstate.stage = 1; - goto lbl_rcomm; -lbl_1: - state->needf = ae_false; - goto lbl_35; -lbl_34: - ae_assert(state->hasfi, "MinLM: internal error 2!", _state); - state->needfi = ae_true; - state->rstate.stage = 2; - goto lbl_rcomm; -lbl_2: - state->needfi = ae_false; - v = ae_v_dotproduct(&state->fi.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1)); - state->f = v; -lbl_35: - state->repnfunc = state->repnfunc+1; - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minlm_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 3; - goto lbl_rcomm; -lbl_3: - state->xupdated = ae_false; -lbl_32: - if( state->userterminationneeded ) - { - - /* - * User requested termination - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->repterminationtype = 8; - result = ae_false; - return result; - } - - /* - * Prepare control variables - */ - state->nu = (double)(1); - state->lambdav = -ae_maxrealnumber; - state->modelage = state->maxmodelage+1; - state->deltaxready = ae_false; - state->deltafready = ae_false; - if( state->algomode==2 ) - { - goto lbl_36; - } - - /* - * Jacobian-based optimization mode - * - * Main cycle. - * - * We move through it until either: - * * one of the stopping conditions is met - * * we decide that stopping conditions are too stringent - * and break from cycle - */ -lbl_38: - if( ae_false ) - { - goto lbl_39; - } - - /* - * First, we have to prepare quadratic model for our function. - * We use BFlag to ensure that model is prepared; - * if it is false at the end of this block, something went wrong. - * - * We may either calculate brand new model or update old one. - * - * Before this block we have: - * * State.XBase - current position. - * * State.DeltaX - if DeltaXReady is True - * * State.DeltaF - if DeltaFReady is True - * - * After this block is over, we will have: - * * State.XBase - base point (unchanged) - * * State.FBase - F(XBase) - * * State.GBase - linear term - * * State.QuadraticModel - quadratic term - * * State.LambdaV - current estimate for lambda - * - * We also clear DeltaXReady/DeltaFReady flags - * after initialization is done. - */ - ae_assert(state->algomode==0||state->algomode==1, "MinLM: integrity check failed", _state); - if( !(state->modelage>state->maxmodelage||!(state->deltaxready&&state->deltafready)) ) - { - goto lbl_40; - } - - /* - * Refresh model (using either finite differences or analytic Jacobian) - */ - if( state->algomode!=0 ) - { - goto lbl_42; - } - - /* - * Optimization using F values only. - * Use finite differences to estimate Jacobian. - */ - ae_assert(state->hasfi, "MinLMIteration: internal error when estimating Jacobian (no f[])", _state); - k = 0; -lbl_44: - if( k>n-1 ) - { - goto lbl_46; - } - - /* - * We guard X[k] from leaving [BndL,BndU]. - * In case BndL=BndU, we assume that derivative in this direction is zero. - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = state->x.ptr.p_double[k]-state->s.ptr.p_double[k]*state->diffstep; - if( state->havebndl.ptr.p_bool[k] ) - { - state->x.ptr.p_double[k] = ae_maxreal(state->x.ptr.p_double[k], state->bndl.ptr.p_double[k], _state); - } - if( state->havebndu.ptr.p_bool[k] ) - { - state->x.ptr.p_double[k] = ae_minreal(state->x.ptr.p_double[k], state->bndu.ptr.p_double[k], _state); - } - state->xm1 = state->x.ptr.p_double[k]; - minlm_clearrequestfields(state, _state); - state->needfi = ae_true; - state->rstate.stage = 4; - goto lbl_rcomm; -lbl_4: - state->repnfunc = state->repnfunc+1; - ae_v_move(&state->fm1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = state->x.ptr.p_double[k]+state->s.ptr.p_double[k]*state->diffstep; - if( state->havebndl.ptr.p_bool[k] ) - { - state->x.ptr.p_double[k] = ae_maxreal(state->x.ptr.p_double[k], state->bndl.ptr.p_double[k], _state); - } - if( state->havebndu.ptr.p_bool[k] ) - { - state->x.ptr.p_double[k] = ae_minreal(state->x.ptr.p_double[k], state->bndu.ptr.p_double[k], _state); - } - state->xp1 = state->x.ptr.p_double[k]; - minlm_clearrequestfields(state, _state); - state->needfi = ae_true; - state->rstate.stage = 5; - goto lbl_rcomm; -lbl_5: - state->repnfunc = state->repnfunc+1; - ae_v_move(&state->fp1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1)); - v = state->xp1-state->xm1; - if( ae_fp_neq(v,(double)(0)) ) - { - v = 1/v; - ae_v_moved(&state->j.ptr.pp_double[0][k], state->j.stride, &state->fp1.ptr.p_double[0], 1, ae_v_len(0,m-1), v); - ae_v_subd(&state->j.ptr.pp_double[0][k], state->j.stride, &state->fm1.ptr.p_double[0], 1, ae_v_len(0,m-1), v); - } - else - { - for(i=0; i<=m-1; i++) - { - state->j.ptr.pp_double[i][k] = (double)(0); - } - } - k = k+1; - goto lbl_44; -lbl_46: - - /* - * Calculate F(XBase) - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minlm_clearrequestfields(state, _state); - state->needfi = ae_true; - state->rstate.stage = 6; - goto lbl_rcomm; -lbl_6: - state->needfi = ae_false; - state->repnfunc = state->repnfunc+1; - state->repnjac = state->repnjac+1; - - /* - * New model - */ - state->modelage = 0; - goto lbl_43; -lbl_42: - - /* - * Obtain f[] and Jacobian - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minlm_clearrequestfields(state, _state); - state->needfij = ae_true; - state->rstate.stage = 7; - goto lbl_rcomm; -lbl_7: - state->needfij = ae_false; - state->repnfunc = state->repnfunc+1; - state->repnjac = state->repnjac+1; - - /* - * New model - */ - state->modelage = 0; -lbl_43: - goto lbl_41; -lbl_40: - - /* - * State.J contains Jacobian or its current approximation; - * refresh it using secant updates: - * - * f(x0+dx) = f(x0) + J*dx, - * J_new = J_old + u*h' - * h = x_new-x_old - * u = (f_new - f_old - J_old*h)/(h'h) - * - * We can explicitly generate h and u, but it is - * preferential to do in-place calculations. Only - * I-th row of J_old is needed to calculate u[I], - * so we can update J row by row in one pass. - * - * NOTE: we expect that State.XBase contains new point, - * State.FBase contains old point, State.DeltaX and - * State.DeltaY contain updates from last step. - */ - ae_assert(state->deltaxready&&state->deltafready, "MinLMIteration: uninitialized DeltaX/DeltaF", _state); - t = ae_v_dotproduct(&state->deltax.ptr.p_double[0], 1, &state->deltax.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_assert(ae_fp_neq(t,(double)(0)), "MinLM: internal error (T=0)", _state); - for(i=0; i<=m-1; i++) - { - v = ae_v_dotproduct(&state->j.ptr.pp_double[i][0], 1, &state->deltax.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = (state->deltaf.ptr.p_double[i]-v)/t; - ae_v_addd(&state->j.ptr.pp_double[i][0], 1, &state->deltax.ptr.p_double[0], 1, ae_v_len(0,n-1), v); - } - ae_v_move(&state->fi.ptr.p_double[0], 1, &state->fibase.ptr.p_double[0], 1, ae_v_len(0,m-1)); - ae_v_add(&state->fi.ptr.p_double[0], 1, &state->deltaf.ptr.p_double[0], 1, ae_v_len(0,m-1)); - - /* - * Increase model age - */ - state->modelage = state->modelage+1; -lbl_41: - rmatrixgemm(n, n, m, 2.0, &state->j, 0, 0, 1, &state->j, 0, 0, 0, 0.0, &state->quadraticmodel, 0, 0, _state); - rmatrixmv(n, m, &state->j, 0, 0, 1, &state->fi, 0, &state->gbase, 0, _state); - ae_v_muld(&state->gbase.ptr.p_double[0], 1, ae_v_len(0,n-1), 2); - v = ae_v_dotproduct(&state->fi.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1)); - state->fbase = v; - ae_v_move(&state->fibase.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1)); - state->deltaxready = ae_false; - state->deltafready = ae_false; - - /* - * Perform integrity check (presense of NAN/INF) - */ - v = state->fbase; - for(i=0; i<=n-1; i++) - { - v = 0.1*v+state->gbase.ptr.p_double[i]; - } - if( !ae_isfinite(v, _state) ) - { - - /* - * Break! - */ - state->repterminationtype = -8; - result = ae_false; - return result; - } - - /* - * If Lambda is not initialized, initialize it using quadratic model - */ - if( ae_fp_less(state->lambdav,(double)(0)) ) - { - state->lambdav = (double)(0); - for(i=0; i<=n-1; i++) - { - state->lambdav = ae_maxreal(state->lambdav, ae_fabs(state->quadraticmodel.ptr.pp_double[i][i], _state)*ae_sqr(state->s.ptr.p_double[i], _state), _state); - } - state->lambdav = 0.001*state->lambdav; - if( ae_fp_eq(state->lambdav,(double)(0)) ) - { - state->lambdav = (double)(1); - } - } - - /* - * Find value of Levenberg-Marquardt damping parameter which: - * * leads to positive definite damped model - * * within bounds specified by StpMax - * * generates step which decreases function value - * - * After this block IFlag is set to: - * * -8, if internal integrity control detected NAN/INF in function values - * * -3, if constraints are infeasible - * * -2, if model update is needed (either Lambda growth is too large - * or step is too short, but we can't rely on model and stop iterations) - * * -1, if model is fresh, Lambda have grown too large, termination is needed - * * 0, if everything is OK, continue iterations - * * >0, successful termination, step is less than EpsX - * - * State.Nu can have any value on enter, but after exit it is set to 1.0 - */ - iflag = -99; - minlm_minlmstepfinderstart(&state->finderstate, &state->quadraticmodel, &state->gbase, state->fbase, &state->xbase, &state->fibase, state->modelage, _state); -lbl_47: - if( !minlm_minlmstepfinderiteration(&state->finderstate, &state->lambdav, &state->nu, &state->xnew, &state->deltax, &state->deltaxready, &state->deltaf, &state->deltafready, &iflag, &fnew, &state->repncholesky, _state) ) - { - goto lbl_48; - } - ae_assert(state->hasfi||state->hasf, "MinLM: internal error 2!", _state); - state->repnfunc = state->repnfunc+1; - minlm_clearrequestfields(state, _state); - if( !state->finderstate.needfi ) - { - goto lbl_49; - } - ae_assert(state->hasfi, "MinLM: internal error 2!", _state); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->finderstate.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->needfi = ae_true; - state->rstate.stage = 8; - goto lbl_rcomm; -lbl_8: - state->needfi = ae_false; - ae_v_move(&state->finderstate.fi.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1)); - goto lbl_47; -lbl_49: - if( !state->finderstate.needf ) - { - goto lbl_51; - } - ae_assert(state->hasf, "MinLM: internal error 2!", _state); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->finderstate.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->needf = ae_true; - state->rstate.stage = 9; - goto lbl_rcomm; -lbl_9: - state->needf = ae_false; - state->finderstate.f = state->f; - goto lbl_47; -lbl_51: - ae_assert(ae_false, "MinLM: internal error 2!", _state); - goto lbl_47; -lbl_48: - if( state->userterminationneeded ) - { - - /* - * User requested termination - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->repterminationtype = 8; - result = ae_false; - return result; - } - state->nu = (double)(1); - ae_assert(((iflag>=-3&&iflag<=0)||iflag==-8)||iflag>0, "MinLM: internal integrity check failed!", _state); - if( iflag==-3 ) - { - state->repterminationtype = -3; - result = ae_false; - return result; - } - if( iflag==-2 ) - { - state->modelage = state->maxmodelage+1; - goto lbl_38; - } - if( iflag!=-1 ) - { - goto lbl_53; - } - - /* - * Stopping conditions are too stringent - */ - state->repterminationtype = 7; - if( !state->xrep ) - { - goto lbl_55; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->f = state->fbase; - minlm_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 10; - goto lbl_rcomm; -lbl_10: - state->xupdated = ae_false; -lbl_55: - result = ae_false; - return result; -lbl_53: - if( !(iflag==-8||iflag>0) ) - { - goto lbl_57; - } - - /* - * Either: - * * Integrity check failed - infinities or NANs - * * successful termination (step size is small enough) - */ - state->repterminationtype = iflag; - if( !state->xrep ) - { - goto lbl_59; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->f = state->fbase; - minlm_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 11; - goto lbl_rcomm; -lbl_11: - state->xupdated = ae_false; -lbl_59: - result = ae_false; - return result; -lbl_57: - state->f = fnew; - - /* - * Levenberg-Marquardt step is ready. - * Compare predicted vs. actual decrease and decide what to do with lambda. - * - * NOTE: we expect that State.DeltaX contains direction of step, - * State.F contains function value at new point. - */ - ae_assert(state->deltaxready, "MinLM: deltaX is not ready", _state); - iflag = minlm_checkdecrease(&state->quadraticmodel, &state->gbase, state->fbase, n, &state->deltax, state->f, &state->lambdav, &state->nu, _state); - if( iflag==0 ) - { - goto lbl_61; - } - state->repterminationtype = iflag; - if( !state->xrep ) - { - goto lbl_63; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->f = state->fbase; - minlm_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 12; - goto lbl_rcomm; -lbl_12: - state->xupdated = ae_false; -lbl_63: - result = ae_false; - return result; -lbl_61: - - /* - * Accept step, report it and - * test stopping conditions on iterations count and function decrease. - * - * NOTE: we expect that State.DeltaX contains direction of step, - * State.F contains function value at new point. - * - * NOTE2: we should update XBase ONLY. In the beginning of the next - * iteration we expect that State.FIBase is NOT updated and - * contains old value of a function vector. - */ - ae_v_move(&state->xbase.ptr.p_double[0], 1, &state->xnew.ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( !state->xrep ) - { - goto lbl_65; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minlm_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 13; - goto lbl_rcomm; -lbl_13: - state->xupdated = ae_false; -lbl_65: - state->repiterationscount = state->repiterationscount+1; - if( state->repiterationscount>=state->maxits&&state->maxits>0 ) - { - state->repterminationtype = 5; - } - if( state->repterminationtype<=0 ) - { - goto lbl_67; - } - if( !state->xrep ) - { - goto lbl_69; - } - - /* - * Report: XBase contains new point, F contains function value at new point - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minlm_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 14; - goto lbl_rcomm; -lbl_14: - state->xupdated = ae_false; -lbl_69: - result = ae_false; - return result; -lbl_67: - state->modelage = state->modelage+1; - goto lbl_38; -lbl_39: - - /* - * Lambda is too large, we have to break iterations. - */ - state->repterminationtype = 7; - if( !state->xrep ) - { - goto lbl_71; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->f = state->fbase; - minlm_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 15; - goto lbl_rcomm; -lbl_15: - state->xupdated = ae_false; -lbl_71: - goto lbl_37; -lbl_36: - - /* - * Legacy Hessian-based mode - * - * Main cycle. - * - * We move through it until either: - * * one of the stopping conditions is met - * * we decide that stopping conditions are too stringent - * and break from cycle - * - */ - if( state->nec+state->nic>0 ) - { - - /* - * FGH solver does not support general linear constraints - */ - state->repterminationtype = -5; - result = ae_false; - return result; - } -lbl_73: - if( ae_false ) - { - goto lbl_74; - } - - /* - * First, we have to prepare quadratic model for our function. - * We use BFlag to ensure that model is prepared; - * if it is false at the end of this block, something went wrong. - * - * We may either calculate brand new model or update old one. - * - * Before this block we have: - * * State.XBase - current position. - * * State.DeltaX - if DeltaXReady is True - * * State.DeltaF - if DeltaFReady is True - * - * After this block is over, we will have: - * * State.XBase - base point (unchanged) - * * State.FBase - F(XBase) - * * State.GBase - linear term - * * State.QuadraticModel - quadratic term - * * State.LambdaV - current estimate for lambda - * - * We also clear DeltaXReady/DeltaFReady flags - * after initialization is done. - */ - bflag = ae_false; - if( !(state->algomode==0||state->algomode==1) ) - { - goto lbl_75; - } - - /* - * Calculate f[] and Jacobian - */ - if( !(state->modelage>state->maxmodelage||!(state->deltaxready&&state->deltafready)) ) - { - goto lbl_77; - } - - /* - * Refresh model (using either finite differences or analytic Jacobian) - */ - if( state->algomode!=0 ) - { - goto lbl_79; - } - - /* - * Optimization using F values only. - * Use finite differences to estimate Jacobian. - */ - ae_assert(state->hasfi, "MinLMIteration: internal error when estimating Jacobian (no f[])", _state); - k = 0; -lbl_81: - if( k>n-1 ) - { - goto lbl_83; - } - - /* - * We guard X[k] from leaving [BndL,BndU]. - * In case BndL=BndU, we assume that derivative in this direction is zero. - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = state->x.ptr.p_double[k]-state->s.ptr.p_double[k]*state->diffstep; - if( state->havebndl.ptr.p_bool[k] ) - { - state->x.ptr.p_double[k] = ae_maxreal(state->x.ptr.p_double[k], state->bndl.ptr.p_double[k], _state); - } - if( state->havebndu.ptr.p_bool[k] ) - { - state->x.ptr.p_double[k] = ae_minreal(state->x.ptr.p_double[k], state->bndu.ptr.p_double[k], _state); - } - state->xm1 = state->x.ptr.p_double[k]; - minlm_clearrequestfields(state, _state); - state->needfi = ae_true; - state->rstate.stage = 16; - goto lbl_rcomm; -lbl_16: - state->repnfunc = state->repnfunc+1; - ae_v_move(&state->fm1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->x.ptr.p_double[k] = state->x.ptr.p_double[k]+state->s.ptr.p_double[k]*state->diffstep; - if( state->havebndl.ptr.p_bool[k] ) - { - state->x.ptr.p_double[k] = ae_maxreal(state->x.ptr.p_double[k], state->bndl.ptr.p_double[k], _state); - } - if( state->havebndu.ptr.p_bool[k] ) - { - state->x.ptr.p_double[k] = ae_minreal(state->x.ptr.p_double[k], state->bndu.ptr.p_double[k], _state); - } - state->xp1 = state->x.ptr.p_double[k]; - minlm_clearrequestfields(state, _state); - state->needfi = ae_true; - state->rstate.stage = 17; - goto lbl_rcomm; -lbl_17: - state->repnfunc = state->repnfunc+1; - ae_v_move(&state->fp1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1)); - v = state->xp1-state->xm1; - if( ae_fp_neq(v,(double)(0)) ) - { - v = 1/v; - ae_v_moved(&state->j.ptr.pp_double[0][k], state->j.stride, &state->fp1.ptr.p_double[0], 1, ae_v_len(0,m-1), v); - ae_v_subd(&state->j.ptr.pp_double[0][k], state->j.stride, &state->fm1.ptr.p_double[0], 1, ae_v_len(0,m-1), v); - } - else - { - for(i=0; i<=m-1; i++) - { - state->j.ptr.pp_double[i][k] = (double)(0); - } - } - k = k+1; - goto lbl_81; -lbl_83: - - /* - * Calculate F(XBase) - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minlm_clearrequestfields(state, _state); - state->needfi = ae_true; - state->rstate.stage = 18; - goto lbl_rcomm; -lbl_18: - state->needfi = ae_false; - state->repnfunc = state->repnfunc+1; - state->repnjac = state->repnjac+1; - - /* - * New model - */ - state->modelage = 0; - goto lbl_80; -lbl_79: - - /* - * Obtain f[] and Jacobian - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minlm_clearrequestfields(state, _state); - state->needfij = ae_true; - state->rstate.stage = 19; - goto lbl_rcomm; -lbl_19: - state->needfij = ae_false; - state->repnfunc = state->repnfunc+1; - state->repnjac = state->repnjac+1; - - /* - * New model - */ - state->modelage = 0; -lbl_80: - goto lbl_78; -lbl_77: - - /* - * State.J contains Jacobian or its current approximation; - * refresh it using secant updates: - * - * f(x0+dx) = f(x0) + J*dx, - * J_new = J_old + u*h' - * h = x_new-x_old - * u = (f_new - f_old - J_old*h)/(h'h) - * - * We can explicitly generate h and u, but it is - * preferential to do in-place calculations. Only - * I-th row of J_old is needed to calculate u[I], - * so we can update J row by row in one pass. - * - * NOTE: we expect that State.XBase contains new point, - * State.FBase contains old point, State.DeltaX and - * State.DeltaY contain updates from last step. - */ - ae_assert(state->deltaxready&&state->deltafready, "MinLMIteration: uninitialized DeltaX/DeltaF", _state); - t = ae_v_dotproduct(&state->deltax.ptr.p_double[0], 1, &state->deltax.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_assert(ae_fp_neq(t,(double)(0)), "MinLM: internal error (T=0)", _state); - for(i=0; i<=m-1; i++) - { - v = ae_v_dotproduct(&state->j.ptr.pp_double[i][0], 1, &state->deltax.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = (state->deltaf.ptr.p_double[i]-v)/t; - ae_v_addd(&state->j.ptr.pp_double[i][0], 1, &state->deltax.ptr.p_double[0], 1, ae_v_len(0,n-1), v); - } - ae_v_move(&state->fi.ptr.p_double[0], 1, &state->fibase.ptr.p_double[0], 1, ae_v_len(0,m-1)); - ae_v_add(&state->fi.ptr.p_double[0], 1, &state->deltaf.ptr.p_double[0], 1, ae_v_len(0,m-1)); - - /* - * Increase model age - */ - state->modelage = state->modelage+1; -lbl_78: - - /* - * Generate quadratic model: - * f(xbase+dx) = - * = (f0 + J*dx)'(f0 + J*dx) - * = f0^2 + dx'J'f0 + f0*J*dx + dx'J'J*dx - * = f0^2 + 2*f0*J*dx + dx'J'J*dx - * - * Note that we calculate 2*(J'J) instead of J'J because - * our quadratic model is based on Tailor decomposition, - * i.e. it has 0.5 before quadratic term. - */ - rmatrixgemm(n, n, m, 2.0, &state->j, 0, 0, 1, &state->j, 0, 0, 0, 0.0, &state->quadraticmodel, 0, 0, _state); - rmatrixmv(n, m, &state->j, 0, 0, 1, &state->fi, 0, &state->gbase, 0, _state); - ae_v_muld(&state->gbase.ptr.p_double[0], 1, ae_v_len(0,n-1), 2); - v = ae_v_dotproduct(&state->fi.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1)); - state->fbase = v; - ae_v_move(&state->fibase.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1)); - - /* - * set control variables - */ - bflag = ae_true; -lbl_75: - if( state->algomode!=2 ) - { - goto lbl_84; - } - ae_assert(!state->hasfi, "MinLMIteration: internal error (HasFI is True in Hessian-based mode)", _state); - - /* - * Obtain F, G, H - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minlm_clearrequestfields(state, _state); - state->needfgh = ae_true; - state->rstate.stage = 20; - goto lbl_rcomm; -lbl_20: - state->needfgh = ae_false; - state->repnfunc = state->repnfunc+1; - state->repngrad = state->repngrad+1; - state->repnhess = state->repnhess+1; - rmatrixcopy(n, n, &state->h, 0, 0, &state->quadraticmodel, 0, 0, _state); - ae_v_move(&state->gbase.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->fbase = state->f; - - /* - * set control variables - */ - bflag = ae_true; - state->modelage = 0; -lbl_84: - ae_assert(bflag, "MinLM: internal integrity check failed!", _state); - state->deltaxready = ae_false; - state->deltafready = ae_false; - - /* - * Perform integrity check (presense of NAN/INF) - */ - v = state->fbase; - for(i=0; i<=n-1; i++) - { - v = 0.1*v+state->gbase.ptr.p_double[i]; - } - if( !ae_isfinite(v, _state) ) - { - - /* - * Break! - */ - state->repterminationtype = -8; - result = ae_false; - return result; - } - - /* - * If Lambda is not initialized, initialize it using quadratic model - */ - if( ae_fp_less(state->lambdav,(double)(0)) ) - { - state->lambdav = (double)(0); - for(i=0; i<=n-1; i++) - { - state->lambdav = ae_maxreal(state->lambdav, ae_fabs(state->quadraticmodel.ptr.pp_double[i][i], _state)*ae_sqr(state->s.ptr.p_double[i], _state), _state); - } - state->lambdav = 0.001*state->lambdav; - if( ae_fp_eq(state->lambdav,(double)(0)) ) - { - state->lambdav = (double)(1); - } - } - - /* - * Find value of Levenberg-Marquardt damping parameter which: - * * leads to positive definite damped model - * * within bounds specified by StpMax - * * generates step which decreases function value - * - * After this block IFlag is set to: - * * -3, if constraints are infeasible - * * -2, if model update is needed (either Lambda growth is too large - * or step is too short, but we can't rely on model and stop iterations) - * * -1, if model is fresh, Lambda have grown too large, termination is needed - * * 0, if everything is OK, continue iterations - * - * State.Nu can have any value on enter, but after exit it is set to 1.0 - */ - iflag = -99; -lbl_86: - if( ae_false ) - { - goto lbl_87; - } - - /* - * Do we need model update? - */ - if( state->modelage>0&&ae_fp_greater_eq(state->nu,minlm_suspiciousnu) ) - { - iflag = -2; - goto lbl_87; - } - - /* - * Setup quadratic solver and solve quadratic programming problem. - * After problem is solved we'll try to bound step by StpMax - * (Lambda will be increased if step size is too large). - * - * We use BFlag variable to indicate that we have to increase Lambda. - * If it is False, we will try to increase Lambda and move to new iteration. - */ - bflag = ae_true; - minqpsetstartingpointfast(&state->qpstate, &state->xbase, _state); - minqpsetoriginfast(&state->qpstate, &state->xbase, _state); - minqpsetlineartermfast(&state->qpstate, &state->gbase, _state); - minqpsetquadratictermfast(&state->qpstate, &state->quadraticmodel, ae_true, 0.0, _state); - for(i=0; i<=n-1; i++) - { - state->tmp0.ptr.p_double[i] = state->quadraticmodel.ptr.pp_double[i][i]+state->lambdav/ae_sqr(state->s.ptr.p_double[i], _state); - } - minqprewritediagonal(&state->qpstate, &state->tmp0, _state); - minqpoptimize(&state->qpstate, _state); - minqpresultsbuf(&state->qpstate, &state->xdir, &state->qprep, _state); - if( state->qprep.terminationtype>0 ) - { - - /* - * successful solution of QP problem - */ - ae_v_sub(&state->xdir.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = ae_v_dotproduct(&state->xdir.ptr.p_double[0], 1, &state->xdir.ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( ae_isfinite(v, _state) ) - { - v = ae_sqrt(v, _state); - if( ae_fp_greater(state->stpmax,(double)(0))&&ae_fp_greater(v,state->stpmax) ) - { - bflag = ae_false; - } - } - else - { - bflag = ae_false; - } - } - else - { - - /* - * Either problem is non-convex (increase LambdaV) or constraints are inconsistent - */ - ae_assert((state->qprep.terminationtype==-3||state->qprep.terminationtype==-4)||state->qprep.terminationtype==-5, "MinLM: unexpected completion code from QP solver", _state); - if( state->qprep.terminationtype==-3 ) - { - iflag = -3; - goto lbl_87; - } - bflag = ae_false; - } - if( !bflag ) - { - - /* - * Solution failed: - * try to increase lambda to make matrix positive definite and continue. - */ - if( !minlm_increaselambda(&state->lambdav, &state->nu, _state) ) - { - iflag = -1; - goto lbl_87; - } - goto lbl_86; - } - - /* - * Step in State.XDir and it is bounded by StpMax. - * - * We should check stopping conditions on step size here. - * DeltaX, which is used for secant updates, is initialized here. - * - * This code is a bit tricky because sometimes XDir<>0, but - * it is so small that XDir+XBase==XBase (in finite precision - * arithmetics). So we set DeltaX to XBase, then - * add XDir, and then subtract XBase to get exact value of - * DeltaX. - * - * Step length is estimated using DeltaX. - * - * NOTE: stopping conditions are tested - * for fresh models only (ModelAge=0) - */ - ae_v_move(&state->deltax.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_add(&state->deltax.ptr.p_double[0], 1, &state->xdir.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_sub(&state->deltax.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->deltaxready = ae_true; - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(state->deltax.ptr.p_double[i]/state->s.ptr.p_double[i], _state); - } - v = ae_sqrt(v, _state); - if( ae_fp_greater(v,state->epsx) ) - { - goto lbl_88; - } - if( state->modelage!=0 ) - { - goto lbl_90; - } - - /* - * Step is too short, model is fresh and we can rely on it. - * Terminating. - */ - state->repterminationtype = 2; - if( !state->xrep ) - { - goto lbl_92; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->f = state->fbase; - minlm_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 21; - goto lbl_rcomm; -lbl_21: - state->xupdated = ae_false; -lbl_92: - result = ae_false; - return result; - goto lbl_91; -lbl_90: - - /* - * Step is suspiciously short, but model is not fresh - * and we can't rely on it. - */ - iflag = -2; - goto lbl_87; -lbl_91: -lbl_88: - - /* - * Let's evaluate new step: - * a) if we have Fi vector, we evaluate it using rcomm, and - * then we manually calculate State.F as sum of squares of Fi[] - * b) if we have F value, we just evaluate it through rcomm interface - * - * We prefer (a) because we may need Fi vector for additional - * iterations - */ - ae_assert(state->hasfi||state->hasf, "MinLM: internal error 2!", _state); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_add(&state->x.ptr.p_double[0], 1, &state->xdir.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minlm_clearrequestfields(state, _state); - if( !state->hasfi ) - { - goto lbl_94; - } - state->needfi = ae_true; - state->rstate.stage = 22; - goto lbl_rcomm; -lbl_22: - state->needfi = ae_false; - v = ae_v_dotproduct(&state->fi.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1)); - state->f = v; - ae_v_move(&state->deltaf.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1)); - ae_v_sub(&state->deltaf.ptr.p_double[0], 1, &state->fibase.ptr.p_double[0], 1, ae_v_len(0,m-1)); - state->deltafready = ae_true; - goto lbl_95; -lbl_94: - state->needf = ae_true; - state->rstate.stage = 23; - goto lbl_rcomm; -lbl_23: - state->needf = ae_false; -lbl_95: - state->repnfunc = state->repnfunc+1; - if( !ae_isfinite(state->f, _state) ) - { - - /* - * Integrity check failed, break! - */ - state->repterminationtype = -8; - result = ae_false; - return result; - } - if( ae_fp_greater_eq(state->f,state->fbase) ) - { - - /* - * Increase lambda and continue - */ - if( !minlm_increaselambda(&state->lambdav, &state->nu, _state) ) - { - iflag = -1; - goto lbl_87; - } - goto lbl_86; - } - - /* - * We've found our step! - */ - iflag = 0; - goto lbl_87; - goto lbl_86; -lbl_87: - if( state->userterminationneeded ) - { - - /* - * User requested termination - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->repterminationtype = 8; - result = ae_false; - return result; - } - state->nu = (double)(1); - ae_assert(iflag>=-3&&iflag<=0, "MinLM: internal integrity check failed!", _state); - if( iflag==-3 ) - { - state->repterminationtype = -3; - result = ae_false; - return result; - } - if( iflag==-2 ) - { - state->modelage = state->maxmodelage+1; - goto lbl_73; - } - if( iflag==-1 ) - { - goto lbl_74; - } - - /* - * Levenberg-Marquardt step is ready. - * Compare predicted vs. actual decrease and decide what to do with lambda. - * - * NOTE: we expect that State.DeltaX contains direction of step, - * State.F contains function value at new point. - */ - ae_assert(state->deltaxready, "MinLM: deltaX is not ready", _state); - t = (double)(0); - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&state->quadraticmodel.ptr.pp_double[i][0], 1, &state->deltax.ptr.p_double[0], 1, ae_v_len(0,n-1)); - t = t+state->deltax.ptr.p_double[i]*state->gbase.ptr.p_double[i]+0.5*state->deltax.ptr.p_double[i]*v; - } - state->predicteddecrease = -t; - state->actualdecrease = -(state->f-state->fbase); - if( ae_fp_less_eq(state->predicteddecrease,(double)(0)) ) - { - goto lbl_74; - } - v = state->actualdecrease/state->predicteddecrease; - if( ae_fp_greater_eq(v,0.1) ) - { - goto lbl_96; - } - if( minlm_increaselambda(&state->lambdav, &state->nu, _state) ) - { - goto lbl_98; - } - - /* - * Lambda is too large, we have to break iterations. - */ - state->repterminationtype = 7; - if( !state->xrep ) - { - goto lbl_100; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->f = state->fbase; - minlm_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 24; - goto lbl_rcomm; -lbl_24: - state->xupdated = ae_false; -lbl_100: - result = ae_false; - return result; -lbl_98: -lbl_96: - if( ae_fp_greater(v,0.5) ) - { - minlm_decreaselambda(&state->lambdav, &state->nu, _state); - } - - /* - * Accept step, report it and - * test stopping conditions on iterations count and function decrease. - * - * NOTE: we expect that State.DeltaX contains direction of step, - * State.F contains function value at new point. - * - * NOTE2: we should update XBase ONLY. In the beginning of the next - * iteration we expect that State.FIBase is NOT updated and - * contains old value of a function vector. - */ - ae_v_add(&state->xbase.ptr.p_double[0], 1, &state->deltax.ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( !state->xrep ) - { - goto lbl_102; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minlm_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 25; - goto lbl_rcomm; -lbl_25: - state->xupdated = ae_false; -lbl_102: - state->repiterationscount = state->repiterationscount+1; - if( state->repiterationscount>=state->maxits&&state->maxits>0 ) - { - state->repterminationtype = 5; - } - if( state->repterminationtype<=0 ) - { - goto lbl_104; - } - if( !state->xrep ) - { - goto lbl_106; - } - - /* - * Report: XBase contains new point, F contains function value at new point - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - minlm_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 26; - goto lbl_rcomm; -lbl_26: - state->xupdated = ae_false; -lbl_106: - result = ae_false; - return result; -lbl_104: - state->modelage = state->modelage+1; - goto lbl_73; -lbl_74: - - /* - * Lambda is too large, we have to break iterations. - */ - state->repterminationtype = 7; - if( !state->xrep ) - { - goto lbl_108; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->f = state->fbase; - minlm_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 27; - goto lbl_rcomm; -lbl_27: - state->xupdated = ae_false; -lbl_108: -lbl_37: - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = n; - state->rstate.ia.ptr.p_int[1] = m; - state->rstate.ia.ptr.p_int[2] = iflag; - state->rstate.ia.ptr.p_int[3] = i; - state->rstate.ia.ptr.p_int[4] = k; - state->rstate.ba.ptr.p_bool[0] = bflag; - state->rstate.ra.ptr.p_double[0] = v; - state->rstate.ra.ptr.p_double[1] = s; - state->rstate.ra.ptr.p_double[2] = t; - state->rstate.ra.ptr.p_double[3] = fnew; - return result; -} - - -/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic Jacobian. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function vector at the initial -point (note: future versions may also perform check at the final point) -and compares numerical Jacobian with analytic one provided by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both Jacobians, and specific components highlighted as -suspicious by the OptGuard. - -The OptGuard report can be retrieved with minlmoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with minlmsetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minlmoptguardgradient(minlmstate* state, - double teststep, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(teststep, _state), "MinLMOptGuardGradient: TestStep contains NaN or INF", _state); - ae_assert(ae_fp_greater_eq(teststep,(double)(0)), "MinLMOptGuardGradient: invalid argument TestStep(TestStep<0)", _state); - state->teststep = teststep; -} - - -/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -OptGuard checks analytic Jacobian against reference value obtained by -numerical differentiation with user-specified step. - -NOTE: other optimizers perform additional OptGuard checks for things like - C0/C1-continuity violations. However, LM optimizer can check only - for incorrect Jacobian. - - The reason is that unlike line search methods LM optimizer does not - perform extensive evaluations along the line. Thus, we simply do not - have enough data to catch C0/C1-violations. - -This check is activated with minlmoptguardgradient() function. - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradfidx for specific function (Jacobian row) suspected - * rep.badgradvidx for specific variable (Jacobian column) suspected - * rep.badgradxbase, a point where gradient/Jacobian is tested - * rep.badgraduser, user-provided gradient/Jacobian - * rep.badgradnum, reference gradient/Jacobian obtained via numerical - differentiation - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - OptGuard report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minlmoptguardresults(minlmstate* state, - optguardreport* rep, - ae_state *_state) -{ - - _optguardreport_clear(rep); - - smoothnessmonitorexportreport(&state->smonitor, rep, _state); -} - - -/************************************************************************* -Levenberg-Marquardt algorithm results - -NOTE: if you activated OptGuard integrity checking functionality and want - to get OptGuard report, it can be retrieved with the help of - minlmoptguardresults() function. - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report; includes termination codes and - additional information. Termination codes are listed below, - see comments for this structure for more info. - Termination code is stored in rep.terminationtype field: - * -8 optimizer detected NAN/INF values either in the - function itself, or in its Jacobian - * -3 constraints are inconsistent - * 2 relative step is no more than EpsX. - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible - * 8 terminated by user who called minlmrequesttermination(). - X contains point which was "current accepted" when - termination request was submitted. - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmresults(minlmstate* state, - /* Real */ ae_vector* x, - minlmreport* rep, - ae_state *_state) -{ - - ae_vector_clear(x); - _minlmreport_clear(rep); - - minlmresultsbuf(state, x, rep, _state); -} - - -/************************************************************************* -Levenberg-Marquardt algorithm results - -Buffered implementation of MinLMResults(), which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmresultsbuf(minlmstate* state, - /* Real */ ae_vector* x, - minlmreport* rep, - ae_state *_state) -{ - - - if( x->cntn ) - { - ae_vector_set_length(x, state->n, _state); - } - ae_v_move(&x->ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - rep->iterationscount = state->repiterationscount; - rep->terminationtype = state->repterminationtype; - rep->nfunc = state->repnfunc; - rep->njac = state->repnjac; - rep->ngrad = state->repngrad; - rep->nhess = state->repnhess; - rep->ncholesky = state->repncholesky; -} - - -/************************************************************************* -This subroutine restarts LM algorithm from new point. All optimization -parameters are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure used for reverse communication previously - allocated with MinLMCreateXXX call. - X - new starting point. - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -void minlmrestartfrom(minlmstate* state, - /* Real */ ae_vector* x, - ae_state *_state) -{ - - - ae_assert(x->cnt>=state->n, "MinLMRestartFrom: Length(X)n, _state), "MinLMRestartFrom: X contains infinite or NaN values!", _state); - ae_v_move(&state->xbase.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - ae_vector_set_length(&state->rstate.ia, 4+1, _state); - ae_vector_set_length(&state->rstate.ba, 0+1, _state); - ae_vector_set_length(&state->rstate.ra, 3+1, _state); - state->rstate.stage = -1; - minlm_clearrequestfields(state, _state); -} - - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void minlmrequesttermination(minlmstate* state, ae_state *_state) -{ - - - state->userterminationneeded = ae_true; -} - - -/************************************************************************* -This is obsolete function. - -Since ALGLIB 3.3 it is equivalent to MinLMCreateVJ(). - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmcreatevgj(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* x, - minlmstate* state, - ae_state *_state) -{ - - _minlmstate_clear(state); - - minlmcreatevj(n, m, x, state, _state); -} - - -/************************************************************************* -This is obsolete function. - -Since ALGLIB 3.3 it is equivalent to MinLMCreateFJ(). - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmcreatefgj(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* x, - minlmstate* state, - ae_state *_state) -{ - - _minlmstate_clear(state); - - minlmcreatefj(n, m, x, state, _state); -} - - -/************************************************************************* -This function is considered obsolete since ALGLIB 3.1.0 and is present for -backward compatibility only. We recommend to use MinLMCreateVJ, which -provides similar, but more consistent and feature-rich interface. - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmcreatefj(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* x, - minlmstate* state, - ae_state *_state) -{ - - _minlmstate_clear(state); - - ae_assert(n>=1, "MinLMCreateFJ: N<1!", _state); - ae_assert(m>=1, "MinLMCreateFJ: M<1!", _state); - ae_assert(x->cnt>=n, "MinLMCreateFJ: Length(X)teststep = (double)(0); - state->n = n; - state->m = m; - state->algomode = 1; - state->hasf = ae_true; - state->hasfi = ae_false; - state->hasg = ae_false; - - /* - * init 2 - */ - minlm_lmprepare(n, m, ae_true, state, _state); - minlmsetacctype(state, 0, _state); - minlmsetcond(state, (double)(0), 0, _state); - minlmsetxrep(state, ae_false, _state); - minlmsetstpmax(state, (double)(0), _state); - minlmrestartfrom(state, x, _state); -} - - -/************************************************************************* -Prepare internal structures (except for RComm). - -Note: M must be zero for FGH mode, non-zero for V/VJ/FJ/FGJ mode. -*************************************************************************/ -static void minlm_lmprepare(ae_int_t n, - ae_int_t m, - ae_bool havegrad, - minlmstate* state, - ae_state *_state) -{ - ae_int_t i; - - - smoothnessmonitorinit(&state->smonitor, &state->s, 0, 0, ae_false, _state); - if( n<=0||m<0 ) - { - return; - } - if( havegrad ) - { - ae_vector_set_length(&state->g, n, _state); - } - if( m!=0 ) - { - ae_matrix_set_length(&state->j, m, n, _state); - ae_vector_set_length(&state->fi, m, _state); - ae_vector_set_length(&state->fibase, m, _state); - ae_vector_set_length(&state->deltaf, m, _state); - ae_vector_set_length(&state->fm1, m, _state); - ae_vector_set_length(&state->fp1, m, _state); - ae_vector_set_length(&state->fc1, m, _state); - ae_vector_set_length(&state->gm1, m, _state); - ae_vector_set_length(&state->gp1, m, _state); - ae_vector_set_length(&state->gc1, m, _state); - } - else - { - ae_matrix_set_length(&state->h, n, n, _state); - } - ae_vector_set_length(&state->x, n, _state); - ae_vector_set_length(&state->deltax, n, _state); - ae_matrix_set_length(&state->quadraticmodel, n, n, _state); - ae_vector_set_length(&state->xbase, n, _state); - ae_vector_set_length(&state->gbase, n, _state); - ae_vector_set_length(&state->xdir, n, _state); - ae_vector_set_length(&state->tmp0, n, _state); - - /* - * prepare internal L-BFGS - */ - for(i=0; i<=n-1; i++) - { - state->x.ptr.p_double[i] = (double)(0); - } - minlbfgscreate(n, ae_minint(minlm_additers, n, _state), &state->x, &state->internalstate, _state); - minlbfgssetcond(&state->internalstate, 0.0, 0.0, 0.0, ae_minint(minlm_additers, n, _state), _state); - - /* - * Prepare internal QP solver - */ - minqpcreate(n, &state->qpstate, _state); - minqpsetalgoquickqp(&state->qpstate, 0.0, 0.0, coalesce(0.01*state->epsx, 1.0E-12, _state), 10, ae_true, _state); - - /* - * Prepare boundary constraints - */ - ae_vector_set_length(&state->bndl, n, _state); - ae_vector_set_length(&state->bndu, n, _state); - ae_vector_set_length(&state->havebndl, n, _state); - ae_vector_set_length(&state->havebndu, n, _state); - for(i=0; i<=n-1; i++) - { - state->bndl.ptr.p_double[i] = _state->v_neginf; - state->havebndl.ptr.p_bool[i] = ae_false; - state->bndu.ptr.p_double[i] = _state->v_posinf; - state->havebndu.ptr.p_bool[i] = ae_false; - } - - /* - * Prepare scaling matrix - */ - ae_vector_set_length(&state->s, n, _state); - ae_vector_set_length(&state->lastscaleused, n, _state); - for(i=0; i<=n-1; i++) - { - state->s.ptr.p_double[i] = 1.0; - state->lastscaleused.ptr.p_double[i] = 1.0; - } - - /* - * Prepare linear constraints - */ - state->nec = 0; - state->nic = 0; -} - - -/************************************************************************* -Clears request fileds (to be sure that we don't forgot to clear something) -*************************************************************************/ -static void minlm_clearrequestfields(minlmstate* state, ae_state *_state) -{ - - - state->needf = ae_false; - state->needfg = ae_false; - state->needfgh = ae_false; - state->needfij = ae_false; - state->needfi = ae_false; - state->xupdated = ae_false; -} - - -/************************************************************************* -Increases lambda, returns False when there is a danger of overflow -*************************************************************************/ -static ae_bool minlm_increaselambda(double* lambdav, - double* nu, - ae_state *_state) -{ - double lnlambda; - double lnnu; - double lnlambdaup; - double lnmax; - ae_bool result; - - - result = ae_false; - lnlambda = ae_log(*lambdav, _state); - lnlambdaup = ae_log(minlm_lambdaup, _state); - lnnu = ae_log(*nu, _state); - lnmax = ae_log(ae_maxrealnumber, _state); - if( ae_fp_greater(lnlambda+lnlambdaup+lnnu,0.25*lnmax) ) - { - return result; - } - if( ae_fp_greater(lnnu+ae_log((double)(2), _state),lnmax) ) - { - return result; - } - *lambdav = *lambdav*minlm_lambdaup*(*nu); - *nu = *nu*2; - result = ae_true; - return result; -} - - -/************************************************************************* -Decreases lambda, but leaves it unchanged when there is danger of underflow. -*************************************************************************/ -static void minlm_decreaselambda(double* lambdav, - double* nu, - ae_state *_state) -{ - - - *nu = (double)(1); - if( ae_fp_less(ae_log(*lambdav, _state)+ae_log(minlm_lambdadown, _state),ae_log(ae_minrealnumber, _state)) ) - { - *lambdav = ae_minrealnumber; - } - else - { - *lambdav = *lambdav*minlm_lambdadown; - } -} - - -/************************************************************************* -This function compares actual decrease vs predicted decrease and updates -LambdaV/Nu accordingly. - -INPUT PARAMETERS: - QuadraticModel - array[N,N], full Hessian matrix of quadratic - model at deltaX=0 - GBase - array[N], gradient at deltaX=0 - FBase - F(deltaX=0) - N - size - DeltaX - step vector - FNew - new function value - LambdaV - lambda-value, updated on exit - Nu - Nu-multiplier, updated on exit - -On exit it returns: -* Result=0 - if we have to continue iterations -* Result<>0 - if termination with completion code Result is requested - - -- ALGLIB -- - Copyright 17.02.2017 by Bochkanov Sergey -*************************************************************************/ -static ae_int_t minlm_checkdecrease(/* Real */ ae_matrix* quadraticmodel, - /* Real */ ae_vector* gbase, - double fbase, - ae_int_t n, - /* Real */ ae_vector* deltax, - double fnew, - double* lambdav, - double* nu, - ae_state *_state) -{ - ae_int_t i; - double v; - double t; - double predicteddecrease; - double actualdecrease; - ae_int_t result; - - - result = 0; - t = (double)(0); - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&quadraticmodel->ptr.pp_double[i][0], 1, &deltax->ptr.p_double[0], 1, ae_v_len(0,n-1)); - t = t+deltax->ptr.p_double[i]*gbase->ptr.p_double[i]+0.5*deltax->ptr.p_double[i]*v; - } - predicteddecrease = -t; - actualdecrease = -(fnew-fbase); - if( ae_fp_less_eq(predicteddecrease,(double)(0)) ) - { - result = 7; - return result; - } - v = actualdecrease/predicteddecrease; - if( ae_fp_less(v,0.1) ) - { - if( !minlm_increaselambda(lambdav, nu, _state) ) - { - - /* - * Lambda is too large, we have to break iterations. - */ - result = 7; - return result; - } - } - if( ae_fp_greater(v,0.5) ) - { - minlm_decreaselambda(lambdav, nu, _state); - } - return result; -} - - -/************************************************************************* -This function initializes step finder object with problem statement; -model parameters specified during this call should not (and can not) -change during object lifetime (although it is possible to re-initialize -object with different settings). - -This function reuses internally allocated objects as much as possible. - -In addition to initializing step finder, this function enforces feasibility -in initial point X passed to this function. It is important that LM iteration -starts from feasible point and performs feasible steps; - -RETURN VALUE: - True for successful initialization - False for inconsistent constraints; you should not use step finder if - it returned False. -*************************************************************************/ -static ae_bool minlm_minlmstepfinderinit(minlmstepfinder* state, - ae_int_t n, - ae_int_t m, - ae_int_t maxmodelage, - ae_bool hasfi, - /* Real */ ae_vector* xbase, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_matrix* cleic, - ae_int_t nec, - ae_int_t nic, - /* Real */ ae_vector* s, - double stpmax, - double epsx, - ae_state *_state) -{ - ae_int_t i; - ae_bool result; - - - state->n = n; - state->m = m; - state->maxmodelage = maxmodelage; - state->hasfi = hasfi; - state->stpmax = stpmax; - state->epsx = epsx; - - /* - * Allocate temporaries, create QP solver, select QP algorithm - */ - rvectorsetlengthatleast(&state->bndl, n, _state); - rvectorsetlengthatleast(&state->bndu, n, _state); - rvectorsetlengthatleast(&state->s, n, _state); - bvectorsetlengthatleast(&state->havebndl, n, _state); - bvectorsetlengthatleast(&state->havebndu, n, _state); - rvectorsetlengthatleast(&state->x, n, _state); - rvectorsetlengthatleast(&state->xbase, n, _state); - rvectorsetlengthatleast(&state->tmp0, n, _state); - rvectorsetlengthatleast(&state->modeldiag, n, _state); - ivectorsetlengthatleast(&state->tmpct, nec+nic, _state); - rvectorsetlengthatleast(&state->xdir, n, _state); - if( hasfi ) - { - rvectorsetlengthatleast(&state->fi, m, _state); - rvectorsetlengthatleast(&state->fibase, m, _state); - } - for(i=0; i<=n-1; i++) - { - ae_assert(ae_isfinite(bndl->ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "MinLM: integrity check failed", _state); - ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "MinLM: integrity check failed", _state); - state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i]; - state->havebndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state); - state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i]; - state->havebndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state); - state->s.ptr.p_double[i] = s->ptr.p_double[i]; - } - for(i=0; i<=nec-1; i++) - { - state->tmpct.ptr.p_int[i] = 0; - } - for(i=0; i<=nic-1; i++) - { - state->tmpct.ptr.p_int[nec+i] = -1; - } - minqpcreate(n, &state->qpstate, _state); - if( nec+nic==0 ) - { - minqpsetalgoquickqp(&state->qpstate, 0.0, 0.0, coalesce(0.01*epsx, 1.0E-12, _state), 10, ae_true, _state); - } - else - { - minqpsetalgodenseaul(&state->qpstate, coalesce(0.01*epsx, 1.0E-12, _state), (double)(100), 10, _state); - } - minqpsetbc(&state->qpstate, bndl, bndu, _state); - minqpsetlc(&state->qpstate, cleic, &state->tmpct, nec+nic, _state); - minqpsetscale(&state->qpstate, s, _state); - - /* - * Check feasibility of constraints: - * * check/enforce box constraints (straightforward) - * * prepare QP subproblem which return us a feasible point - */ - result = ae_true; - for(i=0; i<=n-1; i++) - { - if( (state->havebndl.ptr.p_bool[i]&&state->havebndu.ptr.p_bool[i])&&ae_fp_greater(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - result = ae_false; - return result; - } - if( state->havebndl.ptr.p_bool[i]&&ae_fp_less(xbase->ptr.p_double[i],state->bndl.ptr.p_double[i]) ) - { - xbase->ptr.p_double[i] = state->bndl.ptr.p_double[i]; - } - if( state->havebndu.ptr.p_bool[i]&&ae_fp_greater(xbase->ptr.p_double[i],state->bndu.ptr.p_double[i]) ) - { - xbase->ptr.p_double[i] = state->bndu.ptr.p_double[i]; - } - } - if( nec+nic>0 ) - { - - /* - * Well, we have linear constraints... let's use heavy machinery. - * - * We will modify QP solver state below, but everything will be - * restored in MinLMStepFinderStart(). - */ - sparsecreate(n, n, n, &state->tmpsp, _state); - for(i=0; i<=n-1; i++) - { - sparseset(&state->tmpsp, i, i, 0.5, _state); - state->tmp0.ptr.p_double[i] = (double)(0); - } - minqpsetstartingpointfast(&state->qpstate, xbase, _state); - minqpsetoriginfast(&state->qpstate, xbase, _state); - minqpsetlineartermfast(&state->qpstate, &state->tmp0, _state); - minqpsetquadratictermsparse(&state->qpstate, &state->tmpsp, ae_true, _state); - minqpoptimize(&state->qpstate, _state); - minqpresultsbuf(&state->qpstate, xbase, &state->qprep, _state); - } - return result; -} - - -/************************************************************************* -This function prepares LM step search session. -*************************************************************************/ -static void minlm_minlmstepfinderstart(minlmstepfinder* state, - /* Real */ ae_matrix* quadraticmodel, - /* Real */ ae_vector* gbase, - double fbase, - /* Real */ ae_vector* xbase, - /* Real */ ae_vector* fibase, - ae_int_t modelage, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - - - n = state->n; - ae_vector_set_length(&state->rstate.ia, 2+1, _state); - ae_vector_set_length(&state->rstate.ba, 0+1, _state); - ae_vector_set_length(&state->rstate.ra, 0+1, _state); - state->rstate.stage = -1; - state->modelage = modelage; - state->fbase = fbase; - if( state->hasfi ) - { - for(i=0; i<=state->m-1; i++) - { - state->fibase.ptr.p_double[i] = fibase->ptr.p_double[i]; - } - } - for(i=0; i<=n-1; i++) - { - state->xbase.ptr.p_double[i] = xbase->ptr.p_double[i]; - state->modeldiag.ptr.p_double[i] = quadraticmodel->ptr.pp_double[i][i]; - } - minqpsetstartingpointfast(&state->qpstate, xbase, _state); - minqpsetoriginfast(&state->qpstate, xbase, _state); - minqpsetlineartermfast(&state->qpstate, gbase, _state); - minqpsetquadratictermfast(&state->qpstate, quadraticmodel, ae_true, 0.0, _state); -} - - -/************************************************************************* -This function runs LM step search session. -// -// Find value of Levenberg-Marquardt damping parameter which: -// * leads to positive definite damped model -// * within bounds specified by StpMax -// * generates step which decreases function value -// -// After this block IFlag is set to: -// * -8, if infinities/NANs were detected in function values/gradient -// * -3, if constraints are infeasible -// * -2, if model update is needed (either Lambda growth is too large -// or step is too short, but we can't rely on model and stop iterations) -// * -1, if model is fresh, Lambda have grown too large, termination is needed -// * 0, if everything is OK, continue iterations -// * >0 - successful completion (step size is small enough) -// -// State.Nu can have any value on enter, but after exit it is set to 1.0 -// -*************************************************************************/ -static ae_bool minlm_minlmstepfinderiteration(minlmstepfinder* state, - double* lambdav, - double* nu, - /* Real */ ae_vector* xnew, - /* Real */ ae_vector* deltax, - ae_bool* deltaxready, - /* Real */ ae_vector* deltaf, - ae_bool* deltafready, - ae_int_t* iflag, - double* fnew, - ae_int_t* ncholesky, - ae_state *_state) -{ - ae_int_t i; - ae_bool bflag; - double v; - ae_int_t n; - ae_int_t m; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - i = state->rstate.ia.ptr.p_int[0]; - n = state->rstate.ia.ptr.p_int[1]; - m = state->rstate.ia.ptr.p_int[2]; - bflag = state->rstate.ba.ptr.p_bool[0]; - v = state->rstate.ra.ptr.p_double[0]; - } - else - { - i = -838; - n = 939; - m = -526; - bflag = ae_true; - v = -541; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - if( state->rstate.stage==1 ) - { - goto lbl_1; - } - - /* - * Routine body - */ - *iflag = -99; - n = state->n; - m = state->m; -lbl_2: - if( ae_false ) - { - goto lbl_3; - } - *deltaxready = ae_false; - *deltafready = ae_false; - - /* - * Do we need model update? - */ - if( state->modelage>0&&ae_fp_greater_eq(*nu,minlm_suspiciousnu) ) - { - *iflag = -2; - goto lbl_3; - } - - /* - * Setup quadratic solver and solve quadratic programming problem. - * After problem is solved we'll try to bound step by StpMax - * (Lambda will be increased if step size is too large). - * - * We use BFlag variable to indicate that we have to increase Lambda. - * If it is False, we will try to increase Lambda and move to new iteration. - */ - bflag = ae_true; - for(i=0; i<=n-1; i++) - { - state->tmp0.ptr.p_double[i] = state->modeldiag.ptr.p_double[i]+*lambdav/ae_sqr(state->s.ptr.p_double[i], _state); - } - minqprewritediagonal(&state->qpstate, &state->tmp0, _state); - minqpoptimize(&state->qpstate, _state); - minqpresultsbuf(&state->qpstate, xnew, &state->qprep, _state); - *ncholesky = *ncholesky+state->qprep.ncholesky; - if( state->qprep.terminationtype==-3 ) - { - - /* - * Infeasible constraints - */ - *iflag = -3; - goto lbl_3; - } - if( state->qprep.terminationtype==-4||state->qprep.terminationtype==-5 ) - { - - /* - * Unconstrained direction of negative curvature was detected - */ - if( !minlm_increaselambda(lambdav, nu, _state) ) - { - *iflag = -1; - goto lbl_3; - } - goto lbl_2; - } - ae_assert(state->qprep.terminationtype>0, "MinLM: unexpected completion code from QP solver", _state); - ae_v_move(&state->xdir.ptr.p_double[0], 1, &xnew->ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_sub(&state->xdir.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(state->xdir.ptr.p_double[i]/state->s.ptr.p_double[i], _state); - } - if( ae_isfinite(v, _state) ) - { - v = ae_sqrt(v, _state); - if( ae_fp_greater(state->stpmax,(double)(0))&&ae_fp_greater(v,state->stpmax) ) - { - bflag = ae_false; - } - } - else - { - bflag = ae_false; - } - if( !bflag ) - { - - /* - * Solution failed: - * try to increase lambda to make matrix positive definite and continue. - */ - if( !minlm_increaselambda(lambdav, nu, _state) ) - { - *iflag = -1; - goto lbl_3; - } - goto lbl_2; - } - - /* - * Step in State.XDir and it is bounded by StpMax. - * - * We should check stopping conditions on step size here. - * DeltaX, which is used for secant updates, is initialized here. - * - * This code is a bit tricky because sometimes XDir<>0, but - * it is so small that XDir+XBase==XBase (in finite precision - * arithmetics). So we set DeltaX to XBase, then - * add XDir, and then subtract XBase to get exact value of - * DeltaX. - * - * Step length is estimated using DeltaX. - * - * NOTE: stopping conditions are tested - * for fresh models only (ModelAge=0) - */ - ae_v_move(&deltax->ptr.p_double[0], 1, &xnew->ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_sub(&deltax->ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - *deltaxready = ae_true; - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(deltax->ptr.p_double[i]/state->s.ptr.p_double[i], _state); - } - v = ae_sqrt(v, _state); - if( ae_fp_less_eq(v,state->epsx) ) - { - if( state->modelage==0 ) - { - - /* - * Step is too short, model is fresh and we can rely on it. - * Terminating. - */ - *iflag = 2; - goto lbl_3; - } - else - { - - /* - * Step is suspiciously short, but model is not fresh - * and we can't rely on it. - */ - *iflag = -2; - goto lbl_3; - } - } - - /* - * Let's evaluate new step: - * a) if we have Fi vector, we evaluate it using rcomm, and - * then we manually calculate State.F as sum of squares of Fi[] - * b) if we have F value, we just evaluate it through rcomm interface - * - * We prefer (a) because we may need Fi vector for additional - * iterations - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &xnew->ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->needf = ae_false; - state->needfi = ae_false; - if( !state->hasfi ) - { - goto lbl_4; - } - state->needfi = ae_true; - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - state->needfi = ae_false; - v = ae_v_dotproduct(&state->fi.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1)); - *fnew = v; - ae_v_move(&deltaf->ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1)); - ae_v_sub(&deltaf->ptr.p_double[0], 1, &state->fibase.ptr.p_double[0], 1, ae_v_len(0,m-1)); - *deltafready = ae_true; - goto lbl_5; -lbl_4: - state->needf = ae_true; - state->rstate.stage = 1; - goto lbl_rcomm; -lbl_1: - state->needf = ae_false; - *fnew = state->f; -lbl_5: - if( !ae_isfinite(*fnew, _state) ) - { - - /* - * Integrity check failed, break! - */ - *iflag = -8; - goto lbl_3; - } - if( ae_fp_greater_eq(*fnew,state->fbase) ) - { - - /* - * Increase lambda and continue - */ - if( !minlm_increaselambda(lambdav, nu, _state) ) - { - *iflag = -1; - goto lbl_3; - } - goto lbl_2; - } - - /* - * We've found our step! - */ - *iflag = 0; - goto lbl_3; - goto lbl_2; -lbl_3: - *nu = (double)(1); - ae_assert(((*iflag>=-3&&*iflag<=0)||*iflag==-8)||*iflag>0, "MinLM: internal integrity check failed!", _state); - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = i; - state->rstate.ia.ptr.p_int[1] = n; - state->rstate.ia.ptr.p_int[2] = m; - state->rstate.ba.ptr.p_bool[0] = bflag; - state->rstate.ra.ptr.p_double[0] = v; - return result; -} - - -void _minlmstepfinder_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minlmstepfinder *p = (minlmstepfinder*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fi, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->modeldiag, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xbase, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fibase, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->havebndl, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->havebndu, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); - ae_vector_init(&p->xdir, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->choleskybuf, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpct, 0, DT_INT, _state, make_automatic); - _minqpstate_init(&p->qpstate, _state, make_automatic); - _minqpreport_init(&p->qprep, _state, make_automatic); - _sparsematrix_init(&p->tmpsp, _state, make_automatic); -} - - -void _minlmstepfinder_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minlmstepfinder *dst = (minlmstepfinder*)_dst; - minlmstepfinder *src = (minlmstepfinder*)_src; - dst->n = src->n; - dst->m = src->m; - dst->stpmax = src->stpmax; - dst->modelage = src->modelage; - dst->maxmodelage = src->maxmodelage; - dst->hasfi = src->hasfi; - dst->epsx = src->epsx; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - dst->f = src->f; - ae_vector_init_copy(&dst->fi, &src->fi, _state, make_automatic); - dst->needf = src->needf; - dst->needfi = src->needfi; - dst->fbase = src->fbase; - ae_vector_init_copy(&dst->modeldiag, &src->modeldiag, _state, make_automatic); - ae_vector_init_copy(&dst->xbase, &src->xbase, _state, make_automatic); - ae_vector_init_copy(&dst->fibase, &src->fibase, _state, make_automatic); - ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic); - ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic); - ae_vector_init_copy(&dst->havebndl, &src->havebndl, _state, make_automatic); - ae_vector_init_copy(&dst->havebndu, &src->havebndu, _state, make_automatic); - ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic); - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); - ae_vector_init_copy(&dst->xdir, &src->xdir, _state, make_automatic); - ae_vector_init_copy(&dst->choleskybuf, &src->choleskybuf, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - ae_vector_init_copy(&dst->tmpct, &src->tmpct, _state, make_automatic); - dst->actualdecrease = src->actualdecrease; - dst->predicteddecrease = src->predicteddecrease; - _minqpstate_init_copy(&dst->qpstate, &src->qpstate, _state, make_automatic); - _minqpreport_init_copy(&dst->qprep, &src->qprep, _state, make_automatic); - _sparsematrix_init_copy(&dst->tmpsp, &src->tmpsp, _state, make_automatic); -} - - -void _minlmstepfinder_clear(void* _p) -{ - minlmstepfinder *p = (minlmstepfinder*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->x); - ae_vector_clear(&p->fi); - ae_vector_clear(&p->modeldiag); - ae_vector_clear(&p->xbase); - ae_vector_clear(&p->fibase); - ae_vector_clear(&p->bndl); - ae_vector_clear(&p->bndu); - ae_vector_clear(&p->havebndl); - ae_vector_clear(&p->havebndu); - ae_vector_clear(&p->s); - _rcommstate_clear(&p->rstate); - ae_vector_clear(&p->xdir); - ae_vector_clear(&p->choleskybuf); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->tmpct); - _minqpstate_clear(&p->qpstate); - _minqpreport_clear(&p->qprep); - _sparsematrix_clear(&p->tmpsp); -} - - -void _minlmstepfinder_destroy(void* _p) -{ - minlmstepfinder *p = (minlmstepfinder*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->fi); - ae_vector_destroy(&p->modeldiag); - ae_vector_destroy(&p->xbase); - ae_vector_destroy(&p->fibase); - ae_vector_destroy(&p->bndl); - ae_vector_destroy(&p->bndu); - ae_vector_destroy(&p->havebndl); - ae_vector_destroy(&p->havebndu); - ae_vector_destroy(&p->s); - _rcommstate_destroy(&p->rstate); - ae_vector_destroy(&p->xdir); - ae_vector_destroy(&p->choleskybuf); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->tmpct); - _minqpstate_destroy(&p->qpstate); - _minqpreport_destroy(&p->qprep); - _sparsematrix_destroy(&p->tmpsp); -} - - -void _minlmstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minlmstate *p = (minlmstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fi, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->j, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->h, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xbase, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fibase, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->gbase, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->quadraticmodel, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->havebndl, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->havebndu, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->cleic, 0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xnew, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->xdir, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->deltax, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->deltaf, 0, DT_REAL, _state, make_automatic); - _smoothnessmonitor_init(&p->smonitor, _state, make_automatic); - ae_vector_init(&p->lastscaleused, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); - ae_vector_init(&p->choleskybuf, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fm1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fp1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fc1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->gm1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->gp1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->gc1, 0, DT_REAL, _state, make_automatic); - _minlbfgsstate_init(&p->internalstate, _state, make_automatic); - _minlbfgsreport_init(&p->internalrep, _state, make_automatic); - _minqpstate_init(&p->qpstate, _state, make_automatic); - _minqpreport_init(&p->qprep, _state, make_automatic); - _minlmstepfinder_init(&p->finderstate, _state, make_automatic); -} - - -void _minlmstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minlmstate *dst = (minlmstate*)_dst; - minlmstate *src = (minlmstate*)_src; - dst->n = src->n; - dst->m = src->m; - dst->diffstep = src->diffstep; - dst->epsx = src->epsx; - dst->maxits = src->maxits; - dst->xrep = src->xrep; - dst->stpmax = src->stpmax; - dst->maxmodelage = src->maxmodelage; - dst->makeadditers = src->makeadditers; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - dst->f = src->f; - ae_vector_init_copy(&dst->fi, &src->fi, _state, make_automatic); - ae_matrix_init_copy(&dst->j, &src->j, _state, make_automatic); - ae_matrix_init_copy(&dst->h, &src->h, _state, make_automatic); - ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic); - dst->needf = src->needf; - dst->needfg = src->needfg; - dst->needfgh = src->needfgh; - dst->needfij = src->needfij; - dst->needfi = src->needfi; - dst->xupdated = src->xupdated; - dst->userterminationneeded = src->userterminationneeded; - dst->algomode = src->algomode; - dst->hasf = src->hasf; - dst->hasfi = src->hasfi; - dst->hasg = src->hasg; - ae_vector_init_copy(&dst->xbase, &src->xbase, _state, make_automatic); - dst->fbase = src->fbase; - ae_vector_init_copy(&dst->fibase, &src->fibase, _state, make_automatic); - ae_vector_init_copy(&dst->gbase, &src->gbase, _state, make_automatic); - ae_matrix_init_copy(&dst->quadraticmodel, &src->quadraticmodel, _state, make_automatic); - ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic); - ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic); - ae_vector_init_copy(&dst->havebndl, &src->havebndl, _state, make_automatic); - ae_vector_init_copy(&dst->havebndu, &src->havebndu, _state, make_automatic); - ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic); - ae_matrix_init_copy(&dst->cleic, &src->cleic, _state, make_automatic); - dst->nec = src->nec; - dst->nic = src->nic; - dst->lambdav = src->lambdav; - dst->nu = src->nu; - dst->modelage = src->modelage; - ae_vector_init_copy(&dst->xnew, &src->xnew, _state, make_automatic); - ae_vector_init_copy(&dst->xdir, &src->xdir, _state, make_automatic); - ae_vector_init_copy(&dst->deltax, &src->deltax, _state, make_automatic); - ae_vector_init_copy(&dst->deltaf, &src->deltaf, _state, make_automatic); - dst->deltaxready = src->deltaxready; - dst->deltafready = src->deltafready; - _smoothnessmonitor_init_copy(&dst->smonitor, &src->smonitor, _state, make_automatic); - dst->teststep = src->teststep; - ae_vector_init_copy(&dst->lastscaleused, &src->lastscaleused, _state, make_automatic); - dst->repiterationscount = src->repiterationscount; - dst->repterminationtype = src->repterminationtype; - dst->repnfunc = src->repnfunc; - dst->repnjac = src->repnjac; - dst->repngrad = src->repngrad; - dst->repnhess = src->repnhess; - dst->repncholesky = src->repncholesky; - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); - ae_vector_init_copy(&dst->choleskybuf, &src->choleskybuf, _state, make_automatic); - ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic); - dst->actualdecrease = src->actualdecrease; - dst->predicteddecrease = src->predicteddecrease; - dst->xm1 = src->xm1; - dst->xp1 = src->xp1; - ae_vector_init_copy(&dst->fm1, &src->fm1, _state, make_automatic); - ae_vector_init_copy(&dst->fp1, &src->fp1, _state, make_automatic); - ae_vector_init_copy(&dst->fc1, &src->fc1, _state, make_automatic); - ae_vector_init_copy(&dst->gm1, &src->gm1, _state, make_automatic); - ae_vector_init_copy(&dst->gp1, &src->gp1, _state, make_automatic); - ae_vector_init_copy(&dst->gc1, &src->gc1, _state, make_automatic); - _minlbfgsstate_init_copy(&dst->internalstate, &src->internalstate, _state, make_automatic); - _minlbfgsreport_init_copy(&dst->internalrep, &src->internalrep, _state, make_automatic); - _minqpstate_init_copy(&dst->qpstate, &src->qpstate, _state, make_automatic); - _minqpreport_init_copy(&dst->qprep, &src->qprep, _state, make_automatic); - _minlmstepfinder_init_copy(&dst->finderstate, &src->finderstate, _state, make_automatic); -} - - -void _minlmstate_clear(void* _p) -{ - minlmstate *p = (minlmstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->x); - ae_vector_clear(&p->fi); - ae_matrix_clear(&p->j); - ae_matrix_clear(&p->h); - ae_vector_clear(&p->g); - ae_vector_clear(&p->xbase); - ae_vector_clear(&p->fibase); - ae_vector_clear(&p->gbase); - ae_matrix_clear(&p->quadraticmodel); - ae_vector_clear(&p->bndl); - ae_vector_clear(&p->bndu); - ae_vector_clear(&p->havebndl); - ae_vector_clear(&p->havebndu); - ae_vector_clear(&p->s); - ae_matrix_clear(&p->cleic); - ae_vector_clear(&p->xnew); - ae_vector_clear(&p->xdir); - ae_vector_clear(&p->deltax); - ae_vector_clear(&p->deltaf); - _smoothnessmonitor_clear(&p->smonitor); - ae_vector_clear(&p->lastscaleused); - _rcommstate_clear(&p->rstate); - ae_vector_clear(&p->choleskybuf); - ae_vector_clear(&p->tmp0); - ae_vector_clear(&p->fm1); - ae_vector_clear(&p->fp1); - ae_vector_clear(&p->fc1); - ae_vector_clear(&p->gm1); - ae_vector_clear(&p->gp1); - ae_vector_clear(&p->gc1); - _minlbfgsstate_clear(&p->internalstate); - _minlbfgsreport_clear(&p->internalrep); - _minqpstate_clear(&p->qpstate); - _minqpreport_clear(&p->qprep); - _minlmstepfinder_clear(&p->finderstate); -} - - -void _minlmstate_destroy(void* _p) -{ - minlmstate *p = (minlmstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->fi); - ae_matrix_destroy(&p->j); - ae_matrix_destroy(&p->h); - ae_vector_destroy(&p->g); - ae_vector_destroy(&p->xbase); - ae_vector_destroy(&p->fibase); - ae_vector_destroy(&p->gbase); - ae_matrix_destroy(&p->quadraticmodel); - ae_vector_destroy(&p->bndl); - ae_vector_destroy(&p->bndu); - ae_vector_destroy(&p->havebndl); - ae_vector_destroy(&p->havebndu); - ae_vector_destroy(&p->s); - ae_matrix_destroy(&p->cleic); - ae_vector_destroy(&p->xnew); - ae_vector_destroy(&p->xdir); - ae_vector_destroy(&p->deltax); - ae_vector_destroy(&p->deltaf); - _smoothnessmonitor_destroy(&p->smonitor); - ae_vector_destroy(&p->lastscaleused); - _rcommstate_destroy(&p->rstate); - ae_vector_destroy(&p->choleskybuf); - ae_vector_destroy(&p->tmp0); - ae_vector_destroy(&p->fm1); - ae_vector_destroy(&p->fp1); - ae_vector_destroy(&p->fc1); - ae_vector_destroy(&p->gm1); - ae_vector_destroy(&p->gp1); - ae_vector_destroy(&p->gc1); - _minlbfgsstate_destroy(&p->internalstate); - _minlbfgsreport_destroy(&p->internalrep); - _minqpstate_destroy(&p->qpstate); - _minqpreport_destroy(&p->qprep); - _minlmstepfinder_destroy(&p->finderstate); -} - - -void _minlmreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - minlmreport *p = (minlmreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _minlmreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - minlmreport *dst = (minlmreport*)_dst; - minlmreport *src = (minlmreport*)_src; - dst->iterationscount = src->iterationscount; - dst->terminationtype = src->terminationtype; - dst->nfunc = src->nfunc; - dst->njac = src->njac; - dst->ngrad = src->ngrad; - dst->nhess = src->nhess; - dst->ncholesky = src->ncholesky; -} - - -void _minlmreport_clear(void* _p) -{ - minlmreport *p = (minlmreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _minlmreport_destroy(void* _p) -{ - minlmreport *p = (minlmreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif - -} - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/optimization.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/optimization.h deleted file mode 100644 index 054da11..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/optimization.h +++ /dev/null @@ -1,12817 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifndef _optimization_pkg_h -#define _optimization_pkg_h -#include "ap.h" -#include "alglibinternal.h" -#include "linalg.h" -#include "alglibmisc.h" -#include "solvers.h" - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (DATATYPES) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_CQMODELS) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t n; - ae_int_t k; - double alpha; - double tau; - double theta; - ae_matrix a; - ae_matrix q; - ae_vector b; - ae_vector r; - ae_vector xc; - ae_vector d; - ae_vector activeset; - ae_matrix tq2dense; - ae_matrix tk2; - ae_vector tq2diag; - ae_vector tq1; - ae_vector tk1; - double tq0; - double tk0; - ae_vector txc; - ae_vector tb; - ae_int_t nfree; - ae_int_t ecakind; - ae_matrix ecadense; - ae_matrix eq; - ae_matrix eccm; - ae_vector ecadiag; - ae_vector eb; - double ec; - ae_vector tmp0; - ae_vector tmp1; - ae_vector tmpg; - ae_matrix tmp2; - ae_bool ismaintermchanged; - ae_bool issecondarytermchanged; - ae_bool islineartermchanged; - ae_bool isactivesetchanged; -} convexquadraticmodel; -#endif -#if defined(AE_COMPILE_OPTGUARDAPI) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_bool nonc0suspected; - ae_bool nonc0test0positive; - ae_int_t nonc0fidx; - double nonc0lipschitzc; - ae_bool nonc1suspected; - ae_bool nonc1test0positive; - ae_bool nonc1test1positive; - ae_int_t nonc1fidx; - double nonc1lipschitzc; - ae_bool badgradsuspected; - ae_int_t badgradfidx; - ae_int_t badgradvidx; - ae_vector badgradxbase; - ae_matrix badgraduser; - ae_matrix badgradnum; -} optguardreport; -typedef struct -{ - ae_bool positive; - ae_int_t fidx; - ae_vector x0; - ae_vector d; - ae_int_t n; - ae_vector stp; - ae_vector f; - ae_int_t cnt; - ae_int_t stpidxa; - ae_int_t stpidxb; -} optguardnonc0report; -typedef struct -{ - ae_bool positive; - ae_int_t fidx; - ae_vector x0; - ae_vector d; - ae_int_t n; - ae_vector stp; - ae_vector f; - ae_int_t cnt; - ae_int_t stpidxa; - ae_int_t stpidxb; -} optguardnonc1test0report; -typedef struct -{ - ae_bool positive; - ae_int_t fidx; - ae_int_t vidx; - ae_vector x0; - ae_vector d; - ae_int_t n; - ae_vector stp; - ae_vector g; - ae_int_t cnt; - ae_int_t stpidxa; - ae_int_t stpidxb; -} optguardnonc1test1report; -#endif -#if defined(AE_COMPILE_OPTSERV) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_vector norms; - ae_vector alpha; - ae_vector rho; - ae_matrix yk; - ae_vector idx; - ae_vector bufa; - ae_vector bufb; -} precbuflbfgs; -typedef struct -{ - ae_int_t n; - ae_int_t k; - ae_vector d; - ae_matrix v; - ae_vector bufc; - ae_matrix bufz; - ae_matrix bufw; - ae_vector tmp; -} precbuflowrank; -typedef struct -{ - ae_int_t n; - ae_int_t k; - ae_bool checksmoothness; - ae_vector s; - ae_vector dcur; - ae_int_t enqueuedcnt; - ae_vector enqueuedstp; - ae_vector enqueuedx; - ae_vector enqueuedfunc; - ae_matrix enqueuedjac; - ae_vector sortedstp; - ae_vector sortedidx; - ae_int_t sortedcnt; - double probingstp; - ae_vector probingf; - ae_int_t probingnvalues; - double probingstepmax; - double probingstepscale; - ae_int_t probingnstepsstored; - ae_vector probingsteps; - ae_matrix probingvalues; - ae_matrix probingslopes; - rcommstate probingrcomm; - ae_bool linesearchspoiled; - ae_bool linesearchstarted; - double nonc0currentrating; - double nonc1currentrating; - ae_bool badgradhasxj; - optguardreport rep; - double nonc0strrating; - double nonc0lngrating; - optguardnonc0report nonc0strrep; - optguardnonc0report nonc0lngrep; - double nonc1test0strrating; - double nonc1test0lngrating; - optguardnonc1test0report nonc1test0strrep; - optguardnonc1test0report nonc1test0lngrep; - double nonc1test1strrating; - double nonc1test1lngrating; - optguardnonc1test1report nonc1test1strrep; - optguardnonc1test1report nonc1test1lngrep; - ae_bool needfij; - ae_vector x; - ae_vector fi; - ae_matrix j; - rcommstate rstateg0; - ae_vector xbase; - ae_vector fbase; - ae_vector fm; - ae_vector fc; - ae_vector fp; - ae_vector jm; - ae_vector jc; - ae_vector jp; - ae_matrix jbaseusr; - ae_matrix jbasenum; - ae_vector stp; - ae_vector bufr; - ae_vector f; - ae_vector g; - ae_vector deltax; - ae_vector tmpidx; - ae_vector bufi; - ae_vector xu; - ae_vector du; - ae_vector f0; - ae_matrix j0; -} smoothnessmonitor; -#endif -#if defined(AE_COMPILE_SNNLS) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t ns; - ae_int_t nd; - ae_int_t nr; - ae_matrix densea; - ae_vector b; - ae_vector nnc; - double debugflops; - ae_int_t debugmaxinnerits; - ae_vector xn; - ae_vector xp; - ae_matrix tmpca; - ae_matrix tmplq; - ae_matrix trda; - ae_vector trdd; - ae_vector crb; - ae_vector g; - ae_vector d; - ae_vector dx; - ae_vector diagaa; - ae_vector cb; - ae_vector cx; - ae_vector cborg; - ae_vector tmpcholesky; - ae_vector r; - ae_vector regdiag; - ae_vector tmp0; - ae_vector tmp1; - ae_vector tmp2; - ae_vector rdtmprowmap; -} snnlssolver; -#endif -#if defined(AE_COMPILE_SACTIVESETS) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t n; - ae_int_t algostate; - ae_vector xc; - ae_bool hasxc; - ae_vector s; - ae_vector h; - ae_vector cstatus; - ae_bool basisisready; - ae_matrix sdensebatch; - ae_matrix pdensebatch; - ae_matrix idensebatch; - ae_int_t densebatchsize; - ae_vector sparsebatch; - ae_int_t sparsebatchsize; - ae_int_t basisage; - ae_bool feasinitpt; - ae_bool constraintschanged; - ae_vector hasbndl; - ae_vector hasbndu; - ae_vector bndl; - ae_vector bndu; - ae_matrix cleic; - ae_int_t nec; - ae_int_t nic; - ae_vector mtnew; - ae_vector mtx; - ae_vector mtas; - ae_vector cdtmp; - ae_vector corrtmp; - ae_vector unitdiagonal; - snnlssolver solver; - ae_vector scntmp; - ae_vector tmp0; - ae_vector tmpfeas; - ae_matrix tmpm0; - ae_vector rctmps; - ae_vector rctmpg; - ae_vector rctmprightpart; - ae_matrix rctmpdense0; - ae_matrix rctmpdense1; - ae_vector rctmpisequality; - ae_vector rctmpconstraintidx; - ae_vector rctmplambdas; - ae_matrix tmpbasis; - ae_vector tmpnormestimates; - ae_vector tmpreciph; - ae_vector tmpprodp; - ae_vector tmpprods; - ae_vector tmpcp; - ae_vector tmpcs; - ae_vector tmpci; -} sactiveset; -#endif -#if defined(AE_COMPILE_QQPSOLVER) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - double epsg; - double epsf; - double epsx; - ae_int_t maxouterits; - ae_bool cgphase; - ae_bool cnphase; - ae_int_t cgminits; - ae_int_t cgmaxits; - ae_int_t cnmaxupdates; - ae_int_t sparsesolver; -} qqpsettings; -typedef struct -{ - ae_int_t n; - ae_int_t akind; - ae_matrix densea; - sparsematrix sparsea; - ae_bool sparseupper; - double absamax; - double absasum; - double absasum2; - ae_vector b; - ae_vector bndl; - ae_vector bndu; - ae_vector havebndl; - ae_vector havebndu; - ae_vector xs; - ae_vector xf; - ae_vector gc; - ae_vector xp; - ae_vector dc; - ae_vector dp; - ae_vector cgc; - ae_vector cgp; - sactiveset sas; - ae_vector activated; - ae_int_t nfree; - ae_int_t cnmodelage; - ae_matrix densez; - sparsematrix sparsecca; - ae_vector yidx; - ae_vector regdiag; - ae_vector regx0; - ae_vector tmpcn; - ae_vector tmpcni; - ae_vector tmpcnb; - ae_vector tmp0; - ae_vector tmp1; - ae_vector stpbuf; - sparsebuffers sbuf; - ae_int_t repinneriterationscount; - ae_int_t repouteriterationscount; - ae_int_t repncholesky; - ae_int_t repncupdates; -} qqpbuffers; -#endif -#if defined(AE_COMPILE_MINLBFGS) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t n; - ae_int_t m; - double epsg; - double epsf; - double epsx; - ae_int_t maxits; - ae_bool xrep; - double stpmax; - ae_vector s; - double diffstep; - ae_int_t nfev; - ae_int_t mcstage; - ae_int_t k; - ae_int_t q; - ae_int_t p; - ae_vector rho; - ae_matrix yk; - ae_matrix sk; - ae_vector xp; - ae_vector theta; - ae_vector d; - double stp; - ae_vector work; - double fold; - double trimthreshold; - ae_vector xbase; - ae_int_t prectype; - double gammak; - ae_matrix denseh; - ae_vector diagh; - ae_vector precc; - ae_vector precd; - ae_matrix precw; - ae_int_t preck; - precbuflbfgs precbuf; - precbuflowrank lowrankbuf; - double fbase; - double fm2; - double fm1; - double fp1; - double fp2; - ae_vector autobuf; - ae_vector invs; - ae_vector x; - double f; - ae_vector g; - ae_bool needf; - ae_bool needfg; - ae_bool xupdated; - ae_bool userterminationneeded; - double teststep; - rcommstate rstate; - ae_int_t repiterationscount; - ae_int_t repnfev; - ae_int_t repterminationtype; - linminstate lstate; - ae_int_t smoothnessguardlevel; - smoothnessmonitor smonitor; - ae_vector lastscaleused; -} minlbfgsstate; -typedef struct -{ - ae_int_t iterationscount; - ae_int_t nfev; - ae_int_t terminationtype; -} minlbfgsreport; -#endif -#if defined(AE_COMPILE_LPQPSERV) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_VIPMSOLVER) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t n; - ae_int_t m; - ae_vector x; - ae_vector g; - ae_vector w; - ae_vector t; - ae_vector p; - ae_vector y; - ae_vector z; - ae_vector v; - ae_vector s; - ae_vector q; -} vipmvars; -typedef struct -{ - ae_vector sigma; - ae_vector beta; - ae_vector rho; - ae_vector nu; - ae_vector tau; - ae_vector alpha; - ae_vector gammaz; - ae_vector gammas; - ae_vector gammaw; - ae_vector gammaq; -} vipmrighthandside; -typedef struct -{ - ae_bool slacksforequalityconstraints; - ae_int_t n; - ae_int_t nmain; - double epsp; - double epsd; - double epsgap; - ae_bool islinear; - ae_vector scl; - ae_vector invscl; - ae_vector xorigin; - double targetscale; - ae_vector c; - ae_matrix denseh; - sparsematrix sparseh; - ae_vector diagr; - ae_int_t hkind; - ae_vector bndl; - ae_vector bndu; - ae_vector rawbndl; - ae_vector rawbndu; - ae_vector hasbndl; - ae_vector hasbndu; - ae_matrix denseafull; - ae_matrix denseamain; - sparsematrix sparseafull; - sparsematrix sparseamain; - sparsematrix combinedaslack; - ae_vector ascales; - ae_vector aflips; - ae_vector b; - ae_vector r; - ae_vector hasr; - ae_int_t mdense; - ae_int_t msparse; - vipmvars x0; - vipmvars current; - vipmvars best; - vipmvars trial; - vipmvars deltaaff; - vipmvars deltacorr; - ae_vector isfrozen; - ae_vector hasgz; - ae_vector hasts; - ae_vector haswv; - ae_vector haspq; - ae_int_t repiterationscount; - ae_int_t repncholesky; - ae_bool dotrace; - ae_bool dodetailedtrace; - ae_int_t factorizationtype; - ae_bool factorizationpoweredup; - ae_bool factorizationpresent; - ae_vector diagdz; - ae_vector diagdzi; - ae_vector diagdziri; - ae_vector diagds; - ae_vector diagdsi; - ae_vector diagdsiri; - ae_vector diagdw; - ae_vector diagdwi; - ae_vector diagdwir; - ae_vector diagdq; - ae_vector diagdqi; - ae_vector diagdqiri; - ae_vector diagddr; - ae_vector diagde; - ae_vector diagder; - ae_matrix factdensehaug; - ae_vector factregdhrh; - ae_vector factinvregdzrz; - ae_vector factregewave; - sparsematrix factsparsekkttmpl; - sparsematrix factsparsekkt; - ae_vector factsparsekktpivp; - ae_vector facttmpdiag; - spcholanalysis ldltanalysis; - ae_vector factsparsediagd; - vipmrighthandside rhs; - ae_vector rhsalphacap; - ae_vector rhsbetacap; - ae_vector rhsnucap; - ae_vector rhstaucap; - ae_vector deltaxy; - ae_vector tmphx; - ae_vector tmpax; - ae_vector tmpaty; - vipmvars zerovars; - ae_vector dummyr; - ae_vector tmpy; - ae_vector tmp0; - ae_vector tmp1; - ae_vector tmp2; - ae_matrix tmpr2; - ae_vector tmplaggrad; - ae_vector tmpi; - sparsematrix tmpsparse0; -} vipmstate; -#endif -#if defined(AE_COMPILE_NLCSQP) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t algokind; - vipmstate ipmsolver; - ae_vector curb; - ae_vector curbndl; - ae_vector curbndu; - ae_vector cural; - ae_vector curau; - sparsematrix sparserawlc; - sparsematrix sparseefflc; - ae_vector d0; - ae_matrix h; - ae_matrix densedummy; - sparsematrix sparsedummy; - ae_vector tmp0; - ae_vector tmp1; - ae_vector tmp2; - ae_vector sk; - ae_vector yk; - ae_vector hasbndl; - ae_vector hasbndu; - ae_vector hasal; - ae_vector hasau; - ae_matrix activea; - ae_vector activerhs; - ae_vector activeidx; - ae_int_t activesetsize; -} minsqpsubsolver; -typedef struct -{ - ae_vector sclagtmp0; - ae_vector sclagtmp1; -} minsqptmplagrangian; -typedef struct -{ - ae_vector mftmp0; -} minsqptmpmerit; -typedef struct -{ - ae_int_t n; - ae_int_t nec; - ae_int_t nic; - ae_int_t nlec; - ae_int_t nlic; - ae_vector d; - ae_vector dx; - ae_vector stepkx; - ae_vector stepkxc; - ae_vector stepkxn; - ae_vector stepkfi; - ae_vector stepkfic; - ae_vector stepkfin; - ae_matrix stepkj; - ae_matrix stepkjc; - ae_matrix stepkjn; - ae_vector lagmult; - ae_vector dummylagmult; - ae_vector penalties; - minsqptmpmerit tmpmerit; - minsqptmplagrangian tmplagrangianfg; - ae_vector stepklaggrad; - ae_vector stepknlaggrad; - ae_int_t status; - ae_bool increasebigc; - rcommstate rmeritphasestate; -} minsqpmeritphasestate; -typedef struct -{ - ae_int_t n; - ae_int_t nec; - ae_int_t nic; - ae_int_t nlec; - ae_int_t nlic; - ae_vector s; - ae_matrix scaledcleic; - ae_vector lcsrcidx; - ae_vector hasbndl; - ae_vector hasbndu; - ae_vector scaledbndl; - ae_vector scaledbndu; - double epsx; - ae_int_t maxits; - ae_vector x; - ae_vector fi; - ae_matrix j; - double f; - ae_bool needfij; - ae_bool xupdated; - minsqpmeritphasestate meritstate; - double bigc; - double trustrad; - ae_int_t trustradstagnationcnt; - ae_int_t fstagnationcnt; - ae_vector step0x; - ae_vector stepkx; - ae_vector backupx; - ae_vector step0fi; - ae_vector stepkfi; - ae_vector backupfi; - ae_matrix step0j; - ae_matrix stepkj; - ae_bool haslagmult; - ae_vector meritlagmult; - ae_vector dummylagmult; - ae_matrix abslagmemory; - ae_vector fscales; - ae_vector tracegamma; - minsqpsubsolver subsolver; - minsqptmpmerit tmpmerit; - ae_int_t repsimplexiterations; - ae_int_t repsimplexiterations1; - ae_int_t repsimplexiterations2; - ae_int_t repsimplexiterations3; - ae_int_t repiterationscount; - ae_int_t repterminationtype; - double repbcerr; - ae_int_t repbcidx; - double replcerr; - ae_int_t replcidx; - double repnlcerr; - ae_int_t repnlcidx; - rcommstate rstate; -} minsqpstate; -#endif -#if defined(AE_COMPILE_QPDENSEAULSOLVER) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - double epsx; - ae_int_t outerits; - double rho; -} qpdenseaulsettings; -typedef struct -{ - ae_vector nulc; - ae_matrix sclsfta; - ae_vector sclsftb; - ae_vector sclsfthasbndl; - ae_vector sclsfthasbndu; - ae_vector sclsftbndl; - ae_vector sclsftbndu; - ae_vector sclsftxc; - ae_matrix sclsftcleic; - ae_vector cidx; - ae_vector cscales; - ae_matrix exa; - ae_vector exb; - ae_vector exxc; - ae_vector exbndl; - ae_vector exbndu; - ae_vector exscale; - ae_vector exxorigin; - qqpsettings qqpsettingsuser; - qqpbuffers qqpbuf; - ae_vector nulcest; - ae_vector tmpg; - ae_vector tmp0; - ae_matrix tmp2; - ae_vector modelg; - ae_vector d; - ae_vector deltax; - convexquadraticmodel dummycqm; - sparsematrix dummysparse; - ae_matrix qrkkt; - ae_vector qrrightpart; - ae_vector qrtau; - ae_vector qrsv0; - ae_vector qrsvx1; - ae_vector nicerr; - ae_vector nicnact; - ae_int_t repinneriterationscount; - ae_int_t repouteriterationscount; - ae_int_t repncholesky; - ae_int_t repnwrkchanges; - ae_int_t repnwrk0; - ae_int_t repnwrk1; - ae_int_t repnwrkf; - ae_int_t repnmv; -} qpdenseaulbuffers; -#endif -#if defined(AE_COMPILE_MINBLEIC) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t nmain; - ae_int_t nslack; - double epsg; - double epsf; - double epsx; - ae_int_t maxits; - ae_bool xrep; - ae_bool drep; - double stpmax; - double diffstep; - sactiveset sas; - ae_vector s; - ae_int_t prectype; - ae_vector diagh; - ae_vector x; - double f; - ae_vector g; - ae_bool needf; - ae_bool needfg; - ae_bool xupdated; - ae_bool lsstart; - ae_bool steepestdescentstep; - ae_bool boundedstep; - ae_bool userterminationneeded; - rcommstate rstate; - ae_vector ugc; - ae_vector cgc; - ae_vector xn; - ae_vector ugn; - ae_vector cgn; - ae_vector xp; - double fc; - double fn; - double fp; - ae_vector d; - ae_matrix cleic; - ae_int_t nec; - ae_int_t nic; - double lastgoodstep; - double lastscaledgoodstep; - double maxscaledgrad; - ae_vector hasbndl; - ae_vector hasbndu; - ae_vector bndl; - ae_vector bndu; - ae_int_t repinneriterationscount; - ae_int_t repouteriterationscount; - ae_int_t repnfev; - ae_int_t repvaridx; - ae_int_t repterminationtype; - double repdebugeqerr; - double repdebugfs; - double repdebugff; - double repdebugdx; - ae_int_t repdebugfeasqpits; - ae_int_t repdebugfeasgpaits; - ae_vector xstart; - snnlssolver solver; - double fbase; - double fm2; - double fm1; - double fp1; - double fp2; - double xm1; - double xp1; - double gm1; - double gp1; - ae_int_t cidx; - double cval; - ae_vector tmpprec; - ae_vector tmp0; - ae_int_t nfev; - ae_int_t mcstage; - double stp; - double curstpmax; - double activationstep; - ae_vector work; - linminstate lstate; - double trimthreshold; - ae_int_t nonmonotoniccnt; - ae_matrix bufyk; - ae_matrix bufsk; - ae_vector bufrho; - ae_vector buftheta; - ae_int_t bufsize; - double teststep; - ae_int_t smoothnessguardlevel; - smoothnessmonitor smonitor; - ae_vector lastscaleused; - ae_vector invs; -} minbleicstate; -typedef struct -{ - ae_int_t iterationscount; - ae_int_t nfev; - ae_int_t varidx; - ae_int_t terminationtype; - double debugeqerr; - double debugfs; - double debugff; - double debugdx; - ae_int_t debugfeasqpits; - ae_int_t debugfeasgpaits; - ae_int_t inneriterationscount; - ae_int_t outeriterationscount; -} minbleicreport; -#endif -#if defined(AE_COMPILE_QPBLEICSOLVER) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - double epsg; - double epsf; - double epsx; - ae_int_t maxits; -} qpbleicsettings; -typedef struct -{ - minbleicstate solver; - minbleicreport solverrep; - ae_vector tmp0; - ae_vector tmp1; - ae_vector tmpi; - ae_int_t repinneriterationscount; - ae_int_t repouteriterationscount; -} qpbleicbuffers; -#endif -#if defined(AE_COMPILE_MINQP) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t n; - qqpsettings qqpsettingsuser; - qpbleicsettings qpbleicsettingsuser; - qpdenseaulsettings qpdenseaulsettingsuser; - double veps; - ae_bool dbgskipconstraintnormalization; - ae_int_t algokind; - ae_int_t akind; - convexquadraticmodel a; - sparsematrix sparsea; - ae_bool sparseaupper; - double absamax; - double absasum; - double absasum2; - ae_vector b; - ae_vector bndl; - ae_vector bndu; - ae_int_t stype; - ae_vector s; - ae_vector havebndl; - ae_vector havebndu; - ae_vector xorigin; - ae_vector startx; - ae_bool havex; - ae_matrix densec; - sparsematrix sparsec; - ae_vector cl; - ae_vector cu; - ae_int_t mdense; - ae_int_t msparse; - ae_vector xs; - ae_int_t repinneriterationscount; - ae_int_t repouteriterationscount; - ae_int_t repncholesky; - ae_int_t repnmv; - ae_int_t repterminationtype; - ae_vector replagbc; - ae_vector replaglc; - ae_vector effectives; - ae_vector tmp0; - ae_matrix ecleic; - ae_vector elaglc; - ae_vector elagmlt; - ae_vector elagidx; - ae_matrix dummyr2; - sparsematrix dummysparse; - ae_matrix tmpr2; - ae_vector wrkbndl; - ae_vector wrkbndu; - ae_vector wrkcl; - ae_vector wrkcu; - ae_matrix wrkdensec; - sparsematrix wrksparsec; - ae_bool qpbleicfirstcall; - qpbleicbuffers qpbleicbuf; - qqpbuffers qqpbuf; - qpdenseaulbuffers qpdenseaulbuf; - vipmstate vsolver; -} minqpstate; -typedef struct -{ - ae_int_t inneriterationscount; - ae_int_t outeriterationscount; - ae_int_t nmv; - ae_int_t ncholesky; - ae_int_t terminationtype; - ae_vector lagbc; - ae_vector laglc; -} minqpreport; -#endif -#if defined(AE_COMPILE_LPQPPRESOLVE) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t newn; - ae_int_t oldn; - ae_int_t newm; - ae_int_t oldm; - ae_vector rawbndl; - ae_vector rawbndu; - ae_vector colscales; - ae_vector rowscales; - double costscale; - ae_vector c; - ae_vector bndl; - ae_vector bndu; - sparsematrix sparsea; - ae_vector al; - ae_vector au; -} presolveinfo; -#endif -#if defined(AE_COMPILE_REVISEDDUALSIMPLEX) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - double pivottol; - double perturbmag; - ae_int_t maxtrfage; - ae_int_t trftype; - ae_int_t ratiotest; - ae_int_t pricing; - ae_int_t shifting; - double xtolabs; - double xtolrelabs; - double dtolabs; -} dualsimplexsettings; -typedef struct -{ - ae_int_t n; - ae_int_t k; - ae_vector idx; - ae_vector vals; - ae_vector dense; -} dssvector; -typedef struct -{ - ae_int_t ns; - ae_int_t m; - ae_vector idx; - ae_vector nidx; - ae_vector isbasic; - ae_int_t trftype; - ae_bool isvalidtrf; - ae_int_t trfage; - ae_matrix denselu; - sparsematrix sparsel; - sparsematrix sparseu; - sparsematrix sparseut; - ae_vector rowpermbwd; - ae_vector colpermbwd; - ae_vector densepfieta; - ae_vector densemu; - ae_vector rk; - ae_vector dk; - ae_vector dseweights; - ae_bool dsevalid; - double eminu; - ae_int_t statfact; - ae_int_t statupdt; - double statoffdiag; - ae_vector wtmp0; - ae_vector wtmp1; - ae_vector wtmp2; - ae_vector nrs; - ae_vector tcinvidx; - ae_matrix denselu2; - ae_vector densep2; - ae_vector densep2c; - sparsematrix sparselu1; - sparsematrix sparselu2; - sluv2buffer lubuf2; - ae_vector tmpi; - ae_vector utmp0; - ae_vector utmpi; - sparsematrix sparseludbg; -} dualsimplexbasis; -typedef struct -{ - ae_int_t ns; - ae_int_t m; - ae_vector rawc; - ae_vector bndl; - ae_vector bndu; - ae_vector bndt; - ae_vector xa; - ae_vector d; - ae_int_t state; - ae_vector xb; - ae_vector bndlb; - ae_vector bndub; - ae_vector bndtb; - ae_vector bndtollb; - ae_vector bndtolub; - ae_vector effc; -} dualsimplexsubproblem; -typedef struct -{ - ae_vector rowscales; - ae_vector rawbndl; - ae_vector rawbndu; - ae_int_t ns; - ae_int_t m; - sparsematrix a; - sparsematrix at; - dualsimplexbasis basis; - dualsimplexsubproblem primary; - dualsimplexsubproblem phase1; - dualsimplexsubproblem phase3; - ae_vector repx; - ae_vector replagbc; - ae_vector replaglc; - ae_vector repstats; - ae_int_t repterminationtype; - ae_int_t repiterationscount; - ae_int_t repiterationscount1; - ae_int_t repiterationscount2; - ae_int_t repiterationscount3; - ae_int_t repphase1time; - ae_int_t repphase2time; - ae_int_t repphase3time; - ae_int_t repdualpricingtime; - ae_int_t repdualbtrantime; - ae_int_t repdualpivotrowtime; - ae_int_t repdualratiotesttime; - ae_int_t repdualftrantime; - ae_int_t repdualupdatesteptime; - double repfillpivotrow; - ae_int_t repfillpivotrowcnt; - double repfillrhor; - ae_int_t repfillrhorcnt; - double repfilldensemu; - ae_int_t repfilldensemucnt; - ae_bool dotrace; - ae_bool dodetailedtrace; - ae_bool dotimers; - ae_vector btrantmp0; - ae_vector btrantmp1; - ae_vector btrantmp2; - ae_vector ftrantmp0; - ae_vector ftrantmp1; - ae_vector possibleflips; - ae_int_t possibleflipscnt; - ae_vector dfctmp0; - ae_vector dfctmp1; - ae_vector dfctmp2; - ae_vector ustmpi; - apbuffers xydsbuf; - ae_vector tmp0; - ae_vector tmp1; - ae_vector tmp2; - dssvector alphar; - dssvector rhor; - ae_vector tau; - ae_vector alphaq; - ae_vector alphaqim; - ae_vector eligiblealphar; - ae_vector harrisset; -} dualsimplexstate; -#endif -#if defined(AE_COMPILE_MINLP) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t n; - ae_int_t algokind; - double ipmlambda; - ae_vector s; - ae_vector c; - ae_vector bndl; - ae_vector bndu; - ae_int_t m; - sparsematrix a; - ae_vector al; - ae_vector au; - ae_vector xs; - ae_vector lagbc; - ae_vector laglc; - ae_vector cs; - double repf; - double repprimalerror; - double repdualerror; - double repslackerror; - ae_int_t repiterationscount; - ae_int_t repterminationtype; - ae_int_t repn; - ae_int_t repm; - double dsseps; - double ipmeps; - dualsimplexstate dss; - vipmstate ipm; - ae_vector adddtmpi; - ae_vector adddtmpr; - ae_vector tmpax; - ae_vector tmpg; - presolveinfo presolver; - ae_vector zeroorigin; - ae_vector units; - sparsematrix ipmquadratic; -} minlpstate; -typedef struct -{ - double f; - ae_vector lagbc; - ae_vector laglc; - ae_vector y; - ae_vector stats; - double primalerror; - double dualerror; - double slackerror; - ae_int_t iterationscount; - ae_int_t terminationtype; -} minlpreport; -#endif -#if defined(AE_COMPILE_NLCSLP) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - presolveinfo presolver; - dualsimplexstate dss; - dualsimplexsettings dsssettings; - dualsimplexbasis lastbasis; - ae_bool basispresent; - ae_matrix curd; - ae_int_t curdcnt; - ae_vector curb; - ae_vector curbndl; - ae_vector curbndu; - ae_vector cural; - ae_vector curau; - sparsematrix sparserawlc; - sparsematrix sparseefflc; - ae_int_t hessiantype; - ae_matrix h; - ae_matrix curhd; - ae_matrix densedummy; - sparsematrix sparsedummy; - ae_vector tmp0; - ae_vector tmp1; - ae_vector sk; - ae_vector yk; - ae_vector xs; - ae_vector laglc; - ae_vector lagbc; - ae_vector cs; -} minslpsubsolver; -typedef struct -{ - ae_vector sclagtmp0; - ae_vector sclagtmp1; -} minslptmplagrangian; -typedef struct -{ - ae_vector mftmp0; -} minslptmpmerit; -typedef struct -{ - ae_bool usecorrection; - ae_vector d; - ae_vector dx; - ae_vector stepkxc; - ae_vector stepkxn; - ae_vector stepkfic; - ae_vector stepkfin; - ae_matrix stepkjc; - ae_matrix stepkjn; - ae_vector dummylagmult; - minslptmpmerit tmpmerit; - rcommstate rphase13state; -} minslpphase13state; -typedef struct -{ - ae_vector stepkxn; - ae_vector stepkxc; - ae_vector stepkfin; - ae_vector stepkfic; - ae_matrix stepkjn; - ae_matrix stepkjc; - ae_vector stepklaggrad; - ae_vector stepknlaggrad; - ae_vector stepknlagmult; - ae_vector meritlagmult; - minslptmplagrangian tmplagrangianfg; - double lastlcerr; - ae_int_t lastlcidx; - double lastnlcerr; - ae_int_t lastnlcidx; - ae_vector tmp0; - ae_vector d; - linminstate mcstate; - minslptmpmerit tmpmerit; - rcommstate rphase2state; -} minslpphase2state; -typedef struct -{ - ae_int_t n; - ae_int_t nec; - ae_int_t nic; - ae_int_t nlec; - ae_int_t nlic; - ae_vector s; - ae_matrix scaledcleic; - ae_vector lcsrcidx; - ae_vector hasbndl; - ae_vector hasbndu; - ae_vector scaledbndl; - ae_vector scaledbndu; - double epsx; - ae_int_t maxits; - ae_int_t hessiantype; - ae_vector x; - ae_vector fi; - ae_matrix j; - double f; - ae_bool needfij; - ae_bool xupdated; - minslpphase13state state13; - minslpphase2state state2; - double trustrad; - ae_int_t lpfailurecnt; - ae_int_t fstagnationcnt; - ae_vector step0x; - ae_vector stepkx; - ae_vector backupx; - ae_vector step0fi; - ae_vector stepkfi; - ae_vector backupfi; - ae_matrix step0j; - ae_matrix stepkj; - ae_matrix backupj; - ae_vector meritlagmult; - ae_vector dummylagmult; - ae_vector fscales; - ae_vector meritfunctionhistory; - ae_int_t historylen; - minslpsubsolver subsolver; - minslptmpmerit tmpmerit; - ae_int_t repsimplexiterations; - ae_int_t repsimplexiterations1; - ae_int_t repsimplexiterations2; - ae_int_t repsimplexiterations3; - ae_int_t repinneriterationscount; - ae_int_t repouteriterationscount; - ae_int_t repterminationtype; - double repbcerr; - ae_int_t repbcidx; - double replcerr; - ae_int_t replcidx; - double repnlcerr; - ae_int_t repnlcidx; - rcommstate rstate; -} minslpstate; -#endif -#if defined(AE_COMPILE_MINNLC) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - double stabilizingpoint; - double initialinequalitymultiplier; - ae_int_t solvertype; - ae_int_t prectype; - ae_int_t updatefreq; - double rho; - ae_int_t n; - double epsx; - ae_int_t maxits; - ae_int_t aulitscnt; - ae_bool xrep; - double stpmax; - double diffstep; - double teststep; - ae_vector s; - ae_vector bndl; - ae_vector bndu; - ae_vector hasbndl; - ae_vector hasbndu; - ae_int_t nec; - ae_int_t nic; - ae_matrix cleic; - ae_vector lcsrcidx; - ae_int_t ng; - ae_int_t nh; - ae_vector x; - double f; - ae_vector fi; - ae_matrix j; - ae_bool needfij; - ae_bool needfi; - ae_bool xupdated; - rcommstate rstate; - rcommstate rstateaul; - rcommstate rstateslp; - ae_vector scaledbndl; - ae_vector scaledbndu; - ae_matrix scaledcleic; - ae_vector xc; - ae_vector xstart; - ae_vector xbase; - ae_vector fbase; - ae_vector dfbase; - ae_vector fm2; - ae_vector fm1; - ae_vector fp1; - ae_vector fp2; - ae_vector dfm1; - ae_vector dfp1; - ae_vector bufd; - ae_vector bufc; - ae_vector tmp0; - ae_matrix bufw; - ae_matrix bufz; - ae_vector xk; - ae_vector xk1; - ae_vector gk; - ae_vector gk1; - double gammak; - ae_bool xkpresent; - minlbfgsstate auloptimizer; - minlbfgsreport aulreport; - ae_vector nubc; - ae_vector nulc; - ae_vector nunlc; - ae_bool userterminationneeded; - minslpstate slpsolverstate; - minsqpstate sqpsolverstate; - ae_int_t smoothnessguardlevel; - smoothnessmonitor smonitor; - ae_vector lastscaleused; - ae_int_t repinneriterationscount; - ae_int_t repouteriterationscount; - ae_int_t repnfev; - ae_int_t repterminationtype; - double repbcerr; - ae_int_t repbcidx; - double replcerr; - ae_int_t replcidx; - double repnlcerr; - ae_int_t repnlcidx; - ae_int_t repdbgphase0its; -} minnlcstate; -typedef struct -{ - ae_int_t iterationscount; - ae_int_t nfev; - ae_int_t terminationtype; - double bcerr; - ae_int_t bcidx; - double lcerr; - ae_int_t lcidx; - double nlcerr; - ae_int_t nlcidx; - ae_int_t dbgphase0its; -} minnlcreport; -#endif -#if defined(AE_COMPILE_MINBC) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t nmain; - double epsg; - double epsf; - double epsx; - ae_int_t maxits; - ae_bool xrep; - double stpmax; - double diffstep; - ae_vector s; - ae_int_t prectype; - ae_vector diagh; - ae_vector x; - double f; - ae_vector g; - ae_bool needf; - ae_bool needfg; - ae_bool xupdated; - ae_bool userterminationneeded; - rcommstate rstate; - ae_vector xc; - ae_vector ugc; - ae_vector cgc; - ae_vector xn; - ae_vector ugn; - ae_vector cgn; - ae_vector xp; - double fc; - double fn; - double fp; - ae_vector d; - double lastscaledgoodstep; - ae_vector hasbndl; - ae_vector hasbndu; - ae_vector bndl; - ae_vector bndu; - ae_int_t repiterationscount; - ae_int_t repnfev; - ae_int_t repvaridx; - ae_int_t repterminationtype; - ae_vector xstart; - double fbase; - double fm2; - double fm1; - double fp1; - double fp2; - double xm1; - double xp1; - double gm1; - double gp1; - ae_vector tmpprec; - ae_vector tmp0; - ae_int_t nfev; - ae_int_t mcstage; - double stp; - double curstpmax; - ae_vector work; - linminstate lstate; - double trimthreshold; - ae_int_t nonmonotoniccnt; - ae_matrix bufyk; - ae_matrix bufsk; - ae_vector bufrho; - ae_vector buftheta; - ae_int_t bufsize; - double teststep; - ae_int_t smoothnessguardlevel; - smoothnessmonitor smonitor; - ae_vector lastscaleused; - ae_vector invs; -} minbcstate; -typedef struct -{ - ae_int_t iterationscount; - ae_int_t nfev; - ae_int_t varidx; - ae_int_t terminationtype; -} minbcreport; -#endif -#if defined(AE_COMPILE_MINNS) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - double fc; - double fn; - ae_vector xc; - ae_vector xn; - ae_vector x0; - ae_vector gc; - ae_vector d; - ae_matrix uh; - ae_matrix ch; - ae_matrix rk; - ae_vector invutc; - ae_vector tmp0; - ae_vector tmpidx; - ae_vector tmpd; - ae_vector tmpc; - ae_vector tmplambdas; - ae_matrix tmpc2; - ae_vector tmpb; - snnlssolver nnls; -} minnsqp; -typedef struct -{ - ae_int_t solvertype; - ae_int_t n; - double epsx; - ae_int_t maxits; - ae_bool xrep; - double diffstep; - ae_vector s; - ae_vector bndl; - ae_vector bndu; - ae_vector hasbndl; - ae_vector hasbndu; - ae_int_t nec; - ae_int_t nic; - ae_matrix cleic; - ae_int_t ng; - ae_int_t nh; - ae_vector x; - double f; - ae_vector fi; - ae_matrix j; - ae_bool needfij; - ae_bool needfi; - ae_bool xupdated; - rcommstate rstate; - rcommstate rstateags; - hqrndstate agsrs; - double agsradius; - ae_int_t agssamplesize; - double agsraddecay; - double agsalphadecay; - double agsdecrease; - double agsinitstp; - double agsstattold; - double agsshortstpabs; - double agsshortstprel; - double agsshortf; - ae_int_t agsshortlimit; - double agsrhononlinear; - ae_int_t agsminupdate; - ae_int_t agsmaxraddecays; - ae_int_t agsmaxbacktrack; - ae_int_t agsmaxbacktracknonfull; - double agspenaltylevel; - double agspenaltyincrease; - ae_vector xstart; - ae_vector xc; - ae_vector xn; - ae_vector grs; - ae_vector d; - ae_vector colmax; - ae_vector diagh; - ae_vector signmin; - ae_vector signmax; - ae_bool userterminationneeded; - ae_vector scaledbndl; - ae_vector scaledbndu; - ae_matrix scaledcleic; - ae_vector rholinear; - ae_matrix samplex; - ae_matrix samplegm; - ae_matrix samplegmbc; - ae_vector samplef; - ae_vector samplef0; - minnsqp nsqp; - ae_vector tmp0; - ae_vector tmp1; - ae_matrix tmp2; - ae_vector tmp3; - ae_vector xbase; - ae_vector fp; - ae_vector fm; - ae_int_t repinneriterationscount; - ae_int_t repouteriterationscount; - ae_int_t repnfev; - ae_int_t repvaridx; - ae_int_t repfuncidx; - ae_int_t repterminationtype; - double replcerr; - double repnlcerr; - ae_int_t dbgncholesky; -} minnsstate; -typedef struct -{ - ae_int_t iterationscount; - ae_int_t nfev; - double cerr; - double lcerr; - double nlcerr; - ae_int_t terminationtype; - ae_int_t varidx; - ae_int_t funcidx; -} minnsreport; -#endif -#if defined(AE_COMPILE_MINCOMP) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t n; - double epsg; - double epsf; - double epsx; - ae_int_t maxits; - ae_bool xrep; - double stpmax; - ae_int_t cgtype; - ae_int_t k; - ae_int_t nfev; - ae_int_t mcstage; - ae_vector bndl; - ae_vector bndu; - ae_int_t curalgo; - ae_int_t acount; - double mu; - double finit; - double dginit; - ae_vector ak; - ae_vector xk; - ae_vector dk; - ae_vector an; - ae_vector xn; - ae_vector dn; - ae_vector d; - double fold; - double stp; - ae_vector work; - ae_vector yk; - ae_vector gc; - double laststep; - ae_vector x; - double f; - ae_vector g; - ae_bool needfg; - ae_bool xupdated; - rcommstate rstate; - ae_int_t repiterationscount; - ae_int_t repnfev; - ae_int_t repterminationtype; - ae_int_t debugrestartscount; - linminstate lstate; - double betahs; - double betady; -} minasastate; -typedef struct -{ - ae_int_t iterationscount; - ae_int_t nfev; - ae_int_t terminationtype; - ae_int_t activeconstraints; -} minasareport; -#endif -#if defined(AE_COMPILE_MINCG) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t n; - double epsg; - double epsf; - double epsx; - ae_int_t maxits; - double stpmax; - double suggestedstep; - ae_bool xrep; - ae_bool drep; - ae_int_t cgtype; - ae_int_t prectype; - ae_vector diagh; - ae_vector diaghl2; - ae_matrix vcorr; - ae_int_t vcnt; - ae_vector s; - double diffstep; - ae_int_t nfev; - ae_int_t mcstage; - ae_int_t k; - ae_vector xk; - ae_vector dk; - ae_vector xn; - ae_vector dn; - ae_vector d; - double fold; - double stp; - double curstpmax; - ae_vector yk; - double lastgoodstep; - double lastscaledstep; - ae_int_t mcinfo; - ae_bool innerresetneeded; - ae_bool terminationneeded; - double trimthreshold; - ae_vector xbase; - ae_int_t rstimer; - ae_vector x; - double f; - ae_vector g; - ae_bool needf; - ae_bool needfg; - ae_bool xupdated; - ae_bool algpowerup; - ae_bool lsstart; - ae_bool lsend; - ae_bool userterminationneeded; - rcommstate rstate; - ae_int_t repiterationscount; - ae_int_t repnfev; - ae_int_t repterminationtype; - ae_int_t debugrestartscount; - linminstate lstate; - double fbase; - double fm2; - double fm1; - double fp1; - double fp2; - double betahs; - double betady; - ae_vector work0; - ae_vector work1; - ae_vector invs; - double teststep; - ae_int_t smoothnessguardlevel; - smoothnessmonitor smonitor; - ae_vector lastscaleused; -} mincgstate; -typedef struct -{ - ae_int_t iterationscount; - ae_int_t nfev; - ae_int_t terminationtype; -} mincgreport; -#endif -#if defined(AE_COMPILE_MINLM) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t n; - ae_int_t m; - double stpmax; - ae_int_t modelage; - ae_int_t maxmodelage; - ae_bool hasfi; - double epsx; - ae_vector x; - double f; - ae_vector fi; - ae_bool needf; - ae_bool needfi; - double fbase; - ae_vector modeldiag; - ae_vector xbase; - ae_vector fibase; - ae_vector bndl; - ae_vector bndu; - ae_vector havebndl; - ae_vector havebndu; - ae_vector s; - rcommstate rstate; - ae_vector xdir; - ae_vector choleskybuf; - ae_vector tmp0; - ae_vector tmpct; - double actualdecrease; - double predicteddecrease; - minqpstate qpstate; - minqpreport qprep; - sparsematrix tmpsp; -} minlmstepfinder; -typedef struct -{ - ae_int_t n; - ae_int_t m; - double diffstep; - double epsx; - ae_int_t maxits; - ae_bool xrep; - double stpmax; - ae_int_t maxmodelage; - ae_bool makeadditers; - ae_vector x; - double f; - ae_vector fi; - ae_matrix j; - ae_matrix h; - ae_vector g; - ae_bool needf; - ae_bool needfg; - ae_bool needfgh; - ae_bool needfij; - ae_bool needfi; - ae_bool xupdated; - ae_bool userterminationneeded; - ae_int_t algomode; - ae_bool hasf; - ae_bool hasfi; - ae_bool hasg; - ae_vector xbase; - double fbase; - ae_vector fibase; - ae_vector gbase; - ae_matrix quadraticmodel; - ae_vector bndl; - ae_vector bndu; - ae_vector havebndl; - ae_vector havebndu; - ae_vector s; - ae_matrix cleic; - ae_int_t nec; - ae_int_t nic; - double lambdav; - double nu; - ae_int_t modelage; - ae_vector xnew; - ae_vector xdir; - ae_vector deltax; - ae_vector deltaf; - ae_bool deltaxready; - ae_bool deltafready; - smoothnessmonitor smonitor; - double teststep; - ae_vector lastscaleused; - ae_int_t repiterationscount; - ae_int_t repterminationtype; - ae_int_t repnfunc; - ae_int_t repnjac; - ae_int_t repngrad; - ae_int_t repnhess; - ae_int_t repncholesky; - rcommstate rstate; - ae_vector choleskybuf; - ae_vector tmp0; - double actualdecrease; - double predicteddecrease; - double xm1; - double xp1; - ae_vector fm1; - ae_vector fp1; - ae_vector fc1; - ae_vector gm1; - ae_vector gp1; - ae_vector gc1; - minlbfgsstate internalstate; - minlbfgsreport internalrep; - minqpstate qpstate; - minqpreport qprep; - minlmstepfinder finderstate; -} minlmstate; -typedef struct -{ - ae_int_t iterationscount; - ae_int_t terminationtype; - ae_int_t nfunc; - ae_int_t njac; - ae_int_t ngrad; - ae_int_t nhess; - ae_int_t ncholesky; -} minlmreport; -#endif - -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_CQMODELS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_OPTGUARDAPI) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This structure is used to store OptGuard report, i.e. report on the -properties of the nonlinear function being optimized with ALGLIB. - -After you tell your optimizer to activate OptGuard this technology starts -to silently monitor function values and gradients/Jacobians being passed -all around during your optimization session. Depending on specific set of -checks enabled OptGuard may perform additional function evaluations (say, -about 3*N evaluations if you want to check analytic gradient for errors). - -Upon discovering that something strange happens (function values and/or -gradient components change too sharply and/or unexpectedly) OptGuard sets -one of the "suspicion flags" (without interrupting optimization session). -After optimization is done, you can examine OptGuard report. - -Following report fields can be set: -* nonc0suspected -* nonc1suspected -* badgradsuspected - - -=== WHAT CAN BE DETECTED WITH OptGuard INTEGRITY CHECKER ================= - -Following types of errors in your target function (constraints) can be -caught: -a) discontinuous functions ("non-C0" part of the report) -b) functions with discontinuous derivative ("non-C1" part of the report) -c) errors in the analytic gradient provided by user - -These types of errors result in optimizer stopping well before reaching -solution (most often - right after encountering discontinuity). - -Type A errors are usually coding errors during implementation of the -target function. Most "normal" problems involve continuous functions, and -anyway you can't reliably optimize discontinuous function. - -Type B errors are either coding errors or (in case code itself is correct) -evidence of the fact that your problem is an "incorrect" one. Most -optimizers (except for ones provided by MINNS subpackage) do not support -nonsmooth problems. - -Type C errors are coding errors which often prevent optimizer from making -even one step or result in optimizing stopping too early, as soon as -actual descent direction becomes too different from one suggested by user- -supplied gradient. - - -=== WHAT IS REPORTED ===================================================== - -Following set of report fields deals with discontinuous target functions, -ones not belonging to C0 continuity class: - -* nonc0suspected - is a flag which is set upon discovering some indication - of the discontinuity. If this flag is false, the rest of "non-C0" fields - should be ignored -* nonc0fidx - is an index of the function (0 for target function, 1 or - higher for nonlinear constraints) which is suspected of being "non-C0" -* nonc0lipshitzc - a Lipchitz constant for a function which was suspected - of being non-continuous. -* nonc0test0positive - set to indicate specific test which detected - continuity violation (test #0) - -Following set of report fields deals with discontinuous gradient/Jacobian, -i.e. with functions violating C1 continuity: - -* nonc1suspected - is a flag which is set upon discovering some indication - of the discontinuity. If this flag is false, the rest of "non-C1" fields - should be ignored -* nonc1fidx - is an index of the function (0 for target function, 1 or - higher for nonlinear constraints) which is suspected of being "non-C1" -* nonc1lipshitzc - a Lipchitz constant for a function gradient which was - suspected of being non-smooth. -* nonc1test0positive - set to indicate specific test which detected - continuity violation (test #0) -* nonc1test1positive - set to indicate specific test which detected - continuity violation (test #1) - -Following set of report fields deals with errors in the gradient: -* badgradsuspected - is a flad which is set upon discovering an error in - the analytic gradient supplied by user -* badgradfidx - index of the function with bad gradient (0 for target - function, 1 or higher for nonlinear constraints) -* badgradvidx - index of the variable -* badgradxbase - location where Jacobian is tested -* following matrices store user-supplied Jacobian and its numerical - differentiation version (which is assumed to be free from the coding - errors), both of them computed near the initial point: - * badgraduser, an array[K,N], analytic Jacobian supplied by user - * badgradnum, an array[K,N], numeric Jacobian computed by ALGLIB - Here K is a total number of nonlinear functions (target + nonlinear - constraints), N is a variable number. - The element of badgraduser[] with index [badgradfidx,badgradvidx] is - assumed to be wrong. - -More detailed error log can be obtained from optimizer by explicitly -requesting reports for tests C0.0, C1.0, C1.1. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -class _optguardreport_owner -{ -public: - _optguardreport_owner(); - _optguardreport_owner(const _optguardreport_owner &rhs); - _optguardreport_owner& operator=(const _optguardreport_owner &rhs); - virtual ~_optguardreport_owner(); - alglib_impl::optguardreport* c_ptr(); - alglib_impl::optguardreport* c_ptr() const; -protected: - alglib_impl::optguardreport *p_struct; -}; -class optguardreport : public _optguardreport_owner -{ -public: - optguardreport(); - optguardreport(const optguardreport &rhs); - optguardreport& operator=(const optguardreport &rhs); - virtual ~optguardreport(); - ae_bool &nonc0suspected; - ae_bool &nonc0test0positive; - ae_int_t &nonc0fidx; - double &nonc0lipschitzc; - ae_bool &nonc1suspected; - ae_bool &nonc1test0positive; - ae_bool &nonc1test1positive; - ae_int_t &nonc1fidx; - double &nonc1lipschitzc; - ae_bool &badgradsuspected; - ae_int_t &badgradfidx; - ae_int_t &badgradvidx; - real_1d_array badgradxbase; - real_2d_array badgraduser; - real_2d_array badgradnum; - -}; - - -/************************************************************************* -This structure is used for detailed reporting about suspected C0 -continuity violation. - -=== WHAT IS TESTED ======================================================= - -C0 test studies function values (not gradient!) obtained during line -searches and monitors estimate of the Lipschitz constant. Sudden spikes -usually indicate that discontinuity was detected. - - -=== WHAT IS REPORTED ===================================================== - -Actually, report retrieval function returns TWO report structures: - -* one for most suspicious point found so far (one with highest change in - the function value), so called "strongest" report -* another one for most detailed line search (more function evaluations = - easier to understand what's going on) which triggered test #0 criteria, - so called "longest" report - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* fidx - is an index of the function (0 for target function, 1 or higher - for nonlinear constraints) which is suspected of being "non-C1" -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -You can plot function values stored in stp[] and f[] arrays and study -behavior of your function by your own eyes, just to be sure that test -correctly reported C1 violation. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -class _optguardnonc0report_owner -{ -public: - _optguardnonc0report_owner(); - _optguardnonc0report_owner(const _optguardnonc0report_owner &rhs); - _optguardnonc0report_owner& operator=(const _optguardnonc0report_owner &rhs); - virtual ~_optguardnonc0report_owner(); - alglib_impl::optguardnonc0report* c_ptr(); - alglib_impl::optguardnonc0report* c_ptr() const; -protected: - alglib_impl::optguardnonc0report *p_struct; -}; -class optguardnonc0report : public _optguardnonc0report_owner -{ -public: - optguardnonc0report(); - optguardnonc0report(const optguardnonc0report &rhs); - optguardnonc0report& operator=(const optguardnonc0report &rhs); - virtual ~optguardnonc0report(); - ae_bool &positive; - ae_int_t &fidx; - real_1d_array x0; - real_1d_array d; - ae_int_t &n; - real_1d_array stp; - real_1d_array f; - ae_int_t &cnt; - ae_int_t &stpidxa; - ae_int_t &stpidxb; - -}; - - -/************************************************************************* -This structure is used for detailed reporting about suspected C1 -continuity violation as flagged by C1 test #0 (OptGuard has several tests -for C1 continuity, this report is used by #0). - -=== WHAT IS TESTED ======================================================= - -C1 test #0 studies function values (not gradient!) obtained during line -searches and monitors behavior of directional derivative estimate. This -test is less powerful than test #1, but it does not depend on gradient -values and thus it is more robust against artifacts introduced by -numerical differentiation. - - -=== WHAT IS REPORTED ===================================================== - -Actually, report retrieval function returns TWO report structures: - -* one for most suspicious point found so far (one with highest change in - the directional derivative), so called "strongest" report -* another one for most detailed line search (more function evaluations = - easier to understand what's going on) which triggered test #0 criteria, - so called "longest" report - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* fidx - is an index of the function (0 for target function, 1 or higher - for nonlinear constraints) which is suspected of being "non-C1" -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -You can plot function values stored in stp[] and f[] arrays and study -behavior of your function by your own eyes, just to be sure that test -correctly reported C1 violation. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -class _optguardnonc1test0report_owner -{ -public: - _optguardnonc1test0report_owner(); - _optguardnonc1test0report_owner(const _optguardnonc1test0report_owner &rhs); - _optguardnonc1test0report_owner& operator=(const _optguardnonc1test0report_owner &rhs); - virtual ~_optguardnonc1test0report_owner(); - alglib_impl::optguardnonc1test0report* c_ptr(); - alglib_impl::optguardnonc1test0report* c_ptr() const; -protected: - alglib_impl::optguardnonc1test0report *p_struct; -}; -class optguardnonc1test0report : public _optguardnonc1test0report_owner -{ -public: - optguardnonc1test0report(); - optguardnonc1test0report(const optguardnonc1test0report &rhs); - optguardnonc1test0report& operator=(const optguardnonc1test0report &rhs); - virtual ~optguardnonc1test0report(); - ae_bool &positive; - ae_int_t &fidx; - real_1d_array x0; - real_1d_array d; - ae_int_t &n; - real_1d_array stp; - real_1d_array f; - ae_int_t &cnt; - ae_int_t &stpidxa; - ae_int_t &stpidxb; - -}; - - -/************************************************************************* -This structure is used for detailed reporting about suspected C1 -continuity violation as flagged by C1 test #1 (OptGuard has several tests -for C1 continuity, this report is used by #1). - -=== WHAT IS TESTED ======================================================= - -C1 test #1 studies individual components of the gradient as recorded -during line searches. Upon discovering discontinuity in the gradient this -test records specific component which was suspected (or one with highest -indication of discontinuity if multiple components are suspected). - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - - -=== WHAT IS REPORTED ===================================================== - -Actually, report retrieval function returns TWO report structures: - -* one for most suspicious point found so far (one with highest change in - the directional derivative), so called "strongest" report -* another one for most detailed line search (more function evaluations = - easier to understand what's going on) which triggered test #1 criteria, - so called "longest" report - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* fidx - is an index of the function (0 for target function, 1 or higher - for nonlinear constraints) which is suspected of being "non-C1" -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -You can plot function values stored in stp[] and g[] arrays and study -behavior of your function by your own eyes, just to be sure that test -correctly reported C1 violation. - - -- ALGLIB -- - Copyright 19.11.2018 by Bochkanov Sergey -*************************************************************************/ -class _optguardnonc1test1report_owner -{ -public: - _optguardnonc1test1report_owner(); - _optguardnonc1test1report_owner(const _optguardnonc1test1report_owner &rhs); - _optguardnonc1test1report_owner& operator=(const _optguardnonc1test1report_owner &rhs); - virtual ~_optguardnonc1test1report_owner(); - alglib_impl::optguardnonc1test1report* c_ptr(); - alglib_impl::optguardnonc1test1report* c_ptr() const; -protected: - alglib_impl::optguardnonc1test1report *p_struct; -}; -class optguardnonc1test1report : public _optguardnonc1test1report_owner -{ -public: - optguardnonc1test1report(); - optguardnonc1test1report(const optguardnonc1test1report &rhs); - optguardnonc1test1report& operator=(const optguardnonc1test1report &rhs); - virtual ~optguardnonc1test1report(); - ae_bool &positive; - ae_int_t &fidx; - ae_int_t &vidx; - real_1d_array x0; - real_1d_array d; - ae_int_t &n; - real_1d_array stp; - real_1d_array g; - ae_int_t &cnt; - ae_int_t &stpidxa; - ae_int_t &stpidxb; - -}; -#endif - -#if defined(AE_COMPILE_OPTSERV) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SNNLS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SACTIVESETS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_QQPSOLVER) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINLBFGS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - -*************************************************************************/ -class _minlbfgsstate_owner -{ -public: - _minlbfgsstate_owner(); - _minlbfgsstate_owner(const _minlbfgsstate_owner &rhs); - _minlbfgsstate_owner& operator=(const _minlbfgsstate_owner &rhs); - virtual ~_minlbfgsstate_owner(); - alglib_impl::minlbfgsstate* c_ptr(); - alglib_impl::minlbfgsstate* c_ptr() const; -protected: - alglib_impl::minlbfgsstate *p_struct; -}; -class minlbfgsstate : public _minlbfgsstate_owner -{ -public: - minlbfgsstate(); - minlbfgsstate(const minlbfgsstate &rhs); - minlbfgsstate& operator=(const minlbfgsstate &rhs); - virtual ~minlbfgsstate(); - ae_bool &needf; - ae_bool &needfg; - ae_bool &xupdated; - double &f; - real_1d_array g; - real_1d_array x; - -}; - - -/************************************************************************* -This structure stores optimization report: -* IterationsCount total number of inner iterations -* NFEV number of gradient evaluations -* TerminationType termination type (see below) - -TERMINATION CODES - -TerminationType field contains completion code, which can be: - -8 internal integrity control detected infinite or NAN values in - function/gradient. Abnormal termination signalled. - 1 relative function improvement is no more than EpsF. - 2 relative step is no more than EpsX. - 4 gradient norm is no more than EpsG - 5 MaxIts steps was taken - 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - 8 terminated by user who called minlbfgsrequesttermination(). - X contains point which was "current accepted" when termination - request was submitted. - -Other fields of this structure are not documented and should not be used! -*************************************************************************/ -class _minlbfgsreport_owner -{ -public: - _minlbfgsreport_owner(); - _minlbfgsreport_owner(const _minlbfgsreport_owner &rhs); - _minlbfgsreport_owner& operator=(const _minlbfgsreport_owner &rhs); - virtual ~_minlbfgsreport_owner(); - alglib_impl::minlbfgsreport* c_ptr(); - alglib_impl::minlbfgsreport* c_ptr() const; -protected: - alglib_impl::minlbfgsreport *p_struct; -}; -class minlbfgsreport : public _minlbfgsreport_owner -{ -public: - minlbfgsreport(); - minlbfgsreport(const minlbfgsreport &rhs); - minlbfgsreport& operator=(const minlbfgsreport &rhs); - virtual ~minlbfgsreport(); - ae_int_t &iterationscount; - ae_int_t &nfev; - ae_int_t &terminationtype; - -}; -#endif - -#if defined(AE_COMPILE_LPQPSERV) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_VIPMSOLVER) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_NLCSQP) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_QPDENSEAULSOLVER) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINBLEIC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores nonlinear optimizer state. -You should use functions provided by MinBLEIC subpackage to work with this -object -*************************************************************************/ -class _minbleicstate_owner -{ -public: - _minbleicstate_owner(); - _minbleicstate_owner(const _minbleicstate_owner &rhs); - _minbleicstate_owner& operator=(const _minbleicstate_owner &rhs); - virtual ~_minbleicstate_owner(); - alglib_impl::minbleicstate* c_ptr(); - alglib_impl::minbleicstate* c_ptr() const; -protected: - alglib_impl::minbleicstate *p_struct; -}; -class minbleicstate : public _minbleicstate_owner -{ -public: - minbleicstate(); - minbleicstate(const minbleicstate &rhs); - minbleicstate& operator=(const minbleicstate &rhs); - virtual ~minbleicstate(); - ae_bool &needf; - ae_bool &needfg; - ae_bool &xupdated; - double &f; - real_1d_array g; - real_1d_array x; - -}; - - -/************************************************************************* -This structure stores optimization report: -* IterationsCount number of iterations -* NFEV number of gradient evaluations -* TerminationType termination type (see below) - -TERMINATION CODES - -TerminationType field contains completion code, which can be: - -8 internal integrity control detected infinite or NAN values in - function/gradient. Abnormal termination signalled. - -3 inconsistent constraints. Feasible point is - either nonexistent or too hard to find. Try to - restart optimizer with better initial approximation - 1 relative function improvement is no more than EpsF. - 2 relative step is no more than EpsX. - 4 gradient norm is no more than EpsG - 5 MaxIts steps was taken - 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - 8 terminated by user who called minbleicrequesttermination(). X contains - point which was "current accepted" when termination request was - submitted. - -ADDITIONAL FIELDS - -There are additional fields which can be used for debugging: -* DebugEqErr error in the equality constraints (2-norm) -* DebugFS f, calculated at projection of initial point - to the feasible set -* DebugFF f, calculated at the final point -* DebugDX |X_start-X_final| -*************************************************************************/ -class _minbleicreport_owner -{ -public: - _minbleicreport_owner(); - _minbleicreport_owner(const _minbleicreport_owner &rhs); - _minbleicreport_owner& operator=(const _minbleicreport_owner &rhs); - virtual ~_minbleicreport_owner(); - alglib_impl::minbleicreport* c_ptr(); - alglib_impl::minbleicreport* c_ptr() const; -protected: - alglib_impl::minbleicreport *p_struct; -}; -class minbleicreport : public _minbleicreport_owner -{ -public: - minbleicreport(); - minbleicreport(const minbleicreport &rhs); - minbleicreport& operator=(const minbleicreport &rhs); - virtual ~minbleicreport(); - ae_int_t &iterationscount; - ae_int_t &nfev; - ae_int_t &varidx; - ae_int_t &terminationtype; - double &debugeqerr; - double &debugfs; - double &debugff; - double &debugdx; - ae_int_t &debugfeasqpits; - ae_int_t &debugfeasgpaits; - ae_int_t &inneriterationscount; - ae_int_t &outeriterationscount; - -}; -#endif - -#if defined(AE_COMPILE_QPBLEICSOLVER) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINQP) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores nonlinear optimizer state. -You should use functions provided by MinQP subpackage to work with this -object -*************************************************************************/ -class _minqpstate_owner -{ -public: - _minqpstate_owner(); - _minqpstate_owner(const _minqpstate_owner &rhs); - _minqpstate_owner& operator=(const _minqpstate_owner &rhs); - virtual ~_minqpstate_owner(); - alglib_impl::minqpstate* c_ptr(); - alglib_impl::minqpstate* c_ptr() const; -protected: - alglib_impl::minqpstate *p_struct; -}; -class minqpstate : public _minqpstate_owner -{ -public: - minqpstate(); - minqpstate(const minqpstate &rhs); - minqpstate& operator=(const minqpstate &rhs); - virtual ~minqpstate(); - -}; - - -/************************************************************************* -This structure stores optimization report: -* InnerIterationsCount number of inner iterations -* OuterIterationsCount number of outer iterations -* NCholesky number of Cholesky decomposition -* NMV number of matrix-vector products - (only products calculated as part of iterative - process are counted) -* TerminationType completion code (see below) -* LagBC Lagrange multipliers for box constraints, - array[N], not filled by QP-BLEIC solver -* LagLC Lagrange multipliers for linear constraints, - array[MSparse+MDense], ignored by QP-BLEIC solver - -=== COMPLETION CODES ===================================================== - -Completion codes: -* -9 failure of the automatic scale evaluation: one of the diagonal - elements of the quadratic term is non-positive. Specify variable - scales manually! -* -5 inappropriate solver was used: - * QuickQP solver for problem with general linear constraints (dense/sparse) -* -4 BLEIC-QP or QuickQP solver found unconstrained direction - of negative curvature (function is unbounded from - below even under constraints), no meaningful - minimum can be found. -* -3 inconsistent constraints (or, maybe, feasible point is - too hard to find). If you are sure that constraints are feasible, - try to restart optimizer with better initial approximation. -* -2 IPM solver has difficulty finding primal/dual feasible point. - It is likely that the problem is either infeasible or unbounded, - but it is difficult to determine exact reason for termination. - X contains best point found so far. -* 1..4 successful completion -* 5 MaxIts steps was taken -* 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - -=== LAGRANGE MULTIPLIERS ================================================= - -Some optimizers report values of Lagrange multipliers on successful -completion (positive completion code): -* DENSE-IPM-QP and SPARSE-IPM-QP return very precise Lagrange multipliers - as determined during solution process. -* DENSE-AUL-QP returns approximate Lagrange multipliers (which are very - close to "true" Lagrange multipliers except for overconstrained or - degenerate problems) - -Two arrays of multipliers are returned: -* LagBC is array[N] which is loaded with multipliers from box constraints; - LagBC[i]>0 means that I-th constraint is at the upper bound, LagBC[I]<0 - means that I-th constraint is at the lower bound, LagBC[I]=0 means that - I-th box constraint is inactive. -* LagLC is array[MSparse+MDense] which is loaded with multipliers from - general linear constraints (former MSparse elements corresponds to - sparse part of the constraint matrix, latter MDense are for the dense - constraints, as was specified by user). - LagLC[i]>0 means that I-th constraint at the upper bound, LagLC[i]<0 - means that I-th constraint is at the lower bound, LagLC[i]=0 means that - I-th linear constraint is inactive. - -On failure (or when optimizer does not support Lagrange multipliers) these -arrays are zero-filled. - -It is expected that at solution the dual feasibility condition holds: - - C+H*(Xs-X0) + SUM(Ei*LagBC[i],i=0..n-1) + SUM(Ai*LagLC[i],i=0..m-1) ~ 0 - -where -* C is a linear term -* H is a quadratic term -* Xs is a solution, and X0 is an origin term (zero by default) -* Ei is a vector with 1.0 at position I and 0 in other positions -* Ai is an I-th row of linear constraint matrix - -NOTE: methods from IPM family may also return meaningful Lagrange - multipliers on completion with code -2 (infeasibility or - unboundedness detected). -*************************************************************************/ -class _minqpreport_owner -{ -public: - _minqpreport_owner(); - _minqpreport_owner(const _minqpreport_owner &rhs); - _minqpreport_owner& operator=(const _minqpreport_owner &rhs); - virtual ~_minqpreport_owner(); - alglib_impl::minqpreport* c_ptr(); - alglib_impl::minqpreport* c_ptr() const; -protected: - alglib_impl::minqpreport *p_struct; -}; -class minqpreport : public _minqpreport_owner -{ -public: - minqpreport(); - minqpreport(const minqpreport &rhs); - minqpreport& operator=(const minqpreport &rhs); - virtual ~minqpreport(); - ae_int_t &inneriterationscount; - ae_int_t &outeriterationscount; - ae_int_t &nmv; - ae_int_t &ncholesky; - ae_int_t &terminationtype; - real_1d_array lagbc; - real_1d_array laglc; - -}; -#endif - -#if defined(AE_COMPILE_LPQPPRESOLVE) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_REVISEDDUALSIMPLEX) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINLP) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores linear solver state. -You should use functions provided by MinLP subpackage to work with this -object -*************************************************************************/ -class _minlpstate_owner -{ -public: - _minlpstate_owner(); - _minlpstate_owner(const _minlpstate_owner &rhs); - _minlpstate_owner& operator=(const _minlpstate_owner &rhs); - virtual ~_minlpstate_owner(); - alglib_impl::minlpstate* c_ptr(); - alglib_impl::minlpstate* c_ptr() const; -protected: - alglib_impl::minlpstate *p_struct; -}; -class minlpstate : public _minlpstate_owner -{ -public: - minlpstate(); - minlpstate(const minlpstate &rhs); - minlpstate& operator=(const minlpstate &rhs); - virtual ~minlpstate(); - -}; - - -/************************************************************************* -This structure stores optimization report: -* f target function value -* lagbc Lagrange coefficients for box constraints -* laglc Lagrange coefficients for linear constraints -* y dual variables -* stats array[N+M], statuses of box (N) and linear (M) - constraints. This array is filled only by DSS - algorithm because IPM always stops at INTERIOR - point: - * stats[i]>0 => constraint at upper bound - (also used for free non-basic - variables set to zero) - * stats[i]<0 => constraint at lower bound - * stats[i]=0 => constraint is inactive, basic - variable -* primalerror primal feasibility error -* dualerror dual feasibility error -* slackerror complementary slackness error -* iterationscount iteration count -* terminationtype completion code (see below) - -COMPLETION CODES - -Completion codes: -* -4 LP problem is primal unbounded (dual infeasible) -* -3 LP problem is primal infeasible (dual unbounded) -* 1..4 successful completion -* 5 MaxIts steps was taken -* 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - -LAGRANGE COEFFICIENTS - -Positive Lagrange coefficient means that constraint is at its upper bound. -Negative coefficient means that constraint is at its lower bound. It is -expected that at solution the dual feasibility condition holds: - - C + SUM(Ei*LagBC[i],i=0..n-1) + SUM(Ai*LagLC[i],i=0..m-1) ~ 0 - -where -* C is a cost vector (linear term) -* Ei is a vector with 1.0 at position I and 0 in other positions -* Ai is an I-th row of linear constraint matrix -*************************************************************************/ -class _minlpreport_owner -{ -public: - _minlpreport_owner(); - _minlpreport_owner(const _minlpreport_owner &rhs); - _minlpreport_owner& operator=(const _minlpreport_owner &rhs); - virtual ~_minlpreport_owner(); - alglib_impl::minlpreport* c_ptr(); - alglib_impl::minlpreport* c_ptr() const; -protected: - alglib_impl::minlpreport *p_struct; -}; -class minlpreport : public _minlpreport_owner -{ -public: - minlpreport(); - minlpreport(const minlpreport &rhs); - minlpreport& operator=(const minlpreport &rhs); - virtual ~minlpreport(); - double &f; - real_1d_array lagbc; - real_1d_array laglc; - real_1d_array y; - integer_1d_array stats; - double &primalerror; - double &dualerror; - double &slackerror; - ae_int_t &iterationscount; - ae_int_t &terminationtype; - -}; -#endif - -#if defined(AE_COMPILE_NLCSLP) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINNLC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores nonlinear optimizer state. -You should use functions provided by MinNLC subpackage to work with this -object -*************************************************************************/ -class _minnlcstate_owner -{ -public: - _minnlcstate_owner(); - _minnlcstate_owner(const _minnlcstate_owner &rhs); - _minnlcstate_owner& operator=(const _minnlcstate_owner &rhs); - virtual ~_minnlcstate_owner(); - alglib_impl::minnlcstate* c_ptr(); - alglib_impl::minnlcstate* c_ptr() const; -protected: - alglib_impl::minnlcstate *p_struct; -}; -class minnlcstate : public _minnlcstate_owner -{ -public: - minnlcstate(); - minnlcstate(const minnlcstate &rhs); - minnlcstate& operator=(const minnlcstate &rhs); - virtual ~minnlcstate(); - ae_bool &needfi; - ae_bool &needfij; - ae_bool &xupdated; - double &f; - real_1d_array fi; - real_2d_array j; - real_1d_array x; - -}; - - -/************************************************************************* -These fields store optimization report: -* iterationscount total number of inner iterations -* nfev number of gradient evaluations -* terminationtype termination type (see below) - -Scaled constraint violations are reported: -* bcerr maximum violation of the box constraints -* bcidx index of the most violated box constraint (or - -1, if all box constraints are satisfied or - there is no box constraint) -* lcerr maximum violation of the linear constraints, - computed as maximum scaled distance between - final point and constraint boundary. -* lcidx index of the most violated linear constraint - (or -1, if all constraints are satisfied or - there is no general linear constraints) -* nlcerr maximum violation of the nonlinear constraints -* nlcidx index of the most violated nonlinear constraint - (or -1, if all constraints are satisfied or - there is no nonlinear constraints) - -Violations of box constraints are scaled on per-component basis according -to the scale vector s[] as specified by minnlcsetscale(). Violations of -the general linear constraints are also computed using user-supplied -variable scaling. Violations of nonlinear constraints are computed "as is" - -TERMINATION CODES - -TerminationType field contains completion code, which can be either: - -=== FAILURE CODE === - -8 internal integrity control detected infinite or NAN values in - function/gradient. Abnormal termination signaled. - -3 box constraints are infeasible. Note: infeasibility of non-box - constraints does NOT trigger emergency completion; you have to - examine bcerr/lcerr/nlcerr to detect possibly inconsistent - constraints. - -=== SUCCESS CODE === - 2 relative step is no more than EpsX. - 5 MaxIts steps was taken - 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - 8 user requested algorithm termination via minnlcrequesttermination(), - last accepted point is returned - -Other fields of this structure are not documented and should not be used! -*************************************************************************/ -class _minnlcreport_owner -{ -public: - _minnlcreport_owner(); - _minnlcreport_owner(const _minnlcreport_owner &rhs); - _minnlcreport_owner& operator=(const _minnlcreport_owner &rhs); - virtual ~_minnlcreport_owner(); - alglib_impl::minnlcreport* c_ptr(); - alglib_impl::minnlcreport* c_ptr() const; -protected: - alglib_impl::minnlcreport *p_struct; -}; -class minnlcreport : public _minnlcreport_owner -{ -public: - minnlcreport(); - minnlcreport(const minnlcreport &rhs); - minnlcreport& operator=(const minnlcreport &rhs); - virtual ~minnlcreport(); - ae_int_t &iterationscount; - ae_int_t &nfev; - ae_int_t &terminationtype; - double &bcerr; - ae_int_t &bcidx; - double &lcerr; - ae_int_t &lcidx; - double &nlcerr; - ae_int_t &nlcidx; - ae_int_t &dbgphase0its; - -}; -#endif - -#if defined(AE_COMPILE_MINBC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores nonlinear optimizer state. -You should use functions provided by MinBC subpackage to work with this -object -*************************************************************************/ -class _minbcstate_owner -{ -public: - _minbcstate_owner(); - _minbcstate_owner(const _minbcstate_owner &rhs); - _minbcstate_owner& operator=(const _minbcstate_owner &rhs); - virtual ~_minbcstate_owner(); - alglib_impl::minbcstate* c_ptr(); - alglib_impl::minbcstate* c_ptr() const; -protected: - alglib_impl::minbcstate *p_struct; -}; -class minbcstate : public _minbcstate_owner -{ -public: - minbcstate(); - minbcstate(const minbcstate &rhs); - minbcstate& operator=(const minbcstate &rhs); - virtual ~minbcstate(); - ae_bool &needf; - ae_bool &needfg; - ae_bool &xupdated; - double &f; - real_1d_array g; - real_1d_array x; - -}; - - -/************************************************************************* -This structure stores optimization report: -* iterationscount number of iterations -* nfev number of gradient evaluations -* terminationtype termination type (see below) - -TERMINATION CODES - -terminationtype field contains completion code, which can be: - -8 internal integrity control detected infinite or NAN values in - function/gradient. Abnormal termination signalled. - -3 inconsistent constraints. - 1 relative function improvement is no more than EpsF. - 2 relative step is no more than EpsX. - 4 gradient norm is no more than EpsG - 5 MaxIts steps was taken - 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - 8 terminated by user who called minbcrequesttermination(). X contains - point which was "current accepted" when termination request was - submitted. -*************************************************************************/ -class _minbcreport_owner -{ -public: - _minbcreport_owner(); - _minbcreport_owner(const _minbcreport_owner &rhs); - _minbcreport_owner& operator=(const _minbcreport_owner &rhs); - virtual ~_minbcreport_owner(); - alglib_impl::minbcreport* c_ptr(); - alglib_impl::minbcreport* c_ptr() const; -protected: - alglib_impl::minbcreport *p_struct; -}; -class minbcreport : public _minbcreport_owner -{ -public: - minbcreport(); - minbcreport(const minbcreport &rhs); - minbcreport& operator=(const minbcreport &rhs); - virtual ~minbcreport(); - ae_int_t &iterationscount; - ae_int_t &nfev; - ae_int_t &varidx; - ae_int_t &terminationtype; - -}; -#endif - -#if defined(AE_COMPILE_MINNS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores nonlinear optimizer state. -You should use functions provided by MinNS subpackage to work with this -object -*************************************************************************/ -class _minnsstate_owner -{ -public: - _minnsstate_owner(); - _minnsstate_owner(const _minnsstate_owner &rhs); - _minnsstate_owner& operator=(const _minnsstate_owner &rhs); - virtual ~_minnsstate_owner(); - alglib_impl::minnsstate* c_ptr(); - alglib_impl::minnsstate* c_ptr() const; -protected: - alglib_impl::minnsstate *p_struct; -}; -class minnsstate : public _minnsstate_owner -{ -public: - minnsstate(); - minnsstate(const minnsstate &rhs); - minnsstate& operator=(const minnsstate &rhs); - virtual ~minnsstate(); - ae_bool &needfi; - ae_bool &needfij; - ae_bool &xupdated; - double &f; - real_1d_array fi; - real_2d_array j; - real_1d_array x; - -}; - - -/************************************************************************* -This structure stores optimization report: -* IterationsCount total number of inner iterations -* NFEV number of gradient evaluations -* TerminationType termination type (see below) -* CErr maximum violation of all types of constraints -* LCErr maximum violation of linear constraints -* NLCErr maximum violation of nonlinear constraints - -TERMINATION CODES - -TerminationType field contains completion code, which can be: - -8 internal integrity control detected infinite or NAN values in - function/gradient. Abnormal termination signalled. - -3 box constraints are inconsistent - -1 inconsistent parameters were passed: - * penalty parameter for minnssetalgoags() is zero, - but we have nonlinear constraints set by minnssetnlc() - 2 sampling radius decreased below epsx - 5 MaxIts steps was taken - 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - 8 User requested termination via MinNSRequestTermination() - -Other fields of this structure are not documented and should not be used! -*************************************************************************/ -class _minnsreport_owner -{ -public: - _minnsreport_owner(); - _minnsreport_owner(const _minnsreport_owner &rhs); - _minnsreport_owner& operator=(const _minnsreport_owner &rhs); - virtual ~_minnsreport_owner(); - alglib_impl::minnsreport* c_ptr(); - alglib_impl::minnsreport* c_ptr() const; -protected: - alglib_impl::minnsreport *p_struct; -}; -class minnsreport : public _minnsreport_owner -{ -public: - minnsreport(); - minnsreport(const minnsreport &rhs); - minnsreport& operator=(const minnsreport &rhs); - virtual ~minnsreport(); - ae_int_t &iterationscount; - ae_int_t &nfev; - double &cerr; - double &lcerr; - double &nlcerr; - ae_int_t &terminationtype; - ae_int_t &varidx; - ae_int_t &funcidx; - -}; -#endif - -#if defined(AE_COMPILE_MINCOMP) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - -*************************************************************************/ -class _minasastate_owner -{ -public: - _minasastate_owner(); - _minasastate_owner(const _minasastate_owner &rhs); - _minasastate_owner& operator=(const _minasastate_owner &rhs); - virtual ~_minasastate_owner(); - alglib_impl::minasastate* c_ptr(); - alglib_impl::minasastate* c_ptr() const; -protected: - alglib_impl::minasastate *p_struct; -}; -class minasastate : public _minasastate_owner -{ -public: - minasastate(); - minasastate(const minasastate &rhs); - minasastate& operator=(const minasastate &rhs); - virtual ~minasastate(); - ae_bool &needfg; - ae_bool &xupdated; - double &f; - real_1d_array g; - real_1d_array x; - -}; - - -/************************************************************************* - -*************************************************************************/ -class _minasareport_owner -{ -public: - _minasareport_owner(); - _minasareport_owner(const _minasareport_owner &rhs); - _minasareport_owner& operator=(const _minasareport_owner &rhs); - virtual ~_minasareport_owner(); - alglib_impl::minasareport* c_ptr(); - alglib_impl::minasareport* c_ptr() const; -protected: - alglib_impl::minasareport *p_struct; -}; -class minasareport : public _minasareport_owner -{ -public: - minasareport(); - minasareport(const minasareport &rhs); - minasareport& operator=(const minasareport &rhs); - virtual ~minasareport(); - ae_int_t &iterationscount; - ae_int_t &nfev; - ae_int_t &terminationtype; - ae_int_t &activeconstraints; - -}; -#endif - -#if defined(AE_COMPILE_MINCG) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores state of the nonlinear CG optimizer. - -You should use ALGLIB functions to work with this object. -*************************************************************************/ -class _mincgstate_owner -{ -public: - _mincgstate_owner(); - _mincgstate_owner(const _mincgstate_owner &rhs); - _mincgstate_owner& operator=(const _mincgstate_owner &rhs); - virtual ~_mincgstate_owner(); - alglib_impl::mincgstate* c_ptr(); - alglib_impl::mincgstate* c_ptr() const; -protected: - alglib_impl::mincgstate *p_struct; -}; -class mincgstate : public _mincgstate_owner -{ -public: - mincgstate(); - mincgstate(const mincgstate &rhs); - mincgstate& operator=(const mincgstate &rhs); - virtual ~mincgstate(); - ae_bool &needf; - ae_bool &needfg; - ae_bool &xupdated; - double &f; - real_1d_array g; - real_1d_array x; - -}; - - -/************************************************************************* -This structure stores optimization report: -* IterationsCount total number of inner iterations -* NFEV number of gradient evaluations -* TerminationType termination type (see below) - -TERMINATION CODES - -TerminationType field contains completion code, which can be: - -8 internal integrity control detected infinite or NAN values in - function/gradient. Abnormal termination signalled. - 1 relative function improvement is no more than EpsF. - 2 relative step is no more than EpsX. - 4 gradient norm is no more than EpsG - 5 MaxIts steps was taken - 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - 8 terminated by user who called mincgrequesttermination(). X contains - point which was "current accepted" when termination request was - submitted. - -Other fields of this structure are not documented and should not be used! -*************************************************************************/ -class _mincgreport_owner -{ -public: - _mincgreport_owner(); - _mincgreport_owner(const _mincgreport_owner &rhs); - _mincgreport_owner& operator=(const _mincgreport_owner &rhs); - virtual ~_mincgreport_owner(); - alglib_impl::mincgreport* c_ptr(); - alglib_impl::mincgreport* c_ptr() const; -protected: - alglib_impl::mincgreport *p_struct; -}; -class mincgreport : public _mincgreport_owner -{ -public: - mincgreport(); - mincgreport(const mincgreport &rhs); - mincgreport& operator=(const mincgreport &rhs); - virtual ~mincgreport(); - ae_int_t &iterationscount; - ae_int_t &nfev; - ae_int_t &terminationtype; - -}; -#endif - -#if defined(AE_COMPILE_MINLM) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Levenberg-Marquardt optimizer. - -This structure should be created using one of the MinLMCreate???() -functions. You should not access its fields directly; use ALGLIB functions -to work with it. -*************************************************************************/ -class _minlmstate_owner -{ -public: - _minlmstate_owner(); - _minlmstate_owner(const _minlmstate_owner &rhs); - _minlmstate_owner& operator=(const _minlmstate_owner &rhs); - virtual ~_minlmstate_owner(); - alglib_impl::minlmstate* c_ptr(); - alglib_impl::minlmstate* c_ptr() const; -protected: - alglib_impl::minlmstate *p_struct; -}; -class minlmstate : public _minlmstate_owner -{ -public: - minlmstate(); - minlmstate(const minlmstate &rhs); - minlmstate& operator=(const minlmstate &rhs); - virtual ~minlmstate(); - ae_bool &needf; - ae_bool &needfg; - ae_bool &needfgh; - ae_bool &needfi; - ae_bool &needfij; - ae_bool &xupdated; - double &f; - real_1d_array fi; - real_1d_array g; - real_2d_array h; - real_2d_array j; - real_1d_array x; - -}; - - -/************************************************************************* -Optimization report, filled by MinLMResults() function - -FIELDS: -* TerminationType, completetion code: - * -8 optimizer detected NAN/INF values either in the function itself, - or in its Jacobian - * -5 inappropriate solver was used: - * solver created with minlmcreatefgh() used on problem with - general linear constraints (set with minlmsetlc() call). - * -3 constraints are inconsistent - * 2 relative step is no more than EpsX. - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible - * 8 terminated by user who called MinLMRequestTermination(). - X contains point which was "current accepted" when termination - request was submitted. -* IterationsCount, contains iterations count -* NFunc, number of function calculations -* NJac, number of Jacobi matrix calculations -* NGrad, number of gradient calculations -* NHess, number of Hessian calculations -* NCholesky, number of Cholesky decomposition calculations -*************************************************************************/ -class _minlmreport_owner -{ -public: - _minlmreport_owner(); - _minlmreport_owner(const _minlmreport_owner &rhs); - _minlmreport_owner& operator=(const _minlmreport_owner &rhs); - virtual ~_minlmreport_owner(); - alglib_impl::minlmreport* c_ptr(); - alglib_impl::minlmreport* c_ptr() const; -protected: - alglib_impl::minlmreport *p_struct; -}; -class minlmreport : public _minlmreport_owner -{ -public: - minlmreport(); - minlmreport(const minlmreport &rhs); - minlmreport& operator=(const minlmreport &rhs); - virtual ~minlmreport(); - ae_int_t &iterationscount; - ae_int_t &terminationtype; - ae_int_t &nfunc; - ae_int_t &njac; - ae_int_t &ngrad; - ae_int_t &nhess; - ae_int_t &ncholesky; - -}; -#endif - -#if defined(AE_COMPILE_CQMODELS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_OPTGUARDAPI) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_OPTSERV) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SNNLS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_SACTIVESETS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_QQPSOLVER) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINLBFGS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - LIMITED MEMORY BFGS METHOD FOR LARGE SCALE OPTIMIZATION - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments by using a quasi- -Newton method (LBFGS scheme) which is optimized to use a minimum amount -of memory. -The subroutine generates the approximation of an inverse Hessian matrix by -using information about the last M steps of the algorithm (instead of N). -It lessens a required amount of memory from a value of order N^2 to a -value of order 2*N*M. - - -REQUIREMENTS: -Algorithm will request following information during its operation: -* function value F and its gradient G (simultaneously) at given point X - - -USAGE: -1. User initializes algorithm state with MinLBFGSCreate() call -2. User tunes solver parameters with MinLBFGSSetCond() MinLBFGSSetStpMax() - and other functions -3. User calls MinLBFGSOptimize() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. -4. User calls MinLBFGSResults() to get solution -5. Optionally user may call MinLBFGSRestartFrom() to solve another problem - with same N/M but another starting point and/or another function. - MinLBFGSRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension. N>0 - M - number of corrections in the BFGS scheme of Hessian - approximation update. Recommended value: 3<=M<=7. The smaller - value causes worse convergence, the bigger will not cause a - considerably better convergence, but will cause a fall in the - performance. M<=N. - X - initial solution approximation, array[0..N-1]. - - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -NOTES: -1. you may tune stopping conditions with MinLBFGSSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use MinLBFGSSetStpMax() function to bound algorithm's steps. However, - L-BFGS rarely needs such a tuning. - - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgscreate(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlbfgsstate &state, const xparams _xparams = alglib::xdefault); -void minlbfgscreate(const ae_int_t m, const real_1d_array &x, minlbfgsstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -The subroutine is finite difference variant of MinLBFGSCreate(). It uses -finite differences in order to differentiate target function. - -Description below contains information which is specific to this function -only. We recommend to read comments on MinLBFGSCreate() in order to get -more information about creation of LBFGS optimizer. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - M - number of corrections in the BFGS scheme of Hessian - approximation update. Recommended value: 3<=M<=7. The smaller - value causes worse convergence, the bigger will not cause a - considerably better convergence, but will cause a fall in the - performance. M<=N. - X - starting point, array[0..N-1]. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinLBFGSSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large truncation errors, while too small - step will result in too large numerical errors. 1.0E-6 can be good - value to start with. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. LBFGS needs exact gradient values. - Imprecise gradient may slow down convergence, especially on highly - nonlinear problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -void minlbfgscreatef(const ae_int_t n, const ae_int_t m, const real_1d_array &x, const double diffstep, minlbfgsstate &state, const xparams _xparams = alglib::xdefault); -void minlbfgscreatef(const ae_int_t m, const real_1d_array &x, const double diffstep, minlbfgsstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets stopping conditions for L-BFGS optimization algorithm. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|=0 - The subroutine finishes its work if on k+1-th iteration - the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - is satisfied. - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - ste pvector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinLBFGSSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to -automatic stopping criterion selection (small EpsX). - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetcond(const minlbfgsstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinLBFGSOptimize(). - - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetxrep(const minlbfgsstate &state, const bool needxrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0 (default), if - you don't want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which leads to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetstpmax(const minlbfgsstate &state, const double stpmax, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets scaling coefficients for LBFGS optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of the optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -In most optimizers (and in the LBFGS too) scaling is NOT a form of -preconditioning. It just affects stopping conditions. You should set -preconditioner by separate call to one of the MinLBFGSSetPrec...() -functions. - -There is special preconditioning mode, however, which uses scaling -coefficients to form diagonal preconditioning matrix. You can turn this -mode on, if you want. But you should understand that scaling is not the -same thing as preconditioning - these are two different, although related -forms of tuning solver. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetscale(const minlbfgsstate &state, const real_1d_array &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Modification of the preconditioner: default preconditioner (simple -scaling, same for all elements of X) is used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetprecdefault(const minlbfgsstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Modification of the preconditioner: Cholesky factorization of approximate -Hessian is used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - P - triangular preconditioner, Cholesky factorization of - the approximate Hessian. array[0..N-1,0..N-1], - (if larger, only leading N elements are used). - IsUpper - whether upper or lower triangle of P is given - (other triangle is not referenced) - -After call to this function preconditioner is changed to P (P is copied -into the internal buffer). - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - -NOTE 2: P should be nonsingular. Exception will be thrown otherwise. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetpreccholesky(const minlbfgsstate &state, const real_2d_array &p, const bool isupper, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Modification of the preconditioner: diagonal of approximate Hessian is -used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - D - diagonal of the approximate Hessian, array[0..N-1], - (if larger, only leading N elements are used). - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - -NOTE 2: D[i] should be positive. Exception will be thrown otherwise. - -NOTE 3: you should pass diagonal of approximate Hessian - NOT ITS INVERSE. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetprecdiag(const minlbfgsstate &state, const real_1d_array &d, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Modification of the preconditioner: scale-based diagonal preconditioning. - -This preconditioning mode can be useful when you don't have approximate -diagonal of Hessian, but you know that your variables are badly scaled -(for example, one variable is in [1,10], and another in [1000,100000]), -and most part of the ill-conditioning comes from different scales of vars. - -In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2), -can greatly improve convergence. - -IMPRTANT: you should set scale of your variables with MinLBFGSSetScale() -call (before or after MinLBFGSSetPrecScale() call). Without knowledge of -the scale of your variables scale-based preconditioner will be just unit -matrix. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetprecscale(const minlbfgsstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool minlbfgsiteration(const minlbfgsstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This family of functions is used to launcn iterations of nonlinear optimizer - -These functions accept following parameters: - state - algorithm state - func - callback which calculates function (or merit function) - value func at given point x - grad - callback which calculates function (or merit function) - value func and gradient grad at given point x - rep - optional callback which is called after each iteration - can be NULL - ptr - optional pointer which is passed to func/grad/hess/jac/rep - can be NULL - -NOTES: - -1. This function has two different implementations: one which uses exact - (analytical) user-supplied gradient, and one which uses function value - only and numerically differentiates function in order to obtain - gradient. - - Depending on the specific function used to create optimizer object - (either MinLBFGSCreate() for analytical gradient or MinLBFGSCreateF() - for numerical differentiation) you should choose appropriate variant of - MinLBFGSOptimize() - one which accepts function AND gradient or one - which accepts function ONLY. - - Be careful to choose variant of MinLBFGSOptimize() which corresponds to - your optimization scheme! Table below lists different combinations of - callback (function/gradient) passed to MinLBFGSOptimize() and specific - function used to create optimizer. - - - | USER PASSED TO MinLBFGSOptimize() - CREATED WITH | function only | function and gradient - ------------------------------------------------------------ - MinLBFGSCreateF() | work FAIL - MinLBFGSCreate() | FAIL work - - Here "FAIL" denotes inappropriate combinations of optimizer creation - function and MinLBFGSOptimize() version. Attemps to use such - combination (for example, to create optimizer with MinLBFGSCreateF() and - to pass gradient information to MinCGOptimize()) will lead to exception - being thrown. Either you did not pass gradient when it WAS needed or - you passed gradient when it was NOT needed. - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey - -*************************************************************************/ -void minlbfgsoptimize(minlbfgsstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void minlbfgsoptimize(minlbfgsstate &state, - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic gradient. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function at the initial point -(note: future versions may also perform check at the final point) and -compares numerical gradient with analytic one provided by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both gradients and specific components highlighted as -suspicious by the OptGuard. - -The primary OptGuard report can be retrieved with minlbfgsoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with minlbfgssetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsoptguardgradient(const minlbfgsstate &state, const double teststep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) -b) nonsmooth target function (non-C1) - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsoptguardsmoothness(const minlbfgsstate &state, const ae_int_t level, const xparams _xparams = alglib::xdefault); -void minlbfgsoptguardsmoothness(const minlbfgsstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -=== PRIMARY REPORT ======================================================= - -OptGuard performs several checks which are intended to catch common errors -in the implementation of nonlinear function/gradient: -* incorrect analytic gradient -* discontinuous (non-C0) target functions (constraints) -* nonsmooth (non-C1) target functions (constraints) - -Each of these checks is activated with appropriate function: -* minlbfgsoptguardgradient() for gradient verification -* minlbfgsoptguardsmoothness() for C0/C1 checks - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradvidx for specific variable (gradient element) suspected - * rep.badgradxbase, a point where gradient is tested - * rep.badgraduser, user-provided gradient (stored as 2D matrix with - single row in order to make report structure compatible with more - complex optimizers like MinNLC or MinLM) - * rep.badgradnum, reference gradient obtained via numerical - differentiation (stored as 2D matrix with single row in order to make - report structure compatible with more complex optimizers like MinNLC - or MinLM) -* rep.nonc0suspected -* rep.nonc1suspected - -=== ADDITIONAL REPORTS/LOGS ============================================== - -Several different tests are performed to catch C0/C1 errors, you can find -out specific test signaled error by looking to: -* rep.nonc0test0positive, for non-C0 test #0 -* rep.nonc1test0positive, for non-C1 test #0 -* rep.nonc1test1positive, for non-C1 test #1 - -Additional information (including line search logs) can be obtained by -means of: -* minlbfgsoptguardnonc1test0results() -* minlbfgsoptguardnonc1test1results() -which return detailed error reports, specific points where discontinuities -were found, and so on. - -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - generic OptGuard report; more detailed reports can be - retrieved with other functions. - -NOTE: false negatives (nonsmooth problems are not identified as nonsmooth - ones) are possible although unlikely. - - The reason is that you need to make several evaluations around - nonsmoothness in order to accumulate enough information about - function curvature. Say, if you start right from the nonsmooth point, - optimizer simply won't get enough data to understand what is going - wrong before it terminates due to abrupt changes in the derivative. - It is also possible that "unlucky" step will move us to the - termination too quickly. - - Our current approach is to have less than 0.1% false negatives in - our test examples (measured with multiple restarts from random - points), and to have exactly 0% false positives. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsoptguardresults(const minlbfgsstate &state, optguardreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #0 - -Nonsmoothness (non-C1) test #0 studies function values (not gradient!) -obtained during line searches and monitors behavior of the directional -derivative estimate. - -This test is less powerful than test #1, but it does not depend on the -gradient values and thus it is more robust against artifacts introduced by -numerical differentiation. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #0 "strong" report - lngrep - C1 test #0 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsoptguardnonc1test0results(const minlbfgsstate &state, optguardnonc1test0report &strrep, optguardnonc1test0report &lngrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #1 - -Nonsmoothness (non-C1) test #1 studies individual components of the -gradient computed during line search. - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #1 "strong" report - lngrep - C1 test #1 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsoptguardnonc1test1results(const minlbfgsstate &state, optguardnonc1test1report &strrep, optguardnonc1test1report &lngrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -L-BFGS algorithm results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report: - * Rep.TerminationType completetion code: - * -8 internal integrity control detected infinite - or NAN values in function/gradient. Abnormal - termination signalled. - * -2 rounding errors prevent further improvement. - X contains best point found. - * -1 incorrect parameters were specified - * 1 relative function improvement is no more than - EpsF. - * 2 relative step is no more than EpsX. - * 4 gradient norm is no more than EpsG - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible - * 8 terminated by user who called minlbfgsrequesttermination(). - X contains point which was "current accepted" when - termination request was submitted. - * Rep.IterationsCount contains iterations count - * NFEV countains number of function calculations - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsresults(const minlbfgsstate &state, real_1d_array &x, minlbfgsreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -L-BFGS algorithm results - -Buffered implementation of MinLBFGSResults which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 20.08.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsresultsbuf(const minlbfgsstate &state, real_1d_array &x, minlbfgsreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine restarts LBFGS algorithm from new point. All optimization -parameters are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure used to store algorithm state - X - new starting point. - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsrestartfrom(const minlbfgsstate &state, const real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void minlbfgsrequesttermination(const minlbfgsstate &state, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_LPQPSERV) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_VIPMSOLVER) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_NLCSQP) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_QPDENSEAULSOLVER) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINBLEIC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - BOUND CONSTRAINED OPTIMIZATION - WITH ADDITIONAL LINEAR EQUALITY AND INEQUALITY CONSTRAINTS - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments subject to any -combination of: -* bound constraints -* linear inequality constraints -* linear equality constraints - -REQUIREMENTS: -* user must provide function value and gradient -* starting point X0 must be feasible or - not too far away from the feasible set -* grad(f) must be Lipschitz continuous on a level set: - L = { x : f(x)<=f(x0) } -* function must be defined everywhere on the feasible set F - -USAGE: - -Constrained optimization if far more complex than the unconstrained one. -Here we give very brief outline of the BLEIC optimizer. We strongly recommend -you to read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide -on optimization, which is available at http://www.alglib.net/optimization/ - -1. User initializes algorithm state with MinBLEICCreate() call - -2. USer adds boundary and/or linear constraints by calling - MinBLEICSetBC() and MinBLEICSetLC() functions. - -3. User sets stopping conditions with MinBLEICSetCond(). - -4. User calls MinBLEICOptimize() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. - -5. User calls MinBLEICResults() to get solution - -6. Optionally user may call MinBLEICRestartFrom() to solve another problem - with same N but another starting point. - MinBLEICRestartFrom() allows to reuse already initialized structure. - -NOTE: if you have box-only constraints (no general linear constraints), - then MinBC optimizer can be better option. It uses special, faster - constraint activation method, which performs better on problems with - multiple constraints active at the solution. - - On small-scale problems performance of MinBC is similar to that of - MinBLEIC, but on large-scale ones (hundreds and thousands of active - constraints) it can be several times faster than MinBLEIC. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size ofX - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleiccreate(const ae_int_t n, const real_1d_array &x, minbleicstate &state, const xparams _xparams = alglib::xdefault); -void minbleiccreate(const real_1d_array &x, minbleicstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -The subroutine is finite difference variant of MinBLEICCreate(). It uses -finite differences in order to differentiate target function. - -Description below contains information which is specific to this function -only. We recommend to read comments on MinBLEICCreate() in order to get -more information about creation of BLEIC optimizer. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[0..N-1]. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinBLEICSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large truncation errors, while too small - step will result in too large numerical errors. 1.0E-6 can be good - value to start with. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. CG needs exact gradient values. Imprecise - gradient may slow down convergence, especially on highly nonlinear - problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -void minbleiccreatef(const ae_int_t n, const real_1d_array &x, const double diffstep, minbleicstate &state, const xparams _xparams = alglib::xdefault); -void minbleiccreatef(const real_1d_array &x, const double diffstep, minbleicstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets boundary constraints for BLEIC optimizer. - -Boundary constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with MinBLEICRestartFrom(). - -NOTE: if you have box-only constraints (no general linear constraints), - then MinBC optimizer can be better option. It uses special, faster - constraint activation method, which performs better on problems with - multiple constraints active at the solution. - - On small-scale problems performance of MinBC is similar to that of - MinBLEIC, but on large-scale ones (hundreds and thousands of active - constraints) it can be several times faster than MinBLEIC. - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF. - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF. - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - -NOTE 2: this solver has following useful properties: -* bound constraints are always satisfied exactly -* function is evaluated only INSIDE area specified by bound constraints, - even when numerical differentiation is used (algorithm adjusts nodes - according to boundary constraints) - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetbc(const minbleicstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets linear constraints for BLEIC optimizer. - -Linear constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with MinBLEICRestartFrom(). - -INPUT PARAMETERS: - State - structure previously allocated with MinBLEICCreate call. - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -NOTE 1: linear (non-bound) constraints are satisfied only approximately: -* there always exists some minor violation (about Epsilon in magnitude) - due to rounding errors -* numerical differentiation, if used, may lead to function evaluations - outside of the feasible area, because algorithm does NOT change - numerical differentiation formula according to linear constraints. -If you want constraints to be satisfied exactly, try to reformulate your -problem in such manner that all constraints will become boundary ones -(this kind of constraints is always satisfied exactly, both in the final -solution and in all intermediate points). - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetlc(const minbleicstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams = alglib::xdefault); -void minbleicsetlc(const minbleicstate &state, const real_2d_array &c, const integer_1d_array &ct, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets stopping conditions for the optimizer. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|=0 - The subroutine finishes its work if on k+1-th iteration - the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - is satisfied. - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - step vector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinBLEICSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead -to automatic stopping criterion selection. - -NOTE: when SetCond() called with non-zero MaxIts, BLEIC solver may perform - slightly more than MaxIts iterations. I.e., MaxIts sets non-strict - limit on iterations count. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetcond(const minbleicstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets scaling coefficients for BLEIC optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of the optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -In most optimizers (and in the BLEIC too) scaling is NOT a form of -preconditioning. It just affects stopping conditions. You should set -preconditioner by separate call to one of the MinBLEICSetPrec...() -functions. - -There is a special preconditioning mode, however, which uses scaling -coefficients to form diagonal preconditioning matrix. You can turn this -mode on, if you want. But you should understand that scaling is not the -same thing as preconditioning - these are two different, although related -forms of tuning solver. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetscale(const minbleicstate &state, const real_1d_array &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Modification of the preconditioner: preconditioning is turned off. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetprecdefault(const minbleicstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Modification of the preconditioner: diagonal of approximate Hessian is -used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - D - diagonal of the approximate Hessian, array[0..N-1], - (if larger, only leading N elements are used). - -NOTE 1: D[i] should be positive. Exception will be thrown otherwise. - -NOTE 2: you should pass diagonal of approximate Hessian - NOT ITS INVERSE. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetprecdiag(const minbleicstate &state, const real_1d_array &d, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Modification of the preconditioner: scale-based diagonal preconditioning. - -This preconditioning mode can be useful when you don't have approximate -diagonal of Hessian, but you know that your variables are badly scaled -(for example, one variable is in [1,10], and another in [1000,100000]), -and most part of the ill-conditioning comes from different scales of vars. - -In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2), -can greatly improve convergence. - -IMPRTANT: you should set scale of your variables with MinBLEICSetScale() -call (before or after MinBLEICSetPrecScale() call). Without knowledge of -the scale of your variables scale-based preconditioner will be just unit -matrix. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetprecscale(const minbleicstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinBLEICOptimize(). - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetxrep(const minbleicstate &state, const bool needxrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets maximum step length - -IMPORTANT: this feature is hard to combine with preconditioning. You can't -set upper limit on step length, when you solve optimization problem with -linear (non-boundary) constraints AND preconditioner turned on. - -When non-boundary constraints are present, you have to either a) use -preconditioner, or b) use upper limit on step length. YOU CAN'T USE BOTH! -In this case algorithm will terminate with appropriate error code. - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which lead to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetstpmax(const minbleicstate &state, const double stpmax, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool minbleiciteration(const minbleicstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This family of functions is used to launcn iterations of nonlinear optimizer - -These functions accept following parameters: - state - algorithm state - func - callback which calculates function (or merit function) - value func at given point x - grad - callback which calculates function (or merit function) - value func and gradient grad at given point x - rep - optional callback which is called after each iteration - can be NULL - ptr - optional pointer which is passed to func/grad/hess/jac/rep - can be NULL - -NOTES: - -1. This function has two different implementations: one which uses exact - (analytical) user-supplied gradient, and one which uses function value - only and numerically differentiates function in order to obtain - gradient. - - Depending on the specific function used to create optimizer object - (either MinBLEICCreate() for analytical gradient or MinBLEICCreateF() - for numerical differentiation) you should choose appropriate variant of - MinBLEICOptimize() - one which accepts function AND gradient or one - which accepts function ONLY. - - Be careful to choose variant of MinBLEICOptimize() which corresponds to - your optimization scheme! Table below lists different combinations of - callback (function/gradient) passed to MinBLEICOptimize() and specific - function used to create optimizer. - - - | USER PASSED TO MinBLEICOptimize() - CREATED WITH | function only | function and gradient - ------------------------------------------------------------ - MinBLEICCreateF() | work FAIL - MinBLEICCreate() | FAIL work - - Here "FAIL" denotes inappropriate combinations of optimizer creation - function and MinBLEICOptimize() version. Attemps to use such - combination (for example, to create optimizer with MinBLEICCreateF() - and to pass gradient information to MinBLEICOptimize()) will lead to - exception being thrown. Either you did not pass gradient when it WAS - needed or you passed gradient when it was NOT needed. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey - -*************************************************************************/ -void minbleicoptimize(minbleicstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void minbleicoptimize(minbleicstate &state, - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic gradient. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function at the initial point -(note: future versions may also perform check at the final point) and -compares numerical gradient with analytic one provided by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both gradients and specific components highlighted as -suspicious by the OptGuard. - -The primary OptGuard report can be retrieved with minbleicoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with minbleicsetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minbleicoptguardgradient(const minbleicstate &state, const double teststep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) -b) nonsmooth target function (non-C1) - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbleicoptguardsmoothness(const minbleicstate &state, const ae_int_t level, const xparams _xparams = alglib::xdefault); -void minbleicoptguardsmoothness(const minbleicstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -=== PRIMARY REPORT ======================================================= - -OptGuard performs several checks which are intended to catch common errors -in the implementation of nonlinear function/gradient: -* incorrect analytic gradient -* discontinuous (non-C0) target functions (constraints) -* nonsmooth (non-C1) target functions (constraints) - -Each of these checks is activated with appropriate function: -* minbleicoptguardgradient() for gradient verification -* minbleicoptguardsmoothness() for C0/C1 checks - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradvidx for specific variable (gradient element) suspected - * rep.badgradxbase, a point where gradient is tested - * rep.badgraduser, user-provided gradient (stored as 2D matrix with - single row in order to make report structure compatible with more - complex optimizers like MinNLC or MinLM) - * rep.badgradnum, reference gradient obtained via numerical - differentiation (stored as 2D matrix with single row in order to make - report structure compatible with more complex optimizers like MinNLC - or MinLM) -* rep.nonc0suspected -* rep.nonc1suspected - -=== ADDITIONAL REPORTS/LOGS ============================================== - -Several different tests are performed to catch C0/C1 errors, you can find -out specific test signaled error by looking to: -* rep.nonc0test0positive, for non-C0 test #0 -* rep.nonc1test0positive, for non-C1 test #0 -* rep.nonc1test1positive, for non-C1 test #1 - -Additional information (including line search logs) can be obtained by -means of: -* minbleicoptguardnonc1test0results() -* minbleicoptguardnonc1test1results() -which return detailed error reports, specific points where discontinuities -were found, and so on. - -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - generic OptGuard report; more detailed reports can be - retrieved with other functions. - -NOTE: false negatives (nonsmooth problems are not identified as nonsmooth - ones) are possible although unlikely. - - The reason is that you need to make several evaluations around - nonsmoothness in order to accumulate enough information about - function curvature. Say, if you start right from the nonsmooth point, - optimizer simply won't get enough data to understand what is going - wrong before it terminates due to abrupt changes in the derivative. - It is also possible that "unlucky" step will move us to the - termination too quickly. - - Our current approach is to have less than 0.1% false negatives in - our test examples (measured with multiple restarts from random - points), and to have exactly 0% false positives. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbleicoptguardresults(const minbleicstate &state, optguardreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #0 - -Nonsmoothness (non-C1) test #0 studies function values (not gradient!) -obtained during line searches and monitors behavior of the directional -derivative estimate. - -This test is less powerful than test #1, but it does not depend on the -gradient values and thus it is more robust against artifacts introduced by -numerical differentiation. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #0 "strong" report - lngrep - C1 test #0 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbleicoptguardnonc1test0results(const minbleicstate &state, optguardnonc1test0report &strrep, optguardnonc1test0report &lngrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #1 - -Nonsmoothness (non-C1) test #1 studies individual components of the -gradient computed during line search. - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #1 "strong" report - lngrep - C1 test #1 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbleicoptguardnonc1test1results(const minbleicstate &state, optguardnonc1test1report &strrep, optguardnonc1test1report &lngrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -BLEIC results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report. You should check Rep.TerminationType - in order to distinguish successful termination from - unsuccessful one: - * -8 internal integrity control detected infinite or - NAN values in function/gradient. Abnormal - termination signalled. - * -3 inconsistent constraints. Feasible point is - either nonexistent or too hard to find. Try to - restart optimizer with better initial approximation - * 1 relative function improvement is no more than EpsF. - * 2 scaled step is no more than EpsX. - * 4 scaled gradient norm is no more than EpsG. - * 5 MaxIts steps was taken - * 8 terminated by user who called minbleicrequesttermination(). - X contains point which was "current accepted" when - termination request was submitted. - More information about fields of this structure can be - found in the comments on MinBLEICReport datatype. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicresults(const minbleicstate &state, real_1d_array &x, minbleicreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -BLEIC results - -Buffered implementation of MinBLEICResults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicresultsbuf(const minbleicstate &state, real_1d_array &x, minbleicreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine restarts algorithm from new point. -All optimization parameters (including constraints) are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure previously allocated with MinBLEICCreate call. - X - new starting point. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicrestartfrom(const minbleicstate &state, const real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void minbleicrequesttermination(const minbleicstate &state, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_QPBLEICSOLVER) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINQP) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - CONSTRAINED QUADRATIC PROGRAMMING - -The subroutine creates QP optimizer. After initial creation, it contains -default optimization problem with zero quadratic and linear terms and no -constraints. - -In order to actually solve something you should: -* set cost vector with minqpsetlinearterm() -* set variable bounds with minqpsetbc() or minqpsetbcall() -* specify constraint matrix with one of the following functions: - * modern API: - * minqpsetlc2() for sparse two-sided constraints AL <= A*x <= AU - * minqpsetlc2dense() for dense two-sided constraints AL <= A*x <= AU - * minqpsetlc2mixed() for mixed two-sided constraints AL <= A*x <= AU - * minqpaddlc2dense() to add one dense row to dense constraint submatrix - * minqpaddlc2() to add one sparse row to sparse constraint submatrix - * legacy API: - * minqpsetlc() for dense one-sided equality/inequality constraints - * minqpsetlcsparse() for sparse one-sided equality/inequality constraints - * minqpsetlcmixed() for mixed dense/sparse one-sided equality/inequality constraints -* choose appropriate QP solver and set it and its stopping criteria by - means of minqpsetalgo??????() function -* call minqpoptimize() to run the solver and minqpresults() to get the - solution vector and additional information. - -Following solvers are recommended for convex and semidefinite problems: -* QuickQP for dense problems with box-only constraints (or no constraints - at all) -* DENSE-IPM-QP for convex or semidefinite problems with medium (up - to several thousands) variable count, dense/sparse quadratic term and - any number (up to many thousands) of dense/sparse general linear - constraints -* SPARSE-IPM-QP for convex or semidefinite problems with large (many - thousands) variable count, sparse quadratic term AND linear constraints. - -If your problem happens to be nonconvex, but either (a) is effectively -convexified under constraints, or (b) has unique solution even with -nonconvex target, then you can use: -* QuickQP for dense nonconvex problems with box-only constraints -* DENSE-AUL-QP for dense nonconvex problems which are effectively - convexified under constraints with up to several thousands of variables - and any (small or large) number of general linear constraints -* QP-BLEIC for dense/sparse problems with small (up to several hundreds) - number of general linear constraints and arbitrarily large variable - count. - -INPUT PARAMETERS: - N - problem size - -OUTPUT PARAMETERS: - State - optimizer with zero quadratic/linear terms - and no constraints - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpcreate(const ae_int_t n, minqpstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets linear term for QP solver. - -By default, linear term is zero. - -INPUT PARAMETERS: - State - structure which stores algorithm state - B - linear term, array[N]. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlinearterm(const minqpstate &state, const real_1d_array &b, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets dense quadratic term for QP solver. By default, -quadratic term is zero. - -IMPORTANT: - -This solver minimizes following function: - f(x) = 0.5*x'*A*x + b'*x. -Note that quadratic term has 0.5 before it. So if you want to minimize - f(x) = x^2 + x -you should rewrite your problem as follows: - f(x) = 0.5*(2*x^2) + x -and your matrix A will be equal to [[2.0]], not to [[1.0]] - -INPUT PARAMETERS: - State - structure which stores algorithm state - A - matrix, array[N,N] - IsUpper - (optional) storage type: - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used - * if not given, both lower and upper triangles must be - filled. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetquadraticterm(const minqpstate &state, const real_2d_array &a, const bool isupper, const xparams _xparams = alglib::xdefault); -void minqpsetquadraticterm(const minqpstate &state, const real_2d_array &a, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets sparse quadratic term for QP solver. By default, -quadratic term is zero. This function overrides previous calls to -minqpsetquadraticterm() or minqpsetquadratictermsparse(). - -NOTE: dense solvers like DENSE-AUL-QP or DENSE-IPM-QP will convert this - matrix to dense storage anyway. - -IMPORTANT: - -This solver minimizes following function: - f(x) = 0.5*x'*A*x + b'*x. -Note that quadratic term has 0.5 before it. So if you want to minimize - f(x) = x^2 + x -you should rewrite your problem as follows: - f(x) = 0.5*(2*x^2) + x -and your matrix A will be equal to [[2.0]], not to [[1.0]] - -INPUT PARAMETERS: - State - structure which stores algorithm state - A - matrix, array[N,N] - IsUpper - (optional) storage type: - * if True, symmetric matrix A is given by its upper - triangle, and the lower triangle isn't used - * if False, symmetric matrix A is given by its lower - triangle, and the upper triangle isn't used - * if not given, both lower and upper triangles must be - filled. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetquadratictermsparse(const minqpstate &state, const sparsematrix &a, const bool isupper, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets starting point for QP solver. It is useful to have good -initial approximation to the solution, because it will increase speed of -convergence and identification of active constraints. - -NOTE: interior point solvers ignore initial point provided by user. - -INPUT PARAMETERS: - State - structure which stores algorithm state - X - starting point, array[N]. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetstartingpoint(const minqpstate &state, const real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets origin for QP solver. By default, following QP program -is solved: - - min(0.5*x'*A*x+b'*x) - -This function allows to solve different problem: - - min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin)) - -Specification of non-zero origin affects function being minimized, but not -constraints. Box and linear constraints are still calculated without -origin. - -INPUT PARAMETERS: - State - structure which stores algorithm state - XOrigin - origin, array[N]. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetorigin(const minqpstate &state, const real_1d_array &xorigin, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets scaling coefficients. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances) and as -preconditioner. - -Scale of the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the - function - -If you do not know how to choose scales of your variables, you can: -* read www.alglib.net/optimization/scaling.php article -* use minqpsetscaleautodiag(), which calculates scale using diagonal of - the quadratic term: S is set to 1/sqrt(diag(A)), which works well - sometimes. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetscale(const minqpstate &state, const real_1d_array &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets automatic evaluation of variable scaling. - -IMPORTANT: this function works only for matrices with positive diagonal - elements! Zero or negative elements will result in -9 error - code being returned. Specify scale vector manually with - minqpsetscale() in such cases. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances) and as -preconditioner. - -The best way to set scaling is to manually specify variable scales. -However, sometimes you just need quick-and-dirty solution - either when -you perform fast prototyping, or when you know your problem well and you -are 100% sure that this quick solution is robust enough in your case. - -One such solution is to evaluate scale of I-th variable as 1/Sqrt(A[i,i]), -where A[i,i] is an I-th diagonal element of the quadratic term. - -Such approach works well sometimes, but you have to be careful here. - -INPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -void minqpsetscaleautodiag(const minqpstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function tells solver to use BLEIC-based algorithm and sets stopping -criteria for the algorithm. - -This algorithm is intended for large-scale problems, possibly nonconvex, -with small number of general linear constraints. Feasible initial point is -essential for good performance. - -IMPORTANT: when DENSE-IPM (or DENSE-AUL for nonconvex problems) solvers - are applicable, their performance is much better than that of - BLEIC-QP. - We recommend you to use BLEIC only when other solvers can not - be used. - -ALGORITHM FEATURES: - -* supports dense and sparse QP problems -* supports box and general linear equality/inequality constraints -* can solve all types of problems (convex, semidefinite, nonconvex) as - long as they are bounded from below under constraints. - Say, it is possible to solve "min{-x^2} subject to -1<=x<=+1". - Of course, global minimum is found only for positive definite and - semidefinite problems. As for indefinite ones - only local minimum is - found. - -ALGORITHM OUTLINE: - -* BLEIC-QP solver is just a driver function for MinBLEIC solver; it solves - quadratic programming problem as general linearly constrained - optimization problem, which is solved by means of BLEIC solver (part of - ALGLIB, active set method). - -ALGORITHM LIMITATIONS: -* This algorithm is inefficient on problems with hundreds and thousands - of general inequality constraints and infeasible initial point. Initial - feasibility detection stage may take too long on such constraint sets. - Consider using DENSE-IPM or DENSE-AUL instead. -* unlike QuickQP solver, this algorithm does not perform Newton steps and - does not use Level 3 BLAS. Being general-purpose active set method, it - can activate constraints only one-by-one. Thus, its performance is lower - than that of QuickQP. -* its precision is also a bit inferior to that of QuickQP. BLEIC-QP - performs only LBFGS steps (no Newton steps), which are good at detecting - neighborhood of the solution, buy needs many iterations to find solution - with more than 6 digits of precision. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|=0 - The subroutine finishes its work if exploratory steepest - descent step on k+1-th iteration satisfies following - condition: |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - EpsX - >=0 - The subroutine finishes its work if exploratory steepest - descent step on k+1-th iteration satisfies following - condition: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - step vector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinQPSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. NOTE: this algorithm uses LBFGS - iterations, which are relatively cheap, but improve - function value only a bit. So you will need many iterations - to converge - from 0.1*N to 10*N, depending on problem's - condition number. - -IT IS VERY IMPORTANT TO CALL MinQPSetScale() WHEN YOU USE THIS ALGORITHM -BECAUSE ITS STOPPING CRITERIA ARE SCALE-DEPENDENT! - -Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead -to automatic stopping criterion selection (presently it is small step -length, but it may change in the future versions of ALGLIB). - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetalgobleic(const minqpstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function tells QP solver to use DENSE-AUL algorithm and sets stopping -criteria for the algorithm. - -This algorithm is intended for non-convex problems with moderate (up -to several thousands) variable count and arbitrary number of constraints -which are either (a) effectively convexified under constraints or (b) have -unique solution even with nonconvex target. - -IMPORTANT: when DENSE-IPM solver is applicable, its performance is usually - much better than that of DENSE-AUL. - We recommend you to use DENSE-AUL only when other solvers can - not be used. - -ALGORITHM FEATURES: - -* supports box and dense/sparse general linear equality/inequality - constraints -* convergence is theoretically proved for positive-definite (convex) QP - problems. Semidefinite and non-convex problems can be solved as long as - they are bounded from below under constraints, although without - theoretical guarantees. - -ALGORITHM OUTLINE: - -* this algorithm is an augmented Lagrangian method with dense - preconditioner (hence its name). -* it performs several outer iterations in order to refine values of the - Lagrange multipliers. Single outer iteration is a solution of some - unconstrained optimization problem: first it performs dense Cholesky - factorization of the Hessian in order to build preconditioner (adaptive - regularization is applied to enforce positive definiteness), and then - it uses L-BFGS optimizer to solve optimization problem. -* typically you need about 5-10 outer iterations to converge to solution - -ALGORITHM LIMITATIONS: - -* because dense Cholesky driver is used, this algorithm has O(N^2) memory - requirements and O(OuterIterations*N^3) minimum running time. From the - practical point of view, it limits its applicability by several - thousands of variables. - From the other side, variables count is the most limiting factor, - and dependence on constraint count is much more lower. Assuming that - constraint matrix is sparse, it may handle tens of thousands of general - linear constraints. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsX - >=0, stopping criteria for inner optimizer. - Inner iterations are stopped when step length (with - variable scaling being applied) is less than EpsX. - See minqpsetscale() for more information on variable - scaling. - Rho - penalty coefficient, Rho>0: - * large enough that algorithm converges with desired - precision. - * not TOO large to prevent ill-conditioning - * recommended values are 100, 1000 or 10000 - ItsCnt - number of outer iterations: - * recommended values: 10-15 (although in most cases it - converges within 5 iterations, you may need a few more - to be sure). - * ItsCnt=0 means that small number of outer iterations is - automatically chosen (10 iterations in current version). - * ItsCnt=1 means that AUL algorithm performs just as usual - penalty method. - * ItsCnt>1 means that AUL algorithm performs specified - number of outer iterations - -IT IS VERY IMPORTANT TO CALL minqpsetscale() WHEN YOU USE THIS ALGORITHM -BECAUSE ITS CONVERGENCE PROPERTIES AND STOPPING CRITERIA ARE SCALE-DEPENDENT! - -NOTE: Passing EpsX=0 will lead to automatic step length selection - (specific step length chosen may change in the future versions of - ALGLIB, so it is better to specify step length explicitly). - - -- ALGLIB -- - Copyright 20.08.2016 by Bochkanov Sergey -*************************************************************************/ -void minqpsetalgodenseaul(const minqpstate &state, const double epsx, const double rho, const ae_int_t itscnt, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function tells QP solver to use DENSE-IPM QP algorithm and sets -stopping criteria for the algorithm. - -This algorithm is intended for convex and semidefinite problems with -moderate (up to several thousands) variable count and arbitrary number of -constraints. - -IMPORTANT: this algorithm won't work for nonconvex problems, use DENSE-AUL - or BLEIC-QP instead. If you try to run DENSE-IPM on problem - with indefinite matrix (matrix having at least one negative - eigenvalue) then depending on circumstances it may either (a) - stall at some arbitrary point, or (b) throw exception on - failure of Cholesky decomposition. - -ALGORITHM FEATURES: - -* supports box and dense/sparse general linear equality/inequality - constraints - -ALGORITHM OUTLINE: - -* this algorithm is our implementation of interior point method as - formulated by R.J.Vanderbei, with minor modifications to the algorithm - (damped Newton directions are extensively used) -* like all interior point methods, this algorithm tends to converge in - roughly same number of iterations (between 15 and 50) independently from - the problem dimensionality - -ALGORITHM LIMITATIONS: - -* because dense Cholesky driver is used, for N-dimensional problem with - M dense constaints this algorithm has O(N^2+N*M) memory requirements and - O(N^3+N*M^2) running time. - Having sparse constraints with Z nonzeros per row relaxes storage and - running time down to O(N^2+M*Z) and O(N^3+N*Z^2) - From the practical point of view, it limits its applicability by - several thousands of variables. - From the other side, variables count is the most limiting factor, - and dependence on constraint count is much more lower. Assuming that - constraint matrix is sparse, it may handle tens of thousands of general - linear constraints. - -INPUT PARAMETERS: - State - structure which stores algorithm state - Eps - >=0, stopping criteria. The algorithm stops when primal - and dual infeasiblities as well as complementarity gap are - less than Eps. - -IT IS VERY IMPORTANT TO CALL minqpsetscale() WHEN YOU USE THIS ALGORITHM -BECAUSE ITS CONVERGENCE PROPERTIES AND STOPPING CRITERIA ARE SCALE-DEPENDENT! - -NOTE: Passing EpsX=0 will lead to automatic selection of small epsilon. - -===== TRACING IPM SOLVER ================================================= - -IPM solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'IPM' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. -* 'IPM.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'IPM'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("IPM,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void minqpsetalgodenseipm(const minqpstate &state, const double eps, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function tells QP solver to use SPARSE-IPM QP algorithm and sets -stopping criteria for the algorithm. - -This algorithm is intended for convex and semidefinite problems with -large variable and constraint count and sparse quadratic term and -constraints. It is possible to have some limited set of dense linear -constraints - they will be handled separately by dense BLAS - but the more -dense constraints you have, the more time solver needs. - -IMPORTANT: internally this solver performs large and sparse (N+M)x(N+M) - triangular factorization. So it expects both quadratic term and - constraints to be highly sparse. However, its running time is - influenced by BOTH fill factor and sparsity pattern. - - Generally we expect that no more than few nonzero elements per - row are present. However different sparsity patterns may result - in completely different running times even given same fill - factor. - - In many cases this algorithm outperforms DENSE-IPM by order of - magnitude. However, in some cases you may get better results - with DENSE-IPM even when solving sparse task. - -IMPORTANT: this algorithm won't work for nonconvex problems, use DENSE-AUL - or BLEIC-QP instead. If you try to run DENSE-IPM on problem - with indefinite matrix (matrix having at least one negative - eigenvalue) then depending on circumstances it may either (a) - stall at some arbitrary point, or (b) throw exception on - failure of Cholesky decomposition. - -ALGORITHM FEATURES: - -* supports box and dense/sparse general linear equality/inequality - constraints -* specializes on large-scale sparse problems - -ALGORITHM OUTLINE: - -* this algorithm is our implementation of interior point method as - formulated by R.J.Vanderbei, with minor modifications to the algorithm - (damped Newton directions are extensively used) -* like all interior point methods, this algorithm tends to converge in - roughly same number of iterations (between 15 and 50) independently from - the problem dimensionality - -ALGORITHM LIMITATIONS: - -* this algorithm may handle moderate number of dense constraints, usually - no more than a thousand of dense ones without losing its efficiency. - -INPUT PARAMETERS: - State - structure which stores algorithm state - Eps - >=0, stopping criteria. The algorithm stops when primal - and dual infeasiblities as well as complementarity gap are - less than Eps. - -IT IS VERY IMPORTANT TO CALL minqpsetscale() WHEN YOU USE THIS ALGORITHM -BECAUSE ITS CONVERGENCE PROPERTIES AND STOPPING CRITERIA ARE SCALE-DEPENDENT! - -NOTE: Passing EpsX=0 will lead to automatic selection of small epsilon. - -===== TRACING IPM SOLVER ================================================= - -IPM solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'IPM' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. -* 'IPM.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'IPM'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("IPM,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void minqpsetalgosparseipm(const minqpstate &state, const double eps, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function tells solver to use QuickQP algorithm: special extra-fast -algorithm for problems with box-only constrants. It may solve non-convex -problems as long as they are bounded from below under constraints. - -ALGORITHM FEATURES: -* several times faster than DENSE-IPM when running on box-only problem -* utilizes accelerated methods for activation of constraints. -* supports dense and sparse QP problems -* supports ONLY box constraints; general linear constraints are NOT - supported by this solver -* can solve all types of problems (convex, semidefinite, nonconvex) as - long as they are bounded from below under constraints. - Say, it is possible to solve "min{-x^2} subject to -1<=x<=+1". - In convex/semidefinite case global minimum is returned, in nonconvex - case - algorithm returns one of the local minimums. - -ALGORITHM OUTLINE: - -* algorithm performs two kinds of iterations: constrained CG iterations - and constrained Newton iterations -* initially it performs small number of constrained CG iterations, which - can efficiently activate/deactivate multiple constraints -* after CG phase algorithm tries to calculate Cholesky decomposition and - to perform several constrained Newton steps. If Cholesky decomposition - failed (matrix is indefinite even under constraints), we perform more - CG iterations until we converge to such set of constraints that system - matrix becomes positive definite. Constrained Newton steps greatly - increase convergence speed and precision. -* algorithm interleaves CG and Newton iterations which allows to handle - indefinite matrices (CG phase) and quickly converge after final set of - constraints is found (Newton phase). Combination of CG and Newton phases - is called "outer iteration". -* it is possible to turn off Newton phase (beneficial for semidefinite - problems - Cholesky decomposition will fail too often) - -ALGORITHM LIMITATIONS: - -* algorithm does not support general linear constraints; only box ones - are supported -* Cholesky decomposition for sparse problems is performed with Skyline - Cholesky solver, which is intended for low-profile matrices. No profile- - reducing reordering of variables is performed in this version of ALGLIB. -* problems with near-zero negative eigenvalues (or exacty zero ones) may - experience about 2-3x performance penalty. The reason is that Cholesky - decomposition can not be performed until we identify directions of zero - and negative curvature and activate corresponding boundary constraints - - but we need a lot of trial and errors because these directions are hard - to notice in the matrix spectrum. - In this case you may turn off Newton phase of algorithm. - Large negative eigenvalues are not an issue, so highly non-convex - problems can be solved very efficiently. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|=0 - The subroutine finishes its work if exploratory steepest - descent step on k+1-th iteration satisfies following - condition: |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - EpsX - >=0 - The subroutine finishes its work if exploratory steepest - descent step on k+1-th iteration satisfies following - condition: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - step vector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinQPSetScale() - MaxOuterIts-maximum number of OUTER iterations. One outer iteration - includes some amount of CG iterations (from 5 to ~N) and - one or several (usually small amount) Newton steps. Thus, - one outer iteration has high cost, but can greatly reduce - funcation value. - Use 0 if you do not want to limit number of outer iterations. - UseNewton- use Newton phase or not: - * Newton phase improves performance of positive definite - dense problems (about 2 times improvement can be observed) - * can result in some performance penalty on semidefinite - or slightly negative definite problems - each Newton - phase will bring no improvement (Cholesky failure), but - still will require computational time. - * if you doubt, you can turn off this phase - optimizer - will retain its most of its high speed. - -IT IS VERY IMPORTANT TO CALL MinQPSetScale() WHEN YOU USE THIS ALGORITHM -BECAUSE ITS STOPPING CRITERIA ARE SCALE-DEPENDENT! - -Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead -to automatic stopping criterion selection (presently it is small step -length, but it may change in the future versions of ALGLIB). - - -- ALGLIB -- - Copyright 22.05.2014 by Bochkanov Sergey -*************************************************************************/ -void minqpsetalgoquickqp(const minqpstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxouterits, const bool usenewton, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets box constraints for QP solver - -Box constraints are inactive by default (after initial creation). After -being set, they are preserved until explicitly overwritten with another -minqpsetbc() or minqpsetbcall() call, or partially overwritten with -minqpsetbci() call. - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd[i] BndL[i]=BndU[i] - lower bound BndL[i]<=x[i] BndU[i]=+INF - upper bound x[i]<=BndU[i] BndL[i]=-INF - range BndL[i]<=x[i]<=BndU[i] ... - free variable - BndL[I]=-INF, BndU[I]+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF (latter is recommended because - it will allow solver to use better algorithm). - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF (latter is recommended because - it will allow solver to use better algorithm). - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: if constraints for all variables are same you may use minqpsetbcall() - which allows to specify constraints without using arrays. - -NOTE: BndL>BndU will result in QP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetbc(const minqpstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets box constraints for QP solver (all variables at once, -same constraints for all variables) - -Box constraints are inactive by default (after initial creation). After -being set, they are preserved until explicitly overwritten with another -minqpsetbc() or minqpsetbcall() call, or partially overwritten with -minqpsetbci() call. - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd BndL=BndU - lower bound BndL<=x[i] BndU=+INF - upper bound x[i]<=BndU BndL=-INF - range BndL<=x[i]<=BndU ... - free variable - BndL=-INF, BndU+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bound, same for all variables - BndU - upper bound, same for all variables - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: BndL>BndU will result in QP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetbcall(const minqpstate &state, const double bndl, const double bndu, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets box constraints for I-th variable (other variables are -not modified). - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd BndL=BndU - lower bound BndL<=x[i] BndU=+INF - upper bound x[i]<=BndU BndL=-INF - range BndL<=x[i]<=BndU ... - free variable - BndL=-INF, BndU+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bound - BndU - upper bound - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: BndL>BndU will result in QP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpsetbci(const minqpstate &state, const ae_int_t i, const double bndl, const double bndu, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets dense linear constraints for QP optimizer. - -This function overrides results of previous calls to minqpsetlc(), -minqpsetlcsparse() and minqpsetlcmixed(). After call to this function -all non-box constraints are dropped, and you have only those constraints -which were specified in the present call. - -If you want to specify mixed (with dense and sparse terms) linear -constraints, you should call minqpsetlcmixed(). - -INPUT PARAMETERS: - State - structure previously allocated with MinQPCreate call. - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -NOTE 1: linear (non-bound) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations (BLEIC-QP solver is most precise, AUL-QP - solver is less precise). - - -- ALGLIB -- - Copyright 19.06.2012 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlc(const minqpstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams = alglib::xdefault); -void minqpsetlc(const minqpstate &state, const real_2d_array &c, const integer_1d_array &ct, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets sparse linear constraints for QP optimizer. - -This function overrides results of previous calls to minqpsetlc(), -minqpsetlcsparse() and minqpsetlcmixed(). After call to this function -all non-box constraints are dropped, and you have only those constraints -which were specified in the present call. - -If you want to specify mixed (with dense and sparse terms) linear -constraints, you should call minqpsetlcmixed(). - -INPUT PARAMETERS: - State - structure previously allocated with MinQPCreate call. - C - linear constraints, sparse matrix with dimensions at - least [K,N+1]. If matrix has larger size, only leading - Kx(N+1) rectangle is used. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0 - -NOTE 1: linear (non-bound) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations (BLEIC-QP solver is most precise, AUL-QP - solver is less precise). - - -- ALGLIB -- - Copyright 22.08.2016 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlcsparse(const minqpstate &state, const sparsematrix &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets mixed linear constraints, which include a set of dense -rows, and a set of sparse rows. - -This function overrides results of previous calls to minqpsetlc(), -minqpsetlcsparse() and minqpsetlcmixed(). - -This function may be useful if constraint matrix includes large number of -both types of rows - dense and sparse. If you have just a few sparse rows, -you may represent them in dense format without losing performance. -Similarly, if you have just a few dense rows, you may store them in sparse -format with almost same performance. - -INPUT PARAMETERS: - State - structure previously allocated with MinQPCreate call. - SparseC - linear constraints, sparse matrix with dimensions EXACTLY - EQUAL TO [SparseK,N+1]. Each row of C represents one - constraint, either equality or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - SparseCT- type of sparse constraints, array[K]: - * if SparseCT[i]>0, then I-th constraint is SparseC[i,*]*x >= SparseC[i,n+1] - * if SparseCT[i]=0, then I-th constraint is SparseC[i,*]*x = SparseC[i,n+1] - * if SparseCT[i]<0, then I-th constraint is SparseC[i,*]*x <= SparseC[i,n+1] - SparseK - number of sparse equality/inequality constraints, K>=0 - DenseC - dense linear constraints, array[K,N+1]. - Each row of DenseC represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of DenseC (including right part) must be finite. - DenseCT - type of constraints, array[K]: - * if DenseCT[i]>0, then I-th constraint is DenseC[i,*]*x >= DenseC[i,n+1] - * if DenseCT[i]=0, then I-th constraint is DenseC[i,*]*x = DenseC[i,n+1] - * if DenseCT[i]<0, then I-th constraint is DenseC[i,*]*x <= DenseC[i,n+1] - DenseK - number of equality/inequality constraints, DenseK>=0 - -NOTE 1: linear (non-box) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations (BLEIC-QP solver is most precise, AUL-QP - solver is less precise). - -NOTE 2: due to backward compatibility reasons SparseC can be larger than - [SparseK,N+1]. In this case only leading [SparseK,N+1] submatrix - will be used. However, the rest of ALGLIB has more strict - requirements on the input size, so we recommend you to pass sparse - term whose size exactly matches algorithm expectations. - - -- ALGLIB -- - Copyright 22.08.2016 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlcmixed(const minqpstate &state, const sparsematrix &sparsec, const integer_1d_array &sparsect, const ae_int_t sparsek, const real_2d_array &densec, const integer_1d_array &densect, const ae_int_t densek, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function provides legacy API for specification of mixed dense/sparse -linear constraints. - -New conventions used by ALGLIB since release 3.16.0 state that set of -sparse constraints comes first, followed by set of dense ones. This -convention is essential when you talk about things like order of Lagrange -multipliers. - -However, legacy API accepted mixed constraints in reverse order. This -function is here to simplify situation with code relying on legacy API. It -simply accepts constraints in one order (old) and passes them to new API, -now in correct order. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlcmixedlegacy(const minqpstate &state, const real_2d_array &densec, const integer_1d_array &densect, const ae_int_t densek, const sparsematrix &sparsec, const integer_1d_array &sparsect, const ae_int_t sparsek, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU with dense -constraint matrix A. - -NOTE: knowing that constraint matrix is dense helps some QP solvers - (especially modern IPM method) to utilize efficient dense Level 3 - BLAS for dense parts of the problem. If your problem has both dense - and sparse constraints, you can use minqpsetlc2mixed() function, - which will result in dense algebra being applied to dense terms, and - sparse sparse linear algebra applied to sparse terms. - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - A - linear constraints, array[K,N]. Each row of A represents - one constraint. One-sided inequality constraints, two- - sided inequality constraints, equality constraints are - supported (see below) - AL, AU - lower and upper bounds, array[K]; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i] two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0; if not - given, inferred from sizes of A, AL, AU. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlc2dense(const minqpstate &state, const real_2d_array &a, const real_1d_array &al, const real_1d_array &au, const ae_int_t k, const xparams _xparams = alglib::xdefault); -void minqpsetlc2dense(const minqpstate &state, const real_2d_array &a, const real_1d_array &al, const real_1d_array &au, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU with -sparse constraining matrix A. Recommended for large-scale problems. - -This function overwrites linear (non-box) constraints set by previous -calls (if such calls were made). - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - A - sparse matrix with size [K,N] (exactly!). - Each row of A represents one general linear constraint. - A can be stored in any sparse storage format. - AL, AU - lower and upper bounds, array[K]; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i] two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0. If K=0 - is specified, A, AL, AU are ignored. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlc2(const minqpstate &state, const sparsematrix &a, const real_1d_array &al, const real_1d_array &au, const ae_int_t k, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU with -mixed constraining matrix A including sparse part (first SparseK rows) and -dense part (last DenseK rows). Recommended for large-scale problems. - -This function overwrites linear (non-box) constraints set by previous -calls (if such calls were made). - -This function may be useful if constraint matrix includes large number of -both types of rows - dense and sparse. If you have just a few sparse rows, -you may represent them in dense format without losing performance. -Similarly, if you have just a few dense rows, you may store them in sparse -format with almost same performance. - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - SparseA - sparse matrix with size [K,N] (exactly!). - Each row of A represents one general linear constraint. - A can be stored in any sparse storage format. - SparseK - number of sparse constraints, SparseK>=0 - DenseA - linear constraints, array[K,N], set of dense constraints. - Each row of A represents one general linear constraint. - DenseK - number of dense constraints, DenseK>=0 - AL, AU - lower and upper bounds, array[SparseK+DenseK], with former - SparseK elements corresponding to sparse constraints, and - latter DenseK elements corresponding to dense constraints; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i] two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0. If K=0 - is specified, A, AL, AU are ignored. - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -void minqpsetlc2mixed(const minqpstate &state, const sparsematrix &sparsea, const ae_int_t ksparse, const real_2d_array &densea, const ae_int_t kdense, const real_1d_array &al, const real_1d_array &au, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function appends two-sided linear constraint AL <= A*x <= AU to the -list of currently present dense constraints. - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - A - linear constraint coefficient, array[N], right side is NOT - included. - AL, AU - lower and upper bounds; - * AL=AU => equality constraint Ai*x - * AL two-sided constraint AL<=A*x<=AU - * AL=-INF => one-sided constraint Ai*x<=AU - * AU=+INF => one-sided constraint AL<=Ai*x - * AL=-INF, AU=+INF => constraint is ignored - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minqpaddlc2dense(const minqpstate &state, const real_1d_array &a, const double al, const double au, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function appends two-sided linear constraint AL <= A*x <= AU to the -list of currently present sparse constraints. - -Constraint is passed in compressed format: as list of non-zero entries of -coefficient vector A. Such approach is more efficient than dense storage -for highly sparse constraint vectors. - -INPUT PARAMETERS: - State - structure previously allocated with minqpcreate() call. - IdxA - array[NNZ], indexes of non-zero elements of A: - * can be unsorted - * can include duplicate indexes (corresponding entries of - ValA[] will be summed) - ValA - array[NNZ], values of non-zero elements of A - NNZ - number of non-zero coefficients in A - AL, AU - lower and upper bounds; - * AL=AU => equality constraint A*x - * AL two-sided constraint AL<=A*x<=AU - * AL=-INF => one-sided constraint A*x<=AU - * AU=+INF => one-sided constraint AL<=A*x - * AL=-INF, AU=+INF => constraint is ignored - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minqpaddlc2(const minqpstate &state, const integer_1d_array &idxa, const real_1d_array &vala, const ae_int_t nnz, const double al, const double au, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function solves quadratic programming problem. - -Prior to calling this function you should choose solver by means of one of -the following functions: - -* minqpsetalgoquickqp() - for QuickQP solver -* minqpsetalgobleic() - for BLEIC-QP solver -* minqpsetalgodenseaul() - for Dense-AUL-QP solver -* minqpsetalgodenseipm() - for Dense-IPM-QP solver - -These functions also allow you to control stopping criteria of the solver. -If you did not set solver, MinQP subpackage will automatically select -solver for your problem and will run it with default stopping criteria. - -However, it is better to set explicitly solver and its stopping criteria. - -INPUT PARAMETERS: - State - algorithm state - -You should use MinQPResults() function to access results after calls -to this function. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey. - Special thanks to Elvira Illarionova for important suggestions on - the linearly constrained QP algorithm. -*************************************************************************/ -void minqpoptimize(const minqpstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -QP solver results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution (on failure - the best point found - so far). - Rep - optimization report, contains: - * completion code in Rep.TerminationType (positive values - denote some kind of success, negative - failures) - * Lagrange multipliers - for QP solvers which support them - * other statistics - See comments on minqpreport structure for more information - -Following completion codes are returned in Rep.TerminationType: -* -9 failure of the automatic scale evaluation: one of the diagonal - elements of the quadratic term is non-positive. Specify variable - scales manually! -* -5 inappropriate solver was used: - * QuickQP solver for problem with general linear constraints -* -4 the function is unbounded from below even under constraints, - no meaningful minimum can be found. -* -3 inconsistent constraints (or, maybe, feasible point is too hard to - find). -* -2 IPM solver has difficulty finding primal/dual feasible point. - It is likely that the problem is either infeasible or unbounded, - but it is difficult to determine exact reason for termination. - X contains best point found so far. -* >0 success -* 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpresults(const minqpstate &state, real_1d_array &x, minqpreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -QP results - -Buffered implementation of MinQPResults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minqpresultsbuf(const minqpstate &state, real_1d_array &x, minqpreport &rep, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_LPQPPRESOLVE) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_REVISEDDUALSIMPLEX) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINLP) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - LINEAR PROGRAMMING - -The subroutine creates LP solver. After initial creation it contains -default optimization problem with zero cost vector and all variables being -fixed to zero values and no constraints. - -In order to actually solve something you should: -* set cost vector with minlpsetcost() -* set variable bounds with minlpsetbc() or minlpsetbcall() -* specify constraint matrix with one of the following functions: - [*] minlpsetlc() for dense one-sided constraints - [*] minlpsetlc2dense() for dense two-sided constraints - [*] minlpsetlc2() for sparse two-sided constraints - [*] minlpaddlc2dense() to add one dense row to constraint matrix - [*] minlpaddlc2() to add one row to constraint matrix (compressed format) -* call minlpoptimize() to run the solver and minlpresults() to get the - solution vector and additional information. - -By default, LP solver uses best algorithm available. As of ALGLIB 3.17, -sparse interior point (barrier) solver is used. Future releases of ALGLIB -may introduce other solvers. - -User may choose specific LP algorithm by calling: -* minlpsetalgodss() for revised dual simplex method with DSE pricing and - bounds flipping ratio test (aka long dual step). Large-scale sparse LU - solverwith Forest-Tomlin update is used internally as linear algebra - driver. -* minlpsetalgoipm() for sparse interior point method - -INPUT PARAMETERS: - N - problem size - -OUTPUT PARAMETERS: - State - optimizer in the default state - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpcreate(const ae_int_t n, minlpstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets LP algorithm to revised dual simplex method. - -ALGLIB implementation of dual simplex method supports advanced performance -and stability improvements like DSE pricing , bounds flipping ratio test -(aka long dual step), Forest-Tomlin update, shifting. - -INPUT PARAMETERS: - State - optimizer - Eps - stopping condition, Eps>=0: - * should be small number about 1E-6 or 1E-7. - * zero value means that solver automatically selects good - value (can be different in different ALGLIB versions) - * default value is zero - Algorithm stops when relative error is less than Eps. - -===== TRACING DSS SOLVER ================================================= - -DSS solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'DSS' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. -* 'DSS.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'DSS'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("DSS,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 08.11.2020 by Bochkanov Sergey -*************************************************************************/ -void minlpsetalgodss(const minlpstate &state, const double eps, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets LP algorithm to sparse interior point method. - -ALGORITHM INFORMATION: - -* this algorithm is our implementation of interior point method as - formulated by R.J.Vanderbei, with minor modifications to the algorithm - (damped Newton directions are extensively used) -* like all interior point methods, this algorithm tends to converge in - roughly same number of iterations (between 15 and 50) independently from - the problem dimensionality - -INPUT PARAMETERS: - State - optimizer - Eps - stopping condition, Eps>=0: - * should be small number about 1E-7 or 1E-8. - * zero value means that solver automatically selects good - value (can be different in different ALGLIB versions) - * default value is zero - Algorithm stops when primal error AND dual error AND - duality gap are less than Eps. - -===== TRACING IPM SOLVER ================================================= - -IPM solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'IPM' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. -* 'IPM.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'IPM'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("IPM,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 08.11.2020 by Bochkanov Sergey -*************************************************************************/ -void minlpsetalgoipm(const minlpstate &state, const double eps, const xparams _xparams = alglib::xdefault); -void minlpsetalgoipm(const minlpstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets cost term for LP solver. - -By default, cost term is zero. - -INPUT PARAMETERS: - State - structure which stores algorithm state - C - cost term, array[N]. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetcost(const minlpstate &state, const real_1d_array &c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets scaling coefficients. - -ALGLIB optimizers use scaling matrices to test stopping conditions and as -preconditioner. - -Scale of the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the - function - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetscale(const minlpstate &state, const real_1d_array &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets box constraints for LP solver (all variables at once, -different constraints for different variables). - -The default state of constraints is to have all variables fixed at zero. -You have to overwrite it by your own constraint vector. Constraint status -is preserved until constraints are explicitly overwritten with another -minlpsetbc() call, overwritten with minlpsetbcall(), or partially -overwritten with minlmsetbci() call. - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd[i] BndL[i]=BndU[i] - lower bound BndL[i]<=x[i] BndU[i]=+INF - upper bound x[i]<=BndU[i] BndL[i]=-INF - range BndL[i]<=x[i]<=BndU[i] ... - free variable - BndL[I]=-INF, BndU[I]+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - BndU - upper bounds, array[N]. - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: if constraints for all variables are same you may use minlpsetbcall() - which allows to specify constraints without using arrays. - -NOTE: BndL>BndU will result in LP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetbc(const minlpstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets box constraints for LP solver (all variables at once, -same constraints for all variables) - -The default state of constraints is to have all variables fixed at zero. -You have to overwrite it by your own constraint vector. Constraint status -is preserved until constraints are explicitly overwritten with another -minlpsetbc() call or partially overwritten with minlpsetbcall(). - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd[i] BndL[i]=BndU[i] - lower bound BndL[i]<=x[i] BndU[i]=+INF - upper bound x[i]<=BndU[i] BndL[i]=-INF - range BndL[i]<=x[i]<=BndU[i] ... - free variable - BndL[I]=-INF, BndU[I]+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bound, same for all variables - BndU - upper bound, same for all variables - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: minlpsetbc() can be used to specify different constraints for - different variables. - -NOTE: BndL>BndU will result in LP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetbcall(const minlpstate &state, const double bndl, const double bndu, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets box constraints for I-th variable (other variables are -not modified). - -The default state of constraints is to have all variables fixed at zero. -You have to overwrite it by your own constraint vector. - -Following types of constraints are supported: - - DESCRIPTION CONSTRAINT HOW TO SPECIFY - fixed variable x[i]=Bnd[i] BndL[i]=BndU[i] - lower bound BndL[i]<=x[i] BndU[i]=+INF - upper bound x[i]<=BndU[i] BndL[i]=-INF - range BndL[i]<=x[i]<=BndU[i] ... - free variable - BndL[I]=-INF, BndU[I]+INF - -INPUT PARAMETERS: - State - structure stores algorithm state - I - variable index, in [0,N) - BndL - lower bound for I-th variable - BndU - upper bound for I-th variable - -NOTE: infinite values can be specified by means of Double.PositiveInfinity - and Double.NegativeInfinity (in C#) and alglib::fp_posinf and - alglib::fp_neginf (in C++). - -NOTE: you may replace infinities by very small/very large values, but it - is not recommended because large numbers may introduce large numerical - errors in the algorithm. - -NOTE: minlpsetbc() can be used to specify different constraints for - different variables. - -NOTE: BndL>BndU will result in LP problem being recognized as infeasible. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetbci(const minlpstate &state, const ae_int_t i, const double bndl, const double bndu, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets one-sided linear constraints A*x ~ AU, where "~" can be -a mix of "<=", "=" and ">=". - -IMPORTANT: this function is provided here for compatibility with the rest - of ALGLIB optimizers which accept constraints in format like - this one. Many real-life problems feature two-sided constraints - like a0 <= a*x <= a1. It is really inefficient to add them as a - pair of one-sided constraints. - - Use minlpsetlc2dense(), minlpsetlc2(), minlpaddlc2() (or its - sparse version) wherever possible. - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - A - linear constraints, array[K,N+1]. Each row of A represents - one constraint, with first N elements being linear coefficients, - and last element being right side. - CT - constraint types, array[K]: - * if CT[i]>0, then I-th constraint is A[i,*]*x >= A[i,n] - * if CT[i]=0, then I-th constraint is A[i,*]*x = A[i,n] - * if CT[i]<0, then I-th constraint is A[i,*]*x <= A[i,n] - K - number of equality/inequality constraints, K>=0; if not - given, inferred from sizes of A and CT. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetlc(const minlpstate &state, const real_2d_array &a, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams = alglib::xdefault); -void minlpsetlc(const minlpstate &state, const real_2d_array &a, const integer_1d_array &ct, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU. - -This version accepts dense matrix as input; internally LP solver uses -sparse storage anyway (most LP problems are sparse), but for your -convenience it may accept dense inputs. This function overwrites linear -constraints set by previous calls (if such calls were made). - -We recommend you to use sparse version of this function unless you solve -small-scale LP problem (less than few hundreds of variables). - -NOTE: there also exist several versions of this function: - * one-sided dense version which accepts constraints in the same - format as one used by QP and NLP solvers - * two-sided sparse version which accepts sparse matrix - * two-sided dense version which allows you to add constraints row by row - * two-sided sparse version which allows you to add constraints row by row - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - A - linear constraints, array[K,N]. Each row of A represents - one constraint. One-sided inequality constraints, two- - sided inequality constraints, equality constraints are - supported (see below) - AL, AU - lower and upper bounds, array[K]; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i] two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0; if not - given, inferred from sizes of A, AL, AU. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetlc2dense(const minlpstate &state, const real_2d_array &a, const real_1d_array &al, const real_1d_array &au, const ae_int_t k, const xparams _xparams = alglib::xdefault); -void minlpsetlc2dense(const minlpstate &state, const real_2d_array &a, const real_1d_array &al, const real_1d_array &au, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets two-sided linear constraints AL <= A*x <= AU with -sparse constraining matrix A. Recommended for large-scale problems. - -This function overwrites linear (non-box) constraints set by previous -calls (if such calls were made). - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - A - sparse matrix with size [K,N] (exactly!). - Each row of A represents one general linear constraint. - A can be stored in any sparse storage format. - AL, AU - lower and upper bounds, array[K]; - * AL[i]=AU[i] => equality constraint Ai*x - * AL[i] two-sided constraint AL[i]<=Ai*x<=AU[i] - * AL[i]=-INF => one-sided constraint Ai*x<=AU[i] - * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x - * AL[i]=-INF, AU[i]=+INF => constraint is ignored - K - number of equality/inequality constraints, K>=0. If K=0 - is specified, A, AL, AU are ignored. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpsetlc2(const minlpstate &state, const sparsematrix &a, const real_1d_array &al, const real_1d_array &au, const ae_int_t k, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function appends two-sided linear constraint AL <= A*x <= AU to the -list of currently present constraints. - -This version accepts dense constraint vector as input, but sparsifies it -for internal storage and processing. Thus, time to add one constraint in -is O(N) - we have to scan entire array of length N. Sparse version of this -function is order of magnitude faster for constraints with just a few -nonzeros per row. - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - A - linear constraint coefficient, array[N], right side is NOT - included. - AL, AU - lower and upper bounds; - * AL=AU => equality constraint Ai*x - * AL two-sided constraint AL<=A*x<=AU - * AL=-INF => one-sided constraint Ai*x<=AU - * AU=+INF => one-sided constraint AL<=Ai*x - * AL=-INF, AU=+INF => constraint is ignored - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpaddlc2dense(const minlpstate &state, const real_1d_array &a, const double al, const double au, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function appends two-sided linear constraint AL <= A*x <= AU to the -list of currently present constraints. - -Constraint is passed in compressed format: as list of non-zero entries of -coefficient vector A. Such approach is more efficient than dense storage -for highly sparse constraint vectors. - -INPUT PARAMETERS: - State - structure previously allocated with minlpcreate() call. - IdxA - array[NNZ], indexes of non-zero elements of A: - * can be unsorted - * can include duplicate indexes (corresponding entries of - ValA[] will be summed) - ValA - array[NNZ], values of non-zero elements of A - NNZ - number of non-zero coefficients in A - AL, AU - lower and upper bounds; - * AL=AU => equality constraint A*x - * AL two-sided constraint AL<=A*x<=AU - * AL=-INF => one-sided constraint A*x<=AU - * AU=+INF => one-sided constraint AL<=A*x - * AL=-INF, AU=+INF => constraint is ignored - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey -*************************************************************************/ -void minlpaddlc2(const minlpstate &state, const integer_1d_array &idxa, const real_1d_array &vala, const ae_int_t nnz, const double al, const double au, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function solves LP problem. - -INPUT PARAMETERS: - State - algorithm state - -You should use minlpresults() function to access results after calls to -this function. - - -- ALGLIB -- - Copyright 19.07.2018 by Bochkanov Sergey. -*************************************************************************/ -void minlpoptimize(const minlpstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -LP solver results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[N], solution (on failure: last trial point) - Rep - optimization report. You should check Rep.TerminationType, - which contains completion code, and you may check another - fields which contain another information about algorithm - functioning. - - Failure codes returned by algorithm are: - * -4 LP problem is primal unbounded (dual infeasible) - * -3 LP problem is primal infeasible (dual unbounded) - * -2 IPM solver detected that problem is either - infeasible or unbounded - - Success codes: - * 1..4 successful completion - * 5 MaxIts steps was taken - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minlpresults(const minlpstate &state, real_1d_array &x, minlpreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -LP results - -Buffered implementation of MinLPResults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 11.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minlpresultsbuf(const minlpstate &state, real_1d_array &x, minlpreport &rep, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_NLCSLP) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MINNLC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - NONLINEARLY CONSTRAINED OPTIMIZATION - WITH PRECONDITIONED AUGMENTED LAGRANGIAN ALGORITHM - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments subject to any -combination of: -* bound constraints -* linear inequality constraints -* linear equality constraints -* nonlinear equality constraints Gi(x)=0 -* nonlinear inequality constraints Hi(x)<=0 - -REQUIREMENTS: -* user must provide function value and gradient for F(), H(), G() -* starting point X0 must be feasible or not too far away from the feasible - set -* F(), G(), H() are continuously differentiable on the feasible set and - its neighborhood -* nonlinear constraints G() and H() must have non-zero gradient at G(x)=0 - and at H(x)=0. Say, constraint like x^2>=1 is supported, but x^2>=0 is - NOT supported. - -USAGE: - -Constrained optimization if far more complex than the unconstrained one. -Nonlinearly constrained optimization is one of the most esoteric numerical -procedures. - -Here we give very brief outline of the MinNLC optimizer. We strongly -recommend you to study examples in the ALGLIB Reference Manual and to read -ALGLIB User Guide on optimization, which is available at -http://www.alglib.net/optimization/ - -1. User initializes algorithm state with MinNLCCreate() call and chooses - what NLC solver to use. There is some solver which is used by default, - with default settings, but you should NOT rely on default choice. It - may change in future releases of ALGLIB without notice, and no one can - guarantee that new solver will be able to solve your problem with - default settings. - - From the other side, if you choose solver explicitly, you can be pretty - sure that it will work with new ALGLIB releases. - - In the current release following solvers can be used: - * SQP solver, recommended for medium-scale problems (less than thousand - of variables) with hard-to-evaluate target functions. Requires less - function evaluations than other solvers but each step involves - solution of QP subproblem, so running time may be higher than that of - AUL (another recommended option). Activated with minnlcsetalgosqp() - function. - * AUL solver with dense preconditioner, recommended for large-scale - problems or for problems with cheap target function. Needs more - function evaluations that SQP (about 5x-10x times more), but its - iterations are much cheaper that that of SQP. Activated with - minnlcsetalgoaul() function. - * SLP solver, successive linear programming. The slowest one, requires - more target function evaluations that SQP and AUL. However, it is - somewhat more robust in tricky cases, so it can be used as a backup - plan. Activated with minnlcsetalgoslp() function. - -2. [optional] user activates OptGuard integrity checker which tries to - detect possible errors in the user-supplied callbacks: - * discontinuity/nonsmoothness of the target/nonlinear constraints - * errors in the analytic gradient provided by user - This feature is essential for early prototyping stages because it helps - to catch common coding and problem statement errors. - OptGuard can be activated with following functions (one per each check - performed): - * minnlcoptguardsmoothness() - * minnlcoptguardgradient() - -3. User adds boundary and/or linear and/or nonlinear constraints by means - of calling one of the following functions: - a) minnlcsetbc() for boundary constraints - b) minnlcsetlc() for linear constraints - c) minnlcsetnlc() for nonlinear constraints - You may combine (a), (b) and (c) in one optimization problem. - -4. User sets scale of the variables with minnlcsetscale() function. It is - VERY important to set scale of the variables, because nonlinearly - constrained problems are hard to solve when variables are badly scaled. - -5. User sets stopping conditions with minnlcsetcond(). If NLC solver - uses inner/outer iteration layout, this function sets stopping - conditions for INNER iterations. - -6. Finally, user calls minnlcoptimize() function which takes algorithm - state and pointer (delegate, etc.) to callback function which calculates - F/G/H. - -7. User calls minnlcresults() to get solution; additionally you can - retrieve OptGuard report with minnlcoptguardresults(), and get detailed - report about purported errors in the target function with: - * minnlcoptguardnonc1test0results() - * minnlcoptguardnonc1test1results() - -8. Optionally user may call minnlcrestartfrom() to solve another problem - with same N but another starting point. minnlcrestartfrom() allows to - reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size ofX - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlccreate(const ae_int_t n, const real_1d_array &x, minnlcstate &state, const xparams _xparams = alglib::xdefault); -void minnlccreate(const real_1d_array &x, minnlcstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine is a finite difference variant of MinNLCCreate(). It uses -finite differences in order to differentiate target function. - -Description below contains information which is specific to this function -only. We recommend to read comments on MinNLCCreate() in order to get more -information about creation of NLC optimizer. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size ofX - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinNLCSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large TRUNCATION errors, while too small - step will result in too large NUMERICAL errors. 1.0E-4 can be good - value to start from. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. Imprecise gradient may slow down - convergence, especially on highly nonlinear problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlccreatef(const ae_int_t n, const real_1d_array &x, const double diffstep, minnlcstate &state, const xparams _xparams = alglib::xdefault); -void minnlccreatef(const real_1d_array &x, const double diffstep, minnlcstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets boundary constraints for NLC optimizer. - -Boundary constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with MinNLCRestartFrom(). - -You may combine boundary constraints with general linear ones - and with -nonlinear ones! Boundary constraints are handled more efficiently than -other types. Thus, if your problem has mixed constraints, you may -explicitly specify some of them as boundary and save some time/space. - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF. - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF. - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - -NOTE 2: when you solve your problem with augmented Lagrangian solver, - boundary constraints are satisfied only approximately! It is - possible that algorithm will evaluate function outside of - feasible area! - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetbc(const minnlcstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets linear constraints for MinNLC optimizer. - -Linear constraints are inactive by default (after initial creation). They -are preserved after algorithm restart with MinNLCRestartFrom(). - -You may combine linear constraints with boundary ones - and with nonlinear -ones! If your problem has mixed constraints, you may explicitly specify -some of them as linear. It may help optimizer to handle them more -efficiently. - -INPUT PARAMETERS: - State - structure previously allocated with MinNLCCreate call. - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -NOTE 1: when you solve your problem with augmented Lagrangian solver, - linear constraints are satisfied only approximately! It is - possible that algorithm will evaluate function outside of - feasible area! - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetlc(const minnlcstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams = alglib::xdefault); -void minnlcsetlc(const minnlcstate &state, const real_2d_array &c, const integer_1d_array &ct, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets nonlinear constraints for MinNLC optimizer. - -In fact, this function sets NUMBER of nonlinear constraints. Constraints -itself (constraint functions) are passed to MinNLCOptimize() method. This -method requires user-defined vector function F[] and its Jacobian J[], -where: -* first component of F[] and first row of Jacobian J[] corresponds to - function being minimized -* next NLEC components of F[] (and rows of J) correspond to nonlinear - equality constraints G_i(x)=0 -* next NLIC components of F[] (and rows of J) correspond to nonlinear - inequality constraints H_i(x)<=0 - -NOTE: you may combine nonlinear constraints with linear/boundary ones. If - your problem has mixed constraints, you may explicitly specify some - of them as linear ones. It may help optimizer to handle them more - efficiently. - -INPUT PARAMETERS: - State - structure previously allocated with MinNLCCreate call. - NLEC - number of Non-Linear Equality Constraints (NLEC), >=0 - NLIC - number of Non-Linear Inquality Constraints (NLIC), >=0 - -NOTE 1: when you solve your problem with augmented Lagrangian solver, - nonlinear constraints are satisfied only approximately! It is - possible that algorithm will evaluate function outside of - feasible area! - -NOTE 2: algorithm scales variables according to scale specified by - MinNLCSetScale() function, so it can handle problems with badly - scaled variables (as long as we KNOW their scales). - - However, there is no way to automatically scale nonlinear - constraints Gi(x) and Hi(x). Inappropriate scaling of Gi/Hi may - ruin convergence. Solving problem with constraint "1000*G0(x)=0" - is NOT same as solving it with constraint "0.001*G0(x)=0". - - It means that YOU are the one who is responsible for correct - scaling of nonlinear constraints Gi(x) and Hi(x). We recommend you - to scale nonlinear constraints in such way that I-th component of - dG/dX (or dH/dx) has approximately unit magnitude (for problems - with unit scale) or has magnitude approximately equal to 1/S[i] - (where S is a scale set by MinNLCSetScale() function). - - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetnlc(const minnlcstate &state, const ae_int_t nlec, const ae_int_t nlic, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets stopping conditions for inner iterations of optimizer. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - step vector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinNLCSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic -selection of the stopping condition. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetcond(const minnlcstate &state, const double epsx, const ae_int_t maxits, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets scaling coefficients for NLC optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of the optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetscale(const minnlcstate &state, const real_1d_array &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets preconditioner to "inexact LBFGS-based" mode. - -Preconditioning is very important for convergence of Augmented Lagrangian -algorithm because presence of penalty term makes problem ill-conditioned. -Difference between performance of preconditioned and unpreconditioned -methods can be as large as 100x! - -MinNLC optimizer may use following preconditioners, each with its own -benefits and drawbacks: - a) inexact LBFGS-based, with O(N*K) evaluation time - b) exact low rank one, with O(N*K^2) evaluation time - c) exact robust one, with O(N^3+K*N^2) evaluation time -where K is a total number of general linear and nonlinear constraints (box -ones are not counted). - -Inexact LBFGS-based preconditioner uses L-BFGS formula combined with -orthogonality assumption to perform very fast updates. For a N-dimensional -problem with K general linear or nonlinear constraints (boundary ones are -not counted) it has O(N*K) cost per iteration. This preconditioner has -best quality (less iterations) when general linear and nonlinear -constraints are orthogonal to each other (orthogonality with respect to -boundary constraints is not required). Number of iterations increases when -constraints are non-orthogonal, because algorithm assumes orthogonality, -but still it is better than no preconditioner at all. - -INPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 26.09.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetprecinexact(const minnlcstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets preconditioner to "exact low rank" mode. - -Preconditioning is very important for convergence of Augmented Lagrangian -algorithm because presence of penalty term makes problem ill-conditioned. -Difference between performance of preconditioned and unpreconditioned -methods can be as large as 100x! - -MinNLC optimizer may use following preconditioners, each with its own -benefits and drawbacks: - a) inexact LBFGS-based, with O(N*K) evaluation time - b) exact low rank one, with O(N*K^2) evaluation time - c) exact robust one, with O(N^3+K*N^2) evaluation time -where K is a total number of general linear and nonlinear constraints (box -ones are not counted). - -It also provides special unpreconditioned mode of operation which can be -used for test purposes. Comments below discuss low rank preconditioner. - -Exact low-rank preconditioner uses Woodbury matrix identity to build -quadratic model of the penalized function. It has following features: -* no special assumptions about orthogonality of constraints -* preconditioner evaluation is optimized for K<=N. -* finally, stability of the process is guaranteed only for K<=N due to degeneracy of intermediate matrices. - That's why we recommend to use "exact robust" preconditioner for such - cases. - -RECOMMENDATIONS - -We recommend to choose between "exact low rank" and "exact robust" -preconditioners, with "low rank" version being chosen when you know in -advance that total count of non-box constraints won't exceed N, and "robust" -version being chosen when you need bulletproof solution. - -INPUT PARAMETERS: - State - structure stores algorithm state - UpdateFreq- update frequency. Preconditioner is rebuilt after every - UpdateFreq iterations. Recommended value: 10 or higher. - Zero value means that good default value will be used. - - -- ALGLIB -- - Copyright 26.09.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetprecexactlowrank(const minnlcstate &state, const ae_int_t updatefreq, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets preconditioner to "exact robust" mode. - -Preconditioning is very important for convergence of Augmented Lagrangian -algorithm because presence of penalty term makes problem ill-conditioned. -Difference between performance of preconditioned and unpreconditioned -methods can be as large as 100x! - -MinNLC optimizer may use following preconditioners, each with its own -benefits and drawbacks: - a) inexact LBFGS-based, with O(N*K) evaluation time - b) exact low rank one, with O(N*K^2) evaluation time - c) exact robust one, with O(N^3+K*N^2) evaluation time -where K is a total number of general linear and nonlinear constraints (box -ones are not counted). - -It also provides special unpreconditioned mode of operation which can be -used for test purposes. Comments below discuss robust preconditioner. - -Exact robust preconditioner uses Cholesky decomposition to invert -approximate Hessian matrix H=D+W'*C*W (where D stands for diagonal terms -of Hessian, combined result of initial scaling matrix and penalty from box -constraints; W stands for general linear constraints and linearization of -nonlinear ones; C stands for diagonal matrix of penalty coefficients). - -This preconditioner has following features: -* no special assumptions about constraint structure -* preconditioner is optimized for stability; unlike "exact low rank" - version which fails for K>=N, this one works well for any value of K. -* the only drawback is that is takes O(N^3+K*N^2) time to build it. No - economical Woodbury update is applied even when it makes sense, thus - there are exist situations (K<=0. Set StpMax to 0.0 (default), if - you don't want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which leads to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - -NOTE: different solvers employed by MinNLC optimizer use different norms - for step; AUL solver uses 2-norm, whilst SLP solver uses INF-norm. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetstpmax(const minnlcstate &state, const double stpmax, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function tells MinNLC unit to use Augmented Lagrangian algorithm -for nonlinearly constrained optimization. This algorithm is a slight -modification of one described in "A Modified Barrier-Augmented Lagrangian -Method for Constrained Minimization (1999)" by D.GOLDFARB, R.POLYAK, -K. SCHEINBERG, I.YUZEFOVICH. - -AUL solver can be significantly faster than SQP on easy problems due to -cheaper iterations, although it needs more function evaluations. - -Augmented Lagrangian algorithm works by converting problem of minimizing -F(x) subject to equality/inequality constraints to unconstrained problem -of the form - - min[ f(x) + - + Rho*PENALTY_EQ(x) + SHIFT_EQ(x,Nu1) + - + Rho*PENALTY_INEQ(x) + SHIFT_INEQ(x,Nu2) ] - -where: -* Rho is a fixed penalization coefficient -* PENALTY_EQ(x) is a penalty term, which is used to APPROXIMATELY enforce - equality constraints -* SHIFT_EQ(x) is a special "shift" term which is used to "fine-tune" - equality constraints, greatly increasing precision -* PENALTY_INEQ(x) is a penalty term which is used to approximately enforce - inequality constraints -* SHIFT_INEQ(x) is a special "shift" term which is used to "fine-tune" - inequality constraints, greatly increasing precision -* Nu1/Nu2 are vectors of Lagrange coefficients which are fine-tuned during - outer iterations of algorithm - -This version of AUL algorithm uses preconditioner, which greatly -accelerates convergence. Because this algorithm is similar to penalty -methods, it may perform steps into infeasible area. All kinds of -constraints (boundary, linear and nonlinear ones) may be violated in -intermediate points - and in the solution. However, properly configured -AUL method is significantly better at handling constraints than barrier -and/or penalty methods. - -The very basic outline of algorithm is given below: -1) first outer iteration is performed with "default" values of Lagrange - multipliers Nu1/Nu2. Solution quality is low (candidate point can be - too far away from true solution; large violation of constraints is - possible) and is comparable with that of penalty methods. -2) subsequent outer iterations refine Lagrange multipliers and improve - quality of the solution. - -INPUT PARAMETERS: - State - structure which stores algorithm state - Rho - penalty coefficient, Rho>0: - * large enough that algorithm converges with desired - precision. Minimum value is 10*max(S'*diag(H)*S), where - S is a scale matrix (set by MinNLCSetScale) and H is a - Hessian of the function being minimized. If you can not - easily estimate Hessian norm, see our recommendations - below. - * not TOO large to prevent ill-conditioning - * for unit-scale problems (variables and Hessian have unit - magnitude), Rho=100 or Rho=1000 can be used. - * it is important to note that Rho is internally multiplied - by scaling matrix, i.e. optimum value of Rho depends on - scale of variables specified by MinNLCSetScale(). - ItsCnt - number of outer iterations: - * ItsCnt=0 means that small number of outer iterations is - automatically chosen (10 iterations in current version). - * ItsCnt=1 means that AUL algorithm performs just as usual - barrier method. - * ItsCnt>1 means that AUL algorithm performs specified - number of outer iterations - -HOW TO CHOOSE PARAMETERS - -Nonlinear optimization is a tricky area and Augmented Lagrangian algorithm -is sometimes hard to tune. Good values of Rho and ItsCnt are problem- -specific. In order to help you we prepared following set of -recommendations: - -* for unit-scale problems (variables and Hessian have unit magnitude), - Rho=100 or Rho=1000 can be used. - -* start from some small value of Rho and solve problem with just one - outer iteration (ItcCnt=1). In this case algorithm behaves like penalty - method. Increase Rho in 2x or 10x steps until you see that one outer - iteration returns point which is "rough approximation to solution". - - It is very important to have Rho so large that penalty term becomes - constraining i.e. modified function becomes highly convex in constrained - directions. - - From the other side, too large Rho may prevent you from converging to - the solution. You can diagnose it by studying number of inner iterations - performed by algorithm: too few (5-10 on 1000-dimensional problem) or - too many (orders of magnitude more than dimensionality) usually means - that Rho is too large. - -* with just one outer iteration you usually have low-quality solution. - Some constraints can be violated with very large margin, while other - ones (which are NOT violated in the true solution) can push final point - too far in the inner area of the feasible set. - - For example, if you have constraint x0>=0 and true solution x0=1, then - merely a presence of "x0>=0" will introduce a bias towards larger values - of x0. Say, algorithm may stop at x0=1.5 instead of 1.0. - -* after you found good Rho, you may increase number of outer iterations. - ItsCnt=10 is a good value. Subsequent outer iteration will refine values - of Lagrange multipliers. Constraints which were violated will be - enforced, inactive constraints will be dropped (corresponding multipliers - will be decreased). Ideally, you should see 10-1000x improvement in - constraint handling (constraint violation is reduced). - -* if you see that algorithm converges to vicinity of solution, but - additional outer iterations do not refine solution, it may mean that - algorithm is unstable - it wanders around true solution, but can not - approach it. Sometimes algorithm may be stabilized by increasing Rho one - more time, making it 5x or 10x larger. - -SCALING OF CONSTRAINTS [IMPORTANT] - -AUL optimizer scales variables according to scale specified by -MinNLCSetScale() function, so it can handle problems with badly scaled -variables (as long as we KNOW their scales). However, because function -being optimized is a mix of original function and constraint-dependent -penalty functions, it is important to rescale both variables AND -constraints. - -Say, if you minimize f(x)=x^2 subject to 1000000*x>=0, then you have -constraint whose scale is different from that of target function (another -example is 0.000001*x>=0). It is also possible to have constraints whose -scales are misaligned: 1000000*x0>=0, 0.000001*x1<=0. Inappropriate -scaling may ruin convergence because minimizing x^2 subject to x>=0 is NOT -same as minimizing it subject to 1000000*x>=0. - -Because we know coefficients of boundary/linear constraints, we can -automatically rescale and normalize them. However, there is no way to -automatically rescale nonlinear constraints Gi(x) and Hi(x) - they are -black boxes. - -It means that YOU are the one who is responsible for correct scaling of -nonlinear constraints Gi(x) and Hi(x). We recommend you to rescale -nonlinear constraints in such way that I-th component of dG/dX (or dH/dx) -has magnitude approximately equal to 1/S[i] (where S is a scale set by -MinNLCSetScale() function). - -WHAT IF IT DOES NOT CONVERGE? - -It is possible that AUL algorithm fails to converge to precise values of -Lagrange multipliers. It stops somewhere around true solution, but candidate -point is still too far from solution, and some constraints are violated. -Such kind of failure is specific for Lagrangian algorithms - technically, -they stop at some point, but this point is not constrained solution. - -There are exist several reasons why algorithm may fail to converge: -a) too loose stopping criteria for inner iteration -b) degenerate, redundant constraints -c) target function has unconstrained extremum exactly at the boundary of - some constraint -d) numerical noise in the target function - -In all these cases algorithm is unstable - each outer iteration results in -large and almost random step which improves handling of some constraints, -but violates other ones (ideally outer iterations should form a sequence -of progressively decreasing steps towards solution). - -First reason possible is that too loose stopping criteria for inner -iteration were specified. Augmented Lagrangian algorithm solves a sequence -of intermediate problems, and requries each of them to be solved with high -precision. Insufficient precision results in incorrect update of Lagrange -multipliers. - -Another reason is that you may have specified degenerate constraints: say, -some constraint was repeated twice. In most cases AUL algorithm gracefully -handles such situations, but sometimes it may spend too much time figuring -out subtle degeneracies in constraint matrix. - -Third reason is tricky and hard to diagnose. Consider situation when you -minimize f=x^2 subject to constraint x>=0. Unconstrained extremum is -located exactly at the boundary of constrained area. In this case -algorithm will tend to oscillate between negative and positive x. Each -time it stops at x<0 it "reinforces" constraint x>=0, and each time it is -bounced to x>0 it "relaxes" constraint (and is attracted to x<0). - -Such situation sometimes happens in problems with hidden symetries. -Algorithm is got caught in a loop with Lagrange multipliers being -continuously increased/decreased. Luckily, such loop forms after at least -three iterations, so this problem can be solved by DECREASING number of -outer iterations down to 1-2 and increasing penalty coefficient Rho as -much as possible. - -Final reason is numerical noise. AUL algorithm is robust against moderate -noise (more robust than, say, active set methods), but large noise may -destabilize algorithm. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetalgoaul(const minnlcstate &state, const double rho, const ae_int_t itscnt, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function tells MinNLC optimizer to use SLP (Successive Linear -Programming) algorithm for nonlinearly constrained optimization. This -algorithm is a slight modification of one described in "A Linear -programming-based optimization algorithm for solving nonlinear programming -problems" (2010) by Claus Still and Tapio Westerlund. - -This solver is the slowest one in ALGLIB, it requires more target function -evaluations that SQP and AUL. However it is somewhat more robust in tricky -cases, so it can be used as a backup plan. We recommend to use this algo -when SQP/AUL do not work (does not return the solution you expect). If -trying different approach gives same results, then MAYBE something is -wrong with your optimization problem. - -Despite its name ("linear" = "first order method") this algorithm performs -steps similar to that of conjugate gradients method; internally it uses -orthogonality/conjugacy requirement for subsequent steps which makes it -closer to second order methods in terms of convergence speed. - -Convergence is proved for the following case: -* function and constraints are continuously differentiable (C1 class) -* extended Mangasarian–Fromovitz constraint qualification (EMFCQ) holds; - in the context of this algorithm EMFCQ means that one can, for any - infeasible point, find a search direction such that the constraint - infeasibilities are reduced. - -This algorithm has following nice properties: -* no parameters to tune -* no convexity requirements for target function or constraints -* initial point can be infeasible -* algorithm respects box constraints in all intermediate points (it does - not even evaluate function outside of box constrained area) -* once linear constraints are enforced, algorithm will not violate them -* no such guarantees can be provided for nonlinear constraints, but once - nonlinear constraints are enforced, algorithm will try to respect them - as much as possible -* numerical differentiation does not violate box constraints (although - general linear and nonlinear ones can be violated during differentiation) -* from our experience, this algorithm is somewhat more robust in really - difficult cases - -INPUT PARAMETERS: - State - structure which stores algorithm state - -===== TRACING SLP SOLVER ================================================= - -SLP solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'SLP' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. - It also prints OptGuard integrity checker report when - nonsmoothness of target/constraints is suspected. -* 'SLP.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'SLP'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format -* 'SLP.PROBING' - to let algorithm insert additional function evaluations - before line search in order to build human-readable - chart of the raw Lagrangian (~40 additional function - evaluations is performed for each line search). This - symbol also implicitly defines 'SLP'. -* 'OPTGUARD' - for report of smoothness/continuity violations in target - and/or constraints. This kind of reporting is included - in 'SLP', but it comes with lots of additional info. If - you need just smoothness monitoring, specify this - setting. - - NOTE: this tag merely directs OptGuard output to log - file. Even if you specify it, you still have to - configure OptGuard by calling minnlcoptguard...() - family of functions. - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. Specifying 'SLP.PROBING' adds even larger -overhead due to additional function evaluations being performed. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("SLP,SLP.PROBING,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 02.04.2018 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetalgoslp(const minnlcstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function tells MinNLC optimizer to use SQP (Successive Quadratic -Programming) algorithm for nonlinearly constrained optimization. - -This algorithm needs order of magnitude (5x-10x) less function evaluations -than AUL solver, but has higher overhead because each iteration involves -solution of quadratic programming problem. - -Convergence is proved for the following case: -* function and constraints are continuously differentiable (C1 class) - -This algorithm has following nice properties: -* no parameters to tune -* no convexity requirements for target function or constraints -* initial point can be infeasible -* algorithm respects box constraints in all intermediate points (it does - not even evaluate function outside of box constrained area) -* once linear constraints are enforced, algorithm will not violate them -* no such guarantees can be provided for nonlinear constraints, but once - nonlinear constraints are enforced, algorithm will try to respect them - as much as possible -* numerical differentiation does not violate box constraints (although - general linear and nonlinear ones can be violated during differentiation) - -We recommend this algorithm as a default option for medium-scale problems -(less than thousand of variables) or problems with target function being -hard to evaluate. - -For large-scale problems or ones with very cheap target function -AUL solver can be better option. - -INPUT PARAMETERS: - State - structure which stores algorithm state - -===== INTERACTION WITH OPTGUARD ========================================== - -OptGuard integrity checker allows us to catch problems like errors in -gradients and discontinuity/nonsmoothness of the target/constraints. -Latter kind of problems can be detected by looking upon line searches -performed during optimization and searching for signs of nonsmoothness. - -The problem with SQP is that it is too good for OptGuard to work - it does -not perform line searches. It typically needs 1-2 function evaluations -per step, and it is not enough for OptGuard to detect nonsmoothness. - -So, if you suspect that your problem is nonsmooth, we recommend you to use -AUL or SLP solvers. - -===== TRACING SQP SOLVER ================================================= - -SQP solver supports advanced tracing capabilities. You can trace algorithm -output by specifying following trace symbols (case-insensitive) by means -of trace_file() call: -* 'SQP' - for basic trace of algorithm steps and decisions. Only - short scalars (function values and deltas) are printed. - N-dimensional quantities like search directions are NOT - printed. - It also prints OptGuard integrity checker report when - nonsmoothness of target/constraints is suspected. -* 'SQP.DETAILED'- for output of points being visited and search directions - This symbol also implicitly defines 'SQP'. You can - control output format by additionally specifying: - * nothing to output in 6-digit exponential format - * 'PREC.E15' to output in 15-digit exponential format - * 'PREC.F6' to output in 6-digit fixed-point format -* 'SQP.PROBING' - to let algorithm insert additional function evaluations - before line search in order to build human-readable - chart of the raw Lagrangian (~40 additional function - evaluations is performed for each line search). This - symbol also implicitly defines 'SQP' and activates - OptGuard integrity checker which detects continuity and - smoothness violations. An OptGuard log is printed at the - end of the file. - -By default trace is disabled and adds no overhead to the optimization -process. However, specifying any of the symbols adds some formatting and -output-related overhead. Specifying 'SQP.PROBING' adds even larger -overhead due to additional function evaluations being performed. - -You may specify multiple symbols by separating them with commas: -> -> alglib::trace_file("SQP,SQP.PROBING,PREC.F6", "path/to/trace.log") -> - - -- ALGLIB -- - Copyright 02.12.2019 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetalgosqp(const minnlcstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinNLCOptimize(). - -NOTE: algorithm passes two parameters to rep() callback - current point - and penalized function value at current point. Important - function - value which is returned is NOT function being minimized. It is sum - of the value of the function being minimized - and penalty term. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minnlcsetxrep(const minnlcstate &state, const bool needxrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool minnlciteration(const minnlcstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This family of functions is used to launcn iterations of nonlinear optimizer - -These functions accept following parameters: - state - algorithm state - fvec - callback which calculates function vector fi[] - at given point x - jac - callback which calculates function vector fi[] - and Jacobian jac at given point x - rep - optional callback which is called after each iteration - can be NULL - ptr - optional pointer which is passed to func/grad/hess/jac/rep - can be NULL - - -NOTES: - -1. This function has two different implementations: one which uses exact - (analytical) user-supplied Jacobian, and one which uses only function - vector and numerically differentiates function in order to obtain - gradient. - - Depending on the specific function used to create optimizer object - you should choose appropriate variant of MinNLCOptimize() - one which - accepts function AND Jacobian or one which accepts ONLY function. - - Be careful to choose variant of MinNLCOptimize() which corresponds to - your optimization scheme! Table below lists different combinations of - callback (function/gradient) passed to MinNLCOptimize() and specific - function used to create optimizer. - - - | USER PASSED TO MinNLCOptimize() - CREATED WITH | function only | function and gradient - ------------------------------------------------------------ - MinNLCCreateF() | works FAILS - MinNLCCreate() | FAILS works - - Here "FAILS" denotes inappropriate combinations of optimizer creation - function and MinNLCOptimize() version. Attemps to use such - combination will lead to exception. Either you did not pass gradient - when it WAS needed or you passed gradient when it was NOT needed. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey - -*************************************************************************/ -void minnlcoptimize(minnlcstate &state, - void (*fvec)(const real_1d_array &x, real_1d_array &fi, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void minnlcoptimize(minnlcstate &state, - void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic gradient/Jacobian. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function (constraints) at the -initial point (note: future versions may also perform check at the final -point) and compares numerical gradient/Jacobian with analytic one provided -by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both gradients/Jacobians, and specific components highlighted -as suspicious by the OptGuard. - -The primary OptGuard report can be retrieved with minnlcoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with minnlcsetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcoptguardgradient(const minnlcstate &state, const double teststep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) and/or constraints -b) nonsmooth target function (non-C1) and/or constraints - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - This kind of monitoring does not work well with SQP - because SQP solver needs just 1-2 function evaluations - per step, which is not enough for OptGuard to make - any conclusions. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minnlcoptguardsmoothness(const minnlcstate &state, const ae_int_t level, const xparams _xparams = alglib::xdefault); -void minnlcoptguardsmoothness(const minnlcstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -=== PRIMARY REPORT ======================================================= - -OptGuard performs several checks which are intended to catch common errors -in the implementation of nonlinear function/gradient: -* incorrect analytic gradient -* discontinuous (non-C0) target functions (constraints) -* nonsmooth (non-C1) target functions (constraints) - -Each of these checks is activated with appropriate function: -* minnlcoptguardgradient() for gradient verification -* minnlcoptguardsmoothness() for C0/C1 checks - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradfidx for specific function (Jacobian row) suspected - * rep.badgradvidx for specific variable (Jacobian column) suspected - * rep.badgradxbase, a point where gradient/Jacobian is tested - * rep.badgraduser, user-provided gradient/Jacobian - * rep.badgradnum, reference gradient/Jacobian obtained via numerical - differentiation -* rep.nonc0suspected, and additionally: - * rep.nonc0fidx - an index of specific function violating C0 continuity -* rep.nonc1suspected, and additionally - * rep.nonc1fidx - an index of specific function violating C1 continuity -Here function index 0 means target function, index 1 or higher denotes -nonlinear constraints. - -=== ADDITIONAL REPORTS/LOGS ============================================== - -Several different tests are performed to catch C0/C1 errors, you can find -out specific test signaled error by looking to: -* rep.nonc0test0positive, for non-C0 test #0 -* rep.nonc1test0positive, for non-C1 test #0 -* rep.nonc1test1positive, for non-C1 test #1 - -Additional information (including line search logs) can be obtained by -means of: -* minnlcoptguardnonc1test0results() -* minnlcoptguardnonc1test1results() -which return detailed error reports, specific points where discontinuities -were found, and so on. - -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - generic OptGuard report; more detailed reports can be - retrieved with other functions. - -NOTE: false negatives (nonsmooth problems are not identified as nonsmooth - ones) are possible although unlikely. - - The reason is that you need to make several evaluations around - nonsmoothness in order to accumulate enough information about - function curvature. Say, if you start right from the nonsmooth point, - optimizer simply won't get enough data to understand what is going - wrong before it terminates due to abrupt changes in the derivative. - It is also possible that "unlucky" step will move us to the - termination too quickly. - - Our current approach is to have less than 0.1% false negatives in - our test examples (measured with multiple restarts from random - points), and to have exactly 0% false positives. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minnlcoptguardresults(const minnlcstate &state, optguardreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #0 - -Nonsmoothness (non-C1) test #0 studies function values (not gradient!) -obtained during line searches and monitors behavior of the directional -derivative estimate. - -This test is less powerful than test #1, but it does not depend on the -gradient values and thus it is more robust against artifacts introduced by -numerical differentiation. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* fidx - is an index of the function (0 for target function, 1 or higher - for nonlinear constraints) which is suspected of being "non-C1" -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #0 "strong" report - lngrep - C1 test #0 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minnlcoptguardnonc1test0results(const minnlcstate &state, optguardnonc1test0report &strrep, optguardnonc1test0report &lngrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #1 - -Nonsmoothness (non-C1) test #1 studies individual components of the -gradient computed during line search. - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* fidx - is an index of the function (0 for target function, 1 or higher - for nonlinear constraints) which is suspected of being "non-C1" -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #1 "strong" report - lngrep - C1 test #1 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minnlcoptguardnonc1test1results(const minnlcstate &state, optguardnonc1test1report &strrep, optguardnonc1test1report &lngrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -MinNLC results: the solution found, completion codes and additional -information. - -If you activated OptGuard integrity checking functionality and want to get -OptGuard report, it can be retrieved with: -* minnlcoptguardresults() - for a primary report about (a) suspected C0/C1 - continuity violations and (b) errors in the analytic gradient. -* minnlcoptguardnonc1test0results() - for C1 continuity violation test #0, - detailed line search log -* minnlcoptguardnonc1test1results() - for C1 continuity violation test #1, - detailed line search log - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report, contains information about completion - code, constraint violation at the solution and so on. - - You should check rep.terminationtype in order to - distinguish successful termination from unsuccessful one: - - === FAILURE CODES === - * -8 internal integrity control detected infinite or - NAN values in function/gradient. Abnormal - termination signalled. - * -3 box constraints are infeasible. - Note: infeasibility of non-box constraints does - NOT trigger emergency completion; you have - to examine rep.bcerr/rep.lcerr/rep.nlcerr to - detect possibly inconsistent constraints. - - === SUCCESS CODES === - * 2 scaled step is no more than EpsX. - * 5 MaxIts steps were taken. - * 8 user requested algorithm termination via - minnlcrequesttermination(), last accepted point is - returned. - - More information about fields of this structure can be - found in the comments on minnlcreport datatype. - - -- ALGLIB -- - Copyright 06.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcresults(const minnlcstate &state, real_1d_array &x, minnlcreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -NLC results - -Buffered implementation of MinNLCResults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minnlcresultsbuf(const minnlcstate &state, real_1d_array &x, minnlcreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void minnlcrequesttermination(const minnlcstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine restarts algorithm from new point. -All optimization parameters (including constraints) are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure previously allocated with MinNLCCreate call. - X - new starting point. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minnlcrestartfrom(const minnlcstate &state, const real_1d_array &x, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_MINBC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - BOX CONSTRAINED OPTIMIZATION - WITH FAST ACTIVATION OF MULTIPLE BOX CONSTRAINTS - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments subject to box -constraints (with some of box constraints actually being equality ones). - -This optimizer uses algorithm similar to that of MinBLEIC (optimizer with -general linear constraints), but presence of box-only constraints allows -us to use faster constraint activation strategies. On large-scale problems, -with multiple constraints active at the solution, this optimizer can be -several times faster than BLEIC. - -REQUIREMENTS: -* user must provide function value and gradient -* starting point X0 must be feasible or - not too far away from the feasible set -* grad(f) must be Lipschitz continuous on a level set: - L = { x : f(x)<=f(x0) } -* function must be defined everywhere on the feasible set F - -USAGE: - -Constrained optimization if far more complex than the unconstrained one. -Here we give very brief outline of the BC optimizer. We strongly recommend -you to read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide -on optimization, which is available at http://www.alglib.net/optimization/ - -1. User initializes algorithm state with MinBCCreate() call - -2. USer adds box constraints by calling MinBCSetBC() function. - -3. User sets stopping conditions with MinBCSetCond(). - -4. User calls MinBCOptimize() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. - -5. User calls MinBCResults() to get solution - -6. Optionally user may call MinBCRestartFrom() to solve another problem - with same N but another starting point. - MinBCRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size ofX - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbccreate(const ae_int_t n, const real_1d_array &x, minbcstate &state, const xparams _xparams = alglib::xdefault); -void minbccreate(const real_1d_array &x, minbcstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -The subroutine is finite difference variant of MinBCCreate(). It uses -finite differences in order to differentiate target function. - -Description below contains information which is specific to this function -only. We recommend to read comments on MinBCCreate() in order to get -more information about creation of BC optimizer. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[0..N-1]. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinBCSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large truncation errors, while too small - step will result in too large numerical errors. 1.0E-6 can be good - value to start with. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. CG needs exact gradient values. Imprecise - gradient may slow down convergence, especially on highly nonlinear - problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -void minbccreatef(const ae_int_t n, const real_1d_array &x, const double diffstep, minbcstate &state, const xparams _xparams = alglib::xdefault); -void minbccreatef(const real_1d_array &x, const double diffstep, minbcstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets boundary constraints for BC optimizer. - -Boundary constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with MinBCRestartFrom(). - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF. - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF. - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - -NOTE 2: this solver has following useful properties: -* bound constraints are always satisfied exactly -* function is evaluated only INSIDE area specified by bound constraints, - even when numerical differentiation is used (algorithm adjusts nodes - according to boundary constraints) - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcsetbc(const minbcstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets stopping conditions for the optimizer. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|=0 - The subroutine finishes its work if on k+1-th iteration - the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - is satisfied. - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - step vector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinBCSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead -to automatic stopping criterion selection. - -NOTE: when SetCond() called with non-zero MaxIts, BC solver may perform - slightly more than MaxIts iterations. I.e., MaxIts sets non-strict - limit on iterations count. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcsetcond(const minbcstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets scaling coefficients for BC optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of the optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -In most optimizers (and in the BC too) scaling is NOT a form of -preconditioning. It just affects stopping conditions. You should set -preconditioner by separate call to one of the MinBCSetPrec...() -functions. - -There is a special preconditioning mode, however, which uses scaling -coefficients to form diagonal preconditioning matrix. You can turn this -mode on, if you want. But you should understand that scaling is not the -same thing as preconditioning - these are two different, although related -forms of tuning solver. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minbcsetscale(const minbcstate &state, const real_1d_array &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Modification of the preconditioner: preconditioning is turned off. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcsetprecdefault(const minbcstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Modification of the preconditioner: diagonal of approximate Hessian is -used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - D - diagonal of the approximate Hessian, array[0..N-1], - (if larger, only leading N elements are used). - -NOTE 1: D[i] should be positive. Exception will be thrown otherwise. - -NOTE 2: you should pass diagonal of approximate Hessian - NOT ITS INVERSE. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcsetprecdiag(const minbcstate &state, const real_1d_array &d, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Modification of the preconditioner: scale-based diagonal preconditioning. - -This preconditioning mode can be useful when you don't have approximate -diagonal of Hessian, but you know that your variables are badly scaled -(for example, one variable is in [1,10], and another in [1000,100000]), -and most part of the ill-conditioning comes from different scales of vars. - -In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2), -can greatly improve convergence. - -IMPRTANT: you should set scale of your variables with MinBCSetScale() -call (before or after MinBCSetPrecScale() call). Without knowledge of -the scale of your variables scale-based preconditioner will be just unit -matrix. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcsetprecscale(const minbcstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinBCOptimize(). - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcsetxrep(const minbcstate &state, const bool needxrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which lead to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcsetstpmax(const minbcstate &state, const double stpmax, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool minbciteration(const minbcstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This family of functions is used to launcn iterations of nonlinear optimizer - -These functions accept following parameters: - state - algorithm state - func - callback which calculates function (or merit function) - value func at given point x - grad - callback which calculates function (or merit function) - value func and gradient grad at given point x - rep - optional callback which is called after each iteration - can be NULL - ptr - optional pointer which is passed to func/grad/hess/jac/rep - can be NULL - -NOTES: - -1. This function has two different implementations: one which uses exact - (analytical) user-supplied gradient, and one which uses function value - only and numerically differentiates function in order to obtain - gradient. - - Depending on the specific function used to create optimizer object - (either MinBCCreate() for analytical gradient or MinBCCreateF() - for numerical differentiation) you should choose appropriate variant of - MinBCOptimize() - one which accepts function AND gradient or one - which accepts function ONLY. - - Be careful to choose variant of MinBCOptimize() which corresponds to - your optimization scheme! Table below lists different combinations of - callback (function/gradient) passed to MinBCOptimize() and specific - function used to create optimizer. - - - | USER PASSED TO MinBCOptimize() - CREATED WITH | function only | function and gradient - ------------------------------------------------------------ - MinBCCreateF() | works FAILS - MinBCCreate() | FAILS works - - Here "FAIL" denotes inappropriate combinations of optimizer creation - function and MinBCOptimize() version. Attemps to use such - combination (for example, to create optimizer with MinBCCreateF() - and to pass gradient information to MinCGOptimize()) will lead to - exception being thrown. Either you did not pass gradient when it WAS - needed or you passed gradient when it was NOT needed. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey - -*************************************************************************/ -void minbcoptimize(minbcstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void minbcoptimize(minbcstate &state, - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic gradient. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function at the initial point -(note: future versions may also perform check at the final point) and -compares numerical gradient with analytic one provided by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both gradients and specific components highlighted as -suspicious by the OptGuard. - -The primary OptGuard report can be retrieved with minbcoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with minbcsetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minbcoptguardgradient(const minbcstate &state, const double teststep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) -b) nonsmooth target function (non-C1) - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbcoptguardsmoothness(const minbcstate &state, const ae_int_t level, const xparams _xparams = alglib::xdefault); -void minbcoptguardsmoothness(const minbcstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -=== PRIMARY REPORT ======================================================= - -OptGuard performs several checks which are intended to catch common errors -in the implementation of nonlinear function/gradient: -* incorrect analytic gradient -* discontinuous (non-C0) target functions (constraints) -* nonsmooth (non-C1) target functions (constraints) - -Each of these checks is activated with appropriate function: -* minbcoptguardgradient() for gradient verification -* minbcoptguardsmoothness() for C0/C1 checks - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradvidx for specific variable (gradient element) suspected - * rep.badgradxbase, a point where gradient is tested - * rep.badgraduser, user-provided gradient (stored as 2D matrix with - single row in order to make report structure compatible with more - complex optimizers like MinNLC or MinLM) - * rep.badgradnum, reference gradient obtained via numerical - differentiation (stored as 2D matrix with single row in order to make - report structure compatible with more complex optimizers like MinNLC - or MinLM) -* rep.nonc0suspected -* rep.nonc1suspected - -=== ADDITIONAL REPORTS/LOGS ============================================== - -Several different tests are performed to catch C0/C1 errors, you can find -out specific test signaled error by looking to: -* rep.nonc0test0positive, for non-C0 test #0 -* rep.nonc1test0positive, for non-C1 test #0 -* rep.nonc1test1positive, for non-C1 test #1 - -Additional information (including line search logs) can be obtained by -means of: -* minbcoptguardnonc1test0results() -* minbcoptguardnonc1test1results() -which return detailed error reports, specific points where discontinuities -were found, and so on. - -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - generic OptGuard report; more detailed reports can be - retrieved with other functions. - -NOTE: false negatives (nonsmooth problems are not identified as nonsmooth - ones) are possible although unlikely. - - The reason is that you need to make several evaluations around - nonsmoothness in order to accumulate enough information about - function curvature. Say, if you start right from the nonsmooth point, - optimizer simply won't get enough data to understand what is going - wrong before it terminates due to abrupt changes in the derivative. - It is also possible that "unlucky" step will move us to the - termination too quickly. - - Our current approach is to have less than 0.1% false negatives in - our test examples (measured with multiple restarts from random - points), and to have exactly 0% false positives. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbcoptguardresults(const minbcstate &state, optguardreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #0 - -Nonsmoothness (non-C1) test #0 studies function values (not gradient!) -obtained during line searches and monitors behavior of the directional -derivative estimate. - -This test is less powerful than test #1, but it does not depend on the -gradient values and thus it is more robust against artifacts introduced by -numerical differentiation. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #0 "strong" report - lngrep - C1 test #0 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbcoptguardnonc1test0results(const minbcstate &state, optguardnonc1test0report &strrep, optguardnonc1test0report &lngrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #1 - -Nonsmoothness (non-C1) test #1 studies individual components of the -gradient computed during line search. - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #1 "strong" report - lngrep - C1 test #1 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minbcoptguardnonc1test1results(const minbcstate &state, optguardnonc1test1report &strrep, optguardnonc1test1report &lngrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -BC results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report. You should check Rep.TerminationType - in order to distinguish successful termination from - unsuccessful one: - * -8 internal integrity control detected infinite or - NAN values in function/gradient. Abnormal - termination signalled. - * -3 inconsistent constraints. - * 1 relative function improvement is no more than EpsF. - * 2 scaled step is no more than EpsX. - * 4 scaled gradient norm is no more than EpsG. - * 5 MaxIts steps was taken - * 8 terminated by user who called minbcrequesttermination(). - X contains point which was "current accepted" when - termination request was submitted. - More information about fields of this structure can be - found in the comments on MinBCReport datatype. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcresults(const minbcstate &state, real_1d_array &x, minbcreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -BC results - -Buffered implementation of MinBCResults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcresultsbuf(const minbcstate &state, real_1d_array &x, minbcreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine restarts algorithm from new point. -All optimization parameters (including constraints) are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure previously allocated with MinBCCreate call. - X - new starting point. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbcrestartfrom(const minbcstate &state, const real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void minbcrequesttermination(const minbcstate &state, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_MINNS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - NONSMOOTH NONCONVEX OPTIMIZATION - SUBJECT TO BOX/LINEAR/NONLINEAR-NONSMOOTH CONSTRAINTS - -DESCRIPTION: - -The subroutine minimizes function F(x) of N arguments subject to any -combination of: -* bound constraints -* linear inequality constraints -* linear equality constraints -* nonlinear equality constraints Gi(x)=0 -* nonlinear inequality constraints Hi(x)<=0 - -IMPORTANT: see MinNSSetAlgoAGS for important information on performance - restrictions of AGS solver. - -REQUIREMENTS: -* starting point X0 must be feasible or not too far away from the feasible - set -* F(), G(), H() are continuous, locally Lipschitz and continuously (but - not necessarily twice) differentiable in an open dense subset of R^N. - Functions F(), G() and H() may be nonsmooth and non-convex. - Informally speaking, it means that functions are composed of large - differentiable "patches" with nonsmoothness having place only at the - boundaries between these "patches". - Most real-life nonsmooth functions satisfy these requirements. Say, - anything which involves finite number of abs(), min() and max() is very - likely to pass the test. - Say, it is possible to optimize anything of the following: - * f=abs(x0)+2*abs(x1) - * f=max(x0,x1) - * f=sin(max(x0,x1)+abs(x2)) -* for nonlinearly constrained problems: F() must be bounded from below - without nonlinear constraints (this requirement is due to the fact that, - contrary to box and linear constraints, nonlinear ones require special - handling). -* user must provide function value and gradient for F(), H(), G() at all - points where function/gradient can be calculated. If optimizer requires - value exactly at the boundary between "patches" (say, at x=0 for f=abs(x)), - where gradient is not defined, user may resolve tie arbitrarily (in our - case - return +1 or -1 at its discretion). -* NS solver supports numerical differentiation, i.e. it may differentiate - your function for you, but it results in 2N increase of function - evaluations. Not recommended unless you solve really small problems. See - minnscreatef() for more information on this functionality. - -USAGE: - -1. User initializes algorithm state with MinNSCreate() call and chooses - what NLC solver to use. There is some solver which is used by default, - with default settings, but you should NOT rely on default choice. It - may change in future releases of ALGLIB without notice, and no one can - guarantee that new solver will be able to solve your problem with - default settings. - - From the other side, if you choose solver explicitly, you can be pretty - sure that it will work with new ALGLIB releases. - - In the current release following solvers can be used: - * AGS solver (activated with MinNSSetAlgoAGS() function) - -2. User adds boundary and/or linear and/or nonlinear constraints by means - of calling one of the following functions: - a) MinNSSetBC() for boundary constraints - b) MinNSSetLC() for linear constraints - c) MinNSSetNLC() for nonlinear constraints - You may combine (a), (b) and (c) in one optimization problem. - -3. User sets scale of the variables with MinNSSetScale() function. It is - VERY important to set scale of the variables, because nonlinearly - constrained problems are hard to solve when variables are badly scaled. - -4. User sets stopping conditions with MinNSSetCond(). - -5. Finally, user calls MinNSOptimize() function which takes algorithm - state and pointer (delegate, etc) to callback function which calculates - F/G/H. - -7. User calls MinNSResults() to get solution - -8. Optionally user may call MinNSRestartFrom() to solve another problem - with same N but another starting point. MinNSRestartFrom() allows to - reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - -NOTE: minnscreatef() function may be used if you do not have analytic - gradient. This function creates solver which uses numerical - differentiation with user-specified step. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnscreate(const ae_int_t n, const real_1d_array &x, minnsstate &state, const xparams _xparams = alglib::xdefault); -void minnscreate(const real_1d_array &x, minnsstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Version of minnscreatef() which uses numerical differentiation. I.e., you -do not have to calculate derivatives yourself. However, this version needs -2N times more function evaluations. - -2-point differentiation formula is used, because more precise 4-point -formula is unstable when used on non-smooth functions. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[N]: - * it is better to set X to a feasible point - * but X can be infeasible, in which case algorithm will try - to find feasible point first, using X as initial - approximation. - DiffStep- differentiation step, DiffStep>0. Algorithm performs - numerical differentiation with step for I-th variable - being equal to DiffStep*S[I] (here S[] is a scale vector, - set by minnssetscale() function). - Do not use too small steps, because it may lead to - catastrophic cancellation during intermediate calculations. - -OUTPUT PARAMETERS: - State - structure stores algorithm state - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnscreatef(const ae_int_t n, const real_1d_array &x, const double diffstep, minnsstate &state, const xparams _xparams = alglib::xdefault); -void minnscreatef(const real_1d_array &x, const double diffstep, minnsstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets boundary constraints. - -Boundary constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with minnsrestartfrom(). - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF. - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF. - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - -NOTE 2: AGS solver has following useful properties: -* bound constraints are always satisfied exactly -* function is evaluated only INSIDE area specified by bound constraints, - even when numerical differentiation is used (algorithm adjusts nodes - according to boundary constraints) - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnssetbc(const minnsstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets linear constraints. - -Linear constraints are inactive by default (after initial creation). -They are preserved after algorithm restart with minnsrestartfrom(). - -INPUT PARAMETERS: - State - structure previously allocated with minnscreate() call. - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -NOTE: linear (non-bound) constraints are satisfied only approximately: - -* there always exists some minor violation (about current sampling radius - in magnitude during optimization, about EpsX in the solution) due to use - of penalty method to handle constraints. -* numerical differentiation, if used, may lead to function evaluations - outside of the feasible area, because algorithm does NOT change - numerical differentiation formula according to linear constraints. - -If you want constraints to be satisfied exactly, try to reformulate your -problem in such manner that all constraints will become boundary ones -(this kind of constraints is always satisfied exactly, both in the final -solution and in all intermediate points). - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnssetlc(const minnsstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams = alglib::xdefault); -void minnssetlc(const minnsstate &state, const real_2d_array &c, const integer_1d_array &ct, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets nonlinear constraints. - -In fact, this function sets NUMBER of nonlinear constraints. Constraints -itself (constraint functions) are passed to minnsoptimize() method. This -method requires user-defined vector function F[] and its Jacobian J[], -where: -* first component of F[] and first row of Jacobian J[] correspond to - function being minimized -* next NLEC components of F[] (and rows of J) correspond to nonlinear - equality constraints G_i(x)=0 -* next NLIC components of F[] (and rows of J) correspond to nonlinear - inequality constraints H_i(x)<=0 - -NOTE: you may combine nonlinear constraints with linear/boundary ones. If - your problem has mixed constraints, you may explicitly specify some - of them as linear ones. It may help optimizer to handle them more - efficiently. - -INPUT PARAMETERS: - State - structure previously allocated with minnscreate() call. - NLEC - number of Non-Linear Equality Constraints (NLEC), >=0 - NLIC - number of Non-Linear Inquality Constraints (NLIC), >=0 - -NOTE 1: nonlinear constraints are satisfied only approximately! It is - possible that algorithm will evaluate function outside of - the feasible area! - -NOTE 2: algorithm scales variables according to scale specified by - minnssetscale() function, so it can handle problems with badly - scaled variables (as long as we KNOW their scales). - - However, there is no way to automatically scale nonlinear - constraints Gi(x) and Hi(x). Inappropriate scaling of Gi/Hi may - ruin convergence. Solving problem with constraint "1000*G0(x)=0" - is NOT same as solving it with constraint "0.001*G0(x)=0". - - It means that YOU are the one who is responsible for correct - scaling of nonlinear constraints Gi(x) and Hi(x). We recommend you - to scale nonlinear constraints in such way that I-th component of - dG/dX (or dH/dx) has approximately unit magnitude (for problems - with unit scale) or has magnitude approximately equal to 1/S[i] - (where S is a scale set by minnssetscale() function). - -NOTE 3: nonlinear constraints are always hard to handle, no matter what - algorithm you try to use. Even basic box/linear constraints modify - function curvature by adding valleys and ridges. However, - nonlinear constraints add valleys which are very hard to follow - due to their "curved" nature. - - It means that optimization with single nonlinear constraint may be - significantly slower than optimization with multiple linear ones. - It is normal situation, and we recommend you to carefully choose - Rho parameter of minnssetalgoags(), because too large value may - slow down convergence. - - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnssetnlc(const minnsstate &state, const ae_int_t nlec, const ae_int_t nlic, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets stopping conditions for iterations of optimizer. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsX - >=0 - The AGS solver finishes its work if on k+1-th iteration - sampling radius decreases below EpsX. - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic -stopping criterion selection. We do not recommend you to rely on default -choice in production code. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnssetcond(const minnsstate &state, const double epsx, const ae_int_t maxits, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets scaling coefficients for NLC optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of the optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnssetscale(const minnsstate &state, const real_1d_array &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function tells MinNS unit to use AGS (adaptive gradient sampling) -algorithm for nonsmooth constrained optimization. This algorithm is a -slight modification of one described in "An Adaptive Gradient Sampling -Algorithm for Nonsmooth Optimization" by Frank E. Curtisy and Xiaocun Quez. - -This optimizer has following benefits and drawbacks: -+ robustness; it can be used with nonsmooth and nonconvex functions. -+ relatively easy tuning; most of the metaparameters are easy to select. -- it has convergence of steepest descent, slower than CG/LBFGS. -- each iteration involves evaluation of ~2N gradient values and solution - of 2Nx2N quadratic programming problem, which limits applicability of - algorithm by small-scale problems (up to 50-100). - -IMPORTANT: this algorithm has convergence guarantees, i.e. it will - steadily move towards some stationary point of the function. - - However, "stationary point" does not always mean "solution". - Nonsmooth problems often have "flat spots", i.e. areas where - function do not change at all. Such "flat spots" are stationary - points by definition, and algorithm may be caught here. - - Nonsmooth CONVEX tasks are not prone to this problem. Say, if - your function has form f()=MAX(f0,f1,...), and f_i are convex, - then f() is convex too and you have guaranteed convergence to - solution. - -INPUT PARAMETERS: - State - structure which stores algorithm state - Radius - initial sampling radius, >=0. - - Internally multiplied by vector of per-variable scales - specified by minnssetscale()). - - You should select relatively large sampling radius, roughly - proportional to scaled length of the first steps of the - algorithm. Something close to 0.1 in magnitude should be - good for most problems. - - AGS solver can automatically decrease radius, so too large - radius is not a problem (assuming that you won't choose - so large radius that algorithm will sample function in - too far away points, where gradient value is irrelevant). - - Too small radius won't cause algorithm to fail, but it may - slow down algorithm (it may have to perform too short - steps). - Penalty - penalty coefficient for nonlinear constraints: - * for problem with nonlinear constraints should be some - problem-specific positive value, large enough that - penalty term changes shape of the function. - Starting from some problem-specific value penalty - coefficient becomes large enough to exactly enforce - nonlinear constraints; larger values do not improve - precision. - Increasing it too much may slow down convergence, so you - should choose it carefully. - * can be zero for problems WITHOUT nonlinear constraints - (i.e. for unconstrained ones or ones with just box or - linear constraints) - * if you specify zero value for problem with at least one - nonlinear constraint, algorithm will terminate with - error code -1. - -ALGORITHM OUTLINE - -The very basic outline of unconstrained AGS algorithm is given below: - -0. If sampling radius is below EpsX or we performed more then MaxIts - iterations - STOP. -1. sample O(N) gradient values at random locations around current point; - informally speaking, this sample is an implicit piecewise linear model - of the function, although algorithm formulation does not mention that - explicitly -2. solve quadratic programming problem in order to find descent direction -3. if QP solver tells us that we are near solution, decrease sampling - radius and move to (0) -4. perform backtracking line search -5. after moving to new point, goto (0) - -As for the constraints: -* box constraints are handled exactly by modification of the function - being minimized -* linear/nonlinear constraints are handled by adding L1 penalty. Because - our solver can handle nonsmoothness, we can use L1 penalty function, - which is an exact one (i.e. exact solution is returned under such - penalty). -* penalty coefficient for linear constraints is chosen automatically; - however, penalty coefficient for nonlinear constraints must be specified - by user. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnssetalgoags(const minnsstate &state, const double radius, const double penalty, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to minnsoptimize(). - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minnssetxrep(const minnsstate &state, const bool needxrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnsrequesttermination(const minnsstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool minnsiteration(const minnsstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This family of functions is used to launcn iterations of nonlinear optimizer - -These functions accept following parameters: - state - algorithm state - fvec - callback which calculates function vector fi[] - at given point x - jac - callback which calculates function vector fi[] - and Jacobian jac at given point x - rep - optional callback which is called after each iteration - can be NULL - ptr - optional pointer which is passed to func/grad/hess/jac/rep - can be NULL - - -NOTES: - -1. This function has two different implementations: one which uses exact - (analytical) user-supplied Jacobian, and one which uses only function - vector and numerically differentiates function in order to obtain - gradient. - - Depending on the specific function used to create optimizer object - you should choose appropriate variant of minnsoptimize() - one which - accepts function AND Jacobian or one which accepts ONLY function. - - Be careful to choose variant of minnsoptimize() which corresponds to - your optimization scheme! Table below lists different combinations of - callback (function/gradient) passed to minnsoptimize() and specific - function used to create optimizer. - - - | USER PASSED TO minnsoptimize() - CREATED WITH | function only | function and gradient - ------------------------------------------------------------ - minnscreatef() | works FAILS - minnscreate() | FAILS works - - Here "FAILS" denotes inappropriate combinations of optimizer creation - function and minnsoptimize() version. Attemps to use such - combination will lead to exception. Either you did not pass gradient - when it WAS needed or you passed gradient when it was NOT needed. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey - -*************************************************************************/ -void minnsoptimize(minnsstate &state, - void (*fvec)(const real_1d_array &x, real_1d_array &fi, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void minnsoptimize(minnsstate &state, - void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -MinNS results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report. You should check Rep.TerminationType - in order to distinguish successful termination from - unsuccessful one: - * -8 internal integrity control detected infinite or - NAN values in function/gradient. Abnormal - termination signalled. - * -3 box constraints are inconsistent - * -1 inconsistent parameters were passed: - * penalty parameter for minnssetalgoags() is zero, - but we have nonlinear constraints set by minnssetnlc() - * 2 sampling radius decreased below epsx - * 7 stopping conditions are too stringent, - further improvement is impossible, - X contains best point found so far. - * 8 User requested termination via minnsrequesttermination() - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnsresults(const minnsstate &state, real_1d_array &x, minnsreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* - -Buffered implementation of minnsresults() which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnsresultsbuf(const minnsstate &state, real_1d_array &x, minnsreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine restarts algorithm from new point. -All optimization parameters (including constraints) are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure previously allocated with minnscreate() call. - X - new starting point. - - -- ALGLIB -- - Copyright 18.05.2015 by Bochkanov Sergey -*************************************************************************/ -void minnsrestartfrom(const minnsstate &state, const real_1d_array &x, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_MINCOMP) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Obsolete function, use MinLBFGSSetPrecDefault() instead. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetdefaultpreconditioner(const minlbfgsstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Obsolete function, use MinLBFGSSetCholeskyPreconditioner() instead. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlbfgssetcholeskypreconditioner(const minlbfgsstate &state, const real_2d_array &p, const bool isupper, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is obsolete function which was used by previous version of the BLEIC -optimizer. It does nothing in the current version of BLEIC. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetbarrierwidth(const minbleicstate &state, const double mu, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is obsolete function which was used by previous version of the BLEIC -optimizer. It does nothing in the current version of BLEIC. - - -- ALGLIB -- - Copyright 28.11.2010 by Bochkanov Sergey -*************************************************************************/ -void minbleicsetbarrierdecay(const minbleicstate &state, const double mudecay, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 25.03.2010 by Bochkanov Sergey -*************************************************************************/ -void minasacreate(const ae_int_t n, const real_1d_array &x, const real_1d_array &bndl, const real_1d_array &bndu, minasastate &state, const xparams _xparams = alglib::xdefault); -void minasacreate(const real_1d_array &x, const real_1d_array &bndl, const real_1d_array &bndu, minasastate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minasasetcond(const minasastate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minasasetxrep(const minasastate &state, const bool needxrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minasasetalgorithm(const minasastate &state, const ae_int_t algotype, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minasasetstpmax(const minasastate &state, const double stpmax, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool minasaiteration(const minasastate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This family of functions is used to launcn iterations of nonlinear optimizer - -These functions accept following parameters: - state - algorithm state - grad - callback which calculates function (or merit function) - value func and gradient grad at given point x - rep - optional callback which is called after each iteration - can be NULL - ptr - optional pointer which is passed to func/grad/hess/jac/rep - can be NULL - - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey - -*************************************************************************/ -void minasaoptimize(minasastate &state, - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minasaresults(const minasastate &state, real_1d_array &x, minasareport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minasaresultsbuf(const minasastate &state, real_1d_array &x, minasareport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Obsolete optimization algorithm. -Was replaced by MinBLEIC subpackage. - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -void minasarestartfrom(const minasastate &state, const real_1d_array &x, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_MINCG) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - NONLINEAR CONJUGATE GRADIENT METHOD - -DESCRIPTION: -The subroutine minimizes function F(x) of N arguments by using one of the -nonlinear conjugate gradient methods. - -These CG methods are globally convergent (even on non-convex functions) as -long as grad(f) is Lipschitz continuous in a some neighborhood of the -L = { x : f(x)<=f(x0) }. - - -REQUIREMENTS: -Algorithm will request following information during its operation: -* function value F and its gradient G (simultaneously) at given point X - - -USAGE: -1. User initializes algorithm state with MinCGCreate() call -2. User tunes solver parameters with MinCGSetCond(), MinCGSetStpMax() and - other functions -3. User calls MinCGOptimize() function which takes algorithm state and - pointer (delegate, etc.) to callback function which calculates F/G. -4. User calls MinCGResults() to get solution -5. Optionally, user may call MinCGRestartFrom() to solve another problem - with same N but another starting point and/or another function. - MinCGRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[0..N-1]. - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 25.03.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgcreate(const ae_int_t n, const real_1d_array &x, mincgstate &state, const xparams _xparams = alglib::xdefault); -void mincgcreate(const real_1d_array &x, mincgstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -The subroutine is finite difference variant of MinCGCreate(). It uses -finite differences in order to differentiate target function. - -Description below contains information which is specific to this function -only. We recommend to read comments on MinCGCreate() in order to get more -information about creation of CG optimizer. - -INPUT PARAMETERS: - N - problem dimension, N>0: - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - starting point, array[0..N-1]. - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. algorithm uses 4-point central formula for differentiation. -2. differentiation step along I-th axis is equal to DiffStep*S[I] where - S[] is scaling vector which can be set by MinCGSetScale() call. -3. we recommend you to use moderate values of differentiation step. Too - large step will result in too large truncation errors, while too small - step will result in too large numerical errors. 1.0E-6 can be good - value to start with. -4. Numerical differentiation is very inefficient - one gradient - calculation needs 4*N function evaluations. This function will work for - any N - either small (1...10), moderate (10...100) or large (100...). - However, performance penalty will be too severe for any N's except for - small ones. - We should also say that code which relies on numerical differentiation - is less robust and precise. L-BFGS needs exact gradient values. - Imprecise gradient may slow down convergence, especially on highly - nonlinear problems. - Thus we recommend to use this function for fast prototyping on small- - dimensional problems only, and to implement analytical gradient as soon - as possible. - - -- ALGLIB -- - Copyright 16.05.2011 by Bochkanov Sergey -*************************************************************************/ -void mincgcreatef(const ae_int_t n, const real_1d_array &x, const double diffstep, mincgstate &state, const xparams _xparams = alglib::xdefault); -void mincgcreatef(const real_1d_array &x, const double diffstep, mincgstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets stopping conditions for CG optimization algorithm. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsG - >=0 - The subroutine finishes its work if the condition - |v|=0 - The subroutine finishes its work if on k+1-th iteration - the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1} - is satisfied. - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - ste pvector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinCGSetScale() - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to -automatic stopping criterion selection (small EpsX). - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetcond(const mincgstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets scaling coefficients for CG optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Scaling is also used by finite difference variant of CG optimizer - step -along I-th axis is equal to DiffStep*S[I]. - -In most optimizers (and in the CG too) scaling is NOT a form of -preconditioning. It just affects stopping conditions. You should set -preconditioner by separate call to one of the MinCGSetPrec...() functions. - -There is special preconditioning mode, however, which uses scaling -coefficients to form diagonal preconditioning matrix. You can turn this -mode on, if you want. But you should understand that scaling is not the -same thing as preconditioning - these are two different, although related -forms of tuning solver. - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void mincgsetscale(const mincgstate &state, const real_1d_array &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinCGOptimize(). - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetxrep(const mincgstate &state, const bool needxrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets CG algorithm. - -INPUT PARAMETERS: - State - structure which stores algorithm state - CGType - algorithm type: - * -1 automatic selection of the best algorithm - * 0 DY (Dai and Yuan) algorithm - * 1 Hybrid DY-HS algorithm - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetcgtype(const mincgstate &state, const ae_int_t cgtype, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which leads to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetstpmax(const mincgstate &state, const double stpmax, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function allows to suggest initial step length to the CG algorithm. - -Suggested step length is used as starting point for the line search. It -can be useful when you have badly scaled problem, i.e. when ||grad|| -(which is used as initial estimate for the first step) is many orders of -magnitude different from the desired step. - -Line search may fail on such problems without good estimate of initial -step length. Imagine, for example, problem with ||grad||=10^50 and desired -step equal to 0.1 Line search function will use 10^50 as initial step, -then it will decrease step length by 2 (up to 20 attempts) and will get -10^44, which is still too large. - -This function allows us to tell than line search should be started from -some moderate step length, like 1.0, so algorithm will be able to detect -desired step length in a several searches. - -Default behavior (when no step is suggested) is to use preconditioner, if -it is available, to generate initial estimate of step length. - -This function influences only first iteration of algorithm. It should be -called between MinCGCreate/MinCGRestartFrom() call and MinCGOptimize call. -Suggested step is ignored if you have preconditioner. - -INPUT PARAMETERS: - State - structure used to store algorithm state. - Stp - initial estimate of the step length. - Can be zero (no estimate). - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsuggeststep(const mincgstate &state, const double stp, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Modification of the preconditioner: preconditioning is turned off. - -INPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetprecdefault(const mincgstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Modification of the preconditioner: diagonal of approximate Hessian is -used. - -INPUT PARAMETERS: - State - structure which stores algorithm state - D - diagonal of the approximate Hessian, array[0..N-1], - (if larger, only leading N elements are used). - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - -NOTE 2: D[i] should be positive. Exception will be thrown otherwise. - -NOTE 3: you should pass diagonal of approximate Hessian - NOT ITS INVERSE. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetprecdiag(const mincgstate &state, const real_1d_array &d, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Modification of the preconditioner: scale-based diagonal preconditioning. - -This preconditioning mode can be useful when you don't have approximate -diagonal of Hessian, but you know that your variables are badly scaled -(for example, one variable is in [1,10], and another in [1000,100000]), -and most part of the ill-conditioning comes from different scales of vars. - -In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2), -can greatly improve convergence. - -IMPRTANT: you should set scale of your variables with MinCGSetScale() call -(before or after MinCGSetPrecScale() call). Without knowledge of the scale -of your variables scale-based preconditioner will be just unit matrix. - -INPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: you can change preconditioner "on the fly", during algorithm -iterations. - - -- ALGLIB -- - Copyright 13.10.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgsetprecscale(const mincgstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool mincgiteration(const mincgstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This family of functions is used to launcn iterations of nonlinear optimizer - -These functions accept following parameters: - state - algorithm state - func - callback which calculates function (or merit function) - value func at given point x - grad - callback which calculates function (or merit function) - value func and gradient grad at given point x - rep - optional callback which is called after each iteration - can be NULL - ptr - optional pointer which is passed to func/grad/hess/jac/rep - can be NULL - -NOTES: - -1. This function has two different implementations: one which uses exact - (analytical) user-supplied gradient, and one which uses function value - only and numerically differentiates function in order to obtain - gradient. - - Depending on the specific function used to create optimizer object - (either MinCGCreate() for analytical gradient or MinCGCreateF() for - numerical differentiation) you should choose appropriate variant of - MinCGOptimize() - one which accepts function AND gradient or one which - accepts function ONLY. - - Be careful to choose variant of MinCGOptimize() which corresponds to - your optimization scheme! Table below lists different combinations of - callback (function/gradient) passed to MinCGOptimize() and specific - function used to create optimizer. - - - | USER PASSED TO MinCGOptimize() - CREATED WITH | function only | function and gradient - ------------------------------------------------------------ - MinCGCreateF() | work FAIL - MinCGCreate() | FAIL work - - Here "FAIL" denotes inappropriate combinations of optimizer creation - function and MinCGOptimize() version. Attemps to use such combination - (for example, to create optimizer with MinCGCreateF() and to pass - gradient information to MinCGOptimize()) will lead to exception being - thrown. Either you did not pass gradient when it WAS needed or you - passed gradient when it was NOT needed. - - -- ALGLIB -- - Copyright 20.04.2009 by Bochkanov Sergey - -*************************************************************************/ -void mincgoptimize(mincgstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void mincgoptimize(mincgstate &state, - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic gradient. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function at the initial point -(note: future versions may also perform check at the final point) and -compares numerical gradient with analytic one provided by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both gradients and specific components highlighted as -suspicious by the OptGuard. - -The primary OptGuard report can be retrieved with mincgoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with mincgsetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -void mincgoptguardgradient(const mincgstate &state, const double teststep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function activates/deactivates nonsmoothness monitoring option of -the OptGuard integrity checker. Smoothness monitor silently observes -solution process and tries to detect ill-posed problems, i.e. ones with: -a) discontinuous target function (non-C0) -b) nonsmooth target function (non-C1) - -Smoothness monitoring does NOT interrupt optimization even if it suspects -that your problem is nonsmooth. It just sets corresponding flags in the -OptGuard report which can be retrieved after optimization is over. - -Smoothness monitoring is a moderate overhead option which often adds less -than 1% to the optimizer running time. Thus, you can use it even for large -scale problems. - -NOTE: OptGuard does NOT guarantee that it will always detect C0/C1 - continuity violations. - - First, minor errors are hard to catch - say, a 0.0001 difference in - the model values at two sides of the gap may be due to discontinuity - of the model - or simply because the model has changed. - - Second, C1-violations are especially difficult to detect in a - noninvasive way. The optimizer usually performs very short steps - near the nonsmoothness, and differentiation usually introduces a - lot of numerical noise. It is hard to tell whether some tiny - discontinuity in the slope is due to real nonsmoothness or just due - to numerical noise alone. - - Our top priority was to avoid false positives, so in some rare cases - minor errors may went unnoticed (however, in most cases they can be - spotted with restart from different initial point). - -INPUT PARAMETERS: - state - algorithm state - level - monitoring level: - * 0 - monitoring is disabled - * 1 - noninvasive low-overhead monitoring; function values - and/or gradients are recorded, but OptGuard does not - try to perform additional evaluations in order to - get more information about suspicious locations. - -=== EXPLANATION ========================================================== - -One major source of headache during optimization is the possibility of -the coding errors in the target function/constraints (or their gradients). -Such errors most often manifest themselves as discontinuity or -nonsmoothness of the target/constraints. - -Another frequent situation is when you try to optimize something involving -lots of min() and max() operations, i.e. nonsmooth target. Although not a -coding error, it is nonsmoothness anyway - and smooth optimizers usually -stop right after encountering nonsmoothness, well before reaching solution. - -OptGuard integrity checker helps you to catch such situations: it monitors -function values/gradients being passed to the optimizer and tries to -errors. Upon discovering suspicious pair of points it raises appropriate -flag (and allows you to continue optimization). When optimization is done, -you can study OptGuard result. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void mincgoptguardsmoothness(const mincgstate &state, const ae_int_t level, const xparams _xparams = alglib::xdefault); -void mincgoptguardsmoothness(const mincgstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -=== PRIMARY REPORT ======================================================= - -OptGuard performs several checks which are intended to catch common errors -in the implementation of nonlinear function/gradient: -* incorrect analytic gradient -* discontinuous (non-C0) target functions (constraints) -* nonsmooth (non-C1) target functions (constraints) - -Each of these checks is activated with appropriate function: -* mincgoptguardgradient() for gradient verification -* mincgoptguardsmoothness() for C0/C1 checks - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradvidx for specific variable (gradient element) suspected - * rep.badgradxbase, a point where gradient is tested - * rep.badgraduser, user-provided gradient (stored as 2D matrix with - single row in order to make report structure compatible with more - complex optimizers like MinNLC or MinLM) - * rep.badgradnum, reference gradient obtained via numerical - differentiation (stored as 2D matrix with single row in order to make - report structure compatible with more complex optimizers like MinNLC - or MinLM) -* rep.nonc0suspected -* rep.nonc1suspected - -=== ADDITIONAL REPORTS/LOGS ============================================== - -Several different tests are performed to catch C0/C1 errors, you can find -out specific test signaled error by looking to: -* rep.nonc0test0positive, for non-C0 test #0 -* rep.nonc1test0positive, for non-C1 test #0 -* rep.nonc1test1positive, for non-C1 test #1 - -Additional information (including line search logs) can be obtained by -means of: -* mincgoptguardnonc1test0results() -* mincgoptguardnonc1test1results() -which return detailed error reports, specific points where discontinuities -were found, and so on. - -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - generic OptGuard report; more detailed reports can be - retrieved with other functions. - -NOTE: false negatives (nonsmooth problems are not identified as nonsmooth - ones) are possible although unlikely. - - The reason is that you need to make several evaluations around - nonsmoothness in order to accumulate enough information about - function curvature. Say, if you start right from the nonsmooth point, - optimizer simply won't get enough data to understand what is going - wrong before it terminates due to abrupt changes in the derivative. - It is also possible that "unlucky" step will move us to the - termination too quickly. - - Our current approach is to have less than 0.1% false negatives in - our test examples (measured with multiple restarts from random - points), and to have exactly 0% false positives. - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void mincgoptguardresults(const mincgstate &state, optguardreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #0 - -Nonsmoothness (non-C1) test #0 studies function values (not gradient!) -obtained during line searches and monitors behavior of the directional -derivative estimate. - -This test is less powerful than test #1, but it does not depend on the -gradient values and thus it is more robust against artifacts introduced by -numerical differentiation. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], f[] - arrays of length CNT which store step lengths and function - values at these points; f[i] is evaluated in x0+stp[i]*d. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #0 "strong" report - lngrep - C1 test #0 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void mincgoptguardnonc1test0results(const mincgstate &state, optguardnonc1test0report &strrep, optguardnonc1test0report &lngrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Detailed results of the OptGuard integrity check for nonsmoothness test #1 - -Nonsmoothness (non-C1) test #1 studies individual components of the -gradient computed during line search. - -When precise analytic gradient is provided this test is more powerful than -test #0 which works with function values and ignores user-provided -gradient. However, test #0 becomes more powerful when numerical -differentiation is employed (in such cases test #1 detects higher levels -of numerical noise and becomes too conservative). - -This test also tells specific components of the gradient which violate C1 -continuity, which makes it more informative than #0, which just tells that -continuity is violated. - -Two reports are returned: -* a "strongest" one, corresponding to line search which had highest - value of the nonsmoothness indicator -* a "longest" one, corresponding to line search which had more function - evaluations, and thus is more detailed - -In both cases following fields are returned: - -* positive - is TRUE when test flagged suspicious point; FALSE if test - did not notice anything (in the latter cases fields below are empty). -* vidx - is an index of the variable in [0,N) with nonsmooth derivative -* x0[], d[] - arrays of length N which store initial point and direction - for line search (d[] can be normalized, but does not have to) -* stp[], g[] - arrays of length CNT which store step lengths and gradient - values at these points; g[i] is evaluated in x0+stp[i]*d and contains - vidx-th component of the gradient. -* stpidxa, stpidxb - we suspect that function violates C1 continuity - between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3, - with most likely position of the violation between stpidxa+1 and - stpidxa+2. - -========================================================================== -= SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will -= see where C1 continuity is violated. -========================================================================== - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - strrep - C1 test #1 "strong" report - lngrep - C1 test #1 "long" report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void mincgoptguardnonc1test1results(const mincgstate &state, optguardnonc1test1report &strrep, optguardnonc1test1report &lngrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Conjugate gradient results - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report: - * Rep.TerminationType completetion code: - * -8 internal integrity control detected infinite - or NAN values in function/gradient. Abnormal - termination signalled. - * -7 gradient verification failed. - See MinCGSetGradientCheck() for more information. - * 1 relative function improvement is no more than - EpsF. - * 2 relative step is no more than EpsX. - * 4 gradient norm is no more than EpsG - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible, - we return best X found so far - * 8 terminated by user - * Rep.IterationsCount contains iterations count - * NFEV countains number of function calculations - - -- ALGLIB -- - Copyright 20.04.2009 by Bochkanov Sergey -*************************************************************************/ -void mincgresults(const mincgstate &state, real_1d_array &x, mincgreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Conjugate gradient results - -Buffered implementation of MinCGResults(), which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 20.04.2009 by Bochkanov Sergey -*************************************************************************/ -void mincgresultsbuf(const mincgstate &state, real_1d_array &x, mincgreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine restarts CG algorithm from new point. All optimization -parameters are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure used to store algorithm state. - X - new starting point. - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -void mincgrestartfrom(const mincgstate &state, const real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void mincgrequesttermination(const mincgstate &state, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_MINLM) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - IMPROVED LEVENBERG-MARQUARDT METHOD FOR - NON-LINEAR LEAST SQUARES OPTIMIZATION - -DESCRIPTION: -This function is used to find minimum of function which is represented as -sum of squares: - F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1]) -using value of function vector f[] and Jacobian of f[]. - - -REQUIREMENTS: -This algorithm will request following information during its operation: - -* function vector f[] at given point X -* function vector f[] and Jacobian of f[] (simultaneously) at given point - -There are several overloaded versions of MinLMOptimize() function which -correspond to different LM-like optimization algorithms provided by this -unit. You should choose version which accepts fvec() and jac() callbacks. -First one is used to calculate f[] at given point, second one calculates -f[] and Jacobian df[i]/dx[j]. - -You can try to initialize MinLMState structure with VJ function and then -use incorrect version of MinLMOptimize() (for example, version which -works with general form function and does not provide Jacobian), but it -will lead to exception being thrown after first attempt to calculate -Jacobian. - - -USAGE: -1. User initializes algorithm state with MinLMCreateVJ() call -2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and - other functions -3. User calls MinLMOptimize() function which takes algorithm state and - callback functions. -4. User calls MinLMResults() to get solution -5. Optionally, user may call MinLMRestartFrom() to solve another problem - with same N/M but another starting point and/or another function. - MinLMRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - dimension, N>1 - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - M - number of functions f[i] - X - initial solution, array[0..N-1] - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. you may tune stopping conditions with MinLMSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use MinLMSetStpMax() function to bound algorithm's steps. - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmcreatevj(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams = alglib::xdefault); -void minlmcreatevj(const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* - IMPROVED LEVENBERG-MARQUARDT METHOD FOR - NON-LINEAR LEAST SQUARES OPTIMIZATION - -DESCRIPTION: -This function is used to find minimum of function which is represented as -sum of squares: - F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1]) -using value of function vector f[] only. Finite differences are used to -calculate Jacobian. - - -REQUIREMENTS: -This algorithm will request following information during its operation: -* function vector f[] at given point X - -There are several overloaded versions of MinLMOptimize() function which -correspond to different LM-like optimization algorithms provided by this -unit. You should choose version which accepts fvec() callback. - -You can try to initialize MinLMState structure with VJ function and then -use incorrect version of MinLMOptimize() (for example, version which -works with general form function and does not accept function vector), but -it will lead to exception being thrown after first attempt to calculate -Jacobian. - - -USAGE: -1. User initializes algorithm state with MinLMCreateV() call -2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and - other functions -3. User calls MinLMOptimize() function which takes algorithm state and - callback functions. -4. User calls MinLMResults() to get solution -5. Optionally, user may call MinLMRestartFrom() to solve another problem - with same N/M but another starting point and/or another function. - MinLMRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - dimension, N>1 - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - M - number of functions f[i] - X - initial solution, array[0..N-1] - DiffStep- differentiation step, >0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -See also MinLMIteration, MinLMResults. - -NOTES: -1. you may tune stopping conditions with MinLMSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use MinLMSetStpMax() function to bound algorithm's steps. - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmcreatev(const ae_int_t n, const ae_int_t m, const real_1d_array &x, const double diffstep, minlmstate &state, const xparams _xparams = alglib::xdefault); -void minlmcreatev(const ae_int_t m, const real_1d_array &x, const double diffstep, minlmstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* - LEVENBERG-MARQUARDT-LIKE METHOD FOR NON-LINEAR OPTIMIZATION - -DESCRIPTION: -This function is used to find minimum of general form (not "sum-of- --squares") function - F = F(x[0], ..., x[n-1]) -using its gradient and Hessian. Levenberg-Marquardt modification with -L-BFGS pre-optimization and internal pre-conditioned L-BFGS optimization -after each Levenberg-Marquardt step is used. - - -REQUIREMENTS: -This algorithm will request following information during its operation: - -* function value F at given point X -* F and gradient G (simultaneously) at given point X -* F, G and Hessian H (simultaneously) at given point X - -There are several overloaded versions of MinLMOptimize() function which -correspond to different LM-like optimization algorithms provided by this -unit. You should choose version which accepts func(), grad() and hess() -function pointers. First pointer is used to calculate F at given point, -second one calculates F(x) and grad F(x), third one calculates F(x), -grad F(x), hess F(x). - -You can try to initialize MinLMState structure with FGH-function and then -use incorrect version of MinLMOptimize() (for example, version which does -not provide Hessian matrix), but it will lead to exception being thrown -after first attempt to calculate Hessian. - - -USAGE: -1. User initializes algorithm state with MinLMCreateFGH() call -2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and - other functions -3. User calls MinLMOptimize() function which takes algorithm state and - pointers (delegates, etc.) to callback functions. -4. User calls MinLMResults() to get solution -5. Optionally, user may call MinLMRestartFrom() to solve another problem - with same N but another starting point and/or another function. - MinLMRestartFrom() allows to reuse already initialized structure. - - -INPUT PARAMETERS: - N - dimension, N>1 - * if given, only leading N elements of X are used - * if not given, automatically determined from size of X - X - initial solution, array[0..N-1] - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -1. you may tune stopping conditions with MinLMSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use MinLMSetStpMax() function to bound algorithm's steps. - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmcreatefgh(const ae_int_t n, const real_1d_array &x, minlmstate &state, const xparams _xparams = alglib::xdefault); -void minlmcreatefgh(const real_1d_array &x, minlmstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets stopping conditions for Levenberg-Marquardt optimization -algorithm. - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsX - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition |v|<=EpsX is fulfilled, where: - * |.| means Euclidian norm - * v - scaled step vector, v[i]=dx[i]/s[i] - * dx - ste pvector, dx=X(k+1)-X(k) - * s - scaling coefficients set by MinLMSetScale() - Recommended values: 1E-9 ... 1E-12. - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. Only Levenberg-Marquardt - iterations are counted (L-BFGS/CG iterations are NOT - counted because their cost is very low compared to that of - LM). - -Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic -stopping criterion selection (small EpsX). - -NOTE: it is not recommended to set large EpsX (say, 0.001). Because LM is - a second-order method, it performs very precise steps anyway. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlmsetcond(const minlmstate &state, const double epsx, const ae_int_t maxits, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinLMOptimize(). Both Levenberg-Marquardt and internal L-BFGS -iterations are reported. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlmsetxrep(const minlmstate &state, const bool needxrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when you optimize target function which contains exp() -or other fast growing functions, and optimization algorithm makes too -large steps which leads to overflow. This function allows us to reject -steps that are too large (and therefore expose us to the possible -overflow) without actually calculating function value at the x+stp*d. - -NOTE: non-zero StpMax leads to moderate performance degradation because -intermediate step of preconditioned L-BFGS optimization is incompatible -with limits on step size. - - -- ALGLIB -- - Copyright 02.04.2010 by Bochkanov Sergey -*************************************************************************/ -void minlmsetstpmax(const minlmstate &state, const double stpmax, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets scaling coefficients for LM optimizer. - -ALGLIB optimizers use scaling matrices to test stopping conditions (step -size and gradient are scaled before comparison with tolerances). Scale of -the I-th variable is a translation invariant measure of: -a) "how large" the variable is -b) how large the step should be to make significant changes in the function - -Generally, scale is NOT considered to be a form of preconditioner. But LM -optimizer is unique in that it uses scaling matrix both in the stopping -condition tests and as Marquardt damping factor. - -Proper scaling is very important for the algorithm performance. It is less -important for the quality of results, but still has some influence (it is -easier to converge when variables are properly scaled, so premature -stopping is possible when very badly scalled variables are combined with -relaxed stopping conditions). - -INPUT PARAMETERS: - State - structure stores algorithm state - S - array[N], non-zero scaling coefficients - S[i] may be negative, sign doesn't matter. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minlmsetscale(const minlmstate &state, const real_1d_array &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets boundary constraints for LM optimizer - -Boundary constraints are inactive by default (after initial creation). -They are preserved until explicitly turned off with another SetBC() call. - -INPUT PARAMETERS: - State - structure stores algorithm state - BndL - lower bounds, array[N]. - If some (all) variables are unbounded, you may specify - very small number or -INF (latter is recommended because - it will allow solver to use better algorithm). - BndU - upper bounds, array[N]. - If some (all) variables are unbounded, you may specify - very large number or +INF (latter is recommended because - it will allow solver to use better algorithm). - -NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th -variable will be "frozen" at X[i]=BndL[i]=BndU[i]. - -NOTE 2: this solver has following useful properties: -* bound constraints are always satisfied exactly -* function is evaluated only INSIDE area specified by bound constraints - or at its boundary - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minlmsetbc(const minlmstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets general linear constraints for LM optimizer - -Linear constraints are inactive by default (after initial creation). They -are preserved until explicitly turned off with another minlmsetlc() call. - -INPUT PARAMETERS: - State - structure stores algorithm state - C - linear constraints, array[K,N+1]. - Each row of C represents one constraint, either equality - or inequality (see below): - * first N elements correspond to coefficients, - * last element corresponds to the right part. - All elements of C (including right part) must be finite. - CT - type of constraints, array[K]: - * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1] - * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1] - * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1] - K - number of equality/inequality constraints, K>=0: - * if given, only leading K elements of C/CT are used - * if not given, automatically determined from sizes of C/CT - -IMPORTANT: if you have linear constraints, it is strongly recommended to - set scale of variables with minlmsetscale(). QP solver which is - used to calculate linearly constrained steps heavily relies on - good scaling of input problems. - -IMPORTANT: solvers created with minlmcreatefgh() do not support linear - constraints. - -NOTE: linear (non-bound) constraints are satisfied only approximately - - there always exists some violation due to numerical errors and - algorithmic limitations. - -NOTE: general linear constraints add significant overhead to solution - process. Although solver performs roughly same amount of iterations - (when compared with similar box-only constrained problem), each - iteration now involves solution of linearly constrained QP - subproblem, which requires ~3-5 times more Cholesky decompositions. - Thus, if you can reformulate your problem in such way this it has - only box constraints, it may be beneficial to do so. - - -- ALGLIB -- - Copyright 14.01.2011 by Bochkanov Sergey -*************************************************************************/ -void minlmsetlc(const minlmstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams = alglib::xdefault); -void minlmsetlc(const minlmstate &state, const real_2d_array &c, const integer_1d_array &ct, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is used to change acceleration settings - -You can choose between three acceleration strategies: -* AccType=0, no acceleration. -* AccType=1, secant updates are used to update quadratic model after each - iteration. After fixed number of iterations (or after model breakdown) - we recalculate quadratic model using analytic Jacobian or finite - differences. Number of secant-based iterations depends on optimization - settings: about 3 iterations - when we have analytic Jacobian, up to 2*N - iterations - when we use finite differences to calculate Jacobian. - -AccType=1 is recommended when Jacobian calculation cost is prohibitively -high (several Mx1 function vector calculations followed by several NxN -Cholesky factorizations are faster than calculation of one M*N Jacobian). -It should also be used when we have no Jacobian, because finite difference -approximation takes too much time to compute. - -Table below list optimization protocols (XYZ protocol corresponds to -MinLMCreateXYZ) and acceleration types they support (and use by default). - -ACCELERATION TYPES SUPPORTED BY OPTIMIZATION PROTOCOLS: - -protocol 0 1 comment -V + + -VJ + + -FGH + - -DEFAULT VALUES: - -protocol 0 1 comment -V x without acceleration it is so slooooooooow -VJ x -FGH x - -NOTE: this function should be called before optimization. Attempt to call -it during algorithm iterations may result in unexpected behavior. - -NOTE: attempt to call this function with unsupported protocol/acceleration -combination will result in exception being thrown. - - -- ALGLIB -- - Copyright 14.10.2010 by Bochkanov Sergey -*************************************************************************/ -void minlmsetacctype(const minlmstate &state, const ae_int_t acctype, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool minlmiteration(const minlmstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This family of functions is used to launcn iterations of nonlinear optimizer - -These functions accept following parameters: - state - algorithm state - func - callback which calculates function (or merit function) - value func at given point x - grad - callback which calculates function (or merit function) - value func and gradient grad at given point x - hess - callback which calculates function (or merit function) - value func, gradient grad and Hessian hess at given point x - fvec - callback which calculates function vector fi[] - at given point x - jac - callback which calculates function vector fi[] - and Jacobian jac at given point x - rep - optional callback which is called after each iteration - can be NULL - ptr - optional pointer which is passed to func/grad/hess/jac/rep - can be NULL - -NOTES: - -1. Depending on function used to create state structure, this algorithm - may accept Jacobian and/or Hessian and/or gradient. According to the - said above, there ase several versions of this function, which accept - different sets of callbacks. - - This flexibility opens way to subtle errors - you may create state with - MinLMCreateFGH() (optimization using Hessian), but call function which - does not accept Hessian. So when algorithm will request Hessian, there - will be no callback to call. In this case exception will be thrown. - - Be careful to avoid such errors because there is no way to find them at - compile time - you can see them at runtime only. - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey - -*************************************************************************/ -void minlmoptimize(minlmstate &state, - void (*fvec)(const real_1d_array &x, real_1d_array &fi, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void minlmoptimize(minlmstate &state, - void (*fvec)(const real_1d_array &x, real_1d_array &fi, void *ptr), - void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void minlmoptimize(minlmstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*hess)(const real_1d_array &x, double &func, real_1d_array &grad, real_2d_array &hess, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void minlmoptimize(minlmstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); -void minlmoptimize(minlmstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), - void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function activates/deactivates verification of the user-supplied -analytic Jacobian. - -Upon activation of this option OptGuard integrity checker performs -numerical differentiation of your target function vector at the initial -point (note: future versions may also perform check at the final point) -and compares numerical Jacobian with analytic one provided by you. - -If difference is too large, an error flag is set and optimization session -continues. After optimization session is over, you can retrieve the report -which stores both Jacobians, and specific components highlighted as -suspicious by the OptGuard. - -The OptGuard report can be retrieved with minlmoptguardresults(). - -IMPORTANT: gradient check is a high-overhead option which will cost you - about 3*N additional function evaluations. In many cases it may - cost as much as the rest of the optimization session. - - YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO - CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY. - -NOTE: unlike previous incarnation of the gradient checking code, OptGuard - does NOT interrupt optimization even if it discovers bad gradient. - -INPUT PARAMETERS: - State - structure used to store algorithm state - TestStep - verification step used for numerical differentiation: - * TestStep=0 turns verification off - * TestStep>0 activates verification - You should carefully choose TestStep. Value which is - too large (so large that function behavior is non- - cubic at this scale) will lead to false alarms. Too - short step will result in rounding errors dominating - numerical derivative. - - You may use different step for different parameters by - means of setting scale with minlmsetscale(). - -=== EXPLANATION ========================================================== - -In order to verify gradient algorithm performs following steps: - * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i], - where X[i] is i-th component of the initial point and S[i] is a scale - of i-th parameter - * F(X) is evaluated at these trial points - * we perform one more evaluation in the middle point of the interval - * we build cubic model using function values and derivatives at trial - points and we compare its prediction with actual value in the middle - point - - -- ALGLIB -- - Copyright 15.06.2014 by Bochkanov Sergey -*************************************************************************/ -void minlmoptguardgradient(const minlmstate &state, const double teststep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Results of OptGuard integrity check, should be called after optimization -session is over. - -OptGuard checks analytic Jacobian against reference value obtained by -numerical differentiation with user-specified step. - -NOTE: other optimizers perform additional OptGuard checks for things like - C0/C1-continuity violations. However, LM optimizer can check only - for incorrect Jacobian. - - The reason is that unlike line search methods LM optimizer does not - perform extensive evaluations along the line. Thus, we simply do not - have enough data to catch C0/C1-violations. - -This check is activated with minlmoptguardgradient() function. - -Following flags are set when these errors are suspected: -* rep.badgradsuspected, and additionally: - * rep.badgradfidx for specific function (Jacobian row) suspected - * rep.badgradvidx for specific variable (Jacobian column) suspected - * rep.badgradxbase, a point where gradient/Jacobian is tested - * rep.badgraduser, user-provided gradient/Jacobian - * rep.badgradnum, reference gradient/Jacobian obtained via numerical - differentiation - -INPUT PARAMETERS: - state - algorithm state - -OUTPUT PARAMETERS: - rep - OptGuard report - - -- ALGLIB -- - Copyright 21.11.2018 by Bochkanov Sergey -*************************************************************************/ -void minlmoptguardresults(const minlmstate &state, optguardreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Levenberg-Marquardt algorithm results - -NOTE: if you activated OptGuard integrity checking functionality and want - to get OptGuard report, it can be retrieved with the help of - minlmoptguardresults() function. - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report; includes termination codes and - additional information. Termination codes are listed below, - see comments for this structure for more info. - Termination code is stored in rep.terminationtype field: - * -8 optimizer detected NAN/INF values either in the - function itself, or in its Jacobian - * -3 constraints are inconsistent - * 2 relative step is no more than EpsX. - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible - * 8 terminated by user who called minlmrequesttermination(). - X contains point which was "current accepted" when - termination request was submitted. - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmresults(const minlmstate &state, real_1d_array &x, minlmreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Levenberg-Marquardt algorithm results - -Buffered implementation of MinLMResults(), which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 10.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmresultsbuf(const minlmstate &state, real_1d_array &x, minlmreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine restarts LM algorithm from new point. All optimization -parameters are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure used for reverse communication previously - allocated with MinLMCreateXXX call. - X - new starting point. - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -void minlmrestartfrom(const minlmstate &state, const real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine submits request for termination of running optimizer. It -should be called from user-supplied callback when user decides that it is -time to "smoothly" terminate optimization process. As result, optimizer -stops at point which was "current accepted" when termination request was -submitted and returns error code 8 (successful termination). - -INPUT PARAMETERS: - State - optimizer structure - -NOTE: after request for termination optimizer may perform several - additional calls to user-supplied callbacks. It does NOT guarantee - to stop immediately - it just guarantees that these additional calls - will be discarded later. - -NOTE: calling this function on optimizer which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void minlmrequesttermination(const minlmstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is obsolete function. - -Since ALGLIB 3.3 it is equivalent to MinLMCreateVJ(). - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmcreatevgj(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams = alglib::xdefault); -void minlmcreatevgj(const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This is obsolete function. - -Since ALGLIB 3.3 it is equivalent to MinLMCreateFJ(). - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmcreatefgj(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams = alglib::xdefault); -void minlmcreatefgj(const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is considered obsolete since ALGLIB 3.1.0 and is present for -backward compatibility only. We recommend to use MinLMCreateVJ, which -provides similar, but more consistent and feature-rich interface. - - -- ALGLIB -- - Copyright 30.03.2009 by Bochkanov Sergey -*************************************************************************/ -void minlmcreatefj(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams = alglib::xdefault); -void minlmcreatefj(const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams = alglib::xdefault); -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (FUNCTIONS) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_CQMODELS) || !defined(AE_PARTIAL_BUILD) -void cqminit(ae_int_t n, convexquadraticmodel* s, ae_state *_state); -void cqmseta(convexquadraticmodel* s, - /* Real */ ae_matrix* a, - ae_bool isupper, - double alpha, - ae_state *_state); -void cqmgeta(convexquadraticmodel* s, - /* Real */ ae_matrix* a, - ae_state *_state); -void cqmrewritedensediagonal(convexquadraticmodel* s, - /* Real */ ae_vector* z, - ae_state *_state); -void cqmsetd(convexquadraticmodel* s, - /* Real */ ae_vector* d, - double tau, - ae_state *_state); -void cqmdropa(convexquadraticmodel* s, ae_state *_state); -void cqmsetb(convexquadraticmodel* s, - /* Real */ ae_vector* b, - ae_state *_state); -void cqmsetq(convexquadraticmodel* s, - /* Real */ ae_matrix* q, - /* Real */ ae_vector* r, - ae_int_t k, - double theta, - ae_state *_state); -void cqmsetactiveset(convexquadraticmodel* s, - /* Real */ ae_vector* x, - /* Boolean */ ae_vector* activeset, - ae_state *_state); -double cqmeval(convexquadraticmodel* s, - /* Real */ ae_vector* x, - ae_state *_state); -void cqmevalx(convexquadraticmodel* s, - /* Real */ ae_vector* x, - double* r, - double* noise, - ae_state *_state); -void cqmgradunconstrained(convexquadraticmodel* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* g, - ae_state *_state); -double cqmxtadx2(convexquadraticmodel* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* tmp, - ae_state *_state); -void cqmadx(convexquadraticmodel* s, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_state *_state); -ae_bool cqmconstrainedoptimum(convexquadraticmodel* s, - /* Real */ ae_vector* x, - ae_state *_state); -void cqmscalevector(convexquadraticmodel* s, - /* Real */ ae_vector* x, - ae_state *_state); -void cqmgetdiaga(convexquadraticmodel* s, - /* Real */ ae_vector* x, - ae_state *_state); -double cqmdebugconstrainedevalt(convexquadraticmodel* s, - /* Real */ ae_vector* x, - ae_state *_state); -double cqmdebugconstrainedevale(convexquadraticmodel* s, - /* Real */ ae_vector* x, - ae_state *_state); -void _convexquadraticmodel_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _convexquadraticmodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _convexquadraticmodel_clear(void* _p); -void _convexquadraticmodel_destroy(void* _p); -#endif -#if defined(AE_COMPILE_OPTGUARDAPI) || !defined(AE_PARTIAL_BUILD) -void optguardinitinternal(optguardreport* rep, - ae_int_t n, - ae_int_t k, - ae_state *_state); -void optguardexportreport(optguardreport* srcrep, - ae_int_t n, - ae_int_t k, - ae_bool badgradhasxj, - optguardreport* dstrep, - ae_state *_state); -void smoothnessmonitorexportc1test0report(optguardnonc1test0report* srcrep, - /* Real */ ae_vector* s, - optguardnonc1test0report* dstrep, - ae_state *_state); -void smoothnessmonitorexportc1test1report(optguardnonc1test1report* srcrep, - /* Real */ ae_vector* s, - optguardnonc1test1report* dstrep, - ae_state *_state); -ae_bool optguardallclear(optguardreport* rep, ae_state *_state); -void _optguardreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _optguardreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _optguardreport_clear(void* _p); -void _optguardreport_destroy(void* _p); -void _optguardnonc0report_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _optguardnonc0report_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _optguardnonc0report_clear(void* _p); -void _optguardnonc0report_destroy(void* _p); -void _optguardnonc1test0report_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _optguardnonc1test0report_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _optguardnonc1test0report_clear(void* _p); -void _optguardnonc1test0report_destroy(void* _p); -void _optguardnonc1test1report_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _optguardnonc1test1report_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _optguardnonc1test1report_clear(void* _p); -void _optguardnonc1test1report_destroy(void* _p); -#endif -#if defined(AE_COMPILE_OPTSERV) || !defined(AE_PARTIAL_BUILD) -void checkbcviolation(/* Boolean */ ae_vector* hasbndl, - /* Real */ ae_vector* bndl, - /* Boolean */ ae_vector* hasbndu, - /* Real */ ae_vector* bndu, - /* Real */ ae_vector* x, - ae_int_t n, - /* Real */ ae_vector* s, - ae_bool nonunits, - double* bcerr, - ae_int_t* bcidx, - ae_state *_state); -void checklcviolation(/* Real */ ae_matrix* cleic, - /* Integer */ ae_vector* lcsrcidx, - ae_int_t nec, - ae_int_t nic, - /* Real */ ae_vector* x, - ae_int_t n, - double* lcerr, - ae_int_t* lcidx, - ae_state *_state); -void checknlcviolation(/* Real */ ae_vector* fi, - ae_int_t ng, - ae_int_t nh, - double* nlcerr, - ae_int_t* nlcidx, - ae_state *_state); -void unscaleandchecknlcviolation(/* Real */ ae_vector* fi, - /* Real */ ae_vector* fscales, - ae_int_t ng, - ae_int_t nh, - double* nlcerr, - ae_int_t* nlcidx, - ae_state *_state); -void trimprepare(double f, double* threshold, ae_state *_state); -void trimfunction(double* f, - /* Real */ ae_vector* g, - ae_int_t n, - double threshold, - ae_state *_state); -ae_bool enforceboundaryconstraints(/* Real */ ae_vector* x, - /* Real */ ae_vector* bl, - /* Boolean */ ae_vector* havebl, - /* Real */ ae_vector* bu, - /* Boolean */ ae_vector* havebu, - ae_int_t nmain, - ae_int_t nslack, - ae_state *_state); -void projectgradientintobc(/* Real */ ae_vector* x, - /* Real */ ae_vector* g, - /* Real */ ae_vector* bl, - /* Boolean */ ae_vector* havebl, - /* Real */ ae_vector* bu, - /* Boolean */ ae_vector* havebu, - ae_int_t nmain, - ae_int_t nslack, - ae_state *_state); -void calculatestepbound(/* Real */ ae_vector* x, - /* Real */ ae_vector* d, - double alpha, - /* Real */ ae_vector* bndl, - /* Boolean */ ae_vector* havebndl, - /* Real */ ae_vector* bndu, - /* Boolean */ ae_vector* havebndu, - ae_int_t nmain, - ae_int_t nslack, - ae_int_t* variabletofreeze, - double* valuetofreeze, - double* maxsteplen, - ae_state *_state); -ae_int_t postprocessboundedstep(/* Real */ ae_vector* x, - /* Real */ ae_vector* xprev, - /* Real */ ae_vector* bndl, - /* Boolean */ ae_vector* havebndl, - /* Real */ ae_vector* bndu, - /* Boolean */ ae_vector* havebndu, - ae_int_t nmain, - ae_int_t nslack, - ae_int_t variabletofreeze, - double valuetofreeze, - double steptaken, - double maxsteplen, - ae_state *_state); -void filterdirection(/* Real */ ae_vector* d, - /* Real */ ae_vector* x, - /* Real */ ae_vector* bndl, - /* Boolean */ ae_vector* havebndl, - /* Real */ ae_vector* bndu, - /* Boolean */ ae_vector* havebndu, - /* Real */ ae_vector* s, - ae_int_t nmain, - ae_int_t nslack, - double droptol, - ae_state *_state); -ae_int_t numberofchangedconstraints(/* Real */ ae_vector* x, - /* Real */ ae_vector* xprev, - /* Real */ ae_vector* bndl, - /* Boolean */ ae_vector* havebndl, - /* Real */ ae_vector* bndu, - /* Boolean */ ae_vector* havebndu, - ae_int_t nmain, - ae_int_t nslack, - ae_state *_state); -ae_bool findfeasiblepoint(/* Real */ ae_vector* x, - /* Real */ ae_vector* bndl, - /* Boolean */ ae_vector* havebndl, - /* Real */ ae_vector* bndu, - /* Boolean */ ae_vector* havebndu, - ae_int_t nmain, - ae_int_t nslack, - /* Real */ ae_matrix* ce, - ae_int_t k, - double epsi, - ae_int_t* qpits, - ae_int_t* gpaits, - ae_state *_state); -ae_bool derivativecheck(double f0, - double df0, - double f1, - double df1, - double f, - double df, - double width, - ae_state *_state); -void estimateparabolicmodel(double absasum, - double absasum2, - double mx, - double mb, - double md, - double d1, - double d2, - ae_int_t* d1est, - ae_int_t* d2est, - ae_state *_state); -void inexactlbfgspreconditioner(/* Real */ ae_vector* s, - ae_int_t n, - /* Real */ ae_vector* d, - /* Real */ ae_vector* c, - /* Real */ ae_matrix* w, - ae_int_t k, - precbuflbfgs* buf, - ae_state *_state); -void preparelowrankpreconditioner(/* Real */ ae_vector* d, - /* Real */ ae_vector* c, - /* Real */ ae_matrix* w, - ae_int_t n, - ae_int_t k, - precbuflowrank* buf, - ae_state *_state); -void applylowrankpreconditioner(/* Real */ ae_vector* s, - precbuflowrank* buf, - ae_state *_state); -void smoothnessmonitorinit(smoothnessmonitor* monitor, - /* Real */ ae_vector* s, - ae_int_t n, - ae_int_t k, - ae_bool checksmoothness, - ae_state *_state); -void smoothnessmonitorstartlinesearch(smoothnessmonitor* monitor, - /* Real */ ae_vector* x, - /* Real */ ae_vector* fi, - /* Real */ ae_matrix* jac, - ae_state *_state); -void smoothnessmonitorstartlinesearch1u(smoothnessmonitor* monitor, - /* Real */ ae_vector* s, - /* Real */ ae_vector* invs, - /* Real */ ae_vector* x, - double f0, - /* Real */ ae_vector* j0, - ae_state *_state); -void smoothnessmonitorenqueuepoint(smoothnessmonitor* monitor, - /* Real */ ae_vector* d, - double stp, - /* Real */ ae_vector* x, - /* Real */ ae_vector* fi, - /* Real */ ae_matrix* jac, - ae_state *_state); -void smoothnessmonitorenqueuepoint1u(smoothnessmonitor* monitor, - /* Real */ ae_vector* s, - /* Real */ ae_vector* invs, - /* Real */ ae_vector* d, - double stp, - /* Real */ ae_vector* x, - double f0, - /* Real */ ae_vector* j0, - ae_state *_state); -void smoothnessmonitorfinalizelinesearch(smoothnessmonitor* monitor, - ae_state *_state); -void smoothnessmonitorstartprobing(smoothnessmonitor* monitor, - double stpmax, - ae_int_t nvalues, - double stepscale, - ae_state *_state); -ae_bool smoothnessmonitorprobe(smoothnessmonitor* monitor, - ae_state *_state); -void smoothnessmonitortraceprobingresults(smoothnessmonitor* monitor, - ae_state *_state); -void smoothnessmonitortracestatus(smoothnessmonitor* monitor, - ae_bool callersuggeststrace, - ae_state *_state); -void smoothnessmonitorexportreport(smoothnessmonitor* monitor, - optguardreport* rep, - ae_state *_state); -ae_bool smoothnessmonitorcheckgradientatx0(smoothnessmonitor* monitor, - /* Real */ ae_vector* unscaledx0, - /* Real */ ae_vector* s, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_bool hasboxconstraints, - double teststep, - ae_state *_state); -void _precbuflbfgs_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _precbuflbfgs_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _precbuflbfgs_clear(void* _p); -void _precbuflbfgs_destroy(void* _p); -void _precbuflowrank_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _precbuflowrank_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _precbuflowrank_clear(void* _p); -void _precbuflowrank_destroy(void* _p); -void _smoothnessmonitor_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _smoothnessmonitor_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _smoothnessmonitor_clear(void* _p); -void _smoothnessmonitor_destroy(void* _p); -#endif -#if defined(AE_COMPILE_SNNLS) || !defined(AE_PARTIAL_BUILD) -void snnlsinit(ae_int_t nsmax, - ae_int_t ndmax, - ae_int_t nrmax, - snnlssolver* s, - ae_state *_state); -void snnlssetproblem(snnlssolver* s, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* b, - ae_int_t ns, - ae_int_t nd, - ae_int_t nr, - ae_state *_state); -void snnlsdropnnc(snnlssolver* s, ae_int_t idx, ae_state *_state); -void snnlssolve(snnlssolver* s, - /* Real */ ae_vector* x, - ae_state *_state); -void _snnlssolver_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _snnlssolver_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _snnlssolver_clear(void* _p); -void _snnlssolver_destroy(void* _p); -#endif -#if defined(AE_COMPILE_SACTIVESETS) || !defined(AE_PARTIAL_BUILD) -void sasinit(ae_int_t n, sactiveset* s, ae_state *_state); -void sassetscale(sactiveset* state, - /* Real */ ae_vector* s, - ae_state *_state); -void sassetprecdiag(sactiveset* state, - /* Real */ ae_vector* d, - ae_state *_state); -void sassetbc(sactiveset* state, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_state *_state); -void sassetlc(sactiveset* state, - /* Real */ ae_matrix* c, - /* Integer */ ae_vector* ct, - ae_int_t k, - ae_state *_state); -void sassetlcx(sactiveset* state, - /* Real */ ae_matrix* cleic, - ae_int_t nec, - ae_int_t nic, - ae_state *_state); -ae_bool sasstartoptimization(sactiveset* state, - /* Real */ ae_vector* x, - ae_state *_state); -void sasexploredirection(sactiveset* state, - /* Real */ ae_vector* d, - double* stpmax, - ae_int_t* cidx, - double* vval, - ae_state *_state); -ae_int_t sasmoveto(sactiveset* state, - /* Real */ ae_vector* xn, - ae_bool needact, - ae_int_t cidx, - double cval, - ae_state *_state); -void sasimmediateactivation(sactiveset* state, - ae_int_t cidx, - double cval, - ae_state *_state); -void sasconstraineddescent(sactiveset* state, - /* Real */ ae_vector* g, - /* Real */ ae_vector* d, - ae_state *_state); -void sasconstraineddescentprec(sactiveset* state, - /* Real */ ae_vector* g, - /* Real */ ae_vector* d, - ae_state *_state); -void sasconstraineddirection(sactiveset* state, - /* Real */ ae_vector* d, - ae_state *_state); -void sasconstraineddirectionprec(sactiveset* state, - /* Real */ ae_vector* d, - ae_state *_state); -void sascorrection(sactiveset* state, - /* Real */ ae_vector* x, - double* penalty, - ae_state *_state); -double sasactivelcpenalty1(sactiveset* state, - /* Real */ ae_vector* x, - ae_state *_state); -double sasscaledconstrainednorm(sactiveset* state, - /* Real */ ae_vector* d, - ae_state *_state); -void sasstopoptimization(sactiveset* state, ae_state *_state); -void sasreactivateconstraints(sactiveset* state, - /* Real */ ae_vector* gc, - ae_state *_state); -void sasreactivateconstraintsprec(sactiveset* state, - /* Real */ ae_vector* gc, - ae_state *_state); -void sasrebuildbasis(sactiveset* state, ae_state *_state); -void sasappendtobasis(sactiveset* state, - /* Boolean */ ae_vector* newentries, - ae_state *_state); -void _sactiveset_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _sactiveset_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _sactiveset_clear(void* _p); -void _sactiveset_destroy(void* _p); -#endif -#if defined(AE_COMPILE_QQPSOLVER) || !defined(AE_PARTIAL_BUILD) -void qqploaddefaults(ae_int_t n, qqpsettings* s, ae_state *_state); -void qqpcopysettings(qqpsettings* src, qqpsettings* dst, ae_state *_state); -void qqppreallocategrowdense(qqpbuffers* sstate, - ae_int_t nexpected, - ae_int_t ngrowto, - ae_state *_state); -void qqpoptimize(convexquadraticmodel* cqmac, - sparsematrix* sparseac, - /* Real */ ae_matrix* denseac, - ae_int_t akind, - ae_bool isupper, - /* Real */ ae_vector* bc, - /* Real */ ae_vector* bndlc, - /* Real */ ae_vector* bnduc, - /* Real */ ae_vector* sc, - /* Real */ ae_vector* xoriginc, - ae_int_t nc, - qqpsettings* settings, - qqpbuffers* sstate, - /* Real */ ae_vector* xs, - ae_int_t* terminationtype, - ae_state *_state); -void _qqpsettings_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _qqpsettings_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _qqpsettings_clear(void* _p); -void _qqpsettings_destroy(void* _p); -void _qqpbuffers_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _qqpbuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _qqpbuffers_clear(void* _p); -void _qqpbuffers_destroy(void* _p); -#endif -#if defined(AE_COMPILE_MINLBFGS) || !defined(AE_PARTIAL_BUILD) -void minlbfgscreate(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* x, - minlbfgsstate* state, - ae_state *_state); -void minlbfgscreatef(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* x, - double diffstep, - minlbfgsstate* state, - ae_state *_state); -void minlbfgssetcond(minlbfgsstate* state, - double epsg, - double epsf, - double epsx, - ae_int_t maxits, - ae_state *_state); -void minlbfgssetxrep(minlbfgsstate* state, - ae_bool needxrep, - ae_state *_state); -void minlbfgssetstpmax(minlbfgsstate* state, - double stpmax, - ae_state *_state); -void minlbfgssetscale(minlbfgsstate* state, - /* Real */ ae_vector* s, - ae_state *_state); -void minlbfgscreatex(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* x, - ae_int_t flags, - double diffstep, - minlbfgsstate* state, - ae_state *_state); -void minlbfgssetprecdefault(minlbfgsstate* state, ae_state *_state); -void minlbfgssetpreccholesky(minlbfgsstate* state, - /* Real */ ae_matrix* p, - ae_bool isupper, - ae_state *_state); -void minlbfgssetprecdiag(minlbfgsstate* state, - /* Real */ ae_vector* d, - ae_state *_state); -void minlbfgssetprecscale(minlbfgsstate* state, ae_state *_state); -void minlbfgssetprecrankklbfgsfast(minlbfgsstate* state, - /* Real */ ae_vector* d, - /* Real */ ae_vector* c, - /* Real */ ae_matrix* w, - ae_int_t cnt, - ae_state *_state); -void minlbfgssetpreclowrankexact(minlbfgsstate* state, - /* Real */ ae_vector* d, - /* Real */ ae_vector* c, - /* Real */ ae_matrix* w, - ae_int_t cnt, - ae_state *_state); -ae_bool minlbfgsiteration(minlbfgsstate* state, ae_state *_state); -void minlbfgsoptguardgradient(minlbfgsstate* state, - double teststep, - ae_state *_state); -void minlbfgsoptguardsmoothness(minlbfgsstate* state, - ae_int_t level, - ae_state *_state); -void minlbfgsoptguardresults(minlbfgsstate* state, - optguardreport* rep, - ae_state *_state); -void minlbfgsoptguardnonc1test0results(minlbfgsstate* state, - optguardnonc1test0report* strrep, - optguardnonc1test0report* lngrep, - ae_state *_state); -void minlbfgsoptguardnonc1test1results(minlbfgsstate* state, - optguardnonc1test1report* strrep, - optguardnonc1test1report* lngrep, - ae_state *_state); -void minlbfgsresults(minlbfgsstate* state, - /* Real */ ae_vector* x, - minlbfgsreport* rep, - ae_state *_state); -void minlbfgsresultsbuf(minlbfgsstate* state, - /* Real */ ae_vector* x, - minlbfgsreport* rep, - ae_state *_state); -void minlbfgsrestartfrom(minlbfgsstate* state, - /* Real */ ae_vector* x, - ae_state *_state); -void minlbfgsrequesttermination(minlbfgsstate* state, ae_state *_state); -void _minlbfgsstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minlbfgsstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minlbfgsstate_clear(void* _p); -void _minlbfgsstate_destroy(void* _p); -void _minlbfgsreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minlbfgsreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minlbfgsreport_clear(void* _p); -void _minlbfgsreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_LPQPSERV) || !defined(AE_PARTIAL_BUILD) -void scaleshiftbcinplace(/* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_int_t n, - ae_state *_state); -void scaleshiftdensebrlcinplace(/* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - ae_int_t n, - /* Real */ ae_matrix* densea, - /* Real */ ae_vector* ab, - /* Real */ ae_vector* ar, - ae_int_t m, - ae_state *_state); -void scaleshiftmixedbrlcinplace(/* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - ae_int_t n, - sparsematrix* sparsea, - ae_int_t msparse, - /* Real */ ae_matrix* densea, - ae_int_t mdense, - /* Real */ ae_vector* ab, - /* Real */ ae_vector* ar, - ae_state *_state); -void scaledenseqpinplace(/* Real */ ae_matrix* densea, - ae_bool isupper, - ae_int_t nmain, - /* Real */ ae_vector* denseb, - ae_int_t ntotal, - /* Real */ ae_vector* s, - ae_state *_state); -void scalesparseqpinplace(/* Real */ ae_vector* s, - ae_int_t n, - sparsematrix* sparsea, - /* Real */ ae_vector* denseb, - ae_state *_state); -void normalizedensebrlcinplace(/* Real */ ae_matrix* densea, - /* Real */ ae_vector* ab, - /* Real */ ae_vector* ar, - ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* rownorms, - ae_bool neednorms, - ae_state *_state); -void normalizemixedbrlcinplace(sparsematrix* sparsea, - ae_int_t msparse, - /* Real */ ae_matrix* densea, - ae_int_t mdense, - /* Real */ ae_vector* ab, - /* Real */ ae_vector* ar, - ae_int_t n, - ae_bool limitedamplification, - /* Real */ ae_vector* rownorms, - ae_bool neednorms, - ae_state *_state); -double normalizedenseqpinplace(/* Real */ ae_matrix* densea, - ae_bool isupper, - ae_int_t nmain, - /* Real */ ae_vector* denseb, - ae_int_t ntotal, - ae_state *_state); -double normalizesparseqpinplace(sparsematrix* sparsea, - ae_bool isupper, - /* Real */ ae_vector* denseb, - ae_int_t n, - ae_state *_state); -void unscaleunshiftpointbc(/* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - /* Real */ ae_vector* rawbndl, - /* Real */ ae_vector* rawbndu, - /* Real */ ae_vector* sclsftbndl, - /* Real */ ae_vector* sclsftbndu, - /* Boolean */ ae_vector* hasbndl, - /* Boolean */ ae_vector* hasbndu, - /* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state); -#endif -#if defined(AE_COMPILE_VIPMSOLVER) || !defined(AE_PARTIAL_BUILD) -void vipminitdense(vipmstate* state, - /* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - ae_int_t n, - ae_state *_state); -void vipminitdensewithslacks(vipmstate* state, - /* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - ae_int_t nmain, - ae_int_t n, - ae_state *_state); -void vipminitsparse(vipmstate* state, - /* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - ae_int_t n, - ae_state *_state); -void vipmsetquadraticlinear(vipmstate* state, - /* Real */ ae_matrix* denseh, - sparsematrix* sparseh, - ae_int_t hkind, - ae_bool isupper, - /* Real */ ae_vector* c, - ae_state *_state); -void vipmsetconstraints(vipmstate* state, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - sparsematrix* sparsea, - ae_int_t msparse, - /* Real */ ae_matrix* densea, - ae_int_t mdense, - /* Real */ ae_vector* cl, - /* Real */ ae_vector* cu, - ae_state *_state); -void vipmsetcond(vipmstate* state, - double epsp, - double epsd, - double epsgap, - ae_state *_state); -void vipmoptimize(vipmstate* state, - ae_bool dropbigbounds, - /* Real */ ae_vector* xs, - /* Real */ ae_vector* lagbc, - /* Real */ ae_vector* laglc, - ae_int_t* terminationtype, - ae_state *_state); -void _vipmvars_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _vipmvars_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _vipmvars_clear(void* _p); -void _vipmvars_destroy(void* _p); -void _vipmrighthandside_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _vipmrighthandside_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _vipmrighthandside_clear(void* _p); -void _vipmrighthandside_destroy(void* _p); -void _vipmstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _vipmstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _vipmstate_clear(void* _p); -void _vipmstate_destroy(void* _p); -#endif -#if defined(AE_COMPILE_NLCSQP) || !defined(AE_PARTIAL_BUILD) -void minsqpinitbuf(/* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_vector* s, - /* Real */ ae_vector* x0, - ae_int_t n, - /* Real */ ae_matrix* cleic, - /* Integer */ ae_vector* lcsrcidx, - ae_int_t nec, - ae_int_t nic, - ae_int_t nlec, - ae_int_t nlic, - double epsx, - ae_int_t maxits, - minsqpstate* state, - ae_state *_state); -ae_bool minsqpiteration(minsqpstate* state, - smoothnessmonitor* smonitor, - ae_bool userterminationneeded, - ae_state *_state); -void _minsqpsubsolver_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minsqpsubsolver_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minsqpsubsolver_clear(void* _p); -void _minsqpsubsolver_destroy(void* _p); -void _minsqptmplagrangian_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minsqptmplagrangian_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minsqptmplagrangian_clear(void* _p); -void _minsqptmplagrangian_destroy(void* _p); -void _minsqptmpmerit_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minsqptmpmerit_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minsqptmpmerit_clear(void* _p); -void _minsqptmpmerit_destroy(void* _p); -void _minsqpmeritphasestate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minsqpmeritphasestate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minsqpmeritphasestate_clear(void* _p); -void _minsqpmeritphasestate_destroy(void* _p); -void _minsqpstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minsqpstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minsqpstate_clear(void* _p); -void _minsqpstate_destroy(void* _p); -#endif -#if defined(AE_COMPILE_QPDENSEAULSOLVER) || !defined(AE_PARTIAL_BUILD) -void qpdenseaulloaddefaults(ae_int_t nmain, - qpdenseaulsettings* s, - ae_state *_state); -void qpdenseauloptimize(convexquadraticmodel* a, - sparsematrix* sparsea, - ae_int_t akind, - ae_bool sparseaupper, - /* Real */ ae_vector* b, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - ae_int_t nn, - /* Real */ ae_matrix* cleic, - ae_int_t dnec, - ae_int_t dnic, - sparsematrix* scleic, - ae_int_t snec, - ae_int_t snic, - ae_bool renormlc, - qpdenseaulsettings* settings, - qpdenseaulbuffers* state, - /* Real */ ae_vector* xs, - /* Real */ ae_vector* lagbc, - /* Real */ ae_vector* laglc, - ae_int_t* terminationtype, - ae_state *_state); -void _qpdenseaulsettings_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _qpdenseaulsettings_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _qpdenseaulsettings_clear(void* _p); -void _qpdenseaulsettings_destroy(void* _p); -void _qpdenseaulbuffers_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _qpdenseaulbuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _qpdenseaulbuffers_clear(void* _p); -void _qpdenseaulbuffers_destroy(void* _p); -#endif -#if defined(AE_COMPILE_MINBLEIC) || !defined(AE_PARTIAL_BUILD) -void minbleiccreate(ae_int_t n, - /* Real */ ae_vector* x, - minbleicstate* state, - ae_state *_state); -void minbleiccreatef(ae_int_t n, - /* Real */ ae_vector* x, - double diffstep, - minbleicstate* state, - ae_state *_state); -void minbleicsetbc(minbleicstate* state, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_state *_state); -void minbleicsetlc(minbleicstate* state, - /* Real */ ae_matrix* c, - /* Integer */ ae_vector* ct, - ae_int_t k, - ae_state *_state); -void minbleicsetcond(minbleicstate* state, - double epsg, - double epsf, - double epsx, - ae_int_t maxits, - ae_state *_state); -void minbleicsetscale(minbleicstate* state, - /* Real */ ae_vector* s, - ae_state *_state); -void minbleicsetprecdefault(minbleicstate* state, ae_state *_state); -void minbleicsetprecdiag(minbleicstate* state, - /* Real */ ae_vector* d, - ae_state *_state); -void minbleicsetprecscale(minbleicstate* state, ae_state *_state); -void minbleicsetxrep(minbleicstate* state, - ae_bool needxrep, - ae_state *_state); -void minbleicsetdrep(minbleicstate* state, - ae_bool needdrep, - ae_state *_state); -void minbleicsetstpmax(minbleicstate* state, - double stpmax, - ae_state *_state); -ae_bool minbleiciteration(minbleicstate* state, ae_state *_state); -void minbleicoptguardgradient(minbleicstate* state, - double teststep, - ae_state *_state); -void minbleicoptguardsmoothness(minbleicstate* state, - ae_int_t level, - ae_state *_state); -void minbleicoptguardresults(minbleicstate* state, - optguardreport* rep, - ae_state *_state); -void minbleicoptguardnonc1test0results(minbleicstate* state, - optguardnonc1test0report* strrep, - optguardnonc1test0report* lngrep, - ae_state *_state); -void minbleicoptguardnonc1test1results(minbleicstate* state, - optguardnonc1test1report* strrep, - optguardnonc1test1report* lngrep, - ae_state *_state); -void minbleicresults(minbleicstate* state, - /* Real */ ae_vector* x, - minbleicreport* rep, - ae_state *_state); -void minbleicresultsbuf(minbleicstate* state, - /* Real */ ae_vector* x, - minbleicreport* rep, - ae_state *_state); -void minbleicrestartfrom(minbleicstate* state, - /* Real */ ae_vector* x, - ae_state *_state); -void minbleicrequesttermination(minbleicstate* state, ae_state *_state); -void minbleicemergencytermination(minbleicstate* state, ae_state *_state); -void _minbleicstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minbleicstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minbleicstate_clear(void* _p); -void _minbleicstate_destroy(void* _p); -void _minbleicreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minbleicreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minbleicreport_clear(void* _p); -void _minbleicreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_QPBLEICSOLVER) || !defined(AE_PARTIAL_BUILD) -void qpbleicloaddefaults(ae_int_t nmain, - qpbleicsettings* s, - ae_state *_state); -void qpbleiccopysettings(qpbleicsettings* src, - qpbleicsettings* dst, - ae_state *_state); -void qpbleicoptimize(convexquadraticmodel* a, - sparsematrix* sparsea, - ae_int_t akind, - ae_bool sparseaupper, - double absasum, - double absasum2, - /* Real */ ae_vector* b, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_vector* s, - /* Real */ ae_vector* xorigin, - ae_int_t n, - /* Real */ ae_matrix* cleic, - ae_int_t nec, - ae_int_t nic, - qpbleicsettings* settings, - qpbleicbuffers* sstate, - ae_bool* firstcall, - /* Real */ ae_vector* xs, - ae_int_t* terminationtype, - ae_state *_state); -void _qpbleicsettings_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _qpbleicsettings_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _qpbleicsettings_clear(void* _p); -void _qpbleicsettings_destroy(void* _p); -void _qpbleicbuffers_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _qpbleicbuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _qpbleicbuffers_clear(void* _p); -void _qpbleicbuffers_destroy(void* _p); -#endif -#if defined(AE_COMPILE_MINQP) || !defined(AE_PARTIAL_BUILD) -void minqpcreate(ae_int_t n, minqpstate* state, ae_state *_state); -void minqpsetlinearterm(minqpstate* state, - /* Real */ ae_vector* b, - ae_state *_state); -void minqpsetquadraticterm(minqpstate* state, - /* Real */ ae_matrix* a, - ae_bool isupper, - ae_state *_state); -void minqpsetquadratictermsparse(minqpstate* state, - sparsematrix* a, - ae_bool isupper, - ae_state *_state); -void minqpsetstartingpoint(minqpstate* state, - /* Real */ ae_vector* x, - ae_state *_state); -void minqpsetorigin(minqpstate* state, - /* Real */ ae_vector* xorigin, - ae_state *_state); -void minqpsetscale(minqpstate* state, - /* Real */ ae_vector* s, - ae_state *_state); -void minqpsetscaleautodiag(minqpstate* state, ae_state *_state); -void minqpsetalgobleic(minqpstate* state, - double epsg, - double epsf, - double epsx, - ae_int_t maxits, - ae_state *_state); -void minqpsetalgodenseaul(minqpstate* state, - double epsx, - double rho, - ae_int_t itscnt, - ae_state *_state); -void minqpsetalgodenseipm(minqpstate* state, double eps, ae_state *_state); -void minqpsetalgosparseipm(minqpstate* state, - double eps, - ae_state *_state); -void minqpsetalgoquickqp(minqpstate* state, - double epsg, - double epsf, - double epsx, - ae_int_t maxouterits, - ae_bool usenewton, - ae_state *_state); -void minqpsetbc(minqpstate* state, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_state *_state); -void minqpsetbcall(minqpstate* state, - double bndl, - double bndu, - ae_state *_state); -void minqpsetbci(minqpstate* state, - ae_int_t i, - double bndl, - double bndu, - ae_state *_state); -void minqpsetlc(minqpstate* state, - /* Real */ ae_matrix* c, - /* Integer */ ae_vector* ct, - ae_int_t k, - ae_state *_state); -void minqpsetlcsparse(minqpstate* state, - sparsematrix* c, - /* Integer */ ae_vector* ct, - ae_int_t k, - ae_state *_state); -void minqpsetlcmixed(minqpstate* state, - sparsematrix* sparsec, - /* Integer */ ae_vector* sparsect, - ae_int_t sparsek, - /* Real */ ae_matrix* densec, - /* Integer */ ae_vector* densect, - ae_int_t densek, - ae_state *_state); -void minqpsetlcmixedlegacy(minqpstate* state, - /* Real */ ae_matrix* densec, - /* Integer */ ae_vector* densect, - ae_int_t densek, - sparsematrix* sparsec, - /* Integer */ ae_vector* sparsect, - ae_int_t sparsek, - ae_state *_state); -void minqpsetlc2dense(minqpstate* state, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t k, - ae_state *_state); -void minqpsetlc2(minqpstate* state, - sparsematrix* a, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t k, - ae_state *_state); -void minqpsetlc2mixed(minqpstate* state, - sparsematrix* sparsea, - ae_int_t ksparse, - /* Real */ ae_matrix* densea, - ae_int_t kdense, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_state *_state); -void minqpaddlc2dense(minqpstate* state, - /* Real */ ae_vector* a, - double al, - double au, - ae_state *_state); -void minqpaddlc2(minqpstate* state, - /* Integer */ ae_vector* idxa, - /* Real */ ae_vector* vala, - ae_int_t nnz, - double al, - double au, - ae_state *_state); -void minqpoptimize(minqpstate* state, ae_state *_state); -void minqpresults(minqpstate* state, - /* Real */ ae_vector* x, - minqpreport* rep, - ae_state *_state); -void minqpresultsbuf(minqpstate* state, - /* Real */ ae_vector* x, - minqpreport* rep, - ae_state *_state); -void minqpsetlineartermfast(minqpstate* state, - /* Real */ ae_vector* b, - ae_state *_state); -void minqpsetquadratictermfast(minqpstate* state, - /* Real */ ae_matrix* a, - ae_bool isupper, - double s, - ae_state *_state); -void minqprewritediagonal(minqpstate* state, - /* Real */ ae_vector* s, - ae_state *_state); -void minqpsetstartingpointfast(minqpstate* state, - /* Real */ ae_vector* x, - ae_state *_state); -void minqpsetoriginfast(minqpstate* state, - /* Real */ ae_vector* xorigin, - ae_state *_state); -void _minqpstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minqpstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minqpstate_clear(void* _p); -void _minqpstate_destroy(void* _p); -void _minqpreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minqpreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minqpreport_clear(void* _p); -void _minqpreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_LPQPPRESOLVE) || !defined(AE_PARTIAL_BUILD) -void presolvenonescaleuser(/* Real */ ae_vector* s, - /* Real */ ae_vector* c, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_int_t n, - sparsematrix* sparsea, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t k, - presolveinfo* info, - ae_state *_state); -void presolvebwd(presolveinfo* info, - /* Real */ ae_vector* x, - /* Integer */ ae_vector* stats, - /* Real */ ae_vector* lagbc, - /* Real */ ae_vector* laglc, - ae_state *_state); -void _presolveinfo_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _presolveinfo_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _presolveinfo_clear(void* _p); -void _presolveinfo_destroy(void* _p); -#endif -#if defined(AE_COMPILE_REVISEDDUALSIMPLEX) || !defined(AE_PARTIAL_BUILD) -void dsssettingsinit(dualsimplexsettings* settings, ae_state *_state); -void dssinit(ae_int_t n, dualsimplexstate* s, ae_state *_state); -void dsssetproblem(dualsimplexstate* state, - /* Real */ ae_vector* c, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_matrix* densea, - sparsematrix* sparsea, - ae_int_t akind, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t k, - dualsimplexbasis* proposedbasis, - ae_int_t basisinittype, - dualsimplexsettings* settings, - ae_state *_state); -void dssexportbasis(dualsimplexstate* state, - dualsimplexbasis* basis, - ae_state *_state); -void dssoptimize(dualsimplexstate* state, - dualsimplexsettings* settings, - ae_state *_state); -void _dualsimplexsettings_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _dualsimplexsettings_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _dualsimplexsettings_clear(void* _p); -void _dualsimplexsettings_destroy(void* _p); -void _dssvector_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _dssvector_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _dssvector_clear(void* _p); -void _dssvector_destroy(void* _p); -void _dualsimplexbasis_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _dualsimplexbasis_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _dualsimplexbasis_clear(void* _p); -void _dualsimplexbasis_destroy(void* _p); -void _dualsimplexsubproblem_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _dualsimplexsubproblem_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _dualsimplexsubproblem_clear(void* _p); -void _dualsimplexsubproblem_destroy(void* _p); -void _dualsimplexstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _dualsimplexstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _dualsimplexstate_clear(void* _p); -void _dualsimplexstate_destroy(void* _p); -#endif -#if defined(AE_COMPILE_MINLP) || !defined(AE_PARTIAL_BUILD) -void minlpcreate(ae_int_t n, minlpstate* state, ae_state *_state); -void minlpsetalgodss(minlpstate* state, double eps, ae_state *_state); -void minlpsetalgoipm(minlpstate* state, double eps, ae_state *_state); -void minlpsetcost(minlpstate* state, - /* Real */ ae_vector* c, - ae_state *_state); -void minlpsetscale(minlpstate* state, - /* Real */ ae_vector* s, - ae_state *_state); -void minlpsetbc(minlpstate* state, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_state *_state); -void minlpsetbcall(minlpstate* state, - double bndl, - double bndu, - ae_state *_state); -void minlpsetbci(minlpstate* state, - ae_int_t i, - double bndl, - double bndu, - ae_state *_state); -void minlpsetlc(minlpstate* state, - /* Real */ ae_matrix* a, - /* Integer */ ae_vector* ct, - ae_int_t k, - ae_state *_state); -void minlpsetlc2dense(minlpstate* state, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t k, - ae_state *_state); -void minlpsetlc2(minlpstate* state, - sparsematrix* a, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t k, - ae_state *_state); -void minlpaddlc2dense(minlpstate* state, - /* Real */ ae_vector* a, - double al, - double au, - ae_state *_state); -void minlpaddlc2(minlpstate* state, - /* Integer */ ae_vector* idxa, - /* Real */ ae_vector* vala, - ae_int_t nnz, - double al, - double au, - ae_state *_state); -void minlpoptimize(minlpstate* state, ae_state *_state); -void minlpresults(minlpstate* state, - /* Real */ ae_vector* x, - minlpreport* rep, - ae_state *_state); -void minlpresultsbuf(minlpstate* state, - /* Real */ ae_vector* x, - minlpreport* rep, - ae_state *_state); -void _minlpstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minlpstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minlpstate_clear(void* _p); -void _minlpstate_destroy(void* _p); -void _minlpreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minlpreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minlpreport_clear(void* _p); -void _minlpreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_NLCSLP) || !defined(AE_PARTIAL_BUILD) -void minslpinitbuf(/* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_vector* s, - /* Real */ ae_vector* x0, - ae_int_t n, - /* Real */ ae_matrix* cleic, - /* Integer */ ae_vector* lcsrcidx, - ae_int_t nec, - ae_int_t nic, - ae_int_t nlec, - ae_int_t nlic, - double epsx, - ae_int_t maxits, - minslpstate* state, - ae_state *_state); -ae_bool minslpiteration(minslpstate* state, - smoothnessmonitor* smonitor, - ae_bool userterminationneeded, - ae_state *_state); -void _minslpsubsolver_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minslpsubsolver_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minslpsubsolver_clear(void* _p); -void _minslpsubsolver_destroy(void* _p); -void _minslptmplagrangian_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minslptmplagrangian_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minslptmplagrangian_clear(void* _p); -void _minslptmplagrangian_destroy(void* _p); -void _minslptmpmerit_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minslptmpmerit_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minslptmpmerit_clear(void* _p); -void _minslptmpmerit_destroy(void* _p); -void _minslpphase13state_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minslpphase13state_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minslpphase13state_clear(void* _p); -void _minslpphase13state_destroy(void* _p); -void _minslpphase2state_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minslpphase2state_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minslpphase2state_clear(void* _p); -void _minslpphase2state_destroy(void* _p); -void _minslpstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minslpstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minslpstate_clear(void* _p); -void _minslpstate_destroy(void* _p); -#endif -#if defined(AE_COMPILE_MINNLC) || !defined(AE_PARTIAL_BUILD) -void minnlccreate(ae_int_t n, - /* Real */ ae_vector* x, - minnlcstate* state, - ae_state *_state); -void minnlccreatef(ae_int_t n, - /* Real */ ae_vector* x, - double diffstep, - minnlcstate* state, - ae_state *_state); -void minnlcsetbc(minnlcstate* state, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_state *_state); -void minnlcsetlc(minnlcstate* state, - /* Real */ ae_matrix* c, - /* Integer */ ae_vector* ct, - ae_int_t k, - ae_state *_state); -void minnlcsetnlc(minnlcstate* state, - ae_int_t nlec, - ae_int_t nlic, - ae_state *_state); -void minnlcsetcond(minnlcstate* state, - double epsx, - ae_int_t maxits, - ae_state *_state); -void minnlcsetscale(minnlcstate* state, - /* Real */ ae_vector* s, - ae_state *_state); -void minnlcsetprecinexact(minnlcstate* state, ae_state *_state); -void minnlcsetprecexactlowrank(minnlcstate* state, - ae_int_t updatefreq, - ae_state *_state); -void minnlcsetprecexactrobust(minnlcstate* state, - ae_int_t updatefreq, - ae_state *_state); -void minnlcsetprecnone(minnlcstate* state, ae_state *_state); -void minnlcsetstpmax(minnlcstate* state, double stpmax, ae_state *_state); -void minnlcsetalgoaul(minnlcstate* state, - double rho, - ae_int_t itscnt, - ae_state *_state); -void minnlcsetalgoslp(minnlcstate* state, ae_state *_state); -void minnlcsetalgosqp(minnlcstate* state, ae_state *_state); -void minnlcsetxrep(minnlcstate* state, ae_bool needxrep, ae_state *_state); -ae_bool minnlciteration(minnlcstate* state, ae_state *_state); -void minnlcoptguardgradient(minnlcstate* state, - double teststep, - ae_state *_state); -void minnlcoptguardsmoothness(minnlcstate* state, - ae_int_t level, - ae_state *_state); -void minnlcoptguardresults(minnlcstate* state, - optguardreport* rep, - ae_state *_state); -void minnlcoptguardnonc1test0results(minnlcstate* state, - optguardnonc1test0report* strrep, - optguardnonc1test0report* lngrep, - ae_state *_state); -void minnlcoptguardnonc1test1results(minnlcstate* state, - optguardnonc1test1report* strrep, - optguardnonc1test1report* lngrep, - ae_state *_state); -void minnlcresults(minnlcstate* state, - /* Real */ ae_vector* x, - minnlcreport* rep, - ae_state *_state); -void minnlcresultsbuf(minnlcstate* state, - /* Real */ ae_vector* x, - minnlcreport* rep, - ae_state *_state); -void minnlcrequesttermination(minnlcstate* state, ae_state *_state); -void minnlcrestartfrom(minnlcstate* state, - /* Real */ ae_vector* x, - ae_state *_state); -void minnlcequalitypenaltyfunction(double alpha, - double* f, - double* df, - double* d2f, - ae_state *_state); -void minnlcinequalitypenaltyfunction(double alpha, - double stabilizingpoint, - double* f, - double* df, - double* d2f, - ae_state *_state); -void minnlcinequalityshiftfunction(double alpha, - double* f, - double* df, - double* d2f, - ae_state *_state); -void _minnlcstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minnlcstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minnlcstate_clear(void* _p); -void _minnlcstate_destroy(void* _p); -void _minnlcreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minnlcreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minnlcreport_clear(void* _p); -void _minnlcreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_MINBC) || !defined(AE_PARTIAL_BUILD) -void minbccreate(ae_int_t n, - /* Real */ ae_vector* x, - minbcstate* state, - ae_state *_state); -void minbccreatef(ae_int_t n, - /* Real */ ae_vector* x, - double diffstep, - minbcstate* state, - ae_state *_state); -void minbcsetbc(minbcstate* state, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_state *_state); -void minbcsetcond(minbcstate* state, - double epsg, - double epsf, - double epsx, - ae_int_t maxits, - ae_state *_state); -void minbcsetscale(minbcstate* state, - /* Real */ ae_vector* s, - ae_state *_state); -void minbcsetprecdefault(minbcstate* state, ae_state *_state); -void minbcsetprecdiag(minbcstate* state, - /* Real */ ae_vector* d, - ae_state *_state); -void minbcsetprecscale(minbcstate* state, ae_state *_state); -void minbcsetxrep(minbcstate* state, ae_bool needxrep, ae_state *_state); -void minbcsetstpmax(minbcstate* state, double stpmax, ae_state *_state); -ae_bool minbciteration(minbcstate* state, ae_state *_state); -void minbcoptguardgradient(minbcstate* state, - double teststep, - ae_state *_state); -void minbcoptguardsmoothness(minbcstate* state, - ae_int_t level, - ae_state *_state); -void minbcoptguardresults(minbcstate* state, - optguardreport* rep, - ae_state *_state); -void minbcoptguardnonc1test0results(minbcstate* state, - optguardnonc1test0report* strrep, - optguardnonc1test0report* lngrep, - ae_state *_state); -void minbcoptguardnonc1test1results(minbcstate* state, - optguardnonc1test1report* strrep, - optguardnonc1test1report* lngrep, - ae_state *_state); -void minbcresults(minbcstate* state, - /* Real */ ae_vector* x, - minbcreport* rep, - ae_state *_state); -void minbcresultsbuf(minbcstate* state, - /* Real */ ae_vector* x, - minbcreport* rep, - ae_state *_state); -void minbcrestartfrom(minbcstate* state, - /* Real */ ae_vector* x, - ae_state *_state); -void minbcrequesttermination(minbcstate* state, ae_state *_state); -void _minbcstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minbcstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minbcstate_clear(void* _p); -void _minbcstate_destroy(void* _p); -void _minbcreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minbcreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minbcreport_clear(void* _p); -void _minbcreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_MINNS) || !defined(AE_PARTIAL_BUILD) -void minnscreate(ae_int_t n, - /* Real */ ae_vector* x, - minnsstate* state, - ae_state *_state); -void minnscreatef(ae_int_t n, - /* Real */ ae_vector* x, - double diffstep, - minnsstate* state, - ae_state *_state); -void minnssetbc(minnsstate* state, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_state *_state); -void minnssetlc(minnsstate* state, - /* Real */ ae_matrix* c, - /* Integer */ ae_vector* ct, - ae_int_t k, - ae_state *_state); -void minnssetnlc(minnsstate* state, - ae_int_t nlec, - ae_int_t nlic, - ae_state *_state); -void minnssetcond(minnsstate* state, - double epsx, - ae_int_t maxits, - ae_state *_state); -void minnssetscale(minnsstate* state, - /* Real */ ae_vector* s, - ae_state *_state); -void minnssetalgoags(minnsstate* state, - double radius, - double penalty, - ae_state *_state); -void minnssetxrep(minnsstate* state, ae_bool needxrep, ae_state *_state); -void minnsrequesttermination(minnsstate* state, ae_state *_state); -ae_bool minnsiteration(minnsstate* state, ae_state *_state); -void minnsresults(minnsstate* state, - /* Real */ ae_vector* x, - minnsreport* rep, - ae_state *_state); -void minnsresultsbuf(minnsstate* state, - /* Real */ ae_vector* x, - minnsreport* rep, - ae_state *_state); -void minnsrestartfrom(minnsstate* state, - /* Real */ ae_vector* x, - ae_state *_state); -void _minnsqp_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minnsqp_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minnsqp_clear(void* _p); -void _minnsqp_destroy(void* _p); -void _minnsstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minnsstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minnsstate_clear(void* _p); -void _minnsstate_destroy(void* _p); -void _minnsreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minnsreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minnsreport_clear(void* _p); -void _minnsreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_MINCOMP) || !defined(AE_PARTIAL_BUILD) -void minlbfgssetdefaultpreconditioner(minlbfgsstate* state, - ae_state *_state); -void minlbfgssetcholeskypreconditioner(minlbfgsstate* state, - /* Real */ ae_matrix* p, - ae_bool isupper, - ae_state *_state); -void minbleicsetbarrierwidth(minbleicstate* state, - double mu, - ae_state *_state); -void minbleicsetbarrierdecay(minbleicstate* state, - double mudecay, - ae_state *_state); -void minasacreate(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - minasastate* state, - ae_state *_state); -void minasasetcond(minasastate* state, - double epsg, - double epsf, - double epsx, - ae_int_t maxits, - ae_state *_state); -void minasasetxrep(minasastate* state, ae_bool needxrep, ae_state *_state); -void minasasetalgorithm(minasastate* state, - ae_int_t algotype, - ae_state *_state); -void minasasetstpmax(minasastate* state, double stpmax, ae_state *_state); -ae_bool minasaiteration(minasastate* state, ae_state *_state); -void minasaresults(minasastate* state, - /* Real */ ae_vector* x, - minasareport* rep, - ae_state *_state); -void minasaresultsbuf(minasastate* state, - /* Real */ ae_vector* x, - minasareport* rep, - ae_state *_state); -void minasarestartfrom(minasastate* state, - /* Real */ ae_vector* x, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_state *_state); -void _minasastate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minasastate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minasastate_clear(void* _p); -void _minasastate_destroy(void* _p); -void _minasareport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minasareport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minasareport_clear(void* _p); -void _minasareport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_MINCG) || !defined(AE_PARTIAL_BUILD) -void mincgcreate(ae_int_t n, - /* Real */ ae_vector* x, - mincgstate* state, - ae_state *_state); -void mincgcreatef(ae_int_t n, - /* Real */ ae_vector* x, - double diffstep, - mincgstate* state, - ae_state *_state); -void mincgsetcond(mincgstate* state, - double epsg, - double epsf, - double epsx, - ae_int_t maxits, - ae_state *_state); -void mincgsetscale(mincgstate* state, - /* Real */ ae_vector* s, - ae_state *_state); -void mincgsetxrep(mincgstate* state, ae_bool needxrep, ae_state *_state); -void mincgsetdrep(mincgstate* state, ae_bool needdrep, ae_state *_state); -void mincgsetcgtype(mincgstate* state, ae_int_t cgtype, ae_state *_state); -void mincgsetstpmax(mincgstate* state, double stpmax, ae_state *_state); -void mincgsuggeststep(mincgstate* state, double stp, ae_state *_state); -double mincglastgoodstep(mincgstate* state, ae_state *_state); -void mincgsetprecdefault(mincgstate* state, ae_state *_state); -void mincgsetprecdiag(mincgstate* state, - /* Real */ ae_vector* d, - ae_state *_state); -void mincgsetprecscale(mincgstate* state, ae_state *_state); -ae_bool mincgiteration(mincgstate* state, ae_state *_state); -void mincgoptguardgradient(mincgstate* state, - double teststep, - ae_state *_state); -void mincgoptguardsmoothness(mincgstate* state, - ae_int_t level, - ae_state *_state); -void mincgoptguardresults(mincgstate* state, - optguardreport* rep, - ae_state *_state); -void mincgoptguardnonc1test0results(mincgstate* state, - optguardnonc1test0report* strrep, - optguardnonc1test0report* lngrep, - ae_state *_state); -void mincgoptguardnonc1test1results(mincgstate* state, - optguardnonc1test1report* strrep, - optguardnonc1test1report* lngrep, - ae_state *_state); -void mincgresults(mincgstate* state, - /* Real */ ae_vector* x, - mincgreport* rep, - ae_state *_state); -void mincgresultsbuf(mincgstate* state, - /* Real */ ae_vector* x, - mincgreport* rep, - ae_state *_state); -void mincgrestartfrom(mincgstate* state, - /* Real */ ae_vector* x, - ae_state *_state); -void mincgrequesttermination(mincgstate* state, ae_state *_state); -void mincgsetprecdiagfast(mincgstate* state, - /* Real */ ae_vector* d, - ae_state *_state); -void mincgsetpreclowrankfast(mincgstate* state, - /* Real */ ae_vector* d1, - /* Real */ ae_vector* c, - /* Real */ ae_matrix* v, - ae_int_t vcnt, - ae_state *_state); -void mincgsetprecvarpart(mincgstate* state, - /* Real */ ae_vector* d2, - ae_state *_state); -void _mincgstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _mincgstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _mincgstate_clear(void* _p); -void _mincgstate_destroy(void* _p); -void _mincgreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _mincgreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _mincgreport_clear(void* _p); -void _mincgreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_MINLM) || !defined(AE_PARTIAL_BUILD) -void minlmcreatevj(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* x, - minlmstate* state, - ae_state *_state); -void minlmcreatev(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* x, - double diffstep, - minlmstate* state, - ae_state *_state); -void minlmcreatefgh(ae_int_t n, - /* Real */ ae_vector* x, - minlmstate* state, - ae_state *_state); -void minlmsetcond(minlmstate* state, - double epsx, - ae_int_t maxits, - ae_state *_state); -void minlmsetxrep(minlmstate* state, ae_bool needxrep, ae_state *_state); -void minlmsetstpmax(minlmstate* state, double stpmax, ae_state *_state); -void minlmsetscale(minlmstate* state, - /* Real */ ae_vector* s, - ae_state *_state); -void minlmsetbc(minlmstate* state, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_state *_state); -void minlmsetlc(minlmstate* state, - /* Real */ ae_matrix* c, - /* Integer */ ae_vector* ct, - ae_int_t k, - ae_state *_state); -void minlmsetacctype(minlmstate* state, - ae_int_t acctype, - ae_state *_state); -ae_bool minlmiteration(minlmstate* state, ae_state *_state); -void minlmoptguardgradient(minlmstate* state, - double teststep, - ae_state *_state); -void minlmoptguardresults(minlmstate* state, - optguardreport* rep, - ae_state *_state); -void minlmresults(minlmstate* state, - /* Real */ ae_vector* x, - minlmreport* rep, - ae_state *_state); -void minlmresultsbuf(minlmstate* state, - /* Real */ ae_vector* x, - minlmreport* rep, - ae_state *_state); -void minlmrestartfrom(minlmstate* state, - /* Real */ ae_vector* x, - ae_state *_state); -void minlmrequesttermination(minlmstate* state, ae_state *_state); -void minlmcreatevgj(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* x, - minlmstate* state, - ae_state *_state); -void minlmcreatefgj(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* x, - minlmstate* state, - ae_state *_state); -void minlmcreatefj(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* x, - minlmstate* state, - ae_state *_state); -void _minlmstepfinder_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minlmstepfinder_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minlmstepfinder_clear(void* _p); -void _minlmstepfinder_destroy(void* _p); -void _minlmstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minlmstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minlmstate_clear(void* _p); -void _minlmstate_destroy(void* _p); -void _minlmreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _minlmreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _minlmreport_clear(void* _p); -void _minlmreport_destroy(void* _p); -#endif - -} -#endif - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/solvers.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/solvers.cpp deleted file mode 100644 index 47b4f21..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/solvers.cpp +++ /dev/null @@ -1,14097 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifdef _MSC_VER -#define _CRT_SECURE_NO_WARNINGS -#endif -#include "stdafx.h" -#include "solvers.h" - -// disable some irrelevant warnings -#if (AE_COMPILER==AE_MSVC) && !defined(AE_ALL_WARNINGS) -#pragma warning(disable:4100) -#pragma warning(disable:4127) -#pragma warning(disable:4611) -#pragma warning(disable:4702) -#pragma warning(disable:4996) -#endif - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_DIRECTDENSESOLVERS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_LINLSQR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_POLYNOMIALSOLVER) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_NLEQ) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_DIRECTSPARSESOLVERS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_LINCG) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_DIRECTDENSESOLVERS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - -*************************************************************************/ -_densesolverreport_owner::_densesolverreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_densesolverreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::densesolverreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::densesolverreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::densesolverreport)); - alglib_impl::_densesolverreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_densesolverreport_owner::_densesolverreport_owner(const _densesolverreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_densesolverreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: densesolverreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::densesolverreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::densesolverreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::densesolverreport)); - alglib_impl::_densesolverreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_densesolverreport_owner& _densesolverreport_owner::operator=(const _densesolverreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: densesolverreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: densesolverreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_densesolverreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::densesolverreport)); - alglib_impl::_densesolverreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_densesolverreport_owner::~_densesolverreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_densesolverreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::densesolverreport* _densesolverreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::densesolverreport* _densesolverreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -densesolverreport::densesolverreport() : _densesolverreport_owner() ,r1(p_struct->r1),rinf(p_struct->rinf) -{ -} - -densesolverreport::densesolverreport(const densesolverreport &rhs):_densesolverreport_owner(rhs) ,r1(p_struct->r1),rinf(p_struct->rinf) -{ -} - -densesolverreport& densesolverreport::operator=(const densesolverreport &rhs) -{ - if( this==&rhs ) - return *this; - _densesolverreport_owner::operator=(rhs); - return *this; -} - -densesolverreport::~densesolverreport() -{ -} - - -/************************************************************************* - -*************************************************************************/ -_densesolverlsreport_owner::_densesolverlsreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_densesolverlsreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::densesolverlsreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::densesolverlsreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::densesolverlsreport)); - alglib_impl::_densesolverlsreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_densesolverlsreport_owner::_densesolverlsreport_owner(const _densesolverlsreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_densesolverlsreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: densesolverlsreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::densesolverlsreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::densesolverlsreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::densesolverlsreport)); - alglib_impl::_densesolverlsreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_densesolverlsreport_owner& _densesolverlsreport_owner::operator=(const _densesolverlsreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: densesolverlsreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: densesolverlsreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_densesolverlsreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::densesolverlsreport)); - alglib_impl::_densesolverlsreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_densesolverlsreport_owner::~_densesolverlsreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_densesolverlsreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::densesolverlsreport* _densesolverlsreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::densesolverlsreport* _densesolverlsreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -densesolverlsreport::densesolverlsreport() : _densesolverlsreport_owner() ,r2(p_struct->r2),cx(&p_struct->cx),n(p_struct->n),k(p_struct->k) -{ -} - -densesolverlsreport::densesolverlsreport(const densesolverlsreport &rhs):_densesolverlsreport_owner(rhs) ,r2(p_struct->r2),cx(&p_struct->cx),n(p_struct->n),k(p_struct->k) -{ -} - -densesolverlsreport& densesolverlsreport::operator=(const densesolverlsreport &rhs) -{ - if( this==&rhs ) - return *this; - _densesolverlsreport_owner::operator=(rhs); - return *this; -} - -densesolverlsreport::~densesolverlsreport() -{ -} - -/************************************************************************* -Dense solver for A*x=b with N*N real matrix A and N*1 real vectorx x and -b. This is "slow-but-feature rich" version of the linear solver. Faster -version is RMatrixSolveFast() function. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(N^3) complexity - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system - ! and performs iterative refinement, which results in - ! significant performance penalty when compared with "fast" - ! version which just performs LU decomposition and calls - ! triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. It is also very significant on small matrices. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, RMatrixSolveFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixsolve(const real_2d_array &a, const ae_int_t n, const real_1d_array &b, ae_int_t &info, densesolverreport &rep, real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixsolve(const_cast(a.c_ptr()), n, const_cast(b.c_ptr()), &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver. - -This subroutine solves a system A*x=b, where A is NxN non-denegerate -real matrix, x and b are vectors. This is a "fast" version of linear -solver which does NOT provide any additional functions like condition -number estimation or iterative refinement. - -Algorithm features: -* efficient algorithm O(N^3) complexity -* no performance overhead from additional functionality - -If you need condition number estimation or iterative refinement, use more -feature-rich version - RMatrixSolve(). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 16.03.2015 by Bochkanov Sergey -*************************************************************************/ -void rmatrixsolvefast(const real_2d_array &a, const ae_int_t n, const real_1d_array &b, ae_int_t &info, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixsolvefast(const_cast(a.c_ptr()), n, const_cast(b.c_ptr()), &info, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver. - -Similar to RMatrixSolve() but solves task with multiple right parts (where -b and x are NxM matrices). This is "slow-but-robust" version of linear -solver with additional functionality like condition number estimation. -There also exists faster version - RMatrixSolveMFast(). - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* optional iterative refinement -* O(N^3+M*N^2) complexity - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system - ! and performs iterative refinement, which results in - ! significant performance penalty when compared with "fast" - ! version which just performs LU decomposition and calls - ! triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. It also very significant on small matrices. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, RMatrixSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - RFS - iterative refinement switch: - * True - refinement is used. - Less performance, more precision. - * False - refinement is not used. - More performance, less precision. - -OUTPUT PARAMETERS - Info - return code: - * -3 A is ill conditioned or singular. - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixsolvem(const real_2d_array &a, const ae_int_t n, const real_2d_array &b, const ae_int_t m, const bool rfs, ae_int_t &info, densesolverreport &rep, real_2d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixsolvem(const_cast(a.c_ptr()), n, const_cast(b.c_ptr()), m, rfs, &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver. - -Similar to RMatrixSolve() but solves task with multiple right parts (where -b and x are NxM matrices). This is "fast" version of linear solver which -does NOT offer additional functions like condition number estimation or -iterative refinement. - -Algorithm features: -* O(N^3+M*N^2) complexity -* no additional functionality, highest performance - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - RFS - iterative refinement switch: - * True - refinement is used. - Less performance, more precision. - * False - refinement is not used. - More performance, less precision. - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - B - array[N]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixsolvemfast(const real_2d_array &a, const ae_int_t n, const real_2d_array &b, const ae_int_t m, ae_int_t &info, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixsolvemfast(const_cast(a.c_ptr()), n, const_cast(b.c_ptr()), m, &info, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver. - -This subroutine solves a system A*x=b, where A is NxN non-denegerate -real matrix given by its LU decomposition, x and b are real vectors. This -is "slow-but-robust" version of the linear LU-based solver. Faster version -is RMatrixLUSolveFast() function. - -Algorithm features: -* automatic detection of degenerate cases -* O(N^2) complexity -* condition number estimation - -No iterative refinement is provided because exact form of original matrix -is not known to subroutine. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in 10-15x performance penalty when compared - ! with "fast" version which just calls triangular solver. - ! - ! This performance penalty is insignificant when compared with - ! cost of large LU decomposition. However, if you call this - ! function many times for the same left side, this overhead - ! BECOMES significant. It also becomes significant for small- - ! scale problems. - ! - ! In such cases we strongly recommend you to use faster solver, - ! RMatrixLUSolveFast() function. - -INPUT PARAMETERS - LUA - array[N,N], LU decomposition, RMatrixLU result - P - array[N], pivots array, RMatrixLU result - N - size of A - B - array[N], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixlusolve(const real_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const real_1d_array &b, ae_int_t &info, densesolverreport &rep, real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixlusolve(const_cast(lua.c_ptr()), const_cast(p.c_ptr()), n, const_cast(b.c_ptr()), &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver. - -This subroutine solves a system A*x=b, where A is NxN non-denegerate -real matrix given by its LU decomposition, x and b are real vectors. This -is "fast-without-any-checks" version of the linear LU-based solver. Slower -but more robust version is RMatrixLUSolve() function. - -Algorithm features: -* O(N^2) complexity -* fast algorithm without ANY additional checks, just triangular solver - -INPUT PARAMETERS - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 18.03.2015 by Bochkanov Sergey -*************************************************************************/ -void rmatrixlusolvefast(const real_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const real_1d_array &b, ae_int_t &info, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixlusolvefast(const_cast(lua.c_ptr()), const_cast(p.c_ptr()), n, const_cast(b.c_ptr()), &info, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver. - -Similar to RMatrixLUSolve() but solves task with multiple right parts -(where b and x are NxM matrices). This is "robust-but-slow" version of -LU-based solver which performs additional checks for non-degeneracy of -inputs (condition number estimation). If you need best performance, use -"fast-without-any-checks" version, RMatrixLUSolveMFast(). - -Algorithm features: -* automatic detection of degenerate cases -* O(M*N^2) complexity -* condition number estimation - -No iterative refinement is provided because exact form of original matrix -is not known to subroutine. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just calls triangular - ! solver. - ! - ! This performance penalty is especially apparent when you use - ! ALGLIB parallel capabilities (condition number estimation is - ! inherently sequential). It also becomes significant for - ! small-scale problems. - ! - ! In such cases we strongly recommend you to use faster solver, - ! RMatrixLUSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - LUA - array[N,N], LU decomposition, RMatrixLU result - P - array[N], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixlusolvem(const real_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const real_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, real_2d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixlusolvem(const_cast(lua.c_ptr()), const_cast(p.c_ptr()), n, const_cast(b.c_ptr()), m, &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver. - -Similar to RMatrixLUSolve() but solves task with multiple right parts, -where b and x are NxM matrices. This is "fast-without-any-checks" version -of LU-based solver. It does not estimate condition number of a system, -so it is extremely fast. If you need better detection of near-degenerate -cases, use RMatrixLUSolveM() function. - -Algorithm features: -* O(M*N^2) complexity -* fast algorithm without ANY additional checks, just triangular solver - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS: - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N,M]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 18.03.2015 by Bochkanov Sergey -*************************************************************************/ -void rmatrixlusolvemfast(const real_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const real_2d_array &b, const ae_int_t m, ae_int_t &info, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixlusolvemfast(const_cast(lua.c_ptr()), const_cast(p.c_ptr()), n, const_cast(b.c_ptr()), m, &info, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver. - -This subroutine solves a system A*x=b, where BOTH ORIGINAL A AND ITS -LU DECOMPOSITION ARE KNOWN. You can use it if for some reasons you have -both A and its LU decomposition. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(N^2) complexity - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixmixedsolve(const real_2d_array &a, const real_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const real_1d_array &b, ae_int_t &info, densesolverreport &rep, real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixmixedsolve(const_cast(a.c_ptr()), const_cast(lua.c_ptr()), const_cast(p.c_ptr()), n, const_cast(b.c_ptr()), &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver. - -Similar to RMatrixMixedSolve() but solves task with multiple right parts -(where b and x are NxM matrices). - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(M*N^2) complexity - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixmixedsolvem(const real_2d_array &a, const real_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const real_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, real_2d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixmixedsolvem(const_cast(a.c_ptr()), const_cast(lua.c_ptr()), const_cast(p.c_ptr()), n, const_cast(b.c_ptr()), m, &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Complex dense solver for A*X=B with N*N complex matrix A, N*M complex -matrices X and B. "Slow-but-feature-rich" version which provides -additional functions, at the cost of slower performance. Faster version -may be invoked with CMatrixSolveMFast() function. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(N^3+M*N^2) complexity - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system - ! and performs iterative refinement, which results in - ! significant performance penalty when compared with "fast" - ! version which just performs LU decomposition and calls - ! triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, CMatrixSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - RFS - iterative refinement switch: - * True - refinement is used. - Less performance, more precision. - * False - refinement is not used. - More performance, less precision. - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixsolvem(const complex_2d_array &a, const ae_int_t n, const complex_2d_array &b, const ae_int_t m, const bool rfs, ae_int_t &info, densesolverreport &rep, complex_2d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixsolvem(const_cast(a.c_ptr()), n, const_cast(b.c_ptr()), m, rfs, &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Complex dense solver for A*X=B with N*N complex matrix A, N*M complex -matrices X and B. "Fast-but-lightweight" version which provides just -triangular solver - and no additional functions like iterative refinement -or condition number estimation. - -Algorithm features: -* O(N^3+M*N^2) complexity -* no additional time consuming functions - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS: - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N,M]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 16.03.2015 by Bochkanov Sergey -*************************************************************************/ -void cmatrixsolvemfast(const complex_2d_array &a, const ae_int_t n, const complex_2d_array &b, const ae_int_t m, ae_int_t &info, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixsolvemfast(const_cast(a.c_ptr()), n, const_cast(b.c_ptr()), m, &info, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Complex dense solver for A*x=B with N*N complex matrix A and N*1 complex -vectors x and b. "Slow-but-feature-rich" version of the solver. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(N^3) complexity - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system - ! and performs iterative refinement, which results in - ! significant performance penalty when compared with "fast" - ! version which just performs LU decomposition and calls - ! triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, CMatrixSolveFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixsolve(const complex_2d_array &a, const ae_int_t n, const complex_1d_array &b, ae_int_t &info, densesolverreport &rep, complex_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixsolve(const_cast(a.c_ptr()), n, const_cast(b.c_ptr()), &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Complex dense solver for A*x=B with N*N complex matrix A and N*1 complex -vectors x and b. "Fast-but-lightweight" version of the solver. - -Algorithm features: -* O(N^3) complexity -* no additional time consuming features, just triangular solver - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS: - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixsolvefast(const complex_2d_array &a, const ae_int_t n, const complex_1d_array &b, ae_int_t &info, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixsolvefast(const_cast(a.c_ptr()), n, const_cast(b.c_ptr()), &info, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver for A*X=B with N*N complex A given by its LU decomposition, -and N*M matrices X and B (multiple right sides). "Slow-but-feature-rich" -version of the solver. - -Algorithm features: -* automatic detection of degenerate cases -* O(M*N^2) complexity -* condition number estimation - -No iterative refinement is provided because exact form of original matrix -is not known to subroutine. Use CMatrixSolve or CMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just calls triangular - ! solver. - ! - ! This performance penalty is especially apparent when you use - ! ALGLIB parallel capabilities (condition number estimation is - ! inherently sequential). It also becomes significant for - ! small-scale problems. - ! - ! In such cases we strongly recommend you to use faster solver, - ! CMatrixLUSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixlusolvem(const complex_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const complex_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, complex_2d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixlusolvem(const_cast(lua.c_ptr()), const_cast(p.c_ptr()), n, const_cast(b.c_ptr()), m, &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver for A*X=B with N*N complex A given by its LU decomposition, -and N*M matrices X and B (multiple right sides). "Fast-but-lightweight" -version of the solver. - -Algorithm features: -* O(M*N^2) complexity -* no additional time-consuming features - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N,M]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixlusolvemfast(const complex_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const complex_2d_array &b, const ae_int_t m, ae_int_t &info, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixlusolvemfast(const_cast(lua.c_ptr()), const_cast(p.c_ptr()), n, const_cast(b.c_ptr()), m, &info, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Complex dense linear solver for A*x=b with complex N*N A given by its LU -decomposition and N*1 vectors x and b. This is "slow-but-robust" version -of the complex linear solver with additional features which add -significant performance overhead. Faster version is CMatrixLUSolveFast() -function. - -Algorithm features: -* automatic detection of degenerate cases -* O(N^2) complexity -* condition number estimation - -No iterative refinement is provided because exact form of original matrix -is not known to subroutine. Use CMatrixSolve or CMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in 10-15x performance penalty when compared - ! with "fast" version which just calls triangular solver. - ! - ! This performance penalty is insignificant when compared with - ! cost of large LU decomposition. However, if you call this - ! function many times for the same left side, this overhead - ! BECOMES significant. It also becomes significant for small- - ! scale problems. - ! - ! In such cases we strongly recommend you to use faster solver, - ! CMatrixLUSolveFast() function. - -INPUT PARAMETERS - LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU result - P - array[0..N-1], pivots array, CMatrixLU result - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixlusolve(const complex_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const complex_1d_array &b, ae_int_t &info, densesolverreport &rep, complex_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixlusolve(const_cast(lua.c_ptr()), const_cast(p.c_ptr()), n, const_cast(b.c_ptr()), &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Complex dense linear solver for A*x=b with N*N complex A given by its LU -decomposition and N*1 vectors x and b. This is fast lightweight version -of solver, which is significantly faster than CMatrixLUSolve(), but does -not provide additional information (like condition numbers). - -Algorithm features: -* O(N^2) complexity -* no additional time-consuming features, just triangular solver - -INPUT PARAMETERS - LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU result - P - array[0..N-1], pivots array, CMatrixLU result - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - -NOTE: unlike CMatrixLUSolve(), this function does NOT check for - near-degeneracy of input matrix. It checks for EXACT degeneracy, - because this check is easy to do. However, very badly conditioned - matrices may went unnoticed. - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixlusolvefast(const complex_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const complex_1d_array &b, ae_int_t &info, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixlusolvefast(const_cast(lua.c_ptr()), const_cast(p.c_ptr()), n, const_cast(b.c_ptr()), &info, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver. Same as RMatrixMixedSolveM(), but for complex matrices. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(M*N^2) complexity - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU result - P - array[0..N-1], pivots array, CMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixmixedsolvem(const complex_2d_array &a, const complex_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const complex_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, complex_2d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixmixedsolvem(const_cast(a.c_ptr()), const_cast(lua.c_ptr()), const_cast(p.c_ptr()), n, const_cast(b.c_ptr()), m, &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver. Same as RMatrixMixedSolve(), but for complex matrices. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(N^2) complexity - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU result - P - array[0..N-1], pivots array, CMatrixLU result - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixmixedsolve(const complex_2d_array &a, const complex_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const complex_1d_array &b, ae_int_t &info, densesolverreport &rep, complex_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::cmatrixmixedsolve(const_cast(a.c_ptr()), const_cast(lua.c_ptr()), const_cast(p.c_ptr()), n, const_cast(b.c_ptr()), &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver for A*X=B with N*N symmetric positive definite matrix A, and -N*M vectors X and B. It is "slow-but-feature-rich" version of the solver. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* O(N^3+M*N^2) complexity -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just performs Cholesky - ! decomposition and calls triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, SPDMatrixSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or non-SPD. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixsolvem(const real_2d_array &a, const ae_int_t n, const bool isupper, const real_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, real_2d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spdmatrixsolvem(const_cast(a.c_ptr()), n, isupper, const_cast(b.c_ptr()), m, &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver for A*X=B with N*N symmetric positive definite matrix A, and -N*M vectors X and B. It is "fast-but-lightweight" version of the solver. - -Algorithm features: -* O(N^3+M*N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional time consuming features - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular - * -1 N<=0 was passed - * 1 task was solved - B - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 17.03.2015 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixsolvemfast(const real_2d_array &a, const ae_int_t n, const bool isupper, const real_2d_array &b, const ae_int_t m, ae_int_t &info, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spdmatrixsolvemfast(const_cast(a.c_ptr()), n, isupper, const_cast(b.c_ptr()), m, &info, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense linear solver for A*x=b with N*N real symmetric positive definite -matrix A, N*1 vectors x and b. "Slow-but-feature-rich" version of the -solver. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* O(N^3) complexity -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just performs Cholesky - ! decomposition and calls triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, SPDMatrixSolveFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or non-SPD. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixsolve(const real_2d_array &a, const ae_int_t n, const bool isupper, const real_1d_array &b, ae_int_t &info, densesolverreport &rep, real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spdmatrixsolve(const_cast(a.c_ptr()), n, isupper, const_cast(b.c_ptr()), &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense linear solver for A*x=b with N*N real symmetric positive definite -matrix A, N*1 vectors x and b. "Fast-but-lightweight" version of the -solver. - -Algorithm features: -* O(N^3) complexity -* matrix is represented by its upper or lower triangle -* no additional time consuming features like condition number estimation - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or non-SPD - * -1 N<=0 was passed - * 1 task was solved - B - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 17.03.2015 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixsolvefast(const real_2d_array &a, const ae_int_t n, const bool isupper, const real_1d_array &b, ae_int_t &info, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spdmatrixsolvefast(const_cast(a.c_ptr()), n, isupper, const_cast(b.c_ptr()), &info, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver for A*X=B with N*N symmetric positive definite matrix A given -by its Cholesky decomposition, and N*M vectors X and B. It is "slow-but- -feature-rich" version of the solver which estimates condition number of -the system. - -Algorithm features: -* automatic detection of degenerate cases -* O(M*N^2) complexity -* condition number estimation -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just calls triangular - ! solver. Amount of overhead introduced depends on M (the - ! larger - the more efficient). - ! - ! This performance penalty is insignificant when compared with - ! cost of large LU decomposition. However, if you call this - ! function many times for the same left side, this overhead - ! BECOMES significant. It also becomes significant for small- - ! scale problems (N<50). - ! - ! In such cases we strongly recommend you to use faster solver, - ! SPDMatrixCholeskySolveMFast() function. - -INPUT PARAMETERS - CHA - array[0..N-1,0..N-1], Cholesky decomposition, - SPDMatrixCholesky result - N - size of CHA - IsUpper - what half of CHA is provided - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or badly conditioned - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task was solved - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N]: - * for info>0 contains solution - * for info=-3 filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixcholeskysolvem(const real_2d_array &cha, const ae_int_t n, const bool isupper, const real_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, real_2d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spdmatrixcholeskysolvem(const_cast(cha.c_ptr()), n, isupper, const_cast(b.c_ptr()), m, &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver for A*X=B with N*N symmetric positive definite matrix A given -by its Cholesky decomposition, and N*M vectors X and B. It is "fast-but- -lightweight" version of the solver which just solves linear system, -without any additional functions. - -Algorithm features: -* O(M*N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional functionality - -INPUT PARAMETERS - CHA - array[N,N], Cholesky decomposition, - SPDMatrixCholesky result - N - size of CHA - IsUpper - what half of CHA is provided - B - array[N,M], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or badly conditioned - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task was solved - B - array[N]: - * for info>0 overwritten by solution - * for info=-3 filled by zeros - - -- ALGLIB -- - Copyright 18.03.2015 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixcholeskysolvemfast(const real_2d_array &cha, const ae_int_t n, const bool isupper, const real_2d_array &b, const ae_int_t m, ae_int_t &info, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spdmatrixcholeskysolvemfast(const_cast(cha.c_ptr()), n, isupper, const_cast(b.c_ptr()), m, &info, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver for A*x=b with N*N symmetric positive definite matrix A given -by its Cholesky decomposition, and N*1 real vectors x and b. This is "slow- -but-feature-rich" version of the solver which, in addition to the -solution, performs condition number estimation. - -Algorithm features: -* automatic detection of degenerate cases -* O(N^2) complexity -* condition number estimation -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in 10-15x performance penalty when compared - ! with "fast" version which just calls triangular solver. - ! - ! This performance penalty is insignificant when compared with - ! cost of large LU decomposition. However, if you call this - ! function many times for the same left side, this overhead - ! BECOMES significant. It also becomes significant for small- - ! scale problems (N<50). - ! - ! In such cases we strongly recommend you to use faster solver, - ! SPDMatrixCholeskySolveFast() function. - -INPUT PARAMETERS - CHA - array[N,N], Cholesky decomposition, - SPDMatrixCholesky result - N - size of A - IsUpper - what half of CHA is provided - B - array[N], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or ill conditioned - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N]: - * for info>0 - solution - * for info=-3 - filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixcholeskysolve(const real_2d_array &cha, const ae_int_t n, const bool isupper, const real_1d_array &b, ae_int_t &info, densesolverreport &rep, real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spdmatrixcholeskysolve(const_cast(cha.c_ptr()), n, isupper, const_cast(b.c_ptr()), &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver for A*x=b with N*N symmetric positive definite matrix A given -by its Cholesky decomposition, and N*1 real vectors x and b. This is "fast- -but-lightweight" version of the solver. - -Algorithm features: -* O(N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional features - -INPUT PARAMETERS - CHA - array[N,N], Cholesky decomposition, - SPDMatrixCholesky result - N - size of A - IsUpper - what half of CHA is provided - B - array[N], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or ill conditioned - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * for info>0 - overwritten by solution - * for info=-3 - filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixcholeskysolvefast(const real_2d_array &cha, const ae_int_t n, const bool isupper, const real_1d_array &b, ae_int_t &info, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spdmatrixcholeskysolvefast(const_cast(cha.c_ptr()), n, isupper, const_cast(b.c_ptr()), &info, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver for A*X=B, with N*N Hermitian positive definite matrix A and -N*M complex matrices X and B. "Slow-but-feature-rich" version of the -solver. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* O(N^3+M*N^2) complexity -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just calls triangular - ! solver. - ! - ! This performance penalty is especially apparent when you use - ! ALGLIB parallel capabilities (condition number estimation is - ! inherently sequential). It also becomes significant for - ! small-scale problems (N<100). - ! - ! In such cases we strongly recommend you to use faster solver, - ! HPDMatrixSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - same as in RMatrixSolve. - Returns -3 for non-HPD matrices. - Rep - same as in RMatrixSolve - X - same as in RMatrixSolve - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixsolvem(const complex_2d_array &a, const ae_int_t n, const bool isupper, const complex_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, complex_2d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hpdmatrixsolvem(const_cast(a.c_ptr()), n, isupper, const_cast(b.c_ptr()), m, &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver for A*X=B, with N*N Hermitian positive definite matrix A and -N*M complex matrices X and B. "Fast-but-lightweight" version of the solver. - -Algorithm features: -* O(N^3+M*N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional time consuming features like condition number estimation - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or is not positive definite. - B is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - B - array[0..N-1]: - * overwritten by solution - * zeros, if problem was not solved - - -- ALGLIB -- - Copyright 17.03.2015 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixsolvemfast(const complex_2d_array &a, const ae_int_t n, const bool isupper, const complex_2d_array &b, const ae_int_t m, ae_int_t &info, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hpdmatrixsolvemfast(const_cast(a.c_ptr()), n, isupper, const_cast(b.c_ptr()), m, &info, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver for A*x=b, with N*N Hermitian positive definite matrix A, and -N*1 complex vectors x and b. "Slow-but-feature-rich" version of the -solver. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* O(N^3) complexity -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just performs Cholesky - ! decomposition and calls triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, HPDMatrixSolveFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - same as in RMatrixSolve - Returns -3 for non-HPD matrices. - Rep - same as in RMatrixSolve - X - same as in RMatrixSolve - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixsolve(const complex_2d_array &a, const ae_int_t n, const bool isupper, const complex_1d_array &b, ae_int_t &info, densesolverreport &rep, complex_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hpdmatrixsolve(const_cast(a.c_ptr()), n, isupper, const_cast(b.c_ptr()), &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver for A*x=b, with N*N Hermitian positive definite matrix A, and -N*1 complex vectors x and b. "Fast-but-lightweight" version of the -solver without additional functions. - -Algorithm features: -* O(N^3) complexity -* matrix is represented by its upper or lower triangle -* no additional time consuming functions - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or not positive definite - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task was solved - B - array[0..N-1]: - * overwritten by solution - * zeros, if A is exactly singular (diagonal of its LU - decomposition has exact zeros). - - -- ALGLIB -- - Copyright 17.03.2015 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixsolvefast(const complex_2d_array &a, const ae_int_t n, const bool isupper, const complex_1d_array &b, ae_int_t &info, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hpdmatrixsolvefast(const_cast(a.c_ptr()), n, isupper, const_cast(b.c_ptr()), &info, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver for A*X=B with N*N Hermitian positive definite matrix A given -by its Cholesky decomposition and N*M complex matrices X and B. This is -"slow-but-feature-rich" version of the solver which, in addition to the -solution, estimates condition number of the system. - -Algorithm features: -* automatic detection of degenerate cases -* O(M*N^2) complexity -* condition number estimation -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just calls triangular - ! solver. Amount of overhead introduced depends on M (the - ! larger - the more efficient). - ! - ! This performance penalty is insignificant when compared with - ! cost of large Cholesky decomposition. However, if you call - ! this function many times for the same left side, this - ! overhead BECOMES significant. It also becomes significant - ! for small-scale problems (N<50). - ! - ! In such cases we strongly recommend you to use faster solver, - ! HPDMatrixCholeskySolveMFast() function. - - -INPUT PARAMETERS - CHA - array[N,N], Cholesky decomposition, - HPDMatrixCholesky result - N - size of CHA - IsUpper - what half of CHA is provided - B - array[N,M], right part - M - right part size - -OUTPUT PARAMETERS: - Info - return code: - * -3 A is singular, or VERY close to singular. - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task was solved - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N]: - * for info>0 contains solution - * for info=-3 filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixcholeskysolvem(const complex_2d_array &cha, const ae_int_t n, const bool isupper, const complex_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, complex_2d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hpdmatrixcholeskysolvem(const_cast(cha.c_ptr()), n, isupper, const_cast(b.c_ptr()), m, &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver for A*X=B with N*N Hermitian positive definite matrix A given -by its Cholesky decomposition and N*M complex matrices X and B. This is -"fast-but-lightweight" version of the solver. - -Algorithm features: -* O(M*N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional time-consuming features - -INPUT PARAMETERS - CHA - array[N,N], Cholesky decomposition, - HPDMatrixCholesky result - N - size of CHA - IsUpper - what half of CHA is provided - B - array[N,M], right part - M - right part size - -OUTPUT PARAMETERS: - Info - return code: - * -3 A is singular, or VERY close to singular. - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task was solved - B - array[N]: - * for info>0 overwritten by solution - * for info=-3 filled by zeros - - -- ALGLIB -- - Copyright 18.03.2015 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixcholeskysolvemfast(const complex_2d_array &cha, const ae_int_t n, const bool isupper, const complex_2d_array &b, const ae_int_t m, ae_int_t &info, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hpdmatrixcholeskysolvemfast(const_cast(cha.c_ptr()), n, isupper, const_cast(b.c_ptr()), m, &info, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver for A*x=b with N*N Hermitian positive definite matrix A given -by its Cholesky decomposition, and N*1 complex vectors x and b. This is -"slow-but-feature-rich" version of the solver which estimates condition -number of the system. - -Algorithm features: -* automatic detection of degenerate cases -* O(N^2) complexity -* condition number estimation -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in 10-15x performance penalty when compared - ! with "fast" version which just calls triangular solver. - ! - ! This performance penalty is insignificant when compared with - ! cost of large LU decomposition. However, if you call this - ! function many times for the same left side, this overhead - ! BECOMES significant. It also becomes significant for small- - ! scale problems (N<50). - ! - ! In such cases we strongly recommend you to use faster solver, - ! HPDMatrixCholeskySolveFast() function. - -INPUT PARAMETERS - CHA - array[0..N-1,0..N-1], Cholesky decomposition, - SPDMatrixCholesky result - N - size of A - IsUpper - what half of CHA is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or ill conditioned - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N]: - * for info>0 - solution - * for info=-3 - filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixcholeskysolve(const complex_2d_array &cha, const ae_int_t n, const bool isupper, const complex_1d_array &b, ae_int_t &info, densesolverreport &rep, complex_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hpdmatrixcholeskysolve(const_cast(cha.c_ptr()), n, isupper, const_cast(b.c_ptr()), &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver for A*x=b with N*N Hermitian positive definite matrix A given -by its Cholesky decomposition, and N*1 complex vectors x and b. This is -"fast-but-lightweight" version of the solver. - -Algorithm features: -* O(N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional time-consuming features - -INPUT PARAMETERS - CHA - array[0..N-1,0..N-1], Cholesky decomposition, - SPDMatrixCholesky result - N - size of A - IsUpper - what half of CHA is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or ill conditioned - B is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * for info>0 - overwritten by solution - * for info=-3 - filled by zeros - - -- ALGLIB -- - Copyright 18.03.2015 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixcholeskysolvefast(const complex_2d_array &cha, const ae_int_t n, const bool isupper, const complex_1d_array &b, ae_int_t &info, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hpdmatrixcholeskysolvefast(const_cast(cha.c_ptr()), n, isupper, const_cast(b.c_ptr()), &info, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Dense solver. - -This subroutine finds solution of the linear system A*X=B with non-square, -possibly degenerate A. System is solved in the least squares sense, and -general least squares solution X = X0 + CX*y which minimizes |A*X-B| is -returned. If A is non-degenerate, solution in the usual sense is returned. - -Algorithm features: -* automatic detection (and correct handling!) of degenerate cases -* iterative refinement -* O(N^3) complexity - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..NRows-1,0..NCols-1], system matrix - NRows - vertical size of A - NCols - horizontal size of A - B - array[0..NCols-1], right part - Threshold- a number in [0,1]. Singular values beyond Threshold are - considered zero. Set it to 0.0, if you don't understand - what it means, so the solver will choose good value on its - own. - -OUTPUT PARAMETERS - Info - return code: - * -4 SVD subroutine failed - * -1 if NRows<=0 or NCols<=0 or Threshold<0 was passed - * 1 if task is solved - Rep - solver report, see below for more info - X - array[0..N-1,0..M-1], it contains: - * solution of A*X=B (even for singular A) - * zeros, if SVD subroutine failed - -SOLVER REPORT - -Subroutine sets following fields of the Rep structure: -* R2 reciprocal of condition number: 1/cond(A), 2-norm. -* N = NCols -* K dim(Null(A)) -* CX array[0..N-1,0..K-1], kernel of A. - Columns of CX store such vectors that A*CX[i]=0. - - -- ALGLIB -- - Copyright 24.08.2009 by Bochkanov Sergey -*************************************************************************/ -void rmatrixsolvels(const real_2d_array &a, const ae_int_t nrows, const ae_int_t ncols, const real_1d_array &b, const double threshold, ae_int_t &info, densesolverlsreport &rep, real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rmatrixsolvels(const_cast(a.c_ptr()), nrows, ncols, const_cast(b.c_ptr()), threshold, &info, const_cast(rep.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_LINLSQR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores state of the LinLSQR method. - -You should use ALGLIB functions to work with this object. -*************************************************************************/ -_linlsqrstate_owner::_linlsqrstate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_linlsqrstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::linlsqrstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::linlsqrstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::linlsqrstate)); - alglib_impl::_linlsqrstate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_linlsqrstate_owner::_linlsqrstate_owner(const _linlsqrstate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_linlsqrstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: linlsqrstate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::linlsqrstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::linlsqrstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::linlsqrstate)); - alglib_impl::_linlsqrstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_linlsqrstate_owner& _linlsqrstate_owner::operator=(const _linlsqrstate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: linlsqrstate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: linlsqrstate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_linlsqrstate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::linlsqrstate)); - alglib_impl::_linlsqrstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_linlsqrstate_owner::~_linlsqrstate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_linlsqrstate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::linlsqrstate* _linlsqrstate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::linlsqrstate* _linlsqrstate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -linlsqrstate::linlsqrstate() : _linlsqrstate_owner() -{ -} - -linlsqrstate::linlsqrstate(const linlsqrstate &rhs):_linlsqrstate_owner(rhs) -{ -} - -linlsqrstate& linlsqrstate::operator=(const linlsqrstate &rhs) -{ - if( this==&rhs ) - return *this; - _linlsqrstate_owner::operator=(rhs); - return *this; -} - -linlsqrstate::~linlsqrstate() -{ -} - - -/************************************************************************* - -*************************************************************************/ -_linlsqrreport_owner::_linlsqrreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_linlsqrreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::linlsqrreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::linlsqrreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::linlsqrreport)); - alglib_impl::_linlsqrreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_linlsqrreport_owner::_linlsqrreport_owner(const _linlsqrreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_linlsqrreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: linlsqrreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::linlsqrreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::linlsqrreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::linlsqrreport)); - alglib_impl::_linlsqrreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_linlsqrreport_owner& _linlsqrreport_owner::operator=(const _linlsqrreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: linlsqrreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: linlsqrreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_linlsqrreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::linlsqrreport)); - alglib_impl::_linlsqrreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_linlsqrreport_owner::~_linlsqrreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_linlsqrreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::linlsqrreport* _linlsqrreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::linlsqrreport* _linlsqrreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -linlsqrreport::linlsqrreport() : _linlsqrreport_owner() ,iterationscount(p_struct->iterationscount),nmv(p_struct->nmv),terminationtype(p_struct->terminationtype) -{ -} - -linlsqrreport::linlsqrreport(const linlsqrreport &rhs):_linlsqrreport_owner(rhs) ,iterationscount(p_struct->iterationscount),nmv(p_struct->nmv),terminationtype(p_struct->terminationtype) -{ -} - -linlsqrreport& linlsqrreport::operator=(const linlsqrreport &rhs) -{ - if( this==&rhs ) - return *this; - _linlsqrreport_owner::operator=(rhs); - return *this; -} - -linlsqrreport::~linlsqrreport() -{ -} - -/************************************************************************* -This function initializes linear LSQR Solver. This solver is used to solve -non-symmetric (and, possibly, non-square) problems. Least squares solution -is returned for non-compatible systems. - -USAGE: -1. User initializes algorithm state with LinLSQRCreate() call -2. User tunes solver parameters with LinLSQRSetCond() and other functions -3. User calls LinLSQRSolveSparse() function which takes algorithm state - and SparseMatrix object. -4. User calls LinLSQRResults() to get solution -5. Optionally, user may call LinLSQRSolveSparse() again to solve another - problem with different matrix and/or right part without reinitializing - LinLSQRState structure. - -INPUT PARAMETERS: - M - number of rows in A - N - number of variables, N>0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: see also linlsqrcreatebuf() for version which reuses previously - allocated place as much as possible. - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -void linlsqrcreate(const ae_int_t m, const ae_int_t n, linlsqrstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::linlsqrcreate(m, n, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function initializes linear LSQR Solver. It provides exactly same -functionality as linlsqrcreate(), but reuses previously allocated space -as much as possible. - -INPUT PARAMETERS: - M - number of rows in A - N - number of variables, N>0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 14.11.2018 by Bochkanov Sergey -*************************************************************************/ -void linlsqrcreatebuf(const ae_int_t m, const ae_int_t n, const linlsqrstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::linlsqrcreatebuf(m, n, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function changes preconditioning settings of LinLSQQSolveSparse() -function. By default, SolveSparse() uses diagonal preconditioner, but if -you want to use solver without preconditioning, you can call this function -which forces solver to use unit matrix for preconditioning. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 19.11.2012 by Bochkanov Sergey -*************************************************************************/ -void linlsqrsetprecunit(const linlsqrstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::linlsqrsetprecunit(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function changes preconditioning settings of LinCGSolveSparse() -function. LinCGSolveSparse() will use diagonal of the system matrix as -preconditioner. This preconditioning mode is active by default. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 19.11.2012 by Bochkanov Sergey -*************************************************************************/ -void linlsqrsetprecdiag(const linlsqrstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::linlsqrsetprecdiag(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets optional Tikhonov regularization coefficient. -It is zero by default. - -INPUT PARAMETERS: - LambdaI - regularization factor, LambdaI>=0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -void linlsqrsetlambdai(const linlsqrstate &state, const double lambdai, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::linlsqrsetlambdai(const_cast(state.c_ptr()), lambdai, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Procedure for solution of A*x=b with sparse A. - -INPUT PARAMETERS: - State - algorithm state - A - sparse M*N matrix in the CRS format (you MUST contvert it - to CRS format by calling SparseConvertToCRS() function - BEFORE you pass it to this function). - B - right part, array[M] - -RESULT: - This function returns no result. - You can get solution by calling LinCGResults() - -NOTE: this function uses lightweight preconditioning - multiplication by - inverse of diag(A). If you want, you can turn preconditioning off by - calling LinLSQRSetPrecUnit(). However, preconditioning cost is low - and preconditioner is very important for solution of badly scaled - problems. - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -void linlsqrsolvesparse(const linlsqrstate &state, const sparsematrix &a, const real_1d_array &b, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::linlsqrsolvesparse(const_cast(state.c_ptr()), const_cast(a.c_ptr()), const_cast(b.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets stopping criteria. - -INPUT PARAMETERS: - EpsA - algorithm will be stopped if ||A^T*Rk||/(||A||*||Rk||)<=EpsA. - EpsB - algorithm will be stopped if ||Rk||<=EpsB*||B|| - MaxIts - algorithm will be stopped if number of iterations - more than MaxIts. - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: if EpsA,EpsB,EpsC and MaxIts are zero then these variables will -be setted as default values. - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -void linlsqrsetcond(const linlsqrstate &state, const double epsa, const double epsb, const ae_int_t maxits, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::linlsqrsetcond(const_cast(state.c_ptr()), epsa, epsb, maxits, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -LSQR solver: results. - -This function must be called after LinLSQRSolve - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[N], solution - Rep - optimization report: - * Rep.TerminationType completetion code: - * 1 ||Rk||<=EpsB*||B|| - * 4 ||A^T*Rk||/(||A||*||Rk||)<=EpsA - * 5 MaxIts steps was taken - * 7 rounding errors prevent further progress, - X contains best point found so far. - (sometimes returned on singular systems) - * 8 user requested termination via calling - linlsqrrequesttermination() - * Rep.IterationsCount contains iterations count - * NMV countains number of matrix-vector calculations - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -void linlsqrresults(const linlsqrstate &state, real_1d_array &x, linlsqrreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::linlsqrresults(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinCGOptimize(). - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -void linlsqrsetxrep(const linlsqrstate &state, const bool needxrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::linlsqrsetxrep(const_cast(state.c_ptr()), needxrep, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function is used to peek into LSQR solver and get current iteration -counter. You can safely "peek" into the solver from another thread. - -INPUT PARAMETERS: - S - solver object - -RESULT: - iteration counter, in [0,INF) - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -ae_int_t linlsqrpeekiterationscount(const linlsqrstate &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_int_t result = alglib_impl::linlsqrpeekiterationscount(const_cast(s.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -This subroutine submits request for termination of the running solver. It -can be called from some other thread which wants LSQR solver to terminate -(obviously, the thread running LSQR solver can not request termination -because it is already busy working on LSQR). - -As result, solver stops at point which was "current accepted" when -termination request was submitted and returns error code 8 (successful -termination). Such termination is a smooth process which properly -deallocates all temporaries. - -INPUT PARAMETERS: - State - solver structure - -NOTE: calling this function on solver which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - -NOTE: solver clears termination flag on its start, it means that if some - other thread will request termination too soon, its request will went - unnoticed. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void linlsqrrequesttermination(const linlsqrstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::linlsqrrequesttermination(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_POLYNOMIALSOLVER) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - -*************************************************************************/ -_polynomialsolverreport_owner::_polynomialsolverreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_polynomialsolverreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::polynomialsolverreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::polynomialsolverreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::polynomialsolverreport)); - alglib_impl::_polynomialsolverreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_polynomialsolverreport_owner::_polynomialsolverreport_owner(const _polynomialsolverreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_polynomialsolverreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: polynomialsolverreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::polynomialsolverreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::polynomialsolverreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::polynomialsolverreport)); - alglib_impl::_polynomialsolverreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_polynomialsolverreport_owner& _polynomialsolverreport_owner::operator=(const _polynomialsolverreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: polynomialsolverreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: polynomialsolverreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_polynomialsolverreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::polynomialsolverreport)); - alglib_impl::_polynomialsolverreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_polynomialsolverreport_owner::~_polynomialsolverreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_polynomialsolverreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::polynomialsolverreport* _polynomialsolverreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::polynomialsolverreport* _polynomialsolverreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -polynomialsolverreport::polynomialsolverreport() : _polynomialsolverreport_owner() ,maxerr(p_struct->maxerr) -{ -} - -polynomialsolverreport::polynomialsolverreport(const polynomialsolverreport &rhs):_polynomialsolverreport_owner(rhs) ,maxerr(p_struct->maxerr) -{ -} - -polynomialsolverreport& polynomialsolverreport::operator=(const polynomialsolverreport &rhs) -{ - if( this==&rhs ) - return *this; - _polynomialsolverreport_owner::operator=(rhs); - return *this; -} - -polynomialsolverreport::~polynomialsolverreport() -{ -} - -/************************************************************************* -Polynomial root finding. - -This function returns all roots of the polynomial - P(x) = a0 + a1*x + a2*x^2 + ... + an*x^n -Both real and complex roots are returned (see below). - -INPUT PARAMETERS: - A - array[N+1], polynomial coefficients: - * A[0] is constant term - * A[N] is a coefficient of X^N - N - polynomial degree - -OUTPUT PARAMETERS: - X - array of complex roots: - * for isolated real root, X[I] is strictly real: IMAGE(X[I])=0 - * complex roots are always returned in pairs - roots occupy - positions I and I+1, with: - * X[I+1]=Conj(X[I]) - * IMAGE(X[I]) > 0 - * IMAGE(X[I+1]) = -IMAGE(X[I]) < 0 - * multiple real roots may have non-zero imaginary part due - to roundoff errors. There is no reliable way to distinguish - real root of multiplicity 2 from two complex roots in - the presence of roundoff errors. - Rep - report, additional information, following fields are set: - * Rep.MaxErr - max( |P(xi)| ) for i=0..N-1. This field - allows to quickly estimate "quality" of the roots being - returned. - -NOTE: this function uses companion matrix method to find roots. In case - internal EVD solver fails do find eigenvalues, exception is - generated. - -NOTE: roots are not "polished" and no matrix balancing is performed - for them. - - -- ALGLIB -- - Copyright 24.02.2014 by Bochkanov Sergey -*************************************************************************/ -void polynomialsolve(const real_1d_array &a, const ae_int_t n, complex_1d_array &x, polynomialsolverreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::polynomialsolve(const_cast(a.c_ptr()), n, const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_NLEQ) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - -*************************************************************************/ -_nleqstate_owner::_nleqstate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_nleqstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::nleqstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::nleqstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::nleqstate)); - alglib_impl::_nleqstate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_nleqstate_owner::_nleqstate_owner(const _nleqstate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_nleqstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: nleqstate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::nleqstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::nleqstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::nleqstate)); - alglib_impl::_nleqstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_nleqstate_owner& _nleqstate_owner::operator=(const _nleqstate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: nleqstate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: nleqstate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_nleqstate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::nleqstate)); - alglib_impl::_nleqstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_nleqstate_owner::~_nleqstate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_nleqstate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::nleqstate* _nleqstate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::nleqstate* _nleqstate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -nleqstate::nleqstate() : _nleqstate_owner() ,needf(p_struct->needf),needfij(p_struct->needfij),xupdated(p_struct->xupdated),f(p_struct->f),fi(&p_struct->fi),j(&p_struct->j),x(&p_struct->x) -{ -} - -nleqstate::nleqstate(const nleqstate &rhs):_nleqstate_owner(rhs) ,needf(p_struct->needf),needfij(p_struct->needfij),xupdated(p_struct->xupdated),f(p_struct->f),fi(&p_struct->fi),j(&p_struct->j),x(&p_struct->x) -{ -} - -nleqstate& nleqstate::operator=(const nleqstate &rhs) -{ - if( this==&rhs ) - return *this; - _nleqstate_owner::operator=(rhs); - return *this; -} - -nleqstate::~nleqstate() -{ -} - - -/************************************************************************* - -*************************************************************************/ -_nleqreport_owner::_nleqreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_nleqreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::nleqreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::nleqreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::nleqreport)); - alglib_impl::_nleqreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_nleqreport_owner::_nleqreport_owner(const _nleqreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_nleqreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: nleqreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::nleqreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::nleqreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::nleqreport)); - alglib_impl::_nleqreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_nleqreport_owner& _nleqreport_owner::operator=(const _nleqreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: nleqreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: nleqreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_nleqreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::nleqreport)); - alglib_impl::_nleqreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_nleqreport_owner::~_nleqreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_nleqreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::nleqreport* _nleqreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::nleqreport* _nleqreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -nleqreport::nleqreport() : _nleqreport_owner() ,iterationscount(p_struct->iterationscount),nfunc(p_struct->nfunc),njac(p_struct->njac),terminationtype(p_struct->terminationtype) -{ -} - -nleqreport::nleqreport(const nleqreport &rhs):_nleqreport_owner(rhs) ,iterationscount(p_struct->iterationscount),nfunc(p_struct->nfunc),njac(p_struct->njac),terminationtype(p_struct->terminationtype) -{ -} - -nleqreport& nleqreport::operator=(const nleqreport &rhs) -{ - if( this==&rhs ) - return *this; - _nleqreport_owner::operator=(rhs); - return *this; -} - -nleqreport::~nleqreport() -{ -} - -/************************************************************************* - LEVENBERG-MARQUARDT-LIKE NONLINEAR SOLVER - -DESCRIPTION: -This algorithm solves system of nonlinear equations - F[0](x[0], ..., x[n-1]) = 0 - F[1](x[0], ..., x[n-1]) = 0 - ... - F[M-1](x[0], ..., x[n-1]) = 0 -with M/N do not necessarily coincide. Algorithm converges quadratically -under following conditions: - * the solution set XS is nonempty - * for some xs in XS there exist such neighbourhood N(xs) that: - * vector function F(x) and its Jacobian J(x) are continuously - differentiable on N - * ||F(x)|| provides local error bound on N, i.e. there exists such - c1, that ||F(x)||>c1*distance(x,XS) -Note that these conditions are much more weaker than usual non-singularity -conditions. For example, algorithm will converge for any affine function -F (whether its Jacobian singular or not). - - -REQUIREMENTS: -Algorithm will request following information during its operation: -* function vector F[] and Jacobian matrix at given point X -* value of merit function f(x)=F[0]^2(x)+...+F[M-1]^2(x) at given point X - - -USAGE: -1. User initializes algorithm state with NLEQCreateLM() call -2. User tunes solver parameters with NLEQSetCond(), NLEQSetStpMax() and - other functions -3. User calls NLEQSolve() function which takes algorithm state and - pointers (delegates, etc.) to callback functions which calculate merit - function value and Jacobian. -4. User calls NLEQResults() to get solution -5. Optionally, user may call NLEQRestartFrom() to solve another problem - with same parameters (N/M) but another starting point and/or another - function vector. NLEQRestartFrom() allows to reuse already initialized - structure. - - -INPUT PARAMETERS: - N - space dimension, N>1: - * if provided, only leading N elements of X are used - * if not provided, determined automatically from size of X - M - system size - X - starting point - - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -NOTES: -1. you may tune stopping conditions with NLEQSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use NLEQSetStpMax() function to bound algorithm's steps. -3. this algorithm is a slightly modified implementation of the method - described in 'Levenberg-Marquardt method for constrained nonlinear - equations with strong local convergence properties' by Christian Kanzow - Nobuo Yamashita and Masao Fukushima and further developed in 'On the - convergence of a New Levenberg-Marquardt Method' by Jin-yan Fan and - Ya-Xiang Yuan. - - - -- ALGLIB -- - Copyright 20.08.2009 by Bochkanov Sergey -*************************************************************************/ -void nleqcreatelm(const ae_int_t n, const ae_int_t m, const real_1d_array &x, nleqstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::nleqcreatelm(n, m, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* - LEVENBERG-MARQUARDT-LIKE NONLINEAR SOLVER - -DESCRIPTION: -This algorithm solves system of nonlinear equations - F[0](x[0], ..., x[n-1]) = 0 - F[1](x[0], ..., x[n-1]) = 0 - ... - F[M-1](x[0], ..., x[n-1]) = 0 -with M/N do not necessarily coincide. Algorithm converges quadratically -under following conditions: - * the solution set XS is nonempty - * for some xs in XS there exist such neighbourhood N(xs) that: - * vector function F(x) and its Jacobian J(x) are continuously - differentiable on N - * ||F(x)|| provides local error bound on N, i.e. there exists such - c1, that ||F(x)||>c1*distance(x,XS) -Note that these conditions are much more weaker than usual non-singularity -conditions. For example, algorithm will converge for any affine function -F (whether its Jacobian singular or not). - - -REQUIREMENTS: -Algorithm will request following information during its operation: -* function vector F[] and Jacobian matrix at given point X -* value of merit function f(x)=F[0]^2(x)+...+F[M-1]^2(x) at given point X - - -USAGE: -1. User initializes algorithm state with NLEQCreateLM() call -2. User tunes solver parameters with NLEQSetCond(), NLEQSetStpMax() and - other functions -3. User calls NLEQSolve() function which takes algorithm state and - pointers (delegates, etc.) to callback functions which calculate merit - function value and Jacobian. -4. User calls NLEQResults() to get solution -5. Optionally, user may call NLEQRestartFrom() to solve another problem - with same parameters (N/M) but another starting point and/or another - function vector. NLEQRestartFrom() allows to reuse already initialized - structure. - - -INPUT PARAMETERS: - N - space dimension, N>1: - * if provided, only leading N elements of X are used - * if not provided, determined automatically from size of X - M - system size - X - starting point - - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -NOTES: -1. you may tune stopping conditions with NLEQSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use NLEQSetStpMax() function to bound algorithm's steps. -3. this algorithm is a slightly modified implementation of the method - described in 'Levenberg-Marquardt method for constrained nonlinear - equations with strong local convergence properties' by Christian Kanzow - Nobuo Yamashita and Masao Fukushima and further developed in 'On the - convergence of a New Levenberg-Marquardt Method' by Jin-yan Fan and - Ya-Xiang Yuan. - - - -- ALGLIB -- - Copyright 20.08.2009 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void nleqcreatelm(const ae_int_t m, const real_1d_array &x, nleqstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::nleqcreatelm(n, m, const_cast(x.c_ptr()), const_cast(state.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function sets stopping conditions for the nonlinear solver - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsF - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition ||F||<=EpsF is satisfied - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsF=0 and MaxIts=0 simultaneously will lead to automatic -stopping criterion selection (small EpsF). - -NOTES: - - -- ALGLIB -- - Copyright 20.08.2010 by Bochkanov Sergey -*************************************************************************/ -void nleqsetcond(const nleqstate &state, const double epsf, const ae_int_t maxits, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::nleqsetcond(const_cast(state.c_ptr()), epsf, maxits, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to NLEQSolve(). - - -- ALGLIB -- - Copyright 20.08.2010 by Bochkanov Sergey -*************************************************************************/ -void nleqsetxrep(const nleqstate &state, const bool needxrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::nleqsetxrep(const_cast(state.c_ptr()), needxrep, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when target function contains exp() or other fast -growing functions, and algorithm makes too large steps which lead to -overflow. This function allows us to reject steps that are too large (and -therefore expose us to the possible overflow) without actually calculating -function value at the x+stp*d. - - -- ALGLIB -- - Copyright 20.08.2010 by Bochkanov Sergey -*************************************************************************/ -void nleqsetstpmax(const nleqstate &state, const double stpmax, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::nleqsetstpmax(const_cast(state.c_ptr()), stpmax, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool nleqiteration(const nleqstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - ae_bool result = alglib_impl::nleqiteration(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - - -void nleqsolve(nleqstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr), - void *ptr, - const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'nleqsolve()' (func is NULL)", &_alglib_env_state); - alglib_impl::ae_assert(jac!=NULL, "ALGLIB: error in 'nleqsolve()' (jac is NULL)", &_alglib_env_state); - while( alglib_impl::nleqiteration(state.c_ptr(), &_alglib_env_state) ) - { - _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN - if( state.needf ) - { - func(state.x, state.f, ptr); - continue; - } - if( state.needfij ) - { - jac(state.x, state.fi, state.j, ptr); - continue; - } - if( state.xupdated ) - { - if( rep!=NULL ) - rep(state.x, state.f, ptr); - continue; - } - goto lbl_no_callback; - _ALGLIB_CALLBACK_EXCEPTION_GUARD_END - lbl_no_callback: - alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'nleqsolve' (some derivatives were not provided?)", &_alglib_env_state); - } - alglib_impl::ae_state_clear(&_alglib_env_state); -} - - - -/************************************************************************* -NLEQ solver results - -INPUT PARAMETERS: - State - algorithm state. - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report: - * Rep.TerminationType completetion code: - * -4 ERROR: algorithm has converged to the - stationary point Xf which is local minimum of - f=F[0]^2+...+F[m-1]^2, but is not solution of - nonlinear system. - * 1 sqrt(f)<=EpsF. - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible - * Rep.IterationsCount contains iterations count - * NFEV countains number of function calculations - * ActiveConstraints contains number of active constraints - - -- ALGLIB -- - Copyright 20.08.2009 by Bochkanov Sergey -*************************************************************************/ -void nleqresults(const nleqstate &state, real_1d_array &x, nleqreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::nleqresults(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -NLEQ solver results - -Buffered implementation of NLEQResults(), which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 20.08.2009 by Bochkanov Sergey -*************************************************************************/ -void nleqresultsbuf(const nleqstate &state, real_1d_array &x, nleqreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::nleqresultsbuf(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This subroutine restarts CG algorithm from new point. All optimization -parameters are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure used for reverse communication previously - allocated with MinCGCreate call. - X - new starting point. - BndL - new lower bounds - BndU - new upper bounds - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -void nleqrestartfrom(const nleqstate &state, const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::nleqrestartfrom(const_cast(state.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_DIRECTSPARSESOLVERS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This structure is a sparse solver report. - -Following fields can be accessed by users: -*************************************************************************/ -_sparsesolverreport_owner::_sparsesolverreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_sparsesolverreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::sparsesolverreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::sparsesolverreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::sparsesolverreport)); - alglib_impl::_sparsesolverreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_sparsesolverreport_owner::_sparsesolverreport_owner(const _sparsesolverreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_sparsesolverreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: sparsesolverreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::sparsesolverreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::sparsesolverreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::sparsesolverreport)); - alglib_impl::_sparsesolverreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_sparsesolverreport_owner& _sparsesolverreport_owner::operator=(const _sparsesolverreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: sparsesolverreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: sparsesolverreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_sparsesolverreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::sparsesolverreport)); - alglib_impl::_sparsesolverreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_sparsesolverreport_owner::~_sparsesolverreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_sparsesolverreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::sparsesolverreport* _sparsesolverreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::sparsesolverreport* _sparsesolverreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -sparsesolverreport::sparsesolverreport() : _sparsesolverreport_owner() ,terminationtype(p_struct->terminationtype) -{ -} - -sparsesolverreport::sparsesolverreport(const sparsesolverreport &rhs):_sparsesolverreport_owner(rhs) ,terminationtype(p_struct->terminationtype) -{ -} - -sparsesolverreport& sparsesolverreport::operator=(const sparsesolverreport &rhs) -{ - if( this==&rhs ) - return *this; - _sparsesolverreport_owner::operator=(rhs); - return *this; -} - -sparsesolverreport::~sparsesolverreport() -{ -} - -/************************************************************************* -Sparse linear solver for A*x=b with N*N sparse real symmetric positive -definite matrix A, N*1 vectors x and b. - -This solver converts input matrix to SKS format, performs Cholesky -factorization using SKS Cholesky subroutine (works well for limited -bandwidth matrices) and uses sparse triangular solvers to get solution of -the original system. - -INPUT PARAMETERS - A - sparse matrix, must be NxN exactly - IsUpper - which half of A is provided (another half is ignored) - B - array[0..N-1], right part - -OUTPUT PARAMETERS - X - array[N], it contains: - * rep.terminationtype>0 => solution - * rep.terminationtype=-3 => filled by zeros - Rep - solver report, following fields are set: - * rep.terminationtype - solver status; >0 for success, - set to -3 on failure (degenerate or non-SPD system). - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -void sparsespdsolvesks(const sparsematrix &a, const bool isupper, const real_1d_array &b, real_1d_array &x, sparsesolverreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsespdsolvesks(const_cast(a.c_ptr()), isupper, const_cast(b.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Sparse linear solver for A*x=b with N*N sparse real symmetric positive -definite matrix A, N*1 vectors x and b. - -This solver converts input matrix to CRS format, performs Cholesky -factorization using supernodal Cholesky decomposition with permutation- -reducing ordering and uses sparse triangular solver to get solution of the -original system. - -INPUT PARAMETERS - A - sparse matrix, must be NxN exactly - IsUpper - which half of A is provided (another half is ignored) - B - array[N], right part - -OUTPUT PARAMETERS - X - array[N], it contains: - * rep.terminationtype>0 => solution - * rep.terminationtype=-3 => filled by zeros - Rep - solver report, following fields are set: - * rep.terminationtype - solver status; >0 for success, - set to -3 on failure (degenerate or non-SPD system). - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -void sparsespdsolve(const sparsematrix &a, const bool isupper, const real_1d_array &b, real_1d_array &x, sparsesolverreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsespdsolve(const_cast(a.c_ptr()), isupper, const_cast(b.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Sparse linear solver for A*x=b with N*N real symmetric positive definite -matrix A given by its Cholesky decomposition, and N*1 vectors x and b. - -IMPORTANT: this solver requires input matrix to be in the SKS (Skyline) - or CRS (compressed row storage) format. An exception will be - generated if you pass matrix in some other format. - -INPUT PARAMETERS - A - sparse NxN matrix stored in CRs or SKS format, must be NxN - exactly - IsUpper - which half of A is provided (another half is ignored) - B - array[N], right part - -OUTPUT PARAMETERS - X - array[N], it contains: - * rep.terminationtype>0 => solution - * rep.terminationtype=-3 => filled by zeros - Rep - solver report, following fields are set: - * rep.terminationtype - solver status; >0 for success, - set to -3 on failure (degenerate or non-SPD system). - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -void sparsespdcholeskysolve(const sparsematrix &a, const bool isupper, const real_1d_array &b, real_1d_array &x, sparsesolverreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsespdcholeskysolve(const_cast(a.c_ptr()), isupper, const_cast(b.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Sparse linear solver for A*x=b with general (nonsymmetric) N*N sparse real -matrix A, N*1 vectors x and b. - -This solver converts input matrix to CRS format, performs LU factorization -and uses sparse triangular solvers to get solution of the original system. - -INPUT PARAMETERS - A - sparse matrix, must be NxN exactly, any storage format - N - size of A, N>0 - B - array[0..N-1], right part - -OUTPUT PARAMETERS - X - array[N], it contains: - * rep.terminationtype>0 => solution - * rep.terminationtype=-3 => filled by zeros - Rep - solver report, following fields are set: - * rep.terminationtype - solver status; >0 for success, - set to -3 on failure (degenerate system). - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -void sparsesolve(const sparsematrix &a, const real_1d_array &b, real_1d_array &x, sparsesolverreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparsesolve(const_cast(a.c_ptr()), const_cast(b.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Sparse linear solver for A*x=b with general (nonsymmetric) N*N sparse real -matrix A given by its LU factorization, N*1 vectors x and b. - -IMPORTANT: this solver requires input matrix to be in the CRS sparse - storage format. An exception will be generated if you pass - matrix in some other format (HASH or SKS). - -INPUT PARAMETERS - A - LU factorization of the sparse matrix, must be NxN exactly - in CRS storage format - P, Q - pivot indexes from LU factorization - N - size of A, N>0 - B - array[0..N-1], right part - -OUTPUT PARAMETERS - X - array[N], it contains: - * rep.terminationtype>0 => solution - * rep.terminationtype=-3 => filled by zeros - Rep - solver report, following fields are set: - * rep.terminationtype - solver status; >0 for success, - set to -3 on failure (degenerate system). - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -void sparselusolve(const sparsematrix &a, const integer_1d_array &p, const integer_1d_array &q, const real_1d_array &b, real_1d_array &x, sparsesolverreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sparselusolve(const_cast(a.c_ptr()), const_cast(p.c_ptr()), const_cast(q.c_ptr()), const_cast(b.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_LINCG) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores state of the linear CG method. - -You should use ALGLIB functions to work with this object. -Never try to access its fields directly! -*************************************************************************/ -_lincgstate_owner::_lincgstate_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_lincgstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::lincgstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::lincgstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::lincgstate)); - alglib_impl::_lincgstate_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_lincgstate_owner::_lincgstate_owner(const _lincgstate_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_lincgstate_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: lincgstate copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::lincgstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::lincgstate), &_state); - memset(p_struct, 0, sizeof(alglib_impl::lincgstate)); - alglib_impl::_lincgstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_lincgstate_owner& _lincgstate_owner::operator=(const _lincgstate_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: lincgstate assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: lincgstate assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_lincgstate_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::lincgstate)); - alglib_impl::_lincgstate_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_lincgstate_owner::~_lincgstate_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_lincgstate_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::lincgstate* _lincgstate_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::lincgstate* _lincgstate_owner::c_ptr() const -{ - return const_cast(p_struct); -} -lincgstate::lincgstate() : _lincgstate_owner() -{ -} - -lincgstate::lincgstate(const lincgstate &rhs):_lincgstate_owner(rhs) -{ -} - -lincgstate& lincgstate::operator=(const lincgstate &rhs) -{ - if( this==&rhs ) - return *this; - _lincgstate_owner::operator=(rhs); - return *this; -} - -lincgstate::~lincgstate() -{ -} - - -/************************************************************************* - -*************************************************************************/ -_lincgreport_owner::_lincgreport_owner() -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_lincgreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - p_struct = (alglib_impl::lincgreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::lincgreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::lincgreport)); - alglib_impl::_lincgreport_init(p_struct, &_state, ae_false); - ae_state_clear(&_state); -} - -_lincgreport_owner::_lincgreport_owner(const _lincgreport_owner &rhs) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { - if( p_struct!=NULL ) - { - alglib_impl::_lincgreport_destroy(p_struct); - alglib_impl::ae_free(p_struct); - } - p_struct = NULL; -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - p_struct = NULL; - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: lincgreport copy constructor failure (source is not initialized)", &_state); - p_struct = (alglib_impl::lincgreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::lincgreport), &_state); - memset(p_struct, 0, sizeof(alglib_impl::lincgreport)); - alglib_impl::_lincgreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); -} - -_lincgreport_owner& _lincgreport_owner::operator=(const _lincgreport_owner &rhs) -{ - if( this==&rhs ) - return *this; - jmp_buf _break_jump; - alglib_impl::ae_state _state; - - alglib_impl::ae_state_init(&_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_state.error_msg); - return *this; -#endif - } - alglib_impl::ae_state_set_break_jump(&_state, &_break_jump); - alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: lincgreport assignment constructor failure (destination is not initialized)", &_state); - alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: lincgreport assignment constructor failure (source is not initialized)", &_state); - alglib_impl::_lincgreport_destroy(p_struct); - memset(p_struct, 0, sizeof(alglib_impl::lincgreport)); - alglib_impl::_lincgreport_init_copy(p_struct, const_cast(rhs.p_struct), &_state, ae_false); - ae_state_clear(&_state); - return *this; -} - -_lincgreport_owner::~_lincgreport_owner() -{ - if( p_struct!=NULL ) - { - alglib_impl::_lincgreport_destroy(p_struct); - ae_free(p_struct); - } -} - -alglib_impl::lincgreport* _lincgreport_owner::c_ptr() -{ - return p_struct; -} - -alglib_impl::lincgreport* _lincgreport_owner::c_ptr() const -{ - return const_cast(p_struct); -} -lincgreport::lincgreport() : _lincgreport_owner() ,iterationscount(p_struct->iterationscount),nmv(p_struct->nmv),terminationtype(p_struct->terminationtype),r2(p_struct->r2) -{ -} - -lincgreport::lincgreport(const lincgreport &rhs):_lincgreport_owner(rhs) ,iterationscount(p_struct->iterationscount),nmv(p_struct->nmv),terminationtype(p_struct->terminationtype),r2(p_struct->r2) -{ -} - -lincgreport& lincgreport::operator=(const lincgreport &rhs) -{ - if( this==&rhs ) - return *this; - _lincgreport_owner::operator=(rhs); - return *this; -} - -lincgreport::~lincgreport() -{ -} - -/************************************************************************* -This function initializes linear CG Solver. This solver is used to solve -symmetric positive definite problems. If you want to solve nonsymmetric -(or non-positive definite) problem you may use LinLSQR solver provided by -ALGLIB. - -USAGE: -1. User initializes algorithm state with LinCGCreate() call -2. User tunes solver parameters with LinCGSetCond() and other functions -3. Optionally, user sets starting point with LinCGSetStartingPoint() -4. User calls LinCGSolveSparse() function which takes algorithm state and - SparseMatrix object. -5. User calls LinCGResults() to get solution -6. Optionally, user may call LinCGSolveSparse() again to solve another - problem with different matrix and/or right part without reinitializing - LinCGState structure. - -INPUT PARAMETERS: - N - problem dimension, N>0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgcreate(const ae_int_t n, lincgstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lincgcreate(n, const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets starting point. -By default, zero starting point is used. - -INPUT PARAMETERS: - X - starting point, array[N] - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgsetstartingpoint(const lincgstate &state, const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lincgsetstartingpoint(const_cast(state.c_ptr()), const_cast(x.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function changes preconditioning settings of LinCGSolveSparse() -function. By default, SolveSparse() uses diagonal preconditioner, but if -you want to use solver without preconditioning, you can call this function -which forces solver to use unit matrix for preconditioning. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 19.11.2012 by Bochkanov Sergey -*************************************************************************/ -void lincgsetprecunit(const lincgstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lincgsetprecunit(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function changes preconditioning settings of LinCGSolveSparse() -function. LinCGSolveSparse() will use diagonal of the system matrix as -preconditioner. This preconditioning mode is active by default. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 19.11.2012 by Bochkanov Sergey -*************************************************************************/ -void lincgsetprecdiag(const lincgstate &state, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lincgsetprecdiag(const_cast(state.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets stopping criteria. - -INPUT PARAMETERS: - EpsF - algorithm will be stopped if norm of residual is less than - EpsF*||b||. - MaxIts - algorithm will be stopped if number of iterations is more - than MaxIts. - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -If both EpsF and MaxIts are zero then small EpsF will be set to small -value. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgsetcond(const lincgstate &state, const double epsf, const ae_int_t maxits, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lincgsetcond(const_cast(state.c_ptr()), epsf, maxits, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Procedure for solution of A*x=b with sparse A. - -INPUT PARAMETERS: - State - algorithm state - A - sparse matrix in the CRS format (you MUST contvert it to - CRS format by calling SparseConvertToCRS() function). - IsUpper - whether upper or lower triangle of A is used: - * IsUpper=True => only upper triangle is used and lower - triangle is not referenced at all - * IsUpper=False => only lower triangle is used and upper - triangle is not referenced at all - B - right part, array[N] - -RESULT: - This function returns no result. - You can get solution by calling LinCGResults() - -NOTE: this function uses lightweight preconditioning - multiplication by - inverse of diag(A). If you want, you can turn preconditioning off by - calling LinCGSetPrecUnit(). However, preconditioning cost is low and - preconditioner is very important for solution of badly scaled - problems. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgsolvesparse(const lincgstate &state, const sparsematrix &a, const bool isupper, const real_1d_array &b, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lincgsolvesparse(const_cast(state.c_ptr()), const_cast(a.c_ptr()), isupper, const_cast(b.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -CG-solver: results. - -This function must be called after LinCGSolve - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[N], solution - Rep - optimization report: - * Rep.TerminationType completetion code: - * -5 input matrix is either not positive definite, - too large or too small - * -4 overflow/underflow during solution - (ill conditioned problem) - * 1 ||residual||<=EpsF*||b|| - * 5 MaxIts steps was taken - * 7 rounding errors prevent further progress, - best point found is returned - * Rep.IterationsCount contains iterations count - * NMV countains number of matrix-vector calculations - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgresults(const lincgstate &state, real_1d_array &x, lincgreport &rep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lincgresults(const_cast(state.c_ptr()), const_cast(x.c_ptr()), const_cast(rep.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets restart frequency. By default, algorithm is restarted -after N subsequent iterations. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgsetrestartfreq(const lincgstate &state, const ae_int_t srf, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lincgsetrestartfreq(const_cast(state.c_ptr()), srf, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function sets frequency of residual recalculations. - -Algorithm updates residual r_k using iterative formula, but recalculates -it from scratch after each 10 iterations. It is done to avoid accumulation -of numerical errors and to stop algorithm when r_k starts to grow. - -Such low update frequence (1/10) gives very little overhead, but makes -algorithm a bit more robust against numerical errors. However, you may -change it - -INPUT PARAMETERS: - Freq - desired update frequency, Freq>=0. - Zero value means that no updates will be done. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgsetrupdatefreq(const lincgstate &state, const ae_int_t freq, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lincgsetrupdatefreq(const_cast(state.c_ptr()), freq, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinCGOptimize(). - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgsetxrep(const lincgstate &state, const bool needxrep, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::lincgsetxrep(const_cast(state.c_ptr()), needxrep, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF COMPUTATIONAL CORE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_DIRECTDENSESOLVERS) || !defined(AE_PARTIAL_BUILD) -static void directdensesolvers_rmatrixlusolveinternal(/* Real */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_bool havea, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_matrix* x, - ae_state *_state); -static void directdensesolvers_spdmatrixcholeskysolveinternal(/* Real */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_matrix* a, - ae_bool havea, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_matrix* x, - ae_state *_state); -static void directdensesolvers_cmatrixlusolveinternal(/* Complex */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_bool havea, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_matrix* x, - ae_state *_state); -static void directdensesolvers_hpdmatrixcholeskysolveinternal(/* Complex */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_matrix* a, - ae_bool havea, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_matrix* x, - ae_state *_state); -static ae_int_t directdensesolvers_densesolverrfsmax(ae_int_t n, - double r1, - double rinf, - ae_state *_state); -static ae_int_t directdensesolvers_densesolverrfsmaxv2(ae_int_t n, - double r2, - ae_state *_state); -static void directdensesolvers_rbasiclusolve(/* Real */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Real */ ae_vector* xb, - ae_state *_state); -static void directdensesolvers_spdbasiccholeskysolve(/* Real */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* xb, - ae_state *_state); -static void directdensesolvers_cbasiclusolve(/* Complex */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Complex */ ae_vector* xb, - ae_state *_state); -static void directdensesolvers_hpdbasiccholeskysolve(/* Complex */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* xb, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_LINLSQR) || !defined(AE_PARTIAL_BUILD) -static double linlsqr_atol = 1.0E-6; -static double linlsqr_btol = 1.0E-6; -static void linlsqr_clearrfields(linlsqrstate* state, ae_state *_state); - - -#endif -#if defined(AE_COMPILE_POLYNOMIALSOLVER) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_NLEQ) || !defined(AE_PARTIAL_BUILD) -static void nleq_clearrequestfields(nleqstate* state, ae_state *_state); -static ae_bool nleq_increaselambda(double* lambdav, - double* nu, - double lambdaup, - ae_state *_state); -static void nleq_decreaselambda(double* lambdav, - double* nu, - double lambdadown, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_DIRECTSPARSESOLVERS) || !defined(AE_PARTIAL_BUILD) -static void directsparsesolvers_initreport(sparsesolverreport* rep, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_LINCG) || !defined(AE_PARTIAL_BUILD) -static double lincg_defaultprecision = 1.0E-6; -static void lincg_clearrfields(lincgstate* state, ae_state *_state); -static void lincg_updateitersdata(lincgstate* state, ae_state *_state); - - -#endif - -#if defined(AE_COMPILE_DIRECTDENSESOLVERS) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Dense solver for A*x=b with N*N real matrix A and N*1 real vectorx x and -b. This is "slow-but-feature rich" version of the linear solver. Faster -version is RMatrixSolveFast() function. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(N^3) complexity - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system - ! and performs iterative refinement, which results in - ! significant performance penalty when compared with "fast" - ! version which just performs LU decomposition and calls - ! triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. It is also very significant on small matrices. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, RMatrixSolveFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixsolve(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_vector* b, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix bm; - ae_matrix xm; - - ae_frame_make(_state, &_frame_block); - memset(&bm, 0, sizeof(bm)); - memset(&xm, 0, sizeof(xm)); - *info = 0; - _densesolverreport_clear(rep); - ae_vector_clear(x); - ae_matrix_init(&bm, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xm, 0, 0, DT_REAL, _state, ae_true); - - if( n<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&bm, n, 1, _state); - ae_v_move(&bm.ptr.pp_double[0][0], bm.stride, &b->ptr.p_double[0], 1, ae_v_len(0,n-1)); - rmatrixsolvem(a, n, &bm, 1, ae_true, info, rep, &xm, _state); - ae_vector_set_length(x, n, _state); - ae_v_move(&x->ptr.p_double[0], 1, &xm.ptr.pp_double[0][0], xm.stride, ae_v_len(0,n-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense solver. - -This subroutine solves a system A*x=b, where A is NxN non-denegerate -real matrix, x and b are vectors. This is a "fast" version of linear -solver which does NOT provide any additional functions like condition -number estimation or iterative refinement. - -Algorithm features: -* efficient algorithm O(N^3) complexity -* no performance overhead from additional functionality - -If you need condition number estimation or iterative refinement, use more -feature-rich version - RMatrixSolve(). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 16.03.2015 by Bochkanov Sergey -*************************************************************************/ -void rmatrixsolvefast(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_vector* b, - ae_int_t* info, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_int_t i; - ae_int_t j; - ae_vector p; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&p, 0, sizeof(p)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - *info = 0; - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - - if( n<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - rmatrixlu(a, n, n, &p, _state); - for(i=0; i<=n-1; i++) - { - if( ae_fp_eq(a->ptr.pp_double[i][i],(double)(0)) ) - { - for(j=0; j<=n-1; j++) - { - b->ptr.p_double[j] = 0.0; - } - *info = -3; - ae_frame_leave(_state); - return; - } - } - directdensesolvers_rbasiclusolve(a, &p, n, b, _state); - *info = 1; - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense solver. - -Similar to RMatrixSolve() but solves task with multiple right parts (where -b and x are NxM matrices). This is "slow-but-robust" version of linear -solver with additional functionality like condition number estimation. -There also exists faster version - RMatrixSolveMFast(). - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* optional iterative refinement -* O(N^3+M*N^2) complexity - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system - ! and performs iterative refinement, which results in - ! significant performance penalty when compared with "fast" - ! version which just performs LU decomposition and calls - ! triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. It also very significant on small matrices. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, RMatrixSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - RFS - iterative refinement switch: - * True - refinement is used. - Less performance, more precision. - * False - refinement is not used. - More performance, less precision. - -OUTPUT PARAMETERS - Info - return code: - * -3 A is ill conditioned or singular. - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixsolvem(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_bool rfs, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_matrix* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix da; - ae_matrix emptya; - ae_vector p; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&da, 0, sizeof(da)); - memset(&emptya, 0, sizeof(emptya)); - memset(&p, 0, sizeof(p)); - *info = 0; - _densesolverreport_clear(rep); - ae_matrix_clear(x); - ae_matrix_init(&da, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&emptya, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - - - /* - * prepare: check inputs, allocate space... - */ - if( n<=0||m<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&da, n, n, _state); - - /* - * 1. factorize matrix - * 3. solve - */ - for(i=0; i<=n-1; i++) - { - ae_v_move(&da.ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - } - rmatrixlu(&da, n, n, &p, _state); - if( rfs ) - { - directdensesolvers_rmatrixlusolveinternal(&da, &p, n, a, ae_true, b, m, info, rep, x, _state); - } - else - { - directdensesolvers_rmatrixlusolveinternal(&da, &p, n, &emptya, ae_false, b, m, info, rep, x, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense solver. - -Similar to RMatrixSolve() but solves task with multiple right parts (where -b and x are NxM matrices). This is "fast" version of linear solver which -does NOT offer additional functions like condition number estimation or -iterative refinement. - -Algorithm features: -* O(N^3+M*N^2) complexity -* no additional functionality, highest performance - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - RFS - iterative refinement switch: - * True - refinement is used. - Less performance, more precision. - * False - refinement is not used. - More performance, less precision. - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - B - array[N]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixsolvemfast(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - double v; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_vector p; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&p, 0, sizeof(p)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - *info = 0; - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - - - /* - * Check for exact degeneracy - */ - if( n<=0||m<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - rmatrixlu(a, n, n, &p, _state); - for(i=0; i<=n-1; i++) - { - if( ae_fp_eq(a->ptr.pp_double[i][i],(double)(0)) ) - { - for(j=0; j<=n-1; j++) - { - for(k=0; k<=m-1; k++) - { - b->ptr.pp_double[j][k] = 0.0; - } - } - *info = -3; - ae_frame_leave(_state); - return; - } - } - - /* - * Solve with TRSM() - */ - for(i=0; i<=n-1; i++) - { - if( p.ptr.p_int[i]!=i ) - { - for(j=0; j<=m-1; j++) - { - v = b->ptr.pp_double[i][j]; - b->ptr.pp_double[i][j] = b->ptr.pp_double[p.ptr.p_int[i]][j]; - b->ptr.pp_double[p.ptr.p_int[i]][j] = v; - } - } - } - rmatrixlefttrsm(n, m, a, 0, 0, ae_false, ae_true, 0, b, 0, 0, _state); - rmatrixlefttrsm(n, m, a, 0, 0, ae_true, ae_false, 0, b, 0, 0, _state); - *info = 1; - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense solver. - -This subroutine solves a system A*x=b, where A is NxN non-denegerate -real matrix given by its LU decomposition, x and b are real vectors. This -is "slow-but-robust" version of the linear LU-based solver. Faster version -is RMatrixLUSolveFast() function. - -Algorithm features: -* automatic detection of degenerate cases -* O(N^2) complexity -* condition number estimation - -No iterative refinement is provided because exact form of original matrix -is not known to subroutine. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in 10-15x performance penalty when compared - ! with "fast" version which just calls triangular solver. - ! - ! This performance penalty is insignificant when compared with - ! cost of large LU decomposition. However, if you call this - ! function many times for the same left side, this overhead - ! BECOMES significant. It also becomes significant for small- - ! scale problems. - ! - ! In such cases we strongly recommend you to use faster solver, - ! RMatrixLUSolveFast() function. - -INPUT PARAMETERS - LUA - array[N,N], LU decomposition, RMatrixLU result - P - array[N], pivots array, RMatrixLU result - N - size of A - B - array[N], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixlusolve(/* Real */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Real */ ae_vector* b, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix bm; - ae_matrix xm; - - ae_frame_make(_state, &_frame_block); - memset(&bm, 0, sizeof(bm)); - memset(&xm, 0, sizeof(xm)); - *info = 0; - _densesolverreport_clear(rep); - ae_vector_clear(x); - ae_matrix_init(&bm, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xm, 0, 0, DT_REAL, _state, ae_true); - - if( n<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&bm, n, 1, _state); - ae_v_move(&bm.ptr.pp_double[0][0], bm.stride, &b->ptr.p_double[0], 1, ae_v_len(0,n-1)); - rmatrixlusolvem(lua, p, n, &bm, 1, info, rep, &xm, _state); - ae_vector_set_length(x, n, _state); - ae_v_move(&x->ptr.p_double[0], 1, &xm.ptr.pp_double[0][0], xm.stride, ae_v_len(0,n-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense solver. - -This subroutine solves a system A*x=b, where A is NxN non-denegerate -real matrix given by its LU decomposition, x and b are real vectors. This -is "fast-without-any-checks" version of the linear LU-based solver. Slower -but more robust version is RMatrixLUSolve() function. - -Algorithm features: -* O(N^2) complexity -* fast algorithm without ANY additional checks, just triangular solver - -INPUT PARAMETERS - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 18.03.2015 by Bochkanov Sergey -*************************************************************************/ -void rmatrixlusolvefast(/* Real */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Real */ ae_vector* b, - ae_int_t* info, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - *info = 0; - - if( n<=0 ) - { - *info = -1; - return; - } - for(i=0; i<=n-1; i++) - { - if( ae_fp_eq(lua->ptr.pp_double[i][i],(double)(0)) ) - { - for(j=0; j<=n-1; j++) - { - b->ptr.p_double[j] = 0.0; - } - *info = -3; - return; - } - } - directdensesolvers_rbasiclusolve(lua, p, n, b, _state); - *info = 1; -} - - -/************************************************************************* -Dense solver. - -Similar to RMatrixLUSolve() but solves task with multiple right parts -(where b and x are NxM matrices). This is "robust-but-slow" version of -LU-based solver which performs additional checks for non-degeneracy of -inputs (condition number estimation). If you need best performance, use -"fast-without-any-checks" version, RMatrixLUSolveMFast(). - -Algorithm features: -* automatic detection of degenerate cases -* O(M*N^2) complexity -* condition number estimation - -No iterative refinement is provided because exact form of original matrix -is not known to subroutine. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just calls triangular - ! solver. - ! - ! This performance penalty is especially apparent when you use - ! ALGLIB parallel capabilities (condition number estimation is - ! inherently sequential). It also becomes significant for - ! small-scale problems. - ! - ! In such cases we strongly recommend you to use faster solver, - ! RMatrixLUSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - LUA - array[N,N], LU decomposition, RMatrixLU result - P - array[N], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixlusolvem(/* Real */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_matrix* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix emptya; - - ae_frame_make(_state, &_frame_block); - memset(&emptya, 0, sizeof(emptya)); - *info = 0; - _densesolverreport_clear(rep); - ae_matrix_clear(x); - ae_matrix_init(&emptya, 0, 0, DT_REAL, _state, ae_true); - - - /* - * prepare: check inputs, allocate space... - */ - if( n<=0||m<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - - /* - * solve - */ - directdensesolvers_rmatrixlusolveinternal(lua, p, n, &emptya, ae_false, b, m, info, rep, x, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense solver. - -Similar to RMatrixLUSolve() but solves task with multiple right parts, -where b and x are NxM matrices. This is "fast-without-any-checks" version -of LU-based solver. It does not estimate condition number of a system, -so it is extremely fast. If you need better detection of near-degenerate -cases, use RMatrixLUSolveM() function. - -Algorithm features: -* O(M*N^2) complexity -* fast algorithm without ANY additional checks, just triangular solver - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS: - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N,M]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 18.03.2015 by Bochkanov Sergey -*************************************************************************/ -void rmatrixlusolvemfast(/* Real */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - ae_state *_state) -{ - double v; - ae_int_t i; - ae_int_t j; - ae_int_t k; - - *info = 0; - - - /* - * Check for exact degeneracy - */ - if( n<=0||m<=0 ) - { - *info = -1; - return; - } - for(i=0; i<=n-1; i++) - { - if( ae_fp_eq(lua->ptr.pp_double[i][i],(double)(0)) ) - { - for(j=0; j<=n-1; j++) - { - for(k=0; k<=m-1; k++) - { - b->ptr.pp_double[j][k] = 0.0; - } - } - *info = -3; - return; - } - } - - /* - * Solve with TRSM() - */ - for(i=0; i<=n-1; i++) - { - if( p->ptr.p_int[i]!=i ) - { - for(j=0; j<=m-1; j++) - { - v = b->ptr.pp_double[i][j]; - b->ptr.pp_double[i][j] = b->ptr.pp_double[p->ptr.p_int[i]][j]; - b->ptr.pp_double[p->ptr.p_int[i]][j] = v; - } - } - } - rmatrixlefttrsm(n, m, lua, 0, 0, ae_false, ae_true, 0, b, 0, 0, _state); - rmatrixlefttrsm(n, m, lua, 0, 0, ae_true, ae_false, 0, b, 0, 0, _state); - *info = 1; -} - - -/************************************************************************* -Dense solver. - -This subroutine solves a system A*x=b, where BOTH ORIGINAL A AND ITS -LU DECOMPOSITION ARE KNOWN. You can use it if for some reasons you have -both A and its LU decomposition. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(N^2) complexity - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixmixedsolve(/* Real */ ae_matrix* a, - /* Real */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Real */ ae_vector* b, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix bm; - ae_matrix xm; - - ae_frame_make(_state, &_frame_block); - memset(&bm, 0, sizeof(bm)); - memset(&xm, 0, sizeof(xm)); - *info = 0; - _densesolverreport_clear(rep); - ae_vector_clear(x); - ae_matrix_init(&bm, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xm, 0, 0, DT_REAL, _state, ae_true); - - if( n<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&bm, n, 1, _state); - ae_v_move(&bm.ptr.pp_double[0][0], bm.stride, &b->ptr.p_double[0], 1, ae_v_len(0,n-1)); - rmatrixmixedsolvem(a, lua, p, n, &bm, 1, info, rep, &xm, _state); - ae_vector_set_length(x, n, _state); - ae_v_move(&x->ptr.p_double[0], 1, &xm.ptr.pp_double[0][0], xm.stride, ae_v_len(0,n-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense solver. - -Similar to RMatrixMixedSolve() but solves task with multiple right parts -(where b and x are NxM matrices). - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(M*N^2) complexity - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixmixedsolvem(/* Real */ ae_matrix* a, - /* Real */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_matrix* x, - ae_state *_state) -{ - - *info = 0; - _densesolverreport_clear(rep); - ae_matrix_clear(x); - - - /* - * prepare: check inputs, allocate space... - */ - if( n<=0||m<=0 ) - { - *info = -1; - return; - } - - /* - * solve - */ - directdensesolvers_rmatrixlusolveinternal(lua, p, n, a, ae_true, b, m, info, rep, x, _state); -} - - -/************************************************************************* -Complex dense solver for A*X=B with N*N complex matrix A, N*M complex -matrices X and B. "Slow-but-feature-rich" version which provides -additional functions, at the cost of slower performance. Faster version -may be invoked with CMatrixSolveMFast() function. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(N^3+M*N^2) complexity - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system - ! and performs iterative refinement, which results in - ! significant performance penalty when compared with "fast" - ! version which just performs LU decomposition and calls - ! triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, CMatrixSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - RFS - iterative refinement switch: - * True - refinement is used. - Less performance, more precision. - * False - refinement is not used. - More performance, less precision. - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixsolvem(/* Complex */ ae_matrix* a, - ae_int_t n, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_bool rfs, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_matrix* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix da; - ae_matrix emptya; - ae_vector p; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&da, 0, sizeof(da)); - memset(&emptya, 0, sizeof(emptya)); - memset(&p, 0, sizeof(p)); - *info = 0; - _densesolverreport_clear(rep); - ae_matrix_clear(x); - ae_matrix_init(&da, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&emptya, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - - - /* - * prepare: check inputs, allocate space... - */ - if( n<=0||m<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&da, n, n, _state); - - /* - * factorize, solve - */ - for(i=0; i<=n-1; i++) - { - ae_v_cmove(&da.ptr.pp_complex[i][0], 1, &a->ptr.pp_complex[i][0], 1, "N", ae_v_len(0,n-1)); - } - cmatrixlu(&da, n, n, &p, _state); - if( rfs ) - { - directdensesolvers_cmatrixlusolveinternal(&da, &p, n, a, ae_true, b, m, info, rep, x, _state); - } - else - { - directdensesolvers_cmatrixlusolveinternal(&da, &p, n, &emptya, ae_false, b, m, info, rep, x, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Complex dense solver for A*X=B with N*N complex matrix A, N*M complex -matrices X and B. "Fast-but-lightweight" version which provides just -triangular solver - and no additional functions like iterative refinement -or condition number estimation. - -Algorithm features: -* O(N^3+M*N^2) complexity -* no additional time consuming functions - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS: - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N,M]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 16.03.2015 by Bochkanov Sergey -*************************************************************************/ -void cmatrixsolvemfast(/* Complex */ ae_matrix* a, - ae_int_t n, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_complex v; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_vector p; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&p, 0, sizeof(p)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - *info = 0; - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - - - /* - * Check for exact degeneracy - */ - if( n<=0||m<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - cmatrixlu(a, n, n, &p, _state); - for(i=0; i<=n-1; i++) - { - if( ae_c_eq_d(a->ptr.pp_complex[i][i],(double)(0)) ) - { - for(j=0; j<=n-1; j++) - { - for(k=0; k<=m-1; k++) - { - b->ptr.pp_complex[j][k] = ae_complex_from_d(0.0); - } - } - *info = -3; - ae_frame_leave(_state); - return; - } - } - - /* - * Solve with TRSM() - */ - for(i=0; i<=n-1; i++) - { - if( p.ptr.p_int[i]!=i ) - { - for(j=0; j<=m-1; j++) - { - v = b->ptr.pp_complex[i][j]; - b->ptr.pp_complex[i][j] = b->ptr.pp_complex[p.ptr.p_int[i]][j]; - b->ptr.pp_complex[p.ptr.p_int[i]][j] = v; - } - } - } - cmatrixlefttrsm(n, m, a, 0, 0, ae_false, ae_true, 0, b, 0, 0, _state); - cmatrixlefttrsm(n, m, a, 0, 0, ae_true, ae_false, 0, b, 0, 0, _state); - *info = 1; - ae_frame_leave(_state); -} - - -/************************************************************************* -Complex dense solver for A*x=B with N*N complex matrix A and N*1 complex -vectors x and b. "Slow-but-feature-rich" version of the solver. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(N^3) complexity - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system - ! and performs iterative refinement, which results in - ! significant performance penalty when compared with "fast" - ! version which just performs LU decomposition and calls - ! triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, CMatrixSolveFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixsolve(/* Complex */ ae_matrix* a, - ae_int_t n, - /* Complex */ ae_vector* b, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_vector* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix bm; - ae_matrix xm; - - ae_frame_make(_state, &_frame_block); - memset(&bm, 0, sizeof(bm)); - memset(&xm, 0, sizeof(xm)); - *info = 0; - _densesolverreport_clear(rep); - ae_vector_clear(x); - ae_matrix_init(&bm, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&xm, 0, 0, DT_COMPLEX, _state, ae_true); - - if( n<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&bm, n, 1, _state); - ae_v_cmove(&bm.ptr.pp_complex[0][0], bm.stride, &b->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1)); - cmatrixsolvem(a, n, &bm, 1, ae_true, info, rep, &xm, _state); - ae_vector_set_length(x, n, _state); - ae_v_cmove(&x->ptr.p_complex[0], 1, &xm.ptr.pp_complex[0][0], xm.stride, "N", ae_v_len(0,n-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -Complex dense solver for A*x=B with N*N complex matrix A and N*1 complex -vectors x and b. "Fast-but-lightweight" version of the solver. - -Algorithm features: -* O(N^3) complexity -* no additional time consuming features, just triangular solver - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS: - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixsolvefast(/* Complex */ ae_matrix* a, - ae_int_t n, - /* Complex */ ae_vector* b, - ae_int_t* info, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_int_t i; - ae_int_t j; - ae_vector p; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&p, 0, sizeof(p)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - *info = 0; - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - - if( n<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - cmatrixlu(a, n, n, &p, _state); - for(i=0; i<=n-1; i++) - { - if( ae_c_eq_d(a->ptr.pp_complex[i][i],(double)(0)) ) - { - for(j=0; j<=n-1; j++) - { - b->ptr.p_complex[j] = ae_complex_from_d(0.0); - } - *info = -3; - ae_frame_leave(_state); - return; - } - } - directdensesolvers_cbasiclusolve(a, &p, n, b, _state); - *info = 1; - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense solver for A*X=B with N*N complex A given by its LU decomposition, -and N*M matrices X and B (multiple right sides). "Slow-but-feature-rich" -version of the solver. - -Algorithm features: -* automatic detection of degenerate cases -* O(M*N^2) complexity -* condition number estimation - -No iterative refinement is provided because exact form of original matrix -is not known to subroutine. Use CMatrixSolve or CMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just calls triangular - ! solver. - ! - ! This performance penalty is especially apparent when you use - ! ALGLIB parallel capabilities (condition number estimation is - ! inherently sequential). It also becomes significant for - ! small-scale problems. - ! - ! In such cases we strongly recommend you to use faster solver, - ! CMatrixLUSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixlusolvem(/* Complex */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_matrix* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix emptya; - - ae_frame_make(_state, &_frame_block); - memset(&emptya, 0, sizeof(emptya)); - *info = 0; - _densesolverreport_clear(rep); - ae_matrix_clear(x); - ae_matrix_init(&emptya, 0, 0, DT_COMPLEX, _state, ae_true); - - - /* - * prepare: check inputs, allocate space... - */ - if( n<=0||m<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - - /* - * solve - */ - directdensesolvers_cmatrixlusolveinternal(lua, p, n, &emptya, ae_false, b, m, info, rep, x, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense solver for A*X=B with N*N complex A given by its LU decomposition, -and N*M matrices X and B (multiple right sides). "Fast-but-lightweight" -version of the solver. - -Algorithm features: -* O(M*N^2) complexity -* no additional time-consuming features - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N,M]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixlusolvemfast(/* Complex */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - ae_state *_state) -{ - ae_complex v; - ae_int_t i; - ae_int_t j; - ae_int_t k; - - *info = 0; - - - /* - * Check for exact degeneracy - */ - if( n<=0||m<=0 ) - { - *info = -1; - return; - } - for(i=0; i<=n-1; i++) - { - if( ae_c_eq_d(lua->ptr.pp_complex[i][i],(double)(0)) ) - { - for(j=0; j<=n-1; j++) - { - for(k=0; k<=m-1; k++) - { - b->ptr.pp_complex[j][k] = ae_complex_from_d(0.0); - } - } - *info = -3; - return; - } - } - - /* - * Solve with TRSM() - */ - for(i=0; i<=n-1; i++) - { - if( p->ptr.p_int[i]!=i ) - { - for(j=0; j<=m-1; j++) - { - v = b->ptr.pp_complex[i][j]; - b->ptr.pp_complex[i][j] = b->ptr.pp_complex[p->ptr.p_int[i]][j]; - b->ptr.pp_complex[p->ptr.p_int[i]][j] = v; - } - } - } - cmatrixlefttrsm(n, m, lua, 0, 0, ae_false, ae_true, 0, b, 0, 0, _state); - cmatrixlefttrsm(n, m, lua, 0, 0, ae_true, ae_false, 0, b, 0, 0, _state); - *info = 1; -} - - -/************************************************************************* -Complex dense linear solver for A*x=b with complex N*N A given by its LU -decomposition and N*1 vectors x and b. This is "slow-but-robust" version -of the complex linear solver with additional features which add -significant performance overhead. Faster version is CMatrixLUSolveFast() -function. - -Algorithm features: -* automatic detection of degenerate cases -* O(N^2) complexity -* condition number estimation - -No iterative refinement is provided because exact form of original matrix -is not known to subroutine. Use CMatrixSolve or CMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in 10-15x performance penalty when compared - ! with "fast" version which just calls triangular solver. - ! - ! This performance penalty is insignificant when compared with - ! cost of large LU decomposition. However, if you call this - ! function many times for the same left side, this overhead - ! BECOMES significant. It also becomes significant for small- - ! scale problems. - ! - ! In such cases we strongly recommend you to use faster solver, - ! CMatrixLUSolveFast() function. - -INPUT PARAMETERS - LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU result - P - array[0..N-1], pivots array, CMatrixLU result - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixlusolve(/* Complex */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Complex */ ae_vector* b, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_vector* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix bm; - ae_matrix xm; - - ae_frame_make(_state, &_frame_block); - memset(&bm, 0, sizeof(bm)); - memset(&xm, 0, sizeof(xm)); - *info = 0; - _densesolverreport_clear(rep); - ae_vector_clear(x); - ae_matrix_init(&bm, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&xm, 0, 0, DT_COMPLEX, _state, ae_true); - - if( n<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&bm, n, 1, _state); - ae_v_cmove(&bm.ptr.pp_complex[0][0], bm.stride, &b->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1)); - cmatrixlusolvem(lua, p, n, &bm, 1, info, rep, &xm, _state); - ae_vector_set_length(x, n, _state); - ae_v_cmove(&x->ptr.p_complex[0], 1, &xm.ptr.pp_complex[0][0], xm.stride, "N", ae_v_len(0,n-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -Complex dense linear solver for A*x=b with N*N complex A given by its LU -decomposition and N*1 vectors x and b. This is fast lightweight version -of solver, which is significantly faster than CMatrixLUSolve(), but does -not provide additional information (like condition numbers). - -Algorithm features: -* O(N^2) complexity -* no additional time-consuming features, just triangular solver - -INPUT PARAMETERS - LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU result - P - array[0..N-1], pivots array, CMatrixLU result - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - -NOTE: unlike CMatrixLUSolve(), this function does NOT check for - near-degeneracy of input matrix. It checks for EXACT degeneracy, - because this check is easy to do. However, very badly conditioned - matrices may went unnoticed. - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixlusolvefast(/* Complex */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Complex */ ae_vector* b, - ae_int_t* info, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - *info = 0; - - if( n<=0 ) - { - *info = -1; - return; - } - for(i=0; i<=n-1; i++) - { - if( ae_c_eq_d(lua->ptr.pp_complex[i][i],(double)(0)) ) - { - for(j=0; j<=n-1; j++) - { - b->ptr.p_complex[j] = ae_complex_from_d(0.0); - } - *info = -3; - return; - } - } - directdensesolvers_cbasiclusolve(lua, p, n, b, _state); - *info = 1; -} - - -/************************************************************************* -Dense solver. Same as RMatrixMixedSolveM(), but for complex matrices. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(M*N^2) complexity - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU result - P - array[0..N-1], pivots array, CMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixmixedsolvem(/* Complex */ ae_matrix* a, - /* Complex */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_matrix* x, - ae_state *_state) -{ - - *info = 0; - _densesolverreport_clear(rep); - ae_matrix_clear(x); - - - /* - * prepare: check inputs, allocate space... - */ - if( n<=0||m<=0 ) - { - *info = -1; - return; - } - - /* - * solve - */ - directdensesolvers_cmatrixlusolveinternal(lua, p, n, a, ae_true, b, m, info, rep, x, _state); -} - - -/************************************************************************* -Dense solver. Same as RMatrixMixedSolve(), but for complex matrices. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(N^2) complexity - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU result - P - array[0..N-1], pivots array, CMatrixLU result - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixmixedsolve(/* Complex */ ae_matrix* a, - /* Complex */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Complex */ ae_vector* b, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_vector* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix bm; - ae_matrix xm; - - ae_frame_make(_state, &_frame_block); - memset(&bm, 0, sizeof(bm)); - memset(&xm, 0, sizeof(xm)); - *info = 0; - _densesolverreport_clear(rep); - ae_vector_clear(x); - ae_matrix_init(&bm, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&xm, 0, 0, DT_COMPLEX, _state, ae_true); - - if( n<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&bm, n, 1, _state); - ae_v_cmove(&bm.ptr.pp_complex[0][0], bm.stride, &b->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1)); - cmatrixmixedsolvem(a, lua, p, n, &bm, 1, info, rep, &xm, _state); - ae_vector_set_length(x, n, _state); - ae_v_cmove(&x->ptr.p_complex[0], 1, &xm.ptr.pp_complex[0][0], xm.stride, "N", ae_v_len(0,n-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense solver for A*X=B with N*N symmetric positive definite matrix A, and -N*M vectors X and B. It is "slow-but-feature-rich" version of the solver. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* O(N^3+M*N^2) complexity -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just performs Cholesky - ! decomposition and calls triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, SPDMatrixSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or non-SPD. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixsolvem(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_matrix* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix da; - ae_int_t i; - ae_int_t j; - ae_int_t j1; - ae_int_t j2; - - ae_frame_make(_state, &_frame_block); - memset(&da, 0, sizeof(da)); - *info = 0; - _densesolverreport_clear(rep); - ae_matrix_clear(x); - ae_matrix_init(&da, 0, 0, DT_REAL, _state, ae_true); - - - /* - * prepare: check inputs, allocate space... - */ - if( n<=0||m<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&da, n, n, _state); - - /* - * factorize - * solve - */ - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j1 = i; - j2 = n-1; - } - else - { - j1 = 0; - j2 = i; - } - ae_v_move(&da.ptr.pp_double[i][j1], 1, &a->ptr.pp_double[i][j1], 1, ae_v_len(j1,j2)); - } - if( !spdmatrixcholesky(&da, n, isupper, _state) ) - { - ae_matrix_set_length(x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x->ptr.pp_double[i][j] = (double)(0); - } - } - rep->r1 = (double)(0); - rep->rinf = (double)(0); - *info = -3; - ae_frame_leave(_state); - return; - } - *info = 1; - directdensesolvers_spdmatrixcholeskysolveinternal(&da, n, isupper, a, ae_true, b, m, info, rep, x, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense solver for A*X=B with N*N symmetric positive definite matrix A, and -N*M vectors X and B. It is "fast-but-lightweight" version of the solver. - -Algorithm features: -* O(N^3+M*N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional time consuming features - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular - * -1 N<=0 was passed - * 1 task was solved - B - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 17.03.2015 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixsolvemfast(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_int_t i; - ae_int_t j; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - *info = 0; - - *info = 1; - if( n<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - if( !spdmatrixcholesky(a, n, isupper, _state) ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - b->ptr.pp_double[i][j] = 0.0; - } - } - *info = -3; - ae_frame_leave(_state); - return; - } - if( isupper ) - { - rmatrixlefttrsm(n, m, a, 0, 0, ae_true, ae_false, 1, b, 0, 0, _state); - rmatrixlefttrsm(n, m, a, 0, 0, ae_true, ae_false, 0, b, 0, 0, _state); - } - else - { - rmatrixlefttrsm(n, m, a, 0, 0, ae_false, ae_false, 0, b, 0, 0, _state); - rmatrixlefttrsm(n, m, a, 0, 0, ae_false, ae_false, 1, b, 0, 0, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense linear solver for A*x=b with N*N real symmetric positive definite -matrix A, N*1 vectors x and b. "Slow-but-feature-rich" version of the -solver. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* O(N^3) complexity -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just performs Cholesky - ! decomposition and calls triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, SPDMatrixSolveFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or non-SPD. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixsolve(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* b, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix bm; - ae_matrix xm; - - ae_frame_make(_state, &_frame_block); - memset(&bm, 0, sizeof(bm)); - memset(&xm, 0, sizeof(xm)); - *info = 0; - _densesolverreport_clear(rep); - ae_vector_clear(x); - ae_matrix_init(&bm, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xm, 0, 0, DT_REAL, _state, ae_true); - - if( n<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&bm, n, 1, _state); - ae_v_move(&bm.ptr.pp_double[0][0], bm.stride, &b->ptr.p_double[0], 1, ae_v_len(0,n-1)); - spdmatrixsolvem(a, n, isupper, &bm, 1, info, rep, &xm, _state); - ae_vector_set_length(x, n, _state); - ae_v_move(&x->ptr.p_double[0], 1, &xm.ptr.pp_double[0][0], xm.stride, ae_v_len(0,n-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense linear solver for A*x=b with N*N real symmetric positive definite -matrix A, N*1 vectors x and b. "Fast-but-lightweight" version of the -solver. - -Algorithm features: -* O(N^3) complexity -* matrix is represented by its upper or lower triangle -* no additional time consuming features like condition number estimation - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or non-SPD - * -1 N<=0 was passed - * 1 task was solved - B - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 17.03.2015 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixsolvefast(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* b, - ae_int_t* info, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - *info = 0; - - *info = 1; - if( n<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - if( !spdmatrixcholesky(a, n, isupper, _state) ) - { - for(i=0; i<=n-1; i++) - { - b->ptr.p_double[i] = 0.0; - } - *info = -3; - ae_frame_leave(_state); - return; - } - directdensesolvers_spdbasiccholeskysolve(a, n, isupper, b, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense solver for A*X=B with N*N symmetric positive definite matrix A given -by its Cholesky decomposition, and N*M vectors X and B. It is "slow-but- -feature-rich" version of the solver which estimates condition number of -the system. - -Algorithm features: -* automatic detection of degenerate cases -* O(M*N^2) complexity -* condition number estimation -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just calls triangular - ! solver. Amount of overhead introduced depends on M (the - ! larger - the more efficient). - ! - ! This performance penalty is insignificant when compared with - ! cost of large LU decomposition. However, if you call this - ! function many times for the same left side, this overhead - ! BECOMES significant. It also becomes significant for small- - ! scale problems (N<50). - ! - ! In such cases we strongly recommend you to use faster solver, - ! SPDMatrixCholeskySolveMFast() function. - -INPUT PARAMETERS - CHA - array[0..N-1,0..N-1], Cholesky decomposition, - SPDMatrixCholesky result - N - size of CHA - IsUpper - what half of CHA is provided - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or badly conditioned - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task was solved - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N]: - * for info>0 contains solution - * for info=-3 filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixcholeskysolvem(/* Real */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_matrix* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix emptya; - - ae_frame_make(_state, &_frame_block); - memset(&emptya, 0, sizeof(emptya)); - *info = 0; - _densesolverreport_clear(rep); - ae_matrix_clear(x); - ae_matrix_init(&emptya, 0, 0, DT_REAL, _state, ae_true); - - - /* - * prepare: check inputs, allocate space... - */ - if( n<=0||m<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - - /* - * solve - */ - directdensesolvers_spdmatrixcholeskysolveinternal(cha, n, isupper, &emptya, ae_false, b, m, info, rep, x, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense solver for A*X=B with N*N symmetric positive definite matrix A given -by its Cholesky decomposition, and N*M vectors X and B. It is "fast-but- -lightweight" version of the solver which just solves linear system, -without any additional functions. - -Algorithm features: -* O(M*N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional functionality - -INPUT PARAMETERS - CHA - array[N,N], Cholesky decomposition, - SPDMatrixCholesky result - N - size of CHA - IsUpper - what half of CHA is provided - B - array[N,M], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or badly conditioned - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task was solved - B - array[N]: - * for info>0 overwritten by solution - * for info=-3 filled by zeros - - -- ALGLIB -- - Copyright 18.03.2015 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixcholeskysolvemfast(/* Real */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - - *info = 0; - - *info = 1; - if( n<=0 ) - { - *info = -1; - return; - } - for(k=0; k<=n-1; k++) - { - if( ae_fp_eq(cha->ptr.pp_double[k][k],0.0) ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - b->ptr.pp_double[i][j] = 0.0; - } - } - *info = -3; - return; - } - } - if( isupper ) - { - rmatrixlefttrsm(n, m, cha, 0, 0, ae_true, ae_false, 1, b, 0, 0, _state); - rmatrixlefttrsm(n, m, cha, 0, 0, ae_true, ae_false, 0, b, 0, 0, _state); - } - else - { - rmatrixlefttrsm(n, m, cha, 0, 0, ae_false, ae_false, 0, b, 0, 0, _state); - rmatrixlefttrsm(n, m, cha, 0, 0, ae_false, ae_false, 1, b, 0, 0, _state); - } -} - - -/************************************************************************* -Dense solver for A*x=b with N*N symmetric positive definite matrix A given -by its Cholesky decomposition, and N*1 real vectors x and b. This is "slow- -but-feature-rich" version of the solver which, in addition to the -solution, performs condition number estimation. - -Algorithm features: -* automatic detection of degenerate cases -* O(N^2) complexity -* condition number estimation -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in 10-15x performance penalty when compared - ! with "fast" version which just calls triangular solver. - ! - ! This performance penalty is insignificant when compared with - ! cost of large LU decomposition. However, if you call this - ! function many times for the same left side, this overhead - ! BECOMES significant. It also becomes significant for small- - ! scale problems (N<50). - ! - ! In such cases we strongly recommend you to use faster solver, - ! SPDMatrixCholeskySolveFast() function. - -INPUT PARAMETERS - CHA - array[N,N], Cholesky decomposition, - SPDMatrixCholesky result - N - size of A - IsUpper - what half of CHA is provided - B - array[N], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or ill conditioned - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N]: - * for info>0 - solution - * for info=-3 - filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixcholeskysolve(/* Real */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* b, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix bm; - ae_matrix xm; - - ae_frame_make(_state, &_frame_block); - memset(&bm, 0, sizeof(bm)); - memset(&xm, 0, sizeof(xm)); - *info = 0; - _densesolverreport_clear(rep); - ae_vector_clear(x); - ae_matrix_init(&bm, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xm, 0, 0, DT_REAL, _state, ae_true); - - if( n<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&bm, n, 1, _state); - ae_v_move(&bm.ptr.pp_double[0][0], bm.stride, &b->ptr.p_double[0], 1, ae_v_len(0,n-1)); - spdmatrixcholeskysolvem(cha, n, isupper, &bm, 1, info, rep, &xm, _state); - ae_vector_set_length(x, n, _state); - ae_v_move(&x->ptr.p_double[0], 1, &xm.ptr.pp_double[0][0], xm.stride, ae_v_len(0,n-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense solver for A*x=b with N*N symmetric positive definite matrix A given -by its Cholesky decomposition, and N*1 real vectors x and b. This is "fast- -but-lightweight" version of the solver. - -Algorithm features: -* O(N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional features - -INPUT PARAMETERS - CHA - array[N,N], Cholesky decomposition, - SPDMatrixCholesky result - N - size of A - IsUpper - what half of CHA is provided - B - array[N], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or ill conditioned - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * for info>0 - overwritten by solution - * for info=-3 - filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixcholeskysolvefast(/* Real */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* b, - ae_int_t* info, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - - *info = 0; - - *info = 1; - if( n<=0 ) - { - *info = -1; - return; - } - for(k=0; k<=n-1; k++) - { - if( ae_fp_eq(cha->ptr.pp_double[k][k],0.0) ) - { - for(i=0; i<=n-1; i++) - { - b->ptr.p_double[i] = 0.0; - } - *info = -3; - return; - } - } - directdensesolvers_spdbasiccholeskysolve(cha, n, isupper, b, _state); -} - - -/************************************************************************* -Dense solver for A*X=B, with N*N Hermitian positive definite matrix A and -N*M complex matrices X and B. "Slow-but-feature-rich" version of the -solver. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* O(N^3+M*N^2) complexity -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just calls triangular - ! solver. - ! - ! This performance penalty is especially apparent when you use - ! ALGLIB parallel capabilities (condition number estimation is - ! inherently sequential). It also becomes significant for - ! small-scale problems (N<100). - ! - ! In such cases we strongly recommend you to use faster solver, - ! HPDMatrixSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - same as in RMatrixSolve. - Returns -3 for non-HPD matrices. - Rep - same as in RMatrixSolve - X - same as in RMatrixSolve - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixsolvem(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_matrix* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix da; - ae_int_t i; - ae_int_t j; - ae_int_t j1; - ae_int_t j2; - - ae_frame_make(_state, &_frame_block); - memset(&da, 0, sizeof(da)); - *info = 0; - _densesolverreport_clear(rep); - ae_matrix_clear(x); - ae_matrix_init(&da, 0, 0, DT_COMPLEX, _state, ae_true); - - - /* - * prepare: check inputs, allocate space... - */ - if( n<=0||m<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&da, n, n, _state); - - /* - * factorize matrix, solve - */ - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j1 = i; - j2 = n-1; - } - else - { - j1 = 0; - j2 = i; - } - ae_v_cmove(&da.ptr.pp_complex[i][j1], 1, &a->ptr.pp_complex[i][j1], 1, "N", ae_v_len(j1,j2)); - } - if( !hpdmatrixcholesky(&da, n, isupper, _state) ) - { - ae_matrix_set_length(x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x->ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - rep->r1 = (double)(0); - rep->rinf = (double)(0); - *info = -3; - ae_frame_leave(_state); - return; - } - *info = 1; - directdensesolvers_hpdmatrixcholeskysolveinternal(&da, n, isupper, a, ae_true, b, m, info, rep, x, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense solver for A*X=B, with N*N Hermitian positive definite matrix A and -N*M complex matrices X and B. "Fast-but-lightweight" version of the solver. - -Algorithm features: -* O(N^3+M*N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional time consuming features like condition number estimation - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or is not positive definite. - B is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - B - array[0..N-1]: - * overwritten by solution - * zeros, if problem was not solved - - -- ALGLIB -- - Copyright 17.03.2015 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixsolvemfast(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_int_t i; - ae_int_t j; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - *info = 0; - - *info = 1; - if( n<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - if( !hpdmatrixcholesky(a, n, isupper, _state) ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - b->ptr.pp_complex[i][j] = ae_complex_from_d(0.0); - } - } - *info = -3; - ae_frame_leave(_state); - return; - } - if( isupper ) - { - cmatrixlefttrsm(n, m, a, 0, 0, ae_true, ae_false, 2, b, 0, 0, _state); - cmatrixlefttrsm(n, m, a, 0, 0, ae_true, ae_false, 0, b, 0, 0, _state); - } - else - { - cmatrixlefttrsm(n, m, a, 0, 0, ae_false, ae_false, 0, b, 0, 0, _state); - cmatrixlefttrsm(n, m, a, 0, 0, ae_false, ae_false, 2, b, 0, 0, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense solver for A*x=b, with N*N Hermitian positive definite matrix A, and -N*1 complex vectors x and b. "Slow-but-feature-rich" version of the -solver. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* O(N^3) complexity -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just performs Cholesky - ! decomposition and calls triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, HPDMatrixSolveFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - same as in RMatrixSolve - Returns -3 for non-HPD matrices. - Rep - same as in RMatrixSolve - X - same as in RMatrixSolve - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixsolve(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* b, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_vector* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix bm; - ae_matrix xm; - - ae_frame_make(_state, &_frame_block); - memset(&bm, 0, sizeof(bm)); - memset(&xm, 0, sizeof(xm)); - *info = 0; - _densesolverreport_clear(rep); - ae_vector_clear(x); - ae_matrix_init(&bm, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&xm, 0, 0, DT_COMPLEX, _state, ae_true); - - if( n<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&bm, n, 1, _state); - ae_v_cmove(&bm.ptr.pp_complex[0][0], bm.stride, &b->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1)); - hpdmatrixsolvem(a, n, isupper, &bm, 1, info, rep, &xm, _state); - ae_vector_set_length(x, n, _state); - ae_v_cmove(&x->ptr.p_complex[0], 1, &xm.ptr.pp_complex[0][0], xm.stride, "N", ae_v_len(0,n-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense solver for A*x=b, with N*N Hermitian positive definite matrix A, and -N*1 complex vectors x and b. "Fast-but-lightweight" version of the -solver without additional functions. - -Algorithm features: -* O(N^3) complexity -* matrix is represented by its upper or lower triangle -* no additional time consuming functions - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or not positive definite - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task was solved - B - array[0..N-1]: - * overwritten by solution - * zeros, if A is exactly singular (diagonal of its LU - decomposition has exact zeros). - - -- ALGLIB -- - Copyright 17.03.2015 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixsolvefast(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* b, - ae_int_t* info, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - *info = 0; - - *info = 1; - if( n<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - if( !hpdmatrixcholesky(a, n, isupper, _state) ) - { - for(i=0; i<=n-1; i++) - { - b->ptr.p_complex[i] = ae_complex_from_d(0.0); - } - *info = -3; - ae_frame_leave(_state); - return; - } - directdensesolvers_hpdbasiccholeskysolve(a, n, isupper, b, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense solver for A*X=B with N*N Hermitian positive definite matrix A given -by its Cholesky decomposition and N*M complex matrices X and B. This is -"slow-but-feature-rich" version of the solver which, in addition to the -solution, estimates condition number of the system. - -Algorithm features: -* automatic detection of degenerate cases -* O(M*N^2) complexity -* condition number estimation -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just calls triangular - ! solver. Amount of overhead introduced depends on M (the - ! larger - the more efficient). - ! - ! This performance penalty is insignificant when compared with - ! cost of large Cholesky decomposition. However, if you call - ! this function many times for the same left side, this - ! overhead BECOMES significant. It also becomes significant - ! for small-scale problems (N<50). - ! - ! In such cases we strongly recommend you to use faster solver, - ! HPDMatrixCholeskySolveMFast() function. - - -INPUT PARAMETERS - CHA - array[N,N], Cholesky decomposition, - HPDMatrixCholesky result - N - size of CHA - IsUpper - what half of CHA is provided - B - array[N,M], right part - M - right part size - -OUTPUT PARAMETERS: - Info - return code: - * -3 A is singular, or VERY close to singular. - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task was solved - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N]: - * for info>0 contains solution - * for info=-3 filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixcholeskysolvem(/* Complex */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_matrix* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix emptya; - - ae_frame_make(_state, &_frame_block); - memset(&emptya, 0, sizeof(emptya)); - *info = 0; - _densesolverreport_clear(rep); - ae_matrix_clear(x); - ae_matrix_init(&emptya, 0, 0, DT_COMPLEX, _state, ae_true); - - - /* - * prepare: check inputs, allocate space... - */ - if( n<=0||m<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - - /* - * 1. scale matrix, max(|U[i,j]|) - * 2. factorize scaled matrix - * 3. solve - */ - directdensesolvers_hpdmatrixcholeskysolveinternal(cha, n, isupper, &emptya, ae_false, b, m, info, rep, x, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense solver for A*X=B with N*N Hermitian positive definite matrix A given -by its Cholesky decomposition and N*M complex matrices X and B. This is -"fast-but-lightweight" version of the solver. - -Algorithm features: -* O(M*N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional time-consuming features - -INPUT PARAMETERS - CHA - array[N,N], Cholesky decomposition, - HPDMatrixCholesky result - N - size of CHA - IsUpper - what half of CHA is provided - B - array[N,M], right part - M - right part size - -OUTPUT PARAMETERS: - Info - return code: - * -3 A is singular, or VERY close to singular. - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task was solved - B - array[N]: - * for info>0 overwritten by solution - * for info=-3 filled by zeros - - -- ALGLIB -- - Copyright 18.03.2015 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixcholeskysolvemfast(/* Complex */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - - *info = 0; - - *info = 1; - if( n<=0 ) - { - *info = -1; - return; - } - for(k=0; k<=n-1; k++) - { - if( ae_fp_eq(cha->ptr.pp_complex[k][k].x,0.0)&&ae_fp_eq(cha->ptr.pp_complex[k][k].y,0.0) ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - b->ptr.pp_complex[i][j] = ae_complex_from_d(0.0); - } - } - *info = -3; - return; - } - } - if( isupper ) - { - cmatrixlefttrsm(n, m, cha, 0, 0, ae_true, ae_false, 2, b, 0, 0, _state); - cmatrixlefttrsm(n, m, cha, 0, 0, ae_true, ae_false, 0, b, 0, 0, _state); - } - else - { - cmatrixlefttrsm(n, m, cha, 0, 0, ae_false, ae_false, 0, b, 0, 0, _state); - cmatrixlefttrsm(n, m, cha, 0, 0, ae_false, ae_false, 2, b, 0, 0, _state); - } -} - - -/************************************************************************* -Dense solver for A*x=b with N*N Hermitian positive definite matrix A given -by its Cholesky decomposition, and N*1 complex vectors x and b. This is -"slow-but-feature-rich" version of the solver which estimates condition -number of the system. - -Algorithm features: -* automatic detection of degenerate cases -* O(N^2) complexity -* condition number estimation -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in 10-15x performance penalty when compared - ! with "fast" version which just calls triangular solver. - ! - ! This performance penalty is insignificant when compared with - ! cost of large LU decomposition. However, if you call this - ! function many times for the same left side, this overhead - ! BECOMES significant. It also becomes significant for small- - ! scale problems (N<50). - ! - ! In such cases we strongly recommend you to use faster solver, - ! HPDMatrixCholeskySolveFast() function. - -INPUT PARAMETERS - CHA - array[0..N-1,0..N-1], Cholesky decomposition, - SPDMatrixCholesky result - N - size of A - IsUpper - what half of CHA is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or ill conditioned - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N]: - * for info>0 - solution - * for info=-3 - filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixcholeskysolve(/* Complex */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* b, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_vector* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix bm; - ae_matrix xm; - - ae_frame_make(_state, &_frame_block); - memset(&bm, 0, sizeof(bm)); - memset(&xm, 0, sizeof(xm)); - *info = 0; - _densesolverreport_clear(rep); - ae_vector_clear(x); - ae_matrix_init(&bm, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&xm, 0, 0, DT_COMPLEX, _state, ae_true); - - if( n<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&bm, n, 1, _state); - ae_v_cmove(&bm.ptr.pp_complex[0][0], bm.stride, &b->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1)); - hpdmatrixcholeskysolvem(cha, n, isupper, &bm, 1, info, rep, &xm, _state); - ae_vector_set_length(x, n, _state); - ae_v_cmove(&x->ptr.p_complex[0], 1, &xm.ptr.pp_complex[0][0], xm.stride, "N", ae_v_len(0,n-1)); - ae_frame_leave(_state); -} - - -/************************************************************************* -Dense solver for A*x=b with N*N Hermitian positive definite matrix A given -by its Cholesky decomposition, and N*1 complex vectors x and b. This is -"fast-but-lightweight" version of the solver. - -Algorithm features: -* O(N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional time-consuming features - -INPUT PARAMETERS - CHA - array[0..N-1,0..N-1], Cholesky decomposition, - SPDMatrixCholesky result - N - size of A - IsUpper - what half of CHA is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or ill conditioned - B is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * for info>0 - overwritten by solution - * for info=-3 - filled by zeros - - -- ALGLIB -- - Copyright 18.03.2015 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixcholeskysolvefast(/* Complex */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* b, - ae_int_t* info, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - - *info = 0; - - *info = 1; - if( n<=0 ) - { - *info = -1; - return; - } - for(k=0; k<=n-1; k++) - { - if( ae_fp_eq(cha->ptr.pp_complex[k][k].x,0.0)&&ae_fp_eq(cha->ptr.pp_complex[k][k].y,0.0) ) - { - for(i=0; i<=n-1; i++) - { - b->ptr.p_complex[i] = ae_complex_from_d(0.0); - } - *info = -3; - return; - } - } - directdensesolvers_hpdbasiccholeskysolve(cha, n, isupper, b, _state); -} - - -/************************************************************************* -Dense solver. - -This subroutine finds solution of the linear system A*X=B with non-square, -possibly degenerate A. System is solved in the least squares sense, and -general least squares solution X = X0 + CX*y which minimizes |A*X-B| is -returned. If A is non-degenerate, solution in the usual sense is returned. - -Algorithm features: -* automatic detection (and correct handling!) of degenerate cases -* iterative refinement -* O(N^3) complexity - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..NRows-1,0..NCols-1], system matrix - NRows - vertical size of A - NCols - horizontal size of A - B - array[0..NCols-1], right part - Threshold- a number in [0,1]. Singular values beyond Threshold are - considered zero. Set it to 0.0, if you don't understand - what it means, so the solver will choose good value on its - own. - -OUTPUT PARAMETERS - Info - return code: - * -4 SVD subroutine failed - * -1 if NRows<=0 or NCols<=0 or Threshold<0 was passed - * 1 if task is solved - Rep - solver report, see below for more info - X - array[0..N-1,0..M-1], it contains: - * solution of A*X=B (even for singular A) - * zeros, if SVD subroutine failed - -SOLVER REPORT - -Subroutine sets following fields of the Rep structure: -* R2 reciprocal of condition number: 1/cond(A), 2-norm. -* N = NCols -* K dim(Null(A)) -* CX array[0..N-1,0..K-1], kernel of A. - Columns of CX store such vectors that A*CX[i]=0. - - -- ALGLIB -- - Copyright 24.08.2009 by Bochkanov Sergey -*************************************************************************/ -void rmatrixsolvels(/* Real */ ae_matrix* a, - ae_int_t nrows, - ae_int_t ncols, - /* Real */ ae_vector* b, - double threshold, - ae_int_t* info, - densesolverlsreport* rep, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector sv; - ae_matrix u; - ae_matrix vt; - ae_vector rp; - ae_vector utb; - ae_vector sutb; - ae_vector tmp; - ae_vector ta; - ae_vector tx; - ae_vector buf; - ae_vector w; - ae_int_t i; - ae_int_t j; - ae_int_t nsv; - ae_int_t kernelidx; - double v; - double verr; - ae_bool svdfailed; - ae_bool zeroa; - ae_int_t rfs; - ae_int_t nrfs; - ae_bool terminatenexttime; - ae_bool smallerr; - - ae_frame_make(_state, &_frame_block); - memset(&sv, 0, sizeof(sv)); - memset(&u, 0, sizeof(u)); - memset(&vt, 0, sizeof(vt)); - memset(&rp, 0, sizeof(rp)); - memset(&utb, 0, sizeof(utb)); - memset(&sutb, 0, sizeof(sutb)); - memset(&tmp, 0, sizeof(tmp)); - memset(&ta, 0, sizeof(ta)); - memset(&tx, 0, sizeof(tx)); - memset(&buf, 0, sizeof(buf)); - memset(&w, 0, sizeof(w)); - *info = 0; - _densesolverlsreport_clear(rep); - ae_vector_clear(x); - ae_vector_init(&sv, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vt, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&utb, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sutb, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ta, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&buf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - - if( (nrows<=0||ncols<=0)||ae_fp_less(threshold,(double)(0)) ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - if( ae_fp_eq(threshold,(double)(0)) ) - { - threshold = 1000*ae_machineepsilon; - } - - /* - * Factorize A first - */ - svdfailed = !rmatrixsvd(a, nrows, ncols, 1, 2, 2, &sv, &u, &vt, _state); - zeroa = ae_fp_eq(sv.ptr.p_double[0],(double)(0)); - if( svdfailed||zeroa ) - { - if( svdfailed ) - { - *info = -4; - } - else - { - *info = 1; - } - ae_vector_set_length(x, ncols, _state); - for(i=0; i<=ncols-1; i++) - { - x->ptr.p_double[i] = (double)(0); - } - rep->n = ncols; - rep->k = ncols; - ae_matrix_set_length(&rep->cx, ncols, ncols, _state); - for(i=0; i<=ncols-1; i++) - { - for(j=0; j<=ncols-1; j++) - { - if( i==j ) - { - rep->cx.ptr.pp_double[i][j] = (double)(1); - } - else - { - rep->cx.ptr.pp_double[i][j] = (double)(0); - } - } - } - rep->r2 = (double)(0); - ae_frame_leave(_state); - return; - } - nsv = ae_minint(ncols, nrows, _state); - if( nsv==ncols ) - { - rep->r2 = sv.ptr.p_double[nsv-1]/sv.ptr.p_double[0]; - } - else - { - rep->r2 = (double)(0); - } - rep->n = ncols; - *info = 1; - - /* - * Iterative refinement of xc combined with solution: - * 1. xc = 0 - * 2. calculate r = bc-A*xc using extra-precise dot product - * 3. solve A*y = r - * 4. update x:=x+r - * 5. goto 2 - * - * This cycle is executed until one of two things happens: - * 1. maximum number of iterations reached - * 2. last iteration decreased error to the lower limit - */ - ae_vector_set_length(&utb, nsv, _state); - ae_vector_set_length(&sutb, nsv, _state); - ae_vector_set_length(x, ncols, _state); - ae_vector_set_length(&tmp, ncols, _state); - ae_vector_set_length(&ta, ncols+1, _state); - ae_vector_set_length(&tx, ncols+1, _state); - ae_vector_set_length(&buf, ncols+1, _state); - for(i=0; i<=ncols-1; i++) - { - x->ptr.p_double[i] = (double)(0); - } - kernelidx = nsv; - for(i=0; i<=nsv-1; i++) - { - if( ae_fp_less_eq(sv.ptr.p_double[i],threshold*sv.ptr.p_double[0]) ) - { - kernelidx = i; - break; - } - } - rep->k = ncols-kernelidx; - nrfs = directdensesolvers_densesolverrfsmaxv2(ncols, rep->r2, _state); - terminatenexttime = ae_false; - ae_vector_set_length(&rp, nrows, _state); - for(rfs=0; rfs<=nrfs; rfs++) - { - if( terminatenexttime ) - { - break; - } - - /* - * calculate right part - */ - if( rfs==0 ) - { - ae_v_move(&rp.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,nrows-1)); - } - else - { - smallerr = ae_true; - for(i=0; i<=nrows-1; i++) - { - ae_v_move(&ta.ptr.p_double[0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,ncols-1)); - ta.ptr.p_double[ncols] = (double)(-1); - ae_v_move(&tx.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,ncols-1)); - tx.ptr.p_double[ncols] = b->ptr.p_double[i]; - xdot(&ta, &tx, ncols+1, &buf, &v, &verr, _state); - rp.ptr.p_double[i] = -v; - smallerr = smallerr&&ae_fp_less(ae_fabs(v, _state),4*verr); - } - if( smallerr ) - { - terminatenexttime = ae_true; - } - } - - /* - * solve A*dx = rp - */ - for(i=0; i<=ncols-1; i++) - { - tmp.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=nsv-1; i++) - { - utb.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=nrows-1; i++) - { - v = rp.ptr.p_double[i]; - ae_v_addd(&utb.ptr.p_double[0], 1, &u.ptr.pp_double[i][0], 1, ae_v_len(0,nsv-1), v); - } - for(i=0; i<=nsv-1; i++) - { - if( iptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,ncols-1)); - } - - /* - * fill CX - */ - if( rep->k>0 ) - { - ae_matrix_set_length(&rep->cx, ncols, rep->k, _state); - for(i=0; i<=rep->k-1; i++) - { - ae_v_move(&rep->cx.ptr.pp_double[0][i], rep->cx.stride, &vt.ptr.pp_double[kernelidx+i][0], 1, ae_v_len(0,ncols-1)); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal LU solver - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -static void directdensesolvers_rmatrixlusolveinternal(/* Real */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_bool havea, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_matrix* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t rfs; - ae_int_t nrfs; - ae_vector xc; - ae_vector y; - ae_vector bc; - ae_vector xa; - ae_vector xb; - ae_vector tx; - double v; - double verr; - double mxb; - ae_bool smallerr; - ae_bool terminatenexttime; - - ae_frame_make(_state, &_frame_block); - memset(&xc, 0, sizeof(xc)); - memset(&y, 0, sizeof(y)); - memset(&bc, 0, sizeof(bc)); - memset(&xa, 0, sizeof(xa)); - memset(&xb, 0, sizeof(xb)); - memset(&tx, 0, sizeof(tx)); - *info = 0; - _densesolverreport_clear(rep); - ae_matrix_clear(x); - ae_vector_init(&xc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xa, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xb, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tx, 0, DT_REAL, _state, ae_true); - - - /* - * prepare: check inputs, allocate space... - */ - if( n<=0||m<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - if( p->ptr.p_int[i]>n-1||p->ptr.p_int[i]r1 = rmatrixlurcond1(lua, n, _state); - rep->rinf = rmatrixlurcondinf(lua, n, _state); - if( ae_fp_less(rep->r1,rcondthreshold(_state))||ae_fp_less(rep->rinf,rcondthreshold(_state)) ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x->ptr.pp_double[i][j] = (double)(0); - } - } - rep->r1 = (double)(0); - rep->rinf = (double)(0); - *info = -3; - ae_frame_leave(_state); - return; - } - *info = 1; - - /* - * First stage of solution: rough solution with TRSM() - */ - mxb = 0.0; - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - v = b->ptr.pp_double[i][j]; - mxb = ae_maxreal(mxb, ae_fabs(v, _state), _state); - x->ptr.pp_double[i][j] = v; - } - } - for(i=0; i<=n-1; i++) - { - if( p->ptr.p_int[i]!=i ) - { - for(j=0; j<=m-1; j++) - { - v = x->ptr.pp_double[i][j]; - x->ptr.pp_double[i][j] = x->ptr.pp_double[p->ptr.p_int[i]][j]; - x->ptr.pp_double[p->ptr.p_int[i]][j] = v; - } - } - } - rmatrixlefttrsm(n, m, lua, 0, 0, ae_false, ae_true, 0, x, 0, 0, _state); - rmatrixlefttrsm(n, m, lua, 0, 0, ae_true, ae_false, 0, x, 0, 0, _state); - - /* - * Second stage: iterative refinement - */ - if( havea ) - { - for(k=0; k<=m-1; k++) - { - nrfs = directdensesolvers_densesolverrfsmax(n, rep->r1, rep->rinf, _state); - terminatenexttime = ae_false; - for(rfs=0; rfs<=nrfs-1; rfs++) - { - if( terminatenexttime ) - { - break; - } - - /* - * generate right part - */ - smallerr = ae_true; - ae_v_move(&xb.ptr.p_double[0], 1, &x->ptr.pp_double[0][k], x->stride, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - ae_v_move(&xa.ptr.p_double[0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - xa.ptr.p_double[n] = (double)(-1); - xb.ptr.p_double[n] = b->ptr.pp_double[i][k]; - xdot(&xa, &xb, n+1, &tx, &v, &verr, _state); - y.ptr.p_double[i] = -v; - smallerr = smallerr&&ae_fp_less(ae_fabs(v, _state),4*verr); - } - if( smallerr ) - { - terminatenexttime = ae_true; - } - - /* - * solve and update - */ - directdensesolvers_rbasiclusolve(lua, p, n, &y, _state); - ae_v_add(&x->ptr.pp_double[0][k], x->stride, &y.ptr.p_double[0], 1, ae_v_len(0,n-1)); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal Cholesky solver - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -static void directdensesolvers_spdmatrixcholeskysolveinternal(/* Real */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_matrix* a, - ae_bool havea, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_matrix* x, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - *info = 0; - _densesolverreport_clear(rep); - ae_matrix_clear(x); - - - /* - * prepare: check inputs, allocate space... - */ - if( n<=0||m<=0 ) - { - *info = -1; - return; - } - ae_matrix_set_length(x, n, m, _state); - - /* - * estimate condition number, test for near singularity - */ - rep->r1 = spdmatrixcholeskyrcond(cha, n, isupper, _state); - rep->rinf = rep->r1; - if( ae_fp_less(rep->r1,rcondthreshold(_state)) ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x->ptr.pp_double[i][j] = (double)(0); - } - } - rep->r1 = (double)(0); - rep->rinf = (double)(0); - *info = -3; - return; - } - *info = 1; - - /* - * Solve with TRSM() - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x->ptr.pp_double[i][j] = b->ptr.pp_double[i][j]; - } - } - if( isupper ) - { - rmatrixlefttrsm(n, m, cha, 0, 0, ae_true, ae_false, 1, x, 0, 0, _state); - rmatrixlefttrsm(n, m, cha, 0, 0, ae_true, ae_false, 0, x, 0, 0, _state); - } - else - { - rmatrixlefttrsm(n, m, cha, 0, 0, ae_false, ae_false, 0, x, 0, 0, _state); - rmatrixlefttrsm(n, m, cha, 0, 0, ae_false, ae_false, 1, x, 0, 0, _state); - } -} - - -/************************************************************************* -Internal LU solver - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -static void directdensesolvers_cmatrixlusolveinternal(/* Complex */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_bool havea, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_matrix* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t rfs; - ae_int_t nrfs; - ae_vector xc; - ae_vector y; - ae_vector bc; - ae_vector xa; - ae_vector xb; - ae_vector tx; - ae_vector tmpbuf; - ae_complex v; - double verr; - ae_bool smallerr; - ae_bool terminatenexttime; - - ae_frame_make(_state, &_frame_block); - memset(&xc, 0, sizeof(xc)); - memset(&y, 0, sizeof(y)); - memset(&bc, 0, sizeof(bc)); - memset(&xa, 0, sizeof(xa)); - memset(&xb, 0, sizeof(xb)); - memset(&tx, 0, sizeof(tx)); - memset(&tmpbuf, 0, sizeof(tmpbuf)); - *info = 0; - _densesolverreport_clear(rep); - ae_matrix_clear(x); - ae_vector_init(&xc, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&y, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&bc, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&xa, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&xb, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&tx, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&tmpbuf, 0, DT_REAL, _state, ae_true); - - - /* - * prepare: check inputs, allocate space... - */ - if( n<=0||m<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - if( p->ptr.p_int[i]>n-1||p->ptr.p_int[i]r1 = cmatrixlurcond1(lua, n, _state); - rep->rinf = cmatrixlurcondinf(lua, n, _state); - if( ae_fp_less(rep->r1,rcondthreshold(_state))||ae_fp_less(rep->rinf,rcondthreshold(_state)) ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x->ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - rep->r1 = (double)(0); - rep->rinf = (double)(0); - *info = -3; - ae_frame_leave(_state); - return; - } - *info = 1; - - /* - * First phase: solve with TRSM() - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x->ptr.pp_complex[i][j] = b->ptr.pp_complex[i][j]; - } - } - for(i=0; i<=n-1; i++) - { - if( p->ptr.p_int[i]!=i ) - { - for(j=0; j<=m-1; j++) - { - v = x->ptr.pp_complex[i][j]; - x->ptr.pp_complex[i][j] = x->ptr.pp_complex[p->ptr.p_int[i]][j]; - x->ptr.pp_complex[p->ptr.p_int[i]][j] = v; - } - } - } - cmatrixlefttrsm(n, m, lua, 0, 0, ae_false, ae_true, 0, x, 0, 0, _state); - cmatrixlefttrsm(n, m, lua, 0, 0, ae_true, ae_false, 0, x, 0, 0, _state); - - /* - * solve - */ - for(k=0; k<=m-1; k++) - { - ae_v_cmove(&bc.ptr.p_complex[0], 1, &b->ptr.pp_complex[0][k], b->stride, "N", ae_v_len(0,n-1)); - ae_v_cmove(&xc.ptr.p_complex[0], 1, &x->ptr.pp_complex[0][k], x->stride, "N", ae_v_len(0,n-1)); - - /* - * Iterative refinement of xc: - * * calculate r = bc-A*xc using extra-precise dot product - * * solve A*y = r - * * update x:=x+r - * - * This cycle is executed until one of two things happens: - * 1. maximum number of iterations reached - * 2. last iteration decreased error to the lower limit - */ - if( havea ) - { - nrfs = directdensesolvers_densesolverrfsmax(n, rep->r1, rep->rinf, _state); - terminatenexttime = ae_false; - for(rfs=0; rfs<=nrfs-1; rfs++) - { - if( terminatenexttime ) - { - break; - } - - /* - * generate right part - */ - smallerr = ae_true; - ae_v_cmove(&xb.ptr.p_complex[0], 1, &xc.ptr.p_complex[0], 1, "N", ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - ae_v_cmove(&xa.ptr.p_complex[0], 1, &a->ptr.pp_complex[i][0], 1, "N", ae_v_len(0,n-1)); - xa.ptr.p_complex[n] = ae_complex_from_i(-1); - xb.ptr.p_complex[n] = bc.ptr.p_complex[i]; - xcdot(&xa, &xb, n+1, &tmpbuf, &v, &verr, _state); - y.ptr.p_complex[i] = ae_c_neg(v); - smallerr = smallerr&&ae_fp_less(ae_c_abs(v, _state),4*verr); - } - if( smallerr ) - { - terminatenexttime = ae_true; - } - - /* - * solve and update - */ - directdensesolvers_cbasiclusolve(lua, p, n, &y, _state); - ae_v_cadd(&xc.ptr.p_complex[0], 1, &y.ptr.p_complex[0], 1, "N", ae_v_len(0,n-1)); - } - } - - /* - * Store xc. - * Post-scale result. - */ - ae_v_cmove(&x->ptr.pp_complex[0][k], x->stride, &xc.ptr.p_complex[0], 1, "N", ae_v_len(0,n-1)); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal Cholesky solver - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -static void directdensesolvers_hpdmatrixcholeskysolveinternal(/* Complex */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_matrix* a, - ae_bool havea, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_matrix* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_vector xc; - ae_vector y; - ae_vector bc; - ae_vector xa; - ae_vector xb; - ae_vector tx; - - ae_frame_make(_state, &_frame_block); - memset(&xc, 0, sizeof(xc)); - memset(&y, 0, sizeof(y)); - memset(&bc, 0, sizeof(bc)); - memset(&xa, 0, sizeof(xa)); - memset(&xb, 0, sizeof(xb)); - memset(&tx, 0, sizeof(tx)); - *info = 0; - _densesolverreport_clear(rep); - ae_matrix_clear(x); - ae_vector_init(&xc, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&y, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&bc, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&xa, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&xb, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&tx, 0, DT_COMPLEX, _state, ae_true); - - - /* - * prepare: check inputs, allocate space... - */ - if( n<=0||m<=0 ) - { - *info = -1; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(x, n, m, _state); - ae_vector_set_length(&y, n, _state); - ae_vector_set_length(&xc, n, _state); - ae_vector_set_length(&bc, n, _state); - ae_vector_set_length(&tx, n+1, _state); - ae_vector_set_length(&xa, n+1, _state); - ae_vector_set_length(&xb, n+1, _state); - - /* - * estimate condition number, test for near singularity - */ - rep->r1 = hpdmatrixcholeskyrcond(cha, n, isupper, _state); - rep->rinf = rep->r1; - if( ae_fp_less(rep->r1,rcondthreshold(_state)) ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x->ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - rep->r1 = (double)(0); - rep->rinf = (double)(0); - *info = -3; - ae_frame_leave(_state); - return; - } - *info = 1; - - /* - * solve - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x->ptr.pp_complex[i][j] = b->ptr.pp_complex[i][j]; - } - } - if( isupper ) - { - cmatrixlefttrsm(n, m, cha, 0, 0, ae_true, ae_false, 2, x, 0, 0, _state); - cmatrixlefttrsm(n, m, cha, 0, 0, ae_true, ae_false, 0, x, 0, 0, _state); - } - else - { - cmatrixlefttrsm(n, m, cha, 0, 0, ae_false, ae_false, 0, x, 0, 0, _state); - cmatrixlefttrsm(n, m, cha, 0, 0, ae_false, ae_false, 2, x, 0, 0, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal subroutine. -Returns maximum count of RFS iterations as function of: -1. machine epsilon -2. task size. -3. condition number - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -static ae_int_t directdensesolvers_densesolverrfsmax(ae_int_t n, - double r1, - double rinf, - ae_state *_state) -{ - ae_int_t result; - - - result = 5; - return result; -} - - -/************************************************************************* -Internal subroutine. -Returns maximum count of RFS iterations as function of: -1. machine epsilon -2. task size. -3. norm-2 condition number - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -static ae_int_t directdensesolvers_densesolverrfsmaxv2(ae_int_t n, - double r2, - ae_state *_state) -{ - ae_int_t result; - - - result = directdensesolvers_densesolverrfsmax(n, (double)(0), (double)(0), _state); - return result; -} - - -/************************************************************************* -Basic LU solver for PLU*x = y. - -This subroutine assumes that: -* A=PLU is well-conditioned, so no zero divisions or overflow may occur - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -static void directdensesolvers_rbasiclusolve(/* Real */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Real */ ae_vector* xb, - ae_state *_state) -{ - ae_int_t i; - double v; - - - for(i=0; i<=n-1; i++) - { - if( p->ptr.p_int[i]!=i ) - { - v = xb->ptr.p_double[i]; - xb->ptr.p_double[i] = xb->ptr.p_double[p->ptr.p_int[i]]; - xb->ptr.p_double[p->ptr.p_int[i]] = v; - } - } - for(i=1; i<=n-1; i++) - { - v = ae_v_dotproduct(&lua->ptr.pp_double[i][0], 1, &xb->ptr.p_double[0], 1, ae_v_len(0,i-1)); - xb->ptr.p_double[i] = xb->ptr.p_double[i]-v; - } - xb->ptr.p_double[n-1] = xb->ptr.p_double[n-1]/lua->ptr.pp_double[n-1][n-1]; - for(i=n-2; i>=0; i--) - { - v = ae_v_dotproduct(&lua->ptr.pp_double[i][i+1], 1, &xb->ptr.p_double[i+1], 1, ae_v_len(i+1,n-1)); - xb->ptr.p_double[i] = (xb->ptr.p_double[i]-v)/lua->ptr.pp_double[i][i]; - } -} - - -/************************************************************************* -Basic Cholesky solver for ScaleA*Cholesky(A)'*x = y. - -This subroutine assumes that: -* A*ScaleA is well scaled -* A is well-conditioned, so no zero divisions or overflow may occur - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -static void directdensesolvers_spdbasiccholeskysolve(/* Real */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* xb, - ae_state *_state) -{ - ae_int_t i; - double v; - - - - /* - * A = L*L' or A=U'*U - */ - if( isupper ) - { - - /* - * Solve U'*y=b first. - */ - for(i=0; i<=n-1; i++) - { - xb->ptr.p_double[i] = xb->ptr.p_double[i]/cha->ptr.pp_double[i][i]; - if( iptr.p_double[i]; - ae_v_subd(&xb->ptr.p_double[i+1], 1, &cha->ptr.pp_double[i][i+1], 1, ae_v_len(i+1,n-1), v); - } - } - - /* - * Solve U*x=y then. - */ - for(i=n-1; i>=0; i--) - { - if( iptr.pp_double[i][i+1], 1, &xb->ptr.p_double[i+1], 1, ae_v_len(i+1,n-1)); - xb->ptr.p_double[i] = xb->ptr.p_double[i]-v; - } - xb->ptr.p_double[i] = xb->ptr.p_double[i]/cha->ptr.pp_double[i][i]; - } - } - else - { - - /* - * Solve L*y=b first - */ - for(i=0; i<=n-1; i++) - { - if( i>0 ) - { - v = ae_v_dotproduct(&cha->ptr.pp_double[i][0], 1, &xb->ptr.p_double[0], 1, ae_v_len(0,i-1)); - xb->ptr.p_double[i] = xb->ptr.p_double[i]-v; - } - xb->ptr.p_double[i] = xb->ptr.p_double[i]/cha->ptr.pp_double[i][i]; - } - - /* - * Solve L'*x=y then. - */ - for(i=n-1; i>=0; i--) - { - xb->ptr.p_double[i] = xb->ptr.p_double[i]/cha->ptr.pp_double[i][i]; - if( i>0 ) - { - v = xb->ptr.p_double[i]; - ae_v_subd(&xb->ptr.p_double[0], 1, &cha->ptr.pp_double[i][0], 1, ae_v_len(0,i-1), v); - } - } - } -} - - -/************************************************************************* -Basic LU solver for ScaleA*PLU*x = y. - -This subroutine assumes that: -* L is well-scaled, and it is U which needs scaling by ScaleA. -* A=PLU is well-conditioned, so no zero divisions or overflow may occur - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -static void directdensesolvers_cbasiclusolve(/* Complex */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Complex */ ae_vector* xb, - ae_state *_state) -{ - ae_int_t i; - ae_complex v; - - - for(i=0; i<=n-1; i++) - { - if( p->ptr.p_int[i]!=i ) - { - v = xb->ptr.p_complex[i]; - xb->ptr.p_complex[i] = xb->ptr.p_complex[p->ptr.p_int[i]]; - xb->ptr.p_complex[p->ptr.p_int[i]] = v; - } - } - for(i=1; i<=n-1; i++) - { - v = ae_v_cdotproduct(&lua->ptr.pp_complex[i][0], 1, "N", &xb->ptr.p_complex[0], 1, "N", ae_v_len(0,i-1)); - xb->ptr.p_complex[i] = ae_c_sub(xb->ptr.p_complex[i],v); - } - xb->ptr.p_complex[n-1] = ae_c_div(xb->ptr.p_complex[n-1],lua->ptr.pp_complex[n-1][n-1]); - for(i=n-2; i>=0; i--) - { - v = ae_v_cdotproduct(&lua->ptr.pp_complex[i][i+1], 1, "N", &xb->ptr.p_complex[i+1], 1, "N", ae_v_len(i+1,n-1)); - xb->ptr.p_complex[i] = ae_c_div(ae_c_sub(xb->ptr.p_complex[i],v),lua->ptr.pp_complex[i][i]); - } -} - - -/************************************************************************* -Basic Cholesky solver for ScaleA*Cholesky(A)'*x = y. - -This subroutine assumes that: -* A*ScaleA is well scaled -* A is well-conditioned, so no zero divisions or overflow may occur - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -static void directdensesolvers_hpdbasiccholeskysolve(/* Complex */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* xb, - ae_state *_state) -{ - ae_int_t i; - ae_complex v; - - - - /* - * A = L*L' or A=U'*U - */ - if( isupper ) - { - - /* - * Solve U'*y=b first. - */ - for(i=0; i<=n-1; i++) - { - xb->ptr.p_complex[i] = ae_c_div(xb->ptr.p_complex[i],ae_c_conj(cha->ptr.pp_complex[i][i], _state)); - if( iptr.p_complex[i]; - ae_v_csubc(&xb->ptr.p_complex[i+1], 1, &cha->ptr.pp_complex[i][i+1], 1, "Conj", ae_v_len(i+1,n-1), v); - } - } - - /* - * Solve U*x=y then. - */ - for(i=n-1; i>=0; i--) - { - if( iptr.pp_complex[i][i+1], 1, "N", &xb->ptr.p_complex[i+1], 1, "N", ae_v_len(i+1,n-1)); - xb->ptr.p_complex[i] = ae_c_sub(xb->ptr.p_complex[i],v); - } - xb->ptr.p_complex[i] = ae_c_div(xb->ptr.p_complex[i],cha->ptr.pp_complex[i][i]); - } - } - else - { - - /* - * Solve L*y=b first - */ - for(i=0; i<=n-1; i++) - { - if( i>0 ) - { - v = ae_v_cdotproduct(&cha->ptr.pp_complex[i][0], 1, "N", &xb->ptr.p_complex[0], 1, "N", ae_v_len(0,i-1)); - xb->ptr.p_complex[i] = ae_c_sub(xb->ptr.p_complex[i],v); - } - xb->ptr.p_complex[i] = ae_c_div(xb->ptr.p_complex[i],cha->ptr.pp_complex[i][i]); - } - - /* - * Solve L'*x=y then. - */ - for(i=n-1; i>=0; i--) - { - xb->ptr.p_complex[i] = ae_c_div(xb->ptr.p_complex[i],ae_c_conj(cha->ptr.pp_complex[i][i], _state)); - if( i>0 ) - { - v = xb->ptr.p_complex[i]; - ae_v_csubc(&xb->ptr.p_complex[0], 1, &cha->ptr.pp_complex[i][0], 1, "Conj", ae_v_len(0,i-1), v); - } - } - } -} - - -void _densesolverreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - densesolverreport *p = (densesolverreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _densesolverreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - densesolverreport *dst = (densesolverreport*)_dst; - densesolverreport *src = (densesolverreport*)_src; - dst->r1 = src->r1; - dst->rinf = src->rinf; -} - - -void _densesolverreport_clear(void* _p) -{ - densesolverreport *p = (densesolverreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _densesolverreport_destroy(void* _p) -{ - densesolverreport *p = (densesolverreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _densesolverlsreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - densesolverlsreport *p = (densesolverlsreport*)_p; - ae_touch_ptr((void*)p); - ae_matrix_init(&p->cx, 0, 0, DT_REAL, _state, make_automatic); -} - - -void _densesolverlsreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - densesolverlsreport *dst = (densesolverlsreport*)_dst; - densesolverlsreport *src = (densesolverlsreport*)_src; - dst->r2 = src->r2; - ae_matrix_init_copy(&dst->cx, &src->cx, _state, make_automatic); - dst->n = src->n; - dst->k = src->k; -} - - -void _densesolverlsreport_clear(void* _p) -{ - densesolverlsreport *p = (densesolverlsreport*)_p; - ae_touch_ptr((void*)p); - ae_matrix_clear(&p->cx); -} - - -void _densesolverlsreport_destroy(void* _p) -{ - densesolverlsreport *p = (densesolverlsreport*)_p; - ae_touch_ptr((void*)p); - ae_matrix_destroy(&p->cx); -} - - -#endif -#if defined(AE_COMPILE_LINLSQR) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function initializes linear LSQR Solver. This solver is used to solve -non-symmetric (and, possibly, non-square) problems. Least squares solution -is returned for non-compatible systems. - -USAGE: -1. User initializes algorithm state with LinLSQRCreate() call -2. User tunes solver parameters with LinLSQRSetCond() and other functions -3. User calls LinLSQRSolveSparse() function which takes algorithm state - and SparseMatrix object. -4. User calls LinLSQRResults() to get solution -5. Optionally, user may call LinLSQRSolveSparse() again to solve another - problem with different matrix and/or right part without reinitializing - LinLSQRState structure. - -INPUT PARAMETERS: - M - number of rows in A - N - number of variables, N>0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: see also linlsqrcreatebuf() for version which reuses previously - allocated place as much as possible. - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -void linlsqrcreate(ae_int_t m, - ae_int_t n, - linlsqrstate* state, - ae_state *_state) -{ - - _linlsqrstate_clear(state); - - ae_assert(m>0, "LinLSQRCreate: M<=0", _state); - ae_assert(n>0, "LinLSQRCreate: N<=0", _state); - linlsqrcreatebuf(m, n, state, _state); -} - - -/************************************************************************* -This function initializes linear LSQR Solver. It provides exactly same -functionality as linlsqrcreate(), but reuses previously allocated space -as much as possible. - -INPUT PARAMETERS: - M - number of rows in A - N - number of variables, N>0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 14.11.2018 by Bochkanov Sergey -*************************************************************************/ -void linlsqrcreatebuf(ae_int_t m, - ae_int_t n, - linlsqrstate* state, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(m>0, "LinLSQRCreateBuf: M<=0", _state); - ae_assert(n>0, "LinLSQRCreateBuf: N<=0", _state); - state->m = m; - state->n = n; - state->prectype = 0; - state->epsa = linlsqr_atol; - state->epsb = linlsqr_btol; - state->epsc = 1/ae_sqrt(ae_machineepsilon, _state); - state->maxits = 0; - state->lambdai = (double)(0); - state->xrep = ae_false; - state->running = ae_false; - state->repiterationscount = 0; - - /* - * * allocate arrays - * * set RX to NAN (just for the case user calls Results() without - * calling SolveSparse() - * * set B to zero - */ - normestimatorcreate(m, n, 2, 2, &state->nes, _state); - ae_vector_set_length(&state->rx, state->n, _state); - ae_vector_set_length(&state->ui, state->m+state->n, _state); - ae_vector_set_length(&state->uip1, state->m+state->n, _state); - ae_vector_set_length(&state->vip1, state->n, _state); - ae_vector_set_length(&state->vi, state->n, _state); - ae_vector_set_length(&state->omegai, state->n, _state); - ae_vector_set_length(&state->omegaip1, state->n, _state); - ae_vector_set_length(&state->d, state->n, _state); - ae_vector_set_length(&state->x, state->m+state->n, _state); - ae_vector_set_length(&state->mv, state->m+state->n, _state); - ae_vector_set_length(&state->mtv, state->n, _state); - ae_vector_set_length(&state->b, state->m, _state); - for(i=0; i<=n-1; i++) - { - state->rx.ptr.p_double[i] = _state->v_nan; - } - for(i=0; i<=m-1; i++) - { - state->b.ptr.p_double[i] = (double)(0); - } - ae_vector_set_length(&state->rstate.ia, 1+1, _state); - ae_vector_set_length(&state->rstate.ra, 0+1, _state); - state->rstate.stage = -1; -} - - -/************************************************************************* -This function sets right part. By default, right part is zero. - -INPUT PARAMETERS: - B - right part, array[N]. - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -void linlsqrsetb(linlsqrstate* state, - /* Real */ ae_vector* b, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(!state->running, "LinLSQRSetB: you can not change B when LinLSQRIteration is running", _state); - ae_assert(state->m<=b->cnt, "LinLSQRSetB: Length(B)m, _state), "LinLSQRSetB: B contains infinite or NaN values", _state); - state->bnorm2 = (double)(0); - for(i=0; i<=state->m-1; i++) - { - state->b.ptr.p_double[i] = b->ptr.p_double[i]; - state->bnorm2 = state->bnorm2+b->ptr.p_double[i]*b->ptr.p_double[i]; - } -} - - -/************************************************************************* -This function changes preconditioning settings of LinLSQQSolveSparse() -function. By default, SolveSparse() uses diagonal preconditioner, but if -you want to use solver without preconditioning, you can call this function -which forces solver to use unit matrix for preconditioning. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 19.11.2012 by Bochkanov Sergey -*************************************************************************/ -void linlsqrsetprecunit(linlsqrstate* state, ae_state *_state) -{ - - - ae_assert(!state->running, "LinLSQRSetPrecUnit: you can not change preconditioner, because function LinLSQRIteration is running!", _state); - state->prectype = -1; -} - - -/************************************************************************* -This function changes preconditioning settings of LinCGSolveSparse() -function. LinCGSolveSparse() will use diagonal of the system matrix as -preconditioner. This preconditioning mode is active by default. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 19.11.2012 by Bochkanov Sergey -*************************************************************************/ -void linlsqrsetprecdiag(linlsqrstate* state, ae_state *_state) -{ - - - ae_assert(!state->running, "LinLSQRSetPrecDiag: you can not change preconditioner, because function LinCGIteration is running!", _state); - state->prectype = 0; -} - - -/************************************************************************* -This function sets optional Tikhonov regularization coefficient. -It is zero by default. - -INPUT PARAMETERS: - LambdaI - regularization factor, LambdaI>=0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -void linlsqrsetlambdai(linlsqrstate* state, - double lambdai, - ae_state *_state) -{ - - - ae_assert(!state->running, "LinLSQRSetLambdaI: you can not set LambdaI, because function LinLSQRIteration is running", _state); - ae_assert(ae_isfinite(lambdai, _state)&&ae_fp_greater_eq(lambdai,(double)(0)), "LinLSQRSetLambdaI: LambdaI is infinite or NaN", _state); - state->lambdai = lambdai; -} - - -/************************************************************************* - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -ae_bool linlsqriteration(linlsqrstate* state, ae_state *_state) -{ - ae_int_t summn; - double bnorm; - ae_int_t i; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - summn = state->rstate.ia.ptr.p_int[0]; - i = state->rstate.ia.ptr.p_int[1]; - bnorm = state->rstate.ra.ptr.p_double[0]; - } - else - { - summn = 359; - i = -58; - bnorm = -919; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - if( state->rstate.stage==1 ) - { - goto lbl_1; - } - if( state->rstate.stage==2 ) - { - goto lbl_2; - } - if( state->rstate.stage==3 ) - { - goto lbl_3; - } - if( state->rstate.stage==4 ) - { - goto lbl_4; - } - if( state->rstate.stage==5 ) - { - goto lbl_5; - } - if( state->rstate.stage==6 ) - { - goto lbl_6; - } - - /* - * Routine body - */ - ae_assert(state->b.cnt>0, "LinLSQRIteration: using non-allocated array B", _state); - summn = state->m+state->n; - bnorm = ae_sqrt(state->bnorm2, _state); - state->userterminationneeded = ae_false; - state->running = ae_true; - state->repnmv = 0; - state->repiterationscount = 0; - state->r2 = state->bnorm2; - linlsqr_clearrfields(state, _state); - - /* - *estimate for ANorm - */ - normestimatorrestart(&state->nes, _state); -lbl_7: - if( !normestimatoriteration(&state->nes, _state) ) - { - goto lbl_8; - } - if( !state->nes.needmv ) - { - goto lbl_9; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->nes.x.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - state->repnmv = state->repnmv+1; - linlsqr_clearrfields(state, _state); - state->needmv = ae_true; - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - state->needmv = ae_false; - ae_v_move(&state->nes.mv.ptr.p_double[0], 1, &state->mv.ptr.p_double[0], 1, ae_v_len(0,state->m-1)); - goto lbl_7; -lbl_9: - if( !state->nes.needmtv ) - { - goto lbl_11; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->nes.x.ptr.p_double[0], 1, ae_v_len(0,state->m-1)); - - /* - *matrix-vector multiplication - */ - state->repnmv = state->repnmv+1; - linlsqr_clearrfields(state, _state); - state->needmtv = ae_true; - state->rstate.stage = 1; - goto lbl_rcomm; -lbl_1: - state->needmtv = ae_false; - ae_v_move(&state->nes.mtv.ptr.p_double[0], 1, &state->mtv.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - goto lbl_7; -lbl_11: - goto lbl_7; -lbl_8: - normestimatorresults(&state->nes, &state->anorm, _state); - - /* - *initialize .RX by zeros - */ - for(i=0; i<=state->n-1; i++) - { - state->rx.ptr.p_double[i] = (double)(0); - } - - /* - *output first report - */ - if( !state->xrep ) - { - goto lbl_13; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->rx.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - linlsqr_clearrfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 2; - goto lbl_rcomm; -lbl_2: - state->xupdated = ae_false; -lbl_13: - - /* - * LSQR, Step 0. - * - * Algorithm outline corresponds to one which was described at p.50 of - * "LSQR - an algorithm for sparse linear equations and sparse least - * squares" by C.Paige and M.Saunders with one small addition - we - * explicitly extend system matrix by additional N lines in order - * to handle non-zero lambda, i.e. original A is replaced by - * [ A ] - * A_mod = [ ] - * [ lambda*I ]. - * - * Step 0: - * x[0] = 0 - * beta[1]*u[1] = b - * alpha[1]*v[1] = A_mod'*u[1] - * w[1] = v[1] - * phiBar[1] = beta[1] - * rhoBar[1] = alpha[1] - * d[0] = 0 - * - * NOTE: - * There are three criteria for stopping: - * (S0) maximum number of iterations - * (S1) ||Rk||<=EpsB*||B||; - * (S2) ||A^T*Rk||/(||A||*||Rk||)<=EpsA. - * It is very important that S2 always checked AFTER S1. It is necessary - * to avoid division by zero when Rk=0. - */ - state->betai = bnorm; - if( ae_fp_eq(state->betai,(double)(0)) ) - { - - /* - * Zero right part - */ - state->running = ae_false; - state->repterminationtype = 1; - result = ae_false; - return result; - } - for(i=0; i<=summn-1; i++) - { - if( im ) - { - state->ui.ptr.p_double[i] = state->b.ptr.p_double[i]/state->betai; - } - else - { - state->ui.ptr.p_double[i] = (double)(0); - } - state->x.ptr.p_double[i] = state->ui.ptr.p_double[i]; - } - state->repnmv = state->repnmv+1; - linlsqr_clearrfields(state, _state); - state->needmtv = ae_true; - state->rstate.stage = 3; - goto lbl_rcomm; -lbl_3: - state->needmtv = ae_false; - for(i=0; i<=state->n-1; i++) - { - state->mtv.ptr.p_double[i] = state->mtv.ptr.p_double[i]+state->lambdai*state->ui.ptr.p_double[state->m+i]; - } - state->alphai = (double)(0); - for(i=0; i<=state->n-1; i++) - { - state->alphai = state->alphai+state->mtv.ptr.p_double[i]*state->mtv.ptr.p_double[i]; - } - state->alphai = ae_sqrt(state->alphai, _state); - if( ae_fp_eq(state->alphai,(double)(0)) ) - { - - /* - * Orthogonality stopping criterion is met - */ - state->running = ae_false; - state->repterminationtype = 4; - result = ae_false; - return result; - } - for(i=0; i<=state->n-1; i++) - { - state->vi.ptr.p_double[i] = state->mtv.ptr.p_double[i]/state->alphai; - state->omegai.ptr.p_double[i] = state->vi.ptr.p_double[i]; - } - state->phibari = state->betai; - state->rhobari = state->alphai; - for(i=0; i<=state->n-1; i++) - { - state->d.ptr.p_double[i] = (double)(0); - } - state->dnorm = (double)(0); - - /* - * Steps I=1, 2, ... - */ -lbl_15: - if( ae_false ) - { - goto lbl_16; - } - - /* - * At I-th step State.RepIterationsCount=I. - */ - state->repiterationscount = state->repiterationscount+1; - - /* - * Bidiagonalization part: - * beta[i+1]*u[i+1] = A_mod*v[i]-alpha[i]*u[i] - * alpha[i+1]*v[i+1] = A_mod'*u[i+1] - beta[i+1]*v[i] - * - * NOTE: beta[i+1]=0 or alpha[i+1]=0 will lead to successful termination - * in the end of the current iteration. In this case u/v are zero. - * NOTE2: algorithm won't fail on zero alpha or beta (there will be no - * division by zero because it will be stopped BEFORE division - * occurs). However, near-zero alpha and beta won't stop algorithm - * and, although no division by zero will happen, orthogonality - * in U and V will be lost. - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->vi.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - state->repnmv = state->repnmv+1; - linlsqr_clearrfields(state, _state); - state->needmv = ae_true; - state->rstate.stage = 4; - goto lbl_rcomm; -lbl_4: - state->needmv = ae_false; - for(i=0; i<=state->n-1; i++) - { - state->mv.ptr.p_double[state->m+i] = state->lambdai*state->vi.ptr.p_double[i]; - } - state->betaip1 = (double)(0); - for(i=0; i<=summn-1; i++) - { - state->uip1.ptr.p_double[i] = state->mv.ptr.p_double[i]-state->alphai*state->ui.ptr.p_double[i]; - state->betaip1 = state->betaip1+state->uip1.ptr.p_double[i]*state->uip1.ptr.p_double[i]; - } - if( ae_fp_neq(state->betaip1,(double)(0)) ) - { - state->betaip1 = ae_sqrt(state->betaip1, _state); - for(i=0; i<=summn-1; i++) - { - state->uip1.ptr.p_double[i] = state->uip1.ptr.p_double[i]/state->betaip1; - } - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->uip1.ptr.p_double[0], 1, ae_v_len(0,state->m-1)); - state->repnmv = state->repnmv+1; - linlsqr_clearrfields(state, _state); - state->needmtv = ae_true; - state->rstate.stage = 5; - goto lbl_rcomm; -lbl_5: - state->needmtv = ae_false; - for(i=0; i<=state->n-1; i++) - { - state->mtv.ptr.p_double[i] = state->mtv.ptr.p_double[i]+state->lambdai*state->uip1.ptr.p_double[state->m+i]; - } - state->alphaip1 = (double)(0); - for(i=0; i<=state->n-1; i++) - { - state->vip1.ptr.p_double[i] = state->mtv.ptr.p_double[i]-state->betaip1*state->vi.ptr.p_double[i]; - state->alphaip1 = state->alphaip1+state->vip1.ptr.p_double[i]*state->vip1.ptr.p_double[i]; - } - if( ae_fp_neq(state->alphaip1,(double)(0)) ) - { - state->alphaip1 = ae_sqrt(state->alphaip1, _state); - for(i=0; i<=state->n-1; i++) - { - state->vip1.ptr.p_double[i] = state->vip1.ptr.p_double[i]/state->alphaip1; - } - } - - /* - * Build next orthogonal transformation - */ - state->rhoi = safepythag2(state->rhobari, state->betaip1, _state); - state->ci = state->rhobari/state->rhoi; - state->si = state->betaip1/state->rhoi; - state->theta = state->si*state->alphaip1; - state->rhobarip1 = -state->ci*state->alphaip1; - state->phii = state->ci*state->phibari; - state->phibarip1 = state->si*state->phibari; - - /* - * Update .RNorm - * - * This tricky formula is necessary because simply writing - * State.R2:=State.PhiBarIP1*State.PhiBarIP1 does NOT guarantees - * monotonic decrease of R2. Roundoff error combined with 80-bit - * precision used internally by Intel chips allows R2 to increase - * slightly in some rare, but possible cases. This property is - * undesirable, so we prefer to guard against R increase. - */ - state->r2 = ae_minreal(state->r2, state->phibarip1*state->phibarip1, _state); - - /* - * Update d and DNorm, check condition-related stopping criteria - */ - for(i=0; i<=state->n-1; i++) - { - state->d.ptr.p_double[i] = 1/state->rhoi*(state->vi.ptr.p_double[i]-state->theta*state->d.ptr.p_double[i]); - state->dnorm = state->dnorm+state->d.ptr.p_double[i]*state->d.ptr.p_double[i]; - } - if( ae_fp_greater_eq(ae_sqrt(state->dnorm, _state)*state->anorm,state->epsc) ) - { - state->running = ae_false; - state->repterminationtype = 7; - result = ae_false; - return result; - } - - /* - * Update x, output report - */ - for(i=0; i<=state->n-1; i++) - { - state->rx.ptr.p_double[i] = state->rx.ptr.p_double[i]+state->phii/state->rhoi*state->omegai.ptr.p_double[i]; - } - if( !state->xrep ) - { - goto lbl_17; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->rx.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - linlsqr_clearrfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 6; - goto lbl_rcomm; -lbl_6: - state->xupdated = ae_false; -lbl_17: - - /* - * Check stopping criteria - * 1. achieved required number of iterations; - * 2. ||Rk||<=EpsB*||B||; - * 3. ||A^T*Rk||/(||A||*||Rk||)<=EpsA; - */ - if( state->maxits>0&&state->repiterationscount>=state->maxits ) - { - - /* - * Achieved required number of iterations - */ - state->running = ae_false; - state->repterminationtype = 5; - result = ae_false; - return result; - } - if( ae_fp_less_eq(state->phibarip1,state->epsb*bnorm) ) - { - - /* - * ||Rk||<=EpsB*||B||, here ||Rk||=PhiBar - */ - state->running = ae_false; - state->repterminationtype = 1; - result = ae_false; - return result; - } - if( ae_fp_less_eq(state->alphaip1*ae_fabs(state->ci, _state)/state->anorm,state->epsa) ) - { - - /* - * ||A^T*Rk||/(||A||*||Rk||)<=EpsA, here ||A^T*Rk||=PhiBar*Alpha[i+1]*|.C| - */ - state->running = ae_false; - state->repterminationtype = 4; - result = ae_false; - return result; - } - if( state->userterminationneeded ) - { - - /* - * User requested termination - */ - state->running = ae_false; - state->repterminationtype = 8; - result = ae_false; - return result; - } - - /* - * Update omega - */ - for(i=0; i<=state->n-1; i++) - { - state->omegaip1.ptr.p_double[i] = state->vip1.ptr.p_double[i]-state->theta/state->rhoi*state->omegai.ptr.p_double[i]; - } - - /* - * Prepare for the next iteration - rename variables: - * u[i] := u[i+1] - * v[i] := v[i+1] - * rho[i] := rho[i+1] - * ... - */ - ae_v_move(&state->ui.ptr.p_double[0], 1, &state->uip1.ptr.p_double[0], 1, ae_v_len(0,summn-1)); - ae_v_move(&state->vi.ptr.p_double[0], 1, &state->vip1.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - ae_v_move(&state->omegai.ptr.p_double[0], 1, &state->omegaip1.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - state->alphai = state->alphaip1; - state->betai = state->betaip1; - state->phibari = state->phibarip1; - state->rhobari = state->rhobarip1; - goto lbl_15; -lbl_16: - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = summn; - state->rstate.ia.ptr.p_int[1] = i; - state->rstate.ra.ptr.p_double[0] = bnorm; - return result; -} - - -/************************************************************************* -Procedure for solution of A*x=b with sparse A. - -INPUT PARAMETERS: - State - algorithm state - A - sparse M*N matrix in the CRS format (you MUST contvert it - to CRS format by calling SparseConvertToCRS() function - BEFORE you pass it to this function). - B - right part, array[M] - -RESULT: - This function returns no result. - You can get solution by calling LinCGResults() - -NOTE: this function uses lightweight preconditioning - multiplication by - inverse of diag(A). If you want, you can turn preconditioning off by - calling LinLSQRSetPrecUnit(). However, preconditioning cost is low - and preconditioner is very important for solution of badly scaled - problems. - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -void linlsqrsolvesparse(linlsqrstate* state, - sparsematrix* a, - /* Real */ ae_vector* b, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t t0; - ae_int_t t1; - double v; - - - n = state->n; - ae_assert(!state->running, "LinLSQRSolveSparse: you can not call this function when LinLSQRIteration is running", _state); - ae_assert(b->cnt>=state->m, "LinLSQRSolveSparse: Length(B)m, _state), "LinLSQRSolveSparse: B contains infinite or NaN values", _state); - - /* - * Allocate temporaries - */ - rvectorsetlengthatleast(&state->tmpd, n, _state); - rvectorsetlengthatleast(&state->tmpx, n, _state); - - /* - * Compute diagonal scaling matrix D - */ - if( state->prectype==0 ) - { - - /* - * Default preconditioner - inverse of column norms - */ - for(i=0; i<=n-1; i++) - { - state->tmpd.ptr.p_double[i] = (double)(0); - } - t0 = 0; - t1 = 0; - while(sparseenumerate(a, &t0, &t1, &i, &j, &v, _state)) - { - state->tmpd.ptr.p_double[j] = state->tmpd.ptr.p_double[j]+ae_sqr(v, _state); - } - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(state->tmpd.ptr.p_double[i],(double)(0)) ) - { - state->tmpd.ptr.p_double[i] = 1/ae_sqrt(state->tmpd.ptr.p_double[i], _state); - } - else - { - state->tmpd.ptr.p_double[i] = (double)(1); - } - } - } - else - { - - /* - * No diagonal scaling - */ - for(i=0; i<=n-1; i++) - { - state->tmpd.ptr.p_double[i] = (double)(1); - } - } - - /* - * Solve. - * - * Instead of solving A*x=b we solve preconditioned system (A*D)*(inv(D)*x)=b. - * Transformed A is not calculated explicitly, we just modify multiplication - * by A or A'. After solution we modify State.RX so it will store untransformed - * variables - */ - linlsqrsetb(state, b, _state); - linlsqrrestart(state, _state); - while(linlsqriteration(state, _state)) - { - if( state->needmv ) - { - for(i=0; i<=n-1; i++) - { - state->tmpx.ptr.p_double[i] = state->tmpd.ptr.p_double[i]*state->x.ptr.p_double[i]; - } - sparsemv(a, &state->tmpx, &state->mv, _state); - } - if( state->needmtv ) - { - sparsemtv(a, &state->x, &state->mtv, _state); - for(i=0; i<=n-1; i++) - { - state->mtv.ptr.p_double[i] = state->tmpd.ptr.p_double[i]*state->mtv.ptr.p_double[i]; - } - } - } - for(i=0; i<=n-1; i++) - { - state->rx.ptr.p_double[i] = state->tmpd.ptr.p_double[i]*state->rx.ptr.p_double[i]; - } -} - - -/************************************************************************* -This function sets stopping criteria. - -INPUT PARAMETERS: - EpsA - algorithm will be stopped if ||A^T*Rk||/(||A||*||Rk||)<=EpsA. - EpsB - algorithm will be stopped if ||Rk||<=EpsB*||B|| - MaxIts - algorithm will be stopped if number of iterations - more than MaxIts. - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: if EpsA,EpsB,EpsC and MaxIts are zero then these variables will -be setted as default values. - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -void linlsqrsetcond(linlsqrstate* state, - double epsa, - double epsb, - ae_int_t maxits, - ae_state *_state) -{ - - - ae_assert(!state->running, "LinLSQRSetCond: you can not call this function when LinLSQRIteration is running", _state); - ae_assert(ae_isfinite(epsa, _state)&&ae_fp_greater_eq(epsa,(double)(0)), "LinLSQRSetCond: EpsA is negative, INF or NAN", _state); - ae_assert(ae_isfinite(epsb, _state)&&ae_fp_greater_eq(epsb,(double)(0)), "LinLSQRSetCond: EpsB is negative, INF or NAN", _state); - ae_assert(maxits>=0, "LinLSQRSetCond: MaxIts is negative", _state); - if( (ae_fp_eq(epsa,(double)(0))&&ae_fp_eq(epsb,(double)(0)))&&maxits==0 ) - { - state->epsa = linlsqr_atol; - state->epsb = linlsqr_btol; - state->maxits = state->n; - } - else - { - state->epsa = epsa; - state->epsb = epsb; - state->maxits = maxits; - } -} - - -/************************************************************************* -LSQR solver: results. - -This function must be called after LinLSQRSolve - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[N], solution - Rep - optimization report: - * Rep.TerminationType completetion code: - * 1 ||Rk||<=EpsB*||B|| - * 4 ||A^T*Rk||/(||A||*||Rk||)<=EpsA - * 5 MaxIts steps was taken - * 7 rounding errors prevent further progress, - X contains best point found so far. - (sometimes returned on singular systems) - * 8 user requested termination via calling - linlsqrrequesttermination() - * Rep.IterationsCount contains iterations count - * NMV countains number of matrix-vector calculations - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -void linlsqrresults(linlsqrstate* state, - /* Real */ ae_vector* x, - linlsqrreport* rep, - ae_state *_state) -{ - - ae_vector_clear(x); - _linlsqrreport_clear(rep); - - ae_assert(!state->running, "LinLSQRResult: you can not call this function when LinLSQRIteration is running", _state); - if( x->cntn ) - { - ae_vector_set_length(x, state->n, _state); - } - ae_v_move(&x->ptr.p_double[0], 1, &state->rx.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - rep->iterationscount = state->repiterationscount; - rep->nmv = state->repnmv; - rep->terminationtype = state->repterminationtype; -} - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinCGOptimize(). - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -void linlsqrsetxrep(linlsqrstate* state, - ae_bool needxrep, - ae_state *_state) -{ - - - state->xrep = needxrep; -} - - -/************************************************************************* -This function restarts LinLSQRIteration - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -void linlsqrrestart(linlsqrstate* state, ae_state *_state) -{ - - - ae_vector_set_length(&state->rstate.ia, 1+1, _state); - ae_vector_set_length(&state->rstate.ra, 0+1, _state); - state->rstate.stage = -1; - linlsqr_clearrfields(state, _state); - state->repiterationscount = 0; -} - - -/************************************************************************* -This function is used to peek into LSQR solver and get current iteration -counter. You can safely "peek" into the solver from another thread. - -INPUT PARAMETERS: - S - solver object - -RESULT: - iteration counter, in [0,INF) - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -ae_int_t linlsqrpeekiterationscount(linlsqrstate* s, ae_state *_state) -{ - ae_int_t result; - - - result = s->repiterationscount; - return result; -} - - -/************************************************************************* -This subroutine submits request for termination of the running solver. It -can be called from some other thread which wants LSQR solver to terminate -(obviously, the thread running LSQR solver can not request termination -because it is already busy working on LSQR). - -As result, solver stops at point which was "current accepted" when -termination request was submitted and returns error code 8 (successful -termination). Such termination is a smooth process which properly -deallocates all temporaries. - -INPUT PARAMETERS: - State - solver structure - -NOTE: calling this function on solver which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - -NOTE: solver clears termination flag on its start, it means that if some - other thread will request termination too soon, its request will went - unnoticed. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void linlsqrrequesttermination(linlsqrstate* state, ae_state *_state) -{ - - - state->userterminationneeded = ae_true; -} - - -/************************************************************************* -Clears request fileds (to be sure that we don't forgot to clear something) -*************************************************************************/ -static void linlsqr_clearrfields(linlsqrstate* state, ae_state *_state) -{ - - - state->xupdated = ae_false; - state->needmv = ae_false; - state->needmtv = ae_false; - state->needmv2 = ae_false; - state->needvmv = ae_false; - state->needprec = ae_false; -} - - -void _linlsqrstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - linlsqrstate *p = (linlsqrstate*)_p; - ae_touch_ptr((void*)p); - _normestimatorstate_init(&p->nes, _state, make_automatic); - ae_vector_init(&p->rx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->b, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->ui, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->uip1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->vi, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->vip1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->omegai, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->omegaip1, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->mv, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->mtv, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpd, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpx, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); -} - - -void _linlsqrstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - linlsqrstate *dst = (linlsqrstate*)_dst; - linlsqrstate *src = (linlsqrstate*)_src; - _normestimatorstate_init_copy(&dst->nes, &src->nes, _state, make_automatic); - ae_vector_init_copy(&dst->rx, &src->rx, _state, make_automatic); - ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic); - dst->n = src->n; - dst->m = src->m; - dst->prectype = src->prectype; - ae_vector_init_copy(&dst->ui, &src->ui, _state, make_automatic); - ae_vector_init_copy(&dst->uip1, &src->uip1, _state, make_automatic); - ae_vector_init_copy(&dst->vi, &src->vi, _state, make_automatic); - ae_vector_init_copy(&dst->vip1, &src->vip1, _state, make_automatic); - ae_vector_init_copy(&dst->omegai, &src->omegai, _state, make_automatic); - ae_vector_init_copy(&dst->omegaip1, &src->omegaip1, _state, make_automatic); - dst->alphai = src->alphai; - dst->alphaip1 = src->alphaip1; - dst->betai = src->betai; - dst->betaip1 = src->betaip1; - dst->phibari = src->phibari; - dst->phibarip1 = src->phibarip1; - dst->phii = src->phii; - dst->rhobari = src->rhobari; - dst->rhobarip1 = src->rhobarip1; - dst->rhoi = src->rhoi; - dst->ci = src->ci; - dst->si = src->si; - dst->theta = src->theta; - dst->lambdai = src->lambdai; - ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic); - dst->anorm = src->anorm; - dst->bnorm2 = src->bnorm2; - dst->dnorm = src->dnorm; - dst->r2 = src->r2; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->mv, &src->mv, _state, make_automatic); - ae_vector_init_copy(&dst->mtv, &src->mtv, _state, make_automatic); - dst->epsa = src->epsa; - dst->epsb = src->epsb; - dst->epsc = src->epsc; - dst->maxits = src->maxits; - dst->xrep = src->xrep; - dst->xupdated = src->xupdated; - dst->needmv = src->needmv; - dst->needmtv = src->needmtv; - dst->needmv2 = src->needmv2; - dst->needvmv = src->needvmv; - dst->needprec = src->needprec; - dst->repiterationscount = src->repiterationscount; - dst->repnmv = src->repnmv; - dst->repterminationtype = src->repterminationtype; - dst->running = src->running; - dst->userterminationneeded = src->userterminationneeded; - ae_vector_init_copy(&dst->tmpd, &src->tmpd, _state, make_automatic); - ae_vector_init_copy(&dst->tmpx, &src->tmpx, _state, make_automatic); - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); -} - - -void _linlsqrstate_clear(void* _p) -{ - linlsqrstate *p = (linlsqrstate*)_p; - ae_touch_ptr((void*)p); - _normestimatorstate_clear(&p->nes); - ae_vector_clear(&p->rx); - ae_vector_clear(&p->b); - ae_vector_clear(&p->ui); - ae_vector_clear(&p->uip1); - ae_vector_clear(&p->vi); - ae_vector_clear(&p->vip1); - ae_vector_clear(&p->omegai); - ae_vector_clear(&p->omegaip1); - ae_vector_clear(&p->d); - ae_vector_clear(&p->x); - ae_vector_clear(&p->mv); - ae_vector_clear(&p->mtv); - ae_vector_clear(&p->tmpd); - ae_vector_clear(&p->tmpx); - _rcommstate_clear(&p->rstate); -} - - -void _linlsqrstate_destroy(void* _p) -{ - linlsqrstate *p = (linlsqrstate*)_p; - ae_touch_ptr((void*)p); - _normestimatorstate_destroy(&p->nes); - ae_vector_destroy(&p->rx); - ae_vector_destroy(&p->b); - ae_vector_destroy(&p->ui); - ae_vector_destroy(&p->uip1); - ae_vector_destroy(&p->vi); - ae_vector_destroy(&p->vip1); - ae_vector_destroy(&p->omegai); - ae_vector_destroy(&p->omegaip1); - ae_vector_destroy(&p->d); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->mv); - ae_vector_destroy(&p->mtv); - ae_vector_destroy(&p->tmpd); - ae_vector_destroy(&p->tmpx); - _rcommstate_destroy(&p->rstate); -} - - -void _linlsqrreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - linlsqrreport *p = (linlsqrreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _linlsqrreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - linlsqrreport *dst = (linlsqrreport*)_dst; - linlsqrreport *src = (linlsqrreport*)_src; - dst->iterationscount = src->iterationscount; - dst->nmv = src->nmv; - dst->terminationtype = src->terminationtype; -} - - -void _linlsqrreport_clear(void* _p) -{ - linlsqrreport *p = (linlsqrreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _linlsqrreport_destroy(void* _p) -{ - linlsqrreport *p = (linlsqrreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_POLYNOMIALSOLVER) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Polynomial root finding. - -This function returns all roots of the polynomial - P(x) = a0 + a1*x + a2*x^2 + ... + an*x^n -Both real and complex roots are returned (see below). - -INPUT PARAMETERS: - A - array[N+1], polynomial coefficients: - * A[0] is constant term - * A[N] is a coefficient of X^N - N - polynomial degree - -OUTPUT PARAMETERS: - X - array of complex roots: - * for isolated real root, X[I] is strictly real: IMAGE(X[I])=0 - * complex roots are always returned in pairs - roots occupy - positions I and I+1, with: - * X[I+1]=Conj(X[I]) - * IMAGE(X[I]) > 0 - * IMAGE(X[I+1]) = -IMAGE(X[I]) < 0 - * multiple real roots may have non-zero imaginary part due - to roundoff errors. There is no reliable way to distinguish - real root of multiplicity 2 from two complex roots in - the presence of roundoff errors. - Rep - report, additional information, following fields are set: - * Rep.MaxErr - max( |P(xi)| ) for i=0..N-1. This field - allows to quickly estimate "quality" of the roots being - returned. - -NOTE: this function uses companion matrix method to find roots. In case - internal EVD solver fails do find eigenvalues, exception is - generated. - -NOTE: roots are not "polished" and no matrix balancing is performed - for them. - - -- ALGLIB -- - Copyright 24.02.2014 by Bochkanov Sergey -*************************************************************************/ -void polynomialsolve(/* Real */ ae_vector* a, - ae_int_t n, - /* Complex */ ae_vector* x, - polynomialsolverreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _a; - ae_matrix c; - ae_matrix vl; - ae_matrix vr; - ae_vector wr; - ae_vector wi; - ae_int_t i; - ae_int_t j; - ae_bool status; - ae_int_t nz; - ae_int_t ne; - ae_complex v; - ae_complex vv; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&c, 0, sizeof(c)); - memset(&vl, 0, sizeof(vl)); - memset(&vr, 0, sizeof(vr)); - memset(&wr, 0, sizeof(wr)); - memset(&wi, 0, sizeof(wi)); - ae_vector_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_vector_clear(x); - _polynomialsolverreport_clear(rep); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vl, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vr, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wr, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wi, 0, DT_REAL, _state, ae_true); - - ae_assert(n>0, "PolynomialSolve: N<=0", _state); - ae_assert(a->cnt>=n+1, "PolynomialSolve: Length(A)ptr.p_double[n],(double)(0)), "PolynomialSolve: A[N]=0", _state); - - /* - * Prepare - */ - ae_vector_set_length(x, n, _state); - - /* - * Normalize A: - * * analytically determine NZ zero roots - * * quick exit for NZ=N - * * make residual NE-th degree polynomial monic - * (here NE=N-NZ) - */ - nz = 0; - while(nzptr.p_double[nz],(double)(0))) - { - nz = nz+1; - } - ne = n-nz; - for(i=nz; i<=n; i++) - { - a->ptr.p_double[i-nz] = a->ptr.p_double[i]/a->ptr.p_double[n]; - } - - /* - * For NZ0 ) - { - ae_matrix_set_length(&c, ne, ne, _state); - for(i=0; i<=ne-1; i++) - { - for(j=0; j<=ne-1; j++) - { - c.ptr.pp_double[i][j] = (double)(0); - } - } - c.ptr.pp_double[0][ne-1] = -a->ptr.p_double[0]; - for(i=1; i<=ne-1; i++) - { - c.ptr.pp_double[i][i-1] = (double)(1); - c.ptr.pp_double[i][ne-1] = -a->ptr.p_double[i]; - } - status = rmatrixevd(&c, ne, 0, &wr, &wi, &vl, &vr, _state); - ae_assert(status, "PolynomialSolve: inernal error - EVD solver failed", _state); - for(i=0; i<=ne-1; i++) - { - x->ptr.p_complex[i].x = wr.ptr.p_double[i]; - x->ptr.p_complex[i].y = wi.ptr.p_double[i]; - } - } - - /* - * Remaining NZ zero roots - */ - for(i=ne; i<=n-1; i++) - { - x->ptr.p_complex[i] = ae_complex_from_i(0); - } - - /* - * Rep - */ - rep->maxerr = (double)(0); - for(i=0; i<=ne-1; i++) - { - v = ae_complex_from_i(0); - vv = ae_complex_from_i(1); - for(j=0; j<=ne; j++) - { - v = ae_c_add(v,ae_c_mul_d(vv,a->ptr.p_double[j])); - vv = ae_c_mul(vv,x->ptr.p_complex[i]); - } - rep->maxerr = ae_maxreal(rep->maxerr, ae_c_abs(v, _state), _state); - } - ae_frame_leave(_state); -} - - -void _polynomialsolverreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - polynomialsolverreport *p = (polynomialsolverreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _polynomialsolverreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - polynomialsolverreport *dst = (polynomialsolverreport*)_dst; - polynomialsolverreport *src = (polynomialsolverreport*)_src; - dst->maxerr = src->maxerr; -} - - -void _polynomialsolverreport_clear(void* _p) -{ - polynomialsolverreport *p = (polynomialsolverreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _polynomialsolverreport_destroy(void* _p) -{ - polynomialsolverreport *p = (polynomialsolverreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_NLEQ) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* - LEVENBERG-MARQUARDT-LIKE NONLINEAR SOLVER - -DESCRIPTION: -This algorithm solves system of nonlinear equations - F[0](x[0], ..., x[n-1]) = 0 - F[1](x[0], ..., x[n-1]) = 0 - ... - F[M-1](x[0], ..., x[n-1]) = 0 -with M/N do not necessarily coincide. Algorithm converges quadratically -under following conditions: - * the solution set XS is nonempty - * for some xs in XS there exist such neighbourhood N(xs) that: - * vector function F(x) and its Jacobian J(x) are continuously - differentiable on N - * ||F(x)|| provides local error bound on N, i.e. there exists such - c1, that ||F(x)||>c1*distance(x,XS) -Note that these conditions are much more weaker than usual non-singularity -conditions. For example, algorithm will converge for any affine function -F (whether its Jacobian singular or not). - - -REQUIREMENTS: -Algorithm will request following information during its operation: -* function vector F[] and Jacobian matrix at given point X -* value of merit function f(x)=F[0]^2(x)+...+F[M-1]^2(x) at given point X - - -USAGE: -1. User initializes algorithm state with NLEQCreateLM() call -2. User tunes solver parameters with NLEQSetCond(), NLEQSetStpMax() and - other functions -3. User calls NLEQSolve() function which takes algorithm state and - pointers (delegates, etc.) to callback functions which calculate merit - function value and Jacobian. -4. User calls NLEQResults() to get solution -5. Optionally, user may call NLEQRestartFrom() to solve another problem - with same parameters (N/M) but another starting point and/or another - function vector. NLEQRestartFrom() allows to reuse already initialized - structure. - - -INPUT PARAMETERS: - N - space dimension, N>1: - * if provided, only leading N elements of X are used - * if not provided, determined automatically from size of X - M - system size - X - starting point - - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -NOTES: -1. you may tune stopping conditions with NLEQSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use NLEQSetStpMax() function to bound algorithm's steps. -3. this algorithm is a slightly modified implementation of the method - described in 'Levenberg-Marquardt method for constrained nonlinear - equations with strong local convergence properties' by Christian Kanzow - Nobuo Yamashita and Masao Fukushima and further developed in 'On the - convergence of a New Levenberg-Marquardt Method' by Jin-yan Fan and - Ya-Xiang Yuan. - - - -- ALGLIB -- - Copyright 20.08.2009 by Bochkanov Sergey -*************************************************************************/ -void nleqcreatelm(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* x, - nleqstate* state, - ae_state *_state) -{ - - _nleqstate_clear(state); - - ae_assert(n>=1, "NLEQCreateLM: N<1!", _state); - ae_assert(m>=1, "NLEQCreateLM: M<1!", _state); - ae_assert(x->cnt>=n, "NLEQCreateLM: Length(X)n = n; - state->m = m; - nleqsetcond(state, (double)(0), 0, _state); - nleqsetxrep(state, ae_false, _state); - nleqsetstpmax(state, (double)(0), _state); - ae_vector_set_length(&state->x, n, _state); - ae_vector_set_length(&state->xbase, n, _state); - ae_matrix_set_length(&state->j, m, n, _state); - ae_vector_set_length(&state->fi, m, _state); - ae_vector_set_length(&state->rightpart, n, _state); - ae_vector_set_length(&state->candstep, n, _state); - nleqrestartfrom(state, x, _state); -} - - -/************************************************************************* -This function sets stopping conditions for the nonlinear solver - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsF - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition ||F||<=EpsF is satisfied - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsF=0 and MaxIts=0 simultaneously will lead to automatic -stopping criterion selection (small EpsF). - -NOTES: - - -- ALGLIB -- - Copyright 20.08.2010 by Bochkanov Sergey -*************************************************************************/ -void nleqsetcond(nleqstate* state, - double epsf, - ae_int_t maxits, - ae_state *_state) -{ - - - ae_assert(ae_isfinite(epsf, _state), "NLEQSetCond: EpsF is not finite number!", _state); - ae_assert(ae_fp_greater_eq(epsf,(double)(0)), "NLEQSetCond: negative EpsF!", _state); - ae_assert(maxits>=0, "NLEQSetCond: negative MaxIts!", _state); - if( ae_fp_eq(epsf,(double)(0))&&maxits==0 ) - { - epsf = 1.0E-6; - } - state->epsf = epsf; - state->maxits = maxits; -} - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to NLEQSolve(). - - -- ALGLIB -- - Copyright 20.08.2010 by Bochkanov Sergey -*************************************************************************/ -void nleqsetxrep(nleqstate* state, ae_bool needxrep, ae_state *_state) -{ - - - state->xrep = needxrep; -} - - -/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when target function contains exp() or other fast -growing functions, and algorithm makes too large steps which lead to -overflow. This function allows us to reject steps that are too large (and -therefore expose us to the possible overflow) without actually calculating -function value at the x+stp*d. - - -- ALGLIB -- - Copyright 20.08.2010 by Bochkanov Sergey -*************************************************************************/ -void nleqsetstpmax(nleqstate* state, double stpmax, ae_state *_state) -{ - - - ae_assert(ae_isfinite(stpmax, _state), "NLEQSetStpMax: StpMax is not finite!", _state); - ae_assert(ae_fp_greater_eq(stpmax,(double)(0)), "NLEQSetStpMax: StpMax<0!", _state); - state->stpmax = stpmax; -} - - -/************************************************************************* - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey -*************************************************************************/ -ae_bool nleqiteration(nleqstate* state, ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - ae_int_t i; - double lambdaup; - double lambdadown; - double lambdav; - double rho; - double mu; - double stepnorm; - ae_bool b; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - n = state->rstate.ia.ptr.p_int[0]; - m = state->rstate.ia.ptr.p_int[1]; - i = state->rstate.ia.ptr.p_int[2]; - b = state->rstate.ba.ptr.p_bool[0]; - lambdaup = state->rstate.ra.ptr.p_double[0]; - lambdadown = state->rstate.ra.ptr.p_double[1]; - lambdav = state->rstate.ra.ptr.p_double[2]; - rho = state->rstate.ra.ptr.p_double[3]; - mu = state->rstate.ra.ptr.p_double[4]; - stepnorm = state->rstate.ra.ptr.p_double[5]; - } - else - { - n = 359; - m = -58; - i = -919; - b = ae_true; - lambdaup = 81; - lambdadown = 255; - lambdav = 74; - rho = -788; - mu = 809; - stepnorm = 205; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - if( state->rstate.stage==1 ) - { - goto lbl_1; - } - if( state->rstate.stage==2 ) - { - goto lbl_2; - } - if( state->rstate.stage==3 ) - { - goto lbl_3; - } - if( state->rstate.stage==4 ) - { - goto lbl_4; - } - - /* - * Routine body - */ - - /* - * Prepare - */ - n = state->n; - m = state->m; - state->repterminationtype = 0; - state->repiterationscount = 0; - state->repnfunc = 0; - state->repnjac = 0; - - /* - * Calculate F/G, initialize algorithm - */ - nleq_clearrequestfields(state, _state); - state->needf = ae_true; - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - state->needf = ae_false; - state->repnfunc = state->repnfunc+1; - ae_v_move(&state->xbase.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->fbase = state->f; - state->fprev = ae_maxrealnumber; - if( !state->xrep ) - { - goto lbl_5; - } - - /* - * progress report - */ - nleq_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 1; - goto lbl_rcomm; -lbl_1: - state->xupdated = ae_false; -lbl_5: - if( ae_fp_less_eq(state->f,ae_sqr(state->epsf, _state)) ) - { - state->repterminationtype = 1; - result = ae_false; - return result; - } - - /* - * Main cycle - */ - lambdaup = (double)(10); - lambdadown = 0.3; - lambdav = 0.001; - rho = (double)(1); -lbl_7: - if( ae_false ) - { - goto lbl_8; - } - - /* - * Get Jacobian; - * before we get to this point we already have State.XBase filled - * with current point and State.FBase filled with function value - * at XBase - */ - nleq_clearrequestfields(state, _state); - state->needfij = ae_true; - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->rstate.stage = 2; - goto lbl_rcomm; -lbl_2: - state->needfij = ae_false; - state->repnfunc = state->repnfunc+1; - state->repnjac = state->repnjac+1; - rmatrixmv(n, m, &state->j, 0, 0, 1, &state->fi, 0, &state->rightpart, 0, _state); - ae_v_muld(&state->rightpart.ptr.p_double[0], 1, ae_v_len(0,n-1), -1); - - /* - * Inner cycle: find good lambda - */ -lbl_9: - if( ae_false ) - { - goto lbl_10; - } - - /* - * Solve (J^T*J + (Lambda+Mu)*I)*y = J^T*F - * to get step d=-y where: - * * Mu=||F|| - is damping parameter for nonlinear system - * * Lambda - is additional Levenberg-Marquardt parameter - * for better convergence when far away from minimum - */ - for(i=0; i<=n-1; i++) - { - state->candstep.ptr.p_double[i] = (double)(0); - } - fblssolvecgx(&state->j, m, n, lambdav, &state->rightpart, &state->candstep, &state->cgbuf, _state); - - /* - * Normalize step (it must be no more than StpMax) - */ - stepnorm = (double)(0); - for(i=0; i<=n-1; i++) - { - if( ae_fp_neq(state->candstep.ptr.p_double[i],(double)(0)) ) - { - stepnorm = (double)(1); - break; - } - } - linminnormalized(&state->candstep, &stepnorm, n, _state); - if( ae_fp_neq(state->stpmax,(double)(0)) ) - { - stepnorm = ae_minreal(stepnorm, state->stpmax, _state); - } - - /* - * Test new step - is it good enough? - * * if not, Lambda is increased and we try again. - * * if step is good, we decrease Lambda and move on. - * - * We can break this cycle on two occasions: - * * step is so small that x+step==x (in floating point arithmetics) - * * lambda is so large - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_addd(&state->x.ptr.p_double[0], 1, &state->candstep.ptr.p_double[0], 1, ae_v_len(0,n-1), stepnorm); - b = ae_true; - for(i=0; i<=n-1; i++) - { - if( ae_fp_neq(state->x.ptr.p_double[i],state->xbase.ptr.p_double[i]) ) - { - b = ae_false; - break; - } - } - if( b ) - { - - /* - * Step is too small, force zero step and break - */ - stepnorm = (double)(0); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->f = state->fbase; - goto lbl_10; - } - nleq_clearrequestfields(state, _state); - state->needf = ae_true; - state->rstate.stage = 3; - goto lbl_rcomm; -lbl_3: - state->needf = ae_false; - state->repnfunc = state->repnfunc+1; - if( ae_fp_less(state->f,state->fbase) ) - { - - /* - * function value decreased, move on - */ - nleq_decreaselambda(&lambdav, &rho, lambdadown, _state); - goto lbl_10; - } - if( !nleq_increaselambda(&lambdav, &rho, lambdaup, _state) ) - { - - /* - * Lambda is too large (near overflow), force zero step and break - */ - stepnorm = (double)(0); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->f = state->fbase; - goto lbl_10; - } - goto lbl_9; -lbl_10: - - /* - * Accept step: - * * new position - * * new function value - */ - state->fbase = state->f; - ae_v_addd(&state->xbase.ptr.p_double[0], 1, &state->candstep.ptr.p_double[0], 1, ae_v_len(0,n-1), stepnorm); - state->repiterationscount = state->repiterationscount+1; - - /* - * Report new iteration - */ - if( !state->xrep ) - { - goto lbl_11; - } - nleq_clearrequestfields(state, _state); - state->xupdated = ae_true; - state->f = state->fbase; - ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state->rstate.stage = 4; - goto lbl_rcomm; -lbl_4: - state->xupdated = ae_false; -lbl_11: - - /* - * Test stopping conditions on F, step (zero/non-zero) and MaxIts; - * If one of the conditions is met, RepTerminationType is changed. - */ - if( ae_fp_less_eq(ae_sqrt(state->f, _state),state->epsf) ) - { - state->repterminationtype = 1; - } - if( ae_fp_eq(stepnorm,(double)(0))&&state->repterminationtype==0 ) - { - state->repterminationtype = -4; - } - if( state->repiterationscount>=state->maxits&&state->maxits>0 ) - { - state->repterminationtype = 5; - } - if( state->repterminationtype!=0 ) - { - goto lbl_8; - } - - /* - * Now, iteration is finally over - */ - goto lbl_7; -lbl_8: - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = n; - state->rstate.ia.ptr.p_int[1] = m; - state->rstate.ia.ptr.p_int[2] = i; - state->rstate.ba.ptr.p_bool[0] = b; - state->rstate.ra.ptr.p_double[0] = lambdaup; - state->rstate.ra.ptr.p_double[1] = lambdadown; - state->rstate.ra.ptr.p_double[2] = lambdav; - state->rstate.ra.ptr.p_double[3] = rho; - state->rstate.ra.ptr.p_double[4] = mu; - state->rstate.ra.ptr.p_double[5] = stepnorm; - return result; -} - - -/************************************************************************* -NLEQ solver results - -INPUT PARAMETERS: - State - algorithm state. - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report: - * Rep.TerminationType completetion code: - * -4 ERROR: algorithm has converged to the - stationary point Xf which is local minimum of - f=F[0]^2+...+F[m-1]^2, but is not solution of - nonlinear system. - * 1 sqrt(f)<=EpsF. - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible - * Rep.IterationsCount contains iterations count - * NFEV countains number of function calculations - * ActiveConstraints contains number of active constraints - - -- ALGLIB -- - Copyright 20.08.2009 by Bochkanov Sergey -*************************************************************************/ -void nleqresults(nleqstate* state, - /* Real */ ae_vector* x, - nleqreport* rep, - ae_state *_state) -{ - - ae_vector_clear(x); - _nleqreport_clear(rep); - - nleqresultsbuf(state, x, rep, _state); -} - - -/************************************************************************* -NLEQ solver results - -Buffered implementation of NLEQResults(), which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 20.08.2009 by Bochkanov Sergey -*************************************************************************/ -void nleqresultsbuf(nleqstate* state, - /* Real */ ae_vector* x, - nleqreport* rep, - ae_state *_state) -{ - - - if( x->cntn ) - { - ae_vector_set_length(x, state->n, _state); - } - ae_v_move(&x->ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - rep->iterationscount = state->repiterationscount; - rep->nfunc = state->repnfunc; - rep->njac = state->repnjac; - rep->terminationtype = state->repterminationtype; -} - - -/************************************************************************* -This subroutine restarts CG algorithm from new point. All optimization -parameters are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure used for reverse communication previously - allocated with MinCGCreate call. - X - new starting point. - BndL - new lower bounds - BndU - new upper bounds - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -void nleqrestartfrom(nleqstate* state, - /* Real */ ae_vector* x, - ae_state *_state) -{ - - - ae_assert(x->cnt>=state->n, "NLEQRestartFrom: Length(X)n, _state), "NLEQRestartFrom: X contains infinite or NaN values!", _state); - ae_v_move(&state->x.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - ae_vector_set_length(&state->rstate.ia, 2+1, _state); - ae_vector_set_length(&state->rstate.ba, 0+1, _state); - ae_vector_set_length(&state->rstate.ra, 5+1, _state); - state->rstate.stage = -1; - nleq_clearrequestfields(state, _state); -} - - -/************************************************************************* -Clears request fileds (to be sure that we don't forgot to clear something) -*************************************************************************/ -static void nleq_clearrequestfields(nleqstate* state, ae_state *_state) -{ - - - state->needf = ae_false; - state->needfij = ae_false; - state->xupdated = ae_false; -} - - -/************************************************************************* -Increases lambda, returns False when there is a danger of overflow -*************************************************************************/ -static ae_bool nleq_increaselambda(double* lambdav, - double* nu, - double lambdaup, - ae_state *_state) -{ - double lnlambda; - double lnnu; - double lnlambdaup; - double lnmax; - ae_bool result; - - - result = ae_false; - lnlambda = ae_log(*lambdav, _state); - lnlambdaup = ae_log(lambdaup, _state); - lnnu = ae_log(*nu, _state); - lnmax = 0.5*ae_log(ae_maxrealnumber, _state); - if( ae_fp_greater(lnlambda+lnlambdaup+lnnu,lnmax) ) - { - return result; - } - if( ae_fp_greater(lnnu+ae_log((double)(2), _state),lnmax) ) - { - return result; - } - *lambdav = *lambdav*lambdaup*(*nu); - *nu = *nu*2; - result = ae_true; - return result; -} - - -/************************************************************************* -Decreases lambda, but leaves it unchanged when there is danger of underflow. -*************************************************************************/ -static void nleq_decreaselambda(double* lambdav, - double* nu, - double lambdadown, - ae_state *_state) -{ - - - *nu = (double)(1); - if( ae_fp_less(ae_log(*lambdav, _state)+ae_log(lambdadown, _state),ae_log(ae_minrealnumber, _state)) ) - { - *lambdav = ae_minrealnumber; - } - else - { - *lambdav = *lambdav*lambdadown; - } -} - - -void _nleqstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - nleqstate *p = (nleqstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->fi, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->j, 0, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); - ae_vector_init(&p->xbase, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->candstep, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->rightpart, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cgbuf, 0, DT_REAL, _state, make_automatic); -} - - -void _nleqstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - nleqstate *dst = (nleqstate*)_dst; - nleqstate *src = (nleqstate*)_src; - dst->n = src->n; - dst->m = src->m; - dst->epsf = src->epsf; - dst->maxits = src->maxits; - dst->xrep = src->xrep; - dst->stpmax = src->stpmax; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - dst->f = src->f; - ae_vector_init_copy(&dst->fi, &src->fi, _state, make_automatic); - ae_matrix_init_copy(&dst->j, &src->j, _state, make_automatic); - dst->needf = src->needf; - dst->needfij = src->needfij; - dst->xupdated = src->xupdated; - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); - dst->repiterationscount = src->repiterationscount; - dst->repnfunc = src->repnfunc; - dst->repnjac = src->repnjac; - dst->repterminationtype = src->repterminationtype; - ae_vector_init_copy(&dst->xbase, &src->xbase, _state, make_automatic); - dst->fbase = src->fbase; - dst->fprev = src->fprev; - ae_vector_init_copy(&dst->candstep, &src->candstep, _state, make_automatic); - ae_vector_init_copy(&dst->rightpart, &src->rightpart, _state, make_automatic); - ae_vector_init_copy(&dst->cgbuf, &src->cgbuf, _state, make_automatic); -} - - -void _nleqstate_clear(void* _p) -{ - nleqstate *p = (nleqstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->x); - ae_vector_clear(&p->fi); - ae_matrix_clear(&p->j); - _rcommstate_clear(&p->rstate); - ae_vector_clear(&p->xbase); - ae_vector_clear(&p->candstep); - ae_vector_clear(&p->rightpart); - ae_vector_clear(&p->cgbuf); -} - - -void _nleqstate_destroy(void* _p) -{ - nleqstate *p = (nleqstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->fi); - ae_matrix_destroy(&p->j); - _rcommstate_destroy(&p->rstate); - ae_vector_destroy(&p->xbase); - ae_vector_destroy(&p->candstep); - ae_vector_destroy(&p->rightpart); - ae_vector_destroy(&p->cgbuf); -} - - -void _nleqreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - nleqreport *p = (nleqreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _nleqreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - nleqreport *dst = (nleqreport*)_dst; - nleqreport *src = (nleqreport*)_src; - dst->iterationscount = src->iterationscount; - dst->nfunc = src->nfunc; - dst->njac = src->njac; - dst->terminationtype = src->terminationtype; -} - - -void _nleqreport_clear(void* _p) -{ - nleqreport *p = (nleqreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _nleqreport_destroy(void* _p) -{ - nleqreport *p = (nleqreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_DIRECTSPARSESOLVERS) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Sparse linear solver for A*x=b with N*N sparse real symmetric positive -definite matrix A, N*1 vectors x and b. - -This solver converts input matrix to SKS format, performs Cholesky -factorization using SKS Cholesky subroutine (works well for limited -bandwidth matrices) and uses sparse triangular solvers to get solution of -the original system. - -INPUT PARAMETERS - A - sparse matrix, must be NxN exactly - IsUpper - which half of A is provided (another half is ignored) - B - array[0..N-1], right part - -OUTPUT PARAMETERS - X - array[N], it contains: - * rep.terminationtype>0 => solution - * rep.terminationtype=-3 => filled by zeros - Rep - solver report, following fields are set: - * rep.terminationtype - solver status; >0 for success, - set to -3 on failure (degenerate or non-SPD system). - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -void sparsespdsolvesks(sparsematrix* a, - ae_bool isupper, - /* Real */ ae_vector* b, - /* Real */ ae_vector* x, - sparsesolverreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - sparsematrix a2; - ae_int_t n; - - ae_frame_make(_state, &_frame_block); - memset(&a2, 0, sizeof(a2)); - ae_vector_clear(x); - _sparsesolverreport_clear(rep); - _sparsematrix_init(&a2, _state, ae_true); - - n = sparsegetnrows(a, _state); - ae_assert(n>0, "SparseSPDSolveSKS: N<=0", _state); - ae_assert(sparsegetnrows(a, _state)==n, "SparseSPDSolveSKS: rows(A)!=N", _state); - ae_assert(sparsegetncols(a, _state)==n, "SparseSPDSolveSKS: cols(A)!=N", _state); - ae_assert(b->cnt>=n, "SparseSPDSolveSKS: length(B)terminationtype = -3; - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = (double)(0); - } - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = b->ptr.p_double[i]; - } - if( isupper ) - { - sparsetrsv(&a2, isupper, ae_false, 1, x, _state); - sparsetrsv(&a2, isupper, ae_false, 0, x, _state); - } - else - { - sparsetrsv(&a2, isupper, ae_false, 0, x, _state); - sparsetrsv(&a2, isupper, ae_false, 1, x, _state); - } - rep->terminationtype = 1; - ae_frame_leave(_state); -} - - -/************************************************************************* -Sparse linear solver for A*x=b with N*N sparse real symmetric positive -definite matrix A, N*1 vectors x and b. - -This solver converts input matrix to CRS format, performs Cholesky -factorization using supernodal Cholesky decomposition with permutation- -reducing ordering and uses sparse triangular solver to get solution of the -original system. - -INPUT PARAMETERS - A - sparse matrix, must be NxN exactly - IsUpper - which half of A is provided (another half is ignored) - B - array[N], right part - -OUTPUT PARAMETERS - X - array[N], it contains: - * rep.terminationtype>0 => solution - * rep.terminationtype=-3 => filled by zeros - Rep - solver report, following fields are set: - * rep.terminationtype - solver status; >0 for success, - set to -3 on failure (degenerate or non-SPD system). - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -void sparsespdsolve(sparsematrix* a, - ae_bool isupper, - /* Real */ ae_vector* b, - /* Real */ ae_vector* x, - sparsesolverreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - sparsematrix a2; - ae_int_t n; - double v; - ae_vector p; - - ae_frame_make(_state, &_frame_block); - memset(&a2, 0, sizeof(a2)); - memset(&p, 0, sizeof(p)); - ae_vector_clear(x); - _sparsesolverreport_clear(rep); - _sparsematrix_init(&a2, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - - n = sparsegetnrows(a, _state); - ae_assert(n>0, "SparseSPDSolve: N<=0", _state); - ae_assert(sparsegetnrows(a, _state)==n, "SparseSPDSolve: rows(A)!=N", _state); - ae_assert(sparsegetncols(a, _state)==n, "SparseSPDSolve: cols(A)!=N", _state); - ae_assert(b->cnt>=n, "SparseSPDSolve: length(B)terminationtype = -3; - rsetallocv(n, 0.0, x, _state); - ae_frame_leave(_state); - return; - } - rcopyallocv(n, b, x, _state); - for(i=0; i<=n-1; i++) - { - j = p.ptr.p_int[i]; - v = x->ptr.p_double[i]; - x->ptr.p_double[i] = x->ptr.p_double[j]; - x->ptr.p_double[j] = v; - } - if( isupper ) - { - sparsetrsv(&a2, isupper, ae_false, 1, x, _state); - sparsetrsv(&a2, isupper, ae_false, 0, x, _state); - } - else - { - sparsetrsv(&a2, isupper, ae_false, 0, x, _state); - sparsetrsv(&a2, isupper, ae_false, 1, x, _state); - } - for(i=n-1; i>=0; i--) - { - j = p.ptr.p_int[i]; - v = x->ptr.p_double[i]; - x->ptr.p_double[i] = x->ptr.p_double[j]; - x->ptr.p_double[j] = v; - } - rep->terminationtype = 1; - ae_frame_leave(_state); -} - - -/************************************************************************* -Sparse linear solver for A*x=b with N*N real symmetric positive definite -matrix A given by its Cholesky decomposition, and N*1 vectors x and b. - -IMPORTANT: this solver requires input matrix to be in the SKS (Skyline) - or CRS (compressed row storage) format. An exception will be - generated if you pass matrix in some other format. - -INPUT PARAMETERS - A - sparse NxN matrix stored in CRs or SKS format, must be NxN - exactly - IsUpper - which half of A is provided (another half is ignored) - B - array[N], right part - -OUTPUT PARAMETERS - X - array[N], it contains: - * rep.terminationtype>0 => solution - * rep.terminationtype=-3 => filled by zeros - Rep - solver report, following fields are set: - * rep.terminationtype - solver status; >0 for success, - set to -3 on failure (degenerate or non-SPD system). - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -void sparsespdcholeskysolve(sparsematrix* a, - ae_bool isupper, - /* Real */ ae_vector* b, - /* Real */ ae_vector* x, - sparsesolverreport* rep, - ae_state *_state) -{ - ae_int_t i; - ae_int_t n; - - ae_vector_clear(x); - _sparsesolverreport_clear(rep); - - n = sparsegetnrows(a, _state); - ae_assert(n>0, "SparseSPDCholeskySolve: N<=0", _state); - ae_assert(sparsegetnrows(a, _state)==n, "SparseSPDCholeskySolve: rows(A)!=N", _state); - ae_assert(sparsegetncols(a, _state)==n, "SparseSPDCholeskySolve: cols(A)!=N", _state); - ae_assert(sparseissks(a, _state)||sparseiscrs(a, _state), "SparseSPDCholeskySolve: A is not an SKS/CRS matrix", _state); - ae_assert(b->cnt>=n, "SparseSPDCholeskySolve: length(B)terminationtype = -3; - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = (double)(0); - } - return; - } - } - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = b->ptr.p_double[i]; - } - if( isupper ) - { - sparsetrsv(a, isupper, ae_false, 1, x, _state); - sparsetrsv(a, isupper, ae_false, 0, x, _state); - } - else - { - sparsetrsv(a, isupper, ae_false, 0, x, _state); - sparsetrsv(a, isupper, ae_false, 1, x, _state); - } - rep->terminationtype = 1; -} - - -/************************************************************************* -Sparse linear solver for A*x=b with general (nonsymmetric) N*N sparse real -matrix A, N*1 vectors x and b. - -This solver converts input matrix to CRS format, performs LU factorization -and uses sparse triangular solvers to get solution of the original system. - -INPUT PARAMETERS - A - sparse matrix, must be NxN exactly, any storage format - N - size of A, N>0 - B - array[0..N-1], right part - -OUTPUT PARAMETERS - X - array[N], it contains: - * rep.terminationtype>0 => solution - * rep.terminationtype=-3 => filled by zeros - Rep - solver report, following fields are set: - * rep.terminationtype - solver status; >0 for success, - set to -3 on failure (degenerate system). - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -void sparsesolve(sparsematrix* a, - /* Real */ ae_vector* b, - /* Real */ ae_vector* x, - sparsesolverreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t n; - double v; - sparsematrix a2; - ae_vector pivp; - ae_vector pivq; - - ae_frame_make(_state, &_frame_block); - memset(&a2, 0, sizeof(a2)); - memset(&pivp, 0, sizeof(pivp)); - memset(&pivq, 0, sizeof(pivq)); - ae_vector_clear(x); - _sparsesolverreport_clear(rep); - _sparsematrix_init(&a2, _state, ae_true); - ae_vector_init(&pivp, 0, DT_INT, _state, ae_true); - ae_vector_init(&pivq, 0, DT_INT, _state, ae_true); - - n = sparsegetnrows(a, _state); - ae_assert(n>0, "SparseSolve: N<=0", _state); - ae_assert(sparsegetnrows(a, _state)==n, "SparseSolve: rows(A)!=N", _state); - ae_assert(sparsegetncols(a, _state)==n, "SparseSolve: cols(A)!=N", _state); - ae_assert(b->cnt>=n, "SparseSolve: length(B)terminationtype = -3; - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = (double)(0); - } - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = b->ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - j = pivp.ptr.p_int[i]; - v = x->ptr.p_double[i]; - x->ptr.p_double[i] = x->ptr.p_double[j]; - x->ptr.p_double[j] = v; - } - sparsetrsv(&a2, ae_false, ae_true, 0, x, _state); - sparsetrsv(&a2, ae_true, ae_false, 0, x, _state); - for(i=n-1; i>=0; i--) - { - j = pivq.ptr.p_int[i]; - v = x->ptr.p_double[i]; - x->ptr.p_double[i] = x->ptr.p_double[j]; - x->ptr.p_double[j] = v; - } - rep->terminationtype = 1; - ae_frame_leave(_state); -} - - -/************************************************************************* -Sparse linear solver for A*x=b with general (nonsymmetric) N*N sparse real -matrix A given by its LU factorization, N*1 vectors x and b. - -IMPORTANT: this solver requires input matrix to be in the CRS sparse - storage format. An exception will be generated if you pass - matrix in some other format (HASH or SKS). - -INPUT PARAMETERS - A - LU factorization of the sparse matrix, must be NxN exactly - in CRS storage format - P, Q - pivot indexes from LU factorization - N - size of A, N>0 - B - array[0..N-1], right part - -OUTPUT PARAMETERS - X - array[N], it contains: - * rep.terminationtype>0 => solution - * rep.terminationtype=-3 => filled by zeros - Rep - solver report, following fields are set: - * rep.terminationtype - solver status; >0 for success, - set to -3 on failure (degenerate system). - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -void sparselusolve(sparsematrix* a, - /* Integer */ ae_vector* p, - /* Integer */ ae_vector* q, - /* Real */ ae_vector* b, - /* Real */ ae_vector* x, - sparsesolverreport* rep, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - ae_int_t n; - - ae_vector_clear(x); - _sparsesolverreport_clear(rep); - - n = sparsegetnrows(a, _state); - ae_assert(n>0, "SparseLUSolve: N<=0", _state); - ae_assert(sparsegetnrows(a, _state)==n, "SparseLUSolve: rows(A)!=N", _state); - ae_assert(sparsegetncols(a, _state)==n, "SparseLUSolve: cols(A)!=N", _state); - ae_assert(sparseiscrs(a, _state), "SparseLUSolve: A is not an SKS matrix", _state); - ae_assert(b->cnt>=n, "SparseLUSolve: length(B)cnt>=n, "SparseLUSolve: length(P)cnt>=n, "SparseLUSolve: length(Q)ptr.p_int[i]>=i&&p->ptr.p_int[i]ptr.p_int[i]>=i&&q->ptr.p_int[i]didx.ptr.p_int[i]==a->uidx.ptr.p_int[i]||a->vals.ptr.p_double[a->didx.ptr.p_int[i]]==0.0 ) - { - rep->terminationtype = -3; - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = (double)(0); - } - return; - } - } - for(i=0; i<=n-1; i++) - { - x->ptr.p_double[i] = b->ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - j = p->ptr.p_int[i]; - v = x->ptr.p_double[i]; - x->ptr.p_double[i] = x->ptr.p_double[j]; - x->ptr.p_double[j] = v; - } - sparsetrsv(a, ae_false, ae_true, 0, x, _state); - sparsetrsv(a, ae_true, ae_false, 0, x, _state); - for(i=n-1; i>=0; i--) - { - j = q->ptr.p_int[i]; - v = x->ptr.p_double[i]; - x->ptr.p_double[i] = x->ptr.p_double[j]; - x->ptr.p_double[j] = v; - } - rep->terminationtype = 1; -} - - -/************************************************************************* -Reset report fields - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -static void directsparsesolvers_initreport(sparsesolverreport* rep, - ae_state *_state) -{ - - _sparsesolverreport_clear(rep); - - rep->terminationtype = 0; -} - - -void _sparsesolverreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - sparsesolverreport *p = (sparsesolverreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _sparsesolverreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - sparsesolverreport *dst = (sparsesolverreport*)_dst; - sparsesolverreport *src = (sparsesolverreport*)_src; - dst->terminationtype = src->terminationtype; -} - - -void _sparsesolverreport_clear(void* _p) -{ - sparsesolverreport *p = (sparsesolverreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _sparsesolverreport_destroy(void* _p) -{ - sparsesolverreport *p = (sparsesolverreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif -#if defined(AE_COMPILE_LINCG) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -This function initializes linear CG Solver. This solver is used to solve -symmetric positive definite problems. If you want to solve nonsymmetric -(or non-positive definite) problem you may use LinLSQR solver provided by -ALGLIB. - -USAGE: -1. User initializes algorithm state with LinCGCreate() call -2. User tunes solver parameters with LinCGSetCond() and other functions -3. Optionally, user sets starting point with LinCGSetStartingPoint() -4. User calls LinCGSolveSparse() function which takes algorithm state and - SparseMatrix object. -5. User calls LinCGResults() to get solution -6. Optionally, user may call LinCGSolveSparse() again to solve another - problem with different matrix and/or right part without reinitializing - LinCGState structure. - -INPUT PARAMETERS: - N - problem dimension, N>0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgcreate(ae_int_t n, lincgstate* state, ae_state *_state) -{ - ae_int_t i; - - _lincgstate_clear(state); - - ae_assert(n>0, "LinCGCreate: N<=0", _state); - state->n = n; - state->prectype = 0; - state->itsbeforerestart = n; - state->itsbeforerupdate = 10; - state->epsf = lincg_defaultprecision; - state->maxits = 0; - state->xrep = ae_false; - state->running = ae_false; - - /* - * * allocate arrays - * * set RX to NAN (just for the case user calls Results() without - * calling SolveSparse() - * * set starting point to zero - * * we do NOT initialize B here because we assume that user should - * initializate it using LinCGSetB() function. In case he forgets - * to do so, exception will be thrown in the LinCGIteration(). - */ - ae_vector_set_length(&state->rx, state->n, _state); - ae_vector_set_length(&state->startx, state->n, _state); - ae_vector_set_length(&state->b, state->n, _state); - for(i=0; i<=state->n-1; i++) - { - state->rx.ptr.p_double[i] = _state->v_nan; - state->startx.ptr.p_double[i] = 0.0; - state->b.ptr.p_double[i] = (double)(0); - } - ae_vector_set_length(&state->cx, state->n, _state); - ae_vector_set_length(&state->p, state->n, _state); - ae_vector_set_length(&state->r, state->n, _state); - ae_vector_set_length(&state->cr, state->n, _state); - ae_vector_set_length(&state->z, state->n, _state); - ae_vector_set_length(&state->cz, state->n, _state); - ae_vector_set_length(&state->x, state->n, _state); - ae_vector_set_length(&state->mv, state->n, _state); - ae_vector_set_length(&state->pv, state->n, _state); - lincg_updateitersdata(state, _state); - ae_vector_set_length(&state->rstate.ia, 0+1, _state); - ae_vector_set_length(&state->rstate.ra, 2+1, _state); - state->rstate.stage = -1; -} - - -/************************************************************************* -This function sets starting point. -By default, zero starting point is used. - -INPUT PARAMETERS: - X - starting point, array[N] - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgsetstartingpoint(lincgstate* state, - /* Real */ ae_vector* x, - ae_state *_state) -{ - - - ae_assert(!state->running, "LinCGSetStartingPoint: you can not change starting point because LinCGIteration() function is running", _state); - ae_assert(state->n<=x->cnt, "LinCGSetStartingPoint: Length(X)n, _state), "LinCGSetStartingPoint: X contains infinite or NaN values!", _state); - ae_v_move(&state->startx.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,state->n-1)); -} - - -/************************************************************************* -This function sets right part. By default, right part is zero. - -INPUT PARAMETERS: - B - right part, array[N]. - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgsetb(lincgstate* state, - /* Real */ ae_vector* b, - ae_state *_state) -{ - - - ae_assert(!state->running, "LinCGSetB: you can not set B, because function LinCGIteration is running!", _state); - ae_assert(b->cnt>=state->n, "LinCGSetB: Length(B)n, _state), "LinCGSetB: B contains infinite or NaN values!", _state); - ae_v_move(&state->b.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,state->n-1)); -} - - -/************************************************************************* -This function changes preconditioning settings of LinCGSolveSparse() -function. By default, SolveSparse() uses diagonal preconditioner, but if -you want to use solver without preconditioning, you can call this function -which forces solver to use unit matrix for preconditioning. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 19.11.2012 by Bochkanov Sergey -*************************************************************************/ -void lincgsetprecunit(lincgstate* state, ae_state *_state) -{ - - - ae_assert(!state->running, "LinCGSetPrecUnit: you can not change preconditioner, because function LinCGIteration is running!", _state); - state->prectype = -1; -} - - -/************************************************************************* -This function changes preconditioning settings of LinCGSolveSparse() -function. LinCGSolveSparse() will use diagonal of the system matrix as -preconditioner. This preconditioning mode is active by default. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 19.11.2012 by Bochkanov Sergey -*************************************************************************/ -void lincgsetprecdiag(lincgstate* state, ae_state *_state) -{ - - - ae_assert(!state->running, "LinCGSetPrecDiag: you can not change preconditioner, because function LinCGIteration is running!", _state); - state->prectype = 0; -} - - -/************************************************************************* -This function sets stopping criteria. - -INPUT PARAMETERS: - EpsF - algorithm will be stopped if norm of residual is less than - EpsF*||b||. - MaxIts - algorithm will be stopped if number of iterations is more - than MaxIts. - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -If both EpsF and MaxIts are zero then small EpsF will be set to small -value. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgsetcond(lincgstate* state, - double epsf, - ae_int_t maxits, - ae_state *_state) -{ - - - ae_assert(!state->running, "LinCGSetCond: you can not change stopping criteria when LinCGIteration() is running", _state); - ae_assert(ae_isfinite(epsf, _state)&&ae_fp_greater_eq(epsf,(double)(0)), "LinCGSetCond: EpsF is negative or contains infinite or NaN values", _state); - ae_assert(maxits>=0, "LinCGSetCond: MaxIts is negative", _state); - if( ae_fp_eq(epsf,(double)(0))&&maxits==0 ) - { - state->epsf = lincg_defaultprecision; - state->maxits = maxits; - } - else - { - state->epsf = epsf; - state->maxits = maxits; - } -} - - -/************************************************************************* -Reverse communication version of linear CG. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -ae_bool lincgiteration(lincgstate* state, ae_state *_state) -{ - ae_int_t i; - double uvar; - double bnorm; - double v; - ae_bool result; - - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( state->rstate.stage>=0 ) - { - i = state->rstate.ia.ptr.p_int[0]; - uvar = state->rstate.ra.ptr.p_double[0]; - bnorm = state->rstate.ra.ptr.p_double[1]; - v = state->rstate.ra.ptr.p_double[2]; - } - else - { - i = 359; - uvar = -58; - bnorm = -919; - v = -909; - } - if( state->rstate.stage==0 ) - { - goto lbl_0; - } - if( state->rstate.stage==1 ) - { - goto lbl_1; - } - if( state->rstate.stage==2 ) - { - goto lbl_2; - } - if( state->rstate.stage==3 ) - { - goto lbl_3; - } - if( state->rstate.stage==4 ) - { - goto lbl_4; - } - if( state->rstate.stage==5 ) - { - goto lbl_5; - } - if( state->rstate.stage==6 ) - { - goto lbl_6; - } - if( state->rstate.stage==7 ) - { - goto lbl_7; - } - - /* - * Routine body - */ - ae_assert(state->b.cnt>0, "LinCGIteration: B is not initialized (you must initialize B by LinCGSetB() call", _state); - state->running = ae_true; - state->repnmv = 0; - lincg_clearrfields(state, _state); - lincg_updateitersdata(state, _state); - - /* - * Start 0-th iteration - */ - ae_v_move(&state->rx.ptr.p_double[0], 1, &state->startx.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - ae_v_move(&state->x.ptr.p_double[0], 1, &state->rx.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - state->repnmv = state->repnmv+1; - lincg_clearrfields(state, _state); - state->needvmv = ae_true; - state->rstate.stage = 0; - goto lbl_rcomm; -lbl_0: - state->needvmv = ae_false; - bnorm = (double)(0); - state->r2 = (double)(0); - state->meritfunction = (double)(0); - for(i=0; i<=state->n-1; i++) - { - state->r.ptr.p_double[i] = state->b.ptr.p_double[i]-state->mv.ptr.p_double[i]; - state->r2 = state->r2+state->r.ptr.p_double[i]*state->r.ptr.p_double[i]; - state->meritfunction = state->meritfunction+state->mv.ptr.p_double[i]*state->rx.ptr.p_double[i]-2*state->b.ptr.p_double[i]*state->rx.ptr.p_double[i]; - bnorm = bnorm+state->b.ptr.p_double[i]*state->b.ptr.p_double[i]; - } - bnorm = ae_sqrt(bnorm, _state); - - /* - * Output first report - */ - if( !state->xrep ) - { - goto lbl_8; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->rx.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - lincg_clearrfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 1; - goto lbl_rcomm; -lbl_1: - state->xupdated = ae_false; -lbl_8: - - /* - * Is x0 a solution? - */ - if( !ae_isfinite(state->r2, _state)||ae_fp_less_eq(ae_sqrt(state->r2, _state),state->epsf*bnorm) ) - { - state->running = ae_false; - if( ae_isfinite(state->r2, _state) ) - { - state->repterminationtype = 1; - } - else - { - state->repterminationtype = -4; - } - result = ae_false; - return result; - } - - /* - * Calculate Z and P - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->r.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - state->repnmv = state->repnmv+1; - lincg_clearrfields(state, _state); - state->needprec = ae_true; - state->rstate.stage = 2; - goto lbl_rcomm; -lbl_2: - state->needprec = ae_false; - for(i=0; i<=state->n-1; i++) - { - state->z.ptr.p_double[i] = state->pv.ptr.p_double[i]; - state->p.ptr.p_double[i] = state->z.ptr.p_double[i]; - } - - /* - * Other iterations(1..N) - */ - state->repiterationscount = 0; -lbl_10: - if( ae_false ) - { - goto lbl_11; - } - state->repiterationscount = state->repiterationscount+1; - - /* - * Calculate Alpha - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->p.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - state->repnmv = state->repnmv+1; - lincg_clearrfields(state, _state); - state->needvmv = ae_true; - state->rstate.stage = 3; - goto lbl_rcomm; -lbl_3: - state->needvmv = ae_false; - if( !ae_isfinite(state->vmv, _state)||ae_fp_less_eq(state->vmv,(double)(0)) ) - { - - /* - * a) Overflow when calculating VMV - * b) non-positive VMV (non-SPD matrix) - */ - state->running = ae_false; - if( ae_isfinite(state->vmv, _state) ) - { - state->repterminationtype = -5; - } - else - { - state->repterminationtype = -4; - } - result = ae_false; - return result; - } - state->alpha = (double)(0); - for(i=0; i<=state->n-1; i++) - { - state->alpha = state->alpha+state->r.ptr.p_double[i]*state->z.ptr.p_double[i]; - } - state->alpha = state->alpha/state->vmv; - if( !ae_isfinite(state->alpha, _state) ) - { - - /* - * Overflow when calculating Alpha - */ - state->running = ae_false; - state->repterminationtype = -4; - result = ae_false; - return result; - } - - /* - * Next step toward solution - */ - for(i=0; i<=state->n-1; i++) - { - state->cx.ptr.p_double[i] = state->rx.ptr.p_double[i]+state->alpha*state->p.ptr.p_double[i]; - } - - /* - * Calculate R: - * * use recurrent relation to update R - * * at every ItsBeforeRUpdate-th iteration recalculate it from scratch, using matrix-vector product - * in case R grows instead of decreasing, algorithm is terminated with positive completion code - */ - if( !(state->itsbeforerupdate==0||state->repiterationscount%state->itsbeforerupdate!=0) ) - { - goto lbl_12; - } - - /* - * Calculate R using recurrent formula - */ - for(i=0; i<=state->n-1; i++) - { - state->cr.ptr.p_double[i] = state->r.ptr.p_double[i]-state->alpha*state->mv.ptr.p_double[i]; - state->x.ptr.p_double[i] = state->cr.ptr.p_double[i]; - } - goto lbl_13; -lbl_12: - - /* - * Calculate R using matrix-vector multiplication - */ - ae_v_move(&state->x.ptr.p_double[0], 1, &state->cx.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - state->repnmv = state->repnmv+1; - lincg_clearrfields(state, _state); - state->needmv = ae_true; - state->rstate.stage = 4; - goto lbl_rcomm; -lbl_4: - state->needmv = ae_false; - for(i=0; i<=state->n-1; i++) - { - state->cr.ptr.p_double[i] = state->b.ptr.p_double[i]-state->mv.ptr.p_double[i]; - state->x.ptr.p_double[i] = state->cr.ptr.p_double[i]; - } - - /* - * Calculating merit function - * Check emergency stopping criterion - */ - v = (double)(0); - for(i=0; i<=state->n-1; i++) - { - v = v+state->mv.ptr.p_double[i]*state->cx.ptr.p_double[i]-2*state->b.ptr.p_double[i]*state->cx.ptr.p_double[i]; - } - if( ae_fp_less(v,state->meritfunction) ) - { - goto lbl_14; - } - for(i=0; i<=state->n-1; i++) - { - if( !ae_isfinite(state->rx.ptr.p_double[i], _state) ) - { - state->running = ae_false; - state->repterminationtype = -4; - result = ae_false; - return result; - } - } - - /* - *output last report - */ - if( !state->xrep ) - { - goto lbl_16; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->rx.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - lincg_clearrfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 5; - goto lbl_rcomm; -lbl_5: - state->xupdated = ae_false; -lbl_16: - state->running = ae_false; - state->repterminationtype = 7; - result = ae_false; - return result; -lbl_14: - state->meritfunction = v; -lbl_13: - ae_v_move(&state->rx.ptr.p_double[0], 1, &state->cx.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - - /* - * calculating RNorm - * - * NOTE: monotonic decrease of R2 is not guaranteed by algorithm. - */ - state->r2 = (double)(0); - for(i=0; i<=state->n-1; i++) - { - state->r2 = state->r2+state->cr.ptr.p_double[i]*state->cr.ptr.p_double[i]; - } - - /* - *output report - */ - if( !state->xrep ) - { - goto lbl_18; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->rx.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - lincg_clearrfields(state, _state); - state->xupdated = ae_true; - state->rstate.stage = 6; - goto lbl_rcomm; -lbl_6: - state->xupdated = ae_false; -lbl_18: - - /* - *stopping criterion - *achieved the required precision - */ - if( !ae_isfinite(state->r2, _state)||ae_fp_less_eq(ae_sqrt(state->r2, _state),state->epsf*bnorm) ) - { - state->running = ae_false; - if( ae_isfinite(state->r2, _state) ) - { - state->repterminationtype = 1; - } - else - { - state->repterminationtype = -4; - } - result = ae_false; - return result; - } - if( state->repiterationscount>=state->maxits&&state->maxits>0 ) - { - for(i=0; i<=state->n-1; i++) - { - if( !ae_isfinite(state->rx.ptr.p_double[i], _state) ) - { - state->running = ae_false; - state->repterminationtype = -4; - result = ae_false; - return result; - } - } - - /* - *if X is finite number - */ - state->running = ae_false; - state->repterminationtype = 5; - result = ae_false; - return result; - } - ae_v_move(&state->x.ptr.p_double[0], 1, &state->cr.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - - /* - *prepere of parameters for next iteration - */ - state->repnmv = state->repnmv+1; - lincg_clearrfields(state, _state); - state->needprec = ae_true; - state->rstate.stage = 7; - goto lbl_rcomm; -lbl_7: - state->needprec = ae_false; - ae_v_move(&state->cz.ptr.p_double[0], 1, &state->pv.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - if( state->repiterationscount%state->itsbeforerestart!=0 ) - { - state->beta = (double)(0); - uvar = (double)(0); - for(i=0; i<=state->n-1; i++) - { - state->beta = state->beta+state->cz.ptr.p_double[i]*state->cr.ptr.p_double[i]; - uvar = uvar+state->z.ptr.p_double[i]*state->r.ptr.p_double[i]; - } - - /* - *check that UVar is't INF or is't zero - */ - if( !ae_isfinite(uvar, _state)||ae_fp_eq(uvar,(double)(0)) ) - { - state->running = ae_false; - state->repterminationtype = -4; - result = ae_false; - return result; - } - - /* - *calculate .BETA - */ - state->beta = state->beta/uvar; - - /* - *check that .BETA neither INF nor NaN - */ - if( !ae_isfinite(state->beta, _state) ) - { - state->running = ae_false; - state->repterminationtype = -1; - result = ae_false; - return result; - } - for(i=0; i<=state->n-1; i++) - { - state->p.ptr.p_double[i] = state->cz.ptr.p_double[i]+state->beta*state->p.ptr.p_double[i]; - } - } - else - { - ae_v_move(&state->p.ptr.p_double[0], 1, &state->cz.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - } - - /* - *prepere data for next iteration - */ - for(i=0; i<=state->n-1; i++) - { - - /* - *write (k+1)th iteration to (k )th iteration - */ - state->r.ptr.p_double[i] = state->cr.ptr.p_double[i]; - state->z.ptr.p_double[i] = state->cz.ptr.p_double[i]; - } - goto lbl_10; -lbl_11: - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - state->rstate.ia.ptr.p_int[0] = i; - state->rstate.ra.ptr.p_double[0] = uvar; - state->rstate.ra.ptr.p_double[1] = bnorm; - state->rstate.ra.ptr.p_double[2] = v; - return result; -} - - -/************************************************************************* -Procedure for solution of A*x=b with sparse A. - -INPUT PARAMETERS: - State - algorithm state - A - sparse matrix in the CRS format (you MUST contvert it to - CRS format by calling SparseConvertToCRS() function). - IsUpper - whether upper or lower triangle of A is used: - * IsUpper=True => only upper triangle is used and lower - triangle is not referenced at all - * IsUpper=False => only lower triangle is used and upper - triangle is not referenced at all - B - right part, array[N] - -RESULT: - This function returns no result. - You can get solution by calling LinCGResults() - -NOTE: this function uses lightweight preconditioning - multiplication by - inverse of diag(A). If you want, you can turn preconditioning off by - calling LinCGSetPrecUnit(). However, preconditioning cost is low and - preconditioner is very important for solution of badly scaled - problems. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgsolvesparse(lincgstate* state, - sparsematrix* a, - ae_bool isupper, - /* Real */ ae_vector* b, - ae_state *_state) -{ - ae_int_t n; - ae_int_t i; - double v; - double vmv; - - - n = state->n; - ae_assert(b->cnt>=state->n, "LinCGSetB: Length(B)n, _state), "LinCGSetB: B contains infinite or NaN values!", _state); - - /* - * Allocate temporaries - */ - rvectorsetlengthatleast(&state->tmpd, n, _state); - - /* - * Compute diagonal scaling matrix D - */ - if( state->prectype==0 ) - { - - /* - * Default preconditioner - inverse of matrix diagonal - */ - for(i=0; i<=n-1; i++) - { - v = sparsegetdiagonal(a, i, _state); - if( ae_fp_greater(v,(double)(0)) ) - { - state->tmpd.ptr.p_double[i] = 1/ae_sqrt(v, _state); - } - else - { - state->tmpd.ptr.p_double[i] = (double)(1); - } - } - } - else - { - - /* - * No diagonal scaling - */ - for(i=0; i<=n-1; i++) - { - state->tmpd.ptr.p_double[i] = (double)(1); - } - } - - /* - * Solve - */ - lincgrestart(state, _state); - lincgsetb(state, b, _state); - while(lincgiteration(state, _state)) - { - - /* - * Process different requests from optimizer - */ - if( state->needmv ) - { - sparsesmv(a, isupper, &state->x, &state->mv, _state); - } - if( state->needvmv ) - { - sparsesmv(a, isupper, &state->x, &state->mv, _state); - vmv = ae_v_dotproduct(&state->x.ptr.p_double[0], 1, &state->mv.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - state->vmv = vmv; - } - if( state->needprec ) - { - for(i=0; i<=n-1; i++) - { - state->pv.ptr.p_double[i] = state->x.ptr.p_double[i]*ae_sqr(state->tmpd.ptr.p_double[i], _state); - } - } - } -} - - -/************************************************************************* -CG-solver: results. - -This function must be called after LinCGSolve - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[N], solution - Rep - optimization report: - * Rep.TerminationType completetion code: - * -5 input matrix is either not positive definite, - too large or too small - * -4 overflow/underflow during solution - (ill conditioned problem) - * 1 ||residual||<=EpsF*||b|| - * 5 MaxIts steps was taken - * 7 rounding errors prevent further progress, - best point found is returned - * Rep.IterationsCount contains iterations count - * NMV countains number of matrix-vector calculations - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgresults(lincgstate* state, - /* Real */ ae_vector* x, - lincgreport* rep, - ae_state *_state) -{ - - ae_vector_clear(x); - _lincgreport_clear(rep); - - ae_assert(!state->running, "LinCGResult: you can not get result, because function LinCGIteration has been launched!", _state); - if( x->cntn ) - { - ae_vector_set_length(x, state->n, _state); - } - ae_v_move(&x->ptr.p_double[0], 1, &state->rx.ptr.p_double[0], 1, ae_v_len(0,state->n-1)); - rep->iterationscount = state->repiterationscount; - rep->nmv = state->repnmv; - rep->terminationtype = state->repterminationtype; - rep->r2 = state->r2; -} - - -/************************************************************************* -This function sets restart frequency. By default, algorithm is restarted -after N subsequent iterations. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgsetrestartfreq(lincgstate* state, - ae_int_t srf, - ae_state *_state) -{ - - - ae_assert(!state->running, "LinCGSetRestartFreq: you can not change restart frequency when LinCGIteration() is running", _state); - ae_assert(srf>0, "LinCGSetRestartFreq: non-positive SRF", _state); - state->itsbeforerestart = srf; -} - - -/************************************************************************* -This function sets frequency of residual recalculations. - -Algorithm updates residual r_k using iterative formula, but recalculates -it from scratch after each 10 iterations. It is done to avoid accumulation -of numerical errors and to stop algorithm when r_k starts to grow. - -Such low update frequence (1/10) gives very little overhead, but makes -algorithm a bit more robust against numerical errors. However, you may -change it - -INPUT PARAMETERS: - Freq - desired update frequency, Freq>=0. - Zero value means that no updates will be done. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgsetrupdatefreq(lincgstate* state, - ae_int_t freq, - ae_state *_state) -{ - - - ae_assert(!state->running, "LinCGSetRUpdateFreq: you can not change update frequency when LinCGIteration() is running", _state); - ae_assert(freq>=0, "LinCGSetRUpdateFreq: non-positive Freq", _state); - state->itsbeforerupdate = freq; -} - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinCGOptimize(). - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgsetxrep(lincgstate* state, ae_bool needxrep, ae_state *_state) -{ - - - state->xrep = needxrep; -} - - -/************************************************************************* -Procedure for restart function LinCGIteration - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgrestart(lincgstate* state, ae_state *_state) -{ - - - ae_vector_set_length(&state->rstate.ia, 0+1, _state); - ae_vector_set_length(&state->rstate.ra, 2+1, _state); - state->rstate.stage = -1; - lincg_clearrfields(state, _state); -} - - -/************************************************************************* -Clears request fileds (to be sure that we don't forgot to clear something) -*************************************************************************/ -static void lincg_clearrfields(lincgstate* state, ae_state *_state) -{ - - - state->xupdated = ae_false; - state->needmv = ae_false; - state->needmtv = ae_false; - state->needmv2 = ae_false; - state->needvmv = ae_false; - state->needprec = ae_false; -} - - -/************************************************************************* -Clears request fileds (to be sure that we don't forgot to clear something) -*************************************************************************/ -static void lincg_updateitersdata(lincgstate* state, ae_state *_state) -{ - - - state->repiterationscount = 0; - state->repnmv = 0; - state->repterminationtype = 0; -} - - -void _lincgstate_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - lincgstate *p = (lincgstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->rx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->b, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cr, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->cz, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->p, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->r, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->z, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->mv, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->pv, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->startx, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->tmpd, 0, DT_REAL, _state, make_automatic); - _rcommstate_init(&p->rstate, _state, make_automatic); -} - - -void _lincgstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - lincgstate *dst = (lincgstate*)_dst; - lincgstate *src = (lincgstate*)_src; - ae_vector_init_copy(&dst->rx, &src->rx, _state, make_automatic); - ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic); - dst->n = src->n; - dst->prectype = src->prectype; - ae_vector_init_copy(&dst->cx, &src->cx, _state, make_automatic); - ae_vector_init_copy(&dst->cr, &src->cr, _state, make_automatic); - ae_vector_init_copy(&dst->cz, &src->cz, _state, make_automatic); - ae_vector_init_copy(&dst->p, &src->p, _state, make_automatic); - ae_vector_init_copy(&dst->r, &src->r, _state, make_automatic); - ae_vector_init_copy(&dst->z, &src->z, _state, make_automatic); - dst->alpha = src->alpha; - dst->beta = src->beta; - dst->r2 = src->r2; - dst->meritfunction = src->meritfunction; - ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic); - ae_vector_init_copy(&dst->mv, &src->mv, _state, make_automatic); - ae_vector_init_copy(&dst->pv, &src->pv, _state, make_automatic); - dst->vmv = src->vmv; - ae_vector_init_copy(&dst->startx, &src->startx, _state, make_automatic); - dst->epsf = src->epsf; - dst->maxits = src->maxits; - dst->itsbeforerestart = src->itsbeforerestart; - dst->itsbeforerupdate = src->itsbeforerupdate; - dst->xrep = src->xrep; - dst->xupdated = src->xupdated; - dst->needmv = src->needmv; - dst->needmtv = src->needmtv; - dst->needmv2 = src->needmv2; - dst->needvmv = src->needvmv; - dst->needprec = src->needprec; - dst->repiterationscount = src->repiterationscount; - dst->repnmv = src->repnmv; - dst->repterminationtype = src->repterminationtype; - dst->running = src->running; - ae_vector_init_copy(&dst->tmpd, &src->tmpd, _state, make_automatic); - _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic); -} - - -void _lincgstate_clear(void* _p) -{ - lincgstate *p = (lincgstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->rx); - ae_vector_clear(&p->b); - ae_vector_clear(&p->cx); - ae_vector_clear(&p->cr); - ae_vector_clear(&p->cz); - ae_vector_clear(&p->p); - ae_vector_clear(&p->r); - ae_vector_clear(&p->z); - ae_vector_clear(&p->x); - ae_vector_clear(&p->mv); - ae_vector_clear(&p->pv); - ae_vector_clear(&p->startx); - ae_vector_clear(&p->tmpd); - _rcommstate_clear(&p->rstate); -} - - -void _lincgstate_destroy(void* _p) -{ - lincgstate *p = (lincgstate*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->rx); - ae_vector_destroy(&p->b); - ae_vector_destroy(&p->cx); - ae_vector_destroy(&p->cr); - ae_vector_destroy(&p->cz); - ae_vector_destroy(&p->p); - ae_vector_destroy(&p->r); - ae_vector_destroy(&p->z); - ae_vector_destroy(&p->x); - ae_vector_destroy(&p->mv); - ae_vector_destroy(&p->pv); - ae_vector_destroy(&p->startx); - ae_vector_destroy(&p->tmpd); - _rcommstate_destroy(&p->rstate); -} - - -void _lincgreport_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - lincgreport *p = (lincgreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _lincgreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - lincgreport *dst = (lincgreport*)_dst; - lincgreport *src = (lincgreport*)_src; - dst->iterationscount = src->iterationscount; - dst->nmv = src->nmv; - dst->terminationtype = src->terminationtype; - dst->r2 = src->r2; -} - - -void _lincgreport_clear(void* _p) -{ - lincgreport *p = (lincgreport*)_p; - ae_touch_ptr((void*)p); -} - - -void _lincgreport_destroy(void* _p) -{ - lincgreport *p = (lincgreport*)_p; - ae_touch_ptr((void*)p); -} - - -#endif - -} - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/solvers.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/solvers.h deleted file mode 100644 index 0c7f788..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/solvers.h +++ /dev/null @@ -1,3746 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifndef _solvers_pkg_h -#define _solvers_pkg_h -#include "ap.h" -#include "alglibinternal.h" -#include "alglibmisc.h" -#include "linalg.h" - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (DATATYPES) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_DIRECTDENSESOLVERS) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - double r1; - double rinf; -} densesolverreport; -typedef struct -{ - double r2; - ae_matrix cx; - ae_int_t n; - ae_int_t k; -} densesolverlsreport; -#endif -#if defined(AE_COMPILE_LINLSQR) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - normestimatorstate nes; - ae_vector rx; - ae_vector b; - ae_int_t n; - ae_int_t m; - ae_int_t prectype; - ae_vector ui; - ae_vector uip1; - ae_vector vi; - ae_vector vip1; - ae_vector omegai; - ae_vector omegaip1; - double alphai; - double alphaip1; - double betai; - double betaip1; - double phibari; - double phibarip1; - double phii; - double rhobari; - double rhobarip1; - double rhoi; - double ci; - double si; - double theta; - double lambdai; - ae_vector d; - double anorm; - double bnorm2; - double dnorm; - double r2; - ae_vector x; - ae_vector mv; - ae_vector mtv; - double epsa; - double epsb; - double epsc; - ae_int_t maxits; - ae_bool xrep; - ae_bool xupdated; - ae_bool needmv; - ae_bool needmtv; - ae_bool needmv2; - ae_bool needvmv; - ae_bool needprec; - ae_int_t repiterationscount; - ae_int_t repnmv; - ae_int_t repterminationtype; - ae_bool running; - ae_bool userterminationneeded; - ae_vector tmpd; - ae_vector tmpx; - rcommstate rstate; -} linlsqrstate; -typedef struct -{ - ae_int_t iterationscount; - ae_int_t nmv; - ae_int_t terminationtype; -} linlsqrreport; -#endif -#if defined(AE_COMPILE_POLYNOMIALSOLVER) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - double maxerr; -} polynomialsolverreport; -#endif -#if defined(AE_COMPILE_NLEQ) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t n; - ae_int_t m; - double epsf; - ae_int_t maxits; - ae_bool xrep; - double stpmax; - ae_vector x; - double f; - ae_vector fi; - ae_matrix j; - ae_bool needf; - ae_bool needfij; - ae_bool xupdated; - rcommstate rstate; - ae_int_t repiterationscount; - ae_int_t repnfunc; - ae_int_t repnjac; - ae_int_t repterminationtype; - ae_vector xbase; - double fbase; - double fprev; - ae_vector candstep; - ae_vector rightpart; - ae_vector cgbuf; -} nleqstate; -typedef struct -{ - ae_int_t iterationscount; - ae_int_t nfunc; - ae_int_t njac; - ae_int_t terminationtype; -} nleqreport; -#endif -#if defined(AE_COMPILE_DIRECTSPARSESOLVERS) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_int_t terminationtype; -} sparsesolverreport; -#endif -#if defined(AE_COMPILE_LINCG) || !defined(AE_PARTIAL_BUILD) -typedef struct -{ - ae_vector rx; - ae_vector b; - ae_int_t n; - ae_int_t prectype; - ae_vector cx; - ae_vector cr; - ae_vector cz; - ae_vector p; - ae_vector r; - ae_vector z; - double alpha; - double beta; - double r2; - double meritfunction; - ae_vector x; - ae_vector mv; - ae_vector pv; - double vmv; - ae_vector startx; - double epsf; - ae_int_t maxits; - ae_int_t itsbeforerestart; - ae_int_t itsbeforerupdate; - ae_bool xrep; - ae_bool xupdated; - ae_bool needmv; - ae_bool needmtv; - ae_bool needmv2; - ae_bool needvmv; - ae_bool needprec; - ae_int_t repiterationscount; - ae_int_t repnmv; - ae_int_t repterminationtype; - ae_bool running; - ae_vector tmpd; - rcommstate rstate; -} lincgstate; -typedef struct -{ - ae_int_t iterationscount; - ae_int_t nmv; - ae_int_t terminationtype; - double r2; -} lincgreport; -#endif - -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_DIRECTDENSESOLVERS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - -*************************************************************************/ -class _densesolverreport_owner -{ -public: - _densesolverreport_owner(); - _densesolverreport_owner(const _densesolverreport_owner &rhs); - _densesolverreport_owner& operator=(const _densesolverreport_owner &rhs); - virtual ~_densesolverreport_owner(); - alglib_impl::densesolverreport* c_ptr(); - alglib_impl::densesolverreport* c_ptr() const; -protected: - alglib_impl::densesolverreport *p_struct; -}; -class densesolverreport : public _densesolverreport_owner -{ -public: - densesolverreport(); - densesolverreport(const densesolverreport &rhs); - densesolverreport& operator=(const densesolverreport &rhs); - virtual ~densesolverreport(); - double &r1; - double &rinf; - -}; - - -/************************************************************************* - -*************************************************************************/ -class _densesolverlsreport_owner -{ -public: - _densesolverlsreport_owner(); - _densesolverlsreport_owner(const _densesolverlsreport_owner &rhs); - _densesolverlsreport_owner& operator=(const _densesolverlsreport_owner &rhs); - virtual ~_densesolverlsreport_owner(); - alglib_impl::densesolverlsreport* c_ptr(); - alglib_impl::densesolverlsreport* c_ptr() const; -protected: - alglib_impl::densesolverlsreport *p_struct; -}; -class densesolverlsreport : public _densesolverlsreport_owner -{ -public: - densesolverlsreport(); - densesolverlsreport(const densesolverlsreport &rhs); - densesolverlsreport& operator=(const densesolverlsreport &rhs); - virtual ~densesolverlsreport(); - double &r2; - real_2d_array cx; - ae_int_t &n; - ae_int_t &k; - -}; -#endif - -#if defined(AE_COMPILE_LINLSQR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores state of the LinLSQR method. - -You should use ALGLIB functions to work with this object. -*************************************************************************/ -class _linlsqrstate_owner -{ -public: - _linlsqrstate_owner(); - _linlsqrstate_owner(const _linlsqrstate_owner &rhs); - _linlsqrstate_owner& operator=(const _linlsqrstate_owner &rhs); - virtual ~_linlsqrstate_owner(); - alglib_impl::linlsqrstate* c_ptr(); - alglib_impl::linlsqrstate* c_ptr() const; -protected: - alglib_impl::linlsqrstate *p_struct; -}; -class linlsqrstate : public _linlsqrstate_owner -{ -public: - linlsqrstate(); - linlsqrstate(const linlsqrstate &rhs); - linlsqrstate& operator=(const linlsqrstate &rhs); - virtual ~linlsqrstate(); - -}; - - -/************************************************************************* - -*************************************************************************/ -class _linlsqrreport_owner -{ -public: - _linlsqrreport_owner(); - _linlsqrreport_owner(const _linlsqrreport_owner &rhs); - _linlsqrreport_owner& operator=(const _linlsqrreport_owner &rhs); - virtual ~_linlsqrreport_owner(); - alglib_impl::linlsqrreport* c_ptr(); - alglib_impl::linlsqrreport* c_ptr() const; -protected: - alglib_impl::linlsqrreport *p_struct; -}; -class linlsqrreport : public _linlsqrreport_owner -{ -public: - linlsqrreport(); - linlsqrreport(const linlsqrreport &rhs); - linlsqrreport& operator=(const linlsqrreport &rhs); - virtual ~linlsqrreport(); - ae_int_t &iterationscount; - ae_int_t &nmv; - ae_int_t &terminationtype; - -}; -#endif - -#if defined(AE_COMPILE_POLYNOMIALSOLVER) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - -*************************************************************************/ -class _polynomialsolverreport_owner -{ -public: - _polynomialsolverreport_owner(); - _polynomialsolverreport_owner(const _polynomialsolverreport_owner &rhs); - _polynomialsolverreport_owner& operator=(const _polynomialsolverreport_owner &rhs); - virtual ~_polynomialsolverreport_owner(); - alglib_impl::polynomialsolverreport* c_ptr(); - alglib_impl::polynomialsolverreport* c_ptr() const; -protected: - alglib_impl::polynomialsolverreport *p_struct; -}; -class polynomialsolverreport : public _polynomialsolverreport_owner -{ -public: - polynomialsolverreport(); - polynomialsolverreport(const polynomialsolverreport &rhs); - polynomialsolverreport& operator=(const polynomialsolverreport &rhs); - virtual ~polynomialsolverreport(); - double &maxerr; - -}; -#endif - -#if defined(AE_COMPILE_NLEQ) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - -*************************************************************************/ -class _nleqstate_owner -{ -public: - _nleqstate_owner(); - _nleqstate_owner(const _nleqstate_owner &rhs); - _nleqstate_owner& operator=(const _nleqstate_owner &rhs); - virtual ~_nleqstate_owner(); - alglib_impl::nleqstate* c_ptr(); - alglib_impl::nleqstate* c_ptr() const; -protected: - alglib_impl::nleqstate *p_struct; -}; -class nleqstate : public _nleqstate_owner -{ -public: - nleqstate(); - nleqstate(const nleqstate &rhs); - nleqstate& operator=(const nleqstate &rhs); - virtual ~nleqstate(); - ae_bool &needf; - ae_bool &needfij; - ae_bool &xupdated; - double &f; - real_1d_array fi; - real_2d_array j; - real_1d_array x; - -}; - - -/************************************************************************* - -*************************************************************************/ -class _nleqreport_owner -{ -public: - _nleqreport_owner(); - _nleqreport_owner(const _nleqreport_owner &rhs); - _nleqreport_owner& operator=(const _nleqreport_owner &rhs); - virtual ~_nleqreport_owner(); - alglib_impl::nleqreport* c_ptr(); - alglib_impl::nleqreport* c_ptr() const; -protected: - alglib_impl::nleqreport *p_struct; -}; -class nleqreport : public _nleqreport_owner -{ -public: - nleqreport(); - nleqreport(const nleqreport &rhs); - nleqreport& operator=(const nleqreport &rhs); - virtual ~nleqreport(); - ae_int_t &iterationscount; - ae_int_t &nfunc; - ae_int_t &njac; - ae_int_t &terminationtype; - -}; -#endif - -#if defined(AE_COMPILE_DIRECTSPARSESOLVERS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This structure is a sparse solver report. - -Following fields can be accessed by users: -*************************************************************************/ -class _sparsesolverreport_owner -{ -public: - _sparsesolverreport_owner(); - _sparsesolverreport_owner(const _sparsesolverreport_owner &rhs); - _sparsesolverreport_owner& operator=(const _sparsesolverreport_owner &rhs); - virtual ~_sparsesolverreport_owner(); - alglib_impl::sparsesolverreport* c_ptr(); - alglib_impl::sparsesolverreport* c_ptr() const; -protected: - alglib_impl::sparsesolverreport *p_struct; -}; -class sparsesolverreport : public _sparsesolverreport_owner -{ -public: - sparsesolverreport(); - sparsesolverreport(const sparsesolverreport &rhs); - sparsesolverreport& operator=(const sparsesolverreport &rhs); - virtual ~sparsesolverreport(); - ae_int_t &terminationtype; - -}; -#endif - -#if defined(AE_COMPILE_LINCG) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This object stores state of the linear CG method. - -You should use ALGLIB functions to work with this object. -Never try to access its fields directly! -*************************************************************************/ -class _lincgstate_owner -{ -public: - _lincgstate_owner(); - _lincgstate_owner(const _lincgstate_owner &rhs); - _lincgstate_owner& operator=(const _lincgstate_owner &rhs); - virtual ~_lincgstate_owner(); - alglib_impl::lincgstate* c_ptr(); - alglib_impl::lincgstate* c_ptr() const; -protected: - alglib_impl::lincgstate *p_struct; -}; -class lincgstate : public _lincgstate_owner -{ -public: - lincgstate(); - lincgstate(const lincgstate &rhs); - lincgstate& operator=(const lincgstate &rhs); - virtual ~lincgstate(); - -}; - - -/************************************************************************* - -*************************************************************************/ -class _lincgreport_owner -{ -public: - _lincgreport_owner(); - _lincgreport_owner(const _lincgreport_owner &rhs); - _lincgreport_owner& operator=(const _lincgreport_owner &rhs); - virtual ~_lincgreport_owner(); - alglib_impl::lincgreport* c_ptr(); - alglib_impl::lincgreport* c_ptr() const; -protected: - alglib_impl::lincgreport *p_struct; -}; -class lincgreport : public _lincgreport_owner -{ -public: - lincgreport(); - lincgreport(const lincgreport &rhs); - lincgreport& operator=(const lincgreport &rhs); - virtual ~lincgreport(); - ae_int_t &iterationscount; - ae_int_t &nmv; - ae_int_t &terminationtype; - double &r2; - -}; -#endif - -#if defined(AE_COMPILE_DIRECTDENSESOLVERS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Dense solver for A*x=b with N*N real matrix A and N*1 real vectorx x and -b. This is "slow-but-feature rich" version of the linear solver. Faster -version is RMatrixSolveFast() function. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(N^3) complexity - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system - ! and performs iterative refinement, which results in - ! significant performance penalty when compared with "fast" - ! version which just performs LU decomposition and calls - ! triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. It is also very significant on small matrices. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, RMatrixSolveFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixsolve(const real_2d_array &a, const ae_int_t n, const real_1d_array &b, ae_int_t &info, densesolverreport &rep, real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver. - -This subroutine solves a system A*x=b, where A is NxN non-denegerate -real matrix, x and b are vectors. This is a "fast" version of linear -solver which does NOT provide any additional functions like condition -number estimation or iterative refinement. - -Algorithm features: -* efficient algorithm O(N^3) complexity -* no performance overhead from additional functionality - -If you need condition number estimation or iterative refinement, use more -feature-rich version - RMatrixSolve(). - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 16.03.2015 by Bochkanov Sergey -*************************************************************************/ -void rmatrixsolvefast(const real_2d_array &a, const ae_int_t n, const real_1d_array &b, ae_int_t &info, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver. - -Similar to RMatrixSolve() but solves task with multiple right parts (where -b and x are NxM matrices). This is "slow-but-robust" version of linear -solver with additional functionality like condition number estimation. -There also exists faster version - RMatrixSolveMFast(). - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* optional iterative refinement -* O(N^3+M*N^2) complexity - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system - ! and performs iterative refinement, which results in - ! significant performance penalty when compared with "fast" - ! version which just performs LU decomposition and calls - ! triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. It also very significant on small matrices. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, RMatrixSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - RFS - iterative refinement switch: - * True - refinement is used. - Less performance, more precision. - * False - refinement is not used. - More performance, less precision. - -OUTPUT PARAMETERS - Info - return code: - * -3 A is ill conditioned or singular. - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixsolvem(const real_2d_array &a, const ae_int_t n, const real_2d_array &b, const ae_int_t m, const bool rfs, ae_int_t &info, densesolverreport &rep, real_2d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver. - -Similar to RMatrixSolve() but solves task with multiple right parts (where -b and x are NxM matrices). This is "fast" version of linear solver which -does NOT offer additional functions like condition number estimation or -iterative refinement. - -Algorithm features: -* O(N^3+M*N^2) complexity -* no additional functionality, highest performance - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - RFS - iterative refinement switch: - * True - refinement is used. - Less performance, more precision. - * False - refinement is not used. - More performance, less precision. - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - B - array[N]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixsolvemfast(const real_2d_array &a, const ae_int_t n, const real_2d_array &b, const ae_int_t m, ae_int_t &info, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver. - -This subroutine solves a system A*x=b, where A is NxN non-denegerate -real matrix given by its LU decomposition, x and b are real vectors. This -is "slow-but-robust" version of the linear LU-based solver. Faster version -is RMatrixLUSolveFast() function. - -Algorithm features: -* automatic detection of degenerate cases -* O(N^2) complexity -* condition number estimation - -No iterative refinement is provided because exact form of original matrix -is not known to subroutine. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in 10-15x performance penalty when compared - ! with "fast" version which just calls triangular solver. - ! - ! This performance penalty is insignificant when compared with - ! cost of large LU decomposition. However, if you call this - ! function many times for the same left side, this overhead - ! BECOMES significant. It also becomes significant for small- - ! scale problems. - ! - ! In such cases we strongly recommend you to use faster solver, - ! RMatrixLUSolveFast() function. - -INPUT PARAMETERS - LUA - array[N,N], LU decomposition, RMatrixLU result - P - array[N], pivots array, RMatrixLU result - N - size of A - B - array[N], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixlusolve(const real_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const real_1d_array &b, ae_int_t &info, densesolverreport &rep, real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver. - -This subroutine solves a system A*x=b, where A is NxN non-denegerate -real matrix given by its LU decomposition, x and b are real vectors. This -is "fast-without-any-checks" version of the linear LU-based solver. Slower -but more robust version is RMatrixLUSolve() function. - -Algorithm features: -* O(N^2) complexity -* fast algorithm without ANY additional checks, just triangular solver - -INPUT PARAMETERS - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 18.03.2015 by Bochkanov Sergey -*************************************************************************/ -void rmatrixlusolvefast(const real_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const real_1d_array &b, ae_int_t &info, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver. - -Similar to RMatrixLUSolve() but solves task with multiple right parts -(where b and x are NxM matrices). This is "robust-but-slow" version of -LU-based solver which performs additional checks for non-degeneracy of -inputs (condition number estimation). If you need best performance, use -"fast-without-any-checks" version, RMatrixLUSolveMFast(). - -Algorithm features: -* automatic detection of degenerate cases -* O(M*N^2) complexity -* condition number estimation - -No iterative refinement is provided because exact form of original matrix -is not known to subroutine. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just calls triangular - ! solver. - ! - ! This performance penalty is especially apparent when you use - ! ALGLIB parallel capabilities (condition number estimation is - ! inherently sequential). It also becomes significant for - ! small-scale problems. - ! - ! In such cases we strongly recommend you to use faster solver, - ! RMatrixLUSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - LUA - array[N,N], LU decomposition, RMatrixLU result - P - array[N], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixlusolvem(const real_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const real_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, real_2d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver. - -Similar to RMatrixLUSolve() but solves task with multiple right parts, -where b and x are NxM matrices. This is "fast-without-any-checks" version -of LU-based solver. It does not estimate condition number of a system, -so it is extremely fast. If you need better detection of near-degenerate -cases, use RMatrixLUSolveM() function. - -Algorithm features: -* O(M*N^2) complexity -* fast algorithm without ANY additional checks, just triangular solver - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS: - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N,M]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 18.03.2015 by Bochkanov Sergey -*************************************************************************/ -void rmatrixlusolvemfast(const real_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const real_2d_array &b, const ae_int_t m, ae_int_t &info, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver. - -This subroutine solves a system A*x=b, where BOTH ORIGINAL A AND ITS -LU DECOMPOSITION ARE KNOWN. You can use it if for some reasons you have -both A and its LU decomposition. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(N^2) complexity - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixmixedsolve(const real_2d_array &a, const real_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const real_1d_array &b, ae_int_t &info, densesolverreport &rep, real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver. - -Similar to RMatrixMixedSolve() but solves task with multiple right parts -(where b and x are NxM matrices). - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(M*N^2) complexity - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void rmatrixmixedsolvem(const real_2d_array &a, const real_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const real_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, real_2d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Complex dense solver for A*X=B with N*N complex matrix A, N*M complex -matrices X and B. "Slow-but-feature-rich" version which provides -additional functions, at the cost of slower performance. Faster version -may be invoked with CMatrixSolveMFast() function. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(N^3+M*N^2) complexity - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system - ! and performs iterative refinement, which results in - ! significant performance penalty when compared with "fast" - ! version which just performs LU decomposition and calls - ! triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, CMatrixSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - RFS - iterative refinement switch: - * True - refinement is used. - Less performance, more precision. - * False - refinement is not used. - More performance, less precision. - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixsolvem(const complex_2d_array &a, const ae_int_t n, const complex_2d_array &b, const ae_int_t m, const bool rfs, ae_int_t &info, densesolverreport &rep, complex_2d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Complex dense solver for A*X=B with N*N complex matrix A, N*M complex -matrices X and B. "Fast-but-lightweight" version which provides just -triangular solver - and no additional functions like iterative refinement -or condition number estimation. - -Algorithm features: -* O(N^3+M*N^2) complexity -* no additional time consuming functions - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS: - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N,M]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 16.03.2015 by Bochkanov Sergey -*************************************************************************/ -void cmatrixsolvemfast(const complex_2d_array &a, const ae_int_t n, const complex_2d_array &b, const ae_int_t m, ae_int_t &info, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Complex dense solver for A*x=B with N*N complex matrix A and N*1 complex -vectors x and b. "Slow-but-feature-rich" version of the solver. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(N^3) complexity - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system - ! and performs iterative refinement, which results in - ! significant performance penalty when compared with "fast" - ! version which just performs LU decomposition and calls - ! triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, CMatrixSolveFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixsolve(const complex_2d_array &a, const ae_int_t n, const complex_1d_array &b, ae_int_t &info, densesolverreport &rep, complex_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Complex dense solver for A*x=B with N*N complex matrix A and N*1 complex -vectors x and b. "Fast-but-lightweight" version of the solver. - -Algorithm features: -* O(N^3) complexity -* no additional time consuming features, just triangular solver - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - A - array[0..N-1,0..N-1], system matrix - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS: - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixsolvefast(const complex_2d_array &a, const ae_int_t n, const complex_1d_array &b, ae_int_t &info, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver for A*X=B with N*N complex A given by its LU decomposition, -and N*M matrices X and B (multiple right sides). "Slow-but-feature-rich" -version of the solver. - -Algorithm features: -* automatic detection of degenerate cases -* O(M*N^2) complexity -* condition number estimation - -No iterative refinement is provided because exact form of original matrix -is not known to subroutine. Use CMatrixSolve or CMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just calls triangular - ! solver. - ! - ! This performance penalty is especially apparent when you use - ! ALGLIB parallel capabilities (condition number estimation is - ! inherently sequential). It also becomes significant for - ! small-scale problems. - ! - ! In such cases we strongly recommend you to use faster solver, - ! CMatrixLUSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixlusolvem(const complex_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const complex_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, complex_2d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver for A*X=B with N*N complex A given by its LU decomposition, -and N*M matrices X and B (multiple right sides). "Fast-but-lightweight" -version of the solver. - -Algorithm features: -* O(M*N^2) complexity -* no additional time-consuming features - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU result - P - array[0..N-1], pivots array, RMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N,M]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixlusolvemfast(const complex_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const complex_2d_array &b, const ae_int_t m, ae_int_t &info, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Complex dense linear solver for A*x=b with complex N*N A given by its LU -decomposition and N*1 vectors x and b. This is "slow-but-robust" version -of the complex linear solver with additional features which add -significant performance overhead. Faster version is CMatrixLUSolveFast() -function. - -Algorithm features: -* automatic detection of degenerate cases -* O(N^2) complexity -* condition number estimation - -No iterative refinement is provided because exact form of original matrix -is not known to subroutine. Use CMatrixSolve or CMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in 10-15x performance penalty when compared - ! with "fast" version which just calls triangular solver. - ! - ! This performance penalty is insignificant when compared with - ! cost of large LU decomposition. However, if you call this - ! function many times for the same left side, this overhead - ! BECOMES significant. It also becomes significant for small- - ! scale problems. - ! - ! In such cases we strongly recommend you to use faster solver, - ! CMatrixLUSolveFast() function. - -INPUT PARAMETERS - LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU result - P - array[0..N-1], pivots array, CMatrixLU result - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixlusolve(const complex_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const complex_1d_array &b, ae_int_t &info, densesolverreport &rep, complex_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Complex dense linear solver for A*x=b with N*N complex A given by its LU -decomposition and N*1 vectors x and b. This is fast lightweight version -of solver, which is significantly faster than CMatrixLUSolve(), but does -not provide additional information (like condition numbers). - -Algorithm features: -* O(N^2) complexity -* no additional time-consuming features, just triangular solver - -INPUT PARAMETERS - LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU result - P - array[0..N-1], pivots array, CMatrixLU result - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is exactly singular (ill conditioned matrices - are not recognized). - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * info>0 => overwritten by solution - * info=-3 => filled by zeros - -NOTE: unlike CMatrixLUSolve(), this function does NOT check for - near-degeneracy of input matrix. It checks for EXACT degeneracy, - because this check is easy to do. However, very badly conditioned - matrices may went unnoticed. - - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixlusolvefast(const complex_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const complex_1d_array &b, ae_int_t &info, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver. Same as RMatrixMixedSolveM(), but for complex matrices. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(M*N^2) complexity - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU result - P - array[0..N-1], pivots array, CMatrixLU result - N - size of A - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixmixedsolvem(const complex_2d_array &a, const complex_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const complex_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, complex_2d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver. Same as RMatrixMixedSolve(), but for complex matrices. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* iterative refinement -* O(N^2) complexity - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU result - P - array[0..N-1], pivots array, CMatrixLU result - N - size of A - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or exactly singular. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void cmatrixmixedsolve(const complex_2d_array &a, const complex_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const complex_1d_array &b, ae_int_t &info, densesolverreport &rep, complex_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver for A*X=B with N*N symmetric positive definite matrix A, and -N*M vectors X and B. It is "slow-but-feature-rich" version of the solver. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* O(N^3+M*N^2) complexity -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just performs Cholesky - ! decomposition and calls triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, SPDMatrixSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or non-SPD. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixsolvem(const real_2d_array &a, const ae_int_t n, const bool isupper, const real_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, real_2d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver for A*X=B with N*N symmetric positive definite matrix A, and -N*M vectors X and B. It is "fast-but-lightweight" version of the solver. - -Algorithm features: -* O(N^3+M*N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional time consuming features - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular - * -1 N<=0 was passed - * 1 task was solved - B - array[N,M], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 17.03.2015 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixsolvemfast(const real_2d_array &a, const ae_int_t n, const bool isupper, const real_2d_array &b, const ae_int_t m, ae_int_t &info, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense linear solver for A*x=b with N*N real symmetric positive definite -matrix A, N*1 vectors x and b. "Slow-but-feature-rich" version of the -solver. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* O(N^3) complexity -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just performs Cholesky - ! decomposition and calls triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, SPDMatrixSolveFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 matrix is very badly conditioned or non-SPD. - * -1 N<=0 was passed - * 1 task is solved (but matrix A may be ill-conditioned, - check R1/RInf parameters for condition numbers). - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixsolve(const real_2d_array &a, const ae_int_t n, const bool isupper, const real_1d_array &b, ae_int_t &info, densesolverreport &rep, real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense linear solver for A*x=b with N*N real symmetric positive definite -matrix A, N*1 vectors x and b. "Fast-but-lightweight" version of the -solver. - -Algorithm features: -* O(N^3) complexity -* matrix is represented by its upper or lower triangle -* no additional time consuming features like condition number estimation - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or non-SPD - * -1 N<=0 was passed - * 1 task was solved - B - array[N], it contains: - * info>0 => solution - * info=-3 => filled by zeros - - -- ALGLIB -- - Copyright 17.03.2015 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixsolvefast(const real_2d_array &a, const ae_int_t n, const bool isupper, const real_1d_array &b, ae_int_t &info, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver for A*X=B with N*N symmetric positive definite matrix A given -by its Cholesky decomposition, and N*M vectors X and B. It is "slow-but- -feature-rich" version of the solver which estimates condition number of -the system. - -Algorithm features: -* automatic detection of degenerate cases -* O(M*N^2) complexity -* condition number estimation -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just calls triangular - ! solver. Amount of overhead introduced depends on M (the - ! larger - the more efficient). - ! - ! This performance penalty is insignificant when compared with - ! cost of large LU decomposition. However, if you call this - ! function many times for the same left side, this overhead - ! BECOMES significant. It also becomes significant for small- - ! scale problems (N<50). - ! - ! In such cases we strongly recommend you to use faster solver, - ! SPDMatrixCholeskySolveMFast() function. - -INPUT PARAMETERS - CHA - array[0..N-1,0..N-1], Cholesky decomposition, - SPDMatrixCholesky result - N - size of CHA - IsUpper - what half of CHA is provided - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or badly conditioned - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task was solved - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N]: - * for info>0 contains solution - * for info=-3 filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixcholeskysolvem(const real_2d_array &cha, const ae_int_t n, const bool isupper, const real_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, real_2d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver for A*X=B with N*N symmetric positive definite matrix A given -by its Cholesky decomposition, and N*M vectors X and B. It is "fast-but- -lightweight" version of the solver which just solves linear system, -without any additional functions. - -Algorithm features: -* O(M*N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional functionality - -INPUT PARAMETERS - CHA - array[N,N], Cholesky decomposition, - SPDMatrixCholesky result - N - size of CHA - IsUpper - what half of CHA is provided - B - array[N,M], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or badly conditioned - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task was solved - B - array[N]: - * for info>0 overwritten by solution - * for info=-3 filled by zeros - - -- ALGLIB -- - Copyright 18.03.2015 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixcholeskysolvemfast(const real_2d_array &cha, const ae_int_t n, const bool isupper, const real_2d_array &b, const ae_int_t m, ae_int_t &info, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver for A*x=b with N*N symmetric positive definite matrix A given -by its Cholesky decomposition, and N*1 real vectors x and b. This is "slow- -but-feature-rich" version of the solver which, in addition to the -solution, performs condition number estimation. - -Algorithm features: -* automatic detection of degenerate cases -* O(N^2) complexity -* condition number estimation -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in 10-15x performance penalty when compared - ! with "fast" version which just calls triangular solver. - ! - ! This performance penalty is insignificant when compared with - ! cost of large LU decomposition. However, if you call this - ! function many times for the same left side, this overhead - ! BECOMES significant. It also becomes significant for small- - ! scale problems (N<50). - ! - ! In such cases we strongly recommend you to use faster solver, - ! SPDMatrixCholeskySolveFast() function. - -INPUT PARAMETERS - CHA - array[N,N], Cholesky decomposition, - SPDMatrixCholesky result - N - size of A - IsUpper - what half of CHA is provided - B - array[N], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or ill conditioned - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N]: - * for info>0 - solution - * for info=-3 - filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixcholeskysolve(const real_2d_array &cha, const ae_int_t n, const bool isupper, const real_1d_array &b, ae_int_t &info, densesolverreport &rep, real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver for A*x=b with N*N symmetric positive definite matrix A given -by its Cholesky decomposition, and N*1 real vectors x and b. This is "fast- -but-lightweight" version of the solver. - -Algorithm features: -* O(N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional features - -INPUT PARAMETERS - CHA - array[N,N], Cholesky decomposition, - SPDMatrixCholesky result - N - size of A - IsUpper - what half of CHA is provided - B - array[N], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or ill conditioned - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * for info>0 - overwritten by solution - * for info=-3 - filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void spdmatrixcholeskysolvefast(const real_2d_array &cha, const ae_int_t n, const bool isupper, const real_1d_array &b, ae_int_t &info, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver for A*X=B, with N*N Hermitian positive definite matrix A and -N*M complex matrices X and B. "Slow-but-feature-rich" version of the -solver. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* O(N^3+M*N^2) complexity -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just calls triangular - ! solver. - ! - ! This performance penalty is especially apparent when you use - ! ALGLIB parallel capabilities (condition number estimation is - ! inherently sequential). It also becomes significant for - ! small-scale problems (N<100). - ! - ! In such cases we strongly recommend you to use faster solver, - ! HPDMatrixSolveMFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - same as in RMatrixSolve. - Returns -3 for non-HPD matrices. - Rep - same as in RMatrixSolve - X - same as in RMatrixSolve - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixsolvem(const complex_2d_array &a, const ae_int_t n, const bool isupper, const complex_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, complex_2d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver for A*X=B, with N*N Hermitian positive definite matrix A and -N*M complex matrices X and B. "Fast-but-lightweight" version of the solver. - -Algorithm features: -* O(N^3+M*N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional time consuming features like condition number estimation - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1,0..M-1], right part - M - right part size - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or is not positive definite. - B is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - B - array[0..N-1]: - * overwritten by solution - * zeros, if problem was not solved - - -- ALGLIB -- - Copyright 17.03.2015 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixsolvemfast(const complex_2d_array &a, const ae_int_t n, const bool isupper, const complex_2d_array &b, const ae_int_t m, ae_int_t &info, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver for A*x=b, with N*N Hermitian positive definite matrix A, and -N*1 complex vectors x and b. "Slow-but-feature-rich" version of the -solver. - -Algorithm features: -* automatic detection of degenerate cases -* condition number estimation -* O(N^3) complexity -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just performs Cholesky - ! decomposition and calls triangular solver. - ! - ! This performance penalty is especially visible in the - ! multithreaded mode, because both condition number estimation - ! and iterative refinement are inherently sequential - ! calculations. - ! - ! Thus, if you need high performance and if you are pretty sure - ! that your system is well conditioned, we strongly recommend - ! you to use faster solver, HPDMatrixSolveFast() function. - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - same as in RMatrixSolve - Returns -3 for non-HPD matrices. - Rep - same as in RMatrixSolve - X - same as in RMatrixSolve - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixsolve(const complex_2d_array &a, const ae_int_t n, const bool isupper, const complex_1d_array &b, ae_int_t &info, densesolverreport &rep, complex_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver for A*x=b, with N*N Hermitian positive definite matrix A, and -N*1 complex vectors x and b. "Fast-but-lightweight" version of the -solver without additional functions. - -Algorithm features: -* O(N^3) complexity -* matrix is represented by its upper or lower triangle -* no additional time consuming functions - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..N-1,0..N-1], system matrix - N - size of A - IsUpper - what half of A is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or not positive definite - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task was solved - B - array[0..N-1]: - * overwritten by solution - * zeros, if A is exactly singular (diagonal of its LU - decomposition has exact zeros). - - -- ALGLIB -- - Copyright 17.03.2015 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixsolvefast(const complex_2d_array &a, const ae_int_t n, const bool isupper, const complex_1d_array &b, ae_int_t &info, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver for A*X=B with N*N Hermitian positive definite matrix A given -by its Cholesky decomposition and N*M complex matrices X and B. This is -"slow-but-feature-rich" version of the solver which, in addition to the -solution, estimates condition number of the system. - -Algorithm features: -* automatic detection of degenerate cases -* O(M*N^2) complexity -* condition number estimation -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in significant performance penalty when - ! compared with "fast" version which just calls triangular - ! solver. Amount of overhead introduced depends on M (the - ! larger - the more efficient). - ! - ! This performance penalty is insignificant when compared with - ! cost of large Cholesky decomposition. However, if you call - ! this function many times for the same left side, this - ! overhead BECOMES significant. It also becomes significant - ! for small-scale problems (N<50). - ! - ! In such cases we strongly recommend you to use faster solver, - ! HPDMatrixCholeskySolveMFast() function. - - -INPUT PARAMETERS - CHA - array[N,N], Cholesky decomposition, - HPDMatrixCholesky result - N - size of CHA - IsUpper - what half of CHA is provided - B - array[N,M], right part - M - right part size - -OUTPUT PARAMETERS: - Info - return code: - * -3 A is singular, or VERY close to singular. - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task was solved - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N]: - * for info>0 contains solution - * for info=-3 filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixcholeskysolvem(const complex_2d_array &cha, const ae_int_t n, const bool isupper, const complex_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, complex_2d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver for A*X=B with N*N Hermitian positive definite matrix A given -by its Cholesky decomposition and N*M complex matrices X and B. This is -"fast-but-lightweight" version of the solver. - -Algorithm features: -* O(M*N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional time-consuming features - -INPUT PARAMETERS - CHA - array[N,N], Cholesky decomposition, - HPDMatrixCholesky result - N - size of CHA - IsUpper - what half of CHA is provided - B - array[N,M], right part - M - right part size - -OUTPUT PARAMETERS: - Info - return code: - * -3 A is singular, or VERY close to singular. - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task was solved - B - array[N]: - * for info>0 overwritten by solution - * for info=-3 filled by zeros - - -- ALGLIB -- - Copyright 18.03.2015 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixcholeskysolvemfast(const complex_2d_array &cha, const ae_int_t n, const bool isupper, const complex_2d_array &b, const ae_int_t m, ae_int_t &info, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver for A*x=b with N*N Hermitian positive definite matrix A given -by its Cholesky decomposition, and N*1 complex vectors x and b. This is -"slow-but-feature-rich" version of the solver which estimates condition -number of the system. - -Algorithm features: -* automatic detection of degenerate cases -* O(N^2) complexity -* condition number estimation -* matrix is represented by its upper or lower triangle - -No iterative refinement is provided because such partial representation of -matrix does not allow efficient calculation of extra-precise matrix-vector -products for large matrices. Use RMatrixSolve or RMatrixMixedSolve if you -need iterative refinement. - -IMPORTANT: ! this function is NOT the most efficient linear solver provided - ! by ALGLIB. It estimates condition number of linear system, - ! which results in 10-15x performance penalty when compared - ! with "fast" version which just calls triangular solver. - ! - ! This performance penalty is insignificant when compared with - ! cost of large LU decomposition. However, if you call this - ! function many times for the same left side, this overhead - ! BECOMES significant. It also becomes significant for small- - ! scale problems (N<50). - ! - ! In such cases we strongly recommend you to use faster solver, - ! HPDMatrixCholeskySolveFast() function. - -INPUT PARAMETERS - CHA - array[0..N-1,0..N-1], Cholesky decomposition, - SPDMatrixCholesky result - N - size of A - IsUpper - what half of CHA is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or ill conditioned - X is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - Rep - additional report, following fields are set: - * rep.r1 condition number in 1-norm - * rep.rinf condition number in inf-norm - X - array[N]: - * for info>0 - solution - * for info=-3 - filled by zeros - - -- ALGLIB -- - Copyright 27.01.2010 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixcholeskysolve(const complex_2d_array &cha, const ae_int_t n, const bool isupper, const complex_1d_array &b, ae_int_t &info, densesolverreport &rep, complex_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver for A*x=b with N*N Hermitian positive definite matrix A given -by its Cholesky decomposition, and N*1 complex vectors x and b. This is -"fast-but-lightweight" version of the solver. - -Algorithm features: -* O(N^2) complexity -* matrix is represented by its upper or lower triangle -* no additional time-consuming features - -INPUT PARAMETERS - CHA - array[0..N-1,0..N-1], Cholesky decomposition, - SPDMatrixCholesky result - N - size of A - IsUpper - what half of CHA is provided - B - array[0..N-1], right part - -OUTPUT PARAMETERS - Info - return code: - * -3 A is is exactly singular or ill conditioned - B is filled by zeros in such cases. - * -1 N<=0 was passed - * 1 task is solved - B - array[N]: - * for info>0 - overwritten by solution - * for info=-3 - filled by zeros - - -- ALGLIB -- - Copyright 18.03.2015 by Bochkanov Sergey -*************************************************************************/ -void hpdmatrixcholeskysolvefast(const complex_2d_array &cha, const ae_int_t n, const bool isupper, const complex_1d_array &b, ae_int_t &info, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Dense solver. - -This subroutine finds solution of the linear system A*X=B with non-square, -possibly degenerate A. System is solved in the least squares sense, and -general least squares solution X = X0 + CX*y which minimizes |A*X-B| is -returned. If A is non-degenerate, solution in the usual sense is returned. - -Algorithm features: -* automatic detection (and correct handling!) of degenerate cases -* iterative refinement -* O(N^3) complexity - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS - A - array[0..NRows-1,0..NCols-1], system matrix - NRows - vertical size of A - NCols - horizontal size of A - B - array[0..NCols-1], right part - Threshold- a number in [0,1]. Singular values beyond Threshold are - considered zero. Set it to 0.0, if you don't understand - what it means, so the solver will choose good value on its - own. - -OUTPUT PARAMETERS - Info - return code: - * -4 SVD subroutine failed - * -1 if NRows<=0 or NCols<=0 or Threshold<0 was passed - * 1 if task is solved - Rep - solver report, see below for more info - X - array[0..N-1,0..M-1], it contains: - * solution of A*X=B (even for singular A) - * zeros, if SVD subroutine failed - -SOLVER REPORT - -Subroutine sets following fields of the Rep structure: -* R2 reciprocal of condition number: 1/cond(A), 2-norm. -* N = NCols -* K dim(Null(A)) -* CX array[0..N-1,0..K-1], kernel of A. - Columns of CX store such vectors that A*CX[i]=0. - - -- ALGLIB -- - Copyright 24.08.2009 by Bochkanov Sergey -*************************************************************************/ -void rmatrixsolvels(const real_2d_array &a, const ae_int_t nrows, const ae_int_t ncols, const real_1d_array &b, const double threshold, ae_int_t &info, densesolverlsreport &rep, real_1d_array &x, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_LINLSQR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This function initializes linear LSQR Solver. This solver is used to solve -non-symmetric (and, possibly, non-square) problems. Least squares solution -is returned for non-compatible systems. - -USAGE: -1. User initializes algorithm state with LinLSQRCreate() call -2. User tunes solver parameters with LinLSQRSetCond() and other functions -3. User calls LinLSQRSolveSparse() function which takes algorithm state - and SparseMatrix object. -4. User calls LinLSQRResults() to get solution -5. Optionally, user may call LinLSQRSolveSparse() again to solve another - problem with different matrix and/or right part without reinitializing - LinLSQRState structure. - -INPUT PARAMETERS: - M - number of rows in A - N - number of variables, N>0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: see also linlsqrcreatebuf() for version which reuses previously - allocated place as much as possible. - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -void linlsqrcreate(const ae_int_t m, const ae_int_t n, linlsqrstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function initializes linear LSQR Solver. It provides exactly same -functionality as linlsqrcreate(), but reuses previously allocated space -as much as possible. - -INPUT PARAMETERS: - M - number of rows in A - N - number of variables, N>0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 14.11.2018 by Bochkanov Sergey -*************************************************************************/ -void linlsqrcreatebuf(const ae_int_t m, const ae_int_t n, const linlsqrstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function changes preconditioning settings of LinLSQQSolveSparse() -function. By default, SolveSparse() uses diagonal preconditioner, but if -you want to use solver without preconditioning, you can call this function -which forces solver to use unit matrix for preconditioning. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 19.11.2012 by Bochkanov Sergey -*************************************************************************/ -void linlsqrsetprecunit(const linlsqrstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function changes preconditioning settings of LinCGSolveSparse() -function. LinCGSolveSparse() will use diagonal of the system matrix as -preconditioner. This preconditioning mode is active by default. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 19.11.2012 by Bochkanov Sergey -*************************************************************************/ -void linlsqrsetprecdiag(const linlsqrstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets optional Tikhonov regularization coefficient. -It is zero by default. - -INPUT PARAMETERS: - LambdaI - regularization factor, LambdaI>=0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -void linlsqrsetlambdai(const linlsqrstate &state, const double lambdai, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Procedure for solution of A*x=b with sparse A. - -INPUT PARAMETERS: - State - algorithm state - A - sparse M*N matrix in the CRS format (you MUST contvert it - to CRS format by calling SparseConvertToCRS() function - BEFORE you pass it to this function). - B - right part, array[M] - -RESULT: - This function returns no result. - You can get solution by calling LinCGResults() - -NOTE: this function uses lightweight preconditioning - multiplication by - inverse of diag(A). If you want, you can turn preconditioning off by - calling LinLSQRSetPrecUnit(). However, preconditioning cost is low - and preconditioner is very important for solution of badly scaled - problems. - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -void linlsqrsolvesparse(const linlsqrstate &state, const sparsematrix &a, const real_1d_array &b, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets stopping criteria. - -INPUT PARAMETERS: - EpsA - algorithm will be stopped if ||A^T*Rk||/(||A||*||Rk||)<=EpsA. - EpsB - algorithm will be stopped if ||Rk||<=EpsB*||B|| - MaxIts - algorithm will be stopped if number of iterations - more than MaxIts. - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTE: if EpsA,EpsB,EpsC and MaxIts are zero then these variables will -be setted as default values. - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -void linlsqrsetcond(const linlsqrstate &state, const double epsa, const double epsb, const ae_int_t maxits, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -LSQR solver: results. - -This function must be called after LinLSQRSolve - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[N], solution - Rep - optimization report: - * Rep.TerminationType completetion code: - * 1 ||Rk||<=EpsB*||B|| - * 4 ||A^T*Rk||/(||A||*||Rk||)<=EpsA - * 5 MaxIts steps was taken - * 7 rounding errors prevent further progress, - X contains best point found so far. - (sometimes returned on singular systems) - * 8 user requested termination via calling - linlsqrrequesttermination() - * Rep.IterationsCount contains iterations count - * NMV countains number of matrix-vector calculations - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -void linlsqrresults(const linlsqrstate &state, real_1d_array &x, linlsqrreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinCGOptimize(). - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -void linlsqrsetxrep(const linlsqrstate &state, const bool needxrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function is used to peek into LSQR solver and get current iteration -counter. You can safely "peek" into the solver from another thread. - -INPUT PARAMETERS: - S - solver object - -RESULT: - iteration counter, in [0,INF) - - -- ALGLIB -- - Copyright 21.05.2018 by Bochkanov Sergey -*************************************************************************/ -ae_int_t linlsqrpeekiterationscount(const linlsqrstate &s, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine submits request for termination of the running solver. It -can be called from some other thread which wants LSQR solver to terminate -(obviously, the thread running LSQR solver can not request termination -because it is already busy working on LSQR). - -As result, solver stops at point which was "current accepted" when -termination request was submitted and returns error code 8 (successful -termination). Such termination is a smooth process which properly -deallocates all temporaries. - -INPUT PARAMETERS: - State - solver structure - -NOTE: calling this function on solver which is NOT running will have no - effect. - -NOTE: multiple calls to this function are possible. First call is counted, - subsequent calls are silently ignored. - -NOTE: solver clears termination flag on its start, it means that if some - other thread will request termination too soon, its request will went - unnoticed. - - -- ALGLIB -- - Copyright 08.10.2014 by Bochkanov Sergey -*************************************************************************/ -void linlsqrrequesttermination(const linlsqrstate &state, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_POLYNOMIALSOLVER) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Polynomial root finding. - -This function returns all roots of the polynomial - P(x) = a0 + a1*x + a2*x^2 + ... + an*x^n -Both real and complex roots are returned (see below). - -INPUT PARAMETERS: - A - array[N+1], polynomial coefficients: - * A[0] is constant term - * A[N] is a coefficient of X^N - N - polynomial degree - -OUTPUT PARAMETERS: - X - array of complex roots: - * for isolated real root, X[I] is strictly real: IMAGE(X[I])=0 - * complex roots are always returned in pairs - roots occupy - positions I and I+1, with: - * X[I+1]=Conj(X[I]) - * IMAGE(X[I]) > 0 - * IMAGE(X[I+1]) = -IMAGE(X[I]) < 0 - * multiple real roots may have non-zero imaginary part due - to roundoff errors. There is no reliable way to distinguish - real root of multiplicity 2 from two complex roots in - the presence of roundoff errors. - Rep - report, additional information, following fields are set: - * Rep.MaxErr - max( |P(xi)| ) for i=0..N-1. This field - allows to quickly estimate "quality" of the roots being - returned. - -NOTE: this function uses companion matrix method to find roots. In case - internal EVD solver fails do find eigenvalues, exception is - generated. - -NOTE: roots are not "polished" and no matrix balancing is performed - for them. - - -- ALGLIB -- - Copyright 24.02.2014 by Bochkanov Sergey -*************************************************************************/ -void polynomialsolve(const real_1d_array &a, const ae_int_t n, complex_1d_array &x, polynomialsolverreport &rep, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_NLEQ) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* - LEVENBERG-MARQUARDT-LIKE NONLINEAR SOLVER - -DESCRIPTION: -This algorithm solves system of nonlinear equations - F[0](x[0], ..., x[n-1]) = 0 - F[1](x[0], ..., x[n-1]) = 0 - ... - F[M-1](x[0], ..., x[n-1]) = 0 -with M/N do not necessarily coincide. Algorithm converges quadratically -under following conditions: - * the solution set XS is nonempty - * for some xs in XS there exist such neighbourhood N(xs) that: - * vector function F(x) and its Jacobian J(x) are continuously - differentiable on N - * ||F(x)|| provides local error bound on N, i.e. there exists such - c1, that ||F(x)||>c1*distance(x,XS) -Note that these conditions are much more weaker than usual non-singularity -conditions. For example, algorithm will converge for any affine function -F (whether its Jacobian singular or not). - - -REQUIREMENTS: -Algorithm will request following information during its operation: -* function vector F[] and Jacobian matrix at given point X -* value of merit function f(x)=F[0]^2(x)+...+F[M-1]^2(x) at given point X - - -USAGE: -1. User initializes algorithm state with NLEQCreateLM() call -2. User tunes solver parameters with NLEQSetCond(), NLEQSetStpMax() and - other functions -3. User calls NLEQSolve() function which takes algorithm state and - pointers (delegates, etc.) to callback functions which calculate merit - function value and Jacobian. -4. User calls NLEQResults() to get solution -5. Optionally, user may call NLEQRestartFrom() to solve another problem - with same parameters (N/M) but another starting point and/or another - function vector. NLEQRestartFrom() allows to reuse already initialized - structure. - - -INPUT PARAMETERS: - N - space dimension, N>1: - * if provided, only leading N elements of X are used - * if not provided, determined automatically from size of X - M - system size - X - starting point - - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -NOTES: -1. you may tune stopping conditions with NLEQSetCond() function -2. if target function contains exp() or other fast growing functions, and - optimization algorithm makes too large steps which leads to overflow, - use NLEQSetStpMax() function to bound algorithm's steps. -3. this algorithm is a slightly modified implementation of the method - described in 'Levenberg-Marquardt method for constrained nonlinear - equations with strong local convergence properties' by Christian Kanzow - Nobuo Yamashita and Masao Fukushima and further developed in 'On the - convergence of a New Levenberg-Marquardt Method' by Jin-yan Fan and - Ya-Xiang Yuan. - - - -- ALGLIB -- - Copyright 20.08.2009 by Bochkanov Sergey -*************************************************************************/ -void nleqcreatelm(const ae_int_t n, const ae_int_t m, const real_1d_array &x, nleqstate &state, const xparams _xparams = alglib::xdefault); -void nleqcreatelm(const ae_int_t m, const real_1d_array &x, nleqstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets stopping conditions for the nonlinear solver - -INPUT PARAMETERS: - State - structure which stores algorithm state - EpsF - >=0 - The subroutine finishes its work if on k+1-th iteration - the condition ||F||<=EpsF is satisfied - MaxIts - maximum number of iterations. If MaxIts=0, the number of - iterations is unlimited. - -Passing EpsF=0 and MaxIts=0 simultaneously will lead to automatic -stopping criterion selection (small EpsF). - -NOTES: - - -- ALGLIB -- - Copyright 20.08.2010 by Bochkanov Sergey -*************************************************************************/ -void nleqsetcond(const nleqstate &state, const double epsf, const ae_int_t maxits, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to NLEQSolve(). - - -- ALGLIB -- - Copyright 20.08.2010 by Bochkanov Sergey -*************************************************************************/ -void nleqsetxrep(const nleqstate &state, const bool needxrep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets maximum step length - -INPUT PARAMETERS: - State - structure which stores algorithm state - StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't - want to limit step length. - -Use this subroutine when target function contains exp() or other fast -growing functions, and algorithm makes too large steps which lead to -overflow. This function allows us to reject steps that are too large (and -therefore expose us to the possible overflow) without actually calculating -function value at the x+stp*d. - - -- ALGLIB -- - Copyright 20.08.2010 by Bochkanov Sergey -*************************************************************************/ -void nleqsetstpmax(const nleqstate &state, const double stpmax, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function provides reverse communication interface -Reverse communication interface is not documented or recommended to use. -See below for functions which provide better documented API -*************************************************************************/ -bool nleqiteration(const nleqstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This family of functions is used to launcn iterations of nonlinear solver - -These functions accept following parameters: - state - algorithm state - func - callback which calculates function (or merit function) - value func at given point x - jac - callback which calculates function vector fi[] - and Jacobian jac at given point x - rep - optional callback which is called after each iteration - can be NULL - ptr - optional pointer which is passed to func/grad/hess/jac/rep - can be NULL - - - -- ALGLIB -- - Copyright 20.03.2009 by Bochkanov Sergey - -*************************************************************************/ -void nleqsolve(nleqstate &state, - void (*func)(const real_1d_array &x, double &func, void *ptr), - void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr), - void (*rep)(const real_1d_array &x, double func, void *ptr) = NULL, - void *ptr = NULL, - const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -NLEQ solver results - -INPUT PARAMETERS: - State - algorithm state. - -OUTPUT PARAMETERS: - X - array[0..N-1], solution - Rep - optimization report: - * Rep.TerminationType completetion code: - * -4 ERROR: algorithm has converged to the - stationary point Xf which is local minimum of - f=F[0]^2+...+F[m-1]^2, but is not solution of - nonlinear system. - * 1 sqrt(f)<=EpsF. - * 5 MaxIts steps was taken - * 7 stopping conditions are too stringent, - further improvement is impossible - * Rep.IterationsCount contains iterations count - * NFEV countains number of function calculations - * ActiveConstraints contains number of active constraints - - -- ALGLIB -- - Copyright 20.08.2009 by Bochkanov Sergey -*************************************************************************/ -void nleqresults(const nleqstate &state, real_1d_array &x, nleqreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -NLEQ solver results - -Buffered implementation of NLEQResults(), which uses pre-allocated buffer -to store X[]. If buffer size is too small, it resizes buffer. It is -intended to be used in the inner cycles of performance critical algorithms -where array reallocation penalty is too large to be ignored. - - -- ALGLIB -- - Copyright 20.08.2009 by Bochkanov Sergey -*************************************************************************/ -void nleqresultsbuf(const nleqstate &state, real_1d_array &x, nleqreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This subroutine restarts CG algorithm from new point. All optimization -parameters are left unchanged. - -This function allows to solve multiple optimization problems (which -must have same number of dimensions) without object reallocation penalty. - -INPUT PARAMETERS: - State - structure used for reverse communication previously - allocated with MinCGCreate call. - X - new starting point. - BndL - new lower bounds - BndU - new upper bounds - - -- ALGLIB -- - Copyright 30.07.2010 by Bochkanov Sergey -*************************************************************************/ -void nleqrestartfrom(const nleqstate &state, const real_1d_array &x, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_DIRECTSPARSESOLVERS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Sparse linear solver for A*x=b with N*N sparse real symmetric positive -definite matrix A, N*1 vectors x and b. - -This solver converts input matrix to SKS format, performs Cholesky -factorization using SKS Cholesky subroutine (works well for limited -bandwidth matrices) and uses sparse triangular solvers to get solution of -the original system. - -INPUT PARAMETERS - A - sparse matrix, must be NxN exactly - IsUpper - which half of A is provided (another half is ignored) - B - array[0..N-1], right part - -OUTPUT PARAMETERS - X - array[N], it contains: - * rep.terminationtype>0 => solution - * rep.terminationtype=-3 => filled by zeros - Rep - solver report, following fields are set: - * rep.terminationtype - solver status; >0 for success, - set to -3 on failure (degenerate or non-SPD system). - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -void sparsespdsolvesks(const sparsematrix &a, const bool isupper, const real_1d_array &b, real_1d_array &x, sparsesolverreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Sparse linear solver for A*x=b with N*N sparse real symmetric positive -definite matrix A, N*1 vectors x and b. - -This solver converts input matrix to CRS format, performs Cholesky -factorization using supernodal Cholesky decomposition with permutation- -reducing ordering and uses sparse triangular solver to get solution of the -original system. - -INPUT PARAMETERS - A - sparse matrix, must be NxN exactly - IsUpper - which half of A is provided (another half is ignored) - B - array[N], right part - -OUTPUT PARAMETERS - X - array[N], it contains: - * rep.terminationtype>0 => solution - * rep.terminationtype=-3 => filled by zeros - Rep - solver report, following fields are set: - * rep.terminationtype - solver status; >0 for success, - set to -3 on failure (degenerate or non-SPD system). - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -void sparsespdsolve(const sparsematrix &a, const bool isupper, const real_1d_array &b, real_1d_array &x, sparsesolverreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Sparse linear solver for A*x=b with N*N real symmetric positive definite -matrix A given by its Cholesky decomposition, and N*1 vectors x and b. - -IMPORTANT: this solver requires input matrix to be in the SKS (Skyline) - or CRS (compressed row storage) format. An exception will be - generated if you pass matrix in some other format. - -INPUT PARAMETERS - A - sparse NxN matrix stored in CRs or SKS format, must be NxN - exactly - IsUpper - which half of A is provided (another half is ignored) - B - array[N], right part - -OUTPUT PARAMETERS - X - array[N], it contains: - * rep.terminationtype>0 => solution - * rep.terminationtype=-3 => filled by zeros - Rep - solver report, following fields are set: - * rep.terminationtype - solver status; >0 for success, - set to -3 on failure (degenerate or non-SPD system). - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -void sparsespdcholeskysolve(const sparsematrix &a, const bool isupper, const real_1d_array &b, real_1d_array &x, sparsesolverreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Sparse linear solver for A*x=b with general (nonsymmetric) N*N sparse real -matrix A, N*1 vectors x and b. - -This solver converts input matrix to CRS format, performs LU factorization -and uses sparse triangular solvers to get solution of the original system. - -INPUT PARAMETERS - A - sparse matrix, must be NxN exactly, any storage format - N - size of A, N>0 - B - array[0..N-1], right part - -OUTPUT PARAMETERS - X - array[N], it contains: - * rep.terminationtype>0 => solution - * rep.terminationtype=-3 => filled by zeros - Rep - solver report, following fields are set: - * rep.terminationtype - solver status; >0 for success, - set to -3 on failure (degenerate system). - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -void sparsesolve(const sparsematrix &a, const real_1d_array &b, real_1d_array &x, sparsesolverreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Sparse linear solver for A*x=b with general (nonsymmetric) N*N sparse real -matrix A given by its LU factorization, N*1 vectors x and b. - -IMPORTANT: this solver requires input matrix to be in the CRS sparse - storage format. An exception will be generated if you pass - matrix in some other format (HASH or SKS). - -INPUT PARAMETERS - A - LU factorization of the sparse matrix, must be NxN exactly - in CRS storage format - P, Q - pivot indexes from LU factorization - N - size of A, N>0 - B - array[0..N-1], right part - -OUTPUT PARAMETERS - X - array[N], it contains: - * rep.terminationtype>0 => solution - * rep.terminationtype=-3 => filled by zeros - Rep - solver report, following fields are set: - * rep.terminationtype - solver status; >0 for success, - set to -3 on failure (degenerate system). - - -- ALGLIB -- - Copyright 26.12.2017 by Bochkanov Sergey -*************************************************************************/ -void sparselusolve(const sparsematrix &a, const integer_1d_array &p, const integer_1d_array &q, const real_1d_array &b, real_1d_array &x, sparsesolverreport &rep, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_LINCG) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -This function initializes linear CG Solver. This solver is used to solve -symmetric positive definite problems. If you want to solve nonsymmetric -(or non-positive definite) problem you may use LinLSQR solver provided by -ALGLIB. - -USAGE: -1. User initializes algorithm state with LinCGCreate() call -2. User tunes solver parameters with LinCGSetCond() and other functions -3. Optionally, user sets starting point with LinCGSetStartingPoint() -4. User calls LinCGSolveSparse() function which takes algorithm state and - SparseMatrix object. -5. User calls LinCGResults() to get solution -6. Optionally, user may call LinCGSolveSparse() again to solve another - problem with different matrix and/or right part without reinitializing - LinCGState structure. - -INPUT PARAMETERS: - N - problem dimension, N>0 - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgcreate(const ae_int_t n, lincgstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets starting point. -By default, zero starting point is used. - -INPUT PARAMETERS: - X - starting point, array[N] - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgsetstartingpoint(const lincgstate &state, const real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function changes preconditioning settings of LinCGSolveSparse() -function. By default, SolveSparse() uses diagonal preconditioner, but if -you want to use solver without preconditioning, you can call this function -which forces solver to use unit matrix for preconditioning. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 19.11.2012 by Bochkanov Sergey -*************************************************************************/ -void lincgsetprecunit(const lincgstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function changes preconditioning settings of LinCGSolveSparse() -function. LinCGSolveSparse() will use diagonal of the system matrix as -preconditioner. This preconditioning mode is active by default. - -INPUT PARAMETERS: - State - structure which stores algorithm state - - -- ALGLIB -- - Copyright 19.11.2012 by Bochkanov Sergey -*************************************************************************/ -void lincgsetprecdiag(const lincgstate &state, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets stopping criteria. - -INPUT PARAMETERS: - EpsF - algorithm will be stopped if norm of residual is less than - EpsF*||b||. - MaxIts - algorithm will be stopped if number of iterations is more - than MaxIts. - -OUTPUT PARAMETERS: - State - structure which stores algorithm state - -NOTES: -If both EpsF and MaxIts are zero then small EpsF will be set to small -value. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgsetcond(const lincgstate &state, const double epsf, const ae_int_t maxits, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Procedure for solution of A*x=b with sparse A. - -INPUT PARAMETERS: - State - algorithm state - A - sparse matrix in the CRS format (you MUST contvert it to - CRS format by calling SparseConvertToCRS() function). - IsUpper - whether upper or lower triangle of A is used: - * IsUpper=True => only upper triangle is used and lower - triangle is not referenced at all - * IsUpper=False => only lower triangle is used and upper - triangle is not referenced at all - B - right part, array[N] - -RESULT: - This function returns no result. - You can get solution by calling LinCGResults() - -NOTE: this function uses lightweight preconditioning - multiplication by - inverse of diag(A). If you want, you can turn preconditioning off by - calling LinCGSetPrecUnit(). However, preconditioning cost is low and - preconditioner is very important for solution of badly scaled - problems. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgsolvesparse(const lincgstate &state, const sparsematrix &a, const bool isupper, const real_1d_array &b, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -CG-solver: results. - -This function must be called after LinCGSolve - -INPUT PARAMETERS: - State - algorithm state - -OUTPUT PARAMETERS: - X - array[N], solution - Rep - optimization report: - * Rep.TerminationType completetion code: - * -5 input matrix is either not positive definite, - too large or too small - * -4 overflow/underflow during solution - (ill conditioned problem) - * 1 ||residual||<=EpsF*||b|| - * 5 MaxIts steps was taken - * 7 rounding errors prevent further progress, - best point found is returned - * Rep.IterationsCount contains iterations count - * NMV countains number of matrix-vector calculations - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgresults(const lincgstate &state, real_1d_array &x, lincgreport &rep, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets restart frequency. By default, algorithm is restarted -after N subsequent iterations. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgsetrestartfreq(const lincgstate &state, const ae_int_t srf, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function sets frequency of residual recalculations. - -Algorithm updates residual r_k using iterative formula, but recalculates -it from scratch after each 10 iterations. It is done to avoid accumulation -of numerical errors and to stop algorithm when r_k starts to grow. - -Such low update frequence (1/10) gives very little overhead, but makes -algorithm a bit more robust against numerical errors. However, you may -change it - -INPUT PARAMETERS: - Freq - desired update frequency, Freq>=0. - Zero value means that no updates will be done. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgsetrupdatefreq(const lincgstate &state, const ae_int_t freq, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function turns on/off reporting. - -INPUT PARAMETERS: - State - structure which stores algorithm state - NeedXRep- whether iteration reports are needed or not - -If NeedXRep is True, algorithm will call rep() callback function if it is -provided to MinCGOptimize(). - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -void lincgsetxrep(const lincgstate &state, const bool needxrep, const xparams _xparams = alglib::xdefault); -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (FUNCTIONS) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_DIRECTDENSESOLVERS) || !defined(AE_PARTIAL_BUILD) -void rmatrixsolve(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_vector* b, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_vector* x, - ae_state *_state); -void rmatrixsolvefast(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_vector* b, - ae_int_t* info, - ae_state *_state); -void rmatrixsolvem(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_bool rfs, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_matrix* x, - ae_state *_state); -void rmatrixsolvemfast(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - ae_state *_state); -void rmatrixlusolve(/* Real */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Real */ ae_vector* b, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_vector* x, - ae_state *_state); -void rmatrixlusolvefast(/* Real */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Real */ ae_vector* b, - ae_int_t* info, - ae_state *_state); -void rmatrixlusolvem(/* Real */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_matrix* x, - ae_state *_state); -void rmatrixlusolvemfast(/* Real */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - ae_state *_state); -void rmatrixmixedsolve(/* Real */ ae_matrix* a, - /* Real */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Real */ ae_vector* b, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_vector* x, - ae_state *_state); -void rmatrixmixedsolvem(/* Real */ ae_matrix* a, - /* Real */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_matrix* x, - ae_state *_state); -void cmatrixsolvem(/* Complex */ ae_matrix* a, - ae_int_t n, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_bool rfs, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_matrix* x, - ae_state *_state); -void cmatrixsolvemfast(/* Complex */ ae_matrix* a, - ae_int_t n, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - ae_state *_state); -void cmatrixsolve(/* Complex */ ae_matrix* a, - ae_int_t n, - /* Complex */ ae_vector* b, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_vector* x, - ae_state *_state); -void cmatrixsolvefast(/* Complex */ ae_matrix* a, - ae_int_t n, - /* Complex */ ae_vector* b, - ae_int_t* info, - ae_state *_state); -void cmatrixlusolvem(/* Complex */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_matrix* x, - ae_state *_state); -void cmatrixlusolvemfast(/* Complex */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - ae_state *_state); -void cmatrixlusolve(/* Complex */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Complex */ ae_vector* b, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_vector* x, - ae_state *_state); -void cmatrixlusolvefast(/* Complex */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Complex */ ae_vector* b, - ae_int_t* info, - ae_state *_state); -void cmatrixmixedsolvem(/* Complex */ ae_matrix* a, - /* Complex */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_matrix* x, - ae_state *_state); -void cmatrixmixedsolve(/* Complex */ ae_matrix* a, - /* Complex */ ae_matrix* lua, - /* Integer */ ae_vector* p, - ae_int_t n, - /* Complex */ ae_vector* b, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_vector* x, - ae_state *_state); -void spdmatrixsolvem(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_matrix* x, - ae_state *_state); -void spdmatrixsolvemfast(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - ae_state *_state); -void spdmatrixsolve(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* b, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_vector* x, - ae_state *_state); -void spdmatrixsolvefast(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* b, - ae_int_t* info, - ae_state *_state); -void spdmatrixcholeskysolvem(/* Real */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_matrix* x, - ae_state *_state); -void spdmatrixcholeskysolvemfast(/* Real */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - ae_state *_state); -void spdmatrixcholeskysolve(/* Real */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* b, - ae_int_t* info, - densesolverreport* rep, - /* Real */ ae_vector* x, - ae_state *_state); -void spdmatrixcholeskysolvefast(/* Real */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_vector* b, - ae_int_t* info, - ae_state *_state); -void hpdmatrixsolvem(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_matrix* x, - ae_state *_state); -void hpdmatrixsolvemfast(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - ae_state *_state); -void hpdmatrixsolve(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* b, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_vector* x, - ae_state *_state); -void hpdmatrixsolvefast(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* b, - ae_int_t* info, - ae_state *_state); -void hpdmatrixcholeskysolvem(/* Complex */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_matrix* x, - ae_state *_state); -void hpdmatrixcholeskysolvemfast(/* Complex */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_matrix* b, - ae_int_t m, - ae_int_t* info, - ae_state *_state); -void hpdmatrixcholeskysolve(/* Complex */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* b, - ae_int_t* info, - densesolverreport* rep, - /* Complex */ ae_vector* x, - ae_state *_state); -void hpdmatrixcholeskysolvefast(/* Complex */ ae_matrix* cha, - ae_int_t n, - ae_bool isupper, - /* Complex */ ae_vector* b, - ae_int_t* info, - ae_state *_state); -void rmatrixsolvels(/* Real */ ae_matrix* a, - ae_int_t nrows, - ae_int_t ncols, - /* Real */ ae_vector* b, - double threshold, - ae_int_t* info, - densesolverlsreport* rep, - /* Real */ ae_vector* x, - ae_state *_state); -void _densesolverreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _densesolverreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _densesolverreport_clear(void* _p); -void _densesolverreport_destroy(void* _p); -void _densesolverlsreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _densesolverlsreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _densesolverlsreport_clear(void* _p); -void _densesolverlsreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_LINLSQR) || !defined(AE_PARTIAL_BUILD) -void linlsqrcreate(ae_int_t m, - ae_int_t n, - linlsqrstate* state, - ae_state *_state); -void linlsqrcreatebuf(ae_int_t m, - ae_int_t n, - linlsqrstate* state, - ae_state *_state); -void linlsqrsetb(linlsqrstate* state, - /* Real */ ae_vector* b, - ae_state *_state); -void linlsqrsetprecunit(linlsqrstate* state, ae_state *_state); -void linlsqrsetprecdiag(linlsqrstate* state, ae_state *_state); -void linlsqrsetlambdai(linlsqrstate* state, - double lambdai, - ae_state *_state); -ae_bool linlsqriteration(linlsqrstate* state, ae_state *_state); -void linlsqrsolvesparse(linlsqrstate* state, - sparsematrix* a, - /* Real */ ae_vector* b, - ae_state *_state); -void linlsqrsetcond(linlsqrstate* state, - double epsa, - double epsb, - ae_int_t maxits, - ae_state *_state); -void linlsqrresults(linlsqrstate* state, - /* Real */ ae_vector* x, - linlsqrreport* rep, - ae_state *_state); -void linlsqrsetxrep(linlsqrstate* state, - ae_bool needxrep, - ae_state *_state); -void linlsqrrestart(linlsqrstate* state, ae_state *_state); -ae_int_t linlsqrpeekiterationscount(linlsqrstate* s, ae_state *_state); -void linlsqrrequesttermination(linlsqrstate* state, ae_state *_state); -void _linlsqrstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _linlsqrstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _linlsqrstate_clear(void* _p); -void _linlsqrstate_destroy(void* _p); -void _linlsqrreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _linlsqrreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _linlsqrreport_clear(void* _p); -void _linlsqrreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_POLYNOMIALSOLVER) || !defined(AE_PARTIAL_BUILD) -void polynomialsolve(/* Real */ ae_vector* a, - ae_int_t n, - /* Complex */ ae_vector* x, - polynomialsolverreport* rep, - ae_state *_state); -void _polynomialsolverreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _polynomialsolverreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _polynomialsolverreport_clear(void* _p); -void _polynomialsolverreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_NLEQ) || !defined(AE_PARTIAL_BUILD) -void nleqcreatelm(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* x, - nleqstate* state, - ae_state *_state); -void nleqsetcond(nleqstate* state, - double epsf, - ae_int_t maxits, - ae_state *_state); -void nleqsetxrep(nleqstate* state, ae_bool needxrep, ae_state *_state); -void nleqsetstpmax(nleqstate* state, double stpmax, ae_state *_state); -ae_bool nleqiteration(nleqstate* state, ae_state *_state); -void nleqresults(nleqstate* state, - /* Real */ ae_vector* x, - nleqreport* rep, - ae_state *_state); -void nleqresultsbuf(nleqstate* state, - /* Real */ ae_vector* x, - nleqreport* rep, - ae_state *_state); -void nleqrestartfrom(nleqstate* state, - /* Real */ ae_vector* x, - ae_state *_state); -void _nleqstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _nleqstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _nleqstate_clear(void* _p); -void _nleqstate_destroy(void* _p); -void _nleqreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _nleqreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _nleqreport_clear(void* _p); -void _nleqreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_DIRECTSPARSESOLVERS) || !defined(AE_PARTIAL_BUILD) -void sparsespdsolvesks(sparsematrix* a, - ae_bool isupper, - /* Real */ ae_vector* b, - /* Real */ ae_vector* x, - sparsesolverreport* rep, - ae_state *_state); -void sparsespdsolve(sparsematrix* a, - ae_bool isupper, - /* Real */ ae_vector* b, - /* Real */ ae_vector* x, - sparsesolverreport* rep, - ae_state *_state); -void sparsespdcholeskysolve(sparsematrix* a, - ae_bool isupper, - /* Real */ ae_vector* b, - /* Real */ ae_vector* x, - sparsesolverreport* rep, - ae_state *_state); -void sparsesolve(sparsematrix* a, - /* Real */ ae_vector* b, - /* Real */ ae_vector* x, - sparsesolverreport* rep, - ae_state *_state); -void sparselusolve(sparsematrix* a, - /* Integer */ ae_vector* p, - /* Integer */ ae_vector* q, - /* Real */ ae_vector* b, - /* Real */ ae_vector* x, - sparsesolverreport* rep, - ae_state *_state); -void _sparsesolverreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _sparsesolverreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _sparsesolverreport_clear(void* _p); -void _sparsesolverreport_destroy(void* _p); -#endif -#if defined(AE_COMPILE_LINCG) || !defined(AE_PARTIAL_BUILD) -void lincgcreate(ae_int_t n, lincgstate* state, ae_state *_state); -void lincgsetstartingpoint(lincgstate* state, - /* Real */ ae_vector* x, - ae_state *_state); -void lincgsetb(lincgstate* state, - /* Real */ ae_vector* b, - ae_state *_state); -void lincgsetprecunit(lincgstate* state, ae_state *_state); -void lincgsetprecdiag(lincgstate* state, ae_state *_state); -void lincgsetcond(lincgstate* state, - double epsf, - ae_int_t maxits, - ae_state *_state); -ae_bool lincgiteration(lincgstate* state, ae_state *_state); -void lincgsolvesparse(lincgstate* state, - sparsematrix* a, - ae_bool isupper, - /* Real */ ae_vector* b, - ae_state *_state); -void lincgresults(lincgstate* state, - /* Real */ ae_vector* x, - lincgreport* rep, - ae_state *_state); -void lincgsetrestartfreq(lincgstate* state, - ae_int_t srf, - ae_state *_state); -void lincgsetrupdatefreq(lincgstate* state, - ae_int_t freq, - ae_state *_state); -void lincgsetxrep(lincgstate* state, ae_bool needxrep, ae_state *_state); -void lincgrestart(lincgstate* state, ae_state *_state); -void _lincgstate_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _lincgstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _lincgstate_clear(void* _p); -void _lincgstate_destroy(void* _p); -void _lincgreport_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _lincgreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _lincgreport_clear(void* _p); -void _lincgreport_destroy(void* _p); -#endif - -} -#endif - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/specialfunctions.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/specialfunctions.cpp deleted file mode 100644 index b2b1a7f..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/specialfunctions.cpp +++ /dev/null @@ -1,10763 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifdef _MSC_VER -#define _CRT_SECURE_NO_WARNINGS -#endif -#include "stdafx.h" -#include "specialfunctions.h" - -// disable some irrelevant warnings -#if (AE_COMPILER==AE_MSVC) && !defined(AE_ALL_WARNINGS) -#pragma warning(disable:4100) -#pragma warning(disable:4127) -#pragma warning(disable:4611) -#pragma warning(disable:4702) -#pragma warning(disable:4996) -#endif - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_GAMMAFUNC) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_NORMALDISTR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_IGAMMAF) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_ELLIPTIC) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_HERMITE) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_DAWSON) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_TRIGINTEGRALS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_POISSONDISTR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_BESSEL) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_IBETAF) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_FDISTR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_FRESNEL) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_JACOBIANELLIPTIC) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_PSIF) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_EXPINTEGRALS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_LAGUERRE) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_CHISQUAREDISTR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_LEGENDRE) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_BETAF) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_CHEBYSHEV) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_STUDENTTDISTR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_BINOMIALDISTR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_AIRYF) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_GAMMAFUNC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Gamma function - -Input parameters: - X - argument - -Domain: - 0 < X < 171.6 - -170 < X < 0, X is not an integer. - -Relative error: - arithmetic domain # trials peak rms - IEEE -170,-33 20000 2.3e-15 3.3e-16 - IEEE -33, 33 20000 9.4e-16 2.2e-16 - IEEE 33, 171.6 20000 2.3e-15 3.2e-16 - -Cephes Math Library Release 2.8: June, 2000 -Original copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier -Translated to AlgoPascal by Bochkanov Sergey (2005, 2006, 2007). -*************************************************************************/ -double gammafunction(const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::gammafunction(x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Natural logarithm of gamma function - -Input parameters: - X - argument - -Result: - logarithm of the absolute value of the Gamma(X). - -Output parameters: - SgnGam - sign(Gamma(X)) - -Domain: - 0 < X < 2.55e305 - -2.55e305 < X < 0, X is not an integer. - -ACCURACY: -arithmetic domain # trials peak rms - IEEE 0, 3 28000 5.4e-16 1.1e-16 - IEEE 2.718, 2.556e305 40000 3.5e-16 8.3e-17 -The error criterion was relative when the function magnitude -was greater than one but absolute when it was less than one. - -The following test used the relative error criterion, though -at certain points the relative error could be much higher than -indicated. - IEEE -200, -4 10000 4.8e-16 1.3e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier -Translated to AlgoPascal by Bochkanov Sergey (2005, 2006, 2007). -*************************************************************************/ -double lngamma(const double x, double &sgngam, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::lngamma(x, &sgngam, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_NORMALDISTR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Error function - -The integral is - - x - - - 2 | | 2 - erf(x) = -------- | exp( - t ) dt. - sqrt(pi) | | - - - 0 - -For 0 <= |x| < 1, erf(x) = x * P4(x**2)/Q5(x**2); otherwise -erf(x) = 1 - erfc(x). - - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,1 30000 3.7e-16 1.0e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double errorfunction(const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::errorfunction(x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Complementary error function - - 1 - erf(x) = - - inf. - - - 2 | | 2 - erfc(x) = -------- | exp( - t ) dt - sqrt(pi) | | - - - x - - -For small x, erfc(x) = 1 - erf(x); otherwise rational -approximations are computed. - - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,26.6417 30000 5.7e-14 1.5e-14 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double errorfunctionc(const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::errorfunctionc(x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Same as normalcdf(), obsolete name. -*************************************************************************/ -double normaldistribution(const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::normaldistribution(x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Normal distribution PDF - -Returns Gaussian probability density function: - - 1 - f(x) = --------- * exp(-x^2/2) - sqrt(2pi) - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double normalpdf(const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::normalpdf(x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Normal distribution CDF - -Returns the area under the Gaussian probability density -function, integrated from minus infinity to x: - - x - - - 1 | | 2 - ndtr(x) = --------- | exp( - t /2 ) dt - sqrt(2pi) | | - - - -inf. - - = ( 1 + erf(z) ) / 2 - = erfc(z) / 2 - -where z = x/sqrt(2). Computation is via the functions -erf and erfc. - - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE -13,0 30000 3.4e-14 6.7e-15 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double normalcdf(const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::normalcdf(x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Inverse of the error function - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double inverf(const double e, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::inverf(e, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Same as invnormalcdf(), deprecated name -*************************************************************************/ -double invnormaldistribution(const double y0, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::invnormaldistribution(y0, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Inverse of Normal CDF - -Returns the argument, x, for which the area under the -Gaussian probability density function (integrated from -minus infinity to x) is equal to y. - - -For small arguments 0 < y < exp(-2), the program computes -z = sqrt( -2.0 * log(y) ); then the approximation is -x = z - log(z)/z - (1/z) P(1/z) / Q(1/z). -There are two rational functions P/Q, one for 0 < y < exp(-32) -and the other for y up to exp(-2). For larger arguments, -w = y - 0.5, and x/sqrt(2pi) = w + w**3 R(w**2)/S(w**2)). - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0.125, 1 20000 7.2e-16 1.3e-16 - IEEE 3e-308, 0.135 50000 4.6e-16 9.8e-17 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double invnormalcdf(const double y0, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::invnormalcdf(y0, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Bivariate normal PDF - -Returns probability density function of the bivariate Gaussian with -correlation parameter equal to Rho: - - 1 ( x^2 - 2*rho*x*y + y^2 ) - f(x,y,rho) = ----------------- * exp( - ----------------------- ) - 2pi*sqrt(1-rho^2) ( 2*(1-rho^2) ) - - -with -1(&result)); -} - -/************************************************************************* -Bivariate normal CDF - -Returns the area under the bivariate Gaussian PDF with correlation -parameter equal to Rho, integrated from minus infinity to (x,y): - - - x y - - - - 1 | | | | - bvn(x,y,rho) = ------------------- | | f(u,v,rho)*du*dv - 2pi*sqrt(1-rho^2) | | | | - - - - -INF -INF - - -where - - ( u^2 - 2*rho*u*v + v^2 ) - f(u,v,rho) = exp( - ----------------------- ) - ( 2*(1-rho^2) ) - - -with -1(&result)); -} -#endif - -#if defined(AE_COMPILE_IGAMMAF) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Incomplete gamma integral - -The function is defined by - - x - - - 1 | | -t a-1 - igam(a,x) = ----- | e t dt. - - | | - | (a) - - 0 - - -In this implementation both arguments must be positive. -The integral is evaluated by either a power series or -continued fraction expansion, depending on the relative -values of a and x. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,30 200000 3.6e-14 2.9e-15 - IEEE 0,100 300000 9.9e-14 1.5e-14 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1985, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double incompletegamma(const double a, const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::incompletegamma(a, x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Complemented incomplete gamma integral - -The function is defined by - - - igamc(a,x) = 1 - igam(a,x) - - inf. - - - 1 | | -t a-1 - = ----- | e t dt. - - | | - | (a) - - x - - -In this implementation both arguments must be positive. -The integral is evaluated by either a power series or -continued fraction expansion, depending on the relative -values of a and x. - -ACCURACY: - -Tested at random a, x. - a x Relative error: -arithmetic domain domain # trials peak rms - IEEE 0.5,100 0,100 200000 1.9e-14 1.7e-15 - IEEE 0.01,0.5 0,100 200000 1.4e-13 1.6e-15 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1985, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double incompletegammac(const double a, const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::incompletegammac(a, x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Inverse of complemented imcomplete gamma integral - -Given p, the function finds x such that - - igamc( a, x ) = p. - -Starting with the approximate value - - 3 - x = a t - - where - - t = 1 - d - ndtri(p) sqrt(d) - -and - - d = 1/9a, - -the routine performs up to 10 Newton iterations to find the -root of igamc(a,x) - p = 0. - -ACCURACY: - -Tested at random a, p in the intervals indicated. - - a p Relative error: -arithmetic domain domain # trials peak rms - IEEE 0.5,100 0,0.5 100000 1.0e-14 1.7e-15 - IEEE 0.01,0.5 0,0.5 100000 9.0e-14 3.4e-15 - IEEE 0.5,10000 0,0.5 20000 2.3e-13 3.8e-14 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double invincompletegammac(const double a, const double y0, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::invincompletegammac(a, y0, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_ELLIPTIC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Complete elliptic integral of the first kind - -Approximates the integral - - - - pi/2 - - - | | - | dt -K(m) = | ------------------ - | 2 - | | sqrt( 1 - m sin t ) - - - 0 - -using the approximation - - P(x) - log x Q(x). - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,1 30000 2.5e-16 6.8e-17 - -Cephes Math Library, Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double ellipticintegralk(const double m, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::ellipticintegralk(m, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Complete elliptic integral of the first kind - -Approximates the integral - - - - pi/2 - - - | | - | dt -K(m) = | ------------------ - | 2 - | | sqrt( 1 - m sin t ) - - - 0 - -where m = 1 - m1, using the approximation - - P(x) - log x Q(x). - -The argument m1 is used rather than m so that the logarithmic -singularity at m = 1 will be shifted to the origin; this -preserves maximum accuracy. - -K(0) = pi/2. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,1 30000 2.5e-16 6.8e-17 - -Cephes Math Library, Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double ellipticintegralkhighprecision(const double m1, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::ellipticintegralkhighprecision(m1, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Incomplete elliptic integral of the first kind F(phi|m) - -Approximates the integral - - - - phi - - - | | - | dt -F(phi_\m) = | ------------------ - | 2 - | | sqrt( 1 - m sin t ) - - - 0 - -of amplitude phi and modulus m, using the arithmetic - -geometric mean algorithm. - - - - -ACCURACY: - -Tested at random points with m in [0, 1] and phi as indicated. - - Relative error: -arithmetic domain # trials peak rms - IEEE -10,10 200000 7.4e-16 1.0e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double incompleteellipticintegralk(const double phi, const double m, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::incompleteellipticintegralk(phi, m, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Complete elliptic integral of the second kind - -Approximates the integral - - - pi/2 - - - | | 2 -E(m) = | sqrt( 1 - m sin t ) dt - | | - - - 0 - -using the approximation - - P(x) - x log x Q(x). - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0, 1 10000 2.1e-16 7.3e-17 - -Cephes Math Library, Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -double ellipticintegrale(const double m, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::ellipticintegrale(m, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Incomplete elliptic integral of the second kind - -Approximates the integral - - - phi - - - | | - | 2 -E(phi_\m) = | sqrt( 1 - m sin t ) dt - | - | | - - - 0 - -of amplitude phi and modulus m, using the arithmetic - -geometric mean algorithm. - -ACCURACY: - -Tested at random arguments with phi in [-10, 10] and m in -[0, 1]. - Relative error: -arithmetic domain # trials peak rms - IEEE -10,10 150000 3.3e-15 1.4e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1993, 2000 by Stephen L. Moshier -*************************************************************************/ -double incompleteellipticintegrale(const double phi, const double m, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::incompleteellipticintegrale(phi, m, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_HERMITE) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Calculation of the value of the Hermite polynomial. - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Hermite polynomial Hn at x -*************************************************************************/ -double hermitecalculate(const ae_int_t n, const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::hermitecalculate(n, x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Summation of Hermite polynomials using Clenshaw's recurrence formula. - -This routine calculates - c[0]*H0(x) + c[1]*H1(x) + ... + c[N]*HN(x) - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Hermite polynomial at x -*************************************************************************/ -double hermitesum(const real_1d_array &c, const ae_int_t n, const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::hermitesum(const_cast(c.c_ptr()), n, x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Representation of Hn as C[0] + C[1]*X + ... + C[N]*X^N - -Input parameters: - N - polynomial degree, n>=0 - -Output parameters: - C - coefficients -*************************************************************************/ -void hermitecoefficients(const ae_int_t n, real_1d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hermitecoefficients(n, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_DAWSON) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Dawson's Integral - -Approximates the integral - - x - - - 2 | | 2 - dawsn(x) = exp( -x ) | exp( t ) dt - | | - - - 0 - -Three different rational approximations are employed, for -the intervals 0 to 3.25; 3.25 to 6.25; and 6.25 up. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,10 10000 6.9e-16 1.0e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -double dawsonintegral(const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::dawsonintegral(x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_TRIGINTEGRALS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Sine and cosine integrals - -Evaluates the integrals - - x - - - | cos t - 1 - Ci(x) = eul + ln x + | --------- dt, - | t - - - 0 - x - - - | sin t - Si(x) = | ----- dt - | t - - - 0 - -where eul = 0.57721566490153286061 is Euler's constant. -The integrals are approximated by rational functions. -For x > 8 auxiliary functions f(x) and g(x) are employed -such that - -Ci(x) = f(x) sin(x) - g(x) cos(x) -Si(x) = pi/2 - f(x) cos(x) - g(x) sin(x) - - -ACCURACY: - Test interval = [0,50]. -Absolute error, except relative when > 1: -arithmetic function # trials peak rms - IEEE Si 30000 4.4e-16 7.3e-17 - IEEE Ci 30000 6.9e-16 5.1e-17 - -Cephes Math Library Release 2.1: January, 1989 -Copyright 1984, 1987, 1989 by Stephen L. Moshier -*************************************************************************/ -void sinecosineintegrals(const double x, double &si, double &ci, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sinecosineintegrals(x, &si, &ci, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Hyperbolic sine and cosine integrals - -Approximates the integrals - - x - - - | | cosh t - 1 - Chi(x) = eul + ln x + | ----------- dt, - | | t - - - 0 - - x - - - | | sinh t - Shi(x) = | ------ dt - | | t - - - 0 - -where eul = 0.57721566490153286061 is Euler's constant. -The integrals are evaluated by power series for x < 8 -and by Chebyshev expansions for x between 8 and 88. -For large x, both functions approach exp(x)/2x. -Arguments greater than 88 in magnitude return MAXNUM. - - -ACCURACY: - -Test interval 0 to 88. - Relative error: -arithmetic function # trials peak rms - IEEE Shi 30000 6.9e-16 1.6e-16 - Absolute error, except relative when |Chi| > 1: - IEEE Chi 30000 8.4e-16 1.4e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -void hyperbolicsinecosineintegrals(const double x, double &shi, double &chi, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::hyperbolicsinecosineintegrals(x, &shi, &chi, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_POISSONDISTR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Poisson distribution - -Returns the sum of the first k+1 terms of the Poisson -distribution: - - k j - -- -m m - > e -- - -- j! - j=0 - -The terms are not summed directly; instead the incomplete -gamma integral is employed, according to the relation - -y = pdtr( k, m ) = igamc( k+1, m ). - -The arguments must both be positive. -ACCURACY: - -See incomplete gamma function - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double poissondistribution(const ae_int_t k, const double m, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::poissondistribution(k, m, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Complemented Poisson distribution - -Returns the sum of the terms k+1 to infinity of the Poisson -distribution: - - inf. j - -- -m m - > e -- - -- j! - j=k+1 - -The terms are not summed directly; instead the incomplete -gamma integral is employed, according to the formula - -y = pdtrc( k, m ) = igam( k+1, m ). - -The arguments must both be positive. - -ACCURACY: - -See incomplete gamma function - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double poissoncdistribution(const ae_int_t k, const double m, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::poissoncdistribution(k, m, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Inverse Poisson distribution - -Finds the Poisson variable x such that the integral -from 0 to x of the Poisson density is equal to the -given probability y. - -This is accomplished using the inverse gamma integral -function and the relation - - m = igami( k+1, y ). - -ACCURACY: - -See inverse incomplete gamma function - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double invpoissondistribution(const ae_int_t k, const double y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::invpoissondistribution(k, y, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_BESSEL) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Bessel function of order zero - -Returns Bessel function of order zero of the argument. - -The domain is divided into the intervals [0, 5] and -(5, infinity). In the first interval the following rational -approximation is used: - - - 2 2 -(w - r ) (w - r ) P (w) / Q (w) - 1 2 3 8 - - 2 -where w = x and the two r's are zeros of the function. - -In the second interval, the Hankel asymptotic expansion -is employed with two rational functions of degree 6/6 -and 7/7. - -ACCURACY: - - Absolute error: -arithmetic domain # trials peak rms - IEEE 0, 30 60000 4.2e-16 1.1e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -double besselj0(const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::besselj0(x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Bessel function of order one - -Returns Bessel function of order one of the argument. - -The domain is divided into the intervals [0, 8] and -(8, infinity). In the first interval a 24 term Chebyshev -expansion is used. In the second, the asymptotic -trigonometric representation is employed using two -rational functions of degree 5/5. - -ACCURACY: - - Absolute error: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 2.6e-16 1.1e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -double besselj1(const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::besselj1(x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Bessel function of integer order - -Returns Bessel function of order n, where n is a -(possibly negative) integer. - -The ratio of jn(x) to j0(x) is computed by backward -recurrence. First the ratio jn/jn-1 is found by a -continued fraction expansion. Then the recurrence -relating successive orders is applied until j0 or j1 is -reached. - -If n = 0 or 1 the routine for j0 or j1 is called -directly. - -ACCURACY: - - Absolute error: -arithmetic range # trials peak rms - IEEE 0, 30 5000 4.4e-16 7.9e-17 - - -Not suitable for large n or x. Use jv() (fractional order) instead. - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double besseljn(const ae_int_t n, const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::besseljn(n, x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Bessel function of the second kind, order zero - -Returns Bessel function of the second kind, of order -zero, of the argument. - -The domain is divided into the intervals [0, 5] and -(5, infinity). In the first interval a rational approximation -R(x) is employed to compute - y0(x) = R(x) + 2 * log(x) * j0(x) / PI. -Thus a call to j0() is required. - -In the second interval, the Hankel asymptotic expansion -is employed with two rational functions of degree 6/6 -and 7/7. - - - -ACCURACY: - - Absolute error, when y0(x) < 1; else relative error: - -arithmetic domain # trials peak rms - IEEE 0, 30 30000 1.3e-15 1.6e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -double bessely0(const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::bessely0(x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Bessel function of second kind of order one - -Returns Bessel function of the second kind of order one -of the argument. - -The domain is divided into the intervals [0, 8] and -(8, infinity). In the first interval a 25 term Chebyshev -expansion is used, and a call to j1() is required. -In the second, the asymptotic trigonometric representation -is employed using two rational functions of degree 5/5. - -ACCURACY: - - Absolute error: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 1.0e-15 1.3e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -double bessely1(const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::bessely1(x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Bessel function of second kind of integer order - -Returns Bessel function of order n, where n is a -(possibly negative) integer. - -The function is evaluated by forward recurrence on -n, starting with values computed by the routines -y0() and y1(). - -If n = 0 or 1 the routine for y0 or y1 is called -directly. - -ACCURACY: - Absolute error, except relative - when y > 1: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 3.4e-15 4.3e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double besselyn(const ae_int_t n, const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::besselyn(n, x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Modified Bessel function of order zero - -Returns modified Bessel function of order zero of the -argument. - -The function is defined as i0(x) = j0( ix ). - -The range is partitioned into the two intervals [0,8] and -(8, infinity). Chebyshev polynomial expansions are employed -in each interval. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,30 30000 5.8e-16 1.4e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double besseli0(const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::besseli0(x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Modified Bessel function of order one - -Returns modified Bessel function of order one of the -argument. - -The function is defined as i1(x) = -i j1( ix ). - -The range is partitioned into the two intervals [0,8] and -(8, infinity). Chebyshev polynomial expansions are employed -in each interval. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 1.9e-15 2.1e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1985, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double besseli1(const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::besseli1(x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Modified Bessel function, second kind, order zero - -Returns modified Bessel function of the second kind -of order zero of the argument. - -The range is partitioned into the two intervals [0,8] and -(8, infinity). Chebyshev polynomial expansions are employed -in each interval. - -ACCURACY: - -Tested at 2000 random points between 0 and 8. Peak absolute -error (relative when K0 > 1) was 1.46e-14; rms, 4.26e-15. - Relative error: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 1.2e-15 1.6e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double besselk0(const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::besselk0(x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Modified Bessel function, second kind, order one - -Computes the modified Bessel function of the second kind -of order one of the argument. - -The range is partitioned into the two intervals [0,2] and -(2, infinity). Chebyshev polynomial expansions are employed -in each interval. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 1.2e-15 1.6e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double besselk1(const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::besselk1(x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Modified Bessel function, second kind, integer order - -Returns modified Bessel function of the second kind -of order n of the argument. - -The range is partitioned into the two intervals [0,9.55] and -(9.55, infinity). An ascending power series is used in the -low range, and an asymptotic expansion in the high range. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,30 90000 1.8e-8 3.0e-10 - -Error is high only near the crossover point x = 9.55 -between the two expansions used. - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 2000 by Stephen L. Moshier -*************************************************************************/ -double besselkn(const ae_int_t nn, const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::besselkn(nn, x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_IBETAF) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Incomplete beta integral - -Returns incomplete beta integral of the arguments, evaluated -from zero to x. The function is defined as - - x - - - - | (a+b) | | a-1 b-1 - ----------- | t (1-t) dt. - - - | | - | (a) | (b) - - 0 - -The domain of definition is 0 <= x <= 1. In this -implementation a and b are restricted to positive values. -The integral from x to 1 may be obtained by the symmetry -relation - - 1 - incbet( a, b, x ) = incbet( b, a, 1-x ). - -The integral is evaluated by a continued fraction expansion -or, when b*x is small, by a power series. - -ACCURACY: - -Tested at uniformly distributed random points (a,b,x) with a and b -in "domain" and x between 0 and 1. - Relative error -arithmetic domain # trials peak rms - IEEE 0,5 10000 6.9e-15 4.5e-16 - IEEE 0,85 250000 2.2e-13 1.7e-14 - IEEE 0,1000 30000 5.3e-12 6.3e-13 - IEEE 0,10000 250000 9.3e-11 7.1e-12 - IEEE 0,100000 10000 8.7e-10 4.8e-11 -Outputs smaller than the IEEE gradual underflow threshold -were excluded from these statistics. - -Cephes Math Library, Release 2.8: June, 2000 -Copyright 1984, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double incompletebeta(const double a, const double b, const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::incompletebeta(a, b, x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Inverse of imcomplete beta integral - -Given y, the function finds x such that - - incbet( a, b, x ) = y . - -The routine performs interval halving or Newton iterations to find the -root of incbet(a,b,x) - y = 0. - - -ACCURACY: - - Relative error: - x a,b -arithmetic domain domain # trials peak rms - IEEE 0,1 .5,10000 50000 5.8e-12 1.3e-13 - IEEE 0,1 .25,100 100000 1.8e-13 3.9e-15 - IEEE 0,1 0,5 50000 1.1e-12 5.5e-15 -With a and b constrained to half-integer or integer values: - IEEE 0,1 .5,10000 50000 5.8e-12 1.1e-13 - IEEE 0,1 .5,100 100000 1.7e-14 7.9e-16 -With a = .5, b constrained to half-integer or integer values: - IEEE 0,1 .5,10000 10000 8.3e-11 1.0e-11 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1996, 2000 by Stephen L. Moshier -*************************************************************************/ -double invincompletebeta(const double a, const double b, const double y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::invincompletebeta(a, b, y, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_FDISTR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -F distribution - -Returns the area from zero to x under the F density -function (also known as Snedcor's density or the -variance ratio density). This is the density -of x = (u1/df1)/(u2/df2), where u1 and u2 are random -variables having Chi square distributions with df1 -and df2 degrees of freedom, respectively. -The incomplete beta integral is used, according to the -formula - -P(x) = incbet( df1/2, df2/2, (df1*x/(df2 + df1*x) ). - - -The arguments a and b are greater than zero, and x is -nonnegative. - -ACCURACY: - -Tested at random points (a,b,x). - - x a,b Relative error: -arithmetic domain domain # trials peak rms - IEEE 0,1 0,100 100000 9.8e-15 1.7e-15 - IEEE 1,5 0,100 100000 6.5e-15 3.5e-16 - IEEE 0,1 1,10000 100000 2.2e-11 3.3e-12 - IEEE 1,5 1,10000 100000 1.1e-11 1.7e-13 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double fdistribution(const ae_int_t a, const ae_int_t b, const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::fdistribution(a, b, x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Complemented F distribution - -Returns the area from x to infinity under the F density -function (also known as Snedcor's density or the -variance ratio density). - - - inf. - - - 1 | | a-1 b-1 -1-P(x) = ------ | t (1-t) dt - B(a,b) | | - - - x - - -The incomplete beta integral is used, according to the -formula - -P(x) = incbet( df2/2, df1/2, (df2/(df2 + df1*x) ). - - -ACCURACY: - -Tested at random points (a,b,x) in the indicated intervals. - x a,b Relative error: -arithmetic domain domain # trials peak rms - IEEE 0,1 1,100 100000 3.7e-14 5.9e-16 - IEEE 1,5 1,100 100000 8.0e-15 1.6e-15 - IEEE 0,1 1,10000 100000 1.8e-11 3.5e-13 - IEEE 1,5 1,10000 100000 2.0e-11 3.0e-12 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double fcdistribution(const ae_int_t a, const ae_int_t b, const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::fcdistribution(a, b, x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Inverse of complemented F distribution - -Finds the F density argument x such that the integral -from x to infinity of the F density is equal to the -given probability p. - -This is accomplished using the inverse beta integral -function and the relations - - z = incbi( df2/2, df1/2, p ) - x = df2 (1-z) / (df1 z). - -Note: the following relations hold for the inverse of -the uncomplemented F distribution: - - z = incbi( df1/2, df2/2, p ) - x = df2 z / (df1 (1-z)). - -ACCURACY: - -Tested at random points (a,b,p). - - a,b Relative error: -arithmetic domain # trials peak rms - For p between .001 and 1: - IEEE 1,100 100000 8.3e-15 4.7e-16 - IEEE 1,10000 100000 2.1e-11 1.4e-13 - For p between 10^-6 and 10^-3: - IEEE 1,100 50000 1.3e-12 8.4e-15 - IEEE 1,10000 50000 3.0e-12 4.8e-14 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double invfdistribution(const ae_int_t a, const ae_int_t b, const double y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::invfdistribution(a, b, y, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_FRESNEL) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Fresnel integral - -Evaluates the Fresnel integrals - - x - - - | | -C(x) = | cos(pi/2 t**2) dt, - | | - - - 0 - - x - - - | | -S(x) = | sin(pi/2 t**2) dt. - | | - - - 0 - - -The integrals are evaluated by a power series for x < 1. -For x >= 1 auxiliary functions f(x) and g(x) are employed -such that - -C(x) = 0.5 + f(x) sin( pi/2 x**2 ) - g(x) cos( pi/2 x**2 ) -S(x) = 0.5 - f(x) cos( pi/2 x**2 ) - g(x) sin( pi/2 x**2 ) - - - -ACCURACY: - - Relative error. - -Arithmetic function domain # trials peak rms - IEEE S(x) 0, 10 10000 2.0e-15 3.2e-16 - IEEE C(x) 0, 10 10000 1.8e-15 3.3e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -void fresnelintegral(const double x, double &c, double &s, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::fresnelintegral(x, &c, &s, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_JACOBIANELLIPTIC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Jacobian Elliptic Functions - -Evaluates the Jacobian elliptic functions sn(u|m), cn(u|m), -and dn(u|m) of parameter m between 0 and 1, and real -argument u. - -These functions are periodic, with quarter-period on the -real axis equal to the complete elliptic integral -ellpk(1.0-m). - -Relation to incomplete elliptic integral: -If u = ellik(phi,m), then sn(u|m) = sin(phi), -and cn(u|m) = cos(phi). Phi is called the amplitude of u. - -Computation is by means of the arithmetic-geometric mean -algorithm, except when m is within 1e-9 of 0 or 1. In the -latter case with m close to 1, the approximation applies -only for phi < pi/2. - -ACCURACY: - -Tested at random points with u between 0 and 10, m between -0 and 1. - - Absolute error (* = relative error): -arithmetic function # trials peak rms - IEEE phi 10000 9.2e-16* 1.4e-16* - IEEE sn 50000 4.1e-15 4.6e-16 - IEEE cn 40000 3.6e-15 4.4e-16 - IEEE dn 10000 1.3e-12 1.8e-14 - - Peak error observed in consistency check using addition -theorem for sn(u+v) was 4e-16 (absolute). Also tested by -the above relation to the incomplete elliptic integral. -Accuracy deteriorates when u is large. - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -void jacobianellipticfunctions(const double u, const double m, double &sn, double &cn, double &dn, double &ph, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::jacobianellipticfunctions(u, m, &sn, &cn, &dn, &ph, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_PSIF) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Psi (digamma) function - - d - - psi(x) = -- ln | (x) - dx - -is the logarithmic derivative of the gamma function. -For integer x, - n-1 - - -psi(n) = -EUL + > 1/k. - - - k=1 - -This formula is used for 0 < n <= 10. If x is negative, it -is transformed to a positive argument by the reflection -formula psi(1-x) = psi(x) + pi cot(pi x). -For general positive x, the argument is made greater than 10 -using the recurrence psi(x+1) = psi(x) + 1/x. -Then the following asymptotic expansion is applied: - - inf. B - - 2k -psi(x) = log(x) - 1/2x - > ------- - - 2k - k=1 2k x - -where the B2k are Bernoulli numbers. - -ACCURACY: - Relative error (except absolute when |psi| < 1): -arithmetic domain # trials peak rms - IEEE 0,30 30000 1.3e-15 1.4e-16 - IEEE -30,0 40000 1.5e-15 2.2e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double psi(const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::psi(x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_EXPINTEGRALS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Exponential integral Ei(x) - - x - - t - | | e - Ei(x) = -|- --- dt . - | | t - - - -inf - -Not defined for x <= 0. -See also expn.c. - - - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,100 50000 8.6e-16 1.3e-16 - -Cephes Math Library Release 2.8: May, 1999 -Copyright 1999 by Stephen L. Moshier -*************************************************************************/ -double exponentialintegralei(const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::exponentialintegralei(x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Exponential integral En(x) - -Evaluates the exponential integral - - inf. - - - | | -xt - | e - E (x) = | ---- dt. - n | n - | | t - - - 1 - - -Both n and x must be nonnegative. - -The routine employs either a power series, a continued -fraction, or an asymptotic formula depending on the -relative values of n and x. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0, 30 10000 1.7e-15 3.6e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1985, 2000 by Stephen L. Moshier -*************************************************************************/ -double exponentialintegralen(const double x, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::exponentialintegralen(x, n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_LAGUERRE) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Calculation of the value of the Laguerre polynomial. - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Laguerre polynomial Ln at x -*************************************************************************/ -double laguerrecalculate(const ae_int_t n, const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::laguerrecalculate(n, x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Summation of Laguerre polynomials using Clenshaw's recurrence formula. - -This routine calculates c[0]*L0(x) + c[1]*L1(x) + ... + c[N]*LN(x) - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Laguerre polynomial at x -*************************************************************************/ -double laguerresum(const real_1d_array &c, const ae_int_t n, const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::laguerresum(const_cast(c.c_ptr()), n, x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Representation of Ln as C[0] + C[1]*X + ... + C[N]*X^N - -Input parameters: - N - polynomial degree, n>=0 - -Output parameters: - C - coefficients -*************************************************************************/ -void laguerrecoefficients(const ae_int_t n, real_1d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::laguerrecoefficients(n, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_CHISQUAREDISTR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Chi-square distribution - -Returns the area under the left hand tail (from 0 to x) -of the Chi square probability density function with -v degrees of freedom. - - - x - - - 1 | | v/2-1 -t/2 - P( x | v ) = ----------- | t e dt - v/2 - | | - 2 | (v/2) - - 0 - -where x is the Chi-square variable. - -The incomplete gamma integral is used, according to the -formula - -y = chdtr( v, x ) = igam( v/2.0, x/2.0 ). - -The arguments must both be positive. - -ACCURACY: - -See incomplete gamma function - - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double chisquaredistribution(const double v, const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::chisquaredistribution(v, x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Complemented Chi-square distribution - -Returns the area under the right hand tail (from x to -infinity) of the Chi square probability density function -with v degrees of freedom: - - inf. - - - 1 | | v/2-1 -t/2 - P( x | v ) = ----------- | t e dt - v/2 - | | - 2 | (v/2) - - x - -where x is the Chi-square variable. - -The incomplete gamma integral is used, according to the -formula - -y = chdtr( v, x ) = igamc( v/2.0, x/2.0 ). - -The arguments must both be positive. - -ACCURACY: - -See incomplete gamma function - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double chisquarecdistribution(const double v, const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::chisquarecdistribution(v, x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Inverse of complemented Chi-square distribution - -Finds the Chi-square argument x such that the integral -from x to infinity of the Chi-square density is equal -to the given cumulative probability y. - -This is accomplished using the inverse gamma integral -function and the relation - - x/2 = igami( df/2, y ); - -ACCURACY: - -See inverse incomplete gamma function - - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double invchisquaredistribution(const double v, const double y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::invchisquaredistribution(v, y, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_LEGENDRE) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Calculation of the value of the Legendre polynomial Pn. - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Legendre polynomial Pn at x -*************************************************************************/ -double legendrecalculate(const ae_int_t n, const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::legendrecalculate(n, x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Summation of Legendre polynomials using Clenshaw's recurrence formula. - -This routine calculates - c[0]*P0(x) + c[1]*P1(x) + ... + c[N]*PN(x) - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Legendre polynomial at x -*************************************************************************/ -double legendresum(const real_1d_array &c, const ae_int_t n, const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::legendresum(const_cast(c.c_ptr()), n, x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Representation of Pn as C[0] + C[1]*X + ... + C[N]*X^N - -Input parameters: - N - polynomial degree, n>=0 - -Output parameters: - C - coefficients -*************************************************************************/ -void legendrecoefficients(const ae_int_t n, real_1d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::legendrecoefficients(n, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_BETAF) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Beta function - - - - - - | (a) | (b) -beta( a, b ) = -----------. - - - | (a+b) - -For large arguments the logarithm of the function is -evaluated using lgam(), then exponentiated. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,30 30000 8.1e-14 1.1e-14 - -Cephes Math Library Release 2.0: April, 1987 -Copyright 1984, 1987 by Stephen L. Moshier -*************************************************************************/ -double beta(const double a, const double b, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::beta(a, b, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_CHEBYSHEV) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Calculation of the value of the Chebyshev polynomials of the -first and second kinds. - -Parameters: - r - polynomial kind, either 1 or 2. - n - degree, n>=0 - x - argument, -1 <= x <= 1 - -Result: - the value of the Chebyshev polynomial at x -*************************************************************************/ -double chebyshevcalculate(const ae_int_t r, const ae_int_t n, const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::chebyshevcalculate(r, n, x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Summation of Chebyshev polynomials using Clenshaw's recurrence formula. - -This routine calculates - c[0]*T0(x) + c[1]*T1(x) + ... + c[N]*TN(x) -or - c[0]*U0(x) + c[1]*U1(x) + ... + c[N]*UN(x) -depending on the R. - -Parameters: - r - polynomial kind, either 1 or 2. - n - degree, n>=0 - x - argument - -Result: - the value of the Chebyshev polynomial at x -*************************************************************************/ -double chebyshevsum(const real_1d_array &c, const ae_int_t r, const ae_int_t n, const double x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::chebyshevsum(const_cast(c.c_ptr()), r, n, x, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Representation of Tn as C[0] + C[1]*X + ... + C[N]*X^N - -Input parameters: - N - polynomial degree, n>=0 - -Output parameters: - C - coefficients -*************************************************************************/ -void chebyshevcoefficients(const ae_int_t n, real_1d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::chebyshevcoefficients(n, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Conversion of a series of Chebyshev polynomials to a power series. - -Represents A[0]*T0(x) + A[1]*T1(x) + ... + A[N]*Tn(x) as -B[0] + B[1]*X + ... + B[N]*X^N. - -Input parameters: - A - Chebyshev series coefficients - N - degree, N>=0 - -Output parameters - B - power series coefficients -*************************************************************************/ -void fromchebyshev(const real_1d_array &a, const ae_int_t n, real_1d_array &b, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::fromchebyshev(const_cast(a.c_ptr()), n, const_cast(b.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_STUDENTTDISTR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Student's t distribution - -Computes the integral from minus infinity to t of the Student -t distribution with integer k > 0 degrees of freedom: - - t - - - | | - - | 2 -(k+1)/2 - | ( (k+1)/2 ) | ( x ) - ---------------------- | ( 1 + --- ) dx - - | ( k ) - sqrt( k pi ) | ( k/2 ) | - | | - - - -inf. - -Relation to incomplete beta integral: - - 1 - stdtr(k,t) = 0.5 * incbet( k/2, 1/2, z ) -where - z = k/(k + t**2). - -For t < -2, this is the method of computation. For higher t, -a direct method is derived from integration by parts. -Since the function is symmetric about t=0, the area under the -right tail of the density is found by calling the function -with -t instead of t. - -ACCURACY: - -Tested at random 1 <= k <= 25. The "domain" refers to t. - Relative error: -arithmetic domain # trials peak rms - IEEE -100,-2 50000 5.9e-15 1.4e-15 - IEEE -2,100 500000 2.7e-15 4.9e-17 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double studenttdistribution(const ae_int_t k, const double t, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::studenttdistribution(k, t, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Functional inverse of Student's t distribution - -Given probability p, finds the argument t such that stdtr(k,t) -is equal to p. - -ACCURACY: - -Tested at random 1 <= k <= 100. The "domain" refers to p: - Relative error: -arithmetic domain # trials peak rms - IEEE .001,.999 25000 5.7e-15 8.0e-16 - IEEE 10^-6,.001 25000 2.0e-12 2.9e-14 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double invstudenttdistribution(const ae_int_t k, const double p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::invstudenttdistribution(k, p, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_BINOMIALDISTR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Binomial distribution - -Returns the sum of the terms 0 through k of the Binomial -probability density: - - k - -- ( n ) j n-j - > ( ) p (1-p) - -- ( j ) - j=0 - -The terms are not summed directly; instead the incomplete -beta integral is employed, according to the formula - -y = bdtr( k, n, p ) = incbet( n-k, k+1, 1-p ). - -The arguments must be positive, with p ranging from 0 to 1. - -ACCURACY: - -Tested at random points (a,b,p), with p between 0 and 1. - - a,b Relative error: -arithmetic domain # trials peak rms - For p between 0.001 and 1: - IEEE 0,100 100000 4.3e-15 2.6e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double binomialdistribution(const ae_int_t k, const ae_int_t n, const double p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::binomialdistribution(k, n, p, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Complemented binomial distribution - -Returns the sum of the terms k+1 through n of the Binomial -probability density: - - n - -- ( n ) j n-j - > ( ) p (1-p) - -- ( j ) - j=k+1 - -The terms are not summed directly; instead the incomplete -beta integral is employed, according to the formula - -y = bdtrc( k, n, p ) = incbet( k+1, n-k, p ). - -The arguments must be positive, with p ranging from 0 to 1. - -ACCURACY: - -Tested at random points (a,b,p). - - a,b Relative error: -arithmetic domain # trials peak rms - For p between 0.001 and 1: - IEEE 0,100 100000 6.7e-15 8.2e-16 - For p between 0 and .001: - IEEE 0,100 100000 1.5e-13 2.7e-15 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double binomialcdistribution(const ae_int_t k, const ae_int_t n, const double p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::binomialcdistribution(k, n, p, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Inverse binomial distribution - -Finds the event probability p such that the sum of the -terms 0 through k of the Binomial probability density -is equal to the given cumulative probability y. - -This is accomplished using the inverse beta integral -function and the relation - -1 - p = incbi( n-k, k+1, y ). - -ACCURACY: - -Tested at random points (a,b,p). - - a,b Relative error: -arithmetic domain # trials peak rms - For p between 0.001 and 1: - IEEE 0,100 100000 2.3e-14 6.4e-16 - IEEE 0,10000 100000 6.6e-12 1.2e-13 - For p between 10^-6 and 0.001: - IEEE 0,100 100000 2.0e-12 1.3e-14 - IEEE 0,10000 100000 1.5e-12 3.2e-14 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double invbinomialdistribution(const ae_int_t k, const ae_int_t n, const double y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::invbinomialdistribution(k, n, y, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_AIRYF) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Airy function - -Solution of the differential equation - -y"(x) = xy. - -The function returns the two independent solutions Ai, Bi -and their first derivatives Ai'(x), Bi'(x). - -Evaluation is by power series summation for small x, -by rational minimax approximations for large x. - - - -ACCURACY: -Error criterion is absolute when function <= 1, relative -when function > 1, except * denotes relative error criterion. -For large negative x, the absolute error increases as x^1.5. -For large positive x, the relative error increases as x^1.5. - -Arithmetic domain function # trials peak rms -IEEE -10, 0 Ai 10000 1.6e-15 2.7e-16 -IEEE 0, 10 Ai 10000 2.3e-14* 1.8e-15* -IEEE -10, 0 Ai' 10000 4.6e-15 7.6e-16 -IEEE 0, 10 Ai' 10000 1.8e-14* 1.5e-15* -IEEE -10, 10 Bi 30000 4.2e-15 5.3e-16 -IEEE -10, 10 Bi' 30000 4.9e-15 7.3e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -void airy(const double x, double &ai, double &aip, double &bi, double &bip, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::airy(x, &ai, &aip, &bi, &bip, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF COMPUTATIONAL CORE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_GAMMAFUNC) || !defined(AE_PARTIAL_BUILD) -static double gammafunc_gammastirf(double x, ae_state *_state); - - -#endif -#if defined(AE_COMPILE_NORMALDISTR) || !defined(AE_PARTIAL_BUILD) -static double normaldistr_bvnintegrate3(double rangea, - double rangeb, - double x, - double y, - double gw, - double gx, - ae_state *_state); -static double normaldistr_bvnintegrate6(double rangea, - double rangeb, - double x, - double y, - double s, - double gw, - double gx, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_IGAMMAF) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_ELLIPTIC) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_HERMITE) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_DAWSON) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_TRIGINTEGRALS) || !defined(AE_PARTIAL_BUILD) -static void trigintegrals_chebiterationshichi(double x, - double c, - double* b0, - double* b1, - double* b2, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_POISSONDISTR) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_BESSEL) || !defined(AE_PARTIAL_BUILD) -static void bessel_besselmfirstcheb(double c, - double* b0, - double* b1, - double* b2, - ae_state *_state); -static void bessel_besselmnextcheb(double x, - double c, - double* b0, - double* b1, - double* b2, - ae_state *_state); -static void bessel_besselm1firstcheb(double c, - double* b0, - double* b1, - double* b2, - ae_state *_state); -static void bessel_besselm1nextcheb(double x, - double c, - double* b0, - double* b1, - double* b2, - ae_state *_state); -static void bessel_besselasympt0(double x, - double* pzero, - double* qzero, - ae_state *_state); -static void bessel_besselasympt1(double x, - double* pzero, - double* qzero, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_IBETAF) || !defined(AE_PARTIAL_BUILD) -static double ibetaf_incompletebetafe(double a, - double b, - double x, - double big, - double biginv, - ae_state *_state); -static double ibetaf_incompletebetafe2(double a, - double b, - double x, - double big, - double biginv, - ae_state *_state); -static double ibetaf_incompletebetaps(double a, - double b, - double x, - double maxgam, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_FDISTR) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_FRESNEL) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_JACOBIANELLIPTIC) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_PSIF) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_EXPINTEGRALS) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_LAGUERRE) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_CHISQUAREDISTR) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_LEGENDRE) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_BETAF) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_CHEBYSHEV) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_STUDENTTDISTR) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_BINOMIALDISTR) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_AIRYF) || !defined(AE_PARTIAL_BUILD) - - -#endif - -#if defined(AE_COMPILE_GAMMAFUNC) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Gamma function - -Input parameters: - X - argument - -Domain: - 0 < X < 171.6 - -170 < X < 0, X is not an integer. - -Relative error: - arithmetic domain # trials peak rms - IEEE -170,-33 20000 2.3e-15 3.3e-16 - IEEE -33, 33 20000 9.4e-16 2.2e-16 - IEEE 33, 171.6 20000 2.3e-15 3.2e-16 - -Cephes Math Library Release 2.8: June, 2000 -Original copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier -Translated to AlgoPascal by Bochkanov Sergey (2005, 2006, 2007). -*************************************************************************/ -double gammafunction(double x, ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_SPECFUNCS - double p; - double pp; - double q; - double qq; - double z; - ae_int_t i; - double sgngam; - double result; - - - sgngam = (double)(1); - q = ae_fabs(x, _state); - if( ae_fp_greater(q,33.0) ) - { - if( ae_fp_less(x,0.0) ) - { - p = (double)(ae_ifloor(q, _state)); - i = ae_round(p, _state); - if( i%2==0 ) - { - sgngam = (double)(-1); - } - z = q-p; - if( ae_fp_greater(z,0.5) ) - { - p = p+1; - z = q-p; - } - z = q*ae_sin(ae_pi*z, _state); - z = ae_fabs(z, _state); - z = ae_pi/(z*gammafunc_gammastirf(q, _state)); - } - else - { - z = gammafunc_gammastirf(x, _state); - } - result = sgngam*z; - return result; - } - z = (double)(1); - while(ae_fp_greater_eq(x,(double)(3))) - { - x = x-1; - z = z*x; - } - while(ae_fp_less(x,(double)(0))) - { - if( ae_fp_greater(x,-0.000000001) ) - { - result = z/((1+0.5772156649015329*x)*x); - return result; - } - z = z/x; - x = x+1; - } - while(ae_fp_less(x,(double)(2))) - { - if( ae_fp_less(x,0.000000001) ) - { - result = z/((1+0.5772156649015329*x)*x); - return result; - } - z = z/x; - x = x+1.0; - } - if( ae_fp_eq(x,(double)(2)) ) - { - result = z; - return result; - } - x = x-2.0; - pp = 1.60119522476751861407E-4; - pp = 1.19135147006586384913E-3+x*pp; - pp = 1.04213797561761569935E-2+x*pp; - pp = 4.76367800457137231464E-2+x*pp; - pp = 2.07448227648435975150E-1+x*pp; - pp = 4.94214826801497100753E-1+x*pp; - pp = 9.99999999999999996796E-1+x*pp; - qq = -2.31581873324120129819E-5; - qq = 5.39605580493303397842E-4+x*qq; - qq = -4.45641913851797240494E-3+x*qq; - qq = 1.18139785222060435552E-2+x*qq; - qq = 3.58236398605498653373E-2+x*qq; - qq = -2.34591795718243348568E-1+x*qq; - qq = 7.14304917030273074085E-2+x*qq; - qq = 1.00000000000000000320+x*qq; - result = z*pp/qq; - return result; -#else - return _ialglib_i_gammafunction(x); -#endif -} - - -/************************************************************************* -Natural logarithm of gamma function - -Input parameters: - X - argument - -Result: - logarithm of the absolute value of the Gamma(X). - -Output parameters: - SgnGam - sign(Gamma(X)) - -Domain: - 0 < X < 2.55e305 - -2.55e305 < X < 0, X is not an integer. - -ACCURACY: -arithmetic domain # trials peak rms - IEEE 0, 3 28000 5.4e-16 1.1e-16 - IEEE 2.718, 2.556e305 40000 3.5e-16 8.3e-17 -The error criterion was relative when the function magnitude -was greater than one but absolute when it was less than one. - -The following test used the relative error criterion, though -at certain points the relative error could be much higher than -indicated. - IEEE -200, -4 10000 4.8e-16 1.3e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier -Translated to AlgoPascal by Bochkanov Sergey (2005, 2006, 2007). -*************************************************************************/ -double lngamma(double x, double* sgngam, ae_state *_state) -{ -#ifndef ALGLIB_INTERCEPTS_SPECFUNCS - double a; - double b; - double c; - double p; - double q; - double u; - double w; - double z; - ae_int_t i; - double logpi; - double ls2pi; - double tmp; - double result; - - *sgngam = 0; - - *sgngam = (double)(1); - logpi = 1.14472988584940017414; - ls2pi = 0.91893853320467274178; - if( ae_fp_less(x,-34.0) ) - { - q = -x; - w = lngamma(q, &tmp, _state); - p = (double)(ae_ifloor(q, _state)); - i = ae_round(p, _state); - if( i%2==0 ) - { - *sgngam = (double)(-1); - } - else - { - *sgngam = (double)(1); - } - z = q-p; - if( ae_fp_greater(z,0.5) ) - { - p = p+1; - z = p-q; - } - z = q*ae_sin(ae_pi*z, _state); - result = logpi-ae_log(z, _state)-w; - return result; - } - if( ae_fp_less(x,(double)(13)) ) - { - z = (double)(1); - p = (double)(0); - u = x; - while(ae_fp_greater_eq(u,(double)(3))) - { - p = p-1; - u = x+p; - z = z*u; - } - while(ae_fp_less(u,(double)(2))) - { - z = z/u; - p = p+1; - u = x+p; - } - if( ae_fp_less(z,(double)(0)) ) - { - *sgngam = (double)(-1); - z = -z; - } - else - { - *sgngam = (double)(1); - } - if( ae_fp_eq(u,(double)(2)) ) - { - result = ae_log(z, _state); - return result; - } - p = p-2; - x = x+p; - b = -1378.25152569120859100; - b = -38801.6315134637840924+x*b; - b = -331612.992738871184744+x*b; - b = -1162370.97492762307383+x*b; - b = -1721737.00820839662146+x*b; - b = -853555.664245765465627+x*b; - c = (double)(1); - c = -351.815701436523470549+x*c; - c = -17064.2106651881159223+x*c; - c = -220528.590553854454839+x*c; - c = -1139334.44367982507207+x*c; - c = -2532523.07177582951285+x*c; - c = -2018891.41433532773231+x*c; - p = x*b/c; - result = ae_log(z, _state)+p; - return result; - } - q = (x-0.5)*ae_log(x, _state)-x+ls2pi; - if( ae_fp_greater(x,(double)(100000000)) ) - { - result = q; - return result; - } - p = 1/(x*x); - if( ae_fp_greater_eq(x,1000.0) ) - { - q = q+((7.9365079365079365079365*0.0001*p-2.7777777777777777777778*0.001)*p+0.0833333333333333333333)/x; - } - else - { - a = 8.11614167470508450300*0.0001; - a = -5.95061904284301438324*0.0001+p*a; - a = 7.93650340457716943945*0.0001+p*a; - a = -2.77777777730099687205*0.001+p*a; - a = 8.33333333333331927722*0.01+p*a; - q = q+a/x; - } - result = q; - return result; -#else - return _ialglib_i_lngamma(x, sgngam); -#endif -} - - -static double gammafunc_gammastirf(double x, ae_state *_state) -{ - double y; - double w; - double v; - double stir; - double result; - - - w = 1/x; - stir = 7.87311395793093628397E-4; - stir = -2.29549961613378126380E-4+w*stir; - stir = -2.68132617805781232825E-3+w*stir; - stir = 3.47222221605458667310E-3+w*stir; - stir = 8.33333333333482257126E-2+w*stir; - w = 1+w*stir; - y = ae_exp(x, _state); - if( ae_fp_greater(x,143.01608) ) - { - v = ae_pow(x, 0.5*x-0.25, _state); - y = v*(v/y); - } - else - { - y = ae_pow(x, x-0.5, _state)/y; - } - result = 2.50662827463100050242*y*w; - return result; -} - - -#endif -#if defined(AE_COMPILE_NORMALDISTR) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Error function - -The integral is - - x - - - 2 | | 2 - erf(x) = -------- | exp( - t ) dt. - sqrt(pi) | | - - - 0 - -For 0 <= |x| < 1, erf(x) = x * P4(x**2)/Q5(x**2); otherwise -erf(x) = 1 - erfc(x). - - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,1 30000 3.7e-16 1.0e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double errorfunction(double x, ae_state *_state) -{ - double xsq; - double s; - double p; - double q; - double result; - - - s = (double)(ae_sign(x, _state)); - x = ae_fabs(x, _state); - if( ae_fp_less(x,0.5) ) - { - xsq = x*x; - p = 0.007547728033418631287834; - p = -0.288805137207594084924010+xsq*p; - p = 14.3383842191748205576712+xsq*p; - p = 38.0140318123903008244444+xsq*p; - p = 3017.82788536507577809226+xsq*p; - p = 7404.07142710151470082064+xsq*p; - p = 80437.3630960840172832162+xsq*p; - q = 0.0; - q = 1.00000000000000000000000+xsq*q; - q = 38.0190713951939403753468+xsq*q; - q = 658.070155459240506326937+xsq*q; - q = 6379.60017324428279487120+xsq*q; - q = 34216.5257924628539769006+xsq*q; - q = 80437.3630960840172826266+xsq*q; - result = s*1.1283791670955125738961589031*x*p/q; - return result; - } - if( ae_fp_greater_eq(x,(double)(10)) ) - { - result = s; - return result; - } - result = s*(1-errorfunctionc(x, _state)); - return result; -} - - -/************************************************************************* -Complementary error function - - 1 - erf(x) = - - inf. - - - 2 | | 2 - erfc(x) = -------- | exp( - t ) dt - sqrt(pi) | | - - - x - - -For small x, erfc(x) = 1 - erf(x); otherwise rational -approximations are computed. - - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,26.6417 30000 5.7e-14 1.5e-14 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double errorfunctionc(double x, ae_state *_state) -{ - double p; - double q; - double result; - - - if( ae_fp_less(x,(double)(0)) ) - { - result = 2-errorfunctionc(-x, _state); - return result; - } - if( ae_fp_less(x,0.5) ) - { - result = 1.0-errorfunction(x, _state); - return result; - } - if( ae_fp_greater_eq(x,(double)(10)) ) - { - result = (double)(0); - return result; - } - p = 0.0; - p = 0.5641877825507397413087057563+x*p; - p = 9.675807882987265400604202961+x*p; - p = 77.08161730368428609781633646+x*p; - p = 368.5196154710010637133875746+x*p; - p = 1143.262070703886173606073338+x*p; - p = 2320.439590251635247384768711+x*p; - p = 2898.0293292167655611275846+x*p; - p = 1826.3348842295112592168999+x*p; - q = 1.0; - q = 17.14980943627607849376131193+x*q; - q = 137.1255960500622202878443578+x*q; - q = 661.7361207107653469211984771+x*q; - q = 2094.384367789539593790281779+x*q; - q = 4429.612803883682726711528526+x*q; - q = 6089.5424232724435504633068+x*q; - q = 4958.82756472114071495438422+x*q; - q = 1826.3348842295112595576438+x*q; - result = ae_exp(-ae_sqr(x, _state), _state)*p/q; - return result; -} - - -/************************************************************************* -Same as normalcdf(), obsolete name. -*************************************************************************/ -double normaldistribution(double x, ae_state *_state) -{ - double result; - - - result = 0.5*(errorfunction(x/1.41421356237309504880, _state)+1); - return result; -} - - -/************************************************************************* -Normal distribution PDF - -Returns Gaussian probability density function: - - 1 - f(x) = --------- * exp(-x^2/2) - sqrt(2pi) - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double normalpdf(double x, ae_state *_state) -{ - double result; - - - ae_assert(ae_isfinite(x, _state), "NormalPDF: X is infinite", _state); - result = ae_exp(-x*x/2, _state)/ae_sqrt(2*ae_pi, _state); - return result; -} - - -/************************************************************************* -Normal distribution CDF - -Returns the area under the Gaussian probability density -function, integrated from minus infinity to x: - - x - - - 1 | | 2 - ndtr(x) = --------- | exp( - t /2 ) dt - sqrt(2pi) | | - - - -inf. - - = ( 1 + erf(z) ) / 2 - = erfc(z) / 2 - -where z = x/sqrt(2). Computation is via the functions -erf and erfc. - - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE -13,0 30000 3.4e-14 6.7e-15 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double normalcdf(double x, ae_state *_state) -{ - double result; - - - result = 0.5*(errorfunction(x/1.41421356237309504880, _state)+1); - return result; -} - - -/************************************************************************* -Inverse of the error function - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double inverf(double e, ae_state *_state) -{ - double result; - - - result = invnormaldistribution(0.5*(e+1), _state)/ae_sqrt((double)(2), _state); - return result; -} - - -/************************************************************************* -Same as invnormalcdf(), deprecated name -*************************************************************************/ -double invnormaldistribution(double y0, ae_state *_state) -{ - double result; - - - result = invnormalcdf(y0, _state); - return result; -} - - -/************************************************************************* -Inverse of Normal CDF - -Returns the argument, x, for which the area under the -Gaussian probability density function (integrated from -minus infinity to x) is equal to y. - - -For small arguments 0 < y < exp(-2), the program computes -z = sqrt( -2.0 * log(y) ); then the approximation is -x = z - log(z)/z - (1/z) P(1/z) / Q(1/z). -There are two rational functions P/Q, one for 0 < y < exp(-32) -and the other for y up to exp(-2). For larger arguments, -w = y - 0.5, and x/sqrt(2pi) = w + w**3 R(w**2)/S(w**2)). - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0.125, 1 20000 7.2e-16 1.3e-16 - IEEE 3e-308, 0.135 50000 4.6e-16 9.8e-17 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double invnormalcdf(double y0, ae_state *_state) -{ - double expm2; - double s2pi; - double x; - double y; - double z; - double y2; - double x0; - double x1; - ae_int_t code; - double p0; - double q0; - double p1; - double q1; - double p2; - double q2; - double result; - - - expm2 = 0.13533528323661269189; - s2pi = 2.50662827463100050242; - if( ae_fp_less_eq(y0,(double)(0)) ) - { - result = -ae_maxrealnumber; - return result; - } - if( ae_fp_greater_eq(y0,(double)(1)) ) - { - result = ae_maxrealnumber; - return result; - } - code = 1; - y = y0; - if( ae_fp_greater(y,1.0-expm2) ) - { - y = 1.0-y; - code = 0; - } - if( ae_fp_greater(y,expm2) ) - { - y = y-0.5; - y2 = y*y; - p0 = -59.9633501014107895267; - p0 = 98.0010754185999661536+y2*p0; - p0 = -56.6762857469070293439+y2*p0; - p0 = 13.9312609387279679503+y2*p0; - p0 = -1.23916583867381258016+y2*p0; - q0 = (double)(1); - q0 = 1.95448858338141759834+y2*q0; - q0 = 4.67627912898881538453+y2*q0; - q0 = 86.3602421390890590575+y2*q0; - q0 = -225.462687854119370527+y2*q0; - q0 = 200.260212380060660359+y2*q0; - q0 = -82.0372256168333339912+y2*q0; - q0 = 15.9056225126211695515+y2*q0; - q0 = -1.18331621121330003142+y2*q0; - x = y+y*y2*p0/q0; - x = x*s2pi; - result = x; - return result; - } - x = ae_sqrt(-2.0*ae_log(y, _state), _state); - x0 = x-ae_log(x, _state)/x; - z = 1.0/x; - if( ae_fp_less(x,8.0) ) - { - p1 = 4.05544892305962419923; - p1 = 31.5251094599893866154+z*p1; - p1 = 57.1628192246421288162+z*p1; - p1 = 44.0805073893200834700+z*p1; - p1 = 14.6849561928858024014+z*p1; - p1 = 2.18663306850790267539+z*p1; - p1 = -1.40256079171354495875*0.1+z*p1; - p1 = -3.50424626827848203418*0.01+z*p1; - p1 = -8.57456785154685413611*0.0001+z*p1; - q1 = (double)(1); - q1 = 15.7799883256466749731+z*q1; - q1 = 45.3907635128879210584+z*q1; - q1 = 41.3172038254672030440+z*q1; - q1 = 15.0425385692907503408+z*q1; - q1 = 2.50464946208309415979+z*q1; - q1 = -1.42182922854787788574*0.1+z*q1; - q1 = -3.80806407691578277194*0.01+z*q1; - q1 = -9.33259480895457427372*0.0001+z*q1; - x1 = z*p1/q1; - } - else - { - p2 = 3.23774891776946035970; - p2 = 6.91522889068984211695+z*p2; - p2 = 3.93881025292474443415+z*p2; - p2 = 1.33303460815807542389+z*p2; - p2 = 2.01485389549179081538*0.1+z*p2; - p2 = 1.23716634817820021358*0.01+z*p2; - p2 = 3.01581553508235416007*0.0001+z*p2; - p2 = 2.65806974686737550832*0.000001+z*p2; - p2 = 6.23974539184983293730*0.000000001+z*p2; - q2 = (double)(1); - q2 = 6.02427039364742014255+z*q2; - q2 = 3.67983563856160859403+z*q2; - q2 = 1.37702099489081330271+z*q2; - q2 = 2.16236993594496635890*0.1+z*q2; - q2 = 1.34204006088543189037*0.01+z*q2; - q2 = 3.28014464682127739104*0.0001+z*q2; - q2 = 2.89247864745380683936*0.000001+z*q2; - q2 = 6.79019408009981274425*0.000000001+z*q2; - x1 = z*p2/q2; - } - x = x0-x1; - if( code!=0 ) - { - x = -x; - } - result = x; - return result; -} - - -/************************************************************************* -Bivariate normal PDF - -Returns probability density function of the bivariate Gaussian with -correlation parameter equal to Rho: - - 1 ( x^2 - 2*rho*x*y + y^2 ) - f(x,y,rho) = ----------------- * exp( - ----------------------- ) - 2pi*sqrt(1-rho^2) ( 2*(1-rho^2) ) - - -with -11 ) - { - d = 0.5*d+0.5; - } - else - { - d = (y0-yl)/(yh-yl); - } - } - dir = dir+1; - } - else - { - x0 = x; - yl = y; - if( dir>0 ) - { - dir = 0; - d = 0.5; - } - else - { - if( dir<-1 ) - { - d = 0.5*d; - } - else - { - d = (y0-yl)/(yh-yl); - } - } - dir = dir-1; - } - i = i+1; - } - result = x; - return result; -} - - -#endif -#if defined(AE_COMPILE_ELLIPTIC) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Complete elliptic integral of the first kind - -Approximates the integral - - - - pi/2 - - - | | - | dt -K(m) = | ------------------ - | 2 - | | sqrt( 1 - m sin t ) - - - 0 - -using the approximation - - P(x) - log x Q(x). - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,1 30000 2.5e-16 6.8e-17 - -Cephes Math Library, Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double ellipticintegralk(double m, ae_state *_state) -{ - double result; - - - result = ellipticintegralkhighprecision(1.0-m, _state); - return result; -} - - -/************************************************************************* -Complete elliptic integral of the first kind - -Approximates the integral - - - - pi/2 - - - | | - | dt -K(m) = | ------------------ - | 2 - | | sqrt( 1 - m sin t ) - - - 0 - -where m = 1 - m1, using the approximation - - P(x) - log x Q(x). - -The argument m1 is used rather than m so that the logarithmic -singularity at m = 1 will be shifted to the origin; this -preserves maximum accuracy. - -K(0) = pi/2. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,1 30000 2.5e-16 6.8e-17 - -Cephes Math Library, Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double ellipticintegralkhighprecision(double m1, ae_state *_state) -{ - double p; - double q; - double result; - - - if( ae_fp_less_eq(m1,ae_machineepsilon) ) - { - result = 1.3862943611198906188E0-0.5*ae_log(m1, _state); - } - else - { - p = 1.37982864606273237150E-4; - p = p*m1+2.28025724005875567385E-3; - p = p*m1+7.97404013220415179367E-3; - p = p*m1+9.85821379021226008714E-3; - p = p*m1+6.87489687449949877925E-3; - p = p*m1+6.18901033637687613229E-3; - p = p*m1+8.79078273952743772254E-3; - p = p*m1+1.49380448916805252718E-2; - p = p*m1+3.08851465246711995998E-2; - p = p*m1+9.65735902811690126535E-2; - p = p*m1+1.38629436111989062502E0; - q = 2.94078955048598507511E-5; - q = q*m1+9.14184723865917226571E-4; - q = q*m1+5.94058303753167793257E-3; - q = q*m1+1.54850516649762399335E-2; - q = q*m1+2.39089602715924892727E-2; - q = q*m1+3.01204715227604046988E-2; - q = q*m1+3.73774314173823228969E-2; - q = q*m1+4.88280347570998239232E-2; - q = q*m1+7.03124996963957469739E-2; - q = q*m1+1.24999999999870820058E-1; - q = q*m1+4.99999999999999999821E-1; - result = p-q*ae_log(m1, _state); - } - return result; -} - - -/************************************************************************* -Incomplete elliptic integral of the first kind F(phi|m) - -Approximates the integral - - - - phi - - - | | - | dt -F(phi_\m) = | ------------------ - | 2 - | | sqrt( 1 - m sin t ) - - - 0 - -of amplitude phi and modulus m, using the arithmetic - -geometric mean algorithm. - - - - -ACCURACY: - -Tested at random points with m in [0, 1] and phi as indicated. - - Relative error: -arithmetic domain # trials peak rms - IEEE -10,10 200000 7.4e-16 1.0e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double incompleteellipticintegralk(double phi, double m, ae_state *_state) -{ - double a; - double b; - double c; - double e; - double temp; - double pio2; - double t; - double k; - ae_int_t d; - ae_int_t md; - ae_int_t s; - ae_int_t npio2; - double result; - - - pio2 = 1.57079632679489661923; - if( ae_fp_eq(m,(double)(0)) ) - { - result = phi; - return result; - } - a = 1-m; - if( ae_fp_eq(a,(double)(0)) ) - { - result = ae_log(ae_tan(0.5*(pio2+phi), _state), _state); - return result; - } - npio2 = ae_ifloor(phi/pio2, _state); - if( npio2%2!=0 ) - { - npio2 = npio2+1; - } - if( npio2!=0 ) - { - k = ellipticintegralk(1-a, _state); - phi = phi-npio2*pio2; - } - else - { - k = (double)(0); - } - if( ae_fp_less(phi,(double)(0)) ) - { - phi = -phi; - s = -1; - } - else - { - s = 0; - } - b = ae_sqrt(a, _state); - t = ae_tan(phi, _state); - if( ae_fp_greater(ae_fabs(t, _state),(double)(10)) ) - { - e = 1.0/(b*t); - if( ae_fp_less(ae_fabs(e, _state),(double)(10)) ) - { - e = ae_atan(e, _state); - if( npio2==0 ) - { - k = ellipticintegralk(1-a, _state); - } - temp = k-incompleteellipticintegralk(e, m, _state); - if( s<0 ) - { - temp = -temp; - } - result = temp+npio2*k; - return result; - } - } - a = 1.0; - c = ae_sqrt(m, _state); - d = 1; - md = 0; - while(ae_fp_greater(ae_fabs(c/a, _state),ae_machineepsilon)) - { - temp = b/a; - phi = phi+ae_atan(t*temp, _state)+md*ae_pi; - md = ae_trunc((phi+pio2)/ae_pi, _state); - t = t*(1.0+temp)/(1.0-temp*t*t); - c = 0.5*(a-b); - temp = ae_sqrt(a*b, _state); - a = 0.5*(a+b); - b = temp; - d = d+d; - } - temp = (ae_atan(t, _state)+md*ae_pi)/(d*a); - if( s<0 ) - { - temp = -temp; - } - result = temp+npio2*k; - return result; -} - - -/************************************************************************* -Complete elliptic integral of the second kind - -Approximates the integral - - - pi/2 - - - | | 2 -E(m) = | sqrt( 1 - m sin t ) dt - | | - - - 0 - -using the approximation - - P(x) - x log x Q(x). - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0, 1 10000 2.1e-16 7.3e-17 - -Cephes Math Library, Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -double ellipticintegrale(double m, ae_state *_state) -{ - double p; - double q; - double result; - - - ae_assert(ae_fp_greater_eq(m,(double)(0))&&ae_fp_less_eq(m,(double)(1)), "Domain error in EllipticIntegralE: m<0 or m>1", _state); - m = 1-m; - if( ae_fp_eq(m,(double)(0)) ) - { - result = (double)(1); - return result; - } - p = 1.53552577301013293365E-4; - p = p*m+2.50888492163602060990E-3; - p = p*m+8.68786816565889628429E-3; - p = p*m+1.07350949056076193403E-2; - p = p*m+7.77395492516787092951E-3; - p = p*m+7.58395289413514708519E-3; - p = p*m+1.15688436810574127319E-2; - p = p*m+2.18317996015557253103E-2; - p = p*m+5.68051945617860553470E-2; - p = p*m+4.43147180560990850618E-1; - p = p*m+1.00000000000000000299E0; - q = 3.27954898576485872656E-5; - q = q*m+1.00962792679356715133E-3; - q = q*m+6.50609489976927491433E-3; - q = q*m+1.68862163993311317300E-2; - q = q*m+2.61769742454493659583E-2; - q = q*m+3.34833904888224918614E-2; - q = q*m+4.27180926518931511717E-2; - q = q*m+5.85936634471101055642E-2; - q = q*m+9.37499997197644278445E-2; - q = q*m+2.49999999999888314361E-1; - result = p-q*m*ae_log(m, _state); - return result; -} - - -/************************************************************************* -Incomplete elliptic integral of the second kind - -Approximates the integral - - - phi - - - | | - | 2 -E(phi_\m) = | sqrt( 1 - m sin t ) dt - | - | | - - - 0 - -of amplitude phi and modulus m, using the arithmetic - -geometric mean algorithm. - -ACCURACY: - -Tested at random arguments with phi in [-10, 10] and m in -[0, 1]. - Relative error: -arithmetic domain # trials peak rms - IEEE -10,10 150000 3.3e-15 1.4e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1993, 2000 by Stephen L. Moshier -*************************************************************************/ -double incompleteellipticintegrale(double phi, double m, ae_state *_state) -{ - double pio2; - double a; - double b; - double c; - double e; - double temp; - double lphi; - double t; - double ebig; - ae_int_t d; - ae_int_t md; - ae_int_t npio2; - ae_int_t s; - double result; - - - pio2 = 1.57079632679489661923; - if( ae_fp_eq(m,(double)(0)) ) - { - result = phi; - return result; - } - lphi = phi; - npio2 = ae_ifloor(lphi/pio2, _state); - if( npio2%2!=0 ) - { - npio2 = npio2+1; - } - lphi = lphi-npio2*pio2; - if( ae_fp_less(lphi,(double)(0)) ) - { - lphi = -lphi; - s = -1; - } - else - { - s = 1; - } - a = 1.0-m; - ebig = ellipticintegrale(m, _state); - if( ae_fp_eq(a,(double)(0)) ) - { - temp = ae_sin(lphi, _state); - if( s<0 ) - { - temp = -temp; - } - result = temp+npio2*ebig; - return result; - } - t = ae_tan(lphi, _state); - b = ae_sqrt(a, _state); - - /* - * Thanks to Brian Fitzgerald - * for pointing out an instability near odd multiples of pi/2 - */ - if( ae_fp_greater(ae_fabs(t, _state),(double)(10)) ) - { - - /* - * Transform the amplitude - */ - e = 1.0/(b*t); - - /* - * ... but avoid multiple recursions. - */ - if( ae_fp_less(ae_fabs(e, _state),(double)(10)) ) - { - e = ae_atan(e, _state); - temp = ebig+m*ae_sin(lphi, _state)*ae_sin(e, _state)-incompleteellipticintegrale(e, m, _state); - if( s<0 ) - { - temp = -temp; - } - result = temp+npio2*ebig; - return result; - } - } - c = ae_sqrt(m, _state); - a = 1.0; - d = 1; - e = 0.0; - md = 0; - while(ae_fp_greater(ae_fabs(c/a, _state),ae_machineepsilon)) - { - temp = b/a; - lphi = lphi+ae_atan(t*temp, _state)+md*ae_pi; - md = ae_trunc((lphi+pio2)/ae_pi, _state); - t = t*(1.0+temp)/(1.0-temp*t*t); - c = 0.5*(a-b); - temp = ae_sqrt(a*b, _state); - a = 0.5*(a+b); - b = temp; - d = d+d; - e = e+c*ae_sin(lphi, _state); - } - temp = ebig/ellipticintegralk(m, _state); - temp = temp*((ae_atan(t, _state)+md*ae_pi)/(d*a)); - temp = temp+e; - if( s<0 ) - { - temp = -temp; - } - result = temp+npio2*ebig; - return result; -} - - -#endif -#if defined(AE_COMPILE_HERMITE) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Calculation of the value of the Hermite polynomial. - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Hermite polynomial Hn at x -*************************************************************************/ -double hermitecalculate(ae_int_t n, double x, ae_state *_state) -{ - ae_int_t i; - double a; - double b; - double result; - - - result = (double)(0); - - /* - * Prepare A and B - */ - a = (double)(1); - b = 2*x; - - /* - * Special cases: N=0 or N=1 - */ - if( n==0 ) - { - result = a; - return result; - } - if( n==1 ) - { - result = b; - return result; - } - - /* - * General case: N>=2 - */ - for(i=2; i<=n; i++) - { - result = 2*x*b-2*(i-1)*a; - a = b; - b = result; - } - return result; -} - - -/************************************************************************* -Summation of Hermite polynomials using Clenshaw's recurrence formula. - -This routine calculates - c[0]*H0(x) + c[1]*H1(x) + ... + c[N]*HN(x) - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Hermite polynomial at x -*************************************************************************/ -double hermitesum(/* Real */ ae_vector* c, - ae_int_t n, - double x, - ae_state *_state) -{ - double b1; - double b2; - ae_int_t i; - double result; - - - b1 = (double)(0); - b2 = (double)(0); - result = (double)(0); - for(i=n; i>=0; i--) - { - result = 2*(x*b1-(i+1)*b2)+c->ptr.p_double[i]; - b2 = b1; - b1 = result; - } - return result; -} - - -/************************************************************************* -Representation of Hn as C[0] + C[1]*X + ... + C[N]*X^N - -Input parameters: - N - polynomial degree, n>=0 - -Output parameters: - C - coefficients -*************************************************************************/ -void hermitecoefficients(ae_int_t n, - /* Real */ ae_vector* c, - ae_state *_state) -{ - ae_int_t i; - - ae_vector_clear(c); - - ae_vector_set_length(c, n+1, _state); - for(i=0; i<=n; i++) - { - c->ptr.p_double[i] = (double)(0); - } - c->ptr.p_double[n] = ae_exp(n*ae_log((double)(2), _state), _state); - for(i=0; i<=n/2-1; i++) - { - c->ptr.p_double[n-2*(i+1)] = -c->ptr.p_double[n-2*i]*(n-2*i)*(n-2*i-1)/4/(i+1); - } -} - - -#endif -#if defined(AE_COMPILE_DAWSON) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Dawson's Integral - -Approximates the integral - - x - - - 2 | | 2 - dawsn(x) = exp( -x ) | exp( t ) dt - | | - - - 0 - -Three different rational approximations are employed, for -the intervals 0 to 3.25; 3.25 to 6.25; and 6.25 up. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,10 10000 6.9e-16 1.0e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -double dawsonintegral(double x, ae_state *_state) -{ - double x2; - double y; - ae_int_t sg; - double an; - double ad; - double bn; - double bd; - double cn; - double cd; - double result; - - - sg = 1; - if( ae_fp_less(x,(double)(0)) ) - { - sg = -1; - x = -x; - } - if( ae_fp_less(x,3.25) ) - { - x2 = x*x; - an = 1.13681498971755972054E-11; - an = an*x2+8.49262267667473811108E-10; - an = an*x2+1.94434204175553054283E-8; - an = an*x2+9.53151741254484363489E-7; - an = an*x2+3.07828309874913200438E-6; - an = an*x2+3.52513368520288738649E-4; - an = an*x2+(-8.50149846724410912031E-4); - an = an*x2+4.22618223005546594270E-2; - an = an*x2+(-9.17480371773452345351E-2); - an = an*x2+9.99999999999999994612E-1; - ad = 2.40372073066762605484E-11; - ad = ad*x2+1.48864681368493396752E-9; - ad = ad*x2+5.21265281010541664570E-8; - ad = ad*x2+1.27258478273186970203E-6; - ad = ad*x2+2.32490249820789513991E-5; - ad = ad*x2+3.25524741826057911661E-4; - ad = ad*x2+3.48805814657162590916E-3; - ad = ad*x2+2.79448531198828973716E-2; - ad = ad*x2+1.58874241960120565368E-1; - ad = ad*x2+5.74918629489320327824E-1; - ad = ad*x2+1.00000000000000000539E0; - y = x*an/ad; - result = sg*y; - return result; - } - x2 = 1.0/(x*x); - if( ae_fp_less(x,6.25) ) - { - bn = 5.08955156417900903354E-1; - bn = bn*x2-2.44754418142697847934E-1; - bn = bn*x2+9.41512335303534411857E-2; - bn = bn*x2-2.18711255142039025206E-2; - bn = bn*x2+3.66207612329569181322E-3; - bn = bn*x2-4.23209114460388756528E-4; - bn = bn*x2+3.59641304793896631888E-5; - bn = bn*x2-2.14640351719968974225E-6; - bn = bn*x2+9.10010780076391431042E-8; - bn = bn*x2-2.40274520828250956942E-9; - bn = bn*x2+3.59233385440928410398E-11; - bd = 1.00000000000000000000E0; - bd = bd*x2-6.31839869873368190192E-1; - bd = bd*x2+2.36706788228248691528E-1; - bd = bd*x2-5.31806367003223277662E-2; - bd = bd*x2+8.48041718586295374409E-3; - bd = bd*x2-9.47996768486665330168E-4; - bd = bd*x2+7.81025592944552338085E-5; - bd = bd*x2-4.55875153252442634831E-6; - bd = bd*x2+1.89100358111421846170E-7; - bd = bd*x2-4.91324691331920606875E-9; - bd = bd*x2+7.18466403235734541950E-11; - y = 1.0/x+x2*bn/(bd*x); - result = sg*0.5*y; - return result; - } - if( ae_fp_greater(x,1.0E9) ) - { - result = sg*0.5/x; - return result; - } - cn = -5.90592860534773254987E-1; - cn = cn*x2+6.29235242724368800674E-1; - cn = cn*x2-1.72858975380388136411E-1; - cn = cn*x2+1.64837047825189632310E-2; - cn = cn*x2-4.86827613020462700845E-4; - cd = 1.00000000000000000000E0; - cd = cd*x2-2.69820057197544900361E0; - cd = cd*x2+1.73270799045947845857E0; - cd = cd*x2-3.93708582281939493482E-1; - cd = cd*x2+3.44278924041233391079E-2; - cd = cd*x2-9.73655226040941223894E-4; - y = 1.0/x+x2*cn/(cd*x); - result = sg*0.5*y; - return result; -} - - -#endif -#if defined(AE_COMPILE_TRIGINTEGRALS) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Sine and cosine integrals - -Evaluates the integrals - - x - - - | cos t - 1 - Ci(x) = eul + ln x + | --------- dt, - | t - - - 0 - x - - - | sin t - Si(x) = | ----- dt - | t - - - 0 - -where eul = 0.57721566490153286061 is Euler's constant. -The integrals are approximated by rational functions. -For x > 8 auxiliary functions f(x) and g(x) are employed -such that - -Ci(x) = f(x) sin(x) - g(x) cos(x) -Si(x) = pi/2 - f(x) cos(x) - g(x) sin(x) - - -ACCURACY: - Test interval = [0,50]. -Absolute error, except relative when > 1: -arithmetic function # trials peak rms - IEEE Si 30000 4.4e-16 7.3e-17 - IEEE Ci 30000 6.9e-16 5.1e-17 - -Cephes Math Library Release 2.1: January, 1989 -Copyright 1984, 1987, 1989 by Stephen L. Moshier -*************************************************************************/ -void sinecosineintegrals(double x, - double* si, - double* ci, - ae_state *_state) -{ - double z; - double c; - double s; - double f; - double g; - ae_int_t sg; - double sn; - double sd; - double cn; - double cd; - double fn; - double fd; - double gn; - double gd; - - *si = 0; - *ci = 0; - - if( ae_fp_less(x,(double)(0)) ) - { - sg = -1; - x = -x; - } - else - { - sg = 0; - } - if( ae_fp_eq(x,(double)(0)) ) - { - *si = (double)(0); - *ci = -ae_maxrealnumber; - return; - } - if( ae_fp_greater(x,1.0E9) ) - { - *si = 1.570796326794896619-ae_cos(x, _state)/x; - *ci = ae_sin(x, _state)/x; - return; - } - if( ae_fp_less_eq(x,(double)(4)) ) - { - z = x*x; - sn = -8.39167827910303881427E-11; - sn = sn*z+4.62591714427012837309E-8; - sn = sn*z-9.75759303843632795789E-6; - sn = sn*z+9.76945438170435310816E-4; - sn = sn*z-4.13470316229406538752E-2; - sn = sn*z+1.00000000000000000302E0; - sd = 2.03269266195951942049E-12; - sd = sd*z+1.27997891179943299903E-9; - sd = sd*z+4.41827842801218905784E-7; - sd = sd*z+9.96412122043875552487E-5; - sd = sd*z+1.42085239326149893930E-2; - sd = sd*z+9.99999999999999996984E-1; - s = x*sn/sd; - cn = 2.02524002389102268789E-11; - cn = cn*z-1.35249504915790756375E-8; - cn = cn*z+3.59325051419993077021E-6; - cn = cn*z-4.74007206873407909465E-4; - cn = cn*z+2.89159652607555242092E-2; - cn = cn*z-1.00000000000000000080E0; - cd = 4.07746040061880559506E-12; - cd = cd*z+3.06780997581887812692E-9; - cd = cd*z+1.23210355685883423679E-6; - cd = cd*z+3.17442024775032769882E-4; - cd = cd*z+5.10028056236446052392E-2; - cd = cd*z+4.00000000000000000080E0; - c = z*cn/cd; - if( sg!=0 ) - { - s = -s; - } - *si = s; - *ci = 0.57721566490153286061+ae_log(x, _state)+c; - return; - } - s = ae_sin(x, _state); - c = ae_cos(x, _state); - z = 1.0/(x*x); - if( ae_fp_less(x,(double)(8)) ) - { - fn = 4.23612862892216586994E0; - fn = fn*z+5.45937717161812843388E0; - fn = fn*z+1.62083287701538329132E0; - fn = fn*z+1.67006611831323023771E-1; - fn = fn*z+6.81020132472518137426E-3; - fn = fn*z+1.08936580650328664411E-4; - fn = fn*z+5.48900223421373614008E-7; - fd = 1.00000000000000000000E0; - fd = fd*z+8.16496634205391016773E0; - fd = fd*z+7.30828822505564552187E0; - fd = fd*z+1.86792257950184183883E0; - fd = fd*z+1.78792052963149907262E-1; - fd = fd*z+7.01710668322789753610E-3; - fd = fd*z+1.10034357153915731354E-4; - fd = fd*z+5.48900252756255700982E-7; - f = fn/(x*fd); - gn = 8.71001698973114191777E-2; - gn = gn*z+6.11379109952219284151E-1; - gn = gn*z+3.97180296392337498885E-1; - gn = gn*z+7.48527737628469092119E-2; - gn = gn*z+5.38868681462177273157E-3; - gn = gn*z+1.61999794598934024525E-4; - gn = gn*z+1.97963874140963632189E-6; - gn = gn*z+7.82579040744090311069E-9; - gd = 1.00000000000000000000E0; - gd = gd*z+1.64402202413355338886E0; - gd = gd*z+6.66296701268987968381E-1; - gd = gd*z+9.88771761277688796203E-2; - gd = gd*z+6.22396345441768420760E-3; - gd = gd*z+1.73221081474177119497E-4; - gd = gd*z+2.02659182086343991969E-6; - gd = gd*z+7.82579218933534490868E-9; - g = z*gn/gd; - } - else - { - fn = 4.55880873470465315206E-1; - fn = fn*z+7.13715274100146711374E-1; - fn = fn*z+1.60300158222319456320E-1; - fn = fn*z+1.16064229408124407915E-2; - fn = fn*z+3.49556442447859055605E-4; - fn = fn*z+4.86215430826454749482E-6; - fn = fn*z+3.20092790091004902806E-8; - fn = fn*z+9.41779576128512936592E-11; - fn = fn*z+9.70507110881952024631E-14; - fd = 1.00000000000000000000E0; - fd = fd*z+9.17463611873684053703E-1; - fd = fd*z+1.78685545332074536321E-1; - fd = fd*z+1.22253594771971293032E-2; - fd = fd*z+3.58696481881851580297E-4; - fd = fd*z+4.92435064317881464393E-6; - fd = fd*z+3.21956939101046018377E-8; - fd = fd*z+9.43720590350276732376E-11; - fd = fd*z+9.70507110881952025725E-14; - f = fn/(x*fd); - gn = 6.97359953443276214934E-1; - gn = gn*z+3.30410979305632063225E-1; - gn = gn*z+3.84878767649974295920E-2; - gn = gn*z+1.71718239052347903558E-3; - gn = gn*z+3.48941165502279436777E-5; - gn = gn*z+3.47131167084116673800E-7; - gn = gn*z+1.70404452782044526189E-9; - gn = gn*z+3.85945925430276600453E-12; - gn = gn*z+3.14040098946363334640E-15; - gd = 1.00000000000000000000E0; - gd = gd*z+1.68548898811011640017E0; - gd = gd*z+4.87852258695304967486E-1; - gd = gd*z+4.67913194259625806320E-2; - gd = gd*z+1.90284426674399523638E-3; - gd = gd*z+3.68475504442561108162E-5; - gd = gd*z+3.57043223443740838771E-7; - gd = gd*z+1.72693748966316146736E-9; - gd = gd*z+3.87830166023954706752E-12; - gd = gd*z+3.14040098946363335242E-15; - g = z*gn/gd; - } - *si = 1.570796326794896619-f*c-g*s; - if( sg!=0 ) - { - *si = -*si; - } - *ci = f*s-g*c; -} - - -/************************************************************************* -Hyperbolic sine and cosine integrals - -Approximates the integrals - - x - - - | | cosh t - 1 - Chi(x) = eul + ln x + | ----------- dt, - | | t - - - 0 - - x - - - | | sinh t - Shi(x) = | ------ dt - | | t - - - 0 - -where eul = 0.57721566490153286061 is Euler's constant. -The integrals are evaluated by power series for x < 8 -and by Chebyshev expansions for x between 8 and 88. -For large x, both functions approach exp(x)/2x. -Arguments greater than 88 in magnitude return MAXNUM. - - -ACCURACY: - -Test interval 0 to 88. - Relative error: -arithmetic function # trials peak rms - IEEE Shi 30000 6.9e-16 1.6e-16 - Absolute error, except relative when |Chi| > 1: - IEEE Chi 30000 8.4e-16 1.4e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -void hyperbolicsinecosineintegrals(double x, - double* shi, - double* chi, - ae_state *_state) -{ - double k; - double z; - double c; - double s; - double a; - ae_int_t sg; - double b0; - double b1; - double b2; - - *shi = 0; - *chi = 0; - - if( ae_fp_less(x,(double)(0)) ) - { - sg = -1; - x = -x; - } - else - { - sg = 0; - } - if( ae_fp_eq(x,(double)(0)) ) - { - *shi = (double)(0); - *chi = -ae_maxrealnumber; - return; - } - if( ae_fp_less(x,8.0) ) - { - z = x*x; - a = 1.0; - s = 1.0; - c = 0.0; - k = 2.0; - do - { - a = a*z/k; - c = c+a/k; - k = k+1.0; - a = a/k; - s = s+a/k; - k = k+1.0; - } - while(ae_fp_greater_eq(ae_fabs(a/s, _state),ae_machineepsilon)); - s = s*x; - } - else - { - if( ae_fp_less(x,18.0) ) - { - a = (576.0/x-52.0)/10.0; - k = ae_exp(x, _state)/x; - b0 = 1.83889230173399459482E-17; - b1 = 0.0; - trigintegrals_chebiterationshichi(a, -9.55485532279655569575E-17, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 2.04326105980879882648E-16, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 1.09896949074905343022E-15, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -1.31313534344092599234E-14, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 5.93976226264314278932E-14, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -3.47197010497749154755E-14, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -1.40059764613117131000E-12, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 9.49044626224223543299E-12, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -1.61596181145435454033E-11, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -1.77899784436430310321E-10, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 1.35455469767246947469E-9, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -1.03257121792819495123E-9, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -3.56699611114982536845E-8, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 1.44818877384267342057E-7, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 7.82018215184051295296E-7, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -5.39919118403805073710E-6, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -3.12458202168959833422E-5, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 8.90136741950727517826E-5, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 2.02558474743846862168E-3, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 2.96064440855633256972E-2, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 1.11847751047257036625E0, &b0, &b1, &b2, _state); - s = k*0.5*(b0-b2); - b0 = -8.12435385225864036372E-18; - b1 = 0.0; - trigintegrals_chebiterationshichi(a, 2.17586413290339214377E-17, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 5.22624394924072204667E-17, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -9.48812110591690559363E-16, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 5.35546311647465209166E-15, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -1.21009970113732918701E-14, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -6.00865178553447437951E-14, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 7.16339649156028587775E-13, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -2.93496072607599856104E-12, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -1.40359438136491256904E-12, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 8.76302288609054966081E-11, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -4.40092476213282340617E-10, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -1.87992075640569295479E-10, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 1.31458150989474594064E-8, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -4.75513930924765465590E-8, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -2.21775018801848880741E-7, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 1.94635531373272490962E-6, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 4.33505889257316408893E-6, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -6.13387001076494349496E-5, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -3.13085477492997465138E-4, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 4.97164789823116062801E-4, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 2.64347496031374526641E-2, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 1.11446150876699213025E0, &b0, &b1, &b2, _state); - c = k*0.5*(b0-b2); - } - else - { - if( ae_fp_less_eq(x,88.0) ) - { - a = (6336.0/x-212.0)/70.0; - k = ae_exp(x, _state)/x; - b0 = -1.05311574154850938805E-17; - b1 = 0.0; - trigintegrals_chebiterationshichi(a, 2.62446095596355225821E-17, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 8.82090135625368160657E-17, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -3.38459811878103047136E-16, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -8.30608026366935789136E-16, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 3.93397875437050071776E-15, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 1.01765565969729044505E-14, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -4.21128170307640802703E-14, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -1.60818204519802480035E-13, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 3.34714954175994481761E-13, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 2.72600352129153073807E-12, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 1.66894954752839083608E-12, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -3.49278141024730899554E-11, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -1.58580661666482709598E-10, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -1.79289437183355633342E-10, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 1.76281629144264523277E-9, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 1.69050228879421288846E-8, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 1.25391771228487041649E-7, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 1.16229947068677338732E-6, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 1.61038260117376323993E-5, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 3.49810375601053973070E-4, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 1.28478065259647610779E-2, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 1.03665722588798326712E0, &b0, &b1, &b2, _state); - s = k*0.5*(b0-b2); - b0 = 8.06913408255155572081E-18; - b1 = 0.0; - trigintegrals_chebiterationshichi(a, -2.08074168180148170312E-17, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -5.98111329658272336816E-17, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 2.68533951085945765591E-16, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 4.52313941698904694774E-16, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -3.10734917335299464535E-15, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -4.42823207332531972288E-15, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 3.49639695410806959872E-14, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 6.63406731718911586609E-14, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -3.71902448093119218395E-13, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -1.27135418132338309016E-12, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 2.74851141935315395333E-12, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 2.33781843985453438400E-11, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 2.71436006377612442764E-11, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -2.56600180000355990529E-10, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -1.61021375163803438552E-9, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -4.72543064876271773512E-9, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, -3.00095178028681682282E-9, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 7.79387474390914922337E-8, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 1.06942765566401507066E-6, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 1.59503164802313196374E-5, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 3.49592575153777996871E-4, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 1.28475387530065247392E-2, &b0, &b1, &b2, _state); - trigintegrals_chebiterationshichi(a, 1.03665693917934275131E0, &b0, &b1, &b2, _state); - c = k*0.5*(b0-b2); - } - else - { - if( sg!=0 ) - { - *shi = -ae_maxrealnumber; - } - else - { - *shi = ae_maxrealnumber; - } - *chi = ae_maxrealnumber; - return; - } - } - } - if( sg!=0 ) - { - s = -s; - } - *shi = s; - *chi = 0.57721566490153286061+ae_log(x, _state)+c; -} - - -static void trigintegrals_chebiterationshichi(double x, - double c, - double* b0, - double* b1, - double* b2, - ae_state *_state) -{ - - - *b2 = *b1; - *b1 = *b0; - *b0 = x*(*b1)-(*b2)+c; -} - - -#endif -#if defined(AE_COMPILE_POISSONDISTR) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Poisson distribution - -Returns the sum of the first k+1 terms of the Poisson -distribution: - - k j - -- -m m - > e -- - -- j! - j=0 - -The terms are not summed directly; instead the incomplete -gamma integral is employed, according to the relation - -y = pdtr( k, m ) = igamc( k+1, m ). - -The arguments must both be positive. -ACCURACY: - -See incomplete gamma function - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double poissondistribution(ae_int_t k, double m, ae_state *_state) -{ - double result; - - - ae_assert(k>=0&&ae_fp_greater(m,(double)(0)), "Domain error in PoissonDistribution", _state); - result = incompletegammac((double)(k+1), m, _state); - return result; -} - - -/************************************************************************* -Complemented Poisson distribution - -Returns the sum of the terms k+1 to infinity of the Poisson -distribution: - - inf. j - -- -m m - > e -- - -- j! - j=k+1 - -The terms are not summed directly; instead the incomplete -gamma integral is employed, according to the formula - -y = pdtrc( k, m ) = igam( k+1, m ). - -The arguments must both be positive. - -ACCURACY: - -See incomplete gamma function - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double poissoncdistribution(ae_int_t k, double m, ae_state *_state) -{ - double result; - - - ae_assert(k>=0&&ae_fp_greater(m,(double)(0)), "Domain error in PoissonDistributionC", _state); - result = incompletegamma((double)(k+1), m, _state); - return result; -} - - -/************************************************************************* -Inverse Poisson distribution - -Finds the Poisson variable x such that the integral -from 0 to x of the Poisson density is equal to the -given probability y. - -This is accomplished using the inverse gamma integral -function and the relation - - m = igami( k+1, y ). - -ACCURACY: - -See inverse incomplete gamma function - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double invpoissondistribution(ae_int_t k, double y, ae_state *_state) -{ - double result; - - - ae_assert((k>=0&&ae_fp_greater_eq(y,(double)(0)))&&ae_fp_less(y,(double)(1)), "Domain error in InvPoissonDistribution", _state); - result = invincompletegammac((double)(k+1), y, _state); - return result; -} - - -#endif -#if defined(AE_COMPILE_BESSEL) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Bessel function of order zero - -Returns Bessel function of order zero of the argument. - -The domain is divided into the intervals [0, 5] and -(5, infinity). In the first interval the following rational -approximation is used: - - - 2 2 -(w - r ) (w - r ) P (w) / Q (w) - 1 2 3 8 - - 2 -where w = x and the two r's are zeros of the function. - -In the second interval, the Hankel asymptotic expansion -is employed with two rational functions of degree 6/6 -and 7/7. - -ACCURACY: - - Absolute error: -arithmetic domain # trials peak rms - IEEE 0, 30 60000 4.2e-16 1.1e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -double besselj0(double x, ae_state *_state) -{ - double xsq; - double nn; - double pzero; - double qzero; - double p1; - double q1; - double result; - - - if( ae_fp_less(x,(double)(0)) ) - { - x = -x; - } - if( ae_fp_greater(x,8.0) ) - { - bessel_besselasympt0(x, &pzero, &qzero, _state); - nn = x-ae_pi/4; - result = ae_sqrt(2/ae_pi/x, _state)*(pzero*ae_cos(nn, _state)-qzero*ae_sin(nn, _state)); - return result; - } - xsq = ae_sqr(x, _state); - p1 = 26857.86856980014981415848441; - p1 = -40504123.71833132706360663322+xsq*p1; - p1 = 25071582855.36881945555156435+xsq*p1; - p1 = -8085222034853.793871199468171+xsq*p1; - p1 = 1434354939140344.111664316553+xsq*p1; - p1 = -136762035308817138.6865416609+xsq*p1; - p1 = 6382059341072356562.289432465+xsq*p1; - p1 = -117915762910761053603.8440800+xsq*p1; - p1 = 493378725179413356181.6813446+xsq*p1; - q1 = 1.0; - q1 = 1363.063652328970604442810507+xsq*q1; - q1 = 1114636.098462985378182402543+xsq*q1; - q1 = 669998767.2982239671814028660+xsq*q1; - q1 = 312304311494.1213172572469442+xsq*q1; - q1 = 112775673967979.8507056031594+xsq*q1; - q1 = 30246356167094626.98627330784+xsq*q1; - q1 = 5428918384092285160.200195092+xsq*q1; - q1 = 493378725179413356211.3278438+xsq*q1; - result = p1/q1; - return result; -} - - -/************************************************************************* -Bessel function of order one - -Returns Bessel function of order one of the argument. - -The domain is divided into the intervals [0, 8] and -(8, infinity). In the first interval a 24 term Chebyshev -expansion is used. In the second, the asymptotic -trigonometric representation is employed using two -rational functions of degree 5/5. - -ACCURACY: - - Absolute error: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 2.6e-16 1.1e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -double besselj1(double x, ae_state *_state) -{ - double s; - double xsq; - double nn; - double pzero; - double qzero; - double p1; - double q1; - double result; - - - s = (double)(ae_sign(x, _state)); - if( ae_fp_less(x,(double)(0)) ) - { - x = -x; - } - if( ae_fp_greater(x,8.0) ) - { - bessel_besselasympt1(x, &pzero, &qzero, _state); - nn = x-3*ae_pi/4; - result = ae_sqrt(2/ae_pi/x, _state)*(pzero*ae_cos(nn, _state)-qzero*ae_sin(nn, _state)); - if( ae_fp_less(s,(double)(0)) ) - { - result = -result; - } - return result; - } - xsq = ae_sqr(x, _state); - p1 = 2701.122710892323414856790990; - p1 = -4695753.530642995859767162166+xsq*p1; - p1 = 3413234182.301700539091292655+xsq*p1; - p1 = -1322983480332.126453125473247+xsq*p1; - p1 = 290879526383477.5409737601689+xsq*p1; - p1 = -35888175699101060.50743641413+xsq*p1; - p1 = 2316433580634002297.931815435+xsq*p1; - p1 = -66721065689249162980.20941484+xsq*p1; - p1 = 581199354001606143928.050809+xsq*p1; - q1 = 1.0; - q1 = 1606.931573481487801970916749+xsq*q1; - q1 = 1501793.594998585505921097578+xsq*q1; - q1 = 1013863514.358673989967045588+xsq*q1; - q1 = 524371026216.7649715406728642+xsq*q1; - q1 = 208166122130760.7351240184229+xsq*q1; - q1 = 60920613989175217.46105196863+xsq*q1; - q1 = 11857707121903209998.37113348+xsq*q1; - q1 = 1162398708003212287858.529400+xsq*q1; - result = s*x*p1/q1; - return result; -} - - -/************************************************************************* -Bessel function of integer order - -Returns Bessel function of order n, where n is a -(possibly negative) integer. - -The ratio of jn(x) to j0(x) is computed by backward -recurrence. First the ratio jn/jn-1 is found by a -continued fraction expansion. Then the recurrence -relating successive orders is applied until j0 or j1 is -reached. - -If n = 0 or 1 the routine for j0 or j1 is called -directly. - -ACCURACY: - - Absolute error: -arithmetic range # trials peak rms - IEEE 0, 30 5000 4.4e-16 7.9e-17 - - -Not suitable for large n or x. Use jv() (fractional order) instead. - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double besseljn(ae_int_t n, double x, ae_state *_state) -{ - double pkm2; - double pkm1; - double pk; - double xk; - double r; - double ans; - ae_int_t k; - ae_int_t sg; - double result; - - - if( n<0 ) - { - n = -n; - if( n%2==0 ) - { - sg = 1; - } - else - { - sg = -1; - } - } - else - { - sg = 1; - } - if( ae_fp_less(x,(double)(0)) ) - { - if( n%2!=0 ) - { - sg = -sg; - } - x = -x; - } - if( n==0 ) - { - result = sg*besselj0(x, _state); - return result; - } - if( n==1 ) - { - result = sg*besselj1(x, _state); - return result; - } - if( n==2 ) - { - if( ae_fp_eq(x,(double)(0)) ) - { - result = (double)(0); - } - else - { - result = sg*(2.0*besselj1(x, _state)/x-besselj0(x, _state)); - } - return result; - } - if( ae_fp_less(x,ae_machineepsilon) ) - { - result = (double)(0); - return result; - } - k = 53; - pk = (double)(2*(n+k)); - ans = pk; - xk = x*x; - do - { - pk = pk-2.0; - ans = pk-xk/ans; - k = k-1; - } - while(k!=0); - ans = x/ans; - pk = 1.0; - pkm1 = 1.0/ans; - k = n-1; - r = (double)(2*k); - do - { - pkm2 = (pkm1*r-pk*x)/x; - pk = pkm1; - pkm1 = pkm2; - r = r-2.0; - k = k-1; - } - while(k!=0); - if( ae_fp_greater(ae_fabs(pk, _state),ae_fabs(pkm1, _state)) ) - { - ans = besselj1(x, _state)/pk; - } - else - { - ans = besselj0(x, _state)/pkm1; - } - result = sg*ans; - return result; -} - - -/************************************************************************* -Bessel function of the second kind, order zero - -Returns Bessel function of the second kind, of order -zero, of the argument. - -The domain is divided into the intervals [0, 5] and -(5, infinity). In the first interval a rational approximation -R(x) is employed to compute - y0(x) = R(x) + 2 * log(x) * j0(x) / PI. -Thus a call to j0() is required. - -In the second interval, the Hankel asymptotic expansion -is employed with two rational functions of degree 6/6 -and 7/7. - - - -ACCURACY: - - Absolute error, when y0(x) < 1; else relative error: - -arithmetic domain # trials peak rms - IEEE 0, 30 30000 1.3e-15 1.6e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -double bessely0(double x, ae_state *_state) -{ - double nn; - double xsq; - double pzero; - double qzero; - double p4; - double q4; - double result; - - - if( ae_fp_greater(x,8.0) ) - { - bessel_besselasympt0(x, &pzero, &qzero, _state); - nn = x-ae_pi/4; - result = ae_sqrt(2/ae_pi/x, _state)*(pzero*ae_sin(nn, _state)+qzero*ae_cos(nn, _state)); - return result; - } - xsq = ae_sqr(x, _state); - p4 = -41370.35497933148554125235152; - p4 = 59152134.65686889654273830069+xsq*p4; - p4 = -34363712229.79040378171030138+xsq*p4; - p4 = 10255208596863.94284509167421+xsq*p4; - p4 = -1648605817185729.473122082537+xsq*p4; - p4 = 137562431639934407.8571335453+xsq*p4; - p4 = -5247065581112764941.297350814+xsq*p4; - p4 = 65874732757195549259.99402049+xsq*p4; - p4 = -27502866786291095837.01933175+xsq*p4; - q4 = 1.0; - q4 = 1282.452772478993804176329391+xsq*q4; - q4 = 1001702.641288906265666651753+xsq*q4; - q4 = 579512264.0700729537480087915+xsq*q4; - q4 = 261306575504.1081249568482092+xsq*q4; - q4 = 91620380340751.85262489147968+xsq*q4; - q4 = 23928830434997818.57439356652+xsq*q4; - q4 = 4192417043410839973.904769661+xsq*q4; - q4 = 372645883898616588198.9980+xsq*q4; - result = p4/q4+2/ae_pi*besselj0(x, _state)*ae_log(x, _state); - return result; -} - - -/************************************************************************* -Bessel function of second kind of order one - -Returns Bessel function of the second kind of order one -of the argument. - -The domain is divided into the intervals [0, 8] and -(8, infinity). In the first interval a 25 term Chebyshev -expansion is used, and a call to j1() is required. -In the second, the asymptotic trigonometric representation -is employed using two rational functions of degree 5/5. - -ACCURACY: - - Absolute error: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 1.0e-15 1.3e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -double bessely1(double x, ae_state *_state) -{ - double nn; - double xsq; - double pzero; - double qzero; - double p4; - double q4; - double result; - - - if( ae_fp_greater(x,8.0) ) - { - bessel_besselasympt1(x, &pzero, &qzero, _state); - nn = x-3*ae_pi/4; - result = ae_sqrt(2/ae_pi/x, _state)*(pzero*ae_sin(nn, _state)+qzero*ae_cos(nn, _state)); - return result; - } - xsq = ae_sqr(x, _state); - p4 = -2108847.540133123652824139923; - p4 = 3639488548.124002058278999428+xsq*p4; - p4 = -2580681702194.450950541426399+xsq*p4; - p4 = 956993023992168.3481121552788+xsq*p4; - p4 = -196588746272214065.8820322248+xsq*p4; - p4 = 21931073399177975921.11427556+xsq*p4; - p4 = -1212297555414509577913.561535+xsq*p4; - p4 = 26554738314348543268942.48968+xsq*p4; - p4 = -99637534243069222259967.44354+xsq*p4; - q4 = 1.0; - q4 = 1612.361029677000859332072312+xsq*q4; - q4 = 1563282.754899580604737366452+xsq*q4; - q4 = 1128686837.169442121732366891+xsq*q4; - q4 = 646534088126.5275571961681500+xsq*q4; - q4 = 297663212564727.6729292742282+xsq*q4; - q4 = 108225825940881955.2553850180+xsq*q4; - q4 = 29549879358971486742.90758119+xsq*q4; - q4 = 5435310377188854170800.653097+xsq*q4; - q4 = 508206736694124324531442.4152+xsq*q4; - result = x*p4/q4+2/ae_pi*(besselj1(x, _state)*ae_log(x, _state)-1/x); - return result; -} - - -/************************************************************************* -Bessel function of second kind of integer order - -Returns Bessel function of order n, where n is a -(possibly negative) integer. - -The function is evaluated by forward recurrence on -n, starting with values computed by the routines -y0() and y1(). - -If n = 0 or 1 the routine for y0 or y1 is called -directly. - -ACCURACY: - Absolute error, except relative - when y > 1: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 3.4e-15 4.3e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double besselyn(ae_int_t n, double x, ae_state *_state) -{ - ae_int_t i; - double a; - double b; - double tmp; - double s; - double result; - - - s = (double)(1); - if( n<0 ) - { - n = -n; - if( n%2!=0 ) - { - s = (double)(-1); - } - } - if( n==0 ) - { - result = bessely0(x, _state); - return result; - } - if( n==1 ) - { - result = s*bessely1(x, _state); - return result; - } - a = bessely0(x, _state); - b = bessely1(x, _state); - for(i=1; i<=n-1; i++) - { - tmp = b; - b = 2*i/x*b-a; - a = tmp; - } - result = s*b; - return result; -} - - -/************************************************************************* -Modified Bessel function of order zero - -Returns modified Bessel function of order zero of the -argument. - -The function is defined as i0(x) = j0( ix ). - -The range is partitioned into the two intervals [0,8] and -(8, infinity). Chebyshev polynomial expansions are employed -in each interval. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,30 30000 5.8e-16 1.4e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double besseli0(double x, ae_state *_state) -{ - double y; - double v; - double z; - double b0; - double b1; - double b2; - double result; - - - if( ae_fp_less(x,(double)(0)) ) - { - x = -x; - } - if( ae_fp_less_eq(x,8.0) ) - { - y = x/2.0-2.0; - bessel_besselmfirstcheb(-4.41534164647933937950E-18, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 3.33079451882223809783E-17, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, -2.43127984654795469359E-16, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 1.71539128555513303061E-15, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, -1.16853328779934516808E-14, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 7.67618549860493561688E-14, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, -4.85644678311192946090E-13, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 2.95505266312963983461E-12, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, -1.72682629144155570723E-11, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 9.67580903537323691224E-11, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, -5.18979560163526290666E-10, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 2.65982372468238665035E-9, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, -1.30002500998624804212E-8, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 6.04699502254191894932E-8, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, -2.67079385394061173391E-7, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 1.11738753912010371815E-6, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, -4.41673835845875056359E-6, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 1.64484480707288970893E-5, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, -5.75419501008210370398E-5, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 1.88502885095841655729E-4, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, -5.76375574538582365885E-4, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 1.63947561694133579842E-3, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, -4.32430999505057594430E-3, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 1.05464603945949983183E-2, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, -2.37374148058994688156E-2, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 4.93052842396707084878E-2, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, -9.49010970480476444210E-2, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 1.71620901522208775349E-1, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, -3.04682672343198398683E-1, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 6.76795274409476084995E-1, &b0, &b1, &b2, _state); - v = 0.5*(b0-b2); - result = ae_exp(x, _state)*v; - return result; - } - z = 32.0/x-2.0; - bessel_besselmfirstcheb(-7.23318048787475395456E-18, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, -4.83050448594418207126E-18, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 4.46562142029675999901E-17, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 3.46122286769746109310E-17, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, -2.82762398051658348494E-16, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, -3.42548561967721913462E-16, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 1.77256013305652638360E-15, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 3.81168066935262242075E-15, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, -9.55484669882830764870E-15, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, -4.15056934728722208663E-14, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 1.54008621752140982691E-14, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 3.85277838274214270114E-13, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 7.18012445138366623367E-13, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, -1.79417853150680611778E-12, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, -1.32158118404477131188E-11, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, -3.14991652796324136454E-11, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 1.18891471078464383424E-11, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 4.94060238822496958910E-10, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 3.39623202570838634515E-9, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 2.26666899049817806459E-8, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 2.04891858946906374183E-7, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 2.89137052083475648297E-6, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 6.88975834691682398426E-5, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 3.36911647825569408990E-3, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 8.04490411014108831608E-1, &b0, &b1, &b2, _state); - v = 0.5*(b0-b2); - result = ae_exp(x, _state)*v/ae_sqrt(x, _state); - return result; -} - - -/************************************************************************* -Modified Bessel function of order one - -Returns modified Bessel function of order one of the -argument. - -The function is defined as i1(x) = -i j1( ix ). - -The range is partitioned into the two intervals [0,8] and -(8, infinity). Chebyshev polynomial expansions are employed -in each interval. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 1.9e-15 2.1e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1985, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double besseli1(double x, ae_state *_state) -{ - double y; - double z; - double v; - double b0; - double b1; - double b2; - double result; - - - z = ae_fabs(x, _state); - if( ae_fp_less_eq(z,8.0) ) - { - y = z/2.0-2.0; - bessel_besselm1firstcheb(2.77791411276104639959E-18, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -2.11142121435816608115E-17, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 1.55363195773620046921E-16, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -1.10559694773538630805E-15, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 7.60068429473540693410E-15, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -5.04218550472791168711E-14, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 3.22379336594557470981E-13, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -1.98397439776494371520E-12, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 1.17361862988909016308E-11, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -6.66348972350202774223E-11, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 3.62559028155211703701E-10, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -1.88724975172282928790E-9, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 9.38153738649577178388E-9, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -4.44505912879632808065E-8, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 2.00329475355213526229E-7, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -8.56872026469545474066E-7, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 3.47025130813767847674E-6, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -1.32731636560394358279E-5, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 4.78156510755005422638E-5, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -1.61760815825896745588E-4, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 5.12285956168575772895E-4, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -1.51357245063125314899E-3, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 4.15642294431288815669E-3, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -1.05640848946261981558E-2, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 2.47264490306265168283E-2, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -5.29459812080949914269E-2, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 1.02643658689847095384E-1, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -1.76416518357834055153E-1, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 2.52587186443633654823E-1, &b0, &b1, &b2, _state); - v = 0.5*(b0-b2); - z = v*z*ae_exp(z, _state); - } - else - { - y = 32.0/z-2.0; - bessel_besselm1firstcheb(7.51729631084210481353E-18, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 4.41434832307170791151E-18, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -4.65030536848935832153E-17, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -3.20952592199342395980E-17, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 2.96262899764595013876E-16, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 3.30820231092092828324E-16, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -1.88035477551078244854E-15, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -3.81440307243700780478E-15, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 1.04202769841288027642E-14, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 4.27244001671195135429E-14, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -2.10154184277266431302E-14, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -4.08355111109219731823E-13, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -7.19855177624590851209E-13, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 2.03562854414708950722E-12, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 1.41258074366137813316E-11, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 3.25260358301548823856E-11, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -1.89749581235054123450E-11, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -5.58974346219658380687E-10, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -3.83538038596423702205E-9, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -2.63146884688951950684E-8, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -2.51223623787020892529E-7, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -3.88256480887769039346E-6, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -1.10588938762623716291E-4, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -9.76109749136146840777E-3, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 7.78576235018280120474E-1, &b0, &b1, &b2, _state); - v = 0.5*(b0-b2); - z = v*ae_exp(z, _state)/ae_sqrt(z, _state); - } - if( ae_fp_less(x,(double)(0)) ) - { - z = -z; - } - result = z; - return result; -} - - -/************************************************************************* -Modified Bessel function, second kind, order zero - -Returns modified Bessel function of the second kind -of order zero of the argument. - -The range is partitioned into the two intervals [0,8] and -(8, infinity). Chebyshev polynomial expansions are employed -in each interval. - -ACCURACY: - -Tested at 2000 random points between 0 and 8. Peak absolute -error (relative when K0 > 1) was 1.46e-14; rms, 4.26e-15. - Relative error: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 1.2e-15 1.6e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double besselk0(double x, ae_state *_state) -{ - double y; - double z; - double v; - double b0; - double b1; - double b2; - double result; - - - ae_assert(ae_fp_greater(x,(double)(0)), "Domain error in BesselK0: x<=0", _state); - if( ae_fp_less_eq(x,(double)(2)) ) - { - y = x*x-2.0; - bessel_besselmfirstcheb(1.37446543561352307156E-16, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 4.25981614279661018399E-14, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 1.03496952576338420167E-11, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 1.90451637722020886025E-9, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 2.53479107902614945675E-7, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 2.28621210311945178607E-5, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 1.26461541144692592338E-3, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 3.59799365153615016266E-2, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, 3.44289899924628486886E-1, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(y, -5.35327393233902768720E-1, &b0, &b1, &b2, _state); - v = 0.5*(b0-b2); - v = v-ae_log(0.5*x, _state)*besseli0(x, _state); - } - else - { - z = 8.0/x-2.0; - bessel_besselmfirstcheb(5.30043377268626276149E-18, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, -1.64758043015242134646E-17, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 5.21039150503902756861E-17, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, -1.67823109680541210385E-16, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 5.51205597852431940784E-16, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, -1.84859337734377901440E-15, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 6.34007647740507060557E-15, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, -2.22751332699166985548E-14, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 8.03289077536357521100E-14, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, -2.98009692317273043925E-13, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 1.14034058820847496303E-12, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, -4.51459788337394416547E-12, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 1.85594911495471785253E-11, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, -7.95748924447710747776E-11, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 3.57739728140030116597E-10, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, -1.69753450938905987466E-9, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 8.57403401741422608519E-9, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, -4.66048989768794782956E-8, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 2.76681363944501510342E-7, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, -1.83175552271911948767E-6, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 1.39498137188764993662E-5, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, -1.28495495816278026384E-4, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 1.56988388573005337491E-3, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, -3.14481013119645005427E-2, &b0, &b1, &b2, _state); - bessel_besselmnextcheb(z, 2.44030308206595545468E0, &b0, &b1, &b2, _state); - v = 0.5*(b0-b2); - v = v*ae_exp(-x, _state)/ae_sqrt(x, _state); - } - result = v; - return result; -} - - -/************************************************************************* -Modified Bessel function, second kind, order one - -Computes the modified Bessel function of the second kind -of order one of the argument. - -The range is partitioned into the two intervals [0,2] and -(2, infinity). Chebyshev polynomial expansions are employed -in each interval. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 1.2e-15 1.6e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double besselk1(double x, ae_state *_state) -{ - double y; - double z; - double v; - double b0; - double b1; - double b2; - double result; - - - z = 0.5*x; - ae_assert(ae_fp_greater(z,(double)(0)), "Domain error in K1", _state); - if( ae_fp_less_eq(x,(double)(2)) ) - { - y = x*x-2.0; - bessel_besselm1firstcheb(-7.02386347938628759343E-18, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -2.42744985051936593393E-15, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -6.66690169419932900609E-13, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -1.41148839263352776110E-10, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -2.21338763073472585583E-8, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -2.43340614156596823496E-6, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -1.73028895751305206302E-4, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -6.97572385963986435018E-3, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -1.22611180822657148235E-1, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -3.53155960776544875667E-1, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 1.52530022733894777053E0, &b0, &b1, &b2, _state); - v = 0.5*(b0-b2); - result = ae_log(z, _state)*besseli1(x, _state)+v/x; - } - else - { - y = 8.0/x-2.0; - bessel_besselm1firstcheb(-5.75674448366501715755E-18, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 1.79405087314755922667E-17, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -5.68946255844285935196E-17, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 1.83809354436663880070E-16, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -6.05704724837331885336E-16, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 2.03870316562433424052E-15, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -7.01983709041831346144E-15, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 2.47715442448130437068E-14, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -8.97670518232499435011E-14, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 3.34841966607842919884E-13, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -1.28917396095102890680E-12, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 5.13963967348173025100E-12, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -2.12996783842756842877E-11, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 9.21831518760500529508E-11, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -4.19035475934189648750E-10, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 2.01504975519703286596E-9, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -1.03457624656780970260E-8, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 5.74108412545004946722E-8, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -3.50196060308781257119E-7, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 2.40648494783721712015E-6, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -1.93619797416608296024E-5, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 1.95215518471351631108E-4, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, -2.85781685962277938680E-3, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 1.03923736576817238437E-1, &b0, &b1, &b2, _state); - bessel_besselm1nextcheb(y, 2.72062619048444266945E0, &b0, &b1, &b2, _state); - v = 0.5*(b0-b2); - result = ae_exp(-x, _state)*v/ae_sqrt(x, _state); - } - return result; -} - - -/************************************************************************* -Modified Bessel function, second kind, integer order - -Returns modified Bessel function of the second kind -of order n of the argument. - -The range is partitioned into the two intervals [0,9.55] and -(9.55, infinity). An ascending power series is used in the -low range, and an asymptotic expansion in the high range. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,30 90000 1.8e-8 3.0e-10 - -Error is high only near the crossover point x = 9.55 -between the two expansions used. - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 2000 by Stephen L. Moshier -*************************************************************************/ -double besselkn(ae_int_t nn, double x, ae_state *_state) -{ - double k; - double kf; - double nk1f; - double nkf; - double zn; - double t; - double s; - double z0; - double z; - double ans; - double fn; - double pn; - double pk; - double zmn; - double tlg; - double tox; - ae_int_t i; - ae_int_t n; - double eul; - double result; - - - eul = 5.772156649015328606065e-1; - if( nn<0 ) - { - n = -nn; - } - else - { - n = nn; - } - ae_assert(n<=31, "Overflow in BesselKN", _state); - ae_assert(ae_fp_greater(x,(double)(0)), "Domain error in BesselKN", _state); - if( ae_fp_less_eq(x,9.55) ) - { - ans = 0.0; - z0 = 0.25*x*x; - fn = 1.0; - pn = 0.0; - zmn = 1.0; - tox = 2.0/x; - if( n>0 ) - { - pn = -eul; - k = 1.0; - for(i=1; i<=n-1; i++) - { - pn = pn+1.0/k; - k = k+1.0; - fn = fn*k; - } - zmn = tox; - if( n==1 ) - { - ans = 1.0/x; - } - else - { - nk1f = fn/n; - kf = 1.0; - s = nk1f; - z = -z0; - zn = 1.0; - for(i=1; i<=n-1; i++) - { - nk1f = nk1f/(n-i); - kf = kf*i; - zn = zn*z; - t = nk1f*zn/kf; - s = s+t; - ae_assert(ae_fp_greater(ae_maxrealnumber-ae_fabs(t, _state),ae_fabs(s, _state)), "Overflow in BesselKN", _state); - ae_assert(!(ae_fp_greater(tox,1.0)&&ae_fp_less(ae_maxrealnumber/tox,zmn)), "Overflow in BesselKN", _state); - zmn = zmn*tox; - } - s = s*0.5; - t = ae_fabs(s, _state); - ae_assert(!(ae_fp_greater(zmn,1.0)&&ae_fp_less(ae_maxrealnumber/zmn,t)), "Overflow in BesselKN", _state); - ae_assert(!(ae_fp_greater(t,1.0)&&ae_fp_less(ae_maxrealnumber/t,zmn)), "Overflow in BesselKN", _state); - ans = s*zmn; - } - } - tlg = 2.0*ae_log(0.5*x, _state); - pk = -eul; - if( n==0 ) - { - pn = pk; - t = 1.0; - } - else - { - pn = pn+1.0/n; - t = 1.0/fn; - } - s = (pk+pn-tlg)*t; - k = 1.0; - do - { - t = t*(z0/(k*(k+n))); - pk = pk+1.0/k; - pn = pn+1.0/(k+n); - s = s+(pk+pn-tlg)*t; - k = k+1.0; - } - while(ae_fp_greater(ae_fabs(t/s, _state),ae_machineepsilon)); - s = 0.5*s/zmn; - if( n%2!=0 ) - { - s = -s; - } - ans = ans+s; - result = ans; - return result; - } - if( ae_fp_greater(x,ae_log(ae_maxrealnumber, _state)) ) - { - result = (double)(0); - return result; - } - k = (double)(n); - pn = 4.0*k*k; - pk = 1.0; - z0 = 8.0*x; - fn = 1.0; - t = 1.0; - s = t; - nkf = ae_maxrealnumber; - i = 0; - do - { - z = pn-pk*pk; - t = t*z/(fn*z0); - nk1f = ae_fabs(t, _state); - if( i>=n&&ae_fp_greater(nk1f,nkf) ) - { - break; - } - nkf = nk1f; - s = s+t; - fn = fn+1.0; - pk = pk+2.0; - i = i+1; - } - while(ae_fp_greater(ae_fabs(t/s, _state),ae_machineepsilon)); - result = ae_exp(-x, _state)*ae_sqrt(ae_pi/(2.0*x), _state)*s; - return result; -} - - -/************************************************************************* -Internal subroutine - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -static void bessel_besselmfirstcheb(double c, - double* b0, - double* b1, - double* b2, - ae_state *_state) -{ - - - *b0 = c; - *b1 = 0.0; - *b2 = 0.0; -} - - -/************************************************************************* -Internal subroutine - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -static void bessel_besselmnextcheb(double x, - double c, - double* b0, - double* b1, - double* b2, - ae_state *_state) -{ - - - *b2 = *b1; - *b1 = *b0; - *b0 = x*(*b1)-(*b2)+c; -} - - -/************************************************************************* -Internal subroutine - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -static void bessel_besselm1firstcheb(double c, - double* b0, - double* b1, - double* b2, - ae_state *_state) -{ - - - *b0 = c; - *b1 = 0.0; - *b2 = 0.0; -} - - -/************************************************************************* -Internal subroutine - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -static void bessel_besselm1nextcheb(double x, - double c, - double* b0, - double* b1, - double* b2, - ae_state *_state) -{ - - - *b2 = *b1; - *b1 = *b0; - *b0 = x*(*b1)-(*b2)+c; -} - - -static void bessel_besselasympt0(double x, - double* pzero, - double* qzero, - ae_state *_state) -{ - double xsq; - double p2; - double q2; - double p3; - double q3; - - *pzero = 0; - *qzero = 0; - - xsq = 64.0/(x*x); - p2 = 0.0; - p2 = 2485.271928957404011288128951+xsq*p2; - p2 = 153982.6532623911470917825993+xsq*p2; - p2 = 2016135.283049983642487182349+xsq*p2; - p2 = 8413041.456550439208464315611+xsq*p2; - p2 = 12332384.76817638145232406055+xsq*p2; - p2 = 5393485.083869438325262122897+xsq*p2; - q2 = 1.0; - q2 = 2615.700736920839685159081813+xsq*q2; - q2 = 156001.7276940030940592769933+xsq*q2; - q2 = 2025066.801570134013891035236+xsq*q2; - q2 = 8426449.050629797331554404810+xsq*q2; - q2 = 12338310.22786324960844856182+xsq*q2; - q2 = 5393485.083869438325560444960+xsq*q2; - p3 = -0.0; - p3 = -4.887199395841261531199129300+xsq*p3; - p3 = -226.2630641933704113967255053+xsq*p3; - p3 = -2365.956170779108192723612816+xsq*p3; - p3 = -8239.066313485606568803548860+xsq*p3; - p3 = -10381.41698748464093880530341+xsq*p3; - p3 = -3984.617357595222463506790588+xsq*p3; - q3 = 1.0; - q3 = 408.7714673983499223402830260+xsq*q3; - q3 = 15704.89191515395519392882766+xsq*q3; - q3 = 156021.3206679291652539287109+xsq*q3; - q3 = 533291.3634216897168722255057+xsq*q3; - q3 = 666745.4239319826986004038103+xsq*q3; - q3 = 255015.5108860942382983170882+xsq*q3; - *pzero = p2/q2; - *qzero = 8*p3/q3/x; -} - - -static void bessel_besselasympt1(double x, - double* pzero, - double* qzero, - ae_state *_state) -{ - double xsq; - double p2; - double q2; - double p3; - double q3; - - *pzero = 0; - *qzero = 0; - - xsq = 64.0/(x*x); - p2 = -1611.616644324610116477412898; - p2 = -109824.0554345934672737413139+xsq*p2; - p2 = -1523529.351181137383255105722+xsq*p2; - p2 = -6603373.248364939109255245434+xsq*p2; - p2 = -9942246.505077641195658377899+xsq*p2; - p2 = -4435757.816794127857114720794+xsq*p2; - q2 = 1.0; - q2 = -1455.009440190496182453565068+xsq*q2; - q2 = -107263.8599110382011903063867+xsq*q2; - q2 = -1511809.506634160881644546358+xsq*q2; - q2 = -6585339.479723087072826915069+xsq*q2; - q2 = -9934124.389934585658967556309+xsq*q2; - q2 = -4435757.816794127856828016962+xsq*q2; - p3 = 35.26513384663603218592175580; - p3 = 1706.375429020768002061283546+xsq*p3; - p3 = 18494.26287322386679652009819+xsq*p3; - p3 = 66178.83658127083517939992166+xsq*p3; - p3 = 85145.16067533570196555001171+xsq*p3; - p3 = 33220.91340985722351859704442+xsq*p3; - q3 = 1.0; - q3 = 863.8367769604990967475517183+xsq*q3; - q3 = 37890.22974577220264142952256+xsq*q3; - q3 = 400294.4358226697511708610813+xsq*q3; - q3 = 1419460.669603720892855755253+xsq*q3; - q3 = 1819458.042243997298924553839+xsq*q3; - q3 = 708712.8194102874357377502472+xsq*q3; - *pzero = p2/q2; - *qzero = 8*p3/q3/x; -} - - -#endif -#if defined(AE_COMPILE_IBETAF) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Incomplete beta integral - -Returns incomplete beta integral of the arguments, evaluated -from zero to x. The function is defined as - - x - - - - | (a+b) | | a-1 b-1 - ----------- | t (1-t) dt. - - - | | - | (a) | (b) - - 0 - -The domain of definition is 0 <= x <= 1. In this -implementation a and b are restricted to positive values. -The integral from x to 1 may be obtained by the symmetry -relation - - 1 - incbet( a, b, x ) = incbet( b, a, 1-x ). - -The integral is evaluated by a continued fraction expansion -or, when b*x is small, by a power series. - -ACCURACY: - -Tested at uniformly distributed random points (a,b,x) with a and b -in "domain" and x between 0 and 1. - Relative error -arithmetic domain # trials peak rms - IEEE 0,5 10000 6.9e-15 4.5e-16 - IEEE 0,85 250000 2.2e-13 1.7e-14 - IEEE 0,1000 30000 5.3e-12 6.3e-13 - IEEE 0,10000 250000 9.3e-11 7.1e-12 - IEEE 0,100000 10000 8.7e-10 4.8e-11 -Outputs smaller than the IEEE gradual underflow threshold -were excluded from these statistics. - -Cephes Math Library, Release 2.8: June, 2000 -Copyright 1984, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double incompletebeta(double a, double b, double x, ae_state *_state) -{ - double t; - double xc; - double w; - double y; - ae_int_t flag; - double sg; - double big; - double biginv; - double maxgam; - double minlog; - double maxlog; - double result; - - - big = 4.503599627370496e15; - biginv = 2.22044604925031308085e-16; - maxgam = 171.624376956302725; - minlog = ae_log(ae_minrealnumber, _state); - maxlog = ae_log(ae_maxrealnumber, _state); - ae_assert(ae_fp_greater(a,(double)(0))&&ae_fp_greater(b,(double)(0)), "Domain error in IncompleteBeta", _state); - ae_assert(ae_fp_greater_eq(x,(double)(0))&&ae_fp_less_eq(x,(double)(1)), "Domain error in IncompleteBeta", _state); - if( ae_fp_eq(x,(double)(0)) ) - { - result = (double)(0); - return result; - } - if( ae_fp_eq(x,(double)(1)) ) - { - result = (double)(1); - return result; - } - flag = 0; - if( ae_fp_less_eq(b*x,1.0)&&ae_fp_less_eq(x,0.95) ) - { - result = ibetaf_incompletebetaps(a, b, x, maxgam, _state); - return result; - } - w = 1.0-x; - if( ae_fp_greater(x,a/(a+b)) ) - { - flag = 1; - t = a; - a = b; - b = t; - xc = x; - x = w; - } - else - { - xc = w; - } - if( (flag==1&&ae_fp_less_eq(b*x,1.0))&&ae_fp_less_eq(x,0.95) ) - { - t = ibetaf_incompletebetaps(a, b, x, maxgam, _state); - if( ae_fp_less_eq(t,ae_machineepsilon) ) - { - result = 1.0-ae_machineepsilon; - } - else - { - result = 1.0-t; - } - return result; - } - y = x*(a+b-2.0)-(a-1.0); - if( ae_fp_less(y,0.0) ) - { - w = ibetaf_incompletebetafe(a, b, x, big, biginv, _state); - } - else - { - w = ibetaf_incompletebetafe2(a, b, x, big, biginv, _state)/xc; - } - y = a*ae_log(x, _state); - t = b*ae_log(xc, _state); - if( (ae_fp_less(a+b,maxgam)&&ae_fp_less(ae_fabs(y, _state),maxlog))&&ae_fp_less(ae_fabs(t, _state),maxlog) ) - { - t = ae_pow(xc, b, _state); - t = t*ae_pow(x, a, _state); - t = t/a; - t = t*w; - t = t*(gammafunction(a+b, _state)/(gammafunction(a, _state)*gammafunction(b, _state))); - if( flag==1 ) - { - if( ae_fp_less_eq(t,ae_machineepsilon) ) - { - result = 1.0-ae_machineepsilon; - } - else - { - result = 1.0-t; - } - } - else - { - result = t; - } - return result; - } - y = y+t+lngamma(a+b, &sg, _state)-lngamma(a, &sg, _state)-lngamma(b, &sg, _state); - y = y+ae_log(w/a, _state); - if( ae_fp_less(y,minlog) ) - { - t = 0.0; - } - else - { - t = ae_exp(y, _state); - } - if( flag==1 ) - { - if( ae_fp_less_eq(t,ae_machineepsilon) ) - { - t = 1.0-ae_machineepsilon; - } - else - { - t = 1.0-t; - } - } - result = t; - return result; -} - - -/************************************************************************* -Inverse of imcomplete beta integral - -Given y, the function finds x such that - - incbet( a, b, x ) = y . - -The routine performs interval halving or Newton iterations to find the -root of incbet(a,b,x) - y = 0. - - -ACCURACY: - - Relative error: - x a,b -arithmetic domain domain # trials peak rms - IEEE 0,1 .5,10000 50000 5.8e-12 1.3e-13 - IEEE 0,1 .25,100 100000 1.8e-13 3.9e-15 - IEEE 0,1 0,5 50000 1.1e-12 5.5e-15 -With a and b constrained to half-integer or integer values: - IEEE 0,1 .5,10000 50000 5.8e-12 1.1e-13 - IEEE 0,1 .5,100 100000 1.7e-14 7.9e-16 -With a = .5, b constrained to half-integer or integer values: - IEEE 0,1 .5,10000 10000 8.3e-11 1.0e-11 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1996, 2000 by Stephen L. Moshier -*************************************************************************/ -double invincompletebeta(double a, double b, double y, ae_state *_state) -{ - double aaa; - double bbb; - double y0; - double d; - double yyy; - double x; - double x0; - double x1; - double lgm; - double yp; - double di; - double dithresh; - double yl; - double yh; - double xt; - ae_int_t i; - ae_int_t rflg; - ae_int_t dir; - ae_int_t nflg; - double s; - ae_int_t mainlooppos; - ae_int_t ihalve; - ae_int_t ihalvecycle; - ae_int_t newt; - ae_int_t newtcycle; - ae_int_t breaknewtcycle; - ae_int_t breakihalvecycle; - double result; - - - i = 0; - ae_assert(ae_fp_greater_eq(y,(double)(0))&&ae_fp_less_eq(y,(double)(1)), "Domain error in InvIncompleteBeta", _state); - - /* - * special cases - */ - if( ae_fp_eq(y,(double)(0)) ) - { - result = (double)(0); - return result; - } - if( ae_fp_eq(y,1.0) ) - { - result = (double)(1); - return result; - } - - /* - * these initializations are not really necessary, - * but without them compiler complains about 'possibly uninitialized variables'. - */ - dithresh = (double)(0); - rflg = 0; - aaa = (double)(0); - bbb = (double)(0); - y0 = (double)(0); - x = (double)(0); - yyy = (double)(0); - lgm = (double)(0); - dir = 0; - di = (double)(0); - - /* - * normal initializations - */ - x0 = 0.0; - yl = 0.0; - x1 = 1.0; - yh = 1.0; - nflg = 0; - mainlooppos = 0; - ihalve = 1; - ihalvecycle = 2; - newt = 3; - newtcycle = 4; - breaknewtcycle = 5; - breakihalvecycle = 6; - - /* - * main loop - */ - for(;;) - { - - /* - * start - */ - if( mainlooppos==0 ) - { - if( ae_fp_less_eq(a,1.0)||ae_fp_less_eq(b,1.0) ) - { - dithresh = 1.0e-6; - rflg = 0; - aaa = a; - bbb = b; - y0 = y; - x = aaa/(aaa+bbb); - yyy = incompletebeta(aaa, bbb, x, _state); - mainlooppos = ihalve; - continue; - } - else - { - dithresh = 1.0e-4; - } - yp = -invnormaldistribution(y, _state); - if( ae_fp_greater(y,0.5) ) - { - rflg = 1; - aaa = b; - bbb = a; - y0 = 1.0-y; - yp = -yp; - } - else - { - rflg = 0; - aaa = a; - bbb = b; - y0 = y; - } - lgm = (yp*yp-3.0)/6.0; - x = 2.0/(1.0/(2.0*aaa-1.0)+1.0/(2.0*bbb-1.0)); - d = yp*ae_sqrt(x+lgm, _state)/x-(1.0/(2.0*bbb-1.0)-1.0/(2.0*aaa-1.0))*(lgm+5.0/6.0-2.0/(3.0*x)); - d = 2.0*d; - if( ae_fp_less(d,ae_log(ae_minrealnumber, _state)) ) - { - x = (double)(0); - break; - } - x = aaa/(aaa+bbb*ae_exp(d, _state)); - yyy = incompletebeta(aaa, bbb, x, _state); - yp = (yyy-y0)/y0; - if( ae_fp_less(ae_fabs(yp, _state),0.2) ) - { - mainlooppos = newt; - continue; - } - mainlooppos = ihalve; - continue; - } - - /* - * ihalve - */ - if( mainlooppos==ihalve ) - { - dir = 0; - di = 0.5; - i = 0; - mainlooppos = ihalvecycle; - continue; - } - - /* - * ihalvecycle - */ - if( mainlooppos==ihalvecycle ) - { - if( i<=99 ) - { - if( i!=0 ) - { - x = x0+di*(x1-x0); - if( ae_fp_eq(x,1.0) ) - { - x = 1.0-ae_machineepsilon; - } - if( ae_fp_eq(x,0.0) ) - { - di = 0.5; - x = x0+di*(x1-x0); - if( ae_fp_eq(x,0.0) ) - { - break; - } - } - yyy = incompletebeta(aaa, bbb, x, _state); - yp = (x1-x0)/(x1+x0); - if( ae_fp_less(ae_fabs(yp, _state),dithresh) ) - { - mainlooppos = newt; - continue; - } - yp = (yyy-y0)/y0; - if( ae_fp_less(ae_fabs(yp, _state),dithresh) ) - { - mainlooppos = newt; - continue; - } - } - if( ae_fp_less(yyy,y0) ) - { - x0 = x; - yl = yyy; - if( dir<0 ) - { - dir = 0; - di = 0.5; - } - else - { - if( dir>3 ) - { - di = 1.0-(1.0-di)*(1.0-di); - } - else - { - if( dir>1 ) - { - di = 0.5*di+0.5; - } - else - { - di = (y0-yyy)/(yh-yl); - } - } - } - dir = dir+1; - if( ae_fp_greater(x0,0.75) ) - { - if( rflg==1 ) - { - rflg = 0; - aaa = a; - bbb = b; - y0 = y; - } - else - { - rflg = 1; - aaa = b; - bbb = a; - y0 = 1.0-y; - } - x = 1.0-x; - yyy = incompletebeta(aaa, bbb, x, _state); - x0 = 0.0; - yl = 0.0; - x1 = 1.0; - yh = 1.0; - mainlooppos = ihalve; - continue; - } - } - else - { - x1 = x; - if( rflg==1&&ae_fp_less(x1,ae_machineepsilon) ) - { - x = 0.0; - break; - } - yh = yyy; - if( dir>0 ) - { - dir = 0; - di = 0.5; - } - else - { - if( dir<-3 ) - { - di = di*di; - } - else - { - if( dir<-1 ) - { - di = 0.5*di; - } - else - { - di = (yyy-y0)/(yh-yl); - } - } - } - dir = dir-1; - } - i = i+1; - mainlooppos = ihalvecycle; - continue; - } - else - { - mainlooppos = breakihalvecycle; - continue; - } - } - - /* - * breakihalvecycle - */ - if( mainlooppos==breakihalvecycle ) - { - if( ae_fp_greater_eq(x0,1.0) ) - { - x = 1.0-ae_machineepsilon; - break; - } - if( ae_fp_less_eq(x,0.0) ) - { - x = 0.0; - break; - } - mainlooppos = newt; - continue; - } - - /* - * newt - */ - if( mainlooppos==newt ) - { - if( nflg!=0 ) - { - break; - } - nflg = 1; - lgm = lngamma(aaa+bbb, &s, _state)-lngamma(aaa, &s, _state)-lngamma(bbb, &s, _state); - i = 0; - mainlooppos = newtcycle; - continue; - } - - /* - * newtcycle - */ - if( mainlooppos==newtcycle ) - { - if( i<=7 ) - { - if( i!=0 ) - { - yyy = incompletebeta(aaa, bbb, x, _state); - } - if( ae_fp_less(yyy,yl) ) - { - x = x0; - yyy = yl; - } - else - { - if( ae_fp_greater(yyy,yh) ) - { - x = x1; - yyy = yh; - } - else - { - if( ae_fp_less(yyy,y0) ) - { - x0 = x; - yl = yyy; - } - else - { - x1 = x; - yh = yyy; - } - } - } - if( ae_fp_eq(x,1.0)||ae_fp_eq(x,0.0) ) - { - mainlooppos = breaknewtcycle; - continue; - } - d = (aaa-1.0)*ae_log(x, _state)+(bbb-1.0)*ae_log(1.0-x, _state)+lgm; - if( ae_fp_less(d,ae_log(ae_minrealnumber, _state)) ) - { - break; - } - if( ae_fp_greater(d,ae_log(ae_maxrealnumber, _state)) ) - { - mainlooppos = breaknewtcycle; - continue; - } - d = ae_exp(d, _state); - d = (yyy-y0)/d; - xt = x-d; - if( ae_fp_less_eq(xt,x0) ) - { - yyy = (x-x0)/(x1-x0); - xt = x0+0.5*yyy*(x-x0); - if( ae_fp_less_eq(xt,0.0) ) - { - mainlooppos = breaknewtcycle; - continue; - } - } - if( ae_fp_greater_eq(xt,x1) ) - { - yyy = (x1-x)/(x1-x0); - xt = x1-0.5*yyy*(x1-x); - if( ae_fp_greater_eq(xt,1.0) ) - { - mainlooppos = breaknewtcycle; - continue; - } - } - x = xt; - if( ae_fp_less(ae_fabs(d/x, _state),128.0*ae_machineepsilon) ) - { - break; - } - i = i+1; - mainlooppos = newtcycle; - continue; - } - else - { - mainlooppos = breaknewtcycle; - continue; - } - } - - /* - * breaknewtcycle - */ - if( mainlooppos==breaknewtcycle ) - { - dithresh = 256.0*ae_machineepsilon; - mainlooppos = ihalve; - continue; - } - } - - /* - * done - */ - if( rflg!=0 ) - { - if( ae_fp_less_eq(x,ae_machineepsilon) ) - { - x = 1.0-ae_machineepsilon; - } - else - { - x = 1.0-x; - } - } - result = x; - return result; -} - - -/************************************************************************* -Continued fraction expansion #1 for incomplete beta integral - -Cephes Math Library, Release 2.8: June, 2000 -Copyright 1984, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -static double ibetaf_incompletebetafe(double a, - double b, - double x, - double big, - double biginv, - ae_state *_state) -{ - double xk; - double pk; - double pkm1; - double pkm2; - double qk; - double qkm1; - double qkm2; - double k1; - double k2; - double k3; - double k4; - double k5; - double k6; - double k7; - double k8; - double r; - double t; - double ans; - double thresh; - ae_int_t n; - double result; - - - k1 = a; - k2 = a+b; - k3 = a; - k4 = a+1.0; - k5 = 1.0; - k6 = b-1.0; - k7 = k4; - k8 = a+2.0; - pkm2 = 0.0; - qkm2 = 1.0; - pkm1 = 1.0; - qkm1 = 1.0; - ans = 1.0; - r = 1.0; - n = 0; - thresh = 3.0*ae_machineepsilon; - do - { - xk = -x*k1*k2/(k3*k4); - pk = pkm1+pkm2*xk; - qk = qkm1+qkm2*xk; - pkm2 = pkm1; - pkm1 = pk; - qkm2 = qkm1; - qkm1 = qk; - xk = x*k5*k6/(k7*k8); - pk = pkm1+pkm2*xk; - qk = qkm1+qkm2*xk; - pkm2 = pkm1; - pkm1 = pk; - qkm2 = qkm1; - qkm1 = qk; - if( ae_fp_neq(qk,(double)(0)) ) - { - r = pk/qk; - } - if( ae_fp_neq(r,(double)(0)) ) - { - t = ae_fabs((ans-r)/r, _state); - ans = r; - } - else - { - t = 1.0; - } - if( ae_fp_less(t,thresh) ) - { - break; - } - k1 = k1+1.0; - k2 = k2+1.0; - k3 = k3+2.0; - k4 = k4+2.0; - k5 = k5+1.0; - k6 = k6-1.0; - k7 = k7+2.0; - k8 = k8+2.0; - if( ae_fp_greater(ae_fabs(qk, _state)+ae_fabs(pk, _state),big) ) - { - pkm2 = pkm2*biginv; - pkm1 = pkm1*biginv; - qkm2 = qkm2*biginv; - qkm1 = qkm1*biginv; - } - if( ae_fp_less(ae_fabs(qk, _state),biginv)||ae_fp_less(ae_fabs(pk, _state),biginv) ) - { - pkm2 = pkm2*big; - pkm1 = pkm1*big; - qkm2 = qkm2*big; - qkm1 = qkm1*big; - } - n = n+1; - } - while(n!=300); - result = ans; - return result; -} - - -/************************************************************************* -Continued fraction expansion #2 -for incomplete beta integral - -Cephes Math Library, Release 2.8: June, 2000 -Copyright 1984, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -static double ibetaf_incompletebetafe2(double a, - double b, - double x, - double big, - double biginv, - ae_state *_state) -{ - double xk; - double pk; - double pkm1; - double pkm2; - double qk; - double qkm1; - double qkm2; - double k1; - double k2; - double k3; - double k4; - double k5; - double k6; - double k7; - double k8; - double r; - double t; - double ans; - double z; - double thresh; - ae_int_t n; - double result; - - - k1 = a; - k2 = b-1.0; - k3 = a; - k4 = a+1.0; - k5 = 1.0; - k6 = a+b; - k7 = a+1.0; - k8 = a+2.0; - pkm2 = 0.0; - qkm2 = 1.0; - pkm1 = 1.0; - qkm1 = 1.0; - z = x/(1.0-x); - ans = 1.0; - r = 1.0; - n = 0; - thresh = 3.0*ae_machineepsilon; - do - { - xk = -z*k1*k2/(k3*k4); - pk = pkm1+pkm2*xk; - qk = qkm1+qkm2*xk; - pkm2 = pkm1; - pkm1 = pk; - qkm2 = qkm1; - qkm1 = qk; - xk = z*k5*k6/(k7*k8); - pk = pkm1+pkm2*xk; - qk = qkm1+qkm2*xk; - pkm2 = pkm1; - pkm1 = pk; - qkm2 = qkm1; - qkm1 = qk; - if( ae_fp_neq(qk,(double)(0)) ) - { - r = pk/qk; - } - if( ae_fp_neq(r,(double)(0)) ) - { - t = ae_fabs((ans-r)/r, _state); - ans = r; - } - else - { - t = 1.0; - } - if( ae_fp_less(t,thresh) ) - { - break; - } - k1 = k1+1.0; - k2 = k2-1.0; - k3 = k3+2.0; - k4 = k4+2.0; - k5 = k5+1.0; - k6 = k6+1.0; - k7 = k7+2.0; - k8 = k8+2.0; - if( ae_fp_greater(ae_fabs(qk, _state)+ae_fabs(pk, _state),big) ) - { - pkm2 = pkm2*biginv; - pkm1 = pkm1*biginv; - qkm2 = qkm2*biginv; - qkm1 = qkm1*biginv; - } - if( ae_fp_less(ae_fabs(qk, _state),biginv)||ae_fp_less(ae_fabs(pk, _state),biginv) ) - { - pkm2 = pkm2*big; - pkm1 = pkm1*big; - qkm2 = qkm2*big; - qkm1 = qkm1*big; - } - n = n+1; - } - while(n!=300); - result = ans; - return result; -} - - -/************************************************************************* -Power series for incomplete beta integral. -Use when b*x is small and x not too close to 1. - -Cephes Math Library, Release 2.8: June, 2000 -Copyright 1984, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -static double ibetaf_incompletebetaps(double a, - double b, - double x, - double maxgam, - ae_state *_state) -{ - double s; - double t; - double u; - double v; - double n; - double t1; - double z; - double ai; - double sg; - double result; - - - ai = 1.0/a; - u = (1.0-b)*x; - v = u/(a+1.0); - t1 = v; - t = u; - n = 2.0; - s = 0.0; - z = ae_machineepsilon*ai; - while(ae_fp_greater(ae_fabs(v, _state),z)) - { - u = (n-b)*x/n; - t = t*u; - v = t/(a+n); - s = s+v; - n = n+1.0; - } - s = s+t1; - s = s+ai; - u = a*ae_log(x, _state); - if( ae_fp_less(a+b,maxgam)&&ae_fp_less(ae_fabs(u, _state),ae_log(ae_maxrealnumber, _state)) ) - { - t = gammafunction(a+b, _state)/(gammafunction(a, _state)*gammafunction(b, _state)); - s = s*t*ae_pow(x, a, _state); - } - else - { - t = lngamma(a+b, &sg, _state)-lngamma(a, &sg, _state)-lngamma(b, &sg, _state)+u+ae_log(s, _state); - if( ae_fp_less(t,ae_log(ae_minrealnumber, _state)) ) - { - s = 0.0; - } - else - { - s = ae_exp(t, _state); - } - } - result = s; - return result; -} - - -#endif -#if defined(AE_COMPILE_FDISTR) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -F distribution - -Returns the area from zero to x under the F density -function (also known as Snedcor's density or the -variance ratio density). This is the density -of x = (u1/df1)/(u2/df2), where u1 and u2 are random -variables having Chi square distributions with df1 -and df2 degrees of freedom, respectively. -The incomplete beta integral is used, according to the -formula - -P(x) = incbet( df1/2, df2/2, (df1*x/(df2 + df1*x) ). - - -The arguments a and b are greater than zero, and x is -nonnegative. - -ACCURACY: - -Tested at random points (a,b,x). - - x a,b Relative error: -arithmetic domain domain # trials peak rms - IEEE 0,1 0,100 100000 9.8e-15 1.7e-15 - IEEE 1,5 0,100 100000 6.5e-15 3.5e-16 - IEEE 0,1 1,10000 100000 2.2e-11 3.3e-12 - IEEE 1,5 1,10000 100000 1.1e-11 1.7e-13 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double fdistribution(ae_int_t a, ae_int_t b, double x, ae_state *_state) -{ - double w; - double result; - - - ae_assert((a>=1&&b>=1)&&ae_fp_greater_eq(x,(double)(0)), "Domain error in FDistribution", _state); - w = a*x; - w = w/(b+w); - result = incompletebeta(0.5*a, 0.5*b, w, _state); - return result; -} - - -/************************************************************************* -Complemented F distribution - -Returns the area from x to infinity under the F density -function (also known as Snedcor's density or the -variance ratio density). - - - inf. - - - 1 | | a-1 b-1 -1-P(x) = ------ | t (1-t) dt - B(a,b) | | - - - x - - -The incomplete beta integral is used, according to the -formula - -P(x) = incbet( df2/2, df1/2, (df2/(df2 + df1*x) ). - - -ACCURACY: - -Tested at random points (a,b,x) in the indicated intervals. - x a,b Relative error: -arithmetic domain domain # trials peak rms - IEEE 0,1 1,100 100000 3.7e-14 5.9e-16 - IEEE 1,5 1,100 100000 8.0e-15 1.6e-15 - IEEE 0,1 1,10000 100000 1.8e-11 3.5e-13 - IEEE 1,5 1,10000 100000 2.0e-11 3.0e-12 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double fcdistribution(ae_int_t a, ae_int_t b, double x, ae_state *_state) -{ - double w; - double result; - - - ae_assert((a>=1&&b>=1)&&ae_fp_greater_eq(x,(double)(0)), "Domain error in FCDistribution", _state); - w = b/(b+a*x); - result = incompletebeta(0.5*b, 0.5*a, w, _state); - return result; -} - - -/************************************************************************* -Inverse of complemented F distribution - -Finds the F density argument x such that the integral -from x to infinity of the F density is equal to the -given probability p. - -This is accomplished using the inverse beta integral -function and the relations - - z = incbi( df2/2, df1/2, p ) - x = df2 (1-z) / (df1 z). - -Note: the following relations hold for the inverse of -the uncomplemented F distribution: - - z = incbi( df1/2, df2/2, p ) - x = df2 z / (df1 (1-z)). - -ACCURACY: - -Tested at random points (a,b,p). - - a,b Relative error: -arithmetic domain # trials peak rms - For p between .001 and 1: - IEEE 1,100 100000 8.3e-15 4.7e-16 - IEEE 1,10000 100000 2.1e-11 1.4e-13 - For p between 10^-6 and 10^-3: - IEEE 1,100 50000 1.3e-12 8.4e-15 - IEEE 1,10000 50000 3.0e-12 4.8e-14 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double invfdistribution(ae_int_t a, - ae_int_t b, - double y, - ae_state *_state) -{ - double w; - double result; - - - ae_assert(((a>=1&&b>=1)&&ae_fp_greater(y,(double)(0)))&&ae_fp_less_eq(y,(double)(1)), "Domain error in InvFDistribution", _state); - - /* - * Compute probability for x = 0.5 - */ - w = incompletebeta(0.5*b, 0.5*a, 0.5, _state); - - /* - * If that is greater than y, then the solution w < .5 - * Otherwise, solve at 1-y to remove cancellation in (b - b*w) - */ - if( ae_fp_greater(w,y)||ae_fp_less(y,0.001) ) - { - w = invincompletebeta(0.5*b, 0.5*a, y, _state); - result = (b-b*w)/(a*w); - } - else - { - w = invincompletebeta(0.5*a, 0.5*b, 1.0-y, _state); - result = b*w/(a*(1.0-w)); - } - return result; -} - - -#endif -#if defined(AE_COMPILE_FRESNEL) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Fresnel integral - -Evaluates the Fresnel integrals - - x - - - | | -C(x) = | cos(pi/2 t**2) dt, - | | - - - 0 - - x - - - | | -S(x) = | sin(pi/2 t**2) dt. - | | - - - 0 - - -The integrals are evaluated by a power series for x < 1. -For x >= 1 auxiliary functions f(x) and g(x) are employed -such that - -C(x) = 0.5 + f(x) sin( pi/2 x**2 ) - g(x) cos( pi/2 x**2 ) -S(x) = 0.5 - f(x) cos( pi/2 x**2 ) - g(x) sin( pi/2 x**2 ) - - - -ACCURACY: - - Relative error. - -Arithmetic function domain # trials peak rms - IEEE S(x) 0, 10 10000 2.0e-15 3.2e-16 - IEEE C(x) 0, 10 10000 1.8e-15 3.3e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -void fresnelintegral(double x, double* c, double* s, ae_state *_state) -{ - double xxa; - double f; - double g; - double cc; - double ss; - double t; - double u; - double x2; - double sn; - double sd; - double cn; - double cd; - double fn; - double fd; - double gn; - double gd; - double mpi; - double mpio2; - - - mpi = 3.14159265358979323846; - mpio2 = 1.57079632679489661923; - xxa = x; - x = ae_fabs(xxa, _state); - x2 = x*x; - if( ae_fp_less(x2,2.5625) ) - { - t = x2*x2; - sn = -2.99181919401019853726E3; - sn = sn*t+7.08840045257738576863E5; - sn = sn*t-6.29741486205862506537E7; - sn = sn*t+2.54890880573376359104E9; - sn = sn*t-4.42979518059697779103E10; - sn = sn*t+3.18016297876567817986E11; - sd = 1.00000000000000000000E0; - sd = sd*t+2.81376268889994315696E2; - sd = sd*t+4.55847810806532581675E4; - sd = sd*t+5.17343888770096400730E6; - sd = sd*t+4.19320245898111231129E8; - sd = sd*t+2.24411795645340920940E10; - sd = sd*t+6.07366389490084639049E11; - cn = -4.98843114573573548651E-8; - cn = cn*t+9.50428062829859605134E-6; - cn = cn*t-6.45191435683965050962E-4; - cn = cn*t+1.88843319396703850064E-2; - cn = cn*t-2.05525900955013891793E-1; - cn = cn*t+9.99999999999999998822E-1; - cd = 3.99982968972495980367E-12; - cd = cd*t+9.15439215774657478799E-10; - cd = cd*t+1.25001862479598821474E-7; - cd = cd*t+1.22262789024179030997E-5; - cd = cd*t+8.68029542941784300606E-4; - cd = cd*t+4.12142090722199792936E-2; - cd = cd*t+1.00000000000000000118E0; - *s = ae_sign(xxa, _state)*x*x2*sn/sd; - *c = ae_sign(xxa, _state)*x*cn/cd; - return; - } - if( ae_fp_greater(x,36974.0) ) - { - *c = ae_sign(xxa, _state)*0.5; - *s = ae_sign(xxa, _state)*0.5; - return; - } - x2 = x*x; - t = mpi*x2; - u = 1/(t*t); - t = 1/t; - fn = 4.21543555043677546506E-1; - fn = fn*u+1.43407919780758885261E-1; - fn = fn*u+1.15220955073585758835E-2; - fn = fn*u+3.45017939782574027900E-4; - fn = fn*u+4.63613749287867322088E-6; - fn = fn*u+3.05568983790257605827E-8; - fn = fn*u+1.02304514164907233465E-10; - fn = fn*u+1.72010743268161828879E-13; - fn = fn*u+1.34283276233062758925E-16; - fn = fn*u+3.76329711269987889006E-20; - fd = 1.00000000000000000000E0; - fd = fd*u+7.51586398353378947175E-1; - fd = fd*u+1.16888925859191382142E-1; - fd = fd*u+6.44051526508858611005E-3; - fd = fd*u+1.55934409164153020873E-4; - fd = fd*u+1.84627567348930545870E-6; - fd = fd*u+1.12699224763999035261E-8; - fd = fd*u+3.60140029589371370404E-11; - fd = fd*u+5.88754533621578410010E-14; - fd = fd*u+4.52001434074129701496E-17; - fd = fd*u+1.25443237090011264384E-20; - gn = 5.04442073643383265887E-1; - gn = gn*u+1.97102833525523411709E-1; - gn = gn*u+1.87648584092575249293E-2; - gn = gn*u+6.84079380915393090172E-4; - gn = gn*u+1.15138826111884280931E-5; - gn = gn*u+9.82852443688422223854E-8; - gn = gn*u+4.45344415861750144738E-10; - gn = gn*u+1.08268041139020870318E-12; - gn = gn*u+1.37555460633261799868E-15; - gn = gn*u+8.36354435630677421531E-19; - gn = gn*u+1.86958710162783235106E-22; - gd = 1.00000000000000000000E0; - gd = gd*u+1.47495759925128324529E0; - gd = gd*u+3.37748989120019970451E-1; - gd = gd*u+2.53603741420338795122E-2; - gd = gd*u+8.14679107184306179049E-4; - gd = gd*u+1.27545075667729118702E-5; - gd = gd*u+1.04314589657571990585E-7; - gd = gd*u+4.60680728146520428211E-10; - gd = gd*u+1.10273215066240270757E-12; - gd = gd*u+1.38796531259578871258E-15; - gd = gd*u+8.39158816283118707363E-19; - gd = gd*u+1.86958710162783236342E-22; - f = 1-u*fn/fd; - g = t*gn/gd; - t = mpio2*x2; - cc = ae_cos(t, _state); - ss = ae_sin(t, _state); - t = mpi*x; - *c = 0.5+(f*ss-g*cc)/t; - *s = 0.5-(f*cc+g*ss)/t; - *c = *c*ae_sign(xxa, _state); - *s = *s*ae_sign(xxa, _state); -} - - -#endif -#if defined(AE_COMPILE_JACOBIANELLIPTIC) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Jacobian Elliptic Functions - -Evaluates the Jacobian elliptic functions sn(u|m), cn(u|m), -and dn(u|m) of parameter m between 0 and 1, and real -argument u. - -These functions are periodic, with quarter-period on the -real axis equal to the complete elliptic integral -ellpk(1.0-m). - -Relation to incomplete elliptic integral: -If u = ellik(phi,m), then sn(u|m) = sin(phi), -and cn(u|m) = cos(phi). Phi is called the amplitude of u. - -Computation is by means of the arithmetic-geometric mean -algorithm, except when m is within 1e-9 of 0 or 1. In the -latter case with m close to 1, the approximation applies -only for phi < pi/2. - -ACCURACY: - -Tested at random points with u between 0 and 10, m between -0 and 1. - - Absolute error (* = relative error): -arithmetic function # trials peak rms - IEEE phi 10000 9.2e-16* 1.4e-16* - IEEE sn 50000 4.1e-15 4.6e-16 - IEEE cn 40000 3.6e-15 4.4e-16 - IEEE dn 10000 1.3e-12 1.8e-14 - - Peak error observed in consistency check using addition -theorem for sn(u+v) was 4e-16 (absolute). Also tested by -the above relation to the incomplete elliptic integral. -Accuracy deteriorates when u is large. - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -void jacobianellipticfunctions(double u, - double m, - double* sn, - double* cn, - double* dn, - double* ph, - ae_state *_state) -{ - ae_frame _frame_block; - double ai; - double b; - double phi; - double t; - double twon; - ae_vector a; - ae_vector c; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&c, 0, sizeof(c)); - *sn = 0; - *cn = 0; - *dn = 0; - *ph = 0; - ae_vector_init(&a, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c, 0, DT_REAL, _state, ae_true); - - ae_assert(ae_fp_greater_eq(m,(double)(0))&&ae_fp_less_eq(m,(double)(1)), "Domain error in JacobianEllipticFunctions: m<0 or m>1", _state); - ae_vector_set_length(&a, 8+1, _state); - ae_vector_set_length(&c, 8+1, _state); - if( ae_fp_less(m,1.0e-9) ) - { - t = ae_sin(u, _state); - b = ae_cos(u, _state); - ai = 0.25*m*(u-t*b); - *sn = t-ai*b; - *cn = b+ai*t; - *ph = u-ai; - *dn = 1.0-0.5*m*t*t; - ae_frame_leave(_state); - return; - } - if( ae_fp_greater_eq(m,0.9999999999) ) - { - ai = 0.25*(1.0-m); - b = ae_cosh(u, _state); - t = ae_tanh(u, _state); - phi = 1.0/b; - twon = b*ae_sinh(u, _state); - *sn = t+ai*(twon-u)/(b*b); - *ph = 2.0*ae_atan(ae_exp(u, _state), _state)-1.57079632679489661923+ai*(twon-u)/b; - ai = ai*t*phi; - *cn = phi-ai*(twon-u); - *dn = phi+ai*(twon+u); - ae_frame_leave(_state); - return; - } - a.ptr.p_double[0] = 1.0; - b = ae_sqrt(1.0-m, _state); - c.ptr.p_double[0] = ae_sqrt(m, _state); - twon = 1.0; - i = 0; - while(ae_fp_greater(ae_fabs(c.ptr.p_double[i]/a.ptr.p_double[i], _state),ae_machineepsilon)) - { - if( i>7 ) - { - ae_assert(ae_false, "Overflow in JacobianEllipticFunctions", _state); - break; - } - ai = a.ptr.p_double[i]; - i = i+1; - c.ptr.p_double[i] = 0.5*(ai-b); - t = ae_sqrt(ai*b, _state); - a.ptr.p_double[i] = 0.5*(ai+b); - b = t; - twon = twon*2.0; - } - phi = twon*a.ptr.p_double[i]*u; - do - { - t = c.ptr.p_double[i]*ae_sin(phi, _state)/a.ptr.p_double[i]; - b = phi; - phi = (ae_asin(t, _state)+phi)/2.0; - i = i-1; - } - while(i!=0); - *sn = ae_sin(phi, _state); - t = ae_cos(phi, _state); - *cn = t; - *dn = t/ae_cos(phi-b, _state); - *ph = phi; - ae_frame_leave(_state); -} - - -#endif -#if defined(AE_COMPILE_PSIF) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Psi (digamma) function - - d - - psi(x) = -- ln | (x) - dx - -is the logarithmic derivative of the gamma function. -For integer x, - n-1 - - -psi(n) = -EUL + > 1/k. - - - k=1 - -This formula is used for 0 < n <= 10. If x is negative, it -is transformed to a positive argument by the reflection -formula psi(1-x) = psi(x) + pi cot(pi x). -For general positive x, the argument is made greater than 10 -using the recurrence psi(x+1) = psi(x) + 1/x. -Then the following asymptotic expansion is applied: - - inf. B - - 2k -psi(x) = log(x) - 1/2x - > ------- - - 2k - k=1 2k x - -where the B2k are Bernoulli numbers. - -ACCURACY: - Relative error (except absolute when |psi| < 1): -arithmetic domain # trials peak rms - IEEE 0,30 30000 1.3e-15 1.4e-16 - IEEE -30,0 40000 1.5e-15 2.2e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double psi(double x, ae_state *_state) -{ - double p; - double q; - double nz; - double s; - double w; - double y; - double z; - double polv; - ae_int_t i; - ae_int_t n; - ae_int_t negative; - double result; - - - negative = 0; - nz = 0.0; - if( ae_fp_less_eq(x,(double)(0)) ) - { - negative = 1; - q = x; - p = (double)(ae_ifloor(q, _state)); - if( ae_fp_eq(p,q) ) - { - ae_assert(ae_false, "Singularity in Psi(x)", _state); - result = ae_maxrealnumber; - return result; - } - nz = q-p; - if( ae_fp_neq(nz,0.5) ) - { - if( ae_fp_greater(nz,0.5) ) - { - p = p+1.0; - nz = q-p; - } - nz = ae_pi/ae_tan(ae_pi*nz, _state); - } - else - { - nz = 0.0; - } - x = 1.0-x; - } - if( ae_fp_less_eq(x,10.0)&&ae_fp_eq(x,(double)(ae_ifloor(x, _state))) ) - { - y = 0.0; - n = ae_ifloor(x, _state); - for(i=1; i<=n-1; i++) - { - w = (double)(i); - y = y+1.0/w; - } - y = y-0.57721566490153286061; - } - else - { - s = x; - w = 0.0; - while(ae_fp_less(s,10.0)) - { - w = w+1.0/s; - s = s+1.0; - } - if( ae_fp_less(s,1.0E17) ) - { - z = 1.0/(s*s); - polv = 8.33333333333333333333E-2; - polv = polv*z-2.10927960927960927961E-2; - polv = polv*z+7.57575757575757575758E-3; - polv = polv*z-4.16666666666666666667E-3; - polv = polv*z+3.96825396825396825397E-3; - polv = polv*z-8.33333333333333333333E-3; - polv = polv*z+8.33333333333333333333E-2; - y = z*polv; - } - else - { - y = 0.0; - } - y = ae_log(s, _state)-0.5/s-y-w; - } - if( negative!=0 ) - { - y = y-nz; - } - result = y; - return result; -} - - -#endif -#if defined(AE_COMPILE_EXPINTEGRALS) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Exponential integral Ei(x) - - x - - t - | | e - Ei(x) = -|- --- dt . - | | t - - - -inf - -Not defined for x <= 0. -See also expn.c. - - - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,100 50000 8.6e-16 1.3e-16 - -Cephes Math Library Release 2.8: May, 1999 -Copyright 1999 by Stephen L. Moshier -*************************************************************************/ -double exponentialintegralei(double x, ae_state *_state) -{ - double eul; - double f; - double f1; - double f2; - double w; - double result; - - - eul = 0.5772156649015328606065; - if( ae_fp_less_eq(x,(double)(0)) ) - { - result = (double)(0); - return result; - } - if( ae_fp_less(x,(double)(2)) ) - { - f1 = -5.350447357812542947283; - f1 = f1*x+218.5049168816613393830; - f1 = f1*x-4176.572384826693777058; - f1 = f1*x+55411.76756393557601232; - f1 = f1*x-331338.1331178144034309; - f1 = f1*x+1592627.163384945414220; - f2 = 1.000000000000000000000; - f2 = f2*x-52.50547959112862969197; - f2 = f2*x+1259.616186786790571525; - f2 = f2*x-17565.49581973534652631; - f2 = f2*x+149306.2117002725991967; - f2 = f2*x-729494.9239640527645655; - f2 = f2*x+1592627.163384945429726; - f = f1/f2; - result = eul+ae_log(x, _state)+x*f; - return result; - } - if( ae_fp_less(x,(double)(4)) ) - { - w = 1/x; - f1 = 1.981808503259689673238E-2; - f1 = f1*w-1.271645625984917501326; - f1 = f1*w-2.088160335681228318920; - f1 = f1*w+2.755544509187936721172; - f1 = f1*w-4.409507048701600257171E-1; - f1 = f1*w+4.665623805935891391017E-2; - f1 = f1*w-1.545042679673485262580E-3; - f1 = f1*w+7.059980605299617478514E-5; - f2 = 1.000000000000000000000; - f2 = f2*w+1.476498670914921440652; - f2 = f2*w+5.629177174822436244827E-1; - f2 = f2*w+1.699017897879307263248E-1; - f2 = f2*w+2.291647179034212017463E-2; - f2 = f2*w+4.450150439728752875043E-3; - f2 = f2*w+1.727439612206521482874E-4; - f2 = f2*w+3.953167195549672482304E-5; - f = f1/f2; - result = ae_exp(x, _state)*w*(1+w*f); - return result; - } - if( ae_fp_less(x,(double)(8)) ) - { - w = 1/x; - f1 = -1.373215375871208729803; - f1 = f1*w-7.084559133740838761406E-1; - f1 = f1*w+1.580806855547941010501; - f1 = f1*w-2.601500427425622944234E-1; - f1 = f1*w+2.994674694113713763365E-2; - f1 = f1*w-1.038086040188744005513E-3; - f1 = f1*w+4.371064420753005429514E-5; - f1 = f1*w+2.141783679522602903795E-6; - f2 = 1.000000000000000000000; - f2 = f2*w+8.585231423622028380768E-1; - f2 = f2*w+4.483285822873995129957E-1; - f2 = f2*w+7.687932158124475434091E-2; - f2 = f2*w+2.449868241021887685904E-2; - f2 = f2*w+8.832165941927796567926E-4; - f2 = f2*w+4.590952299511353531215E-4; - f2 = f2*w+(-4.729848351866523044863E-6); - f2 = f2*w+2.665195537390710170105E-6; - f = f1/f2; - result = ae_exp(x, _state)*w*(1+w*f); - return result; - } - if( ae_fp_less(x,(double)(16)) ) - { - w = 1/x; - f1 = -2.106934601691916512584; - f1 = f1*w+1.732733869664688041885; - f1 = f1*w-2.423619178935841904839E-1; - f1 = f1*w+2.322724180937565842585E-2; - f1 = f1*w+2.372880440493179832059E-4; - f1 = f1*w-8.343219561192552752335E-5; - f1 = f1*w+1.363408795605250394881E-5; - f1 = f1*w-3.655412321999253963714E-7; - f1 = f1*w+1.464941733975961318456E-8; - f1 = f1*w+6.176407863710360207074E-10; - f2 = 1.000000000000000000000; - f2 = f2*w-2.298062239901678075778E-1; - f2 = f2*w+1.105077041474037862347E-1; - f2 = f2*w-1.566542966630792353556E-2; - f2 = f2*w+2.761106850817352773874E-3; - f2 = f2*w-2.089148012284048449115E-4; - f2 = f2*w+1.708528938807675304186E-5; - f2 = f2*w-4.459311796356686423199E-7; - f2 = f2*w+1.394634930353847498145E-8; - f2 = f2*w+6.150865933977338354138E-10; - f = f1/f2; - result = ae_exp(x, _state)*w*(1+w*f); - return result; - } - if( ae_fp_less(x,(double)(32)) ) - { - w = 1/x; - f1 = -2.458119367674020323359E-1; - f1 = f1*w-1.483382253322077687183E-1; - f1 = f1*w+7.248291795735551591813E-2; - f1 = f1*w-1.348315687380940523823E-2; - f1 = f1*w+1.342775069788636972294E-3; - f1 = f1*w-7.942465637159712264564E-5; - f1 = f1*w+2.644179518984235952241E-6; - f1 = f1*w-4.239473659313765177195E-8; - f2 = 1.000000000000000000000; - f2 = f2*w-1.044225908443871106315E-1; - f2 = f2*w-2.676453128101402655055E-1; - f2 = f2*w+9.695000254621984627876E-2; - f2 = f2*w-1.601745692712991078208E-2; - f2 = f2*w+1.496414899205908021882E-3; - f2 = f2*w-8.462452563778485013756E-5; - f2 = f2*w+2.728938403476726394024E-6; - f2 = f2*w-4.239462431819542051337E-8; - f = f1/f2; - result = ae_exp(x, _state)*w*(1+w*f); - return result; - } - if( ae_fp_less(x,(double)(64)) ) - { - w = 1/x; - f1 = 1.212561118105456670844E-1; - f1 = f1*w-5.823133179043894485122E-1; - f1 = f1*w+2.348887314557016779211E-1; - f1 = f1*w-3.040034318113248237280E-2; - f1 = f1*w+1.510082146865190661777E-3; - f1 = f1*w-2.523137095499571377122E-5; - f2 = 1.000000000000000000000; - f2 = f2*w-1.002252150365854016662; - f2 = f2*w+2.928709694872224144953E-1; - f2 = f2*w-3.337004338674007801307E-2; - f2 = f2*w+1.560544881127388842819E-3; - f2 = f2*w-2.523137093603234562648E-5; - f = f1/f2; - result = ae_exp(x, _state)*w*(1+w*f); - return result; - } - w = 1/x; - f1 = -7.657847078286127362028E-1; - f1 = f1*w+6.886192415566705051750E-1; - f1 = f1*w-2.132598113545206124553E-1; - f1 = f1*w+3.346107552384193813594E-2; - f1 = f1*w-3.076541477344756050249E-3; - f1 = f1*w+1.747119316454907477380E-4; - f1 = f1*w-6.103711682274170530369E-6; - f1 = f1*w+1.218032765428652199087E-7; - f1 = f1*w-1.086076102793290233007E-9; - f2 = 1.000000000000000000000; - f2 = f2*w-1.888802868662308731041; - f2 = f2*w+1.066691687211408896850; - f2 = f2*w-2.751915982306380647738E-1; - f2 = f2*w+3.930852688233823569726E-2; - f2 = f2*w-3.414684558602365085394E-3; - f2 = f2*w+1.866844370703555398195E-4; - f2 = f2*w-6.345146083130515357861E-6; - f2 = f2*w+1.239754287483206878024E-7; - f2 = f2*w-1.086076102793126632978E-9; - f = f1/f2; - result = ae_exp(x, _state)*w*(1+w*f); - return result; -} - - -/************************************************************************* -Exponential integral En(x) - -Evaluates the exponential integral - - inf. - - - | | -xt - | e - E (x) = | ---- dt. - n | n - | | t - - - 1 - - -Both n and x must be nonnegative. - -The routine employs either a power series, a continued -fraction, or an asymptotic formula depending on the -relative values of n and x. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0, 30 10000 1.7e-15 3.6e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1985, 2000 by Stephen L. Moshier -*************************************************************************/ -double exponentialintegralen(double x, ae_int_t n, ae_state *_state) -{ - double r; - double t; - double yk; - double xk; - double pk; - double pkm1; - double pkm2; - double qk; - double qkm1; - double qkm2; - double psi; - double z; - ae_int_t i; - ae_int_t k; - double big; - double eul; - double result; - - - eul = 0.57721566490153286060; - big = 1.44115188075855872*ae_pow((double)(10), (double)(17), _state); - if( ((n<0||ae_fp_less(x,(double)(0)))||ae_fp_greater(x,(double)(170)))||(ae_fp_eq(x,(double)(0))&&n<2) ) - { - result = (double)(-1); - return result; - } - if( ae_fp_eq(x,(double)(0)) ) - { - result = (double)1/(double)(n-1); - return result; - } - if( n==0 ) - { - result = ae_exp(-x, _state)/x; - return result; - } - if( n>5000 ) - { - xk = x+n; - yk = 1/(xk*xk); - t = (double)(n); - result = yk*t*(6*x*x-8*t*x+t*t); - result = yk*(result+t*(t-2.0*x)); - result = yk*(result+t); - result = (result+1)*ae_exp(-x, _state)/xk; - return result; - } - if( ae_fp_less_eq(x,(double)(1)) ) - { - psi = -eul-ae_log(x, _state); - for(i=1; i<=n-1; i++) - { - psi = psi+(double)1/(double)i; - } - z = -x; - xk = (double)(0); - yk = (double)(1); - pk = (double)(1-n); - if( n==1 ) - { - result = 0.0; - } - else - { - result = 1.0/pk; - } - do - { - xk = xk+1; - yk = yk*z/xk; - pk = pk+1; - if( ae_fp_neq(pk,(double)(0)) ) - { - result = result+yk/pk; - } - if( ae_fp_neq(result,(double)(0)) ) - { - t = ae_fabs(yk/result, _state); - } - else - { - t = (double)(1); - } - } - while(ae_fp_greater_eq(t,ae_machineepsilon)); - t = (double)(1); - for(i=1; i<=n-1; i++) - { - t = t*z/i; - } - result = psi*t-result; - return result; - } - else - { - k = 1; - pkm2 = (double)(1); - qkm2 = x; - pkm1 = 1.0; - qkm1 = x+n; - result = pkm1/qkm1; - do - { - k = k+1; - if( k%2==1 ) - { - yk = (double)(1); - xk = n+(double)(k-1)/(double)2; - } - else - { - yk = x; - xk = (double)k/(double)2; - } - pk = pkm1*yk+pkm2*xk; - qk = qkm1*yk+qkm2*xk; - if( ae_fp_neq(qk,(double)(0)) ) - { - r = pk/qk; - t = ae_fabs((result-r)/r, _state); - result = r; - } - else - { - t = (double)(1); - } - pkm2 = pkm1; - pkm1 = pk; - qkm2 = qkm1; - qkm1 = qk; - if( ae_fp_greater(ae_fabs(pk, _state),big) ) - { - pkm2 = pkm2/big; - pkm1 = pkm1/big; - qkm2 = qkm2/big; - qkm1 = qkm1/big; - } - } - while(ae_fp_greater_eq(t,ae_machineepsilon)); - result = result*ae_exp(-x, _state); - } - return result; -} - - -#endif -#if defined(AE_COMPILE_LAGUERRE) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Calculation of the value of the Laguerre polynomial. - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Laguerre polynomial Ln at x -*************************************************************************/ -double laguerrecalculate(ae_int_t n, double x, ae_state *_state) -{ - double a; - double b; - double i; - double result; - - - result = (double)(1); - a = (double)(1); - b = 1-x; - if( n==1 ) - { - result = b; - } - i = (double)(2); - while(ae_fp_less_eq(i,(double)(n))) - { - result = ((2*i-1-x)*b-(i-1)*a)/i; - a = b; - b = result; - i = i+1; - } - return result; -} - - -/************************************************************************* -Summation of Laguerre polynomials using Clenshaw's recurrence formula. - -This routine calculates c[0]*L0(x) + c[1]*L1(x) + ... + c[N]*LN(x) - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Laguerre polynomial at x -*************************************************************************/ -double laguerresum(/* Real */ ae_vector* c, - ae_int_t n, - double x, - ae_state *_state) -{ - double b1; - double b2; - ae_int_t i; - double result; - - - b1 = (double)(0); - b2 = (double)(0); - result = (double)(0); - for(i=n; i>=0; i--) - { - result = (2*i+1-x)*b1/(i+1)-(i+1)*b2/(i+2)+c->ptr.p_double[i]; - b2 = b1; - b1 = result; - } - return result; -} - - -/************************************************************************* -Representation of Ln as C[0] + C[1]*X + ... + C[N]*X^N - -Input parameters: - N - polynomial degree, n>=0 - -Output parameters: - C - coefficients -*************************************************************************/ -void laguerrecoefficients(ae_int_t n, - /* Real */ ae_vector* c, - ae_state *_state) -{ - ae_int_t i; - - ae_vector_clear(c); - - ae_vector_set_length(c, n+1, _state); - c->ptr.p_double[0] = (double)(1); - for(i=0; i<=n-1; i++) - { - c->ptr.p_double[i+1] = -c->ptr.p_double[i]*(n-i)/(i+1)/(i+1); - } -} - - -#endif -#if defined(AE_COMPILE_CHISQUAREDISTR) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Chi-square distribution - -Returns the area under the left hand tail (from 0 to x) -of the Chi square probability density function with -v degrees of freedom. - - - x - - - 1 | | v/2-1 -t/2 - P( x | v ) = ----------- | t e dt - v/2 - | | - 2 | (v/2) - - 0 - -where x is the Chi-square variable. - -The incomplete gamma integral is used, according to the -formula - -y = chdtr( v, x ) = igam( v/2.0, x/2.0 ). - -The arguments must both be positive. - -ACCURACY: - -See incomplete gamma function - - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double chisquaredistribution(double v, double x, ae_state *_state) -{ - double result; - - - ae_assert(ae_fp_greater_eq(x,(double)(0))&&ae_fp_greater_eq(v,(double)(1)), "Domain error in ChiSquareDistribution", _state); - result = incompletegamma(v/2.0, x/2.0, _state); - return result; -} - - -/************************************************************************* -Complemented Chi-square distribution - -Returns the area under the right hand tail (from x to -infinity) of the Chi square probability density function -with v degrees of freedom: - - inf. - - - 1 | | v/2-1 -t/2 - P( x | v ) = ----------- | t e dt - v/2 - | | - 2 | (v/2) - - x - -where x is the Chi-square variable. - -The incomplete gamma integral is used, according to the -formula - -y = chdtr( v, x ) = igamc( v/2.0, x/2.0 ). - -The arguments must both be positive. - -ACCURACY: - -See incomplete gamma function - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double chisquarecdistribution(double v, double x, ae_state *_state) -{ - double result; - - - ae_assert(ae_fp_greater_eq(x,(double)(0))&&ae_fp_greater_eq(v,(double)(1)), "Domain error in ChiSquareDistributionC", _state); - result = incompletegammac(v/2.0, x/2.0, _state); - return result; -} - - -/************************************************************************* -Inverse of complemented Chi-square distribution - -Finds the Chi-square argument x such that the integral -from x to infinity of the Chi-square density is equal -to the given cumulative probability y. - -This is accomplished using the inverse gamma integral -function and the relation - - x/2 = igami( df/2, y ); - -ACCURACY: - -See inverse incomplete gamma function - - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double invchisquaredistribution(double v, double y, ae_state *_state) -{ - double result; - - - ae_assert((ae_fp_greater_eq(y,(double)(0))&&ae_fp_less_eq(y,(double)(1)))&&ae_fp_greater_eq(v,(double)(1)), "Domain error in InvChiSquareDistribution", _state); - result = 2*invincompletegammac(0.5*v, y, _state); - return result; -} - - -#endif -#if defined(AE_COMPILE_LEGENDRE) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Calculation of the value of the Legendre polynomial Pn. - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Legendre polynomial Pn at x -*************************************************************************/ -double legendrecalculate(ae_int_t n, double x, ae_state *_state) -{ - double a; - double b; - ae_int_t i; - double result; - - - result = (double)(1); - a = (double)(1); - b = x; - if( n==0 ) - { - result = a; - return result; - } - if( n==1 ) - { - result = b; - return result; - } - for(i=2; i<=n; i++) - { - result = ((2*i-1)*x*b-(i-1)*a)/i; - a = b; - b = result; - } - return result; -} - - -/************************************************************************* -Summation of Legendre polynomials using Clenshaw's recurrence formula. - -This routine calculates - c[0]*P0(x) + c[1]*P1(x) + ... + c[N]*PN(x) - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Legendre polynomial at x -*************************************************************************/ -double legendresum(/* Real */ ae_vector* c, - ae_int_t n, - double x, - ae_state *_state) -{ - double b1; - double b2; - ae_int_t i; - double result; - - - b1 = (double)(0); - b2 = (double)(0); - result = (double)(0); - for(i=n; i>=0; i--) - { - result = (2*i+1)*x*b1/(i+1)-(i+1)*b2/(i+2)+c->ptr.p_double[i]; - b2 = b1; - b1 = result; - } - return result; -} - - -/************************************************************************* -Representation of Pn as C[0] + C[1]*X + ... + C[N]*X^N - -Input parameters: - N - polynomial degree, n>=0 - -Output parameters: - C - coefficients -*************************************************************************/ -void legendrecoefficients(ae_int_t n, - /* Real */ ae_vector* c, - ae_state *_state) -{ - ae_int_t i; - - ae_vector_clear(c); - - ae_vector_set_length(c, n+1, _state); - for(i=0; i<=n; i++) - { - c->ptr.p_double[i] = (double)(0); - } - c->ptr.p_double[n] = (double)(1); - for(i=1; i<=n; i++) - { - c->ptr.p_double[n] = c->ptr.p_double[n]*(n+i)/2/i; - } - for(i=0; i<=n/2-1; i++) - { - c->ptr.p_double[n-2*(i+1)] = -c->ptr.p_double[n-2*i]*(n-2*i)*(n-2*i-1)/2/(i+1)/(2*(n-i)-1); - } -} - - -#endif -#if defined(AE_COMPILE_BETAF) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Beta function - - - - - - | (a) | (b) -beta( a, b ) = -----------. - - - | (a+b) - -For large arguments the logarithm of the function is -evaluated using lgam(), then exponentiated. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,30 30000 8.1e-14 1.1e-14 - -Cephes Math Library Release 2.0: April, 1987 -Copyright 1984, 1987 by Stephen L. Moshier -*************************************************************************/ -double beta(double a, double b, ae_state *_state) -{ - double y; - double sg; - double s; - double result; - - - sg = (double)(1); - ae_assert(ae_fp_greater(a,(double)(0))||ae_fp_neq(a,(double)(ae_ifloor(a, _state))), "Overflow in Beta", _state); - ae_assert(ae_fp_greater(b,(double)(0))||ae_fp_neq(b,(double)(ae_ifloor(b, _state))), "Overflow in Beta", _state); - y = a+b; - if( ae_fp_greater(ae_fabs(y, _state),171.624376956302725) ) - { - y = lngamma(y, &s, _state); - sg = sg*s; - y = lngamma(b, &s, _state)-y; - sg = sg*s; - y = lngamma(a, &s, _state)+y; - sg = sg*s; - ae_assert(ae_fp_less_eq(y,ae_log(ae_maxrealnumber, _state)), "Overflow in Beta", _state); - result = sg*ae_exp(y, _state); - return result; - } - y = gammafunction(y, _state); - ae_assert(ae_fp_neq(y,(double)(0)), "Overflow in Beta", _state); - if( ae_fp_greater(a,b) ) - { - y = gammafunction(a, _state)/y; - y = y*gammafunction(b, _state); - } - else - { - y = gammafunction(b, _state)/y; - y = y*gammafunction(a, _state); - } - result = y; - return result; -} - - -#endif -#if defined(AE_COMPILE_CHEBYSHEV) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Calculation of the value of the Chebyshev polynomials of the -first and second kinds. - -Parameters: - r - polynomial kind, either 1 or 2. - n - degree, n>=0 - x - argument, -1 <= x <= 1 - -Result: - the value of the Chebyshev polynomial at x -*************************************************************************/ -double chebyshevcalculate(ae_int_t r, - ae_int_t n, - double x, - ae_state *_state) -{ - ae_int_t i; - double a; - double b; - double result; - - - result = (double)(0); - - /* - * Prepare A and B - */ - if( r==1 ) - { - a = (double)(1); - b = x; - } - else - { - a = (double)(1); - b = 2*x; - } - - /* - * Special cases: N=0 or N=1 - */ - if( n==0 ) - { - result = a; - return result; - } - if( n==1 ) - { - result = b; - return result; - } - - /* - * General case: N>=2 - */ - for(i=2; i<=n; i++) - { - result = 2*x*b-a; - a = b; - b = result; - } - return result; -} - - -/************************************************************************* -Summation of Chebyshev polynomials using Clenshaw's recurrence formula. - -This routine calculates - c[0]*T0(x) + c[1]*T1(x) + ... + c[N]*TN(x) -or - c[0]*U0(x) + c[1]*U1(x) + ... + c[N]*UN(x) -depending on the R. - -Parameters: - r - polynomial kind, either 1 or 2. - n - degree, n>=0 - x - argument - -Result: - the value of the Chebyshev polynomial at x -*************************************************************************/ -double chebyshevsum(/* Real */ ae_vector* c, - ae_int_t r, - ae_int_t n, - double x, - ae_state *_state) -{ - double b1; - double b2; - ae_int_t i; - double result; - - - b1 = (double)(0); - b2 = (double)(0); - for(i=n; i>=1; i--) - { - result = 2*x*b1-b2+c->ptr.p_double[i]; - b2 = b1; - b1 = result; - } - if( r==1 ) - { - result = -b2+x*b1+c->ptr.p_double[0]; - } - else - { - result = -b2+2*x*b1+c->ptr.p_double[0]; - } - return result; -} - - -/************************************************************************* -Representation of Tn as C[0] + C[1]*X + ... + C[N]*X^N - -Input parameters: - N - polynomial degree, n>=0 - -Output parameters: - C - coefficients -*************************************************************************/ -void chebyshevcoefficients(ae_int_t n, - /* Real */ ae_vector* c, - ae_state *_state) -{ - ae_int_t i; - - ae_vector_clear(c); - - ae_vector_set_length(c, n+1, _state); - for(i=0; i<=n; i++) - { - c->ptr.p_double[i] = (double)(0); - } - if( n==0||n==1 ) - { - c->ptr.p_double[n] = (double)(1); - } - else - { - c->ptr.p_double[n] = ae_exp((n-1)*ae_log((double)(2), _state), _state); - for(i=0; i<=n/2-1; i++) - { - c->ptr.p_double[n-2*(i+1)] = -c->ptr.p_double[n-2*i]*(n-2*i)*(n-2*i-1)/4/(i+1)/(n-i-1); - } - } -} - - -/************************************************************************* -Conversion of a series of Chebyshev polynomials to a power series. - -Represents A[0]*T0(x) + A[1]*T1(x) + ... + A[N]*Tn(x) as -B[0] + B[1]*X + ... + B[N]*X^N. - -Input parameters: - A - Chebyshev series coefficients - N - degree, N>=0 - -Output parameters - B - power series coefficients -*************************************************************************/ -void fromchebyshev(/* Real */ ae_vector* a, - ae_int_t n, - /* Real */ ae_vector* b, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - double e; - double d; - - ae_vector_clear(b); - - ae_vector_set_length(b, n+1, _state); - for(i=0; i<=n; i++) - { - b->ptr.p_double[i] = (double)(0); - } - d = (double)(0); - i = 0; - do - { - k = i; - do - { - e = b->ptr.p_double[k]; - b->ptr.p_double[k] = (double)(0); - if( i<=1&&k==i ) - { - b->ptr.p_double[k] = (double)(1); - } - else - { - if( i!=0 ) - { - b->ptr.p_double[k] = 2*d; - } - if( k>i+1 ) - { - b->ptr.p_double[k] = b->ptr.p_double[k]-b->ptr.p_double[k-2]; - } - } - d = e; - k = k+1; - } - while(k<=n); - d = b->ptr.p_double[i]; - e = (double)(0); - k = i; - while(k<=n) - { - e = e+b->ptr.p_double[k]*a->ptr.p_double[k]; - k = k+2; - } - b->ptr.p_double[i] = e; - i = i+1; - } - while(i<=n); -} - - -#endif -#if defined(AE_COMPILE_STUDENTTDISTR) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Student's t distribution - -Computes the integral from minus infinity to t of the Student -t distribution with integer k > 0 degrees of freedom: - - t - - - | | - - | 2 -(k+1)/2 - | ( (k+1)/2 ) | ( x ) - ---------------------- | ( 1 + --- ) dx - - | ( k ) - sqrt( k pi ) | ( k/2 ) | - | | - - - -inf. - -Relation to incomplete beta integral: - - 1 - stdtr(k,t) = 0.5 * incbet( k/2, 1/2, z ) -where - z = k/(k + t**2). - -For t < -2, this is the method of computation. For higher t, -a direct method is derived from integration by parts. -Since the function is symmetric about t=0, the area under the -right tail of the density is found by calling the function -with -t instead of t. - -ACCURACY: - -Tested at random 1 <= k <= 25. The "domain" refers to t. - Relative error: -arithmetic domain # trials peak rms - IEEE -100,-2 50000 5.9e-15 1.4e-15 - IEEE -2,100 500000 2.7e-15 4.9e-17 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double studenttdistribution(ae_int_t k, double t, ae_state *_state) -{ - double x; - double rk; - double z; - double f; - double tz; - double p; - double xsqk; - ae_int_t j; - double result; - - - ae_assert(k>0, "Domain error in StudentTDistribution", _state); - if( ae_fp_eq(t,(double)(0)) ) - { - result = 0.5; - return result; - } - if( ae_fp_less(t,-2.0) ) - { - rk = (double)(k); - z = rk/(rk+t*t); - result = 0.5*incompletebeta(0.5*rk, 0.5, z, _state); - return result; - } - if( ae_fp_less(t,(double)(0)) ) - { - x = -t; - } - else - { - x = t; - } - rk = (double)(k); - z = 1.0+x*x/rk; - if( k%2!=0 ) - { - xsqk = x/ae_sqrt(rk, _state); - p = ae_atan(xsqk, _state); - if( k>1 ) - { - f = 1.0; - tz = 1.0; - j = 3; - while(j<=k-2&&ae_fp_greater(tz/f,ae_machineepsilon)) - { - tz = tz*((j-1)/(z*j)); - f = f+tz; - j = j+2; - } - p = p+f*xsqk/z; - } - p = p*2.0/ae_pi; - } - else - { - f = 1.0; - tz = 1.0; - j = 2; - while(j<=k-2&&ae_fp_greater(tz/f,ae_machineepsilon)) - { - tz = tz*((j-1)/(z*j)); - f = f+tz; - j = j+2; - } - p = f*x/ae_sqrt(z*rk, _state); - } - if( ae_fp_less(t,(double)(0)) ) - { - p = -p; - } - result = 0.5+0.5*p; - return result; -} - - -/************************************************************************* -Functional inverse of Student's t distribution - -Given probability p, finds the argument t such that stdtr(k,t) -is equal to p. - -ACCURACY: - -Tested at random 1 <= k <= 100. The "domain" refers to p: - Relative error: -arithmetic domain # trials peak rms - IEEE .001,.999 25000 5.7e-15 8.0e-16 - IEEE 10^-6,.001 25000 2.0e-12 2.9e-14 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double invstudenttdistribution(ae_int_t k, double p, ae_state *_state) -{ - double t; - double rk; - double z; - ae_int_t rflg; - double result; - - - ae_assert((k>0&&ae_fp_greater(p,(double)(0)))&&ae_fp_less(p,(double)(1)), "Domain error in InvStudentTDistribution", _state); - rk = (double)(k); - if( ae_fp_greater(p,0.25)&&ae_fp_less(p,0.75) ) - { - if( ae_fp_eq(p,0.5) ) - { - result = (double)(0); - return result; - } - z = 1.0-2.0*p; - z = invincompletebeta(0.5, 0.5*rk, ae_fabs(z, _state), _state); - t = ae_sqrt(rk*z/(1.0-z), _state); - if( ae_fp_less(p,0.5) ) - { - t = -t; - } - result = t; - return result; - } - rflg = -1; - if( ae_fp_greater_eq(p,0.5) ) - { - p = 1.0-p; - rflg = 1; - } - z = invincompletebeta(0.5*rk, 0.5, 2.0*p, _state); - if( ae_fp_less(ae_maxrealnumber*z,rk) ) - { - result = rflg*ae_maxrealnumber; - return result; - } - t = ae_sqrt(rk/z-rk, _state); - result = rflg*t; - return result; -} - - -#endif -#if defined(AE_COMPILE_BINOMIALDISTR) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Binomial distribution - -Returns the sum of the terms 0 through k of the Binomial -probability density: - - k - -- ( n ) j n-j - > ( ) p (1-p) - -- ( j ) - j=0 - -The terms are not summed directly; instead the incomplete -beta integral is employed, according to the formula - -y = bdtr( k, n, p ) = incbet( n-k, k+1, 1-p ). - -The arguments must be positive, with p ranging from 0 to 1. - -ACCURACY: - -Tested at random points (a,b,p), with p between 0 and 1. - - a,b Relative error: -arithmetic domain # trials peak rms - For p between 0.001 and 1: - IEEE 0,100 100000 4.3e-15 2.6e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double binomialdistribution(ae_int_t k, - ae_int_t n, - double p, - ae_state *_state) -{ - double dk; - double dn; - double result; - - - ae_assert(ae_fp_greater_eq(p,(double)(0))&&ae_fp_less_eq(p,(double)(1)), "Domain error in BinomialDistribution", _state); - ae_assert(k>=-1&&k<=n, "Domain error in BinomialDistribution", _state); - if( k==-1 ) - { - result = (double)(0); - return result; - } - if( k==n ) - { - result = (double)(1); - return result; - } - dn = (double)(n-k); - if( k==0 ) - { - dk = ae_pow(1.0-p, dn, _state); - } - else - { - dk = (double)(k+1); - dk = incompletebeta(dn, dk, 1.0-p, _state); - } - result = dk; - return result; -} - - -/************************************************************************* -Complemented binomial distribution - -Returns the sum of the terms k+1 through n of the Binomial -probability density: - - n - -- ( n ) j n-j - > ( ) p (1-p) - -- ( j ) - j=k+1 - -The terms are not summed directly; instead the incomplete -beta integral is employed, according to the formula - -y = bdtrc( k, n, p ) = incbet( k+1, n-k, p ). - -The arguments must be positive, with p ranging from 0 to 1. - -ACCURACY: - -Tested at random points (a,b,p). - - a,b Relative error: -arithmetic domain # trials peak rms - For p between 0.001 and 1: - IEEE 0,100 100000 6.7e-15 8.2e-16 - For p between 0 and .001: - IEEE 0,100 100000 1.5e-13 2.7e-15 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double binomialcdistribution(ae_int_t k, - ae_int_t n, - double p, - ae_state *_state) -{ - double dk; - double dn; - double result; - - - ae_assert(ae_fp_greater_eq(p,(double)(0))&&ae_fp_less_eq(p,(double)(1)), "Domain error in BinomialDistributionC", _state); - ae_assert(k>=-1&&k<=n, "Domain error in BinomialDistributionC", _state); - if( k==-1 ) - { - result = (double)(1); - return result; - } - if( k==n ) - { - result = (double)(0); - return result; - } - dn = (double)(n-k); - if( k==0 ) - { - if( ae_fp_less(p,0.01) ) - { - dk = -nuexpm1(dn*nulog1p(-p, _state), _state); - } - else - { - dk = 1.0-ae_pow(1.0-p, dn, _state); - } - } - else - { - dk = (double)(k+1); - dk = incompletebeta(dk, dn, p, _state); - } - result = dk; - return result; -} - - -/************************************************************************* -Inverse binomial distribution - -Finds the event probability p such that the sum of the -terms 0 through k of the Binomial probability density -is equal to the given cumulative probability y. - -This is accomplished using the inverse beta integral -function and the relation - -1 - p = incbi( n-k, k+1, y ). - -ACCURACY: - -Tested at random points (a,b,p). - - a,b Relative error: -arithmetic domain # trials peak rms - For p between 0.001 and 1: - IEEE 0,100 100000 2.3e-14 6.4e-16 - IEEE 0,10000 100000 6.6e-12 1.2e-13 - For p between 10^-6 and 0.001: - IEEE 0,100 100000 2.0e-12 1.3e-14 - IEEE 0,10000 100000 1.5e-12 3.2e-14 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double invbinomialdistribution(ae_int_t k, - ae_int_t n, - double y, - ae_state *_state) -{ - double dk; - double dn; - double p; - double result; - - - ae_assert(k>=0&&k 1, except * denotes relative error criterion. -For large negative x, the absolute error increases as x^1.5. -For large positive x, the relative error increases as x^1.5. - -Arithmetic domain function # trials peak rms -IEEE -10, 0 Ai 10000 1.6e-15 2.7e-16 -IEEE 0, 10 Ai 10000 2.3e-14* 1.8e-15* -IEEE -10, 0 Ai' 10000 4.6e-15 7.6e-16 -IEEE 0, 10 Ai' 10000 1.8e-14* 1.5e-15* -IEEE -10, 10 Bi 30000 4.2e-15 5.3e-16 -IEEE -10, 10 Bi' 30000 4.9e-15 7.3e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -void airy(double x, - double* ai, - double* aip, - double* bi, - double* bip, - ae_state *_state) -{ - double z; - double zz; - double t; - double f; - double g; - double uf; - double ug; - double k; - double zeta; - double theta; - ae_int_t domflg; - double c1; - double c2; - double sqrt3; - double sqpii; - double afn; - double afd; - double agn; - double agd; - double apfn; - double apfd; - double apgn; - double apgd; - double an; - double ad; - double apn; - double apd; - double bn16; - double bd16; - double bppn; - double bppd; - - *ai = 0; - *aip = 0; - *bi = 0; - *bip = 0; - - sqpii = 5.64189583547756286948E-1; - c1 = 0.35502805388781723926; - c2 = 0.258819403792806798405; - sqrt3 = 1.732050807568877293527; - domflg = 0; - if( ae_fp_greater(x,25.77) ) - { - *ai = (double)(0); - *aip = (double)(0); - *bi = ae_maxrealnumber; - *bip = ae_maxrealnumber; - return; - } - if( ae_fp_less(x,-2.09) ) - { - domflg = 15; - t = ae_sqrt(-x, _state); - zeta = -2.0*x*t/3.0; - t = ae_sqrt(t, _state); - k = sqpii/t; - z = 1.0/zeta; - zz = z*z; - afn = -1.31696323418331795333E-1; - afn = afn*zz-6.26456544431912369773E-1; - afn = afn*zz-6.93158036036933542233E-1; - afn = afn*zz-2.79779981545119124951E-1; - afn = afn*zz-4.91900132609500318020E-2; - afn = afn*zz-4.06265923594885404393E-3; - afn = afn*zz-1.59276496239262096340E-4; - afn = afn*zz-2.77649108155232920844E-6; - afn = afn*zz-1.67787698489114633780E-8; - afd = 1.00000000000000000000E0; - afd = afd*zz+1.33560420706553243746E1; - afd = afd*zz+3.26825032795224613948E1; - afd = afd*zz+2.67367040941499554804E1; - afd = afd*zz+9.18707402907259625840E0; - afd = afd*zz+1.47529146771666414581E0; - afd = afd*zz+1.15687173795188044134E-1; - afd = afd*zz+4.40291641615211203805E-3; - afd = afd*zz+7.54720348287414296618E-5; - afd = afd*zz+4.51850092970580378464E-7; - uf = 1.0+zz*afn/afd; - agn = 1.97339932091685679179E-2; - agn = agn*zz+3.91103029615688277255E-1; - agn = agn*zz+1.06579897599595591108E0; - agn = agn*zz+9.39169229816650230044E-1; - agn = agn*zz+3.51465656105547619242E-1; - agn = agn*zz+6.33888919628925490927E-2; - agn = agn*zz+5.85804113048388458567E-3; - agn = agn*zz+2.82851600836737019778E-4; - agn = agn*zz+6.98793669997260967291E-6; - agn = agn*zz+8.11789239554389293311E-8; - agn = agn*zz+3.41551784765923618484E-10; - agd = 1.00000000000000000000E0; - agd = agd*zz+9.30892908077441974853E0; - agd = agd*zz+1.98352928718312140417E1; - agd = agd*zz+1.55646628932864612953E1; - agd = agd*zz+5.47686069422975497931E0; - agd = agd*zz+9.54293611618961883998E-1; - agd = agd*zz+8.64580826352392193095E-2; - agd = agd*zz+4.12656523824222607191E-3; - agd = agd*zz+1.01259085116509135510E-4; - agd = agd*zz+1.17166733214413521882E-6; - agd = agd*zz+4.91834570062930015649E-9; - ug = z*agn/agd; - theta = zeta+0.25*ae_pi; - f = ae_sin(theta, _state); - g = ae_cos(theta, _state); - *ai = k*(f*uf-g*ug); - *bi = k*(g*uf+f*ug); - apfn = 1.85365624022535566142E-1; - apfn = apfn*zz+8.86712188052584095637E-1; - apfn = apfn*zz+9.87391981747398547272E-1; - apfn = apfn*zz+4.01241082318003734092E-1; - apfn = apfn*zz+7.10304926289631174579E-2; - apfn = apfn*zz+5.90618657995661810071E-3; - apfn = apfn*zz+2.33051409401776799569E-4; - apfn = apfn*zz+4.08718778289035454598E-6; - apfn = apfn*zz+2.48379932900442457853E-8; - apfd = 1.00000000000000000000E0; - apfd = apfd*zz+1.47345854687502542552E1; - apfd = apfd*zz+3.75423933435489594466E1; - apfd = apfd*zz+3.14657751203046424330E1; - apfd = apfd*zz+1.09969125207298778536E1; - apfd = apfd*zz+1.78885054766999417817E0; - apfd = apfd*zz+1.41733275753662636873E-1; - apfd = apfd*zz+5.44066067017226003627E-3; - apfd = apfd*zz+9.39421290654511171663E-5; - apfd = apfd*zz+5.65978713036027009243E-7; - uf = 1.0+zz*apfn/apfd; - apgn = -3.55615429033082288335E-2; - apgn = apgn*zz-6.37311518129435504426E-1; - apgn = apgn*zz-1.70856738884312371053E0; - apgn = apgn*zz-1.50221872117316635393E0; - apgn = apgn*zz-5.63606665822102676611E-1; - apgn = apgn*zz-1.02101031120216891789E-1; - apgn = apgn*zz-9.48396695961445269093E-3; - apgn = apgn*zz-4.60325307486780994357E-4; - apgn = apgn*zz-1.14300836484517375919E-5; - apgn = apgn*zz-1.33415518685547420648E-7; - apgn = apgn*zz-5.63803833958893494476E-10; - apgd = 1.00000000000000000000E0; - apgd = apgd*zz+9.85865801696130355144E0; - apgd = apgd*zz+2.16401867356585941885E1; - apgd = apgd*zz+1.73130776389749389525E1; - apgd = apgd*zz+6.17872175280828766327E0; - apgd = apgd*zz+1.08848694396321495475E0; - apgd = apgd*zz+9.95005543440888479402E-2; - apgd = apgd*zz+4.78468199683886610842E-3; - apgd = apgd*zz+1.18159633322838625562E-4; - apgd = apgd*zz+1.37480673554219441465E-6; - apgd = apgd*zz+5.79912514929147598821E-9; - ug = z*apgn/apgd; - k = sqpii*t; - *aip = -k*(g*uf+f*ug); - *bip = k*(f*uf-g*ug); - return; - } - if( ae_fp_greater_eq(x,2.09) ) - { - domflg = 5; - t = ae_sqrt(x, _state); - zeta = 2.0*x*t/3.0; - g = ae_exp(zeta, _state); - t = ae_sqrt(t, _state); - k = 2.0*t*g; - z = 1.0/zeta; - an = 3.46538101525629032477E-1; - an = an*z+1.20075952739645805542E1; - an = an*z+7.62796053615234516538E1; - an = an*z+1.68089224934630576269E2; - an = an*z+1.59756391350164413639E2; - an = an*z+7.05360906840444183113E1; - an = an*z+1.40264691163389668864E1; - an = an*z+9.99999999999999995305E-1; - ad = 5.67594532638770212846E-1; - ad = ad*z+1.47562562584847203173E1; - ad = ad*z+8.45138970141474626562E1; - ad = ad*z+1.77318088145400459522E2; - ad = ad*z+1.64234692871529701831E2; - ad = ad*z+7.14778400825575695274E1; - ad = ad*z+1.40959135607834029598E1; - ad = ad*z+1.00000000000000000470E0; - f = an/ad; - *ai = sqpii*f/k; - k = -0.5*sqpii*t/g; - apn = 6.13759184814035759225E-1; - apn = apn*z+1.47454670787755323881E1; - apn = apn*z+8.20584123476060982430E1; - apn = apn*z+1.71184781360976385540E2; - apn = apn*z+1.59317847137141783523E2; - apn = apn*z+6.99778599330103016170E1; - apn = apn*z+1.39470856980481566958E1; - apn = apn*z+1.00000000000000000550E0; - apd = 3.34203677749736953049E-1; - apd = apd*z+1.11810297306158156705E1; - apd = apd*z+7.11727352147859965283E1; - apd = apd*z+1.58778084372838313640E2; - apd = apd*z+1.53206427475809220834E2; - apd = apd*z+6.86752304592780337944E1; - apd = apd*z+1.38498634758259442477E1; - apd = apd*z+9.99999999999999994502E-1; - f = apn/apd; - *aip = f*k; - if( ae_fp_greater(x,8.3203353) ) - { - bn16 = -2.53240795869364152689E-1; - bn16 = bn16*z+5.75285167332467384228E-1; - bn16 = bn16*z-3.29907036873225371650E-1; - bn16 = bn16*z+6.44404068948199951727E-2; - bn16 = bn16*z-3.82519546641336734394E-3; - bd16 = 1.00000000000000000000E0; - bd16 = bd16*z-7.15685095054035237902E0; - bd16 = bd16*z+1.06039580715664694291E1; - bd16 = bd16*z-5.23246636471251500874E0; - bd16 = bd16*z+9.57395864378383833152E-1; - bd16 = bd16*z-5.50828147163549611107E-2; - f = z*bn16/bd16; - k = sqpii*g; - *bi = k*(1.0+f)/t; - bppn = 4.65461162774651610328E-1; - bppn = bppn*z-1.08992173800493920734E0; - bppn = bppn*z+6.38800117371827987759E-1; - bppn = bppn*z-1.26844349553102907034E-1; - bppn = bppn*z+7.62487844342109852105E-3; - bppd = 1.00000000000000000000E0; - bppd = bppd*z-8.70622787633159124240E0; - bppd = bppd*z+1.38993162704553213172E1; - bppd = bppd*z-7.14116144616431159572E0; - bppd = bppd*z+1.34008595960680518666E0; - bppd = bppd*z-7.84273211323341930448E-2; - f = z*bppn/bppd; - *bip = k*t*(1.0+f); - return; - } - } - f = 1.0; - g = x; - t = 1.0; - uf = 1.0; - ug = x; - k = 1.0; - z = x*x*x; - while(ae_fp_greater(t,ae_machineepsilon)) - { - uf = uf*z; - k = k+1.0; - uf = uf/k; - ug = ug*z; - k = k+1.0; - ug = ug/k; - uf = uf/k; - f = f+uf; - k = k+1.0; - ug = ug/k; - g = g+ug; - t = ae_fabs(uf/f, _state); - } - uf = c1*f; - ug = c2*g; - if( domflg%2==0 ) - { - *ai = uf-ug; - } - if( domflg/2%2==0 ) - { - *bi = sqrt3*(uf+ug); - } - k = 4.0; - uf = x*x/2.0; - ug = z/3.0; - f = uf; - g = 1.0+ug; - uf = uf/3.0; - t = 1.0; - while(ae_fp_greater(t,ae_machineepsilon)) - { - uf = uf*z; - ug = ug/k; - k = k+1.0; - ug = ug*z; - uf = uf/k; - f = f+uf; - k = k+1.0; - ug = ug/k; - uf = uf/k; - g = g+ug; - k = k+1.0; - t = ae_fabs(ug/g, _state); - } - uf = c1*f; - ug = c2*g; - if( domflg/4%2==0 ) - { - *aip = uf-ug; - } - if( domflg/8%2==0 ) - { - *bip = sqrt3*(uf+ug); - } -} - - -#endif - -} - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/specialfunctions.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/specialfunctions.h deleted file mode 100644 index e23788e..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/specialfunctions.h +++ /dev/null @@ -1,2305 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifndef _specialfunctions_pkg_h -#define _specialfunctions_pkg_h -#include "ap.h" -#include "alglibinternal.h" -#include "alglibmisc.h" - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (DATATYPES) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_GAMMAFUNC) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_NORMALDISTR) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_IGAMMAF) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_ELLIPTIC) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_HERMITE) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_DAWSON) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_TRIGINTEGRALS) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_POISSONDISTR) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_BESSEL) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_IBETAF) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_FDISTR) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_FRESNEL) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_JACOBIANELLIPTIC) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_PSIF) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_EXPINTEGRALS) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_LAGUERRE) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_CHISQUAREDISTR) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_LEGENDRE) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_BETAF) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_CHEBYSHEV) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_STUDENTTDISTR) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_BINOMIALDISTR) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_AIRYF) || !defined(AE_PARTIAL_BUILD) -#endif - -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_GAMMAFUNC) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_NORMALDISTR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_IGAMMAF) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_ELLIPTIC) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_HERMITE) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_DAWSON) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_TRIGINTEGRALS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_POISSONDISTR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_BESSEL) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_IBETAF) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_FDISTR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_FRESNEL) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_JACOBIANELLIPTIC) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_PSIF) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_EXPINTEGRALS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_LAGUERRE) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_CHISQUAREDISTR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_LEGENDRE) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_BETAF) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_CHEBYSHEV) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_STUDENTTDISTR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_BINOMIALDISTR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_AIRYF) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_GAMMAFUNC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Gamma function - -Input parameters: - X - argument - -Domain: - 0 < X < 171.6 - -170 < X < 0, X is not an integer. - -Relative error: - arithmetic domain # trials peak rms - IEEE -170,-33 20000 2.3e-15 3.3e-16 - IEEE -33, 33 20000 9.4e-16 2.2e-16 - IEEE 33, 171.6 20000 2.3e-15 3.2e-16 - -Cephes Math Library Release 2.8: June, 2000 -Original copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier -Translated to AlgoPascal by Bochkanov Sergey (2005, 2006, 2007). -*************************************************************************/ -double gammafunction(const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Natural logarithm of gamma function - -Input parameters: - X - argument - -Result: - logarithm of the absolute value of the Gamma(X). - -Output parameters: - SgnGam - sign(Gamma(X)) - -Domain: - 0 < X < 2.55e305 - -2.55e305 < X < 0, X is not an integer. - -ACCURACY: -arithmetic domain # trials peak rms - IEEE 0, 3 28000 5.4e-16 1.1e-16 - IEEE 2.718, 2.556e305 40000 3.5e-16 8.3e-17 -The error criterion was relative when the function magnitude -was greater than one but absolute when it was less than one. - -The following test used the relative error criterion, though -at certain points the relative error could be much higher than -indicated. - IEEE -200, -4 10000 4.8e-16 1.3e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier -Translated to AlgoPascal by Bochkanov Sergey (2005, 2006, 2007). -*************************************************************************/ -double lngamma(const double x, double &sgngam, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_NORMALDISTR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Error function - -The integral is - - x - - - 2 | | 2 - erf(x) = -------- | exp( - t ) dt. - sqrt(pi) | | - - - 0 - -For 0 <= |x| < 1, erf(x) = x * P4(x**2)/Q5(x**2); otherwise -erf(x) = 1 - erfc(x). - - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,1 30000 3.7e-16 1.0e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double errorfunction(const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Complementary error function - - 1 - erf(x) = - - inf. - - - 2 | | 2 - erfc(x) = -------- | exp( - t ) dt - sqrt(pi) | | - - - x - - -For small x, erfc(x) = 1 - erf(x); otherwise rational -approximations are computed. - - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,26.6417 30000 5.7e-14 1.5e-14 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double errorfunctionc(const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Same as normalcdf(), obsolete name. -*************************************************************************/ -double normaldistribution(const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Normal distribution PDF - -Returns Gaussian probability density function: - - 1 - f(x) = --------- * exp(-x^2/2) - sqrt(2pi) - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double normalpdf(const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Normal distribution CDF - -Returns the area under the Gaussian probability density -function, integrated from minus infinity to x: - - x - - - 1 | | 2 - ndtr(x) = --------- | exp( - t /2 ) dt - sqrt(2pi) | | - - - -inf. - - = ( 1 + erf(z) ) / 2 - = erfc(z) / 2 - -where z = x/sqrt(2). Computation is via the functions -erf and erfc. - - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE -13,0 30000 3.4e-14 6.7e-15 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double normalcdf(const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Inverse of the error function - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double inverf(const double e, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Same as invnormalcdf(), deprecated name -*************************************************************************/ -double invnormaldistribution(const double y0, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Inverse of Normal CDF - -Returns the argument, x, for which the area under the -Gaussian probability density function (integrated from -minus infinity to x) is equal to y. - - -For small arguments 0 < y < exp(-2), the program computes -z = sqrt( -2.0 * log(y) ); then the approximation is -x = z - log(z)/z - (1/z) P(1/z) / Q(1/z). -There are two rational functions P/Q, one for 0 < y < exp(-32) -and the other for y up to exp(-2). For larger arguments, -w = y - 0.5, and x/sqrt(2pi) = w + w**3 R(w**2)/S(w**2)). - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0.125, 1 20000 7.2e-16 1.3e-16 - IEEE 3e-308, 0.135 50000 4.6e-16 9.8e-17 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double invnormalcdf(const double y0, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Bivariate normal PDF - -Returns probability density function of the bivariate Gaussian with -correlation parameter equal to Rho: - - 1 ( x^2 - 2*rho*x*y + y^2 ) - f(x,y,rho) = ----------------- * exp( - ----------------------- ) - 2pi*sqrt(1-rho^2) ( 2*(1-rho^2) ) - - -with -1=0 - x - argument - -Result: - the value of the Hermite polynomial Hn at x -*************************************************************************/ -double hermitecalculate(const ae_int_t n, const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Summation of Hermite polynomials using Clenshaw's recurrence formula. - -This routine calculates - c[0]*H0(x) + c[1]*H1(x) + ... + c[N]*HN(x) - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Hermite polynomial at x -*************************************************************************/ -double hermitesum(const real_1d_array &c, const ae_int_t n, const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Representation of Hn as C[0] + C[1]*X + ... + C[N]*X^N - -Input parameters: - N - polynomial degree, n>=0 - -Output parameters: - C - coefficients -*************************************************************************/ -void hermitecoefficients(const ae_int_t n, real_1d_array &c, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_DAWSON) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Dawson's Integral - -Approximates the integral - - x - - - 2 | | 2 - dawsn(x) = exp( -x ) | exp( t ) dt - | | - - - 0 - -Three different rational approximations are employed, for -the intervals 0 to 3.25; 3.25 to 6.25; and 6.25 up. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,10 10000 6.9e-16 1.0e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -double dawsonintegral(const double x, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_TRIGINTEGRALS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Sine and cosine integrals - -Evaluates the integrals - - x - - - | cos t - 1 - Ci(x) = eul + ln x + | --------- dt, - | t - - - 0 - x - - - | sin t - Si(x) = | ----- dt - | t - - - 0 - -where eul = 0.57721566490153286061 is Euler's constant. -The integrals are approximated by rational functions. -For x > 8 auxiliary functions f(x) and g(x) are employed -such that - -Ci(x) = f(x) sin(x) - g(x) cos(x) -Si(x) = pi/2 - f(x) cos(x) - g(x) sin(x) - - -ACCURACY: - Test interval = [0,50]. -Absolute error, except relative when > 1: -arithmetic function # trials peak rms - IEEE Si 30000 4.4e-16 7.3e-17 - IEEE Ci 30000 6.9e-16 5.1e-17 - -Cephes Math Library Release 2.1: January, 1989 -Copyright 1984, 1987, 1989 by Stephen L. Moshier -*************************************************************************/ -void sinecosineintegrals(const double x, double &si, double &ci, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Hyperbolic sine and cosine integrals - -Approximates the integrals - - x - - - | | cosh t - 1 - Chi(x) = eul + ln x + | ----------- dt, - | | t - - - 0 - - x - - - | | sinh t - Shi(x) = | ------ dt - | | t - - - 0 - -where eul = 0.57721566490153286061 is Euler's constant. -The integrals are evaluated by power series for x < 8 -and by Chebyshev expansions for x between 8 and 88. -For large x, both functions approach exp(x)/2x. -Arguments greater than 88 in magnitude return MAXNUM. - - -ACCURACY: - -Test interval 0 to 88. - Relative error: -arithmetic function # trials peak rms - IEEE Shi 30000 6.9e-16 1.6e-16 - Absolute error, except relative when |Chi| > 1: - IEEE Chi 30000 8.4e-16 1.4e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -void hyperbolicsinecosineintegrals(const double x, double &shi, double &chi, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_POISSONDISTR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Poisson distribution - -Returns the sum of the first k+1 terms of the Poisson -distribution: - - k j - -- -m m - > e -- - -- j! - j=0 - -The terms are not summed directly; instead the incomplete -gamma integral is employed, according to the relation - -y = pdtr( k, m ) = igamc( k+1, m ). - -The arguments must both be positive. -ACCURACY: - -See incomplete gamma function - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double poissondistribution(const ae_int_t k, const double m, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Complemented Poisson distribution - -Returns the sum of the terms k+1 to infinity of the Poisson -distribution: - - inf. j - -- -m m - > e -- - -- j! - j=k+1 - -The terms are not summed directly; instead the incomplete -gamma integral is employed, according to the formula - -y = pdtrc( k, m ) = igam( k+1, m ). - -The arguments must both be positive. - -ACCURACY: - -See incomplete gamma function - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double poissoncdistribution(const ae_int_t k, const double m, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Inverse Poisson distribution - -Finds the Poisson variable x such that the integral -from 0 to x of the Poisson density is equal to the -given probability y. - -This is accomplished using the inverse gamma integral -function and the relation - - m = igami( k+1, y ). - -ACCURACY: - -See inverse incomplete gamma function - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double invpoissondistribution(const ae_int_t k, const double y, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_BESSEL) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Bessel function of order zero - -Returns Bessel function of order zero of the argument. - -The domain is divided into the intervals [0, 5] and -(5, infinity). In the first interval the following rational -approximation is used: - - - 2 2 -(w - r ) (w - r ) P (w) / Q (w) - 1 2 3 8 - - 2 -where w = x and the two r's are zeros of the function. - -In the second interval, the Hankel asymptotic expansion -is employed with two rational functions of degree 6/6 -and 7/7. - -ACCURACY: - - Absolute error: -arithmetic domain # trials peak rms - IEEE 0, 30 60000 4.2e-16 1.1e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -double besselj0(const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Bessel function of order one - -Returns Bessel function of order one of the argument. - -The domain is divided into the intervals [0, 8] and -(8, infinity). In the first interval a 24 term Chebyshev -expansion is used. In the second, the asymptotic -trigonometric representation is employed using two -rational functions of degree 5/5. - -ACCURACY: - - Absolute error: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 2.6e-16 1.1e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -double besselj1(const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Bessel function of integer order - -Returns Bessel function of order n, where n is a -(possibly negative) integer. - -The ratio of jn(x) to j0(x) is computed by backward -recurrence. First the ratio jn/jn-1 is found by a -continued fraction expansion. Then the recurrence -relating successive orders is applied until j0 or j1 is -reached. - -If n = 0 or 1 the routine for j0 or j1 is called -directly. - -ACCURACY: - - Absolute error: -arithmetic range # trials peak rms - IEEE 0, 30 5000 4.4e-16 7.9e-17 - - -Not suitable for large n or x. Use jv() (fractional order) instead. - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double besseljn(const ae_int_t n, const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Bessel function of the second kind, order zero - -Returns Bessel function of the second kind, of order -zero, of the argument. - -The domain is divided into the intervals [0, 5] and -(5, infinity). In the first interval a rational approximation -R(x) is employed to compute - y0(x) = R(x) + 2 * log(x) * j0(x) / PI. -Thus a call to j0() is required. - -In the second interval, the Hankel asymptotic expansion -is employed with two rational functions of degree 6/6 -and 7/7. - - - -ACCURACY: - - Absolute error, when y0(x) < 1; else relative error: - -arithmetic domain # trials peak rms - IEEE 0, 30 30000 1.3e-15 1.6e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -double bessely0(const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Bessel function of second kind of order one - -Returns Bessel function of the second kind of order one -of the argument. - -The domain is divided into the intervals [0, 8] and -(8, infinity). In the first interval a 25 term Chebyshev -expansion is used, and a call to j1() is required. -In the second, the asymptotic trigonometric representation -is employed using two rational functions of degree 5/5. - -ACCURACY: - - Absolute error: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 1.0e-15 1.3e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -double bessely1(const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Bessel function of second kind of integer order - -Returns Bessel function of order n, where n is a -(possibly negative) integer. - -The function is evaluated by forward recurrence on -n, starting with values computed by the routines -y0() and y1(). - -If n = 0 or 1 the routine for y0 or y1 is called -directly. - -ACCURACY: - Absolute error, except relative - when y > 1: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 3.4e-15 4.3e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double besselyn(const ae_int_t n, const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Modified Bessel function of order zero - -Returns modified Bessel function of order zero of the -argument. - -The function is defined as i0(x) = j0( ix ). - -The range is partitioned into the two intervals [0,8] and -(8, infinity). Chebyshev polynomial expansions are employed -in each interval. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,30 30000 5.8e-16 1.4e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double besseli0(const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Modified Bessel function of order one - -Returns modified Bessel function of order one of the -argument. - -The function is defined as i1(x) = -i j1( ix ). - -The range is partitioned into the two intervals [0,8] and -(8, infinity). Chebyshev polynomial expansions are employed -in each interval. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 1.9e-15 2.1e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1985, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double besseli1(const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Modified Bessel function, second kind, order zero - -Returns modified Bessel function of the second kind -of order zero of the argument. - -The range is partitioned into the two intervals [0,8] and -(8, infinity). Chebyshev polynomial expansions are employed -in each interval. - -ACCURACY: - -Tested at 2000 random points between 0 and 8. Peak absolute -error (relative when K0 > 1) was 1.46e-14; rms, 4.26e-15. - Relative error: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 1.2e-15 1.6e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double besselk0(const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Modified Bessel function, second kind, order one - -Computes the modified Bessel function of the second kind -of order one of the argument. - -The range is partitioned into the two intervals [0,2] and -(2, infinity). Chebyshev polynomial expansions are employed -in each interval. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0, 30 30000 1.2e-15 1.6e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double besselk1(const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Modified Bessel function, second kind, integer order - -Returns modified Bessel function of the second kind -of order n of the argument. - -The range is partitioned into the two intervals [0,9.55] and -(9.55, infinity). An ascending power series is used in the -low range, and an asymptotic expansion in the high range. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,30 90000 1.8e-8 3.0e-10 - -Error is high only near the crossover point x = 9.55 -between the two expansions used. - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1988, 2000 by Stephen L. Moshier -*************************************************************************/ -double besselkn(const ae_int_t nn, const double x, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_IBETAF) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Incomplete beta integral - -Returns incomplete beta integral of the arguments, evaluated -from zero to x. The function is defined as - - x - - - - | (a+b) | | a-1 b-1 - ----------- | t (1-t) dt. - - - | | - | (a) | (b) - - 0 - -The domain of definition is 0 <= x <= 1. In this -implementation a and b are restricted to positive values. -The integral from x to 1 may be obtained by the symmetry -relation - - 1 - incbet( a, b, x ) = incbet( b, a, 1-x ). - -The integral is evaluated by a continued fraction expansion -or, when b*x is small, by a power series. - -ACCURACY: - -Tested at uniformly distributed random points (a,b,x) with a and b -in "domain" and x between 0 and 1. - Relative error -arithmetic domain # trials peak rms - IEEE 0,5 10000 6.9e-15 4.5e-16 - IEEE 0,85 250000 2.2e-13 1.7e-14 - IEEE 0,1000 30000 5.3e-12 6.3e-13 - IEEE 0,10000 250000 9.3e-11 7.1e-12 - IEEE 0,100000 10000 8.7e-10 4.8e-11 -Outputs smaller than the IEEE gradual underflow threshold -were excluded from these statistics. - -Cephes Math Library, Release 2.8: June, 2000 -Copyright 1984, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double incompletebeta(const double a, const double b, const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Inverse of imcomplete beta integral - -Given y, the function finds x such that - - incbet( a, b, x ) = y . - -The routine performs interval halving or Newton iterations to find the -root of incbet(a,b,x) - y = 0. - - -ACCURACY: - - Relative error: - x a,b -arithmetic domain domain # trials peak rms - IEEE 0,1 .5,10000 50000 5.8e-12 1.3e-13 - IEEE 0,1 .25,100 100000 1.8e-13 3.9e-15 - IEEE 0,1 0,5 50000 1.1e-12 5.5e-15 -With a and b constrained to half-integer or integer values: - IEEE 0,1 .5,10000 50000 5.8e-12 1.1e-13 - IEEE 0,1 .5,100 100000 1.7e-14 7.9e-16 -With a = .5, b constrained to half-integer or integer values: - IEEE 0,1 .5,10000 10000 8.3e-11 1.0e-11 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1996, 2000 by Stephen L. Moshier -*************************************************************************/ -double invincompletebeta(const double a, const double b, const double y, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_FDISTR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -F distribution - -Returns the area from zero to x under the F density -function (also known as Snedcor's density or the -variance ratio density). This is the density -of x = (u1/df1)/(u2/df2), where u1 and u2 are random -variables having Chi square distributions with df1 -and df2 degrees of freedom, respectively. -The incomplete beta integral is used, according to the -formula - -P(x) = incbet( df1/2, df2/2, (df1*x/(df2 + df1*x) ). - - -The arguments a and b are greater than zero, and x is -nonnegative. - -ACCURACY: - -Tested at random points (a,b,x). - - x a,b Relative error: -arithmetic domain domain # trials peak rms - IEEE 0,1 0,100 100000 9.8e-15 1.7e-15 - IEEE 1,5 0,100 100000 6.5e-15 3.5e-16 - IEEE 0,1 1,10000 100000 2.2e-11 3.3e-12 - IEEE 1,5 1,10000 100000 1.1e-11 1.7e-13 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double fdistribution(const ae_int_t a, const ae_int_t b, const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Complemented F distribution - -Returns the area from x to infinity under the F density -function (also known as Snedcor's density or the -variance ratio density). - - - inf. - - - 1 | | a-1 b-1 -1-P(x) = ------ | t (1-t) dt - B(a,b) | | - - - x - - -The incomplete beta integral is used, according to the -formula - -P(x) = incbet( df2/2, df1/2, (df2/(df2 + df1*x) ). - - -ACCURACY: - -Tested at random points (a,b,x) in the indicated intervals. - x a,b Relative error: -arithmetic domain domain # trials peak rms - IEEE 0,1 1,100 100000 3.7e-14 5.9e-16 - IEEE 1,5 1,100 100000 8.0e-15 1.6e-15 - IEEE 0,1 1,10000 100000 1.8e-11 3.5e-13 - IEEE 1,5 1,10000 100000 2.0e-11 3.0e-12 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double fcdistribution(const ae_int_t a, const ae_int_t b, const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Inverse of complemented F distribution - -Finds the F density argument x such that the integral -from x to infinity of the F density is equal to the -given probability p. - -This is accomplished using the inverse beta integral -function and the relations - - z = incbi( df2/2, df1/2, p ) - x = df2 (1-z) / (df1 z). - -Note: the following relations hold for the inverse of -the uncomplemented F distribution: - - z = incbi( df1/2, df2/2, p ) - x = df2 z / (df1 (1-z)). - -ACCURACY: - -Tested at random points (a,b,p). - - a,b Relative error: -arithmetic domain # trials peak rms - For p between .001 and 1: - IEEE 1,100 100000 8.3e-15 4.7e-16 - IEEE 1,10000 100000 2.1e-11 1.4e-13 - For p between 10^-6 and 10^-3: - IEEE 1,100 50000 1.3e-12 8.4e-15 - IEEE 1,10000 50000 3.0e-12 4.8e-14 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double invfdistribution(const ae_int_t a, const ae_int_t b, const double y, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_FRESNEL) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Fresnel integral - -Evaluates the Fresnel integrals - - x - - - | | -C(x) = | cos(pi/2 t**2) dt, - | | - - - 0 - - x - - - | | -S(x) = | sin(pi/2 t**2) dt. - | | - - - 0 - - -The integrals are evaluated by a power series for x < 1. -For x >= 1 auxiliary functions f(x) and g(x) are employed -such that - -C(x) = 0.5 + f(x) sin( pi/2 x**2 ) - g(x) cos( pi/2 x**2 ) -S(x) = 0.5 - f(x) cos( pi/2 x**2 ) - g(x) sin( pi/2 x**2 ) - - - -ACCURACY: - - Relative error. - -Arithmetic function domain # trials peak rms - IEEE S(x) 0, 10 10000 2.0e-15 3.2e-16 - IEEE C(x) 0, 10 10000 1.8e-15 3.3e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -void fresnelintegral(const double x, double &c, double &s, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_JACOBIANELLIPTIC) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Jacobian Elliptic Functions - -Evaluates the Jacobian elliptic functions sn(u|m), cn(u|m), -and dn(u|m) of parameter m between 0 and 1, and real -argument u. - -These functions are periodic, with quarter-period on the -real axis equal to the complete elliptic integral -ellpk(1.0-m). - -Relation to incomplete elliptic integral: -If u = ellik(phi,m), then sn(u|m) = sin(phi), -and cn(u|m) = cos(phi). Phi is called the amplitude of u. - -Computation is by means of the arithmetic-geometric mean -algorithm, except when m is within 1e-9 of 0 or 1. In the -latter case with m close to 1, the approximation applies -only for phi < pi/2. - -ACCURACY: - -Tested at random points with u between 0 and 10, m between -0 and 1. - - Absolute error (* = relative error): -arithmetic function # trials peak rms - IEEE phi 10000 9.2e-16* 1.4e-16* - IEEE sn 50000 4.1e-15 4.6e-16 - IEEE cn 40000 3.6e-15 4.4e-16 - IEEE dn 10000 1.3e-12 1.8e-14 - - Peak error observed in consistency check using addition -theorem for sn(u+v) was 4e-16 (absolute). Also tested by -the above relation to the incomplete elliptic integral. -Accuracy deteriorates when u is large. - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -void jacobianellipticfunctions(const double u, const double m, double &sn, double &cn, double &dn, double &ph, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_PSIF) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Psi (digamma) function - - d - - psi(x) = -- ln | (x) - dx - -is the logarithmic derivative of the gamma function. -For integer x, - n-1 - - -psi(n) = -EUL + > 1/k. - - - k=1 - -This formula is used for 0 < n <= 10. If x is negative, it -is transformed to a positive argument by the reflection -formula psi(1-x) = psi(x) + pi cot(pi x). -For general positive x, the argument is made greater than 10 -using the recurrence psi(x+1) = psi(x) + 1/x. -Then the following asymptotic expansion is applied: - - inf. B - - 2k -psi(x) = log(x) - 1/2x - > ------- - - 2k - k=1 2k x - -where the B2k are Bernoulli numbers. - -ACCURACY: - Relative error (except absolute when |psi| < 1): -arithmetic domain # trials peak rms - IEEE 0,30 30000 1.3e-15 1.4e-16 - IEEE -30,0 40000 1.5e-15 2.2e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1992, 2000 by Stephen L. Moshier -*************************************************************************/ -double psi(const double x, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_EXPINTEGRALS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Exponential integral Ei(x) - - x - - t - | | e - Ei(x) = -|- --- dt . - | | t - - - -inf - -Not defined for x <= 0. -See also expn.c. - - - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,100 50000 8.6e-16 1.3e-16 - -Cephes Math Library Release 2.8: May, 1999 -Copyright 1999 by Stephen L. Moshier -*************************************************************************/ -double exponentialintegralei(const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Exponential integral En(x) - -Evaluates the exponential integral - - inf. - - - | | -xt - | e - E (x) = | ---- dt. - n | n - | | t - - - 1 - - -Both n and x must be nonnegative. - -The routine employs either a power series, a continued -fraction, or an asymptotic formula depending on the -relative values of n and x. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0, 30 10000 1.7e-15 3.6e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1985, 2000 by Stephen L. Moshier -*************************************************************************/ -double exponentialintegralen(const double x, const ae_int_t n, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_LAGUERRE) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Calculation of the value of the Laguerre polynomial. - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Laguerre polynomial Ln at x -*************************************************************************/ -double laguerrecalculate(const ae_int_t n, const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Summation of Laguerre polynomials using Clenshaw's recurrence formula. - -This routine calculates c[0]*L0(x) + c[1]*L1(x) + ... + c[N]*LN(x) - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Laguerre polynomial at x -*************************************************************************/ -double laguerresum(const real_1d_array &c, const ae_int_t n, const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Representation of Ln as C[0] + C[1]*X + ... + C[N]*X^N - -Input parameters: - N - polynomial degree, n>=0 - -Output parameters: - C - coefficients -*************************************************************************/ -void laguerrecoefficients(const ae_int_t n, real_1d_array &c, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_CHISQUAREDISTR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Chi-square distribution - -Returns the area under the left hand tail (from 0 to x) -of the Chi square probability density function with -v degrees of freedom. - - - x - - - 1 | | v/2-1 -t/2 - P( x | v ) = ----------- | t e dt - v/2 - | | - 2 | (v/2) - - 0 - -where x is the Chi-square variable. - -The incomplete gamma integral is used, according to the -formula - -y = chdtr( v, x ) = igam( v/2.0, x/2.0 ). - -The arguments must both be positive. - -ACCURACY: - -See incomplete gamma function - - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double chisquaredistribution(const double v, const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Complemented Chi-square distribution - -Returns the area under the right hand tail (from x to -infinity) of the Chi square probability density function -with v degrees of freedom: - - inf. - - - 1 | | v/2-1 -t/2 - P( x | v ) = ----------- | t e dt - v/2 - | | - 2 | (v/2) - - x - -where x is the Chi-square variable. - -The incomplete gamma integral is used, according to the -formula - -y = chdtr( v, x ) = igamc( v/2.0, x/2.0 ). - -The arguments must both be positive. - -ACCURACY: - -See incomplete gamma function - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double chisquarecdistribution(const double v, const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Inverse of complemented Chi-square distribution - -Finds the Chi-square argument x such that the integral -from x to infinity of the Chi-square density is equal -to the given cumulative probability y. - -This is accomplished using the inverse gamma integral -function and the relation - - x/2 = igami( df/2, y ); - -ACCURACY: - -See inverse incomplete gamma function - - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 2000 by Stephen L. Moshier -*************************************************************************/ -double invchisquaredistribution(const double v, const double y, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_LEGENDRE) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Calculation of the value of the Legendre polynomial Pn. - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Legendre polynomial Pn at x -*************************************************************************/ -double legendrecalculate(const ae_int_t n, const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Summation of Legendre polynomials using Clenshaw's recurrence formula. - -This routine calculates - c[0]*P0(x) + c[1]*P1(x) + ... + c[N]*PN(x) - -Parameters: - n - degree, n>=0 - x - argument - -Result: - the value of the Legendre polynomial at x -*************************************************************************/ -double legendresum(const real_1d_array &c, const ae_int_t n, const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Representation of Pn as C[0] + C[1]*X + ... + C[N]*X^N - -Input parameters: - N - polynomial degree, n>=0 - -Output parameters: - C - coefficients -*************************************************************************/ -void legendrecoefficients(const ae_int_t n, real_1d_array &c, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_BETAF) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Beta function - - - - - - | (a) | (b) -beta( a, b ) = -----------. - - - | (a+b) - -For large arguments the logarithm of the function is -evaluated using lgam(), then exponentiated. - -ACCURACY: - - Relative error: -arithmetic domain # trials peak rms - IEEE 0,30 30000 8.1e-14 1.1e-14 - -Cephes Math Library Release 2.0: April, 1987 -Copyright 1984, 1987 by Stephen L. Moshier -*************************************************************************/ -double beta(const double a, const double b, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_CHEBYSHEV) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Calculation of the value of the Chebyshev polynomials of the -first and second kinds. - -Parameters: - r - polynomial kind, either 1 or 2. - n - degree, n>=0 - x - argument, -1 <= x <= 1 - -Result: - the value of the Chebyshev polynomial at x -*************************************************************************/ -double chebyshevcalculate(const ae_int_t r, const ae_int_t n, const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Summation of Chebyshev polynomials using Clenshaw's recurrence formula. - -This routine calculates - c[0]*T0(x) + c[1]*T1(x) + ... + c[N]*TN(x) -or - c[0]*U0(x) + c[1]*U1(x) + ... + c[N]*UN(x) -depending on the R. - -Parameters: - r - polynomial kind, either 1 or 2. - n - degree, n>=0 - x - argument - -Result: - the value of the Chebyshev polynomial at x -*************************************************************************/ -double chebyshevsum(const real_1d_array &c, const ae_int_t r, const ae_int_t n, const double x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Representation of Tn as C[0] + C[1]*X + ... + C[N]*X^N - -Input parameters: - N - polynomial degree, n>=0 - -Output parameters: - C - coefficients -*************************************************************************/ -void chebyshevcoefficients(const ae_int_t n, real_1d_array &c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Conversion of a series of Chebyshev polynomials to a power series. - -Represents A[0]*T0(x) + A[1]*T1(x) + ... + A[N]*Tn(x) as -B[0] + B[1]*X + ... + B[N]*X^N. - -Input parameters: - A - Chebyshev series coefficients - N - degree, N>=0 - -Output parameters - B - power series coefficients -*************************************************************************/ -void fromchebyshev(const real_1d_array &a, const ae_int_t n, real_1d_array &b, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_STUDENTTDISTR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Student's t distribution - -Computes the integral from minus infinity to t of the Student -t distribution with integer k > 0 degrees of freedom: - - t - - - | | - - | 2 -(k+1)/2 - | ( (k+1)/2 ) | ( x ) - ---------------------- | ( 1 + --- ) dx - - | ( k ) - sqrt( k pi ) | ( k/2 ) | - | | - - - -inf. - -Relation to incomplete beta integral: - - 1 - stdtr(k,t) = 0.5 * incbet( k/2, 1/2, z ) -where - z = k/(k + t**2). - -For t < -2, this is the method of computation. For higher t, -a direct method is derived from integration by parts. -Since the function is symmetric about t=0, the area under the -right tail of the density is found by calling the function -with -t instead of t. - -ACCURACY: - -Tested at random 1 <= k <= 25. The "domain" refers to t. - Relative error: -arithmetic domain # trials peak rms - IEEE -100,-2 50000 5.9e-15 1.4e-15 - IEEE -2,100 500000 2.7e-15 4.9e-17 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double studenttdistribution(const ae_int_t k, const double t, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Functional inverse of Student's t distribution - -Given probability p, finds the argument t such that stdtr(k,t) -is equal to p. - -ACCURACY: - -Tested at random 1 <= k <= 100. The "domain" refers to p: - Relative error: -arithmetic domain # trials peak rms - IEEE .001,.999 25000 5.7e-15 8.0e-16 - IEEE 10^-6,.001 25000 2.0e-12 2.9e-14 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double invstudenttdistribution(const ae_int_t k, const double p, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_BINOMIALDISTR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Binomial distribution - -Returns the sum of the terms 0 through k of the Binomial -probability density: - - k - -- ( n ) j n-j - > ( ) p (1-p) - -- ( j ) - j=0 - -The terms are not summed directly; instead the incomplete -beta integral is employed, according to the formula - -y = bdtr( k, n, p ) = incbet( n-k, k+1, 1-p ). - -The arguments must be positive, with p ranging from 0 to 1. - -ACCURACY: - -Tested at random points (a,b,p), with p between 0 and 1. - - a,b Relative error: -arithmetic domain # trials peak rms - For p between 0.001 and 1: - IEEE 0,100 100000 4.3e-15 2.6e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double binomialdistribution(const ae_int_t k, const ae_int_t n, const double p, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Complemented binomial distribution - -Returns the sum of the terms k+1 through n of the Binomial -probability density: - - n - -- ( n ) j n-j - > ( ) p (1-p) - -- ( j ) - j=k+1 - -The terms are not summed directly; instead the incomplete -beta integral is employed, according to the formula - -y = bdtrc( k, n, p ) = incbet( k+1, n-k, p ). - -The arguments must be positive, with p ranging from 0 to 1. - -ACCURACY: - -Tested at random points (a,b,p). - - a,b Relative error: -arithmetic domain # trials peak rms - For p between 0.001 and 1: - IEEE 0,100 100000 6.7e-15 8.2e-16 - For p between 0 and .001: - IEEE 0,100 100000 1.5e-13 2.7e-15 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double binomialcdistribution(const ae_int_t k, const ae_int_t n, const double p, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Inverse binomial distribution - -Finds the event probability p such that the sum of the -terms 0 through k of the Binomial probability density -is equal to the given cumulative probability y. - -This is accomplished using the inverse beta integral -function and the relation - -1 - p = incbi( n-k, k+1, y ). - -ACCURACY: - -Tested at random points (a,b,p). - - a,b Relative error: -arithmetic domain # trials peak rms - For p between 0.001 and 1: - IEEE 0,100 100000 2.3e-14 6.4e-16 - IEEE 0,10000 100000 6.6e-12 1.2e-13 - For p between 10^-6 and 0.001: - IEEE 0,100 100000 2.0e-12 1.3e-14 - IEEE 0,10000 100000 1.5e-12 3.2e-14 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1995, 2000 by Stephen L. Moshier -*************************************************************************/ -double invbinomialdistribution(const ae_int_t k, const ae_int_t n, const double y, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_AIRYF) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Airy function - -Solution of the differential equation - -y"(x) = xy. - -The function returns the two independent solutions Ai, Bi -and their first derivatives Ai'(x), Bi'(x). - -Evaluation is by power series summation for small x, -by rational minimax approximations for large x. - - - -ACCURACY: -Error criterion is absolute when function <= 1, relative -when function > 1, except * denotes relative error criterion. -For large negative x, the absolute error increases as x^1.5. -For large positive x, the relative error increases as x^1.5. - -Arithmetic domain function # trials peak rms -IEEE -10, 0 Ai 10000 1.6e-15 2.7e-16 -IEEE 0, 10 Ai 10000 2.3e-14* 1.8e-15* -IEEE -10, 0 Ai' 10000 4.6e-15 7.6e-16 -IEEE 0, 10 Ai' 10000 1.8e-14* 1.5e-15* -IEEE -10, 10 Bi 30000 4.2e-15 5.3e-16 -IEEE -10, 10 Bi' 30000 4.9e-15 7.3e-16 - -Cephes Math Library Release 2.8: June, 2000 -Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier -*************************************************************************/ -void airy(const double x, double &ai, double &aip, double &bi, double &bip, const xparams _xparams = alglib::xdefault); -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (FUNCTIONS) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_GAMMAFUNC) || !defined(AE_PARTIAL_BUILD) -double gammafunction(double x, ae_state *_state); -double lngamma(double x, double* sgngam, ae_state *_state); -#endif -#if defined(AE_COMPILE_NORMALDISTR) || !defined(AE_PARTIAL_BUILD) -double errorfunction(double x, ae_state *_state); -double errorfunctionc(double x, ae_state *_state); -double normaldistribution(double x, ae_state *_state); -double normalpdf(double x, ae_state *_state); -double normalcdf(double x, ae_state *_state); -double inverf(double e, ae_state *_state); -double invnormaldistribution(double y0, ae_state *_state); -double invnormalcdf(double y0, ae_state *_state); -double bivariatenormalpdf(double x, - double y, - double rho, - ae_state *_state); -double bivariatenormalcdf(double x, - double y, - double rho, - ae_state *_state); -#endif -#if defined(AE_COMPILE_IGAMMAF) || !defined(AE_PARTIAL_BUILD) -double incompletegamma(double a, double x, ae_state *_state); -double incompletegammac(double a, double x, ae_state *_state); -double invincompletegammac(double a, double y0, ae_state *_state); -#endif -#if defined(AE_COMPILE_ELLIPTIC) || !defined(AE_PARTIAL_BUILD) -double ellipticintegralk(double m, ae_state *_state); -double ellipticintegralkhighprecision(double m1, ae_state *_state); -double incompleteellipticintegralk(double phi, double m, ae_state *_state); -double ellipticintegrale(double m, ae_state *_state); -double incompleteellipticintegrale(double phi, double m, ae_state *_state); -#endif -#if defined(AE_COMPILE_HERMITE) || !defined(AE_PARTIAL_BUILD) -double hermitecalculate(ae_int_t n, double x, ae_state *_state); -double hermitesum(/* Real */ ae_vector* c, - ae_int_t n, - double x, - ae_state *_state); -void hermitecoefficients(ae_int_t n, - /* Real */ ae_vector* c, - ae_state *_state); -#endif -#if defined(AE_COMPILE_DAWSON) || !defined(AE_PARTIAL_BUILD) -double dawsonintegral(double x, ae_state *_state); -#endif -#if defined(AE_COMPILE_TRIGINTEGRALS) || !defined(AE_PARTIAL_BUILD) -void sinecosineintegrals(double x, - double* si, - double* ci, - ae_state *_state); -void hyperbolicsinecosineintegrals(double x, - double* shi, - double* chi, - ae_state *_state); -#endif -#if defined(AE_COMPILE_POISSONDISTR) || !defined(AE_PARTIAL_BUILD) -double poissondistribution(ae_int_t k, double m, ae_state *_state); -double poissoncdistribution(ae_int_t k, double m, ae_state *_state); -double invpoissondistribution(ae_int_t k, double y, ae_state *_state); -#endif -#if defined(AE_COMPILE_BESSEL) || !defined(AE_PARTIAL_BUILD) -double besselj0(double x, ae_state *_state); -double besselj1(double x, ae_state *_state); -double besseljn(ae_int_t n, double x, ae_state *_state); -double bessely0(double x, ae_state *_state); -double bessely1(double x, ae_state *_state); -double besselyn(ae_int_t n, double x, ae_state *_state); -double besseli0(double x, ae_state *_state); -double besseli1(double x, ae_state *_state); -double besselk0(double x, ae_state *_state); -double besselk1(double x, ae_state *_state); -double besselkn(ae_int_t nn, double x, ae_state *_state); -#endif -#if defined(AE_COMPILE_IBETAF) || !defined(AE_PARTIAL_BUILD) -double incompletebeta(double a, double b, double x, ae_state *_state); -double invincompletebeta(double a, double b, double y, ae_state *_state); -#endif -#if defined(AE_COMPILE_FDISTR) || !defined(AE_PARTIAL_BUILD) -double fdistribution(ae_int_t a, ae_int_t b, double x, ae_state *_state); -double fcdistribution(ae_int_t a, ae_int_t b, double x, ae_state *_state); -double invfdistribution(ae_int_t a, - ae_int_t b, - double y, - ae_state *_state); -#endif -#if defined(AE_COMPILE_FRESNEL) || !defined(AE_PARTIAL_BUILD) -void fresnelintegral(double x, double* c, double* s, ae_state *_state); -#endif -#if defined(AE_COMPILE_JACOBIANELLIPTIC) || !defined(AE_PARTIAL_BUILD) -void jacobianellipticfunctions(double u, - double m, - double* sn, - double* cn, - double* dn, - double* ph, - ae_state *_state); -#endif -#if defined(AE_COMPILE_PSIF) || !defined(AE_PARTIAL_BUILD) -double psi(double x, ae_state *_state); -#endif -#if defined(AE_COMPILE_EXPINTEGRALS) || !defined(AE_PARTIAL_BUILD) -double exponentialintegralei(double x, ae_state *_state); -double exponentialintegralen(double x, ae_int_t n, ae_state *_state); -#endif -#if defined(AE_COMPILE_LAGUERRE) || !defined(AE_PARTIAL_BUILD) -double laguerrecalculate(ae_int_t n, double x, ae_state *_state); -double laguerresum(/* Real */ ae_vector* c, - ae_int_t n, - double x, - ae_state *_state); -void laguerrecoefficients(ae_int_t n, - /* Real */ ae_vector* c, - ae_state *_state); -#endif -#if defined(AE_COMPILE_CHISQUAREDISTR) || !defined(AE_PARTIAL_BUILD) -double chisquaredistribution(double v, double x, ae_state *_state); -double chisquarecdistribution(double v, double x, ae_state *_state); -double invchisquaredistribution(double v, double y, ae_state *_state); -#endif -#if defined(AE_COMPILE_LEGENDRE) || !defined(AE_PARTIAL_BUILD) -double legendrecalculate(ae_int_t n, double x, ae_state *_state); -double legendresum(/* Real */ ae_vector* c, - ae_int_t n, - double x, - ae_state *_state); -void legendrecoefficients(ae_int_t n, - /* Real */ ae_vector* c, - ae_state *_state); -#endif -#if defined(AE_COMPILE_BETAF) || !defined(AE_PARTIAL_BUILD) -double beta(double a, double b, ae_state *_state); -#endif -#if defined(AE_COMPILE_CHEBYSHEV) || !defined(AE_PARTIAL_BUILD) -double chebyshevcalculate(ae_int_t r, - ae_int_t n, - double x, - ae_state *_state); -double chebyshevsum(/* Real */ ae_vector* c, - ae_int_t r, - ae_int_t n, - double x, - ae_state *_state); -void chebyshevcoefficients(ae_int_t n, - /* Real */ ae_vector* c, - ae_state *_state); -void fromchebyshev(/* Real */ ae_vector* a, - ae_int_t n, - /* Real */ ae_vector* b, - ae_state *_state); -#endif -#if defined(AE_COMPILE_STUDENTTDISTR) || !defined(AE_PARTIAL_BUILD) -double studenttdistribution(ae_int_t k, double t, ae_state *_state); -double invstudenttdistribution(ae_int_t k, double p, ae_state *_state); -#endif -#if defined(AE_COMPILE_BINOMIALDISTR) || !defined(AE_PARTIAL_BUILD) -double binomialdistribution(ae_int_t k, - ae_int_t n, - double p, - ae_state *_state); -double binomialcdistribution(ae_int_t k, - ae_int_t n, - double p, - ae_state *_state); -double invbinomialdistribution(ae_int_t k, - ae_int_t n, - double y, - ae_state *_state); -#endif -#if defined(AE_COMPILE_AIRYF) || !defined(AE_PARTIAL_BUILD) -void airy(double x, - double* ai, - double* aip, - double* bi, - double* bip, - ae_state *_state); -#endif - -} -#endif - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/statistics.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/statistics.cpp deleted file mode 100644 index 786ec7c..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/statistics.cpp +++ /dev/null @@ -1,19832 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifdef _MSC_VER -#define _CRT_SECURE_NO_WARNINGS -#endif -#include "stdafx.h" -#include "statistics.h" - -// disable some irrelevant warnings -#if (AE_COMPILER==AE_MSVC) && !defined(AE_ALL_WARNINGS) -#pragma warning(disable:4100) -#pragma warning(disable:4127) -#pragma warning(disable:4611) -#pragma warning(disable:4702) -#pragma warning(disable:4996) -#endif - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_BASESTAT) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_WSR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_STEST) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_CORRELATIONTESTS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_STUDENTTTESTS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MANNWHITNEYU) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_JARQUEBERA) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_VARIANCETESTS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_BASESTAT) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Calculation of the distribution moments: mean, variance, skewness, kurtosis. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -OUTPUT PARAMETERS - Mean - mean. - Variance- variance. - Skewness- skewness (if variance<>0; zero otherwise). - Kurtosis- kurtosis (if variance<>0; zero otherwise). - -NOTE: variance is calculated by dividing sum of squares by N-1, not N. - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -void samplemoments(const real_1d_array &x, const ae_int_t n, double &mean, double &variance, double &skewness, double &kurtosis, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::samplemoments(const_cast(x.c_ptr()), n, &mean, &variance, &skewness, &kurtosis, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Calculation of the distribution moments: mean, variance, skewness, kurtosis. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -OUTPUT PARAMETERS - Mean - mean. - Variance- variance. - Skewness- skewness (if variance<>0; zero otherwise). - Kurtosis- kurtosis (if variance<>0; zero otherwise). - -NOTE: variance is calculated by dividing sum of squares by N-1, not N. - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void samplemoments(const real_1d_array &x, double &mean, double &variance, double &skewness, double &kurtosis, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::samplemoments(const_cast(x.c_ptr()), n, &mean, &variance, &skewness, &kurtosis, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Calculation of the mean. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -NOTE: - -This function return result which calculated by 'SampleMoments' function -and stored at 'Mean' variable. - - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -double samplemean(const real_1d_array &x, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::samplemean(const_cast(x.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Calculation of the mean. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -NOTE: - -This function return result which calculated by 'SampleMoments' function -and stored at 'Mean' variable. - - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -double samplemean(const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::samplemean(const_cast(x.c_ptr()), n, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -Calculation of the variance. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -NOTE: - -This function return result which calculated by 'SampleMoments' function -and stored at 'Variance' variable. - - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -double samplevariance(const real_1d_array &x, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::samplevariance(const_cast(x.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Calculation of the variance. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -NOTE: - -This function return result which calculated by 'SampleMoments' function -and stored at 'Variance' variable. - - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -double samplevariance(const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::samplevariance(const_cast(x.c_ptr()), n, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -Calculation of the skewness. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -NOTE: - -This function return result which calculated by 'SampleMoments' function -and stored at 'Skewness' variable. - - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -double sampleskewness(const real_1d_array &x, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::sampleskewness(const_cast(x.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Calculation of the skewness. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -NOTE: - -This function return result which calculated by 'SampleMoments' function -and stored at 'Skewness' variable. - - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -double sampleskewness(const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::sampleskewness(const_cast(x.c_ptr()), n, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -Calculation of the kurtosis. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -NOTE: - -This function return result which calculated by 'SampleMoments' function -and stored at 'Kurtosis' variable. - - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -double samplekurtosis(const real_1d_array &x, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::samplekurtosis(const_cast(x.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Calculation of the kurtosis. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -NOTE: - -This function return result which calculated by 'SampleMoments' function -and stored at 'Kurtosis' variable. - - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -double samplekurtosis(const real_1d_array &x, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::samplekurtosis(const_cast(x.c_ptr()), n, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -ADev - -Input parameters: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -Output parameters: - ADev- ADev - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -void sampleadev(const real_1d_array &x, const ae_int_t n, double &adev, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sampleadev(const_cast(x.c_ptr()), n, &adev, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -ADev - -Input parameters: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -Output parameters: - ADev- ADev - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void sampleadev(const real_1d_array &x, double &adev, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::sampleadev(const_cast(x.c_ptr()), n, &adev, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Median calculation. - -Input parameters: - X - sample (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -Output parameters: - Median - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -void samplemedian(const real_1d_array &x, const ae_int_t n, double &median, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::samplemedian(const_cast(x.c_ptr()), n, &median, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Median calculation. - -Input parameters: - X - sample (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -Output parameters: - Median - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void samplemedian(const real_1d_array &x, double &median, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::samplemedian(const_cast(x.c_ptr()), n, &median, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Percentile calculation. - -Input parameters: - X - sample (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - P - percentile (0<=P<=1) - -Output parameters: - V - percentile - - -- ALGLIB -- - Copyright 01.03.2008 by Bochkanov Sergey -*************************************************************************/ -void samplepercentile(const real_1d_array &x, const ae_int_t n, const double p, double &v, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::samplepercentile(const_cast(x.c_ptr()), n, p, &v, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Percentile calculation. - -Input parameters: - X - sample (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - P - percentile (0<=P<=1) - -Output parameters: - V - percentile - - -- ALGLIB -- - Copyright 01.03.2008 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void samplepercentile(const real_1d_array &x, const double p, double &v, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::samplepercentile(const_cast(x.c_ptr()), n, p, &v, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -2-sample covariance - -Input parameters: - X - sample 1 (array indexes: [0..N-1]) - Y - sample 2 (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only N leading elements of X/Y are processed - * if not given, automatically determined from input sizes - -Result: - covariance (zero for N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -double cov2(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::cov2(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -2-sample covariance - -Input parameters: - X - sample 1 (array indexes: [0..N-1]) - Y - sample 2 (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only N leading elements of X/Y are processed - * if not given, automatically determined from input sizes - -Result: - covariance (zero for N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -double cov2(const real_1d_array &x, const real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (x.length()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'cov2': looks like one of arguments has wrong size"); - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::cov2(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -Pearson product-moment correlation coefficient - -Input parameters: - X - sample 1 (array indexes: [0..N-1]) - Y - sample 2 (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only N leading elements of X/Y are processed - * if not given, automatically determined from input sizes - -Result: - Pearson product-moment correlation coefficient - (zero for N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -double pearsoncorr2(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::pearsoncorr2(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Pearson product-moment correlation coefficient - -Input parameters: - X - sample 1 (array indexes: [0..N-1]) - Y - sample 2 (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only N leading elements of X/Y are processed - * if not given, automatically determined from input sizes - -Result: - Pearson product-moment correlation coefficient - (zero for N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -double pearsoncorr2(const real_1d_array &x, const real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (x.length()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'pearsoncorr2': looks like one of arguments has wrong size"); - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::pearsoncorr2(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -Spearman's rank correlation coefficient - -Input parameters: - X - sample 1 (array indexes: [0..N-1]) - Y - sample 2 (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only N leading elements of X/Y are processed - * if not given, automatically determined from input sizes - -Result: - Spearman's rank correlation coefficient - (zero for N=0 or N=1) - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -double spearmancorr2(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::spearmancorr2(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Spearman's rank correlation coefficient - -Input parameters: - X - sample 1 (array indexes: [0..N-1]) - Y - sample 2 (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only N leading elements of X/Y are processed - * if not given, automatically determined from input sizes - -Result: - Spearman's rank correlation coefficient - (zero for N=0 or N=1) - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -double spearmancorr2(const real_1d_array &x, const real_1d_array &y, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - if( (x.length()!=y.length())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spearmancorr2': looks like one of arguments has wrong size"); - n = x.length(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::spearmancorr2(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -/************************************************************************* -Covariance matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X are used - * if not given, automatically determined from input size - M - M>0, number of variables: - * if given, only leading M columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M,M], covariance matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -void covm(const real_2d_array &x, const ae_int_t n, const ae_int_t m, real_2d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::covm(const_cast(x.c_ptr()), n, m, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Covariance matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X are used - * if not given, automatically determined from input size - M - M>0, number of variables: - * if given, only leading M columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M,M], covariance matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void covm(const real_2d_array &x, real_2d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t m; - - n = x.rows(); - m = x.cols(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::covm(const_cast(x.c_ptr()), n, m, const_cast(c.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Pearson product-moment correlation matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X are used - * if not given, automatically determined from input size - M - M>0, number of variables: - * if given, only leading M columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M,M], correlation matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -void pearsoncorrm(const real_2d_array &x, const ae_int_t n, const ae_int_t m, real_2d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::pearsoncorrm(const_cast(x.c_ptr()), n, m, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Pearson product-moment correlation matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X are used - * if not given, automatically determined from input size - M - M>0, number of variables: - * if given, only leading M columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M,M], correlation matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void pearsoncorrm(const real_2d_array &x, real_2d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t m; - - n = x.rows(); - m = x.cols(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::pearsoncorrm(const_cast(x.c_ptr()), n, m, const_cast(c.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Spearman's rank correlation matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X are used - * if not given, automatically determined from input size - M - M>0, number of variables: - * if given, only leading M columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M,M], correlation matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -void spearmancorrm(const real_2d_array &x, const ae_int_t n, const ae_int_t m, real_2d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spearmancorrm(const_cast(x.c_ptr()), n, m, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Spearman's rank correlation matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X are used - * if not given, automatically determined from input size - M - M>0, number of variables: - * if given, only leading M columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M,M], correlation matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spearmancorrm(const real_2d_array &x, real_2d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t m; - - n = x.rows(); - m = x.cols(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spearmancorrm(const_cast(x.c_ptr()), n, m, const_cast(c.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Cross-covariance matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M1], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - Y - array[N,M2], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X/Y are used - * if not given, automatically determined from input sizes - M1 - M1>0, number of variables in X: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - M2 - M2>0, number of variables in Y: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M1,M2], cross-covariance matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -void covm2(const real_2d_array &x, const real_2d_array &y, const ae_int_t n, const ae_int_t m1, const ae_int_t m2, real_2d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::covm2(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, m1, m2, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Cross-covariance matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M1], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - Y - array[N,M2], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X/Y are used - * if not given, automatically determined from input sizes - M1 - M1>0, number of variables in X: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - M2 - M2>0, number of variables in Y: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M1,M2], cross-covariance matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void covm2(const real_2d_array &x, const real_2d_array &y, real_2d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t m1; - ae_int_t m2; - if( (x.rows()!=y.rows())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'covm2': looks like one of arguments has wrong size"); - n = x.rows(); - m1 = x.cols(); - m2 = y.cols(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::covm2(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, m1, m2, const_cast(c.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Pearson product-moment cross-correlation matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M1], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - Y - array[N,M2], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X/Y are used - * if not given, automatically determined from input sizes - M1 - M1>0, number of variables in X: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - M2 - M2>0, number of variables in Y: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M1,M2], cross-correlation matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -void pearsoncorrm2(const real_2d_array &x, const real_2d_array &y, const ae_int_t n, const ae_int_t m1, const ae_int_t m2, real_2d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::pearsoncorrm2(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, m1, m2, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Pearson product-moment cross-correlation matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M1], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - Y - array[N,M2], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X/Y are used - * if not given, automatically determined from input sizes - M1 - M1>0, number of variables in X: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - M2 - M2>0, number of variables in Y: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M1,M2], cross-correlation matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void pearsoncorrm2(const real_2d_array &x, const real_2d_array &y, real_2d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t m1; - ae_int_t m2; - if( (x.rows()!=y.rows())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'pearsoncorrm2': looks like one of arguments has wrong size"); - n = x.rows(); - m1 = x.cols(); - m2 = y.cols(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::pearsoncorrm2(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, m1, m2, const_cast(c.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Spearman's rank cross-correlation matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M1], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - Y - array[N,M2], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X/Y are used - * if not given, automatically determined from input sizes - M1 - M1>0, number of variables in X: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - M2 - M2>0, number of variables in Y: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M1,M2], cross-correlation matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -void spearmancorrm2(const real_2d_array &x, const real_2d_array &y, const ae_int_t n, const ae_int_t m1, const ae_int_t m2, real_2d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spearmancorrm2(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, m1, m2, const_cast(c.c_ptr()), &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Spearman's rank cross-correlation matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M1], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - Y - array[N,M2], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X/Y are used - * if not given, automatically determined from input sizes - M1 - M1>0, number of variables in X: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - M2 - M2>0, number of variables in Y: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M1,M2], cross-correlation matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void spearmancorrm2(const real_2d_array &x, const real_2d_array &y, real_2d_array &c, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t n; - ae_int_t m1; - ae_int_t m2; - if( (x.rows()!=y.rows())) - _ALGLIB_CPP_EXCEPTION("Error while calling 'spearmancorrm2': looks like one of arguments has wrong size"); - n = x.rows(); - m1 = x.cols(); - m2 = y.cols(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spearmancorrm2(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, m1, m2, const_cast(c.c_ptr()), &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function replaces data in XY by their ranks: -* XY is processed row-by-row -* rows are processed separately -* tied data are correctly handled (tied ranks are calculated) -* ranking starts from 0, ends at NFeatures-1 -* sum of within-row values is equal to (NFeatures-1)*NFeatures/2 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - array[NPoints,NFeatures], dataset - NPoints - number of points - NFeatures- number of features - -OUTPUT PARAMETERS: - XY - data are replaced by their within-row ranks; - ranking starts from 0, ends at NFeatures-1 - - -- ALGLIB -- - Copyright 18.04.2013 by Bochkanov Sergey -*************************************************************************/ -void rankdata(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nfeatures, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rankdata(const_cast(xy.c_ptr()), npoints, nfeatures, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function replaces data in XY by their ranks: -* XY is processed row-by-row -* rows are processed separately -* tied data are correctly handled (tied ranks are calculated) -* ranking starts from 0, ends at NFeatures-1 -* sum of within-row values is equal to (NFeatures-1)*NFeatures/2 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - array[NPoints,NFeatures], dataset - NPoints - number of points - NFeatures- number of features - -OUTPUT PARAMETERS: - XY - data are replaced by their within-row ranks; - ranking starts from 0, ends at NFeatures-1 - - -- ALGLIB -- - Copyright 18.04.2013 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void rankdata(real_2d_array &xy, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t npoints; - ae_int_t nfeatures; - - npoints = xy.rows(); - nfeatures = xy.cols(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rankdata(const_cast(xy.c_ptr()), npoints, nfeatures, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -This function replaces data in XY by their CENTERED ranks: -* XY is processed row-by-row -* rows are processed separately -* tied data are correctly handled (tied ranks are calculated) -* centered ranks are just usual ranks, but centered in such way that sum - of within-row values is equal to 0.0. -* centering is performed by subtracting mean from each row, i.e it changes - mean value, but does NOT change higher moments - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - array[NPoints,NFeatures], dataset - NPoints - number of points - NFeatures- number of features - -OUTPUT PARAMETERS: - XY - data are replaced by their within-row ranks; - ranking starts from 0, ends at NFeatures-1 - - -- ALGLIB -- - Copyright 18.04.2013 by Bochkanov Sergey -*************************************************************************/ -void rankdatacentered(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nfeatures, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rankdatacentered(const_cast(xy.c_ptr()), npoints, nfeatures, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -This function replaces data in XY by their CENTERED ranks: -* XY is processed row-by-row -* rows are processed separately -* tied data are correctly handled (tied ranks are calculated) -* centered ranks are just usual ranks, but centered in such way that sum - of within-row values is equal to 0.0. -* centering is performed by subtracting mean from each row, i.e it changes - mean value, but does NOT change higher moments - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - array[NPoints,NFeatures], dataset - NPoints - number of points - NFeatures- number of features - -OUTPUT PARAMETERS: - XY - data are replaced by their within-row ranks; - ranking starts from 0, ends at NFeatures-1 - - -- ALGLIB -- - Copyright 18.04.2013 by Bochkanov Sergey -*************************************************************************/ -#if !defined(AE_NO_EXCEPTIONS) -void rankdatacentered(real_2d_array &xy, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - ae_int_t npoints; - ae_int_t nfeatures; - - npoints = xy.rows(); - nfeatures = xy.cols(); - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::rankdatacentered(const_cast(xy.c_ptr()), npoints, nfeatures, &_alglib_env_state); - - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -/************************************************************************* -Obsolete function, we recommend to use PearsonCorr2(). - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -double pearsoncorrelation(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::pearsoncorrelation(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} - -/************************************************************************* -Obsolete function, we recommend to use SpearmanCorr2(). - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -double spearmanrankcorrelation(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return 0; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - double result = alglib_impl::spearmanrankcorrelation(const_cast(x.c_ptr()), const_cast(y.c_ptr()), n, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return *(reinterpret_cast(&result)); -} -#endif - -#if defined(AE_COMPILE_WSR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Wilcoxon signed-rank test - -This test checks three hypotheses about the median of the given sample. -The following tests are performed: - * two-tailed test (null hypothesis - the median is equal to the given - value) - * left-tailed test (null hypothesis - the median is greater than or - equal to the given value) - * right-tailed test (null hypothesis - the median is less than or - equal to the given value) - -Requirements: - * the scale of measurement should be ordinal, interval or ratio (i.e. - the test could not be applied to nominal variables). - * the distribution should be continuous and symmetric relative to its - median. - * number of distinct values in the X array should be greater than 4 - -The test is non-parametric and doesn't require distribution X to be normal - -Input parameters: - X - sample. Array whose index goes from 0 to N-1. - N - size of the sample. - Median - assumed median value. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -To calculate p-values, special approximation is used. This method lets us -calculate p-values with two decimal places in interval [0.0001, 1]. - -"Two decimal places" does not sound very impressive, but in practice the -relative error of less than 1% is enough to make a decision. - -There is no approximation outside the [0.0001, 1] interval. Therefore, if -the significance level outlies this interval, the test returns 0.0001. - - -- ALGLIB -- - Copyright 08.09.2006 by Bochkanov Sergey -*************************************************************************/ -void wilcoxonsignedranktest(const real_1d_array &x, const ae_int_t n, const double e, double &bothtails, double &lefttail, double &righttail, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::wilcoxonsignedranktest(const_cast(x.c_ptr()), n, e, &bothtails, &lefttail, &righttail, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_STEST) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Sign test - -This test checks three hypotheses about the median of the given sample. -The following tests are performed: - * two-tailed test (null hypothesis - the median is equal to the given - value) - * left-tailed test (null hypothesis - the median is greater than or - equal to the given value) - * right-tailed test (null hypothesis - the median is less than or - equal to the given value) - -Requirements: - * the scale of measurement should be ordinal, interval or ratio (i.e. - the test could not be applied to nominal variables). - -The test is non-parametric and doesn't require distribution X to be normal - -Input parameters: - X - sample. Array whose index goes from 0 to N-1. - N - size of the sample. - Median - assumed median value. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -While calculating p-values high-precision binomial distribution -approximation is used, so significance levels have about 15 exact digits. - - -- ALGLIB -- - Copyright 08.09.2006 by Bochkanov Sergey -*************************************************************************/ -void onesamplesigntest(const real_1d_array &x, const ae_int_t n, const double median, double &bothtails, double &lefttail, double &righttail, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::onesamplesigntest(const_cast(x.c_ptr()), n, median, &bothtails, &lefttail, &righttail, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_CORRELATIONTESTS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Pearson's correlation coefficient significance test - -This test checks hypotheses about whether X and Y are samples of two -continuous distributions having zero correlation or whether their -correlation is non-zero. - -The following tests are performed: - * two-tailed test (null hypothesis - X and Y have zero correlation) - * left-tailed test (null hypothesis - the correlation coefficient is - greater than or equal to 0) - * right-tailed test (null hypothesis - the correlation coefficient is - less than or equal to 0). - -Requirements: - * the number of elements in each sample is not less than 5 - * normality of distributions of X and Y. - -Input parameters: - R - Pearson's correlation coefficient for X and Y - N - number of elements in samples, N>=5. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -void pearsoncorrelationsignificance(const double r, const ae_int_t n, double &bothtails, double &lefttail, double &righttail, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::pearsoncorrelationsignificance(r, n, &bothtails, &lefttail, &righttail, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Spearman's rank correlation coefficient significance test - -This test checks hypotheses about whether X and Y are samples of two -continuous distributions having zero correlation or whether their -correlation is non-zero. - -The following tests are performed: - * two-tailed test (null hypothesis - X and Y have zero correlation) - * left-tailed test (null hypothesis - the correlation coefficient is - greater than or equal to 0) - * right-tailed test (null hypothesis - the correlation coefficient is - less than or equal to 0). - -Requirements: - * the number of elements in each sample is not less than 5. - -The test is non-parametric and doesn't require distributions X and Y to be -normal. - -Input parameters: - R - Spearman's rank correlation coefficient for X and Y - N - number of elements in samples, N>=5. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -void spearmanrankcorrelationsignificance(const double r, const ae_int_t n, double &bothtails, double &lefttail, double &righttail, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::spearmanrankcorrelationsignificance(r, n, &bothtails, &lefttail, &righttail, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_STUDENTTTESTS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -One-sample t-test - -This test checks three hypotheses about the mean of the given sample. The -following tests are performed: - * two-tailed test (null hypothesis - the mean is equal to the given - value) - * left-tailed test (null hypothesis - the mean is greater than or - equal to the given value) - * right-tailed test (null hypothesis - the mean is less than or equal - to the given value). - -The test is based on the assumption that a given sample has a normal -distribution and an unknown dispersion. If the distribution sharply -differs from normal, the test will work incorrectly. - -INPUT PARAMETERS: - X - sample. Array whose index goes from 0 to N-1. - N - size of sample, N>=0 - Mean - assumed value of the mean. - -OUTPUT PARAMETERS: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -NOTE: this function correctly handles degenerate cases: - * when N=0, all p-values are set to 1.0 - * when variance of X[] is exactly zero, p-values are set - to 1.0 or 0.0, depending on difference between sample mean and - value of mean being tested. - - - -- ALGLIB -- - Copyright 08.09.2006 by Bochkanov Sergey -*************************************************************************/ -void studentttest1(const real_1d_array &x, const ae_int_t n, const double mean, double &bothtails, double &lefttail, double &righttail, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::studentttest1(const_cast(x.c_ptr()), n, mean, &bothtails, &lefttail, &righttail, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Two-sample pooled test - -This test checks three hypotheses about the mean of the given samples. The -following tests are performed: - * two-tailed test (null hypothesis - the means are equal) - * left-tailed test (null hypothesis - the mean of the first sample is - greater than or equal to the mean of the second sample) - * right-tailed test (null hypothesis - the mean of the first sample is - less than or equal to the mean of the second sample). - -Test is based on the following assumptions: - * given samples have normal distributions - * dispersions are equal - * samples are independent. - -Input parameters: - X - sample 1. Array whose index goes from 0 to N-1. - N - size of sample. - Y - sample 2. Array whose index goes from 0 to M-1. - M - size of sample. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -NOTE: this function correctly handles degenerate cases: - * when N=0 or M=0, all p-values are set to 1.0 - * when both samples has exactly zero variance, p-values are set - to 1.0 or 0.0, depending on difference between means. - - -- ALGLIB -- - Copyright 18.09.2006 by Bochkanov Sergey -*************************************************************************/ -void studentttest2(const real_1d_array &x, const ae_int_t n, const real_1d_array &y, const ae_int_t m, double &bothtails, double &lefttail, double &righttail, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::studentttest2(const_cast(x.c_ptr()), n, const_cast(y.c_ptr()), m, &bothtails, &lefttail, &righttail, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -Two-sample unpooled test - -This test checks three hypotheses about the mean of the given samples. The -following tests are performed: - * two-tailed test (null hypothesis - the means are equal) - * left-tailed test (null hypothesis - the mean of the first sample is - greater than or equal to the mean of the second sample) - * right-tailed test (null hypothesis - the mean of the first sample is - less than or equal to the mean of the second sample). - -Test is based on the following assumptions: - * given samples have normal distributions - * samples are independent. -Equality of variances is NOT required. - -Input parameters: - X - sample 1. Array whose index goes from 0 to N-1. - N - size of the sample. - Y - sample 2. Array whose index goes from 0 to M-1. - M - size of the sample. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -NOTE: this function correctly handles degenerate cases: - * when N=0 or M=0, all p-values are set to 1.0 - * when both samples has zero variance, p-values are set - to 1.0 or 0.0, depending on difference between means. - * when only one sample has zero variance, test reduces to 1-sample - version. - - -- ALGLIB -- - Copyright 18.09.2006 by Bochkanov Sergey -*************************************************************************/ -void unequalvariancettest(const real_1d_array &x, const ae_int_t n, const real_1d_array &y, const ae_int_t m, double &bothtails, double &lefttail, double &righttail, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::unequalvariancettest(const_cast(x.c_ptr()), n, const_cast(y.c_ptr()), m, &bothtails, &lefttail, &righttail, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_MANNWHITNEYU) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Mann-Whitney U-test - -This test checks hypotheses about whether X and Y are samples of two -continuous distributions of the same shape and same median or whether -their medians are different. - -The following tests are performed: - * two-tailed test (null hypothesis - the medians are equal) - * left-tailed test (null hypothesis - the median of the first sample - is greater than or equal to the median of the second sample) - * right-tailed test (null hypothesis - the median of the first sample - is less than or equal to the median of the second sample). - -Requirements: - * the samples are independent - * X and Y are continuous distributions (or discrete distributions well- - approximating continuous distributions) - * distributions of X and Y have the same shape. The only possible - difference is their position (i.e. the value of the median) - * the number of elements in each sample is not less than 5 - * the scale of measurement should be ordinal, interval or ratio (i.e. - the test could not be applied to nominal variables). - -The test is non-parametric and doesn't require distributions to be normal. - -Input parameters: - X - sample 1. Array whose index goes from 0 to N-1. - N - size of the sample. N>=5 - Y - sample 2. Array whose index goes from 0 to M-1. - M - size of the sample. M>=5 - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -To calculate p-values, special approximation is used. This method lets us -calculate p-values with satisfactory accuracy in interval [0.0001, 1]. -There is no approximation outside the [0.0001, 1] interval. Therefore, if -the significance level outlies this interval, the test returns 0.0001. - -Relative precision of approximation of p-value: - -N M Max.err. Rms.err. -5..10 N..10 1.4e-02 6.0e-04 -5..10 N..100 2.2e-02 5.3e-06 -10..15 N..15 1.0e-02 3.2e-04 -10..15 N..100 1.0e-02 2.2e-05 -15..100 N..100 6.1e-03 2.7e-06 - -For N,M>100 accuracy checks weren't put into practice, but taking into -account characteristics of asymptotic approximation used, precision should -not be sharply different from the values for interval [5, 100]. - -NOTE: P-value approximation was optimized for 0.0001<=p<=0.2500. Thus, - P's outside of this interval are enforced to these bounds. Say, you - may quite often get P equal to exactly 0.25 or 0.0001. - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -void mannwhitneyutest(const real_1d_array &x, const ae_int_t n, const real_1d_array &y, const ae_int_t m, double &bothtails, double &lefttail, double &righttail, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::mannwhitneyutest(const_cast(x.c_ptr()), n, const_cast(y.c_ptr()), m, &bothtails, &lefttail, &righttail, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_JARQUEBERA) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Jarque-Bera test - -This test checks hypotheses about the fact that a given sample X is a -sample of normal random variable. - -Requirements: - * the number of elements in the sample is not less than 5. - -Input parameters: - X - sample. Array whose index goes from 0 to N-1. - N - size of the sample. N>=5 - -Output parameters: - P - p-value for the test - -Accuracy of the approximation used (5<=N<=1951): - -p-value relative error (5<=N<=1951) -[1, 0.1] < 1% -[0.1, 0.01] < 2% -[0.01, 0.001] < 6% -[0.001, 0] wasn't measured - -For N>1951 accuracy wasn't measured but it shouldn't be sharply different -from table values. - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -void jarqueberatest(const real_1d_array &x, const ae_int_t n, double &p, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::jarqueberatest(const_cast(x.c_ptr()), n, &p, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif - -#if defined(AE_COMPILE_VARIANCETESTS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Two-sample F-test - -This test checks three hypotheses about dispersions of the given samples. -The following tests are performed: - * two-tailed test (null hypothesis - the dispersions are equal) - * left-tailed test (null hypothesis - the dispersion of the first - sample is greater than or equal to the dispersion of the second - sample). - * right-tailed test (null hypothesis - the dispersion of the first - sample is less than or equal to the dispersion of the second sample) - -The test is based on the following assumptions: - * the given samples have normal distributions - * the samples are independent. - -Input parameters: - X - sample 1. Array whose index goes from 0 to N-1. - N - sample size. - Y - sample 2. Array whose index goes from 0 to M-1. - M - sample size. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - - -- ALGLIB -- - Copyright 19.09.2006 by Bochkanov Sergey -*************************************************************************/ -void ftest(const real_1d_array &x, const ae_int_t n, const real_1d_array &y, const ae_int_t m, double &bothtails, double &lefttail, double &righttail, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::ftest(const_cast(x.c_ptr()), n, const_cast(y.c_ptr()), m, &bothtails, &lefttail, &righttail, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} - -/************************************************************************* -One-sample chi-square test - -This test checks three hypotheses about the dispersion of the given sample -The following tests are performed: - * two-tailed test (null hypothesis - the dispersion equals the given - number) - * left-tailed test (null hypothesis - the dispersion is greater than - or equal to the given number) - * right-tailed test (null hypothesis - dispersion is less than or - equal to the given number). - -Test is based on the following assumptions: - * the given sample has a normal distribution. - -Input parameters: - X - sample 1. Array whose index goes from 0 to N-1. - N - size of the sample. - Variance - dispersion value to compare with. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - - -- ALGLIB -- - Copyright 19.09.2006 by Bochkanov Sergey -*************************************************************************/ -void onesamplevariancetest(const real_1d_array &x, const ae_int_t n, const double variance, double &bothtails, double &lefttail, double &righttail, const xparams _xparams) -{ - jmp_buf _break_jump; - alglib_impl::ae_state _alglib_env_state; - alglib_impl::ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { -#if !defined(AE_NO_EXCEPTIONS) - _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg); -#else - _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg); - return; -#endif - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( _xparams.flags!=0x0 ) - ae_state_set_flags(&_alglib_env_state, _xparams.flags); - alglib_impl::onesamplevariancetest(const_cast(x.c_ptr()), n, variance, &bothtails, &lefttail, &righttail, &_alglib_env_state); - alglib_impl::ae_state_clear(&_alglib_env_state); - return; -} -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS IMPLEMENTATION OF COMPUTATIONAL CORE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_BASESTAT) || !defined(AE_PARTIAL_BUILD) -static void basestat_rankdatarec(/* Real */ ae_matrix* xy, - ae_int_t i0, - ae_int_t i1, - ae_int_t nfeatures, - ae_bool iscentered, - ae_shared_pool* pool, - ae_int_t basecasecost, - ae_state *_state); -ae_bool _trypexec_basestat_rankdatarec(/* Real */ ae_matrix* xy, - ae_int_t i0, - ae_int_t i1, - ae_int_t nfeatures, - ae_bool iscentered, - ae_shared_pool* pool, - ae_int_t basecasecost, ae_state *_state); -static void basestat_rankdatabasecase(/* Real */ ae_matrix* xy, - ae_int_t i0, - ae_int_t i1, - ae_int_t nfeatures, - ae_bool iscentered, - apbuffers* buf0, - apbuffers* buf1, - ae_state *_state); -ae_bool _trypexec_basestat_rankdatabasecase(/* Real */ ae_matrix* xy, - ae_int_t i0, - ae_int_t i1, - ae_int_t nfeatures, - ae_bool iscentered, - apbuffers* buf0, - apbuffers* buf1, ae_state *_state); - - -#endif -#if defined(AE_COMPILE_WSR) || !defined(AE_PARTIAL_BUILD) -static void wsr_wcheb(double x, - double c, - double* tj, - double* tj1, - double* r, - ae_state *_state); -static double wsr_w5(double s, ae_state *_state); -static double wsr_w6(double s, ae_state *_state); -static double wsr_w7(double s, ae_state *_state); -static double wsr_w8(double s, ae_state *_state); -static double wsr_w9(double s, ae_state *_state); -static double wsr_w10(double s, ae_state *_state); -static double wsr_w11(double s, ae_state *_state); -static double wsr_w12(double s, ae_state *_state); -static double wsr_w13(double s, ae_state *_state); -static double wsr_w14(double s, ae_state *_state); -static double wsr_w15(double s, ae_state *_state); -static double wsr_w16(double s, ae_state *_state); -static double wsr_w17(double s, ae_state *_state); -static double wsr_w18(double s, ae_state *_state); -static double wsr_w19(double s, ae_state *_state); -static double wsr_w20(double s, ae_state *_state); -static double wsr_w21(double s, ae_state *_state); -static double wsr_w22(double s, ae_state *_state); -static double wsr_w23(double s, ae_state *_state); -static double wsr_w24(double s, ae_state *_state); -static double wsr_w25(double s, ae_state *_state); -static double wsr_w26(double s, ae_state *_state); -static double wsr_w27(double s, ae_state *_state); -static double wsr_w28(double s, ae_state *_state); -static double wsr_w29(double s, ae_state *_state); -static double wsr_w30(double s, ae_state *_state); -static double wsr_w40(double s, ae_state *_state); -static double wsr_w60(double s, ae_state *_state); -static double wsr_w120(double s, ae_state *_state); -static double wsr_w200(double s, ae_state *_state); -static double wsr_wsigma(double s, ae_int_t n, ae_state *_state); - - -#endif -#if defined(AE_COMPILE_STEST) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_CORRELATIONTESTS) || !defined(AE_PARTIAL_BUILD) -static double correlationtests_spearmantail5(double s, ae_state *_state); -static double correlationtests_spearmantail6(double s, ae_state *_state); -static double correlationtests_spearmantail7(double s, ae_state *_state); -static double correlationtests_spearmantail8(double s, ae_state *_state); -static double correlationtests_spearmantail9(double s, ae_state *_state); -static double correlationtests_spearmantail(double t, - ae_int_t n, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_STUDENTTTESTS) || !defined(AE_PARTIAL_BUILD) - - -#endif -#if defined(AE_COMPILE_MANNWHITNEYU) || !defined(AE_PARTIAL_BUILD) -static void mannwhitneyu_ucheb(double x, - double c, - double* tj, - double* tj1, - double* r, - ae_state *_state); -static double mannwhitneyu_uninterpolate(double p1, - double p2, - double p3, - ae_int_t n, - ae_state *_state); -static double mannwhitneyu_usigma000(ae_int_t n1, - ae_int_t n2, - ae_state *_state); -static double mannwhitneyu_usigma075(ae_int_t n1, - ae_int_t n2, - ae_state *_state); -static double mannwhitneyu_usigma150(ae_int_t n1, - ae_int_t n2, - ae_state *_state); -static double mannwhitneyu_usigma225(ae_int_t n1, - ae_int_t n2, - ae_state *_state); -static double mannwhitneyu_usigma300(ae_int_t n1, - ae_int_t n2, - ae_state *_state); -static double mannwhitneyu_usigma333(ae_int_t n1, - ae_int_t n2, - ae_state *_state); -static double mannwhitneyu_usigma367(ae_int_t n1, - ae_int_t n2, - ae_state *_state); -static double mannwhitneyu_usigma400(ae_int_t n1, - ae_int_t n2, - ae_state *_state); -static double mannwhitneyu_utbln5n5(double s, ae_state *_state); -static double mannwhitneyu_utbln5n6(double s, ae_state *_state); -static double mannwhitneyu_utbln5n7(double s, ae_state *_state); -static double mannwhitneyu_utbln5n8(double s, ae_state *_state); -static double mannwhitneyu_utbln5n9(double s, ae_state *_state); -static double mannwhitneyu_utbln5n10(double s, ae_state *_state); -static double mannwhitneyu_utbln5n11(double s, ae_state *_state); -static double mannwhitneyu_utbln5n12(double s, ae_state *_state); -static double mannwhitneyu_utbln5n13(double s, ae_state *_state); -static double mannwhitneyu_utbln5n14(double s, ae_state *_state); -static double mannwhitneyu_utbln5n15(double s, ae_state *_state); -static double mannwhitneyu_utbln5n16(double s, ae_state *_state); -static double mannwhitneyu_utbln5n17(double s, ae_state *_state); -static double mannwhitneyu_utbln5n18(double s, ae_state *_state); -static double mannwhitneyu_utbln5n19(double s, ae_state *_state); -static double mannwhitneyu_utbln5n20(double s, ae_state *_state); -static double mannwhitneyu_utbln5n21(double s, ae_state *_state); -static double mannwhitneyu_utbln5n22(double s, ae_state *_state); -static double mannwhitneyu_utbln5n23(double s, ae_state *_state); -static double mannwhitneyu_utbln5n24(double s, ae_state *_state); -static double mannwhitneyu_utbln5n25(double s, ae_state *_state); -static double mannwhitneyu_utbln5n26(double s, ae_state *_state); -static double mannwhitneyu_utbln5n27(double s, ae_state *_state); -static double mannwhitneyu_utbln5n28(double s, ae_state *_state); -static double mannwhitneyu_utbln5n29(double s, ae_state *_state); -static double mannwhitneyu_utbln5n30(double s, ae_state *_state); -static double mannwhitneyu_utbln5n100(double s, ae_state *_state); -static double mannwhitneyu_utbln6n6(double s, ae_state *_state); -static double mannwhitneyu_utbln6n7(double s, ae_state *_state); -static double mannwhitneyu_utbln6n8(double s, ae_state *_state); -static double mannwhitneyu_utbln6n9(double s, ae_state *_state); -static double mannwhitneyu_utbln6n10(double s, ae_state *_state); -static double mannwhitneyu_utbln6n11(double s, ae_state *_state); -static double mannwhitneyu_utbln6n12(double s, ae_state *_state); -static double mannwhitneyu_utbln6n13(double s, ae_state *_state); -static double mannwhitneyu_utbln6n14(double s, ae_state *_state); -static double mannwhitneyu_utbln6n15(double s, ae_state *_state); -static double mannwhitneyu_utbln6n30(double s, ae_state *_state); -static double mannwhitneyu_utbln6n100(double s, ae_state *_state); -static double mannwhitneyu_utbln7n7(double s, ae_state *_state); -static double mannwhitneyu_utbln7n8(double s, ae_state *_state); -static double mannwhitneyu_utbln7n9(double s, ae_state *_state); -static double mannwhitneyu_utbln7n10(double s, ae_state *_state); -static double mannwhitneyu_utbln7n11(double s, ae_state *_state); -static double mannwhitneyu_utbln7n12(double s, ae_state *_state); -static double mannwhitneyu_utbln7n13(double s, ae_state *_state); -static double mannwhitneyu_utbln7n14(double s, ae_state *_state); -static double mannwhitneyu_utbln7n15(double s, ae_state *_state); -static double mannwhitneyu_utbln7n30(double s, ae_state *_state); -static double mannwhitneyu_utbln7n100(double s, ae_state *_state); -static double mannwhitneyu_utbln8n8(double s, ae_state *_state); -static double mannwhitneyu_utbln8n9(double s, ae_state *_state); -static double mannwhitneyu_utbln8n10(double s, ae_state *_state); -static double mannwhitneyu_utbln8n11(double s, ae_state *_state); -static double mannwhitneyu_utbln8n12(double s, ae_state *_state); -static double mannwhitneyu_utbln8n13(double s, ae_state *_state); -static double mannwhitneyu_utbln8n14(double s, ae_state *_state); -static double mannwhitneyu_utbln8n15(double s, ae_state *_state); -static double mannwhitneyu_utbln8n30(double s, ae_state *_state); -static double mannwhitneyu_utbln8n100(double s, ae_state *_state); -static double mannwhitneyu_utbln9n9(double s, ae_state *_state); -static double mannwhitneyu_utbln9n10(double s, ae_state *_state); -static double mannwhitneyu_utbln9n11(double s, ae_state *_state); -static double mannwhitneyu_utbln9n12(double s, ae_state *_state); -static double mannwhitneyu_utbln9n13(double s, ae_state *_state); -static double mannwhitneyu_utbln9n14(double s, ae_state *_state); -static double mannwhitneyu_utbln9n15(double s, ae_state *_state); -static double mannwhitneyu_utbln9n30(double s, ae_state *_state); -static double mannwhitneyu_utbln9n100(double s, ae_state *_state); -static double mannwhitneyu_utbln10n10(double s, ae_state *_state); -static double mannwhitneyu_utbln10n11(double s, ae_state *_state); -static double mannwhitneyu_utbln10n12(double s, ae_state *_state); -static double mannwhitneyu_utbln10n13(double s, ae_state *_state); -static double mannwhitneyu_utbln10n14(double s, ae_state *_state); -static double mannwhitneyu_utbln10n15(double s, ae_state *_state); -static double mannwhitneyu_utbln10n30(double s, ae_state *_state); -static double mannwhitneyu_utbln10n100(double s, ae_state *_state); -static double mannwhitneyu_utbln11n11(double s, ae_state *_state); -static double mannwhitneyu_utbln11n12(double s, ae_state *_state); -static double mannwhitneyu_utbln11n13(double s, ae_state *_state); -static double mannwhitneyu_utbln11n14(double s, ae_state *_state); -static double mannwhitneyu_utbln11n15(double s, ae_state *_state); -static double mannwhitneyu_utbln11n30(double s, ae_state *_state); -static double mannwhitneyu_utbln11n100(double s, ae_state *_state); -static double mannwhitneyu_utbln12n12(double s, ae_state *_state); -static double mannwhitneyu_utbln12n13(double s, ae_state *_state); -static double mannwhitneyu_utbln12n14(double s, ae_state *_state); -static double mannwhitneyu_utbln12n15(double s, ae_state *_state); -static double mannwhitneyu_utbln12n30(double s, ae_state *_state); -static double mannwhitneyu_utbln12n100(double s, ae_state *_state); -static double mannwhitneyu_utbln13n13(double s, ae_state *_state); -static double mannwhitneyu_utbln13n14(double s, ae_state *_state); -static double mannwhitneyu_utbln13n15(double s, ae_state *_state); -static double mannwhitneyu_utbln13n30(double s, ae_state *_state); -static double mannwhitneyu_utbln13n100(double s, ae_state *_state); -static double mannwhitneyu_utbln14n14(double s, ae_state *_state); -static double mannwhitneyu_utbln14n15(double s, ae_state *_state); -static double mannwhitneyu_utbln14n30(double s, ae_state *_state); -static double mannwhitneyu_utbln14n100(double s, ae_state *_state); -static double mannwhitneyu_usigma(double s, - ae_int_t n1, - ae_int_t n2, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_JARQUEBERA) || !defined(AE_PARTIAL_BUILD) -static void jarquebera_jarqueberastatistic(/* Real */ ae_vector* x, - ae_int_t n, - double* s, - ae_state *_state); -static double jarquebera_jarqueberaapprox(ae_int_t n, - double s, - ae_state *_state); -static double jarquebera_jbtbl5(double s, ae_state *_state); -static double jarquebera_jbtbl6(double s, ae_state *_state); -static double jarquebera_jbtbl7(double s, ae_state *_state); -static double jarquebera_jbtbl8(double s, ae_state *_state); -static double jarquebera_jbtbl9(double s, ae_state *_state); -static double jarquebera_jbtbl10(double s, ae_state *_state); -static double jarquebera_jbtbl11(double s, ae_state *_state); -static double jarquebera_jbtbl12(double s, ae_state *_state); -static double jarquebera_jbtbl13(double s, ae_state *_state); -static double jarquebera_jbtbl14(double s, ae_state *_state); -static double jarquebera_jbtbl15(double s, ae_state *_state); -static double jarquebera_jbtbl16(double s, ae_state *_state); -static double jarquebera_jbtbl17(double s, ae_state *_state); -static double jarquebera_jbtbl18(double s, ae_state *_state); -static double jarquebera_jbtbl19(double s, ae_state *_state); -static double jarquebera_jbtbl20(double s, ae_state *_state); -static double jarquebera_jbtbl30(double s, ae_state *_state); -static double jarquebera_jbtbl50(double s, ae_state *_state); -static double jarquebera_jbtbl65(double s, ae_state *_state); -static double jarquebera_jbtbl100(double s, ae_state *_state); -static double jarquebera_jbtbl130(double s, ae_state *_state); -static double jarquebera_jbtbl200(double s, ae_state *_state); -static double jarquebera_jbtbl301(double s, ae_state *_state); -static double jarquebera_jbtbl501(double s, ae_state *_state); -static double jarquebera_jbtbl701(double s, ae_state *_state); -static double jarquebera_jbtbl1401(double s, ae_state *_state); -static void jarquebera_jbcheb(double x, - double c, - double* tj, - double* tj1, - double* r, - ae_state *_state); - - -#endif -#if defined(AE_COMPILE_VARIANCETESTS) || !defined(AE_PARTIAL_BUILD) - - -#endif - -#if defined(AE_COMPILE_BASESTAT) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Calculation of the distribution moments: mean, variance, skewness, kurtosis. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -OUTPUT PARAMETERS - Mean - mean. - Variance- variance. - Skewness- skewness (if variance<>0; zero otherwise). - Kurtosis- kurtosis (if variance<>0; zero otherwise). - -NOTE: variance is calculated by dividing sum of squares by N-1, not N. - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -void samplemoments(/* Real */ ae_vector* x, - ae_int_t n, - double* mean, - double* variance, - double* skewness, - double* kurtosis, - ae_state *_state) -{ - ae_int_t i; - double v; - double v1; - double v2; - double stddev; - - *mean = 0; - *variance = 0; - *skewness = 0; - *kurtosis = 0; - - ae_assert(n>=0, "SampleMoments: N<0", _state); - ae_assert(x->cnt>=n, "SampleMoments: Length(X)ptr.p_double[i]; - } - *mean = *mean/n; - - /* - * Variance (using corrected two-pass algorithm) - */ - if( n!=1 ) - { - v1 = (double)(0); - for(i=0; i<=n-1; i++) - { - v1 = v1+ae_sqr(x->ptr.p_double[i]-(*mean), _state); - } - v2 = (double)(0); - for(i=0; i<=n-1; i++) - { - v2 = v2+(x->ptr.p_double[i]-(*mean)); - } - v2 = ae_sqr(v2, _state)/n; - *variance = (v1-v2)/(n-1); - if( ae_fp_less(*variance,(double)(0)) ) - { - *variance = (double)(0); - } - stddev = ae_sqrt(*variance, _state); - } - - /* - * Skewness and kurtosis - */ - if( ae_fp_neq(stddev,(double)(0)) ) - { - for(i=0; i<=n-1; i++) - { - v = (x->ptr.p_double[i]-(*mean))/stddev; - v2 = ae_sqr(v, _state); - *skewness = *skewness+v2*v; - *kurtosis = *kurtosis+ae_sqr(v2, _state); - } - *skewness = *skewness/n; - *kurtosis = *kurtosis/n-3; - } -} - - -/************************************************************************* -Calculation of the mean. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -NOTE: - -This function return result which calculated by 'SampleMoments' function -and stored at 'Mean' variable. - - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -double samplemean(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state) -{ - double mean; - double tmp0; - double tmp1; - double tmp2; - double result; - - - samplemoments(x, n, &mean, &tmp0, &tmp1, &tmp2, _state); - result = mean; - return result; -} - - -/************************************************************************* -Calculation of the variance. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -NOTE: - -This function return result which calculated by 'SampleMoments' function -and stored at 'Variance' variable. - - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -double samplevariance(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state) -{ - double variance; - double tmp0; - double tmp1; - double tmp2; - double result; - - - samplemoments(x, n, &tmp0, &variance, &tmp1, &tmp2, _state); - result = variance; - return result; -} - - -/************************************************************************* -Calculation of the skewness. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -NOTE: - -This function return result which calculated by 'SampleMoments' function -and stored at 'Skewness' variable. - - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -double sampleskewness(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state) -{ - double skewness; - double tmp0; - double tmp1; - double tmp2; - double result; - - - samplemoments(x, n, &tmp0, &tmp1, &skewness, &tmp2, _state); - result = skewness; - return result; -} - - -/************************************************************************* -Calculation of the kurtosis. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -NOTE: - -This function return result which calculated by 'SampleMoments' function -and stored at 'Kurtosis' variable. - - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -double samplekurtosis(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state) -{ - double kurtosis; - double tmp0; - double tmp1; - double tmp2; - double result; - - - samplemoments(x, n, &tmp0, &tmp1, &tmp2, &kurtosis, _state); - result = kurtosis; - return result; -} - - -/************************************************************************* -ADev - -Input parameters: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -Output parameters: - ADev- ADev - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -void sampleadev(/* Real */ ae_vector* x, - ae_int_t n, - double* adev, - ae_state *_state) -{ - ae_int_t i; - double mean; - - *adev = 0; - - ae_assert(n>=0, "SampleADev: N<0", _state); - ae_assert(x->cnt>=n, "SampleADev: Length(X)ptr.p_double[i]; - } - mean = mean/n; - - /* - * ADev - */ - for(i=0; i<=n-1; i++) - { - *adev = *adev+ae_fabs(x->ptr.p_double[i]-mean, _state); - } - *adev = *adev/n; -} - - -/************************************************************************* -Median calculation. - -Input parameters: - X - sample (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -Output parameters: - Median - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -void samplemedian(/* Real */ ae_vector* x, - ae_int_t n, - double* median, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_int_t i; - ae_int_t ir; - ae_int_t j; - ae_int_t l; - ae_int_t midp; - ae_int_t k; - double a; - double tval; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - *median = 0; - - ae_assert(n>=0, "SampleMedian: N<0", _state); - ae_assert(x->cnt>=n, "SampleMedian: Length(X)ptr.p_double[0]; - ae_frame_leave(_state); - return; - } - if( n==2 ) - { - *median = 0.5*(x->ptr.p_double[0]+x->ptr.p_double[1]); - ae_frame_leave(_state); - return; - } - - /* - * Common case, N>=3. - * Choose X[(N-1)/2] - */ - l = 0; - ir = n-1; - k = (n-1)/2; - for(;;) - { - if( ir<=l+1 ) - { - - /* - * 1 or 2 elements in partition - */ - if( ir==l+1&&ae_fp_less(x->ptr.p_double[ir],x->ptr.p_double[l]) ) - { - tval = x->ptr.p_double[l]; - x->ptr.p_double[l] = x->ptr.p_double[ir]; - x->ptr.p_double[ir] = tval; - } - break; - } - else - { - midp = (l+ir)/2; - tval = x->ptr.p_double[midp]; - x->ptr.p_double[midp] = x->ptr.p_double[l+1]; - x->ptr.p_double[l+1] = tval; - if( ae_fp_greater(x->ptr.p_double[l],x->ptr.p_double[ir]) ) - { - tval = x->ptr.p_double[l]; - x->ptr.p_double[l] = x->ptr.p_double[ir]; - x->ptr.p_double[ir] = tval; - } - if( ae_fp_greater(x->ptr.p_double[l+1],x->ptr.p_double[ir]) ) - { - tval = x->ptr.p_double[l+1]; - x->ptr.p_double[l+1] = x->ptr.p_double[ir]; - x->ptr.p_double[ir] = tval; - } - if( ae_fp_greater(x->ptr.p_double[l],x->ptr.p_double[l+1]) ) - { - tval = x->ptr.p_double[l]; - x->ptr.p_double[l] = x->ptr.p_double[l+1]; - x->ptr.p_double[l+1] = tval; - } - i = l+1; - j = ir; - a = x->ptr.p_double[l+1]; - for(;;) - { - do - { - i = i+1; - } - while(ae_fp_less(x->ptr.p_double[i],a)); - do - { - j = j-1; - } - while(ae_fp_greater(x->ptr.p_double[j],a)); - if( jptr.p_double[i]; - x->ptr.p_double[i] = x->ptr.p_double[j]; - x->ptr.p_double[j] = tval; - } - x->ptr.p_double[l+1] = x->ptr.p_double[j]; - x->ptr.p_double[j] = a; - if( j>=k ) - { - ir = j-1; - } - if( j<=k ) - { - l = i; - } - } - } - - /* - * If N is odd, return result - */ - if( n%2==1 ) - { - *median = x->ptr.p_double[k]; - ae_frame_leave(_state); - return; - } - a = x->ptr.p_double[n-1]; - for(i=k+1; i<=n-1; i++) - { - if( ae_fp_less(x->ptr.p_double[i],a) ) - { - a = x->ptr.p_double[i]; - } - } - *median = 0.5*(x->ptr.p_double[k]+a); - ae_frame_leave(_state); -} - - -/************************************************************************* -Percentile calculation. - -Input parameters: - X - sample (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - P - percentile (0<=P<=1) - -Output parameters: - V - percentile - - -- ALGLIB -- - Copyright 01.03.2008 by Bochkanov Sergey -*************************************************************************/ -void samplepercentile(/* Real */ ae_vector* x, - ae_int_t n, - double p, - double* v, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_int_t i1; - double t; - ae_vector rbuf; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&rbuf, 0, sizeof(rbuf)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - *v = 0; - ae_vector_init(&rbuf, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=0, "SamplePercentile: N<0", _state); - ae_assert(x->cnt>=n, "SamplePercentile: Length(X)ptr.p_double[0]; - ae_frame_leave(_state); - return; - } - if( ae_fp_eq(p,(double)(1)) ) - { - *v = x->ptr.p_double[n-1]; - ae_frame_leave(_state); - return; - } - t = p*(n-1); - i1 = ae_ifloor(t, _state); - t = t-ae_ifloor(t, _state); - *v = x->ptr.p_double[i1]*(1-t)+x->ptr.p_double[i1+1]*t; - ae_frame_leave(_state); -} - - -/************************************************************************* -2-sample covariance - -Input parameters: - X - sample 1 (array indexes: [0..N-1]) - Y - sample 2 (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only N leading elements of X/Y are processed - * if not given, automatically determined from input sizes - -Result: - covariance (zero for N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -double cov2(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - double xmean; - double ymean; - double v; - double x0; - double y0; - double s; - ae_bool samex; - ae_bool samey; - double result; - - - ae_assert(n>=0, "Cov2: N<0", _state); - ae_assert(x->cnt>=n, "Cov2: Length(X)cnt>=n, "Cov2: Length(Y)ptr.p_double[0]; - y0 = y->ptr.p_double[0]; - v = (double)1/(double)n; - for(i=0; i<=n-1; i++) - { - s = x->ptr.p_double[i]; - samex = samex&&ae_fp_eq(s,x0); - xmean = xmean+s*v; - s = y->ptr.p_double[i]; - samey = samey&&ae_fp_eq(s,y0); - ymean = ymean+s*v; - } - if( samex||samey ) - { - result = (double)(0); - return result; - } - - /* - * covariance - */ - v = (double)1/(double)(n-1); - result = (double)(0); - for(i=0; i<=n-1; i++) - { - result = result+v*(x->ptr.p_double[i]-xmean)*(y->ptr.p_double[i]-ymean); - } - return result; -} - - -/************************************************************************* -Pearson product-moment correlation coefficient - -Input parameters: - X - sample 1 (array indexes: [0..N-1]) - Y - sample 2 (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only N leading elements of X/Y are processed - * if not given, automatically determined from input sizes - -Result: - Pearson product-moment correlation coefficient - (zero for N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -double pearsoncorr2(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - double xmean; - double ymean; - double v; - double x0; - double y0; - double s; - ae_bool samex; - ae_bool samey; - double xv; - double yv; - double t1; - double t2; - double result; - - - ae_assert(n>=0, "PearsonCorr2: N<0", _state); - ae_assert(x->cnt>=n, "PearsonCorr2: Length(X)cnt>=n, "PearsonCorr2: Length(Y)ptr.p_double[0]; - y0 = y->ptr.p_double[0]; - v = (double)1/(double)n; - for(i=0; i<=n-1; i++) - { - s = x->ptr.p_double[i]; - samex = samex&&ae_fp_eq(s,x0); - xmean = xmean+s*v; - s = y->ptr.p_double[i]; - samey = samey&&ae_fp_eq(s,y0); - ymean = ymean+s*v; - } - if( samex||samey ) - { - result = (double)(0); - return result; - } - - /* - * numerator and denominator - */ - s = (double)(0); - xv = (double)(0); - yv = (double)(0); - for(i=0; i<=n-1; i++) - { - t1 = x->ptr.p_double[i]-xmean; - t2 = y->ptr.p_double[i]-ymean; - xv = xv+ae_sqr(t1, _state); - yv = yv+ae_sqr(t2, _state); - s = s+t1*t2; - } - if( ae_fp_eq(xv,(double)(0))||ae_fp_eq(yv,(double)(0)) ) - { - result = (double)(0); - } - else - { - result = s/(ae_sqrt(xv, _state)*ae_sqrt(yv, _state)); - } - return result; -} - - -/************************************************************************* -Spearman's rank correlation coefficient - -Input parameters: - X - sample 1 (array indexes: [0..N-1]) - Y - sample 2 (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only N leading elements of X/Y are processed - * if not given, automatically determined from input sizes - -Result: - Spearman's rank correlation coefficient - (zero for N=0 or N=1) - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -double spearmancorr2(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_vector _y; - apbuffers buf; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - memset(&buf, 0, sizeof(buf)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_vector_init_copy(&_y, y, _state, ae_true); - y = &_y; - _apbuffers_init(&buf, _state, ae_true); - - ae_assert(n>=0, "SpearmanCorr2: N<0", _state); - ae_assert(x->cnt>=n, "SpearmanCorr2: Length(X)cnt>=n, "SpearmanCorr2: Length(Y)=0, number of observations: - * if given, only leading N rows of X are used - * if not given, automatically determined from input size - M - M>0, number of variables: - * if given, only leading M columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M,M], covariance matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -void covm(/* Real */ ae_matrix* x, - ae_int_t n, - ae_int_t m, - /* Real */ ae_matrix* c, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _x; - ae_int_t i; - ae_int_t j; - double v; - ae_vector t; - ae_vector x0; - ae_vector same; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&t, 0, sizeof(t)); - memset(&x0, 0, sizeof(x0)); - memset(&same, 0, sizeof(same)); - ae_matrix_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_matrix_clear(c); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&same, 0, DT_BOOL, _state, ae_true); - - ae_assert(n>=0, "CovM: N<0", _state); - ae_assert(m>=1, "CovM: M<1", _state); - ae_assert(x->rows>=n, "CovM: Rows(X)cols>=m||n==0, "CovM: Cols(X)ptr.pp_double[i][j] = (double)(0); - } - } - ae_frame_leave(_state); - return; - } - - /* - * Calculate means, - * check for constant columns - */ - ae_vector_set_length(&t, m, _state); - ae_vector_set_length(&x0, m, _state); - ae_vector_set_length(&same, m, _state); - ae_matrix_set_length(c, m, m, _state); - for(i=0; i<=m-1; i++) - { - t.ptr.p_double[i] = (double)(0); - same.ptr.p_bool[i] = ae_true; - } - ae_v_move(&x0.ptr.p_double[0], 1, &x->ptr.pp_double[0][0], 1, ae_v_len(0,m-1)); - v = (double)1/(double)n; - for(i=0; i<=n-1; i++) - { - ae_v_addd(&t.ptr.p_double[0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v); - for(j=0; j<=m-1; j++) - { - same.ptr.p_bool[j] = same.ptr.p_bool[j]&&ae_fp_eq(x->ptr.pp_double[i][j],x0.ptr.p_double[j]); - } - } - - /* - * * center variables; - * * if we have constant columns, these columns are - * artificially zeroed (they must be zero in exact arithmetics, - * but unfortunately floating point ops are not exact). - * * calculate upper half of symmetric covariance matrix - */ - for(i=0; i<=n-1; i++) - { - ae_v_sub(&x->ptr.pp_double[i][0], 1, &t.ptr.p_double[0], 1, ae_v_len(0,m-1)); - for(j=0; j<=m-1; j++) - { - if( same.ptr.p_bool[j] ) - { - x->ptr.pp_double[i][j] = (double)(0); - } - } - } - rmatrixsyrk(m, n, (double)1/(double)(n-1), x, 0, 0, 1, 0.0, c, 0, 0, ae_true, _state); - rmatrixenforcesymmetricity(c, m, ae_true, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Pearson product-moment correlation matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X are used - * if not given, automatically determined from input size - M - M>0, number of variables: - * if given, only leading M columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M,M], correlation matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -void pearsoncorrm(/* Real */ ae_matrix* x, - ae_int_t n, - ae_int_t m, - /* Real */ ae_matrix* c, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector t; - ae_int_t i; - ae_int_t j; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&t, 0, sizeof(t)); - ae_matrix_clear(c); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=0, "PearsonCorrM: N<0", _state); - ae_assert(m>=1, "PearsonCorrM: M<1", _state); - ae_assert(x->rows>=n, "PearsonCorrM: Rows(X)cols>=m||n==0, "PearsonCorrM: Cols(X)ptr.pp_double[i][i],(double)(0)) ) - { - t.ptr.p_double[i] = 1/ae_sqrt(c->ptr.pp_double[i][i], _state); - } - else - { - t.ptr.p_double[i] = 0.0; - } - } - for(i=0; i<=m-1; i++) - { - v = t.ptr.p_double[i]; - for(j=0; j<=m-1; j++) - { - c->ptr.pp_double[i][j] = c->ptr.pp_double[i][j]*v*t.ptr.p_double[j]; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Spearman's rank correlation matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X are used - * if not given, automatically determined from input size - M - M>0, number of variables: - * if given, only leading M columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M,M], correlation matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -void spearmancorrm(/* Real */ ae_matrix* x, - ae_int_t n, - ae_int_t m, - /* Real */ ae_matrix* c, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - apbuffers buf; - ae_matrix xc; - ae_vector t; - double v; - double vv; - double x0; - ae_bool b; - - ae_frame_make(_state, &_frame_block); - memset(&buf, 0, sizeof(buf)); - memset(&xc, 0, sizeof(xc)); - memset(&t, 0, sizeof(t)); - ae_matrix_clear(c); - _apbuffers_init(&buf, _state, ae_true); - ae_matrix_init(&xc, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - - ae_assert(n>=0, "SpearmanCorrM: N<0", _state); - ae_assert(m>=1, "SpearmanCorrM: M<1", _state); - ae_assert(x->rows>=n, "SpearmanCorrM: Rows(X)cols>=m||n==0, "SpearmanCorrM: Cols(X)ptr.pp_double[i][j] = (double)(0); - } - } - ae_frame_leave(_state); - return; - } - - /* - * Allocate - */ - ae_vector_set_length(&t, ae_maxint(n, m, _state), _state); - ae_matrix_set_length(c, m, m, _state); - - /* - * Replace data with ranks - */ - ae_matrix_set_length(&xc, m, n, _state); - rmatrixtranspose(n, m, x, 0, 0, &xc, 0, 0, _state); - rankdata(&xc, m, n, _state); - - /* - * 1. Calculate means, check for constant columns - * 2. Center variables, constant columns are - * artificialy zeroed (they must be zero in exact arithmetics, - * but unfortunately floating point is not exact). - */ - for(i=0; i<=m-1; i++) - { - - /* - * Calculate: - * * V - mean value of I-th variable - * * B - True in case all variable values are same - */ - v = (double)(0); - b = ae_true; - x0 = xc.ptr.pp_double[i][0]; - for(j=0; j<=n-1; j++) - { - vv = xc.ptr.pp_double[i][j]; - v = v+vv; - b = b&&ae_fp_eq(vv,x0); - } - v = v/n; - - /* - * Center/zero I-th variable - */ - if( b ) - { - - /* - * Zero - */ - for(j=0; j<=n-1; j++) - { - xc.ptr.pp_double[i][j] = 0.0; - } - } - else - { - - /* - * Center - */ - for(j=0; j<=n-1; j++) - { - xc.ptr.pp_double[i][j] = xc.ptr.pp_double[i][j]-v; - } - } - } - - /* - * Calculate upper half of symmetric covariance matrix - */ - rmatrixsyrk(m, n, (double)1/(double)(n-1), &xc, 0, 0, 0, 0.0, c, 0, 0, ae_true, _state); - - /* - * Calculate Pearson coefficients (upper triangle) - */ - for(i=0; i<=m-1; i++) - { - if( ae_fp_greater(c->ptr.pp_double[i][i],(double)(0)) ) - { - t.ptr.p_double[i] = 1/ae_sqrt(c->ptr.pp_double[i][i], _state); - } - else - { - t.ptr.p_double[i] = 0.0; - } - } - for(i=0; i<=m-1; i++) - { - v = t.ptr.p_double[i]; - for(j=i; j<=m-1; j++) - { - c->ptr.pp_double[i][j] = c->ptr.pp_double[i][j]*v*t.ptr.p_double[j]; - } - } - - /* - * force symmetricity - */ - rmatrixenforcesymmetricity(c, m, ae_true, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Cross-covariance matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M1], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - Y - array[N,M2], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X/Y are used - * if not given, automatically determined from input sizes - M1 - M1>0, number of variables in X: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - M2 - M2>0, number of variables in Y: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M1,M2], cross-covariance matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -void covm2(/* Real */ ae_matrix* x, - /* Real */ ae_matrix* y, - ae_int_t n, - ae_int_t m1, - ae_int_t m2, - /* Real */ ae_matrix* c, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _x; - ae_matrix _y; - ae_int_t i; - ae_int_t j; - double v; - ae_vector t; - ae_vector x0; - ae_vector y0; - ae_vector samex; - ae_vector samey; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - memset(&t, 0, sizeof(t)); - memset(&x0, 0, sizeof(x0)); - memset(&y0, 0, sizeof(y0)); - memset(&samex, 0, sizeof(samex)); - memset(&samey, 0, sizeof(samey)); - ae_matrix_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_matrix_init_copy(&_y, y, _state, ae_true); - y = &_y; - ae_matrix_clear(c); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&samex, 0, DT_BOOL, _state, ae_true); - ae_vector_init(&samey, 0, DT_BOOL, _state, ae_true); - - ae_assert(n>=0, "CovM2: N<0", _state); - ae_assert(m1>=1, "CovM2: M1<1", _state); - ae_assert(m2>=1, "CovM2: M2<1", _state); - ae_assert(x->rows>=n, "CovM2: Rows(X)cols>=m1||n==0, "CovM2: Cols(X)rows>=n, "CovM2: Rows(Y)cols>=m2||n==0, "CovM2: Cols(Y)ptr.pp_double[i][j] = (double)(0); - } - } - ae_frame_leave(_state); - return; - } - - /* - * Allocate - */ - ae_vector_set_length(&t, ae_maxint(m1, m2, _state), _state); - ae_vector_set_length(&x0, m1, _state); - ae_vector_set_length(&y0, m2, _state); - ae_vector_set_length(&samex, m1, _state); - ae_vector_set_length(&samey, m2, _state); - ae_matrix_set_length(c, m1, m2, _state); - - /* - * * calculate means of X - * * center X - * * if we have constant columns, these columns are - * artificially zeroed (they must be zero in exact arithmetics, - * but unfortunately floating point ops are not exact). - */ - for(i=0; i<=m1-1; i++) - { - t.ptr.p_double[i] = (double)(0); - samex.ptr.p_bool[i] = ae_true; - } - ae_v_move(&x0.ptr.p_double[0], 1, &x->ptr.pp_double[0][0], 1, ae_v_len(0,m1-1)); - v = (double)1/(double)n; - for(i=0; i<=n-1; i++) - { - ae_v_addd(&t.ptr.p_double[0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m1-1), v); - for(j=0; j<=m1-1; j++) - { - samex.ptr.p_bool[j] = samex.ptr.p_bool[j]&&ae_fp_eq(x->ptr.pp_double[i][j],x0.ptr.p_double[j]); - } - } - for(i=0; i<=n-1; i++) - { - ae_v_sub(&x->ptr.pp_double[i][0], 1, &t.ptr.p_double[0], 1, ae_v_len(0,m1-1)); - for(j=0; j<=m1-1; j++) - { - if( samex.ptr.p_bool[j] ) - { - x->ptr.pp_double[i][j] = (double)(0); - } - } - } - - /* - * Repeat same steps for Y - */ - for(i=0; i<=m2-1; i++) - { - t.ptr.p_double[i] = (double)(0); - samey.ptr.p_bool[i] = ae_true; - } - ae_v_move(&y0.ptr.p_double[0], 1, &y->ptr.pp_double[0][0], 1, ae_v_len(0,m2-1)); - v = (double)1/(double)n; - for(i=0; i<=n-1; i++) - { - ae_v_addd(&t.ptr.p_double[0], 1, &y->ptr.pp_double[i][0], 1, ae_v_len(0,m2-1), v); - for(j=0; j<=m2-1; j++) - { - samey.ptr.p_bool[j] = samey.ptr.p_bool[j]&&ae_fp_eq(y->ptr.pp_double[i][j],y0.ptr.p_double[j]); - } - } - for(i=0; i<=n-1; i++) - { - ae_v_sub(&y->ptr.pp_double[i][0], 1, &t.ptr.p_double[0], 1, ae_v_len(0,m2-1)); - for(j=0; j<=m2-1; j++) - { - if( samey.ptr.p_bool[j] ) - { - y->ptr.pp_double[i][j] = (double)(0); - } - } - } - - /* - * calculate cross-covariance matrix - */ - rmatrixgemm(m1, m2, n, (double)1/(double)(n-1), x, 0, 0, 1, y, 0, 0, 0, 0.0, c, 0, 0, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Pearson product-moment cross-correlation matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M1], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - Y - array[N,M2], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X/Y are used - * if not given, automatically determined from input sizes - M1 - M1>0, number of variables in X: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - M2 - M2>0, number of variables in Y: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M1,M2], cross-correlation matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -void pearsoncorrm2(/* Real */ ae_matrix* x, - /* Real */ ae_matrix* y, - ae_int_t n, - ae_int_t m1, - ae_int_t m2, - /* Real */ ae_matrix* c, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _x; - ae_matrix _y; - ae_int_t i; - ae_int_t j; - double v; - ae_vector t; - ae_vector x0; - ae_vector y0; - ae_vector sx; - ae_vector sy; - ae_vector samex; - ae_vector samey; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&_y, 0, sizeof(_y)); - memset(&t, 0, sizeof(t)); - memset(&x0, 0, sizeof(x0)); - memset(&y0, 0, sizeof(y0)); - memset(&sx, 0, sizeof(sx)); - memset(&sy, 0, sizeof(sy)); - memset(&samex, 0, sizeof(samex)); - memset(&samey, 0, sizeof(samey)); - ae_matrix_init_copy(&_x, x, _state, ae_true); - x = &_x; - ae_matrix_init_copy(&_y, y, _state, ae_true); - y = &_y; - ae_matrix_clear(c); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sy, 0, DT_REAL, _state, ae_true); - ae_vector_init(&samex, 0, DT_BOOL, _state, ae_true); - ae_vector_init(&samey, 0, DT_BOOL, _state, ae_true); - - ae_assert(n>=0, "PearsonCorrM2: N<0", _state); - ae_assert(m1>=1, "PearsonCorrM2: M1<1", _state); - ae_assert(m2>=1, "PearsonCorrM2: M2<1", _state); - ae_assert(x->rows>=n, "PearsonCorrM2: Rows(X)cols>=m1||n==0, "PearsonCorrM2: Cols(X)rows>=n, "PearsonCorrM2: Rows(Y)cols>=m2||n==0, "PearsonCorrM2: Cols(Y)ptr.pp_double[i][j] = (double)(0); - } - } - ae_frame_leave(_state); - return; - } - - /* - * Allocate - */ - ae_vector_set_length(&t, ae_maxint(m1, m2, _state), _state); - ae_vector_set_length(&x0, m1, _state); - ae_vector_set_length(&y0, m2, _state); - ae_vector_set_length(&sx, m1, _state); - ae_vector_set_length(&sy, m2, _state); - ae_vector_set_length(&samex, m1, _state); - ae_vector_set_length(&samey, m2, _state); - ae_matrix_set_length(c, m1, m2, _state); - - /* - * * calculate means of X - * * center X - * * if we have constant columns, these columns are - * artificially zeroed (they must be zero in exact arithmetics, - * but unfortunately floating point ops are not exact). - * * calculate column variances - */ - for(i=0; i<=m1-1; i++) - { - t.ptr.p_double[i] = (double)(0); - samex.ptr.p_bool[i] = ae_true; - sx.ptr.p_double[i] = (double)(0); - } - ae_v_move(&x0.ptr.p_double[0], 1, &x->ptr.pp_double[0][0], 1, ae_v_len(0,m1-1)); - v = (double)1/(double)n; - for(i=0; i<=n-1; i++) - { - ae_v_addd(&t.ptr.p_double[0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m1-1), v); - for(j=0; j<=m1-1; j++) - { - samex.ptr.p_bool[j] = samex.ptr.p_bool[j]&&ae_fp_eq(x->ptr.pp_double[i][j],x0.ptr.p_double[j]); - } - } - for(i=0; i<=n-1; i++) - { - ae_v_sub(&x->ptr.pp_double[i][0], 1, &t.ptr.p_double[0], 1, ae_v_len(0,m1-1)); - for(j=0; j<=m1-1; j++) - { - if( samex.ptr.p_bool[j] ) - { - x->ptr.pp_double[i][j] = (double)(0); - } - sx.ptr.p_double[j] = sx.ptr.p_double[j]+x->ptr.pp_double[i][j]*x->ptr.pp_double[i][j]; - } - } - for(j=0; j<=m1-1; j++) - { - sx.ptr.p_double[j] = ae_sqrt(sx.ptr.p_double[j]/(n-1), _state); - } - - /* - * Repeat same steps for Y - */ - for(i=0; i<=m2-1; i++) - { - t.ptr.p_double[i] = (double)(0); - samey.ptr.p_bool[i] = ae_true; - sy.ptr.p_double[i] = (double)(0); - } - ae_v_move(&y0.ptr.p_double[0], 1, &y->ptr.pp_double[0][0], 1, ae_v_len(0,m2-1)); - v = (double)1/(double)n; - for(i=0; i<=n-1; i++) - { - ae_v_addd(&t.ptr.p_double[0], 1, &y->ptr.pp_double[i][0], 1, ae_v_len(0,m2-1), v); - for(j=0; j<=m2-1; j++) - { - samey.ptr.p_bool[j] = samey.ptr.p_bool[j]&&ae_fp_eq(y->ptr.pp_double[i][j],y0.ptr.p_double[j]); - } - } - for(i=0; i<=n-1; i++) - { - ae_v_sub(&y->ptr.pp_double[i][0], 1, &t.ptr.p_double[0], 1, ae_v_len(0,m2-1)); - for(j=0; j<=m2-1; j++) - { - if( samey.ptr.p_bool[j] ) - { - y->ptr.pp_double[i][j] = (double)(0); - } - sy.ptr.p_double[j] = sy.ptr.p_double[j]+y->ptr.pp_double[i][j]*y->ptr.pp_double[i][j]; - } - } - for(j=0; j<=m2-1; j++) - { - sy.ptr.p_double[j] = ae_sqrt(sy.ptr.p_double[j]/(n-1), _state); - } - - /* - * calculate cross-covariance matrix - */ - rmatrixgemm(m1, m2, n, (double)1/(double)(n-1), x, 0, 0, 1, y, 0, 0, 0, 0.0, c, 0, 0, _state); - - /* - * Divide by standard deviations - */ - for(i=0; i<=m1-1; i++) - { - if( ae_fp_neq(sx.ptr.p_double[i],(double)(0)) ) - { - sx.ptr.p_double[i] = 1/sx.ptr.p_double[i]; - } - else - { - sx.ptr.p_double[i] = 0.0; - } - } - for(i=0; i<=m2-1; i++) - { - if( ae_fp_neq(sy.ptr.p_double[i],(double)(0)) ) - { - sy.ptr.p_double[i] = 1/sy.ptr.p_double[i]; - } - else - { - sy.ptr.p_double[i] = 0.0; - } - } - for(i=0; i<=m1-1; i++) - { - v = sx.ptr.p_double[i]; - for(j=0; j<=m2-1; j++) - { - c->ptr.pp_double[i][j] = c->ptr.pp_double[i][j]*v*sy.ptr.p_double[j]; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Spearman's rank cross-correlation matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M1], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - Y - array[N,M2], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X/Y are used - * if not given, automatically determined from input sizes - M1 - M1>0, number of variables in X: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - M2 - M2>0, number of variables in Y: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M1,M2], cross-correlation matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -void spearmancorrm2(/* Real */ ae_matrix* x, - /* Real */ ae_matrix* y, - ae_int_t n, - ae_int_t m1, - ae_int_t m2, - /* Real */ ae_matrix* c, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - double v; - double v2; - double vv; - ae_bool b; - ae_vector t; - double x0; - double y0; - ae_vector sx; - ae_vector sy; - ae_matrix xc; - ae_matrix yc; - apbuffers buf; - - ae_frame_make(_state, &_frame_block); - memset(&t, 0, sizeof(t)); - memset(&sx, 0, sizeof(sx)); - memset(&sy, 0, sizeof(sy)); - memset(&xc, 0, sizeof(xc)); - memset(&yc, 0, sizeof(yc)); - memset(&buf, 0, sizeof(buf)); - ae_matrix_clear(c); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sy, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xc, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&yc, 0, 0, DT_REAL, _state, ae_true); - _apbuffers_init(&buf, _state, ae_true); - - ae_assert(n>=0, "SpearmanCorrM2: N<0", _state); - ae_assert(m1>=1, "SpearmanCorrM2: M1<1", _state); - ae_assert(m2>=1, "SpearmanCorrM2: M2<1", _state); - ae_assert(x->rows>=n, "SpearmanCorrM2: Rows(X)cols>=m1||n==0, "SpearmanCorrM2: Cols(X)rows>=n, "SpearmanCorrM2: Rows(Y)cols>=m2||n==0, "SpearmanCorrM2: Cols(Y)ptr.pp_double[i][j] = (double)(0); - } - } - ae_frame_leave(_state); - return; - } - - /* - * Allocate - */ - ae_vector_set_length(&t, ae_maxint(ae_maxint(m1, m2, _state), n, _state), _state); - ae_vector_set_length(&sx, m1, _state); - ae_vector_set_length(&sy, m2, _state); - ae_matrix_set_length(c, m1, m2, _state); - - /* - * Replace data with ranks - */ - ae_matrix_set_length(&xc, m1, n, _state); - ae_matrix_set_length(&yc, m2, n, _state); - rmatrixtranspose(n, m1, x, 0, 0, &xc, 0, 0, _state); - rmatrixtranspose(n, m2, y, 0, 0, &yc, 0, 0, _state); - rankdata(&xc, m1, n, _state); - rankdata(&yc, m2, n, _state); - - /* - * 1. Calculate means, variances, check for constant columns - * 2. Center variables, constant columns are - * artificialy zeroed (they must be zero in exact arithmetics, - * but unfortunately floating point is not exact). - * - * Description of variables: - * * V - mean value of I-th variable - * * V2- variance - * * VV-temporary - * * B - True in case all variable values are same - */ - for(i=0; i<=m1-1; i++) - { - v = (double)(0); - v2 = 0.0; - b = ae_true; - x0 = xc.ptr.pp_double[i][0]; - for(j=0; j<=n-1; j++) - { - vv = xc.ptr.pp_double[i][j]; - v = v+vv; - b = b&&ae_fp_eq(vv,x0); - } - v = v/n; - if( b ) - { - for(j=0; j<=n-1; j++) - { - xc.ptr.pp_double[i][j] = 0.0; - } - } - else - { - for(j=0; j<=n-1; j++) - { - vv = xc.ptr.pp_double[i][j]; - xc.ptr.pp_double[i][j] = vv-v; - v2 = v2+(vv-v)*(vv-v); - } - } - sx.ptr.p_double[i] = ae_sqrt(v2/(n-1), _state); - } - for(i=0; i<=m2-1; i++) - { - v = (double)(0); - v2 = 0.0; - b = ae_true; - y0 = yc.ptr.pp_double[i][0]; - for(j=0; j<=n-1; j++) - { - vv = yc.ptr.pp_double[i][j]; - v = v+vv; - b = b&&ae_fp_eq(vv,y0); - } - v = v/n; - if( b ) - { - for(j=0; j<=n-1; j++) - { - yc.ptr.pp_double[i][j] = 0.0; - } - } - else - { - for(j=0; j<=n-1; j++) - { - vv = yc.ptr.pp_double[i][j]; - yc.ptr.pp_double[i][j] = vv-v; - v2 = v2+(vv-v)*(vv-v); - } - } - sy.ptr.p_double[i] = ae_sqrt(v2/(n-1), _state); - } - - /* - * calculate cross-covariance matrix - */ - rmatrixgemm(m1, m2, n, (double)1/(double)(n-1), &xc, 0, 0, 0, &yc, 0, 0, 1, 0.0, c, 0, 0, _state); - - /* - * Divide by standard deviations - */ - for(i=0; i<=m1-1; i++) - { - if( ae_fp_neq(sx.ptr.p_double[i],(double)(0)) ) - { - sx.ptr.p_double[i] = 1/sx.ptr.p_double[i]; - } - else - { - sx.ptr.p_double[i] = 0.0; - } - } - for(i=0; i<=m2-1; i++) - { - if( ae_fp_neq(sy.ptr.p_double[i],(double)(0)) ) - { - sy.ptr.p_double[i] = 1/sy.ptr.p_double[i]; - } - else - { - sy.ptr.p_double[i] = 0.0; - } - } - for(i=0; i<=m1-1; i++) - { - v = sx.ptr.p_double[i]; - for(j=0; j<=m2-1; j++) - { - c->ptr.pp_double[i][j] = c->ptr.pp_double[i][j]*v*sy.ptr.p_double[j]; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function replaces data in XY by their ranks: -* XY is processed row-by-row -* rows are processed separately -* tied data are correctly handled (tied ranks are calculated) -* ranking starts from 0, ends at NFeatures-1 -* sum of within-row values is equal to (NFeatures-1)*NFeatures/2 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - array[NPoints,NFeatures], dataset - NPoints - number of points - NFeatures- number of features - -OUTPUT PARAMETERS: - XY - data are replaced by their within-row ranks; - ranking starts from 0, ends at NFeatures-1 - - -- ALGLIB -- - Copyright 18.04.2013 by Bochkanov Sergey -*************************************************************************/ -void rankdata(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nfeatures, - ae_state *_state) -{ - ae_frame _frame_block; - apbuffers buf0; - apbuffers buf1; - ae_int_t basecasecost; - ae_shared_pool pool; - - ae_frame_make(_state, &_frame_block); - memset(&buf0, 0, sizeof(buf0)); - memset(&buf1, 0, sizeof(buf1)); - memset(&pool, 0, sizeof(pool)); - _apbuffers_init(&buf0, _state, ae_true); - _apbuffers_init(&buf1, _state, ae_true); - ae_shared_pool_init(&pool, _state, ae_true); - - ae_assert(npoints>=0, "RankData: NPoints<0", _state); - ae_assert(nfeatures>=1, "RankData: NFeatures<1", _state); - ae_assert(xy->rows>=npoints, "RankData: Rows(XY)cols>=nfeatures||npoints==0, "RankData: Cols(XY)=0, "RankData: NPoints<0", _state); - ae_assert(nfeatures>=1, "RankData: NFeatures<1", _state); - ae_assert(xy->rows>=npoints, "RankData: Rows(XY)cols>=nfeatures||npoints==0, "RankData: Cols(XY)=i0, "RankDataRec: internal error", _state); - - /* - * Try to activate parallelism - */ - if( i1-i0>=4&&ae_fp_greater_eq(rmul3((double)(i1-i0), (double)(nfeatures), logbase2((double)(nfeatures), _state), _state),smpactivationlevel(_state)) ) - { - if( _trypexec_basestat_rankdatarec(xy,i0,i1,nfeatures,iscentered,pool,basecasecost, _state) ) - { - ae_frame_leave(_state); - return; - } - } - - /* - * Recursively split problem, if it is too large - */ - problemcost = rmul3((double)(i1-i0), (double)(nfeatures), logbase2((double)(nfeatures), _state), _state); - if( i1-i0>=2&&ae_fp_greater(problemcost,spawnlevel(_state)) ) - { - im = (i1+i0)/2; - basestat_rankdatarec(xy, i0, im, nfeatures, iscentered, pool, basecasecost, _state); - basestat_rankdatarec(xy, im, i1, nfeatures, iscentered, pool, basecasecost, _state); - ae_frame_leave(_state); - return; - } - - /* - * Retrieve buffers from pool, call serial code, return buffers to pool - */ - ae_shared_pool_retrieve(pool, &_buf0, _state); - ae_shared_pool_retrieve(pool, &_buf1, _state); - basestat_rankdatabasecase(xy, i0, i1, nfeatures, iscentered, buf0, buf1, _state); - ae_shared_pool_recycle(pool, &_buf0, _state); - ae_shared_pool_recycle(pool, &_buf1, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_basestat_rankdatarec(/* Real */ ae_matrix* xy, - ae_int_t i0, - ae_int_t i1, - ae_int_t nfeatures, - ae_bool iscentered, - ae_shared_pool* pool, - ae_int_t basecasecost, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -Basecase code for RankData(), performs actual work on subset of data using -temporary buffer passed as parameter. - -INPUT PARAMETERS: - XY - array[NPoints,NFeatures], dataset - I0 - index of first row to process - I1 - index of past-the-last row to process; - this function processes half-interval [I0,I1). - NFeatures- number of features - IsCentered- whether ranks are centered or not: - * True - ranks are centered in such way that their - within-row sum is zero - * False - ranks are not centered - Buf0 - temporary buffers, may be empty (this function automatically - allocates/reuses buffers). - Buf1 - temporary buffers, may be empty (this function automatically - allocates/reuses buffers). - -OUTPUT PARAMETERS: - XY - data in [I0,I1) are replaced by their within-row ranks; - ranking starts from 0, ends at NFeatures-1 - - -- ALGLIB -- - Copyright 18.04.2013 by Bochkanov Sergey -*************************************************************************/ -static void basestat_rankdatabasecase(/* Real */ ae_matrix* xy, - ae_int_t i0, - ae_int_t i1, - ae_int_t nfeatures, - ae_bool iscentered, - apbuffers* buf0, - apbuffers* buf1, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(i1>=i0, "RankDataBasecase: internal error", _state); - if( buf1->ra0.cntra0, nfeatures, _state); - } - for(i=i0; i<=i1-1; i++) - { - ae_v_move(&buf1->ra0.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nfeatures-1)); - rankx(&buf1->ra0, nfeatures, iscentered, buf0, _state); - ae_v_move(&xy->ptr.pp_double[i][0], 1, &buf1->ra0.ptr.p_double[0], 1, ae_v_len(0,nfeatures-1)); - } -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_basestat_rankdatabasecase(/* Real */ ae_matrix* xy, - ae_int_t i0, - ae_int_t i1, - ae_int_t nfeatures, - ae_bool iscentered, - apbuffers* buf0, - apbuffers* buf1, - ae_state *_state) -{ - return ae_false; -} - - -#endif -#if defined(AE_COMPILE_WSR) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Wilcoxon signed-rank test - -This test checks three hypotheses about the median of the given sample. -The following tests are performed: - * two-tailed test (null hypothesis - the median is equal to the given - value) - * left-tailed test (null hypothesis - the median is greater than or - equal to the given value) - * right-tailed test (null hypothesis - the median is less than or - equal to the given value) - -Requirements: - * the scale of measurement should be ordinal, interval or ratio (i.e. - the test could not be applied to nominal variables). - * the distribution should be continuous and symmetric relative to its - median. - * number of distinct values in the X array should be greater than 4 - -The test is non-parametric and doesn't require distribution X to be normal - -Input parameters: - X - sample. Array whose index goes from 0 to N-1. - N - size of the sample. - Median - assumed median value. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -To calculate p-values, special approximation is used. This method lets us -calculate p-values with two decimal places in interval [0.0001, 1]. - -"Two decimal places" does not sound very impressive, but in practice the -relative error of less than 1% is enough to make a decision. - -There is no approximation outside the [0.0001, 1] interval. Therefore, if -the significance level outlies this interval, the test returns 0.0001. - - -- ALGLIB -- - Copyright 08.09.2006 by Bochkanov Sergey -*************************************************************************/ -void wilcoxonsignedranktest(/* Real */ ae_vector* x, - ae_int_t n, - double e, - double* bothtails, - double* lefttail, - double* righttail, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _x; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t t; - double tmp; - ae_int_t tmpi; - ae_int_t ns; - ae_vector r; - ae_vector c; - double w; - double p; - double mp; - double s; - double sigma; - double mu; - - ae_frame_make(_state, &_frame_block); - memset(&_x, 0, sizeof(_x)); - memset(&r, 0, sizeof(r)); - memset(&c, 0, sizeof(c)); - ae_vector_init_copy(&_x, x, _state, ae_true); - x = &_x; - *bothtails = 0; - *lefttail = 0; - *righttail = 0; - ae_vector_init(&r, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c, 0, DT_INT, _state, ae_true); - - - /* - * Prepare - */ - if( n<5 ) - { - *bothtails = 1.0; - *lefttail = 1.0; - *righttail = 1.0; - ae_frame_leave(_state); - return; - } - ns = 0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_eq(x->ptr.p_double[i],e) ) - { - continue; - } - x->ptr.p_double[ns] = x->ptr.p_double[i]; - ns = ns+1; - } - if( ns<5 ) - { - *bothtails = 1.0; - *lefttail = 1.0; - *righttail = 1.0; - ae_frame_leave(_state); - return; - } - ae_vector_set_length(&r, ns-1+1, _state); - ae_vector_set_length(&c, ns-1+1, _state); - for(i=0; i<=ns-1; i++) - { - r.ptr.p_double[i] = ae_fabs(x->ptr.p_double[i]-e, _state); - c.ptr.p_int[i] = i; - } - - /* - * sort {R, C} - */ - if( ns!=1 ) - { - i = 2; - do - { - t = i; - while(t!=1) - { - k = t/2; - if( ae_fp_greater_eq(r.ptr.p_double[k-1],r.ptr.p_double[t-1]) ) - { - t = 1; - } - else - { - tmp = r.ptr.p_double[k-1]; - r.ptr.p_double[k-1] = r.ptr.p_double[t-1]; - r.ptr.p_double[t-1] = tmp; - tmpi = c.ptr.p_int[k-1]; - c.ptr.p_int[k-1] = c.ptr.p_int[t-1]; - c.ptr.p_int[t-1] = tmpi; - t = k; - } - } - i = i+1; - } - while(i<=ns); - i = ns-1; - do - { - tmp = r.ptr.p_double[i]; - r.ptr.p_double[i] = r.ptr.p_double[0]; - r.ptr.p_double[0] = tmp; - tmpi = c.ptr.p_int[i]; - c.ptr.p_int[i] = c.ptr.p_int[0]; - c.ptr.p_int[0] = tmpi; - t = 1; - while(t!=0) - { - k = 2*t; - if( k>i ) - { - t = 0; - } - else - { - if( k=1); - } - - /* - * compute tied ranks - */ - i = 0; - while(i<=ns-1) - { - j = i+1; - while(j<=ns-1) - { - if( ae_fp_neq(r.ptr.p_double[j],r.ptr.p_double[i]) ) - { - break; - } - j = j+1; - } - for(k=i; k<=j-1; k++) - { - r.ptr.p_double[k] = 1+(double)(i+j-1)/(double)2; - } - i = j; - } - - /* - * Compute W+ - */ - w = (double)(0); - for(i=0; i<=ns-1; i++) - { - if( ae_fp_greater(x->ptr.p_double[c.ptr.p_int[i]],e) ) - { - w = w+r.ptr.p_double[i]; - } - } - - /* - * Result - */ - mu = rmul2((double)(ns), (double)(ns+1), _state)/4; - sigma = ae_sqrt(mu*(2*ns+1)/6, _state); - s = (w-mu)/sigma; - if( ae_fp_less_eq(s,(double)(0)) ) - { - p = ae_exp(wsr_wsigma(-(w-mu)/sigma, ns, _state), _state); - mp = 1-ae_exp(wsr_wsigma(-(w-1-mu)/sigma, ns, _state), _state); - } - else - { - mp = ae_exp(wsr_wsigma((w-mu)/sigma, ns, _state), _state); - p = 1-ae_exp(wsr_wsigma((w+1-mu)/sigma, ns, _state), _state); - } - *lefttail = ae_maxreal(p, 1.0E-4, _state); - *righttail = ae_maxreal(mp, 1.0E-4, _state); - *bothtails = 2*ae_minreal(*lefttail, *righttail, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Sequential Chebyshev interpolation. -*************************************************************************/ -static void wsr_wcheb(double x, - double c, - double* tj, - double* tj1, - double* r, - ae_state *_state) -{ - double t; - - - *r = *r+c*(*tj); - t = 2*x*(*tj1)-(*tj); - *tj = *tj1; - *tj1 = t; -} - - -/************************************************************************* -Tail(S, 5) -*************************************************************************/ -static double wsr_w5(double s, ae_state *_state) -{ - ae_int_t w; - double r; - double result; - - - r = (double)(0); - w = ae_round(-3.708099e+00*s+7.500000e+00, _state); - if( w>=7 ) - { - r = -6.931e-01; - } - if( w==6 ) - { - r = -9.008e-01; - } - if( w==5 ) - { - r = -1.163e+00; - } - if( w==4 ) - { - r = -1.520e+00; - } - if( w==3 ) - { - r = -1.856e+00; - } - if( w==2 ) - { - r = -2.367e+00; - } - if( w==1 ) - { - r = -2.773e+00; - } - if( w<=0 ) - { - r = -3.466e+00; - } - result = r; - return result; -} - - -/************************************************************************* -Tail(S, 6) -*************************************************************************/ -static double wsr_w6(double s, ae_state *_state) -{ - ae_int_t w; - double r; - double result; - - - r = (double)(0); - w = ae_round(-4.769696e+00*s+1.050000e+01, _state); - if( w>=10 ) - { - r = -6.931e-01; - } - if( w==9 ) - { - r = -8.630e-01; - } - if( w==8 ) - { - r = -1.068e+00; - } - if( w==7 ) - { - r = -1.269e+00; - } - if( w==6 ) - { - r = -1.520e+00; - } - if( w==5 ) - { - r = -1.856e+00; - } - if( w==4 ) - { - r = -2.213e+00; - } - if( w==3 ) - { - r = -2.549e+00; - } - if( w==2 ) - { - r = -3.060e+00; - } - if( w==1 ) - { - r = -3.466e+00; - } - if( w<=0 ) - { - r = -4.159e+00; - } - result = r; - return result; -} - - -/************************************************************************* -Tail(S, 7) -*************************************************************************/ -static double wsr_w7(double s, ae_state *_state) -{ - ae_int_t w; - double r; - double result; - - - r = (double)(0); - w = ae_round(-5.916080e+00*s+1.400000e+01, _state); - if( w>=14 ) - { - r = -6.325e-01; - } - if( w==13 ) - { - r = -7.577e-01; - } - if( w==12 ) - { - r = -9.008e-01; - } - if( w==11 ) - { - r = -1.068e+00; - } - if( w==10 ) - { - r = -1.241e+00; - } - if( w==9 ) - { - r = -1.451e+00; - } - if( w==8 ) - { - r = -1.674e+00; - } - if( w==7 ) - { - r = -1.908e+00; - } - if( w==6 ) - { - r = -2.213e+00; - } - if( w==5 ) - { - r = -2.549e+00; - } - if( w==4 ) - { - r = -2.906e+00; - } - if( w==3 ) - { - r = -3.243e+00; - } - if( w==2 ) - { - r = -3.753e+00; - } - if( w==1 ) - { - r = -4.159e+00; - } - if( w<=0 ) - { - r = -4.852e+00; - } - result = r; - return result; -} - - -/************************************************************************* -Tail(S, 8) -*************************************************************************/ -static double wsr_w8(double s, ae_state *_state) -{ - ae_int_t w; - double r; - double result; - - - r = (double)(0); - w = ae_round(-7.141428e+00*s+1.800000e+01, _state); - if( w>=18 ) - { - r = -6.399e-01; - } - if( w==17 ) - { - r = -7.494e-01; - } - if( w==16 ) - { - r = -8.630e-01; - } - if( w==15 ) - { - r = -9.913e-01; - } - if( w==14 ) - { - r = -1.138e+00; - } - if( w==13 ) - { - r = -1.297e+00; - } - if( w==12 ) - { - r = -1.468e+00; - } - if( w==11 ) - { - r = -1.653e+00; - } - if( w==10 ) - { - r = -1.856e+00; - } - if( w==9 ) - { - r = -2.079e+00; - } - if( w==8 ) - { - r = -2.326e+00; - } - if( w==7 ) - { - r = -2.601e+00; - } - if( w==6 ) - { - r = -2.906e+00; - } - if( w==5 ) - { - r = -3.243e+00; - } - if( w==4 ) - { - r = -3.599e+00; - } - if( w==3 ) - { - r = -3.936e+00; - } - if( w==2 ) - { - r = -4.447e+00; - } - if( w==1 ) - { - r = -4.852e+00; - } - if( w<=0 ) - { - r = -5.545e+00; - } - result = r; - return result; -} - - -/************************************************************************* -Tail(S, 9) -*************************************************************************/ -static double wsr_w9(double s, ae_state *_state) -{ - ae_int_t w; - double r; - double result; - - - r = (double)(0); - w = ae_round(-8.440972e+00*s+2.250000e+01, _state); - if( w>=22 ) - { - r = -6.931e-01; - } - if( w==21 ) - { - r = -7.873e-01; - } - if( w==20 ) - { - r = -8.912e-01; - } - if( w==19 ) - { - r = -1.002e+00; - } - if( w==18 ) - { - r = -1.120e+00; - } - if( w==17 ) - { - r = -1.255e+00; - } - if( w==16 ) - { - r = -1.394e+00; - } - if( w==15 ) - { - r = -1.547e+00; - } - if( w==14 ) - { - r = -1.717e+00; - } - if( w==13 ) - { - r = -1.895e+00; - } - if( w==12 ) - { - r = -2.079e+00; - } - if( w==11 ) - { - r = -2.287e+00; - } - if( w==10 ) - { - r = -2.501e+00; - } - if( w==9 ) - { - r = -2.742e+00; - } - if( w==8 ) - { - r = -3.019e+00; - } - if( w==7 ) - { - r = -3.294e+00; - } - if( w==6 ) - { - r = -3.599e+00; - } - if( w==5 ) - { - r = -3.936e+00; - } - if( w==4 ) - { - r = -4.292e+00; - } - if( w==3 ) - { - r = -4.629e+00; - } - if( w==2 ) - { - r = -5.140e+00; - } - if( w==1 ) - { - r = -5.545e+00; - } - if( w<=0 ) - { - r = -6.238e+00; - } - result = r; - return result; -} - - -/************************************************************************* -Tail(S, 10) -*************************************************************************/ -static double wsr_w10(double s, ae_state *_state) -{ - ae_int_t w; - double r; - double result; - - - r = (double)(0); - w = ae_round(-9.810708e+00*s+2.750000e+01, _state); - if( w>=27 ) - { - r = -6.931e-01; - } - if( w==26 ) - { - r = -7.745e-01; - } - if( w==25 ) - { - r = -8.607e-01; - } - if( w==24 ) - { - r = -9.551e-01; - } - if( w==23 ) - { - r = -1.057e+00; - } - if( w==22 ) - { - r = -1.163e+00; - } - if( w==21 ) - { - r = -1.279e+00; - } - if( w==20 ) - { - r = -1.402e+00; - } - if( w==19 ) - { - r = -1.533e+00; - } - if( w==18 ) - { - r = -1.674e+00; - } - if( w==17 ) - { - r = -1.826e+00; - } - if( w==16 ) - { - r = -1.983e+00; - } - if( w==15 ) - { - r = -2.152e+00; - } - if( w==14 ) - { - r = -2.336e+00; - } - if( w==13 ) - { - r = -2.525e+00; - } - if( w==12 ) - { - r = -2.727e+00; - } - if( w==11 ) - { - r = -2.942e+00; - } - if( w==10 ) - { - r = -3.170e+00; - } - if( w==9 ) - { - r = -3.435e+00; - } - if( w==8 ) - { - r = -3.713e+00; - } - if( w==7 ) - { - r = -3.987e+00; - } - if( w==6 ) - { - r = -4.292e+00; - } - if( w==5 ) - { - r = -4.629e+00; - } - if( w==4 ) - { - r = -4.986e+00; - } - if( w==3 ) - { - r = -5.322e+00; - } - if( w==2 ) - { - r = -5.833e+00; - } - if( w==1 ) - { - r = -6.238e+00; - } - if( w<=0 ) - { - r = -6.931e+00; - } - result = r; - return result; -} - - -/************************************************************************* -Tail(S, 11) -*************************************************************************/ -static double wsr_w11(double s, ae_state *_state) -{ - ae_int_t w; - double r; - double result; - - - r = (double)(0); - w = ae_round(-1.124722e+01*s+3.300000e+01, _state); - if( w>=33 ) - { - r = -6.595e-01; - } - if( w==32 ) - { - r = -7.279e-01; - } - if( w==31 ) - { - r = -8.002e-01; - } - if( w==30 ) - { - r = -8.782e-01; - } - if( w==29 ) - { - r = -9.615e-01; - } - if( w==28 ) - { - r = -1.050e+00; - } - if( w==27 ) - { - r = -1.143e+00; - } - if( w==26 ) - { - r = -1.243e+00; - } - if( w==25 ) - { - r = -1.348e+00; - } - if( w==24 ) - { - r = -1.459e+00; - } - if( w==23 ) - { - r = -1.577e+00; - } - if( w==22 ) - { - r = -1.700e+00; - } - if( w==21 ) - { - r = -1.832e+00; - } - if( w==20 ) - { - r = -1.972e+00; - } - if( w==19 ) - { - r = -2.119e+00; - } - if( w==18 ) - { - r = -2.273e+00; - } - if( w==17 ) - { - r = -2.437e+00; - } - if( w==16 ) - { - r = -2.607e+00; - } - if( w==15 ) - { - r = -2.788e+00; - } - if( w==14 ) - { - r = -2.980e+00; - } - if( w==13 ) - { - r = -3.182e+00; - } - if( w==12 ) - { - r = -3.391e+00; - } - if( w==11 ) - { - r = -3.617e+00; - } - if( w==10 ) - { - r = -3.863e+00; - } - if( w==9 ) - { - r = -4.128e+00; - } - if( w==8 ) - { - r = -4.406e+00; - } - if( w==7 ) - { - r = -4.680e+00; - } - if( w==6 ) - { - r = -4.986e+00; - } - if( w==5 ) - { - r = -5.322e+00; - } - if( w==4 ) - { - r = -5.679e+00; - } - if( w==3 ) - { - r = -6.015e+00; - } - if( w==2 ) - { - r = -6.526e+00; - } - if( w==1 ) - { - r = -6.931e+00; - } - if( w<=0 ) - { - r = -7.625e+00; - } - result = r; - return result; -} - - -/************************************************************************* -Tail(S, 12) -*************************************************************************/ -static double wsr_w12(double s, ae_state *_state) -{ - ae_int_t w; - double r; - double result; - - - r = (double)(0); - w = ae_round(-1.274755e+01*s+3.900000e+01, _state); - if( w>=39 ) - { - r = -6.633e-01; - } - if( w==38 ) - { - r = -7.239e-01; - } - if( w==37 ) - { - r = -7.878e-01; - } - if( w==36 ) - { - r = -8.556e-01; - } - if( w==35 ) - { - r = -9.276e-01; - } - if( w==34 ) - { - r = -1.003e+00; - } - if( w==33 ) - { - r = -1.083e+00; - } - if( w==32 ) - { - r = -1.168e+00; - } - if( w==31 ) - { - r = -1.256e+00; - } - if( w==30 ) - { - r = -1.350e+00; - } - if( w==29 ) - { - r = -1.449e+00; - } - if( w==28 ) - { - r = -1.552e+00; - } - if( w==27 ) - { - r = -1.660e+00; - } - if( w==26 ) - { - r = -1.774e+00; - } - if( w==25 ) - { - r = -1.893e+00; - } - if( w==24 ) - { - r = -2.017e+00; - } - if( w==23 ) - { - r = -2.148e+00; - } - if( w==22 ) - { - r = -2.285e+00; - } - if( w==21 ) - { - r = -2.429e+00; - } - if( w==20 ) - { - r = -2.581e+00; - } - if( w==19 ) - { - r = -2.738e+00; - } - if( w==18 ) - { - r = -2.902e+00; - } - if( w==17 ) - { - r = -3.076e+00; - } - if( w==16 ) - { - r = -3.255e+00; - } - if( w==15 ) - { - r = -3.443e+00; - } - if( w==14 ) - { - r = -3.645e+00; - } - if( w==13 ) - { - r = -3.852e+00; - } - if( w==12 ) - { - r = -4.069e+00; - } - if( w==11 ) - { - r = -4.310e+00; - } - if( w==10 ) - { - r = -4.557e+00; - } - if( w==9 ) - { - r = -4.821e+00; - } - if( w==8 ) - { - r = -5.099e+00; - } - if( w==7 ) - { - r = -5.373e+00; - } - if( w==6 ) - { - r = -5.679e+00; - } - if( w==5 ) - { - r = -6.015e+00; - } - if( w==4 ) - { - r = -6.372e+00; - } - if( w==3 ) - { - r = -6.708e+00; - } - if( w==2 ) - { - r = -7.219e+00; - } - if( w==1 ) - { - r = -7.625e+00; - } - if( w<=0 ) - { - r = -8.318e+00; - } - result = r; - return result; -} - - -/************************************************************************* -Tail(S, 13) -*************************************************************************/ -static double wsr_w13(double s, ae_state *_state) -{ - ae_int_t w; - double r; - double result; - - - r = (double)(0); - w = ae_round(-1.430909e+01*s+4.550000e+01, _state); - if( w>=45 ) - { - r = -6.931e-01; - } - if( w==44 ) - { - r = -7.486e-01; - } - if( w==43 ) - { - r = -8.068e-01; - } - if( w==42 ) - { - r = -8.683e-01; - } - if( w==41 ) - { - r = -9.328e-01; - } - if( w==40 ) - { - r = -1.001e+00; - } - if( w==39 ) - { - r = -1.072e+00; - } - if( w==38 ) - { - r = -1.146e+00; - } - if( w==37 ) - { - r = -1.224e+00; - } - if( w==36 ) - { - r = -1.306e+00; - } - if( w==35 ) - { - r = -1.392e+00; - } - if( w==34 ) - { - r = -1.481e+00; - } - if( w==33 ) - { - r = -1.574e+00; - } - if( w==32 ) - { - r = -1.672e+00; - } - if( w==31 ) - { - r = -1.773e+00; - } - if( w==30 ) - { - r = -1.879e+00; - } - if( w==29 ) - { - r = -1.990e+00; - } - if( w==28 ) - { - r = -2.104e+00; - } - if( w==27 ) - { - r = -2.224e+00; - } - if( w==26 ) - { - r = -2.349e+00; - } - if( w==25 ) - { - r = -2.479e+00; - } - if( w==24 ) - { - r = -2.614e+00; - } - if( w==23 ) - { - r = -2.755e+00; - } - if( w==22 ) - { - r = -2.902e+00; - } - if( w==21 ) - { - r = -3.055e+00; - } - if( w==20 ) - { - r = -3.215e+00; - } - if( w==19 ) - { - r = -3.380e+00; - } - if( w==18 ) - { - r = -3.551e+00; - } - if( w==17 ) - { - r = -3.733e+00; - } - if( w==16 ) - { - r = -3.917e+00; - } - if( w==15 ) - { - r = -4.113e+00; - } - if( w==14 ) - { - r = -4.320e+00; - } - if( w==13 ) - { - r = -4.534e+00; - } - if( w==12 ) - { - r = -4.762e+00; - } - if( w==11 ) - { - r = -5.004e+00; - } - if( w==10 ) - { - r = -5.250e+00; - } - if( w==9 ) - { - r = -5.514e+00; - } - if( w==8 ) - { - r = -5.792e+00; - } - if( w==7 ) - { - r = -6.066e+00; - } - if( w==6 ) - { - r = -6.372e+00; - } - if( w==5 ) - { - r = -6.708e+00; - } - if( w==4 ) - { - r = -7.065e+00; - } - if( w==3 ) - { - r = -7.401e+00; - } - if( w==2 ) - { - r = -7.912e+00; - } - if( w==1 ) - { - r = -8.318e+00; - } - if( w<=0 ) - { - r = -9.011e+00; - } - result = r; - return result; -} - - -/************************************************************************* -Tail(S, 14) -*************************************************************************/ -static double wsr_w14(double s, ae_state *_state) -{ - ae_int_t w; - double r; - double result; - - - r = (double)(0); - w = ae_round(-1.592953e+01*s+5.250000e+01, _state); - if( w>=52 ) - { - r = -6.931e-01; - } - if( w==51 ) - { - r = -7.428e-01; - } - if( w==50 ) - { - r = -7.950e-01; - } - if( w==49 ) - { - r = -8.495e-01; - } - if( w==48 ) - { - r = -9.067e-01; - } - if( w==47 ) - { - r = -9.664e-01; - } - if( w==46 ) - { - r = -1.029e+00; - } - if( w==45 ) - { - r = -1.094e+00; - } - if( w==44 ) - { - r = -1.162e+00; - } - if( w==43 ) - { - r = -1.233e+00; - } - if( w==42 ) - { - r = -1.306e+00; - } - if( w==41 ) - { - r = -1.383e+00; - } - if( w==40 ) - { - r = -1.463e+00; - } - if( w==39 ) - { - r = -1.546e+00; - } - if( w==38 ) - { - r = -1.632e+00; - } - if( w==37 ) - { - r = -1.722e+00; - } - if( w==36 ) - { - r = -1.815e+00; - } - if( w==35 ) - { - r = -1.911e+00; - } - if( w==34 ) - { - r = -2.011e+00; - } - if( w==33 ) - { - r = -2.115e+00; - } - if( w==32 ) - { - r = -2.223e+00; - } - if( w==31 ) - { - r = -2.334e+00; - } - if( w==30 ) - { - r = -2.450e+00; - } - if( w==29 ) - { - r = -2.570e+00; - } - if( w==28 ) - { - r = -2.694e+00; - } - if( w==27 ) - { - r = -2.823e+00; - } - if( w==26 ) - { - r = -2.956e+00; - } - if( w==25 ) - { - r = -3.095e+00; - } - if( w==24 ) - { - r = -3.238e+00; - } - if( w==23 ) - { - r = -3.387e+00; - } - if( w==22 ) - { - r = -3.541e+00; - } - if( w==21 ) - { - r = -3.700e+00; - } - if( w==20 ) - { - r = -3.866e+00; - } - if( w==19 ) - { - r = -4.038e+00; - } - if( w==18 ) - { - r = -4.215e+00; - } - if( w==17 ) - { - r = -4.401e+00; - } - if( w==16 ) - { - r = -4.592e+00; - } - if( w==15 ) - { - r = -4.791e+00; - } - if( w==14 ) - { - r = -5.004e+00; - } - if( w==13 ) - { - r = -5.227e+00; - } - if( w==12 ) - { - r = -5.456e+00; - } - if( w==11 ) - { - r = -5.697e+00; - } - if( w==10 ) - { - r = -5.943e+00; - } - if( w==9 ) - { - r = -6.208e+00; - } - if( w==8 ) - { - r = -6.485e+00; - } - if( w==7 ) - { - r = -6.760e+00; - } - if( w==6 ) - { - r = -7.065e+00; - } - if( w==5 ) - { - r = -7.401e+00; - } - if( w==4 ) - { - r = -7.758e+00; - } - if( w==3 ) - { - r = -8.095e+00; - } - if( w==2 ) - { - r = -8.605e+00; - } - if( w==1 ) - { - r = -9.011e+00; - } - if( w<=0 ) - { - r = -9.704e+00; - } - result = r; - return result; -} - - -/************************************************************************* -Tail(S, 15) -*************************************************************************/ -static double wsr_w15(double s, ae_state *_state) -{ - ae_int_t w; - double r; - double result; - - - r = (double)(0); - w = ae_round(-1.760682e+01*s+6.000000e+01, _state); - if( w>=60 ) - { - r = -6.714e-01; - } - if( w==59 ) - { - r = -7.154e-01; - } - if( w==58 ) - { - r = -7.613e-01; - } - if( w==57 ) - { - r = -8.093e-01; - } - if( w==56 ) - { - r = -8.593e-01; - } - if( w==55 ) - { - r = -9.114e-01; - } - if( w==54 ) - { - r = -9.656e-01; - } - if( w==53 ) - { - r = -1.022e+00; - } - if( w==52 ) - { - r = -1.081e+00; - } - if( w==51 ) - { - r = -1.142e+00; - } - if( w==50 ) - { - r = -1.205e+00; - } - if( w==49 ) - { - r = -1.270e+00; - } - if( w==48 ) - { - r = -1.339e+00; - } - if( w==47 ) - { - r = -1.409e+00; - } - if( w==46 ) - { - r = -1.482e+00; - } - if( w==45 ) - { - r = -1.558e+00; - } - if( w==44 ) - { - r = -1.636e+00; - } - if( w==43 ) - { - r = -1.717e+00; - } - if( w==42 ) - { - r = -1.801e+00; - } - if( w==41 ) - { - r = -1.888e+00; - } - if( w==40 ) - { - r = -1.977e+00; - } - if( w==39 ) - { - r = -2.070e+00; - } - if( w==38 ) - { - r = -2.166e+00; - } - if( w==37 ) - { - r = -2.265e+00; - } - if( w==36 ) - { - r = -2.366e+00; - } - if( w==35 ) - { - r = -2.472e+00; - } - if( w==34 ) - { - r = -2.581e+00; - } - if( w==33 ) - { - r = -2.693e+00; - } - if( w==32 ) - { - r = -2.809e+00; - } - if( w==31 ) - { - r = -2.928e+00; - } - if( w==30 ) - { - r = -3.051e+00; - } - if( w==29 ) - { - r = -3.179e+00; - } - if( w==28 ) - { - r = -3.310e+00; - } - if( w==27 ) - { - r = -3.446e+00; - } - if( w==26 ) - { - r = -3.587e+00; - } - if( w==25 ) - { - r = -3.732e+00; - } - if( w==24 ) - { - r = -3.881e+00; - } - if( w==23 ) - { - r = -4.036e+00; - } - if( w==22 ) - { - r = -4.195e+00; - } - if( w==21 ) - { - r = -4.359e+00; - } - if( w==20 ) - { - r = -4.531e+00; - } - if( w==19 ) - { - r = -4.707e+00; - } - if( w==18 ) - { - r = -4.888e+00; - } - if( w==17 ) - { - r = -5.079e+00; - } - if( w==16 ) - { - r = -5.273e+00; - } - if( w==15 ) - { - r = -5.477e+00; - } - if( w==14 ) - { - r = -5.697e+00; - } - if( w==13 ) - { - r = -5.920e+00; - } - if( w==12 ) - { - r = -6.149e+00; - } - if( w==11 ) - { - r = -6.390e+00; - } - if( w==10 ) - { - r = -6.636e+00; - } - if( w==9 ) - { - r = -6.901e+00; - } - if( w==8 ) - { - r = -7.178e+00; - } - if( w==7 ) - { - r = -7.453e+00; - } - if( w==6 ) - { - r = -7.758e+00; - } - if( w==5 ) - { - r = -8.095e+00; - } - if( w==4 ) - { - r = -8.451e+00; - } - if( w==3 ) - { - r = -8.788e+00; - } - if( w==2 ) - { - r = -9.299e+00; - } - if( w==1 ) - { - r = -9.704e+00; - } - if( w<=0 ) - { - r = -1.040e+01; - } - result = r; - return result; -} - - -/************************************************************************* -Tail(S, 16) -*************************************************************************/ -static double wsr_w16(double s, ae_state *_state) -{ - ae_int_t w; - double r; - double result; - - - r = (double)(0); - w = ae_round(-1.933908e+01*s+6.800000e+01, _state); - if( w>=68 ) - { - r = -6.733e-01; - } - if( w==67 ) - { - r = -7.134e-01; - } - if( w==66 ) - { - r = -7.551e-01; - } - if( w==65 ) - { - r = -7.986e-01; - } - if( w==64 ) - { - r = -8.437e-01; - } - if( w==63 ) - { - r = -8.905e-01; - } - if( w==62 ) - { - r = -9.391e-01; - } - if( w==61 ) - { - r = -9.895e-01; - } - if( w==60 ) - { - r = -1.042e+00; - } - if( w==59 ) - { - r = -1.096e+00; - } - if( w==58 ) - { - r = -1.152e+00; - } - if( w==57 ) - { - r = -1.210e+00; - } - if( w==56 ) - { - r = -1.270e+00; - } - if( w==55 ) - { - r = -1.331e+00; - } - if( w==54 ) - { - r = -1.395e+00; - } - if( w==53 ) - { - r = -1.462e+00; - } - if( w==52 ) - { - r = -1.530e+00; - } - if( w==51 ) - { - r = -1.600e+00; - } - if( w==50 ) - { - r = -1.673e+00; - } - if( w==49 ) - { - r = -1.748e+00; - } - if( w==48 ) - { - r = -1.825e+00; - } - if( w==47 ) - { - r = -1.904e+00; - } - if( w==46 ) - { - r = -1.986e+00; - } - if( w==45 ) - { - r = -2.071e+00; - } - if( w==44 ) - { - r = -2.158e+00; - } - if( w==43 ) - { - r = -2.247e+00; - } - if( w==42 ) - { - r = -2.339e+00; - } - if( w==41 ) - { - r = -2.434e+00; - } - if( w==40 ) - { - r = -2.532e+00; - } - if( w==39 ) - { - r = -2.632e+00; - } - if( w==38 ) - { - r = -2.735e+00; - } - if( w==37 ) - { - r = -2.842e+00; - } - if( w==36 ) - { - r = -2.951e+00; - } - if( w==35 ) - { - r = -3.064e+00; - } - if( w==34 ) - { - r = -3.179e+00; - } - if( w==33 ) - { - r = -3.298e+00; - } - if( w==32 ) - { - r = -3.420e+00; - } - if( w==31 ) - { - r = -3.546e+00; - } - if( w==30 ) - { - r = -3.676e+00; - } - if( w==29 ) - { - r = -3.810e+00; - } - if( w==28 ) - { - r = -3.947e+00; - } - if( w==27 ) - { - r = -4.088e+00; - } - if( w==26 ) - { - r = -4.234e+00; - } - if( w==25 ) - { - r = -4.383e+00; - } - if( w==24 ) - { - r = -4.538e+00; - } - if( w==23 ) - { - r = -4.697e+00; - } - if( w==22 ) - { - r = -4.860e+00; - } - if( w==21 ) - { - r = -5.029e+00; - } - if( w==20 ) - { - r = -5.204e+00; - } - if( w==19 ) - { - r = -5.383e+00; - } - if( w==18 ) - { - r = -5.569e+00; - } - if( w==17 ) - { - r = -5.762e+00; - } - if( w==16 ) - { - r = -5.960e+00; - } - if( w==15 ) - { - r = -6.170e+00; - } - if( w==14 ) - { - r = -6.390e+00; - } - if( w==13 ) - { - r = -6.613e+00; - } - if( w==12 ) - { - r = -6.842e+00; - } - if( w==11 ) - { - r = -7.083e+00; - } - if( w==10 ) - { - r = -7.329e+00; - } - if( w==9 ) - { - r = -7.594e+00; - } - if( w==8 ) - { - r = -7.871e+00; - } - if( w==7 ) - { - r = -8.146e+00; - } - if( w==6 ) - { - r = -8.451e+00; - } - if( w==5 ) - { - r = -8.788e+00; - } - if( w==4 ) - { - r = -9.144e+00; - } - if( w==3 ) - { - r = -9.481e+00; - } - if( w==2 ) - { - r = -9.992e+00; - } - if( w==1 ) - { - r = -1.040e+01; - } - if( w<=0 ) - { - r = -1.109e+01; - } - result = r; - return result; -} - - -/************************************************************************* -Tail(S, 17) -*************************************************************************/ -static double wsr_w17(double s, ae_state *_state) -{ - ae_int_t w; - double r; - double result; - - - r = (double)(0); - w = ae_round(-2.112463e+01*s+7.650000e+01, _state); - if( w>=76 ) - { - r = -6.931e-01; - } - if( w==75 ) - { - r = -7.306e-01; - } - if( w==74 ) - { - r = -7.695e-01; - } - if( w==73 ) - { - r = -8.097e-01; - } - if( w==72 ) - { - r = -8.514e-01; - } - if( w==71 ) - { - r = -8.946e-01; - } - if( w==70 ) - { - r = -9.392e-01; - } - if( w==69 ) - { - r = -9.853e-01; - } - if( w==68 ) - { - r = -1.033e+00; - } - if( w==67 ) - { - r = -1.082e+00; - } - if( w==66 ) - { - r = -1.133e+00; - } - if( w==65 ) - { - r = -1.185e+00; - } - if( w==64 ) - { - r = -1.240e+00; - } - if( w==63 ) - { - r = -1.295e+00; - } - if( w==62 ) - { - r = -1.353e+00; - } - if( w==61 ) - { - r = -1.412e+00; - } - if( w==60 ) - { - r = -1.473e+00; - } - if( w==59 ) - { - r = -1.536e+00; - } - if( w==58 ) - { - r = -1.600e+00; - } - if( w==57 ) - { - r = -1.666e+00; - } - if( w==56 ) - { - r = -1.735e+00; - } - if( w==55 ) - { - r = -1.805e+00; - } - if( w==54 ) - { - r = -1.877e+00; - } - if( w==53 ) - { - r = -1.951e+00; - } - if( w==52 ) - { - r = -2.028e+00; - } - if( w==51 ) - { - r = -2.106e+00; - } - if( w==50 ) - { - r = -2.186e+00; - } - if( w==49 ) - { - r = -2.269e+00; - } - if( w==48 ) - { - r = -2.353e+00; - } - if( w==47 ) - { - r = -2.440e+00; - } - if( w==46 ) - { - r = -2.530e+00; - } - if( w==45 ) - { - r = -2.621e+00; - } - if( w==44 ) - { - r = -2.715e+00; - } - if( w==43 ) - { - r = -2.812e+00; - } - if( w==42 ) - { - r = -2.911e+00; - } - if( w==41 ) - { - r = -3.012e+00; - } - if( w==40 ) - { - r = -3.116e+00; - } - if( w==39 ) - { - r = -3.223e+00; - } - if( w==38 ) - { - r = -3.332e+00; - } - if( w==37 ) - { - r = -3.445e+00; - } - if( w==36 ) - { - r = -3.560e+00; - } - if( w==35 ) - { - r = -3.678e+00; - } - if( w==34 ) - { - r = -3.799e+00; - } - if( w==33 ) - { - r = -3.924e+00; - } - if( w==32 ) - { - r = -4.052e+00; - } - if( w==31 ) - { - r = -4.183e+00; - } - if( w==30 ) - { - r = -4.317e+00; - } - if( w==29 ) - { - r = -4.456e+00; - } - if( w==28 ) - { - r = -4.597e+00; - } - if( w==27 ) - { - r = -4.743e+00; - } - if( w==26 ) - { - r = -4.893e+00; - } - if( w==25 ) - { - r = -5.047e+00; - } - if( w==24 ) - { - r = -5.204e+00; - } - if( w==23 ) - { - r = -5.367e+00; - } - if( w==22 ) - { - r = -5.534e+00; - } - if( w==21 ) - { - r = -5.706e+00; - } - if( w==20 ) - { - r = -5.884e+00; - } - if( w==19 ) - { - r = -6.066e+00; - } - if( w==18 ) - { - r = -6.254e+00; - } - if( w==17 ) - { - r = -6.451e+00; - } - if( w==16 ) - { - r = -6.654e+00; - } - if( w==15 ) - { - r = -6.864e+00; - } - if( w==14 ) - { - r = -7.083e+00; - } - if( w==13 ) - { - r = -7.306e+00; - } - if( w==12 ) - { - r = -7.535e+00; - } - if( w==11 ) - { - r = -7.776e+00; - } - if( w==10 ) - { - r = -8.022e+00; - } - if( w==9 ) - { - r = -8.287e+00; - } - if( w==8 ) - { - r = -8.565e+00; - } - if( w==7 ) - { - r = -8.839e+00; - } - if( w==6 ) - { - r = -9.144e+00; - } - if( w==5 ) - { - r = -9.481e+00; - } - if( w==4 ) - { - r = -9.838e+00; - } - if( w==3 ) - { - r = -1.017e+01; - } - if( w==2 ) - { - r = -1.068e+01; - } - if( w==1 ) - { - r = -1.109e+01; - } - if( w<=0 ) - { - r = -1.178e+01; - } - result = r; - return result; -} - - -/************************************************************************* -Tail(S, 18) -*************************************************************************/ -static double wsr_w18(double s, ae_state *_state) -{ - ae_int_t w; - double r; - double result; - - - r = (double)(0); - w = ae_round(-2.296193e+01*s+8.550000e+01, _state); - if( w>=85 ) - { - r = -6.931e-01; - } - if( w==84 ) - { - r = -7.276e-01; - } - if( w==83 ) - { - r = -7.633e-01; - } - if( w==82 ) - { - r = -8.001e-01; - } - if( w==81 ) - { - r = -8.381e-01; - } - if( w==80 ) - { - r = -8.774e-01; - } - if( w==79 ) - { - r = -9.179e-01; - } - if( w==78 ) - { - r = -9.597e-01; - } - if( w==77 ) - { - r = -1.003e+00; - } - if( w==76 ) - { - r = -1.047e+00; - } - if( w==75 ) - { - r = -1.093e+00; - } - if( w==74 ) - { - r = -1.140e+00; - } - if( w==73 ) - { - r = -1.188e+00; - } - if( w==72 ) - { - r = -1.238e+00; - } - if( w==71 ) - { - r = -1.289e+00; - } - if( w==70 ) - { - r = -1.342e+00; - } - if( w==69 ) - { - r = -1.396e+00; - } - if( w==68 ) - { - r = -1.452e+00; - } - if( w==67 ) - { - r = -1.509e+00; - } - if( w==66 ) - { - r = -1.568e+00; - } - if( w==65 ) - { - r = -1.628e+00; - } - if( w==64 ) - { - r = -1.690e+00; - } - if( w==63 ) - { - r = -1.753e+00; - } - if( w==62 ) - { - r = -1.818e+00; - } - if( w==61 ) - { - r = -1.885e+00; - } - if( w==60 ) - { - r = -1.953e+00; - } - if( w==59 ) - { - r = -2.023e+00; - } - if( w==58 ) - { - r = -2.095e+00; - } - if( w==57 ) - { - r = -2.168e+00; - } - if( w==56 ) - { - r = -2.244e+00; - } - if( w==55 ) - { - r = -2.321e+00; - } - if( w==54 ) - { - r = -2.400e+00; - } - if( w==53 ) - { - r = -2.481e+00; - } - if( w==52 ) - { - r = -2.564e+00; - } - if( w==51 ) - { - r = -2.648e+00; - } - if( w==50 ) - { - r = -2.735e+00; - } - if( w==49 ) - { - r = -2.824e+00; - } - if( w==48 ) - { - r = -2.915e+00; - } - if( w==47 ) - { - r = -3.008e+00; - } - if( w==46 ) - { - r = -3.104e+00; - } - if( w==45 ) - { - r = -3.201e+00; - } - if( w==44 ) - { - r = -3.301e+00; - } - if( w==43 ) - { - r = -3.403e+00; - } - if( w==42 ) - { - r = -3.508e+00; - } - if( w==41 ) - { - r = -3.615e+00; - } - if( w==40 ) - { - r = -3.724e+00; - } - if( w==39 ) - { - r = -3.836e+00; - } - if( w==38 ) - { - r = -3.950e+00; - } - if( w==37 ) - { - r = -4.068e+00; - } - if( w==36 ) - { - r = -4.188e+00; - } - if( w==35 ) - { - r = -4.311e+00; - } - if( w==34 ) - { - r = -4.437e+00; - } - if( w==33 ) - { - r = -4.565e+00; - } - if( w==32 ) - { - r = -4.698e+00; - } - if( w==31 ) - { - r = -4.833e+00; - } - if( w==30 ) - { - r = -4.971e+00; - } - if( w==29 ) - { - r = -5.113e+00; - } - if( w==28 ) - { - r = -5.258e+00; - } - if( w==27 ) - { - r = -5.408e+00; - } - if( w==26 ) - { - r = -5.561e+00; - } - if( w==25 ) - { - r = -5.717e+00; - } - if( w==24 ) - { - r = -5.878e+00; - } - if( w==23 ) - { - r = -6.044e+00; - } - if( w==22 ) - { - r = -6.213e+00; - } - if( w==21 ) - { - r = -6.388e+00; - } - if( w==20 ) - { - r = -6.569e+00; - } - if( w==19 ) - { - r = -6.753e+00; - } - if( w==18 ) - { - r = -6.943e+00; - } - if( w==17 ) - { - r = -7.144e+00; - } - if( w==16 ) - { - r = -7.347e+00; - } - if( w==15 ) - { - r = -7.557e+00; - } - if( w==14 ) - { - r = -7.776e+00; - } - if( w==13 ) - { - r = -7.999e+00; - } - if( w==12 ) - { - r = -8.228e+00; - } - if( w==11 ) - { - r = -8.469e+00; - } - if( w==10 ) - { - r = -8.715e+00; - } - if( w==9 ) - { - r = -8.980e+00; - } - if( w==8 ) - { - r = -9.258e+00; - } - if( w==7 ) - { - r = -9.532e+00; - } - if( w==6 ) - { - r = -9.838e+00; - } - if( w==5 ) - { - r = -1.017e+01; - } - if( w==4 ) - { - r = -1.053e+01; - } - if( w==3 ) - { - r = -1.087e+01; - } - if( w==2 ) - { - r = -1.138e+01; - } - if( w==1 ) - { - r = -1.178e+01; - } - if( w<=0 ) - { - r = -1.248e+01; - } - result = r; - return result; -} - - -/************************************************************************* -Tail(S, 19) -*************************************************************************/ -static double wsr_w19(double s, ae_state *_state) -{ - ae_int_t w; - double r; - double result; - - - r = (double)(0); - w = ae_round(-2.484955e+01*s+9.500000e+01, _state); - if( w>=95 ) - { - r = -6.776e-01; - } - if( w==94 ) - { - r = -7.089e-01; - } - if( w==93 ) - { - r = -7.413e-01; - } - if( w==92 ) - { - r = -7.747e-01; - } - if( w==91 ) - { - r = -8.090e-01; - } - if( w==90 ) - { - r = -8.445e-01; - } - if( w==89 ) - { - r = -8.809e-01; - } - if( w==88 ) - { - r = -9.185e-01; - } - if( w==87 ) - { - r = -9.571e-01; - } - if( w==86 ) - { - r = -9.968e-01; - } - if( w==85 ) - { - r = -1.038e+00; - } - if( w==84 ) - { - r = -1.080e+00; - } - if( w==83 ) - { - r = -1.123e+00; - } - if( w==82 ) - { - r = -1.167e+00; - } - if( w==81 ) - { - r = -1.213e+00; - } - if( w==80 ) - { - r = -1.259e+00; - } - if( w==79 ) - { - r = -1.307e+00; - } - if( w==78 ) - { - r = -1.356e+00; - } - if( w==77 ) - { - r = -1.407e+00; - } - if( w==76 ) - { - r = -1.458e+00; - } - if( w==75 ) - { - r = -1.511e+00; - } - if( w==74 ) - { - r = -1.565e+00; - } - if( w==73 ) - { - r = -1.621e+00; - } - if( w==72 ) - { - r = -1.678e+00; - } - if( w==71 ) - { - r = -1.736e+00; - } - if( w==70 ) - { - r = -1.796e+00; - } - if( w==69 ) - { - r = -1.857e+00; - } - if( w==68 ) - { - r = -1.919e+00; - } - if( w==67 ) - { - r = -1.983e+00; - } - if( w==66 ) - { - r = -2.048e+00; - } - if( w==65 ) - { - r = -2.115e+00; - } - if( w==64 ) - { - r = -2.183e+00; - } - if( w==63 ) - { - r = -2.253e+00; - } - if( w==62 ) - { - r = -2.325e+00; - } - if( w==61 ) - { - r = -2.398e+00; - } - if( w==60 ) - { - r = -2.472e+00; - } - if( w==59 ) - { - r = -2.548e+00; - } - if( w==58 ) - { - r = -2.626e+00; - } - if( w==57 ) - { - r = -2.706e+00; - } - if( w==56 ) - { - r = -2.787e+00; - } - if( w==55 ) - { - r = -2.870e+00; - } - if( w==54 ) - { - r = -2.955e+00; - } - if( w==53 ) - { - r = -3.042e+00; - } - if( w==52 ) - { - r = -3.130e+00; - } - if( w==51 ) - { - r = -3.220e+00; - } - if( w==50 ) - { - r = -3.313e+00; - } - if( w==49 ) - { - r = -3.407e+00; - } - if( w==48 ) - { - r = -3.503e+00; - } - if( w==47 ) - { - r = -3.601e+00; - } - if( w==46 ) - { - r = -3.702e+00; - } - if( w==45 ) - { - r = -3.804e+00; - } - if( w==44 ) - { - r = -3.909e+00; - } - if( w==43 ) - { - r = -4.015e+00; - } - if( w==42 ) - { - r = -4.125e+00; - } - if( w==41 ) - { - r = -4.236e+00; - } - if( w==40 ) - { - r = -4.350e+00; - } - if( w==39 ) - { - r = -4.466e+00; - } - if( w==38 ) - { - r = -4.585e+00; - } - if( w==37 ) - { - r = -4.706e+00; - } - if( w==36 ) - { - r = -4.830e+00; - } - if( w==35 ) - { - r = -4.957e+00; - } - if( w==34 ) - { - r = -5.086e+00; - } - if( w==33 ) - { - r = -5.219e+00; - } - if( w==32 ) - { - r = -5.355e+00; - } - if( w==31 ) - { - r = -5.493e+00; - } - if( w==30 ) - { - r = -5.634e+00; - } - if( w==29 ) - { - r = -5.780e+00; - } - if( w==28 ) - { - r = -5.928e+00; - } - if( w==27 ) - { - r = -6.080e+00; - } - if( w==26 ) - { - r = -6.235e+00; - } - if( w==25 ) - { - r = -6.394e+00; - } - if( w==24 ) - { - r = -6.558e+00; - } - if( w==23 ) - { - r = -6.726e+00; - } - if( w==22 ) - { - r = -6.897e+00; - } - if( w==21 ) - { - r = -7.074e+00; - } - if( w==20 ) - { - r = -7.256e+00; - } - if( w==19 ) - { - r = -7.443e+00; - } - if( w==18 ) - { - r = -7.636e+00; - } - if( w==17 ) - { - r = -7.837e+00; - } - if( w==16 ) - { - r = -8.040e+00; - } - if( w==15 ) - { - r = -8.250e+00; - } - if( w==14 ) - { - r = -8.469e+00; - } - if( w==13 ) - { - r = -8.692e+00; - } - if( w==12 ) - { - r = -8.921e+00; - } - if( w==11 ) - { - r = -9.162e+00; - } - if( w==10 ) - { - r = -9.409e+00; - } - if( w==9 ) - { - r = -9.673e+00; - } - if( w==8 ) - { - r = -9.951e+00; - } - if( w==7 ) - { - r = -1.023e+01; - } - if( w==6 ) - { - r = -1.053e+01; - } - if( w==5 ) - { - r = -1.087e+01; - } - if( w==4 ) - { - r = -1.122e+01; - } - if( w==3 ) - { - r = -1.156e+01; - } - if( w==2 ) - { - r = -1.207e+01; - } - if( w==1 ) - { - r = -1.248e+01; - } - if( w<=0 ) - { - r = -1.317e+01; - } - result = r; - return result; -} - - -/************************************************************************* -Tail(S, 20) -*************************************************************************/ -static double wsr_w20(double s, ae_state *_state) -{ - ae_int_t w; - double r; - double result; - - - r = (double)(0); - w = ae_round(-2.678619e+01*s+1.050000e+02, _state); - if( w>=105 ) - { - r = -6.787e-01; - } - if( w==104 ) - { - r = -7.078e-01; - } - if( w==103 ) - { - r = -7.378e-01; - } - if( w==102 ) - { - r = -7.686e-01; - } - if( w==101 ) - { - r = -8.004e-01; - } - if( w==100 ) - { - r = -8.330e-01; - } - if( w==99 ) - { - r = -8.665e-01; - } - if( w==98 ) - { - r = -9.010e-01; - } - if( w==97 ) - { - r = -9.363e-01; - } - if( w==96 ) - { - r = -9.726e-01; - } - if( w==95 ) - { - r = -1.010e+00; - } - if( w==94 ) - { - r = -1.048e+00; - } - if( w==93 ) - { - r = -1.087e+00; - } - if( w==92 ) - { - r = -1.128e+00; - } - if( w==91 ) - { - r = -1.169e+00; - } - if( w==90 ) - { - r = -1.211e+00; - } - if( w==89 ) - { - r = -1.254e+00; - } - if( w==88 ) - { - r = -1.299e+00; - } - if( w==87 ) - { - r = -1.344e+00; - } - if( w==86 ) - { - r = -1.390e+00; - } - if( w==85 ) - { - r = -1.438e+00; - } - if( w==84 ) - { - r = -1.486e+00; - } - if( w==83 ) - { - r = -1.536e+00; - } - if( w==82 ) - { - r = -1.587e+00; - } - if( w==81 ) - { - r = -1.639e+00; - } - if( w==80 ) - { - r = -1.692e+00; - } - if( w==79 ) - { - r = -1.746e+00; - } - if( w==78 ) - { - r = -1.802e+00; - } - if( w==77 ) - { - r = -1.859e+00; - } - if( w==76 ) - { - r = -1.916e+00; - } - if( w==75 ) - { - r = -1.976e+00; - } - if( w==74 ) - { - r = -2.036e+00; - } - if( w==73 ) - { - r = -2.098e+00; - } - if( w==72 ) - { - r = -2.161e+00; - } - if( w==71 ) - { - r = -2.225e+00; - } - if( w==70 ) - { - r = -2.290e+00; - } - if( w==69 ) - { - r = -2.357e+00; - } - if( w==68 ) - { - r = -2.426e+00; - } - if( w==67 ) - { - r = -2.495e+00; - } - if( w==66 ) - { - r = -2.566e+00; - } - if( w==65 ) - { - r = -2.639e+00; - } - if( w==64 ) - { - r = -2.713e+00; - } - if( w==63 ) - { - r = -2.788e+00; - } - if( w==62 ) - { - r = -2.865e+00; - } - if( w==61 ) - { - r = -2.943e+00; - } - if( w==60 ) - { - r = -3.023e+00; - } - if( w==59 ) - { - r = -3.104e+00; - } - if( w==58 ) - { - r = -3.187e+00; - } - if( w==57 ) - { - r = -3.272e+00; - } - if( w==56 ) - { - r = -3.358e+00; - } - if( w==55 ) - { - r = -3.446e+00; - } - if( w==54 ) - { - r = -3.536e+00; - } - if( w==53 ) - { - r = -3.627e+00; - } - if( w==52 ) - { - r = -3.721e+00; - } - if( w==51 ) - { - r = -3.815e+00; - } - if( w==50 ) - { - r = -3.912e+00; - } - if( w==49 ) - { - r = -4.011e+00; - } - if( w==48 ) - { - r = -4.111e+00; - } - if( w==47 ) - { - r = -4.214e+00; - } - if( w==46 ) - { - r = -4.318e+00; - } - if( w==45 ) - { - r = -4.425e+00; - } - if( w==44 ) - { - r = -4.534e+00; - } - if( w==43 ) - { - r = -4.644e+00; - } - if( w==42 ) - { - r = -4.757e+00; - } - if( w==41 ) - { - r = -4.872e+00; - } - if( w==40 ) - { - r = -4.990e+00; - } - if( w==39 ) - { - r = -5.109e+00; - } - if( w==38 ) - { - r = -5.232e+00; - } - if( w==37 ) - { - r = -5.356e+00; - } - if( w==36 ) - { - r = -5.484e+00; - } - if( w==35 ) - { - r = -5.614e+00; - } - if( w==34 ) - { - r = -5.746e+00; - } - if( w==33 ) - { - r = -5.882e+00; - } - if( w==32 ) - { - r = -6.020e+00; - } - if( w==31 ) - { - r = -6.161e+00; - } - if( w==30 ) - { - r = -6.305e+00; - } - if( w==29 ) - { - r = -6.453e+00; - } - if( w==28 ) - { - r = -6.603e+00; - } - if( w==27 ) - { - r = -6.757e+00; - } - if( w==26 ) - { - r = -6.915e+00; - } - if( w==25 ) - { - r = -7.076e+00; - } - if( w==24 ) - { - r = -7.242e+00; - } - if( w==23 ) - { - r = -7.411e+00; - } - if( w==22 ) - { - r = -7.584e+00; - } - if( w==21 ) - { - r = -7.763e+00; - } - if( w==20 ) - { - r = -7.947e+00; - } - if( w==19 ) - { - r = -8.136e+00; - } - if( w==18 ) - { - r = -8.330e+00; - } - if( w==17 ) - { - r = -8.530e+00; - } - if( w==16 ) - { - r = -8.733e+00; - } - if( w==15 ) - { - r = -8.943e+00; - } - if( w==14 ) - { - r = -9.162e+00; - } - if( w==13 ) - { - r = -9.386e+00; - } - if( w==12 ) - { - r = -9.614e+00; - } - if( w==11 ) - { - r = -9.856e+00; - } - if( w==10 ) - { - r = -1.010e+01; - } - if( w==9 ) - { - r = -1.037e+01; - } - if( w==8 ) - { - r = -1.064e+01; - } - if( w==7 ) - { - r = -1.092e+01; - } - if( w==6 ) - { - r = -1.122e+01; - } - if( w==5 ) - { - r = -1.156e+01; - } - if( w==4 ) - { - r = -1.192e+01; - } - if( w==3 ) - { - r = -1.225e+01; - } - if( w==2 ) - { - r = -1.276e+01; - } - if( w==1 ) - { - r = -1.317e+01; - } - if( w<=0 ) - { - r = -1.386e+01; - } - result = r; - return result; -} - - -/************************************************************************* -Tail(S, 21) -*************************************************************************/ -static double wsr_w21(double s, ae_state *_state) -{ - ae_int_t w; - double r; - double result; - - - r = (double)(0); - w = ae_round(-2.877064e+01*s+1.155000e+02, _state); - if( w>=115 ) - { - r = -6.931e-01; - } - if( w==114 ) - { - r = -7.207e-01; - } - if( w==113 ) - { - r = -7.489e-01; - } - if( w==112 ) - { - r = -7.779e-01; - } - if( w==111 ) - { - r = -8.077e-01; - } - if( w==110 ) - { - r = -8.383e-01; - } - if( w==109 ) - { - r = -8.697e-01; - } - if( w==108 ) - { - r = -9.018e-01; - } - if( w==107 ) - { - r = -9.348e-01; - } - if( w==106 ) - { - r = -9.685e-01; - } - if( w==105 ) - { - r = -1.003e+00; - } - if( w==104 ) - { - r = -1.039e+00; - } - if( w==103 ) - { - r = -1.075e+00; - } - if( w==102 ) - { - r = -1.112e+00; - } - if( w==101 ) - { - r = -1.150e+00; - } - if( w==100 ) - { - r = -1.189e+00; - } - if( w==99 ) - { - r = -1.229e+00; - } - if( w==98 ) - { - r = -1.269e+00; - } - if( w==97 ) - { - r = -1.311e+00; - } - if( w==96 ) - { - r = -1.353e+00; - } - if( w==95 ) - { - r = -1.397e+00; - } - if( w==94 ) - { - r = -1.441e+00; - } - if( w==93 ) - { - r = -1.486e+00; - } - if( w==92 ) - { - r = -1.533e+00; - } - if( w==91 ) - { - r = -1.580e+00; - } - if( w==90 ) - { - r = -1.628e+00; - } - if( w==89 ) - { - r = -1.677e+00; - } - if( w==88 ) - { - r = -1.728e+00; - } - if( w==87 ) - { - r = -1.779e+00; - } - if( w==86 ) - { - r = -1.831e+00; - } - if( w==85 ) - { - r = -1.884e+00; - } - if( w==84 ) - { - r = -1.939e+00; - } - if( w==83 ) - { - r = -1.994e+00; - } - if( w==82 ) - { - r = -2.051e+00; - } - if( w==81 ) - { - r = -2.108e+00; - } - if( w==80 ) - { - r = -2.167e+00; - } - if( w==79 ) - { - r = -2.227e+00; - } - if( w==78 ) - { - r = -2.288e+00; - } - if( w==77 ) - { - r = -2.350e+00; - } - if( w==76 ) - { - r = -2.414e+00; - } - if( w==75 ) - { - r = -2.478e+00; - } - if( w==74 ) - { - r = -2.544e+00; - } - if( w==73 ) - { - r = -2.611e+00; - } - if( w==72 ) - { - r = -2.679e+00; - } - if( w==71 ) - { - r = -2.748e+00; - } - if( w==70 ) - { - r = -2.819e+00; - } - if( w==69 ) - { - r = -2.891e+00; - } - if( w==68 ) - { - r = -2.964e+00; - } - if( w==67 ) - { - r = -3.039e+00; - } - if( w==66 ) - { - r = -3.115e+00; - } - if( w==65 ) - { - r = -3.192e+00; - } - if( w==64 ) - { - r = -3.270e+00; - } - if( w==63 ) - { - r = -3.350e+00; - } - if( w==62 ) - { - r = -3.432e+00; - } - if( w==61 ) - { - r = -3.515e+00; - } - if( w==60 ) - { - r = -3.599e+00; - } - if( w==59 ) - { - r = -3.685e+00; - } - if( w==58 ) - { - r = -3.772e+00; - } - if( w==57 ) - { - r = -3.861e+00; - } - if( w==56 ) - { - r = -3.952e+00; - } - if( w==55 ) - { - r = -4.044e+00; - } - if( w==54 ) - { - r = -4.138e+00; - } - if( w==53 ) - { - r = -4.233e+00; - } - if( w==52 ) - { - r = -4.330e+00; - } - if( w==51 ) - { - r = -4.429e+00; - } - if( w==50 ) - { - r = -4.530e+00; - } - if( w==49 ) - { - r = -4.632e+00; - } - if( w==48 ) - { - r = -4.736e+00; - } - if( w==47 ) - { - r = -4.842e+00; - } - if( w==46 ) - { - r = -4.950e+00; - } - if( w==45 ) - { - r = -5.060e+00; - } - if( w==44 ) - { - r = -5.172e+00; - } - if( w==43 ) - { - r = -5.286e+00; - } - if( w==42 ) - { - r = -5.402e+00; - } - if( w==41 ) - { - r = -5.520e+00; - } - if( w==40 ) - { - r = -5.641e+00; - } - if( w==39 ) - { - r = -5.763e+00; - } - if( w==38 ) - { - r = -5.889e+00; - } - if( w==37 ) - { - r = -6.016e+00; - } - if( w==36 ) - { - r = -6.146e+00; - } - if( w==35 ) - { - r = -6.278e+00; - } - if( w==34 ) - { - r = -6.413e+00; - } - if( w==33 ) - { - r = -6.551e+00; - } - if( w==32 ) - { - r = -6.692e+00; - } - if( w==31 ) - { - r = -6.835e+00; - } - if( w==30 ) - { - r = -6.981e+00; - } - if( w==29 ) - { - r = -7.131e+00; - } - if( w==28 ) - { - r = -7.283e+00; - } - if( w==27 ) - { - r = -7.439e+00; - } - if( w==26 ) - { - r = -7.599e+00; - } - if( w==25 ) - { - r = -7.762e+00; - } - if( w==24 ) - { - r = -7.928e+00; - } - if( w==23 ) - { - r = -8.099e+00; - } - if( w==22 ) - { - r = -8.274e+00; - } - if( w==21 ) - { - r = -8.454e+00; - } - if( w==20 ) - { - r = -8.640e+00; - } - if( w==19 ) - { - r = -8.829e+00; - } - if( w==18 ) - { - r = -9.023e+00; - } - if( w==17 ) - { - r = -9.223e+00; - } - if( w==16 ) - { - r = -9.426e+00; - } - if( w==15 ) - { - r = -9.636e+00; - } - if( w==14 ) - { - r = -9.856e+00; - } - if( w==13 ) - { - r = -1.008e+01; - } - if( w==12 ) - { - r = -1.031e+01; - } - if( w==11 ) - { - r = -1.055e+01; - } - if( w==10 ) - { - r = -1.079e+01; - } - if( w==9 ) - { - r = -1.106e+01; - } - if( w==8 ) - { - r = -1.134e+01; - } - if( w==7 ) - { - r = -1.161e+01; - } - if( w==6 ) - { - r = -1.192e+01; - } - if( w==5 ) - { - r = -1.225e+01; - } - if( w==4 ) - { - r = -1.261e+01; - } - if( w==3 ) - { - r = -1.295e+01; - } - if( w==2 ) - { - r = -1.346e+01; - } - if( w==1 ) - { - r = -1.386e+01; - } - if( w<=0 ) - { - r = -1.456e+01; - } - result = r; - return result; -} - - -/************************************************************************* -Tail(S, 22) -*************************************************************************/ -static double wsr_w22(double s, ae_state *_state) -{ - ae_int_t w; - double r; - double result; - - - r = (double)(0); - w = ae_round(-3.080179e+01*s+1.265000e+02, _state); - if( w>=126 ) - { - r = -6.931e-01; - } - if( w==125 ) - { - r = -7.189e-01; - } - if( w==124 ) - { - r = -7.452e-01; - } - if( w==123 ) - { - r = -7.722e-01; - } - if( w==122 ) - { - r = -7.999e-01; - } - if( w==121 ) - { - r = -8.283e-01; - } - if( w==120 ) - { - r = -8.573e-01; - } - if( w==119 ) - { - r = -8.871e-01; - } - if( w==118 ) - { - r = -9.175e-01; - } - if( w==117 ) - { - r = -9.486e-01; - } - if( w==116 ) - { - r = -9.805e-01; - } - if( w==115 ) - { - r = -1.013e+00; - } - if( w==114 ) - { - r = -1.046e+00; - } - if( w==113 ) - { - r = -1.080e+00; - } - if( w==112 ) - { - r = -1.115e+00; - } - if( w==111 ) - { - r = -1.151e+00; - } - if( w==110 ) - { - r = -1.187e+00; - } - if( w==109 ) - { - r = -1.224e+00; - } - if( w==108 ) - { - r = -1.262e+00; - } - if( w==107 ) - { - r = -1.301e+00; - } - if( w==106 ) - { - r = -1.340e+00; - } - if( w==105 ) - { - r = -1.381e+00; - } - if( w==104 ) - { - r = -1.422e+00; - } - if( w==103 ) - { - r = -1.464e+00; - } - if( w==102 ) - { - r = -1.506e+00; - } - if( w==101 ) - { - r = -1.550e+00; - } - if( w==100 ) - { - r = -1.594e+00; - } - if( w==99 ) - { - r = -1.640e+00; - } - if( w==98 ) - { - r = -1.686e+00; - } - if( w==97 ) - { - r = -1.733e+00; - } - if( w==96 ) - { - r = -1.781e+00; - } - if( w==95 ) - { - r = -1.830e+00; - } - if( w==94 ) - { - r = -1.880e+00; - } - if( w==93 ) - { - r = -1.930e+00; - } - if( w==92 ) - { - r = -1.982e+00; - } - if( w==91 ) - { - r = -2.034e+00; - } - if( w==90 ) - { - r = -2.088e+00; - } - if( w==89 ) - { - r = -2.142e+00; - } - if( w==88 ) - { - r = -2.198e+00; - } - if( w==87 ) - { - r = -2.254e+00; - } - if( w==86 ) - { - r = -2.312e+00; - } - if( w==85 ) - { - r = -2.370e+00; - } - if( w==84 ) - { - r = -2.429e+00; - } - if( w==83 ) - { - r = -2.490e+00; - } - if( w==82 ) - { - r = -2.551e+00; - } - if( w==81 ) - { - r = -2.614e+00; - } - if( w==80 ) - { - r = -2.677e+00; - } - if( w==79 ) - { - r = -2.742e+00; - } - if( w==78 ) - { - r = -2.808e+00; - } - if( w==77 ) - { - r = -2.875e+00; - } - if( w==76 ) - { - r = -2.943e+00; - } - if( w==75 ) - { - r = -3.012e+00; - } - if( w==74 ) - { - r = -3.082e+00; - } - if( w==73 ) - { - r = -3.153e+00; - } - if( w==72 ) - { - r = -3.226e+00; - } - if( w==71 ) - { - r = -3.300e+00; - } - if( w==70 ) - { - r = -3.375e+00; - } - if( w==69 ) - { - r = -3.451e+00; - } - if( w==68 ) - { - r = -3.529e+00; - } - if( w==67 ) - { - r = -3.607e+00; - } - if( w==66 ) - { - r = -3.687e+00; - } - if( w==65 ) - { - r = -3.769e+00; - } - if( w==64 ) - { - r = -3.851e+00; - } - if( w==63 ) - { - r = -3.935e+00; - } - if( w==62 ) - { - r = -4.021e+00; - } - if( w==61 ) - { - r = -4.108e+00; - } - if( w==60 ) - { - r = -4.196e+00; - } - if( w==59 ) - { - r = -4.285e+00; - } - if( w==58 ) - { - r = -4.376e+00; - } - if( w==57 ) - { - r = -4.469e+00; - } - if( w==56 ) - { - r = -4.563e+00; - } - if( w==55 ) - { - r = -4.659e+00; - } - if( w==54 ) - { - r = -4.756e+00; - } - if( w==53 ) - { - r = -4.855e+00; - } - if( w==52 ) - { - r = -4.955e+00; - } - if( w==51 ) - { - r = -5.057e+00; - } - if( w==50 ) - { - r = -5.161e+00; - } - if( w==49 ) - { - r = -5.266e+00; - } - if( w==48 ) - { - r = -5.374e+00; - } - if( w==47 ) - { - r = -5.483e+00; - } - if( w==46 ) - { - r = -5.594e+00; - } - if( w==45 ) - { - r = -5.706e+00; - } - if( w==44 ) - { - r = -5.821e+00; - } - if( w==43 ) - { - r = -5.938e+00; - } - if( w==42 ) - { - r = -6.057e+00; - } - if( w==41 ) - { - r = -6.177e+00; - } - if( w==40 ) - { - r = -6.300e+00; - } - if( w==39 ) - { - r = -6.426e+00; - } - if( w==38 ) - { - r = -6.553e+00; - } - if( w==37 ) - { - r = -6.683e+00; - } - if( w==36 ) - { - r = -6.815e+00; - } - if( w==35 ) - { - r = -6.949e+00; - } - if( w==34 ) - { - r = -7.086e+00; - } - if( w==33 ) - { - r = -7.226e+00; - } - if( w==32 ) - { - r = -7.368e+00; - } - if( w==31 ) - { - r = -7.513e+00; - } - if( w==30 ) - { - r = -7.661e+00; - } - if( w==29 ) - { - r = -7.813e+00; - } - if( w==28 ) - { - r = -7.966e+00; - } - if( w==27 ) - { - r = -8.124e+00; - } - if( w==26 ) - { - r = -8.285e+00; - } - if( w==25 ) - { - r = -8.449e+00; - } - if( w==24 ) - { - r = -8.617e+00; - } - if( w==23 ) - { - r = -8.789e+00; - } - if( w==22 ) - { - r = -8.965e+00; - } - if( w==21 ) - { - r = -9.147e+00; - } - if( w==20 ) - { - r = -9.333e+00; - } - if( w==19 ) - { - r = -9.522e+00; - } - if( w==18 ) - { - r = -9.716e+00; - } - if( w==17 ) - { - r = -9.917e+00; - } - if( w==16 ) - { - r = -1.012e+01; - } - if( w==15 ) - { - r = -1.033e+01; - } - if( w==14 ) - { - r = -1.055e+01; - } - if( w==13 ) - { - r = -1.077e+01; - } - if( w==12 ) - { - r = -1.100e+01; - } - if( w==11 ) - { - r = -1.124e+01; - } - if( w==10 ) - { - r = -1.149e+01; - } - if( w==9 ) - { - r = -1.175e+01; - } - if( w==8 ) - { - r = -1.203e+01; - } - if( w==7 ) - { - r = -1.230e+01; - } - if( w==6 ) - { - r = -1.261e+01; - } - if( w==5 ) - { - r = -1.295e+01; - } - if( w==4 ) - { - r = -1.330e+01; - } - if( w==3 ) - { - r = -1.364e+01; - } - if( w==2 ) - { - r = -1.415e+01; - } - if( w==1 ) - { - r = -1.456e+01; - } - if( w<=0 ) - { - r = -1.525e+01; - } - result = r; - return result; -} - - -/************************************************************************* -Tail(S, 23) -*************************************************************************/ -static double wsr_w23(double s, ae_state *_state) -{ - ae_int_t w; - double r; - double result; - - - r = (double)(0); - w = ae_round(-3.287856e+01*s+1.380000e+02, _state); - if( w>=138 ) - { - r = -6.813e-01; - } - if( w==137 ) - { - r = -7.051e-01; - } - if( w==136 ) - { - r = -7.295e-01; - } - if( w==135 ) - { - r = -7.544e-01; - } - if( w==134 ) - { - r = -7.800e-01; - } - if( w==133 ) - { - r = -8.061e-01; - } - if( w==132 ) - { - r = -8.328e-01; - } - if( w==131 ) - { - r = -8.601e-01; - } - if( w==130 ) - { - r = -8.880e-01; - } - if( w==129 ) - { - r = -9.166e-01; - } - if( w==128 ) - { - r = -9.457e-01; - } - if( w==127 ) - { - r = -9.755e-01; - } - if( w==126 ) - { - r = -1.006e+00; - } - if( w==125 ) - { - r = -1.037e+00; - } - if( w==124 ) - { - r = -1.069e+00; - } - if( w==123 ) - { - r = -1.101e+00; - } - if( w==122 ) - { - r = -1.134e+00; - } - if( w==121 ) - { - r = -1.168e+00; - } - if( w==120 ) - { - r = -1.202e+00; - } - if( w==119 ) - { - r = -1.237e+00; - } - if( w==118 ) - { - r = -1.273e+00; - } - if( w==117 ) - { - r = -1.309e+00; - } - if( w==116 ) - { - r = -1.347e+00; - } - if( w==115 ) - { - r = -1.384e+00; - } - if( w==114 ) - { - r = -1.423e+00; - } - if( w==113 ) - { - r = -1.462e+00; - } - if( w==112 ) - { - r = -1.502e+00; - } - if( w==111 ) - { - r = -1.543e+00; - } - if( w==110 ) - { - r = -1.585e+00; - } - if( w==109 ) - { - r = -1.627e+00; - } - if( w==108 ) - { - r = -1.670e+00; - } - if( w==107 ) - { - r = -1.714e+00; - } - if( w==106 ) - { - r = -1.758e+00; - } - if( w==105 ) - { - r = -1.804e+00; - } - if( w==104 ) - { - r = -1.850e+00; - } - if( w==103 ) - { - r = -1.897e+00; - } - if( w==102 ) - { - r = -1.944e+00; - } - if( w==101 ) - { - r = -1.993e+00; - } - if( w==100 ) - { - r = -2.042e+00; - } - if( w==99 ) - { - r = -2.093e+00; - } - if( w==98 ) - { - r = -2.144e+00; - } - if( w==97 ) - { - r = -2.195e+00; - } - if( w==96 ) - { - r = -2.248e+00; - } - if( w==95 ) - { - r = -2.302e+00; - } - if( w==94 ) - { - r = -2.356e+00; - } - if( w==93 ) - { - r = -2.412e+00; - } - if( w==92 ) - { - r = -2.468e+00; - } - if( w==91 ) - { - r = -2.525e+00; - } - if( w==90 ) - { - r = -2.583e+00; - } - if( w==89 ) - { - r = -2.642e+00; - } - if( w==88 ) - { - r = -2.702e+00; - } - if( w==87 ) - { - r = -2.763e+00; - } - if( w==86 ) - { - r = -2.825e+00; - } - if( w==85 ) - { - r = -2.888e+00; - } - if( w==84 ) - { - r = -2.951e+00; - } - if( w==83 ) - { - r = -3.016e+00; - } - if( w==82 ) - { - r = -3.082e+00; - } - if( w==81 ) - { - r = -3.149e+00; - } - if( w==80 ) - { - r = -3.216e+00; - } - if( w==79 ) - { - r = -3.285e+00; - } - if( w==78 ) - { - r = -3.355e+00; - } - if( w==77 ) - { - r = -3.426e+00; - } - if( w==76 ) - { - r = -3.498e+00; - } - if( w==75 ) - { - r = -3.571e+00; - } - if( w==74 ) - { - r = -3.645e+00; - } - if( w==73 ) - { - r = -3.721e+00; - } - if( w==72 ) - { - r = -3.797e+00; - } - if( w==71 ) - { - r = -3.875e+00; - } - if( w==70 ) - { - r = -3.953e+00; - } - if( w==69 ) - { - r = -4.033e+00; - } - if( w==68 ) - { - r = -4.114e+00; - } - if( w==67 ) - { - r = -4.197e+00; - } - if( w==66 ) - { - r = -4.280e+00; - } - if( w==65 ) - { - r = -4.365e+00; - } - if( w==64 ) - { - r = -4.451e+00; - } - if( w==63 ) - { - r = -4.539e+00; - } - if( w==62 ) - { - r = -4.628e+00; - } - if( w==61 ) - { - r = -4.718e+00; - } - if( w==60 ) - { - r = -4.809e+00; - } - if( w==59 ) - { - r = -4.902e+00; - } - if( w==58 ) - { - r = -4.996e+00; - } - if( w==57 ) - { - r = -5.092e+00; - } - if( w==56 ) - { - r = -5.189e+00; - } - if( w==55 ) - { - r = -5.287e+00; - } - if( w==54 ) - { - r = -5.388e+00; - } - if( w==53 ) - { - r = -5.489e+00; - } - if( w==52 ) - { - r = -5.592e+00; - } - if( w==51 ) - { - r = -5.697e+00; - } - if( w==50 ) - { - r = -5.804e+00; - } - if( w==49 ) - { - r = -5.912e+00; - } - if( w==48 ) - { - r = -6.022e+00; - } - if( w==47 ) - { - r = -6.133e+00; - } - if( w==46 ) - { - r = -6.247e+00; - } - if( w==45 ) - { - r = -6.362e+00; - } - if( w==44 ) - { - r = -6.479e+00; - } - if( w==43 ) - { - r = -6.598e+00; - } - if( w==42 ) - { - r = -6.719e+00; - } - if( w==41 ) - { - r = -6.842e+00; - } - if( w==40 ) - { - r = -6.967e+00; - } - if( w==39 ) - { - r = -7.094e+00; - } - if( w==38 ) - { - r = -7.224e+00; - } - if( w==37 ) - { - r = -7.355e+00; - } - if( w==36 ) - { - r = -7.489e+00; - } - if( w==35 ) - { - r = -7.625e+00; - } - if( w==34 ) - { - r = -7.764e+00; - } - if( w==33 ) - { - r = -7.905e+00; - } - if( w==32 ) - { - r = -8.049e+00; - } - if( w==31 ) - { - r = -8.196e+00; - } - if( w==30 ) - { - r = -8.345e+00; - } - if( w==29 ) - { - r = -8.498e+00; - } - if( w==28 ) - { - r = -8.653e+00; - } - if( w==27 ) - { - r = -8.811e+00; - } - if( w==26 ) - { - r = -8.974e+00; - } - if( w==25 ) - { - r = -9.139e+00; - } - if( w==24 ) - { - r = -9.308e+00; - } - if( w==23 ) - { - r = -9.481e+00; - } - if( w==22 ) - { - r = -9.658e+00; - } - if( w==21 ) - { - r = -9.840e+00; - } - if( w==20 ) - { - r = -1.003e+01; - } - if( w==19 ) - { - r = -1.022e+01; - } - if( w==18 ) - { - r = -1.041e+01; - } - if( w==17 ) - { - r = -1.061e+01; - } - if( w==16 ) - { - r = -1.081e+01; - } - if( w==15 ) - { - r = -1.102e+01; - } - if( w==14 ) - { - r = -1.124e+01; - } - if( w==13 ) - { - r = -1.147e+01; - } - if( w==12 ) - { - r = -1.169e+01; - } - if( w==11 ) - { - r = -1.194e+01; - } - if( w==10 ) - { - r = -1.218e+01; - } - if( w==9 ) - { - r = -1.245e+01; - } - if( w==8 ) - { - r = -1.272e+01; - } - if( w==7 ) - { - r = -1.300e+01; - } - if( w==6 ) - { - r = -1.330e+01; - } - if( w==5 ) - { - r = -1.364e+01; - } - if( w==4 ) - { - r = -1.400e+01; - } - if( w==3 ) - { - r = -1.433e+01; - } - if( w==2 ) - { - r = -1.484e+01; - } - if( w==1 ) - { - r = -1.525e+01; - } - if( w<=0 ) - { - r = -1.594e+01; - } - result = r; - return result; -} - - -/************************************************************************* -Tail(S, 24) -*************************************************************************/ -static double wsr_w24(double s, ae_state *_state) -{ - ae_int_t w; - double r; - double result; - - - r = (double)(0); - w = ae_round(-3.500000e+01*s+1.500000e+02, _state); - if( w>=150 ) - { - r = -6.820e-01; - } - if( w==149 ) - { - r = -7.044e-01; - } - if( w==148 ) - { - r = -7.273e-01; - } - if( w==147 ) - { - r = -7.507e-01; - } - if( w==146 ) - { - r = -7.746e-01; - } - if( w==145 ) - { - r = -7.990e-01; - } - if( w==144 ) - { - r = -8.239e-01; - } - if( w==143 ) - { - r = -8.494e-01; - } - if( w==142 ) - { - r = -8.754e-01; - } - if( w==141 ) - { - r = -9.020e-01; - } - if( w==140 ) - { - r = -9.291e-01; - } - if( w==139 ) - { - r = -9.567e-01; - } - if( w==138 ) - { - r = -9.849e-01; - } - if( w==137 ) - { - r = -1.014e+00; - } - if( w==136 ) - { - r = -1.043e+00; - } - if( w==135 ) - { - r = -1.073e+00; - } - if( w==134 ) - { - r = -1.103e+00; - } - if( w==133 ) - { - r = -1.135e+00; - } - if( w==132 ) - { - r = -1.166e+00; - } - if( w==131 ) - { - r = -1.198e+00; - } - if( w==130 ) - { - r = -1.231e+00; - } - if( w==129 ) - { - r = -1.265e+00; - } - if( w==128 ) - { - r = -1.299e+00; - } - if( w==127 ) - { - r = -1.334e+00; - } - if( w==126 ) - { - r = -1.369e+00; - } - if( w==125 ) - { - r = -1.405e+00; - } - if( w==124 ) - { - r = -1.441e+00; - } - if( w==123 ) - { - r = -1.479e+00; - } - if( w==122 ) - { - r = -1.517e+00; - } - if( w==121 ) - { - r = -1.555e+00; - } - if( w==120 ) - { - r = -1.594e+00; - } - if( w==119 ) - { - r = -1.634e+00; - } - if( w==118 ) - { - r = -1.675e+00; - } - if( w==117 ) - { - r = -1.716e+00; - } - if( w==116 ) - { - r = -1.758e+00; - } - if( w==115 ) - { - r = -1.800e+00; - } - if( w==114 ) - { - r = -1.844e+00; - } - if( w==113 ) - { - r = -1.888e+00; - } - if( w==112 ) - { - r = -1.932e+00; - } - if( w==111 ) - { - r = -1.978e+00; - } - if( w==110 ) - { - r = -2.024e+00; - } - if( w==109 ) - { - r = -2.070e+00; - } - if( w==108 ) - { - r = -2.118e+00; - } - if( w==107 ) - { - r = -2.166e+00; - } - if( w==106 ) - { - r = -2.215e+00; - } - if( w==105 ) - { - r = -2.265e+00; - } - if( w==104 ) - { - r = -2.316e+00; - } - if( w==103 ) - { - r = -2.367e+00; - } - if( w==102 ) - { - r = -2.419e+00; - } - if( w==101 ) - { - r = -2.472e+00; - } - if( w==100 ) - { - r = -2.526e+00; - } - if( w==99 ) - { - r = -2.580e+00; - } - if( w==98 ) - { - r = -2.636e+00; - } - if( w==97 ) - { - r = -2.692e+00; - } - if( w==96 ) - { - r = -2.749e+00; - } - if( w==95 ) - { - r = -2.806e+00; - } - if( w==94 ) - { - r = -2.865e+00; - } - if( w==93 ) - { - r = -2.925e+00; - } - if( w==92 ) - { - r = -2.985e+00; - } - if( w==91 ) - { - r = -3.046e+00; - } - if( w==90 ) - { - r = -3.108e+00; - } - if( w==89 ) - { - r = -3.171e+00; - } - if( w==88 ) - { - r = -3.235e+00; - } - if( w==87 ) - { - r = -3.300e+00; - } - if( w==86 ) - { - r = -3.365e+00; - } - if( w==85 ) - { - r = -3.432e+00; - } - if( w==84 ) - { - r = -3.499e+00; - } - if( w==83 ) - { - r = -3.568e+00; - } - if( w==82 ) - { - r = -3.637e+00; - } - if( w==81 ) - { - r = -3.708e+00; - } - if( w==80 ) - { - r = -3.779e+00; - } - if( w==79 ) - { - r = -3.852e+00; - } - if( w==78 ) - { - r = -3.925e+00; - } - if( w==77 ) - { - r = -4.000e+00; - } - if( w==76 ) - { - r = -4.075e+00; - } - if( w==75 ) - { - r = -4.151e+00; - } - if( w==74 ) - { - r = -4.229e+00; - } - if( w==73 ) - { - r = -4.308e+00; - } - if( w==72 ) - { - r = -4.387e+00; - } - if( w==71 ) - { - r = -4.468e+00; - } - if( w==70 ) - { - r = -4.550e+00; - } - if( w==69 ) - { - r = -4.633e+00; - } - if( w==68 ) - { - r = -4.718e+00; - } - if( w==67 ) - { - r = -4.803e+00; - } - if( w==66 ) - { - r = -4.890e+00; - } - if( w==65 ) - { - r = -4.978e+00; - } - if( w==64 ) - { - r = -5.067e+00; - } - if( w==63 ) - { - r = -5.157e+00; - } - if( w==62 ) - { - r = -5.249e+00; - } - if( w==61 ) - { - r = -5.342e+00; - } - if( w==60 ) - { - r = -5.436e+00; - } - if( w==59 ) - { - r = -5.531e+00; - } - if( w==58 ) - { - r = -5.628e+00; - } - if( w==57 ) - { - r = -5.727e+00; - } - if( w==56 ) - { - r = -5.826e+00; - } - if( w==55 ) - { - r = -5.927e+00; - } - if( w==54 ) - { - r = -6.030e+00; - } - if( w==53 ) - { - r = -6.134e+00; - } - if( w==52 ) - { - r = -6.240e+00; - } - if( w==51 ) - { - r = -6.347e+00; - } - if( w==50 ) - { - r = -6.456e+00; - } - if( w==49 ) - { - r = -6.566e+00; - } - if( w==48 ) - { - r = -6.678e+00; - } - if( w==47 ) - { - r = -6.792e+00; - } - if( w==46 ) - { - r = -6.907e+00; - } - if( w==45 ) - { - r = -7.025e+00; - } - if( w==44 ) - { - r = -7.144e+00; - } - if( w==43 ) - { - r = -7.265e+00; - } - if( w==42 ) - { - r = -7.387e+00; - } - if( w==41 ) - { - r = -7.512e+00; - } - if( w==40 ) - { - r = -7.639e+00; - } - if( w==39 ) - { - r = -7.768e+00; - } - if( w==38 ) - { - r = -7.899e+00; - } - if( w==37 ) - { - r = -8.032e+00; - } - if( w==36 ) - { - r = -8.167e+00; - } - if( w==35 ) - { - r = -8.305e+00; - } - if( w==34 ) - { - r = -8.445e+00; - } - if( w==33 ) - { - r = -8.588e+00; - } - if( w==32 ) - { - r = -8.733e+00; - } - if( w==31 ) - { - r = -8.881e+00; - } - if( w==30 ) - { - r = -9.031e+00; - } - if( w==29 ) - { - r = -9.185e+00; - } - if( w==28 ) - { - r = -9.341e+00; - } - if( w==27 ) - { - r = -9.501e+00; - } - if( w==26 ) - { - r = -9.664e+00; - } - if( w==25 ) - { - r = -9.830e+00; - } - if( w==24 ) - { - r = -1.000e+01; - } - if( w==23 ) - { - r = -1.017e+01; - } - if( w==22 ) - { - r = -1.035e+01; - } - if( w==21 ) - { - r = -1.053e+01; - } - if( w==20 ) - { - r = -1.072e+01; - } - if( w==19 ) - { - r = -1.091e+01; - } - if( w==18 ) - { - r = -1.110e+01; - } - if( w==17 ) - { - r = -1.130e+01; - } - if( w==16 ) - { - r = -1.151e+01; - } - if( w==15 ) - { - r = -1.172e+01; - } - if( w==14 ) - { - r = -1.194e+01; - } - if( w==13 ) - { - r = -1.216e+01; - } - if( w==12 ) - { - r = -1.239e+01; - } - if( w==11 ) - { - r = -1.263e+01; - } - if( w==10 ) - { - r = -1.287e+01; - } - if( w==9 ) - { - r = -1.314e+01; - } - if( w==8 ) - { - r = -1.342e+01; - } - if( w==7 ) - { - r = -1.369e+01; - } - if( w==6 ) - { - r = -1.400e+01; - } - if( w==5 ) - { - r = -1.433e+01; - } - if( w==4 ) - { - r = -1.469e+01; - } - if( w==3 ) - { - r = -1.503e+01; - } - if( w==2 ) - { - r = -1.554e+01; - } - if( w==1 ) - { - r = -1.594e+01; - } - if( w<=0 ) - { - r = -1.664e+01; - } - result = r; - return result; -} - - -/************************************************************************* -Tail(S, 25) -*************************************************************************/ -static double wsr_w25(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/4.000000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - wsr_wcheb(x, -5.150509e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -5.695528e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.437637e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -2.611906e-01, &tj, &tj1, &result, _state); - wsr_wcheb(x, -7.625722e-02, &tj, &tj1, &result, _state); - wsr_wcheb(x, -2.579892e-02, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.086876e-02, &tj, &tj1, &result, _state); - wsr_wcheb(x, -2.906543e-03, &tj, &tj1, &result, _state); - wsr_wcheb(x, -2.354881e-03, &tj, &tj1, &result, _state); - wsr_wcheb(x, 1.007195e-04, &tj, &tj1, &result, _state); - wsr_wcheb(x, -8.437327e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 26) -*************************************************************************/ -static double wsr_w26(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/4.000000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - wsr_wcheb(x, -5.117622e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -5.635159e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.395167e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -2.382823e-01, &tj, &tj1, &result, _state); - wsr_wcheb(x, -6.531987e-02, &tj, &tj1, &result, _state); - wsr_wcheb(x, -2.060112e-02, &tj, &tj1, &result, _state); - wsr_wcheb(x, -8.203697e-03, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.516523e-03, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.431364e-03, &tj, &tj1, &result, _state); - wsr_wcheb(x, 6.384553e-04, &tj, &tj1, &result, _state); - wsr_wcheb(x, -3.238369e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 27) -*************************************************************************/ -static double wsr_w27(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/4.000000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - wsr_wcheb(x, -5.089731e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -5.584248e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.359966e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -2.203696e-01, &tj, &tj1, &result, _state); - wsr_wcheb(x, -5.753344e-02, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.761891e-02, &tj, &tj1, &result, _state); - wsr_wcheb(x, -7.096897e-03, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.419108e-03, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.581214e-03, &tj, &tj1, &result, _state); - wsr_wcheb(x, 3.033766e-04, &tj, &tj1, &result, _state); - wsr_wcheb(x, -5.901441e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 28) -*************************************************************************/ -static double wsr_w28(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/4.000000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - wsr_wcheb(x, -5.065046e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -5.539163e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.328939e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -2.046376e-01, &tj, &tj1, &result, _state); - wsr_wcheb(x, -5.061515e-02, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.469271e-02, &tj, &tj1, &result, _state); - wsr_wcheb(x, -5.711578e-03, &tj, &tj1, &result, _state); - wsr_wcheb(x, -8.389153e-04, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.250575e-03, &tj, &tj1, &result, _state); - wsr_wcheb(x, 4.047245e-04, &tj, &tj1, &result, _state); - wsr_wcheb(x, -5.128555e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 29) -*************************************************************************/ -static double wsr_w29(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/4.000000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - wsr_wcheb(x, -5.043413e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -5.499756e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.302137e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.915129e-01, &tj, &tj1, &result, _state); - wsr_wcheb(x, -4.516329e-02, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.260064e-02, &tj, &tj1, &result, _state); - wsr_wcheb(x, -4.817269e-03, &tj, &tj1, &result, _state); - wsr_wcheb(x, -5.478130e-04, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.111668e-03, &tj, &tj1, &result, _state); - wsr_wcheb(x, 4.093451e-04, &tj, &tj1, &result, _state); - wsr_wcheb(x, -5.135860e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 30) -*************************************************************************/ -static double wsr_w30(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/4.000000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - wsr_wcheb(x, -5.024071e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -5.464515e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.278342e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.800030e-01, &tj, &tj1, &result, _state); - wsr_wcheb(x, -4.046294e-02, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.076162e-02, &tj, &tj1, &result, _state); - wsr_wcheb(x, -3.968677e-03, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.911679e-04, &tj, &tj1, &result, _state); - wsr_wcheb(x, -8.619185e-04, &tj, &tj1, &result, _state); - wsr_wcheb(x, 5.125362e-04, &tj, &tj1, &result, _state); - wsr_wcheb(x, -3.984370e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 40) -*************************************************************************/ -static double wsr_w40(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/4.000000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - wsr_wcheb(x, -4.904809e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -5.248327e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.136698e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.170982e-01, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.824427e-02, &tj, &tj1, &result, _state); - wsr_wcheb(x, -3.888648e-03, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.344929e-03, &tj, &tj1, &result, _state); - wsr_wcheb(x, 2.790407e-04, &tj, &tj1, &result, _state); - wsr_wcheb(x, -4.619858e-04, &tj, &tj1, &result, _state); - wsr_wcheb(x, 3.359121e-04, &tj, &tj1, &result, _state); - wsr_wcheb(x, -2.883026e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 60) -*************************************************************************/ -static double wsr_w60(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/4.000000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - wsr_wcheb(x, -4.809656e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -5.077191e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.029402e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -7.507931e-02, &tj, &tj1, &result, _state); - wsr_wcheb(x, -6.506226e-03, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.391278e-03, &tj, &tj1, &result, _state); - wsr_wcheb(x, -4.263635e-04, &tj, &tj1, &result, _state); - wsr_wcheb(x, 2.302271e-04, &tj, &tj1, &result, _state); - wsr_wcheb(x, -2.384348e-04, &tj, &tj1, &result, _state); - wsr_wcheb(x, 1.865587e-04, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.622355e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 120) -*************************************************************************/ -static double wsr_w120(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/4.000000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - wsr_wcheb(x, -4.729426e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -4.934426e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -9.433231e-01, &tj, &tj1, &result, _state); - wsr_wcheb(x, -4.492504e-02, &tj, &tj1, &result, _state); - wsr_wcheb(x, 1.673948e-05, &tj, &tj1, &result, _state); - wsr_wcheb(x, -6.077014e-04, &tj, &tj1, &result, _state); - wsr_wcheb(x, -7.215768e-05, &tj, &tj1, &result, _state); - wsr_wcheb(x, 9.086734e-05, &tj, &tj1, &result, _state); - wsr_wcheb(x, -8.447980e-05, &tj, &tj1, &result, _state); - wsr_wcheb(x, 6.705028e-05, &tj, &tj1, &result, _state); - wsr_wcheb(x, -5.828507e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 200) -*************************************************************************/ -static double wsr_w200(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/4.000000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - wsr_wcheb(x, -4.700240e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -4.883080e+00, &tj, &tj1, &result, _state); - wsr_wcheb(x, -9.132168e-01, &tj, &tj1, &result, _state); - wsr_wcheb(x, -3.512684e-02, &tj, &tj1, &result, _state); - wsr_wcheb(x, 1.726342e-03, &tj, &tj1, &result, _state); - wsr_wcheb(x, -5.189796e-04, &tj, &tj1, &result, _state); - wsr_wcheb(x, -1.628659e-06, &tj, &tj1, &result, _state); - wsr_wcheb(x, 4.261786e-05, &tj, &tj1, &result, _state); - wsr_wcheb(x, -4.002498e-05, &tj, &tj1, &result, _state); - wsr_wcheb(x, 3.146287e-05, &tj, &tj1, &result, _state); - wsr_wcheb(x, -2.727576e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S,N), S>=0 -*************************************************************************/ -static double wsr_wsigma(double s, ae_int_t n, ae_state *_state) -{ - double f0; - double f1; - double f2; - double f3; - double f4; - double x0; - double x1; - double x2; - double x3; - double x4; - double x; - double result; - - - result = (double)(0); - if( n==5 ) - { - result = wsr_w5(s, _state); - } - if( n==6 ) - { - result = wsr_w6(s, _state); - } - if( n==7 ) - { - result = wsr_w7(s, _state); - } - if( n==8 ) - { - result = wsr_w8(s, _state); - } - if( n==9 ) - { - result = wsr_w9(s, _state); - } - if( n==10 ) - { - result = wsr_w10(s, _state); - } - if( n==11 ) - { - result = wsr_w11(s, _state); - } - if( n==12 ) - { - result = wsr_w12(s, _state); - } - if( n==13 ) - { - result = wsr_w13(s, _state); - } - if( n==14 ) - { - result = wsr_w14(s, _state); - } - if( n==15 ) - { - result = wsr_w15(s, _state); - } - if( n==16 ) - { - result = wsr_w16(s, _state); - } - if( n==17 ) - { - result = wsr_w17(s, _state); - } - if( n==18 ) - { - result = wsr_w18(s, _state); - } - if( n==19 ) - { - result = wsr_w19(s, _state); - } - if( n==20 ) - { - result = wsr_w20(s, _state); - } - if( n==21 ) - { - result = wsr_w21(s, _state); - } - if( n==22 ) - { - result = wsr_w22(s, _state); - } - if( n==23 ) - { - result = wsr_w23(s, _state); - } - if( n==24 ) - { - result = wsr_w24(s, _state); - } - if( n==25 ) - { - result = wsr_w25(s, _state); - } - if( n==26 ) - { - result = wsr_w26(s, _state); - } - if( n==27 ) - { - result = wsr_w27(s, _state); - } - if( n==28 ) - { - result = wsr_w28(s, _state); - } - if( n==29 ) - { - result = wsr_w29(s, _state); - } - if( n==30 ) - { - result = wsr_w30(s, _state); - } - if( n>30 ) - { - x = 1.0/n; - x0 = 1.0/30; - f0 = wsr_w30(s, _state); - x1 = 1.0/40; - f1 = wsr_w40(s, _state); - x2 = 1.0/60; - f2 = wsr_w60(s, _state); - x3 = 1.0/120; - f3 = wsr_w120(s, _state); - x4 = 1.0/200; - f4 = wsr_w200(s, _state); - f1 = ((x-x0)*f1-(x-x1)*f0)/(x1-x0); - f2 = ((x-x0)*f2-(x-x2)*f0)/(x2-x0); - f3 = ((x-x0)*f3-(x-x3)*f0)/(x3-x0); - f4 = ((x-x0)*f4-(x-x4)*f0)/(x4-x0); - f2 = ((x-x1)*f2-(x-x2)*f1)/(x2-x1); - f3 = ((x-x1)*f3-(x-x3)*f1)/(x3-x1); - f4 = ((x-x1)*f4-(x-x4)*f1)/(x4-x1); - f3 = ((x-x2)*f3-(x-x3)*f2)/(x3-x2); - f4 = ((x-x2)*f4-(x-x4)*f2)/(x4-x2); - f4 = ((x-x3)*f4-(x-x4)*f3)/(x4-x3); - result = f4; - } - return result; -} - - -#endif -#if defined(AE_COMPILE_STEST) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Sign test - -This test checks three hypotheses about the median of the given sample. -The following tests are performed: - * two-tailed test (null hypothesis - the median is equal to the given - value) - * left-tailed test (null hypothesis - the median is greater than or - equal to the given value) - * right-tailed test (null hypothesis - the median is less than or - equal to the given value) - -Requirements: - * the scale of measurement should be ordinal, interval or ratio (i.e. - the test could not be applied to nominal variables). - -The test is non-parametric and doesn't require distribution X to be normal - -Input parameters: - X - sample. Array whose index goes from 0 to N-1. - N - size of the sample. - Median - assumed median value. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -While calculating p-values high-precision binomial distribution -approximation is used, so significance levels have about 15 exact digits. - - -- ALGLIB -- - Copyright 08.09.2006 by Bochkanov Sergey -*************************************************************************/ -void onesamplesigntest(/* Real */ ae_vector* x, - ae_int_t n, - double median, - double* bothtails, - double* lefttail, - double* righttail, - ae_state *_state) -{ - ae_int_t i; - ae_int_t gtcnt; - ae_int_t necnt; - - *bothtails = 0; - *lefttail = 0; - *righttail = 0; - - if( n<=1 ) - { - *bothtails = 1.0; - *lefttail = 1.0; - *righttail = 1.0; - return; - } - - /* - * Calculate: - * GTCnt - count of x[i]>Median - * NECnt - count of x[i]<>Median - */ - gtcnt = 0; - necnt = 0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(x->ptr.p_double[i],median) ) - { - gtcnt = gtcnt+1; - } - if( ae_fp_neq(x->ptr.p_double[i],median) ) - { - necnt = necnt+1; - } - } - if( necnt==0 ) - { - - /* - * all x[i] are equal to Median. - * So we can conclude that Median is a true median :) - */ - *bothtails = 1.0; - *lefttail = 1.0; - *righttail = 1.0; - return; - } - *bothtails = ae_minreal(2*binomialdistribution(ae_minint(gtcnt, necnt-gtcnt, _state), necnt, 0.5, _state), 1.0, _state); - *lefttail = binomialdistribution(gtcnt, necnt, 0.5, _state); - *righttail = binomialcdistribution(gtcnt-1, necnt, 0.5, _state); -} - - -#endif -#if defined(AE_COMPILE_CORRELATIONTESTS) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Pearson's correlation coefficient significance test - -This test checks hypotheses about whether X and Y are samples of two -continuous distributions having zero correlation or whether their -correlation is non-zero. - -The following tests are performed: - * two-tailed test (null hypothesis - X and Y have zero correlation) - * left-tailed test (null hypothesis - the correlation coefficient is - greater than or equal to 0) - * right-tailed test (null hypothesis - the correlation coefficient is - less than or equal to 0). - -Requirements: - * the number of elements in each sample is not less than 5 - * normality of distributions of X and Y. - -Input parameters: - R - Pearson's correlation coefficient for X and Y - N - number of elements in samples, N>=5. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -void pearsoncorrelationsignificance(double r, - ae_int_t n, - double* bothtails, - double* lefttail, - double* righttail, - ae_state *_state) -{ - double t; - double p; - - *bothtails = 0; - *lefttail = 0; - *righttail = 0; - - - /* - * Some special cases - */ - if( ae_fp_greater_eq(r,(double)(1)) ) - { - *bothtails = 0.0; - *lefttail = 1.0; - *righttail = 0.0; - return; - } - if( ae_fp_less_eq(r,(double)(-1)) ) - { - *bothtails = 0.0; - *lefttail = 0.0; - *righttail = 1.0; - return; - } - if( n<5 ) - { - *bothtails = 1.0; - *lefttail = 1.0; - *righttail = 1.0; - return; - } - - /* - * General case - */ - t = r*ae_sqrt((n-2)/(1-ae_sqr(r, _state)), _state); - p = studenttdistribution(n-2, t, _state); - *bothtails = 2*ae_minreal(p, 1-p, _state); - *lefttail = p; - *righttail = 1-p; -} - - -/************************************************************************* -Spearman's rank correlation coefficient significance test - -This test checks hypotheses about whether X and Y are samples of two -continuous distributions having zero correlation or whether their -correlation is non-zero. - -The following tests are performed: - * two-tailed test (null hypothesis - X and Y have zero correlation) - * left-tailed test (null hypothesis - the correlation coefficient is - greater than or equal to 0) - * right-tailed test (null hypothesis - the correlation coefficient is - less than or equal to 0). - -Requirements: - * the number of elements in each sample is not less than 5. - -The test is non-parametric and doesn't require distributions X and Y to be -normal. - -Input parameters: - R - Spearman's rank correlation coefficient for X and Y - N - number of elements in samples, N>=5. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -void spearmanrankcorrelationsignificance(double r, - ae_int_t n, - double* bothtails, - double* lefttail, - double* righttail, - ae_state *_state) -{ - double t; - double p; - - *bothtails = 0; - *lefttail = 0; - *righttail = 0; - - - /* - * Special case - */ - if( n<5 ) - { - *bothtails = 1.0; - *lefttail = 1.0; - *righttail = 1.0; - return; - } - - /* - * General case - */ - if( ae_fp_greater_eq(r,(double)(1)) ) - { - t = 1.0E10; - } - else - { - if( ae_fp_less_eq(r,(double)(-1)) ) - { - t = -1.0E10; - } - else - { - t = r*ae_sqrt((n-2)/(1-ae_sqr(r, _state)), _state); - } - } - if( ae_fp_less(t,(double)(0)) ) - { - p = correlationtests_spearmantail(t, n, _state); - *bothtails = 2*p; - *lefttail = p; - *righttail = 1-p; - } - else - { - p = correlationtests_spearmantail(-t, n, _state); - *bothtails = 2*p; - *lefttail = 1-p; - *righttail = p; - } -} - - -/************************************************************************* -Tail(S, 5) -*************************************************************************/ -static double correlationtests_spearmantail5(double s, ae_state *_state) -{ - double result; - - - if( ae_fp_less(s,0.000e+00) ) - { - result = studenttdistribution(3, -s, _state); - return result; - } - if( ae_fp_greater_eq(s,3.580e+00) ) - { - result = 8.304e-03; - return result; - } - if( ae_fp_greater_eq(s,2.322e+00) ) - { - result = 4.163e-02; - return result; - } - if( ae_fp_greater_eq(s,1.704e+00) ) - { - result = 6.641e-02; - return result; - } - if( ae_fp_greater_eq(s,1.303e+00) ) - { - result = 1.164e-01; - return result; - } - if( ae_fp_greater_eq(s,1.003e+00) ) - { - result = 1.748e-01; - return result; - } - if( ae_fp_greater_eq(s,7.584e-01) ) - { - result = 2.249e-01; - return result; - } - if( ae_fp_greater_eq(s,5.468e-01) ) - { - result = 2.581e-01; - return result; - } - if( ae_fp_greater_eq(s,3.555e-01) ) - { - result = 3.413e-01; - return result; - } - if( ae_fp_greater_eq(s,1.759e-01) ) - { - result = 3.911e-01; - return result; - } - if( ae_fp_greater_eq(s,1.741e-03) ) - { - result = 4.747e-01; - return result; - } - if( ae_fp_greater_eq(s,0.000e+00) ) - { - result = 5.248e-01; - return result; - } - result = (double)(0); - return result; -} - - -/************************************************************************* -Tail(S, 6) -*************************************************************************/ -static double correlationtests_spearmantail6(double s, ae_state *_state) -{ - double result; - - - if( ae_fp_less(s,1.001e+00) ) - { - result = studenttdistribution(4, -s, _state); - return result; - } - if( ae_fp_greater_eq(s,5.663e+00) ) - { - result = 1.366e-03; - return result; - } - if( ae_fp_greater_eq(s,3.834e+00) ) - { - result = 8.350e-03; - return result; - } - if( ae_fp_greater_eq(s,2.968e+00) ) - { - result = 1.668e-02; - return result; - } - if( ae_fp_greater_eq(s,2.430e+00) ) - { - result = 2.921e-02; - return result; - } - if( ae_fp_greater_eq(s,2.045e+00) ) - { - result = 5.144e-02; - return result; - } - if( ae_fp_greater_eq(s,1.747e+00) ) - { - result = 6.797e-02; - return result; - } - if( ae_fp_greater_eq(s,1.502e+00) ) - { - result = 8.752e-02; - return result; - } - if( ae_fp_greater_eq(s,1.295e+00) ) - { - result = 1.210e-01; - return result; - } - if( ae_fp_greater_eq(s,1.113e+00) ) - { - result = 1.487e-01; - return result; - } - if( ae_fp_greater_eq(s,1.001e+00) ) - { - result = 1.780e-01; - return result; - } - result = (double)(0); - return result; -} - - -/************************************************************************* -Tail(S, 7) -*************************************************************************/ -static double correlationtests_spearmantail7(double s, ae_state *_state) -{ - double result; - - - if( ae_fp_less(s,1.001e+00) ) - { - result = studenttdistribution(5, -s, _state); - return result; - } - if( ae_fp_greater_eq(s,8.159e+00) ) - { - result = 2.081e-04; - return result; - } - if( ae_fp_greater_eq(s,5.620e+00) ) - { - result = 1.393e-03; - return result; - } - if( ae_fp_greater_eq(s,4.445e+00) ) - { - result = 3.398e-03; - return result; - } - if( ae_fp_greater_eq(s,3.728e+00) ) - { - result = 6.187e-03; - return result; - } - if( ae_fp_greater_eq(s,3.226e+00) ) - { - result = 1.200e-02; - return result; - } - if( ae_fp_greater_eq(s,2.844e+00) ) - { - result = 1.712e-02; - return result; - } - if( ae_fp_greater_eq(s,2.539e+00) ) - { - result = 2.408e-02; - return result; - } - if( ae_fp_greater_eq(s,2.285e+00) ) - { - result = 3.320e-02; - return result; - } - if( ae_fp_greater_eq(s,2.068e+00) ) - { - result = 4.406e-02; - return result; - } - if( ae_fp_greater_eq(s,1.879e+00) ) - { - result = 5.478e-02; - return result; - } - if( ae_fp_greater_eq(s,1.710e+00) ) - { - result = 6.946e-02; - return result; - } - if( ae_fp_greater_eq(s,1.559e+00) ) - { - result = 8.331e-02; - return result; - } - if( ae_fp_greater_eq(s,1.420e+00) ) - { - result = 1.001e-01; - return result; - } - if( ae_fp_greater_eq(s,1.292e+00) ) - { - result = 1.180e-01; - return result; - } - if( ae_fp_greater_eq(s,1.173e+00) ) - { - result = 1.335e-01; - return result; - } - if( ae_fp_greater_eq(s,1.062e+00) ) - { - result = 1.513e-01; - return result; - } - if( ae_fp_greater_eq(s,1.001e+00) ) - { - result = 1.770e-01; - return result; - } - result = (double)(0); - return result; -} - - -/************************************************************************* -Tail(S, 8) -*************************************************************************/ -static double correlationtests_spearmantail8(double s, ae_state *_state) -{ - double result; - - - if( ae_fp_less(s,2.001e+00) ) - { - result = studenttdistribution(6, -s, _state); - return result; - } - if( ae_fp_greater_eq(s,1.103e+01) ) - { - result = 2.194e-05; - return result; - } - if( ae_fp_greater_eq(s,7.685e+00) ) - { - result = 2.008e-04; - return result; - } - if( ae_fp_greater_eq(s,6.143e+00) ) - { - result = 5.686e-04; - return result; - } - if( ae_fp_greater_eq(s,5.213e+00) ) - { - result = 1.138e-03; - return result; - } - if( ae_fp_greater_eq(s,4.567e+00) ) - { - result = 2.310e-03; - return result; - } - if( ae_fp_greater_eq(s,4.081e+00) ) - { - result = 3.634e-03; - return result; - } - if( ae_fp_greater_eq(s,3.697e+00) ) - { - result = 5.369e-03; - return result; - } - if( ae_fp_greater_eq(s,3.381e+00) ) - { - result = 7.708e-03; - return result; - } - if( ae_fp_greater_eq(s,3.114e+00) ) - { - result = 1.087e-02; - return result; - } - if( ae_fp_greater_eq(s,2.884e+00) ) - { - result = 1.397e-02; - return result; - } - if( ae_fp_greater_eq(s,2.682e+00) ) - { - result = 1.838e-02; - return result; - } - if( ae_fp_greater_eq(s,2.502e+00) ) - { - result = 2.288e-02; - return result; - } - if( ae_fp_greater_eq(s,2.340e+00) ) - { - result = 2.883e-02; - return result; - } - if( ae_fp_greater_eq(s,2.192e+00) ) - { - result = 3.469e-02; - return result; - } - if( ae_fp_greater_eq(s,2.057e+00) ) - { - result = 4.144e-02; - return result; - } - if( ae_fp_greater_eq(s,2.001e+00) ) - { - result = 4.804e-02; - return result; - } - result = (double)(0); - return result; -} - - -/************************************************************************* -Tail(S, 9) -*************************************************************************/ -static double correlationtests_spearmantail9(double s, ae_state *_state) -{ - double result; - - - if( ae_fp_less(s,2.001e+00) ) - { - result = studenttdistribution(7, -s, _state); - return result; - } - if( ae_fp_greater_eq(s,9.989e+00) ) - { - result = 2.306e-05; - return result; - } - if( ae_fp_greater_eq(s,8.069e+00) ) - { - result = 8.167e-05; - return result; - } - if( ae_fp_greater_eq(s,6.890e+00) ) - { - result = 1.744e-04; - return result; - } - if( ae_fp_greater_eq(s,6.077e+00) ) - { - result = 3.625e-04; - return result; - } - if( ae_fp_greater_eq(s,5.469e+00) ) - { - result = 6.450e-04; - return result; - } - if( ae_fp_greater_eq(s,4.991e+00) ) - { - result = 1.001e-03; - return result; - } - if( ae_fp_greater_eq(s,4.600e+00) ) - { - result = 1.514e-03; - return result; - } - if( ae_fp_greater_eq(s,4.272e+00) ) - { - result = 2.213e-03; - return result; - } - if( ae_fp_greater_eq(s,3.991e+00) ) - { - result = 2.990e-03; - return result; - } - if( ae_fp_greater_eq(s,3.746e+00) ) - { - result = 4.101e-03; - return result; - } - if( ae_fp_greater_eq(s,3.530e+00) ) - { - result = 5.355e-03; - return result; - } - if( ae_fp_greater_eq(s,3.336e+00) ) - { - result = 6.887e-03; - return result; - } - if( ae_fp_greater_eq(s,3.161e+00) ) - { - result = 8.598e-03; - return result; - } - if( ae_fp_greater_eq(s,3.002e+00) ) - { - result = 1.065e-02; - return result; - } - if( ae_fp_greater_eq(s,2.855e+00) ) - { - result = 1.268e-02; - return result; - } - if( ae_fp_greater_eq(s,2.720e+00) ) - { - result = 1.552e-02; - return result; - } - if( ae_fp_greater_eq(s,2.595e+00) ) - { - result = 1.836e-02; - return result; - } - if( ae_fp_greater_eq(s,2.477e+00) ) - { - result = 2.158e-02; - return result; - } - if( ae_fp_greater_eq(s,2.368e+00) ) - { - result = 2.512e-02; - return result; - } - if( ae_fp_greater_eq(s,2.264e+00) ) - { - result = 2.942e-02; - return result; - } - if( ae_fp_greater_eq(s,2.166e+00) ) - { - result = 3.325e-02; - return result; - } - if( ae_fp_greater_eq(s,2.073e+00) ) - { - result = 3.800e-02; - return result; - } - if( ae_fp_greater_eq(s,2.001e+00) ) - { - result = 4.285e-02; - return result; - } - result = (double)(0); - return result; -} - - -/************************************************************************* -Tail(T,N), accepts T<0 -*************************************************************************/ -static double correlationtests_spearmantail(double t, - ae_int_t n, - ae_state *_state) -{ - double result; - - - if( n==5 ) - { - result = correlationtests_spearmantail5(-t, _state); - return result; - } - if( n==6 ) - { - result = correlationtests_spearmantail6(-t, _state); - return result; - } - if( n==7 ) - { - result = correlationtests_spearmantail7(-t, _state); - return result; - } - if( n==8 ) - { - result = correlationtests_spearmantail8(-t, _state); - return result; - } - if( n==9 ) - { - result = correlationtests_spearmantail9(-t, _state); - return result; - } - result = studenttdistribution(n-2, t, _state); - return result; -} - - -#endif -#if defined(AE_COMPILE_STUDENTTTESTS) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -One-sample t-test - -This test checks three hypotheses about the mean of the given sample. The -following tests are performed: - * two-tailed test (null hypothesis - the mean is equal to the given - value) - * left-tailed test (null hypothesis - the mean is greater than or - equal to the given value) - * right-tailed test (null hypothesis - the mean is less than or equal - to the given value). - -The test is based on the assumption that a given sample has a normal -distribution and an unknown dispersion. If the distribution sharply -differs from normal, the test will work incorrectly. - -INPUT PARAMETERS: - X - sample. Array whose index goes from 0 to N-1. - N - size of sample, N>=0 - Mean - assumed value of the mean. - -OUTPUT PARAMETERS: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -NOTE: this function correctly handles degenerate cases: - * when N=0, all p-values are set to 1.0 - * when variance of X[] is exactly zero, p-values are set - to 1.0 or 0.0, depending on difference between sample mean and - value of mean being tested. - - - -- ALGLIB -- - Copyright 08.09.2006 by Bochkanov Sergey -*************************************************************************/ -void studentttest1(/* Real */ ae_vector* x, - ae_int_t n, - double mean, - double* bothtails, - double* lefttail, - double* righttail, - ae_state *_state) -{ - ae_int_t i; - double xmean; - double x0; - double v; - ae_bool samex; - double xvariance; - double xstddev; - double v1; - double v2; - double stat; - double s; - - *bothtails = 0; - *lefttail = 0; - *righttail = 0; - - if( n<=0 ) - { - *bothtails = 1.0; - *lefttail = 1.0; - *righttail = 1.0; - return; - } - - /* - * Mean - */ - xmean = (double)(0); - x0 = x->ptr.p_double[0]; - samex = ae_true; - for(i=0; i<=n-1; i++) - { - v = x->ptr.p_double[i]; - xmean = xmean+v; - samex = samex&&ae_fp_eq(v,x0); - } - if( samex ) - { - xmean = x0; - } - else - { - xmean = xmean/n; - } - - /* - * Variance (using corrected two-pass algorithm) - */ - xvariance = (double)(0); - xstddev = (double)(0); - if( n!=1&&!samex ) - { - v1 = (double)(0); - for(i=0; i<=n-1; i++) - { - v1 = v1+ae_sqr(x->ptr.p_double[i]-xmean, _state); - } - v2 = (double)(0); - for(i=0; i<=n-1; i++) - { - v2 = v2+(x->ptr.p_double[i]-xmean); - } - v2 = ae_sqr(v2, _state)/n; - xvariance = (v1-v2)/(n-1); - if( ae_fp_less(xvariance,(double)(0)) ) - { - xvariance = (double)(0); - } - xstddev = ae_sqrt(xvariance, _state); - } - if( ae_fp_eq(xstddev,(double)(0)) ) - { - if( ae_fp_eq(xmean,mean) ) - { - *bothtails = 1.0; - } - else - { - *bothtails = 0.0; - } - if( ae_fp_greater_eq(xmean,mean) ) - { - *lefttail = 1.0; - } - else - { - *lefttail = 0.0; - } - if( ae_fp_less_eq(xmean,mean) ) - { - *righttail = 1.0; - } - else - { - *righttail = 0.0; - } - return; - } - - /* - * Statistic - */ - stat = (xmean-mean)/(xstddev/ae_sqrt((double)(n), _state)); - s = studenttdistribution(n-1, stat, _state); - *bothtails = 2*ae_minreal(s, 1-s, _state); - *lefttail = s; - *righttail = 1-s; -} - - -/************************************************************************* -Two-sample pooled test - -This test checks three hypotheses about the mean of the given samples. The -following tests are performed: - * two-tailed test (null hypothesis - the means are equal) - * left-tailed test (null hypothesis - the mean of the first sample is - greater than or equal to the mean of the second sample) - * right-tailed test (null hypothesis - the mean of the first sample is - less than or equal to the mean of the second sample). - -Test is based on the following assumptions: - * given samples have normal distributions - * dispersions are equal - * samples are independent. - -Input parameters: - X - sample 1. Array whose index goes from 0 to N-1. - N - size of sample. - Y - sample 2. Array whose index goes from 0 to M-1. - M - size of sample. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -NOTE: this function correctly handles degenerate cases: - * when N=0 or M=0, all p-values are set to 1.0 - * when both samples has exactly zero variance, p-values are set - to 1.0 or 0.0, depending on difference between means. - - -- ALGLIB -- - Copyright 18.09.2006 by Bochkanov Sergey -*************************************************************************/ -void studentttest2(/* Real */ ae_vector* x, - ae_int_t n, - /* Real */ ae_vector* y, - ae_int_t m, - double* bothtails, - double* lefttail, - double* righttail, - ae_state *_state) -{ - ae_int_t i; - ae_bool samex; - ae_bool samey; - double x0; - double y0; - double xmean; - double ymean; - double v; - double stat; - double s; - double p; - - *bothtails = 0; - *lefttail = 0; - *righttail = 0; - - if( n<=0||m<=0 ) - { - *bothtails = 1.0; - *lefttail = 1.0; - *righttail = 1.0; - return; - } - - /* - * Mean - */ - xmean = (double)(0); - x0 = x->ptr.p_double[0]; - samex = ae_true; - for(i=0; i<=n-1; i++) - { - v = x->ptr.p_double[i]; - xmean = xmean+v; - samex = samex&&ae_fp_eq(v,x0); - } - if( samex ) - { - xmean = x0; - } - else - { - xmean = xmean/n; - } - ymean = (double)(0); - y0 = y->ptr.p_double[0]; - samey = ae_true; - for(i=0; i<=m-1; i++) - { - v = y->ptr.p_double[i]; - ymean = ymean+v; - samey = samey&&ae_fp_eq(v,y0); - } - if( samey ) - { - ymean = y0; - } - else - { - ymean = ymean/m; - } - - /* - * S - */ - s = (double)(0); - if( n+m>2 ) - { - for(i=0; i<=n-1; i++) - { - s = s+ae_sqr(x->ptr.p_double[i]-xmean, _state); - } - for(i=0; i<=m-1; i++) - { - s = s+ae_sqr(y->ptr.p_double[i]-ymean, _state); - } - s = ae_sqrt(s*((double)1/(double)n+(double)1/(double)m)/(n+m-2), _state); - } - if( ae_fp_eq(s,(double)(0)) ) - { - if( ae_fp_eq(xmean,ymean) ) - { - *bothtails = 1.0; - } - else - { - *bothtails = 0.0; - } - if( ae_fp_greater_eq(xmean,ymean) ) - { - *lefttail = 1.0; - } - else - { - *lefttail = 0.0; - } - if( ae_fp_less_eq(xmean,ymean) ) - { - *righttail = 1.0; - } - else - { - *righttail = 0.0; - } - return; - } - - /* - * Statistic - */ - stat = (xmean-ymean)/s; - p = studenttdistribution(n+m-2, stat, _state); - *bothtails = 2*ae_minreal(p, 1-p, _state); - *lefttail = p; - *righttail = 1-p; -} - - -/************************************************************************* -Two-sample unpooled test - -This test checks three hypotheses about the mean of the given samples. The -following tests are performed: - * two-tailed test (null hypothesis - the means are equal) - * left-tailed test (null hypothesis - the mean of the first sample is - greater than or equal to the mean of the second sample) - * right-tailed test (null hypothesis - the mean of the first sample is - less than or equal to the mean of the second sample). - -Test is based on the following assumptions: - * given samples have normal distributions - * samples are independent. -Equality of variances is NOT required. - -Input parameters: - X - sample 1. Array whose index goes from 0 to N-1. - N - size of the sample. - Y - sample 2. Array whose index goes from 0 to M-1. - M - size of the sample. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -NOTE: this function correctly handles degenerate cases: - * when N=0 or M=0, all p-values are set to 1.0 - * when both samples has zero variance, p-values are set - to 1.0 or 0.0, depending on difference between means. - * when only one sample has zero variance, test reduces to 1-sample - version. - - -- ALGLIB -- - Copyright 18.09.2006 by Bochkanov Sergey -*************************************************************************/ -void unequalvariancettest(/* Real */ ae_vector* x, - ae_int_t n, - /* Real */ ae_vector* y, - ae_int_t m, - double* bothtails, - double* lefttail, - double* righttail, - ae_state *_state) -{ - ae_int_t i; - ae_bool samex; - ae_bool samey; - double x0; - double y0; - double xmean; - double ymean; - double xvar; - double yvar; - double v; - double df; - double p; - double stat; - double c; - - *bothtails = 0; - *lefttail = 0; - *righttail = 0; - - if( n<=0||m<=0 ) - { - *bothtails = 1.0; - *lefttail = 1.0; - *righttail = 1.0; - return; - } - - /* - * Mean - */ - xmean = (double)(0); - x0 = x->ptr.p_double[0]; - samex = ae_true; - for(i=0; i<=n-1; i++) - { - v = x->ptr.p_double[i]; - xmean = xmean+v; - samex = samex&&ae_fp_eq(v,x0); - } - if( samex ) - { - xmean = x0; - } - else - { - xmean = xmean/n; - } - ymean = (double)(0); - y0 = y->ptr.p_double[0]; - samey = ae_true; - for(i=0; i<=m-1; i++) - { - v = y->ptr.p_double[i]; - ymean = ymean+v; - samey = samey&&ae_fp_eq(v,y0); - } - if( samey ) - { - ymean = y0; - } - else - { - ymean = ymean/m; - } - - /* - * Variance (using corrected two-pass algorithm) - */ - xvar = (double)(0); - if( n>=2&&!samex ) - { - for(i=0; i<=n-1; i++) - { - xvar = xvar+ae_sqr(x->ptr.p_double[i]-xmean, _state); - } - xvar = xvar/(n-1); - } - yvar = (double)(0); - if( m>=2&&!samey ) - { - for(i=0; i<=m-1; i++) - { - yvar = yvar+ae_sqr(y->ptr.p_double[i]-ymean, _state); - } - yvar = yvar/(m-1); - } - - /* - * Handle different special cases - * (one or both variances are zero). - */ - if( ae_fp_eq(xvar,(double)(0))&&ae_fp_eq(yvar,(double)(0)) ) - { - if( ae_fp_eq(xmean,ymean) ) - { - *bothtails = 1.0; - } - else - { - *bothtails = 0.0; - } - if( ae_fp_greater_eq(xmean,ymean) ) - { - *lefttail = 1.0; - } - else - { - *lefttail = 0.0; - } - if( ae_fp_less_eq(xmean,ymean) ) - { - *righttail = 1.0; - } - else - { - *righttail = 0.0; - } - return; - } - if( ae_fp_eq(xvar,(double)(0)) ) - { - - /* - * X is constant, unpooled 2-sample test reduces to 1-sample test. - * - * NOTE: right-tail and left-tail must be passed to 1-sample - * t-test in reverse order because we reverse order of - * of samples. - */ - studentttest1(y, m, xmean, bothtails, righttail, lefttail, _state); - return; - } - if( ae_fp_eq(yvar,(double)(0)) ) - { - - /* - * Y is constant, unpooled 2-sample test reduces to 1-sample test. - */ - studentttest1(x, n, ymean, bothtails, lefttail, righttail, _state); - return; - } - - /* - * Statistic - */ - stat = (xmean-ymean)/ae_sqrt(xvar/n+yvar/m, _state); - c = xvar/n/(xvar/n+yvar/m); - df = rmul2((double)(n-1), (double)(m-1), _state)/((m-1)*ae_sqr(c, _state)+(n-1)*ae_sqr(1-c, _state)); - if( ae_fp_greater(stat,(double)(0)) ) - { - p = 1-0.5*incompletebeta(df/2, 0.5, df/(df+ae_sqr(stat, _state)), _state); - } - else - { - p = 0.5*incompletebeta(df/2, 0.5, df/(df+ae_sqr(stat, _state)), _state); - } - *bothtails = 2*ae_minreal(p, 1-p, _state); - *lefttail = p; - *righttail = 1-p; -} - - -#endif -#if defined(AE_COMPILE_MANNWHITNEYU) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Mann-Whitney U-test - -This test checks hypotheses about whether X and Y are samples of two -continuous distributions of the same shape and same median or whether -their medians are different. - -The following tests are performed: - * two-tailed test (null hypothesis - the medians are equal) - * left-tailed test (null hypothesis - the median of the first sample - is greater than or equal to the median of the second sample) - * right-tailed test (null hypothesis - the median of the first sample - is less than or equal to the median of the second sample). - -Requirements: - * the samples are independent - * X and Y are continuous distributions (or discrete distributions well- - approximating continuous distributions) - * distributions of X and Y have the same shape. The only possible - difference is their position (i.e. the value of the median) - * the number of elements in each sample is not less than 5 - * the scale of measurement should be ordinal, interval or ratio (i.e. - the test could not be applied to nominal variables). - -The test is non-parametric and doesn't require distributions to be normal. - -Input parameters: - X - sample 1. Array whose index goes from 0 to N-1. - N - size of the sample. N>=5 - Y - sample 2. Array whose index goes from 0 to M-1. - M - size of the sample. M>=5 - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -To calculate p-values, special approximation is used. This method lets us -calculate p-values with satisfactory accuracy in interval [0.0001, 1]. -There is no approximation outside the [0.0001, 1] interval. Therefore, if -the significance level outlies this interval, the test returns 0.0001. - -Relative precision of approximation of p-value: - -N M Max.err. Rms.err. -5..10 N..10 1.4e-02 6.0e-04 -5..10 N..100 2.2e-02 5.3e-06 -10..15 N..15 1.0e-02 3.2e-04 -10..15 N..100 1.0e-02 2.2e-05 -15..100 N..100 6.1e-03 2.7e-06 - -For N,M>100 accuracy checks weren't put into practice, but taking into -account characteristics of asymptotic approximation used, precision should -not be sharply different from the values for interval [5, 100]. - -NOTE: P-value approximation was optimized for 0.0001<=p<=0.2500. Thus, - P's outside of this interval are enforced to these bounds. Say, you - may quite often get P equal to exactly 0.25 or 0.0001. - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -void mannwhitneyutest(/* Real */ ae_vector* x, - ae_int_t n, - /* Real */ ae_vector* y, - ae_int_t m, - double* bothtails, - double* lefttail, - double* righttail, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t t; - double tmp; - ae_int_t tmpi; - ae_int_t ns; - ae_vector r; - ae_vector c; - double u; - double p; - double mp; - double s; - double sigma; - double mu; - ae_int_t tiecount; - ae_vector tiesize; - - ae_frame_make(_state, &_frame_block); - memset(&r, 0, sizeof(r)); - memset(&c, 0, sizeof(c)); - memset(&tiesize, 0, sizeof(tiesize)); - *bothtails = 0; - *lefttail = 0; - *righttail = 0; - ae_vector_init(&r, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c, 0, DT_INT, _state, ae_true); - ae_vector_init(&tiesize, 0, DT_INT, _state, ae_true); - - - /* - * Prepare - */ - if( n<=4||m<=4 ) - { - *bothtails = 1.0; - *lefttail = 1.0; - *righttail = 1.0; - ae_frame_leave(_state); - return; - } - ns = n+m; - ae_vector_set_length(&r, ns-1+1, _state); - ae_vector_set_length(&c, ns-1+1, _state); - for(i=0; i<=n-1; i++) - { - r.ptr.p_double[i] = x->ptr.p_double[i]; - c.ptr.p_int[i] = 0; - } - for(i=0; i<=m-1; i++) - { - r.ptr.p_double[n+i] = y->ptr.p_double[i]; - c.ptr.p_int[n+i] = 1; - } - - /* - * sort {R, C} - */ - if( ns!=1 ) - { - i = 2; - do - { - t = i; - while(t!=1) - { - k = t/2; - if( ae_fp_greater_eq(r.ptr.p_double[k-1],r.ptr.p_double[t-1]) ) - { - t = 1; - } - else - { - tmp = r.ptr.p_double[k-1]; - r.ptr.p_double[k-1] = r.ptr.p_double[t-1]; - r.ptr.p_double[t-1] = tmp; - tmpi = c.ptr.p_int[k-1]; - c.ptr.p_int[k-1] = c.ptr.p_int[t-1]; - c.ptr.p_int[t-1] = tmpi; - t = k; - } - } - i = i+1; - } - while(i<=ns); - i = ns-1; - do - { - tmp = r.ptr.p_double[i]; - r.ptr.p_double[i] = r.ptr.p_double[0]; - r.ptr.p_double[0] = tmp; - tmpi = c.ptr.p_int[i]; - c.ptr.p_int[i] = c.ptr.p_int[0]; - c.ptr.p_int[0] = tmpi; - t = 1; - while(t!=0) - { - k = 2*t; - if( k>i ) - { - t = 0; - } - else - { - if( k=1); - } - - /* - * compute tied ranks - */ - i = 0; - tiecount = 0; - ae_vector_set_length(&tiesize, ns-1+1, _state); - while(i<=ns-1) - { - j = i+1; - while(j<=ns-1) - { - if( ae_fp_neq(r.ptr.p_double[j],r.ptr.p_double[i]) ) - { - break; - } - j = j+1; - } - for(k=i; k<=j-1; k++) - { - r.ptr.p_double[k] = 1+(double)(i+j-1)/(double)2; - } - tiesize.ptr.p_int[tiecount] = j-i; - tiecount = tiecount+1; - i = j; - } - - /* - * Compute U - */ - u = (double)(0); - for(i=0; i<=ns-1; i++) - { - if( c.ptr.p_int[i]==0 ) - { - u = u+r.ptr.p_double[i]; - } - } - u = rmul2((double)(n), (double)(m), _state)+rmul2((double)(n), (double)(n+1), _state)*0.5-u; - - /* - * Result - */ - mu = rmul2((double)(n), (double)(m), _state)/2; - tmp = ns*(ae_sqr((double)(ns), _state)-1)/12; - for(i=0; i<=tiecount-1; i++) - { - tmp = tmp-tiesize.ptr.p_int[i]*(ae_sqr((double)(tiesize.ptr.p_int[i]), _state)-1)/12; - } - sigma = ae_sqrt(rmul2((double)(n), (double)(m), _state)/ns/(ns-1)*tmp, _state); - s = (u-mu)/sigma; - if( ae_fp_less_eq(s,(double)(0)) ) - { - p = ae_exp(mannwhitneyu_usigma(-(u-mu)/sigma, n, m, _state), _state); - mp = 1-ae_exp(mannwhitneyu_usigma(-(u-1-mu)/sigma, n, m, _state), _state); - } - else - { - mp = ae_exp(mannwhitneyu_usigma((u-mu)/sigma, n, m, _state), _state); - p = 1-ae_exp(mannwhitneyu_usigma((u+1-mu)/sigma, n, m, _state), _state); - } - *lefttail = boundval(ae_maxreal(mp, 1.0E-4, _state), 0.0001, 0.2500, _state); - *righttail = boundval(ae_maxreal(p, 1.0E-4, _state), 0.0001, 0.2500, _state); - *bothtails = 2*ae_minreal(*lefttail, *righttail, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Sequential Chebyshev interpolation. -*************************************************************************/ -static void mannwhitneyu_ucheb(double x, - double c, - double* tj, - double* tj1, - double* r, - ae_state *_state) -{ - double t; - - - *r = *r+c*(*tj); - t = 2*x*(*tj1)-(*tj); - *tj = *tj1; - *tj1 = t; -} - - -/************************************************************************* -Three-point polynomial interpolation. -*************************************************************************/ -static double mannwhitneyu_uninterpolate(double p1, - double p2, - double p3, - ae_int_t n, - ae_state *_state) -{ - double t1; - double t2; - double t3; - double t; - double p12; - double p23; - double result; - - - t1 = 1.0/15.0; - t2 = 1.0/30.0; - t3 = 1.0/100.0; - t = 1.0/n; - p12 = ((t-t2)*p1+(t1-t)*p2)/(t1-t2); - p23 = ((t-t3)*p2+(t2-t)*p3)/(t2-t3); - result = ((t-t3)*p12+(t1-t)*p23)/(t1-t3); - return result; -} - - -/************************************************************************* -Tail(0, N1, N2) -*************************************************************************/ -static double mannwhitneyu_usigma000(ae_int_t n1, - ae_int_t n2, - ae_state *_state) -{ - double p1; - double p2; - double p3; - double result; - - - p1 = mannwhitneyu_uninterpolate(-6.76984e-01, -6.83700e-01, -6.89873e-01, n2, _state); - p2 = mannwhitneyu_uninterpolate(-6.83700e-01, -6.87311e-01, -6.90957e-01, n2, _state); - p3 = mannwhitneyu_uninterpolate(-6.89873e-01, -6.90957e-01, -6.92175e-01, n2, _state); - result = mannwhitneyu_uninterpolate(p1, p2, p3, n1, _state); - return result; -} - - -/************************************************************************* -Tail(0.75, N1, N2) -*************************************************************************/ -static double mannwhitneyu_usigma075(ae_int_t n1, - ae_int_t n2, - ae_state *_state) -{ - double p1; - double p2; - double p3; - double result; - - - p1 = mannwhitneyu_uninterpolate(-1.44500e+00, -1.45906e+00, -1.47063e+00, n2, _state); - p2 = mannwhitneyu_uninterpolate(-1.45906e+00, -1.46856e+00, -1.47644e+00, n2, _state); - p3 = mannwhitneyu_uninterpolate(-1.47063e+00, -1.47644e+00, -1.48100e+00, n2, _state); - result = mannwhitneyu_uninterpolate(p1, p2, p3, n1, _state); - return result; -} - - -/************************************************************************* -Tail(1.5, N1, N2) -*************************************************************************/ -static double mannwhitneyu_usigma150(ae_int_t n1, - ae_int_t n2, - ae_state *_state) -{ - double p1; - double p2; - double p3; - double result; - - - p1 = mannwhitneyu_uninterpolate(-2.65380e+00, -2.67352e+00, -2.69011e+00, n2, _state); - p2 = mannwhitneyu_uninterpolate(-2.67352e+00, -2.68591e+00, -2.69659e+00, n2, _state); - p3 = mannwhitneyu_uninterpolate(-2.69011e+00, -2.69659e+00, -2.70192e+00, n2, _state); - result = mannwhitneyu_uninterpolate(p1, p2, p3, n1, _state); - return result; -} - - -/************************************************************************* -Tail(2.25, N1, N2) -*************************************************************************/ -static double mannwhitneyu_usigma225(ae_int_t n1, - ae_int_t n2, - ae_state *_state) -{ - double p1; - double p2; - double p3; - double result; - - - p1 = mannwhitneyu_uninterpolate(-4.41465e+00, -4.42260e+00, -4.43702e+00, n2, _state); - p2 = mannwhitneyu_uninterpolate(-4.42260e+00, -4.41639e+00, -4.41928e+00, n2, _state); - p3 = mannwhitneyu_uninterpolate(-4.43702e+00, -4.41928e+00, -4.41030e+00, n2, _state); - result = mannwhitneyu_uninterpolate(p1, p2, p3, n1, _state); - return result; -} - - -/************************************************************************* -Tail(3.0, N1, N2) -*************************************************************************/ -static double mannwhitneyu_usigma300(ae_int_t n1, - ae_int_t n2, - ae_state *_state) -{ - double p1; - double p2; - double p3; - double result; - - - p1 = mannwhitneyu_uninterpolate(-6.89839e+00, -6.83477e+00, -6.82340e+00, n2, _state); - p2 = mannwhitneyu_uninterpolate(-6.83477e+00, -6.74559e+00, -6.71117e+00, n2, _state); - p3 = mannwhitneyu_uninterpolate(-6.82340e+00, -6.71117e+00, -6.64929e+00, n2, _state); - result = mannwhitneyu_uninterpolate(p1, p2, p3, n1, _state); - return result; -} - - -/************************************************************************* -Tail(3.33, N1, N2) -*************************************************************************/ -static double mannwhitneyu_usigma333(ae_int_t n1, - ae_int_t n2, - ae_state *_state) -{ - double p1; - double p2; - double p3; - double result; - - - p1 = mannwhitneyu_uninterpolate(-8.31272e+00, -8.17096e+00, -8.13125e+00, n2, _state); - p2 = mannwhitneyu_uninterpolate(-8.17096e+00, -8.00156e+00, -7.93245e+00, n2, _state); - p3 = mannwhitneyu_uninterpolate(-8.13125e+00, -7.93245e+00, -7.82502e+00, n2, _state); - result = mannwhitneyu_uninterpolate(p1, p2, p3, n1, _state); - return result; -} - - -/************************************************************************* -Tail(3.66, N1, N2) -*************************************************************************/ -static double mannwhitneyu_usigma367(ae_int_t n1, - ae_int_t n2, - ae_state *_state) -{ - double p1; - double p2; - double p3; - double result; - - - p1 = mannwhitneyu_uninterpolate(-9.98837e+00, -9.70844e+00, -9.62087e+00, n2, _state); - p2 = mannwhitneyu_uninterpolate(-9.70844e+00, -9.41156e+00, -9.28998e+00, n2, _state); - p3 = mannwhitneyu_uninterpolate(-9.62087e+00, -9.28998e+00, -9.11686e+00, n2, _state); - result = mannwhitneyu_uninterpolate(p1, p2, p3, n1, _state); - return result; -} - - -/************************************************************************* -Tail(4.0, N1, N2) -*************************************************************************/ -static double mannwhitneyu_usigma400(ae_int_t n1, - ae_int_t n2, - ae_state *_state) -{ - double p1; - double p2; - double p3; - double result; - - - p1 = mannwhitneyu_uninterpolate(-1.20250e+01, -1.14911e+01, -1.13231e+01, n2, _state); - p2 = mannwhitneyu_uninterpolate(-1.14911e+01, -1.09927e+01, -1.07937e+01, n2, _state); - p3 = mannwhitneyu_uninterpolate(-1.13231e+01, -1.07937e+01, -1.05285e+01, n2, _state); - result = mannwhitneyu_uninterpolate(p1, p2, p3, n1, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 5) -*************************************************************************/ -static double mannwhitneyu_utbln5n5(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/2.611165e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -2.596264e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.412086e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.858542e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.614282e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.372686e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 8.524731e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.435331e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.284665e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.184141e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.298360e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 7.447272e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.938769e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.276205e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.138481e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 8.684625e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.558104e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 6) -*************************************************************************/ -static double mannwhitneyu_utbln5n6(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/2.738613e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -2.810459e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.684429e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.712858e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.009324e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.644391e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 6.034173e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.953498e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.279293e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.563485e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.971952e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.506309e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.541406e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.283205e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.016347e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.221626e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.286752e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 7) -*************************************************************************/ -static double mannwhitneyu_utbln5n7(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/2.841993e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -2.994677e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.923264e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.506190e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.054280e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.794587e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.726290e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.534180e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.517845e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.904428e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.882443e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.482988e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.114875e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.515082e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.996056e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.293581e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.349444e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 8) -*************************************************************************/ -static double mannwhitneyu_utbln5n8(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/2.927700e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.155727e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.135078e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.247203e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.309697e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.993725e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.567219e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.383704e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.002188e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.487322e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.443899e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.688270e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.600339e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.874948e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.811593e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.072353e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.659457e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 9) -*************************************************************************/ -static double mannwhitneyu_utbln5n9(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.000000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.298162e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.325016e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.939852e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.563029e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.222652e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.195200e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.445665e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.204792e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.775217e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.527781e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.221948e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.242968e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.607959e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.771285e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 6.694026e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.481190e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 10) -*************************************************************************/ -static double mannwhitneyu_utbln5n10(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.061862e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.425360e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.496710e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.587658e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.812005e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.427637e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.515702e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.406867e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.796295e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.237591e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.654249e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.181165e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.011665e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.417927e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.534880e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.791255e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.871512e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 11) -*************************************************************************/ -static double mannwhitneyu_utbln5n11(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.115427e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.539959e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.652998e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.196503e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.054363e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.618848e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.109411e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.786668e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.215648e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.484220e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.935991e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.396191e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.894177e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.206979e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.519055e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.210326e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.189679e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 12) -*************************************************************************/ -static double mannwhitneyu_utbln5n12(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.162278e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.644007e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.796173e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.771177e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.290043e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.794686e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.702110e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.185959e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.416259e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.592056e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.201530e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.754365e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.978945e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.012032e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.304579e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.100378e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.728269e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 13) -*************************************************************************/ -static double mannwhitneyu_utbln5n13(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.203616e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.739120e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.928117e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.031605e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.519403e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.962648e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.292183e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.809293e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.465156e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.456278e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.446055e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.109490e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.218256e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.941479e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.058603e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.824402e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.830947e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 14) -*************************************************************************/ -static double mannwhitneyu_utbln5n14(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.240370e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.826559e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.050370e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.083408e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.743164e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.012030e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.884686e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.059656e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.327521e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.134026e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.584201e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.440618e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.524133e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.990007e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.887334e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.534977e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.705395e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 15) -*************************************************************************/ -static double mannwhitneyu_utbln5n15(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.250000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.851572e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.082033e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.095983e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.814595e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.073148e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.420213e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.517175e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.344180e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.371393e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.711443e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.228569e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.683483e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.267112e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.156044e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 9.131316e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.301023e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 16) -*************************************************************************/ -static double mannwhitneyu_utbln5n16(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.250000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.852210e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.077482e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.091186e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.797282e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.084994e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.667054e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.843909e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.456732e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.039830e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.723508e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.940608e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.478285e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.649144e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.237703e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.707410e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.874293e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 17) -*************************************************************************/ -static double mannwhitneyu_utbln5n17(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.250000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.851752e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.071259e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.084700e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.758898e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.073846e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.684838e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.964936e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.782442e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.956362e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.984727e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.196936e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.558262e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.690746e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.364855e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.401006e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.546748e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 18) -*************************************************************************/ -static double mannwhitneyu_utbln5n18(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.250000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.850840e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.064799e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.077651e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.712659e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.049217e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.571333e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.929809e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.752044e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.949464e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.896101e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.614460e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.384357e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.489113e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.445725e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.945636e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.424653e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 19) -*************************************************************************/ -static double mannwhitneyu_utbln5n19(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.250000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.850027e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.059159e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.071106e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.669960e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.022780e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.442555e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.851335e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.433865e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.514465e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.332989e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 8.606099e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.341945e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.402164e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.039761e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.512831e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.284427e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 20) -*************************************************************************/ -static double mannwhitneyu_utbln5n20(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.250000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.849651e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.054729e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.065747e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.636243e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.003234e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.372789e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.831551e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.763090e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.830626e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.122384e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 8.108328e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.557983e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.945666e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.965696e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.493236e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.162591e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 21) -*************************************************************************/ -static double mannwhitneyu_utbln5n21(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.250000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.849649e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.051155e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.061430e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.608869e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.902788e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.346562e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.874709e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.682887e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.026206e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.534551e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.990575e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.713334e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 9.737011e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.304571e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.133110e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.123457e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 22) -*************************************************************************/ -static double mannwhitneyu_utbln5n22(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.250000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.849598e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.047605e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.057264e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.579513e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.749602e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.275137e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.881768e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.177374e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.981056e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.696290e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.886803e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.085378e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.675242e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.426367e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.039613e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.662378e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 23) -*************************************************************************/ -static double mannwhitneyu_utbln5n23(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.250000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.849269e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.043761e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.052735e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.544683e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.517503e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.112082e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.782070e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.549483e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.747329e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.694263e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.147141e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.526209e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.039173e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.235615e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.656546e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.014423e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 24) -*************************************************************************/ -static double mannwhitneyu_utbln5n24(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.250000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.848925e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.040178e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.048355e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.510198e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.261134e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.915864e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.627423e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.307345e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.732992e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.869652e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.494176e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.047533e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.178439e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.424171e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.829195e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.840810e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 25) -*************************************************************************/ -static double mannwhitneyu_utbln5n25(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.250000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.848937e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.037512e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.044866e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.483269e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.063682e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.767778e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.508540e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.332756e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.881511e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.124041e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.368456e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.930499e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.779630e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.029528e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.658678e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.289695e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 26) -*************************************************************************/ -static double mannwhitneyu_utbln5n26(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.250000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.849416e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.035915e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.042493e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.466021e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.956432e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.698914e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.465689e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.035254e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.674614e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.492734e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.014021e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.944953e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.255750e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.075841e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.989330e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.134862e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 27) -*************************************************************************/ -static double mannwhitneyu_utbln5n27(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.250000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.850070e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.034815e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.040650e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.453117e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.886426e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.661702e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.452346e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.002476e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.720126e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.001400e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.729826e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.740640e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.206333e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.366093e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.193471e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.804091e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 28) -*************************************************************************/ -static double mannwhitneyu_utbln5n28(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.250000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.850668e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.033786e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.038853e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.440281e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.806020e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.612883e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.420436e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.787982e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.535230e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.263121e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.849609e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.863967e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.391610e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.720294e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.952273e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.901413e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 29) -*************************************************************************/ -static double mannwhitneyu_utbln5n29(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.250000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.851217e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.032834e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.037113e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.427762e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.719146e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.557172e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.375498e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.452033e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.187516e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.916936e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.065533e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.067301e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.615824e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.432244e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.417795e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.710038e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 30) -*************************************************************************/ -static double mannwhitneyu_utbln5n30(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.250000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.851845e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.032148e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.035679e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.417758e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.655330e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.522132e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.352106e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.326911e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.064969e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.813321e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.683881e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.813346e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.627085e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.832107e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.519336e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.888530e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 5, 100) -*************************************************************************/ -static double mannwhitneyu_utbln5n100(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.250000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.877940e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.039324e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.022243e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.305825e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.960119e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.112000e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.138868e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.418164e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.174520e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.489617e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.878301e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.302233e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.054113e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.458862e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.186591e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.623412e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 6, 6) -*************************************************************************/ -static double mannwhitneyu_utbln6n6(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/2.882307e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.054075e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.998804e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.681518e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.067578e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.709435e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 9.952661e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.641700e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.304572e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.336275e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.770385e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.401891e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.246148e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.442663e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.502866e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.105855e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.739371e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 6, 7) -*************************************************************************/ -static double mannwhitneyu_utbln6n7(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.000000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.265287e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.274613e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.582352e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.334293e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.915502e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.108091e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.546701e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.298827e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.891501e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.313717e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.989501e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.914594e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.062372e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.158841e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.596443e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.185662e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 6, 8) -*************************************************************************/ -static double mannwhitneyu_utbln6n8(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.098387e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.450954e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.520462e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.420299e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.604853e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.165840e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.008756e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.723402e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.843521e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.883405e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.720980e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.301709e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.948034e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.776243e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 8.623736e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.742068e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.796927e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 6, 9) -*************************************************************************/ -static double mannwhitneyu_utbln6n9(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.181981e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.616113e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.741650e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.204487e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.873068e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.446794e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.632286e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.266481e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.280067e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.780687e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.480242e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.592200e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.581019e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.264231e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.347174e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.167535e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.092185e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 6, 10) -*************************************************************************/ -static double mannwhitneyu_utbln6n10(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.253957e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.764382e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.942366e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.939896e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.137812e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.720270e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.281070e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.901060e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.824937e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.802812e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.258132e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.233536e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.085530e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.212151e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.001329e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.226048e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.035298e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 6, 11) -*************************************************************************/ -static double mannwhitneyu_utbln6n11(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.316625e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.898597e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.125710e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.063297e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.396852e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.990126e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.927977e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.726500e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.858745e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.654590e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.217736e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.989770e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.768493e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.924364e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.140215e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.647914e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.924802e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 6, 12) -*************************************************************************/ -static double mannwhitneyu_utbln6n12(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.371709e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.020941e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.294250e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.128842e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.650389e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.248611e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.578510e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.162852e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.746982e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.454209e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.128042e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.936650e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.530794e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.665192e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.994144e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.662249e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.368541e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 6, 13) -*************************************************************************/ -static double mannwhitneyu_utbln6n13(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.420526e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.133167e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.450016e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.191088e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.898220e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.050249e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.226901e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.471113e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.007470e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.049420e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.059074e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.881249e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.452780e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.441805e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.787493e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.483957e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.481590e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 6, 14) -*************************************************************************/ -static double mannwhitneyu_utbln6n14(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.450000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.201268e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.542568e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.226965e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.046029e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.136657e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.786757e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.843748e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.588022e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.253029e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.667188e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.788330e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.474545e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.540494e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.951188e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.863323e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.220904e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 6, 15) -*************************************************************************/ -static double mannwhitneyu_utbln6n15(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.450000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.195689e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.526567e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.213617e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.975035e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.118480e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.859142e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.083312e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.298720e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.766708e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.026356e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.093113e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.135168e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.136376e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.190870e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.435972e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.413129e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 6, 30) -*************************************************************************/ -static double mannwhitneyu_utbln6n30(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.450000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.166269e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.427399e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.118239e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.360847e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.745885e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.025041e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.187179e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.432089e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.408451e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.388774e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.795560e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.304136e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.258516e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.180236e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.388679e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.836027e-06, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 6, 100) -*************************************************************************/ -static double mannwhitneyu_utbln6n100(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.450000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.181350e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.417919e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.094201e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.195883e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.818937e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.514202e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.125047e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.022148e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.284181e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.157766e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.023752e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.127985e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.221690e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.516179e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 9.501398e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 9.380220e-06, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 7, 7) -*************************************************************************/ -static double mannwhitneyu_utbln7n7(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.130495e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.501264e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.584790e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.577311e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.617002e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.145186e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.023462e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.408251e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 8.626515e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.072492e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.722926e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.095445e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.842602e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.751427e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.008927e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.892431e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.772386e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 7, 8) -*************************************************************************/ -static double mannwhitneyu_utbln7n8(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.240370e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.709965e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.862154e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.504541e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.900195e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.439995e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.678028e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.485540e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.437047e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.440092e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.114227e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.516569e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.829457e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.787550e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.761866e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.991911e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.533481e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 7, 9) -*************************************************************************/ -static double mannwhitneyu_utbln7n9(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.334314e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.896550e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.112671e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.037277e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.181695e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.765190e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.360116e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.695960e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.780578e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 8.963843e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.616148e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.852104e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.390744e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.014041e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.888101e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.467474e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.004611e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 7, 10) -*************************************************************************/ -static double mannwhitneyu_utbln7n10(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.415650e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.064844e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.340749e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.118888e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.459730e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.097781e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.057688e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.097406e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.209262e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.065641e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.196677e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.313994e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.827157e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.822284e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.389090e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.340850e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.395172e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 7, 11) -*************************************************************************/ -static double mannwhitneyu_utbln7n11(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.486817e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.217795e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.549783e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.195905e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.733093e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.428447e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.760093e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.431676e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.717152e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.032199e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.832423e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.905979e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.302799e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.464371e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.456211e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.736244e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.140712e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 7, 12) -*************************************************************************/ -static double mannwhitneyu_utbln7n12(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.500000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.235822e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.564100e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.190813e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.686546e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.395083e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.967359e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.747096e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.304144e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.903198e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.134906e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.175035e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.266224e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.892931e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.604706e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 9.070459e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.427010e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 7, 13) -*************************************************************************/ -static double mannwhitneyu_utbln7n13(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.500000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.222204e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.532300e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.164642e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.523768e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.531984e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.467857e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.483804e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.524136e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.077740e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.745218e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.602085e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.828831e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.994070e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.873879e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.341937e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.706444e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 7, 14) -*************************************************************************/ -static double mannwhitneyu_utbln7n14(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.500000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.211763e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.507542e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.143640e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.395755e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.808020e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.044259e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.182308e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.057325e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.724255e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 8.303900e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.113148e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 8.102514e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.559442e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.634986e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.776476e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.054489e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 7, 15) -*************************************************************************/ -static double mannwhitneyu_utbln7n15(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.500000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.204898e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.489960e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.129172e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.316741e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.506107e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.983676e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.258013e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.262515e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.984156e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.912108e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 8.974023e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 6.056195e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.090842e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.232620e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.816339e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.020421e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 7, 30) -*************************************************************************/ -static double mannwhitneyu_utbln7n30(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.500000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.176536e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.398705e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.045481e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.821982e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.962304e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.698132e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.062667e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.282353e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.014836e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.035683e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.004137e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.801453e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.920705e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.518735e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.821501e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.801008e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 7, 100) -*************************************************************************/ -static double mannwhitneyu_utbln7n100(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.500000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.188337e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.386949e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.022834e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.686517e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.323516e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.399392e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.644333e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.617044e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.031396e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.792066e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.675457e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.673416e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.258552e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.174214e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.073644e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.349958e-06, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 8, 8) -*************************************************************************/ -static double mannwhitneyu_utbln8n8(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.360672e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -3.940217e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.168913e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.051485e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.195325e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.775196e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.385506e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.244902e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.525632e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.771275e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.332874e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.079599e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.882551e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.407944e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.769844e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.062433e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.872535e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 8, 9) -*************************************************************************/ -static double mannwhitneyu_utbln8n9(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.464102e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.147004e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.446939e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.146155e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.488561e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.144561e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.116917e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.205667e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.515661e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.618616e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.599011e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.457324e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.482917e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.488267e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.469823e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.957591e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 8.058326e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 8, 10) -*************************************************************************/ -static double mannwhitneyu_utbln8n10(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.554093e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.334282e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.700860e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.235253e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.778489e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.527324e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.862885e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.589781e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.507355e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.717526e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 9.215726e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.848696e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.918854e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.219614e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.753761e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.573688e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.602177e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 8, 11) -*************************************************************************/ -static double mannwhitneyu_utbln8n11(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.600000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.421882e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.812457e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.266153e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.849344e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.971527e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.258944e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.944820e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.894685e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.031836e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.514330e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.351660e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 6.206748e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.492600e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.005338e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.780099e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.673599e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 8, 12) -*************************************************************************/ -static double mannwhitneyu_utbln8n12(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.600000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.398211e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.762214e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.226296e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.603837e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.643223e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.502438e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.544574e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.647734e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.442259e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.011484e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.384758e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.998259e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.659985e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.331046e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.638478e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.056785e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 8, 13) -*************************************************************************/ -static double mannwhitneyu_utbln8n13(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.600000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.380670e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.724511e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.195851e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.420511e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.609928e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.893999e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.115919e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.291410e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.339664e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.801548e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.534710e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.793250e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.806718e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.384624e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.120582e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.936453e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 8, 14) -*************************************************************************/ -static double mannwhitneyu_utbln8n14(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.600000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.368494e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.697171e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.174440e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.300621e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.087393e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.685826e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.085254e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.525658e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.966647e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.453388e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.826066e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.501958e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.336297e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.251972e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.118456e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.415959e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 8, 15) -*************************************************************************/ -static double mannwhitneyu_utbln8n15(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.600000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.358397e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.674485e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.155941e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.195780e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.544830e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.426183e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.309902e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.650956e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.068874e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.538544e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 8.192525e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.073905e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.079673e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 9.423572e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 6.579647e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.765904e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 8, 30) -*************************************************************************/ -static double mannwhitneyu_utbln8n30(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.600000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.318823e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.567159e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.064864e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.688413e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.153712e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.309389e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.226861e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.523815e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.780987e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.166866e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.922431e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.466397e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.690036e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.008185e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.271903e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.534751e-06, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 8, 100) -*************************************************************************/ -static double mannwhitneyu_utbln8n100(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.600000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.324531e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.547071e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.038129e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.541549e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.525605e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.044992e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.085713e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.017871e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.459226e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.092064e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.024349e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 7.366347e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 6.385637e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 8.321722e-08, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.439286e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.058079e-07, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 9, 9) -*************************************************************************/ -static double mannwhitneyu_utbln9n9(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.576237e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.372857e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.750859e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.248233e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.792868e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.559372e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.894941e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.643256e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.091370e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.285034e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 6.112997e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.806229e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.150741e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.509825e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.891051e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.485013e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.343653e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 9, 10) -*************************************************************************/ -static double mannwhitneyu_utbln9n10(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.650000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.516726e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.939333e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.305046e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.935326e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.029141e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.420592e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.053140e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.065930e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.523581e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.544888e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.813741e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.510631e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.536057e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.833815e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.189692e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.615050e-03, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 9, 11) -*************************************************************************/ -static double mannwhitneyu_utbln9n11(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.650000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.481308e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.867483e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.249072e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.591790e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.400128e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.341992e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.463680e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.487211e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.671196e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.343472e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.544146e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.802335e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.117084e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.217443e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.858766e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.193687e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 9, 12) -*************************************************************************/ -static double mannwhitneyu_utbln9n12(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.650000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.456776e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.817037e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.209788e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.362108e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.171356e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.661557e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.026141e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.361908e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.093885e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.298389e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.663603e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.768522e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.579015e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.868677e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.440652e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.523037e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 9, 13) -*************************************************************************/ -static double mannwhitneyu_utbln9n13(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.650000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.438840e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.779308e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.180614e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.196489e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.346621e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.234857e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.796211e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.575715e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.525647e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.964651e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.275235e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.299124e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.397416e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.295781e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.237619e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 7.269692e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 9, 14) -*************************************************************************/ -static double mannwhitneyu_utbln9n14(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.650000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.425981e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.751545e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.159543e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.086570e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.917446e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.120112e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.175519e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.515473e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.727772e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.070629e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.677569e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.876953e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.233502e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.508182e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.120389e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.847212e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 9, 15) -*************************************************************************/ -static double mannwhitneyu_utbln9n15(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.650000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.414952e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.727612e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.140634e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.981231e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.382635e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.853575e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.571051e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.567625e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.214197e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.448700e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.712669e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.015050e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.438610e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 6.301363e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.309386e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.164772e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 9, 30) -*************************************************************************/ -static double mannwhitneyu_utbln9n30(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.650000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.370720e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.615712e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.050023e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.504775e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.318265e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.646826e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.741492e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.735360e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.966911e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.100738e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.348991e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.527687e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.917286e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.397466e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.360175e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.892252e-07, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 9, 100) -*************************************************************************/ -static double mannwhitneyu_utbln9n100(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.650000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.372506e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.590966e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.021758e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.359849e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.755519e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.533166e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.936659e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.634913e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.730053e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.791845e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.030682e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.228663e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 8.631175e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.636749e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.404599e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.789872e-07, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 10, 10) -*************************************************************************/ -static double mannwhitneyu_utbln10n10(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.650000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.468831e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.844398e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.231728e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.486073e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.781321e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.971425e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.215371e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.828451e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.419872e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.430165e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.740363e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.049211e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.269371e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.211393e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.232314e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.016081e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 10, 11) -*************************************************************************/ -static double mannwhitneyu_utbln10n11(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.650000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.437998e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.782296e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.184732e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.219585e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.457012e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.296008e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.481501e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.527940e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.953426e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.563840e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.574403e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.535775e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.338037e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.002654e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.852676e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.318132e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 10, 12) -*************************************************************************/ -static double mannwhitneyu_utbln10n12(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.650000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.416082e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.737458e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.150952e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.036884e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.609030e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.908684e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.439666e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.162647e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.451601e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.148757e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.803981e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.731621e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.346903e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.013151e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.956148e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.438381e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 10, 13) -*************************************************************************/ -static double mannwhitneyu_utbln10n13(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.650000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.399480e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.702863e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.124829e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.897428e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.979802e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.634368e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.180461e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.484926e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.864376e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.186576e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.886925e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.836828e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.074756e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.209547e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.883266e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.380143e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 10, 14) -*************************************************************************/ -static double mannwhitneyu_utbln10n14(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.650000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.386924e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.676124e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.104740e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.793826e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.558886e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.492462e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.052903e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.917782e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.878696e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.576046e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.764551e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.288778e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.757658e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.299101e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.265197e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.384503e-07, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 10, 15) -*************************************************************************/ -static double mannwhitneyu_utbln10n15(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.650000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.376846e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.654247e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.088083e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.705945e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.169677e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.317213e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.264836e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.548024e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.633910e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.505621e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.658588e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.320254e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.175277e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.122317e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.675688e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.661363e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 10, 30) -*************************************************************************/ -static double mannwhitneyu_utbln10n30(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.650000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.333977e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.548099e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.004444e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.291014e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.523674e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.828211e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.716917e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.894256e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.433371e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.522675e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.764192e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.140235e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.629230e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.541895e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.944946e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.726360e-06, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 10, 100) -*************************************************************************/ -static double mannwhitneyu_utbln10n100(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.650000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.334008e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.522316e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.769627e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.158110e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.053650e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.242235e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.173571e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.033661e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.824732e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.084420e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.610036e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.728155e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.217130e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.340966e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.001235e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.694052e-07, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 11, 11) -*************************************************************************/ -static double mannwhitneyu_utbln11n11(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.700000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.519760e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.880694e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.200698e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.174092e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.072304e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.054773e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.506613e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.813942e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.223644e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.417416e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.499166e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.194332e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 7.369096e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.968590e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.630532e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.061000e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 11, 12) -*************************************************************************/ -static double mannwhitneyu_utbln11n12(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.700000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.495790e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.832622e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.165420e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.987306e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.265621e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.723537e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.347406e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.353464e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 6.613369e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.102522e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.237709e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.665652e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.626903e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.167518e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.564455e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.047320e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 11, 13) -*************************************************************************/ -static double mannwhitneyu_utbln11n13(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.700000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.477880e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.796242e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.138769e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.851739e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.722104e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.548304e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.176683e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.817895e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.842451e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.935870e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 8.421777e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.238831e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 8.867026e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.458255e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.306259e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.961487e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 11, 14) -*************************************************************************/ -static double mannwhitneyu_utbln11n14(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.700000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.463683e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.766969e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.117082e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.739574e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.238865e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.350306e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.425871e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.640172e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.660633e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.879883e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.349658e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.271795e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.304544e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.024201e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.816867e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.596787e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 11, 15) -*************************************************************************/ -static double mannwhitneyu_utbln11n15(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.700000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.452526e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.743570e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.099705e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.650612e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.858285e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.187036e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.689241e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.294360e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.072623e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.278008e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.322382e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.131558e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.305669e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.825627e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.332689e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.120973e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 11, 30) -*************************************************************************/ -static double mannwhitneyu_utbln11n30(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.700000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.402621e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.627440e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.011333e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.224126e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.232856e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.859347e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.377381e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.756709e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.033230e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.875472e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.608399e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.102943e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.740693e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.343139e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.196878e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.658062e-07, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 11, 100) -*************************************************************************/ -static double mannwhitneyu_utbln11n100(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.700000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.398795e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.596486e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.814761e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.085187e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.766529e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.379425e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.986351e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.214705e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.360075e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.260869e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.033307e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.727087e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.393883e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.242989e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.111928e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.898823e-09, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 12, 12) -*************************************************************************/ -static double mannwhitneyu_utbln12n12(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.700000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.472616e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.786627e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.132099e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.817523e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.570179e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.479511e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.799492e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.565350e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.530139e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.380132e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.242761e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.576269e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.018771e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.933911e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 9.002799e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.022048e-06, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 12, 13) -*************************************************************************/ -static double mannwhitneyu_utbln12n13(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.700000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.454800e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.750794e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.105988e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.684754e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.011826e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.262579e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.044492e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.478741e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.322165e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.621104e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.068753e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.468396e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.056235e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.327375e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.914877e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.784191e-04, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 12, 14) -*************************************************************************/ -static double mannwhitneyu_utbln12n14(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.700000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.440910e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.722404e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.085254e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.579439e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.563738e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.066730e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.129346e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.014531e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.129679e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.000909e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.996174e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 6.377924e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 8.936304e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.051098e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 9.025820e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 8.730585e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 12, 15) -*************************************************************************/ -static double mannwhitneyu_utbln12n15(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.700000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.430123e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.700008e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.068971e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.499725e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.250897e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.473145e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.680008e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.483350e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.766992e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.891081e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.015140e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.977756e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.707414e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.114786e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 6.238865e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.381445e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 12, 30) -*************************************************************************/ -static double mannwhitneyu_utbln12n30(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.700000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.380023e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.585782e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.838583e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.103394e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.834015e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.635212e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.948212e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.574169e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.747980e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.833672e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.722433e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.181038e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.206473e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.716003e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.476434e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.217700e-07, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 12, 100) -*************************************************************************/ -static double mannwhitneyu_utbln12n100(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.700000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.374567e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.553481e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.541334e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.701907e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.414757e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.404103e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.234388e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.453762e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.311060e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.317501e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.713888e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.309583e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.019804e-08, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.224829e-09, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.349019e-08, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.893302e-08, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 13, 13) -*************************************************************************/ -static double mannwhitneyu_utbln13n13(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.750000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.541046e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.859047e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.130164e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.689719e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.950693e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.231455e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.976550e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.538455e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.245603e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.142647e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.831434e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.032483e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.488405e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.156927e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.949279e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.532700e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 13, 14) -*************************************************************************/ -static double mannwhitneyu_utbln13n14(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.750000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.525655e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.828341e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.108110e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.579552e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.488307e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.032328e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.988741e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.766394e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.388950e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.338179e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.133440e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.023518e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.110570e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.202332e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.056132e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.536323e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 13, 15) -*************************************************************************/ -static double mannwhitneyu_utbln13n15(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.750000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.513585e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.803952e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.090686e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.495310e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.160314e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.073124e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.480313e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.478239e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.140914e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.311541e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.677105e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.115464e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.578563e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.044604e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.888939e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 2.395644e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 13, 30) -*************************************************************************/ -static double mannwhitneyu_utbln13n30(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.750000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.455999e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.678434e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.995491e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.078100e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.705220e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.258739e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.671526e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.185458e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.507764e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.411446e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.044355e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.285765e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.345282e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.066940e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.962037e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.723644e-07, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 13, 100) -*************************************************************************/ -static double mannwhitneyu_utbln13n100(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.750000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.446787e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.640804e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.671552e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.364990e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.274444e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.047440e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.161439e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.171729e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.562171e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.359762e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.275494e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.747635e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.700292e-08, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.565559e-09, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 5.005396e-09, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 3.335794e-09, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 14, 14) -*************************************************************************/ -static double mannwhitneyu_utbln14n14(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.750000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.510624e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.798584e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.087107e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.478532e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.098050e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.855986e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.409083e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.299536e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.176177e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.479417e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.812761e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -5.225872e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 4.516521e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 6.730551e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 9.237563e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.611820e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 14, 15) -*************************************************************************/ -static double mannwhitneyu_utbln14n15(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.750000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.498681e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.774668e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.070267e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.399348e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.807239e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.845763e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.071773e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.261698e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.011695e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.305946e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.879295e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.999439e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.904438e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.944986e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.373908e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.140794e-05, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 14, 30) -*************************************************************************/ -static double mannwhitneyu_utbln14n30(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.750000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.440378e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.649587e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.807829e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.989753e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.463646e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.586580e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -6.745917e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.635398e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.923172e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.446699e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.613892e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.214073e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.651683e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.272777e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.464988e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.109803e-07, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, 14, 100) -*************************************************************************/ -static double mannwhitneyu_utbln14n100(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - x = ae_minreal(2*(s-0.000000e+00)/3.750000e+00-1, 1.0, _state); - tj = (double)(1); - tj1 = x; - mannwhitneyu_ucheb(x, -4.429701e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -4.610577e+00, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -9.482675e-01, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.605550e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.062151e-02, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.525154e-03, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.835983e-04, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -8.411440e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.744901e-05, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.318850e-06, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.692100e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -1.536270e-07, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -3.705888e-08, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -7.999599e-09, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, -2.908395e-09, &tj, &tj1, &result, _state); - mannwhitneyu_ucheb(x, 1.546923e-09, &tj, &tj1, &result, _state); - return result; -} - - -/************************************************************************* -Tail(S, N1, N2) -*************************************************************************/ -static double mannwhitneyu_usigma(double s, - ae_int_t n1, - ae_int_t n2, - ae_state *_state) -{ - double f0; - double f1; - double f2; - double f3; - double f4; - double s0; - double s1; - double s2; - double s3; - double s4; - double result; - - - result = (double)(0); - - /* - * N1=5, N2 = 5, 6, 7, ... - */ - if( ae_minint(n1, n2, _state)==5 ) - { - if( ae_maxint(n1, n2, _state)==5 ) - { - result = mannwhitneyu_utbln5n5(s, _state); - } - if( ae_maxint(n1, n2, _state)==6 ) - { - result = mannwhitneyu_utbln5n6(s, _state); - } - if( ae_maxint(n1, n2, _state)==7 ) - { - result = mannwhitneyu_utbln5n7(s, _state); - } - if( ae_maxint(n1, n2, _state)==8 ) - { - result = mannwhitneyu_utbln5n8(s, _state); - } - if( ae_maxint(n1, n2, _state)==9 ) - { - result = mannwhitneyu_utbln5n9(s, _state); - } - if( ae_maxint(n1, n2, _state)==10 ) - { - result = mannwhitneyu_utbln5n10(s, _state); - } - if( ae_maxint(n1, n2, _state)==11 ) - { - result = mannwhitneyu_utbln5n11(s, _state); - } - if( ae_maxint(n1, n2, _state)==12 ) - { - result = mannwhitneyu_utbln5n12(s, _state); - } - if( ae_maxint(n1, n2, _state)==13 ) - { - result = mannwhitneyu_utbln5n13(s, _state); - } - if( ae_maxint(n1, n2, _state)==14 ) - { - result = mannwhitneyu_utbln5n14(s, _state); - } - if( ae_maxint(n1, n2, _state)==15 ) - { - result = mannwhitneyu_utbln5n15(s, _state); - } - if( ae_maxint(n1, n2, _state)==16 ) - { - result = mannwhitneyu_utbln5n16(s, _state); - } - if( ae_maxint(n1, n2, _state)==17 ) - { - result = mannwhitneyu_utbln5n17(s, _state); - } - if( ae_maxint(n1, n2, _state)==18 ) - { - result = mannwhitneyu_utbln5n18(s, _state); - } - if( ae_maxint(n1, n2, _state)==19 ) - { - result = mannwhitneyu_utbln5n19(s, _state); - } - if( ae_maxint(n1, n2, _state)==20 ) - { - result = mannwhitneyu_utbln5n20(s, _state); - } - if( ae_maxint(n1, n2, _state)==21 ) - { - result = mannwhitneyu_utbln5n21(s, _state); - } - if( ae_maxint(n1, n2, _state)==22 ) - { - result = mannwhitneyu_utbln5n22(s, _state); - } - if( ae_maxint(n1, n2, _state)==23 ) - { - result = mannwhitneyu_utbln5n23(s, _state); - } - if( ae_maxint(n1, n2, _state)==24 ) - { - result = mannwhitneyu_utbln5n24(s, _state); - } - if( ae_maxint(n1, n2, _state)==25 ) - { - result = mannwhitneyu_utbln5n25(s, _state); - } - if( ae_maxint(n1, n2, _state)==26 ) - { - result = mannwhitneyu_utbln5n26(s, _state); - } - if( ae_maxint(n1, n2, _state)==27 ) - { - result = mannwhitneyu_utbln5n27(s, _state); - } - if( ae_maxint(n1, n2, _state)==28 ) - { - result = mannwhitneyu_utbln5n28(s, _state); - } - if( ae_maxint(n1, n2, _state)==29 ) - { - result = mannwhitneyu_utbln5n29(s, _state); - } - if( ae_maxint(n1, n2, _state)>29 ) - { - f0 = mannwhitneyu_utbln5n15(s, _state); - f1 = mannwhitneyu_utbln5n30(s, _state); - f2 = mannwhitneyu_utbln5n100(s, _state); - result = mannwhitneyu_uninterpolate(f0, f1, f2, ae_maxint(n1, n2, _state), _state); - } - return result; - } - - /* - * N1=6, N2 = 6, 7, 8, ... - */ - if( ae_minint(n1, n2, _state)==6 ) - { - if( ae_maxint(n1, n2, _state)==6 ) - { - result = mannwhitneyu_utbln6n6(s, _state); - } - if( ae_maxint(n1, n2, _state)==7 ) - { - result = mannwhitneyu_utbln6n7(s, _state); - } - if( ae_maxint(n1, n2, _state)==8 ) - { - result = mannwhitneyu_utbln6n8(s, _state); - } - if( ae_maxint(n1, n2, _state)==9 ) - { - result = mannwhitneyu_utbln6n9(s, _state); - } - if( ae_maxint(n1, n2, _state)==10 ) - { - result = mannwhitneyu_utbln6n10(s, _state); - } - if( ae_maxint(n1, n2, _state)==11 ) - { - result = mannwhitneyu_utbln6n11(s, _state); - } - if( ae_maxint(n1, n2, _state)==12 ) - { - result = mannwhitneyu_utbln6n12(s, _state); - } - if( ae_maxint(n1, n2, _state)==13 ) - { - result = mannwhitneyu_utbln6n13(s, _state); - } - if( ae_maxint(n1, n2, _state)==14 ) - { - result = mannwhitneyu_utbln6n14(s, _state); - } - if( ae_maxint(n1, n2, _state)==15 ) - { - result = mannwhitneyu_utbln6n15(s, _state); - } - if( ae_maxint(n1, n2, _state)>15 ) - { - f0 = mannwhitneyu_utbln6n15(s, _state); - f1 = mannwhitneyu_utbln6n30(s, _state); - f2 = mannwhitneyu_utbln6n100(s, _state); - result = mannwhitneyu_uninterpolate(f0, f1, f2, ae_maxint(n1, n2, _state), _state); - } - return result; - } - - /* - * N1=7, N2 = 7, 8, ... - */ - if( ae_minint(n1, n2, _state)==7 ) - { - if( ae_maxint(n1, n2, _state)==7 ) - { - result = mannwhitneyu_utbln7n7(s, _state); - } - if( ae_maxint(n1, n2, _state)==8 ) - { - result = mannwhitneyu_utbln7n8(s, _state); - } - if( ae_maxint(n1, n2, _state)==9 ) - { - result = mannwhitneyu_utbln7n9(s, _state); - } - if( ae_maxint(n1, n2, _state)==10 ) - { - result = mannwhitneyu_utbln7n10(s, _state); - } - if( ae_maxint(n1, n2, _state)==11 ) - { - result = mannwhitneyu_utbln7n11(s, _state); - } - if( ae_maxint(n1, n2, _state)==12 ) - { - result = mannwhitneyu_utbln7n12(s, _state); - } - if( ae_maxint(n1, n2, _state)==13 ) - { - result = mannwhitneyu_utbln7n13(s, _state); - } - if( ae_maxint(n1, n2, _state)==14 ) - { - result = mannwhitneyu_utbln7n14(s, _state); - } - if( ae_maxint(n1, n2, _state)==15 ) - { - result = mannwhitneyu_utbln7n15(s, _state); - } - if( ae_maxint(n1, n2, _state)>15 ) - { - f0 = mannwhitneyu_utbln7n15(s, _state); - f1 = mannwhitneyu_utbln7n30(s, _state); - f2 = mannwhitneyu_utbln7n100(s, _state); - result = mannwhitneyu_uninterpolate(f0, f1, f2, ae_maxint(n1, n2, _state), _state); - } - return result; - } - - /* - * N1=8, N2 = 8, 9, 10, ... - */ - if( ae_minint(n1, n2, _state)==8 ) - { - if( ae_maxint(n1, n2, _state)==8 ) - { - result = mannwhitneyu_utbln8n8(s, _state); - } - if( ae_maxint(n1, n2, _state)==9 ) - { - result = mannwhitneyu_utbln8n9(s, _state); - } - if( ae_maxint(n1, n2, _state)==10 ) - { - result = mannwhitneyu_utbln8n10(s, _state); - } - if( ae_maxint(n1, n2, _state)==11 ) - { - result = mannwhitneyu_utbln8n11(s, _state); - } - if( ae_maxint(n1, n2, _state)==12 ) - { - result = mannwhitneyu_utbln8n12(s, _state); - } - if( ae_maxint(n1, n2, _state)==13 ) - { - result = mannwhitneyu_utbln8n13(s, _state); - } - if( ae_maxint(n1, n2, _state)==14 ) - { - result = mannwhitneyu_utbln8n14(s, _state); - } - if( ae_maxint(n1, n2, _state)==15 ) - { - result = mannwhitneyu_utbln8n15(s, _state); - } - if( ae_maxint(n1, n2, _state)>15 ) - { - f0 = mannwhitneyu_utbln8n15(s, _state); - f1 = mannwhitneyu_utbln8n30(s, _state); - f2 = mannwhitneyu_utbln8n100(s, _state); - result = mannwhitneyu_uninterpolate(f0, f1, f2, ae_maxint(n1, n2, _state), _state); - } - return result; - } - - /* - * N1=9, N2 = 9, 10, ... - */ - if( ae_minint(n1, n2, _state)==9 ) - { - if( ae_maxint(n1, n2, _state)==9 ) - { - result = mannwhitneyu_utbln9n9(s, _state); - } - if( ae_maxint(n1, n2, _state)==10 ) - { - result = mannwhitneyu_utbln9n10(s, _state); - } - if( ae_maxint(n1, n2, _state)==11 ) - { - result = mannwhitneyu_utbln9n11(s, _state); - } - if( ae_maxint(n1, n2, _state)==12 ) - { - result = mannwhitneyu_utbln9n12(s, _state); - } - if( ae_maxint(n1, n2, _state)==13 ) - { - result = mannwhitneyu_utbln9n13(s, _state); - } - if( ae_maxint(n1, n2, _state)==14 ) - { - result = mannwhitneyu_utbln9n14(s, _state); - } - if( ae_maxint(n1, n2, _state)==15 ) - { - result = mannwhitneyu_utbln9n15(s, _state); - } - if( ae_maxint(n1, n2, _state)>15 ) - { - f0 = mannwhitneyu_utbln9n15(s, _state); - f1 = mannwhitneyu_utbln9n30(s, _state); - f2 = mannwhitneyu_utbln9n100(s, _state); - result = mannwhitneyu_uninterpolate(f0, f1, f2, ae_maxint(n1, n2, _state), _state); - } - return result; - } - - /* - * N1=10, N2 = 10, 11, ... - */ - if( ae_minint(n1, n2, _state)==10 ) - { - if( ae_maxint(n1, n2, _state)==10 ) - { - result = mannwhitneyu_utbln10n10(s, _state); - } - if( ae_maxint(n1, n2, _state)==11 ) - { - result = mannwhitneyu_utbln10n11(s, _state); - } - if( ae_maxint(n1, n2, _state)==12 ) - { - result = mannwhitneyu_utbln10n12(s, _state); - } - if( ae_maxint(n1, n2, _state)==13 ) - { - result = mannwhitneyu_utbln10n13(s, _state); - } - if( ae_maxint(n1, n2, _state)==14 ) - { - result = mannwhitneyu_utbln10n14(s, _state); - } - if( ae_maxint(n1, n2, _state)==15 ) - { - result = mannwhitneyu_utbln10n15(s, _state); - } - if( ae_maxint(n1, n2, _state)>15 ) - { - f0 = mannwhitneyu_utbln10n15(s, _state); - f1 = mannwhitneyu_utbln10n30(s, _state); - f2 = mannwhitneyu_utbln10n100(s, _state); - result = mannwhitneyu_uninterpolate(f0, f1, f2, ae_maxint(n1, n2, _state), _state); - } - return result; - } - - /* - * N1=11, N2 = 11, 12, ... - */ - if( ae_minint(n1, n2, _state)==11 ) - { - if( ae_maxint(n1, n2, _state)==11 ) - { - result = mannwhitneyu_utbln11n11(s, _state); - } - if( ae_maxint(n1, n2, _state)==12 ) - { - result = mannwhitneyu_utbln11n12(s, _state); - } - if( ae_maxint(n1, n2, _state)==13 ) - { - result = mannwhitneyu_utbln11n13(s, _state); - } - if( ae_maxint(n1, n2, _state)==14 ) - { - result = mannwhitneyu_utbln11n14(s, _state); - } - if( ae_maxint(n1, n2, _state)==15 ) - { - result = mannwhitneyu_utbln11n15(s, _state); - } - if( ae_maxint(n1, n2, _state)>15 ) - { - f0 = mannwhitneyu_utbln11n15(s, _state); - f1 = mannwhitneyu_utbln11n30(s, _state); - f2 = mannwhitneyu_utbln11n100(s, _state); - result = mannwhitneyu_uninterpolate(f0, f1, f2, ae_maxint(n1, n2, _state), _state); - } - return result; - } - - /* - * N1=12, N2 = 12, 13, ... - */ - if( ae_minint(n1, n2, _state)==12 ) - { - if( ae_maxint(n1, n2, _state)==12 ) - { - result = mannwhitneyu_utbln12n12(s, _state); - } - if( ae_maxint(n1, n2, _state)==13 ) - { - result = mannwhitneyu_utbln12n13(s, _state); - } - if( ae_maxint(n1, n2, _state)==14 ) - { - result = mannwhitneyu_utbln12n14(s, _state); - } - if( ae_maxint(n1, n2, _state)==15 ) - { - result = mannwhitneyu_utbln12n15(s, _state); - } - if( ae_maxint(n1, n2, _state)>15 ) - { - f0 = mannwhitneyu_utbln12n15(s, _state); - f1 = mannwhitneyu_utbln12n30(s, _state); - f2 = mannwhitneyu_utbln12n100(s, _state); - result = mannwhitneyu_uninterpolate(f0, f1, f2, ae_maxint(n1, n2, _state), _state); - } - return result; - } - - /* - * N1=13, N2 = 13, 14, ... - */ - if( ae_minint(n1, n2, _state)==13 ) - { - if( ae_maxint(n1, n2, _state)==13 ) - { - result = mannwhitneyu_utbln13n13(s, _state); - } - if( ae_maxint(n1, n2, _state)==14 ) - { - result = mannwhitneyu_utbln13n14(s, _state); - } - if( ae_maxint(n1, n2, _state)==15 ) - { - result = mannwhitneyu_utbln13n15(s, _state); - } - if( ae_maxint(n1, n2, _state)>15 ) - { - f0 = mannwhitneyu_utbln13n15(s, _state); - f1 = mannwhitneyu_utbln13n30(s, _state); - f2 = mannwhitneyu_utbln13n100(s, _state); - result = mannwhitneyu_uninterpolate(f0, f1, f2, ae_maxint(n1, n2, _state), _state); - } - return result; - } - - /* - * N1=14, N2 = 14, 15, ... - */ - if( ae_minint(n1, n2, _state)==14 ) - { - if( ae_maxint(n1, n2, _state)==14 ) - { - result = mannwhitneyu_utbln14n14(s, _state); - } - if( ae_maxint(n1, n2, _state)==15 ) - { - result = mannwhitneyu_utbln14n15(s, _state); - } - if( ae_maxint(n1, n2, _state)>15 ) - { - f0 = mannwhitneyu_utbln14n15(s, _state); - f1 = mannwhitneyu_utbln14n30(s, _state); - f2 = mannwhitneyu_utbln14n100(s, _state); - result = mannwhitneyu_uninterpolate(f0, f1, f2, ae_maxint(n1, n2, _state), _state); - } - return result; - } - - /* - * N1 >= 15, N2 >= 15 - */ - if( ae_fp_greater(s,(double)(4)) ) - { - s = (double)(4); - } - if( ae_fp_less(s,(double)(3)) ) - { - s0 = 0.000000e+00; - f0 = mannwhitneyu_usigma000(n1, n2, _state); - s1 = 7.500000e-01; - f1 = mannwhitneyu_usigma075(n1, n2, _state); - s2 = 1.500000e+00; - f2 = mannwhitneyu_usigma150(n1, n2, _state); - s3 = 2.250000e+00; - f3 = mannwhitneyu_usigma225(n1, n2, _state); - s4 = 3.000000e+00; - f4 = mannwhitneyu_usigma300(n1, n2, _state); - f1 = ((s-s0)*f1-(s-s1)*f0)/(s1-s0); - f2 = ((s-s0)*f2-(s-s2)*f0)/(s2-s0); - f3 = ((s-s0)*f3-(s-s3)*f0)/(s3-s0); - f4 = ((s-s0)*f4-(s-s4)*f0)/(s4-s0); - f2 = ((s-s1)*f2-(s-s2)*f1)/(s2-s1); - f3 = ((s-s1)*f3-(s-s3)*f1)/(s3-s1); - f4 = ((s-s1)*f4-(s-s4)*f1)/(s4-s1); - f3 = ((s-s2)*f3-(s-s3)*f2)/(s3-s2); - f4 = ((s-s2)*f4-(s-s4)*f2)/(s4-s2); - f4 = ((s-s3)*f4-(s-s4)*f3)/(s4-s3); - result = f4; - } - else - { - s0 = 3.000000e+00; - f0 = mannwhitneyu_usigma300(n1, n2, _state); - s1 = 3.333333e+00; - f1 = mannwhitneyu_usigma333(n1, n2, _state); - s2 = 3.666667e+00; - f2 = mannwhitneyu_usigma367(n1, n2, _state); - s3 = 4.000000e+00; - f3 = mannwhitneyu_usigma400(n1, n2, _state); - f1 = ((s-s0)*f1-(s-s1)*f0)/(s1-s0); - f2 = ((s-s0)*f2-(s-s2)*f0)/(s2-s0); - f3 = ((s-s0)*f3-(s-s3)*f0)/(s3-s0); - f2 = ((s-s1)*f2-(s-s2)*f1)/(s2-s1); - f3 = ((s-s1)*f3-(s-s3)*f1)/(s3-s1); - f3 = ((s-s2)*f3-(s-s3)*f2)/(s3-s2); - result = f3; - } - return result; -} - - -#endif -#if defined(AE_COMPILE_JARQUEBERA) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Jarque-Bera test - -This test checks hypotheses about the fact that a given sample X is a -sample of normal random variable. - -Requirements: - * the number of elements in the sample is not less than 5. - -Input parameters: - X - sample. Array whose index goes from 0 to N-1. - N - size of the sample. N>=5 - -Output parameters: - P - p-value for the test - -Accuracy of the approximation used (5<=N<=1951): - -p-value relative error (5<=N<=1951) -[1, 0.1] < 1% -[0.1, 0.01] < 2% -[0.01, 0.001] < 6% -[0.001, 0] wasn't measured - -For N>1951 accuracy wasn't measured but it shouldn't be sharply different -from table values. - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -void jarqueberatest(/* Real */ ae_vector* x, - ae_int_t n, - double* p, - ae_state *_state) -{ - double s; - - *p = 0; - - - /* - * N is too small - */ - if( n<5 ) - { - *p = 1.0; - return; - } - - /* - * N is large enough - */ - jarquebera_jarqueberastatistic(x, n, &s, _state); - *p = jarquebera_jarqueberaapprox(n, s, _state); -} - - -static void jarquebera_jarqueberastatistic(/* Real */ ae_vector* x, - ae_int_t n, - double* s, - ae_state *_state) -{ - ae_int_t i; - double v; - double v1; - double v2; - double stddev; - double mean; - double variance; - double skewness; - double kurtosis; - - *s = 0; - - mean = (double)(0); - variance = (double)(0); - skewness = (double)(0); - kurtosis = (double)(0); - stddev = (double)(0); - ae_assert(n>1, "Assertion failed", _state); - - /* - * Mean - */ - for(i=0; i<=n-1; i++) - { - mean = mean+x->ptr.p_double[i]; - } - mean = mean/n; - - /* - * Variance (using corrected two-pass algorithm) - */ - if( n!=1 ) - { - v1 = (double)(0); - for(i=0; i<=n-1; i++) - { - v1 = v1+ae_sqr(x->ptr.p_double[i]-mean, _state); - } - v2 = (double)(0); - for(i=0; i<=n-1; i++) - { - v2 = v2+(x->ptr.p_double[i]-mean); - } - v2 = ae_sqr(v2, _state)/n; - variance = (v1-v2)/(n-1); - if( ae_fp_less(variance,(double)(0)) ) - { - variance = (double)(0); - } - stddev = ae_sqrt(variance, _state); - } - - /* - * Skewness and kurtosis - */ - if( ae_fp_neq(stddev,(double)(0)) ) - { - for(i=0; i<=n-1; i++) - { - v = (x->ptr.p_double[i]-mean)/stddev; - v2 = ae_sqr(v, _state); - skewness = skewness+v2*v; - kurtosis = kurtosis+ae_sqr(v2, _state); - } - skewness = skewness/n; - kurtosis = kurtosis/n-3; - } - - /* - * Statistic - */ - *s = (double)n/(double)6*(ae_sqr(skewness, _state)+ae_sqr(kurtosis, _state)/4); -} - - -static double jarquebera_jarqueberaapprox(ae_int_t n, - double s, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector vx; - ae_vector vy; - ae_matrix ctbl; - double t1; - double t2; - double t3; - double t; - double f1; - double f2; - double f3; - double f12; - double f23; - double x; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&vx, 0, sizeof(vx)); - memset(&vy, 0, sizeof(vy)); - memset(&ctbl, 0, sizeof(ctbl)); - ae_vector_init(&vx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vy, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ctbl, 0, 0, DT_REAL, _state, ae_true); - - result = (double)(1); - x = s; - if( n<5 ) - { - ae_frame_leave(_state); - return result; - } - - /* - * N = 5..20 are tabulated - */ - if( n>=5&&n<=20 ) - { - if( n==5 ) - { - result = ae_exp(jarquebera_jbtbl5(x, _state), _state); - } - if( n==6 ) - { - result = ae_exp(jarquebera_jbtbl6(x, _state), _state); - } - if( n==7 ) - { - result = ae_exp(jarquebera_jbtbl7(x, _state), _state); - } - if( n==8 ) - { - result = ae_exp(jarquebera_jbtbl8(x, _state), _state); - } - if( n==9 ) - { - result = ae_exp(jarquebera_jbtbl9(x, _state), _state); - } - if( n==10 ) - { - result = ae_exp(jarquebera_jbtbl10(x, _state), _state); - } - if( n==11 ) - { - result = ae_exp(jarquebera_jbtbl11(x, _state), _state); - } - if( n==12 ) - { - result = ae_exp(jarquebera_jbtbl12(x, _state), _state); - } - if( n==13 ) - { - result = ae_exp(jarquebera_jbtbl13(x, _state), _state); - } - if( n==14 ) - { - result = ae_exp(jarquebera_jbtbl14(x, _state), _state); - } - if( n==15 ) - { - result = ae_exp(jarquebera_jbtbl15(x, _state), _state); - } - if( n==16 ) - { - result = ae_exp(jarquebera_jbtbl16(x, _state), _state); - } - if( n==17 ) - { - result = ae_exp(jarquebera_jbtbl17(x, _state), _state); - } - if( n==18 ) - { - result = ae_exp(jarquebera_jbtbl18(x, _state), _state); - } - if( n==19 ) - { - result = ae_exp(jarquebera_jbtbl19(x, _state), _state); - } - if( n==20 ) - { - result = ae_exp(jarquebera_jbtbl20(x, _state), _state); - } - ae_frame_leave(_state); - return result; - } - - /* - * N = 20, 30, 50 are tabulated. - * In-between values are interpolated - * using interpolating polynomial of the second degree. - */ - if( n>20&&n<=50 ) - { - t1 = -1.0/20.0; - t2 = -1.0/30.0; - t3 = -1.0/50.0; - t = -1.0/n; - f1 = jarquebera_jbtbl20(x, _state); - f2 = jarquebera_jbtbl30(x, _state); - f3 = jarquebera_jbtbl50(x, _state); - f12 = ((t-t2)*f1+(t1-t)*f2)/(t1-t2); - f23 = ((t-t3)*f2+(t2-t)*f3)/(t2-t3); - result = ((t-t3)*f12+(t1-t)*f23)/(t1-t3); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - result = ae_exp(result, _state); - ae_frame_leave(_state); - return result; - } - - /* - * N = 50, 65, 100 are tabulated. - * In-between values are interpolated - * using interpolating polynomial of the second degree. - */ - if( n>50&&n<=100 ) - { - t1 = -1.0/50.0; - t2 = -1.0/65.0; - t3 = -1.0/100.0; - t = -1.0/n; - f1 = jarquebera_jbtbl50(x, _state); - f2 = jarquebera_jbtbl65(x, _state); - f3 = jarquebera_jbtbl100(x, _state); - f12 = ((t-t2)*f1+(t1-t)*f2)/(t1-t2); - f23 = ((t-t3)*f2+(t2-t)*f3)/(t2-t3); - result = ((t-t3)*f12+(t1-t)*f23)/(t1-t3); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - result = ae_exp(result, _state); - ae_frame_leave(_state); - return result; - } - - /* - * N = 100, 130, 200 are tabulated. - * In-between values are interpolated - * using interpolating polynomial of the second degree. - */ - if( n>100&&n<=200 ) - { - t1 = -1.0/100.0; - t2 = -1.0/130.0; - t3 = -1.0/200.0; - t = -1.0/n; - f1 = jarquebera_jbtbl100(x, _state); - f2 = jarquebera_jbtbl130(x, _state); - f3 = jarquebera_jbtbl200(x, _state); - f12 = ((t-t2)*f1+(t1-t)*f2)/(t1-t2); - f23 = ((t-t3)*f2+(t2-t)*f3)/(t2-t3); - result = ((t-t3)*f12+(t1-t)*f23)/(t1-t3); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - result = ae_exp(result, _state); - ae_frame_leave(_state); - return result; - } - - /* - * N = 200, 301, 501 are tabulated. - * In-between values are interpolated - * using interpolating polynomial of the second degree. - */ - if( n>200&&n<=501 ) - { - t1 = -1.0/200.0; - t2 = -1.0/301.0; - t3 = -1.0/501.0; - t = -1.0/n; - f1 = jarquebera_jbtbl200(x, _state); - f2 = jarquebera_jbtbl301(x, _state); - f3 = jarquebera_jbtbl501(x, _state); - f12 = ((t-t2)*f1+(t1-t)*f2)/(t1-t2); - f23 = ((t-t3)*f2+(t2-t)*f3)/(t2-t3); - result = ((t-t3)*f12+(t1-t)*f23)/(t1-t3); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - result = ae_exp(result, _state); - ae_frame_leave(_state); - return result; - } - - /* - * N = 501, 701, 1401 are tabulated. - * In-between values are interpolated - * using interpolating polynomial of the second degree. - */ - if( n>501&&n<=1401 ) - { - t1 = -1.0/501.0; - t2 = -1.0/701.0; - t3 = -1.0/1401.0; - t = -1.0/n; - f1 = jarquebera_jbtbl501(x, _state); - f2 = jarquebera_jbtbl701(x, _state); - f3 = jarquebera_jbtbl1401(x, _state); - f12 = ((t-t2)*f1+(t1-t)*f2)/(t1-t2); - f23 = ((t-t3)*f2+(t2-t)*f3)/(t2-t3); - result = ((t-t3)*f12+(t1-t)*f23)/(t1-t3); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - result = ae_exp(result, _state); - ae_frame_leave(_state); - return result; - } - - /* - * Asymptotic expansion - */ - if( n>1401 ) - { - result = -0.5*x+(jarquebera_jbtbl1401(x, _state)+0.5*x)*ae_sqrt((double)1401/(double)n, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - result = ae_exp(result, _state); - ae_frame_leave(_state); - return result; - } - ae_frame_leave(_state); - return result; -} - - -static double jarquebera_jbtbl5(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,0.4000) ) - { - x = 2*(s-0.000000)/0.400000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -1.097885e-20, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.854501e-20, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.756616e-20, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,1.1000) ) - { - x = 2*(s-0.400000)/0.700000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -1.324545e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.075941e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -9.772272e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.175686e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.576162e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.126861e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.434425e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.790359e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.809178e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.479704e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.717040e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.294170e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.880632e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.023344e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.601531e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -7.920403e-02, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -5.188419e+02*(s-1.100000e+00)-4.767297e+00; - return result; -} - - -static double jarquebera_jbtbl6(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,0.2500) ) - { - x = 2*(s-0.000000)/0.250000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -2.274707e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.700471e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.425764e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,1.3000) ) - { - x = 2*(s-0.250000)/1.050000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -1.339000e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.011104e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -8.168177e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.085666e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 7.738606e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 7.022876e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.462402e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 6.908270e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -8.230772e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.006996e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.410222e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.893768e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 8.114564e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,1.8500) ) - { - x = 2*(s-1.300000)/0.550000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -6.794311e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.578700e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.394664e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -7.928290e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.813273e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.076063e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.835380e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.013013e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.058903e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.856915e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.710887e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -1.770029e+02*(s-1.850000e+00)-1.371015e+01; - return result; -} - - -static double jarquebera_jbtbl7(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,1.4000) ) - { - x = 2*(s-0.000000)/1.400000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -1.093681e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.695911e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -7.473192e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.203236e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 6.590379e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 6.291876e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.132007e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 9.411147e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.180067e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.487610e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.436561e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,3.0000) ) - { - x = 2*(s-1.400000)/1.600000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -5.947854e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.772675e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.707912e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.691171e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.132795e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.481310e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.867536e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 8.772327e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.033387e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.378277e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.497964e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.636814e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -9.581640e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,3.2000) ) - { - x = 2*(s-3.000000)/0.200000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -7.511008e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -8.140472e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.682053e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.568561e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.933930e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -8.140472e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.895025e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -8.140472e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.933930e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.568561e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.682053e+00, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -1.824116e+03*(s-3.200000e+00)-1.440330e+01; - return result; -} - - -static double jarquebera_jbtbl8(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,1.3000) ) - { - x = 2*(s-0.000000)/1.300000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -7.199015e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.095921e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.736828e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.047438e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.484320e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 7.937923e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 4.810470e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.139780e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 6.708443e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,2.0000) ) - { - x = 2*(s-1.300000)/0.700000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -3.378966e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -7.802461e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.547593e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.241042e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.203274e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.201990e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.125597e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.584426e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.546069e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,5.0000) ) - { - x = 2*(s-2.000000)/3.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -6.828366e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.137533e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.016671e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.745637e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.189801e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.621610e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.741122e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.516368e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.552085e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.787029e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.359774e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -5.087028e+00*(s-5.000000e+00)-1.071300e+01; - return result; -} - - -static double jarquebera_jbtbl9(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,1.3000) ) - { - x = 2*(s-0.000000)/1.300000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -6.279320e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -9.277151e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.669339e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -7.086149e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.333816e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.871249e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.007048e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 7.482245e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.355615e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,2.0000) ) - { - x = 2*(s-1.300000)/0.700000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -2.981430e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -7.972248e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.747737e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.808530e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -7.888305e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 9.001302e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.378767e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.108510e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.915372e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,7.0000) ) - { - x = 2*(s-2.000000)/5.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -6.387463e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.845231e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.809956e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -7.543461e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.880397e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.160074e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -7.356527e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.394428e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 9.619892e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.758763e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 4.790977e-05, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -2.020952e+00*(s-7.000000e+00)-9.516623e+00; - return result; -} - - -static double jarquebera_jbtbl10(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,1.2000) ) - { - x = 2*(s-0.000000)/1.200000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -4.590993e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.562730e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.353934e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.069933e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.849151e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 8.931406e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.636295e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.178340e-05, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -8.917749e-05, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,2.0000) ) - { - x = 2*(s-1.200000)/0.800000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -2.537658e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -9.962401e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.838715e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.055792e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.580316e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.781701e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.770362e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.838983e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.999052e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,7.0000) ) - { - x = 2*(s-2.000000)/5.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -5.337524e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.877029e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 4.734650e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.249254e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.320250e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.432266e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -8.711035e-01*(s-7.000000e+00)-7.212811e+00; - return result; -} - - -static double jarquebera_jbtbl11(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,1.2000) ) - { - x = 2*(s-0.000000)/1.200000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -4.339517e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.051558e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.000992e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.022547e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -9.808401e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.592870e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.575081e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.086173e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 6.089011e-05, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,2.2500) ) - { - x = 2*(s-1.200000)/1.050000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -2.523221e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.068388e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.179661e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.555524e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.238964e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 7.364320e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 4.895771e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.762774e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -8.201340e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,8.0000) ) - { - x = 2*(s-2.250000)/5.750000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -5.212179e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.684579e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 8.299519e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.606261e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 7.310869e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.320115e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -5.715445e-01*(s-8.000000e+00)-6.845834e+00; - return result; -} - - -static double jarquebera_jbtbl12(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,1.0000) ) - { - x = 2*(s-0.000000)/1.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -2.736742e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.657836e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.047209e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.319599e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.545631e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 9.280445e-05, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.815679e-05, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.213519e-05, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.256838e-05, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,3.0000) ) - { - x = 2*(s-1.000000)/2.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -2.573947e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.515287e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.611880e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.271311e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.495815e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 4.141186e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 7.180886e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.388211e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 4.890761e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.233175e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.946156e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,12.0000) ) - { - x = 2*(s-3.000000)/9.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -5.947819e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.034157e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 6.878986e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.078603e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 6.990977e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.866215e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.897866e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.512252e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.073743e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.022621e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.501343e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -2.877243e-01*(s-1.200000e+01)-7.936839e+00; - return result; -} - - -static double jarquebera_jbtbl13(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,1.0000) ) - { - x = 2*(s-0.000000)/1.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -2.713276e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.557541e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -9.459092e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.044145e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.546132e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.002374e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.349456e-05, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -7.025669e-05, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.590242e-05, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,3.0000) ) - { - x = 2*(s-1.000000)/2.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -2.454383e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.467539e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.270774e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -8.075763e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.611647e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.990785e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 8.109212e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.135031e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.915919e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.522390e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.144701e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,13.0000) ) - { - x = 2*(s-3.000000)/10.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -5.736127e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.920809e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.175858e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.002049e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.158966e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.157781e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.762172e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.780347e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.193310e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.442421e-05, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.547756e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -2.799944e-01*(s-1.300000e+01)-7.566269e+00; - return result; -} - - -static double jarquebera_jbtbl14(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,1.0000) ) - { - x = 2*(s-0.000000)/1.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -2.698527e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.479081e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -8.640733e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -8.466899e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.469485e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.150009e-05, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.965975e-05, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.710210e-05, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.327808e-05, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,3.0000) ) - { - x = 2*(s-1.000000)/2.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -2.350359e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.421365e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.960468e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.149167e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.361109e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.976022e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.082700e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -8.563328e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.453123e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.917559e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.151067e-05, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,15.0000) ) - { - x = 2*(s-3.000000)/12.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -5.746892e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.010441e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.566146e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.129690e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.929724e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.524227e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.192933e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.254730e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.620685e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 7.289618e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.112350e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -2.590621e-01*(s-1.500000e+01)-7.632238e+00; - return result; -} - - -static double jarquebera_jbtbl15(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,2.0000) ) - { - x = 2*(s-0.000000)/2.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -1.043660e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.361653e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.009497e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 4.951784e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 4.377903e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.003253e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.271309e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,5.0000) ) - { - x = 2*(s-2.000000)/3.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -3.582778e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -8.349578e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 9.476514e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.717385e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.222591e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.635124e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.815993e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,17.0000) ) - { - x = 2*(s-5.000000)/12.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -6.115476e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.655936e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 8.404310e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.663794e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 8.868618e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.381447e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 9.444801e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.581503e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -9.468696e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.728509e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.206470e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -1.927937e-01*(s-1.700000e+01)-7.700983e+00; - return result; -} - - -static double jarquebera_jbtbl16(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,2.0000) ) - { - x = 2*(s-0.000000)/2.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -1.002570e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.298141e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.832803e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.877026e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.539436e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 8.439658e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.756911e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,5.0000) ) - { - x = 2*(s-2.000000)/3.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -3.486198e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -8.242944e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.020002e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.130531e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.512373e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -8.054876e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.556839e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,20.0000) ) - { - x = 2*(s-5.000000)/15.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -6.241608e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.832655e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.340545e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.361143e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.283219e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.484549e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.805968e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.057243e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.454439e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.177513e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.819209e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -2.391580e-01*(s-2.000000e+01)-7.963205e+00; - return result; -} - - -static double jarquebera_jbtbl17(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,3.0000) ) - { - x = 2*(s-0.000000)/3.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -1.566973e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.810330e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.840039e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.337294e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.383549e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.556515e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -8.656965e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.404569e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 6.447867e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,6.0000) ) - { - x = 2*(s-3.000000)/3.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -3.905684e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.222920e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 4.146667e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.809176e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.057028e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.211838e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.099683e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.161105e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.225465e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,24.0000) ) - { - x = 2*(s-6.000000)/18.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -6.594282e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.917838e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.455980e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.999589e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.604263e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.484445e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.819937e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.930390e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.771761e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.232581e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -7.029083e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -2.127771e-01*(s-2.400000e+01)-8.400197e+00; - return result; -} - - -static double jarquebera_jbtbl18(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,3.0000) ) - { - x = 2*(s-0.000000)/3.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -1.526802e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.762373e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.598890e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.189437e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.971721e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.823067e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.064501e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.014932e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.953513e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,6.0000) ) - { - x = 2*(s-3.000000)/3.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -3.818669e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.070918e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 4.277196e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.879817e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 6.887357e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.638451e-05, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.502800e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.165796e-05, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.034960e-05, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,20.0000) ) - { - x = 2*(s-6.000000)/14.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -6.010656e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.496296e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.002227e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.338250e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 4.137036e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.586202e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -9.736384e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.332251e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.877982e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.160963e-05, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.547247e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -1.684623e-01*(s-2.000000e+01)-7.428883e+00; - return result; -} - - -static double jarquebera_jbtbl19(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,3.0000) ) - { - x = 2*(s-0.000000)/3.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -1.490213e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.719633e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.459123e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.034878e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.113868e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.030922e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.054022e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 7.525623e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.277360e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,6.0000) ) - { - x = 2*(s-3.000000)/3.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -3.744750e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.977749e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 4.223716e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.363889e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.711774e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.557257e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 4.254794e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 9.034207e-05, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.498107e-05, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,20.0000) ) - { - x = 2*(s-6.000000)/14.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -5.872768e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.430689e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.136575e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.726627e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.421110e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.581510e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.559520e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.838208e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 8.428839e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -7.170682e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.006647e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -1.539373e-01*(s-2.000000e+01)-7.206941e+00; - return result; -} - - -static double jarquebera_jbtbl20(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,4.0000) ) - { - x = 2*(s-0.000000)/4.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -1.854794e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.948947e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.632184e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.139397e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.006237e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.810031e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.573620e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 9.951242e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.274092e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.464196e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 4.882139e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.575144e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.822804e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -7.061348e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.908404e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.978353e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,15.0000) ) - { - x = 2*(s-4.000000)/11.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -5.030989e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.327151e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.346404e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.840051e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 7.578551e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -9.813886e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.905973e-05, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.358489e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.450795e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.941157e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -7.432418e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.070537e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 9.375654e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.367378e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 9.890859e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 6.679782e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,25.0000) ) - { - x = 2*(s-15.000000)/10.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -7.015854e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -7.487737e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.244254e-02, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -1.318007e-01*(s-2.500000e+01)-7.742185e+00; - return result; -} - - -static double jarquebera_jbtbl30(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,4.0000) ) - { - x = 2*(s-0.000000)/4.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -1.630822e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.724298e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 7.872756e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.658268e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.573597e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.994157e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.994825e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 7.394303e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.785029e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.990264e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.037838e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 6.755546e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.774473e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.821395e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.392603e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.353313e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,15.0000) ) - { - x = 2*(s-4.000000)/11.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -4.539322e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.197018e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.396848e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.804293e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 6.867928e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.768758e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.211792e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 4.925799e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.046235e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -9.536469e-05, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.489642e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,25.0000) ) - { - x = 2*(s-15.000000)/10.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -6.263462e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.177316e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.590637e-02, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -1.028212e-01*(s-2.500000e+01)-6.855288e+00; - return result; -} - - -static double jarquebera_jbtbl50(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,4.0000) ) - { - x = 2*(s-0.000000)/4.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -1.436279e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.519711e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.148699e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.001204e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.207620e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.034778e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.220322e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.033260e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.588280e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.851653e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.287733e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,15.0000) ) - { - x = 2*(s-4.000000)/11.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -4.234645e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.189127e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.429738e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.058822e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 9.086776e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.445783e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.311671e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -7.261298e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 6.496987e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.605249e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 8.162282e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,25.0000) ) - { - x = 2*(s-15.000000)/10.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -5.921095e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.888603e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.080113e-02, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -9.313116e-02*(s-2.500000e+01)-6.479154e+00; - return result; -} - - -static double jarquebera_jbtbl65(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,4.0000) ) - { - x = 2*(s-0.000000)/4.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -1.360024e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.434631e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.514580e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 7.332038e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.158197e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.121233e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.051056e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,15.0000) ) - { - x = 2*(s-4.000000)/11.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -4.148601e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.214233e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.487977e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.424720e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.116715e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.043152e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.718149e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.313701e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.097305e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.181031e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.256975e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,25.0000) ) - { - x = 2*(s-15.000000)/10.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -5.858951e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.895179e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.933237e-02, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -9.443768e-02*(s-2.500000e+01)-6.419137e+00; - return result; -} - - -static double jarquebera_jbtbl100(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,4.0000) ) - { - x = 2*(s-0.000000)/4.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -1.257021e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.313418e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.628931e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 4.264287e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.518487e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.499826e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.836044e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,15.0000) ) - { - x = 2*(s-4.000000)/11.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -4.056508e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.279690e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.665746e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.290012e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.487632e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.704465e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.211669e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,25.0000) ) - { - x = 2*(s-15.000000)/10.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -5.866099e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.399767e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.498208e-02, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -1.080097e-01*(s-2.500000e+01)-6.481094e+00; - return result; -} - - -static double jarquebera_jbtbl130(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,4.0000) ) - { - x = 2*(s-0.000000)/4.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -1.207999e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.253864e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.618032e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.112729e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.210546e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.732602e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.410527e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,15.0000) ) - { - x = 2*(s-4.000000)/11.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -4.026324e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.331990e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.779129e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.674749e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.669077e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.679136e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 8.833221e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,25.0000) ) - { - x = 2*(s-15.000000)/10.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -5.893951e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.475304e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.116734e-02, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -1.045722e-01*(s-2.500000e+01)-6.510314e+00; - return result; -} - - -static double jarquebera_jbtbl200(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,4.0000) ) - { - x = 2*(s-0.000000)/4.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -1.146155e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.177398e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.297970e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.869745e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.717288e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.982108e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 6.427636e-05, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,15.0000) ) - { - x = 2*(s-4.000000)/11.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -4.034235e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.455006e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.942996e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.973795e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.418812e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.156778e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 4.896705e-05, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,25.0000) ) - { - x = 2*(s-15.000000)/10.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -6.086071e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -7.152176e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.725393e-02, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -1.132404e-01*(s-2.500000e+01)-6.764034e+00; - return result; -} - - -static double jarquebera_jbtbl301(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,4.0000) ) - { - x = 2*(s-0.000000)/4.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -1.104290e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.125800e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -9.595847e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.219666e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.502210e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.414543e-05, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 6.754115e-05, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,15.0000) ) - { - x = 2*(s-4.000000)/11.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -4.065955e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.582060e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.004472e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -4.709092e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.105779e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.197391e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -8.386780e-04, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,25.0000) ) - { - x = 2*(s-15.000000)/10.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -6.311384e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -7.918763e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.626584e-02, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -1.293626e-01*(s-2.500000e+01)-7.066995e+00; - return result; -} - - -static double jarquebera_jbtbl501(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,4.0000) ) - { - x = 2*(s-0.000000)/4.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -1.067426e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.079765e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -5.463005e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 6.875659e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,15.0000) ) - { - x = 2*(s-4.000000)/11.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -4.127574e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.740694e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.044502e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.746714e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 3.810594e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.197111e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,25.0000) ) - { - x = 2*(s-15.000000)/10.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -6.628194e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -8.846221e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 4.386405e-02, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -1.418332e-01*(s-2.500000e+01)-7.468952e+00; - return result; -} - - -static double jarquebera_jbtbl701(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,4.0000) ) - { - x = 2*(s-0.000000)/4.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -1.050999e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.059769e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -3.922680e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 4.847054e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,15.0000) ) - { - x = 2*(s-4.000000)/11.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -4.192182e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.860007e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.963942e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.838711e-02, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.893112e-04, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.159788e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,25.0000) ) - { - x = 2*(s-15.000000)/10.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -6.917851e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -9.817020e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.383727e-02, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -1.532706e-01*(s-2.500000e+01)-7.845715e+00; - return result; -} - - -static double jarquebera_jbtbl1401(double s, ae_state *_state) -{ - double x; - double tj; - double tj1; - double result; - - - result = (double)(0); - if( ae_fp_less_eq(s,4.0000) ) - { - x = 2*(s-0.000000)/4.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -1.026266e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.030061e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.259222e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 2.536254e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,15.0000) ) - { - x = 2*(s-4.000000)/11.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -4.329849e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -2.095443e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 1.759363e-01, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -7.751359e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -6.124368e-03, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.793114e-03, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - if( ae_fp_less_eq(s,25.0000) ) - { - x = 2*(s-15.000000)/10.000000-1; - tj = (double)(1); - tj1 = x; - jarquebera_jbcheb(x, -7.544330e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, -1.225382e+00, &tj, &tj1, &result, _state); - jarquebera_jbcheb(x, 5.392349e-02, &tj, &tj1, &result, _state); - if( ae_fp_greater(result,(double)(0)) ) - { - result = (double)(0); - } - return result; - } - result = -2.019375e-01*(s-2.500000e+01)-8.715788e+00; - return result; -} - - -static void jarquebera_jbcheb(double x, - double c, - double* tj, - double* tj1, - double* r, - ae_state *_state) -{ - double t; - - - *r = *r+c*(*tj); - t = 2*x*(*tj1)-(*tj); - *tj = *tj1; - *tj1 = t; -} - - -#endif -#if defined(AE_COMPILE_VARIANCETESTS) || !defined(AE_PARTIAL_BUILD) - - -/************************************************************************* -Two-sample F-test - -This test checks three hypotheses about dispersions of the given samples. -The following tests are performed: - * two-tailed test (null hypothesis - the dispersions are equal) - * left-tailed test (null hypothesis - the dispersion of the first - sample is greater than or equal to the dispersion of the second - sample). - * right-tailed test (null hypothesis - the dispersion of the first - sample is less than or equal to the dispersion of the second sample) - -The test is based on the following assumptions: - * the given samples have normal distributions - * the samples are independent. - -Input parameters: - X - sample 1. Array whose index goes from 0 to N-1. - N - sample size. - Y - sample 2. Array whose index goes from 0 to M-1. - M - sample size. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - - -- ALGLIB -- - Copyright 19.09.2006 by Bochkanov Sergey -*************************************************************************/ -void ftest(/* Real */ ae_vector* x, - ae_int_t n, - /* Real */ ae_vector* y, - ae_int_t m, - double* bothtails, - double* lefttail, - double* righttail, - ae_state *_state) -{ - ae_int_t i; - double xmean; - double ymean; - double xvar; - double yvar; - ae_int_t df1; - ae_int_t df2; - double stat; - - *bothtails = 0; - *lefttail = 0; - *righttail = 0; - - if( n<=2||m<=2 ) - { - *bothtails = 1.0; - *lefttail = 1.0; - *righttail = 1.0; - return; - } - - /* - * Mean - */ - xmean = (double)(0); - for(i=0; i<=n-1; i++) - { - xmean = xmean+x->ptr.p_double[i]; - } - xmean = xmean/n; - ymean = (double)(0); - for(i=0; i<=m-1; i++) - { - ymean = ymean+y->ptr.p_double[i]; - } - ymean = ymean/m; - - /* - * Variance (using corrected two-pass algorithm) - */ - xvar = (double)(0); - for(i=0; i<=n-1; i++) - { - xvar = xvar+ae_sqr(x->ptr.p_double[i]-xmean, _state); - } - xvar = xvar/(n-1); - yvar = (double)(0); - for(i=0; i<=m-1; i++) - { - yvar = yvar+ae_sqr(y->ptr.p_double[i]-ymean, _state); - } - yvar = yvar/(m-1); - if( ae_fp_eq(xvar,(double)(0))||ae_fp_eq(yvar,(double)(0)) ) - { - *bothtails = 1.0; - *lefttail = 1.0; - *righttail = 1.0; - return; - } - - /* - * Statistic - */ - df1 = n-1; - df2 = m-1; - stat = ae_minreal(xvar/yvar, yvar/xvar, _state); - *bothtails = 1-(fdistribution(df1, df2, 1/stat, _state)-fdistribution(df1, df2, stat, _state)); - *lefttail = fdistribution(df1, df2, xvar/yvar, _state); - *righttail = 1-(*lefttail); -} - - -/************************************************************************* -One-sample chi-square test - -This test checks three hypotheses about the dispersion of the given sample -The following tests are performed: - * two-tailed test (null hypothesis - the dispersion equals the given - number) - * left-tailed test (null hypothesis - the dispersion is greater than - or equal to the given number) - * right-tailed test (null hypothesis - dispersion is less than or - equal to the given number). - -Test is based on the following assumptions: - * the given sample has a normal distribution. - -Input parameters: - X - sample 1. Array whose index goes from 0 to N-1. - N - size of the sample. - Variance - dispersion value to compare with. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - - -- ALGLIB -- - Copyright 19.09.2006 by Bochkanov Sergey -*************************************************************************/ -void onesamplevariancetest(/* Real */ ae_vector* x, - ae_int_t n, - double variance, - double* bothtails, - double* lefttail, - double* righttail, - ae_state *_state) -{ - ae_int_t i; - double xmean; - double xvar; - double s; - double stat; - - *bothtails = 0; - *lefttail = 0; - *righttail = 0; - - if( n<=1 ) - { - *bothtails = 1.0; - *lefttail = 1.0; - *righttail = 1.0; - return; - } - - /* - * Mean - */ - xmean = (double)(0); - for(i=0; i<=n-1; i++) - { - xmean = xmean+x->ptr.p_double[i]; - } - xmean = xmean/n; - - /* - * Variance - */ - xvar = (double)(0); - for(i=0; i<=n-1; i++) - { - xvar = xvar+ae_sqr(x->ptr.p_double[i]-xmean, _state); - } - xvar = xvar/(n-1); - if( ae_fp_eq(xvar,(double)(0)) ) - { - *bothtails = 1.0; - *lefttail = 1.0; - *righttail = 1.0; - return; - } - - /* - * Statistic - */ - stat = (n-1)*xvar/variance; - s = chisquaredistribution((double)(n-1), stat, _state); - *bothtails = 2*ae_minreal(s, 1-s, _state); - *lefttail = s; - *righttail = 1-(*lefttail); -} - - -#endif - -} - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/statistics.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/statistics.h deleted file mode 100644 index 3ab5f8b..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/statistics.h +++ /dev/null @@ -1,1359 +0,0 @@ -/************************************************************************* -ALGLIB 3.17.0 (source code generated 2020-12-27) -Copyright (c) Sergey Bochkanov (ALGLIB project). - ->>> SOURCE LICENSE >>> -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation (www.fsf.org); either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -A copy of the GNU General Public License is available at -http://www.fsf.org/licensing/licenses ->>> END OF LICENSE >>> -*************************************************************************/ -#ifndef _statistics_pkg_h -#define _statistics_pkg_h -#include "ap.h" -#include "alglibinternal.h" -#include "linalg.h" -#include "specialfunctions.h" -#include "alglibmisc.h" - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (DATATYPES) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_BASESTAT) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_WSR) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_STEST) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_CORRELATIONTESTS) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_STUDENTTTESTS) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_MANNWHITNEYU) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_JARQUEBERA) || !defined(AE_PARTIAL_BUILD) -#endif -#if defined(AE_COMPILE_VARIANCETESTS) || !defined(AE_PARTIAL_BUILD) -#endif - -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS C++ INTERFACE -// -///////////////////////////////////////////////////////////////////////// -namespace alglib -{ - -#if defined(AE_COMPILE_BASESTAT) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_WSR) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_STEST) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_CORRELATIONTESTS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_STUDENTTTESTS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_MANNWHITNEYU) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_JARQUEBERA) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_VARIANCETESTS) || !defined(AE_PARTIAL_BUILD) - -#endif - -#if defined(AE_COMPILE_BASESTAT) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Calculation of the distribution moments: mean, variance, skewness, kurtosis. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -OUTPUT PARAMETERS - Mean - mean. - Variance- variance. - Skewness- skewness (if variance<>0; zero otherwise). - Kurtosis- kurtosis (if variance<>0; zero otherwise). - -NOTE: variance is calculated by dividing sum of squares by N-1, not N. - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -void samplemoments(const real_1d_array &x, const ae_int_t n, double &mean, double &variance, double &skewness, double &kurtosis, const xparams _xparams = alglib::xdefault); -void samplemoments(const real_1d_array &x, double &mean, double &variance, double &skewness, double &kurtosis, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Calculation of the mean. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -NOTE: - -This function return result which calculated by 'SampleMoments' function -and stored at 'Mean' variable. - - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -double samplemean(const real_1d_array &x, const ae_int_t n, const xparams _xparams = alglib::xdefault); -double samplemean(const real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Calculation of the variance. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -NOTE: - -This function return result which calculated by 'SampleMoments' function -and stored at 'Variance' variable. - - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -double samplevariance(const real_1d_array &x, const ae_int_t n, const xparams _xparams = alglib::xdefault); -double samplevariance(const real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Calculation of the skewness. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -NOTE: - -This function return result which calculated by 'SampleMoments' function -and stored at 'Skewness' variable. - - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -double sampleskewness(const real_1d_array &x, const ae_int_t n, const xparams _xparams = alglib::xdefault); -double sampleskewness(const real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Calculation of the kurtosis. - -INPUT PARAMETERS: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -NOTE: - -This function return result which calculated by 'SampleMoments' function -and stored at 'Kurtosis' variable. - - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -double samplekurtosis(const real_1d_array &x, const ae_int_t n, const xparams _xparams = alglib::xdefault); -double samplekurtosis(const real_1d_array &x, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -ADev - -Input parameters: - X - sample - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -Output parameters: - ADev- ADev - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -void sampleadev(const real_1d_array &x, const ae_int_t n, double &adev, const xparams _xparams = alglib::xdefault); -void sampleadev(const real_1d_array &x, double &adev, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Median calculation. - -Input parameters: - X - sample (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - -Output parameters: - Median - - -- ALGLIB -- - Copyright 06.09.2006 by Bochkanov Sergey -*************************************************************************/ -void samplemedian(const real_1d_array &x, const ae_int_t n, double &median, const xparams _xparams = alglib::xdefault); -void samplemedian(const real_1d_array &x, double &median, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Percentile calculation. - -Input parameters: - X - sample (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only leading N elements of X are processed - * if not given, automatically determined from size of X - P - percentile (0<=P<=1) - -Output parameters: - V - percentile - - -- ALGLIB -- - Copyright 01.03.2008 by Bochkanov Sergey -*************************************************************************/ -void samplepercentile(const real_1d_array &x, const ae_int_t n, const double p, double &v, const xparams _xparams = alglib::xdefault); -void samplepercentile(const real_1d_array &x, const double p, double &v, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -2-sample covariance - -Input parameters: - X - sample 1 (array indexes: [0..N-1]) - Y - sample 2 (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only N leading elements of X/Y are processed - * if not given, automatically determined from input sizes - -Result: - covariance (zero for N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -double cov2(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const xparams _xparams = alglib::xdefault); -double cov2(const real_1d_array &x, const real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Pearson product-moment correlation coefficient - -Input parameters: - X - sample 1 (array indexes: [0..N-1]) - Y - sample 2 (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only N leading elements of X/Y are processed - * if not given, automatically determined from input sizes - -Result: - Pearson product-moment correlation coefficient - (zero for N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -double pearsoncorr2(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const xparams _xparams = alglib::xdefault); -double pearsoncorr2(const real_1d_array &x, const real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Spearman's rank correlation coefficient - -Input parameters: - X - sample 1 (array indexes: [0..N-1]) - Y - sample 2 (array indexes: [0..N-1]) - N - N>=0, sample size: - * if given, only N leading elements of X/Y are processed - * if not given, automatically determined from input sizes - -Result: - Spearman's rank correlation coefficient - (zero for N=0 or N=1) - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -double spearmancorr2(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const xparams _xparams = alglib::xdefault); -double spearmancorr2(const real_1d_array &x, const real_1d_array &y, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Covariance matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X are used - * if not given, automatically determined from input size - M - M>0, number of variables: - * if given, only leading M columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M,M], covariance matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -void covm(const real_2d_array &x, const ae_int_t n, const ae_int_t m, real_2d_array &c, const xparams _xparams = alglib::xdefault); -void covm(const real_2d_array &x, real_2d_array &c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Pearson product-moment correlation matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X are used - * if not given, automatically determined from input size - M - M>0, number of variables: - * if given, only leading M columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M,M], correlation matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -void pearsoncorrm(const real_2d_array &x, const ae_int_t n, const ae_int_t m, real_2d_array &c, const xparams _xparams = alglib::xdefault); -void pearsoncorrm(const real_2d_array &x, real_2d_array &c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Spearman's rank correlation matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X are used - * if not given, automatically determined from input size - M - M>0, number of variables: - * if given, only leading M columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M,M], correlation matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -void spearmancorrm(const real_2d_array &x, const ae_int_t n, const ae_int_t m, real_2d_array &c, const xparams _xparams = alglib::xdefault); -void spearmancorrm(const real_2d_array &x, real_2d_array &c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Cross-covariance matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M1], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - Y - array[N,M2], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X/Y are used - * if not given, automatically determined from input sizes - M1 - M1>0, number of variables in X: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - M2 - M2>0, number of variables in Y: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M1,M2], cross-covariance matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -void covm2(const real_2d_array &x, const real_2d_array &y, const ae_int_t n, const ae_int_t m1, const ae_int_t m2, real_2d_array &c, const xparams _xparams = alglib::xdefault); -void covm2(const real_2d_array &x, const real_2d_array &y, real_2d_array &c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Pearson product-moment cross-correlation matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M1], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - Y - array[N,M2], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X/Y are used - * if not given, automatically determined from input sizes - M1 - M1>0, number of variables in X: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - M2 - M2>0, number of variables in Y: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M1,M2], cross-correlation matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -void pearsoncorrm2(const real_2d_array &x, const real_2d_array &y, const ae_int_t n, const ae_int_t m1, const ae_int_t m2, real_2d_array &c, const xparams _xparams = alglib::xdefault); -void pearsoncorrm2(const real_2d_array &x, const real_2d_array &y, real_2d_array &c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Spearman's rank cross-correlation matrix - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! * hardware vendor (Intel) implementations of linear algebra primitives - ! (C++ and C# versions, x86/x64 platform) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - X - array[N,M1], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - Y - array[N,M2], sample matrix: - * J-th column corresponds to J-th variable - * I-th row corresponds to I-th observation - N - N>=0, number of observations: - * if given, only leading N rows of X/Y are used - * if not given, automatically determined from input sizes - M1 - M1>0, number of variables in X: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - M2 - M2>0, number of variables in Y: - * if given, only leading M1 columns of X are used - * if not given, automatically determined from input size - -OUTPUT PARAMETERS: - C - array[M1,M2], cross-correlation matrix (zero if N=0 or N=1) - - -- ALGLIB -- - Copyright 28.10.2010 by Bochkanov Sergey -*************************************************************************/ -void spearmancorrm2(const real_2d_array &x, const real_2d_array &y, const ae_int_t n, const ae_int_t m1, const ae_int_t m2, real_2d_array &c, const xparams _xparams = alglib::xdefault); -void spearmancorrm2(const real_2d_array &x, const real_2d_array &y, real_2d_array &c, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function replaces data in XY by their ranks: -* XY is processed row-by-row -* rows are processed separately -* tied data are correctly handled (tied ranks are calculated) -* ranking starts from 0, ends at NFeatures-1 -* sum of within-row values is equal to (NFeatures-1)*NFeatures/2 - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - array[NPoints,NFeatures], dataset - NPoints - number of points - NFeatures- number of features - -OUTPUT PARAMETERS: - XY - data are replaced by their within-row ranks; - ranking starts from 0, ends at NFeatures-1 - - -- ALGLIB -- - Copyright 18.04.2013 by Bochkanov Sergey -*************************************************************************/ -void rankdata(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nfeatures, const xparams _xparams = alglib::xdefault); -void rankdata(real_2d_array &xy, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -This function replaces data in XY by their CENTERED ranks: -* XY is processed row-by-row -* rows are processed separately -* tied data are correctly handled (tied ranks are calculated) -* centered ranks are just usual ranks, but centered in such way that sum - of within-row values is equal to 0.0. -* centering is performed by subtracting mean from each row, i.e it changes - mean value, but does NOT change higher moments - - ! COMMERCIAL EDITION OF ALGLIB: - ! - ! Commercial Edition of ALGLIB includes following important improvements - ! of this function: - ! * high-performance native backend with same C# interface (C# version) - ! * multithreading support (C++ and C# versions) - ! - ! We recommend you to read 'Working with commercial version' section of - ! ALGLIB Reference Manual in order to find out how to use performance- - ! related features provided by commercial edition of ALGLIB. - -INPUT PARAMETERS: - XY - array[NPoints,NFeatures], dataset - NPoints - number of points - NFeatures- number of features - -OUTPUT PARAMETERS: - XY - data are replaced by their within-row ranks; - ranking starts from 0, ends at NFeatures-1 - - -- ALGLIB -- - Copyright 18.04.2013 by Bochkanov Sergey -*************************************************************************/ -void rankdatacentered(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nfeatures, const xparams _xparams = alglib::xdefault); -void rankdatacentered(real_2d_array &xy, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Obsolete function, we recommend to use PearsonCorr2(). - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -double pearsoncorrelation(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Obsolete function, we recommend to use SpearmanCorr2(). - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -double spearmanrankcorrelation(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_WSR) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Wilcoxon signed-rank test - -This test checks three hypotheses about the median of the given sample. -The following tests are performed: - * two-tailed test (null hypothesis - the median is equal to the given - value) - * left-tailed test (null hypothesis - the median is greater than or - equal to the given value) - * right-tailed test (null hypothesis - the median is less than or - equal to the given value) - -Requirements: - * the scale of measurement should be ordinal, interval or ratio (i.e. - the test could not be applied to nominal variables). - * the distribution should be continuous and symmetric relative to its - median. - * number of distinct values in the X array should be greater than 4 - -The test is non-parametric and doesn't require distribution X to be normal - -Input parameters: - X - sample. Array whose index goes from 0 to N-1. - N - size of the sample. - Median - assumed median value. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -To calculate p-values, special approximation is used. This method lets us -calculate p-values with two decimal places in interval [0.0001, 1]. - -"Two decimal places" does not sound very impressive, but in practice the -relative error of less than 1% is enough to make a decision. - -There is no approximation outside the [0.0001, 1] interval. Therefore, if -the significance level outlies this interval, the test returns 0.0001. - - -- ALGLIB -- - Copyright 08.09.2006 by Bochkanov Sergey -*************************************************************************/ -void wilcoxonsignedranktest(const real_1d_array &x, const ae_int_t n, const double e, double &bothtails, double &lefttail, double &righttail, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_STEST) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Sign test - -This test checks three hypotheses about the median of the given sample. -The following tests are performed: - * two-tailed test (null hypothesis - the median is equal to the given - value) - * left-tailed test (null hypothesis - the median is greater than or - equal to the given value) - * right-tailed test (null hypothesis - the median is less than or - equal to the given value) - -Requirements: - * the scale of measurement should be ordinal, interval or ratio (i.e. - the test could not be applied to nominal variables). - -The test is non-parametric and doesn't require distribution X to be normal - -Input parameters: - X - sample. Array whose index goes from 0 to N-1. - N - size of the sample. - Median - assumed median value. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -While calculating p-values high-precision binomial distribution -approximation is used, so significance levels have about 15 exact digits. - - -- ALGLIB -- - Copyright 08.09.2006 by Bochkanov Sergey -*************************************************************************/ -void onesamplesigntest(const real_1d_array &x, const ae_int_t n, const double median, double &bothtails, double &lefttail, double &righttail, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_CORRELATIONTESTS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Pearson's correlation coefficient significance test - -This test checks hypotheses about whether X and Y are samples of two -continuous distributions having zero correlation or whether their -correlation is non-zero. - -The following tests are performed: - * two-tailed test (null hypothesis - X and Y have zero correlation) - * left-tailed test (null hypothesis - the correlation coefficient is - greater than or equal to 0) - * right-tailed test (null hypothesis - the correlation coefficient is - less than or equal to 0). - -Requirements: - * the number of elements in each sample is not less than 5 - * normality of distributions of X and Y. - -Input parameters: - R - Pearson's correlation coefficient for X and Y - N - number of elements in samples, N>=5. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -void pearsoncorrelationsignificance(const double r, const ae_int_t n, double &bothtails, double &lefttail, double &righttail, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Spearman's rank correlation coefficient significance test - -This test checks hypotheses about whether X and Y are samples of two -continuous distributions having zero correlation or whether their -correlation is non-zero. - -The following tests are performed: - * two-tailed test (null hypothesis - X and Y have zero correlation) - * left-tailed test (null hypothesis - the correlation coefficient is - greater than or equal to 0) - * right-tailed test (null hypothesis - the correlation coefficient is - less than or equal to 0). - -Requirements: - * the number of elements in each sample is not less than 5. - -The test is non-parametric and doesn't require distributions X and Y to be -normal. - -Input parameters: - R - Spearman's rank correlation coefficient for X and Y - N - number of elements in samples, N>=5. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -void spearmanrankcorrelationsignificance(const double r, const ae_int_t n, double &bothtails, double &lefttail, double &righttail, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_STUDENTTTESTS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -One-sample t-test - -This test checks three hypotheses about the mean of the given sample. The -following tests are performed: - * two-tailed test (null hypothesis - the mean is equal to the given - value) - * left-tailed test (null hypothesis - the mean is greater than or - equal to the given value) - * right-tailed test (null hypothesis - the mean is less than or equal - to the given value). - -The test is based on the assumption that a given sample has a normal -distribution and an unknown dispersion. If the distribution sharply -differs from normal, the test will work incorrectly. - -INPUT PARAMETERS: - X - sample. Array whose index goes from 0 to N-1. - N - size of sample, N>=0 - Mean - assumed value of the mean. - -OUTPUT PARAMETERS: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -NOTE: this function correctly handles degenerate cases: - * when N=0, all p-values are set to 1.0 - * when variance of X[] is exactly zero, p-values are set - to 1.0 or 0.0, depending on difference between sample mean and - value of mean being tested. - - - -- ALGLIB -- - Copyright 08.09.2006 by Bochkanov Sergey -*************************************************************************/ -void studentttest1(const real_1d_array &x, const ae_int_t n, const double mean, double &bothtails, double &lefttail, double &righttail, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Two-sample pooled test - -This test checks three hypotheses about the mean of the given samples. The -following tests are performed: - * two-tailed test (null hypothesis - the means are equal) - * left-tailed test (null hypothesis - the mean of the first sample is - greater than or equal to the mean of the second sample) - * right-tailed test (null hypothesis - the mean of the first sample is - less than or equal to the mean of the second sample). - -Test is based on the following assumptions: - * given samples have normal distributions - * dispersions are equal - * samples are independent. - -Input parameters: - X - sample 1. Array whose index goes from 0 to N-1. - N - size of sample. - Y - sample 2. Array whose index goes from 0 to M-1. - M - size of sample. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -NOTE: this function correctly handles degenerate cases: - * when N=0 or M=0, all p-values are set to 1.0 - * when both samples has exactly zero variance, p-values are set - to 1.0 or 0.0, depending on difference between means. - - -- ALGLIB -- - Copyright 18.09.2006 by Bochkanov Sergey -*************************************************************************/ -void studentttest2(const real_1d_array &x, const ae_int_t n, const real_1d_array &y, const ae_int_t m, double &bothtails, double &lefttail, double &righttail, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -Two-sample unpooled test - -This test checks three hypotheses about the mean of the given samples. The -following tests are performed: - * two-tailed test (null hypothesis - the means are equal) - * left-tailed test (null hypothesis - the mean of the first sample is - greater than or equal to the mean of the second sample) - * right-tailed test (null hypothesis - the mean of the first sample is - less than or equal to the mean of the second sample). - -Test is based on the following assumptions: - * given samples have normal distributions - * samples are independent. -Equality of variances is NOT required. - -Input parameters: - X - sample 1. Array whose index goes from 0 to N-1. - N - size of the sample. - Y - sample 2. Array whose index goes from 0 to M-1. - M - size of the sample. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -NOTE: this function correctly handles degenerate cases: - * when N=0 or M=0, all p-values are set to 1.0 - * when both samples has zero variance, p-values are set - to 1.0 or 0.0, depending on difference between means. - * when only one sample has zero variance, test reduces to 1-sample - version. - - -- ALGLIB -- - Copyright 18.09.2006 by Bochkanov Sergey -*************************************************************************/ -void unequalvariancettest(const real_1d_array &x, const ae_int_t n, const real_1d_array &y, const ae_int_t m, double &bothtails, double &lefttail, double &righttail, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_MANNWHITNEYU) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Mann-Whitney U-test - -This test checks hypotheses about whether X and Y are samples of two -continuous distributions of the same shape and same median or whether -their medians are different. - -The following tests are performed: - * two-tailed test (null hypothesis - the medians are equal) - * left-tailed test (null hypothesis - the median of the first sample - is greater than or equal to the median of the second sample) - * right-tailed test (null hypothesis - the median of the first sample - is less than or equal to the median of the second sample). - -Requirements: - * the samples are independent - * X and Y are continuous distributions (or discrete distributions well- - approximating continuous distributions) - * distributions of X and Y have the same shape. The only possible - difference is their position (i.e. the value of the median) - * the number of elements in each sample is not less than 5 - * the scale of measurement should be ordinal, interval or ratio (i.e. - the test could not be applied to nominal variables). - -The test is non-parametric and doesn't require distributions to be normal. - -Input parameters: - X - sample 1. Array whose index goes from 0 to N-1. - N - size of the sample. N>=5 - Y - sample 2. Array whose index goes from 0 to M-1. - M - size of the sample. M>=5 - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - -To calculate p-values, special approximation is used. This method lets us -calculate p-values with satisfactory accuracy in interval [0.0001, 1]. -There is no approximation outside the [0.0001, 1] interval. Therefore, if -the significance level outlies this interval, the test returns 0.0001. - -Relative precision of approximation of p-value: - -N M Max.err. Rms.err. -5..10 N..10 1.4e-02 6.0e-04 -5..10 N..100 2.2e-02 5.3e-06 -10..15 N..15 1.0e-02 3.2e-04 -10..15 N..100 1.0e-02 2.2e-05 -15..100 N..100 6.1e-03 2.7e-06 - -For N,M>100 accuracy checks weren't put into practice, but taking into -account characteristics of asymptotic approximation used, precision should -not be sharply different from the values for interval [5, 100]. - -NOTE: P-value approximation was optimized for 0.0001<=p<=0.2500. Thus, - P's outside of this interval are enforced to these bounds. Say, you - may quite often get P equal to exactly 0.25 or 0.0001. - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -void mannwhitneyutest(const real_1d_array &x, const ae_int_t n, const real_1d_array &y, const ae_int_t m, double &bothtails, double &lefttail, double &righttail, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_JARQUEBERA) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Jarque-Bera test - -This test checks hypotheses about the fact that a given sample X is a -sample of normal random variable. - -Requirements: - * the number of elements in the sample is not less than 5. - -Input parameters: - X - sample. Array whose index goes from 0 to N-1. - N - size of the sample. N>=5 - -Output parameters: - P - p-value for the test - -Accuracy of the approximation used (5<=N<=1951): - -p-value relative error (5<=N<=1951) -[1, 0.1] < 1% -[0.1, 0.01] < 2% -[0.01, 0.001] < 6% -[0.001, 0] wasn't measured - -For N>1951 accuracy wasn't measured but it shouldn't be sharply different -from table values. - - -- ALGLIB -- - Copyright 09.04.2007 by Bochkanov Sergey -*************************************************************************/ -void jarqueberatest(const real_1d_array &x, const ae_int_t n, double &p, const xparams _xparams = alglib::xdefault); -#endif - -#if defined(AE_COMPILE_VARIANCETESTS) || !defined(AE_PARTIAL_BUILD) -/************************************************************************* -Two-sample F-test - -This test checks three hypotheses about dispersions of the given samples. -The following tests are performed: - * two-tailed test (null hypothesis - the dispersions are equal) - * left-tailed test (null hypothesis - the dispersion of the first - sample is greater than or equal to the dispersion of the second - sample). - * right-tailed test (null hypothesis - the dispersion of the first - sample is less than or equal to the dispersion of the second sample) - -The test is based on the following assumptions: - * the given samples have normal distributions - * the samples are independent. - -Input parameters: - X - sample 1. Array whose index goes from 0 to N-1. - N - sample size. - Y - sample 2. Array whose index goes from 0 to M-1. - M - sample size. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - - -- ALGLIB -- - Copyright 19.09.2006 by Bochkanov Sergey -*************************************************************************/ -void ftest(const real_1d_array &x, const ae_int_t n, const real_1d_array &y, const ae_int_t m, double &bothtails, double &lefttail, double &righttail, const xparams _xparams = alglib::xdefault); - - -/************************************************************************* -One-sample chi-square test - -This test checks three hypotheses about the dispersion of the given sample -The following tests are performed: - * two-tailed test (null hypothesis - the dispersion equals the given - number) - * left-tailed test (null hypothesis - the dispersion is greater than - or equal to the given number) - * right-tailed test (null hypothesis - dispersion is less than or - equal to the given number). - -Test is based on the following assumptions: - * the given sample has a normal distribution. - -Input parameters: - X - sample 1. Array whose index goes from 0 to N-1. - N - size of the sample. - Variance - dispersion value to compare with. - -Output parameters: - BothTails - p-value for two-tailed test. - If BothTails is less than the given significance level - the null hypothesis is rejected. - LeftTail - p-value for left-tailed test. - If LeftTail is less than the given significance level, - the null hypothesis is rejected. - RightTail - p-value for right-tailed test. - If RightTail is less than the given significance level - the null hypothesis is rejected. - - -- ALGLIB -- - Copyright 19.09.2006 by Bochkanov Sergey -*************************************************************************/ -void onesamplevariancetest(const real_1d_array &x, const ae_int_t n, const double variance, double &bothtails, double &lefttail, double &righttail, const xparams _xparams = alglib::xdefault); -#endif -} - -///////////////////////////////////////////////////////////////////////// -// -// THIS SECTION CONTAINS COMPUTATIONAL CORE DECLARATIONS (FUNCTIONS) -// -///////////////////////////////////////////////////////////////////////// -namespace alglib_impl -{ -#if defined(AE_COMPILE_BASESTAT) || !defined(AE_PARTIAL_BUILD) -void samplemoments(/* Real */ ae_vector* x, - ae_int_t n, - double* mean, - double* variance, - double* skewness, - double* kurtosis, - ae_state *_state); -double samplemean(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state); -double samplevariance(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state); -double sampleskewness(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state); -double samplekurtosis(/* Real */ ae_vector* x, - ae_int_t n, - ae_state *_state); -void sampleadev(/* Real */ ae_vector* x, - ae_int_t n, - double* adev, - ae_state *_state); -void samplemedian(/* Real */ ae_vector* x, - ae_int_t n, - double* median, - ae_state *_state); -void samplepercentile(/* Real */ ae_vector* x, - ae_int_t n, - double p, - double* v, - ae_state *_state); -double cov2(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_state *_state); -double pearsoncorr2(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_state *_state); -double spearmancorr2(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_state *_state); -void covm(/* Real */ ae_matrix* x, - ae_int_t n, - ae_int_t m, - /* Real */ ae_matrix* c, - ae_state *_state); -void pearsoncorrm(/* Real */ ae_matrix* x, - ae_int_t n, - ae_int_t m, - /* Real */ ae_matrix* c, - ae_state *_state); -void spearmancorrm(/* Real */ ae_matrix* x, - ae_int_t n, - ae_int_t m, - /* Real */ ae_matrix* c, - ae_state *_state); -void covm2(/* Real */ ae_matrix* x, - /* Real */ ae_matrix* y, - ae_int_t n, - ae_int_t m1, - ae_int_t m2, - /* Real */ ae_matrix* c, - ae_state *_state); -void pearsoncorrm2(/* Real */ ae_matrix* x, - /* Real */ ae_matrix* y, - ae_int_t n, - ae_int_t m1, - ae_int_t m2, - /* Real */ ae_matrix* c, - ae_state *_state); -void spearmancorrm2(/* Real */ ae_matrix* x, - /* Real */ ae_matrix* y, - ae_int_t n, - ae_int_t m1, - ae_int_t m2, - /* Real */ ae_matrix* c, - ae_state *_state); -void rankdata(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nfeatures, - ae_state *_state); -ae_bool _trypexec_rankdata(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nfeatures, ae_state *_state); -void rankdatacentered(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nfeatures, - ae_state *_state); -ae_bool _trypexec_rankdatacentered(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nfeatures, ae_state *_state); -double pearsoncorrelation(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_state *_state); -double spearmanrankcorrelation(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_state *_state); -#endif -#if defined(AE_COMPILE_WSR) || !defined(AE_PARTIAL_BUILD) -void wilcoxonsignedranktest(/* Real */ ae_vector* x, - ae_int_t n, - double e, - double* bothtails, - double* lefttail, - double* righttail, - ae_state *_state); -#endif -#if defined(AE_COMPILE_STEST) || !defined(AE_PARTIAL_BUILD) -void onesamplesigntest(/* Real */ ae_vector* x, - ae_int_t n, - double median, - double* bothtails, - double* lefttail, - double* righttail, - ae_state *_state); -#endif -#if defined(AE_COMPILE_CORRELATIONTESTS) || !defined(AE_PARTIAL_BUILD) -void pearsoncorrelationsignificance(double r, - ae_int_t n, - double* bothtails, - double* lefttail, - double* righttail, - ae_state *_state); -void spearmanrankcorrelationsignificance(double r, - ae_int_t n, - double* bothtails, - double* lefttail, - double* righttail, - ae_state *_state); -#endif -#if defined(AE_COMPILE_STUDENTTTESTS) || !defined(AE_PARTIAL_BUILD) -void studentttest1(/* Real */ ae_vector* x, - ae_int_t n, - double mean, - double* bothtails, - double* lefttail, - double* righttail, - ae_state *_state); -void studentttest2(/* Real */ ae_vector* x, - ae_int_t n, - /* Real */ ae_vector* y, - ae_int_t m, - double* bothtails, - double* lefttail, - double* righttail, - ae_state *_state); -void unequalvariancettest(/* Real */ ae_vector* x, - ae_int_t n, - /* Real */ ae_vector* y, - ae_int_t m, - double* bothtails, - double* lefttail, - double* righttail, - ae_state *_state); -#endif -#if defined(AE_COMPILE_MANNWHITNEYU) || !defined(AE_PARTIAL_BUILD) -void mannwhitneyutest(/* Real */ ae_vector* x, - ae_int_t n, - /* Real */ ae_vector* y, - ae_int_t m, - double* bothtails, - double* lefttail, - double* righttail, - ae_state *_state); -#endif -#if defined(AE_COMPILE_JARQUEBERA) || !defined(AE_PARTIAL_BUILD) -void jarqueberatest(/* Real */ ae_vector* x, - ae_int_t n, - double* p, - ae_state *_state); -#endif -#if defined(AE_COMPILE_VARIANCETESTS) || !defined(AE_PARTIAL_BUILD) -void ftest(/* Real */ ae_vector* x, - ae_int_t n, - /* Real */ ae_vector* y, - ae_int_t m, - double* bothtails, - double* lefttail, - double* righttail, - ae_state *_state); -void onesamplevariancetest(/* Real */ ae_vector* x, - ae_int_t n, - double variance, - double* bothtails, - double* lefttail, - double* righttail, - ae_state *_state); -#endif - -} -#endif - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/stdafx.h b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/stdafx.h deleted file mode 100644 index 139597f..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/src/stdafx.h +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/tests/test_c.cpp b/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/tests/test_c.cpp deleted file mode 100644 index 8bfae65..0000000 --- a/bioneuralnet/clustering/hybrid_clustering/correlated-louvain/vendor/source/alglib/tests/test_c.cpp +++ /dev/null @@ -1,131052 +0,0 @@ -#include -#include -#include "ap.h" -// disable some irrelevant warnings -#if (AE_COMPILER==AE_MSVC) && !defined(AE_ALL_WARNINGS) -#pragma warning(disable:4100) -#pragma warning(disable:4127) -#pragma warning(disable:4611) -#pragma warning(disable:4702) -#pragma warning(disable:4996) -#endif -#include "alglibinternal.h" -#include "alglibmisc.h" -#include "diffequations.h" -#include "linalg.h" -#include "optimization.h" -#include "solvers.h" -#include "statistics.h" -#include "dataanalysis.h" -#include "specialfunctions.h" -#include "integration.h" -#include "fasttransforms.h" -#include "interpolation.h" - -using namespace alglib_impl; - - - - - - -/************************************************************************* -Testing tag sort -*************************************************************************/ -ae_bool testtsort(ae_bool silent, ae_state *_state); -ae_bool _pexec_testtsort(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Testing Nearest Neighbor Search -*************************************************************************/ -ae_bool testnearestneighbor(ae_bool silent, ae_state *_state); -ae_bool _pexec_testnearestneighbor(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testhqrnd(ae_bool silent, ae_state *_state); -ae_bool _pexec_testhqrnd(ae_bool silent, ae_state *_state); - - -/************************************************************************* -Function for test HQRNDContinuous function -*************************************************************************/ -ae_bool hqrndcontinuoustest(ae_bool silent, ae_state *_state); - - -/************************************************************************* -Function for test HQRNDContinuous function -*************************************************************************/ -ae_bool hqrnddiscretetest(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testodesolver(ae_bool silent, ae_state *_state); -ae_bool _pexec_testodesolver(ae_bool silent, ae_state *_state); - - - - - -typedef struct -{ - ae_int_t n; - ae_int_t m; - ae_int_t matkind; - ae_int_t triangle; - ae_matrix bufa; - hqrndstate rs; - rcommstate rcs; -} sparsegenerator; - - - - - -ae_bool testsparse(ae_bool silent, ae_state *_state); -ae_bool _pexec_testsparse(ae_bool silent, ae_state *_state); - - -/************************************************************************* -Function for testing basic SKS functional. -Returns True on errors, False on success. - - -- ALGLIB PROJECT -- - Copyright 16.01.1014 by Bochkanov Sergey -*************************************************************************/ -ae_bool skstest(ae_state *_state); - - -/************************************************************************* -Function for testing CRS-specific functionality. -On failure sets ErrorFlag, on success does not touch it. - - -- ALGLIB PROJECT -- - Copyright 30.01.2018 by Bochkanov Sergey -*************************************************************************/ -void crstest(ae_bool* errorflag, ae_state *_state); - - -/************************************************************************* -Function for testing basic functional - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -ae_bool basicfunctest(ae_state *_state); - - -/************************************************************************* -Function for testing Level 2 unsymmetric linear algebra functions. -Additionally it tests SparseGet() for several matrix formats. -Returns True on failure. - - -- ALGLIB PROJECT -- - Copyright 20.01.2014 by Bochkanov Sergey -*************************************************************************/ -ae_bool testlevel2unsymmetric(ae_state *_state); - - -/************************************************************************* -Function for testing Level 3 unsymmetric linear algebra functions. -Additionally it tests SparseGet() for several matrix formats. -Returns True on failure. - - -- ALGLIB PROJECT -- - Copyright 20.01.2014 by Bochkanov Sergey -*************************************************************************/ -ae_bool testlevel3unsymmetric(ae_state *_state); - - -/************************************************************************* -Function for testing Level 2 symmetric linear algebra functions. -Additionally it tests SparseGet() for several matrix formats. -Returns True on failure. - - -- ALGLIB PROJECT -- - Copyright 20.01.2014 by Bochkanov Sergey -*************************************************************************/ -ae_bool testlevel2symmetric(ae_state *_state); - - -/************************************************************************* -Function for testing Level 2 symmetric linear algebra functions. -Additionally it tests SparseGet() for several matrix formats. -Returns True on failure. - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -ae_bool testlevel3symmetric(ae_state *_state); - - -/************************************************************************* -Function for testing sparse symmetric permutations - - -- ALGLIB PROJECT -- - Copyright 07.10.2020 by Bochkanov Sergey -*************************************************************************/ -ae_bool testsymmetricperm(ae_state *_state); - - -/************************************************************************* -Function for testing Level 2 triangular linear algebra functions. -Returns True on failure. - - -- ALGLIB PROJECT -- - Copyright 20.01.2014 by Bochkanov Sergey -*************************************************************************/ -ae_bool testlevel2triangular(ae_state *_state); - - -/************************************************************************* -Function for testing basic functional - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -ae_bool basicfuncrandomtest(ae_state *_state); - - -/************************************************************************* -Function for testing multyplication matrix with vector - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -ae_bool linearfunctionstest(ae_state *_state); - - -/************************************************************************* -Function for testing multyplication for simmetric matrix with vector - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -ae_bool linearfunctionsstest(ae_state *_state); - - -/************************************************************************* -Function for testing multyplication sparse matrix with nerrow dense matrix - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -ae_bool linearfunctionsmmtest(ae_state *_state); - - -/************************************************************************* -Function for testing multyplication for simmetric sparse matrix with narrow -dense matrix - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -ae_bool linearfunctionssmmtest(ae_state *_state); - - -/************************************************************************* -Function for basic test SparseCopy - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -ae_bool basiccopyfunctest(ae_bool silent, ae_state *_state); - - -/************************************************************************* -Function for testing SparseCopy - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -ae_bool copyfunctest(ae_bool silent, ae_state *_state); -void _sparsegenerator_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _sparsegenerator_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _sparsegenerator_clear(void* _p); -void _sparsegenerator_destroy(void* _p); - - - - - - - - -ae_bool testablas(ae_bool silent, ae_state *_state); -ae_bool _pexec_testablas(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testcreflections(ae_bool silent, ae_state *_state); -ae_bool _pexec_testcreflections(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testmatgen(ae_bool silent, ae_state *_state); -ae_bool _pexec_testmatgen(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testtrfac(ae_bool silent, ae_state *_state); -ae_bool _pexec_testtrfac(ae_bool silent, ae_state *_state); - - -/************************************************************************* -Function for testing sparse real Cholesky. -Returns True on errors, False on success. - - -- ALGLIB PROJECT -- - Copyright 16.01.1014 by Bochkanov Sergey -*************************************************************************/ -ae_bool sparserealcholeskytest(ae_state *_state); - - -/************************************************************************* -Function for testing sparse real LU decomposition. -Sets error flag on failure, leave is unchanged on success. - - -- ALGLIB PROJECT -- - Copyright 16.01.1014 by Bochkanov Sergey -*************************************************************************/ -void sparsereallutest(ae_bool* err, ae_state *_state); - - - - - - - - -/************************************************************************* -Main unittest subroutine -*************************************************************************/ -ae_bool testtrlinsolve(ae_bool silent, ae_state *_state); -ae_bool _pexec_testtrlinsolve(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Main unittest subroutine -*************************************************************************/ -ae_bool testsafesolve(ae_bool silent, ae_state *_state); -ae_bool _pexec_testsafesolve(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testrcond(ae_bool silent, ae_state *_state); -ae_bool _pexec_testrcond(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testmatinv(ae_bool silent, ae_state *_state); -ae_bool _pexec_testmatinv(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testhblas(ae_bool silent, ae_state *_state); -ae_bool _pexec_testhblas(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testsblas(ae_bool silent, ae_state *_state); -ae_bool _pexec_testsblas(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Main unittest subroutine -*************************************************************************/ -ae_bool testortfac(ae_bool silent, ae_state *_state); -ae_bool _pexec_testortfac(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Testing -*************************************************************************/ -ae_bool testfbls(ae_bool silent, ae_state *_state); -ae_bool _pexec_testfbls(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testcqmodels(ae_bool silent, ae_state *_state); -ae_bool _pexec_testcqmodels(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Testing bidiagonal SVD decomposition subroutine -*************************************************************************/ -ae_bool testbdsvd(ae_bool silent, ae_state *_state); -ae_bool _pexec_testbdsvd(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testblas(ae_bool silent, ae_state *_state); -ae_bool _pexec_testblas(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Testing SVD decomposition subroutine -*************************************************************************/ -ae_bool testsvd(ae_bool silent, ae_state *_state); -ae_bool _pexec_testsvd(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testoptserv(ae_bool silent, ae_state *_state); -ae_bool _pexec_testoptserv(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testsnnls(ae_bool silent, ae_state *_state); -ae_bool _pexec_testsnnls(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testsactivesets(ae_bool silent, ae_state *_state); -ae_bool _pexec_testsactivesets(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testxblas(ae_bool silent, ae_state *_state); -ae_bool _pexec_testxblas(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testdirectdensesolvers(ae_bool silent, ae_state *_state); -ae_bool _pexec_testdirectdensesolvers(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testlinmin(ae_bool silent, ae_state *_state); -ae_bool _pexec_testlinmin(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testminlbfgs(ae_bool silent, ae_state *_state); -ae_bool _pexec_testminlbfgs(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testnormestimator(ae_bool silent, ae_state *_state); -ae_bool _pexec_testnormestimator(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testlinlsqr(ae_bool silent, ae_state *_state); -ae_bool _pexec_testlinlsqr(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testminbleic(ae_bool silent, ae_state *_state); -ae_bool _pexec_testminbleic(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testminqp(ae_bool silent, ae_state *_state); -ae_bool _pexec_testminqp(ae_bool silent, ae_state *_state); - - -/************************************************************************* -Function to test: 'MinQPCreate', 'MinQPSetQuadraticTerm', 'MinQPSetBC', -'MinQPSetOrigin', 'MinQPSetStartingPoint', 'MinQPOptimize', 'MinQPResults'. - -Test problem: - A = diag(aii), aii>0 (random) - b = 0 - random bounds (either no bounds, one bound, two bounds a 0 - without bounds - random start point - dimension - from 1 to 5. -*************************************************************************/ -ae_bool functest1(ae_state *_state); - - -/************************************************************************* -Function to test: 'MinQPCreate', 'MinQPSetLinearTerm', 'MinQPSetQuadraticTerm', -'MinQPSetBC', 'MinQPSetOrigin', 'MinQPSetStartingPoint', 'MinQPOptimize', -'MinQPResults'. - -Test problem: - A = positive-definite matrix, obtained by 'SPDMatrixRndCond' function - b <> 0 - boundary constraints - random start point - dimension - from 1 to 5. -*************************************************************************/ -ae_bool functest2(ae_state *_state); - - -/************************************************************************* -ConsoleTest. -*************************************************************************/ -ae_bool consoletest(ae_state *_state); - - -/************************************************************************* -This function performs tests specific for QuickQP solver - -Returns True on failure. -*************************************************************************/ -ae_bool quickqptests(ae_state *_state); - - -/************************************************************************* -This function performs tests specific for BLEIC solver - -Returns True on error, False on success. -*************************************************************************/ -ae_bool bleictests(ae_state *_state); - - - - - - - - -ae_bool testminlp(ae_bool silent, ae_state *_state); -ae_bool _pexec_testminlp(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testminnlc(ae_bool silent, ae_state *_state); -ae_bool _pexec_testminnlc(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testminbc(ae_bool silent, ae_state *_state); -ae_bool _pexec_testminbc(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testminns(ae_bool silent, ae_state *_state); -ae_bool _pexec_testminns(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testmincg(ae_bool silent, ae_state *_state); -ae_bool _pexec_testmincg(ae_bool silent, ae_state *_state); - - -/************************************************************************* -Other properties -*************************************************************************/ -void testother(ae_bool* err, ae_state *_state); - - - - - - - - -ae_bool testminlm(ae_bool silent, ae_state *_state); -ae_bool _pexec_testminlm(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Testing symmetric EVD subroutine -*************************************************************************/ -ae_bool testevd(ae_bool silent, ae_state *_state); -ae_bool _pexec_testevd(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testbasestat(ae_bool silent, ae_state *_state); -ae_bool _pexec_testbasestat(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testpca(ae_bool silent, ae_state *_state); -ae_bool _pexec_testpca(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Testing BDSS operations -*************************************************************************/ -ae_bool testbdss(ae_bool silent, ae_state *_state); -ae_bool _pexec_testbdss(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testmlpbase(ae_bool silent, ae_state *_state); -ae_bool _pexec_testmlpbase(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testlda(ae_bool silent, ae_state *_state); -ae_bool _pexec_testlda(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testssa(ae_bool silent, ae_state *_state); -ae_bool _pexec_testssa(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testgammafunc(ae_bool silent, ae_state *_state); -ae_bool _pexec_testgammafunc(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testnormaldistr(ae_bool silent, ae_state *_state); -ae_bool _pexec_testnormaldistr(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testlinreg(ae_bool silent, ae_state *_state); -ae_bool _pexec_testlinreg(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testfilters(ae_bool silent, ae_state *_state); -ae_bool _pexec_testfilters(ae_bool silent, ae_state *_state); - - -/************************************************************************* -This function tests SMA(k) filter. It returns True on error. - -Additional IsSilent parameter controls detailed error reporting. -*************************************************************************/ -ae_bool testsma(ae_bool issilent, ae_state *_state); - - -/************************************************************************* -This function tests EMA(alpha) filter. It returns True on error. - -Additional IsSilent parameter controls detailed error reporting. -*************************************************************************/ -ae_bool testema(ae_bool issilent, ae_state *_state); - - -/************************************************************************* -This function tests LRMA(k) filter. It returns True on error. - -Additional IsSilent parameter controls detailed error reporting. -*************************************************************************/ -ae_bool testlrma(ae_bool issilent, ae_state *_state); - - - - - - - - -ae_bool testmcpd(ae_bool silent, ae_state *_state); -ae_bool _pexec_testmcpd(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testmlpe(ae_bool silent, ae_state *_state); -ae_bool _pexec_testmlpe(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testmlptrain(ae_bool silent, ae_state *_state); -ae_bool _pexec_testmlptrain(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Testing clustering -*************************************************************************/ -ae_bool testclustering(ae_bool silent, ae_state *_state); -ae_bool _pexec_testclustering(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testdforest(ae_bool silent, ae_state *_state); -ae_bool _pexec_testdforest(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testknn(ae_bool silent, ae_state *_state); -ae_bool _pexec_testknn(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testgq(ae_bool silent, ae_state *_state); -ae_bool _pexec_testgq(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testgkq(ae_bool silent, ae_state *_state); -ae_bool _pexec_testgkq(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testautogk(ae_bool silent, ae_state *_state); -ae_bool _pexec_testautogk(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testfft(ae_bool silent, ae_state *_state); -ae_bool _pexec_testfft(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testfht(ae_bool silent, ae_state *_state); -ae_bool _pexec_testfht(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testconv(ae_bool silent, ae_state *_state); -ae_bool _pexec_testconv(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testcorr(ae_bool silent, ae_state *_state); -ae_bool _pexec_testcorr(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Testing IDW interpolation -*************************************************************************/ -ae_bool testidw(ae_bool silent, ae_state *_state); -ae_bool _pexec_testidw(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testratint(ae_bool silent, ae_state *_state); -ae_bool _pexec_testratint(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testfitsphere(ae_bool silent, ae_state *_state); -ae_bool _pexec_testfitsphere(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testspline1d(ae_bool silent, ae_state *_state); -ae_bool _pexec_testspline1d(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testparametric(ae_bool silent, ae_state *_state); -ae_bool _pexec_testparametric(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testspline3d(ae_bool silence, ae_state *_state); -ae_bool _pexec_testspline3d(ae_bool silence, ae_state *_state); - - - - - - - - -/************************************************************************* -Unit test -*************************************************************************/ -ae_bool testpolint(ae_bool silent, ae_state *_state); -ae_bool _pexec_testpolint(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testlsfit(ae_bool silent, ae_state *_state); -ae_bool _pexec_testlsfit(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testspline2d(ae_bool silent, ae_state *_state); -ae_bool _pexec_testspline2d(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testrbf(ae_bool silent, ae_state *_state); -ae_bool _pexec_testrbf(ae_bool silent, ae_state *_state); - - -/************************************************************************* -The test has to check, that algorithm can solve problems of matrix are -degenerate. - * used model with linear term; - * points locate in a subspace of dimension less than an original space. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -ae_bool sqrdegmatrixrbftest(ae_bool silent, ae_state *_state); - - -/************************************************************************* -Function for testing basic functionality of RBF module on regular grids with -multi-layer algorithm in 1D. - - -- ALGLIB -- - Copyright 2.03.2012 by Bochkanov Sergey -*************************************************************************/ -ae_bool basicmultilayerrbf1dtest(ae_state *_state); - - - - - - - - -ae_bool testhermite(ae_bool silent, ae_state *_state); -ae_bool _pexec_testhermite(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testlaguerre(ae_bool silent, ae_state *_state); -ae_bool _pexec_testlaguerre(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testlegendre(ae_bool silent, ae_state *_state); -ae_bool _pexec_testlegendre(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testchebyshev(ae_bool silent, ae_state *_state); -ae_bool _pexec_testchebyshev(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testwsr(ae_bool silent, ae_state *_state); -ae_bool _pexec_testwsr(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool teststest(ae_bool silent, ae_state *_state); -ae_bool _pexec_teststest(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool teststudentttests(ae_bool silent, ae_state *_state); -ae_bool _pexec_teststudentttests(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testmannwhitneyu(ae_bool silent, ae_state *_state); -ae_bool _pexec_testmannwhitneyu(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Testing Schur decomposition subroutine -*************************************************************************/ -ae_bool testschur(ae_bool silent, ae_state *_state); -ae_bool _pexec_testschur(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Testing bidiagonal SVD decomposition subroutine -*************************************************************************/ -ae_bool testspdgevd(ae_bool silent, ae_state *_state); -ae_bool _pexec_testspdgevd(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testinverseupdate(ae_bool silent, ae_state *_state); -ae_bool _pexec_testinverseupdate(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testpolynomialsolver(ae_bool silent, ae_state *_state); -ae_bool _pexec_testpolynomialsolver(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testnleq(ae_bool silent, ae_state *_state); -ae_bool _pexec_testnleq(ae_bool silent, ae_state *_state); - - - - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testdirectsparsesolvers(ae_bool silent, ae_state *_state); -ae_bool _pexec_testdirectsparsesolvers(ae_bool silent, ae_state *_state); - - - - - - - - -ae_bool testlincg(ae_bool silent, ae_state *_state); -ae_bool _pexec_testlincg(ae_bool silent, ae_state *_state); - - - - - -typedef struct -{ - ae_bool bfield; - double rfield; - ae_int_t ifield; - ae_complex cfield; - ae_vector b1field; - ae_vector r1field; - ae_vector i1field; - ae_vector c1field; - ae_matrix b2field; - ae_matrix r2field; - ae_matrix i2field; - ae_matrix c2field; -} rec1; - - -typedef struct -{ - ae_vector b; - ae_vector i; - ae_vector r; -} rec4serialization; - - -typedef struct -{ - ae_complex cval; - double rval; - ae_int_t ival; - ae_bool bval; - ae_vector i1val; -} poolrec1; - - -typedef struct -{ - ae_bool bval; - poolrec1 recval; - ae_shared_pool pool; -} poolrec2; - - -typedef struct -{ - ae_int_t val; -} poolsummand; - - - - - -void rec4serializationalloc(ae_serializer* s, - rec4serialization* v, - ae_state *_state); - - -void rec4serializationserialize(ae_serializer* s, - rec4serialization* v, - ae_state *_state); - - -void rec4serializationunserialize(ae_serializer* s, - rec4serialization* v, - ae_state *_state); - - -ae_bool testalglibbasics(ae_bool silent, ae_state *_state); -ae_bool _pexec_testalglibbasics(ae_bool silent, ae_state *_state); -void _rec1_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _rec1_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _rec1_clear(void* _p); -void _rec1_destroy(void* _p); -void _rec4serialization_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _rec4serialization_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _rec4serialization_clear(void* _p); -void _rec4serialization_destroy(void* _p); -void _poolrec1_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _poolrec1_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _poolrec1_clear(void* _p); -void _poolrec1_destroy(void* _p); -void _poolrec2_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _poolrec2_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _poolrec2_clear(void* _p); -void _poolrec2_destroy(void* _p); -void _poolsummand_init(void* _p, ae_state *_state, ae_bool make_automatic); -void _poolsummand_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic); -void _poolsummand_clear(void* _p); -void _poolsummand_destroy(void* _p); - - - - -static void testtsortunit_unset1di(/* Integer */ ae_vector* a, - ae_state *_state); -static void testtsortunit_testsortresults(/* Real */ ae_vector* asorted, - /* Integer */ ae_vector* p1, - /* Integer */ ae_vector* p2, - /* Real */ ae_vector* aoriginal, - ae_int_t n, - ae_bool* waserrors, - ae_state *_state); - - - - - -/************************************************************************* -Testing tag sort -*************************************************************************/ -ae_bool testtsort(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_bool waserrors; - ae_int_t n; - ae_int_t i; - ae_int_t m; - ae_int_t offs; - ae_int_t pass; - ae_int_t passcount; - ae_int_t maxn; - ae_vector a; - ae_vector a0; - ae_vector a1; - ae_vector a2; - ae_vector a3; - ae_vector i1; - ae_vector i2; - ae_vector i3; - ae_vector a4; - ae_vector a5; - ae_vector pa4; - ae_vector ar; - ae_vector ar2; - ae_vector ai; - ae_vector p1; - ae_vector p2; - ae_vector bufr1; - ae_vector bufr2; - ae_vector bufi1; - ae_bool distinctvals; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&a0, 0, sizeof(a0)); - memset(&a1, 0, sizeof(a1)); - memset(&a2, 0, sizeof(a2)); - memset(&a3, 0, sizeof(a3)); - memset(&i1, 0, sizeof(i1)); - memset(&i2, 0, sizeof(i2)); - memset(&i3, 0, sizeof(i3)); - memset(&a4, 0, sizeof(a4)); - memset(&a5, 0, sizeof(a5)); - memset(&pa4, 0, sizeof(pa4)); - memset(&ar, 0, sizeof(ar)); - memset(&ar2, 0, sizeof(ar2)); - memset(&ai, 0, sizeof(ai)); - memset(&p1, 0, sizeof(p1)); - memset(&p2, 0, sizeof(p2)); - memset(&bufr1, 0, sizeof(bufr1)); - memset(&bufr2, 0, sizeof(bufr2)); - memset(&bufi1, 0, sizeof(bufi1)); - ae_vector_init(&a, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a3, 0, DT_REAL, _state, ae_true); - ae_vector_init(&i1, 0, DT_INT, _state, ae_true); - ae_vector_init(&i2, 0, DT_INT, _state, ae_true); - ae_vector_init(&i3, 0, DT_INT, _state, ae_true); - ae_vector_init(&a4, 0, DT_INT, _state, ae_true); - ae_vector_init(&a5, 0, DT_INT, _state, ae_true); - ae_vector_init(&pa4, 0, DT_INT, _state, ae_true); - ae_vector_init(&ar, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ar2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ai, 0, DT_INT, _state, ae_true); - ae_vector_init(&p1, 0, DT_INT, _state, ae_true); - ae_vector_init(&p2, 0, DT_INT, _state, ae_true); - ae_vector_init(&bufr1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bufr2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bufi1, 0, DT_INT, _state, ae_true); - - waserrors = ae_false; - maxn = 100; - passcount = 10; - - /* - * Test tagsort - */ - for(n=1; n<=maxn; n++) - { - for(pass=1; pass<=passcount; pass++) - { - - /* - * Pprobably distinct sort: - * * generate array of integer random numbers. - * Because of birthday paradox, random numbers have to be VERY large - * in order to avoid situation when we have distinct values. - * * sort A0 using TagSort and test sort results - * * now we can use A0 as reference point and test other functions - */ - testtsortunit_unset1di(&p1, _state); - testtsortunit_unset1di(&p2, _state); - ae_vector_set_length(&a, n, _state); - ae_vector_set_length(&a0, n, _state); - ae_vector_set_length(&a1, n, _state); - ae_vector_set_length(&a2, n, _state); - ae_vector_set_length(&a3, n, _state); - ae_vector_set_length(&a4, n, _state); - ae_vector_set_length(&a5, n, _state); - ae_vector_set_length(&ar, n, _state); - ae_vector_set_length(&ar2, n, _state); - ae_vector_set_length(&ai, n, _state); - for(i=0; i<=n-1; i++) - { - a.ptr.p_double[i] = (double)(ae_randominteger(100000000, _state)); - a0.ptr.p_double[i] = a.ptr.p_double[i]; - a1.ptr.p_double[i] = a.ptr.p_double[i]; - a2.ptr.p_double[i] = a.ptr.p_double[i]; - a3.ptr.p_double[i] = a.ptr.p_double[i]; - a4.ptr.p_int[i] = ae_round(a.ptr.p_double[i], _state); - a5.ptr.p_int[i] = ae_round(a.ptr.p_double[i], _state); - ar.ptr.p_double[i] = (double)(i); - ar2.ptr.p_double[i] = (double)(i); - ai.ptr.p_int[i] = i; - } - tagsort(&a0, n, &p1, &p2, _state); - testtsortunit_testsortresults(&a0, &p1, &p2, &a, n, &waserrors, _state); - distinctvals = ae_true; - for(i=1; i<=n-1; i++) - { - distinctvals = distinctvals&&ae_fp_neq(a0.ptr.p_double[i],a0.ptr.p_double[i-1]); - } - if( distinctvals ) - { - tagsortfasti(&a1, &ai, &bufr1, &bufi1, n, _state); - for(i=0; i<=n-1; i++) - { - waserrors = (waserrors||ae_fp_neq(a1.ptr.p_double[i],a0.ptr.p_double[i]))||ai.ptr.p_int[i]!=p1.ptr.p_int[i]; - } - tagsortfastr(&a2, &ar, &bufr1, &bufr2, n, _state); - for(i=0; i<=n-1; i++) - { - waserrors = (waserrors||ae_fp_neq(a2.ptr.p_double[i],a0.ptr.p_double[i]))||ae_fp_neq(ar.ptr.p_double[i],(double)(p1.ptr.p_int[i])); - } - tagsortfast(&a3, &bufr1, n, _state); - for(i=0; i<=n-1; i++) - { - waserrors = waserrors||ae_fp_neq(a3.ptr.p_double[i],a0.ptr.p_double[i]); - } - tagsortmiddleir(&a4, &ar2, 0, n, _state); - for(i=0; i<=n-1; i++) - { - waserrors = (waserrors||ae_fp_neq((double)(a4.ptr.p_int[i]),a0.ptr.p_double[i]))||ae_fp_neq(ar2.ptr.p_double[i],(double)(p1.ptr.p_int[i])); - } - sortmiddlei(&a5, 0, n, _state); - for(i=0; i<=n-1; i++) - { - waserrors = waserrors||ae_fp_neq((double)(a5.ptr.p_int[i]),a0.ptr.p_double[i]); - } - } - - /* - * Non-distinct sort. - * We test that keys are correctly reordered, but do NOT test order of values. - */ - testtsortunit_unset1di(&p1, _state); - testtsortunit_unset1di(&p2, _state); - ae_vector_set_length(&a, n, _state); - ae_vector_set_length(&a0, n, _state); - ae_vector_set_length(&a1, n, _state); - ae_vector_set_length(&a2, n, _state); - ae_vector_set_length(&a3, n, _state); - ae_vector_set_length(&a4, n, _state); - ae_vector_set_length(&a5, n, _state); - ae_vector_set_length(&ar, n, _state); - ae_vector_set_length(&ar2, n, _state); - ae_vector_set_length(&ai, n, _state); - for(i=0; i<=n-1; i++) - { - a.ptr.p_double[i] = (double)((n-i)/2); - a0.ptr.p_double[i] = a.ptr.p_double[i]; - a1.ptr.p_double[i] = a.ptr.p_double[i]; - a2.ptr.p_double[i] = a.ptr.p_double[i]; - a3.ptr.p_double[i] = a.ptr.p_double[i]; - a4.ptr.p_int[i] = ae_round(a.ptr.p_double[i], _state); - a5.ptr.p_int[i] = ae_round(a.ptr.p_double[i], _state); - ar.ptr.p_double[i] = (double)(i); - ar2.ptr.p_double[i] = (double)(i); - ai.ptr.p_int[i] = i; - } - tagsort(&a0, n, &p1, &p2, _state); - testtsortunit_testsortresults(&a0, &p1, &p2, &a, n, &waserrors, _state); - tagsortfasti(&a1, &ai, &bufr1, &bufi1, n, _state); - for(i=0; i<=n-1; i++) - { - waserrors = waserrors||ae_fp_neq(a1.ptr.p_double[i],a0.ptr.p_double[i]); - } - tagsortfastr(&a2, &ar, &bufr1, &bufr2, n, _state); - for(i=0; i<=n-1; i++) - { - waserrors = waserrors||ae_fp_neq(a2.ptr.p_double[i],a0.ptr.p_double[i]); - } - tagsortfast(&a3, &bufr1, n, _state); - for(i=0; i<=n-1; i++) - { - waserrors = waserrors||ae_fp_neq(a3.ptr.p_double[i],a0.ptr.p_double[i]); - } - tagsortmiddleir(&a4, &ar2, 0, n, _state); - for(i=0; i<=n-1; i++) - { - waserrors = waserrors||ae_fp_neq((double)(a4.ptr.p_int[i]),a0.ptr.p_double[i]); - } - sortmiddlei(&a5, 0, n, _state); - for(i=0; i<=n-1; i++) - { - waserrors = waserrors||ae_fp_neq((double)(a5.ptr.p_int[i]),a0.ptr.p_double[i]); - } - - /* - * 'All same' sort - * We test that keys are correctly reordered, but do NOT test order of values. - */ - testtsortunit_unset1di(&p1, _state); - testtsortunit_unset1di(&p2, _state); - ae_vector_set_length(&a, n, _state); - ae_vector_set_length(&a0, n, _state); - ae_vector_set_length(&a1, n, _state); - ae_vector_set_length(&a2, n, _state); - ae_vector_set_length(&a3, n, _state); - ae_vector_set_length(&a4, n, _state); - ae_vector_set_length(&ar, n, _state); - ae_vector_set_length(&ar2, n, _state); - ae_vector_set_length(&ai, n, _state); - for(i=0; i<=n-1; i++) - { - a.ptr.p_double[i] = (double)(0); - a0.ptr.p_double[i] = a.ptr.p_double[i]; - a1.ptr.p_double[i] = a.ptr.p_double[i]; - a2.ptr.p_double[i] = a.ptr.p_double[i]; - a3.ptr.p_double[i] = a.ptr.p_double[i]; - a4.ptr.p_int[i] = ae_round(a.ptr.p_double[i], _state); - ar.ptr.p_double[i] = (double)(i); - ar2.ptr.p_double[i] = (double)(i); - ai.ptr.p_int[i] = i; - } - tagsort(&a0, n, &p1, &p2, _state); - testtsortunit_testsortresults(&a0, &p1, &p2, &a, n, &waserrors, _state); - tagsortfasti(&a1, &ai, &bufr1, &bufi1, n, _state); - for(i=0; i<=n-1; i++) - { - waserrors = waserrors||ae_fp_neq(a1.ptr.p_double[i],a0.ptr.p_double[i]); - } - tagsortfastr(&a2, &ar, &bufr1, &bufr2, n, _state); - for(i=0; i<=n-1; i++) - { - waserrors = waserrors||ae_fp_neq(a2.ptr.p_double[i],a0.ptr.p_double[i]); - } - tagsortfast(&a3, &bufr1, n, _state); - for(i=0; i<=n-1; i++) - { - waserrors = waserrors||ae_fp_neq(a3.ptr.p_double[i],a0.ptr.p_double[i]); - } - tagsortmiddleir(&a4, &ar2, 0, n, _state); - for(i=0; i<=n-1; i++) - { - waserrors = waserrors||ae_fp_neq((double)(a4.ptr.p_int[i]),a0.ptr.p_double[i]); - } - - /* - * 0-1 sort - * We test that keys are correctly reordered, but do NOT test order of values. - */ - testtsortunit_unset1di(&p1, _state); - testtsortunit_unset1di(&p2, _state); - ae_vector_set_length(&a, n, _state); - ae_vector_set_length(&a0, n, _state); - ae_vector_set_length(&a1, n, _state); - ae_vector_set_length(&a2, n, _state); - ae_vector_set_length(&a3, n, _state); - ae_vector_set_length(&a4, n, _state); - ae_vector_set_length(&ar, n, _state); - ae_vector_set_length(&ar2, n, _state); - ae_vector_set_length(&ai, n, _state); - for(i=0; i<=n-1; i++) - { - a.ptr.p_double[i] = (double)(ae_randominteger(2, _state)); - a0.ptr.p_double[i] = a.ptr.p_double[i]; - a1.ptr.p_double[i] = a.ptr.p_double[i]; - a2.ptr.p_double[i] = a.ptr.p_double[i]; - a3.ptr.p_double[i] = a.ptr.p_double[i]; - a4.ptr.p_int[i] = ae_round(a.ptr.p_double[i], _state); - ar.ptr.p_double[i] = (double)(i); - ar2.ptr.p_double[i] = (double)(i); - ai.ptr.p_int[i] = i; - } - tagsort(&a0, n, &p1, &p2, _state); - testtsortunit_testsortresults(&a0, &p1, &p2, &a, n, &waserrors, _state); - tagsortfasti(&a1, &ai, &bufr1, &bufi1, n, _state); - for(i=0; i<=n-1; i++) - { - waserrors = waserrors||ae_fp_neq(a1.ptr.p_double[i],a0.ptr.p_double[i]); - } - tagsortfastr(&a2, &ar, &bufr1, &bufr2, n, _state); - for(i=0; i<=n-1; i++) - { - waserrors = waserrors||ae_fp_neq(a2.ptr.p_double[i],a0.ptr.p_double[i]); - } - tagsortfast(&a3, &bufr1, n, _state); - for(i=0; i<=n-1; i++) - { - waserrors = waserrors||ae_fp_neq(a3.ptr.p_double[i],a0.ptr.p_double[i]); - } - tagsortmiddleir(&a4, &ar2, 0, n, _state); - for(i=0; i<=n-1; i++) - { - waserrors = waserrors||ae_fp_neq((double)(a4.ptr.p_int[i]),a0.ptr.p_double[i]); - } - - /* - * Special test for TagSortMiddleIR: sorting in the middle gives same results - * as sorting in the beginning of the array - */ - m = 3*n; - offs = ae_randominteger(n, _state); - ae_vector_set_length(&i1, m, _state); - ae_vector_set_length(&i2, m, _state); - ae_vector_set_length(&i3, m, _state); - ae_vector_set_length(&ar, m, _state); - ae_vector_set_length(&ar2, m, _state); - for(i=0; i<=m-1; i++) - { - i1.ptr.p_int[i] = ae_randominteger(100000000, _state); - i2.ptr.p_int[i] = i1.ptr.p_int[i]; - i3.ptr.p_int[i] = i1.ptr.p_int[i]; - ar.ptr.p_double[i] = (double)(i); - ar2.ptr.p_double[i] = (double)(i); - } - for(i=0; i<=n-1; i++) - { - i1.ptr.p_int[i] = i1.ptr.p_int[offs+i]; - ar.ptr.p_double[i] = ar.ptr.p_double[offs+i]; - } - tagsortmiddleir(&i1, &ar, 0, n, _state); - for(i=1; i<=n-1; i++) - { - distinctvals = distinctvals&&i1.ptr.p_int[i]!=i1.ptr.p_int[i-1]; - } - if( distinctvals ) - { - tagsortmiddleir(&i2, &ar2, offs, n, _state); - for(i=0; i<=n-1; i++) - { - waserrors = (waserrors||i2.ptr.p_int[offs+i]!=i1.ptr.p_int[i])||ae_fp_neq(ar2.ptr.p_double[offs+i],ar.ptr.p_double[i]); - } - } - } - } - - /* - * report - */ - if( !silent ) - { - printf("TESTING TAGSORT\n"); - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Unsets 1D array. -*************************************************************************/ -static void testtsortunit_unset1di(/* Integer */ ae_vector* a, - ae_state *_state) -{ - - - ae_vector_set_length(a, 0+1, _state); - a->ptr.p_int[0] = ae_randominteger(3, _state)-1; -} - - -static void testtsortunit_testsortresults(/* Real */ ae_vector* asorted, - /* Integer */ ae_vector* p1, - /* Integer */ ae_vector* p2, - /* Real */ ae_vector* aoriginal, - ae_int_t n, - ae_bool* waserrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_vector a2; - double t; - ae_vector f; - - ae_frame_make(_state, &_frame_block); - memset(&a2, 0, sizeof(a2)); - memset(&f, 0, sizeof(f)); - ae_vector_init(&a2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&f, 0, DT_INT, _state, ae_true); - - ae_vector_set_length(&a2, n-1+1, _state); - ae_vector_set_length(&f, n-1+1, _state); - - /* - * is set ordered? - */ - for(i=0; i<=n-2; i++) - { - *waserrors = *waserrors||ae_fp_greater(asorted->ptr.p_double[i],asorted->ptr.p_double[i+1]); - } - - /* - * P1 correctness - */ - for(i=0; i<=n-1; i++) - { - *waserrors = *waserrors||ae_fp_neq(asorted->ptr.p_double[i],aoriginal->ptr.p_double[p1->ptr.p_int[i]]); - } - for(i=0; i<=n-1; i++) - { - f.ptr.p_int[i] = 0; - } - for(i=0; i<=n-1; i++) - { - f.ptr.p_int[p1->ptr.p_int[i]] = f.ptr.p_int[p1->ptr.p_int[i]]+1; - } - for(i=0; i<=n-1; i++) - { - *waserrors = *waserrors||f.ptr.p_int[i]!=1; - } - - /* - * P2 correctness - */ - for(i=0; i<=n-1; i++) - { - a2.ptr.p_double[i] = aoriginal->ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - if( p2->ptr.p_int[i]!=i ) - { - t = a2.ptr.p_double[i]; - a2.ptr.p_double[i] = a2.ptr.p_double[p2->ptr.p_int[i]]; - a2.ptr.p_double[p2->ptr.p_int[i]] = t; - } - } - for(i=0; i<=n-1; i++) - { - *waserrors = *waserrors||ae_fp_neq(asorted->ptr.p_double[i],a2.ptr.p_double[i]); - } - ae_frame_leave(_state); -} - - - -static ae_bool testnearestneighborunit_kdtresultsdifferent(/* Real */ ae_matrix* refxy, - ae_int_t ntotal, - /* Real */ ae_matrix* qx, - /* Real */ ae_matrix* qxy, - /* Integer */ ae_vector* qt, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - ae_state *_state); -static double testnearestneighborunit_vnorm(/* Real */ ae_vector* x, - ae_int_t n, - ae_int_t normtype, - ae_state *_state); -static void testnearestneighborunit_testkdtuniform(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - ae_int_t normtype, - ae_bool* kdterrors, - ae_state *_state); -static void testnearestneighborunit_testkdtreeserialization(ae_bool* err, - ae_state *_state); -static ae_bool testnearestneighborunit_testspecialcases(ae_state *_state); - - - - - -/************************************************************************* -Testing Nearest Neighbor Search -*************************************************************************/ -ae_bool testnearestneighbor(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix xy; - ae_int_t i; - ae_int_t j; - double v; - ae_int_t normtype; - ae_int_t nx; - ae_int_t ny; - ae_int_t n; - ae_int_t smalln; - ae_int_t largen; - ae_int_t passcount; - ae_int_t pass; - ae_bool waserrors; - ae_bool kdterrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - - kdterrors = ae_false; - passcount = 2; - smalln = 256; - largen = 2048; - ny = 3; - - /* - * - */ - testnearestneighborunit_testkdtreeserialization(&kdterrors, _state); - for(pass=1; pass<=passcount; pass++) - { - for(normtype=0; normtype<=2; normtype++) - { - for(nx=1; nx<=3; nx++) - { - - /* - * Test in hypercube - */ - ae_matrix_set_length(&xy, largen, nx+ny, _state); - for(i=0; i<=largen-1; i++) - { - for(j=0; j<=nx+ny-1; j++) - { - xy.ptr.pp_double[i][j] = 10*ae_randomreal(_state)-5; - } - } - for(n=1; n<=10; n++) - { - testnearestneighborunit_testkdtuniform(&xy, n, nx, ae_randominteger(ny+1, _state), normtype, &kdterrors, _state); - } - testnearestneighborunit_testkdtuniform(&xy, largen, nx, ae_randominteger(ny+1, _state), normtype, &kdterrors, _state); - - /* - * Test clustered (2*N points, pairs of equal points) - */ - ae_matrix_set_length(&xy, 2*smalln, nx+ny, _state); - for(i=0; i<=smalln-1; i++) - { - for(j=0; j<=nx+ny-1; j++) - { - xy.ptr.pp_double[2*i+0][j] = 10*ae_randomreal(_state)-5; - xy.ptr.pp_double[2*i+1][j] = xy.ptr.pp_double[2*i+0][j]; - } - } - testnearestneighborunit_testkdtuniform(&xy, 2*smalln, nx, ae_randominteger(ny+1, _state), normtype, &kdterrors, _state); - - /* - * Test degenerate case: all points are same except for one - */ - ae_matrix_set_length(&xy, smalln, nx+ny, _state); - v = ae_randomreal(_state); - for(i=0; i<=smalln-2; i++) - { - for(j=0; j<=nx+ny-1; j++) - { - xy.ptr.pp_double[i][j] = v; - } - } - for(j=0; j<=nx+ny-1; j++) - { - xy.ptr.pp_double[smalln-1][j] = 10*ae_randomreal(_state)-5; - } - testnearestneighborunit_testkdtuniform(&xy, smalln, nx, ae_randominteger(ny+1, _state), normtype, &kdterrors, _state); - } - } - } - kdterrors = kdterrors||testnearestneighborunit_testspecialcases(_state); - - /* - * report - */ - waserrors = kdterrors; - if( !silent ) - { - printf("TESTING NEAREST NEIGHBOR SEARCH\n"); - printf("* KD TREES: "); - if( !kdterrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Compare results from different queries: -* X just X-values -* XY X-values and Y-values -* XT X-values and tag values -*************************************************************************/ -static ae_bool testnearestneighborunit_kdtresultsdifferent(/* Real */ ae_matrix* refxy, - ae_int_t ntotal, - /* Real */ ae_matrix* qx, - /* Real */ ae_matrix* qxy, - /* Integer */ ae_vector* qt, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_bool result; - - - result = ae_false; - for(i=0; i<=n-1; i++) - { - if( qt->ptr.p_int[i]<0||qt->ptr.p_int[i]>=ntotal ) - { - result = ae_true; - return result; - } - for(j=0; j<=nx-1; j++) - { - result = result||ae_fp_neq(qx->ptr.pp_double[i][j],refxy->ptr.pp_double[qt->ptr.p_int[i]][j]); - result = result||ae_fp_neq(qxy->ptr.pp_double[i][j],refxy->ptr.pp_double[qt->ptr.p_int[i]][j]); - } - for(j=0; j<=ny-1; j++) - { - result = result||ae_fp_neq(qxy->ptr.pp_double[i][nx+j],refxy->ptr.pp_double[qt->ptr.p_int[i]][nx+j]); - } - } - return result; -} - - -/************************************************************************* -Returns norm -*************************************************************************/ -static double testnearestneighborunit_vnorm(/* Real */ ae_vector* x, - ae_int_t n, - ae_int_t normtype, - ae_state *_state) -{ - ae_int_t i; - double result; - - - result = ae_randomreal(_state); - if( normtype==0 ) - { - result = (double)(0); - for(i=0; i<=n-1; i++) - { - result = ae_maxreal(result, ae_fabs(x->ptr.p_double[i], _state), _state); - } - return result; - } - if( normtype==1 ) - { - result = (double)(0); - for(i=0; i<=n-1; i++) - { - result = result+ae_fabs(x->ptr.p_double[i], _state); - } - return result; - } - if( normtype==2 ) - { - result = (double)(0); - for(i=0; i<=n-1; i++) - { - result = result+ae_sqr(x->ptr.p_double[i], _state); - } - result = ae_sqrt(result, _state); - return result; - } - return result; -} - - -/************************************************************************* -Testing Nearest Neighbor Search on uniformly distributed hypercube - -NormType: 0, 1, 2 -D: space dimension -N: points count -*************************************************************************/ -static void testnearestneighborunit_testkdtuniform(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t nx, - ae_int_t ny, - ae_int_t normtype, - ae_bool* kdterrors, - ae_state *_state) -{ - ae_frame _frame_block; - double errtol; - ae_vector tags; - ae_vector ptx; - ae_vector tmpx; - ae_vector tmpb; - kdtree treex; - kdtree treexy; - kdtree treext; - kdtreerequestbuffer bufx; - kdtreerequestbuffer bufxy; - kdtreerequestbuffer bufxt; - ae_matrix qx; - ae_matrix qxy; - ae_vector qtags; - ae_vector qr; - ae_vector boxmin; - ae_vector boxmax; - ae_vector qmin; - ae_vector qmax; - double spread; - ae_int_t kx; - ae_int_t kxy; - ae_int_t kt; - double eps; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t task; - ae_bool isequal; - double r; - ae_int_t q; - ae_int_t qcount; - double v; - ae_bool inthebox; - ae_bool orderedrnn; - - ae_frame_make(_state, &_frame_block); - memset(&tags, 0, sizeof(tags)); - memset(&ptx, 0, sizeof(ptx)); - memset(&tmpx, 0, sizeof(tmpx)); - memset(&tmpb, 0, sizeof(tmpb)); - memset(&treex, 0, sizeof(treex)); - memset(&treexy, 0, sizeof(treexy)); - memset(&treext, 0, sizeof(treext)); - memset(&bufx, 0, sizeof(bufx)); - memset(&bufxy, 0, sizeof(bufxy)); - memset(&bufxt, 0, sizeof(bufxt)); - memset(&qx, 0, sizeof(qx)); - memset(&qxy, 0, sizeof(qxy)); - memset(&qtags, 0, sizeof(qtags)); - memset(&qr, 0, sizeof(qr)); - memset(&boxmin, 0, sizeof(boxmin)); - memset(&boxmax, 0, sizeof(boxmax)); - memset(&qmin, 0, sizeof(qmin)); - memset(&qmax, 0, sizeof(qmax)); - ae_vector_init(&tags, 0, DT_INT, _state, ae_true); - ae_vector_init(&ptx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpb, 0, DT_BOOL, _state, ae_true); - _kdtree_init(&treex, _state, ae_true); - _kdtree_init(&treexy, _state, ae_true); - _kdtree_init(&treext, _state, ae_true); - _kdtreerequestbuffer_init(&bufx, _state, ae_true); - _kdtreerequestbuffer_init(&bufxy, _state, ae_true); - _kdtreerequestbuffer_init(&bufxt, _state, ae_true); - ae_matrix_init(&qx, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&qxy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&qtags, 0, DT_INT, _state, ae_true); - ae_vector_init(&qr, 0, DT_REAL, _state, ae_true); - ae_vector_init(&boxmin, 0, DT_REAL, _state, ae_true); - ae_vector_init(&boxmax, 0, DT_REAL, _state, ae_true); - ae_vector_init(&qmin, 0, DT_REAL, _state, ae_true); - ae_vector_init(&qmax, 0, DT_REAL, _state, ae_true); - - qcount = 10; - ae_assert(n>0, "Assertion failed", _state); - - /* - * Tol - roundoff error tolerance (for '>=' comparisons) - */ - errtol = 100000*ae_machineepsilon; - - /* - * Evaluate bounding box and spread. - */ - ae_vector_set_length(&boxmin, nx, _state); - ae_vector_set_length(&boxmax, nx, _state); - for(j=0; j<=nx-1; j++) - { - boxmin.ptr.p_double[j] = xy->ptr.pp_double[0][j]; - boxmax.ptr.p_double[j] = xy->ptr.pp_double[0][j]; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - boxmin.ptr.p_double[j] = ae_minreal(boxmin.ptr.p_double[j], xy->ptr.pp_double[i][j], _state); - boxmax.ptr.p_double[j] = ae_maxreal(boxmax.ptr.p_double[j], xy->ptr.pp_double[i][j], _state); - } - } - spread = (double)(0); - for(j=0; j<=nx-1; j++) - { - spread = ae_maxreal(spread, boxmax.ptr.p_double[j]-boxmin.ptr.p_double[j], _state); - } - if( ae_fp_eq(spread,(double)(0)) ) - { - spread = (double)(1); - } - - /* - * fill tags - */ - ae_vector_set_length(&tags, n, _state); - for(i=0; i<=n-1; i++) - { - tags.ptr.p_int[i] = i; - } - - /* - * build trees - */ - kdtreebuild(xy, n, nx, 0, normtype, &treex, _state); - kdtreebuild(xy, n, nx, ny, normtype, &treexy, _state); - kdtreebuildtagged(xy, &tags, n, nx, 0, normtype, &treext, _state); - - /* - * allocate arrays - */ - ae_vector_set_length(&tmpx, nx, _state); - ae_vector_set_length(&tmpb, n, _state); - ae_matrix_set_length(&qx, n, nx, _state); - ae_matrix_set_length(&qxy, n, nx+ny, _state); - ae_vector_set_length(&qtags, n, _state); - ae_vector_set_length(&qr, n, _state); - ae_vector_set_length(&ptx, nx, _state); - - /* - * test general K-NN queries (with self-matches): - * * compare results from different trees (must be equal) and - * check that correct (value,tag) pairs are returned - * * test results from XT tree - let R be radius of query result. - * then all points not in result must be not closer than R. - */ - for(q=1; q<=qcount; q++) - { - - /* - * Select K: 1..N - */ - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - k = 1+ae_randominteger(n, _state); - } - else - { - k = 1; - } - - /* - * Select point (either one of the points, or random) - */ - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - i = ae_randominteger(n, _state); - ae_v_move(&ptx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1)); - } - else - { - for(i=0; i<=nx-1; i++) - { - ptx.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - } - - /* - * Test functions which use internal buffer: - * * consistency of results from different queries - * * points in query are IN the R-sphere (or at the boundary), - * and points not in query are outside of the R-sphere (or at the boundary) - * * distances are correct and are ordered - */ - kx = kdtreequeryknn(&treex, &ptx, k, ae_true, _state); - kxy = kdtreequeryknn(&treexy, &ptx, k, ae_true, _state); - kt = kdtreequeryknn(&treext, &ptx, k, ae_true, _state); - if( (kx!=k||kxy!=k)||kt!=k ) - { - *kdterrors = ae_true; - ae_frame_leave(_state); - return; - } - unsetrealmatrix(&qx, _state); - unsetrealmatrix(&qxy, _state); - unsetintegerarray(&qtags, _state); - unsetrealarray(&qr, _state); - kdtreequeryresultsxi(&treex, &qx, _state); - kdtreequeryresultsxyi(&treexy, &qxy, _state); - kdtreequeryresultstagsi(&treext, &qtags, _state); - kdtreequeryresultsdistancesi(&treext, &qr, _state); - *kdterrors = *kdterrors||testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, k, nx, ny, _state); - unsetrealmatrix(&qx, _state); - unsetrealmatrix(&qxy, _state); - unsetintegerarray(&qtags, _state); - unsetrealarray(&qr, _state); - kdtreequeryresultsx(&treex, &qx, _state); - kdtreequeryresultsxy(&treexy, &qxy, _state); - kdtreequeryresultstags(&treext, &qtags, _state); - kdtreequeryresultsdistances(&treext, &qr, _state); - *kdterrors = *kdterrors||testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, k, nx, ny, _state); - for(i=0; i<=n-1; i++) - { - tmpb.ptr.p_bool[i] = ae_true; - } - r = (double)(0); - for(i=0; i<=k-1; i++) - { - tmpb.ptr.p_bool[qtags.ptr.p_int[i]] = ae_false; - ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1)); - ae_v_sub(&tmpx.ptr.p_double[0], 1, &qx.ptr.pp_double[i][0], 1, ae_v_len(0,nx-1)); - r = ae_maxreal(r, testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state), _state); - } - for(i=0; i<=n-1; i++) - { - if( tmpb.ptr.p_bool[i] ) - { - ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1)); - ae_v_sub(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1)); - *kdterrors = *kdterrors||ae_fp_less(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state),r*(1-errtol)); - } - } - for(i=0; i<=k-2; i++) - { - *kdterrors = *kdterrors||ae_fp_greater(qr.ptr.p_double[i],qr.ptr.p_double[i+1]); - } - for(i=0; i<=k-1; i++) - { - ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1)); - ae_v_sub(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[qtags.ptr.p_int[i]][0], 1, ae_v_len(0,nx-1)); - *kdterrors = *kdterrors||ae_fp_greater(ae_fabs(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state)-qr.ptr.p_double[i], _state),errtol); - } - - /* - * Test functions which use external buffer: - * * create external request buffer, perform buffered request - * * reset status of internal buffer by performing 1-NN query, it is essential - * to test the fact that external buffer is used - * * check consistency of results from different queries - * * check that points in query are IN the R-sphere (or at the boundary), - * and points not in query are outside of the R-sphere (or at the boundary) - * * check that distances are correct and are ordered - */ - kdtreecreaterequestbuffer(&treex, &bufx, _state); - kdtreecreaterequestbuffer(&treexy, &bufxy, _state); - kdtreecreaterequestbuffer(&treext, &bufxt, _state); - kx = kdtreetsqueryknn(&treex, &bufx, &ptx, k, ae_true, _state); - kxy = kdtreetsqueryknn(&treexy, &bufxy, &ptx, k, ae_true, _state); - kt = kdtreetsqueryknn(&treext, &bufxt, &ptx, k, ae_true, _state); - kdtreequeryknn(&treex, &ptx, 1, ae_true, _state); - kdtreequeryknn(&treexy, &ptx, 1, ae_true, _state); - kdtreequeryknn(&treext, &ptx, 1, ae_true, _state); - if( (kx!=k||kxy!=k)||kt!=k ) - { - *kdterrors = ae_true; - ae_frame_leave(_state); - return; - } - unsetrealmatrix(&qx, _state); - unsetrealmatrix(&qxy, _state); - unsetintegerarray(&qtags, _state); - unsetrealarray(&qr, _state); - kdtreetsqueryresultsx(&treex, &bufx, &qx, _state); - kdtreetsqueryresultsxy(&treexy, &bufxy, &qxy, _state); - kdtreetsqueryresultstags(&treext, &bufxt, &qtags, _state); - kdtreetsqueryresultsdistances(&treext, &bufxt, &qr, _state); - *kdterrors = *kdterrors||testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, k, nx, ny, _state); - for(i=0; i<=n-1; i++) - { - tmpb.ptr.p_bool[i] = ae_true; - } - r = (double)(0); - for(i=0; i<=k-1; i++) - { - tmpb.ptr.p_bool[qtags.ptr.p_int[i]] = ae_false; - ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1)); - ae_v_sub(&tmpx.ptr.p_double[0], 1, &qx.ptr.pp_double[i][0], 1, ae_v_len(0,nx-1)); - r = ae_maxreal(r, testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state), _state); - } - for(i=0; i<=n-1; i++) - { - if( tmpb.ptr.p_bool[i] ) - { - ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1)); - ae_v_sub(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1)); - *kdterrors = *kdterrors||ae_fp_less(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state),r*(1-errtol)); - } - } - for(i=0; i<=k-2; i++) - { - *kdterrors = *kdterrors||ae_fp_greater(qr.ptr.p_double[i],qr.ptr.p_double[i+1]); - } - for(i=0; i<=k-1; i++) - { - ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1)); - ae_v_sub(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[qtags.ptr.p_int[i]][0], 1, ae_v_len(0,nx-1)); - *kdterrors = *kdterrors||ae_fp_greater(ae_fabs(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state)-qr.ptr.p_double[i], _state),errtol); - } - - /* - * Test reallocation properties: functions must automatically - * resize array which is too small, but leave unchanged array which is - * too large. - */ - if( n>=2 ) - { - - /* - * First step: array is too small, two elements are required - */ - k = 2; - kx = kdtreequeryknn(&treex, &ptx, k, ae_true, _state); - kxy = kdtreequeryknn(&treexy, &ptx, k, ae_true, _state); - kt = kdtreequeryknn(&treext, &ptx, k, ae_true, _state); - if( (kx!=k||kxy!=k)||kt!=k ) - { - *kdterrors = ae_true; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&qx, 1, 1, _state); - ae_matrix_set_length(&qxy, 1, 1, _state); - ae_vector_set_length(&qtags, 1, _state); - ae_vector_set_length(&qr, 1, _state); - kdtreequeryresultsx(&treex, &qx, _state); - kdtreequeryresultsxy(&treexy, &qxy, _state); - kdtreequeryresultstags(&treext, &qtags, _state); - kdtreequeryresultsdistances(&treext, &qr, _state); - *kdterrors = *kdterrors||testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, k, nx, ny, _state); - - /* - * Second step: array is one row larger than needed, so only first - * row is overwritten. Test it. - */ - k = 1; - kx = kdtreequeryknn(&treex, &ptx, k, ae_true, _state); - kxy = kdtreequeryknn(&treexy, &ptx, k, ae_true, _state); - kt = kdtreequeryknn(&treext, &ptx, k, ae_true, _state); - if( (kx!=k||kxy!=k)||kt!=k ) - { - *kdterrors = ae_true; - ae_frame_leave(_state); - return; - } - for(i=0; i<=nx-1; i++) - { - qx.ptr.pp_double[1][i] = _state->v_nan; - } - for(i=0; i<=nx+ny-1; i++) - { - qxy.ptr.pp_double[1][i] = _state->v_nan; - } - qtags.ptr.p_int[1] = 999; - qr.ptr.p_double[1] = _state->v_nan; - kdtreequeryresultsx(&treex, &qx, _state); - kdtreequeryresultsxy(&treexy, &qxy, _state); - kdtreequeryresultstags(&treext, &qtags, _state); - kdtreequeryresultsdistances(&treext, &qr, _state); - *kdterrors = *kdterrors||testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, k, nx, ny, _state); - for(i=0; i<=nx-1; i++) - { - *kdterrors = *kdterrors||!ae_isnan(qx.ptr.pp_double[1][i], _state); - } - for(i=0; i<=nx+ny-1; i++) - { - *kdterrors = *kdterrors||!ae_isnan(qxy.ptr.pp_double[1][i], _state); - } - *kdterrors = *kdterrors||!(qtags.ptr.p_int[1]==999); - *kdterrors = *kdterrors||!ae_isnan(qr.ptr.p_double[1], _state); - } - - /* - * Test reallocation properties: 'interactive' functions must allocate - * new array on each call. - */ - if( n>=2 ) - { - - /* - * On input array is either too small or too large - */ - for(k=1; k<=2; k++) - { - ae_assert(k==1||k==2, "KNN: internal error (unexpected K)!", _state); - kx = kdtreequeryknn(&treex, &ptx, k, ae_true, _state); - kxy = kdtreequeryknn(&treexy, &ptx, k, ae_true, _state); - kt = kdtreequeryknn(&treext, &ptx, k, ae_true, _state); - if( (kx!=k||kxy!=k)||kt!=k ) - { - *kdterrors = ae_true; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&qx, 3-k, 3-k, _state); - ae_matrix_set_length(&qxy, 3-k, 3-k, _state); - ae_vector_set_length(&qtags, 3-k, _state); - ae_vector_set_length(&qr, 3-k, _state); - kdtreequeryresultsxi(&treex, &qx, _state); - kdtreequeryresultsxyi(&treexy, &qxy, _state); - kdtreequeryresultstagsi(&treext, &qtags, _state); - kdtreequeryresultsdistancesi(&treext, &qr, _state); - *kdterrors = *kdterrors||testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, k, nx, ny, _state); - *kdterrors = (*kdterrors||qx.rows!=k)||qx.cols!=nx; - *kdterrors = (*kdterrors||qxy.rows!=k)||qxy.cols!=nx+ny; - *kdterrors = *kdterrors||qtags.cnt!=k; - *kdterrors = *kdterrors||qr.cnt!=k; - } - } - } - - /* - * test general approximate K-NN queries (with self-matches): - * * compare results from different trees (must be equal) and - * check that correct (value,tag) pairs are returned - * * test results from XT tree - let R be radius of query result. - * then all points not in result must be not closer than R/(1+Eps). - */ - for(q=1; q<=qcount; q++) - { - - /* - * Select K: 1..N - */ - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - k = 1+ae_randominteger(n, _state); - } - else - { - k = 1; - } - - /* - * Select Eps - */ - eps = 0.5+ae_randomreal(_state); - - /* - * Select point (either one of the points, or random) - */ - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - i = ae_randominteger(n, _state); - ae_v_move(&ptx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1)); - } - else - { - for(i=0; i<=nx-1; i++) - { - ptx.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - } - - /* - * Test functions which use internal buffer: - * * consistency of results from different queries - * * points in query are IN the R-sphere (or at the boundary), - * and points not in query are outside of the R-sphere (or at the boundary) - * * distances are correct and are ordered - */ - kx = kdtreequeryaknn(&treex, &ptx, k, ae_true, eps, _state); - kxy = kdtreequeryaknn(&treexy, &ptx, k, ae_true, eps, _state); - kt = kdtreequeryaknn(&treext, &ptx, k, ae_true, eps, _state); - if( (kx!=k||kxy!=k)||kt!=k ) - { - *kdterrors = ae_true; - ae_frame_leave(_state); - return; - } - unsetrealmatrix(&qx, _state); - unsetrealmatrix(&qxy, _state); - unsetintegerarray(&qtags, _state); - unsetrealarray(&qr, _state); - kdtreequeryresultsxi(&treex, &qx, _state); - kdtreequeryresultsxyi(&treexy, &qxy, _state); - kdtreequeryresultstagsi(&treext, &qtags, _state); - kdtreequeryresultsdistancesi(&treext, &qr, _state); - *kdterrors = *kdterrors||testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, k, nx, ny, _state); - unsetrealmatrix(&qx, _state); - unsetrealmatrix(&qxy, _state); - unsetintegerarray(&qtags, _state); - unsetrealarray(&qr, _state); - kdtreequeryresultsx(&treex, &qx, _state); - kdtreequeryresultsxy(&treexy, &qxy, _state); - kdtreequeryresultstags(&treext, &qtags, _state); - kdtreequeryresultsdistances(&treext, &qr, _state); - *kdterrors = *kdterrors||testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, k, nx, ny, _state); - for(i=0; i<=n-1; i++) - { - tmpb.ptr.p_bool[i] = ae_true; - } - r = (double)(0); - for(i=0; i<=k-1; i++) - { - tmpb.ptr.p_bool[qtags.ptr.p_int[i]] = ae_false; - ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1)); - ae_v_sub(&tmpx.ptr.p_double[0], 1, &qx.ptr.pp_double[i][0], 1, ae_v_len(0,nx-1)); - r = ae_maxreal(r, testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state), _state); - } - for(i=0; i<=n-1; i++) - { - if( tmpb.ptr.p_bool[i] ) - { - ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1)); - ae_v_sub(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1)); - *kdterrors = *kdterrors||ae_fp_less(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state),r*(1-errtol)/(1+eps)); - } - } - for(i=0; i<=k-2; i++) - { - *kdterrors = *kdterrors||ae_fp_greater(qr.ptr.p_double[i],qr.ptr.p_double[i+1]); - } - for(i=0; i<=k-1; i++) - { - ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1)); - ae_v_sub(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[qtags.ptr.p_int[i]][0], 1, ae_v_len(0,nx-1)); - *kdterrors = *kdterrors||ae_fp_greater(ae_fabs(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state)-qr.ptr.p_double[i], _state),errtol); - } - - /* - * Test functions which use external buffer: - * * create external request buffer, perform buffered request - * * reset status of internal buffer by performing 1-NN query, it is essential - * to test the fact that external buffer is used - * * check consistency of results from different queries - * * check that points in query are IN the R-sphere (or at the boundary), - * and points not in query are outside of the R-sphere (or at the boundary) - * * check that distances are correct and are ordered - */ - kdtreecreaterequestbuffer(&treex, &bufx, _state); - kdtreecreaterequestbuffer(&treexy, &bufxy, _state); - kdtreecreaterequestbuffer(&treext, &bufxt, _state); - kx = kdtreetsqueryaknn(&treex, &bufx, &ptx, k, ae_true, eps, _state); - kxy = kdtreetsqueryaknn(&treexy, &bufxy, &ptx, k, ae_true, eps, _state); - kt = kdtreetsqueryaknn(&treext, &bufxt, &ptx, k, ae_true, eps, _state); - kdtreequeryknn(&treex, &ptx, 1, ae_true, _state); - kdtreequeryknn(&treexy, &ptx, 1, ae_true, _state); - kdtreequeryknn(&treext, &ptx, 1, ae_true, _state); - if( (kx!=k||kxy!=k)||kt!=k ) - { - *kdterrors = ae_true; - ae_frame_leave(_state); - return; - } - unsetrealmatrix(&qx, _state); - unsetrealmatrix(&qxy, _state); - unsetintegerarray(&qtags, _state); - unsetrealarray(&qr, _state); - kdtreetsqueryresultsx(&treex, &bufx, &qx, _state); - kdtreetsqueryresultsxy(&treexy, &bufxy, &qxy, _state); - kdtreetsqueryresultstags(&treext, &bufxt, &qtags, _state); - kdtreetsqueryresultsdistances(&treext, &bufxt, &qr, _state); - *kdterrors = *kdterrors||testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, k, nx, ny, _state); - for(i=0; i<=n-1; i++) - { - tmpb.ptr.p_bool[i] = ae_true; - } - r = (double)(0); - for(i=0; i<=k-1; i++) - { - tmpb.ptr.p_bool[qtags.ptr.p_int[i]] = ae_false; - ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1)); - ae_v_sub(&tmpx.ptr.p_double[0], 1, &qx.ptr.pp_double[i][0], 1, ae_v_len(0,nx-1)); - r = ae_maxreal(r, testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state), _state); - } - for(i=0; i<=n-1; i++) - { - if( tmpb.ptr.p_bool[i] ) - { - ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1)); - ae_v_sub(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1)); - *kdterrors = *kdterrors||ae_fp_less(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state),r*(1-errtol)/(1+eps)); - } - } - for(i=0; i<=k-2; i++) - { - *kdterrors = *kdterrors||ae_fp_greater(qr.ptr.p_double[i],qr.ptr.p_double[i+1]); - } - for(i=0; i<=k-1; i++) - { - ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1)); - ae_v_sub(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[qtags.ptr.p_int[i]][0], 1, ae_v_len(0,nx-1)); - *kdterrors = *kdterrors||ae_fp_greater(ae_fabs(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state)-qr.ptr.p_double[i], _state),errtol); - } - } - - /* - * test ordered/unordered R-NN queries (with self-matches): - * * compare results from different trees (must be equal) and - * check that correct (value,tag) pairs are returned - * * test results from XT tree - let R be radius of query result. - * then all points not in result must be not closer than R. - */ - for(q=1; q<=qcount; q++) - { - - /* - * Use ordering? - */ - orderedrnn = ae_fp_greater(ae_randomreal(_state),0.5); - - /* - * Select R - */ - if( ae_fp_greater(ae_randomreal(_state),0.3) ) - { - r = ae_maxreal(ae_randomreal(_state), ae_machineepsilon, _state); - } - else - { - r = ae_machineepsilon; - } - - /* - * Select point (either one of the points, or random) - */ - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - i = ae_randominteger(n, _state); - ae_v_move(&ptx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1)); - } - else - { - for(i=0; i<=nx-1; i++) - { - ptx.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - } - - /* - * Test functions which use internal buffer: - * * consistency of results from different queries - * * points in query are IN the R-sphere (or at the boundary), - * and points not in query are outside of the R-sphere (or at the boundary) - * * distances are correct and are ordered - */ - if( orderedrnn ) - { - kx = kdtreequeryrnn(&treex, &ptx, r, ae_true, _state); - kxy = kdtreequeryrnn(&treexy, &ptx, r, ae_true, _state); - kt = kdtreequeryrnn(&treext, &ptx, r, ae_true, _state); - } - else - { - kx = kdtreequeryrnnu(&treex, &ptx, r, ae_true, _state); - kxy = kdtreequeryrnnu(&treexy, &ptx, r, ae_true, _state); - kt = kdtreequeryrnnu(&treext, &ptx, r, ae_true, _state); - } - if( kxy!=kx||kt!=kx ) - { - ae_set_error_flag(kdterrors, ae_true, __FILE__, __LINE__, "testnearestneighborunit.ap:648"); - ae_frame_leave(_state); - return; - } - unsetrealmatrix(&qx, _state); - unsetrealmatrix(&qxy, _state); - unsetintegerarray(&qtags, _state); - unsetrealarray(&qr, _state); - kdtreequeryresultsxi(&treex, &qx, _state); - kdtreequeryresultsxyi(&treexy, &qxy, _state); - kdtreequeryresultstagsi(&treext, &qtags, _state); - kdtreequeryresultsdistancesi(&treext, &qr, _state); - ae_set_error_flag(kdterrors, testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, kx, nx, ny, _state), __FILE__, __LINE__, "testnearestneighborunit.ap:659"); - unsetrealmatrix(&qx, _state); - unsetrealmatrix(&qxy, _state); - unsetintegerarray(&qtags, _state); - unsetrealarray(&qr, _state); - kdtreequeryresultsx(&treex, &qx, _state); - kdtreequeryresultsxy(&treexy, &qxy, _state); - kdtreequeryresultstags(&treext, &qtags, _state); - kdtreequeryresultsdistances(&treext, &qr, _state); - ae_set_error_flag(kdterrors, testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, kx, nx, ny, _state), __FILE__, __LINE__, "testnearestneighborunit.ap:668"); - for(i=0; i<=n-1; i++) - { - tmpb.ptr.p_bool[i] = ae_true; - } - for(i=0; i<=kx-1; i++) - { - tmpb.ptr.p_bool[qtags.ptr.p_int[i]] = ae_false; - } - for(i=0; i<=n-1; i++) - { - ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1)); - ae_v_sub(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1)); - if( tmpb.ptr.p_bool[i] ) - { - ae_set_error_flag(kdterrors, ae_fp_less(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state),r*(1-errtol)), __FILE__, __LINE__, "testnearestneighborunit.ap:678"); - } - else - { - ae_set_error_flag(kdterrors, ae_fp_greater(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state),r*(1+errtol)), __FILE__, __LINE__, "testnearestneighborunit.ap:680"); - } - } - if( orderedrnn ) - { - for(i=0; i<=kx-2; i++) - { - ae_set_error_flag(kdterrors, ae_fp_greater(qr.ptr.p_double[i],qr.ptr.p_double[i+1]), __FILE__, __LINE__, "testnearestneighborunit.ap:685"); - } - } - - /* - * Test functions which use external buffer: - * * create external request buffer, perform buffered request - * * reset status of internal buffer by performing 1-NN query, it is essential - * to test the fact that external buffer is used - * * check consistency of results from different queries - * * check that points in query are IN the R-sphere (or at the boundary), - * and points not in query are outside of the R-sphere (or at the boundary) - * * check that distances are correct and are ordered - */ - kdtreecreaterequestbuffer(&treex, &bufx, _state); - kdtreecreaterequestbuffer(&treexy, &bufxy, _state); - kdtreecreaterequestbuffer(&treext, &bufxt, _state); - if( orderedrnn ) - { - kx = kdtreetsqueryrnn(&treex, &bufx, &ptx, r, ae_true, _state); - kxy = kdtreetsqueryrnn(&treexy, &bufxy, &ptx, r, ae_true, _state); - kt = kdtreetsqueryrnn(&treext, &bufxt, &ptx, r, ae_true, _state); - } - else - { - kx = kdtreetsqueryrnnu(&treex, &bufx, &ptx, r, ae_true, _state); - kxy = kdtreetsqueryrnnu(&treexy, &bufxy, &ptx, r, ae_true, _state); - kt = kdtreetsqueryrnnu(&treext, &bufxt, &ptx, r, ae_true, _state); - } - kdtreequeryknn(&treex, &ptx, 1, ae_true, _state); - kdtreequeryknn(&treexy, &ptx, 1, ae_true, _state); - kdtreequeryknn(&treext, &ptx, 1, ae_true, _state); - if( kxy!=kx||kt!=kx ) - { - ae_set_error_flag(kdterrors, ae_true, __FILE__, __LINE__, "testnearestneighborunit.ap:718"); - ae_frame_leave(_state); - return; - } - unsetrealmatrix(&qx, _state); - unsetrealmatrix(&qxy, _state); - unsetintegerarray(&qtags, _state); - unsetrealarray(&qr, _state); - kdtreetsqueryresultsx(&treex, &bufx, &qx, _state); - kdtreetsqueryresultsxy(&treexy, &bufxy, &qxy, _state); - kdtreetsqueryresultstags(&treext, &bufxt, &qtags, _state); - kdtreetsqueryresultsdistances(&treext, &bufxt, &qr, _state); - ae_set_error_flag(kdterrors, testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, kx, nx, ny, _state), __FILE__, __LINE__, "testnearestneighborunit.ap:729"); - for(i=0; i<=n-1; i++) - { - tmpb.ptr.p_bool[i] = ae_true; - } - for(i=0; i<=kx-1; i++) - { - tmpb.ptr.p_bool[qtags.ptr.p_int[i]] = ae_false; - } - for(i=0; i<=n-1; i++) - { - ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1)); - ae_v_sub(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1)); - if( tmpb.ptr.p_bool[i] ) - { - ae_set_error_flag(kdterrors, ae_fp_less(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state),r*(1-errtol)), __FILE__, __LINE__, "testnearestneighborunit.ap:739"); - } - else - { - ae_set_error_flag(kdterrors, ae_fp_greater(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state),r*(1+errtol)), __FILE__, __LINE__, "testnearestneighborunit.ap:741"); - } - } - if( orderedrnn ) - { - for(i=0; i<=kx-2; i++) - { - ae_set_error_flag(kdterrors, ae_fp_greater(qr.ptr.p_double[i],qr.ptr.p_double[i+1]), __FILE__, __LINE__, "testnearestneighborunit.ap:746"); - } - } - } - - /* - * test box queries - */ - ae_vector_set_length(&qmin, nx, _state); - ae_vector_set_length(&qmax, nx, _state); - for(q=1; q<=qcount; q++) - { - - /* - * Test for box exactly equal to one of the points. - * More than one exactly equal point may be found. - * Only thread-safe version is tested. - */ - kdtreecreaterequestbuffer(&treext, &bufxt, _state); - k = ae_randominteger(n, _state); - for(j=0; j<=nx-1; j++) - { - qmin.ptr.p_double[j] = xy->ptr.pp_double[k][j]; - qmax.ptr.p_double[j] = xy->ptr.pp_double[k][j]; - } - kx = kdtreetsquerybox(&treext, &bufxt, &qmin, &qmax, _state); - if( kx<1 ) - { - *kdterrors = ae_true; - ae_frame_leave(_state); - return; - } - unsetrealmatrix(&qx, _state); - unsetintegerarray(&qtags, _state); - unsetrealarray(&qr, _state); - kdtreetsqueryresultsx(&treext, &bufxt, &qx, _state); - kdtreetsqueryresultstags(&treext, &bufxt, &qtags, _state); - kdtreetsqueryresultsdistances(&treext, &bufxt, &qr, _state); - for(i=0; i<=kx-1; i++) - { - ae_set_error_flag(kdterrors, ae_fp_neq(qr.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testnearestneighborunit.ap:783"); - } - for(i=0; i<=kx-1; i++) - { - for(j=0; j<=nx-1; j++) - { - ae_set_error_flag(kdterrors, ae_fp_neq(qx.ptr.pp_double[i][j],xy->ptr.pp_double[k][j]), __FILE__, __LINE__, "testnearestneighborunit.ap:788"); - ae_set_error_flag(kdterrors, ae_fp_neq(qx.ptr.pp_double[i][j],xy->ptr.pp_double[qtags.ptr.p_int[i]][j]), __FILE__, __LINE__, "testnearestneighborunit.ap:789"); - } - } - - /* - * Test for randomly generated box (thread-safe version) - */ - for(j=0; j<=nx-1; j++) - { - qmin.ptr.p_double[j] = boxmin.ptr.p_double[j]+ae_randomreal(_state)*(boxmax.ptr.p_double[j]-boxmin.ptr.p_double[j]); - qmax.ptr.p_double[j] = qmin.ptr.p_double[j]; - v = spread*ae_pow((double)(10), -2*ae_randomreal(_state), _state); - qmin.ptr.p_double[j] = qmin.ptr.p_double[j]-v; - qmax.ptr.p_double[j] = qmax.ptr.p_double[j]+v; - } - kx = kdtreetsquerybox(&treext, &bufxt, &qmin, &qmax, _state); - unsetrealmatrix(&qx, _state); - unsetintegerarray(&qtags, _state); - unsetrealarray(&qr, _state); - kdtreetsqueryresultsx(&treext, &bufxt, &qx, _state); - kdtreetsqueryresultstags(&treext, &bufxt, &qtags, _state); - kdtreetsqueryresultsdistances(&treext, &bufxt, &qr, _state); - for(i=0; i<=kx-1; i++) - { - ae_set_error_flag(kdterrors, ae_fp_neq(qr.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testnearestneighborunit.ap:812"); - } - for(i=0; i<=n-1; i++) - { - tmpb.ptr.p_bool[i] = ae_false; - } - for(i=0; i<=kx-1; i++) - { - tmpb.ptr.p_bool[qtags.ptr.p_int[i]] = ae_true; - } - for(i=0; i<=n-1; i++) - { - inthebox = ae_true; - for(j=0; j<=nx-1; j++) - { - inthebox = inthebox&&ae_fp_greater_eq(xy->ptr.pp_double[i][j],qmin.ptr.p_double[j]); - inthebox = inthebox&&ae_fp_less_eq(xy->ptr.pp_double[i][j],qmax.ptr.p_double[j]); - } - if( tmpb.ptr.p_bool[i] ) - { - ae_set_error_flag(kdterrors, !inthebox, __FILE__, __LINE__, "testnearestneighborunit.ap:826"); - } - else - { - ae_set_error_flag(kdterrors, inthebox, __FILE__, __LINE__, "testnearestneighborunit.ap:828"); - } - } - - /* - * Test for randomly generated box (non-thread-safe version) - */ - for(j=0; j<=nx-1; j++) - { - qmin.ptr.p_double[j] = boxmin.ptr.p_double[j]+ae_randomreal(_state)*(boxmax.ptr.p_double[j]-boxmin.ptr.p_double[j]); - qmax.ptr.p_double[j] = qmin.ptr.p_double[j]; - v = spread*ae_pow((double)(10), -2*ae_randomreal(_state), _state); - qmin.ptr.p_double[j] = qmin.ptr.p_double[j]-v; - qmax.ptr.p_double[j] = qmax.ptr.p_double[j]+v; - } - kx = kdtreequerybox(&treext, &qmin, &qmax, _state); - unsetrealmatrix(&qx, _state); - unsetintegerarray(&qtags, _state); - unsetrealarray(&qr, _state); - kdtreequeryresultsx(&treext, &qx, _state); - kdtreequeryresultstags(&treext, &qtags, _state); - kdtreequeryresultsdistances(&treext, &qr, _state); - for(i=0; i<=kx-1; i++) - { - ae_set_error_flag(kdterrors, ae_fp_neq(qr.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testnearestneighborunit.ap:850"); - } - for(i=0; i<=n-1; i++) - { - tmpb.ptr.p_bool[i] = ae_false; - } - for(i=0; i<=kx-1; i++) - { - tmpb.ptr.p_bool[qtags.ptr.p_int[i]] = ae_true; - } - for(i=0; i<=n-1; i++) - { - inthebox = ae_true; - for(j=0; j<=nx-1; j++) - { - inthebox = inthebox&&ae_fp_greater_eq(xy->ptr.pp_double[i][j],qmin.ptr.p_double[j]); - inthebox = inthebox&&ae_fp_less_eq(xy->ptr.pp_double[i][j],qmax.ptr.p_double[j]); - } - if( tmpb.ptr.p_bool[i] ) - { - ae_set_error_flag(kdterrors, !inthebox, __FILE__, __LINE__, "testnearestneighborunit.ap:864"); - } - else - { - ae_set_error_flag(kdterrors, inthebox, __FILE__, __LINE__, "testnearestneighborunit.ap:866"); - } - } - } - - /* - * Test self-matching: - * * self-match - nearest neighbor of each point in XY is the point itself - * * no self-match - nearest neighbor is NOT the point itself - */ - if( n>1 ) - { - - /* - * test for N=1 have non-general form, but it is not really needed - */ - for(task=0; task<=1; task++) - { - for(i=0; i<=n-1; i++) - { - ae_v_move(&ptx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1)); - kx = kdtreequeryknn(&treex, &ptx, 1, task==0, _state); - kdtreequeryresultsxi(&treex, &qx, _state); - if( kx!=1 ) - { - *kdterrors = ae_true; - ae_frame_leave(_state); - return; - } - isequal = ae_true; - for(j=0; j<=nx-1; j++) - { - isequal = isequal&&ae_fp_eq(qx.ptr.pp_double[0][j],ptx.ptr.p_double[j]); - } - if( task==0 ) - { - *kdterrors = *kdterrors||!isequal; - } - else - { - *kdterrors = *kdterrors||isequal; - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Testing serialization of KD trees - -This function sets Err to True on errors, but leaves it unchanged on success -*************************************************************************/ -static void testnearestneighborunit_testkdtreeserialization(ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t nx; - ae_int_t ny; - ae_int_t normtype; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t q; - ae_matrix xy; - ae_vector x; - ae_vector tags; - ae_vector qsizes; - double threshold; - kdtree tree0; - kdtree tree1; - ae_int_t k0; - ae_int_t k1; - ae_matrix xy0; - ae_matrix xy1; - ae_vector tags0; - ae_vector tags1; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&x, 0, sizeof(x)); - memset(&tags, 0, sizeof(tags)); - memset(&qsizes, 0, sizeof(qsizes)); - memset(&tree0, 0, sizeof(tree0)); - memset(&tree1, 0, sizeof(tree1)); - memset(&xy0, 0, sizeof(xy0)); - memset(&xy1, 0, sizeof(xy1)); - memset(&tags0, 0, sizeof(tags0)); - memset(&tags1, 0, sizeof(tags1)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tags, 0, DT_INT, _state, ae_true); - ae_vector_init(&qsizes, 0, DT_INT, _state, ae_true); - _kdtree_init(&tree0, _state, ae_true); - _kdtree_init(&tree1, _state, ae_true); - ae_matrix_init(&xy0, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy1, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tags0, 0, DT_INT, _state, ae_true); - ae_vector_init(&tags1, 0, DT_INT, _state, ae_true); - - threshold = 100*ae_machineepsilon; - - /* - * different N, NX, NY, NormType - */ - n = 1; - while(n<=51) - { - - /* - * prepare array with query sizes - */ - ae_vector_set_length(&qsizes, 4, _state); - qsizes.ptr.p_int[0] = 1; - qsizes.ptr.p_int[1] = ae_minint(2, n, _state); - qsizes.ptr.p_int[2] = ae_minint(4, n, _state); - qsizes.ptr.p_int[3] = n; - - /* - * different NX/NY/NormType - */ - for(nx=1; nx<=2; nx++) - { - for(ny=0; ny<=2; ny++) - { - for(normtype=0; normtype<=2; normtype++) - { - - /* - * Prepare data - */ - ae_matrix_set_length(&xy, n, nx+ny, _state); - ae_vector_set_length(&tags, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx+ny-1; j++) - { - xy.ptr.pp_double[i][j] = ae_randomreal(_state); - } - tags.ptr.p_int[i] = ae_randominteger(100, _state); - } - - /* - * Build tree, pass it through serializer - */ - kdtreebuildtagged(&xy, &tags, n, nx, ny, normtype, &tree0, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - kdtreealloc(&_local_serializer, &tree0, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - kdtreeserialize(&_local_serializer, &tree0, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - kdtreeunserialize(&_local_serializer, &tree1, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - - /* - * For each point of XY we make queries with different sizes - */ - ae_vector_set_length(&x, nx, _state); - for(k=0; k<=n-1; k++) - { - for(q=0; q<=qsizes.cnt-1; q++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xy.ptr.pp_double[k][0], 1, ae_v_len(0,nx-1)); - k0 = kdtreequeryknn(&tree0, &x, qsizes.ptr.p_int[q], ae_true, _state); - k1 = kdtreequeryknn(&tree1, &x, qsizes.ptr.p_int[q], ae_true, _state); - if( k0!=k1 ) - { - *err = ae_true; - ae_frame_leave(_state); - return; - } - kdtreequeryresultsxy(&tree0, &xy0, _state); - kdtreequeryresultsxy(&tree1, &xy1, _state); - for(i=0; i<=k0-1; i++) - { - for(j=0; j<=nx+ny-1; j++) - { - if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[i][j]-xy1.ptr.pp_double[i][j], _state),threshold) ) - { - *err = ae_true; - ae_frame_leave(_state); - return; - } - } - } - kdtreequeryresultstags(&tree0, &tags0, _state); - kdtreequeryresultstags(&tree1, &tags1, _state); - for(i=0; i<=k0-1; i++) - { - if( tags0.ptr.p_int[i]!=tags1.ptr.p_int[i] ) - { - *err = ae_true; - ae_frame_leave(_state); - return; - } - } - } - } - } - } - } - - /* - * Next N - */ - n = n+25; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests different special cases: -* Kd-tree for a zero number of points -* Kd-tree for array with a lot of duplicates (early versions of ALGLIB - raised stack overflow on such datasets) - -It returns True on errors, False on success. -*************************************************************************/ -static ae_bool testnearestneighborunit_testspecialcases(ae_state *_state) -{ - ae_frame _frame_block; - kdtree kdt; - ae_matrix xy; - ae_vector tags; - ae_vector x; - ae_int_t n; - ae_int_t nk; - ae_int_t nx; - ae_int_t ny; - ae_int_t normtype; - ae_int_t i; - ae_int_t j; - double v; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&kdt, 0, sizeof(kdt)); - memset(&xy, 0, sizeof(xy)); - memset(&tags, 0, sizeof(tags)); - memset(&x, 0, sizeof(x)); - _kdtree_init(&kdt, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tags, 0, DT_INT, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - - result = ae_false; - for(nx=1; nx<=3; nx++) - { - for(ny=0; ny<=3; ny++) - { - for(normtype=0; normtype<=2; normtype++) - { - - /* - * Build tree - */ - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - kdtreebuildtagged(&xy, &tags, 0, nx, ny, normtype, &kdt, _state); - } - else - { - kdtreebuild(&xy, 0, nx, ny, normtype, &kdt, _state); - } - - /* - * Test different queries - */ - ae_vector_set_length(&x, nx, _state); - for(i=0; i<=nx-1; i++) - { - x.ptr.p_double[i] = ae_randomreal(_state); - } - result = result||kdtreequeryknn(&kdt, &x, 1, ae_true, _state)>0; - result = result||kdtreequeryrnn(&kdt, &x, 1.0E6, ae_true, _state)>0; - result = result||kdtreequeryaknn(&kdt, &x, 1, ae_true, 2.0, _state)>0; - } - } - } - - /* - * Ability to handle array with a lot of duplicates without causing - * stack overflow. - * - * Two situations are handled: - * * array where ALL N elements are duplicates - * * array where there are NK distinct elements and N-NK duplicates - */ - nx = 2; - ny = 1; - n = 100000; - nk = 100; - v = ae_randomreal(_state); - ae_matrix_set_length(&xy, n, nx+ny, _state); - ae_vector_set_length(&x, nx, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx+ny-1; j++) - { - xy.ptr.pp_double[i][j] = v; - } - } - kdtreebuild(&xy, n, nx, ny, 2, &kdt, _state); - for(j=0; j<=nx-1; j++) - { - x.ptr.p_double[j] = v; - } - result = result||kdtreequeryrnn(&kdt, &x, 0.0001, ae_true, _state)!=n; - for(i=0; i<=nk-1; i++) - { - for(j=0; j<=nx+ny-1; j++) - { - xy.ptr.pp_double[i][j] = ae_randomreal(_state); - } - } - kdtreebuild(&xy, n, nx, ny, 2, &kdt, _state); - result = result||kdtreequeryrnn(&kdt, &x, 0.0001, ae_true, _state)=bins.cnt ) - { - k = bins.cnt-1; - } - bins.ptr.p_int[k] = bins.ptr.p_int[k]+1; - } - for(i=0; i<=bins.cnt-1; i++) - { - ae_set_error_flag(&unit2errors, ae_fp_less((double)(bins.ptr.p_int[i]),0.9*n/bins.cnt)||ae_fp_greater((double)(bins.ptr.p_int[i]),1.1*n/bins.cnt), __FILE__, __LINE__, "testhqrndunit.ap:301"); - } - - /* - * Test exponential - */ - testhqrndunit_unsetstate(&state, _state); - hqrndrandomize(&state, _state); - expsigmaerr = (double)(0); - lambdav = 2+5*ae_randomreal(_state); - for(i=0; i<=samplesize-1; i++) - { - x.ptr.p_double[i] = hqrndexponential(&state, lambdav, _state); - } - for(i=0; i<=samplesize-1; i++) - { - uierrors = uierrors||ae_fp_less(x.ptr.p_double[i],(double)(0)); - } - testhqrndunit_calculatemv(&x, samplesize, &mean, &means, &stddev, &stddevs, _state); - if( ae_fp_neq(means,(double)(0)) ) - { - expsigmaerr = ae_maxreal(expsigmaerr, ae_fabs((mean-1.0/lambdav)/means, _state), _state); - } - else - { - experrors = ae_true; - } - if( ae_fp_neq(stddevs,(double)(0)) ) - { - expsigmaerr = ae_maxreal(expsigmaerr, ae_fabs((stddev-1.0/lambdav)/stddevs, _state), _state); - } - else - { - experrors = ae_true; - } - experrors = experrors||ae_fp_greater(expsigmaerr,sigmathreshold); - - /* - *Discrete/Continuous tests - */ - discreteerr = hqrnddiscretetest(ae_true, _state); - continuouserr = hqrndcontinuoustest(ae_true, _state); - - /* - * Final report - */ - waserrors = ((((((seederrors||urerrors)||uierrors)||normerrors)||unit2errors)||experrors)||discreteerr)||continuouserr; - if( !silent ) - { - printf("RNG TEST\n"); - printf("SEED TEST: "); - if( !seederrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("UNIFORM CONTINUOUS: "); - if( !urerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("UNIFORM INTEGER: "); - if( !uierrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("NORMAL: "); - if( !normerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("UNIT2: "); - if( !unit2errors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("EXPONENTIAL: "); - if( !experrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("DISCRETE: "); - if( !discreteerr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("CONTINUOUS: "); - if( !continuouserr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST SUMMARY: FAILED\n"); - } - else - { - printf("TEST SUMMARY: PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Function for test HQRNDContinuous function -*************************************************************************/ -ae_bool hqrndcontinuoustest(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_vector sample; - ae_vector bins; - ae_vector binbounds; - ae_int_t nb; - ae_int_t samplesize; - hqrndstate state; - ae_int_t xp; - ae_int_t i; - ae_int_t j; - double v; - double sigma; - double sigmamax; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&sample, 0, sizeof(sample)); - memset(&bins, 0, sizeof(bins)); - memset(&binbounds, 0, sizeof(binbounds)); - memset(&state, 0, sizeof(state)); - ae_vector_init(&sample, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bins, 0, DT_INT, _state, ae_true); - ae_vector_init(&binbounds, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&state, _state, ae_true); - - result = ae_false; - - /* - * Test for sample size equal to 1 - */ - ae_vector_set_length(&sample, 1, _state); - sample.ptr.p_double[0] = ae_randomreal(_state); - hqrndrandomize(&state, _state); - result = result||ae_fp_neq(hqrndcontinuous(&state, &sample, 1, _state),sample.ptr.p_double[0]); - - /* - * Test for larger samples - */ - xp = 100000; - sigmamax = 10.0; - for(samplesize=2; samplesize<=5; samplesize++) - { - - /* - * 1. Generate random sample with SampleSize points - * 2. Generate NB=3*(SampleSize-1) bins, with bounds as prescribed by (BinBounds[I],BinBounds[I+1]). - * Bin bounds are generated in such a way that value can fall into any bin with same probability - * 3. Generate many random values - * 4. Calculate number of values which fall into each bin - * 5. Bins[I] should have binomial distribution with mean XP/NB and - * variance XP*(1/NB)*(1-1/NB) - */ - nb = 3*(samplesize-1); - sigma = ae_sqrt(xp*((double)1/(double)nb)*(1-(double)1/(double)nb), _state); - ae_vector_set_length(&sample, samplesize, _state); - sample.ptr.p_double[0] = 2*ae_randomreal(_state)-1; - for(i=0; i<=samplesize-2; i++) - { - sample.ptr.p_double[i+1] = sample.ptr.p_double[i]+0.1+ae_randomreal(_state); - } - ae_vector_set_length(&bins, nb, _state); - ae_vector_set_length(&binbounds, nb+1, _state); - for(i=0; i<=samplesize-2; i++) - { - bins.ptr.p_int[3*i+0] = 0; - bins.ptr.p_int[3*i+1] = 0; - bins.ptr.p_int[3*i+2] = 0; - binbounds.ptr.p_double[3*i+0] = sample.ptr.p_double[i]; - binbounds.ptr.p_double[3*i+1] = sample.ptr.p_double[i]+(sample.ptr.p_double[i+1]-sample.ptr.p_double[i])/3; - binbounds.ptr.p_double[3*i+2] = sample.ptr.p_double[i]+(sample.ptr.p_double[i+1]-sample.ptr.p_double[i])*2/3; - } - binbounds.ptr.p_double[nb] = sample.ptr.p_double[samplesize-1]; - hqrndrandomize(&state, _state); - for(i=0; i<=xp-1; i++) - { - v = hqrndcontinuous(&state, &sample, samplesize, _state); - for(j=0; j<=nb-1; j++) - { - if( ae_fp_greater(v,binbounds.ptr.p_double[j])&&ae_fp_less(v,binbounds.ptr.p_double[j+1]) ) - { - bins.ptr.p_int[j] = bins.ptr.p_int[j]+1; - break; - } - } - } - for(i=0; i<=nb-1; i++) - { - result = result||ae_fp_greater(ae_fabs(bins.ptr.p_int[i]-(double)xp/(double)nb, _state),sigma*sigmamax); - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Function for test HQRNDContinuous function -*************************************************************************/ -ae_bool hqrnddiscretetest(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_vector sample; - double sigma; - double sigmathreshold; - double tsample; - double max; - double min; - ae_int_t i; - ae_int_t j; - ae_int_t s1; - ae_int_t s2; - ae_int_t binscount; - ae_int_t xp; - ae_vector nn; - hqrndstate state; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&sample, 0, sizeof(sample)); - memset(&nn, 0, sizeof(nn)); - memset(&state, 0, sizeof(state)); - ae_vector_init(&sample, 0, DT_REAL, _state, ae_true); - ae_vector_init(&nn, 0, DT_INT, _state, ae_true); - _hqrndstate_init(&state, _state, ae_true); - - - /* - * We test that all values from discrete sample are generated with same probability. - * To do this, we generate random values many times, then we calculate actual probabilities - * and compare them with theoretical ones. - */ - max = (double)(100); - min = (double)(-100); - xp = 100000; - sigmathreshold = 10.0; - for(binscount=1; binscount<=5; binscount++) - { - sigma = ae_sqrt(xp*((double)1/(double)binscount)*(1-(double)1/(double)binscount), _state); - ae_vector_set_length(&nn, binscount, _state); - for(i=0; i<=binscount-1; i++) - { - nn.ptr.p_int[i] = 0; - } - ae_vector_set_length(&sample, binscount, _state); - sample.ptr.p_double[0] = (max-min)*ae_randomreal(_state)+min; - for(i=1; i<=binscount-1; i++) - { - sample.ptr.p_double[i] = sample.ptr.p_double[i-1]+max*ae_randomreal(_state)+0.001; - } - s1 = 1+ae_randominteger(32000, _state); - s2 = 1+ae_randominteger(32000, _state); - hqrndseed(s1, s2, &state, _state); - for(i=0; i<=xp-1; i++) - { - tsample = hqrnddiscrete(&state, &sample, binscount, _state); - for(j=0; j<=binscount-1; j++) - { - if( ae_fp_eq(tsample,sample.ptr.p_double[j]) ) - { - nn.ptr.p_int[j] = nn.ptr.p_int[j]+1; - break; - } - } - } - for(i=0; i<=binscount-1; i++) - { - if( ae_fp_less((double)(nn.ptr.p_int[i]),(double)xp/(double)binscount-sigmathreshold*sigma)||ae_fp_greater((double)(nn.ptr.p_int[i]),(double)xp/(double)binscount+sigmathreshold*sigma) ) - { - if( !silent ) - { - printf("HQRNDDiscreteTest::ErrorReport::\n"); - printf("nn[%0d]=%0d;\n xp/BinsCount=%0.5f;\n C*sigma=%0.5f\n", - (int)(i), - (int)(nn.ptr.p_int[i]), - (double)((double)xp/(double)binscount), - (double)(sigmathreshold*sigma)); - printf("HQRNDDiscreteTest: test is FAILED!\n"); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - if( !silent ) - { - printf("HQRNDDiscreteTest: test is OK.\n"); - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -static void testhqrndunit_calculatemv(/* Real */ ae_vector* x, - ae_int_t n, - double* mean, - double* means, - double* stddev, - double* stddevs, - ae_state *_state) -{ - ae_int_t i; - double v1; - double v2; - double variance; - - *mean = 0; - *means = 0; - *stddev = 0; - *stddevs = 0; - - *mean = (double)(0); - *means = (double)(1); - *stddev = (double)(0); - *stddevs = (double)(1); - variance = (double)(0); - if( n<=1 ) - { - return; - } - - /* - * Mean - */ - for(i=0; i<=n-1; i++) - { - *mean = *mean+x->ptr.p_double[i]; - } - *mean = *mean/n; - - /* - * Variance (using corrected two-pass algorithm) - */ - if( n!=1 ) - { - v1 = (double)(0); - for(i=0; i<=n-1; i++) - { - v1 = v1+ae_sqr(x->ptr.p_double[i]-(*mean), _state); - } - v2 = (double)(0); - for(i=0; i<=n-1; i++) - { - v2 = v2+(x->ptr.p_double[i]-(*mean)); - } - v2 = ae_sqr(v2, _state)/n; - variance = (v1-v2)/(n-1); - if( ae_fp_less(variance,(double)(0)) ) - { - variance = (double)(0); - } - *stddev = ae_sqrt(variance, _state); - } - - /* - * Errors - */ - *means = *stddev/ae_sqrt((double)(n), _state); - *stddevs = *stddev*ae_sqrt((double)(2), _state)/ae_sqrt((double)(n-1), _state); -} - - -/************************************************************************* -Unsets HQRNDState structure -*************************************************************************/ -static void testhqrndunit_unsetstate(hqrndstate* state, ae_state *_state) -{ - - - state->s1 = 0; - state->s2 = 0; - state->magicv = 0; -} - - - - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testodesolver(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t passcount; - ae_bool curerrors; - ae_bool rkckerrors; - ae_bool waserrors; - ae_vector xtbl; - ae_matrix ytbl; - odesolverreport rep; - ae_vector xg; - ae_vector y; - double h; - double eps; - ae_int_t solver; - ae_int_t pass; - ae_int_t mynfev; - double v; - ae_int_t m; - ae_int_t m2; - ae_int_t i; - double err; - odesolverstate state; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&xtbl, 0, sizeof(xtbl)); - memset(&ytbl, 0, sizeof(ytbl)); - memset(&rep, 0, sizeof(rep)); - memset(&xg, 0, sizeof(xg)); - memset(&y, 0, sizeof(y)); - memset(&state, 0, sizeof(state)); - ae_vector_init(&xtbl, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ytbl, 0, 0, DT_REAL, _state, ae_true); - _odesolverreport_init(&rep, _state, ae_true); - ae_vector_init(&xg, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - _odesolverstate_init(&state, _state, ae_true); - - rkckerrors = ae_false; - waserrors = ae_false; - passcount = 10; - - /* - * simple test: just A*sin(x)+B*cos(x) - */ - ae_assert(passcount>=2, "Assertion failed", _state); - for(pass=0; pass<=passcount-1; pass++) - { - for(solver=0; solver<=0; solver++) - { - - /* - * prepare - */ - h = 1.0E-2; - eps = 1.0E-5; - if( pass%2==0 ) - { - eps = -eps; - } - ae_vector_set_length(&y, 2, _state); - for(i=0; i<=1; i++) - { - y.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - m = 2+ae_randominteger(10, _state); - ae_vector_set_length(&xg, m, _state); - xg.ptr.p_double[0] = (m-1)*ae_randomreal(_state); - for(i=1; i<=m-1; i++) - { - xg.ptr.p_double[i] = xg.ptr.p_double[i-1]+ae_randomreal(_state); - } - v = 2*ae_pi/(xg.ptr.p_double[m-1]-xg.ptr.p_double[0]); - ae_v_muld(&xg.ptr.p_double[0], 1, ae_v_len(0,m-1), v); - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - ae_v_muld(&xg.ptr.p_double[0], 1, ae_v_len(0,m-1), -1); - } - mynfev = 0; - - /* - * choose solver - */ - if( solver==0 ) - { - odesolverrkck(&y, 2, &xg, m, eps, h, &state, _state); - } - - /* - * solve - */ - while(odesolveriteration(&state, _state)) - { - state.dy.ptr.p_double[0] = state.y.ptr.p_double[1]; - state.dy.ptr.p_double[1] = -state.y.ptr.p_double[0]; - mynfev = mynfev+1; - } - odesolverresults(&state, &m2, &xtbl, &ytbl, &rep, _state); - - /* - * check results - */ - curerrors = ae_false; - if( rep.terminationtype<=0 ) - { - curerrors = ae_true; - } - else - { - curerrors = curerrors||m2!=m; - err = (double)(0); - for(i=0; i<=m-1; i++) - { - err = ae_maxreal(err, ae_fabs(ytbl.ptr.pp_double[i][0]-(y.ptr.p_double[0]*ae_cos(xtbl.ptr.p_double[i]-xtbl.ptr.p_double[0], _state)+y.ptr.p_double[1]*ae_sin(xtbl.ptr.p_double[i]-xtbl.ptr.p_double[0], _state)), _state), _state); - err = ae_maxreal(err, ae_fabs(ytbl.ptr.pp_double[i][1]-(-y.ptr.p_double[0]*ae_sin(xtbl.ptr.p_double[i]-xtbl.ptr.p_double[0], _state)+y.ptr.p_double[1]*ae_cos(xtbl.ptr.p_double[i]-xtbl.ptr.p_double[0], _state)), _state), _state); - } - curerrors = curerrors||ae_fp_greater(err,10*ae_fabs(eps, _state)); - curerrors = curerrors||mynfev!=rep.nfev; - } - if( solver==0 ) - { - rkckerrors = rkckerrors||curerrors; - } - } - } - - /* - * another test: - * - * y(0) = 0 - * dy/dx = f(x,y) - * f(x,y) = 0, x<1 - * x-1, x>=1 - * - * with BOTH absolute and fractional tolerances. - * Starting from zero will be real challenge for - * fractional tolerance. - */ - ae_assert(passcount>=2, "Assertion failed", _state); - for(pass=0; pass<=passcount-1; pass++) - { - h = 1.0E-4; - eps = 1.0E-4; - if( pass%2==0 ) - { - eps = -eps; - } - ae_vector_set_length(&y, 1, _state); - y.ptr.p_double[0] = (double)(0); - m = 21; - ae_vector_set_length(&xg, m, _state); - for(i=0; i<=m-1; i++) - { - xg.ptr.p_double[i] = (double)(2*i)/(double)(m-1); - } - mynfev = 0; - odesolverrkck(&y, 1, &xg, m, eps, h, &state, _state); - while(odesolveriteration(&state, _state)) - { - state.dy.ptr.p_double[0] = ae_maxreal(state.x-1, (double)(0), _state); - mynfev = mynfev+1; - } - odesolverresults(&state, &m2, &xtbl, &ytbl, &rep, _state); - if( rep.terminationtype<=0 ) - { - rkckerrors = ae_true; - } - else - { - rkckerrors = rkckerrors||m2!=m; - err = (double)(0); - for(i=0; i<=m-1; i++) - { - err = ae_maxreal(err, ae_fabs(ytbl.ptr.pp_double[i][0]-ae_sqr(ae_maxreal(xg.ptr.p_double[i]-1, (double)(0), _state), _state)/2, _state), _state); - } - rkckerrors = rkckerrors||ae_fp_greater(err,ae_fabs(eps, _state)); - rkckerrors = rkckerrors||mynfev!=rep.nfev; - } - } - - /* - * end - */ - waserrors = rkckerrors; - if( !silent ) - { - printf("TESTING ODE SOLVER\n"); - printf("* RK CASH-KARP: "); - if( rkckerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - - -static void testsparseunit_initgenerator(ae_int_t m, - ae_int_t n, - ae_int_t matkind, - ae_int_t triangle, - sparsegenerator* g, - ae_state *_state); -static ae_bool testsparseunit_generatenext(sparsegenerator* g, - /* Real */ ae_matrix* da, - sparsematrix* sa, - ae_state *_state); -static void testsparseunit_createrandom(ae_int_t m, - ae_int_t n, - ae_int_t pkind, - ae_int_t ckind, - ae_int_t p0, - ae_int_t p1, - /* Real */ ae_matrix* da, - sparsematrix* sa, - ae_state *_state); -static ae_bool testsparseunit_enumeratetest(ae_state *_state); -static ae_bool testsparseunit_rewriteexistingtest(ae_state *_state); -static void testsparseunit_testgetrow(ae_bool* err, ae_state *_state); -static ae_bool testsparseunit_testconvertsm(ae_state *_state); -static ae_bool testsparseunit_testgcmatrixtype(ae_state *_state); - - - - - -ae_bool testsparse(ae_bool silent, ae_state *_state) -{ - ae_bool waserrors; - ae_bool basicerrors; - ae_bool linearerrors; - ae_bool basicrnderrors; - ae_bool level2unsymmetricerrors; - ae_bool level2symmetricerrors; - ae_bool level2triangularerrors; - ae_bool level3unsymmetricerrors; - ae_bool level3symmetricerrors; - ae_bool symmetricpermerrors; - ae_bool linearserrors; - ae_bool linearmmerrors; - ae_bool linearsmmerrors; - ae_bool getrowerrors; - ae_bool copyerrors; - ae_bool basiccopyerrors; - ae_bool enumerateerrors; - ae_bool rewriteexistingerr; - ae_bool skserrors; - ae_bool crserrors; - ae_bool result; - - - getrowerrors = ae_false; - crserrors = ae_false; - skserrors = skstest(_state); - crstest(&crserrors, _state); - basicerrors = basicfunctest(_state)||testsparseunit_testgcmatrixtype(_state); - basicrnderrors = basicfuncrandomtest(_state); - linearerrors = linearfunctionstest(_state); - level2unsymmetricerrors = testlevel2unsymmetric(_state); - level2symmetricerrors = testlevel2symmetric(_state); - level2triangularerrors = testlevel2triangular(_state); - level3unsymmetricerrors = testlevel3unsymmetric(_state); - level3symmetricerrors = testlevel3symmetric(_state); - symmetricpermerrors = testsymmetricperm(_state); - linearserrors = linearfunctionsstest(_state); - linearmmerrors = linearfunctionsmmtest(_state); - linearsmmerrors = linearfunctionssmmtest(_state); - copyerrors = copyfunctest(ae_true, _state)||testsparseunit_testconvertsm(_state); - basiccopyerrors = basiccopyfunctest(ae_true, _state); - enumerateerrors = testsparseunit_enumeratetest(_state); - rewriteexistingerr = testsparseunit_rewriteexistingtest(_state); - testsparseunit_testgetrow(&getrowerrors, _state); - - /* - * report - */ - waserrors = (((((((((((((((((skserrors||crserrors)||getrowerrors)||basicerrors)||linearerrors)||basicrnderrors)||level2unsymmetricerrors)||level2symmetricerrors)||level2triangularerrors)||level3unsymmetricerrors)||level3symmetricerrors)||symmetricpermerrors)||linearserrors)||linearmmerrors)||linearsmmerrors)||copyerrors)||basiccopyerrors)||enumerateerrors)||rewriteexistingerr; - if( !silent ) - { - printf("TESTING SPARSE\n"); - printf("STORAGE FORMAT SPECIFICS:\n"); - printf("* SKS: "); - if( !skserrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* CRS: "); - if( !crserrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("OPERATIONS:\n"); - printf("* GETROW: "); - if( !getrowerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("BLAS:\n"); - printf("* LEVEL 2 GENERAL: "); - if( !level2unsymmetricerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* LEVEL 2 SYMMETRIC: "); - if( !level2symmetricerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* LEVEL 2 TRIANGULAR: "); - if( !level2triangularerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* LEVEL 3 GENERAL: "); - if( !level3unsymmetricerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* LEVEL 3 SYMMETRIC: "); - if( !level3symmetricerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* PERMUTATIONS (SYMMETRIC): "); - if( !symmetricpermerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("BASIC TEST: "); - if( !basicerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("COPY TEST: "); - if( !copyerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("BASIC_COPY TEST: "); - if( !basiccopyerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("BASIC_RND TEST: "); - if( !basicrnderrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("LINEAR TEST: "); - if( !linearerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("LINEAR TEST FOR SYMMETRIC MATRICES: "); - if( !linearserrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("LINEAR MxM TEST: "); - if( !linearmmerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("LINEAR MxM TEST FOR SYMMETRIC MATRICES: "); - if( !linearsmmerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("ENUMERATE TEST: "); - if( !enumerateerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("REWRITE EXISTING TEST: "); - if( !rewriteexistingerr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - return result; -} - - -/************************************************************************* -Function for testing basic SKS functional. -Returns True on errors, False on success. - - -- ALGLIB PROJECT -- - Copyright 16.01.1014 by Bochkanov Sergey -*************************************************************************/ -ae_bool skstest(ae_state *_state) -{ - ae_frame _frame_block; - sparsematrix s0; - sparsematrix s1; - sparsematrix s2; - sparsematrix s3; - sparsematrix s4; - sparsematrix s5; - sparsematrix s6; - ae_int_t n; - ae_int_t nz; - double pnz; - ae_int_t i; - ae_int_t j; - ae_int_t t0; - ae_int_t t1; - ae_matrix a; - ae_matrix wasenumerated; - ae_vector d; - ae_vector u; - hqrndstate rs; - double v0; - double v1; - ae_int_t uppercnt; - ae_int_t lowercnt; - ae_int_t bw; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s0, 0, sizeof(s0)); - memset(&s1, 0, sizeof(s1)); - memset(&s2, 0, sizeof(s2)); - memset(&s3, 0, sizeof(s3)); - memset(&s4, 0, sizeof(s4)); - memset(&s5, 0, sizeof(s5)); - memset(&s6, 0, sizeof(s6)); - memset(&a, 0, sizeof(a)); - memset(&wasenumerated, 0, sizeof(wasenumerated)); - memset(&d, 0, sizeof(d)); - memset(&u, 0, sizeof(u)); - memset(&rs, 0, sizeof(rs)); - _sparsematrix_init(&s0, _state, ae_true); - _sparsematrix_init(&s1, _state, ae_true); - _sparsematrix_init(&s2, _state, ae_true); - _sparsematrix_init(&s3, _state, ae_true); - _sparsematrix_init(&s4, _state, ae_true); - _sparsematrix_init(&s5, _state, ae_true); - _sparsematrix_init(&s6, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&wasenumerated, 0, 0, DT_BOOL, _state, ae_true); - ae_vector_init(&d, 0, DT_INT, _state, ae_true); - ae_vector_init(&u, 0, DT_INT, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - result = ae_false; - hqrndrandomize(&rs, _state); - for(n=1; n<=20; n++) - { - nz = n*n-n; - for(;;) - { - - /* - * Generate N*N matrix where probability of non-diagonal element - * being non-zero is PNZ. We also generate D and U - subdiagonal - * and superdiagonal profile sizes. - * - * Create matrix with either general SKS or banded SKS constructor function - */ - if( n>1 ) - { - pnz = (double)nz/(double)(n*n-n); - } - else - { - pnz = 1.0; - } - ae_vector_set_length(&d, n, _state); - ae_vector_set_length(&u, n, _state); - ae_matrix_set_length(&a, n, n, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - - /* - * Test SparseCreateSKS() functionality - */ - for(i=0; i<=n-1; i++) - { - d.ptr.p_int[i] = 0; - u.ptr.p_int[i] = 0; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j||ae_fp_less_eq(hqrnduniformr(&rs, _state),pnz) ) - { - a.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5; - if( j=j&&i-j>d.ptr.p_int[i] ) - { - ae_set_error_flag(&result, sparseexists(&s0, i, j, _state), __FILE__, __LINE__, "testsparseunit.ap:464"); - } - if( i>=j&&i-j<=d.ptr.p_int[i] ) - { - ae_set_error_flag(&result, !sparseexists(&s0, i, j, _state), __FILE__, __LINE__, "testsparseunit.ap:466"); - } - if( i<=j&&j-i>u.ptr.p_int[j] ) - { - ae_set_error_flag(&result, sparseexists(&s0, i, j, _state), __FILE__, __LINE__, "testsparseunit.ap:468"); - } - if( i<=j&&j-i<=u.ptr.p_int[j] ) - { - ae_set_error_flag(&result, !sparseexists(&s0, i, j, _state), __FILE__, __LINE__, "testsparseunit.ap:470"); - } - } - } - - /* - * Try to call SparseRewriteExisting() for out-of-band elements, make sure that it returns False. - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (i>=j&&i-j>d.ptr.p_int[i])||(i<=j&&j-i>u.ptr.p_int[j]) ) - { - ae_set_error_flag(&result, sparserewriteexisting(&s0, i, j, 1.0, _state), __FILE__, __LINE__, "testsparseunit.ap:479"); - } - } - } - - /* - * Convert to several different formats, check their contents with SparseGet(). - */ - sparsecopy(&s0, &s1, _state); - sparseconverttocrs(&s1, _state); - sparsecopytocrs(&s0, &s2, _state); - sparsecopytocrsbuf(&s0, &s3, _state); - sparsecopytohash(&s0, &s4, _state); - sparsecopytohashbuf(&s0, &s5, _state); - sparsecopy(&s0, &s6, _state); - sparseconverttohash(&s6, _state); - ae_set_error_flag(&result, sparsegetnrows(&s0, _state)!=n, __FILE__, __LINE__, "testsparseunit.ap:492"); - ae_set_error_flag(&result, sparsegetncols(&s0, _state)!=n, __FILE__, __LINE__, "testsparseunit.ap:493"); - ae_set_error_flag(&result, sparsegetmatrixtype(&s0, _state)!=2, __FILE__, __LINE__, "testsparseunit.ap:494"); - ae_set_error_flag(&result, !sparseissks(&s0, _state), __FILE__, __LINE__, "testsparseunit.ap:495"); - ae_set_error_flag(&result, sparseiscrs(&s0, _state), __FILE__, __LINE__, "testsparseunit.ap:496"); - ae_set_error_flag(&result, sparseishash(&s0, _state), __FILE__, __LINE__, "testsparseunit.ap:497"); - ae_set_error_flag(&result, sparseissks(&s1, _state), __FILE__, __LINE__, "testsparseunit.ap:498"); - ae_set_error_flag(&result, !sparseiscrs(&s1, _state), __FILE__, __LINE__, "testsparseunit.ap:499"); - ae_set_error_flag(&result, sparseishash(&s1, _state), __FILE__, __LINE__, "testsparseunit.ap:500"); - for(i=0; i<=n-1; i++) - { - v1 = a.ptr.pp_double[i][i]; - v0 = sparsegetdiagonal(&s0, i, _state); - ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:505"); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v1 = a.ptr.pp_double[i][j]; - v0 = sparseget(&s0, i, j, _state); - ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:512"); - v0 = sparseget(&s1, i, j, _state); - ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:514"); - v0 = sparseget(&s2, i, j, _state); - ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:516"); - v0 = sparseget(&s3, i, j, _state); - ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:518"); - v0 = sparseget(&s4, i, j, _state); - ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:520"); - v0 = sparseget(&s5, i, j, _state); - ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:522"); - v0 = sparseget(&s6, i, j, _state); - ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:524"); - } - } - - /* - * Check enumeration capabilities: - * * each element returned by SparseEnumerate() is returned only once - * * each non-zero element of A was enumerated - */ - ae_matrix_set_length(&wasenumerated, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - wasenumerated.ptr.pp_bool[i][j] = ae_false; - } - } - t0 = 0; - t1 = 0; - while(sparseenumerate(&s0, &t0, &t1, &i, &j, &v0, _state)) - { - ae_set_error_flag(&result, wasenumerated.ptr.pp_bool[i][j], __FILE__, __LINE__, "testsparseunit.ap:540"); - wasenumerated.ptr.pp_bool[i][j] = ae_true; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_neq(a.ptr.pp_double[i][j],(double)(0)) ) - { - ae_set_error_flag(&result, !wasenumerated.ptr.pp_bool[i][j], __FILE__, __LINE__, "testsparseunit.ap:546"); - } - } - } - - /* - * Check UpperCnt()/LowerCnt() - */ - ae_set_error_flag(&result, sparsegetuppercount(&s0, _state)!=uppercnt, __FILE__, __LINE__, "testsparseunit.ap:551"); - ae_set_error_flag(&result, sparsegetlowercount(&s0, _state)!=lowercnt, __FILE__, __LINE__, "testsparseunit.ap:552"); - - /* - * Check in-place transposition - */ - sparsecopy(&s0, &s1, _state); - sparsetransposesks(&s1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v0 = sparseget(&s0, i, j, _state); - v1 = sparseget(&s1, j, i, _state); - ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:564"); - } - } - - /* - * One more check - matrix is initially created in some other format - * (CRS or Hash) and converted to SKS later. - */ - sparsecreate(n, n, 0, &s0, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_neq(a.ptr.pp_double[i][j],(double)(0)) ) - { - sparseset(&s0, i, j, a.ptr.pp_double[i][j], _state); - } - } - } - sparsecopy(&s0, &s1, _state); - sparseconverttosks(&s1, _state); - sparsecopytosks(&s0, &s2, _state); - sparsecopytosksbuf(&s0, &s3, _state); - ae_set_error_flag(&result, !sparseissks(&s1, _state), __FILE__, __LINE__, "testsparseunit.ap:580"); - ae_set_error_flag(&result, sparseiscrs(&s1, _state), __FILE__, __LINE__, "testsparseunit.ap:581"); - ae_set_error_flag(&result, sparseishash(&s1, _state), __FILE__, __LINE__, "testsparseunit.ap:582"); - ae_set_error_flag(&result, !sparseissks(&s2, _state), __FILE__, __LINE__, "testsparseunit.ap:583"); - ae_set_error_flag(&result, sparseiscrs(&s2, _state), __FILE__, __LINE__, "testsparseunit.ap:584"); - ae_set_error_flag(&result, sparseishash(&s2, _state), __FILE__, __LINE__, "testsparseunit.ap:585"); - ae_set_error_flag(&result, !sparseissks(&s3, _state), __FILE__, __LINE__, "testsparseunit.ap:586"); - ae_set_error_flag(&result, sparseiscrs(&s3, _state), __FILE__, __LINE__, "testsparseunit.ap:587"); - ae_set_error_flag(&result, sparseishash(&s3, _state), __FILE__, __LINE__, "testsparseunit.ap:588"); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v1 = a.ptr.pp_double[i][j]; - v0 = sparseget(&s1, i, j, _state); - ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:594"); - v0 = sparseget(&s2, i, j, _state); - ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:596"); - v0 = sparseget(&s3, i, j, _state); - ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:598"); - } - } - - /* - * Increase problem sparcity and try one more time. - * Stop after testing NZ=0. - */ - if( nz==0 ) - { - break; - } - nz = ae_minint(ae_round(nz*0.95, _state), nz-1, _state); - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Function for testing CRS-specific functionality. -On failure sets ErrorFlag, on success does not touch it. - - -- ALGLIB PROJECT -- - Copyright 30.01.2018 by Bochkanov Sergey -*************************************************************************/ -void crstest(ae_bool* errorflag, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t m; - ae_int_t nz; - double pnz; - hqrndstate rs; - sparsematrix s0; - sparsematrix s1; - sparsematrix s2; - sparsematrix s3; - sparsematrix s4; - ae_int_t i; - ae_int_t j; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - memset(&s0, 0, sizeof(s0)); - memset(&s1, 0, sizeof(s1)); - memset(&s2, 0, sizeof(s2)); - memset(&s3, 0, sizeof(s3)); - memset(&s4, 0, sizeof(s4)); - _hqrndstate_init(&rs, _state, ae_true); - _sparsematrix_init(&s0, _state, ae_true); - _sparsematrix_init(&s1, _state, ae_true); - _sparsematrix_init(&s2, _state, ae_true); - _sparsematrix_init(&s3, _state, ae_true); - _sparsematrix_init(&s4, _state, ae_true); - - hqrndrandomize(&rs, _state); - for(n=1; n<=10; n++) - { - for(m=1; m<=10; m++) - { - nz = n*m; - for(;;) - { - - /* - * Generate N*N matrix where probability of non-diagonal element - * being non-zero is PNZ. We also generate D and U - subdiagonal - * and superdiagonal profile sizes. - * - * Create matrix with either general SKS or banded SKS constructor function - */ - if( n>1 ) - { - pnz = (double)nz/(double)(m*n); - } - else - { - pnz = 1.0; - } - - /* - * Generate random matrix in HASH format (testing SparseExists() - * during process), copy it to CRS format, compare with original - */ - sparsecreate(m, n, ae_round(nz*hqrnduniformr(&rs, _state), _state), &s0, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(errorflag, sparseexists(&s0, i, j, _state), __FILE__, __LINE__, "testsparseunit.ap:665"); - if( ae_fp_less_eq(hqrnduniformr(&rs, _state),pnz) ) - { - sparseset(&s0, i, j, hqrndnormal(&rs, _state), _state); - ae_set_error_flag(errorflag, !sparseexists(&s0, i, j, _state), __FILE__, __LINE__, "testsparseunit.ap:669"); - } - } - } - sparsecopytocrs(&s0, &s1, _state); - ae_set_error_flag(errorflag, !sparseiscrs(&s1, _state), __FILE__, __LINE__, "testsparseunit.ap:673"); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(errorflag, ae_fp_neq(sparseget(&s0, i, j, _state),sparseget(&s1, i, j, _state)), __FILE__, __LINE__, "testsparseunit.ap:677"); - ae_set_error_flag(errorflag, sparseexists(&s0, i, j, _state)&&!sparseexists(&s1, i, j, _state), __FILE__, __LINE__, "testsparseunit.ap:678"); - ae_set_error_flag(errorflag, sparseexists(&s1, i, j, _state)&&!sparseexists(&s0, i, j, _state), __FILE__, __LINE__, "testsparseunit.ap:679"); - } - } - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check transposition - */ - sparsecopytocrs(&s1, &s2, _state); - sparsetransposecrs(&s2, _state); - ae_set_error_flag(errorflag, !sparseiscrs(&s2, _state), __FILE__, __LINE__, "testsparseunit.ap:689"); - ae_set_error_flag(errorflag, sparsegetnrows(&s1, _state)!=sparsegetncols(&s2, _state), __FILE__, __LINE__, "testsparseunit.ap:690"); - ae_set_error_flag(errorflag, sparsegetncols(&s1, _state)!=sparsegetnrows(&s2, _state), __FILE__, __LINE__, "testsparseunit.ap:691"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(errorflag, ae_fp_neq(sparseget(&s1, i, j, _state),sparseget(&s2, j, i, _state)), __FILE__, __LINE__, "testsparseunit.ap:696"); - } - } - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check transposition - */ - sparsecopytransposecrs(&s1, &s3, _state); - ae_set_error_flag(errorflag, !sparseiscrs(&s3, _state), __FILE__, __LINE__, "testsparseunit.ap:704"); - ae_set_error_flag(errorflag, sparsegetnrows(&s1, _state)!=sparsegetncols(&s3, _state), __FILE__, __LINE__, "testsparseunit.ap:705"); - ae_set_error_flag(errorflag, sparsegetncols(&s1, _state)!=sparsegetnrows(&s3, _state), __FILE__, __LINE__, "testsparseunit.ap:706"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(errorflag, ae_fp_neq(sparseget(&s1, i, j, _state),sparseget(&s3, j, i, _state)), __FILE__, __LINE__, "testsparseunit.ap:711"); - } - } - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check transposition - */ - sparsecopytransposecrs(&s1, &s4, _state); - ae_set_error_flag(errorflag, !sparseiscrs(&s4, _state), __FILE__, __LINE__, "testsparseunit.ap:719"); - ae_set_error_flag(errorflag, sparsegetnrows(&s1, _state)!=sparsegetncols(&s4, _state), __FILE__, __LINE__, "testsparseunit.ap:720"); - ae_set_error_flag(errorflag, sparsegetncols(&s1, _state)!=sparsegetnrows(&s4, _state), __FILE__, __LINE__, "testsparseunit.ap:721"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(errorflag, ae_fp_neq(sparseget(&s1, i, j, _state),sparseget(&s4, j, i, _state)), __FILE__, __LINE__, "testsparseunit.ap:726"); - } - } - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - - /* - * Increase problem sparcity and try one more time. - * Stop after testing NZ=0. - */ - if( nz==0 ) - { - break; - } - nz = ae_minint(ae_round(nz*0.95, _state), nz-1, _state); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Function for testing basic functional - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -ae_bool basicfunctest(ae_state *_state) -{ - ae_frame _frame_block; - sparsematrix s; - ae_int_t n; - ae_int_t m; - ae_int_t i; - ae_int_t j; - ae_int_t i1; - ae_int_t j1; - ae_int_t uppercnt; - ae_int_t lowercnt; - ae_matrix a; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&a, 0, sizeof(a)); - _sparsematrix_init(&s, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - - n = 10; - m = 10; - result = ae_false; - for(i=1; i<=m-1; i++) - { - for(j=1; j<=n-1; j++) - { - sparsecreate(i, j, 1, &s, _state); - ae_matrix_set_length(&a, i, j, _state); - - /* - * Checking for Matrix with hash table type - */ - uppercnt = 0; - lowercnt = 0; - for(i1=0; i1<=i-1; i1++) - { - for(j1=0; j1<=j-1; j1++) - { - if( j1>i1 ) - { - inc(&uppercnt, _state); - } - if( j1N - * * with 50% probability to CRS or SKS, if M=N - */ - if( m!=n||ae_fp_less(hqrnduniformr(&rs, _state),0.5) ) - { - sparsecopytocrs(&sa, &s0, _state); - } - else - { - sparsecopytosks(&sa, &s0, _state); - } - - /* - * Test SparseGet() for SA and S0 against matrix returned in A - */ - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(sparseget(&sa, i, j, _state)-a.ptr.pp_double[i][j], _state),eps), __FILE__, __LINE__, "testsparseunit.ap:874"); - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(sparseget(&s0, i, j, _state)-a.ptr.pp_double[i][j], _state),eps), __FILE__, __LINE__, "testsparseunit.ap:875"); - } - } - - /* - * Test SparseMV - */ - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&x1, n, _state); - for(j=0; j<=n-1; j++) - { - x0.ptr.p_double[j] = hqrnduniformr(&rs, _state)-0.5; - x1.ptr.p_double[j] = x0.ptr.p_double[j]; - } - sparsemv(&s0, &x0, &y0, _state); - ae_set_error_flag(&result, y0.cntN - * * with 50% probability to CRS or SKS, if M=N - */ - if( m!=n||ae_fp_less(hqrnduniformr(&rs, _state),0.5) ) - { - sparsecopytocrs(&sa, &s0, _state); - } - else - { - sparsecopytosks(&sa, &s0, _state); - } - - /* - * Test SparseGet() for SA and S0 against matrix returned in A - */ - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(&result, ae_fp_neq(sparseget(&sa, i, j, _state),a.ptr.pp_double[i][j]), __FILE__, __LINE__, "testsparseunit.ap:1064"); - ae_set_error_flag(&result, ae_fp_neq(sparseget(&s0, i, j, _state),a.ptr.pp_double[i][j]), __FILE__, __LINE__, "testsparseunit.ap:1065"); - } - } - - /* - * Test SparseMV - */ - ae_matrix_set_length(&x0, n, k, _state); - ae_matrix_set_length(&x1, n, k, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=k-1; j++) - { - x0.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5; - x1.ptr.pp_double[i][j] = x0.ptr.pp_double[i][j]; - } - } - sparsemm(&s0, &x0, k, &y0, _state); - ae_set_error_flag(&result, y0.rows0 ) - { - isupper = ae_true; - } - testsparseunit_initgenerator(n, n, 0, triangletype, &g, _state); - while(testsparseunit_generatenext(&g, &a, &sa, _state)) - { - - /* - * Convert SA to desired storage format: - * * S0 stores unmodified copy - * * S1 stores copy with unmodified triangle corresponding - * to IsUpper and another triangle being spoiled by random - * trash - */ - sparsecopytohash(&sa, &s1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (ji&&!isupper) ) - { - sparseset(&s1, i, j, hqrnduniformr(&rs, _state), _state); - } - } - } - if( ae_fp_less(hqrnduniformr(&rs, _state),0.5) ) - { - sparsecopytocrs(&sa, &s0, _state); - sparseconverttocrs(&s1, _state); - } - else - { - sparsecopytosks(&sa, &s0, _state); - sparseconverttosks(&s1, _state); - } - - /* - * Test SparseGet() for SA and S0 against matrix returned in A - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(sparseget(&sa, i, j, _state)-a.ptr.pp_double[i][j], _state),eps), __FILE__, __LINE__, "testsparseunit.ap:1219"); - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(sparseget(&s0, i, j, _state)-a.ptr.pp_double[i][j], _state),eps), __FILE__, __LINE__, "testsparseunit.ap:1220"); - ae_set_error_flag(&result, (ji&&triangletype==-1)&&ae_fp_neq(sparseget(&s0, i, j, _state),(double)(0)), __FILE__, __LINE__, "testsparseunit.ap:1222"); - } - } - - /* - * Before we proceed with testing, update empty triangle of A - * with its copy from another part of the matrix. - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (ji&&!isupper) ) - { - a.ptr.pp_double[i][j] = a.ptr.pp_double[j][i]; - } - } - } - - /* - * Test SparseSMV - */ - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&x1, n, _state); - for(j=0; j<=n-1; j++) - { - x0.ptr.p_double[j] = hqrnduniformr(&rs, _state)-0.5; - x1.ptr.p_double[j] = x0.ptr.p_double[j]; - } - sparsesmv(&s0, isupper, &x0, &y0, _state); - ae_set_error_flag(&result, y0.cnt0 ) - { - isupper = ae_true; - } - testsparseunit_initgenerator(n, n, 0, triangletype, &g, _state); - while(testsparseunit_generatenext(&g, &a, &sa, _state)) - { - - /* - * Choose matrix width K - */ - k = 1+hqrnduniformi(&rs, 20, _state); - - /* - * Convert SA to desired storage format: - * * S0 stores unmodified copy - * * S1 stores copy with unmodified triangle corresponding - * to IsUpper and another triangle being spoiled by random - * trash - */ - sparsecopytohash(&sa, &s1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (ji&&!isupper) ) - { - sparseset(&s1, i, j, hqrnduniformr(&rs, _state), _state); - } - } - } - if( ae_fp_less(hqrnduniformr(&rs, _state),0.5) ) - { - sparsecopytocrs(&sa, &s0, _state); - sparseconverttocrs(&s1, _state); - } - else - { - sparsecopytosks(&sa, &s0, _state); - sparseconverttosks(&s1, _state); - } - - /* - * Test SparseGet() for SA and S0 against matrix returned in A - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(sparseget(&sa, i, j, _state)-a.ptr.pp_double[i][j], _state),eps), __FILE__, __LINE__, "testsparseunit.ap:1361"); - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(sparseget(&s0, i, j, _state)-a.ptr.pp_double[i][j], _state),eps), __FILE__, __LINE__, "testsparseunit.ap:1362"); - ae_set_error_flag(&result, (ji&&triangletype==-1)&&ae_fp_neq(sparseget(&s0, i, j, _state),(double)(0)), __FILE__, __LINE__, "testsparseunit.ap:1364"); - } - } - - /* - * Before we proceed with testing, update empty triangle of A - * with its copy from another part of the matrix. - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (ji&&!isupper) ) - { - a.ptr.pp_double[i][j] = a.ptr.pp_double[j][i]; - } - } - } - - /* - * Test SparseSMM - */ - ae_matrix_set_length(&x0, n, k, _state); - ae_matrix_set_length(&x1, n, k, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=k-1; j++) - { - x0.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5; - x1.ptr.pp_double[i][j] = x0.ptr.pp_double[i][j]; - } - } - sparsesmm(&s0, isupper, &x0, k, &y0, _state); - ae_set_error_flag(&result, y0.rows=i)&&ae_fp_greater(ae_fabs(db.ptr.pp_double[i][j]-sparseget(&sb, i, j, _state), _state),eps), __FILE__, __LINE__, "testsparseunit.ap:1498"); - ae_set_error_flag(&result, (isupper&&j0 ) - { - isupper = ae_true; - } - testsparseunit_initgenerator(n, n, 0, triangletype, &g, _state); - while(testsparseunit_generatenext(&g, &a, &sa, _state)) - { - - /* - * Settings (IsUpper was already set, handle the rest) - */ - isunit = ae_fp_less(hqrnduniformr(&rs, _state),0.5); - optype = hqrnduniformi(&rs, 2, _state); - - /* - * Convert SA to desired storage format: - * * S0 stores unmodified copy - * * S1 stores copy with unmodified triangle corresponding - * to IsUpper and another triangle being spoiled by random - * trash - */ - sparsecopytohash(&sa, &s1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (ji&&!isupper) ) - { - sparseset(&s1, i, j, hqrnduniformr(&rs, _state), _state); - } - } - } - if( ae_fp_less(hqrnduniformr(&rs, _state),0.5) ) - { - sparsecopytocrs(&sa, &s0, _state); - sparseconverttocrs(&s1, _state); - } - else - { - sparsecopytosks(&sa, &s0, _state); - sparseconverttosks(&s1, _state); - } - - /* - * Generate "effective A" - */ - ae_matrix_set_length(&ea, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - ea.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (j>=i&&isupper)||(j<=i&&!isupper) ) - { - i1 = i; - j1 = j; - if( optype==1 ) - { - swapi(&i1, &j1, _state); - } - ea.ptr.pp_double[i1][j1] = a.ptr.pp_double[i][j]; - if( isunit&&i1==j1 ) - { - ea.ptr.pp_double[i1][j1] = 1.0; - } - } - } - } - - /* - * Test SparseTRMV - */ - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&x1, n, _state); - for(j=0; j<=n-1; j++) - { - x0.ptr.p_double[j] = hqrnduniformr(&rs, _state)-0.5; - x1.ptr.p_double[j] = x0.ptr.p_double[j]; - } - sparsetrmv(&s0, isupper, isunit, optype, &x0, &y0, _state); - ae_set_error_flag(&result, y0.cnti&&!isupper) ) - { - sparseset(&s1, i, j, hqrnduniformr(&rs, _state), _state); - } - } - } - if( ae_fp_less(hqrnduniformr(&rs, _state),0.5) ) - { - sparsecopytocrs(&sa, &s0, _state); - sparseconverttocrs(&s1, _state); - } - else - { - sparsecopytosks(&sa, &s0, _state); - sparseconverttosks(&s1, _state); - } - - /* - * Generate "effective A" and EY = inv(EA)*x0 - */ - ae_matrix_set_length(&ea, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - ea.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (j>=i&&isupper)||(j<=i&&!isupper) ) - { - i1 = i; - j1 = j; - if( optype==1 ) - { - swapi(&i1, &j1, _state); - } - ea.ptr.pp_double[i1][j1] = a.ptr.pp_double[i][j]; - if( isunit&&i1==j1 ) - { - ea.ptr.pp_double[i1][j1] = 1.0; - } - } - } - } - ae_vector_set_length(&ey, n, _state); - for(i=0; i<=n-1; i++) - { - ey.ptr.p_double[i] = hqrnduniformr(&rs, _state)-0.5; - } - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&x1, n, _state); - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&ea.ptr.pp_double[i][0], 1, &ey.ptr.p_double[0], 1, ae_v_len(0,n-1)); - x0.ptr.p_double[i] = v; - x1.ptr.p_double[i] = v; - } - - /* - * Test SparseTRSV - */ - sparsetrsv(&s0, isupper, isunit, optype, &x0, _state); - ae_set_error_flag(&result, x0.cnti1&&j1<=i1+2 ) - { - a.ptr.pp_double[i1][j1] = (double)(i1+j1+1); - sparseset(&s, i1, j1, a.ptr.pp_double[i1][j1], _state); - sparseadd(&s, i1, j1, (double)(0), _state); - sparseset(&sss, i1, j1, a.ptr.pp_double[i1][j1], _state); - } - else - { - a.ptr.pp_double[i1][j1] = (double)(0); - sparseset(&s, i1, j1, a.ptr.pp_double[i1][j1], _state); - sparseadd(&s, i1, j1, (double)(0), _state); - } - - /* - * Check for SparseCreate - */ - sparsecopy(&s, &ss, _state); - a0 = sparseget(&s, i1, j1, _state); - a1 = sparseget(&ss, i1, j1, _state); - if( ae_fp_neq(a0,a1) ) - { - if( !silent ) - { - printf("BasicCopyFuncTest::Report::SparseGet\n"); - printf("S::[%0d,%0d]=%0.5f\n", - (int)(i1), - (int)(j1), - (double)(a0)); - printf("SS::[%0d,%0d]=%0.5f\n", - (int)(i1), - (int)(j1), - (double)(a1)); - printf(" TEST FAILED.\n"); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - - /* - * Check for SparseCreateCRS - */ - for(i1=0; i1<=i-1; i1++) - { - for(j1=0; j1<=j-1; j1++) - { - sparsecopy(&sss, &ss, _state); - a0 = sparseget(&sss, i1, j1, _state); - a1 = sparseget(&ss, i1, j1, _state); - if( ae_fp_neq(a0,a1) ) - { - if( !silent ) - { - printf("BasicCopyFuncTest::Report::SparseGet\n"); - printf("S::[%0d,%0d]=%0.5f\n", - (int)(i1), - (int)(j1), - (double)(a0)); - printf("SS::[%0d,%0d]=%0.5f\n", - (int)(i1), - (int)(j1), - (double)(a1)); - printf(" TEST FAILED.\n"); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - - /* - * Check for Matrix with CRS type - */ - sparseconverttocrs(&s, _state); - sparsecopy(&s, &ss, _state); - for(i1=0; i1<=i-1; i1++) - { - for(j1=0; j1<=j-1; j1++) - { - a0 = sparseget(&s, i1, j1, _state); - a1 = sparseget(&ss, i1, j1, _state); - if( ae_fp_neq(a0,a1) ) - { - if( !silent ) - { - printf("BasicCopyFuncTest::Report::SparseGet\n"); - printf("S::[%0d,%0d]=%0.5f\n", - (int)(i1), - (int)(j1), - (double)(a0)); - printf("SS::[%0d,%0d]=%0.5f\n", - (int)(i1), - (int)(j1), - (double)(a1)); - printf(" TEST FAILED.\n"); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - } - if( !silent ) - { - printf(" TEST IS PASSED.\n"); - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Function for testing SparseCopy - - -- ALGLIB PROJECT -- - Copyright 14.10.2011 by Bochkanov Sergey -*************************************************************************/ -ae_bool copyfunctest(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - sparsematrix s; - sparsematrix ss; - ae_int_t n; - ae_int_t m; - ae_int_t mtype; - ae_int_t i; - ae_int_t j; - ae_int_t i1; - ae_int_t j1; - double lb; - double rb; - ae_matrix a; - ae_vector x0; - ae_vector x1; - ae_vector ty; - ae_vector tyt; - ae_vector y; - ae_vector yt; - ae_vector y0; - ae_vector yt0; - ae_vector cpy; - ae_vector cpyt; - ae_vector cpy0; - ae_vector cpyt0; - double eps; - double a0; - double a1; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&ss, 0, sizeof(ss)); - memset(&a, 0, sizeof(a)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&ty, 0, sizeof(ty)); - memset(&tyt, 0, sizeof(tyt)); - memset(&y, 0, sizeof(y)); - memset(&yt, 0, sizeof(yt)); - memset(&y0, 0, sizeof(y0)); - memset(&yt0, 0, sizeof(yt0)); - memset(&cpy, 0, sizeof(cpy)); - memset(&cpyt, 0, sizeof(cpyt)); - memset(&cpy0, 0, sizeof(cpy0)); - memset(&cpyt0, 0, sizeof(cpyt0)); - _sparsematrix_init(&s, _state, ae_true); - _sparsematrix_init(&ss, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ty, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tyt, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yt, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yt0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cpy, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cpyt, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cpy0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cpyt0, 0, DT_REAL, _state, ae_true); - - - /* - * Accuracy - */ - eps = 1000*ae_machineepsilon; - - /* - * Size of the matrix (m*n) - */ - n = 30; - m = 30; - - /* - * Left and right borders, limiting matrix values - */ - lb = (double)(-10); - rb = (double)(10); - - /* - * Test linear algebra functions for: - * a) sparse matrix converted to CRS from Hash-Table - * b) sparse matrix initially created as CRS - */ - for(i=1; i<=m-1; i++) - { - for(j=1; j<=n-1; j++) - { - for(mtype=0; mtype<=1; mtype++) - { - - /* - * Prepare test problem - */ - testsparseunit_createrandom(i, j, -1, mtype, -1, -1, &a, &s, _state); - sparsecopy(&s, &ss, _state); - - /* - * Initialize temporaries - */ - ae_vector_set_length(&ty, i, _state); - ae_vector_set_length(&tyt, j, _state); - for(i1=0; i1<=i-1; i1++) - { - ty.ptr.p_double[i1] = (double)(0); - } - for(i1=0; i1<=j-1; i1++) - { - tyt.ptr.p_double[i1] = (double)(0); - } - ae_vector_set_length(&x0, j, _state); - ae_vector_set_length(&x1, i, _state); - for(i1=0; i1<=j-1; i1++) - { - x0.ptr.p_double[i1] = (rb-lb)*ae_randomreal(_state)+lb; - } - for(i1=0; i1<=i-1; i1++) - { - x1.ptr.p_double[i1] = (rb-lb)*ae_randomreal(_state)+lb; - } - - /* - * Consider two cases: square matrix, and non-square matrix - */ - if( i!=j ) - { - - /* - * Searching true result - */ - for(i1=0; i1<=i-1; i1++) - { - for(j1=0; j1<=j-1; j1++) - { - ty.ptr.p_double[i1] = ty.ptr.p_double[i1]+a.ptr.pp_double[i1][j1]*x0.ptr.p_double[j1]; - tyt.ptr.p_double[j1] = tyt.ptr.p_double[j1]+a.ptr.pp_double[i1][j1]*x1.ptr.p_double[i1]; - } - } - - /* - * Multiplication - */ - sparsemv(&s, &x0, &y, _state); - sparsemtv(&s, &x1, &yt, _state); - sparsemv(&ss, &x0, &cpy, _state); - sparsemtv(&ss, &x1, &cpyt, _state); - - /* - * Check for MV-result - */ - for(i1=0; i1<=i-1; i1++) - { - if( (ae_fp_greater_eq(ae_fabs(y.ptr.p_double[i1]-ty.ptr.p_double[i1], _state),eps)||ae_fp_greater_eq(ae_fabs(cpy.ptr.p_double[i1]-ty.ptr.p_double[i1], _state),eps))||ae_fp_neq(cpy.ptr.p_double[i1]-y.ptr.p_double[i1],(double)(0)) ) - { - if( !silent ) - { - printf("CopyFuncTest::Report::RES_MV\n"); - printf("Y[%0d]=%0.5f; tY[%0d]=%0.5f\n", - (int)(i1), - (double)(y.ptr.p_double[i1]), - (int)(i1), - (double)(ty.ptr.p_double[i1])); - printf("cpY[%0d]=%0.5f;\n", - (int)(i1), - (double)(cpy.ptr.p_double[i1])); - printf(" TEST FAILED.\n"); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - - /* - * Check for MTV-result - */ - for(i1=0; i1<=j-1; i1++) - { - if( (ae_fp_greater_eq(ae_fabs(yt.ptr.p_double[i1]-tyt.ptr.p_double[i1], _state),eps)||ae_fp_greater_eq(ae_fabs(cpyt.ptr.p_double[i1]-tyt.ptr.p_double[i1], _state),eps))||ae_fp_neq(cpyt.ptr.p_double[i1]-yt.ptr.p_double[i1],(double)(0)) ) - { - if( !silent ) - { - printf("CopyFuncTest::Report::RES_MTV\n"); - printf("Yt[%0d]=%0.5f; tYt[%0d]=%0.5f\n", - (int)(i1), - (double)(yt.ptr.p_double[i1]), - (int)(i1), - (double)(tyt.ptr.p_double[i1])); - printf("cpYt[%0d]=%0.5f;\n", - (int)(i1), - (double)(cpyt.ptr.p_double[i1])); - printf(" TEST FAILED.\n"); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - sparsecopy(&s, &ss, _state); - for(i1=0; i1<=i-1; i1++) - { - for(j1=0; j1<=j-1; j1++) - { - a0 = sparseget(&s, i1, j1, _state); - a1 = sparseget(&ss, i1, j1, _state); - if( ae_fp_neq(a0,a1) ) - { - if( !silent ) - { - printf("CopyFuncTest::Report::SparseGet\n"); - printf("S::[%0d,%0d]=%0.5f\n", - (int)(i1), - (int)(j1), - (double)(a0)); - printf("SS::[%0d,%0d]=%0.5f\n", - (int)(i1), - (int)(j1), - (double)(a1)); - printf(" TEST FAILED.\n"); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - else - { - - /* - * Searching true result - */ - for(i1=0; i1<=i-1; i1++) - { - for(j1=0; j1<=j-1; j1++) - { - ty.ptr.p_double[i1] = ty.ptr.p_double[i1]+a.ptr.pp_double[i1][j1]*x0.ptr.p_double[j1]; - tyt.ptr.p_double[j1] = tyt.ptr.p_double[j1]+a.ptr.pp_double[i1][j1]*x0.ptr.p_double[i1]; - } - } - - /* - * Multiplication - */ - sparsemv(&s, &x0, &y, _state); - sparsemtv(&s, &x0, &yt, _state); - sparsemv2(&s, &x0, &y0, &yt0, _state); - sparsemv(&ss, &x0, &cpy, _state); - sparsemtv(&ss, &x0, &cpyt, _state); - sparsemv2(&ss, &x0, &cpy0, &cpyt0, _state); - - /* - * Check for MV2-result - */ - for(i1=0; i1<=i-1; i1++) - { - if( ((((ae_fp_greater_eq(ae_fabs(y0.ptr.p_double[i1]-ty.ptr.p_double[i1], _state),eps)||ae_fp_greater_eq(ae_fabs(yt0.ptr.p_double[i1]-tyt.ptr.p_double[i1], _state),eps))||ae_fp_greater_eq(ae_fabs(cpy0.ptr.p_double[i1]-ty.ptr.p_double[i1], _state),eps))||ae_fp_greater_eq(ae_fabs(cpyt0.ptr.p_double[i1]-tyt.ptr.p_double[i1], _state),eps))||ae_fp_neq(cpy0.ptr.p_double[i1]-y0.ptr.p_double[i1],(double)(0)))||ae_fp_neq(cpyt0.ptr.p_double[i1]-yt0.ptr.p_double[i1],(double)(0)) ) - { - if( !silent ) - { - printf("CopyFuncTest::Report::RES_MV2\n"); - printf("Y0[%0d]=%0.5f; tY[%0d]=%0.5f\n", - (int)(i1), - (double)(y0.ptr.p_double[i1]), - (int)(i1), - (double)(ty.ptr.p_double[i1])); - printf("Yt0[%0d]=%0.5f; tYt[%0d]=%0.5f\n", - (int)(i1), - (double)(yt0.ptr.p_double[i1]), - (int)(i1), - (double)(tyt.ptr.p_double[i1])); - printf("cpY0[%0d]=%0.5f;\n", - (int)(i1), - (double)(cpy0.ptr.p_double[i1])); - printf("cpYt0[%0d]=%0.5f;\n", - (int)(i1), - (double)(cpyt0.ptr.p_double[i1])); - printf(" TEST FAILED.\n"); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - - /* - * Check for MV- and MTV-result by help MV2 - */ - for(i1=0; i1<=i-1; i1++) - { - if( ((ae_fp_greater(ae_fabs(y0.ptr.p_double[i1]-y.ptr.p_double[i1], _state),eps)||ae_fp_greater(ae_fabs(yt0.ptr.p_double[i1]-yt.ptr.p_double[i1], _state),eps))||ae_fp_greater(ae_fabs(cpy0.ptr.p_double[i1]-cpy.ptr.p_double[i1], _state),eps))||ae_fp_greater(ae_fabs(cpyt0.ptr.p_double[i1]-cpyt.ptr.p_double[i1], _state),eps) ) - { - if( !silent ) - { - printf("CopyFuncTest::Report::RES_MV_MVT\n"); - printf("Y0[%0d]=%0.5f; Y[%0d]=%0.5f\n", - (int)(i1), - (double)(y0.ptr.p_double[i1]), - (int)(i1), - (double)(y.ptr.p_double[i1])); - printf("Yt0[%0d]=%0.5f; Yt[%0d]=%0.5f\n", - (int)(i1), - (double)(yt0.ptr.p_double[i1]), - (int)(i1), - (double)(yt.ptr.p_double[i1])); - printf("cpY0[%0d]=%0.5f; cpY[%0d]=%0.5f\n", - (int)(i1), - (double)(cpy0.ptr.p_double[i1]), - (int)(i1), - (double)(cpy.ptr.p_double[i1])); - printf("cpYt0[%0d]=%0.5f; cpYt[%0d]=%0.5f\n", - (int)(i1), - (double)(cpyt0.ptr.p_double[i1]), - (int)(i1), - (double)(cpyt.ptr.p_double[i1])); - printf(" TEST FAILED.\n"); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - sparsecopy(&s, &ss, _state); - for(i1=0; i1<=i-1; i1++) - { - for(j1=0; j1<=j-1; j1++) - { - a0 = sparseget(&s, i1, j1, _state); - a1 = sparseget(&ss, i1, j1, _state); - if( ae_fp_neq(a0,a1) ) - { - if( !silent ) - { - printf("CopyFuncTest::Report::SparseGet\n"); - printf("S::[%0d,%0d]=%0.5f\n", - (int)(i1), - (int)(j1), - (double)(a0)); - printf("SS::[%0d,%0d]=%0.5f\n", - (int)(i1), - (int)(j1), - (double)(a1)); - printf(" TEST FAILED.\n"); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - } - } - } - if( !silent ) - { - printf(" TEST IS PASSED.\n"); - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function initializes sparse matrix generator, which is used to generate -a set of matrices with sequentially increasing sparsity. - -PARAMETERS: - M, N - matrix size. If M=0, then matrix is square N*N. - N and M must be small enough to store N*M dense matrix. - MatKind - matrix properties: - * 0 - general sparse (no structure) - * 1 - general sparse, but diagonal is always present and non-zero - * 2 - diagonally dominant, SPD - Triangle - triangle being returned: - * +1 - upper triangle - * -1 - lower triangle - * 0 - full matrix is returned - -OUTPUT PARAMETERS: - G - generator - A - matrix A in dense format - SA - matrix A in sparse format (hash-table storage) -*************************************************************************/ -static void testsparseunit_initgenerator(ae_int_t m, - ae_int_t n, - ae_int_t matkind, - ae_int_t triangle, - sparsegenerator* g, - ae_state *_state) -{ - - _sparsegenerator_clear(g); - - g->n = n; - g->m = m; - g->matkind = matkind; - g->triangle = triangle; - hqrndrandomize(&g->rs, _state); - ae_vector_set_length(&g->rcs.ia, 5+1, _state); - ae_vector_set_length(&g->rcs.ra, 1+1, _state); - g->rcs.stage = -1; -} - - -static ae_bool testsparseunit_generatenext(sparsegenerator* g, - /* Real */ ae_matrix* da, - sparsematrix* sa, - ae_state *_state) -{ - ae_int_t n; - ae_int_t m; - ae_int_t nz; - ae_int_t nzd; - double pnz; - ae_int_t i; - ae_int_t j; - double v; - ae_bool result; - - ae_matrix_clear(da); - _sparsematrix_clear(sa); - - - /* - * Reverse communication preparations - * I know it looks ugly, but it works the same way - * anywhere from C++ to Python. - * - * This code initializes locals by: - * * random values determined during code - * generation - on first subroutine call - * * values from previous call - on subsequent calls - */ - if( g->rcs.stage>=0 ) - { - n = g->rcs.ia.ptr.p_int[0]; - m = g->rcs.ia.ptr.p_int[1]; - nz = g->rcs.ia.ptr.p_int[2]; - nzd = g->rcs.ia.ptr.p_int[3]; - i = g->rcs.ia.ptr.p_int[4]; - j = g->rcs.ia.ptr.p_int[5]; - pnz = g->rcs.ra.ptr.p_double[0]; - v = g->rcs.ra.ptr.p_double[1]; - } - else - { - n = 359; - m = -58; - nz = -919; - nzd = -909; - i = 81; - j = 255; - pnz = 74; - v = -788; - } - if( g->rcs.stage==0 ) - { - goto lbl_0; - } - if( g->rcs.stage==1 ) - { - goto lbl_1; - } - - /* - * Routine body - */ - n = g->n; - if( g->m==0 ) - { - m = n; - } - else - { - m = g->m; - } - ae_assert(m>0&&n>0, "GenerateNext: incorrect N/M", _state); - - /* - * Generate general sparse matrix - */ - if( g->matkind!=0 ) - { - goto lbl_2; - } - nz = n*m; -lbl_4: - if( ae_false ) - { - goto lbl_5; - } - - /* - * Generate dense N*N matrix where probability of element - * being non-zero is PNZ. - */ - pnz = (double)nz/(double)(n*m); - ae_matrix_set_length(&g->bufa, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_less_eq(hqrnduniformr(&g->rs, _state),pnz) ) - { - g->bufa.ptr.pp_double[i][j] = hqrnduniformr(&g->rs, _state)-0.5; - } - else - { - g->bufa.ptr.pp_double[i][j] = 0.0; - } - } - } - - /* - * Output matrix and RComm - */ - ae_matrix_set_length(da, m, n, _state); - sparsecreate(m, n, ae_round(pnz*m*n, _state), sa, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (j<=i&&g->triangle<=0)||(j>=i&&g->triangle>=0) ) - { - da->ptr.pp_double[i][j] = g->bufa.ptr.pp_double[i][j]; - sparseset(sa, i, j, g->bufa.ptr.pp_double[i][j], _state); - } - else - { - da->ptr.pp_double[i][j] = 0.0; - } - } - } - g->rcs.stage = 0; - goto lbl_rcomm; -lbl_0: - - /* - * Increase problem sparcity and try one more time. - * Stop after testing NZ=0. - */ - if( nz==0 ) - { - goto lbl_5; - } - nz = nz/2; - goto lbl_4; -lbl_5: - result = ae_false; - return result; -lbl_2: - - /* - * Generate general sparse matrix with non-zero diagonal - */ - if( g->matkind!=1 ) - { - goto lbl_6; - } - ae_assert(n==m, "GenerateNext: non-square matrix for MatKind=1", _state); - nz = n*n-n; -lbl_8: - if( ae_false ) - { - goto lbl_9; - } - - /* - * Generate dense N*N matrix where probability of non-diagonal element - * being non-zero is PNZ. - */ - if( n>1 ) - { - pnz = (double)nz/(double)(n*n-n); - } - else - { - pnz = (double)(1); - } - ae_matrix_set_length(&g->bufa, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - do - { - g->bufa.ptr.pp_double[i][i] = hqrnduniformr(&g->rs, _state)-0.5; - } - while(ae_fp_eq(g->bufa.ptr.pp_double[i][i],(double)(0))); - g->bufa.ptr.pp_double[i][i] = g->bufa.ptr.pp_double[i][i]+1.5*ae_sign(g->bufa.ptr.pp_double[i][i], _state); - continue; - } - if( ae_fp_less_eq(hqrnduniformr(&g->rs, _state),pnz) ) - { - g->bufa.ptr.pp_double[i][j] = hqrnduniformr(&g->rs, _state)-0.5; - } - else - { - g->bufa.ptr.pp_double[i][j] = 0.0; - } - } - } - - /* - * Output matrix and RComm - */ - ae_matrix_set_length(da, n, n, _state); - sparsecreate(n, n, ae_round(pnz*(n*n-n)+n, _state), sa, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (j<=i&&g->triangle<=0)||(j>=i&&g->triangle>=0) ) - { - da->ptr.pp_double[i][j] = g->bufa.ptr.pp_double[i][j]; - sparseset(sa, i, j, g->bufa.ptr.pp_double[i][j], _state); - } - else - { - da->ptr.pp_double[i][j] = 0.0; - } - } - } - g->rcs.stage = 1; - goto lbl_rcomm; -lbl_1: - - /* - * Increase problem sparcity and try one more time. - * Stop after testing NZ=0. - */ - if( nz==0 ) - { - goto lbl_9; - } - nz = nz/2; - goto lbl_8; -lbl_9: - result = ae_false; - return result; -lbl_6: - ae_assert(ae_false, "Assertion failed", _state); - result = ae_false; - return result; - - /* - * Saving state - */ -lbl_rcomm: - result = ae_true; - g->rcs.ia.ptr.p_int[0] = n; - g->rcs.ia.ptr.p_int[1] = m; - g->rcs.ia.ptr.p_int[2] = nz; - g->rcs.ia.ptr.p_int[3] = nzd; - g->rcs.ia.ptr.p_int[4] = i; - g->rcs.ia.ptr.p_int[5] = j; - g->rcs.ra.ptr.p_double[0] = pnz; - g->rcs.ra.ptr.p_double[1] = v; - return result; -} - - -/************************************************************************* -This function creates random sparse matrix with some prescribed pattern. - -INPUT PARAMETERS: - M - number of rows - N - number of columns - PKind - sparsity pattern: - *-1 = pattern is chosen at random as well as P0/P1 - * 0 = matrix with up to P0 non-zero elements at random locations - (however, actual number of non-zero elements can be - less than P0, and in fact can be zero) - * 1 = band matrix with P0 non-zero elements below diagonal - and P1 non-zero element above diagonal - * 2 = matrix with random number of contiguous non-zero - elements in the each row - CKind - creation type: - *-1 = CKind is chosen at random - * 0 = matrix is created in Hash-Table format and converted - to CRS representation - * 1 = matrix is created in CRS format - -OUTPUT PARAMETERS: - DA - dense representation of A, array[M,N] - SA - sparse representation of A, in CRS format - - -- ALGLIB PROJECT -- - Copyright 31.10.2011 by Bochkanov Sergey -*************************************************************************/ -static void testsparseunit_createrandom(ae_int_t m, - ae_int_t n, - ae_int_t pkind, - ae_int_t ckind, - ae_int_t p0, - ae_int_t p1, - /* Real */ ae_matrix* da, - sparsematrix* sa, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t maxpkind; - ae_int_t maxckind; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - ae_vector c0; - ae_vector c1; - ae_vector rowsizes; - - ae_frame_make(_state, &_frame_block); - memset(&c0, 0, sizeof(c0)); - memset(&c1, 0, sizeof(c1)); - memset(&rowsizes, 0, sizeof(rowsizes)); - ae_matrix_clear(da); - _sparsematrix_clear(sa); - ae_vector_init(&c0, 0, DT_INT, _state, ae_true); - ae_vector_init(&c1, 0, DT_INT, _state, ae_true); - ae_vector_init(&rowsizes, 0, DT_INT, _state, ae_true); - - maxpkind = 2; - maxckind = 1; - ae_assert(m>=1, "CreateRandom: incorrect parameters", _state); - ae_assert(n>=1, "CreateRandom: incorrect parameters", _state); - ae_assert(pkind>=-1&&pkind<=maxpkind, "CreateRandom: incorrect parameters", _state); - ae_assert(ckind>=-1&&ckind<=maxckind, "CreateRandom: incorrect parameters", _state); - if( pkind==-1 ) - { - pkind = ae_randominteger(maxpkind+1, _state); - if( pkind==0 ) - { - p0 = ae_randominteger(m*n, _state); - } - if( pkind==1 ) - { - p0 = ae_randominteger(ae_minint(m, n, _state), _state); - p1 = ae_randominteger(ae_minint(m, n, _state), _state); - } - } - if( ckind==-1 ) - { - ckind = ae_randominteger(maxckind+1, _state); - } - if( pkind==0 ) - { - - /* - * Matrix with elements at random locations - */ - ae_matrix_set_length(da, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - da->ptr.pp_double[i][j] = (double)(0); - } - } - if( ckind==0 ) - { - - /* - * Create matrix in Hash format, convert to CRS - */ - sparsecreate(m, n, 1, sa, _state); - for(k=0; k<=p0-1; k++) - { - i = ae_randominteger(m, _state); - j = ae_randominteger(n, _state); - v = (double)(ae_randominteger(17, _state)-8)/(double)8; - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - da->ptr.pp_double[i][j] = v; - sparseset(sa, i, j, v, _state); - } - else - { - da->ptr.pp_double[i][j] = da->ptr.pp_double[i][j]+v; - sparseadd(sa, i, j, v, _state); - } - } - sparseconverttocrs(sa, _state); - ae_frame_leave(_state); - return; - } - if( ckind==1 ) - { - - /* - * Create matrix in CRS format - */ - for(k=0; k<=p0-1; k++) - { - i = ae_randominteger(m, _state); - j = ae_randominteger(n, _state); - v = (double)(ae_randominteger(17, _state)-8)/(double)8; - da->ptr.pp_double[i][j] = v; - } - ae_vector_set_length(&rowsizes, m, _state); - for(i=0; i<=m-1; i++) - { - rowsizes.ptr.p_int[i] = 0; - for(j=0; j<=n-1; j++) - { - if( ae_fp_neq(da->ptr.pp_double[i][j],(double)(0)) ) - { - rowsizes.ptr.p_int[i] = rowsizes.ptr.p_int[i]+1; - } - } - } - sparsecreatecrs(m, n, &rowsizes, sa, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_neq(da->ptr.pp_double[i][j],(double)(0)) ) - { - sparseset(sa, i, j, da->ptr.pp_double[i][j], _state); - } - } - } - ae_frame_leave(_state); - return; - } - ae_assert(ae_false, "CreateRandom: internal error", _state); - } - if( pkind==1 ) - { - - /* - * Band matrix - */ - ae_matrix_set_length(da, m, n, _state); - ae_vector_set_length(&rowsizes, m, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - da->ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=m-1; i++) - { - for(j=ae_maxint(i-p0, 0, _state); j<=ae_minint(i+p1, n-1, _state); j++) - { - do - { - da->ptr.pp_double[i][j] = (double)(ae_randominteger(17, _state)-8)/(double)8; - } - while(ae_fp_eq(da->ptr.pp_double[i][j],(double)(0))); - } - rowsizes.ptr.p_int[i] = ae_maxint(ae_minint(i+p1, n-1, _state)-ae_maxint(i-p0, 0, _state)+1, 0, _state); - } - if( ckind==0 ) - { - sparsecreate(m, n, 1, sa, _state); - } - if( ckind==1 ) - { - sparsecreatecrs(m, n, &rowsizes, sa, _state); - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_neq(da->ptr.pp_double[i][j],(double)(0)) ) - { - sparseset(sa, i, j, da->ptr.pp_double[i][j], _state); - } - } - } - sparseconverttocrs(sa, _state); - ae_frame_leave(_state); - return; - } - if( pkind==2 ) - { - - /* - * Matrix with one contiguous sequence of non-zero elements per row - */ - ae_matrix_set_length(da, m, n, _state); - ae_vector_set_length(&rowsizes, m, _state); - ae_vector_set_length(&c0, m, _state); - ae_vector_set_length(&c1, m, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - da->ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=m-1; i++) - { - c0.ptr.p_int[i] = ae_randominteger(n, _state); - c1.ptr.p_int[i] = c0.ptr.p_int[i]+ae_randominteger(n-c0.ptr.p_int[i]+1, _state); - rowsizes.ptr.p_int[i] = c1.ptr.p_int[i]-c0.ptr.p_int[i]; - } - for(i=0; i<=m-1; i++) - { - for(j=c0.ptr.p_int[i]; j<=c1.ptr.p_int[i]-1; j++) - { - do - { - da->ptr.pp_double[i][j] = (double)(ae_randominteger(17, _state)-8)/(double)8; - } - while(ae_fp_eq(da->ptr.pp_double[i][j],(double)(0))); - } - } - if( ckind==0 ) - { - sparsecreate(m, n, 1, sa, _state); - } - if( ckind==1 ) - { - sparsecreatecrs(m, n, &rowsizes, sa, _state); - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_neq(da->ptr.pp_double[i][j],(double)(0)) ) - { - sparseset(sa, i, j, da->ptr.pp_double[i][j], _state); - } - } - } - sparseconverttocrs(sa, _state); - ae_frame_leave(_state); - return; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function does test for SparseEnumerate function. - - -- ALGLIB PROJECT -- - Copyright 14.03.2012 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testsparseunit_enumeratetest(ae_state *_state) -{ - ae_frame _frame_block; - sparsematrix spa; - ae_matrix a; - ae_matrix ta; - ae_int_t m; - ae_int_t n; - double r; - double v; - ae_int_t ne; - ae_int_t t0; - ae_int_t t1; - ae_int_t counter; - ae_int_t c; - ae_int_t hashcrs; - ae_int_t i; - ae_int_t j; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&spa, 0, sizeof(spa)); - memset(&a, 0, sizeof(a)); - memset(&ta, 0, sizeof(ta)); - _sparsematrix_init(&spa, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ta, 0, 0, DT_BOOL, _state, ae_true); - - r = 10.5; - for(m=1; m<=30; m++) - { - for(n=1; n<=30; n++) - { - ne = 0; - - /* - * Create matrix with non-zero elements inside the region: - * 0<=In ) - { - ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testsparseunit.ap:3255"); - ae_frame_leave(_state); - return; - } - for(j=0; j<=n-1; j++) - { - wasreturned.ptr.p_bool[j] = ae_false; - } - for(j=0; j<=nz-1; j++) - { - if( colidx.ptr.p_int[j]<0||colidx.ptr.p_int[j]>n ) - { - ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testsparseunit.ap:3264"); - ae_frame_leave(_state); - return; - } - ae_set_error_flag(err, j>0&&colidx.ptr.p_int[j]<=colidx.ptr.p_int[j-1], __FILE__, __LINE__, "testsparseunit.ap:3267"); - ae_set_error_flag(err, ae_fp_neq(vals.ptr.p_double[j],a.ptr.pp_double[i][colidx.ptr.p_int[j]])||ae_fp_neq(vals.ptr.p_double[j],sparseget(&s, i, colidx.ptr.p_int[j], _state)), __FILE__, __LINE__, "testsparseunit.ap:3268"); - wasreturned.ptr.p_bool[colidx.ptr.p_int[j]] = ae_true; - } - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(err, ae_fp_neq(a.ptr.pp_double[i][j],(double)(0))&&!wasreturned.ptr.p_bool[j], __FILE__, __LINE__, "testsparseunit.ap:3272"); - } - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Test for SparseConvert functions(isn't tested ConvertToCRS function). The -function create random dense and sparse matrices in CRS format. Then -convert sparse matrix to some format by CONVERT_TO/COPY_TO functions, -then it does some modification in matrices and compares that marices are -identical. - -NOTE: - Result of the function assigned to variable CopyErrors in unit test. - - -- ALGLIB PROJECT -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testsparseunit_testconvertsm(ae_state *_state) -{ - ae_frame _frame_block; - sparsematrix s; - sparsematrix cs; - ae_matrix a; - ae_int_t m; - ae_int_t n; - ae_int_t msize; - ae_int_t nsize; - ae_vector ner; - double tmp; - ae_int_t i; - ae_int_t j; - ae_int_t vartf; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&cs, 0, sizeof(cs)); - memset(&a, 0, sizeof(a)); - memset(&ner, 0, sizeof(ner)); - _sparsematrix_init(&s, _state, ae_true); - _sparsematrix_init(&cs, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ner, 0, DT_INT, _state, ae_true); - - msize = 15; - nsize = 15; - for(m=1; m<=msize; m++) - { - for(n=1; n<=nsize; n++) - { - for(vartf=0; vartf<=2; vartf++) - { - ae_matrix_set_length(&a, m, n, _state); - ae_vector_set_length(&ner, m, _state); - for(i=0; i<=m-1; i++) - { - ner.ptr.p_int[i] = 0; - for(j=0; j<=n-1; j++) - { - if( ae_randominteger(5, _state)==3 ) - { - ner.ptr.p_int[i] = ner.ptr.p_int[i]+1; - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - else - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - } - - /* - * Create sparse matrix - */ - sparsecreatecrs(m, n, &ner, &s, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_neq(a.ptr.pp_double[i][j],(double)(0)) ) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - sparseset(&s, i, j, a.ptr.pp_double[i][j], _state); - } - } - } - - /* - * Set matrix type(we have to be sure that all formats - * converted correctly) - */ - i = ae_randominteger(2, _state); - if( i==0 ) - { - sparseconverttohash(&s, _state); - } - if( i==1 ) - { - sparseconverttocrs(&s, _state); - } - - /* - * Start test - */ - if( vartf==0 ) - { - sparseconverttohash(&s, _state); - sparsecopy(&s, &cs, _state); - } - if( vartf==1 ) - { - sparsecopytohash(&s, &cs, _state); - } - if( vartf==2 ) - { - sparsecopytocrs(&s, &cs, _state); - } - - /* - * Change some elements in row - */ - if( vartf!=2 ) - { - for(i=0; i<=m-1; i++) - { - tmp = 2*ae_randomreal(_state)-1; - j = ae_randominteger(n, _state); - a.ptr.pp_double[i][j] = tmp; - sparseset(&cs, i, j, tmp, _state); - tmp = 2*ae_randomreal(_state)-1; - j = ae_randominteger(n, _state); - a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+tmp; - sparseadd(&cs, i, j, tmp, _state); - } - } - - /* - * Check that A is identical to S - */ - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_neq(a.ptr.pp_double[i][j],sparseget(&cs, i, j, _state)) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Test for check/get type functions. The function create sparse matrix, -converts it to desired type then check this type. - -NOTE: - Result of the function assigned to variable BasicErrors in unit test. - - -- ALGLIB PROJECT -- - Copyright 23.07.2012 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testsparseunit_testgcmatrixtype(ae_state *_state) -{ - ae_frame _frame_block; - sparsematrix s; - sparsematrix cs; - ae_int_t m; - ae_int_t n; - ae_int_t msize; - ae_int_t nsize; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&cs, 0, sizeof(cs)); - _sparsematrix_init(&s, _state, ae_true); - _sparsematrix_init(&cs, _state, ae_true); - - msize = 5; - nsize = 5; - for(m=1; m<=msize; m++) - { - for(n=1; n<=nsize; n++) - { - sparsecreate(m, n, 1, &s, _state); - sparseconverttocrs(&s, _state); - if( (sparseishash(&s, _state)||!sparseiscrs(&s, _state))||sparsegetmatrixtype(&s, _state)!=1 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - sparseconverttohash(&s, _state); - if( (!sparseishash(&s, _state)||sparseiscrs(&s, _state))||sparsegetmatrixtype(&s, _state)!=0 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - sparsecopytocrs(&s, &cs, _state); - if( (sparseishash(&cs, _state)||!sparseiscrs(&cs, _state))||sparsegetmatrixtype(&cs, _state)!=1 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - sparsecopytohash(&cs, &s, _state); - if( (!sparseishash(&s, _state)||sparseiscrs(&s, _state))||sparsegetmatrixtype(&s, _state)!=0 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -void _sparsegenerator_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - sparsegenerator *p = (sparsegenerator*)_p; - ae_touch_ptr((void*)p); - ae_matrix_init(&p->bufa, 0, 0, DT_REAL, _state, make_automatic); - _hqrndstate_init(&p->rs, _state, make_automatic); - _rcommstate_init(&p->rcs, _state, make_automatic); -} - - -void _sparsegenerator_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - sparsegenerator *dst = (sparsegenerator*)_dst; - sparsegenerator *src = (sparsegenerator*)_src; - dst->n = src->n; - dst->m = src->m; - dst->matkind = src->matkind; - dst->triangle = src->triangle; - ae_matrix_init_copy(&dst->bufa, &src->bufa, _state, make_automatic); - _hqrndstate_init_copy(&dst->rs, &src->rs, _state, make_automatic); - _rcommstate_init_copy(&dst->rcs, &src->rcs, _state, make_automatic); -} - - -void _sparsegenerator_clear(void* _p) -{ - sparsegenerator *p = (sparsegenerator*)_p; - ae_touch_ptr((void*)p); - ae_matrix_clear(&p->bufa); - _hqrndstate_clear(&p->rs); - _rcommstate_clear(&p->rcs); -} - - -void _sparsegenerator_destroy(void* _p) -{ - sparsegenerator *p = (sparsegenerator*)_p; - ae_touch_ptr((void*)p); - ae_matrix_destroy(&p->bufa); - _hqrndstate_destroy(&p->rs); - _rcommstate_destroy(&p->rcs); -} - - - -static ae_bool testablasunit_testtrsm(ae_int_t minn, - ae_int_t maxn, - ae_state *_state); -static ae_bool testablasunit_testsyrk(ae_int_t minn, - ae_int_t maxn, - ae_state *_state); -static ae_bool testablasunit_testgemm(ae_int_t minn, - ae_int_t maxn, - ae_state *_state); -static ae_bool testablasunit_testtrans(ae_int_t minn, - ae_int_t maxn, - ae_state *_state); -static ae_bool testablasunit_testrank1(ae_int_t minn, - ae_int_t maxn, - ae_state *_state); -static ae_bool testablasunit_testgemv(ae_int_t minn, - ae_int_t maxn, - ae_state *_state); -static void testablasunit_testsymv(ae_int_t minn, - ae_int_t maxn, - ae_bool* errorflag, - ae_state *_state); -static void testablasunit_testtrsv(ae_int_t minn, - ae_int_t maxn, - ae_bool* errorflag, - ae_state *_state); -static void testablasunit_spectest(ae_bool* errorflag, ae_state *_state); -static ae_bool testablasunit_testcopy(ae_int_t minn, - ae_int_t maxn, - ae_state *_state); -static void testablasunit_testreflections(ae_bool* errorflag, - ae_state *_state); -static void testablasunit_refcmatrixrighttrsm(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state); -static void testablasunit_refcmatrixlefttrsm(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state); -static void testablasunit_refrmatrixrighttrsm(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state); -static void testablasunit_refrmatrixlefttrsm(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state); -static ae_bool testablasunit_internalcmatrixtrinverse(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunittriangular, - ae_state *_state); -static ae_bool testablasunit_internalrmatrixtrinverse(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunittriangular, - ae_state *_state); -static void testablasunit_refcmatrixherk(ae_int_t n, - ae_int_t k, - double alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state); -static void testablasunit_refrmatrixsyrk(ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state); -static void testablasunit_refcmatrixgemm(ae_int_t m, - ae_int_t n, - ae_int_t k, - ae_complex alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Complex */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - ae_complex beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state); -static void testablasunit_refrmatrixgemm(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state); -static void testablasunit_refrmatrixsymv(ae_int_t n, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_bool isupper, - /* Real */ ae_vector* x, - ae_int_t ix, - double beta, - /* Real */ ae_vector* y, - ae_int_t iy, - ae_state *_state); -static double testablasunit_refrmatrixsyvmv(ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_bool isupper, - /* Real */ ae_vector* x, - ae_int_t ix, - ae_state *_state); - - - - - -ae_bool testablas(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n0; - ae_int_t n1; - ae_bool trsmerrors; - ae_bool syrkerrors; - ae_bool gemmerrors; - ae_bool transerrors; - ae_bool rank1errors; - ae_bool gemverrors; - ae_bool symverrors; - ae_bool trsverrors; - ae_bool reflerrors; - ae_bool copyerrors; - ae_bool specerrors; - ae_bool waserrors; - ae_matrix ra; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&ra, 0, sizeof(ra)); - ae_matrix_init(&ra, 0, 0, DT_REAL, _state, ae_true); - - trsmerrors = ae_false; - syrkerrors = ae_false; - gemmerrors = ae_false; - transerrors = ae_false; - rank1errors = ae_false; - gemverrors = ae_false; - symverrors = ae_false; - trsverrors = ae_false; - reflerrors = ae_false; - copyerrors = ae_false; - waserrors = ae_false; - specerrors = ae_false; - testablasunit_spectest(&specerrors, _state); - trsmerrors = trsmerrors||testablasunit_testtrsm(1, 3*matrixtilesizea(_state)+1, _state); - syrkerrors = syrkerrors||testablasunit_testsyrk(1, 3*matrixtilesizea(_state)+1, _state); - gemmerrors = gemmerrors||testablasunit_testgemm(1, 3*matrixtilesizea(_state)+1, _state); - transerrors = transerrors||testablasunit_testtrans(1, 3*matrixtilesizea(_state)+1, _state); - rank1errors = rank1errors||testablasunit_testrank1(1, 3*matrixtilesizea(_state)+1, _state); - gemverrors = gemverrors||testablasunit_testgemv(1, 3*matrixtilesizea(_state)+1, _state); - copyerrors = copyerrors||testablasunit_testcopy(1, 3*matrixtilesizea(_state)+1, _state); - testablasunit_testsymv(1, 3*matrixtilesizea(_state)+1, &symverrors, _state); - testablasunit_testtrsv(1, 3*matrixtilesizea(_state)+1, &trsverrors, _state); - testablasunit_testreflections(&reflerrors, _state); - n0 = 6*matrixtilesizeb(_state); - n1 = 6*matrixtilesizeb(_state); - gemmerrors = gemmerrors||testablasunit_testgemm(n0, n1, _state); - trsmerrors = trsmerrors||testablasunit_testtrsm(n0, n1, _state); - syrkerrors = syrkerrors||testablasunit_testsyrk(n0, n1, _state); - - /* - * report - */ - waserrors = (((((((((trsmerrors||syrkerrors)||gemmerrors)||transerrors)||rank1errors)||gemverrors)||symverrors)||trsverrors)||reflerrors)||copyerrors)||specerrors; - if( !silent ) - { - printf("TESTING ABLAS\n"); - printf("LEVEL 3 FUNCTIONS:\n"); - printf("* TRSM "); - if( trsmerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* SYRK "); - if( syrkerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* GEMM "); - if( gemmerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("LEVEL 2 FUNCTIONS:\n"); - printf("* TRANS "); - if( transerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* RANK1 "); - if( rank1errors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* GEMV "); - if( gemverrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* SYMV/SYVMV "); - if( symverrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* TRSV "); - if( trsverrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* REFL "); - if( reflerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* COPY "); - if( copyerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("SPECIAL TESTS "); - if( specerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -?Matrix????TRSM tests - -Returns False for passed test, True - for failed -*************************************************************************/ -static ae_bool testablasunit_testtrsm(ae_int_t minn, - ae_int_t maxn, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t m; - ae_int_t mx; - ae_int_t i; - ae_int_t j; - ae_int_t optype; - ae_int_t uppertype; - ae_int_t unittype; - ae_int_t xoffsi; - ae_int_t xoffsj; - ae_int_t aoffsitype; - ae_int_t aoffsjtype; - ae_int_t aoffsi; - ae_int_t aoffsj; - ae_matrix refra; - ae_matrix refrxl; - ae_matrix refrxr; - ae_matrix refca; - ae_matrix refcxl; - ae_matrix refcxr; - ae_matrix ra; - ae_matrix ca; - ae_matrix rxr1; - ae_matrix rxl1; - ae_matrix cxr1; - ae_matrix cxl1; - ae_matrix rxr2; - ae_matrix rxl2; - ae_matrix cxr2; - ae_matrix cxl2; - double threshold; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&refra, 0, sizeof(refra)); - memset(&refrxl, 0, sizeof(refrxl)); - memset(&refrxr, 0, sizeof(refrxr)); - memset(&refca, 0, sizeof(refca)); - memset(&refcxl, 0, sizeof(refcxl)); - memset(&refcxr, 0, sizeof(refcxr)); - memset(&ra, 0, sizeof(ra)); - memset(&ca, 0, sizeof(ca)); - memset(&rxr1, 0, sizeof(rxr1)); - memset(&rxl1, 0, sizeof(rxl1)); - memset(&cxr1, 0, sizeof(cxr1)); - memset(&cxl1, 0, sizeof(cxl1)); - memset(&rxr2, 0, sizeof(rxr2)); - memset(&rxl2, 0, sizeof(rxl2)); - memset(&cxr2, 0, sizeof(cxr2)); - memset(&cxl2, 0, sizeof(cxl2)); - ae_matrix_init(&refra, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&refrxl, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&refrxr, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&refca, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&refcxl, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&refcxr, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&ra, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ca, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&rxr1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&rxl1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&cxr1, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&cxl1, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&rxr2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&rxl2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&cxr2, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&cxl2, 0, 0, DT_COMPLEX, _state, ae_true); - - threshold = ae_sqr((double)(maxn), _state)*100*ae_machineepsilon; - result = ae_false; - for(mx=minn; mx<=maxn; mx++) - { - - /* - * Select random M/N in [1,MX] such that max(M,N)=MX - */ - m = 1+ae_randominteger(mx, _state); - n = 1+ae_randominteger(mx, _state); - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - m = mx; - } - else - { - n = mx; - } - - /* - * Initialize RefRA/RefCA by random matrices whose upper - * and lower triangle submatrices are non-degenerate - * well-conditioned matrices. - * - * Matrix size is 2Mx2M (four copies of same MxM matrix - * to test different offsets) - */ - ae_matrix_set_length(&refra, 2*m, 2*m, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - refra.ptr.pp_double[i][j] = 0.2*ae_randomreal(_state)-0.1; - } - } - for(i=0; i<=m-1; i++) - { - refra.ptr.pp_double[i][i] = (2*ae_randominteger(1, _state)-1)*(2*m+ae_randomreal(_state)); - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - refra.ptr.pp_double[i+m][j] = refra.ptr.pp_double[i][j]; - refra.ptr.pp_double[i][j+m] = refra.ptr.pp_double[i][j]; - refra.ptr.pp_double[i+m][j+m] = refra.ptr.pp_double[i][j]; - } - } - ae_matrix_set_length(&refca, 2*m, 2*m, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - refca.ptr.pp_complex[i][j].x = 0.2*ae_randomreal(_state)-0.1; - refca.ptr.pp_complex[i][j].y = 0.2*ae_randomreal(_state)-0.1; - } - } - for(i=0; i<=m-1; i++) - { - refca.ptr.pp_complex[i][i].x = (2*ae_randominteger(2, _state)-1)*(2*m+ae_randomreal(_state)); - refca.ptr.pp_complex[i][i].y = (2*ae_randominteger(2, _state)-1)*(2*m+ae_randomreal(_state)); - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - refca.ptr.pp_complex[i+m][j] = refca.ptr.pp_complex[i][j]; - refca.ptr.pp_complex[i][j+m] = refca.ptr.pp_complex[i][j]; - refca.ptr.pp_complex[i+m][j+m] = refca.ptr.pp_complex[i][j]; - } - } - - /* - * Generate random XL/XR. - * - * XR is NxM matrix (matrix for 'Right' subroutines) - * XL is MxN matrix (matrix for 'Left' subroutines) - */ - ae_matrix_set_length(&refrxr, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - refrxr.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - ae_matrix_set_length(&refrxl, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - refrxl.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - ae_matrix_set_length(&refcxr, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - refcxr.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - refcxr.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - ae_matrix_set_length(&refcxl, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - refcxl.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - refcxl.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - - /* - * test different types of operations, offsets, and so on... - * - * to avoid unnecessary slowdown we don't test ALL possible - * combinations of operation types. We just generate one random - * set of parameters and test it. - */ - ae_matrix_set_length(&ra, 2*m, 2*m, _state); - ae_matrix_set_length(&rxr1, n, m, _state); - ae_matrix_set_length(&rxr2, n, m, _state); - ae_matrix_set_length(&rxl1, m, n, _state); - ae_matrix_set_length(&rxl2, m, n, _state); - ae_matrix_set_length(&ca, 2*m, 2*m, _state); - ae_matrix_set_length(&cxr1, n, m, _state); - ae_matrix_set_length(&cxr2, n, m, _state); - ae_matrix_set_length(&cxl1, m, n, _state); - ae_matrix_set_length(&cxl2, m, n, _state); - optype = ae_randominteger(3, _state); - uppertype = ae_randominteger(2, _state); - unittype = ae_randominteger(2, _state); - xoffsi = ae_randominteger(2, _state); - xoffsj = ae_randominteger(2, _state); - aoffsitype = ae_randominteger(2, _state); - aoffsjtype = ae_randominteger(2, _state); - aoffsi = m*aoffsitype; - aoffsj = m*aoffsjtype; - - /* - * copy A, XR, XL (fill unused parts with random garbage) - */ - for(i=0; i<=2*m-1; i++) - { - for(j=0; j<=2*m-1; j++) - { - if( ((i>=aoffsi&&i=aoffsj)&&j=xoffsi&&j>=xoffsj ) - { - cxr1.ptr.pp_complex[i][j] = refcxr.ptr.pp_complex[i][j]; - cxr2.ptr.pp_complex[i][j] = refcxr.ptr.pp_complex[i][j]; - rxr1.ptr.pp_double[i][j] = refrxr.ptr.pp_double[i][j]; - rxr2.ptr.pp_double[i][j] = refrxr.ptr.pp_double[i][j]; - } - else - { - cxr1.ptr.pp_complex[i][j] = ae_complex_from_d(ae_randomreal(_state)); - cxr2.ptr.pp_complex[i][j] = cxr1.ptr.pp_complex[i][j]; - rxr1.ptr.pp_double[i][j] = ae_randomreal(_state); - rxr2.ptr.pp_double[i][j] = rxr1.ptr.pp_double[i][j]; - } - } - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i>=xoffsi&&j>=xoffsj ) - { - cxl1.ptr.pp_complex[i][j] = refcxl.ptr.pp_complex[i][j]; - cxl2.ptr.pp_complex[i][j] = refcxl.ptr.pp_complex[i][j]; - rxl1.ptr.pp_double[i][j] = refrxl.ptr.pp_double[i][j]; - rxl2.ptr.pp_double[i][j] = refrxl.ptr.pp_double[i][j]; - } - else - { - cxl1.ptr.pp_complex[i][j] = ae_complex_from_d(ae_randomreal(_state)); - cxl2.ptr.pp_complex[i][j] = cxl1.ptr.pp_complex[i][j]; - rxl1.ptr.pp_double[i][j] = ae_randomreal(_state); - rxl2.ptr.pp_double[i][j] = rxl1.ptr.pp_double[i][j]; - } - } - } - - /* - * Test CXR - */ - cmatrixrighttrsm(n-xoffsi, m-xoffsj, &ca, aoffsi, aoffsj, uppertype==0, unittype==0, optype, &cxr1, xoffsi, xoffsj, _state); - testablasunit_refcmatrixrighttrsm(n-xoffsi, m-xoffsj, &ca, aoffsi, aoffsj, uppertype==0, unittype==0, optype, &cxr2, xoffsi, xoffsj, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - result = result||ae_fp_greater(ae_c_abs(ae_c_sub(cxr1.ptr.pp_complex[i][j],cxr2.ptr.pp_complex[i][j]), _state),threshold); - } - } - - /* - * Test CXL - */ - cmatrixlefttrsm(m-xoffsi, n-xoffsj, &ca, aoffsi, aoffsj, uppertype==0, unittype==0, optype, &cxl1, xoffsi, xoffsj, _state); - testablasunit_refcmatrixlefttrsm(m-xoffsi, n-xoffsj, &ca, aoffsi, aoffsj, uppertype==0, unittype==0, optype, &cxl2, xoffsi, xoffsj, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - result = result||ae_fp_greater(ae_c_abs(ae_c_sub(cxl1.ptr.pp_complex[i][j],cxl2.ptr.pp_complex[i][j]), _state),threshold); - } - } - if( optype<2 ) - { - - /* - * Test RXR - */ - rmatrixrighttrsm(n-xoffsi, m-xoffsj, &ra, aoffsi, aoffsj, uppertype==0, unittype==0, optype, &rxr1, xoffsi, xoffsj, _state); - testablasunit_refrmatrixrighttrsm(n-xoffsi, m-xoffsj, &ra, aoffsi, aoffsj, uppertype==0, unittype==0, optype, &rxr2, xoffsi, xoffsj, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - result = result||ae_fp_greater(ae_fabs(rxr1.ptr.pp_double[i][j]-rxr2.ptr.pp_double[i][j], _state),threshold); - } - } - - /* - * Test RXL - */ - rmatrixlefttrsm(m-xoffsi, n-xoffsj, &ra, aoffsi, aoffsj, uppertype==0, unittype==0, optype, &rxl1, xoffsi, xoffsj, _state); - testablasunit_refrmatrixlefttrsm(m-xoffsi, n-xoffsj, &ra, aoffsi, aoffsj, uppertype==0, unittype==0, optype, &rxl2, xoffsi, xoffsj, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - result = result||ae_fp_greater(ae_fabs(rxl1.ptr.pp_double[i][j]-rxl2.ptr.pp_double[i][j], _state),threshold); - } - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -SYRK tests - -Returns False for passed test, True - for failed -*************************************************************************/ -static ae_bool testablasunit_testsyrk(ae_int_t minn, - ae_int_t maxn, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t k; - ae_int_t mx; - ae_int_t i; - ae_int_t j; - ae_int_t uppertype; - ae_int_t xoffsi; - ae_int_t xoffsj; - ae_int_t aoffsitype; - ae_int_t aoffsjtype; - ae_int_t aoffsi; - ae_int_t aoffsj; - ae_int_t alphatype; - ae_int_t betatype; - ae_matrix refra; - ae_matrix refrc; - ae_matrix refca; - ae_matrix refcc; - double alpha; - double beta; - ae_matrix ra1; - ae_matrix ra2; - ae_matrix ca1; - ae_matrix ca2; - ae_matrix rc; - ae_matrix rct; - ae_matrix cc; - ae_matrix cct; - double threshold; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&refra, 0, sizeof(refra)); - memset(&refrc, 0, sizeof(refrc)); - memset(&refca, 0, sizeof(refca)); - memset(&refcc, 0, sizeof(refcc)); - memset(&ra1, 0, sizeof(ra1)); - memset(&ra2, 0, sizeof(ra2)); - memset(&ca1, 0, sizeof(ca1)); - memset(&ca2, 0, sizeof(ca2)); - memset(&rc, 0, sizeof(rc)); - memset(&rct, 0, sizeof(rct)); - memset(&cc, 0, sizeof(cc)); - memset(&cct, 0, sizeof(cct)); - ae_matrix_init(&refra, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&refrc, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&refca, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&refcc, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&ra1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ra2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ca1, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&ca2, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&rc, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&rct, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&cc, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&cct, 0, 0, DT_COMPLEX, _state, ae_true); - - threshold = maxn*100*ae_machineepsilon; - result = ae_false; - for(mx=minn; mx<=maxn; mx++) - { - - /* - * Select random M/N in [1,MX] such that max(M,N)=MX - */ - k = 1+ae_randominteger(mx, _state); - n = 1+ae_randominteger(mx, _state); - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - k = mx; - } - else - { - n = mx; - } - - /* - * Initialize RefRA/RefCA by random Hermitian matrices, - * RefRC/RefCC by random matrices - * - * RA/CA size is 2Nx2N (four copies of same NxN matrix - * to test different offsets) - */ - ae_matrix_set_length(&refra, 2*n, 2*n, _state); - ae_matrix_set_length(&refca, 2*n, 2*n, _state); - for(i=0; i<=n-1; i++) - { - refra.ptr.pp_double[i][i] = 2*ae_randomreal(_state)-1; - refca.ptr.pp_complex[i][i] = ae_complex_from_d(2*ae_randomreal(_state)-1); - for(j=i+1; j<=n-1; j++) - { - refra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - refca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - refca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - refra.ptr.pp_double[j][i] = refra.ptr.pp_double[i][j]; - refca.ptr.pp_complex[j][i] = ae_c_conj(refca.ptr.pp_complex[i][j], _state); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - refra.ptr.pp_double[i+n][j] = refra.ptr.pp_double[i][j]; - refra.ptr.pp_double[i][j+n] = refra.ptr.pp_double[i][j]; - refra.ptr.pp_double[i+n][j+n] = refra.ptr.pp_double[i][j]; - refca.ptr.pp_complex[i+n][j] = refca.ptr.pp_complex[i][j]; - refca.ptr.pp_complex[i][j+n] = refca.ptr.pp_complex[i][j]; - refca.ptr.pp_complex[i+n][j+n] = refca.ptr.pp_complex[i][j]; - } - } - ae_matrix_set_length(&refrc, n, k, _state); - ae_matrix_set_length(&refcc, n, k, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=k-1; j++) - { - refrc.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - refcc.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - refcc.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - - /* - * test different types of operations, offsets, and so on... - * - * to avoid unnecessary slowdown we don't test ALL possible - * combinations of operation types. We just generate one random - * set of parameters and test it. - */ - ae_matrix_set_length(&ra1, 2*n, 2*n, _state); - ae_matrix_set_length(&ra2, 2*n, 2*n, _state); - ae_matrix_set_length(&ca1, 2*n, 2*n, _state); - ae_matrix_set_length(&ca2, 2*n, 2*n, _state); - ae_matrix_set_length(&rc, n, k, _state); - ae_matrix_set_length(&rct, k, n, _state); - ae_matrix_set_length(&cc, n, k, _state); - ae_matrix_set_length(&cct, k, n, _state); - uppertype = ae_randominteger(2, _state); - xoffsi = ae_randominteger(2, _state); - xoffsj = ae_randominteger(2, _state); - aoffsitype = ae_randominteger(2, _state); - aoffsjtype = ae_randominteger(2, _state); - alphatype = ae_randominteger(2, _state); - betatype = ae_randominteger(2, _state); - aoffsi = n*aoffsitype; - aoffsj = n*aoffsjtype; - alpha = alphatype*(2*ae_randomreal(_state)-1); - beta = betatype*(2*ae_randomreal(_state)-1); - - /* - * copy A, C (fill unused parts with random garbage) - */ - for(i=0; i<=2*n-1; i++) - { - for(j=0; j<=2*n-1; j++) - { - if( ((i>=aoffsi&&i=aoffsj)&&j=xoffsi&&j>=xoffsj ) - { - rc.ptr.pp_double[i][j] = refrc.ptr.pp_double[i][j]; - rct.ptr.pp_double[j][i] = refrc.ptr.pp_double[i][j]; - cc.ptr.pp_complex[i][j] = refcc.ptr.pp_complex[i][j]; - cct.ptr.pp_complex[j][i] = refcc.ptr.pp_complex[i][j]; - } - else - { - rc.ptr.pp_double[i][j] = ae_randomreal(_state); - rct.ptr.pp_double[j][i] = rc.ptr.pp_double[i][j]; - cc.ptr.pp_complex[i][j] = ae_complex_from_d(ae_randomreal(_state)); - cct.ptr.pp_complex[j][i] = cct.ptr.pp_complex[j][i]; - } - } - } - - /* - * Test complex - * Only one of transform types is selected and tested - */ - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - cmatrixherk(n-xoffsi, k-xoffsj, alpha, &cc, xoffsi, xoffsj, 0, beta, &ca1, aoffsi, aoffsj, uppertype==0, _state); - testablasunit_refcmatrixherk(n-xoffsi, k-xoffsj, alpha, &cc, xoffsi, xoffsj, 0, beta, &ca2, aoffsi, aoffsj, uppertype==0, _state); - } - else - { - cmatrixherk(n-xoffsi, k-xoffsj, alpha, &cct, xoffsj, xoffsi, 2, beta, &ca1, aoffsi, aoffsj, uppertype==0, _state); - testablasunit_refcmatrixherk(n-xoffsi, k-xoffsj, alpha, &cct, xoffsj, xoffsi, 2, beta, &ca2, aoffsi, aoffsj, uppertype==0, _state); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - result = result||ae_fp_greater(ae_c_abs(ae_c_sub(ca1.ptr.pp_complex[i][j],ca2.ptr.pp_complex[i][j]), _state),threshold); - } - } - - /* - * Test old version of HERK (named SYRK) - * Only one of transform types is selected and tested - */ - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - cmatrixsyrk(n-xoffsi, k-xoffsj, alpha, &cc, xoffsi, xoffsj, 0, beta, &ca1, aoffsi, aoffsj, uppertype==0, _state); - testablasunit_refcmatrixherk(n-xoffsi, k-xoffsj, alpha, &cc, xoffsi, xoffsj, 0, beta, &ca2, aoffsi, aoffsj, uppertype==0, _state); - } - else - { - cmatrixsyrk(n-xoffsi, k-xoffsj, alpha, &cct, xoffsj, xoffsi, 2, beta, &ca1, aoffsi, aoffsj, uppertype==0, _state); - testablasunit_refcmatrixherk(n-xoffsi, k-xoffsj, alpha, &cct, xoffsj, xoffsi, 2, beta, &ca2, aoffsi, aoffsj, uppertype==0, _state); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - result = result||ae_fp_greater(ae_c_abs(ae_c_sub(ca1.ptr.pp_complex[i][j],ca2.ptr.pp_complex[i][j]), _state),threshold); - } - } - - /* - * Test real - * Only one of transform types is selected and tested - */ - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - rmatrixsyrk(n-xoffsi, k-xoffsj, alpha, &rc, xoffsi, xoffsj, 0, beta, &ra1, aoffsi, aoffsj, uppertype==0, _state); - testablasunit_refrmatrixsyrk(n-xoffsi, k-xoffsj, alpha, &rc, xoffsi, xoffsj, 0, beta, &ra2, aoffsi, aoffsj, uppertype==0, _state); - } - else - { - rmatrixsyrk(n-xoffsi, k-xoffsj, alpha, &rct, xoffsj, xoffsi, 1, beta, &ra1, aoffsi, aoffsj, uppertype==0, _state); - testablasunit_refrmatrixsyrk(n-xoffsi, k-xoffsj, alpha, &rct, xoffsj, xoffsi, 1, beta, &ra2, aoffsi, aoffsj, uppertype==0, _state); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - result = result||ae_fp_greater(ae_fabs(ra1.ptr.pp_double[i][j]-ra2.ptr.pp_double[i][j], _state),threshold); - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -GEMM tests - -Returns False for passed test, True - for failed -*************************************************************************/ -static ae_bool testablasunit_testgemm(ae_int_t minn, - ae_int_t maxn, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t m; - ae_int_t n; - ae_int_t k; - ae_int_t mx; - ae_int_t i; - ae_int_t j; - ae_int_t aoffsi; - ae_int_t aoffsj; - ae_int_t aoptype; - ae_int_t aoptyper; - ae_int_t boffsi; - ae_int_t boffsj; - ae_int_t boptype; - ae_int_t boptyper; - ae_int_t coffsi; - ae_int_t coffsj; - ae_matrix refra; - ae_matrix refrb; - ae_matrix refrc; - ae_matrix refca; - ae_matrix refcb; - ae_matrix refcc; - double alphar; - double betar; - ae_complex alphac; - ae_complex betac; - ae_matrix rc1; - ae_matrix rc2; - ae_matrix cc1; - ae_matrix cc2; - double threshold; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&refra, 0, sizeof(refra)); - memset(&refrb, 0, sizeof(refrb)); - memset(&refrc, 0, sizeof(refrc)); - memset(&refca, 0, sizeof(refca)); - memset(&refcb, 0, sizeof(refcb)); - memset(&refcc, 0, sizeof(refcc)); - memset(&rc1, 0, sizeof(rc1)); - memset(&rc2, 0, sizeof(rc2)); - memset(&cc1, 0, sizeof(cc1)); - memset(&cc2, 0, sizeof(cc2)); - ae_matrix_init(&refra, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&refrb, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&refrc, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&refca, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&refcb, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&refcc, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&rc1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&rc2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&cc1, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&cc2, 0, 0, DT_COMPLEX, _state, ae_true); - - threshold = maxn*100*ae_machineepsilon; - result = ae_false; - for(mx=minn; mx<=maxn; mx++) - { - - /* - * Select random M/N/K in [1,MX] such that max(M,N,K)=MX - */ - m = 1+ae_randominteger(mx, _state); - n = 1+ae_randominteger(mx, _state); - k = 1+ae_randominteger(mx, _state); - i = ae_randominteger(3, _state); - if( i==0 ) - { - m = mx; - } - if( i==1 ) - { - n = mx; - } - if( i==2 ) - { - k = mx; - } - - /* - * Initialize A/B/C by random matrices with size (MaxN+1)*(MaxN+1) - */ - ae_matrix_set_length(&refra, maxn+1, maxn+1, _state); - ae_matrix_set_length(&refrb, maxn+1, maxn+1, _state); - ae_matrix_set_length(&refrc, maxn+1, maxn+1, _state); - ae_matrix_set_length(&refca, maxn+1, maxn+1, _state); - ae_matrix_set_length(&refcb, maxn+1, maxn+1, _state); - ae_matrix_set_length(&refcc, maxn+1, maxn+1, _state); - for(i=0; i<=maxn; i++) - { - for(j=0; j<=maxn; j++) - { - refra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - refrb.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - refrc.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - refca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - refca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - refcb.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - refcb.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - refcc.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - refcc.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - - /* - * test different types of operations, offsets, and so on... - * - * to avoid unnecessary slowdown we don't test ALL possible - * combinations of operation types. We just generate one random - * set of parameters and test it. - */ - ae_matrix_set_length(&rc1, maxn+1, maxn+1, _state); - ae_matrix_set_length(&rc2, maxn+1, maxn+1, _state); - ae_matrix_set_length(&cc1, maxn+1, maxn+1, _state); - ae_matrix_set_length(&cc2, maxn+1, maxn+1, _state); - aoffsi = ae_randominteger(2, _state); - aoffsj = ae_randominteger(2, _state); - aoptype = ae_randominteger(3, _state); - aoptyper = ae_randominteger(2, _state); - boffsi = ae_randominteger(2, _state); - boffsj = ae_randominteger(2, _state); - boptype = ae_randominteger(3, _state); - boptyper = ae_randominteger(2, _state); - coffsi = ae_randominteger(2, _state); - coffsj = ae_randominteger(2, _state); - alphar = ae_randominteger(2, _state)*(2*ae_randomreal(_state)-1); - betar = ae_randominteger(2, _state)*(2*ae_randomreal(_state)-1); - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - alphac.x = 2*ae_randomreal(_state)-1; - alphac.y = 2*ae_randomreal(_state)-1; - } - else - { - alphac = ae_complex_from_i(0); - } - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - betac.x = 2*ae_randomreal(_state)-1; - betac.y = 2*ae_randomreal(_state)-1; - } - else - { - betac = ae_complex_from_i(0); - } - - /* - * copy C - */ - for(i=0; i<=maxn; i++) - { - for(j=0; j<=maxn; j++) - { - rc1.ptr.pp_double[i][j] = refrc.ptr.pp_double[i][j]; - rc2.ptr.pp_double[i][j] = refrc.ptr.pp_double[i][j]; - cc1.ptr.pp_complex[i][j] = refcc.ptr.pp_complex[i][j]; - cc2.ptr.pp_complex[i][j] = refcc.ptr.pp_complex[i][j]; - } - } - - /* - * Test complex - */ - cmatrixgemm(m, n, k, alphac, &refca, aoffsi, aoffsj, aoptype, &refcb, boffsi, boffsj, boptype, betac, &cc1, coffsi, coffsj, _state); - testablasunit_refcmatrixgemm(m, n, k, alphac, &refca, aoffsi, aoffsj, aoptype, &refcb, boffsi, boffsj, boptype, betac, &cc2, coffsi, coffsj, _state); - for(i=0; i<=maxn; i++) - { - for(j=0; j<=maxn; j++) - { - result = result||ae_fp_greater(ae_c_abs(ae_c_sub(cc1.ptr.pp_complex[i][j],cc2.ptr.pp_complex[i][j]), _state),threshold); - } - } - - /* - * Test real - */ - rmatrixgemm(m, n, k, alphar, &refra, aoffsi, aoffsj, aoptyper, &refrb, boffsi, boffsj, boptyper, betar, &rc1, coffsi, coffsj, _state); - testablasunit_refrmatrixgemm(m, n, k, alphar, &refra, aoffsi, aoffsj, aoptyper, &refrb, boffsi, boffsj, boptyper, betar, &rc2, coffsi, coffsj, _state); - for(i=0; i<=maxn; i++) - { - for(j=0; j<=maxn; j++) - { - result = result||ae_fp_greater(ae_fabs(rc1.ptr.pp_double[i][j]-rc2.ptr.pp_double[i][j], _state),threshold); - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -transpose tests - -Returns False for passed test, True - for failed -*************************************************************************/ -static ae_bool testablasunit_testtrans(ae_int_t minn, - ae_int_t maxn, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t m; - ae_int_t n; - ae_int_t mx; - ae_int_t i; - ae_int_t j; - ae_int_t aoffsi; - ae_int_t aoffsj; - ae_int_t boffsi; - ae_int_t boffsj; - double v1; - double v2; - double threshold; - ae_matrix refra; - ae_matrix refrb; - ae_matrix refca; - ae_matrix refcb; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&refra, 0, sizeof(refra)); - memset(&refrb, 0, sizeof(refrb)); - memset(&refca, 0, sizeof(refca)); - memset(&refcb, 0, sizeof(refcb)); - ae_matrix_init(&refra, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&refrb, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&refca, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&refcb, 0, 0, DT_COMPLEX, _state, ae_true); - - result = ae_false; - threshold = 1000*ae_machineepsilon; - for(mx=minn; mx<=maxn; mx++) - { - - /* - * Select random M/N in [1,MX] such that max(M,N)=MX - * Generate random V1 and V2 which are used to fill - * RefRB/RefCB with control values. - */ - m = 1+ae_randominteger(mx, _state); - n = 1+ae_randominteger(mx, _state); - if( ae_randominteger(2, _state)==0 ) - { - m = mx; - } - else - { - n = mx; - } - v1 = ae_randomreal(_state); - v2 = ae_randomreal(_state); - - /* - * Initialize A by random matrix with size (MaxN+1)*(MaxN+1) - * Fill B with control values - */ - ae_matrix_set_length(&refra, maxn+1, maxn+1, _state); - ae_matrix_set_length(&refrb, maxn+1, maxn+1, _state); - ae_matrix_set_length(&refca, maxn+1, maxn+1, _state); - ae_matrix_set_length(&refcb, maxn+1, maxn+1, _state); - for(i=0; i<=maxn; i++) - { - for(j=0; j<=maxn; j++) - { - refra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - refca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - refca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - refrb.ptr.pp_double[i][j] = i*v1+j*v2; - refcb.ptr.pp_complex[i][j] = ae_complex_from_d(i*v1+j*v2); - } - } - - /* - * test different offsets (zero or one) - * - * to avoid unnecessary slowdown we don't test ALL possible - * combinations of operation types. We just generate one random - * set of parameters and test it. - */ - aoffsi = ae_randominteger(2, _state); - aoffsj = ae_randominteger(2, _state); - boffsi = ae_randominteger(2, _state); - boffsj = ae_randominteger(2, _state); - rmatrixtranspose(m, n, &refra, aoffsi, aoffsj, &refrb, boffsi, boffsj, _state); - for(i=0; i<=maxn; i++) - { - for(j=0; j<=maxn; j++) - { - if( ((i=boffsi+n)||j=boffsj+m ) - { - result = result||ae_fp_greater(ae_fabs(refrb.ptr.pp_double[i][j]-(v1*i+v2*j), _state),threshold); - } - else - { - result = result||ae_fp_greater(ae_fabs(refrb.ptr.pp_double[i][j]-refra.ptr.pp_double[aoffsi+j-boffsj][aoffsj+i-boffsi], _state),threshold); - } - } - } - cmatrixtranspose(m, n, &refca, aoffsi, aoffsj, &refcb, boffsi, boffsj, _state); - for(i=0; i<=maxn; i++) - { - for(j=0; j<=maxn; j++) - { - if( ((i=boffsi+n)||j=boffsj+m ) - { - result = result||ae_fp_greater(ae_c_abs(ae_c_sub_d(refcb.ptr.pp_complex[i][j],v1*i+v2*j), _state),threshold); - } - else - { - result = result||ae_fp_greater(ae_c_abs(ae_c_sub(refcb.ptr.pp_complex[i][j],refca.ptr.pp_complex[aoffsi+j-boffsj][aoffsj+i-boffsi]), _state),threshold); - } - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -rank-1tests - -Returns False for passed test, True - for failed -*************************************************************************/ -static ae_bool testablasunit_testrank1(ae_int_t minn, - ae_int_t maxn, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t m; - ae_int_t n; - ae_int_t mx; - ae_int_t i; - ae_int_t j; - ae_int_t aoffsi; - ae_int_t aoffsj; - ae_int_t uoffs; - ae_int_t voffs; - double threshold; - double ralpha; - ae_matrix refra; - ae_matrix refrb; - ae_matrix refca; - ae_matrix refcb; - ae_vector ru; - ae_vector rv; - ae_vector cu; - ae_vector cv; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&refra, 0, sizeof(refra)); - memset(&refrb, 0, sizeof(refrb)); - memset(&refca, 0, sizeof(refca)); - memset(&refcb, 0, sizeof(refcb)); - memset(&ru, 0, sizeof(ru)); - memset(&rv, 0, sizeof(rv)); - memset(&cu, 0, sizeof(cu)); - memset(&cv, 0, sizeof(cv)); - ae_matrix_init(&refra, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&refrb, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&refca, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&refcb, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&ru, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rv, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cu, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&cv, 0, DT_COMPLEX, _state, ae_true); - - result = ae_false; - threshold = 1000*ae_machineepsilon; - for(mx=minn; mx<=maxn; mx++) - { - - /* - * Select random M/N in [1,MX] such that max(M,N)=MX - */ - m = 1+ae_randominteger(mx, _state); - n = 1+ae_randominteger(mx, _state); - if( ae_randominteger(2, _state)==0 ) - { - m = mx; - } - else - { - n = mx; - } - - /* - * Initialize A by random matrix with size (MaxN+1)*(MaxN+1) - * Fill B with control values - */ - ae_matrix_set_length(&refra, maxn+maxn, maxn+maxn, _state); - ae_matrix_set_length(&refrb, maxn+maxn, maxn+maxn, _state); - ae_matrix_set_length(&refca, maxn+maxn, maxn+maxn, _state); - ae_matrix_set_length(&refcb, maxn+maxn, maxn+maxn, _state); - for(i=0; i<=2*maxn-1; i++) - { - for(j=0; j<=2*maxn-1; j++) - { - refrb.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - refcb.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - refcb.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - ae_vector_set_length(&ru, 2*m, _state); - ae_vector_set_length(&cu, 2*m, _state); - for(i=0; i<=2*m-1; i++) - { - ru.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - cu.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1; - cu.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1; - } - ae_vector_set_length(&rv, 2*n, _state); - ae_vector_set_length(&cv, 2*n, _state); - for(i=0; i<=2*n-1; i++) - { - rv.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - cv.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1; - cv.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1; - } - - /* - * Generate random offsets of all operands and random coefficients. - */ - aoffsi = ae_randominteger(maxn, _state); - aoffsj = ae_randominteger(maxn, _state); - uoffs = ae_randominteger(m, _state); - voffs = ae_randominteger(n, _state); - ralpha = ae_randomreal(_state)-0.5; - - /* - * Test CMatrixRank1() and deprecated RMatrixRank1() - */ - for(i=0; i<=2*maxn-1; i++) - { - for(j=0; j<=2*maxn-1; j++) - { - refca.ptr.pp_complex[i][j] = refcb.ptr.pp_complex[i][j]; - } - } - cmatrixrank1(m, n, &refca, aoffsi, aoffsj, &cu, uoffs, &cv, voffs, _state); - for(i=0; i<=2*maxn-1; i++) - { - for(j=0; j<=2*maxn-1; j++) - { - if( ((i=aoffsi+m)||j=aoffsj+n ) - { - result = result||ae_fp_greater(ae_c_abs(ae_c_sub(refca.ptr.pp_complex[i][j],refcb.ptr.pp_complex[i][j]), _state),threshold); - } - else - { - result = result||ae_fp_greater(ae_c_abs(ae_c_sub(refca.ptr.pp_complex[i][j],ae_c_add(refcb.ptr.pp_complex[i][j],ae_c_mul(cu.ptr.p_complex[i-aoffsi+uoffs],cv.ptr.p_complex[j-aoffsj+voffs]))), _state),threshold); - } - } - } - for(i=0; i<=2*maxn-1; i++) - { - for(j=0; j<=2*maxn-1; j++) - { - refra.ptr.pp_double[i][j] = refrb.ptr.pp_double[i][j]; - } - } - rmatrixrank1(m, n, &refra, aoffsi, aoffsj, &ru, uoffs, &rv, voffs, _state); - for(i=0; i<=2*maxn-1; i++) - { - for(j=0; j<=2*maxn-1; j++) - { - if( ((i=aoffsi+m)||j=aoffsj+n ) - { - result = result||ae_fp_greater(ae_fabs(refra.ptr.pp_double[i][j]-refrb.ptr.pp_double[i][j], _state),threshold); - } - else - { - result = result||ae_fp_greater(ae_fabs(refra.ptr.pp_double[i][j]-(refrb.ptr.pp_double[i][j]+ru.ptr.p_double[i-aoffsi+uoffs]*rv.ptr.p_double[j-aoffsj+voffs]), _state),threshold); - } - } - } - - /* - * Test modern RMatrixGER() - */ - for(i=0; i<=2*maxn-1; i++) - { - for(j=0; j<=2*maxn-1; j++) - { - refra.ptr.pp_double[i][j] = refrb.ptr.pp_double[i][j]; - } - } - rmatrixger(m, n, &refra, aoffsi, aoffsj, ralpha, &ru, uoffs, &rv, voffs, _state); - for(i=0; i<=2*maxn-1; i++) - { - for(j=0; j<=2*maxn-1; j++) - { - if( ((i=aoffsi+m)||j=aoffsj+n ) - { - ae_set_error_flag(&result, ae_fp_neq(ae_fabs(refra.ptr.pp_double[i][j]-refrb.ptr.pp_double[i][j], _state),0.0), __FILE__, __LINE__, "testablasunit.ap:1132"); - } - else - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(refra.ptr.pp_double[i][j]-(refrb.ptr.pp_double[i][j]+ralpha*ru.ptr.p_double[i-aoffsi+uoffs]*rv.ptr.p_double[j-aoffsj+voffs]), _state),threshold), __FILE__, __LINE__, "testablasunit.ap:1134"); - } - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -MV tests - -Returns False for passed test, True - for failed -*************************************************************************/ -static ae_bool testablasunit_testgemv(ae_int_t minn, - ae_int_t maxn, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t m; - ae_int_t n; - ae_int_t mx; - ae_int_t i; - ae_int_t j; - ae_int_t aoffsi; - ae_int_t aoffsj; - ae_int_t xoffs; - ae_int_t yoffs; - ae_int_t opca; - ae_int_t opra; - double threshold; - double ralpha; - double rbeta; - double rv1; - double rv2; - ae_complex cv1; - ae_complex cv2; - ae_matrix refra; - ae_matrix refca; - ae_vector rx; - ae_vector ry; - ae_vector cx; - ae_vector cy; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&refra, 0, sizeof(refra)); - memset(&refca, 0, sizeof(refca)); - memset(&rx, 0, sizeof(rx)); - memset(&ry, 0, sizeof(ry)); - memset(&cx, 0, sizeof(cx)); - memset(&cy, 0, sizeof(cy)); - ae_matrix_init(&refra, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&refca, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&rx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ry, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cx, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&cy, 0, DT_COMPLEX, _state, ae_true); - - result = ae_false; - threshold = 1000*ae_machineepsilon; - for(mx=minn; mx<=maxn; mx++) - { - - /* - * Select random M/N in [1,MX] such that max(M,N)=MX - */ - m = 1+ae_randominteger(mx, _state); - n = 1+ae_randominteger(mx, _state); - if( ae_randominteger(2, _state)==0 ) - { - m = mx; - } - else - { - n = mx; - } - - /* - * Initialize A by random matrix with size (MaxN+MaxN)*(MaxN+MaxN) - * Initialize X by random vector with size (MaxN+MaxN) - * Fill Y by control values - */ - ae_matrix_set_length(&refra, maxn+maxn, maxn+maxn, _state); - ae_matrix_set_length(&refca, maxn+maxn, maxn+maxn, _state); - for(i=0; i<=2*maxn-1; i++) - { - for(j=0; j<=2*maxn-1; j++) - { - refra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - refca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - refca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - ae_vector_set_length(&rx, 2*maxn, _state); - ae_vector_set_length(&cx, 2*maxn, _state); - ae_vector_set_length(&ry, 2*maxn, _state); - ae_vector_set_length(&cy, 2*maxn, _state); - for(i=0; i<=2*maxn-1; i++) - { - rx.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - cx.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1; - cx.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1; - } - - /* - * Select random offsets and operations. - * - * To avoid unnecessary slowdown we don't test ALL possible - * combinations of operation types. We just generate one random - * set of parameters and test it. - */ - aoffsi = ae_randominteger(maxn, _state); - aoffsj = ae_randominteger(maxn, _state); - xoffs = ae_randominteger(maxn, _state); - yoffs = ae_randominteger(maxn, _state); - opca = ae_randominteger(3, _state); - opra = ae_randominteger(2, _state); - ralpha = (ae_randomreal(_state)-0.5)*ae_randominteger(2, _state); - rbeta = (ae_randomreal(_state)-0.5)*ae_randominteger(2, _state); - - /* - * Test CMatrixMV and deprecated RMatrixMV - */ - for(i=0; i<=2*maxn-1; i++) - { - cy.ptr.p_complex[i] = ae_complex_from_i(i); - } - cmatrixmv(m, n, &refca, aoffsi, aoffsj, opca, &cx, xoffs, &cy, yoffs, _state); - for(i=0; i<=2*maxn-1; i++) - { - if( i=yoffs+m ) - { - result = result||ae_c_neq_d(cy.ptr.p_complex[i],(double)(i)); - } - else - { - cv1 = cy.ptr.p_complex[i]; - cv2 = ae_complex_from_d(0.0); - if( opca==0 ) - { - cv2 = ae_v_cdotproduct(&refca.ptr.pp_complex[aoffsi+i-yoffs][aoffsj], 1, "N", &cx.ptr.p_complex[xoffs], 1, "N", ae_v_len(aoffsj,aoffsj+n-1)); - } - if( opca==1 ) - { - cv2 = ae_v_cdotproduct(&refca.ptr.pp_complex[aoffsi][aoffsj+i-yoffs], refca.stride, "N", &cx.ptr.p_complex[xoffs], 1, "N", ae_v_len(aoffsi,aoffsi+n-1)); - } - if( opca==2 ) - { - cv2 = ae_v_cdotproduct(&refca.ptr.pp_complex[aoffsi][aoffsj+i-yoffs], refca.stride, "Conj", &cx.ptr.p_complex[xoffs], 1, "N", ae_v_len(aoffsi,aoffsi+n-1)); - } - result = result||ae_fp_greater(ae_c_abs(ae_c_sub(cv1,cv2), _state),threshold); - } - } - for(i=0; i<=2*maxn-1; i++) - { - ry.ptr.p_double[i] = (double)(i); - } - rmatrixmv(m, n, &refra, aoffsi, aoffsj, opra, &rx, xoffs, &ry, yoffs, _state); - for(i=0; i<=2*maxn-1; i++) - { - if( i=yoffs+m ) - { - result = result||ae_fp_neq(ry.ptr.p_double[i],(double)(i)); - } - else - { - rv1 = ry.ptr.p_double[i]; - rv2 = (double)(0); - if( opra==0 ) - { - rv2 = ae_v_dotproduct(&refra.ptr.pp_double[aoffsi+i-yoffs][aoffsj], 1, &rx.ptr.p_double[xoffs], 1, ae_v_len(aoffsj,aoffsj+n-1)); - } - if( opra==1 ) - { - rv2 = ae_v_dotproduct(&refra.ptr.pp_double[aoffsi][aoffsj+i-yoffs], refra.stride, &rx.ptr.p_double[xoffs], 1, ae_v_len(aoffsi,aoffsi+n-1)); - } - result = result||ae_fp_greater(ae_fabs(rv1-rv2, _state),threshold); - } - } - - /* - * Test modern RMatrixGEMV() - */ - for(i=0; i<=2*maxn-1; i++) - { - ry.ptr.p_double[i] = (double)(i); - } - rmatrixgemv(m, n, ralpha, &refra, aoffsi, aoffsj, opra, &rx, xoffs, rbeta, &ry, yoffs, _state); - for(i=0; i<=2*maxn-1; i++) - { - if( i=yoffs+m ) - { - ae_set_error_flag(&result, ae_fp_neq(ry.ptr.p_double[i],(double)(i)), __FILE__, __LINE__, "testablasunit.ap:1282"); - } - else - { - rv1 = ry.ptr.p_double[i]; - rv2 = (double)(0); - if( opra==0 ) - { - rv2 = ae_v_dotproduct(&refra.ptr.pp_double[aoffsi+i-yoffs][aoffsj], 1, &rx.ptr.p_double[xoffs], 1, ae_v_len(aoffsj,aoffsj+n-1)); - } - if( opra==1 ) - { - rv2 = ae_v_dotproduct(&refra.ptr.pp_double[aoffsi][aoffsj+i-yoffs], refra.stride, &rx.ptr.p_double[xoffs], 1, ae_v_len(aoffsi,aoffsi+n-1)); - } - rv2 = rbeta*i+ralpha*rv2; - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(rv1-rv2, _state),threshold), __FILE__, __LINE__, "testablasunit.ap:1292"); - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -SYMV/SYVMV tests - -Sets error flag on failure, ignores on success. -*************************************************************************/ -static void testablasunit_testsymv(ae_int_t minn, - ae_int_t maxn, - ae_bool* errorflag, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t aoffsi; - ae_int_t aoffsj; - ae_int_t xoffs; - ae_int_t yoffs; - ae_bool isuppera; - double threshold; - double ralpha; - double rbeta; - double rv1; - double rv2; - ae_matrix refra; - ae_vector rx; - ae_vector ry; - ae_vector rz; - - ae_frame_make(_state, &_frame_block); - memset(&refra, 0, sizeof(refra)); - memset(&rx, 0, sizeof(rx)); - memset(&ry, 0, sizeof(ry)); - memset(&rz, 0, sizeof(rz)); - ae_matrix_init(&refra, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ry, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rz, 0, DT_REAL, _state, ae_true); - - threshold = 1000*ae_machineepsilon; - for(n=minn; n<=maxn; n++) - { - - /* - * Initialize A by random matrix with size (MaxN+MaxN)*(MaxN+MaxN) - * Initialize X by random vector with size (MaxN+MaxN) - * Fill Y by control values - */ - ae_matrix_set_length(&refra, maxn+maxn, maxn+maxn, _state); - for(i=0; i<=2*maxn-1; i++) - { - for(j=0; j<=2*maxn-1; j++) - { - refra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - ae_vector_set_length(&rx, 2*maxn, _state); - ae_vector_set_length(&ry, 2*maxn, _state); - ae_vector_set_length(&rz, 2*maxn, _state); - for(i=0; i<=2*maxn-1; i++) - { - rx.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - - /* - * Select random offsets and operations. - * - * To avoid unnecessary slowdown we don't test ALL possible - * combinations of operation types. We just generate one random - * set of parameters and test it. - */ - aoffsi = ae_randominteger(maxn, _state); - aoffsj = ae_randominteger(maxn, _state); - xoffs = ae_randominteger(maxn, _state); - yoffs = ae_randominteger(maxn, _state); - isuppera = ae_fp_greater(ae_randomreal(_state),0.5); - ralpha = (ae_randomreal(_state)-0.5)*ae_randominteger(2, _state); - rbeta = (ae_randomreal(_state)-0.5)*ae_randominteger(2, _state); - - /* - * Test RMatrixSYMV() - */ - for(i=0; i<=2*maxn-1; i++) - { - ry.ptr.p_double[i] = (double)(i); - rz.ptr.p_double[i] = (double)(i); - } - rmatrixsymv(n, ralpha, &refra, aoffsi, aoffsj, isuppera, &rx, xoffs, rbeta, &ry, yoffs, _state); - testablasunit_refrmatrixsymv(n, ralpha, &refra, aoffsi, aoffsj, isuppera, &rx, xoffs, rbeta, &rz, yoffs, _state); - for(i=0; i<=2*maxn-1; i++) - { - if( i=yoffs+n ) - { - ae_set_error_flag(errorflag, ae_fp_neq(ry.ptr.p_double[i],(double)(i)), __FILE__, __LINE__, "testablasunit.ap:1380"); - } - else - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(ry.ptr.p_double[i]-rz.ptr.p_double[i], _state),threshold*maxreal3(ae_fabs(ry.ptr.p_double[i], _state), ae_fabs(rz.ptr.p_double[i], _state), 1.0, _state)), __FILE__, __LINE__, "testablasunit.ap:1382"); - } - } - - /* - * Test RMatrixSYVMV() - */ - rv1 = rmatrixsyvmv(n, &refra, aoffsi, aoffsj, isuppera, &rx, xoffs, &ry, _state); - rv2 = testablasunit_refrmatrixsyvmv(n, &refra, aoffsi, aoffsj, isuppera, &rx, xoffs, _state); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(rv1-rv2, _state),threshold*maxreal3(ae_fabs(rv1, _state), ae_fabs(rv2, _state), 1.0, _state)), __FILE__, __LINE__, "testablasunit.ap:1396"); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -TRSV tests - -Sets error flag on failure, ignores on success. -*************************************************************************/ -static void testablasunit_testtrsv(ae_int_t minn, - ae_int_t maxn, - ae_bool* errorflag, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t aoffsi; - ae_int_t aoffsj; - ae_int_t xoffs; - ae_bool isuppera; - ae_bool isunita; - ae_int_t opa; - double threshold; - ae_matrix refra; - ae_matrix ea; - ae_vector rx; - ae_vector ry; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&refra, 0, sizeof(refra)); - memset(&ea, 0, sizeof(ea)); - memset(&rx, 0, sizeof(rx)); - memset(&ry, 0, sizeof(ry)); - ae_matrix_init(&refra, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ea, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ry, 0, DT_REAL, _state, ae_true); - - for(n=minn; n<=maxn; n++) - { - - /* - * Decreased threshold because of ill-conditioning of randomly generated matrices - */ - threshold = 1.0E-6*(1+n); - - /* - * Initialize A by random matrix with size (MaxN+MaxN)*(MaxN+MaxN) - * Initialize X by sparse random vector with size (MaxN+MaxN) (sparsity is important to test some branches of algorithm) - * Fill Y by control values - */ - ae_matrix_set_length(&refra, maxn+maxn, maxn+maxn, _state); - for(i=0; i<=2*maxn-1; i++) - { - for(j=0; j<=2*maxn-1; j++) - { - refra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - ae_vector_set_length(&rx, 2*maxn, _state); - ae_vector_set_length(&ry, 2*maxn, _state); - for(i=0; i<=2*maxn-1; i++) - { - rx.ptr.p_double[i] = (2*ae_randomreal(_state)-1)*ae_randominteger(3, _state); - } - - /* - * Select random offsets and operations. - * - * To avoid unnecessary slowdown we don't test ALL possible - * combinations of operation types. We just generate one random - * set of parameters and test it. - * - * NOTE: in order to improve conditioning properties we add 10*Identity - * to purported diagonal of A - */ - aoffsi = ae_randominteger(maxn, _state); - aoffsj = ae_randominteger(maxn, _state); - xoffs = ae_randominteger(maxn, _state); - isuppera = ae_fp_greater(ae_randomreal(_state),0.5); - isunita = ae_fp_greater(ae_randomreal(_state),0.5); - opa = ae_randominteger(2, _state); - for(i=0; i<=n-1; i++) - { - refra.ptr.pp_double[aoffsi+i][aoffsj+i] = refra.ptr.pp_double[aoffsi+i][aoffsj+i]+10; - } - - /* - * Test RMatrixTRSV(): - * * check that elements of RX beyond [XOffs,XOffs+N-1] are unchanged - * * calculate RX:=TRSV(RX) - * * extract effective A from RefRA to EA=array[N,N] - * * compare product EA*RX, compare with copy of RX stored in RY - */ - for(i=0; i<=2*maxn-1; i++) - { - ry.ptr.p_double[i] = rx.ptr.p_double[i]; - } - rmatrixtrsv(n, &refra, aoffsi, aoffsj, isuppera, isunita, opa, &rx, xoffs, _state); - for(i=0; i<=2*maxn-1; i++) - { - if( ixoffs+n-1 ) - { - ae_set_error_flag(errorflag, ae_fp_neq(rx.ptr.p_double[i],ry.ptr.p_double[i]), __FILE__, __LINE__, "testablasunit.ap:1480"); - } - } - ae_matrix_set_length(&ea, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = refra.ptr.pp_double[aoffsi+i][aoffsj+j]; - if( (ji&&!isuppera) ) - { - v = (double)(0); - } - if( isunita&&i==j ) - { - v = (double)(1); - } - if( opa==0 ) - { - ea.ptr.pp_double[i][j] = v; - } - else - { - ea.ptr.pp_double[j][i] = v; - } - } - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&ea.ptr.pp_double[i][0], 1, &rx.ptr.p_double[xoffs], 1, ae_v_len(0,n-1)); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v-ry.ptr.p_double[xoffs+i], _state),threshold), __FILE__, __LINE__, "testablasunit.ap:1503"); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Special test. -On failure sets error flag, on success does not change it. -*************************************************************************/ -static void testablasunit_spectest(ae_bool* errorflag, ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix emptyr2; - ae_matrix emptyc2; - ae_matrix outputr2; - ae_matrix outputc2; - ae_int_t i; - ae_int_t j; - ae_int_t n; - ae_int_t pass; - - ae_frame_make(_state, &_frame_block); - memset(&emptyr2, 0, sizeof(emptyr2)); - memset(&emptyc2, 0, sizeof(emptyc2)); - memset(&outputr2, 0, sizeof(outputr2)); - memset(&outputc2, 0, sizeof(outputc2)); - ae_matrix_init(&emptyr2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&emptyc2, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&outputr2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&outputc2, 0, 0, DT_COMPLEX, _state, ae_true); - - - /* - * Test that SYRK, GEMM and TRSM does not reference empty argument at all. - * - * In order to perform this test we pass empty (unallocated) matrix - * with large offset; incorrect implementation will crash on such data. - */ - n = 128+ae_randominteger(65, _state)-32; - ae_matrix_set_length(&outputr2, n, n, _state); - ae_matrix_set_length(&outputc2, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - outputr2.ptr.pp_double[i][j] = (double)(0); - outputc2.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - for(pass=0; pass<=10; pass++) - { - rmatrixgemm(n, n, 0, 1.0, &emptyr2, 35345, 23453, ae_randominteger(2, _state), &emptyr2, 74764, 26845, ae_randominteger(2, _state), 1.0+ae_randominteger(2, _state), &outputr2, 0, 0, _state); - rmatrixgemm(n, n, n, 0.0, &emptyr2, 35345, 23453, ae_randominteger(2, _state), &emptyr2, 74764, 26845, ae_randominteger(2, _state), 1.0+ae_randominteger(2, _state), &outputr2, 0, 0, _state); - cmatrixgemm(n, n, 0, ae_complex_from_d(1.0), &emptyc2, 35345, 23453, ae_randominteger(3, _state), &emptyc2, 74764, 26845, ae_randominteger(3, _state), ae_complex_from_d(1.0+ae_randominteger(2, _state)), &outputc2, 0, 0, _state); - cmatrixgemm(n, n, n, ae_complex_from_d(0.0), &emptyc2, 35345, 23453, ae_randominteger(3, _state), &emptyc2, 74764, 26845, ae_randominteger(3, _state), ae_complex_from_d(1.0+ae_randominteger(2, _state)), &outputc2, 0, 0, _state); - rmatrixsyrk(n, 0, 1.0, &emptyr2, 54674, 34657, 2*ae_randominteger(2, _state), 1.0+ae_randominteger(2, _state), &outputr2, 0, 0, ae_fp_greater(ae_randomreal(_state),0.5), _state); - rmatrixsyrk(n, n, 0.0, &emptyr2, 54674, 34657, 2*ae_randominteger(2, _state), 1.0+ae_randominteger(2, _state), &outputr2, 0, 0, ae_fp_greater(ae_randomreal(_state),0.5), _state); - cmatrixherk(n, 0, 1.0, &emptyc2, 54674, 34657, 2*ae_randominteger(2, _state), 1.0+ae_randominteger(2, _state), &outputc2, 0, 0, ae_fp_greater(ae_randomreal(_state),0.5), _state); - cmatrixherk(n, n, 0.0, &emptyc2, 54674, 34657, 2*ae_randominteger(2, _state), 1.0+ae_randominteger(2, _state), &outputc2, 0, 0, ae_fp_greater(ae_randomreal(_state),0.5), _state); - rmatrixrighttrsm(0, 0, &emptyr2, 63463, 36345, ae_fp_greater(ae_randomreal(_state),0.5), ae_fp_greater(ae_randomreal(_state),0.5), ae_randominteger(2, _state), &outputr2, 0, 0, _state); - rmatrixlefttrsm(0, 0, &emptyr2, 63463, 36345, ae_fp_greater(ae_randomreal(_state),0.5), ae_fp_greater(ae_randomreal(_state),0.5), ae_randominteger(2, _state), &outputr2, 0, 0, _state); - cmatrixrighttrsm(0, 0, &emptyc2, 63463, 36345, ae_fp_greater(ae_randomreal(_state),0.5), ae_fp_greater(ae_randomreal(_state),0.5), ae_randominteger(3, _state), &outputc2, 0, 0, _state); - cmatrixlefttrsm(0, 0, &emptyc2, 63463, 36345, ae_fp_greater(ae_randomreal(_state),0.5), ae_fp_greater(ae_randomreal(_state),0.5), ae_randominteger(3, _state), &outputc2, 0, 0, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -COPY tests - -Returns False for passed test, True - for failed -*************************************************************************/ -static ae_bool testablasunit_testcopy(ae_int_t minn, - ae_int_t maxn, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t m; - ae_int_t n; - ae_int_t mx; - ae_int_t i; - ae_int_t j; - ae_int_t aoffsi; - ae_int_t aoffsj; - ae_int_t boffsi; - ae_int_t boffsj; - double threshold; - ae_matrix ra; - ae_matrix rb; - ae_matrix ca; - ae_matrix cb; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&ra, 0, sizeof(ra)); - memset(&rb, 0, sizeof(rb)); - memset(&ca, 0, sizeof(ca)); - memset(&cb, 0, sizeof(cb)); - ae_matrix_init(&ra, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&rb, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ca, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&cb, 0, 0, DT_COMPLEX, _state, ae_true); - - result = ae_false; - threshold = 1000*ae_machineepsilon; - for(mx=minn; mx<=maxn; mx++) - { - - /* - * Select random M/N in [1,MX] such that max(M,N)=MX - */ - m = 1+ae_randominteger(mx, _state); - n = 1+ae_randominteger(mx, _state); - if( ae_randominteger(2, _state)==0 ) - { - m = mx; - } - else - { - n = mx; - } - - /* - * Initialize A by random matrix with size (MaxN+MaxN)*(MaxN+MaxN) - * Initialize X by random vector with size (MaxN+MaxN) - * Fill Y by control values - */ - ae_matrix_set_length(&ra, maxn+maxn, maxn+maxn, _state); - ae_matrix_set_length(&ca, maxn+maxn, maxn+maxn, _state); - ae_matrix_set_length(&rb, maxn+maxn, maxn+maxn, _state); - ae_matrix_set_length(&cb, maxn+maxn, maxn+maxn, _state); - for(i=0; i<=2*maxn-1; i++) - { - for(j=0; j<=2*maxn-1; j++) - { - ra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - ca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - ca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - rb.ptr.pp_double[i][j] = (double)(1+2*i+3*j); - cb.ptr.pp_complex[i][j] = ae_complex_from_i(1+2*i+3*j); - } - } - - /* - * test different offsets (zero or one) - * - * to avoid unnecessary slowdown we don't test ALL possible - * combinations of operation types. We just generate one random - * set of parameters and test it. - */ - aoffsi = ae_randominteger(maxn, _state); - aoffsj = ae_randominteger(maxn, _state); - boffsi = ae_randominteger(maxn, _state); - boffsj = ae_randominteger(maxn, _state); - cmatrixcopy(m, n, &ca, aoffsi, aoffsj, &cb, boffsi, boffsj, _state); - for(i=0; i<=2*maxn-1; i++) - { - for(j=0; j<=2*maxn-1; j++) - { - if( ((i=boffsi+m)||j=boffsj+n ) - { - result = result||ae_c_neq_d(cb.ptr.pp_complex[i][j],(double)(1+2*i+3*j)); - } - else - { - result = result||ae_fp_greater(ae_c_abs(ae_c_sub(ca.ptr.pp_complex[aoffsi+i-boffsi][aoffsj+j-boffsj],cb.ptr.pp_complex[i][j]), _state),threshold); - } - } - } - rmatrixcopy(m, n, &ra, aoffsi, aoffsj, &rb, boffsi, boffsj, _state); - for(i=0; i<=2*maxn-1; i++) - { - for(j=0; j<=2*maxn-1; j++) - { - if( ((i=boffsi+m)||j=boffsj+n ) - { - result = result||ae_fp_neq(rb.ptr.pp_double[i][j],(double)(1+2*i+3*j)); - } - else - { - result = result||ae_fp_greater(ae_fabs(ra.ptr.pp_double[aoffsi+i-boffsi][aoffsj+j-boffsj]-rb.ptr.pp_double[i][j], _state),threshold); - } - } - } - } - ae_frame_leave(_state); - return result; -} - - -static void testablasunit_testreflections(ae_bool* errorflag, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t n; - ae_int_t m; - ae_int_t maxmn; - ae_vector x; - ae_vector v; - ae_vector work; - ae_matrix h; - ae_matrix a; - ae_matrix b; - ae_matrix c; - double tmp; - double beta; - double tau; - double err; - double mer; - double mel; - double meg; - ae_int_t pass; - ae_int_t passcount; - double threshold; - ae_int_t tasktype; - double xscale; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&v, 0, sizeof(v)); - memset(&work, 0, sizeof(work)); - memset(&h, 0, sizeof(h)); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - memset(&c, 0, sizeof(c)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&v, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&h, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - - passcount = 10; - threshold = 100*ae_machineepsilon; - mer = (double)(0); - mel = (double)(0); - meg = (double)(0); - for(pass=1; pass<=passcount; pass++) - { - for(n=1; n<=10; n++) - { - for(m=1; m<=10; m++) - { - - /* - * Task - */ - n = 1+ae_randominteger(10, _state); - m = 1+ae_randominteger(10, _state); - maxmn = ae_maxint(m, n, _state); - - /* - * Initialize - */ - ae_vector_set_length(&x, maxmn+1, _state); - ae_vector_set_length(&v, maxmn+1, _state); - ae_vector_set_length(&work, maxmn+1, _state); - ae_matrix_set_length(&h, maxmn+1, maxmn+1, _state); - ae_matrix_set_length(&a, maxmn+1, maxmn+1, _state); - ae_matrix_set_length(&b, maxmn+1, maxmn+1, _state); - ae_matrix_set_length(&c, maxmn+1, maxmn+1, _state); - - /* - * GenerateReflection, three tasks are possible: - * * random X - * * zero X - * * non-zero X[1], all other are zeros - * * random X, near underflow scale - * * random X, near overflow scale - */ - for(tasktype=0; tasktype<=4; tasktype++) - { - xscale = (double)(1); - if( tasktype==0 ) - { - for(i=1; i<=n; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - } - if( tasktype==1 ) - { - for(i=1; i<=n; i++) - { - x.ptr.p_double[i] = (double)(0); - } - } - if( tasktype==2 ) - { - x.ptr.p_double[1] = 2*ae_randomreal(_state)-1; - for(i=2; i<=n; i++) - { - x.ptr.p_double[i] = (double)(0); - } - } - if( tasktype==3 ) - { - for(i=1; i<=n; i++) - { - x.ptr.p_double[i] = (ae_randominteger(21, _state)-10)*ae_minrealnumber; - } - xscale = 10*ae_minrealnumber; - } - if( tasktype==4 ) - { - for(i=1; i<=n; i++) - { - x.ptr.p_double[i] = (2*ae_randomreal(_state)-1)*ae_maxrealnumber; - } - xscale = ae_maxrealnumber; - } - ae_v_move(&v.ptr.p_double[1], 1, &x.ptr.p_double[1], 1, ae_v_len(1,n)); - generatereflection(&v, n, &tau, _state); - beta = v.ptr.p_double[1]; - v.ptr.p_double[1] = (double)(1); - for(i=1; i<=n; i++) - { - for(j=1; j<=n; j++) - { - if( i==j ) - { - h.ptr.pp_double[i][j] = 1-tau*v.ptr.p_double[i]*v.ptr.p_double[j]; - } - else - { - h.ptr.pp_double[i][j] = -tau*v.ptr.p_double[i]*v.ptr.p_double[j]; - } - } - } - err = (double)(0); - for(i=1; i<=n; i++) - { - tmp = ae_v_dotproduct(&h.ptr.pp_double[i][1], 1, &x.ptr.p_double[1], 1, ae_v_len(1,n)); - if( i==1 ) - { - err = ae_maxreal(err, ae_fabs(tmp-beta, _state), _state); - } - else - { - err = ae_maxreal(err, ae_fabs(tmp, _state), _state); - } - } - meg = ae_maxreal(meg, err/xscale, _state); - } - - /* - * ApplyReflectionFromTheLeft - */ - for(i=1; i<=m; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - v.ptr.p_double[i] = x.ptr.p_double[i]; - } - for(i=1; i<=m; i++) - { - for(j=1; j<=n; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - b.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]; - } - } - generatereflection(&v, m, &tau, _state); - beta = v.ptr.p_double[1]; - v.ptr.p_double[1] = (double)(1); - applyreflectionfromtheleft(&b, tau, &v, 1, m, 1, n, &work, _state); - for(i=1; i<=m; i++) - { - for(j=1; j<=m; j++) - { - if( i==j ) - { - h.ptr.pp_double[i][j] = 1-tau*v.ptr.p_double[i]*v.ptr.p_double[j]; - } - else - { - h.ptr.pp_double[i][j] = -tau*v.ptr.p_double[i]*v.ptr.p_double[j]; - } - } - } - for(i=1; i<=m; i++) - { - for(j=1; j<=n; j++) - { - tmp = ae_v_dotproduct(&h.ptr.pp_double[i][1], 1, &a.ptr.pp_double[1][j], a.stride, ae_v_len(1,m)); - c.ptr.pp_double[i][j] = tmp; - } - } - err = (double)(0); - for(i=1; i<=m; i++) - { - for(j=1; j<=n; j++) - { - err = ae_maxreal(err, ae_fabs(b.ptr.pp_double[i][j]-c.ptr.pp_double[i][j], _state), _state); - } - } - mel = ae_maxreal(mel, err, _state); - - /* - * ApplyReflectionFromTheRight - */ - for(i=1; i<=n; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - v.ptr.p_double[i] = x.ptr.p_double[i]; - } - for(i=1; i<=m; i++) - { - for(j=1; j<=n; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - b.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]; - } - } - generatereflection(&v, n, &tau, _state); - beta = v.ptr.p_double[1]; - v.ptr.p_double[1] = (double)(1); - applyreflectionfromtheright(&b, tau, &v, 1, m, 1, n, &work, _state); - for(i=1; i<=n; i++) - { - for(j=1; j<=n; j++) - { - if( i==j ) - { - h.ptr.pp_double[i][j] = 1-tau*v.ptr.p_double[i]*v.ptr.p_double[j]; - } - else - { - h.ptr.pp_double[i][j] = -tau*v.ptr.p_double[i]*v.ptr.p_double[j]; - } - } - } - for(i=1; i<=m; i++) - { - for(j=1; j<=n; j++) - { - tmp = ae_v_dotproduct(&a.ptr.pp_double[i][1], 1, &h.ptr.pp_double[1][j], h.stride, ae_v_len(1,n)); - c.ptr.pp_double[i][j] = tmp; - } - } - err = (double)(0); - for(i=1; i<=m; i++) - { - for(j=1; j<=n; j++) - { - err = ae_maxreal(err, ae_fabs(b.ptr.pp_double[i][j]-c.ptr.pp_double[i][j], _state), _state); - } - } - mer = ae_maxreal(mer, err, _state); - } - } - } - - /* - * Overflow crash test - */ - ae_vector_set_length(&x, 10+1, _state); - ae_vector_set_length(&v, 10+1, _state); - for(i=1; i<=10; i++) - { - v.ptr.p_double[i] = ae_maxrealnumber*0.01*(2*ae_randomreal(_state)-1); - } - generatereflection(&v, 10, &tau, _state); - - /* - * Result - */ - ae_set_error_flag(errorflag, (ae_fp_greater(meg,threshold)||ae_fp_greater(mel,threshold))||ae_fp_greater(mer,threshold), __FILE__, __LINE__, "testablasunit.ap:1888"); - ae_frame_leave(_state); -} - - -/************************************************************************* -Reference implementation - - -- ALGLIB routine -- - 15.12.2009 - Bochkanov Sergey -*************************************************************************/ -static void testablasunit_refcmatrixrighttrsm(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a1; - ae_matrix a2; - ae_vector tx; - ae_int_t i; - ae_int_t j; - ae_complex vc; - ae_bool rupper; - - ae_frame_make(_state, &_frame_block); - memset(&a1, 0, sizeof(a1)); - memset(&a2, 0, sizeof(a2)); - memset(&tx, 0, sizeof(tx)); - ae_matrix_init(&a1, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&a2, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&tx, 0, DT_COMPLEX, _state, ae_true); - - if( n*m==0 ) - { - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&a1, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a1.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - if( isupper ) - { - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - a1.ptr.pp_complex[i][j] = a->ptr.pp_complex[i1+i][j1+j]; - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i; j++) - { - a1.ptr.pp_complex[i][j] = a->ptr.pp_complex[i1+i][j1+j]; - } - } - } - rupper = isupper; - if( isunit ) - { - for(i=0; i<=n-1; i++) - { - a1.ptr.pp_complex[i][i] = ae_complex_from_i(1); - } - } - ae_matrix_set_length(&a2, n, n, _state); - if( optype==0 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a2.ptr.pp_complex[i][j] = a1.ptr.pp_complex[i][j]; - } - } - } - if( optype==1 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a2.ptr.pp_complex[i][j] = a1.ptr.pp_complex[j][i]; - } - } - rupper = !rupper; - } - if( optype==2 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a2.ptr.pp_complex[i][j] = ae_c_conj(a1.ptr.pp_complex[j][i], _state); - } - } - rupper = !rupper; - } - testablasunit_internalcmatrixtrinverse(&a2, n, rupper, ae_false, _state); - ae_vector_set_length(&tx, n, _state); - for(i=0; i<=m-1; i++) - { - ae_v_cmove(&tx.ptr.p_complex[0], 1, &x->ptr.pp_complex[i2+i][j2], 1, "N", ae_v_len(0,n-1)); - for(j=0; j<=n-1; j++) - { - vc = ae_v_cdotproduct(&tx.ptr.p_complex[0], 1, "N", &a2.ptr.pp_complex[0][j], a2.stride, "N", ae_v_len(0,n-1)); - x->ptr.pp_complex[i2+i][j2+j] = vc; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Reference implementation - - -- ALGLIB routine -- - 15.12.2009 - Bochkanov Sergey -*************************************************************************/ -static void testablasunit_refcmatrixlefttrsm(ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Complex */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a1; - ae_matrix a2; - ae_vector tx; - ae_int_t i; - ae_int_t j; - ae_complex vc; - ae_bool rupper; - - ae_frame_make(_state, &_frame_block); - memset(&a1, 0, sizeof(a1)); - memset(&a2, 0, sizeof(a2)); - memset(&tx, 0, sizeof(tx)); - ae_matrix_init(&a1, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&a2, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&tx, 0, DT_COMPLEX, _state, ae_true); - - if( n*m==0 ) - { - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&a1, m, m, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - a1.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - if( isupper ) - { - for(i=0; i<=m-1; i++) - { - for(j=i; j<=m-1; j++) - { - a1.ptr.pp_complex[i][j] = a->ptr.pp_complex[i1+i][j1+j]; - } - } - } - else - { - for(i=0; i<=m-1; i++) - { - for(j=0; j<=i; j++) - { - a1.ptr.pp_complex[i][j] = a->ptr.pp_complex[i1+i][j1+j]; - } - } - } - rupper = isupper; - if( isunit ) - { - for(i=0; i<=m-1; i++) - { - a1.ptr.pp_complex[i][i] = ae_complex_from_i(1); - } - } - ae_matrix_set_length(&a2, m, m, _state); - if( optype==0 ) - { - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - a2.ptr.pp_complex[i][j] = a1.ptr.pp_complex[i][j]; - } - } - } - if( optype==1 ) - { - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - a2.ptr.pp_complex[i][j] = a1.ptr.pp_complex[j][i]; - } - } - rupper = !rupper; - } - if( optype==2 ) - { - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - a2.ptr.pp_complex[i][j] = ae_c_conj(a1.ptr.pp_complex[j][i], _state); - } - } - rupper = !rupper; - } - testablasunit_internalcmatrixtrinverse(&a2, m, rupper, ae_false, _state); - ae_vector_set_length(&tx, m, _state); - for(j=0; j<=n-1; j++) - { - ae_v_cmove(&tx.ptr.p_complex[0], 1, &x->ptr.pp_complex[i2][j2+j], x->stride, "N", ae_v_len(0,m-1)); - for(i=0; i<=m-1; i++) - { - vc = ae_v_cdotproduct(&a2.ptr.pp_complex[i][0], 1, "N", &tx.ptr.p_complex[0], 1, "N", ae_v_len(0,m-1)); - x->ptr.pp_complex[i2+i][j2+j] = vc; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Reference implementation - - -- ALGLIB routine -- - 15.12.2009 - Bochkanov Sergey -*************************************************************************/ -static void testablasunit_refrmatrixrighttrsm(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a1; - ae_matrix a2; - ae_vector tx; - ae_int_t i; - ae_int_t j; - double vr; - ae_bool rupper; - - ae_frame_make(_state, &_frame_block); - memset(&a1, 0, sizeof(a1)); - memset(&a2, 0, sizeof(a2)); - memset(&tx, 0, sizeof(tx)); - ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a2, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tx, 0, DT_REAL, _state, ae_true); - - if( n*m==0 ) - { - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&a1, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a1.ptr.pp_double[i][j] = (double)(0); - } - } - if( isupper ) - { - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - a1.ptr.pp_double[i][j] = a->ptr.pp_double[i1+i][j1+j]; - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i; j++) - { - a1.ptr.pp_double[i][j] = a->ptr.pp_double[i1+i][j1+j]; - } - } - } - rupper = isupper; - if( isunit ) - { - for(i=0; i<=n-1; i++) - { - a1.ptr.pp_double[i][i] = (double)(1); - } - } - ae_matrix_set_length(&a2, n, n, _state); - if( optype==0 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a2.ptr.pp_double[i][j] = a1.ptr.pp_double[i][j]; - } - } - } - if( optype==1 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a2.ptr.pp_double[i][j] = a1.ptr.pp_double[j][i]; - } - } - rupper = !rupper; - } - testablasunit_internalrmatrixtrinverse(&a2, n, rupper, ae_false, _state); - ae_vector_set_length(&tx, n, _state); - for(i=0; i<=m-1; i++) - { - ae_v_move(&tx.ptr.p_double[0], 1, &x->ptr.pp_double[i2+i][j2], 1, ae_v_len(0,n-1)); - for(j=0; j<=n-1; j++) - { - vr = ae_v_dotproduct(&tx.ptr.p_double[0], 1, &a2.ptr.pp_double[0][j], a2.stride, ae_v_len(0,n-1)); - x->ptr.pp_double[i2+i][j2+j] = vr; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Reference implementation - - -- ALGLIB routine -- - 15.12.2009 - Bochkanov Sergey -*************************************************************************/ -static void testablasunit_refrmatrixlefttrsm(ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t i1, - ae_int_t j1, - ae_bool isupper, - ae_bool isunit, - ae_int_t optype, - /* Real */ ae_matrix* x, - ae_int_t i2, - ae_int_t j2, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a1; - ae_matrix a2; - ae_vector tx; - ae_int_t i; - ae_int_t j; - double vr; - ae_bool rupper; - - ae_frame_make(_state, &_frame_block); - memset(&a1, 0, sizeof(a1)); - memset(&a2, 0, sizeof(a2)); - memset(&tx, 0, sizeof(tx)); - ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a2, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tx, 0, DT_REAL, _state, ae_true); - - if( n*m==0 ) - { - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&a1, m, m, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - a1.ptr.pp_double[i][j] = (double)(0); - } - } - if( isupper ) - { - for(i=0; i<=m-1; i++) - { - for(j=i; j<=m-1; j++) - { - a1.ptr.pp_double[i][j] = a->ptr.pp_double[i1+i][j1+j]; - } - } - } - else - { - for(i=0; i<=m-1; i++) - { - for(j=0; j<=i; j++) - { - a1.ptr.pp_double[i][j] = a->ptr.pp_double[i1+i][j1+j]; - } - } - } - rupper = isupper; - if( isunit ) - { - for(i=0; i<=m-1; i++) - { - a1.ptr.pp_double[i][i] = (double)(1); - } - } - ae_matrix_set_length(&a2, m, m, _state); - if( optype==0 ) - { - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - a2.ptr.pp_double[i][j] = a1.ptr.pp_double[i][j]; - } - } - } - if( optype==1 ) - { - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - a2.ptr.pp_double[i][j] = a1.ptr.pp_double[j][i]; - } - } - rupper = !rupper; - } - testablasunit_internalrmatrixtrinverse(&a2, m, rupper, ae_false, _state); - ae_vector_set_length(&tx, m, _state); - for(j=0; j<=n-1; j++) - { - ae_v_move(&tx.ptr.p_double[0], 1, &x->ptr.pp_double[i2][j2+j], x->stride, ae_v_len(0,m-1)); - for(i=0; i<=m-1; i++) - { - vr = ae_v_dotproduct(&a2.ptr.pp_double[i][0], 1, &tx.ptr.p_double[0], 1, ae_v_len(0,m-1)); - x->ptr.pp_double[i2+i][j2+j] = vr; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal subroutine. -Triangular matrix inversion - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - February 29, 1992 -*************************************************************************/ -static ae_bool testablasunit_internalcmatrixtrinverse(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunittriangular, - ae_state *_state) -{ - ae_frame _frame_block; - ae_bool nounit; - ae_int_t i; - ae_int_t j; - ae_complex v; - ae_complex ajj; - ae_vector t; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&t, 0, sizeof(t)); - ae_vector_init(&t, 0, DT_COMPLEX, _state, ae_true); - - result = ae_true; - ae_vector_set_length(&t, n-1+1, _state); - - /* - * Test the input parameters. - */ - nounit = !isunittriangular; - if( isupper ) - { - - /* - * Compute inverse of upper triangular matrix. - */ - for(j=0; j<=n-1; j++) - { - if( nounit ) - { - if( ae_c_eq_d(a->ptr.pp_complex[j][j],(double)(0)) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - a->ptr.pp_complex[j][j] = ae_c_d_div(1,a->ptr.pp_complex[j][j]); - ajj = ae_c_neg(a->ptr.pp_complex[j][j]); - } - else - { - ajj = ae_complex_from_i(-1); - } - - /* - * Compute elements 1:j-1 of j-th column. - */ - if( j>0 ) - { - ae_v_cmove(&t.ptr.p_complex[0], 1, &a->ptr.pp_complex[0][j], a->stride, "N", ae_v_len(0,j-1)); - for(i=0; i<=j-1; i++) - { - if( i+1ptr.pp_complex[i][i+1], 1, "N", &t.ptr.p_complex[i+1], 1, "N", ae_v_len(i+1,j-1)); - } - else - { - v = ae_complex_from_i(0); - } - if( nounit ) - { - a->ptr.pp_complex[i][j] = ae_c_add(v,ae_c_mul(a->ptr.pp_complex[i][i],t.ptr.p_complex[i])); - } - else - { - a->ptr.pp_complex[i][j] = ae_c_add(v,t.ptr.p_complex[i]); - } - } - ae_v_cmulc(&a->ptr.pp_complex[0][j], a->stride, ae_v_len(0,j-1), ajj); - } - } - } - else - { - - /* - * Compute inverse of lower triangular matrix. - */ - for(j=n-1; j>=0; j--) - { - if( nounit ) - { - if( ae_c_eq_d(a->ptr.pp_complex[j][j],(double)(0)) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - a->ptr.pp_complex[j][j] = ae_c_d_div(1,a->ptr.pp_complex[j][j]); - ajj = ae_c_neg(a->ptr.pp_complex[j][j]); - } - else - { - ajj = ae_complex_from_i(-1); - } - if( j+1ptr.pp_complex[j+1][j], a->stride, "N", ae_v_len(j+1,n-1)); - for(i=j+1; i<=n-1; i++) - { - if( i>j+1 ) - { - v = ae_v_cdotproduct(&a->ptr.pp_complex[i][j+1], 1, "N", &t.ptr.p_complex[j+1], 1, "N", ae_v_len(j+1,i-1)); - } - else - { - v = ae_complex_from_i(0); - } - if( nounit ) - { - a->ptr.pp_complex[i][j] = ae_c_add(v,ae_c_mul(a->ptr.pp_complex[i][i],t.ptr.p_complex[i])); - } - else - { - a->ptr.pp_complex[i][j] = ae_c_add(v,t.ptr.p_complex[i]); - } - } - ae_v_cmulc(&a->ptr.pp_complex[j+1][j], a->stride, ae_v_len(j+1,n-1), ajj); - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Internal subroutine. -Triangular matrix inversion - - -- LAPACK routine (version 3.0) -- - Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., - Courant Institute, Argonne National Lab, and Rice University - February 29, 1992 -*************************************************************************/ -static ae_bool testablasunit_internalrmatrixtrinverse(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunittriangular, - ae_state *_state) -{ - ae_frame _frame_block; - ae_bool nounit; - ae_int_t i; - ae_int_t j; - double v; - double ajj; - ae_vector t; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&t, 0, sizeof(t)); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - - result = ae_true; - ae_vector_set_length(&t, n-1+1, _state); - - /* - * Test the input parameters. - */ - nounit = !isunittriangular; - if( isupper ) - { - - /* - * Compute inverse of upper triangular matrix. - */ - for(j=0; j<=n-1; j++) - { - if( nounit ) - { - if( ae_fp_eq(a->ptr.pp_double[j][j],(double)(0)) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - a->ptr.pp_double[j][j] = 1/a->ptr.pp_double[j][j]; - ajj = -a->ptr.pp_double[j][j]; - } - else - { - ajj = (double)(-1); - } - - /* - * Compute elements 1:j-1 of j-th column. - */ - if( j>0 ) - { - ae_v_move(&t.ptr.p_double[0], 1, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,j-1)); - for(i=0; i<=j-1; i++) - { - if( iptr.pp_double[i][i+1], 1, &t.ptr.p_double[i+1], 1, ae_v_len(i+1,j-1)); - } - else - { - v = (double)(0); - } - if( nounit ) - { - a->ptr.pp_double[i][j] = v+a->ptr.pp_double[i][i]*t.ptr.p_double[i]; - } - else - { - a->ptr.pp_double[i][j] = v+t.ptr.p_double[i]; - } - } - ae_v_muld(&a->ptr.pp_double[0][j], a->stride, ae_v_len(0,j-1), ajj); - } - } - } - else - { - - /* - * Compute inverse of lower triangular matrix. - */ - for(j=n-1; j>=0; j--) - { - if( nounit ) - { - if( ae_fp_eq(a->ptr.pp_double[j][j],(double)(0)) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - a->ptr.pp_double[j][j] = 1/a->ptr.pp_double[j][j]; - ajj = -a->ptr.pp_double[j][j]; - } - else - { - ajj = (double)(-1); - } - if( jptr.pp_double[j+1][j], a->stride, ae_v_len(j+1,n-1)); - for(i=j+1; i<=n-1; i++) - { - if( i>j+1 ) - { - v = ae_v_dotproduct(&a->ptr.pp_double[i][j+1], 1, &t.ptr.p_double[j+1], 1, ae_v_len(j+1,i-1)); - } - else - { - v = (double)(0); - } - if( nounit ) - { - a->ptr.pp_double[i][j] = v+a->ptr.pp_double[i][i]*t.ptr.p_double[i]; - } - else - { - a->ptr.pp_double[i][j] = v+t.ptr.p_double[i]; - } - } - ae_v_muld(&a->ptr.pp_double[j+1][j], a->stride, ae_v_len(j+1,n-1), ajj); - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Reference SYRK subroutine. - - -- ALGLIB routine -- - 16.12.2009 - Bochkanov Sergey -*************************************************************************/ -static void testablasunit_refcmatrixherk(ae_int_t n, - ae_int_t k, - double alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix ae; - ae_int_t i; - ae_int_t j; - ae_complex vc; - - ae_frame_make(_state, &_frame_block); - memset(&ae, 0, sizeof(ae)); - ae_matrix_init(&ae, 0, 0, DT_COMPLEX, _state, ae_true); - - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (isupper&&j>=i)||(!isupper&&j<=i) ) - { - if( ae_fp_eq(beta,(double)(0)) ) - { - c->ptr.pp_complex[i+ic][j+jc] = ae_complex_from_i(0); - } - else - { - c->ptr.pp_complex[i+ic][j+jc] = ae_c_mul_d(c->ptr.pp_complex[i+ic][j+jc],beta); - } - } - } - } - if( ae_fp_eq(alpha,(double)(0)) ) - { - ae_frame_leave(_state); - return; - } - if( n*k>0 ) - { - ae_matrix_set_length(&ae, n, k, _state); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=k-1; j++) - { - if( optypea==0 ) - { - ae.ptr.pp_complex[i][j] = a->ptr.pp_complex[ia+i][ja+j]; - } - if( optypea==2 ) - { - ae.ptr.pp_complex[i][j] = ae_c_conj(a->ptr.pp_complex[ia+j][ja+i], _state); - } - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - vc = ae_complex_from_i(0); - if( k>0 ) - { - vc = ae_v_cdotproduct(&ae.ptr.pp_complex[i][0], 1, "N", &ae.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,k-1)); - } - vc = ae_c_mul_d(vc,alpha); - if( isupper&&j>=i ) - { - c->ptr.pp_complex[ic+i][jc+j] = ae_c_add(vc,c->ptr.pp_complex[ic+i][jc+j]); - } - if( !isupper&&j<=i ) - { - c->ptr.pp_complex[ic+i][jc+j] = ae_c_add(vc,c->ptr.pp_complex[ic+i][jc+j]); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Reference SYRK subroutine. - - -- ALGLIB routine -- - 16.12.2009 - Bochkanov Sergey -*************************************************************************/ -static void testablasunit_refrmatrixsyrk(ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_bool isupper, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix ae; - ae_int_t i; - ae_int_t j; - double vr; - - ae_frame_make(_state, &_frame_block); - memset(&ae, 0, sizeof(ae)); - ae_matrix_init(&ae, 0, 0, DT_REAL, _state, ae_true); - - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (isupper&&j>=i)||(!isupper&&j<=i) ) - { - if( ae_fp_eq(beta,(double)(0)) ) - { - c->ptr.pp_double[i+ic][j+jc] = (double)(0); - } - else - { - c->ptr.pp_double[i+ic][j+jc] = c->ptr.pp_double[i+ic][j+jc]*beta; - } - } - } - } - if( ae_fp_eq(alpha,(double)(0)) ) - { - ae_frame_leave(_state); - return; - } - if( n*k>0 ) - { - ae_matrix_set_length(&ae, n, k, _state); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=k-1; j++) - { - if( optypea==0 ) - { - ae.ptr.pp_double[i][j] = a->ptr.pp_double[ia+i][ja+j]; - } - if( optypea==1 ) - { - ae.ptr.pp_double[i][j] = a->ptr.pp_double[ia+j][ja+i]; - } - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - vr = (double)(0); - if( k>0 ) - { - vr = ae_v_dotproduct(&ae.ptr.pp_double[i][0], 1, &ae.ptr.pp_double[j][0], 1, ae_v_len(0,k-1)); - } - vr = alpha*vr; - if( isupper&&j>=i ) - { - c->ptr.pp_double[ic+i][jc+j] = vr+c->ptr.pp_double[ic+i][jc+j]; - } - if( !isupper&&j<=i ) - { - c->ptr.pp_double[ic+i][jc+j] = vr+c->ptr.pp_double[ic+i][jc+j]; - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Reference GEMM, -ALGLIB subroutine -*************************************************************************/ -static void testablasunit_refcmatrixgemm(ae_int_t m, - ae_int_t n, - ae_int_t k, - ae_complex alpha, - /* Complex */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Complex */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - ae_complex beta, - /* Complex */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix ae; - ae_matrix be; - ae_int_t i; - ae_int_t j; - ae_complex vc; - - ae_frame_make(_state, &_frame_block); - memset(&ae, 0, sizeof(ae)); - memset(&be, 0, sizeof(be)); - ae_matrix_init(&ae, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&be, 0, 0, DT_COMPLEX, _state, ae_true); - - ae_matrix_set_length(&ae, m, k, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=k-1; j++) - { - if( optypea==0 ) - { - ae.ptr.pp_complex[i][j] = a->ptr.pp_complex[ia+i][ja+j]; - } - if( optypea==1 ) - { - ae.ptr.pp_complex[i][j] = a->ptr.pp_complex[ia+j][ja+i]; - } - if( optypea==2 ) - { - ae.ptr.pp_complex[i][j] = ae_c_conj(a->ptr.pp_complex[ia+j][ja+i], _state); - } - } - } - ae_matrix_set_length(&be, k, n, _state); - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( optypeb==0 ) - { - be.ptr.pp_complex[i][j] = b->ptr.pp_complex[ib+i][jb+j]; - } - if( optypeb==1 ) - { - be.ptr.pp_complex[i][j] = b->ptr.pp_complex[ib+j][jb+i]; - } - if( optypeb==2 ) - { - be.ptr.pp_complex[i][j] = ae_c_conj(b->ptr.pp_complex[ib+j][jb+i], _state); - } - } - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - vc = ae_v_cdotproduct(&ae.ptr.pp_complex[i][0], 1, "N", &be.ptr.pp_complex[0][j], be.stride, "N", ae_v_len(0,k-1)); - vc = ae_c_mul(alpha,vc); - if( ae_c_neq_d(beta,(double)(0)) ) - { - vc = ae_c_add(vc,ae_c_mul(beta,c->ptr.pp_complex[ic+i][jc+j])); - } - c->ptr.pp_complex[ic+i][jc+j] = vc; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Reference GEMM, -ALGLIB subroutine -*************************************************************************/ -static void testablasunit_refrmatrixgemm(ae_int_t m, - ae_int_t n, - ae_int_t k, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_int_t optypea, - /* Real */ ae_matrix* b, - ae_int_t ib, - ae_int_t jb, - ae_int_t optypeb, - double beta, - /* Real */ ae_matrix* c, - ae_int_t ic, - ae_int_t jc, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix ae; - ae_matrix be; - ae_int_t i; - ae_int_t j; - double vc; - - ae_frame_make(_state, &_frame_block); - memset(&ae, 0, sizeof(ae)); - memset(&be, 0, sizeof(be)); - ae_matrix_init(&ae, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&be, 0, 0, DT_REAL, _state, ae_true); - - ae_matrix_set_length(&ae, m, k, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=k-1; j++) - { - if( optypea==0 ) - { - ae.ptr.pp_double[i][j] = a->ptr.pp_double[ia+i][ja+j]; - } - if( optypea==1 ) - { - ae.ptr.pp_double[i][j] = a->ptr.pp_double[ia+j][ja+i]; - } - } - } - ae_matrix_set_length(&be, k, n, _state); - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( optypeb==0 ) - { - be.ptr.pp_double[i][j] = b->ptr.pp_double[ib+i][jb+j]; - } - if( optypeb==1 ) - { - be.ptr.pp_double[i][j] = b->ptr.pp_double[ib+j][jb+i]; - } - } - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - vc = ae_v_dotproduct(&ae.ptr.pp_double[i][0], 1, &be.ptr.pp_double[0][j], be.stride, ae_v_len(0,k-1)); - vc = alpha*vc; - if( ae_fp_neq(beta,(double)(0)) ) - { - vc = vc+beta*c->ptr.pp_double[ic+i][jc+j]; - } - c->ptr.pp_double[ic+i][jc+j] = vc; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Reference SYMV, -ALGLIB subroutine -*************************************************************************/ -static void testablasunit_refrmatrixsymv(ae_int_t n, - double alpha, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_bool isupper, - /* Real */ ae_vector* x, - ae_int_t ix, - double beta, - /* Real */ ae_vector* y, - ae_int_t iy, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - double v; - ae_matrix b; - - ae_frame_make(_state, &_frame_block); - memset(&b, 0, sizeof(b)); - ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true); - - - /* - * Convert problem to traditional dense GEMV - */ - ae_matrix_set_length(&b, n, n, _state); - if( isupper ) - { - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - b.ptr.pp_double[i][j] = a->ptr.pp_double[ia+i][ja+j]; - b.ptr.pp_double[j][i] = a->ptr.pp_double[ia+i][ja+j]; - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i; j++) - { - b.ptr.pp_double[i][j] = a->ptr.pp_double[ia+i][ja+j]; - b.ptr.pp_double[j][i] = a->ptr.pp_double[ia+i][ja+j]; - } - } - } - - /* - * Calculate result - */ - for(i=0; i<=n-1; i++) - { - v = beta*y->ptr.p_double[iy+i]; - for(j=0; j<=n-1; j++) - { - v = v+alpha*b.ptr.pp_double[i][j]*x->ptr.p_double[ix+j]; - } - y->ptr.p_double[iy+i] = v; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Reference SYVMV, -ALGLIB subroutine -*************************************************************************/ -static double testablasunit_refrmatrixsyvmv(ae_int_t n, - /* Real */ ae_matrix* a, - ae_int_t ia, - ae_int_t ja, - ae_bool isupper, - /* Real */ ae_vector* x, - ae_int_t ix, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_matrix b; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&b, 0, sizeof(b)); - ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true); - - - /* - * Convert problem to traditional dense GEMV - */ - ae_matrix_set_length(&b, n, n, _state); - if( isupper ) - { - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - b.ptr.pp_double[i][j] = a->ptr.pp_double[ia+i][ja+j]; - b.ptr.pp_double[j][i] = a->ptr.pp_double[ia+i][ja+j]; - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i; j++) - { - b.ptr.pp_double[i][j] = a->ptr.pp_double[ia+i][ja+j]; - b.ptr.pp_double[j][i] = a->ptr.pp_double[ia+i][ja+j]; - } - } - } - - /* - * Calculate result - */ - result = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - result = result+x->ptr.p_double[ix+i]*b.ptr.pp_double[i][j]*x->ptr.p_double[ix+j]; - } - } - ae_frame_leave(_state); - return result; -} - - - - - - - - -ae_bool testcreflections(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t n; - ae_int_t m; - ae_int_t maxmn; - ae_vector x; - ae_vector v; - ae_vector work; - ae_matrix h; - ae_matrix a; - ae_matrix b; - ae_matrix c; - ae_complex tmp; - ae_complex beta; - ae_complex tau; - double err; - double mer; - double mel; - double meg; - ae_int_t pass; - ae_int_t passcount; - ae_bool waserrors; - double threshold; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&v, 0, sizeof(v)); - memset(&work, 0, sizeof(work)); - memset(&h, 0, sizeof(h)); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - memset(&c, 0, sizeof(c)); - ae_vector_init(&x, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&v, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&work, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&h, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&b, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_COMPLEX, _state, ae_true); - - threshold = 1000*ae_machineepsilon; - passcount = 1000; - mer = (double)(0); - mel = (double)(0); - meg = (double)(0); - for(pass=1; pass<=passcount; pass++) - { - - /* - * Task - */ - n = 1+ae_randominteger(10, _state); - m = 1+ae_randominteger(10, _state); - maxmn = ae_maxint(m, n, _state); - - /* - * Initialize - */ - ae_vector_set_length(&x, maxmn+1, _state); - ae_vector_set_length(&v, maxmn+1, _state); - ae_vector_set_length(&work, maxmn+1, _state); - ae_matrix_set_length(&h, maxmn+1, maxmn+1, _state); - ae_matrix_set_length(&a, maxmn+1, maxmn+1, _state); - ae_matrix_set_length(&b, maxmn+1, maxmn+1, _state); - ae_matrix_set_length(&c, maxmn+1, maxmn+1, _state); - - /* - * GenerateReflection - */ - for(i=1; i<=n; i++) - { - x.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1; - x.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1; - v.ptr.p_complex[i] = x.ptr.p_complex[i]; - } - complexgeneratereflection(&v, n, &tau, _state); - beta = v.ptr.p_complex[1]; - v.ptr.p_complex[1] = ae_complex_from_i(1); - for(i=1; i<=n; i++) - { - for(j=1; j<=n; j++) - { - if( i==j ) - { - h.ptr.pp_complex[i][j] = ae_c_d_sub(1,ae_c_mul(ae_c_mul(tau,v.ptr.p_complex[i]),ae_c_conj(v.ptr.p_complex[j], _state))); - } - else - { - h.ptr.pp_complex[i][j] = ae_c_neg(ae_c_mul(ae_c_mul(tau,v.ptr.p_complex[i]),ae_c_conj(v.ptr.p_complex[j], _state))); - } - } - } - err = (double)(0); - for(i=1; i<=n; i++) - { - tmp = ae_v_cdotproduct(&h.ptr.pp_complex[1][i], h.stride, "Conj", &x.ptr.p_complex[1], 1, "N", ae_v_len(1,n)); - if( i==1 ) - { - err = ae_maxreal(err, ae_c_abs(ae_c_sub(tmp,beta), _state), _state); - } - else - { - err = ae_maxreal(err, ae_c_abs(tmp, _state), _state); - } - } - err = ae_maxreal(err, ae_fabs(beta.y, _state), _state); - meg = ae_maxreal(meg, err, _state); - - /* - * ApplyReflectionFromTheLeft - */ - for(i=1; i<=m; i++) - { - x.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1; - x.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1; - v.ptr.p_complex[i] = x.ptr.p_complex[i]; - } - for(i=1; i<=m; i++) - { - for(j=1; j<=n; j++) - { - a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - b.ptr.pp_complex[i][j] = a.ptr.pp_complex[i][j]; - } - } - complexgeneratereflection(&v, m, &tau, _state); - beta = v.ptr.p_complex[1]; - v.ptr.p_complex[1] = ae_complex_from_i(1); - complexapplyreflectionfromtheleft(&b, tau, &v, 1, m, 1, n, &work, _state); - for(i=1; i<=m; i++) - { - for(j=1; j<=m; j++) - { - if( i==j ) - { - h.ptr.pp_complex[i][j] = ae_c_d_sub(1,ae_c_mul(ae_c_mul(tau,v.ptr.p_complex[i]),ae_c_conj(v.ptr.p_complex[j], _state))); - } - else - { - h.ptr.pp_complex[i][j] = ae_c_neg(ae_c_mul(ae_c_mul(tau,v.ptr.p_complex[i]),ae_c_conj(v.ptr.p_complex[j], _state))); - } - } - } - for(i=1; i<=m; i++) - { - for(j=1; j<=n; j++) - { - tmp = ae_v_cdotproduct(&h.ptr.pp_complex[i][1], 1, "N", &a.ptr.pp_complex[1][j], a.stride, "N", ae_v_len(1,m)); - c.ptr.pp_complex[i][j] = tmp; - } - } - err = (double)(0); - for(i=1; i<=m; i++) - { - for(j=1; j<=n; j++) - { - err = ae_maxreal(err, ae_c_abs(ae_c_sub(b.ptr.pp_complex[i][j],c.ptr.pp_complex[i][j]), _state), _state); - } - } - mel = ae_maxreal(mel, err, _state); - - /* - * ApplyReflectionFromTheRight - */ - for(i=1; i<=n; i++) - { - x.ptr.p_complex[i] = ae_complex_from_d(2*ae_randomreal(_state)-1); - v.ptr.p_complex[i] = x.ptr.p_complex[i]; - } - for(i=1; i<=m; i++) - { - for(j=1; j<=n; j++) - { - a.ptr.pp_complex[i][j] = ae_complex_from_d(2*ae_randomreal(_state)-1); - b.ptr.pp_complex[i][j] = a.ptr.pp_complex[i][j]; - } - } - complexgeneratereflection(&v, n, &tau, _state); - beta = v.ptr.p_complex[1]; - v.ptr.p_complex[1] = ae_complex_from_i(1); - complexapplyreflectionfromtheright(&b, tau, &v, 1, m, 1, n, &work, _state); - for(i=1; i<=n; i++) - { - for(j=1; j<=n; j++) - { - if( i==j ) - { - h.ptr.pp_complex[i][j] = ae_c_d_sub(1,ae_c_mul(ae_c_mul(tau,v.ptr.p_complex[i]),ae_c_conj(v.ptr.p_complex[j], _state))); - } - else - { - h.ptr.pp_complex[i][j] = ae_c_neg(ae_c_mul(ae_c_mul(tau,v.ptr.p_complex[i]),ae_c_conj(v.ptr.p_complex[j], _state))); - } - } - } - for(i=1; i<=m; i++) - { - for(j=1; j<=n; j++) - { - tmp = ae_v_cdotproduct(&a.ptr.pp_complex[i][1], 1, "N", &h.ptr.pp_complex[1][j], h.stride, "N", ae_v_len(1,n)); - c.ptr.pp_complex[i][j] = tmp; - } - } - err = (double)(0); - for(i=1; i<=m; i++) - { - for(j=1; j<=n; j++) - { - err = ae_maxreal(err, ae_c_abs(ae_c_sub(b.ptr.pp_complex[i][j],c.ptr.pp_complex[i][j]), _state), _state); - } - } - mer = ae_maxreal(mer, err, _state); - } - - /* - * Overflow crash test - */ - ae_vector_set_length(&x, 10+1, _state); - ae_vector_set_length(&v, 10+1, _state); - for(i=1; i<=10; i++) - { - v.ptr.p_complex[i] = ae_complex_from_d(ae_maxrealnumber*0.01*(2*ae_randomreal(_state)-1)); - } - complexgeneratereflection(&v, 10, &tau, _state); - - /* - * report - */ - waserrors = (ae_fp_greater(meg,threshold)||ae_fp_greater(mel,threshold))||ae_fp_greater(mer,threshold); - if( !silent ) - { - printf("TESTING COMPLEX REFLECTIONS\n"); - printf("Generate error: %5.3e\n", - (double)(meg)); - printf("Apply(L) error: %5.3e\n", - (double)(mel)); - printf("Apply(R) error: %5.3e\n", - (double)(mer)); - printf("Threshold: %5.3e\n", - (double)(threshold)); - printf("Overflow crash test: PASSED\n"); - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - - -static ae_int_t testmatgenunit_maxsvditerations = 60; -static void testmatgenunit_unset2d(/* Real */ ae_matrix* a, - ae_state *_state); -static void testmatgenunit_unset2dc(/* Complex */ ae_matrix* a, - ae_state *_state); -static ae_bool testmatgenunit_isspd(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_state *_state); -static ae_bool testmatgenunit_ishpd(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_state *_state); -static ae_bool testmatgenunit_testeult(ae_state *_state); -static double testmatgenunit_svdcond(/* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state); -static ae_bool testmatgenunit_obsoletesvddecomposition(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* v, - ae_state *_state); -static double testmatgenunit_extsign(double a, double b, ae_state *_state); -static double testmatgenunit_mymax(double a, double b, ae_state *_state); -static double testmatgenunit_pythag(double a, double b, ae_state *_state); - - - - - -ae_bool testmatgen(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix b; - ae_matrix u; - ae_matrix v; - ae_matrix ca; - ae_matrix cb; - ae_matrix r1; - ae_matrix r2; - ae_matrix c1; - ae_matrix c2; - ae_vector w; - ae_int_t n; - ae_int_t maxn; - ae_int_t i; - ae_int_t j; - ae_int_t pass; - ae_int_t passcount; - ae_bool waserrors; - double cond; - double threshold; - double vt; - ae_complex ct; - double minw; - double maxw; - ae_bool serr; - ae_bool herr; - ae_bool spderr; - ae_bool hpderr; - ae_bool rerr; - ae_bool cerr; - ae_bool eulerr; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - memset(&u, 0, sizeof(u)); - memset(&v, 0, sizeof(v)); - memset(&ca, 0, sizeof(ca)); - memset(&cb, 0, sizeof(cb)); - memset(&r1, 0, sizeof(r1)); - memset(&r2, 0, sizeof(r2)); - memset(&c1, 0, sizeof(c1)); - memset(&c2, 0, sizeof(c2)); - memset(&w, 0, sizeof(w)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ca, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&cb, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&r1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&r2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c1, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&c2, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - - rerr = ae_false; - cerr = ae_false; - serr = ae_false; - herr = ae_false; - spderr = ae_false; - hpderr = ae_false; - eulerr = ae_false; - waserrors = ae_false; - maxn = 20; - passcount = 15; - threshold = 1000*ae_machineepsilon; - - /* - * Testing orthogonal - */ - for(n=1; n<=maxn; n++) - { - for(pass=1; pass<=passcount; pass++) - { - ae_matrix_set_length(&r1, n-1+1, 2*n-1+1, _state); - ae_matrix_set_length(&r2, 2*n-1+1, n-1+1, _state); - ae_matrix_set_length(&c1, n-1+1, 2*n-1+1, _state); - ae_matrix_set_length(&c2, 2*n-1+1, n-1+1, _state); - - /* - * Random orthogonal, real - */ - testmatgenunit_unset2d(&a, _state); - testmatgenunit_unset2d(&b, _state); - rmatrixrndorthogonal(n, &a, _state); - rmatrixrndorthogonal(n, &b, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - - /* - * orthogonality test - */ - vt = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &a.ptr.pp_double[j][0], 1, ae_v_len(0,n-1)); - if( i==j ) - { - rerr = rerr||ae_fp_greater(ae_fabs(vt-1, _state),threshold); - } - else - { - rerr = rerr||ae_fp_greater(ae_fabs(vt, _state),threshold); - } - vt = ae_v_dotproduct(&b.ptr.pp_double[i][0], 1, &b.ptr.pp_double[j][0], 1, ae_v_len(0,n-1)); - if( i==j ) - { - rerr = rerr||ae_fp_greater(ae_fabs(vt-1, _state),threshold); - } - else - { - rerr = rerr||ae_fp_greater(ae_fabs(vt, _state),threshold); - } - - /* - * test for difference in A and B - */ - if( n>=2 ) - { - rerr = rerr||ae_fp_eq(a.ptr.pp_double[i][j],b.ptr.pp_double[i][j]); - } - } - } - - /* - * Random orthogonal, complex - */ - testmatgenunit_unset2dc(&ca, _state); - testmatgenunit_unset2dc(&cb, _state); - cmatrixrndorthogonal(n, &ca, _state); - cmatrixrndorthogonal(n, &cb, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - - /* - * orthogonality test - */ - ct = ae_v_cdotproduct(&ca.ptr.pp_complex[i][0], 1, "N", &ca.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,n-1)); - if( i==j ) - { - cerr = cerr||ae_fp_greater(ae_c_abs(ae_c_sub_d(ct,1), _state),threshold); - } - else - { - cerr = cerr||ae_fp_greater(ae_c_abs(ct, _state),threshold); - } - ct = ae_v_cdotproduct(&cb.ptr.pp_complex[i][0], 1, "N", &cb.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,n-1)); - if( i==j ) - { - cerr = cerr||ae_fp_greater(ae_c_abs(ae_c_sub_d(ct,1), _state),threshold); - } - else - { - cerr = cerr||ae_fp_greater(ae_c_abs(ct, _state),threshold); - } - - /* - * test for difference in A and B - */ - if( n>=2 ) - { - cerr = cerr||ae_c_eq(ca.ptr.pp_complex[i][j],cb.ptr.pp_complex[i][j]); - } - } - } - - /* - * From the right real tests: - * 1. E*Q is orthogonal - * 2. Q1<>Q2 (routine result is changing) - * 3. (E E)'*Q = (Q' Q')' (correct handling of non-square matrices) - */ - testmatgenunit_unset2d(&a, _state); - testmatgenunit_unset2d(&b, _state); - ae_matrix_set_length(&a, n-1+1, n-1+1, _state); - ae_matrix_set_length(&b, n-1+1, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - b.ptr.pp_double[i][j] = (double)(0); - } - a.ptr.pp_double[i][i] = (double)(1); - b.ptr.pp_double[i][i] = (double)(1); - } - rmatrixrndorthogonalfromtheright(&a, n, n, _state); - rmatrixrndorthogonalfromtheright(&b, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - - /* - * orthogonality test - */ - vt = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &a.ptr.pp_double[j][0], 1, ae_v_len(0,n-1)); - if( i==j ) - { - rerr = rerr||ae_fp_greater(ae_fabs(vt-1, _state),threshold); - } - else - { - rerr = rerr||ae_fp_greater(ae_fabs(vt, _state),threshold); - } - vt = ae_v_dotproduct(&b.ptr.pp_double[i][0], 1, &b.ptr.pp_double[j][0], 1, ae_v_len(0,n-1)); - if( i==j ) - { - rerr = rerr||ae_fp_greater(ae_fabs(vt-1, _state),threshold); - } - else - { - rerr = rerr||ae_fp_greater(ae_fabs(vt, _state),threshold); - } - - /* - * test for difference in A and B - */ - if( n>=2 ) - { - rerr = rerr||ae_fp_eq(a.ptr.pp_double[i][j],b.ptr.pp_double[i][j]); - } - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - r2.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - r2.ptr.pp_double[i+n][j] = r2.ptr.pp_double[i][j]; - } - } - rmatrixrndorthogonalfromtheright(&r2, 2*n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - rerr = rerr||ae_fp_greater(ae_fabs(r2.ptr.pp_double[i+n][j]-r2.ptr.pp_double[i][j], _state),threshold); - } - } - - /* - * From the left real tests: - * 1. Q*E is orthogonal - * 2. Q1<>Q2 (routine result is changing) - * 3. Q*(E E) = (Q Q) (correct handling of non-square matrices) - */ - testmatgenunit_unset2d(&a, _state); - testmatgenunit_unset2d(&b, _state); - ae_matrix_set_length(&a, n-1+1, n-1+1, _state); - ae_matrix_set_length(&b, n-1+1, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - b.ptr.pp_double[i][j] = (double)(0); - } - a.ptr.pp_double[i][i] = (double)(1); - b.ptr.pp_double[i][i] = (double)(1); - } - rmatrixrndorthogonalfromtheleft(&a, n, n, _state); - rmatrixrndorthogonalfromtheleft(&b, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - - /* - * orthogonality test - */ - vt = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &a.ptr.pp_double[j][0], 1, ae_v_len(0,n-1)); - if( i==j ) - { - rerr = rerr||ae_fp_greater(ae_fabs(vt-1, _state),threshold); - } - else - { - rerr = rerr||ae_fp_greater(ae_fabs(vt, _state),threshold); - } - vt = ae_v_dotproduct(&b.ptr.pp_double[i][0], 1, &b.ptr.pp_double[j][0], 1, ae_v_len(0,n-1)); - if( i==j ) - { - rerr = rerr||ae_fp_greater(ae_fabs(vt-1, _state),threshold); - } - else - { - rerr = rerr||ae_fp_greater(ae_fabs(vt, _state),threshold); - } - - /* - * test for difference in A and B - */ - if( n>=2 ) - { - rerr = rerr||ae_fp_eq(a.ptr.pp_double[i][j],b.ptr.pp_double[i][j]); - } - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - r1.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - r1.ptr.pp_double[i][j+n] = r1.ptr.pp_double[i][j]; - } - } - rmatrixrndorthogonalfromtheleft(&r1, n, 2*n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - rerr = rerr||ae_fp_greater(ae_fabs(r1.ptr.pp_double[i][j]-r1.ptr.pp_double[i][j+n], _state),threshold); - } - } - - /* - * From the right complex tests: - * 1. E*Q is orthogonal - * 2. Q1<>Q2 (routine result is changing) - * 3. (E E)'*Q = (Q' Q')' (correct handling of non-square matrices) - */ - testmatgenunit_unset2dc(&ca, _state); - testmatgenunit_unset2dc(&cb, _state); - ae_matrix_set_length(&ca, n-1+1, n-1+1, _state); - ae_matrix_set_length(&cb, n-1+1, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - ca.ptr.pp_complex[i][j] = ae_complex_from_i(0); - cb.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - ca.ptr.pp_complex[i][i] = ae_complex_from_i(1); - cb.ptr.pp_complex[i][i] = ae_complex_from_i(1); - } - cmatrixrndorthogonalfromtheright(&ca, n, n, _state); - cmatrixrndorthogonalfromtheright(&cb, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - - /* - * orthogonality test - */ - ct = ae_v_cdotproduct(&ca.ptr.pp_complex[i][0], 1, "N", &ca.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,n-1)); - if( i==j ) - { - cerr = cerr||ae_fp_greater(ae_c_abs(ae_c_sub_d(ct,1), _state),threshold); - } - else - { - cerr = cerr||ae_fp_greater(ae_c_abs(ct, _state),threshold); - } - ct = ae_v_cdotproduct(&cb.ptr.pp_complex[i][0], 1, "N", &cb.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,n-1)); - if( i==j ) - { - cerr = cerr||ae_fp_greater(ae_c_abs(ae_c_sub_d(ct,1), _state),threshold); - } - else - { - cerr = cerr||ae_fp_greater(ae_c_abs(ct, _state),threshold); - } - - /* - * test for difference in A and B - */ - cerr = cerr||ae_c_eq(ca.ptr.pp_complex[i][j],cb.ptr.pp_complex[i][j]); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - c2.ptr.pp_complex[i][j] = ae_complex_from_d(2*ae_randomreal(_state)-1); - c2.ptr.pp_complex[i+n][j] = c2.ptr.pp_complex[i][j]; - } - } - cmatrixrndorthogonalfromtheright(&c2, 2*n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - cerr = cerr||ae_fp_greater(ae_c_abs(ae_c_sub(c2.ptr.pp_complex[i+n][j],c2.ptr.pp_complex[i][j]), _state),threshold); - } - } - - /* - * From the left complex tests: - * 1. Q*E is orthogonal - * 2. Q1<>Q2 (routine result is changing) - * 3. Q*(E E) = (Q Q) (correct handling of non-square matrices) - */ - testmatgenunit_unset2dc(&ca, _state); - testmatgenunit_unset2dc(&cb, _state); - ae_matrix_set_length(&ca, n-1+1, n-1+1, _state); - ae_matrix_set_length(&cb, n-1+1, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - ca.ptr.pp_complex[i][j] = ae_complex_from_i(0); - cb.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - ca.ptr.pp_complex[i][i] = ae_complex_from_i(1); - cb.ptr.pp_complex[i][i] = ae_complex_from_i(1); - } - cmatrixrndorthogonalfromtheleft(&ca, n, n, _state); - cmatrixrndorthogonalfromtheleft(&cb, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - - /* - * orthogonality test - */ - ct = ae_v_cdotproduct(&ca.ptr.pp_complex[i][0], 1, "N", &ca.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,n-1)); - if( i==j ) - { - cerr = cerr||ae_fp_greater(ae_c_abs(ae_c_sub_d(ct,1), _state),threshold); - } - else - { - cerr = cerr||ae_fp_greater(ae_c_abs(ct, _state),threshold); - } - ct = ae_v_cdotproduct(&cb.ptr.pp_complex[i][0], 1, "N", &cb.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,n-1)); - if( i==j ) - { - cerr = cerr||ae_fp_greater(ae_c_abs(ae_c_sub_d(ct,1), _state),threshold); - } - else - { - cerr = cerr||ae_fp_greater(ae_c_abs(ct, _state),threshold); - } - - /* - * test for difference in A and B - */ - cerr = cerr||ae_c_eq(ca.ptr.pp_complex[i][j],cb.ptr.pp_complex[i][j]); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - c1.ptr.pp_complex[i][j] = ae_complex_from_d(2*ae_randomreal(_state)-1); - c1.ptr.pp_complex[i][j+n] = c1.ptr.pp_complex[i][j]; - } - } - cmatrixrndorthogonalfromtheleft(&c1, n, 2*n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - cerr = cerr||ae_fp_greater(ae_c_abs(ae_c_sub(c1.ptr.pp_complex[i][j],c1.ptr.pp_complex[i][j+n]), _state),threshold); - } - } - } - } - - /* - * Testing GCond - */ - for(n=2; n<=maxn; n++) - { - for(pass=1; pass<=passcount; pass++) - { - - /* - * real test - */ - testmatgenunit_unset2d(&a, _state); - cond = ae_exp(ae_log((double)(1000), _state)*ae_randomreal(_state), _state); - rmatrixrndcond(n, cond, &a, _state); - ae_matrix_set_length(&b, n+1, n+1, _state); - for(i=1; i<=n; i++) - { - for(j=1; j<=n; j++) - { - b.ptr.pp_double[i][j] = a.ptr.pp_double[i-1][j-1]; - } - } - if( testmatgenunit_obsoletesvddecomposition(&b, n, n, &w, &v, _state) ) - { - maxw = w.ptr.p_double[1]; - minw = w.ptr.p_double[1]; - for(i=2; i<=n; i++) - { - if( ae_fp_greater(w.ptr.p_double[i],maxw) ) - { - maxw = w.ptr.p_double[i]; - } - if( ae_fp_less(w.ptr.p_double[i],minw) ) - { - minw = w.ptr.p_double[i]; - } - } - vt = maxw/minw/cond; - if( ae_fp_greater(ae_fabs(ae_log(vt, _state), _state),ae_log(1+threshold, _state)) ) - { - rerr = ae_true; - } - } - } - } - - /* - * Symmetric/SPD - * N = 2 .. 30 - */ - for(n=2; n<=maxn; n++) - { - - /* - * SPD matrices - */ - for(pass=1; pass<=passcount; pass++) - { - - /* - * Generate A - */ - testmatgenunit_unset2d(&a, _state); - cond = ae_exp(ae_log((double)(1000), _state)*ae_randomreal(_state), _state); - spdmatrixrndcond(n, cond, &a, _state); - - /* - * test condition number - */ - spderr = spderr||ae_fp_greater(testmatgenunit_svdcond(&a, n, _state)/cond-1,threshold); - - /* - * test SPD - */ - spderr = spderr||!testmatgenunit_isspd(&a, n, ae_true, _state); - - /* - * test that A is symmetic - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - spderr = spderr||ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-a.ptr.pp_double[j][i], _state),threshold); - } - } - - /* - * test for difference between A and B (subsequent matrix) - */ - testmatgenunit_unset2d(&b, _state); - spdmatrixrndcond(n, cond, &b, _state); - if( n>=2 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - spderr = spderr||ae_fp_eq(a.ptr.pp_double[i][j],b.ptr.pp_double[i][j]); - } - } - } - } - - /* - * HPD matrices - */ - for(pass=1; pass<=passcount; pass++) - { - - /* - * Generate A - */ - testmatgenunit_unset2dc(&ca, _state); - cond = ae_exp(ae_log((double)(1000), _state)*ae_randomreal(_state), _state); - hpdmatrixrndcond(n, cond, &ca, _state); - - /* - * test HPD - */ - hpderr = hpderr||!testmatgenunit_ishpd(&ca, n, _state); - - /* - * test that A is Hermitian - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - hpderr = hpderr||ae_fp_greater(ae_c_abs(ae_c_sub(ca.ptr.pp_complex[i][j],ae_c_conj(ca.ptr.pp_complex[j][i], _state)), _state),threshold); - } - } - - /* - * test for difference between A and B (subsequent matrix) - */ - testmatgenunit_unset2dc(&cb, _state); - hpdmatrixrndcond(n, cond, &cb, _state); - if( n>=2 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - hpderr = hpderr||ae_c_eq(ca.ptr.pp_complex[i][j],cb.ptr.pp_complex[i][j]); - } - } - } - } - - /* - * Symmetric matrices - */ - for(pass=1; pass<=passcount; pass++) - { - - /* - * test condition number - */ - testmatgenunit_unset2d(&a, _state); - cond = ae_exp(ae_log((double)(1000), _state)*ae_randomreal(_state), _state); - smatrixrndcond(n, cond, &a, _state); - serr = serr||ae_fp_greater(testmatgenunit_svdcond(&a, n, _state)/cond-1,threshold); - - /* - * test for difference between A and B - */ - testmatgenunit_unset2d(&b, _state); - smatrixrndcond(n, cond, &b, _state); - if( n>=2 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - serr = serr||ae_fp_eq(a.ptr.pp_double[i][j],b.ptr.pp_double[i][j]); - } - } - } - } - - /* - * Hermitian matrices - */ - for(pass=1; pass<=passcount; pass++) - { - - /* - * Generate A - */ - testmatgenunit_unset2dc(&ca, _state); - cond = ae_exp(ae_log((double)(1000), _state)*ae_randomreal(_state), _state); - hmatrixrndcond(n, cond, &ca, _state); - - /* - * test that A is Hermitian - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - herr = herr||ae_fp_greater(ae_c_abs(ae_c_sub(ca.ptr.pp_complex[i][j],ae_c_conj(ca.ptr.pp_complex[j][i], _state)), _state),threshold); - } - } - - /* - * test for difference between A and B (subsequent matrix) - */ - testmatgenunit_unset2dc(&cb, _state); - hmatrixrndcond(n, cond, &cb, _state); - if( n>=2 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - herr = herr||ae_c_eq(ca.ptr.pp_complex[i][j],cb.ptr.pp_complex[i][j]); - } - } - } - } - } - - /* - * Test for symmetric matrices - */ - eulerr = testmatgenunit_testeult(_state); - - /* - * report - */ - waserrors = (((((rerr||cerr)||serr)||spderr)||herr)||hpderr)||eulerr; - if( !silent ) - { - printf("TESTING MATRIX GENERATOR\n"); - printf("REAL TEST: "); - if( !rerr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("COMPLEX TEST: "); - if( !cerr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("SYMMETRIC TEST: "); - if( !serr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("HERMITIAN TEST: "); - if( !herr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("SPD TEST: "); - if( !spderr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("HPD TEST: "); - if( !hpderr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("TEST FOR SYMMETRIC MATRICES: "); - if( !eulerr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Unsets 2D array. -*************************************************************************/ -static void testmatgenunit_unset2d(/* Real */ ae_matrix* a, - ae_state *_state) -{ - - - ae_matrix_set_length(a, 0+1, 0+1, _state); - a->ptr.pp_double[0][0] = 2*ae_randomreal(_state)-1; -} - - -/************************************************************************* -Unsets 2D array. -*************************************************************************/ -static void testmatgenunit_unset2dc(/* Complex */ ae_matrix* a, - ae_state *_state) -{ - - - ae_matrix_set_length(a, 0+1, 0+1, _state); - a->ptr.pp_complex[0][0] = ae_complex_from_d(2*ae_randomreal(_state)-1); -} - - -/************************************************************************* -Test whether matrix is SPD -*************************************************************************/ -static ae_bool testmatgenunit_isspd(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_int_t i; - ae_int_t j; - double ajj; - double v; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - - - /* - * Test the input parameters. - */ - ae_assert(n>=0, "Error in SMatrixCholesky: incorrect function arguments", _state); - - /* - * Quick return if possible - */ - result = ae_true; - if( n<=0 ) - { - ae_frame_leave(_state); - return result; - } - if( isupper ) - { - - /* - * Compute the Cholesky factorization A = U'*U. - */ - for(j=0; j<=n-1; j++) - { - - /* - * Compute U(J,J) and test for non-positive-definiteness. - */ - v = ae_v_dotproduct(&a->ptr.pp_double[0][j], a->stride, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,j-1)); - ajj = a->ptr.pp_double[j][j]-v; - if( ae_fp_less_eq(ajj,(double)(0)) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - ajj = ae_sqrt(ajj, _state); - a->ptr.pp_double[j][j] = ajj; - - /* - * Compute elements J+1:N of row J. - */ - if( jptr.pp_double[0][i], a->stride, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,j-1)); - a->ptr.pp_double[j][i] = a->ptr.pp_double[j][i]-v; - } - v = 1/ajj; - ae_v_muld(&a->ptr.pp_double[j][j+1], 1, ae_v_len(j+1,n-1), v); - } - } - } - else - { - - /* - * Compute the Cholesky factorization A = L*L'. - */ - for(j=0; j<=n-1; j++) - { - - /* - * Compute L(J,J) and test for non-positive-definiteness. - */ - v = ae_v_dotproduct(&a->ptr.pp_double[j][0], 1, &a->ptr.pp_double[j][0], 1, ae_v_len(0,j-1)); - ajj = a->ptr.pp_double[j][j]-v; - if( ae_fp_less_eq(ajj,(double)(0)) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - ajj = ae_sqrt(ajj, _state); - a->ptr.pp_double[j][j] = ajj; - - /* - * Compute elements J+1:N of column J. - */ - if( jptr.pp_double[i][0], 1, &a->ptr.pp_double[j][0], 1, ae_v_len(0,j-1)); - a->ptr.pp_double[i][j] = a->ptr.pp_double[i][j]-v; - } - v = 1/ajj; - ae_v_muld(&a->ptr.pp_double[j+1][j], a->stride, ae_v_len(j+1,n-1), v); - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Tests whether A is HPD -*************************************************************************/ -static ae_bool testmatgenunit_ishpd(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_int_t j; - double ajj; - ae_complex v; - double r; - ae_vector t; - ae_vector t2; - ae_vector t3; - ae_int_t i; - ae_matrix a1; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&t, 0, sizeof(t)); - memset(&t2, 0, sizeof(t2)); - memset(&t3, 0, sizeof(t3)); - memset(&a1, 0, sizeof(a1)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_vector_init(&t, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&t2, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&t3, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&a1, 0, 0, DT_COMPLEX, _state, ae_true); - - ae_vector_set_length(&t, n-1+1, _state); - ae_vector_set_length(&t2, n-1+1, _state); - ae_vector_set_length(&t3, n-1+1, _state); - result = ae_true; - - /* - * Compute the Cholesky factorization A = U'*U. - */ - for(j=0; j<=n-1; j++) - { - - /* - * Compute U(J,J) and test for non-positive-definiteness. - */ - v = ae_v_cdotproduct(&a->ptr.pp_complex[0][j], a->stride, "Conj", &a->ptr.pp_complex[0][j], a->stride, "N", ae_v_len(0,j-1)); - ajj = ae_c_sub(a->ptr.pp_complex[j][j],v).x; - if( ae_fp_less_eq(ajj,(double)(0)) ) - { - a->ptr.pp_complex[j][j] = ae_complex_from_d(ajj); - result = ae_false; - ae_frame_leave(_state); - return result; - } - ajj = ae_sqrt(ajj, _state); - a->ptr.pp_complex[j][j] = ae_complex_from_d(ajj); - - /* - * Compute elements J+1:N-1 of row J. - */ - if( jptr.pp_complex[0][j], a->stride, "Conj", ae_v_len(0,j-1)); - ae_v_cmove(&t3.ptr.p_complex[j+1], 1, &a->ptr.pp_complex[j][j+1], 1, "N", ae_v_len(j+1,n-1)); - for(i=j+1; i<=n-1; i++) - { - v = ae_v_cdotproduct(&a->ptr.pp_complex[0][i], a->stride, "N", &t2.ptr.p_complex[0], 1, "N", ae_v_len(0,j-1)); - t3.ptr.p_complex[i] = ae_c_sub(t3.ptr.p_complex[i],v); - } - ae_v_cmove(&a->ptr.pp_complex[j][j+1], 1, &t3.ptr.p_complex[j+1], 1, "N", ae_v_len(j+1,n-1)); - r = 1/ajj; - ae_v_cmuld(&a->ptr.pp_complex[j][j+1], 1, ae_v_len(j+1,n-1), r); - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -The function check, that upper triangle from symmetric matrix is equal to -lower triangle. -*************************************************************************/ -static ae_bool testmatgenunit_testeult(ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix b; - double c; - double range; - double eps; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&b, 0, 0, DT_COMPLEX, _state, ae_true); - - eps = 2*ae_machineepsilon; - range = 100*(2*ae_randomreal(_state)-1); - for(n=1; n<=15; n++) - { - c = 900*ae_randomreal(_state)+100; - - /* - * Generate symmetric matrix and check it - */ - smatrixrndcond(n, c, &a, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-a.ptr.pp_double[j][i], _state),eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - spdmatrixrndcond(n, c, &a, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-a.ptr.pp_double[j][i], _state),eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - hmatrixrndcond(n, c, &b, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_greater(ae_fabs(b.ptr.pp_complex[i][j].x-b.ptr.pp_complex[j][i].x, _state),eps)||ae_fp_greater(ae_fabs(b.ptr.pp_complex[i][j].y+b.ptr.pp_complex[j][i].y, _state),eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - hpdmatrixrndcond(n, c, &b, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_greater(ae_fabs(b.ptr.pp_complex[i][j].x-b.ptr.pp_complex[j][i].x, _state),eps)||ae_fp_greater(ae_fabs(b.ptr.pp_complex[i][j].y+b.ptr.pp_complex[j][i].y, _state),eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - - /* - * Prepare symmetric matrix with real values - */ - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = range*(2*ae_randomreal(_state)-1); - } - } - for(i=0; i<=n-2; i++) - { - for(j=i+1; j<=n-1; j++) - { - a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j]; - } - } - smatrixrndmultiply(&a, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-a.ptr.pp_double[j][i], _state),eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - - /* - * Prepare symmetric matrix with complex values - */ - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - b.ptr.pp_complex[i][j].x = range*(2*ae_randomreal(_state)-1); - if( i!=j ) - { - b.ptr.pp_complex[i][j].y = range*(2*ae_randomreal(_state)-1); - } - else - { - b.ptr.pp_complex[i][j].y = (double)(0); - } - } - } - for(i=0; i<=n-1; i++) - { - for(j=i+1; j<=n-1; j++) - { - b.ptr.pp_complex[i][j].x = b.ptr.pp_complex[j][i].x; - b.ptr.pp_complex[i][j].y = -b.ptr.pp_complex[j][i].y; - } - } - hmatrixrndmultiply(&b, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.pp_complex[i][i].y = (double)(0); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_greater(ae_fabs(b.ptr.pp_complex[i][j].x-b.ptr.pp_complex[j][i].x, _state),eps)||ae_fp_greater(ae_fabs(b.ptr.pp_complex[i][j].y+b.ptr.pp_complex[j][i].y, _state),eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -SVD condition number -*************************************************************************/ -static double testmatgenunit_svdcond(/* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a1; - ae_matrix v; - ae_vector w; - ae_int_t i; - ae_int_t j; - double minw; - double maxw; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&a1, 0, sizeof(a1)); - memset(&v, 0, sizeof(v)); - memset(&w, 0, sizeof(w)); - ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - - ae_matrix_set_length(&a1, n+1, n+1, _state); - for(i=1; i<=n; i++) - { - for(j=1; j<=n; j++) - { - a1.ptr.pp_double[i][j] = a->ptr.pp_double[i-1][j-1]; - } - } - if( !testmatgenunit_obsoletesvddecomposition(&a1, n, n, &w, &v, _state) ) - { - result = (double)(0); - ae_frame_leave(_state); - return result; - } - minw = w.ptr.p_double[1]; - maxw = w.ptr.p_double[1]; - for(i=2; i<=n; i++) - { - if( ae_fp_less(w.ptr.p_double[i],minw) ) - { - minw = w.ptr.p_double[i]; - } - if( ae_fp_greater(w.ptr.p_double[i],maxw) ) - { - maxw = w.ptr.p_double[i]; - } - } - result = maxw/minw; - ae_frame_leave(_state); - return result; -} - - -static ae_bool testmatgenunit_obsoletesvddecomposition(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* v, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nm; - ae_int_t minmn; - ae_int_t l; - ae_int_t k; - ae_int_t j; - ae_int_t jj; - ae_int_t its; - ae_int_t i; - double z; - double y; - double x; - double vscale; - double s; - double h; - double g; - double f; - double c; - double anorm; - ae_vector rv1; - ae_bool flag; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&rv1, 0, sizeof(rv1)); - ae_vector_clear(w); - ae_matrix_clear(v); - ae_vector_init(&rv1, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&rv1, n+1, _state); - ae_vector_set_length(w, n+1, _state); - ae_matrix_set_length(v, n+1, n+1, _state); - result = ae_true; - if( mptr.pp_double[k][i], _state); - } - if( ae_fp_neq(vscale,0.0) ) - { - for(k=i; k<=m; k++) - { - a->ptr.pp_double[k][i] = a->ptr.pp_double[k][i]/vscale; - s = s+a->ptr.pp_double[k][i]*a->ptr.pp_double[k][i]; - } - f = a->ptr.pp_double[i][i]; - g = -testmatgenunit_extsign(ae_sqrt(s, _state), f, _state); - h = f*g-s; - a->ptr.pp_double[i][i] = f-g; - if( i!=n ) - { - for(j=l; j<=n; j++) - { - s = 0.0; - for(k=i; k<=m; k++) - { - s = s+a->ptr.pp_double[k][i]*a->ptr.pp_double[k][j]; - } - f = s/h; - for(k=i; k<=m; k++) - { - a->ptr.pp_double[k][j] = a->ptr.pp_double[k][j]+f*a->ptr.pp_double[k][i]; - } - } - } - for(k=i; k<=m; k++) - { - a->ptr.pp_double[k][i] = vscale*a->ptr.pp_double[k][i]; - } - } - } - w->ptr.p_double[i] = vscale*g; - g = 0.0; - s = 0.0; - vscale = 0.0; - if( i<=m&&i!=n ) - { - for(k=l; k<=n; k++) - { - vscale = vscale+ae_fabs(a->ptr.pp_double[i][k], _state); - } - if( ae_fp_neq(vscale,0.0) ) - { - for(k=l; k<=n; k++) - { - a->ptr.pp_double[i][k] = a->ptr.pp_double[i][k]/vscale; - s = s+a->ptr.pp_double[i][k]*a->ptr.pp_double[i][k]; - } - f = a->ptr.pp_double[i][l]; - g = -testmatgenunit_extsign(ae_sqrt(s, _state), f, _state); - h = f*g-s; - a->ptr.pp_double[i][l] = f-g; - for(k=l; k<=n; k++) - { - rv1.ptr.p_double[k] = a->ptr.pp_double[i][k]/h; - } - if( i!=m ) - { - for(j=l; j<=m; j++) - { - s = 0.0; - for(k=l; k<=n; k++) - { - s = s+a->ptr.pp_double[j][k]*a->ptr.pp_double[i][k]; - } - for(k=l; k<=n; k++) - { - a->ptr.pp_double[j][k] = a->ptr.pp_double[j][k]+s*rv1.ptr.p_double[k]; - } - } - } - for(k=l; k<=n; k++) - { - a->ptr.pp_double[i][k] = vscale*a->ptr.pp_double[i][k]; - } - } - } - anorm = testmatgenunit_mymax(anorm, ae_fabs(w->ptr.p_double[i], _state)+ae_fabs(rv1.ptr.p_double[i], _state), _state); - } - for(i=n; i>=1; i--) - { - if( iptr.pp_double[j][i] = a->ptr.pp_double[i][j]/a->ptr.pp_double[i][l]/g; - } - for(j=l; j<=n; j++) - { - s = 0.0; - for(k=l; k<=n; k++) - { - s = s+a->ptr.pp_double[i][k]*v->ptr.pp_double[k][j]; - } - for(k=l; k<=n; k++) - { - v->ptr.pp_double[k][j] = v->ptr.pp_double[k][j]+s*v->ptr.pp_double[k][i]; - } - } - } - for(j=l; j<=n; j++) - { - v->ptr.pp_double[i][j] = 0.0; - v->ptr.pp_double[j][i] = 0.0; - } - } - v->ptr.pp_double[i][i] = 1.0; - g = rv1.ptr.p_double[i]; - l = i; - } - for(i=minmn; i>=1; i--) - { - l = i+1; - g = w->ptr.p_double[i]; - if( iptr.pp_double[i][j] = 0.0; - } - } - if( ae_fp_neq(g,0.0) ) - { - g = 1.0/g; - if( i!=n ) - { - for(j=l; j<=n; j++) - { - s = 0.0; - for(k=l; k<=m; k++) - { - s = s+a->ptr.pp_double[k][i]*a->ptr.pp_double[k][j]; - } - f = s/a->ptr.pp_double[i][i]*g; - for(k=i; k<=m; k++) - { - a->ptr.pp_double[k][j] = a->ptr.pp_double[k][j]+f*a->ptr.pp_double[k][i]; - } - } - } - for(j=i; j<=m; j++) - { - a->ptr.pp_double[j][i] = a->ptr.pp_double[j][i]*g; - } - } - else - { - for(j=i; j<=m; j++) - { - a->ptr.pp_double[j][i] = 0.0; - } - } - a->ptr.pp_double[i][i] = a->ptr.pp_double[i][i]+1.0; - } - nm = 0; - for(k=n; k>=1; k--) - { - for(its=1; its<=testmatgenunit_maxsvditerations; its++) - { - flag = ae_true; - for(l=k; l>=1; l--) - { - nm = l-1; - if( ae_fp_eq(ae_fabs(rv1.ptr.p_double[l], _state)+anorm,anorm) ) - { - flag = ae_false; - break; - } - if( ae_fp_eq(ae_fabs(w->ptr.p_double[nm], _state)+anorm,anorm) ) - { - break; - } - } - if( flag ) - { - c = 0.0; - s = 1.0; - for(i=l; i<=k; i++) - { - f = s*rv1.ptr.p_double[i]; - if( ae_fp_neq(ae_fabs(f, _state)+anorm,anorm) ) - { - g = w->ptr.p_double[i]; - h = testmatgenunit_pythag(f, g, _state); - w->ptr.p_double[i] = h; - h = 1.0/h; - c = g*h; - s = -f*h; - for(j=1; j<=m; j++) - { - y = a->ptr.pp_double[j][nm]; - z = a->ptr.pp_double[j][i]; - a->ptr.pp_double[j][nm] = y*c+z*s; - a->ptr.pp_double[j][i] = -y*s+z*c; - } - } - } - } - z = w->ptr.p_double[k]; - if( l==k ) - { - if( ae_fp_less(z,0.0) ) - { - w->ptr.p_double[k] = -z; - for(j=1; j<=n; j++) - { - v->ptr.pp_double[j][k] = -v->ptr.pp_double[j][k]; - } - } - break; - } - if( its==testmatgenunit_maxsvditerations ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - x = w->ptr.p_double[l]; - nm = k-1; - y = w->ptr.p_double[nm]; - g = rv1.ptr.p_double[nm]; - h = rv1.ptr.p_double[k]; - f = ((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y); - g = testmatgenunit_pythag(f, (double)(1), _state); - f = ((x-z)*(x+z)+h*(y/(f+testmatgenunit_extsign(g, f, _state))-h))/x; - c = 1.0; - s = 1.0; - for(j=l; j<=nm; j++) - { - i = j+1; - g = rv1.ptr.p_double[i]; - y = w->ptr.p_double[i]; - h = s*g; - g = c*g; - z = testmatgenunit_pythag(f, h, _state); - rv1.ptr.p_double[j] = z; - c = f/z; - s = h/z; - f = x*c+g*s; - g = -x*s+g*c; - h = y*s; - y = y*c; - for(jj=1; jj<=n; jj++) - { - x = v->ptr.pp_double[jj][j]; - z = v->ptr.pp_double[jj][i]; - v->ptr.pp_double[jj][j] = x*c+z*s; - v->ptr.pp_double[jj][i] = -x*s+z*c; - } - z = testmatgenunit_pythag(f, h, _state); - w->ptr.p_double[j] = z; - if( ae_fp_neq(z,0.0) ) - { - z = 1.0/z; - c = f*z; - s = h*z; - } - f = c*g+s*y; - x = -s*g+c*y; - for(jj=1; jj<=m; jj++) - { - y = a->ptr.pp_double[jj][j]; - z = a->ptr.pp_double[jj][i]; - a->ptr.pp_double[jj][j] = y*c+z*s; - a->ptr.pp_double[jj][i] = -y*s+z*c; - } - } - rv1.ptr.p_double[l] = 0.0; - rv1.ptr.p_double[k] = f; - w->ptr.p_double[k] = x; - } - } - ae_frame_leave(_state); - return result; -} - - -static double testmatgenunit_extsign(double a, double b, ae_state *_state) -{ - double result; - - - if( ae_fp_greater_eq(b,(double)(0)) ) - { - result = ae_fabs(a, _state); - } - else - { - result = -ae_fabs(a, _state); - } - return result; -} - - -static double testmatgenunit_mymax(double a, double b, ae_state *_state) -{ - double result; - - - if( ae_fp_greater(a,b) ) - { - result = a; - } - else - { - result = b; - } - return result; -} - - -static double testmatgenunit_pythag(double a, double b, ae_state *_state) -{ - double result; - - - if( ae_fp_less(ae_fabs(a, _state),ae_fabs(b, _state)) ) - { - result = ae_fabs(b, _state)*ae_sqrt(1+ae_sqr(a/b, _state), _state); - } - else - { - result = ae_fabs(a, _state)*ae_sqrt(1+ae_sqr(b/a, _state), _state); - } - return result; -} - - - -static void testtrfacunit_testcluproblem(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double threshold, - ae_bool* err, - ae_bool* properr, - ae_state *_state); -static void testtrfacunit_testrluproblem(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double threshold, - ae_bool* err, - ae_bool* properr, - ae_state *_state); -static void testtrfacunit_testdensecholeskyupdates(ae_bool* spdupderrorflag, - ae_state *_state); - - - - - -ae_bool testtrfac(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix ra; - ae_matrix ral; - ae_matrix rau; - ae_matrix ca; - ae_matrix cal; - ae_matrix cau; - ae_int_t m; - ae_int_t n; - ae_int_t mx; - ae_int_t maxmn; - ae_int_t largemn; - ae_int_t i; - ae_int_t j; - ae_complex vc; - double vr; - ae_bool waserrors; - ae_bool dspderr; - ae_bool sspderr; - ae_bool srerr; - ae_bool hpderr; - ae_bool rerr; - ae_bool cerr; - ae_bool properr; - ae_bool dspdupderr; - double threshold; - ae_int_t pass; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&ra, 0, sizeof(ra)); - memset(&ral, 0, sizeof(ral)); - memset(&rau, 0, sizeof(rau)); - memset(&ca, 0, sizeof(ca)); - memset(&cal, 0, sizeof(cal)); - memset(&cau, 0, sizeof(cau)); - ae_matrix_init(&ra, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ral, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&rau, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ca, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&cal, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&cau, 0, 0, DT_COMPLEX, _state, ae_true); - - rerr = ae_false; - dspderr = ae_false; - sspderr = ae_false; - cerr = ae_false; - hpderr = ae_false; - properr = ae_false; - dspdupderr = ae_false; - srerr = ae_false; - waserrors = ae_false; - maxmn = 4*matrixtilesizea(_state)+1; - largemn = 256; - threshold = 1000*ae_machineepsilon*maxmn; - - /* - * Sparse Cholesky - */ - sspderr = sparserealcholeskytest(_state); - - /* - * Sparse LU - */ - sparsereallutest(&srerr, _state); - - /* - * Cholesky updates - */ - testtrfacunit_testdensecholeskyupdates(&dspdupderr, _state); - - /* - * test LU: - * * first, test on small-scale matrices - * * then, perform several large-scale tests - */ - for(mx=1; mx<=maxmn; mx++) - { - - /* - * Initialize N/M, both are <=MX, - * at least one of them is exactly equal to MX - */ - n = 1+ae_randominteger(mx, _state); - m = 1+ae_randominteger(mx, _state); - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - n = mx; - } - else - { - m = mx; - } - - /* - * First, test on zero matrix - */ - ae_matrix_set_length(&ra, m, n, _state); - ae_matrix_set_length(&ca, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - ra.ptr.pp_double[i][j] = (double)(0); - ca.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - testtrfacunit_testcluproblem(&ca, m, n, threshold, &cerr, &properr, _state); - testtrfacunit_testrluproblem(&ra, m, n, threshold, &rerr, &properr, _state); - - /* - * Second, random matrix with moderate condition number - */ - ae_matrix_set_length(&ra, m, n, _state); - ae_matrix_set_length(&ca, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - ra.ptr.pp_double[i][j] = (double)(0); - ca.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - for(i=0; i<=ae_minint(m, n, _state)-1; i++) - { - ra.ptr.pp_double[i][i] = 1+10*ae_randomreal(_state); - ca.ptr.pp_complex[i][i] = ae_complex_from_d(1+10*ae_randomreal(_state)); - } - cmatrixrndorthogonalfromtheleft(&ca, m, n, _state); - cmatrixrndorthogonalfromtheright(&ca, m, n, _state); - rmatrixrndorthogonalfromtheleft(&ra, m, n, _state); - rmatrixrndorthogonalfromtheright(&ra, m, n, _state); - testtrfacunit_testcluproblem(&ca, m, n, threshold, &cerr, &properr, _state); - testtrfacunit_testrluproblem(&ra, m, n, threshold, &rerr, &properr, _state); - } - for(pass=1; pass<=2; pass++) - { - m = largemn+(ae_randominteger(3, _state)-1); - n = largemn+(ae_randominteger(3, _state)-1); - - /* - * Random matrix with moderate condition number - */ - ae_matrix_set_length(&ra, m, n, _state); - ae_matrix_set_length(&ca, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - ra.ptr.pp_double[i][j] = (double)(0); - ca.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - for(i=0; i<=ae_minint(m, n, _state)-1; i++) - { - ra.ptr.pp_double[i][i] = 1+10*ae_randomreal(_state); - ca.ptr.pp_complex[i][i] = ae_complex_from_d(1+10*ae_randomreal(_state)); - } - cmatrixrndorthogonalfromtheleft(&ca, m, n, _state); - cmatrixrndorthogonalfromtheright(&ca, m, n, _state); - rmatrixrndorthogonalfromtheleft(&ra, m, n, _state); - rmatrixrndorthogonalfromtheright(&ra, m, n, _state); - testtrfacunit_testcluproblem(&ca, m, n, threshold, &cerr, &properr, _state); - testtrfacunit_testrluproblem(&ra, m, n, threshold, &rerr, &properr, _state); - } - - /* - * Test Cholesky - */ - for(n=1; n<=maxmn; n++) - { - - /* - * Load CA (HPD matrix with low condition number), - * CAL and CAU - its lower and upper triangles - */ - hpdmatrixrndcond(n, 1+50*ae_randomreal(_state), &ca, _state); - ae_matrix_set_length(&cal, n, n, _state); - ae_matrix_set_length(&cau, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - cal.ptr.pp_complex[i][j] = ae_complex_from_i(i); - cau.ptr.pp_complex[i][j] = ae_complex_from_i(j); - } - } - for(i=0; i<=n-1; i++) - { - ae_v_cmove(&cal.ptr.pp_complex[i][0], 1, &ca.ptr.pp_complex[i][0], 1, "N", ae_v_len(0,i)); - ae_v_cmove(&cau.ptr.pp_complex[i][i], 1, &ca.ptr.pp_complex[i][i], 1, "N", ae_v_len(i,n-1)); - } - - /* - * Test HPDMatrixCholesky: - * 1. it must leave upper (lower) part unchanged - * 2. max(A-L*L^H) must be small - */ - if( hpdmatrixcholesky(&cal, n, ae_false, _state) ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( j>i ) - { - hpderr = hpderr||ae_c_neq_d(cal.ptr.pp_complex[i][j],(double)(i)); - } - else - { - vc = ae_v_cdotproduct(&cal.ptr.pp_complex[i][0], 1, "N", &cal.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,j)); - hpderr = hpderr||ae_fp_greater(ae_c_abs(ae_c_sub(ca.ptr.pp_complex[i][j],vc), _state),threshold); - } - } - } - } - else - { - hpderr = ae_true; - } - if( hpdmatrixcholesky(&cau, n, ae_true, _state) ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ji ) - { - dspderr = dspderr||ae_fp_neq(ral.ptr.pp_double[i][j],(double)(i)); - } - else - { - vr = ae_v_dotproduct(&ral.ptr.pp_double[i][0], 1, &ral.ptr.pp_double[j][0], 1, ae_v_len(0,j)); - dspderr = dspderr||ae_fp_greater(ae_fabs(ra.ptr.pp_double[i][j]-vr, _state),threshold); - } - } - } - } - else - { - dspderr = ae_true; - } - if( spdmatrixcholesky(&rau, n, ae_true, _state) ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( j1 ) - { - pnz = (double)nz/(double)(n*n-n); - } - else - { - pnz = 1.0; - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i; j++) - { - if( i==j ) - { - a.ptr.pp_double[i][i] = 1+hqrnduniformr(&rs, _state); - continue; - } - if( ae_fp_less_eq(hqrnduniformr(&rs, _state),pnz) ) - { - a.ptr.pp_double[i][j] = 0.5/n*(hqrnduniformr(&rs, _state)-0.5); - a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j]; - } - else - { - a.ptr.pp_double[i][j] = 0.0; - a.ptr.pp_double[j][i] = 0.0; - } - } - } - - /* - * Create matrix in hash-based storage format, convert it to random storage format. - */ - isupper = ae_fp_greater(ae_randomreal(_state),0.5); - sparsecreate(n, n, 0, &sa, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (j<=i&&!isupper)||(j>=i&&isupper) ) - { - sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state); - } - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (ji&&!isupper) ) - { - if( ae_fp_less_eq(hqrnduniformr(&rs, _state),pnz) ) - { - sparseset(&sa, i, j, hqrndnormal(&rs, _state), _state); - } - } - } - } - sparseconvertto(&sa, hqrnduniformi(&rs, maxfmt+1, _state), _state); - - /* - * Try various factorization routines: - * * SparseCholesky() without permutation - * * SparseCholeskyP() - * * Analyze/Factorize family of functions - */ - for(routinetype=0; routinetype<=2; routinetype++) - { - - /* - * The factorization - */ - sparsecopy(&sa, &sc, _state); - if( routinetype==0 ) - { - - /* - * Positive-definite Cholesky without permutation - */ - if( !sparsecholesky(&sc, isupper, _state) ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:695"); - ae_frame_leave(_state); - return result; - } - ae_vector_set_length(&p0, n, _state); - ae_vector_set_length(&d, n, _state); - for(i=0; i<=n-1; i++) - { - p0.ptr.p_int[i] = i; - d.ptr.p_double[i] = 1.0; - } - } - if( routinetype==1 ) - { - - /* - * Positive-definite Cholesky with permutation - */ - if( !sparsecholeskyp(&sc, isupper, &p0, _state) ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:713"); - ae_frame_leave(_state); - return result; - } - ae_vector_set_length(&d, n, _state); - for(i=0; i<=n-1; i++) - { - d.ptr.p_double[i] = 1.0; - } - } - if( routinetype==2 ) - { - - /* - * Positive-definite analyze/factorize with randomly chosen permutation. - * We also check that we may analyze one matrix and factorize another one - * with same sparsity pattern. - */ - sparsecopybuf(&sc, &sp, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( sparseexists(&sp, i, j, _state) ) - { - sparserewriteexisting(&sp, i, j, 1.0, _state); - } - } - } - permtype = minperm+hqrnduniformi(&rs, maxperm-minperm+1, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - - /* - * Test analyze/factorize sequence - */ - if( !sparsecholeskyanalyze(&sc, isupper, 0, permtype, &analysis, _state) ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:740"); - ae_frame_leave(_state); - return result; - } - sparsecreate(1, 1, 0, &sc, _state); - if( !sparsecholeskyfactorize(&analysis, isupper, &sc, &d, &p0, _state) ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:746"); - ae_frame_leave(_state); - return result; - } - } - else - { - - /* - * Test analyze/reload/factorize sequence - */ - if( !sparsecholeskyanalyze(&sp, isupper, 0, permtype, &analysis, _state) ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:757"); - ae_frame_leave(_state); - return result; - } - sparsecholeskyreload(&analysis, &sc, isupper, _state); - sparsecreate(1, 1, 0, &sc, _state); - if( !sparsecholeskyfactorize(&analysis, isupper, &sc, &d, &p0, _state) ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:764"); - ae_frame_leave(_state); - return result; - } - } - if( d.cnt!=n ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:770"); - ae_frame_leave(_state); - return result; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(&result, ae_fp_neq(d.ptr.p_double[i],1.0), __FILE__, __LINE__, "testtrfacunit.ap:774"); - } - } - - /* - * Check output sizes and formats - */ - ae_set_error_flag(&result, (!sparseiscrs(&sc, _state)||sparsegetnrows(&sc, _state)!=n)||sparsegetncols(&sc, _state)!=n, __FILE__, __LINE__, "testtrfacunit.ap:780"); - ae_set_error_flag(&result, p0.cnt!=n, __FILE__, __LINE__, "testtrfacunit.ap:781"); - ae_set_error_flag(&result, d.cnt!=n, __FILE__, __LINE__, "testtrfacunit.ap:782"); - if( result ) - { - ae_frame_leave(_state); - return result; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(&result, p0.ptr.p_int[i]=n, __FILE__, __LINE__, "testtrfacunit.ap:787"); - ae_set_error_flag(&result, !ae_isfinite(d.ptr.p_double[i], _state), __FILE__, __LINE__, "testtrfacunit.ap:788"); - } - if( result ) - { - ae_frame_leave(_state); - return result; - } - t0 = 0; - t1 = 0; - while(sparseenumerate(&sc, &t0, &t1, &i, &j, &v, _state)) - { - ae_set_error_flag(&result, ji&&!isupper, __FILE__, __LINE__, "testtrfacunit.ap:797"); - } - if( result ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Now, test correctness of Cholesky decomposition itself. - * We calculate U'*U (or L*L') and check it against permutation - * of A given by P0. - * - * NOTE: we expect that only one triangle of SC is filled, - * and another one is exactly zero. - */ - ae_matrix_set_length(&a1, n, n, _state); - if( isupper ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = 0.0; - for(k=0; k<=n-1; k++) - { - v = v+sparseget(&sc, k, j, _state)*d.ptr.p_double[k]*sparseget(&sc, k, i, _state); - } - a1.ptr.pp_double[i][j] = v; - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = 0.0; - for(k=0; k<=n-1; k++) - { - v = v+sparseget(&sc, j, k, _state)*d.ptr.p_double[k]*sparseget(&sc, i, k, _state); - } - a1.ptr.pp_double[i][j] = v; - } - } - } - for(i=n-1; i>=0; i--) - { - swaprows(&a1, i, p0.ptr.p_int[i], n, _state); - swapcols(&a1, i, p0.ptr.p_int[i], n, _state); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-a1.ptr.pp_double[i][j], _state),tol), __FILE__, __LINE__, "testtrfacunit.ap:840"); - } - } - } - - /* - * Check handling of degenerate problems: zeros at main diagonal, negative definite matrices - */ - for(routinetype=0; routinetype<=1; routinetype++) - { - - /* - * Exact zero at diagonal - */ - sparsecopy(&sa, &sc, _state); - sparseconverttohash(&sc, _state); - k = hqrnduniformi(&rs, n, _state); - sparseset(&sc, k, k, (double)(0), _state); - sparseconvertto(&sc, hqrnduniformi(&rs, maxfmt+1, _state), _state); - if( routinetype==0 ) - { - ae_set_error_flag(&result, sparsecholesky(&sc, isupper, _state), __FILE__, __LINE__, "testtrfacunit.ap:857"); - } - if( routinetype==1 ) - { - ae_set_error_flag(&result, sparsecholeskyp(&sc, isupper, &p0, _state), __FILE__, __LINE__, "testtrfacunit.ap:859"); - } - - /* - * Negative definite matrix - */ - sparsecopy(&sa, &sc, _state); - sparseconverttohash(&sc, _state); - k = hqrnduniformi(&rs, n, _state); - sparseset(&sc, k, k, -1.0E10, _state); - sparseconvertto(&sc, hqrnduniformi(&rs, maxfmt+1, _state), _state); - if( routinetype==0 ) - { - ae_set_error_flag(&result, sparsecholesky(&sc, isupper, _state), __FILE__, __LINE__, "testtrfacunit.ap:870"); - } - if( routinetype==1 ) - { - ae_set_error_flag(&result, sparsecholeskyp(&sc, isupper, &p0, _state), __FILE__, __LINE__, "testtrfacunit.ap:872"); - } - } - - /* - * Increase problem sparcity and try one more time. - * Stop after testing NZ=0. - */ - if( nz==0 ) - { - break; - } - nz = nz/2; - } - } - - /* - * Negative definite LDLT factorization: performed for matrices with various sparsity factors - */ - for(n=1; n<=30; n++) - { - nz = n*n-n; - for(;;) - { - - /* - * Generate symmetric N*N matrix where probability of non-diagonal element - * being non-zero is PNZ. Off-diagonal elements are set to very - * small values, so positive definiteness is guaranteed. - */ - if( n>1 ) - { - pnz = (double)nz/(double)(n*n-n); - } - else - { - pnz = 1.0; - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i; j++) - { - if( i==j ) - { - a.ptr.pp_double[i][i] = possign(hqrndnormal(&rs, _state), _state)*(1+hqrnduniformr(&rs, _state)); - continue; - } - if( ae_fp_less_eq(hqrnduniformr(&rs, _state),pnz) ) - { - a.ptr.pp_double[i][j] = 0.5/n*(hqrnduniformr(&rs, _state)-0.5); - a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j]; - } - else - { - a.ptr.pp_double[i][j] = 0.0; - a.ptr.pp_double[j][i] = 0.0; - } - } - } - - /* - * Create matrix in hash-based storage format, convert it to random storage format. - */ - isupper = ae_fp_greater(ae_randomreal(_state),0.5); - sparsecreate(n, n, 0, &sa, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (j<=i&&!isupper)||(j>=i&&isupper) ) - { - sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state); - } - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (ji&&!isupper) ) - { - if( ae_fp_less_eq(hqrnduniformr(&rs, _state),pnz) ) - { - sparseset(&sa, i, j, hqrndnormal(&rs, _state), _state); - } - } - } - } - sparseconvertto(&sa, hqrnduniformi(&rs, maxfmt+1, _state), _state); - - /* - * Try Analyze/Factorize family of functions - */ - sparsecopy(&sa, &sc, _state); - sparsecopybuf(&sc, &sp, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( sparseexists(&sp, i, j, _state) ) - { - sparserewriteexisting(&sp, i, j, 1.0, _state); - } - } - } - facttype = 1; - permtype = minperm+hqrnduniformi(&rs, maxperm-minperm+1, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - - /* - * Test analyze/factorize sequence - */ - if( !sparsecholeskyanalyze(&sc, isupper, facttype, permtype, &analysis, _state) ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:957"); - ae_frame_leave(_state); - return result; - } - sparsecreate(1, 1, 0, &sc, _state); - if( !sparsecholeskyfactorize(&analysis, isupper, &sc, &d, &p0, _state) ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:963"); - ae_frame_leave(_state); - return result; - } - } - else - { - - /* - * Test analyze/reload/factorize sequence - */ - if( !sparsecholeskyanalyze(&sp, isupper, facttype, permtype, &analysis, _state) ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:974"); - ae_frame_leave(_state); - return result; - } - sparsecholeskyreload(&analysis, &sc, isupper, _state); - sparsecreate(1, 1, 0, &sc, _state); - if( !sparsecholeskyfactorize(&analysis, isupper, &sc, &d, &p0, _state) ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:981"); - ae_frame_leave(_state); - return result; - } - } - - /* - * Check output sizes and formats - */ - ae_set_error_flag(&result, (!sparseiscrs(&sc, _state)||sparsegetnrows(&sc, _state)!=n)||sparsegetncols(&sc, _state)!=n, __FILE__, __LINE__, "testtrfacunit.ap:989"); - ae_set_error_flag(&result, p0.cnt!=n, __FILE__, __LINE__, "testtrfacunit.ap:990"); - ae_set_error_flag(&result, d.cnt!=n, __FILE__, __LINE__, "testtrfacunit.ap:991"); - if( result ) - { - ae_frame_leave(_state); - return result; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(&result, p0.ptr.p_int[i]=n, __FILE__, __LINE__, "testtrfacunit.ap:996"); - ae_set_error_flag(&result, !ae_isfinite(d.ptr.p_double[i], _state), __FILE__, __LINE__, "testtrfacunit.ap:997"); - } - if( result ) - { - ae_frame_leave(_state); - return result; - } - t0 = 0; - t1 = 0; - while(sparseenumerate(&sc, &t0, &t1, &i, &j, &v, _state)) - { - ae_set_error_flag(&result, ji&&!isupper, __FILE__, __LINE__, "testtrfacunit.ap:1006"); - } - if( result ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Now, test correctness of Cholesky decomposition itself. - * We calculate U'*U (or L*L') and check it against permutation - * of A given by P0. - * - * NOTE: we expect that only one triangle of SC is filled, - * and another one is exactly zero. - */ - ae_matrix_set_length(&a1, n, n, _state); - if( isupper ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = 0.0; - for(k=0; k<=n-1; k++) - { - v = v+sparseget(&sc, k, j, _state)*d.ptr.p_double[k]*sparseget(&sc, k, i, _state); - } - a1.ptr.pp_double[i][j] = v; - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = 0.0; - for(k=0; k<=n-1; k++) - { - v = v+sparseget(&sc, j, k, _state)*d.ptr.p_double[k]*sparseget(&sc, i, k, _state); - } - a1.ptr.pp_double[i][j] = v; - } - } - } - for(i=n-1; i>=0; i--) - { - swaprows(&a1, i, p0.ptr.p_int[i], n, _state); - swapcols(&a1, i, p0.ptr.p_int[i], n, _state); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-a1.ptr.pp_double[i][j], _state),tol), __FILE__, __LINE__, "testtrfacunit.ap:1049"); - } - } - - /* - * Increase problem sparcity and try one more time. - * Stop after testing NZ=0. - */ - if( nz==0 ) - { - break; - } - nz = nz/2; - } - } - - /* - * Basis test of modified Cholesky. - * - * We do not perform deep tests here, basically the fact that with diagonal modification - * we can complete factorization that can't be completed without modification. - */ - for(n=1; n<=30; n++) - { - nz = n*n-n; - for(;;) - { - - /* - * Generate symmetric N*N matrix where probability of non-diagonal element - * being non-zero is PNZ. One of diagonal elements is guaranteed to be - * negative in order to test modification strategy. - */ - if( n>1 ) - { - pnz = (double)nz/(double)(n*n-n); - } - else - { - pnz = 1.0; - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i; j++) - { - if( i==j ) - { - a.ptr.pp_double[i][i] = hqrndnormal(&rs, _state); - continue; - } - if( ae_fp_less_eq(hqrnduniformr(&rs, _state),pnz) ) - { - a.ptr.pp_double[i][j] = 0.5/n*(hqrnduniformr(&rs, _state)-0.5); - a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j]; - } - else - { - a.ptr.pp_double[i][j] = 0.0; - a.ptr.pp_double[j][i] = 0.0; - } - } - } - i = hqrnduniformi(&rs, n, _state); - a.ptr.pp_double[i][i] = (double)(-1); - sparsecreate(n, n, 0, &sa, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (j<=i&&!isupper)||(j>=i&&isupper) ) - { - sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state); - } - } - } - - /* - * Try Analyze/Factorize family of functions - */ - facttype = 0; - permtype = minperm+hqrnduniformi(&rs, maxperm-minperm+1, _state); - sparsecopy(&sa, &sc, _state); - if( !sparsecholeskyanalyze(&sc, isupper, facttype, permtype, &analysis, _state) ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:1117"); - ae_frame_leave(_state); - return result; - } - if( sparsecholeskyfactorize(&analysis, isupper, &sc, &d, &p0, _state) ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:1122"); - ae_frame_leave(_state); - return result; - } - sparsecopy(&sa, &sc, _state); - sparsecholeskysetmodtype(&analysis, 1, 1.0, (double)(0), (double)(0), (double)(0), _state); - sparsecholeskyreload(&analysis, &sc, isupper, _state); - if( !sparsecholeskyfactorize(&analysis, isupper, &sc, &d, &p0, _state) ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:1130"); - ae_frame_leave(_state); - return result; - } - - /* - * Increase problem sparcity and try one more time. - * Stop after testing NZ=0. - */ - if( nz==0 ) - { - break; - } - nz = nz/2; - } - } - - /* - * Specially designed matrix that allows us to test all internal supernodal update kernels, - * with all update ranks, update widths, target widths - */ - updaterank = 1; - updatewidth = 3; - targetwidth = updatewidth; - for(updaterank=1; updaterank<=spsymmgetmaxfastkernel(_state); updaterank++) - { - for(updatewidth=1; updatewidth<=spsymmgetmaxfastkernel(_state); updatewidth++) - { - for(targetwidth=updatewidth; targetwidth<=spsymmgetmaxfastkernel(_state); targetwidth++) - { - - /* - * Generate test matrix A: - * - * [ U ] - * [ UU ] - * [ UUU ] - * [ UUUT ] - * [ UUUTT ] - * [ UUUTTT ] - * [ TTTT ] - * [ TTTTR ] - * [ TTTTRR ] - * [ TTTTRRR ] - * [ TTTTRRRR ] - * [ TTTTRRRRR ] - * [ RRRRRR ] - * [ RRRRRRR ] - * [ RRRRRRRR ] - * [ RRRRRRRRR ] - * [ UUUTTTTRRRRRRRRRR ] - * [ UUUTTTTRRRRRRRRRRR ] - * - * where U is update matrix, T is target matrix, heights of U and T are chosen in - * such a way that supernode T will NOT be merged with supernode U, their sizes - * are chosen to investigate all possible kinds of update kernels. The residual - * R is also chosen in such a way that it is NOT merged with T. - */ - bigsize = 10; - bottomsize = 2+hqrnduniformi(&rs, 10, _state); - n = updaterank+targetwidth+2*bigsize+bottomsize; - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - a.ptr.pp_double[i][j] = 1+hqrnduniformr(&rs, _state); - } - else - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - } - for(j=0; j<=updaterank-1; j++) - { - for(i=j+1; i<=updaterank+updatewidth-1; i++) - { - a.ptr.pp_double[i][j] = 0.5/n*(hqrnduniformr(&rs, _state)-0.5); - } - for(i=n-bottomsize; i<=n-1; i++) - { - a.ptr.pp_double[i][j] = 0.5/n*(hqrnduniformr(&rs, _state)-0.5); - } - } - for(j=updaterank; j<=updaterank+targetwidth-1; j++) - { - for(i=j+1; i<=updaterank+targetwidth+bigsize-1; i++) - { - a.ptr.pp_double[i][j] = 0.5/n*(hqrnduniformr(&rs, _state)-0.5); - } - for(i=n-bottomsize; i<=n-1; i++) - { - a.ptr.pp_double[i][j] = 0.5/n*(hqrnduniformr(&rs, _state)-0.5); - } - } - for(j=updaterank+targetwidth; j<=n-1; j++) - { - for(i=j+1; i<=n-1; i++) - { - a.ptr.pp_double[i][j] = 0.5/n*(hqrnduniformr(&rs, _state)-0.5); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i-1; j++) - { - a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j]; - } - } - - /* - * Create matrix in hash-based storage format - */ - isupper = ae_false; - sparsecreate(n, n, 0, &sa, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state); - } - } - - /* - * Try analysis with random permutation and factorization - */ - facttype = hqrnduniformi(&rs, 2, _state); - permtype = minperm+hqrnduniformi(&rs, maxperm-minperm+1, _state); - if( !sparsecholeskyanalyze(&sa, isupper, facttype, permtype, &analysis, _state) ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:1230"); - ae_frame_leave(_state); - return result; - } - if( !sparsecholeskyfactorize(&analysis, isupper, &sc, &d, &p0, _state) ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:1235"); - ae_frame_leave(_state); - return result; - } - - /* - * Check output sizes and formats - */ - ae_set_error_flag(&result, (!sparseiscrs(&sc, _state)||sparsegetnrows(&sc, _state)!=n)||sparsegetncols(&sc, _state)!=n, __FILE__, __LINE__, "testtrfacunit.ap:1243"); - ae_set_error_flag(&result, p0.cnt!=n, __FILE__, __LINE__, "testtrfacunit.ap:1244"); - ae_set_error_flag(&result, d.cnt!=n, __FILE__, __LINE__, "testtrfacunit.ap:1245"); - if( result ) - { - ae_frame_leave(_state); - return result; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(&result, p0.ptr.p_int[i]=n, __FILE__, __LINE__, "testtrfacunit.ap:1250"); - ae_set_error_flag(&result, !ae_isfinite(d.ptr.p_double[i], _state), __FILE__, __LINE__, "testtrfacunit.ap:1251"); - } - if( result ) - { - ae_frame_leave(_state); - return result; - } - t0 = 0; - t1 = 0; - while(sparseenumerate(&sc, &t0, &t1, &i, &j, &v, _state)) - { - ae_set_error_flag(&result, ji&&!isupper, __FILE__, __LINE__, "testtrfacunit.ap:1260"); - } - if( result ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Now, test correctness of Cholesky decomposition itself. - * We calculate U'*U (or L*L') and check it against permutation - * of A given by P0. - * - * NOTE: we expect that only one triangle of SC is filled, - * and another one is exactly zero. - */ - ae_matrix_set_length(&a1, n, n, _state); - if( isupper ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = 0.0; - for(k=0; k<=n-1; k++) - { - v = v+sparseget(&sc, k, j, _state)*d.ptr.p_double[k]*sparseget(&sc, k, i, _state); - } - a1.ptr.pp_double[i][j] = v; - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = 0.0; - for(k=0; k<=n-1; k++) - { - v = v+sparseget(&sc, j, k, _state)*d.ptr.p_double[k]*sparseget(&sc, i, k, _state); - } - a1.ptr.pp_double[i][j] = v; - } - } - } - for(i=n-1; i>=0; i--) - { - swaprows(&a1, i, p0.ptr.p_int[i], n, _state); - swapcols(&a1, i, p0.ptr.p_int[i], n, _state); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-a1.ptr.pp_double[i][j], _state),tol), __FILE__, __LINE__, "testtrfacunit.ap:1303"); - } - } - } - } - } - - /* - * SparseCholeskySkyline test: performed for matrices - * of all sizes in 1..20 and all sparcity percentages. - */ - for(n=1; n<=20; n++) - { - nz = n*n-n; - for(;;) - { - - /* - * Choose IsUpper - main triangle to work with. - * - * Generate A - symmetric N*N matrix where probability of non-diagonal - * element being non-zero is PNZ. Off-diagonal elements are set to - * very small values, so positive definiteness is guaranteed. Full matrix - * is generated. - * - * Additionally, we create A1 - same as A, but one of the triangles is - * asymmetrically spoiled. If IsUpper is True, we spoil lower one, or vice versa. - */ - isupper = ae_fp_greater(ae_randomreal(_state),0.5); - if( n>1 ) - { - pnz = (double)nz/(double)(n*n-n); - } - else - { - pnz = 1.0; - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i; j++) - { - if( i==j ) - { - a.ptr.pp_double[i][i] = 1+hqrnduniformr(&rs, _state); - continue; - } - if( ae_fp_less_eq(hqrnduniformr(&rs, _state),pnz) ) - { - a.ptr.pp_double[i][j] = offscale*(hqrnduniformr(&rs, _state)-0.5); - a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j]; - } - else - { - a.ptr.pp_double[i][j] = 0.0; - a.ptr.pp_double[j][i] = 0.0; - } - } - } - ae_matrix_set_length(&a1, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (j<=i&&!isupper)||(j>=i&&isupper) ) - { - - /* - * Copy one triangle - */ - a1.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]; - } - else - { - - /* - * Form another sparse pattern in different triangle. - */ - if( ae_fp_less_eq(hqrnduniformr(&rs, _state),pnz) ) - { - a1.ptr.pp_double[i][j] = offscale*(hqrnduniformr(&rs, _state)-0.5); - } - else - { - a1.ptr.pp_double[i][j] = 0.0; - } - } - } - } - - /* - * Create copies of A and A1 in hash-based storage format. - * Only one triangle of A is copied, but A1 is copied fully. - * Convert them to SKS - */ - sparsecreate(n, n, 0, &sa, _state); - sparsecreate(n, n, 0, &sa1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (j<=i&&!isupper)||(j>=i&&isupper) ) - { - sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state); - } - sparseset(&sa1, i, j, a1.ptr.pp_double[i][j], _state); - } - } - sparseconverttosks(&sa, _state); - sparseconverttosks(&sa1, _state); - - /* - * Call SparseCholeskySkyline() for SA and make several tests: - * * check that it is still SKS - * * check that it has correct size (exactly N*N) - * * check that correct triangle is returned (and another one is unchanged - zero) - * * check that it is correct Cholesky decomposition. - * We calculate U'*U (or L*L') and check at against A. We expect - * that only one triangle of SA is filled, and another one is - * exactly zero. - */ - if( !sparsecholeskyskyline(&sa, n, isupper, _state) ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:1405"); - ae_frame_leave(_state); - return result; - } - ae_set_error_flag(&result, !sparseissks(&sa, _state), __FILE__, __LINE__, "testtrfacunit.ap:1408"); - ae_set_error_flag(&result, sparsegetncols(&sa, _state)!=n, __FILE__, __LINE__, "testtrfacunit.ap:1409"); - ae_set_error_flag(&result, sparsegetnrows(&sa, _state)!=n, __FILE__, __LINE__, "testtrfacunit.ap:1410"); - t0 = 0; - t1 = 0; - while(sparseenumerate(&sa, &t0, &t1, &i, &j, &v, _state)) - { - ae_set_error_flag(&result, ji&&!isupper, __FILE__, __LINE__, "testtrfacunit.ap:1416"); - } - if( isupper ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = 0.0; - for(k=0; k<=n-1; k++) - { - v = v+sparseget(&sa, k, j, _state)*sparseget(&sa, k, i, _state); - } - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-v, _state),tol), __FILE__, __LINE__, "testtrfacunit.ap:1426"); - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = 0.0; - for(k=0; k<=n-1; k++) - { - v = v+sparseget(&sa, j, k, _state)*sparseget(&sa, i, k, _state); - } - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-v, _state),tol), __FILE__, __LINE__, "testtrfacunit.ap:1437"); - } - } - } - - /* - * Call SparseCholeskySkyline() for SA1 and make several tests: - * * check that it is still SKS - * * check that it has correct size (exactly N*N) - * * check that factorized triangle matches contents of SA, - * and another triangle was unchanged (matches contents of A1). - */ - if( !sparsecholeskyskyline(&sa1, n, isupper, _state) ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:1450"); - ae_frame_leave(_state); - return result; - } - ae_set_error_flag(&result, !sparseissks(&sa1, _state), __FILE__, __LINE__, "testtrfacunit.ap:1453"); - ae_set_error_flag(&result, sparsegetncols(&sa1, _state)!=n, __FILE__, __LINE__, "testtrfacunit.ap:1454"); - ae_set_error_flag(&result, sparsegetnrows(&sa1, _state)!=n, __FILE__, __LINE__, "testtrfacunit.ap:1455"); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (j<=i&&!isupper)||(j>=i&&isupper) ) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(sparseget(&sa1, i, j, _state)-sparseget(&sa, i, j, _state), _state),10*ae_machineepsilon), __FILE__, __LINE__, "testtrfacunit.ap:1459"); - } - else - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(sparseget(&sa1, i, j, _state)-a1.ptr.pp_double[i][j], _state),10*ae_machineepsilon), __FILE__, __LINE__, "testtrfacunit.ap:1461"); - } - } - } - - /* - * Increase problem sparcity and try one more time. - * Stop after testing NZ=0. - */ - if( nz==0 ) - { - break; - } - nz = nz/2; - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Function for testing sparse real LU decomposition. -Sets error flag on failure, leave is unchanged on success. - - -- ALGLIB PROJECT -- - Copyright 16.01.1014 by Bochkanov Sergey -*************************************************************************/ -void sparsereallutest(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t nz; - double pnz; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - ae_matrix a; - ae_matrix b1; - ae_matrix b2; - ae_matrix c; - ae_vector pivr; - ae_vector pivc; - sparsematrix sa; - sparsematrix crsa; - ae_bool success; - double tol; - ae_bool haszero; - ae_int_t pivottype; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&b1, 0, sizeof(b1)); - memset(&b2, 0, sizeof(b2)); - memset(&c, 0, sizeof(c)); - memset(&pivr, 0, sizeof(pivr)); - memset(&pivc, 0, sizeof(pivc)); - memset(&sa, 0, sizeof(sa)); - memset(&crsa, 0, sizeof(crsa)); - memset(&rs, 0, sizeof(rs)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&b1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&b2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&pivr, 0, DT_INT, _state, ae_true); - ae_vector_init(&pivc, 0, DT_INT, _state, ae_true); - _sparsematrix_init(&sa, _state, ae_true); - _sparsematrix_init(&crsa, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - tol = 1.0E4*ae_machineepsilon; - - /* - * Test matrix sizes in 1...20 and with all sparsity percentages - */ - for(n=1; n<=20; n++) - { - nz = n*n; - for(;;) - { - - /* - * Generate N*N matrix where probability of element being - * non-zero is PNZ. Create sparse matrix in hash-based storage format. - */ - pnz = (double)nz/(double)(n*n); - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_less_eq(hqrnduniformr(&rs, _state),pnz) ) - { - a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - else - { - a.ptr.pp_double[i][j] = 0.0; - } - } - } - sparsecreate(n, n, 0, &sa, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state); - } - } - - /* - * Test SparseLU() - */ - for(pivottype=0; pivottype<=2; pivottype++) - { - sparsecopytocrs(&sa, &crsa, _state); - ae_vector_set_length(&pivr, 0, _state); - ae_vector_set_length(&pivc, 0, _state); - success = sparselu(&crsa, pivottype, &pivr, &pivc, _state); - ae_set_error_flag(err, !sparseiscrs(&crsa, _state), __FILE__, __LINE__, "testtrfacunit.ap:1539"); - ae_set_error_flag(err, sparsegetncols(&crsa, _state)!=n, __FILE__, __LINE__, "testtrfacunit.ap:1540"); - ae_set_error_flag(err, sparsegetnrows(&crsa, _state)!=n, __FILE__, __LINE__, "testtrfacunit.ap:1541"); - ae_set_error_flag(err, pivr.cnt!=n, __FILE__, __LINE__, "testtrfacunit.ap:1542"); - ae_set_error_flag(err, pivc.cnt!=n, __FILE__, __LINE__, "testtrfacunit.ap:1543"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(err, ((pivr.ptr.p_int[i]<0||pivr.ptr.p_int[i]>=n)||pivc.ptr.p_int[i]<0)||pivc.ptr.p_int[i]>=n, __FILE__, __LINE__, "testtrfacunit.ap:1547"); - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(err, pivottype==1&&pivc.ptr.p_int[i]!=i, __FILE__, __LINE__, "testtrfacunit.ap:1549"); - } - ae_matrix_set_length(&b1, n, n, _state); - ae_matrix_set_length(&b2, n, n, _state); - haszero = ae_false; - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i-1; j++) - { - b1.ptr.pp_double[i][j] = sparseget(&crsa, i, j, _state); - } - b1.ptr.pp_double[i][i] = (double)(1); - for(j=i+1; j<=n-1; j++) - { - b1.ptr.pp_double[i][j] = (double)(0); - } - for(j=0; j<=i-1; j++) - { - b2.ptr.pp_double[i][j] = (double)(0); - } - for(j=i; j<=n-1; j++) - { - b2.ptr.pp_double[i][j] = sparseget(&crsa, i, j, _state); - } - haszero = haszero||ae_fp_eq(b2.ptr.pp_double[i][i],(double)(0)); - } - ae_matrix_set_length(&c, n, n, _state); - rmatrixgemm(n, n, n, 1.0, &b1, 0, 0, 0, &b2, 0, 0, 0, 0.0, &c, 0, 0, _state); - for(i=n-1; i>=0; i--) - { - j = pivr.ptr.p_int[i]; - for(k=0; k<=n-1; k++) - { - v = c.ptr.pp_double[i][k]; - c.ptr.pp_double[i][k] = c.ptr.pp_double[j][k]; - c.ptr.pp_double[j][k] = v; - } - } - for(i=n-1; i>=0; i--) - { - j = pivc.ptr.p_int[i]; - for(k=0; k<=n-1; k++) - { - v = c.ptr.pp_double[k][i]; - c.ptr.pp_double[k][i] = c.ptr.pp_double[k][j]; - c.ptr.pp_double[k][j] = v; - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(c.ptr.pp_double[i][j]-a.ptr.pp_double[i][j], _state),tol), __FILE__, __LINE__, "testtrfacunit.ap:1598"); - } - } - ae_set_error_flag(err, (success&&haszero)||(!haszero&&!success), __FILE__, __LINE__, "testtrfacunit.ap:1599"); - } - - /* - * Increase problem sparcity and try one more time. - * Stop after testing NZ=0. - */ - if( nz==0 ) - { - break; - } - nz = nz/2; - } - } - ae_frame_leave(_state); -} - - -static void testtrfacunit_testcluproblem(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double threshold, - ae_bool* err, - ae_bool* properr, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix ca; - ae_matrix cl; - ae_matrix cu; - ae_matrix ca2; - ae_vector ct; - ae_int_t i; - ae_int_t j; - ae_int_t minmn; - ae_complex v; - ae_vector p; - - ae_frame_make(_state, &_frame_block); - memset(&ca, 0, sizeof(ca)); - memset(&cl, 0, sizeof(cl)); - memset(&cu, 0, sizeof(cu)); - memset(&ca2, 0, sizeof(ca2)); - memset(&ct, 0, sizeof(ct)); - memset(&p, 0, sizeof(p)); - ae_matrix_init(&ca, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&cl, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&cu, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&ca2, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&ct, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - - minmn = ae_minint(m, n, _state); - - /* - * PLU test - */ - ae_matrix_set_length(&ca, m, n, _state); - for(i=0; i<=m-1; i++) - { - ae_v_cmove(&ca.ptr.pp_complex[i][0], 1, &a->ptr.pp_complex[i][0], 1, "N", ae_v_len(0,n-1)); - } - cmatrixplu(&ca, m, n, &p, _state); - for(i=0; i<=minmn-1; i++) - { - if( p.ptr.p_int[i]=m ) - { - *properr = ae_true; - ae_frame_leave(_state); - return; - } - } - ae_matrix_set_length(&cl, m, minmn, _state); - for(j=0; j<=minmn-1; j++) - { - for(i=0; i<=j-1; i++) - { - cl.ptr.pp_complex[i][j] = ae_complex_from_d(0.0); - } - cl.ptr.pp_complex[j][j] = ae_complex_from_d(1.0); - for(i=j+1; i<=m-1; i++) - { - cl.ptr.pp_complex[i][j] = ca.ptr.pp_complex[i][j]; - } - } - ae_matrix_set_length(&cu, minmn, n, _state); - for(i=0; i<=minmn-1; i++) - { - for(j=0; j<=i-1; j++) - { - cu.ptr.pp_complex[i][j] = ae_complex_from_d(0.0); - } - for(j=i; j<=n-1; j++) - { - cu.ptr.pp_complex[i][j] = ca.ptr.pp_complex[i][j]; - } - } - ae_matrix_set_length(&ca2, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_cdotproduct(&cl.ptr.pp_complex[i][0], 1, "N", &cu.ptr.pp_complex[0][j], cu.stride, "N", ae_v_len(0,minmn-1)); - ca2.ptr.pp_complex[i][j] = v; - } - } - ae_vector_set_length(&ct, n, _state); - for(i=minmn-1; i>=0; i--) - { - if( i!=p.ptr.p_int[i] ) - { - ae_v_cmove(&ct.ptr.p_complex[0], 1, &ca2.ptr.pp_complex[i][0], 1, "N", ae_v_len(0,n-1)); - ae_v_cmove(&ca2.ptr.pp_complex[i][0], 1, &ca2.ptr.pp_complex[p.ptr.p_int[i]][0], 1, "N", ae_v_len(0,n-1)); - ae_v_cmove(&ca2.ptr.pp_complex[p.ptr.p_int[i]][0], 1, &ct.ptr.p_complex[0], 1, "N", ae_v_len(0,n-1)); - } - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - *err = *err||ae_fp_greater(ae_c_abs(ae_c_sub(a->ptr.pp_complex[i][j],ca2.ptr.pp_complex[i][j]), _state),threshold); - } - } - - /* - * LUP test - */ - ae_matrix_set_length(&ca, m, n, _state); - for(i=0; i<=m-1; i++) - { - ae_v_cmove(&ca.ptr.pp_complex[i][0], 1, &a->ptr.pp_complex[i][0], 1, "N", ae_v_len(0,n-1)); - } - cmatrixlup(&ca, m, n, &p, _state); - for(i=0; i<=minmn-1; i++) - { - if( p.ptr.p_int[i]=n ) - { - *properr = ae_true; - ae_frame_leave(_state); - return; - } - } - ae_matrix_set_length(&cl, m, minmn, _state); - for(j=0; j<=minmn-1; j++) - { - for(i=0; i<=j-1; i++) - { - cl.ptr.pp_complex[i][j] = ae_complex_from_d(0.0); - } - for(i=j; i<=m-1; i++) - { - cl.ptr.pp_complex[i][j] = ca.ptr.pp_complex[i][j]; - } - } - ae_matrix_set_length(&cu, minmn, n, _state); - for(i=0; i<=minmn-1; i++) - { - for(j=0; j<=i-1; j++) - { - cu.ptr.pp_complex[i][j] = ae_complex_from_d(0.0); - } - cu.ptr.pp_complex[i][i] = ae_complex_from_d(1.0); - for(j=i+1; j<=n-1; j++) - { - cu.ptr.pp_complex[i][j] = ca.ptr.pp_complex[i][j]; - } - } - ae_matrix_set_length(&ca2, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_cdotproduct(&cl.ptr.pp_complex[i][0], 1, "N", &cu.ptr.pp_complex[0][j], cu.stride, "N", ae_v_len(0,minmn-1)); - ca2.ptr.pp_complex[i][j] = v; - } - } - ae_vector_set_length(&ct, m, _state); - for(i=minmn-1; i>=0; i--) - { - if( i!=p.ptr.p_int[i] ) - { - ae_v_cmove(&ct.ptr.p_complex[0], 1, &ca2.ptr.pp_complex[0][i], ca2.stride, "N", ae_v_len(0,m-1)); - ae_v_cmove(&ca2.ptr.pp_complex[0][i], ca2.stride, &ca2.ptr.pp_complex[0][p.ptr.p_int[i]], ca2.stride, "N", ae_v_len(0,m-1)); - ae_v_cmove(&ca2.ptr.pp_complex[0][p.ptr.p_int[i]], ca2.stride, &ct.ptr.p_complex[0], 1, "N", ae_v_len(0,m-1)); - } - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - *err = *err||ae_fp_greater(ae_c_abs(ae_c_sub(a->ptr.pp_complex[i][j],ca2.ptr.pp_complex[i][j]), _state),threshold); - } - } - ae_frame_leave(_state); -} - - -static void testtrfacunit_testrluproblem(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double threshold, - ae_bool* err, - ae_bool* properr, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix ca; - ae_matrix cl; - ae_matrix cu; - ae_matrix ca2; - ae_vector ct; - ae_int_t i; - ae_int_t j; - ae_int_t minmn; - double v; - ae_vector p; - - ae_frame_make(_state, &_frame_block); - memset(&ca, 0, sizeof(ca)); - memset(&cl, 0, sizeof(cl)); - memset(&cu, 0, sizeof(cu)); - memset(&ca2, 0, sizeof(ca2)); - memset(&ct, 0, sizeof(ct)); - memset(&p, 0, sizeof(p)); - ae_matrix_init(&ca, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&cl, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&cu, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ca2, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - - minmn = ae_minint(m, n, _state); - - /* - * PLU test - */ - ae_matrix_set_length(&ca, m, n, _state); - for(i=0; i<=m-1; i++) - { - ae_v_move(&ca.ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - } - rmatrixplu(&ca, m, n, &p, _state); - for(i=0; i<=minmn-1; i++) - { - if( p.ptr.p_int[i]=m ) - { - *properr = ae_true; - ae_frame_leave(_state); - return; - } - } - ae_matrix_set_length(&cl, m, minmn, _state); - for(j=0; j<=minmn-1; j++) - { - for(i=0; i<=j-1; i++) - { - cl.ptr.pp_double[i][j] = 0.0; - } - cl.ptr.pp_double[j][j] = 1.0; - for(i=j+1; i<=m-1; i++) - { - cl.ptr.pp_double[i][j] = ca.ptr.pp_double[i][j]; - } - } - ae_matrix_set_length(&cu, minmn, n, _state); - for(i=0; i<=minmn-1; i++) - { - for(j=0; j<=i-1; j++) - { - cu.ptr.pp_double[i][j] = 0.0; - } - for(j=i; j<=n-1; j++) - { - cu.ptr.pp_double[i][j] = ca.ptr.pp_double[i][j]; - } - } - ae_matrix_set_length(&ca2, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&cl.ptr.pp_double[i][0], 1, &cu.ptr.pp_double[0][j], cu.stride, ae_v_len(0,minmn-1)); - ca2.ptr.pp_double[i][j] = v; - } - } - ae_vector_set_length(&ct, n, _state); - for(i=minmn-1; i>=0; i--) - { - if( i!=p.ptr.p_int[i] ) - { - ae_v_move(&ct.ptr.p_double[0], 1, &ca2.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - ae_v_move(&ca2.ptr.pp_double[i][0], 1, &ca2.ptr.pp_double[p.ptr.p_int[i]][0], 1, ae_v_len(0,n-1)); - ae_v_move(&ca2.ptr.pp_double[p.ptr.p_int[i]][0], 1, &ct.ptr.p_double[0], 1, ae_v_len(0,n-1)); - } - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - *err = *err||ae_fp_greater(ae_fabs(a->ptr.pp_double[i][j]-ca2.ptr.pp_double[i][j], _state),threshold); - } - } - - /* - * LUP test - */ - ae_matrix_set_length(&ca, m, n, _state); - for(i=0; i<=m-1; i++) - { - ae_v_move(&ca.ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - } - rmatrixlup(&ca, m, n, &p, _state); - for(i=0; i<=minmn-1; i++) - { - if( p.ptr.p_int[i]=n ) - { - *properr = ae_true; - ae_frame_leave(_state); - return; - } - } - ae_matrix_set_length(&cl, m, minmn, _state); - for(j=0; j<=minmn-1; j++) - { - for(i=0; i<=j-1; i++) - { - cl.ptr.pp_double[i][j] = 0.0; - } - for(i=j; i<=m-1; i++) - { - cl.ptr.pp_double[i][j] = ca.ptr.pp_double[i][j]; - } - } - ae_matrix_set_length(&cu, minmn, n, _state); - for(i=0; i<=minmn-1; i++) - { - for(j=0; j<=i-1; j++) - { - cu.ptr.pp_double[i][j] = 0.0; - } - cu.ptr.pp_double[i][i] = 1.0; - for(j=i+1; j<=n-1; j++) - { - cu.ptr.pp_double[i][j] = ca.ptr.pp_double[i][j]; - } - } - ae_matrix_set_length(&ca2, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&cl.ptr.pp_double[i][0], 1, &cu.ptr.pp_double[0][j], cu.stride, ae_v_len(0,minmn-1)); - ca2.ptr.pp_double[i][j] = v; - } - } - ae_vector_set_length(&ct, m, _state); - for(i=minmn-1; i>=0; i--) - { - if( i!=p.ptr.p_int[i] ) - { - ae_v_move(&ct.ptr.p_double[0], 1, &ca2.ptr.pp_double[0][i], ca2.stride, ae_v_len(0,m-1)); - ae_v_move(&ca2.ptr.pp_double[0][i], ca2.stride, &ca2.ptr.pp_double[0][p.ptr.p_int[i]], ca2.stride, ae_v_len(0,m-1)); - ae_v_move(&ca2.ptr.pp_double[0][p.ptr.p_int[i]], ca2.stride, &ct.ptr.p_double[0], 1, ae_v_len(0,m-1)); - } - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - *err = *err||ae_fp_greater(ae_fabs(a->ptr.pp_double[i][j]-ca2.ptr.pp_double[i][j], _state),threshold); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Function for testing dense Cholesky updates -Sets error flag to True on errors, does not change it on success. - - -- ALGLIB PROJECT -- - Copyright 16.01.1014 by Bochkanov Sergey -*************************************************************************/ -static void testtrfacunit_testdensecholeskyupdates(ae_bool* spdupderrorflag, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - double pfix; - ae_matrix a0; - ae_matrix a1; - ae_vector u; - ae_vector fix; - ae_int_t i; - ae_int_t j; - ae_bool isupper; - double tol; - ae_vector bufr; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&a0, 0, sizeof(a0)); - memset(&a1, 0, sizeof(a1)); - memset(&u, 0, sizeof(u)); - memset(&fix, 0, sizeof(fix)); - memset(&bufr, 0, sizeof(bufr)); - memset(&rs, 0, sizeof(rs)); - ae_matrix_init(&a0, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&u, 0, DT_REAL, _state, ae_true); - ae_vector_init(&fix, 0, DT_BOOL, _state, ae_true); - ae_vector_init(&bufr, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Settings - */ - tol = 1.0E-8; - - /* - * Test rank-1 updates - * - * For each matrix size in 1..30 select sparse update vector with probability of element - * being non-zero equal to 1/2. - */ - for(n=1; n<=30; n++) - { - - /* - * Generate two matrices A0=A1, fill one triangle with SPD matrix, - * another one with trash. Prepare vector U. - */ - isupper = ae_fp_less(hqrnduniformr(&rs, _state),0.5); - spdmatrixrndcond(n, 1.0E4, &a0, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (ji&&!isupper) ) - { - a0.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5; - } - } - } - ae_matrix_set_length(&a1, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a1.ptr.pp_double[i][j] = a0.ptr.pp_double[i][j]; - } - } - ae_vector_set_length(&u, n, _state); - for(i=0; i<=n-1; i++) - { - if( ae_fp_less_eq(hqrnduniformr(&rs, _state),0.5) ) - { - u.ptr.p_double[i] = hqrnduniformr(&rs, _state)-0.5; - } - else - { - u.ptr.p_double[i] = (double)(0); - } - } - - /* - * Factorize and compare: - * * A0 is factorized as follows: first with full Cholesky, then - * we call SPDMatrixCholeskyUpdateAdd1 - * * A1 is transformed explicitly before factorization with full Cholesky - * - * We randomly test either SPDMatrixCholeskyUpdateFix() or its - * buffered version, SPDMatrixCholeskyUpdateFixBuf() - */ - ae_set_error_flag(spdupderrorflag, !spdmatrixcholesky(&a0, n, isupper, _state), __FILE__, __LINE__, "testtrfacunit.ap:1681"); - if( *spdupderrorflag ) - { - ae_frame_leave(_state); - return; - } - if( ae_fp_less(hqrnduniformr(&rs, _state),0.5) ) - { - spdmatrixcholeskyupdateadd1(&a0, n, isupper, &u, _state); - } - else - { - spdmatrixcholeskyupdateadd1buf(&a0, n, isupper, &u, &bufr, _state); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (j>=i&&isupper)||(j<=i&&!isupper) ) - { - a1.ptr.pp_double[i][j] = a1.ptr.pp_double[i][j]+u.ptr.p_double[i]*u.ptr.p_double[j]; - } - } - } - ae_set_error_flag(spdupderrorflag, !spdmatrixcholesky(&a1, n, isupper, _state), __FILE__, __LINE__, "testtrfacunit.ap:1692"); - if( *spdupderrorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(spdupderrorflag, ae_fp_greater(ae_fabs(a0.ptr.pp_double[i][j]-a1.ptr.pp_double[i][j], _state),tol), __FILE__, __LINE__, "testtrfacunit.ap:1697"); - } - } - } - - /* - * Test variable fixing functions. - * - * For each matrix size in 1..30 select PFix - probability of each variable being fixed, - * and perform test. - */ - for(n=1; n<=30; n++) - { - - /* - * Generate two matrices A0=A1, fill one triangle with SPD matrix, - * another one with trash. Prepare vector Fix. - */ - pfix = (double)hqrnduniformi(&rs, n+1, _state)/(double)n; - isupper = ae_fp_less(hqrnduniformr(&rs, _state),0.5); - spdmatrixrndcond(n, 1.0E4, &a0, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (ji&&!isupper) ) - { - a0.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5; - } - } - } - ae_matrix_set_length(&a1, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a1.ptr.pp_double[i][j] = a0.ptr.pp_double[i][j]; - } - } - ae_vector_set_length(&fix, n, _state); - for(i=0; i<=n-1; i++) - { - fix.ptr.p_bool[i] = ae_fp_less_eq(hqrnduniformr(&rs, _state),pfix); - } - - /* - * Factorize and compare: - * * A0 is factorized as follows: first with full Cholesky, then - * variables are fixed with SPDMatrixCholeskyUpdateFix - * * A1 is fixed explicitly before factorization with full Cholesky - * - * We randomly test either SPDMatrixCholeskyUpdateFix() or its - * buffered version, SPDMatrixCholeskyUpdateFixBuf() - */ - ae_set_error_flag(spdupderrorflag, !spdmatrixcholesky(&a0, n, isupper, _state), __FILE__, __LINE__, "testtrfacunit.ap:1736"); - if( *spdupderrorflag ) - { - ae_frame_leave(_state); - return; - } - if( ae_fp_less(hqrnduniformr(&rs, _state),0.5) ) - { - spdmatrixcholeskyupdatefixbuf(&a0, n, isupper, &fix, &bufr, _state); - } - else - { - spdmatrixcholeskyupdatefix(&a0, n, isupper, &fix, _state); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (j>=i&&isupper)||(j<=i&&!isupper) ) - { - if( fix.ptr.p_bool[i]||fix.ptr.p_bool[j] ) - { - if( i==j ) - { - a1.ptr.pp_double[i][j] = (double)(1); - } - else - { - a1.ptr.pp_double[i][j] = (double)(0); - } - } - } - } - } - ae_set_error_flag(spdupderrorflag, !spdmatrixcholesky(&a1, n, isupper, _state), __FILE__, __LINE__, "testtrfacunit.ap:1753"); - if( *spdupderrorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(spdupderrorflag, ae_fp_greater(ae_fabs(a0.ptr.pp_double[i][j]-a1.ptr.pp_double[i][j], _state),tol), __FILE__, __LINE__, "testtrfacunit.ap:1758"); - } - } - } - ae_frame_leave(_state); -} - - - - - - - - -/************************************************************************* -Main unittest subroutine -*************************************************************************/ -ae_bool testtrlinsolve(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t maxmn; - ae_int_t passcount; - double threshold; - ae_matrix aeffective; - ae_matrix aparam; - ae_vector xe; - ae_vector b; - ae_int_t n; - ae_int_t pass; - ae_int_t i; - ae_int_t j; - ae_int_t cnts; - ae_int_t cntu; - ae_int_t cntt; - ae_int_t cntm; - ae_bool waserrors; - ae_bool isupper; - ae_bool istrans; - ae_bool isunit; - double v; - double s; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&aeffective, 0, sizeof(aeffective)); - memset(&aparam, 0, sizeof(aparam)); - memset(&xe, 0, sizeof(xe)); - memset(&b, 0, sizeof(b)); - ae_matrix_init(&aeffective, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&aparam, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xe, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - - waserrors = ae_false; - maxmn = 15; - passcount = 15; - threshold = 1000*ae_machineepsilon; - - /* - * Different problems - */ - for(n=1; n<=maxmn; n++) - { - ae_matrix_set_length(&aeffective, n-1+1, n-1+1, _state); - ae_matrix_set_length(&aparam, n-1+1, n-1+1, _state); - ae_vector_set_length(&xe, n-1+1, _state); - ae_vector_set_length(&b, n-1+1, _state); - for(pass=1; pass<=passcount; pass++) - { - for(cnts=0; cnts<=1; cnts++) - { - for(cntu=0; cntu<=1; cntu++) - { - for(cntt=0; cntt<=1; cntt++) - { - for(cntm=0; cntm<=2; cntm++) - { - isupper = cnts==0; - isunit = cntu==0; - istrans = cntt==0; - - /* - * Skip meaningless combinations of parameters: - * (matrix is singular) AND (matrix is unit diagonal) - */ - if( cntm==2&&isunit ) - { - continue; - } - - /* - * Clear matrices - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - aeffective.ptr.pp_double[i][j] = (double)(0); - aparam.ptr.pp_double[i][j] = (double)(0); - } - } - - /* - * Prepare matrices - */ - if( isupper ) - { - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - aeffective.ptr.pp_double[i][j] = 0.9*(2*ae_randomreal(_state)-1); - aparam.ptr.pp_double[i][j] = aeffective.ptr.pp_double[i][j]; - } - aeffective.ptr.pp_double[i][i] = (2*ae_randominteger(2, _state)-1)*(0.8+ae_randomreal(_state)); - aparam.ptr.pp_double[i][i] = aeffective.ptr.pp_double[i][i]; - } - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i; j++) - { - aeffective.ptr.pp_double[i][j] = 0.9*(2*ae_randomreal(_state)-1); - aparam.ptr.pp_double[i][j] = aeffective.ptr.pp_double[i][j]; - } - aeffective.ptr.pp_double[i][i] = (2*ae_randominteger(2, _state)-1)*(0.8+ae_randomreal(_state)); - aparam.ptr.pp_double[i][i] = aeffective.ptr.pp_double[i][i]; - } - } - if( isunit ) - { - for(i=0; i<=n-1; i++) - { - aeffective.ptr.pp_double[i][i] = (double)(1); - aparam.ptr.pp_double[i][i] = (double)(0); - } - } - if( istrans ) - { - if( isupper ) - { - for(i=0; i<=n-1; i++) - { - for(j=i+1; j<=n-1; j++) - { - aeffective.ptr.pp_double[j][i] = aeffective.ptr.pp_double[i][j]; - aeffective.ptr.pp_double[i][j] = (double)(0); - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=i+1; j<=n-1; j++) - { - aeffective.ptr.pp_double[i][j] = aeffective.ptr.pp_double[j][i]; - aeffective.ptr.pp_double[j][i] = (double)(0); - } - } - } - } - - /* - * Prepare task, solve, compare - */ - for(i=0; i<=n-1; i++) - { - xe.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&aeffective.ptr.pp_double[i][0], 1, &xe.ptr.p_double[0], 1, ae_v_len(0,n-1)); - b.ptr.p_double[i] = v; - } - rmatrixtrsafesolve(&aparam, n, &b, &s, isupper, istrans, isunit, _state); - ae_v_muld(&xe.ptr.p_double[0], 1, ae_v_len(0,n-1), s); - ae_v_sub(&xe.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = ae_v_dotproduct(&xe.ptr.p_double[0], 1, &xe.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = ae_sqrt(v, _state); - waserrors = waserrors||ae_fp_greater(v,threshold); - } - } - } - } - } - } - - /* - * report - */ - if( !silent ) - { - printf("TESTING RMatrixTRSafeSolve\n"); - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - - -static void testsafesolveunit_rmatrixmakeacopy(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* b, - ae_state *_state); -static void testsafesolveunit_cmatrixmakeacopy(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* b, - ae_state *_state); - - - - - -/************************************************************************* -Main unittest subroutine -*************************************************************************/ -ae_bool testsafesolve(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t maxmn; - double threshold; - ae_bool rerrors; - ae_bool cerrors; - ae_bool waserrors; - ae_bool isupper; - ae_int_t trans; - ae_bool isunit; - double scalea; - double growth; - ae_int_t i; - ae_int_t j; - ae_int_t n; - ae_int_t j1; - ae_int_t j2; - ae_complex cv; - ae_matrix ca; - ae_matrix cea; - ae_matrix ctmpa; - ae_vector cxs; - ae_vector cxe; - double rv; - ae_matrix ra; - ae_matrix rea; - ae_matrix rtmpa; - ae_vector rxs; - ae_vector rxe; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&ca, 0, sizeof(ca)); - memset(&cea, 0, sizeof(cea)); - memset(&ctmpa, 0, sizeof(ctmpa)); - memset(&cxs, 0, sizeof(cxs)); - memset(&cxe, 0, sizeof(cxe)); - memset(&ra, 0, sizeof(ra)); - memset(&rea, 0, sizeof(rea)); - memset(&rtmpa, 0, sizeof(rtmpa)); - memset(&rxs, 0, sizeof(rxs)); - memset(&rxe, 0, sizeof(rxe)); - ae_matrix_init(&ca, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&cea, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&ctmpa, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&cxs, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&cxe, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&ra, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&rea, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&rtmpa, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rxs, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rxe, 0, DT_REAL, _state, ae_true); - - maxmn = 30; - threshold = 100000*ae_machineepsilon; - rerrors = ae_false; - cerrors = ae_false; - waserrors = ae_false; - - /* - * Different problems: general tests - */ - for(n=1; n<=maxmn; n++) - { - - /* - * test complex solver with well-conditioned matrix: - * 1. generate A: fill off-diagonal elements with small values, - * diagonal elements are filled with larger values - * 2. generate 'effective' A - * 3. prepare task (exact X is stored in CXE, right part - in CXS), - * solve and compare CXS and CXE - */ - isupper = ae_fp_greater(ae_randomreal(_state),0.5); - trans = ae_randominteger(3, _state); - isunit = ae_fp_greater(ae_randomreal(_state),0.5); - scalea = ae_randomreal(_state)+0.5; - ae_matrix_set_length(&ca, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - ca.ptr.pp_complex[i][j].x = (2*ae_randominteger(2, _state)-1)*(5+ae_randomreal(_state)); - ca.ptr.pp_complex[i][j].y = (2*ae_randominteger(2, _state)-1)*(5+ae_randomreal(_state)); - } - else - { - ca.ptr.pp_complex[i][j].x = 0.2*ae_randomreal(_state)-0.1; - ca.ptr.pp_complex[i][j].y = 0.2*ae_randomreal(_state)-0.1; - } - } - } - testsafesolveunit_cmatrixmakeacopy(&ca, n, n, &ctmpa, _state); - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j1 = 0; - j2 = i-1; - } - else - { - j1 = i+1; - j2 = n-1; - } - for(j=j1; j<=j2; j++) - { - ctmpa.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - if( isunit ) - { - ctmpa.ptr.pp_complex[i][i] = ae_complex_from_i(1); - } - } - ae_matrix_set_length(&cea, n, n, _state); - for(i=0; i<=n-1; i++) - { - if( trans==0 ) - { - ae_v_cmoved(&cea.ptr.pp_complex[i][0], 1, &ctmpa.ptr.pp_complex[i][0], 1, "N", ae_v_len(0,n-1), scalea); - } - if( trans==1 ) - { - ae_v_cmoved(&cea.ptr.pp_complex[0][i], cea.stride, &ctmpa.ptr.pp_complex[i][0], 1, "N", ae_v_len(0,n-1), scalea); - } - if( trans==2 ) - { - ae_v_cmoved(&cea.ptr.pp_complex[0][i], cea.stride, &ctmpa.ptr.pp_complex[i][0], 1, "Conj", ae_v_len(0,n-1), scalea); - } - } - ae_vector_set_length(&cxe, n, _state); - for(i=0; i<=n-1; i++) - { - cxe.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1; - cxe.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1; - } - ae_vector_set_length(&cxs, n, _state); - for(i=0; i<=n-1; i++) - { - cv = ae_v_cdotproduct(&cea.ptr.pp_complex[i][0], 1, "N", &cxe.ptr.p_complex[0], 1, "N", ae_v_len(0,n-1)); - cxs.ptr.p_complex[i] = cv; - } - if( cmatrixscaledtrsafesolve(&ca, scalea, n, &cxs, isupper, trans, isunit, ae_sqrt(ae_maxrealnumber, _state), _state) ) - { - for(i=0; i<=n-1; i++) - { - cerrors = cerrors||ae_fp_greater(ae_c_abs(ae_c_sub(cxs.ptr.p_complex[i],cxe.ptr.p_complex[i]), _state),threshold); - } - } - else - { - cerrors = ae_true; - } - - /* - * same with real - */ - isupper = ae_fp_greater(ae_randomreal(_state),0.5); - trans = ae_randominteger(2, _state); - isunit = ae_fp_greater(ae_randomreal(_state),0.5); - scalea = ae_randomreal(_state)+0.5; - ae_matrix_set_length(&ra, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - ra.ptr.pp_double[i][j] = (2*ae_randominteger(2, _state)-1)*(5+ae_randomreal(_state)); - } - else - { - ra.ptr.pp_double[i][j] = 0.2*ae_randomreal(_state)-0.1; - } - } - } - testsafesolveunit_rmatrixmakeacopy(&ra, n, n, &rtmpa, _state); - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j1 = 0; - j2 = i-1; - } - else - { - j1 = i+1; - j2 = n-1; - } - for(j=j1; j<=j2; j++) - { - rtmpa.ptr.pp_double[i][j] = (double)(0); - } - if( isunit ) - { - rtmpa.ptr.pp_double[i][i] = (double)(1); - } - } - ae_matrix_set_length(&rea, n, n, _state); - for(i=0; i<=n-1; i++) - { - if( trans==0 ) - { - ae_v_moved(&rea.ptr.pp_double[i][0], 1, &rtmpa.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), scalea); - } - if( trans==1 ) - { - ae_v_moved(&rea.ptr.pp_double[0][i], rea.stride, &rtmpa.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), scalea); - } - } - ae_vector_set_length(&rxe, n, _state); - for(i=0; i<=n-1; i++) - { - rxe.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - ae_vector_set_length(&rxs, n, _state); - for(i=0; i<=n-1; i++) - { - rv = ae_v_dotproduct(&rea.ptr.pp_double[i][0], 1, &rxe.ptr.p_double[0], 1, ae_v_len(0,n-1)); - rxs.ptr.p_double[i] = rv; - } - if( rmatrixscaledtrsafesolve(&ra, scalea, n, &rxs, isupper, trans, isunit, ae_sqrt(ae_maxrealnumber, _state), _state) ) - { - for(i=0; i<=n-1; i++) - { - rerrors = rerrors||ae_fp_greater(ae_fabs(rxs.ptr.p_double[i]-rxe.ptr.p_double[i], _state),threshold); - } - } - else - { - rerrors = ae_true; - } - } - - /* - * Special test with diagonal ill-conditioned matrix: - * * ability to solve it when resulting growth is less than threshold - * * ability to stop solve when resulting growth is greater than threshold - * - * A = diag(1, 1/growth) - * b = (1, 0.5) - */ - n = 2; - growth = (double)(10); - ae_matrix_set_length(&ca, n, n, _state); - ca.ptr.pp_complex[0][0] = ae_complex_from_i(1); - ca.ptr.pp_complex[0][1] = ae_complex_from_i(0); - ca.ptr.pp_complex[1][0] = ae_complex_from_i(0); - ca.ptr.pp_complex[1][1] = ae_complex_from_d(1/growth); - ae_vector_set_length(&cxs, n, _state); - cxs.ptr.p_complex[0] = ae_complex_from_d(1.0); - cxs.ptr.p_complex[1] = ae_complex_from_d(0.5); - cerrors = cerrors||!cmatrixscaledtrsafesolve(&ca, 1.0, n, &cxs, ae_fp_greater(ae_randomreal(_state),0.5), ae_randominteger(3, _state), ae_false, 1.05*ae_maxreal(ae_c_abs(cxs.ptr.p_complex[1], _state)*growth, 1.0, _state), _state); - cerrors = cerrors||!cmatrixscaledtrsafesolve(&ca, 1.0, n, &cxs, ae_fp_greater(ae_randomreal(_state),0.5), ae_randominteger(3, _state), ae_false, 0.95*ae_maxreal(ae_c_abs(cxs.ptr.p_complex[1], _state)*growth, 1.0, _state), _state); - ae_matrix_set_length(&ra, n, n, _state); - ra.ptr.pp_double[0][0] = (double)(1); - ra.ptr.pp_double[0][1] = (double)(0); - ra.ptr.pp_double[1][0] = (double)(0); - ra.ptr.pp_double[1][1] = 1/growth; - ae_vector_set_length(&rxs, n, _state); - rxs.ptr.p_double[0] = 1.0; - rxs.ptr.p_double[1] = 0.5; - rerrors = rerrors||!rmatrixscaledtrsafesolve(&ra, 1.0, n, &rxs, ae_fp_greater(ae_randomreal(_state),0.5), ae_randominteger(2, _state), ae_false, 1.05*ae_maxreal(ae_fabs(rxs.ptr.p_double[1], _state)*growth, 1.0, _state), _state); - rerrors = rerrors||!rmatrixscaledtrsafesolve(&ra, 1.0, n, &rxs, ae_fp_greater(ae_randomreal(_state),0.5), ae_randominteger(2, _state), ae_false, 0.95*ae_maxreal(ae_fabs(rxs.ptr.p_double[1], _state)*growth, 1.0, _state), _state); - - /* - * Special test with diagonal degenerate matrix: - * * ability to solve it when resulting growth is less than threshold - * * ability to stop solve when resulting growth is greater than threshold - * - * A = diag(1, 0) - * b = (1, 0.5) - */ - n = 2; - ae_matrix_set_length(&ca, n, n, _state); - ca.ptr.pp_complex[0][0] = ae_complex_from_i(1); - ca.ptr.pp_complex[0][1] = ae_complex_from_i(0); - ca.ptr.pp_complex[1][0] = ae_complex_from_i(0); - ca.ptr.pp_complex[1][1] = ae_complex_from_i(0); - ae_vector_set_length(&cxs, n, _state); - cxs.ptr.p_complex[0] = ae_complex_from_d(1.0); - cxs.ptr.p_complex[1] = ae_complex_from_d(0.5); - cerrors = cerrors||cmatrixscaledtrsafesolve(&ca, 1.0, n, &cxs, ae_fp_greater(ae_randomreal(_state),0.5), ae_randominteger(3, _state), ae_false, ae_sqrt(ae_maxrealnumber, _state), _state); - ae_matrix_set_length(&ra, n, n, _state); - ra.ptr.pp_double[0][0] = (double)(1); - ra.ptr.pp_double[0][1] = (double)(0); - ra.ptr.pp_double[1][0] = (double)(0); - ra.ptr.pp_double[1][1] = (double)(0); - ae_vector_set_length(&rxs, n, _state); - rxs.ptr.p_double[0] = 1.0; - rxs.ptr.p_double[1] = 0.5; - rerrors = rerrors||rmatrixscaledtrsafesolve(&ra, 1.0, n, &rxs, ae_fp_greater(ae_randomreal(_state),0.5), ae_randominteger(2, _state), ae_false, ae_sqrt(ae_maxrealnumber, _state), _state); - - /* - * report - */ - waserrors = rerrors||cerrors; - if( !silent ) - { - printf("TESTING SAFE TR SOLVER\n"); - printf("REAL: "); - if( !rerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("COMPLEX: "); - if( !cerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Copy -*************************************************************************/ -static void testsafesolveunit_rmatrixmakeacopy(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* b, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(b); - - ae_matrix_set_length(b, m-1+1, n-1+1, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - b->ptr.pp_double[i][j] = a->ptr.pp_double[i][j]; - } - } -} - - -/************************************************************************* -Copy -*************************************************************************/ -static void testsafesolveunit_cmatrixmakeacopy(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* b, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(b); - - ae_matrix_set_length(b, m-1+1, n-1+1, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - b->ptr.pp_complex[i][j] = a->ptr.pp_complex[i][j]; - } - } -} - - - -static double testrcondunit_threshold50 = 0.25; -static double testrcondunit_threshold90 = 0.10; -static void testrcondunit_rmatrixmakeacopy(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* b, - ae_state *_state); -static void testrcondunit_rmatrixdrophalf(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool droplower, - ae_state *_state); -static void testrcondunit_cmatrixdrophalf(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool droplower, - ae_state *_state); -static void testrcondunit_rmatrixgenzero(/* Real */ ae_matrix* a0, - ae_int_t n, - ae_state *_state); -static ae_bool testrcondunit_rmatrixinvmattr(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunittriangular, - ae_state *_state); -static ae_bool testrcondunit_rmatrixinvmatlu(/* Real */ ae_matrix* a, - /* Integer */ ae_vector* pivots, - ae_int_t n, - ae_state *_state); -static ae_bool testrcondunit_rmatrixinvmat(/* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state); -static void testrcondunit_rmatrixrefrcond(/* Real */ ae_matrix* a, - ae_int_t n, - double* rc1, - double* rcinf, - ae_state *_state); -static void testrcondunit_cmatrixmakeacopy(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* b, - ae_state *_state); -static void testrcondunit_cmatrixgenzero(/* Complex */ ae_matrix* a0, - ae_int_t n, - ae_state *_state); -static ae_bool testrcondunit_cmatrixinvmattr(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunittriangular, - ae_state *_state); -static ae_bool testrcondunit_cmatrixinvmatlu(/* Complex */ ae_matrix* a, - /* Integer */ ae_vector* pivots, - ae_int_t n, - ae_state *_state); -static ae_bool testrcondunit_cmatrixinvmat(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_state *_state); -static void testrcondunit_cmatrixrefrcond(/* Complex */ ae_matrix* a, - ae_int_t n, - double* rc1, - double* rcinf, - ae_state *_state); -static ae_bool testrcondunit_testrmatrixtrrcond(ae_int_t maxn, - ae_int_t passcount, - ae_state *_state); -static ae_bool testrcondunit_testcmatrixtrrcond(ae_int_t maxn, - ae_int_t passcount, - ae_state *_state); -static ae_bool testrcondunit_testrmatrixrcond(ae_int_t maxn, - ae_int_t passcount, - ae_state *_state); -static ae_bool testrcondunit_testspdmatrixrcond(ae_int_t maxn, - ae_int_t passcount, - ae_state *_state); -static ae_bool testrcondunit_testcmatrixrcond(ae_int_t maxn, - ae_int_t passcount, - ae_state *_state); -static ae_bool testrcondunit_testhpdmatrixrcond(ae_int_t maxn, - ae_int_t passcount, - ae_state *_state); - - - - - -ae_bool testrcond(ae_bool silent, ae_state *_state) -{ - ae_int_t maxn; - ae_int_t passcount; - ae_bool waserrors; - ae_bool rtrerr; - ae_bool ctrerr; - ae_bool rerr; - ae_bool cerr; - ae_bool spderr; - ae_bool hpderr; - ae_bool result; - - - maxn = 10; - passcount = 100; - - /* - * report - */ - rtrerr = !testrcondunit_testrmatrixtrrcond(maxn, passcount, _state); - ctrerr = !testrcondunit_testcmatrixtrrcond(maxn, passcount, _state); - rerr = !testrcondunit_testrmatrixrcond(maxn, passcount, _state); - cerr = !testrcondunit_testcmatrixrcond(maxn, passcount, _state); - spderr = !testrcondunit_testspdmatrixrcond(maxn, passcount, _state); - hpderr = !testrcondunit_testhpdmatrixrcond(maxn, passcount, _state); - waserrors = ((((rtrerr||ctrerr)||rerr)||cerr)||spderr)||hpderr; - if( !silent ) - { - printf("TESTING RCOND\n"); - printf("REAL TRIANGULAR: "); - if( !rtrerr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("COMPLEX TRIANGULAR: "); - if( !ctrerr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("REAL: "); - if( !rerr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("SPD: "); - if( !spderr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("HPD: "); - if( !hpderr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("COMPLEX: "); - if( !cerr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - return result; -} - - -/************************************************************************* -Copy -*************************************************************************/ -static void testrcondunit_rmatrixmakeacopy(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* b, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(b); - - ae_matrix_set_length(b, m-1+1, n-1+1, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - b->ptr.pp_double[i][j] = a->ptr.pp_double[i][j]; - } - } -} - - -/************************************************************************* -Drops upper or lower half of the matrix - fills it by special pattern -which may be used later to ensure that this part wasn't changed -*************************************************************************/ -static void testrcondunit_rmatrixdrophalf(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool droplower, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (droplower&&i>j)||(!droplower&&iptr.pp_double[i][j] = (double)(1+2*i+3*j); - } - } - } -} - - -/************************************************************************* -Drops upper or lower half of the matrix - fills it by special pattern -which may be used later to ensure that this part wasn't changed -*************************************************************************/ -static void testrcondunit_cmatrixdrophalf(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool droplower, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (droplower&&i>j)||(!droplower&&iptr.pp_complex[i][j] = ae_complex_from_i(1+2*i+3*j); - } - } - } -} - - -/************************************************************************* -Generate matrix with given condition number C (2-norm) -*************************************************************************/ -static void testrcondunit_rmatrixgenzero(/* Real */ ae_matrix* a0, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - ae_matrix_set_length(a0, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a0->ptr.pp_double[i][j] = (double)(0); - } - } -} - - -/************************************************************************* -triangular inverse -*************************************************************************/ -static ae_bool testrcondunit_rmatrixinvmattr(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunittriangular, - ae_state *_state) -{ - ae_frame _frame_block; - ae_bool nounit; - ae_int_t i; - ae_int_t j; - double v; - double ajj; - ae_vector t; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&t, 0, sizeof(t)); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - - result = ae_true; - ae_vector_set_length(&t, n-1+1, _state); - - /* - * Test the input parameters. - */ - nounit = !isunittriangular; - if( isupper ) - { - - /* - * Compute inverse of upper triangular matrix. - */ - for(j=0; j<=n-1; j++) - { - if( nounit ) - { - if( ae_fp_eq(a->ptr.pp_double[j][j],(double)(0)) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - a->ptr.pp_double[j][j] = 1/a->ptr.pp_double[j][j]; - ajj = -a->ptr.pp_double[j][j]; - } - else - { - ajj = (double)(-1); - } - - /* - * Compute elements 1:j-1 of j-th column. - */ - if( j>0 ) - { - ae_v_move(&t.ptr.p_double[0], 1, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,j-1)); - for(i=0; i<=j-1; i++) - { - if( iptr.pp_double[i][i+1], 1, &t.ptr.p_double[i+1], 1, ae_v_len(i+1,j-1)); - } - else - { - v = (double)(0); - } - if( nounit ) - { - a->ptr.pp_double[i][j] = v+a->ptr.pp_double[i][i]*t.ptr.p_double[i]; - } - else - { - a->ptr.pp_double[i][j] = v+t.ptr.p_double[i]; - } - } - ae_v_muld(&a->ptr.pp_double[0][j], a->stride, ae_v_len(0,j-1), ajj); - } - } - } - else - { - - /* - * Compute inverse of lower triangular matrix. - */ - for(j=n-1; j>=0; j--) - { - if( nounit ) - { - if( ae_fp_eq(a->ptr.pp_double[j][j],(double)(0)) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - a->ptr.pp_double[j][j] = 1/a->ptr.pp_double[j][j]; - ajj = -a->ptr.pp_double[j][j]; - } - else - { - ajj = (double)(-1); - } - if( jptr.pp_double[j+1][j], a->stride, ae_v_len(j+1,n-1)); - for(i=j+1; i<=n-1; i++) - { - if( i>j+1 ) - { - v = ae_v_dotproduct(&a->ptr.pp_double[i][j+1], 1, &t.ptr.p_double[j+1], 1, ae_v_len(j+1,i-1)); - } - else - { - v = (double)(0); - } - if( nounit ) - { - a->ptr.pp_double[i][j] = v+a->ptr.pp_double[i][i]*t.ptr.p_double[i]; - } - else - { - a->ptr.pp_double[i][j] = v+t.ptr.p_double[i]; - } - } - ae_v_muld(&a->ptr.pp_double[j+1][j], a->stride, ae_v_len(j+1,n-1), ajj); - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -LU inverse -*************************************************************************/ -static ae_bool testrcondunit_rmatrixinvmatlu(/* Real */ ae_matrix* a, - /* Integer */ ae_vector* pivots, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector work; - ae_int_t i; - ae_int_t j; - ae_int_t jp; - double v; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&work, 0, sizeof(work)); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - - result = ae_true; - - /* - * Quick return if possible - */ - if( n==0 ) - { - ae_frame_leave(_state); - return result; - } - ae_vector_set_length(&work, n-1+1, _state); - - /* - * Form inv(U) - */ - if( !testrcondunit_rmatrixinvmattr(a, n, ae_true, ae_false, _state) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - - /* - * Solve the equation inv(A)*L = inv(U) for inv(A). - */ - for(j=n-1; j>=0; j--) - { - - /* - * Copy current column of L to WORK and replace with zeros. - */ - for(i=j+1; i<=n-1; i++) - { - work.ptr.p_double[i] = a->ptr.pp_double[i][j]; - a->ptr.pp_double[i][j] = (double)(0); - } - - /* - * Compute current column of inv(A). - */ - if( jptr.pp_double[i][j+1], 1, &work.ptr.p_double[j+1], 1, ae_v_len(j+1,n-1)); - a->ptr.pp_double[i][j] = a->ptr.pp_double[i][j]-v; - } - } - } - - /* - * Apply column interchanges. - */ - for(j=n-2; j>=0; j--) - { - jp = pivots->ptr.p_int[j]; - if( jp!=j ) - { - ae_v_move(&work.ptr.p_double[0], 1, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,n-1)); - ae_v_move(&a->ptr.pp_double[0][j], a->stride, &a->ptr.pp_double[0][jp], a->stride, ae_v_len(0,n-1)); - ae_v_move(&a->ptr.pp_double[0][jp], a->stride, &work.ptr.p_double[0], 1, ae_v_len(0,n-1)); - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Matrix inverse -*************************************************************************/ -static ae_bool testrcondunit_rmatrixinvmat(/* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector pivots; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&pivots, 0, sizeof(pivots)); - ae_vector_init(&pivots, 0, DT_INT, _state, ae_true); - - rmatrixlu(a, n, n, &pivots, _state); - result = testrcondunit_rmatrixinvmatlu(a, &pivots, n, _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -reference RCond -*************************************************************************/ -static void testrcondunit_rmatrixrefrcond(/* Real */ ae_matrix* a, - ae_int_t n, - double* rc1, - double* rcinf, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix inva; - double nrm1a; - double nrminfa; - double nrm1inva; - double nrminfinva; - double v; - ae_int_t k; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&inva, 0, sizeof(inva)); - *rc1 = 0; - *rcinf = 0; - ae_matrix_init(&inva, 0, 0, DT_REAL, _state, ae_true); - - - /* - * inv A - */ - testrcondunit_rmatrixmakeacopy(a, n, n, &inva, _state); - if( !testrcondunit_rmatrixinvmat(&inva, n, _state) ) - { - *rc1 = (double)(0); - *rcinf = (double)(0); - ae_frame_leave(_state); - return; - } - - /* - * norm A - */ - nrm1a = (double)(0); - nrminfa = (double)(0); - for(k=0; k<=n-1; k++) - { - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_fabs(a->ptr.pp_double[i][k], _state); - } - nrm1a = ae_maxreal(nrm1a, v, _state); - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_fabs(a->ptr.pp_double[k][i], _state); - } - nrminfa = ae_maxreal(nrminfa, v, _state); - } - - /* - * norm inv A - */ - nrm1inva = (double)(0); - nrminfinva = (double)(0); - for(k=0; k<=n-1; k++) - { - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_fabs(inva.ptr.pp_double[i][k], _state); - } - nrm1inva = ae_maxreal(nrm1inva, v, _state); - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_fabs(inva.ptr.pp_double[k][i], _state); - } - nrminfinva = ae_maxreal(nrminfinva, v, _state); - } - - /* - * result - */ - *rc1 = nrm1inva*nrm1a; - *rcinf = nrminfinva*nrminfa; - ae_frame_leave(_state); -} - - -/************************************************************************* -Copy -*************************************************************************/ -static void testrcondunit_cmatrixmakeacopy(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* b, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(b); - - ae_matrix_set_length(b, m-1+1, n-1+1, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - b->ptr.pp_complex[i][j] = a->ptr.pp_complex[i][j]; - } - } -} - - -/************************************************************************* -Generate matrix with given condition number C (2-norm) -*************************************************************************/ -static void testrcondunit_cmatrixgenzero(/* Complex */ ae_matrix* a0, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - ae_matrix_set_length(a0, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a0->ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } -} - - -/************************************************************************* -triangular inverse -*************************************************************************/ -static ae_bool testrcondunit_cmatrixinvmattr(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunittriangular, - ae_state *_state) -{ - ae_frame _frame_block; - ae_bool nounit; - ae_int_t i; - ae_int_t j; - ae_complex v; - ae_complex ajj; - ae_vector t; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&t, 0, sizeof(t)); - ae_vector_init(&t, 0, DT_COMPLEX, _state, ae_true); - - result = ae_true; - ae_vector_set_length(&t, n-1+1, _state); - - /* - * Test the input parameters. - */ - nounit = !isunittriangular; - if( isupper ) - { - - /* - * Compute inverse of upper triangular matrix. - */ - for(j=0; j<=n-1; j++) - { - if( nounit ) - { - if( ae_c_eq_d(a->ptr.pp_complex[j][j],(double)(0)) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - a->ptr.pp_complex[j][j] = ae_c_d_div(1,a->ptr.pp_complex[j][j]); - ajj = ae_c_neg(a->ptr.pp_complex[j][j]); - } - else - { - ajj = ae_complex_from_i(-1); - } - - /* - * Compute elements 1:j-1 of j-th column. - */ - if( j>0 ) - { - ae_v_cmove(&t.ptr.p_complex[0], 1, &a->ptr.pp_complex[0][j], a->stride, "N", ae_v_len(0,j-1)); - for(i=0; i<=j-1; i++) - { - if( iptr.pp_complex[i][i+1], 1, "N", &t.ptr.p_complex[i+1], 1, "N", ae_v_len(i+1,j-1)); - } - else - { - v = ae_complex_from_i(0); - } - if( nounit ) - { - a->ptr.pp_complex[i][j] = ae_c_add(v,ae_c_mul(a->ptr.pp_complex[i][i],t.ptr.p_complex[i])); - } - else - { - a->ptr.pp_complex[i][j] = ae_c_add(v,t.ptr.p_complex[i]); - } - } - ae_v_cmulc(&a->ptr.pp_complex[0][j], a->stride, ae_v_len(0,j-1), ajj); - } - } - } - else - { - - /* - * Compute inverse of lower triangular matrix. - */ - for(j=n-1; j>=0; j--) - { - if( nounit ) - { - if( ae_c_eq_d(a->ptr.pp_complex[j][j],(double)(0)) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - a->ptr.pp_complex[j][j] = ae_c_d_div(1,a->ptr.pp_complex[j][j]); - ajj = ae_c_neg(a->ptr.pp_complex[j][j]); - } - else - { - ajj = ae_complex_from_i(-1); - } - if( jptr.pp_complex[j+1][j], a->stride, "N", ae_v_len(j+1,n-1)); - for(i=j+1; i<=n-1; i++) - { - if( i>j+1 ) - { - v = ae_v_cdotproduct(&a->ptr.pp_complex[i][j+1], 1, "N", &t.ptr.p_complex[j+1], 1, "N", ae_v_len(j+1,i-1)); - } - else - { - v = ae_complex_from_i(0); - } - if( nounit ) - { - a->ptr.pp_complex[i][j] = ae_c_add(v,ae_c_mul(a->ptr.pp_complex[i][i],t.ptr.p_complex[i])); - } - else - { - a->ptr.pp_complex[i][j] = ae_c_add(v,t.ptr.p_complex[i]); - } - } - ae_v_cmulc(&a->ptr.pp_complex[j+1][j], a->stride, ae_v_len(j+1,n-1), ajj); - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -LU inverse -*************************************************************************/ -static ae_bool testrcondunit_cmatrixinvmatlu(/* Complex */ ae_matrix* a, - /* Integer */ ae_vector* pivots, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector work; - ae_int_t i; - ae_int_t j; - ae_int_t jp; - ae_complex v; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&work, 0, sizeof(work)); - ae_vector_init(&work, 0, DT_COMPLEX, _state, ae_true); - - result = ae_true; - - /* - * Quick return if possible - */ - if( n==0 ) - { - ae_frame_leave(_state); - return result; - } - ae_vector_set_length(&work, n-1+1, _state); - - /* - * Form inv(U) - */ - if( !testrcondunit_cmatrixinvmattr(a, n, ae_true, ae_false, _state) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - - /* - * Solve the equation inv(A)*L = inv(U) for inv(A). - */ - for(j=n-1; j>=0; j--) - { - - /* - * Copy current column of L to WORK and replace with zeros. - */ - for(i=j+1; i<=n-1; i++) - { - work.ptr.p_complex[i] = a->ptr.pp_complex[i][j]; - a->ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - - /* - * Compute current column of inv(A). - */ - if( jptr.pp_complex[i][j+1], 1, "N", &work.ptr.p_complex[j+1], 1, "N", ae_v_len(j+1,n-1)); - a->ptr.pp_complex[i][j] = ae_c_sub(a->ptr.pp_complex[i][j],v); - } - } - } - - /* - * Apply column interchanges. - */ - for(j=n-2; j>=0; j--) - { - jp = pivots->ptr.p_int[j]; - if( jp!=j ) - { - ae_v_cmove(&work.ptr.p_complex[0], 1, &a->ptr.pp_complex[0][j], a->stride, "N", ae_v_len(0,n-1)); - ae_v_cmove(&a->ptr.pp_complex[0][j], a->stride, &a->ptr.pp_complex[0][jp], a->stride, "N", ae_v_len(0,n-1)); - ae_v_cmove(&a->ptr.pp_complex[0][jp], a->stride, &work.ptr.p_complex[0], 1, "N", ae_v_len(0,n-1)); - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Matrix inverse -*************************************************************************/ -static ae_bool testrcondunit_cmatrixinvmat(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector pivots; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&pivots, 0, sizeof(pivots)); - ae_vector_init(&pivots, 0, DT_INT, _state, ae_true); - - cmatrixlu(a, n, n, &pivots, _state); - result = testrcondunit_cmatrixinvmatlu(a, &pivots, n, _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -reference RCond -*************************************************************************/ -static void testrcondunit_cmatrixrefrcond(/* Complex */ ae_matrix* a, - ae_int_t n, - double* rc1, - double* rcinf, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix inva; - double nrm1a; - double nrminfa; - double nrm1inva; - double nrminfinva; - double v; - ae_int_t k; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&inva, 0, sizeof(inva)); - *rc1 = 0; - *rcinf = 0; - ae_matrix_init(&inva, 0, 0, DT_COMPLEX, _state, ae_true); - - - /* - * inv A - */ - testrcondunit_cmatrixmakeacopy(a, n, n, &inva, _state); - if( !testrcondunit_cmatrixinvmat(&inva, n, _state) ) - { - *rc1 = (double)(0); - *rcinf = (double)(0); - ae_frame_leave(_state); - return; - } - - /* - * norm A - */ - nrm1a = (double)(0); - nrminfa = (double)(0); - for(k=0; k<=n-1; k++) - { - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_c_abs(a->ptr.pp_complex[i][k], _state); - } - nrm1a = ae_maxreal(nrm1a, v, _state); - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_c_abs(a->ptr.pp_complex[k][i], _state); - } - nrminfa = ae_maxreal(nrminfa, v, _state); - } - - /* - * norm inv A - */ - nrm1inva = (double)(0); - nrminfinva = (double)(0); - for(k=0; k<=n-1; k++) - { - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_c_abs(inva.ptr.pp_complex[i][k], _state); - } - nrm1inva = ae_maxreal(nrm1inva, v, _state); - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_c_abs(inva.ptr.pp_complex[k][i], _state); - } - nrminfinva = ae_maxreal(nrminfinva, v, _state); - } - - /* - * result - */ - *rc1 = nrm1inva*nrm1a; - *rcinf = nrminfinva*nrminfa; - ae_frame_leave(_state); -} - - -/************************************************************************* -Returns True for successful test, False - for failed test -*************************************************************************/ -static ae_bool testrcondunit_testrmatrixtrrcond(ae_int_t maxn, - ae_int_t passcount, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix ea; - ae_vector p; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t j1; - ae_int_t j2; - ae_int_t pass; - ae_bool err50; - ae_bool err90; - ae_bool errspec; - ae_bool errless; - double erc1; - double ercinf; - ae_vector q50; - ae_vector q90; - double v; - ae_bool isupper; - ae_bool isunit; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&ea, 0, sizeof(ea)); - memset(&p, 0, sizeof(p)); - memset(&q50, 0, sizeof(q50)); - memset(&q90, 0, sizeof(q90)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ea, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - ae_vector_init(&q50, 0, DT_REAL, _state, ae_true); - ae_vector_init(&q90, 0, DT_REAL, _state, ae_true); - - err50 = ae_false; - err90 = ae_false; - errless = ae_false; - errspec = ae_false; - ae_vector_set_length(&q50, 2, _state); - ae_vector_set_length(&q90, 2, _state); - for(n=1; n<=maxn; n++) - { - - /* - * special test for zero matrix - */ - testrcondunit_rmatrixgenzero(&a, n, _state); - errspec = errspec||ae_fp_neq(rmatrixtrrcond1(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0)); - errspec = errspec||ae_fp_neq(rmatrixtrrcondinf(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0)); - - /* - * general test - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=1; i++) - { - q50.ptr.p_double[i] = (double)(0); - q90.ptr.p_double[i] = (double)(0); - } - for(pass=1; pass<=passcount; pass++) - { - isupper = ae_fp_greater(ae_randomreal(_state),0.5); - isunit = ae_fp_greater(ae_randomreal(_state),0.5); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = ae_randomreal(_state)-0.5; - } - } - for(i=0; i<=n-1; i++) - { - a.ptr.pp_double[i][i] = 1+ae_randomreal(_state); - } - testrcondunit_rmatrixmakeacopy(&a, n, n, &ea, _state); - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j1 = 0; - j2 = i-1; - } - else - { - j1 = i+1; - j2 = n-1; - } - for(j=j1; j<=j2; j++) - { - ea.ptr.pp_double[i][j] = (double)(0); - } - if( isunit ) - { - ea.ptr.pp_double[i][i] = (double)(1); - } - } - testrcondunit_rmatrixrefrcond(&ea, n, &erc1, &ercinf, _state); - - /* - * 1-norm - */ - v = 1/rmatrixtrrcond1(&a, n, isupper, isunit, _state); - if( ae_fp_greater_eq(v,testrcondunit_threshold50*erc1) ) - { - q50.ptr.p_double[0] = q50.ptr.p_double[0]+(double)1/(double)passcount; - } - if( ae_fp_greater_eq(v,testrcondunit_threshold90*erc1) ) - { - q90.ptr.p_double[0] = q90.ptr.p_double[0]+(double)1/(double)passcount; - } - errless = errless||ae_fp_greater(v,erc1*1.001); - - /* - * Inf-norm - */ - v = 1/rmatrixtrrcondinf(&a, n, isupper, isunit, _state); - if( ae_fp_greater_eq(v,testrcondunit_threshold50*ercinf) ) - { - q50.ptr.p_double[1] = q50.ptr.p_double[1]+(double)1/(double)passcount; - } - if( ae_fp_greater_eq(v,testrcondunit_threshold90*ercinf) ) - { - q90.ptr.p_double[1] = q90.ptr.p_double[1]+(double)1/(double)passcount; - } - errless = errless||ae_fp_greater(v,ercinf*1.001); - } - for(i=0; i<=1; i++) - { - err50 = err50||ae_fp_less(q50.ptr.p_double[i],0.50); - err90 = err90||ae_fp_less(q90.ptr.p_double[i],0.90); - } - - /* - * degenerate matrix test - */ - if( n>=3 ) - { - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - a.ptr.pp_double[0][0] = (double)(1); - a.ptr.pp_double[n-1][n-1] = (double)(1); - errspec = errspec||ae_fp_neq(rmatrixtrrcond1(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0)); - errspec = errspec||ae_fp_neq(rmatrixtrrcondinf(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0)); - } - - /* - * near-degenerate matrix test - */ - if( n>=2 ) - { - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - for(i=0; i<=n-1; i++) - { - a.ptr.pp_double[i][i] = (double)(1); - } - i = ae_randominteger(n, _state); - a.ptr.pp_double[i][i] = 0.1*ae_maxrealnumber; - errspec = errspec||ae_fp_neq(rmatrixtrrcond1(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0)); - errspec = errspec||ae_fp_neq(rmatrixtrrcondinf(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0)); - } - } - - /* - * report - */ - result = !(((err50||err90)||errless)||errspec); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Returns True for successful test, False - for failed test -*************************************************************************/ -static ae_bool testrcondunit_testcmatrixtrrcond(ae_int_t maxn, - ae_int_t passcount, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix ea; - ae_vector p; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t j1; - ae_int_t j2; - ae_int_t pass; - ae_bool err50; - ae_bool err90; - ae_bool errspec; - ae_bool errless; - double erc1; - double ercinf; - ae_vector q50; - ae_vector q90; - double v; - ae_bool isupper; - ae_bool isunit; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&ea, 0, sizeof(ea)); - memset(&p, 0, sizeof(p)); - memset(&q50, 0, sizeof(q50)); - memset(&q90, 0, sizeof(q90)); - ae_matrix_init(&a, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&ea, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - ae_vector_init(&q50, 0, DT_REAL, _state, ae_true); - ae_vector_init(&q90, 0, DT_REAL, _state, ae_true); - - err50 = ae_false; - err90 = ae_false; - errless = ae_false; - errspec = ae_false; - ae_vector_set_length(&q50, 2, _state); - ae_vector_set_length(&q90, 2, _state); - for(n=1; n<=maxn; n++) - { - - /* - * special test for zero matrix - */ - testrcondunit_cmatrixgenzero(&a, n, _state); - errspec = errspec||ae_fp_neq(cmatrixtrrcond1(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0)); - errspec = errspec||ae_fp_neq(cmatrixtrrcondinf(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0)); - - /* - * general test - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=1; i++) - { - q50.ptr.p_double[i] = (double)(0); - q90.ptr.p_double[i] = (double)(0); - } - for(pass=1; pass<=passcount; pass++) - { - isupper = ae_fp_greater(ae_randomreal(_state),0.5); - isunit = ae_fp_greater(ae_randomreal(_state),0.5); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j].x = ae_randomreal(_state)-0.5; - a.ptr.pp_complex[i][j].y = ae_randomreal(_state)-0.5; - } - } - for(i=0; i<=n-1; i++) - { - a.ptr.pp_complex[i][i].x = 1+ae_randomreal(_state); - a.ptr.pp_complex[i][i].y = 1+ae_randomreal(_state); - } - testrcondunit_cmatrixmakeacopy(&a, n, n, &ea, _state); - for(i=0; i<=n-1; i++) - { - if( isupper ) - { - j1 = 0; - j2 = i-1; - } - else - { - j1 = i+1; - j2 = n-1; - } - for(j=j1; j<=j2; j++) - { - ea.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - if( isunit ) - { - ea.ptr.pp_complex[i][i] = ae_complex_from_i(1); - } - } - testrcondunit_cmatrixrefrcond(&ea, n, &erc1, &ercinf, _state); - - /* - * 1-norm - */ - v = 1/cmatrixtrrcond1(&a, n, isupper, isunit, _state); - if( ae_fp_greater_eq(v,testrcondunit_threshold50*erc1) ) - { - q50.ptr.p_double[0] = q50.ptr.p_double[0]+(double)1/(double)passcount; - } - if( ae_fp_greater_eq(v,testrcondunit_threshold90*erc1) ) - { - q90.ptr.p_double[0] = q90.ptr.p_double[0]+(double)1/(double)passcount; - } - errless = errless||ae_fp_greater(v,erc1*1.001); - - /* - * Inf-norm - */ - v = 1/cmatrixtrrcondinf(&a, n, isupper, isunit, _state); - if( ae_fp_greater_eq(v,testrcondunit_threshold50*ercinf) ) - { - q50.ptr.p_double[1] = q50.ptr.p_double[1]+(double)1/(double)passcount; - } - if( ae_fp_greater_eq(v,testrcondunit_threshold90*ercinf) ) - { - q90.ptr.p_double[1] = q90.ptr.p_double[1]+(double)1/(double)passcount; - } - errless = errless||ae_fp_greater(v,ercinf*1.001); - } - for(i=0; i<=1; i++) - { - err50 = err50||ae_fp_less(q50.ptr.p_double[i],0.50); - err90 = err90||ae_fp_less(q90.ptr.p_double[i],0.90); - } - - /* - * degenerate matrix test - */ - if( n>=3 ) - { - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j] = ae_complex_from_d(0.0); - } - } - a.ptr.pp_complex[0][0] = ae_complex_from_i(1); - a.ptr.pp_complex[n-1][n-1] = ae_complex_from_i(1); - errspec = errspec||ae_fp_neq(cmatrixtrrcond1(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0)); - errspec = errspec||ae_fp_neq(cmatrixtrrcondinf(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0)); - } - - /* - * near-degenerate matrix test - */ - if( n>=2 ) - { - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j] = ae_complex_from_d(0.0); - } - } - for(i=0; i<=n-1; i++) - { - a.ptr.pp_complex[i][i] = ae_complex_from_i(1); - } - i = ae_randominteger(n, _state); - a.ptr.pp_complex[i][i] = ae_complex_from_d(0.1*ae_maxrealnumber); - errspec = errspec||ae_fp_neq(cmatrixtrrcond1(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0)); - errspec = errspec||ae_fp_neq(cmatrixtrrcondinf(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0)); - } - } - - /* - * report - */ - result = !(((err50||err90)||errless)||errspec); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Returns True for successful test, False - for failed test -*************************************************************************/ -static ae_bool testrcondunit_testrmatrixrcond(ae_int_t maxn, - ae_int_t passcount, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix lua; - ae_vector p; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t pass; - ae_bool err50; - ae_bool err90; - ae_bool errspec; - ae_bool errless; - double erc1; - double ercinf; - ae_vector q50; - ae_vector q90; - double v; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&lua, 0, sizeof(lua)); - memset(&p, 0, sizeof(p)); - memset(&q50, 0, sizeof(q50)); - memset(&q90, 0, sizeof(q90)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&lua, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - ae_vector_init(&q50, 0, DT_REAL, _state, ae_true); - ae_vector_init(&q90, 0, DT_REAL, _state, ae_true); - - err50 = ae_false; - err90 = ae_false; - errless = ae_false; - errspec = ae_false; - ae_vector_set_length(&q50, 3+1, _state); - ae_vector_set_length(&q90, 3+1, _state); - for(n=1; n<=maxn; n++) - { - - /* - * special test for zero matrix - */ - testrcondunit_rmatrixgenzero(&a, n, _state); - testrcondunit_rmatrixmakeacopy(&a, n, n, &lua, _state); - rmatrixlu(&lua, n, n, &p, _state); - errspec = errspec||ae_fp_neq(rmatrixrcond1(&a, n, _state),(double)(0)); - errspec = errspec||ae_fp_neq(rmatrixrcondinf(&a, n, _state),(double)(0)); - errspec = errspec||ae_fp_neq(rmatrixlurcond1(&lua, n, _state),(double)(0)); - errspec = errspec||ae_fp_neq(rmatrixlurcondinf(&lua, n, _state),(double)(0)); - - /* - * general test - */ - ae_matrix_set_length(&a, n-1+1, n-1+1, _state); - for(i=0; i<=3; i++) - { - q50.ptr.p_double[i] = (double)(0); - q90.ptr.p_double[i] = (double)(0); - } - for(pass=1; pass<=passcount; pass++) - { - rmatrixrndcond(n, ae_exp(ae_randomreal(_state)*ae_log((double)(1000), _state), _state), &a, _state); - testrcondunit_rmatrixmakeacopy(&a, n, n, &lua, _state); - rmatrixlu(&lua, n, n, &p, _state); - testrcondunit_rmatrixrefrcond(&a, n, &erc1, &ercinf, _state); - - /* - * 1-norm, normal - */ - v = 1/rmatrixrcond1(&a, n, _state); - if( ae_fp_greater_eq(v,testrcondunit_threshold50*erc1) ) - { - q50.ptr.p_double[0] = q50.ptr.p_double[0]+(double)1/(double)passcount; - } - if( ae_fp_greater_eq(v,testrcondunit_threshold90*erc1) ) - { - q90.ptr.p_double[0] = q90.ptr.p_double[0]+(double)1/(double)passcount; - } - errless = errless||ae_fp_greater(v,erc1*1.001); - - /* - * 1-norm, LU - */ - v = 1/rmatrixlurcond1(&lua, n, _state); - if( ae_fp_greater_eq(v,testrcondunit_threshold50*erc1) ) - { - q50.ptr.p_double[1] = q50.ptr.p_double[1]+(double)1/(double)passcount; - } - if( ae_fp_greater_eq(v,testrcondunit_threshold90*erc1) ) - { - q90.ptr.p_double[1] = q90.ptr.p_double[1]+(double)1/(double)passcount; - } - errless = errless||ae_fp_greater(v,erc1*1.001); - - /* - * Inf-norm, normal - */ - v = 1/rmatrixrcondinf(&a, n, _state); - if( ae_fp_greater_eq(v,testrcondunit_threshold50*ercinf) ) - { - q50.ptr.p_double[2] = q50.ptr.p_double[2]+(double)1/(double)passcount; - } - if( ae_fp_greater_eq(v,testrcondunit_threshold90*ercinf) ) - { - q90.ptr.p_double[2] = q90.ptr.p_double[2]+(double)1/(double)passcount; - } - errless = errless||ae_fp_greater(v,ercinf*1.001); - - /* - * Inf-norm, LU - */ - v = 1/rmatrixlurcondinf(&lua, n, _state); - if( ae_fp_greater_eq(v,testrcondunit_threshold50*ercinf) ) - { - q50.ptr.p_double[3] = q50.ptr.p_double[3]+(double)1/(double)passcount; - } - if( ae_fp_greater_eq(v,testrcondunit_threshold90*ercinf) ) - { - q90.ptr.p_double[3] = q90.ptr.p_double[3]+(double)1/(double)passcount; - } - errless = errless||ae_fp_greater(v,ercinf*1.001); - } - for(i=0; i<=3; i++) - { - err50 = err50||ae_fp_less(q50.ptr.p_double[i],0.50); - err90 = err90||ae_fp_less(q90.ptr.p_double[i],0.90); - } - - /* - * degenerate matrix test - */ - if( n>=3 ) - { - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - a.ptr.pp_double[0][0] = (double)(1); - a.ptr.pp_double[n-1][n-1] = (double)(1); - errspec = errspec||ae_fp_neq(rmatrixrcond1(&a, n, _state),(double)(0)); - errspec = errspec||ae_fp_neq(rmatrixrcondinf(&a, n, _state),(double)(0)); - errspec = errspec||ae_fp_neq(rmatrixlurcond1(&a, n, _state),(double)(0)); - errspec = errspec||ae_fp_neq(rmatrixlurcondinf(&a, n, _state),(double)(0)); - } - - /* - * near-degenerate matrix test - */ - if( n>=2 ) - { - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - for(i=0; i<=n-1; i++) - { - a.ptr.pp_double[i][i] = (double)(1); - } - i = ae_randominteger(n, _state); - a.ptr.pp_double[i][i] = 0.1*ae_maxrealnumber; - errspec = errspec||ae_fp_neq(rmatrixrcond1(&a, n, _state),(double)(0)); - errspec = errspec||ae_fp_neq(rmatrixrcondinf(&a, n, _state),(double)(0)); - errspec = errspec||ae_fp_neq(rmatrixlurcond1(&a, n, _state),(double)(0)); - errspec = errspec||ae_fp_neq(rmatrixlurcondinf(&a, n, _state),(double)(0)); - } - } - - /* - * report - */ - result = !(((err50||err90)||errless)||errspec); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Returns True for successful test, False - for failed test -*************************************************************************/ -static ae_bool testrcondunit_testspdmatrixrcond(ae_int_t maxn, - ae_int_t passcount, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix cha; - ae_vector p; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t pass; - ae_bool err50; - ae_bool err90; - ae_bool errspec; - ae_bool errless; - ae_bool isupper; - double erc1; - double ercinf; - ae_vector q50; - ae_vector q90; - double v; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&cha, 0, sizeof(cha)); - memset(&p, 0, sizeof(p)); - memset(&q50, 0, sizeof(q50)); - memset(&q90, 0, sizeof(q90)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&cha, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - ae_vector_init(&q50, 0, DT_REAL, _state, ae_true); - ae_vector_init(&q90, 0, DT_REAL, _state, ae_true); - - err50 = ae_false; - err90 = ae_false; - errless = ae_false; - errspec = ae_false; - ae_vector_set_length(&q50, 2, _state); - ae_vector_set_length(&q90, 2, _state); - for(n=1; n<=maxn; n++) - { - isupper = ae_fp_greater(ae_randomreal(_state),0.5); - - /* - * general test - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=1; i++) - { - q50.ptr.p_double[i] = (double)(0); - q90.ptr.p_double[i] = (double)(0); - } - for(pass=1; pass<=passcount; pass++) - { - spdmatrixrndcond(n, ae_exp(ae_randomreal(_state)*ae_log((double)(1000), _state), _state), &a, _state); - testrcondunit_rmatrixrefrcond(&a, n, &erc1, &ercinf, _state); - testrcondunit_rmatrixdrophalf(&a, n, isupper, _state); - testrcondunit_rmatrixmakeacopy(&a, n, n, &cha, _state); - spdmatrixcholesky(&cha, n, isupper, _state); - - /* - * normal - */ - v = 1/spdmatrixrcond(&a, n, isupper, _state); - if( ae_fp_greater_eq(v,testrcondunit_threshold50*erc1) ) - { - q50.ptr.p_double[0] = q50.ptr.p_double[0]+(double)1/(double)passcount; - } - if( ae_fp_greater_eq(v,testrcondunit_threshold90*erc1) ) - { - q90.ptr.p_double[0] = q90.ptr.p_double[0]+(double)1/(double)passcount; - } - errless = errless||ae_fp_greater(v,erc1*1.001); - - /* - * Cholesky - */ - v = 1/spdmatrixcholeskyrcond(&cha, n, isupper, _state); - if( ae_fp_greater_eq(v,testrcondunit_threshold50*erc1) ) - { - q50.ptr.p_double[1] = q50.ptr.p_double[1]+(double)1/(double)passcount; - } - if( ae_fp_greater_eq(v,testrcondunit_threshold90*erc1) ) - { - q90.ptr.p_double[1] = q90.ptr.p_double[1]+(double)1/(double)passcount; - } - errless = errless||ae_fp_greater(v,erc1*1.001); - } - for(i=0; i<=1; i++) - { - err50 = err50||ae_fp_less(q50.ptr.p_double[i],0.50); - err90 = err90||ae_fp_less(q90.ptr.p_double[i],0.90); - } - - /* - * degenerate matrix test - */ - if( n>=3 ) - { - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - a.ptr.pp_double[0][0] = (double)(1); - a.ptr.pp_double[n-1][n-1] = (double)(1); - errspec = errspec||ae_fp_neq(spdmatrixrcond(&a, n, isupper, _state),(double)(-1)); - errspec = errspec||ae_fp_neq(spdmatrixcholeskyrcond(&a, n, isupper, _state),(double)(0)); - } - - /* - * near-degenerate matrix test - */ - if( n>=2 ) - { - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - for(i=0; i<=n-1; i++) - { - a.ptr.pp_double[i][i] = (double)(1); - } - i = ae_randominteger(n, _state); - a.ptr.pp_double[i][i] = 0.1*ae_maxrealnumber; - errspec = errspec||ae_fp_neq(spdmatrixrcond(&a, n, isupper, _state),(double)(0)); - errspec = errspec||ae_fp_neq(spdmatrixcholeskyrcond(&a, n, isupper, _state),(double)(0)); - } - } - - /* - * report - */ - result = !(((err50||err90)||errless)||errspec); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Returns True for successful test, False - for failed test -*************************************************************************/ -static ae_bool testrcondunit_testcmatrixrcond(ae_int_t maxn, - ae_int_t passcount, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix lua; - ae_vector p; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t pass; - ae_bool err50; - ae_bool err90; - ae_bool errless; - ae_bool errspec; - double erc1; - double ercinf; - ae_vector q50; - ae_vector q90; - double v; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&lua, 0, sizeof(lua)); - memset(&p, 0, sizeof(p)); - memset(&q50, 0, sizeof(q50)); - memset(&q90, 0, sizeof(q90)); - ae_matrix_init(&a, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&lua, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - ae_vector_init(&q50, 0, DT_REAL, _state, ae_true); - ae_vector_init(&q90, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&q50, 3+1, _state); - ae_vector_set_length(&q90, 3+1, _state); - err50 = ae_false; - err90 = ae_false; - errless = ae_false; - errspec = ae_false; - - /* - * process - */ - for(n=1; n<=maxn; n++) - { - - /* - * special test for zero matrix - */ - testrcondunit_cmatrixgenzero(&a, n, _state); - testrcondunit_cmatrixmakeacopy(&a, n, n, &lua, _state); - cmatrixlu(&lua, n, n, &p, _state); - errspec = errspec||ae_fp_neq(cmatrixrcond1(&a, n, _state),(double)(0)); - errspec = errspec||ae_fp_neq(cmatrixrcondinf(&a, n, _state),(double)(0)); - errspec = errspec||ae_fp_neq(cmatrixlurcond1(&lua, n, _state),(double)(0)); - errspec = errspec||ae_fp_neq(cmatrixlurcondinf(&lua, n, _state),(double)(0)); - - /* - * general test - */ - ae_matrix_set_length(&a, n-1+1, n-1+1, _state); - for(i=0; i<=3; i++) - { - q50.ptr.p_double[i] = (double)(0); - q90.ptr.p_double[i] = (double)(0); - } - for(pass=1; pass<=passcount; pass++) - { - cmatrixrndcond(n, ae_exp(ae_randomreal(_state)*ae_log((double)(1000), _state), _state), &a, _state); - testrcondunit_cmatrixmakeacopy(&a, n, n, &lua, _state); - cmatrixlu(&lua, n, n, &p, _state); - testrcondunit_cmatrixrefrcond(&a, n, &erc1, &ercinf, _state); - - /* - * 1-norm, normal - */ - v = 1/cmatrixrcond1(&a, n, _state); - if( ae_fp_greater_eq(v,testrcondunit_threshold50*erc1) ) - { - q50.ptr.p_double[0] = q50.ptr.p_double[0]+(double)1/(double)passcount; - } - if( ae_fp_greater_eq(v,testrcondunit_threshold90*erc1) ) - { - q90.ptr.p_double[0] = q90.ptr.p_double[0]+(double)1/(double)passcount; - } - errless = errless||ae_fp_greater(v,erc1*1.001); - - /* - * 1-norm, LU - */ - v = 1/cmatrixlurcond1(&lua, n, _state); - if( ae_fp_greater_eq(v,testrcondunit_threshold50*erc1) ) - { - q50.ptr.p_double[1] = q50.ptr.p_double[1]+(double)1/(double)passcount; - } - if( ae_fp_greater_eq(v,testrcondunit_threshold90*erc1) ) - { - q90.ptr.p_double[1] = q90.ptr.p_double[1]+(double)1/(double)passcount; - } - errless = errless||ae_fp_greater(v,erc1*1.001); - - /* - * Inf-norm, normal - */ - v = 1/cmatrixrcondinf(&a, n, _state); - if( ae_fp_greater_eq(v,testrcondunit_threshold50*ercinf) ) - { - q50.ptr.p_double[2] = q50.ptr.p_double[2]+(double)1/(double)passcount; - } - if( ae_fp_greater_eq(v,testrcondunit_threshold90*ercinf) ) - { - q90.ptr.p_double[2] = q90.ptr.p_double[2]+(double)1/(double)passcount; - } - errless = errless||ae_fp_greater(v,ercinf*1.001); - - /* - * Inf-norm, LU - */ - v = 1/cmatrixlurcondinf(&lua, n, _state); - if( ae_fp_greater_eq(v,testrcondunit_threshold50*ercinf) ) - { - q50.ptr.p_double[3] = q50.ptr.p_double[3]+(double)1/(double)passcount; - } - if( ae_fp_greater_eq(v,testrcondunit_threshold90*ercinf) ) - { - q90.ptr.p_double[3] = q90.ptr.p_double[3]+(double)1/(double)passcount; - } - errless = errless||ae_fp_greater(v,ercinf*1.001); - } - for(i=0; i<=3; i++) - { - err50 = err50||ae_fp_less(q50.ptr.p_double[i],0.50); - err90 = err90||ae_fp_less(q90.ptr.p_double[i],0.90); - } - - /* - * degenerate matrix test - */ - if( n>=3 ) - { - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j] = ae_complex_from_d(0.0); - } - } - a.ptr.pp_complex[0][0] = ae_complex_from_i(1); - a.ptr.pp_complex[n-1][n-1] = ae_complex_from_i(1); - errspec = errspec||ae_fp_neq(cmatrixrcond1(&a, n, _state),(double)(0)); - errspec = errspec||ae_fp_neq(cmatrixrcondinf(&a, n, _state),(double)(0)); - errspec = errspec||ae_fp_neq(cmatrixlurcond1(&a, n, _state),(double)(0)); - errspec = errspec||ae_fp_neq(cmatrixlurcondinf(&a, n, _state),(double)(0)); - } - - /* - * near-degenerate matrix test - */ - if( n>=2 ) - { - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j] = ae_complex_from_d(0.0); - } - } - for(i=0; i<=n-1; i++) - { - a.ptr.pp_complex[i][i] = ae_complex_from_i(1); - } - i = ae_randominteger(n, _state); - a.ptr.pp_complex[i][i] = ae_complex_from_d(0.1*ae_maxrealnumber); - errspec = errspec||ae_fp_neq(cmatrixrcond1(&a, n, _state),(double)(0)); - errspec = errspec||ae_fp_neq(cmatrixrcondinf(&a, n, _state),(double)(0)); - errspec = errspec||ae_fp_neq(cmatrixlurcond1(&a, n, _state),(double)(0)); - errspec = errspec||ae_fp_neq(cmatrixlurcondinf(&a, n, _state),(double)(0)); - } - } - - /* - * report - */ - result = !(((err50||err90)||errless)||errspec); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Returns True for successful test, False - for failed test -*************************************************************************/ -static ae_bool testrcondunit_testhpdmatrixrcond(ae_int_t maxn, - ae_int_t passcount, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix cha; - ae_vector p; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t pass; - ae_bool err50; - ae_bool err90; - ae_bool errspec; - ae_bool errless; - ae_bool isupper; - double erc1; - double ercinf; - ae_vector q50; - ae_vector q90; - double v; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&cha, 0, sizeof(cha)); - memset(&p, 0, sizeof(p)); - memset(&q50, 0, sizeof(q50)); - memset(&q90, 0, sizeof(q90)); - ae_matrix_init(&a, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&cha, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - ae_vector_init(&q50, 0, DT_REAL, _state, ae_true); - ae_vector_init(&q90, 0, DT_REAL, _state, ae_true); - - err50 = ae_false; - err90 = ae_false; - errless = ae_false; - errspec = ae_false; - ae_vector_set_length(&q50, 2, _state); - ae_vector_set_length(&q90, 2, _state); - for(n=1; n<=maxn; n++) - { - isupper = ae_fp_greater(ae_randomreal(_state),0.5); - - /* - * general test - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=1; i++) - { - q50.ptr.p_double[i] = (double)(0); - q90.ptr.p_double[i] = (double)(0); - } - for(pass=1; pass<=passcount; pass++) - { - hpdmatrixrndcond(n, ae_exp(ae_randomreal(_state)*ae_log((double)(1000), _state), _state), &a, _state); - testrcondunit_cmatrixrefrcond(&a, n, &erc1, &ercinf, _state); - testrcondunit_cmatrixdrophalf(&a, n, isupper, _state); - testrcondunit_cmatrixmakeacopy(&a, n, n, &cha, _state); - hpdmatrixcholesky(&cha, n, isupper, _state); - - /* - * normal - */ - v = 1/hpdmatrixrcond(&a, n, isupper, _state); - if( ae_fp_greater_eq(v,testrcondunit_threshold50*erc1) ) - { - q50.ptr.p_double[0] = q50.ptr.p_double[0]+(double)1/(double)passcount; - } - if( ae_fp_greater_eq(v,testrcondunit_threshold90*erc1) ) - { - q90.ptr.p_double[0] = q90.ptr.p_double[0]+(double)1/(double)passcount; - } - errless = errless||ae_fp_greater(v,erc1*1.001); - - /* - * Cholesky - */ - v = 1/hpdmatrixcholeskyrcond(&cha, n, isupper, _state); - if( ae_fp_greater_eq(v,testrcondunit_threshold50*erc1) ) - { - q50.ptr.p_double[1] = q50.ptr.p_double[1]+(double)1/(double)passcount; - } - if( ae_fp_greater_eq(v,testrcondunit_threshold90*erc1) ) - { - q90.ptr.p_double[1] = q90.ptr.p_double[1]+(double)1/(double)passcount; - } - errless = errless||ae_fp_greater(v,erc1*1.001); - } - for(i=0; i<=1; i++) - { - err50 = err50||ae_fp_less(q50.ptr.p_double[i],0.50); - err90 = err90||ae_fp_less(q90.ptr.p_double[i],0.90); - } - - /* - * degenerate matrix test - */ - if( n>=3 ) - { - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j] = ae_complex_from_d(0.0); - } - } - a.ptr.pp_complex[0][0] = ae_complex_from_i(1); - a.ptr.pp_complex[n-1][n-1] = ae_complex_from_i(1); - errspec = errspec||ae_fp_neq(hpdmatrixrcond(&a, n, isupper, _state),(double)(-1)); - errspec = errspec||ae_fp_neq(hpdmatrixcholeskyrcond(&a, n, isupper, _state),(double)(0)); - } - - /* - * near-degenerate matrix test - */ - if( n>=2 ) - { - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j] = ae_complex_from_d(0.0); - } - } - for(i=0; i<=n-1; i++) - { - a.ptr.pp_complex[i][i] = ae_complex_from_i(1); - } - i = ae_randominteger(n, _state); - a.ptr.pp_complex[i][i] = ae_complex_from_d(0.1*ae_maxrealnumber); - errspec = errspec||ae_fp_neq(hpdmatrixrcond(&a, n, isupper, _state),(double)(0)); - errspec = errspec||ae_fp_neq(hpdmatrixcholeskyrcond(&a, n, isupper, _state),(double)(0)); - } - } - - /* - * report - */ - result = !(((err50||err90)||errless)||errspec); - ae_frame_leave(_state); - return result; -} - - - -static void testmatinvunit_rmatrixmakeacopy(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* b, - ae_state *_state); -static void testmatinvunit_cmatrixmakeacopy(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* b, - ae_state *_state); -static ae_bool testmatinvunit_rmatrixcheckinverse(/* Real */ ae_matrix* a, - /* Real */ ae_matrix* inva, - ae_int_t n, - double threshold, - ae_int_t info, - matinvreport* rep, - ae_state *_state); -static ae_bool testmatinvunit_spdmatrixcheckinverse(/* Real */ ae_matrix* a, - /* Real */ ae_matrix* inva, - ae_bool isupper, - ae_int_t n, - double threshold, - ae_int_t info, - matinvreport* rep, - ae_state *_state); -static ae_bool testmatinvunit_hpdmatrixcheckinverse(/* Complex */ ae_matrix* a, - /* Complex */ ae_matrix* inva, - ae_bool isupper, - ae_int_t n, - double threshold, - ae_int_t info, - matinvreport* rep, - ae_state *_state); -static ae_bool testmatinvunit_rmatrixcheckinversesingular(/* Real */ ae_matrix* inva, - ae_int_t n, - double threshold, - ae_int_t info, - matinvreport* rep, - ae_state *_state); -static ae_bool testmatinvunit_cmatrixcheckinverse(/* Complex */ ae_matrix* a, - /* Complex */ ae_matrix* inva, - ae_int_t n, - double threshold, - ae_int_t info, - matinvreport* rep, - ae_state *_state); -static ae_bool testmatinvunit_cmatrixcheckinversesingular(/* Complex */ ae_matrix* inva, - ae_int_t n, - double threshold, - ae_int_t info, - matinvreport* rep, - ae_state *_state); -static void testmatinvunit_rmatrixdrophalf(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool droplower, - ae_state *_state); -static void testmatinvunit_cmatrixdrophalf(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool droplower, - ae_state *_state); -static void testmatinvunit_testrtrinv(ae_int_t minn, - ae_int_t maxn, - ae_int_t passcount, - double threshold, - ae_bool* rtrerrors, - ae_state *_state); -static void testmatinvunit_testctrinv(ae_int_t minn, - ae_int_t maxn, - ae_int_t passcount, - double threshold, - ae_bool* ctrerrors, - ae_state *_state); -static void testmatinvunit_testrinv(ae_int_t minn, - ae_int_t maxn, - ae_int_t passcount, - double threshold, - ae_bool* rerrors, - ae_state *_state); -static void testmatinvunit_testcinv(ae_int_t minn, - ae_int_t maxn, - ae_int_t passcount, - double threshold, - ae_bool* cerrors, - ae_state *_state); -static void testmatinvunit_testspdinv(ae_int_t minn, - ae_int_t maxn, - ae_int_t passcount, - double threshold, - ae_bool* spderrors, - ae_state *_state); -static void testmatinvunit_testhpdinv(ae_int_t minn, - ae_int_t maxn, - ae_int_t passcount, - double threshold, - ae_bool* hpderrors, - ae_state *_state); -static void testmatinvunit_unset2d(/* Real */ ae_matrix* x, - ae_state *_state); -static void testmatinvunit_cunset2d(/* Complex */ ae_matrix* x, - ae_state *_state); -static void testmatinvunit_unsetrep(matinvreport* r, ae_state *_state); - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testmatinv(ae_bool silent, ae_state *_state) -{ - ae_int_t maxrn; - ae_int_t maxcn; - ae_int_t largen; - ae_int_t passcount; - double threshold; - ae_bool rtrerrors; - ae_bool ctrerrors; - ae_bool rerrors; - ae_bool cerrors; - ae_bool spderrors; - ae_bool hpderrors; - ae_bool waserrors; - ae_bool result; - - - maxrn = 3*matrixtilesizea(_state)+1; - maxcn = 3*matrixtilesizea(_state)+1; - largen = 4*matrixtilesizeb(_state)+1; - passcount = 1; - threshold = 10000*ae_machineepsilon; - rtrerrors = ae_false; - ctrerrors = ae_false; - rerrors = ae_false; - cerrors = ae_false; - spderrors = ae_false; - hpderrors = ae_false; - testmatinvunit_testrtrinv(1, maxrn, passcount, threshold, &rtrerrors, _state); - testmatinvunit_testctrinv(1, maxcn, passcount, threshold, &ctrerrors, _state); - testmatinvunit_testrinv(1, maxrn, passcount, threshold, &rerrors, _state); - testmatinvunit_testspdinv(1, maxrn, passcount, threshold, &spderrors, _state); - testmatinvunit_testcinv(1, maxcn, passcount, threshold, &cerrors, _state); - testmatinvunit_testhpdinv(1, maxcn, passcount, threshold, &hpderrors, _state); - testmatinvunit_testrtrinv(largen, largen, passcount, threshold, &rtrerrors, _state); - testmatinvunit_testctrinv(largen, largen, passcount, threshold, &ctrerrors, _state); - testmatinvunit_testrinv(largen, largen, passcount, threshold, &rerrors, _state); - testmatinvunit_testspdinv(largen, largen, passcount, threshold, &spderrors, _state); - testmatinvunit_testcinv(largen, largen, passcount, threshold, &cerrors, _state); - testmatinvunit_testhpdinv(largen, largen, passcount, threshold, &hpderrors, _state); - waserrors = ((((rtrerrors||ctrerrors)||rerrors)||cerrors)||spderrors)||hpderrors; - if( !silent ) - { - printf("TESTING MATINV\n"); - printf("* REAL TRIANGULAR: "); - if( rtrerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* COMPLEX TRIANGULAR: "); - if( ctrerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* REAL: "); - if( rerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* COMPLEX: "); - if( cerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* SPD: "); - if( spderrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* HPD: "); - if( hpderrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - } - result = !waserrors; - return result; -} - - -/************************************************************************* -Copy -*************************************************************************/ -static void testmatinvunit_rmatrixmakeacopy(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* b, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(b); - - ae_matrix_set_length(b, m-1+1, n-1+1, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - b->ptr.pp_double[i][j] = a->ptr.pp_double[i][j]; - } - } -} - - -/************************************************************************* -Copy -*************************************************************************/ -static void testmatinvunit_cmatrixmakeacopy(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* b, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(b); - - ae_matrix_set_length(b, m-1+1, n-1+1, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - b->ptr.pp_complex[i][j] = a->ptr.pp_complex[i][j]; - } - } -} - - -/************************************************************************* -Checks whether inverse is correct -Returns True on success. -*************************************************************************/ -static ae_bool testmatinvunit_rmatrixcheckinverse(/* Real */ ae_matrix* a, - /* Real */ ae_matrix* inva, - ae_int_t n, - double threshold, - ae_int_t info, - matinvreport* rep, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - ae_bool result; - - - result = ae_true; - if( info<=0 ) - { - result = ae_false; - } - else - { - result = result&&!(ae_fp_less(rep->r1,100*ae_machineepsilon)||ae_fp_greater(rep->r1,1+1000*ae_machineepsilon)); - result = result&&!(ae_fp_less(rep->rinf,100*ae_machineepsilon)||ae_fp_greater(rep->rinf,1+1000*ae_machineepsilon)); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&a->ptr.pp_double[i][0], 1, &inva->ptr.pp_double[0][j], inva->stride, ae_v_len(0,n-1)); - if( i==j ) - { - v = v-1; - } - result = result&&ae_fp_less_eq(ae_fabs(v, _state),threshold); - } - } - } - return result; -} - - -/************************************************************************* -Checks whether inverse is correct -Returns True on success. -*************************************************************************/ -static ae_bool testmatinvunit_spdmatrixcheckinverse(/* Real */ ae_matrix* a, - /* Real */ ae_matrix* inva, - ae_bool isupper, - ae_int_t n, - double threshold, - ae_int_t info, - matinvreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_matrix _inva; - ae_int_t i; - ae_int_t j; - double v; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&_inva, 0, sizeof(_inva)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_matrix_init_copy(&_inva, inva, _state, ae_true); - inva = &_inva; - - for(i=0; i<=n-2; i++) - { - if( isupper ) - { - ae_v_move(&a->ptr.pp_double[i+1][i], a->stride, &a->ptr.pp_double[i][i+1], 1, ae_v_len(i+1,n-1)); - ae_v_move(&inva->ptr.pp_double[i+1][i], inva->stride, &inva->ptr.pp_double[i][i+1], 1, ae_v_len(i+1,n-1)); - } - else - { - ae_v_move(&a->ptr.pp_double[i][i+1], 1, &a->ptr.pp_double[i+1][i], a->stride, ae_v_len(i+1,n-1)); - ae_v_move(&inva->ptr.pp_double[i][i+1], 1, &inva->ptr.pp_double[i+1][i], inva->stride, ae_v_len(i+1,n-1)); - } - } - result = ae_true; - if( info<=0 ) - { - result = ae_false; - } - else - { - result = result&&!(ae_fp_less(rep->r1,100*ae_machineepsilon)||ae_fp_greater(rep->r1,1+1000*ae_machineepsilon)); - result = result&&!(ae_fp_less(rep->rinf,100*ae_machineepsilon)||ae_fp_greater(rep->rinf,1+1000*ae_machineepsilon)); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&a->ptr.pp_double[i][0], 1, &inva->ptr.pp_double[0][j], inva->stride, ae_v_len(0,n-1)); - if( i==j ) - { - v = v-1; - } - result = result&&ae_fp_less_eq(ae_fabs(v, _state),threshold); - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Checks whether inverse is correct -Returns True on success. -*************************************************************************/ -static ae_bool testmatinvunit_hpdmatrixcheckinverse(/* Complex */ ae_matrix* a, - /* Complex */ ae_matrix* inva, - ae_bool isupper, - ae_int_t n, - double threshold, - ae_int_t info, - matinvreport* rep, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _a; - ae_matrix _inva; - ae_int_t i; - ae_int_t j; - ae_complex v; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_a, 0, sizeof(_a)); - memset(&_inva, 0, sizeof(_inva)); - ae_matrix_init_copy(&_a, a, _state, ae_true); - a = &_a; - ae_matrix_init_copy(&_inva, inva, _state, ae_true); - inva = &_inva; - - for(i=0; i<=n-2; i++) - { - if( isupper ) - { - ae_v_cmove(&a->ptr.pp_complex[i+1][i], a->stride, &a->ptr.pp_complex[i][i+1], 1, "Conj", ae_v_len(i+1,n-1)); - ae_v_cmove(&inva->ptr.pp_complex[i+1][i], inva->stride, &inva->ptr.pp_complex[i][i+1], 1, "Conj", ae_v_len(i+1,n-1)); - } - else - { - ae_v_cmove(&a->ptr.pp_complex[i][i+1], 1, &a->ptr.pp_complex[i+1][i], a->stride, "Conj", ae_v_len(i+1,n-1)); - ae_v_cmove(&inva->ptr.pp_complex[i][i+1], 1, &inva->ptr.pp_complex[i+1][i], inva->stride, "Conj", ae_v_len(i+1,n-1)); - } - } - result = ae_true; - if( info<=0 ) - { - result = ae_false; - } - else - { - result = result&&!(ae_fp_less(rep->r1,100*ae_machineepsilon)||ae_fp_greater(rep->r1,1+1000*ae_machineepsilon)); - result = result&&!(ae_fp_less(rep->rinf,100*ae_machineepsilon)||ae_fp_greater(rep->rinf,1+1000*ae_machineepsilon)); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_cdotproduct(&a->ptr.pp_complex[i][0], 1, "N", &inva->ptr.pp_complex[0][j], inva->stride, "N", ae_v_len(0,n-1)); - if( i==j ) - { - v = ae_c_sub_d(v,1); - } - result = result&&ae_fp_less_eq(ae_c_abs(v, _state),threshold); - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Checks whether inversion result indicate singular matrix -Returns True on success. -*************************************************************************/ -static ae_bool testmatinvunit_rmatrixcheckinversesingular(/* Real */ ae_matrix* inva, - ae_int_t n, - double threshold, - ae_int_t info, - matinvreport* rep, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_bool result; - - - result = ae_true; - if( info!=-3&&info!=1 ) - { - result = ae_false; - } - else - { - result = result&&!(ae_fp_less(rep->r1,(double)(0))||ae_fp_greater(rep->r1,1000*ae_machineepsilon)); - result = result&&!(ae_fp_less(rep->rinf,(double)(0))||ae_fp_greater(rep->rinf,1000*ae_machineepsilon)); - if( info==-3 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - result = result&&ae_fp_eq(inva->ptr.pp_double[i][j],(double)(0)); - } - } - } - } - return result; -} - - -/************************************************************************* -Checks whether inverse is correct -Returns True on success. -*************************************************************************/ -static ae_bool testmatinvunit_cmatrixcheckinverse(/* Complex */ ae_matrix* a, - /* Complex */ ae_matrix* inva, - ae_int_t n, - double threshold, - ae_int_t info, - matinvreport* rep, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_complex v; - ae_bool result; - - - result = ae_true; - if( info<=0 ) - { - result = ae_false; - } - else - { - result = result&&!(ae_fp_less(rep->r1,100*ae_machineepsilon)||ae_fp_greater(rep->r1,1+1000*ae_machineepsilon)); - result = result&&!(ae_fp_less(rep->rinf,100*ae_machineepsilon)||ae_fp_greater(rep->rinf,1+1000*ae_machineepsilon)); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_cdotproduct(&a->ptr.pp_complex[i][0], 1, "N", &inva->ptr.pp_complex[0][j], inva->stride, "N", ae_v_len(0,n-1)); - if( i==j ) - { - v = ae_c_sub_d(v,1); - } - result = result&&ae_fp_less_eq(ae_c_abs(v, _state),threshold); - } - } - } - return result; -} - - -/************************************************************************* -Checks whether inversion result indicate singular matrix -Returns True on success. -*************************************************************************/ -static ae_bool testmatinvunit_cmatrixcheckinversesingular(/* Complex */ ae_matrix* inva, - ae_int_t n, - double threshold, - ae_int_t info, - matinvreport* rep, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_bool result; - - - result = ae_true; - if( info!=-3&&info!=1 ) - { - result = ae_false; - } - else - { - result = result&&!(ae_fp_less(rep->r1,(double)(0))||ae_fp_greater(rep->r1,1000*ae_machineepsilon)); - result = result&&!(ae_fp_less(rep->rinf,(double)(0))||ae_fp_greater(rep->rinf,1000*ae_machineepsilon)); - if( info==-3 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - result = result&&ae_c_eq_d(inva->ptr.pp_complex[i][j],(double)(0)); - } - } - } - } - return result; -} - - -/************************************************************************* -Drops upper or lower half of the matrix - fills it by special pattern -which may be used later to ensure that this part wasn't changed -*************************************************************************/ -static void testmatinvunit_rmatrixdrophalf(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool droplower, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (droplower&&i>j)||(!droplower&&iptr.pp_double[i][j] = (double)(1+2*i+3*j); - } - } - } -} - - -/************************************************************************* -Drops upper or lower half of the matrix - fills it by special pattern -which may be used later to ensure that this part wasn't changed -*************************************************************************/ -static void testmatinvunit_cmatrixdrophalf(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool droplower, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (droplower&&i>j)||(!droplower&&iptr.pp_complex[i][j] = ae_complex_from_i(1+2*i+3*j); - } - } - } -} - - -/************************************************************************* -Real TR inverse -*************************************************************************/ -static void testmatinvunit_testrtrinv(ae_int_t minn, - ae_int_t maxn, - ae_int_t passcount, - double threshold, - ae_bool* rtrerrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix b; - ae_int_t n; - ae_int_t pass; - ae_int_t i; - ae_int_t j; - ae_int_t task; - ae_bool isupper; - ae_bool isunit; - double v; - ae_int_t info; - matinvreport rep; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true); - _matinvreport_init(&rep, _state, ae_true); - - - /* - * Test - */ - for(n=minn; n<=maxn; n++) - { - ae_matrix_set_length(&a, n, n, _state); - ae_matrix_set_length(&b, n, n, _state); - for(task=0; task<=3; task++) - { - for(pass=1; pass<=passcount; pass++) - { - - /* - * Determine task - */ - isupper = task%2==0; - isunit = task/2%2==0; - - /* - * Generate matrix - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - a.ptr.pp_double[i][i] = 1+ae_randomreal(_state); - } - else - { - a.ptr.pp_double[i][j] = 0.2*ae_randomreal(_state)-0.1; - } - b.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]; - } - } - - /* - * Inverse - */ - rmatrixtrinverse(&b, n, isupper, isunit, &info, &rep, _state); - if( info<=0 ) - { - *rtrerrors = ae_true; - ae_frame_leave(_state); - return; - } - - /* - * Structural test - */ - if( isunit ) - { - for(i=0; i<=n-1; i++) - { - *rtrerrors = *rtrerrors||ae_fp_neq(a.ptr.pp_double[i][i],b.ptr.pp_double[i][i]); - } - } - if( isupper ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i-1; j++) - { - *rtrerrors = *rtrerrors||ae_fp_neq(a.ptr.pp_double[i][j],b.ptr.pp_double[i][j]); - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=i+1; j<=n-1; j++) - { - *rtrerrors = *rtrerrors||ae_fp_neq(a.ptr.pp_double[i][j],b.ptr.pp_double[i][j]); - } - } - } - - /* - * Inverse test - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (ji&&!isupper) ) - { - a.ptr.pp_double[i][j] = (double)(0); - b.ptr.pp_double[i][j] = (double)(0); - } - } - } - if( isunit ) - { - for(i=0; i<=n-1; i++) - { - a.ptr.pp_double[i][i] = (double)(1); - b.ptr.pp_double[i][i] = (double)(1); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &b.ptr.pp_double[0][j], b.stride, ae_v_len(0,n-1)); - if( j!=i ) - { - *rtrerrors = *rtrerrors||ae_fp_greater(ae_fabs(v, _state),threshold); - } - else - { - *rtrerrors = *rtrerrors||ae_fp_greater(ae_fabs(v-1, _state),threshold); - } - } - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Complex TR inverse -*************************************************************************/ -static void testmatinvunit_testctrinv(ae_int_t minn, - ae_int_t maxn, - ae_int_t passcount, - double threshold, - ae_bool* ctrerrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix b; - ae_int_t n; - ae_int_t pass; - ae_int_t i; - ae_int_t j; - ae_int_t task; - ae_bool isupper; - ae_bool isunit; - ae_complex v; - ae_int_t info; - matinvreport rep; - double emax; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_init(&a, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&b, 0, 0, DT_COMPLEX, _state, ae_true); - _matinvreport_init(&rep, _state, ae_true); - - - /* - * Test - */ - for(n=minn; n<=maxn; n++) - { - ae_matrix_set_length(&a, n, n, _state); - ae_matrix_set_length(&b, n, n, _state); - for(task=0; task<=3; task++) - { - for(pass=1; pass<=passcount; pass++) - { - - /* - * Determine task - */ - isupper = task%2==0; - isunit = task/2%2==0; - - /* - * Generate matrix - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - a.ptr.pp_complex[i][i].x = 1+ae_randomreal(_state); - a.ptr.pp_complex[i][i].y = 1+ae_randomreal(_state); - } - else - { - a.ptr.pp_complex[i][j].x = 0.2*ae_randomreal(_state)-0.1; - a.ptr.pp_complex[i][j].y = 0.2*ae_randomreal(_state)-0.1; - } - b.ptr.pp_complex[i][j] = a.ptr.pp_complex[i][j]; - } - } - - /* - * Inverse - */ - cmatrixtrinverse(&b, n, isupper, isunit, &info, &rep, _state); - if( info<=0 ) - { - *ctrerrors = ae_true; - ae_frame_leave(_state); - return; - } - - /* - * Structural test - */ - if( isunit ) - { - for(i=0; i<=n-1; i++) - { - *ctrerrors = *ctrerrors||ae_c_neq(a.ptr.pp_complex[i][i],b.ptr.pp_complex[i][i]); - } - } - if( isupper ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i-1; j++) - { - *ctrerrors = *ctrerrors||ae_c_neq(a.ptr.pp_complex[i][j],b.ptr.pp_complex[i][j]); - } - } - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=i+1; j<=n-1; j++) - { - *ctrerrors = *ctrerrors||ae_c_neq(a.ptr.pp_complex[i][j],b.ptr.pp_complex[i][j]); - } - } - } - - /* - * Inverse test - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (ji&&!isupper) ) - { - a.ptr.pp_complex[i][j] = ae_complex_from_i(0); - b.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - } - if( isunit ) - { - for(i=0; i<=n-1; i++) - { - a.ptr.pp_complex[i][i] = ae_complex_from_i(1); - b.ptr.pp_complex[i][i] = ae_complex_from_i(1); - } - } - emax = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_cdotproduct(&a.ptr.pp_complex[i][0], 1, "N", &b.ptr.pp_complex[0][j], b.stride, "N", ae_v_len(0,n-1)); - if( j==i ) - { - v = ae_c_sub_d(v,1); - } - emax = ae_maxreal(emax, ae_c_abs(v, _state), _state); - } - } - *ctrerrors = *ctrerrors||ae_fp_greater(emax,threshold); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Real test -*************************************************************************/ -static void testmatinvunit_testrinv(ae_int_t minn, - ae_int_t maxn, - ae_int_t passcount, - double threshold, - ae_bool* rerrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix lua; - ae_matrix inva; - ae_matrix invlua; - ae_vector p; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t n; - ae_int_t pass; - ae_int_t taskkind; - ae_int_t info; - matinvreport rep; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&lua, 0, sizeof(lua)); - memset(&inva, 0, sizeof(inva)); - memset(&invlua, 0, sizeof(invlua)); - memset(&p, 0, sizeof(p)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&lua, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&inva, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&invlua, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - _matinvreport_init(&rep, _state, ae_true); - - - /* - * General square matrices: - * * test general solvers - * * test least squares solver - */ - for(pass=1; pass<=passcount; pass++) - { - for(n=minn; n<=maxn; n++) - { - - /* - * ******************************************************** - * WELL CONDITIONED TASKS - * ability to find correct solution is tested - * ******************************************************** - * - * 1. generate random well conditioned matrix A. - * 2. generate random solution vector xe - * 3. generate right part b=A*xe - * 4. test different methods on original A - */ - rmatrixrndcond(n, (double)(1000), &a, _state); - testmatinvunit_rmatrixmakeacopy(&a, n, n, &lua, _state); - rmatrixlu(&lua, n, n, &p, _state); - testmatinvunit_rmatrixmakeacopy(&a, n, n, &inva, _state); - testmatinvunit_rmatrixmakeacopy(&lua, n, n, &invlua, _state); - info = 0; - testmatinvunit_unsetrep(&rep, _state); - rmatrixinverse(&inva, n, &info, &rep, _state); - *rerrors = *rerrors||!testmatinvunit_rmatrixcheckinverse(&a, &inva, n, threshold, info, &rep, _state); - info = 0; - testmatinvunit_unsetrep(&rep, _state); - rmatrixluinverse(&invlua, &p, n, &info, &rep, _state); - *rerrors = *rerrors||!testmatinvunit_rmatrixcheckinverse(&a, &invlua, n, threshold, info, &rep, _state); - - /* - * ******************************************************** - * EXACTLY SINGULAR MATRICES - * ability to detect singularity is tested - * ******************************************************** - * - * 1. generate different types of singular matrices: - * * zero - * * with zero columns - * * with zero rows - * * with equal rows/columns - * 2. test different methods - */ - for(taskkind=0; taskkind<=4; taskkind++) - { - testmatinvunit_unset2d(&a, _state); - if( taskkind==0 ) - { - - /* - * all zeros - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - } - if( taskkind==1 ) - { - - /* - * there is zero column - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - k = ae_randominteger(n, _state); - ae_v_muld(&a.ptr.pp_double[0][k], a.stride, ae_v_len(0,n-1), 0); - } - if( taskkind==2 ) - { - - /* - * there is zero row - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - k = ae_randominteger(n, _state); - ae_v_muld(&a.ptr.pp_double[k][0], 1, ae_v_len(0,n-1), 0); - } - if( taskkind==3 ) - { - - /* - * equal columns - */ - if( n<2 ) - { - continue; - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - k = 1+ae_randominteger(n-1, _state); - ae_v_move(&a.ptr.pp_double[0][0], a.stride, &a.ptr.pp_double[0][k], a.stride, ae_v_len(0,n-1)); - } - if( taskkind==4 ) - { - - /* - * equal rows - */ - if( n<2 ) - { - continue; - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - k = 1+ae_randominteger(n-1, _state); - ae_v_move(&a.ptr.pp_double[0][0], 1, &a.ptr.pp_double[k][0], 1, ae_v_len(0,n-1)); - } - testmatinvunit_rmatrixmakeacopy(&a, n, n, &lua, _state); - rmatrixlu(&lua, n, n, &p, _state); - info = 0; - testmatinvunit_unsetrep(&rep, _state); - rmatrixinverse(&a, n, &info, &rep, _state); - *rerrors = *rerrors||!testmatinvunit_rmatrixcheckinversesingular(&a, n, threshold, info, &rep, _state); - info = 0; - testmatinvunit_unsetrep(&rep, _state); - rmatrixluinverse(&lua, &p, n, &info, &rep, _state); - *rerrors = *rerrors||!testmatinvunit_rmatrixcheckinversesingular(&lua, n, threshold, info, &rep, _state); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Complex test -*************************************************************************/ -static void testmatinvunit_testcinv(ae_int_t minn, - ae_int_t maxn, - ae_int_t passcount, - double threshold, - ae_bool* cerrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix lua; - ae_matrix inva; - ae_matrix invlua; - ae_vector p; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t n; - ae_int_t pass; - ae_int_t taskkind; - ae_int_t info; - matinvreport rep; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&lua, 0, sizeof(lua)); - memset(&inva, 0, sizeof(inva)); - memset(&invlua, 0, sizeof(invlua)); - memset(&p, 0, sizeof(p)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_init(&a, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&lua, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&inva, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&invlua, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - _matinvreport_init(&rep, _state, ae_true); - - - /* - * General square matrices: - * * test general solvers - * * test least squares solver - */ - for(pass=1; pass<=passcount; pass++) - { - for(n=minn; n<=maxn; n++) - { - - /* - * ******************************************************** - * WELL CONDITIONED TASKS - * ability to find correct solution is tested - * ******************************************************** - * - * 1. generate random well conditioned matrix A. - * 2. generate random solution vector xe - * 3. generate right part b=A*xe - * 4. test different methods on original A - */ - cmatrixrndcond(n, (double)(1000), &a, _state); - testmatinvunit_cmatrixmakeacopy(&a, n, n, &lua, _state); - cmatrixlu(&lua, n, n, &p, _state); - testmatinvunit_cmatrixmakeacopy(&a, n, n, &inva, _state); - testmatinvunit_cmatrixmakeacopy(&lua, n, n, &invlua, _state); - info = 0; - testmatinvunit_unsetrep(&rep, _state); - cmatrixinverse(&inva, n, &info, &rep, _state); - *cerrors = *cerrors||!testmatinvunit_cmatrixcheckinverse(&a, &inva, n, threshold, info, &rep, _state); - info = 0; - testmatinvunit_unsetrep(&rep, _state); - cmatrixluinverse(&invlua, &p, n, &info, &rep, _state); - *cerrors = *cerrors||!testmatinvunit_cmatrixcheckinverse(&a, &invlua, n, threshold, info, &rep, _state); - - /* - * ******************************************************** - * EXACTLY SINGULAR MATRICES - * ability to detect singularity is tested - * ******************************************************** - * - * 1. generate different types of singular matrices: - * * zero - * * with zero columns - * * with zero rows - * * with equal rows/columns - * 2. test different methods - */ - for(taskkind=0; taskkind<=4; taskkind++) - { - testmatinvunit_cunset2d(&a, _state); - if( taskkind==0 ) - { - - /* - * all zeros - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - } - if( taskkind==1 ) - { - - /* - * there is zero column - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - k = ae_randominteger(n, _state); - ae_v_cmuld(&a.ptr.pp_complex[0][k], a.stride, ae_v_len(0,n-1), 0); - } - if( taskkind==2 ) - { - - /* - * there is zero row - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - k = ae_randominteger(n, _state); - ae_v_cmuld(&a.ptr.pp_complex[k][0], 1, ae_v_len(0,n-1), 0); - } - if( taskkind==3 ) - { - - /* - * equal columns - */ - if( n<2 ) - { - continue; - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - k = 1+ae_randominteger(n-1, _state); - ae_v_cmove(&a.ptr.pp_complex[0][0], a.stride, &a.ptr.pp_complex[0][k], a.stride, "N", ae_v_len(0,n-1)); - } - if( taskkind==4 ) - { - - /* - * equal rows - */ - if( n<2 ) - { - continue; - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - k = 1+ae_randominteger(n-1, _state); - ae_v_cmove(&a.ptr.pp_complex[0][0], 1, &a.ptr.pp_complex[k][0], 1, "N", ae_v_len(0,n-1)); - } - testmatinvunit_cmatrixmakeacopy(&a, n, n, &lua, _state); - cmatrixlu(&lua, n, n, &p, _state); - info = 0; - testmatinvunit_unsetrep(&rep, _state); - cmatrixinverse(&a, n, &info, &rep, _state); - *cerrors = *cerrors||!testmatinvunit_cmatrixcheckinversesingular(&a, n, threshold, info, &rep, _state); - info = 0; - testmatinvunit_unsetrep(&rep, _state); - cmatrixluinverse(&lua, &p, n, &info, &rep, _state); - *cerrors = *cerrors||!testmatinvunit_cmatrixcheckinversesingular(&lua, n, threshold, info, &rep, _state); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -SPD test -*************************************************************************/ -static void testmatinvunit_testspdinv(ae_int_t minn, - ae_int_t maxn, - ae_int_t passcount, - double threshold, - ae_bool* spderrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix cha; - ae_matrix inva; - ae_matrix invcha; - ae_bool isupper; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t n; - ae_int_t pass; - ae_int_t taskkind; - ae_int_t info; - matinvreport rep; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&cha, 0, sizeof(cha)); - memset(&inva, 0, sizeof(inva)); - memset(&invcha, 0, sizeof(invcha)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&cha, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&inva, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&invcha, 0, 0, DT_REAL, _state, ae_true); - _matinvreport_init(&rep, _state, ae_true); - - - /* - * General square matrices: - * * test general solvers - * * test least squares solver - */ - for(pass=1; pass<=passcount; pass++) - { - for(n=minn; n<=maxn; n++) - { - isupper = ae_fp_greater(ae_randomreal(_state),0.5); - - /* - * ******************************************************** - * WELL CONDITIONED TASKS - * ability to find correct solution is tested - * ******************************************************** - * - * 1. generate random well conditioned matrix A. - * 2. generate random solution vector xe - * 3. generate right part b=A*xe - * 4. test different methods on original A - */ - spdmatrixrndcond(n, (double)(1000), &a, _state); - testmatinvunit_rmatrixdrophalf(&a, n, isupper, _state); - testmatinvunit_rmatrixmakeacopy(&a, n, n, &cha, _state); - if( !spdmatrixcholesky(&cha, n, isupper, _state) ) - { - continue; - } - testmatinvunit_rmatrixmakeacopy(&a, n, n, &inva, _state); - testmatinvunit_rmatrixmakeacopy(&cha, n, n, &invcha, _state); - info = 0; - testmatinvunit_unsetrep(&rep, _state); - spdmatrixinverse(&inva, n, isupper, &info, &rep, _state); - *spderrors = *spderrors||!testmatinvunit_spdmatrixcheckinverse(&a, &inva, isupper, n, threshold, info, &rep, _state); - info = 0; - testmatinvunit_unsetrep(&rep, _state); - spdmatrixcholeskyinverse(&invcha, n, isupper, &info, &rep, _state); - *spderrors = *spderrors||!testmatinvunit_spdmatrixcheckinverse(&a, &invcha, isupper, n, threshold, info, &rep, _state); - - /* - * ******************************************************** - * EXACTLY SINGULAR MATRICES - * ability to detect singularity is tested - * ******************************************************** - * - * 1. generate different types of singular matrices: - * * zero - * * with zero columns - * * with zero rows - * 2. test different methods - */ - for(taskkind=0; taskkind<=2; taskkind++) - { - testmatinvunit_unset2d(&a, _state); - if( taskkind==0 ) - { - - /* - * all zeros - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - } - if( taskkind==1 ) - { - - /* - * there is zero column - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - k = ae_randominteger(n, _state); - ae_v_muld(&a.ptr.pp_double[0][k], a.stride, ae_v_len(0,n-1), 0); - } - if( taskkind==2 ) - { - - /* - * there is zero row - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - k = ae_randominteger(n, _state); - ae_v_muld(&a.ptr.pp_double[k][0], 1, ae_v_len(0,n-1), 0); - } - info = 0; - testmatinvunit_unsetrep(&rep, _state); - spdmatrixcholeskyinverse(&a, n, isupper, &info, &rep, _state); - if( info!=-3&&info!=1 ) - { - *spderrors = ae_true; - } - else - { - *spderrors = (*spderrors||ae_fp_less(rep.r1,(double)(0)))||ae_fp_greater(rep.r1,1000*ae_machineepsilon); - *spderrors = (*spderrors||ae_fp_less(rep.rinf,(double)(0)))||ae_fp_greater(rep.rinf,1000*ae_machineepsilon); - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -HPD test -*************************************************************************/ -static void testmatinvunit_testhpdinv(ae_int_t minn, - ae_int_t maxn, - ae_int_t passcount, - double threshold, - ae_bool* hpderrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix cha; - ae_matrix inva; - ae_matrix invcha; - ae_bool isupper; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t n; - ae_int_t pass; - ae_int_t taskkind; - ae_int_t info; - matinvreport rep; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&cha, 0, sizeof(cha)); - memset(&inva, 0, sizeof(inva)); - memset(&invcha, 0, sizeof(invcha)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_init(&a, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&cha, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&inva, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&invcha, 0, 0, DT_COMPLEX, _state, ae_true); - _matinvreport_init(&rep, _state, ae_true); - - - /* - * General square matrices: - * * test general solvers - * * test least squares solver - */ - for(pass=1; pass<=passcount; pass++) - { - for(n=minn; n<=maxn; n++) - { - isupper = ae_fp_greater(ae_randomreal(_state),0.5); - - /* - * ******************************************************** - * WELL CONDITIONED TASKS - * ability to find correct solution is tested - * ******************************************************** - * - * 1. generate random well conditioned matrix A. - * 2. generate random solution vector xe - * 3. generate right part b=A*xe - * 4. test different methods on original A - */ - hpdmatrixrndcond(n, (double)(1000), &a, _state); - testmatinvunit_cmatrixdrophalf(&a, n, isupper, _state); - testmatinvunit_cmatrixmakeacopy(&a, n, n, &cha, _state); - if( !hpdmatrixcholesky(&cha, n, isupper, _state) ) - { - continue; - } - testmatinvunit_cmatrixmakeacopy(&a, n, n, &inva, _state); - testmatinvunit_cmatrixmakeacopy(&cha, n, n, &invcha, _state); - info = 0; - testmatinvunit_unsetrep(&rep, _state); - hpdmatrixinverse(&inva, n, isupper, &info, &rep, _state); - *hpderrors = *hpderrors||!testmatinvunit_hpdmatrixcheckinverse(&a, &inva, isupper, n, threshold, info, &rep, _state); - info = 0; - testmatinvunit_unsetrep(&rep, _state); - hpdmatrixcholeskyinverse(&invcha, n, isupper, &info, &rep, _state); - *hpderrors = *hpderrors||!testmatinvunit_hpdmatrixcheckinverse(&a, &invcha, isupper, n, threshold, info, &rep, _state); - - /* - * ******************************************************** - * EXACTLY SINGULAR MATRICES - * ability to detect singularity is tested - * ******************************************************** - * - * 1. generate different types of singular matrices: - * * zero - * * with zero columns - * * with zero rows - * 2. test different methods - */ - for(taskkind=0; taskkind<=2; taskkind++) - { - testmatinvunit_cunset2d(&a, _state); - if( taskkind==0 ) - { - - /* - * all zeros - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - } - if( taskkind==1 ) - { - - /* - * there is zero column - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - k = ae_randominteger(n, _state); - ae_v_cmuld(&a.ptr.pp_complex[0][k], a.stride, ae_v_len(0,n-1), 0); - ae_v_cmuld(&a.ptr.pp_complex[k][0], 1, ae_v_len(0,n-1), 0); - } - if( taskkind==2 ) - { - - /* - * there is zero row - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - k = ae_randominteger(n, _state); - ae_v_cmuld(&a.ptr.pp_complex[k][0], 1, ae_v_len(0,n-1), 0); - ae_v_cmuld(&a.ptr.pp_complex[0][k], a.stride, ae_v_len(0,n-1), 0); - } - info = 0; - testmatinvunit_unsetrep(&rep, _state); - hpdmatrixcholeskyinverse(&a, n, isupper, &info, &rep, _state); - if( info!=-3&&info!=1 ) - { - *hpderrors = ae_true; - } - else - { - *hpderrors = (*hpderrors||ae_fp_less(rep.r1,(double)(0)))||ae_fp_greater(rep.r1,1000*ae_machineepsilon); - *hpderrors = (*hpderrors||ae_fp_less(rep.rinf,(double)(0)))||ae_fp_greater(rep.rinf,1000*ae_machineepsilon); - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Unsets real matrix -*************************************************************************/ -static void testmatinvunit_unset2d(/* Real */ ae_matrix* x, - ae_state *_state) -{ - - - ae_matrix_set_length(x, 1, 1, _state); - x->ptr.pp_double[0][0] = 2*ae_randomreal(_state)-1; -} - - -/************************************************************************* -Unsets real matrix -*************************************************************************/ -static void testmatinvunit_cunset2d(/* Complex */ ae_matrix* x, - ae_state *_state) -{ - - - ae_matrix_set_length(x, 1, 1, _state); - x->ptr.pp_complex[0][0] = ae_complex_from_d(2*ae_randomreal(_state)-1); -} - - -/************************************************************************* -Unsets report -*************************************************************************/ -static void testmatinvunit_unsetrep(matinvreport* r, ae_state *_state) -{ - - - r->r1 = (double)(-1); - r->rinf = (double)(-1); -} - - - - - - - - -ae_bool testhblas(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix ua; - ae_matrix la; - ae_vector x; - ae_vector y1; - ae_vector y2; - ae_vector y3; - ae_int_t n; - ae_int_t maxn; - ae_int_t i; - ae_int_t j; - ae_int_t i1; - ae_int_t i2; - ae_bool waserrors; - double mverr; - double threshold; - ae_complex alpha; - ae_complex v; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&ua, 0, sizeof(ua)); - memset(&la, 0, sizeof(la)); - memset(&x, 0, sizeof(x)); - memset(&y1, 0, sizeof(y1)); - memset(&y2, 0, sizeof(y2)); - memset(&y3, 0, sizeof(y3)); - ae_matrix_init(&a, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&ua, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&la, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&x, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&y1, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&y2, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&y3, 0, DT_COMPLEX, _state, ae_true); - - mverr = (double)(0); - waserrors = ae_false; - maxn = 10; - threshold = 1000*ae_machineepsilon; - - /* - * Test MV - */ - for(n=2; n<=maxn; n++) - { - ae_matrix_set_length(&a, n+1, n+1, _state); - ae_matrix_set_length(&ua, n+1, n+1, _state); - ae_matrix_set_length(&la, n+1, n+1, _state); - ae_vector_set_length(&x, n+1, _state); - ae_vector_set_length(&y1, n+1, _state); - ae_vector_set_length(&y2, n+1, _state); - ae_vector_set_length(&y3, n+1, _state); - - /* - * fill A, UA, LA - */ - for(i=1; i<=n; i++) - { - a.ptr.pp_complex[i][i].x = 2*ae_randomreal(_state)-1; - a.ptr.pp_complex[i][i].y = (double)(0); - for(j=i+1; j<=n; j++) - { - a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - a.ptr.pp_complex[j][i] = ae_c_conj(a.ptr.pp_complex[i][j], _state); - } - } - for(i=1; i<=n; i++) - { - for(j=1; j<=n; j++) - { - ua.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - for(i=1; i<=n; i++) - { - for(j=i; j<=n; j++) - { - ua.ptr.pp_complex[i][j] = a.ptr.pp_complex[i][j]; - } - } - for(i=1; i<=n; i++) - { - for(j=1; j<=n; j++) - { - la.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - for(i=1; i<=n; i++) - { - for(j=1; j<=i; j++) - { - la.ptr.pp_complex[i][j] = a.ptr.pp_complex[i][j]; - } - } - - /* - * test on different I1, I2 - */ - for(i1=1; i1<=n; i1++) - { - for(i2=i1; i2<=n; i2++) - { - - /* - * Fill X, choose Alpha - */ - for(i=1; i<=i2-i1+1; i++) - { - x.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1; - x.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1; - } - alpha.x = 2*ae_randomreal(_state)-1; - alpha.y = 2*ae_randomreal(_state)-1; - - /* - * calculate A*x, UA*x, LA*x - */ - for(i=i1; i<=i2; i++) - { - v = ae_v_cdotproduct(&a.ptr.pp_complex[i][i1], 1, "N", &x.ptr.p_complex[1], 1, "N", ae_v_len(i1,i2)); - y1.ptr.p_complex[i-i1+1] = ae_c_mul(alpha,v); - } - hermitianmatrixvectormultiply(&ua, ae_true, i1, i2, &x, alpha, &y2, _state); - hermitianmatrixvectormultiply(&la, ae_false, i1, i2, &x, alpha, &y3, _state); - - /* - * Calculate error - */ - ae_v_csub(&y2.ptr.p_complex[1], 1, &y1.ptr.p_complex[1], 1, "N", ae_v_len(1,i2-i1+1)); - v = ae_v_cdotproduct(&y2.ptr.p_complex[1], 1, "N", &y2.ptr.p_complex[1], 1, "Conj", ae_v_len(1,i2-i1+1)); - mverr = ae_maxreal(mverr, ae_sqrt(ae_c_abs(v, _state), _state), _state); - ae_v_csub(&y3.ptr.p_complex[1], 1, &y1.ptr.p_complex[1], 1, "N", ae_v_len(1,i2-i1+1)); - v = ae_v_cdotproduct(&y3.ptr.p_complex[1], 1, "N", &y3.ptr.p_complex[1], 1, "Conj", ae_v_len(1,i2-i1+1)); - mverr = ae_maxreal(mverr, ae_sqrt(ae_c_abs(v, _state), _state), _state); - } - } - } - - /* - * report - */ - waserrors = ae_fp_greater(mverr,threshold); - if( !silent ) - { - printf("TESTING HERMITIAN BLAS\n"); - printf("MV error: %5.3e\n", - (double)(mverr)); - printf("Threshold: %5.3e\n", - (double)(threshold)); - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - - - - - - - -ae_bool testsblas(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix ua; - ae_matrix la; - ae_vector x; - ae_vector y1; - ae_vector y2; - ae_vector y3; - ae_int_t n; - ae_int_t maxn; - ae_int_t i; - ae_int_t j; - ae_int_t i1; - ae_int_t i2; - ae_bool waserrors; - double mverr; - double threshold; - double alpha; - double v; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&ua, 0, sizeof(ua)); - memset(&la, 0, sizeof(la)); - memset(&x, 0, sizeof(x)); - memset(&y1, 0, sizeof(y1)); - memset(&y2, 0, sizeof(y2)); - memset(&y3, 0, sizeof(y3)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ua, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&la, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y3, 0, DT_REAL, _state, ae_true); - - mverr = (double)(0); - waserrors = ae_false; - maxn = 10; - threshold = 1000*ae_machineepsilon; - - /* - * Test MV - */ - for(n=2; n<=maxn; n++) - { - ae_matrix_set_length(&a, n+1, n+1, _state); - ae_matrix_set_length(&ua, n+1, n+1, _state); - ae_matrix_set_length(&la, n+1, n+1, _state); - ae_vector_set_length(&x, n+1, _state); - ae_vector_set_length(&y1, n+1, _state); - ae_vector_set_length(&y2, n+1, _state); - ae_vector_set_length(&y3, n+1, _state); - - /* - * fill A, UA, LA - */ - for(i=1; i<=n; i++) - { - a.ptr.pp_double[i][i] = 2*ae_randomreal(_state)-1; - for(j=i+1; j<=n; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j]; - } - } - for(i=1; i<=n; i++) - { - for(j=1; j<=n; j++) - { - ua.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=1; i<=n; i++) - { - for(j=i; j<=n; j++) - { - ua.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]; - } - } - for(i=1; i<=n; i++) - { - for(j=1; j<=n; j++) - { - la.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=1; i<=n; i++) - { - for(j=1; j<=i; j++) - { - la.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]; - } - } - - /* - * test on different I1, I2 - */ - for(i1=1; i1<=n; i1++) - { - for(i2=i1; i2<=n; i2++) - { - - /* - * Fill X, choose Alpha - */ - for(i=1; i<=i2-i1+1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - alpha = 2*ae_randomreal(_state)-1; - - /* - * calculate A*x, UA*x, LA*x - */ - for(i=i1; i<=i2; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][i1], 1, &x.ptr.p_double[1], 1, ae_v_len(i1,i2)); - y1.ptr.p_double[i-i1+1] = alpha*v; - } - symmetricmatrixvectormultiply(&ua, ae_true, i1, i2, &x, alpha, &y2, _state); - symmetricmatrixvectormultiply(&la, ae_false, i1, i2, &x, alpha, &y3, _state); - - /* - * Calculate error - */ - ae_v_sub(&y2.ptr.p_double[1], 1, &y1.ptr.p_double[1], 1, ae_v_len(1,i2-i1+1)); - v = ae_v_dotproduct(&y2.ptr.p_double[1], 1, &y2.ptr.p_double[1], 1, ae_v_len(1,i2-i1+1)); - mverr = ae_maxreal(mverr, ae_sqrt(v, _state), _state); - ae_v_sub(&y3.ptr.p_double[1], 1, &y1.ptr.p_double[1], 1, ae_v_len(1,i2-i1+1)); - v = ae_v_dotproduct(&y3.ptr.p_double[1], 1, &y3.ptr.p_double[1], 1, ae_v_len(1,i2-i1+1)); - mverr = ae_maxreal(mverr, ae_sqrt(v, _state), _state); - } - } - } - - /* - * report - */ - waserrors = ae_fp_greater(mverr,threshold); - if( !silent ) - { - printf("TESTING SYMMETRIC BLAS\n"); - printf("MV error: %5.3e\n", - (double)(mverr)); - printf("Threshold: %5.3e\n", - (double)(threshold)); - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - - -static double testortfacunit_rmatrixdiff(/* Real */ ae_matrix* a, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t n, - ae_state *_state); -static void testortfacunit_rmatrixmakeacopy(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* b, - ae_state *_state); -static void testortfacunit_cmatrixmakeacopy(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* b, - ae_state *_state); -static void testortfacunit_rmatrixfillsparsea(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double sparcity, - ae_state *_state); -static void testortfacunit_cmatrixfillsparsea(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double sparcity, - ae_state *_state); -static void testortfacunit_internalmatrixmatrixmultiply(/* Real */ ae_matrix* a, - ae_int_t ai1, - ae_int_t ai2, - ae_int_t aj1, - ae_int_t aj2, - ae_bool transa, - /* Real */ ae_matrix* b, - ae_int_t bi1, - ae_int_t bi2, - ae_int_t bj1, - ae_int_t bj2, - ae_bool transb, - /* Real */ ae_matrix* c, - ae_int_t ci1, - ae_int_t ci2, - ae_int_t cj1, - ae_int_t cj2, - ae_state *_state); -static void testortfacunit_testrqrproblem(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double threshold, - ae_bool* qrerrors, - ae_state *_state); -static void testortfacunit_testcqrproblem(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double threshold, - ae_bool* qrerrors, - ae_state *_state); -static void testortfacunit_testrlqproblem(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double threshold, - ae_bool* lqerrors, - ae_state *_state); -static void testortfacunit_testclqproblem(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double threshold, - ae_bool* lqerrors, - ae_state *_state); -static void testortfacunit_testrbdproblem(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double threshold, - ae_bool* bderrors, - ae_state *_state); -static void testortfacunit_testrhessproblem(/* Real */ ae_matrix* a, - ae_int_t n, - double threshold, - ae_bool* hesserrors, - ae_state *_state); -static void testortfacunit_testrtdproblem(/* Real */ ae_matrix* a, - ae_int_t n, - double threshold, - ae_bool* tderrors, - ae_state *_state); -static void testortfacunit_testctdproblem(/* Complex */ ae_matrix* a, - ae_int_t n, - double threshold, - ae_bool* tderrors, - ae_state *_state); - - - - - -/************************************************************************* -Main unittest subroutine -*************************************************************************/ -ae_bool testortfac(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - double threshold; - ae_int_t mx; - ae_matrix ra; - ae_matrix ca; - ae_int_t m; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_bool rqrerrors; - ae_bool rlqerrors; - ae_bool cqrerrors; - ae_bool clqerrors; - ae_bool rbderrors; - ae_bool rhesserrors; - ae_bool rtderrors; - ae_bool ctderrors; - ae_bool waserrors; - hqrndstate rs; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&ra, 0, sizeof(ra)); - memset(&ca, 0, sizeof(ca)); - memset(&rs, 0, sizeof(rs)); - ae_matrix_init(&ra, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ca, 0, 0, DT_COMPLEX, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - waserrors = ae_false; - rqrerrors = ae_false; - rlqerrors = ae_false; - cqrerrors = ae_false; - clqerrors = ae_false; - rbderrors = ae_false; - rhesserrors = ae_false; - rtderrors = ae_false; - ctderrors = ae_false; - threshold = 5*1000*ae_machineepsilon; - - /* - * Medium-scale problems with various sparseness profiles - */ - for(mx=1; mx<=3*matrixtilesizea(_state)+1; mx++) - { - - /* - * Rectangular factorizations: QR, LQ, bidiagonal - * Matrix types: zero, dense, sparse - */ - n = 1+ae_randominteger(mx, _state); - m = 1+ae_randominteger(mx, _state); - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - n = mx; - } - else - { - m = mx; - } - ae_matrix_set_length(&ra, m, n, _state); - ae_matrix_set_length(&ca, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - ra.ptr.pp_double[i][j] = (double)(0); - ca.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - testortfacunit_testrqrproblem(&ra, m, n, threshold, &rqrerrors, _state); - testortfacunit_testrlqproblem(&ra, m, n, threshold, &rlqerrors, _state); - testortfacunit_testcqrproblem(&ca, m, n, threshold, &cqrerrors, _state); - testortfacunit_testclqproblem(&ca, m, n, threshold, &clqerrors, _state); - testortfacunit_testrbdproblem(&ra, m, n, threshold, &rbderrors, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - ra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - ca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - ca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - testortfacunit_testrqrproblem(&ra, m, n, threshold, &rqrerrors, _state); - testortfacunit_testrlqproblem(&ra, m, n, threshold, &rlqerrors, _state); - testortfacunit_testcqrproblem(&ca, m, n, threshold, &cqrerrors, _state); - testortfacunit_testclqproblem(&ca, m, n, threshold, &clqerrors, _state); - testortfacunit_testrbdproblem(&ra, m, n, threshold, &rbderrors, _state); - testortfacunit_rmatrixfillsparsea(&ra, m, n, 0.95, _state); - testortfacunit_cmatrixfillsparsea(&ca, m, n, 0.95, _state); - testortfacunit_testrqrproblem(&ra, m, n, threshold, &rqrerrors, _state); - testortfacunit_testrlqproblem(&ra, m, n, threshold, &rlqerrors, _state); - testortfacunit_testcqrproblem(&ca, m, n, threshold, &cqrerrors, _state); - testortfacunit_testclqproblem(&ca, m, n, threshold, &clqerrors, _state); - testortfacunit_testrbdproblem(&ra, m, n, threshold, &rbderrors, _state); - - /* - * Square factorizations: Hessenberg, tridiagonal - * Matrix types: zero, dense, sparse - */ - ae_matrix_set_length(&ra, mx, mx, _state); - ae_matrix_set_length(&ca, mx, mx, _state); - for(i=0; i<=mx-1; i++) - { - for(j=0; j<=mx-1; j++) - { - ra.ptr.pp_double[i][j] = (double)(0); - ca.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - testortfacunit_testrhessproblem(&ra, mx, threshold, &rhesserrors, _state); - for(i=0; i<=mx-1; i++) - { - for(j=0; j<=mx-1; j++) - { - ra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - ca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - ca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - testortfacunit_testrhessproblem(&ra, mx, threshold, &rhesserrors, _state); - testortfacunit_rmatrixfillsparsea(&ra, mx, mx, 0.95, _state); - testortfacunit_cmatrixfillsparsea(&ca, mx, mx, 0.95, _state); - testortfacunit_testrhessproblem(&ra, mx, threshold, &rhesserrors, _state); - - /* - * Symetric factorizations: tridiagonal - * Matrix types: zero, dense, sparse - */ - ae_matrix_set_length(&ra, mx, mx, _state); - ae_matrix_set_length(&ca, mx, mx, _state); - for(i=0; i<=mx-1; i++) - { - for(j=0; j<=mx-1; j++) - { - ra.ptr.pp_double[i][j] = (double)(0); - ca.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - testortfacunit_testrtdproblem(&ra, mx, threshold, &rtderrors, _state); - testortfacunit_testctdproblem(&ca, mx, threshold, &ctderrors, _state); - for(i=0; i<=mx-1; i++) - { - for(j=i; j<=mx-1; j++) - { - ra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - ca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - ca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - ra.ptr.pp_double[j][i] = ra.ptr.pp_double[i][j]; - ca.ptr.pp_complex[j][i] = ae_c_conj(ca.ptr.pp_complex[i][j], _state); - } - } - for(i=0; i<=mx-1; i++) - { - ca.ptr.pp_complex[i][i] = ae_complex_from_d(2*ae_randomreal(_state)-1); - } - testortfacunit_testrtdproblem(&ra, mx, threshold, &rtderrors, _state); - testortfacunit_testctdproblem(&ca, mx, threshold, &ctderrors, _state); - testortfacunit_rmatrixfillsparsea(&ra, mx, mx, 0.95, _state); - testortfacunit_cmatrixfillsparsea(&ca, mx, mx, 0.95, _state); - for(i=0; i<=mx-1; i++) - { - for(j=i; j<=mx-1; j++) - { - ra.ptr.pp_double[j][i] = ra.ptr.pp_double[i][j]; - ca.ptr.pp_complex[j][i] = ae_c_conj(ca.ptr.pp_complex[i][j], _state); - } - } - for(i=0; i<=mx-1; i++) - { - ca.ptr.pp_complex[i][i] = ae_complex_from_d(2*ae_randomreal(_state)-1); - } - testortfacunit_testrtdproblem(&ra, mx, threshold, &rtderrors, _state); - testortfacunit_testctdproblem(&ca, mx, threshold, &ctderrors, _state); - } - - /* - * Large-scale tests - */ - for(mx=4*matrixtilesizeb(_state); mx<=4*matrixtilesizeb(_state); mx++) - { - - /* - * Rectangular factorizations: QR, LQ, bidiagonal - * Matrix types: dense - */ - n = 1+ae_randominteger(mx, _state); - m = 1+ae_randominteger(mx, _state); - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - n = mx; - } - else - { - m = mx; - } - ae_matrix_set_length(&ra, m, n, _state); - ae_matrix_set_length(&ca, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - ra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - ca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - ca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - testortfacunit_testrqrproblem(&ra, m, n, threshold, &rqrerrors, _state); - testortfacunit_testrlqproblem(&ra, m, n, threshold, &rlqerrors, _state); - testortfacunit_testcqrproblem(&ca, m, n, threshold, &cqrerrors, _state); - testortfacunit_testclqproblem(&ca, m, n, threshold, &clqerrors, _state); - testortfacunit_testrbdproblem(&ra, m, n, threshold, &rbderrors, _state); - - /* - * Square factorizations: Hessenberg, tridiagonal - * Matrix types: dense - */ - ae_matrix_set_length(&ra, mx, mx, _state); - ae_matrix_set_length(&ca, mx, mx, _state); - for(i=0; i<=mx-1; i++) - { - for(j=0; j<=mx-1; j++) - { - ra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - ca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - ca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - testortfacunit_testrhessproblem(&ra, mx, threshold, &rhesserrors, _state); - - /* - * Symetric factorizations: tridiagonal - * Matrix types: dense - */ - ae_matrix_set_length(&ra, mx, mx, _state); - ae_matrix_set_length(&ca, mx, mx, _state); - for(i=0; i<=mx-1; i++) - { - for(j=i; j<=mx-1; j++) - { - ra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - ca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - ca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - ra.ptr.pp_double[j][i] = ra.ptr.pp_double[i][j]; - ca.ptr.pp_complex[j][i] = ae_c_conj(ca.ptr.pp_complex[i][j], _state); - } - } - for(i=0; i<=mx-1; i++) - { - ca.ptr.pp_complex[i][i] = ae_complex_from_d(2*ae_randomreal(_state)-1); - } - testortfacunit_testrtdproblem(&ra, mx, threshold, &rtderrors, _state); - testortfacunit_testctdproblem(&ca, mx, threshold, &ctderrors, _state); - } - - /* - * report - */ - waserrors = ((((((rqrerrors||rlqerrors)||cqrerrors)||clqerrors)||rbderrors)||rhesserrors)||rtderrors)||ctderrors; - if( !silent ) - { - printf("TESTING ORTFAC UNIT\n"); - printf("RQR ERRORS: "); - if( !rqrerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("RLQ ERRORS: "); - if( !rlqerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("CQR ERRORS: "); - if( !cqrerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("CLQ ERRORS: "); - if( !clqerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("RBD ERRORS: "); - if( !rbderrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("RHESS ERRORS: "); - if( !rhesserrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("RTD ERRORS: "); - if( !rtderrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("CTD ERRORS: "); - if( !ctderrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Diff -*************************************************************************/ -static double testortfacunit_rmatrixdiff(/* Real */ ae_matrix* a, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double result; - - - result = (double)(0); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - result = ae_maxreal(result, ae_fabs(b->ptr.pp_double[i][j]-a->ptr.pp_double[i][j], _state), _state); - } - } - return result; -} - - -/************************************************************************* -Copy -*************************************************************************/ -static void testortfacunit_rmatrixmakeacopy(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* b, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(b); - - ae_matrix_set_length(b, m-1+1, n-1+1, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - b->ptr.pp_double[i][j] = a->ptr.pp_double[i][j]; - } - } -} - - -/************************************************************************* -Copy -*************************************************************************/ -static void testortfacunit_cmatrixmakeacopy(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* b, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(b); - - ae_matrix_set_length(b, m-1+1, n-1+1, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - b->ptr.pp_complex[i][j] = a->ptr.pp_complex[i][j]; - } - } -} - - -/************************************************************************* -Sparse fill -*************************************************************************/ -static void testortfacunit_rmatrixfillsparsea(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double sparcity, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_greater_eq(ae_randomreal(_state),sparcity) ) - { - a->ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - else - { - a->ptr.pp_double[i][j] = (double)(0); - } - } - } -} - - -/************************************************************************* -Sparse fill -*************************************************************************/ -static void testortfacunit_cmatrixfillsparsea(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double sparcity, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_greater_eq(ae_randomreal(_state),sparcity) ) - { - a->ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - a->ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - else - { - a->ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - } -} - - -/************************************************************************* -Matrix multiplication -*************************************************************************/ -static void testortfacunit_internalmatrixmatrixmultiply(/* Real */ ae_matrix* a, - ae_int_t ai1, - ae_int_t ai2, - ae_int_t aj1, - ae_int_t aj2, - ae_bool transa, - /* Real */ ae_matrix* b, - ae_int_t bi1, - ae_int_t bi2, - ae_int_t bj1, - ae_int_t bj2, - ae_bool transb, - /* Real */ ae_matrix* c, - ae_int_t ci1, - ae_int_t ci2, - ae_int_t cj1, - ae_int_t cj2, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t arows; - ae_int_t acols; - ae_int_t brows; - ae_int_t bcols; - ae_int_t crows; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t l; - ae_int_t r; - double v; - ae_vector work; - double beta; - double alpha; - - ae_frame_make(_state, &_frame_block); - memset(&work, 0, sizeof(work)); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - - - /* - * Pre-setup - */ - k = ae_maxint(ai2-ai1+1, aj2-aj1+1, _state); - k = ae_maxint(k, bi2-bi1+1, _state); - k = ae_maxint(k, bj2-bj1+1, _state); - ae_vector_set_length(&work, k+1, _state); - beta = (double)(0); - alpha = (double)(1); - - /* - * Setup - */ - if( !transa ) - { - arows = ai2-ai1+1; - acols = aj2-aj1+1; - } - else - { - arows = aj2-aj1+1; - acols = ai2-ai1+1; - } - if( !transb ) - { - brows = bi2-bi1+1; - bcols = bj2-bj1+1; - } - else - { - brows = bj2-bj1+1; - bcols = bi2-bi1+1; - } - ae_assert(acols==brows, "MatrixMatrixMultiply: incorrect matrix sizes!", _state); - if( ((arows<=0||acols<=0)||brows<=0)||bcols<=0 ) - { - ae_frame_leave(_state); - return; - } - crows = arows; - - /* - * Test WORK - */ - i = ae_maxint(arows, acols, _state); - i = ae_maxint(brows, i, _state); - i = ae_maxint(i, bcols, _state); - work.ptr.p_double[1] = (double)(0); - work.ptr.p_double[i] = (double)(0); - - /* - * Prepare C - */ - if( ae_fp_eq(beta,(double)(0)) ) - { - for(i=ci1; i<=ci2; i++) - { - for(j=cj1; j<=cj2; j++) - { - c->ptr.pp_double[i][j] = (double)(0); - } - } - } - else - { - for(i=ci1; i<=ci2; i++) - { - ae_v_muld(&c->ptr.pp_double[i][cj1], 1, ae_v_len(cj1,cj2), beta); - } - } - - /* - * A*B - */ - if( !transa&&!transb ) - { - for(l=ai1; l<=ai2; l++) - { - for(r=bi1; r<=bi2; r++) - { - v = alpha*a->ptr.pp_double[l][aj1+r-bi1]; - k = ci1+l-ai1; - ae_v_addd(&c->ptr.pp_double[k][cj1], 1, &b->ptr.pp_double[r][bj1], 1, ae_v_len(cj1,cj2), v); - } - } - ae_frame_leave(_state); - return; - } - - /* - * A*B' - */ - if( !transa&&transb ) - { - if( arows*acolsptr.pp_double[l][aj1], 1, &b->ptr.pp_double[r][bj1], 1, ae_v_len(aj1,aj2)); - c->ptr.pp_double[ci1+l-ai1][cj1+r-bi1] = c->ptr.pp_double[ci1+l-ai1][cj1+r-bi1]+alpha*v; - } - } - ae_frame_leave(_state); - return; - } - else - { - for(l=ai1; l<=ai2; l++) - { - for(r=bi1; r<=bi2; r++) - { - v = ae_v_dotproduct(&a->ptr.pp_double[l][aj1], 1, &b->ptr.pp_double[r][bj1], 1, ae_v_len(aj1,aj2)); - c->ptr.pp_double[ci1+l-ai1][cj1+r-bi1] = c->ptr.pp_double[ci1+l-ai1][cj1+r-bi1]+alpha*v; - } - } - ae_frame_leave(_state); - return; - } - } - - /* - * A'*B - */ - if( transa&&!transb ) - { - for(l=aj1; l<=aj2; l++) - { - for(r=bi1; r<=bi2; r++) - { - v = alpha*a->ptr.pp_double[ai1+r-bi1][l]; - k = ci1+l-aj1; - ae_v_addd(&c->ptr.pp_double[k][cj1], 1, &b->ptr.pp_double[r][bj1], 1, ae_v_len(cj1,cj2), v); - } - } - ae_frame_leave(_state); - return; - } - - /* - * A'*B' - */ - if( transa&&transb ) - { - if( arows*acolsptr.pp_double[r][bj1+l-ai1]; - k = cj1+r-bi1; - ae_v_addd(&work.ptr.p_double[1], 1, &a->ptr.pp_double[l][aj1], 1, ae_v_len(1,crows), v); - } - ae_v_add(&c->ptr.pp_double[ci1][k], c->stride, &work.ptr.p_double[1], 1, ae_v_len(ci1,ci2)); - } - ae_frame_leave(_state); - return; - } - else - { - for(l=aj1; l<=aj2; l++) - { - k = ai2-ai1+1; - ae_v_move(&work.ptr.p_double[1], 1, &a->ptr.pp_double[ai1][l], a->stride, ae_v_len(1,k)); - for(r=bi1; r<=bi2; r++) - { - v = ae_v_dotproduct(&work.ptr.p_double[1], 1, &b->ptr.pp_double[r][bj1], 1, ae_v_len(1,k)); - c->ptr.pp_double[ci1+l-aj1][cj1+r-bi1] = c->ptr.pp_double[ci1+l-aj1][cj1+r-bi1]+alpha*v; - } - } - ae_frame_leave(_state); - return; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Problem testing -*************************************************************************/ -static void testortfacunit_testrqrproblem(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double threshold, - ae_bool* qrerrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_matrix b; - ae_vector taub; - ae_matrix q; - ae_matrix r; - ae_matrix q2; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&b, 0, sizeof(b)); - memset(&taub, 0, sizeof(taub)); - memset(&q, 0, sizeof(q)); - memset(&r, 0, sizeof(r)); - memset(&q2, 0, sizeof(q2)); - ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&taub, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&r, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&q2, 0, 0, DT_REAL, _state, ae_true); - - - /* - * Test decompose-and-unpack error - */ - testortfacunit_rmatrixmakeacopy(a, m, n, &b, _state); - rmatrixqr(&b, m, n, &taub, _state); - rmatrixqrunpackq(&b, m, n, &taub, m, &q, _state); - rmatrixqrunpackr(&b, m, n, &r, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &r.ptr.pp_double[0][j], r.stride, ae_v_len(0,m-1)); - *qrerrors = *qrerrors||ae_fp_greater(ae_fabs(v-a->ptr.pp_double[i][j], _state),threshold); - } - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=ae_minint(i, n-1, _state)-1; j++) - { - *qrerrors = *qrerrors||ae_fp_neq(r.ptr.pp_double[i][j],(double)(0)); - } - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - v = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &q.ptr.pp_double[j][0], 1, ae_v_len(0,m-1)); - if( i==j ) - { - v = v-1; - } - *qrerrors = *qrerrors||ae_fp_greater_eq(ae_fabs(v, _state),threshold); - } - } - - /* - * Test for other errors - */ - k = 1+ae_randominteger(m, _state); - rmatrixqrunpackq(&b, m, n, &taub, k, &q2, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=k-1; j++) - { - *qrerrors = *qrerrors||ae_fp_greater(ae_fabs(q2.ptr.pp_double[i][j]-q.ptr.pp_double[i][j], _state),10*ae_machineepsilon); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Problem testing -*************************************************************************/ -static void testortfacunit_testcqrproblem(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double threshold, - ae_bool* qrerrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_matrix b; - ae_vector taub; - ae_matrix q; - ae_matrix r; - ae_matrix q2; - ae_complex v; - - ae_frame_make(_state, &_frame_block); - memset(&b, 0, sizeof(b)); - memset(&taub, 0, sizeof(taub)); - memset(&q, 0, sizeof(q)); - memset(&r, 0, sizeof(r)); - memset(&q2, 0, sizeof(q2)); - ae_matrix_init(&b, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&taub, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&q, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&r, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&q2, 0, 0, DT_COMPLEX, _state, ae_true); - - - /* - * Test decompose-and-unpack error - */ - testortfacunit_cmatrixmakeacopy(a, m, n, &b, _state); - cmatrixqr(&b, m, n, &taub, _state); - cmatrixqrunpackq(&b, m, n, &taub, m, &q, _state); - cmatrixqrunpackr(&b, m, n, &r, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_cdotproduct(&q.ptr.pp_complex[i][0], 1, "N", &r.ptr.pp_complex[0][j], r.stride, "N", ae_v_len(0,m-1)); - *qrerrors = *qrerrors||ae_fp_greater(ae_c_abs(ae_c_sub(v,a->ptr.pp_complex[i][j]), _state),threshold); - } - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=ae_minint(i, n-1, _state)-1; j++) - { - *qrerrors = *qrerrors||ae_c_neq_d(r.ptr.pp_complex[i][j],(double)(0)); - } - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - v = ae_v_cdotproduct(&q.ptr.pp_complex[i][0], 1, "N", &q.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,m-1)); - if( i==j ) - { - v = ae_c_sub_d(v,1); - } - *qrerrors = *qrerrors||ae_fp_greater_eq(ae_c_abs(v, _state),threshold); - } - } - - /* - * Test for other errors - */ - k = 1+ae_randominteger(m, _state); - cmatrixqrunpackq(&b, m, n, &taub, k, &q2, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=k-1; j++) - { - *qrerrors = *qrerrors||ae_fp_greater(ae_c_abs(ae_c_sub(q2.ptr.pp_complex[i][j],q.ptr.pp_complex[i][j]), _state),10*ae_machineepsilon); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Problem testing -*************************************************************************/ -static void testortfacunit_testrlqproblem(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double threshold, - ae_bool* lqerrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_matrix b; - ae_vector taub; - ae_matrix q; - ae_matrix l; - ae_matrix q2; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&b, 0, sizeof(b)); - memset(&taub, 0, sizeof(taub)); - memset(&q, 0, sizeof(q)); - memset(&l, 0, sizeof(l)); - memset(&q2, 0, sizeof(q2)); - ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&taub, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&l, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&q2, 0, 0, DT_REAL, _state, ae_true); - - - /* - * Test decompose-and-unpack error - */ - testortfacunit_rmatrixmakeacopy(a, m, n, &b, _state); - rmatrixlq(&b, m, n, &taub, _state); - rmatrixlqunpackq(&b, m, n, &taub, n, &q, _state); - rmatrixlqunpackl(&b, m, n, &l, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&l.ptr.pp_double[i][0], 1, &q.ptr.pp_double[0][j], q.stride, ae_v_len(0,n-1)); - *lqerrors = *lqerrors||ae_fp_greater_eq(ae_fabs(v-a->ptr.pp_double[i][j], _state),threshold); - } - } - for(i=0; i<=m-1; i++) - { - for(j=ae_minint(i, n-1, _state)+1; j<=n-1; j++) - { - *lqerrors = *lqerrors||ae_fp_neq(l.ptr.pp_double[i][j],(double)(0)); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &q.ptr.pp_double[j][0], 1, ae_v_len(0,n-1)); - if( i==j ) - { - v = v-1; - } - *lqerrors = *lqerrors||ae_fp_greater_eq(ae_fabs(v, _state),threshold); - } - } - - /* - * Test for other errors - */ - k = 1+ae_randominteger(n, _state); - rmatrixlqunpackq(&b, m, n, &taub, k, &q2, _state); - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - *lqerrors = *lqerrors||ae_fp_greater(ae_fabs(q2.ptr.pp_double[i][j]-q.ptr.pp_double[i][j], _state),10*ae_machineepsilon); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Problem testing -*************************************************************************/ -static void testortfacunit_testclqproblem(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double threshold, - ae_bool* lqerrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_matrix b; - ae_vector taub; - ae_matrix q; - ae_matrix l; - ae_matrix q2; - ae_complex v; - - ae_frame_make(_state, &_frame_block); - memset(&b, 0, sizeof(b)); - memset(&taub, 0, sizeof(taub)); - memset(&q, 0, sizeof(q)); - memset(&l, 0, sizeof(l)); - memset(&q2, 0, sizeof(q2)); - ae_matrix_init(&b, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&taub, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&q, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&l, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&q2, 0, 0, DT_COMPLEX, _state, ae_true); - - - /* - * Test decompose-and-unpack error - */ - testortfacunit_cmatrixmakeacopy(a, m, n, &b, _state); - cmatrixlq(&b, m, n, &taub, _state); - cmatrixlqunpackq(&b, m, n, &taub, n, &q, _state); - cmatrixlqunpackl(&b, m, n, &l, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_cdotproduct(&l.ptr.pp_complex[i][0], 1, "N", &q.ptr.pp_complex[0][j], q.stride, "N", ae_v_len(0,n-1)); - *lqerrors = *lqerrors||ae_fp_greater_eq(ae_c_abs(ae_c_sub(v,a->ptr.pp_complex[i][j]), _state),threshold); - } - } - for(i=0; i<=m-1; i++) - { - for(j=ae_minint(i, n-1, _state)+1; j<=n-1; j++) - { - *lqerrors = *lqerrors||ae_c_neq_d(l.ptr.pp_complex[i][j],(double)(0)); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_cdotproduct(&q.ptr.pp_complex[i][0], 1, "N", &q.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,n-1)); - if( i==j ) - { - v = ae_c_sub_d(v,1); - } - *lqerrors = *lqerrors||ae_fp_greater_eq(ae_c_abs(v, _state),threshold); - } - } - - /* - * Test for other errors - */ - k = 1+ae_randominteger(n, _state); - cmatrixlqunpackq(&b, m, n, &taub, k, &q2, _state); - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - *lqerrors = *lqerrors||ae_fp_greater(ae_c_abs(ae_c_sub(q2.ptr.pp_complex[i][j],q.ptr.pp_complex[i][j]), _state),10*ae_machineepsilon); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Problem testing -*************************************************************************/ -static void testortfacunit_testrbdproblem(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double threshold, - ae_bool* bderrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_matrix t; - ae_matrix pt; - ae_matrix q; - ae_matrix r; - ae_matrix bd; - ae_matrix x; - ae_matrix r1; - ae_matrix r2; - ae_vector taup; - ae_vector tauq; - ae_vector d; - ae_vector e; - ae_bool up; - double v; - ae_int_t mtsize; - - ae_frame_make(_state, &_frame_block); - memset(&t, 0, sizeof(t)); - memset(&pt, 0, sizeof(pt)); - memset(&q, 0, sizeof(q)); - memset(&r, 0, sizeof(r)); - memset(&bd, 0, sizeof(bd)); - memset(&x, 0, sizeof(x)); - memset(&r1, 0, sizeof(r1)); - memset(&r2, 0, sizeof(r2)); - memset(&taup, 0, sizeof(taup)); - memset(&tauq, 0, sizeof(tauq)); - memset(&d, 0, sizeof(d)); - memset(&e, 0, sizeof(e)); - ae_matrix_init(&t, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&pt, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&r, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&bd, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&x, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&r1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&r2, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&taup, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tauq, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&e, 0, DT_REAL, _state, ae_true); - - - /* - * Bidiagonal decomposition error - */ - testortfacunit_rmatrixmakeacopy(a, m, n, &t, _state); - rmatrixbd(&t, m, n, &tauq, &taup, _state); - rmatrixbdunpackq(&t, m, n, &tauq, m, &q, _state); - rmatrixbdunpackpt(&t, m, n, &taup, n, &pt, _state); - rmatrixbdunpackdiagonals(&t, m, n, &up, &d, &e, _state); - ae_matrix_set_length(&bd, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - bd.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=ae_minint(m, n, _state)-1; i++) - { - bd.ptr.pp_double[i][i] = d.ptr.p_double[i]; - } - if( up ) - { - for(i=0; i<=ae_minint(m, n, _state)-2; i++) - { - bd.ptr.pp_double[i][i+1] = e.ptr.p_double[i]; - } - } - else - { - for(i=0; i<=ae_minint(m, n, _state)-2; i++) - { - bd.ptr.pp_double[i+1][i] = e.ptr.p_double[i]; - } - } - ae_matrix_set_length(&r, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &bd.ptr.pp_double[0][j], bd.stride, ae_v_len(0,m-1)); - r.ptr.pp_double[i][j] = v; - } - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&r.ptr.pp_double[i][0], 1, &pt.ptr.pp_double[0][j], pt.stride, ae_v_len(0,n-1)); - *bderrors = *bderrors||ae_fp_greater(ae_fabs(v-a->ptr.pp_double[i][j], _state),threshold); - } - } - - /* - * Orthogonality test for Q/PT - */ - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - v = ae_v_dotproduct(&q.ptr.pp_double[0][i], q.stride, &q.ptr.pp_double[0][j], q.stride, ae_v_len(0,m-1)); - if( i==j ) - { - *bderrors = *bderrors||ae_fp_greater(ae_fabs(v-1, _state),threshold); - } - else - { - *bderrors = *bderrors||ae_fp_greater(ae_fabs(v, _state),threshold); - } - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&pt.ptr.pp_double[i][0], 1, &pt.ptr.pp_double[j][0], 1, ae_v_len(0,n-1)); - if( i==j ) - { - *bderrors = *bderrors||ae_fp_greater(ae_fabs(v-1, _state),threshold); - } - else - { - *bderrors = *bderrors||ae_fp_greater(ae_fabs(v, _state),threshold); - } - } - } - - /* - * Partial unpacking test - */ - k = 1+ae_randominteger(m, _state); - rmatrixbdunpackq(&t, m, n, &tauq, k, &r, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=k-1; j++) - { - *bderrors = *bderrors||ae_fp_greater(ae_fabs(r.ptr.pp_double[i][j]-q.ptr.pp_double[i][j], _state),10*ae_machineepsilon); - } - } - k = 1+ae_randominteger(n, _state); - rmatrixbdunpackpt(&t, m, n, &taup, k, &r, _state); - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - *bderrors = *bderrors||ae_fp_greater(ae_fabs(r.ptr.pp_double[i][j]-pt.ptr.pp_double[i][j], _state),10*ae_machineepsilon); - } - } - - /* - * Multiplication test - */ - ae_matrix_set_length(&x, ae_maxint(m, n, _state)-1+1, ae_maxint(m, n, _state)-1+1, _state); - ae_matrix_set_length(&r, ae_maxint(m, n, _state)-1+1, ae_maxint(m, n, _state)-1+1, _state); - ae_matrix_set_length(&r1, ae_maxint(m, n, _state)-1+1, ae_maxint(m, n, _state)-1+1, _state); - ae_matrix_set_length(&r2, ae_maxint(m, n, _state)-1+1, ae_maxint(m, n, _state)-1+1, _state); - for(i=0; i<=ae_maxint(m, n, _state)-1; i++) - { - for(j=0; j<=ae_maxint(m, n, _state)-1; j++) - { - x.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - mtsize = 1+ae_randominteger(ae_maxint(m, n, _state), _state); - testortfacunit_rmatrixmakeacopy(&x, mtsize, m, &r, _state); - testortfacunit_internalmatrixmatrixmultiply(&r, 0, mtsize-1, 0, m-1, ae_false, &q, 0, m-1, 0, m-1, ae_false, &r1, 0, mtsize-1, 0, m-1, _state); - testortfacunit_rmatrixmakeacopy(&x, mtsize, m, &r2, _state); - rmatrixbdmultiplybyq(&t, m, n, &tauq, &r2, mtsize, m, ae_true, ae_false, _state); - *bderrors = *bderrors||ae_fp_greater(testortfacunit_rmatrixdiff(&r1, &r2, mtsize, m, _state),threshold); - testortfacunit_rmatrixmakeacopy(&x, mtsize, m, &r, _state); - testortfacunit_internalmatrixmatrixmultiply(&r, 0, mtsize-1, 0, m-1, ae_false, &q, 0, m-1, 0, m-1, ae_true, &r1, 0, mtsize-1, 0, m-1, _state); - testortfacunit_rmatrixmakeacopy(&x, mtsize, m, &r2, _state); - rmatrixbdmultiplybyq(&t, m, n, &tauq, &r2, mtsize, m, ae_true, ae_true, _state); - *bderrors = *bderrors||ae_fp_greater(testortfacunit_rmatrixdiff(&r1, &r2, mtsize, m, _state),threshold); - testortfacunit_rmatrixmakeacopy(&x, m, mtsize, &r, _state); - testortfacunit_internalmatrixmatrixmultiply(&q, 0, m-1, 0, m-1, ae_false, &r, 0, m-1, 0, mtsize-1, ae_false, &r1, 0, m-1, 0, mtsize-1, _state); - testortfacunit_rmatrixmakeacopy(&x, m, mtsize, &r2, _state); - rmatrixbdmultiplybyq(&t, m, n, &tauq, &r2, m, mtsize, ae_false, ae_false, _state); - *bderrors = *bderrors||ae_fp_greater(testortfacunit_rmatrixdiff(&r1, &r2, m, mtsize, _state),threshold); - testortfacunit_rmatrixmakeacopy(&x, m, mtsize, &r, _state); - testortfacunit_internalmatrixmatrixmultiply(&q, 0, m-1, 0, m-1, ae_true, &r, 0, m-1, 0, mtsize-1, ae_false, &r1, 0, m-1, 0, mtsize-1, _state); - testortfacunit_rmatrixmakeacopy(&x, m, mtsize, &r2, _state); - rmatrixbdmultiplybyq(&t, m, n, &tauq, &r2, m, mtsize, ae_false, ae_true, _state); - *bderrors = *bderrors||ae_fp_greater(testortfacunit_rmatrixdiff(&r1, &r2, m, mtsize, _state),threshold); - testortfacunit_rmatrixmakeacopy(&x, mtsize, n, &r, _state); - testortfacunit_internalmatrixmatrixmultiply(&r, 0, mtsize-1, 0, n-1, ae_false, &pt, 0, n-1, 0, n-1, ae_true, &r1, 0, mtsize-1, 0, n-1, _state); - testortfacunit_rmatrixmakeacopy(&x, mtsize, n, &r2, _state); - rmatrixbdmultiplybyp(&t, m, n, &taup, &r2, mtsize, n, ae_true, ae_false, _state); - *bderrors = *bderrors||ae_fp_greater(testortfacunit_rmatrixdiff(&r1, &r2, mtsize, n, _state),threshold); - testortfacunit_rmatrixmakeacopy(&x, mtsize, n, &r, _state); - testortfacunit_internalmatrixmatrixmultiply(&r, 0, mtsize-1, 0, n-1, ae_false, &pt, 0, n-1, 0, n-1, ae_false, &r1, 0, mtsize-1, 0, n-1, _state); - testortfacunit_rmatrixmakeacopy(&x, mtsize, n, &r2, _state); - rmatrixbdmultiplybyp(&t, m, n, &taup, &r2, mtsize, n, ae_true, ae_true, _state); - *bderrors = *bderrors||ae_fp_greater(testortfacunit_rmatrixdiff(&r1, &r2, mtsize, n, _state),threshold); - testortfacunit_rmatrixmakeacopy(&x, n, mtsize, &r, _state); - testortfacunit_internalmatrixmatrixmultiply(&pt, 0, n-1, 0, n-1, ae_true, &r, 0, n-1, 0, mtsize-1, ae_false, &r1, 0, n-1, 0, mtsize-1, _state); - testortfacunit_rmatrixmakeacopy(&x, n, mtsize, &r2, _state); - rmatrixbdmultiplybyp(&t, m, n, &taup, &r2, n, mtsize, ae_false, ae_false, _state); - *bderrors = *bderrors||ae_fp_greater(testortfacunit_rmatrixdiff(&r1, &r2, n, mtsize, _state),threshold); - testortfacunit_rmatrixmakeacopy(&x, n, mtsize, &r, _state); - testortfacunit_internalmatrixmatrixmultiply(&pt, 0, n-1, 0, n-1, ae_false, &r, 0, n-1, 0, mtsize-1, ae_false, &r1, 0, n-1, 0, mtsize-1, _state); - testortfacunit_rmatrixmakeacopy(&x, n, mtsize, &r2, _state); - rmatrixbdmultiplybyp(&t, m, n, &taup, &r2, n, mtsize, ae_false, ae_true, _state); - *bderrors = *bderrors||ae_fp_greater(testortfacunit_rmatrixdiff(&r1, &r2, n, mtsize, _state),threshold); - ae_frame_leave(_state); -} - - -/************************************************************************* -Problem testing -*************************************************************************/ -static void testortfacunit_testrhessproblem(/* Real */ ae_matrix* a, - ae_int_t n, - double threshold, - ae_bool* hesserrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix b; - ae_matrix h; - ae_matrix q; - ae_matrix t1; - ae_matrix t2; - ae_vector tau; - ae_int_t i; - ae_int_t j; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&b, 0, sizeof(b)); - memset(&h, 0, sizeof(h)); - memset(&q, 0, sizeof(q)); - memset(&t1, 0, sizeof(t1)); - memset(&t2, 0, sizeof(t2)); - memset(&tau, 0, sizeof(tau)); - ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&h, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&t1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&t2, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tau, 0, DT_REAL, _state, ae_true); - - testortfacunit_rmatrixmakeacopy(a, n, n, &b, _state); - - /* - * Decomposition - */ - rmatrixhessenberg(&b, n, &tau, _state); - rmatrixhessenbergunpackq(&b, n, &tau, &q, _state); - rmatrixhessenbergunpackh(&b, n, &h, _state); - - /* - * Matrix properties - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&q.ptr.pp_double[0][i], q.stride, &q.ptr.pp_double[0][j], q.stride, ae_v_len(0,n-1)); - if( i==j ) - { - v = v-1; - } - *hesserrors = *hesserrors||ae_fp_greater(ae_fabs(v, _state),threshold); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i-2; j++) - { - *hesserrors = *hesserrors||ae_fp_neq(h.ptr.pp_double[i][j],(double)(0)); - } - } - - /* - * Decomposition error - */ - ae_matrix_set_length(&t1, n, n, _state); - ae_matrix_set_length(&t2, n, n, _state); - testortfacunit_internalmatrixmatrixmultiply(&q, 0, n-1, 0, n-1, ae_false, &h, 0, n-1, 0, n-1, ae_false, &t1, 0, n-1, 0, n-1, _state); - testortfacunit_internalmatrixmatrixmultiply(&t1, 0, n-1, 0, n-1, ae_false, &q, 0, n-1, 0, n-1, ae_true, &t2, 0, n-1, 0, n-1, _state); - *hesserrors = *hesserrors||ae_fp_greater(testortfacunit_rmatrixdiff(&t2, a, n, n, _state),threshold); - ae_frame_leave(_state); -} - - -/************************************************************************* -Tridiagonal tester -*************************************************************************/ -static void testortfacunit_testrtdproblem(/* Real */ ae_matrix* a, - ae_int_t n, - double threshold, - ae_bool* tderrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_matrix ua; - ae_matrix la; - ae_matrix t; - ae_matrix q; - ae_matrix t2; - ae_matrix t3; - ae_vector tau; - ae_vector d; - ae_vector e; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&ua, 0, sizeof(ua)); - memset(&la, 0, sizeof(la)); - memset(&t, 0, sizeof(t)); - memset(&q, 0, sizeof(q)); - memset(&t2, 0, sizeof(t2)); - memset(&t3, 0, sizeof(t3)); - memset(&tau, 0, sizeof(tau)); - memset(&d, 0, sizeof(d)); - memset(&e, 0, sizeof(e)); - ae_matrix_init(&ua, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&la, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&t, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&t2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&t3, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tau, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&e, 0, DT_REAL, _state, ae_true); - - ae_matrix_set_length(&ua, n-1+1, n-1+1, _state); - ae_matrix_set_length(&la, n-1+1, n-1+1, _state); - ae_matrix_set_length(&t, n-1+1, n-1+1, _state); - ae_matrix_set_length(&q, n-1+1, n-1+1, _state); - ae_matrix_set_length(&t2, n-1+1, n-1+1, _state); - ae_matrix_set_length(&t3, n-1+1, n-1+1, _state); - - /* - * fill - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - ua.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - ua.ptr.pp_double[i][j] = a->ptr.pp_double[i][j]; - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - la.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i; j++) - { - la.ptr.pp_double[i][j] = a->ptr.pp_double[i][j]; - } - } - - /* - * Test 2tridiagonal: upper - */ - smatrixtd(&ua, n, ae_true, &tau, &d, &e, _state); - smatrixtdunpackq(&ua, n, ae_true, &tau, &q, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - t.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=n-1; i++) - { - t.ptr.pp_double[i][i] = d.ptr.p_double[i]; - } - for(i=0; i<=n-2; i++) - { - t.ptr.pp_double[i][i+1] = e.ptr.p_double[i]; - t.ptr.pp_double[i+1][i] = e.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&q.ptr.pp_double[0][i], q.stride, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,n-1)); - t2.ptr.pp_double[i][j] = v; - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&t2.ptr.pp_double[i][0], 1, &q.ptr.pp_double[0][j], q.stride, ae_v_len(0,n-1)); - t3.ptr.pp_double[i][j] = v; - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - *tderrors = *tderrors||ae_fp_greater(ae_fabs(t3.ptr.pp_double[i][j]-t.ptr.pp_double[i][j], _state),threshold); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &q.ptr.pp_double[j][0], 1, ae_v_len(0,n-1)); - if( i==j ) - { - v = v-1; - } - *tderrors = *tderrors||ae_fp_greater(ae_fabs(v, _state),threshold); - } - } - - /* - * Test 2tridiagonal: lower - */ - smatrixtd(&la, n, ae_false, &tau, &d, &e, _state); - smatrixtdunpackq(&la, n, ae_false, &tau, &q, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - t.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=n-1; i++) - { - t.ptr.pp_double[i][i] = d.ptr.p_double[i]; - } - for(i=0; i<=n-2; i++) - { - t.ptr.pp_double[i][i+1] = e.ptr.p_double[i]; - t.ptr.pp_double[i+1][i] = e.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&q.ptr.pp_double[0][i], q.stride, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,n-1)); - t2.ptr.pp_double[i][j] = v; - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&t2.ptr.pp_double[i][0], 1, &q.ptr.pp_double[0][j], q.stride, ae_v_len(0,n-1)); - t3.ptr.pp_double[i][j] = v; - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - *tderrors = *tderrors||ae_fp_greater(ae_fabs(t3.ptr.pp_double[i][j]-t.ptr.pp_double[i][j], _state),threshold); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &q.ptr.pp_double[j][0], 1, ae_v_len(0,n-1)); - if( i==j ) - { - v = v-1; - } - *tderrors = *tderrors||ae_fp_greater(ae_fabs(v, _state),threshold); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Hermitian problem tester -*************************************************************************/ -static void testortfacunit_testctdproblem(/* Complex */ ae_matrix* a, - ae_int_t n, - double threshold, - ae_bool* tderrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_matrix ua; - ae_matrix la; - ae_matrix t; - ae_matrix q; - ae_matrix t2; - ae_matrix t3; - ae_vector tau; - ae_vector d; - ae_vector e; - ae_complex v; - - ae_frame_make(_state, &_frame_block); - memset(&ua, 0, sizeof(ua)); - memset(&la, 0, sizeof(la)); - memset(&t, 0, sizeof(t)); - memset(&q, 0, sizeof(q)); - memset(&t2, 0, sizeof(t2)); - memset(&t3, 0, sizeof(t3)); - memset(&tau, 0, sizeof(tau)); - memset(&d, 0, sizeof(d)); - memset(&e, 0, sizeof(e)); - ae_matrix_init(&ua, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&la, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&t, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&q, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&t2, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&t3, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&tau, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&e, 0, DT_REAL, _state, ae_true); - - ae_matrix_set_length(&ua, n-1+1, n-1+1, _state); - ae_matrix_set_length(&la, n-1+1, n-1+1, _state); - ae_matrix_set_length(&t, n-1+1, n-1+1, _state); - ae_matrix_set_length(&q, n-1+1, n-1+1, _state); - ae_matrix_set_length(&t2, n-1+1, n-1+1, _state); - ae_matrix_set_length(&t3, n-1+1, n-1+1, _state); - - /* - * fill - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - ua.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - ua.ptr.pp_complex[i][j] = a->ptr.pp_complex[i][j]; - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - la.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i; j++) - { - la.ptr.pp_complex[i][j] = a->ptr.pp_complex[i][j]; - } - } - - /* - * Test 2tridiagonal: upper - */ - hmatrixtd(&ua, n, ae_true, &tau, &d, &e, _state); - hmatrixtdunpackq(&ua, n, ae_true, &tau, &q, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - t.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - for(i=0; i<=n-1; i++) - { - t.ptr.pp_complex[i][i] = ae_complex_from_d(d.ptr.p_double[i]); - } - for(i=0; i<=n-2; i++) - { - t.ptr.pp_complex[i][i+1] = ae_complex_from_d(e.ptr.p_double[i]); - t.ptr.pp_complex[i+1][i] = ae_complex_from_d(e.ptr.p_double[i]); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_cdotproduct(&q.ptr.pp_complex[0][i], q.stride, "Conj", &a->ptr.pp_complex[0][j], a->stride, "N", ae_v_len(0,n-1)); - t2.ptr.pp_complex[i][j] = v; - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_cdotproduct(&t2.ptr.pp_complex[i][0], 1, "N", &q.ptr.pp_complex[0][j], q.stride, "N", ae_v_len(0,n-1)); - t3.ptr.pp_complex[i][j] = v; - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - *tderrors = *tderrors||ae_fp_greater(ae_c_abs(ae_c_sub(t3.ptr.pp_complex[i][j],t.ptr.pp_complex[i][j]), _state),threshold); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_cdotproduct(&q.ptr.pp_complex[i][0], 1, "N", &q.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,n-1)); - if( i==j ) - { - v = ae_c_sub_d(v,1); - } - *tderrors = *tderrors||ae_fp_greater(ae_c_abs(v, _state),threshold); - } - } - - /* - * Test 2tridiagonal: lower - */ - hmatrixtd(&la, n, ae_false, &tau, &d, &e, _state); - hmatrixtdunpackq(&la, n, ae_false, &tau, &q, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - t.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - for(i=0; i<=n-1; i++) - { - t.ptr.pp_complex[i][i] = ae_complex_from_d(d.ptr.p_double[i]); - } - for(i=0; i<=n-2; i++) - { - t.ptr.pp_complex[i][i+1] = ae_complex_from_d(e.ptr.p_double[i]); - t.ptr.pp_complex[i+1][i] = ae_complex_from_d(e.ptr.p_double[i]); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_cdotproduct(&q.ptr.pp_complex[0][i], q.stride, "Conj", &a->ptr.pp_complex[0][j], a->stride, "N", ae_v_len(0,n-1)); - t2.ptr.pp_complex[i][j] = v; - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_cdotproduct(&t2.ptr.pp_complex[i][0], 1, "N", &q.ptr.pp_complex[0][j], q.stride, "N", ae_v_len(0,n-1)); - t3.ptr.pp_complex[i][j] = v; - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - *tderrors = *tderrors||ae_fp_greater(ae_c_abs(ae_c_sub(t3.ptr.pp_complex[i][j],t.ptr.pp_complex[i][j]), _state),threshold); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_cdotproduct(&q.ptr.pp_complex[i][0], 1, "N", &q.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,n-1)); - if( i==j ) - { - v = ae_c_sub_d(v,1); - } - *tderrors = *tderrors||ae_fp_greater(ae_c_abs(v, _state),threshold); - } - } - ae_frame_leave(_state); -} - - - -static void testfblsunit_testgmres(ae_bool* err, ae_state *_state); - - - - - -/************************************************************************* -Testing -*************************************************************************/ -ae_bool testfbls(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t m; - ae_int_t mx; - ae_int_t i; - ae_int_t j; - ae_bool waserrors; - ae_bool cgerrors; - ae_bool lserrors; - ae_bool cholerrors; - ae_bool gmreserrors; - double eps; - double v; - double v1; - double v2; - ae_vector tmp0; - ae_vector tmp1; - ae_vector tmp2; - double scalea; - ae_bool uppera; - ae_matrix a; - ae_matrix ea; - ae_vector b; - ae_vector x; - ae_vector xe; - ae_vector buf; - double alpha; - double e1; - double e2; - fblslincgstate cgstate; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&tmp0, 0, sizeof(tmp0)); - memset(&tmp1, 0, sizeof(tmp1)); - memset(&tmp2, 0, sizeof(tmp2)); - memset(&a, 0, sizeof(a)); - memset(&ea, 0, sizeof(ea)); - memset(&b, 0, sizeof(b)); - memset(&x, 0, sizeof(x)); - memset(&xe, 0, sizeof(xe)); - memset(&buf, 0, sizeof(buf)); - memset(&cgstate, 0, sizeof(cgstate)); - ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp2, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ea, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xe, 0, DT_REAL, _state, ae_true); - ae_vector_init(&buf, 0, DT_REAL, _state, ae_true); - _fblslincgstate_init(&cgstate, _state, ae_true); - - mx = 10; - waserrors = ae_false; - cgerrors = ae_false; - lserrors = ae_false; - cholerrors = ae_false; - gmreserrors = ae_false; - - /* - * - */ - testfblsunit_testgmres(&gmreserrors, _state); - - /* - * Test CG solver: - * * generate problem (A, B, Alpha, XE - exact solution) and initial approximation X - * * E1 = ||A'A*x-b|| - * * solve - * * E2 = ||A'A*x-b|| - * * test that E2<0.001*E1 - */ - for(n=1; n<=mx; n++) - { - for(m=1; m<=mx; m++) - { - ae_matrix_set_length(&a, m, n, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&xe, n, _state); - ae_vector_set_length(&tmp1, m, _state); - ae_vector_set_length(&tmp2, n, _state); - - /* - * init A, alpha, B, X (initial approximation), XE (exact solution) - * X is initialized in such way that is has no chances to be equal to XE. - */ - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - alpha = ae_randomreal(_state)+0.1; - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - xe.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x.ptr.p_double[i] = (2*ae_randominteger(2, _state)-1)*(2+ae_randomreal(_state)); - } - - /* - * Test dense CG (which solves A'A*x=b and accepts dense A) - */ - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = (2*ae_randominteger(2, _state)-1)*(2+ae_randomreal(_state)); - } - rmatrixmv(m, n, &a, 0, 0, 0, &x, 0, &tmp1, 0, _state); - rmatrixmv(n, m, &a, 0, 0, 1, &tmp1, 0, &tmp2, 0, _state); - ae_v_addd(&tmp2.ptr.p_double[0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1), alpha); - ae_v_sub(&tmp2.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = ae_v_dotproduct(&tmp2.ptr.p_double[0], 1, &tmp2.ptr.p_double[0], 1, ae_v_len(0,n-1)); - e1 = ae_sqrt(v, _state); - fblssolvecgx(&a, m, n, alpha, &b, &x, &buf, _state); - rmatrixmv(m, n, &a, 0, 0, 0, &x, 0, &tmp1, 0, _state); - rmatrixmv(n, m, &a, 0, 0, 1, &tmp1, 0, &tmp2, 0, _state); - ae_v_addd(&tmp2.ptr.p_double[0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1), alpha); - ae_v_sub(&tmp2.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = ae_v_dotproduct(&tmp2.ptr.p_double[0], 1, &tmp2.ptr.p_double[0], 1, ae_v_len(0,n-1)); - e2 = ae_sqrt(v, _state); - cgerrors = cgerrors||ae_fp_greater(e2,0.001*e1); - - /* - * Test sparse CG (which relies on reverse communication) - */ - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = (2*ae_randominteger(2, _state)-1)*(2+ae_randomreal(_state)); - } - rmatrixmv(m, n, &a, 0, 0, 0, &x, 0, &tmp1, 0, _state); - rmatrixmv(n, m, &a, 0, 0, 1, &tmp1, 0, &tmp2, 0, _state); - ae_v_addd(&tmp2.ptr.p_double[0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1), alpha); - ae_v_sub(&tmp2.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = ae_v_dotproduct(&tmp2.ptr.p_double[0], 1, &tmp2.ptr.p_double[0], 1, ae_v_len(0,n-1)); - e1 = ae_sqrt(v, _state); - fblscgcreate(&x, &b, n, &cgstate, _state); - while(fblscgiteration(&cgstate, _state)) - { - rmatrixmv(m, n, &a, 0, 0, 0, &cgstate.x, 0, &tmp1, 0, _state); - rmatrixmv(n, m, &a, 0, 0, 1, &tmp1, 0, &cgstate.ax, 0, _state); - ae_v_addd(&cgstate.ax.ptr.p_double[0], 1, &cgstate.x.ptr.p_double[0], 1, ae_v_len(0,n-1), alpha); - v1 = ae_v_dotproduct(&tmp1.ptr.p_double[0], 1, &tmp1.ptr.p_double[0], 1, ae_v_len(0,m-1)); - v2 = ae_v_dotproduct(&cgstate.x.ptr.p_double[0], 1, &cgstate.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - cgstate.xax = v1+alpha*v2; - } - rmatrixmv(m, n, &a, 0, 0, 0, &cgstate.xk, 0, &tmp1, 0, _state); - rmatrixmv(n, m, &a, 0, 0, 1, &tmp1, 0, &tmp2, 0, _state); - ae_v_addd(&tmp2.ptr.p_double[0], 1, &cgstate.xk.ptr.p_double[0], 1, ae_v_len(0,n-1), alpha); - ae_v_sub(&tmp2.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = ae_v_dotproduct(&tmp2.ptr.p_double[0], 1, &tmp2.ptr.p_double[0], 1, ae_v_len(0,n-1)); - e2 = ae_sqrt(v, _state); - cgerrors = cgerrors||ae_fp_greater(ae_fabs(e1-cgstate.e1, _state),100*ae_machineepsilon*e1); - cgerrors = cgerrors||ae_fp_greater(ae_fabs(e2-cgstate.e2, _state),100*ae_machineepsilon*e1); - cgerrors = cgerrors||ae_fp_greater(e2,0.001*e1); - } - } - - /* - * Test linear least squares: - * * try N=1..5, M=N..2*N - * [ B ] - * * generate MxN matrix A = [ ], where (M-N)xN submatrix B contains - * [ C ] - * random values from [-1,+1], and NxN submatrix C is diagonally dominant - * (diagonal of C is equal to 1.0, and magnitude of off-diagonal elements - * is smaller than 0.01). Such matrix is guaranteed to be non-degenerate. - * * generate random known solution xe, set right part b=A*xe - * * check that results of FBLSSolveLS agree with xe - */ - eps = 1.0E-6; - for(n=1; n<=5; n++) - { - for(m=n; m<=2*n; m++) - { - ae_matrix_set_length(&a, m, n, _state); - for(i=0; i<=m-n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - for(i=m-n; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.01*(2*ae_randomreal(_state)-1); - } - a.ptr.pp_double[i][i-(m-n)] = 1.0; - } - ae_vector_set_length(&xe, n, _state); - for(i=0; i<=n-1; i++) - { - xe.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - ae_vector_set_length(&b, m, _state); - for(i=0; i<=m-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xe.ptr.p_double[0], 1, ae_v_len(0,n-1)); - b.ptr.p_double[i] = v; - } - fblssolvels(&a, &b, m, n, &tmp0, &tmp1, &tmp2, _state); - for(i=0; i<=n-1; i++) - { - lserrors = lserrors||ae_fp_greater(ae_fabs(b.ptr.p_double[i]-xe.ptr.p_double[i], _state),eps); - } - } - } - - /* - * Test Cholesky solver: - * * generate trial A, ScaleA, XS and corresponding right part B - */ - for(n=1; n<=30; n++) - { - - /* - * Generate test problem - */ - ae_matrix_set_length(&a, n, n, _state); - ae_matrix_set_length(&ea, n, n, _state); - ae_vector_set_length(&xe, n, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&buf, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.01*(ae_randomreal(_state)-0.5); - } - a.ptr.pp_double[i][i] = 1+ae_randomreal(_state); - xe.ptr.p_double[i] = ae_randomreal(_state)-0.5; - } - scalea = ae_pow((double)(10), ae_randomreal(_state)*4-2, _state); - uppera = ae_fp_greater(ae_randomreal(_state),0.5); - for(i=0; i<=n-1; i++) - { - if( uppera ) - { - for(j=0; j<=i-1; j++) - { - ea.ptr.pp_double[i][j] = (double)(0); - } - for(j=i; j<=n-1; j++) - { - ea.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]; - } - } - else - { - for(j=0; j<=i; j++) - { - ea.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]; - } - for(j=i+1; j<=n-1; j++) - { - ea.ptr.pp_double[i][j] = (double)(0); - } - } - } - if( uppera ) - { - rmatrixgemv(n, n, 1.0, &ea, 0, 0, 0, &xe, 0, 0.0, &buf, 0, _state); - rmatrixgemv(n, n, 1.0, &ea, 0, 0, 1, &buf, 0, 0.0, &b, 0, _state); - } - else - { - rmatrixgemv(n, n, 1.0, &ea, 0, 0, 1, &xe, 0, 0.0, &buf, 0, _state); - rmatrixgemv(n, n, 1.0, &ea, 0, 0, 0, &buf, 0, 0.0, &b, 0, _state); - } - ae_v_muld(&b.ptr.p_double[0], 1, ae_v_len(0,n-1), scalea); - - /* - * Test - */ - fblscholeskysolve(&a, ae_sqrt(scalea, _state), n, uppera, &b, &buf, _state); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(&cholerrors, ae_fp_greater(ae_fabs(b.ptr.p_double[i]-xe.ptr.p_double[i], _state),1.0E3*ae_machineepsilon), __FILE__, __LINE__, "testfblsunit.ap:291"); - } - } - - /* - * report - */ - waserrors = ((cgerrors||lserrors)||cholerrors)||gmreserrors; - if( !silent ) - { - printf("TESTING FBLS\n"); - printf("CG ERRORS: "); - if( cgerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("LS ERRORS: "); - if( lserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("CHOL ERRORS: "); - if( cholerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("GMRES ERRORS: "); - if( gmreserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Testing GMRES. Sets error flag on failure, does not change it on success. -*************************************************************************/ -static void testfblsunit_testgmres(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t n; - ae_int_t rk; - ae_int_t itscnt; - ae_matrix a; - ae_matrix c; - ae_vector b; - ae_vector r; - ae_vector xe; - hqrndstate rs; - fblsgmresstate state; - double e; - double eprev; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&c, 0, sizeof(c)); - memset(&b, 0, sizeof(b)); - memset(&r, 0, sizeof(r)); - memset(&xe, 0, sizeof(xe)); - memset(&rs, 0, sizeof(rs)); - memset(&state, 0, sizeof(state)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&r, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xe, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - _fblsgmresstate_init(&state, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Test following properties: - * * increasing iterations count results in decreased residual - * * residual with ItsCnt=N is nearly zero - * * State.Qi are orthonormal - */ - for(n=1; n<=5; n++) - { - - /* - * Create problem - */ - hqrndnormalv(&rs, n, &b, _state); - hqrndnormalm(&rs, n, n, &a, _state); - - /* - * Test sequence of iteration counts - */ - eprev = ae_maxrealnumber; - for(itscnt=1; itscnt<=n; itscnt++) - { - - /* - * Solve - */ - fblsgmrescreate(&b, n, itscnt, &state, _state); - while(fblsgmresiteration(&state, _state)) - { - rmatrixmv(n, n, &a, 0, 0, 0, &state.x, 0, &state.ax, 0, _state); - } - - /* - * Check orthonormality of Qi - */ - ae_set_error_flag(err, state.qi.rows=k - */ - for(n=2; n<=10; n++) - { - for(rk=1; rk<=n-1; rk++) - { - - /* - * Create problem - */ - hqrndnormalm(&rs, n, rk, &c, _state); - ae_matrix_set_length(&a, n, n, _state); - rmatrixgemm(n, n, rk, 1.0, &c, 0, 0, 0, &c, 0, 0, 1, 0.0, &a, 0, 0, _state); - hqrndnormalv(&rs, n, &xe, _state); - ae_vector_set_length(&b, n, _state); - rmatrixmv(n, n, &a, 0, 0, 0, &xe, 0, &b, 0, _state); - - /* - * Try various iteration counts - */ - for(itscnt=rk; itscnt<=n; itscnt++) - { - - /* - * Solve - */ - fblsgmrescreate(&b, n, itscnt, &state, _state); - while(fblsgmresiteration(&state, _state)) - { - rmatrixmv(n, n, &a, 0, 0, 0, &state.x, 0, &state.ax, 0, _state); - } - - /* - * Compute residual - */ - rallocv(n, &r, _state); - rmatrixmv(n, n, &a, 0, 0, 0, &state.xs, 0, &r, 0, _state); - raddv(n, -1.0, &b, &r, _state); - e = ae_sqrt(rdotv2(n, &r, _state), _state); - - /* - * Test condition - */ - ae_set_error_flag(err, ae_fp_greater(e,1.0E6*ae_machineepsilon), __FILE__, __LINE__, "testfblsunit.ap:449"); - } - } - } - - /* - * Test with zero matrix - */ - for(n=1; n<=10; n++) - { - for(itscnt=1; itscnt<=n; itscnt++) - { - - /* - * Create problem - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - hqrndnormalv(&rs, n, &b, _state); - - /* - * Try to solve - */ - fblsgmrescreate(&b, n, itscnt, &state, _state); - while(fblsgmresiteration(&state, _state)) - { - rmatrixmv(n, n, &a, 0, 0, 0, &state.x, 0, &state.ax, 0, _state); - } - - /* - * Test solution - */ - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(err, ae_fp_neq(state.xs.ptr.p_double[i],0.0), __FILE__, __LINE__, "testfblsunit.ap:479"); - } - } - } - ae_frame_leave(_state); -} - - - - - - - - -ae_bool testcqmodels(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_bool eval0errors; - ae_bool eval1errors; - ae_bool eval2errors; - ae_bool newton0errors; - ae_bool newton1errors; - ae_bool newton2errors; - ae_bool waserrors; - convexquadraticmodel s; - ae_int_t nkind; - ae_int_t kmax; - ae_int_t n; - ae_int_t k; - ae_int_t i; - ae_int_t pass; - ae_int_t j; - double alpha; - double theta; - double tau; - double v; - double v2; - double h; - double f0; - double mkind; - double xtadx2; - double noise; - ae_matrix a; - ae_matrix q; - ae_vector b; - ae_vector r; - ae_vector x; - ae_vector x0; - ae_vector xc; - ae_vector d; - ae_vector ge; - ae_vector gt; - ae_vector tmp0; - ae_vector adx; - ae_vector adxe; - ae_vector activeset; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&a, 0, sizeof(a)); - memset(&q, 0, sizeof(q)); - memset(&b, 0, sizeof(b)); - memset(&r, 0, sizeof(r)); - memset(&x, 0, sizeof(x)); - memset(&x0, 0, sizeof(x0)); - memset(&xc, 0, sizeof(xc)); - memset(&d, 0, sizeof(d)); - memset(&ge, 0, sizeof(ge)); - memset(>, 0, sizeof(gt)); - memset(&tmp0, 0, sizeof(tmp0)); - memset(&adx, 0, sizeof(adx)); - memset(&adxe, 0, sizeof(adxe)); - memset(&activeset, 0, sizeof(activeset)); - _convexquadraticmodel_init(&s, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&r, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ge, 0, DT_REAL, _state, ae_true); - ae_vector_init(>, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&adx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&adxe, 0, DT_REAL, _state, ae_true); - ae_vector_init(&activeset, 0, DT_BOOL, _state, ae_true); - - waserrors = ae_false; - - /* - * Eval0 test: unconstrained model evaluation - */ - eval0errors = ae_false; - for(n=1; n<=5; n++) - { - for(k=0; k<=2*n; k++) - { - - /* - * Allocate place - */ - ae_matrix_set_length(&a, n, n, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&d, n, _state); - ae_vector_set_length(&ge, n, _state); - ae_vector_set_length(>, n, _state); - ae_vector_set_length(&tmp0, n, _state); - if( k>0 ) - { - ae_matrix_set_length(&q, k, n, _state); - ae_vector_set_length(&r, k, _state); - } - - /* - * Generate problem - */ - alpha = ae_randomreal(_state)+1.0; - theta = ae_randomreal(_state)+1.0; - tau = ae_randomreal(_state)*ae_randominteger(2, _state); - for(i=0; i<=n-1; i++) - { - a.ptr.pp_double[i][i] = 10*(1+ae_randomreal(_state)); - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - d.ptr.p_double[i] = ae_randomreal(_state)+1; - for(j=i+1; j<=n-1; j++) - { - v = 0.1*ae_randomreal(_state)-0.05; - a.ptr.pp_double[i][j] = v; - a.ptr.pp_double[j][i] = v; - } - for(j=0; j<=k-1; j++) - { - q.ptr.pp_double[j][i] = 2*ae_randomreal(_state)-1; - } - } - for(i=0; i<=k-1; i++) - { - r.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - - /* - * Build model - */ - cqminit(n, &s, _state); - cqmseta(&s, &a, ae_fp_greater(ae_randomreal(_state),0.5), alpha, _state); - cqmsetb(&s, &b, _state); - cqmsetq(&s, &q, &r, k, theta, _state); - cqmsetd(&s, &d, tau, _state); - - /* - * Evaluate and compare: - * * X - random point - * * GE - "exact" gradient - * * XTADX2 - x'*(alpha*A+tau*D)*x/2 - * * ADXE - (alpha*A+tau*D)*x - * * V - model value at X - */ - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - ge.ptr.p_double[i] = 0.0; - } - v = 0.0; - xtadx2 = 0.0; - ae_vector_set_length(&adxe, n, _state); - for(i=0; i<=n-1; i++) - { - adxe.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - v = v+x.ptr.p_double[i]*b.ptr.p_double[i]; - ge.ptr.p_double[i] = ge.ptr.p_double[i]+b.ptr.p_double[i]; - v = v+0.5*ae_sqr(x.ptr.p_double[i], _state)*tau*d.ptr.p_double[i]; - ge.ptr.p_double[i] = ge.ptr.p_double[i]+x.ptr.p_double[i]*tau*d.ptr.p_double[i]; - adxe.ptr.p_double[i] = adxe.ptr.p_double[i]+x.ptr.p_double[i]*tau*d.ptr.p_double[i]; - xtadx2 = xtadx2+0.5*ae_sqr(x.ptr.p_double[i], _state)*tau*d.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - v = v+0.5*alpha*x.ptr.p_double[i]*a.ptr.pp_double[i][j]*x.ptr.p_double[j]; - ge.ptr.p_double[i] = ge.ptr.p_double[i]+alpha*a.ptr.pp_double[i][j]*x.ptr.p_double[j]; - adxe.ptr.p_double[i] = adxe.ptr.p_double[i]+alpha*a.ptr.pp_double[i][j]*x.ptr.p_double[j]; - xtadx2 = xtadx2+0.5*alpha*x.ptr.p_double[i]*a.ptr.pp_double[i][j]*x.ptr.p_double[j]; - } - } - for(i=0; i<=k-1; i++) - { - v2 = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = v+0.5*theta*ae_sqr(v2-r.ptr.p_double[i], _state); - for(j=0; j<=n-1; j++) - { - ge.ptr.p_double[j] = ge.ptr.p_double[j]+theta*(v2-r.ptr.p_double[i])*q.ptr.pp_double[i][j]; - } - } - v2 = cqmeval(&s, &x, _state); - eval0errors = eval0errors||ae_fp_greater(ae_fabs(v-v2, _state),10000*ae_machineepsilon); - cqmevalx(&s, &x, &v2, &noise, _state); - eval0errors = eval0errors||ae_fp_greater(ae_fabs(v-v2, _state),10000*ae_machineepsilon); - eval0errors = (eval0errors||ae_fp_less(noise,(double)(0)))||ae_fp_greater(noise,10000*ae_machineepsilon); - v2 = cqmxtadx2(&s, &x, &tmp0, _state); - eval0errors = eval0errors||ae_fp_greater(ae_fabs(xtadx2-v2, _state),10000*ae_machineepsilon); - cqmgradunconstrained(&s, &x, >, _state); - for(i=0; i<=n-1; i++) - { - eval0errors = eval0errors||ae_fp_greater(ae_fabs(ge.ptr.p_double[i]-gt.ptr.p_double[i], _state),10000*ae_machineepsilon); - } - cqmadx(&s, &x, &adx, _state); - for(i=0; i<=n-1; i++) - { - eval0errors = eval0errors||ae_fp_greater(ae_fabs(adx.ptr.p_double[i]-adxe.ptr.p_double[i], _state),10000*ae_machineepsilon); - } - } - } - waserrors = waserrors||eval0errors; - - /* - * Eval1 test: constrained model evaluation - */ - eval1errors = ae_false; - for(n=1; n<=5; n++) - { - for(k=0; k<=2*n; k++) - { - - /* - * Allocate place - */ - ae_matrix_set_length(&a, n, n, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&xc, n, _state); - ae_vector_set_length(&activeset, n, _state); - if( k>0 ) - { - ae_matrix_set_length(&q, k, n, _state); - ae_vector_set_length(&r, k, _state); - } - - /* - * Generate problem - */ - alpha = ae_randomreal(_state)+1.0; - theta = ae_randomreal(_state)+1.0; - for(i=0; i<=n-1; i++) - { - a.ptr.pp_double[i][i] = 10*(1+ae_randomreal(_state)); - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - activeset.ptr.p_bool[i] = ae_fp_greater(ae_randomreal(_state),0.5); - for(j=i+1; j<=n-1; j++) - { - v = 0.1*ae_randomreal(_state)-0.05; - a.ptr.pp_double[i][j] = v; - a.ptr.pp_double[j][i] = v; - } - for(j=0; j<=k-1; j++) - { - q.ptr.pp_double[j][i] = 2*ae_randomreal(_state)-1; - } - } - for(i=0; i<=k-1; i++) - { - r.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - - /* - * Build model, evaluate at random point X, compare - */ - cqminit(n, &s, _state); - cqmseta(&s, &a, ae_fp_greater(ae_randomreal(_state),0.5), alpha, _state); - cqmsetb(&s, &b, _state); - cqmsetq(&s, &q, &r, k, theta, _state); - cqmsetactiveset(&s, &xc, &activeset, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - if( !activeset.ptr.p_bool[i] ) - { - xc.ptr.p_double[i] = x.ptr.p_double[i]; - } - } - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+xc.ptr.p_double[i]*b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - v = v+0.5*alpha*xc.ptr.p_double[i]*a.ptr.pp_double[i][j]*xc.ptr.p_double[j]; - } - } - for(i=0; i<=k-1; i++) - { - v2 = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &xc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = v+0.5*theta*ae_sqr(v2-r.ptr.p_double[i], _state); - } - eval1errors = eval1errors||ae_fp_greater(ae_fabs(v-cqmeval(&s, &xc, _state), _state),10000*ae_machineepsilon); - eval1errors = eval1errors||ae_fp_greater(ae_fabs(v-cqmdebugconstrainedevalt(&s, &x, _state), _state),10000*ae_machineepsilon); - eval1errors = eval1errors||ae_fp_greater(ae_fabs(v-cqmdebugconstrainedevale(&s, &x, _state), _state),10000*ae_machineepsilon); - } - } - waserrors = waserrors||eval1errors; - - /* - * Eval2 test: we generate empty problem and apply sequence of random transformations, - * re-evaluating and re-checking model after each modification. - * - * The purpose of such test is to ensure that our caching strategy works correctly. - */ - eval2errors = ae_false; - for(n=1; n<=5; n++) - { - kmax = 2*n; - ae_matrix_set_length(&a, n, n, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&d, n, _state); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&xc, n, _state); - ae_matrix_set_length(&q, kmax, n, _state); - ae_vector_set_length(&r, kmax, _state); - ae_vector_set_length(&activeset, n, _state); - ae_vector_set_length(&tmp0, n, _state); - alpha = 0.0; - theta = 0.0; - k = 0; - tau = 1.0+ae_randomreal(_state); - for(i=0; i<=n-1; i++) - { - activeset.ptr.p_bool[i] = ae_false; - d.ptr.p_double[i] = 1.0; - b.ptr.p_double[i] = 0.0; - xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - cqminit(n, &s, _state); - cqmsetd(&s, &d, tau, _state); - for(pass=1; pass<=100; pass++) - { - - /* - * Select random modification type, apply modification. - * - * MKind is a random integer in [0,7] - number of specific - * modification to apply. - */ - mkind = (double)(ae_randominteger(8, _state)); - if( ae_fp_eq(mkind,(double)(0)) ) - { - - /* - * Set non-zero D - */ - tau = 1.0+ae_randomreal(_state); - for(i=0; i<=n-1; i++) - { - d.ptr.p_double[i] = 2*ae_randomreal(_state)+1; - } - cqmsetd(&s, &d, tau, _state); - } - else - { - if( ae_fp_eq(mkind,(double)(1)) ) - { - - /* - * Set zero D. - * In case Alpha=0, set non-zero A. - */ - if( ae_fp_eq(alpha,(double)(0)) ) - { - alpha = 1.0+ae_randomreal(_state); - for(i=0; i<=n-1; i++) - { - for(j=i+1; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.2*ae_randomreal(_state)-0.1; - a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j]; - } - } - for(i=0; i<=n-1; i++) - { - a.ptr.pp_double[i][i] = 4+2*ae_randomreal(_state); - } - cqmseta(&s, &a, ae_fp_greater(ae_randomreal(_state),0.5), alpha, _state); - } - tau = 0.0; - for(i=0; i<=n-1; i++) - { - d.ptr.p_double[i] = (double)(0); - } - cqmsetd(&s, &d, 0.0, _state); - } - else - { - if( ae_fp_eq(mkind,(double)(2)) ) - { - - /* - * Set non-zero A - */ - alpha = 1.0+ae_randomreal(_state); - for(i=0; i<=n-1; i++) - { - for(j=i+1; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.2*ae_randomreal(_state)-0.1; - a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j]; - } - } - for(i=0; i<=n-1; i++) - { - a.ptr.pp_double[i][i] = 4+2*ae_randomreal(_state); - } - cqmseta(&s, &a, ae_fp_greater(ae_randomreal(_state),0.5), alpha, _state); - } - else - { - if( ae_fp_eq(mkind,(double)(3)) ) - { - - /* - * Set zero A. - * In case Tau=0, set non-zero D. - */ - if( ae_fp_eq(tau,(double)(0)) ) - { - tau = 1.0+ae_randomreal(_state); - for(i=0; i<=n-1; i++) - { - d.ptr.p_double[i] = 2*ae_randomreal(_state)+1; - } - cqmsetd(&s, &d, tau, _state); - } - alpha = 0.0; - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - cqmseta(&s, &a, ae_fp_greater(ae_randomreal(_state),0.5), alpha, _state); - } - else - { - if( ae_fp_eq(mkind,(double)(4)) ) - { - - /* - * Set B. - */ - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - cqmsetb(&s, &b, _state); - } - else - { - if( ae_fp_eq(mkind,(double)(5)) ) - { - - /* - * Set Q. - */ - k = ae_randominteger(kmax+1, _state); - theta = 1.0+ae_randomreal(_state); - for(i=0; i<=k-1; i++) - { - r.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - for(j=0; j<=n-1; j++) - { - q.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - cqmsetq(&s, &q, &r, k, theta, _state); - } - else - { - if( ae_fp_eq(mkind,(double)(6)) ) - { - - /* - * Set active set - */ - for(i=0; i<=n-1; i++) - { - activeset.ptr.p_bool[i] = ae_fp_greater(ae_randomreal(_state),0.5); - xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - cqmsetactiveset(&s, &xc, &activeset, _state); - } - else - { - if( ae_fp_eq(mkind,(double)(7)) ) - { - - /* - * Rewrite main diagonal - */ - if( ae_fp_eq(alpha,(double)(0)) ) - { - alpha = 1.0; - } - for(i=0; i<=n-1; i++) - { - tmp0.ptr.p_double[i] = 1+ae_randomreal(_state); - a.ptr.pp_double[i][i] = tmp0.ptr.p_double[i]/alpha; - } - cqmrewritedensediagonal(&s, &tmp0, _state); - } - } - } - } - } - } - } - } - - /* - * generate random point with respect to constraints, - * test model at this point - */ - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - if( activeset.ptr.p_bool[i] ) - { - x.ptr.p_double[i] = xc.ptr.p_double[i]; - } - } - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+x.ptr.p_double[i]*b.ptr.p_double[i]; - } - if( ae_fp_greater(tau,(double)(0)) ) - { - for(i=0; i<=n-1; i++) - { - v = v+0.5*tau*d.ptr.p_double[i]*ae_sqr(x.ptr.p_double[i], _state); - } - } - if( ae_fp_greater(alpha,(double)(0)) ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = v+0.5*alpha*x.ptr.p_double[i]*a.ptr.pp_double[i][j]*x.ptr.p_double[j]; - } - } - } - if( ae_fp_greater(theta,(double)(0)) ) - { - for(i=0; i<=k-1; i++) - { - v2 = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = v+0.5*theta*ae_sqr(v2-r.ptr.p_double[i], _state); - } - } - v2 = cqmeval(&s, &x, _state); - eval2errors = eval2errors||ae_fp_greater(ae_fabs(v-v2, _state),10000*ae_machineepsilon); - v2 = cqmdebugconstrainedevalt(&s, &x, _state); - eval2errors = eval2errors||ae_fp_greater(ae_fabs(v-v2, _state),10000*ae_machineepsilon); - v2 = cqmdebugconstrainedevale(&s, &x, _state); - eval2errors = eval2errors||ae_fp_greater(ae_fabs(v-v2, _state),10000*ae_machineepsilon); - } - } - waserrors = waserrors||eval2errors; - - /* - * Newton0 test: unconstrained optimization - */ - newton0errors = ae_false; - for(n=1; n<=5; n++) - { - for(k=0; k<=2*n; k++) - { - - /* - * Allocate place - */ - ae_matrix_set_length(&a, n, n, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&x0, n, _state); - if( k>0 ) - { - ae_matrix_set_length(&q, k, n, _state); - ae_vector_set_length(&r, k, _state); - } - - /* - * Generate problem with known solution x0: - * min f(x), - * f(x) = 0.5*(x-x0)'*A*(x-x0) - * = 0.5*x'*A*x + (-x0'*A)*x + 0.5*x0'*A*x0' - */ - alpha = ae_randomreal(_state)+1.0; - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - a.ptr.pp_double[i][i] = 10*(1+ae_randomreal(_state)); - for(j=i+1; j<=n-1; j++) - { - v = 0.1*ae_randomreal(_state)-0.05; - a.ptr.pp_double[i][j] = v; - a.ptr.pp_double[j][i] = v; - } - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - b.ptr.p_double[i] = -alpha*v; - } - theta = ae_randomreal(_state)+1.0; - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - q.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - v = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - r.ptr.p_double[i] = v; - } - - /* - * Build model, evaluate at random point X, compare - */ - cqminit(n, &s, _state); - cqmseta(&s, &a, ae_fp_greater(ae_randomreal(_state),0.5), alpha, _state); - cqmsetb(&s, &b, _state); - cqmsetq(&s, &q, &r, k, theta, _state); - cqmconstrainedoptimum(&s, &x, _state); - for(i=0; i<=n-1; i++) - { - newton0errors = newton0errors||ae_fp_greater(ae_fabs(x.ptr.p_double[i]-x0.ptr.p_double[i], _state),1.0E6*ae_machineepsilon); - } - } - } - waserrors = waserrors||newton0errors; - - /* - * Newton1 test: constrained optimization - */ - newton1errors = ae_false; - h = 1.0E-3; - for(n=1; n<=5; n++) - { - for(k=0; k<=2*n; k++) - { - - /* - * Allocate place - */ - ae_matrix_set_length(&a, n, n, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&xc, n, _state); - ae_vector_set_length(&activeset, n, _state); - if( k>0 ) - { - ae_matrix_set_length(&q, k, n, _state); - ae_vector_set_length(&r, k, _state); - } - - /* - * Generate test problem with unknown solution. - */ - alpha = ae_randomreal(_state)+1.0; - for(i=0; i<=n-1; i++) - { - a.ptr.pp_double[i][i] = 10*(1+ae_randomreal(_state)); - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - activeset.ptr.p_bool[i] = ae_fp_greater(ae_randomreal(_state),0.5); - for(j=i+1; j<=n-1; j++) - { - v = 0.1*ae_randomreal(_state)-0.05; - a.ptr.pp_double[i][j] = v; - a.ptr.pp_double[j][i] = v; - } - } - theta = ae_randomreal(_state)+1.0; - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - q.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - r.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - - /* - * Build model, find solution - */ - cqminit(n, &s, _state); - cqmseta(&s, &a, ae_fp_greater(ae_randomreal(_state),0.5), alpha, _state); - cqmsetb(&s, &b, _state); - cqmsetq(&s, &q, &r, k, theta, _state); - cqmsetactiveset(&s, &xc, &activeset, _state); - if( cqmconstrainedoptimum(&s, &x, _state) ) - { - - /* - * Check that constraints are satisfied, - * and that solution is true optimum - */ - f0 = cqmeval(&s, &x, _state); - for(i=0; i<=n-1; i++) - { - newton1errors = newton1errors||(activeset.ptr.p_bool[i]&&ae_fp_neq(x.ptr.p_double[i],xc.ptr.p_double[i])); - if( !activeset.ptr.p_bool[i] ) - { - v = x.ptr.p_double[i]; - x.ptr.p_double[i] = v+h; - v2 = cqmeval(&s, &x, _state); - newton1errors = newton1errors||ae_fp_less(v2,f0); - x.ptr.p_double[i] = v-h; - v2 = cqmeval(&s, &x, _state); - newton1errors = newton1errors||ae_fp_less(v2,f0); - x.ptr.p_double[i] = v; - } - } - } - else - { - newton1errors = ae_true; - } - } - } - waserrors = waserrors||newton1errors; - - /* - * Newton2 test: we test ability to work with diagonal matrices, including - * very large ones (up to 100.000 elements). This test checks that: - * a) we can work with Alpha=0, i.e. when we have strictly diagonal A - * b) diagonal problems are handled efficiently, i.e. algorithm will - * successfully solve problem with N=100.000 - * - * Test problem: - * * diagonal term D and rank-K term Q - * * known solution X0, - * * about 50% of constraints are active and equal to components of X0 - */ - newton2errors = ae_false; - for(nkind=0; nkind<=5; nkind++) - { - for(k=0; k<=5; k++) - { - n = ae_round(ae_pow((double)(n), (double)(nkind), _state), _state); - - /* - * generate problem - */ - ae_vector_set_length(&d, n, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&activeset, n, _state); - if( k>0 ) - { - ae_matrix_set_length(&q, k, n, _state); - ae_vector_set_length(&r, k, _state); - } - tau = 1+ae_randomreal(_state); - theta = 1+ae_randomreal(_state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - d.ptr.p_double[i] = 1+ae_randomreal(_state); - b.ptr.p_double[i] = -x0.ptr.p_double[i]*tau*d.ptr.p_double[i]; - activeset.ptr.p_bool[i] = ae_fp_greater(ae_randomreal(_state),0.5); - } - for(i=0; i<=k-1; i++) - { - v = 0.0; - for(j=0; j<=n-1; j++) - { - q.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - v = v+q.ptr.pp_double[i][j]*x0.ptr.p_double[j]; - } - r.ptr.p_double[i] = v; - } - - /* - * Solve, test - */ - cqminit(n, &s, _state); - cqmsetb(&s, &b, _state); - cqmsetd(&s, &d, tau, _state); - cqmsetq(&s, &q, &r, k, theta, _state); - cqmsetactiveset(&s, &x0, &activeset, _state); - if( cqmconstrainedoptimum(&s, &x, _state) ) - { - - /* - * Check that constraints are satisfied, - * and that solution is true optimum - */ - f0 = cqmeval(&s, &x, _state); - for(i=0; i<=n-1; i++) - { - newton2errors = newton2errors||(activeset.ptr.p_bool[i]&&ae_fp_neq(x.ptr.p_double[i],x0.ptr.p_double[i])); - newton2errors = newton2errors||(!activeset.ptr.p_bool[i]&&ae_fp_greater(ae_fabs(x.ptr.p_double[i]-x0.ptr.p_double[i], _state),1000*ae_machineepsilon)); - } - - /* - * Check that constrained evaluation at some point gives correct results - */ - for(i=0; i<=n-1; i++) - { - if( activeset.ptr.p_bool[i] ) - { - x.ptr.p_double[i] = x0.ptr.p_double[i]; - } - else - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - } - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+0.5*tau*d.ptr.p_double[i]*ae_sqr(x.ptr.p_double[i], _state)+x.ptr.p_double[i]*b.ptr.p_double[i]; - } - for(i=0; i<=k-1; i++) - { - v2 = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = v+0.5*theta*ae_sqr(v2-r.ptr.p_double[i], _state); - } - v2 = cqmeval(&s, &x, _state); - newton2errors = (newton2errors||!ae_isfinite(v2, _state))||ae_fp_greater(ae_fabs(v-v2, _state),10000*ae_machineepsilon); - v2 = cqmdebugconstrainedevalt(&s, &x, _state); - newton2errors = (newton2errors||!ae_isfinite(v2, _state))||ae_fp_greater(ae_fabs(v-v2, _state),10000*ae_machineepsilon); - v2 = cqmdebugconstrainedevale(&s, &x, _state); - newton2errors = (newton2errors||!ae_isfinite(v2, _state))||ae_fp_greater(ae_fabs(v-v2, _state),10000*ae_machineepsilon); - } - else - { - newton2errors = ae_true; - } - } - } - waserrors = waserrors||newton2errors; - - /* - * report - */ - if( !silent ) - { - printf("TESTING CONVEX QUADRATIC MODELS\n"); - printf("Eval0 test: "); - if( eval0errors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("Eval1 test: "); - if( eval1errors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("Eval2 test: "); - if( eval2errors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("Newton0 test: "); - if( newton0errors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("Newton1 test: "); - if( newton1errors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("Newton2 test: "); - if( newton2errors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - - -static void testbdsvdunit_fillidentity(/* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state); -static void testbdsvdunit_fillsparsede(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - double sparcity, - ae_state *_state); -static void testbdsvdunit_getbdsvderror(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_matrix* u, - /* Real */ ae_matrix* c, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* vt, - double* materr, - double* orterr, - ae_bool* wsorted, - ae_state *_state); -static void testbdsvdunit_checksvdmultiplication(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_matrix* u, - /* Real */ ae_matrix* c, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* vt, - double* err, - ae_state *_state); -static void testbdsvdunit_testbdsvdproblem(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - double* materr, - double* orterr, - ae_bool* wsorted, - ae_bool* wfailed, - ae_int_t* failcount, - ae_int_t* succcount, - ae_state *_state); - - - - - -/************************************************************************* -Testing bidiagonal SVD decomposition subroutine -*************************************************************************/ -ae_bool testbdsvd(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_vector d; - ae_vector e; - ae_matrix mempty; - ae_int_t n; - ae_int_t maxn; - ae_int_t i; - ae_int_t pass; - ae_bool waserrors; - ae_bool wsorted; - ae_bool wfailed; - double materr; - double orterr; - double threshold; - double failr; - ae_int_t failcount; - ae_int_t succcount; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&d, 0, sizeof(d)); - memset(&e, 0, sizeof(e)); - memset(&mempty, 0, sizeof(mempty)); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&e, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&mempty, 0, 0, DT_REAL, _state, ae_true); - - failcount = 0; - succcount = 0; - materr = (double)(0); - orterr = (double)(0); - wsorted = ae_true; - wfailed = ae_false; - waserrors = ae_false; - maxn = 15; - threshold = 5*100*ae_machineepsilon; - ae_vector_set_length(&d, maxn-1+1, _state); - ae_vector_set_length(&e, maxn-2+1, _state); - - /* - * special case: zero divide matrix - * unfixed LAPACK routine should fail on this problem - */ - n = 7; - d.ptr.p_double[0] = -6.96462904751731892700e-01; - d.ptr.p_double[1] = 0.00000000000000000000e+00; - d.ptr.p_double[2] = -5.73827770385971991400e-01; - d.ptr.p_double[3] = -6.62562624399371191700e-01; - d.ptr.p_double[4] = 5.82737148001782223600e-01; - d.ptr.p_double[5] = 3.84825263580925003300e-01; - d.ptr.p_double[6] = 9.84087420830525472200e-01; - e.ptr.p_double[0] = -7.30307931760612871800e-02; - e.ptr.p_double[1] = -2.30079042939542843800e-01; - e.ptr.p_double[2] = -6.87824621739351216300e-01; - e.ptr.p_double[3] = -1.77306437707837570600e-02; - e.ptr.p_double[4] = 1.78285126526551632000e-15; - e.ptr.p_double[5] = -4.89434737751289969400e-02; - rmatrixbdsvd(&d, &e, n, ae_true, ae_false, &mempty, 0, &mempty, 0, &mempty, 0, _state); - - /* - * zero matrix, several cases - */ - for(i=0; i<=maxn-1; i++) - { - d.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=maxn-2; i++) - { - e.ptr.p_double[i] = (double)(0); - } - for(n=1; n<=maxn; n++) - { - testbdsvdunit_testbdsvdproblem(&d, &e, n, &materr, &orterr, &wsorted, &wfailed, &failcount, &succcount, _state); - } - - /* - * Dense matrix - */ - for(n=1; n<=maxn; n++) - { - for(pass=1; pass<=10; pass++) - { - for(i=0; i<=maxn-1; i++) - { - d.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=maxn-2; i++) - { - e.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - testbdsvdunit_testbdsvdproblem(&d, &e, n, &materr, &orterr, &wsorted, &wfailed, &failcount, &succcount, _state); - } - } - - /* - * Sparse matrices, very sparse matrices, incredible sparse matrices - */ - for(n=1; n<=maxn; n++) - { - for(pass=1; pass<=10; pass++) - { - testbdsvdunit_fillsparsede(&d, &e, n, 0.5, _state); - testbdsvdunit_testbdsvdproblem(&d, &e, n, &materr, &orterr, &wsorted, &wfailed, &failcount, &succcount, _state); - testbdsvdunit_fillsparsede(&d, &e, n, 0.8, _state); - testbdsvdunit_testbdsvdproblem(&d, &e, n, &materr, &orterr, &wsorted, &wfailed, &failcount, &succcount, _state); - testbdsvdunit_fillsparsede(&d, &e, n, 0.9, _state); - testbdsvdunit_testbdsvdproblem(&d, &e, n, &materr, &orterr, &wsorted, &wfailed, &failcount, &succcount, _state); - testbdsvdunit_fillsparsede(&d, &e, n, 0.95, _state); - testbdsvdunit_testbdsvdproblem(&d, &e, n, &materr, &orterr, &wsorted, &wfailed, &failcount, &succcount, _state); - } - } - - /* - * report - */ - failr = (double)failcount/(double)(succcount+failcount); - waserrors = ((wfailed||ae_fp_greater(materr,threshold))||ae_fp_greater(orterr,threshold))||!wsorted; - if( !silent ) - { - printf("TESTING BIDIAGONAL SVD DECOMPOSITION\n"); - printf("SVD decomposition error: %5.3e\n", - (double)(materr)); - printf("SVD orthogonality error: %5.3e\n", - (double)(orterr)); - printf("Singular values order: "); - if( wsorted ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("Always converged: "); - if( !wfailed ) - { - printf("YES\n"); - } - else - { - printf("NO\n"); - printf("Fail ratio: %5.3f\n", - (double)(failr)); - } - printf("Threshold: %5.3e\n", - (double)(threshold)); - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -static void testbdsvdunit_fillidentity(/* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - ae_matrix_set_length(a, n-1+1, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - a->ptr.pp_double[i][j] = (double)(1); - } - else - { - a->ptr.pp_double[i][j] = (double)(0); - } - } - } -} - - -static void testbdsvdunit_fillsparsede(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - double sparcity, - ae_state *_state) -{ - ae_int_t i; - - - ae_vector_set_length(d, n-1+1, _state); - ae_vector_set_length(e, ae_maxint(0, n-2, _state)+1, _state); - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater_eq(ae_randomreal(_state),sparcity) ) - { - d->ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - else - { - d->ptr.p_double[i] = (double)(0); - } - } - for(i=0; i<=n-2; i++) - { - if( ae_fp_greater_eq(ae_randomreal(_state),sparcity) ) - { - e->ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - else - { - e->ptr.p_double[i] = (double)(0); - } - } -} - - -static void testbdsvdunit_getbdsvderror(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_matrix* u, - /* Real */ ae_matrix* c, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* vt, - double* materr, - double* orterr, - ae_bool* wsorted, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double locerr; - double sm; - - - - /* - * decomposition error - */ - locerr = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - sm = (double)(0); - for(k=0; k<=n-1; k++) - { - sm = sm+w->ptr.p_double[k]*u->ptr.pp_double[i][k]*vt->ptr.pp_double[k][j]; - } - if( isupper ) - { - if( i==j ) - { - locerr = ae_maxreal(locerr, ae_fabs(d->ptr.p_double[i]-sm, _state), _state); - } - else - { - if( i==j-1 ) - { - locerr = ae_maxreal(locerr, ae_fabs(e->ptr.p_double[i]-sm, _state), _state); - } - else - { - locerr = ae_maxreal(locerr, ae_fabs(sm, _state), _state); - } - } - } - else - { - if( i==j ) - { - locerr = ae_maxreal(locerr, ae_fabs(d->ptr.p_double[i]-sm, _state), _state); - } - else - { - if( i-1==j ) - { - locerr = ae_maxreal(locerr, ae_fabs(e->ptr.p_double[j]-sm, _state), _state); - } - else - { - locerr = ae_maxreal(locerr, ae_fabs(sm, _state), _state); - } - } - } - } - } - *materr = ae_maxreal(*materr, locerr, _state); - - /* - * check for C = U' - * we consider it as decomposition error - */ - locerr = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - locerr = ae_maxreal(locerr, ae_fabs(u->ptr.pp_double[i][j]-c->ptr.pp_double[j][i], _state), _state); - } - } - *materr = ae_maxreal(*materr, locerr, _state); - - /* - * orthogonality error - */ - locerr = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - sm = ae_v_dotproduct(&u->ptr.pp_double[0][i], u->stride, &u->ptr.pp_double[0][j], u->stride, ae_v_len(0,n-1)); - if( i!=j ) - { - locerr = ae_maxreal(locerr, ae_fabs(sm, _state), _state); - } - else - { - locerr = ae_maxreal(locerr, ae_fabs(sm-1, _state), _state); - } - sm = ae_v_dotproduct(&vt->ptr.pp_double[i][0], 1, &vt->ptr.pp_double[j][0], 1, ae_v_len(0,n-1)); - if( i!=j ) - { - locerr = ae_maxreal(locerr, ae_fabs(sm, _state), _state); - } - else - { - locerr = ae_maxreal(locerr, ae_fabs(sm-1, _state), _state); - } - } - } - *orterr = ae_maxreal(*orterr, locerr, _state); - - /* - * values order error - */ - for(i=1; i<=n-1; i++) - { - if( ae_fp_greater(w->ptr.p_double[i],w->ptr.p_double[i-1]) ) - { - *wsorted = ae_false; - } - } -} - - -static void testbdsvdunit_checksvdmultiplication(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_bool isupper, - /* Real */ ae_matrix* u, - /* Real */ ae_matrix* c, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* vt, - double* err, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_vector wt; - ae_matrix u2; - ae_matrix c2; - ae_matrix vt2; - ae_matrix u1; - ae_matrix c1; - ae_matrix vt1; - ae_int_t nru; - ae_int_t ncc; - ae_int_t ncvt; - ae_int_t pass; - hqrndstate rs; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&wt, 0, sizeof(wt)); - memset(&u2, 0, sizeof(u2)); - memset(&c2, 0, sizeof(c2)); - memset(&vt2, 0, sizeof(vt2)); - memset(&u1, 0, sizeof(u1)); - memset(&c1, 0, sizeof(c1)); - memset(&vt1, 0, sizeof(vt1)); - memset(&rs, 0, sizeof(rs)); - ae_vector_init(&wt, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&u2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vt2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&u1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vt1, 0, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - ae_vector_set_length(&wt, n, _state); - - /* - * Perform nonsquare SVD - */ - for(pass=1; pass<=20; pass++) - { - - /* - * Problem size - */ - nru = hqrnduniformi(&rs, 2*n, _state); - ncc = hqrnduniformi(&rs, 2*n, _state); - ncvt = hqrnduniformi(&rs, 2*n, _state); - - /* - * Reference matrices (copy 1) and working matrices (copy 2) - */ - for(i=0; i<=n-1; i++) - { - wt.ptr.p_double[i] = d->ptr.p_double[i]; - } - if( nru>0 ) - { - - /* - * init U1/U2 - */ - ae_matrix_set_length(&u1, nru, n, _state); - ae_matrix_set_length(&u2, nru, n, _state); - for(i=0; i<=u1.rows-1; i++) - { - for(j=0; j<=u1.cols-1; j++) - { - u1.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5; - u2.ptr.pp_double[i][j] = u1.ptr.pp_double[i][j]; - } - } - } - else - { - - /* - * Set U1/U2 to 1x1 matrices; working with 1x1 matrices allows - * to test correctness of code which passes them to MKL. - */ - ae_matrix_set_length(&u1, 1, 1, _state); - ae_matrix_set_length(&u2, 1, 1, _state); - } - if( ncc>0 ) - { - ae_matrix_set_length(&c1, n, ncc, _state); - ae_matrix_set_length(&c2, n, ncc, _state); - for(i=0; i<=c1.rows-1; i++) - { - for(j=0; j<=c1.cols-1; j++) - { - c1.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5; - c2.ptr.pp_double[i][j] = c1.ptr.pp_double[i][j]; - } - } - } - else - { - - /* - * Set C1/C1 to 1x1 matrices; working with 1x1 matrices allows - * to test correctness of code which passes them to MKL. - */ - ae_matrix_set_length(&c1, 1, 1, _state); - ae_matrix_set_length(&c2, 1, 1, _state); - } - if( ncvt>0 ) - { - ae_matrix_set_length(&vt1, n, ncvt, _state); - ae_matrix_set_length(&vt2, n, ncvt, _state); - for(i=0; i<=vt1.rows-1; i++) - { - for(j=0; j<=vt1.cols-1; j++) - { - vt1.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5; - vt2.ptr.pp_double[i][j] = vt1.ptr.pp_double[i][j]; - } - } - } - else - { - - /* - * Set VT1/VT1 to 1x1 matrices; working with 1x1 matrices allows - * to test correctness of code which passes them to MKL. - */ - ae_matrix_set_length(&vt1, 1, 1, _state); - ae_matrix_set_length(&vt2, 1, 1, _state); - } - - /* - * SVD with non-square U/C/VT - */ - if( !rmatrixbdsvd(&wt, e, n, isupper, ae_fp_greater(hqrnduniformr(&rs, _state),(double)(0)), &u2, nru, &c2, ncc, &vt2, ncvt, _state) ) - { - *err = 1.0; - ae_frame_leave(_state); - return; - } - for(i=0; i<=nru-1; i++) - { - for(j=0; j<=u2.cols-1; j++) - { - v = ae_v_dotproduct(&u1.ptr.pp_double[i][0], 1, &u->ptr.pp_double[0][j], u->stride, ae_v_len(0,n-1)); - *err = ae_maxreal(*err, ae_fabs(v-u2.ptr.pp_double[i][j], _state), _state); - } - } - for(i=0; i<=c2.rows-1; i++) - { - for(j=0; j<=ncc-1; j++) - { - v = ae_v_dotproduct(&c->ptr.pp_double[i][0], 1, &c1.ptr.pp_double[0][j], c1.stride, ae_v_len(0,n-1)); - *err = ae_maxreal(*err, ae_fabs(v-c2.ptr.pp_double[i][j], _state), _state); - } - } - for(i=0; i<=vt2.rows-1; i++) - { - for(j=0; j<=ncvt-1; j++) - { - v = ae_v_dotproduct(&vt->ptr.pp_double[i][0], 1, &vt1.ptr.pp_double[0][j], vt1.stride, ae_v_len(0,n-1)); - *err = ae_maxreal(*err, ae_fabs(v-vt2.ptr.pp_double[i][j], _state), _state); - } - } - } - ae_frame_leave(_state); -} - - -static void testbdsvdunit_testbdsvdproblem(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - double* materr, - double* orterr, - ae_bool* wsorted, - ae_bool* wfailed, - ae_int_t* failcount, - ae_int_t* succcount, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix u; - ae_matrix vt; - ae_matrix c; - ae_vector w; - ae_int_t i; - double mx; - - ae_frame_make(_state, &_frame_block); - memset(&u, 0, sizeof(u)); - memset(&vt, 0, sizeof(vt)); - memset(&c, 0, sizeof(c)); - memset(&w, 0, sizeof(w)); - ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vt, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(ae_fabs(d->ptr.p_double[i], _state),mx) ) - { - mx = ae_fabs(d->ptr.p_double[i], _state); - } - } - for(i=0; i<=n-2; i++) - { - if( ae_fp_greater(ae_fabs(e->ptr.p_double[i], _state),mx) ) - { - mx = ae_fabs(e->ptr.p_double[i], _state); - } - } - if( ae_fp_eq(mx,(double)(0)) ) - { - mx = (double)(1); - } - - /* - * Upper BDSVD tests - */ - ae_vector_set_length(&w, n-1+1, _state); - testbdsvdunit_fillidentity(&u, n, _state); - testbdsvdunit_fillidentity(&vt, n, _state); - testbdsvdunit_fillidentity(&c, n, _state); - for(i=0; i<=n-1; i++) - { - w.ptr.p_double[i] = d->ptr.p_double[i]; - } - if( !rmatrixbdsvd(&w, e, n, ae_true, ae_false, &u, n, &c, n, &vt, n, _state) ) - { - *failcount = *failcount+1; - *wfailed = ae_true; - ae_frame_leave(_state); - return; - } - testbdsvdunit_getbdsvderror(d, e, n, ae_true, &u, &c, &w, &vt, materr, orterr, wsorted, _state); - testbdsvdunit_checksvdmultiplication(d, e, n, ae_true, &u, &c, &w, &vt, materr, _state); - testbdsvdunit_fillidentity(&u, n, _state); - testbdsvdunit_fillidentity(&vt, n, _state); - testbdsvdunit_fillidentity(&c, n, _state); - for(i=0; i<=n-1; i++) - { - w.ptr.p_double[i] = d->ptr.p_double[i]; - } - if( !rmatrixbdsvd(&w, e, n, ae_true, ae_true, &u, n, &c, n, &vt, n, _state) ) - { - *failcount = *failcount+1; - *wfailed = ae_true; - ae_frame_leave(_state); - return; - } - testbdsvdunit_getbdsvderror(d, e, n, ae_true, &u, &c, &w, &vt, materr, orterr, wsorted, _state); - testbdsvdunit_checksvdmultiplication(d, e, n, ae_true, &u, &c, &w, &vt, materr, _state); - - /* - * Lower BDSVD tests - */ - ae_vector_set_length(&w, n-1+1, _state); - testbdsvdunit_fillidentity(&u, n, _state); - testbdsvdunit_fillidentity(&vt, n, _state); - testbdsvdunit_fillidentity(&c, n, _state); - for(i=0; i<=n-1; i++) - { - w.ptr.p_double[i] = d->ptr.p_double[i]; - } - if( !rmatrixbdsvd(&w, e, n, ae_false, ae_false, &u, n, &c, n, &vt, n, _state) ) - { - *failcount = *failcount+1; - *wfailed = ae_true; - ae_frame_leave(_state); - return; - } - testbdsvdunit_getbdsvderror(d, e, n, ae_false, &u, &c, &w, &vt, materr, orterr, wsorted, _state); - testbdsvdunit_checksvdmultiplication(d, e, n, ae_false, &u, &c, &w, &vt, materr, _state); - testbdsvdunit_fillidentity(&u, n, _state); - testbdsvdunit_fillidentity(&vt, n, _state); - testbdsvdunit_fillidentity(&c, n, _state); - for(i=0; i<=n-1; i++) - { - w.ptr.p_double[i] = d->ptr.p_double[i]; - } - if( !rmatrixbdsvd(&w, e, n, ae_false, ae_true, &u, n, &c, n, &vt, n, _state) ) - { - *failcount = *failcount+1; - *wfailed = ae_true; - ae_frame_leave(_state); - return; - } - testbdsvdunit_getbdsvderror(d, e, n, ae_false, &u, &c, &w, &vt, materr, orterr, wsorted, _state); - testbdsvdunit_checksvdmultiplication(d, e, n, ae_false, &u, &c, &w, &vt, materr, _state); - - /* - * update counter - */ - *succcount = *succcount+1; - ae_frame_leave(_state); -} - - - -static void testblasunit_naivematrixmatrixmultiply(/* Real */ ae_matrix* a, - ae_int_t ai1, - ae_int_t ai2, - ae_int_t aj1, - ae_int_t aj2, - ae_bool transa, - /* Real */ ae_matrix* b, - ae_int_t bi1, - ae_int_t bi2, - ae_int_t bj1, - ae_int_t bj2, - ae_bool transb, - double alpha, - /* Real */ ae_matrix* c, - ae_int_t ci1, - ae_int_t ci2, - ae_int_t cj1, - ae_int_t cj2, - double beta, - ae_state *_state); - - - - - -ae_bool testblas(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t pass; - ae_int_t passcount; - ae_int_t n; - ae_int_t i; - ae_int_t i1; - ae_int_t i2; - ae_int_t j; - ae_int_t j1; - ae_int_t j2; - ae_int_t l; - ae_int_t k; - ae_int_t r; - ae_int_t i3; - ae_int_t j3; - ae_int_t col1; - ae_int_t col2; - ae_int_t row1; - ae_int_t row2; - ae_vector x1; - ae_vector x2; - ae_matrix a; - ae_matrix b; - ae_matrix c1; - ae_matrix c2; - double err; - double e1; - double e2; - double e3; - double v; - double scl1; - double scl2; - double scl3; - ae_bool was1; - ae_bool was2; - ae_bool trans1; - ae_bool trans2; - double threshold; - ae_bool n2errors; - ae_bool hsnerrors; - ae_bool amaxerrors; - ae_bool mverrors; - ae_bool iterrors; - ae_bool cterrors; - ae_bool mmerrors; - ae_bool waserrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&x1, 0, sizeof(x1)); - memset(&x2, 0, sizeof(x2)); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - memset(&c1, 0, sizeof(c1)); - memset(&c2, 0, sizeof(c2)); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c2, 0, 0, DT_REAL, _state, ae_true); - - n2errors = ae_false; - amaxerrors = ae_false; - hsnerrors = ae_false; - mverrors = ae_false; - iterrors = ae_false; - cterrors = ae_false; - mmerrors = ae_false; - waserrors = ae_false; - threshold = 10000*ae_machineepsilon; - - /* - * Test Norm2 - */ - passcount = 1000; - e1 = (double)(0); - e2 = (double)(0); - e3 = (double)(0); - scl2 = 0.5*ae_maxrealnumber; - scl3 = 2*ae_minrealnumber; - for(pass=1; pass<=passcount; pass++) - { - n = 1+ae_randominteger(1000, _state); - i1 = ae_randominteger(10, _state); - i2 = n+i1-1; - ae_vector_set_length(&x1, i2+1, _state); - ae_vector_set_length(&x2, i2+1, _state); - for(i=i1; i<=i2; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - v = (double)(0); - for(i=i1; i<=i2; i++) - { - v = v+ae_sqr(x1.ptr.p_double[i], _state); - } - v = ae_sqrt(v, _state); - e1 = ae_maxreal(e1, ae_fabs(v-vectornorm2(&x1, i1, i2, _state), _state), _state); - for(i=i1; i<=i2; i++) - { - x2.ptr.p_double[i] = scl2*x1.ptr.p_double[i]; - } - e2 = ae_maxreal(e2, ae_fabs(v*scl2-vectornorm2(&x2, i1, i2, _state), _state), _state); - for(i=i1; i<=i2; i++) - { - x2.ptr.p_double[i] = scl3*x1.ptr.p_double[i]; - } - e3 = ae_maxreal(e3, ae_fabs(v*scl3-vectornorm2(&x2, i1, i2, _state), _state), _state); - } - e2 = e2/scl2; - e3 = e3/scl3; - n2errors = (ae_fp_greater_eq(e1,threshold)||ae_fp_greater_eq(e2,threshold))||ae_fp_greater_eq(e3,threshold); - - /* - * Testing VectorAbsMax, Column/Row AbsMax - */ - ae_vector_set_length(&x1, 5+1, _state); - x1.ptr.p_double[1] = 2.0; - x1.ptr.p_double[2] = 0.2; - x1.ptr.p_double[3] = -1.3; - x1.ptr.p_double[4] = 0.7; - x1.ptr.p_double[5] = -3.0; - amaxerrors = (vectoridxabsmax(&x1, 1, 5, _state)!=5||vectoridxabsmax(&x1, 1, 4, _state)!=1)||vectoridxabsmax(&x1, 2, 4, _state)!=3; - n = 30; - ae_vector_set_length(&x1, n+1, _state); - ae_matrix_set_length(&a, n+1, n+1, _state); - for(i=1; i<=n; i++) - { - for(j=1; j<=n; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - was1 = ae_false; - was2 = ae_false; - for(pass=1; pass<=1000; pass++) - { - j = 1+ae_randominteger(n, _state); - i1 = 1+ae_randominteger(n, _state); - i2 = i1+ae_randominteger(n+1-i1, _state); - ae_v_move(&x1.ptr.p_double[i1], 1, &a.ptr.pp_double[i1][j], a.stride, ae_v_len(i1,i2)); - if( vectoridxabsmax(&x1, i1, i2, _state)!=columnidxabsmax(&a, i1, i2, j, _state) ) - { - was1 = ae_true; - } - i = 1+ae_randominteger(n, _state); - j1 = 1+ae_randominteger(n, _state); - j2 = j1+ae_randominteger(n+1-j1, _state); - ae_v_move(&x1.ptr.p_double[j1], 1, &a.ptr.pp_double[i][j1], 1, ae_v_len(j1,j2)); - if( vectoridxabsmax(&x1, j1, j2, _state)!=rowidxabsmax(&a, j1, j2, i, _state) ) - { - was2 = ae_true; - } - } - amaxerrors = (amaxerrors||was1)||was2; - - /* - * Testing upper Hessenberg 1-norm - */ - ae_matrix_set_length(&a, 3+1, 3+1, _state); - ae_vector_set_length(&x1, 3+1, _state); - a.ptr.pp_double[1][1] = (double)(2); - a.ptr.pp_double[1][2] = (double)(3); - a.ptr.pp_double[1][3] = (double)(1); - a.ptr.pp_double[2][1] = (double)(4); - a.ptr.pp_double[2][2] = (double)(-5); - a.ptr.pp_double[2][3] = (double)(8); - a.ptr.pp_double[3][1] = (double)(99); - a.ptr.pp_double[3][2] = (double)(3); - a.ptr.pp_double[3][3] = (double)(1); - hsnerrors = ae_fp_greater(ae_fabs(upperhessenberg1norm(&a, 1, 3, 1, 3, &x1, _state)-11, _state),threshold); - - /* - * Testing MatrixVectorMultiply - */ - ae_matrix_set_length(&a, 3+1, 5+1, _state); - ae_vector_set_length(&x1, 3+1, _state); - ae_vector_set_length(&x2, 2+1, _state); - a.ptr.pp_double[2][3] = (double)(2); - a.ptr.pp_double[2][4] = (double)(-1); - a.ptr.pp_double[2][5] = (double)(-1); - a.ptr.pp_double[3][3] = (double)(1); - a.ptr.pp_double[3][4] = (double)(-2); - a.ptr.pp_double[3][5] = (double)(2); - x1.ptr.p_double[1] = (double)(1); - x1.ptr.p_double[2] = (double)(2); - x1.ptr.p_double[3] = (double)(1); - x2.ptr.p_double[1] = (double)(-1); - x2.ptr.p_double[2] = (double)(-1); - matrixvectormultiply(&a, 2, 3, 3, 5, ae_false, &x1, 1, 3, 1.0, &x2, 1, 2, 1.0, _state); - matrixvectormultiply(&a, 2, 3, 3, 5, ae_true, &x2, 1, 2, 1.0, &x1, 1, 3, 1.0, _state); - e1 = ae_fabs(x1.ptr.p_double[1]+5, _state)+ae_fabs(x1.ptr.p_double[2]-8, _state)+ae_fabs(x1.ptr.p_double[3]+1, _state)+ae_fabs(x2.ptr.p_double[1]+2, _state)+ae_fabs(x2.ptr.p_double[2]+2, _state); - x1.ptr.p_double[1] = (double)(1); - x1.ptr.p_double[2] = (double)(2); - x1.ptr.p_double[3] = (double)(1); - x2.ptr.p_double[1] = (double)(-1); - x2.ptr.p_double[2] = (double)(-1); - matrixvectormultiply(&a, 2, 3, 3, 5, ae_false, &x1, 1, 3, 1.0, &x2, 1, 2, 0.0, _state); - matrixvectormultiply(&a, 2, 3, 3, 5, ae_true, &x2, 1, 2, 1.0, &x1, 1, 3, 0.0, _state); - e2 = ae_fabs(x1.ptr.p_double[1]+3, _state)+ae_fabs(x1.ptr.p_double[2]-3, _state)+ae_fabs(x1.ptr.p_double[3]+1, _state)+ae_fabs(x2.ptr.p_double[1]+1, _state)+ae_fabs(x2.ptr.p_double[2]+1, _state); - mverrors = ae_fp_greater_eq(e1+e2,threshold); - - /* - * testing inplace transpose - */ - n = 10; - ae_matrix_set_length(&a, n+1, n+1, _state); - ae_matrix_set_length(&b, n+1, n+1, _state); - ae_vector_set_length(&x1, n-1+1, _state); - for(i=1; i<=n; i++) - { - for(j=1; j<=n; j++) - { - a.ptr.pp_double[i][j] = ae_randomreal(_state); - } - } - passcount = 10000; - was1 = ae_false; - for(pass=1; pass<=passcount; pass++) - { - i1 = 1+ae_randominteger(n, _state); - i2 = i1+ae_randominteger(n-i1+1, _state); - j1 = 1+ae_randominteger(n-(i2-i1), _state); - j2 = j1+(i2-i1); - copymatrix(&a, i1, i2, j1, j2, &b, i1, i2, j1, j2, _state); - inplacetranspose(&b, i1, i2, j1, j2, &x1, _state); - for(i=i1; i<=i2; i++) - { - for(j=j1; j<=j2; j++) - { - if( ae_fp_neq(a.ptr.pp_double[i][j],b.ptr.pp_double[i1+(j-j1)][j1+(i-i1)]) ) - { - was1 = ae_true; - } - } - } - } - iterrors = was1; - - /* - * testing copy and transpose - */ - n = 10; - ae_matrix_set_length(&a, n+1, n+1, _state); - ae_matrix_set_length(&b, n+1, n+1, _state); - for(i=1; i<=n; i++) - { - for(j=1; j<=n; j++) - { - a.ptr.pp_double[i][j] = ae_randomreal(_state); - } - } - passcount = 10000; - was1 = ae_false; - for(pass=1; pass<=passcount; pass++) - { - i1 = 1+ae_randominteger(n, _state); - i2 = i1+ae_randominteger(n-i1+1, _state); - j1 = 1+ae_randominteger(n, _state); - j2 = j1+ae_randominteger(n-j1+1, _state); - copyandtranspose(&a, i1, i2, j1, j2, &b, j1, j2, i1, i2, _state); - for(i=i1; i<=i2; i++) - { - for(j=j1; j<=j2; j++) - { - if( ae_fp_neq(a.ptr.pp_double[i][j],b.ptr.pp_double[j][i]) ) - { - was1 = ae_true; - } - } - } - } - cterrors = was1; - - /* - * Testing MatrixMatrixMultiply - */ - n = 10; - ae_matrix_set_length(&a, 2*n+1, 2*n+1, _state); - ae_matrix_set_length(&b, 2*n+1, 2*n+1, _state); - ae_matrix_set_length(&c1, 2*n+1, 2*n+1, _state); - ae_matrix_set_length(&c2, 2*n+1, 2*n+1, _state); - ae_vector_set_length(&x1, n+1, _state); - ae_vector_set_length(&x2, n+1, _state); - for(i=1; i<=2*n; i++) - { - for(j=1; j<=2*n; j++) - { - a.ptr.pp_double[i][j] = ae_randomreal(_state); - b.ptr.pp_double[i][j] = ae_randomreal(_state); - } - } - passcount = 1000; - was1 = ae_false; - for(pass=1; pass<=passcount; pass++) - { - for(i=1; i<=2*n; i++) - { - for(j=1; j<=2*n; j++) - { - c1.ptr.pp_double[i][j] = 2.1*i+3.1*j; - c2.ptr.pp_double[i][j] = c1.ptr.pp_double[i][j]; - } - } - l = 1+ae_randominteger(n, _state); - k = 1+ae_randominteger(n, _state); - r = 1+ae_randominteger(n, _state); - i1 = 1+ae_randominteger(n, _state); - j1 = 1+ae_randominteger(n, _state); - i2 = 1+ae_randominteger(n, _state); - j2 = 1+ae_randominteger(n, _state); - i3 = 1+ae_randominteger(n, _state); - j3 = 1+ae_randominteger(n, _state); - trans1 = ae_fp_greater(ae_randomreal(_state),0.5); - trans2 = ae_fp_greater(ae_randomreal(_state),0.5); - if( trans1 ) - { - col1 = l; - row1 = k; - } - else - { - col1 = k; - row1 = l; - } - if( trans2 ) - { - col2 = k; - row2 = r; - } - else - { - col2 = r; - row2 = k; - } - scl1 = ae_randomreal(_state); - scl2 = ae_randomreal(_state); - matrixmatrixmultiply(&a, i1, i1+row1-1, j1, j1+col1-1, trans1, &b, i2, i2+row2-1, j2, j2+col2-1, trans2, scl1, &c1, i3, i3+l-1, j3, j3+r-1, scl2, &x1, _state); - testblasunit_naivematrixmatrixmultiply(&a, i1, i1+row1-1, j1, j1+col1-1, trans1, &b, i2, i2+row2-1, j2, j2+col2-1, trans2, scl1, &c2, i3, i3+l-1, j3, j3+r-1, scl2, _state); - err = (double)(0); - for(i=1; i<=l; i++) - { - for(j=1; j<=r; j++) - { - err = ae_maxreal(err, ae_fabs(c1.ptr.pp_double[i3+i-1][j3+j-1]-c2.ptr.pp_double[i3+i-1][j3+j-1], _state), _state); - } - } - if( ae_fp_greater(err,threshold) ) - { - was1 = ae_true; - break; - } - } - mmerrors = was1; - - /* - * report - */ - waserrors = (((((n2errors||amaxerrors)||hsnerrors)||mverrors)||iterrors)||cterrors)||mmerrors; - if( !silent ) - { - printf("TESTING BLAS\n"); - printf("VectorNorm2: "); - if( n2errors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("AbsMax (vector/row/column): "); - if( amaxerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("UpperHessenberg1Norm: "); - if( hsnerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("MatrixVectorMultiply: "); - if( mverrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("InplaceTranspose: "); - if( iterrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("CopyAndTranspose: "); - if( cterrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("MatrixMatrixMultiply: "); - if( mmerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -static void testblasunit_naivematrixmatrixmultiply(/* Real */ ae_matrix* a, - ae_int_t ai1, - ae_int_t ai2, - ae_int_t aj1, - ae_int_t aj2, - ae_bool transa, - /* Real */ ae_matrix* b, - ae_int_t bi1, - ae_int_t bi2, - ae_int_t bj1, - ae_int_t bj2, - ae_bool transb, - double alpha, - /* Real */ ae_matrix* c, - ae_int_t ci1, - ae_int_t ci2, - ae_int_t cj1, - ae_int_t cj2, - double beta, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t arows; - ae_int_t acols; - ae_int_t brows; - ae_int_t bcols; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t l; - ae_int_t r; - double v; - ae_vector x1; - ae_vector x2; - - ae_frame_make(_state, &_frame_block); - memset(&x1, 0, sizeof(x1)); - memset(&x2, 0, sizeof(x2)); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - - - /* - * Setup - */ - if( !transa ) - { - arows = ai2-ai1+1; - acols = aj2-aj1+1; - } - else - { - arows = aj2-aj1+1; - acols = ai2-ai1+1; - } - if( !transb ) - { - brows = bi2-bi1+1; - bcols = bj2-bj1+1; - } - else - { - brows = bj2-bj1+1; - bcols = bi2-bi1+1; - } - ae_assert(acols==brows, "NaiveMatrixMatrixMultiply: incorrect matrix sizes!", _state); - if( ((arows<=0||acols<=0)||brows<=0)||bcols<=0 ) - { - ae_frame_leave(_state); - return; - } - l = arows; - r = bcols; - k = acols; - ae_vector_set_length(&x1, k+1, _state); - ae_vector_set_length(&x2, k+1, _state); - for(i=1; i<=l; i++) - { - for(j=1; j<=r; j++) - { - if( !transa ) - { - if( !transb ) - { - v = ae_v_dotproduct(&b->ptr.pp_double[bi1][bj1+j-1], b->stride, &a->ptr.pp_double[ai1+i-1][aj1], 1, ae_v_len(bi1,bi2)); - } - else - { - v = ae_v_dotproduct(&b->ptr.pp_double[bi1+j-1][bj1], 1, &a->ptr.pp_double[ai1+i-1][aj1], 1, ae_v_len(bj1,bj2)); - } - } - else - { - if( !transb ) - { - v = ae_v_dotproduct(&b->ptr.pp_double[bi1][bj1+j-1], b->stride, &a->ptr.pp_double[ai1][aj1+i-1], a->stride, ae_v_len(bi1,bi2)); - } - else - { - v = ae_v_dotproduct(&b->ptr.pp_double[bi1+j-1][bj1], 1, &a->ptr.pp_double[ai1][aj1+i-1], a->stride, ae_v_len(bj1,bj2)); - } - } - if( ae_fp_eq(beta,(double)(0)) ) - { - c->ptr.pp_double[ci1+i-1][cj1+j-1] = alpha*v; - } - else - { - c->ptr.pp_double[ci1+i-1][cj1+j-1] = beta*c->ptr.pp_double[ci1+i-1][cj1+j-1]+alpha*v; - } - } - } - ae_frame_leave(_state); -} - - - -static void testsvdunit_fillsparsea(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double sparcity, - ae_state *_state); -static void testsvdunit_getsvderror(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* u, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* vt, - double* materr, - double* orterr, - ae_bool* wsorted, - ae_state *_state); -static void testsvdunit_testsvdproblem(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double* materr, - double* orterr, - double* othererr, - ae_bool* wsorted, - ae_bool* wfailed, - ae_int_t* failcount, - ae_int_t* succcount, - ae_state *_state); - - - - - -/************************************************************************* -Testing SVD decomposition subroutine -*************************************************************************/ -ae_bool testsvd(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_int_t m; - ae_int_t n; - ae_int_t maxmn; - ae_int_t i; - ae_int_t j; - ae_int_t gpass; - ae_int_t pass; - ae_bool waserrors; - ae_bool wsorted; - ae_bool wfailed; - double materr; - double orterr; - double othererr; - double threshold; - double failr; - ae_int_t failcount; - ae_int_t succcount; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - - failcount = 0; - succcount = 0; - materr = (double)(0); - orterr = (double)(0); - othererr = (double)(0); - wsorted = ae_true; - wfailed = ae_false; - waserrors = ae_false; - maxmn = 30; - threshold = 5*100*ae_machineepsilon; - ae_matrix_set_length(&a, maxmn-1+1, maxmn-1+1, _state); - - /* - * TODO: div by zero fail, convergence fail - */ - for(gpass=1; gpass<=1; gpass++) - { - - /* - * zero matrix, several cases - */ - for(i=0; i<=maxmn-1; i++) - { - for(j=0; j<=maxmn-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=1; i<=ae_minint(5, maxmn, _state); i++) - { - for(j=1; j<=ae_minint(5, maxmn, _state); j++) - { - testsvdunit_testsvdproblem(&a, i, j, &materr, &orterr, &othererr, &wsorted, &wfailed, &failcount, &succcount, _state); - } - } - - /* - * Long dense matrix - */ - for(i=0; i<=maxmn-1; i++) - { - for(j=0; j<=ae_minint(5, maxmn, _state)-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - for(i=1; i<=maxmn; i++) - { - for(j=1; j<=ae_minint(5, maxmn, _state); j++) - { - testsvdunit_testsvdproblem(&a, i, j, &materr, &orterr, &othererr, &wsorted, &wfailed, &failcount, &succcount, _state); - } - } - for(i=0; i<=ae_minint(5, maxmn, _state)-1; i++) - { - for(j=0; j<=maxmn-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - for(i=1; i<=ae_minint(5, maxmn, _state); i++) - { - for(j=1; j<=maxmn; j++) - { - testsvdunit_testsvdproblem(&a, i, j, &materr, &orterr, &othererr, &wsorted, &wfailed, &failcount, &succcount, _state); - } - } - - /* - * Dense matrices - */ - for(m=1; m<=ae_minint(10, maxmn, _state); m++) - { - for(n=1; n<=ae_minint(10, maxmn, _state); n++) - { - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - testsvdunit_testsvdproblem(&a, m, n, &materr, &orterr, &othererr, &wsorted, &wfailed, &failcount, &succcount, _state); - } - } - - /* - * Sparse matrices, very sparse matrices, incredible sparse matrices - */ - for(m=1; m<=10; m++) - { - for(n=1; n<=10; n++) - { - for(pass=1; pass<=2; pass++) - { - testsvdunit_fillsparsea(&a, m, n, 0.8, _state); - testsvdunit_testsvdproblem(&a, m, n, &materr, &orterr, &othererr, &wsorted, &wfailed, &failcount, &succcount, _state); - testsvdunit_fillsparsea(&a, m, n, 0.9, _state); - testsvdunit_testsvdproblem(&a, m, n, &materr, &orterr, &othererr, &wsorted, &wfailed, &failcount, &succcount, _state); - testsvdunit_fillsparsea(&a, m, n, 0.95, _state); - testsvdunit_testsvdproblem(&a, m, n, &materr, &orterr, &othererr, &wsorted, &wfailed, &failcount, &succcount, _state); - } - } - } - } - - /* - * report - */ - failr = (double)failcount/(double)(succcount+failcount); - waserrors = (((wfailed||ae_fp_greater(materr,threshold))||ae_fp_greater(orterr,threshold))||ae_fp_greater(othererr,threshold))||!wsorted; - if( !silent ) - { - printf("TESTING SVD DECOMPOSITION\n"); - printf("SVD decomposition error: %5.3e\n", - (double)(materr)); - printf("SVD orthogonality error: %5.3e\n", - (double)(orterr)); - printf("SVD with different parameters error: %5.3e\n", - (double)(othererr)); - printf("Singular values order: "); - if( wsorted ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("Always converged: "); - if( !wfailed ) - { - printf("YES\n"); - } - else - { - printf("NO\n"); - printf("Fail ratio: %5.3f\n", - (double)(failr)); - } - printf("Threshold: %5.3e\n", - (double)(threshold)); - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -static void testsvdunit_fillsparsea(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double sparcity, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_greater_eq(ae_randomreal(_state),sparcity) ) - { - a->ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - else - { - a->ptr.pp_double[i][j] = (double)(0); - } - } - } -} - - -static void testsvdunit_getsvderror(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* u, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* vt, - double* materr, - double* orterr, - ae_bool* wsorted, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t minmn; - double locerr; - double sm; - - - minmn = ae_minint(m, n, _state); - - /* - * decomposition error - */ - locerr = (double)(0); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - sm = (double)(0); - for(k=0; k<=minmn-1; k++) - { - sm = sm+w->ptr.p_double[k]*u->ptr.pp_double[i][k]*vt->ptr.pp_double[k][j]; - } - locerr = ae_maxreal(locerr, ae_fabs(a->ptr.pp_double[i][j]-sm, _state), _state); - } - } - *materr = ae_maxreal(*materr, locerr, _state); - - /* - * orthogonality error - */ - locerr = (double)(0); - for(i=0; i<=minmn-1; i++) - { - for(j=i; j<=minmn-1; j++) - { - sm = ae_v_dotproduct(&u->ptr.pp_double[0][i], u->stride, &u->ptr.pp_double[0][j], u->stride, ae_v_len(0,m-1)); - if( i!=j ) - { - locerr = ae_maxreal(locerr, ae_fabs(sm, _state), _state); - } - else - { - locerr = ae_maxreal(locerr, ae_fabs(sm-1, _state), _state); - } - sm = ae_v_dotproduct(&vt->ptr.pp_double[i][0], 1, &vt->ptr.pp_double[j][0], 1, ae_v_len(0,n-1)); - if( i!=j ) - { - locerr = ae_maxreal(locerr, ae_fabs(sm, _state), _state); - } - else - { - locerr = ae_maxreal(locerr, ae_fabs(sm-1, _state), _state); - } - } - } - *orterr = ae_maxreal(*orterr, locerr, _state); - - /* - * values order error - */ - for(i=1; i<=minmn-1; i++) - { - if( ae_fp_greater(w->ptr.p_double[i],w->ptr.p_double[i-1]) ) - { - *wsorted = ae_false; - } - } -} - - -static void testsvdunit_testsvdproblem(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double* materr, - double* orterr, - double* othererr, - ae_bool* wsorted, - ae_bool* wfailed, - ae_int_t* failcount, - ae_int_t* succcount, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix u; - ae_matrix vt; - ae_matrix u2; - ae_matrix vt2; - ae_vector w; - ae_vector w2; - ae_int_t i; - ae_int_t j; - ae_int_t ujob; - ae_int_t vtjob; - ae_int_t memjob; - ae_int_t ucheck; - ae_int_t vtcheck; - - ae_frame_make(_state, &_frame_block); - memset(&u, 0, sizeof(u)); - memset(&vt, 0, sizeof(vt)); - memset(&u2, 0, sizeof(u2)); - memset(&vt2, 0, sizeof(vt2)); - memset(&w, 0, sizeof(w)); - memset(&w2, 0, sizeof(w2)); - ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vt, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&u2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vt2, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w2, 0, DT_REAL, _state, ae_true); - - - /* - * Main SVD test - */ - if( !rmatrixsvd(a, m, n, 2, 2, 2, &w, &u, &vt, _state) ) - { - *failcount = *failcount+1; - *wfailed = ae_true; - ae_frame_leave(_state); - return; - } - testsvdunit_getsvderror(a, m, n, &u, &w, &vt, materr, orterr, wsorted, _state); - - /* - * Additional SVD tests - */ - for(ujob=0; ujob<=2; ujob++) - { - for(vtjob=0; vtjob<=2; vtjob++) - { - for(memjob=0; memjob<=2; memjob++) - { - if( !rmatrixsvd(a, m, n, ujob, vtjob, memjob, &w2, &u2, &vt2, _state) ) - { - *failcount = *failcount+1; - *wfailed = ae_true; - ae_frame_leave(_state); - return; - } - ucheck = 0; - if( ujob==1 ) - { - ucheck = ae_minint(m, n, _state); - } - if( ujob==2 ) - { - ucheck = m; - } - vtcheck = 0; - if( vtjob==1 ) - { - vtcheck = ae_minint(m, n, _state); - } - if( vtjob==2 ) - { - vtcheck = n; - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=ucheck-1; j++) - { - *othererr = ae_maxreal(*othererr, ae_fabs(u.ptr.pp_double[i][j]-u2.ptr.pp_double[i][j], _state), _state); - } - } - for(i=0; i<=vtcheck-1; i++) - { - for(j=0; j<=n-1; j++) - { - *othererr = ae_maxreal(*othererr, ae_fabs(vt.ptr.pp_double[i][j]-vt2.ptr.pp_double[i][j], _state), _state); - } - } - for(i=0; i<=ae_minint(m, n, _state)-1; i++) - { - *othererr = ae_maxreal(*othererr, ae_fabs(w.ptr.p_double[i]-w2.ptr.p_double[i], _state), _state); - } - } - } - } - - /* - * update counter - */ - *succcount = *succcount+1; - ae_frame_leave(_state); -} - - - -static void testoptservunit_testprec(ae_bool* wereerrors, - ae_state *_state); - - - - - -ae_bool testoptserv(ae_bool silent, ae_state *_state) -{ - ae_bool precerrors; - ae_bool wereerrors; - ae_bool result; - - - precerrors = ae_false; - testoptservunit_testprec(&precerrors, _state); - - /* - * report - */ - wereerrors = precerrors; - if( !silent ) - { - printf("TESTING OPTSERV\n"); - printf("TESTS: \n"); - printf("* PRECONDITIONERS "); - if( precerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( wereerrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !wereerrors; - return result; -} - - -/************************************************************************* -This function checks preconditioning functions - -On failure sets error flag. -*************************************************************************/ -static void testoptservunit_testprec(ae_bool* wereerrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t k; - ae_int_t i; - ae_int_t j; - ae_int_t i0; - ae_int_t j0; - ae_int_t j1; - double v; - double rho; - double theta; - double tolg; - ae_matrix va; - ae_vector vc; - ae_vector vd; - ae_vector vb; - ae_vector s0; - ae_vector s1; - ae_vector s2; - ae_vector g; - precbuflbfgs buf; - precbuflowrank lowrankbuf; - ae_vector norms; - ae_matrix sk; - ae_matrix yk; - ae_matrix bk; - ae_vector bksk; - ae_vector tmp; - matinvreport rep; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&va, 0, sizeof(va)); - memset(&vc, 0, sizeof(vc)); - memset(&vd, 0, sizeof(vd)); - memset(&vb, 0, sizeof(vb)); - memset(&s0, 0, sizeof(s0)); - memset(&s1, 0, sizeof(s1)); - memset(&s2, 0, sizeof(s2)); - memset(&g, 0, sizeof(g)); - memset(&buf, 0, sizeof(buf)); - memset(&lowrankbuf, 0, sizeof(lowrankbuf)); - memset(&norms, 0, sizeof(norms)); - memset(&sk, 0, sizeof(sk)); - memset(&yk, 0, sizeof(yk)); - memset(&bk, 0, sizeof(bk)); - memset(&bksk, 0, sizeof(bksk)); - memset(&tmp, 0, sizeof(tmp)); - memset(&rep, 0, sizeof(rep)); - memset(&rs, 0, sizeof(rs)); - ae_matrix_init(&va, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vd, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vb, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&g, 0, DT_REAL, _state, ae_true); - _precbuflbfgs_init(&buf, _state, ae_true); - _precbuflowrank_init(&lowrankbuf, _state, ae_true); - ae_vector_init(&norms, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&sk, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&yk, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&bk, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bksk, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - _matinvreport_init(&rep, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Test for inexact L-BFGS preconditioner. - * - * We generate QP problem 0.5*x'*H*x, with random H=D+V'*C*V. - * Different K's, from 0 to N, are tried. We test preconditioner - * code which uses compact L-BFGS update against reference implementation - * which uses non-compact BFGS scheme. - * - * For each K we perform two tests: first for KxN non-zero matrix V, - * second one for NxN matrix V with last N-K rows set to zero. Last test - * checks algorithm's ability to handle zero updates. - */ - tolg = 1.0E-9; - for(n=1; n<=10; n++) - { - for(k=0; k<=n; k++) - { - - /* - * Prepare problem: - * * VD, VC, VA, with VC/VA reordered by ascending of VC[i]*norm(VA[i,...])^2 - * * trial vector S (copies are stored to S0,S1,S2) - */ - ae_vector_set_length(&vd, n, _state); - ae_vector_set_length(&s0, n, _state); - ae_vector_set_length(&s1, n, _state); - ae_vector_set_length(&s2, n, _state); - for(i=0; i<=n-1; i++) - { - vd.ptr.p_double[i] = ae_exp(hqrndnormal(&rs, _state), _state); - s0.ptr.p_double[i] = hqrndnormal(&rs, _state); - s1.ptr.p_double[i] = s0.ptr.p_double[i]; - s2.ptr.p_double[i] = s0.ptr.p_double[i]; - } - rmatrixrndcond(n, 1.0E2, &va, _state); - rvectorsetlengthatleast(&vc, n, _state); - for(i=0; i<=k-1; i++) - { - vc.ptr.p_double[i] = ae_exp(hqrndnormal(&rs, _state), _state); - } - for(i=k; i<=n-1; i++) - { - vc.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - va.ptr.pp_double[i][j] = 0.0; - } - } - ae_vector_set_length(&norms, k, _state); - for(i=0; i<=k-1; i++) - { - v = ae_v_dotproduct(&va.ptr.pp_double[i][0], 1, &va.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - norms.ptr.p_double[i] = v*vc.ptr.p_double[i]; - } - for(i=0; i<=k-1; i++) - { - for(j=0; j<=k-2; j++) - { - if( ae_fp_greater(norms.ptr.p_double[j],norms.ptr.p_double[j+1]) ) - { - - /* - * Swap elements J and J+1 - */ - v = norms.ptr.p_double[j]; - norms.ptr.p_double[j] = norms.ptr.p_double[j+1]; - norms.ptr.p_double[j+1] = v; - v = vc.ptr.p_double[j]; - vc.ptr.p_double[j] = vc.ptr.p_double[j+1]; - vc.ptr.p_double[j+1] = v; - for(j0=0; j0<=n-1; j0++) - { - v = va.ptr.pp_double[j][j0]; - va.ptr.pp_double[j][j0] = va.ptr.pp_double[j+1][j0]; - va.ptr.pp_double[j+1][j0] = v; - } - } - } - } - - /* - * Generate reference model and apply it to S2: - * * generate approximate Hessian Bk - * * calculate inv(Bk) - * * calculate inv(Bk)*S2, store to S2 - */ - rmatrixsetlengthatleast(&sk, k, n, _state); - rmatrixsetlengthatleast(&yk, k, n, _state); - ae_matrix_set_length(&bk, n, n, _state); - ae_vector_set_length(&bksk, n, _state); - ae_vector_set_length(&tmp, n, _state); - for(i=0; i<=k-1; i++) - { - ae_v_move(&sk.ptr.pp_double[i][0], 1, &va.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - v = ae_v_dotproduct(&va.ptr.pp_double[i][0], 1, &sk.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - v = v*vc.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - yk.ptr.pp_double[i][j] = vd.ptr.p_double[j]*sk.ptr.pp_double[i][j]+va.ptr.pp_double[i][j]*v; - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - bk.ptr.pp_double[i][i] = vd.ptr.p_double[i]; - } - else - { - bk.ptr.pp_double[i][j] = 0.0; - } - } - } - for(i=0; i<=k-1; i++) - { - theta = 0.0; - for(j0=0; j0<=n-1; j0++) - { - bksk.ptr.p_double[j0] = (double)(0); - for(j1=0; j1<=n-1; j1++) - { - theta = theta+sk.ptr.pp_double[i][j0]*bk.ptr.pp_double[j0][j1]*sk.ptr.pp_double[i][j1]; - bksk.ptr.p_double[j0] = bksk.ptr.p_double[j0]+bk.ptr.pp_double[j0][j1]*sk.ptr.pp_double[i][j1]; - } - } - theta = 1/theta; - rho = ae_v_dotproduct(&sk.ptr.pp_double[i][0], 1, &yk.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - rho = 1/rho; - for(j0=0; j0<=n-1; j0++) - { - for(j1=0; j1<=n-1; j1++) - { - bk.ptr.pp_double[j0][j1] = bk.ptr.pp_double[j0][j1]+rho*yk.ptr.pp_double[i][j0]*yk.ptr.pp_double[i][j1]; - } - } - for(j0=0; j0<=n-1; j0++) - { - for(j1=0; j1<=n-1; j1++) - { - bk.ptr.pp_double[j0][j1] = bk.ptr.pp_double[j0][j1]-theta*bksk.ptr.p_double[j0]*bksk.ptr.p_double[j1]; - } - } - } - rmatrixinverse(&bk, n, &j0, &rep, _state); - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&bk.ptr.pp_double[i][0], 1, &s2.ptr.p_double[0], 1, ae_v_len(0,n-1)); - tmp.ptr.p_double[i] = v; - } - for(i=0; i<=n-1; i++) - { - s2.ptr.p_double[i] = tmp.ptr.p_double[i]; - } - - /* - * First test for non-zero V: - * * apply preconditioner to X0 - * * compare reference model against implementation being tested - */ - inexactlbfgspreconditioner(&s0, n, &vd, &vc, &va, k, &buf, _state); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(s2.ptr.p_double[i]-s0.ptr.p_double[i], _state),tolg), __FILE__, __LINE__, "testoptservunit.ap:236"); - } - - /* - * Second test - N-K zero rows appended to V and rows are - * randomly reordered. Doing so should not change result, - * algorithm must be able to order rows according to second derivative - * and skip zero updates. - */ - for(i=0; i<=n-1; i++) - { - i0 = i+hqrnduniformi(&rs, n-i, _state); - v = vc.ptr.p_double[i]; - vc.ptr.p_double[i] = vc.ptr.p_double[i0]; - vc.ptr.p_double[i0] = v; - for(j=0; j<=n-1; j++) - { - v = va.ptr.pp_double[i][j]; - va.ptr.pp_double[i][j] = va.ptr.pp_double[i0][j]; - va.ptr.pp_double[i0][j] = v; - } - } - inexactlbfgspreconditioner(&s1, n, &vd, &vc, &va, n, &buf, _state); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(s2.ptr.p_double[i]-s1.ptr.p_double[i], _state),tolg), __FILE__, __LINE__, "testoptservunit.ap:259"); - } - } - } - - /* - * Test for exact low-rank preconditioner. - * - * We generate QP problem 0.5*x'*H*x, with random H=D+V'*C*V. - * Different K's, from 0 to N, are tried. We test preconditioner - * code which uses Woodbury update against reference implementation - * which performs straightforward matrix inversion. - * - * For each K we perform two tests: first for KxN non-zero matrix V, - * second one for NxN matrix V with randomly appended N-K zero rows. - * Last test checks algorithm's ability to handle zero updates. - */ - tolg = 1.0E-9; - for(n=1; n<=10; n++) - { - for(k=0; k<=n; k++) - { - - /* - * Prepare problem: - * * VD, VC, VA - * * trial vector S (copies are stored to S0,S1,S2) - */ - ae_vector_set_length(&vd, n, _state); - ae_vector_set_length(&s0, n, _state); - ae_vector_set_length(&s1, n, _state); - ae_vector_set_length(&s2, n, _state); - for(i=0; i<=n-1; i++) - { - vd.ptr.p_double[i] = ae_exp(hqrndnormal(&rs, _state), _state); - s0.ptr.p_double[i] = hqrndnormal(&rs, _state); - s1.ptr.p_double[i] = s0.ptr.p_double[i]; - s2.ptr.p_double[i] = s0.ptr.p_double[i]; - } - rmatrixrndcond(n, 1.0E2, &va, _state); - rvectorsetlengthatleast(&vc, n, _state); - for(i=0; i<=k-1; i++) - { - vc.ptr.p_double[i] = ae_exp(hqrndnormal(&rs, _state), _state); - } - for(i=k; i<=n-1; i++) - { - vc.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - va.ptr.pp_double[i][j] = 0.0; - } - } - - /* - * Generate reference model and apply it to S2 - */ - ae_matrix_set_length(&bk, n, n, _state); - ae_vector_set_length(&tmp, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - v = vd.ptr.p_double[i]; - } - else - { - v = 0.0; - } - for(j1=0; j1<=k-1; j1++) - { - v = v+va.ptr.pp_double[j1][i]*vc.ptr.p_double[j1]*va.ptr.pp_double[j1][j]; - } - bk.ptr.pp_double[i][j] = v; - } - } - rmatrixinverse(&bk, n, &j, &rep, _state); - ae_assert(j>0, "Assertion failed", _state); - for(i=0; i<=n-1; i++) - { - v = 0.0; - for(j=0; j<=n-1; j++) - { - v = v+bk.ptr.pp_double[i][j]*s2.ptr.p_double[j]; - } - tmp.ptr.p_double[i] = v; - } - for(i=0; i<=n-1; i++) - { - s2.ptr.p_double[i] = tmp.ptr.p_double[i]; - } - - /* - * First test for non-zero V: - * * apply preconditioner to X0 - * * compare reference model against implementation being tested - */ - preparelowrankpreconditioner(&vd, &vc, &va, n, k, &lowrankbuf, _state); - applylowrankpreconditioner(&s0, &lowrankbuf, _state); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(s2.ptr.p_double[i]-s0.ptr.p_double[i], _state),tolg), __FILE__, __LINE__, "testoptservunit.ap:341"); - } - - /* - * Second test - N-K zero rows appended to V and rows are - * randomly reordered. Doing so should not change result, - * algorithm must be able to order rows according to second derivative - * and skip zero updates. - */ - for(i=0; i<=n-1; i++) - { - i0 = i+hqrnduniformi(&rs, n-i, _state); - v = vc.ptr.p_double[i]; - vc.ptr.p_double[i] = vc.ptr.p_double[i0]; - vc.ptr.p_double[i0] = v; - for(j=0; j<=n-1; j++) - { - v = va.ptr.pp_double[i][j]; - va.ptr.pp_double[i][j] = va.ptr.pp_double[i0][j]; - va.ptr.pp_double[i0][j] = v; - } - } - preparelowrankpreconditioner(&vd, &vc, &va, n, n, &lowrankbuf, _state); - applylowrankpreconditioner(&s1, &lowrankbuf, _state); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(s2.ptr.p_double[i]-s1.ptr.p_double[i], _state),tolg), __FILE__, __LINE__, "testoptservunit.ap:365"); - } - } - } - ae_frame_leave(_state); -} - - - - - - - - -ae_bool testsnnls(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_bool test0errors; - ae_bool test1errors; - ae_bool test2errors; - ae_bool testnewtonerrors; - ae_bool waserrors; - double eps; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - ae_int_t ns; - ae_int_t nd; - ae_int_t nr; - ae_matrix densea; - ae_matrix effectivea; - ae_vector isconstrained; - ae_vector g; - ae_vector b; - ae_vector x; - ae_vector xs; - snnlssolver s; - hqrndstate rs; - double rho; - double xtol; - ae_int_t nmax; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&densea, 0, sizeof(densea)); - memset(&effectivea, 0, sizeof(effectivea)); - memset(&isconstrained, 0, sizeof(isconstrained)); - memset(&g, 0, sizeof(g)); - memset(&b, 0, sizeof(b)); - memset(&x, 0, sizeof(x)); - memset(&xs, 0, sizeof(xs)); - memset(&s, 0, sizeof(s)); - memset(&rs, 0, sizeof(rs)); - ae_matrix_init(&densea, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&effectivea, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&isconstrained, 0, DT_BOOL, _state, ae_true); - ae_vector_init(&g, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xs, 0, DT_REAL, _state, ae_true); - _snnlssolver_init(&s, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - test0errors = ae_false; - test1errors = ae_false; - test2errors = ae_false; - testnewtonerrors = ae_false; - waserrors = ae_false; - hqrndrandomize(&rs, _state); - nmax = 10; - - /* - * Test 2 (comes first because it is very basic): - * * NS=0 - * * ND in [1,NMAX] - * * NR=ND - * * DenseA is diagonal with positive entries - * * B is random - * * random constraints - * Exact solution is known and can be tested - */ - eps = 1.0E-12; - for(nd=1; nd<=nmax; nd++) - { - - /* - * Generate problem - */ - ns = 0; - nr = nd; - ae_matrix_set_length(&densea, nd, nd, _state); - ae_vector_set_length(&b, nd, _state); - ae_vector_set_length(&isconstrained, nd, _state); - for(i=0; i<=nd-1; i++) - { - for(j=0; j<=nd-1; j++) - { - densea.ptr.pp_double[i][j] = (double)(0); - } - densea.ptr.pp_double[i][i] = (double)(1+hqrnduniformi(&rs, 2, _state)); - b.ptr.p_double[i] = (double)((1+hqrnduniformi(&rs, 2, _state))*(2*hqrnduniformi(&rs, 2, _state)-1)); - isconstrained.ptr.p_bool[i] = ae_fp_greater(hqrnduniformr(&rs, _state),0.5); - } - - /* - * Solve with SNNLS solver - */ - snnlsinit(0, 0, 0, &s, _state); - snnlssetproblem(&s, &densea, &b, 0, nd, nd, _state); - for(i=0; i<=nd-1; i++) - { - if( !isconstrained.ptr.p_bool[i] ) - { - snnlsdropnnc(&s, i, _state); - } - } - snnlssolve(&s, &x, _state); - - /* - * Check - */ - for(i=0; i<=nd-1; i++) - { - if( isconstrained.ptr.p_bool[i] ) - { - ae_set_error_flag(&test2errors, ae_fp_greater(ae_fabs(x.ptr.p_double[i]-ae_maxreal(b.ptr.p_double[i]/densea.ptr.pp_double[i][i], 0.0, _state), _state),eps), __FILE__, __LINE__, "testsnnlsunit.ap:86"); - ae_set_error_flag(&test2errors, ae_fp_less(x.ptr.p_double[i],0.0), __FILE__, __LINE__, "testsnnlsunit.ap:87"); - } - else - { - ae_set_error_flag(&test2errors, ae_fp_greater(ae_fabs(x.ptr.p_double[i]-b.ptr.p_double[i]/densea.ptr.pp_double[i][i], _state),eps), __FILE__, __LINE__, "testsnnlsunit.ap:90"); - } - } - } - - /* - * Test 0: - * * NS in [0,NMAX] - * * ND in [0,NMAX] - * * NR in [NS,NS+ND+NMAX] - * * NS+ND>0, NR>0 - * * about 50% of variables are constrained - * * we check that constrained gradient is small at the solution - */ - eps = 1.0E-5; - for(ns=0; ns<=nmax; ns++) - { - for(nd=0; nd<=nmax; nd++) - { - for(nr=ns; nr<=ns+nd+nmax; nr++) - { - - /* - * Skip NS+ND=0, NR=0 - */ - if( ns+nd==0 ) - { - continue; - } - if( nr==0 ) - { - continue; - } - - /* - * Generate problem: - * * DenseA, array[NR,ND] - * * EffectiveA, array[NR,NS+ND] - * * B, array[NR] - * * IsConstrained, array[NS+ND] - */ - if( nd>0 ) - { - ae_matrix_set_length(&densea, nr, nd, _state); - for(i=0; i<=nr-1; i++) - { - for(j=0; j<=nd-1; j++) - { - densea.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - } - ae_matrix_set_length(&effectivea, nr, ns+nd, _state); - for(i=0; i<=nr-1; i++) - { - for(j=0; j<=ns+nd-1; j++) - { - effectivea.ptr.pp_double[i][j] = 0.0; - } - } - for(i=0; i<=ns-1; i++) - { - effectivea.ptr.pp_double[i][i] = 1.0; - } - for(i=0; i<=nr-1; i++) - { - for(j=0; j<=nd-1; j++) - { - effectivea.ptr.pp_double[i][ns+j] = densea.ptr.pp_double[i][j]; - } - } - ae_vector_set_length(&b, nr, _state); - for(i=0; i<=nr-1; i++) - { - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - ae_vector_set_length(&isconstrained, ns+nd, _state); - for(i=0; i<=ns+nd-1; i++) - { - isconstrained.ptr.p_bool[i] = ae_fp_greater(ae_randomreal(_state),0.5); - } - - /* - * Solve with SNNLS solver - */ - snnlsinit(0, 0, 0, &s, _state); - snnlssetproblem(&s, &densea, &b, ns, nd, nr, _state); - for(i=0; i<=ns+nd-1; i++) - { - if( !isconstrained.ptr.p_bool[i] ) - { - snnlsdropnnc(&s, i, _state); - } - } - snnlssolve(&s, &x, _state); - - /* - * Check non-negativity - */ - for(i=0; i<=ns+nd-1; i++) - { - ae_set_error_flag(&test0errors, isconstrained.ptr.p_bool[i]&&ae_fp_less(x.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testsnnlsunit.ap:160"); - } - - /* - * Calculate gradient A'*A*x-b'*A. - * Check projected gradient (each component must be less than Eps). - */ - ae_vector_set_length(&g, ns+nd, _state); - for(i=0; i<=ns+nd-1; i++) - { - v = ae_v_dotproduct(&b.ptr.p_double[0], 1, &effectivea.ptr.pp_double[0][i], effectivea.stride, ae_v_len(0,nr-1)); - g.ptr.p_double[i] = -v; - } - for(i=0; i<=nr-1; i++) - { - v = ae_v_dotproduct(&effectivea.ptr.pp_double[i][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,ns+nd-1)); - ae_v_addd(&g.ptr.p_double[0], 1, &effectivea.ptr.pp_double[i][0], 1, ae_v_len(0,ns+nd-1), v); - } - for(i=0; i<=ns+nd-1; i++) - { - if( !isconstrained.ptr.p_bool[i]||ae_fp_greater(x.ptr.p_double[i],(double)(0)) ) - { - ae_set_error_flag(&test0errors, ae_fp_greater(ae_fabs(g.ptr.p_double[i], _state),eps), __FILE__, __LINE__, "testsnnlsunit.ap:179"); - } - else - { - ae_set_error_flag(&test0errors, ae_fp_less(g.ptr.p_double[i],-eps), __FILE__, __LINE__, "testsnnlsunit.ap:181"); - } - } - } - } - } - - /* - * Test 1: ability of the solver to take very short steps. - * - * We solve problem similar to one solver in test 0, but with - * progressively decreased magnitude of variables. We generate - * problem with already-known solution and compare results against it. - */ - xtol = 1.0E-7; - for(ns=0; ns<=nmax; ns++) - { - for(nd=0; nd<=nmax; nd++) - { - for(nr=ns; nr<=ns+nd+nmax; nr++) - { - for(k=0; k<=20; k++) - { - - /* - * Skip NS+ND=0, NR=0 - * - * Skip degenerate problems (NR0 ) - { - ae_matrix_set_length(&densea, nr, nd, _state); - for(i=0; i<=nr-1; i++) - { - for(j=0; j<=nd-1; j++) - { - densea.ptr.pp_double[i][j] = 2*hqrnduniformr(&rs, _state)-1; - } - } - } - ae_matrix_set_length(&effectivea, nr, ns+nd, _state); - for(i=0; i<=nr-1; i++) - { - for(j=0; j<=ns+nd-1; j++) - { - effectivea.ptr.pp_double[i][j] = 0.0; - } - } - for(i=0; i<=ns-1; i++) - { - effectivea.ptr.pp_double[i][i] = 1.0; - } - for(i=0; i<=nr-1; i++) - { - for(j=0; j<=nd-1; j++) - { - effectivea.ptr.pp_double[i][ns+j] = densea.ptr.pp_double[i][j]; - } - } - ae_vector_set_length(&xs, ns+nd, _state); - ae_vector_set_length(&isconstrained, ns+nd, _state); - for(i=0; i<=ns+nd-1; i++) - { - xs.ptr.p_double[i] = rho*(hqrnduniformr(&rs, _state)-0.5); - isconstrained.ptr.p_bool[i] = ae_fp_greater(xs.ptr.p_double[i],0.0); - } - ae_vector_set_length(&b, nr, _state); - for(i=0; i<=nr-1; i++) - { - v = 0.0; - for(j=0; j<=ns+nd-1; j++) - { - v = v+effectivea.ptr.pp_double[i][j]*xs.ptr.p_double[j]; - } - b.ptr.p_double[i] = v; - } - - /* - * Solve with SNNLS solver - */ - snnlsinit(0, 0, 0, &s, _state); - snnlssetproblem(&s, &densea, &b, ns, nd, nr, _state); - for(i=0; i<=ns+nd-1; i++) - { - if( !isconstrained.ptr.p_bool[i] ) - { - snnlsdropnnc(&s, i, _state); - } - } - snnlssolve(&s, &x, _state); - - /* - * Check non-negativity - */ - for(i=0; i<=ns+nd-1; i++) - { - ae_set_error_flag(&test1errors, isconstrained.ptr.p_bool[i]&&ae_fp_less(x.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testsnnlsunit.ap:263"); - } - - /* - * Compare with true solution - */ - for(i=0; i<=ns+nd-1; i++) - { - ae_set_error_flag(&test1errors, ae_fp_greater(ae_fabs(xs.ptr.p_double[i]-x.ptr.p_double[i], _state),rho*xtol), __FILE__, __LINE__, "testsnnlsunit.ap:269"); - } - } - } - } - } - - /* - * Test for Newton phase: - * * NS in [0,NMAX] - * * ND in [0,NMAX] - * * NR in [NS,NS+ND+NMAX] - * * NS+ND>0, NR>0 - * * all variables are unconstrained - * * S.DebugMaxNewton is set to 1, S.RefinementIts is set to 1, - * i.e. algorithm is terminated after one Newton iteration, and no - * iterative refinement is used. - * * we test that gradient is small at solution, i.e. one Newton iteration - * on unconstrained problem is enough to find solution. In case of buggy - * Newton solver one iteration won't move us to the solution - it may - * decrease function value, but won't find exact solution. - * - * This test is intended to catch subtle bugs in the Newton solver which - * do NOT prevent algorithm from converging to the solution, but slow it - * down (convergence becomes linear or even slower). - */ - eps = 1.0E-4; - for(ns=0; ns<=nmax; ns++) - { - for(nd=0; nd<=nmax; nd++) - { - for(nr=ns; nr<=ns+nd+nmax; nr++) - { - - /* - * Skip NS+ND=0, NR=0 - */ - if( ns+nd==0 ) - { - continue; - } - if( nr==0 ) - { - continue; - } - - /* - * Generate problem: - * * DenseA, array[NR,ND] - * * EffectiveA, array[NR,NS+ND] - * * B, array[NR] - * * IsConstrained, array[NS+ND] - */ - if( nd>0 ) - { - ae_matrix_set_length(&densea, nr, nd, _state); - for(i=0; i<=nr-1; i++) - { - for(j=0; j<=nd-1; j++) - { - densea.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - } - ae_matrix_set_length(&effectivea, nr, ns+nd, _state); - for(i=0; i<=nr-1; i++) - { - for(j=0; j<=ns+nd-1; j++) - { - effectivea.ptr.pp_double[i][j] = 0.0; - } - } - for(i=0; i<=ns-1; i++) - { - effectivea.ptr.pp_double[i][i] = 1.0; - } - for(i=0; i<=nr-1; i++) - { - for(j=0; j<=nd-1; j++) - { - effectivea.ptr.pp_double[i][ns+j] = densea.ptr.pp_double[i][j]; - } - } - ae_vector_set_length(&b, nr, _state); - for(i=0; i<=nr-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - - /* - * Solve with SNNLS solver - */ - snnlsinit(0, 0, 0, &s, _state); - snnlssetproblem(&s, &densea, &b, ns, nd, nr, _state); - for(i=0; i<=ns+nd-1; i++) - { - snnlsdropnnc(&s, i, _state); - } - s.debugmaxinnerits = 1; - snnlssolve(&s, &x, _state); - - /* - * Calculate gradient A'*A*x-b'*A. - * Check projected gradient (each component must be less than Eps). - */ - ae_vector_set_length(&g, ns+nd, _state); - for(i=0; i<=ns+nd-1; i++) - { - v = ae_v_dotproduct(&b.ptr.p_double[0], 1, &effectivea.ptr.pp_double[0][i], effectivea.stride, ae_v_len(0,nr-1)); - g.ptr.p_double[i] = -v; - } - for(i=0; i<=nr-1; i++) - { - v = ae_v_dotproduct(&effectivea.ptr.pp_double[i][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,ns+nd-1)); - ae_v_addd(&g.ptr.p_double[0], 1, &effectivea.ptr.pp_double[i][0], 1, ae_v_len(0,ns+nd-1), v); - } - for(i=0; i<=ns+nd-1; i++) - { - ae_set_error_flag(&testnewtonerrors, ae_fp_greater(ae_fabs(g.ptr.p_double[i], _state),eps), __FILE__, __LINE__, "testsnnlsunit.ap:358"); - } - } - } - } - - /* - * report - */ - waserrors = ((test0errors||test1errors)||test2errors)||testnewtonerrors; - if( !silent ) - { - printf("TESTING SPECIAL NNLS SOLVER\n"); - printf("TEST 0: "); - if( test0errors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("TEST 1: "); - if( test1errors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("TEST 2: "); - if( test2errors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("NEWTON PHASE: "); - if( testnewtonerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - - -static void testsactivesetsunit_testspecproperties(ae_bool* err, - ae_state *_state); - - - - - -ae_bool testsactivesets(ae_bool silent, ae_state *_state) -{ - ae_bool waserrors; - ae_bool specerr; - ae_bool result; - - - specerr = ae_false; - testsactivesetsunit_testspecproperties(&specerr, _state); - - /* - * report - */ - waserrors = specerr; - if( !silent ) - { - printf("TESTING ACTIVE SETS\n"); - printf("* SPECIAL PROPERTIES "); - if( specerr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - return result; -} - - -/************************************************************************* -This function tests special properties. - -On failure sets Err to True (leaves it unchanged otherwise) -*************************************************************************/ -static void testsactivesetsunit_testspecproperties(ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t n; - ae_int_t nec; - ae_int_t nic; - double v; - double vv; - sactiveset state; - hqrndstate rs; - ae_vector bl; - ae_vector bu; - ae_vector x; - ae_vector s; - ae_matrix c; - ae_vector ct; - ae_int_t scaletype; - ae_int_t pass; - ae_int_t distortidx; - double distortmag; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&rs, 0, sizeof(rs)); - memset(&bl, 0, sizeof(bl)); - memset(&bu, 0, sizeof(bu)); - memset(&x, 0, sizeof(x)); - memset(&s, 0, sizeof(s)); - memset(&c, 0, sizeof(c)); - memset(&ct, 0, sizeof(ct)); - _sactiveset_init(&state, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - ae_vector_init(&bl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * N-dimensional problem with Ne equality and Ni inequality constraints. - * - * Check that SActiveSet object uses efficient algorithm - * to determine initial point: it avoids expensive (N+Ni)-dimensional - * QP subproblem when initial point is feasible w.r.t. constraints. - * - * In order to do so we try to find initial point for a problem with - * 2 equality constraints and 1000000 inequality constraints (+box - * constraints). Inefficient algorithm will simply fail to allocate - * enough memory, so we do not have to perform any checks here. - */ - n = 5; - nec = 2; - nic = 1000000; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - for(scaletype=0; scaletype<=1; scaletype++) - { - - /* - * Generate problem - */ - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = hqrnduniformr(&rs, _state); - bl.ptr.p_double[i] = x.ptr.p_double[i]-hqrnduniformr(&rs, _state)*hqrnduniformi(&rs, 2, _state); - bu.ptr.p_double[i] = x.ptr.p_double[i]+hqrnduniformr(&rs, _state)*hqrnduniformi(&rs, 2, _state); - } - ae_matrix_set_length(&c, nec+nic, n+1, _state); - ae_vector_set_length(&ct, nec+nic, _state); - for(i=0; i<=nec+nic-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - v = v+c.ptr.pp_double[i][j]*x.ptr.p_double[j]; - } - c.ptr.pp_double[i][n] = v; - if( i1 ) - { - s = ae_maxrealnumber; - } - ry.ptr.p_double[0] = (2*ae_randomreal(_state)-1)*s*ae_sqrt(2*ae_randomreal(_state), _state); - for(i=1; i<=n-1; i++) - { - ry.ptr.p_double[i] = ry.ptr.p_double[0]; - } - for(i=0; i<=n/2-1; i++) - { - rx.ptr.p_double[i] = (double)(1); - } - for(i=n/2; i<=n-2; i++) - { - rx.ptr.p_double[i] = (double)(-1); - } - rx.ptr.p_double[n-1] = (double)(0); - xdot(&rx, &ry, n, &temp, &rv2, &rv2err, _state); - exactnesserrors = exactnesserrors||ae_fp_less(rv2err,(double)(0)); - exactnesserrors = exactnesserrors||ae_fp_greater(rv2err,4*ae_machineepsilon*ae_fabs(ry.ptr.p_double[0], _state)); - exactnesserrors = exactnesserrors||ae_fp_greater(ae_fabs(rv2-ry.ptr.p_double[0], _state),rv2err); - - /* - * First test: X + X + ... + X = N*X - */ - s = ae_exp((double)(ae_maxint(pass, 50, _state)), _state); - if( pass==passcount-1&&pass>1 ) - { - s = ae_maxrealnumber; - } - ry.ptr.p_double[0] = (2*ae_randomreal(_state)-1)*s*ae_sqrt(2*ae_randomreal(_state), _state); - for(i=1; i<=n-1; i++) - { - ry.ptr.p_double[i] = ry.ptr.p_double[0]; - } - for(i=0; i<=n-1; i++) - { - rx.ptr.p_double[i] = (double)(1); - } - xdot(&rx, &ry, n, &temp, &rv2, &rv2err, _state); - exactnesserrors = exactnesserrors||ae_fp_less(rv2err,(double)(0)); - exactnesserrors = exactnesserrors||ae_fp_greater(rv2err,4*ae_machineepsilon*ae_fabs(ry.ptr.p_double[0], _state)*n); - exactnesserrors = exactnesserrors||ae_fp_greater(ae_fabs(rv2-n*ry.ptr.p_double[0], _state),rv2err); - } - - /* - * test of precision: complex - */ - n = 50000; - ae_vector_set_length(&cx, n, _state); - ae_vector_set_length(&cy, n, _state); - ae_vector_set_length(&temp, 2*n, _state); - for(pass=0; pass<=passcount-1; pass++) - { - ae_assert(n%2==0, "Assertion failed", _state); - - /* - * First test: X + X + ... + X - X - X - ... - X = 1*X - */ - s = ae_exp((double)(ae_maxint(pass, 50, _state)), _state); - if( pass==passcount-1&&pass>1 ) - { - s = ae_maxrealnumber; - } - cy.ptr.p_complex[0].x = (2*ae_randomreal(_state)-1)*s*ae_sqrt(2*ae_randomreal(_state), _state); - cy.ptr.p_complex[0].y = (2*ae_randomreal(_state)-1)*s*ae_sqrt(2*ae_randomreal(_state), _state); - for(i=1; i<=n-1; i++) - { - cy.ptr.p_complex[i] = cy.ptr.p_complex[0]; - } - for(i=0; i<=n/2-1; i++) - { - cx.ptr.p_complex[i] = ae_complex_from_i(1); - } - for(i=n/2; i<=n-2; i++) - { - cx.ptr.p_complex[i] = ae_complex_from_i(-1); - } - cx.ptr.p_complex[n-1] = ae_complex_from_i(0); - xcdot(&cx, &cy, n, &temp, &cv2, &cv2err, _state); - exactnesserrors = exactnesserrors||ae_fp_less(cv2err,(double)(0)); - exactnesserrors = exactnesserrors||ae_fp_greater(cv2err,4*ae_machineepsilon*ae_c_abs(cy.ptr.p_complex[0], _state)); - exactnesserrors = exactnesserrors||ae_fp_greater(ae_c_abs(ae_c_sub(cv2,cy.ptr.p_complex[0]), _state),cv2err); - - /* - * First test: X + X + ... + X = N*X - */ - s = ae_exp((double)(ae_maxint(pass, 50, _state)), _state); - if( pass==passcount-1&&pass>1 ) - { - s = ae_maxrealnumber; - } - cy.ptr.p_complex[0] = ae_complex_from_d((2*ae_randomreal(_state)-1)*s*ae_sqrt(2*ae_randomreal(_state), _state)); - for(i=1; i<=n-1; i++) - { - cy.ptr.p_complex[i] = cy.ptr.p_complex[0]; - } - for(i=0; i<=n-1; i++) - { - cx.ptr.p_complex[i] = ae_complex_from_i(1); - } - xcdot(&cx, &cy, n, &temp, &cv2, &cv2err, _state); - exactnesserrors = exactnesserrors||ae_fp_less(cv2err,(double)(0)); - exactnesserrors = exactnesserrors||ae_fp_greater(cv2err,4*ae_machineepsilon*ae_c_abs(cy.ptr.p_complex[0], _state)*n); - exactnesserrors = exactnesserrors||ae_fp_greater(ae_c_abs(ae_c_sub(cv2,ae_c_mul_d(cy.ptr.p_complex[0],1.0*n)), _state),cv2err); - } - - /* - * report - */ - waserrors = approxerrors||exactnesserrors; - if( !silent ) - { - printf("TESTING XBLAS\n"); - printf("APPROX.TESTS: "); - if( approxerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("EXACT TESTS: "); - if( exactnesserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - - /* - * end - */ - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - - -static ae_bool testdirectdensesolversunit_rmatrixchecksolutionm(/* Real */ ae_matrix* xe, - ae_int_t n, - ae_int_t m, - double threshold, - ae_int_t info, - densesolverreport* rep, - /* Real */ ae_matrix* xs, - ae_state *_state); -static ae_bool testdirectdensesolversunit_rmatrixchecksolutionmfast(/* Real */ ae_matrix* xe, - ae_int_t n, - ae_int_t m, - double threshold, - ae_int_t info, - /* Real */ ae_matrix* xs, - ae_state *_state); -static ae_bool testdirectdensesolversunit_rmatrixchecksolution(/* Real */ ae_matrix* xe, - ae_int_t n, - double threshold, - ae_int_t info, - densesolverreport* rep, - /* Real */ ae_vector* xs, - ae_state *_state); -static ae_bool testdirectdensesolversunit_rmatrixchecksolutionfast(/* Real */ ae_matrix* xe, - ae_int_t n, - double threshold, - ae_int_t info, - /* Real */ ae_vector* xs, - ae_state *_state); -static ae_bool testdirectdensesolversunit_rmatrixchecksingularm(ae_int_t n, - ae_int_t m, - ae_int_t info, - densesolverreport* rep, - /* Real */ ae_matrix* xs, - ae_state *_state); -static ae_bool testdirectdensesolversunit_rmatrixchecksingularmfast(ae_int_t n, - ae_int_t m, - ae_int_t info, - /* Real */ ae_matrix* xs, - ae_state *_state); -static ae_bool testdirectdensesolversunit_rmatrixchecksingular(ae_int_t n, - ae_int_t info, - densesolverreport* rep, - /* Real */ ae_vector* xs, - ae_state *_state); -static ae_bool testdirectdensesolversunit_rmatrixchecksingularfast(ae_int_t n, - ae_int_t info, - /* Real */ ae_vector* xs, - ae_state *_state); -static ae_bool testdirectdensesolversunit_cmatrixchecksolutionm(/* Complex */ ae_matrix* xe, - ae_int_t n, - ae_int_t m, - double threshold, - ae_int_t info, - densesolverreport* rep, - /* Complex */ ae_matrix* xs, - ae_state *_state); -static ae_bool testdirectdensesolversunit_cmatrixchecksolutionmfast(/* Complex */ ae_matrix* xe, - ae_int_t n, - ae_int_t m, - double threshold, - ae_int_t info, - /* Complex */ ae_matrix* xs, - ae_state *_state); -static ae_bool testdirectdensesolversunit_cmatrixchecksolution(/* Complex */ ae_matrix* xe, - ae_int_t n, - double threshold, - ae_int_t info, - densesolverreport* rep, - /* Complex */ ae_vector* xs, - ae_state *_state); -static ae_bool testdirectdensesolversunit_cmatrixchecksolutionfast(/* Complex */ ae_matrix* xe, - ae_int_t n, - double threshold, - ae_int_t info, - /* Complex */ ae_vector* xs, - ae_state *_state); -static ae_bool testdirectdensesolversunit_cmatrixchecksingularm(ae_int_t n, - ae_int_t m, - ae_int_t info, - densesolverreport* rep, - /* Complex */ ae_matrix* xs, - ae_state *_state); -static ae_bool testdirectdensesolversunit_cmatrixchecksingularmfast(ae_int_t n, - ae_int_t m, - ae_int_t info, - /* Complex */ ae_matrix* xs, - ae_state *_state); -static ae_bool testdirectdensesolversunit_cmatrixchecksingular(ae_int_t n, - ae_int_t info, - densesolverreport* rep, - /* Complex */ ae_vector* xs, - ae_state *_state); -static ae_bool testdirectdensesolversunit_cmatrixchecksingularfast(ae_int_t n, - ae_int_t info, - /* Complex */ ae_vector* xs, - ae_state *_state); -static void testdirectdensesolversunit_rmatrixmakeacopy(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* b, - ae_state *_state); -static void testdirectdensesolversunit_cmatrixmakeacopy(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* b, - ae_state *_state); -static void testdirectdensesolversunit_rmatrixdrophalf(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool droplower, - ae_state *_state); -static void testdirectdensesolversunit_cmatrixdrophalf(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool droplower, - ae_state *_state); -static void testdirectdensesolversunit_testrsolver(ae_int_t maxn, - ae_int_t maxm, - ae_int_t passcount, - double threshold, - ae_bool* rerrors, - ae_bool* rfserrors, - ae_state *_state); -static void testdirectdensesolversunit_testspdsolver(ae_int_t maxn, - ae_int_t maxm, - ae_int_t passcount, - double threshold, - ae_bool* spderrors, - ae_bool* rfserrors, - ae_state *_state); -static void testdirectdensesolversunit_testcsolver(ae_int_t maxn, - ae_int_t maxm, - ae_int_t passcount, - double threshold, - ae_bool* cerrors, - ae_bool* rfserrors, - ae_state *_state); -static void testdirectdensesolversunit_testhpdsolver(ae_int_t maxn, - ae_int_t maxm, - ae_int_t passcount, - double threshold, - ae_bool* hpderrors, - ae_bool* rfserrors, - ae_state *_state); -static void testdirectdensesolversunit_unset2d(/* Real */ ae_matrix* x, - ae_state *_state); -static void testdirectdensesolversunit_unset1d(/* Real */ ae_vector* x, - ae_state *_state); -static void testdirectdensesolversunit_cunset2d(/* Complex */ ae_matrix* x, - ae_state *_state); -static void testdirectdensesolversunit_cunset1d(/* Complex */ ae_vector* x, - ae_state *_state); -static void testdirectdensesolversunit_unsetrep(densesolverreport* r, - ae_state *_state); -static void testdirectdensesolversunit_unsetlsrep(densesolverlsreport* r, - ae_state *_state); - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testdirectdensesolvers(ae_bool silent, ae_state *_state) -{ - ae_int_t maxn; - ae_int_t maxm; - ae_int_t passcount; - double threshold; - ae_bool rerrors; - ae_bool cerrors; - ae_bool spderrors; - ae_bool hpderrors; - ae_bool rfserrors; - ae_bool waserrors; - ae_bool result; - - - maxn = 10; - maxm = 5; - passcount = 5; - threshold = 10000*ae_machineepsilon; - rfserrors = ae_false; - rerrors = ae_false; - cerrors = ae_false; - spderrors = ae_false; - hpderrors = ae_false; - testdirectdensesolversunit_testrsolver(maxn, maxm, passcount, threshold, &rerrors, &rfserrors, _state); - testdirectdensesolversunit_testspdsolver(maxn, maxm, passcount, threshold, &spderrors, &rfserrors, _state); - testdirectdensesolversunit_testcsolver(maxn, maxm, passcount, threshold, &cerrors, &rfserrors, _state); - testdirectdensesolversunit_testhpdsolver(maxn, maxm, passcount, threshold, &hpderrors, &rfserrors, _state); - waserrors = (((rerrors||cerrors)||spderrors)||hpderrors)||rfserrors; - if( !silent ) - { - printf("TESTING DENSE SOLVER\n"); - printf("* REAL: "); - if( rerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* COMPLEX: "); - if( cerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* SPD: "); - if( spderrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* HPD: "); - if( hpderrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* ITERATIVE IMPROVEMENT: "); - if( rfserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - } - result = !waserrors; - return result; -} - - -/************************************************************************* -Checks whether solver results are correct solution. -Returns True on success. -*************************************************************************/ -static ae_bool testdirectdensesolversunit_rmatrixchecksolutionm(/* Real */ ae_matrix* xe, - ae_int_t n, - ae_int_t m, - double threshold, - ae_int_t info, - densesolverreport* rep, - /* Real */ ae_matrix* xs, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_bool result; - - - result = ae_true; - if( info<=0 ) - { - result = ae_false; - } - else - { - result = result&&!(ae_fp_less(rep->r1,100*ae_machineepsilon)||ae_fp_greater(rep->r1,1+1000*ae_machineepsilon)); - result = result&&!(ae_fp_less(rep->rinf,100*ae_machineepsilon)||ae_fp_greater(rep->rinf,1+1000*ae_machineepsilon)); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - result = result&&ae_fp_less_eq(ae_fabs(xe->ptr.pp_double[i][j]-xs->ptr.pp_double[i][j], _state),threshold); - } - } - } - return result; -} - - -/************************************************************************* -Checks whether solver results are correct solution. -Returns True on success. -*************************************************************************/ -static ae_bool testdirectdensesolversunit_rmatrixchecksolutionmfast(/* Real */ ae_matrix* xe, - ae_int_t n, - ae_int_t m, - double threshold, - ae_int_t info, - /* Real */ ae_matrix* xs, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_bool result; - - - result = ae_true; - if( info<=0 ) - { - result = ae_false; - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - result = result&&ae_fp_less_eq(ae_fabs(xe->ptr.pp_double[i][j]-xs->ptr.pp_double[i][j], _state),threshold); - } - } - } - return result; -} - - -/************************************************************************* -Checks whether solver results are correct solution. -Returns True on success. -*************************************************************************/ -static ae_bool testdirectdensesolversunit_rmatrixchecksolution(/* Real */ ae_matrix* xe, - ae_int_t n, - double threshold, - ae_int_t info, - densesolverreport* rep, - /* Real */ ae_vector* xs, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix xsm; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&xsm, 0, sizeof(xsm)); - ae_matrix_init(&xsm, 0, 0, DT_REAL, _state, ae_true); - - ae_matrix_set_length(&xsm, n, 1, _state); - ae_v_move(&xsm.ptr.pp_double[0][0], xsm.stride, &xs->ptr.p_double[0], 1, ae_v_len(0,n-1)); - result = testdirectdensesolversunit_rmatrixchecksolutionm(xe, n, 1, threshold, info, rep, &xsm, _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Checks whether solver results are correct solution. -Returns True on success. -*************************************************************************/ -static ae_bool testdirectdensesolversunit_rmatrixchecksolutionfast(/* Real */ ae_matrix* xe, - ae_int_t n, - double threshold, - ae_int_t info, - /* Real */ ae_vector* xs, - ae_state *_state) -{ - ae_int_t i; - ae_bool result; - - - result = ae_true; - if( info<=0 ) - { - result = ae_false; - } - else - { - for(i=0; i<=n-1; i++) - { - result = result&&ae_fp_less_eq(ae_fabs(xe->ptr.pp_double[i][0]-xs->ptr.p_double[i], _state),threshold); - } - } - return result; -} - - -/************************************************************************* -Checks whether solver results indicate singular matrix. -Returns True on success. -*************************************************************************/ -static ae_bool testdirectdensesolversunit_rmatrixchecksingularm(ae_int_t n, - ae_int_t m, - ae_int_t info, - densesolverreport* rep, - /* Real */ ae_matrix* xs, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_bool result; - - - result = ae_true; - if( info!=-3&&info!=1 ) - { - result = ae_false; - } - else - { - result = result&&!(ae_fp_less(rep->r1,(double)(0))||ae_fp_greater(rep->r1,1000*ae_machineepsilon)); - result = result&&!(ae_fp_less(rep->rinf,(double)(0))||ae_fp_greater(rep->rinf,1000*ae_machineepsilon)); - if( info==-3 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - result = result&&ae_fp_eq(xs->ptr.pp_double[i][j],(double)(0)); - } - } - } - } - return result; -} - - -/************************************************************************* -Checks whether solver results indicate singular matrix. -Returns True on success. -*************************************************************************/ -static ae_bool testdirectdensesolversunit_rmatrixchecksingularmfast(ae_int_t n, - ae_int_t m, - ae_int_t info, - /* Real */ ae_matrix* xs, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_bool result; - - - result = ae_true; - if( info!=-3 ) - { - result = ae_false; - } - else - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - result = result&&ae_fp_eq(xs->ptr.pp_double[i][j],(double)(0)); - } - } - } - return result; -} - - -/************************************************************************* -Checks whether solver results indicate singular matrix. -Returns True on success. -*************************************************************************/ -static ae_bool testdirectdensesolversunit_rmatrixchecksingular(ae_int_t n, - ae_int_t info, - densesolverreport* rep, - /* Real */ ae_vector* xs, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix xsm; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&xsm, 0, sizeof(xsm)); - ae_matrix_init(&xsm, 0, 0, DT_REAL, _state, ae_true); - - ae_matrix_set_length(&xsm, n, 1, _state); - ae_v_move(&xsm.ptr.pp_double[0][0], xsm.stride, &xs->ptr.p_double[0], 1, ae_v_len(0,n-1)); - result = testdirectdensesolversunit_rmatrixchecksingularm(n, 1, info, rep, &xsm, _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Checks whether solver results indicate singular matrix. -Returns True on success. -*************************************************************************/ -static ae_bool testdirectdensesolversunit_rmatrixchecksingularfast(ae_int_t n, - ae_int_t info, - /* Real */ ae_vector* xs, - ae_state *_state) -{ - ae_int_t i; - ae_bool result; - - - result = ae_true; - if( info!=-3 ) - { - result = ae_false; - } - else - { - for(i=0; i<=n-1; i++) - { - result = result&&ae_fp_eq(xs->ptr.p_double[i],(double)(0)); - } - } - return result; -} - - -/************************************************************************* -Checks whether solver results are correct solution. -Returns True on success. -*************************************************************************/ -static ae_bool testdirectdensesolversunit_cmatrixchecksolutionm(/* Complex */ ae_matrix* xe, - ae_int_t n, - ae_int_t m, - double threshold, - ae_int_t info, - densesolverreport* rep, - /* Complex */ ae_matrix* xs, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_bool result; - - - result = ae_true; - if( info<=0 ) - { - result = ae_false; - } - else - { - result = result&&!(ae_fp_less(rep->r1,100*ae_machineepsilon)||ae_fp_greater(rep->r1,1+1000*ae_machineepsilon)); - result = result&&!(ae_fp_less(rep->rinf,100*ae_machineepsilon)||ae_fp_greater(rep->rinf,1+1000*ae_machineepsilon)); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - result = result&&ae_fp_less_eq(ae_c_abs(ae_c_sub(xe->ptr.pp_complex[i][j],xs->ptr.pp_complex[i][j]), _state),threshold); - } - } - } - return result; -} - - -/************************************************************************* -Checks whether solver results are correct solution. -Returns True on success. -*************************************************************************/ -static ae_bool testdirectdensesolversunit_cmatrixchecksolutionmfast(/* Complex */ ae_matrix* xe, - ae_int_t n, - ae_int_t m, - double threshold, - ae_int_t info, - /* Complex */ ae_matrix* xs, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_bool result; - - - result = ae_true; - if( info<=0 ) - { - result = ae_false; - return result; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - result = result&&ae_fp_less_eq(ae_c_abs(ae_c_sub(xe->ptr.pp_complex[i][j],xs->ptr.pp_complex[i][j]), _state),threshold); - } - } - return result; -} - - -/************************************************************************* -Checks whether solver results are correct solution. -Returns True on success. -*************************************************************************/ -static ae_bool testdirectdensesolversunit_cmatrixchecksolution(/* Complex */ ae_matrix* xe, - ae_int_t n, - double threshold, - ae_int_t info, - densesolverreport* rep, - /* Complex */ ae_vector* xs, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix xsm; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&xsm, 0, sizeof(xsm)); - ae_matrix_init(&xsm, 0, 0, DT_COMPLEX, _state, ae_true); - - ae_matrix_set_length(&xsm, n, 1, _state); - ae_v_cmove(&xsm.ptr.pp_complex[0][0], xsm.stride, &xs->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1)); - result = testdirectdensesolversunit_cmatrixchecksolutionm(xe, n, 1, threshold, info, rep, &xsm, _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Checks whether solver results are correct solution. -Returns True on success. -*************************************************************************/ -static ae_bool testdirectdensesolversunit_cmatrixchecksolutionfast(/* Complex */ ae_matrix* xe, - ae_int_t n, - double threshold, - ae_int_t info, - /* Complex */ ae_vector* xs, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix xsm; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&xsm, 0, sizeof(xsm)); - ae_matrix_init(&xsm, 0, 0, DT_COMPLEX, _state, ae_true); - - ae_matrix_set_length(&xsm, n, 1, _state); - ae_v_cmove(&xsm.ptr.pp_complex[0][0], xsm.stride, &xs->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1)); - result = testdirectdensesolversunit_cmatrixchecksolutionmfast(xe, n, 1, threshold, info, &xsm, _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Checks whether solver results indicate singular matrix. -Returns True on success. -*************************************************************************/ -static ae_bool testdirectdensesolversunit_cmatrixchecksingularm(ae_int_t n, - ae_int_t m, - ae_int_t info, - densesolverreport* rep, - /* Complex */ ae_matrix* xs, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_bool result; - - - result = ae_true; - if( info!=-3&&info!=1 ) - { - result = ae_false; - return result; - } - result = result&&!(ae_fp_less(rep->r1,(double)(0))||ae_fp_greater(rep->r1,1000*ae_machineepsilon)); - result = result&&!(ae_fp_less(rep->rinf,(double)(0))||ae_fp_greater(rep->rinf,1000*ae_machineepsilon)); - if( info==-3 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - result = result&&ae_c_eq_d(xs->ptr.pp_complex[i][j],(double)(0)); - } - } - } - return result; -} - - -/************************************************************************* -Checks whether solver results indicate singular matrix. -Returns True on success. -*************************************************************************/ -static ae_bool testdirectdensesolversunit_cmatrixchecksingularmfast(ae_int_t n, - ae_int_t m, - ae_int_t info, - /* Complex */ ae_matrix* xs, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_bool result; - - - result = ae_true; - if( info!=-3 ) - { - result = ae_false; - return result; - } - if( info==-3 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - result = result&&ae_c_eq_d(xs->ptr.pp_complex[i][j],(double)(0)); - } - } - } - return result; -} - - -/************************************************************************* -Checks whether solver results indicate singular matrix. -Returns True on success. -*************************************************************************/ -static ae_bool testdirectdensesolversunit_cmatrixchecksingular(ae_int_t n, - ae_int_t info, - densesolverreport* rep, - /* Complex */ ae_vector* xs, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix xsm; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&xsm, 0, sizeof(xsm)); - ae_matrix_init(&xsm, 0, 0, DT_COMPLEX, _state, ae_true); - - ae_matrix_set_length(&xsm, n, 1, _state); - ae_v_cmove(&xsm.ptr.pp_complex[0][0], xsm.stride, &xs->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1)); - result = testdirectdensesolversunit_cmatrixchecksingularm(n, 1, info, rep, &xsm, _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Checks whether solver results indicate singular matrix. -Returns True on success. -*************************************************************************/ -static ae_bool testdirectdensesolversunit_cmatrixchecksingularfast(ae_int_t n, - ae_int_t info, - /* Complex */ ae_vector* xs, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix xsm; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&xsm, 0, sizeof(xsm)); - ae_matrix_init(&xsm, 0, 0, DT_COMPLEX, _state, ae_true); - - ae_matrix_set_length(&xsm, n, 1, _state); - ae_v_cmove(&xsm.ptr.pp_complex[0][0], xsm.stride, &xs->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1)); - result = testdirectdensesolversunit_cmatrixchecksingularmfast(n, 1, info, &xsm, _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Copy -*************************************************************************/ -static void testdirectdensesolversunit_rmatrixmakeacopy(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Real */ ae_matrix* b, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(b); - - ae_matrix_set_length(b, m-1+1, n-1+1, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - b->ptr.pp_double[i][j] = a->ptr.pp_double[i][j]; - } - } -} - - -/************************************************************************* -Copy -*************************************************************************/ -static void testdirectdensesolversunit_cmatrixmakeacopy(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Complex */ ae_matrix* b, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - ae_matrix_clear(b); - - ae_matrix_set_length(b, m-1+1, n-1+1, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - b->ptr.pp_complex[i][j] = a->ptr.pp_complex[i][j]; - } - } -} - - -/************************************************************************* -Drops upper or lower half of the matrix - fills it by special pattern -which may be used later to ensure that this part wasn't changed -*************************************************************************/ -static void testdirectdensesolversunit_rmatrixdrophalf(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool droplower, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (droplower&&i>j)||(!droplower&&iptr.pp_double[i][j] = (double)(1+2*i+3*j); - } - } - } -} - - -/************************************************************************* -Drops upper or lower half of the matrix - fills it by special pattern -which may be used later to ensure that this part wasn't changed -*************************************************************************/ -static void testdirectdensesolversunit_cmatrixdrophalf(/* Complex */ ae_matrix* a, - ae_int_t n, - ae_bool droplower, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (droplower&&i>j)||(!droplower&&iptr.pp_complex[i][j] = ae_complex_from_i(1+2*i+3*j); - } - } - } -} - - -/************************************************************************* -Real test -*************************************************************************/ -static void testdirectdensesolversunit_testrsolver(ae_int_t maxn, - ae_int_t maxm, - ae_int_t passcount, - double threshold, - ae_bool* rerrors, - ae_bool* rfserrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix lua; - ae_matrix atmp; - ae_vector p; - ae_matrix xe; - ae_matrix b; - ae_vector bv; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t n; - ae_int_t m; - ae_int_t pass; - ae_int_t taskkind; - double v; - double verr; - ae_int_t info; - densesolverreport rep; - densesolverlsreport repls; - ae_matrix x; - ae_vector xv; - ae_vector y; - ae_vector tx; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&lua, 0, sizeof(lua)); - memset(&atmp, 0, sizeof(atmp)); - memset(&p, 0, sizeof(p)); - memset(&xe, 0, sizeof(xe)); - memset(&b, 0, sizeof(b)); - memset(&bv, 0, sizeof(bv)); - memset(&rep, 0, sizeof(rep)); - memset(&repls, 0, sizeof(repls)); - memset(&x, 0, sizeof(x)); - memset(&xv, 0, sizeof(xv)); - memset(&y, 0, sizeof(y)); - memset(&tx, 0, sizeof(tx)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&lua, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&atmp, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - ae_matrix_init(&xe, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bv, 0, DT_REAL, _state, ae_true); - _densesolverreport_init(&rep, _state, ae_true); - _densesolverlsreport_init(&repls, _state, ae_true); - ae_matrix_init(&x, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xv, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tx, 0, DT_REAL, _state, ae_true); - - - /* - * General square matrices: - * * test general solvers - * * test least squares solver - */ - for(pass=1; pass<=passcount; pass++) - { - for(n=1; n<=maxn; n++) - { - for(m=1; m<=maxm; m++) - { - - /* - * ******************************************************** - * WELL CONDITIONED TASKS - * ability to find correct solution is tested - * ******************************************************** - * - * 1. generate random well conditioned matrix A. - * 2. generate random solution vector xe - * 3. generate right part b=A*xe - * 4. test different methods on original A - */ - rmatrixrndcond(n, (double)(1000), &a, _state); - testdirectdensesolversunit_rmatrixmakeacopy(&a, n, n, &lua, _state); - rmatrixlu(&lua, n, n, &p, _state); - ae_matrix_set_length(&xe, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - xe.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - ae_matrix_set_length(&b, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xe.ptr.pp_double[0][j], xe.stride, ae_v_len(0,n-1)); - b.ptr.pp_double[i][j] = v; - } - } - - /* - * Test solvers - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_unset2d(&x, _state); - rmatrixsolvem(&a, n, &b, m, ae_fp_greater(ae_randomreal(_state),0.5), &info, &rep, &x, _state); - *rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksolutionm(&xe, n, m, threshold, info, &rep, &x, _state); - info = 0; - ae_matrix_set_length(&x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_double[i][j] = b.ptr.pp_double[i][j]; - } - } - rmatrixsolvemfast(&a, n, &x, m, &info, _state); - *rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksolutionmfast(&xe, n, m, threshold, info, &x, _state); - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_unset1d(&xv, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - rmatrixsolve(&a, n, &bv, &info, &rep, &xv, _state); - *rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksolution(&xe, n, threshold, info, &rep, &xv, _state); - info = 0; - ae_vector_set_length(&bv, n, _state); - ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - rmatrixsolvefast(&a, n, &bv, &info, _state); - *rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksolutionfast(&xe, n, threshold, info, &bv, _state); - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_unset2d(&x, _state); - rmatrixlusolvem(&lua, &p, n, &b, m, &info, &rep, &x, _state); - *rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksolutionm(&xe, n, m, threshold, info, &rep, &x, _state); - info = 0; - ae_matrix_set_length(&x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_double[i][j] = b.ptr.pp_double[i][j]; - } - } - rmatrixlusolvemfast(&lua, &p, n, &x, m, &info, _state); - ae_set_error_flag(rerrors, !testdirectdensesolversunit_rmatrixchecksolutionmfast(&xe, n, m, threshold, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:552"); - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_unset1d(&xv, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - rmatrixlusolve(&lua, &p, n, &bv, &info, &rep, &xv, _state); - *rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksolution(&xe, n, threshold, info, &rep, &xv, _state); - info = 0; - ae_vector_set_length(&bv, n, _state); - ae_v_move(&xv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - rmatrixlusolvefast(&lua, &p, n, &xv, &info, _state); - ae_set_error_flag(rerrors, !testdirectdensesolversunit_rmatrixchecksolutionfast(&xe, n, threshold, info, &xv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:566"); - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_unset2d(&x, _state); - rmatrixmixedsolvem(&a, &lua, &p, n, &b, m, &info, &rep, &x, _state); - *rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksolutionm(&xe, n, m, threshold, info, &rep, &x, _state); - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_unset1d(&xv, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - rmatrixmixedsolve(&a, &lua, &p, n, &bv, &info, &rep, &xv, _state); - *rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksolution(&xe, n, threshold, info, &rep, &xv, _state); - - /* - * Test DenseSolverRLS(): - * * test on original system A*x = b - * * test on overdetermined system with the same solution: (A' A')'*x = (b' b')' - * * test on underdetermined system with the same solution: (A 0 0 0 ) * z = b - */ - info = 0; - testdirectdensesolversunit_unsetlsrep(&repls, _state); - testdirectdensesolversunit_unset1d(&xv, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - rmatrixsolvels(&a, n, n, &bv, 0.0, &info, &repls, &xv, _state); - if( info<=0 ) - { - *rerrors = ae_true; - } - else - { - *rerrors = (*rerrors||ae_fp_less(repls.r2,100*ae_machineepsilon))||ae_fp_greater(repls.r2,1+1000*ae_machineepsilon); - *rerrors = (*rerrors||repls.n!=n)||repls.k!=0; - for(i=0; i<=n-1; i++) - { - *rerrors = *rerrors||ae_fp_greater(ae_fabs(xe.ptr.pp_double[i][0]-xv.ptr.p_double[i], _state),threshold); - } - } - info = 0; - testdirectdensesolversunit_unsetlsrep(&repls, _state); - testdirectdensesolversunit_unset1d(&xv, _state); - ae_vector_set_length(&bv, 2*n, _state); - ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - ae_v_move(&bv.ptr.p_double[n], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(n,2*n-1)); - ae_matrix_set_length(&atmp, 2*n, n, _state); - copymatrix(&a, 0, n-1, 0, n-1, &atmp, 0, n-1, 0, n-1, _state); - copymatrix(&a, 0, n-1, 0, n-1, &atmp, n, 2*n-1, 0, n-1, _state); - rmatrixsolvels(&atmp, 2*n, n, &bv, 0.0, &info, &repls, &xv, _state); - if( info<=0 ) - { - *rerrors = ae_true; - } - else - { - *rerrors = (*rerrors||ae_fp_less(repls.r2,100*ae_machineepsilon))||ae_fp_greater(repls.r2,1+1000*ae_machineepsilon); - *rerrors = (*rerrors||repls.n!=n)||repls.k!=0; - for(i=0; i<=n-1; i++) - { - *rerrors = *rerrors||ae_fp_greater(ae_fabs(xe.ptr.pp_double[i][0]-xv.ptr.p_double[i], _state),threshold); - } - } - info = 0; - testdirectdensesolversunit_unsetlsrep(&repls, _state); - testdirectdensesolversunit_unset1d(&xv, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - ae_matrix_set_length(&atmp, n, 2*n, _state); - copymatrix(&a, 0, n-1, 0, n-1, &atmp, 0, n-1, 0, n-1, _state); - for(i=0; i<=n-1; i++) - { - for(j=n; j<=2*n-1; j++) - { - atmp.ptr.pp_double[i][j] = (double)(0); - } - } - rmatrixsolvels(&atmp, n, 2*n, &bv, 0.0, &info, &repls, &xv, _state); - if( info<=0 ) - { - *rerrors = ae_true; - } - else - { - *rerrors = *rerrors||ae_fp_neq(repls.r2,(double)(0)); - *rerrors = (*rerrors||repls.n!=2*n)||repls.k!=n; - for(i=0; i<=n-1; i++) - { - *rerrors = *rerrors||ae_fp_greater(ae_fabs(xe.ptr.pp_double[i][0]-xv.ptr.p_double[i], _state),threshold); - } - for(i=n; i<=2*n-1; i++) - { - *rerrors = *rerrors||ae_fp_greater(ae_fabs(xv.ptr.p_double[i], _state),threshold); - } - } - - /* - * ******************************************************** - * EXACTLY SINGULAR MATRICES - * ability to detect singularity is tested - * ******************************************************** - * - * 1. generate different types of singular matrices: - * * zero (TaskKind=0) - * * with zero columns (TaskKind=1) - * * with zero rows (TaskKind=2) - * * with equal rows/columns (TaskKind=2 or 3) - * 2. generate random solution vector xe - * 3. generate right part b=A*xe - * 4. test different methods - */ - for(taskkind=0; taskkind<=4; taskkind++) - { - testdirectdensesolversunit_unset2d(&a, _state); - if( taskkind==0 ) - { - - /* - * all zeros - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - } - if( taskkind==1 ) - { - - /* - * there is zero column - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - k = ae_randominteger(n, _state); - ae_v_muld(&a.ptr.pp_double[0][k], a.stride, ae_v_len(0,n-1), 0); - } - if( taskkind==2 ) - { - - /* - * there is zero row - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - k = ae_randominteger(n, _state); - ae_v_muld(&a.ptr.pp_double[k][0], 1, ae_v_len(0,n-1), 0); - } - if( taskkind==3 ) - { - - /* - * equal columns - */ - if( n<2 ) - { - continue; - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - k = 1+ae_randominteger(n-1, _state); - ae_v_move(&a.ptr.pp_double[0][0], a.stride, &a.ptr.pp_double[0][k], a.stride, ae_v_len(0,n-1)); - } - if( taskkind==4 ) - { - - /* - * equal rows - */ - if( n<2 ) - { - continue; - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - k = 1+ae_randominteger(n-1, _state); - ae_v_move(&a.ptr.pp_double[0][0], 1, &a.ptr.pp_double[k][0], 1, ae_v_len(0,n-1)); - } - ae_matrix_set_length(&xe, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - xe.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - ae_matrix_set_length(&b, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xe.ptr.pp_double[0][j], xe.stride, ae_v_len(0,n-1)); - b.ptr.pp_double[i][j] = v; - } - } - testdirectdensesolversunit_rmatrixmakeacopy(&a, n, n, &lua, _state); - rmatrixlu(&lua, n, n, &p, _state); - - /* - * Test RMatrixSolveM() - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_unset2d(&x, _state); - rmatrixsolvem(&a, n, &b, m, ae_fp_greater(ae_randomreal(_state),0.5), &info, &rep, &x, _state); - *rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksingularm(n, m, info, &rep, &x, _state); - - /* - * Test RMatrixSolveMFast(); performed only for matrices - * with zero rows or columns - */ - if( (taskkind==0||taskkind==1)||taskkind==2 ) - { - info = 0; - ae_matrix_set_length(&x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_double[i][j] = b.ptr.pp_double[i][j]; - } - } - rmatrixsolvemfast(&a, n, &x, m, &info, _state); - *rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksingularmfast(n, m, info, &x, _state); - } - - /* - * Test RMatrixSolve() - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_unset2d(&x, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - rmatrixsolve(&a, n, &bv, &info, &rep, &xv, _state); - *rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksingular(n, info, &rep, &xv, _state); - - /* - * Test RMatrixSolveFast(); performed only for matrices - * with zero rows or columns - */ - if( (taskkind==0||taskkind==1)||taskkind==2 ) - { - info = 0; - ae_vector_set_length(&bv, n, _state); - ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - rmatrixsolvefast(&a, n, &bv, &info, _state); - ae_set_error_flag(rerrors, !testdirectdensesolversunit_rmatrixchecksingularfast(n, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:784"); - } - - /* - * Test RMatrixLUSolveM() - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_unset2d(&x, _state); - rmatrixlusolvem(&lua, &p, n, &b, m, &info, &rep, &x, _state); - *rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksingularm(n, m, info, &rep, &x, _state); - - /* - * Test RMatrixLUSolveMFast(); performed only for matrices - * with zero rows or columns - */ - if( (taskkind==0||taskkind==1)||taskkind==2 ) - { - info = 0; - ae_matrix_set_length(&x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_double[i][j] = b.ptr.pp_double[i][j]; - } - } - rmatrixlusolvemfast(&lua, &p, n, &x, m, &info, _state); - ae_set_error_flag(rerrors, !testdirectdensesolversunit_rmatrixchecksingularmfast(n, m, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:808"); - } - - /* - * Test RMatrixLUSolve() - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_unset2d(&x, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - rmatrixlusolve(&lua, &p, n, &bv, &info, &rep, &xv, _state); - *rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksingular(n, info, &rep, &xv, _state); - - /* - * Test RMatrixLUSolveFast(); performed only for matrices - * with zero rows or columns - */ - if( (taskkind==0||taskkind==1)||taskkind==2 ) - { - info = 0; - ae_vector_set_length(&bv, n, _state); - ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - rmatrixlusolvefast(&lua, &p, n, &bv, &info, _state); - ae_set_error_flag(rerrors, !testdirectdensesolversunit_rmatrixchecksingularfast(n, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:832"); - } - - /* - * Test RMatrixMixedSolveM() - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_unset2d(&x, _state); - rmatrixmixedsolvem(&a, &lua, &p, n, &b, m, &info, &rep, &x, _state); - *rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksingularm(n, m, info, &rep, &x, _state); - - /* - * Test RMatrixMixedSolve() - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_unset2d(&x, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - rmatrixmixedsolve(&a, &lua, &p, n, &bv, &info, &rep, &xv, _state); - *rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksingular(n, info, &rep, &xv, _state); - } - } - } - } - - /* - * test iterative improvement - */ - for(pass=1; pass<=passcount; pass++) - { - - /* - * Test iterative improvement matrices - * - * A matrix/right part are constructed such that both matrix - * and solution components are within (-1,+1). Such matrix/right part - * have nice properties - system can be solved using iterative - * improvement with |A*x-b| about several ulps of max(1,|b|). - */ - n = 100; - ae_matrix_set_length(&a, n, n, _state); - ae_matrix_set_length(&b, n, 1, _state); - ae_vector_set_length(&bv, n, _state); - ae_vector_set_length(&tx, n, _state); - ae_vector_set_length(&xv, n, _state); - ae_vector_set_length(&y, n, _state); - for(i=0; i<=n-1; i++) - { - xv.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - ae_v_move(&y.ptr.p_double[0], 1, &a.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - xdot(&y, &xv, n, &tx, &v, &verr, _state); - bv.ptr.p_double[i] = v; - } - ae_v_move(&b.ptr.pp_double[0][0], b.stride, &bv.ptr.p_double[0], 1, ae_v_len(0,n-1)); - - /* - * Test RMatrixSolveM() - */ - testdirectdensesolversunit_unset2d(&x, _state); - rmatrixsolvem(&a, n, &b, 1, ae_true, &info, &rep, &x, _state); - if( info<=0 ) - { - *rfserrors = ae_true; - } - else - { - ae_vector_set_length(&xv, n, _state); - ae_v_move(&xv.ptr.p_double[0], 1, &x.ptr.pp_double[0][0], x.stride, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - ae_v_move(&y.ptr.p_double[0], 1, &a.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - xdot(&y, &xv, n, &tx, &v, &verr, _state); - *rfserrors = *rfserrors||ae_fp_greater(ae_fabs(v-b.ptr.pp_double[i][0], _state),8*ae_machineepsilon*ae_maxreal((double)(1), ae_fabs(b.ptr.pp_double[i][0], _state), _state)); - } - } - - /* - * Test RMatrixSolve() - */ - testdirectdensesolversunit_unset1d(&xv, _state); - rmatrixsolve(&a, n, &bv, &info, &rep, &xv, _state); - if( info<=0 ) - { - *rfserrors = ae_true; - } - else - { - for(i=0; i<=n-1; i++) - { - ae_v_move(&y.ptr.p_double[0], 1, &a.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - xdot(&y, &xv, n, &tx, &v, &verr, _state); - *rfserrors = *rfserrors||ae_fp_greater(ae_fabs(v-bv.ptr.p_double[i], _state),8*ae_machineepsilon*ae_maxreal((double)(1), ae_fabs(bv.ptr.p_double[i], _state), _state)); - } - } - - /* - * Test LS-solver on the same matrix - */ - rmatrixsolvels(&a, n, n, &bv, 0.0, &info, &repls, &xv, _state); - if( info<=0 ) - { - *rfserrors = ae_true; - } - else - { - for(i=0; i<=n-1; i++) - { - ae_v_move(&y.ptr.p_double[0], 1, &a.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - xdot(&y, &xv, n, &tx, &v, &verr, _state); - *rfserrors = *rfserrors||ae_fp_greater(ae_fabs(v-bv.ptr.p_double[i], _state),8*ae_machineepsilon*ae_maxreal((double)(1), ae_fabs(bv.ptr.p_double[i], _state), _state)); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -SPD test -*************************************************************************/ -static void testdirectdensesolversunit_testspdsolver(ae_int_t maxn, - ae_int_t maxm, - ae_int_t passcount, - double threshold, - ae_bool* spderrors, - ae_bool* rfserrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix cha; - ae_matrix atmp; - ae_vector p; - ae_matrix xe; - ae_matrix b; - ae_vector bv; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t n; - ae_int_t m; - ae_int_t pass; - ae_int_t taskkind; - double v; - ae_bool isupper; - ae_int_t info; - densesolverreport rep; - densesolverlsreport repls; - ae_matrix x; - ae_vector xv; - ae_vector y; - ae_vector tx; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&cha, 0, sizeof(cha)); - memset(&atmp, 0, sizeof(atmp)); - memset(&p, 0, sizeof(p)); - memset(&xe, 0, sizeof(xe)); - memset(&b, 0, sizeof(b)); - memset(&bv, 0, sizeof(bv)); - memset(&rep, 0, sizeof(rep)); - memset(&repls, 0, sizeof(repls)); - memset(&x, 0, sizeof(x)); - memset(&xv, 0, sizeof(xv)); - memset(&y, 0, sizeof(y)); - memset(&tx, 0, sizeof(tx)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&cha, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&atmp, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - ae_matrix_init(&xe, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bv, 0, DT_REAL, _state, ae_true); - _densesolverreport_init(&rep, _state, ae_true); - _densesolverlsreport_init(&repls, _state, ae_true); - ae_matrix_init(&x, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xv, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tx, 0, DT_REAL, _state, ae_true); - - - /* - * General square matrices: - * * test general solvers - * * test least squares solver - */ - for(pass=1; pass<=passcount; pass++) - { - for(n=1; n<=maxn; n++) - { - for(m=1; m<=maxm; m++) - { - - /* - * ******************************************************** - * WELL CONDITIONED TASKS - * ability to find correct solution is tested - * ******************************************************** - * - * 1. generate random well conditioned matrix A. - * 2. generate random solution vector xe - * 3. generate right part b=A*xe - * 4. test different methods on original A - */ - isupper = ae_fp_greater(ae_randomreal(_state),0.5); - spdmatrixrndcond(n, (double)(1000), &a, _state); - testdirectdensesolversunit_rmatrixmakeacopy(&a, n, n, &cha, _state); - if( !spdmatrixcholesky(&cha, n, isupper, _state) ) - { - *spderrors = ae_true; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&xe, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - xe.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - ae_matrix_set_length(&b, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xe.ptr.pp_double[0][j], xe.stride, ae_v_len(0,n-1)); - b.ptr.pp_double[i][j] = v; - } - } - testdirectdensesolversunit_rmatrixdrophalf(&a, n, isupper, _state); - testdirectdensesolversunit_rmatrixdrophalf(&cha, n, isupper, _state); - - /* - * Test solvers - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_unset2d(&x, _state); - spdmatrixsolvem(&a, n, isupper, &b, m, &info, &rep, &x, _state); - *spderrors = *spderrors||!testdirectdensesolversunit_rmatrixchecksolutionm(&xe, n, m, threshold, info, &rep, &x, _state); - info = 0; - ae_matrix_set_length(&x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_double[i][j] = b.ptr.pp_double[i][j]; - } - } - spdmatrixsolvemfast(&a, n, isupper, &x, m, &info, _state); - ae_set_error_flag(spderrors, !testdirectdensesolversunit_rmatrixchecksolutionmfast(&xe, n, m, threshold, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1023"); - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_unset1d(&xv, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - spdmatrixsolve(&a, n, isupper, &bv, &info, &rep, &xv, _state); - *spderrors = *spderrors||!testdirectdensesolversunit_rmatrixchecksolution(&xe, n, threshold, info, &rep, &xv, _state); - info = 0; - ae_vector_set_length(&bv, n, _state); - ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - spdmatrixsolvefast(&a, n, isupper, &bv, &info, _state); - ae_set_error_flag(spderrors, !testdirectdensesolversunit_rmatrixchecksolutionfast(&xe, n, threshold, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1037"); - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_unset2d(&x, _state); - spdmatrixcholeskysolvem(&cha, n, isupper, &b, m, &info, &rep, &x, _state); - *spderrors = *spderrors||!testdirectdensesolversunit_rmatrixchecksolutionm(&xe, n, m, threshold, info, &rep, &x, _state); - info = 0; - ae_matrix_set_length(&x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_double[i][j] = b.ptr.pp_double[i][j]; - } - } - spdmatrixcholeskysolvemfast(&cha, n, isupper, &x, m, &info, _state); - ae_set_error_flag(spderrors, !testdirectdensesolversunit_rmatrixchecksolutionmfast(&xe, n, m, threshold, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1051"); - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_unset1d(&xv, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - spdmatrixcholeskysolve(&cha, n, isupper, &bv, &info, &rep, &xv, _state); - *spderrors = *spderrors||!testdirectdensesolversunit_rmatrixchecksolution(&xe, n, threshold, info, &rep, &xv, _state); - info = 0; - ae_vector_set_length(&bv, n, _state); - ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - spdmatrixcholeskysolvefast(&cha, n, isupper, &bv, &info, _state); - ae_set_error_flag(spderrors, !testdirectdensesolversunit_rmatrixchecksolutionfast(&xe, n, threshold, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1065"); - - /* - * ******************************************************** - * EXACTLY SINGULAR MATRICES - * ability to detect singularity is tested - * ******************************************************** - * - * 1. generate different types of singular matrices: - * * zero - * * with zero columns - * * with zero rows - * * with equal rows/columns - * 2. generate random solution vector xe - * 3. generate right part b=A*xe - * 4. test different methods - */ - for(taskkind=0; taskkind<=3; taskkind++) - { - testdirectdensesolversunit_unset2d(&a, _state); - if( taskkind==0 ) - { - - /* - * all zeros - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - } - if( taskkind==1 ) - { - - /* - * there is zero column - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j]; - } - } - k = ae_randominteger(n, _state); - ae_v_muld(&a.ptr.pp_double[0][k], a.stride, ae_v_len(0,n-1), 0); - ae_v_muld(&a.ptr.pp_double[k][0], 1, ae_v_len(0,n-1), 0); - } - if( taskkind==2 ) - { - - /* - * there is zero row - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j]; - } - } - k = ae_randominteger(n, _state); - ae_v_muld(&a.ptr.pp_double[k][0], 1, ae_v_len(0,n-1), 0); - ae_v_muld(&a.ptr.pp_double[0][k], a.stride, ae_v_len(0,n-1), 0); - } - if( taskkind==3 ) - { - - /* - * equal columns/rows - */ - if( n<2 ) - { - continue; - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j]; - } - } - k = 1+ae_randominteger(n-1, _state); - ae_v_move(&a.ptr.pp_double[0][0], a.stride, &a.ptr.pp_double[0][k], a.stride, ae_v_len(0,n-1)); - ae_v_move(&a.ptr.pp_double[0][0], 1, &a.ptr.pp_double[k][0], 1, ae_v_len(0,n-1)); - } - ae_matrix_set_length(&xe, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - xe.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - ae_matrix_set_length(&b, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xe.ptr.pp_double[0][j], xe.stride, ae_v_len(0,n-1)); - b.ptr.pp_double[i][j] = v; - } - } - testdirectdensesolversunit_rmatrixmakeacopy(&a, n, n, &cha, _state); - testdirectdensesolversunit_rmatrixdrophalf(&a, n, isupper, _state); - testdirectdensesolversunit_rmatrixdrophalf(&cha, n, isupper, _state); - - /* - * Test SPDMatrixSolveM() - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_unset2d(&x, _state); - spdmatrixsolvem(&a, n, isupper, &b, m, &info, &rep, &x, _state); - *spderrors = *spderrors||!testdirectdensesolversunit_rmatrixchecksingularm(n, m, info, &rep, &x, _state); - - /* - * Test SPDMatrixSolveMFast() - */ - if( (taskkind==0||taskkind==1)||taskkind==2 ) - { - info = 0; - ae_matrix_set_length(&x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_double[i][j] = b.ptr.pp_double[i][j]; - } - } - spdmatrixsolvemfast(&a, n, isupper, &x, m, &info, _state); - ae_set_error_flag(spderrors, !testdirectdensesolversunit_rmatrixchecksingularmfast(n, m, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1181"); - } - - /* - * Test SPDMatrixSolve() - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_unset2d(&x, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - spdmatrixsolve(&a, n, isupper, &bv, &info, &rep, &xv, _state); - *spderrors = *spderrors||!testdirectdensesolversunit_rmatrixchecksingular(n, info, &rep, &xv, _state); - - /* - * Test SPDMatrixSolveFast() - */ - info = 0; - ae_vector_set_length(&bv, n, _state); - ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - spdmatrixsolvefast(&a, n, isupper, &bv, &info, _state); - ae_set_error_flag(spderrors, !testdirectdensesolversunit_rmatrixchecksingular(n, info, &rep, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1202"); - - /* - * 'equal columns/rows' are degenerate, but - * Cholesky matrix with equal columns/rows IS NOT degenerate, - * so it is not used for testing purposes. - */ - if( taskkind!=3 ) - { - - /* - * Test SPDMatrixLUSolveM() (and fast version) - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_unset2d(&x, _state); - spdmatrixcholeskysolvem(&cha, n, isupper, &b, m, &info, &rep, &x, _state); - *spderrors = *spderrors||!testdirectdensesolversunit_rmatrixchecksingularm(n, m, info, &rep, &x, _state); - if( (taskkind==0||taskkind==1)||taskkind==2 ) - { - info = 0; - ae_matrix_set_length(&x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_double[i][j] = b.ptr.pp_double[i][j]; - } - } - spdmatrixcholeskysolvemfast(&a, n, isupper, &x, m, &info, _state); - ae_set_error_flag(spderrors, !testdirectdensesolversunit_rmatrixchecksingularmfast(n, m, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1227"); - } - - /* - * Test SPDMatrixLUSolve() - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_unset2d(&x, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - spdmatrixcholeskysolve(&cha, n, isupper, &bv, &info, &rep, &xv, _state); - *spderrors = *spderrors||!testdirectdensesolversunit_rmatrixchecksingular(n, info, &rep, &xv, _state); - if( (taskkind==0||taskkind==1)||taskkind==2 ) - { - info = 0; - ae_vector_set_length(&bv, n, _state); - ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1)); - spdmatrixcholeskysolvefast(&a, n, isupper, &bv, &info, _state); - ae_set_error_flag(spderrors, !testdirectdensesolversunit_rmatrixchecksingularfast(n, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1246"); - } - } - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Real test -*************************************************************************/ -static void testdirectdensesolversunit_testcsolver(ae_int_t maxn, - ae_int_t maxm, - ae_int_t passcount, - double threshold, - ae_bool* cerrors, - ae_bool* rfserrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix lua; - ae_matrix atmp; - ae_vector p; - ae_matrix xe; - ae_matrix b; - ae_vector bv; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t n; - ae_int_t m; - ae_int_t pass; - ae_int_t taskkind; - double verr; - ae_complex v; - ae_int_t info; - densesolverreport rep; - densesolverlsreport repls; - ae_matrix x; - ae_vector xv; - ae_vector y; - ae_vector tx; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&lua, 0, sizeof(lua)); - memset(&atmp, 0, sizeof(atmp)); - memset(&p, 0, sizeof(p)); - memset(&xe, 0, sizeof(xe)); - memset(&b, 0, sizeof(b)); - memset(&bv, 0, sizeof(bv)); - memset(&rep, 0, sizeof(rep)); - memset(&repls, 0, sizeof(repls)); - memset(&x, 0, sizeof(x)); - memset(&xv, 0, sizeof(xv)); - memset(&y, 0, sizeof(y)); - memset(&tx, 0, sizeof(tx)); - ae_matrix_init(&a, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&lua, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&atmp, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - ae_matrix_init(&xe, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&b, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&bv, 0, DT_COMPLEX, _state, ae_true); - _densesolverreport_init(&rep, _state, ae_true); - _densesolverlsreport_init(&repls, _state, ae_true); - ae_matrix_init(&x, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&xv, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&y, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&tx, 0, DT_REAL, _state, ae_true); - - - /* - * General square matrices: - * * test general solvers - * * test least squares solver - */ - for(pass=1; pass<=passcount; pass++) - { - for(n=1; n<=maxn; n++) - { - for(m=1; m<=maxm; m++) - { - - /* - * ******************************************************** - * WELL CONDITIONED TASKS - * ability to find correct solution is tested - * ******************************************************** - * - * 1. generate random well conditioned matrix A. - * 2. generate random solution vector xe - * 3. generate right part b=A*xe - * 4. test different methods on original A - */ - cmatrixrndcond(n, (double)(1000), &a, _state); - testdirectdensesolversunit_cmatrixmakeacopy(&a, n, n, &lua, _state); - cmatrixlu(&lua, n, n, &p, _state); - ae_matrix_set_length(&xe, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - xe.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - xe.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - ae_matrix_set_length(&b, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - v = ae_v_cdotproduct(&a.ptr.pp_complex[i][0], 1, "N", &xe.ptr.pp_complex[0][j], xe.stride, "N", ae_v_len(0,n-1)); - b.ptr.pp_complex[i][j] = v; - } - } - - /* - * Test solvers - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_cunset2d(&x, _state); - cmatrixsolvem(&a, n, &b, m, ae_fp_greater(ae_randomreal(_state),0.5), &info, &rep, &x, _state); - *cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksolutionm(&xe, n, m, threshold, info, &rep, &x, _state); - info = 0; - ae_matrix_set_length(&x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_complex[i][j] = b.ptr.pp_complex[i][j]; - } - } - cmatrixsolvemfast(&a, n, &x, m, &info, _state); - *cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksolutionmfast(&xe, n, m, threshold, info, &x, _state); - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_cunset1d(&xv, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1)); - cmatrixsolve(&a, n, &bv, &info, &rep, &xv, _state); - *cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksolution(&xe, n, threshold, info, &rep, &xv, _state); - info = 0; - ae_vector_set_length(&bv, n, _state); - ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1)); - cmatrixsolvefast(&a, n, &bv, &info, _state); - *cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksolutionfast(&xe, n, threshold, info, &bv, _state); - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_cunset2d(&x, _state); - cmatrixlusolvem(&lua, &p, n, &b, m, &info, &rep, &x, _state); - *cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksolutionm(&xe, n, m, threshold, info, &rep, &x, _state); - info = 0; - ae_matrix_set_length(&x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_complex[i][j] = b.ptr.pp_complex[i][j]; - } - } - cmatrixlusolvemfast(&lua, &p, n, &x, m, &info, _state); - ae_set_error_flag(cerrors, !testdirectdensesolversunit_cmatrixchecksolutionmfast(&xe, n, m, threshold, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1358"); - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_cunset1d(&xv, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1)); - cmatrixlusolve(&lua, &p, n, &bv, &info, &rep, &xv, _state); - *cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksolution(&xe, n, threshold, info, &rep, &xv, _state); - info = 0; - ae_vector_set_length(&bv, n, _state); - ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1)); - cmatrixlusolvefast(&lua, &p, n, &bv, &info, _state); - ae_set_error_flag(cerrors, !testdirectdensesolversunit_cmatrixchecksolutionfast(&xe, n, threshold, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1372"); - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_cunset2d(&x, _state); - cmatrixmixedsolvem(&a, &lua, &p, n, &b, m, &info, &rep, &x, _state); - *cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksolutionm(&xe, n, m, threshold, info, &rep, &x, _state); - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_cunset1d(&xv, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1)); - cmatrixmixedsolve(&a, &lua, &p, n, &bv, &info, &rep, &xv, _state); - *cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksolution(&xe, n, threshold, info, &rep, &xv, _state); - - /* - * ******************************************************** - * EXACTLY SINGULAR MATRICES - * ability to detect singularity is tested - * ******************************************************** - * - * 1. generate different types of singular matrices: - * * zero - * * with zero columns - * * with zero rows - * * with equal rows/columns - * 2. generate random solution vector xe - * 3. generate right part b=A*xe - * 4. test different methods - */ - for(taskkind=0; taskkind<=4; taskkind++) - { - testdirectdensesolversunit_cunset2d(&a, _state); - if( taskkind==0 ) - { - - /* - * all zeros - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - } - if( taskkind==1 ) - { - - /* - * there is zero column - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - k = ae_randominteger(n, _state); - ae_v_cmuld(&a.ptr.pp_complex[0][k], a.stride, ae_v_len(0,n-1), 0); - } - if( taskkind==2 ) - { - - /* - * there is zero row - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - k = ae_randominteger(n, _state); - ae_v_cmuld(&a.ptr.pp_complex[k][0], 1, ae_v_len(0,n-1), 0); - } - if( taskkind==3 ) - { - - /* - * equal columns - */ - if( n<2 ) - { - continue; - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - k = 1+ae_randominteger(n-1, _state); - ae_v_cmove(&a.ptr.pp_complex[0][0], a.stride, &a.ptr.pp_complex[0][k], a.stride, "N", ae_v_len(0,n-1)); - } - if( taskkind==4 ) - { - - /* - * equal rows - */ - if( n<2 ) - { - continue; - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - k = 1+ae_randominteger(n-1, _state); - ae_v_cmove(&a.ptr.pp_complex[0][0], 1, &a.ptr.pp_complex[k][0], 1, "N", ae_v_len(0,n-1)); - } - ae_matrix_set_length(&xe, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - xe.ptr.pp_complex[i][j] = ae_complex_from_d(2*ae_randomreal(_state)-1); - } - } - ae_matrix_set_length(&b, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - v = ae_v_cdotproduct(&a.ptr.pp_complex[i][0], 1, "N", &xe.ptr.pp_complex[0][j], xe.stride, "N", ae_v_len(0,n-1)); - b.ptr.pp_complex[i][j] = v; - } - } - testdirectdensesolversunit_cmatrixmakeacopy(&a, n, n, &lua, _state); - cmatrixlu(&lua, n, n, &p, _state); - - /* - * Test CMatrixSolveM() - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_cunset2d(&x, _state); - cmatrixsolvem(&a, n, &b, m, ae_fp_greater(ae_randomreal(_state),0.5), &info, &rep, &x, _state); - *cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksingularm(n, m, info, &rep, &x, _state); - - /* - * Test CMatrixSolveMFast(); performed only for matrices - * with zero rows or columns - */ - if( (taskkind==0||taskkind==1)||taskkind==2 ) - { - info = 0; - ae_matrix_set_length(&x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_complex[i][j] = b.ptr.pp_complex[i][j]; - } - } - cmatrixsolvemfast(&a, n, &x, m, &info, _state); - ae_set_error_flag(cerrors, !testdirectdensesolversunit_cmatrixchecksingularmfast(n, m, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1515"); - } - - /* - * Test CMatrixSolve() - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_cunset2d(&x, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1)); - cmatrixsolve(&a, n, &bv, &info, &rep, &xv, _state); - *cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksingular(n, info, &rep, &xv, _state); - if( (taskkind==0||taskkind==1)||taskkind==2 ) - { - info = 0; - ae_vector_set_length(&bv, n, _state); - ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1)); - cmatrixsolvefast(&a, n, &bv, &info, _state); - ae_set_error_flag(cerrors, !testdirectdensesolversunit_cmatrixchecksingularfast(n, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1535"); - } - - /* - * Test CMatrixLUSolveM() - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_cunset2d(&x, _state); - cmatrixlusolvem(&lua, &p, n, &b, m, &info, &rep, &x, _state); - *cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksingularm(n, m, info, &rep, &x, _state); - - /* - * Test CMatrixLUSolveMFast() - */ - if( (taskkind==0||taskkind==1)||taskkind==2 ) - { - info = 0; - ae_matrix_set_length(&x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_complex[i][j] = b.ptr.pp_complex[i][j]; - } - } - cmatrixlusolvemfast(&lua, &p, n, &x, m, &info, _state); - ae_set_error_flag(cerrors, !testdirectdensesolversunit_cmatrixchecksingularmfast(n, m, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1559"); - } - - /* - * Test CMatrixLUSolve() - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_cunset2d(&x, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1)); - cmatrixlusolve(&lua, &p, n, &bv, &info, &rep, &xv, _state); - *cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksingular(n, info, &rep, &xv, _state); - - /* - * Test CMatrixLUSolveFast() - */ - if( (taskkind==0||taskkind==1)||taskkind==2 ) - { - info = 0; - ae_vector_set_length(&bv, n, _state); - ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1)); - cmatrixlusolvefast(&lua, &p, n, &bv, &info, _state); - ae_set_error_flag(cerrors, !testdirectdensesolversunit_cmatrixchecksingularfast(n, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1582"); - } - - /* - * Test CMatrixMixedSolveM() - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_cunset2d(&x, _state); - cmatrixmixedsolvem(&a, &lua, &p, n, &b, m, &info, &rep, &x, _state); - *cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksingularm(n, m, info, &rep, &x, _state); - - /* - * Test CMatrixMixedSolve() - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_cunset2d(&x, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1)); - cmatrixmixedsolve(&a, &lua, &p, n, &bv, &info, &rep, &xv, _state); - *cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksingular(n, info, &rep, &xv, _state); - } - } - } - } - - /* - * test iterative improvement - */ - for(pass=1; pass<=passcount; pass++) - { - - /* - * Test iterative improvement matrices - * - * A matrix/right part are constructed such that both matrix - * and solution components magnitudes are within (-1,+1). - * Such matrix/right part have nice properties - system can - * be solved using iterative improvement with |A*x-b| about - * several ulps of max(1,|b|). - */ - n = 100; - ae_matrix_set_length(&a, n, n, _state); - ae_matrix_set_length(&b, n, 1, _state); - ae_vector_set_length(&bv, n, _state); - ae_vector_set_length(&tx, 2*n, _state); - ae_vector_set_length(&xv, n, _state); - ae_vector_set_length(&y, n, _state); - for(i=0; i<=n-1; i++) - { - xv.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1; - xv.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - ae_v_cmove(&y.ptr.p_complex[0], 1, &a.ptr.pp_complex[i][0], 1, "N", ae_v_len(0,n-1)); - xcdot(&y, &xv, n, &tx, &v, &verr, _state); - bv.ptr.p_complex[i] = v; - } - ae_v_cmove(&b.ptr.pp_complex[0][0], b.stride, &bv.ptr.p_complex[0], 1, "N", ae_v_len(0,n-1)); - - /* - * Test CMatrixSolveM() - */ - testdirectdensesolversunit_cunset2d(&x, _state); - cmatrixsolvem(&a, n, &b, 1, ae_true, &info, &rep, &x, _state); - if( info<=0 ) - { - *rfserrors = ae_true; - } - else - { - ae_vector_set_length(&xv, n, _state); - ae_v_cmove(&xv.ptr.p_complex[0], 1, &x.ptr.pp_complex[0][0], x.stride, "N", ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - ae_v_cmove(&y.ptr.p_complex[0], 1, &a.ptr.pp_complex[i][0], 1, "N", ae_v_len(0,n-1)); - xcdot(&y, &xv, n, &tx, &v, &verr, _state); - *rfserrors = *rfserrors||ae_fp_greater(ae_c_abs(ae_c_sub(v,b.ptr.pp_complex[i][0]), _state),8*ae_machineepsilon*ae_maxreal((double)(1), ae_c_abs(b.ptr.pp_complex[i][0], _state), _state)); - } - } - - /* - * Test CMatrixSolve() - */ - testdirectdensesolversunit_cunset1d(&xv, _state); - cmatrixsolve(&a, n, &bv, &info, &rep, &xv, _state); - if( info<=0 ) - { - *rfserrors = ae_true; - } - else - { - for(i=0; i<=n-1; i++) - { - ae_v_cmove(&y.ptr.p_complex[0], 1, &a.ptr.pp_complex[i][0], 1, "N", ae_v_len(0,n-1)); - xcdot(&y, &xv, n, &tx, &v, &verr, _state); - *rfserrors = *rfserrors||ae_fp_greater(ae_c_abs(ae_c_sub(v,bv.ptr.p_complex[i]), _state),8*ae_machineepsilon*ae_maxreal((double)(1), ae_c_abs(bv.ptr.p_complex[i], _state), _state)); - } - } - - /* - * TODO: Test LS-solver on the same matrix - */ - } - ae_frame_leave(_state); -} - - -/************************************************************************* -HPD test -*************************************************************************/ -static void testdirectdensesolversunit_testhpdsolver(ae_int_t maxn, - ae_int_t maxm, - ae_int_t passcount, - double threshold, - ae_bool* hpderrors, - ae_bool* rfserrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix cha; - ae_matrix atmp; - ae_vector p; - ae_matrix xe; - ae_matrix b; - ae_vector bv; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t n; - ae_int_t m; - ae_int_t pass; - ae_int_t taskkind; - ae_complex v; - ae_bool isupper; - ae_int_t info; - densesolverreport rep; - densesolverlsreport repls; - ae_matrix x; - ae_vector xv; - ae_vector y; - ae_vector tx; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&cha, 0, sizeof(cha)); - memset(&atmp, 0, sizeof(atmp)); - memset(&p, 0, sizeof(p)); - memset(&xe, 0, sizeof(xe)); - memset(&b, 0, sizeof(b)); - memset(&bv, 0, sizeof(bv)); - memset(&rep, 0, sizeof(rep)); - memset(&repls, 0, sizeof(repls)); - memset(&x, 0, sizeof(x)); - memset(&xv, 0, sizeof(xv)); - memset(&y, 0, sizeof(y)); - memset(&tx, 0, sizeof(tx)); - ae_matrix_init(&a, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&cha, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&atmp, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&p, 0, DT_INT, _state, ae_true); - ae_matrix_init(&xe, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&b, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&bv, 0, DT_COMPLEX, _state, ae_true); - _densesolverreport_init(&rep, _state, ae_true); - _densesolverlsreport_init(&repls, _state, ae_true); - ae_matrix_init(&x, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&xv, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&y, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&tx, 0, DT_COMPLEX, _state, ae_true); - - - /* - * General square matrices: - * * test general solvers - * * test least squares solver - */ - for(pass=1; pass<=passcount; pass++) - { - for(n=1; n<=maxn; n++) - { - for(m=1; m<=maxm; m++) - { - - /* - * ******************************************************** - * WELL CONDITIONED TASKS - * ability to find correct solution is tested - * ******************************************************** - * - * 1. generate random well conditioned matrix A. - * 2. generate random solution vector xe - * 3. generate right part b=A*xe - * 4. test different methods on original A - */ - isupper = ae_fp_greater(ae_randomreal(_state),0.5); - hpdmatrixrndcond(n, (double)(1000), &a, _state); - testdirectdensesolversunit_cmatrixmakeacopy(&a, n, n, &cha, _state); - if( !hpdmatrixcholesky(&cha, n, isupper, _state) ) - { - *hpderrors = ae_true; - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&xe, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - xe.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - xe.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - ae_matrix_set_length(&b, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - v = ae_v_cdotproduct(&a.ptr.pp_complex[i][0], 1, "N", &xe.ptr.pp_complex[0][j], xe.stride, "N", ae_v_len(0,n-1)); - b.ptr.pp_complex[i][j] = v; - } - } - testdirectdensesolversunit_cmatrixdrophalf(&a, n, isupper, _state); - testdirectdensesolversunit_cmatrixdrophalf(&cha, n, isupper, _state); - - /* - * Test solvers - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_cunset2d(&x, _state); - hpdmatrixsolvem(&a, n, isupper, &b, m, &info, &rep, &x, _state); - *hpderrors = *hpderrors||!testdirectdensesolversunit_cmatrixchecksolutionm(&xe, n, m, threshold, info, &rep, &x, _state); - info = 0; - ae_matrix_set_length(&x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_complex[i][j] = b.ptr.pp_complex[i][j]; - } - } - hpdmatrixsolvemfast(&a, n, isupper, &x, m, &info, _state); - ae_set_error_flag(hpderrors, !testdirectdensesolversunit_cmatrixchecksolutionmfast(&xe, n, m, threshold, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1771"); - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_cunset1d(&xv, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1)); - hpdmatrixsolve(&a, n, isupper, &bv, &info, &rep, &xv, _state); - *hpderrors = *hpderrors||!testdirectdensesolversunit_cmatrixchecksolution(&xe, n, threshold, info, &rep, &xv, _state); - info = 0; - ae_vector_set_length(&bv, n, _state); - ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1)); - hpdmatrixsolvefast(&a, n, isupper, &bv, &info, _state); - *hpderrors = *hpderrors||!testdirectdensesolversunit_cmatrixchecksolution(&xe, n, threshold, info, &rep, &bv, _state); - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_cunset2d(&x, _state); - hpdmatrixcholeskysolvem(&cha, n, isupper, &b, m, &info, &rep, &x, _state); - *hpderrors = *hpderrors||!testdirectdensesolversunit_cmatrixchecksolutionm(&xe, n, m, threshold, info, &rep, &x, _state); - info = 0; - ae_matrix_set_length(&x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_complex[i][j] = b.ptr.pp_complex[i][j]; - } - } - hpdmatrixcholeskysolvemfast(&cha, n, isupper, &x, m, &info, _state); - ae_set_error_flag(hpderrors, !testdirectdensesolversunit_cmatrixchecksolutionmfast(&xe, n, m, threshold, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1799"); - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_cunset1d(&xv, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1)); - hpdmatrixcholeskysolve(&cha, n, isupper, &bv, &info, &rep, &xv, _state); - *hpderrors = *hpderrors||!testdirectdensesolversunit_cmatrixchecksolution(&xe, n, threshold, info, &rep, &xv, _state); - info = 0; - ae_vector_set_length(&bv, n, _state); - ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1)); - hpdmatrixcholeskysolvefast(&cha, n, isupper, &bv, &info, _state); - ae_set_error_flag(hpderrors, !testdirectdensesolversunit_cmatrixchecksolutionfast(&xe, n, threshold, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1813"); - - /* - * ******************************************************** - * EXACTLY SINGULAR MATRICES - * ability to detect singularity is tested - * ******************************************************** - * - * 1. generate different types of singular matrices: - * * zero - * * with zero columns - * * with zero rows - * * with equal rows/columns - * 2. generate random solution vector xe - * 3. generate right part b=A*xe - * 4. test different methods - */ - for(taskkind=0; taskkind<=3; taskkind++) - { - testdirectdensesolversunit_cunset2d(&a, _state); - if( taskkind==0 ) - { - - /* - * all zeros - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - } - if( taskkind==1 ) - { - - /* - * there is zero column - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - if( i==j ) - { - a.ptr.pp_complex[i][j].y = (double)(0); - } - a.ptr.pp_complex[j][i] = a.ptr.pp_complex[i][j]; - } - } - k = ae_randominteger(n, _state); - ae_v_cmuld(&a.ptr.pp_complex[0][k], a.stride, ae_v_len(0,n-1), 0); - ae_v_cmuld(&a.ptr.pp_complex[k][0], 1, ae_v_len(0,n-1), 0); - } - if( taskkind==2 ) - { - - /* - * there is zero row - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - if( i==j ) - { - a.ptr.pp_complex[i][j].y = (double)(0); - } - a.ptr.pp_complex[j][i] = a.ptr.pp_complex[i][j]; - } - } - k = ae_randominteger(n, _state); - ae_v_cmuld(&a.ptr.pp_complex[k][0], 1, ae_v_len(0,n-1), 0); - ae_v_cmuld(&a.ptr.pp_complex[0][k], a.stride, ae_v_len(0,n-1), 0); - } - if( taskkind==3 ) - { - - /* - * equal columns/rows - */ - if( n<2 ) - { - continue; - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - if( i==j ) - { - a.ptr.pp_complex[i][j].y = (double)(0); - } - a.ptr.pp_complex[j][i] = a.ptr.pp_complex[i][j]; - } - } - k = 1+ae_randominteger(n-1, _state); - ae_v_cmove(&a.ptr.pp_complex[0][0], a.stride, &a.ptr.pp_complex[0][k], a.stride, "N", ae_v_len(0,n-1)); - ae_v_cmove(&a.ptr.pp_complex[0][0], 1, &a.ptr.pp_complex[k][0], 1, "N", ae_v_len(0,n-1)); - } - ae_matrix_set_length(&xe, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - xe.ptr.pp_complex[i][j] = ae_complex_from_d(2*ae_randomreal(_state)-1); - } - } - ae_matrix_set_length(&b, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - v = ae_v_cdotproduct(&a.ptr.pp_complex[i][0], 1, "N", &xe.ptr.pp_complex[0][j], xe.stride, "N", ae_v_len(0,n-1)); - b.ptr.pp_complex[i][j] = v; - } - } - testdirectdensesolversunit_cmatrixmakeacopy(&a, n, n, &cha, _state); - testdirectdensesolversunit_cmatrixdrophalf(&a, n, isupper, _state); - testdirectdensesolversunit_cmatrixdrophalf(&cha, n, isupper, _state); - - /* - * Test SPDMatrixSolveM() (and fast version) - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_cunset2d(&x, _state); - hpdmatrixsolvem(&a, n, isupper, &b, m, &info, &rep, &x, _state); - *hpderrors = *hpderrors||!testdirectdensesolversunit_cmatrixchecksingularm(n, m, info, &rep, &x, _state); - if( (taskkind==0||taskkind==1)||taskkind==2 ) - { - info = 0; - ae_matrix_set_length(&x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_complex[i][j] = b.ptr.pp_complex[i][j]; - } - } - hpdmatrixsolvemfast(&a, n, isupper, &x, m, &info, _state); - ae_set_error_flag(hpderrors, !testdirectdensesolversunit_cmatrixchecksingularmfast(n, m, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1934"); - } - - /* - * Test SPDMatrixSolve() - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_cunset2d(&x, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1)); - hpdmatrixsolve(&a, n, isupper, &bv, &info, &rep, &xv, _state); - *hpderrors = *hpderrors||!testdirectdensesolversunit_cmatrixchecksingular(n, info, &rep, &xv, _state); - if( (taskkind==0||taskkind==1)||taskkind==2 ) - { - info = 0; - ae_vector_set_length(&bv, n, _state); - ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1)); - hpdmatrixsolvefast(&a, n, isupper, &bv, &info, _state); - ae_set_error_flag(hpderrors, !testdirectdensesolversunit_cmatrixchecksingularfast(n, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1953"); - } - - /* - * 'equal columns/rows' are degenerate, but - * Cholesky matrix with equal columns/rows IS NOT degenerate, - * so it is not used for testing purposes. - */ - if( taskkind!=3 ) - { - - /* - * Test SPDMatrixCholeskySolveM()/fast - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_cunset2d(&x, _state); - hpdmatrixcholeskysolvem(&cha, n, isupper, &b, m, &info, &rep, &x, _state); - *hpderrors = *hpderrors||!testdirectdensesolversunit_cmatrixchecksingularm(n, m, info, &rep, &x, _state); - if( (taskkind==0||taskkind==1)||taskkind==2 ) - { - info = 0; - ae_matrix_set_length(&x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_complex[i][j] = b.ptr.pp_complex[i][j]; - } - } - hpdmatrixcholeskysolvemfast(&cha, n, isupper, &x, m, &info, _state); - ae_set_error_flag(hpderrors, !testdirectdensesolversunit_cmatrixchecksingularmfast(n, m, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1979"); - } - - /* - * Test HPDMatrixCholeskySolve() (fast) - */ - info = 0; - testdirectdensesolversunit_unsetrep(&rep, _state); - testdirectdensesolversunit_cunset2d(&x, _state); - ae_vector_set_length(&bv, n, _state); - ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1)); - hpdmatrixcholeskysolve(&cha, n, isupper, &bv, &info, &rep, &xv, _state); - *hpderrors = *hpderrors||!testdirectdensesolversunit_cmatrixchecksingular(n, info, &rep, &xv, _state); - if( (taskkind==0||taskkind==1)||taskkind==2 ) - { - ae_vector_set_length(&bv, n, _state); - ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1)); - hpdmatrixcholeskysolvefast(&cha, n, isupper, &bv, &info, _state); - ae_set_error_flag(hpderrors, !testdirectdensesolversunit_cmatrixchecksingularfast(n, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1997"); - } - } - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Unsets real matrix -*************************************************************************/ -static void testdirectdensesolversunit_unset2d(/* Real */ ae_matrix* x, - ae_state *_state) -{ - - - ae_matrix_set_length(x, 1, 1, _state); - x->ptr.pp_double[0][0] = 2*ae_randomreal(_state)-1; -} - - -/************************************************************************* -Unsets real vector -*************************************************************************/ -static void testdirectdensesolversunit_unset1d(/* Real */ ae_vector* x, - ae_state *_state) -{ - - - ae_vector_set_length(x, 1, _state); - x->ptr.p_double[0] = 2*ae_randomreal(_state)-1; -} - - -/************************************************************************* -Unsets real matrix -*************************************************************************/ -static void testdirectdensesolversunit_cunset2d(/* Complex */ ae_matrix* x, - ae_state *_state) -{ - - - ae_matrix_set_length(x, 1, 1, _state); - x->ptr.pp_complex[0][0] = ae_complex_from_d(2*ae_randomreal(_state)-1); -} - - -/************************************************************************* -Unsets real vector -*************************************************************************/ -static void testdirectdensesolversunit_cunset1d(/* Complex */ ae_vector* x, - ae_state *_state) -{ - - - ae_vector_set_length(x, 1, _state); - x->ptr.p_complex[0] = ae_complex_from_d(2*ae_randomreal(_state)-1); -} - - -/************************************************************************* -Unsets report -*************************************************************************/ -static void testdirectdensesolversunit_unsetrep(densesolverreport* r, - ae_state *_state) -{ - - - r->r1 = (double)(-1); - r->rinf = (double)(-1); -} - - -/************************************************************************* -Unsets report -*************************************************************************/ -static void testdirectdensesolversunit_unsetlsrep(densesolverlsreport* r, - ae_state *_state) -{ - - - r->r2 = (double)(-1); - r->n = -1; - r->k = -1; - testdirectdensesolversunit_unset2d(&r->cx, _state); -} - - - - - - - - -ae_bool testlinmin(ae_bool silent, ae_state *_state) -{ - ae_bool waserrors; - ae_bool result; - - - waserrors = ae_false; - if( !silent ) - { - printf("TESTING LINMIN\n"); - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - return result; -} - - - -static ae_int_t testminlbfgsunit_maxoptguardlevel = 1; -static void testminlbfgsunit_testfunc2(minlbfgsstate* state, - ae_state *_state); -static void testminlbfgsunit_testfunc3(minlbfgsstate* state, - ae_state *_state); -static void testminlbfgsunit_calciip2(minlbfgsstate* state, - ae_int_t n, - ae_state *_state); -static void testminlbfgsunit_testpreconditioning(ae_bool* err, - ae_state *_state); -static void testminlbfgsunit_testother(ae_bool* err, ae_state *_state); -static void testminlbfgsunit_testoptguard(ae_bool* wereerrors, - ae_state *_state); -static void testminlbfgsunit_testoptguardc1test0reportfortask0(ae_bool* err, - optguardnonc1test0report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state); -static void testminlbfgsunit_testoptguardc1test1reportfortask0(ae_bool* err, - optguardnonc1test1report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state); - - - - - -ae_bool testminlbfgs(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_bool waserrors; - ae_bool referror; - ae_bool nonconverror; - ae_bool eqerror; - ae_bool converror; - ae_bool crashtest; - ae_bool othererrors; - ae_bool restartserror; - ae_bool precerror; - ae_bool optguarderr; - ae_int_t n; - ae_int_t m; - ae_vector x; - ae_vector xe; - ae_vector b; - ae_vector xlast; - ae_int_t i; - ae_int_t j; - double v; - ae_matrix a; - ae_vector diagh; - ae_int_t maxits; - minlbfgsstate state; - minlbfgsreport rep; - double diffstep; - ae_int_t dkind; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&xe, 0, sizeof(xe)); - memset(&b, 0, sizeof(b)); - memset(&xlast, 0, sizeof(xlast)); - memset(&a, 0, sizeof(a)); - memset(&diagh, 0, sizeof(diagh)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xe, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xlast, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&diagh, 0, DT_REAL, _state, ae_true); - _minlbfgsstate_init(&state, _state, ae_true); - _minlbfgsreport_init(&rep, _state, ae_true); - - waserrors = ae_false; - referror = ae_false; - precerror = ae_false; - nonconverror = ae_false; - restartserror = ae_false; - eqerror = ae_false; - converror = ae_false; - crashtest = ae_false; - othererrors = ae_false; - testminlbfgsunit_testpreconditioning(&precerror, _state); - testminlbfgsunit_testother(&othererrors, _state); - - /* - * Reference problem - */ - diffstep = 1.0E-6; - for(dkind=0; dkind<=1; dkind++) - { - ae_vector_set_length(&x, 3, _state); - n = 3; - m = 2; - x.ptr.p_double[0] = 100*ae_randomreal(_state)-50; - x.ptr.p_double[1] = 100*ae_randomreal(_state)-50; - x.ptr.p_double[2] = 100*ae_randomreal(_state)-50; - if( dkind==0 ) - { - minlbfgscreate(n, m, &x, &state, _state); - } - if( dkind==1 ) - { - minlbfgscreatef(n, m, &x, diffstep, &state, _state); - } - minlbfgssetcond(&state, (double)(0), (double)(0), (double)(0), 0, _state); - while(minlbfgsiteration(&state, _state)) - { - if( state.needf||state.needfg ) - { - state.f = ae_sqr(state.x.ptr.p_double[0]-2, _state)+ae_sqr(state.x.ptr.p_double[1], _state)+ae_sqr(state.x.ptr.p_double[2]-state.x.ptr.p_double[0], _state); - } - if( state.needfg ) - { - state.g.ptr.p_double[0] = 2*(state.x.ptr.p_double[0]-2)+2*(state.x.ptr.p_double[0]-state.x.ptr.p_double[2]); - state.g.ptr.p_double[1] = 2*state.x.ptr.p_double[1]; - state.g.ptr.p_double[2] = 2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0]); - } - } - minlbfgsresults(&state, &x, &rep, _state); - referror = (((referror||rep.terminationtype<=0)||ae_fp_greater(ae_fabs(x.ptr.p_double[0]-2, _state),0.001))||ae_fp_greater(ae_fabs(x.ptr.p_double[1], _state),0.001))||ae_fp_greater(ae_fabs(x.ptr.p_double[2]-2, _state),0.001); - } - - /* - * nonconvex problems with complex surface: we start from point with very small - * gradient, but we need ever smaller gradient in the next step due to - * Wolfe conditions. - */ - diffstep = 1.0E-6; - for(dkind=0; dkind<=1; dkind++) - { - ae_vector_set_length(&x, 1, _state); - n = 1; - m = 1; - v = (double)(-100); - while(ae_fp_less(v,0.1)) - { - x.ptr.p_double[0] = v; - if( dkind==0 ) - { - minlbfgscreate(n, m, &x, &state, _state); - } - if( dkind==1 ) - { - minlbfgscreatef(n, m, &x, diffstep, &state, _state); - } - minlbfgssetcond(&state, 1.0E-9, (double)(0), (double)(0), 0, _state); - while(minlbfgsiteration(&state, _state)) - { - if( state.needf||state.needfg ) - { - state.f = ae_sqr(state.x.ptr.p_double[0], _state)/(1+ae_sqr(state.x.ptr.p_double[0], _state)); - } - if( state.needfg ) - { - state.g.ptr.p_double[0] = (2*state.x.ptr.p_double[0]*(1+ae_sqr(state.x.ptr.p_double[0], _state))-ae_sqr(state.x.ptr.p_double[0], _state)*2*state.x.ptr.p_double[0])/ae_sqr(1+ae_sqr(state.x.ptr.p_double[0], _state), _state); - } - } - minlbfgsresults(&state, &x, &rep, _state); - nonconverror = (nonconverror||rep.terminationtype<=0)||ae_fp_greater(ae_fabs(x.ptr.p_double[0], _state),0.001); - v = v+0.1; - } - } - - /* - * F2 problem with restarts: - * * make several iterations and restart BEFORE termination - * * iterate and restart AFTER termination - * - * NOTE: step is bounded from above to avoid premature convergence - */ - diffstep = 1.0E-6; - for(dkind=0; dkind<=1; dkind++) - { - ae_vector_set_length(&x, 3, _state); - n = 3; - m = 2; - x.ptr.p_double[0] = 10+10*ae_randomreal(_state); - x.ptr.p_double[1] = 10+10*ae_randomreal(_state); - x.ptr.p_double[2] = 10+10*ae_randomreal(_state); - if( dkind==0 ) - { - minlbfgscreate(n, m, &x, &state, _state); - } - if( dkind==1 ) - { - minlbfgscreatef(n, m, &x, diffstep, &state, _state); - } - minlbfgssetstpmax(&state, 0.1, _state); - minlbfgssetcond(&state, 0.0000001, 0.0, 0.0, 0, _state); - for(i=0; i<=10; i++) - { - if( !minlbfgsiteration(&state, _state) ) - { - break; - } - testminlbfgsunit_testfunc2(&state, _state); - } - x.ptr.p_double[0] = 10+10*ae_randomreal(_state); - x.ptr.p_double[1] = 10+10*ae_randomreal(_state); - x.ptr.p_double[2] = 10+10*ae_randomreal(_state); - minlbfgsrestartfrom(&state, &x, _state); - while(minlbfgsiteration(&state, _state)) - { - testminlbfgsunit_testfunc2(&state, _state); - } - minlbfgsresults(&state, &x, &rep, _state); - restartserror = (((restartserror||rep.terminationtype<=0)||ae_fp_greater(ae_fabs(x.ptr.p_double[0]-ae_log((double)(2), _state), _state),0.01))||ae_fp_greater(ae_fabs(x.ptr.p_double[1], _state),0.01))||ae_fp_greater(ae_fabs(x.ptr.p_double[2]-ae_log((double)(2), _state), _state),0.01); - x.ptr.p_double[0] = 10+10*ae_randomreal(_state); - x.ptr.p_double[1] = 10+10*ae_randomreal(_state); - x.ptr.p_double[2] = 10+10*ae_randomreal(_state); - minlbfgsrestartfrom(&state, &x, _state); - while(minlbfgsiteration(&state, _state)) - { - testminlbfgsunit_testfunc2(&state, _state); - } - minlbfgsresults(&state, &x, &rep, _state); - restartserror = (((restartserror||rep.terminationtype<=0)||ae_fp_greater(ae_fabs(x.ptr.p_double[0]-ae_log((double)(2), _state), _state),0.01))||ae_fp_greater(ae_fabs(x.ptr.p_double[1], _state),0.01))||ae_fp_greater(ae_fabs(x.ptr.p_double[2]-ae_log((double)(2), _state), _state),0.01); - } - - /* - * Linear equations - */ - diffstep = 1.0E-6; - for(n=1; n<=10; n++) - { - - /* - * Prepare task - */ - ae_matrix_set_length(&a, n-1+1, n-1+1, _state); - ae_vector_set_length(&x, n-1+1, _state); - ae_vector_set_length(&xe, n-1+1, _state); - ae_vector_set_length(&b, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - xe.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - a.ptr.pp_double[i][i] = a.ptr.pp_double[i][i]+3*ae_sign(a.ptr.pp_double[i][i], _state); - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xe.ptr.p_double[0], 1, ae_v_len(0,n-1)); - b.ptr.p_double[i] = v; - } - - /* - * Test different M/DKind - */ - for(m=1; m<=n; m++) - { - for(dkind=0; dkind<=1; dkind++) - { - - /* - * Solve task - */ - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - if( dkind==0 ) - { - minlbfgscreate(n, m, &x, &state, _state); - } - if( dkind==1 ) - { - minlbfgscreatef(n, m, &x, diffstep, &state, _state); - } - minlbfgssetcond(&state, (double)(0), (double)(0), (double)(0), 0, _state); - while(minlbfgsiteration(&state, _state)) - { - if( state.needf||state.needfg ) - { - state.f = (double)(0); - } - if( state.needfg ) - { - for(i=0; i<=n-1; i++) - { - state.g.ptr.p_double[i] = (double)(0); - } - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( state.needf||state.needfg ) - { - state.f = state.f+ae_sqr(v-b.ptr.p_double[i], _state); - } - if( state.needfg ) - { - for(j=0; j<=n-1; j++) - { - state.g.ptr.p_double[j] = state.g.ptr.p_double[j]+2*(v-b.ptr.p_double[i])*a.ptr.pp_double[i][j]; - } - } - } - } - minlbfgsresults(&state, &x, &rep, _state); - eqerror = eqerror||rep.terminationtype<=0; - for(i=0; i<=n-1; i++) - { - eqerror = eqerror||ae_fp_greater(ae_fabs(x.ptr.p_double[i]-xe.ptr.p_double[i], _state),0.001); - } - } - } - } - - /* - * Testing convergence properties - */ - diffstep = 1.0E-6; - for(dkind=0; dkind<=1; dkind++) - { - ae_vector_set_length(&x, 3, _state); - n = 3; - m = 2; - for(i=0; i<=2; i++) - { - x.ptr.p_double[i] = 6*ae_randomreal(_state)-3; - } - if( dkind==0 ) - { - minlbfgscreate(n, m, &x, &state, _state); - } - if( dkind==1 ) - { - minlbfgscreatef(n, m, &x, diffstep, &state, _state); - } - minlbfgssetcond(&state, 0.001, (double)(0), (double)(0), 0, _state); - while(minlbfgsiteration(&state, _state)) - { - testminlbfgsunit_testfunc3(&state, _state); - } - minlbfgsresults(&state, &x, &rep, _state); - converror = converror||rep.terminationtype!=4; - for(i=0; i<=2; i++) - { - x.ptr.p_double[i] = 6*ae_randomreal(_state)-3; - } - if( dkind==0 ) - { - minlbfgscreate(n, m, &x, &state, _state); - } - if( dkind==1 ) - { - minlbfgscreatef(n, m, &x, diffstep, &state, _state); - } - minlbfgssetcond(&state, (double)(0), 0.001, (double)(0), 0, _state); - while(minlbfgsiteration(&state, _state)) - { - testminlbfgsunit_testfunc3(&state, _state); - } - minlbfgsresults(&state, &x, &rep, _state); - converror = converror||rep.terminationtype!=1; - for(i=0; i<=2; i++) - { - x.ptr.p_double[i] = 6*ae_randomreal(_state)-3; - } - if( dkind==0 ) - { - minlbfgscreate(n, m, &x, &state, _state); - } - if( dkind==1 ) - { - minlbfgscreatef(n, m, &x, diffstep, &state, _state); - } - minlbfgssetcond(&state, (double)(0), (double)(0), 0.001, 0, _state); - while(minlbfgsiteration(&state, _state)) - { - testminlbfgsunit_testfunc3(&state, _state); - } - minlbfgsresults(&state, &x, &rep, _state); - converror = converror||rep.terminationtype!=2; - for(i=0; i<=2; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - if( dkind==0 ) - { - minlbfgscreate(n, m, &x, &state, _state); - } - if( dkind==1 ) - { - minlbfgscreatef(n, m, &x, diffstep, &state, _state); - } - minlbfgssetcond(&state, (double)(0), (double)(0), (double)(0), 10, _state); - while(minlbfgsiteration(&state, _state)) - { - testminlbfgsunit_testfunc3(&state, _state); - } - minlbfgsresults(&state, &x, &rep, _state); - converror = (converror||rep.terminationtype!=5)||rep.iterationscount!=10; - } - - /* - * Crash test: too many iterations on a simple tasks - * May fail when encounter zero step, underflow or something like that - */ - ae_vector_set_length(&x, 2+1, _state); - n = 3; - m = 2; - maxits = 10000; - for(i=0; i<=2; i++) - { - x.ptr.p_double[i] = 6*ae_randomreal(_state)-3; - } - minlbfgscreate(n, m, &x, &state, _state); - minlbfgssetcond(&state, (double)(0), (double)(0), (double)(0), maxits, _state); - while(minlbfgsiteration(&state, _state)) - { - state.f = ae_sqr(ae_exp(state.x.ptr.p_double[0], _state)-2, _state)+ae_sqr(state.x.ptr.p_double[1], _state)+ae_sqr(state.x.ptr.p_double[2]-state.x.ptr.p_double[0], _state); - state.g.ptr.p_double[0] = 2*(ae_exp(state.x.ptr.p_double[0], _state)-2)*ae_exp(state.x.ptr.p_double[0], _state)+2*(state.x.ptr.p_double[0]-state.x.ptr.p_double[2]); - state.g.ptr.p_double[1] = 2*state.x.ptr.p_double[1]; - state.g.ptr.p_double[2] = 2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0]); - } - minlbfgsresults(&state, &x, &rep, _state); - crashtest = crashtest||rep.terminationtype<=0; - - /* - * Test OptGuard - */ - optguarderr = ae_false; - testminlbfgsunit_testoptguard(&optguarderr, _state); - - /* - * end - */ - waserrors = (((((((referror||nonconverror)||eqerror)||converror)||crashtest)||othererrors)||restartserror)||precerror)||optguarderr; - if( !silent ) - { - printf("TESTING L-BFGS OPTIMIZATION\n"); - printf("REFERENCE PROBLEM: "); - if( referror ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("NON-CONVEX PROBLEM: "); - if( nonconverror ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("LINEAR EQUATIONS: "); - if( eqerror ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("RESTARTS: "); - if( restartserror ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("PRECONDITIONER: "); - if( precerror ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("CONVERGENCE PROPERTIES: "); - if( converror ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("CRASH TEST: "); - if( crashtest ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("OTHER PROPERTIES: "); - if( othererrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("OPTGUARD: "); - if( optguarderr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Calculate test function #2 - -Simple variation of #1, much more nonlinear, which makes unlikely premature -convergence of algorithm . -*************************************************************************/ -static void testminlbfgsunit_testfunc2(minlbfgsstate* state, - ae_state *_state) -{ - - - if( ae_fp_less(state->x.ptr.p_double[0],(double)(100)) ) - { - if( state->needf||state->needfg ) - { - state->f = ae_sqr(ae_exp(state->x.ptr.p_double[0], _state)-2, _state)+ae_sqr(ae_sqr(state->x.ptr.p_double[1], _state), _state)+ae_sqr(state->x.ptr.p_double[2]-state->x.ptr.p_double[0], _state); - } - if( state->needfg ) - { - state->g.ptr.p_double[0] = 2*(ae_exp(state->x.ptr.p_double[0], _state)-2)*ae_exp(state->x.ptr.p_double[0], _state)+2*(state->x.ptr.p_double[0]-state->x.ptr.p_double[2]); - state->g.ptr.p_double[1] = 4*state->x.ptr.p_double[1]*ae_sqr(state->x.ptr.p_double[1], _state); - state->g.ptr.p_double[2] = 2*(state->x.ptr.p_double[2]-state->x.ptr.p_double[0]); - } - } - else - { - if( state->needf||state->needfg ) - { - state->f = ae_sqrt(ae_maxrealnumber, _state); - } - if( state->needfg ) - { - state->g.ptr.p_double[0] = ae_sqrt(ae_maxrealnumber, _state); - state->g.ptr.p_double[1] = (double)(0); - state->g.ptr.p_double[2] = (double)(0); - } - } -} - - -/************************************************************************* -Calculate test function #3 - -Simple variation of #1, much more nonlinear, with non-zero value at minimum. -It achieve two goals: -* makes unlikely premature convergence of algorithm . -* solves some issues with EpsF stopping condition which arise when - F(minimum) is zero - -*************************************************************************/ -static void testminlbfgsunit_testfunc3(minlbfgsstate* state, - ae_state *_state) -{ - double s; - - - s = 0.001; - if( ae_fp_less(state->x.ptr.p_double[0],(double)(100)) ) - { - if( state->needf||state->needfg ) - { - state->f = ae_sqr(ae_exp(state->x.ptr.p_double[0], _state)-2, _state)+ae_sqr(ae_sqr(state->x.ptr.p_double[1], _state)+s, _state)+ae_sqr(state->x.ptr.p_double[2]-state->x.ptr.p_double[0], _state); - } - if( state->needfg ) - { - state->g.ptr.p_double[0] = 2*(ae_exp(state->x.ptr.p_double[0], _state)-2)*ae_exp(state->x.ptr.p_double[0], _state)+2*(state->x.ptr.p_double[0]-state->x.ptr.p_double[2]); - state->g.ptr.p_double[1] = 2*(ae_sqr(state->x.ptr.p_double[1], _state)+s)*2*state->x.ptr.p_double[1]; - state->g.ptr.p_double[2] = 2*(state->x.ptr.p_double[2]-state->x.ptr.p_double[0]); - } - } - else - { - if( state->needf||state->needfg ) - { - state->f = ae_sqrt(ae_maxrealnumber, _state); - } - if( state->needfg ) - { - state->g.ptr.p_double[0] = ae_sqrt(ae_maxrealnumber, _state); - state->g.ptr.p_double[1] = (double)(0); - state->g.ptr.p_double[2] = (double)(0); - } - } -} - - -/************************************************************************* -Calculate test function IIP2 - -f(x) = sum( ((i*i+1)*x[i])^2, i=0..N-1) - -It has high condition number which makes fast convergence unlikely without -good preconditioner. - -*************************************************************************/ -static void testminlbfgsunit_calciip2(minlbfgsstate* state, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - - - if( state->needf||state->needfg ) - { - state->f = (double)(0); - } - for(i=0; i<=n-1; i++) - { - if( state->needf||state->needfg ) - { - state->f = state->f+ae_sqr((double)(i*i+1), _state)*ae_sqr(state->x.ptr.p_double[i], _state); - } - if( state->needfg ) - { - state->g.ptr.p_double[i] = ae_sqr((double)(i*i+1), _state)*2*state->x.ptr.p_double[i]; - } - } -} - - -/************************************************************************* -This function tests preconditioning - -On failure sets Err to True (leaves it unchanged otherwise) -*************************************************************************/ -static void testminlbfgsunit_testpreconditioning(ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t pass; - ae_int_t n; - ae_int_t m; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t cntb1; - ae_int_t cntb2; - ae_int_t cntg1; - ae_int_t cntg2; - ae_int_t pkind; - minlbfgsstate state; - minlbfgsreport rep; - ae_vector x; - ae_vector s; - ae_matrix a; - ae_vector diagh; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&x, 0, sizeof(x)); - memset(&s, 0, sizeof(s)); - memset(&a, 0, sizeof(a)); - memset(&diagh, 0, sizeof(diagh)); - _minlbfgsstate_init(&state, _state, ae_true); - _minlbfgsreport_init(&rep, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&diagh, 0, DT_REAL, _state, ae_true); - - m = 1; - k = 50; - - /* - * Preconditioner test1. - * - * If - * * B1 is default preconditioner - * * B2 is Cholesky preconditioner with unit diagonal - * * G1 is Cholesky preconditioner based on exact Hessian with perturbations - * * G2 is diagonal precomditioner based on approximate diagonal of Hessian matrix - * then "bad" preconditioners (B1/B2/..) are worse than "good" ones (G1/G2/..). - * "Worse" means more iterations to converge. - * - * We test it using f(x) = sum( ((i*i+1)*x[i])^2, i=0..N-1) and L-BFGS - * optimizer with deliberately small M=1. - * - * N - problem size - * PKind - zero for upper triangular preconditioner, one for lower triangular. - * K - number of repeated passes (should be large enough to average out random factors) - */ - for(n=10; n<=15; n++) - { - pkind = ae_randominteger(2, _state); - ae_vector_set_length(&x, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = (double)(0); - } - minlbfgscreate(n, m, &x, &state, _state); - - /* - * Test it with default preconditioner - */ - minlbfgssetprecdefault(&state, _state); - cntb1 = 0; - for(pass=0; pass<=k-1; pass++) - { - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - minlbfgsrestartfrom(&state, &x, _state); - while(minlbfgsiteration(&state, _state)) - { - testminlbfgsunit_calciip2(&state, n, _state); - } - minlbfgsresults(&state, &x, &rep, _state); - cntb1 = cntb1+rep.iterationscount; - *err = *err||rep.terminationtype<=0; - } - - /* - * Test it with unit preconditioner - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - a.ptr.pp_double[i][i] = (double)(1); - } - else - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - } - minlbfgssetpreccholesky(&state, &a, pkind==0, _state); - cntb2 = 0; - for(pass=0; pass<=k-1; pass++) - { - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - minlbfgsrestartfrom(&state, &x, _state); - while(minlbfgsiteration(&state, _state)) - { - testminlbfgsunit_calciip2(&state, n, _state); - } - minlbfgsresults(&state, &x, &rep, _state); - cntb2 = cntb2+rep.iterationscount; - *err = *err||rep.terminationtype<=0; - } - - /* - * Test it with perturbed Hessian preconditioner - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - a.ptr.pp_double[i][i] = (i*i+1)*(0.8+0.4*ae_randomreal(_state)); - } - else - { - if( (pkind==0&&j>i)||(pkind==1&&jv_nan; - } - } - } - } - minlbfgssetpreccholesky(&state, &a, pkind==0, _state); - cntg1 = 0; - for(pass=0; pass<=k-1; pass++) - { - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - minlbfgsrestartfrom(&state, &x, _state); - while(minlbfgsiteration(&state, _state)) - { - testminlbfgsunit_calciip2(&state, n, _state); - } - minlbfgsresults(&state, &x, &rep, _state); - cntg1 = cntg1+rep.iterationscount; - *err = *err||rep.terminationtype<=0; - } - - /* - * Test it with perturbed diagonal preconditioner - */ - ae_vector_set_length(&diagh, n, _state); - for(i=0; i<=n-1; i++) - { - diagh.ptr.p_double[i] = 2*ae_sqr((double)(i*i+1), _state)*(0.8+0.4*ae_randomreal(_state)); - } - minlbfgssetprecdiag(&state, &diagh, _state); - cntg2 = 0; - for(pass=0; pass<=k-1; pass++) - { - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - minlbfgsrestartfrom(&state, &x, _state); - while(minlbfgsiteration(&state, _state)) - { - testminlbfgsunit_calciip2(&state, n, _state); - } - minlbfgsresults(&state, &x, &rep, _state); - cntg2 = cntg2+rep.iterationscount; - *err = *err||rep.terminationtype<=0; - } - - /* - * Compare - */ - *err = *err||cntb1=0.999999 - * - * where c is either 1.0 or 1.0E+6, M is either 1.0E8, 1.0E20 or +INF - * (we try different combinations) - */ - for(ckind=0; ckind<=1; ckind++) - { - for(mkind=0; mkind<=2; mkind++) - { - - /* - * Choose c and M - */ - vc = (double)(1); - vm = (double)(1); - if( ckind==0 ) - { - vc = 1.0; - } - if( ckind==1 ) - { - vc = 1.0E+6; - } - if( mkind==0 ) - { - vm = 1.0E+8; - } - if( mkind==1 ) - { - vm = 1.0E+20; - } - if( mkind==2 ) - { - vm = _state->v_posinf; - } - - /* - * Create optimizer, solve optimization problem - */ - epsg = 1.0E-6*vc; - ae_vector_set_length(&x, 1, _state); - x.ptr.p_double[0] = 0.0; - minlbfgscreate(1, 1, &x, &state, _state); - minlbfgssetcond(&state, epsg, (double)(0), (double)(0), 0, _state); - while(minlbfgsiteration(&state, _state)) - { - if( state.needfg ) - { - if( ae_fp_less(-0.999999,state.x.ptr.p_double[0])&&ae_fp_less(state.x.ptr.p_double[0],0.999999) ) - { - state.f = 1/(1-state.x.ptr.p_double[0])+1/(1+state.x.ptr.p_double[0])+vc*state.x.ptr.p_double[0]; - state.g.ptr.p_double[0] = 1/ae_sqr(1-state.x.ptr.p_double[0], _state)-1/ae_sqr(1+state.x.ptr.p_double[0], _state)+vc; - } - else - { - state.f = vm; - } - } - } - minlbfgsresults(&state, &x, &rep, _state); - if( rep.terminationtype<=0 ) - { - *err = ae_true; - ae_frame_leave(_state); - return; - } - *err = *err||ae_fp_greater(ae_fabs(1/ae_sqr(1-x.ptr.p_double[0], _state)-1/ae_sqr(1+x.ptr.p_double[0], _state)+vc, _state),epsg); - } - } - - /* - * Test integrity checks for NAN/INF: - * * algorithm solves optimization problem, which is normal for some time (quadratic) - * * after 5-th step we choose random component of gradient and consistently spoil - * it by NAN or INF. - * * we check that correct termination code is returned (-8) - */ - n = 100; - for(pass=1; pass<=10; pass++) - { - spoiliteration = 5; - stopiteration = 8; - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - - /* - * Gradient can be spoiled by +INF, -INF, NAN - */ - spoilvar = hqrnduniformi(&rs, n, _state); - i = hqrnduniformi(&rs, 3, _state); - spoilval = _state->v_nan; - if( i==0 ) - { - spoilval = _state->v_neginf; - } - if( i==1 ) - { - spoilval = _state->v_posinf; - } - } - else - { - - /* - * Function value can be spoiled only by NAN - * (+INF can be recognized as legitimate value during optimization) - */ - spoilvar = -1; - spoilval = _state->v_nan; - } - spdmatrixrndcond(n, 1.0E5, &fulla, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - minlbfgscreate(n, 1, &x0, &state, _state); - minlbfgssetcond(&state, 0.0, 0.0, 0.0, stopiteration, _state); - minlbfgssetxrep(&state, ae_true, _state); - k = -1; - while(minlbfgsiteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.g.ptr.p_double[i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.f = state.f+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.g.ptr.p_double[i] = state.g.ptr.p_double[i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - if( k>=spoiliteration ) - { - if( spoilvar<0 ) - { - state.f = spoilval; - } - else - { - state.g.ptr.p_double[spoilvar] = spoilval; - } - } - continue; - } - if( state.xupdated ) - { - inc(&k, _state); - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minlbfgsresults(&state, &x1, &rep, _state); - ae_set_error_flag(err, rep.terminationtype!=-8, __FILE__, __LINE__, "testminlbfgsunit.ap:1123"); - } - - /* - * Check algorithm ability to handle request for termination: - * * to terminate with correct return code = 8 - * * to return point which was "current" at the moment of termination - */ - for(pass=1; pass<=50; pass++) - { - n = 3; - ss = (double)(100); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&xlast, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 6+ae_randomreal(_state); - } - stopcallidx = ae_randominteger(20, _state); - maxits = 25; - minlbfgscreate(n, 1, &x, &state, _state); - minlbfgssetcond(&state, (double)(0), (double)(0), (double)(0), maxits, _state); - minlbfgssetxrep(&state, ae_true, _state); - callidx = 0; - terminationrequested = ae_false; - ae_v_move(&xlast.ptr.p_double[0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - while(minlbfgsiteration(&state, _state)) - { - if( state.needfg ) - { - state.f = ss*ae_sqr(ae_exp(state.x.ptr.p_double[0], _state)-2, _state)+ae_sqr(state.x.ptr.p_double[1], _state)+ae_sqr(state.x.ptr.p_double[2]-state.x.ptr.p_double[0], _state); - state.g.ptr.p_double[0] = 2*ss*(ae_exp(state.x.ptr.p_double[0], _state)-2)*ae_exp(state.x.ptr.p_double[0], _state)+2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0])*(-1); - state.g.ptr.p_double[1] = 2*state.x.ptr.p_double[1]; - state.g.ptr.p_double[2] = 2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0]); - if( callidx==stopcallidx ) - { - minlbfgsrequesttermination(&state, _state); - terminationrequested = ae_true; - } - inc(&callidx, _state); - continue; - } - if( state.xupdated ) - { - if( !terminationrequested ) - { - ae_v_move(&xlast.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minlbfgsresults(&state, &x, &rep, _state); - ae_set_error_flag(err, rep.terminationtype!=8, __FILE__, __LINE__, "testminlbfgsunit.ap:1173"); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(err, ae_fp_neq(x.ptr.p_double[i],xlast.ptr.p_double[i]), __FILE__, __LINE__, "testminlbfgsunit.ap:1175"); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests OptGuard - -On failure sets error flag. -*************************************************************************/ -static void testminlbfgsunit_testoptguard(ae_bool* wereerrors, - ae_state *_state) -{ - ae_frame _frame_block; - hqrndstate rs; - double v; - minlbfgsstate state; - minlbfgsreport rep; - optguardreport ogrep; - optguardnonc1test0report ognonc1test0strrep; - optguardnonc1test0report ognonc1test0lngrep; - optguardnonc1test1report ognonc1test1strrep; - optguardnonc1test1report ognonc1test1lngrep; - ae_int_t i; - ae_int_t j; - ae_int_t n; - ae_int_t m; - ae_matrix a; - ae_matrix a1; - ae_vector s; - ae_vector x0; - ae_vector x1; - ae_vector b; - double diffstep; - ae_int_t pass; - ae_int_t defecttype; - ae_bool failed; - ae_int_t passcount; - ae_int_t maxfails; - ae_int_t failurecounter; - ae_int_t maxc1test0fails; - ae_int_t maxc1test1fails; - ae_int_t c1test0fails; - ae_int_t c1test1fails; - double avgstr0len; - double avglng0len; - double avgstr1len; - double avglng1len; - ae_int_t varidx; - ae_int_t skind; - ae_matrix jactrue; - ae_matrix jacdefect; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&ogrep, 0, sizeof(ogrep)); - memset(&ognonc1test0strrep, 0, sizeof(ognonc1test0strrep)); - memset(&ognonc1test0lngrep, 0, sizeof(ognonc1test0lngrep)); - memset(&ognonc1test1strrep, 0, sizeof(ognonc1test1strrep)); - memset(&ognonc1test1lngrep, 0, sizeof(ognonc1test1lngrep)); - memset(&a, 0, sizeof(a)); - memset(&a1, 0, sizeof(a1)); - memset(&s, 0, sizeof(s)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&b, 0, sizeof(b)); - memset(&jactrue, 0, sizeof(jactrue)); - memset(&jacdefect, 0, sizeof(jacdefect)); - _hqrndstate_init(&rs, _state, ae_true); - _minlbfgsstate_init(&state, _state, ae_true); - _minlbfgsreport_init(&rep, _state, ae_true); - _optguardreport_init(&ogrep, _state, ae_true); - _optguardnonc1test0report_init(&ognonc1test0strrep, _state, ae_true); - _optguardnonc1test0report_init(&ognonc1test0lngrep, _state, ae_true); - _optguardnonc1test1report_init(&ognonc1test1strrep, _state, ae_true); - _optguardnonc1test1report_init(&ognonc1test1lngrep, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&jactrue, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&jacdefect, 0, 0, DT_REAL, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Check that gradient verification is disabled by default: - * gradient checking for bad problem must return nothing - */ - n = 10; - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 1.0+0.1*i; - } - spdmatrixrndcond(n, 1.0E3, &a, _state); - spdmatrixrndcond(n, 1.0E3, &a1, _state); - minlbfgscreate(n, 3, &x0, &state, _state); - minlbfgssetcond(&state, (double)(0), (double)(0), 1.0E-9, 10, _state); - while(minlbfgsiteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.f = state.f+0.5*state.x.ptr.p_double[i]*v; - } - for(i=0; i<=n-1; i++) - { - state.g.ptr.p_double[i] = (double)(0); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minlbfgsresults(&state, &x1, &rep, _state); - minlbfgsoptguardresults(&state, &ogrep, _state); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1248"); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1249"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(wereerrors, ogrep.badgradxbase.cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1252"); - ae_set_error_flag(wereerrors, ogrep.badgraduser.rows!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1253"); - ae_set_error_flag(wereerrors, ogrep.badgraduser.cols!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1254"); - ae_set_error_flag(wereerrors, ogrep.badgradnum.rows!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1255"); - ae_set_error_flag(wereerrors, ogrep.badgradnum.cols!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1256"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(wereerrors, ogrep.badgradsuspected, __FILE__, __LINE__, "testminlbfgsunit.ap:1259"); - ae_set_error_flag(wereerrors, ogrep.badgradfidx!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1260"); - ae_set_error_flag(wereerrors, ogrep.badgradvidx!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1261"); - - /* - * Test that C0/C1 continuity monitoring is disabled by default; - * we solve nonsmooth problem and test that nothing is returned - * by OptGuard. - */ - n = 10; - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - minlbfgscreate(n, 2, &x0, &state, _state); - minlbfgssetcond(&state, (double)(0), (double)(0), 1.0E-9, 50, _state); - while(minlbfgsiteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.g.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.f = state.f+ae_fabs(v, _state); - v = (double)(ae_sign(v, _state)); - for(j=0; j<=n-1; j++) - { - state.g.ptr.p_double[j] = state.g.ptr.p_double[j]+v*a.ptr.pp_double[i][j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minlbfgsresults(&state, &x1, &rep, _state); - minlbfgsoptguardresults(&state, &ogrep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1301"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1302"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminlbfgsunit.ap:1305"); - ae_set_error_flag(wereerrors, ogrep.nonc1suspected, __FILE__, __LINE__, "testminlbfgsunit.ap:1306"); - ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1307"); - ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1308"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx>=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1309"); - ae_set_error_flag(wereerrors, ogrep.nonc1test0positive, __FILE__, __LINE__, "testminlbfgsunit.ap:1310"); - ae_set_error_flag(wereerrors, ogrep.nonc1test1positive, __FILE__, __LINE__, "testminlbfgsunit.ap:1311"); - - /* - * Test gradient checking functionality, try various - * defect types: - * * accidental zeroing of some gradient component - * * accidental addition of 1.0 to some component - * * accidental multiplication by 2.0 - * Try distorting both target and constraints. - */ - diffstep = 0.001; - n = 10; - m = 2; - for(skind=0; skind<=1; skind++) - { - for(defecttype=-1; defecttype<=2; defecttype++) - { - varidx = hqrnduniformi(&rs, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = ae_pow((double)(10), skind*(30*hqrnduniformr(&rs, _state)-15), _state); - x0.ptr.p_double[i] = (1.0+0.1*i)*s.ptr.p_double[i]; - } - spdmatrixrndcond(n, 1.0E3, &a, _state); - spdmatrixrndcond(n, 1.0E3, &a1, _state); - minlbfgscreate(n, m, &x0, &state, _state); - minlbfgsoptguardgradient(&state, diffstep, _state); - minlbfgssetcond(&state, (double)(0), (double)(0), 1.0E-9, 10, _state); - minlbfgssetscale(&state, &s, _state); - while(minlbfgsiteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.f = state.f+0.5*(state.x.ptr.p_double[i]/s.ptr.p_double[i])*v; - state.g.ptr.p_double[i] = v; - } - if( defecttype==0 ) - { - state.g.ptr.p_double[varidx] = (double)(0); - } - if( defecttype==1 ) - { - state.g.ptr.p_double[varidx] = state.g.ptr.p_double[varidx]+1; - } - if( defecttype==2 ) - { - state.g.ptr.p_double[varidx] = state.g.ptr.p_double[varidx]*2; - } - for(i=0; i<=n-1; i++) - { - state.g.ptr.p_double[i] = state.g.ptr.p_double[i]/s.ptr.p_double[i]; - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minlbfgsresults(&state, &x1, &rep, _state); - minlbfgsoptguardresults(&state, &ogrep, _state); - - /* - * Check that something is returned - */ - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1377"); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1378"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Compute reference values for true and spoiled Jacobian at X0 - */ - ae_set_error_flag(wereerrors, !isfinitevector(&ogrep.badgradxbase, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1385"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&jactrue, 1, n, _state); - ae_matrix_set_length(&jacdefect, 1, n, _state); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+ogrep.badgradxbase.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - jactrue.ptr.pp_double[0][i] = v; - jacdefect.ptr.pp_double[0][i] = v; - } - if( defecttype==0 ) - { - jacdefect.ptr.pp_double[0][varidx] = (double)(0); - } - if( defecttype==1 ) - { - jacdefect.ptr.pp_double[0][varidx] = jacdefect.ptr.pp_double[0][varidx]+1; - } - if( defecttype==2 ) - { - jacdefect.ptr.pp_double[0][varidx] = jacdefect.ptr.pp_double[0][varidx]*2; - } - for(i=0; i<=n-1; i++) - { - jactrue.ptr.pp_double[0][i] = jactrue.ptr.pp_double[0][i]/s.ptr.p_double[i]; - jacdefect.ptr.pp_double[0][i] = jacdefect.ptr.pp_double[0][i]/s.ptr.p_double[i]; - } - - /* - * Check OptGuard report - */ - ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgraduser, 1, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1413"); - ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgradnum, 1, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1414"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - if( defecttype>=0 ) - { - ae_set_error_flag(wereerrors, !ogrep.badgradsuspected, __FILE__, __LINE__, "testminlbfgsunit.ap:1419"); - ae_set_error_flag(wereerrors, ogrep.badgradfidx!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1420"); - ae_set_error_flag(wereerrors, ogrep.badgradvidx!=varidx, __FILE__, __LINE__, "testminlbfgsunit.ap:1421"); - } - else - { - ae_set_error_flag(wereerrors, ogrep.badgradsuspected, __FILE__, __LINE__, "testminlbfgsunit.ap:1425"); - ae_set_error_flag(wereerrors, ogrep.badgradfidx!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1426"); - ae_set_error_flag(wereerrors, ogrep.badgradvidx!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1427"); - } - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jactrue.ptr.pp_double[0][j]-ogrep.badgradnum.ptr.pp_double[0][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testminlbfgsunit.ap:1431"); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jacdefect.ptr.pp_double[0][j]-ogrep.badgraduser.ptr.pp_double[0][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testminlbfgsunit.ap:1432"); - } - } - } - - /* - * A test for detection of C1 continuity violations in the target. - * - * Target function is a sum of |(x,c_i)| for i=1..N. - * No constraints is present. - * Analytic gradient is provided. - * - * OptGuard should be able to detect violations in more than - * 99.9% of runs; it means that 100 runs should have no more than 4 - * failures in all cases (even after multiple repeated tests; according - * to the binomial distribution quantiles). - * - * We select some N and perform exhaustive search for this N. - */ - passcount = 100; - maxfails = 4; - maxc1test0fails = 10; - maxc1test1fails = 10; - n = 1+hqrnduniformi(&rs, 10, _state); - m = 1+hqrnduniformi(&rs, n, _state); - failurecounter = 0; - c1test0fails = 0; - c1test1fails = 0; - avgstr0len = (double)(0); - avglng0len = (double)(0); - avgstr1len = (double)(0); - avglng1len = (double)(0); - for(pass=1; pass<=passcount; pass++) - { - - /* - * Formulate problem - */ - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - - /* - * Create and try to solve - */ - minlbfgscreate(n, m, &x0, &state, _state); - minlbfgssetcond(&state, (double)(0), (double)(0), 1.0E-9, 50, _state); - minlbfgssetscale(&state, &s, _state); - minlbfgsoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminlbfgsunit_maxoptguardlevel, _state), _state); - while(minlbfgsiteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.g.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.f = state.f+ae_fabs(v, _state); - v = (double)(ae_sign(v, _state)); - for(j=0; j<=n-1; j++) - { - state.g.ptr.p_double[j] = state.g.ptr.p_double[j]+v*a.ptr.pp_double[i][j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minlbfgsresults(&state, &x1, &rep, _state); - minlbfgsoptguardresults(&state, &ogrep, _state); - - /* - * Check basic properties of the solution - */ - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1514"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1515"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check generic OptGuard report: distinguish between "hard" - * failures which result in immediate termination - * (C0 violation being reported) and "soft" ones - * (C1 violation is NOT reported) which accumulate - * until we exhaust limit. - */ - ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminlbfgsunit.ap:1526"); - ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1527"); - failed = ae_false; - failed = failed||optguardallclear(&ogrep, _state); - failed = failed||!ogrep.nonc1suspected; - failed = failed||ogrep.nonc1fidx!=0; - if( failed ) - { - inc(&failurecounter, _state); - } - - /* - * Check C1 continuity test #0 - */ - minlbfgsoptguardnonc1test0results(&state, &ognonc1test0strrep, &ognonc1test0lngrep, _state); - minlbfgsoptguardnonc1test1results(&state, &ognonc1test1strrep, &ognonc1test1lngrep, _state); - if( ogrep.nonc1test0positive ) - { - ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminlbfgsunit.ap:1542"); - ae_set_error_flag(wereerrors, !ognonc1test0strrep.positive, __FILE__, __LINE__, "testminlbfgsunit.ap:1543"); - ae_set_error_flag(wereerrors, !ognonc1test0lngrep.positive, __FILE__, __LINE__, "testminlbfgsunit.ap:1544"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1545"); - testminlbfgsunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0strrep, &a, n, _state); - testminlbfgsunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0lngrep, &a, n, _state); - avgstr0len = avgstr0len+(double)ognonc1test0strrep.cnt/(double)passcount; - avglng0len = avglng0len+(double)ognonc1test0lngrep.cnt/(double)passcount; - } - else - { - ae_set_error_flag(wereerrors, ognonc1test0strrep.positive, __FILE__, __LINE__, "testminlbfgsunit.ap:1553"); - ae_set_error_flag(wereerrors, ognonc1test0lngrep.positive, __FILE__, __LINE__, "testminlbfgsunit.ap:1554"); - testminlbfgsunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0strrep, &a, n, _state); - testminlbfgsunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0lngrep, &a, n, _state); - inc(&c1test0fails, _state); - } - if( ogrep.nonc1test1positive ) - { - ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminlbfgsunit.ap:1561"); - ae_set_error_flag(wereerrors, !ognonc1test1strrep.positive, __FILE__, __LINE__, "testminlbfgsunit.ap:1562"); - ae_set_error_flag(wereerrors, !ognonc1test1lngrep.positive, __FILE__, __LINE__, "testminlbfgsunit.ap:1563"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1564"); - testminlbfgsunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1strrep, &a, n, _state); - testminlbfgsunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1lngrep, &a, n, _state); - avgstr1len = avgstr1len+(double)ognonc1test1strrep.cnt/(double)passcount; - avglng1len = avglng1len+(double)ognonc1test1lngrep.cnt/(double)passcount; - } - else - { - ae_set_error_flag(wereerrors, ognonc1test1strrep.positive, __FILE__, __LINE__, "testminlbfgsunit.ap:1572"); - ae_set_error_flag(wereerrors, ognonc1test1lngrep.positive, __FILE__, __LINE__, "testminlbfgsunit.ap:1573"); - testminlbfgsunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1strrep, &a, n, _state); - testminlbfgsunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1lngrep, &a, n, _state); - inc(&c1test1fails, _state); - } - } - ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testminlbfgsunit.ap:1580"); - ae_set_error_flag(wereerrors, c1test0fails>maxc1test0fails, __FILE__, __LINE__, "testminlbfgsunit.ap:1581"); - ae_set_error_flag(wereerrors, c1test1fails>maxc1test1fails, __FILE__, __LINE__, "testminlbfgsunit.ap:1582"); - ae_set_error_flag(wereerrors, ae_fp_less_eq(avglng0len,avgstr0len), __FILE__, __LINE__, "testminlbfgsunit.ap:1583"); - ae_set_error_flag(wereerrors, ae_fp_less_eq(avglng1len,avgstr1len), __FILE__, __LINE__, "testminlbfgsunit.ap:1584"); - - /* - * Detection of C1 continuity violations in the target under numerical differentiation: - * * target function is a sum of |(x,c_i)| for i=1..N. - * * no constraints is present. - * * analytic gradient is provided. - * - * OptGuard should always be able to detect violations in more than - * 99% of runs (note: reduced strength when compared with analytic gradient); - * it means that 100 runs should have no more than 10 failures in all cases - * (even after multiple repeated tests; according to the binomial distribution - * quantiles). - * - * We select some N and perform exhaustive search for this N. - */ - diffstep = 0.0001; - passcount = 100; - maxfails = 10; - n = 1+hqrnduniformi(&rs, 10, _state); - m = 1+hqrnduniformi(&rs, n, _state); - failurecounter = 0; - for(pass=1; pass<=passcount; pass++) - { - - /* - * Formulate problem - */ - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = 0.01*ae_pow((double)(2), 0.33*hqrndnormal(&rs, _state), _state); - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - - /* - * Create and try to solve - */ - minlbfgscreatef(n, m, &x0, diffstep, &state, _state); - minlbfgssetcond(&state, (double)(0), (double)(0), 1.0E-9, 50, _state); - minlbfgsoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminlbfgsunit_maxoptguardlevel, _state), _state); - while(minlbfgsiteration(&state, _state)) - { - if( state.needf ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.f = state.f+ae_fabs(v, _state); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minlbfgsresults(&state, &x1, &rep, _state); - minlbfgsoptguardresults(&state, &ogrep, _state); - - /* - * Check basic properties of the solution - */ - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1650"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1651"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check OptGuard report: distinguish between "hard" - * failures which result in immediate termination - * (C0 violation being reported) and "soft" ones - * (C1 violation is NOT reported) which accumulate - * until we exhaust limit. - */ - ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminlbfgsunit.ap:1662"); - ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1663"); - failed = ae_false; - failed = failed||optguardallclear(&ogrep, _state); - failed = failed||!ogrep.nonc1suspected; - failed = failed||ogrep.nonc1fidx!=0; - if( failed ) - { - inc(&failurecounter, _state); - } - } - ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testminlbfgsunit.ap:1671"); - - /* - * Make sure than no false positives are reported for larger - * problems where numerical noise can be an issue: - * * N=100 dimensions - * * positive-definite quadratic programming problem - * * upper limit on iterations count, MaxIts=25 - * We simply test that OptGuard does not return error code. - */ - n = 100; - m = 5; - spdmatrixrndcond(n, 1.0E2, &a, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - x0.ptr.p_double[i] = ae_pow(2.0, hqrndnormal(&rs, _state), _state); - } - minlbfgscreate(n, m, &x0, &state, _state); - minlbfgsoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminlbfgsunit_maxoptguardlevel, _state), _state); - minlbfgssetcond(&state, (double)(0), (double)(0), 1.0E-9, 25, _state); - while(minlbfgsiteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.g.ptr.p_double[i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.f = state.f+0.5*state.x.ptr.p_double[i]*a.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.g.ptr.p_double[i] = state.g.ptr.p_double[i]+a.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minlbfgsresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1715"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1716"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - minlbfgsoptguardresults(&state, &ogrep, _state); - ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1720"); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests report of "non-C1" test #0 for task #0 -given by matrix A. - -On failure sets error flag. -*************************************************************************/ -static void testminlbfgsunit_testoptguardc1test0reportfortask0(ae_bool* err, - optguardnonc1test0report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double vv; - double va; - double vb; - ae_bool hasc1discontinuities; - - - if( rep->positive ) - { - - /* - * Check positive report, first checks - */ - ae_set_error_flag(err, rep->fidx!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1747"); - ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testminlbfgsunit.ap:1748"); - ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testminlbfgsunit.ap:1749"); - ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testminlbfgsunit.ap:1750"); - ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testminlbfgsunit.ap:1751"); - ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testminlbfgsunit.ap:1752"); - ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testminlbfgsunit.ap:1753"); - ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testminlbfgsunit.ap:1754"); - ae_set_error_flag(err, rep->f.cnt!=rep->cnt, __FILE__, __LINE__, "testminlbfgsunit.ap:1755"); - ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1756"); - ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1757"); - ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1758"); - ae_set_error_flag(err, !isfinitevector(&rep->f, rep->cnt, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1759"); - if( *err ) - { - return; - } - - /* - * Check consistency of X0, D, Stp and F - */ - for(k=0; k<=rep->cnt-2; k++) - { - ae_set_error_flag(err, ae_fp_greater_eq(rep->stp.ptr.p_double[k],rep->stp.ptr.p_double[k+1]), __FILE__, __LINE__, "testminlbfgsunit.ap:1767"); - } - for(k=0; k<=rep->cnt-1; k++) - { - v = (double)(0); - for(i=0; i<=n-1; i++) - { - vv = (double)(0); - for(j=0; j<=n-1; j++) - { - vv = vv+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[k]); - } - v = v+ae_fabs(vv, _state); - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-rep->f.ptr.p_double[k], _state),1.0E-6*ae_maxreal(ae_fabs(v, _state), (double)(1), _state)), __FILE__, __LINE__, "testminlbfgsunit.ap:1780"); - } - - /* - * Check that interval [#StpIdxA,#StpIdxB] contains at least one discontinuity - */ - hasc1discontinuities = ae_false; - for(i=0; i<=n-1; i++) - { - va = (double)(0); - vb = (double)(0); - for(j=0; j<=n-1; j++) - { - va = va+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxa]); - vb = vb+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxb]); - } - hasc1discontinuities = hasc1discontinuities||ae_sign(va, _state)!=ae_sign(vb, _state); - } - ae_set_error_flag(err, !hasc1discontinuities, __FILE__, __LINE__, "testminlbfgsunit.ap:1798"); - } - else - { - - /* - * Check negative report: fields must be empty - */ - ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1805"); - ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1806"); - ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1807"); - ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1808"); - ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1809"); - ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1810"); - ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1811"); - ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1812"); - ae_set_error_flag(err, rep->f.cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1813"); - } -} - - -/************************************************************************* -This function tests report of "non-C1" test #1 for task #0 -given by matrix A. - -On failure sets error flag. -*************************************************************************/ -static void testminlbfgsunit_testoptguardc1test1reportfortask0(ae_bool* err, - optguardnonc1test1report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double vv; - double va; - double vb; - ae_bool tooclose; - ae_bool hasc1discontinuities; - - - if( rep->positive ) - { - - /* - * Check positive report, first checks - */ - ae_set_error_flag(err, rep->fidx!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1841"); - ae_set_error_flag(err, rep->vidx<0, __FILE__, __LINE__, "testminlbfgsunit.ap:1842"); - ae_set_error_flag(err, rep->vidx>n, __FILE__, __LINE__, "testminlbfgsunit.ap:1843"); - ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testminlbfgsunit.ap:1844"); - ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testminlbfgsunit.ap:1845"); - ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testminlbfgsunit.ap:1846"); - ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testminlbfgsunit.ap:1847"); - ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testminlbfgsunit.ap:1848"); - ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testminlbfgsunit.ap:1849"); - ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testminlbfgsunit.ap:1850"); - ae_set_error_flag(err, rep->g.cnt!=rep->cnt, __FILE__, __LINE__, "testminlbfgsunit.ap:1851"); - ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1852"); - ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1853"); - ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1854"); - ae_set_error_flag(err, !isfinitevector(&rep->g, rep->cnt, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1855"); - if( *err ) - { - return; - } - - /* - * Check consistency of X0, D, Stp and G - */ - for(k=0; k<=rep->cnt-2; k++) - { - ae_set_error_flag(err, ae_fp_greater_eq(rep->stp.ptr.p_double[k],rep->stp.ptr.p_double[k+1]), __FILE__, __LINE__, "testminlbfgsunit.ap:1863"); - } - for(k=0; k<=rep->cnt-1; k++) - { - v = (double)(0); - tooclose = ae_false; - for(i=0; i<=n-1; i++) - { - vv = (double)(0); - for(j=0; j<=n-1; j++) - { - vv = vv+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[k]); - } - v = v+ae_sign(vv, _state)*a->ptr.pp_double[i][rep->vidx]; - tooclose = tooclose||ae_fp_less(ae_fabs(vv, _state),1.0E-4); - } - if( !tooclose ) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-rep->g.ptr.p_double[k], _state),1.0E-6*ae_maxreal(ae_fabs(v, _state), (double)(1), _state)), __FILE__, __LINE__, "testminlbfgsunit.ap:1877"); - } - } - - /* - * Check that interval [#StpIdxA,#StpIdxB] contains at least one discontinuity - */ - tooclose = ae_false; - hasc1discontinuities = ae_false; - for(i=0; i<=n-1; i++) - { - va = (double)(0); - vb = (double)(0); - for(j=0; j<=n-1; j++) - { - va = va+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxa]); - vb = vb+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxb]); - } - tooclose = (tooclose||ae_fp_less(ae_fabs(va, _state),1.0E-8))||ae_fp_less(ae_fabs(vb, _state),1.0E-8); - hasc1discontinuities = hasc1discontinuities||ae_sign(va, _state)!=ae_sign(vb, _state); - } - if( !tooclose ) - { - ae_set_error_flag(err, !hasc1discontinuities, __FILE__, __LINE__, "testminlbfgsunit.ap:1898"); - } - } - else - { - - /* - * Check negative report: fields must be empty - */ - ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1905"); - ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1906"); - ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1907"); - ae_set_error_flag(err, rep->vidx!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1908"); - ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1909"); - ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1910"); - ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1911"); - ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1912"); - ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1913"); - ae_set_error_flag(err, rep->g.cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1914"); - } -} - - - - - - - - -ae_bool testnormestimator(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - double tol; - ae_int_t maxmn; - ae_int_t m; - ae_int_t n; - ae_int_t pass; - ae_int_t passcount; - ae_matrix a; - ae_vector rowsizes; - sparsematrix s; - double snorm; - double enorm; - double enorm2; - ae_int_t nbetter; - double sigma; - ae_int_t i; - ae_int_t j; - normestimatorstate e; - normestimatorstate e2; - ae_bool waserrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&rowsizes, 0, sizeof(rowsizes)); - memset(&s, 0, sizeof(s)); - memset(&e, 0, sizeof(e)); - memset(&e2, 0, sizeof(e2)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rowsizes, 0, DT_INT, _state, ae_true); - _sparsematrix_init(&s, _state, ae_true); - _normestimatorstate_init(&e, _state, ae_true); - _normestimatorstate_init(&e2, _state, ae_true); - - tol = 0.01; - maxmn = 5; - waserrors = ae_false; - - /* - * First test: algorithm must correctly determine matrix norm - */ - for(m=1; m<=maxmn; m++) - { - for(n=1; n<=maxmn; n++) - { - - /* - * Create estimator with quite large NStart and NIts. - * It should guarantee that we converge to the correct solution. - */ - normestimatorcreate(m, n, 15, 15, &e, _state); - - /* - * Try with zero A first - */ - sparsecreate(m, n, 1, &s, _state); - sparseconverttocrs(&s, _state); - normestimatorestimatesparse(&e, &s, _state); - normestimatorresults(&e, &enorm, _state); - waserrors = waserrors||ae_fp_neq(enorm,(double)(0)); - - /* - * Choose random norm, try with non-zero matrix - * with specified norm. - */ - snorm = ae_exp(10*ae_randomreal(_state)-5, _state); - sparsecreate(m, n, 1, &s, _state); - if( m>=n ) - { - - /* - * Generate random orthogonal M*M matrix, - * use N leading columns as columns of A - */ - rmatrixrndorthogonal(m, &a, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - sparseset(&s, i, j, snorm*a.ptr.pp_double[i][j], _state); - } - } - } - else - { - - /* - * Generate random orthogonal N*N matrix, - * use M leading rows as rows of A - */ - rmatrixrndorthogonal(n, &a, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - sparseset(&s, i, j, snorm*a.ptr.pp_double[i][j], _state); - } - } - } - sparseconverttocrs(&s, _state); - normestimatorestimatesparse(&e, &s, _state); - normestimatorresults(&e, &enorm, _state); - waserrors = (waserrors||ae_fp_greater(enorm,snorm*(1+tol)))||ae_fp_less(enorm,snorm*(1-tol)); - } - } - - /* - * NStart=10 should give statistically better results than NStart=1. - * In order to test it we perform PassCount attempts to solve random - * problem by means of two estimators: one with NStart=10 and another - * one with NStart=1. Every time we compare two estimates and choose - * better one. - * - * Random variable NBetter is a number of cases when NStart=10 was better. - * Under null hypothesis (no difference) it is binomially distributed - * with mean PassCount/2 and variance PassCount/4. However, we expect - * to have significant deviation to the right, in the area of larger - * values. - * - * NOTE: we use fixed N because this test is independent of problem size. - */ - n = 3; - normestimatorcreate(n, n, 1, 1, &e, _state); - normestimatorcreate(n, n, 10, 1, &e2, _state); - normestimatorsetseed(&e, 0, _state); - normestimatorsetseed(&e2, 0, _state); - nbetter = 0; - passcount = 2000; - sigma = 5.0; - for(pass=1; pass<=passcount; pass++) - { - snorm = ae_pow(10.0, 2*ae_randomreal(_state)-1, _state); - sparsecreate(n, n, 1, &s, _state); - rmatrixrndcond(n, 2.0, &a, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - sparseset(&s, i, j, snorm*a.ptr.pp_double[i][j], _state); - } - } - sparseconverttocrs(&s, _state); - normestimatorestimatesparse(&e, &s, _state); - normestimatorresults(&e, &enorm, _state); - normestimatorestimatesparse(&e2, &s, _state); - normestimatorresults(&e2, &enorm2, _state); - if( ae_fp_less(ae_fabs(enorm2-snorm, _state),ae_fabs(enorm-snorm, _state)) ) - { - nbetter = nbetter+1; - } - } - waserrors = waserrors||ae_fp_less((double)(nbetter),0.5*passcount+sigma*ae_sqrt(0.25*passcount, _state)); - - /* - * Same as previous one (for NStart), but tests dependence on NIts. - */ - n = 3; - normestimatorcreate(n, n, 1, 1, &e, _state); - normestimatorcreate(n, n, 1, 10, &e2, _state); - normestimatorsetseed(&e, 0, _state); - normestimatorsetseed(&e2, 0, _state); - nbetter = 0; - passcount = 2000; - sigma = 5.0; - for(pass=1; pass<=passcount; pass++) - { - snorm = ae_pow(10.0, 2*ae_randomreal(_state)-1, _state); - sparsecreate(n, n, 1, &s, _state); - rmatrixrndcond(n, 2.0, &a, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - sparseset(&s, i, j, snorm*a.ptr.pp_double[i][j], _state); - } - } - sparseconverttocrs(&s, _state); - normestimatorestimatesparse(&e, &s, _state); - normestimatorresults(&e, &enorm, _state); - normestimatorestimatesparse(&e2, &s, _state); - normestimatorresults(&e2, &enorm2, _state); - if( ae_fp_less(ae_fabs(enorm2-snorm, _state),ae_fabs(enorm-snorm, _state)) ) - { - nbetter = nbetter+1; - } - } - waserrors = waserrors||ae_fp_less((double)(nbetter),0.5*passcount+sigma*ae_sqrt(0.25*passcount, _state)); - - /* - * report - */ - if( !silent ) - { - printf("TESTING NORM ESTIMATOR\n"); - printf("TEST: "); - if( !waserrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - - -static double testlinlsqrunit_e0 = 1.0E-6; -static double testlinlsqrunit_tolort = 1.0E-4; -static double testlinlsqrunit_emergencye0 = 1.0E-12; -static ae_bool testlinlsqrunit_svdtest(ae_bool silent, ae_state *_state); -static ae_bool testlinlsqrunit_mwcranksvdtest(ae_bool silent, - ae_state *_state); -static ae_bool testlinlsqrunit_mwicranksvdtest(ae_bool silent, - ae_state *_state); -static ae_bool testlinlsqrunit_bidiagonaltest(ae_bool silent, - ae_state *_state); -static ae_bool testlinlsqrunit_zeromatrixtest(ae_bool silent, - ae_state *_state); -static ae_bool testlinlsqrunit_reportcorrectnesstest(ae_bool silent, - ae_state *_state); -static ae_bool testlinlsqrunit_stoppingcriteriatest(ae_bool silent, - ae_state *_state); -static ae_bool testlinlsqrunit_analytictest(ae_bool silent, - ae_state *_state); -static void testlinlsqrunit_testterminationrequests(ae_bool* err, - ae_state *_state); -static ae_bool testlinlsqrunit_isitgoodsolution(/* Real */ ae_matrix* a, - /* Real */ ae_vector* b, - ae_int_t m, - ae_int_t n, - double lambdav, - /* Real */ ae_vector* x, - double epserr, - double epsort, - ae_state *_state); -static ae_bool testlinlsqrunit_preconditionertest(ae_state *_state); - - - - - -ae_bool testlinlsqr(ae_bool silent, ae_state *_state) -{ - ae_bool svdtesterrors; - ae_bool mwcranksvderr; - ae_bool mwicranksvderr; - ae_bool bidiagonalerr; - ae_bool zeromatrixerr; - ae_bool reportcorrectnesserr; - ae_bool stoppingcriteriaerr; - ae_bool analytictesterrors; - ae_bool prectesterrors; - ae_bool termreqerrors; - ae_bool waserrors; - ae_bool result; - - - termreqerrors = ae_false; - svdtesterrors = testlinlsqrunit_svdtest(ae_true, _state); - mwcranksvderr = testlinlsqrunit_mwcranksvdtest(ae_true, _state); - mwicranksvderr = testlinlsqrunit_mwicranksvdtest(ae_true, _state); - bidiagonalerr = testlinlsqrunit_bidiagonaltest(ae_true, _state); - zeromatrixerr = testlinlsqrunit_zeromatrixtest(ae_true, _state); - reportcorrectnesserr = testlinlsqrunit_reportcorrectnesstest(ae_true, _state); - stoppingcriteriaerr = testlinlsqrunit_stoppingcriteriatest(ae_true, _state); - analytictesterrors = testlinlsqrunit_analytictest(ae_true, _state); - prectesterrors = testlinlsqrunit_preconditionertest(_state); - testlinlsqrunit_testterminationrequests(&termreqerrors, _state); - - /* - * report - */ - waserrors = ((((((((svdtesterrors||mwcranksvderr)||mwicranksvderr)||bidiagonalerr)||zeromatrixerr)||reportcorrectnesserr)||stoppingcriteriaerr)||analytictesterrors)||prectesterrors)||termreqerrors; - if( !silent ) - { - printf("TESTING LinLSQR\n"); - printf("Different matrix types:\n"); - printf("* general M*N "); - if( svdtesterrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* well conditioned M*N "); - if( mwcranksvderr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* rank deficient M*N "); - if( mwicranksvderr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* sparse bidiagonal "); - if( bidiagonalerr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* zero "); - if( zeromatrixerr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("Other properties:\n"); - printf("* report correctness "); - if( reportcorrectnesserr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* stopping criteria "); - if( stoppingcriteriaerr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* analytic properties "); - if( analytictesterrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* preconditioner test "); - if( prectesterrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* termination requests "); - if( termreqerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - - /* - *was errors? - */ - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - return result; -} - - -/************************************************************************* -This function generates random MxN problem, solves it with LSQR and -compares with results obtained from SVD solver. Matrix A is generated as -MxN matrix with uniformly distributed random entries, i.e. it has no -special properties (like conditioning or separation of singular values). - -We apply random amount regularization to our problem (from zero to large) -in order to test regularizer. Default stopping criteria are used. -Preconditioning is turned off because it skews results for rank-deficient -problems. - -INPUT: - Silent - if true then function output report - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testlinlsqrunit_svdtest(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - linlsqrstate s; - linlsqrreport rep; - sparsematrix spa; - ae_matrix a; - ae_vector b; - ae_vector x0; - ae_int_t szn; - ae_int_t szm; - ae_int_t n; - ae_int_t m; - double lambdai; - ae_int_t i; - ae_int_t j; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&spa, 0, sizeof(spa)); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - memset(&x0, 0, sizeof(x0)); - _linlsqrstate_init(&s, _state, ae_true); - _linlsqrreport_init(&rep, _state, ae_true); - _sparsematrix_init(&spa, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - - szm = 5; - szn = 5; - for(m=1; m<=szm; m++) - { - for(n=1; n<=szn; n++) - { - - /* - * Prepare MxN matrix A, right part B, lambda - */ - lambdai = ae_randomreal(_state); - ae_matrix_set_length(&a, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - sparsecreate(m, n, 1, &spa, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - sparseset(&spa, i, j, a.ptr.pp_double[i][j], _state); - } - } - sparseconverttocrs(&spa, _state); - ae_vector_set_length(&b, m, _state); - for(i=0; i<=m-1; i++) - { - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - - /* - * Solve by calling LinLSQRIteration - */ - linlsqrcreate(m, n, &s, _state); - linlsqrsetb(&s, &b, _state); - linlsqrsetlambdai(&s, lambdai, _state); - linlsqrsetprecunit(&s, _state); - while(linlsqriteration(&s, _state)) - { - if( s.needmv ) - { - for(i=0; i<=m-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - } - } - if( s.needmtv ) - { - for(i=0; i<=n-1; i++) - { - s.mtv.ptr.p_double[i] = (double)(0); - for(j=0; j<=m-1; j++) - { - s.mtv.ptr.p_double[i] = s.mtv.ptr.p_double[i]+a.ptr.pp_double[j][i]*s.x.ptr.p_double[j]; - } - } - } - } - linlsqrresults(&s, &x0, &rep, _state); - if( !testlinlsqrunit_isitgoodsolution(&a, &b, m, n, lambdai, &x0, testlinlsqrunit_e0, testlinlsqrunit_tolort, _state) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - *test LinLSQRRestart and LinLSQRSolveSparse - */ - linlsqrrestart(&s, _state); - linlsqrsolvesparse(&s, &spa, &b, _state); - linlsqrresults(&s, &x0, &rep, _state); - if( !testlinlsqrunit_isitgoodsolution(&a, &b, m, n, lambdai, &x0, testlinlsqrunit_e0, testlinlsqrunit_tolort, _state) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - if( !silent ) - { - printf("SVDTest::Ok\n"); - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -The test checks that algorithm can solve MxN (with N<=M) well-conditioned -problems - and can do so within exactly N iterations. We use moderate -condition numbers, from 1.0 to 10.0, because larger condition number may -require several additional iterations to converge. - -We try different scalings of the A and B. - -INPUT: - Silent - if true then function does not outputs results to console - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testlinlsqrunit_mwcranksvdtest(ae_bool silent, - ae_state *_state) -{ - ae_frame _frame_block; - linlsqrstate s; - linlsqrreport rep; - ae_matrix a; - ae_vector b; - double bnorm; - ae_vector x0; - ae_int_t szm; - ae_int_t n; - ae_int_t m; - ae_int_t ns0; - ae_int_t ns1; - ae_int_t nlambdai; - double s0; - double s1; - double lambdai; - double c; - ae_int_t i; - ae_int_t j; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - memset(&x0, 0, sizeof(x0)); - _linlsqrstate_init(&s, _state, ae_true); - _linlsqrreport_init(&rep, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - - szm = 5; - for(m=1; m<=szm; m++) - { - for(n=1; n<=m; n++) - { - for(nlambdai=0; nlambdai<=3; nlambdai++) - { - for(ns0=-1; ns0<=1; ns0++) - { - for(ns1=-1; ns1<=1; ns1++) - { - - /* - * Generate problem: - * * scale factors s0, s1 - * * MxN well conditioned A (with condition number C in [1,10] and norm s0) - * * regularization coefficient LambdaI - * * right part b, with |b|=s1 - */ - s0 = ae_pow((double)(10), (double)(10*ns0), _state); - s1 = ae_pow((double)(10), (double)(10*ns1), _state); - lambdai = (double)(0); - if( nlambdai==0 ) - { - lambdai = (double)(0); - } - if( nlambdai==1 ) - { - lambdai = s0/1000; - } - if( nlambdai==2 ) - { - lambdai = s0; - } - if( nlambdai==3 ) - { - lambdai = s0*1000; - } - c = (10-1)*ae_randomreal(_state)+1; - rmatrixrndcond(m, c, &a, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = s0*a.ptr.pp_double[i][j]; - } - } - ae_vector_set_length(&b, m, _state); - do - { - bnorm = (double)(0); - for(i=0; i<=m-1; i++) - { - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - bnorm = bnorm+b.ptr.p_double[i]*b.ptr.p_double[i]; - } - bnorm = ae_sqrt(bnorm, _state); - } - while(ae_fp_less_eq(bnorm,testlinlsqrunit_e0)); - for(i=0; i<=m-1; i++) - { - b.ptr.p_double[i] = b.ptr.p_double[i]*s1/bnorm; - } - - /* - * Solve by LSQR method - */ - linlsqrcreate(m, n, &s, _state); - linlsqrsetb(&s, &b, _state); - linlsqrsetcond(&s, (double)(0), (double)(0), n, _state); - linlsqrsetlambdai(&s, lambdai, _state); - while(linlsqriteration(&s, _state)) - { - if( s.needmv ) - { - for(i=0; i<=m-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - } - } - if( s.needmtv ) - { - for(i=0; i<=n-1; i++) - { - s.mtv.ptr.p_double[i] = (double)(0); - for(j=0; j<=m-1; j++) - { - s.mtv.ptr.p_double[i] = s.mtv.ptr.p_double[i]+a.ptr.pp_double[j][i]*s.x.ptr.p_double[j]; - } - } - } - } - linlsqrresults(&s, &x0, &rep, _state); - if( !testlinlsqrunit_isitgoodsolution(&a, &b, m, n, lambdai, &x0, testlinlsqrunit_e0, testlinlsqrunit_tolort, _state) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -The test checks that algorithm can find a solution with minimum norm for a -singular rectangular problem. System matrix has special property - singular -values are either zero or well separated from zero. - -INPUT: - Silent - if true then function output report - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testlinlsqrunit_mwicranksvdtest(ae_bool silent, - ae_state *_state) -{ - ae_frame _frame_block; - linlsqrstate s; - linlsqrreport rep; - sparsematrix spa; - ae_vector b; - double bnorm; - ae_vector x0; - ae_int_t szm; - ae_int_t n; - ae_int_t m; - ae_int_t nz; - ae_int_t ns0; - ae_int_t ns1; - ae_int_t nlambdai; - double s0; - double s1; - double lambdai; - ae_int_t i; - ae_int_t j; - ae_matrix a; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&spa, 0, sizeof(spa)); - memset(&b, 0, sizeof(b)); - memset(&x0, 0, sizeof(x0)); - memset(&a, 0, sizeof(a)); - _linlsqrstate_init(&s, _state, ae_true); - _linlsqrreport_init(&rep, _state, ae_true); - _sparsematrix_init(&spa, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - - result = ae_false; - szm = 5; - for(m=1; m<=szm; m++) - { - for(n=1; n<=m; n++) - { - for(nlambdai=0; nlambdai<=2; nlambdai++) - { - for(ns0=-1; ns0<=1; ns0++) - { - for(ns1=-1; ns1<=1; ns1++) - { - for(nz=0; nz<=n-1; nz++) - { - - /* - * Generate problem: - * * scale coefficients s0, s1 - * * regularization coefficient LambdaI - * * MxN matrix A, norm(A)=s0, with NZ zero singular values and N-NZ nonzero ones - * * right part b with norm(b)=s1 - */ - s0 = ae_pow((double)(10), (double)(10*ns0), _state); - s1 = ae_pow((double)(10), (double)(10*ns1), _state); - lambdai = (double)(0); - if( nlambdai==0 ) - { - lambdai = (double)(0); - } - if( nlambdai==1 ) - { - lambdai = s0; - } - if( nlambdai==2 ) - { - lambdai = s0*1000; - } - ae_matrix_set_length(&a, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=n-nz-1; i++) - { - a.ptr.pp_double[i][i] = s0*(0.1+0.9*ae_randomreal(_state)); - } - rmatrixrndorthogonalfromtheleft(&a, m, n, _state); - rmatrixrndorthogonalfromtheright(&a, m, n, _state); - ae_vector_set_length(&b, m, _state); - do - { - bnorm = (double)(0); - for(i=0; i<=m-1; i++) - { - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - bnorm = bnorm+b.ptr.p_double[i]*b.ptr.p_double[i]; - } - bnorm = ae_sqrt(bnorm, _state); - } - while(ae_fp_less_eq(bnorm,testlinlsqrunit_e0)); - for(i=0; i<=m-1; i++) - { - b.ptr.p_double[i] = b.ptr.p_double[i]*s1/bnorm; - } - - /* - * Solve by LSQR method - */ - linlsqrcreate(m, n, &s, _state); - linlsqrsetb(&s, &b, _state); - linlsqrsetcond(&s, testlinlsqrunit_emergencye0, testlinlsqrunit_emergencye0, n, _state); - linlsqrsetlambdai(&s, lambdai, _state); - while(linlsqriteration(&s, _state)) - { - if( s.needmv ) - { - for(i=0; i<=m-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - } - } - if( s.needmtv ) - { - for(i=0; i<=n-1; i++) - { - s.mtv.ptr.p_double[i] = (double)(0); - for(j=0; j<=m-1; j++) - { - s.mtv.ptr.p_double[i] = s.mtv.ptr.p_double[i]+a.ptr.pp_double[j][i]*s.x.ptr.p_double[j]; - } - } - } - } - linlsqrresults(&s, &x0, &rep, _state); - - /* - * Check - */ - if( !testlinlsqrunit_isitgoodsolution(&a, &b, m, n, lambdai, &x0, testlinlsqrunit_e0, testlinlsqrunit_tolort, _state) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -The test does check, that algorithm can find a solution with minimum norm, -if a problem has bidiagonal matrix on diagonals of a lot of zeros. This -problem has to lead to case when State.Alpha and State.Beta are zero, and we -we can be sure that the algorithm correctly handles it. - -We do not use iteration count as stopping condition, because problem can -be degenerate and we may need more than N iterations to converge. - -INPUT: - Silent - if true then function output report - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testlinlsqrunit_bidiagonaltest(ae_bool silent, - ae_state *_state) -{ - ae_frame _frame_block; - linlsqrstate s; - linlsqrreport rep; - ae_matrix a; - ae_vector b; - double bnorm; - ae_vector x0; - ae_int_t sz; - ae_int_t n; - ae_int_t m; - ae_int_t minmn; - ae_int_t ns0; - ae_int_t ns1; - double s0; - double s1; - ae_int_t i; - ae_int_t j; - ae_int_t p; - ae_int_t diag; - double pz; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - memset(&x0, 0, sizeof(x0)); - _linlsqrstate_init(&s, _state, ae_true); - _linlsqrreport_init(&rep, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - - sz = 5; - for(m=1; m<=sz; m++) - { - for(n=1; n<=sz; n++) - { - minmn = ae_minint(m, n, _state); - for(p=0; p<=2; p++) - { - for(ns0=-1; ns0<=1; ns0++) - { - for(ns1=-1; ns1<=1; ns1++) - { - for(diag=0; diag<=1; diag++) - { - - /* - * Generate problem: - * * scaling coefficients s0, s1 - * * bidiagonal A, with probability of having zero element at diagonal equal to PZ - */ - s0 = ae_pow((double)(10), (double)(10*ns0), _state); - s1 = ae_pow((double)(10), (double)(10*ns1), _state); - pz = 0.0; - if( p==0 ) - { - pz = 0.25; - } - if( p==1 ) - { - pz = 0.5; - } - if( p==2 ) - { - pz = 0.75; - } - ae_matrix_set_length(&a, m, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=minmn-1; i++) - { - if( ae_fp_greater_eq(ae_randomreal(_state),pz) ) - { - a.ptr.pp_double[i][i] = 2*ae_randomreal(_state)-1; - } - } - for(i=1; i<=minmn-1; i++) - { - if( ae_fp_greater_eq(ae_randomreal(_state),pz) ) - { - if( diag==0 ) - { - a.ptr.pp_double[i-1][i] = 2*ae_randomreal(_state)-1; - } - if( diag==1 ) - { - a.ptr.pp_double[i][i-1] = 2*ae_randomreal(_state)-1; - } - } - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = s0*a.ptr.pp_double[i][j]; - } - } - ae_vector_set_length(&b, m, _state); - do - { - bnorm = (double)(0); - for(i=0; i<=m-1; i++) - { - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - bnorm = bnorm+b.ptr.p_double[i]*b.ptr.p_double[i]; - } - bnorm = ae_sqrt(bnorm, _state); - } - while(ae_fp_less_eq(bnorm,testlinlsqrunit_e0)); - for(i=0; i<=m-1; i++) - { - b.ptr.p_double[i] = b.ptr.p_double[i]*s1/bnorm; - } - - /* - * LSQR solution - */ - linlsqrcreate(m, n, &s, _state); - linlsqrsetb(&s, &b, _state); - linlsqrsetcond(&s, testlinlsqrunit_e0, testlinlsqrunit_e0, 0, _state); - while(linlsqriteration(&s, _state)) - { - if( s.needmv ) - { - for(i=0; i<=m-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - } - } - if( s.needmtv ) - { - for(i=0; i<=n-1; i++) - { - s.mtv.ptr.p_double[i] = (double)(0); - for(j=0; j<=m-1; j++) - { - s.mtv.ptr.p_double[i] = s.mtv.ptr.p_double[i]+a.ptr.pp_double[j][i]*s.x.ptr.p_double[j]; - } - } - } - } - linlsqrresults(&s, &x0, &rep, _state); - - /* - * Check - */ - if( !testlinlsqrunit_isitgoodsolution(&a, &b, m, n, 0.0, &x0, testlinlsqrunit_e0, testlinlsqrunit_tolort, _state) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -The test does check, that algorithm correctly solves a problem in cases: - 1. A=0, B<>0; - 2. A<>0, B=0; - 3. A=0, B=0. -If some part is not zero then it filled with ones. - -INPUT: - Silent - if true then function output report - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testlinlsqrunit_zeromatrixtest(ae_bool silent, - ae_state *_state) -{ - ae_frame _frame_block; - linlsqrstate s; - linlsqrreport rep; - ae_matrix a; - ae_vector b; - ae_vector x0; - ae_int_t sz; - ae_int_t n; - ae_int_t m; - ae_int_t i; - ae_int_t j; - ae_int_t nzeropart; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - memset(&x0, 0, sizeof(x0)); - _linlsqrstate_init(&s, _state, ae_true); - _linlsqrreport_init(&rep, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - - sz = 5; - result = ae_false; - for(m=1; m<=sz; m++) - { - for(n=1; n<=sz; n++) - { - for(nzeropart=0; nzeropart<=2; nzeropart++) - { - - /* - * Initialize A, b - */ - ae_matrix_set_length(&a, m, n, _state); - if( nzeropart==0||nzeropart==2 ) - { - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - } - else - { - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(1); - } - } - } - ae_vector_set_length(&b, m, _state); - if( nzeropart==1||nzeropart==2 ) - { - for(i=0; i<=m-1; i++) - { - b.ptr.p_double[i] = (double)(0); - } - } - else - { - for(i=0; i<=m-1; i++) - { - b.ptr.p_double[i] = (double)(1); - } - } - - /* - * LSQR - */ - linlsqrcreate(m, n, &s, _state); - linlsqrsetb(&s, &b, _state); - linlsqrsetcond(&s, (double)(0), (double)(0), n, _state); - while(linlsqriteration(&s, _state)) - { - if( s.needmv ) - { - for(i=0; i<=m-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - } - } - if( s.needmtv ) - { - for(i=0; i<=n-1; i++) - { - s.mtv.ptr.p_double[i] = (double)(0); - for(j=0; j<=m-1; j++) - { - s.mtv.ptr.p_double[i] = s.mtv.ptr.p_double[i]+a.ptr.pp_double[j][i]*s.x.ptr.p_double[j]; - } - } - } - } - linlsqrresults(&s, &x0, &rep, _state); - - /* - * Check - */ - if( !testlinlsqrunit_isitgoodsolution(&a, &b, m, n, 0.0, &x0, testlinlsqrunit_e0, testlinlsqrunit_tolort, _state) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -The test does check, that algorithm correctly displays a progress report. - -INPUT: - Silent - if true then function output report - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testlinlsqrunit_reportcorrectnesstest(ae_bool silent, - ae_state *_state) -{ - ae_frame _frame_block; - linlsqrstate s; - linlsqrreport rep; - ae_matrix a; - ae_matrix u; - ae_matrix v; - ae_vector w; - ae_vector b; - ae_vector x0; - ae_vector firstx; - ae_vector lastx; - double rnorm; - double tnorm; - ae_int_t sz; - ae_int_t n; - ae_int_t m; - ae_int_t lambdai; - double mn; - double mx; - double c; - ae_int_t i; - ae_int_t j; - ae_int_t its; - double tmp; - double eps; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&a, 0, sizeof(a)); - memset(&u, 0, sizeof(u)); - memset(&v, 0, sizeof(v)); - memset(&w, 0, sizeof(w)); - memset(&b, 0, sizeof(b)); - memset(&x0, 0, sizeof(x0)); - memset(&firstx, 0, sizeof(firstx)); - memset(&lastx, 0, sizeof(lastx)); - _linlsqrstate_init(&s, _state, ae_true); - _linlsqrreport_init(&rep, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&firstx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&lastx, 0, DT_REAL, _state, ae_true); - - eps = 0.001; - sz = 5; - mn = (double)(-100); - mx = (double)(100); - c = (double)(100); - result = ae_false; - for(m=1; m<=sz; m++) - { - for(n=1; n<=m; n++) - { - for(lambdai=0; lambdai<=1; lambdai++) - { - its = -1; - - /* - *initialize matrix A - */ - spdmatrixrndcond(m+n, c, &a, _state); - for(i=m; i<=m+n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i-m==j ) - { - a.ptr.pp_double[i][j] = (double)(lambdai); - } - else - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - } - - /* - *initialize b - */ - ae_vector_set_length(&b, m+n, _state); - rnorm = (double)(0); - for(i=0; i<=m+n-1; i++) - { - if( imaxits||rep.terminationtype<=0 ) - { - if( !silent ) - { - printf("StoppingCriteriaTest::Fail\n"); - printf("N=%0d\n", - (int)(n)); - printf("IterationsCount=%0d\n", - (int)(rep.iterationscount)); - printf("NMV=%0d\n", - (int)(rep.nmv)); - printf("TerminationType=%0d\n", - (int)(rep.terminationtype)); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Test EpsB. - * Set EpsB=eps, check that |r|=2) and using first N-1 columns as rectangular - * system matrix, and sum of all columns with random non-zero coefficients - * as right part. - */ - for(n=2; n<=sz; n++) - { - for(k0=-1; k0<=1; k0++) - { - for(k1=-1; k1<=1; k1++) - { - - /* - * Initialize A with non-unit norm 10^(10*K0), b with non-unit norm 10^(10*K1) - */ - anorm = ae_pow((double)(10), (double)(10*k0), _state); - rmatrixrndorthogonal(n, &a, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = anorm*a.ptr.pp_double[i][j]; - } - } - ae_vector_set_length(&b, n, _state); - for(j=0; j<=n-1; j++) - { - b.ptr.p_double[j] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - tmp = 1+ae_randomreal(_state); - ae_v_addd(&b.ptr.p_double[0], 1, &a.ptr.pp_double[0][i], a.stride, ae_v_len(0,n-1), tmp); - } - tmp = (double)(0); - for(i=0; i<=n-1; i++) - { - tmp = tmp+ae_sqr(b.ptr.p_double[i], _state); - } - tmp = ae_pow((double)(10), (double)(10*k1), _state)/ae_sqrt(tmp, _state); - ae_v_muld(&b.ptr.p_double[0], 1, ae_v_len(0,n-1), tmp); - - /* - * Test EpsA - * - * NOTE: it is guaranteed that algorithm will terminate with correct - * TerminationType because other stopping criteria (EpsB) won't be satisfied - * on such system. - */ - eps = ae_pow((double)(10), (double)(-(2+ae_randominteger(3, _state))), _state); - epsmod = 1.1*eps; - linlsqrcreate(n, n-1, &s, _state); - linlsqrsetb(&s, &b, _state); - linlsqrsetcond(&s, eps, (double)(0), 0, _state); - while(linlsqriteration(&s, _state)) - { - if( s.needmv ) - { - for(i=0; i<=n-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-2; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - } - } - if( s.needmtv ) - { - for(i=0; i<=n-2; i++) - { - s.mtv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mtv.ptr.p_double[i] = s.mtv.ptr.p_double[i]+a.ptr.pp_double[j][i]*s.x.ptr.p_double[j]; - } - } - } - } - linlsqrresults(&s, &x0, &rep, _state); - - /* - * Check condition - */ - ae_vector_set_length(&rk, n, _state); - ae_vector_set_length(&ark, n-1, _state); - rknorm = (double)(0); - for(i=0; i<=n-1; i++) - { - rk.ptr.p_double[i] = b.ptr.p_double[i]; - for(j=0; j<=n-2; j++) - { - rk.ptr.p_double[i] = rk.ptr.p_double[i]-a.ptr.pp_double[i][j]*x0.ptr.p_double[j]; - } - rknorm = rknorm+ae_sqr(rk.ptr.p_double[i], _state); - } - rknorm = ae_sqrt(rknorm, _state); - arknorm = (double)(0); - for(i=0; i<=n-2; i++) - { - ark.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - ark.ptr.p_double[i] = ark.ptr.p_double[i]+a.ptr.pp_double[j][i]*rk.ptr.p_double[j]; - } - arknorm = arknorm+ae_sqr(ark.ptr.p_double[i], _state); - } - arknorm = ae_sqrt(arknorm, _state); - if( ae_fp_greater(arknorm/(anorm*rknorm),epsmod)||rep.terminationtype!=4 ) - { - if( !silent ) - { - printf("StoppingCriteriaTest::Fail\n"); - printf("N=%0d\n", - (int)(n)); - printf("IterationsCount=%0d\n", - (int)(rep.iterationscount)); - printf("NMV=%0d\n", - (int)(rep.nmv)); - printf("TerminationType=%0d\n", - (int)(rep.terminationtype)); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - if( !silent ) - { - printf("StoppingCriteriaTest::Ok\n"); - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This test compares LSQR for original system A*x=b against CG for a -modified system (A'*A)x = A*b. Both algorithms should give same sequences -of trial points (under exact arithmetics, or for very good conditioned -systems). - -INPUT: - Silent - if true then function does not output report - - -- ALGLIB -- - Copyright 30.11.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testlinlsqrunit_analytictest(ae_bool silent, - ae_state *_state) -{ - ae_frame _frame_block; - linlsqrstate s; - linlsqrreport rep; - ae_matrix a; - ae_matrix xk; - ae_matrix ap; - ae_matrix r; - ae_vector b; - ae_vector tmp; - ae_int_t n; - ae_int_t m; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t smallk; - ae_int_t pointsstored; - double v; - double tol; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&a, 0, sizeof(a)); - memset(&xk, 0, sizeof(xk)); - memset(&ap, 0, sizeof(ap)); - memset(&r, 0, sizeof(r)); - memset(&b, 0, sizeof(b)); - memset(&tmp, 0, sizeof(tmp)); - _linlsqrstate_init(&s, _state, ae_true); - _linlsqrreport_init(&rep, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xk, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ap, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&r, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - - - /* - * Set: - * * SmallK - number of steps to check, must be small number in order - * to reduce influence of the rounding errors - * * Tol - error tolerance for orthogonality/conjugacy criteria - */ - result = ae_false; - smallk = 4; - tol = 1.0E-7; - for(m=smallk; m<=smallk+5; m++) - { - for(n=smallk; n<=m; n++) - { - - /* - * Prepare problem: - * * MxN matrix A, Mx1 vector B - * * A is filled with random values from [-1,+1] - * * diagonal elements are filled with large positive values - * (should make system better conditioned) - */ - ae_matrix_set_length(&a, m, n, _state); - ae_vector_set_length(&b, m, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=n-1; i++) - { - a.ptr.pp_double[i][i] = 10*(1+ae_randomreal(_state)); - } - - /* - * Solve with LSQR, save trial points into XK[] array - */ - ae_matrix_set_length(&xk, smallk+1, n, _state); - linlsqrcreate(m, n, &s, _state); - linlsqrsetb(&s, &b, _state); - linlsqrsetcond(&s, (double)(0), (double)(0), smallk, _state); - linlsqrsetxrep(&s, ae_true, _state); - pointsstored = 0; - while(linlsqriteration(&s, _state)) - { - if( s.needmv ) - { - for(i=0; i<=m-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - } - } - if( s.needmtv ) - { - for(i=0; i<=n-1; i++) - { - s.mtv.ptr.p_double[i] = (double)(0); - for(j=0; j<=m-1; j++) - { - s.mtv.ptr.p_double[i] = s.mtv.ptr.p_double[i]+a.ptr.pp_double[j][i]*s.x.ptr.p_double[j]; - } - } - } - if( s.xupdated ) - { - ae_assert(pointsstoredj - * * (p[i]^T)*A'*A*p[j]=0 for i<>j - * where r[i]=(A'*A)*x[i]-A'*b is I-th residual , p[i] is I-th step. - * - * In order to test these criteria we generate two matrices: - * * (PointsStored-1)*M matrix AP (matrix of A*p products) - * * (PointsStored-1)*N matrix R (matrix of residuals) - * Then, we check that each matrix has orthogonal rows. - */ - ae_matrix_set_length(&ap, pointsstored-1, m, _state); - ae_matrix_set_length(&r, pointsstored-1, n, _state); - ae_vector_set_length(&tmp, m, _state); - for(k=0; k<=pointsstored-2; k++) - { - - /* - * Calculate K-th row of AP - */ - for(i=0; i<=m-1; i++) - { - ap.ptr.pp_double[k][i] = 0.0; - for(j=0; j<=n-1; j++) - { - ap.ptr.pp_double[k][i] = ap.ptr.pp_double[k][i]+a.ptr.pp_double[i][j]*(xk.ptr.pp_double[k+1][j]-xk.ptr.pp_double[k][j]); - } - } - - /* - * Calculate K-th row of R - */ - for(i=0; i<=m-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xk.ptr.pp_double[k][0], 1, ae_v_len(0,n-1)); - tmp.ptr.p_double[i] = v-b.ptr.p_double[i]; - } - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[0][j], a.stride, &tmp.ptr.p_double[0], 1, ae_v_len(0,m-1)); - r.ptr.pp_double[k][j] = v; - } - } - for(i=0; i<=pointsstored-2; i++) - { - for(j=0; j<=pointsstored-2; j++) - { - if( i!=j ) - { - v = ae_v_dotproduct(&ap.ptr.pp_double[i][0], 1, &ap.ptr.pp_double[j][0], 1, ae_v_len(0,m-1)); - result = result||ae_fp_greater(ae_fabs(v, _state),tol); - v = ae_v_dotproduct(&r.ptr.pp_double[i][0], 1, &r.ptr.pp_double[j][0], 1, ae_v_len(0,n-1)); - result = result||ae_fp_greater(ae_fabs(v, _state),tol); - } - } - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This test checks behavior of the termination requests. Sets error flag on -failure, leaves it unchanged on success. - - - -- ALGLIB -- - Copyright 16.11.2018 by Bochkanov Sergey -*************************************************************************/ -static void testlinlsqrunit_testterminationrequests(ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - linlsqrstate s; - linlsqrreport rep; - hqrndstate rs; - ae_int_t pass; - ae_matrix a; - ae_vector b; - ae_vector x1; - ae_int_t n; - ae_int_t m; - ae_int_t callsleft; - ae_int_t reportsafterrequest; - ae_bool firstpointreported; - ae_int_t i; - ae_int_t j; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&rs, 0, sizeof(rs)); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - memset(&x1, 0, sizeof(x1)); - _linlsqrstate_init(&s, _state, ae_true); - _linlsqrreport_init(&rep, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - - hqrndrandomize(&rs, _state); - for(pass=1; pass<=50; pass++) - { - - /* - * Prepare problem - */ - callsleft = 1+hqrnduniformi(&rs, 10, _state); - n = callsleft+100+hqrnduniformi(&rs, 50, _state); - m = n+hqrnduniformi(&rs, 50, _state); - ae_matrix_set_length(&a, m, n, _state); - ae_vector_set_length(&b, m, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - - /* - * Solve with LSQR, terminate after specified amount of A*x/A^T*x requests. - */ - linlsqrcreate(m, n, &s, _state); - linlsqrsetb(&s, &b, _state); - linlsqrsetcond(&s, (double)(0), (double)(0), n, _state); - linlsqrsetxrep(&s, ae_true, _state); - firstpointreported = ae_false; - reportsafterrequest = 0; - while(linlsqriteration(&s, _state)) - { - if( s.needmv ) - { - for(i=0; i<=m-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - } - if( firstpointreported ) - { - dec(&callsleft, _state); - } - if( callsleft==0 ) - { - linlsqrrequesttermination(&s, _state); - } - } - if( s.needmtv ) - { - for(i=0; i<=n-1; i++) - { - s.mtv.ptr.p_double[i] = (double)(0); - for(j=0; j<=m-1; j++) - { - s.mtv.ptr.p_double[i] = s.mtv.ptr.p_double[i]+a.ptr.pp_double[j][i]*s.x.ptr.p_double[j]; - } - } - if( firstpointreported ) - { - dec(&callsleft, _state); - } - if( callsleft==0 ) - { - linlsqrrequesttermination(&s, _state); - } - } - if( s.xupdated ) - { - firstpointreported = ae_true; - if( callsleft<=0 ) - { - inc(&reportsafterrequest, _state); - } - } - } - linlsqrresults(&s, &x1, &rep, _state); - ae_set_error_flag(err, rep.terminationtype!=8, __FILE__, __LINE__, "testlinlsqrunit.ap:1460"); - ae_set_error_flag(err, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testlinlsqrunit.ap:1461"); - ae_set_error_flag(err, reportsafterrequest!=1, __FILE__, __LINE__, "testlinlsqrunit.ap:1462"); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function compares solution calculated by LSQR with one calculated by -SVD solver. Following comparisons are performed: -1. either: - 1.a) residual norm |Rk| for LSQR solution is at most epsErr*|B| - 1.b) |A^T*Rk|/(|A|*|Rk|)<=EpsOrt -2. norm(LSQR_solution) is at most 1.2*norm(SVD_solution) - -Test (1) verifies that LSQR found good solution, test (2) verifies that -LSQR finds solution with close-to-minimum norm. We use factor as large as -1.2 to test deviation from SVD solution because LSQR is not very good at -solving degenerate problems. - -INPUT PARAMETERS: - A - array[M,N], system matrix - B - right part - M, N - problem size - LambdaV - regularization value for the problem, >=0 - X - array[N], solution found by LSQR - EpsErr - tolerance for |A*x-b| - EpsOrt - tolerance for |A^T*Rk|/(|A|*|Rk|) - -RESULT - True, for solution which passess all the tests -*************************************************************************/ -static ae_bool testlinlsqrunit_isitgoodsolution(/* Real */ ae_matrix* a, - /* Real */ ae_vector* b, - ae_int_t m, - ae_int_t n, - double lambdav, - /* Real */ ae_vector* x, - double epserr, - double epsort, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix svda; - ae_matrix u; - ae_matrix vt; - ae_vector w; - ae_vector svdx; - ae_vector tmparr; - ae_vector r; - ae_int_t i; - ae_int_t j; - ae_int_t minmn; - ae_bool svdresult; - double v; - double rnorm; - double bnorm; - double anorm; - double atrnorm; - double xnorm; - double svdxnorm; - ae_bool clause1holds; - ae_bool clause2holds; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&svda, 0, sizeof(svda)); - memset(&u, 0, sizeof(u)); - memset(&vt, 0, sizeof(vt)); - memset(&w, 0, sizeof(w)); - memset(&svdx, 0, sizeof(svdx)); - memset(&tmparr, 0, sizeof(tmparr)); - memset(&r, 0, sizeof(r)); - ae_matrix_init(&svda, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vt, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&svdx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmparr, 0, DT_REAL, _state, ae_true); - ae_vector_init(&r, 0, DT_REAL, _state, ae_true); - - - /* - * Solve regularized problem with SVD solver - */ - ae_matrix_set_length(&svda, m+n, n, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - svda.ptr.pp_double[i][j] = a->ptr.pp_double[i][j]; - } - } - for(i=m; i<=m+n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i-m==j ) - { - svda.ptr.pp_double[i][j] = lambdav; - } - else - { - svda.ptr.pp_double[i][j] = (double)(0); - } - } - } - svdresult = rmatrixsvd(&svda, m+n, n, 1, 1, 0, &w, &u, &vt, _state); - ae_assert(svdresult, "LINLSQR: internal error in unit test (SVD failed)", _state); - minmn = ae_minint(m, n, _state); - ae_vector_set_length(&svdx, n, _state); - ae_vector_set_length(&tmparr, minmn, _state); - for(i=0; i<=minmn-1; i++) - { - tmparr.ptr.p_double[i] = (double)(0); - for(j=0; j<=m-1; j++) - { - tmparr.ptr.p_double[i] = tmparr.ptr.p_double[i]+u.ptr.pp_double[j][i]*b->ptr.p_double[j]; - } - if( ae_fp_less_eq(w.ptr.p_double[i],ae_sqrt(ae_machineepsilon, _state)*w.ptr.p_double[0]) ) - { - tmparr.ptr.p_double[i] = (double)(0); - } - else - { - tmparr.ptr.p_double[i] = tmparr.ptr.p_double[i]/w.ptr.p_double[i]; - } - } - for(i=0; i<=n-1; i++) - { - svdx.ptr.p_double[i] = (double)(0); - for(j=0; j<=minmn-1; j++) - { - svdx.ptr.p_double[i] = svdx.ptr.p_double[i]+vt.ptr.pp_double[j][i]*tmparr.ptr.p_double[j]; - } - } - - /* - * Calculate residual, perform checks 1.a and 1.b: - * * first, we check 1.a - * * in case 1.a fails we check 1.b - */ - ae_vector_set_length(&r, m+n, _state); - for(i=0; i<=m+n-1; i++) - { - v = ae_v_dotproduct(&svda.ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - r.ptr.p_double[i] = v; - if( iptr.p_double[i]; - } - } - v = ae_v_dotproduct(&r.ptr.p_double[0], 1, &r.ptr.p_double[0], 1, ae_v_len(0,m+n-1)); - rnorm = ae_sqrt(v, _state); - v = ae_v_dotproduct(&b->ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,m-1)); - bnorm = ae_sqrt(v, _state); - if( ae_fp_less_eq(rnorm,epserr*bnorm) ) - { - - /* - * 1.a is true, no further checks is needed - */ - clause1holds = ae_true; - } - else - { - - /* - * 1.a is false, we have to check 1.b - * - * In order to do so, we calculate ||A|| and ||A^T*Rk||. We do - * not store product of A and Rk to some array, all we need is - * just one component of product at time, stored in V. - * - */ - anorm = (double)(0); - atrnorm = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=m+n-1; j++) - { - v = v+svda.ptr.pp_double[j][i]*r.ptr.p_double[j]; - anorm = anorm+ae_sqr(svda.ptr.pp_double[j][i], _state); - } - atrnorm = atrnorm+ae_sqr(v, _state); - } - anorm = ae_sqrt(anorm, _state); - atrnorm = ae_sqrt(atrnorm, _state); - clause1holds = ae_fp_eq(anorm*rnorm,(double)(0))||ae_fp_less_eq(atrnorm/(anorm*rnorm),epsort); - } - - /* - * Check (2). - * Here we assume that Result=True when we enter this block. - */ - v = ae_v_dotproduct(&x->ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1)); - xnorm = ae_sqrt(v, _state); - v = ae_v_dotproduct(&svdx.ptr.p_double[0], 1, &svdx.ptr.p_double[0], 1, ae_v_len(0,n-1)); - svdxnorm = ae_sqrt(v, _state); - clause2holds = ae_fp_less_eq(xnorm,1.2*svdxnorm); - - /* - * End - */ - result = clause1holds&&clause2holds; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Function for testing preconditioned LSQR method. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testlinlsqrunit_preconditionertest(ae_state *_state) -{ - ae_frame _frame_block; - linlsqrstate s; - linlsqrreport rep; - ae_matrix a; - ae_matrix ta; - sparsematrix sa; - ae_vector b; - ae_vector d; - ae_vector xe; - ae_vector x0; - ae_bool bflag; - ae_int_t i; - ae_int_t j; - ae_int_t n; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&a, 0, sizeof(a)); - memset(&ta, 0, sizeof(ta)); - memset(&sa, 0, sizeof(sa)); - memset(&b, 0, sizeof(b)); - memset(&d, 0, sizeof(d)); - memset(&xe, 0, sizeof(xe)); - memset(&x0, 0, sizeof(x0)); - _linlsqrstate_init(&s, _state, ae_true); - _linlsqrreport_init(&rep, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ta, 0, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&sa, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xe, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - - - /* - * Test 1. - * - * We test automatic diagonal preconditioning used by SolveSparse. - * In order to do so we: - * 1. generate 20*20 matrix A0 with condition number equal to 1.0E1 - * 2. generate random "exact" solution xe and right part b=A0*xe - * 3. generate random ill-conditioned diagonal scaling matrix D with - * condition number equal to 1.0E50: - * 4. transform A*x=b into badly scaled problem: - * A0*x0=b0 - * (A0*D)*(inv(D)*x0)=b0 - * finally we got new problem A*x=b with A=A0*D, b=b0, x=inv(D)*x0 - * - * Then we solve A*x=b: - * 1. with default preconditioner - * 2. with explicitly activayed diagonal preconditioning - * 3. with unit preconditioner. - * 1st and 2nd solutions must be close to xe, 3rd solution must be very - * far from the true one. - */ - n = 20; - rmatrixrndcond(n, 1.0E1, &ta, _state); - ae_vector_set_length(&xe, n, _state); - for(i=0; i<=n-1; i++) - { - xe.ptr.p_double[i] = randomnormal(_state); - } - ae_vector_set_length(&b, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - b.ptr.p_double[i] = b.ptr.p_double[i]+ta.ptr.pp_double[i][j]*xe.ptr.p_double[j]; - } - } - ae_vector_set_length(&d, n, _state); - for(i=0; i<=n-1; i++) - { - d.ptr.p_double[i] = ae_pow((double)(10), 100*ae_randomreal(_state)-50, _state); - } - ae_matrix_set_length(&a, n, n, _state); - sparsecreate(n, n, n*n, &sa, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = ta.ptr.pp_double[i][j]*d.ptr.p_double[j]; - sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state); - } - xe.ptr.p_double[i] = xe.ptr.p_double[i]/d.ptr.p_double[i]; - } - sparseconverttocrs(&sa, _state); - linlsqrcreate(n, n, &s, _state); - linlsqrsetcond(&s, (double)(0), (double)(0), 2*n, _state); - linlsqrsolvesparse(&s, &sa, &b, _state); - linlsqrresults(&s, &x0, &rep, _state); - if( rep.terminationtype<=0 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-x0.ptr.p_double[i], _state),5.0E-2/d.ptr.p_double[i]) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - linlsqrsetprecunit(&s, _state); - linlsqrsolvesparse(&s, &sa, &b, _state); - linlsqrresults(&s, &x0, &rep, _state); - if( rep.terminationtype>0 ) - { - bflag = ae_false; - for(i=0; i<=n-1; i++) - { - bflag = bflag||ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-x0.ptr.p_double[i], _state),5.0E-2/d.ptr.p_double[i]); - } - if( !bflag ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - linlsqrsetprecdiag(&s, _state); - linlsqrsolvesparse(&s, &sa, &b, _state); - linlsqrresults(&s, &x0, &rep, _state); - if( rep.terminationtype<=0 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-x0.ptr.p_double[i], _state),5.0E-2/d.ptr.p_double[i]) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - - /* - *test has been passed - */ - result = ae_false; - ae_frame_leave(_state); - return result; -} - - - -static ae_int_t testminbleicunit_maxoptguardlevel = 1; -static void testminbleicunit_calciip2(minbleicstate* state, - ae_int_t n, - ae_int_t fk, - ae_state *_state); -static void testminbleicunit_testfeasibility(ae_bool* feaserr, - ae_bool* converr, - ae_bool* interr, - ae_state *_state); -static void testminbleicunit_testother(ae_bool* err, ae_state *_state); -static void testminbleicunit_testconv(ae_bool* err, ae_state *_state); -static void testminbleicunit_testpreconditioning(ae_bool* err, - ae_state *_state); -static void testminbleicunit_setrandompreconditioner(minbleicstate* state, - ae_int_t n, - ae_int_t preckind, - ae_state *_state); -static void testminbleicunit_testbugs(ae_bool* err, ae_state *_state); -static void testminbleicunit_testoptguard(ae_bool* wereerrors, - ae_state *_state); -static void testminbleicunit_testoptguardc1test0reportfortask0(ae_bool* err, - optguardnonc1test0report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state); -static void testminbleicunit_testoptguardc1test1reportfortask0(ae_bool* err, - optguardnonc1test1report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state); - - - - - -ae_bool testminbleic(ae_bool silent, ae_state *_state) -{ - ae_bool waserrors; - ae_bool feasibilityerrors; - ae_bool othererrors; - ae_bool precerrors; - ae_bool interrors; - ae_bool converrors; - ae_bool optguarderrors; - ae_bool bugs; - ae_bool result; - - - waserrors = ae_false; - feasibilityerrors = ae_false; - othererrors = ae_false; - precerrors = ae_false; - interrors = ae_false; - converrors = ae_false; - optguarderrors = ae_false; - bugs = ae_false; - testminbleicunit_testfeasibility(&feasibilityerrors, &converrors, &interrors, _state); - testminbleicunit_testother(&othererrors, _state); - testminbleicunit_testconv(&converrors, _state); - testminbleicunit_testbugs(&bugs, _state); - testminbleicunit_testpreconditioning(&precerrors, _state); - testminbleicunit_testoptguard(&optguarderrors, _state); - - /* - * end - */ - waserrors = (((((feasibilityerrors||othererrors)||converrors)||interrors)||precerrors)||optguarderrors)||bugs; - if( !silent ) - { - printf("TESTING BLEIC OPTIMIZATION\n"); - printf("FEASIBILITY PROPERTIES: "); - if( feasibilityerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("PRECONDITIONING: "); - if( precerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("OTHER PROPERTIES: "); - if( othererrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("CONVERGENCE PROPERTIES: "); - if( converrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("INTERNAL ERRORS: "); - if( interrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("OPTGUARD: "); - if( optguarderrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("FIXED BUGS: "); - if( bugs ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - return result; -} - - -/************************************************************************* -Calculate test function IIP2 - -f(x) = sum( ((i*i+1)^FK*x[i])^2, i=0..N-1) - -It has high condition number which makes fast convergence unlikely without -good preconditioner. - -*************************************************************************/ -static void testminbleicunit_calciip2(minbleicstate* state, - ae_int_t n, - ae_int_t fk, - ae_state *_state) -{ - ae_int_t i; - - - if( state->needfg ) - { - state->f = (double)(0); - } - for(i=0; i<=n-1; i++) - { - if( state->needfg ) - { - state->f = state->f+ae_pow((double)(i*i+1), (double)(2*fk), _state)*ae_sqr(state->x.ptr.p_double[i], _state); - state->g.ptr.p_double[i] = ae_pow((double)(i*i+1), (double)(2*fk), _state)*2*state->x.ptr.p_double[i]; - } - } -} - - -/************************************************************************* -This function test feasibility properties. -It launches a sequence of problems and examines their solutions. -Most of the attention is directed towards feasibility properties, -although we make some quick checks to ensure that actual solution is found. - -On failure sets FeasErr (or ConvErr, depending on failure type) to True, -or leaves it unchanged otherwise. - -IntErr is set to True on internal errors (errors in the control flow). -*************************************************************************/ -static void testminbleicunit_testfeasibility(ae_bool* feaserr, - ae_bool* converr, - ae_bool* interr, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t pkind; - ae_int_t preckind; - ae_int_t passcount; - ae_int_t pass; - ae_int_t n; - ae_int_t nmax; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t p; - double v; - double v2; - double v3; - double vv; - ae_vector bl; - ae_vector bu; - ae_vector x; - ae_vector g; - ae_vector x0; - ae_vector xc; - ae_vector xs; - ae_vector svdw; - ae_matrix c; - ae_matrix svdu; - ae_matrix svdvt; - ae_vector ct; - minbleicstate state; - double epsx; - double epsfeas; - double weakepsg; - minbleicreport rep; - ae_int_t dkind; - double diffstep; - - ae_frame_make(_state, &_frame_block); - memset(&bl, 0, sizeof(bl)); - memset(&bu, 0, sizeof(bu)); - memset(&x, 0, sizeof(x)); - memset(&g, 0, sizeof(g)); - memset(&x0, 0, sizeof(x0)); - memset(&xc, 0, sizeof(xc)); - memset(&xs, 0, sizeof(xs)); - memset(&svdw, 0, sizeof(svdw)); - memset(&c, 0, sizeof(c)); - memset(&svdu, 0, sizeof(svdu)); - memset(&svdvt, 0, sizeof(svdvt)); - memset(&ct, 0, sizeof(ct)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - ae_vector_init(&bl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&g, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xs, 0, DT_REAL, _state, ae_true); - ae_vector_init(&svdw, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&svdu, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&svdvt, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - _minbleicstate_init(&state, _state, ae_true); - _minbleicreport_init(&rep, _state, ae_true); - - nmax = 5; - weakepsg = 1.0E-4; - epsx = 1.0E-4; - epsfeas = 1.0E-6; - passcount = 10; - for(pass=1; pass<=passcount; pass++) - { - - /* - * Test problem 1: - * * no boundary and inequality constraints - * * randomly generated plane as equality constraint - * * random point (not necessarily on the plane) - * * f = |x|^P, P = {2, 4} is used as target function - * * preconditioner is chosen at random (we just want to be - * sure that preconditioning won't prevent us from converging - * to the feasible point): - * * unit preconditioner - * * random diagonal-based preconditioner - * * random scale-based preconditioner - * * either analytic gradient or numerical differentiation are used - * * we check that after work is over we are on the plane and - * that we are in the stationary point of constrained F - */ - diffstep = 1.0E-6; - for(dkind=0; dkind<=1; dkind++) - { - for(preckind=0; preckind<=2; preckind++) - { - for(pkind=1; pkind<=2; pkind++) - { - for(n=1; n<=nmax; n++) - { - - /* - * Generate X, BL, BU, CT and left part of C. - * - * Right part of C is generated using somewhat complex algo: - * * we generate random vector and multiply it by C. - * * result is used as the right part. - * * calculations are done on the fly, vector itself is not stored - * We use such algo to be sure that our system is consistent. - */ - p = 2*pkind; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&g, n, _state); - ae_matrix_set_length(&c, 1, n+1, _state); - ae_vector_set_length(&ct, 1, _state); - c.ptr.pp_double[0][n] = (double)(0); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - c.ptr.pp_double[0][i] = 2*ae_randomreal(_state)-1; - v = 2*ae_randomreal(_state)-1; - c.ptr.pp_double[0][n] = c.ptr.pp_double[0][n]+c.ptr.pp_double[0][i]*v; - } - ct.ptr.p_int[0] = 0; - - /* - * Create and optimize - */ - if( dkind==0 ) - { - minbleiccreate(n, &x, &state, _state); - } - if( dkind==1 ) - { - minbleiccreatef(n, &x, diffstep, &state, _state); - } - minbleicsetlc(&state, &c, &ct, 1, _state); - minbleicsetcond(&state, weakepsg, 0.0, 0.0, 0, _state); - testminbleicunit_setrandompreconditioner(&state, n, preckind, _state); - while(minbleiciteration(&state, _state)) - { - if( state.needf||state.needfg ) - { - state.f = (double)(0); - } - for(i=0; i<=n-1; i++) - { - if( state.needf||state.needfg ) - { - state.f = state.f+ae_pow(state.x.ptr.p_double[i], (double)(p), _state); - } - if( state.needfg ) - { - state.g.ptr.p_double[i] = p*ae_pow(state.x.ptr.p_double[i], (double)(p-1), _state); - } - } - } - minbleicresults(&state, &x, &rep, _state); - if( rep.terminationtype<=0 ) - { - *converr = ae_true; - ae_frame_leave(_state); - return; - } - - /* - * Test feasibility of solution - */ - v = ae_v_dotproduct(&c.ptr.pp_double[0][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - *feaserr = *feaserr||ae_fp_greater(ae_fabs(v-c.ptr.pp_double[0][n], _state),epsfeas); - - /* - * if C is nonzero, test that result is - * a stationary point of constrained F. - * - * NOTE: this check is done only if C is nonzero - */ - vv = ae_v_dotproduct(&c.ptr.pp_double[0][0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1)); - if( ae_fp_neq(vv,(double)(0)) ) - { - - /* - * Calculate gradient at the result - * Project gradient into C - * Check projected norm - */ - for(i=0; i<=n-1; i++) - { - g.ptr.p_double[i] = p*ae_pow(x.ptr.p_double[i], (double)(p-1), _state); - } - v2 = ae_v_dotproduct(&c.ptr.pp_double[0][0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1)); - v = ae_v_dotproduct(&c.ptr.pp_double[0][0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - vv = v/v2; - ae_v_subd(&g.ptr.p_double[0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1), vv); - v3 = ae_v_dotproduct(&g.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - *converr = *converr||ae_fp_greater(ae_sqrt(v3, _state),weakepsg); - } - } - } - } - } - - /* - * Test problem 2 (multiple equality constraints): - * * 1<=N<=NMax, 1<=K<=N - * * no boundary constraints - * * N-dimensional space - * * randomly generated point xs - * * K randomly generated hyperplanes which all pass through xs - * define K equality constraints: (a[k],x)=b[k] - * * equality constraints are checked for being well conditioned - * * preconditioner is chosen at random (we just want to be - * sure that preconditioning won't prevent us from converging - * to the feasible point): - * * unit preconditioner - * * random diagonal-based preconditioner - * * random scale-based preconditioner - * * f(x) = |x-x0|^2, x0 = xs+a[0] - * * either analytic gradient or numerical differentiation are used - * * extremum of f(x) is exactly xs because: - * * xs is the closest point in the plane defined by (a[0],x)=b[0] - * * xs is feasible by definition - */ - diffstep = 1.0E-6; - for(dkind=0; dkind<=1; dkind++) - { - for(preckind=0; preckind<=2; preckind++) - { - for(n=2; n<=nmax; n++) - { - for(k=1; k<=n; k++) - { - - /* - * Generate X, X0, XS, BL, BU, CT and left part of C. - * - * Right part of C is generated using somewhat complex algo: - * * we generate random vector and multiply it by C. - * * result is used as the right part. - * * calculations are done on the fly, vector itself is not stored - * We use such algo to be sure that our system is consistent. - */ - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xs, n, _state); - ae_vector_set_length(&g, n, _state); - ae_matrix_set_length(&c, k, n+1, _state); - ae_vector_set_length(&ct, k, _state); - c.ptr.pp_double[0][n] = (double)(0); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - xs.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - do - { - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &xs.ptr.p_double[0], 1, ae_v_len(0,n-1)); - c.ptr.pp_double[i][n] = v; - ct.ptr.p_int[i] = 0; - } - ae_set_error_flag(feaserr, !rmatrixsvd(&c, k, n, 0, 0, 0, &svdw, &svdu, &svdvt, _state), __FILE__, __LINE__, "testminbleicunit.ap:342"); - } - while(!(ae_fp_greater(svdw.ptr.p_double[0],(double)(0))&&ae_fp_greater(svdw.ptr.p_double[k-1],0.001*svdw.ptr.p_double[0]))); - ae_v_move(&x0.ptr.p_double[0], 1, &xs.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_add(&x0.ptr.p_double[0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1)); - - /* - * Create and optimize - */ - if( dkind==0 ) - { - minbleiccreate(n, &x, &state, _state); - } - if( dkind==1 ) - { - minbleiccreatef(n, &x, diffstep, &state, _state); - } - minbleicsetlc(&state, &c, &ct, k, _state); - minbleicsetcond(&state, weakepsg, 0.0, 0.0, 0, _state); - testminbleicunit_setrandompreconditioner(&state, n, preckind, _state); - while(minbleiciteration(&state, _state)) - { - if( state.needf||state.needfg ) - { - state.f = (double)(0); - } - for(i=0; i<=n-1; i++) - { - if( state.needf||state.needfg ) - { - state.f = state.f+ae_sqr(state.x.ptr.p_double[i]-x0.ptr.p_double[i], _state); - } - if( state.needfg ) - { - state.g.ptr.p_double[i] = 2*(state.x.ptr.p_double[i]-x0.ptr.p_double[i]); - } - } - } - minbleicresults(&state, &x, &rep, _state); - if( rep.terminationtype<=0 ) - { - *converr = ae_true; - ae_frame_leave(_state); - return; - } - - /* - * check feasiblity properties - */ - for(i=0; i<=k-1; i++) - { - v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - *feaserr = *feaserr||ae_fp_greater(ae_fabs(v-c.ptr.pp_double[i][n], _state),epsx); - } - - /* - * Compare with XS - */ - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(x.ptr.p_double[i]-xs.ptr.p_double[i], _state); - } - v = ae_sqrt(v, _state); - *converr = *converr||ae_fp_greater(ae_fabs(v, _state),0.001); - } - } - } - } - - /* - * Another simple problem: - * * bound constraints 0 <= x[i] <= 1 - * * no linear constraints - * * preconditioner is chosen at random (we just want to be - * sure that preconditioning won't prevent us from converging - * to the feasible point): - * * unit preconditioner - * * random diagonal-based preconditioner - * * random scale-based preconditioner - * * F(x) = |x-x0|^P, where P={2,4} and x0 is randomly selected from [-1,+2]^N - * * with such simple boundaries and function it is easy to find - * analytic form of solution: S[i] = bound(x0[i], 0, 1) - * * we also check that both final solution and subsequent iterates - * are strictly feasible - */ - diffstep = 1.0E-6; - for(dkind=0; dkind<=1; dkind++) - { - for(preckind=0; preckind<=2; preckind++) - { - for(pkind=1; pkind<=2; pkind++) - { - for(n=1; n<=nmax; n++) - { - - /* - * Generate X, BL, BU. - */ - p = 2*pkind; - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - bl.ptr.p_double[i] = (double)(0); - bu.ptr.p_double[i] = (double)(1); - x.ptr.p_double[i] = ae_randomreal(_state); - x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1; - } - - /* - * Create and optimize - */ - if( dkind==0 ) - { - minbleiccreate(n, &x, &state, _state); - } - if( dkind==1 ) - { - minbleiccreatef(n, &x, diffstep, &state, _state); - } - minbleicsetbc(&state, &bl, &bu, _state); - minbleicsetcond(&state, weakepsg, 0.0, 0.0, 0, _state); - testminbleicunit_setrandompreconditioner(&state, n, preckind, _state); - while(minbleiciteration(&state, _state)) - { - if( state.needf||state.needfg ) - { - state.f = (double)(0); - } - for(i=0; i<=n-1; i++) - { - if( state.needf||state.needfg ) - { - state.f = state.f+ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p), _state); - } - if( state.needfg ) - { - state.g.ptr.p_double[i] = p*ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state); - } - *feaserr = *feaserr||ae_fp_less(state.x.ptr.p_double[i],0.0); - *feaserr = *feaserr||ae_fp_greater(state.x.ptr.p_double[i],1.0); - } - } - minbleicresults(&state, &x, &rep, _state); - if( rep.terminationtype<=0 ) - { - *converr = ae_true; - ae_frame_leave(_state); - return; - } - - /* - * * compare solution with analytic one - * * check feasibility - */ - v = 0.0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(x.ptr.p_double[i],(double)(0))&&ae_fp_less(x.ptr.p_double[i],(double)(1)) ) - { - v = v+ae_sqr(p*ae_pow(x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state), _state); - } - *feaserr = *feaserr||ae_fp_less(x.ptr.p_double[i],0.0); - *feaserr = *feaserr||ae_fp_greater(x.ptr.p_double[i],1.0); - } - *converr = *converr||ae_fp_greater(ae_sqrt(v, _state),weakepsg); - } - } - } - } - - /* - * Same as previous problem, but with minor modifications: - * * some bound constraints are 0<=x[i]<=1, some are Ci=x[i]=Ci - * * no linear constraints - * * preconditioner is chosen at random (we just want to be - * sure that preconditioning won't prevent us from converging - * to the feasible point): - * * unit preconditioner - * * random diagonal-based preconditioner - * * random scale-based preconditioner - * * F(x) = |x-x0|^P, where P={2,4} and x0 is randomly selected from [-1,+2]^N - * * with such simple boundaries and function it is easy to find - * analytic form of solution: S[i] = bound(x0[i], 0, 1) - * * we also check that both final solution and subsequent iterates - * are strictly feasible - */ - diffstep = 1.0E-6; - for(dkind=0; dkind<=1; dkind++) - { - for(preckind=0; preckind<=2; preckind++) - { - for(pkind=1; pkind<=2; pkind++) - { - for(n=1; n<=nmax; n++) - { - - /* - * Generate X, BL, BU. - */ - p = 2*pkind; - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - bl.ptr.p_double[i] = (double)(0); - bu.ptr.p_double[i] = (double)(1); - } - else - { - bl.ptr.p_double[i] = ae_randomreal(_state); - bu.ptr.p_double[i] = bl.ptr.p_double[i]; - } - x.ptr.p_double[i] = ae_randomreal(_state); - x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1; - } - - /* - * Create and optimize - */ - if( dkind==0 ) - { - minbleiccreate(n, &x, &state, _state); - } - if( dkind==1 ) - { - minbleiccreatef(n, &x, diffstep, &state, _state); - } - minbleicsetbc(&state, &bl, &bu, _state); - minbleicsetcond(&state, weakepsg, 0.0, 0.0, 0, _state); - testminbleicunit_setrandompreconditioner(&state, n, preckind, _state); - while(minbleiciteration(&state, _state)) - { - if( state.needf||state.needfg ) - { - state.f = (double)(0); - } - for(i=0; i<=n-1; i++) - { - if( state.needf||state.needfg ) - { - state.f = state.f+ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p), _state); - } - if( state.needfg ) - { - state.g.ptr.p_double[i] = p*ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state); - } - *feaserr = *feaserr||ae_fp_less(state.x.ptr.p_double[i],bl.ptr.p_double[i]); - *feaserr = *feaserr||ae_fp_greater(state.x.ptr.p_double[i],bu.ptr.p_double[i]); - } - } - minbleicresults(&state, &x, &rep, _state); - if( rep.terminationtype<=0 ) - { - *converr = ae_true; - ae_frame_leave(_state); - return; - } - - /* - * * compare solution with analytic one - * * check feasibility - */ - v = 0.0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(x.ptr.p_double[i],bl.ptr.p_double[i])&&ae_fp_less(x.ptr.p_double[i],bu.ptr.p_double[i]) ) - { - v = v+ae_sqr(p*ae_pow(x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state), _state); - } - *feaserr = *feaserr||ae_fp_less(x.ptr.p_double[i],bl.ptr.p_double[i]); - *feaserr = *feaserr||ae_fp_greater(x.ptr.p_double[i],bu.ptr.p_double[i]); - } - *converr = *converr||ae_fp_greater(ae_sqrt(v, _state),weakepsg); - } - } - } - } - - /* - * Same as previous one, but with bound constraints posed - * as general linear ones: - * * no bound constraints - * * 2*N linear constraints 0 <= x[i] <= 1 - * * preconditioner is chosen at random (we just want to be - * sure that preconditioning won't prevent us from converging - * to the feasible point): - * * unit preconditioner - * * random diagonal-based preconditioner - * * random scale-based preconditioner - * * F(x) = |x-x0|^P, where P={2,4} and x0 is randomly selected from [-1,+2]^N - * * with such simple constraints and function it is easy to find - * analytic form of solution: S[i] = bound(x0[i], 0, 1). - * * however, we can't guarantee that solution is strictly feasible - * with respect to nonlinearity constraint, so we check - * for approximate feasibility. - */ - for(preckind=0; preckind<=2; preckind++) - { - for(pkind=1; pkind<=2; pkind++) - { - for(n=1; n<=nmax; n++) - { - - /* - * Generate X, BL, BU. - */ - p = 2*pkind; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_matrix_set_length(&c, 2*n, n+1, _state); - ae_vector_set_length(&ct, 2*n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = ae_randomreal(_state); - x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1; - for(j=0; j<=n; j++) - { - c.ptr.pp_double[2*i+0][j] = (double)(0); - c.ptr.pp_double[2*i+1][j] = (double)(0); - } - c.ptr.pp_double[2*i+0][i] = (double)(1); - c.ptr.pp_double[2*i+0][n] = (double)(0); - ct.ptr.p_int[2*i+0] = 1; - c.ptr.pp_double[2*i+1][i] = (double)(1); - c.ptr.pp_double[2*i+1][n] = (double)(1); - ct.ptr.p_int[2*i+1] = -1; - } - - /* - * Create and optimize - */ - minbleiccreate(n, &x, &state, _state); - minbleicsetlc(&state, &c, &ct, 2*n, _state); - minbleicsetcond(&state, weakepsg, 0.0, 0.0, 0, _state); - testminbleicunit_setrandompreconditioner(&state, n, preckind, _state); - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p), _state); - state.g.ptr.p_double[i] = p*ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state); - } - continue; - } - - /* - * Unknown protocol specified - */ - *interr = ae_true; - ae_frame_leave(_state); - return; - } - minbleicresults(&state, &x, &rep, _state); - if( rep.terminationtype<=0 ) - { - *converr = ae_true; - ae_frame_leave(_state); - return; - } - - /* - * * compare solution with analytic one - * * check feasibility - */ - v = 0.0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(x.ptr.p_double[i],0.02)&&ae_fp_less(x.ptr.p_double[i],0.98) ) - { - v = v+ae_sqr(p*ae_pow(x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state), _state); - } - *feaserr = *feaserr||ae_fp_less(x.ptr.p_double[i],0.0-epsfeas); - *feaserr = *feaserr||ae_fp_greater(x.ptr.p_double[i],1.0+epsfeas); - } - *converr = *converr||ae_fp_greater(ae_sqrt(v, _state),weakepsg); - } - } - } - - /* - * Feasibility problem: - * * bound constraints 0<=x[i]<=1 - * * starting point xs with xs[i] in [-1,+2] - * * random point xc from [0,1] is used to generate K<=N - * random linear equality/inequality constraints of the form - * (c,x-xc)=0.0 (or, alternatively, >= or <=), where - * c is a random vector. - * * preconditioner is chosen at random (we just want to be - * sure that preconditioning won't prevent us from converging - * to the feasible point): - * * unit preconditioner - * * random diagonal-based preconditioner - * * random scale-based preconditioner - * * F(x) = |x-x0|^P, where P={2,4} and x0 is randomly selected from [-1,+2]^N - * * we do not know analytic form of the solution, and, if fact, we do not - * check for solution correctness. We just check that algorithm converges - * to the feasible points. - */ - for(preckind=0; preckind<=2; preckind++) - { - for(pkind=1; pkind<=2; pkind++) - { - for(n=1; n<=nmax; n++) - { - for(k=1; k<=n; k++) - { - - /* - * Generate X, BL, BU. - */ - p = 2*pkind; - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xc, n, _state); - ae_vector_set_length(&xs, n, _state); - ae_matrix_set_length(&c, k, n+1, _state); - ae_vector_set_length(&ct, k, _state); - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1; - xs.ptr.p_double[i] = 3*ae_randomreal(_state)-1; - xc.ptr.p_double[i] = 0.1+0.8*ae_randomreal(_state); - bl.ptr.p_double[i] = (double)(0); - bu.ptr.p_double[i] = (double)(1); - } - for(i=0; i<=k-1; i++) - { - c.ptr.pp_double[i][n] = (double)(0); - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - c.ptr.pp_double[i][n] = c.ptr.pp_double[i][n]+c.ptr.pp_double[i][j]*xc.ptr.p_double[j]; - } - ct.ptr.p_int[i] = ae_randominteger(3, _state)-1; - } - - /* - * Create and optimize - */ - minbleiccreate(n, &xs, &state, _state); - minbleicsetbc(&state, &bl, &bu, _state); - minbleicsetlc(&state, &c, &ct, k, _state); - minbleicsetcond(&state, weakepsg, 0.0, 0.0, 0, _state); - testminbleicunit_setrandompreconditioner(&state, n, preckind, _state); - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p), _state); - state.g.ptr.p_double[i] = p*ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state); - } - continue; - } - - /* - * Unknown protocol specified - */ - *interr = ae_true; - ae_frame_leave(_state); - return; - } - minbleicresults(&state, &x, &rep, _state); - if( rep.terminationtype<=0 ) - { - *converr = ae_true; - ae_frame_leave(_state); - return; - } - - /* - * Check feasibility - */ - for(i=0; i<=n-1; i++) - { - *feaserr = *feaserr||ae_fp_less(x.ptr.p_double[i],0.0); - *feaserr = *feaserr||ae_fp_greater(x.ptr.p_double[i],1.0); - } - for(i=0; i<=k-1; i++) - { - v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = v-c.ptr.pp_double[i][n]; - if( ct.ptr.p_int[i]==0 ) - { - *feaserr = *feaserr||ae_fp_greater(ae_fabs(v, _state),epsfeas); - } - if( ct.ptr.p_int[i]<0 ) - { - *feaserr = *feaserr||ae_fp_greater(v,epsfeas); - } - if( ct.ptr.p_int[i]>0 ) - { - *feaserr = *feaserr||ae_fp_less(v,-epsfeas); - } - } - } - } - } - } - - /* - * Infeasible problem: - * * all bound constraints are 0 <= x[i] <= 1 except for one - * * that one is 0 >= x[i] >= 1 - * * no linear constraints - * * preconditioner is chosen at random (we just want to be - * sure that preconditioning won't prevent us from detecting - * infeasible point): - * * unit preconditioner - * * random diagonal-based preconditioner - * * random scale-based preconditioner - * * F(x) = |x-x0|^P, where P={2,4} and x0 is randomly selected from [-1,+2]^N - * * algorithm must return correct error code on such problem - */ - for(preckind=0; preckind<=2; preckind++) - { - for(pkind=1; pkind<=2; pkind++) - { - for(n=1; n<=nmax; n++) - { - - /* - * Generate X, BL, BU. - */ - p = 2*pkind; - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - bl.ptr.p_double[i] = (double)(0); - bu.ptr.p_double[i] = (double)(1); - x.ptr.p_double[i] = ae_randomreal(_state); - x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1; - } - i = ae_randominteger(n, _state); - bl.ptr.p_double[i] = (double)(1); - bu.ptr.p_double[i] = (double)(0); - - /* - * Create and optimize - */ - minbleiccreate(n, &x, &state, _state); - minbleicsetbc(&state, &bl, &bu, _state); - minbleicsetcond(&state, weakepsg, 0.0, 0.0, 0, _state); - testminbleicunit_setrandompreconditioner(&state, n, preckind, _state); - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p), _state); - state.g.ptr.p_double[i] = p*ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state); - } - continue; - } - - /* - * Unknown protocol specified - */ - *interr = ae_true; - ae_frame_leave(_state); - return; - } - minbleicresults(&state, &x, &rep, _state); - *feaserr = *feaserr||rep.terminationtype!=-3; - } - } - } - - /* - * Infeasible problem (2): - * * no bound and inequality constraints - * * 1<=K<=N arbitrary equality constraints - * * (K+1)th constraint which is equal to the first constraint a*x=c, - * but with c:=c+1. I.e. we have both a*x=c and a*x=c+1, which can't - * be true (other constraints may be inconsistent too, but we don't - * have to check it). - * * preconditioner is chosen at random (we just want to be - * sure that preconditioning won't prevent us from detecting - * infeasible point): - * * unit preconditioner - * * random diagonal-based preconditioner - * * random scale-based preconditioner - * * F(x) = |x|^P, where P={2,4} - * * algorithm must return correct error code on such problem - */ - for(preckind=0; preckind<=2; preckind++) - { - for(pkind=1; pkind<=2; pkind++) - { - for(n=1; n<=nmax; n++) - { - for(k=1; k<=n; k++) - { - - /* - * Generate X, BL, BU. - */ - p = 2*pkind; - ae_vector_set_length(&x, n, _state); - ae_matrix_set_length(&c, k+1, n+1, _state); - ae_vector_set_length(&ct, k+1, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = ae_randomreal(_state); - } - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n; j++) - { - c.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - ct.ptr.p_int[i] = 0; - } - ct.ptr.p_int[k] = 0; - ae_v_move(&c.ptr.pp_double[k][0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1)); - c.ptr.pp_double[k][n] = c.ptr.pp_double[0][n]+1; - - /* - * Create and optimize - */ - minbleiccreate(n, &x, &state, _state); - minbleicsetlc(&state, &c, &ct, k+1, _state); - minbleicsetcond(&state, weakepsg, 0.0, 0.0, 0, _state); - testminbleicunit_setrandompreconditioner(&state, n, preckind, _state); - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+ae_pow(state.x.ptr.p_double[i], (double)(p), _state); - state.g.ptr.p_double[i] = p*ae_pow(state.x.ptr.p_double[i], (double)(p-1), _state); - } - continue; - } - - /* - * Unknown protocol specified - */ - *interr = ae_true; - ae_frame_leave(_state); - return; - } - minbleicresults(&state, &x, &rep, _state); - *feaserr = *feaserr||rep.terminationtype!=-3; - } - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function additional properties. - -On failure sets Err to True (leaves it unchanged otherwise) -*************************************************************************/ -static void testminbleicunit_testother(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t passcount; - ae_int_t pass; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_vector bl; - ae_vector bu; - ae_vector x; - ae_vector xf; - ae_vector x0; - ae_vector x1; - ae_vector b; - ae_vector xlast; - ae_vector a; - ae_vector s; - ae_vector h; - ae_matrix c; - ae_matrix fulla; - ae_vector ct; - double fprev; - double xprev; - double stpmax; - double v; - ae_int_t nec; - ae_int_t nic; - ae_int_t pkind; - ae_int_t ckind; - ae_int_t mkind; - double vc; - double vm; - minbleicstate state; - double epsx; - double epsg; - double eps; - double tmpeps; - minbleicreport rep; - double diffstep; - ae_int_t dkind; - ae_bool wasf; - ae_bool wasfg; - double r; - hqrndstate rs; - ae_int_t spoiliteration; - ae_int_t stopiteration; - ae_int_t spoilvar; - double spoilval; - double ss; - ae_int_t stopcallidx; - ae_int_t callidx; - ae_int_t maxits; - ae_bool terminationrequested; - ae_int_t scaletype; - - ae_frame_make(_state, &_frame_block); - memset(&bl, 0, sizeof(bl)); - memset(&bu, 0, sizeof(bu)); - memset(&x, 0, sizeof(x)); - memset(&xf, 0, sizeof(xf)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&b, 0, sizeof(b)); - memset(&xlast, 0, sizeof(xlast)); - memset(&a, 0, sizeof(a)); - memset(&s, 0, sizeof(s)); - memset(&h, 0, sizeof(h)); - memset(&c, 0, sizeof(c)); - memset(&fulla, 0, sizeof(fulla)); - memset(&ct, 0, sizeof(ct)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&rs, 0, sizeof(rs)); - ae_vector_init(&bl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xlast, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&h, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&fulla, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - _minbleicstate_init(&state, _state, ae_true); - _minbleicreport_init(&rep, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - epsx = 1.0E-4; - epsg = 1.0E-8; - passcount = 10; - - /* - * Try to reproduce bug 570 (optimizer hangs on problems where it is required - * to perform very small step - less than 1E-50 - in order to activate constraints). - * - * The problem being solved is: - * - * min x[0]+x[1]+...+x[n-1] - * - * subject to - * - * x[i]>=0, for i=0..n-1 - * - * with initial point - * - * x[0] = 1.0E-100, x[1]=x[2]=...=0.5 - * - * We try to reproduce this problem in different settings: - * * boundary-only constraints - we test that completion code is positive, - * and all x[] are EXACTLY zero - * * boundary constraints posed as general linear ones - we test that - * completion code is positive, and all x[] are APPROXIMATELY zero. - */ - n = 10; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - ae_matrix_set_length(&c, n, n+1, _state); - ae_vector_set_length(&ct, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 0.5; - bl.ptr.p_double[i] = 0.0; - bu.ptr.p_double[i] = _state->v_posinf; - ct.ptr.p_int[i] = 1; - for(j=0; j<=n; j++) - { - c.ptr.pp_double[i][j] = 0.0; - } - c.ptr.pp_double[i][i] = 1.0; - } - x.ptr.p_double[0] = 1.0E-100; - minbleiccreate(n, &x, &state, _state); - minbleicsetbc(&state, &bl, &bu, _state); - minbleicsetcond(&state, (double)(0), (double)(0), (double)(0), 2*n, _state); - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+state.x.ptr.p_double[i]; - state.g.ptr.p_double[i] = 1.0; - } - } - } - minbleicresults(&state, &xf, &rep, _state); - ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminbleicunit.ap:1030"); - if( rep.terminationtype>0 ) - { - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(err, ae_fp_neq(xf.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testminbleicunit.ap:1033"); - } - } - minbleiccreate(n, &x, &state, _state); - minbleicsetlc(&state, &c, &ct, n, _state); - minbleicsetcond(&state, 1.0E-64, (double)(0), (double)(0), 10, _state); - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+state.x.ptr.p_double[i]; - state.g.ptr.p_double[i] = 1.0; - } - } - } - minbleicresults(&state, &xf, &rep, _state); - ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminbleicunit.ap:1051"); - if( rep.terminationtype>0 ) - { - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(xf.ptr.p_double[i], _state),1.0E-10), __FILE__, __LINE__, "testminbleicunit.ap:1054"); - } - } - - /* - * Test reports: - * * first value must be starting point - * * last value must be last point - */ - for(pass=1; pass<=passcount; pass++) - { - n = 50; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&xlast, n, _state); - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = (double)(10); - bl.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - bu.ptr.p_double[i] = _state->v_posinf; - } - minbleiccreate(n, &x, &state, _state); - minbleicsetbc(&state, &bl, &bu, _state); - minbleicsetcond(&state, 1.0E-64, (double)(0), (double)(0), 10, _state); - minbleicsetxrep(&state, ae_true, _state); - fprev = ae_maxrealnumber; - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+ae_sqr((1+i)*state.x.ptr.p_double[i], _state); - state.g.ptr.p_double[i] = 2*(1+i)*state.x.ptr.p_double[i]; - } - } - if( state.xupdated ) - { - if( ae_fp_eq(fprev,ae_maxrealnumber) ) - { - for(i=0; i<=n-1; i++) - { - *err = *err||ae_fp_neq(state.x.ptr.p_double[i],x.ptr.p_double[i]); - } - } - fprev = state.f; - ae_v_move(&xlast.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - } - } - minbleicresults(&state, &x, &rep, _state); - for(i=0; i<=n-1; i++) - { - *err = *err||ae_fp_neq(x.ptr.p_double[i],xlast.ptr.p_double[i]); - } - } - - /* - * Test differentiation vs. analytic gradient - * (first one issues NeedF requests, second one issues NeedFG requests) - */ - for(pass=1; pass<=passcount; pass++) - { - n = 10; - diffstep = 1.0E-6; - for(dkind=0; dkind<=1; dkind++) - { - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&xlast, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = (double)(1); - } - if( dkind==0 ) - { - minbleiccreate(n, &x, &state, _state); - } - if( dkind==1 ) - { - minbleiccreatef(n, &x, diffstep, &state, _state); - } - minbleicsetcond(&state, 1.0E-6, (double)(0), epsx, 0, _state); - wasf = ae_false; - wasfg = ae_false; - while(minbleiciteration(&state, _state)) - { - if( state.needf||state.needfg ) - { - state.f = (double)(0); - } - for(i=0; i<=n-1; i++) - { - if( state.needf||state.needfg ) - { - state.f = state.f+ae_sqr((1+i)*state.x.ptr.p_double[i], _state); - } - if( state.needfg ) - { - state.g.ptr.p_double[i] = 2*(1+i)*state.x.ptr.p_double[i]; - } - } - wasf = wasf||state.needf; - wasfg = wasfg||state.needfg; - } - minbleicresults(&state, &x, &rep, _state); - if( dkind==0 ) - { - *err = (*err||wasf)||!wasfg; - } - if( dkind==1 ) - { - *err = (*err||!wasf)||wasfg; - } - } - } - - /* - * Test that numerical differentiation uses scaling. - * - * In order to test that we solve simple optimization - * problem: min(x^2) with initial x equal to 0.0. - * - * We choose random DiffStep and S, then we check that - * optimizer evaluates function at +-DiffStep*S only. - */ - for(pass=1; pass<=passcount; pass++) - { - ae_vector_set_length(&x, 1, _state); - ae_vector_set_length(&s, 1, _state); - diffstep = ae_randomreal(_state)*1.0E-6; - s.ptr.p_double[0] = ae_exp(ae_randomreal(_state)*4-2, _state); - x.ptr.p_double[0] = (double)(0); - minbleiccreatef(1, &x, diffstep, &state, _state); - minbleicsetcond(&state, 1.0E-6, (double)(0), epsx, 0, _state); - minbleicsetscale(&state, &s, _state); - v = (double)(0); - while(minbleiciteration(&state, _state)) - { - state.f = ae_sqr(state.x.ptr.p_double[0], _state); - v = ae_maxreal(v, ae_fabs(state.x.ptr.p_double[0], _state), _state); - } - minbleicresults(&state, &x, &rep, _state); - r = v/(s.ptr.p_double[0]*diffstep); - *err = *err||ae_fp_greater(ae_fabs(ae_log(r, _state), _state),ae_log(1+1000*ae_machineepsilon, _state)); - } - - /* - * Test stpmax - */ - for(pass=1; pass<=passcount; pass++) - { - n = 1; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - x.ptr.p_double[0] = (double)(100); - bl.ptr.p_double[0] = 2*ae_randomreal(_state)-1; - bu.ptr.p_double[0] = _state->v_posinf; - stpmax = 0.05+0.05*ae_randomreal(_state); - minbleiccreate(n, &x, &state, _state); - minbleicsetbc(&state, &bl, &bu, _state); - minbleicsetcond(&state, epsg, (double)(0), epsx, 0, _state); - minbleicsetxrep(&state, ae_true, _state); - minbleicsetstpmax(&state, stpmax, _state); - xprev = x.ptr.p_double[0]; - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = ae_exp(state.x.ptr.p_double[0], _state)+ae_exp(-state.x.ptr.p_double[0], _state); - state.g.ptr.p_double[0] = ae_exp(state.x.ptr.p_double[0], _state)-ae_exp(-state.x.ptr.p_double[0], _state); - *err = *err||ae_fp_greater(ae_fabs(state.x.ptr.p_double[0]-xprev, _state),(1+ae_sqrt(ae_machineepsilon, _state))*stpmax); - } - if( state.xupdated ) - { - *err = *err||ae_fp_greater(ae_fabs(state.x.ptr.p_double[0]-xprev, _state),(1+ae_sqrt(ae_machineepsilon, _state))*stpmax); - xprev = state.x.ptr.p_double[0]; - } - } - } - - /* - * Ability to solve problems with function which is unbounded from below - */ - for(pass=1; pass<=passcount; pass++) - { - n = 1; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - bl.ptr.p_double[0] = 4*ae_randomreal(_state)+1; - bu.ptr.p_double[0] = bl.ptr.p_double[0]+1; - x.ptr.p_double[0] = 0.5*(bl.ptr.p_double[0]+bu.ptr.p_double[0]); - minbleiccreate(n, &x, &state, _state); - minbleicsetbc(&state, &bl, &bu, _state); - minbleicsetcond(&state, epsg, (double)(0), epsx, 0, _state); - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = -1.0E8*ae_sqr(state.x.ptr.p_double[0], _state); - state.g.ptr.p_double[0] = -2.0E8*state.x.ptr.p_double[0]; - } - } - minbleicresults(&state, &x, &rep, _state); - *err = *err||ae_fp_greater(ae_fabs(x.ptr.p_double[0]-bu.ptr.p_double[0], _state),epsx); - } - - /* - * Test correctness of the scaling: - * * initial point is random point from [+1,+2]^N - * * f(x) = SUM(A[i]*x[i]^4), C[i] is random from [0.01,100] - * * function is EFFECTIVELY unconstrained; it has formal constraints, - * but they are inactive at the solution; we try different variants - * in order to explore different control paths of the optimizer: - * 0) absense of constraints - * 1) bound constraints -100000<=x[i]<=100000 - * 2) one linear constraint 0*x=0 - * 3) combination of (1) and (2) - * * we use random scaling matrix - * * we test different variants of the preconditioning: - * 0) unit preconditioner - * 1) random diagonal from [0.01,100] - * 2) scale preconditioner - * * we set very stringent stopping conditions - * * and we test that in the extremum stopping conditions are - * satisfied subject to the current scaling coefficients. - */ - for(pass=1; pass<=passcount; pass++) - { - tmpeps = 1.0E-5; - for(n=1; n<=10; n++) - { - for(ckind=0; ckind<=3; ckind++) - { - for(pkind=0; pkind<=2; pkind++) - { - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&a, n, _state); - ae_vector_set_length(&s, n, _state); - ae_vector_set_length(&h, n, _state); - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - ae_matrix_set_length(&c, 1, n+1, _state); - ae_vector_set_length(&ct, 1, _state); - ct.ptr.p_int[0] = 0; - c.ptr.pp_double[0][n] = (double)(0); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = ae_randomreal(_state)+1; - bl.ptr.p_double[i] = (double)(-100000); - bu.ptr.p_double[i] = (double)(100000); - c.ptr.pp_double[0][i] = (double)(0); - a.ptr.p_double[i] = ae_exp(ae_log((double)(10), _state)*(2*ae_randomreal(_state)-1), _state); - s.ptr.p_double[i] = ae_exp(ae_log((double)(10), _state)*(2*ae_randomreal(_state)-1), _state); - h.ptr.p_double[i] = ae_exp(ae_log((double)(10), _state)*(2*ae_randomreal(_state)-1), _state); - } - minbleiccreate(n, &x, &state, _state); - if( ckind==1||ckind==3 ) - { - minbleicsetbc(&state, &bl, &bu, _state); - } - if( ckind==2||ckind==3 ) - { - minbleicsetlc(&state, &c, &ct, 1, _state); - } - if( pkind==1 ) - { - minbleicsetprecdiag(&state, &h, _state); - } - if( pkind==2 ) - { - minbleicsetprecscale(&state, _state); - } - minbleicsetcond(&state, tmpeps, (double)(0), (double)(0), 0, _state); - minbleicsetscale(&state, &s, _state); - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+a.ptr.p_double[i]*ae_sqr(state.x.ptr.p_double[i], _state); - state.g.ptr.p_double[i] = 2*a.ptr.p_double[i]*state.x.ptr.p_double[i]; - } - } - } - minbleicresults(&state, &x, &rep, _state); - if( rep.terminationtype<=0 ) - { - *err = ae_true; - ae_frame_leave(_state); - return; - } - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(s.ptr.p_double[i]*2*a.ptr.p_double[i]*x.ptr.p_double[i], _state); - } - v = ae_sqrt(v, _state); - ae_set_error_flag(err, ae_fp_greater(v,tmpeps), __FILE__, __LINE__, "testminbleicunit.ap:1320"); - } - } - } - } - - /* - * Check correctness of the "trimming". - * - * Trimming is a technique which is used to help algorithm - * cope with unbounded functions. In order to check this - * technique we will try to solve following optimization - * problem: - * - * min f(x) subject to no constraints on X - * { 1/(1-x) + 1/(1+x) + c*x, if -0.999999=0.999999 - * - * where c is either 1.0 or 1.0E+4, M is either 1.0E8, 1.0E20 or +INF - * (we try different combinations) - */ - for(pass=1; pass<=passcount; pass++) - { - for(ckind=0; ckind<=1; ckind++) - { - for(mkind=0; mkind<=2; mkind++) - { - - /* - * Choose c and M - */ - vc = (double)(1); - vm = (double)(1); - if( ckind==0 ) - { - vc = 1.0; - } - if( ckind==1 ) - { - vc = 1.0E+4; - } - if( mkind==0 ) - { - vm = 1.0E+8; - } - if( mkind==1 ) - { - vm = 1.0E+20; - } - if( mkind==2 ) - { - vm = _state->v_posinf; - } - - /* - * Create optimizer, solve optimization problem - */ - epsg = 1.0E-6*vc; - ae_vector_set_length(&x, 1, _state); - x.ptr.p_double[0] = 0.0; - minbleiccreate(1, &x, &state, _state); - minbleicsetcond(&state, epsg, (double)(0), (double)(0), 0, _state); - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - if( ae_fp_less(-0.999999,state.x.ptr.p_double[0])&&ae_fp_less(state.x.ptr.p_double[0],0.999999) ) - { - state.f = 1/(1-state.x.ptr.p_double[0])+1/(1+state.x.ptr.p_double[0])+vc*state.x.ptr.p_double[0]; - state.g.ptr.p_double[0] = 1/ae_sqr(1-state.x.ptr.p_double[0], _state)-1/ae_sqr(1+state.x.ptr.p_double[0], _state)+vc; - } - else - { - state.f = vm; - state.g.ptr.p_double[0] = (double)(0); - } - } - } - minbleicresults(&state, &x, &rep, _state); - if( rep.terminationtype<=0 ) - { - *err = ae_true; - ae_frame_leave(_state); - return; - } - *err = *err||ae_fp_greater(ae_fabs(1/ae_sqr(1-x.ptr.p_double[0], _state)-1/ae_sqr(1+x.ptr.p_double[0], _state)+vc, _state),epsg); - } - } - } - - /* - * Test behaviour on noisy functions. - * - * Consider following problem: - * * f(x,y) = (x+1)^2 + (y+1)^2 + 10000*MachineEpsilon*RandomReal() - * * boundary constraints x>=0, y>=0 - * * starting point (x0,y0)=(10*MachineEpsilon,1.0) - * - * Such problem contains small numerical noise. Without noise its - * solution is (xs,ys)=(0,0), which is easy to find. However, presence - * of the noise makes it hard to solve: - * * noisy f(x,y) is monotonically decreasing only when we perform - * steps orders of magnitude larger than 10000*MachineEpsilon - * * at small scales f(x,y) is non-monotonic and non-convex - * * however, our first step must be done towards - * (x1,y1) = (0,1-some_small_value), and length of such step is - * many times SMALLER than 10000*MachineEpsilon - * * second step, from (x1,y1) to (xs,ys), will be large enough to - * ignore numerical noise, so the only problem is to perform - * first step - * - * Naive implementation of BLEIC should fail sometimes (sometimes - - * due to non-deterministic nature of noise) on such problem. However, - * our improved implementation should solve it correctly. We test - * several variations of inner stopping criteria. - */ - for(pass=1; pass<=passcount; pass++) - { - eps = 1.0E-9; - ae_vector_set_length(&x, 2, _state); - ae_vector_set_length(&bl, 2, _state); - ae_vector_set_length(&bu, 2, _state); - x.ptr.p_double[0] = 10*ae_machineepsilon; - x.ptr.p_double[1] = 1.0; - bl.ptr.p_double[0] = 0.0; - bu.ptr.p_double[0] = _state->v_posinf; - bl.ptr.p_double[1] = 0.0; - bu.ptr.p_double[1] = _state->v_posinf; - for(ckind=0; ckind<=2; ckind++) - { - minbleiccreate(2, &x, &state, _state); - minbleicsetbc(&state, &bl, &bu, _state); - if( ckind==0 ) - { - minbleicsetcond(&state, eps, (double)(0), (double)(0), 0, _state); - } - if( ckind==1 ) - { - minbleicsetcond(&state, (double)(0), eps, (double)(0), 0, _state); - } - if( ckind==2 ) - { - minbleicsetcond(&state, (double)(0), (double)(0), eps, 0, _state); - } - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = ae_sqr(state.x.ptr.p_double[0]+1, _state)+ae_sqr(state.x.ptr.p_double[1]+1, _state)+10000*ae_machineepsilon*ae_randomreal(_state); - state.g.ptr.p_double[0] = 2*(state.x.ptr.p_double[0]+1); - state.g.ptr.p_double[1] = 2*(state.x.ptr.p_double[1]+1); - } - } - minbleicresults(&state, &xf, &rep, _state); - if( (rep.terminationtype<=0||ae_fp_neq(xf.ptr.p_double[0],(double)(0)))||ae_fp_neq(xf.ptr.p_double[1],(double)(0)) ) - { - *err = ae_true; - ae_frame_leave(_state); - return; - } - } - } - - /* - * Deterministic variation of the previous problem. - * - * Consider following problem: - * * boundary constraints x>=0, y>=0 - * * starting point (x0,y0)=(10*MachineEpsilon,1.0) - * / (x+1)^2 + (y+1)^2, for (x,y)<>(x0,y0) - * * f(x,y) = | - * \ (x+1)^2 + (y+1)^2 - 0.1, for (x,y)=(x0,y0) - * - * Such problem contains deterministic numerical noise (-0.1 at - * starting point). Without noise its solution is easy to find. - * However, presence of the noise makes it hard to solve: - * * our first step must be done towards (x1,y1) = (0,1-some_small_value), - * but such step will increase function valye by approximately 0.1 - - * instead of decreasing it. - * - * Naive implementation of BLEIC should fail on such problem. However, - * our improved implementation should solve it correctly. We test - * several variations of inner stopping criteria. - */ - for(pass=1; pass<=passcount; pass++) - { - eps = 1.0E-9; - ae_vector_set_length(&x, 2, _state); - ae_vector_set_length(&bl, 2, _state); - ae_vector_set_length(&bu, 2, _state); - x.ptr.p_double[0] = 10*ae_machineepsilon; - x.ptr.p_double[1] = 1.0; - bl.ptr.p_double[0] = 0.0; - bu.ptr.p_double[0] = _state->v_posinf; - bl.ptr.p_double[1] = 0.0; - bu.ptr.p_double[1] = _state->v_posinf; - for(ckind=0; ckind<=2; ckind++) - { - minbleiccreate(2, &x, &state, _state); - minbleicsetbc(&state, &bl, &bu, _state); - if( ckind==0 ) - { - minbleicsetcond(&state, eps, (double)(0), (double)(0), 0, _state); - } - if( ckind==1 ) - { - minbleicsetcond(&state, (double)(0), eps, (double)(0), 0, _state); - } - if( ckind==2 ) - { - minbleicsetcond(&state, (double)(0), (double)(0), eps, 0, _state); - } - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = ae_sqr(state.x.ptr.p_double[0]+1, _state)+ae_sqr(state.x.ptr.p_double[1]+1, _state); - if( ae_fp_eq(state.x.ptr.p_double[0],x.ptr.p_double[0])&&ae_fp_eq(state.x.ptr.p_double[1],x.ptr.p_double[1]) ) - { - state.f = state.f-0.1; - } - state.g.ptr.p_double[0] = 2*(state.x.ptr.p_double[0]+1); - state.g.ptr.p_double[1] = 2*(state.x.ptr.p_double[1]+1); - } - } - minbleicresults(&state, &xf, &rep, _state); - if( (rep.terminationtype<=0||ae_fp_neq(xf.ptr.p_double[0],(double)(0)))||ae_fp_neq(xf.ptr.p_double[1],(double)(0)) ) - { - *err = ae_true; - ae_frame_leave(_state); - return; - } - } - } - - /* - * Test integrity checks for NAN/INF: - * * algorithm solves optimization problem, which is normal for some time (quadratic) - * * after 5-th step we choose random component of gradient and consistently spoil - * it by NAN or INF. - * * we check that correct termination code is returned (-8) - */ - n = 100; - for(pass=1; pass<=10; pass++) - { - spoiliteration = 5; - stopiteration = 8; - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - - /* - * Gradient can be spoiled by +INF, -INF, NAN - */ - spoilvar = hqrnduniformi(&rs, n, _state); - i = hqrnduniformi(&rs, 3, _state); - spoilval = _state->v_nan; - if( i==0 ) - { - spoilval = _state->v_neginf; - } - if( i==1 ) - { - spoilval = _state->v_posinf; - } - } - else - { - - /* - * Function value can be spoiled only by NAN - * (+INF can be recognized as legitimate value during optimization) - */ - spoilvar = -1; - spoilval = _state->v_nan; - } - spdmatrixrndcond(n, 1.0E5, &fulla, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - minbleiccreate(n, &x0, &state, _state); - minbleicsetcond(&state, 0.0, 0.0, 0.0, stopiteration, _state); - minbleicsetxrep(&state, ae_true, _state); - k = -1; - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.g.ptr.p_double[i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.f = state.f+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.g.ptr.p_double[i] = state.g.ptr.p_double[i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - if( k>=spoiliteration ) - { - if( spoilvar<0 ) - { - state.f = spoilval; - } - else - { - state.g.ptr.p_double[spoilvar] = spoilval; - } - } - continue; - } - if( state.xupdated ) - { - inc(&k, _state); - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minbleicresults(&state, &x1, &rep, _state); - ae_set_error_flag(err, rep.terminationtype!=-8, __FILE__, __LINE__, "testminbleicunit.ap:1603"); - } - - /* - * Check algorithm ability to handle request for termination: - * * to terminate with correct return code = 8 - * * to return point which was "current" at the moment of termination - * - * NOTE: we solve problem with "corrupted" preconditioner which makes it hard - * to converge in less than StopCallIdx iterations - */ - for(pass=1; pass<=50; pass++) - { - n = 3; - ss = (double)(100); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&xlast, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 6+ae_randomreal(_state); - } - ae_vector_set_length(&s, 3, _state); - s.ptr.p_double[0] = 0.00001; - s.ptr.p_double[1] = 0.00001; - s.ptr.p_double[2] = 10000.0; - stopcallidx = ae_randominteger(20, _state); - maxits = 25; - minbleiccreate(n, &x, &state, _state); - minbleicsetcond(&state, (double)(0), (double)(0), (double)(0), maxits, _state); - minbleicsetxrep(&state, ae_true, _state); - minbleicsetprecdiag(&state, &s, _state); - callidx = 0; - terminationrequested = ae_false; - ae_v_move(&xlast.ptr.p_double[0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = ss*ae_sqr(ae_exp(state.x.ptr.p_double[0], _state)-2, _state)+ae_sqr(state.x.ptr.p_double[1], _state)+ae_sqr(state.x.ptr.p_double[2]-state.x.ptr.p_double[0], _state); - state.g.ptr.p_double[0] = 2*ss*(ae_exp(state.x.ptr.p_double[0], _state)-2)*ae_exp(state.x.ptr.p_double[0], _state)+2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0])*(-1); - state.g.ptr.p_double[1] = 2*state.x.ptr.p_double[1]; - state.g.ptr.p_double[2] = 2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0]); - if( callidx==stopcallidx ) - { - minbleicrequesttermination(&state, _state); - terminationrequested = ae_true; - } - inc(&callidx, _state); - continue; - } - if( state.xupdated ) - { - if( !terminationrequested ) - { - ae_v_move(&xlast.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minbleicresults(&state, &x, &rep, _state); - ae_set_error_flag(err, rep.terminationtype!=8, __FILE__, __LINE__, "testminbleicunit.ap:1661"); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(err, ae_fp_neq(x.ptr.p_double[i],xlast.ptr.p_double[i]), __FILE__, __LINE__, "testminbleicunit.ap:1663"); - } - } - - /* - * N-dimensional problem with Ne equality and Ni inequality constraints. - * - * Check that internal SActiveSet object uses efficient algorithm - * to determine initial point: it avoids expensive (N+Ni)-dimensional - * QP subproblem when initial point is feasible w.r.t. constraints. - * - * In order to do so we try to solve 5-dimensional QP problem with - * 2 equality constraints and 1000000 inequality constraints (+box - * constraints). Inefficient algorithm will simply fail to allocate - * enough memory, so we do not have to perform any checks here. - */ - n = 5; - nec = 2; - nic = 1000000; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - for(scaletype=0; scaletype<=1; scaletype++) - { - - /* - * Generate problem - */ - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = hqrnduniformr(&rs, _state); - bl.ptr.p_double[i] = x.ptr.p_double[i]-hqrnduniformr(&rs, _state)*hqrnduniformi(&rs, 2, _state); - bu.ptr.p_double[i] = x.ptr.p_double[i]+hqrnduniformr(&rs, _state)*hqrnduniformi(&rs, 2, _state); - } - ae_matrix_set_length(&c, nec+nic, n+1, _state); - ae_vector_set_length(&ct, nec+nic, _state); - for(i=0; i<=nec+nic-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - v = v+c.ptr.pp_double[i][j]*x.ptr.p_double[j]; - } - c.ptr.pp_double[i][n] = v; - if( i=c'*x0, with c=A*x0 - * * run BLEIC algorithm from initial point x0 for target function f=0.5*x'*A*x - * and check that it stops at x0 (less than 1E-12 away from it) - */ - n = 20; - for(pass=0; pass<=20000; pass++) - { - spdmatrixrndcond(n, 1.0E3, &fulla, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - fulla.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j]*1.0E9; - } - } - ae_vector_set_length(&x0, n, _state); - v = (double)(0); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrnduniformr(&rs, _state); - v = v+ae_sqr(x0.ptr.p_double[i], _state); - } - ae_assert(ae_fp_greater(v,(double)(0)), "MinBLEIC: integrity check failed in the unit test", _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = x0.ptr.p_double[i]/ae_sqrt(v, _state); - } - ae_matrix_set_length(&c, 1, n+1, _state); - ae_vector_set_length(&ct, 1, _state); - ct.ptr.p_int[0] = 1; - c.ptr.pp_double[0][n] = (double)(0); - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&fulla.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - c.ptr.pp_double[0][i] = v; - c.ptr.pp_double[0][n] = c.ptr.pp_double[0][n]+v*x0.ptr.p_double[i]; - } - ae_assert(ae_fp_greater(c.ptr.pp_double[0][n],(double)(0)), "MinBLEIC: integrity check failed in the unit test", _state); - minbleiccreate(n, &x0, &state, _state); - minbleicsetlc(&state, &c, &ct, 1, _state); - minbleicsetcond(&state, 0.0, (double)(0), 1.0E-15, 0, _state); - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&fulla.ptr.pp_double[i][0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state.f = state.f+0.5*v*state.x.ptr.p_double[i]; - state.g.ptr.p_double[i] = v; - } - } - } - minbleicresults(&state, &xf, &rep, _state); - ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminbleicunit.ap:1819"); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(x0.ptr.p_double[i]-xf.ptr.p_double[i], _state),1.0E-12), __FILE__, __LINE__, "testminbleicunit.ap:1821"); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests convergence properties. -We solve several simple problems with different combinations of constraints - -On failure sets Err to True (leaves it unchanged otherwise) -*************************************************************************/ -static void testminbleicunit_testconv(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t passcount; - ae_int_t pass; - ae_vector bl; - ae_vector bu; - ae_vector x; - ae_vector b; - ae_vector tmp; - ae_vector g; - ae_vector xf; - ae_vector xs0; - ae_vector xs1; - ae_matrix a; - ae_matrix c; - ae_matrix ce; - ae_vector ct; - ae_vector nonnegative; - minbleicstate state; - double epsg; - double epsfeas; - double tol; - minbleicreport rep; - snnlssolver nnls; - ae_int_t m; - ae_int_t n; - ae_int_t k; - ae_int_t i; - ae_int_t j; - double v; - double vv; - ae_int_t preckind; - ae_int_t akind; - ae_int_t shiftkind; - ae_int_t bscale; - double tolconstr; - double f0; - double f1; - ae_int_t ccnt; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&bl, 0, sizeof(bl)); - memset(&bu, 0, sizeof(bu)); - memset(&x, 0, sizeof(x)); - memset(&b, 0, sizeof(b)); - memset(&tmp, 0, sizeof(tmp)); - memset(&g, 0, sizeof(g)); - memset(&xf, 0, sizeof(xf)); - memset(&xs0, 0, sizeof(xs0)); - memset(&xs1, 0, sizeof(xs1)); - memset(&a, 0, sizeof(a)); - memset(&c, 0, sizeof(c)); - memset(&ce, 0, sizeof(ce)); - memset(&ct, 0, sizeof(ct)); - memset(&nonnegative, 0, sizeof(nonnegative)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&nnls, 0, sizeof(nnls)); - memset(&rs, 0, sizeof(rs)); - ae_vector_init(&bl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&g, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xs0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xs1, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ce, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - ae_vector_init(&nonnegative, 0, DT_BOOL, _state, ae_true); - _minbleicstate_init(&state, _state, ae_true); - _minbleicreport_init(&rep, _state, ae_true); - _snnlssolver_init(&nnls, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - epsg = 1.0E-8; - epsfeas = 1.0E-8; - tol = 0.001; - passcount = 10; - - /* - * Three closely connected problems: - * * 2-dimensional space - * * octagonal area bounded by: - * * -1<=x<=+1 - * * -1<=y<=+1 - * * x+y<=1.5 - * * x-y<=1.5 - * * -x+y<=1.5 - * * -x-y<=1.5 - * * several target functions: - * * f0=x+0.001*y, minimum at x=-1, y=-0.5 - * * f1=(x+10)^2+y^2, minimum at x=-1, y=0 - * * f2=(x+10)^2+(y-0.6)^2, minimum at x=-1, y=0.5 - */ - ae_vector_set_length(&x, 2, _state); - ae_vector_set_length(&bl, 2, _state); - ae_vector_set_length(&bu, 2, _state); - ae_matrix_set_length(&c, 4, 3, _state); - ae_vector_set_length(&ct, 4, _state); - bl.ptr.p_double[0] = (double)(-1); - bl.ptr.p_double[1] = (double)(-1); - bu.ptr.p_double[0] = (double)(1); - bu.ptr.p_double[1] = (double)(1); - c.ptr.pp_double[0][0] = (double)(1); - c.ptr.pp_double[0][1] = (double)(1); - c.ptr.pp_double[0][2] = 1.5; - ct.ptr.p_int[0] = -1; - c.ptr.pp_double[1][0] = (double)(1); - c.ptr.pp_double[1][1] = (double)(-1); - c.ptr.pp_double[1][2] = 1.5; - ct.ptr.p_int[1] = -1; - c.ptr.pp_double[2][0] = (double)(-1); - c.ptr.pp_double[2][1] = (double)(1); - c.ptr.pp_double[2][2] = 1.5; - ct.ptr.p_int[2] = -1; - c.ptr.pp_double[3][0] = (double)(-1); - c.ptr.pp_double[3][1] = (double)(-1); - c.ptr.pp_double[3][2] = 1.5; - ct.ptr.p_int[3] = -1; - for(pass=1; pass<=passcount; pass++) - { - - /* - * f0 - */ - x.ptr.p_double[0] = 0.2*ae_randomreal(_state)-0.1; - x.ptr.p_double[1] = 0.2*ae_randomreal(_state)-0.1; - minbleiccreate(2, &x, &state, _state); - minbleicsetbc(&state, &bl, &bu, _state); - minbleicsetlc(&state, &c, &ct, 4, _state); - minbleicsetcond(&state, epsg, 0.0, 0.0, 0, _state); - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = state.x.ptr.p_double[0]+0.001*state.x.ptr.p_double[1]; - state.g.ptr.p_double[0] = (double)(1); - state.g.ptr.p_double[1] = 0.001; - } - } - minbleicresults(&state, &x, &rep, _state); - if( rep.terminationtype>0 ) - { - *err = *err||ae_fp_greater(ae_fabs(x.ptr.p_double[0]+1, _state),tol); - *err = *err||ae_fp_greater(ae_fabs(x.ptr.p_double[1]+0.5, _state),tol); - } - else - { - *err = ae_true; - } - - /* - * f1 - */ - x.ptr.p_double[0] = 0.2*ae_randomreal(_state)-0.1; - x.ptr.p_double[1] = 0.2*ae_randomreal(_state)-0.1; - minbleiccreate(2, &x, &state, _state); - minbleicsetbc(&state, &bl, &bu, _state); - minbleicsetlc(&state, &c, &ct, 4, _state); - minbleicsetcond(&state, epsg, 0.0, 0.0, 0, _state); - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = ae_sqr(state.x.ptr.p_double[0]+10, _state)+ae_sqr(state.x.ptr.p_double[1], _state); - state.g.ptr.p_double[0] = 2*(state.x.ptr.p_double[0]+10); - state.g.ptr.p_double[1] = 2*state.x.ptr.p_double[1]; - } - } - minbleicresults(&state, &x, &rep, _state); - if( rep.terminationtype>0 ) - { - *err = *err||ae_fp_greater(ae_fabs(x.ptr.p_double[0]+1, _state),tol); - *err = *err||ae_fp_greater(ae_fabs(x.ptr.p_double[1], _state),tol); - } - else - { - *err = ae_true; - } - - /* - * f2 - */ - x.ptr.p_double[0] = 0.2*ae_randomreal(_state)-0.1; - x.ptr.p_double[1] = 0.2*ae_randomreal(_state)-0.1; - minbleiccreate(2, &x, &state, _state); - minbleicsetbc(&state, &bl, &bu, _state); - minbleicsetlc(&state, &c, &ct, 4, _state); - minbleicsetcond(&state, epsg, 0.0, 0.0, 0, _state); - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = ae_sqr(state.x.ptr.p_double[0]+10, _state)+ae_sqr(state.x.ptr.p_double[1]-0.6, _state); - state.g.ptr.p_double[0] = 2*(state.x.ptr.p_double[0]+10); - state.g.ptr.p_double[1] = 2*(state.x.ptr.p_double[1]-0.6); - } - } - minbleicresults(&state, &x, &rep, _state); - if( rep.terminationtype>0 ) - { - *err = *err||ae_fp_greater(ae_fabs(x.ptr.p_double[0]+1, _state),tol); - *err = *err||ae_fp_greater(ae_fabs(x.ptr.p_double[1]-0.5, _state),tol); - } - else - { - *err = ae_true; - } - } - - /* - * Degenerate optimization problem with excessive constraints. - * - * * N=3..10, M=N div 3, K = 2*N - * * f(x) = 0.5*|A*x-b|^2, where A is MxN random matrix, b is Mx1 random vector - * * bound constraint: - * a) Ci=x[i]=Ci for i=0..M-1 - * b) 0<=x[i]<=1 for i=M..N-1 - * * linear constraints (for fixed feasible xf and random ai): - * a) ai*x = ai*xf for i=0..M-1 - * b) ai*x <= ai*xf+random(0.1,1.0) for i=M..K-1 - * * preconditioner is chosen at random (we just want to be - * sure that preconditioning won't prevent us from detecting - * infeasible point): - * a) unit preconditioner - * b) random diagonal-based preconditioner - * c) random scale-based preconditioner - * * we choose two random initial points from interior of the area - * given by bound constraints. - * - * We do not know analytic solution of this problem, and we do not need - * to solve it :) we just perform two restarts from two different initial - * points and check that both solutions give approximately same function - * value. - */ - for(preckind=0; preckind<=2; preckind++) - { - for(n=3; n<=10; n++) - { - - /* - * Generate problem - */ - m = n/3; - k = 2*n; - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&xs0, n, _state); - ae_vector_set_length(&xs1, n, _state); - ae_vector_set_length(&xf, n, _state); - for(i=0; i<=n-1; i++) - { - if( i=-2; bscale--) - { - - /* - * Generate A, B and initial point - */ - ae_matrix_set_length(&a, n, n, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = ae_pow((double)(10), (double)(bscale), _state)*hqrndnormal(&rs, _state); - x.ptr.p_double[i] = hqrnduniformr(&rs, _state)-0.5; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - if( akind==1 ) - { - - /* - * Dense well conditioned SPD - */ - spdmatrixrndcond(n, 50.0, &a, _state); - } - if( akind==2 ) - { - - /* - * Dense well conditioned indefinite - */ - smatrixrndcond(n, 50.0, &a, _state); - } - if( akind==3 ) - { - - /* - * Low rank - */ - ae_vector_set_length(&tmp, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - for(k=1; k<=ae_minint(3, n-1, _state); k++) - { - for(i=0; i<=n-1; i++) - { - tmp.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - v = hqrndnormal(&rs, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j]; - } - } - } - } - - /* - * Generate constraints - */ - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - for(i=0; i<=n-1; i++) - { - bl.ptr.p_double[i] = -1.0; - bu.ptr.p_double[i] = 1.0; - } - ccnt = ae_round(ae_pow((double)(2), (double)(n), _state), _state); - ae_matrix_set_length(&c, ccnt, n+1, _state); - ae_vector_set_length(&ct, ccnt, _state); - for(i=0; i<=ccnt-1; i++) - { - ct.ptr.p_int[i] = -1; - k = i; - c.ptr.pp_double[i][n] = ae_sign((double)(shiftkind), _state)*ae_pow((double)(10), ae_fabs((double)(shiftkind), _state), _state)*ae_machineepsilon; - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = (double)(2*(k%2)-1); - c.ptr.pp_double[i][n] = c.ptr.pp_double[i][n]+c.ptr.pp_double[i][j]*c.ptr.pp_double[i][j]; - k = k/2; - } - } - - /* - * Create and optimize - */ - minbleiccreate(n, &x, &state, _state); - minbleicsetbc(&state, &bl, &bu, _state); - minbleicsetlc(&state, &c, &ct, ccnt, _state); - minbleicsetcond(&state, 1.0E-9, 0.0, 0.0, 0, _state); - while(minbleiciteration(&state, _state)) - { - ae_assert(state.needfg, "Assertion failed", _state); - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+state.x.ptr.p_double[i]*b.ptr.p_double[i]; - state.g.ptr.p_double[i] = b.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state.f = state.f+0.5*state.x.ptr.p_double[i]*v; - state.g.ptr.p_double[i] = state.g.ptr.p_double[i]+v; - } - } - minbleicresults(&state, &xs0, &rep, _state); - ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminbleicunit.ap:2341"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - - /* - * Evaluate gradient at solution and test - */ - vv = 0.0; - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xs0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = v+b.ptr.p_double[i]; - if( ae_fp_less_eq(xs0.ptr.p_double[i],bl.ptr.p_double[i]+tolconstr)&&ae_fp_greater(v,(double)(0)) ) - { - v = 0.0; - } - if( ae_fp_greater_eq(xs0.ptr.p_double[i],bu.ptr.p_double[i]-tolconstr)&&ae_fp_less(v,(double)(0)) ) - { - v = 0.0; - } - vv = vv+ae_sqr(v, _state); - } - vv = ae_sqrt(vv, _state); - ae_set_error_flag(err, ae_fp_greater(vv,1.0E-5), __FILE__, __LINE__, "testminbleicunit.ap:2365"); - } - } - } - } - - /* - * Convex/nonconvex optimization problem with combination of - * box and linear constraints: - * - * * N=2..8 - * * f = 0.5*x'*A*x+b'*x - * * b has normally distributed entries with scale 10^BScale - * * several kinds of A are tried: zero, well conditioned SPD, - * well conditioned indefinite, low rank - * * box constraints: x[i] in [-1,+1] - * * initial point x0 = [0 0 ... 0 0] - * * CCnt=min(3,N-1) general linear constraints of form (c,x)=0. - * random mix of equality/inequality constraints is tried. - * x0 is guaranteed to be feasible. - * - * We check that constrained gradient is close to zero at solution. - * Inequality constraint is considered active if distance to boundary - * is less than TolConstr. We use nonnegative least squares solver - * in order to compute constrained gradient. - */ - tolconstr = 1.0E-8; - for(n=2; n<=8; n++) - { - for(akind=0; akind<=3; akind++) - { - for(bscale=0; bscale>=-2; bscale--) - { - - /* - * Generate A, B and initial point - */ - ae_matrix_set_length(&a, n, n, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = ae_pow((double)(10), (double)(bscale), _state)*hqrndnormal(&rs, _state); - x.ptr.p_double[i] = 0.0; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - if( akind==1 ) - { - - /* - * Dense well conditioned SPD - */ - spdmatrixrndcond(n, 50.0, &a, _state); - } - if( akind==2 ) - { - - /* - * Dense well conditioned indefinite - */ - smatrixrndcond(n, 50.0, &a, _state); - } - if( akind==3 ) - { - - /* - * Low rank - */ - ae_vector_set_length(&tmp, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - for(k=1; k<=ae_minint(3, n-1, _state); k++) - { - for(i=0; i<=n-1; i++) - { - tmp.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - v = hqrndnormal(&rs, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j]; - } - } - } - } - - /* - * Generate constraints - */ - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - for(i=0; i<=n-1; i++) - { - bl.ptr.p_double[i] = -1.0; - bu.ptr.p_double[i] = 1.0; - } - ccnt = ae_minint(3, n-1, _state); - ae_matrix_set_length(&c, ccnt, n+1, _state); - ae_vector_set_length(&ct, ccnt, _state); - for(i=0; i<=ccnt-1; i++) - { - ct.ptr.p_int[i] = hqrnduniformi(&rs, 3, _state)-1; - c.ptr.pp_double[i][n] = 0.0; - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5; - } - } - - /* - * Create and optimize - */ - minbleiccreate(n, &x, &state, _state); - minbleicsetbc(&state, &bl, &bu, _state); - minbleicsetlc(&state, &c, &ct, ccnt, _state); - minbleicsetcond(&state, 1.0E-9, 0.0, 0.0, 0, _state); - while(minbleiciteration(&state, _state)) - { - ae_assert(state.needfg, "Assertion failed", _state); - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+state.x.ptr.p_double[i]*b.ptr.p_double[i]; - state.g.ptr.p_double[i] = b.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state.f = state.f+0.5*state.x.ptr.p_double[i]*v; - state.g.ptr.p_double[i] = state.g.ptr.p_double[i]+v; - } - } - minbleicresults(&state, &xs0, &rep, _state); - ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminbleicunit.ap:2487"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - - /* - * 1. evaluate unconstrained gradient at solution - * - * 2. calculate constrained gradient (NNLS solver is used - * to evaluate gradient subject to active constraints). - * In order to do this we form CE matrix, matrix of active - * constraints (columns store constraint vectors). Then - * we try to approximate gradient vector by columns of CE, - * subject to non-negativity restriction placed on variables - * corresponding to inequality constraints. - * - * Residual from such regression is a constrained gradient vector. - */ - ae_vector_set_length(&g, n, _state); - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xs0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - g.ptr.p_double[i] = v+b.ptr.p_double[i]; - } - ae_matrix_set_length(&ce, n, n+ccnt, _state); - ae_vector_set_length(&nonnegative, n+ccnt, _state); - k = 0; - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(err, ae_fp_less(xs0.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testminbleicunit.ap:2515"); - ae_set_error_flag(err, ae_fp_greater(xs0.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testminbleicunit.ap:2516"); - if( ae_fp_less_eq(xs0.ptr.p_double[i],bl.ptr.p_double[i]+tolconstr) ) - { - for(j=0; j<=n-1; j++) - { - ce.ptr.pp_double[j][k] = 0.0; - } - ce.ptr.pp_double[i][k] = 1.0; - nonnegative.ptr.p_bool[k] = ae_true; - inc(&k, _state); - continue; - } - if( ae_fp_greater_eq(xs0.ptr.p_double[i],bu.ptr.p_double[i]-tolconstr) ) - { - for(j=0; j<=n-1; j++) - { - ce.ptr.pp_double[j][k] = 0.0; - } - ce.ptr.pp_double[i][k] = -1.0; - nonnegative.ptr.p_bool[k] = ae_true; - inc(&k, _state); - continue; - } - } - for(i=0; i<=ccnt-1; i++) - { - v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &xs0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = v-c.ptr.pp_double[i][n]; - ae_set_error_flag(err, ct.ptr.p_int[i]==0&&ae_fp_greater(ae_fabs(v, _state),tolconstr), __FILE__, __LINE__, "testminbleicunit.ap:2540"); - ae_set_error_flag(err, ct.ptr.p_int[i]>0&&ae_fp_less(v,-tolconstr), __FILE__, __LINE__, "testminbleicunit.ap:2541"); - ae_set_error_flag(err, ct.ptr.p_int[i]<0&&ae_fp_greater(v,tolconstr), __FILE__, __LINE__, "testminbleicunit.ap:2542"); - if( ct.ptr.p_int[i]==0 ) - { - for(j=0; j<=n-1; j++) - { - ce.ptr.pp_double[j][k] = c.ptr.pp_double[i][j]; - } - nonnegative.ptr.p_bool[k] = ae_false; - inc(&k, _state); - continue; - } - if( (ct.ptr.p_int[i]>0&&ae_fp_less_eq(v,tolconstr))||(ct.ptr.p_int[i]<0&&ae_fp_greater_eq(v,-tolconstr)) ) - { - for(j=0; j<=n-1; j++) - { - ce.ptr.pp_double[j][k] = ae_sign((double)(ct.ptr.p_int[i]), _state)*c.ptr.pp_double[i][j]; - } - nonnegative.ptr.p_bool[k] = ae_true; - inc(&k, _state); - continue; - } - } - snnlsinit(0, 0, 0, &nnls, _state); - snnlssetproblem(&nnls, &ce, &g, 0, k, n, _state); - for(i=0; i<=k-1; i++) - { - if( !nonnegative.ptr.p_bool[i] ) - { - snnlsdropnnc(&nnls, i, _state); - } - } - snnlssolve(&nnls, &tmp, _state); - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - g.ptr.p_double[j] = g.ptr.p_double[j]-tmp.ptr.p_double[i]*ce.ptr.pp_double[j][i]; - } - } - vv = ae_v_dotproduct(&g.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - vv = ae_sqrt(vv, _state); - ae_set_error_flag(err, ae_fp_greater(vv,1.0E-5), __FILE__, __LINE__, "testminbleicunit.ap:2571"); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests preconditioning - -On failure sets Err to True (leaves it unchanged otherwise) -*************************************************************************/ -static void testminbleicunit_testpreconditioning(ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t pass; - ae_int_t n; - ae_vector x; - ae_vector x0; - ae_int_t i; - ae_int_t k; - ae_matrix v; - ae_matrix c; - ae_vector ct; - ae_vector bl; - ae_vector bu; - ae_vector vd; - ae_vector d; - ae_vector units; - ae_vector s; - ae_int_t cntb1; - ae_int_t cntb2; - ae_int_t cntg1; - ae_int_t cntg2; - double epsg; - ae_vector diagh; - minbleicstate state; - minbleicreport rep; - ae_int_t ckind; - ae_int_t fk; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&x0, 0, sizeof(x0)); - memset(&v, 0, sizeof(v)); - memset(&c, 0, sizeof(c)); - memset(&ct, 0, sizeof(ct)); - memset(&bl, 0, sizeof(bl)); - memset(&bu, 0, sizeof(bu)); - memset(&vd, 0, sizeof(vd)); - memset(&d, 0, sizeof(d)); - memset(&units, 0, sizeof(units)); - memset(&s, 0, sizeof(s)); - memset(&diagh, 0, sizeof(diagh)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - ae_vector_init(&bl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vd, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&units, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&diagh, 0, DT_REAL, _state, ae_true); - _minbleicstate_init(&state, _state, ae_true); - _minbleicreport_init(&rep, _state, ae_true); - - - /* - * Preconditioner test 1. - * - * If - * * B1 is default preconditioner with unit scale - * * G1 is diagonal preconditioner based on approximate diagonal of Hessian matrix - * * B2 is default preconditioner with non-unit scale S[i]=1/sqrt(h[i]) - * * G2 is scale-based preconditioner with non-unit scale S[i]=1/sqrt(h[i]) - * then B1 is worse than G1, B2 is worse than G2. - * "Worse" means more iterations to converge. - * - * Test problem setup: - * * f(x) = sum( ((i*i+1)*x[i])^2, i=0..N-1) - * * constraints: - * 0) absent - * 1) boundary only - * 2) linear equality only - * 3) combination of boundary and linear equality constraints - * - * N - problem size - * K - number of repeated passes (should be large enough to average out random factors) - */ - k = 100; - epsg = 1.0E-8; - for(n=10; n<=10; n++) - { - for(ckind=0; ckind<=3; ckind++) - { - fk = 1; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&units, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = (double)(0); - units.ptr.p_double[i] = (double)(1); - } - minbleiccreate(n, &x, &state, _state); - minbleicsetcond(&state, epsg, 0.0, 0.0, 0, _state); - if( ckind==1||ckind==3 ) - { - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - for(i=0; i<=n-1; i++) - { - bl.ptr.p_double[i] = (double)(-1); - bu.ptr.p_double[i] = (double)(1); - } - minbleicsetbc(&state, &bl, &bu, _state); - } - if( ckind==2||ckind==3 ) - { - ae_matrix_set_length(&c, 1, n+1, _state); - ae_vector_set_length(&ct, 1, _state); - ct.ptr.p_int[0] = ae_randominteger(3, _state)-1; - for(i=0; i<=n-1; i++) - { - c.ptr.pp_double[0][i] = 2*ae_randomreal(_state)-1; - } - c.ptr.pp_double[0][n] = (double)(0); - minbleicsetlc(&state, &c, &ct, 1, _state); - } - - /* - * Test it with default preconditioner VS. perturbed diagonal preconditioner - */ - minbleicsetprecdefault(&state, _state); - minbleicsetscale(&state, &units, _state); - cntb1 = 0; - for(pass=0; pass<=k-1; pass++) - { - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - minbleicrestartfrom(&state, &x, _state); - while(minbleiciteration(&state, _state)) - { - testminbleicunit_calciip2(&state, n, fk, _state); - } - minbleicresults(&state, &x, &rep, _state); - cntb1 = cntb1+rep.inneriterationscount; - *err = *err||rep.terminationtype<=0; - } - ae_vector_set_length(&diagh, n, _state); - for(i=0; i<=n-1; i++) - { - diagh.ptr.p_double[i] = 2*ae_pow((double)(i*i+1), (double)(2*fk), _state)*(0.8+0.4*ae_randomreal(_state)); - } - minbleicsetprecdiag(&state, &diagh, _state); - minbleicsetscale(&state, &units, _state); - cntg1 = 0; - for(pass=0; pass<=k-1; pass++) - { - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - minbleicrestartfrom(&state, &x, _state); - while(minbleiciteration(&state, _state)) - { - testminbleicunit_calciip2(&state, n, fk, _state); - } - minbleicresults(&state, &x, &rep, _state); - cntg1 = cntg1+rep.inneriterationscount; - *err = *err||rep.terminationtype<=0; - } - *err = *err||cntb1=0, __FILE__, __LINE__, "testminbleicunit.ap:3117"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx>=0, __FILE__, __LINE__, "testminbleicunit.ap:3118"); - ae_set_error_flag(wereerrors, ogrep.nonc1test0positive, __FILE__, __LINE__, "testminbleicunit.ap:3119"); - ae_set_error_flag(wereerrors, ogrep.nonc1test1positive, __FILE__, __LINE__, "testminbleicunit.ap:3120"); - - /* - * Test gradient checking functionality, try various - * defect types: - * * accidental zeroing of some gradient component - * * accidental addition of 1.0 to some component - * * accidental multiplication by 2.0 - * Try distorting both target and constraints. - */ - diffstep = 0.001; - n = 10; - for(skind=0; skind<=1; skind++) - { - for(defecttype=-1; defecttype<=2; defecttype++) - { - varidx = hqrnduniformi(&rs, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&s, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = ae_pow((double)(10), skind*(30*hqrnduniformr(&rs, _state)-15), _state); - x0.ptr.p_double[i] = (1.0+0.1*i)*s.ptr.p_double[i]; - j = hqrnduniformi(&rs, 3, _state); - bndl.ptr.p_double[i] = -100*s.ptr.p_double[i]; - bndu.ptr.p_double[i] = 100*s.ptr.p_double[i]; - if( j==1 ) - { - bndl.ptr.p_double[i] = x0.ptr.p_double[i]; - } - if( j==2 ) - { - bndu.ptr.p_double[i] = x0.ptr.p_double[i]; - } - } - spdmatrixrndcond(n, 1.0E3, &a, _state); - spdmatrixrndcond(n, 1.0E3, &a1, _state); - minbleiccreate(n, &x0, &state, _state); - minbleicoptguardgradient(&state, diffstep, _state); - minbleicsetcond(&state, (double)(0), (double)(0), 1.0E-9, 10, _state); - minbleicsetscale(&state, &s, _state); - minbleicsetbc(&state, &bndl, &bndu, _state); - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(wereerrors, ae_fp_less(state.x.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminbleicunit.ap:3167"); - ae_set_error_flag(wereerrors, ae_fp_greater(state.x.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminbleicunit.ap:3168"); - } - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.f = state.f+0.5*(state.x.ptr.p_double[i]/s.ptr.p_double[i])*v; - state.g.ptr.p_double[i] = v; - } - if( defecttype==0 ) - { - state.g.ptr.p_double[varidx] = (double)(0); - } - if( defecttype==1 ) - { - state.g.ptr.p_double[varidx] = state.g.ptr.p_double[varidx]+1; - } - if( defecttype==2 ) - { - state.g.ptr.p_double[varidx] = state.g.ptr.p_double[varidx]*2; - } - for(i=0; i<=n-1; i++) - { - state.g.ptr.p_double[i] = state.g.ptr.p_double[i]/s.ptr.p_double[i]; - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minbleicresults(&state, &x1, &rep, _state); - minbleicoptguardresults(&state, &ogrep, _state); - - /* - * Check that something is returned - */ - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminbleicunit.ap:3201"); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3202"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Compute reference values for true and spoiled Jacobian at X0 - */ - ae_set_error_flag(wereerrors, !isfinitevector(&ogrep.badgradxbase, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3209"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&jactrue, 1, n, _state); - ae_matrix_set_length(&jacdefect, 1, n, _state); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+ogrep.badgradxbase.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - jactrue.ptr.pp_double[0][i] = v; - jacdefect.ptr.pp_double[0][i] = v; - } - if( defecttype==0 ) - { - jacdefect.ptr.pp_double[0][varidx] = (double)(0); - } - if( defecttype==1 ) - { - jacdefect.ptr.pp_double[0][varidx] = jacdefect.ptr.pp_double[0][varidx]+1; - } - if( defecttype==2 ) - { - jacdefect.ptr.pp_double[0][varidx] = jacdefect.ptr.pp_double[0][varidx]*2; - } - for(i=0; i<=n-1; i++) - { - jactrue.ptr.pp_double[0][i] = jactrue.ptr.pp_double[0][i]/s.ptr.p_double[i]; - jacdefect.ptr.pp_double[0][i] = jacdefect.ptr.pp_double[0][i]/s.ptr.p_double[i]; - } - - /* - * Check OptGuard report - */ - ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgraduser, 1, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3237"); - ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgradnum, 1, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3238"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - if( defecttype>=0 ) - { - ae_set_error_flag(wereerrors, !ogrep.badgradsuspected, __FILE__, __LINE__, "testminbleicunit.ap:3243"); - ae_set_error_flag(wereerrors, ogrep.badgradfidx!=0, __FILE__, __LINE__, "testminbleicunit.ap:3244"); - ae_set_error_flag(wereerrors, ogrep.badgradvidx!=varidx, __FILE__, __LINE__, "testminbleicunit.ap:3245"); - } - else - { - ae_set_error_flag(wereerrors, ogrep.badgradsuspected, __FILE__, __LINE__, "testminbleicunit.ap:3249"); - ae_set_error_flag(wereerrors, ogrep.badgradfidx!=-1, __FILE__, __LINE__, "testminbleicunit.ap:3250"); - ae_set_error_flag(wereerrors, ogrep.badgradvidx!=-1, __FILE__, __LINE__, "testminbleicunit.ap:3251"); - } - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jactrue.ptr.pp_double[0][j]-ogrep.badgradnum.ptr.pp_double[0][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testminbleicunit.ap:3255"); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jacdefect.ptr.pp_double[0][j]-ogrep.badgraduser.ptr.pp_double[0][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testminbleicunit.ap:3256"); - } - } - } - - /* - * A test for detection of C1 continuity violations in the target. - * - * Target function is a sum of |(x,c_i)| for i=1..N. - * No constraints is present. - * Analytic gradient is provided. - * - * OptGuard should be able to detect violations in more than - * 99.9% of runs; it means that 100 runs should have no more than 4 - * failures in all cases (even after multiple repeated tests; according - * to the binomial distribution quantiles). - * - * We select some N and perform exhaustive search for this N. - */ - passcount = 100; - maxfails = 4; - maxc1test0fails = 10; - maxc1test1fails = 10; - n = 1+hqrnduniformi(&rs, 10, _state); - failurecounter = 0; - c1test0fails = 0; - c1test1fails = 0; - avgstr0len = (double)(0); - avglng0len = (double)(0); - avgstr1len = (double)(0); - avglng1len = (double)(0); - for(pass=1; pass<=passcount; pass++) - { - - /* - * Formulate problem - */ - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - - /* - * Create and try to solve - */ - minbleiccreate(n, &x0, &state, _state); - minbleicsetcond(&state, (double)(0), (double)(0), 1.0E-9, 50, _state); - minbleicsetscale(&state, &s, _state); - minbleicoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminbleicunit_maxoptguardlevel, _state), _state); - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.g.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.f = state.f+ae_fabs(v, _state); - v = (double)(ae_sign(v, _state)); - for(j=0; j<=n-1; j++) - { - state.g.ptr.p_double[j] = state.g.ptr.p_double[j]+v*a.ptr.pp_double[i][j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minbleicresults(&state, &x1, &rep, _state); - minbleicoptguardresults(&state, &ogrep, _state); - - /* - * Check basic properties of the solution - */ - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3337"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminbleicunit.ap:3338"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check generic OptGuard report: distinguish between "hard" - * failures which result in immediate termination - * (C0 violation being reported) and "soft" ones - * (C1 violation is NOT reported) which accumulate - * until we exhaust limit. - */ - ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminbleicunit.ap:3349"); - ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminbleicunit.ap:3350"); - failed = ae_false; - failed = failed||optguardallclear(&ogrep, _state); - failed = failed||!ogrep.nonc1suspected; - failed = failed||ogrep.nonc1fidx!=0; - if( failed ) - { - inc(&failurecounter, _state); - } - - /* - * Check C1 continuity test #0 - */ - minbleicoptguardnonc1test0results(&state, &ognonc1test0strrep, &ognonc1test0lngrep, _state); - minbleicoptguardnonc1test1results(&state, &ognonc1test1strrep, &ognonc1test1lngrep, _state); - if( ogrep.nonc1test0positive ) - { - ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminbleicunit.ap:3365"); - ae_set_error_flag(wereerrors, !ognonc1test0strrep.positive, __FILE__, __LINE__, "testminbleicunit.ap:3366"); - ae_set_error_flag(wereerrors, !ognonc1test0lngrep.positive, __FILE__, __LINE__, "testminbleicunit.ap:3367"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testminbleicunit.ap:3368"); - testminbleicunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0strrep, &a, n, _state); - testminbleicunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0lngrep, &a, n, _state); - avgstr0len = avgstr0len+(double)ognonc1test0strrep.cnt/(double)passcount; - avglng0len = avglng0len+(double)ognonc1test0lngrep.cnt/(double)passcount; - } - else - { - ae_set_error_flag(wereerrors, ognonc1test0strrep.positive, __FILE__, __LINE__, "testminbleicunit.ap:3376"); - ae_set_error_flag(wereerrors, ognonc1test0lngrep.positive, __FILE__, __LINE__, "testminbleicunit.ap:3377"); - testminbleicunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0strrep, &a, n, _state); - testminbleicunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0lngrep, &a, n, _state); - inc(&c1test0fails, _state); - } - if( ogrep.nonc1test1positive ) - { - ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminbleicunit.ap:3384"); - ae_set_error_flag(wereerrors, !ognonc1test1strrep.positive, __FILE__, __LINE__, "testminbleicunit.ap:3385"); - ae_set_error_flag(wereerrors, !ognonc1test1lngrep.positive, __FILE__, __LINE__, "testminbleicunit.ap:3386"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testminbleicunit.ap:3387"); - testminbleicunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1strrep, &a, n, _state); - testminbleicunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1lngrep, &a, n, _state); - avgstr1len = avgstr1len+(double)ognonc1test1strrep.cnt/(double)passcount; - avglng1len = avglng1len+(double)ognonc1test1lngrep.cnt/(double)passcount; - } - else - { - ae_set_error_flag(wereerrors, ognonc1test1strrep.positive, __FILE__, __LINE__, "testminbleicunit.ap:3395"); - ae_set_error_flag(wereerrors, ognonc1test1lngrep.positive, __FILE__, __LINE__, "testminbleicunit.ap:3396"); - testminbleicunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1strrep, &a, n, _state); - testminbleicunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1lngrep, &a, n, _state); - inc(&c1test1fails, _state); - } - } - ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testminbleicunit.ap:3403"); - ae_set_error_flag(wereerrors, c1test0fails>maxc1test0fails, __FILE__, __LINE__, "testminbleicunit.ap:3404"); - ae_set_error_flag(wereerrors, c1test1fails>maxc1test1fails, __FILE__, __LINE__, "testminbleicunit.ap:3405"); - ae_set_error_flag(wereerrors, ae_fp_less_eq(avglng0len,avgstr0len), __FILE__, __LINE__, "testminbleicunit.ap:3406"); - ae_set_error_flag(wereerrors, ae_fp_less_eq(avglng1len,avgstr1len), __FILE__, __LINE__, "testminbleicunit.ap:3407"); - - /* - * Detection of C1 continuity violations in the target under numerical differentiation: - * * target function is a sum of |(x,c_i)| for i=1..N. - * * no constraints is present. - * * analytic gradient is provided. - * - * OptGuard should always be able to detect violations in more than - * 99% of runs (note: reduced strength when compared with analytic gradient); - * it means that 100 runs should have no more than 10 failures in all cases - * (even after multiple repeated tests; according to the binomial distribution - * quantiles). - * - * We select some N and perform exhaustive search for this N. - */ - diffstep = 0.0001; - passcount = 100; - maxfails = 10; - n = 1+hqrnduniformi(&rs, 10, _state); - failurecounter = 0; - for(pass=1; pass<=passcount; pass++) - { - - /* - * Formulate problem - */ - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = 0.01*ae_pow((double)(2), 0.33*hqrndnormal(&rs, _state), _state); - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - - /* - * Create and try to solve - */ - minbleiccreatef(n, &x0, diffstep, &state, _state); - minbleicsetcond(&state, (double)(0), (double)(0), 1.0E-9, 50, _state); - minbleicoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminbleicunit_maxoptguardlevel, _state), _state); - while(minbleiciteration(&state, _state)) - { - if( state.needf ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.f = state.f+ae_fabs(v, _state); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minbleicresults(&state, &x1, &rep, _state); - minbleicoptguardresults(&state, &ogrep, _state); - - /* - * Check basic properties of the solution - */ - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3472"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminbleicunit.ap:3473"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check OptGuard report: distinguish between "hard" - * failures which result in immediate termination - * (C0 violation being reported) and "soft" ones - * (C1 violation is NOT reported) which accumulate - * until we exhaust limit. - */ - ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminbleicunit.ap:3484"); - ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminbleicunit.ap:3485"); - failed = ae_false; - failed = failed||optguardallclear(&ogrep, _state); - failed = failed||!ogrep.nonc1suspected; - failed = failed||ogrep.nonc1fidx!=0; - if( failed ) - { - inc(&failurecounter, _state); - } - } - ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testminbleicunit.ap:3493"); - - /* - * Make sure than no false positives are reported for larger - * problems where numerical noise can be an issue: - * * N=100 dimensions - * * positive-definite quadratic programming problem - * * upper limit on iterations count, MaxIts=25 - * We simply test that OptGuard does not return error code. - */ - n = 100; - spdmatrixrndcond(n, 1.0E2, &a, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - x0.ptr.p_double[i] = ae_pow(2.0, hqrndnormal(&rs, _state), _state); - } - minbleiccreate(n, &x0, &state, _state); - minbleicoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminbleicunit_maxoptguardlevel, _state), _state); - minbleicsetcond(&state, (double)(0), (double)(0), 1.0E-9, 25, _state); - while(minbleiciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.g.ptr.p_double[i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.f = state.f+0.5*state.x.ptr.p_double[i]*a.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.g.ptr.p_double[i] = state.g.ptr.p_double[i]+a.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minbleicresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3536"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminbleicunit.ap:3537"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - minbleicoptguardresults(&state, &ogrep, _state); - ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminbleicunit.ap:3541"); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests report of "non-C1" test #0 for task #0 -given by matrix A. - -On failure sets error flag. -*************************************************************************/ -static void testminbleicunit_testoptguardc1test0reportfortask0(ae_bool* err, - optguardnonc1test0report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double vv; - double va; - double vb; - ae_bool hasc1discontinuities; - - - if( rep->positive ) - { - - /* - * Check positive report, first checks - */ - ae_set_error_flag(err, rep->fidx!=0, __FILE__, __LINE__, "testminbleicunit.ap:3568"); - ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testminbleicunit.ap:3569"); - ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testminbleicunit.ap:3570"); - ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testminbleicunit.ap:3571"); - ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testminbleicunit.ap:3572"); - ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testminbleicunit.ap:3573"); - ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testminbleicunit.ap:3574"); - ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testminbleicunit.ap:3575"); - ae_set_error_flag(err, rep->f.cnt!=rep->cnt, __FILE__, __LINE__, "testminbleicunit.ap:3576"); - ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3577"); - ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3578"); - ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testminbleicunit.ap:3579"); - ae_set_error_flag(err, !isfinitevector(&rep->f, rep->cnt, _state), __FILE__, __LINE__, "testminbleicunit.ap:3580"); - if( *err ) - { - return; - } - - /* - * Check consistency of X0, D, Stp and F - */ - for(k=0; k<=rep->cnt-2; k++) - { - ae_set_error_flag(err, ae_fp_greater_eq(rep->stp.ptr.p_double[k],rep->stp.ptr.p_double[k+1]), __FILE__, __LINE__, "testminbleicunit.ap:3588"); - } - for(k=0; k<=rep->cnt-1; k++) - { - v = (double)(0); - for(i=0; i<=n-1; i++) - { - vv = (double)(0); - for(j=0; j<=n-1; j++) - { - vv = vv+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[k]); - } - v = v+ae_fabs(vv, _state); - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-rep->f.ptr.p_double[k], _state),1.0E-6*ae_maxreal(ae_fabs(v, _state), (double)(1), _state)), __FILE__, __LINE__, "testminbleicunit.ap:3601"); - } - - /* - * Check that interval [#StpIdxA,#StpIdxB] contains at least one discontinuity - */ - hasc1discontinuities = ae_false; - for(i=0; i<=n-1; i++) - { - va = (double)(0); - vb = (double)(0); - for(j=0; j<=n-1; j++) - { - va = va+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxa]); - vb = vb+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxb]); - } - hasc1discontinuities = hasc1discontinuities||ae_sign(va, _state)!=ae_sign(vb, _state); - } - ae_set_error_flag(err, !hasc1discontinuities, __FILE__, __LINE__, "testminbleicunit.ap:3619"); - } - else - { - - /* - * Check negative report: fields must be empty - */ - ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testminbleicunit.ap:3626"); - ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testminbleicunit.ap:3627"); - ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testminbleicunit.ap:3628"); - ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testminbleicunit.ap:3629"); - ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testminbleicunit.ap:3630"); - ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testminbleicunit.ap:3631"); - ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testminbleicunit.ap:3632"); - ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testminbleicunit.ap:3633"); - ae_set_error_flag(err, rep->f.cnt!=0, __FILE__, __LINE__, "testminbleicunit.ap:3634"); - } -} - - -/************************************************************************* -This function tests report of "non-C1" test #1 for task #0 -given by matrix A. - -On failure sets error flag. -*************************************************************************/ -static void testminbleicunit_testoptguardc1test1reportfortask0(ae_bool* err, - optguardnonc1test1report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double vv; - double va; - double vb; - ae_bool tooclose; - ae_bool hasc1discontinuities; - - - if( rep->positive ) - { - - /* - * Check positive report, first checks - */ - ae_set_error_flag(err, rep->fidx!=0, __FILE__, __LINE__, "testminbleicunit.ap:3662"); - ae_set_error_flag(err, rep->vidx<0, __FILE__, __LINE__, "testminbleicunit.ap:3663"); - ae_set_error_flag(err, rep->vidx>n, __FILE__, __LINE__, "testminbleicunit.ap:3664"); - ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testminbleicunit.ap:3665"); - ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testminbleicunit.ap:3666"); - ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testminbleicunit.ap:3667"); - ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testminbleicunit.ap:3668"); - ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testminbleicunit.ap:3669"); - ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testminbleicunit.ap:3670"); - ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testminbleicunit.ap:3671"); - ae_set_error_flag(err, rep->g.cnt!=rep->cnt, __FILE__, __LINE__, "testminbleicunit.ap:3672"); - ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3673"); - ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3674"); - ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testminbleicunit.ap:3675"); - ae_set_error_flag(err, !isfinitevector(&rep->g, rep->cnt, _state), __FILE__, __LINE__, "testminbleicunit.ap:3676"); - if( *err ) - { - return; - } - - /* - * Check consistency of X0, D, Stp and G - */ - for(k=0; k<=rep->cnt-2; k++) - { - ae_set_error_flag(err, ae_fp_greater_eq(rep->stp.ptr.p_double[k],rep->stp.ptr.p_double[k+1]), __FILE__, __LINE__, "testminbleicunit.ap:3684"); - } - for(k=0; k<=rep->cnt-1; k++) - { - v = (double)(0); - tooclose = ae_false; - for(i=0; i<=n-1; i++) - { - vv = (double)(0); - for(j=0; j<=n-1; j++) - { - vv = vv+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[k]); - } - v = v+ae_sign(vv, _state)*a->ptr.pp_double[i][rep->vidx]; - tooclose = tooclose||ae_fp_less(ae_fabs(vv, _state),1.0E-4); - } - if( !tooclose ) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-rep->g.ptr.p_double[k], _state),1.0E-6*ae_maxreal(ae_fabs(v, _state), (double)(1), _state)), __FILE__, __LINE__, "testminbleicunit.ap:3698"); - } - } - - /* - * Check that interval [#StpIdxA,#StpIdxB] contains at least one discontinuity - */ - tooclose = ae_false; - hasc1discontinuities = ae_false; - for(i=0; i<=n-1; i++) - { - va = (double)(0); - vb = (double)(0); - for(j=0; j<=n-1; j++) - { - va = va+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxa]); - vb = vb+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxb]); - } - tooclose = (tooclose||ae_fp_less(ae_fabs(va, _state),1.0E-8))||ae_fp_less(ae_fabs(vb, _state),1.0E-8); - hasc1discontinuities = hasc1discontinuities||ae_sign(va, _state)!=ae_sign(vb, _state); - } - if( !tooclose ) - { - ae_set_error_flag(err, !hasc1discontinuities, __FILE__, __LINE__, "testminbleicunit.ap:3719"); - } - } - else - { - - /* - * Check negative report: fields must be empty - */ - ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testminbleicunit.ap:3726"); - ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testminbleicunit.ap:3727"); - ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testminbleicunit.ap:3728"); - ae_set_error_flag(err, rep->vidx!=-1, __FILE__, __LINE__, "testminbleicunit.ap:3729"); - ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testminbleicunit.ap:3730"); - ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testminbleicunit.ap:3731"); - ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testminbleicunit.ap:3732"); - ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testminbleicunit.ap:3733"); - ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testminbleicunit.ap:3734"); - ae_set_error_flag(err, rep->g.cnt!=0, __FILE__, __LINE__, "testminbleicunit.ap:3735"); - } -} - - - -static void testminqpunit_bcqptest(ae_bool* wereerrors, ae_state *_state); -static ae_bool testminqpunit_ecqptest(ae_state *_state); -static void testminqpunit_icqptest(ae_bool* err, ae_state *_state); -static void testminqpunit_generallcqptest(ae_bool* errorflag, - ae_state *_state); -static ae_bool testminqpunit_specialicqptests(ae_state *_state); -static void testminqpunit_denseaultests(ae_bool* errorflag, - ae_state *_state); -static void testminqpunit_ipmtests(ae_bool* errorflag, ae_state *_state); -static void testminqpunit_spectests(ae_bool* errorflag, ae_state *_state); -static double testminqpunit_projectedantigradnorm(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* g, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_state *_state); -static void testminqpunit_testbcgradandfeasibility(/* Real */ ae_matrix* a, - /* Real */ ae_vector* b, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_int_t n, - /* Real */ ae_vector* x, - double eps, - ae_bool* errorflag, - ae_state *_state); -static ae_int_t testminqpunit_setrandomalgoallmodern(minqpstate* s, - double* bctol, - double* lctol, - ae_state *_state); -static void testminqpunit_setrandomalgononconvex(minqpstate* s, - ae_state *_state); -static void testminqpunit_setrandomalgosemidefinite(minqpstate* s, - double* bctol, - double* lctol, - ae_state *_state); -static void testminqpunit_setrandomalgobc(minqpstate* s, ae_state *_state); -static void testminqpunit_setrandomalgoconvexlc(minqpstate* s, - ae_state *_state); -static void testminqpunit_setrandomalgononconvexlc(minqpstate* s, - ae_state *_state); -static void testminqpunit_densetosparse(/* Real */ ae_matrix* a, - ae_int_t n, - sparsematrix* s, - ae_state *_state); -static void testminqpunit_randomlysplitlc(/* Real */ ae_matrix* rawc, - /* Integer */ ae_vector* rawct, - ae_int_t rawccnt, - ae_int_t n, - sparsematrix* sparsec, - /* Integer */ ae_vector* sparsect, - ae_int_t* sparseccnt, - /* Real */ ae_matrix* densec, - /* Integer */ ae_vector* densect, - ae_int_t* denseccnt, - hqrndstate* rs, - ae_state *_state); -static void testminqpunit_randomlysplitandsetlclegacy(/* Real */ ae_matrix* rawc, - /* Integer */ ae_vector* rawct, - ae_int_t rawccnt, - ae_int_t n, - minqpstate* state, - hqrndstate* rs, - ae_state *_state); -static void testminqpunit_randomlysplitandsetlc2(/* Real */ ae_matrix* rawc, - /* Real */ ae_vector* rawcl, - /* Real */ ae_vector* rawcu, - ae_int_t rawccnt, - ae_int_t n, - minqpstate* state, - hqrndstate* rs, - ae_state *_state); -static void testminqpunit_randomlyselectconvertandsetquadraticterm(/* Real */ ae_matrix* a, - ae_int_t n, - minqpstate* state, - hqrndstate* rs, - ae_state *_state); -static double testminqpunit_getconstraintrcond(/* Real */ ae_matrix* c, - ae_int_t k, - ae_int_t n, - ae_state *_state); -static double testminqpunit_quadratictarget(/* Real */ ae_matrix* a, - /* Real */ ae_vector* b, - ae_int_t n, - /* Real */ ae_vector* x, - ae_state *_state); - - - - - -ae_bool testminqp(ae_bool silent, ae_state *_state) -{ - ae_bool simpleerrors; - ae_bool func1errors; - ae_bool func2errors; - ae_bool bcqperrors; - ae_bool ecqperrors; - ae_bool icqperrors; - ae_bool lcqperrors; - ae_bool quickqperrors; - ae_bool bleicerrors; - ae_bool denseaulerrors; - ae_bool ipmerrors; - ae_bool specerrors; - ae_bool waserrors; - ae_bool result; - - - - /* - * The VERY basic tests for Cholesky and BLEIC - */ - simpleerrors = simpletest(_state); - func1errors = functest1(_state); - func2errors = functest2(_state); - - /* - * Solver-specific tests - */ - denseaulerrors = ae_false; - ipmerrors = ae_false; - quickqperrors = quickqptests(_state); - bleicerrors = bleictests(_state); - testminqpunit_denseaultests(&denseaulerrors, _state); - testminqpunit_ipmtests(&ipmerrors, _state); - - /* - * - */ - icqperrors = ae_false; - lcqperrors = ae_false; - bcqperrors = ae_false; - testminqpunit_bcqptest(&bcqperrors, _state); - ecqperrors = testminqpunit_ecqptest(_state); - testminqpunit_icqptest(&icqperrors, _state); - icqperrors = icqperrors||testminqpunit_specialicqptests(_state); - testminqpunit_generallcqptest(&lcqperrors, _state); - specerrors = ae_false; - testminqpunit_spectests(&specerrors, _state); - - /* - * report - */ - waserrors = ((((((((((simpleerrors||func1errors)||func2errors)||bcqperrors)||ecqperrors)||icqperrors)||lcqperrors)||quickqperrors)||bleicerrors)||denseaulerrors)||ipmerrors)||specerrors; - if( !silent ) - { - printf("TESTING MinQP\n"); - printf("BASIC TESTS:\n"); - printf("* SimpleTest: "); - if( simpleerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* Func1Test: "); - if( func1errors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* Func2Test: "); - if( func2errors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("GENERIC QP TESTS:\n"); - printf("* box constrained: "); - if( bcqperrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* linearly constrained: "); - if( (ecqperrors||icqperrors)||lcqperrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("SOLVER-SPECIFIC TESTS:\n"); - printf("* QuickQP solver tests: "); - if( quickqperrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* BLEIC solver tests: "); - if( bleicerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* DENSE-AUL solver tests: "); - if( denseaulerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* IPM solver tests: "); - if( ipmerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("SPECIAL PROPERTIES: "); - if( specerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - return result; -} - - -/************************************************************************* -Function to test: 'MinQPCreate', 'MinQPSetQuadraticTerm', 'MinQPSetBC', -'MinQPSetOrigin', 'MinQPSetStartingPoint', 'MinQPOptimize', 'MinQPResults'. - -Test problem: - A = diag(aii), aii>0 (random) - b = 0 - random bounds (either no bounds, one bound, two bounds av_neginf; - ub.ptr.p_double[j] = _state->v_posinf; - } - else - { - if( infd==1 ) - { - db.ptr.p_double[j] = _state->v_neginf; - ub.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb; - } - else - { - if( infd==2 ) - { - db.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb; - ub.ptr.p_double[j] = _state->v_posinf; - } - else - { - if( infd==3 ) - { - db.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb; - ub.ptr.p_double[j] = db.ptr.p_double[j]+maxstb*ae_randomreal(_state)+0.01; - } - else - { - db.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb; - ub.ptr.p_double[j] = db.ptr.p_double[j]; - } - } - } - } - } - minqpsetbc(&state, &db, &ub, _state); - - /* - *initialization for shifting - *initial value for 'XORi' - *and searching true results - */ - for(j=0; j<=sn-1; j++) - { - xori.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb; - tx.ptr.p_double[j] = boundval(xori.ptr.p_double[j], db.ptr.p_double[j], ub.ptr.p_double[j], _state); - } - minqpsetorigin(&state, &xori, _state); - - /* - *initialization for starting point - */ - for(j=0; j<=sn-1; j++) - { - stx.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb; - } - minqpsetstartingpoint(&state, &stx, _state); - - /* - *optimize and get result - */ - minqpoptimize(&state, _state); - minqpresults(&state, &x, &rep, _state); - for(j=0; j<=sn-1; j++) - { - if( ae_fp_greater(ae_fabs(tx.ptr.p_double[j]-x.ptr.p_double[j], _state),eps)||(ae_fp_less(x.ptr.p_double[j],db.ptr.p_double[j])||ae_fp_greater(x.ptr.p_double[j],ub.ptr.p_double[j])) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Function to test: 'MinQPCreate', 'MinQPSetLinearTerm', 'MinQPSetQuadraticTerm', -'MinQPSetOrigin', 'MinQPSetStartingPoint', 'MinQPOptimize', 'MinQPResults'. - -Test problem: - A = positive-definite matrix, obtained by 'SPDMatrixRndCond' function - b <> 0 - without bounds - random start point - dimension - from 1 to 5. -*************************************************************************/ -ae_bool functest1(ae_state *_state) -{ - ae_frame _frame_block; - minqpstate state; - ae_int_t nexp; - ae_int_t msn; - ae_int_t sn; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_matrix a; - ae_vector ub; - ae_vector db; - ae_vector x; - ae_vector tx; - ae_vector stx; - ae_vector xori; - ae_vector xoric; - minqpreport rep; - double eps; - ae_vector b; - ae_int_t c2; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&a, 0, sizeof(a)); - memset(&ub, 0, sizeof(ub)); - memset(&db, 0, sizeof(db)); - memset(&x, 0, sizeof(x)); - memset(&tx, 0, sizeof(tx)); - memset(&stx, 0, sizeof(stx)); - memset(&xori, 0, sizeof(xori)); - memset(&xoric, 0, sizeof(xoric)); - memset(&rep, 0, sizeof(rep)); - memset(&b, 0, sizeof(b)); - _minqpstate_init(&state, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ub, 0, DT_REAL, _state, ae_true); - ae_vector_init(&db, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&stx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xori, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xoric, 0, DT_REAL, _state, ae_true); - _minqpreport_init(&rep, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - - eps = 0.001; - msn = 5; - c2 = 1000; - nexp = 1000; - for(sn=1; sn<=msn; sn++) - { - ae_vector_set_length(&b, sn, _state); - ae_vector_set_length(&tx, sn, _state); - ae_vector_set_length(&xori, sn, _state); - ae_vector_set_length(&xoric, sn, _state); - ae_vector_set_length(&stx, sn, _state); - for(i=0; i<=nexp; i++) - { - - /* - *create simmetric matrix 'A' - */ - spdmatrixrndcond(sn, ae_exp(ae_randomreal(_state)*ae_log((double)(c2), _state), _state), &a, _state); - minqpcreate(sn, &state, _state); - testminqpunit_setrandomalgobc(&state, _state); - minqpsetquadraticterm(&state, &a, ae_false, _state); - for(j=0; j<=sn-1; j++) - { - xoric.ptr.p_double[j] = 2*ae_randomreal(_state)-1; - } - - /* - *create linear part - */ - for(j=0; j<=sn-1; j++) - { - b.ptr.p_double[j] = (double)(0); - for(k=0; k<=sn-1; k++) - { - b.ptr.p_double[j] = b.ptr.p_double[j]-xoric.ptr.p_double[k]*a.ptr.pp_double[k][j]; - } - } - minqpsetlinearterm(&state, &b, _state); - - /* - *initialization for shifting - *initial value for 'XORi' - *and searching true results - */ - for(j=0; j<=sn-1; j++) - { - xori.ptr.p_double[j] = 2*ae_randomreal(_state)-1; - tx.ptr.p_double[j] = xori.ptr.p_double[j]+xoric.ptr.p_double[j]; - } - minqpsetorigin(&state, &xori, _state); - - /* - *initialization for starting point - */ - for(j=0; j<=sn-1; j++) - { - stx.ptr.p_double[j] = 2*ae_randomreal(_state)-1; - } - minqpsetstartingpoint(&state, &stx, _state); - - /* - *optimize and get result - */ - minqpoptimize(&state, _state); - minqpresults(&state, &x, &rep, _state); - for(j=0; j<=sn-1; j++) - { - if( ae_fp_greater(ae_fabs(tx.ptr.p_double[j]-x.ptr.p_double[j], _state),eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Function to test: 'MinQPCreate', 'MinQPSetLinearTerm', 'MinQPSetQuadraticTerm', -'MinQPSetBC', 'MinQPSetOrigin', 'MinQPSetStartingPoint', 'MinQPOptimize', -'MinQPResults'. - -Test problem: - A = positive-definite matrix, obtained by 'SPDMatrixRndCond' function - b <> 0 - boundary constraints - random start point - dimension - from 1 to 5. -*************************************************************************/ -ae_bool functest2(ae_state *_state) -{ - ae_frame _frame_block; - minqpstate state; - ae_int_t nexp; - ae_int_t msn; - ae_int_t sn; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_matrix a; - ae_vector ub; - ae_vector db; - ae_vector x; - ae_vector tmpx; - double maxstb; - ae_vector stx; - ae_vector xori; - ae_vector xoric; - ae_int_t infd; - minqpreport rep; - double maxnb; - double minnb; - double eps; - ae_vector b; - ae_vector g; - ae_vector c; - ae_vector y0; - ae_vector y1; - ae_int_t c2; - double anti; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&a, 0, sizeof(a)); - memset(&ub, 0, sizeof(ub)); - memset(&db, 0, sizeof(db)); - memset(&x, 0, sizeof(x)); - memset(&tmpx, 0, sizeof(tmpx)); - memset(&stx, 0, sizeof(stx)); - memset(&xori, 0, sizeof(xori)); - memset(&xoric, 0, sizeof(xoric)); - memset(&rep, 0, sizeof(rep)); - memset(&b, 0, sizeof(b)); - memset(&g, 0, sizeof(g)); - memset(&c, 0, sizeof(c)); - memset(&y0, 0, sizeof(y0)); - memset(&y1, 0, sizeof(y1)); - _minqpstate_init(&state, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ub, 0, DT_REAL, _state, ae_true); - ae_vector_init(&db, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&stx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xori, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xoric, 0, DT_REAL, _state, ae_true); - _minqpreport_init(&rep, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&g, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y1, 0, DT_REAL, _state, ae_true); - - eps = 0.001; - msn = 5; - c2 = 1000; - maxstb = (double)(10); - nexp = 1000; - maxnb = (double)(1000); - minnb = (double)(-1000); - for(sn=1; sn<=msn; sn++) - { - ae_vector_set_length(&tmpx, sn, _state); - ae_vector_set_length(&b, sn, _state); - ae_vector_set_length(&c, sn, _state); - ae_vector_set_length(&g, sn, _state); - ae_vector_set_length(&xori, sn, _state); - ae_vector_set_length(&xoric, sn, _state); - ae_vector_set_length(&stx, sn, _state); - ae_vector_set_length(&db, sn, _state); - ae_vector_set_length(&ub, sn, _state); - ae_vector_set_length(&y0, sn, _state); - ae_vector_set_length(&y1, sn, _state); - for(i=0; i<=nexp; i++) - { - - /* - *create simmetric matrix 'A' - */ - spdmatrixrndcond(sn, ae_exp(ae_randomreal(_state)*ae_log((double)(c2), _state), _state), &a, _state); - minqpcreate(sn, &state, _state); - testminqpunit_setrandomalgobc(&state, _state); - minqpsetquadraticterm(&state, &a, ae_false, _state); - for(j=0; j<=sn-1; j++) - { - xoric.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb; - } - - /* - *create linear part - */ - for(j=0; j<=sn-1; j++) - { - b.ptr.p_double[j] = (double)(0); - for(k=0; k<=sn-1; k++) - { - b.ptr.p_double[j] = b.ptr.p_double[j]-xoric.ptr.p_double[k]*a.ptr.pp_double[k][j]; - } - } - minqpsetlinearterm(&state, &b, _state); - for(j=0; j<=sn-1; j++) - { - infd = ae_randominteger(4, _state); - if( infd==0 ) - { - db.ptr.p_double[j] = _state->v_neginf; - ub.ptr.p_double[j] = _state->v_posinf; - } - else - { - if( infd==1 ) - { - db.ptr.p_double[j] = _state->v_neginf; - ub.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb; - } - else - { - if( infd==2 ) - { - db.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb; - ub.ptr.p_double[j] = _state->v_posinf; - } - else - { - db.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb; - ub.ptr.p_double[j] = db.ptr.p_double[j]+maxstb*ae_randomreal(_state)+0.01; - } - } - } - } - minqpsetbc(&state, &db, &ub, _state); - - /* - *initialization for shifting - *initial value for 'XORi' - *and searching true results - */ - for(j=0; j<=sn-1; j++) - { - xori.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb; - } - minqpsetorigin(&state, &xori, _state); - for(j=0; j<=sn-1; j++) - { - c.ptr.p_double[j] = (double)(0); - for(k=0; k<=sn-1; k++) - { - c.ptr.p_double[j] = c.ptr.p_double[j]-xori.ptr.p_double[k]*a.ptr.pp_double[k][j]; - } - } - - /* - *initialization for starting point - */ - for(j=0; j<=sn-1; j++) - { - stx.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb; - } - minqpsetstartingpoint(&state, &stx, _state); - - /* - *optimize and get result - */ - minqpoptimize(&state, _state); - minqpresults(&state, &x, &rep, _state); - rmatrixmv(sn, sn, &a, 0, 0, 0, &x, 0, &y0, 0, _state); - for(j=0; j<=sn-1; j++) - { - g.ptr.p_double[j] = y0.ptr.p_double[j]+c.ptr.p_double[j]+b.ptr.p_double[j]; - } - anti = testminqpunit_projectedantigradnorm(sn, &x, &g, &db, &ub, _state); - for(j=0; j<=sn-1; j++) - { - if( ae_fp_greater(ae_fabs(anti, _state),eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -ConsoleTest. -*************************************************************************/ -ae_bool consoletest(ae_state *_state) -{ - ae_frame _frame_block; - minqpstate state; - ae_int_t nexp; - ae_int_t msn; - ae_int_t sn; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_matrix a; - ae_vector ub; - ae_vector db; - ae_vector x; - ae_vector stx; - ae_vector xori; - ae_vector xoric; - minqpreport rep; - double eps; - ae_vector b; - ae_vector g; - ae_vector y0; - ae_vector y1; - double c; - double anti; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&a, 0, sizeof(a)); - memset(&ub, 0, sizeof(ub)); - memset(&db, 0, sizeof(db)); - memset(&x, 0, sizeof(x)); - memset(&stx, 0, sizeof(stx)); - memset(&xori, 0, sizeof(xori)); - memset(&xoric, 0, sizeof(xoric)); - memset(&rep, 0, sizeof(rep)); - memset(&b, 0, sizeof(b)); - memset(&g, 0, sizeof(g)); - memset(&y0, 0, sizeof(y0)); - memset(&y1, 0, sizeof(y1)); - _minqpstate_init(&state, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ub, 0, DT_REAL, _state, ae_true); - ae_vector_init(&db, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&stx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xori, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xoric, 0, DT_REAL, _state, ae_true); - _minqpreport_init(&rep, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&g, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y1, 0, DT_REAL, _state, ae_true); - - eps = 0.001; - msn = 2; - nexp = 0; - for(sn=2; sn<=msn; sn++) - { - ae_vector_set_length(&b, sn, _state); - ae_vector_set_length(&g, sn, _state); - ae_vector_set_length(&xori, sn, _state); - ae_vector_set_length(&xoric, sn, _state); - ae_vector_set_length(&stx, sn, _state); - ae_vector_set_length(&db, sn, _state); - ae_vector_set_length(&ub, sn, _state); - ae_vector_set_length(&y0, sn, _state); - ae_vector_set_length(&y1, sn, _state); - for(i=0; i<=nexp; i++) - { - - /* - *create simmetric matrix 'A' - */ - ae_matrix_set_length(&a, sn, sn, _state); - for(j=0; j<=sn-1; j++) - { - for(k=0; k<=sn-1; k++) - { - if( j==k ) - { - a.ptr.pp_double[j][k] = (double)(1); - } - else - { - a.ptr.pp_double[j][k] = (double)(0); - } - printf("%0.5f ", - (double)(a.ptr.pp_double[j][k])); - } - printf("\n"); - } - minqpcreate(sn, &state, _state); - testminqpunit_setrandomalgobc(&state, _state); - minqpsetquadraticterm(&state, &a, ae_false, _state); - for(j=0; j<=sn-1; j++) - { - xoric.ptr.p_double[j] = (double)(1); - printf("XoriC=%0.5f \n", - (double)(xoric.ptr.p_double[j])); - } - - /* - *create linear part - */ - for(j=0; j<=sn-1; j++) - { - b.ptr.p_double[j] = (double)(0); - for(k=0; k<=sn-1; k++) - { - b.ptr.p_double[j] = b.ptr.p_double[j]-xoric.ptr.p_double[k]*a.ptr.pp_double[k][j]; - } - printf("B[%0d]=%0.5f\n", - (int)(j), - (double)(b.ptr.p_double[j])); - } - minqpsetlinearterm(&state, &b, _state); - for(j=0; j<=sn-1; j++) - { - db.ptr.p_double[j] = (double)(10); - ub.ptr.p_double[j] = (double)(20); - } - minqpsetbc(&state, &db, &ub, _state); - - /* - *initialization for shifting - *initial value for 'XORi' - *and searching true results - */ - for(j=0; j<=sn-1; j++) - { - xori.ptr.p_double[j] = (double)(1); - } - minqpsetorigin(&state, &xori, _state); - - /* - *optimize and get result - */ - minqpoptimize(&state, _state); - minqpresults(&state, &x, &rep, _state); - rmatrixmv(sn, sn, &a, 0, 0, 0, &x, 0, &y0, 0, _state); - rmatrixmv(sn, sn, &a, 0, 0, 0, &x, 0, &y1, 0, _state); - for(j=0; j<=sn-1; j++) - { - c = (double)(0); - for(k=0; k<=sn-1; k++) - { - c = c-xori.ptr.p_double[k]*a.ptr.pp_double[k][j]; - } - g.ptr.p_double[j] = b.ptr.p_double[j]+c+y0.ptr.p_double[j]+y1.ptr.p_double[j]; - } - anti = testminqpunit_projectedantigradnorm(sn, &x, &b, &db, &ub, _state); - printf("SN=%0d\n", - (int)(sn)); - printf("NEXP=%0d\n", - (int)(i)); - printf("TermType=%0d\n", - (int)(rep.terminationtype)); - for(j=0; j<=sn-1; j++) - { - printf("X[%0d]=%0.5f;\n", - (int)(j), - (double)(x.ptr.p_double[j])); - printf("DB[%0d]=%0.5f; UB[%0d]=%0.5f\n", - (int)(j), - (double)(db.ptr.p_double[j]), - (int)(j), - (double)(ub.ptr.p_double[j])); - printf("XORi[%0d]=%0.5f; XORiC[%0d]=%0.5f;\n", - (int)(j), - (double)(xori.ptr.p_double[j]), - (int)(j), - (double)(xoric.ptr.p_double[j])); - printf("Anti[%0d]=%0.5f;\n", - (int)(j), - (double)(anti)); - if( ae_fp_greater(ae_fabs(anti, _state),eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function performs tests specific for QuickQP solver - -Returns True on failure. -*************************************************************************/ -ae_bool quickqptests(ae_state *_state) -{ - ae_frame _frame_block; - minqpstate state; - minqpreport rep; - ae_int_t n; - ae_int_t pass; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double g; - double gnorm; - ae_bool flag; - ae_int_t origintype; - ae_int_t scaletype; - ae_bool isupper; - ae_bool issparse; - ae_int_t itscnt; - ae_vector nlist; - ae_int_t nidx; - ae_matrix a; - ae_matrix za; - ae_matrix fulla; - ae_matrix halfa; - ae_matrix c; - sparsematrix sa; - ae_vector ct; - ae_vector b; - ae_vector zb; - ae_vector bndl; - ae_vector bndu; - ae_vector x0; - ae_vector x1; - ae_vector xend0; - ae_vector xend1; - ae_vector xori; - ae_vector xz; - ae_vector s; - double eps; - hqrndstate rs; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&nlist, 0, sizeof(nlist)); - memset(&a, 0, sizeof(a)); - memset(&za, 0, sizeof(za)); - memset(&fulla, 0, sizeof(fulla)); - memset(&halfa, 0, sizeof(halfa)); - memset(&c, 0, sizeof(c)); - memset(&sa, 0, sizeof(sa)); - memset(&ct, 0, sizeof(ct)); - memset(&b, 0, sizeof(b)); - memset(&zb, 0, sizeof(zb)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&xend0, 0, sizeof(xend0)); - memset(&xend1, 0, sizeof(xend1)); - memset(&xori, 0, sizeof(xori)); - memset(&xz, 0, sizeof(xz)); - memset(&s, 0, sizeof(s)); - memset(&rs, 0, sizeof(rs)); - _minqpstate_init(&state, _state, ae_true); - _minqpreport_init(&rep, _state, ae_true); - ae_vector_init(&nlist, 0, DT_INT, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&za, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&fulla, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&halfa, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&sa, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&zb, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xend0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xend1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xori, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xz, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - result = ae_false; - hqrndrandomize(&rs, _state); - - /* - * Convex unconstrained test: - * * N dimensions - * * positive-definite A - * * algorithm randomly choose dense or sparse A, and for - * sparse matrix it randomly choose format. - * * random B with normal entries - * * initial point is random, feasible - * * random origin (zero or non-zero) and scale (unit or - * non-unit) are generated - */ - eps = 1.0E-5; - for(n=1; n<=10; n++) - { - for(pass=1; pass<=10; pass++) - { - - /* - * Generate problem - */ - origintype = hqrnduniformi(&rs, 2, _state); - scaletype = hqrnduniformi(&rs, 2, _state); - isupper = ae_fp_less(hqrnduniformr(&rs, _state),0.5); - issparse = ae_fp_less(hqrnduniformr(&rs, _state),0.5); - spdmatrixrndcond(n, 1.0E3, &fulla, _state); - ae_matrix_set_length(&halfa, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (j>=i&&isupper)||(j<=i&&!isupper) ) - { - halfa.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j]; - } - else - { - halfa.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5; - } - } - } - testminqpunit_densetosparse(&halfa, n, &sa, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xori, n, _state); - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - if( origintype==0 ) - { - xori.ptr.p_double[i] = (double)(0); - } - else - { - xori.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - if( scaletype==0 ) - { - s.ptr.p_double[i] = (double)(1); - } - else - { - s.ptr.p_double[i] = ae_exp(0.5*hqrndnormal(&rs, _state), _state); - } - } - - /* - * Solve problem - */ - minqpcreate(n, &state, _state); - minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, 0, ae_fp_greater(hqrnduniformr(&rs, _state),0.5), _state); - minqpsetlinearterm(&state, &b, _state); - if( issparse ) - { - minqpsetquadratictermsparse(&state, &sa, isupper, _state); - } - else - { - minqpsetquadraticterm(&state, &halfa, isupper, _state); - } - if( origintype!=0 ) - { - minqpsetorigin(&state, &xori, _state); - } - if( scaletype!=0 ) - { - minqpsetscale(&state, &s, _state); - } - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:5731"); - if( rep.terminationtype<=0 ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test - calculate constrained gradient at solution, - * check its norm. - */ - gnorm = 0.0; - for(i=0; i<=n-1; i++) - { - g = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - g = g+fulla.ptr.pp_double[i][j]*(x1.ptr.p_double[j]-xori.ptr.p_double[j]); - } - gnorm = gnorm+ae_sqr(g, _state); - } - gnorm = ae_sqrt(gnorm, _state); - ae_set_error_flag(&result, ae_fp_greater(gnorm,eps), __FILE__, __LINE__, "testminqpunit.ap:5749"); - } - } - - /* - * Convex test: - * * N dimensions - * * random number (0..N) of random boundary constraints - * * positive-definite A - * * algorithm randomly choose dense or sparse A, and for - * sparse matrix it randomly choose format. - * * random B with normal entries - * * initial point is random, feasible - * * random origin (zero or non-zero) and scale (unit or - * non-unit) are generated - */ - eps = 1.0E-5; - for(n=1; n<=10; n++) - { - for(pass=1; pass<=10; pass++) - { - - /* - * Generate problem - */ - origintype = hqrnduniformi(&rs, 2, _state); - scaletype = hqrnduniformi(&rs, 2, _state); - isupper = ae_fp_less(hqrnduniformr(&rs, _state),0.5); - issparse = ae_fp_less(hqrnduniformr(&rs, _state),0.5); - spdmatrixrndcond(n, 1.0E3, &fulla, _state); - ae_matrix_set_length(&halfa, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (j>=i&&isupper)||(j<=i&&!isupper) ) - { - halfa.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j]; - } - else - { - halfa.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5; - } - } - } - testminqpunit_densetosparse(&halfa, n, &sa, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xori, n, _state); - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - bndl.ptr.p_double[i] = _state->v_neginf; - bndu.ptr.p_double[i] = _state->v_posinf; - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - if( origintype==0 ) - { - xori.ptr.p_double[i] = (double)(0); - } - else - { - xori.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - if( scaletype==0 ) - { - s.ptr.p_double[i] = (double)(1); - } - else - { - s.ptr.p_double[i] = ae_exp(0.5*hqrndnormal(&rs, _state), _state); - } - j = hqrnduniformi(&rs, 5, _state); - if( j==0 ) - { - bndl.ptr.p_double[i] = (double)(0); - x0.ptr.p_double[i] = ae_fabs(x0.ptr.p_double[i], _state); - } - if( j==1 ) - { - bndu.ptr.p_double[i] = (double)(0); - x0.ptr.p_double[i] = -ae_fabs(x0.ptr.p_double[i], _state); - } - if( j==2 ) - { - bndl.ptr.p_double[i] = hqrndnormal(&rs, _state); - bndu.ptr.p_double[i] = bndl.ptr.p_double[i]; - x0.ptr.p_double[i] = bndl.ptr.p_double[i]; - } - if( j==3 ) - { - bndl.ptr.p_double[i] = -0.1; - bndu.ptr.p_double[i] = 0.1; - x0.ptr.p_double[i] = 0.2*hqrnduniformr(&rs, _state)-0.1; - } - } - - /* - * Solve problem - */ - minqpcreate(n, &state, _state); - minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, 0, ae_fp_greater(hqrnduniformr(&rs, _state),0.5), _state); - minqpsetlinearterm(&state, &b, _state); - if( issparse ) - { - minqpsetquadratictermsparse(&state, &sa, isupper, _state); - } - else - { - minqpsetquadraticterm(&state, &halfa, isupper, _state); - } - if( origintype!=0 ) - { - minqpsetorigin(&state, &xori, _state); - } - if( scaletype!=0 ) - { - minqpsetscale(&state, &s, _state); - } - minqpsetbc(&state, &bndl, &bndu, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:5846"); - if( rep.terminationtype<=0 ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test - calculate constrained gradient at solution, - * check its norm. - */ - gnorm = 0.0; - for(i=0; i<=n-1; i++) - { - g = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - g = g+fulla.ptr.pp_double[i][j]*(x1.ptr.p_double[j]-xori.ptr.p_double[j]); - } - if( ae_fp_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i])&&ae_fp_greater(g,(double)(0)) ) - { - g = (double)(0); - } - if( ae_fp_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i])&&ae_fp_less(g,(double)(0)) ) - { - g = (double)(0); - } - gnorm = gnorm+ae_sqr(g, _state); - ae_set_error_flag(&result, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:5866"); - ae_set_error_flag(&result, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:5867"); - } - gnorm = ae_sqrt(gnorm, _state); - ae_set_error_flag(&result, ae_fp_greater(gnorm,eps), __FILE__, __LINE__, "testminqpunit.ap:5870"); - } - } - - /* - * Strongly non-convex test: - * * N dimensions, N>=2 - * * box constraints, x[i] in [-1,+1] - * * A = A0-0.5*I, where A0 is SPD with unit norm and smallest - * singular value equal to 1.0E-3, I is identity matrix - * * random B with normal entries - * * initial point is random, feasible - * - * We perform two tests: - * * unconstrained problem must be recognized as unbounded - * * constrained problem can be successfully solved - * - * NOTE: it is important to have N>=2, because formula for A - * can be applied only to matrix with at least two - * singular values - */ - eps = 1.0E-5; - for(n=2; n<=10; n++) - { - for(pass=1; pass<=10; pass++) - { - - /* - * Generate problem - */ - spdmatrixrndcond(n, 1.0E3, &fulla, _state); - for(i=0; i<=n-1; i++) - { - fulla.ptr.pp_double[i][i] = fulla.ptr.pp_double[i][i]-0.5; - } - isupper = ae_fp_less(hqrnduniformr(&rs, _state),0.5); - ae_matrix_set_length(&halfa, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (j>=i&&isupper)||(j<=i&&!isupper) ) - { - halfa.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j]; - } - else - { - halfa.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5; - } - } - } - testminqpunit_densetosparse(&halfa, n, &sa, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - bndl.ptr.p_double[i] = (double)(-1); - bndu.ptr.p_double[i] = (double)(1); - x0.ptr.p_double[i] = 2*hqrnduniformr(&rs, _state)-1; - } - - /* - * Solve problem: - * * without constraints we expect failure - * * with constraints algorithm must succeed - */ - minqpcreate(n, &state, _state); - minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, 0, ae_fp_greater(hqrnduniformr(&rs, _state),0.5), _state); - minqpsetlinearterm(&state, &b, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minqpsetquadraticterm(&state, &halfa, isupper, _state); - } - else - { - minqpsetquadratictermsparse(&state, &sa, isupper, _state); - } - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype!=-4, __FILE__, __LINE__, "testminqpunit.ap:5935"); - minqpsetbc(&state, &bndl, &bndu, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:5939"); - if( rep.terminationtype<=0 ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test - calculate constrained gradient at solution, - * check its norm. - */ - gnorm = 0.0; - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&fulla.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - g = v+b.ptr.p_double[i]; - if( ae_fp_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i])&&ae_fp_greater(g,(double)(0)) ) - { - g = (double)(0); - } - if( ae_fp_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i])&&ae_fp_less(g,(double)(0)) ) - { - g = (double)(0); - } - gnorm = gnorm+ae_sqr(g, _state); - ae_set_error_flag(&result, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:5958"); - ae_set_error_flag(&result, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:5959"); - } - gnorm = ae_sqrt(gnorm, _state); - ae_set_error_flag(&result, ae_fp_greater(gnorm,eps), __FILE__, __LINE__, "testminqpunit.ap:5962"); - } - } - - /* - * Basic semi-definite test: - * * N dimensions, N>=2 - * * box constraints, x[i] in [-1,+1] - * [ 1 1 ... 1 1 ] - * * A = [ ... ... ... ], with one (random) diagonal entry set to -1 - * [ 1 1 ... 1 1 ] - * * random B with normal entries - * * initial point is random, feasible - * - * We perform two tests: - * * unconstrained problem must be recognized as unbounded - * * constrained problem must be recognized as bounded and - * successfully solved - * - * Both problems require subtle programming when we work - * with semidefinite QP. - * - * NOTE: unlike BLEIC-QP algorthm, QQP may detect unboundedness - * of the problem when started from any x0, with any b. - * BLEIC-based solver requires carefully chosen x0 and b - * to find direction of zero curvature, but this solver - * can find it from any point. - */ - ae_vector_set_length(&nlist, 12, _state); - nlist.ptr.p_int[0] = 2; - nlist.ptr.p_int[1] = 3; - nlist.ptr.p_int[2] = 4; - nlist.ptr.p_int[3] = 5; - nlist.ptr.p_int[4] = 6; - nlist.ptr.p_int[5] = 7; - nlist.ptr.p_int[6] = 8; - nlist.ptr.p_int[7] = 9; - nlist.ptr.p_int[8] = 10; - nlist.ptr.p_int[9] = 20; - nlist.ptr.p_int[10] = 40; - nlist.ptr.p_int[11] = 80; - eps = 1.0E-5; - for(nidx=0; nidx<=nlist.cnt-1; nidx++) - { - for(pass=1; pass<=10; pass++) - { - - /* - * Generate problem - */ - n = nlist.ptr.p_int[nidx]; - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - do - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - while(ae_fp_eq(b.ptr.p_double[i],(double)(0))); - bndl.ptr.p_double[i] = (double)(-1); - bndu.ptr.p_double[i] = (double)(1); - x0.ptr.p_double[i] = 2*hqrnduniformr(&rs, _state)-1; - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 1.0; - } - } - j = hqrnduniformi(&rs, n, _state); - a.ptr.pp_double[j][j] = -1.0; - testminqpunit_densetosparse(&a, n, &sa, _state); - - /* - * Solve problem: - * * without constraints we expect failure - * * with constraints algorithm must succeed - */ - minqpcreate(n, &state, _state); - minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, 0, ae_fp_greater(hqrnduniformr(&rs, _state),0.5), _state); - minqpsetlinearterm(&state, &b, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minqpsetquadraticterm(&state, &a, ae_true, _state); - } - else - { - minqpsetquadratictermsparse(&state, &sa, ae_true, _state); - } - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype!=-4, __FILE__, __LINE__, "testminqpunit.ap:6045"); - minqpsetbc(&state, &bndl, &bndu, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:6049"); - if( rep.terminationtype<=0 ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test - calculate constrained gradient at solution, - * check its norm. - */ - gnorm = 0.0; - for(i=0; i<=n-1; i++) - { - g = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - g = g+a.ptr.pp_double[i][j]*x1.ptr.p_double[j]; - } - if( ae_fp_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i])&&ae_fp_greater(g,(double)(0)) ) - { - g = (double)(0); - } - if( ae_fp_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i])&&ae_fp_less(g,(double)(0)) ) - { - g = (double)(0); - } - gnorm = gnorm+ae_sqr(g, _state); - ae_set_error_flag(&result, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6070"); - ae_set_error_flag(&result, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6071"); - } - gnorm = ae_sqrt(gnorm, _state); - ae_set_error_flag(&result, ae_fp_greater(gnorm,eps), __FILE__, __LINE__, "testminqpunit.ap:6074"); - } - } - - /* - * Linear (zero-quadratic) test: - * * N dimensions, N>=1 - * * box constraints, x[i] in [-1,+1] - * * A = 0 - * * random B with normal entries - * * initial point is random, feasible - * - * We perform two tests: - * * unconstrained problem must be recognized as unbounded - * * constrained problem can be successfully solved - * - * NOTE: we may explicitly set zero A, or assume that by - * default it is zero. During test we will try both - * ways. - */ - eps = 1.0E-5; - for(n=1; n<=10; n++) - { - for(pass=1; pass<=10; pass++) - { - - /* - * Generate problem - */ - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - do - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - while(ae_fp_eq(b.ptr.p_double[i],(double)(0))); - bndl.ptr.p_double[i] = (double)(-1); - bndu.ptr.p_double[i] = (double)(1); - x0.ptr.p_double[i] = 2*hqrnduniformr(&rs, _state)-1; - } - - /* - * Solve problem: - * * without constraints we expect failure - * * with constraints algorithm must succeed - */ - minqpcreate(n, &state, _state); - minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, 0, ae_fp_greater(hqrnduniformr(&rs, _state),0.5), _state); - minqpsetlinearterm(&state, &b, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - minqpsetquadraticterm(&state, &a, ae_true, _state); - } - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype!=-4, __FILE__, __LINE__, "testminqpunit.ap:6132"); - minqpsetbc(&state, &bndl, &bndu, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:6136"); - if( rep.terminationtype<=0 ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test - calculate constrained gradient at solution, - * check its norm. - */ - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(&result, ae_fp_greater(b.ptr.p_double[i],(double)(0))&&ae_fp_greater(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6146"); - ae_set_error_flag(&result, ae_fp_less(b.ptr.p_double[i],(double)(0))&&ae_fp_less(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6147"); - } - } - } - - /* - * Test for Newton phase of QQP algorithm - we test that Newton - * phase can find good solution within one step. In order to do - * so we: - * * solve convex QP problem (dense or sparse) - * * with K<=N equality-only constraints ai=x=bi - * * with number of outer iterations limited to just 1 - * * and with CG phase turned off (we modify internal structures - * of the QQP solver in order to make it) - */ - eps = 1.0E-5; - for(pass=1; pass<=10; pass++) - { - - /* - * Generate problem - */ - n = 50+hqrnduniformi(&rs, 51, _state); - spdmatrixrndcond(n, 1.0E3, &a, _state); - testminqpunit_densetosparse(&a, n, &sa, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - bndl.ptr.p_double[i] = _state->v_neginf; - bndu.ptr.p_double[i] = _state->v_posinf; - } - else - { - bndl.ptr.p_double[i] = hqrndnormal(&rs, _state); - bndu.ptr.p_double[i] = bndl.ptr.p_double[i]; - } - } - - /* - * Solve problem - * - * NOTE: we modify internal structures of QQP solver in order - * to deactivate CG phase - */ - minqpcreate(n, &state, _state); - minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, 1, ae_true, _state); - state.qqpsettingsuser.cgphase = ae_false; - minqpsetlinearterm(&state, &b, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minqpsetquadraticterm(&state, &a, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), _state); - } - else - { - minqpsetquadratictermsparse(&state, &sa, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), _state); - } - minqpsetbc(&state, &bndl, &bndu, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:6207"); - if( rep.terminationtype<=0 ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test - calculate constrained gradient at solution, - * check its norm. - */ - gnorm = 0.0; - for(i=0; i<=n-1; i++) - { - g = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - g = g+a.ptr.pp_double[i][j]*x1.ptr.p_double[j]; - } - if( ae_fp_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i])&&ae_fp_greater(g,(double)(0)) ) - { - g = (double)(0); - } - if( ae_fp_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i])&&ae_fp_less(g,(double)(0)) ) - { - g = (double)(0); - } - gnorm = gnorm+ae_sqr(g, _state); - ae_set_error_flag(&result, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6227"); - ae_set_error_flag(&result, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6228"); - } - gnorm = ae_sqrt(gnorm, _state); - ae_set_error_flag(&result, ae_fp_greater(gnorm,eps), __FILE__, __LINE__, "testminqpunit.ap:6231"); - } - - /* - * Test for Newton phase of QQP algorithm - we test that Newton - * updates work correctly, i.e. that CNewtonUpdate() internal - * function correctly updates inverse Hessian matrix. - * - * To test it we: - * * solve ill conditioned convex QP problem - * * with unconstrained solution XZ whose components are within [-0.5,+0.5] - * * with one inequality constraint X[k]>=5 - * * with initial point such that: - * * X0[i] = 100 for i<>k - * * X0[k] = 5+1.0E-5 - * * with number of outer iterations limited to just 1 - * * and with CG phase turned off (we modify internal structures - * of the QQP solver in order to make it) - * - * The idea is that single Newton step is not enough to find solution, - * but with just one update we can move exactly to the solution. - * - * We perform two tests: - * * first one with State.QQP.NewtMaxIts set to 1, in order to - * make sure that algorithm fails with just one iteration - * * second one with State.QQP.NewtMaxIts set to 2, in order to - * make sure that algorithm converges when it can perform update - */ - eps = 1.0E-5; - for(pass=1; pass<=10; pass++) - { - - /* - * Generate problem - */ - n = 20+hqrnduniformi(&rs, 20, _state); - spdmatrixrndcond(n, 1.0E5, &a, _state); - testminqpunit_densetosparse(&a, n, &sa, _state); - sparseconverttocrs(&sa, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xz, n, _state); - for(i=0; i<=n-1; i++) - { - xz.ptr.p_double[i] = hqrnduniformr(&rs, _state)-0.5; - x0.ptr.p_double[i] = (double)(100); - bndl.ptr.p_double[i] = _state->v_neginf; - bndu.ptr.p_double[i] = _state->v_posinf; - } - k = hqrnduniformi(&rs, n, _state); - x0.ptr.p_double[k] = 5.00001; - bndl.ptr.p_double[k] = 5.0; - sparsemv(&sa, &xz, &b, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = -b.ptr.p_double[i]; - } - - /* - * Create solver - */ - minqpcreate(n, &state, _state); - minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, 1, ae_true, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetquadraticterm(&state, &a, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), _state); - minqpsetbc(&state, &bndl, &bndu, _state); - minqpsetstartingpoint(&state, &x0, _state); - - /* - * Solve problem. First time, with no Newton updates. - * It must fail. - * - * NOTE: we modify internal structures of QQP solver in order - * to deactivate CG phase and turn off Newton updates. - */ - state.qqpsettingsuser.cgphase = ae_false; - state.qqpsettingsuser.cnphase = ae_true; - state.qqpsettingsuser.cnmaxupdates = 0; - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:6310"); - if( result ) - { - ae_frame_leave(_state); - return result; - } - flag = ae_false; - testminqpunit_testbcgradandfeasibility(&a, &b, &bndl, &bndu, n, &x1, eps, &flag, _state); - ae_set_error_flag(&result, !flag, __FILE__, __LINE__, "testminqpunit.ap:6315"); - - /* - * Now with Newton updates - it must succeeed. - */ - state.qqpsettingsuser.cgphase = ae_false; - state.qqpsettingsuser.cnmaxupdates = n; - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:6324"); - if( result ) - { - ae_frame_leave(_state); - return result; - } - flag = ae_false; - testminqpunit_testbcgradandfeasibility(&a, &b, &bndl, &bndu, n, &x1, eps, &flag, _state); - ae_set_error_flag(&result, flag, __FILE__, __LINE__, "testminqpunit.ap:6329"); - } - - /* - * Check that problem with general constraints results in - * correct error code (-5 should be returned). - */ - ae_matrix_set_length(&c, 1, 3, _state); - ae_vector_set_length(&ct, 1, _state); - c.ptr.pp_double[0][0] = 1.0; - c.ptr.pp_double[0][1] = 1.0; - c.ptr.pp_double[0][2] = 2.0; - ct.ptr.p_int[0] = 0; - minqpcreate(2, &state, _state); - minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, 0, ae_fp_greater(hqrnduniformr(&rs, _state),0.5), _state); - minqpsetlc(&state, &c, &ct, 1, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype!=-5, __FILE__, __LINE__, "testminqpunit.ap:6347"); - - /* - * Test sparse functionality. QQP solver must perform - * same steps independently of matrix type (dense or sparse). - * - * We generate random unconstrained test problem and solve it - * twice - first time we solve dense version, second time - - * sparse version is solved. - * - * During this test we: - * * use stringent stopping criteria (one outer iteration) - * * turn off Newton phase of the algorithm to slow down - * convergence - */ - eps = 1.0E-3; - itscnt = 1; - n = 20; - isupper = ae_fp_greater(ae_randomreal(_state),0.5); - spdmatrixrndcond(n, 1.0E3, &za, _state); - sparsecreate(n, n, 0, &sa, _state); - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( j>=i&&isupper ) - { - sparseset(&sa, i, j, za.ptr.pp_double[i][j], _state); - a.ptr.pp_double[i][j] = za.ptr.pp_double[i][j]; - } - if( j<=i&&!isupper ) - { - sparseset(&sa, i, j, za.ptr.pp_double[i][j], _state); - a.ptr.pp_double[i][j] = za.ptr.pp_double[i][j]; - } - } - } - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = randomnormal(_state); - s.ptr.p_double[i] = ae_pow(10.0, randomnormal(_state)/10, _state); - } - minqpcreate(n, &state, _state); - minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, itscnt, ae_false, _state); - minqpsetscale(&state, &s, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetquadraticterm(&state, &a, isupper, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend0, &rep, _state); - minqpcreate(n, &state, _state); - minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, itscnt, ae_false, _state); - minqpsetscale(&state, &s, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetquadratictermsparse(&state, &sa, isupper, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend1, &rep, _state); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(xend0.ptr.p_double[i]-xend1.ptr.p_double[i], _state),eps), __FILE__, __LINE__, "testminqpunit.ap:6465"); - } - - /* - * Test scale-invariance. QQP performs same steps on scaled and - * unscaled problems (assuming that scale of the variables is known). - * - * We generate random scale matrix S and random well-conditioned and - * well scaled matrix A. Then we solve two problems: - * - * (1) f = 0.5*x'*A*x+b'*x - * (identity scale matrix is used) - * - * and - * - * (2) f = 0.5*y'*(inv(S)*A*inv(S))*y + (inv(S)*b)'*y - * (scale matrix S is used) - * - * Solution process is started from X=0, we perform ItsCnt=1 outer - * iterations with Newton phase turned off (to slow down convergence; - * we want to prevent algorithm from converging to exact solution which - * is exactly same for both problems; the idea is to test that same - * intermediate tests are taken). - * - * As result, we must get S*x=y - */ - eps = 1.0E-3; - itscnt = 1; - n = 100; - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = ae_pow(10.0, randomnormal(_state)/10, _state); - } - spdmatrixrndcond(n, 1.0E3, &a, _state); - ae_matrix_set_length(&za, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - za.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]); - } - } - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&zb, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = randomnormal(_state); - zb.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i]; - } - minqpcreate(n, &state, _state); - minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, itscnt, ae_false, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetquadraticterm(&state, &a, ae_true, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend0, &rep, _state); - minqpcreate(n, &state, _state); - minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, itscnt, ae_false, _state); - minqpsetlinearterm(&state, &zb, _state); - minqpsetquadraticterm(&state, &za, ae_true, _state); - minqpsetscale(&state, &s, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend1, &rep, _state); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(s.ptr.p_double[i]*xend0.ptr.p_double[i]-xend1.ptr.p_double[i], _state),eps), __FILE__, __LINE__, "testminqpunit.ap:6522"); - } - - /* - * Test that QQP can efficiently use sparse matrices (i.e. it is - * not disguised version of some dense QP solver). In order to test - * it we create very large and very sparse problem (diagonal matrix - * with N=40.000) and perform 10 iterations of QQP solver. - * - * In case QP solver uses some form of dense linear algebra to solve - * this problem, it will take TOO much time to solve it. And we will - * notice it by EXTREME slowdown during testing. - */ - n = 40000; - sparsecreate(n, n, 0, &sa, _state); - for(i=0; i<=n-1; i++) - { - sparseset(&sa, i, i, ae_pow(10.0, -3*ae_randomreal(_state), _state), _state); - } - ae_vector_set_length(&b, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = randomnormal(_state); - } - minqpcreate(n, &state, _state); - minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, 10, ae_fp_greater(hqrnduniformr(&rs, _state),0.5), _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetquadratictermsparse(&state, &sa, ae_true, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend0, &rep, _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function performs tests specific for BLEIC solver - -Returns True on error, False on success. -*************************************************************************/ -ae_bool bleictests(ae_state *_state) -{ - ae_frame _frame_block; - minqpstate state; - minqpreport rep; - ae_vector nlist; - ae_int_t nidx; - ae_matrix a; - ae_matrix za; - ae_matrix c; - ae_vector b; - ae_vector zb; - ae_vector bndl; - ae_vector bndu; - ae_vector s; - ae_vector x; - ae_vector ct; - sparsematrix sa; - ae_int_t n; - ae_vector x0; - ae_vector x1; - hqrndstate rs; - ae_int_t i; - ae_int_t j; - ae_int_t pass; - ae_vector xend0; - ae_vector xend1; - double eps; - double v; - double g; - double gnorm; - ae_int_t itscnt; - ae_bool isupper; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&nlist, 0, sizeof(nlist)); - memset(&a, 0, sizeof(a)); - memset(&za, 0, sizeof(za)); - memset(&c, 0, sizeof(c)); - memset(&b, 0, sizeof(b)); - memset(&zb, 0, sizeof(zb)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&s, 0, sizeof(s)); - memset(&x, 0, sizeof(x)); - memset(&ct, 0, sizeof(ct)); - memset(&sa, 0, sizeof(sa)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&rs, 0, sizeof(rs)); - memset(&xend0, 0, sizeof(xend0)); - memset(&xend1, 0, sizeof(xend1)); - _minqpstate_init(&state, _state, ae_true); - _minqpreport_init(&rep, _state, ae_true); - ae_vector_init(&nlist, 0, DT_INT, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&za, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&zb, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - _sparsematrix_init(&sa, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - ae_vector_init(&xend0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xend1, 0, DT_REAL, _state, ae_true); - - result = ae_false; - hqrndrandomize(&rs, _state); - - /* - * Test sparse functionality. BLEIC-based solver must perform - * same steps independently of matrix type (dense or sparse). - * - * We generate random unconstrained test problem and solve it - * twice - first time we solve dense version, second time - - * sparse version is solved. - */ - eps = 1.0E-3; - itscnt = 5; - n = 20; - isupper = ae_fp_greater(ae_randomreal(_state),0.5); - spdmatrixrndcond(n, 1.0E3, &za, _state); - sparsecreate(n, n, 0, &sa, _state); - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( j>=i&&isupper ) - { - sparseset(&sa, i, j, za.ptr.pp_double[i][j], _state); - a.ptr.pp_double[i][j] = za.ptr.pp_double[i][j]; - } - if( j<=i&&!isupper ) - { - sparseset(&sa, i, j, za.ptr.pp_double[i][j], _state); - a.ptr.pp_double[i][j] = za.ptr.pp_double[i][j]; - } - } - } - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = randomnormal(_state); - s.ptr.p_double[i] = ae_pow(10.0, randomnormal(_state)/10, _state); - } - minqpcreate(n, &state, _state); - minqpsetalgobleic(&state, 0.0, 0.0, 0.0, itscnt, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetquadraticterm(&state, &a, isupper, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend0, &rep, _state); - minqpcreate(n, &state, _state); - minqpsetalgobleic(&state, 0.0, 0.0, 0.0, itscnt, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetquadratictermsparse(&state, &sa, isupper, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend1, &rep, _state); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(xend0.ptr.p_double[i]-xend1.ptr.p_double[i], _state),eps), __FILE__, __LINE__, "testminqpunit.ap:6637"); - } - - /* - * Test scale-invariance. BLEIC performs same steps on scaled and - * unscaled problems (assuming that scale of the variables is known). - * - * We generate random scale matrix S and random well-conditioned and - * well scaled matrix A. Then we solve two problems: - * - * (1) f = 0.5*x'*A*x+b'*x - * (identity scale matrix is used) - * - * and - * - * (2) f = 0.5*y'*(inv(S)*A*inv(S))*y + (inv(S)*b)'*y - * (scale matrix S is used) - * - * Solution process is started from X=0, we perform ItsCnt=5 steps. - * As result, we must get S*x=y - */ - eps = 1.0E-3; - itscnt = 5; - n = 20; - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = ae_pow(10.0, randomnormal(_state)/10, _state); - } - spdmatrixrndcond(n, 1.0E3, &a, _state); - ae_matrix_set_length(&za, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - za.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]); - } - } - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&zb, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = randomnormal(_state); - zb.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i]; - } - minqpcreate(n, &state, _state); - minqpsetalgobleic(&state, 0.0, 0.0, 0.0, itscnt, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetquadraticterm(&state, &a, ae_true, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend0, &rep, _state); - minqpcreate(n, &state, _state); - minqpsetalgobleic(&state, 0.0, 0.0, 0.0, itscnt, _state); - minqpsetlinearterm(&state, &zb, _state); - minqpsetquadraticterm(&state, &za, ae_true, _state); - minqpsetscale(&state, &s, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend1, &rep, _state); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(s.ptr.p_double[i]*xend0.ptr.p_double[i]-xend1.ptr.p_double[i], _state),eps), __FILE__, __LINE__, "testminqpunit.ap:6690"); - } - - /* - * Test that BLEIC can efficiently use sparse matrices (i.e. it is - * not disguised version of some dense QP solver). In order to test - * it we create very large and very sparse problem (diagonal matrix - * with N=20.000) and perform 10 iterations of BLEIC-based QP solver. - * - * In case QP solver uses some form of dense linear algebra to solve - * this problem, it will take TOO much time to solve it. And we will - * notice it by EXTREME slowdown during testing. - */ - n = 20000; - sparsecreate(n, n, 0, &sa, _state); - for(i=0; i<=n-1; i++) - { - sparseset(&sa, i, i, ae_pow(10.0, -3*ae_randomreal(_state), _state), _state); - } - ae_vector_set_length(&b, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = randomnormal(_state); - } - minqpcreate(n, &state, _state); - minqpsetalgobleic(&state, 0.0, 0.0, 0.0, 10, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetquadratictermsparse(&state, &sa, ae_true, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend0, &rep, _state); - - /* - * Special semi-definite test: - * * N dimensions, N>=2 (important!) - * * box constraints, x[i] in [-1,+1] - * [ 1 1 ... 1 1 ] - * * A = [ ... ... ... ] - * [ 1 1 ... 1 1 ] - * * random B such that SUM(b[i])=0.0 (important!) - * * initial point x0 is chosen in such way that SUM(x[i])=0.0 - * (important!) - * - * We perform two tests: - * * unconstrained problem must be recognized as unbounded - * (when starting from x0!) - * * constrained problem must be recognized as bounded - * and successfully solved - * - * Both problems require subtle programming when we work - * with semidefinite QP. - * - * NOTE: it is very important to have N>=2 (otherwise problem - * will be bounded from below even without boundary - * constraints) and to have x0/b0 such that sum of - * components is zero (such x0 is exact minimum of x'*A*x, - * which allows algorithm to find direction of zero curvature - * at the very first step). If x0/b are chosen in other way, - * algorithm may be unable to find direction of zero - * curvature and will cycle forever, slowly decreasing - * function value at each iteration. - * This is major difference from similar test for QQP solver - - * QQP can find direction of zero curvature from almost any - * point due to internal CG solver which favors such directions. - * BLEIC uses LBFGS, which is less able to find direction of - * zero curvature. - */ - ae_vector_set_length(&nlist, 12, _state); - nlist.ptr.p_int[0] = 2; - nlist.ptr.p_int[1] = 3; - nlist.ptr.p_int[2] = 4; - nlist.ptr.p_int[3] = 5; - nlist.ptr.p_int[4] = 6; - nlist.ptr.p_int[5] = 7; - nlist.ptr.p_int[6] = 8; - nlist.ptr.p_int[7] = 9; - nlist.ptr.p_int[8] = 10; - nlist.ptr.p_int[9] = 20; - nlist.ptr.p_int[10] = 40; - nlist.ptr.p_int[11] = 80; - eps = 1.0E-5; - for(nidx=0; nidx<=nlist.cnt-1; nidx++) - { - for(pass=1; pass<=10; pass++) - { - - /* - * Generate problem - */ - n = nlist.ptr.p_int[nidx]; - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - do - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - while(ae_fp_eq(b.ptr.p_double[i],(double)(0))); - bndl.ptr.p_double[i] = (double)(-1); - bndu.ptr.p_double[i] = (double)(1); - x0.ptr.p_double[i] = 2*hqrnduniformr(&rs, _state)-1; - } - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+x0.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = x0.ptr.p_double[i]-v/n; - } - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+b.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = b.ptr.p_double[i]-v/n; - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 1.0; - } - } - testminqpunit_densetosparse(&a, n, &sa, _state); - - /* - * Solve problem: - * * without constraints we expect failure - * * with constraints algorithm must succeed - */ - minqpcreate(n, &state, _state); - minqpsetalgobleic(&state, 0.0, 0.0, 0.0, 0, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetstartingpoint(&state, &x0, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minqpsetquadraticterm(&state, &a, ae_true, _state); - } - else - { - minqpsetquadratictermsparse(&state, &sa, ae_true, _state); - } - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype!=-4, __FILE__, __LINE__, "testminqpunit.ap:6818"); - minqpsetbc(&state, &bndl, &bndu, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:6822"); - if( rep.terminationtype<=0 ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test - calculate constrained gradient at solution, - * check its norm. - */ - gnorm = 0.0; - for(i=0; i<=n-1; i++) - { - g = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - g = g+a.ptr.pp_double[i][j]*x1.ptr.p_double[j]; - } - if( ae_fp_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i])&&ae_fp_greater(g,(double)(0)) ) - { - g = (double)(0); - } - if( ae_fp_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i])&&ae_fp_less(g,(double)(0)) ) - { - g = (double)(0); - } - gnorm = gnorm+ae_sqr(g, _state); - ae_set_error_flag(&result, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6842"); - ae_set_error_flag(&result, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6843"); - } - gnorm = ae_sqrt(gnorm, _state); - ae_set_error_flag(&result, ae_fp_greater(gnorm,eps), __FILE__, __LINE__, "testminqpunit.ap:6846"); - } - } - - /* - * Test that BLEIC-based QP solver can solve non-convex problems - * which are bounded from below on the feasible set: - * - * min -||x||^2 s.t. x[i] in [-1,+1] - * - * We also test ability of the solver to detect unbounded problems - * (we remove one of the constraints and repeat solution process). - */ - n = 20; - eps = 1.0E-14; - sparsecreate(n, n, 0, &sa, _state); - for(i=0; i<=n-1; i++) - { - sparseset(&sa, i, i, (double)(-1), _state); - } - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x, n, _state); - for(i=0; i<=n-1; i++) - { - bndl.ptr.p_double[i] = (double)(-1); - bndu.ptr.p_double[i] = (double)(1); - x.ptr.p_double[i] = ae_randomreal(_state)-0.5; - } - minqpcreate(n, &state, _state); - minqpsetalgobleic(&state, eps, 0.0, 0.0, 0, _state); - minqpsetquadratictermsparse(&state, &sa, ae_true, _state); - minqpsetbc(&state, &bndl, &bndu, _state); - minqpsetstartingpoint(&state, &x, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend0, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:6879"); - if( rep.terminationtype>0 ) - { - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(&result, ae_fp_neq(xend0.ptr.p_double[i],(double)(-1))&&ae_fp_neq(xend0.ptr.p_double[i],(double)(1)), __FILE__, __LINE__, "testminqpunit.ap:6882"); - } - } - i = ae_randominteger(n, _state); - bndl.ptr.p_double[i] = _state->v_neginf; - bndu.ptr.p_double[i] = _state->v_posinf; - minqpsetbc(&state, &bndl, &bndu, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend0, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype!=-4, __FILE__, __LINE__, "testminqpunit.ap:6889"); - - /* - * Test that BLEIC-based QP solver can solve non-convex problems - * which are bounded from below on the feasible set: - * - * min -||x||^2 s.t. x[i] in [-1,+1], - * with inequality constraints handled as general linear ones - * - * We also test ability of the solver to detect unbounded problems - * (we remove last pair of constraints and try to solve modified - * problem). - */ - n = 20; - eps = 1.0E-14; - sparsecreate(n, n, 0, &sa, _state); - for(i=0; i<=n-1; i++) - { - sparseset(&sa, i, i, (double)(-1), _state); - } - ae_matrix_set_length(&c, 2*n, n+1, _state); - ae_vector_set_length(&ct, 2*n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n; j++) - { - c.ptr.pp_double[2*i+0][j] = (double)(0); - c.ptr.pp_double[2*i+1][j] = (double)(0); - } - c.ptr.pp_double[2*i+0][i] = 1.0; - c.ptr.pp_double[2*i+0][n] = 1.0; - ct.ptr.p_int[2*i+0] = -1; - c.ptr.pp_double[2*i+1][i] = 1.0; - c.ptr.pp_double[2*i+1][n] = -1.0; - ct.ptr.p_int[2*i+1] = 1; - } - ae_vector_set_length(&x, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = ae_randomreal(_state)-0.5; - } - minqpcreate(n, &state, _state); - minqpsetalgobleic(&state, eps, 0.0, 0.0, 0, _state); - minqpsetquadratictermsparse(&state, &sa, ae_true, _state); - minqpsetlc(&state, &c, &ct, 2*n, _state); - minqpsetstartingpoint(&state, &x, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend0, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:6934"); - if( rep.terminationtype>0 ) - { - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(xend0.ptr.p_double[i]+1, _state),100*ae_machineepsilon)&&ae_fp_greater(ae_fabs(xend0.ptr.p_double[i]-1, _state),100*ae_machineepsilon), __FILE__, __LINE__, "testminqpunit.ap:6937"); - } - } - minqpsetlc(&state, &c, &ct, 2*(n-1), _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend0, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype!=-4, __FILE__, __LINE__, "testminqpunit.ap:6941"); - - /* - * Test that BLEIC-based QP solver can solve QP problems with - * zero quadratic term: - * - * min b'*x s.t. x[i] in [-1,+1] - * - * It means that QP solver can be used as linear programming solver - * (altough performance of such solver is worse than that of specialized - * LP solver). - * - * NOTE: we perform this test twice - first time without explicitly setting - * quadratic term (we test that default quadratic term is zero), and - * second time - with explicitly set quadratic term. - */ - n = 20; - sparsecreate(n, n, 0, &sa, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&b, n, _state); - for(i=0; i<=n-1; i++) - { - bndl.ptr.p_double[i] = (double)(-1); - bndu.ptr.p_double[i] = (double)(1); - b.ptr.p_double[i] = randomnormal(_state); - } - minqpcreate(n, &state, _state); - minqpsetalgobleic(&state, eps, 0.0, 0.0, 0, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetbc(&state, &bndl, &bndu, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend0, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:6975"); - if( rep.terminationtype>0 ) - { - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(&result, ae_fp_greater(b.ptr.p_double[i],(double)(0))&&ae_fp_neq(xend0.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6979"); - ae_set_error_flag(&result, ae_fp_less(b.ptr.p_double[i],(double)(0))&&ae_fp_neq(xend0.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6980"); - } - } - minqpcreate(n, &state, _state); - minqpsetalgobleic(&state, eps, 0.0, 0.0, 0, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetbc(&state, &bndl, &bndu, _state); - minqpsetquadratictermsparse(&state, &sa, ae_true, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend0, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:6989"); - if( rep.terminationtype>0 ) - { - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(&result, ae_fp_greater(b.ptr.p_double[i],(double)(0))&&ae_fp_neq(xend0.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6993"); - ae_set_error_flag(&result, ae_fp_less(b.ptr.p_double[i],(double)(0))&&ae_fp_neq(xend0.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6994"); - } - } - - /* - * Test specific problem sent by V.Semenenko, which resulted in - * the initinite loop in FindFeasiblePoint (before fix). We do - * not test results returned by solver - simply being able to - * stop is enough for this test. - * - * NOTE: it is important that modifications to problem are applied - * sequentially. Test fails after 100-5000 such modifications. - * One modification is not enough to cause failure. - */ - n = 3; - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - a.ptr.pp_double[0][0] = 1.222990; - a.ptr.pp_double[1][1] = 1.934900; - a.ptr.pp_double[2][2] = 0.603924; - ae_vector_set_length(&b, n, _state); - b.ptr.p_double[0] = -4.97245; - b.ptr.p_double[1] = -9.09039; - b.ptr.p_double[2] = -4.63856; - ae_matrix_set_length(&c, 8, n+1, _state); - for(i=0; i<=c.rows-1; i++) - { - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = 0.0; - } - } - c.ptr.pp_double[0][0] = (double)(1); - c.ptr.pp_double[0][n] = 4.94298; - c.ptr.pp_double[1][0] = (double)(1); - c.ptr.pp_double[1][n] = 4.79981; - c.ptr.pp_double[2][1] = (double)(1); - c.ptr.pp_double[2][n] = -0.4848; - c.ptr.pp_double[3][1] = (double)(1); - c.ptr.pp_double[3][n] = -0.73804; - c.ptr.pp_double[4][2] = (double)(1); - c.ptr.pp_double[4][n] = 0.575729; - c.ptr.pp_double[5][2] = (double)(1); - c.ptr.pp_double[5][n] = 0.458645; - c.ptr.pp_double[6][0] = (double)(1); - c.ptr.pp_double[6][2] = (double)(-1); - c.ptr.pp_double[6][n] = -0.0546574; - c.ptr.pp_double[7][0] = (double)(1); - c.ptr.pp_double[7][2] = (double)(-1); - c.ptr.pp_double[7][n] = -0.5900440; - ae_vector_set_length(&ct, 8, _state); - ct.ptr.p_int[0] = -1; - ct.ptr.p_int[1] = 1; - ct.ptr.p_int[2] = -1; - ct.ptr.p_int[3] = 1; - ct.ptr.p_int[4] = -1; - ct.ptr.p_int[5] = 1; - ct.ptr.p_int[6] = -1; - ct.ptr.p_int[7] = 1; - ae_vector_set_length(&s, n, _state); - s.ptr.p_double[0] = 0.143171; - s.ptr.p_double[1] = 0.253240; - s.ptr.p_double[2] = 0.117084; - ae_vector_set_length(&x0, n, _state); - x0.ptr.p_double[0] = 3.51126; - x0.ptr.p_double[1] = 4.05731; - x0.ptr.p_double[2] = 6.63307; - for(pass=1; pass<=10000; pass++) - { - - /* - * Apply random distortion - */ - for(j=0; j<=n-1; j++) - { - b.ptr.p_double[j] = b.ptr.p_double[j]+(2*hqrnduniformi(&rs, 2, _state)-1)*0.1; - } - for(j=0; j<=6-1; j++) - { - c.ptr.pp_double[j][n] = c.ptr.pp_double[j][n]+(2*hqrnduniformi(&rs, 2, _state)-1)*0.1; - } - - /* - * Solve - */ - minqpcreate(3, &state, _state); - minqpsetquadraticterm(&state, &a, ae_true, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetlc(&state, &c, &ct, 8, _state); - minqpsetalgobleic(&state, 0.0, 0.0, 0.0, 0, _state); - minqpsetstartingpoint(&state, &x0, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function tests bound constrained quadratic programming algorithm. - -On failure sets error flag. -*************************************************************************/ -static void testminqpunit_bcqptest(ae_bool* wereerrors, ae_state *_state) -{ - ae_frame _frame_block; - minqpstate state; - minqpreport rep; - ae_int_t n; - ae_int_t pass; - ae_int_t i; - ae_int_t j; - double v; - double g; - double gnorm; - ae_int_t origintype; - ae_int_t scaletype; - ae_bool isupper; - ae_bool issparse; - double bctol; - double lctol; - ae_matrix a; - ae_matrix fulla; - ae_matrix halfa; - ae_matrix c; - sparsematrix sa; - ae_vector ct; - ae_vector b; - ae_vector bndl; - ae_vector bndu; - ae_vector gtrial; - double vl; - double vu; - ae_vector x0; - ae_vector x1; - ae_vector xori; - ae_vector xz; - ae_vector s; - double eps; - hqrndstate rs; - ae_int_t solvertype; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&a, 0, sizeof(a)); - memset(&fulla, 0, sizeof(fulla)); - memset(&halfa, 0, sizeof(halfa)); - memset(&c, 0, sizeof(c)); - memset(&sa, 0, sizeof(sa)); - memset(&ct, 0, sizeof(ct)); - memset(&b, 0, sizeof(b)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(>rial, 0, sizeof(gtrial)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&xori, 0, sizeof(xori)); - memset(&xz, 0, sizeof(xz)); - memset(&s, 0, sizeof(s)); - memset(&rs, 0, sizeof(rs)); - _minqpstate_init(&state, _state, ae_true); - _minqpreport_init(&rep, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&fulla, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&halfa, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&sa, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - ae_vector_init(>rial, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xori, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xz, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Convex test: - * * N dimensions - * * random number (0..N) of random boundary constraints - * * positive-definite A - * * algorithm randomly choose dense or sparse A, and for - * sparse matrix it randomly choose format. - * * random B with normal entries - * * initial point is random, feasible - * * random origin (zero or non-zero) and scale (unit or - * non-unit) are generated - */ - eps = 1.0E-3; - for(n=1; n<=10; n++) - { - for(pass=1; pass<=10; pass++) - { - - /* - * Generate problem - */ - origintype = hqrnduniformi(&rs, 2, _state); - scaletype = hqrnduniformi(&rs, 2, _state); - isupper = ae_fp_less(hqrnduniformr(&rs, _state),0.5); - issparse = ae_fp_less(hqrnduniformr(&rs, _state),0.5); - spdmatrixrndcond(n, 1.0E3, &fulla, _state); - ae_matrix_set_length(&halfa, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (j>=i&&isupper)||(j<=i&&!isupper) ) - { - halfa.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j]; - } - else - { - halfa.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5; - } - } - } - testminqpunit_densetosparse(&halfa, n, &sa, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xori, n, _state); - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - bndl.ptr.p_double[i] = _state->v_neginf; - bndu.ptr.p_double[i] = _state->v_posinf; - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - if( origintype==0 ) - { - xori.ptr.p_double[i] = (double)(0); - } - else - { - xori.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - if( scaletype==0 ) - { - s.ptr.p_double[i] = (double)(1); - } - else - { - s.ptr.p_double[i] = ae_exp(0.5*hqrndnormal(&rs, _state), _state); - } - j = hqrnduniformi(&rs, 5, _state); - if( j==0 ) - { - bndl.ptr.p_double[i] = (double)(0); - x0.ptr.p_double[i] = ae_fabs(x0.ptr.p_double[i], _state); - } - if( j==1 ) - { - bndu.ptr.p_double[i] = (double)(0); - x0.ptr.p_double[i] = -ae_fabs(x0.ptr.p_double[i], _state); - } - if( j==2 ) - { - bndl.ptr.p_double[i] = hqrndnormal(&rs, _state); - bndu.ptr.p_double[i] = bndl.ptr.p_double[i]; - x0.ptr.p_double[i] = bndl.ptr.p_double[i]; - } - if( j==3 ) - { - bndl.ptr.p_double[i] = -0.1; - bndu.ptr.p_double[i] = 0.1; - x0.ptr.p_double[i] = 0.2*hqrnduniformr(&rs, _state)-0.1; - } - } - - /* - * Solve problem - */ - minqpcreate(n, &state, _state); - solvertype = testminqpunit_setrandomalgoallmodern(&state, &bctol, &lctol, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetstartingpoint(&state, &x0, _state); - if( issparse ) - { - minqpsetquadratictermsparse(&state, &sa, isupper, _state); - } - else - { - minqpsetquadraticterm(&state, &halfa, isupper, _state); - } - if( origintype!=0 ) - { - minqpsetorigin(&state, &xori, _state); - } - if( scaletype!=0 ) - { - minqpsetscale(&state, &s, _state); - } - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minqpsetbc(&state, &bndl, &bndu, _state); - } - else - { - for(i=0; i<=n-1; i++) - { - minqpsetbci(&state, i, bndl.ptr.p_double[i], bndu.ptr.p_double[i], _state); - } - } - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:882"); - ae_set_error_flag(wereerrors, x1.cnt=i&&isupper)||(j<=i&&!isupper) ) - { - halfa.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j]; - } - else - { - halfa.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5; - } - } - } - testminqpunit_densetosparse(&halfa, n, &sa, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xori, n, _state); - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - if( origintype==0 ) - { - xori.ptr.p_double[i] = (double)(0); - } - else - { - xori.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - if( scaletype==0 ) - { - s.ptr.p_double[i] = (double)(1); - } - else - { - s.ptr.p_double[i] = ae_exp(0.5*hqrndnormal(&rs, _state), _state); - } - } - vl = _state->v_neginf; - vu = _state->v_posinf; - j = hqrnduniformi(&rs, 5, _state); - if( j==0 ) - { - vl = (double)(0); - } - if( j==1 ) - { - vu = (double)(0); - } - if( j==2 ) - { - vl = hqrndnormal(&rs, _state); - vu = vl; - } - if( j==3 ) - { - vl = -0.1-ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - vu = 0.1+ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - } - - /* - * Solve problem - */ - minqpcreate(n, &state, _state); - testminqpunit_setrandomalgoallmodern(&state, &bctol, &lctol, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetstartingpoint(&state, &x0, _state); - if( issparse ) - { - minqpsetquadratictermsparse(&state, &sa, isupper, _state); - } - else - { - minqpsetquadraticterm(&state, &halfa, isupper, _state); - } - if( origintype!=0 ) - { - minqpsetorigin(&state, &xori, _state); - } - if( scaletype!=0 ) - { - minqpsetscale(&state, &s, _state); - } - minqpsetbcall(&state, vl, vu, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:1017"); - if( rep.terminationtype<=0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Test - calculate constrained gradient at solution, - * check its norm. - */ - gnorm = 0.0; - for(i=0; i<=n-1; i++) - { - g = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - g = g+fulla.ptr.pp_double[i][j]*(x1.ptr.p_double[j]-xori.ptr.p_double[j]); - } - if( ae_fp_less_eq(x1.ptr.p_double[i],vl+bctol)&&ae_fp_greater(g,(double)(0)) ) - { - g = (double)(0); - } - if( ae_fp_greater_eq(x1.ptr.p_double[i],vu-bctol)&&ae_fp_less(g,(double)(0)) ) - { - g = (double)(0); - } - gnorm = gnorm+ae_sqr(g, _state); - ae_set_error_flag(wereerrors, ae_fp_less(x1.ptr.p_double[i],vl), __FILE__, __LINE__, "testminqpunit.ap:1037"); - ae_set_error_flag(wereerrors, ae_fp_greater(x1.ptr.p_double[i],vu), __FILE__, __LINE__, "testminqpunit.ap:1038"); - } - gnorm = ae_sqrt(gnorm, _state); - ae_set_error_flag(wereerrors, ae_fp_greater(gnorm,eps), __FILE__, __LINE__, "testminqpunit.ap:1041"); - } - } - - /* - * Semidefinite test: - * * N dimensions - * * nonnegativity constraints - * * A = [ 1 1 ... 1 1 ; 1 1 ... 1 1 ; .... ; 1 1 ... 1 1 ] - * * algorithm randomly choose dense or sparse A, and for - * sparse matrix it randomly choose format. - * * random B with normal entries - * * initial point is random, feasible - */ - eps = 1.0E-4; - for(n=1; n<=10; n++) - { - for(pass=1; pass<=10; pass++) - { - - /* - * Generate problem - */ - isupper = ae_fp_less(hqrnduniformr(&rs, _state),0.5); - issparse = ae_fp_less(hqrnduniformr(&rs, _state),0.5); - ae_matrix_set_length(&fulla, n, n, _state); - ae_matrix_set_length(&halfa, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - fulla.ptr.pp_double[i][j] = 1.0; - if( (j>=i&&isupper)||(j<=i&&!isupper) ) - { - halfa.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j]; - } - else - { - halfa.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5; - } - } - } - testminqpunit_densetosparse(&halfa, n, &sa, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - bndl.ptr.p_double[i] = 0.0; - bndu.ptr.p_double[i] = _state->v_posinf; - x0.ptr.p_double[i] = (double)(hqrnduniformi(&rs, 2, _state)); - } - - /* - * Solve problem - */ - minqpcreate(n, &state, _state); - testminqpunit_setrandomalgosemidefinite(&state, &bctol, &lctol, _state); - minqpsetstartingpoint(&state, &x0, _state); - minqpsetlinearterm(&state, &b, _state); - if( issparse ) - { - minqpsetquadratictermsparse(&state, &sa, isupper, _state); - } - else - { - minqpsetquadraticterm(&state, &halfa, isupper, _state); - } - minqpsetbc(&state, &bndl, &bndu, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:1101"); - if( rep.terminationtype<=0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Test - calculate constrained gradient at solution, - * check its norm. - */ - gnorm = 0.0; - for(i=0; i<=n-1; i++) - { - g = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - g = g+fulla.ptr.pp_double[i][j]*x1.ptr.p_double[j]; - } - if( ae_fp_less_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i]+bctol)&&ae_fp_greater(g,(double)(0)) ) - { - g = (double)(0); - } - if( ae_fp_greater_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i]-bctol)&&ae_fp_less(g,(double)(0)) ) - { - g = (double)(0); - } - gnorm = gnorm+ae_sqr(g, _state); - ae_set_error_flag(wereerrors, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:1121"); - ae_set_error_flag(wereerrors, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:1122"); - } - gnorm = ae_sqrt(gnorm, _state); - ae_set_error_flag(wereerrors, ae_fp_greater(gnorm,eps), __FILE__, __LINE__, "testminqpunit.ap:1125"); - } - } - - /* - * Non-convex test: - * * N dimensions, N>=2 - * * box constraints, x[i] in [-1,+1] - * * A = A0-0.5*I, where A0 is SPD with unit norm and smallest - * singular value equal to 1.0E-3, I is identity matrix - * * random B with normal entries - * * initial point is random, feasible - * - * We perform two tests: - * * unconstrained problem must be recognized as unbounded - * * constrained problem can be successfully solved - * - * NOTE: it is important to have N>=2, because formula for A - * can be applied only to matrix with at least two - * singular values - */ - eps = 1.0E-4; - for(n=2; n<=10; n++) - { - for(pass=1; pass<=10; pass++) - { - - /* - * Generate problem - */ - spdmatrixrndcond(n, 1.0E3, &fulla, _state); - for(i=0; i<=n-1; i++) - { - fulla.ptr.pp_double[i][i] = fulla.ptr.pp_double[i][i]-0.5; - } - isupper = ae_fp_less(hqrnduniformr(&rs, _state),0.5); - ae_matrix_set_length(&halfa, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (j>=i&&isupper)||(j<=i&&!isupper) ) - { - halfa.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j]; - } - else - { - halfa.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5; - } - } - } - testminqpunit_densetosparse(&halfa, n, &sa, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - bndl.ptr.p_double[i] = (double)(-1); - bndu.ptr.p_double[i] = (double)(1); - x0.ptr.p_double[i] = 2*hqrnduniformr(&rs, _state)-1; - } - - /* - * Solve problem: - * * without constraints we expect failure - * * with constraints algorithm must succeed - */ - minqpcreate(n, &state, _state); - testminqpunit_setrandomalgononconvex(&state, _state); - minqpsetstartingpoint(&state, &x0, _state); - minqpsetlinearterm(&state, &b, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minqpsetquadraticterm(&state, &halfa, isupper, _state); - } - else - { - minqpsetquadratictermsparse(&state, &sa, isupper, _state); - } - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, rep.terminationtype!=-4, __FILE__, __LINE__, "testminqpunit.ap:1192"); - minqpsetbc(&state, &bndl, &bndu, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:1196"); - if( rep.terminationtype<=0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Test - calculate constrained gradient at solution, - * check its norm. - */ - gnorm = 0.0; - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&fulla.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - g = v+b.ptr.p_double[i]; - if( ae_fp_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i])&&ae_fp_greater(g,(double)(0)) ) - { - g = (double)(0); - } - if( ae_fp_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i])&&ae_fp_less(g,(double)(0)) ) - { - g = (double)(0); - } - gnorm = gnorm+ae_sqr(g, _state); - ae_set_error_flag(wereerrors, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:1215"); - ae_set_error_flag(wereerrors, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:1216"); - } - gnorm = ae_sqrt(gnorm, _state); - ae_set_error_flag(wereerrors, ae_fp_greater(gnorm,eps), __FILE__, __LINE__, "testminqpunit.ap:1219"); - } - } - - /* - * Linear (zero-quadratic) test: - * * N dimensions, N>=1 - * * box constraints, x[i] in [-1,+1] - * * A = 0 - * * random B with normal entries - * * initial point is random, feasible - * - * We perform two tests: - * * unconstrained problem must be recognized as unbounded - * * constrained problem can be successfully solved - * - * NOTE: we may explicitly set zero A, or assume that by - * default it is zero. During test we will try both - * ways. - */ - eps = 1.0E-4; - for(n=1; n<=10; n++) - { - for(pass=1; pass<=10; pass++) - { - - /* - * Generate problem - */ - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - do - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - while(ae_fp_eq(b.ptr.p_double[i],(double)(0))); - bndl.ptr.p_double[i] = (double)(-1); - bndu.ptr.p_double[i] = (double)(1); - x0.ptr.p_double[i] = 2*hqrnduniformr(&rs, _state)-1; - } - - /* - * Solve problem: - * * without constraints we expect failure - * * with constraints algorithm must succeed - */ - minqpcreate(n, &state, _state); - testminqpunit_setrandomalgosemidefinite(&state, &bctol, &lctol, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetstartingpoint(&state, &x0, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - minqpsetquadraticterm(&state, &a, ae_true, _state); - } - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, rep.terminationtype!=-4&&rep.terminationtype!=-2, __FILE__, __LINE__, "testminqpunit.ap:1278"); - minqpsetbc(&state, &bndl, &bndu, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:1283"); - if( rep.terminationtype<=0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Test - calculate constrained gradient at solution, - * check its norm. - */ - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(wereerrors, ae_fp_greater(b.ptr.p_double[i],(double)(0))&&ae_fp_greater(x1.ptr.p_double[i],bndl.ptr.p_double[i]+bctol), __FILE__, __LINE__, "testminqpunit.ap:1293"); - ae_set_error_flag(wereerrors, ae_fp_less(b.ptr.p_double[i],(double)(0))&&ae_fp_less(x1.ptr.p_double[i],bndu.ptr.p_double[i]-bctol), __FILE__, __LINE__, "testminqpunit.ap:1294"); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests equality constrained quadratic programming algorithm. - -Returns True on errors. -*************************************************************************/ -static ae_bool testminqpunit_ecqptest(ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t k; - ae_matrix a; - ae_matrix q; - ae_matrix c; - ae_matrix a2; - ae_vector b; - ae_vector b2; - ae_vector xstart; - ae_vector xstart2; - ae_vector xend; - ae_vector xend2; - ae_vector x0; - ae_vector x1; - ae_vector xd; - ae_vector xs; - ae_vector tmp; - ae_vector g; - ae_vector bndl; - ae_vector bndu; - ae_vector xorigin; - ae_vector ct; - double eps; - double theta; - double f0; - double f1; - minqpstate state; - minqpstate state2; - minqpreport rep; - ae_int_t i; - ae_int_t j; - ae_int_t pass; - ae_int_t rk; - double v; - ae_int_t aulits; - ae_bool waserrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&q, 0, sizeof(q)); - memset(&c, 0, sizeof(c)); - memset(&a2, 0, sizeof(a2)); - memset(&b, 0, sizeof(b)); - memset(&b2, 0, sizeof(b2)); - memset(&xstart, 0, sizeof(xstart)); - memset(&xstart2, 0, sizeof(xstart2)); - memset(&xend, 0, sizeof(xend)); - memset(&xend2, 0, sizeof(xend2)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&xd, 0, sizeof(xd)); - memset(&xs, 0, sizeof(xs)); - memset(&tmp, 0, sizeof(tmp)); - memset(&g, 0, sizeof(g)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&xorigin, 0, sizeof(xorigin)); - memset(&ct, 0, sizeof(ct)); - memset(&state, 0, sizeof(state)); - memset(&state2, 0, sizeof(state2)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a2, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xstart, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xstart2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xend, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xend2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xd, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xs, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&g, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xorigin, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - _minqpstate_init(&state, _state, ae_true); - _minqpstate_init(&state2, _state, ae_true); - _minqpreport_init(&rep, _state, ae_true); - - waserrors = ae_false; - - /* - * First test: - * * N*N identity A - * * K=0, where q is random unit vector - * * optimization problem has form 0.5*x'*A*x-(x1*A)*x, - * where x1 is some random vector - * * either: - * a) x1 is feasible => we must stop at x1 - * b) x1 is infeasible => we must stop at the boundary q'*x=0 and - * projection of gradient onto q*x=0 must be zero - * - * NOTE: we make several passes because some specific kind of errors is rarely - * caught by this test, so we need several repetitions. - */ - eps = 1.0E-4; - for(n=2; n<=6; n++) - { - for(pass=0; pass<=4; pass++) - { - - /* - * Generate problem: A, b, CMatrix, x0, XStart - */ - spdmatrixrndcond(n, ae_pow(10.0, 3*ae_randomreal(_state), _state), &a, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x1, n, _state); - ae_vector_set_length(&xstart, n, _state); - ae_matrix_set_length(&c, 1, n+1, _state); - ae_vector_set_length(&ct, 1, _state); - for(i=0; i<=n-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - xstart.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - do - { - v = (double)(0); - for(i=0; i<=n-1; i++) - { - c.ptr.pp_double[0][i] = 2*ae_randomreal(_state)-1; - v = v+ae_sqr(c.ptr.pp_double[0][i], _state); - } - v = ae_sqrt(v, _state); - } - while(ae_fp_eq(v,(double)(0))); - for(i=0; i<=n-1; i++) - { - c.ptr.pp_double[0][i] = c.ptr.pp_double[0][i]/v; - } - c.ptr.pp_double[0][n] = (double)(0); - ct.ptr.p_int[0] = 1; - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - b.ptr.p_double[i] = -v; - } - - /* - * Create optimizer, solve - */ - minqpcreate(n, &state, _state); - testminqpunit_setrandomalgoconvexlc(&state, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetquadraticterm(&state, &a, ae_fp_greater(ae_randomreal(_state),0.5), _state); - minqpsetstartingpoint(&state, &xstart, _state); - minqpsetlc(&state, &c, &ct, 1, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend, &rep, _state); - - /* - * Test - */ - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminqpunit.ap:2160"); - continue; - } - v = ae_v_dotproduct(&x1.ptr.p_double[0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1)); - if( ae_fp_greater_eq(v,(double)(0)) ) - { - - /* - * X1 is feasible, compare target function values at XEnd and X1 - */ - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(xend.ptr.p_double[i]-x1.ptr.p_double[i], _state),eps), __FILE__, __LINE__, "testminqpunit.ap:2173"); - } - } - else - { - - /* - * X1 is infeasible: - * * XEnd must be approximately feasible - * * gradient projection onto c'*x=0 must be zero - */ - v = ae_v_dotproduct(&xend.ptr.p_double[0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1)); - ae_set_error_flag(err, ae_fp_less(v,-eps), __FILE__, __LINE__, "testminqpunit.ap:2183"); - ae_vector_set_length(&g, n, _state); - ae_v_move(&g.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xend.ptr.p_double[0], 1, ae_v_len(0,n-1)); - g.ptr.p_double[i] = g.ptr.p_double[i]+v; - } - v = ae_v_dotproduct(&g.ptr.p_double[0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1)); - ae_v_subd(&g.ptr.p_double[0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1), v); - v = ae_v_dotproduct(&g.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_set_error_flag(err, ae_fp_greater(ae_sqrt(v, _state),eps), __FILE__, __LINE__, "testminqpunit.ap:2194"); - } - } - } - - /* - * Boundary and linear equality/inequality constrained QP problem, - * test for correct handling of non-zero XOrigin: - * * N*N SPD A with moderate condtion number (up to 100) - * * boundary constraints 0<=x[i]<=1 - * * K0 ) - { - ae_set_error_flag(err, ae_fp_less(v,c.ptr.pp_double[i][n]-eps), __FILE__, __LINE__, "testminqpunit.ap:2325"); - } - if( ct.ptr.p_int[i]<0 ) - { - ae_set_error_flag(err, ae_fp_greater(v,c.ptr.pp_double[i][n]+eps), __FILE__, __LINE__, "testminqpunit.ap:2327"); - } - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(xend.ptr.p_double[i]-xend2.ptr.p_double[i], _state),eps), __FILE__, __LINE__, "testminqpunit.ap:2331"); - ae_set_error_flag(err, ae_fp_less(xend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testminqpunit.ap:2332"); - ae_set_error_flag(err, ae_fp_greater(xend.ptr.p_double[i],(double)(1)), __FILE__, __LINE__, "testminqpunit.ap:2333"); - } - } - } - - /* - * Boundary constraints vs linear ones: - * * N*N SPD A - * * optimization problem has form 0.5*x'*A*x-(x1*A)*x, - * where x1 is some random vector from [-1,+1] - * * K=2*N constraints of the form ai<=x[i] or x[i]<=b[i], - * with ai in [-1.0,-0.1], bi in [+0.1,+1.0] - * * initial point xstart is from [-1,+2] - * * we solve two related QP problems: - * a) one with constraints posed as boundary ones - * b) another one with same constraints posed as general linear ones - * both problems must have same solution. - * Here we test that boundary constrained and linear inequality constrained - * solvers give same results. - */ - eps = 1.0E-3; - for(n=1; n<=6; n++) - { - - /* - * Generate problem: A, b, x0, XStart, C, CT - */ - spdmatrixrndcond(n, ae_pow(10.0, 3*ae_randomreal(_state), _state), &a, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x1, n, _state); - ae_vector_set_length(&xstart, n, _state); - ae_matrix_set_length(&c, 2*n, n+1, _state); - ae_vector_set_length(&ct, 2*n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - for(i=0; i<=n-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - xstart.ptr.p_double[i] = 3*ae_randomreal(_state)-1; - bndl.ptr.p_double[i] = -(0.1+0.9*ae_randomreal(_state)); - bndu.ptr.p_double[i] = 0.1+0.9*ae_randomreal(_state); - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[2*i+0][j] = (double)(0); - c.ptr.pp_double[2*i+1][j] = (double)(0); - } - c.ptr.pp_double[2*i+0][i] = (double)(1); - c.ptr.pp_double[2*i+0][n] = bndl.ptr.p_double[i]; - ct.ptr.p_int[2*i+0] = 1; - c.ptr.pp_double[2*i+1][i] = (double)(1); - c.ptr.pp_double[2*i+1][n] = bndu.ptr.p_double[i]; - ct.ptr.p_int[2*i+1] = -1; - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - b.ptr.p_double[i] = -v; - } - - /* - * Solve linear inequality constrained problem - */ - minqpcreate(n, &state, _state); - testminqpunit_setrandomalgoconvexlc(&state, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetquadraticterm(&state, &a, ae_fp_greater(ae_randomreal(_state),0.5), _state); - minqpsetstartingpoint(&state, &xstart, _state); - minqpsetlc(&state, &c, &ct, 2*n, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend, &rep, _state); - - /* - * Solve boundary constrained problem - */ - minqpcreate(n, &state2, _state); - testminqpunit_setrandomalgoconvexlc(&state, _state); - minqpsetlinearterm(&state2, &b, _state); - minqpsetquadraticterm(&state2, &a, ae_fp_greater(ae_randomreal(_state),0.5), _state); - minqpsetstartingpoint(&state2, &xstart, _state); - minqpsetbc(&state2, &bndl, &bndu, _state); - minqpoptimize(&state2, _state); - minqpresults(&state2, &xend2, &rep2, _state); - - /* - * Calculate gradient, check projection - */ - if( rep.terminationtype<=0||rep2.terminationtype<=0 ) - { - ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminqpunit.ap:2421"); - continue; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(err, ae_fp_less(xend.ptr.p_double[i],bndl.ptr.p_double[i]-eps), __FILE__, __LINE__, "testminqpunit.ap:2426"); - ae_set_error_flag(err, ae_fp_greater(xend.ptr.p_double[i],bndu.ptr.p_double[i]+eps), __FILE__, __LINE__, "testminqpunit.ap:2427"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(xend.ptr.p_double[i]-xend2.ptr.p_double[i], _state),eps), __FILE__, __LINE__, "testminqpunit.ap:2428"); - } - } - - /* - * Boundary constraints posed as general linear ones: - * * no bound constraints - * * 2*N linear constraints 0 <= x[i] <= 1 - * * preconditioner is chosen at random (we just want to be - * sure that preconditioning won't prevent us from converging - * to the feasible point): - * * unit preconditioner - * * random diagonal-based preconditioner - * * random scale-based preconditioner - * * F(x) = |x-x0|^P, where P={2,4} and x0 is randomly selected from [-1,+2]^N - * * with such simple constraints and function it is easy to find - * analytic form of solution: S[i] = bound(x0[i], 0, 1). - * * however, we can't guarantee that solution is strictly feasible - * with respect to nonlinearity constraint, so we check - * for approximate feasibility. - */ - for(n=1; n<=5; n++) - { - - /* - * Generate X, BL, BU. - */ - ae_matrix_set_length(&a, n, n, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&xstart, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_matrix_set_length(&c, 2*n, n+1, _state); - ae_vector_set_length(&ct, 2*n, _state); - for(i=0; i<=n-1; i++) - { - xstart.ptr.p_double[i] = ae_randomreal(_state); - x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1; - b.ptr.p_double[i] = -x0.ptr.p_double[i]; - for(j=0; j<=n; j++) - { - c.ptr.pp_double[2*i+0][j] = (double)(0); - c.ptr.pp_double[2*i+1][j] = (double)(0); - } - c.ptr.pp_double[2*i+0][i] = (double)(1); - c.ptr.pp_double[2*i+0][n] = (double)(0); - ct.ptr.p_int[2*i+0] = 1; - c.ptr.pp_double[2*i+1][i] = (double)(1); - c.ptr.pp_double[2*i+1][n] = (double)(1); - ct.ptr.p_int[2*i+1] = -1; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - a.ptr.pp_double[i][j] = (double)(1); - } - else - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - } - - /* - * Create and optimize - */ - minqpcreate(n, &state, _state); - testminqpunit_setrandomalgoconvexlc(&state, _state); - minqpsetlc(&state, &c, &ct, 2*n, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetquadraticterm(&state, &a, ae_fp_greater(ae_randomreal(_state),0.5), _state); - minqpsetstartingpoint(&state, &xstart, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminqpunit.ap:2497"); - continue; - } - - /* - * * compare solution with analytic one - * * check feasibility - */ - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(xend.ptr.p_double[i]-boundval(x0.ptr.p_double[i], 0.0, 1.0, _state), _state),0.05), __FILE__, __LINE__, "testminqpunit.ap:2507"); - ae_set_error_flag(err, ae_fp_less(xend.ptr.p_double[i],0.0-1.0E-6), __FILE__, __LINE__, "testminqpunit.ap:2508"); - ae_set_error_flag(err, ae_fp_greater(xend.ptr.p_double[i],1.0+1.0E-6), __FILE__, __LINE__, "testminqpunit.ap:2509"); - } - } - - /* - * Boundary and linear equality/inequality constrained QP problem with - * excessive constraints: - * * N*N SPD A with moderate condtion number (up to 100) - * * boundary constraints 0<=x[i]<=1 - * * K=2*N equality/inequality constraints Q*x = Q*x0, where Q is random matrix, - * x0 is some random vector from the feasible hypercube (0.1<=x0[i]<=0.9) - * * optimization problem has form 0.5*x'*A*x-b*x, - * where b is some random vector - * * because constraints are excessive, the main problem is to find - * feasible point; usually, the only existing feasible point is solution, - * so we have to check only feasibility - */ - eps = 1.0E-4; - for(n=1; n<=6; n++) - { - - /* - * Generate problem: A, b, BndL, BndU, CMatrix, x0, x1, XStart - */ - k = 2*n; - spdmatrixrndcond(n, ae_pow(10.0, 3*ae_randomreal(_state), _state), &a, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&x1, n, _state); - ae_vector_set_length(&xstart, n, _state); - ae_matrix_set_length(&c, k, n+1, _state); - ae_vector_set_length(&ct, k, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 0.1+0.8*ae_randomreal(_state); - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - bndl.ptr.p_double[i] = 0.0; - bndu.ptr.p_double[i] = 1.0; - xstart.ptr.p_double[i] = (double)(ae_randominteger(2, _state)); - } - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ct.ptr.p_int[i] = ae_randominteger(3, _state)-1; - if( ct.ptr.p_int[i]==0 ) - { - c.ptr.pp_double[i][n] = v; - } - if( ct.ptr.p_int[i]>0 ) - { - c.ptr.pp_double[i][n] = v-1.0E-3; - } - if( ct.ptr.p_int[i]<0 ) - { - c.ptr.pp_double[i][n] = v+1.0E-3; - } - } - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - - /* - * Create optimizer, solve - */ - minqpcreate(n, &state, _state); - testminqpunit_setrandomalgoconvexlc(&state, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetquadraticterm(&state, &a, ae_fp_greater(ae_randomreal(_state),0.5), _state); - minqpsetstartingpoint(&state, &xstart, _state); - minqpsetbc(&state, &bndl, &bndu, _state); - minqpsetlc(&state, &c, &ct, k, _state); - minqpoptimize(&state, _state); - ae_vector_set_length(&xend, 0, _state); - minqpresults(&state, &xend, &rep, _state); - - /* - * Check feasibility properties of the solution - * - * NOTE: we do not check termination type because some solvers (IPM) may return feasible X even with negative code - */ - if( xend.cnt!=n ) - { - ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminqpunit.ap:2588"); - continue; - } - for(i=0; i<=k-1; i++) - { - v = ae_v_dotproduct(&xend.ptr.p_double[0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - if( ct.ptr.p_int[i]==0 ) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-c.ptr.pp_double[i][n], _state),eps), __FILE__, __LINE__, "testminqpunit.ap:2595"); - } - if( ct.ptr.p_int[i]>0 ) - { - ae_set_error_flag(err, ae_fp_less(v,c.ptr.pp_double[i][n]-eps), __FILE__, __LINE__, "testminqpunit.ap:2597"); - } - if( ct.ptr.p_int[i]<0 ) - { - ae_set_error_flag(err, ae_fp_greater(v,c.ptr.pp_double[i][n]+eps), __FILE__, __LINE__, "testminqpunit.ap:2599"); - } - } - } - - /* - * General inequality constrained problem: - * * N*N SPD diagonal A with moderate condtion number - * * no boundary constraints - * * K=N inequality constraints C*x >= C*x0, where C is N*N well conditioned - * matrix, x0 is some random vector [-1,+1] - * * optimization problem has form 0.5*x'*A*x-b'*x, - * where b is random vector from [-1,+1] - * * using duality, we can obtain solution of QP problem as follows: - * a) intermediate problem min(0.5*y'*B*y + d'*y) s.t. y>=0 - * is solved, where B = C*inv(A)*C', d = -(C*inv(A)*b + C*x0) - * b) after we got dual solution ys, we calculate primal solution - * xs = inv(A)*(C'*ys-b) - */ - eps = 1.0E-3; - for(n=1; n<=6; n++) - { - - /* - * Generate problem - */ - ae_vector_set_length(&da, n, _state); - ae_matrix_set_length(&a, n, n, _state); - rmatrixrndcond(n, ae_pow(10.0, 2*ae_randomreal(_state), _state), &t2, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xstart, n, _state); - ae_matrix_set_length(&c, n, n+1, _state); - ae_vector_set_length(&ct, n, _state); - for(i=0; i<=n-1; i++) - { - da.ptr.p_double[i] = ae_exp(8*ae_randomreal(_state)-4, _state); - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - a.ptr.pp_double[i][i] = da.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - xstart.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=n-1; i++) - { - ae_v_move(&c.ptr.pp_double[i][0], 1, &t2.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - c.ptr.pp_double[i][n] = v; - ct.ptr.p_int[i] = 1; - } - - /* - * Solve primal problem, check feasibility - */ - minqpcreate(n, &state, _state); - testminqpunit_setrandomalgoconvexlc(&state, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetquadraticterm(&state, &a, ae_fp_greater(ae_randomreal(_state),0.5), _state); - minqpsetstartingpoint(&state, &xstart, _state); - minqpsetlc(&state, &c, &ct, n, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminqpunit.ap:2665"); - continue; - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&xend.ptr.p_double[0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - ae_set_error_flag(err, ae_fp_less(v,c.ptr.pp_double[i][n]-eps), __FILE__, __LINE__, "testminqpunit.ap:2671"); - } - - /* - * Generate dual problem: - * * A2 stores new quadratic term - * * B2 stores new linear term - * * BndL/BndU store boundary constraints - */ - ae_matrix_set_length(&t3, n, n, _state); - ae_matrix_set_length(&a2, n, n, _state); - rmatrixtranspose(n, n, &c, 0, 0, &t3, 0, 0, _state); - for(i=0; i<=n-1; i++) - { - v = 1/ae_sqrt(da.ptr.p_double[i], _state); - ae_v_muld(&t3.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v); - } - rmatrixsyrk(n, n, 1.0, &t3, 0, 0, 2, 0.0, &a2, 0, 0, ae_true, _state); - ae_vector_set_length(&tmp0, n, _state); - ae_v_move(&tmp0.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - tmp0.ptr.p_double[i] = tmp0.ptr.p_double[i]/da.ptr.p_double[i]; - } - ae_vector_set_length(&b2, n, _state); - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &tmp0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - b2.ptr.p_double[i] = -(v+c.ptr.pp_double[i][n]); - } - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - for(i=0; i<=n-1; i++) - { - bndl.ptr.p_double[i] = 0.0; - bndu.ptr.p_double[i] = _state->v_posinf; - } - minqpcreate(n, &state2, _state); - testminqpunit_setrandomalgoconvexlc(&state, _state); - minqpsetlinearterm(&state2, &b2, _state); - minqpsetquadraticterm(&state2, &a2, ae_true, _state); - minqpsetbc(&state2, &bndl, &bndu, _state); - minqpoptimize(&state2, _state); - minqpresults(&state2, &xend2, &rep2, _state); - if( rep2.terminationtype<=0 ) - { - ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminqpunit.ap:2726"); - continue; - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&c.ptr.pp_double[0][i], c.stride, &xend2.ptr.p_double[0], 1, ae_v_len(0,n-1)); - tmp0.ptr.p_double[i] = v-b.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - tmp0.ptr.p_double[i] = tmp0.ptr.p_double[i]/da.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(tmp0.ptr.p_double[i]-xend.ptr.p_double[i], _state),eps*ae_maxreal(ae_fabs(tmp0.ptr.p_double[i], _state), 1.0, _state)), __FILE__, __LINE__, "testminqpunit.ap:2739"); - } - } - - /* - * Boundary and linear equality/inequality constrained QP problem, - * test checks that different starting points yield same final point: - * * random N from [1..6], random K from [1..2*N] - * * N*N SPD A with moderate condtion number (up to 100) - * * boundary constraints 0<=x[i]<=1 - * * K<2*N linear inequality constraints Q*x <= Q*x0, where - * Q is random K*N matrix, x0 is some random vector from the - * inner area of the feasible hypercube (0.1<=x0[i]<=0.9) - * * optimization problem has form 0.5*x'*A*x+b*x, - * where b is some random vector with -5<=b[i]<=+5 - * * every component of the initial point XStart is random from [-2,+2] - * * we perform two starts from random different XStart and compare values - * of the target function (although final points may be slightly different, - * function values should match each other) - */ - eps = 1.0E-4; - for(pass=1; pass<=50; pass++) - { - - /* - * Generate problem: N, K, A, b, BndL, BndU, CMatrix, x0, x1, XStart. - */ - n = ae_randominteger(5, _state)+2; - k = ae_randominteger(2*n, _state)+1; - spdmatrixrndcond(n, ae_pow(10.0, 2*ae_randomreal(_state), _state), &a, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&b2, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xstart, n, _state); - ae_vector_set_length(&xstart2, n, _state); - ae_matrix_set_length(&c, k, n+1, _state); - ae_vector_set_length(&ct, k, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 0.1+0.8*ae_randomreal(_state); - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - bndl.ptr.p_double[i] = 0.0; - bndu.ptr.p_double[i] = 1.0; - xstart.ptr.p_double[i] = 4*ae_randomreal(_state)-2; - xstart2.ptr.p_double[i] = 4*ae_randomreal(_state)-2; - } - for(i=0; i<=k-1; i++) - { - - /* - * Generate I-th row of C - * Avoid excessive (more than N/2) equality constraints. - */ - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - c.ptr.pp_double[i][n] = v; - ct.ptr.p_int[i] = ae_randominteger(3, _state)-1; - if( ae_fp_greater_eq((double)(i),0.5*n)&&ct.ptr.p_int[i]==0 ) - { - ct.ptr.p_int[i] = 1; - } - if( ct.ptr.p_int[i]<0 ) - { - c.ptr.pp_double[i][n] = c.ptr.pp_double[i][n]+0.1; - } - if( ct.ptr.p_int[i]>0 ) - { - c.ptr.pp_double[i][n] = c.ptr.pp_double[i][n]-0.1; - } - } - - /* - * Solve with XStart - * - * NOTE: we do not check termination type because some solvers (IPM) may return feasible X even with negative code - */ - minqpcreate(n, &state, _state); - testminqpunit_setrandomalgoconvexlc(&state, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetquadraticterm(&state, &a, ae_fp_greater(ae_randomreal(_state),0.5), _state); - minqpsetstartingpoint(&state, &xstart, _state); - minqpsetbc(&state, &bndl, &bndu, _state); - minqpsetlc(&state, &c, &ct, k, _state); - minqpoptimize(&state, _state); - ae_vector_set_length(&xend, 0, _state); - minqpresults(&state, &xend, &rep, _state); - if( xend.cnt!=n||!isfinitevector(&xend, n, _state) ) - { - ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminqpunit.ap:2821"); - continue; - } - - /* - * Solve with XStart2 - */ - minqpsetstartingpoint(&state, &xstart2, _state); - minqpoptimize(&state, _state); - ae_vector_set_length(&xend2, 0, _state); - minqpresults(&state, &xend2, &rep, _state); - if( xend2.cnt!=n||!isfinitevector(&xend2, n, _state) ) - { - ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminqpunit.ap:2834"); - continue; - } - - /* - * Calculate function value and XEnd and XEnd2, compare solutions - */ - f0 = 0.0; - f1 = 0.0; - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - f0 = f0+0.5*xend.ptr.p_double[i]*a.ptr.pp_double[i][j]*xend.ptr.p_double[j]; - f1 = f1+0.5*xend2.ptr.p_double[i]*a.ptr.pp_double[i][j]*xend2.ptr.p_double[j]; - } - f0 = f0+xend.ptr.p_double[i]*b.ptr.p_double[i]; - f1 = f1+xend2.ptr.p_double[i]*b.ptr.p_double[i]; - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(f0-f1, _state),eps), __FILE__, __LINE__, "testminqpunit.ap:2853"); - } - - /* - * Convex/nonconvex optimization problem with excessive constraints: - * - * * N=2..5 - * * f = 0.5*x'*A*x+b'*x - * * b has normally distributed entries with scale 10^BScale - * * several kinds of A are tried: zero, well conditioned SPD, well conditioned indefinite, low rank SPD, low rank indefinite - * * box constraints: x[i] in [-1,+1] - * * 2^N "excessive" general linear constraints (v_k,x)<=(v_k,v_k)+v_shift, - * where v_k is one of 2^N vertices of feasible hypercube, v_shift is - * a shift parameter: - * * with zero v_shift such constraints are degenerate (each vertex has - * N box constraints and one "redundant" linear constraint) - * * with positive v_shift linear constraint is always inactive - * * with small (about machine epsilon) but negative v_shift, - * constraint is close to degenerate - but not exactly - * - * We check that constrained gradient is close to zero at solution. - * Box constraint is considered active if distance to boundary is less - * than TolConstr. - * - * NOTE: TolConstr must be large enough so it won't conflict with - * perturbation introduced by v_shift - */ - tolconstr = 1.0E-3; - for(n=2; n<=5; n++) - { - for(akind=0; akind<=4; akind++) - { - for(shiftkind=-5; shiftkind<=1; shiftkind++) - { - for(bscale=0; bscale>=-2; bscale--) - { - - /* - * Generate A, B and initial point - */ - ae_matrix_set_length(&a, n, n, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = ae_pow((double)(10), (double)(bscale), _state)*hqrndnormal(&rs, _state); - x.ptr.p_double[i] = hqrnduniformr(&rs, _state)-0.5; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - isnonconvex = ae_false; - if( akind==1 ) - { - - /* - * Dense well conditioned SPD - */ - spdmatrixrndcond(n, 50.0, &a, _state); - } - if( akind==2 ) - { - - /* - * Dense well conditioned indefinite - */ - smatrixrndcond(n, 50.0, &a, _state); - isnonconvex = ae_true; - } - if( akind==3 ) - { - - /* - * Low rank semidefinite - */ - ae_vector_set_length(&tmp, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - for(k=1; k<=ae_minint(3, n-1, _state); k++) - { - for(i=0; i<=n-1; i++) - { - tmp.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - v = ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j]; - } - } - } - } - if( akind==4 ) - { - - /* - * Low rank indefinite - */ - ae_vector_set_length(&tmp, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - for(k=1; k<=ae_minint(3, n-1, _state); k++) - { - for(i=0; i<=n-1; i++) - { - tmp.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - v = hqrndnormal(&rs, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j]; - } - } - } - isnonconvex = ae_true; - } - - /* - * Generate constraints - */ - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - for(i=0; i<=n-1; i++) - { - bl.ptr.p_double[i] = -1.0; - bu.ptr.p_double[i] = 1.0; - } - ccnt = ae_round(ae_pow((double)(2), (double)(n), _state), _state); - ae_matrix_set_length(&c, ccnt, n+1, _state); - ae_vector_set_length(&ct, ccnt, _state); - for(i=0; i<=ccnt-1; i++) - { - ct.ptr.p_int[i] = -1; - k = i; - c.ptr.pp_double[i][n] = ae_sign((double)(shiftkind), _state)*ae_pow((double)(10), ae_fabs((double)(shiftkind), _state), _state)*ae_machineepsilon; - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = (double)(2*(k%2)-1); - c.ptr.pp_double[i][n] = c.ptr.pp_double[i][n]+c.ptr.pp_double[i][j]*c.ptr.pp_double[i][j]; - k = k/2; - } - } - - /* - * Create and optimize - */ - minqpcreate(n, &state, _state); - minqpsetstartingpoint(&state, &x, _state); - if( isnonconvex ) - { - testminqpunit_setrandomalgononconvexlc(&state, _state); - } - else - { - testminqpunit_setrandomalgoconvexlc(&state, _state); - } - minqpsetbc(&state, &bl, &bu, _state); - minqpsetlc(&state, &c, &ct, ccnt, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetquadraticterm(&state, &a, ae_fp_greater(ae_randomreal(_state),0.5), _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xs0, &rep, _state); - ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:3000"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - - /* - * Evaluate gradient at solution and test - */ - vv = 0.0; - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xs0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = v+b.ptr.p_double[i]; - if( ae_fp_less_eq(xs0.ptr.p_double[i],bl.ptr.p_double[i]+tolconstr)&&ae_fp_greater(v,(double)(0)) ) - { - v = 0.0; - } - if( ae_fp_greater_eq(xs0.ptr.p_double[i],bu.ptr.p_double[i]-tolconstr)&&ae_fp_less(v,(double)(0)) ) - { - v = 0.0; - } - vv = vv+ae_sqr(v, _state); - } - vv = ae_sqrt(vv, _state); - ae_set_error_flag(err, ae_fp_greater(vv,1.0E-3), __FILE__, __LINE__, "testminqpunit.ap:3024"); - } - } - } - } - - /* - * Convex/nonconvex optimization problem with combination of - * box and linear constraints: - * - * * N=2..8 - * * f = 0.5*x'*A*x+b'*x - * * b has normally distributed entries with scale 10^BScale - * * several kinds of A are tried: zero, well conditioned SPD, - * well conditioned indefinite, low rank semidefinite, low rank indefinite - * * box constraints: x[i] in [-1,+1] - * * initial point x0 = [0 0 ... 0 0] - * * CCnt=min(3,N-1) general linear constraints of form (c,x)=0. - * random mix of equality/inequality constraints is tried. - * x0 is guaranteed to be feasible. - * - * We check that constrained gradient is close to zero at solution. - * Inequality constraint is considered active if distance to boundary - * is less than TolConstr. We use nonnegative least squares solver - * in order to compute constrained gradient. - */ - tolconstr = 1.0E-3; - for(n=2; n<=8; n++) - { - for(akind=0; akind<=4; akind++) - { - for(bscale=0; bscale>=-2; bscale--) - { - - /* - * Generate A, B and initial point - */ - ae_matrix_set_length(&a, n, n, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = ae_pow((double)(10), (double)(bscale), _state)*hqrndnormal(&rs, _state); - x.ptr.p_double[i] = 0.0; - } - isnonconvex = ae_false; - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - if( akind==1 ) - { - - /* - * Dense well conditioned SPD - */ - spdmatrixrndcond(n, 50.0, &a, _state); - } - if( akind==2 ) - { - - /* - * Dense well conditioned indefinite - */ - smatrixrndcond(n, 50.0, &a, _state); - isnonconvex = ae_true; - } - if( akind==3 ) - { - - /* - * Low rank - */ - ae_vector_set_length(&tmp, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - for(k=1; k<=ae_minint(3, n-1, _state); k++) - { - for(i=0; i<=n-1; i++) - { - tmp.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - v = ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j]; - } - } - } - } - if( akind==4 ) - { - - /* - * Low rank indefinite - */ - ae_vector_set_length(&tmp, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - for(k=1; k<=ae_minint(3, n-1, _state); k++) - { - for(i=0; i<=n-1; i++) - { - tmp.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - v = hqrndnormal(&rs, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j]; - } - } - } - isnonconvex = ae_true; - } - - /* - * Generate constraints - */ - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - for(i=0; i<=n-1; i++) - { - bl.ptr.p_double[i] = -1.0; - bu.ptr.p_double[i] = 1.0; - } - ccnt = ae_minint(3, n-1, _state); - ae_matrix_set_length(&c, ccnt, n+1, _state); - ae_vector_set_length(&ct, ccnt, _state); - for(i=0; i<=ccnt-1; i++) - { - ct.ptr.p_int[i] = hqrnduniformi(&rs, 3, _state)-1; - c.ptr.pp_double[i][n] = 0.0; - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5; - } - } - - /* - * Create and optimize - */ - minqpcreate(n, &state, _state); - minqpsetstartingpoint(&state, &x, _state); - if( isnonconvex ) - { - testminqpunit_setrandomalgononconvexlc(&state, _state); - } - else - { - testminqpunit_setrandomalgoconvexlc(&state, _state); - } - minqpsetbc(&state, &bl, &bu, _state); - minqpsetlc(&state, &c, &ct, ccnt, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetquadraticterm(&state, &a, ae_fp_greater(ae_randomreal(_state),0.5), _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xs0, &rep, _state); - ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:3159"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - - /* - * 1. evaluate unconstrained gradient at solution - * - * 2. calculate constrained gradient (NNLS solver is used - * to evaluate gradient subject to active constraints). - * In order to do this we form CE matrix, matrix of active - * constraints (columns store constraint vectors). Then - * we try to approximate gradient vector by columns of CE, - * subject to non-negativity restriction placed on variables - * corresponding to inequality constraints. - * - * Residual from such regression is a constrained gradient vector. - */ - ae_vector_set_length(&g, n, _state); - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xs0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - g.ptr.p_double[i] = v+b.ptr.p_double[i]; - } - ae_matrix_set_length(&ce, n, n+ccnt, _state); - ae_vector_set_length(&nonnegative, n+ccnt, _state); - k = 0; - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(err, ae_fp_less(xs0.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:3187"); - ae_set_error_flag(err, ae_fp_greater(xs0.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:3188"); - if( ae_fp_less_eq(xs0.ptr.p_double[i],bl.ptr.p_double[i]+tolconstr) ) - { - for(j=0; j<=n-1; j++) - { - ce.ptr.pp_double[j][k] = 0.0; - } - ce.ptr.pp_double[i][k] = 1.0; - nonnegative.ptr.p_bool[k] = ae_true; - inc(&k, _state); - continue; - } - if( ae_fp_greater_eq(xs0.ptr.p_double[i],bu.ptr.p_double[i]-tolconstr) ) - { - for(j=0; j<=n-1; j++) - { - ce.ptr.pp_double[j][k] = 0.0; - } - ce.ptr.pp_double[i][k] = -1.0; - nonnegative.ptr.p_bool[k] = ae_true; - inc(&k, _state); - continue; - } - } - for(i=0; i<=ccnt-1; i++) - { - v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &xs0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = v-c.ptr.pp_double[i][n]; - ae_set_error_flag(err, ct.ptr.p_int[i]==0&&ae_fp_greater(ae_fabs(v, _state),tolconstr), __FILE__, __LINE__, "testminqpunit.ap:3212"); - ae_set_error_flag(err, ct.ptr.p_int[i]>0&&ae_fp_less(v,-tolconstr), __FILE__, __LINE__, "testminqpunit.ap:3213"); - ae_set_error_flag(err, ct.ptr.p_int[i]<0&&ae_fp_greater(v,tolconstr), __FILE__, __LINE__, "testminqpunit.ap:3214"); - if( ct.ptr.p_int[i]==0 ) - { - for(j=0; j<=n-1; j++) - { - ce.ptr.pp_double[j][k] = c.ptr.pp_double[i][j]; - } - nonnegative.ptr.p_bool[k] = ae_false; - inc(&k, _state); - continue; - } - if( (ct.ptr.p_int[i]>0&&ae_fp_less_eq(v,tolconstr))||(ct.ptr.p_int[i]<0&&ae_fp_greater_eq(v,-tolconstr)) ) - { - for(j=0; j<=n-1; j++) - { - ce.ptr.pp_double[j][k] = ae_sign((double)(ct.ptr.p_int[i]), _state)*c.ptr.pp_double[i][j]; - } - nonnegative.ptr.p_bool[k] = ae_true; - inc(&k, _state); - continue; - } - } - snnlsinit(0, 0, 0, &nnls, _state); - snnlssetproblem(&nnls, &ce, &g, 0, k, n, _state); - for(i=0; i<=k-1; i++) - { - if( !nonnegative.ptr.p_bool[i] ) - { - snnlsdropnnc(&nnls, i, _state); - } - } - snnlssolve(&nnls, &tmp, _state); - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - g.ptr.p_double[j] = g.ptr.p_double[j]-tmp.ptr.p_double[i]*ce.ptr.pp_double[j][i]; - } - } - vv = ae_v_dotproduct(&g.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - vv = ae_sqrt(vv, _state); - if( akind==3||akind==4 ) - { - ae_set_error_flag(err, ae_fp_greater(vv,1.0E-2), __FILE__, __LINE__, "testminqpunit.ap:3244"); - } - else - { - ae_set_error_flag(err, ae_fp_greater(vv,1.0E-3), __FILE__, __LINE__, "testminqpunit.ap:3246"); - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests linearly constrained QP solvers. - -On failure sets Err to True; on success leaves it unchanged. -*************************************************************************/ -static void testminqpunit_generallcqptest(ae_bool* errorflag, - ae_state *_state) -{ - ae_frame _frame_block; - hqrndstate rs; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t solvertype; - double v; - double vv; - ae_bool bflag; - ae_int_t pass; - ae_matrix rawa; - ae_matrix a; - sparsematrix sa; - ae_vector b; - ae_vector b2; - ae_vector xs; - ae_vector x0; - ae_vector x1; - ae_vector x2; - ae_vector xf; - ae_vector xorigin; - ae_vector s; - ae_vector da; - ae_vector xstart; - ae_vector g; - ae_vector gtrial; - ae_vector gs; - ae_vector tmp; - ae_vector tmp0; - ae_vector tmp1; - ae_vector tmp2; - ae_vector lagrange; - ae_vector bndl; - ae_vector bndu; - ae_matrix rawc; - ae_vector rawcl; - ae_vector rawcu; - ae_vector rawct; - ae_int_t rawccnt; - ae_matrix densec; - ae_vector densect; - ae_int_t denseccnt; - sparsematrix sparsec; - ae_vector sparsect; - ae_int_t sparseccnt; - ae_matrix activeset; - ae_vector activeeq; - ae_int_t nactive; - snnlssolver nnls; - double constraintsrcond; - ae_vector svdw; - ae_matrix svdu; - ae_matrix svdvt; - minqpstate state; - minqpreport rep; - minqpstate state2; - minqpreport rep2; - double f0; - double f1; - double xtol; - double ftol; - double gtol; - double tolconstr; - ae_int_t bscale; - ae_int_t akind; - ae_matrix ce; - ae_matrix q; - ae_matrix t2; - ae_matrix t3; - ae_matrix a2; - ae_vector lagbc; - ae_vector laglc; - ae_vector nonnegative; - double mx; - ae_int_t shiftkind; - ae_int_t nnz; - ae_bool issemidefinite; - ae_bool skiptest; - double bleicepsx; - double aulepsx; - double aulrho; - ae_int_t aulits; - double ipmeps; - ae_matrix kkt; - ae_vector kktright; - double minushuge; - double plushuge; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - memset(&rawa, 0, sizeof(rawa)); - memset(&a, 0, sizeof(a)); - memset(&sa, 0, sizeof(sa)); - memset(&b, 0, sizeof(b)); - memset(&b2, 0, sizeof(b2)); - memset(&xs, 0, sizeof(xs)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&x2, 0, sizeof(x2)); - memset(&xf, 0, sizeof(xf)); - memset(&xorigin, 0, sizeof(xorigin)); - memset(&s, 0, sizeof(s)); - memset(&da, 0, sizeof(da)); - memset(&xstart, 0, sizeof(xstart)); - memset(&g, 0, sizeof(g)); - memset(>rial, 0, sizeof(gtrial)); - memset(&gs, 0, sizeof(gs)); - memset(&tmp, 0, sizeof(tmp)); - memset(&tmp0, 0, sizeof(tmp0)); - memset(&tmp1, 0, sizeof(tmp1)); - memset(&tmp2, 0, sizeof(tmp2)); - memset(&lagrange, 0, sizeof(lagrange)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&rawc, 0, sizeof(rawc)); - memset(&rawcl, 0, sizeof(rawcl)); - memset(&rawcu, 0, sizeof(rawcu)); - memset(&rawct, 0, sizeof(rawct)); - memset(&densec, 0, sizeof(densec)); - memset(&densect, 0, sizeof(densect)); - memset(&sparsec, 0, sizeof(sparsec)); - memset(&sparsect, 0, sizeof(sparsect)); - memset(&activeset, 0, sizeof(activeset)); - memset(&activeeq, 0, sizeof(activeeq)); - memset(&nnls, 0, sizeof(nnls)); - memset(&svdw, 0, sizeof(svdw)); - memset(&svdu, 0, sizeof(svdu)); - memset(&svdvt, 0, sizeof(svdvt)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&state2, 0, sizeof(state2)); - memset(&rep2, 0, sizeof(rep2)); - memset(&ce, 0, sizeof(ce)); - memset(&q, 0, sizeof(q)); - memset(&t2, 0, sizeof(t2)); - memset(&t3, 0, sizeof(t3)); - memset(&a2, 0, sizeof(a2)); - memset(&lagbc, 0, sizeof(lagbc)); - memset(&laglc, 0, sizeof(laglc)); - memset(&nonnegative, 0, sizeof(nonnegative)); - memset(&kkt, 0, sizeof(kkt)); - memset(&kktright, 0, sizeof(kktright)); - _hqrndstate_init(&rs, _state, ae_true); - ae_matrix_init(&rawa, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&sa, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xs, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xorigin, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&da, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xstart, 0, DT_REAL, _state, ae_true); - ae_vector_init(&g, 0, DT_REAL, _state, ae_true); - ae_vector_init(>rial, 0, DT_REAL, _state, ae_true); - ae_vector_init(&gs, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&lagrange, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&rawc, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rawcl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rawcu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rawct, 0, DT_INT, _state, ae_true); - ae_matrix_init(&densec, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&densect, 0, DT_INT, _state, ae_true); - _sparsematrix_init(&sparsec, _state, ae_true); - ae_vector_init(&sparsect, 0, DT_INT, _state, ae_true); - ae_matrix_init(&activeset, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&activeeq, 0, DT_BOOL, _state, ae_true); - _snnlssolver_init(&nnls, _state, ae_true); - ae_vector_init(&svdw, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&svdu, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&svdvt, 0, 0, DT_REAL, _state, ae_true); - _minqpstate_init(&state, _state, ae_true); - _minqpreport_init(&rep, _state, ae_true); - _minqpstate_init(&state2, _state, ae_true); - _minqpreport_init(&rep2, _state, ae_true); - ae_matrix_init(&ce, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&t2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&t3, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a2, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&lagbc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&laglc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&nonnegative, 0, DT_BOOL, _state, ae_true); - ae_matrix_init(&kkt, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&kktright, 0, DT_REAL, _state, ae_true); - - hqrndrandomize(&rs, _state); - bleicepsx = 1.0E-9; - ipmeps = 1.0E-12; - aulepsx = 1.0E-12; - aulrho = 1.0E3; - aulits = 15; - - /* - * SMALL-SCALE TESTS: many tests for small N's - */ - for(solvertype=0; solvertype<=3; solvertype++) - { - - /* - * Test random linearly constrained convex QP problem with known answer: - * * generate random A and b - * * generate random solution XS - * * calculate unconstrained gradient GS at XS - * * generate random box/linear constraints C, with some of them being - * active at XS, and some being inactive. Calculate residual gradient - * GP after projection of GS onto active set, add one more constraint - * equal to +-(GP-GS). - * - * We test here BLEIC and Dense-AUL solvers, with A being passed - * in dense or sparse format, and linear constraints C being passed - * as dense, sparse or mixed ones. - */ - for(n=1; n<=10; n++) - { - - /* - * Generate random A, b and xs - */ - spdmatrixrndcond(n, ae_pow(10.0, 2*ae_randomreal(_state), _state), &rawa, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&xs, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - xs.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - - /* - * Generate well conditioned "raw" constraints: - * * generate random box and CCnt-1 linear constraints - * * determine active set, calculate its condition number - * * repeat until condition number is good enough - * (better than 1E2; larger values sometimes result in - * spurious failures) - */ - ae_vector_set_length(&gs, n, _state); - ae_vector_set_length(&tmp, n, _state); - rmatrixmv(n, n, &rawa, 0, 0, 0, &xs, 0, &gs, 0, _state); - for(i=0; i<=n-1; i++) - { - gs.ptr.p_double[i] = gs.ptr.p_double[i]+b.ptr.p_double[i]; - } - rawccnt = 1+hqrnduniformi(&rs, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_matrix_set_length(&activeset, n, n+rawccnt, _state); - ae_vector_set_length(&activeeq, n+rawccnt, _state); - ae_matrix_set_length(&rawc, rawccnt, n+1, _state); - ae_vector_set_length(&rawct, rawccnt, _state); - do - { - nactive = 0; - for(i=0; i<=n-1; i++) - { - bndl.ptr.p_double[i] = xs.ptr.p_double[i]-1-hqrnduniformr(&rs, _state); - bndu.ptr.p_double[i] = xs.ptr.p_double[i]+1+hqrnduniformr(&rs, _state); - if( ae_fp_less(hqrnduniformr(&rs, _state),0.66) ) - { - - /* - * I-th box constraint is inactive - */ - continue; - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),0.50) ) - { - - /* - * I-th box constraint is equality one - */ - bndl.ptr.p_double[i] = xs.ptr.p_double[i]; - bndu.ptr.p_double[i] = xs.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - activeset.ptr.pp_double[j][nactive] = (double)(0); - } - activeset.ptr.pp_double[i][nactive] = (double)(1); - activeeq.ptr.p_bool[nactive] = ae_true; - nactive = nactive+1; - } - else - { - - /* - * I-th box constraint is inequality one - */ - for(j=0; j<=n-1; j++) - { - activeset.ptr.pp_double[j][nactive] = (double)(0); - } - if( ae_fp_greater(gs.ptr.p_double[i],(double)(0)) ) - { - bndl.ptr.p_double[i] = xs.ptr.p_double[i]; - activeset.ptr.pp_double[i][nactive] = (double)(-1); - if( ae_fp_greater(hqrnduniformr(&rs, _state),0.50) ) - { - bndu.ptr.p_double[i] = _state->v_posinf; - } - } - else - { - bndu.ptr.p_double[i] = xs.ptr.p_double[i]; - activeset.ptr.pp_double[i][nactive] = (double)(1); - if( ae_fp_greater(hqrnduniformr(&rs, _state),0.50) ) - { - bndl.ptr.p_double[i] = _state->v_neginf; - } - } - activeeq.ptr.p_bool[nactive] = ae_false; - nactive = nactive+1; - } - } - for(i=0; i<=rawccnt-2; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_less(hqrnduniformr(&rs, _state),0.50) ) - { - rawc.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - else - { - rawc.ptr.pp_double[i][j] = (double)(0); - } - } - rawc.ptr.pp_double[i][hqrnduniformi(&rs, n, _state)] = hqrndnormal(&rs, _state); - rawc.ptr.pp_double[i][n] = (double)(0); - for(j=0; j<=n-1; j++) - { - rawc.ptr.pp_double[i][n] = rawc.ptr.pp_double[i][n]+rawc.ptr.pp_double[i][j]*xs.ptr.p_double[j]; - } - rawct.ptr.p_int[i] = -1; - if( ae_fp_less(hqrnduniformr(&rs, _state),0.66) ) - { - - /* - * I-th box constraint is inactive - */ - rawc.ptr.pp_double[i][n] = rawc.ptr.pp_double[i][n]+(1+hqrnduniformr(&rs, _state)); - if( ae_fp_greater(hqrnduniformr(&rs, _state),0.50) ) - { - ae_v_muld(&rawc.ptr.pp_double[i][0], 1, ae_v_len(0,n), -1); - rawct.ptr.p_int[i] = -rawct.ptr.p_int[i]; - } - continue; - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),0.50) ) - { - - /* - * I-th box constraint is equality one - */ - rawct.ptr.p_int[i] = 0; - for(j=0; j<=n-1; j++) - { - activeset.ptr.pp_double[j][nactive] = rawc.ptr.pp_double[i][j]; - } - activeeq.ptr.p_bool[nactive] = ae_true; - nactive = nactive+1; - } - else - { - - /* - * I-th box constraint is inequality one - */ - v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &gs.ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( ae_fp_greater(v,(double)(0)) ) - { - rawct.ptr.p_int[i] = 1; - for(j=0; j<=n-1; j++) - { - activeset.ptr.pp_double[j][nactive] = -rawc.ptr.pp_double[i][j]; - } - } - else - { - rawct.ptr.p_int[i] = -1; - for(j=0; j<=n-1; j++) - { - activeset.ptr.pp_double[j][nactive] = rawc.ptr.pp_double[i][j]; - } - } - activeeq.ptr.p_bool[nactive] = ae_false; - nactive = nactive+1; - } - } - ae_v_moveneg(&tmp.ptr.p_double[0], 1, &gs.ptr.p_double[0], 1, ae_v_len(0,n-1)); - snnlsinit(0, 0, 0, &nnls, _state); - snnlssetproblem(&nnls, &activeset, &tmp, 0, nactive, n, _state); - for(i=0; i<=nactive-1; i++) - { - if( activeeq.ptr.p_bool[i] ) - { - snnlsdropnnc(&nnls, i, _state); - } - } - snnlssolve(&nnls, &lagrange, _state); - ae_v_moveneg(&tmp.ptr.p_double[0], 1, &gs.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=nactive-1; i++) - { - v = lagrange.ptr.p_double[i]; - ae_v_subd(&tmp.ptr.p_double[0], 1, &activeset.ptr.pp_double[0][i], activeset.stride, ae_v_len(0,n-1), v); - } - ae_v_move(&rawc.ptr.pp_double[rawccnt-1][0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = ae_v_dotproduct(&tmp.ptr.p_double[0], 1, &xs.ptr.p_double[0], 1, ae_v_len(0,n-1)); - rawc.ptr.pp_double[rawccnt-1][n] = v; - rawct.ptr.p_int[rawccnt-1] = -1; - - /* - * Calculate reciprocal condition number - */ - if( nactive>0 ) - { - bflag = rmatrixsvd(&activeset, n, nactive, 0, 0, 0, &svdw, &svdu, &svdvt, _state); - ae_assert(bflag, "MinQPTest: integrity failure", _state); - constraintsrcond = svdw.ptr.p_double[ae_minint(nactive, n, _state)-1]/svdw.ptr.p_double[0]; - } - else - { - constraintsrcond = (double)(1); - } - - /* - * Check RCond - */ - } - while(!(ae_fp_greater_eq(constraintsrcond,0.01)&&nactive<=n-1)); - - /* - * Create optimizer, solve - */ - minqpcreate(n, &state, _state); - if( solvertype==0 ) - { - minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state); - } - else - { - if( solvertype==1 ) - { - minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state); - } - else - { - if( solvertype==2 ) - { - minqpsetalgodenseipm(&state, ipmeps, _state); - } - else - { - if( solvertype==3 ) - { - minqpsetalgosparseipm(&state, ipmeps, _state); - } - else - { - ae_assert(ae_false, "unexpected solver type", _state); - } - } - } - } - minqpsetlinearterm(&state, &b, _state); - testminqpunit_randomlyselectconvertandsetquadraticterm(&rawa, n, &state, &rs, _state); - minqpsetbc(&state, &bndl, &bndu, _state); - testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, rawccnt, n, &state, &rs, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - - /* - * Test - * - * Because constrained problems are often ill-conditioned, - * we do NOT compare X1 with XS directly. Instead, we: - * a) compare function values at X1 and XS with good precision - * b) check constraint violation with good precision - * c) perform comparison for |X1-XS| with LOW precision - */ - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:3569"); - ae_frame_leave(_state); - return; - } - f0 = (double)(0); - f1 = (double)(0); - for(i=0; i<=n-1; i++) - { - f0 = f0+b.ptr.p_double[i]*xs.ptr.p_double[i]; - f1 = f1+b.ptr.p_double[i]*x1.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - f0 = f0+0.5*xs.ptr.p_double[i]*rawa.ptr.pp_double[i][j]*xs.ptr.p_double[j]; - f1 = f1+0.5*x1.ptr.p_double[i]*rawa.ptr.pp_double[i][j]*x1.ptr.p_double[j]; - } - } - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(f0-f1, _state),1.0E-3), __FILE__, __LINE__, "testminqpunit.ap:3584"); - } - - /* - * Inequality constrained convex problem: - * * N*N diagonal A - * * one inequality constraint q'*x>=0, where q is random unit vector - * * optimization problem has form 0.5*x'*A*x-(xs*A)*x, - * where xs is some random vector - * * either: - * a) xs is feasible => we must stop at xs - * b) xs is infeasible => we must stop at the boundary q'*x=0 and - * projection of gradient onto q*x=0 must be zero - * - * NOTE: we make several passes because some specific kind of errors is rarely - * caught by this test, so we need several repetitions. - */ - xtol = 1.0E-4; - gtol = 1.0E-4; - for(n=2; n<=6; n++) - { - for(pass=0; pass<=4; pass++) - { - - /* - * Generate problem: A, b, CMatrix, x0, XStart - */ - spdmatrixrndcond(n, ae_pow(10.0, 3*ae_randomreal(_state), _state), &a, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&xs, n, _state); - ae_vector_set_length(&xstart, n, _state); - ae_matrix_set_length(&rawc, 1, n+1, _state); - ae_vector_set_length(&rawct, 1, _state); - for(i=0; i<=n-1; i++) - { - xs.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - xstart.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - do - { - v = (double)(0); - for(i=0; i<=n-1; i++) - { - rawc.ptr.pp_double[0][i] = 2*ae_randomreal(_state)-1; - v = v+ae_sqr(rawc.ptr.pp_double[0][i], _state); - } - v = ae_sqrt(v, _state); - } - while(ae_fp_eq(v,(double)(0))); - for(i=0; i<=n-1; i++) - { - rawc.ptr.pp_double[0][i] = rawc.ptr.pp_double[0][i]/v; - } - rawc.ptr.pp_double[0][n] = (double)(0); - rawct.ptr.p_int[0] = 1; - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xs.ptr.p_double[0], 1, ae_v_len(0,n-1)); - b.ptr.p_double[i] = -v; - } - - /* - * Create optimizer, solve - */ - minqpcreate(n, &state, _state); - if( solvertype==0 ) - { - minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state); - } - else - { - if( solvertype==1 ) - { - minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state); - } - else - { - if( solvertype==2 ) - { - minqpsetalgodenseipm(&state, ipmeps, _state); - } - else - { - if( solvertype==3 ) - { - minqpsetalgosparseipm(&state, ipmeps, _state); - } - else - { - ae_assert(ae_false, "unexpected solver type", _state); - } - } - } - } - minqpsetlinearterm(&state, &b, _state); - testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state, &rs, _state); - minqpsetstartingpoint(&state, &xstart, _state); - testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, 1, n, &state, &rs, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - - /* - * Test - */ - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:3667"); - ae_frame_leave(_state); - return; - } - v = ae_v_dotproduct(&xs.ptr.p_double[0], 1, &rawc.ptr.pp_double[0][0], 1, ae_v_len(0,n-1)); - if( ae_fp_greater_eq(v,(double)(0)) ) - { - - /* - * XS is feasible - */ - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-xs.ptr.p_double[i], _state),xtol), __FILE__, __LINE__, "testminqpunit.ap:3677"); - } - } - else - { - - /* - * XS is infeasible: - * * X1 must be approximately feasible - * * gradient projection onto c'*x=0 must be zero - */ - v = ae_v_dotproduct(&x1.ptr.p_double[0], 1, &rawc.ptr.pp_double[0][0], 1, ae_v_len(0,n-1)); - ae_set_error_flag(errorflag, ae_fp_less(v,-xtol), __FILE__, __LINE__, "testminqpunit.ap:3687"); - ae_vector_set_length(&g, n, _state); - ae_v_move(&g.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - g.ptr.p_double[i] = g.ptr.p_double[i]+v; - } - v = ae_v_dotproduct(&g.ptr.p_double[0], 1, &rawc.ptr.pp_double[0][0], 1, ae_v_len(0,n-1)); - ae_v_subd(&g.ptr.p_double[0], 1, &rawc.ptr.pp_double[0][0], 1, ae_v_len(0,n-1), v); - v = ae_v_dotproduct(&g.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_set_error_flag(errorflag, ae_fp_greater(ae_sqrt(v, _state),gtol), __FILE__, __LINE__, "testminqpunit.ap:3698"); - } - } - } - - /* - * Box constraints vs linear ones: - * * N*N SPD A - * * optimization problem has form 0.5*x'*A*x-(x1*A)*x, - * where x1 is some random vector from [-1,+1] - * * K=2*N constraints of the form ai<=x[i] or x[i]<=b[i], - * with ai in [-1.0,-0.1], bi in [+0.1,+1.0] - * * initial point xstart is from [-1,+2] - * * we solve two related QP problems: - * a) one with constraints posed as boundary ones - * b) another one with same constraints posed as general linear ones - * both problems must have same solution. - * Here we test that boundary constrained and linear inequality constrained - * solvers give same results. - */ - xtol = 1.0E-5; - for(n=1; n<=6; n++) - { - - /* - * Generate problem: A, b, x0, XStart, C, CT - */ - spdmatrixrndcond(n, ae_pow(10.0, 3*ae_randomreal(_state), _state), &a, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x1, n, _state); - ae_vector_set_length(&xstart, n, _state); - ae_matrix_set_length(&rawc, 2*n, n+1, _state); - ae_vector_set_length(&rawct, 2*n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - for(i=0; i<=n-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - xstart.ptr.p_double[i] = 3*ae_randomreal(_state)-1; - bndl.ptr.p_double[i] = -(0.1+0.9*ae_randomreal(_state)); - bndu.ptr.p_double[i] = 0.1+0.9*ae_randomreal(_state); - for(j=0; j<=n-1; j++) - { - rawc.ptr.pp_double[2*i+0][j] = (double)(0); - rawc.ptr.pp_double[2*i+1][j] = (double)(0); - } - rawc.ptr.pp_double[2*i+0][i] = (double)(1); - rawc.ptr.pp_double[2*i+0][n] = bndl.ptr.p_double[i]; - rawct.ptr.p_int[2*i+0] = 1; - rawc.ptr.pp_double[2*i+1][i] = (double)(1); - rawc.ptr.pp_double[2*i+1][n] = bndu.ptr.p_double[i]; - rawct.ptr.p_int[2*i+1] = -1; - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - b.ptr.p_double[i] = -v; - } - - /* - * Solve linear inequality constrained problem - */ - minqpcreate(n, &state, _state); - if( solvertype==0 ) - { - minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state); - } - else - { - if( solvertype==1 ) - { - minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state); - } - else - { - if( solvertype==2 ) - { - minqpsetalgodenseipm(&state, ipmeps, _state); - } - else - { - if( solvertype==3 ) - { - minqpsetalgosparseipm(&state, ipmeps, _state); - } - else - { - ae_assert(ae_false, "unexpected solver type", _state); - } - } - } - } - minqpsetlinearterm(&state, &b, _state); - testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state, &rs, _state); - minqpsetstartingpoint(&state, &xstart, _state); - testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, 2*n, n, &state, &rs, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - - /* - * Solve boundary constrained problem - */ - minqpcreate(n, &state2, _state); - if( solvertype==0 ) - { - minqpsetalgobleic(&state2, 0.0, 0.0, bleicepsx, 0, _state); - } - else - { - if( solvertype==1 ) - { - minqpsetalgodenseaul(&state2, aulepsx, aulrho, aulits, _state); - } - else - { - if( solvertype==2 ) - { - minqpsetalgodenseipm(&state2, ipmeps, _state); - } - else - { - if( solvertype==3 ) - { - minqpsetalgosparseipm(&state2, ipmeps, _state); - } - else - { - ae_assert(ae_false, "unexpected solver type", _state); - } - } - } - } - minqpsetlinearterm(&state2, &b, _state); - testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state2, &rs, _state); - minqpsetstartingpoint(&state2, &xstart, _state); - minqpsetbc(&state2, &bndl, &bndu, _state); - minqpoptimize(&state2, _state); - minqpresults(&state2, &x2, &rep2, _state); - - /* - * Calculate gradient, check projection - */ - if( rep.terminationtype<=0||rep2.terminationtype<=0 ) - { - ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:3804"); - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]-xtol), __FILE__, __LINE__, "testminqpunit.ap:3809"); - ae_set_error_flag(errorflag, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]+xtol), __FILE__, __LINE__, "testminqpunit.ap:3810"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-x2.ptr.p_double[i], _state),xtol), __FILE__, __LINE__, "testminqpunit.ap:3811"); - } - } - - /* - * Convex/nonconvex optimization problem with combination of - * box and linear constraints: - * - * * N=2..8 - * * f = 0.5*x'*A*x+b'*x - * * b has normally distributed entries with scale 10^BScale - * * several kinds of A are tried: zero, well conditioned SPD, - * well conditioned indefinite, low rank - * * box constraints: x[i] in [-1,+1] - * * initial point x0 = [0 0 ... 0 0] - * * CCnt=min(3,N-1) general linear constraints of form (c,x)=0. - * random mix of equality/inequality constraints is tried, moderate - * condition number is guaranteed, x0 is guaranteed to be feasible. - * - * We check that constrained gradient is close to zero at solution. - * Inequality constraint is considered active if distance to boundary - * is less than TolConstr. We use nonnegative least squares solver - * in order to compute constrained gradient. - */ - tolconstr = (double)(-99999); - for(n=2; n<=8; n++) - { - for(akind=0; akind<=4; akind++) - { - for(bscale=1; bscale>=-1; bscale--) - { - - /* - * Dense-AUL solver has lower precision on rank-deficient - * problems, so we skip AKind=3. - * - * IPM solvers can not work with indefinite problems. - */ - if( solvertype==1&&akind==3 ) - { - continue; - } - if( (solvertype==2||solvertype==3)&&(akind==2||akind==4) ) - { - continue; - } - - /* - * Set up tolerances - */ - if( solvertype==0 ) - { - tolconstr = 1.0E-8; - } - else - { - if( (solvertype==1||solvertype==2)||solvertype==3 ) - { - tolconstr = 1.0E-3; - if( akind==3 ) - { - tolconstr = tolconstr*5; - } - } - else - { - ae_assert(ae_false, "unexpected solver type", _state); - } - } - gtol = 1.0E-4; - - /* - * Generate A, B and initial point - */ - ae_matrix_set_length(&a, n, n, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&xstart, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = ae_pow((double)(10), (double)(bscale), _state)*hqrndnormal(&rs, _state); - xstart.ptr.p_double[i] = 0.0; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - if( akind==1 ) - { - - /* - * Dense well conditioned SPD - */ - spdmatrixrndcond(n, 50.0, &a, _state); - } - if( akind==2 ) - { - - /* - * Dense well conditioned indefinite - */ - smatrixrndcond(n, 50.0, &a, _state); - } - if( akind==3 ) - { - - /* - * Low rank semidefinite - */ - ae_vector_set_length(&tmp, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - for(k=1; k<=ae_minint(3, n-1, _state); k++) - { - for(i=0; i<=n-1; i++) - { - tmp.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - v = ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j]; - } - } - } - } - if( akind==4 ) - { - - /* - * Low rank indefinite - */ - ae_vector_set_length(&tmp, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - for(k=1; k<=ae_minint(3, n-1, _state); k++) - { - for(i=0; i<=n-1; i++) - { - tmp.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - v = hqrndnormal(&rs, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j]; - } - } - } - } - - /* - * Generate constraints - */ - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - for(i=0; i<=n-1; i++) - { - bndl.ptr.p_double[i] = -1.0; - bndu.ptr.p_double[i] = 1.0; - } - rawccnt = ae_minint(3, n-1, _state); - ae_matrix_set_length(&rawc, rawccnt, n+1, _state); - ae_vector_set_length(&rawct, rawccnt, _state); - do - { - for(i=0; i<=rawccnt-1; i++) - { - rawct.ptr.p_int[i] = hqrnduniformi(&rs, 3, _state)-1; - rawc.ptr.pp_double[i][n] = 0.0; - for(j=0; j<=n-1; j++) - { - rawc.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5; - } - } - } - while(ae_fp_less_eq(testminqpunit_getconstraintrcond(&rawc, rawccnt, n, _state),0.01)); - - /* - * Create and optimize - */ - minqpcreate(n, &state, _state); - minqpsetstartingpoint(&state, &xstart, _state); - if( solvertype==0 ) - { - minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state); - } - else - { - if( solvertype==1 ) - { - minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state); - } - else - { - if( solvertype==2 ) - { - minqpsetalgodenseipm(&state, ipmeps, _state); - } - else - { - if( solvertype==3 ) - { - minqpsetalgosparseipm(&state, ipmeps, _state); - } - else - { - ae_assert(ae_false, "unexpected solver type", _state); - } - } - } - } - minqpsetbc(&state, &bndl, &bndu, _state); - testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, rawccnt, n, &state, &rs, _state); - minqpsetlinearterm(&state, &b, _state); - testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state, &rs, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:3980"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - - /* - * 1. evaluate unconstrained gradient at solution - * - * 2. calculate constrained gradient (NNLS solver is used - * to evaluate gradient subject to active constraints). - * In order to do this we form CE matrix, matrix of active - * constraints (columns store constraint vectors). Then - * we try to approximate gradient vector by columns of CE, - * subject to non-negativity restriction placed on variables - * corresponding to inequality constraints. - * - * Residual from such regression is a constrained gradient vector. - */ - ae_vector_set_length(&g, n, _state); - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - g.ptr.p_double[i] = v+b.ptr.p_double[i]; - } - ae_matrix_set_length(&ce, n, n+rawccnt, _state); - ae_vector_set_length(&nonnegative, n+rawccnt, _state); - k = 0; - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:4008"); - ae_set_error_flag(errorflag, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:4009"); - if( ae_fp_less_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i]+tolconstr) ) - { - for(j=0; j<=n-1; j++) - { - ce.ptr.pp_double[j][k] = 0.0; - } - ce.ptr.pp_double[i][k] = 1.0; - nonnegative.ptr.p_bool[k] = ae_true; - inc(&k, _state); - continue; - } - if( ae_fp_greater_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i]-tolconstr) ) - { - for(j=0; j<=n-1; j++) - { - ce.ptr.pp_double[j][k] = 0.0; - } - ce.ptr.pp_double[i][k] = -1.0; - nonnegative.ptr.p_bool[k] = ae_true; - inc(&k, _state); - continue; - } - } - for(i=0; i<=rawccnt-1; i++) - { - v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = v-rawc.ptr.pp_double[i][n]; - ae_set_error_flag(errorflag, rawct.ptr.p_int[i]==0&&ae_fp_greater(ae_fabs(v, _state),tolconstr), __FILE__, __LINE__, "testminqpunit.ap:4033"); - ae_set_error_flag(errorflag, rawct.ptr.p_int[i]>0&&ae_fp_less(v,-tolconstr), __FILE__, __LINE__, "testminqpunit.ap:4034"); - ae_set_error_flag(errorflag, rawct.ptr.p_int[i]<0&&ae_fp_greater(v,tolconstr), __FILE__, __LINE__, "testminqpunit.ap:4035"); - if( rawct.ptr.p_int[i]==0 ) - { - for(j=0; j<=n-1; j++) - { - ce.ptr.pp_double[j][k] = rawc.ptr.pp_double[i][j]; - } - nonnegative.ptr.p_bool[k] = ae_false; - inc(&k, _state); - continue; - } - if( (rawct.ptr.p_int[i]>0&&ae_fp_less_eq(v,tolconstr))||(rawct.ptr.p_int[i]<0&&ae_fp_greater_eq(v,-tolconstr)) ) - { - for(j=0; j<=n-1; j++) - { - ce.ptr.pp_double[j][k] = ae_sign((double)(rawct.ptr.p_int[i]), _state)*rawc.ptr.pp_double[i][j]; - } - nonnegative.ptr.p_bool[k] = ae_true; - inc(&k, _state); - continue; - } - } - snnlsinit(0, 0, 0, &nnls, _state); - snnlssetproblem(&nnls, &ce, &g, 0, k, n, _state); - for(i=0; i<=k-1; i++) - { - if( !nonnegative.ptr.p_bool[i] ) - { - snnlsdropnnc(&nnls, i, _state); - } - } - snnlssolve(&nnls, &tmp, _state); - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - g.ptr.p_double[j] = g.ptr.p_double[j]-tmp.ptr.p_double[i]*ce.ptr.pp_double[j][i]; - } - } - vv = ae_v_dotproduct(&g.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - vv = ae_sqrt(vv, _state); - ae_set_error_flag(errorflag, ae_fp_greater(vv,gtol), __FILE__, __LINE__, "testminqpunit.ap:4064"); - } - } - } - - /* - * Boundary and linear equality/inequality constrained QP problem, - * test for correct handling of non-zero XOrigin: - * * N*N SPD A with moderate condtion number (up to 100) - * * boundary constraints 0<=x[i]<=1 - * * K0 ) - { - rawc.ptr.pp_double[i][n] = rawc.ptr.pp_double[i][n]-0.1; - } - } - testminqpunit_randomlysplitlc(&rawc, &rawct, k, n, &sparsec, &sparsect, &sparseccnt, &densec, &densect, &denseccnt, &rs, _state); - minqpcreate(n, &state, _state); - state.dbgskipconstraintnormalization = ae_true; - if( solvertype==0 ) - { - minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state); - } - else - { - if( solvertype==1 ) - { - minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state); - } - else - { - if( solvertype==2 ) - { - minqpsetalgodenseipm(&state, ipmeps, _state); - } - else - { - if( solvertype==3 ) - { - minqpsetalgosparseipm(&state, ipmeps, _state); - } - else - { - ae_assert(ae_false, "unexpected solver type", _state); - } - } - } - } - minqpsetlinearterm(&state, &b, _state); - testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state, &rs, _state); - minqpsetstartingpoint(&state, &xstart, _state); - minqpsetorigin(&state, &xorigin, _state); - minqpsetbc(&state, &bndl, &bndu, _state); - minqpsetlcmixed(&state, &sparsec, &sparsect, sparseccnt, &densec, &densect, denseccnt, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:4325"); - continue; - } - - /* - * Scale problem and solve one more time. - * Randomly choose between dense and sparse versions. - */ - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = ae_pow((double)(2), (double)(hqrnduniformi(&rs, 7, _state)-3), _state); - } - akind = hqrnduniformi(&rs, 2, _state); - if( akind==0 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]); - } - } - } - else - { - sparsecreate(n, n, 0, &sa, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - sparseset(&sa, i, j, a.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]), _state); - } - } - } - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i]; - xstart.ptr.p_double[i] = xstart.ptr.p_double[i]*s.ptr.p_double[i]; - xorigin.ptr.p_double[i] = xorigin.ptr.p_double[i]*s.ptr.p_double[i]; - bndl.ptr.p_double[i] = bndl.ptr.p_double[i]*s.ptr.p_double[i]; - bndu.ptr.p_double[i] = bndu.ptr.p_double[i]*s.ptr.p_double[i]; - } - for(i=0; i<=denseccnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - densec.ptr.pp_double[i][j] = densec.ptr.pp_double[i][j]/s.ptr.p_double[j]; - } - } - for(i=0; i<=sparseccnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - sparseset(&sparsec, i, j, sparseget(&sparsec, i, j, _state)/s.ptr.p_double[j], _state); - } - } - minqpcreate(n, &state, _state); - state.dbgskipconstraintnormalization = ae_true; - if( solvertype==0 ) - { - minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state); - } - else - { - if( solvertype==1 ) - { - minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state); - } - else - { - if( solvertype==2 ) - { - minqpsetalgodenseipm(&state, ipmeps, _state); - } - else - { - if( solvertype==3 ) - { - minqpsetalgosparseipm(&state, ipmeps, _state); - } - else - { - ae_assert(ae_false, "unexpected solver type", _state); - } - } - } - } - minqpsetlinearterm(&state, &b, _state); - if( akind==0 ) - { - minqpsetquadraticterm(&state, &a, ae_fp_greater(ae_randomreal(_state),0.5), _state); - } - if( akind==1 ) - { - minqpsetquadratictermsparse(&state, &sa, ae_fp_greater(ae_randomreal(_state),0.5), _state); - } - minqpsetstartingpoint(&state, &xstart, _state); - minqpsetorigin(&state, &xorigin, _state); - minqpsetbc(&state, &bndl, &bndu, _state); - minqpsetlcmixed(&state, &sparsec, &sparsect, sparseccnt, &densec, &densect, denseccnt, _state); - minqpsetscale(&state, &s, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x2, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:4390"); - continue; - } - - /* - * Compare - */ - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - mx = ae_maxreal(mx, ae_fabs(x1.ptr.p_double[i], _state), _state); - } - mx = ae_maxreal(mx, (double)(1), _state); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-x2.ptr.p_double[i]/s.ptr.p_double[i], _state),xtol*mx), __FILE__, __LINE__, "testminqpunit.ap:4402"); - } - } - } - - /* - * General inequality constrained problem: - * * N*N SPD diagonal A with moderate condtion number - * * no boundary constraints - * * K=N inequality constraints C*x >= C*x0, where C is N*N well conditioned - * matrix, x0 is some random vector [-1,+1] - * * optimization problem has form 0.5*x'*A*x-b'*x, - * where b is random vector from [-1,+1] - * * using duality, we can obtain solution of QP problem as follows: - * a) intermediate problem min(0.5*y'*B*y + d'*y) s.t. y>=0 - * is solved, where B = C*inv(A)*C', d = -(C*inv(A)*b + C*x0) - * b) after we got dual solution ys, we calculate primal solution - * xs = inv(A)*(C'*ys-b) - */ - for(n=1; n<=6; n++) - { - - /* - * Set up tolerances - */ - if( solvertype==0 ) - { - xtol = 1.0E-5; - } - else - { - if( (solvertype==1||solvertype==2)||solvertype==3 ) - { - xtol = 1.0E-3; - } - else - { - ae_assert(ae_false, "unexpected solver type", _state); - } - } - - /* - * Generate problem - */ - ae_vector_set_length(&da, n, _state); - ae_matrix_set_length(&a, n, n, _state); - rmatrixrndcond(n, ae_pow(10.0, 2*ae_randomreal(_state), _state), &t2, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xstart, n, _state); - ae_matrix_set_length(&rawc, n, n+1, _state); - ae_vector_set_length(&rawct, n, _state); - for(i=0; i<=n-1; i++) - { - da.ptr.p_double[i] = ae_exp(6*ae_randomreal(_state)-3, _state); - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - a.ptr.pp_double[i][i] = da.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - xstart.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=n-1; i++) - { - ae_v_move(&rawc.ptr.pp_double[i][0], 1, &t2.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - rawc.ptr.pp_double[i][n] = v; - rawct.ptr.p_int[i] = 1; - } - - /* - * Solve primal problem, check feasibility - */ - minqpcreate(n, &state, _state); - if( solvertype==0 ) - { - minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state); - } - else - { - if( solvertype==1 ) - { - minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state); - } - else - { - if( solvertype==2 ) - { - minqpsetalgodenseipm(&state, ipmeps, _state); - } - else - { - if( solvertype==3 ) - { - minqpsetalgosparseipm(&state, ipmeps, _state); - } - else - { - ae_assert(ae_false, "unexpected solver type", _state); - } - } - } - } - minqpsetlinearterm(&state, &b, _state); - testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state, &rs, _state); - minqpsetstartingpoint(&state, &xstart, _state); - minqpsetlc(&state, &rawc, &rawct, n, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:4490"); - continue; - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&x1.ptr.p_double[0], 1, &rawc.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - ae_set_error_flag(errorflag, ae_fp_less(v,rawc.ptr.pp_double[i][n]-xtol), __FILE__, __LINE__, "testminqpunit.ap:4496"); - } - - /* - * Generate dual problem: - * * A2 stores new quadratic term - * * B2 stores new linear term - * * BndL/BndU store boundary constraints - */ - ae_matrix_set_length(&t3, n, n, _state); - ae_matrix_set_length(&a2, n, n, _state); - rmatrixtranspose(n, n, &rawc, 0, 0, &t3, 0, 0, _state); - for(i=0; i<=n-1; i++) - { - v = 1/ae_sqrt(da.ptr.p_double[i], _state); - ae_v_muld(&t3.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v); - } - rmatrixsyrk(n, n, 1.0, &t3, 0, 0, 2, 0.0, &a2, 0, 0, ae_true, _state); - ae_vector_set_length(&tmp0, n, _state); - ae_v_move(&tmp0.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - tmp0.ptr.p_double[i] = tmp0.ptr.p_double[i]/da.ptr.p_double[i]; - } - ae_vector_set_length(&b2, n, _state); - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &tmp0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - b2.ptr.p_double[i] = -(v+rawc.ptr.pp_double[i][n]); - } - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - for(i=0; i<=n-1; i++) - { - bndl.ptr.p_double[i] = 0.0; - bndu.ptr.p_double[i] = _state->v_posinf; - } - minqpcreate(n, &state2, _state); - minqpsetalgoquickqp(&state2, 0.0, 0.0, 1.0E-9, 0, ae_true, _state); - minqpsetlinearterm(&state2, &b2, _state); - minqpsetquadraticterm(&state2, &a2, ae_true, _state); - minqpsetbc(&state2, &bndl, &bndu, _state); - minqpoptimize(&state2, _state); - minqpresults(&state2, &x2, &rep2, _state); - if( rep2.terminationtype<=0 ) - { - ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:4551"); - continue; - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&rawc.ptr.pp_double[0][i], rawc.stride, &x2.ptr.p_double[0], 1, ae_v_len(0,n-1)); - tmp0.ptr.p_double[i] = v-b.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - tmp0.ptr.p_double[i] = tmp0.ptr.p_double[i]/da.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(tmp0.ptr.p_double[i]-x1.ptr.p_double[i], _state),xtol*ae_maxreal(ae_fabs(tmp0.ptr.p_double[i], _state), 1.0, _state)), __FILE__, __LINE__, "testminqpunit.ap:4564"); - } - } - - /* - * Boundary and linear equality/inequality constrained QP problem with - * excessive constraints: - * * N*N SPD A with moderate condtion number (up to 100) - * * boundary constraints 0<=x[i]<=1 - * * K=2*N equality/inequality constraints Q*x = Q*x0, where Q is random matrix, - * x0 is some random vector from the feasible hypercube (0.1<=x0[i]<=0.9) - * * optimization problem has form 0.5*x'*A*x-b*x, - * where b is some random vector - * * because constraints are excessive, the main problem is to find - * feasible point; usually, the only existing feasible point is solution, - * so we have to check only feasibility - */ - for(n=1; n<=6; n++) - { - - /* - * Set up tolerances - */ - if( solvertype==0 ) - { - xtol = 1.0E-5; - } - else - { - if( (solvertype==1||solvertype==2)||solvertype==3 ) - { - xtol = 5.0E-3; - } - else - { - ae_assert(ae_false, "unexpected solver type", _state); - } - } - - /* - * Generate problem: A, b, BndL, BndU, CMatrix, x0, x1, XStart - */ - k = 2*n; - spdmatrixrndcond(n, ae_pow(10.0, 3*ae_randomreal(_state), _state), &a, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&x1, n, _state); - ae_vector_set_length(&xstart, n, _state); - ae_matrix_set_length(&rawc, k, n+1, _state); - ae_vector_set_length(&rawct, k, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 0.1+0.8*ae_randomreal(_state); - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - bndl.ptr.p_double[i] = 0.0; - bndu.ptr.p_double[i] = 1.0; - xstart.ptr.p_double[i] = (double)(ae_randominteger(2, _state)); - } - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - rawc.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - rawct.ptr.p_int[i] = ae_randominteger(3, _state)-1; - if( rawct.ptr.p_int[i]==0 ) - { - rawc.ptr.pp_double[i][n] = v; - } - if( rawct.ptr.p_int[i]>0 ) - { - rawc.ptr.pp_double[i][n] = v-50*xtol; - } - if( rawct.ptr.p_int[i]<0 ) - { - rawc.ptr.pp_double[i][n] = v+50*xtol; - } - } - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - - /* - * Create optimizer, solve - */ - minqpcreate(n, &state, _state); - if( solvertype==0 ) - { - minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state); - } - else - { - if( solvertype==1 ) - { - minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state); - } - else - { - if( solvertype==2 ) - { - minqpsetalgodenseipm(&state, ipmeps, _state); - } - else - { - if( solvertype==3 ) - { - minqpsetalgosparseipm(&state, ipmeps, _state); - } - else - { - ae_assert(ae_false, "unexpected solver type", _state); - } - } - } - } - minqpsetlinearterm(&state, &b, _state); - testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state, &rs, _state); - minqpsetstartingpoint(&state, &xstart, _state); - minqpsetbc(&state, &bndl, &bndu, _state); - testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, k, n, &state, &rs, _state); - minqpoptimize(&state, _state); - ae_vector_set_length(&x1, 0, _state); - minqpresults(&state, &x1, &rep, _state); - - /* - * Check feasibility properties of the solution - * - * NOTE: we do not check termination type because some solvers (IPM) may return feasible X even with negative code - */ - if( x1.cnt!=n ) - { - ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:4665"); - continue; - } - for(i=0; i<=k-1; i++) - { - v = ae_v_dotproduct(&x1.ptr.p_double[0], 1, &rawc.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - if( rawct.ptr.p_int[i]==0 ) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v-rawc.ptr.pp_double[i][n], _state),xtol), __FILE__, __LINE__, "testminqpunit.ap:4672"); - } - if( rawct.ptr.p_int[i]>0 ) - { - ae_set_error_flag(errorflag, ae_fp_less(v,rawc.ptr.pp_double[i][n]-xtol), __FILE__, __LINE__, "testminqpunit.ap:4674"); - } - if( rawct.ptr.p_int[i]<0 ) - { - ae_set_error_flag(errorflag, ae_fp_greater(v,rawc.ptr.pp_double[i][n]+xtol), __FILE__, __LINE__, "testminqpunit.ap:4676"); - } - } - } - - /* - * Boundary constraints posed as general linear ones: - * * no bound constraints - * * 2*N linear constraints 0 <= x[i] <= 1 - * * F(x) = |x-x0|^P, where P={2,4} and x0 is randomly selected from [-1,+2]^N - * * with such simple constraints and function it is easy to find - * analytic form of solution: S[i] = bound(x0[i], 0, 1). - * * however, we can't guarantee that solution is strictly feasible - * with respect to nonlinearity constraint, so we check - * for approximate feasibility. - */ - for(n=1; n<=5; n++) - { - - /* - * Set up tolerances - */ - if( solvertype==0 ) - { - xtol = 1.0E-3; - } - else - { - if( (solvertype==1||solvertype==2)||solvertype==3 ) - { - xtol = 1.0E-3; - } - else - { - ae_assert(ae_false, "unexpected solver type", _state); - } - } - - /* - * Generate X, BL, BU. - */ - ae_matrix_set_length(&a, n, n, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&xstart, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_matrix_set_length(&rawc, 2*n, n+1, _state); - ae_vector_set_length(&rawct, 2*n, _state); - k = 2*n; - for(i=0; i<=n-1; i++) - { - xstart.ptr.p_double[i] = ae_randomreal(_state); - x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1; - b.ptr.p_double[i] = -x0.ptr.p_double[i]; - for(j=0; j<=n; j++) - { - rawc.ptr.pp_double[2*i+0][j] = (double)(0); - rawc.ptr.pp_double[2*i+1][j] = (double)(0); - } - rawc.ptr.pp_double[2*i+0][i] = (double)(1); - rawc.ptr.pp_double[2*i+0][n] = (double)(0); - rawct.ptr.p_int[2*i+0] = 1; - rawc.ptr.pp_double[2*i+1][i] = (double)(1); - rawc.ptr.pp_double[2*i+1][n] = (double)(1); - rawct.ptr.p_int[2*i+1] = -1; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - a.ptr.pp_double[i][j] = (double)(1); - } - else - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - } - - /* - * Create and optimize - */ - minqpcreate(n, &state, _state); - if( solvertype==0 ) - { - minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state); - } - else - { - if( solvertype==1 ) - { - minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state); - } - else - { - if( solvertype==2 ) - { - minqpsetalgodenseipm(&state, ipmeps, _state); - } - else - { - if( solvertype==3 ) - { - minqpsetalgosparseipm(&state, ipmeps, _state); - } - else - { - ae_assert(ae_false, "unexpected solver type", _state); - } - } - } - } - testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, k, n, &state, &rs, _state); - minqpsetlinearterm(&state, &b, _state); - testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state, &rs, _state); - minqpsetstartingpoint(&state, &xstart, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:4763"); - continue; - } - - /* - * * compare solution with analytic one - * * check feasibility - */ - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-boundval(x0.ptr.p_double[i], 0.0, 1.0, _state), _state),xtol), __FILE__, __LINE__, "testminqpunit.ap:4773"); - ae_set_error_flag(errorflag, ae_fp_less(x1.ptr.p_double[i],0.0-xtol), __FILE__, __LINE__, "testminqpunit.ap:4774"); - ae_set_error_flag(errorflag, ae_fp_greater(x1.ptr.p_double[i],1.0+xtol), __FILE__, __LINE__, "testminqpunit.ap:4775"); - } - } - - /* - * Convex optimization problem with excessive constraints: - * - * * N=2..5 - * * f = 0.5*x'*A*x+b'*x - * * b has normally distributed entries - * * A is diagonal with log-normally distributed entries - * * box constraints: x[i] in [-1,+1] - * * 2^N "excessive" general linear constraints (v_k,x)<=(v_k,v_k)+v_shift, - * where v_k is one of 2^N vertices of feasible hypercube, v_shift is - * a shift parameter: - * * with zero v_shift such constraints are degenerate (each vertex has - * N box constraints and one "redundant" linear constraint) - * * with positive v_shift linear constraint is always inactive - * * with small (about machine epsilon) but negative v_shift, - * constraint is close to degenerate - but not exactly - * - * Because A is diagonal, we can easily find out solution analytically. - * - * NOTE: TolConstr must be large enough so it won't conflict with - * perturbation introduced by v_shift - */ - for(n=2; n<=5; n++) - { - for(shiftkind=-5; shiftkind<=1; shiftkind++) - { - - /* - * Set up tolerances - */ - if( solvertype==0 ) - { - tolconstr = 1.0E-6; - gtol = 1.0E-6; - } - else - { - if( (solvertype==1||solvertype==2)||solvertype==3 ) - { - tolconstr = 1.0E-4; - gtol = 1.0E-4; - } - else - { - ae_assert(ae_false, "unexpected solver type", _state); - } - } - - /* - * Generate A, B and initial point - */ - ae_matrix_set_length(&a, n, n, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&xstart, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - xstart.ptr.p_double[i] = hqrnduniformr(&rs, _state)-0.5; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - a.ptr.pp_double[i][i] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - } - - /* - * Generate constraints - */ - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - for(i=0; i<=n-1; i++) - { - bndl.ptr.p_double[i] = -1.0; - bndu.ptr.p_double[i] = 1.0; - } - rawccnt = ae_round(ae_pow((double)(2), (double)(n), _state), _state); - ae_matrix_set_length(&rawc, rawccnt, n+1, _state); - ae_vector_set_length(&rawct, rawccnt, _state); - for(i=0; i<=rawccnt-1; i++) - { - rawct.ptr.p_int[i] = -1; - k = i; - rawc.ptr.pp_double[i][n] = ae_sign((double)(shiftkind), _state)*ae_pow((double)(10), ae_fabs((double)(shiftkind), _state), _state)*ae_machineepsilon; - for(j=0; j<=n-1; j++) - { - rawc.ptr.pp_double[i][j] = (double)(2*(k%2)-1); - rawc.ptr.pp_double[i][n] = rawc.ptr.pp_double[i][n]+rawc.ptr.pp_double[i][j]*rawc.ptr.pp_double[i][j]; - k = k/2; - } - } - - /* - * Create and optimize - */ - minqpcreate(n, &state, _state); - minqpsetstartingpoint(&state, &xstart, _state); - if( solvertype==0 ) - { - minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state); - } - else - { - if( solvertype==1 ) - { - minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state); - } - else - { - if( solvertype==2 ) - { - minqpsetalgodenseipm(&state, ipmeps, _state); - } - else - { - if( solvertype==3 ) - { - minqpsetalgosparseipm(&state, ipmeps, _state); - } - else - { - ae_assert(ae_false, "unexpected solver type", _state); - } - } - } - } - minqpsetbc(&state, &bndl, &bndu, _state); - testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, rawccnt, n, &state, &rs, _state); - minqpsetlinearterm(&state, &b, _state); - testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state, &rs, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:4886"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - - /* - * Evaluate gradient at solution and test - */ - vv = 0.0; - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = v+b.ptr.p_double[i]; - if( ae_fp_less_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i]+tolconstr)&&ae_fp_greater(v,(double)(0)) ) - { - v = 0.0; - } - if( ae_fp_greater_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i]-tolconstr)&&ae_fp_less(v,(double)(0)) ) - { - v = 0.0; - } - vv = vv+ae_sqr(v, _state); - } - vv = ae_sqrt(vv, _state); - ae_set_error_flag(errorflag, ae_fp_greater(vv,gtol), __FILE__, __LINE__, "testminqpunit.ap:4910"); - } - } - - /* - * Convex optimization problem with known answer (we generate constraints - * and Lagrange coefficients, and then generate quadratic and linear term - * which satisfy KKT conditions for given Lagrange coefficients): - * - * * N=2..8 - * * f = 0.5*x'*A*x+b'*x - * * several kinds of A are tried: zero, well conditioned SPD, low rank - * * initial point x0 = [0 0 ... 0 0] - * * absent bounds can be set to +-INF or to some huge number (randomly) - * * first, we generate set of linear constraints (without bounds), - * solution point X and Lagrange multipliers for linear and box constraints - * * then we determine bounds on variables and linear constraints which - * align with values/signs of Lagrange multipliers - * * then, having quadratic term A and known constraints and Lagrange - * multipliers we determine linear term B which makes KKT conditions true - */ - for(n=1; n<=8; n++) - { - for(akind=0; akind<=2; akind++) - { - - /* - * Select number used for absent bounds: - * * +- INF - * * 1e9 - * * 1e11 - */ - i = hqrnduniformi(&rs, 3, _state); - minushuge = _state->v_neginf; - plushuge = _state->v_posinf; - if( i==1 ) - { - minushuge = -1.0E9; - plushuge = 1.0E9; - } - if( i==2 ) - { - minushuge = -1.0E11; - plushuge = 1.0E11; - } - - /* - * Generate quadratic term A, origin and scale - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - issemidefinite = ae_true; - if( akind==1 ) - { - - /* - * Dense well conditioned SPD - */ - spdmatrixrndcond(n, 50.0, &a, _state); - issemidefinite = ae_false; - } - if( akind==2 ) - { - - /* - * Low rank semidefinite - */ - ae_vector_set_length(&tmp, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - for(k=1; k<=ae_minint(3, n-1, _state); k++) - { - for(i=0; i<=n-1; i++) - { - tmp.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - v = ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j]; - } - } - } - issemidefinite = ae_true; - } - ae_vector_set_length(&s, n, _state); - ae_vector_set_length(&xorigin, n, _state); - for(j=0; j<=n-1; j++) - { - xorigin.ptr.p_double[j] = hqrndnormal(&rs, _state); - s.ptr.p_double[j] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - } - - /* - * Generate linear constraints (left parts) - */ - rawccnt = hqrnduniformi(&rs, 2*n+1, _state); - ae_matrix_set_length(&rawc, rawccnt, n, _state); - for(i=0; i<=rawccnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - rawc.ptr.pp_double[i][j] = (double)(0); - } - nnz = hqrnduniformi(&rs, n+1, _state); - for(k=0; k<=nnz-1; k++) - { - j = hqrnduniformi(&rs, n, _state); - v = hqrndnormal(&rs, _state); - v = v+0.1*possign(v, _state); - rawc.ptr.pp_double[i][j] = v; - } - } - - /* - * Generate Lagrange multipliers, with at most NActive= C*x0, where C is N*N well conditioned - * matrix, x0 is some random vector [-1,+1] - * * optimization problem has form 0.5*x'*A*x-b'*x, - * where b is random vector from [-1,+1] - * * using duality, we can obtain solution of QP problem as follows: - * a) intermediate problem min(0.5*y'*B*y + d'*y) s.t. y>=0 - * is solved, where B = C*inv(A)*C', d = -(C*inv(A)*b + C*x0) - * b) after we got dual solution ys, we calculate primal solution - * xs = inv(A)*(C'*ys-b) - */ - n = 60; - rawccnt = 40; - if( solvertype==0 ) - { - xtol = 1.0E-3; - } - else - { - if( (solvertype==1||solvertype==2)||solvertype==3 ) - { - xtol = 1.0E-3; - } - else - { - ae_assert(ae_false, "unexpected solver type", _state); - } - } - ae_vector_set_length(&da, n, _state); - ae_matrix_set_length(&a, n, n, _state); - rmatrixrndcond(n, ae_pow(10.0, 2*ae_randomreal(_state), _state), &t2, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xstart, n, _state); - ae_matrix_set_length(&rawc, rawccnt, n+1, _state); - ae_vector_set_length(&rawct, rawccnt, _state); - for(i=0; i<=n-1; i++) - { - da.ptr.p_double[i] = ae_exp(8*ae_randomreal(_state)-4, _state); - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - a.ptr.pp_double[i][i] = da.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - xstart.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=rawccnt-1; i++) - { - ae_v_move(&rawc.ptr.pp_double[i][0], 1, &t2.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - rawc.ptr.pp_double[i][n] = v; - rawct.ptr.p_int[i] = 1; - } - minqpcreate(n, &state, _state); - if( solvertype==0 ) - { - minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state); - } - else - { - if( solvertype==1 ) - { - minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state); - } - else - { - if( solvertype==2 ) - { - minqpsetalgodenseipm(&state, ipmeps, _state); - } - else - { - if( solvertype==3 ) - { - minqpsetalgosparseipm(&state, ipmeps, _state); - } - else - { - ae_assert(ae_false, "unexpected solver type", _state); - } - } - } - } - minqpsetlinearterm(&state, &b, _state); - testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state, &rs, _state); - minqpsetstartingpoint(&state, &xstart, _state); - testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, rawccnt, n, &state, &rs, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &x1, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:5390"); - continue; - } - for(i=0; i<=rawccnt-1; i++) - { - v = ae_v_dotproduct(&x1.ptr.p_double[0], 1, &rawc.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - ae_set_error_flag(errorflag, ae_fp_less(v,rawc.ptr.pp_double[i][n]-xtol), __FILE__, __LINE__, "testminqpunit.ap:5396"); - } - ae_matrix_set_length(&t3, n, rawccnt, _state); - ae_matrix_set_length(&a2, rawccnt, rawccnt, _state); - rmatrixtranspose(rawccnt, n, &rawc, 0, 0, &t3, 0, 0, _state); - for(i=0; i<=n-1; i++) - { - v = 1/ae_sqrt(da.ptr.p_double[i], _state); - ae_v_muld(&t3.ptr.pp_double[i][0], 1, ae_v_len(0,rawccnt-1), v); - } - rmatrixsyrk(rawccnt, n, 1.0, &t3, 0, 0, 2, 0.0, &a2, 0, 0, ae_true, _state); - ae_vector_set_length(&tmp0, n, _state); - ae_v_move(&tmp0.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - tmp0.ptr.p_double[i] = tmp0.ptr.p_double[i]/da.ptr.p_double[i]; - } - ae_vector_set_length(&b2, rawccnt, _state); - for(i=0; i<=rawccnt-1; i++) - { - v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &tmp0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - b2.ptr.p_double[i] = -(v+rawc.ptr.pp_double[i][n]); - } - ae_vector_set_length(&bndl, rawccnt, _state); - ae_vector_set_length(&bndu, rawccnt, _state); - for(i=0; i<=rawccnt-1; i++) - { - bndl.ptr.p_double[i] = 0.0; - bndu.ptr.p_double[i] = _state->v_posinf; - } - minqpcreate(rawccnt, &state2, _state); - minqpsetalgoquickqp(&state2, 0.0, 0.0, 1.0E-9, 0, ae_true, _state); - minqpsetlinearterm(&state2, &b2, _state); - minqpsetquadraticterm(&state2, &a2, ae_true, _state); - minqpsetbc(&state2, &bndl, &bndu, _state); - minqpoptimize(&state2, _state); - minqpresults(&state2, &x2, &rep2, _state); - if( rep2.terminationtype<=0 ) - { - ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:5449"); - continue; - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&rawc.ptr.pp_double[0][i], rawc.stride, &x2.ptr.p_double[0], 1, ae_v_len(0,rawccnt-1)); - tmp0.ptr.p_double[i] = v-b.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - tmp0.ptr.p_double[i] = tmp0.ptr.p_double[i]/da.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(tmp0.ptr.p_double[i]-x1.ptr.p_double[i], _state),xtol*ae_maxreal(ae_fabs(tmp0.ptr.p_double[i], _state), 1.0, _state)), __FILE__, __LINE__, "testminqpunit.ap:5462"); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests special inequality constrained QP problems. - -Returns True on errors. -*************************************************************************/ -static ae_bool testminqpunit_specialicqptests(ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_matrix c; - ae_vector xstart; - ae_vector xend; - ae_vector xexact; - ae_vector b; - ae_vector bndl; - ae_vector bndu; - ae_vector ct; - minqpstate state; - minqpreport rep; - ae_bool waserrors; - ae_int_t i; - ae_int_t j; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&c, 0, sizeof(c)); - memset(&xstart, 0, sizeof(xstart)); - memset(&xend, 0, sizeof(xend)); - memset(&xexact, 0, sizeof(xexact)); - memset(&b, 0, sizeof(b)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&ct, 0, sizeof(ct)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xstart, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xend, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xexact, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - _minqpstate_init(&state, _state, ae_true); - _minqpreport_init(&rep, _state, ae_true); - - waserrors = ae_false; - - /* - * Test 1: reported by Vanderlande Industries. - * Tests algorithm ability to handle degenerate constraints. - */ - ae_matrix_set_length(&a, 3, 3, _state); - for(i=0; i<=2; i++) - { - for(j=0; j<=2; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=2; i++) - { - a.ptr.pp_double[i][i] = (double)(1); - } - ae_vector_set_length(&b, 3, _state); - b.ptr.p_double[0] = (double)(-50); - b.ptr.p_double[1] = (double)(-50); - b.ptr.p_double[2] = (double)(-75); - ae_vector_set_length(&bndl, 3, _state); - bndl.ptr.p_double[0] = (double)(0); - bndl.ptr.p_double[1] = (double)(0); - bndl.ptr.p_double[2] = (double)(0); - ae_vector_set_length(&bndu, 3, _state); - bndu.ptr.p_double[0] = (double)(100); - bndu.ptr.p_double[1] = (double)(100); - bndu.ptr.p_double[2] = (double)(150); - ae_vector_set_length(&xstart, 3, _state); - xstart.ptr.p_double[0] = (double)(0); - xstart.ptr.p_double[1] = (double)(100); - xstart.ptr.p_double[2] = (double)(0); - ae_vector_set_length(&xexact, 3, _state); - xexact.ptr.p_double[0] = (double)(0); - xexact.ptr.p_double[1] = (double)(100); - xexact.ptr.p_double[2] = (double)(50); - ae_matrix_set_length(&c, 3, 4, _state); - c.ptr.pp_double[0][0] = (double)(1); - c.ptr.pp_double[0][1] = (double)(-1); - c.ptr.pp_double[0][2] = (double)(0); - c.ptr.pp_double[0][3] = (double)(-100); - c.ptr.pp_double[1][0] = (double)(1); - c.ptr.pp_double[1][1] = (double)(0); - c.ptr.pp_double[1][2] = (double)(-1); - c.ptr.pp_double[1][3] = (double)(0); - c.ptr.pp_double[2][0] = (double)(-1); - c.ptr.pp_double[2][1] = (double)(0); - c.ptr.pp_double[2][2] = (double)(1); - c.ptr.pp_double[2][3] = (double)(50); - ae_vector_set_length(&ct, 3, _state); - ct.ptr.p_int[0] = -1; - ct.ptr.p_int[1] = -1; - ct.ptr.p_int[2] = -1; - minqpcreate(3, &state, _state); - testminqpunit_setrandomalgoconvexlc(&state, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetquadraticterm(&state, &a, ae_true, _state); - minqpsetstartingpoint(&state, &xstart, _state); - minqpsetbc(&state, &bndl, &bndu, _state); - minqpsetlc(&state, &c, &ct, 3, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend, &rep, _state); - if( rep.terminationtype>0 ) - { - for(i=0; i<=2; i++) - { - waserrors = waserrors||ae_fp_greater(ae_fabs(xend.ptr.p_double[i]-xexact.ptr.p_double[i], _state),1.0E6*ae_machineepsilon); - } - } - else - { - waserrors = ae_true; - } - - /* - * Test 2: reported by Vanderlande Industries. - * Tests algorithm ability to handle degenerate constraints. - */ - ae_matrix_set_length(&a, 3, 3, _state); - for(i=0; i<=2; i++) - { - for(j=0; j<=2; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=2; i++) - { - a.ptr.pp_double[i][i] = (double)(1); - } - ae_vector_set_length(&b, 3, _state); - b.ptr.p_double[0] = (double)(-50); - b.ptr.p_double[1] = (double)(-50); - b.ptr.p_double[2] = (double)(-75); - ae_vector_set_length(&bndl, 3, _state); - bndl.ptr.p_double[0] = (double)(0); - bndl.ptr.p_double[1] = (double)(0); - bndl.ptr.p_double[2] = (double)(0); - ae_vector_set_length(&bndu, 3, _state); - bndu.ptr.p_double[0] = (double)(100); - bndu.ptr.p_double[1] = (double)(100); - bndu.ptr.p_double[2] = (double)(150); - ae_vector_set_length(&xstart, 3, _state); - xstart.ptr.p_double[0] = (double)(0); - xstart.ptr.p_double[1] = (double)(100); - xstart.ptr.p_double[2] = (double)(150); - ae_vector_set_length(&xexact, 3, _state); - xexact.ptr.p_double[0] = (double)(0); - xexact.ptr.p_double[1] = (double)(100); - xexact.ptr.p_double[2] = (double)(100); - ae_matrix_set_length(&c, 3, 4, _state); - c.ptr.pp_double[0][0] = (double)(1); - c.ptr.pp_double[0][1] = (double)(-1); - c.ptr.pp_double[0][2] = (double)(0); - c.ptr.pp_double[0][3] = (double)(-100); - c.ptr.pp_double[1][0] = (double)(0); - c.ptr.pp_double[1][1] = (double)(1); - c.ptr.pp_double[1][2] = (double)(-1); - c.ptr.pp_double[1][3] = (double)(0); - c.ptr.pp_double[2][0] = (double)(0); - c.ptr.pp_double[2][1] = (double)(-1); - c.ptr.pp_double[2][2] = (double)(1); - c.ptr.pp_double[2][3] = (double)(50); - ae_vector_set_length(&ct, 3, _state); - ct.ptr.p_int[0] = -1; - ct.ptr.p_int[1] = -1; - ct.ptr.p_int[2] = -1; - minqpcreate(3, &state, _state); - testminqpunit_setrandomalgoconvexlc(&state, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetquadraticterm(&state, &a, ae_true, _state); - minqpsetstartingpoint(&state, &xstart, _state); - minqpsetbc(&state, &bndl, &bndu, _state); - minqpsetlc(&state, &c, &ct, 3, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xend, &rep, _state); - if( rep.terminationtype>0 ) - { - for(i=0; i<=2; i++) - { - waserrors = waserrors||ae_fp_greater(ae_fabs(xend.ptr.p_double[i]-xexact.ptr.p_double[i], _state),1.0E6*ae_machineepsilon); - } - } - else - { - waserrors = ae_true; - } - result = waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function tests linearly constrained DENSE-AUL solver - -On failure sets Err to True; on success leaves it unchanged. -*************************************************************************/ -static void testminqpunit_denseaultests(ae_bool* errorflag, - ae_state *_state) -{ - ae_frame _frame_block; - hqrndstate rs; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double vv; - ae_int_t scaletype; - ae_matrix rawa; - ae_matrix z; - ae_vector bndl; - ae_vector bndu; - ae_matrix rawc; - ae_vector rawct; - ae_int_t rawccnt; - ae_vector b; - ae_vector x0; - ae_vector xf; - ae_vector r; - ae_vector xsol; - ae_vector s; - minqpstate state; - minqpreport rep; - double epsx; - double xtol; - double rho; - ae_int_t outerits; - densesolverreport svrep; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - memset(&rawa, 0, sizeof(rawa)); - memset(&z, 0, sizeof(z)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&rawc, 0, sizeof(rawc)); - memset(&rawct, 0, sizeof(rawct)); - memset(&b, 0, sizeof(b)); - memset(&x0, 0, sizeof(x0)); - memset(&xf, 0, sizeof(xf)); - memset(&r, 0, sizeof(r)); - memset(&xsol, 0, sizeof(xsol)); - memset(&s, 0, sizeof(s)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&svrep, 0, sizeof(svrep)); - _hqrndstate_init(&rs, _state, ae_true); - ae_matrix_init(&rawa, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&rawc, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rawct, 0, DT_INT, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&r, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xsol, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - _minqpstate_init(&state, _state, ae_true); - _minqpreport_init(&rep, _state, ae_true); - _densesolverreport_init(&svrep, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Test that unconstrained problem is solved with high precision, - * independently of Rho and/or outer iterations count. - * - * 50% of problems are rescaled wildly (with scale being passed to - * the solver). - */ - epsx = 1.0E-12; - xtol = 1.0E-7; - for(n=1; n<=10; n++) - { - for(scaletype=0; scaletype<=1; scaletype++) - { - - /* - * Generate random A, b, X0 and XSOL - */ - spdmatrixrndcond(n, ae_pow(10.0, 3*hqrnduniformr(&rs, _state), _state), &rawa, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&xsol, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - xsol.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&rawa.ptr.pp_double[i][0], 1, &xsol.ptr.p_double[0], 1, ae_v_len(0,n-1)); - b.ptr.p_double[i] = -v; - } - - /* - * Generate scale vector, apply it - */ - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - if( scaletype>0 ) - { - s.ptr.p_double[i] = ae_pow((double)(10), hqrnduniformr(&rs, _state)*20-10, _state); - } - else - { - s.ptr.p_double[i] = (double)(1); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - rawa.ptr.pp_double[i][j] = rawa.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]); - } - b.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i]; - x0.ptr.p_double[i] = x0.ptr.p_double[i]*s.ptr.p_double[i]; - xsol.ptr.p_double[i] = xsol.ptr.p_double[i]*s.ptr.p_double[i]; - } - - /* - * Create optimizer, solve - */ - rho = ae_pow((double)(10), 2*hqrnduniformr(&rs, _state), _state); - outerits = hqrnduniformi(&rs, 5, _state); - minqpcreate(n, &state, _state); - minqpsetalgodenseaul(&state, epsx, rho, outerits, _state); - minqpsetlinearterm(&state, &b, _state); - testminqpunit_randomlyselectconvertandsetquadraticterm(&rawa, n, &state, &rs, _state); - minqpsetscale(&state, &s, _state); - minqpsetstartingpoint(&state, &x0, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xf, &rep, _state); - - /* - * Compare against analytically known solution - */ - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:7182"); - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xf.ptr.p_double[i]-xsol.ptr.p_double[i], _state)/s.ptr.p_double[i],xtol), __FILE__, __LINE__, "testminqpunit.ap:7186"); - } - } - } - - /* - * Test that problem with zero constraint matrix can be solved - * (with high precision). We do not perform any additional "tweaks" - * like scaling of variables, just want to test ability to handle - * zero matrices. - */ - epsx = 1.0E-12; - xtol = 1.0E-7; - for(n=1; n<=10; n++) - { - - /* - * Generate random A, b, X0 and XSOL - */ - spdmatrixrndcond(n, ae_pow(10.0, 3*hqrnduniformr(&rs, _state), _state), &rawa, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&xsol, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - xsol.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&rawa.ptr.pp_double[i][0], 1, &xsol.ptr.p_double[0], 1, ae_v_len(0,n-1)); - b.ptr.p_double[i] = -v; - } - rawccnt = hqrnduniformi(&rs, 2*n, _state); - ae_matrix_set_length(&rawc, rawccnt, n+1, _state); - ae_vector_set_length(&rawct, rawccnt, _state); - for(i=0; i<=rawccnt-1; i++) - { - for(j=0; j<=n; j++) - { - rawc.ptr.pp_double[i][j] = (double)(0); - } - rawct.ptr.p_int[i] = hqrnduniformi(&rs, 3, _state)-1; - } - - /* - * Create optimizer, solve - */ - rho = ae_pow((double)(10), 2*hqrnduniformr(&rs, _state), _state); - outerits = hqrnduniformi(&rs, 5, _state); - minqpcreate(n, &state, _state); - minqpsetalgodenseaul(&state, epsx, rho, outerits, _state); - minqpsetlinearterm(&state, &b, _state); - testminqpunit_randomlyselectconvertandsetquadraticterm(&rawa, n, &state, &rs, _state); - minqpsetlc(&state, &rawc, &rawct, rawccnt, _state); - minqpsetstartingpoint(&state, &x0, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xf, &rep, _state); - - /* - * Compare against analytically known solution - */ - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:7246"); - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xf.ptr.p_double[i]-xsol.ptr.p_double[i], _state),xtol), __FILE__, __LINE__, "testminqpunit.ap:7250"); - } - } - - /* - * Test that box/linearly inequality constrained problem with ALL constraints - * being inactive at BOTH initial and final points is solved with high precision. - * - * 50% of problems are rescaled wildly (with scale being passed to - * the solver). - */ - epsx = 1.0E-12; - xtol = 1.0E-7; - for(n=1; n<=10; n++) - { - for(scaletype=0; scaletype<=1; scaletype++) - { - - /* - * Generate random A, b, X0 and XSOL - */ - spdmatrixrndcond(n, ae_pow(10.0, 3*hqrnduniformr(&rs, _state), _state), &rawa, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&xsol, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - xsol.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&rawa.ptr.pp_double[i][0], 1, &xsol.ptr.p_double[0], 1, ae_v_len(0,n-1)); - b.ptr.p_double[i] = -v; - } - - /* - * Generate such set of inequality constraints that ALL - * constraints are inactive at both X0 and XSOL. - */ - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - for(i=0; i<=n-1; i++) - { - bndl.ptr.p_double[i] = ae_minreal(x0.ptr.p_double[i], xsol.ptr.p_double[i], _state)-1-hqrnduniformr(&rs, _state); - bndu.ptr.p_double[i] = ae_maxreal(x0.ptr.p_double[i], xsol.ptr.p_double[i], _state)+1+hqrnduniformr(&rs, _state); - } - rawccnt = hqrnduniformi(&rs, 2*n, _state); - ae_matrix_set_length(&rawc, rawccnt, n+1, _state); - ae_vector_set_length(&rawct, rawccnt, _state); - for(i=0; i<=rawccnt-1; i++) - { - v = (double)(0); - vv = (double)(0); - for(j=0; j<=n-1; j++) - { - rawc.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - v = v+rawc.ptr.pp_double[i][j]*x0.ptr.p_double[j]; - vv = vv+rawc.ptr.pp_double[i][j]*xsol.ptr.p_double[j]; - } - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - rawct.ptr.p_int[i] = 1; - rawc.ptr.pp_double[i][n] = ae_minreal(v, vv, _state)-1-hqrnduniformr(&rs, _state); - } - else - { - rawct.ptr.p_int[i] = -1; - rawc.ptr.pp_double[i][n] = ae_maxreal(v, vv, _state)+1+hqrnduniformr(&rs, _state); - } - } - - /* - * Generate scale vector, apply it - */ - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - if( scaletype>0 ) - { - s.ptr.p_double[i] = ae_pow((double)(10), hqrnduniformr(&rs, _state)*20-10, _state); - } - else - { - s.ptr.p_double[i] = (double)(1); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - rawa.ptr.pp_double[i][j] = rawa.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]); - } - b.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i]; - x0.ptr.p_double[i] = x0.ptr.p_double[i]*s.ptr.p_double[i]; - xsol.ptr.p_double[i] = xsol.ptr.p_double[i]*s.ptr.p_double[i]; - bndl.ptr.p_double[i] = bndl.ptr.p_double[i]*s.ptr.p_double[i]; - bndu.ptr.p_double[i] = bndu.ptr.p_double[i]*s.ptr.p_double[i]; - } - for(i=0; i<=rawccnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - rawc.ptr.pp_double[i][j] = rawc.ptr.pp_double[i][j]/s.ptr.p_double[j]; - } - } - - /* - * Create optimizer, solve - */ - rho = 100.0; - outerits = 1; - minqpcreate(n, &state, _state); - minqpsetstartingpoint(&state, &x0, _state); - minqpsetalgodenseaul(&state, epsx, rho, outerits, _state); - minqpsetlinearterm(&state, &b, _state); - testminqpunit_randomlyselectconvertandsetquadraticterm(&rawa, n, &state, &rs, _state); - minqpsetbc(&state, &bndl, &bndu, _state); - testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, rawccnt, n, &state, &rs, _state); - minqpsetscale(&state, &s, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xf, &rep, _state); - - /* - * Compare against analytically known solution - */ - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:7367"); - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xf.ptr.p_double[i]-xsol.ptr.p_double[i], _state)/s.ptr.p_double[i],xtol), __FILE__, __LINE__, "testminqpunit.ap:7371"); - } - } - } - - /* - * Test that linear equality constrained problem is solved with high precision. - * - * 50% of problems are rescaled wildly (variable scaling, with scale being - * passed to the solver). - */ - epsx = 1.0E-12; - xtol = 1.0E-6; - for(n=1; n<=10; n++) - { - for(scaletype=0; scaletype<=1; scaletype++) - { - - /* - * Generate random A, b, X0, constraints - */ - spdmatrixrndcond(n, ae_pow(10.0, 3*hqrnduniformr(&rs, _state), _state), &rawa, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&xsol, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - rmatrixrndcond(n, (double)(10), &z, _state); - rawccnt = ae_maxint(n-2, 0, _state); - if( rawccnt>0 ) - { - ae_matrix_set_length(&rawc, rawccnt, n+1, _state); - ae_vector_set_length(&rawct, rawccnt, _state); - for(i=0; i<=rawccnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - rawc.ptr.pp_double[i][j] = z.ptr.pp_double[i][j]; - } - rawct.ptr.p_int[i] = 0; - rawc.ptr.pp_double[i][n] = hqrndnormal(&rs, _state); - } - } - - /* - * Generate scale vector, apply it - */ - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - if( scaletype>0 ) - { - s.ptr.p_double[i] = ae_pow((double)(10), hqrnduniformr(&rs, _state)*20-10, _state); - } - else - { - s.ptr.p_double[i] = (double)(1); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - rawa.ptr.pp_double[i][j] = rawa.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]); - } - b.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i]; - x0.ptr.p_double[i] = x0.ptr.p_double[i]*s.ptr.p_double[i]; - xsol.ptr.p_double[i] = xsol.ptr.p_double[i]*s.ptr.p_double[i]; - } - for(i=0; i<=rawccnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - rawc.ptr.pp_double[i][j] = rawc.ptr.pp_double[i][j]/s.ptr.p_double[j]; - } - } - - /* - * Create optimizer, solve - */ - rho = 100.0; - outerits = 3; - minqpcreate(n, &state, _state); - minqpsetalgodenseaul(&state, epsx, rho, outerits, _state); - minqpsetlinearterm(&state, &b, _state); - testminqpunit_randomlyselectconvertandsetquadraticterm(&rawa, n, &state, &rs, _state); - testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, rawccnt, n, &state, &rs, _state); - minqpsetscale(&state, &s, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xf, &rep, _state); - - /* - * Solve problem analytically using Lagrangian approach - */ - ae_matrix_set_length(&z, n+rawccnt, n+rawccnt, _state); - ae_vector_set_length(&r, n+rawccnt, _state); - for(i=0; i<=n+rawccnt-1; i++) - { - for(j=0; j<=n+rawccnt-1; j++) - { - z.ptr.pp_double[i][j] = (double)(0); - } - r.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - z.ptr.pp_double[i][j] = rawa.ptr.pp_double[i][j]; - } - } - for(i=0; i<=n-1; i++) - { - r.ptr.p_double[i] = -b.ptr.p_double[i]; - } - for(i=0; i<=rawccnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - z.ptr.pp_double[n+i][j] = rawc.ptr.pp_double[i][j]; - z.ptr.pp_double[j][n+i] = rawc.ptr.pp_double[i][j]; - } - r.ptr.p_double[n+i] = rawc.ptr.pp_double[i][n]; - } - rmatrixsolve(&z, n+rawccnt, &r, &k, &svrep, &xsol, _state); - ae_assert(k>0, "MinQPTest: integrity check failed", _state); - - /* - * Compare against analytically known solution - */ - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:7481"); - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xf.ptr.p_double[i]-xsol.ptr.p_double[i], _state)/s.ptr.p_double[i],xtol), __FILE__, __LINE__, "testminqpunit.ap:7485"); - } - } - } - - /* - * MEDIUM-SCALE VERSION OF PREVIOUS TEST. - * - * Test that linear equality constrained problem is solved with high precision. - * - * 50% of problems are rescaled wildly (variable scaling, with scale being - * passed to the solver). - */ - epsx = 1.0E-12; - xtol = 1.0E-6; - for(n=99; n<=101; n++) - { - for(scaletype=0; scaletype<=1; scaletype++) - { - - /* - * Generate random A, b, X0, constraints - */ - spdmatrixrndcond(n, ae_pow(10.0, 3*hqrnduniformr(&rs, _state), _state), &rawa, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&xsol, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - rmatrixrndcond(n, (double)(10), &z, _state); - rawccnt = ae_maxint(n-2, 0, _state); - if( rawccnt>0 ) - { - ae_matrix_set_length(&rawc, rawccnt, n+1, _state); - ae_vector_set_length(&rawct, rawccnt, _state); - for(i=0; i<=rawccnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - rawc.ptr.pp_double[i][j] = z.ptr.pp_double[i][j]; - } - rawct.ptr.p_int[i] = 0; - rawc.ptr.pp_double[i][n] = hqrndnormal(&rs, _state); - } - } - - /* - * Generate scale vector, apply it - */ - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - if( scaletype>0 ) - { - s.ptr.p_double[i] = ae_pow((double)(10), hqrnduniformr(&rs, _state)*20-10, _state); - } - else - { - s.ptr.p_double[i] = (double)(1); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - rawa.ptr.pp_double[i][j] = rawa.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]); - } - b.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i]; - x0.ptr.p_double[i] = x0.ptr.p_double[i]*s.ptr.p_double[i]; - xsol.ptr.p_double[i] = xsol.ptr.p_double[i]*s.ptr.p_double[i]; - } - for(i=0; i<=rawccnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - rawc.ptr.pp_double[i][j] = rawc.ptr.pp_double[i][j]/s.ptr.p_double[j]; - } - } - - /* - * Create optimizer, solve - */ - rho = 100.0; - outerits = 3; - minqpcreate(n, &state, _state); - minqpsetalgodenseaul(&state, epsx, rho, outerits, _state); - minqpsetlinearterm(&state, &b, _state); - testminqpunit_randomlyselectconvertandsetquadraticterm(&rawa, n, &state, &rs, _state); - testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, rawccnt, n, &state, &rs, _state); - minqpsetscale(&state, &s, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xf, &rep, _state); - - /* - * Solve problem analytically using Lagrangian approach - */ - ae_matrix_set_length(&z, n+rawccnt, n+rawccnt, _state); - ae_vector_set_length(&r, n+rawccnt, _state); - for(i=0; i<=n+rawccnt-1; i++) - { - for(j=0; j<=n+rawccnt-1; j++) - { - z.ptr.pp_double[i][j] = (double)(0); - } - r.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - z.ptr.pp_double[i][j] = rawa.ptr.pp_double[i][j]; - } - } - for(i=0; i<=n-1; i++) - { - r.ptr.p_double[i] = -b.ptr.p_double[i]; - } - for(i=0; i<=rawccnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - z.ptr.pp_double[n+i][j] = rawc.ptr.pp_double[i][j]; - z.ptr.pp_double[j][n+i] = rawc.ptr.pp_double[i][j]; - } - r.ptr.p_double[n+i] = rawc.ptr.pp_double[i][n]; - } - rmatrixsolve(&z, n+rawccnt, &r, &k, &svrep, &xsol, _state); - ae_assert(k>0, "MinQPTest: integrity check failed", _state); - - /* - * Compare against analytically known solution - */ - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:7597"); - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xf.ptr.p_double[i]-xsol.ptr.p_double[i], _state)/s.ptr.p_double[i],xtol), __FILE__, __LINE__, "testminqpunit.ap:7601"); - } - } - } - - /* - * Test that constraints are automatically scaled to adapt to problem curvature - * (that multiplication of A and b by some large/small number does not affect - * solver). - * - * We generate random well-scaled problem, and multiply A/b by some large/small number, - * and test that problem is still solved with high precision. - * - * NOTE: just to make things worse, we rescale variables randomly, but primary - * idea of this test is to check for multiplication of A/B - */ - epsx = 1.0E-12; - xtol = 1.0E-6; - for(n=1; n<=10; n++) - { - for(scaletype=-1; scaletype<=1; scaletype++) - { - - /* - * Generate random A, b, X0, constraints - */ - spdmatrixrndcond(n, ae_pow(10.0, 3*hqrnduniformr(&rs, _state), _state), &rawa, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&xsol, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - rmatrixrndcond(n, (double)(10), &z, _state); - rawccnt = ae_maxint(n-2, 0, _state); - if( rawccnt>0 ) - { - ae_matrix_set_length(&rawc, rawccnt, n+1, _state); - ae_vector_set_length(&rawct, rawccnt, _state); - for(i=0; i<=rawccnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - rawc.ptr.pp_double[i][j] = z.ptr.pp_double[i][j]; - } - rawct.ptr.p_int[i] = 0; - rawc.ptr.pp_double[i][n] = hqrndnormal(&rs, _state); - } - } - - /* - * Solve problem analytically using Lagrangian approach - */ - ae_matrix_set_length(&z, n+rawccnt, n+rawccnt, _state); - ae_vector_set_length(&r, n+rawccnt, _state); - for(i=0; i<=n+rawccnt-1; i++) - { - for(j=0; j<=n+rawccnt-1; j++) - { - z.ptr.pp_double[i][j] = (double)(0); - } - r.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - z.ptr.pp_double[i][j] = rawa.ptr.pp_double[i][j]; - } - } - for(i=0; i<=n-1; i++) - { - r.ptr.p_double[i] = -b.ptr.p_double[i]; - } - for(i=0; i<=rawccnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - z.ptr.pp_double[n+i][j] = rawc.ptr.pp_double[i][j]; - z.ptr.pp_double[j][n+i] = rawc.ptr.pp_double[i][j]; - } - r.ptr.p_double[n+i] = rawc.ptr.pp_double[i][n]; - } - rmatrixsolve(&z, n+rawccnt, &r, &k, &svrep, &xsol, _state); - ae_assert(k>0, "MinQPTest: integrity check failed", _state); - - /* - * Generate scale vector, apply it - */ - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = ae_pow((double)(10), hqrnduniformr(&rs, _state)*20-10, _state); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - rawa.ptr.pp_double[i][j] = rawa.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]); - } - b.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i]; - x0.ptr.p_double[i] = x0.ptr.p_double[i]*s.ptr.p_double[i]; - xsol.ptr.p_double[i] = xsol.ptr.p_double[i]*s.ptr.p_double[i]; - } - for(i=0; i<=rawccnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - rawc.ptr.pp_double[i][j] = rawc.ptr.pp_double[i][j]/s.ptr.p_double[j]; - } - } - - /* - * Multiply A/B by some coefficient with wild magnitude - */ - v = ae_pow((double)(10), (double)(10*scaletype), _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - rawa.ptr.pp_double[i][j] = rawa.ptr.pp_double[i][j]*v; - } - b.ptr.p_double[i] = b.ptr.p_double[i]*v; - } - - /* - * Create optimizer, solve - */ - rho = 100.0; - outerits = 3; - minqpcreate(n, &state, _state); - minqpsetalgodenseaul(&state, epsx, rho, outerits, _state); - minqpsetlinearterm(&state, &b, _state); - testminqpunit_randomlyselectconvertandsetquadraticterm(&rawa, n, &state, &rs, _state); - testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, rawccnt, n, &state, &rs, _state); - minqpsetscale(&state, &s, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xf, &rep, _state); - - /* - * Compare against analytically known solution - */ - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:7724"); - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xf.ptr.p_double[i]-xsol.ptr.p_double[i], _state)/s.ptr.p_double[i],xtol), __FILE__, __LINE__, "testminqpunit.ap:7728"); - } - } - } - - /* - * Test that problem with slight negative curvature f = -0.001*|x|^2 - * subject to general linear (!) constraints -1 <= x[i] <= +1 is - * correctly solved. Initial point is in [-0.001,+0.001] range. - * - * NOTE: this test is mostly intended for working set selection algorithm; - * it must correctly detect non-SPD problems and select full working - * set; starting with zero working set will result in recognition of - * problem as unbounded one and premature termination of algorithm. - */ - epsx = 1.0E-12; - xtol = 1.0E-6; - for(n=1; n<=10; n++) - { - - /* - * Generate A, b, X0, constraints - */ - ae_matrix_set_length(&rawa, n, n, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - rawa.ptr.pp_double[i][j] = (double)(0); - } - rawa.ptr.pp_double[i][i] = -0.001; - b.ptr.p_double[i] = (double)(0); - x0.ptr.p_double[i] = 0.001*hqrndnormal(&rs, _state); - } - ae_matrix_set_length(&rawc, 2*n, n+1, _state); - ae_vector_set_length(&rawct, 2*n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n; j++) - { - rawc.ptr.pp_double[2*i+0][j] = (double)(0); - rawc.ptr.pp_double[2*i+1][j] = (double)(0); - } - rawc.ptr.pp_double[2*i+0][i] = (double)(1); - rawc.ptr.pp_double[2*i+1][i] = (double)(1); - rawc.ptr.pp_double[2*i+0][n] = (double)(-1); - rawc.ptr.pp_double[2*i+1][n] = (double)(1); - rawct.ptr.p_int[2*i+0] = 1; - rawct.ptr.p_int[2*i+1] = -1; - } - - /* - * Create optimizer, solve - */ - rho = 100.0; - outerits = 5; - minqpcreate(n, &state, _state); - minqpsetalgodenseaul(&state, epsx, rho, outerits, _state); - minqpsetstartingpoint(&state, &x0, _state); - minqpsetquadraticterm(&state, &rawa, ae_true, _state); - minqpsetlinearterm(&state, &b, _state); - minqpsetlc(&state, &rawc, &rawct, 2*n, _state); - minqpoptimize(&state, _state); - minqpresults(&state, &xf, &rep, _state); - - /* - * Test - */ - ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:7793"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(ae_fabs(xf.ptr.p_double[i], _state)-1, _state),xtol), __FILE__, __LINE__, "testminqpunit.ap:7797"); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests IPM QP solver - -On failure sets Err to True; on success leaves it unchanged. -*************************************************************************/ -static void testminqpunit_ipmtests(ae_bool* errorflag, ae_state *_state) -{ - ae_frame _frame_block; - hqrndstate rs; - ae_int_t n; - ae_int_t nmain; - ae_int_t nslack; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - ae_int_t nnz; - ae_int_t nactive; - double f0; - double f1; - ae_matrix maina; - ae_matrix fulla; - ae_vector s; - ae_vector xorigin; - ae_vector xf; - ae_vector x1; - ae_vector g; - ae_vector b; - ae_vector gtrial; - ae_vector bndl; - ae_vector bndu; - ae_int_t akind; - ae_matrix rawc; - ae_vector rawcl; - ae_vector rawcu; - ae_int_t rawccnt; - sparsematrix sparsec; - ae_int_t sparseccnt; - ae_matrix densec; - ae_int_t denseccnt; - ae_bool issemidefinite; - ae_vector tmp; - ae_vector lagbc; - ae_vector laglc; - sparsematrix dummysparse; - vipmstate vsolver; - ae_vector replagbc; - ae_vector replaglc; - ae_int_t repterminationtype; - double epsx; - double xtol; - ae_vector xsol; - ae_vector x0; - ae_vector rawct; - minqpstate state; - minqpreport rep; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - memset(&maina, 0, sizeof(maina)); - memset(&fulla, 0, sizeof(fulla)); - memset(&s, 0, sizeof(s)); - memset(&xorigin, 0, sizeof(xorigin)); - memset(&xf, 0, sizeof(xf)); - memset(&x1, 0, sizeof(x1)); - memset(&g, 0, sizeof(g)); - memset(&b, 0, sizeof(b)); - memset(>rial, 0, sizeof(gtrial)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&rawc, 0, sizeof(rawc)); - memset(&rawcl, 0, sizeof(rawcl)); - memset(&rawcu, 0, sizeof(rawcu)); - memset(&sparsec, 0, sizeof(sparsec)); - memset(&densec, 0, sizeof(densec)); - memset(&tmp, 0, sizeof(tmp)); - memset(&lagbc, 0, sizeof(lagbc)); - memset(&laglc, 0, sizeof(laglc)); - memset(&dummysparse, 0, sizeof(dummysparse)); - memset(&vsolver, 0, sizeof(vsolver)); - memset(&replagbc, 0, sizeof(replagbc)); - memset(&replaglc, 0, sizeof(replaglc)); - memset(&xsol, 0, sizeof(xsol)); - memset(&x0, 0, sizeof(x0)); - memset(&rawct, 0, sizeof(rawct)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - _hqrndstate_init(&rs, _state, ae_true); - ae_matrix_init(&maina, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&fulla, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xorigin, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&g, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(>rial, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&rawc, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rawcl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rawcu, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&sparsec, _state, ae_true); - ae_matrix_init(&densec, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&lagbc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&laglc, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&dummysparse, _state, ae_true); - _vipmstate_init(&vsolver, _state, ae_true); - ae_vector_init(&replagbc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&replaglc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xsol, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rawct, 0, DT_INT, _state, ae_true); - _minqpstate_init(&state, _state, ae_true); - _minqpreport_init(&rep, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Test handling of slack variables by IPM solver. We use IPM directly, - * without wrapping it with MinQP interface layer. - * - * Convex optimization problem with known answer (we generate constraints - * and Lagrange coefficients, and then generate quadratic and linear term - * which satisfy KKT conditions for given Lagrange coefficients): - * - * * N=2..8 - * * f = 0.5*x'*A*x+b'*x - * * several kinds of A are tried: zero, well conditioned SPD, low rank - * * initial point x0 = [0 0 ... 0 0] - * * first, we generate set of linear constraints (without bounds), - * solution point X and Lagrange multipliers for linear and box constraints - * * then we determine bounds on variables and linear constraints which - * align with values/signs of Lagrange multipliers - * * then, having quadratic term A and known constraints and Lagrange - * multipliers we determine linear term B which makes KKT conditions true - */ - epsx = 1.0E-12; - for(nmain=1; nmain<=8; nmain++) - { - for(nslack=0; nslack<=8; nslack++) - { - for(akind=0; akind<=2; akind++) - { - n = nmain+nslack; - - /* - * Generate quadratic term A, origin and scale - */ - ae_matrix_set_length(&maina, nmain, nmain, _state); - for(i=0; i<=nmain-1; i++) - { - for(j=0; j<=nmain-1; j++) - { - maina.ptr.pp_double[i][j] = 0.0; - } - } - issemidefinite = ae_true; - if( akind==1 ) - { - - /* - * Dense well conditioned SPD - */ - spdmatrixrndcond(nmain, 50.0, &maina, _state); - issemidefinite = ae_false; - } - if( akind==2 ) - { - - /* - * Low rank semidefinite - */ - ae_vector_set_length(&tmp, nmain, _state); - for(i=0; i<=nmain-1; i++) - { - for(j=0; j<=nmain-1; j++) - { - maina.ptr.pp_double[i][j] = 0.0; - } - } - for(k=1; k<=ae_minint(3, nmain-1, _state); k++) - { - for(i=0; i<=nmain-1; i++) - { - tmp.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - v = ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - for(i=0; i<=nmain-1; i++) - { - for(j=0; j<=nmain-1; j++) - { - maina.ptr.pp_double[i][j] = maina.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j]; - } - } - } - issemidefinite = ae_true; - } - issemidefinite = issemidefinite||nslack>0; - ae_matrix_set_length(&fulla, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - fulla.ptr.pp_double[i][j] = 0.0; - } - } - for(i=0; i<=nmain-1; i++) - { - for(j=0; j<=nmain-1; j++) - { - fulla.ptr.pp_double[i][j] = maina.ptr.pp_double[i][j]; - } - } - ae_vector_set_length(&s, n, _state); - ae_vector_set_length(&xorigin, n, _state); - for(j=0; j<=n-1; j++) - { - xorigin.ptr.p_double[j] = hqrndnormal(&rs, _state); - s.ptr.p_double[j] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - } - - /* - * Generate linear constraints (left parts) - */ - rawccnt = hqrnduniformi(&rs, 2*n+1, _state); - if( rawccnt>0 ) - { - ae_matrix_set_length(&rawc, rawccnt, n, _state); - for(i=0; i<=rawccnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - rawc.ptr.pp_double[i][j] = (double)(0); - } - nnz = hqrnduniformi(&rs, nmain+1, _state); - for(k=0; k<=nnz-1; k++) - { - j = hqrnduniformi(&rs, nmain, _state); - v = hqrndnormal(&rs, _state); - v = v+0.1*possign(v, _state); - rawc.ptr.pp_double[i][j] = v; - } - } - for(j=nmain; j<=n-1; j++) - { - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - v = hqrndnormal(&rs, _state); - v = v+0.1*possign(v, _state); - rawc.ptr.pp_double[hqrnduniformi(&rs, rawccnt, _state)][j] = v; - } - } - } - - /* - * Generate Lagrange multipliers, with 0<=NActive<=N-1 being non-zero - */ - ae_vector_set_length(&lagbc, n, _state); - ae_vector_set_length(&laglc, rawccnt, _state); - for(i=0; i<=n-1; i++) - { - lagbc.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=rawccnt-1; i++) - { - laglc.ptr.p_double[i] = (double)(0); - } - nactive = hqrnduniformi(&rs, n, _state); - k = hqrnduniformi(&rs, ae_minint(nactive, rawccnt, _state)+1, _state); - for(i=0; i<=k-1; i++) - { - v = hqrndnormal(&rs, _state); - v = v+0.01*possign(v, _state); - laglc.ptr.p_double[hqrnduniformi(&rs, rawccnt, _state)] = v; - } - for(i=k; i<=nactive-1; i++) - { - v = hqrndnormal(&rs, _state); - v = v+0.01*possign(v, _state); - lagbc.ptr.p_double[hqrnduniformi(&rs, n, _state)] = v; - } - - /* - * Generate solution and gradient at the solution, set B to -G - */ - ae_vector_set_length(&xf, n, _state); - for(i=0; i<=n-1; i++) - { - xf.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&g, n, _state); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+fulla.ptr.pp_double[i][j]*(xf.ptr.p_double[j]-xorigin.ptr.p_double[j]); - } - g.ptr.p_double[i] = v; - } - for(i=0; i<=n-1; i++) - { - g.ptr.p_double[i] = g.ptr.p_double[i]+lagbc.ptr.p_double[i]; - } - for(i=0; i<=rawccnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - g.ptr.p_double[j] = g.ptr.p_double[j]+laglc.ptr.p_double[i]*rawc.ptr.pp_double[i][j]; - } - } - ae_vector_set_length(&b, n, _state); - for(j=0; j<=n-1; j++) - { - b.ptr.p_double[j] = -g.ptr.p_double[j]; - } - - /* - * Set up bounds according to Lagrange multipliers - * - * NOTE: for semidefinite problems we set all variable bounds - */ - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - for(j=0; j<=n-1; j++) - { - bndl.ptr.p_double[j] = _state->v_neginf; - bndu.ptr.p_double[j] = _state->v_posinf; - if( (ae_fp_greater(hqrndnormal(&rs, _state),(double)(0))||issemidefinite)||j>=nmain ) - { - bndl.ptr.p_double[j] = xf.ptr.p_double[j]-ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - } - if( (ae_fp_greater(hqrndnormal(&rs, _state),(double)(0))||issemidefinite)||j>=nmain ) - { - bndu.ptr.p_double[j] = xf.ptr.p_double[j]+ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - } - if( ae_fp_neq(lagbc.ptr.p_double[j],(double)(0)) ) - { - if( ae_fp_less(hqrnduniformr(&rs, _state),0.15) ) - { - bndl.ptr.p_double[j] = xf.ptr.p_double[j]; - bndu.ptr.p_double[j] = xf.ptr.p_double[j]; - } - else - { - if( ae_fp_less(lagbc.ptr.p_double[j],(double)(0)) ) - { - bndl.ptr.p_double[j] = xf.ptr.p_double[j]; - } - if( ae_fp_greater(lagbc.ptr.p_double[j],(double)(0)) ) - { - bndu.ptr.p_double[j] = xf.ptr.p_double[j]; - } - } - } - } - ae_vector_set_length(&rawcl, rawccnt, _state); - ae_vector_set_length(&rawcu, rawccnt, _state); - for(i=0; i<=rawccnt-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+rawc.ptr.pp_double[i][j]*xf.ptr.p_double[j]; - } - rawcl.ptr.p_double[i] = _state->v_neginf; - rawcu.ptr.p_double[i] = _state->v_posinf; - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - rawcl.ptr.p_double[i] = v-ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - } - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - rawcu.ptr.p_double[i] = v+ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - } - if( ae_fp_neq(laglc.ptr.p_double[i],(double)(0)) ) - { - if( ae_fp_less(hqrnduniformr(&rs, _state),0.15) ) - { - - /* - * Active equality constraint - */ - rawcl.ptr.p_double[i] = v; - rawcu.ptr.p_double[i] = v; - } - else - { - - /* - * Active inequality constraint - */ - if( ae_fp_less(laglc.ptr.p_double[i],(double)(0)) ) - { - rawcl.ptr.p_double[i] = v; - } - if( ae_fp_greater(laglc.ptr.p_double[i],(double)(0)) ) - { - rawcu.ptr.p_double[i] = v; - } - } - } - if( !ae_isfinite(rawcl.ptr.p_double[i], _state)&&!ae_isfinite(rawcu.ptr.p_double[i], _state) ) - { - - /* - * At least one bound must be present for linear constraint - */ - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - rawcl.ptr.p_double[i] = v-10; - } - else - { - rawcu.ptr.p_double[i] = v+10; - } - } - } - - /* - * Randomly split constraints into dense and sparse parts - */ - sparseccnt = hqrnduniformi(&rs, rawccnt+1, _state); - denseccnt = rawccnt-sparseccnt; - if( sparseccnt>0 ) - { - sparsecreate(sparseccnt, n, 0, &sparsec, _state); - for(i=0; i<=sparseccnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - sparseset(&sparsec, i, j, rawc.ptr.pp_double[i][j], _state); - } - } - sparseconverttocrs(&sparsec, _state); - } - if( denseccnt>0 ) - { - ae_matrix_set_length(&densec, denseccnt, n, _state); - for(i=0; i<=denseccnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - densec.ptr.pp_double[i][j] = rawc.ptr.pp_double[i+sparseccnt][j]; - } - } - } - - /* - * Solve - */ - vipminitdensewithslacks(&vsolver, &s, &xorigin, nmain, n, _state); - vipmsetquadraticlinear(&vsolver, &fulla, &dummysparse, 0, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &b, _state); - vipmsetconstraints(&vsolver, &bndl, &bndu, &sparsec, sparseccnt, &densec, denseccnt, &rawcl, &rawcu, _state); - vipmsetcond(&vsolver, epsx, epsx, epsx, _state); - vipmoptimize(&vsolver, ae_false, &x1, &replagbc, &replaglc, &repterminationtype, _state); - ae_set_error_flag(errorflag, repterminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:8123"); - ae_set_error_flag(errorflag, x1.cntptr.p_double[i],bndl->ptr.p_double[i])&&ae_fp_less_eq(x->ptr.p_double[i],bndu->ptr.p_double[i]), "ProjectedAntiGradNormal: boundary constraints violation", _state); - if( ((ae_fp_greater(x->ptr.p_double[i],bndl->ptr.p_double[i])&&ae_fp_less(x->ptr.p_double[i],bndu->ptr.p_double[i]))||(ae_fp_eq(x->ptr.p_double[i],bndl->ptr.p_double[i])&&ae_fp_greater(-g->ptr.p_double[i],(double)(0))))||(ae_fp_eq(x->ptr.p_double[i],bndu->ptr.p_double[i])&&ae_fp_less(-g->ptr.p_double[i],(double)(0))) ) - { - r = r+g->ptr.p_double[i]*g->ptr.p_double[i]; - } - } - result = ae_sqrt(r, _state); - return result; -} - - -/************************************************************************* -This function tests that norm of bound-constrained gradient at point X is -less than Eps: -* unconstrained gradient is A*x+b -* if I-th component is at the boundary, and antigradient points outside of - the feasible area, I-th component of constrained gradient is zero - -This function accepts QP terms A and B, bound constraints, current point, -and performs test. Additionally, it checks that point is feasible w.r.t. -boundary constraints. - -In case of failure, error flag is set. Otherwise, it is not modified. - -IMPORTANT: this function does NOT use SetErrorFlag() to modify flag. - If you want to use SetErrorFlag() for easier tracking of errors, - you should store flag returned by this function into separate - variable TmpFlag and call SetErrorFlag(ErrorFlag, TmpFlag) yourself. -*************************************************************************/ -static void testminqpunit_testbcgradandfeasibility(/* Real */ ae_matrix* a, - /* Real */ ae_vector* b, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_int_t n, - /* Real */ ae_vector* x, - double eps, - ae_bool* errorflag, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double g; - double gnorm; - - - gnorm = 0.0; - for(i=0; i<=n-1; i++) - { - g = b->ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - g = g+a->ptr.pp_double[i][j]*x->ptr.p_double[j]; - } - if( ae_fp_eq(x->ptr.p_double[i],bndl->ptr.p_double[i])&&ae_fp_greater(g,(double)(0)) ) - { - g = (double)(0); - } - if( ae_fp_eq(x->ptr.p_double[i],bndu->ptr.p_double[i])&&ae_fp_less(g,(double)(0)) ) - { - g = (double)(0); - } - gnorm = gnorm+ae_sqr(g, _state); - if( ae_fp_less(x->ptr.p_double[i],bndl->ptr.p_double[i]) ) - { - *errorflag = ae_true; - } - if( ae_fp_greater(x->ptr.p_double[i],bndu->ptr.p_double[i]) ) - { - *errorflag = ae_true; - } - } - gnorm = ae_sqrt(gnorm, _state); - if( ae_fp_greater(gnorm,eps) ) - { - *errorflag = ae_true; - } -} - - -/************************************************************************* -set random type of the QP solver. -All "modern" solvers can be chosen. - -OUTPUT PARAMETERS: - BCTol - expected precision of box constraints handling assuming - unit scale of variables. - LCTol - expected precinion of linear constraints handling assuming - unit scale of variables. - -RESULT: - Solver type: - *-1 for QuickQP - * 0 for BLEIC-QP - * 1 for DENSE-AUL - * 2 for DENSE-IPM - * 3 for SPARSE-IPM - -BCTol and LCTol have following meaning - if some constraint is active, it -means that we should be at most TOL units away from boundary. It is possible -that zero value is returned. - -From definition it follows that if we stopped at more than TOL units away -from the boundary, gradient in corresponding direction is nearly zero. -*************************************************************************/ -static ae_int_t testminqpunit_setrandomalgoallmodern(minqpstate* s, - double* bctol, - double* lctol, - ae_state *_state) -{ - ae_int_t result; - - *bctol = 0; - *lctol = 0; - - result = ae_randominteger(5, _state)-1; - if( result==-1 ) - { - minqpsetalgoquickqp(s, 1.0E-12, 0.0, 0.0, 0, ae_fp_greater(ae_randomreal(_state),0.5), _state); - *bctol = (double)(0); - *lctol = (double)(0); - } - if( result==0 ) - { - minqpsetalgobleic(s, 1.0E-12, 0.0, 0.0, 0, _state); - *bctol = (double)(0); - *lctol = 1.0E-8; - } - if( result==1 ) - { - minqpsetalgodenseaul(s, 1.0E-12, 1000.0, 10, _state); - *bctol = 1.0E-3; - *lctol = 1.0E-3; - } - if( result==2 ) - { - minqpsetalgodenseipm(s, 1.0E-12, _state); - *bctol = 1.0E-3; - *lctol = 1.0E-3; - } - if( result==3 ) - { - minqpsetalgosparseipm(s, 1.0E-12, _state); - *bctol = 1.0E-3; - *lctol = 1.0E-3; - } - return result; -} - - -/************************************************************************* -set random type of theQP solver -*************************************************************************/ -static void testminqpunit_setrandomalgononconvex(minqpstate* s, - ae_state *_state) -{ - ae_int_t i; - - - i = 1+ae_randominteger(2, _state); - if( i==1 ) - { - minqpsetalgobleic(s, 1.0E-12, 0.0, 0.0, 0, _state); - } - if( i==2 ) - { - minqpsetalgoquickqp(s, 1.0E-12, 0.0, 0.0, 0, ae_fp_greater(ae_randomreal(_state),0.5), _state); - } -} - - -/************************************************************************* -set random type of theQP solver -*************************************************************************/ -static void testminqpunit_setrandomalgosemidefinite(minqpstate* s, - double* bctol, - double* lctol, - ae_state *_state) -{ - ae_int_t i; - - *bctol = 0; - *lctol = 0; - - i = 1+ae_randominteger(4, _state); - if( i==1 ) - { - minqpsetalgobleic(s, 1.0E-12, 0.0, 0.0, 0, _state); - *bctol = (double)(0); - *lctol = 1.0E-8; - } - if( i==2 ) - { - minqpsetalgoquickqp(s, 1.0E-12, 0.0, 0.0, 0, ae_fp_greater(ae_randomreal(_state),0.5), _state); - *bctol = (double)(0); - *lctol = (double)(0); - } - if( i==3 ) - { - minqpsetalgodenseipm(s, 1.0E-12, _state); - *bctol = 1.0E-3; - *lctol = 1.0E-3; - } - if( i==4 ) - { - minqpsetalgosparseipm(s, 1.0E-12, _state); - *bctol = 1.0E-3; - *lctol = 1.0E-3; - } -} - - -/************************************************************************* -set random type of the QP solver, must support boundary constraints -*************************************************************************/ -static void testminqpunit_setrandomalgobc(minqpstate* s, ae_state *_state) -{ - ae_int_t i; - - - i = ae_randominteger(2, _state); - if( i==0 ) - { - minqpsetalgoquickqp(s, 0.0, 0.0, 1.0E-13, 0, ae_true, _state); - } - if( i==1 ) - { - minqpsetalgobleic(s, 1.0E-12, 0.0, 0.0, 0, _state); - } -} - - -/************************************************************************* -set random type of the QP solver, -must support convex problems with boundary/linear constraints -*************************************************************************/ -static void testminqpunit_setrandomalgoconvexlc(minqpstate* s, - ae_state *_state) -{ - ae_int_t i; - - - i = ae_randominteger(4, _state); - if( i==0 ) - { - minqpsetalgodenseaul(s, 1.0E-12, (double)(10000), 15, _state); - } - if( i==1 ) - { - minqpsetalgobleic(s, 0.0, 0.0, 1.0E-12, 0, _state); - } - if( i==2 ) - { - minqpsetalgodenseipm(s, 1.0E-12, _state); - } - if( i==3 ) - { - minqpsetalgosparseipm(s, 1.0E-12, _state); - } -} - - -/************************************************************************* -set random type of the QP solver, -must support nonconvex problems with boundary/linear constraints -*************************************************************************/ -static void testminqpunit_setrandomalgononconvexlc(minqpstate* s, - ae_state *_state) -{ - ae_int_t i; - - - i = ae_randominteger(1, _state); - if( i==0 ) - { - minqpsetalgobleic(s, 1.0E-12, 0.0, 0.0, 0, _state); - } -} - - -/************************************************************************* -Convert dense matrix to sparse matrix using random format -*************************************************************************/ -static void testminqpunit_densetosparse(/* Real */ ae_matrix* a, - ae_int_t n, - sparsematrix* s, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - sparsematrix s0; - - ae_frame_make(_state, &_frame_block); - memset(&s0, 0, sizeof(s0)); - _sparsematrix_clear(s); - _sparsematrix_init(&s0, _state, ae_true); - - sparsecreate(n, n, n*n, &s0, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - sparseset(&s0, i, j, a->ptr.pp_double[i][j], _state); - } - } - sparsecopytobuf(&s0, ae_randominteger(3, _state), s, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Randomly split constraints into dense and sparse parts -*************************************************************************/ -static void testminqpunit_randomlysplitlc(/* Real */ ae_matrix* rawc, - /* Integer */ ae_vector* rawct, - ae_int_t rawccnt, - ae_int_t n, - sparsematrix* sparsec, - /* Integer */ ae_vector* sparsect, - ae_int_t* sparseccnt, - /* Real */ ae_matrix* densec, - /* Integer */ ae_vector* densect, - ae_int_t* denseccnt, - hqrndstate* rs, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - _sparsematrix_clear(sparsec); - ae_vector_clear(sparsect); - *sparseccnt = 0; - ae_matrix_clear(densec); - ae_vector_clear(densect); - *denseccnt = 0; - - - /* - * Split "raw" constraints into dense and sparse parts - */ - *sparseccnt = hqrnduniformi(rs, rawccnt+1, _state); - *denseccnt = rawccnt-(*sparseccnt); - if( *sparseccnt>0 ) - { - sparsecreate(*sparseccnt, n+1, 0, sparsec, _state); - ae_vector_set_length(sparsect, *sparseccnt, _state); - for(i=0; i<=*sparseccnt-1; i++) - { - for(j=0; j<=n; j++) - { - sparseset(sparsec, i, j, rawc->ptr.pp_double[i][j], _state); - } - sparsect->ptr.p_int[i] = rawct->ptr.p_int[i]; - } - } - if( *denseccnt>0 ) - { - ae_matrix_set_length(densec, *denseccnt, n+1, _state); - ae_vector_set_length(densect, *denseccnt, _state); - for(i=0; i<=*denseccnt-1; i++) - { - for(j=0; j<=n; j++) - { - densec->ptr.pp_double[i][j] = rawc->ptr.pp_double[*sparseccnt+i][j]; - } - densect->ptr.p_int[i] = rawct->ptr.p_int[*sparseccnt+i]; - } - } -} - - -/************************************************************************* -Randomly split constraints into dense and sparse parts and set them; -legacy API is used. -*************************************************************************/ -static void testminqpunit_randomlysplitandsetlclegacy(/* Real */ ae_matrix* rawc, - /* Integer */ ae_vector* rawct, - ae_int_t rawccnt, - ae_int_t n, - minqpstate* state, - hqrndstate* rs, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix densec; - ae_vector densect; - sparsematrix sparsec; - ae_vector sparsect; - ae_int_t denseccnt; - ae_int_t sparseccnt; - - ae_frame_make(_state, &_frame_block); - memset(&densec, 0, sizeof(densec)); - memset(&densect, 0, sizeof(densect)); - memset(&sparsec, 0, sizeof(sparsec)); - memset(&sparsect, 0, sizeof(sparsect)); - ae_matrix_init(&densec, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&densect, 0, DT_INT, _state, ae_true); - _sparsematrix_init(&sparsec, _state, ae_true); - ae_vector_init(&sparsect, 0, DT_INT, _state, ae_true); - - - /* - * reset constraints - */ - minqpsetlc(state, &densec, &densect, 0, _state); - - /* - * split and set - */ - testminqpunit_randomlysplitlc(rawc, rawct, rawccnt, n, &sparsec, &sparsect, &sparseccnt, &densec, &densect, &denseccnt, rs, _state); - if( ae_fp_greater(hqrnduniformr(rs, _state),0.5)||denseccnt*sparseccnt>0 ) - { - minqpsetlcmixed(state, &sparsec, &sparsect, sparseccnt, &densec, &densect, denseccnt, _state); - } - else - { - if( denseccnt>0 ) - { - minqpsetlc(state, &densec, &densect, denseccnt, _state); - } - if( sparseccnt>0 ) - { - minqpsetlcsparse(state, &sparsec, &sparsect, sparseccnt, _state); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Randomly split 2-sided constraints into dense and sparse parts and set them; -*************************************************************************/ -static void testminqpunit_randomlysplitandsetlc2(/* Real */ ae_matrix* rawc, - /* Real */ ae_vector* rawcl, - /* Real */ ae_vector* rawcu, - ae_int_t rawccnt, - ae_int_t n, - minqpstate* state, - hqrndstate* rs, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix densec; - ae_vector densecl; - ae_vector densecu; - sparsematrix sparsec; - ae_vector sparsecl; - ae_vector sparsecu; - ae_vector wrkcl; - ae_vector wrkcu; - ae_int_t denseccnt; - ae_int_t sparseccnt; - ae_int_t i; - ae_int_t j; - ae_int_t appenddense; - ae_int_t appendsparse; - ae_vector cv; - ae_vector ci; - ae_int_t nnz; - - ae_frame_make(_state, &_frame_block); - memset(&densec, 0, sizeof(densec)); - memset(&densecl, 0, sizeof(densecl)); - memset(&densecu, 0, sizeof(densecu)); - memset(&sparsec, 0, sizeof(sparsec)); - memset(&sparsecl, 0, sizeof(sparsecl)); - memset(&sparsecu, 0, sizeof(sparsecu)); - memset(&wrkcl, 0, sizeof(wrkcl)); - memset(&wrkcu, 0, sizeof(wrkcu)); - memset(&cv, 0, sizeof(cv)); - memset(&ci, 0, sizeof(ci)); - ae_matrix_init(&densec, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&densecl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&densecu, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&sparsec, _state, ae_true); - ae_vector_init(&sparsecl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sparsecu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wrkcl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wrkcu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cv, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ci, 0, DT_INT, _state, ae_true); - - - /* - * reset constraints - */ - minqpsetlc2dense(state, &densec, &densecl, &densecu, 0, _state); - - /* - * Split "raw" constraints into dense and sparse parts - */ - sparseccnt = hqrnduniformi(rs, rawccnt+1, _state); - denseccnt = rawccnt-sparseccnt; - appenddense = hqrnduniformi(rs, denseccnt+1, _state); - denseccnt = denseccnt-appenddense; - appendsparse = hqrnduniformi(rs, sparseccnt+1, _state); - sparseccnt = sparseccnt-appendsparse; - ae_vector_set_length(&wrkcl, sparseccnt+denseccnt, _state); - ae_vector_set_length(&wrkcu, sparseccnt+denseccnt, _state); - if( sparseccnt>0 ) - { - sparsecreate(sparseccnt, n, 0, &sparsec, _state); - ae_vector_set_length(&sparsecl, sparseccnt, _state); - ae_vector_set_length(&sparsecu, sparseccnt, _state); - for(i=0; i<=sparseccnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - sparseset(&sparsec, i, j, rawc->ptr.pp_double[i][j], _state); - } - sparsecl.ptr.p_double[i] = rawcl->ptr.p_double[i]; - sparsecu.ptr.p_double[i] = rawcu->ptr.p_double[i]; - wrkcl.ptr.p_double[i] = sparsecl.ptr.p_double[i]; - wrkcu.ptr.p_double[i] = sparsecu.ptr.p_double[i]; - } - } - if( denseccnt>0 ) - { - ae_matrix_set_length(&densec, denseccnt, n, _state); - ae_vector_set_length(&densecl, denseccnt, _state); - ae_vector_set_length(&densecu, denseccnt, _state); - for(i=0; i<=denseccnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - densec.ptr.pp_double[i][j] = rawc->ptr.pp_double[sparseccnt+appendsparse+i][j]; - } - densecl.ptr.p_double[i] = rawcl->ptr.p_double[sparseccnt+appendsparse+i]; - densecu.ptr.p_double[i] = rawcu->ptr.p_double[sparseccnt+appendsparse+i]; - wrkcl.ptr.p_double[sparseccnt+i] = densecl.ptr.p_double[i]; - wrkcu.ptr.p_double[sparseccnt+i] = densecu.ptr.p_double[i]; - } - } - - /* - * split and set - */ - if( ae_fp_greater(hqrnduniformr(rs, _state),0.5)||denseccnt*sparseccnt>0 ) - { - minqpsetlc2mixed(state, &sparsec, sparseccnt, &densec, denseccnt, &wrkcl, &wrkcu, _state); - } - else - { - if( denseccnt>0 ) - { - minqpsetlc2dense(state, &densec, &densecl, &densecu, denseccnt, _state); - } - if( sparseccnt>0 ) - { - minqpsetlc2(state, &sparsec, &sparsecl, &sparsecu, sparseccnt, _state); - } - } - ae_vector_set_length(&cv, 2*n, _state); - ae_vector_set_length(&ci, 2*n, _state); - for(i=sparseccnt; i<=sparseccnt+appendsparse-1; i++) - { - - /* - * Generate sparse representation - */ - nnz = 0; - for(j=0; j<=n-1; j++) - { - if( ae_fp_neq(rawc->ptr.pp_double[i][j],(double)(0)) ) - { - cv.ptr.p_double[nnz] = rawc->ptr.pp_double[i][j]; - ci.ptr.p_int[nnz] = j; - nnz = nnz+1; - } - } - - /* - * Add duplicates which do not change constraint (after simplification) - */ - while((nnz>0&&nnzptr.p_double[i], rawcu->ptr.p_double[i], _state); - } - for(i=rawccnt-appenddense; i<=rawccnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - cv.ptr.p_double[j] = rawc->ptr.pp_double[i][j]; - } - minqpaddlc2dense(state, &cv, rawcl->ptr.p_double[i], rawcu->ptr.p_double[i], _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Randomly selects triangle of full symmetric matrix, converts it to one of -the matrix storage formats (dense or sparse) and sets. -*************************************************************************/ -static void testminqpunit_randomlyselectconvertandsetquadraticterm(/* Real */ ae_matrix* a, - ae_int_t n, - minqpstate* state, - hqrndstate* rs, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_matrix densea; - sparsematrix sparsea; - ae_bool isupper; - ae_bool isdense; - - ae_frame_make(_state, &_frame_block); - memset(&densea, 0, sizeof(densea)); - memset(&sparsea, 0, sizeof(sparsea)); - ae_matrix_init(&densea, 0, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&sparsea, _state, ae_true); - - isupper = ae_fp_greater(hqrnduniformr(rs, _state),0.5); - isdense = ae_fp_greater(hqrnduniformr(rs, _state),0.5); - if( isupper&&isdense ) - { - ae_matrix_set_length(&densea, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - densea.ptr.pp_double[i][j] = a->ptr.pp_double[i][j]; - } - } - minqpsetquadraticterm(state, &densea, isupper, _state); - ae_frame_leave(_state); - return; - } - if( !isupper&&isdense ) - { - ae_matrix_set_length(&densea, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i; j++) - { - densea.ptr.pp_double[i][j] = a->ptr.pp_double[i][j]; - } - } - minqpsetquadraticterm(state, &densea, isupper, _state); - ae_frame_leave(_state); - return; - } - if( isupper&&!isdense ) - { - sparsecreate(n, n, 0, &sparsea, _state); - for(i=0; i<=n-1; i++) - { - for(j=i; j<=n-1; j++) - { - sparseset(&sparsea, i, j, a->ptr.pp_double[i][j], _state); - } - } - minqpsetquadratictermsparse(state, &sparsea, isupper, _state); - ae_frame_leave(_state); - return; - } - if( !isupper&&!isdense ) - { - sparsecreate(n, n, 0, &sparsea, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=i; j++) - { - sparseset(&sparsea, i, j, a->ptr.pp_double[i][j], _state); - } - } - minqpsetquadratictermsparse(state, &sparsea, isupper, _state); - ae_frame_leave(_state); - return; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function returns reciprocal of condition number of general linear -constraints. -*************************************************************************/ -static double testminqpunit_getconstraintrcond(/* Real */ ae_matrix* c, - ae_int_t k, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_bool bflag; - ae_vector svdw; - ae_matrix svdu; - ae_matrix svdvt; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&svdw, 0, sizeof(svdw)); - memset(&svdu, 0, sizeof(svdu)); - memset(&svdvt, 0, sizeof(svdvt)); - ae_vector_init(&svdw, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&svdu, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&svdvt, 0, 0, DT_REAL, _state, ae_true); - - bflag = rmatrixsvd(c, k, n, 0, 0, 0, &svdw, &svdu, &svdvt, _state); - ae_assert(bflag, "MinQPTest: integrity failure", _state); - if( ae_fp_greater(svdw.ptr.p_double[0],(double)(0)) ) - { - result = svdw.ptr.p_double[ae_minint(k, n, _state)-1]/svdw.ptr.p_double[0]; - } - else - { - result = (double)(1); - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Computes target function 0.5*x'*H*x+c'*x - - -- ALGLIB -- - Copyright 01.11.2019 by Bochkanov Sergey -*************************************************************************/ -static double testminqpunit_quadratictarget(/* Real */ ae_matrix* a, - /* Real */ ae_vector* b, - ae_int_t n, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double result; - - - result = (double)(0); - for(i=0; i<=n-1; i++) - { - result = result+b->ptr.p_double[i]*x->ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - result = result+0.5*x->ptr.p_double[i]*a->ptr.pp_double[i][j]*x->ptr.p_double[j]; - } - } - return result; -} - - - -static ae_int_t testminlpunit_solverscount = 2; -static void testminlpunit_basictests(ae_bool* err, ae_state *_state); -static void testminlpunit_singlecalltests(ae_bool* err, ae_state *_state); -static void testminlpunit_validatesolution(/* Real */ ae_vector* c, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - ae_int_t n, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t m, - /* Real */ ae_vector* xcand, - minlpreport* rep, - ae_int_t solvertype, - double* errprim, - double* errdual, - double* errslack, - ae_state *_state); -static void testminlpunit_generatelpproblem(hqrndstate* rs, - ae_int_t n, - /* Real */ ae_vector* c, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t* m, - ae_state *_state); -static void testminlpunit_generateunboundedlpproblem(hqrndstate* rs, - ae_int_t n, - /* Real */ ae_vector* c, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t* m, - ae_state *_state); -static void testminlpunit_generateinfeasiblelpproblem(hqrndstate* rs, - ae_int_t n, - /* Real */ ae_vector* c, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t* m, - ae_state *_state); -static void testminlpunit_generatecabxd(hqrndstate* rs, - ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* c, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* xx, - /* Real */ ae_vector* d, - /* Integer */ ae_vector* basicnonbasic, - ae_state *_state); -static void testminlpunit_generatebounds(hqrndstate* rs, - ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* xx, - /* Real */ ae_vector* d, - /* Integer */ ae_vector* basicnonbasic, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_state *_state); -static void testminlpunit_modifyandsendconstraintsto(ae_int_t n, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t m, - hqrndstate* rs, - minlpstate* state, - ae_state *_state); -static void testminlpunit_selectrandomsolver(minlpstate* state, - ae_state *_state); -static void testminlpunit_selectsolver(minlpstate* state, - ae_int_t st, - ae_state *_state); -static void testminlpunit_shiftfromzero(/* Real */ ae_vector* c, - ae_int_t n, - double s, - ae_state *_state); - - - - - -ae_bool testminlp(ae_bool silent, ae_state *_state) -{ - ae_bool basicerrors; - ae_bool singlecall; - ae_bool wereerrors; - ae_bool result; - - - basicerrors = ae_false; - singlecall = ae_false; - result = ae_true; - testminlpunit_basictests(&basicerrors, _state); - testminlpunit_singlecalltests(&singlecall, _state); - - /* - * report - */ - wereerrors = basicerrors||singlecall; - if( !silent ) - { - printf("TESTING MinLP\n"); - printf("BASIC TESTS "); - if( basicerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("COMMON TESTS:\n"); - printf("* single call usage "); - if( singlecall ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( wereerrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !wereerrors; - return result; -} - - -/************************************************************************* -Basic tests; sets error flag on failure, does not touch it on success. -*************************************************************************/ -static void testminlpunit_basictests(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t n; - ae_int_t ccnt; - ae_int_t pass; - minlpstate state; - minlpreport rep; - ae_vector c; - ae_vector x; - ae_vector x0; - ae_vector x2; - ae_vector bndl; - ae_vector bndu; - ae_vector al; - ae_vector au; - ae_matrix a; - double v0; - double v1; - double errslack; - double primtol; - double dualtol; - double slacktol; - ae_int_t solvertype; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&c, 0, sizeof(c)); - memset(&x, 0, sizeof(x)); - memset(&x0, 0, sizeof(x0)); - memset(&x2, 0, sizeof(x2)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&al, 0, sizeof(al)); - memset(&au, 0, sizeof(au)); - memset(&a, 0, sizeof(a)); - memset(&rs, 0, sizeof(rs)); - _minlpstate_init(&state, _state, ae_true); - _minlpreport_init(&rep, _state, ae_true); - ae_vector_init(&c, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&al, 0, DT_REAL, _state, ae_true); - ae_vector_init(&au, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - primtol = 1.0E-4; - dualtol = 1.0E-4; - slacktol = 1.0E-4; - hqrndrandomize(&rs, _state); - - /* - * Test default state of the solver - */ - for(pass=1; pass<=5; pass++) - { - n = 1+hqrnduniformi(&rs, 10, _state); - minlpcreate(n, &state, _state); - testminlpunit_selectrandomsolver(&state, _state); - minlpoptimize(&state, _state); - minlpresults(&state, &x, &rep, _state); - ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminlpunit.ap:100"); - ae_set_error_flag(err, x.cntv_posinf; - } - if( ae_fp_less(c.ptr.p_double[i],(double)(0)) ) - { - bndl.ptr.p_double[i] = _state->v_neginf; - } - } - testminlpunit_shiftfromzero(&c, n, 0.01, _state); - minlpcreate(n, &state, _state); - testminlpunit_selectsolver(&state, solvertype, _state); - minlpsetcost(&state, &c, _state); - minlpsetbc(&state, &bndl, &bndu, _state); - minlpoptimize(&state, _state); - minlpresults(&state, &x, &rep, _state); - ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminlpunit.ap:166"); - ae_set_error_flag(err, x.cntv_neginf; - bndu.ptr.p_double[k] = _state->v_posinf; - minlpcreate(n, &state, _state); - testminlpunit_selectsolver(&state, solvertype, _state); - minlpsetcost(&state, &c, _state); - minlpsetbc(&state, &bndl, &bndu, _state); - minlpoptimize(&state, _state); - minlpresults(&state, &x, &rep, _state); - ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminlpunit.ap:199"); - ae_set_error_flag(err, x.cntv_posinf; - minlpsetbc(&state, &bndl, &bndu, _state); - minlpoptimize(&state, _state); - minlpresults(&state, &x, &rep, _state); - ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminlpunit.ap:217"); - ae_set_error_flag(err, x.cntv_neginf; - bndu.ptr.p_double[k] = hqrndnormal(&rs, _state); - minlpsetbc(&state, &bndl, &bndu, _state); - minlpoptimize(&state, _state); - minlpresults(&state, &x, &rep, _state); - ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminlpunit.ap:236"); - ae_set_error_flag(err, x.cntv_neginf; - } - else - { - bndu.ptr.p_double[k] = _state->v_posinf; - } - minlpcreate(n, &state, _state); - testminlpunit_selectsolver(&state, solvertype, _state); - minlpsetcost(&state, &c, _state); - minlpsetbc(&state, &bndl, &bndu, _state); - minlpoptimize(&state, _state); - minlpresults(&state, &x, &rep, _state); - ae_set_error_flag(err, rep.terminationtype!=-4, __FILE__, __LINE__, "testminlpunit.ap:300"); - ae_set_error_flag(err, x.cnt=2, "LPTEST: integrity check failed", _state); - n0 = n/2; - ae_assert(n0ptr.p_double[i], _state) ) - { - *errprim = ae_maxreal(*errprim, bndl->ptr.p_double[i]-xcand->ptr.p_double[i], _state); - } - if( ae_isfinite(bndu->ptr.p_double[i], _state) ) - { - *errprim = ae_maxreal(*errprim, xcand->ptr.p_double[i]-bndu->ptr.p_double[i], _state); - } - } - for(i=0; i<=m-1; i++) - { - v = rdotvr(n, xcand, a, i, _state); - if( ae_isfinite(al->ptr.p_double[i], _state) ) - { - *errprim = ae_maxreal(*errprim, al->ptr.p_double[i]-v, _state); - } - if( ae_isfinite(au->ptr.p_double[i], _state) ) - { - *errprim = ae_maxreal(*errprim, v-au->ptr.p_double[i], _state); - } - } - - /* - * Test dual feasibility using Lagrange multipliers - */ - ae_vector_set_length(&d, n, _state); - for(i=0; i<=n-1; i++) - { - d.ptr.p_double[i] = c->ptr.p_double[i]; - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - d.ptr.p_double[j] = d.ptr.p_double[j]+rep->laglc.ptr.p_double[i]*a->ptr.pp_double[i][j]; - } - } - for(i=0; i<=n-1; i++) - { - d.ptr.p_double[i] = d.ptr.p_double[i]+rep->lagbc.ptr.p_double[i]; - } - *errdual = ae_maxreal(*errdual, rmaxabsv(n, &d, _state), _state); - - /* - * Test complementary slackness - */ - for(i=0; i<=n-1; i++) - { - if( ae_isfinite(bndl->ptr.p_double[i], _state) ) - { - *errslack = ae_maxreal(*errslack, ae_maxreal(xcand->ptr.p_double[i]-bndl->ptr.p_double[i], 0.0, _state)*ae_maxreal(-rep->lagbc.ptr.p_double[i], 0.0, _state), _state); - } - if( ae_isfinite(bndu->ptr.p_double[i], _state) ) - { - *errslack = ae_maxreal(*errslack, ae_maxreal(bndu->ptr.p_double[i]-xcand->ptr.p_double[i], 0.0, _state)*ae_maxreal(rep->lagbc.ptr.p_double[i], 0.0, _state), _state); - } - } - for(i=0; i<=m-1; i++) - { - v = rdotvr(n, xcand, a, i, _state); - if( ae_isfinite(al->ptr.p_double[i], _state) ) - { - *errslack = ae_maxreal(*errslack, ae_maxreal(v-al->ptr.p_double[i], 0.0, _state)*ae_maxreal(-rep->laglc.ptr.p_double[i], 0.0, _state), _state); - } - if( ae_isfinite(au->ptr.p_double[i], _state) ) - { - *errslack = ae_maxreal(*errslack, ae_maxreal(au->ptr.p_double[i]-v, 0.0, _state)*ae_maxreal(rep->laglc.ptr.p_double[i], 0.0, _state), _state); - } - } - - /* - * Test dual feasibility using Stats[] array - */ - if( checkstats ) - { - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function generates random LP problem with user-specified number of -variables, with several problem types being randomly chosen internally. - -Constraint counts and types are generated randomly; it is possible that -zero amount of constraints is generated. -*************************************************************************/ -static void testminlpunit_generatelpproblem(hqrndstate* rs, - ae_int_t n, - /* Real */ ae_vector* c, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t* m, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t ptype; - ae_int_t pcount; - ae_vector x0; - ae_vector xx; - ae_vector d; - ae_vector basicnonbasic; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t kk; - ae_int_t kt; - double v; - double q; - double big; - double mincoeff; - ae_int_t nprimal; - ae_int_t ndual; - - ae_frame_make(_state, &_frame_block); - memset(&x0, 0, sizeof(x0)); - memset(&xx, 0, sizeof(xx)); - memset(&d, 0, sizeof(d)); - memset(&basicnonbasic, 0, sizeof(basicnonbasic)); - ae_vector_clear(c); - ae_vector_clear(bndl); - ae_vector_clear(bndu); - ae_matrix_clear(a); - ae_vector_clear(al); - ae_vector_clear(au); - *m = 0; - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&basicnonbasic, 0, DT_INT, _state, ae_true); - - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(c, n, _state); - ae_vector_set_length(bndl, n, _state); - ae_vector_set_length(bndu, n, _state); - - /* - * Choose problem type - */ - pcount = 4; - ptype = hqrnduniformi(rs, pcount, _state); - mincoeff = 0.001; - - /* - * A linearly constrained LP problem with all variables/linear constraints - * being boxed (easy start). - */ - if( ptype==0 ) - { - q = 5.0; - *m = 1+hqrnduniformi(rs, 2*n, _state); - ae_matrix_set_length(a, *m, n, _state); - ae_vector_set_length(al, *m, _state); - ae_vector_set_length(au, *m, _state); - for(i=0; i<=n-1; i++) - { - c->ptr.p_double[i] = hqrndnormal(rs, _state); - bndl->ptr.p_double[i] = ae_pow(q, hqrndnormal(rs, _state), _state)-ae_pow(q, hqrndnormal(rs, _state), _state); - bndu->ptr.p_double[i] = bndl->ptr.p_double[i]+ae_pow(q, hqrndnormal(rs, _state), _state); - v = 0.01+0.98*hqrnduniformr(rs, _state); - x0.ptr.p_double[i] = (1-v)*bndl->ptr.p_double[i]+v*bndu->ptr.p_double[i]; - } - for(i=0; i<=*m-1; i++) - { - v = 0.0; - for(j=0; j<=n-1; j++) - { - a->ptr.pp_double[i][j] = hqrndnormal(rs, _state)*hqrnduniformi(rs, 2, _state); - a->ptr.pp_double[i][j] = a->ptr.pp_double[i][j]+ae_sign(a->ptr.pp_double[i][j], _state)*mincoeff; - v = v+a->ptr.pp_double[i][j]*x0.ptr.p_double[j]; - } - al->ptr.p_double[i] = v-ae_pow(q, hqrndnormal(rs, _state), _state); - au->ptr.p_double[i] = v+ae_pow(q, hqrndnormal(rs, _state), _state); - } - ae_frame_leave(_state); - return; - } - - /* - * A linearly constrained LP problem with up to M variables (linear - * constraints) being non-boxed (free or having just one constraint). - * A bit harder than all-boxed version. - * - * NOTE: components of C[] corresponding to these non-boxed variables - * are chosen in a way which guarantees dual feasibility of the - * problem. - */ - if( ptype==1 ) - { - q = 2.0; - big = 100.00; - *m = 1+hqrnduniformi(rs, 2*n, _state); - ae_matrix_set_length(a, *m, n, _state); - ae_vector_set_length(al, *m, _state); - ae_vector_set_length(au, *m, _state); - for(i=0; i<=n-1; i++) - { - c->ptr.p_double[i] = hqrndnormal(rs, _state); - bndl->ptr.p_double[i] = ae_pow(q, hqrndnormal(rs, _state), _state)-ae_pow(q, hqrndnormal(rs, _state), _state); - bndu->ptr.p_double[i] = bndl->ptr.p_double[i]+ae_pow(q, hqrndnormal(rs, _state), _state); - v = 0.01+0.98*hqrnduniformr(rs, _state); - x0.ptr.p_double[i] = (1-v)*bndl->ptr.p_double[i]+v*bndu->ptr.p_double[i]; - } - for(i=0; i<=*m-1; i++) - { - v = 0.0; - for(j=0; j<=n-1; j++) - { - a->ptr.pp_double[i][j] = hqrndnormal(rs, _state); - a->ptr.pp_double[i][j] = a->ptr.pp_double[i][j]+ae_sign(a->ptr.pp_double[i][j], _state)*mincoeff; - v = v+a->ptr.pp_double[i][j]*x0.ptr.p_double[j]; - } - al->ptr.p_double[i] = v-ae_pow(q, hqrndnormal(rs, _state), _state); - au->ptr.p_double[i] = v+ae_pow(q, hqrndnormal(rs, _state), _state); - } - kk = 1+hqrnduniformi(rs, *m, _state); - for(k=0; k<=kk-1; k++) - { - i = hqrnduniformi(rs, n+(*m), _state); - if( iptr.p_double[i] = _state->v_neginf; - c->ptr.p_double[i] = -big*(1+hqrnduniformr(rs, _state)); - } - if( kt==1 ) - { - bndu->ptr.p_double[i] = _state->v_posinf; - c->ptr.p_double[i] = big*(1+hqrnduniformr(rs, _state)); - } - if( kt==2 ) - { - bndl->ptr.p_double[i] = _state->v_neginf; - bndu->ptr.p_double[i] = _state->v_posinf; - } - } - else - { - kt = hqrnduniformi(rs, 3, _state); - if( kt==0 ) - { - au->ptr.p_double[i-n] = _state->v_posinf; - } - if( kt==1 ) - { - al->ptr.p_double[i-n] = _state->v_neginf; - } - if( kt==2 ) - { - al->ptr.p_double[i-n] = _state->v_neginf; - au->ptr.p_double[i-n] = _state->v_posinf; - } - } - } - ae_frame_leave(_state); - return; - } - - /* - * A randomly generated non-degenerate LP problem. A mix of fixed, - * range, upper/lower bounds and free variables. - */ - if( ptype==2 ) - { - *m = 1+hqrnduniformi(rs, 2*n, _state); - testminlpunit_generatecabxd(rs, n, *m, c, a, &xx, &d, &basicnonbasic, _state); - testminlpunit_generatebounds(rs, n, *m, &xx, &d, &basicnonbasic, bndl, bndu, al, au, _state); - ae_frame_leave(_state); - return; - } - - /* - * A randomly generated primal/dual degenerate LP problem. A mix of - * fixed, range, upper/lower bounds and free variables. - */ - if( ptype==3 ) - { - *m = 1+hqrnduniformi(rs, 2*n, _state); - testminlpunit_generatecabxd(rs, n, *m, c, a, &xx, &d, &basicnonbasic, _state); - testminlpunit_generatebounds(rs, n, *m, &xx, &d, &basicnonbasic, bndl, bndu, al, au, _state); - ndual = 1+hqrnduniformi(rs, *m, _state); - for(i=0; i<=ndual-1; i++) - { - j = basicnonbasic.ptr.p_int[*m+hqrnduniformi(rs, n, _state)]; - if( jptr.p_double[j] = c->ptr.p_double[j]-d.ptr.p_double[j]; - d.ptr.p_double[j] = (double)(0); - } - } - nprimal = 1+hqrnduniformi(rs, *m, _state); - for(i=0; i<=nprimal-1; i++) - { - j = basicnonbasic.ptr.p_int[hqrnduniformi(rs, *m, _state)]; - if( jptr.p_double[j] = xx.ptr.p_double[j]; - } - else - { - bndu->ptr.p_double[j] = xx.ptr.p_double[j]; - } - } - else - { - if( ae_fp_greater(hqrndnormal(rs, _state),(double)(0)) ) - { - al->ptr.p_double[j-n] = xx.ptr.p_double[j]; - } - else - { - au->ptr.p_double[j-n] = xx.ptr.p_double[j]; - } - } - } - ae_frame_leave(_state); - return; - } - ae_assert(ae_false, "GenerateLPProblem failed", _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function generates random primal unbounded LP problem. -*************************************************************************/ -static void testminlpunit_generateunboundedlpproblem(hqrndstate* rs, - ae_int_t n, - /* Real */ ae_vector* c, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t* m, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t ptype; - ae_int_t pcount; - double v; - double vv; - double q; - ae_vector x0; - - ae_frame_make(_state, &_frame_block); - memset(&x0, 0, sizeof(x0)); - ae_vector_clear(c); - ae_vector_clear(bndl); - ae_vector_clear(bndu); - ae_matrix_clear(a); - ae_vector_clear(al); - ae_vector_clear(au); - *m = 0; - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(c, n, _state); - ae_vector_set_length(bndl, n, _state); - ae_vector_set_length(bndu, n, _state); - - /* - * Choose problem type - */ - pcount = 2; - ptype = hqrnduniformi(rs, pcount, _state); - - /* - * Boundary-only constraints, can be easily made primal unbounded - */ - if( ptype==0 ) - { - q = 5.0; - *m = 0; - ae_matrix_set_length(a, 0, 0, _state); - ae_vector_set_length(al, 0, _state); - ae_vector_set_length(au, 0, _state); - for(i=0; i<=n-1; i++) - { - c->ptr.p_double[i] = hqrndnormal(rs, _state); - v = ae_pow(q, hqrndnormal(rs, _state), _state)-ae_pow(q, hqrndnormal(rs, _state), _state); - if( ae_fp_greater(c->ptr.p_double[i],(double)(0)) ) - { - bndl->ptr.p_double[i] = v; - bndu->ptr.p_double[i] = _state->v_posinf; - } - else - { - bndl->ptr.p_double[i] = _state->v_neginf; - bndu->ptr.p_double[i] = v; - } - } - i = hqrnduniformi(rs, n, _state); - do - { - c->ptr.p_double[i] = hqrndnormal(rs, _state); - } - while(ae_fp_eq(c->ptr.p_double[i],(double)(0))); - c->ptr.p_double[i] = c->ptr.p_double[i]+0.1*ae_sign(c->ptr.p_double[i], _state); - v = ae_pow(q, hqrndnormal(rs, _state), _state)-ae_pow(q, hqrndnormal(rs, _state), _state); - if( ae_fp_less(c->ptr.p_double[i],(double)(0)) ) - { - bndl->ptr.p_double[i] = v; - bndu->ptr.p_double[i] = _state->v_posinf; - } - else - { - bndl->ptr.p_double[i] = _state->v_neginf; - bndu->ptr.p_double[i] = v; - } - ae_frame_leave(_state); - return; - } - - /* - * Boundary and single-sided linear constraints; a bit more tricky to make it primal unbounded - */ - if( ptype==1 ) - { - q = 5.0; - *m = 1+hqrnduniformi(rs, 2*n, _state); - ae_matrix_set_length(a, *m, n, _state); - ae_vector_set_length(al, *m, _state); - ae_vector_set_length(au, *m, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - c->ptr.p_double[i] = hqrndnormal(rs, _state); - x0.ptr.p_double[i] = hqrndnormal(rs, _state); - if( ae_fp_greater_eq(c->ptr.p_double[i],(double)(0)) ) - { - bndl->ptr.p_double[i] = _state->v_neginf; - bndu->ptr.p_double[i] = x0.ptr.p_double[i]; - } - else - { - bndl->ptr.p_double[i] = x0.ptr.p_double[i]; - bndu->ptr.p_double[i] = _state->v_posinf; - } - } - for(i=0; i<=*m-1; i++) - { - v = (double)(0); - vv = (double)(0); - for(j=0; j<=n-1; j++) - { - a->ptr.pp_double[i][j] = hqrndnormal(rs, _state); - v = v+a->ptr.pp_double[i][j]*x0.ptr.p_double[j]; - vv = vv+a->ptr.pp_double[i][j]*c->ptr.p_double[j]; - } - if( ae_fp_greater_eq(vv,(double)(0)) ) - { - al->ptr.p_double[i] = _state->v_neginf; - au->ptr.p_double[i] = v; - } - else - { - al->ptr.p_double[i] = v; - au->ptr.p_double[i] = _state->v_posinf; - } - } - ae_frame_leave(_state); - return; - } - ae_assert(ae_false, "GenerateUnboundedLPProblem failed", _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function generates random primal infeasible LP problem -*************************************************************************/ -static void testminlpunit_generateinfeasiblelpproblem(hqrndstate* rs, - ae_int_t n, - /* Real */ ae_vector* c, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t* m, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t ptype; - ae_int_t pcount; - double v; - double q; - double minerr; - ae_vector xx; - ae_vector d; - ae_vector x0; - ae_vector tmpi; - - ae_frame_make(_state, &_frame_block); - memset(&xx, 0, sizeof(xx)); - memset(&d, 0, sizeof(d)); - memset(&x0, 0, sizeof(x0)); - memset(&tmpi, 0, sizeof(tmpi)); - ae_vector_clear(c); - ae_vector_clear(bndl); - ae_vector_clear(bndu); - ae_matrix_clear(a); - ae_vector_clear(al); - ae_vector_clear(au); - *m = 0; - ae_vector_init(&xx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpi, 0, DT_INT, _state, ae_true); - - ae_vector_set_length(c, n, _state); - ae_vector_set_length(bndl, n, _state); - ae_vector_set_length(bndu, n, _state); - - /* - * Choose problem type - */ - pcount = 3; - ptype = hqrnduniformi(rs, pcount, _state); - - /* - * Boundary-only constraints, can be easily made primal infeasible - */ - if( ptype==0 ) - { - q = 5.0; - *m = 0; - ae_matrix_set_length(a, 0, 0, _state); - ae_vector_set_length(al, 0, _state); - ae_vector_set_length(au, 0, _state); - for(i=0; i<=n-1; i++) - { - c->ptr.p_double[i] = hqrndnormal(rs, _state); - v = ae_pow(q, hqrndnormal(rs, _state), _state)-ae_pow(q, hqrndnormal(rs, _state), _state); - bndl->ptr.p_double[i] = v-ae_pow(q, hqrndnormal(rs, _state), _state); - bndu->ptr.p_double[i] = v+ae_pow(q, hqrndnormal(rs, _state), _state); - } - i = hqrnduniformi(rs, n, _state); - v = bndl->ptr.p_double[i]; - bndl->ptr.p_double[i] = bndu->ptr.p_double[i]; - bndu->ptr.p_double[i] = v; - ae_frame_leave(_state); - return; - } - - /* - * Linearly constrained problem with infeasible box constraints - */ - if( ptype==1 ) - { - q = (double)(5); - *m = 1+hqrnduniformi(rs, 2*n, _state); - testminlpunit_generatecabxd(rs, n, *m, c, a, &xx, &d, &tmpi, _state); - testminlpunit_generatebounds(rs, n, *m, &xx, &d, &tmpi, bndl, bndu, al, au, _state); - i = hqrnduniformi(rs, n, _state); - v = ae_pow(q, hqrndnormal(rs, _state), _state)-ae_pow(q, hqrndnormal(rs, _state), _state); - bndl->ptr.p_double[i] = v+ae_pow(q, hqrndnormal(rs, _state), _state); - bndu->ptr.p_double[i] = v-ae_pow(q, hqrndnormal(rs, _state), _state); - ae_frame_leave(_state); - return; - } - - /* - * Linearly constrained problem with infeasible linear constraints - */ - if( ptype==2 ) - { - q = (double)(5); - minerr = 0.01; - *m = 1+hqrnduniformi(rs, 2*n, _state); - testminlpunit_generatecabxd(rs, n, *m, c, a, &xx, &d, &tmpi, _state); - testminlpunit_generatebounds(rs, n, *m, &xx, &d, &tmpi, bndl, bndu, al, au, _state); - rmatrixresize(a, a->rows+1, a->cols, _state); - rvectorresize(al, al->cnt+1, _state); - rvectorresize(au, au->cnt+1, _state); - for(i=0; i<=n-1; i++) - { - a->ptr.pp_double[*m][i] = a->ptr.pp_double[*m-1][i]; - } - v = minerr+ae_pow(q, hqrndnormal(rs, _state), _state); - v = v*ae_maxreal(1.0, ae_sqrt(rdotrr(n, a, *m, a, *m, _state), _state), _state); - if( ae_isfinite(al->ptr.p_double[*m-1], _state)&&ae_isfinite(au->ptr.p_double[*m-1], _state) ) - { - al->ptr.p_double[*m] = au->ptr.p_double[*m-1]+v; - au->ptr.p_double[*m] = al->ptr.p_double[*m]+ae_pow(q, hqrndnormal(rs, _state), _state); - } - if( ae_isfinite(al->ptr.p_double[*m-1], _state)&&!ae_isfinite(au->ptr.p_double[*m-1], _state) ) - { - au->ptr.p_double[*m] = al->ptr.p_double[*m-1]-v; - al->ptr.p_double[*m] = au->ptr.p_double[*m]-ae_pow(q, hqrndnormal(rs, _state), _state); - } - if( !ae_isfinite(al->ptr.p_double[*m-1], _state)&&ae_isfinite(au->ptr.p_double[*m-1], _state) ) - { - al->ptr.p_double[*m] = au->ptr.p_double[*m-1]+v; - au->ptr.p_double[*m] = al->ptr.p_double[*m]+ae_pow(q, hqrndnormal(rs, _state), _state); - } - if( !ae_isfinite(al->ptr.p_double[*m-1], _state)&&!ae_isfinite(au->ptr.p_double[*m-1], _state) ) - { - al->ptr.p_double[*m] = v; - au->ptr.p_double[*m] = v-ae_pow(q, hqrndnormal(rs, _state), _state); - } - *m = *m+1; - ae_frame_leave(_state); - return; - } - ae_assert(ae_false, "GenerateUnboundedLPProblem failed", _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function generates random C[] and A[] as well as feasible point XX[N+M], -with XX[0..N-1] being structural variables and XX[N..N+M-1] being values -of logical variables. - -It also splits structural/logical variables into basic/nonbasic ones and -generates BasicNonbasic[] array, with indexes of basic variables being stored in -first M positions, and indexes of non-basic variables being stored in the -next N positions. -*************************************************************************/ -static void testminlpunit_generatecabxd(hqrndstate* rs, - ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* c, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* xx, - /* Real */ ae_vector* d, - /* Integer */ ae_vector* basicnonbasic, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector y; - ae_vector cx; - ae_matrix ax; - ae_vector pivots; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t kk; - double v; - double mincoeff; - - ae_frame_make(_state, &_frame_block); - memset(&y, 0, sizeof(y)); - memset(&cx, 0, sizeof(cx)); - memset(&ax, 0, sizeof(ax)); - memset(&pivots, 0, sizeof(pivots)); - ae_vector_clear(c); - ae_matrix_clear(a); - ae_vector_clear(xx); - ae_vector_clear(d); - ae_vector_clear(basicnonbasic); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cx, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ax, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&pivots, 0, DT_INT, _state, ae_true); - - mincoeff = 0.001; - - /* - * Randomly partition columns into basic and nonbasic ones - */ - ae_vector_set_length(basicnonbasic, n+m, _state); - for(i=0; i<=n+m-1; i++) - { - basicnonbasic->ptr.p_int[i] = i; - } - for(i=0; i<=m-1; i++) - { - k = i+hqrnduniformi(rs, n+m-i, _state); - kk = basicnonbasic->ptr.p_int[i]; - basicnonbasic->ptr.p_int[i] = basicnonbasic->ptr.p_int[k]; - basicnonbasic->ptr.p_int[k] = kk; - } - - /* - * Generate constraint matrix A - */ - ae_matrix_set_length(a, m, n, _state); - ae_matrix_set_length(&ax, m, n+m, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - ax.ptr.pp_double[i][j] = hqrndnormal(rs, _state); - ax.ptr.pp_double[i][j] = ax.ptr.pp_double[i][j]+ae_sign(ax.ptr.pp_double[i][j], _state)*mincoeff; - a->ptr.pp_double[i][j] = ax.ptr.pp_double[i][j]; - } - for(j=0; j<=m-1; j++) - { - ax.ptr.pp_double[i][n+j] = (double)(0); - } - ax.ptr.pp_double[i][n+i] = (double)(-1); - } - - /* - * Generate feasible point - */ - ae_vector_set_length(xx, n+m, _state); - for(i=0; i<=n-1; i++) - { - xx->ptr.p_double[i] = hqrndnormal(rs, _state); - } - for(i=n; i<=n+m-1; i++) - { - xx->ptr.p_double[i] = (double)(0); - } - for(i=0; i<=m-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+xx->ptr.p_double[j]*ax.ptr.pp_double[i][j]; - } - xx->ptr.p_double[n+i] = v; - } - - /* - * Generate random Y. - * Entries corresponding to basic constraints must be zero. - */ - ae_vector_set_length(&y, m, _state); - for(i=0; i<=m-1; i++) - { - y.ptr.p_double[i] = hqrndnormal(rs, _state); - } - for(i=0; i<=m-1; i++) - { - if( basicnonbasic->ptr.p_int[i]>=n ) - { - y.ptr.p_double[basicnonbasic->ptr.p_int[i]-n] = (double)(0); - } - } - - /* - * Generate D and C - */ - ae_vector_set_length(d, n+m, _state); - rmatrixgemv(n+m, m, -1.0, &ax, 0, 0, 1, &y, 0, 0.0, d, 0, _state); - ae_vector_set_length(&cx, n+m, _state); - for(i=0; i<=n-1; i++) - { - cx.ptr.p_double[i] = hqrndnormal(rs, _state); - } - for(i=n; i<=n+m-1; i++) - { - cx.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=m-1; i++) - { - cx.ptr.p_double[basicnonbasic->ptr.p_int[i]] = -d->ptr.p_double[basicnonbasic->ptr.p_int[i]]; - } - raddv(n+m, 1.0, &cx, d, _state); - ae_vector_set_length(c, n, _state); - rcopyv(n, &cx, c, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function generates random non-degenerate bounds for given XX and D. -*************************************************************************/ -static void testminlpunit_generatebounds(hqrndstate* rs, - ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* xx, - /* Real */ ae_vector* d, - /* Integer */ ae_vector* basicnonbasic, - /* Real */ ae_vector* bndl, - /* Real */ ae_vector* bndu, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_state *_state) -{ - double v0; - double v1; - double q; - ae_int_t i; - ae_int_t kk; - - ae_vector_clear(bndl); - ae_vector_clear(bndu); - ae_vector_clear(al); - ae_vector_clear(au); - - ae_vector_set_length(bndl, n, _state); - ae_vector_set_length(bndu, n, _state); - ae_vector_set_length(al, m, _state); - ae_vector_set_length(au, m, _state); - - /* - * Choose bounds in such a way that non-basic variables are - * strictly at the bounds and dual feasible, and all basic - * variables are strictly within bounds. - */ - q = (double)(5); - for(kk=0; kk<=n+m-1; kk++) - { - i = basicnonbasic->ptr.p_int[kk]; - v0 = xx->ptr.p_double[i]-ae_pow(q, hqrndnormal(rs, _state), _state); - v1 = xx->ptr.p_double[i]+ae_pow(q, hqrndnormal(rs, _state), _state); - if( ae_fp_greater(hqrndnormal(rs, _state),(double)(0)) ) - { - v0 = _state->v_neginf; - } - if( ae_fp_greater(hqrndnormal(rs, _state),(double)(0)) ) - { - v1 = _state->v_posinf; - } - if( kk>=m ) - { - if( ae_fp_greater_eq(d->ptr.p_double[i],(double)(0)) ) - { - v0 = xx->ptr.p_double[i]; - if( ae_fp_less(hqrnduniformr(rs, _state),0.05) ) - { - v1 = v0; - } - } - else - { - v1 = xx->ptr.p_double[i]; - if( ae_fp_less(hqrnduniformr(rs, _state),0.05) ) - { - v0 = v1; - } - } - } - if( iptr.p_double[i] = v0; - bndu->ptr.p_double[i] = v1; - } - else - { - al->ptr.p_double[i-n] = v0; - au->ptr.p_double[i-n] = v1; - } - } -} - - -/************************************************************************* -This function sets linear constraints using randomly chosen sequence of -SetLC/AddLC calls. - -It may also modify constraints: -* split two-sided constraint into two one-sided constraints -* create duplicates -* insert zero dummies - -Thus, you should not use this function when you want to test things like -correctness of Lagrange multipliers and so on. -*************************************************************************/ -static void testminlpunit_modifyandsendconstraintsto(ae_int_t n, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* al, - /* Real */ ae_vector* au, - ae_int_t m, - hqrndstate* rs, - minlpstate* state, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t stype; - ae_vector ai; - ae_vector idxi; - ae_int_t nz; - ae_int_t nzmod; - ae_matrix a1; - sparsematrix sa; - ae_vector ct; - ae_int_t ccnt; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t t; - ae_int_t minit; - ae_int_t nadd; - ae_int_t ndup; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&ai, 0, sizeof(ai)); - memset(&idxi, 0, sizeof(idxi)); - memset(&a1, 0, sizeof(a1)); - memset(&sa, 0, sizeof(sa)); - memset(&ct, 0, sizeof(ct)); - ae_vector_init(&ai, 0, DT_REAL, _state, ae_true); - ae_vector_init(&idxi, 0, DT_INT, _state, ae_true); - ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&sa, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - - - /* - * Choose sequence type - */ - stype = hqrnduniformi(rs, 4, _state); - - /* - * Straightforward SetLC2() call - */ - if( stype==0 ) - { - minlpsetlc2dense(state, a, al, au, m, _state); - ae_frame_leave(_state); - return; - } - - /* - * SetLC1() call (conversion to other format) - */ - if( stype==1 ) - { - ae_matrix_set_length(&a1, 2*m, n+1, _state); - ae_vector_set_length(&ct, 2*m, _state); - ccnt = 0; - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - a1.ptr.pp_double[ccnt+0][j] = a->ptr.pp_double[i][j]; - a1.ptr.pp_double[ccnt+1][j] = a->ptr.pp_double[i][j]; - } - if( (ae_isfinite(al->ptr.p_double[i], _state)&&ae_isfinite(au->ptr.p_double[i], _state))&&ae_fp_eq(al->ptr.p_double[i],au->ptr.p_double[i]) ) - { - a1.ptr.pp_double[ccnt][n] = al->ptr.p_double[i]; - ct.ptr.p_int[ccnt] = 0; - ccnt = ccnt+1; - } - else - { - if( ae_isfinite(al->ptr.p_double[i], _state) ) - { - a1.ptr.pp_double[ccnt][n] = al->ptr.p_double[i]; - ct.ptr.p_int[ccnt] = 1; - ccnt = ccnt+1; - } - if( ae_isfinite(au->ptr.p_double[i], _state) ) - { - a1.ptr.pp_double[ccnt][n] = au->ptr.p_double[i]; - ct.ptr.p_int[ccnt] = -1; - ccnt = ccnt+1; - } - } - } - minlpsetlc(state, &a1, &ct, ccnt, _state); - ae_frame_leave(_state); - return; - } - - /* - * Straightforward SetLC2Sparse() call - */ - if( stype==2 ) - { - if( m==0 ) - { - minlpsetlc2(state, &sa, al, au, 0, _state); - ae_frame_leave(_state); - return; - } - sparsecreate(m, n, 0, &sa, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_neq(a->ptr.pp_double[i][j],(double)(0)) ) - { - sparseset(&sa, i, j, a->ptr.pp_double[i][j], _state); - } - } - } - if( ae_fp_greater(hqrndnormal(rs, _state),(double)(0)) ) - { - sparseconverttocrs(&sa, _state); - } - minlpsetlc2(state, &sa, al, au, m, _state); - ae_frame_leave(_state); - return; - } - - /* - * A few rows are added with SetLC2Dense() call, the rest - * is processed with random mix of AddLC2Dense()/AddLC2() - */ - if( stype==3 ) - { - if( m==0 ) - { - minlpsetlc2(state, &sa, al, au, 0, _state); - ae_frame_leave(_state); - return; - } - minit = hqrnduniformi(rs, m, _state); - minlpsetlc2dense(state, a, al, au, minit, _state); - for(i=minit; i<=m-1; i++) - { - if( hqrnduniformi(rs, 2, _state)==0 ) - { - - /* - * Add as dense row - */ - ae_vector_set_length(&ai, n, _state); - for(j=0; j<=n-1; j++) - { - ai.ptr.p_double[j] = a->ptr.pp_double[i][j]; - } - minlpaddlc2dense(state, &ai, al->ptr.p_double[i], au->ptr.p_double[i], _state); - } - else - { - - /* - * Add as sparse row with shuffle and possible duplicates - */ - ae_vector_set_length(&ai, n, _state); - ae_vector_set_length(&idxi, n, _state); - nz = 0; - for(j=0; j<=n-1; j++) - { - if( ae_fp_neq(a->ptr.pp_double[i][j],(double)(0)) ) - { - ai.ptr.p_double[nz] = a->ptr.pp_double[i][j]; - idxi.ptr.p_int[nz] = j; - nz = nz+1; - } - } - rvectorresize(&ai, nz, _state); - ivectorresize(&idxi, nz, _state); - - /* - * Already existing elements are split in two - */ - nadd = 0; - if( nz!=0 ) - { - nadd = hqrnduniformi(rs, 2, _state)*hqrnduniformi(rs, 4, _state); - rvectorresize(&ai, nz+nadd, _state); - ivectorresize(&idxi, nz+nadd, _state); - for(j=0; j<=nadd-1; j++) - { - k = hqrnduniformi(rs, nz, _state); - v = hqrndnormal(rs, _state); - idxi.ptr.p_int[nz+j] = idxi.ptr.p_int[k]; - ai.ptr.p_double[nz+j] = v; - ai.ptr.p_double[k] = ai.ptr.p_double[k]-v; - } - } - - /* - * Possibly nonexistent elements are added as +V and -V - * Do not performed for NZ=0 rows because it may introduce slightly nonzero coefficients - * to exactly zero row (constraint normalization goes crazy). - */ - ndup = hqrnduniformi(rs, 2, _state)*hqrnduniformi(rs, 4, _state); - if( nz==0 ) - { - ndup = 0; - } - rvectorresize(&ai, nz+nadd+2*ndup, _state); - ivectorresize(&idxi, nz+nadd+2*ndup, _state); - for(j=0; j<=ndup-1; j++) - { - k = hqrnduniformi(rs, n, _state); - v = hqrndnormal(rs, _state); - idxi.ptr.p_int[nz+nadd+2*j+0] = k; - idxi.ptr.p_int[nz+nadd+2*j+1] = k; - ai.ptr.p_double[nz+nadd+2*j+0] = v; - ai.ptr.p_double[nz+nadd+2*j+1] = -v; - } - nzmod = nz+nadd+2*ndup; - for(j=0; j<=nzmod-1; j++) - { - k = j+hqrnduniformi(rs, nzmod-j, _state); - t = idxi.ptr.p_int[j]; - idxi.ptr.p_int[j] = idxi.ptr.p_int[k]; - idxi.ptr.p_int[k] = t; - v = ai.ptr.p_double[j]; - ai.ptr.p_double[j] = ai.ptr.p_double[k]; - ai.ptr.p_double[k] = v; - } - minlpaddlc2(state, &idxi, &ai, nzmod, al->ptr.p_double[i], au->ptr.p_double[i], _state); - } - } - ae_frame_leave(_state); - return; - } - ae_assert(ae_false, "MINLPTest: integrity check failed", _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function selects random LP solver -*************************************************************************/ -static void testminlpunit_selectrandomsolver(minlpstate* state, - ae_state *_state) -{ - ae_int_t k; - - - k = ae_randominteger(2, _state); - if( k==0 ) - { - minlpsetalgodss(state, 0.0, _state); - } - if( k==1 ) - { - minlpsetalgoipm(state, 0.0, _state); - } -} - - -/************************************************************************* -This function selects specific LP solver. - -Reg parameter is used to regularize IPM algo, ignore for DSS -*************************************************************************/ -static void testminlpunit_selectsolver(minlpstate* state, - ae_int_t st, - ae_state *_state) -{ - - - if( st==0 ) - { - minlpsetalgodss(state, 0.0, _state); - return; - } - if( st==1 ) - { - minlpsetalgoipm(state, 0.0, _state); - return; - } - ae_assert(ae_false, "SelectSolver: unexpected solver", _state); -} - - -/************************************************************************* -Shifts nonzero elements of C[] away from zero -*************************************************************************/ -static void testminlpunit_shiftfromzero(/* Real */ ae_vector* c, - ae_int_t n, - double s, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=n-1; i++) - { - c->ptr.p_double[i] = c->ptr.p_double[i]+ae_sign(c->ptr.p_double[i], _state)*s; - } -} - - - -static ae_int_t testminnlcunit_maxsolvertype = 2; -static ae_int_t testminnlcunit_maxoptguardlevel = 1; -static void testminnlcunit_testbc(ae_bool* wereerrors, ae_state *_state); -static void testminnlcunit_testlc(ae_bool* wereerrors, ae_state *_state); -static void testminnlcunit_testnlc(ae_bool* wereerrors, ae_state *_state); -static void testminnlcunit_testother(ae_bool* wereerrors, - ae_state *_state); -static void testminnlcunit_testoptguard(ae_bool* wereerrors, - ae_state *_state); -static void testminnlcunit_testbugs(ae_bool* wereerrors, ae_state *_state); -static void testminnlcunit_testoptguardc1test0reportfortask0(ae_bool* err, - optguardnonc1test0report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state); -static void testminnlcunit_testoptguardc1test1reportfortask0(ae_bool* err, - optguardnonc1test1report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state); -static void testminnlcunit_testoptguardc1test0reportfortask1(ae_bool* err, - optguardnonc1test0report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t goodidx, - ae_state *_state); -static void testminnlcunit_testoptguardc1test1reportfortask1(ae_bool* err, - optguardnonc1test1report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t goodidx, - ae_state *_state); - - - - - -ae_bool testminnlc(ae_bool silent, ae_state *_state) -{ - ae_bool waserrors; - ae_bool bcerr; - ae_bool lcerr; - ae_bool nlcerr; - ae_bool othererr; - ae_bool optguarderr; - ae_bool bugs; - ae_bool result; - - - waserrors = ae_false; - bcerr = ae_false; - lcerr = ae_false; - nlcerr = ae_false; - othererr = ae_false; - optguarderr = ae_false; - bugs = ae_false; - testminnlcunit_testbugs(&bugs, _state); - testminnlcunit_testbc(&bcerr, _state); - testminnlcunit_testlc(&lcerr, _state); - testminnlcunit_testnlc(&nlcerr, _state); - testminnlcunit_testother(&othererr, _state); - testminnlcunit_testoptguard(&optguarderr, _state); - - /* - * end - */ - waserrors = ((((bcerr||lcerr)||nlcerr)||othererr)||bugs)||optguarderr; - if( !silent ) - { - printf("TESTING MINNLC OPTIMIZATION\n"); - printf("GENERIC TESTS:\n"); - printf("* box constrained "); - if( bcerr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* linearly constrained "); - if( lcerr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* nonlinearly constrained "); - if( nlcerr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* other properties "); - if( othererr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* optguard integrity monitor "); - if( optguarderr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* fixed bugs "); - if( bugs ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - return result; -} - - -/************************************************************************* -This function tests bound constrained quadratic programming algorithm. - -On failure sets error flag. -*************************************************************************/ -static void testminnlcunit_testbc(ae_bool* wereerrors, ae_state *_state) -{ - ae_frame _frame_block; - minnlcstate state; - minnlcreport rep; - optguardreport ogrep; - ae_int_t n; - ae_int_t pass; - ae_int_t i; - ae_int_t j; - ae_int_t aulits; - double tolx; - double tolg; - ae_int_t scaletype; - double rho; - ae_int_t solvertype; - ae_matrix fulla; - ae_vector b; - ae_vector bndl; - ae_vector bndu; - ae_vector s; - ae_vector x0; - ae_vector x1; - double gnorm; - double g; - ae_int_t prectype; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&ogrep, 0, sizeof(ogrep)); - memset(&fulla, 0, sizeof(fulla)); - memset(&b, 0, sizeof(b)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&s, 0, sizeof(s)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&rs, 0, sizeof(rs)); - _minnlcstate_init(&state, _state, ae_true); - _minnlcreport_init(&rep, _state, ae_true); - _optguardreport_init(&ogrep, _state, ae_true); - ae_matrix_init(&fulla, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - for(solvertype=0; solvertype<=testminnlcunit_maxsolvertype; solvertype++) - { - - /* - * Convex test: - * * N dimensions - * * random number (0..N) of random boundary constraints - * * positive-definite quadratic programming problem - * * initial point is random (maybe infeasible!) - * * random scale (unit or non-unit) - */ - aulits = 10; - rho = 200.0; - tolx = 0.0005; - tolg = 0.01; - for(n=1; n<=10; n++) - { - for(pass=1; pass<=10; pass++) - { - for(prectype=0; prectype<=2; prectype++) - { - - /* - * Generate well-conditioned problem with unit scale - */ - spdmatrixrndcond(n, 1.0E2, &fulla, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - bndl.ptr.p_double[i] = _state->v_neginf; - bndu.ptr.p_double[i] = _state->v_posinf; - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - j = hqrnduniformi(&rs, 5, _state); - if( j==0 ) - { - bndl.ptr.p_double[i] = (double)(0); - } - if( j==1 ) - { - bndu.ptr.p_double[i] = (double)(0); - } - if( j==2 ) - { - bndl.ptr.p_double[i] = hqrndnormal(&rs, _state); - bndu.ptr.p_double[i] = bndl.ptr.p_double[i]; - } - if( j==3 ) - { - bndl.ptr.p_double[i] = -0.1; - bndu.ptr.p_double[i] = 0.1; - } - } - - /* - * Apply scaling to quadratic/linear term, so problem becomes - * well-conditioned in the scaled coordinates. - */ - scaletype = hqrnduniformi(&rs, 2, _state); - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - if( scaletype==0 ) - { - s.ptr.p_double[i] = (double)(1); - } - else - { - s.ptr.p_double[i] = ae_exp(5*hqrndnormal(&rs, _state), _state); - } - } - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = x0.ptr.p_double[i]*s.ptr.p_double[i]; - bndl.ptr.p_double[i] = bndl.ptr.p_double[i]*s.ptr.p_double[i]; - bndu.ptr.p_double[i] = bndu.ptr.p_double[i]*s.ptr.p_double[i]; - b.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - fulla.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]); - } - } - - /* - * Solve problem - */ - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, rho, aulits, _state); - if( prectype==1 ) - { - minnlcsetprecexactlowrank(&state, 0, _state); - } - if( prectype==2 ) - { - minnlcsetprecexactrobust(&state, 0, _state); - } - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - if( scaletype!=0 ) - { - minnlcsetscale(&state, &s, _state); - } - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minnlcoptguardsmoothness(&state, hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel+1, _state), _state); - } - minnlcsetbc(&state, &bndl, &bndu, _state); - minnlcsetcond(&state, 1.0E-7, 0, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.j.ptr.pp_double[0][i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:240"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:241"); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minnlcoptguardresults(&state, &ogrep, _state); - ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:245"); - } - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check constraint violation reports - */ - ae_set_error_flag(wereerrors, ae_fp_greater(rep.bcerr,tolx), __FILE__, __LINE__, "testminnlcunit.ap:253"); - ae_set_error_flag(wereerrors, rep.bcidx>=n, __FILE__, __LINE__, "testminnlcunit.ap:254"); - ae_set_error_flag(wereerrors, ae_fp_greater(rep.lcerr,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:255"); - ae_set_error_flag(wereerrors, rep.lcidx>=0, __FILE__, __LINE__, "testminnlcunit.ap:256"); - - /* - * Check feasibility properties - */ - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(wereerrors, ae_isfinite(bndl.ptr.p_double[i], _state)&&ae_fp_less_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i]-tolx*s.ptr.p_double[i]), __FILE__, __LINE__, "testminnlcunit.ap:263"); - ae_set_error_flag(wereerrors, ae_isfinite(bndu.ptr.p_double[i], _state)&&ae_fp_greater_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i]+tolx*s.ptr.p_double[i]), __FILE__, __LINE__, "testminnlcunit.ap:264"); - } - - /* - * Test - calculate scaled constrained gradient at solution, - * check its norm. - */ - gnorm = 0.0; - for(i=0; i<=n-1; i++) - { - g = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - g = g+fulla.ptr.pp_double[i][j]*x1.ptr.p_double[j]; - } - g = s.ptr.p_double[i]*g; - if( (ae_isfinite(bndl.ptr.p_double[i], _state)&&ae_fp_less(ae_fabs(x1.ptr.p_double[i]-bndl.ptr.p_double[i], _state),tolx*s.ptr.p_double[i]))&&ae_fp_greater(g,(double)(0)) ) - { - g = (double)(0); - } - if( (ae_isfinite(bndu.ptr.p_double[i], _state)&&ae_fp_less(ae_fabs(x1.ptr.p_double[i]-bndu.ptr.p_double[i], _state),tolx*s.ptr.p_double[i]))&&ae_fp_less(g,(double)(0)) ) - { - g = (double)(0); - } - gnorm = gnorm+ae_sqr(g, _state); - } - gnorm = ae_sqrt(gnorm, _state); - ae_set_error_flag(wereerrors, ae_fp_greater(gnorm,tolg), __FILE__, __LINE__, "testminnlcunit.ap:286"); - } - } - } - - /* - * Non-convex test: - * * N dimensions, N>=2 - * * box constraints, x[i] in [-1,+1] - * * A is symmetric indefinite with condition number 50.0 - * * random B with normal entries - * * initial point is random, feasible - * * scale is always unit - * - * We check that constrained problem can be successfully solved. - * We do not check ability to detect unboundedness of unconstrained - * problem because there is such functionality in MinNLC. - */ - aulits = 50; - rho = 200.0; - tolx = 0.0005; - tolg = 0.01; - for(n=2; n<=10; n++) - { - for(pass=1; pass<=10; pass++) - { - for(prectype=0; prectype<=2; prectype++) - { - - /* - * Generate problem - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - fulla.ptr.pp_double[i][j] = 0.0; - } - } - for(i=0; i<=n-1; i++) - { - fulla.ptr.pp_double[i][i] = -1-hqrnduniformr(&rs, _state); - } - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = 0.05*hqrndnormal(&rs, _state); - bndl.ptr.p_double[i] = (double)(-1); - bndu.ptr.p_double[i] = (double)(1); - x0.ptr.p_double[i] = 2*hqrnduniformr(&rs, _state)-1; - } - - /* - * Solve problem: - * * without constraints we expect failure - * * with constraints algorithm must succeed - */ - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, rho, aulits, _state); - if( prectype==0 ) - { - minnlcsetprecinexact(&state, _state); - } - if( prectype==1 ) - { - minnlcsetprecexactlowrank(&state, 0, _state); - } - if( prectype==2 ) - { - minnlcsetprecexactrobust(&state, 0, _state); - } - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minnlcoptguardsmoothness(&state, hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel+1, _state), _state); - } - minnlcsetbc(&state, &bndl, &bndu, _state); - minnlcsetcond(&state, 1.0E-7, 0, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.j.ptr.pp_double[0][i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:378"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:379"); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minnlcoptguardresults(&state, &ogrep, _state); - ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:383"); - } - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check feasibility properties - */ - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(wereerrors, ae_isfinite(bndl.ptr.p_double[i], _state)&&ae_fp_less_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i]-tolx), __FILE__, __LINE__, "testminnlcunit.ap:393"); - ae_set_error_flag(wereerrors, ae_isfinite(bndu.ptr.p_double[i], _state)&&ae_fp_greater_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i]+tolx), __FILE__, __LINE__, "testminnlcunit.ap:394"); - } - - /* - * Test - calculate scaled constrained gradient at solution, - * check its norm. - */ - gnorm = 0.0; - for(i=0; i<=n-1; i++) - { - g = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - g = g+fulla.ptr.pp_double[i][j]*x1.ptr.p_double[j]; - } - if( (ae_isfinite(bndl.ptr.p_double[i], _state)&&ae_fp_less(ae_fabs(x1.ptr.p_double[i]-bndl.ptr.p_double[i], _state),tolx))&&ae_fp_greater(g,(double)(0)) ) - { - g = (double)(0); - } - if( (ae_isfinite(bndu.ptr.p_double[i], _state)&&ae_fp_less(ae_fabs(x1.ptr.p_double[i]-bndu.ptr.p_double[i], _state),tolx))&&ae_fp_less(g,(double)(0)) ) - { - g = (double)(0); - } - gnorm = gnorm+ae_sqr(g, _state); - } - gnorm = ae_sqrt(gnorm, _state); - ae_set_error_flag(wereerrors, ae_fp_greater(gnorm,tolg), __FILE__, __LINE__, "testminnlcunit.ap:415"); - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests linearly constrained quadratic programming algorithm. - -Sets error flag on failure. -*************************************************************************/ -static void testminnlcunit_testlc(ae_bool* wereerrors, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t k; - ae_int_t i; - ae_int_t j; - ae_int_t pass; - ae_matrix q; - ae_matrix fulla; - double v; - double vv; - ae_vector tmp; - ae_vector bl; - ae_vector bu; - ae_vector b; - ae_vector xs0; - ae_vector xstart; - ae_vector x; - ae_vector x0; - ae_vector x1; - ae_vector x2; - ae_vector xm; - ae_vector s; - ae_vector g; - ae_vector bndl; - ae_vector bndu; - ae_matrix a; - ae_matrix c; - ae_matrix ce; - ae_vector ct; - ae_vector nonnegative; - double tolx; - double tolg; - double tolf; - ae_int_t aulits; - double rho; - minnlcstate state; - minnlcreport rep; - optguardreport ogrep; - ae_int_t scaletype; - double f0; - double f1; - double tolconstr; - ae_int_t bscale; - ae_int_t akind; - ae_int_t ccnt; - ae_int_t shiftkind; - ae_int_t prectype; - ae_int_t solvertype; - double gnrm2; - hqrndstate rs; - snnlssolver nnls; - - ae_frame_make(_state, &_frame_block); - memset(&q, 0, sizeof(q)); - memset(&fulla, 0, sizeof(fulla)); - memset(&tmp, 0, sizeof(tmp)); - memset(&bl, 0, sizeof(bl)); - memset(&bu, 0, sizeof(bu)); - memset(&b, 0, sizeof(b)); - memset(&xs0, 0, sizeof(xs0)); - memset(&xstart, 0, sizeof(xstart)); - memset(&x, 0, sizeof(x)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&x2, 0, sizeof(x2)); - memset(&xm, 0, sizeof(xm)); - memset(&s, 0, sizeof(s)); - memset(&g, 0, sizeof(g)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&a, 0, sizeof(a)); - memset(&c, 0, sizeof(c)); - memset(&ce, 0, sizeof(ce)); - memset(&ct, 0, sizeof(ct)); - memset(&nonnegative, 0, sizeof(nonnegative)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&ogrep, 0, sizeof(ogrep)); - memset(&rs, 0, sizeof(rs)); - memset(&nnls, 0, sizeof(nnls)); - ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&fulla, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xs0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xstart, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xm, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&g, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ce, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - ae_vector_init(&nonnegative, 0, DT_BOOL, _state, ae_true); - _minnlcstate_init(&state, _state, ae_true); - _minnlcreport_init(&rep, _state, ae_true); - _optguardreport_init(&ogrep, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - _snnlssolver_init(&nnls, _state, ae_true); - - hqrndrandomize(&rs, _state); - for(solvertype=0; solvertype<=testminnlcunit_maxsolvertype; solvertype++) - { - - /* - * First test: - * * K=0, __FILE__, __LINE__, "testminnlcunit.ap:594"); - ae_set_error_flag(wereerrors, ae_fp_greater(rep.lcerr,tolx), __FILE__, __LINE__, "testminnlcunit.ap:595"); - ae_set_error_flag(wereerrors, rep.lcidx>=n, __FILE__, __LINE__, "testminnlcunit.ap:596"); - - /* - * Compare with analytic solution - */ - f0 = (double)(0); - f1 = (double)(0); - for(i=0; i<=n-1; i++) - { - f0 = f0+b.ptr.p_double[i]*x0.ptr.p_double[i]+0.5*ae_sqr(x0.ptr.p_double[i]/s.ptr.p_double[i], _state); - f1 = f1+b.ptr.p_double[i]*x1.ptr.p_double[i]+0.5*ae_sqr(x1.ptr.p_double[i]/s.ptr.p_double[i], _state); - } - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(f1-f0, _state),tolf), __FILE__, __LINE__, "testminnlcunit.ap:608"); - } - } - } - - /* - * Inequality constrained problem: - * * N*N diagonal A - * * one inequality constraint q'*x>=0, where q is random unit vector - * * optimization problem has form 0.5*x'*A*x-(x1*A)*x, - * where x1 is some random vector - * * either: - * a) x1 is feasible => we must stop at x1 - * b) x1 is infeasible => we must stop at the boundary q'*x=0 and - * projection of gradient onto q*x=0 must be zero - * - * NOTE: we make several passes because some specific kind of errors is rarely - * caught by this test, so we need several repetitions. - */ - rho = 200.0; - tolx = 0.0005; - tolg = 0.01; - aulits = 50; - for(n=2; n<=6; n++) - { - for(pass=0; pass<=4; pass++) - { - - /* - * Generate problem: A, b, CMatrix, x0, XStart - */ - spdmatrixrndcond(n, 1.0E2, &fulla, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&xm, n, _state); - ae_vector_set_length(&xstart, n, _state); - ae_matrix_set_length(&c, 1, n+1, _state); - ae_vector_set_length(&ct, 1, _state); - for(i=0; i<=n-1; i++) - { - xm.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - xstart.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - do - { - v = (double)(0); - for(i=0; i<=n-1; i++) - { - c.ptr.pp_double[0][i] = 2*ae_randomreal(_state)-1; - v = v+ae_sqr(c.ptr.pp_double[0][i], _state); - } - v = ae_sqrt(v, _state); - } - while(ae_fp_eq(v,(double)(0))); - for(i=0; i<=n-1; i++) - { - c.ptr.pp_double[0][i] = c.ptr.pp_double[0][i]/v; - } - c.ptr.pp_double[0][n] = (double)(0); - ct.ptr.p_int[0] = 1; - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&fulla.ptr.pp_double[i][0], 1, &xm.ptr.p_double[0], 1, ae_v_len(0,n-1)); - b.ptr.p_double[i] = -v; - } - - /* - * Apply scaling to linear term and known solution, - * so problem becomes well-conditioned in the scaled coordinates. - */ - scaletype = hqrnduniformi(&rs, 2, _state); - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - if( scaletype==0 ) - { - s.ptr.p_double[i] = (double)(1); - } - else - { - s.ptr.p_double[i] = ae_exp(hqrndnormal(&rs, _state), _state); - } - } - for(i=0; i<=n-1; i++) - { - xm.ptr.p_double[i] = xm.ptr.p_double[i]*s.ptr.p_double[i]; - xstart.ptr.p_double[i] = xstart.ptr.p_double[i]*s.ptr.p_double[i]; - b.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - fulla.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]); - } - } - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[0][j] = c.ptr.pp_double[0][j]/s.ptr.p_double[j]; - } - - /* - * Create optimizer, solve - */ - minnlccreate(n, &xstart, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, rho, aulits, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetlc(&state, &c, &ct, 1, _state); - minnlcsetscale(&state, &s, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minnlcoptguardsmoothness(&state, hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel+1, _state), _state); - } - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.j.ptr.pp_double[0][i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:730"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:731"); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minnlcoptguardresults(&state, &ogrep, _state); - ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:735"); - } - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check constraint violation reports - */ - ae_set_error_flag(wereerrors, ae_fp_greater(rep.bcerr,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:743"); - ae_set_error_flag(wereerrors, rep.bcidx>=0, __FILE__, __LINE__, "testminnlcunit.ap:744"); - ae_set_error_flag(wereerrors, ae_fp_greater(rep.lcerr,tolx), __FILE__, __LINE__, "testminnlcunit.ap:745"); - ae_set_error_flag(wereerrors, rep.lcidx>=n, __FILE__, __LINE__, "testminnlcunit.ap:746"); - - /* - * Test solution - */ - ae_vector_set_length(&g, n, _state); - ae_v_move(&g.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&fulla.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - g.ptr.p_double[i] = g.ptr.p_double[i]+v; - } - v = ae_v_dotproduct(&x1.ptr.p_double[0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1)); - ae_set_error_flag(wereerrors, ae_fp_less(v,-tolx), __FILE__, __LINE__, "testminnlcunit.ap:759"); - if( ae_fp_less(v,tolx) ) - { - - /* - * Point at the boundary, project gradient into - * equality-constrained subspace. - */ - v = 0.0; - vv = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+g.ptr.p_double[i]*c.ptr.pp_double[0][i]; - vv = vv+c.ptr.pp_double[0][i]*c.ptr.pp_double[0][i]; - } - v = v/vv; - ae_v_subd(&g.ptr.p_double[0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1), v); - } - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(g.ptr.p_double[i]*s.ptr.p_double[i], _state); - } - ae_set_error_flag(wereerrors, ae_fp_greater(ae_sqrt(v, _state),tolg), __FILE__, __LINE__, "testminnlcunit.ap:779"); - } - } - - /* - * Equality-constrained test: - * * N*N SPD A - * * K=0, __FILE__, __LINE__, "testminnlcunit.ap:888"); - ae_set_error_flag(wereerrors, ae_fp_greater(rep.lcerr,tolx), __FILE__, __LINE__, "testminnlcunit.ap:889"); - ae_set_error_flag(wereerrors, rep.lcidx>=n, __FILE__, __LINE__, "testminnlcunit.ap:890"); - - /* - * Check feasibility properties and gradient projection - */ - for(i=0; i<=k-1; i++) - { - v = ae_v_dotproduct(&x1.ptr.p_double[0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(v-c.ptr.pp_double[i][n], _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:898"); - } - ae_vector_set_length(&g, n, _state); - ae_v_move(&g.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&fulla.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - g.ptr.p_double[i] = g.ptr.p_double[i]+v; - } - for(i=0; i<=k-1; i++) - { - v = ae_v_dotproduct(&g.ptr.p_double[0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - ae_v_subd(&g.ptr.p_double[0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v); - } - v = ae_v_dotproduct(&g.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_sqrt(v, _state),tolg), __FILE__, __LINE__, "testminnlcunit.ap:913"); - } - } - - /* - * Boundary constraints vs linear ones: - * * N*N SPD A - * * optimization problem has form 0.5*x'*A*x-(xm*A)*x, - * where xm is some random vector from [-1,+1] - * * K=2*N constraints of the form ai<=x[i] or x[i]<=b[i], - * with ai in [-1.0,-0.1], bi in [+0.1,+1.0] - * * initial point xstart is from [-1,+2] - * * we solve two related QP problems: - * a) one with constraints posed as boundary ones - * b) another one with same constraints posed as general linear ones - * both problems must have same solution. - * Here we test that boundary constrained and linear inequality constrained - * solvers give same results. - */ - rho = 200.0; - tolx = 0.0005; - tolf = 0.00001; - aulits = 50; - for(n=1; n<=6; n++) - { - - /* - * Generate problem: A, b, x0, XStart, C, CT - */ - spdmatrixrndcond(n, 1.0E2, &fulla, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&xm, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_matrix_set_length(&c, 2*n, n+1, _state); - ae_vector_set_length(&ct, 2*n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - for(i=0; i<=n-1; i++) - { - xm.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1; - bndl.ptr.p_double[i] = -(0.1+0.9*ae_randomreal(_state)); - bndu.ptr.p_double[i] = 0.1+0.9*ae_randomreal(_state); - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[2*i+0][j] = (double)(0); - c.ptr.pp_double[2*i+1][j] = (double)(0); - } - c.ptr.pp_double[2*i+0][i] = (double)(1); - c.ptr.pp_double[2*i+0][n] = bndl.ptr.p_double[i]; - ct.ptr.p_int[2*i+0] = 1; - c.ptr.pp_double[2*i+1][i] = (double)(1); - c.ptr.pp_double[2*i+1][n] = bndu.ptr.p_double[i]; - ct.ptr.p_int[2*i+1] = -1; - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&fulla.ptr.pp_double[i][0], 1, &xm.ptr.p_double[0], 1, ae_v_len(0,n-1)); - b.ptr.p_double[i] = -v; - } - - /* - * Solve linear inequality constrained problem - */ - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, rho, aulits, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetlc(&state, &c, &ct, 2*n, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minnlcoptguardsmoothness(&state, hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel+1, _state), _state); - } - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.j.ptr.pp_double[0][i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:1013"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:1014"); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minnlcoptguardresults(&state, &ogrep, _state); - ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:1018"); - } - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Solve boundary constrained problem - */ - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, rho, aulits, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetbc(&state, &bndl, &bndu, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.j.ptr.pp_double[0][i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x2, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x2, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:1060"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:1061"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Compare solutions - */ - f0 = (double)(0); - f1 = (double)(0); - for(i=0; i<=n-1; i++) - { - f0 = f0+b.ptr.p_double[i]*x1.ptr.p_double[i]; - f1 = f1+b.ptr.p_double[i]*x2.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - f0 = f0+0.5*x1.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*x1.ptr.p_double[j]; - f1 = f1+0.5*x2.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*x2.ptr.p_double[j]; - } - } - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(f0-f1, _state),tolf), __FILE__, __LINE__, "testminnlcunit.ap:1080"); - } - - /* - * Boundary and linear equality constrained QP problem with excessive - * equality constraints: - * * N*N SPD A with moderate condtion number (up to 100) - * * boundary constraints 0<=x[i]<=1 - * * K=2*N equality constraints Q*x = Q*x0, where Q is random matrix, - * x0 is some random vector from the feasible hypercube (0.1<=x0[i]<=0.9) - * * optimization problem has form 0.5*x'*A*x-b*x, - * where b is some random vector - * * because constraints are excessive, the main problem is to find - * feasible point; the only existing feasible point is solution, - * so we have to check only feasibility - */ - rho = 1000.0; - tolx = 0.0005; - aulits = 10; - for(n=1; n<=6; n++) - { - - /* - * Generate problem: A, b, BndL, BndU, CMatrix, x0, xm, XStart - */ - k = 2*n; - spdmatrixrndcond(n, 1.0E2, &fulla, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xm, n, _state); - ae_vector_set_length(&xstart, n, _state); - ae_matrix_set_length(&c, k, n+1, _state); - ae_vector_set_length(&ct, k, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 0.1+0.8*ae_randomreal(_state); - xm.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - bndl.ptr.p_double[i] = 0.0; - bndu.ptr.p_double[i] = 1.0; - xstart.ptr.p_double[i] = (double)(ae_randominteger(2, _state)); - } - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - c.ptr.pp_double[i][n] = v; - ct.ptr.p_int[i] = 0; - } - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - - /* - * Create optimizer, solve - */ - minnlccreate(n, &xstart, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, rho, aulits, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetcond(&state, 1.0E-7, 0, _state); - minnlcsetlc(&state, &c, &ct, k, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minnlcoptguardsmoothness(&state, hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel+1, _state), _state); - } - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.j.ptr.pp_double[0][i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:1177"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:1178"); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minnlcoptguardresults(&state, &ogrep, _state); - ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:1182"); - } - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=k-1; i++) - { - v = ae_v_dotproduct(&x1.ptr.p_double[0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(v-c.ptr.pp_double[i][n], _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:1189"); - } - } - - /* - * Boundary and linear equality/inequality constrained QP problem with - * excessive constraints: - * * N*N SPD A with moderate condtion number (up to 100) - * * boundary constraints 0<=x[i]<=1 - * * K=2*N equality/inequality constraints: - * * N/2 equality ones q'*x = q'*xm for random vector q - * * the rest are inequality ones, feasible at xm (xm is an inner point for these constraints) - * where xm is some random vector from the feasible hypercube (0.1<=xm[i]<=0.9) - * * optimization problem has form 0.5*x'*A*x-b*x, - * where b is some random vector - * * because constraints are excessive, the main problem is to find - * feasible point; we do not check that algorithm found a solution, - * we just check that it found feasible point. - * - * NOTE: this problem is difficult one (estimates of Lagrange multipliers converge - * slowly), so we use relaxed tolerances - 0.010 for AUL solver - */ - rho = 1000.0; - aulits = 30; - for(n=1; n<=6; n++) - { - - /* - * Generate problem: A, b, BndL, BndU, CMatrix, xm, x1, XStart - */ - k = 2*n; - spdmatrixrndcond(n, 1.0E2, &fulla, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&xm, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_matrix_set_length(&c, k, n+1, _state); - ae_vector_set_length(&ct, k, _state); - for(i=0; i<=n-1; i++) - { - xm.ptr.p_double[i] = 0.1+0.8*ae_randomreal(_state); - bndl.ptr.p_double[i] = 0.0; - bndu.ptr.p_double[i] = 1.0; - x0.ptr.p_double[i] = (double)(ae_randominteger(2, _state)); - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=n/2-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - v = v+c.ptr.pp_double[i][j]*xm.ptr.p_double[j]; - } - c.ptr.pp_double[i][n] = v; - ct.ptr.p_int[i] = 0; - } - for(i=n/2; i<=k-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state)/ae_sqrt((double)(n), _state); - v = v+c.ptr.pp_double[i][j]*xm.ptr.p_double[j]; - } - c.ptr.pp_double[i][n] = v; - ct.ptr.p_int[i] = 2*hqrnduniformi(&rs, 2, _state)-1; - if( ct.ptr.p_int[i]>0 ) - { - c.ptr.pp_double[i][n] = c.ptr.pp_double[i][n]-0.1; - } - else - { - c.ptr.pp_double[i][n] = c.ptr.pp_double[i][n]+0.1; - } - } - - /* - * Create optimizer, solve - */ - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, rho, aulits, _state); - tolx = 0.0050; - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - tolx = 0.0010; - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - tolx = 0.0010; - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetbc(&state, &bndl, &bndu, _state); - minnlcsetlc(&state, &c, &ct, k, _state); - minnlcsetcond(&state, 1.0E-7, 0, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minnlcoptguardsmoothness(&state, hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel+1, _state), _state); - } - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.j.ptr.pp_double[0][i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:1309"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:1310"); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minnlcoptguardresults(&state, &ogrep, _state); - ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:1314"); - } - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=k-1; i++) - { - v = ae_v_dotproduct(&x1.ptr.p_double[0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - if( ct.ptr.p_int[i]==0 ) - { - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(v-c.ptr.pp_double[i][n], _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:1322"); - } - if( ct.ptr.p_int[i]>0 ) - { - ae_set_error_flag(wereerrors, ae_fp_less(v,c.ptr.pp_double[i][n]-tolx), __FILE__, __LINE__, "testminnlcunit.ap:1324"); - } - if( ct.ptr.p_int[i]<0 ) - { - ae_set_error_flag(wereerrors, ae_fp_greater(v,c.ptr.pp_double[i][n]+tolx), __FILE__, __LINE__, "testminnlcunit.ap:1326"); - } - } - } - - /* - * Boundary and linear equality constrained QP problem, - * test checks that different starting points yield same final point: - * * random N from [1..6], random K from [1..N-1] - * * N*N SPD A with moderate condtion number (important!) - * * boundary constraints 0<=x[i]<=1 - * * K=-2; bscale--) - { - - /* - * Generate A, B and initial point - */ - ae_matrix_set_length(&a, n, n, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = ae_pow((double)(10), (double)(bscale), _state)*hqrndnormal(&rs, _state); - x.ptr.p_double[i] = 0.0; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - } - if( akind==1 ) - { - - /* - * Dense well conditioned SPD - */ - spdmatrixrndcond(n, 50.0, &a, _state); - } - if( solvertype!=0 ) - { - - /* - * AUL performs poorly on such problems, - * but SLP works goo. - */ - if( akind==2 ) - { - - /* - * Dense well conditioned indefinite - */ - smatrixrndcond(n, 50.0, &a, _state); - } - if( akind==3 ) - { - - /* - * Low rank - */ - ae_vector_set_length(&tmp, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 0.0; - } - a.ptr.pp_double[i][i] = 1.0E-9; - } - for(k=1; k<=ae_minint(3, n-1, _state); k++) - { - for(i=0; i<=n-1; i++) - { - tmp.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - v = hqrndnormal(&rs, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j]; - } - } - } - } - } - - /* - * Generate constraints - */ - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - for(i=0; i<=n-1; i++) - { - bl.ptr.p_double[i] = -1.0; - bu.ptr.p_double[i] = 1.0; - } - ccnt = ae_minint(3, n-1, _state); - ae_matrix_set_length(&c, ccnt, n+1, _state); - ae_vector_set_length(&ct, ccnt, _state); - for(i=0; i<=ccnt-1; i++) - { - ct.ptr.p_int[i] = hqrnduniformi(&rs, 3, _state)-1; - c.ptr.pp_double[i][n] = 0.0; - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5; - } - c.ptr.pp_double[i][i] = c.ptr.pp_double[i][i]+4; - } - - /* - * Create and optimize - */ - minnlccreate(n, &x, &state, _state); - minnlcsetbc(&state, &bl, &bu, _state); - minnlcsetlc(&state, &c, &ct, ccnt, _state); - minnlcsetcond(&state, 1.0E-7, 0, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, 1000.0, 10, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minnlcoptguardsmoothness(&state, hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel+1, _state), _state); - } - while(minnlciteration(&state, _state)) - { - ae_assert(state.needfij, "Assertion failed", _state); - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+state.x.ptr.p_double[i]*b.ptr.p_double[i]; - state.j.ptr.pp_double[0][i] = b.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*v; - state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+v; - } - } - minnlcresults(&state, &xs0, &rep, _state); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:1817"); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minnlcoptguardresults(&state, &ogrep, _state); - ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:1821"); - } - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * 1. evaluate unconstrained gradient at solution - * - * 2. calculate constrained gradient (NNLS solver is used - * to evaluate gradient subject to active constraints). - * In order to do this we form CE matrix, matrix of active - * constraints (columns store constraint vectors). Then - * we try to approximate gradient vector by columns of CE, - * subject to non-negativity restriction placed on variables - * corresponding to inequality constraints. - * - * Residual from such regression is a constrained gradient vector. - */ - ae_vector_set_length(&g, n, _state); - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xs0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - g.ptr.p_double[i] = v+b.ptr.p_double[i]; - } - ae_matrix_set_length(&ce, n, n+ccnt, _state); - ae_vector_set_length(&nonnegative, n+ccnt, _state); - k = 0; - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(wereerrors, ae_fp_less(xs0.ptr.p_double[i],bl.ptr.p_double[i]-tolconstr), __FILE__, __LINE__, "testminnlcunit.ap:1850"); - ae_set_error_flag(wereerrors, ae_fp_greater(xs0.ptr.p_double[i],bu.ptr.p_double[i]+tolconstr), __FILE__, __LINE__, "testminnlcunit.ap:1851"); - if( ae_fp_less_eq(xs0.ptr.p_double[i],bl.ptr.p_double[i]+tolconstr) ) - { - for(j=0; j<=n-1; j++) - { - ce.ptr.pp_double[j][k] = 0.0; - } - ce.ptr.pp_double[i][k] = 1.0; - nonnegative.ptr.p_bool[k] = ae_true; - inc(&k, _state); - continue; - } - if( ae_fp_greater_eq(xs0.ptr.p_double[i],bu.ptr.p_double[i]-tolconstr) ) - { - for(j=0; j<=n-1; j++) - { - ce.ptr.pp_double[j][k] = 0.0; - } - ce.ptr.pp_double[i][k] = -1.0; - nonnegative.ptr.p_bool[k] = ae_true; - inc(&k, _state); - continue; - } - } - for(i=0; i<=ccnt-1; i++) - { - v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &xs0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = v-c.ptr.pp_double[i][n]; - ae_set_error_flag(wereerrors, ct.ptr.p_int[i]==0&&ae_fp_greater(ae_fabs(v, _state),tolconstr), __FILE__, __LINE__, "testminnlcunit.ap:1875"); - ae_set_error_flag(wereerrors, ct.ptr.p_int[i]>0&&ae_fp_less(v,-tolconstr), __FILE__, __LINE__, "testminnlcunit.ap:1876"); - ae_set_error_flag(wereerrors, ct.ptr.p_int[i]<0&&ae_fp_greater(v,tolconstr), __FILE__, __LINE__, "testminnlcunit.ap:1877"); - if( ct.ptr.p_int[i]==0 ) - { - for(j=0; j<=n-1; j++) - { - ce.ptr.pp_double[j][k] = c.ptr.pp_double[i][j]; - } - nonnegative.ptr.p_bool[k] = ae_false; - inc(&k, _state); - continue; - } - if( (ct.ptr.p_int[i]>0&&ae_fp_less_eq(v,tolconstr))||(ct.ptr.p_int[i]<0&&ae_fp_greater_eq(v,-tolconstr)) ) - { - for(j=0; j<=n-1; j++) - { - ce.ptr.pp_double[j][k] = ae_sign((double)(ct.ptr.p_int[i]), _state)*c.ptr.pp_double[i][j]; - } - nonnegative.ptr.p_bool[k] = ae_true; - inc(&k, _state); - continue; - } - } - snnlsinit(0, 0, 0, &nnls, _state); - snnlssetproblem(&nnls, &ce, &g, 0, k, n, _state); - for(i=0; i<=k-1; i++) - { - if( !nonnegative.ptr.p_bool[i] ) - { - snnlsdropnnc(&nnls, i, _state); - } - } - snnlssolve(&nnls, &tmp, _state); - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - g.ptr.p_double[j] = g.ptr.p_double[j]-tmp.ptr.p_double[i]*ce.ptr.pp_double[j][i]; - } - } - vv = ae_v_dotproduct(&g.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,n-1)); - vv = ae_sqrt(vv, _state); - ae_set_error_flag(wereerrors, ae_fp_greater(vv,1.0E-3), __FILE__, __LINE__, "testminnlcunit.ap:1906"); - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests nonlinearly constrained quadratic programming algorithm. - -Sets error flag on failure. -*************************************************************************/ -static void testminnlcunit_testnlc(ae_bool* wereerrors, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t n2; - double tolx; - double tolg; - ae_int_t aulits; - double rho; - minnlcstate state; - minnlcreport rep; - optguardreport ogrep; - ae_int_t scaletype; - ae_vector x0; - ae_vector x1; - ae_vector b; - ae_vector bndl; - ae_vector bndu; - ae_vector s; - ae_vector g; - ae_vector rnlc; - ae_vector ckind; - ae_matrix fulla; - ae_matrix c; - ae_vector ct; - ae_int_t cntbc; - ae_int_t cntlc; - ae_int_t cntnlec; - ae_int_t cntnlic; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t pass; - ae_int_t klc; - ae_int_t knlec; - ae_int_t knlic; - double v; - double vv; - double vx; - double vy; - double gnorm2; - double rawgnorm2; - hqrndstate rs; - ae_int_t prectype; - ae_int_t solvertype; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&ogrep, 0, sizeof(ogrep)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&b, 0, sizeof(b)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&s, 0, sizeof(s)); - memset(&g, 0, sizeof(g)); - memset(&rnlc, 0, sizeof(rnlc)); - memset(&ckind, 0, sizeof(ckind)); - memset(&fulla, 0, sizeof(fulla)); - memset(&c, 0, sizeof(c)); - memset(&ct, 0, sizeof(ct)); - memset(&rs, 0, sizeof(rs)); - _minnlcstate_init(&state, _state, ae_true); - _minnlcreport_init(&rep, _state, ae_true); - _optguardreport_init(&ogrep, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&g, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rnlc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ckind, 0, DT_INT, _state, ae_true); - ae_matrix_init(&fulla, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - for(solvertype=0; solvertype<=testminnlcunit_maxsolvertype; solvertype++) - { - - /* - * Basic test: - * * 2-dimensional problem - * * target function F(x0,x1) = (x0-1)^2 + (x1-1)^2 - * * one nonlinear constraint Z(x0,x1) = x0^2+x1^2-1, - * which is tried as equality and inequality one - */ - rho = 200.0; - tolx = 0.0005; - aulits = 50; - n = 2; - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, rho, aulits, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetcond(&state, 1.0E-7, 0, _state); - minnlcsetnlc(&state, 0, 1, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = ae_sqr(state.x.ptr.p_double[0]-1, _state)+ae_sqr(state.x.ptr.p_double[1]-1, _state); - state.j.ptr.pp_double[0][0] = 2*(state.x.ptr.p_double[0]-1); - state.j.ptr.pp_double[0][1] = 2*(state.x.ptr.p_double[1]-1); - state.fi.ptr.p_double[1] = ae_sqr(state.x.ptr.p_double[0], _state)+ae_sqr(state.x.ptr.p_double[1], _state)-1; - state.j.ptr.pp_double[1][0] = 2*state.x.ptr.p_double[0]; - state.j.ptr.pp_double[1][1] = 2*state.x.ptr.p_double[1]; - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:1992"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:1993"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[0]-ae_sqrt((double)(2), _state)/2, _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:1996"); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[1]-ae_sqrt((double)(2), _state)/2, _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:1997"); - minnlcsetnlc(&state, 1, 0, _state); - minnlcrestartfrom(&state, &x0, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minnlcoptguardsmoothness(&state, hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel+1, _state), _state); - } - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = ae_sqr(state.x.ptr.p_double[0]-1, _state)+ae_sqr(state.x.ptr.p_double[1]-1, _state); - state.j.ptr.pp_double[0][0] = 2*(state.x.ptr.p_double[0]-1); - state.j.ptr.pp_double[0][1] = 2*(state.x.ptr.p_double[1]-1); - state.fi.ptr.p_double[1] = ae_sqr(state.x.ptr.p_double[0], _state)+ae_sqr(state.x.ptr.p_double[1], _state)-1; - state.j.ptr.pp_double[1][0] = 2*state.x.ptr.p_double[0]; - state.j.ptr.pp_double[1][1] = 2*state.x.ptr.p_double[1]; - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:2017"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:2018"); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minnlcoptguardresults(&state, &ogrep, _state); - ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:2022"); - } - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[0]-ae_sqrt((double)(2), _state)/2, _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:2026"); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[1]-ae_sqrt((double)(2), _state)/2, _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:2027"); - - /* - * This test checks correctness of scaling being applied to nonlinear - * constraints. We solve bound constrained scaled problem and check - * that solution is correct. - */ - aulits = 50; - rho = 200.0; - tolx = 0.0005; - tolg = 0.01; - for(n=1; n<=10; n++) - { - for(pass=1; pass<=10; pass++) - { - - /* - * Generate well-conditioned problem with unit scale - */ - spdmatrixrndcond(n, 1.0E2, &fulla, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - cntnlec = hqrnduniformi(&rs, n, _state); - cntnlic = n-cntnlec; - for(i=0; i<=cntnlec-1; i++) - { - bndl.ptr.p_double[i] = hqrndnormal(&rs, _state); - bndu.ptr.p_double[i] = bndl.ptr.p_double[i]; - } - for(i=cntnlec; i<=n-1; i++) - { - bndl.ptr.p_double[i] = hqrndnormal(&rs, _state); - bndu.ptr.p_double[i] = bndl.ptr.p_double[i]+0.5; - } - - /* - * Apply scaling to quadratic/linear term, so problem becomes - * well-conditioned in the scaled coordinates. - */ - scaletype = hqrnduniformi(&rs, 2, _state); - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - if( scaletype==0 ) - { - s.ptr.p_double[i] = (double)(1); - } - else - { - s.ptr.p_double[i] = ae_exp(5*hqrndnormal(&rs, _state), _state); - } - } - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = x0.ptr.p_double[i]*s.ptr.p_double[i]; - bndl.ptr.p_double[i] = bndl.ptr.p_double[i]*s.ptr.p_double[i]; - bndu.ptr.p_double[i] = bndu.ptr.p_double[i]*s.ptr.p_double[i]; - b.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - fulla.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]); - } - } - - /* - * Solve problem with boundary constraints posed as nonlinear ones - */ - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, rho, aulits, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetscale(&state, &s, _state); - minnlcsetnlc(&state, cntnlec, 2*cntnlic, _state); - minnlcsetcond(&state, 1.0E-7, 0, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minnlcoptguardsmoothness(&state, hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel+1, _state), _state); - } - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - for(i=0; i<=cntnlec+2*cntnlic; i++) - { - state.fi.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - state.j.ptr.pp_double[i][j] = (double)(0); - } - } - - /* - * Function itself - */ - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.j.ptr.pp_double[0][i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - - /* - * Equality constraints - */ - for(i=0; i<=cntnlec-1; i++) - { - state.fi.ptr.p_double[1+i] = (state.x.ptr.p_double[i]-bndl.ptr.p_double[i])/s.ptr.p_double[i]; - state.j.ptr.pp_double[1+i][i] = 1/s.ptr.p_double[i]; - } - - /* - * Inequality constraints - */ - for(i=0; i<=cntnlic-1; i++) - { - k = cntnlec+i; - state.fi.ptr.p_double[1+cntnlec+2*i+0] = (bndl.ptr.p_double[k]-state.x.ptr.p_double[k])/s.ptr.p_double[k]; - state.j.ptr.pp_double[1+cntnlec+2*i+0][k] = -1/s.ptr.p_double[k]; - state.fi.ptr.p_double[1+cntnlec+2*i+1] = (state.x.ptr.p_double[k]-bndu.ptr.p_double[k])/s.ptr.p_double[k]; - state.j.ptr.pp_double[1+cntnlec+2*i+1][k] = 1/s.ptr.p_double[k]; - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:2161"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:2162"); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minnlcoptguardresults(&state, &ogrep, _state); - ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:2166"); - } - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check feasibility properties - */ - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(wereerrors, ae_isfinite(bndl.ptr.p_double[i], _state)&&ae_fp_less_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i]-tolx*s.ptr.p_double[i]), __FILE__, __LINE__, "testminnlcunit.ap:2176"); - ae_set_error_flag(wereerrors, ae_isfinite(bndu.ptr.p_double[i], _state)&&ae_fp_greater_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i]+tolx*s.ptr.p_double[i]), __FILE__, __LINE__, "testminnlcunit.ap:2177"); - } - - /* - * Test - calculate scaled constrained gradient at solution, - * check its norm. - */ - ae_vector_set_length(&g, n, _state); - gnorm2 = 0.0; - for(i=0; i<=n-1; i++) - { - g.ptr.p_double[i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - g.ptr.p_double[i] = g.ptr.p_double[i]+fulla.ptr.pp_double[i][j]*x1.ptr.p_double[j]; - } - g.ptr.p_double[i] = s.ptr.p_double[i]*g.ptr.p_double[i]; - if( (ae_isfinite(bndl.ptr.p_double[i], _state)&&ae_fp_less(ae_fabs(x1.ptr.p_double[i]-bndl.ptr.p_double[i], _state),tolx*s.ptr.p_double[i]))&&ae_fp_greater(g.ptr.p_double[i],(double)(0)) ) - { - g.ptr.p_double[i] = (double)(0); - } - if( (ae_isfinite(bndu.ptr.p_double[i], _state)&&ae_fp_less(ae_fabs(x1.ptr.p_double[i]-bndu.ptr.p_double[i], _state),tolx*s.ptr.p_double[i]))&&ae_fp_less(g.ptr.p_double[i],(double)(0)) ) - { - g.ptr.p_double[i] = (double)(0); - } - gnorm2 = gnorm2+ae_sqr(g.ptr.p_double[i], _state); - } - ae_set_error_flag(wereerrors, ae_fp_greater(gnorm2,ae_sqr(tolg, _state)), __FILE__, __LINE__, "testminnlcunit.ap:2199"); - } - } - - /* - * Complex problem with mix of boundary, linear and nonlinear constraints: - * * quadratic target function f(x) = 0.5*x'*A*x + b'*x - * * unit scaling is used - * * problem size N is even - * * all variables are divided into pairs: x[0] and x[1], x[2] and x[3], ... - * * constraints are set for pairs of variables, i.e. each constraint involves - * only pair of adjacent variables (x0/x1, x2/x3, x4/x5 and so on), and each - * pair of variables has at most one constraint which binds them - * * for variables u and v following kinds of constraints can be randomly set: - * * CKind=0 no constraint - * * CKind=1 boundary equality constraint: u=a, v=b - * * CKind=2 boundary inequality constraint: a0<=u<=b0, a1<=v<=b1 - * * CKind=3 linear equality constraint: a*u+b*v = c - * * CKind=4 linear inequality constraint: a*u+b*v <= c - * * CKind=5 nonlinear equality constraint: u^2+v^2 = 1 - * * CKind=6 nonlinear inequality constraint: u^2+v^2 <= 1 - * * it is relatively easy to calculated projected gradient for such problem - */ - aulits = 50; - rho = 200.0; - tolx = 0.0005; - tolg = 0.005; - n = 20; - n2 = n/2; - for(pass=1; pass<=5; pass++) - { - for(prectype=1; prectype<=2; prectype++) - { - - /* - * Generate well-conditioned problem with unit scale - */ - spdmatrixrndcond(n, 1.0E2, &fulla, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_matrix_set_length(&c, n, n+1, _state); - ae_vector_set_length(&ct, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&ckind, n2, _state); - ae_vector_set_length(&rnlc, n2, _state); - cntbc = 0; - cntlc = 0; - cntnlec = 0; - cntnlic = 0; - for(i=0; i<=n-1; i++) - { - bndl.ptr.p_double[i] = _state->v_neginf; - bndu.ptr.p_double[i] = _state->v_posinf; - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - b.ptr.p_double[i] = 10*hqrndnormal(&rs, _state); - } - for(i=0; i<=n2-1; i++) - { - ckind.ptr.p_int[i] = hqrnduniformi(&rs, 7, _state); - rnlc.ptr.p_double[i] = (double)(0); - if( ckind.ptr.p_int[i]==0 ) - { - - /* - * Unconstrained - */ - continue; - } - if( ckind.ptr.p_int[i]==1 ) - { - - /* - * Bound equality constrained - */ - bndl.ptr.p_double[2*i+0] = hqrnduniformr(&rs, _state)-0.5; - bndu.ptr.p_double[2*i+0] = bndl.ptr.p_double[2*i+0]; - bndl.ptr.p_double[2*i+1] = hqrnduniformr(&rs, _state)-0.5; - bndu.ptr.p_double[2*i+1] = bndl.ptr.p_double[2*i+1]; - inc(&cntbc, _state); - continue; - } - if( ckind.ptr.p_int[i]==2 ) - { - - /* - * Bound inequality constrained - */ - bndl.ptr.p_double[2*i+0] = hqrnduniformr(&rs, _state)-0.5; - bndu.ptr.p_double[2*i+0] = bndl.ptr.p_double[2*i+0]+0.5; - bndl.ptr.p_double[2*i+1] = hqrnduniformr(&rs, _state)-0.5; - bndu.ptr.p_double[2*i+1] = bndl.ptr.p_double[2*i+1]+0.5; - inc(&cntbc, _state); - continue; - } - if( ckind.ptr.p_int[i]==3 ) - { - - /* - * Linear equality constrained - */ - for(j=0; j<=n; j++) - { - c.ptr.pp_double[cntlc][j] = 0.0; - } - vx = hqrnduniformr(&rs, _state)-0.5; - vy = hqrnduniformr(&rs, _state)-0.5; - c.ptr.pp_double[cntlc][2*i+0] = vx; - c.ptr.pp_double[cntlc][2*i+1] = vy; - c.ptr.pp_double[cntlc][n] = hqrnduniformr(&rs, _state)-0.5; - ct.ptr.p_int[cntlc] = 0; - inc(&cntlc, _state); - continue; - } - if( ckind.ptr.p_int[i]==4 ) - { - - /* - * Linear inequality constrained - */ - for(j=0; j<=n; j++) - { - c.ptr.pp_double[cntlc][j] = 0.0; - } - vx = hqrnduniformr(&rs, _state)-0.5; - vy = hqrnduniformr(&rs, _state)-0.5; - c.ptr.pp_double[cntlc][2*i+0] = vx; - c.ptr.pp_double[cntlc][2*i+1] = vy; - c.ptr.pp_double[cntlc][n] = hqrnduniformr(&rs, _state)-0.5; - ct.ptr.p_int[cntlc] = -1; - inc(&cntlc, _state); - continue; - } - if( ckind.ptr.p_int[i]==5 ) - { - - /* - * Nonlinear equality constrained - */ - rnlc.ptr.p_double[i] = 0.5+hqrnduniformr(&rs, _state); - inc(&cntnlec, _state); - continue; - } - if( ckind.ptr.p_int[i]==6 ) - { - - /* - * Nonlinear inequality constrained - */ - rnlc.ptr.p_double[i] = 0.5+hqrnduniformr(&rs, _state); - inc(&cntnlic, _state); - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - - /* - * Solve problem - */ - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, rho, aulits, _state); - minnlcsetcond(&state, 1.0E-7, 0, _state); - if( prectype==0 ) - { - minnlcsetprecinexact(&state, _state); - } - if( prectype==1 ) - { - minnlcsetprecexactlowrank(&state, 0, _state); - } - if( prectype==2 ) - { - minnlcsetprecexactrobust(&state, 0, _state); - } - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - minnlcsetcond(&state, 1.0E-6, 0, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - minnlcsetcond(&state, 1.0E-6, 0, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetbc(&state, &bndl, &bndu, _state); - minnlcsetlc(&state, &c, &ct, cntlc, _state); - minnlcsetnlc(&state, cntnlec, cntnlic, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minnlcoptguardsmoothness(&state, hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel+1, _state), _state); - } - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - - /* - * Evaluate target function - */ - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.j.ptr.pp_double[0][i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - - /* - * Evaluate constraint functions - */ - knlec = 1; - knlic = 1+cntnlec; - for(i=0; i<=n2-1; i++) - { - if( ckind.ptr.p_int[i]==5 ) - { - state.fi.ptr.p_double[knlec] = (double)(0); - for(j=0; j<=n-1; j++) - { - state.j.ptr.pp_double[knlec][j] = 0.0; - } - state.fi.ptr.p_double[knlec] = ae_sqr(state.x.ptr.p_double[2*i+0], _state)+ae_sqr(state.x.ptr.p_double[2*i+1], _state)-rnlc.ptr.p_double[i]; - state.j.ptr.pp_double[knlec][2*i+0] = 2*state.x.ptr.p_double[2*i+0]; - state.j.ptr.pp_double[knlec][2*i+1] = 2*state.x.ptr.p_double[2*i+1]; - inc(&knlec, _state); - continue; - } - if( ckind.ptr.p_int[i]==6 ) - { - state.fi.ptr.p_double[knlic] = (double)(0); - for(j=0; j<=n-1; j++) - { - state.j.ptr.pp_double[knlic][j] = 0.0; - } - state.fi.ptr.p_double[knlic] = ae_sqr(state.x.ptr.p_double[2*i+0], _state)+ae_sqr(state.x.ptr.p_double[2*i+1], _state)-rnlc.ptr.p_double[i]; - state.j.ptr.pp_double[knlic][2*i+0] = 2*state.x.ptr.p_double[2*i+0]; - state.j.ptr.pp_double[knlic][2*i+1] = 2*state.x.ptr.p_double[2*i+1]; - inc(&knlic, _state); - continue; - } - } - ae_assert(knlec==1+cntnlec, "Assertion failed", _state); - ae_assert(knlic==1+cntnlec+cntnlic, "Assertion failed", _state); - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:2430"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:2431"); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - minnlcoptguardresults(&state, &ogrep, _state); - ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:2435"); - } - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check feasibility properties - */ - klc = 0; - for(i=0; i<=n2-1; i++) - { - if( ckind.ptr.p_int[i]==0 ) - { - - /* - * Unconstrained - */ - continue; - } - if( ckind.ptr.p_int[i]==1 ) - { - - /* - * Bound equality constrained - */ - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[2*i+0]-bndl.ptr.p_double[2*i+0], _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:2458"); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[2*i+1]-bndl.ptr.p_double[2*i+1], _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:2459"); - continue; - } - if( ckind.ptr.p_int[i]==2 ) - { - - /* - * Bound inequality constrained - */ - ae_set_error_flag(wereerrors, ae_fp_less(x1.ptr.p_double[2*i+0],bndl.ptr.p_double[2*i+0]-tolx), __FILE__, __LINE__, "testminnlcunit.ap:2467"); - ae_set_error_flag(wereerrors, ae_fp_greater(x1.ptr.p_double[2*i+0],bndu.ptr.p_double[2*i+0]+tolx), __FILE__, __LINE__, "testminnlcunit.ap:2468"); - ae_set_error_flag(wereerrors, ae_fp_less(x1.ptr.p_double[2*i+1],bndl.ptr.p_double[2*i+1]-tolx), __FILE__, __LINE__, "testminnlcunit.ap:2469"); - ae_set_error_flag(wereerrors, ae_fp_greater(x1.ptr.p_double[2*i+1],bndu.ptr.p_double[2*i+1]+tolx), __FILE__, __LINE__, "testminnlcunit.ap:2470"); - continue; - } - if( ckind.ptr.p_int[i]==3 ) - { - - /* - * Linear equality constrained - */ - v = x1.ptr.p_double[2*i+0]*c.ptr.pp_double[klc][2*i+0]+x1.ptr.p_double[2*i+1]*c.ptr.pp_double[klc][2*i+1]-c.ptr.pp_double[klc][n]; - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(v, _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:2479"); - inc(&klc, _state); - continue; - } - if( ckind.ptr.p_int[i]==4 ) - { - - /* - * Linear inequality constrained - */ - v = x1.ptr.p_double[2*i+0]*c.ptr.pp_double[klc][2*i+0]+x1.ptr.p_double[2*i+1]*c.ptr.pp_double[klc][2*i+1]-c.ptr.pp_double[klc][n]; - ae_set_error_flag(wereerrors, ae_fp_greater(v,tolx), __FILE__, __LINE__, "testminnlcunit.ap:2489"); - inc(&klc, _state); - continue; - } - if( ckind.ptr.p_int[i]==5 ) - { - - /* - * Nonlinear equality constrained - */ - v = ae_sqr(x1.ptr.p_double[2*i+0], _state)+ae_sqr(x1.ptr.p_double[2*i+1], _state)-rnlc.ptr.p_double[i]; - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(v, _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:2499"); - continue; - } - if( ckind.ptr.p_int[i]==6 ) - { - - /* - * Nonlinear inequality constrained - */ - v = ae_sqr(x1.ptr.p_double[2*i+0], _state)+ae_sqr(x1.ptr.p_double[2*i+1], _state)-rnlc.ptr.p_double[i]; - ae_set_error_flag(wereerrors, ae_fp_greater(v,tolx), __FILE__, __LINE__, "testminnlcunit.ap:2508"); - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - - /* - * Test - calculate scaled constrained gradient at solution, - * check its norm. - */ - gnorm2 = 0.0; - rawgnorm2 = (double)(0); - ae_vector_set_length(&g, n, _state); - for(i=0; i<=n-1; i++) - { - v = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - v = v+fulla.ptr.pp_double[i][j]*x1.ptr.p_double[j]; - } - g.ptr.p_double[i] = v; - rawgnorm2 = rawgnorm2+v*v; - } - klc = 0; - for(i=0; i<=n2-1; i++) - { - if( ckind.ptr.p_int[i]==0 ) - { - - /* - * Unconstrained - */ - gnorm2 = gnorm2+ae_sqr(g.ptr.p_double[2*i+0], _state)+ae_sqr(g.ptr.p_double[2*i+1], _state); - ae_set_error_flag(wereerrors, ae_fp_greater(gnorm2,ae_sqr(tolg, _state)*ae_maxreal(rawgnorm2, 1.0, _state)), __FILE__, __LINE__, "testminnlcunit.ap:2538"); - continue; - } - if( ckind.ptr.p_int[i]==1 ) - { - - /* - * Bound equality constrained, unconditionally set gradient to zero - */ - g.ptr.p_double[2*i+0] = 0.0; - g.ptr.p_double[2*i+1] = 0.0; - gnorm2 = gnorm2+ae_sqr(g.ptr.p_double[2*i+0], _state)+ae_sqr(g.ptr.p_double[2*i+1], _state); - ae_set_error_flag(wereerrors, ae_fp_greater(gnorm2,ae_sqr(tolg, _state)*ae_maxreal(rawgnorm2, 1.0, _state)), __FILE__, __LINE__, "testminnlcunit.ap:2549"); - continue; - } - if( ckind.ptr.p_int[i]==2 ) - { - - /* - * Bound inequality constrained, conditionally set gradient to zero - * (when constraint is active) - */ - if( ae_fp_less(x1.ptr.p_double[2*i+0],bndl.ptr.p_double[2*i+0]+tolx)||ae_fp_greater(x1.ptr.p_double[2*i+0],bndu.ptr.p_double[2*i+0]-tolx) ) - { - g.ptr.p_double[2*i+0] = 0.0; - } - if( ae_fp_less(x1.ptr.p_double[2*i+1],bndl.ptr.p_double[2*i+1]+tolx)||ae_fp_greater(x1.ptr.p_double[2*i+1],bndu.ptr.p_double[2*i+1]-tolx) ) - { - g.ptr.p_double[2*i+1] = 0.0; - } - gnorm2 = gnorm2+ae_sqr(g.ptr.p_double[2*i+0], _state)+ae_sqr(g.ptr.p_double[2*i+1], _state); - ae_set_error_flag(wereerrors, ae_fp_greater(gnorm2,ae_sqr(tolg, _state)*ae_maxreal(rawgnorm2, 1.0, _state)), __FILE__, __LINE__, "testminnlcunit.ap:2563"); - continue; - } - if( ckind.ptr.p_int[i]==3 ) - { - - /* - * Linear equality constrained, unconditionally project gradient into - * equality constrained subspace - */ - v = g.ptr.p_double[2*i+0]*c.ptr.pp_double[klc][2*i+0]+g.ptr.p_double[2*i+1]*c.ptr.pp_double[klc][2*i+1]; - vv = ae_sqr(c.ptr.pp_double[klc][2*i+0], _state)+ae_sqr(c.ptr.pp_double[klc][2*i+1], _state); - g.ptr.p_double[2*i+0] = g.ptr.p_double[2*i+0]-c.ptr.pp_double[klc][2*i+0]*(v/vv); - g.ptr.p_double[2*i+1] = g.ptr.p_double[2*i+1]-c.ptr.pp_double[klc][2*i+1]*(v/vv); - inc(&klc, _state); - gnorm2 = gnorm2+ae_sqr(g.ptr.p_double[2*i+0], _state)+ae_sqr(g.ptr.p_double[2*i+1], _state); - ae_set_error_flag(wereerrors, ae_fp_greater(gnorm2,ae_sqr(tolg, _state)*ae_maxreal(rawgnorm2, 1.0, _state)), __FILE__, __LINE__, "testminnlcunit.ap:2578"); - continue; - } - if( ckind.ptr.p_int[i]==4 ) - { - - /* - * Linear inequality constrained, conditionally project gradient - * (when constraint is active) - */ - v = x1.ptr.p_double[2*i+0]*c.ptr.pp_double[klc][2*i+0]+x1.ptr.p_double[2*i+1]*c.ptr.pp_double[klc][2*i+1]-c.ptr.pp_double[klc][n]; - if( ae_fp_greater(v,-tolx) ) - { - v = g.ptr.p_double[2*i+0]*c.ptr.pp_double[klc][2*i+0]+g.ptr.p_double[2*i+1]*c.ptr.pp_double[klc][2*i+1]; - vv = ae_sqr(c.ptr.pp_double[klc][2*i+0], _state)+ae_sqr(c.ptr.pp_double[klc][2*i+1], _state); - g.ptr.p_double[2*i+0] = g.ptr.p_double[2*i+0]-c.ptr.pp_double[klc][2*i+0]*(v/vv); - g.ptr.p_double[2*i+1] = g.ptr.p_double[2*i+1]-c.ptr.pp_double[klc][2*i+1]*(v/vv); - } - inc(&klc, _state); - gnorm2 = gnorm2+ae_sqr(g.ptr.p_double[2*i+0], _state)+ae_sqr(g.ptr.p_double[2*i+1], _state); - ae_set_error_flag(wereerrors, ae_fp_greater(gnorm2,ae_sqr(tolg, _state)*ae_maxreal(rawgnorm2, 1.0, _state)), __FILE__, __LINE__, "testminnlcunit.ap:2597"); - continue; - } - if( ckind.ptr.p_int[i]==5 ) - { - - /* - * Nonlinear equality constrained, unconditionally project gradient - * - * NOTE: here we rely on the fact that corresponding components of X - * sum to one. - */ - v = coalesce(ae_sqrt(ae_sqr(x1.ptr.p_double[2*i+0], _state)+ae_sqr(x1.ptr.p_double[2*i+1], _state), _state), 1.0, _state); - vx = x1.ptr.p_double[2*i+0]/v; - vy = x1.ptr.p_double[2*i+1]/v; - v = g.ptr.p_double[2*i+0]*vx+g.ptr.p_double[2*i+1]*vy; - g.ptr.p_double[2*i+0] = g.ptr.p_double[2*i+0]-vx*v; - g.ptr.p_double[2*i+1] = g.ptr.p_double[2*i+1]-vy*v; - gnorm2 = gnorm2+ae_sqr(g.ptr.p_double[2*i+0], _state)+ae_sqr(g.ptr.p_double[2*i+1], _state); - ae_set_error_flag(wereerrors, ae_fp_greater(gnorm2,ae_sqr(tolg, _state)*ae_maxreal(rawgnorm2, 1.0, _state)), __FILE__, __LINE__, "testminnlcunit.ap:2615"); - continue; - } - if( ckind.ptr.p_int[i]==6 ) - { - - /* - * Nonlinear inequality constrained, conditionally project gradient - * (when constraint is active) - * - * NOTE: here we rely on the fact that corresponding components of X - * sum to one. - */ - v = ae_sqr(x1.ptr.p_double[2*i+0], _state)+ae_sqr(x1.ptr.p_double[2*i+1], _state)-rnlc.ptr.p_double[i]; - if( ae_fp_greater(v,-tolx) ) - { - v = coalesce(ae_sqrt(ae_sqr(x1.ptr.p_double[2*i+0], _state)+ae_sqr(x1.ptr.p_double[2*i+1], _state), _state), 1.0, _state); - vx = x1.ptr.p_double[2*i+0]/v; - vy = x1.ptr.p_double[2*i+1]/v; - v = g.ptr.p_double[2*i+0]*vx+g.ptr.p_double[2*i+1]*vy; - g.ptr.p_double[2*i+0] = g.ptr.p_double[2*i+0]-vx*v; - g.ptr.p_double[2*i+1] = g.ptr.p_double[2*i+1]-vy*v; - } - gnorm2 = gnorm2+ae_sqr(g.ptr.p_double[2*i+0], _state)+ae_sqr(g.ptr.p_double[2*i+1], _state); - ae_set_error_flag(wereerrors, ae_fp_greater(gnorm2,ae_sqr(tolg, _state)*ae_maxreal(rawgnorm2, 1.0, _state)), __FILE__, __LINE__, "testminnlcunit.ap:2638"); - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function performs additional tests - -On failure sets error flag. -*************************************************************************/ -static void testminnlcunit_testother(ae_bool* wereerrors, - ae_state *_state) -{ - ae_frame _frame_block; - hqrndstate rs; - double v; - double h; - double fl; - double fr; - double fl2; - double fr2; - double dfl; - double dfr; - double dfl2; - double dfr2; - double d2fl; - double d2fr; - double d2fl2; - double d2fr2; - double f0; - double df; - double d2f; - double ndf; - double nd2f; - double dtol; - double diffstep; - minnlcstate state; - minnlcreport rep; - optguardreport ogrep; - double rho; - ae_int_t aulits; - double tolx; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t n; - ae_vector s; - ae_vector b; - ae_vector x0; - ae_vector x1; - ae_vector x2; - ae_vector x3; - ae_vector xlast; - ae_vector bndl; - ae_vector bndu; - ae_vector xu; - double condv; - ae_matrix a; - ae_matrix c; - ae_matrix fulla; - ae_vector ct; - ae_int_t nlbfgs; - ae_int_t nexactlowrank; - ae_int_t nexactrobust; - ae_int_t nnone; - ae_int_t prectype; - ae_int_t ctype; - ae_int_t trialidx; - ae_int_t blocksize; - ae_int_t blockcnt; - ae_int_t maxits; - ae_int_t spoiliteration; - ae_int_t stopiteration; - ae_int_t spoilvar; - double spoilval; - ae_int_t pass; - ae_int_t solvertype; - ae_int_t badidx0; - ae_int_t badidx1; - ae_int_t nlec; - ae_int_t nlic; - double ss; - ae_int_t stopcallidx; - ae_int_t callidx; - ae_bool terminationrequested; - ae_bool firstrep; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&ogrep, 0, sizeof(ogrep)); - memset(&s, 0, sizeof(s)); - memset(&b, 0, sizeof(b)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&x2, 0, sizeof(x2)); - memset(&x3, 0, sizeof(x3)); - memset(&xlast, 0, sizeof(xlast)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&xu, 0, sizeof(xu)); - memset(&a, 0, sizeof(a)); - memset(&c, 0, sizeof(c)); - memset(&fulla, 0, sizeof(fulla)); - memset(&ct, 0, sizeof(ct)); - _hqrndstate_init(&rs, _state, ae_true); - _minnlcstate_init(&state, _state, ae_true); - _minnlcreport_init(&rep, _state, ae_true); - _optguardreport_init(&ogrep, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x3, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xlast, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xu, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&fulla, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Test equality penalty function (correctly calculated and smooth) - */ - h = 1.0E-4; - v = -0.98; - dtol = 1.0E-3; - while(ae_fp_less_eq(v,0.98)) - { - - /* - * Test numerical derivative; this test also checks continuity of the - * function - */ - minnlcequalitypenaltyfunction(v-2*h, &fl2, &dfl2, &d2fl2, _state); - minnlcequalitypenaltyfunction(v-h, &fl, &dfl, &d2fl, _state); - minnlcequalitypenaltyfunction(v+h, &fr, &dfr, &d2fr, _state); - minnlcequalitypenaltyfunction(v+2*h, &fr2, &dfr2, &d2fr2, _state); - minnlcequalitypenaltyfunction(v, &f0, &df, &d2f, _state); - ndf = (-fr2+8*fr-8*fl+fl2)/(12*h); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(ndf-df, _state),dtol*ae_maxreal(ae_fabs(ndf, _state), (double)(1), _state)), __FILE__, __LINE__, "testminnlcunit.ap:2727"); - nd2f = (-dfr2+8*dfr-8*dfl+dfl2)/(12*h); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(nd2f-d2f, _state),dtol*ae_maxreal(ae_fabs(nd2f, _state), (double)(1), _state)), __FILE__, __LINE__, "testminnlcunit.ap:2729"); - - /* - * Next point - */ - v = v+h; - } - minnlcequalitypenaltyfunction(0.0, &f0, &df, &d2f, _state); - ae_set_error_flag(wereerrors, ae_fp_neq(f0,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:2737"); - ae_set_error_flag(wereerrors, ae_fp_neq(df,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:2738"); - - /* - * Test inequality penalty function (correctly calculated and smooth) - */ - h = 1.0E-4; - v = 0.02; - dtol = 1.0E-3; - while(ae_fp_less_eq(v,2.00)) - { - - /* - * Test numerical derivative; this test also checks continuity of the - * function - */ - minnlcinequalityshiftfunction(v-2*h, &fl2, &dfl2, &d2fl2, _state); - minnlcinequalityshiftfunction(v-h, &fl, &dfl, &d2fl, _state); - minnlcinequalityshiftfunction(v+h, &fr, &dfr, &d2fr, _state); - minnlcinequalityshiftfunction(v+2*h, &fr2, &dfr2, &d2fr2, _state); - minnlcinequalityshiftfunction(v, &f0, &df, &d2f, _state); - ndf = (-fr2+8*fr-8*fl+fl2)/(12*h); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(ndf-df, _state),dtol*ae_maxreal(ae_fabs(ndf, _state), (double)(1), _state)), __FILE__, __LINE__, "testminnlcunit.ap:2762"); - nd2f = (-dfr2+8*dfr-8*dfl+dfl2)/(12*h); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(nd2f-d2f, _state),dtol*ae_maxreal(ae_fabs(nd2f, _state), (double)(1), _state)), __FILE__, __LINE__, "testminnlcunit.ap:2764"); - - /* - * Next point - */ - v = v+h; - } - minnlcinequalityshiftfunction(1.0, &f0, &df, &d2f, _state); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(f0, _state),1.0E-6), __FILE__, __LINE__, "testminnlcunit.ap:2772"); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(df+1, _state),1.0E-6), __FILE__, __LINE__, "testminnlcunit.ap:2773"); - - /* - * Test different properties shared by all solvers - */ - for(solvertype=0; solvertype<=testminnlcunit_maxsolvertype; solvertype++) - { - - /* - * Test location reports - */ - aulits = 50; - rho = 200.0; - n = 2; - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xlast, n, _state); - x0.ptr.p_double[0] = 0.1+0.1*hqrnduniformr(&rs, _state); - x0.ptr.p_double[1] = 0.2+0.1*hqrnduniformr(&rs, _state); - xlast.ptr.p_double[0] = (double)(0); - xlast.ptr.p_double[1] = (double)(0); - firstrep = ae_true; - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, rho, aulits, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetcond(&state, 1.0E-7, 0, _state); - minnlcsetnlc(&state, 0, 1, _state); - minnlcsetxrep(&state, ae_true, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = ae_sqr(state.x.ptr.p_double[0]-1, _state)+ae_sqr(state.x.ptr.p_double[1]-1, _state); - state.j.ptr.pp_double[0][0] = 2*(state.x.ptr.p_double[0]-1); - state.j.ptr.pp_double[0][1] = 2*(state.x.ptr.p_double[1]-1); - state.fi.ptr.p_double[1] = ae_sqr(state.x.ptr.p_double[0], _state)+ae_sqr(state.x.ptr.p_double[1], _state)-1; - state.j.ptr.pp_double[1][0] = 2*state.x.ptr.p_double[0]; - state.j.ptr.pp_double[1][1] = 2*state.x.ptr.p_double[1]; - continue; - } - if( state.xupdated ) - { - - /* - * If first point reported, compare with initial one - */ - if( firstrep ) - { - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(state.x.ptr.p_double[0]-x0.ptr.p_double[0], _state),1.0E4*ae_machineepsilon), __FILE__, __LINE__, "testminnlcunit.ap:2826"); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(state.x.ptr.p_double[1]-x0.ptr.p_double[1], _state),1.0E4*ae_machineepsilon), __FILE__, __LINE__, "testminnlcunit.ap:2827"); - } - firstrep = ae_false; - - /* - * Save last point - */ - xlast.ptr.p_double[0] = state.x.ptr.p_double[0]; - xlast.ptr.p_double[1] = state.x.ptr.p_double[1]; - - /* - * Done - */ - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:2845"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:2846"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[0]-xlast.ptr.p_double[0], _state),1.0E4*ae_machineepsilon), __FILE__, __LINE__, "testminnlcunit.ap:2849"); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[1]-xlast.ptr.p_double[1], _state),1.0E4*ae_machineepsilon), __FILE__, __LINE__, "testminnlcunit.ap:2850"); - - /* - * Test numerical differentiation - */ - aulits = 50; - rho = 200.0; - tolx = 0.001; - diffstep = 0.0001; - n = 2; - ae_vector_set_length(&x0, n, _state); - x0.ptr.p_double[0] = 0.1; - x0.ptr.p_double[1] = 0.2; - minnlccreatef(n, &x0, diffstep, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, rho, aulits, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetcond(&state, 1.0E-7, 0, _state); - minnlcsetnlc(&state, 0, 1, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfi ) - { - state.fi.ptr.p_double[0] = ae_sqr(state.x.ptr.p_double[0]-1, _state)+ae_sqr(state.x.ptr.p_double[1]-1, _state); - state.fi.ptr.p_double[1] = ae_sqr(state.x.ptr.p_double[0], _state)+ae_sqr(state.x.ptr.p_double[1], _state)-1; - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:2886"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:2887"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[0]-ae_sqrt((double)(2), _state)/2, _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:2890"); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[1]-ae_sqrt((double)(2), _state)/2, _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:2891"); - - /* - * Check handling of general linear constraints: solve linearly - * constrained twice, first time with constraints posed as linear - * ones, second time with constraints posed as nonlinear ones. - * - * Linear constraints are normalized because we know that optimizer - * normalizes them internally. - * - * We perform small amount of inner iterations - just 3 steps. - * Only one outer iteration is performed. Such small number of - * iterations allows to reduce influence of round-off errors - * and compare results returned by different control paths within - * optimizer (control path for linear constraints and one for - * nonlinear constraints). - * - * We test following kinds of preconditioners: - * * "none" - * * "exact low rank", restart frequency is 1 - * * "exact robust", restart frequency is 1 - * Inexact LBFGS-based preconditioner is not tested because its - * behavior greatly depends on order of equations. - */ - n = 15; - k = 5; - maxits = 1; - ae_vector_set_length(&x0, n, _state); - ae_matrix_set_length(&c, k, n+1, _state); - ae_vector_set_length(&ct, k, _state); - for(prectype=0; prectype<=2; prectype++) - { - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - for(i=0; i<=k-1; i++) - { - v = 0.0; - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - v = v+ae_sqr(c.ptr.pp_double[i][j], _state); - } - v = 1/ae_sqrt(v, _state); - ae_v_muld(&c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v); - v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - c.ptr.pp_double[i][n] = v; - ct.ptr.p_int[i] = 0; - } - minnlccreate(n, &x0, &state, _state); - minnlcsetcond(&state, 0.0, maxits, _state); - if( solvertype==0 ) - { - aulits = 1; - rho = 1.0E3; - minnlcsetalgoaul(&state, rho, aulits, _state); - if( prectype==0 ) - { - minnlcsetprecnone(&state, _state); - } - if( prectype==1 ) - { - minnlcsetprecexactlowrank(&state, 1, _state); - } - if( prectype==2 ) - { - minnlcsetprecexactrobust(&state, 1, _state); - } - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetlc(&state, &c, &ct, k, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_sqr(state.x.ptr.p_double[i], _state); - state.j.ptr.pp_double[0][i] = 2*state.x.ptr.p_double[i]; - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:2976"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:2977"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - aulits = 1; - rho = 1.0E3; - minnlcsetalgoaul(&state, rho, aulits, _state); - if( prectype==0 ) - { - minnlcsetprecnone(&state, _state); - } - if( prectype==1 ) - { - minnlcsetprecexactlowrank(&state, 1, _state); - } - if( prectype==2 ) - { - minnlcsetprecexactrobust(&state, 1, _state); - } - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetcond(&state, 0.0, maxits, _state); - minnlcsetnlc(&state, k, 0, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_sqr(state.x.ptr.p_double[i], _state); - state.j.ptr.pp_double[0][i] = 2*state.x.ptr.p_double[i]; - } - for(i=0; i<=k-1; i++) - { - v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state.fi.ptr.p_double[1+i] = v-c.ptr.pp_double[i][n]; - ae_v_move(&state.j.ptr.pp_double[1+i][0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x2, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x2, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:3022"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:3023"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-x2.ptr.p_double[i], _state),1.0E-3), __FILE__, __LINE__, "testminnlcunit.ap:3027"); - } - } - - /* - * Test integrity checks for NAN/INF: - * * algorithm solves optimization problem, which is normal for some time (quadratic) - * * after 5-th step we choose random component of gradient and consistently spoil - * it by NAN or INF. - * * we check that correct termination code is returned (-8) - */ - n = 100; - for(pass=1; pass<=10; pass++) - { - spoiliteration = 5; - stopiteration = 8; - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - - /* - * Gradient can be spoiled by +INF, -INF, NAN - */ - spoilvar = hqrnduniformi(&rs, n, _state); - i = hqrnduniformi(&rs, 3, _state); - spoilval = _state->v_nan; - if( i==0 ) - { - spoilval = _state->v_neginf; - } - if( i==1 ) - { - spoilval = _state->v_posinf; - } - } - else - { - - /* - * Function value can be spoiled only by NAN - * (+INF can be recognized as legitimate value during optimization) - */ - spoilvar = -1; - spoilval = _state->v_nan; - } - spdmatrixrndcond(n, 1.0E5, &fulla, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - aulits = 5; - rho = 1.0E3; - minnlcsetalgoaul(&state, rho, aulits, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetcond(&state, 0.0, stopiteration, _state); - minnlcsetxrep(&state, ae_true, _state); - k = -1; - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.j.ptr.pp_double[0][i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - if( k>=spoiliteration ) - { - if( spoilvar<0 ) - { - state.fi.ptr.p_double[0] = spoilval; - } - else - { - state.j.ptr.pp_double[0][spoilvar] = spoilval; - } - } - continue; - } - if( state.xupdated ) - { - inc(&k, _state); - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, rep.terminationtype!=-8, __FILE__, __LINE__, "testminnlcunit.ap:3121"); - } - - /* - * Test that optimizer respects box constraints in all - * intermediate points: - * * test that analytic Jacobian respects them - * * test that numerical Jacobian respects them - * - * NOTE: we skip SolverType=0 (AUL) because AUL optimizer - * does not provide such guarantee - */ - if( solvertype!=0 ) - { - n = 10; - spdmatrixrndcond(n, 1.0E3, &fulla, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - bndl.ptr.p_double[i] = (double)(0); - bndu.ptr.p_double[i] = _state->v_posinf; - } - else - { - bndl.ptr.p_double[i] = _state->v_neginf; - bndu.ptr.p_double[i] = (double)(0); - } - } - - /* - * Check analytic Jacobian - */ - minnlccreate(n, &x0, &state, _state); - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - minnlcsetbc(&state, &bndl, &bndu, _state); - minnlcsetcond(&state, 1.0E-8, 0, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(wereerrors, ae_fp_less(state.x.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminnlcunit.ap:3176"); - ae_set_error_flag(wereerrors, ae_fp_greater(state.x.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminnlcunit.ap:3177"); - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.j.ptr.pp_double[0][i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:3191"); - - /* - * Check numerical Jacobian - */ - minnlccreatef(n, &x0, 1.0E-4, &state, _state); - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - minnlcsetbc(&state, &bndl, &bndu, _state); - minnlcsetcond(&state, 1.0E-8, 0, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfi ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(wereerrors, ae_fp_less(state.x.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminnlcunit.ap:3212"); - ae_set_error_flag(wereerrors, ae_fp_greater(state.x.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminnlcunit.ap:3213"); - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:3223"); - } - - /* - * Test constraint violation reports for completely unconstrained - * problems and problems with all constraints being satisfied exactly - */ - tolx = 0.01; - for(pass=1; pass<=10; pass++) - { - n = 1+hqrnduniformi(&rs, 5, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, 1000.0, 10, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetcond(&state, 1.0E-7, 200, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_pow(state.x.ptr.p_double[i], (double)(4), _state); - state.j.ptr.pp_double[0][i] = 4*ae_pow(state.x.ptr.p_double[i], (double)(3), _state); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - - /* - * Check solution itself - */ - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:3266"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:3267"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[i], _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:3271"); - } - - /* - * Check constraint violation reports - */ - ae_set_error_flag(wereerrors, ae_fp_neq(rep.bcerr,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:3276"); - ae_set_error_flag(wereerrors, rep.bcidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:3277"); - ae_set_error_flag(wereerrors, ae_fp_neq(rep.lcerr,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:3278"); - ae_set_error_flag(wereerrors, rep.lcidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:3279"); - ae_set_error_flag(wereerrors, ae_fp_neq(rep.nlcerr,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:3280"); - ae_set_error_flag(wereerrors, rep.nlcidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:3281"); - } - for(pass=1; pass<=10; pass++) - { - n = 1+hqrnduniformi(&rs, 5, _state); - k = 1+hqrnduniformi(&rs, 5, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xu, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_matrix_set_length(&c, k, n+1, _state); - ae_vector_set_length(&ct, k, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - xu.ptr.p_double[i] = hqrndnormal(&rs, _state); - bndl.ptr.p_double[i] = (double)(-1000); - bndu.ptr.p_double[i] = (double)(1000); - } - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - c.ptr.pp_double[i][n] = (double)(1000); - ct.ptr.p_int[i] = -1; - } - else - { - c.ptr.pp_double[i][n] = (double)(-1000); - ct.ptr.p_int[i] = 1; - } - } - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, 1000.0, 20, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetbc(&state, &bndl, &bndu, _state); - minnlcsetlc(&state, &c, &ct, k, _state); - minnlcsetcond(&state, 1.0E-7, 0, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_pow(state.x.ptr.p_double[i]-xu.ptr.p_double[i], (double)(2), _state); - state.j.ptr.pp_double[0][i] = 2*(state.x.ptr.p_double[i]-xu.ptr.p_double[i]); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - - /* - * Check solution itself, calculate reference violation values - */ - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:3346"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:3347"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check constraint violation reports - */ - ae_set_error_flag(wereerrors, ae_fp_neq(rep.bcerr,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:3354"); - ae_set_error_flag(wereerrors, rep.bcidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:3355"); - ae_set_error_flag(wereerrors, ae_fp_neq(rep.lcerr,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:3356"); - ae_set_error_flag(wereerrors, rep.lcidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:3357"); - ae_set_error_flag(wereerrors, ae_fp_neq(rep.nlcerr,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:3358"); - ae_set_error_flag(wereerrors, rep.nlcidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:3359"); - } - - /* - * Test constraint violation reports for box/linearly constrained - * problems. We generate a problem which can not satisfy one (and - * just one) general linear constraint. - */ - tolx = 0.001; - for(pass=1; pass<=10; pass++) - { - - /* - * Formulate problem with inconsistent constraints - */ - n = 2+hqrnduniformi(&rs, 5, _state); - k = 1+hqrnduniformi(&rs, 5, _state); - ae_vector_set_length(&s, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xu, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_matrix_set_length(&c, k, n+1, _state); - ae_vector_set_length(&ct, k, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - xu.ptr.p_double[i] = hqrndnormal(&rs, _state); - bndl.ptr.p_double[i] = -0.5*hqrnduniformr(&rs, _state)-0.1; - bndu.ptr.p_double[i] = 0.5*hqrnduniformr(&rs, _state)+0.1; - } - for(i=0; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - c.ptr.pp_double[i][n] = (double)(1000); - ct.ptr.p_int[i] = -1; - } - else - { - c.ptr.pp_double[i][n] = (double)(-1000); - ct.ptr.p_int[i] = 1; - } - } - ae_assert(n>=2, "NLCTest: integrity check failed", _state); - badidx0 = hqrnduniformi(&rs, k, _state); - badidx1 = hqrnduniformi(&rs, n, _state); - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[badidx0][j] = (double)(0); - } - for(j=0; j<=k-1; j++) - { - c.ptr.pp_double[j][badidx1] = (double)(0); - } - c.ptr.pp_double[badidx0][badidx1] = (double)(1); - c.ptr.pp_double[badidx0][n] = (double)(10*(2*hqrnduniformi(&rs, 2, _state)-1)); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - ct.ptr.p_int[badidx0] = 0; - } - else - { - ct.ptr.p_int[badidx0] = ae_sign(c.ptr.pp_double[badidx0][n], _state); - } - - /* - * Create and try to solve - */ - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, 1000.0, 20, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetbc(&state, &bndl, &bndu, _state); - minnlcsetlc(&state, &c, &ct, k, _state); - minnlcsetscale(&state, &s, _state); - minnlcsetcond(&state, 1.0E-7, 0, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_pow(state.x.ptr.p_double[i]-xu.ptr.p_double[i], (double)(2), _state); - state.j.ptr.pp_double[0][i] = 2*(state.x.ptr.p_double[i]-xu.ptr.p_double[i]); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - - /* - * Check solution itself, calculate reference violation values - */ - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:3454"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:3455"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check constraint violation reports - */ - if( ae_fp_greater(rep.bcerr,(double)(0)) ) - { - v = ae_maxreal(bndl.ptr.p_double[badidx1]-x1.ptr.p_double[badidx1], x1.ptr.p_double[badidx1]-bndu.ptr.p_double[badidx1], _state); - v = v/s.ptr.p_double[badidx1]; - ae_set_error_flag(wereerrors, rep.bcidx!=badidx1, __FILE__, __LINE__, "testminnlcunit.ap:3466"); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(rep.bcerr-v, _state),1.0E3*ae_machineepsilon), __FILE__, __LINE__, "testminnlcunit.ap:3468"); - } - else - { - ae_set_error_flag(wereerrors, ae_fp_neq(rep.bcerr,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:3473"); - ae_set_error_flag(wereerrors, rep.bcidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:3474"); - ae_set_error_flag(wereerrors, ae_fp_less(x1.ptr.p_double[badidx1],bndl.ptr.p_double[badidx1])||ae_fp_greater(x1.ptr.p_double[badidx1],bndu.ptr.p_double[badidx1]), __FILE__, __LINE__, "testminnlcunit.ap:3475"); - } - ae_set_error_flag(wereerrors, rep.lcidx!=badidx0, __FILE__, __LINE__, "testminnlcunit.ap:3477"); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(rep.lcerr-ae_fabs(x1.ptr.p_double[badidx1]-c.ptr.pp_double[badidx0][n], _state)/s.ptr.p_double[badidx1], _state),1.0E3*ae_machineepsilon), __FILE__, __LINE__, "testminnlcunit.ap:3478"); - ae_set_error_flag(wereerrors, ae_fp_neq(rep.nlcerr,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:3479"); - ae_set_error_flag(wereerrors, rep.nlcidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:3480"); - } - - /* - * Test constraint violation reports for box/nonlinearly constrained - * problems. We generate a problem which can not satisfy one (and - * just one) general linear constraint. - * - * NOTE: it is important to have N>=NLEC+NLIC - */ - tolx = 0.001; - for(pass=1; pass<=10; pass++) - { - - /* - * Formulate problem with inconsistent constraints - */ - nlec = 1+hqrnduniformi(&rs, 5, _state); - nlic = 1+hqrnduniformi(&rs, 5, _state); - k = nlec+nlic; - n = k+hqrnduniformi(&rs, 5, _state); - ae_vector_set_length(&s, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xu, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_matrix_set_length(&c, k, n+1, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - xu.ptr.p_double[i] = hqrndnormal(&rs, _state); - bndl.ptr.p_double[i] = -0.5*hqrnduniformr(&rs, _state)-0.1; - bndu.ptr.p_double[i] = 0.5*hqrnduniformr(&rs, _state)+0.1; - } - for(i=0; i<=nlec-1; i++) - { - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = (double)(0); - } - c.ptr.pp_double[i][i] = (double)(1); - c.ptr.pp_double[i][n] = bndl.ptr.p_double[i]+hqrnduniformr(&rs, _state)*(bndu.ptr.p_double[i]-bndl.ptr.p_double[i]); - } - for(i=nlec; i<=k-1; i++) - { - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = (double)(0); - } - c.ptr.pp_double[i][i] = (double)(1); - c.ptr.pp_double[i][n] = (double)(1000); - } - badidx0 = hqrnduniformi(&rs, k, _state); - if( badidx0v_posinf; - x0.ptr.p_double[i] = hqrnduniformr(&rs, _state); - } - else - { - bndl.ptr.p_double[i] = (double)(0); - bndu.ptr.p_double[i] = (double)(0); - x0.ptr.p_double[i] = (double)(0); - } - } - for(i=0; i<=blocksize*blockcnt-1; i++) - { - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = 0.0; - } - } - for(k=0; k<=blockcnt-1; k++) - { - rmatrixrndcond(blocksize, condv, &a, _state); - for(i=0; i<=blocksize-1; i++) - { - for(j=0; j<=blocksize-1; j++) - { - c.ptr.pp_double[k*blocksize+i][k*blocksize+j] = a.ptr.pp_double[i][j]; - } - } - } - for(i=0; i<=blocksize*blockcnt-1; i++) - { - v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - v = 1/ae_sqrt(v, _state); - ae_v_muld(&c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v); - v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - c.ptr.pp_double[i][n] = v; - ct.ptr.p_int[i] = hqrnduniformi(&rs, 3, _state)-1; - } - - /* - * Test unpreconditioned iteration - */ - minnlccreate(n, &x0, &state, _state); - minnlcsetalgoaul(&state, rho, aulits, _state); - minnlcsetcond(&state, 1.0E-7, 0, _state); - if( ctype==0 ) - { - minnlcsetlc(&state, &c, &ct, blocksize*blockcnt, _state); - } - else - { - minnlcsetnlc(&state, blocksize*blockcnt, 0, _state); - } - minnlcsetprecnone(&state, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_sqr(state.x.ptr.p_double[i], _state); - state.j.ptr.pp_double[0][i] = 2*state.x.ptr.p_double[i]; - } - if( ctype==1 ) - { - for(i=0; i<=blocksize*blockcnt-1; i++) - { - v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state.fi.ptr.p_double[1+i] = v-c.ptr.pp_double[i][n]; - ae_v_move(&state.j.ptr.pp_double[1+i][0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:3795"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:3796"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - nnone = nnone+rep.iterationscount; - - /* - * Test LBFGS preconditioned iteration - */ - minnlccreate(n, &x0, &state, _state); - minnlcsetalgoaul(&state, rho, aulits, _state); - minnlcsetcond(&state, 1.0E-7, 0, _state); - if( ctype==0 ) - { - minnlcsetlc(&state, &c, &ct, blocksize*blockcnt, _state); - } - else - { - minnlcsetnlc(&state, blocksize*blockcnt, 0, _state); - } - minnlcsetprecinexact(&state, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_sqr(state.x.ptr.p_double[i], _state); - state.j.ptr.pp_double[0][i] = 2*state.x.ptr.p_double[i]; - } - if( ctype==1 ) - { - for(i=0; i<=blocksize*blockcnt-1; i++) - { - v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state.fi.ptr.p_double[1+i] = v-c.ptr.pp_double[i][n]; - ae_v_move(&state.j.ptr.pp_double[1+i][0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:3836"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:3837"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - nlbfgs = nlbfgs+rep.iterationscount; - - /* - * Test exact low rank preconditioner - */ - minnlccreate(n, &x0, &state, _state); - minnlcsetalgoaul(&state, rho, aulits, _state); - minnlcsetcond(&state, 1.0E-7, 0, _state); - if( ctype==0 ) - { - minnlcsetlc(&state, &c, &ct, blocksize*blockcnt, _state); - } - else - { - minnlcsetnlc(&state, blocksize*blockcnt, 0, _state); - } - minnlcsetprecexactlowrank(&state, 3, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_sqr(state.x.ptr.p_double[i], _state); - state.j.ptr.pp_double[0][i] = 2*state.x.ptr.p_double[i]; - } - if( ctype==1 ) - { - for(i=0; i<=blocksize*blockcnt-1; i++) - { - v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state.fi.ptr.p_double[1+i] = v-c.ptr.pp_double[i][n]; - ae_v_move(&state.j.ptr.pp_double[1+i][0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:3877"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:3878"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - nexactlowrank = nexactlowrank+rep.iterationscount; - - /* - * Test exact robust preconditioner - */ - minnlccreate(n, &x0, &state, _state); - minnlcsetalgoaul(&state, rho, aulits, _state); - minnlcsetcond(&state, 1.0E-7, 0, _state); - if( ctype==0 ) - { - minnlcsetlc(&state, &c, &ct, blocksize*blockcnt, _state); - } - else - { - minnlcsetnlc(&state, blocksize*blockcnt, 0, _state); - } - minnlcsetprecexactrobust(&state, 3, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_sqr(state.x.ptr.p_double[i], _state); - state.j.ptr.pp_double[0][i] = 2*state.x.ptr.p_double[i]; - } - if( ctype==1 ) - { - for(i=0; i<=blocksize*blockcnt-1; i++) - { - v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - state.fi.ptr.p_double[1+i] = v-c.ptr.pp_double[i][n]; - ae_v_move(&state.j.ptr.pp_double[1+i][0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:3918"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:3919"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - nexactrobust = nexactrobust+rep.iterationscount; - } - - /* - * Compare. - * - * Preconditioners must be significantly different, - * with exact being best one, inexact being second, - * "none" being worst option. - */ - ae_set_error_flag(wereerrors, !ae_fp_less((double)(nexactlowrank),0.9*nlbfgs), __FILE__, __LINE__, "testminnlcunit.ap:3932"); - ae_set_error_flag(wereerrors, !ae_fp_less((double)(nexactrobust),0.9*nlbfgs), __FILE__, __LINE__, "testminnlcunit.ap:3933"); - ae_set_error_flag(wereerrors, !ae_fp_less((double)(nlbfgs),0.9*nnone), __FILE__, __LINE__, "testminnlcunit.ap:3934"); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests OptGuard - -On failure sets error flag. -*************************************************************************/ -static void testminnlcunit_testoptguard(ae_bool* wereerrors, - ae_state *_state) -{ - ae_frame _frame_block; - hqrndstate rs; - double v; - minnlcstate state; - minnlcreport rep; - optguardreport ogrep; - optguardnonc1test0report ognonc1test0strrep; - optguardnonc1test0report ognonc1test0lngrep; - optguardnonc1test1report ognonc1test1strrep; - optguardnonc1test1report ognonc1test1lngrep; - ae_int_t i; - ae_int_t j; - ae_int_t n; - ae_matrix a; - ae_matrix a1; - ae_vector s; - ae_vector x0; - ae_vector x1; - ae_vector xlast; - ae_vector b; - ae_vector bndl; - ae_vector bndu; - ae_vector xu; - double diffstep; - ae_int_t pass; - ae_int_t solvertype; - double vbnd; - double fscale; - ae_int_t defecttype; - double vshift; - double vpower; - ae_int_t cntabove; - ae_int_t cntbelow; - ae_bool linesearchstarted; - ae_bool wasgoodlinesearch0; - ae_bool wasgoodlinesearch1; - ae_int_t shortsessions; - ae_int_t maxshortsessions; - double stplen; - double shortstplen; - ae_bool failed; - ae_int_t passcount; - ae_int_t maxfails; - ae_int_t failurecounter; - ae_int_t maxc1test0fails; - ae_int_t maxc1test1fails; - ae_int_t c1test0fails; - ae_int_t c1test1fails; - ae_int_t goodidx; - double avgstr0len; - double avglng0len; - double avgstr1len; - double avglng1len; - ae_int_t funcidx; - ae_int_t varidx; - ae_int_t skind; - ae_matrix jactrue; - ae_matrix jacdefect; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&ogrep, 0, sizeof(ogrep)); - memset(&ognonc1test0strrep, 0, sizeof(ognonc1test0strrep)); - memset(&ognonc1test0lngrep, 0, sizeof(ognonc1test0lngrep)); - memset(&ognonc1test1strrep, 0, sizeof(ognonc1test1strrep)); - memset(&ognonc1test1lngrep, 0, sizeof(ognonc1test1lngrep)); - memset(&a, 0, sizeof(a)); - memset(&a1, 0, sizeof(a1)); - memset(&s, 0, sizeof(s)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&xlast, 0, sizeof(xlast)); - memset(&b, 0, sizeof(b)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&xu, 0, sizeof(xu)); - memset(&jactrue, 0, sizeof(jactrue)); - memset(&jacdefect, 0, sizeof(jacdefect)); - _hqrndstate_init(&rs, _state, ae_true); - _minnlcstate_init(&state, _state, ae_true); - _minnlcreport_init(&rep, _state, ae_true); - _optguardreport_init(&ogrep, _state, ae_true); - _optguardnonc1test0report_init(&ognonc1test0strrep, _state, ae_true); - _optguardnonc1test0report_init(&ognonc1test0lngrep, _state, ae_true); - _optguardnonc1test1report_init(&ognonc1test1strrep, _state, ae_true); - _optguardnonc1test1report_init(&ognonc1test1lngrep, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xlast, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xu, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&jactrue, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&jacdefect, 0, 0, DT_REAL, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Test functionality which should work in all NLC solvers - */ - for(solvertype=0; solvertype<=testminnlcunit_maxsolvertype; solvertype++) - { - - /* - * Check that gradient verification is disabled by default: - * gradient checking for bad problem must return nothing - */ - n = 10; - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 1.0+0.1*i; - } - spdmatrixrndcond(n, 1.0E3, &a, _state); - spdmatrixrndcond(n, 1.0E3, &a1, _state); - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, 1000.0, 5, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetcond(&state, 1.0E-7, 10, _state); - minnlcsetnlc(&state, 0, 1, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*v; - } - state.fi.ptr.p_double[1] = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]*a1.ptr.pp_double[i][j]; - } - state.fi.ptr.p_double[1] = state.fi.ptr.p_double[1]+0.5*state.x.ptr.p_double[i]*v; - } - for(i=0; i<=n-1; i++) - { - state.j.ptr.pp_double[0][i] = (double)(0); - state.j.ptr.pp_double[1][i] = (double)(0); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - minnlcoptguardresults(&state, &ogrep, _state); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:4046"); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4047"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(wereerrors, ogrep.badgradxbase.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:4050"); - ae_set_error_flag(wereerrors, ogrep.badgraduser.rows!=0, __FILE__, __LINE__, "testminnlcunit.ap:4051"); - ae_set_error_flag(wereerrors, ogrep.badgraduser.cols!=0, __FILE__, __LINE__, "testminnlcunit.ap:4052"); - ae_set_error_flag(wereerrors, ogrep.badgradnum.rows!=0, __FILE__, __LINE__, "testminnlcunit.ap:4053"); - ae_set_error_flag(wereerrors, ogrep.badgradnum.cols!=0, __FILE__, __LINE__, "testminnlcunit.ap:4054"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(wereerrors, ogrep.badgradsuspected, __FILE__, __LINE__, "testminnlcunit.ap:4057"); - ae_set_error_flag(wereerrors, ogrep.badgradfidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:4058"); - ae_set_error_flag(wereerrors, ogrep.badgradvidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:4059"); - - /* - * Test that C0/C1 continuity monitoring is disabled by default; - * we solve nonsmooth problem and test that nothing is returned - * by OptGuard. - */ - n = 10; - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, 1000.0, 1, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetcond(&state, 1.0E-9, 50, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.j.ptr.pp_double[0][i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_fabs(v, _state); - v = (double)(ae_sign(v, _state)); - for(j=0; j<=n-1; j++) - { - state.j.ptr.pp_double[0][j] = state.j.ptr.pp_double[0][j]+v*a.ptr.pp_double[i][j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - minnlcoptguardresults(&state, &ogrep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4107"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:4108"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminnlcunit.ap:4111"); - ae_set_error_flag(wereerrors, ogrep.nonc1suspected, __FILE__, __LINE__, "testminnlcunit.ap:4112"); - ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:4113"); - ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminnlcunit.ap:4114"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx>=0, __FILE__, __LINE__, "testminnlcunit.ap:4115"); - ae_set_error_flag(wereerrors, ogrep.nonc1test0positive, __FILE__, __LINE__, "testminnlcunit.ap:4116"); - ae_set_error_flag(wereerrors, ogrep.nonc1test1positive, __FILE__, __LINE__, "testminnlcunit.ap:4117"); - - /* - * Test gradient checking functionality, try various - * defect types: - * * accidental zeroing of some gradient component - * * accidental addition of 1.0 to some component - * * accidental multiplication by 2.0 - * Try distorting both target and constraints. - */ - diffstep = 0.001; - n = 10; - for(skind=0; skind<=1; skind++) - { - for(funcidx=0; funcidx<=1; funcidx++) - { - for(defecttype=-1; defecttype<=2; defecttype++) - { - varidx = hqrnduniformi(&rs, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&s, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = ae_pow((double)(10), skind*(30*hqrnduniformr(&rs, _state)-15), _state); - x0.ptr.p_double[i] = (1.0+0.1*i)*s.ptr.p_double[i]; - j = hqrnduniformi(&rs, 3, _state); - bndl.ptr.p_double[i] = -100*s.ptr.p_double[i]; - bndu.ptr.p_double[i] = 100*s.ptr.p_double[i]; - if( j==1 ) - { - bndl.ptr.p_double[i] = x0.ptr.p_double[i]; - } - if( j==2 ) - { - bndu.ptr.p_double[i] = x0.ptr.p_double[i]; - } - } - spdmatrixrndcond(n, 1.0E3, &a, _state); - spdmatrixrndcond(n, 1.0E3, &a1, _state); - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, 1000.0, 5, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcoptguardgradient(&state, diffstep, _state); - minnlcsetcond(&state, 1.0E-7, 10, _state); - minnlcsetscale(&state, &s, _state); - minnlcsetbc(&state, &bndl, &bndu, _state); - minnlcsetnlc(&state, 0, 1, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - if( solvertype!=0 ) - { - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(wereerrors, ae_fp_less(state.x.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminnlcunit.ap:4177"); - ae_set_error_flag(wereerrors, ae_fp_greater(state.x.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminnlcunit.ap:4178"); - } - } - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*(state.x.ptr.p_double[i]/s.ptr.p_double[i])*v; - state.j.ptr.pp_double[0][i] = v; - } - state.fi.ptr.p_double[1] = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]/s.ptr.p_double[j]*a1.ptr.pp_double[i][j]; - } - state.fi.ptr.p_double[1] = state.fi.ptr.p_double[1]+0.5*(state.x.ptr.p_double[i]/s.ptr.p_double[i])*v; - state.j.ptr.pp_double[1][i] = v; - } - if( defecttype==0 ) - { - state.j.ptr.pp_double[funcidx][varidx] = (double)(0); - } - if( defecttype==1 ) - { - state.j.ptr.pp_double[funcidx][varidx] = state.j.ptr.pp_double[funcidx][varidx]+1; - } - if( defecttype==2 ) - { - state.j.ptr.pp_double[funcidx][varidx] = state.j.ptr.pp_double[funcidx][varidx]*2; - } - for(i=0; i<=n-1; i++) - { - state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]/s.ptr.p_double[i]; - state.j.ptr.pp_double[1][i] = state.j.ptr.pp_double[1][i]/s.ptr.p_double[i]; - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - minnlcoptguardresults(&state, &ogrep, _state); - - /* - * Check that something is returned - */ - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:4228"); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4229"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Compute reference values for true and spoiled Jacobian at X0 - */ - ae_set_error_flag(wereerrors, !isfinitevector(&ogrep.badgradxbase, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4236"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&jactrue, 2, n, _state); - ae_matrix_set_length(&jacdefect, 2, n, _state); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+ogrep.badgradxbase.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - jactrue.ptr.pp_double[0][i] = v; - jacdefect.ptr.pp_double[0][i] = v; - } - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+ogrep.badgradxbase.ptr.p_double[j]/s.ptr.p_double[j]*a1.ptr.pp_double[i][j]; - } - jactrue.ptr.pp_double[1][i] = v; - jacdefect.ptr.pp_double[1][i] = v; - } - if( defecttype==0 ) - { - jacdefect.ptr.pp_double[funcidx][varidx] = (double)(0); - } - if( defecttype==1 ) - { - jacdefect.ptr.pp_double[funcidx][varidx] = jacdefect.ptr.pp_double[funcidx][varidx]+1; - } - if( defecttype==2 ) - { - jacdefect.ptr.pp_double[funcidx][varidx] = jacdefect.ptr.pp_double[funcidx][varidx]*2; - } - for(i=0; i<=n-1; i++) - { - jactrue.ptr.pp_double[0][i] = jactrue.ptr.pp_double[0][i]/s.ptr.p_double[i]; - jactrue.ptr.pp_double[1][i] = jactrue.ptr.pp_double[1][i]/s.ptr.p_double[i]; - jacdefect.ptr.pp_double[0][i] = jacdefect.ptr.pp_double[0][i]/s.ptr.p_double[i]; - jacdefect.ptr.pp_double[1][i] = jacdefect.ptr.pp_double[1][i]/s.ptr.p_double[i]; - } - - /* - * Check OptGuard report - */ - ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgraduser, 2, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4274"); - ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgradnum, 2, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4275"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - if( defecttype>=0 ) - { - ae_set_error_flag(wereerrors, !ogrep.badgradsuspected, __FILE__, __LINE__, "testminnlcunit.ap:4280"); - ae_set_error_flag(wereerrors, ogrep.badgradfidx!=funcidx, __FILE__, __LINE__, "testminnlcunit.ap:4281"); - ae_set_error_flag(wereerrors, ogrep.badgradvidx!=varidx, __FILE__, __LINE__, "testminnlcunit.ap:4282"); - } - else - { - ae_set_error_flag(wereerrors, ogrep.badgradsuspected, __FILE__, __LINE__, "testminnlcunit.ap:4286"); - ae_set_error_flag(wereerrors, ogrep.badgradfidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:4287"); - ae_set_error_flag(wereerrors, ogrep.badgradvidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:4288"); - } - for(i=0; i<=1; i++) - { - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jactrue.ptr.pp_double[i][j]-ogrep.badgradnum.ptr.pp_double[i][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testminnlcunit.ap:4293"); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jacdefect.ptr.pp_double[i][j]-ogrep.badgraduser.ptr.pp_double[i][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testminnlcunit.ap:4294"); - } - } - } - } - } - - /* - * Make sure than no false positives are reported for larger - * problems where numerical noise can be an issue: - * * N=100 dimensions - * * nonnegativity constraints - * * positive-definite quadratic programming problem - * * upper limit on iterations count, MaxIts=25 - * We simply test that OptGuard does not return error code. - */ - n = 100; - spdmatrixrndcond(n, 1.0E2, &a, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - bndl.ptr.p_double[i] = (double)(0); - bndu.ptr.p_double[i] = _state->v_posinf; - x0.ptr.p_double[i] = ae_pow(2.0, hqrndnormal(&rs, _state), _state); - } - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, 1000.0, 3, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel, _state), _state); - minnlcsetbc(&state, &bndl, &bndu, _state); - minnlcsetcond(&state, 1.0E-7, 25, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.j.ptr.pp_double[0][i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*a.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+a.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4352"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:4353"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - minnlcoptguardresults(&state, &ogrep, _state); - ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:4357"); - } - - /* - * Test functionality which works only in some NLC solvers - */ - for(solvertype=0; solvertype<=testminnlcunit_maxsolvertype; solvertype++) - { - - /* - * Skip - */ - if( solvertype==2 ) - { - continue; - } - - /* - * Test detection of discontinuities in the target function - * and its gradient (analytic gradient is used). - * - * Target function is convex quadratic modified by addition of - * nonsmooth/discontinuous (depending on DefectType) perturbation. - * - * This test is complicated because OptGuard does NOT guarantee - * that C0/C1 violations are ALWAYS caught. OptGuard needs line - * search to perform - * * at least 4 function evaluations, with discontinuity in the - * middle of them (at least two function values from the left, - * at least two from the right) - * * at least 7 function evaluations to catch C1 violation - * - * Furthermore, it is possible that optimizer will perform a few - * function evaluations BEFORE and AFTER line search starts, - * which complicates everything. - * - * N, VPower and VBnd are selected randomly at the start of the test. - */ - for(defecttype=0; defecttype<=1; defecttype++) - { - n = 1+hqrnduniformi(&rs, 10, _state); - vpower = 10*ae_pow((double)(10), -0.2*hqrnduniformr(&rs, _state), _state); - vbnd = 1*ae_pow((double)(10), -0.2*hqrnduniformr(&rs, _state), _state); - fscale = 0.1; - maxshortsessions = 4; - shortstplen = 1.0E-6; - shortsessions = 0; - for(pass=1; pass<=100; pass++) - { - - /* - * Formulate problem - */ - ae_vector_set_length(&s, n, _state); - ae_vector_set_length(&xlast, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xu, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - do - { - v = (double)(0); - for(i=0; i<=n-1; i++) - { - xu.ptr.p_double[i] = 0.1+hqrnduniformr(&rs, _state); - v = v+ae_sqr(xu.ptr.p_double[i], _state); - } - v = ae_sqrt(v, _state); - } - while(ae_fp_less_eq(v,(double)(0))); - for(i=0; i<=n-1; i++) - { - xu.ptr.p_double[i] = xu.ptr.p_double[i]/v; - } - for(i=0; i<=n-1; i++) - { - xlast.ptr.p_double[i] = (double)(0); - x0.ptr.p_double[i] = 2*xu.ptr.p_double[i]+0.1*hqrnduniformr(&rs, _state); - bndl.ptr.p_double[i] = 0.0; - bndu.ptr.p_double[i] = _state->v_posinf; - s.ptr.p_double[i] = ae_pow((double)(2), 0.1*hqrndnormal(&rs, _state), _state); - } - if( defecttype==0 ) - { - vshift = (double)(1); - } - else - { - vshift = (double)(0); - } - - /* - * Prepare code which detects "good" (long enough) line searches - */ - cntbelow = 0; - cntabove = 0; - wasgoodlinesearch0 = ae_false; - wasgoodlinesearch1 = ae_false; - linesearchstarted = ae_false; - - /* - * Create and try to solve - */ - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, 1000.0, 5, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetbc(&state, &bndl, &bndu, _state); - minnlcsetscale(&state, &s, _state); - minnlcsetcond(&state, 1.0E-7, 1000, _state); - minnlcoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel, _state), _state); - minnlcsetxrep(&state, ae_true, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+fscale*ae_pow(state.x.ptr.p_double[i], (double)(2), _state); - state.j.ptr.pp_double[0][i] = 2*fscale*state.x.ptr.p_double[i]; - } - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+state.x.ptr.p_double[i]*xu.ptr.p_double[i]; - } - if( ae_fp_less(v,vbnd) ) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+(vshift+vpower*(vbnd-v)); - for(i=0; i<=n-1; i++) - { - state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]-vpower*xu.ptr.p_double[i]; - } - if( linesearchstarted ) - { - inc(&cntbelow, _state); - } - } - else - { - if( linesearchstarted ) - { - inc(&cntabove, _state); - } - } - continue; - } - if( state.xupdated ) - { - - /* - * Finalize previous line search - */ - if( linesearchstarted ) - { - stplen = (double)(0); - for(i=0; i<=n-1; i++) - { - stplen = stplen+ae_sqr(state.x.ptr.p_double[i]-xlast.ptr.p_double[i], _state); - } - stplen = ae_sqrt(stplen, _state); - wasgoodlinesearch0 = wasgoodlinesearch0||((cntbelow>=2&&cntabove>=2)&&ae_fp_greater_eq(stplen,shortstplen)); - wasgoodlinesearch1 = wasgoodlinesearch1||((cntbelow>=2&&cntabove>=2)&&ae_fp_greater_eq(stplen,shortstplen)); - } - - /* - * Start new line search - */ - linesearchstarted = ae_true; - cntbelow = 0; - cntabove = 0; - for(i=0; i<=n-1; i++) - { - xlast.ptr.p_double[i] = state.x.ptr.p_double[i]; - } - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+state.x.ptr.p_double[i]*xu.ptr.p_double[i]; - } - if( ae_fp_less(v,vbnd) ) - { - inc(&cntbelow, _state); - } - else - { - inc(&cntabove, _state); - } - - /* - * Done - */ - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - minnlcoptguardresults(&state, &ogrep, _state); - - /* - * Check basic properties of the solution - */ - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4534"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:4535"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check OptGuard report, increase - */ - if( defecttype==0 ) - { - if( wasgoodlinesearch0 ) - { - ae_set_error_flag(wereerrors, optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:4546"); - ae_set_error_flag(wereerrors, !ogrep.nonc0suspected, __FILE__, __LINE__, "testminnlcunit.ap:4547"); - ae_set_error_flag(wereerrors, ogrep.nonc0fidx!=0, __FILE__, __LINE__, "testminnlcunit.ap:4548"); - } - else - { - inc(&shortsessions, _state); - } - } - if( defecttype==1 ) - { - if( wasgoodlinesearch1 ) - { - ae_set_error_flag(wereerrors, optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:4557"); - ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminnlcunit.ap:4558"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testminnlcunit.ap:4559"); - } - else - { - inc(&shortsessions, _state); - } - } - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - } - - /* - * Check that short optimization sessions are rare. - */ - ae_set_error_flag(wereerrors, shortsessions>maxshortsessions, __FILE__, __LINE__, "testminnlcunit.ap:4571"); - } - - /* - * One more test for detection of C1 continuity violations in the target. - * - * Target function is a sum of |(x,c_i)| for i=1..N. - * No constraints is present. - * Analytic gradient is provided. - * - * OptGuard should be able to detect violations in more than - * 99.9% of runs; it means that 100 runs should have no more than 4 - * failures in all cases (even after multiple repeated tests; according - * to the binomial distribution quantiles). - * - * We select some N and perform exhaustive search for this N. - * - * NOTE: we skip SQP for this test - */ - passcount = 100; - maxfails = 4; - maxc1test0fails = 10; - maxc1test1fails = 10; - n = 1+hqrnduniformi(&rs, 10, _state); - failurecounter = 0; - c1test0fails = 0; - c1test1fails = 0; - avgstr0len = (double)(0); - avglng0len = (double)(0); - avgstr1len = (double)(0); - avglng1len = (double)(0); - for(pass=1; pass<=passcount; pass++) - { - - /* - * Formulate problem - */ - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - - /* - * Create and try to solve - */ - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, 1000.0, 1, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetcond(&state, 1.0E-7, 50, _state); - minnlcsetscale(&state, &s, _state); - minnlcoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel, _state), _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.j.ptr.pp_double[0][i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_fabs(v, _state); - v = (double)(ae_sign(v, _state)); - for(j=0; j<=n-1; j++) - { - state.j.ptr.pp_double[0][j] = state.j.ptr.pp_double[0][j]+v*a.ptr.pp_double[i][j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - minnlcoptguardresults(&state, &ogrep, _state); - - /* - * Check basic properties of the solution - */ - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4661"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:4662"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check generic OptGuard report: distinguish between "hard" - * failures which result in immediate termination - * (C0 violation being reported) and "soft" ones - * (C1 violation is NOT reported) which accumulate - * until we exhaust limit. - */ - ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminnlcunit.ap:4673"); - ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminnlcunit.ap:4674"); - failed = ae_false; - failed = failed||optguardallclear(&ogrep, _state); - failed = failed||!ogrep.nonc1suspected; - failed = failed||ogrep.nonc1fidx!=0; - if( failed ) - { - inc(&failurecounter, _state); - } - - /* - * Check C1 continuity test #0 - */ - minnlcoptguardnonc1test0results(&state, &ognonc1test0strrep, &ognonc1test0lngrep, _state); - minnlcoptguardnonc1test1results(&state, &ognonc1test1strrep, &ognonc1test1lngrep, _state); - if( ogrep.nonc1test0positive ) - { - ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminnlcunit.ap:4689"); - ae_set_error_flag(wereerrors, !ognonc1test0strrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4690"); - ae_set_error_flag(wereerrors, !ognonc1test0lngrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4691"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testminnlcunit.ap:4692"); - testminnlcunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0strrep, &a, n, _state); - testminnlcunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0lngrep, &a, n, _state); - avgstr0len = avgstr0len+(double)ognonc1test0strrep.cnt/(double)passcount; - avglng0len = avglng0len+(double)ognonc1test0lngrep.cnt/(double)passcount; - } - else - { - ae_set_error_flag(wereerrors, ognonc1test0strrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4700"); - ae_set_error_flag(wereerrors, ognonc1test0lngrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4701"); - testminnlcunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0strrep, &a, n, _state); - testminnlcunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0lngrep, &a, n, _state); - inc(&c1test0fails, _state); - } - if( ogrep.nonc1test1positive ) - { - ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminnlcunit.ap:4708"); - ae_set_error_flag(wereerrors, !ognonc1test1strrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4709"); - ae_set_error_flag(wereerrors, !ognonc1test1lngrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4710"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testminnlcunit.ap:4711"); - testminnlcunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1strrep, &a, n, _state); - testminnlcunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1lngrep, &a, n, _state); - avgstr1len = avgstr1len+(double)ognonc1test1strrep.cnt/(double)passcount; - avglng1len = avglng1len+(double)ognonc1test1lngrep.cnt/(double)passcount; - } - else - { - ae_set_error_flag(wereerrors, ognonc1test1strrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4719"); - ae_set_error_flag(wereerrors, ognonc1test1lngrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4720"); - testminnlcunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1strrep, &a, n, _state); - testminnlcunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1lngrep, &a, n, _state); - inc(&c1test1fails, _state); - } - } - ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testminnlcunit.ap:4727"); - ae_set_error_flag(wereerrors, c1test0fails>maxc1test0fails, __FILE__, __LINE__, "testminnlcunit.ap:4728"); - ae_set_error_flag(wereerrors, c1test1fails>maxc1test1fails, __FILE__, __LINE__, "testminnlcunit.ap:4729"); - ae_set_error_flag(wereerrors, ae_fp_less_eq(avglng0len,avgstr0len), __FILE__, __LINE__, "testminnlcunit.ap:4730"); - ae_set_error_flag(wereerrors, ae_fp_less_eq(avglng1len,avgstr1len), __FILE__, __LINE__, "testminnlcunit.ap:4731"); - - /* - * Detection of C1 continuity violations in the target under numerical differentiation: - * * target function is a sum of |(x,c_i)| for i=1..N. - * * no constraints is present. - * * analytic gradient is provided. - * - * OptGuard should always be able to detect violations in more than - * 99% of runs (note: reduced strength when compared with analytic gradient); - * it means that 100 runs should have no more than 10 failures in all cases - * (even after multiple repeated tests; according to the binomial distribution - * quantiles). - * - * We select some N and perform exhaustive search for this N. - * - * NOTE: we skip SQP solver for this test - */ - diffstep = 0.0001; - passcount = 100; - maxfails = 10; - n = 1+hqrnduniformi(&rs, 10, _state); - failurecounter = 0; - for(pass=1; pass<=passcount; pass++) - { - - /* - * Formulate problem - */ - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = 0.01*ae_pow((double)(2), 0.33*hqrndnormal(&rs, _state), _state); - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - - /* - * Create and try to solve - */ - minnlccreatef(n, &x0, diffstep, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, 1000.0, 1, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetcond(&state, 1.0E-7, 50, _state); - minnlcoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel, _state), _state); - while(minnlciteration(&state, _state)) - { - if( state.needfi ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_fabs(v, _state); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - minnlcoptguardresults(&state, &ogrep, _state); - - /* - * Check basic properties of the solution - */ - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4806"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:4807"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check OptGuard report: distinguish between "hard" - * failures which result in immediate termination - * (C0 violation being reported) and "soft" ones - * (C1 violation is NOT reported) which accumulate - * until we exhaust limit. - */ - ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminnlcunit.ap:4818"); - ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminnlcunit.ap:4819"); - failed = ae_false; - failed = failed||optguardallclear(&ogrep, _state); - failed = failed||!ogrep.nonc1suspected; - failed = failed||ogrep.nonc1fidx!=0; - if( failed ) - { - inc(&failurecounter, _state); - } - } - ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testminnlcunit.ap:4827"); - - /* - * Detection of C1 continuity violations in the nonlinear constraints. - * - * This test is a bit tricky because optimizers are less sensitive to - * continuity violations in constraints, so we may have hard time collecting - * enough statistics. In order to do so we solve carefully designed hard - * problem with MULTIPLE bad constraints and only one good constraint. - * - * Optimizer may report any of bad constraints, but not good one. - * - * We select some N and perform exhaustive search for this N. - */ - passcount = 100; - maxfails = 20; - n = 5; - failurecounter = 0; - c1test0fails = 0; - c1test1fails = 0; - for(pass=1; pass<=passcount; pass++) - { - - /* - * Formulate problem, select constraint index to perturb with - * nonsmoothness; make sure that this constraint is active at - * the solution - */ - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&s, n, _state); - ae_vector_set_length(&b, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrnduniformr(&rs, _state)-0.5; - s.ptr.p_double[i] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = ae_pow((double)(2), 0.01*hqrndnormal(&rs, _state), _state); - } - } - goodidx = hqrnduniformi(&rs, n, _state); - - /* - * Create and try to solve - */ - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, 1000.0, 3, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetcond(&state, 1.0E-7, 50, _state); - minnlcsetnlc(&state, 0, n, _state); - minnlcsetscale(&state, &s, _state); - minnlcoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel, _state), _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.j.ptr.pp_double[0][i] = b.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[1+i] = (double)(-1); - for(j=0; j<=n-1; j++) - { - state.fi.ptr.p_double[1+i] = state.fi.ptr.p_double[1+i]+a.ptr.pp_double[i][j]*ae_sqr(state.x.ptr.p_double[j], _state); - state.j.ptr.pp_double[1+i][j] = 2*a.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - if( i!=goodidx ) - { - state.fi.ptr.p_double[1+i] = ae_maxreal(state.fi.ptr.p_double[1+i], 0.0, _state); - for(j=0; j<=n-1; j++) - { - state.j.ptr.pp_double[1+i][j] = ae_sign(state.fi.ptr.p_double[1+i], _state)*state.j.ptr.pp_double[1+i][j]; - } - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - minnlcoptguardresults(&state, &ogrep, _state); - - /* - * Check basic properties of the solution - */ - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4923"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:4924"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check generic OptGuard report: distinguish between "hard" - * failures which result in immediate termination - * (C0 violation being reported) and "soft" ones - * (C1 violation is NOT reported) which accumulate - * until we exhaust limit. - */ - ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminnlcunit.ap:4935"); - ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminnlcunit.ap:4936"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx==goodidx+1, __FILE__, __LINE__, "testminnlcunit.ap:4937"); - failed = ae_false; - failed = failed||optguardallclear(&ogrep, _state); - failed = failed||!ogrep.nonc1suspected; - if( failed ) - { - inc(&failurecounter, _state); - } - - /* - * Check C1 continuity tests #0 and #1 - */ - minnlcoptguardnonc1test0results(&state, &ognonc1test0strrep, &ognonc1test0lngrep, _state); - minnlcoptguardnonc1test1results(&state, &ognonc1test1strrep, &ognonc1test1lngrep, _state); - if( ogrep.nonc1test0positive ) - { - ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminnlcunit.ap:4951"); - ae_set_error_flag(wereerrors, !ognonc1test0strrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4952"); - ae_set_error_flag(wereerrors, !ognonc1test0lngrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4953"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx<1, __FILE__, __LINE__, "testminnlcunit.ap:4954"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx>n, __FILE__, __LINE__, "testminnlcunit.ap:4955"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx==goodidx+1, __FILE__, __LINE__, "testminnlcunit.ap:4956"); - testminnlcunit_testoptguardc1test0reportfortask1(wereerrors, &ognonc1test0strrep, &a, n, goodidx, _state); - testminnlcunit_testoptguardc1test0reportfortask1(wereerrors, &ognonc1test0lngrep, &a, n, goodidx, _state); - } - else - { - ae_set_error_flag(wereerrors, ognonc1test0strrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4962"); - ae_set_error_flag(wereerrors, ognonc1test0lngrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4963"); - testminnlcunit_testoptguardc1test0reportfortask1(wereerrors, &ognonc1test0strrep, &a, n, goodidx, _state); - testminnlcunit_testoptguardc1test0reportfortask1(wereerrors, &ognonc1test0lngrep, &a, n, goodidx, _state); - inc(&c1test0fails, _state); - } - if( ogrep.nonc1test1positive ) - { - ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminnlcunit.ap:4970"); - ae_set_error_flag(wereerrors, !ognonc1test1strrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4971"); - ae_set_error_flag(wereerrors, !ognonc1test1lngrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4972"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx<1, __FILE__, __LINE__, "testminnlcunit.ap:4973"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx>n, __FILE__, __LINE__, "testminnlcunit.ap:4974"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx==goodidx+1, __FILE__, __LINE__, "testminnlcunit.ap:4975"); - testminnlcunit_testoptguardc1test1reportfortask1(wereerrors, &ognonc1test1strrep, &a, n, goodidx, _state); - testminnlcunit_testoptguardc1test1reportfortask1(wereerrors, &ognonc1test1lngrep, &a, n, goodidx, _state); - } - else - { - ae_set_error_flag(wereerrors, ognonc1test1strrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4981"); - ae_set_error_flag(wereerrors, ognonc1test1lngrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4982"); - testminnlcunit_testoptguardc1test1reportfortask1(wereerrors, &ognonc1test1strrep, &a, n, goodidx, _state); - testminnlcunit_testoptguardc1test1reportfortask1(wereerrors, &ognonc1test1lngrep, &a, n, goodidx, _state); - inc(&c1test1fails, _state); - } - } - ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testminnlcunit.ap:4988"); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function performs tests for fixed bugs - -On failure sets error flag. -*************************************************************************/ -static void testminnlcunit_testbugs(ae_bool* wereerrors, ae_state *_state) -{ - ae_frame _frame_block; - hqrndstate rs; - ae_int_t n; - ae_int_t aulits; - ae_int_t maxits; - double rho; - ae_int_t ckind; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t solvertype; - minnlcstate state; - minnlcreport rep; - ae_vector x0; - ae_vector x1; - ae_vector x2; - ae_vector bndl; - ae_vector bndu; - ae_vector d; - ae_vector b; - ae_vector ct; - ae_matrix c; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&x2, 0, sizeof(x2)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&d, 0, sizeof(d)); - memset(&b, 0, sizeof(b)); - memset(&ct, 0, sizeof(ct)); - memset(&c, 0, sizeof(c)); - _hqrndstate_init(&rs, _state, ae_true); - _minnlcstate_init(&state, _state, ae_true); - _minnlcreport_init(&rep, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Bug description (fixed): sometimes on non-convex problems, when - * Lagrange coefficient for inequality constraint becomes small, - * algorithm performs VERY deep step into infeasible area (step is 1E50), - * which de-stabilizes it and prevents from converging back to feasible area. - * - * Very rare situation, but must be fixed with additional "convexifying" term. - * This test reproduces situation with convexified term turned off, then - * checks that introduction of term solves issue. - * - * We perform three kinds of tests: - * * with box inequality constraint - * * with linear inequality constraint - * * with nonlinear inequality constraint - * - * In all three cases we: - * * first time solve non-convex problem with artificially moved stabilizing - * point and decreased initial value of Lagrange multiplier. - * * second time we solve problem with good stabilizing point, but zero Lagrange multiplier - * * last time solve same problem, but with default settings - */ - aulits = 1; - maxits = 1; - rho = 100.0; - n = 1; - ae_vector_set_length(&x0, n, _state); - x0.ptr.p_double[0] = 0.0; - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - bndl.ptr.p_double[0] = 0.0; - bndu.ptr.p_double[0] = _state->v_posinf; - ae_matrix_set_length(&c, 1, 2, _state); - ae_vector_set_length(&ct, 1, _state); - c.ptr.pp_double[0][0] = 1.0; - c.ptr.pp_double[0][1] = 0.0; - ct.ptr.p_int[0] = 1; - for(ckind=0; ckind<=2; ckind++) - { - minnlccreate(n, &x0, &state, _state); - state.stabilizingpoint = -1.0E300; - state.initialinequalitymultiplier = 1.0E-12; - minnlcsetalgoaul(&state, rho, aulits, _state); - minnlcsetcond(&state, 0.0, maxits, _state); - if( ckind==0 ) - { - minnlcsetbc(&state, &bndl, &bndu, _state); - } - if( ckind==1 ) - { - minnlcsetlc(&state, &c, &ct, 1, _state); - } - if( ckind==2 ) - { - minnlcsetnlc(&state, 0, 1, _state); - } - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = state.x.ptr.p_double[0]-ae_sqr(state.x.ptr.p_double[0], _state); - state.j.ptr.pp_double[0][0] = 1-2*state.x.ptr.p_double[0]; - if( ckind==2 ) - { - state.fi.ptr.p_double[1] = -state.x.ptr.p_double[0]; - state.j.ptr.pp_double[1][0] = (double)(-1); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:5086"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(wereerrors, ae_fp_greater(x1.ptr.p_double[0],-1.0E6), __FILE__, __LINE__, "testminnlcunit.ap:5089"); - minnlccreate(n, &x0, &state, _state); - state.stabilizingpoint = -1.0E2; - state.initialinequalitymultiplier = 1.0E-12; - minnlcsetalgoaul(&state, rho, aulits, _state); - minnlcsetcond(&state, 0.0, maxits, _state); - if( ckind==0 ) - { - minnlcsetbc(&state, &bndl, &bndu, _state); - } - if( ckind==1 ) - { - minnlcsetlc(&state, &c, &ct, 1, _state); - } - if( ckind==2 ) - { - minnlcsetnlc(&state, 0, 1, _state); - } - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = state.x.ptr.p_double[0]-ae_sqr(state.x.ptr.p_double[0], _state); - state.j.ptr.pp_double[0][0] = 1-2*state.x.ptr.p_double[0]; - if( ckind==2 ) - { - state.fi.ptr.p_double[1] = -state.x.ptr.p_double[0]; - state.j.ptr.pp_double[1][0] = (double)(-1); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:5118"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(wereerrors, ae_fp_less(x1.ptr.p_double[0],3*state.stabilizingpoint), __FILE__, __LINE__, "testminnlcunit.ap:5121"); - minnlccreate(n, &x0, &state, _state); - minnlcsetalgoaul(&state, rho, aulits, _state); - minnlcsetcond(&state, 0.0, maxits, _state); - if( ckind==0 ) - { - minnlcsetbc(&state, &bndl, &bndu, _state); - } - if( ckind==1 ) - { - minnlcsetlc(&state, &c, &ct, 1, _state); - } - if( ckind==2 ) - { - minnlcsetnlc(&state, 0, 1, _state); - } - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = state.x.ptr.p_double[0]-ae_sqr(state.x.ptr.p_double[0], _state); - state.j.ptr.pp_double[0][0] = 1-2*state.x.ptr.p_double[0]; - if( ckind==2 ) - { - state.fi.ptr.p_double[1] = -state.x.ptr.p_double[0]; - state.j.ptr.pp_double[1][0] = (double)(-1); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:5148"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(wereerrors, ae_fp_less(x1.ptr.p_double[0],3*state.stabilizingpoint), __FILE__, __LINE__, "testminnlcunit.ap:5151"); - } - - /* - * This test checks report by E. Pozamantir. Relevant for SLP - * and related methods, but we test it for all algorithms. - * - * Description: - * - * The sequential linear programming solver performs warm-start - * at each iteration, i.e. it reuses previously found LP basis. - * However, when some initially non-zero Jacobian entries become - * exactly zero (possible with constraints which are nonsmooth - * at some distance from the boundary), our warm-start strategy - * may fail because warm-start basis becomes exactly degenerate. - * - * In order to test that this bug was fixed we solve carefully - * designed noisy test problem with Jacobian entries being randomly - * turned on and off. Simply being able to return from the solver - * without triggering critical exception is enough. - */ - for(solvertype=0; solvertype<=testminnlcunit_maxsolvertype; solvertype++) - { - for(n=6; n<=15; n++) - { - - /* - * Setup problem - */ - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&d, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - d.ptr.p_double[i] = ae_sqr(hqrndnormal(&rs, _state), _state); - } - k = 1+hqrnduniformi(&rs, n/3, _state); - ae_matrix_set_length(&c, 2*k, n+1, _state); - for(i=0; i<=2*k-1; i++) - { - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - for(i=0; i<=k-1; i++) - { - c.ptr.pp_double[i][n] = (double)(0); - } - for(i=k; i<=2*k-1; i++) - { - c.ptr.pp_double[i][n] = 0.1+hqrnduniformr(&rs, _state); - } - - /* - * Create solver and solve problem - */ - minnlccreate(n, &x0, &state, _state); - if( solvertype==0 ) - { - minnlcsetalgoaul(&state, 200.0, 20, _state); - } - else - { - if( solvertype==1 ) - { - minnlcsetalgoslp(&state, _state); - } - else - { - if( solvertype==2 ) - { - minnlcsetalgosqp(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - minnlcsetcond(&state, 1.0E-7, 20, _state); - minnlcsetnlc(&state, k, k, _state); - while(minnlciteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(j=0; j<=n-1; j++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*d.ptr.p_double[j]*ae_sqr(state.x.ptr.p_double[j], _state); - state.j.ptr.pp_double[0][j] = d.ptr.p_double[j]*state.x.ptr.p_double[j]; - } - for(i=0; i<=2*k-1; i++) - { - state.fi.ptr.p_double[1+i] = -c.ptr.pp_double[i][n]; - for(j=0; j<=n-1; j++) - { - state.fi.ptr.p_double[1+i] = state.fi.ptr.p_double[1+i]+c.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.j.ptr.pp_double[1+i][j] = hqrnduniformi(&rs, 2, _state)*c.ptr.pp_double[i][j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnlcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:5238"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:5239"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests report of "non-C1" test #0 for task #0 -given by matrix A. - -On failure sets error flag. -*************************************************************************/ -static void testminnlcunit_testoptguardc1test0reportfortask0(ae_bool* err, - optguardnonc1test0report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double va; - double vb; - ae_bool hasc1discontinuities; - - - if( rep->positive ) - { - - /* - * Check positive report, first checks - */ - ae_set_error_flag(err, rep->fidx!=0, __FILE__, __LINE__, "testminnlcunit.ap:5268"); - ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testminnlcunit.ap:5269"); - ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testminnlcunit.ap:5270"); - ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testminnlcunit.ap:5271"); - ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testminnlcunit.ap:5272"); - ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testminnlcunit.ap:5273"); - ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testminnlcunit.ap:5274"); - ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testminnlcunit.ap:5275"); - ae_set_error_flag(err, rep->f.cnt!=rep->cnt, __FILE__, __LINE__, "testminnlcunit.ap:5276"); - ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:5277"); - ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:5278"); - ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testminnlcunit.ap:5279"); - ae_set_error_flag(err, !isfinitevector(&rep->f, rep->cnt, _state), __FILE__, __LINE__, "testminnlcunit.ap:5280"); - if( *err ) - { - return; - } - - /* - * Check consistency of Stp. - */ - for(k=0; k<=rep->cnt-2; k++) - { - ae_set_error_flag(err, ae_fp_greater_eq(rep->stp.ptr.p_double[k],rep->stp.ptr.p_double[k+1]), __FILE__, __LINE__, "testminnlcunit.ap:5288"); - } - - /* - * Check that interval [#StpIdxA,#StpIdxB] contains at least one discontinuity - */ - hasc1discontinuities = ae_false; - for(i=0; i<=n-1; i++) - { - va = (double)(0); - vb = (double)(0); - for(j=0; j<=n-1; j++) - { - va = va+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxa]); - vb = vb+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxb]); - } - hasc1discontinuities = hasc1discontinuities||ae_sign(va, _state)!=ae_sign(vb, _state); - } - ae_set_error_flag(err, !hasc1discontinuities, __FILE__, __LINE__, "testminnlcunit.ap:5305"); - } - else - { - - /* - * Check negative report: fields must be empty - */ - ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5312"); - ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5313"); - ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5314"); - ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5315"); - ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testminnlcunit.ap:5316"); - ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5317"); - ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5318"); - ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5319"); - ae_set_error_flag(err, rep->f.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5320"); - } -} - - -/************************************************************************* -This function tests report of "non-C1" test #1 for task #0 -given by matrix A. - -On failure sets error flag. -*************************************************************************/ -static void testminnlcunit_testoptguardc1test1reportfortask0(ae_bool* err, - optguardnonc1test1report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double va; - double vb; - ae_bool tooclose; - ae_bool hasc1discontinuities; - - - if( rep->positive ) - { - - /* - * Check positive report, first checks - */ - ae_set_error_flag(err, rep->fidx!=0, __FILE__, __LINE__, "testminnlcunit.ap:5348"); - ae_set_error_flag(err, rep->vidx<0, __FILE__, __LINE__, "testminnlcunit.ap:5349"); - ae_set_error_flag(err, rep->vidx>n, __FILE__, __LINE__, "testminnlcunit.ap:5350"); - ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testminnlcunit.ap:5351"); - ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testminnlcunit.ap:5352"); - ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testminnlcunit.ap:5353"); - ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testminnlcunit.ap:5354"); - ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testminnlcunit.ap:5355"); - ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testminnlcunit.ap:5356"); - ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testminnlcunit.ap:5357"); - ae_set_error_flag(err, rep->g.cnt!=rep->cnt, __FILE__, __LINE__, "testminnlcunit.ap:5358"); - ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:5359"); - ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:5360"); - ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testminnlcunit.ap:5361"); - ae_set_error_flag(err, !isfinitevector(&rep->g, rep->cnt, _state), __FILE__, __LINE__, "testminnlcunit.ap:5362"); - if( *err ) - { - return; - } - - /* - * Check consistency of Stp - */ - for(k=0; k<=rep->cnt-2; k++) - { - ae_set_error_flag(err, ae_fp_greater_eq(rep->stp.ptr.p_double[k],rep->stp.ptr.p_double[k+1]), __FILE__, __LINE__, "testminnlcunit.ap:5370"); - } - - /* - * Check that interval [#StpIdxA,#StpIdxB] contains at least one discontinuity - */ - tooclose = ae_false; - hasc1discontinuities = ae_false; - for(i=0; i<=n-1; i++) - { - va = (double)(0); - vb = (double)(0); - for(j=0; j<=n-1; j++) - { - va = va+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxa]); - vb = vb+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxb]); - } - tooclose = (tooclose||ae_fp_less(ae_fabs(va, _state),1.0E-8))||ae_fp_less(ae_fabs(vb, _state),1.0E-8); - hasc1discontinuities = hasc1discontinuities||ae_sign(va, _state)!=ae_sign(vb, _state); - } - if( !tooclose ) - { - ae_set_error_flag(err, !hasc1discontinuities, __FILE__, __LINE__, "testminnlcunit.ap:5390"); - } - } - else - { - - /* - * Check negative report: fields must be empty - */ - ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5397"); - ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5398"); - ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5399"); - ae_set_error_flag(err, rep->vidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5400"); - ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5401"); - ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testminnlcunit.ap:5402"); - ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5403"); - ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5404"); - ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5405"); - ae_set_error_flag(err, rep->g.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5406"); - } -} - - -/************************************************************************* -This function tests report of "non-C1" test #0 for task #1 -given by matrix A. - -On failure sets error flag. -*************************************************************************/ -static void testminnlcunit_testoptguardc1test0reportfortask1(ae_bool* err, - optguardnonc1test0report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t goodidx, - ae_state *_state) -{ - - - if( rep->positive ) - { - - /* - * Check positive report, first checks - */ - ae_set_error_flag(err, rep->fidx==goodidx+1, __FILE__, __LINE__, "testminnlcunit.ap:5430"); - ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testminnlcunit.ap:5431"); - ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testminnlcunit.ap:5432"); - ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testminnlcunit.ap:5433"); - ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testminnlcunit.ap:5434"); - ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testminnlcunit.ap:5435"); - ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testminnlcunit.ap:5436"); - ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testminnlcunit.ap:5437"); - ae_set_error_flag(err, rep->f.cnt!=rep->cnt, __FILE__, __LINE__, "testminnlcunit.ap:5438"); - ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:5439"); - ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:5440"); - ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testminnlcunit.ap:5441"); - ae_set_error_flag(err, !isfinitevector(&rep->f, rep->cnt, _state), __FILE__, __LINE__, "testminnlcunit.ap:5442"); - if( *err ) - { - return; - } - } - else - { - - /* - * Check negative report: fields must be empty - */ - ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5451"); - ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5452"); - ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5453"); - ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5454"); - ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testminnlcunit.ap:5455"); - ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5456"); - ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5457"); - ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5458"); - ae_set_error_flag(err, rep->f.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5459"); - } -} - - -/************************************************************************* -This function tests report of "non-C1" test #1 for task #1 given by matrix A. - -On failure sets error flag. -*************************************************************************/ -static void testminnlcunit_testoptguardc1test1reportfortask1(ae_bool* err, - optguardnonc1test1report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t goodidx, - ae_state *_state) -{ - - - if( rep->positive ) - { - - /* - * Check positive report, first checks - */ - ae_set_error_flag(err, rep->fidx==goodidx+1, __FILE__, __LINE__, "testminnlcunit.ap:5482"); - ae_set_error_flag(err, rep->vidx<0, __FILE__, __LINE__, "testminnlcunit.ap:5483"); - ae_set_error_flag(err, rep->vidx>n, __FILE__, __LINE__, "testminnlcunit.ap:5484"); - ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testminnlcunit.ap:5485"); - ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testminnlcunit.ap:5486"); - ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testminnlcunit.ap:5487"); - ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testminnlcunit.ap:5488"); - ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testminnlcunit.ap:5489"); - ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testminnlcunit.ap:5490"); - ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testminnlcunit.ap:5491"); - ae_set_error_flag(err, rep->g.cnt!=rep->cnt, __FILE__, __LINE__, "testminnlcunit.ap:5492"); - ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:5493"); - ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:5494"); - ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testminnlcunit.ap:5495"); - ae_set_error_flag(err, !isfinitevector(&rep->g, rep->cnt, _state), __FILE__, __LINE__, "testminnlcunit.ap:5496"); - if( *err ) - { - return; - } - } - else - { - - /* - * Check negative report: fields must be empty - */ - ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5505"); - ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5506"); - ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5507"); - ae_set_error_flag(err, rep->vidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5508"); - ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5509"); - ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testminnlcunit.ap:5510"); - ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5511"); - ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5512"); - ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5513"); - ae_set_error_flag(err, rep->g.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5514"); - } -} - - - -static ae_int_t testminbcunit_maxoptguardlevel = 1; -static void testminbcunit_calciip2(minbcstate* state, - ae_int_t n, - ae_int_t fk, - ae_state *_state); -static void testminbcunit_testfeasibility(ae_bool* feaserr, - ae_bool* converr, - ae_bool* interr, - ae_state *_state); -static void testminbcunit_testother(ae_bool* err, ae_state *_state); -static void testminbcunit_testpreconditioning(ae_bool* err, - ae_state *_state); -static void testminbcunit_testoptguard(ae_bool* wereerrors, - ae_state *_state); -static void testminbcunit_setrandompreconditioner(minbcstate* state, - ae_int_t n, - ae_int_t preckind, - ae_state *_state); -static void testminbcunit_testoptguardc1test0reportfortask0(ae_bool* err, - optguardnonc1test0report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state); -static void testminbcunit_testoptguardc1test1reportfortask0(ae_bool* err, - optguardnonc1test1report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state); - - - - - -ae_bool testminbc(ae_bool silent, ae_state *_state) -{ - ae_bool waserrors; - ae_bool feasibilityerrors; - ae_bool othererrors; - ae_bool precerrors; - ae_bool interrors; - ae_bool converrors; - ae_bool optguarderrors; - ae_bool result; - - - waserrors = ae_false; - feasibilityerrors = ae_false; - othererrors = ae_false; - precerrors = ae_false; - interrors = ae_false; - converrors = ae_false; - optguarderrors = ae_false; - testminbcunit_testfeasibility(&feasibilityerrors, &converrors, &interrors, _state); - testminbcunit_testother(&othererrors, _state); - testminbcunit_testpreconditioning(&precerrors, _state); - testminbcunit_testoptguard(&optguarderrors, _state); - - /* - * end - */ - waserrors = ((((feasibilityerrors||othererrors)||converrors)||interrors)||precerrors)||optguarderrors; - if( !silent ) - { - printf("TESTING BC OPTIMIZATION\n"); - printf("FEASIBILITY PROPERTIES: "); - if( feasibilityerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("PRECONDITIONING: "); - if( precerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("OTHER PROPERTIES: "); - if( othererrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("CONVERGENCE PROPERTIES: "); - if( converrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("INTERNAL ERRORS: "); - if( interrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("OPTGUARD: "); - if( optguarderrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - return result; -} - - -/************************************************************************* -Calculate test function IIP2 - -f(x) = sum( ((i*i+1)^FK*x[i])^2, i=0..N-1) - -It has high condition number which makes fast convergence unlikely without -good preconditioner. - -*************************************************************************/ -static void testminbcunit_calciip2(minbcstate* state, - ae_int_t n, - ae_int_t fk, - ae_state *_state) -{ - ae_int_t i; - - - if( state->needfg ) - { - state->f = (double)(0); - } - for(i=0; i<=n-1; i++) - { - if( state->needfg ) - { - state->f = state->f+ae_pow((double)(i*i+1), (double)(2*fk), _state)*ae_sqr(state->x.ptr.p_double[i], _state); - state->g.ptr.p_double[i] = ae_pow((double)(i*i+1), (double)(2*fk), _state)*2*state->x.ptr.p_double[i]; - } - } -} - - -/************************************************************************* -This function test feasibility properties. -It launches a sequence of problems and examines their solutions. -Most of the attention is directed towards feasibility properties, -although we make some quick checks to ensure that actual solution is found. - -On failure sets FeasErr (or ConvErr, depending on failure type) to True, -or leaves it unchanged otherwise. - -IntErr is set to True on internal errors (errors in the control flow). -*************************************************************************/ -static void testminbcunit_testfeasibility(ae_bool* feaserr, - ae_bool* converr, - ae_bool* interr, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t pkind; - ae_int_t preckind; - ae_int_t passcount; - ae_int_t pass; - ae_int_t n; - ae_int_t nmax; - ae_int_t i; - ae_int_t p; - double v; - ae_vector bl; - ae_vector bu; - ae_vector x; - ae_vector g; - ae_vector x0; - ae_vector xc; - ae_vector xs; - ae_vector svdw; - ae_matrix csvdu; - ae_matrix svdvt; - minbcstate state; - double weakepsg; - minbcreport rep; - ae_int_t dkind; - double diffstep; - - ae_frame_make(_state, &_frame_block); - memset(&bl, 0, sizeof(bl)); - memset(&bu, 0, sizeof(bu)); - memset(&x, 0, sizeof(x)); - memset(&g, 0, sizeof(g)); - memset(&x0, 0, sizeof(x0)); - memset(&xc, 0, sizeof(xc)); - memset(&xs, 0, sizeof(xs)); - memset(&svdw, 0, sizeof(svdw)); - memset(&csvdu, 0, sizeof(csvdu)); - memset(&svdvt, 0, sizeof(svdvt)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - ae_vector_init(&bl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&g, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xs, 0, DT_REAL, _state, ae_true); - ae_vector_init(&svdw, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&csvdu, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&svdvt, 0, 0, DT_REAL, _state, ae_true); - _minbcstate_init(&state, _state, ae_true); - _minbcreport_init(&rep, _state, ae_true); - - nmax = 5; - weakepsg = 1.0E-4; - passcount = 10; - for(pass=1; pass<=passcount; pass++) - { - - /* - * Another simple problem: - * * bound constraints 0 <= x[i] <= 1 - * * no linear constraints - * * preconditioner is chosen at random (we just want to be - * sure that preconditioning won't prevent us from converging - * to the feasible point): - * * unit preconditioner - * * random diagonal-based preconditioner - * * random scale-based preconditioner - * * F(x) = |x-x0|^P, where P={2,4} and x0 is randomly selected from [-1,+2]^N - * * with such simple boundaries and function it is easy to find - * analytic form of solution: S[i] = bound(x0[i], 0, 1) - * * we also check that both final solution and subsequent iterates - * are strictly feasible - */ - diffstep = 1.0E-6; - for(dkind=0; dkind<=1; dkind++) - { - for(preckind=0; preckind<=2; preckind++) - { - for(pkind=1; pkind<=2; pkind++) - { - for(n=1; n<=nmax; n++) - { - - /* - * Generate X, BL, BU. - */ - p = 2*pkind; - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - bl.ptr.p_double[i] = (double)(0); - bu.ptr.p_double[i] = (double)(1); - x.ptr.p_double[i] = ae_randomreal(_state); - x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1; - } - - /* - * Create and optimize - */ - if( dkind==0 ) - { - minbccreate(n, &x, &state, _state); - } - if( dkind==1 ) - { - minbccreatef(n, &x, diffstep, &state, _state); - } - minbcsetbc(&state, &bl, &bu, _state); - minbcsetcond(&state, weakepsg, 0.0, 0.0, 0, _state); - testminbcunit_setrandompreconditioner(&state, n, preckind, _state); - while(minbciteration(&state, _state)) - { - if( state.needf||state.needfg ) - { - state.f = (double)(0); - } - for(i=0; i<=n-1; i++) - { - if( state.needf||state.needfg ) - { - state.f = state.f+ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p), _state); - } - if( state.needfg ) - { - state.g.ptr.p_double[i] = p*ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state); - } - *feaserr = *feaserr||ae_fp_less(state.x.ptr.p_double[i],0.0); - *feaserr = *feaserr||ae_fp_greater(state.x.ptr.p_double[i],1.0); - } - } - minbcresults(&state, &x, &rep, _state); - if( rep.terminationtype<=0 ) - { - *converr = ae_true; - ae_frame_leave(_state); - return; - } - - /* - * * compare solution with analytic one - * * check feasibility - */ - v = 0.0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(x.ptr.p_double[i],(double)(0))&&ae_fp_less(x.ptr.p_double[i],(double)(1)) ) - { - v = v+ae_sqr(p*ae_pow(x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state), _state); - } - *feaserr = *feaserr||ae_fp_less(x.ptr.p_double[i],0.0); - *feaserr = *feaserr||ae_fp_greater(x.ptr.p_double[i],1.0); - } - *converr = *converr||ae_fp_greater(ae_sqrt(v, _state),weakepsg); - } - } - } - } - - /* - * Same as previous problem, but with minor modifications: - * * some bound constraints are 0<=x[i]<=1, some are Ci=x[i]=Ci - * * no linear constraints - * * preconditioner is chosen at random (we just want to be - * sure that preconditioning won't prevent us from converging - * to the feasible point): - * * unit preconditioner - * * random diagonal-based preconditioner - * * random scale-based preconditioner - * * F(x) = |x-x0|^P, where P={2,4} and x0 is randomly selected from [-1,+2]^N - * * with such simple boundaries and function it is easy to find - * analytic form of solution: S[i] = bound(x0[i], 0, 1) - * * we also check that both final solution and subsequent iterates - * are strictly feasible - */ - diffstep = 1.0E-6; - for(dkind=0; dkind<=1; dkind++) - { - for(preckind=0; preckind<=2; preckind++) - { - for(pkind=1; pkind<=2; pkind++) - { - for(n=1; n<=nmax; n++) - { - - /* - * Generate X, BL, BU. - */ - p = 2*pkind; - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - bl.ptr.p_double[i] = (double)(0); - bu.ptr.p_double[i] = (double)(1); - } - else - { - bl.ptr.p_double[i] = ae_randomreal(_state); - bu.ptr.p_double[i] = bl.ptr.p_double[i]; - } - x.ptr.p_double[i] = ae_randomreal(_state); - x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1; - } - - /* - * Create and optimize - */ - if( dkind==0 ) - { - minbccreate(n, &x, &state, _state); - } - if( dkind==1 ) - { - minbccreatef(n, &x, diffstep, &state, _state); - } - minbcsetbc(&state, &bl, &bu, _state); - minbcsetcond(&state, weakepsg, 0.0, 0.0, 0, _state); - testminbcunit_setrandompreconditioner(&state, n, preckind, _state); - while(minbciteration(&state, _state)) - { - if( state.needf||state.needfg ) - { - state.f = (double)(0); - } - for(i=0; i<=n-1; i++) - { - if( state.needf||state.needfg ) - { - state.f = state.f+ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p), _state); - } - if( state.needfg ) - { - state.g.ptr.p_double[i] = p*ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state); - } - *feaserr = *feaserr||ae_fp_less(state.x.ptr.p_double[i],bl.ptr.p_double[i]); - *feaserr = *feaserr||ae_fp_greater(state.x.ptr.p_double[i],bu.ptr.p_double[i]); - } - } - minbcresults(&state, &x, &rep, _state); - if( rep.terminationtype<=0 ) - { - *converr = ae_true; - ae_frame_leave(_state); - return; - } - - /* - * * compare solution with analytic one - * * check feasibility - */ - v = 0.0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(x.ptr.p_double[i],bl.ptr.p_double[i])&&ae_fp_less(x.ptr.p_double[i],bu.ptr.p_double[i]) ) - { - v = v+ae_sqr(p*ae_pow(x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state), _state); - } - *feaserr = *feaserr||ae_fp_less(x.ptr.p_double[i],bl.ptr.p_double[i]); - *feaserr = *feaserr||ae_fp_greater(x.ptr.p_double[i],bu.ptr.p_double[i]); - } - *converr = *converr||ae_fp_greater(ae_sqrt(v, _state),weakepsg); - } - } - } - } - - /* - * Infeasible problem: - * * all bound constraints are 0 <= x[i] <= 1 except for one - * * that one is 0 >= x[i] >= 1 - * * no linear constraints - * * preconditioner is chosen at random (we just want to be - * sure that preconditioning won't prevent us from detecting - * infeasible point): - * * unit preconditioner - * * random diagonal-based preconditioner - * * random scale-based preconditioner - * * F(x) = |x-x0|^P, where P={2,4} and x0 is randomly selected from [-1,+2]^N - * * algorithm must return correct error code on such problem - */ - for(preckind=0; preckind<=2; preckind++) - { - for(pkind=1; pkind<=2; pkind++) - { - for(n=1; n<=nmax; n++) - { - - /* - * Generate X, BL, BU. - */ - p = 2*pkind; - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - bl.ptr.p_double[i] = (double)(0); - bu.ptr.p_double[i] = (double)(1); - x.ptr.p_double[i] = ae_randomreal(_state); - x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1; - } - i = ae_randominteger(n, _state); - bl.ptr.p_double[i] = (double)(1); - bu.ptr.p_double[i] = (double)(0); - - /* - * Create and optimize - */ - minbccreate(n, &x, &state, _state); - minbcsetbc(&state, &bl, &bu, _state); - minbcsetcond(&state, weakepsg, 0.0, 0.0, 0, _state); - testminbcunit_setrandompreconditioner(&state, n, preckind, _state); - while(minbciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p), _state); - state.g.ptr.p_double[i] = p*ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state); - } - continue; - } - - /* - * Unknown protocol specified - */ - *interr = ae_true; - ae_frame_leave(_state); - return; - } - minbcresults(&state, &x, &rep, _state); - *feaserr = *feaserr||rep.terminationtype!=-3; - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function additional properties. - -On failure sets Err to True (leaves it unchanged otherwise) -*************************************************************************/ -static void testminbcunit_testother(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t passcount; - ae_int_t pass; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_vector bl; - ae_vector bu; - ae_vector x; - ae_vector xf; - ae_vector x0; - ae_vector x1; - ae_vector b; - ae_vector xlast; - ae_vector a; - ae_vector s; - ae_vector h; - ae_matrix fulla; - double fprev; - double xprev; - double stpmax; - double v; - ae_int_t pkind; - ae_int_t ckind; - ae_int_t mkind; - double vc; - double vm; - minbcstate state; - double epsx; - double epsg; - double eps; - double tmpeps; - minbcreport rep; - double diffstep; - ae_int_t dkind; - ae_bool wasf; - ae_bool wasfg; - double r; - hqrndstate rs; - ae_int_t spoiliteration; - ae_int_t stopiteration; - ae_int_t spoilvar; - double spoilval; - double ss; - ae_int_t stopcallidx; - ae_int_t callidx; - ae_int_t maxits; - ae_bool terminationrequested; - - ae_frame_make(_state, &_frame_block); - memset(&bl, 0, sizeof(bl)); - memset(&bu, 0, sizeof(bu)); - memset(&x, 0, sizeof(x)); - memset(&xf, 0, sizeof(xf)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&b, 0, sizeof(b)); - memset(&xlast, 0, sizeof(xlast)); - memset(&a, 0, sizeof(a)); - memset(&s, 0, sizeof(s)); - memset(&h, 0, sizeof(h)); - memset(&fulla, 0, sizeof(fulla)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&rs, 0, sizeof(rs)); - ae_vector_init(&bl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xlast, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&h, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&fulla, 0, 0, DT_REAL, _state, ae_true); - _minbcstate_init(&state, _state, ae_true); - _minbcreport_init(&rep, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - epsx = 1.0E-4; - epsg = 1.0E-8; - passcount = 10; - - /* - * Try to reproduce bug 570 (optimizer hangs on problems where it is required - * to perform very small step - less than 1E-50 - in order to activate constraints). - * - * The problem being solved is: - * - * min x[0]+x[1]+...+x[n-1] - * - * subject to - * - * x[i]>=0, for i=0..n-1 - * - * with initial point - * - * x[0] = 1.0E-100, x[1]=x[2]=...=0.5 - * - * We try to reproduce this problem in different settings: - * * boundary-only constraints - we test that completion code is positive, - * and all x[] are EXACTLY zero - * * boundary constraints posed as general linear ones - we test that - * completion code is positive, and all x[] are APPROXIMATELY zero. - */ - n = 10; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 0.5; - bl.ptr.p_double[i] = 0.0; - bu.ptr.p_double[i] = _state->v_posinf; - } - x.ptr.p_double[0] = 1.0E-100; - minbccreate(n, &x, &state, _state); - minbcsetbc(&state, &bl, &bu, _state); - minbcsetcond(&state, (double)(0), (double)(0), (double)(0), 2*n, _state); - while(minbciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+state.x.ptr.p_double[i]; - state.g.ptr.p_double[i] = 1.0; - } - } - } - minbcresults(&state, &xf, &rep, _state); - ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminbcunit.ap:494"); - if( rep.terminationtype>0 ) - { - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(err, ae_fp_neq(xf.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testminbcunit.ap:497"); - } - } - - /* - * Test reports: - * * first value must be starting point - * * last value must be last point - */ - for(pass=1; pass<=passcount; pass++) - { - n = 50; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&xlast, n, _state); - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = (double)(10); - bl.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - bu.ptr.p_double[i] = _state->v_posinf; - } - minbccreate(n, &x, &state, _state); - minbcsetbc(&state, &bl, &bu, _state); - minbcsetcond(&state, 1.0E-64, (double)(0), (double)(0), 10, _state); - minbcsetxrep(&state, ae_true, _state); - fprev = ae_maxrealnumber; - while(minbciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+ae_sqr((1+i)*state.x.ptr.p_double[i], _state); - state.g.ptr.p_double[i] = 2*(1+i)*state.x.ptr.p_double[i]; - } - } - if( state.xupdated ) - { - if( ae_fp_eq(fprev,ae_maxrealnumber) ) - { - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(err, ae_fp_neq(state.x.ptr.p_double[i],x.ptr.p_double[i]), __FILE__, __LINE__, "testminbcunit.ap:538"); - } - } - fprev = state.f; - ae_v_move(&xlast.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - } - } - minbcresults(&state, &x, &rep, _state); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(err, ae_fp_neq(x.ptr.p_double[i],xlast.ptr.p_double[i]), __FILE__, __LINE__, "testminbcunit.ap:545"); - } - } - - /* - * Test differentiation vs. analytic gradient - * (first one issues NeedF requests, second one issues NeedFG requests) - */ - for(pass=1; pass<=passcount; pass++) - { - n = 10; - diffstep = 1.0E-6; - for(dkind=0; dkind<=1; dkind++) - { - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&xlast, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = (double)(1); - } - if( dkind==0 ) - { - minbccreate(n, &x, &state, _state); - } - if( dkind==1 ) - { - minbccreatef(n, &x, diffstep, &state, _state); - } - minbcsetcond(&state, 1.0E-6, (double)(0), epsx, 0, _state); - wasf = ae_false; - wasfg = ae_false; - while(minbciteration(&state, _state)) - { - if( state.needf||state.needfg ) - { - state.f = (double)(0); - } - for(i=0; i<=n-1; i++) - { - if( state.needf||state.needfg ) - { - state.f = state.f+ae_sqr((1+i)*state.x.ptr.p_double[i], _state); - } - if( state.needfg ) - { - state.g.ptr.p_double[i] = 2*(1+i)*state.x.ptr.p_double[i]; - } - } - wasf = wasf||state.needf; - wasfg = wasfg||state.needfg; - } - minbcresults(&state, &x, &rep, _state); - if( dkind==0 ) - { - ae_set_error_flag(err, wasf||!wasfg, __FILE__, __LINE__, "testminbcunit.ap:585"); - } - if( dkind==1 ) - { - ae_set_error_flag(err, !wasf||wasfg, __FILE__, __LINE__, "testminbcunit.ap:587"); - } - } - } - - /* - * Test that numerical differentiation uses scaling. - * - * In order to test that we solve simple optimization - * problem: min(x^2) with initial x equal to 0.0. - * - * We choose random DiffStep and S, then we check that - * optimizer evaluates function at +-DiffStep*S only. - */ - for(pass=1; pass<=passcount; pass++) - { - ae_vector_set_length(&x, 1, _state); - ae_vector_set_length(&s, 1, _state); - diffstep = ae_randomreal(_state)*1.0E-6; - s.ptr.p_double[0] = ae_exp(ae_randomreal(_state)*4-2, _state); - x.ptr.p_double[0] = (double)(0); - minbccreatef(1, &x, diffstep, &state, _state); - minbcsetcond(&state, 1.0E-6, (double)(0), epsx, 0, _state); - minbcsetscale(&state, &s, _state); - v = (double)(0); - while(minbciteration(&state, _state)) - { - state.f = ae_sqr(state.x.ptr.p_double[0], _state); - v = ae_maxreal(v, ae_fabs(state.x.ptr.p_double[0], _state), _state); - } - minbcresults(&state, &x, &rep, _state); - r = v/(s.ptr.p_double[0]*diffstep); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(ae_log(r, _state), _state),ae_log(1+1000*ae_machineepsilon, _state)), __FILE__, __LINE__, "testminbcunit.ap:618"); - } - - /* - * Test stpmax - */ - for(pass=1; pass<=passcount; pass++) - { - n = 1; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - x.ptr.p_double[0] = (double)(100); - bl.ptr.p_double[0] = 2*ae_randomreal(_state)-1; - bu.ptr.p_double[0] = _state->v_posinf; - stpmax = 0.05+0.05*ae_randomreal(_state); - minbccreate(n, &x, &state, _state); - minbcsetbc(&state, &bl, &bu, _state); - minbcsetcond(&state, epsg, (double)(0), epsx, 0, _state); - minbcsetxrep(&state, ae_true, _state); - minbcsetstpmax(&state, stpmax, _state); - xprev = x.ptr.p_double[0]; - while(minbciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = ae_exp(state.x.ptr.p_double[0], _state)+ae_exp(-state.x.ptr.p_double[0], _state); - state.g.ptr.p_double[0] = ae_exp(state.x.ptr.p_double[0], _state)-ae_exp(-state.x.ptr.p_double[0], _state); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(state.x.ptr.p_double[0]-xprev, _state),(1+ae_sqrt(ae_machineepsilon, _state))*stpmax), __FILE__, __LINE__, "testminbcunit.ap:646"); - } - if( state.xupdated ) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(state.x.ptr.p_double[0]-xprev, _state),(1+ae_sqrt(ae_machineepsilon, _state))*stpmax), __FILE__, __LINE__, "testminbcunit.ap:650"); - xprev = state.x.ptr.p_double[0]; - } - } - } - - /* - * Ability to solve problems with function which is unbounded from below - */ - for(pass=1; pass<=passcount; pass++) - { - n = 1; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - bl.ptr.p_double[0] = 4*ae_randomreal(_state)+1; - bu.ptr.p_double[0] = bl.ptr.p_double[0]+1; - x.ptr.p_double[0] = 0.5*(bl.ptr.p_double[0]+bu.ptr.p_double[0]); - minbccreate(n, &x, &state, _state); - minbcsetbc(&state, &bl, &bu, _state); - minbcsetcond(&state, epsg, (double)(0), epsx, 0, _state); - while(minbciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = -1.0E8*ae_sqr(state.x.ptr.p_double[0], _state); - state.g.ptr.p_double[0] = -2.0E8*state.x.ptr.p_double[0]; - } - } - minbcresults(&state, &x, &rep, _state); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(x.ptr.p_double[0]-bu.ptr.p_double[0], _state),epsx), __FILE__, __LINE__, "testminbcunit.ap:680"); - } - - /* - * Test correctness of the scaling: - * * initial point is random point from [+1,+2]^N - * * f(x) = SUM(A[i]*x[i]^4), C[i] is random from [0.01,100] - * * function is EFFECTIVELY unconstrained; it has formal constraints, - * but they are inactive at the solution; we try different variants - * in order to explore different control paths of the optimizer: - * 0) absense of constraints - * 1) bound constraints -100000<=x[i]<=100000 - * * we use random scaling matrix - * * we test different variants of the preconditioning: - * 0) unit preconditioner - * 1) random diagonal from [0.01,100] - * 2) scale preconditioner - * * we set very stringent stopping conditions - * * and we test that in the extremum stopping conditions are - * satisfied subject to the current scaling coefficients. - */ - for(pass=1; pass<=passcount; pass++) - { - tmpeps = 1.0E-5; - for(n=1; n<=10; n++) - { - for(ckind=0; ckind<=1; ckind++) - { - for(pkind=0; pkind<=2; pkind++) - { - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&a, n, _state); - ae_vector_set_length(&s, n, _state); - ae_vector_set_length(&h, n, _state); - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = ae_randomreal(_state)+1; - bl.ptr.p_double[i] = (double)(-100000); - bu.ptr.p_double[i] = (double)(100000); - a.ptr.p_double[i] = ae_exp(ae_log((double)(10), _state)*(2*ae_randomreal(_state)-1), _state); - s.ptr.p_double[i] = ae_exp(ae_log((double)(10), _state)*(2*ae_randomreal(_state)-1), _state); - h.ptr.p_double[i] = ae_exp(ae_log((double)(10), _state)*(2*ae_randomreal(_state)-1), _state); - } - minbccreate(n, &x, &state, _state); - if( ckind==1 ) - { - minbcsetbc(&state, &bl, &bu, _state); - } - if( pkind==1 ) - { - minbcsetprecdiag(&state, &h, _state); - } - if( pkind==2 ) - { - minbcsetprecscale(&state, _state); - } - minbcsetcond(&state, tmpeps, (double)(0), (double)(0), 0, _state); - minbcsetscale(&state, &s, _state); - while(minbciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+a.ptr.p_double[i]*ae_sqr(state.x.ptr.p_double[i], _state); - state.g.ptr.p_double[i] = 2*a.ptr.p_double[i]*state.x.ptr.p_double[i]; - } - } - } - minbcresults(&state, &x, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminbcunit.ap:747"); - ae_frame_leave(_state); - return; - } - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+ae_sqr(s.ptr.p_double[i]*2*a.ptr.p_double[i]*x.ptr.p_double[i], _state); - } - v = ae_sqrt(v, _state); - ae_set_error_flag(err, ae_fp_greater(v,tmpeps), __FILE__, __LINE__, "testminbcunit.ap:754"); - } - } - } - } - - /* - * Check correctness of the "trimming". - * - * Trimming is a technique which is used to help algorithm - * cope with unbounded functions. In order to check this - * technique we will try to solve following optimization - * problem: - * - * min f(x) subject to no constraints on X - * { 1/(1-x) + 1/(1+x) + c*x, if -0.999999=0.999999 - * - * where c is either 1.0 or 1.0E+4, M is either 1.0E8, 1.0E20 or +INF - * (we try different combinations) - */ - for(pass=1; pass<=passcount; pass++) - { - for(ckind=0; ckind<=1; ckind++) - { - for(mkind=0; mkind<=2; mkind++) - { - - /* - * Choose c and M - */ - vc = (double)(1); - vm = (double)(1); - if( ckind==0 ) - { - vc = 1.0; - } - if( ckind==1 ) - { - vc = 1.0E+4; - } - if( mkind==0 ) - { - vm = 1.0E+8; - } - if( mkind==1 ) - { - vm = 1.0E+20; - } - if( mkind==2 ) - { - vm = _state->v_posinf; - } - - /* - * Create optimizer, solve optimization problem - */ - epsg = 1.0E-6*vc; - ae_vector_set_length(&x, 1, _state); - x.ptr.p_double[0] = 0.0; - minbccreate(1, &x, &state, _state); - minbcsetcond(&state, epsg, (double)(0), (double)(0), 0, _state); - while(minbciteration(&state, _state)) - { - if( state.needfg ) - { - if( ae_fp_less(-0.999999,state.x.ptr.p_double[0])&&ae_fp_less(state.x.ptr.p_double[0],0.999999) ) - { - state.f = 1/(1-state.x.ptr.p_double[0])+1/(1+state.x.ptr.p_double[0])+vc*state.x.ptr.p_double[0]; - state.g.ptr.p_double[0] = 1/ae_sqr(1-state.x.ptr.p_double[0], _state)-1/ae_sqr(1+state.x.ptr.p_double[0], _state)+vc; - } - else - { - state.f = vm; - state.g.ptr.p_double[0] = (double)(0); - } - } - } - minbcresults(&state, &x, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminbcunit.ap:822"); - ae_frame_leave(_state); - return; - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(1/ae_sqr(1-x.ptr.p_double[0], _state)-1/ae_sqr(1+x.ptr.p_double[0], _state)+vc, _state),epsg), __FILE__, __LINE__, "testminbcunit.ap:825"); - } - } - } - - /* - * Test behaviour on noisy functions. - * - * Consider following problem: - * * f(x,y) = (x+1)^2 + (y+1)^2 + 10000*MachineEpsilon*RandomReal() - * * boundary constraints x>=0, y>=0 - * * starting point (x0,y0)=(10*MachineEpsilon,1.0) - * - * Such problem contains small numerical noise. Without noise its - * solution is (xs,ys)=(0,0), which is easy to find. However, presence - * of the noise makes it hard to solve: - * * noisy f(x,y) is monotonically decreasing only when we perform - * steps orders of magnitude larger than 10000*MachineEpsilon - * * at small scales f(x,y) is non-monotonic and non-convex - * * however, our first step must be done towards - * (x1,y1) = (0,1-some_small_value), and length of such step is - * many times SMALLER than 10000*MachineEpsilon - * * second step, from (x1,y1) to (xs,ys), will be large enough to - * ignore numerical noise, so the only problem is to perform - * first step - * - * Naive implementation of BC should fail sometimes (sometimes - - * due to non-deterministic nature of noise) on such problem. However, - * our improved implementation should solve it correctly. We test - * several variations of inner stopping criteria. - */ - for(pass=1; pass<=passcount; pass++) - { - eps = 1.0E-9; - ae_vector_set_length(&x, 2, _state); - ae_vector_set_length(&bl, 2, _state); - ae_vector_set_length(&bu, 2, _state); - x.ptr.p_double[0] = 10*ae_machineepsilon; - x.ptr.p_double[1] = 1.0; - bl.ptr.p_double[0] = 0.0; - bu.ptr.p_double[0] = _state->v_posinf; - bl.ptr.p_double[1] = 0.0; - bu.ptr.p_double[1] = _state->v_posinf; - for(ckind=0; ckind<=2; ckind++) - { - minbccreate(2, &x, &state, _state); - minbcsetbc(&state, &bl, &bu, _state); - if( ckind==0 ) - { - minbcsetcond(&state, eps, (double)(0), (double)(0), 0, _state); - } - if( ckind==1 ) - { - minbcsetcond(&state, (double)(0), eps, (double)(0), 0, _state); - } - if( ckind==2 ) - { - minbcsetcond(&state, (double)(0), (double)(0), eps, 0, _state); - } - while(minbciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = ae_sqr(state.x.ptr.p_double[0]+1, _state)+ae_sqr(state.x.ptr.p_double[1]+1, _state)+10000*ae_machineepsilon*ae_randomreal(_state); - state.g.ptr.p_double[0] = 2*(state.x.ptr.p_double[0]+1); - state.g.ptr.p_double[1] = 2*(state.x.ptr.p_double[1]+1); - } - } - minbcresults(&state, &xf, &rep, _state); - if( (rep.terminationtype<=0||ae_fp_neq(xf.ptr.p_double[0],(double)(0)))||ae_fp_neq(xf.ptr.p_double[1],(double)(0)) ) - { - ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminbcunit.ap:889"); - ae_frame_leave(_state); - return; - } - } - } - - /* - * Deterministic variation of the previous problem. - * - * Consider following problem: - * * boundary constraints x>=0, y>=0 - * * starting point (x0,y0)=(10*MachineEpsilon,1.0) - * / (x+1)^2 + (y+1)^2, for (x,y)<>(x0,y0) - * * f(x,y) = | - * \ (x+1)^2 + (y+1)^2 - 0.1, for (x,y)=(x0,y0) - * - * Such problem contains deterministic numerical noise (-0.1 at - * starting point). Without noise its solution is easy to find. - * However, presence of the noise makes it hard to solve: - * * our first step must be done towards (x1,y1) = (0,1-some_small_value), - * but such step will increase function valye by approximately 0.1 - - * instead of decreasing it. - * - * Naive implementation of BC should fail on such problem. However, - * our improved implementation should solve it correctly. We test - * several variations of inner stopping criteria. - */ - for(pass=1; pass<=passcount; pass++) - { - eps = 1.0E-9; - ae_vector_set_length(&x, 2, _state); - ae_vector_set_length(&bl, 2, _state); - ae_vector_set_length(&bu, 2, _state); - x.ptr.p_double[0] = 10*ae_machineepsilon; - x.ptr.p_double[1] = 1.0; - bl.ptr.p_double[0] = 0.0; - bu.ptr.p_double[0] = _state->v_posinf; - bl.ptr.p_double[1] = 0.0; - bu.ptr.p_double[1] = _state->v_posinf; - for(ckind=0; ckind<=2; ckind++) - { - minbccreate(2, &x, &state, _state); - minbcsetbc(&state, &bl, &bu, _state); - if( ckind==0 ) - { - minbcsetcond(&state, eps, (double)(0), (double)(0), 0, _state); - } - if( ckind==1 ) - { - minbcsetcond(&state, (double)(0), eps, (double)(0), 0, _state); - } - if( ckind==2 ) - { - minbcsetcond(&state, (double)(0), (double)(0), eps, 0, _state); - } - while(minbciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = ae_sqr(state.x.ptr.p_double[0]+1, _state)+ae_sqr(state.x.ptr.p_double[1]+1, _state); - if( ae_fp_eq(state.x.ptr.p_double[0],x.ptr.p_double[0])&&ae_fp_eq(state.x.ptr.p_double[1],x.ptr.p_double[1]) ) - { - state.f = state.f-0.1; - } - state.g.ptr.p_double[0] = 2*(state.x.ptr.p_double[0]+1); - state.g.ptr.p_double[1] = 2*(state.x.ptr.p_double[1]+1); - } - } - minbcresults(&state, &xf, &rep, _state); - if( (rep.terminationtype<=0||ae_fp_neq(xf.ptr.p_double[0],(double)(0)))||ae_fp_neq(xf.ptr.p_double[1],(double)(0)) ) - { - ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminbcunit.ap:952"); - ae_frame_leave(_state); - return; - } - } - } - - /* - * Test integrity checks for NAN/INF: - * * algorithm solves optimization problem, which is normal for some time (quadratic) - * * after 5-th step we choose random component of gradient and consistently spoil - * it by NAN or INF. - * * we check that correct termination code is returned (-8) - */ - n = 100; - for(pass=1; pass<=10; pass++) - { - spoiliteration = 5; - stopiteration = 8; - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - - /* - * Gradient can be spoiled by +INF, -INF, NAN - */ - spoilvar = hqrnduniformi(&rs, n, _state); - i = hqrnduniformi(&rs, 3, _state); - spoilval = _state->v_nan; - if( i==0 ) - { - spoilval = _state->v_neginf; - } - if( i==1 ) - { - spoilval = _state->v_posinf; - } - } - else - { - - /* - * Function value can be spoiled only by NAN - * (+INF can be recognized as legitimate value during optimization) - */ - spoilvar = -1; - spoilval = _state->v_nan; - } - spdmatrixrndcond(n, 1.0E5, &fulla, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - minbccreate(n, &x0, &state, _state); - minbcsetcond(&state, 0.0, 0.0, 0.0, stopiteration, _state); - minbcsetxrep(&state, ae_true, _state); - k = -1; - while(minbciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.g.ptr.p_double[i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.f = state.f+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.g.ptr.p_double[i] = state.g.ptr.p_double[i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - if( k>=spoiliteration ) - { - if( spoilvar<0 ) - { - state.f = spoilval; - } - else - { - state.g.ptr.p_double[spoilvar] = spoilval; - } - } - continue; - } - if( state.xupdated ) - { - inc(&k, _state); - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minbcresults(&state, &x1, &rep, _state); - ae_set_error_flag(err, rep.terminationtype!=-8, __FILE__, __LINE__, "testminbcunit.ap:1037"); - } - - /* - * Check algorithm ability to handle request for termination: - * * to terminate with correct return code = 8 - * * to return point which was "current" at the moment of termination - * - * NOTE: we solve problem with "corrupted" preconditioner which makes it hard - * to converge in less than StopCallIdx iterations - */ - for(pass=1; pass<=50; pass++) - { - n = 3; - ss = (double)(100); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&xlast, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 6+ae_randomreal(_state); - } - ae_vector_set_length(&s, 3, _state); - s.ptr.p_double[0] = 0.00001; - s.ptr.p_double[1] = 0.00001; - s.ptr.p_double[2] = 10000.0; - stopcallidx = ae_randominteger(20, _state); - maxits = 25; - minbccreate(n, &x, &state, _state); - minbcsetcond(&state, (double)(0), (double)(0), (double)(0), maxits, _state); - minbcsetxrep(&state, ae_true, _state); - minbcsetprecdiag(&state, &s, _state); - callidx = 0; - terminationrequested = ae_false; - ae_v_move(&xlast.ptr.p_double[0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - while(minbciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = ss*ae_sqr(ae_exp(state.x.ptr.p_double[0], _state)-2, _state)+ae_sqr(state.x.ptr.p_double[1], _state)+ae_sqr(state.x.ptr.p_double[2]-state.x.ptr.p_double[0], _state); - state.g.ptr.p_double[0] = 2*ss*(ae_exp(state.x.ptr.p_double[0], _state)-2)*ae_exp(state.x.ptr.p_double[0], _state)+2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0])*(-1); - state.g.ptr.p_double[1] = 2*state.x.ptr.p_double[1]; - state.g.ptr.p_double[2] = 2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0]); - if( callidx==stopcallidx ) - { - minbcrequesttermination(&state, _state); - terminationrequested = ae_true; - } - inc(&callidx, _state); - continue; - } - if( state.xupdated ) - { - if( !terminationrequested ) - { - ae_v_move(&xlast.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minbcresults(&state, &x, &rep, _state); - ae_set_error_flag(err, rep.terminationtype!=8, __FILE__, __LINE__, "testminbcunit.ap:1095"); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(err, ae_fp_neq(x.ptr.p_double[i],xlast.ptr.p_double[i]), __FILE__, __LINE__, "testminbcunit.ap:1097"); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests preconditioning - -On failure sets Err to True (leaves it unchanged otherwise) -*************************************************************************/ -static void testminbcunit_testpreconditioning(ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t pass; - ae_int_t n; - ae_vector x; - ae_vector x0; - ae_int_t i; - ae_int_t k; - ae_matrix v; - ae_vector bl; - ae_vector bu; - ae_vector vd; - ae_vector d; - ae_vector units; - ae_vector s; - ae_int_t cntb1; - ae_int_t cntb2; - ae_int_t cntg1; - ae_int_t cntg2; - double epsg; - ae_vector diagh; - minbcstate state; - minbcreport rep; - ae_int_t ckind; - ae_int_t fk; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&x0, 0, sizeof(x0)); - memset(&v, 0, sizeof(v)); - memset(&bl, 0, sizeof(bl)); - memset(&bu, 0, sizeof(bu)); - memset(&vd, 0, sizeof(vd)); - memset(&d, 0, sizeof(d)); - memset(&units, 0, sizeof(units)); - memset(&s, 0, sizeof(s)); - memset(&diagh, 0, sizeof(diagh)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vd, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&units, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&diagh, 0, DT_REAL, _state, ae_true); - _minbcstate_init(&state, _state, ae_true); - _minbcreport_init(&rep, _state, ae_true); - - - /* - * Preconditioner test 1. - * - * If - * * B1 is default preconditioner with unit scale - * * G1 is diagonal preconditioner based on approximate diagonal of Hessian matrix - * * B2 is default preconditioner with non-unit scale S[i]=1/sqrt(h[i]) - * * G2 is scale-based preconditioner with non-unit scale S[i]=1/sqrt(h[i]) - * then B1 is worse than G1, B2 is worse than G2. - * "Worse" means more iterations to converge. - * - * Test problem setup: - * * f(x) = sum( ((i*i+1)*x[i])^2, i=0..N-1) - * * constraints: - * 0) absent - * 1) box - * - * N - problem size - * K - number of repeated passes (should be large enough to average out random factors) - */ - k = 100; - epsg = 1.0E-8; - for(n=10; n<=10; n++) - { - for(ckind=0; ckind<=1; ckind++) - { - fk = 1; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&units, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = (double)(0); - units.ptr.p_double[i] = (double)(1); - } - minbccreate(n, &x, &state, _state); - minbcsetcond(&state, epsg, 0.0, 0.0, 0, _state); - if( ckind==1 ) - { - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - for(i=0; i<=n-1; i++) - { - bl.ptr.p_double[i] = (double)(-1); - bu.ptr.p_double[i] = (double)(1); - } - minbcsetbc(&state, &bl, &bu, _state); - } - - /* - * Test it with default preconditioner VS. perturbed diagonal preconditioner - */ - minbcsetprecdefault(&state, _state); - minbcsetscale(&state, &units, _state); - cntb1 = 0; - for(pass=0; pass<=k-1; pass++) - { - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - minbcrestartfrom(&state, &x, _state); - while(minbciteration(&state, _state)) - { - testminbcunit_calciip2(&state, n, fk, _state); - } - minbcresults(&state, &x, &rep, _state); - cntb1 = cntb1+rep.iterationscount; - *err = *err||rep.terminationtype<=0; - } - ae_vector_set_length(&diagh, n, _state); - for(i=0; i<=n-1; i++) - { - diagh.ptr.p_double[i] = 2*ae_pow((double)(i*i+1), (double)(2*fk), _state)*(0.8+0.4*ae_randomreal(_state)); - } - minbcsetprecdiag(&state, &diagh, _state); - minbcsetscale(&state, &units, _state); - cntg1 = 0; - for(pass=0; pass<=k-1; pass++) - { - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - minbcrestartfrom(&state, &x, _state); - while(minbciteration(&state, _state)) - { - testminbcunit_calciip2(&state, n, fk, _state); - } - minbcresults(&state, &x, &rep, _state); - cntg1 = cntg1+rep.iterationscount; - *err = *err||rep.terminationtype<=0; - } - *err = *err||cntb1=0, __FILE__, __LINE__, "testminbcunit.ap:1381"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx>=0, __FILE__, __LINE__, "testminbcunit.ap:1382"); - ae_set_error_flag(wereerrors, ogrep.nonc1test0positive, __FILE__, __LINE__, "testminbcunit.ap:1383"); - ae_set_error_flag(wereerrors, ogrep.nonc1test1positive, __FILE__, __LINE__, "testminbcunit.ap:1384"); - - /* - * Test gradient checking functionality, try various - * defect types: - * * accidental zeroing of some gradient component - * * accidental addition of 1.0 to some component - * * accidental multiplication by 2.0 - * Try distorting both target and constraints. - */ - diffstep = 0.001; - n = 10; - for(skind=0; skind<=1; skind++) - { - for(defecttype=-1; defecttype<=2; defecttype++) - { - varidx = hqrnduniformi(&rs, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&s, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = ae_pow((double)(10), skind*(30*hqrnduniformr(&rs, _state)-15), _state); - x0.ptr.p_double[i] = (1.0+0.1*i)*s.ptr.p_double[i]; - j = hqrnduniformi(&rs, 3, _state); - bndl.ptr.p_double[i] = -100*s.ptr.p_double[i]; - bndu.ptr.p_double[i] = 100*s.ptr.p_double[i]; - if( j==1 ) - { - bndl.ptr.p_double[i] = x0.ptr.p_double[i]; - } - if( j==2 ) - { - bndu.ptr.p_double[i] = x0.ptr.p_double[i]; - } - } - spdmatrixrndcond(n, 1.0E3, &a, _state); - spdmatrixrndcond(n, 1.0E3, &a1, _state); - minbccreate(n, &x0, &state, _state); - minbcoptguardgradient(&state, diffstep, _state); - minbcsetcond(&state, (double)(0), (double)(0), 1.0E-9, 10, _state); - minbcsetscale(&state, &s, _state); - minbcsetbc(&state, &bndl, &bndu, _state); - while(minbciteration(&state, _state)) - { - if( state.needfg ) - { - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(wereerrors, ae_fp_less(state.x.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminbcunit.ap:1432"); - ae_set_error_flag(wereerrors, ae_fp_greater(state.x.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminbcunit.ap:1433"); - } - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.f = state.f+0.5*(state.x.ptr.p_double[i]/s.ptr.p_double[i])*v; - state.g.ptr.p_double[i] = v; - } - if( defecttype==0 ) - { - state.g.ptr.p_double[varidx] = (double)(0); - } - if( defecttype==1 ) - { - state.g.ptr.p_double[varidx] = state.g.ptr.p_double[varidx]+1; - } - if( defecttype==2 ) - { - state.g.ptr.p_double[varidx] = state.g.ptr.p_double[varidx]*2; - } - for(i=0; i<=n-1; i++) - { - state.g.ptr.p_double[i] = state.g.ptr.p_double[i]/s.ptr.p_double[i]; - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minbcresults(&state, &x1, &rep, _state); - minbcoptguardresults(&state, &ogrep, _state); - - /* - * Check that something is returned - */ - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminbcunit.ap:1466"); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1467"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Compute reference values for true and spoiled Jacobian at X0 - */ - ae_set_error_flag(wereerrors, !isfinitevector(&ogrep.badgradxbase, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1474"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&jactrue, 1, n, _state); - ae_matrix_set_length(&jacdefect, 1, n, _state); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+ogrep.badgradxbase.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - jactrue.ptr.pp_double[0][i] = v; - jacdefect.ptr.pp_double[0][i] = v; - } - if( defecttype==0 ) - { - jacdefect.ptr.pp_double[0][varidx] = (double)(0); - } - if( defecttype==1 ) - { - jacdefect.ptr.pp_double[0][varidx] = jacdefect.ptr.pp_double[0][varidx]+1; - } - if( defecttype==2 ) - { - jacdefect.ptr.pp_double[0][varidx] = jacdefect.ptr.pp_double[0][varidx]*2; - } - for(i=0; i<=n-1; i++) - { - jactrue.ptr.pp_double[0][i] = jactrue.ptr.pp_double[0][i]/s.ptr.p_double[i]; - jacdefect.ptr.pp_double[0][i] = jacdefect.ptr.pp_double[0][i]/s.ptr.p_double[i]; - } - - /* - * Check OptGuard report - */ - ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgraduser, 1, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1502"); - ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgradnum, 1, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1503"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - if( defecttype>=0 ) - { - ae_set_error_flag(wereerrors, !ogrep.badgradsuspected, __FILE__, __LINE__, "testminbcunit.ap:1508"); - ae_set_error_flag(wereerrors, ogrep.badgradfidx!=0, __FILE__, __LINE__, "testminbcunit.ap:1509"); - ae_set_error_flag(wereerrors, ogrep.badgradvidx!=varidx, __FILE__, __LINE__, "testminbcunit.ap:1510"); - } - else - { - ae_set_error_flag(wereerrors, ogrep.badgradsuspected, __FILE__, __LINE__, "testminbcunit.ap:1514"); - ae_set_error_flag(wereerrors, ogrep.badgradfidx!=-1, __FILE__, __LINE__, "testminbcunit.ap:1515"); - ae_set_error_flag(wereerrors, ogrep.badgradvidx!=-1, __FILE__, __LINE__, "testminbcunit.ap:1516"); - } - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jactrue.ptr.pp_double[0][j]-ogrep.badgradnum.ptr.pp_double[0][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testminbcunit.ap:1520"); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jacdefect.ptr.pp_double[0][j]-ogrep.badgraduser.ptr.pp_double[0][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testminbcunit.ap:1521"); - } - } - } - - /* - * A test for detection of C1 continuity violations in the target. - * - * Target function is a sum of |(x,c_i)| for i=1..N. - * No constraints is present. - * Analytic gradient is provided. - * - * OptGuard should be able to detect violations in more than - * 99.9% of runs; it means that 100 runs should have no more than 4 - * failures in all cases (even after multiple repeated tests; according - * to the binomial distribution quantiles). - * - * We select some N and perform exhaustive search for this N. - */ - passcount = 100; - maxfails = 4; - maxc1test0fails = 10; - maxc1test1fails = 10; - n = 1+hqrnduniformi(&rs, 10, _state); - failurecounter = 0; - c1test0fails = 0; - c1test1fails = 0; - avgstr0len = (double)(0); - avglng0len = (double)(0); - avgstr1len = (double)(0); - avglng1len = (double)(0); - for(pass=1; pass<=passcount; pass++) - { - - /* - * Formulate problem - */ - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - - /* - * Create and try to solve - */ - minbccreate(n, &x0, &state, _state); - minbcsetcond(&state, (double)(0), (double)(0), 1.0E-9, 50, _state); - minbcsetscale(&state, &s, _state); - minbcoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminbcunit_maxoptguardlevel, _state), _state); - while(minbciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.g.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.f = state.f+ae_fabs(v, _state); - v = (double)(ae_sign(v, _state)); - for(j=0; j<=n-1; j++) - { - state.g.ptr.p_double[j] = state.g.ptr.p_double[j]+v*a.ptr.pp_double[i][j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minbcresults(&state, &x1, &rep, _state); - minbcoptguardresults(&state, &ogrep, _state); - - /* - * Check basic properties of the solution - */ - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1602"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminbcunit.ap:1603"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check generic OptGuard report: distinguish between "hard" - * failures which result in immediate termination - * (C0 violation being reported) and "soft" ones - * (C1 violation is NOT reported) which accumulate - * until we exhaust limit. - */ - ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminbcunit.ap:1614"); - ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminbcunit.ap:1615"); - failed = ae_false; - failed = failed||optguardallclear(&ogrep, _state); - failed = failed||!ogrep.nonc1suspected; - failed = failed||ogrep.nonc1fidx!=0; - if( failed ) - { - inc(&failurecounter, _state); - } - - /* - * Check C1 continuity test #0 - */ - minbcoptguardnonc1test0results(&state, &ognonc1test0strrep, &ognonc1test0lngrep, _state); - minbcoptguardnonc1test1results(&state, &ognonc1test1strrep, &ognonc1test1lngrep, _state); - if( ogrep.nonc1test0positive ) - { - ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminbcunit.ap:1630"); - ae_set_error_flag(wereerrors, !ognonc1test0strrep.positive, __FILE__, __LINE__, "testminbcunit.ap:1631"); - ae_set_error_flag(wereerrors, !ognonc1test0lngrep.positive, __FILE__, __LINE__, "testminbcunit.ap:1632"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testminbcunit.ap:1633"); - testminbcunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0strrep, &a, n, _state); - testminbcunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0lngrep, &a, n, _state); - avgstr0len = avgstr0len+(double)ognonc1test0strrep.cnt/(double)passcount; - avglng0len = avglng0len+(double)ognonc1test0lngrep.cnt/(double)passcount; - } - else - { - ae_set_error_flag(wereerrors, ognonc1test0strrep.positive, __FILE__, __LINE__, "testminbcunit.ap:1641"); - ae_set_error_flag(wereerrors, ognonc1test0lngrep.positive, __FILE__, __LINE__, "testminbcunit.ap:1642"); - testminbcunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0strrep, &a, n, _state); - testminbcunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0lngrep, &a, n, _state); - inc(&c1test0fails, _state); - } - if( ogrep.nonc1test1positive ) - { - ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminbcunit.ap:1649"); - ae_set_error_flag(wereerrors, !ognonc1test1strrep.positive, __FILE__, __LINE__, "testminbcunit.ap:1650"); - ae_set_error_flag(wereerrors, !ognonc1test1lngrep.positive, __FILE__, __LINE__, "testminbcunit.ap:1651"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testminbcunit.ap:1652"); - testminbcunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1strrep, &a, n, _state); - testminbcunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1lngrep, &a, n, _state); - avgstr1len = avgstr1len+(double)ognonc1test1strrep.cnt/(double)passcount; - avglng1len = avglng1len+(double)ognonc1test1lngrep.cnt/(double)passcount; - } - else - { - ae_set_error_flag(wereerrors, ognonc1test1strrep.positive, __FILE__, __LINE__, "testminbcunit.ap:1660"); - ae_set_error_flag(wereerrors, ognonc1test1lngrep.positive, __FILE__, __LINE__, "testminbcunit.ap:1661"); - testminbcunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1strrep, &a, n, _state); - testminbcunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1lngrep, &a, n, _state); - inc(&c1test1fails, _state); - } - } - ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testminbcunit.ap:1668"); - ae_set_error_flag(wereerrors, c1test0fails>maxc1test0fails, __FILE__, __LINE__, "testminbcunit.ap:1669"); - ae_set_error_flag(wereerrors, c1test1fails>maxc1test1fails, __FILE__, __LINE__, "testminbcunit.ap:1670"); - ae_set_error_flag(wereerrors, ae_fp_less_eq(avglng0len,avgstr0len), __FILE__, __LINE__, "testminbcunit.ap:1671"); - ae_set_error_flag(wereerrors, ae_fp_less_eq(avglng1len,avgstr1len), __FILE__, __LINE__, "testminbcunit.ap:1672"); - - /* - * Detection of C1 continuity violations in the target under numerical differentiation: - * * target function is a sum of |(x,c_i)| for i=1..N. - * * no constraints is present. - * * analytic gradient is provided. - * - * OptGuard should always be able to detect violations in more than - * 99% of runs (note: reduced strength when compared with analytic gradient); - * it means that 100 runs should have no more than 10 failures in all cases - * (even after multiple repeated tests; according to the binomial distribution - * quantiles). - * - * We select some N and perform exhaustive search for this N. - */ - diffstep = 0.0001; - passcount = 100; - maxfails = 10; - n = 1+hqrnduniformi(&rs, 10, _state); - failurecounter = 0; - for(pass=1; pass<=passcount; pass++) - { - - /* - * Formulate problem - */ - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = 0.01*ae_pow((double)(2), 0.33*hqrndnormal(&rs, _state), _state); - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - - /* - * Create and try to solve - */ - minbccreatef(n, &x0, diffstep, &state, _state); - minbcsetcond(&state, (double)(0), (double)(0), 1.0E-9, 50, _state); - minbcoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminbcunit_maxoptguardlevel, _state), _state); - while(minbciteration(&state, _state)) - { - if( state.needf ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.f = state.f+ae_fabs(v, _state); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minbcresults(&state, &x1, &rep, _state); - minbcoptguardresults(&state, &ogrep, _state); - - /* - * Check basic properties of the solution - */ - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1738"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminbcunit.ap:1739"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check OptGuard report: distinguish between "hard" - * failures which result in immediate termination - * (C0 violation being reported) and "soft" ones - * (C1 violation is NOT reported) which accumulate - * until we exhaust limit. - */ - ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminbcunit.ap:1750"); - ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminbcunit.ap:1751"); - failed = ae_false; - failed = failed||optguardallclear(&ogrep, _state); - failed = failed||!ogrep.nonc1suspected; - failed = failed||ogrep.nonc1fidx!=0; - if( failed ) - { - inc(&failurecounter, _state); - } - } - ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testminbcunit.ap:1759"); - - /* - * Make sure than no false positives are reported for larger - * problems where numerical noise can be an issue: - * * N=100 dimensions - * * positive-definite quadratic programming problem - * * upper limit on iterations count, MaxIts=25 - * We simply test that OptGuard does not return error code. - */ - n = 100; - spdmatrixrndcond(n, 1.0E2, &a, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - x0.ptr.p_double[i] = ae_pow(2.0, hqrndnormal(&rs, _state), _state); - } - minbccreate(n, &x0, &state, _state); - minbcoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminbcunit_maxoptguardlevel, _state), _state); - minbcsetcond(&state, (double)(0), (double)(0), 1.0E-9, 25, _state); - while(minbciteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.g.ptr.p_double[i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.f = state.f+0.5*state.x.ptr.p_double[i]*a.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.g.ptr.p_double[i] = state.g.ptr.p_double[i]+a.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minbcresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1802"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminbcunit.ap:1803"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - minbcoptguardresults(&state, &ogrep, _state); - ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminbcunit.ap:1807"); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function sets random preconditioner: -* unit one, for PrecKind=0 -* diagonal-based one, for PrecKind=1 -* scale-based one, for PrecKind=2 -*************************************************************************/ -static void testminbcunit_setrandompreconditioner(minbcstate* state, - ae_int_t n, - ae_int_t preckind, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector p; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&p, 0, sizeof(p)); - ae_vector_init(&p, 0, DT_REAL, _state, ae_true); - - if( preckind==1 ) - { - ae_vector_set_length(&p, n, _state); - for(i=0; i<=n-1; i++) - { - p.ptr.p_double[i] = ae_exp(6*ae_randomreal(_state)-3, _state); - } - minbcsetprecdiag(state, &p, _state); - } - else - { - minbcsetprecdefault(state, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests report of "non-C1" test #0 for task #0 -given by matrix A. - -On failure sets error flag. -*************************************************************************/ -static void testminbcunit_testoptguardc1test0reportfortask0(ae_bool* err, - optguardnonc1test0report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double vv; - double va; - double vb; - ae_bool hasc1discontinuities; - - - if( rep->positive ) - { - - /* - * Check positive report, first checks - */ - ae_set_error_flag(err, rep->fidx!=0, __FILE__, __LINE__, "testminbcunit.ap:1858"); - ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testminbcunit.ap:1859"); - ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testminbcunit.ap:1860"); - ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testminbcunit.ap:1861"); - ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testminbcunit.ap:1862"); - ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testminbcunit.ap:1863"); - ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testminbcunit.ap:1864"); - ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testminbcunit.ap:1865"); - ae_set_error_flag(err, rep->f.cnt!=rep->cnt, __FILE__, __LINE__, "testminbcunit.ap:1866"); - ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1867"); - ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1868"); - ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testminbcunit.ap:1869"); - ae_set_error_flag(err, !isfinitevector(&rep->f, rep->cnt, _state), __FILE__, __LINE__, "testminbcunit.ap:1870"); - if( *err ) - { - return; - } - - /* - * Check consistency of X0, D, Stp and F - */ - for(k=0; k<=rep->cnt-2; k++) - { - ae_set_error_flag(err, ae_fp_greater_eq(rep->stp.ptr.p_double[k],rep->stp.ptr.p_double[k+1]), __FILE__, __LINE__, "testminbcunit.ap:1878"); - } - for(k=0; k<=rep->cnt-1; k++) - { - v = (double)(0); - for(i=0; i<=n-1; i++) - { - vv = (double)(0); - for(j=0; j<=n-1; j++) - { - vv = vv+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[k]); - } - v = v+ae_fabs(vv, _state); - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-rep->f.ptr.p_double[k], _state),1.0E-6*ae_maxreal(ae_fabs(v, _state), (double)(1), _state)), __FILE__, __LINE__, "testminbcunit.ap:1891"); - } - - /* - * Check that interval [#StpIdxA,#StpIdxB] contains at least one discontinuity - */ - hasc1discontinuities = ae_false; - for(i=0; i<=n-1; i++) - { - va = (double)(0); - vb = (double)(0); - for(j=0; j<=n-1; j++) - { - va = va+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxa]); - vb = vb+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxb]); - } - hasc1discontinuities = hasc1discontinuities||ae_sign(va, _state)!=ae_sign(vb, _state); - } - ae_set_error_flag(err, !hasc1discontinuities, __FILE__, __LINE__, "testminbcunit.ap:1909"); - } - else - { - - /* - * Check negative report: fields must be empty - */ - ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testminbcunit.ap:1916"); - ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testminbcunit.ap:1917"); - ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testminbcunit.ap:1918"); - ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testminbcunit.ap:1919"); - ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testminbcunit.ap:1920"); - ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testminbcunit.ap:1921"); - ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testminbcunit.ap:1922"); - ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testminbcunit.ap:1923"); - ae_set_error_flag(err, rep->f.cnt!=0, __FILE__, __LINE__, "testminbcunit.ap:1924"); - } -} - - -/************************************************************************* -This function tests report of "non-C1" test #1 for task #0 -given by matrix A. - -On failure sets error flag. -*************************************************************************/ -static void testminbcunit_testoptguardc1test1reportfortask0(ae_bool* err, - optguardnonc1test1report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double vv; - double va; - double vb; - ae_bool tooclose; - ae_bool hasc1discontinuities; - - - if( rep->positive ) - { - - /* - * Check positive report, first checks - */ - ae_set_error_flag(err, rep->fidx!=0, __FILE__, __LINE__, "testminbcunit.ap:1952"); - ae_set_error_flag(err, rep->vidx<0, __FILE__, __LINE__, "testminbcunit.ap:1953"); - ae_set_error_flag(err, rep->vidx>n, __FILE__, __LINE__, "testminbcunit.ap:1954"); - ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testminbcunit.ap:1955"); - ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testminbcunit.ap:1956"); - ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testminbcunit.ap:1957"); - ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testminbcunit.ap:1958"); - ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testminbcunit.ap:1959"); - ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testminbcunit.ap:1960"); - ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testminbcunit.ap:1961"); - ae_set_error_flag(err, rep->g.cnt!=rep->cnt, __FILE__, __LINE__, "testminbcunit.ap:1962"); - ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1963"); - ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1964"); - ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testminbcunit.ap:1965"); - ae_set_error_flag(err, !isfinitevector(&rep->g, rep->cnt, _state), __FILE__, __LINE__, "testminbcunit.ap:1966"); - if( *err ) - { - return; - } - - /* - * Check consistency of X0, D, Stp and G - */ - for(k=0; k<=rep->cnt-2; k++) - { - ae_set_error_flag(err, ae_fp_greater_eq(rep->stp.ptr.p_double[k],rep->stp.ptr.p_double[k+1]), __FILE__, __LINE__, "testminbcunit.ap:1974"); - } - for(k=0; k<=rep->cnt-1; k++) - { - v = (double)(0); - tooclose = ae_false; - for(i=0; i<=n-1; i++) - { - vv = (double)(0); - for(j=0; j<=n-1; j++) - { - vv = vv+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[k]); - } - v = v+ae_sign(vv, _state)*a->ptr.pp_double[i][rep->vidx]; - tooclose = tooclose||ae_fp_less(ae_fabs(vv, _state),1.0E-4); - } - if( !tooclose ) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-rep->g.ptr.p_double[k], _state),1.0E-6*ae_maxreal(ae_fabs(v, _state), (double)(1), _state)), __FILE__, __LINE__, "testminbcunit.ap:1988"); - } - } - - /* - * Check that interval [#StpIdxA,#StpIdxB] contains at least one discontinuity - */ - tooclose = ae_false; - hasc1discontinuities = ae_false; - for(i=0; i<=n-1; i++) - { - va = (double)(0); - vb = (double)(0); - for(j=0; j<=n-1; j++) - { - va = va+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxa]); - vb = vb+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxb]); - } - tooclose = (tooclose||ae_fp_less(ae_fabs(va, _state),1.0E-8))||ae_fp_less(ae_fabs(vb, _state),1.0E-8); - hasc1discontinuities = hasc1discontinuities||ae_sign(va, _state)!=ae_sign(vb, _state); - } - if( !tooclose ) - { - ae_set_error_flag(err, !hasc1discontinuities, __FILE__, __LINE__, "testminbcunit.ap:2009"); - } - } - else - { - - /* - * Check negative report: fields must be empty - */ - ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testminbcunit.ap:2016"); - ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testminbcunit.ap:2017"); - ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testminbcunit.ap:2018"); - ae_set_error_flag(err, rep->vidx!=-1, __FILE__, __LINE__, "testminbcunit.ap:2019"); - ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testminbcunit.ap:2020"); - ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testminbcunit.ap:2021"); - ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testminbcunit.ap:2022"); - ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testminbcunit.ap:2023"); - ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testminbcunit.ap:2024"); - ae_set_error_flag(err, rep->g.cnt!=0, __FILE__, __LINE__, "testminbcunit.ap:2025"); - } -} - - - -static double testminnsunit_scalingtesttol = 1.0E-6; -static ae_int_t testminnsunit_scalingtestcnt = 5; -static void testminnsunit_basictest0uc(ae_bool* errors, ae_state *_state); -static void testminnsunit_basictest1uc(ae_bool* errors, ae_state *_state); -static void testminnsunit_basictest0bc(ae_bool* errors, ae_state *_state); -static void testminnsunit_basictest1bc(ae_bool* errors, ae_state *_state); -static void testminnsunit_basictest0lc(ae_bool* errors, ae_state *_state); -static void testminnsunit_basictest1lc(ae_bool* errors, ae_state *_state); -static void testminnsunit_basictest0nlc(ae_bool* errors, ae_state *_state); -static void testminnsunit_testuc(ae_bool* primaryerrors, - ae_bool* othererrors, - ae_state *_state); -static void testminnsunit_testbc(ae_bool* primaryerrors, - ae_bool* othererrors, - ae_state *_state); -static void testminnsunit_testlc(ae_bool* primaryerrors, - ae_bool* othererrors, - ae_state *_state); -static void testminnsunit_testnlc(ae_bool* primaryerrors, - ae_bool* othererrors, - ae_state *_state); -static void testminnsunit_testother(ae_bool* othererrors, - ae_state *_state); - - - - - -ae_bool testminns(ae_bool silent, ae_state *_state) -{ - ae_bool wereerrors; - ae_bool ucerrors; - ae_bool bcerrors; - ae_bool lcerrors; - ae_bool nlcerrors; - ae_bool othererrors; - ae_bool result; - - - wereerrors = ae_false; - ucerrors = ae_false; - bcerrors = ae_false; - lcerrors = ae_false; - nlcerrors = ae_false; - othererrors = ae_false; - - /* - * Basic tests - */ - testminnsunit_basictest0nlc(&nlcerrors, _state); - testminnsunit_basictest0uc(&ucerrors, _state); - testminnsunit_basictest1uc(&ucerrors, _state); - testminnsunit_basictest0bc(&bcerrors, _state); - testminnsunit_basictest1bc(&bcerrors, _state); - testminnsunit_basictest0lc(&lcerrors, _state); - testminnsunit_basictest1lc(&lcerrors, _state); - - /* - * Special tests - */ - testminnsunit_testother(&othererrors, _state); - - /* - * Full scale tests - */ - testminnsunit_testuc(&ucerrors, &othererrors, _state); - testminnsunit_testbc(&bcerrors, &othererrors, _state); - testminnsunit_testlc(&lcerrors, &othererrors, _state); - testminnsunit_testnlc(&nlcerrors, &othererrors, _state); - - /* - * end - */ - wereerrors = (((ucerrors||bcerrors)||lcerrors)||nlcerrors)||othererrors; - if( !silent ) - { - printf("TESTING MINNS OPTIMIZATION\n"); - printf("TESTS:\n"); - printf("* UNCONSTRAINED "); - if( ucerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* BOUND CONSTRAINED "); - if( bcerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* LINEARLY CONSTRAINED "); - if( lcerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* NONLINEARLY CONSTRAINED "); - if( nlcerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* OTHER PROPERTIES "); - if( othererrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( wereerrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !wereerrors; - return result; -} - - -/************************************************************************* -Basic unconstrained test -*************************************************************************/ -static void testminnsunit_basictest0uc(ae_bool* errors, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t i; - ae_vector x0; - ae_vector x1; - ae_vector d; - minnsstate s; - minnsreport rep; - double sumits; - double sumnfev; - ae_int_t pass; - ae_int_t passcount; - - ae_frame_make(_state, &_frame_block); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&d, 0, sizeof(d)); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - _minnsstate_init(&s, _state, ae_true); - _minnsreport_init(&rep, _state, ae_true); - - n = 5; - passcount = 10; - sumits = (double)(0); - sumnfev = (double)(0); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&d, n, _state); - for(pass=1; pass<=10; pass++) - { - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - d.ptr.p_double[i] = ae_pow((double)(10), 2*ae_randomreal(_state)-1, _state); - } - minnscreate(n, &x0, &s, _state); - minnssetalgoags(&s, 0.1, 0.0, _state); - while(minnsiteration(&s, _state)) - { - if( s.needfij ) - { - s.fi.ptr.p_double[0] = 0.0; - for(i=0; i<=n-1; i++) - { - s.fi.ptr.p_double[0] = s.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(s.x.ptr.p_double[i], _state); - s.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(s.x.ptr.p_double[i], _state); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&s, &x1, &rep, _state); - ae_set_error_flag(errors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:143"); - if( *errors ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errors, !ae_isfinite(x1.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[i], _state),0.001), __FILE__, __LINE__, "testminnsunit.ap:147"); - } - sumits = sumits+(double)rep.iterationscount/(double)passcount; - sumnfev = sumnfev+(double)rep.nfev/(double)passcount; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Basic unconstrained test: nonsmooth Rosenbrock posed as unconstrained problem. - - [ ] - minimize [ 10*|x0^2-x1| + (1-x0)^2 + 100*max(sqrt(2)*x0-1,0) + 100*max(2*x1-1,0) ] - [ ] - -It's exact solution is x0=1/sqrt(2), x1=1/2 -*************************************************************************/ -static void testminnsunit_basictest1uc(ae_bool* errors, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - double v0; - double v1; - ae_vector x0; - ae_vector x1; - minnsstate s; - minnsreport rep; - - ae_frame_make(_state, &_frame_block); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - _minnsstate_init(&s, _state, ae_true); - _minnsreport_init(&rep, _state, ae_true); - - n = 2; - ae_vector_set_length(&x0, n, _state); - x0.ptr.p_double[0] = (double)(0); - x0.ptr.p_double[1] = (double)(0); - minnscreate(n, &x0, &s, _state); - minnssetalgoags(&s, 0.1, 0.0, _state); - while(minnsiteration(&s, _state)) - { - if( s.needfij ) - { - v0 = s.x.ptr.p_double[0]; - v1 = s.x.ptr.p_double[1]; - s.fi.ptr.p_double[0] = 10*ae_fabs(ae_sqr(v0, _state)-v1, _state)+ae_sqr(v0-1, _state); - s.j.ptr.pp_double[0][0] = 10*ae_sign(ae_sqr(v0, _state)-v1, _state)*2*v0+2*(v0-1); - s.j.ptr.pp_double[0][1] = (double)(10*ae_sign(ae_sqr(v0, _state)-v1, _state)*(-1)); - if( ae_fp_greater(ae_sqrt((double)(2), _state)*v0-1,0.0) ) - { - s.fi.ptr.p_double[0] = s.fi.ptr.p_double[0]+100*(ae_sqrt((double)(2), _state)*v0-1); - s.j.ptr.pp_double[0][0] = s.j.ptr.pp_double[0][0]+100*ae_sqrt((double)(2), _state); - } - if( ae_fp_greater(2*v1-1,0.0) ) - { - s.fi.ptr.p_double[0] = s.fi.ptr.p_double[0]+100*(2*v1-1); - s.j.ptr.pp_double[0][1] = s.j.ptr.pp_double[0][1]+100*2; - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&s, &x1, &rep, _state); - ae_set_error_flag(errors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:204"); - if( *errors ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(errors, !ae_isfinite(x1.ptr.p_double[0], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[0]-1/ae_sqrt((double)(2), _state), _state),0.001), __FILE__, __LINE__, "testminnsunit.ap:207"); - ae_set_error_flag(errors, !ae_isfinite(x1.ptr.p_double[1], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[1]-(double)1/(double)2, _state),0.001), __FILE__, __LINE__, "testminnsunit.ap:208"); - ae_frame_leave(_state); -} - - -/************************************************************************* -Basic box constrained test -*************************************************************************/ -static void testminnsunit_basictest0bc(ae_bool* errors, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t i; - ae_vector x0; - ae_vector x1; - ae_vector d; - ae_vector bl; - ae_vector bu; - minnsstate s; - minnsreport rep; - double sumits; - double sumnfev; - ae_int_t pass; - ae_int_t passcount; - double v0; - double v1; - - ae_frame_make(_state, &_frame_block); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&d, 0, sizeof(d)); - memset(&bl, 0, sizeof(bl)); - memset(&bu, 0, sizeof(bu)); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bu, 0, DT_REAL, _state, ae_true); - _minnsstate_init(&s, _state, ae_true); - _minnsreport_init(&rep, _state, ae_true); - - n = 5; - passcount = 10; - sumits = (double)(0); - sumnfev = (double)(0); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - ae_vector_set_length(&d, n, _state); - for(pass=1; pass<=10; pass++) - { - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - d.ptr.p_double[i] = ae_pow((double)(10), 2*ae_randomreal(_state)-1, _state); - v0 = 2*ae_randomreal(_state)-1; - v1 = 2*ae_randomreal(_state)-1; - bl.ptr.p_double[i] = ae_minreal(v0, v1, _state); - bu.ptr.p_double[i] = ae_maxreal(v0, v1, _state); - } - minnscreate(n, &x0, &s, _state); - minnssetalgoags(&s, 0.1, 0.0, _state); - minnssetbc(&s, &bl, &bu, _state); - while(minnsiteration(&s, _state)) - { - if( s.needfij ) - { - s.fi.ptr.p_double[0] = 0.0; - for(i=0; i<=n-1; i++) - { - s.fi.ptr.p_double[0] = s.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(s.x.ptr.p_double[i], _state); - s.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(s.x.ptr.p_double[i], _state); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&s, &x1, &rep, _state); - ae_set_error_flag(errors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:263"); - if( *errors ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errors, !ae_isfinite(x1.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-boundval(0.0, bl.ptr.p_double[i], bu.ptr.p_double[i], _state), _state),0.001), __FILE__, __LINE__, "testminnsunit.ap:267"); - } - sumits = sumits+(double)rep.iterationscount/(double)passcount; - sumnfev = sumnfev+(double)rep.nfev/(double)passcount; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Basic constrained test: nonsmooth Rosenbrock posed as box constrained problem. - - [ ] - minimize [ 10*|x0^2-x1| + (1-x0)^2 ] - [ ] - - s.t. x0<=1/sqrt(2), x1<=0.5 - -It's exact solution is x0=1/sqrt(2), x1=1/2 -*************************************************************************/ -static void testminnsunit_basictest1bc(ae_bool* errors, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - double v0; - double v1; - ae_vector x0; - ae_vector x1; - ae_vector bndl; - ae_vector bndu; - minnsstate s; - minnsreport rep; - - ae_frame_make(_state, &_frame_block); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - _minnsstate_init(&s, _state, ae_true); - _minnsreport_init(&rep, _state, ae_true); - - n = 2; - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - x0.ptr.p_double[0] = (double)(0); - x0.ptr.p_double[1] = (double)(0); - bndl.ptr.p_double[0] = _state->v_neginf; - bndl.ptr.p_double[1] = _state->v_neginf; - bndu.ptr.p_double[0] = 1/ae_sqrt((double)(2), _state); - bndu.ptr.p_double[1] = (double)1/(double)2; - minnscreate(n, &x0, &s, _state); - minnssetbc(&s, &bndl, &bndu, _state); - minnssetalgoags(&s, 0.1, 0.0, _state); - while(minnsiteration(&s, _state)) - { - if( s.needfij ) - { - v0 = s.x.ptr.p_double[0]; - v1 = s.x.ptr.p_double[1]; - s.fi.ptr.p_double[0] = 10*ae_fabs(ae_sqr(v0, _state)-v1, _state)+ae_sqr(v0-1, _state); - s.j.ptr.pp_double[0][0] = 10*ae_sign(ae_sqr(v0, _state)-v1, _state)*2*v0+2*(v0-1); - s.j.ptr.pp_double[0][1] = (double)(10*ae_sign(ae_sqr(v0, _state)-v1, _state)*(-1)); - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&s, &x1, &rep, _state); - ae_set_error_flag(errors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:323"); - if( *errors ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(errors, !ae_isfinite(x1.ptr.p_double[0], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[0]-1/ae_sqrt((double)(2), _state), _state),0.001), __FILE__, __LINE__, "testminnsunit.ap:326"); - ae_set_error_flag(errors, !ae_isfinite(x1.ptr.p_double[1], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[1]-(double)1/(double)2, _state),0.001), __FILE__, __LINE__, "testminnsunit.ap:327"); - ae_frame_leave(_state); -} - - -/************************************************************************* -Basic linearly constrained test -*************************************************************************/ -static void testminnsunit_basictest0lc(ae_bool* errors, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_vector x0; - ae_vector x1; - ae_matrix c; - ae_vector ct; - double d; - minnsstate s; - minnsreport rep; - double sumits; - double sumnfev; - ae_int_t pass; - ae_int_t passcount; - ae_int_t nc; - - ae_frame_make(_state, &_frame_block); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&c, 0, sizeof(c)); - memset(&ct, 0, sizeof(ct)); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - _minnsstate_init(&s, _state, ae_true); - _minnsreport_init(&rep, _state, ae_true); - - d = -10.0; - n = 5; - passcount = 10; - sumits = (double)(0); - sumnfev = (double)(0); - ae_vector_set_length(&x0, n, _state); - ae_matrix_set_length(&c, 2*n, n+1, _state); - ae_vector_set_length(&ct, 2*n, _state); - for(pass=1; pass<=10; pass++) - { - nc = 0; - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - if( ae_fp_less(ae_randomreal(_state),0.5) ) - { - for(j=0; j<=n; j++) - { - c.ptr.pp_double[nc][j] = 0.0; - } - c.ptr.pp_double[nc][i] = 1.0+ae_randomreal(_state); - ct.ptr.p_int[nc] = 0; - inc(&nc, _state); - } - else - { - for(j=0; j<=n; j++) - { - c.ptr.pp_double[nc+0][j] = 0.0; - c.ptr.pp_double[nc+1][j] = 0.0; - } - c.ptr.pp_double[nc+0][i] = 1.0+ae_randomreal(_state); - c.ptr.pp_double[nc+1][i] = 1.0+ae_randomreal(_state); - ct.ptr.p_int[nc+0] = 1; - ct.ptr.p_int[nc+1] = -1; - nc = nc+2; - } - } - minnscreate(n, &x0, &s, _state); - minnssetalgoags(&s, 0.1, 0.0, _state); - minnssetlc(&s, &c, &ct, nc, _state); - while(minnsiteration(&s, _state)) - { - if( s.needfij ) - { - s.fi.ptr.p_double[0] = 0.0; - for(i=0; i<=n-1; i++) - { - s.fi.ptr.p_double[0] = d*ae_sqr(s.x.ptr.p_double[i], _state); - s.j.ptr.pp_double[0][i] = d*2*s.x.ptr.p_double[i]; - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&s, &x1, &rep, _state); - ae_set_error_flag(errors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:404"); - if( *errors ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errors, !ae_isfinite(x1.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[i], _state),0.001), __FILE__, __LINE__, "testminnsunit.ap:408"); - } - sumits = sumits+(double)rep.iterationscount/(double)passcount; - sumnfev = sumnfev+(double)rep.nfev/(double)passcount; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Basic constrained test: nonsmooth Rosenbrock posed as linearly constrained problem. - - [ ] - minimize [ 10*|x0^2-x1| + (1-x0)^2 ] - [ ] - - s.t. x0<=1/sqrt(2), x1<=0.5 - -It's exact solution is x0=1/sqrt(2), x1=1/2 -*************************************************************************/ -static void testminnsunit_basictest1lc(ae_bool* errors, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - double v0; - double v1; - ae_vector x0; - ae_vector x1; - ae_matrix c; - ae_vector ct; - minnsstate s; - minnsreport rep; - - ae_frame_make(_state, &_frame_block); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&c, 0, sizeof(c)); - memset(&ct, 0, sizeof(ct)); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - _minnsstate_init(&s, _state, ae_true); - _minnsreport_init(&rep, _state, ae_true); - - n = 2; - ae_vector_set_length(&x0, n, _state); - ae_matrix_set_length(&c, 2, n+1, _state); - ae_vector_set_length(&ct, 2, _state); - x0.ptr.p_double[0] = (double)(0); - x0.ptr.p_double[1] = (double)(0); - c.ptr.pp_double[0][0] = 1.0; - c.ptr.pp_double[0][1] = 0.0; - c.ptr.pp_double[0][2] = 1/ae_sqrt((double)(2), _state); - c.ptr.pp_double[1][0] = 0.0; - c.ptr.pp_double[1][1] = 1.0; - c.ptr.pp_double[1][2] = (double)1/(double)2; - ct.ptr.p_int[0] = -1; - ct.ptr.p_int[1] = -1; - minnscreate(n, &x0, &s, _state); - minnssetlc(&s, &c, &ct, 2, _state); - minnssetalgoags(&s, 0.1, 0.0, _state); - while(minnsiteration(&s, _state)) - { - if( s.needfij ) - { - v0 = s.x.ptr.p_double[0]; - v1 = s.x.ptr.p_double[1]; - s.fi.ptr.p_double[0] = 10*ae_fabs(ae_sqr(v0, _state)-v1, _state)+ae_sqr(v0-1, _state); - s.j.ptr.pp_double[0][0] = 10*ae_sign(ae_sqr(v0, _state)-v1, _state)*2*v0+2*(v0-1); - s.j.ptr.pp_double[0][1] = (double)(10*ae_sign(ae_sqr(v0, _state)-v1, _state)*(-1)); - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&s, &x1, &rep, _state); - ae_set_error_flag(errors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:470"); - if( *errors ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(errors, !ae_isfinite(x1.ptr.p_double[0], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[0]-1/ae_sqrt((double)(2), _state), _state),0.001), __FILE__, __LINE__, "testminnsunit.ap:473"); - ae_set_error_flag(errors, !ae_isfinite(x1.ptr.p_double[1], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[1]-(double)1/(double)2, _state),0.001), __FILE__, __LINE__, "testminnsunit.ap:474"); - ae_frame_leave(_state); -} - - -/************************************************************************* -Basic nonlinearly constrained test -*************************************************************************/ -static void testminnsunit_basictest0nlc(ae_bool* errors, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_vector x0; - ae_vector x1; - ae_matrix ec; - ae_matrix ic; - ae_int_t nec; - ae_int_t nic; - double d; - minnsstate s; - minnsreport rep; - double sumits; - double sumnfev; - ae_int_t pass; - ae_int_t passcount; - - ae_frame_make(_state, &_frame_block); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&ec, 0, sizeof(ec)); - memset(&ic, 0, sizeof(ic)); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ec, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ic, 0, 0, DT_REAL, _state, ae_true); - _minnsstate_init(&s, _state, ae_true); - _minnsreport_init(&rep, _state, ae_true); - - d = -10.0; - n = 5; - passcount = 10; - sumits = (double)(0); - sumnfev = (double)(0); - ae_vector_set_length(&x0, n, _state); - ae_matrix_set_length(&ec, 2*n, n+1, _state); - ae_matrix_set_length(&ic, 2*n, n+1, _state); - for(pass=1; pass<=10; pass++) - { - nec = 0; - nic = 0; - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - if( ae_fp_less(ae_randomreal(_state),0.5) ) - { - for(j=0; j<=n; j++) - { - ec.ptr.pp_double[nec][j] = 0.0; - } - ec.ptr.pp_double[nec][i] = 1.0+ae_randomreal(_state); - inc(&nec, _state); - } - else - { - for(j=0; j<=n; j++) - { - ic.ptr.pp_double[nic+0][j] = 0.0; - ic.ptr.pp_double[nic+1][j] = 0.0; - } - ic.ptr.pp_double[nic+0][i] = 1.0+ae_randomreal(_state); - ic.ptr.pp_double[nic+1][i] = -1.0-ae_randomreal(_state); - nic = nic+2; - } - } - minnscreate(n, &x0, &s, _state); - minnssetalgoags(&s, 0.1, 100.0, _state); - minnssetnlc(&s, nec, nic, _state); - while(minnsiteration(&s, _state)) - { - if( s.needfij ) - { - s.fi.ptr.p_double[0] = 0.0; - for(j=0; j<=n-1; j++) - { - s.fi.ptr.p_double[0] = d*ae_sqr(s.x.ptr.p_double[j], _state); - s.j.ptr.pp_double[0][j] = d*2*s.x.ptr.p_double[j]; - } - for(i=0; i<=nec-1; i++) - { - s.fi.ptr.p_double[1+i] = -ec.ptr.pp_double[i][n]; - for(j=0; j<=n-1; j++) - { - s.fi.ptr.p_double[1+i] = s.fi.ptr.p_double[1+i]+s.x.ptr.p_double[j]*ec.ptr.pp_double[i][j]; - s.j.ptr.pp_double[1+i][j] = ec.ptr.pp_double[i][j]; - } - } - for(i=0; i<=nic-1; i++) - { - s.fi.ptr.p_double[1+nec+i] = -ic.ptr.pp_double[i][n]; - for(j=0; j<=n-1; j++) - { - s.fi.ptr.p_double[1+nec+i] = s.fi.ptr.p_double[1+nec+i]+s.x.ptr.p_double[j]*ic.ptr.pp_double[i][j]; - s.j.ptr.pp_double[1+nec+i][j] = ic.ptr.pp_double[i][j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&s, &x1, &rep, _state); - ae_set_error_flag(errors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:567"); - if( *errors ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errors, !ae_isfinite(x1.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[i], _state),0.001), __FILE__, __LINE__, "testminnsunit.ap:571"); - } - sumits = sumits+(double)rep.iterationscount/(double)passcount; - sumnfev = sumnfev+(double)rep.nfev/(double)passcount; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Unconstrained test -*************************************************************************/ -static void testminnsunit_testuc(ae_bool* primaryerrors, - ae_bool* othererrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t i; - ae_vector x0; - ae_vector x0s; - ae_vector x1; - ae_vector x1s; - ae_vector d; - ae_vector xc; - ae_vector s; - ae_vector xrfirst; - ae_vector xrlast; - minnsstate state; - minnsreport rep; - double v; - ae_int_t pass; - ae_bool requirexrep; - double epsrad; - ae_bool werexreports; - double repferr; - double xtol; - - ae_frame_make(_state, &_frame_block); - memset(&x0, 0, sizeof(x0)); - memset(&x0s, 0, sizeof(x0s)); - memset(&x1, 0, sizeof(x1)); - memset(&x1s, 0, sizeof(x1s)); - memset(&d, 0, sizeof(d)); - memset(&xc, 0, sizeof(xc)); - memset(&s, 0, sizeof(s)); - memset(&xrfirst, 0, sizeof(xrfirst)); - memset(&xrlast, 0, sizeof(xrlast)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xrfirst, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xrlast, 0, DT_REAL, _state, ae_true); - _minnsstate_init(&state, _state, ae_true); - _minnsreport_init(&rep, _state, ae_true); - - for(pass=1; pass<=10; pass++) - { - for(n=1; n<=5; n++) - { - - /* - * First test: - * * test that problem is successfully solved - * * test that X-reports are performed correctly - present - * when requested, return first and last points correctly, - * not present by default, function value is reported - * correctly. - * * we use non-unit scale, randomly chosen one, which results - * in badly conditioned problems (to check robustness) - */ - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xc, n, _state); - ae_vector_set_length(&d, n, _state); - ae_vector_set_length(&s, n, _state); - ae_vector_set_length(&xrfirst, n, _state); - ae_vector_set_length(&xrlast, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 10*(2*ae_randomreal(_state)-1); - xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - d.ptr.p_double[i] = ae_pow((double)(10), 2*(2*ae_randomreal(_state)-1), _state); - s.ptr.p_double[i] = ae_pow((double)(10), 2*(2*ae_randomreal(_state)-1), _state); - } - requirexrep = ae_fp_greater(ae_randomreal(_state),0.5); - epsrad = 0.01*ae_pow((double)(10), -2*ae_randomreal(_state), _state); - xtol = 15.0*epsrad; - minnscreate(n, &x0, &state, _state); - minnssetalgoags(&state, 0.1, 0.0, _state); - minnssetcond(&state, epsrad, 0, _state); - minnssetscale(&state, &s, _state); - if( requirexrep ) - { - minnssetxrep(&state, ae_true, _state); - } - werexreports = ae_false; - repferr = 0.0; - while(minnsiteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = 0.0; - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - } - continue; - } - if( state.xupdated ) - { - if( !werexreports ) - { - ae_v_move(&xrfirst.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - } - ae_v_move(&xrlast.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - werexreports = ae_true; - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - } - repferr = ae_maxreal(repferr, ae_fabs(v-state.f, _state), _state); - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&state, &x1, &rep, _state); - ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:668"); - ae_set_error_flag(othererrors, werexreports&&!requirexrep, __FILE__, __LINE__, "testminnsunit.ap:669"); - ae_set_error_flag(othererrors, requirexrep&&!werexreports, __FILE__, __LINE__, "testminnsunit.ap:670"); - ae_set_error_flag(othererrors, ae_fp_greater(repferr,10000*ae_machineepsilon), __FILE__, __LINE__, "testminnsunit.ap:671"); - if( *primaryerrors||(*othererrors) ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(primaryerrors, !ae_isfinite(x1.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-xc.ptr.p_double[i], _state)/s.ptr.p_double[i],xtol), __FILE__, __LINE__, "testminnsunit.ap:676"); - if( requirexrep ) - { - ae_set_error_flag(othererrors, !ae_isfinite(xrfirst.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x0.ptr.p_double[i]-xrfirst.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testminnsunit.ap:679"); - ae_set_error_flag(othererrors, !ae_isfinite(xrlast.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-xrlast.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testminnsunit.ap:680"); - } - } - - /* - * Test numerical differentiation: - * * test that problem is successfully solved - * * test that correct function value is reported - */ - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xc, n, _state); - ae_vector_set_length(&d, n, _state); - ae_vector_set_length(&s, n, _state); - ae_vector_set_length(&xrlast, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 10*(2*ae_randomreal(_state)-1); - xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - d.ptr.p_double[i] = ae_pow((double)(10), 2*(2*ae_randomreal(_state)-1), _state); - s.ptr.p_double[i] = ae_pow((double)(10), 2*(2*ae_randomreal(_state)-1), _state); - } - epsrad = 0.01*ae_pow((double)(10), -2*ae_randomreal(_state), _state); - xtol = 15.0*epsrad; - minnscreatef(n, &x0, epsrad/100, &state, _state); - minnssetalgoags(&state, 0.1, 0.0, _state); - minnssetcond(&state, epsrad, 0, _state); - minnssetscale(&state, &s, _state); - minnssetxrep(&state, ae_true, _state); - repferr = 0.0; - while(minnsiteration(&state, _state)) - { - if( state.needfi ) - { - state.fi.ptr.p_double[0] = 0.0; - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - } - continue; - } - if( state.xupdated ) - { - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - } - repferr = ae_maxreal(repferr, ae_fabs(v-state.f, _state), _state); - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&state, &x1, &rep, _state); - ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:731"); - ae_set_error_flag(othererrors, ae_fp_greater(repferr,10000*ae_machineepsilon), __FILE__, __LINE__, "testminnsunit.ap:732"); - if( *primaryerrors||(*othererrors) ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(primaryerrors, !ae_isfinite(x1.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-xc.ptr.p_double[i], _state)/s.ptr.p_double[i],xtol), __FILE__, __LINE__, "testminnsunit.ap:736"); - } - - /* - * Test scaling: we perform several steps on unit-scale problem, - * then we perform same amount of steps on re-scaled problem, - * starting from same point (but scaled according to chosen scale). - * - * Correctly written optimizer should perform essentially same steps - * (up to scale) on both problems. At least, it holds within first - * several steps, before rounding errors start to accumulate. - * - * NOTE: we also check that correctly scaled points are reported. - * And, as side effect, we check MinNSRestartFrom(). - * - * NOTE: we use moderate scale and diagonal coefficients in order - * to have well-conditioned system. We test correctness of - * formulae here, not robustness of algorithm. - */ - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xc, n, _state); - ae_vector_set_length(&x0s, n, _state); - ae_vector_set_length(&d, n, _state); - ae_vector_set_length(&s, n, _state); - ae_vector_set_length(&xrlast, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = ae_pow((double)(10), 2*ae_randomreal(_state)-1, _state); - d.ptr.p_double[i] = ae_pow((double)(10), 2*ae_randomreal(_state)-1, _state); - x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x0s.ptr.p_double[i] = x0.ptr.p_double[i]*s.ptr.p_double[i]; - } - minnscreate(n, &x0, &state, _state); - minnssetalgoags(&state, 0.1, 0.0, _state); - minnssetcond(&state, 0.0, testminnsunit_scalingtestcnt, _state); - minnssetxrep(&state, ae_false, _state); - while(minnsiteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = 0.0; - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&state, &x1, &rep, _state); - ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:788"); - if( *primaryerrors||(*othererrors) ) - { - ae_frame_leave(_state); - return; - } - minnssetscale(&state, &s, _state); - minnssetxrep(&state, ae_true, _state); - minnsrestartfrom(&state, &x0s, _state); - werexreports = ae_false; - while(minnsiteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = 0.0; - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]/s.ptr.p_double[i]-xc.ptr.p_double[i], _state); - state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(state.x.ptr.p_double[i]/s.ptr.p_double[i]-xc.ptr.p_double[i], _state)/s.ptr.p_double[i]; - } - continue; - } - if( state.xupdated ) - { - ae_v_move(&xrlast.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - werexreports = ae_true; - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&state, &x1s, &rep, _state); - ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:818"); - if( *primaryerrors||(*othererrors) ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(primaryerrors, (!ae_isfinite(x1.ptr.p_double[i], _state)||!ae_isfinite(x1s.ptr.p_double[i], _state))||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-x1s.ptr.p_double[i]/s.ptr.p_double[i], _state),1.0E-4), __FILE__, __LINE__, "testminnsunit.ap:823"); - ae_set_error_flag(othererrors, !ae_isfinite(xrlast.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1s.ptr.p_double[i]-xrlast.ptr.p_double[i], _state),testminnsunit_scalingtesttol), __FILE__, __LINE__, "testminnsunit.ap:827"); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Box constrained test -*************************************************************************/ -static void testminnsunit_testbc(ae_bool* primaryerrors, - ae_bool* othererrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_vector x0; - ae_vector x0s; - ae_vector x1; - ae_vector x1s; - ae_vector b; - ae_vector d; - ae_vector xc; - ae_vector s; - ae_vector bndl; - ae_vector bndu; - ae_vector scaledbndl; - ae_vector scaledbndu; - ae_vector xrfirst; - ae_vector xrlast; - ae_matrix a; - minnsstate state; - minnsreport rep; - double v; - double v0; - double v1; - ae_int_t pass; - ae_int_t passcount; - ae_bool requirexrep; - double epsrad; - ae_bool werexreports; - double repferr; - double xtol; - ae_int_t maxn; - double conda; - double gnorm; - - ae_frame_make(_state, &_frame_block); - memset(&x0, 0, sizeof(x0)); - memset(&x0s, 0, sizeof(x0s)); - memset(&x1, 0, sizeof(x1)); - memset(&x1s, 0, sizeof(x1s)); - memset(&b, 0, sizeof(b)); - memset(&d, 0, sizeof(d)); - memset(&xc, 0, sizeof(xc)); - memset(&s, 0, sizeof(s)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&scaledbndl, 0, sizeof(scaledbndl)); - memset(&scaledbndu, 0, sizeof(scaledbndu)); - memset(&xrfirst, 0, sizeof(xrfirst)); - memset(&xrlast, 0, sizeof(xrlast)); - memset(&a, 0, sizeof(a)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&scaledbndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&scaledbndu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xrfirst, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xrlast, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - _minnsstate_init(&state, _state, ae_true); - _minnsreport_init(&rep, _state, ae_true); - - passcount = 10; - maxn = 5; - - /* - * First test: - * * sparse function - * * test that problem is successfully solved - * * non-unit scale is used, which results in badly conditioned problem - * * check that all iterates are feasible (box-constrained) - */ - for(pass=1; pass<=passcount; pass++) - { - for(n=1; n<=maxn; n++) - { - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&xc, n, _state); - ae_vector_set_length(&d, n, _state); - ae_vector_set_length(&s, n, _state); - ae_vector_set_length(&xrfirst, n, _state); - ae_vector_set_length(&xrlast, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 10*(2*ae_randomreal(_state)-1); - xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - d.ptr.p_double[i] = ae_pow((double)(10), 2*(2*ae_randomreal(_state)-1), _state); - s.ptr.p_double[i] = ae_pow((double)(10), 2*(2*ae_randomreal(_state)-1), _state); - bndl.ptr.p_double[i] = _state->v_neginf; - bndu.ptr.p_double[i] = _state->v_posinf; - k = ae_randominteger(5, _state); - if( k==1 ) - { - bndl.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - if( k==2 ) - { - bndu.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - if( k==3 ) - { - v0 = 2*ae_randomreal(_state)-1; - v1 = 2*ae_randomreal(_state)-1; - bndl.ptr.p_double[i] = ae_minreal(v0, v1, _state); - bndu.ptr.p_double[i] = ae_maxreal(v0, v1, _state); - } - if( k==4 ) - { - bndl.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - bndu.ptr.p_double[i] = bndl.ptr.p_double[i]; - } - } - requirexrep = ae_fp_greater(ae_randomreal(_state),0.5); - epsrad = 0.01*ae_pow((double)(10), -2*ae_randomreal(_state), _state); - xtol = 15.0*epsrad; - minnscreate(n, &x0, &state, _state); - minnssetalgoags(&state, 0.1, 0.0, _state); - minnssetcond(&state, epsrad, 0, _state); - minnssetbc(&state, &bndl, &bndu, _state); - minnssetscale(&state, &s, _state); - if( requirexrep ) - { - minnssetxrep(&state, ae_true, _state); - } - werexreports = ae_false; - repferr = 0.0; - while(minnsiteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = 0.0; - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - } - continue; - } - if( state.xupdated ) - { - if( !werexreports ) - { - ae_v_move(&xrfirst.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - } - ae_v_move(&xrlast.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - werexreports = ae_true; - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - } - repferr = ae_maxreal(repferr, ae_fabs(v-state.f, _state), _state); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(primaryerrors, ae_fp_less(state.x.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminnsunit.ap:944"); - ae_set_error_flag(primaryerrors, ae_fp_greater(state.x.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminnsunit.ap:945"); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&state, &x1, &rep, _state); - ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:953"); - ae_set_error_flag(othererrors, werexreports&&!requirexrep, __FILE__, __LINE__, "testminnsunit.ap:954"); - ae_set_error_flag(othererrors, requirexrep&&!werexreports, __FILE__, __LINE__, "testminnsunit.ap:955"); - ae_set_error_flag(othererrors, ae_fp_greater(repferr,10000*ae_machineepsilon), __FILE__, __LINE__, "testminnsunit.ap:956"); - if( *primaryerrors||(*othererrors) ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(primaryerrors, !ae_isfinite(x1.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-boundval(xc.ptr.p_double[i], bndl.ptr.p_double[i], bndu.ptr.p_double[i], _state), _state)/s.ptr.p_double[i],xtol), __FILE__, __LINE__, "testminnsunit.ap:961"); - ae_set_error_flag(primaryerrors, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminnsunit.ap:962"); - ae_set_error_flag(primaryerrors, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminnsunit.ap:963"); - if( requirexrep ) - { - ae_set_error_flag(othererrors, !ae_isfinite(xrfirst.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(boundval(x0.ptr.p_double[i], bndl.ptr.p_double[i], bndu.ptr.p_double[i], _state)-xrfirst.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testminnsunit.ap:966"); - ae_set_error_flag(othererrors, !ae_isfinite(xrlast.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-xrlast.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testminnsunit.ap:967"); - } - } - } - } - - /* - * A bit harder test: - * * dense quadratic function (smooth), may be prone to different - * rounding-related issues - * * non-negativity box constraints - * * unit scale is used - * * extreme stopping criteria (EpsX=1.0E-12) - * * single pass for each problem size - * * check that constrained gradient at solution is small - */ - conda = 1.0E3; - epsrad = 1.0E-12; - for(n=1; n<=10; n++) - { - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&b, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 1.0; - b.ptr.p_double[i] = ae_randomreal(_state)-0.5; - bndl.ptr.p_double[i] = 0.0; - bndu.ptr.p_double[i] = _state->v_posinf; - } - spdmatrixrndcond(n, conda, &a, _state); - minnscreate(n, &x0, &state, _state); - minnssetalgoags(&state, 0.1, 0.0, _state); - minnssetcond(&state, epsrad, 0, _state); - minnssetbc(&state, &bndl, &bndu, _state); - while(minnsiteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = 0.0; - for(i=0; i<=n-1; i++) - { - state.j.ptr.pp_double[0][i] = 0.0; - } - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*a.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - for(i=0; i<=n-1; i++) - { - state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+a.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&state, &x1, &rep, _state); - ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1030"); - if( *primaryerrors||(*othererrors) ) - { - ae_frame_leave(_state); - return; - } - gnorm = 0.0; - for(i=0; i<=n-1; i++) - { - v = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - v = v+a.ptr.pp_double[i][j]*x1.ptr.p_double[j]; - } - if( ae_fp_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i])&&ae_fp_greater(v,(double)(0)) ) - { - v = (double)(0); - } - if( ae_fp_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i])&&ae_fp_less(v,(double)(0)) ) - { - v = (double)(0); - } - gnorm = gnorm+ae_sqr(v, _state); - ae_set_error_flag(primaryerrors, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminnsunit.ap:1045"); - ae_set_error_flag(primaryerrors, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminnsunit.ap:1046"); - } - gnorm = ae_sqrt(gnorm, _state); - ae_set_error_flag(primaryerrors, ae_fp_greater(gnorm,1.0E-5), __FILE__, __LINE__, "testminnsunit.ap:1049"); - } - - /* - * Test on HIGHLY nonconvex bound constrained problem. - * Algorithm should be able to stop. - * - * NOTE: because algorithm can be attracted to saddle points, - * x[i] may be -1, +1 or approximately zero. - */ - for(pass=1; pass<=passcount; pass++) - { - for(n=1; n<=maxn; n++) - { - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = ae_randomreal(_state)-0.5; - bndl.ptr.p_double[i] = -1.0; - bndu.ptr.p_double[i] = 1.0; - } - epsrad = 0.0001; - xtol = 15.0*epsrad; - minnscreate(n, &x0, &state, _state); - minnssetalgoags(&state, 0.1, 0.0, _state); - minnssetcond(&state, epsrad, 0, _state); - minnssetbc(&state, &bndl, &bndu, _state); - v = -1000.0; - while(minnsiteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = 0.0; - for(i=0; i<=n-1; i++) - { - v0 = ae_fabs(state.x.ptr.p_double[i], _state); - v1 = (double)(ae_sign(state.x.ptr.p_double[i], _state)); - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+v*(v0+v0*v0); - state.j.ptr.pp_double[0][i] = v*(v1+2*v0*v1); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&state, &x1, &rep, _state); - ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1095"); - for(i=0; i<=n-1; i++) - { - v = ae_fabs(x1.ptr.p_double[i], _state); - ae_set_error_flag(primaryerrors, !ae_isfinite(x1.ptr.p_double[i], _state), __FILE__, __LINE__, "testminnsunit.ap:1099"); - ae_set_error_flag(primaryerrors, ae_fp_neq(v,1.0)&&ae_fp_greater(v,xtol), __FILE__, __LINE__, "testminnsunit.ap:1100"); - } - } - } - - /* - * Test numerical differentiation: - * * test that problem is successfully solved - * * test that correct function value is reported - * * test that all iterates are within bound-constrained area - */ - for(pass=1; pass<=passcount; pass++) - { - for(n=1; n<=maxn; n++) - { - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xc, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&d, n, _state); - ae_vector_set_length(&s, n, _state); - ae_vector_set_length(&xrlast, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 10*(2*ae_randomreal(_state)-1); - xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - d.ptr.p_double[i] = ae_pow((double)(10), 2*(2*ae_randomreal(_state)-1), _state); - s.ptr.p_double[i] = ae_pow((double)(10), 2*(2*ae_randomreal(_state)-1), _state); - bndl.ptr.p_double[i] = _state->v_neginf; - bndu.ptr.p_double[i] = _state->v_posinf; - k = ae_randominteger(5, _state); - if( k==1 ) - { - bndl.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - if( k==2 ) - { - bndu.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - if( k==3 ) - { - v0 = 2*ae_randomreal(_state)-1; - v1 = 2*ae_randomreal(_state)-1; - bndl.ptr.p_double[i] = ae_minreal(v0, v1, _state); - bndu.ptr.p_double[i] = ae_maxreal(v0, v1, _state); - } - if( k==4 ) - { - bndl.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - bndu.ptr.p_double[i] = bndl.ptr.p_double[i]; - } - } - epsrad = 0.01*ae_pow((double)(10), -2*ae_randomreal(_state), _state); - xtol = 15.0*epsrad; - minnscreatef(n, &x0, epsrad/100, &state, _state); - minnssetalgoags(&state, 0.1, 0.0, _state); - minnssetcond(&state, epsrad, 0, _state); - minnssetscale(&state, &s, _state); - minnssetbc(&state, &bndl, &bndu, _state); - minnssetxrep(&state, ae_true, _state); - repferr = 0.0; - while(minnsiteration(&state, _state)) - { - if( state.needfi ) - { - state.fi.ptr.p_double[0] = 0.0; - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - ae_set_error_flag(primaryerrors, ae_fp_less(state.x.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminnsunit.ap:1164"); - ae_set_error_flag(primaryerrors, ae_fp_greater(state.x.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminnsunit.ap:1165"); - } - continue; - } - if( state.xupdated ) - { - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - ae_set_error_flag(primaryerrors, ae_fp_less(state.x.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminnsunit.ap:1176"); - ae_set_error_flag(primaryerrors, ae_fp_greater(state.x.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminnsunit.ap:1177"); - } - repferr = ae_maxreal(repferr, ae_fabs(v-state.f, _state), _state); - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&state, &x1, &rep, _state); - ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1186"); - ae_set_error_flag(othererrors, ae_fp_greater(repferr,10000*ae_machineepsilon), __FILE__, __LINE__, "testminnsunit.ap:1187"); - if( *primaryerrors||(*othererrors) ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(primaryerrors, !ae_isfinite(x1.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-boundval(xc.ptr.p_double[i], bndl.ptr.p_double[i], bndu.ptr.p_double[i], _state), _state)/s.ptr.p_double[i],xtol), __FILE__, __LINE__, "testminnsunit.ap:1191"); - } - } - } - - /* - * Test scaling: we perform several steps on unit-scale problem, - * then we perform same amount of steps on re-scaled problem, - * starting from same point (but scaled according to chosen scale). - * - * Correctly written optimizer should perform essentially same steps - * (up to scale) on both problems. At least, it holds within first - * several steps, before rounding errors start to accumulate. - * - * NOTE: we also check that correctly scaled points are reported. - * And, as side effect, we check MinNSRestartFrom(). - * - * NOTE: we use very low scale and diagonal coefficients in order - * to have well-conditioned system. We test correctness of - * formulae here, not robustness of algorithm. - */ - for(pass=1; pass<=passcount; pass++) - { - for(n=1; n<=maxn; n++) - { - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xc, n, _state); - ae_vector_set_length(&x0s, n, _state); - ae_vector_set_length(&d, n, _state); - ae_vector_set_length(&s, n, _state); - ae_vector_set_length(&xrlast, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - ae_vector_set_length(&scaledbndl, n, _state); - ae_vector_set_length(&scaledbndu, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = ae_pow((double)(10), ae_randomreal(_state)-0.5, _state); - d.ptr.p_double[i] = ae_pow((double)(10), ae_randomreal(_state)-0.5, _state); - x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x0s.ptr.p_double[i] = x0.ptr.p_double[i]*s.ptr.p_double[i]; - bndl.ptr.p_double[i] = _state->v_neginf; - bndu.ptr.p_double[i] = _state->v_posinf; - k = ae_randominteger(5, _state); - if( k==1 ) - { - bndl.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - if( k==2 ) - { - bndu.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - if( k==3 ) - { - v0 = 2*ae_randomreal(_state)-1; - v1 = 2*ae_randomreal(_state)-1; - bndl.ptr.p_double[i] = ae_minreal(v0, v1, _state); - bndu.ptr.p_double[i] = ae_maxreal(v0, v1, _state); - } - if( k==4 ) - { - bndl.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - bndu.ptr.p_double[i] = bndl.ptr.p_double[i]; - } - scaledbndl.ptr.p_double[i] = bndl.ptr.p_double[i]*s.ptr.p_double[i]; - scaledbndu.ptr.p_double[i] = bndu.ptr.p_double[i]*s.ptr.p_double[i]; - } - minnscreate(n, &x0, &state, _state); - minnssetalgoags(&state, 0.01, 0.0, _state); - minnssetcond(&state, 0.0, testminnsunit_scalingtestcnt, _state); - minnssetbc(&state, &bndl, &bndu, _state); - minnssetxrep(&state, ae_false, _state); - while(minnsiteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = 0.0; - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&state, &x1, &rep, _state); - ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1272"); - if( *primaryerrors||(*othererrors) ) - { - ae_frame_leave(_state); - return; - } - minnssetscale(&state, &s, _state); - minnssetbc(&state, &scaledbndl, &scaledbndu, _state); - minnsrestartfrom(&state, &x0s, _state); - while(minnsiteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = 0.0; - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]/s.ptr.p_double[i]-xc.ptr.p_double[i], _state); - state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(state.x.ptr.p_double[i]/s.ptr.p_double[i]-xc.ptr.p_double[i], _state)/s.ptr.p_double[i]; - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&state, &x1s, &rep, _state); - ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1293"); - if( *primaryerrors||(*othererrors) ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(primaryerrors, (!ae_isfinite(x1.ptr.p_double[i], _state)||!ae_isfinite(x1s.ptr.p_double[i], _state))||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-x1s.ptr.p_double[i]/s.ptr.p_double[i], _state),testminnsunit_scalingtesttol), __FILE__, __LINE__, "testminnsunit.ap:1297"); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Linearly constrained test -*************************************************************************/ -static void testminnsunit_testlc(ae_bool* primaryerrors, - ae_bool* othererrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t nc; - ae_vector x0; - ae_vector x0s; - ae_vector x1; - ae_vector x2; - ae_vector x1s; - ae_vector d; - ae_vector xc; - ae_vector s; - ae_vector bndl; - ae_vector bndu; - ae_matrix c; - ae_matrix scaledc; - ae_vector ct; - ae_vector scaledbndl; - ae_vector scaledbndu; - ae_vector xrfirst; - ae_vector xrlast; - minnsstate state; - minnsreport rep; - double v; - double v0; - double v1; - double vv; - double flast0; - double flast1; - ae_int_t pass; - double epsrad; - double repferr; - double xtol; - double ftol; - double rho; - - ae_frame_make(_state, &_frame_block); - memset(&x0, 0, sizeof(x0)); - memset(&x0s, 0, sizeof(x0s)); - memset(&x1, 0, sizeof(x1)); - memset(&x2, 0, sizeof(x2)); - memset(&x1s, 0, sizeof(x1s)); - memset(&d, 0, sizeof(d)); - memset(&xc, 0, sizeof(xc)); - memset(&s, 0, sizeof(s)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&c, 0, sizeof(c)); - memset(&scaledc, 0, sizeof(scaledc)); - memset(&ct, 0, sizeof(ct)); - memset(&scaledbndl, 0, sizeof(scaledbndl)); - memset(&scaledbndu, 0, sizeof(scaledbndu)); - memset(&xrfirst, 0, sizeof(xrfirst)); - memset(&xrlast, 0, sizeof(xrlast)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&scaledc, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - ae_vector_init(&scaledbndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&scaledbndu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xrfirst, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xrlast, 0, DT_REAL, _state, ae_true); - _minnsstate_init(&state, _state, ae_true); - _minnsreport_init(&rep, _state, ae_true); - - for(pass=1; pass<=10; pass++) - { - for(n=1; n<=5; n++) - { - - /* - * First test: - * * smooth problem - * * subject to random linear constraints - * * with non-unit scale - * - * We: - * * compare function value at constrained solution with function - * value for penalized unconstrained problem. We do not compare - * actual X-values returned, because they are highly unstable - - * function values at minimum show better stability. - * * check that correct function values are reported - */ - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xc, n, _state); - ae_vector_set_length(&d, n, _state); - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 10*(2*ae_randomreal(_state)-1); - xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - d.ptr.p_double[i] = 1+ae_randomreal(_state); - s.ptr.p_double[i] = 1+ae_randomreal(_state); - } - nc = ae_randominteger((n+1)/2, _state); - if( nc>0 ) - { - ae_matrix_set_length(&c, nc, n+1, _state); - ae_vector_set_length(&ct, nc, _state); - for(i=0; i<=nc-1; i++) - { - ct.ptr.p_int[i] = ae_randominteger(3, _state)-1; - for(j=0; j<=n; j++) - { - c.ptr.pp_double[i][j] = ae_randomreal(_state)-0.5; - } - } - } - epsrad = 0.00001; - ftol = 0.01; - minnscreate(n, &x0, &state, _state); - minnssetalgoags(&state, 0.1, 0.0, _state); - minnssetcond(&state, epsrad, 0, _state); - minnssetscale(&state, &s, _state); - minnssetxrep(&state, ae_true, _state); - minnssetlc(&state, &c, &ct, nc, _state); - repferr = 0.0; - flast0 = _state->v_nan; - while(minnsiteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = 0.0; - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_sqr(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*(2*(state.x.ptr.p_double[i]-xc.ptr.p_double[i])); - } - continue; - } - if( state.xupdated ) - { - flast0 = 0.0; - for(i=0; i<=n-1; i++) - { - flast0 = flast0+d.ptr.p_double[i]*ae_sqr(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - } - repferr = ae_maxreal(repferr, ae_fabs(flast0-state.f, _state), _state); - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&state, &x1, &rep, _state); - ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1402"); - ae_set_error_flag(primaryerrors, !ae_isfinite(flast0, _state), __FILE__, __LINE__, "testminnsunit.ap:1403"); - ae_set_error_flag(othererrors, ae_fp_greater(repferr,10000*ae_machineepsilon), __FILE__, __LINE__, "testminnsunit.ap:1404"); - if( *primaryerrors||(*othererrors) ) - { - ae_frame_leave(_state); - return; - } - minnssetlc(&state, &c, &ct, 0, _state); - minnsrestartfrom(&state, &x0, _state); - rho = 1000.0; - repferr = 0.0; - flast1 = _state->v_nan; - while(minnsiteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = 0.0; - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_sqr(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*(2*(state.x.ptr.p_double[i]-xc.ptr.p_double[i])); - } - for(i=0; i<=nc-1; i++) - { - v = ae_v_dotproduct(&state.x.ptr.p_double[0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - v = v-c.ptr.pp_double[i][n]; - vv = 0.0; - if( ct.ptr.p_int[i]<0 ) - { - vv = (double)(ae_sign(ae_maxreal(v, 0.0, _state), _state)); - v = ae_maxreal(v, 0.0, _state); - } - if( ct.ptr.p_int[i]==0 ) - { - vv = (double)(ae_sign(v, _state)); - v = ae_fabs(v, _state); - } - if( ct.ptr.p_int[i]>0 ) - { - vv = (double)(-ae_sign(ae_maxreal(-v, 0.0, _state), _state)); - v = ae_maxreal(-v, 0.0, _state); - } - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+rho*v; - for(j=0; j<=n-1; j++) - { - state.j.ptr.pp_double[0][j] = state.j.ptr.pp_double[0][j]+rho*vv*c.ptr.pp_double[i][j]; - } - } - continue; - } - if( state.xupdated ) - { - flast1 = 0.0; - for(i=0; i<=n-1; i++) - { - flast1 = flast1+d.ptr.p_double[i]*ae_sqr(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&state, &x2, &rep, _state); - ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1462"); - ae_set_error_flag(primaryerrors, !ae_isfinite(flast1, _state), __FILE__, __LINE__, "testminnsunit.ap:1463"); - if( *primaryerrors||(*othererrors) ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(primaryerrors, ae_fp_greater(ae_fabs(flast0-flast1, _state),ftol), __FILE__, __LINE__, "testminnsunit.ap:1466"); - - /* - * Test on HIGHLY nonconvex linearly constrained problem. - * Algorithm should be able to stop at the bounds. - */ - ae_vector_set_length(&x0, n, _state); - ae_matrix_set_length(&c, 2*n, n+1, _state); - ae_vector_set_length(&ct, 2*n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = ae_randomreal(_state)-0.5; - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[2*i+0][j] = 0.0; - c.ptr.pp_double[2*i+1][j] = 0.0; - } - c.ptr.pp_double[2*i+0][i] = 1.0; - c.ptr.pp_double[2*i+0][n] = -1.0; - ct.ptr.p_int[2*i+0] = 1; - c.ptr.pp_double[2*i+1][i] = 1.0; - c.ptr.pp_double[2*i+1][n] = 1.0; - ct.ptr.p_int[2*i+1] = -1; - } - epsrad = 0.0001; - xtol = 15.0*epsrad; - minnscreate(n, &x0, &state, _state); - minnssetalgoags(&state, 0.1, 0.0, _state); - minnssetcond(&state, epsrad, 0, _state); - minnssetlc(&state, &c, &ct, 2*n, _state); - v = -1000.0; - while(minnsiteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = 0.0; - for(i=0; i<=n-1; i++) - { - v0 = ae_fabs(state.x.ptr.p_double[i], _state); - v1 = (double)(ae_sign(state.x.ptr.p_double[i], _state)); - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+v*(v0+v0*v0); - state.j.ptr.pp_double[0][i] = v*(v1+2*v0*v1); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&state, &x1, &rep, _state); - ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1516"); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(primaryerrors, !ae_isfinite(x1.ptr.p_double[i], _state), __FILE__, __LINE__, "testminnsunit.ap:1519"); - ae_set_error_flag(primaryerrors, (ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-1, _state),xtol)&&ae_fp_greater(ae_fabs(x1.ptr.p_double[i], _state),xtol))&&ae_fp_greater(ae_fabs(x1.ptr.p_double[i]+1, _state),xtol), __FILE__, __LINE__, "testminnsunit.ap:1520"); - } - - /* - * Test scaling: we perform several steps on unit-scale problem, - * then we perform same amount of steps on re-scaled problem, - * starting from same point (but scaled according to chosen scale). - * - * Correctly written optimizer should perform essentially same steps - * (up to scale) on both problems. At least, it holds within first - * several steps, before rounding errors start to accumulate. - * - * NOTE: we also check that correctly scaled points are reported. - * And, as side effect, we check MinNSRestartFrom(). - * - * NOTE: we use moderate scale and diagonal coefficients in order - * to have well-conditioned system. We test correctness of - * formulae here, not robustness of algorithm. - */ - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xc, n, _state); - ae_vector_set_length(&x0s, n, _state); - ae_vector_set_length(&d, n, _state); - ae_vector_set_length(&s, n, _state); - ae_vector_set_length(&xrlast, n, _state); - ae_matrix_set_length(&c, 2*n, n+1, _state); - ae_matrix_set_length(&scaledc, 2*n, n+1, _state); - ae_vector_set_length(&ct, 2*n, _state); - for(i=0; i<=2*n-1; i++) - { - ct.ptr.p_int[i] = 0; - for(j=0; j<=n; j++) - { - c.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = ae_pow((double)(10), 2*ae_randomreal(_state)-1, _state); - d.ptr.p_double[i] = ae_pow((double)(10), 2*ae_randomreal(_state)-1, _state); - x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x0s.ptr.p_double[i] = x0.ptr.p_double[i]*s.ptr.p_double[i]; - k = ae_randominteger(5, _state); - if( k==1 ) - { - c.ptr.pp_double[2*i+0][i] = 1.0; - c.ptr.pp_double[2*i+0][n] = 2*ae_randomreal(_state)-1; - ct.ptr.p_int[2*i+0] = 1; - } - if( k==2 ) - { - c.ptr.pp_double[2*i+0][i] = 1.0; - c.ptr.pp_double[2*i+0][n] = 2*ae_randomreal(_state)-1; - ct.ptr.p_int[2*i+0] = -1; - } - if( k==3 ) - { - v0 = 2*ae_randomreal(_state)-1; - v1 = 2*ae_randomreal(_state)-1; - c.ptr.pp_double[2*i+0][i] = 1.0; - c.ptr.pp_double[2*i+0][n] = ae_minreal(v0, v1, _state); - c.ptr.pp_double[2*i+1][i] = 1.0; - c.ptr.pp_double[2*i+1][n] = ae_maxreal(v0, v1, _state); - ct.ptr.p_int[2*i+0] = 1; - ct.ptr.p_int[2*i+1] = -1; - } - if( k==4 ) - { - c.ptr.pp_double[2*i+0][i] = 1.0; - c.ptr.pp_double[2*i+0][n] = 2*ae_randomreal(_state)-1; - ct.ptr.p_int[2*i+0] = 0; - } - } - for(i=0; i<=2*n-1; i++) - { - for(j=0; j<=n-1; j++) - { - scaledc.ptr.pp_double[i][j] = c.ptr.pp_double[i][j]/s.ptr.p_double[j]; - } - scaledc.ptr.pp_double[i][n] = c.ptr.pp_double[i][n]; - } - minnscreate(n, &x0, &state, _state); - minnssetalgoags(&state, 0.1, 0.0, _state); - minnssetcond(&state, 0.0, testminnsunit_scalingtestcnt, _state); - minnssetlc(&state, &c, &ct, 2*n, _state); - minnssetxrep(&state, ae_false, _state); - while(minnsiteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = 0.0; - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&state, &x1, &rep, _state); - ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1622"); - if( *primaryerrors||(*othererrors) ) - { - ae_frame_leave(_state); - return; - } - minnssetscale(&state, &s, _state); - minnssetlc(&state, &scaledc, &ct, 2*n, _state); - minnsrestartfrom(&state, &x0s, _state); - while(minnsiteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = 0.0; - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]/s.ptr.p_double[i]-xc.ptr.p_double[i], _state); - state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(state.x.ptr.p_double[i]/s.ptr.p_double[i]-xc.ptr.p_double[i], _state)/s.ptr.p_double[i]; - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&state, &x1s, &rep, _state); - ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1643"); - if( *primaryerrors||(*othererrors) ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(primaryerrors, (!ae_isfinite(x1.ptr.p_double[i], _state)||!ae_isfinite(x1s.ptr.p_double[i], _state))||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-x1s.ptr.p_double[i]/s.ptr.p_double[i], _state),testminnsunit_scalingtesttol), __FILE__, __LINE__, "testminnsunit.ap:1647"); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Nonlinearly constrained test -*************************************************************************/ -static void testminnsunit_testnlc(ae_bool* primaryerrors, - ae_bool* othererrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t nc; - ae_int_t nec; - ae_vector x0; - ae_vector x0s; - ae_vector x1; - ae_vector x2; - ae_vector x1s; - ae_vector d; - ae_vector xc; - ae_vector s; - ae_vector bndl; - ae_vector bndu; - ae_vector b; - ae_vector r; - ae_matrix c; - ae_matrix scaledc; - ae_vector ct; - ae_vector scaledbndl; - ae_vector scaledbndu; - ae_vector xrfirst; - ae_vector xrlast; - minnsstate state; - minnsreport rep; - double v; - ae_int_t pass; - ae_int_t passcount; - double epsrad; - double xtol; - double rho; - ae_int_t maxn; - double diffstep; - - ae_frame_make(_state, &_frame_block); - memset(&x0, 0, sizeof(x0)); - memset(&x0s, 0, sizeof(x0s)); - memset(&x1, 0, sizeof(x1)); - memset(&x2, 0, sizeof(x2)); - memset(&x1s, 0, sizeof(x1s)); - memset(&d, 0, sizeof(d)); - memset(&xc, 0, sizeof(xc)); - memset(&s, 0, sizeof(s)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&b, 0, sizeof(b)); - memset(&r, 0, sizeof(r)); - memset(&c, 0, sizeof(c)); - memset(&scaledc, 0, sizeof(scaledc)); - memset(&ct, 0, sizeof(ct)); - memset(&scaledbndl, 0, sizeof(scaledbndl)); - memset(&scaledbndu, 0, sizeof(scaledbndu)); - memset(&xrfirst, 0, sizeof(xrfirst)); - memset(&xrlast, 0, sizeof(xrlast)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&r, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&scaledc, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - ae_vector_init(&scaledbndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&scaledbndu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xrfirst, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xrlast, 0, DT_REAL, _state, ae_true); - _minnsstate_init(&state, _state, ae_true); - _minnsreport_init(&rep, _state, ae_true); - - passcount = 10; - maxn = 5; - rho = 100.0; - - /* - * First test: - * * simple problem - * * subject to random nonlinear constraints of form r[i]*x[i] OPERATION 0.0, - * where OPERATION is <= or = - * * with non-unit scale - * - * We: - * * compare numerical solution with analytic one, which can be - * easily calculated - */ - for(pass=1; pass<=passcount; pass++) - { - for(n=1; n<=maxn; n++) - { - for(nc=1; nc<=n; nc++) - { - for(nec=0; nec<=nc; nec++) - { - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xc, n, _state); - ae_vector_set_length(&d, n, _state); - ae_vector_set_length(&r, n, _state); - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - d.ptr.p_double[i] = ae_pow((double)(10), ae_randomreal(_state)-0.5, _state); - s.ptr.p_double[i] = ae_pow((double)(10), ae_randomreal(_state)-0.5, _state); - r.ptr.p_double[i] = (2*ae_randominteger(2, _state)-1)*(0.1+ae_randomreal(_state)); - } - epsrad = 0.001; - xtol = 0.01; - minnscreate(n, &x0, &state, _state); - minnssetalgoags(&state, 0.1, rho, _state); - minnssetcond(&state, epsrad, 0, _state); - minnssetscale(&state, &s, _state); - minnssetnlc(&state, nec, nc-nec, _state); - while(minnsiteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = 0.0; - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state); - } - for(i=1; i<=nc; i++) - { - state.fi.ptr.p_double[i] = state.x.ptr.p_double[i-1]*r.ptr.p_double[i-1]; - for(j=0; j<=n-1; j++) - { - state.j.ptr.pp_double[i][j] = 0.0; - } - state.j.ptr.pp_double[i][i-1] = r.ptr.p_double[i-1]; - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minnsresults(&state, &x1, &rep, _state); - ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1743"); - if( *primaryerrors||(*othererrors) ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - v = xc.ptr.p_double[i]; - if( i=nec&&i=nec&&i=0.999999 - * - * where c is either 1.0 or 1.0E+6, M is either 1.0E8, 1.0E20 or +INF - * (we try different combinations) - */ - for(ckind=0; ckind<=1; ckind++) - { - for(mkind=0; mkind<=2; mkind++) - { - - /* - * Choose c and M - */ - vc = 1.0; - vm = 1.0E+8; - if( ckind==1 ) - { - vc = 1.0E+6; - } - if( mkind==1 ) - { - vm = 1.0E+20; - } - if( mkind==2 ) - { - vm = _state->v_posinf; - } - - /* - * Create optimizer, solve optimization problem - */ - epsg = 1.0E-6*vc; - ae_vector_set_length(&x, 1, _state); - x.ptr.p_double[0] = 0.0; - mincgcreate(1, &x, &state, _state); - mincgsetcond(&state, epsg, (double)(0), (double)(0), 0, _state); - mincgsetcgtype(&state, cgtype, _state); - while(mincgiteration(&state, _state)) - { - if( state.needfg ) - { - if( ae_fp_less(-0.999999,state.x.ptr.p_double[0])&&ae_fp_less(state.x.ptr.p_double[0],0.999999) ) - { - state.f = 1/(1-state.x.ptr.p_double[0])+1/(1+state.x.ptr.p_double[0])+vc*state.x.ptr.p_double[0]; - state.g.ptr.p_double[0] = 1/ae_sqr(1-state.x.ptr.p_double[0], _state)-1/ae_sqr(1+state.x.ptr.p_double[0], _state)+vc; - } - else - { - state.f = vm; - } - } - } - mincgresults(&state, &x, &rep, _state); - if( rep.terminationtype<=0 ) - { - *err = ae_true; - ae_frame_leave(_state); - return; - } - *err = *err||ae_fp_greater(ae_fabs(1/ae_sqr(1-x.ptr.p_double[0], _state)-1/ae_sqr(1+x.ptr.p_double[0], _state)+vc, _state),epsg); - } - } - } - - /* - * Test integrity checks for NAN/INF: - * * algorithm solves optimization problem, which is normal for some time (quadratic) - * * after 5-th step we choose random component of gradient and consistently spoil - * it by NAN or INF. - * * we check that correct termination code is returned (-8) - */ - n = 100; - for(pass=1; pass<=10; pass++) - { - spoiliteration = 5; - stopiteration = 8; - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - - /* - * Gradient can be spoiled by +INF, -INF, NAN - */ - spoilvar = hqrnduniformi(&rs, n, _state); - i = hqrnduniformi(&rs, 3, _state); - spoilval = _state->v_nan; - if( i==0 ) - { - spoilval = _state->v_neginf; - } - if( i==1 ) - { - spoilval = _state->v_posinf; - } - } - else - { - - /* - * Function value can be spoiled only by NAN - * (+INF can be recognized as legitimate value during optimization) - */ - spoilvar = -1; - spoilval = _state->v_nan; - } - spdmatrixrndcond(n, 1.0E5, &fulla, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - mincgcreate(n, &x0, &state, _state); - mincgsetcond(&state, 0.0, 0.0, 0.0, stopiteration, _state); - mincgsetxrep(&state, ae_true, _state); - k = -1; - while(mincgiteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.g.ptr.p_double[i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.f = state.f+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.g.ptr.p_double[i] = state.g.ptr.p_double[i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - if( k>=spoiliteration ) - { - if( spoilvar<0 ) - { - state.f = spoilval; - } - else - { - state.g.ptr.p_double[spoilvar] = spoilval; - } - } - continue; - } - if( state.xupdated ) - { - inc(&k, _state); - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - mincgresults(&state, &x1, &rep, _state); - ae_set_error_flag(err, rep.terminationtype!=-8, __FILE__, __LINE__, "testmincgunit.ap:1151"); - } - - /* - * Check algorithm ability to handle request for termination: - * * to terminate with correct return code = 8 - * * to return point which was "current" at the moment of termination - */ - for(pass=1; pass<=50; pass++) - { - n = 3; - ss = (double)(100); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&xlast, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 6+ae_randomreal(_state); - } - stopcallidx = ae_randominteger(20, _state); - maxits = 25; - mincgcreate(n, &x, &state, _state); - mincgsetcond(&state, (double)(0), (double)(0), (double)(0), maxits, _state); - mincgsetxrep(&state, ae_true, _state); - callidx = 0; - terminationrequested = ae_false; - ae_v_move(&xlast.ptr.p_double[0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - while(mincgiteration(&state, _state)) - { - if( state.needfg ) - { - state.f = ss*ae_sqr(ae_exp(state.x.ptr.p_double[0], _state)-2, _state)+ae_sqr(state.x.ptr.p_double[1], _state)+ae_sqr(state.x.ptr.p_double[2]-state.x.ptr.p_double[0], _state); - state.g.ptr.p_double[0] = 2*ss*(ae_exp(state.x.ptr.p_double[0], _state)-2)*ae_exp(state.x.ptr.p_double[0], _state)+2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0])*(-1); - state.g.ptr.p_double[1] = 2*state.x.ptr.p_double[1]; - state.g.ptr.p_double[2] = 2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0]); - if( callidx==stopcallidx ) - { - mincgrequesttermination(&state, _state); - terminationrequested = ae_true; - } - inc(&callidx, _state); - continue; - } - if( state.xupdated ) - { - if( !terminationrequested ) - { - ae_v_move(&xlast.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - mincgresults(&state, &x, &rep, _state); - ae_set_error_flag(err, rep.terminationtype!=8, __FILE__, __LINE__, "testmincgunit.ap:1201"); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(err, ae_fp_neq(x.ptr.p_double[i],xlast.ptr.p_double[i]), __FILE__, __LINE__, "testmincgunit.ap:1203"); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Calculate test function #2 - -Simple variation of #1, much more nonlinear, which makes unlikely premature -convergence of algorithm . -*************************************************************************/ -static void testmincgunit_testfunc2(mincgstate* state, ae_state *_state) -{ - - - if( ae_fp_less(state->x.ptr.p_double[0],(double)(100)) ) - { - if( state->needf||state->needfg ) - { - state->f = ae_sqr(ae_exp(state->x.ptr.p_double[0], _state)-2, _state)+ae_sqr(ae_sqr(state->x.ptr.p_double[1], _state), _state)+ae_sqr(state->x.ptr.p_double[2]-state->x.ptr.p_double[0], _state); - } - if( state->needfg ) - { - state->g.ptr.p_double[0] = 2*(ae_exp(state->x.ptr.p_double[0], _state)-2)*ae_exp(state->x.ptr.p_double[0], _state)+2*(state->x.ptr.p_double[0]-state->x.ptr.p_double[2]); - state->g.ptr.p_double[1] = 4*state->x.ptr.p_double[1]*ae_sqr(state->x.ptr.p_double[1], _state); - state->g.ptr.p_double[2] = 2*(state->x.ptr.p_double[2]-state->x.ptr.p_double[0]); - } - } - else - { - if( state->needf||state->needfg ) - { - state->f = ae_sqrt(ae_maxrealnumber, _state); - } - if( state->needfg ) - { - state->g.ptr.p_double[0] = ae_sqrt(ae_maxrealnumber, _state); - state->g.ptr.p_double[1] = (double)(0); - state->g.ptr.p_double[2] = (double)(0); - } - } -} - - -/************************************************************************* -Calculate test function #3 - -Simple variation of #1, much more nonlinear, with non-zero value at minimum. -It achieve two goals: -* makes unlikely premature convergence of algorithm . -* solves some issues with EpsF stopping condition which arise when - F(minimum) is zero - -*************************************************************************/ -static void testmincgunit_testfunc3(mincgstate* state, ae_state *_state) -{ - double s; - - - s = 0.001; - if( ae_fp_less(state->x.ptr.p_double[0],(double)(100)) ) - { - if( state->needf||state->needfg ) - { - state->f = ae_sqr(ae_exp(state->x.ptr.p_double[0], _state)-2, _state)+ae_sqr(ae_sqr(state->x.ptr.p_double[1], _state)+s, _state)+ae_sqr(state->x.ptr.p_double[2]-state->x.ptr.p_double[0], _state); - } - if( state->needfg ) - { - state->g.ptr.p_double[0] = 2*(ae_exp(state->x.ptr.p_double[0], _state)-2)*ae_exp(state->x.ptr.p_double[0], _state)+2*(state->x.ptr.p_double[0]-state->x.ptr.p_double[2]); - state->g.ptr.p_double[1] = 2*(ae_sqr(state->x.ptr.p_double[1], _state)+s)*2*state->x.ptr.p_double[1]; - state->g.ptr.p_double[2] = 2*(state->x.ptr.p_double[2]-state->x.ptr.p_double[0]); - } - } - else - { - if( state->needf||state->needfg ) - { - state->f = ae_sqrt(ae_maxrealnumber, _state); - } - if( state->needfg ) - { - state->g.ptr.p_double[0] = ae_sqrt(ae_maxrealnumber, _state); - state->g.ptr.p_double[1] = (double)(0); - state->g.ptr.p_double[2] = (double)(0); - } - } -} - - -/************************************************************************* -Calculate test function IIP2 - -f(x) = sum( ((i*i+1)*x[i])^2, i=0..N-1) - -It has high condition number which makes fast convergence unlikely without -good preconditioner. - -*************************************************************************/ -static void testmincgunit_calciip2(mincgstate* state, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - - - if( state->needf||state->needfg ) - { - state->f = (double)(0); - } - for(i=0; i<=n-1; i++) - { - if( state->needf||state->needfg ) - { - state->f = state->f+ae_sqr((double)(i*i+1), _state)*ae_sqr(state->x.ptr.p_double[i], _state); - } - if( state->needfg ) - { - state->g.ptr.p_double[i] = ae_sqr((double)(i*i+1), _state)*2*state->x.ptr.p_double[i]; - } - } -} - - -/************************************************************************* -Calculate test function f(x) = 0.5*(x-x0)'*A*(x-x0), A = D+V'*Vd*V -*************************************************************************/ -static void testmincgunit_calclowrank(mincgstate* state, - ae_int_t n, - ae_int_t vcnt, - /* Real */ ae_vector* d, - /* Real */ ae_matrix* v, - /* Real */ ae_vector* vd, - /* Real */ ae_vector* x0, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double dx; - double t; - double t2; - - - state->f = (double)(0); - for(i=0; i<=n-1; i++) - { - state->g.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - dx = state->x.ptr.p_double[i]-x0->ptr.p_double[i]; - state->f = state->f+0.5*dx*d->ptr.p_double[i]*dx; - state->g.ptr.p_double[i] = state->g.ptr.p_double[i]+d->ptr.p_double[i]*dx; - } - for(i=0; i<=vcnt-1; i++) - { - t = (double)(0); - for(j=0; j<=n-1; j++) - { - t = t+v->ptr.pp_double[i][j]*(state->x.ptr.p_double[j]-x0->ptr.p_double[j]); - } - state->f = state->f+0.5*t*vd->ptr.p_double[i]*t; - t2 = t*vd->ptr.p_double[i]; - ae_v_addd(&state->g.ptr.p_double[0], 1, &v->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), t2); - } -} - - -/************************************************************************* -This function tests preconditioning - -On failure sets Err to True (leaves it unchanged otherwise) -*************************************************************************/ -static void testmincgunit_testpreconditioning(ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t pass; - ae_int_t n; - ae_vector x; - ae_vector x0; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t vs; - ae_matrix v; - ae_vector vd; - ae_vector d; - ae_vector s; - ae_int_t cntb1; - ae_int_t cntg1; - ae_int_t cntb2; - ae_int_t cntg2; - ae_vector diagh; - mincgstate state; - mincgreport rep; - ae_int_t cgtype; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&x0, 0, sizeof(x0)); - memset(&v, 0, sizeof(v)); - memset(&vd, 0, sizeof(vd)); - memset(&d, 0, sizeof(d)); - memset(&s, 0, sizeof(s)); - memset(&diagh, 0, sizeof(diagh)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vd, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&diagh, 0, DT_REAL, _state, ae_true); - _mincgstate_init(&state, _state, ae_true); - _mincgreport_init(&rep, _state, ae_true); - - k = 50; - for(cgtype=-1; cgtype<=1; cgtype++) - { - - /* - * Preconditioner test 1. - * - * If - * * B1 is default preconditioner - * * G1 is diagonal precomditioner based on approximate diagonal of Hessian matrix - * then "bad" preconditioner is worse than "good" one. - * "Worse" means more iterations to converge. - * - * - * We test it using f(x) = sum( ((i*i+1)*x[i])^2, i=0..N-1). - * - * N - problem size - * K - number of repeated passes (should be large enough to average out random factors) - */ - for(n=10; n<=15; n++) - { - ae_vector_set_length(&x, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = (double)(0); - } - mincgcreate(n, &x, &state, _state); - mincgsetcgtype(&state, cgtype, _state); - - /* - * Test it with default preconditioner - */ - mincgsetprecdefault(&state, _state); - cntb1 = 0; - for(pass=0; pass<=k-1; pass++) - { - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - mincgrestartfrom(&state, &x, _state); - while(mincgiteration(&state, _state)) - { - testmincgunit_calciip2(&state, n, _state); - } - mincgresults(&state, &x, &rep, _state); - cntb1 = cntb1+rep.iterationscount; - *err = *err||rep.terminationtype<=0; - } - - /* - * Test it with perturbed diagonal preconditioner - */ - ae_vector_set_length(&diagh, n, _state); - for(i=0; i<=n-1; i++) - { - diagh.ptr.p_double[i] = 2*ae_sqr((double)(i*i+1), _state)*(0.8+0.4*ae_randomreal(_state)); - } - mincgsetprecdiag(&state, &diagh, _state); - cntg1 = 0; - for(pass=0; pass<=k-1; pass++) - { - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - mincgrestartfrom(&state, &x, _state); - while(mincgiteration(&state, _state)) - { - testmincgunit_calciip2(&state, n, _state); - } - mincgresults(&state, &x, &rep, _state); - cntg1 = cntg1+rep.iterationscount; - *err = *err||rep.terminationtype<=0; - } - - /* - * Compare - */ - *err = *err||cntb10 ) - { - ae_matrix_set_length(&v, vs, n, _state); - ae_vector_set_length(&vd, vs, _state); - for(i=0; i<=vs-1; i++) - { - for(j=0; j<=n-1; j++) - { - v.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - vd.ptr.p_double[i] = ae_exp(2*ae_randomreal(_state), _state); - } - } - mincgcreate(n, &x, &state, _state); - mincgsetcgtype(&state, cgtype, _state); - - /* - * Test it with default preconditioner - */ - mincgsetprecdefault(&state, _state); - cntb1 = 0; - for(pass=0; pass<=k-1; pass++) - { - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - mincgrestartfrom(&state, &x, _state); - while(mincgiteration(&state, _state)) - { - testmincgunit_calclowrank(&state, n, vs, &d, &v, &vd, &x0, _state); - } - mincgresults(&state, &x, &rep, _state); - cntb1 = cntb1+rep.iterationscount; - *err = *err||rep.terminationtype<=0; - } - - /* - * Test it with low rank preconditioner - */ - mincgsetpreclowrankfast(&state, &d, &vd, &v, vs, _state); - cntg1 = 0; - for(pass=0; pass<=k-1; pass++) - { - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - mincgrestartfrom(&state, &x, _state); - while(mincgiteration(&state, _state)) - { - testmincgunit_calclowrank(&state, n, vs, &d, &v, &vd, &x0, _state); - } - mincgresults(&state, &x, &rep, _state); - cntg1 = cntg1+rep.iterationscount; - *err = *err||rep.terminationtype<=0; - } - - /* - * Compare - */ - *err = *err||cntb1=0, __FILE__, __LINE__, "testmincgunit.ap:1336"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx>=0, __FILE__, __LINE__, "testmincgunit.ap:1337"); - ae_set_error_flag(wereerrors, ogrep.nonc1test0positive, __FILE__, __LINE__, "testmincgunit.ap:1338"); - ae_set_error_flag(wereerrors, ogrep.nonc1test1positive, __FILE__, __LINE__, "testmincgunit.ap:1339"); - - /* - * Test gradient checking functionality, try various - * defect types: - * * accidental zeroing of some gradient component - * * accidental addition of 1.0 to some component - * * accidental multiplication by 2.0 - * Try distorting both target and constraints. - */ - diffstep = 0.001; - n = 10; - for(skind=0; skind<=1; skind++) - { - for(defecttype=-1; defecttype<=2; defecttype++) - { - varidx = hqrnduniformi(&rs, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = ae_pow((double)(10), skind*(30*hqrnduniformr(&rs, _state)-15), _state); - x0.ptr.p_double[i] = (1.0+0.1*i)*s.ptr.p_double[i]; - } - spdmatrixrndcond(n, 1.0E3, &a, _state); - spdmatrixrndcond(n, 1.0E3, &a1, _state); - mincgcreate(n, &x0, &state, _state); - mincgoptguardgradient(&state, diffstep, _state); - mincgsetcond(&state, (double)(0), (double)(0), 1.0E-9, 10, _state); - mincgsetscale(&state, &s, _state); - while(mincgiteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.f = state.f+0.5*(state.x.ptr.p_double[i]/s.ptr.p_double[i])*v; - state.g.ptr.p_double[i] = v; - } - if( defecttype==0 ) - { - state.g.ptr.p_double[varidx] = (double)(0); - } - if( defecttype==1 ) - { - state.g.ptr.p_double[varidx] = state.g.ptr.p_double[varidx]+1; - } - if( defecttype==2 ) - { - state.g.ptr.p_double[varidx] = state.g.ptr.p_double[varidx]*2; - } - for(i=0; i<=n-1; i++) - { - state.g.ptr.p_double[i] = state.g.ptr.p_double[i]/s.ptr.p_double[i]; - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - mincgresults(&state, &x1, &rep, _state); - mincgoptguardresults(&state, &ogrep, _state); - - /* - * Check that something is returned - */ - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testmincgunit.ap:1403"); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1404"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Compute reference values for true and spoiled Jacobian at X0 - */ - ae_set_error_flag(wereerrors, !isfinitevector(&ogrep.badgradxbase, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1411"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&jactrue, 1, n, _state); - ae_matrix_set_length(&jacdefect, 1, n, _state); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+ogrep.badgradxbase.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - jactrue.ptr.pp_double[0][i] = v; - jacdefect.ptr.pp_double[0][i] = v; - } - if( defecttype==0 ) - { - jacdefect.ptr.pp_double[0][varidx] = (double)(0); - } - if( defecttype==1 ) - { - jacdefect.ptr.pp_double[0][varidx] = jacdefect.ptr.pp_double[0][varidx]+1; - } - if( defecttype==2 ) - { - jacdefect.ptr.pp_double[0][varidx] = jacdefect.ptr.pp_double[0][varidx]*2; - } - for(i=0; i<=n-1; i++) - { - jactrue.ptr.pp_double[0][i] = jactrue.ptr.pp_double[0][i]/s.ptr.p_double[i]; - jacdefect.ptr.pp_double[0][i] = jacdefect.ptr.pp_double[0][i]/s.ptr.p_double[i]; - } - - /* - * Check OptGuard report - */ - ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgraduser, 1, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1439"); - ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgradnum, 1, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1440"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - if( defecttype>=0 ) - { - ae_set_error_flag(wereerrors, !ogrep.badgradsuspected, __FILE__, __LINE__, "testmincgunit.ap:1445"); - ae_set_error_flag(wereerrors, ogrep.badgradfidx!=0, __FILE__, __LINE__, "testmincgunit.ap:1446"); - ae_set_error_flag(wereerrors, ogrep.badgradvidx!=varidx, __FILE__, __LINE__, "testmincgunit.ap:1447"); - } - else - { - ae_set_error_flag(wereerrors, ogrep.badgradsuspected, __FILE__, __LINE__, "testmincgunit.ap:1451"); - ae_set_error_flag(wereerrors, ogrep.badgradfidx!=-1, __FILE__, __LINE__, "testmincgunit.ap:1452"); - ae_set_error_flag(wereerrors, ogrep.badgradvidx!=-1, __FILE__, __LINE__, "testmincgunit.ap:1453"); - } - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jactrue.ptr.pp_double[0][j]-ogrep.badgradnum.ptr.pp_double[0][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testmincgunit.ap:1457"); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jacdefect.ptr.pp_double[0][j]-ogrep.badgraduser.ptr.pp_double[0][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testmincgunit.ap:1458"); - } - } - } - - /* - * A test for detection of C1 continuity violations in the target. - * - * Target function is a sum of |(x,c_i)| for i=1..N. - * No constraints is present. - * Analytic gradient is provided. - * - * OptGuard should be able to detect violations in more than - * 99.9% of runs; it means that 100 runs should have no more than 4 - * failures in all cases (even after multiple repeated tests; according - * to the binomial distribution quantiles). - * - * We select some N and perform exhaustive search for this N. - */ - passcount = 100; - maxfails = 4; - maxc1test0fails = 10; - maxc1test1fails = 10; - n = 1+hqrnduniformi(&rs, 10, _state); - failurecounter = 0; - c1test0fails = 0; - c1test1fails = 0; - avgstr0len = (double)(0); - avglng0len = (double)(0); - avgstr1len = (double)(0); - avglng1len = (double)(0); - for(pass=1; pass<=passcount; pass++) - { - - /* - * Formulate problem - */ - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - - /* - * Create and try to solve - */ - mincgcreate(n, &x0, &state, _state); - mincgsetcond(&state, (double)(0), (double)(0), 1.0E-9, 50, _state); - mincgsetscale(&state, &s, _state); - mincgoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testmincgunit_maxoptguardlevel, _state), _state); - while(mincgiteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.g.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.f = state.f+ae_fabs(v, _state); - v = (double)(ae_sign(v, _state)); - for(j=0; j<=n-1; j++) - { - state.g.ptr.p_double[j] = state.g.ptr.p_double[j]+v*a.ptr.pp_double[i][j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - mincgresults(&state, &x1, &rep, _state); - mincgoptguardresults(&state, &ogrep, _state); - - /* - * Check basic properties of the solution - */ - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1539"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testmincgunit.ap:1540"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check generic OptGuard report: distinguish between "hard" - * failures which result in immediate termination - * (C0 violation being reported) and "soft" ones - * (C1 violation is NOT reported) which accumulate - * until we exhaust limit. - */ - ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testmincgunit.ap:1551"); - ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testmincgunit.ap:1552"); - failed = ae_false; - failed = failed||optguardallclear(&ogrep, _state); - failed = failed||!ogrep.nonc1suspected; - failed = failed||ogrep.nonc1fidx!=0; - if( failed ) - { - inc(&failurecounter, _state); - } - - /* - * Check C1 continuity test #0 - */ - mincgoptguardnonc1test0results(&state, &ognonc1test0strrep, &ognonc1test0lngrep, _state); - mincgoptguardnonc1test1results(&state, &ognonc1test1strrep, &ognonc1test1lngrep, _state); - if( ogrep.nonc1test0positive ) - { - ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testmincgunit.ap:1567"); - ae_set_error_flag(wereerrors, !ognonc1test0strrep.positive, __FILE__, __LINE__, "testmincgunit.ap:1568"); - ae_set_error_flag(wereerrors, !ognonc1test0lngrep.positive, __FILE__, __LINE__, "testmincgunit.ap:1569"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testmincgunit.ap:1570"); - testmincgunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0strrep, &a, n, _state); - testmincgunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0lngrep, &a, n, _state); - avgstr0len = avgstr0len+(double)ognonc1test0strrep.cnt/(double)passcount; - avglng0len = avglng0len+(double)ognonc1test0lngrep.cnt/(double)passcount; - } - else - { - ae_set_error_flag(wereerrors, ognonc1test0strrep.positive, __FILE__, __LINE__, "testmincgunit.ap:1578"); - ae_set_error_flag(wereerrors, ognonc1test0lngrep.positive, __FILE__, __LINE__, "testmincgunit.ap:1579"); - testmincgunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0strrep, &a, n, _state); - testmincgunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0lngrep, &a, n, _state); - inc(&c1test0fails, _state); - } - if( ogrep.nonc1test1positive ) - { - ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testmincgunit.ap:1586"); - ae_set_error_flag(wereerrors, !ognonc1test1strrep.positive, __FILE__, __LINE__, "testmincgunit.ap:1587"); - ae_set_error_flag(wereerrors, !ognonc1test1lngrep.positive, __FILE__, __LINE__, "testmincgunit.ap:1588"); - ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testmincgunit.ap:1589"); - testmincgunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1strrep, &a, n, _state); - testmincgunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1lngrep, &a, n, _state); - avgstr1len = avgstr1len+(double)ognonc1test1strrep.cnt/(double)passcount; - avglng1len = avglng1len+(double)ognonc1test1lngrep.cnt/(double)passcount; - } - else - { - ae_set_error_flag(wereerrors, ognonc1test1strrep.positive, __FILE__, __LINE__, "testmincgunit.ap:1597"); - ae_set_error_flag(wereerrors, ognonc1test1lngrep.positive, __FILE__, __LINE__, "testmincgunit.ap:1598"); - testmincgunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1strrep, &a, n, _state); - testmincgunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1lngrep, &a, n, _state); - inc(&c1test1fails, _state); - } - } - ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testmincgunit.ap:1605"); - ae_set_error_flag(wereerrors, c1test0fails>maxc1test0fails, __FILE__, __LINE__, "testmincgunit.ap:1606"); - ae_set_error_flag(wereerrors, c1test1fails>maxc1test1fails, __FILE__, __LINE__, "testmincgunit.ap:1607"); - ae_set_error_flag(wereerrors, ae_fp_less_eq(avglng0len,avgstr0len), __FILE__, __LINE__, "testmincgunit.ap:1608"); - ae_set_error_flag(wereerrors, ae_fp_less_eq(avglng1len,avgstr1len), __FILE__, __LINE__, "testmincgunit.ap:1609"); - - /* - * Detection of C1 continuity violations in the target under numerical differentiation: - * * target function is a sum of |(x,c_i)| for i=1..N. - * * no constraints is present. - * * analytic gradient is provided. - * - * OptGuard should always be able to detect violations in more than - * 99% of runs (note: reduced strength when compared with analytic gradient); - * it means that 100 runs should have no more than 10 failures in all cases - * (even after multiple repeated tests; according to the binomial distribution - * quantiles). - * - * We select some N and perform exhaustive search for this N. - */ - diffstep = 0.0001; - passcount = 100; - maxfails = 10; - n = 1+hqrnduniformi(&rs, 10, _state); - failurecounter = 0; - for(pass=1; pass<=passcount; pass++) - { - - /* - * Formulate problem - */ - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&s, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = 0.01*ae_pow((double)(2), 0.33*hqrndnormal(&rs, _state), _state); - } - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - - /* - * Create and try to solve - */ - mincgcreatef(n, &x0, diffstep, &state, _state); - mincgsetcond(&state, (double)(0), (double)(0), 1.0E-9, 50, _state); - mincgoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testmincgunit_maxoptguardlevel, _state), _state); - while(mincgiteration(&state, _state)) - { - if( state.needf ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.f = state.f+ae_fabs(v, _state); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - mincgresults(&state, &x1, &rep, _state); - mincgoptguardresults(&state, &ogrep, _state); - - /* - * Check basic properties of the solution - */ - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1674"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testmincgunit.ap:1675"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check OptGuard report: distinguish between "hard" - * failures which result in immediate termination - * (C0 violation being reported) and "soft" ones - * (C1 violation is NOT reported) which accumulate - * until we exhaust limit. - */ - ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testmincgunit.ap:1686"); - ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testmincgunit.ap:1687"); - failed = ae_false; - failed = failed||optguardallclear(&ogrep, _state); - failed = failed||!ogrep.nonc1suspected; - failed = failed||ogrep.nonc1fidx!=0; - if( failed ) - { - inc(&failurecounter, _state); - } - } - ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testmincgunit.ap:1695"); - - /* - * Make sure than no false positives are reported for larger - * problems where numerical noise can be an issue: - * * N=100 dimensions - * * positive-definite quadratic programming problem - * * upper limit on iterations count, MaxIts=25 - * We simply test that OptGuard does not return error code. - */ - n = 100; - spdmatrixrndcond(n, 1.0E2, &a, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = hqrndnormal(&rs, _state); - x0.ptr.p_double[i] = ae_pow(2.0, hqrndnormal(&rs, _state), _state); - } - mincgcreate(n, &x0, &state, _state); - mincgoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testmincgunit_maxoptguardlevel, _state), _state); - mincgsetcond(&state, (double)(0), (double)(0), 1.0E-9, 25, _state); - while(mincgiteration(&state, _state)) - { - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+b.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.g.ptr.p_double[i] = b.ptr.p_double[i]; - for(j=0; j<=n-1; j++) - { - state.f = state.f+0.5*state.x.ptr.p_double[i]*a.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - state.g.ptr.p_double[i] = state.g.ptr.p_double[i]+a.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - mincgresults(&state, &x1, &rep, _state); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1738"); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testmincgunit.ap:1739"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - mincgoptguardresults(&state, &ogrep, _state); - ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testmincgunit.ap:1743"); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests report of "non-C1" test #0 for task #0 -given by matrix A. - -On failure sets error flag. -*************************************************************************/ -static void testmincgunit_testoptguardc1test0reportfortask0(ae_bool* err, - optguardnonc1test0report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double vv; - double va; - double vb; - ae_bool hasc1discontinuities; - - - if( rep->positive ) - { - - /* - * Check positive report, first checks - */ - ae_set_error_flag(err, rep->fidx!=0, __FILE__, __LINE__, "testmincgunit.ap:1770"); - ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testmincgunit.ap:1771"); - ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testmincgunit.ap:1772"); - ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testmincgunit.ap:1773"); - ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testmincgunit.ap:1774"); - ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testmincgunit.ap:1775"); - ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testmincgunit.ap:1776"); - ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testmincgunit.ap:1777"); - ae_set_error_flag(err, rep->f.cnt!=rep->cnt, __FILE__, __LINE__, "testmincgunit.ap:1778"); - ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1779"); - ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1780"); - ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testmincgunit.ap:1781"); - ae_set_error_flag(err, !isfinitevector(&rep->f, rep->cnt, _state), __FILE__, __LINE__, "testmincgunit.ap:1782"); - if( *err ) - { - return; - } - - /* - * Check consistency of X0, D, Stp and F - */ - for(k=0; k<=rep->cnt-2; k++) - { - ae_set_error_flag(err, ae_fp_greater_eq(rep->stp.ptr.p_double[k],rep->stp.ptr.p_double[k+1]), __FILE__, __LINE__, "testmincgunit.ap:1790"); - } - for(k=0; k<=rep->cnt-1; k++) - { - v = (double)(0); - for(i=0; i<=n-1; i++) - { - vv = (double)(0); - for(j=0; j<=n-1; j++) - { - vv = vv+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[k]); - } - v = v+ae_fabs(vv, _state); - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-rep->f.ptr.p_double[k], _state),1.0E-6*ae_maxreal(ae_fabs(v, _state), (double)(1), _state)), __FILE__, __LINE__, "testmincgunit.ap:1803"); - } - - /* - * Check that interval [#StpIdxA,#StpIdxB] contains at least one discontinuity - */ - hasc1discontinuities = ae_false; - for(i=0; i<=n-1; i++) - { - va = (double)(0); - vb = (double)(0); - for(j=0; j<=n-1; j++) - { - va = va+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxa]); - vb = vb+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxb]); - } - hasc1discontinuities = hasc1discontinuities||ae_sign(va, _state)!=ae_sign(vb, _state); - } - ae_set_error_flag(err, !hasc1discontinuities, __FILE__, __LINE__, "testmincgunit.ap:1821"); - } - else - { - - /* - * Check negative report: fields must be empty - */ - ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testmincgunit.ap:1828"); - ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testmincgunit.ap:1829"); - ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testmincgunit.ap:1830"); - ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testmincgunit.ap:1831"); - ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testmincgunit.ap:1832"); - ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testmincgunit.ap:1833"); - ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testmincgunit.ap:1834"); - ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testmincgunit.ap:1835"); - ae_set_error_flag(err, rep->f.cnt!=0, __FILE__, __LINE__, "testmincgunit.ap:1836"); - } -} - - -/************************************************************************* -This function tests report of "non-C1" test #1 for task #0 -given by matrix A. - -On failure sets error flag. -*************************************************************************/ -static void testmincgunit_testoptguardc1test1reportfortask0(ae_bool* err, - optguardnonc1test1report* rep, - /* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double vv; - double va; - double vb; - ae_bool tooclose; - ae_bool hasc1discontinuities; - - - if( rep->positive ) - { - - /* - * Check positive report, first checks - */ - ae_set_error_flag(err, rep->fidx!=0, __FILE__, __LINE__, "testmincgunit.ap:1864"); - ae_set_error_flag(err, rep->vidx<0, __FILE__, __LINE__, "testmincgunit.ap:1865"); - ae_set_error_flag(err, rep->vidx>n, __FILE__, __LINE__, "testmincgunit.ap:1866"); - ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testmincgunit.ap:1867"); - ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testmincgunit.ap:1868"); - ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testmincgunit.ap:1869"); - ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testmincgunit.ap:1870"); - ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testmincgunit.ap:1871"); - ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testmincgunit.ap:1872"); - ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testmincgunit.ap:1873"); - ae_set_error_flag(err, rep->g.cnt!=rep->cnt, __FILE__, __LINE__, "testmincgunit.ap:1874"); - ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1875"); - ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1876"); - ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testmincgunit.ap:1877"); - ae_set_error_flag(err, !isfinitevector(&rep->g, rep->cnt, _state), __FILE__, __LINE__, "testmincgunit.ap:1878"); - if( *err ) - { - return; - } - - /* - * Check consistency of X0, D, Stp and G - */ - for(k=0; k<=rep->cnt-2; k++) - { - ae_set_error_flag(err, ae_fp_greater_eq(rep->stp.ptr.p_double[k],rep->stp.ptr.p_double[k+1]), __FILE__, __LINE__, "testmincgunit.ap:1886"); - } - for(k=0; k<=rep->cnt-1; k++) - { - v = (double)(0); - tooclose = ae_false; - for(i=0; i<=n-1; i++) - { - vv = (double)(0); - for(j=0; j<=n-1; j++) - { - vv = vv+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[k]); - } - v = v+ae_sign(vv, _state)*a->ptr.pp_double[i][rep->vidx]; - tooclose = tooclose||ae_fp_less(ae_fabs(vv, _state),1.0E-4); - } - if( !tooclose ) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-rep->g.ptr.p_double[k], _state),1.0E-6*ae_maxreal(ae_fabs(v, _state), (double)(1), _state)), __FILE__, __LINE__, "testmincgunit.ap:1900"); - } - } - - /* - * Check that interval [#StpIdxA,#StpIdxB] contains at least one discontinuity - */ - tooclose = ae_false; - hasc1discontinuities = ae_false; - for(i=0; i<=n-1; i++) - { - va = (double)(0); - vb = (double)(0); - for(j=0; j<=n-1; j++) - { - va = va+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxa]); - vb = vb+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxb]); - } - tooclose = (tooclose||ae_fp_less(ae_fabs(va, _state),1.0E-8))||ae_fp_less(ae_fabs(vb, _state),1.0E-8); - hasc1discontinuities = hasc1discontinuities||ae_sign(va, _state)!=ae_sign(vb, _state); - } - if( !tooclose ) - { - ae_set_error_flag(err, !hasc1discontinuities, __FILE__, __LINE__, "testmincgunit.ap:1921"); - } - } - else - { - - /* - * Check negative report: fields must be empty - */ - ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testmincgunit.ap:1928"); - ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testmincgunit.ap:1929"); - ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testmincgunit.ap:1930"); - ae_set_error_flag(err, rep->vidx!=-1, __FILE__, __LINE__, "testmincgunit.ap:1931"); - ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testmincgunit.ap:1932"); - ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testmincgunit.ap:1933"); - ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testmincgunit.ap:1934"); - ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testmincgunit.ap:1935"); - ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testmincgunit.ap:1936"); - ae_set_error_flag(err, rep->g.cnt!=0, __FILE__, __LINE__, "testmincgunit.ap:1937"); - } -} - - - -static void testminlmunit_testu(ae_bool* errorflag, - ae_bool* statefieldsconsistencyflag, - ae_state *_state); -static void testminlmunit_testbc(ae_bool* errorflag, ae_state *_state); -static void testminlmunit_testlc(ae_bool* errorflag, ae_state *_state); -static void testminlmunit_testother(ae_bool* errorflag, - ae_bool* statefieldsconsistencyflag, - ae_state *_state); -static void testminlmunit_testoptguard(ae_bool* wereerrors, - ae_state *_state); -static ae_bool testminlmunit_rkindvsstatecheck(ae_int_t rkind, - minlmstate* state, - ae_state *_state); -static void testminlmunit_axmb(minlmstate* state, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* b, - ae_int_t n, - ae_state *_state); -static void testminlmunit_tryreproducefixedbugs(ae_bool* err, - ae_state *_state); -static void testminlmunit_testfunc1(ae_int_t n, - ae_int_t m, - /* Real */ ae_matrix* c, - /* Real */ ae_vector* x, - double* f, - ae_bool needf, - /* Real */ ae_vector* fi, - ae_bool needfi, - /* Real */ ae_matrix* jac, - ae_bool needjac, - ae_state *_state); - - - - - -ae_bool testminlm(ae_bool silent, ae_state *_state) -{ - ae_bool waserrors; - ae_bool uerrors; - ae_bool bcerrors; - ae_bool lcerrors; - ae_bool scerror; - ae_bool othererrors; - ae_bool optguarderr; - ae_bool result; - - - waserrors = ae_false; - scerror = ae_false; - othererrors = ae_false; - uerrors = ae_false; - bcerrors = ae_false; - lcerrors = ae_false; - - /* - * Various tests - */ - testminlmunit_testother(&othererrors, &scerror, _state); - - /* - * Tests sorted by constraint types - */ - testminlmunit_testu(&uerrors, &scerror, _state); - testminlmunit_testbc(&bcerrors, _state); - testminlmunit_testlc(&lcerrors, _state); - - /* - * Try to reproduce previously fixed bugs - */ - testminlmunit_tryreproducefixedbugs(&othererrors, _state); - - /* - * Test for MinLMGradientCheck - */ - optguarderr = ae_false; - testminlmunit_testoptguard(&optguarderr, _state); - - /* - * end - */ - waserrors = ((((uerrors||bcerrors)||lcerrors)||scerror)||othererrors)||optguarderr; - if( !silent ) - { - printf("TESTING LEVENBERG-MARQUARDT OPTIMIZATION\n"); - printf("PROBLEM TYPES:\n"); - printf("* UNCONSTRAINED "); - if( uerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* BOX CONSTRAINED "); - if( bcerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* LINEARLY CONSTRAINED "); - if( lcerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("STATE FIELDS CONSISTENCY: "); - if( scerror ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("OTHER PROPERTIES: "); - if( othererrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("OPTGUARD: "); - if( optguarderr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - return result; -} - - -/************************************************************************* -Test for unconstrained problems. -On failure sets error flag, leaves it unchanged on success. -*************************************************************************/ -static void testminlmunit_testu(ae_bool* errorflag, - ae_bool* statefieldsconsistencyflag, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t m; - ae_int_t i; - ae_vector x; - ae_vector xe; - ae_vector b; - double h; - ae_int_t rkind; - ae_matrix a; - double v; - double s; - double eps; - double epsx; - ae_int_t maxits; - ae_int_t ckind; - minlmstate state; - minlmreport rep; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&xe, 0, sizeof(xe)); - memset(&b, 0, sizeof(b)); - memset(&a, 0, sizeof(a)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xe, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - _minlmstate_init(&state, _state, ae_true); - _minlmreport_init(&rep, _state, ae_true); - - - /* - * Reference problem. - * See comments for RKindVsStateCheck() for more info about RKind. - * - * NOTES: we also test negative RKind's corresponding to "inexact" schemes - * which use approximate finite difference Jacobian. - */ - ae_vector_set_length(&x, 3, _state); - n = 3; - m = 3; - h = 0.0001; - for(rkind=-2; rkind<=5; rkind++) - { - x.ptr.p_double[0] = 100*ae_randomreal(_state)-50; - x.ptr.p_double[1] = 100*ae_randomreal(_state)-50; - x.ptr.p_double[2] = 100*ae_randomreal(_state)-50; - if( rkind==-2 ) - { - minlmcreatev(n, m, &x, h, &state, _state); - minlmsetacctype(&state, 1, _state); - } - if( rkind==-1 ) - { - minlmcreatev(n, m, &x, h, &state, _state); - minlmsetacctype(&state, 0, _state); - } - if( rkind==0 ) - { - minlmcreatefj(n, m, &x, &state, _state); - } - if( rkind==1 ) - { - minlmcreatefgj(n, m, &x, &state, _state); - } - if( rkind==2 ) - { - minlmcreatefgh(n, &x, &state, _state); - } - if( rkind==3 ) - { - minlmcreatevj(n, m, &x, &state, _state); - minlmsetacctype(&state, 0, _state); - } - if( rkind==4 ) - { - minlmcreatevj(n, m, &x, &state, _state); - minlmsetacctype(&state, 1, _state); - } - if( rkind==5 ) - { - minlmcreatevj(n, m, &x, &state, _state); - minlmsetacctype(&state, 2, _state); - } - while(minlmiteration(&state, _state)) - { - - /* - * (x-2)^2 + y^2 + (z-x)^2 - */ - if( state.needfi ) - { - state.fi.ptr.p_double[0] = state.x.ptr.p_double[0]-2; - state.fi.ptr.p_double[1] = state.x.ptr.p_double[1]; - state.fi.ptr.p_double[2] = state.x.ptr.p_double[2]-state.x.ptr.p_double[0]; - } - if( state.needfij ) - { - state.fi.ptr.p_double[0] = state.x.ptr.p_double[0]-2; - state.fi.ptr.p_double[1] = state.x.ptr.p_double[1]; - state.fi.ptr.p_double[2] = state.x.ptr.p_double[2]-state.x.ptr.p_double[0]; - state.j.ptr.pp_double[0][0] = (double)(1); - state.j.ptr.pp_double[0][1] = (double)(0); - state.j.ptr.pp_double[0][2] = (double)(0); - state.j.ptr.pp_double[1][0] = (double)(0); - state.j.ptr.pp_double[1][1] = (double)(1); - state.j.ptr.pp_double[1][2] = (double)(0); - state.j.ptr.pp_double[2][0] = (double)(-1); - state.j.ptr.pp_double[2][1] = (double)(0); - state.j.ptr.pp_double[2][2] = (double)(1); - } - if( (state.needf||state.needfg)||state.needfgh ) - { - state.f = ae_sqr(state.x.ptr.p_double[0]-2, _state)+ae_sqr(state.x.ptr.p_double[1], _state)+ae_sqr(state.x.ptr.p_double[2]-state.x.ptr.p_double[0], _state); - } - if( state.needfg||state.needfgh ) - { - state.g.ptr.p_double[0] = 2*(state.x.ptr.p_double[0]-2)+2*(state.x.ptr.p_double[0]-state.x.ptr.p_double[2]); - state.g.ptr.p_double[1] = 2*state.x.ptr.p_double[1]; - state.g.ptr.p_double[2] = 2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0]); - } - if( state.needfgh ) - { - state.h.ptr.pp_double[0][0] = (double)(4); - state.h.ptr.pp_double[0][1] = (double)(0); - state.h.ptr.pp_double[0][2] = (double)(-2); - state.h.ptr.pp_double[1][0] = (double)(0); - state.h.ptr.pp_double[1][1] = (double)(2); - state.h.ptr.pp_double[1][2] = (double)(0); - state.h.ptr.pp_double[2][0] = (double)(-2); - state.h.ptr.pp_double[2][1] = (double)(0); - state.h.ptr.pp_double[2][2] = (double)(2); - } - ae_set_error_flag(statefieldsconsistencyflag, !testminlmunit_rkindvsstatecheck(rkind, &state, _state), __FILE__, __LINE__, "testminlmunit.ap:212"); - } - minlmresults(&state, &x, &rep, _state); - ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:215"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x.ptr.p_double[0]-2, _state),0.001), __FILE__, __LINE__, "testminlmunit.ap:216"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x.ptr.p_double[1], _state),0.001), __FILE__, __LINE__, "testminlmunit.ap:217"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x.ptr.p_double[2]-2, _state),0.001), __FILE__, __LINE__, "testminlmunit.ap:218"); - } - - /* - * 1D problem #1 - * - * NOTES: we also test negative RKind's corresponding to "inexact" schemes - * which use approximate finite difference Jacobian. - */ - for(rkind=-2; rkind<=5; rkind++) - { - ae_vector_set_length(&x, 1, _state); - n = 1; - m = 1; - h = 0.00001; - x.ptr.p_double[0] = 100*ae_randomreal(_state)-50; - if( rkind==-2 ) - { - minlmcreatev(n, m, &x, h, &state, _state); - minlmsetacctype(&state, 1, _state); - } - if( rkind==-1 ) - { - minlmcreatev(n, m, &x, h, &state, _state); - minlmsetacctype(&state, 0, _state); - } - if( rkind==0 ) - { - minlmcreatefj(n, m, &x, &state, _state); - } - if( rkind==1 ) - { - minlmcreatefgj(n, m, &x, &state, _state); - } - if( rkind==2 ) - { - minlmcreatefgh(n, &x, &state, _state); - } - if( rkind==3 ) - { - minlmcreatevj(n, m, &x, &state, _state); - minlmsetacctype(&state, 0, _state); - } - if( rkind==4 ) - { - minlmcreatevj(n, m, &x, &state, _state); - minlmsetacctype(&state, 1, _state); - } - if( rkind==5 ) - { - minlmcreatevj(n, m, &x, &state, _state); - minlmsetacctype(&state, 2, _state); - } - while(minlmiteration(&state, _state)) - { - if( state.needfi ) - { - state.fi.ptr.p_double[0] = ae_sin(state.x.ptr.p_double[0], _state); - } - if( state.needfij ) - { - state.fi.ptr.p_double[0] = ae_sin(state.x.ptr.p_double[0], _state); - state.j.ptr.pp_double[0][0] = ae_cos(state.x.ptr.p_double[0], _state); - } - if( (state.needf||state.needfg)||state.needfgh ) - { - state.f = ae_sqr(ae_sin(state.x.ptr.p_double[0], _state), _state); - } - if( state.needfg||state.needfgh ) - { - state.g.ptr.p_double[0] = 2*ae_sin(state.x.ptr.p_double[0], _state)*ae_cos(state.x.ptr.p_double[0], _state); - } - if( state.needfgh ) - { - state.h.ptr.pp_double[0][0] = 2*(ae_cos(state.x.ptr.p_double[0], _state)*ae_cos(state.x.ptr.p_double[0], _state)-ae_sin(state.x.ptr.p_double[0], _state)*ae_sin(state.x.ptr.p_double[0], _state)); - } - ae_set_error_flag(statefieldsconsistencyflag, !testminlmunit_rkindvsstatecheck(rkind, &state, _state), __FILE__, __LINE__, "testminlmunit.ap:281"); - } - minlmresults(&state, &x, &rep, _state); - ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:284"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x.ptr.p_double[0]/ae_pi-ae_round(x.ptr.p_double[0]/ae_pi, _state), _state),0.001), __FILE__, __LINE__, "testminlmunit.ap:285"); - } - - /* - * Linear equations: test normal optimization and optimization with restarts - */ - for(n=1; n<=10; n++) - { - - /* - * Prepare task - */ - h = 0.00001; - rmatrixrndcond(n, (double)(100), &a, _state); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&xe, n, _state); - ae_vector_set_length(&b, n, _state); - for(i=0; i<=n-1; i++) - { - xe.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xe.ptr.p_double[0], 1, ae_v_len(0,n-1)); - b.ptr.p_double[i] = v; - } - - /* - * Test different RKind - * - * NOTES: we also test negative RKind's corresponding to "inexact" schemes - * which use approximate finite difference Jacobian. - */ - for(rkind=-2; rkind<=5; rkind++) - { - - /* - * Solve task (first attempt) - */ - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - if( rkind==-2 ) - { - minlmcreatev(n, n, &x, h, &state, _state); - minlmsetacctype(&state, 1, _state); - } - if( rkind==-1 ) - { - minlmcreatev(n, n, &x, h, &state, _state); - minlmsetacctype(&state, 0, _state); - } - if( rkind==0 ) - { - minlmcreatefj(n, n, &x, &state, _state); - } - if( rkind==1 ) - { - minlmcreatefgj(n, n, &x, &state, _state); - } - if( rkind==2 ) - { - minlmcreatefgh(n, &x, &state, _state); - } - if( rkind==3 ) - { - minlmcreatevj(n, n, &x, &state, _state); - minlmsetacctype(&state, 0, _state); - } - if( rkind==4 ) - { - minlmcreatevj(n, n, &x, &state, _state); - minlmsetacctype(&state, 1, _state); - } - if( rkind==5 ) - { - minlmcreatevj(n, n, &x, &state, _state); - minlmsetacctype(&state, 2, _state); - } - while(minlmiteration(&state, _state)) - { - testminlmunit_axmb(&state, &a, &b, n, _state); - ae_set_error_flag(statefieldsconsistencyflag, !testminlmunit_rkindvsstatecheck(rkind, &state, _state), __FILE__, __LINE__, "testminlmunit.ap:357"); - } - minlmresults(&state, &x, &rep, _state); - ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:360"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x.ptr.p_double[i]-xe.ptr.p_double[i], _state),0.001), __FILE__, __LINE__, "testminlmunit.ap:364"); - } - - /* - * Now we try to restart algorithm from new point - */ - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - minlmrestartfrom(&state, &x, _state); - while(minlmiteration(&state, _state)) - { - testminlmunit_axmb(&state, &a, &b, n, _state); - ae_set_error_flag(statefieldsconsistencyflag, !testminlmunit_rkindvsstatecheck(rkind, &state, _state), __FILE__, __LINE__, "testminlmunit.ap:375"); - } - minlmresults(&state, &x, &rep, _state); - ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:378"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x.ptr.p_double[i]-xe.ptr.p_double[i], _state),0.001), __FILE__, __LINE__, "testminlmunit.ap:382"); - } - } - } - - /* - * Testing convergence properties using - * different optimizer types and different conditions. - * - * Only limited subset of optimizers is tested because some - * optimizers converge too quickly. - */ - s = (double)(100); - for(rkind=0; rkind<=5; rkind++) - { - - /* - * Skip FGH optimizer - it converges too quickly - */ - if( rkind==2 ) - { - continue; - } - - /* - * Test - */ - for(ckind=0; ckind<=1; ckind++) - { - eps = (double)(0); - epsx = (double)(0); - maxits = 0; - if( ckind==0 ) - { - epsx = 1.0E-6; - eps = 1.0E-4; - } - if( ckind==1 ) - { - maxits = 2; - eps = 0.05; - } - ae_vector_set_length(&x, 3, _state); - n = 3; - m = 3; - for(i=0; i<=2; i++) - { - x.ptr.p_double[i] = (double)(6); - } - if( rkind==0 ) - { - minlmcreatefj(n, m, &x, &state, _state); - } - if( rkind==1 ) - { - minlmcreatefgj(n, m, &x, &state, _state); - } - ae_assert(rkind!=2, "Assertion failed", _state); - if( rkind==3 ) - { - minlmcreatevj(n, m, &x, &state, _state); - minlmsetacctype(&state, 0, _state); - } - if( rkind==4 ) - { - minlmcreatevj(n, m, &x, &state, _state); - minlmsetacctype(&state, 1, _state); - } - if( rkind==5 ) - { - minlmcreatevj(n, m, &x, &state, _state); - minlmsetacctype(&state, 2, _state); - } - minlmsetcond(&state, epsx, maxits, _state); - while(minlmiteration(&state, _state)) - { - if( state.needfi||state.needfij ) - { - state.fi.ptr.p_double[0] = s*(ae_exp(state.x.ptr.p_double[0], _state)-2); - state.fi.ptr.p_double[1] = ae_sqr(state.x.ptr.p_double[1], _state)+1; - state.fi.ptr.p_double[2] = state.x.ptr.p_double[2]-state.x.ptr.p_double[0]; - } - if( state.needfij ) - { - state.j.ptr.pp_double[0][0] = s*ae_exp(state.x.ptr.p_double[0], _state); - state.j.ptr.pp_double[0][1] = (double)(0); - state.j.ptr.pp_double[0][2] = (double)(0); - state.j.ptr.pp_double[1][0] = (double)(0); - state.j.ptr.pp_double[1][1] = 2*state.x.ptr.p_double[1]; - state.j.ptr.pp_double[1][2] = (double)(0); - state.j.ptr.pp_double[2][0] = (double)(-1); - state.j.ptr.pp_double[2][1] = (double)(0); - state.j.ptr.pp_double[2][2] = (double)(1); - } - if( (state.needf||state.needfg)||state.needfgh ) - { - state.f = s*ae_sqr(ae_exp(state.x.ptr.p_double[0], _state)-2, _state)+ae_sqr(ae_sqr(state.x.ptr.p_double[1], _state)+1, _state)+ae_sqr(state.x.ptr.p_double[2]-state.x.ptr.p_double[0], _state); - } - if( state.needfg||state.needfgh ) - { - state.g.ptr.p_double[0] = s*2*(ae_exp(state.x.ptr.p_double[0], _state)-2)*ae_exp(state.x.ptr.p_double[0], _state)+2*(state.x.ptr.p_double[0]-state.x.ptr.p_double[2]); - state.g.ptr.p_double[1] = 2*(ae_sqr(state.x.ptr.p_double[1], _state)+1)*2*state.x.ptr.p_double[1]; - state.g.ptr.p_double[2] = 2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0]); - } - if( state.needfgh ) - { - state.h.ptr.pp_double[0][0] = s*(4*ae_sqr(ae_exp(state.x.ptr.p_double[0], _state), _state)-4*ae_exp(state.x.ptr.p_double[0], _state))+2; - state.h.ptr.pp_double[0][1] = (double)(0); - state.h.ptr.pp_double[0][2] = (double)(-2); - state.h.ptr.pp_double[1][0] = (double)(0); - state.h.ptr.pp_double[1][1] = 12*ae_sqr(state.x.ptr.p_double[1], _state)+4; - state.h.ptr.pp_double[1][2] = (double)(0); - state.h.ptr.pp_double[2][0] = (double)(-2); - state.h.ptr.pp_double[2][1] = (double)(0); - state.h.ptr.pp_double[2][2] = (double)(2); - } - ae_set_error_flag(statefieldsconsistencyflag, !testminlmunit_rkindvsstatecheck(rkind, &state, _state), __FILE__, __LINE__, "testminlmunit.ap:486"); - } - minlmresults(&state, &x, &rep, _state); - ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:489"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - if( ckind==0 ) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x.ptr.p_double[0]-ae_log((double)(2), _state), _state),eps), __FILE__, __LINE__, "testminlmunit.ap:494"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x.ptr.p_double[1], _state),eps), __FILE__, __LINE__, "testminlmunit.ap:495"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x.ptr.p_double[2]-ae_log((double)(2), _state), _state),eps), __FILE__, __LINE__, "testminlmunit.ap:496"); - ae_set_error_flag(errorflag, rep.terminationtype!=2, __FILE__, __LINE__, "testminlmunit.ap:497"); - } - if( ckind==1 ) - { - ae_set_error_flag(errorflag, rep.terminationtype!=5, __FILE__, __LINE__, "testminlmunit.ap:501"); - ae_set_error_flag(errorflag, rep.iterationscount!=maxits, __FILE__, __LINE__, "testminlmunit.ap:502"); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Test for box constrained problems. -On failure sets error flag, leaves it unchanged on success. -*************************************************************************/ -static void testminlmunit_testbc(ae_bool* errorflag, ae_state *_state) -{ - ae_frame _frame_block; - minlmstate state; - minlmreport rep; - ae_vector bl; - ae_vector bu; - ae_int_t n; - ae_int_t m; - ae_vector x0; - ae_vector x; - ae_vector xe; - ae_vector x1; - ae_vector d; - ae_matrix c; - ae_int_t i; - ae_int_t j; - double v; - double h; - ae_int_t tmpkind; - hqrndstate rs; - double epsx; - double tolf; - double f0; - double f1; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&bl, 0, sizeof(bl)); - memset(&bu, 0, sizeof(bu)); - memset(&x0, 0, sizeof(x0)); - memset(&x, 0, sizeof(x)); - memset(&xe, 0, sizeof(xe)); - memset(&x1, 0, sizeof(x1)); - memset(&d, 0, sizeof(d)); - memset(&c, 0, sizeof(c)); - memset(&rs, 0, sizeof(rs)); - _minlmstate_init(&state, _state, ae_true); - _minlmreport_init(&rep, _state, ae_true); - ae_vector_init(&bl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xe, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Reference box constrained problem: - * - * min sum((x[i]-xe[i])^4) subject to 0<=x[i]<=1 - * - * NOTES: - * 1. we test only two optimization modes - V and FGH, - * because from algorithm internals we can assume that actual - * mode being used doesn't matter for bound constrained optimization - * process. - */ - for(tmpkind=0; tmpkind<=1; tmpkind++) - { - for(n=1; n<=5; n++) - { - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - ae_vector_set_length(&xe, n, _state); - ae_vector_set_length(&x, n, _state); - for(i=0; i<=n-1; i++) - { - bl.ptr.p_double[i] = (double)(0); - bu.ptr.p_double[i] = (double)(1); - xe.ptr.p_double[i] = 3*ae_randomreal(_state)-1; - x.ptr.p_double[i] = ae_randomreal(_state); - } - if( tmpkind==0 ) - { - minlmcreatefgh(n, &x, &state, _state); - } - if( tmpkind==1 ) - { - minlmcreatev(n, n, &x, 1.0E-5, &state, _state); - } - minlmsetcond(&state, 1.0E-6, 0, _state); - minlmsetbc(&state, &bl, &bu, _state); - while(minlmiteration(&state, _state)) - { - if( state.needfi ) - { - for(i=0; i<=n-1; i++) - { - state.fi.ptr.p_double[i] = ae_pow(state.x.ptr.p_double[i]-xe.ptr.p_double[i], (double)(2), _state); - } - } - if( (state.needf||state.needfg)||state.needfgh ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+ae_pow(state.x.ptr.p_double[i]-xe.ptr.p_double[i], (double)(4), _state); - } - } - if( state.needfg||state.needfgh ) - { - for(i=0; i<=n-1; i++) - { - state.g.ptr.p_double[i] = 4*ae_pow(state.x.ptr.p_double[i]-xe.ptr.p_double[i], (double)(3), _state); - } - } - if( state.needfgh ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - state.h.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=n-1; i++) - { - state.h.ptr.pp_double[i][i] = 12*ae_pow(state.x.ptr.p_double[i]-xe.ptr.p_double[i], (double)(2), _state); - } - } - } - minlmresults(&state, &x, &rep, _state); - if( rep.terminationtype>0 ) - { - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x.ptr.p_double[i]-boundval(xe.ptr.p_double[i], bl.ptr.p_double[i], bu.ptr.p_double[i], _state), _state),5.0E-2), __FILE__, __LINE__, "testminlmunit.ap:594"); - } - } - else - { - ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminlmunit.ap:597"); - } - } - } - - /* - * Minimize - * - * [ [ ]2 ] - * SUM_i[ SUM_j[ power(x_j,3)*c_ij ] ] - * [ [ ] ] - * - * subject to non-negativity constraints on x_j - */ - epsx = 1.0E-9; - tolf = 1.0E-10; - for(tmpkind=0; tmpkind<=1; tmpkind++) - { - for(n=1; n<=20; n++) - { - m = n+hqrnduniformi(&rs, n, _state); - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - bl.ptr.p_double[i] = (double)(0); - bu.ptr.p_double[i] = _state->v_posinf; - x0.ptr.p_double[i] = 1+hqrnduniformr(&rs, _state); - } - ae_matrix_set_length(&c, m, n+1, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n; j++) - { - c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - if( tmpkind==0 ) - { - minlmcreatev(n, m, &x0, 10*epsx, &state, _state); - } - if( tmpkind==1 ) - { - minlmcreatevj(n, m, &x0, &state, _state); - } - minlmsetcond(&state, epsx, 0, _state); - minlmsetbc(&state, &bl, &bu, _state); - while(minlmiteration(&state, _state)) - { - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_less(state.x.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:639"); - ae_set_error_flag(errorflag, ae_fp_greater(state.x.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:640"); - } - if( state.needfi ) - { - testminlmunit_testfunc1(n, m, &c, &state.x, &v, ae_false, &state.fi, ae_true, &state.j, ae_false, _state); - continue; - } - if( state.needfij ) - { - testminlmunit_testfunc1(n, m, &c, &state.x, &v, ae_false, &state.fi, ae_true, &state.j, ae_true, _state); - continue; - } - ae_assert(ae_false, "minlm test: integrity check failed", _state); - } - minlmresults(&state, &x, &rep, _state); - ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:655"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - testminlmunit_testfunc1(n, m, &c, &x, &f0, ae_true, &state.fi, ae_false, &state.j, ae_false, _state); - ae_vector_set_length(&x1, n, _state); - h = 0.001; - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_less(x.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:664"); - ae_set_error_flag(errorflag, ae_fp_greater(x.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:665"); - if( ae_fp_greater_eq(x.ptr.p_double[i]+h,bl.ptr.p_double[i]) ) - { - for(j=0; j<=n-1; j++) - { - x1.ptr.p_double[j] = x.ptr.p_double[j]; - } - x1.ptr.p_double[i] = x.ptr.p_double[i]+h; - testminlmunit_testfunc1(n, m, &c, &x1, &f1, ae_true, &state.fi, ae_false, &state.j, ae_false, _state); - ae_set_error_flag(errorflag, ae_fp_less(f1,f0*(1-tolf)), __FILE__, __LINE__, "testminlmunit.ap:674"); - } - if( ae_fp_greater_eq(x.ptr.p_double[i]-h,bl.ptr.p_double[i]) ) - { - for(j=0; j<=n-1; j++) - { - x1.ptr.p_double[j] = x.ptr.p_double[j]; - } - x1.ptr.p_double[i] = x.ptr.p_double[i]-h; - testminlmunit_testfunc1(n, m, &c, &x1, &f1, ae_true, &state.fi, ae_false, &state.j, ae_false, _state); - ae_set_error_flag(errorflag, ae_fp_less(f1,f0*(1-tolf)), __FILE__, __LINE__, "testminlmunit.ap:684"); - } - } - } - } - - /* - * Minimize - * - * [ [ ]2 ] - * SUM_i[ SUM_j[ power(x_j,3)*c_ij ] ] - * [ [ ] ] - * - * subject to random box constraints on x_j - */ - epsx = 1.0E-9; - tolf = 1.0E-10; - for(tmpkind=0; tmpkind<=1; tmpkind++) - { - for(n=1; n<=20; n++) - { - m = n+hqrnduniformi(&rs, n, _state); - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - bl.ptr.p_double[i] = hqrndnormal(&rs, _state); - bu.ptr.p_double[i] = bl.ptr.p_double[i]+hqrnduniformr(&rs, _state); - x0.ptr.p_double[i] = 1+hqrnduniformr(&rs, _state); - } - ae_matrix_set_length(&c, m, n+1, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n; j++) - { - c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - if( tmpkind==0 ) - { - minlmcreatev(n, m, &x0, 10*epsx, &state, _state); - } - if( tmpkind==1 ) - { - minlmcreatevj(n, m, &x0, &state, _state); - } - minlmsetcond(&state, epsx, 0, _state); - minlmsetbc(&state, &bl, &bu, _state); - while(minlmiteration(&state, _state)) - { - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_less(state.x.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:728"); - ae_set_error_flag(errorflag, ae_fp_greater(state.x.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:729"); - } - if( state.needfi ) - { - testminlmunit_testfunc1(n, m, &c, &state.x, &v, ae_false, &state.fi, ae_true, &state.j, ae_false, _state); - continue; - } - if( state.needfij ) - { - testminlmunit_testfunc1(n, m, &c, &state.x, &v, ae_false, &state.fi, ae_true, &state.j, ae_true, _state); - continue; - } - ae_assert(ae_false, "minlm test: integrity check failed", _state); - } - minlmresults(&state, &x, &rep, _state); - ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:744"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - testminlmunit_testfunc1(n, m, &c, &x, &f0, ae_true, &state.fi, ae_false, &state.j, ae_false, _state); - ae_vector_set_length(&x1, n, _state); - h = 0.001; - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_less(x.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:753"); - ae_set_error_flag(errorflag, ae_fp_greater(x.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:754"); - if( ae_fp_greater_eq(x.ptr.p_double[i]+h,bl.ptr.p_double[i])&&ae_fp_less_eq(x.ptr.p_double[i]+h,bu.ptr.p_double[i]) ) - { - for(j=0; j<=n-1; j++) - { - x1.ptr.p_double[j] = x.ptr.p_double[j]; - } - x1.ptr.p_double[i] = x.ptr.p_double[i]+h; - testminlmunit_testfunc1(n, m, &c, &x1, &f1, ae_true, &state.fi, ae_false, &state.j, ae_false, _state); - ae_set_error_flag(errorflag, ae_fp_less(f1,f0*(1-tolf)), __FILE__, __LINE__, "testminlmunit.ap:763"); - } - if( ae_fp_greater_eq(x.ptr.p_double[i]-h,bl.ptr.p_double[i])&&ae_fp_less_eq(x.ptr.p_double[i]-h,bu.ptr.p_double[i]) ) - { - for(j=0; j<=n-1; j++) - { - x1.ptr.p_double[j] = x.ptr.p_double[j]; - } - x1.ptr.p_double[i] = x.ptr.p_double[i]-h; - testminlmunit_testfunc1(n, m, &c, &x1, &f1, ae_true, &state.fi, ae_false, &state.j, ae_false, _state); - ae_set_error_flag(errorflag, ae_fp_less(f1,f0*(1-tolf)), __FILE__, __LINE__, "testminlmunit.ap:773"); - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Test for linearly constrained problems. -On failure sets error flag, leaves it unchanged on success. -*************************************************************************/ -static void testminlmunit_testlc(ae_bool* errorflag, ae_state *_state) -{ - ae_frame _frame_block; - minlmstate state; - minlmreport rep; - ae_vector bl; - ae_vector bu; - ae_int_t n; - ae_int_t m; - ae_int_t m1; - ae_int_t m2; - ae_vector x0; - ae_vector x; - ae_vector xe; - ae_vector x1; - ae_vector x12; - ae_vector d; - ae_matrix rawc; - ae_vector rawct; - ae_int_t rawccnt; - ae_matrix c; - ae_matrix c12; - ae_matrix z; - ae_int_t trialidx; - ae_int_t i; - ae_int_t j; - double v; - double h; - ae_int_t optkind; - hqrndstate rs; - double epsx; - double xtol; - double tolf; - double f0; - double f1; - ae_bool bflag; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&bl, 0, sizeof(bl)); - memset(&bu, 0, sizeof(bu)); - memset(&x0, 0, sizeof(x0)); - memset(&x, 0, sizeof(x)); - memset(&xe, 0, sizeof(xe)); - memset(&x1, 0, sizeof(x1)); - memset(&x12, 0, sizeof(x12)); - memset(&d, 0, sizeof(d)); - memset(&rawc, 0, sizeof(rawc)); - memset(&rawct, 0, sizeof(rawct)); - memset(&c, 0, sizeof(c)); - memset(&c12, 0, sizeof(c12)); - memset(&z, 0, sizeof(z)); - memset(&rs, 0, sizeof(rs)); - _minlmstate_init(&state, _state, ae_true); - _minlmreport_init(&rep, _state, ae_true); - ae_vector_init(&bl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xe, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x12, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&rawc, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rawct, 0, DT_INT, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c12, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Minimize - * - * [ [ ]2 ] - * SUM_i[ SUM_j[ (0.1*x_j+power(x_j,3))*c_ij ] ] - * [ [ ] ] - * - * subject to mix of box and linear inequality constraints on x_j - * - * We check correctness of solution by sampling a few random points - * around one returned by optimizer, and comparing function value - * with target. Sampling is performed with respect to inequality - * constraints. - */ - epsx = 1.0E-12; - xtol = 1.0E-8; - tolf = 1.0E-10; - for(optkind=0; optkind<=1; optkind++) - { - for(n=5; n<=20; n++) - { - - /* - * Generate problem - */ - m = n+hqrnduniformi(&rs, n, _state); - ae_vector_set_length(&bl, n, _state); - ae_vector_set_length(&bu, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - bl.ptr.p_double[i] = hqrndnormal(&rs, _state); - bu.ptr.p_double[i] = bl.ptr.p_double[i]+hqrnduniformr(&rs, _state); - x0.ptr.p_double[i] = bl.ptr.p_double[i]+(bu.ptr.p_double[i]-bl.ptr.p_double[i])*hqrnduniformr(&rs, _state); - } - ae_matrix_set_length(&c, m, n+1, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n; j++) - { - c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - ae_assert(n>=5, "Assertion failed", _state); - rawccnt = 3; - ae_matrix_set_length(&rawc, rawccnt, n+1, _state); - ae_vector_set_length(&rawct, rawccnt, _state); - for(i=0; i<=rawccnt-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - rawc.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - v = v+x0.ptr.p_double[j]*rawc.ptr.pp_double[i][j]; - } - rawc.ptr.pp_double[i][n] = v; - rawct.ptr.p_int[i] = 2*hqrnduniformi(&rs, 2, _state)-1; - } - - /* - * Solve - */ - if( optkind==0 ) - { - minlmcreatev(n, m, &x0, 10*epsx, &state, _state); - } - if( optkind==1 ) - { - minlmcreatevj(n, m, &x0, &state, _state); - } - minlmsetcond(&state, epsx, 0, _state); - minlmsetbc(&state, &bl, &bu, _state); - minlmsetlc(&state, &rawc, &rawct, rawccnt, _state); - while(minlmiteration(&state, _state)) - { - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_less(state.x.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:878"); - ae_set_error_flag(errorflag, ae_fp_greater(state.x.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:879"); - } - if( state.needfi ) - { - testminlmunit_testfunc1(n, m, &c, &state.x, &v, ae_false, &state.fi, ae_true, &state.j, ae_false, _state); - continue; - } - if( state.needfij ) - { - testminlmunit_testfunc1(n, m, &c, &state.x, &v, ae_false, &state.fi, ae_true, &state.j, ae_true, _state); - continue; - } - ae_assert(ae_false, "minlm test: integrity check failed", _state); - } - minlmresults(&state, &x, &rep, _state); - ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:894"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - - /* - * Test feasibility w.r.t. box and linear inequality constraints - */ - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_less(x.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:903"); - ae_set_error_flag(errorflag, ae_fp_greater(x.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:904"); - } - for(i=0; i<=rawccnt-1; i++) - { - v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = v-rawc.ptr.pp_double[i][n]; - if( rawct.ptr.p_int[i]>0 ) - { - ae_set_error_flag(errorflag, ae_fp_less(v,-xtol), __FILE__, __LINE__, "testminlmunit.ap:911"); - } - if( rawct.ptr.p_int[i]<0 ) - { - ae_set_error_flag(errorflag, ae_fp_greater(v,xtol), __FILE__, __LINE__, "testminlmunit.ap:913"); - } - } - - /* - * Make several random trial steps and: - * 0) generate small random trial step - * 1) if step is infeasible, skip to next trial - * 2) compare function value in the trial point against one in other points - */ - testminlmunit_testfunc1(n, m, &c, &x, &f0, ae_true, &state.fi, ae_false, &state.j, ae_false, _state); - ae_vector_set_length(&x1, n, _state); - for(trialidx=0; trialidx<=10*n; trialidx++) - { - h = 0.001; - for(i=0; i<=n-1; i++) - { - do - { - x1.ptr.p_double[i] = x.ptr.p_double[i]+(hqrnduniformr(&rs, _state)*2-1)*h; - } - while(!(ae_fp_greater_eq(x1.ptr.p_double[i],bl.ptr.p_double[i])&&ae_fp_less_eq(x1.ptr.p_double[i],bu.ptr.p_double[i]))); - } - bflag = ae_false; - for(i=0; i<=rawccnt-1; i++) - { - ae_assert(rawct.ptr.p_int[i]!=0, "Assertion failed", _state); - v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = v-rawc.ptr.pp_double[i][n]; - bflag = bflag||(rawct.ptr.p_int[i]>0&&ae_fp_less(v,(double)(0))); - bflag = bflag||(rawct.ptr.p_int[i]<0&&ae_fp_greater(v,(double)(0))); - } - if( bflag ) - { - continue; - } - testminlmunit_testfunc1(n, m, &c, &x1, &f1, ae_true, &state.fi, ae_false, &state.j, ae_false, _state); - ae_set_error_flag(errorflag, ae_fp_less(f1,f0*(1-tolf)), __FILE__, __LINE__, "testminlmunit.ap:950"); - } - } - } - - /* - * Minimize - * - * [ [ ]2 ] - * SUM_i[ SUM_j[ (0.1*x_j+power(x_j,3))*c_ij ] ] - * [ [ ] ] - * - * subject to linear EQUALITY constraints on x_j. - * - * We check correctness of solution by sampling a few random points - * around one returned by optimizer, and comparing function value - * with target. Sampling is performed with respect to equality - * constraints. In order to simplify algorithm we use orthogonal - * equality constraints. - * - * NOTE: we solve problem using VJ mode (analytic Jacobian) because - * roundoff errors from numerical differentiation sometimes - * prevent us from converging with good precision. - */ - epsx = 1.0E-12; - xtol = 1.0E-8; - tolf = 1.0E-10; - optkind = 1; - for(n=10; n<=20; n++) - { - - /* - * Generate problem - */ - m = n+hqrnduniformi(&rs, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_matrix_set_length(&c, m, n+1, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n; j++) - { - c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - ae_assert(n>=5, "Assertion failed", _state); - rawccnt = 1+hqrnduniformi(&rs, 5, _state); - rmatrixrndorthogonal(n, &z, _state); - ae_matrix_set_length(&rawc, rawccnt, n+1, _state); - ae_vector_set_length(&rawct, rawccnt, _state); - for(i=0; i<=rawccnt-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - rawc.ptr.pp_double[i][j] = z.ptr.pp_double[i][j]; - v = v+x0.ptr.p_double[j]*rawc.ptr.pp_double[i][j]; - } - rawc.ptr.pp_double[i][n] = v; - rawct.ptr.p_int[i] = 0; - } - - /* - * Solve - */ - if( optkind==0 ) - { - minlmcreatev(n, m, &x0, 1.0E-12, &state, _state); - } - if( optkind==1 ) - { - minlmcreatevj(n, m, &x0, &state, _state); - } - minlmsetcond(&state, epsx, 0, _state); - minlmsetlc(&state, &rawc, &rawct, rawccnt, _state); - while(minlmiteration(&state, _state)) - { - if( state.needfi ) - { - testminlmunit_testfunc1(n, m, &c, &state.x, &v, ae_false, &state.fi, ae_true, &state.j, ae_false, _state); - continue; - } - if( state.needfij ) - { - testminlmunit_testfunc1(n, m, &c, &state.x, &v, ae_false, &state.fi, ae_true, &state.j, ae_true, _state); - continue; - } - ae_assert(ae_false, "minlm test: integrity check failed", _state); - } - minlmresults(&state, &x, &rep, _state); - ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:1031"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - - /* - * Test feasibility w.r.t. linear equality constraints - */ - for(i=0; i<=rawccnt-1; i++) - { - v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - v = v-rawc.ptr.pp_double[i][n]; - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v, _state),xtol), __FILE__, __LINE__, "testminlmunit.ap:1042"); - } - - /* - * Make several random trial steps and: - * 0) generate small random trial step - * 1) project it onto equality constrained subspace - * 2) compare function value in the trial point against one in other points - */ - testminlmunit_testfunc1(n, m, &c, &x, &f0, ae_true, &state.fi, ae_false, &state.j, ae_false, _state); - ae_vector_set_length(&x1, n, _state); - for(trialidx=0; trialidx<=10*n; trialidx++) - { - h = 0.001; - for(i=0; i<=n-1; i++) - { - x1.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - for(i=0; i<=rawccnt-1; i++) - { - v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_subd(&x1.ptr.p_double[0], 1, &rawc.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v); - } - v = ae_v_dotproduct(&x1.ptr.p_double[0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_assert(ae_fp_greater(v,(double)(0)), "Assertion failed", _state); - v = h/ae_sqrt(v, _state); - ae_v_muld(&x1.ptr.p_double[0], 1, ae_v_len(0,n-1), v); - ae_v_add(&x1.ptr.p_double[0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - testminlmunit_testfunc1(n, m, &c, &x1, &f1, ae_true, &state.fi, ae_false, &state.j, ae_false, _state); - ae_set_error_flag(errorflag, ae_fp_less(f1,f0*(1-tolf)), __FILE__, __LINE__, "testminlmunit.ap:1072"); - } - } - - /* - * Minimize - * - * [ [ ]2 ] [ [ ]2 ] - * SUM_i[ SUM_j[ (0.1*x_j+power(x0_j,3))*c0_ij ] ] + SUM_i[ SUM_j[ (0.1*x_j+power(x1_j,3))*c1_ij ] ] - * [ [ ] ] [ [ ] ] - * - * for two sets of unknowns (x0_j and x1_j) and two sets of - * coefficients (c0_ij and c1_ij, M1*N and M2*N matrices) subject - * to equality constraint - * - * x0_j=x1_j for all j - * - * Such optimization problem arises when we fit same model to - * two distinct datasets and want to share SOME of coefficients - * between fits. If we share ALL coefficients, it is equal to - * fitting one model to combination of two datasets. - * - * Our test checks that such "combined" 2N-dimensional problem - * solved with general linear constraints which "glue" two datasets - * together returns same answer as N-dimensional problem on (M1+M2)-point - * dataset. - * - * NOTE: we solve problem using VJ mode (analytic Jacobian) because - * roundoff errors from numerical differentiation prevent us - * from converging with good precision. - */ - epsx = 1.0E-12; - for(n=5; n<=20; n++) - { - - /* - * Generate problems - */ - m1 = n+hqrnduniformi(&rs, n, _state); - m2 = n+hqrnduniformi(&rs, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&x12, 2*n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = hqrndnormal(&rs, _state); - x12.ptr.p_double[2*i+0] = hqrndnormal(&rs, _state); - x12.ptr.p_double[2*i+1] = hqrndnormal(&rs, _state); - } - ae_matrix_set_length(&c, m1+m2, n+1, _state); - ae_matrix_set_length(&c12, m1+m2, 2*n+1, _state); - for(i=0; i<=m1+m2-1; i++) - { - for(j=0; j<=2*n; j++) - { - c12.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=m1+m2-1; i++) - { - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - if( iv_nan; - if( i==1 ) - { - v = _state->v_posinf; - } - if( i==2 ) - { - v = _state->v_neginf; - } - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - state.fi.ptr.p_double[ae_randominteger(m, _state)] = v; - } - else - { - state.j.ptr.pp_double[ae_randominteger(m, _state)][ae_randominteger(n, _state)] = v; - } - inc(&spoilcnt, _state); - } - continue; - } - if( state.needfi ) - { - for(i=0; i<=n-2; i++) - { - state.fi.ptr.p_double[2*i+0] = s*(state.x.ptr.p_double[i+1]-ae_sqr(state.x.ptr.p_double[i], _state)); - state.fi.ptr.p_double[2*i+1] = 1-state.x.ptr.p_double[i]; - } - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - mx = ae_maxreal(mx, ae_fabs(state.x.ptr.p_double[i]-1, _state), _state); - } - if( ae_fp_less(mx,1.0E-2) ) - { - i = ae_randominteger(3, _state); - v = _state->v_nan; - if( i==1 ) - { - v = _state->v_posinf; - } - if( i==2 ) - { - v = _state->v_neginf; - } - state.fi.ptr.p_double[ae_randominteger(m, _state)] = v; - inc(&spoilcnt, _state); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minlmresults(&state, &x, &rep, _state); - ae_set_error_flag(errorflag, rep.terminationtype!=-8, __FILE__, __LINE__, "testminlmunit.ap:1513"); - ae_set_error_flag(errorflag, spoilcnt!=1, __FILE__, __LINE__, "testminlmunit.ap:1514"); - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests OptGuard - -On failure sets error flag. -*************************************************************************/ -static void testminlmunit_testoptguard(ae_bool* wereerrors, - ae_state *_state) -{ - ae_frame _frame_block; - hqrndstate rs; - double v; - minlmstate state; - minlmreport rep; - optguardreport ogrep; - ae_int_t i; - ae_int_t j; - ae_int_t n; - ae_matrix a; - ae_matrix a1; - ae_vector s; - ae_vector x0; - ae_vector x1; - ae_vector bndl; - ae_vector bndu; - double diffstep; - ae_int_t defecttype; - ae_int_t funcidx; - ae_int_t varidx; - ae_int_t skind; - ae_matrix jactrue; - ae_matrix jacdefect; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&ogrep, 0, sizeof(ogrep)); - memset(&a, 0, sizeof(a)); - memset(&a1, 0, sizeof(a1)); - memset(&s, 0, sizeof(s)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&jactrue, 0, sizeof(jactrue)); - memset(&jacdefect, 0, sizeof(jacdefect)); - _hqrndstate_init(&rs, _state, ae_true); - _minlmstate_init(&state, _state, ae_true); - _minlmreport_init(&rep, _state, ae_true); - _optguardreport_init(&ogrep, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&jactrue, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&jacdefect, 0, 0, DT_REAL, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Check that gradient verification is disabled by default: - * gradient checking for bad problem must return nothing - */ - n = 10; - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 1.0+0.1*i; - } - spdmatrixrndcond(n, 1.0E3, &a, _state); - spdmatrixrndcond(n, 1.0E3, &a1, _state); - minlmcreatevj(n, 1, &x0, &state, _state); - minlmsetcond(&state, 1.0E-9, 10, _state); - while(minlmiteration(&state, _state)) - { - if( state.needfij ) - { - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*v; - } - for(i=0; i<=n-1; i++) - { - state.j.ptr.pp_double[0][i] = (double)(0); - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minlmresults(&state, &x1, &rep, _state); - minlmoptguardresults(&state, &ogrep, _state); - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:1575"); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminlmunit.ap:1576"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(wereerrors, ogrep.badgradxbase.cnt!=0, __FILE__, __LINE__, "testminlmunit.ap:1579"); - ae_set_error_flag(wereerrors, ogrep.badgraduser.rows!=0, __FILE__, __LINE__, "testminlmunit.ap:1580"); - ae_set_error_flag(wereerrors, ogrep.badgraduser.cols!=0, __FILE__, __LINE__, "testminlmunit.ap:1581"); - ae_set_error_flag(wereerrors, ogrep.badgradnum.rows!=0, __FILE__, __LINE__, "testminlmunit.ap:1582"); - ae_set_error_flag(wereerrors, ogrep.badgradnum.cols!=0, __FILE__, __LINE__, "testminlmunit.ap:1583"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(wereerrors, ogrep.badgradsuspected, __FILE__, __LINE__, "testminlmunit.ap:1586"); - ae_set_error_flag(wereerrors, ogrep.badgradfidx!=-1, __FILE__, __LINE__, "testminlmunit.ap:1587"); - ae_set_error_flag(wereerrors, ogrep.badgradvidx!=-1, __FILE__, __LINE__, "testminlmunit.ap:1588"); - - /* - * Test gradient checking functionality, try various - * defect types: - * * accidental zeroing of some gradient component - * * accidental addition of 1.0 to some component - * * accidental multiplication by 2.0 - * Try distorting both target and constraints. - */ - diffstep = 0.001; - n = 10; - for(skind=0; skind<=1; skind++) - { - for(funcidx=0; funcidx<=1; funcidx++) - { - for(defecttype=-1; defecttype<=2; defecttype++) - { - varidx = hqrnduniformi(&rs, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&s, n, _state); - ae_vector_set_length(&bndl, n, _state); - ae_vector_set_length(&bndu, n, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = ae_pow((double)(10), skind*(30*hqrnduniformr(&rs, _state)-15), _state); - x0.ptr.p_double[i] = (1.0+0.1*i)*s.ptr.p_double[i]; - j = hqrnduniformi(&rs, 3, _state); - bndl.ptr.p_double[i] = -100*s.ptr.p_double[i]; - bndu.ptr.p_double[i] = 100*s.ptr.p_double[i]; - if( j==1 ) - { - bndl.ptr.p_double[i] = x0.ptr.p_double[i]; - } - if( j==2 ) - { - bndu.ptr.p_double[i] = x0.ptr.p_double[i]; - } - } - spdmatrixrndcond(n, 1.0E3, &a, _state); - spdmatrixrndcond(n, 1.0E3, &a1, _state); - minlmcreatevj(n, 2, &x0, &state, _state); - minlmoptguardgradient(&state, diffstep, _state); - minlmsetcond(&state, 1.0E-9, 10, _state); - minlmsetscale(&state, &s, _state); - minlmsetbc(&state, &bndl, &bndu, _state); - while(minlmiteration(&state, _state)) - { - if( state.needfi||state.needfij ) - { - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(wereerrors, ae_fp_less(state.x.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:1637"); - ae_set_error_flag(wereerrors, ae_fp_greater(state.x.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:1638"); - } - state.fi.ptr.p_double[0] = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*(state.x.ptr.p_double[i]/s.ptr.p_double[i])*v; - if( state.needfij ) - { - state.j.ptr.pp_double[0][i] = v; - } - } - state.fi.ptr.p_double[1] = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+state.x.ptr.p_double[j]/s.ptr.p_double[j]*a1.ptr.pp_double[i][j]; - } - state.fi.ptr.p_double[1] = state.fi.ptr.p_double[1]+0.5*(state.x.ptr.p_double[i]/s.ptr.p_double[i])*v; - if( state.needfij ) - { - state.j.ptr.pp_double[1][i] = v; - } - } - if( state.needfij ) - { - if( defecttype==0 ) - { - state.j.ptr.pp_double[funcidx][varidx] = (double)(0); - } - if( defecttype==1 ) - { - state.j.ptr.pp_double[funcidx][varidx] = state.j.ptr.pp_double[funcidx][varidx]+1; - } - if( defecttype==2 ) - { - state.j.ptr.pp_double[funcidx][varidx] = state.j.ptr.pp_double[funcidx][varidx]*2; - } - } - if( state.needfij ) - { - for(i=0; i<=n-1; i++) - { - state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]/s.ptr.p_double[i]; - state.j.ptr.pp_double[1][i] = state.j.ptr.pp_double[1][i]/s.ptr.p_double[i]; - } - } - continue; - } - ae_assert(ae_false, "Assertion failed", _state); - } - minlmresults(&state, &x1, &rep, _state); - minlmoptguardresults(&state, &ogrep, _state); - - /* - * Check that something is returned - */ - ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:1695"); - ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminlmunit.ap:1696"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - - /* - * Compute reference values for true and spoiled Jacobian at X0 - */ - ae_set_error_flag(wereerrors, !isfinitevector(&ogrep.badgradxbase, n, _state), __FILE__, __LINE__, "testminlmunit.ap:1703"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&jactrue, 2, n, _state); - ae_matrix_set_length(&jacdefect, 2, n, _state); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+ogrep.badgradxbase.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j]; - } - jactrue.ptr.pp_double[0][i] = v; - jacdefect.ptr.pp_double[0][i] = v; - } - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+ogrep.badgradxbase.ptr.p_double[j]/s.ptr.p_double[j]*a1.ptr.pp_double[i][j]; - } - jactrue.ptr.pp_double[1][i] = v; - jacdefect.ptr.pp_double[1][i] = v; - } - if( defecttype==0 ) - { - jacdefect.ptr.pp_double[funcidx][varidx] = (double)(0); - } - if( defecttype==1 ) - { - jacdefect.ptr.pp_double[funcidx][varidx] = jacdefect.ptr.pp_double[funcidx][varidx]+1; - } - if( defecttype==2 ) - { - jacdefect.ptr.pp_double[funcidx][varidx] = jacdefect.ptr.pp_double[funcidx][varidx]*2; - } - for(i=0; i<=n-1; i++) - { - jactrue.ptr.pp_double[0][i] = jactrue.ptr.pp_double[0][i]/s.ptr.p_double[i]; - jactrue.ptr.pp_double[1][i] = jactrue.ptr.pp_double[1][i]/s.ptr.p_double[i]; - jacdefect.ptr.pp_double[0][i] = jacdefect.ptr.pp_double[0][i]/s.ptr.p_double[i]; - jacdefect.ptr.pp_double[1][i] = jacdefect.ptr.pp_double[1][i]/s.ptr.p_double[i]; - } - - /* - * Check OptGuard report - */ - ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgraduser, 2, n, _state), __FILE__, __LINE__, "testminlmunit.ap:1741"); - ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgradnum, 2, n, _state), __FILE__, __LINE__, "testminlmunit.ap:1742"); - if( *wereerrors ) - { - ae_frame_leave(_state); - return; - } - if( defecttype>=0 ) - { - ae_set_error_flag(wereerrors, !ogrep.badgradsuspected, __FILE__, __LINE__, "testminlmunit.ap:1747"); - ae_set_error_flag(wereerrors, ogrep.badgradfidx!=funcidx, __FILE__, __LINE__, "testminlmunit.ap:1748"); - ae_set_error_flag(wereerrors, ogrep.badgradvidx!=varidx, __FILE__, __LINE__, "testminlmunit.ap:1749"); - } - else - { - ae_set_error_flag(wereerrors, ogrep.badgradsuspected, __FILE__, __LINE__, "testminlmunit.ap:1753"); - ae_set_error_flag(wereerrors, ogrep.badgradfidx!=-1, __FILE__, __LINE__, "testminlmunit.ap:1754"); - ae_set_error_flag(wereerrors, ogrep.badgradvidx!=-1, __FILE__, __LINE__, "testminlmunit.ap:1755"); - } - for(i=0; i<=1; i++) - { - for(j=0; j<=n-1; j++) - { - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jactrue.ptr.pp_double[i][j]-ogrep.badgradnum.ptr.pp_double[i][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testminlmunit.ap:1760"); - ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jacdefect.ptr.pp_double[i][j]-ogrep.badgraduser.ptr.pp_double[i][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testminlmunit.ap:1761"); - } - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Asserts that State fields are consistent with RKind. -Returns False otherwise. - -RKind is an algorithm selector: -* -2 = V, AccType=1 -* -1 = V, AccType=0 -* 0 = FJ -* 1 = FGJ -* 2 = FGH -* 3 = VJ, AccType=0 -* 4 = VJ, AccType=1 -* 5 = VJ, AccType=2 - -*************************************************************************/ -static ae_bool testminlmunit_rkindvsstatecheck(ae_int_t rkind, - minlmstate* state, - ae_state *_state) -{ - ae_int_t nset; - ae_bool result; - - - nset = 0; - if( state->needfi ) - { - nset = nset+1; - } - if( state->needf ) - { - nset = nset+1; - } - if( state->needfg ) - { - nset = nset+1; - } - if( state->needfij ) - { - nset = nset+1; - } - if( state->needfgh ) - { - nset = nset+1; - } - if( state->xupdated ) - { - nset = nset+1; - } - if( nset!=1 ) - { - result = ae_false; - return result; - } - if( rkind==-2 ) - { - result = state->needfi||state->xupdated; - return result; - } - if( rkind==-1 ) - { - result = state->needfi||state->xupdated; - return result; - } - if( rkind==0 ) - { - result = (state->needf||state->needfij)||state->xupdated; - return result; - } - if( rkind==1 ) - { - result = ((state->needf||state->needfij)||state->needfg)||state->xupdated; - return result; - } - if( rkind==2 ) - { - result = ((state->needf||state->needfg)||state->needfgh)||state->xupdated; - return result; - } - if( rkind==3 ) - { - result = (state->needfi||state->needfij)||state->xupdated; - return result; - } - if( rkind==4 ) - { - result = (state->needfi||state->needfij)||state->xupdated; - return result; - } - if( rkind==5 ) - { - result = (state->needfi||state->needfij)||state->xupdated; - return result; - } - result = ae_false; - return result; -} - - -/************************************************************************* -Calculates FI/F/G/H for problem min(||Ax-b||) -*************************************************************************/ -static void testminlmunit_axmb(minlmstate* state, - /* Real */ ae_matrix* a, - /* Real */ ae_vector* b, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - - - if( (state->needf||state->needfg)||state->needfgh ) - { - state->f = (double)(0); - } - if( state->needfg||state->needfgh ) - { - for(i=0; i<=n-1; i++) - { - state->g.ptr.p_double[i] = (double)(0); - } - } - if( state->needfgh ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - state->h.ptr.pp_double[i][j] = (double)(0); - } - } - } - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&a->ptr.pp_double[i][0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( (state->needf||state->needfg)||state->needfgh ) - { - state->f = state->f+ae_sqr(v-b->ptr.p_double[i], _state); - } - if( state->needfg||state->needfgh ) - { - for(j=0; j<=n-1; j++) - { - state->g.ptr.p_double[j] = state->g.ptr.p_double[j]+2*(v-b->ptr.p_double[i])*a->ptr.pp_double[i][j]; - } - } - if( state->needfgh ) - { - for(j=0; j<=n-1; j++) - { - for(k=0; k<=n-1; k++) - { - state->h.ptr.pp_double[j][k] = state->h.ptr.pp_double[j][k]+2*a->ptr.pp_double[i][j]*a->ptr.pp_double[i][k]; - } - } - } - if( state->needfi ) - { - state->fi.ptr.p_double[i] = v-b->ptr.p_double[i]; - } - if( state->needfij ) - { - state->fi.ptr.p_double[i] = v-b->ptr.p_double[i]; - ae_v_move(&state->j.ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - } - } -} - - -/************************************************************************* -This function tries to reproduce previously fixed bugs; in case of bug -being present sets Err to True; leaves it unchanged otherwise. -*************************************************************************/ -static void testminlmunit_tryreproducefixedbugs(ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - minlmstate s; - minlmreport rep; - ae_vector bl; - ae_vector bu; - ae_vector x; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&bl, 0, sizeof(bl)); - memset(&bu, 0, sizeof(bu)); - memset(&x, 0, sizeof(x)); - _minlmstate_init(&s, _state, ae_true); - _minlmreport_init(&rep, _state, ae_true); - ae_vector_init(&bl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - - - /* - * Reproduce bug reported by ISS: - * when solving bound constrained problem with numerical differentiation - * and starting from infeasible point, we won't stop at the feasible point - */ - ae_vector_set_length(&x, 2, _state); - ae_vector_set_length(&bl, 2, _state); - ae_vector_set_length(&bu, 2, _state); - x.ptr.p_double[0] = 2.0; - bl.ptr.p_double[0] = -1.0; - bu.ptr.p_double[0] = 1.0; - x.ptr.p_double[1] = 2.0; - bl.ptr.p_double[1] = -1.0; - bu.ptr.p_double[1] = 1.0; - minlmcreatev(2, 2, &x, 0.001, &s, _state); - minlmsetbc(&s, &bl, &bu, _state); - while(minlmiteration(&s, _state)) - { - if( s.needfi ) - { - s.fi.ptr.p_double[0] = ae_sqr(s.x.ptr.p_double[0], _state); - s.fi.ptr.p_double[1] = ae_sqr(s.x.ptr.p_double[1], _state); - } - } - minlmresults(&s, &x, &rep, _state); - ae_set_error_flag(err, ((ae_fp_less(x.ptr.p_double[0],bl.ptr.p_double[0])||ae_fp_greater(x.ptr.p_double[0],bu.ptr.p_double[0]))||ae_fp_less(x.ptr.p_double[1],bl.ptr.p_double[1]))||ae_fp_greater(x.ptr.p_double[1],bu.ptr.p_double[1]), __FILE__, __LINE__, "testminlmunit.ap:1923"); - ae_frame_leave(_state); -} - - -/************************************************************************* -Test function 1: - - F(N, M, C, X) = SUM( f_i^2 ) - f_i = SUM( (power(x_j,3)+alpha*x_j)*c_ij ) -*************************************************************************/ -static void testminlmunit_testfunc1(ae_int_t n, - ae_int_t m, - /* Real */ ae_matrix* c, - /* Real */ ae_vector* x, - double* f, - ae_bool needf, - /* Real */ ae_vector* fi, - ae_bool needfi, - /* Real */ ae_matrix* jac, - ae_bool needjac, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - double alpha; - - - alpha = 0.01; - if( needf ) - { - *f = (double)(0); - } - for(i=0; i<=m-1; i++) - { - v = c->ptr.pp_double[i][n]; - for(j=0; j<=n-1; j++) - { - v = v+(alpha*x->ptr.p_double[j]+ae_pow(x->ptr.p_double[j], (double)(3), _state))*c->ptr.pp_double[i][j]; - if( needjac ) - { - jac->ptr.pp_double[i][j] = (alpha+3*ae_pow(x->ptr.p_double[j], (double)(2), _state))*c->ptr.pp_double[i][j]; - } - } - if( needfi ) - { - fi->ptr.p_double[i] = v; - } - if( needf ) - { - *f = *f+v*v; - } - } -} - - - -static void testevdunit_rmatrixfillsparsea(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double sparcity, - double diagmag, - ae_state *_state); -static void testevdunit_cmatrixfillsparsea(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double sparcity, - double diagmag, - ae_state *_state); -static void testevdunit_rmatrixsymmetricsplit(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_matrix* al, - /* Real */ ae_matrix* au, - ae_state *_state); -static void testevdunit_cmatrixhermitiansplit(/* Complex */ ae_matrix* a, - ae_int_t n, - /* Complex */ ae_matrix* al, - /* Complex */ ae_matrix* au, - ae_state *_state); -static void testevdunit_unset2d(/* Real */ ae_matrix* a, - ae_state *_state); -static void testevdunit_cunset2d(/* Complex */ ae_matrix* a, - ae_state *_state); -static void testevdunit_unset1d(/* Real */ ae_vector* a, - ae_state *_state); -static double testevdunit_tdtestproduct(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - /* Real */ ae_matrix* z, - /* Real */ ae_vector* lambdav, - ae_state *_state); -static double testevdunit_testproduct(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_matrix* z, - /* Real */ ae_vector* lambdav, - ae_state *_state); -static double testevdunit_testort(/* Real */ ae_matrix* z, - ae_int_t n, - ae_state *_state); -static double testevdunit_testcproduct(/* Complex */ ae_matrix* a, - ae_int_t n, - /* Complex */ ae_matrix* z, - /* Real */ ae_vector* lambdav, - ae_state *_state); -static double testevdunit_testcort(/* Complex */ ae_matrix* z, - ae_int_t n, - ae_state *_state); -static void testevdunit_testsevdproblem(/* Real */ ae_matrix* a, - /* Real */ ae_matrix* al, - /* Real */ ae_matrix* au, - ae_int_t n, - double threshold, - ae_bool* serrors, - ae_int_t* failc, - ae_int_t* runs, - ae_state *_state); -static void testevdunit_testhevdproblem(/* Complex */ ae_matrix* a, - /* Complex */ ae_matrix* al, - /* Complex */ ae_matrix* au, - ae_int_t n, - double threshold, - ae_bool* herrors, - ae_int_t* failc, - ae_int_t* runs, - ae_state *_state); -static void testevdunit_testsevdbiproblem(/* Real */ ae_matrix* afull, - /* Real */ ae_matrix* al, - /* Real */ ae_matrix* au, - ae_int_t n, - ae_bool distvals, - double threshold, - ae_bool* serrors, - ae_int_t* failc, - ae_int_t* runs, - ae_state *_state); -static void testevdunit_testhevdbiproblem(/* Complex */ ae_matrix* afull, - /* Complex */ ae_matrix* al, - /* Complex */ ae_matrix* au, - ae_int_t n, - ae_bool distvals, - double threshold, - ae_bool* herrors, - ae_int_t* failc, - ae_int_t* runs, - ae_state *_state); -static void testevdunit_testtdevdproblem(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - double threshold, - ae_bool* tderrors, - ae_state *_state); -static void testevdunit_testtdevdbiproblem(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_bool distvals, - double threshold, - ae_bool* serrors, - ae_int_t* failc, - ae_int_t* runs, - ae_state *_state); -static void testevdunit_testnsevdproblem(/* Real */ ae_matrix* a, - ae_int_t n, - double threshold, - ae_bool* nserrors, - ae_state *_state); -static void testevdunit_testevdset(ae_int_t n, - double threshold, - double bithreshold, - ae_int_t* failc, - ae_int_t* runs, - ae_bool* nserrors, - ae_bool* serrors, - ae_bool* herrors, - ae_bool* tderrors, - ae_bool* sbierrors, - ae_bool* hbierrors, - ae_bool* tdbierrors, - ae_state *_state); -static void testevdunit_testsisymm(ae_bool* errorflag, ae_state *_state); - - - - - -/************************************************************************* -Testing symmetric EVD subroutine -*************************************************************************/ -ae_bool testevd(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix ra; - ae_int_t n; - ae_int_t j; - ae_int_t failc; - ae_int_t runs; - double failthreshold; - double threshold; - double bithreshold; - ae_bool waserrors; - ae_bool nserrors; - ae_bool serrors; - ae_bool herrors; - ae_bool tderrors; - ae_bool sbierrors; - ae_bool hbierrors; - ae_bool tdbierrors; - ae_bool sisymmerrors; - ae_bool wfailed; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&ra, 0, sizeof(ra)); - ae_matrix_init(&ra, 0, 0, DT_REAL, _state, ae_true); - - failthreshold = 0.005; - threshold = 1.0E-8; - bithreshold = 1.0E-6; - nserrors = ae_false; - serrors = ae_false; - herrors = ae_false; - tderrors = ae_false; - sbierrors = ae_false; - hbierrors = ae_false; - tdbierrors = ae_false; - sisymmerrors = ae_false; - failc = 0; - runs = 0; - - /* - * Test subspace iteration solver - */ - testevdunit_testsisymm(&sisymmerrors, _state); - - /* - * Test dense solvers - */ - for(n=1; n<=ablasblocksize(&ra, _state); n++) - { - testevdunit_testevdset(n, threshold, bithreshold, &failc, &runs, &nserrors, &serrors, &herrors, &tderrors, &sbierrors, &hbierrors, &tdbierrors, _state); - } - for(j=2; j<=3; j++) - { - for(n=j*ablasblocksize(&ra, _state)-1; n<=j*ablasblocksize(&ra, _state)+1; n++) - { - testevdunit_testevdset(n, threshold, bithreshold, &failc, &runs, &nserrors, &serrors, &herrors, &tderrors, &sbierrors, &hbierrors, &tdbierrors, _state); - } - } - - /* - * report - */ - wfailed = ae_fp_greater((double)failc/(double)runs,failthreshold); - waserrors = (((((((nserrors||serrors)||herrors)||tderrors)||sbierrors)||hbierrors)||tdbierrors)||wfailed)||sisymmerrors; - if( !silent ) - { - printf("TESTING EVD UNIT\n"); - printf("DENSE DIRECT SOLVERS:\n"); - printf("* NS "); - if( !nserrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* S "); - if( !serrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* H "); - if( !herrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* TD "); - if( !tderrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* SBI "); - if( !sbierrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* HBI "); - if( !hbierrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* TDBI "); - if( !tdbierrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* FAILURE THRESHOLD "); - if( !wfailed ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("ITERATIVE SOLVERS:\n"); - printf("* SUBSPACE ITERATION (S) "); - if( !sisymmerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Sparse fill - -Sparcity - sparcity level, in [0,1] (0=dense matrix). -DiagMAg - magnitude of dense diagonal entries; zero value means that diagonal -is sparse too, non-zero value means that diagonal is dense -*************************************************************************/ -static void testevdunit_rmatrixfillsparsea(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double sparcity, - double diagmag, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_greater_eq(ae_randomreal(_state),sparcity) ) - { - a->ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - else - { - a->ptr.pp_double[i][j] = (double)(0); - } - } - } - if( ae_fp_greater(diagmag,(double)(0)) ) - { - for(i=0; i<=ae_minint(m, n, _state)-1; i++) - { - a->ptr.pp_double[i][i] = diagmag*(2*ae_randomreal(_state)-1); - } - } -} - - -/************************************************************************* -Sparse fill - -Sparcity - sparcity level, in [0,1] (0=dense matrix). -DiagMAg - magnitude of dense diagonal entries; zero value means that diagonal -is sparse too, non-zero value means that diagonal is dense -*************************************************************************/ -static void testevdunit_cmatrixfillsparsea(/* Complex */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - double sparcity, - double diagmag, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_greater_eq(ae_randomreal(_state),sparcity) ) - { - a->ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - a->ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - else - { - a->ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - } - if( ae_fp_greater(diagmag,(double)(0)) ) - { - for(i=0; i<=ae_minint(m, n, _state)-1; i++) - { - a->ptr.pp_complex[i][i].x = diagmag*(2*ae_randomreal(_state)-1); - a->ptr.pp_complex[i][i].y = diagmag*(2*ae_randomreal(_state)-1); - } - } -} - - -/************************************************************************* -Copies A to AL (lower half) and AU (upper half), filling unused parts by -random garbage. -*************************************************************************/ -static void testevdunit_rmatrixsymmetricsplit(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_matrix* al, - /* Real */ ae_matrix* au, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - for(i=0; i<=n-1; i++) - { - for(j=i+1; j<=n-1; j++) - { - al->ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - al->ptr.pp_double[j][i] = a->ptr.pp_double[i][j]; - au->ptr.pp_double[i][j] = a->ptr.pp_double[i][j]; - au->ptr.pp_double[j][i] = 2*ae_randomreal(_state)-1; - } - al->ptr.pp_double[i][i] = a->ptr.pp_double[i][i]; - au->ptr.pp_double[i][i] = a->ptr.pp_double[i][i]; - } -} - - -/************************************************************************* -Copies A to AL (lower half) and AU (upper half), filling unused parts by -random garbage. -*************************************************************************/ -static void testevdunit_cmatrixhermitiansplit(/* Complex */ ae_matrix* a, - ae_int_t n, - /* Complex */ ae_matrix* al, - /* Complex */ ae_matrix* au, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - - - for(i=0; i<=n-1; i++) - { - for(j=i+1; j<=n-1; j++) - { - al->ptr.pp_complex[i][j] = ae_complex_from_d(2*ae_randomreal(_state)-1); - al->ptr.pp_complex[j][i] = ae_c_conj(a->ptr.pp_complex[i][j], _state); - au->ptr.pp_complex[i][j] = a->ptr.pp_complex[i][j]; - au->ptr.pp_complex[j][i] = ae_complex_from_d(2*ae_randomreal(_state)-1); - } - al->ptr.pp_complex[i][i] = a->ptr.pp_complex[i][i]; - au->ptr.pp_complex[i][i] = a->ptr.pp_complex[i][i]; - } -} - - -/************************************************************************* -Unsets 2D array. -*************************************************************************/ -static void testevdunit_unset2d(/* Real */ ae_matrix* a, - ae_state *_state) -{ - - ae_matrix_clear(a); - - if( a->rows*a->cols>0 ) - { - ae_matrix_set_length(a, 1, 1, _state); - } -} - - -/************************************************************************* -Unsets 2D array. -*************************************************************************/ -static void testevdunit_cunset2d(/* Complex */ ae_matrix* a, - ae_state *_state) -{ - - - ae_matrix_set_length(a, 0+1, 0+1, _state); - a->ptr.pp_complex[0][0] = ae_complex_from_d(2*ae_randomreal(_state)-1); -} - - -/************************************************************************* -Unsets 1D array. -*************************************************************************/ -static void testevdunit_unset1d(/* Real */ ae_vector* a, - ae_state *_state) -{ - - ae_vector_clear(a); - - if( a->cnt>0 ) - { - ae_vector_set_length(a, 1, _state); - } -} - - -/************************************************************************* -Tests Z*Lambda*Z' against tridiag(D,E). -Returns relative error. -*************************************************************************/ -static double testevdunit_tdtestproduct(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - /* Real */ ae_matrix* z, - /* Real */ ae_vector* lambdav, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double mx; - double result; - - - result = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - - /* - * Calculate V = A[i,j], A = Z*Lambda*Z' - */ - v = (double)(0); - for(k=0; k<=n-1; k++) - { - v = v+z->ptr.pp_double[i][k]*lambdav->ptr.p_double[k]*z->ptr.pp_double[j][k]; - } - - /* - * Compare - */ - if( ae_iabs(i-j, _state)==0 ) - { - result = ae_maxreal(result, ae_fabs(v-d->ptr.p_double[i], _state), _state); - } - if( ae_iabs(i-j, _state)==1 ) - { - result = ae_maxreal(result, ae_fabs(v-e->ptr.p_double[ae_minint(i, j, _state)], _state), _state); - } - if( ae_iabs(i-j, _state)>1 ) - { - result = ae_maxreal(result, ae_fabs(v, _state), _state); - } - } - } - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - mx = ae_maxreal(mx, ae_fabs(d->ptr.p_double[i], _state), _state); - } - for(i=0; i<=n-2; i++) - { - mx = ae_maxreal(mx, ae_fabs(e->ptr.p_double[i], _state), _state); - } - if( ae_fp_eq(mx,(double)(0)) ) - { - mx = (double)(1); - } - result = result/mx; - return result; -} - - -/************************************************************************* -Tests Z*Lambda*Z' against A -Returns relative error. -*************************************************************************/ -static double testevdunit_testproduct(/* Real */ ae_matrix* a, - ae_int_t n, - /* Real */ ae_matrix* z, - /* Real */ ae_vector* lambdav, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double mx; - double result; - - - result = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - - /* - * Calculate V = A[i,j], A = Z*Lambda*Z' - */ - v = (double)(0); - for(k=0; k<=n-1; k++) - { - v = v+z->ptr.pp_double[i][k]*lambdav->ptr.p_double[k]*z->ptr.pp_double[j][k]; - } - - /* - * Compare - */ - result = ae_maxreal(result, ae_fabs(v-a->ptr.pp_double[i][j], _state), _state); - } - } - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - mx = ae_maxreal(mx, ae_fabs(a->ptr.pp_double[i][j], _state), _state); - } - } - if( ae_fp_eq(mx,(double)(0)) ) - { - mx = (double)(1); - } - result = result/mx; - return result; -} - - -/************************************************************************* -Tests Z*Z' against diag(1...1) -Returns absolute error. -*************************************************************************/ -static double testevdunit_testort(/* Real */ ae_matrix* z, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - double result; - - - result = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&z->ptr.pp_double[0][i], z->stride, &z->ptr.pp_double[0][j], z->stride, ae_v_len(0,n-1)); - if( i==j ) - { - v = v-1; - } - result = ae_maxreal(result, ae_fabs(v, _state), _state); - } - } - return result; -} - - -/************************************************************************* -Tests Z*Lambda*Z' against A -Returns relative error. -*************************************************************************/ -static double testevdunit_testcproduct(/* Complex */ ae_matrix* a, - ae_int_t n, - /* Complex */ ae_matrix* z, - /* Real */ ae_vector* lambdav, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_complex v; - double mx; - double result; - - - result = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - - /* - * Calculate V = A[i,j], A = Z*Lambda*Z' - */ - v = ae_complex_from_i(0); - for(k=0; k<=n-1; k++) - { - v = ae_c_add(v,ae_c_mul(ae_c_mul_d(z->ptr.pp_complex[i][k],lambdav->ptr.p_double[k]),ae_c_conj(z->ptr.pp_complex[j][k], _state))); - } - - /* - * Compare - */ - result = ae_maxreal(result, ae_c_abs(ae_c_sub(v,a->ptr.pp_complex[i][j]), _state), _state); - } - } - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - mx = ae_maxreal(mx, ae_c_abs(a->ptr.pp_complex[i][j], _state), _state); - } - } - if( ae_fp_eq(mx,(double)(0)) ) - { - mx = (double)(1); - } - result = result/mx; - return result; -} - - -/************************************************************************* -Tests Z*Z' against diag(1...1) -Returns absolute error. -*************************************************************************/ -static double testevdunit_testcort(/* Complex */ ae_matrix* z, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_complex v; - double result; - - - result = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_cdotproduct(&z->ptr.pp_complex[0][i], z->stride, "N", &z->ptr.pp_complex[0][j], z->stride, "Conj", ae_v_len(0,n-1)); - if( i==j ) - { - v = ae_c_sub_d(v,1); - } - result = ae_maxreal(result, ae_c_abs(v, _state), _state); - } - } - return result; -} - - -/************************************************************************* -Tests SEVD problem -*************************************************************************/ -static void testevdunit_testsevdproblem(/* Real */ ae_matrix* a, - /* Real */ ae_matrix* al, - /* Real */ ae_matrix* au, - ae_int_t n, - double threshold, - ae_bool* serrors, - ae_int_t* failc, - ae_int_t* runs, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector lambdav; - ae_vector lambdaref; - ae_matrix z; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&lambdav, 0, sizeof(lambdav)); - memset(&lambdaref, 0, sizeof(lambdaref)); - memset(&z, 0, sizeof(z)); - ae_vector_init(&lambdav, 0, DT_REAL, _state, ae_true); - ae_vector_init(&lambdaref, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true); - - - /* - * Test simple EVD: values and full vectors, lower A - */ - testevdunit_unset1d(&lambdaref, _state); - testevdunit_unset2d(&z, _state); - *runs = *runs+1; - if( !smatrixevd(al, n, 1, ae_false, &lambdaref, &z, _state) ) - { - *failc = *failc+1; - ae_frame_leave(_state); - return; - } - *serrors = *serrors||ae_fp_greater(testevdunit_testproduct(a, n, &z, &lambdaref, _state),threshold); - *serrors = *serrors||ae_fp_greater(testevdunit_testort(&z, n, _state),threshold); - for(i=0; i<=n-2; i++) - { - if( ae_fp_less(lambdaref.ptr.p_double[i+1],lambdaref.ptr.p_double[i]) ) - { - *serrors = ae_true; - ae_frame_leave(_state); - return; - } - } - - /* - * Test simple EVD: values and full vectors, upper A - */ - testevdunit_unset1d(&lambdav, _state); - testevdunit_unset2d(&z, _state); - *runs = *runs+1; - if( !smatrixevd(au, n, 1, ae_true, &lambdav, &z, _state) ) - { - *failc = *failc+1; - ae_frame_leave(_state); - return; - } - *serrors = *serrors||ae_fp_greater(testevdunit_testproduct(a, n, &z, &lambdav, _state),threshold); - *serrors = *serrors||ae_fp_greater(testevdunit_testort(&z, n, _state),threshold); - for(i=0; i<=n-2; i++) - { - if( ae_fp_less(lambdav.ptr.p_double[i+1],lambdav.ptr.p_double[i]) ) - { - *serrors = ae_true; - ae_frame_leave(_state); - return; - } - } - - /* - * Test simple EVD: values only, lower A - */ - testevdunit_unset1d(&lambdav, _state); - testevdunit_unset2d(&z, _state); - *runs = *runs+1; - if( !smatrixevd(al, n, 0, ae_false, &lambdav, &z, _state) ) - { - *failc = *failc+1; - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - *serrors = *serrors||ae_fp_greater(ae_fabs(lambdav.ptr.p_double[i]-lambdaref.ptr.p_double[i], _state),threshold); - } - - /* - * Test simple EVD: values only, upper A - */ - testevdunit_unset1d(&lambdav, _state); - testevdunit_unset2d(&z, _state); - *runs = *runs+1; - if( !smatrixevd(au, n, 0, ae_true, &lambdav, &z, _state) ) - { - *failc = *failc+1; - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - *serrors = *serrors||ae_fp_greater(ae_fabs(lambdav.ptr.p_double[i]-lambdaref.ptr.p_double[i], _state),threshold); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Tests SEVD problem -*************************************************************************/ -static void testevdunit_testhevdproblem(/* Complex */ ae_matrix* a, - /* Complex */ ae_matrix* al, - /* Complex */ ae_matrix* au, - ae_int_t n, - double threshold, - ae_bool* herrors, - ae_int_t* failc, - ae_int_t* runs, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector lambdav; - ae_vector lambdaref; - ae_matrix z; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&lambdav, 0, sizeof(lambdav)); - memset(&lambdaref, 0, sizeof(lambdaref)); - memset(&z, 0, sizeof(z)); - ae_vector_init(&lambdav, 0, DT_REAL, _state, ae_true); - ae_vector_init(&lambdaref, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z, 0, 0, DT_COMPLEX, _state, ae_true); - - - /* - * Test simple EVD: values and full vectors, lower A - */ - testevdunit_unset1d(&lambdaref, _state); - testevdunit_cunset2d(&z, _state); - *runs = *runs+1; - if( !hmatrixevd(al, n, 1, ae_false, &lambdaref, &z, _state) ) - { - *failc = *failc+1; - ae_frame_leave(_state); - return; - } - *herrors = *herrors||ae_fp_greater(testevdunit_testcproduct(a, n, &z, &lambdaref, _state),threshold); - *herrors = *herrors||ae_fp_greater(testevdunit_testcort(&z, n, _state),threshold); - for(i=0; i<=n-2; i++) - { - if( ae_fp_less(lambdaref.ptr.p_double[i+1],lambdaref.ptr.p_double[i]) ) - { - *herrors = ae_true; - ae_frame_leave(_state); - return; - } - } - - /* - * Test simple EVD: values and full vectors, upper A - */ - testevdunit_unset1d(&lambdav, _state); - testevdunit_cunset2d(&z, _state); - *runs = *runs+1; - if( !hmatrixevd(au, n, 1, ae_true, &lambdav, &z, _state) ) - { - *failc = *failc+1; - ae_frame_leave(_state); - return; - } - *herrors = *herrors||ae_fp_greater(testevdunit_testcproduct(a, n, &z, &lambdav, _state),threshold); - *herrors = *herrors||ae_fp_greater(testevdunit_testcort(&z, n, _state),threshold); - for(i=0; i<=n-2; i++) - { - if( ae_fp_less(lambdav.ptr.p_double[i+1],lambdav.ptr.p_double[i]) ) - { - *herrors = ae_true; - ae_frame_leave(_state); - return; - } - } - - /* - * Test simple EVD: values only, lower A - */ - testevdunit_unset1d(&lambdav, _state); - testevdunit_cunset2d(&z, _state); - *runs = *runs+1; - if( !hmatrixevd(al, n, 0, ae_false, &lambdav, &z, _state) ) - { - *failc = *failc+1; - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - *herrors = *herrors||ae_fp_greater(ae_fabs(lambdav.ptr.p_double[i]-lambdaref.ptr.p_double[i], _state),threshold); - } - - /* - * Test simple EVD: values only, upper A - */ - testevdunit_unset1d(&lambdav, _state); - testevdunit_cunset2d(&z, _state); - *runs = *runs+1; - if( !hmatrixevd(au, n, 0, ae_true, &lambdav, &z, _state) ) - { - *failc = *failc+1; - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - *herrors = *herrors||ae_fp_greater(ae_fabs(lambdav.ptr.p_double[i]-lambdaref.ptr.p_double[i], _state),threshold); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Tests EVD problem - -DistVals - is True, when eigenvalues are distinct. Is False, when we - are solving sparse task with lots of zero eigenvalues. - In such cases some tests related to the eigenvectors are - not performed. -*************************************************************************/ -static void testevdunit_testsevdbiproblem(/* Real */ ae_matrix* afull, - /* Real */ ae_matrix* al, - /* Real */ ae_matrix* au, - ae_int_t n, - ae_bool distvals, - double threshold, - ae_bool* serrors, - ae_int_t* failc, - ae_int_t* runs, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector lambdav; - ae_vector lambdaref; - ae_matrix z; - ae_matrix zref; - ae_matrix a1; - ae_matrix a2; - ae_matrix ar; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t m; - ae_int_t i1; - ae_int_t i2; - double v; - double a; - double b; - - ae_frame_make(_state, &_frame_block); - memset(&lambdav, 0, sizeof(lambdav)); - memset(&lambdaref, 0, sizeof(lambdaref)); - memset(&z, 0, sizeof(z)); - memset(&zref, 0, sizeof(zref)); - memset(&a1, 0, sizeof(a1)); - memset(&a2, 0, sizeof(a2)); - memset(&ar, 0, sizeof(ar)); - ae_vector_init(&lambdav, 0, DT_REAL, _state, ae_true); - ae_vector_init(&lambdaref, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&zref, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ar, 0, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&lambdaref, n-1+1, _state); - ae_matrix_set_length(&zref, n-1+1, n-1+1, _state); - ae_matrix_set_length(&a1, n-1+1, n-1+1, _state); - ae_matrix_set_length(&a2, n-1+1, n-1+1, _state); - - /* - * Reference EVD - */ - *runs = *runs+1; - if( !smatrixevd(afull, n, 1, ae_true, &lambdaref, &zref, _state) ) - { - *failc = *failc+1; - ae_frame_leave(_state); - return; - } - - /* - * Select random interval boundaries. - * If there are non-distinct eigenvalues at the boundaries, - * we move indexes further until values splits. It is done to - * avoid situations where we can't get definite answer. - */ - i1 = ae_randominteger(n, _state); - i2 = i1+ae_randominteger(n-i1, _state); - while(i1>0) - { - if( ae_fp_greater(ae_fabs(lambdaref.ptr.p_double[i1-1]-lambdaref.ptr.p_double[i1], _state),10*threshold) ) - { - break; - } - i1 = i1-1; - } - while(i20 ) - { - a = 0.5*(lambdaref.ptr.p_double[i1]+lambdaref.ptr.p_double[i1-1]); - } - else - { - a = lambdaref.ptr.p_double[0]-1; - } - if( i20) - { - if( ae_fp_greater(ae_fabs(lambdaref.ptr.p_double[i1-1]-lambdaref.ptr.p_double[i1], _state),10*threshold) ) - { - break; - } - i1 = i1-1; - } - while(i20 ) - { - a = 0.5*(lambdaref.ptr.p_double[i1]+lambdaref.ptr.p_double[i1-1]); - } - else - { - a = lambdaref.ptr.p_double[0]-1; - } - if( i21 ) - { - ae_vector_set_length(&ee, n-2+1, _state); - } - - /* - * Test simple EVD: values and full vectors - */ - for(i=0; i<=n-1; i++) - { - lambdav.ptr.p_double[i] = d->ptr.p_double[i]; - } - for(i=0; i<=n-2; i++) - { - ee.ptr.p_double[i] = e->ptr.p_double[i]; - } - testevdunit_unset2d(&z, _state); - wsucc = smatrixtdevd(&lambdav, &ee, n, 2, &z, _state); - if( !wsucc ) - { - ae_set_error_flag(tderrors, ae_true, __FILE__, __LINE__, "testevdunit.ap:1113"); - ae_frame_leave(_state); - return; - } - ae_set_error_flag(tderrors, ae_fp_greater(testevdunit_tdtestproduct(d, e, n, &z, &lambdav, _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1116"); - ae_set_error_flag(tderrors, ae_fp_greater(testevdunit_testort(&z, n, _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1117"); - for(i=0; i<=n-2; i++) - { - if( ae_fp_less(lambdav.ptr.p_double[i+1],lambdav.ptr.p_double[i]) ) - { - ae_set_error_flag(tderrors, ae_true, __FILE__, __LINE__, "testevdunit.ap:1121"); - ae_frame_leave(_state); - return; - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - zref.ptr.pp_double[i][j] = z.ptr.pp_double[i][j]; - } - } - - /* - * Test values only variant - */ - for(i=0; i<=n-1; i++) - { - lambda2.ptr.p_double[i] = d->ptr.p_double[i]; - } - for(i=0; i<=n-2; i++) - { - ee.ptr.p_double[i] = e->ptr.p_double[i]; - } - testevdunit_unset2d(&z, _state); - wsucc = smatrixtdevd(&lambda2, &ee, n, 0, &z, _state); - if( !wsucc ) - { - ae_set_error_flag(tderrors, ae_true, __FILE__, __LINE__, "testevdunit.ap:1139"); - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(tderrors, ae_fp_greater(ae_fabs(lambda2.ptr.p_double[i]-lambdav.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1143"); - } - - /* - * Test multiplication variant - */ - for(i=0; i<=n-1; i++) - { - lambda2.ptr.p_double[i] = d->ptr.p_double[i]; - } - for(i=0; i<=n-2; i++) - { - ee.ptr.p_double[i] = e->ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a1.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - a2.ptr.pp_double[i][j] = a1.ptr.pp_double[i][j]; - } - } - wsucc = smatrixtdevd(&lambda2, &ee, n, 1, &a1, _state); - if( !wsucc ) - { - ae_set_error_flag(tderrors, ae_true, __FILE__, __LINE__, "testevdunit.ap:1161"); - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(tderrors, ae_fp_greater(ae_fabs(lambda2.ptr.p_double[i]-lambdav.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1165"); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&a2.ptr.pp_double[i][0], 1, &zref.ptr.pp_double[0][j], zref.stride, ae_v_len(0,n-1)); - - /* - * next line is a bit complicated because - * depending on algorithm used we can get either - * z or -z as eigenvector. so we compare result - * with both A*ZRef and -A*ZRef - */ - ae_set_error_flag(tderrors, ae_fp_greater(ae_fabs(v-a1.ptr.pp_double[i][j], _state),threshold)&&ae_fp_greater(ae_fabs(v+a1.ptr.pp_double[i][j], _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1177"); - } - } - - /* - * Test first row variant. - * - * NOTE: this test is special because ZNeeded=3 is ALGLIB-specific feature - * which is NOT supported by Intel MKL. Thus, MKL-capable version of - * ALGLIB will use different algorithms for ZNeeded=3 and for ZNeeded<3. - * - * In most cases it is OK, but when problem happened to be degenerate - * (two close eigenvalues), Z computed by ALGLIB may be different from - * Z computed by MKL (up to arbitrary rotation), which will lead to - * failure of the test, because ZNeeded=2 is used as reference value - * for ZNeeded=3. - * - * That's why this test is performed only for well-separated matrices, - * and with custom threshold. - */ - requiredseparation = 1.0E-6; - specialthreshold = 1.0E-6; - worstseparation = ae_maxrealnumber; - for(i=0; i<=n-2; i++) - { - worstseparation = ae_minreal(worstseparation, ae_fabs(lambdav.ptr.p_double[i+1]-lambdav.ptr.p_double[i], _state), _state); - } - if( ae_fp_greater(worstseparation,requiredseparation) ) - { - for(i=0; i<=n-1; i++) - { - lambda2.ptr.p_double[i] = d->ptr.p_double[i]; - } - for(i=0; i<=n-2; i++) - { - ee.ptr.p_double[i] = e->ptr.p_double[i]; - } - testevdunit_unset2d(&z, _state); - wsucc = smatrixtdevd(&lambda2, &ee, n, 3, &z, _state); - if( !wsucc ) - { - ae_set_error_flag(tderrors, ae_true, __FILE__, __LINE__, "testevdunit.ap:1211"); - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(tderrors, ae_fp_greater(ae_fabs(lambda2.ptr.p_double[i]-lambdav.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1216"); - - /* - * next line is a bit complicated because - * depending on algorithm used we can get either - * z or -z as eigenvector. so we compare result - * with both z and -z - */ - ae_set_error_flag(tderrors, ae_fp_greater(ae_fabs(z.ptr.pp_double[0][i]-zref.ptr.pp_double[0][i], _state),specialthreshold)&&ae_fp_greater(ae_fabs(z.ptr.pp_double[0][i]+zref.ptr.pp_double[0][i], _state),specialthreshold), __FILE__, __LINE__, "testevdunit.ap:1224"); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Tests EVD problem - -DistVals - is True, when eigenvalues are distinct. Is False, when we - are solving sparse task with lots of zero eigenvalues. - In such cases some tests related to the eigenvectors are - not performed. -*************************************************************************/ -static void testevdunit_testtdevdbiproblem(/* Real */ ae_vector* d, - /* Real */ ae_vector* e, - ae_int_t n, - ae_bool distvals, - double threshold, - ae_bool* serrors, - ae_int_t* failc, - ae_int_t* runs, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector lambdav; - ae_vector lambdaref; - ae_matrix z; - ae_matrix zref; - ae_matrix a1; - ae_matrix a2; - ae_matrix ar; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t m; - ae_int_t i1; - ae_int_t i2; - double v; - double a; - double b; - - ae_frame_make(_state, &_frame_block); - memset(&lambdav, 0, sizeof(lambdav)); - memset(&lambdaref, 0, sizeof(lambdaref)); - memset(&z, 0, sizeof(z)); - memset(&zref, 0, sizeof(zref)); - memset(&a1, 0, sizeof(a1)); - memset(&a2, 0, sizeof(a2)); - memset(&ar, 0, sizeof(ar)); - ae_vector_init(&lambdav, 0, DT_REAL, _state, ae_true); - ae_vector_init(&lambdaref, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&zref, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ar, 0, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&lambdaref, n-1+1, _state); - ae_matrix_set_length(&zref, n-1+1, n-1+1, _state); - ae_matrix_set_length(&a1, n-1+1, n-1+1, _state); - ae_matrix_set_length(&a2, n-1+1, n-1+1, _state); - - /* - * Reference EVD - */ - ae_vector_set_length(&lambdaref, n, _state); - ae_v_move(&lambdaref.ptr.p_double[0], 1, &d->ptr.p_double[0], 1, ae_v_len(0,n-1)); - *runs = *runs+1; - if( !smatrixtdevd(&lambdaref, e, n, 2, &zref, _state) ) - { - *failc = *failc+1; - ae_frame_leave(_state); - return; - } - - /* - * Select random interval boundaries. - * If there are non-distinct eigenvalues at the boundaries, - * we move indexes further until values splits. It is done to - * avoid situations where we can't get definite answer. - */ - i1 = ae_randominteger(n, _state); - i2 = i1+ae_randominteger(n-i1, _state); - while(i1>0) - { - if( ae_fp_greater(ae_fabs(lambdaref.ptr.p_double[i1-1]-lambdaref.ptr.p_double[i1], _state),10*threshold) ) - { - break; - } - i1 = i1-1; - } - while(i20 ) - { - a = 0.5*(lambdaref.ptr.p_double[i1]+lambdaref.ptr.p_double[i1-1]); - } - else - { - a = lambdaref.ptr.p_double[0]-1; - } - if( i2ptr.p_double[i]; - } - *runs = *runs+1; - if( !smatrixtdevdr(&lambdav, e, n, 0, a, b, &m, &z, _state) ) - { - *failc = *failc+1; - ae_frame_leave(_state); - return; - } - if( m!=i2-i1+1 ) - { - *failc = *failc+1; - ae_frame_leave(_state); - return; - } - for(k=0; k<=m-1; k++) - { - *serrors = *serrors||ae_fp_greater(ae_fabs(lambdav.ptr.p_double[k]-lambdaref.ptr.p_double[i1+k], _state),threshold); - } - - /* - * Test indexes, no vectors - */ - ae_vector_set_length(&lambdav, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - lambdav.ptr.p_double[i] = d->ptr.p_double[i]; - } - *runs = *runs+1; - if( !smatrixtdevdi(&lambdav, e, n, 0, i1, i2, &z, _state) ) - { - *failc = *failc+1; - ae_frame_leave(_state); - return; - } - m = i2-i1+1; - for(k=0; k<=m-1; k++) - { - *serrors = *serrors||ae_fp_greater(ae_fabs(lambdav.ptr.p_double[k]-lambdaref.ptr.p_double[i1+k], _state),threshold); - } - - /* - * Test interval, transform vectors - */ - ae_vector_set_length(&lambdav, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - lambdav.ptr.p_double[i] = d->ptr.p_double[i]; - } - ae_matrix_set_length(&a1, n-1+1, n-1+1, _state); - ae_matrix_set_length(&a2, n-1+1, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a1.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - a2.ptr.pp_double[i][j] = a1.ptr.pp_double[i][j]; - } - } - *runs = *runs+1; - if( !smatrixtdevdr(&lambdav, e, n, 1, a, b, &m, &a1, _state) ) - { - *failc = *failc+1; - ae_frame_leave(_state); - return; - } - if( m!=i2-i1+1 ) - { - *failc = *failc+1; - ae_frame_leave(_state); - return; - } - for(k=0; k<=m-1; k++) - { - *serrors = *serrors||ae_fp_greater(ae_fabs(lambdav.ptr.p_double[k]-lambdaref.ptr.p_double[i1+k], _state),threshold); - } - if( distvals ) - { - ae_matrix_set_length(&ar, n-1+1, m-1+1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - v = ae_v_dotproduct(&a2.ptr.pp_double[i][0], 1, &zref.ptr.pp_double[0][i1+j], zref.stride, ae_v_len(0,n-1)); - ar.ptr.pp_double[i][j] = v; - } - } - for(j=0; j<=m-1; j++) - { - v = ae_v_dotproduct(&a1.ptr.pp_double[0][j], a1.stride, &ar.ptr.pp_double[0][j], ar.stride, ae_v_len(0,n-1)); - if( ae_fp_less(v,(double)(0)) ) - { - ae_v_muld(&ar.ptr.pp_double[0][j], ar.stride, ae_v_len(0,n-1), -1); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - *serrors = *serrors||ae_fp_greater(ae_fabs(a1.ptr.pp_double[i][j]-ar.ptr.pp_double[i][j], _state),threshold); - } - } - } - - /* - * Test indexes, transform vectors - */ - ae_vector_set_length(&lambdav, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - lambdav.ptr.p_double[i] = d->ptr.p_double[i]; - } - ae_matrix_set_length(&a1, n-1+1, n-1+1, _state); - ae_matrix_set_length(&a2, n-1+1, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a1.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - a2.ptr.pp_double[i][j] = a1.ptr.pp_double[i][j]; - } - } - *runs = *runs+1; - if( !smatrixtdevdi(&lambdav, e, n, 1, i1, i2, &a1, _state) ) - { - *failc = *failc+1; - ae_frame_leave(_state); - return; - } - m = i2-i1+1; - for(k=0; k<=m-1; k++) - { - *serrors = *serrors||ae_fp_greater(ae_fabs(lambdav.ptr.p_double[k]-lambdaref.ptr.p_double[i1+k], _state),threshold); - } - if( distvals ) - { - ae_matrix_set_length(&ar, n-1+1, m-1+1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - v = ae_v_dotproduct(&a2.ptr.pp_double[i][0], 1, &zref.ptr.pp_double[0][i1+j], zref.stride, ae_v_len(0,n-1)); - ar.ptr.pp_double[i][j] = v; - } - } - for(j=0; j<=m-1; j++) - { - v = ae_v_dotproduct(&a1.ptr.pp_double[0][j], a1.stride, &ar.ptr.pp_double[0][j], ar.stride, ae_v_len(0,n-1)); - if( ae_fp_less(v,(double)(0)) ) - { - ae_v_muld(&ar.ptr.pp_double[0][j], ar.stride, ae_v_len(0,n-1), -1); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - *serrors = *serrors||ae_fp_greater(ae_fabs(a1.ptr.pp_double[i][j]-ar.ptr.pp_double[i][j], _state),threshold); - } - } - } - - /* - * Test interval, do not transform vectors - */ - ae_vector_set_length(&lambdav, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - lambdav.ptr.p_double[i] = d->ptr.p_double[i]; - } - ae_matrix_set_length(&z, 0+1, 0+1, _state); - *runs = *runs+1; - if( !smatrixtdevdr(&lambdav, e, n, 2, a, b, &m, &z, _state) ) - { - *failc = *failc+1; - ae_frame_leave(_state); - return; - } - if( m!=i2-i1+1 ) - { - *failc = *failc+1; - ae_frame_leave(_state); - return; - } - for(k=0; k<=m-1; k++) - { - *serrors = *serrors||ae_fp_greater(ae_fabs(lambdav.ptr.p_double[k]-lambdaref.ptr.p_double[i1+k], _state),threshold); - } - if( distvals ) - { - for(j=0; j<=m-1; j++) - { - v = ae_v_dotproduct(&z.ptr.pp_double[0][j], z.stride, &zref.ptr.pp_double[0][i1+j], zref.stride, ae_v_len(0,n-1)); - if( ae_fp_less(v,(double)(0)) ) - { - ae_v_muld(&z.ptr.pp_double[0][j], z.stride, ae_v_len(0,n-1), -1); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - *serrors = *serrors||ae_fp_greater(ae_fabs(z.ptr.pp_double[i][j]-zref.ptr.pp_double[i][i1+j], _state),threshold); - } - } - } - - /* - * Test indexes, do not transform vectors - */ - ae_vector_set_length(&lambdav, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - lambdav.ptr.p_double[i] = d->ptr.p_double[i]; - } - ae_matrix_set_length(&z, 0+1, 0+1, _state); - *runs = *runs+1; - if( !smatrixtdevdi(&lambdav, e, n, 2, i1, i2, &z, _state) ) - { - *failc = *failc+1; - ae_frame_leave(_state); - return; - } - m = i2-i1+1; - for(k=0; k<=m-1; k++) - { - *serrors = *serrors||ae_fp_greater(ae_fabs(lambdav.ptr.p_double[k]-lambdaref.ptr.p_double[i1+k], _state),threshold); - } - if( distvals ) - { - for(j=0; j<=m-1; j++) - { - v = ae_v_dotproduct(&z.ptr.pp_double[0][j], z.stride, &zref.ptr.pp_double[0][i1+j], zref.stride, ae_v_len(0,n-1)); - if( ae_fp_less(v,(double)(0)) ) - { - ae_v_muld(&z.ptr.pp_double[0][j], z.stride, ae_v_len(0,n-1), -1); - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - *serrors = *serrors||ae_fp_greater(ae_fabs(z.ptr.pp_double[i][j]-zref.ptr.pp_double[i][i1+j], _state),threshold); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Non-symmetric problem -*************************************************************************/ -static void testevdunit_testnsevdproblem(/* Real */ ae_matrix* a, - ae_int_t n, - double threshold, - ae_bool* nserrors, - ae_state *_state) -{ - ae_frame _frame_block; - double mx; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t vjob; - ae_bool needl; - ae_bool needr; - ae_vector wr0; - ae_vector wi0; - ae_vector wr1; - ae_vector wi1; - ae_vector wr0s; - ae_vector wi0s; - ae_vector wr1s; - ae_vector wi1s; - ae_matrix vl; - ae_matrix vr; - ae_vector vec1r; - ae_vector vec1i; - ae_vector vec2r; - ae_vector vec2i; - ae_vector vec3r; - ae_vector vec3i; - double curwr; - double curwi; - double vt; - double tmp; - double vnorm; - - ae_frame_make(_state, &_frame_block); - memset(&wr0, 0, sizeof(wr0)); - memset(&wi0, 0, sizeof(wi0)); - memset(&wr1, 0, sizeof(wr1)); - memset(&wi1, 0, sizeof(wi1)); - memset(&wr0s, 0, sizeof(wr0s)); - memset(&wi0s, 0, sizeof(wi0s)); - memset(&wr1s, 0, sizeof(wr1s)); - memset(&wi1s, 0, sizeof(wi1s)); - memset(&vl, 0, sizeof(vl)); - memset(&vr, 0, sizeof(vr)); - memset(&vec1r, 0, sizeof(vec1r)); - memset(&vec1i, 0, sizeof(vec1i)); - memset(&vec2r, 0, sizeof(vec2r)); - memset(&vec2i, 0, sizeof(vec2i)); - memset(&vec3r, 0, sizeof(vec3r)); - memset(&vec3i, 0, sizeof(vec3i)); - ae_vector_init(&wr0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wi0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wr1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wi1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wr0s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wi0s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wr1s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wi1s, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vl, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vr, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vec1r, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vec1i, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vec2r, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vec2i, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vec3r, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vec3i, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&vec1r, n-1+1, _state); - ae_vector_set_length(&vec2r, n-1+1, _state); - ae_vector_set_length(&vec3r, n-1+1, _state); - ae_vector_set_length(&vec1i, n-1+1, _state); - ae_vector_set_length(&vec2i, n-1+1, _state); - ae_vector_set_length(&vec3i, n-1+1, _state); - ae_vector_set_length(&wr0s, n-1+1, _state); - ae_vector_set_length(&wr1s, n-1+1, _state); - ae_vector_set_length(&wi0s, n-1+1, _state); - ae_vector_set_length(&wi1s, n-1+1, _state); - mx = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_greater(ae_fabs(a->ptr.pp_double[i][j], _state),mx) ) - { - mx = ae_fabs(a->ptr.pp_double[i][j], _state); - } - } - } - if( ae_fp_eq(mx,(double)(0)) ) - { - mx = (double)(1); - } - - /* - * Load values-only - */ - if( !rmatrixevd(a, n, 0, &wr0, &wi0, &vl, &vr, _state) ) - { - ae_set_error_flag(nserrors, ae_true, __FILE__, __LINE__, "testevdunit.ap:1554"); - ae_frame_leave(_state); - return; - } - - /* - * Test different jobs - */ - for(vjob=1; vjob<=3; vjob++) - { - needr = vjob==1||vjob==3; - needl = vjob==2||vjob==3; - if( !rmatrixevd(a, n, vjob, &wr1, &wi1, &vl, &vr, _state) ) - { - ae_set_error_flag(nserrors, ae_true, __FILE__, __LINE__, "testevdunit.ap:1567"); - ae_frame_leave(_state); - return; - } - - /* - * Test values: - * 1. sort by real part - * 2. test - */ - ae_v_move(&wr0s.ptr.p_double[0], 1, &wr0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&wi0s.ptr.p_double[0], 1, &wi0.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-2-i; j++) - { - if( ae_fp_greater(wr0s.ptr.p_double[j],wr0s.ptr.p_double[j+1]) ) - { - tmp = wr0s.ptr.p_double[j]; - wr0s.ptr.p_double[j] = wr0s.ptr.p_double[j+1]; - wr0s.ptr.p_double[j+1] = tmp; - tmp = wi0s.ptr.p_double[j]; - wi0s.ptr.p_double[j] = wi0s.ptr.p_double[j+1]; - wi0s.ptr.p_double[j+1] = tmp; - } - } - } - ae_v_move(&wr1s.ptr.p_double[0], 1, &wr1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&wi1s.ptr.p_double[0], 1, &wi1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-2-i; j++) - { - if( ae_fp_greater(wr1s.ptr.p_double[j],wr1s.ptr.p_double[j+1]) ) - { - tmp = wr1s.ptr.p_double[j]; - wr1s.ptr.p_double[j] = wr1s.ptr.p_double[j+1]; - wr1s.ptr.p_double[j+1] = tmp; - tmp = wi1s.ptr.p_double[j]; - wi1s.ptr.p_double[j] = wi1s.ptr.p_double[j+1]; - wi1s.ptr.p_double[j+1] = tmp; - } - } - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(nserrors, ae_fp_greater(ae_fabs(wr0s.ptr.p_double[i]-wr1s.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1604"); - ae_set_error_flag(nserrors, ae_fp_greater(ae_fabs(wi0s.ptr.p_double[i]-wi1s.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1605"); - } - - /* - * Test right vectors - */ - if( needr ) - { - k = 0; - while(k<=n-1) - { - curwr = (double)(0); - curwi = (double)(0); - if( ae_fp_eq(wi1.ptr.p_double[k],(double)(0)) ) - { - ae_v_move(&vec1r.ptr.p_double[0], 1, &vr.ptr.pp_double[0][k], vr.stride, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - vec1i.ptr.p_double[i] = (double)(0); - } - curwr = wr1.ptr.p_double[k]; - curwi = (double)(0); - } - if( ae_fp_greater(wi1.ptr.p_double[k],(double)(0)) ) - { - ae_v_move(&vec1r.ptr.p_double[0], 1, &vr.ptr.pp_double[0][k], vr.stride, ae_v_len(0,n-1)); - ae_v_move(&vec1i.ptr.p_double[0], 1, &vr.ptr.pp_double[0][k+1], vr.stride, ae_v_len(0,n-1)); - curwr = wr1.ptr.p_double[k]; - curwi = wi1.ptr.p_double[k]; - } - if( ae_fp_less(wi1.ptr.p_double[k],(double)(0)) ) - { - ae_v_move(&vec1r.ptr.p_double[0], 1, &vr.ptr.pp_double[0][k-1], vr.stride, ae_v_len(0,n-1)); - ae_v_moveneg(&vec1i.ptr.p_double[0], 1, &vr.ptr.pp_double[0][k], vr.stride, ae_v_len(0,n-1)); - curwr = wr1.ptr.p_double[k]; - curwi = wi1.ptr.p_double[k]; - } - vnorm = 0.0; - for(i=0; i<=n-1; i++) - { - vt = ae_v_dotproduct(&a->ptr.pp_double[i][0], 1, &vec1r.ptr.p_double[0], 1, ae_v_len(0,n-1)); - vec2r.ptr.p_double[i] = vt; - vt = ae_v_dotproduct(&a->ptr.pp_double[i][0], 1, &vec1i.ptr.p_double[0], 1, ae_v_len(0,n-1)); - vec2i.ptr.p_double[i] = vt; - vnorm = vnorm+ae_sqr(vec1r.ptr.p_double[i], _state)+ae_sqr(vec1i.ptr.p_double[i], _state); - } - vnorm = ae_sqrt(vnorm, _state); - ae_v_moved(&vec3r.ptr.p_double[0], 1, &vec1r.ptr.p_double[0], 1, ae_v_len(0,n-1), curwr); - ae_v_subd(&vec3r.ptr.p_double[0], 1, &vec1i.ptr.p_double[0], 1, ae_v_len(0,n-1), curwi); - ae_v_moved(&vec3i.ptr.p_double[0], 1, &vec1r.ptr.p_double[0], 1, ae_v_len(0,n-1), curwi); - ae_v_addd(&vec3i.ptr.p_double[0], 1, &vec1i.ptr.p_double[0], 1, ae_v_len(0,n-1), curwr); - ae_set_error_flag(nserrors, ae_fp_less(vnorm,1.0E-3)||!ae_isfinite(vnorm, _state), __FILE__, __LINE__, "testevdunit.ap:1654"); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(nserrors, ae_fp_greater(ae_fabs(vec2r.ptr.p_double[i]-vec3r.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1657"); - ae_set_error_flag(nserrors, ae_fp_greater(ae_fabs(vec2i.ptr.p_double[i]-vec3i.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1658"); - } - k = k+1; - } - } - - /* - * Test left vectors - */ - curwr = (double)(0); - curwi = (double)(0); - if( needl ) - { - k = 0; - while(k<=n-1) - { - if( ae_fp_eq(wi1.ptr.p_double[k],(double)(0)) ) - { - ae_v_move(&vec1r.ptr.p_double[0], 1, &vl.ptr.pp_double[0][k], vl.stride, ae_v_len(0,n-1)); - for(i=0; i<=n-1; i++) - { - vec1i.ptr.p_double[i] = (double)(0); - } - curwr = wr1.ptr.p_double[k]; - curwi = (double)(0); - } - if( ae_fp_greater(wi1.ptr.p_double[k],(double)(0)) ) - { - ae_v_move(&vec1r.ptr.p_double[0], 1, &vl.ptr.pp_double[0][k], vl.stride, ae_v_len(0,n-1)); - ae_v_move(&vec1i.ptr.p_double[0], 1, &vl.ptr.pp_double[0][k+1], vl.stride, ae_v_len(0,n-1)); - curwr = wr1.ptr.p_double[k]; - curwi = wi1.ptr.p_double[k]; - } - if( ae_fp_less(wi1.ptr.p_double[k],(double)(0)) ) - { - ae_v_move(&vec1r.ptr.p_double[0], 1, &vl.ptr.pp_double[0][k-1], vl.stride, ae_v_len(0,n-1)); - ae_v_moveneg(&vec1i.ptr.p_double[0], 1, &vl.ptr.pp_double[0][k], vl.stride, ae_v_len(0,n-1)); - curwr = wr1.ptr.p_double[k]; - curwi = wi1.ptr.p_double[k]; - } - vnorm = 0.0; - for(j=0; j<=n-1; j++) - { - vt = ae_v_dotproduct(&vec1r.ptr.p_double[0], 1, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,n-1)); - vec2r.ptr.p_double[j] = vt; - vt = ae_v_dotproduct(&vec1i.ptr.p_double[0], 1, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,n-1)); - vec2i.ptr.p_double[j] = -vt; - vnorm = vnorm+ae_sqr(vec1r.ptr.p_double[j], _state)+ae_sqr(vec1i.ptr.p_double[j], _state); - } - vnorm = ae_sqrt(vnorm, _state); - ae_v_moved(&vec3r.ptr.p_double[0], 1, &vec1r.ptr.p_double[0], 1, ae_v_len(0,n-1), curwr); - ae_v_addd(&vec3r.ptr.p_double[0], 1, &vec1i.ptr.p_double[0], 1, ae_v_len(0,n-1), curwi); - ae_v_moved(&vec3i.ptr.p_double[0], 1, &vec1r.ptr.p_double[0], 1, ae_v_len(0,n-1), curwi); - ae_v_addd(&vec3i.ptr.p_double[0], 1, &vec1i.ptr.p_double[0], 1, ae_v_len(0,n-1), -curwr); - ae_set_error_flag(nserrors, ae_fp_less(vnorm,1.0E-3)||!ae_isfinite(vnorm, _state), __FILE__, __LINE__, "testevdunit.ap:1710"); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(nserrors, ae_fp_greater(ae_fabs(vec2r.ptr.p_double[i]-vec3r.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1713"); - ae_set_error_flag(nserrors, ae_fp_greater(ae_fabs(vec2i.ptr.p_double[i]-vec3i.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1714"); - } - k = k+1; - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Testing EVD subroutines for one N - -NOTES: -* BIThreshold is a threshold for bisection-and-inverse-iteration subroutines. - special threshold is needed because these subroutines may have much more - larger error than QR-based algorithms. -*************************************************************************/ -static void testevdunit_testevdset(ae_int_t n, - double threshold, - double bithreshold, - ae_int_t* failc, - ae_int_t* runs, - ae_bool* nserrors, - ae_bool* serrors, - ae_bool* herrors, - ae_bool* tderrors, - ae_bool* sbierrors, - ae_bool* hbierrors, - ae_bool* tdbierrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix ra; - ae_matrix ral; - ae_matrix rau; - ae_matrix ca; - ae_matrix cal; - ae_matrix cau; - ae_vector d; - ae_vector e; - ae_int_t i; - ae_int_t j; - ae_int_t mkind; - - ae_frame_make(_state, &_frame_block); - memset(&ra, 0, sizeof(ra)); - memset(&ral, 0, sizeof(ral)); - memset(&rau, 0, sizeof(rau)); - memset(&ca, 0, sizeof(ca)); - memset(&cal, 0, sizeof(cal)); - memset(&cau, 0, sizeof(cau)); - memset(&d, 0, sizeof(d)); - memset(&e, 0, sizeof(e)); - ae_matrix_init(&ra, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ral, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&rau, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ca, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&cal, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&cau, 0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&e, 0, DT_REAL, _state, ae_true); - - - /* - * Test symmetric problems - */ - ae_matrix_set_length(&ra, n, n, _state); - ae_matrix_set_length(&ral, n, n, _state); - ae_matrix_set_length(&rau, n, n, _state); - ae_matrix_set_length(&ca, n, n, _state); - ae_matrix_set_length(&cal, n, n, _state); - ae_matrix_set_length(&cau, n, n, _state); - - /* - * Zero matrices - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - ra.ptr.pp_double[i][j] = (double)(0); - ca.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - testevdunit_rmatrixsymmetricsplit(&ra, n, &ral, &rau, _state); - testevdunit_cmatrixhermitiansplit(&ca, n, &cal, &cau, _state); - testevdunit_testsevdproblem(&ra, &ral, &rau, n, threshold, serrors, failc, runs, _state); - testevdunit_testhevdproblem(&ca, &cal, &cau, n, threshold, herrors, failc, runs, _state); - testevdunit_testsevdbiproblem(&ra, &ral, &rau, n, ae_false, bithreshold, sbierrors, failc, runs, _state); - testevdunit_testhevdbiproblem(&ca, &cal, &cau, n, ae_false, bithreshold, hbierrors, failc, runs, _state); - - /* - * Random matrix - */ - for(i=0; i<=n-1; i++) - { - for(j=i+1; j<=n-1; j++) - { - ra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - ca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - ca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - ra.ptr.pp_double[j][i] = ra.ptr.pp_double[i][j]; - ca.ptr.pp_complex[j][i] = ae_c_conj(ca.ptr.pp_complex[i][j], _state); - } - ra.ptr.pp_double[i][i] = 2*ae_randomreal(_state)-1; - ca.ptr.pp_complex[i][i] = ae_complex_from_d(2*ae_randomreal(_state)-1); - } - testevdunit_rmatrixsymmetricsplit(&ra, n, &ral, &rau, _state); - testevdunit_cmatrixhermitiansplit(&ca, n, &cal, &cau, _state); - testevdunit_testsevdproblem(&ra, &ral, &rau, n, threshold, serrors, failc, runs, _state); - testevdunit_testhevdproblem(&ca, &cal, &cau, n, threshold, herrors, failc, runs, _state); - - /* - * Random diagonally dominant matrix with distinct eigenvalues - */ - for(i=0; i<=n-1; i++) - { - for(j=i+1; j<=n-1; j++) - { - ra.ptr.pp_double[i][j] = 0.1*(2*ae_randomreal(_state)-1)/n; - ca.ptr.pp_complex[i][j].x = 0.1*(2*ae_randomreal(_state)-1)/n; - ca.ptr.pp_complex[i][j].y = 0.1*(2*ae_randomreal(_state)-1)/n; - ra.ptr.pp_double[j][i] = ra.ptr.pp_double[i][j]; - ca.ptr.pp_complex[j][i] = ae_c_conj(ca.ptr.pp_complex[i][j], _state); - } - ra.ptr.pp_double[i][i] = 0.1*(2*ae_randomreal(_state)-1)+i; - ca.ptr.pp_complex[i][i] = ae_complex_from_d(0.1*(2*ae_randomreal(_state)-1)+i); - } - testevdunit_rmatrixsymmetricsplit(&ra, n, &ral, &rau, _state); - testevdunit_cmatrixhermitiansplit(&ca, n, &cal, &cau, _state); - testevdunit_testsevdproblem(&ra, &ral, &rau, n, threshold, serrors, failc, runs, _state); - testevdunit_testhevdproblem(&ca, &cal, &cau, n, threshold, herrors, failc, runs, _state); - testevdunit_testsevdbiproblem(&ra, &ral, &rau, n, ae_true, bithreshold, sbierrors, failc, runs, _state); - testevdunit_testhevdbiproblem(&ca, &cal, &cau, n, ae_true, bithreshold, hbierrors, failc, runs, _state); - - /* - * Sparse matrices - */ - testevdunit_rmatrixfillsparsea(&ra, n, n, 0.995, (double)(0), _state); - testevdunit_cmatrixfillsparsea(&ca, n, n, 0.995, (double)(0), _state); - for(i=0; i<=n-1; i++) - { - for(j=i+1; j<=n-1; j++) - { - ra.ptr.pp_double[j][i] = ra.ptr.pp_double[i][j]; - ca.ptr.pp_complex[j][i] = ae_c_conj(ca.ptr.pp_complex[i][j], _state); - } - ca.ptr.pp_complex[i][i].y = (double)(0); - } - testevdunit_rmatrixsymmetricsplit(&ra, n, &ral, &rau, _state); - testevdunit_cmatrixhermitiansplit(&ca, n, &cal, &cau, _state); - testevdunit_testsevdproblem(&ra, &ral, &rau, n, threshold, serrors, failc, runs, _state); - testevdunit_testhevdproblem(&ca, &cal, &cau, n, threshold, herrors, failc, runs, _state); - testevdunit_testsevdbiproblem(&ra, &ral, &rau, n, ae_false, bithreshold, sbierrors, failc, runs, _state); - testevdunit_testhevdbiproblem(&ca, &cal, &cau, n, ae_false, bithreshold, hbierrors, failc, runs, _state); - - /* - * testing tridiagonal problems - */ - for(mkind=0; mkind<=7; mkind++) - { - ae_vector_set_length(&d, n, _state); - if( n>1 ) - { - ae_vector_set_length(&e, n-1, _state); - } - if( mkind==0 ) - { - - /* - * Zero matrix - */ - for(i=0; i<=n-1; i++) - { - d.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-2; i++) - { - e.ptr.p_double[i] = (double)(0); - } - } - if( mkind==1 ) - { - - /* - * Diagonal matrix - */ - for(i=0; i<=n-1; i++) - { - d.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=n-2; i++) - { - e.ptr.p_double[i] = (double)(0); - } - } - if( mkind==2 ) - { - - /* - * Off-diagonal matrix - */ - for(i=0; i<=n-1; i++) - { - d.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-2; i++) - { - e.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - } - if( mkind==3 ) - { - - /* - * Dense matrix with blocks - */ - for(i=0; i<=n-1; i++) - { - d.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=n-2; i++) - { - e.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - j = 1; - i = 2; - while(j<=n-2) - { - e.ptr.p_double[j] = (double)(0); - j = j+i; - i = i+1; - } - } - if( mkind==4 ) - { - - /* - * dense matrix - */ - for(i=0; i<=n-1; i++) - { - d.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=n-2; i++) - { - e.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - } - if( mkind==5 ) - { - - /* - * Diagonal matrix with distinct eigenvalues - */ - for(i=0; i<=n-1; i++) - { - d.ptr.p_double[i] = 0.1*(2*ae_randomreal(_state)-1)+i; - } - for(i=0; i<=n-2; i++) - { - e.ptr.p_double[i] = (double)(0); - } - } - if( mkind==6 ) - { - - /* - * Off-diagonal matrix with distinct eigenvalues - */ - for(i=0; i<=n-1; i++) - { - d.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n-2; i++) - { - e.ptr.p_double[i] = 0.1*(2*ae_randomreal(_state)-1)+i+1; - } - } - if( mkind==7 ) - { - - /* - * dense matrix with distinct eigenvalues - */ - for(i=0; i<=n-1; i++) - { - d.ptr.p_double[i] = 0.1*(2*ae_randomreal(_state)-1)+i+1; - } - for(i=0; i<=n-2; i++) - { - e.ptr.p_double[i] = 0.1*(2*ae_randomreal(_state)-1); - } - } - testevdunit_testtdevdproblem(&d, &e, n, threshold, tderrors, _state); - testevdunit_testtdevdbiproblem(&d, &e, n, (mkind==5||mkind==6)||mkind==7, bithreshold, tdbierrors, failc, runs, _state); - } - - /* - * Test non-symmetric problems - */ - - /* - * Test non-symmetric problems: zero, random, sparse matrices. - */ - ae_matrix_set_length(&ra, n, n, _state); - ae_matrix_set_length(&ca, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - ra.ptr.pp_double[i][j] = (double)(0); - ca.ptr.pp_complex[i][j] = ae_complex_from_i(0); - } - } - testevdunit_testnsevdproblem(&ra, n, threshold, nserrors, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - ra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - ca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1; - ca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1; - } - } - testevdunit_testnsevdproblem(&ra, n, threshold, nserrors, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Testing symmetric mode of subspace iteration solver. - -On failure sets error flag, on success flag is not changed. -*************************************************************************/ -static void testevdunit_testsisymm(ae_bool* errorflag, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t m; - ae_int_t smode; - ae_int_t i; - ae_int_t j; - ae_int_t k; - hqrndstate rs; - double sgn; - ae_vector diaga; - double decaya; - ae_bool isupper; - ae_matrix qa; - ae_matrix densea; - ae_matrix halfa; - ae_matrix ra; - ae_matrix rb; - ae_matrix tmp2; - sparsematrix halfsa; - ae_int_t sformat; - double v; - double mx; - eigsubspacestate s; - eigsubspacereport rep; - ae_vector sw; - ae_matrix sz; - ae_vector u; - double tollambda; - double tolvector; - ae_int_t itscount; - ae_int_t callcount; - ae_int_t requestsize; - ae_int_t requesttype; - ae_int_t pass; - ae_int_t cnta; - ae_int_t cntb; - ae_int_t cntc; - double nu; - double eps; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - memset(&diaga, 0, sizeof(diaga)); - memset(&qa, 0, sizeof(qa)); - memset(&densea, 0, sizeof(densea)); - memset(&halfa, 0, sizeof(halfa)); - memset(&ra, 0, sizeof(ra)); - memset(&rb, 0, sizeof(rb)); - memset(&tmp2, 0, sizeof(tmp2)); - memset(&halfsa, 0, sizeof(halfsa)); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&sw, 0, sizeof(sw)); - memset(&sz, 0, sizeof(sz)); - memset(&u, 0, sizeof(u)); - _hqrndstate_init(&rs, _state, ae_true); - ae_vector_init(&diaga, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&qa, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&densea, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&halfa, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ra, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&rb, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&tmp2, 0, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&halfsa, _state, ae_true); - _eigsubspacestate_init(&s, _state, ae_true); - _eigsubspacereport_init(&rep, _state, ae_true); - ae_vector_init(&sw, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&sz, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&u, 0, DT_REAL, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Problem with weakly separated eigenvalues (but not too weak), - * either with alternating sign - or all positive. EPS-based - * stopping condition is used because we can not tell how many - * iterations is required to solve it. - */ - tollambda = 1.0E-9; - tolvector = 1.0E-4; - for(n=1; n<=25; n++) - { - for(m=1; m<=n; m++) - { - for(smode=0; smode<=2; smode++) - { - - /* - * Generate eigenproblem - */ - sgn = (double)(2*hqrnduniformi(&rs, 2, _state)-1); - decaya = 1.05; - ae_vector_set_length(&diaga, n, _state); - diaga.ptr.p_double[0] = ae_pow((double)(10), 2*hqrnduniformr(&rs, _state)-1, _state); - for(i=1; i<=n-1; i++) - { - diaga.ptr.p_double[i] = diaga.ptr.p_double[i-1]*sgn/(decaya*(1+0.01*hqrnduniformr(&rs, _state))); - } - rmatrixrndorthogonal(n, &qa, _state); - ae_matrix_set_length(&densea, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = (double)(0); - for(k=0; k<=n-1; k++) - { - v = v+qa.ptr.pp_double[k][i]*diaga.ptr.p_double[k]*qa.ptr.pp_double[k][j]; - } - densea.ptr.pp_double[i][j] = v; - } - } - isupper = ae_fp_greater(hqrnduniformr(&rs, _state),0.5); - ae_matrix_set_length(&halfa, n, n, _state); - sparsecreate(n, n, 0, &halfsa, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - halfa.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state); - if( j>=i&&isupper ) - { - halfa.ptr.pp_double[i][j] = densea.ptr.pp_double[i][j]; - sparseset(&halfsa, i, j, densea.ptr.pp_double[i][j], _state); - } - if( j<=i&&!isupper ) - { - halfa.ptr.pp_double[i][j] = densea.ptr.pp_double[i][j]; - sparseset(&halfsa, i, j, densea.ptr.pp_double[i][j], _state); - } - } - } - sformat = hqrnduniformi(&rs, 2, _state); - if( sformat==0 ) - { - sparseconverttocrs(&halfsa, _state); - } - if( sformat==1 ) - { - sparseconverttosks(&halfsa, _state); - } - - /* - * Solve with eigensolver operating in dense mode - */ - eigsubspacecreate(n, m, &s, _state); - eigsubspacesetcond(&s, tollambda/100, 0, _state); - if( smode==0 ) - { - - /* - * Dense mode - */ - eigsubspacesolvedenses(&s, &halfa, isupper, &sw, &sz, &rep, _state); - } - else - { - if( smode==1 ) - { - - /* - * Sparse mode - */ - eigsubspacesolvesparses(&s, &halfsa, isupper, &sw, &sz, &rep, _state); - } - else - { - if( smode==2 ) - { - - /* - * Out-of-core mode, symmetric version - */ - eigsubspaceoocstart(&s, 0, _state); - while(eigsubspaceooccontinue(&s, _state)) - { - eigsubspaceoocgetrequestinfo(&s, &requesttype, &requestsize, _state); - ae_assert(requesttype==0, "EVDI: integrity check failed in unit test", _state); - ae_assert(requestsize>0, "EVDI: integrity check failed in unit test", _state); - eigsubspaceoocgetrequestdata(&s, &ra, _state); - rmatrixsetlengthatleast(&rb, n, requestsize, _state); - rmatrixgemm(n, requestsize, n, 1.0, &densea, 0, 0, 0, &ra, 0, 0, 0, 0.0, &rb, 0, 0, _state); - eigsubspaceoocsendresult(&s, &rb, _state); - } - eigsubspaceoocstop(&s, &sw, &sz, &rep, _state); - } - else - { - ae_assert(ae_false, "unittest: integrity check failed", _state); - } - } - } - - /* - * Compare against reference values - */ - for(i=0; i<=m-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(sw.ptr.p_double[i]-diaga.ptr.p_double[i], _state),tollambda), __FILE__, __LINE__, "testevdunit.ap:2126"); - v = ae_v_dotproduct(&qa.ptr.pp_double[i][0], 1, &sz.ptr.pp_double[0][i], sz.stride, ae_v_len(0,n-1)); - mx = (double)(0); - for(j=0; j<=n-1; j++) - { - mx = ae_maxreal(mx, ae_fabs(sz.ptr.pp_double[j][i]*ae_sign(v, _state)-qa.ptr.pp_double[i][j], _state), _state); - } - ae_set_error_flag(errorflag, ae_fp_greater(mx,tolvector), __FILE__, __LINE__, "testevdunit.ap:2131"); - } - } - } - } - - /* - * Problem with highly separated eigenvalues (either with alternating - * sign - or all positive). Only a few iterations is performed, we - * want to check convergence properties on such problems. - */ - tollambda = 1.0E-9; - tolvector = 1.0E-4; - itscount = 5; - for(n=1; n<=25; n++) - { - for(m=1; m<=n; m++) - { - for(smode=0; smode<=2; smode++) - { - - /* - * Generate eigenproblem - */ - sgn = (double)(2*hqrnduniformi(&rs, 2, _state)-1); - decaya = 1.05; - ae_vector_set_length(&diaga, n, _state); - diaga.ptr.p_double[0] = ae_pow((double)(10), 2*hqrnduniformr(&rs, _state)-1, _state); - for(i=1; i<=n-1; i++) - { - diaga.ptr.p_double[i] = diaga.ptr.p_double[i-1]*sgn/(decaya*(1+0.01*hqrnduniformr(&rs, _state))); - } - for(i=m; i<=n-1; i++) - { - diaga.ptr.p_double[i] = diaga.ptr.p_double[i]/(100+10*hqrnduniformr(&rs, _state)); - } - rmatrixrndorthogonal(n, &qa, _state); - ae_matrix_set_length(&densea, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = (double)(0); - for(k=0; k<=n-1; k++) - { - v = v+qa.ptr.pp_double[k][i]*diaga.ptr.p_double[k]*qa.ptr.pp_double[k][j]; - } - densea.ptr.pp_double[i][j] = v; - } - } - isupper = ae_fp_greater(hqrnduniformr(&rs, _state),0.5); - ae_matrix_set_length(&halfa, n, n, _state); - sparsecreate(n, n, 0, &halfsa, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - halfa.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state); - if( j>=i&&isupper ) - { - halfa.ptr.pp_double[i][j] = densea.ptr.pp_double[i][j]; - sparseset(&halfsa, i, j, densea.ptr.pp_double[i][j], _state); - } - if( j<=i&&!isupper ) - { - halfa.ptr.pp_double[i][j] = densea.ptr.pp_double[i][j]; - sparseset(&halfsa, i, j, densea.ptr.pp_double[i][j], _state); - } - } - } - sformat = hqrnduniformi(&rs, 2, _state); - if( sformat==0 ) - { - sparseconverttocrs(&halfsa, _state); - } - if( sformat==1 ) - { - sparseconverttosks(&halfsa, _state); - } - - /* - * Solve with eigensolver operating in dense mode - */ - eigsubspacecreate(n, m, &s, _state); - eigsubspacesetcond(&s, (double)(0), itscount, _state); - if( smode==0 ) - { - - /* - * Dense mode - */ - eigsubspacesolvedenses(&s, &halfa, isupper, &sw, &sz, &rep, _state); - } - else - { - if( smode==1 ) - { - - /* - * Sparse mode - */ - eigsubspacesolvesparses(&s, &halfsa, isupper, &sw, &sz, &rep, _state); - } - else - { - if( smode==2 ) - { - - /* - * Out-of-core mode, symmetric version - * - * NOTE: we check that solver performs no more than ItsCount+2 calls - */ - callcount = 0; - eigsubspaceoocstart(&s, 0, _state); - while(eigsubspaceooccontinue(&s, _state)) - { - eigsubspaceoocgetrequestinfo(&s, &requesttype, &requestsize, _state); - ae_assert(requesttype==0, "EVDI: integrity check failed in unit test", _state); - ae_assert(requestsize>0, "EVDI: integrity check failed in unit test", _state); - eigsubspaceoocgetrequestdata(&s, &ra, _state); - rmatrixsetlengthatleast(&rb, n, requestsize, _state); - rmatrixgemm(n, requestsize, n, 1.0, &densea, 0, 0, 0, &ra, 0, 0, 0, 0.0, &rb, 0, 0, _state); - eigsubspaceoocsendresult(&s, &rb, _state); - callcount = callcount+1; - } - eigsubspaceoocstop(&s, &sw, &sz, &rep, _state); - ae_set_error_flag(errorflag, callcount>itscount+2, __FILE__, __LINE__, "testevdunit.ap:2238"); - } - else - { - ae_assert(ae_false, "unittest: integrity check failed", _state); - } - } - } - - /* - * Compare against reference values - */ - ae_set_error_flag(errorflag, rep.iterationscount>itscount, __FILE__, __LINE__, "testevdunit.ap:2246"); - for(i=0; i<=m-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(sw.ptr.p_double[i]-diaga.ptr.p_double[i], _state),tollambda), __FILE__, __LINE__, "testevdunit.ap:2249"); - v = ae_v_dotproduct(&qa.ptr.pp_double[i][0], 1, &sz.ptr.pp_double[0][i], sz.stride, ae_v_len(0,n-1)); - mx = (double)(0); - for(j=0; j<=n-1; j++) - { - mx = ae_maxreal(mx, ae_fabs(sz.ptr.pp_double[j][i]*ae_sign(v, _state)-qa.ptr.pp_double[i][j], _state), _state); - } - ae_set_error_flag(errorflag, ae_fp_greater(mx,tolvector), __FILE__, __LINE__, "testevdunit.ap:2254"); - } - } - } - } - - /* - * Problem with numerically zero matrix. We check ability to stop - * and to return orthogonal vectors. - */ - tollambda = 1.0E-9; - itscount = 5; - for(n=1; n<=25; n++) - { - for(m=1; m<=n; m++) - { - - /* - * Generate eigenproblem - */ - ae_matrix_set_length(&densea, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - densea.ptr.pp_double[i][j] = (double)(0); - } - } - - /* - * Solve with eigensolver operating in dense mode, - * iteration count based stopping condition. - */ - eigsubspacecreate(n, m, &s, _state); - eigsubspacesetcond(&s, (double)(0), itscount, _state); - eigsubspacesolvedenses(&s, &densea, ae_true, &sw, &sz, &rep, _state); - ae_set_error_flag(errorflag, rep.iterationscount>itscount, __FILE__, __LINE__, "testevdunit.ap:2283"); - for(i=0; i<=m-1; i++) - { - for(j=i; j<=m-1; j++) - { - v = ae_v_dotproduct(&sz.ptr.pp_double[0][i], sz.stride, &sz.ptr.pp_double[0][j], sz.stride, ae_v_len(0,n-1)); - if( j==i ) - { - v = v-1; - } - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v, _state),1.0E3*ae_machineepsilon), __FILE__, __LINE__, "testevdunit.ap:2291"); - } - ae_set_error_flag(errorflag, ae_fp_neq(sw.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testevdunit.ap:2293"); - } - - /* - * Solve with eigensolver operating in dense mode, - * eps-based stopping condition. - */ - eigsubspacecreate(n, m, &s, _state); - eigsubspacesetcond(&s, tollambda, 0, _state); - eigsubspacesolvedenses(&s, &densea, ae_true, &sw, &sz, &rep, _state); - for(i=0; i<=m-1; i++) - { - for(j=i; j<=m-1; j++) - { - v = ae_v_dotproduct(&sz.ptr.pp_double[0][i], sz.stride, &sz.ptr.pp_double[0][j], sz.stride, ae_v_len(0,n-1)); - if( j==i ) - { - v = v-1; - } - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v, _state),1.0E3*ae_machineepsilon), __FILE__, __LINE__, "testevdunit.ap:2310"); - } - ae_set_error_flag(errorflag, ae_fp_neq(sw.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testevdunit.ap:2312"); - } - } - } - - /* - * Test warm start functionality: - * * for many randomly generated problems... - * * ...solve original problem with EPS-based criterion - * * ...then apply small rank-1 correction to the matrix - * * ...and solve again, with warm start - * * ...and solve again, with explicit cold start - * * do so many times and calculate total iteration counts - * - * Iteration counts for warm starts should be significantly lower, - * whilst solution found should be within tolerances. - */ - cnta = 0; - cntb = 0; - cntc = 0; - eps = 1.0E-3; - nu = 0.001; - for(pass=1; pass<=50; pass++) - { - - /* - * Generate eigenproblem and rank-1 update - */ - n = 50+hqrnduniformi(&rs, 20, _state); - m = 1+hqrnduniformi(&rs, 5, _state); - ae_matrix_set_length(&ra, n, n, _state); - ae_matrix_set_length(&tmp2, n, n, _state); - ae_vector_set_length(&u, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - tmp2.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - rmatrixgemm(n, n, n, 1.0, &tmp2, 0, 0, 0, &tmp2, 0, 0, 1, 0.0, &ra, 0, 0, _state); - - /* - * Solve with eigensolver operating in cold-start mode, - * iteration count based stopping condition. - */ - eigsubspacecreate(n, m, &s, _state); - eigsubspacesetcond(&s, eps, 0, _state); - eigsubspacesolvedenses(&s, &ra, ae_true, &sw, &sz, &rep, _state); - cnta = cnta+rep.iterationscount; - - /* - * Solve with eigensolver operating in warm-start mode, - * iteration count based stopping condition. - */ - for(i=0; i<=n-1; i++) - { - u.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - rmatrixger(n, n, &ra, 0, 0, nu, &u, 0, &u, 0, _state); - eigsubspacesetwarmstart(&s, ae_true, _state); - eigsubspacesolvedenses(&s, &ra, ae_true, &sw, &sz, &rep, _state); - cntb = cntb+rep.iterationscount; - - /* - * Solve with eigensolver operating in explicit cold-start mode, - * iteration count based stopping condition. - */ - for(i=0; i<=n-1; i++) - { - u.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - rmatrixger(n, n, &ra, 0, 0, nu, &u, 0, &u, 0, _state); - eigsubspacesetwarmstart(&s, ae_false, _state); - eigsubspacesolvedenses(&s, &ra, ae_true, &sw, &sz, &rep, _state); - cntc = cntc+rep.iterationscount; - } - ae_set_error_flag(errorflag, ae_fp_greater((double)(cntb),0.66*cnta), __FILE__, __LINE__, "testevdunit.ap:2387"); - ae_set_error_flag(errorflag, ae_fp_less((double)(cntc),0.66*cnta), __FILE__, __LINE__, "testevdunit.ap:2388"); - ae_frame_leave(_state); -} - - - -static void testbasestatunit_testranking(ae_bool* err, ae_state *_state); - - - - - -ae_bool testbasestat(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_bool waserrors; - ae_bool s1errors; - ae_bool covcorrerrors; - ae_bool rankerrors; - double threshold; - ae_int_t i; - ae_int_t j; - ae_int_t n; - ae_int_t kx; - ae_int_t ky; - ae_int_t ctype; - ae_int_t cidxx; - ae_int_t cidxy; - ae_vector x; - ae_vector y; - ae_matrix mx; - ae_matrix my; - ae_matrix cc; - ae_matrix cp; - ae_matrix cs; - double mean; - double variance; - double skewness; - double kurtosis; - double adev; - double median; - double pv; - double v; - double tmean; - double tvariance; - double tskewness; - double tkurtosis; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&mx, 0, sizeof(mx)); - memset(&my, 0, sizeof(my)); - memset(&cc, 0, sizeof(cc)); - memset(&cp, 0, sizeof(cp)); - memset(&cs, 0, sizeof(cs)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&mx, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&my, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&cc, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&cp, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&cs, 0, 0, DT_REAL, _state, ae_true); - - - /* - * Primary settings - */ - waserrors = ae_false; - s1errors = ae_false; - covcorrerrors = ae_false; - rankerrors = ae_false; - threshold = 1000*ae_machineepsilon; - - /* - * Ranking - */ - testbasestatunit_testranking(&rankerrors, _state); - - /* - * * prepare X and Y - two test samples - * * test 1-sample coefficients - * * test for SampleMean, SampleVariance, - * SampleSkewness, SampleKurtosis. - */ - n = 10; - ae_vector_set_length(&x, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = ae_sqr((double)(i), _state); - } - samplemoments(&x, n, &mean, &variance, &skewness, &kurtosis, _state); - s1errors = s1errors||ae_fp_greater(ae_fabs(mean-28.5, _state),0.001); - s1errors = s1errors||ae_fp_greater(ae_fabs(variance-801.1667, _state),0.001); - s1errors = s1errors||ae_fp_greater(ae_fabs(skewness-0.5751, _state),0.001); - s1errors = s1errors||ae_fp_greater(ae_fabs(kurtosis+1.2666, _state),0.001); - tmean = samplemean(&x, n, _state); - tvariance = samplevariance(&x, n, _state); - tskewness = sampleskewness(&x, n, _state); - tkurtosis = samplekurtosis(&x, n, _state); - s1errors = s1errors||ae_fp_greater(ae_fabs(mean-tmean, _state),1.0E-15); - s1errors = s1errors||ae_fp_greater(ae_fabs(variance-tvariance, _state),1.0E-15); - s1errors = s1errors||ae_fp_greater(ae_fabs(skewness-tskewness, _state),1.0E-15); - s1errors = s1errors||ae_fp_greater(ae_fabs(kurtosis-tkurtosis, _state),1.0E-15); - sampleadev(&x, n, &adev, _state); - s1errors = s1errors||ae_fp_greater(ae_fabs(adev-23.2000, _state),0.001); - samplemedian(&x, n, &median, _state); - s1errors = s1errors||ae_fp_greater(ae_fabs(median-0.5*(16+25), _state),0.001); - for(i=0; i<=n-1; i++) - { - samplepercentile(&x, n, (double)i/(double)(n-1), &pv, _state); - s1errors = s1errors||ae_fp_greater(ae_fabs(pv-x.ptr.p_double[i], _state),0.001); - } - samplepercentile(&x, n, 0.5, &pv, _state); - s1errors = s1errors||ae_fp_greater(ae_fabs(pv-0.5*(16+25), _state),0.001); - - /* - * test covariance/correlation: - * * 2-sample coefficients - * - * We generate random matrices MX and MY - */ - n = 10; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = ae_sqr((double)(i), _state); - y.ptr.p_double[i] = (double)(i); - } - covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(pearsoncorr2(&x, &y, n, _state)-0.9627, _state),0.0001); - covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(spearmancorr2(&x, &y, n, _state)-1.0000, _state),0.0001); - covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(cov2(&x, &y, n, _state)-82.5000, _state),0.0001); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = ae_sqr(i-0.5*n, _state); - y.ptr.p_double[i] = (double)(i); - } - covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(pearsoncorr2(&x, &y, n, _state)+0.3676, _state),0.0001); - covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(spearmancorr2(&x, &y, n, _state)+0.2761, _state),0.0001); - covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(cov2(&x, &y, n, _state)+9.1667, _state),0.0001); - - /* - * test covariance/correlation: - * * matrix covariance/correlation - * * matrix cross-covariance/cross-correlation - * - * We generate random matrices MX and MY which contain KX (KY) - * columns, all except one are random, one of them is constant. - * We test that function (a) do not crash on constant column, - * and (b) return variances/correlations that are exactly zero - * for this column. - * - * CType control variable controls type of constant: 0 - no constant - * column, 1 - zero column, 2 - nonzero column with value whose - * binary representation contains many non-zero bits. Using such - * type of constant column we are able to ensure than even in the - * presense of roundoff error functions correctly detect constant - * columns. - */ - for(n=0; n<=10; n++) - { - if( n>0 ) - { - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - } - for(ctype=0; ctype<=2; ctype++) - { - for(kx=1; kx<=10; kx++) - { - for(ky=1; ky<=10; ky++) - { - - /* - * Fill matrices, add constant column (when CType=1 or =2) - */ - cidxx = -1; - cidxy = -1; - if( n>0 ) - { - ae_matrix_set_length(&mx, n, kx, _state); - ae_matrix_set_length(&my, n, ky, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=kx-1; j++) - { - mx.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - for(j=0; j<=ky-1; j++) - { - my.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - if( ctype==1 ) - { - cidxx = ae_randominteger(kx, _state); - cidxy = ae_randominteger(ky, _state); - for(i=0; i<=n-1; i++) - { - mx.ptr.pp_double[i][cidxx] = 0.0; - my.ptr.pp_double[i][cidxy] = 0.0; - } - } - if( ctype==2 ) - { - cidxx = ae_randominteger(kx, _state); - cidxy = ae_randominteger(ky, _state); - v = ae_sqrt((double)(ae_randominteger(kx, _state)+1)/(double)kx, _state); - for(i=0; i<=n-1; i++) - { - mx.ptr.pp_double[i][cidxx] = v; - my.ptr.pp_double[i][cidxy] = v; - } - } - } - - /* - * test covariance/correlation matrix using - * 2-sample functions as reference point. - * - * We also test that coefficients for constant variables - * are exactly zero. - */ - covm(&mx, n, kx, &cc, _state); - pearsoncorrm(&mx, n, kx, &cp, _state); - spearmancorrm(&mx, n, kx, &cs, _state); - for(i=0; i<=kx-1; i++) - { - for(j=0; j<=kx-1; j++) - { - if( n>0 ) - { - ae_v_move(&x.ptr.p_double[0], 1, &mx.ptr.pp_double[0][i], mx.stride, ae_v_len(0,n-1)); - ae_v_move(&y.ptr.p_double[0], 1, &mx.ptr.pp_double[0][j], mx.stride, ae_v_len(0,n-1)); - } - covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(cov2(&x, &y, n, _state)-cc.ptr.pp_double[i][j], _state),threshold); - covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(pearsoncorr2(&x, &y, n, _state)-cp.ptr.pp_double[i][j], _state),threshold); - covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(spearmancorr2(&x, &y, n, _state)-cs.ptr.pp_double[i][j], _state),threshold); - } - } - if( ctype!=0&&n>0 ) - { - for(i=0; i<=kx-1; i++) - { - covcorrerrors = covcorrerrors||ae_fp_neq(cc.ptr.pp_double[i][cidxx],(double)(0)); - covcorrerrors = covcorrerrors||ae_fp_neq(cc.ptr.pp_double[cidxx][i],(double)(0)); - covcorrerrors = covcorrerrors||ae_fp_neq(cp.ptr.pp_double[i][cidxx],(double)(0)); - covcorrerrors = covcorrerrors||ae_fp_neq(cp.ptr.pp_double[cidxx][i],(double)(0)); - covcorrerrors = covcorrerrors||ae_fp_neq(cs.ptr.pp_double[i][cidxx],(double)(0)); - covcorrerrors = covcorrerrors||ae_fp_neq(cs.ptr.pp_double[cidxx][i],(double)(0)); - } - } - - /* - * test cross-covariance/cross-correlation matrix using - * 2-sample functions as reference point. - * - * We also test that coefficients for constant variables - * are exactly zero. - */ - covm2(&mx, &my, n, kx, ky, &cc, _state); - pearsoncorrm2(&mx, &my, n, kx, ky, &cp, _state); - spearmancorrm2(&mx, &my, n, kx, ky, &cs, _state); - for(i=0; i<=kx-1; i++) - { - for(j=0; j<=ky-1; j++) - { - if( n>0 ) - { - ae_v_move(&x.ptr.p_double[0], 1, &mx.ptr.pp_double[0][i], mx.stride, ae_v_len(0,n-1)); - ae_v_move(&y.ptr.p_double[0], 1, &my.ptr.pp_double[0][j], my.stride, ae_v_len(0,n-1)); - } - covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(cov2(&x, &y, n, _state)-cc.ptr.pp_double[i][j], _state),threshold); - covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(pearsoncorr2(&x, &y, n, _state)-cp.ptr.pp_double[i][j], _state),threshold); - covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(spearmancorr2(&x, &y, n, _state)-cs.ptr.pp_double[i][j], _state),threshold); - } - } - if( ctype!=0&&n>0 ) - { - for(i=0; i<=kx-1; i++) - { - covcorrerrors = covcorrerrors||ae_fp_neq(cc.ptr.pp_double[i][cidxy],(double)(0)); - covcorrerrors = covcorrerrors||ae_fp_neq(cp.ptr.pp_double[i][cidxy],(double)(0)); - covcorrerrors = covcorrerrors||ae_fp_neq(cs.ptr.pp_double[i][cidxy],(double)(0)); - } - for(j=0; j<=ky-1; j++) - { - covcorrerrors = covcorrerrors||ae_fp_neq(cc.ptr.pp_double[cidxx][j],(double)(0)); - covcorrerrors = covcorrerrors||ae_fp_neq(cp.ptr.pp_double[cidxx][j],(double)(0)); - covcorrerrors = covcorrerrors||ae_fp_neq(cs.ptr.pp_double[cidxx][j],(double)(0)); - } - } - } - } - } - } - - /* - * Final report - */ - waserrors = (s1errors||covcorrerrors)||rankerrors; - if( !silent ) - { - printf("DESC.STAT TEST\n"); - printf("TOTAL RESULTS: "); - if( !waserrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* 1-SAMPLE FUNCTIONALITY: "); - if( !s1errors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* CORRELATION/COVARIATION: "); - if( !covcorrerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* RANKING: "); - if( !rankerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST SUMMARY: FAILED\n"); - } - else - { - printf("TEST SUMMARY: PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function tests ranking functionality. In case of failure it sets -Err parameter to True; this parameter is left unchanged otherwise. -*************************************************************************/ -static void testbasestatunit_testranking(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t testk; - ae_int_t npoints; - ae_int_t nfeatures; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_matrix xy0; - ae_matrix xy1; - ae_matrix xy2; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&xy0, 0, sizeof(xy0)); - memset(&xy1, 0, sizeof(xy1)); - memset(&xy2, 0, sizeof(xy2)); - ae_matrix_init(&xy0, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true); - - - /* - * Test 1 - large array, unique ranks, each row is obtained as follows: - * * we generate X[i=0..N-1] = I - * * we add random noise: X[i] := X[i] + 0.2*randomreal()-0.1 - * * we perform random permutation - * - * Such dataset has following properties: - * * all data are unique within their rows - * * rank(X[i]) = round(X[i]) - * - * We perform several tests with different NPoints/NFeatures. - */ - for(testk=0; testk<=2; testk++) - { - - /* - * Select problem size - */ - if( testk==0 ) - { - npoints = 200; - nfeatures = 1000; - } - else - { - if( testk==1 ) - { - npoints = 1000; - nfeatures = 200; - } - else - { - npoints = ae_round(ae_sqrt(smpactivationlevel(_state), _state), _state); - nfeatures = ae_round(ae_sqrt(smpactivationlevel(_state), _state), _state); - } - } - - /* - * Generate XY0, XY1, XY2 - */ - ae_matrix_set_length(&xy0, npoints, nfeatures, _state); - ae_matrix_set_length(&xy1, npoints, nfeatures, _state); - ae_matrix_set_length(&xy2, npoints, nfeatures, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nfeatures-1; j++) - { - xy0.ptr.pp_double[i][j] = j+0.2*ae_randomreal(_state)-0.1; - } - for(j=0; j<=nfeatures-2; j++) - { - k = ae_randominteger(nfeatures-j, _state); - if( k!=0 ) - { - v = xy0.ptr.pp_double[i][j]; - xy0.ptr.pp_double[i][j] = xy0.ptr.pp_double[i][j+k]; - xy0.ptr.pp_double[i][j+k] = v; - } - } - for(j=0; j<=nfeatures-1; j++) - { - xy1.ptr.pp_double[i][j] = xy0.ptr.pp_double[i][j]; - xy2.ptr.pp_double[i][j] = xy0.ptr.pp_double[i][j]; - } - } - - /* - * Test uncentered ranks - */ - rankdata(&xy0, npoints, nfeatures, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nfeatures-1; j++) - { - if( ae_fp_neq(xy0.ptr.pp_double[i][j],(double)(ae_round(xy2.ptr.pp_double[i][j], _state))) ) - { - *err = ae_true; - } - } - } - - /* - * Test centered ranks: - * they must be equal to uncentered ranks minus (NFeatures-1)/2 - */ - rankdatacentered(&xy1, npoints, nfeatures, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nfeatures-1; j++) - { - if( ae_fp_neq(xy1.ptr.pp_double[i][j],ae_round(xy2.ptr.pp_double[i][j], _state)-(double)(nfeatures-1)/(double)2) ) - { - *err = ae_true; - } - } - } - } - - /* - * Test correct handling of tied ranks - */ - npoints = 3; - nfeatures = 4; - ae_matrix_set_length(&xy0, npoints, nfeatures, _state); - ae_matrix_set_length(&xy1, npoints, nfeatures, _state); - xy0.ptr.pp_double[0][0] = 2.25; - xy0.ptr.pp_double[0][1] = 3.75; - xy0.ptr.pp_double[0][2] = 3.25; - xy0.ptr.pp_double[0][3] = 2.25; - xy0.ptr.pp_double[1][0] = (double)(2); - xy0.ptr.pp_double[1][1] = (double)(2); - xy0.ptr.pp_double[1][2] = (double)(2); - xy0.ptr.pp_double[1][3] = (double)(7); - xy0.ptr.pp_double[2][0] = (double)(9); - xy0.ptr.pp_double[2][1] = (double)(9); - xy0.ptr.pp_double[2][2] = (double)(9); - xy0.ptr.pp_double[2][3] = (double)(9); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nfeatures-1; j++) - { - xy1.ptr.pp_double[i][j] = xy0.ptr.pp_double[i][j]; - } - } - rankdata(&xy0, npoints, nfeatures, _state); - if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[0][0]-0.5, _state),10*ae_machineepsilon) ) - { - *err = ae_true; - } - if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[0][1]-3.0, _state),10*ae_machineepsilon) ) - { - *err = ae_true; - } - if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[0][2]-2.0, _state),10*ae_machineepsilon) ) - { - *err = ae_true; - } - if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[0][3]-0.5, _state),10*ae_machineepsilon) ) - { - *err = ae_true; - } - if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[1][0]-1.0, _state),10*ae_machineepsilon) ) - { - *err = ae_true; - } - if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[1][1]-1.0, _state),10*ae_machineepsilon) ) - { - *err = ae_true; - } - if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[1][2]-1.0, _state),10*ae_machineepsilon) ) - { - *err = ae_true; - } - if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[1][3]-3.0, _state),10*ae_machineepsilon) ) - { - *err = ae_true; - } - if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[2][0]-1.5, _state),10*ae_machineepsilon) ) - { - *err = ae_true; - } - if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[2][1]-1.5, _state),10*ae_machineepsilon) ) - { - *err = ae_true; - } - if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[2][2]-1.5, _state),10*ae_machineepsilon) ) - { - *err = ae_true; - } - if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[2][3]-1.5, _state),10*ae_machineepsilon) ) - { - *err = ae_true; - } - rankdatacentered(&xy1, npoints, nfeatures, _state); - if( ae_fp_greater(ae_fabs(xy1.ptr.pp_double[0][0]+1.0, _state),10*ae_machineepsilon) ) - { - *err = ae_true; - } - if( ae_fp_greater(ae_fabs(xy1.ptr.pp_double[0][1]-1.5, _state),10*ae_machineepsilon) ) - { - *err = ae_true; - } - if( ae_fp_greater(ae_fabs(xy1.ptr.pp_double[0][2]-0.5, _state),10*ae_machineepsilon) ) - { - *err = ae_true; - } - if( ae_fp_greater(ae_fabs(xy1.ptr.pp_double[0][3]+1.0, _state),10*ae_machineepsilon) ) - { - *err = ae_true; - } - if( ae_fp_greater(ae_fabs(xy1.ptr.pp_double[1][0]+0.5, _state),10*ae_machineepsilon) ) - { - *err = ae_true; - } - if( ae_fp_greater(ae_fabs(xy1.ptr.pp_double[1][1]+0.5, _state),10*ae_machineepsilon) ) - { - *err = ae_true; - } - if( ae_fp_greater(ae_fabs(xy1.ptr.pp_double[1][2]+0.5, _state),10*ae_machineepsilon) ) - { - *err = ae_true; - } - if( ae_fp_greater(ae_fabs(xy1.ptr.pp_double[1][3]-1.5, _state),10*ae_machineepsilon) ) - { - *err = ae_true; - } - if( ae_fp_neq(xy1.ptr.pp_double[2][0],(double)(0)) ) - { - *err = ae_true; - } - if( ae_fp_neq(xy1.ptr.pp_double[2][1],(double)(0)) ) - { - *err = ae_true; - } - if( ae_fp_neq(xy1.ptr.pp_double[2][2],(double)(0)) ) - { - *err = ae_true; - } - if( ae_fp_neq(xy1.ptr.pp_double[2][3],(double)(0)) ) - { - *err = ae_true; - } - ae_frame_leave(_state); -} - - - -static void testpcaunit_calculatemv(/* Real */ ae_vector* x, - ae_int_t n, - double* mean, - double* means, - double* stddev, - double* stddevs, - ae_state *_state); - - - - - -ae_bool testpca(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t maxn; - ae_int_t maxm; - double threshold; - ae_int_t m; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t info; - ae_vector means; - ae_vector s; - ae_vector s2; - ae_vector t2; - ae_vector t3; - ae_matrix v; - ae_matrix v2; - ae_matrix x; - double t; - double h; - sparsematrix xsparse; - double tmean; - double tmeans; - double tstddev; - double tstddevs; - double tmean2; - double tmeans2; - double tstddev2; - double tstddevs2; - hqrndstate rs; - ae_int_t requested; - double tolreduced; - double varcomplete; - double varreduced; - ae_int_t pass; - ae_bool pcaconverrors; - ae_bool pcaorterrors; - ae_bool pcavarerrors; - ae_bool pcaopterrors; - ae_bool pcadensesubspaceerrors; - ae_bool pcasparsesubspaceerrors; - ae_bool waserrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&means, 0, sizeof(means)); - memset(&s, 0, sizeof(s)); - memset(&s2, 0, sizeof(s2)); - memset(&t2, 0, sizeof(t2)); - memset(&t3, 0, sizeof(t3)); - memset(&v, 0, sizeof(v)); - memset(&v2, 0, sizeof(v2)); - memset(&x, 0, sizeof(x)); - memset(&xsparse, 0, sizeof(xsparse)); - memset(&rs, 0, sizeof(rs)); - ae_vector_init(&means, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t3, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&v2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&x, 0, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&xsparse, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Primary settings - */ - maxm = 10; - maxn = 100; - threshold = 1.0E5*ae_machineepsilon; - waserrors = ae_false; - pcaconverrors = ae_false; - pcaorterrors = ae_false; - pcavarerrors = ae_false; - pcaopterrors = ae_false; - pcadensesubspaceerrors = ae_false; - pcasparsesubspaceerrors = ae_false; - - /* - * Test 1: N random points in M-dimensional space, full PCA. - */ - for(m=1; m<=maxm; m++) - { - for(n=1; n<=maxn; n++) - { - - /* - * Generate task - */ - ae_matrix_set_length(&x, n-1+1, m-1+1, _state); - ae_vector_set_length(&means, m-1+1, _state); - for(j=0; j<=m-1; j++) - { - means.ptr.p_double[j] = 1.5*ae_randomreal(_state)-0.75; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_double[i][j] = means.ptr.p_double[j]+(2*ae_randomreal(_state)-1); - } - } - - /* - * Solve - */ - pcabuildbasis(&x, n, m, &info, &s, &v, _state); - if( info!=1 ) - { - pcaconverrors = ae_true; - continue; - } - - /* - * Orthogonality test - */ - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - t = ae_v_dotproduct(&v.ptr.pp_double[0][i], v.stride, &v.ptr.pp_double[0][j], v.stride, ae_v_len(0,m-1)); - if( i==j ) - { - t = t-1; - } - pcaorterrors = pcaorterrors||ae_fp_greater(ae_fabs(t, _state),threshold); - } - } - - /* - * Variance test - */ - ae_vector_set_length(&t2, n-1+1, _state); - for(k=0; k<=m-1; k++) - { - for(i=0; i<=n-1; i++) - { - t = ae_v_dotproduct(&x.ptr.pp_double[i][0], 1, &v.ptr.pp_double[0][k], v.stride, ae_v_len(0,m-1)); - t2.ptr.p_double[i] = t; - } - testpcaunit_calculatemv(&t2, n, &tmean, &tmeans, &tstddev, &tstddevs, _state); - if( n!=1 ) - { - t = ae_sqr(tstddev, _state)*n/(n-1); - } - else - { - t = (double)(0); - } - pcavarerrors = pcavarerrors||ae_fp_greater(ae_fabs(t-s.ptr.p_double[k], _state),threshold); - } - for(k=0; k<=m-2; k++) - { - pcavarerrors = pcavarerrors||ae_fp_less(s.ptr.p_double[k],s.ptr.p_double[k+1]); - } - - /* - * Optimality: different perturbations in V[..,0] can't - * increase variance of projection - can only decrease. - */ - ae_vector_set_length(&t2, n-1+1, _state); - ae_vector_set_length(&t3, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - t = ae_v_dotproduct(&x.ptr.pp_double[i][0], 1, &v.ptr.pp_double[0][0], v.stride, ae_v_len(0,m-1)); - t2.ptr.p_double[i] = t; - } - testpcaunit_calculatemv(&t2, n, &tmean, &tmeans, &tstddev, &tstddevs, _state); - for(k=0; k<=2*m-1; k++) - { - h = 0.001; - if( k%2!=0 ) - { - h = -h; - } - ae_v_move(&t3.ptr.p_double[0], 1, &t2.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_addd(&t3.ptr.p_double[0], 1, &x.ptr.pp_double[0][k/2], x.stride, ae_v_len(0,n-1), h); - t = (double)(0); - for(j=0; j<=m-1; j++) - { - if( j!=k/2 ) - { - t = t+ae_sqr(v.ptr.pp_double[j][0], _state); - } - else - { - t = t+ae_sqr(v.ptr.pp_double[j][0]+h, _state); - } - } - t = 1/ae_sqrt(t, _state); - ae_v_muld(&t3.ptr.p_double[0], 1, ae_v_len(0,n-1), t); - testpcaunit_calculatemv(&t3, n, &tmean2, &tmeans2, &tstddev2, &tstddevs2, _state); - pcaopterrors = pcaopterrors||ae_fp_greater(tstddev2,tstddev+threshold); - } - } - } - - /* - * Special test for N=0 - */ - for(m=1; m<=maxm; m++) - { - - /* - * Solve - */ - pcabuildbasis(&x, 0, m, &info, &s, &v, _state); - if( info!=1 ) - { - pcaconverrors = ae_true; - continue; - } - - /* - * Orthogonality test - */ - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - t = ae_v_dotproduct(&v.ptr.pp_double[0][i], v.stride, &v.ptr.pp_double[0][j], v.stride, ae_v_len(0,m-1)); - if( i==j ) - { - t = t-1; - } - pcaorterrors = pcaorterrors||ae_fp_greater(ae_fabs(t, _state),threshold); - } - } - } - - /* - * Test dense reduced subspace PCA on randomly generated matrix. Because - * matrix is random, it may have bad spectral properties, so large - * number of iterations is performed. - * - * Following properties are tested: - * * principal vectors are orthogonal - * * variance values are computed correctly - * * variance values are decreasing - * * variance by inexact reduced PCA deviates from variance explained - * by top REQUESTED vectors of complete PCA by at most TolReduced. - */ - tolreduced = 1.0E-3; - for(m=1; m<=maxm; m++) - { - for(n=1; n<=maxn; n++) - { - - /* - * Generate task - */ - requested = 1+hqrnduniformi(&rs, m, _state); - ae_vector_set_length(&means, m, _state); - for(j=0; j<=m-1; j++) - { - means.ptr.p_double[j] = 100*hqrndnormal(&rs, _state); - } - ae_matrix_set_length(&x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_double[i][j] = hqrndnormal(&rs, _state)+means.ptr.p_double[j]; - } - } - - /* - * Solve - */ - pcatruncatedsubspace(&x, n, m, requested, 1.0E-9, 0, &s, &v, _state); - - /* - * Orthogonality test - */ - for(i=0; i<=requested-1; i++) - { - for(j=0; j<=requested-1; j++) - { - t = ae_v_dotproduct(&v.ptr.pp_double[0][i], v.stride, &v.ptr.pp_double[0][j], v.stride, ae_v_len(0,m-1)); - if( i==j ) - { - t = t-1; - } - ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_greater(ae_fabs(t, _state),threshold), __FILE__, __LINE__, "testpcaunit.ap:217"); - } - } - - /* - * Variance test - */ - ae_vector_set_length(&t2, n, _state); - for(k=0; k<=requested-1; k++) - { - for(i=0; i<=n-1; i++) - { - t = ae_v_dotproduct(&x.ptr.pp_double[i][0], 1, &v.ptr.pp_double[0][k], v.stride, ae_v_len(0,m-1)); - t2.ptr.p_double[i] = t; - } - testpcaunit_calculatemv(&t2, n, &tmean, &tmeans, &tstddev, &tstddevs, _state); - if( n!=1 ) - { - t = ae_sqr(tstddev, _state)*n/(n-1); - } - else - { - t = (double)(0); - } - ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_greater(ae_fabs(t-s.ptr.p_double[k], _state),threshold), __FILE__, __LINE__, "testpcaunit.ap:236"); - } - for(k=0; k<=requested-2; k++) - { - ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_less(ae_fabs(s.ptr.p_double[k], _state),ae_fabs(s.ptr.p_double[k+1], _state)), __FILE__, __LINE__, "testpcaunit.ap:239"); - } - for(k=0; k<=requested-1; k++) - { - ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_less_eq(s.ptr.p_double[k],(double)(0))&&ae_fp_greater(ae_fabs(s.ptr.p_double[k], _state),1000*ae_machineepsilon*ae_fabs(s.ptr.p_double[0], _state)), __FILE__, __LINE__, "testpcaunit.ap:241"); - } - - /* - * Compare variance explained by top REQUESTED vectors from - * full PCA and variance explained by reduced PCA. - */ - pcabuildbasis(&x, n, m, &info, &s2, &v2, _state); - ae_assert(info>0, "PCA error: solver nonconvergence", _state); - varcomplete = 0.0; - varreduced = 0.0; - for(k=0; k<=requested-1; k++) - { - varreduced = varreduced+s.ptr.p_double[k]; - varcomplete = varcomplete+s2.ptr.p_double[k]; - } - ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_less((varreduced-varcomplete)/varcomplete,-tolreduced), __FILE__, __LINE__, "testpcaunit.ap:256"); - ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_greater((varreduced-varcomplete)/varcomplete,1.0E5*ae_machineepsilon), __FILE__, __LINE__, "testpcaunit.ap:257"); - } - } - - /* - * Test dense subspace reduced PCA on specially designed problem with good - * spectral properties. Only limited number of iterations is performed, - * and we expect fast convergence. - */ - for(pass=0; pass<=3; pass++) - { - - /* - * Generate task - */ - m = -1; - requested = -1; - if( pass==0 ) - { - m = 50+hqrnduniformi(&rs, 50, _state); - requested = 1+hqrnduniformi(&rs, 10, _state); - } - if( pass==1 ) - { - m = 100+hqrnduniformi(&rs, 50, _state); - requested = 1+hqrnduniformi(&rs, 10, _state); - } - if( pass==2 ) - { - m = 100+hqrnduniformi(&rs, 50, _state); - requested = 25+hqrnduniformi(&rs, 10, _state); - } - if( pass==3 ) - { - m = 200+hqrnduniformi(&rs, 200, _state); - requested = 1+hqrnduniformi(&rs, 10, _state); - } - ae_assert(m>0&&requested>0, "PCA test: integrity failure", _state); - n = 2*m; - tolreduced = 1.0E-3; - ae_matrix_set_length(&x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_double[i][j] = (double)(0); - } - } - x.ptr.pp_double[0][0] = 1.0; - for(i=1; i<=m-1; i++) - { - x.ptr.pp_double[i][i] = x.ptr.pp_double[i-1][i-1]*(1/1.05); - } - rmatrixrndorthogonalfromtheleft(&x, n, m, _state); - rmatrixrndorthogonalfromtheright(&x, n, m, _state); - - /* - * Solve - */ - if( ae_fp_greater(hqrnduniformr(&rs, _state),0.5) ) - { - pcatruncatedsubspace(&x, n, m, requested, 0.0, 20, &s, &v, _state); - } - else - { - pcatruncatedsubspace(&x, n, m, requested, 0.0, 0, &s, &v, _state); - } - - /* - * Orthogonality test - */ - for(i=0; i<=requested-1; i++) - { - for(j=0; j<=requested-1; j++) - { - t = ae_v_dotproduct(&v.ptr.pp_double[0][i], v.stride, &v.ptr.pp_double[0][j], v.stride, ae_v_len(0,m-1)); - if( i==j ) - { - t = t-1; - } - ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_greater(ae_fabs(t, _state),threshold), __FILE__, __LINE__, "testpcaunit.ap:323"); - } - } - - /* - * Variance test - */ - ae_vector_set_length(&t2, n, _state); - for(k=0; k<=requested-1; k++) - { - for(i=0; i<=n-1; i++) - { - t = ae_v_dotproduct(&x.ptr.pp_double[i][0], 1, &v.ptr.pp_double[0][k], v.stride, ae_v_len(0,m-1)); - t2.ptr.p_double[i] = t; - } - testpcaunit_calculatemv(&t2, n, &tmean, &tmeans, &tstddev, &tstddevs, _state); - if( n!=1 ) - { - t = ae_sqr(tstddev, _state)*n/(n-1); - } - else - { - t = (double)(0); - } - ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_greater(ae_fabs(t-s.ptr.p_double[k], _state),threshold), __FILE__, __LINE__, "testpcaunit.ap:342"); - } - for(k=0; k<=requested-2; k++) - { - ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_less(s.ptr.p_double[k],s.ptr.p_double[k+1]), __FILE__, __LINE__, "testpcaunit.ap:345"); - } - - /* - * Compare variance explained by top REQUESTED vectors from - * full PCA and variance explained by reduced PCA. - */ - pcabuildbasis(&x, n, m, &info, &s2, &v2, _state); - ae_assert(info>0, "PCA error: solver nonconvergence", _state); - varcomplete = 0.0; - varreduced = 0.0; - for(k=0; k<=requested-1; k++) - { - varreduced = varreduced+s.ptr.p_double[k]; - varcomplete = varcomplete+s2.ptr.p_double[k]; - } - ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_less((varreduced-varcomplete)/varcomplete,-tolreduced), __FILE__, __LINE__, "testpcaunit.ap:360"); - ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_greater((varreduced-varcomplete)/varcomplete,1.0E5*ae_machineepsilon), __FILE__, __LINE__, "testpcaunit.ap:361"); - } - - /* - * Test sparse reduced subspace PCA on randomly generated matrix with - * two non-zero elements at each row. Because matrix is random, it may - * have bad spectral properties, so large number of iterations is performed. - * - * Following properties are tested: - * * principal vectors are orthogonal - * * variance values are computed correctly - * * variance values are decreasing - * * variance by inexact reduced PCA deviates from variance explained - * by top REQUESTED vectors of complete PCA by at most TolReduced. - */ - tolreduced = 1.0E-3; - for(m=1; m<=maxm; m++) - { - for(n=1; n<=maxn; n++) - { - - /* - * Generate task - */ - requested = 1+hqrnduniformi(&rs, m, _state); - ae_vector_set_length(&means, m, _state); - for(j=0; j<=m-1; j++) - { - means.ptr.p_double[j] = 100*hqrndnormal(&rs, _state); - } - sparsecreate(n, m, 0, &xsparse, _state); - for(i=0; i<=n-1; i++) - { - j = hqrnduniformi(&rs, m, _state); - sparseset(&xsparse, i, j, hqrndnormal(&rs, _state)+means.ptr.p_double[j], _state); - j = hqrnduniformi(&rs, m, _state); - sparseset(&xsparse, i, j, hqrndnormal(&rs, _state)+means.ptr.p_double[j], _state); - } - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - sparseconverttocrs(&xsparse, _state); - } - ae_matrix_set_length(&x, n, m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_double[i][j] = sparseget(&xsparse, i, j, _state); - } - } - - /* - * Solve - */ - pcatruncatedsubspacesparse(&xsparse, n, m, requested, 1.0E-9, 0, &s, &v, _state); - - /* - * Orthogonality test - */ - for(i=0; i<=requested-1; i++) - { - for(j=0; j<=requested-1; j++) - { - t = ae_v_dotproduct(&v.ptr.pp_double[0][i], v.stride, &v.ptr.pp_double[0][j], v.stride, ae_v_len(0,m-1)); - if( i==j ) - { - t = t-1; - } - ae_set_error_flag(&pcasparsesubspaceerrors, ae_fp_greater(ae_fabs(t, _state),threshold), __FILE__, __LINE__, "testpcaunit.ap:417"); - } - } - - /* - * Variance test - */ - ae_vector_set_length(&t2, n, _state); - for(k=0; k<=requested-1; k++) - { - for(i=0; i<=n-1; i++) - { - t = ae_v_dotproduct(&x.ptr.pp_double[i][0], 1, &v.ptr.pp_double[0][k], v.stride, ae_v_len(0,m-1)); - t2.ptr.p_double[i] = t; - } - testpcaunit_calculatemv(&t2, n, &tmean, &tmeans, &tstddev, &tstddevs, _state); - if( n!=1 ) - { - t = ae_sqr(tstddev, _state)*n/(n-1); - } - else - { - t = (double)(0); - } - ae_set_error_flag(&pcasparsesubspaceerrors, ae_fp_greater(ae_fabs(t-s.ptr.p_double[k], _state),threshold*rmaxabs3(t, s.ptr.p_double[k], 1.0, _state)), __FILE__, __LINE__, "testpcaunit.ap:436"); - } - for(k=0; k<=requested-2; k++) - { - ae_set_error_flag(&pcasparsesubspaceerrors, ae_fp_less(ae_fabs(s.ptr.p_double[k], _state),ae_fabs(s.ptr.p_double[k+1], _state)), __FILE__, __LINE__, "testpcaunit.ap:439"); - } - for(k=0; k<=requested-1; k++) - { - ae_set_error_flag(&pcasparsesubspaceerrors, ae_fp_less_eq(s.ptr.p_double[k],(double)(0))&&ae_fp_greater(ae_fabs(s.ptr.p_double[k], _state),1000*ae_machineepsilon*ae_maxreal(ae_fabs(s.ptr.p_double[0], _state), (double)(1), _state)), __FILE__, __LINE__, "testpcaunit.ap:441"); - } - - /* - * Compare variance explained by top REQUESTED vectors from - * full PCA and variance explained by reduced PCA. - */ - pcabuildbasis(&x, n, m, &info, &s2, &v2, _state); - ae_assert(info>0, "PCA error: solver nonconvergence", _state); - varcomplete = 0.0; - varreduced = 0.0; - for(k=0; k<=requested-1; k++) - { - varreduced = varreduced+s.ptr.p_double[k]; - varcomplete = varcomplete+s2.ptr.p_double[k]; - } - ae_set_error_flag(&pcasparsesubspaceerrors, ae_fp_less((varreduced-varcomplete)/ae_maxreal(varcomplete, (double)(1), _state),-tolreduced), __FILE__, __LINE__, "testpcaunit.ap:456"); - ae_set_error_flag(&pcasparsesubspaceerrors, ae_fp_greater((varreduced-varcomplete)/ae_maxreal(varcomplete, (double)(1), _state),1.0E5*ae_machineepsilon), __FILE__, __LINE__, "testpcaunit.ap:457"); - } - } - - /* - * Final report - */ - waserrors = ((((pcaconverrors||pcaorterrors)||pcavarerrors)||pcaopterrors)||pcadensesubspaceerrors)||pcasparsesubspaceerrors; - if( !silent ) - { - printf("PCA TEST\n"); - printf("COMPLETE PCA:\n"); - printf("* CONVERGENCE "); - if( !pcaconverrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* ORTOGONALITY "); - if( !pcaorterrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* VARIANCE REPORT "); - if( !pcavarerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* OPTIMALITY "); - if( !pcaopterrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("SUBSPACE PCA:\n"); - printf("* DENSE SUBSPACE PCA "); - if( !pcadensesubspaceerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* SPARSE SUBSPACE PCA "); - if( !pcasparsesubspaceerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST SUMMARY: FAILED\n"); - } - else - { - printf("TEST SUMMARY: PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Moments estimates and their errors -*************************************************************************/ -static void testpcaunit_calculatemv(/* Real */ ae_vector* x, - ae_int_t n, - double* mean, - double* means, - double* stddev, - double* stddevs, - ae_state *_state) -{ - ae_int_t i; - double v1; - double v2; - double variance; - - *mean = 0; - *means = 0; - *stddev = 0; - *stddevs = 0; - - *mean = (double)(0); - *means = (double)(1); - *stddev = (double)(0); - *stddevs = (double)(1); - variance = (double)(0); - if( n<=1 ) - { - return; - } - - /* - * Mean - */ - for(i=0; i<=n-1; i++) - { - *mean = *mean+x->ptr.p_double[i]; - } - *mean = *mean/n; - - /* - * Variance (using corrected two-pass algorithm) - */ - if( n!=1 ) - { - v1 = (double)(0); - for(i=0; i<=n-1; i++) - { - v1 = v1+ae_sqr(x->ptr.p_double[i]-(*mean), _state); - } - v2 = (double)(0); - for(i=0; i<=n-1; i++) - { - v2 = v2+(x->ptr.p_double[i]-(*mean)); - } - v2 = ae_sqr(v2, _state)/n; - variance = (v1-v2)/n; - if( ae_fp_less(variance,(double)(0)) ) - { - variance = (double)(0); - } - *stddev = ae_sqrt(variance, _state); - } - - /* - * Errors - */ - *means = *stddev/ae_sqrt((double)(n), _state); - *stddevs = *stddev*ae_sqrt((double)(2), _state)/ae_sqrt((double)(n-1), _state); -} - - - -static void testbdssunit_unset1di(/* Integer */ ae_vector* a, - ae_state *_state); - - - - - -/************************************************************************* -Testing BDSS operations -*************************************************************************/ -ae_bool testbdss(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t pass; - ae_int_t passcount; - ae_int_t maxn; - ae_int_t maxnq; - ae_vector a; - ae_vector a0; - ae_vector at; - ae_matrix p; - ae_vector thresholds; - ae_int_t ni; - ae_vector c; - ae_vector p1; - ae_vector p2; - ae_vector ties; - ae_vector pt1; - ae_vector pt2; - ae_int_t tiecount; - ae_int_t c1; - ae_int_t c0; - ae_int_t nc; - ae_vector tmp; - ae_vector sortrbuf; - ae_vector sortrbuf2; - ae_vector sortibuf; - double pal; - double pbl; - double par; - double pbr; - double cve; - double cvr; - ae_int_t info; - double threshold; - ae_vector tiebuf; - ae_vector cntbuf; - double rms; - double cvrms; - ae_bool waserrors; - ae_bool tieserrors; - ae_bool split2errors; - ae_bool optimalsplitkerrors; - ae_bool splitkerrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&a0, 0, sizeof(a0)); - memset(&at, 0, sizeof(at)); - memset(&p, 0, sizeof(p)); - memset(&thresholds, 0, sizeof(thresholds)); - memset(&c, 0, sizeof(c)); - memset(&p1, 0, sizeof(p1)); - memset(&p2, 0, sizeof(p2)); - memset(&ties, 0, sizeof(ties)); - memset(&pt1, 0, sizeof(pt1)); - memset(&pt2, 0, sizeof(pt2)); - memset(&tmp, 0, sizeof(tmp)); - memset(&sortrbuf, 0, sizeof(sortrbuf)); - memset(&sortrbuf2, 0, sizeof(sortrbuf2)); - memset(&sortibuf, 0, sizeof(sortibuf)); - memset(&tiebuf, 0, sizeof(tiebuf)); - memset(&cntbuf, 0, sizeof(cntbuf)); - ae_vector_init(&a, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&at, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&p, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&thresholds, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c, 0, DT_INT, _state, ae_true); - ae_vector_init(&p1, 0, DT_INT, _state, ae_true); - ae_vector_init(&p2, 0, DT_INT, _state, ae_true); - ae_vector_init(&ties, 0, DT_INT, _state, ae_true); - ae_vector_init(&pt1, 0, DT_INT, _state, ae_true); - ae_vector_init(&pt2, 0, DT_INT, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sortrbuf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sortrbuf2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sortibuf, 0, DT_INT, _state, ae_true); - ae_vector_init(&tiebuf, 0, DT_INT, _state, ae_true); - ae_vector_init(&cntbuf, 0, DT_INT, _state, ae_true); - - waserrors = ae_false; - tieserrors = ae_false; - split2errors = ae_false; - splitkerrors = ae_false; - optimalsplitkerrors = ae_false; - maxn = 100; - maxnq = 49; - passcount = 10; - - /* - * Test ties - */ - for(n=1; n<=maxn; n++) - { - for(pass=1; pass<=passcount; pass++) - { - - /* - * untied data, test DSTie - */ - testbdssunit_unset1di(&p1, _state); - testbdssunit_unset1di(&p2, _state); - testbdssunit_unset1di(&pt1, _state); - testbdssunit_unset1di(&pt2, _state); - ae_vector_set_length(&a, n-1+1, _state); - ae_vector_set_length(&a0, n-1+1, _state); - ae_vector_set_length(&at, n-1+1, _state); - ae_vector_set_length(&tmp, n-1+1, _state); - a.ptr.p_double[0] = 2*ae_randomreal(_state)-1; - tmp.ptr.p_double[0] = ae_randomreal(_state); - for(i=1; i<=n-1; i++) - { - - /* - * A is randomly permuted - */ - a.ptr.p_double[i] = a.ptr.p_double[i-1]+0.1*ae_randomreal(_state)+0.1; - tmp.ptr.p_double[i] = ae_randomreal(_state); - } - tagsortfastr(&tmp, &a, &sortrbuf, &sortrbuf2, n, _state); - for(i=0; i<=n-1; i++) - { - a0.ptr.p_double[i] = a.ptr.p_double[i]; - at.ptr.p_double[i] = a.ptr.p_double[i]; - } - dstie(&a0, n, &ties, &tiecount, &p1, &p2, _state); - tagsort(&at, n, &pt1, &pt2, _state); - for(i=0; i<=n-1; i++) - { - tieserrors = tieserrors||p1.ptr.p_int[i]!=pt1.ptr.p_int[i]; - tieserrors = tieserrors||p2.ptr.p_int[i]!=pt2.ptr.p_int[i]; - } - tieserrors = tieserrors||tiecount!=n; - if( tiecount==n ) - { - for(i=0; i<=n; i++) - { - tieserrors = tieserrors||ties.ptr.p_int[i]!=i; - } - } - - /* - * tied data, test DSTie - */ - testbdssunit_unset1di(&p1, _state); - testbdssunit_unset1di(&p2, _state); - testbdssunit_unset1di(&pt1, _state); - testbdssunit_unset1di(&pt2, _state); - ae_vector_set_length(&a, n-1+1, _state); - ae_vector_set_length(&a0, n-1+1, _state); - ae_vector_set_length(&at, n-1+1, _state); - c1 = 0; - c0 = 0; - for(i=0; i<=n-1; i++) - { - a.ptr.p_double[i] = (double)(ae_randominteger(2, _state)); - if( ae_fp_eq(a.ptr.p_double[i],(double)(0)) ) - { - c0 = c0+1; - } - else - { - c1 = c1+1; - } - a0.ptr.p_double[i] = a.ptr.p_double[i]; - at.ptr.p_double[i] = a.ptr.p_double[i]; - } - dstie(&a0, n, &ties, &tiecount, &p1, &p2, _state); - tagsort(&at, n, &pt1, &pt2, _state); - for(i=0; i<=n-1; i++) - { - tieserrors = tieserrors||p1.ptr.p_int[i]!=pt1.ptr.p_int[i]; - tieserrors = tieserrors||p2.ptr.p_int[i]!=pt2.ptr.p_int[i]; - } - if( c0==0||c1==0 ) - { - tieserrors = tieserrors||tiecount!=1; - if( tiecount==1 ) - { - tieserrors = tieserrors||ties.ptr.p_int[0]!=0; - tieserrors = tieserrors||ties.ptr.p_int[1]!=n; - } - } - else - { - tieserrors = tieserrors||tiecount!=2; - if( tiecount==2 ) - { - tieserrors = tieserrors||ties.ptr.p_int[0]!=0; - tieserrors = tieserrors||ties.ptr.p_int[1]!=c0; - tieserrors = tieserrors||ties.ptr.p_int[2]!=n; - } - } - } - } - - /* - * split-2 - */ - - /* - * General tests for different N's - */ - for(n=1; n<=maxn; n++) - { - ae_vector_set_length(&a, n-1+1, _state); - ae_vector_set_length(&c, n-1+1, _state); - - /* - * one-tie test - */ - if( n%2==0 ) - { - for(i=0; i<=n-1; i++) - { - a.ptr.p_double[i] = (double)(n); - c.ptr.p_int[i] = i%2; - } - dsoptimalsplit2(&a, &c, n, &info, &threshold, &pal, &pbl, &par, &pbr, &cve, _state); - if( info!=-3 ) - { - split2errors = ae_true; - continue; - } - } - - /* - * two-tie test - */ - - /* - * test #1 - */ - if( n>1 ) - { - for(i=0; i<=n-1; i++) - { - a.ptr.p_double[i] = (double)(i/((n+1)/2)); - c.ptr.p_int[i] = i/((n+1)/2); - } - dsoptimalsplit2(&a, &c, n, &info, &threshold, &pal, &pbl, &par, &pbr, &cve, _state); - if( info!=1 ) - { - split2errors = ae_true; - continue; - } - split2errors = split2errors||ae_fp_greater(ae_fabs(threshold-0.5, _state),100*ae_machineepsilon); - split2errors = split2errors||ae_fp_greater(ae_fabs(pal-1, _state),100*ae_machineepsilon); - split2errors = split2errors||ae_fp_greater(ae_fabs(pbl-0, _state),100*ae_machineepsilon); - split2errors = split2errors||ae_fp_greater(ae_fabs(par-0, _state),100*ae_machineepsilon); - split2errors = split2errors||ae_fp_greater(ae_fabs(pbr-1, _state),100*ae_machineepsilon); - } - } - - /* - * Special "CREDIT"-test (transparency coefficient) - */ - n = 110; - ae_vector_set_length(&a, n-1+1, _state); - ae_vector_set_length(&c, n-1+1, _state); - a.ptr.p_double[0] = 0.000; - c.ptr.p_int[0] = 0; - a.ptr.p_double[1] = 0.000; - c.ptr.p_int[1] = 0; - a.ptr.p_double[2] = 0.000; - c.ptr.p_int[2] = 0; - a.ptr.p_double[3] = 0.000; - c.ptr.p_int[3] = 0; - a.ptr.p_double[4] = 0.000; - c.ptr.p_int[4] = 0; - a.ptr.p_double[5] = 0.000; - c.ptr.p_int[5] = 0; - a.ptr.p_double[6] = 0.000; - c.ptr.p_int[6] = 0; - a.ptr.p_double[7] = 0.000; - c.ptr.p_int[7] = 1; - a.ptr.p_double[8] = 0.000; - c.ptr.p_int[8] = 0; - a.ptr.p_double[9] = 0.000; - c.ptr.p_int[9] = 1; - a.ptr.p_double[10] = 0.000; - c.ptr.p_int[10] = 0; - a.ptr.p_double[11] = 0.000; - c.ptr.p_int[11] = 0; - a.ptr.p_double[12] = 0.000; - c.ptr.p_int[12] = 0; - a.ptr.p_double[13] = 0.000; - c.ptr.p_int[13] = 0; - a.ptr.p_double[14] = 0.000; - c.ptr.p_int[14] = 0; - a.ptr.p_double[15] = 0.000; - c.ptr.p_int[15] = 0; - a.ptr.p_double[16] = 0.000; - c.ptr.p_int[16] = 0; - a.ptr.p_double[17] = 0.000; - c.ptr.p_int[17] = 0; - a.ptr.p_double[18] = 0.000; - c.ptr.p_int[18] = 0; - a.ptr.p_double[19] = 0.000; - c.ptr.p_int[19] = 0; - a.ptr.p_double[20] = 0.000; - c.ptr.p_int[20] = 0; - a.ptr.p_double[21] = 0.000; - c.ptr.p_int[21] = 0; - a.ptr.p_double[22] = 0.000; - c.ptr.p_int[22] = 1; - a.ptr.p_double[23] = 0.000; - c.ptr.p_int[23] = 0; - a.ptr.p_double[24] = 0.000; - c.ptr.p_int[24] = 0; - a.ptr.p_double[25] = 0.000; - c.ptr.p_int[25] = 0; - a.ptr.p_double[26] = 0.000; - c.ptr.p_int[26] = 0; - a.ptr.p_double[27] = 0.000; - c.ptr.p_int[27] = 1; - a.ptr.p_double[28] = 0.000; - c.ptr.p_int[28] = 0; - a.ptr.p_double[29] = 0.000; - c.ptr.p_int[29] = 1; - a.ptr.p_double[30] = 0.000; - c.ptr.p_int[30] = 0; - a.ptr.p_double[31] = 0.000; - c.ptr.p_int[31] = 1; - a.ptr.p_double[32] = 0.000; - c.ptr.p_int[32] = 0; - a.ptr.p_double[33] = 0.000; - c.ptr.p_int[33] = 1; - a.ptr.p_double[34] = 0.000; - c.ptr.p_int[34] = 0; - a.ptr.p_double[35] = 0.030; - c.ptr.p_int[35] = 0; - a.ptr.p_double[36] = 0.030; - c.ptr.p_int[36] = 0; - a.ptr.p_double[37] = 0.050; - c.ptr.p_int[37] = 0; - a.ptr.p_double[38] = 0.070; - c.ptr.p_int[38] = 1; - a.ptr.p_double[39] = 0.110; - c.ptr.p_int[39] = 0; - a.ptr.p_double[40] = 0.110; - c.ptr.p_int[40] = 1; - a.ptr.p_double[41] = 0.120; - c.ptr.p_int[41] = 0; - a.ptr.p_double[42] = 0.130; - c.ptr.p_int[42] = 0; - a.ptr.p_double[43] = 0.140; - c.ptr.p_int[43] = 0; - a.ptr.p_double[44] = 0.140; - c.ptr.p_int[44] = 0; - a.ptr.p_double[45] = 0.140; - c.ptr.p_int[45] = 0; - a.ptr.p_double[46] = 0.150; - c.ptr.p_int[46] = 0; - a.ptr.p_double[47] = 0.150; - c.ptr.p_int[47] = 0; - a.ptr.p_double[48] = 0.170; - c.ptr.p_int[48] = 0; - a.ptr.p_double[49] = 0.190; - c.ptr.p_int[49] = 1; - a.ptr.p_double[50] = 0.200; - c.ptr.p_int[50] = 0; - a.ptr.p_double[51] = 0.200; - c.ptr.p_int[51] = 0; - a.ptr.p_double[52] = 0.250; - c.ptr.p_int[52] = 0; - a.ptr.p_double[53] = 0.250; - c.ptr.p_int[53] = 0; - a.ptr.p_double[54] = 0.260; - c.ptr.p_int[54] = 0; - a.ptr.p_double[55] = 0.270; - c.ptr.p_int[55] = 0; - a.ptr.p_double[56] = 0.280; - c.ptr.p_int[56] = 0; - a.ptr.p_double[57] = 0.310; - c.ptr.p_int[57] = 0; - a.ptr.p_double[58] = 0.310; - c.ptr.p_int[58] = 0; - a.ptr.p_double[59] = 0.330; - c.ptr.p_int[59] = 0; - a.ptr.p_double[60] = 0.330; - c.ptr.p_int[60] = 0; - a.ptr.p_double[61] = 0.340; - c.ptr.p_int[61] = 0; - a.ptr.p_double[62] = 0.340; - c.ptr.p_int[62] = 0; - a.ptr.p_double[63] = 0.370; - c.ptr.p_int[63] = 0; - a.ptr.p_double[64] = 0.380; - c.ptr.p_int[64] = 1; - a.ptr.p_double[65] = 0.380; - c.ptr.p_int[65] = 0; - a.ptr.p_double[66] = 0.410; - c.ptr.p_int[66] = 0; - a.ptr.p_double[67] = 0.460; - c.ptr.p_int[67] = 0; - a.ptr.p_double[68] = 0.520; - c.ptr.p_int[68] = 0; - a.ptr.p_double[69] = 0.530; - c.ptr.p_int[69] = 0; - a.ptr.p_double[70] = 0.540; - c.ptr.p_int[70] = 0; - a.ptr.p_double[71] = 0.560; - c.ptr.p_int[71] = 0; - a.ptr.p_double[72] = 0.560; - c.ptr.p_int[72] = 0; - a.ptr.p_double[73] = 0.570; - c.ptr.p_int[73] = 0; - a.ptr.p_double[74] = 0.600; - c.ptr.p_int[74] = 0; - a.ptr.p_double[75] = 0.600; - c.ptr.p_int[75] = 0; - a.ptr.p_double[76] = 0.620; - c.ptr.p_int[76] = 0; - a.ptr.p_double[77] = 0.650; - c.ptr.p_int[77] = 0; - a.ptr.p_double[78] = 0.660; - c.ptr.p_int[78] = 0; - a.ptr.p_double[79] = 0.680; - c.ptr.p_int[79] = 0; - a.ptr.p_double[80] = 0.700; - c.ptr.p_int[80] = 0; - a.ptr.p_double[81] = 0.750; - c.ptr.p_int[81] = 0; - a.ptr.p_double[82] = 0.770; - c.ptr.p_int[82] = 0; - a.ptr.p_double[83] = 0.770; - c.ptr.p_int[83] = 0; - a.ptr.p_double[84] = 0.770; - c.ptr.p_int[84] = 0; - a.ptr.p_double[85] = 0.790; - c.ptr.p_int[85] = 0; - a.ptr.p_double[86] = 0.810; - c.ptr.p_int[86] = 0; - a.ptr.p_double[87] = 0.840; - c.ptr.p_int[87] = 0; - a.ptr.p_double[88] = 0.860; - c.ptr.p_int[88] = 0; - a.ptr.p_double[89] = 0.870; - c.ptr.p_int[89] = 0; - a.ptr.p_double[90] = 0.890; - c.ptr.p_int[90] = 0; - a.ptr.p_double[91] = 0.900; - c.ptr.p_int[91] = 1; - a.ptr.p_double[92] = 0.900; - c.ptr.p_int[92] = 0; - a.ptr.p_double[93] = 0.910; - c.ptr.p_int[93] = 0; - a.ptr.p_double[94] = 0.940; - c.ptr.p_int[94] = 0; - a.ptr.p_double[95] = 0.950; - c.ptr.p_int[95] = 0; - a.ptr.p_double[96] = 0.952; - c.ptr.p_int[96] = 0; - a.ptr.p_double[97] = 0.970; - c.ptr.p_int[97] = 0; - a.ptr.p_double[98] = 0.970; - c.ptr.p_int[98] = 0; - a.ptr.p_double[99] = 0.980; - c.ptr.p_int[99] = 0; - a.ptr.p_double[100] = 1.000; - c.ptr.p_int[100] = 0; - a.ptr.p_double[101] = 1.000; - c.ptr.p_int[101] = 0; - a.ptr.p_double[102] = 1.000; - c.ptr.p_int[102] = 0; - a.ptr.p_double[103] = 1.000; - c.ptr.p_int[103] = 0; - a.ptr.p_double[104] = 1.000; - c.ptr.p_int[104] = 0; - a.ptr.p_double[105] = 1.020; - c.ptr.p_int[105] = 0; - a.ptr.p_double[106] = 1.090; - c.ptr.p_int[106] = 0; - a.ptr.p_double[107] = 1.130; - c.ptr.p_int[107] = 0; - a.ptr.p_double[108] = 1.840; - c.ptr.p_int[108] = 0; - a.ptr.p_double[109] = 2.470; - c.ptr.p_int[109] = 0; - dsoptimalsplit2(&a, &c, n, &info, &threshold, &pal, &pbl, &par, &pbr, &cve, _state); - if( info!=1 ) - { - split2errors = ae_true; - } - else - { - split2errors = split2errors||ae_fp_greater(ae_fabs(threshold-0.195, _state),100*ae_machineepsilon); - split2errors = split2errors||ae_fp_greater(ae_fabs(pal-0.80, _state),0.02); - split2errors = split2errors||ae_fp_greater(ae_fabs(pbl-0.20, _state),0.02); - split2errors = split2errors||ae_fp_greater(ae_fabs(par-0.97, _state),0.02); - split2errors = split2errors||ae_fp_greater(ae_fabs(pbr-0.03, _state),0.02); - } - - /* - * split-2 fast - */ - - /* - * General tests for different N's - */ - for(n=1; n<=maxn; n++) - { - ae_vector_set_length(&a, n-1+1, _state); - ae_vector_set_length(&c, n-1+1, _state); - ae_vector_set_length(&tiebuf, n+1, _state); - ae_vector_set_length(&cntbuf, 3+1, _state); - - /* - * one-tie test - */ - if( n%2==0 ) - { - for(i=0; i<=n-1; i++) - { - a.ptr.p_double[i] = (double)(n); - c.ptr.p_int[i] = i%2; - } - dsoptimalsplit2fast(&a, &c, &tiebuf, &cntbuf, &sortrbuf, &sortibuf, n, 2, 0.00, &info, &threshold, &rms, &cvrms, _state); - if( info!=-3 ) - { - split2errors = ae_true; - continue; - } - } - - /* - * two-tie test - */ - - /* - * test #1 - */ - if( n>1 ) - { - for(i=0; i<=n-1; i++) - { - a.ptr.p_double[i] = (double)(i/((n+1)/2)); - c.ptr.p_int[i] = i/((n+1)/2); - } - dsoptimalsplit2fast(&a, &c, &tiebuf, &cntbuf, &sortrbuf, &sortibuf, n, 2, 0.00, &info, &threshold, &rms, &cvrms, _state); - if( info!=1 ) - { - split2errors = ae_true; - continue; - } - split2errors = split2errors||ae_fp_greater(ae_fabs(threshold-0.5, _state),100*ae_machineepsilon); - split2errors = split2errors||ae_fp_greater(ae_fabs(rms-0, _state),100*ae_machineepsilon); - if( n==2 ) - { - split2errors = split2errors||ae_fp_greater(ae_fabs(cvrms-0.5, _state),100*ae_machineepsilon); - } - else - { - if( n==3 ) - { - split2errors = split2errors||ae_fp_greater(ae_fabs(cvrms-ae_sqrt((2*0+2*0+2*0.25)/6, _state), _state),100*ae_machineepsilon); - } - else - { - split2errors = split2errors||ae_fp_greater(ae_fabs(cvrms, _state),100*ae_machineepsilon); - } - } - } - } - - /* - * special tests - */ - n = 10; - ae_vector_set_length(&a, n-1+1, _state); - ae_vector_set_length(&c, n-1+1, _state); - ae_vector_set_length(&tiebuf, n+1, _state); - ae_vector_set_length(&cntbuf, 2*3-1+1, _state); - for(i=0; i<=n-1; i++) - { - a.ptr.p_double[i] = (double)(i); - if( i<=n-3 ) - { - c.ptr.p_int[i] = 0; - } - else - { - c.ptr.p_int[i] = i-(n-3); - } - } - dsoptimalsplit2fast(&a, &c, &tiebuf, &cntbuf, &sortrbuf, &sortibuf, n, 3, 0.00, &info, &threshold, &rms, &cvrms, _state); - if( info!=1 ) - { - split2errors = ae_true; - } - else - { - split2errors = split2errors||ae_fp_greater(ae_fabs(threshold-(n-2.5), _state),100*ae_machineepsilon); - split2errors = split2errors||ae_fp_greater(ae_fabs(rms-ae_sqrt((0.25+0.25+0.25+0.25)/(3*n), _state), _state),100*ae_machineepsilon); - split2errors = split2errors||ae_fp_greater(ae_fabs(cvrms-ae_sqrt((double)(1+1+1+1)/(double)(3*n), _state), _state),100*ae_machineepsilon); - } - - /* - * Optimal split-K - */ - - /* - * General tests for different N's - */ - for(n=1; n<=maxnq; n++) - { - ae_vector_set_length(&a, n-1+1, _state); - ae_vector_set_length(&c, n-1+1, _state); - - /* - * one-tie test - */ - if( n%2==0 ) - { - for(i=0; i<=n-1; i++) - { - a.ptr.p_double[i] = (double)(n); - c.ptr.p_int[i] = i%2; - } - dsoptimalsplitk(&a, &c, n, 2, 2+ae_randominteger(5, _state), &info, &thresholds, &ni, &cve, _state); - if( info!=-3 ) - { - optimalsplitkerrors = ae_true; - continue; - } - } - - /* - * two-tie test - */ - - /* - * test #1 - */ - if( n>1 ) - { - c0 = 0; - c1 = 0; - for(i=0; i<=n-1; i++) - { - a.ptr.p_double[i] = (double)(i/((n+1)/2)); - c.ptr.p_int[i] = i/((n+1)/2); - if( c.ptr.p_int[i]==0 ) - { - c0 = c0+1; - } - if( c.ptr.p_int[i]==1 ) - { - c1 = c1+1; - } - } - dsoptimalsplitk(&a, &c, n, 2, 2+ae_randominteger(5, _state), &info, &thresholds, &ni, &cve, _state); - if( info!=1 ) - { - optimalsplitkerrors = ae_true; - continue; - } - optimalsplitkerrors = optimalsplitkerrors||ni!=2; - optimalsplitkerrors = optimalsplitkerrors||ae_fp_greater(ae_fabs(thresholds.ptr.p_double[0]-0.5, _state),100*ae_machineepsilon); - optimalsplitkerrors = optimalsplitkerrors||ae_fp_greater(ae_fabs(cve-(-c0*ae_log((double)c0/(double)(c0+1), _state)-c1*ae_log((double)c1/(double)(c1+1), _state)), _state),100*ae_machineepsilon); - } - - /* - * test #2 - */ - if( n>2 ) - { - c0 = 1+ae_randominteger(n-1, _state); - c1 = n-c0; - for(i=0; i<=n-1; i++) - { - if( i=16 ) - { - - /* - * Multi-tie test. - * - * First NC-1 ties have C0 entries, remaining NC-th tie - * have C1 entries. - */ - nc = ae_round(ae_sqrt((double)(n), _state), _state); - c0 = n/nc; - c1 = n-c0*(nc-1); - for(i=0; i<=nc-2; i++) - { - for(j=c0*i; j<=c0*(i+1)-1; j++) - { - a.ptr.p_double[j] = (double)(j); - c.ptr.p_int[j] = i; - } - } - for(j=c0*(nc-1); j<=n-1; j++) - { - a.ptr.p_double[j] = (double)(j); - c.ptr.p_int[j] = nc-1; - } - dsoptimalsplitk(&a, &c, n, nc, nc+ae_randominteger(nc, _state), &info, &thresholds, &ni, &cve, _state); - if( info!=1 ) - { - optimalsplitkerrors = ae_true; - continue; - } - optimalsplitkerrors = optimalsplitkerrors||ni!=nc; - if( ni==nc ) - { - for(i=0; i<=nc-2; i++) - { - optimalsplitkerrors = optimalsplitkerrors||ae_fp_greater(ae_fabs(thresholds.ptr.p_double[i]-(c0*(i+1)-1+0.5), _state),100*ae_machineepsilon); - } - cvr = -((nc-1)*c0*ae_log((double)c0/(double)(c0+nc-1), _state)+c1*ae_log((double)c1/(double)(c1+nc-1), _state)); - optimalsplitkerrors = optimalsplitkerrors||ae_fp_greater(ae_fabs(cve-cvr, _state),100*ae_machineepsilon); - } - } - } - - /* - * Non-optimal split-K - */ - - /* - * General tests for different N's - */ - for(n=1; n<=maxnq; n++) - { - ae_vector_set_length(&a, n-1+1, _state); - ae_vector_set_length(&c, n-1+1, _state); - - /* - * one-tie test - */ - if( n%2==0 ) - { - for(i=0; i<=n-1; i++) - { - a.ptr.p_double[i] = (double)(99); - c.ptr.p_int[i] = i%2; - } - dssplitk(&a, &c, n, 2, 2+ae_randominteger(5, _state), &info, &thresholds, &ni, &cve, _state); - if( info!=-3 ) - { - splitkerrors = ae_true; - continue; - } - } - - /* - * two-tie test - */ - - /* - * test #1 - */ - if( n>1 ) - { - c0 = 0; - c1 = 0; - for(i=0; i<=n-1; i++) - { - a.ptr.p_double[i] = (double)(i/((n+1)/2)); - c.ptr.p_int[i] = i/((n+1)/2); - if( c.ptr.p_int[i]==0 ) - { - c0 = c0+1; - } - if( c.ptr.p_int[i]==1 ) - { - c1 = c1+1; - } - } - dssplitk(&a, &c, n, 2, 2+ae_randominteger(5, _state), &info, &thresholds, &ni, &cve, _state); - if( info!=1 ) - { - splitkerrors = ae_true; - continue; - } - splitkerrors = splitkerrors||ni!=2; - if( ni==2 ) - { - splitkerrors = splitkerrors||ae_fp_greater(ae_fabs(thresholds.ptr.p_double[0]-0.5, _state),100*ae_machineepsilon); - splitkerrors = splitkerrors||ae_fp_greater(ae_fabs(cve-(-c0*ae_log((double)c0/(double)(c0+1), _state)-c1*ae_log((double)c1/(double)(c1+1), _state)), _state),100*ae_machineepsilon); - } - } - - /* - * test #2 - */ - if( n>2 ) - { - c0 = 1+ae_randominteger(n-1, _state); - c1 = n-c0; - for(i=0; i<=n-1; i++) - { - if( i1 ) - { - nc = n/c0; - for(i=0; i<=nc-1; i++) - { - for(j=c0*i; j<=c0*(i+1)-1; j++) - { - a.ptr.p_double[j] = (double)(j); - c.ptr.p_int[j] = i; - } - } - dssplitk(&a, &c, n, nc, nc+ae_randominteger(nc, _state), &info, &thresholds, &ni, &cve, _state); - if( info!=1 ) - { - splitkerrors = ae_true; - continue; - } - splitkerrors = splitkerrors||ni!=nc; - if( ni==nc ) - { - for(i=0; i<=nc-2; i++) - { - splitkerrors = splitkerrors||ae_fp_greater(ae_fabs(thresholds.ptr.p_double[i]-(c0*(i+1)-1+0.5), _state),100*ae_machineepsilon); - } - cvr = -nc*c0*ae_log((double)c0/(double)(c0+nc-1), _state); - splitkerrors = splitkerrors||ae_fp_greater(ae_fabs(cve-cvr, _state),100*ae_machineepsilon); - } - } - } - } - - /* - * report - */ - waserrors = ((tieserrors||split2errors)||optimalsplitkerrors)||splitkerrors; - if( !silent ) - { - printf("TESTING BASIC DATASET SUBROUTINES\n"); - printf("TIES: "); - if( !tieserrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("SPLIT-2: "); - if( !split2errors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("OPTIMAL SPLIT-K: "); - if( !optimalsplitkerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("SPLIT-K: "); - if( !splitkerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Unsets 1D array. -*************************************************************************/ -static void testbdssunit_unset1di(/* Integer */ ae_vector* a, - ae_state *_state) -{ - - - ae_vector_set_length(a, 0+1, _state); - a->ptr.p_int[0] = ae_randominteger(3, _state)-1; -} - - - -static double testmlpbaseunit_vectordiff(/* Real */ ae_vector* g0, - /* Real */ ae_vector* g1, - ae_int_t n, - double s, - ae_state *_state); -static void testmlpbaseunit_createnetwork(multilayerperceptron* network, - ae_int_t nkind, - double a1, - double a2, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_state *_state); -static void testmlpbaseunit_unsetnetwork(multilayerperceptron* network, - ae_state *_state); -static void testmlpbaseunit_testinformational(ae_int_t nkind, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t passcount, - ae_bool* err, - ae_state *_state); -static void testmlpbaseunit_testprocessing(ae_int_t nkind, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t passcount, - ae_bool* err, - ae_state *_state); -static void testmlpbaseunit_testgradient(ae_int_t nkind, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t passcount, - ae_int_t sizemin, - ae_int_t sizemax, - ae_bool* err, - ae_state *_state); -static void testmlpbaseunit_testhessian(ae_int_t nkind, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t passcount, - ae_bool* err, - ae_state *_state); -static void testmlpbaseunit_testerr(ae_int_t nkind, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t passcount, - ae_int_t sizemin, - ae_int_t sizemax, - ae_bool* err, - ae_state *_state); -static void testmlpbaseunit_spectests(ae_bool* inferrors, - ae_bool* procerrors, - ae_bool* graderrors, - ae_bool* hesserrors, - ae_bool* errerrors, - ae_state *_state); -static ae_bool testmlpbaseunit_testmlpgbsubset(ae_state *_state); - - - - - -ae_bool testmlpbase(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_bool waserrors; - ae_int_t passcount; - ae_int_t maxn; - ae_int_t maxhid; - ae_int_t sizemin; - ae_int_t sizemax; - ae_int_t nf; - ae_int_t nl; - ae_int_t nhid1; - ae_int_t nhid2; - ae_int_t nkind; - multilayerperceptron network; - multilayerperceptron network2; - ae_matrix xy; - ae_matrix valxy; - ae_bool inferrors; - ae_bool procerrors; - ae_bool graderrors; - ae_bool hesserrors; - ae_bool errerrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&network, 0, sizeof(network)); - memset(&network2, 0, sizeof(network2)); - memset(&xy, 0, sizeof(xy)); - memset(&valxy, 0, sizeof(valxy)); - _multilayerperceptron_init(&network, _state, ae_true); - _multilayerperceptron_init(&network2, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&valxy, 0, 0, DT_REAL, _state, ae_true); - - waserrors = ae_false; - inferrors = ae_false; - procerrors = ae_false; - graderrors = ae_false; - hesserrors = ae_false; - errerrors = ae_false; - passcount = 5; - maxn = 3; - maxhid = 3; - - /* - * Special tests - */ - testmlpbaseunit_spectests(&inferrors, &procerrors, &graderrors, &hesserrors, &errerrors, _state); - - /* - * General multilayer network tests. - * These tests are performed with small dataset, whose size is in [0,10]. - * We test correctness of functions on small sets, but do not test code - * which splits large dataset into smaller chunks. - */ - sizemin = 0; - sizemax = 10; - for(nf=1; nf<=maxn; nf++) - { - for(nl=1; nl<=maxn; nl++) - { - for(nhid1=0; nhid1<=maxhid; nhid1++) - { - for(nhid2=0; nhid2<=maxhid; nhid2++) - { - for(nkind=0; nkind<=3; nkind++) - { - - /* - * Skip meaningless parameters combinations - */ - if( nkind==1&&nl<2 ) - { - continue; - } - if( nhid1==0&&nhid2!=0 ) - { - continue; - } - - /* - * Tests - */ - testmlpbaseunit_testinformational(nkind, nf, nhid1, nhid2, nl, passcount, &inferrors, _state); - testmlpbaseunit_testprocessing(nkind, nf, nhid1, nhid2, nl, passcount, &procerrors, _state); - testmlpbaseunit_testgradient(nkind, nf, nhid1, nhid2, nl, passcount, sizemin, sizemax, &graderrors, _state); - testmlpbaseunit_testhessian(nkind, nf, nhid1, nhid2, nl, passcount, &hesserrors, _state); - testmlpbaseunit_testerr(nkind, nf, nhid1, nhid2, nl, passcount, sizemin, sizemax, &errerrors, _state); - } - } - } - } - } - - /* - * Special tests on large datasets: test ability to correctly split - * work into smaller chunks. - */ - nf = 2; - nhid1 = 20; - nhid2 = 20; - nl = 2; - sizemin = 50000; - sizemax = 50000; - testmlpbaseunit_testerr(0, nf, nhid1, nhid2, nl, 1, sizemin, sizemax, &errerrors, _state); - testmlpbaseunit_testgradient(0, nf, nhid1, nhid2, nl, 1, sizemin, sizemax, &graderrors, _state); - - /* - * Test for MLPGradBatch____Subset() - */ - graderrors = graderrors||testmlpbaseunit_testmlpgbsubset(_state); - - /* - * Final report - */ - waserrors = (((inferrors||procerrors)||graderrors)||hesserrors)||errerrors; - if( !silent ) - { - printf("MLP TEST\n"); - printf("INFORMATIONAL FUNCTIONS: "); - if( !inferrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("BASIC PROCESSING: "); - if( !procerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("GRADIENT CALCULATION: "); - if( !graderrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("HESSIAN CALCULATION: "); - if( !hesserrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("ERROR FUNCTIONS: "); - if( !errerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST SUMMARY: FAILED\n"); - } - else - { - printf("TEST SUMMARY: PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function compares vectors G0 and G1 and returns - ||G0-G1||/max(||G0||,||G1||,S) - -For zero G0, G1 and S (all three quantities are zero) it returns zero. -*************************************************************************/ -static double testmlpbaseunit_vectordiff(/* Real */ ae_vector* g0, - /* Real */ ae_vector* g1, - ae_int_t n, - double s, - ae_state *_state) -{ - ae_int_t i; - double norm0; - double norm1; - double diff; - double result; - - - norm0 = (double)(0); - norm1 = (double)(0); - diff = (double)(0); - for(i=0; i<=n-1; i++) - { - norm0 = norm0+ae_sqr(g0->ptr.p_double[i], _state); - norm1 = norm1+ae_sqr(g1->ptr.p_double[i], _state); - diff = diff+ae_sqr(g0->ptr.p_double[i]-g1->ptr.p_double[i], _state); - } - norm0 = ae_sqrt(norm0, _state); - norm1 = ae_sqrt(norm1, _state); - diff = ae_sqrt(diff, _state); - if( (ae_fp_neq(norm0,(double)(0))||ae_fp_neq(norm1,(double)(0)))||ae_fp_neq(s,(double)(0)) ) - { - diff = diff/ae_maxreal(ae_maxreal(norm0, norm1, _state), s, _state); - } - else - { - diff = (double)(0); - } - result = diff; - return result; -} - - -/************************************************************************* -Network creation - -This function creates network with desired structure. - -Network is created using one of the three methods: -a) straightforward creation using MLPCreate???() -b) MLPCreate???() for proxy object, which is copied with PassThroughSerializer() -c) MLPCreate???() for proxy object, which is copied with MLPCopy() - -One of these methods is chosen at random. -*************************************************************************/ -static void testmlpbaseunit_createnetwork(multilayerperceptron* network, - ae_int_t nkind, - double a1, - double a2, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t mkind; - multilayerperceptron tmp; - - ae_frame_make(_state, &_frame_block); - memset(&tmp, 0, sizeof(tmp)); - _multilayerperceptron_init(&tmp, _state, ae_true); - - ae_assert(((nin>0&&nhid1>=0)&&nhid2>=0)&&nout>0, "CreateNetwork error", _state); - ae_assert(nhid1!=0||nhid2==0, "CreateNetwork error", _state); - ae_assert(nkind!=1||nout>=2, "CreateNetwork error", _state); - mkind = ae_randominteger(3, _state); - if( nhid1==0 ) - { - - /* - * No hidden layers - */ - if( nkind==0 ) - { - if( mkind==0 ) - { - mlpcreate0(nin, nout, network, _state); - } - if( mkind==1 ) - { - mlpcreate0(nin, nout, &tmp, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - mlpalloc(&_local_serializer, &tmp, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpserialize(&_local_serializer, &tmp, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpunserialize(&_local_serializer, network, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - } - if( mkind==2 ) - { - mlpcreate0(nin, nout, &tmp, _state); - mlpcopy(&tmp, network, _state); - } - } - else - { - if( nkind==1 ) - { - if( mkind==0 ) - { - mlpcreatec0(nin, nout, network, _state); - } - if( mkind==1 ) - { - mlpcreatec0(nin, nout, &tmp, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - mlpalloc(&_local_serializer, &tmp, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpserialize(&_local_serializer, &tmp, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpunserialize(&_local_serializer, network, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - } - if( mkind==2 ) - { - mlpcreatec0(nin, nout, &tmp, _state); - mlpcopy(&tmp, network, _state); - } - } - else - { - if( nkind==2 ) - { - if( mkind==0 ) - { - mlpcreateb0(nin, nout, a1, a2, network, _state); - } - if( mkind==1 ) - { - mlpcreateb0(nin, nout, a1, a2, &tmp, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - mlpalloc(&_local_serializer, &tmp, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpserialize(&_local_serializer, &tmp, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpunserialize(&_local_serializer, network, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - } - if( mkind==2 ) - { - mlpcreateb0(nin, nout, a1, a2, &tmp, _state); - mlpcopy(&tmp, network, _state); - } - } - else - { - if( nkind==3 ) - { - if( mkind==0 ) - { - mlpcreater0(nin, nout, a1, a2, network, _state); - } - if( mkind==1 ) - { - mlpcreater0(nin, nout, a1, a2, &tmp, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - mlpalloc(&_local_serializer, &tmp, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpserialize(&_local_serializer, &tmp, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpunserialize(&_local_serializer, network, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - } - if( mkind==2 ) - { - mlpcreater0(nin, nout, a1, a2, &tmp, _state); - mlpcopy(&tmp, network, _state); - } - } - } - } - } - mlprandomizefull(network, _state); - ae_frame_leave(_state); - return; - } - if( nhid2==0 ) - { - - /* - * One hidden layer - */ - if( nkind==0 ) - { - if( mkind==0 ) - { - mlpcreate1(nin, nhid1, nout, network, _state); - } - if( mkind==1 ) - { - mlpcreate1(nin, nhid1, nout, &tmp, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - mlpalloc(&_local_serializer, &tmp, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpserialize(&_local_serializer, &tmp, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpunserialize(&_local_serializer, network, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - } - if( mkind==2 ) - { - mlpcreate1(nin, nhid1, nout, &tmp, _state); - mlpcopy(&tmp, network, _state); - } - } - else - { - if( nkind==1 ) - { - if( mkind==0 ) - { - mlpcreatec1(nin, nhid1, nout, network, _state); - } - if( mkind==1 ) - { - mlpcreatec1(nin, nhid1, nout, &tmp, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - mlpalloc(&_local_serializer, &tmp, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpserialize(&_local_serializer, &tmp, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpunserialize(&_local_serializer, network, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - } - if( mkind==2 ) - { - mlpcreatec1(nin, nhid1, nout, &tmp, _state); - mlpcopy(&tmp, network, _state); - } - } - else - { - if( nkind==2 ) - { - if( mkind==0 ) - { - mlpcreateb1(nin, nhid1, nout, a1, a2, network, _state); - } - if( mkind==1 ) - { - mlpcreateb1(nin, nhid1, nout, a1, a2, &tmp, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - mlpalloc(&_local_serializer, &tmp, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpserialize(&_local_serializer, &tmp, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpunserialize(&_local_serializer, network, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - } - if( mkind==2 ) - { - mlpcreateb1(nin, nhid1, nout, a1, a2, &tmp, _state); - mlpcopy(&tmp, network, _state); - } - } - else - { - if( nkind==3 ) - { - if( mkind==0 ) - { - mlpcreater1(nin, nhid1, nout, a1, a2, network, _state); - } - if( mkind==1 ) - { - mlpcreater1(nin, nhid1, nout, a1, a2, &tmp, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - mlpalloc(&_local_serializer, &tmp, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpserialize(&_local_serializer, &tmp, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpunserialize(&_local_serializer, network, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - } - if( mkind==2 ) - { - mlpcreater1(nin, nhid1, nout, a1, a2, &tmp, _state); - mlpcopy(&tmp, network, _state); - } - } - } - } - } - mlprandomizefull(network, _state); - ae_frame_leave(_state); - return; - } - - /* - * Two hidden layers - */ - if( nkind==0 ) - { - if( mkind==0 ) - { - mlpcreate2(nin, nhid1, nhid2, nout, network, _state); - } - if( mkind==1 ) - { - mlpcreate2(nin, nhid1, nhid2, nout, &tmp, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - mlpalloc(&_local_serializer, &tmp, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpserialize(&_local_serializer, &tmp, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpunserialize(&_local_serializer, network, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - } - if( mkind==2 ) - { - mlpcreate2(nin, nhid1, nhid2, nout, &tmp, _state); - mlpcopy(&tmp, network, _state); - } - } - else - { - if( nkind==1 ) - { - if( mkind==0 ) - { - mlpcreatec2(nin, nhid1, nhid2, nout, network, _state); - } - if( mkind==1 ) - { - mlpcreatec2(nin, nhid1, nhid2, nout, &tmp, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - mlpalloc(&_local_serializer, &tmp, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpserialize(&_local_serializer, &tmp, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpunserialize(&_local_serializer, network, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - } - if( mkind==2 ) - { - mlpcreatec2(nin, nhid1, nhid2, nout, &tmp, _state); - mlpcopy(&tmp, network, _state); - } - } - else - { - if( nkind==2 ) - { - if( mkind==0 ) - { - mlpcreateb2(nin, nhid1, nhid2, nout, a1, a2, network, _state); - } - if( mkind==1 ) - { - mlpcreateb2(nin, nhid1, nhid2, nout, a1, a2, &tmp, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - mlpalloc(&_local_serializer, &tmp, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpserialize(&_local_serializer, &tmp, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpunserialize(&_local_serializer, network, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - } - if( mkind==2 ) - { - mlpcreateb2(nin, nhid1, nhid2, nout, a1, a2, &tmp, _state); - mlpcopy(&tmp, network, _state); - } - } - else - { - if( nkind==3 ) - { - if( mkind==0 ) - { - mlpcreater2(nin, nhid1, nhid2, nout, a1, a2, network, _state); - } - if( mkind==1 ) - { - mlpcreater2(nin, nhid1, nhid2, nout, a1, a2, &tmp, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - mlpalloc(&_local_serializer, &tmp, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpserialize(&_local_serializer, &tmp, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpunserialize(&_local_serializer, network, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - } - if( mkind==2 ) - { - mlpcreater2(nin, nhid1, nhid2, nout, a1, a2, &tmp, _state); - mlpcopy(&tmp, network, _state); - } - } - } - } - } - mlprandomizefull(network, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Unsets network (initialize it to smallest network possible -*************************************************************************/ -static void testmlpbaseunit_unsetnetwork(multilayerperceptron* network, - ae_state *_state) -{ - - - mlpcreate0(1, 1, network, _state); -} - - -/************************************************************************* -Informational functions test -*************************************************************************/ -static void testmlpbaseunit_testinformational(ae_int_t nkind, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t passcount, - ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron network; - ae_int_t n1; - ae_int_t n2; - ae_int_t wcount; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double threshold; - ae_int_t nlayers; - ae_int_t nmax; - ae_matrix neurons; - ae_vector x; - ae_vector y; - double mean; - double sigma; - ae_int_t fkind; - double c; - double f; - double df; - double d2f; - double s; - - ae_frame_make(_state, &_frame_block); - memset(&network, 0, sizeof(network)); - memset(&neurons, 0, sizeof(neurons)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - _multilayerperceptron_init(&network, _state, ae_true); - ae_matrix_init(&neurons, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - - threshold = 100000*ae_machineepsilon; - testmlpbaseunit_createnetwork(&network, nkind, 0.0, 0.0, nin, nhid1, nhid2, nout, _state); - - /* - * test MLPProperties() - */ - mlpproperties(&network, &n1, &n2, &wcount, _state); - *err = ((*err||n1!=nin)||n2!=nout)||wcount<=0; - *err = ((*err||mlpgetinputscount(&network, _state)!=nin)||mlpgetoutputscount(&network, _state)!=nout)||mlpgetweightscount(&network, _state)!=wcount; - - /* - * Test network geometry functions - * - * In order to do this we calculate neural network output using - * informational functions only, and compare results with ones - * obtained with MLPProcess(): - * 1. we allocate 2-dimensional array of neurons and fill it by zeros - * 2. we full first layer of neurons by input values - * 3. we move through array, calculating values of subsequent layers - * 4. if we have classification network, we SOFTMAX-normalize output layer - * 5. we apply scaling to the outputs - * 6. we compare results with ones obtained by MLPProcess() - * - * NOTE: it is important to do (4) before (5), because on SOFTMAX network - * MLPGetOutputScaling() must return Mean=0 and Sigma=1. In order - * to test it implicitly, we apply it to the classifier results - * (already normalized). If one of the coefficients deviates from - * expected values, we will get error during (6). - */ - nlayers = 2; - nmax = ae_maxint(nin, nout, _state); - if( nhid1!=0 ) - { - nlayers = 3; - nmax = ae_maxint(nmax, nhid1, _state); - } - if( nhid2!=0 ) - { - nlayers = 4; - nmax = ae_maxint(nmax, nhid2, _state); - } - ae_matrix_set_length(&neurons, nlayers, nmax, _state); - for(i=0; i<=nlayers-1; i++) - { - for(j=0; j<=nmax-1; j++) - { - neurons.ptr.pp_double[i][j] = (double)(0); - } - } - ae_vector_set_length(&x, nin, _state); - for(i=0; i<=nin-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - ae_vector_set_length(&y, nout, _state); - for(i=0; i<=nout-1; i++) - { - y.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(j=0; j<=nin-1; j++) - { - mlpgetinputscaling(&network, j, &mean, &sigma, _state); - neurons.ptr.pp_double[0][j] = (x.ptr.p_double[j]-mean)/sigma; - } - for(i=1; i<=nlayers-1; i++) - { - for(j=0; j<=mlpgetlayersize(&network, i, _state)-1; j++) - { - for(k=0; k<=mlpgetlayersize(&network, i-1, _state)-1; k++) - { - neurons.ptr.pp_double[i][j] = neurons.ptr.pp_double[i][j]+mlpgetweight(&network, i-1, k, i, j, _state)*neurons.ptr.pp_double[i-1][k]; - } - mlpgetneuroninfo(&network, i, j, &fkind, &c, _state); - mlpactivationfunction(neurons.ptr.pp_double[i][j]-c, fkind, &f, &df, &d2f, _state); - neurons.ptr.pp_double[i][j] = f; - } - } - if( nkind==1 ) - { - s = (double)(0); - for(j=0; j<=nout-1; j++) - { - s = s+ae_exp(neurons.ptr.pp_double[nlayers-1][j], _state); - } - for(j=0; j<=nout-1; j++) - { - neurons.ptr.pp_double[nlayers-1][j] = ae_exp(neurons.ptr.pp_double[nlayers-1][j], _state)/s; - } - } - for(j=0; j<=nout-1; j++) - { - mlpgetoutputscaling(&network, j, &mean, &sigma, _state); - neurons.ptr.pp_double[nlayers-1][j] = neurons.ptr.pp_double[nlayers-1][j]*sigma+mean; - } - mlpprocess(&network, &x, &y, _state); - for(j=0; j<=nout-1; j++) - { - *err = *err||ae_fp_greater(ae_fabs(neurons.ptr.pp_double[nlayers-1][j]-y.ptr.p_double[j], _state),threshold); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Processing functions test -*************************************************************************/ -static void testmlpbaseunit_testprocessing(ae_int_t nkind, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t passcount, - ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron network; - multilayerperceptron network2; - sparsematrix sparsexy; - ae_matrix densexy; - ae_int_t npoints; - ae_int_t subnp; - ae_bool iscls; - ae_int_t n1; - ae_int_t n2; - ae_int_t wcount; - ae_bool zeronet; - double a1; - double a2; - ae_int_t pass; - ae_int_t i; - ae_int_t j; - ae_bool allsame; - ae_vector x1; - ae_vector x2; - ae_vector y1; - ae_vector y2; - ae_vector p0; - ae_vector p1; - ae_int_t pcount; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&network, 0, sizeof(network)); - memset(&network2, 0, sizeof(network2)); - memset(&sparsexy, 0, sizeof(sparsexy)); - memset(&densexy, 0, sizeof(densexy)); - memset(&x1, 0, sizeof(x1)); - memset(&x2, 0, sizeof(x2)); - memset(&y1, 0, sizeof(y1)); - memset(&y2, 0, sizeof(y2)); - memset(&p0, 0, sizeof(p0)); - memset(&p1, 0, sizeof(p1)); - _multilayerperceptron_init(&network, _state, ae_true); - _multilayerperceptron_init(&network2, _state, ae_true); - _sparsematrix_init(&sparsexy, _state, ae_true); - ae_matrix_init(&densexy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p1, 0, DT_REAL, _state, ae_true); - - ae_assert(passcount>=2, "PassCount<2!", _state); - - /* - * Prepare network - */ - a1 = (double)(0); - a2 = (double)(0); - if( nkind==2 ) - { - a1 = 1000*ae_randomreal(_state)-500; - a2 = 2*ae_randomreal(_state)-1; - } - if( nkind==3 ) - { - a1 = 1000*ae_randomreal(_state)-500; - a2 = a1+(2*ae_randominteger(2, _state)-1)*(0.1+0.9*ae_randomreal(_state)); - } - testmlpbaseunit_createnetwork(&network, nkind, a1, a2, nin, nhid1, nhid2, nout, _state); - mlpproperties(&network, &n1, &n2, &wcount, _state); - iscls = mlpissoftmax(&network, _state); - - /* - * Initialize arrays - */ - ae_vector_set_length(&x1, nin, _state); - ae_vector_set_length(&x2, nin, _state); - ae_vector_set_length(&y1, nout, _state); - ae_vector_set_length(&y2, nout, _state); - - /* - * Initialize sets - */ - npoints = ae_randominteger(11, _state)+10; - if( iscls ) - { - ae_matrix_set_length(&densexy, npoints, nin+1, _state); - sparsecreate(npoints, nin+1, npoints, &sparsexy, _state); - } - else - { - ae_matrix_set_length(&densexy, npoints, nin+nout, _state); - sparsecreate(npoints, nin+nout, npoints, &sparsexy, _state); - } - sparseconverttocrs(&sparsexy, _state); - - /* - * Main cycle - */ - for(pass=1; pass<=passcount; pass++) - { - - /* - * Last run is made on zero network - */ - mlprandomizefull(&network, _state); - zeronet = ae_false; - if( pass==passcount ) - { - ae_v_muld(&network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), 0); - zeronet = ae_true; - } - - /* - * Same inputs leads to same outputs - */ - for(i=0; i<=nin-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - for(i=0; i<=nout-1; i++) - { - y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - mlpprocess(&network, &x1, &y1, _state); - mlpprocess(&network, &x2, &y2, _state); - ae_set_error_flag(err, ae_fp_neq(testmlpbaseunit_vectordiff(&y1, &y2, nout, 1.0, _state),0.0), __FILE__, __LINE__, "testmlpbaseunit.ap:513"); - - /* - * Same inputs on original network leads to same outputs - * on copy created: - * * using MLPCopy - * * using MLPCopyShared - */ - for(i=0; i<=nin-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - for(i=0; i<=nout-1; i++) - { - y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=nout-1; i++) - { - y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - testmlpbaseunit_unsetnetwork(&network2, _state); - mlpcopy(&network, &network2, _state); - mlpprocess(&network, &x1, &y1, _state); - mlpprocess(&network2, &x2, &y2, _state); - ae_set_error_flag(err, ae_fp_neq(testmlpbaseunit_vectordiff(&y1, &y2, nout, 1.0, _state),0.0), __FILE__, __LINE__, "testmlpbaseunit.ap:534"); - for(i=0; i<=nout-1; i++) - { - y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - testmlpbaseunit_unsetnetwork(&network2, _state); - mlpcopyshared(&network, &network2, _state); - mlpprocess(&network, &x1, &y1, _state); - mlpprocess(&network2, &x2, &y2, _state); - ae_set_error_flag(err, ae_fp_neq(testmlpbaseunit_vectordiff(&y1, &y2, nout, 1.0, _state),0.0), __FILE__, __LINE__, "testmlpbaseunit.ap:541"); - - /* - * Additionally we tests functions for copying of tunable - * parameters by: - * * copying network using MLPCopy - * * randomizing tunable parameters with MLPRandomizeFull() - * * copying tunable parameters with: - * a) MLPCopyTunableParameters - * b) combination of MLPExportTunableParameters and - * MLPImportTunableParameters - we export parameters - * to P1, copy PCount elements to P2, then test import. - */ - for(i=0; i<=nin-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - for(i=0; i<=nout-1; i++) - { - y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=nout-1; i++) - { - y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - testmlpbaseunit_unsetnetwork(&network2, _state); - mlpcopy(&network, &network2, _state); - mlprandomizefull(&network2, _state); - mlpcopytunableparameters(&network, &network2, _state); - mlpprocess(&network, &x1, &y1, _state); - mlpprocess(&network2, &x2, &y2, _state); - ae_set_error_flag(err, ae_fp_neq(testmlpbaseunit_vectordiff(&y1, &y2, nout, 1.0, _state),0.0), __FILE__, __LINE__, "testmlpbaseunit.ap:571"); - for(i=0; i<=nout-1; i++) - { - y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - testmlpbaseunit_unsetnetwork(&network2, _state); - mlpcopy(&network, &network2, _state); - mlprandomizefull(&network2, _state); - mlpexporttunableparameters(&network, &p0, &pcount, _state); - ae_vector_set_length(&p1, pcount, _state); - for(i=0; i<=pcount-1; i++) - { - p1.ptr.p_double[i] = p0.ptr.p_double[i]; - } - mlpimporttunableparameters(&network2, &p1, _state); - mlpprocess(&network, &x1, &y1, _state); - mlpprocess(&network2, &x2, &y2, _state); - ae_set_error_flag(err, ae_fp_neq(testmlpbaseunit_vectordiff(&y1, &y2, nout, 1.0, _state),0.0), __FILE__, __LINE__, "testmlpbaseunit.ap:585"); - - /* - * Same inputs on original network leads to same outputs - * on copy created using MLPSerialize - */ - testmlpbaseunit_unsetnetwork(&network2, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - mlpalloc(&_local_serializer, &network, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpserialize(&_local_serializer, &network, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpunserialize(&_local_serializer, &network2, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - for(i=0; i<=nin-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - for(i=0; i<=nout-1; i++) - { - y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - mlpprocess(&network, &x1, &y1, _state); - mlpprocess(&network2, &x2, &y2, _state); - allsame = ae_true; - for(i=0; i<=nout-1; i++) - { - allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]); - } - *err = *err||!allsame; - - /* - * Different inputs leads to different outputs (non-zero network) - */ - if( !zeronet ) - { - for(i=0; i<=nin-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=nout-1; i++) - { - y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - y2.ptr.p_double[i] = y1.ptr.p_double[i]; - } - mlpprocess(&network, &x1, &y1, _state); - mlpprocess(&network, &x2, &y2, _state); - allsame = ae_true; - for(i=0; i<=nout-1; i++) - { - allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]); - } - *err = *err||allsame; - } - - /* - * Randomization changes outputs (when inputs are unchanged, non-zero network) - */ - if( !zeronet ) - { - for(i=0; i<=nin-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=nout-1; i++) - { - y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - y2.ptr.p_double[i] = y1.ptr.p_double[i]; - } - mlpcopy(&network, &network2, _state); - mlprandomize(&network2, _state); - mlpprocess(&network, &x1, &y1, _state); - mlpprocess(&network2, &x1, &y2, _state); - allsame = ae_true; - for(i=0; i<=nout-1; i++) - { - allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]); - } - *err = *err||allsame; - } - - /* - * Full randomization changes outputs (when inputs are unchanged, non-zero network) - */ - if( !zeronet ) - { - for(i=0; i<=nin-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=nout-1; i++) - { - y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - y2.ptr.p_double[i] = y1.ptr.p_double[i]; - } - mlpcopy(&network, &network2, _state); - mlprandomizefull(&network2, _state); - mlpprocess(&network, &x1, &y1, _state); - mlpprocess(&network2, &x1, &y2, _state); - allsame = ae_true; - for(i=0; i<=nout-1; i++) - { - allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]); - } - *err = *err||allsame; - } - - /* - * Normalization properties - */ - if( nkind==1 ) - { - - /* - * Classifier network outputs are normalized - */ - for(i=0; i<=nin-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - mlpprocess(&network, &x1, &y1, _state); - v = (double)(0); - for(i=0; i<=nout-1; i++) - { - v = v+y1.ptr.p_double[i]; - *err = *err||ae_fp_less(y1.ptr.p_double[i],(double)(0)); - } - *err = *err||ae_fp_greater(ae_fabs(v-1, _state),1000*ae_machineepsilon); - } - if( nkind==2 ) - { - - /* - * B-type network outputs are bounded from above/below - */ - for(i=0; i<=nin-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - mlpprocess(&network, &x1, &y1, _state); - for(i=0; i<=nout-1; i++) - { - if( ae_fp_greater_eq(a2,(double)(0)) ) - { - *err = *err||ae_fp_less(y1.ptr.p_double[i],a1); - } - else - { - *err = *err||ae_fp_greater(y1.ptr.p_double[i],a1); - } - } - } - if( nkind==3 ) - { - - /* - * R-type network outputs are within [A1,A2] (or [A2,A1]) - */ - for(i=0; i<=nin-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - mlpprocess(&network, &x1, &y1, _state); - for(i=0; i<=nout-1; i++) - { - *err = (*err||ae_fp_less(y1.ptr.p_double[i],ae_minreal(a1, a2, _state)))||ae_fp_greater(y1.ptr.p_double[i],ae_maxreal(a1, a2, _state)); - } - } - - /* - * Comperison MLPInitPreprocessor results with - * MLPInitPreprocessorSparse results - */ - sparseconverttohash(&sparsexy, _state); - if( iscls ) - { - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nin-1; j++) - { - densexy.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - sparseset(&sparsexy, i, j, densexy.ptr.pp_double[i][j], _state); - } - densexy.ptr.pp_double[i][nin] = (double)(ae_randominteger(nout, _state)); - sparseset(&sparsexy, i, j, densexy.ptr.pp_double[i][nin], _state); - } - } - else - { - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nin+nout-1; j++) - { - densexy.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - sparseset(&sparsexy, i, j, densexy.ptr.pp_double[i][j], _state); - } - } - } - sparseconverttocrs(&sparsexy, _state); - mlpcopy(&network, &network2, _state); - mlpinitpreprocessor(&network, &densexy, npoints, _state); - mlpinitpreprocessorsparse(&network2, &sparsexy, npoints, _state); - subnp = ae_randominteger(npoints, _state); - for(i=0; i<=subnp-1; i++) - { - for(j=0; j<=nin-1; j++) - { - x1.ptr.p_double[j] = 2*ae_randomreal(_state)-1; - } - mlpprocess(&network, &x1, &y1, _state); - mlpprocess(&network2, &x1, &y2, _state); - for(j=0; j<=nout-1; j++) - { - *err = *err||ae_fp_greater(ae_fabs(y1.ptr.p_double[j]-y2.ptr.p_double[j], _state),1.0E-6); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Gradient functions test -*************************************************************************/ -static void testmlpbaseunit_testgradient(ae_int_t nkind, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t passcount, - ae_int_t sizemin, - ae_int_t sizemax, - ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron network; - sparsematrix sparsexy; - sparsematrix sparsexy2; - ae_int_t n1; - ae_int_t n2; - ae_int_t wcount; - double h; - double etol; - double escale; - double gscale; - double nonstricttolerance; - double a1; - double a2; - ae_int_t pass; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t ssize; - ae_int_t subsetsize; - ae_int_t rowsize; - ae_matrix xy; - ae_matrix xy2; - ae_vector grad1; - ae_vector grad2; - ae_vector gradsp; - ae_vector x; - ae_vector y; - ae_vector x1; - ae_vector x2; - ae_vector y1; - ae_vector y2; - ae_vector idx; - double v; - double e; - double e1; - double e2; - double esp; - double v1; - double v2; - double v3; - double v4; - double wprev; - double referencee; - ae_vector referenceg; - - ae_frame_make(_state, &_frame_block); - memset(&network, 0, sizeof(network)); - memset(&sparsexy, 0, sizeof(sparsexy)); - memset(&sparsexy2, 0, sizeof(sparsexy2)); - memset(&xy, 0, sizeof(xy)); - memset(&xy2, 0, sizeof(xy2)); - memset(&grad1, 0, sizeof(grad1)); - memset(&grad2, 0, sizeof(grad2)); - memset(&gradsp, 0, sizeof(gradsp)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&x1, 0, sizeof(x1)); - memset(&x2, 0, sizeof(x2)); - memset(&y1, 0, sizeof(y1)); - memset(&y2, 0, sizeof(y2)); - memset(&idx, 0, sizeof(idx)); - memset(&referenceg, 0, sizeof(referenceg)); - _multilayerperceptron_init(&network, _state, ae_true); - _sparsematrix_init(&sparsexy, _state, ae_true); - _sparsematrix_init(&sparsexy2, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&grad1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&grad2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&gradsp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&idx, 0, DT_INT, _state, ae_true); - ae_vector_init(&referenceg, 0, DT_REAL, _state, ae_true); - - a1 = (double)(0); - a2 = (double)(0); - if( nkind==2 ) - { - a1 = 1000*ae_randomreal(_state)-500; - a2 = 2*ae_randomreal(_state)-1; - } - if( nkind==3 ) - { - a1 = 1000*ae_randomreal(_state)-500; - a2 = a1+(2*ae_randominteger(2, _state)-1)*(0.1+0.9*ae_randomreal(_state)); - } - testmlpbaseunit_createnetwork(&network, nkind, a1, a2, nin, nhid1, nhid2, nout, _state); - mlpproperties(&network, &n1, &n2, &wcount, _state); - h = 0.0001; - etol = 1.0E-2; - escale = 1.0E-2; - gscale = 1.0E-2; - nonstricttolerance = 0.01; - - /* - * Initialize - */ - ae_vector_set_length(&x, nin, _state); - ae_vector_set_length(&x1, nin, _state); - ae_vector_set_length(&x2, nin, _state); - ae_vector_set_length(&y, nout, _state); - ae_vector_set_length(&y1, nout, _state); - ae_vector_set_length(&y2, nout, _state); - ae_vector_set_length(&referenceg, wcount, _state); - ae_vector_set_length(&grad1, wcount, _state); - ae_vector_set_length(&grad2, wcount, _state); - - /* - * Process - */ - for(pass=1; pass<=passcount; pass++) - { - - /* - * Randomize network, then re-randomaze weights manually. - * - * NOTE: weights magnitude is chosen to be small, about 0.1, - * which allows us to avoid oversaturated network. - * In 10% of cases we use zero weights. - */ - mlprandomizefull(&network, _state); - if( ae_fp_less_eq(ae_randomreal(_state),0.1) ) - { - for(i=0; i<=wcount-1; i++) - { - network.weights.ptr.p_double[i] = 0.0; - } - } - else - { - for(i=0; i<=wcount-1; i++) - { - network.weights.ptr.p_double[i] = 0.2*ae_randomreal(_state)-0.1; - } - } - - /* - * Test MLPError(), MLPErrorSparse(), MLPGrad() for single-element dataset: - * * generate input X, output Y, combine them in dataset XY - * * calculate "reference" error on dataset manually (call MLPProcess and evaluate sum-of-squared errors) - * * calculate "reference" gradient by performing numerical differentiation of "reference" error - * using 4-point differentiation formula - * * test error/gradient returned by MLPGrad(), MLPError(), MLPErrorSparse() - */ - ae_matrix_set_length(&xy, 1, nin+nout, _state); - sparsecreate(1, nin+nout, nin+nout, &sparsexy, _state); - for(i=0; i<=nin-1; i++) - { - x.ptr.p_double[i] = 4*ae_randomreal(_state)-2; - } - ae_v_move(&xy.ptr.pp_double[0][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,nin-1)); - for(i=0; i<=nin-1; i++) - { - sparseset(&sparsexy, 0, i, x.ptr.p_double[i], _state); - } - if( mlpissoftmax(&network, _state) ) - { - for(i=0; i<=nout-1; i++) - { - y.ptr.p_double[i] = (double)(0); - } - xy.ptr.pp_double[0][nin] = (double)(ae_randominteger(nout, _state)); - sparseset(&sparsexy, 0, nin, xy.ptr.pp_double[0][nin], _state); - y.ptr.p_double[ae_round(xy.ptr.pp_double[0][nin], _state)] = (double)(1); - } - else - { - for(i=0; i<=nout-1; i++) - { - y.ptr.p_double[i] = 4*ae_randomreal(_state)-2; - sparseset(&sparsexy, 0, nin+i, y.ptr.p_double[i], _state); - } - ae_v_move(&xy.ptr.pp_double[0][nin], 1, &y.ptr.p_double[0], 1, ae_v_len(nin,nin+nout-1)); - } - sparseconverttocrs(&sparsexy, _state); - mlpprocess(&network, &x, &y2, _state); - ae_v_sub(&y2.ptr.p_double[0], 1, &y.ptr.p_double[0], 1, ae_v_len(0,nout-1)); - referencee = ae_v_dotproduct(&y2.ptr.p_double[0], 1, &y2.ptr.p_double[0], 1, ae_v_len(0,nout-1)); - referencee = referencee/2; - for(i=0; i<=wcount-1; i++) - { - wprev = network.weights.ptr.p_double[i]; - network.weights.ptr.p_double[i] = wprev-2*h; - mlpprocess(&network, &x, &y1, _state); - ae_v_sub(&y1.ptr.p_double[0], 1, &y.ptr.p_double[0], 1, ae_v_len(0,nout-1)); - v1 = ae_v_dotproduct(&y1.ptr.p_double[0], 1, &y1.ptr.p_double[0], 1, ae_v_len(0,nout-1)); - v1 = v1/2; - network.weights.ptr.p_double[i] = wprev-h; - mlpprocess(&network, &x, &y1, _state); - ae_v_sub(&y1.ptr.p_double[0], 1, &y.ptr.p_double[0], 1, ae_v_len(0,nout-1)); - v2 = ae_v_dotproduct(&y1.ptr.p_double[0], 1, &y1.ptr.p_double[0], 1, ae_v_len(0,nout-1)); - v2 = v2/2; - network.weights.ptr.p_double[i] = wprev+h; - mlpprocess(&network, &x, &y1, _state); - ae_v_sub(&y1.ptr.p_double[0], 1, &y.ptr.p_double[0], 1, ae_v_len(0,nout-1)); - v3 = ae_v_dotproduct(&y1.ptr.p_double[0], 1, &y1.ptr.p_double[0], 1, ae_v_len(0,nout-1)); - v3 = v3/2; - network.weights.ptr.p_double[i] = wprev+2*h; - mlpprocess(&network, &x, &y1, _state); - ae_v_sub(&y1.ptr.p_double[0], 1, &y.ptr.p_double[0], 1, ae_v_len(0,nout-1)); - v4 = ae_v_dotproduct(&y1.ptr.p_double[0], 1, &y1.ptr.p_double[0], 1, ae_v_len(0,nout-1)); - v4 = v4/2; - network.weights.ptr.p_double[i] = wprev; - referenceg.ptr.p_double[i] = (v1-8*v2+8*v3-v4)/(12*h); - } - mlpgrad(&network, &x, &y, &e, &grad2, _state); - seterrorflagdiff(err, e, referencee, etol, escale, _state); - seterrorflagdiff(err, mlperror(&network, &xy, 1, _state), referencee, etol, escale, _state); - seterrorflagdiff(err, mlperrorsparse(&network, &sparsexy, 1, _state), referencee, etol, escale, _state); - ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &grad2, wcount, gscale, _state),etol), __FILE__, __LINE__, "testmlpbaseunit.ap:948"); - - /* - * Test MLPErrorN(), MLPGradN() for single-element dataset: - * * generate input X, output Y, combine them in dataset XY - * * calculate "reference" error on dataset manually (call MLPProcess and evaluate sum-of-squared errors) - * * calculate "reference" gradient by performing numerical differentiation of "reference" error - * * test error/gradient returned by MLPGradN(), MLPErrorN() - * - * NOTE: because we use inexact 2-point formula, we perform gradient test with NonStrictTolerance - */ - ae_matrix_set_length(&xy, 1, nin+nout, _state); - for(i=0; i<=nin-1; i++) - { - x.ptr.p_double[i] = 4*ae_randomreal(_state)-2; - } - ae_v_move(&xy.ptr.pp_double[0][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,nin-1)); - if( mlpissoftmax(&network, _state) ) - { - for(i=0; i<=nout-1; i++) - { - y.ptr.p_double[i] = (double)(0); - } - xy.ptr.pp_double[0][nin] = (double)(ae_randominteger(nout, _state)); - y.ptr.p_double[ae_round(xy.ptr.pp_double[0][nin], _state)] = (double)(1); - } - else - { - for(i=0; i<=nout-1; i++) - { - y.ptr.p_double[i] = 4*ae_randomreal(_state)-2; - } - ae_v_move(&xy.ptr.pp_double[0][nin], 1, &y.ptr.p_double[0], 1, ae_v_len(nin,nin+nout-1)); - } - mlpprocess(&network, &x, &y2, _state); - referencee = (double)(0); - if( nkind!=1 ) - { - for(i=0; i<=nout-1; i++) - { - referencee = referencee+0.5*ae_sqr(y2.ptr.p_double[i]-y.ptr.p_double[i], _state); - } - } - else - { - for(i=0; i<=nout-1; i++) - { - if( ae_fp_neq(y.ptr.p_double[i],(double)(0)) ) - { - if( ae_fp_eq(y2.ptr.p_double[i],(double)(0)) ) - { - referencee = referencee+y.ptr.p_double[i]*ae_log(ae_maxrealnumber, _state); - } - else - { - referencee = referencee+y.ptr.p_double[i]*ae_log(y.ptr.p_double[i]/y2.ptr.p_double[i], _state); - } - } - } - } - for(i=0; i<=wcount-1; i++) - { - wprev = network.weights.ptr.p_double[i]; - network.weights.ptr.p_double[i] = wprev+h; - mlpprocess(&network, &x, &y2, _state); - network.weights.ptr.p_double[i] = wprev-h; - mlpprocess(&network, &x, &y1, _state); - network.weights.ptr.p_double[i] = wprev; - v = (double)(0); - if( nkind!=1 ) - { - for(j=0; j<=nout-1; j++) - { - v = v+0.5*(ae_sqr(y2.ptr.p_double[j]-y.ptr.p_double[j], _state)-ae_sqr(y1.ptr.p_double[j]-y.ptr.p_double[j], _state))/(2*h); - } - } - else - { - for(j=0; j<=nout-1; j++) - { - if( ae_fp_neq(y.ptr.p_double[j],(double)(0)) ) - { - if( ae_fp_eq(y2.ptr.p_double[j],(double)(0)) ) - { - v = v+y.ptr.p_double[j]*ae_log(ae_maxrealnumber, _state); - } - else - { - v = v+y.ptr.p_double[j]*ae_log(y.ptr.p_double[j]/y2.ptr.p_double[j], _state); - } - if( ae_fp_eq(y1.ptr.p_double[j],(double)(0)) ) - { - v = v-y.ptr.p_double[j]*ae_log(ae_maxrealnumber, _state); - } - else - { - v = v-y.ptr.p_double[j]*ae_log(y.ptr.p_double[j]/y1.ptr.p_double[j], _state); - } - } - } - v = v/(2*h); - } - referenceg.ptr.p_double[i] = v; - } - mlpgradn(&network, &x, &y, &e, &grad2, _state); - seterrorflagdiff(err, e, referencee, etol, escale, _state); - seterrorflagdiff(err, mlperrorn(&network, &xy, 1, _state), referencee, etol, escale, _state); - ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &grad2, wcount, gscale, _state),nonstricttolerance), __FILE__, __LINE__, "testmlpbaseunit.ap:1029"); - - /* - * Test that gradient calculation functions automatically allocate - * space for gradient, if needed. - * - * NOTE: we perform test with empty dataset. - */ - sparsecreate(1, nin+nout, 0, &sparsexy, _state); - sparseconverttocrs(&sparsexy, _state); - ae_vector_set_length(&grad1, 1, _state); - mlpgradbatch(&network, &xy, 0, &e1, &grad1, _state); - ae_set_error_flag(err, grad1.cnt!=wcount, __FILE__, __LINE__, "testmlpbaseunit.ap:1042"); - ae_vector_set_length(&grad1, 1, _state); - mlpgradbatchsparse(&network, &sparsexy, 0, &e1, &grad1, _state); - ae_set_error_flag(err, grad1.cnt!=wcount, __FILE__, __LINE__, "testmlpbaseunit.ap:1045"); - ae_vector_set_length(&grad1, 1, _state); - mlpgradbatchsubset(&network, &xy, 0, &idx, 0, &e1, &grad1, _state); - ae_set_error_flag(err, grad1.cnt!=wcount, __FILE__, __LINE__, "testmlpbaseunit.ap:1048"); - ae_vector_set_length(&grad1, 1, _state); - mlpgradbatchsparsesubset(&network, &sparsexy, 0, &idx, 0, &e1, &grad1, _state); - ae_set_error_flag(err, grad1.cnt!=wcount, __FILE__, __LINE__, "testmlpbaseunit.ap:1051"); - - /* - * Test MLPError(), MLPErrorSparse(), MLPGradBatch(), MLPGradBatchSparse() for many-element dataset: - * * generate random dataset XY - * * calculate "reference" error/gradient using MLPGrad(), which was tested in previous - * section and is assumed to work correctly - * * test results returned by MLPGradBatch/MLPGradBatchSparse against reference ones - * - * NOTE: about 10% of tests are performed with zero SSize - */ - ssize = sizemin+ae_randominteger(sizemax-sizemin+1, _state); - ae_matrix_set_length(&xy, ae_maxint(ssize, 1, _state), nin+nout, _state); - sparsecreate(ae_maxint(ssize, 1, _state), nin+nout, ssize*(nin+nout), &sparsexy, _state); - for(i=0; i<=wcount-1; i++) - { - referenceg.ptr.p_double[i] = (double)(0); - } - referencee = (double)(0); - for(i=0; i<=ssize-1; i++) - { - for(j=0; j<=nin-1; j++) - { - x1.ptr.p_double[j] = 4*ae_randomreal(_state)-2; - sparseset(&sparsexy, i, j, x1.ptr.p_double[j], _state); - } - ae_v_move(&xy.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,nin-1)); - if( mlpissoftmax(&network, _state) ) - { - for(j=0; j<=nout-1; j++) - { - y1.ptr.p_double[j] = (double)(0); - } - xy.ptr.pp_double[i][nin] = (double)(ae_randominteger(nout, _state)); - sparseset(&sparsexy, i, nin, xy.ptr.pp_double[i][nin], _state); - y1.ptr.p_double[ae_round(xy.ptr.pp_double[i][nin], _state)] = (double)(1); - } - else - { - for(j=0; j<=nout-1; j++) - { - y1.ptr.p_double[j] = 4*ae_randomreal(_state)-2; - sparseset(&sparsexy, i, nin+j, y1.ptr.p_double[j], _state); - } - ae_v_move(&xy.ptr.pp_double[i][nin], 1, &y1.ptr.p_double[0], 1, ae_v_len(nin,nin+nout-1)); - } - mlpgrad(&network, &x1, &y1, &v, &grad2, _state); - referencee = referencee+v; - ae_v_add(&referenceg.ptr.p_double[0], 1, &grad2.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - } - sparseconverttocrs(&sparsexy, _state); - e2 = mlperror(&network, &xy, ssize, _state); - seterrorflagdiff(err, e2, referencee, etol, escale, _state); - e2 = mlperrorsparse(&network, &sparsexy, ssize, _state); - seterrorflagdiff(err, e2, referencee, etol, escale, _state); - mlpgradbatch(&network, &xy, ssize, &e2, &grad2, _state); - seterrorflagdiff(err, e2, referencee, etol, escale, _state); - ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &grad2, wcount, gscale, _state),etol), __FILE__, __LINE__, "testmlpbaseunit.ap:1104"); - mlpgradbatchsparse(&network, &sparsexy, ssize, &esp, &gradsp, _state); - seterrorflagdiff(err, esp, referencee, etol, escale, _state); - ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &gradsp, wcount, gscale, _state),etol), __FILE__, __LINE__, "testmlpbaseunit.ap:1107"); - - /* - * Test MLPErrorSubset(), MLPGradBatchSubset(), MLPErrorSparseSubset(), MLPGradBatchSparseSubset() - * for many-element dataset with different types of subsets: - * * generate random dataset XY - * * "reference" error/gradient are calculated with MLPGradBatch(), - * which was tested in previous section and is assumed to work correctly - * * we perform tests for different subsets: - * * SubsetSize<0 - subset is a full dataset - * * SubsetSize=0 - subset is empty - * * SubsetSize>0 - random subset - */ - ssize = sizemin+ae_randominteger(sizemax-sizemin+1, _state); - ae_matrix_set_length(&xy, ae_maxint(ssize, 1, _state), nin+nout, _state); - sparsecreate(ae_maxint(ssize, 1, _state), nin+nout, ssize*(nin+nout), &sparsexy, _state); - for(i=0; i<=ssize-1; i++) - { - for(j=0; j<=nin-1; j++) - { - x1.ptr.p_double[j] = 4*ae_randomreal(_state)-2; - sparseset(&sparsexy, i, j, x1.ptr.p_double[j], _state); - } - ae_v_move(&xy.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,nin-1)); - if( mlpissoftmax(&network, _state) ) - { - for(j=0; j<=nout-1; j++) - { - y1.ptr.p_double[j] = (double)(0); - } - xy.ptr.pp_double[i][nin] = (double)(ae_randominteger(nout, _state)); - sparseset(&sparsexy, i, nin, xy.ptr.pp_double[i][nin], _state); - y1.ptr.p_double[ae_round(xy.ptr.pp_double[i][nin], _state)] = (double)(1); - } - else - { - for(j=0; j<=nout-1; j++) - { - y1.ptr.p_double[j] = 4*ae_randomreal(_state)-2; - sparseset(&sparsexy, i, nin+j, y1.ptr.p_double[j], _state); - } - ae_v_move(&xy.ptr.pp_double[i][nin], 1, &y1.ptr.p_double[0], 1, ae_v_len(nin,nin+nout-1)); - } - } - sparseconverttocrs(&sparsexy, _state); - if( ssize>0 ) - { - subsetsize = 1+ae_randominteger(10, _state); - ae_matrix_set_length(&xy2, subsetsize, nin+nout, _state); - ae_vector_set_length(&idx, subsetsize, _state); - sparsecreate(subsetsize, nin+nout, subsetsize*(nin+nout), &sparsexy2, _state); - if( mlpissoftmax(&network, _state) ) - { - rowsize = nin+1; - } - else - { - rowsize = nin+nout; - } - for(i=0; i<=subsetsize-1; i++) - { - k = ae_randominteger(ssize, _state); - idx.ptr.p_int[i] = k; - for(j=0; j<=rowsize-1; j++) - { - xy2.ptr.pp_double[i][j] = xy.ptr.pp_double[k][j]; - sparseset(&sparsexy2, i, j, sparseget(&sparsexy, k, j, _state), _state); - } - } - sparseconverttocrs(&sparsexy2, _state); - } - else - { - subsetsize = 0; - ae_matrix_set_length(&xy2, 0, 0, _state); - ae_vector_set_length(&idx, 0, _state); - sparsecreate(1, nin+nout, 0, &sparsexy2, _state); - sparseconverttocrs(&sparsexy2, _state); - } - mlpgradbatch(&network, &xy, ssize, &referencee, &referenceg, _state); - e2 = mlperrorsubset(&network, &xy, ssize, &idx, -1, _state); - esp = mlperrorsparsesubset(&network, &sparsexy, ssize, &idx, -1, _state); - seterrorflagdiff(err, e2, referencee, etol, escale, _state); - seterrorflagdiff(err, esp, referencee, etol, escale, _state); - mlpgradbatchsubset(&network, &xy, ssize, &idx, -1, &e2, &grad2, _state); - mlpgradbatchsparsesubset(&network, &sparsexy, ssize, &idx, -1, &esp, &gradsp, _state); - seterrorflagdiff(err, e2, referencee, etol, escale, _state); - seterrorflagdiff(err, esp, referencee, etol, escale, _state); - ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &grad2, wcount, gscale, _state),etol), __FILE__, __LINE__, "testmlpbaseunit.ap:1192"); - ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &gradsp, wcount, gscale, _state),etol), __FILE__, __LINE__, "testmlpbaseunit.ap:1193"); - mlpgradbatch(&network, &xy, 0, &referencee, &referenceg, _state); - e2 = mlperrorsubset(&network, &xy, ssize, &idx, 0, _state); - esp = mlperrorsparsesubset(&network, &sparsexy, ssize, &idx, 0, _state); - seterrorflagdiff(err, e2, referencee, etol, escale, _state); - seterrorflagdiff(err, esp, referencee, etol, escale, _state); - mlpgradbatchsubset(&network, &xy, ssize, &idx, 0, &e2, &grad2, _state); - mlpgradbatchsparsesubset(&network, &sparsexy, ssize, &idx, 0, &esp, &gradsp, _state); - seterrorflagdiff(err, e2, referencee, etol, escale, _state); - seterrorflagdiff(err, esp, referencee, etol, escale, _state); - ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &grad2, wcount, gscale, _state),etol), __FILE__, __LINE__, "testmlpbaseunit.ap:1205"); - ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &gradsp, wcount, gscale, _state),etol), __FILE__, __LINE__, "testmlpbaseunit.ap:1206"); - mlpgradbatch(&network, &xy2, subsetsize, &referencee, &referenceg, _state); - e2 = mlperrorsubset(&network, &xy, ssize, &idx, subsetsize, _state); - esp = mlperrorsparsesubset(&network, &sparsexy, ssize, &idx, subsetsize, _state); - seterrorflagdiff(err, e2, referencee, etol, escale, _state); - seterrorflagdiff(err, esp, referencee, etol, escale, _state); - mlpgradbatchsubset(&network, &xy, ssize, &idx, subsetsize, &e2, &grad2, _state); - mlpgradbatchsparsesubset(&network, &sparsexy, ssize, &idx, subsetsize, &esp, &gradsp, _state); - seterrorflagdiff(err, e2, referencee, etol, escale, _state); - seterrorflagdiff(err, esp, referencee, etol, escale, _state); - ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &grad2, wcount, gscale, _state),etol), __FILE__, __LINE__, "testmlpbaseunit.ap:1218"); - ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &gradsp, wcount, gscale, _state),etol), __FILE__, __LINE__, "testmlpbaseunit.ap:1219"); - - /* - * Test MLPGradNBatch() for many-element dataset: - * * generate random dataset XY - * * calculate "reference" error/gradient using MLPGrad(), which was tested in previous - * section and is assumed to work correctly - * * test results returned by MLPGradNBatch against reference ones - */ - ssize = sizemin+ae_randominteger(sizemax-sizemin+1, _state); - ae_matrix_set_length(&xy, ssize, nin+nout, _state); - for(i=0; i<=wcount-1; i++) - { - referenceg.ptr.p_double[i] = (double)(0); - } - referencee = (double)(0); - for(i=0; i<=ssize-1; i++) - { - for(j=0; j<=nin-1; j++) - { - x1.ptr.p_double[j] = 4*ae_randomreal(_state)-2; - } - ae_v_move(&xy.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,nin-1)); - if( mlpissoftmax(&network, _state) ) - { - for(j=0; j<=nout-1; j++) - { - y1.ptr.p_double[j] = (double)(0); - } - xy.ptr.pp_double[i][nin] = (double)(ae_randominteger(nout, _state)); - y1.ptr.p_double[ae_round(xy.ptr.pp_double[i][nin], _state)] = (double)(1); - } - else - { - for(j=0; j<=nout-1; j++) - { - y1.ptr.p_double[j] = 4*ae_randomreal(_state)-2; - } - ae_v_move(&xy.ptr.pp_double[i][nin], 1, &y1.ptr.p_double[0], 1, ae_v_len(nin,nin+nout-1)); - } - mlpgradn(&network, &x1, &y1, &v, &grad2, _state); - referencee = referencee+v; - ae_v_add(&referenceg.ptr.p_double[0], 1, &grad2.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - } - mlpgradnbatch(&network, &xy, ssize, &e2, &grad2, _state); - seterrorflagdiff(err, e2, referencee, etol, escale, _state); - ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &grad2, wcount, gscale, _state),etol), __FILE__, __LINE__, "testmlpbaseunit.ap:1258"); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Hessian functions test -*************************************************************************/ -static void testmlpbaseunit_testhessian(ae_int_t nkind, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t passcount, - ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron network; - ae_int_t hkind; - ae_int_t n1; - ae_int_t n2; - ae_int_t wcount; - double h; - double etol; - ae_int_t pass; - ae_int_t i; - ae_int_t j; - ae_int_t ssize; - double a1; - double a2; - ae_matrix xy; - ae_matrix h1; - ae_matrix h2; - ae_vector grad1; - ae_vector grad2; - ae_vector grad3; - ae_vector x; - ae_vector y; - ae_vector x1; - ae_vector x2; - ae_vector y1; - ae_vector y2; - double v; - double e1; - double e2; - double wprev; - - ae_frame_make(_state, &_frame_block); - memset(&network, 0, sizeof(network)); - memset(&xy, 0, sizeof(xy)); - memset(&h1, 0, sizeof(h1)); - memset(&h2, 0, sizeof(h2)); - memset(&grad1, 0, sizeof(grad1)); - memset(&grad2, 0, sizeof(grad2)); - memset(&grad3, 0, sizeof(grad3)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&x1, 0, sizeof(x1)); - memset(&x2, 0, sizeof(x2)); - memset(&y1, 0, sizeof(y1)); - memset(&y2, 0, sizeof(y2)); - _multilayerperceptron_init(&network, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&h1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&h2, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&grad1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&grad2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&grad3, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y2, 0, DT_REAL, _state, ae_true); - - ae_assert(passcount>=2, "PassCount<2!", _state); - a1 = (double)(0); - a2 = (double)(0); - if( nkind==2 ) - { - a1 = 1000*ae_randomreal(_state)-500; - a2 = 2*ae_randomreal(_state)-1; - } - if( nkind==3 ) - { - a1 = 1000*ae_randomreal(_state)-500; - a2 = a1+(2*ae_randominteger(2, _state)-1)*(0.1+0.9*ae_randomreal(_state)); - } - testmlpbaseunit_createnetwork(&network, nkind, a1, a2, nin, nhid1, nhid2, nout, _state); - mlpproperties(&network, &n1, &n2, &wcount, _state); - h = 0.0001; - etol = 0.05; - - /* - * Initialize - */ - ae_vector_set_length(&x, nin-1+1, _state); - ae_vector_set_length(&x1, nin-1+1, _state); - ae_vector_set_length(&x2, nin-1+1, _state); - ae_vector_set_length(&y, nout-1+1, _state); - ae_vector_set_length(&y1, nout-1+1, _state); - ae_vector_set_length(&y2, nout-1+1, _state); - ae_vector_set_length(&grad1, wcount-1+1, _state); - ae_vector_set_length(&grad2, wcount-1+1, _state); - ae_vector_set_length(&grad3, wcount-1+1, _state); - ae_matrix_set_length(&h1, wcount-1+1, wcount-1+1, _state); - ae_matrix_set_length(&h2, wcount-1+1, wcount-1+1, _state); - - /* - * Process - */ - for(pass=1; pass<=passcount; pass++) - { - mlprandomizefull(&network, _state); - - /* - * Test hessian calculation . - * E1 contains total error (calculated using MLPGrad/MLPGradN) - * Grad1 contains total gradient (calculated using MLPGrad/MLPGradN) - * H1 contains Hessian calculated using differences of gradients - * - * E2, Grad2 and H2 contains corresponing values calculated using MLPHessianBatch/MLPHessianNBatch - */ - for(hkind=0; hkind<=1; hkind++) - { - ssize = 1+ae_randominteger(10, _state); - ae_matrix_set_length(&xy, ssize-1+1, nin+nout-1+1, _state); - for(i=0; i<=wcount-1; i++) - { - grad1.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=wcount-1; i++) - { - for(j=0; j<=wcount-1; j++) - { - h1.ptr.pp_double[i][j] = (double)(0); - } - } - e1 = (double)(0); - for(i=0; i<=ssize-1; i++) - { - - /* - * X, Y - */ - for(j=0; j<=nin-1; j++) - { - x1.ptr.p_double[j] = 4*ae_randomreal(_state)-2; - } - ae_v_move(&xy.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,nin-1)); - if( mlpissoftmax(&network, _state) ) - { - for(j=0; j<=nout-1; j++) - { - y1.ptr.p_double[j] = (double)(0); - } - xy.ptr.pp_double[i][nin] = (double)(ae_randominteger(nout, _state)); - y1.ptr.p_double[ae_round(xy.ptr.pp_double[i][nin], _state)] = (double)(1); - } - else - { - for(j=0; j<=nout-1; j++) - { - y1.ptr.p_double[j] = 4*ae_randomreal(_state)-2; - } - ae_v_move(&xy.ptr.pp_double[i][nin], 1, &y1.ptr.p_double[0], 1, ae_v_len(nin,nin+nout-1)); - } - - /* - * E1, Grad1 - */ - if( hkind==0 ) - { - mlpgrad(&network, &x1, &y1, &v, &grad2, _state); - } - else - { - mlpgradn(&network, &x1, &y1, &v, &grad2, _state); - } - e1 = e1+v; - ae_v_add(&grad1.ptr.p_double[0], 1, &grad2.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - - /* - * H1 - */ - for(j=0; j<=wcount-1; j++) - { - wprev = network.weights.ptr.p_double[j]; - network.weights.ptr.p_double[j] = wprev-2*h; - if( hkind==0 ) - { - mlpgrad(&network, &x1, &y1, &v, &grad2, _state); - } - else - { - mlpgradn(&network, &x1, &y1, &v, &grad2, _state); - } - network.weights.ptr.p_double[j] = wprev-h; - if( hkind==0 ) - { - mlpgrad(&network, &x1, &y1, &v, &grad3, _state); - } - else - { - mlpgradn(&network, &x1, &y1, &v, &grad3, _state); - } - ae_v_subd(&grad2.ptr.p_double[0], 1, &grad3.ptr.p_double[0], 1, ae_v_len(0,wcount-1), 8); - network.weights.ptr.p_double[j] = wprev+h; - if( hkind==0 ) - { - mlpgrad(&network, &x1, &y1, &v, &grad3, _state); - } - else - { - mlpgradn(&network, &x1, &y1, &v, &grad3, _state); - } - ae_v_addd(&grad2.ptr.p_double[0], 1, &grad3.ptr.p_double[0], 1, ae_v_len(0,wcount-1), 8); - network.weights.ptr.p_double[j] = wprev+2*h; - if( hkind==0 ) - { - mlpgrad(&network, &x1, &y1, &v, &grad3, _state); - } - else - { - mlpgradn(&network, &x1, &y1, &v, &grad3, _state); - } - ae_v_sub(&grad2.ptr.p_double[0], 1, &grad3.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - v = 1/(12*h); - ae_v_addd(&h1.ptr.pp_double[j][0], 1, &grad2.ptr.p_double[0], 1, ae_v_len(0,wcount-1), v); - network.weights.ptr.p_double[j] = wprev; - } - } - if( hkind==0 ) - { - mlphessianbatch(&network, &xy, ssize, &e2, &grad2, &h2, _state); - } - else - { - mlphessiannbatch(&network, &xy, ssize, &e2, &grad2, &h2, _state); - } - *err = *err||ae_fp_greater(ae_fabs(e1-e2, _state)/e1,etol); - for(i=0; i<=wcount-1; i++) - { - if( ae_fp_greater(ae_fabs(grad1.ptr.p_double[i], _state),1.0E-2) ) - { - *err = *err||ae_fp_greater(ae_fabs((grad2.ptr.p_double[i]-grad1.ptr.p_double[i])/grad1.ptr.p_double[i], _state),etol); - } - else - { - *err = *err||ae_fp_greater(ae_fabs(grad2.ptr.p_double[i]-grad1.ptr.p_double[i], _state),etol); - } - } - for(i=0; i<=wcount-1; i++) - { - for(j=0; j<=wcount-1; j++) - { - if( ae_fp_greater(ae_fabs(h1.ptr.pp_double[i][j], _state),5.0E-2) ) - { - *err = *err||ae_fp_greater(ae_fabs((h1.ptr.pp_double[i][j]-h2.ptr.pp_double[i][j])/h1.ptr.pp_double[i][j], _state),etol); - } - else - { - *err = *err||ae_fp_greater(ae_fabs(h2.ptr.pp_double[i][j]-h1.ptr.pp_double[i][j], _state),etol); - } - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Error functions (other than MLPError and MLPErrorN) test. - -Network of type NKind is created, with NIn inputs, NHid1*NHid2 hidden -layers (one layer if NHid2=0), NOut outputs. PassCount random passes is -performed. Dataset has random size in [SizeMin,SizeMax]. -*************************************************************************/ -static void testmlpbaseunit_testerr(ae_int_t nkind, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t passcount, - ae_int_t sizemin, - ae_int_t sizemax, - ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron network; - sparsematrix sparsexy; - ae_int_t n1; - ae_int_t n2; - ae_int_t wcount; - double etol; - double escale; - double a1; - double a2; - ae_int_t pass; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t ssize; - ae_int_t subsetsize; - ae_matrix xy; - ae_vector y; - ae_vector x1; - ae_vector y1; - ae_vector idx; - ae_vector dummy; - double refrmserror; - double refclserror; - double refrelclserror; - double refavgce; - double refavgerror; - double refavgrelerror; - ae_int_t avgrelcnt; - modelerrors allerrors; - ae_int_t nnmax; - ae_int_t dsmax; - double relclstolerance; - - ae_frame_make(_state, &_frame_block); - memset(&network, 0, sizeof(network)); - memset(&sparsexy, 0, sizeof(sparsexy)); - memset(&xy, 0, sizeof(xy)); - memset(&y, 0, sizeof(y)); - memset(&x1, 0, sizeof(x1)); - memset(&y1, 0, sizeof(y1)); - memset(&idx, 0, sizeof(idx)); - memset(&dummy, 0, sizeof(dummy)); - memset(&allerrors, 0, sizeof(allerrors)); - _multilayerperceptron_init(&network, _state, ae_true); - _sparsematrix_init(&sparsexy, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&idx, 0, DT_INT, _state, ae_true); - ae_vector_init(&dummy, 0, DT_INT, _state, ae_true); - _modelerrors_init(&allerrors, _state, ae_true); - - a1 = (double)(0); - a2 = (double)(0); - if( nkind==2 ) - { - a1 = 1000*ae_randomreal(_state)-500; - a2 = 2*ae_randomreal(_state)-1; - } - if( nkind==3 ) - { - a1 = 1000*ae_randomreal(_state)-500; - a2 = a1+(2*ae_randominteger(2, _state)-1)*(0.1+0.9*ae_randomreal(_state)); - } - testmlpbaseunit_createnetwork(&network, nkind, a1, a2, nin, nhid1, nhid2, nout, _state); - mlpproperties(&network, &n1, &n2, &wcount, _state); - etol = 1.0E-4; - escale = 1.0E-2; - - /* - * Initialize - */ - ae_vector_set_length(&x1, nin, _state); - ae_vector_set_length(&y, nout, _state); - ae_vector_set_length(&y1, nout, _state); - - /* - * Process - */ - for(pass=1; pass<=passcount; pass++) - { - - /* - * Randomize network, then re-randomaze weights manually. - * - * NOTE: weights magnitude is chosen to be small, about 0.1, - * which allows us to avoid oversaturated network. - * In 10% of cases we use zero weights. - */ - mlprandomizefull(&network, _state); - if( ae_fp_less_eq(ae_randomreal(_state),0.1) ) - { - for(i=0; i<=wcount-1; i++) - { - network.weights.ptr.p_double[i] = 0.0; - } - } - else - { - for(i=0; i<=wcount-1; i++) - { - network.weights.ptr.p_double[i] = 0.2*ae_randomreal(_state)-0.1; - } - } - - /* - * Generate random dataset. - * Calculate reference errors. - * - * NOTE: about 10% of tests are performed with zero SSize - */ - ssize = sizemin+ae_randominteger(sizemax-sizemin+1, _state); - if( mlpissoftmax(&network, _state) ) - { - ae_matrix_set_length(&xy, ae_maxint(ssize, 1, _state), nin+1, _state); - sparsecreate(ae_maxint(ssize, 1, _state), nin+1, 0, &sparsexy, _state); - } - else - { - ae_matrix_set_length(&xy, ae_maxint(ssize, 1, _state), nin+nout, _state); - sparsecreate(ae_maxint(ssize, 1, _state), nin+nout, 0, &sparsexy, _state); - } - refrmserror = 0.0; - refclserror = 0.0; - refavgce = 0.0; - refavgerror = 0.0; - refavgrelerror = 0.0; - avgrelcnt = 0; - for(i=0; i<=ssize-1; i++) - { - - /* - * Fill I-th row - */ - for(j=0; j<=nin-1; j++) - { - x1.ptr.p_double[j] = 4*ae_randomreal(_state)-2; - sparseset(&sparsexy, i, j, x1.ptr.p_double[j], _state); - } - ae_v_move(&xy.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,nin-1)); - if( mlpissoftmax(&network, _state) ) - { - for(j=0; j<=nout-1; j++) - { - y1.ptr.p_double[j] = (double)(0); - } - xy.ptr.pp_double[i][nin] = (double)(ae_randominteger(nout, _state)); - sparseset(&sparsexy, i, nin, xy.ptr.pp_double[i][nin], _state); - y1.ptr.p_double[ae_round(xy.ptr.pp_double[i][nin], _state)] = (double)(1); - } - else - { - for(j=0; j<=nout-1; j++) - { - y1.ptr.p_double[j] = 4*ae_randomreal(_state)-2; - sparseset(&sparsexy, i, nin+j, y1.ptr.p_double[j], _state); - } - ae_v_move(&xy.ptr.pp_double[i][nin], 1, &y1.ptr.p_double[0], 1, ae_v_len(nin,nin+nout-1)); - } - - /* - * Process - */ - mlpprocess(&network, &x1, &y, _state); - - /* - * Update reference errors - */ - nnmax = 0; - if( mlpissoftmax(&network, _state) ) - { - if( ae_fp_greater(y.ptr.p_double[ae_round(xy.ptr.pp_double[i][nin], _state)],(double)(0)) ) - { - refavgce = refavgce+ae_log(1/y.ptr.p_double[ae_round(xy.ptr.pp_double[i][nin], _state)], _state); - } - else - { - refavgce = refavgce+ae_log(ae_maxrealnumber, _state); - } - } - if( mlpissoftmax(&network, _state) ) - { - dsmax = ae_round(xy.ptr.pp_double[i][nin], _state); - } - else - { - dsmax = 0; - } - for(j=0; j<=nout-1; j++) - { - refrmserror = refrmserror+ae_sqr(y.ptr.p_double[j]-y1.ptr.p_double[j], _state); - refavgerror = refavgerror+ae_fabs(y.ptr.p_double[j]-y1.ptr.p_double[j], _state); - if( ae_fp_neq(y1.ptr.p_double[j],(double)(0)) ) - { - refavgrelerror = refavgrelerror+ae_fabs(y.ptr.p_double[j]-y1.ptr.p_double[j], _state)/ae_fabs(y1.ptr.p_double[j], _state); - avgrelcnt = avgrelcnt+1; - } - if( ae_fp_greater(y.ptr.p_double[j],y.ptr.p_double[nnmax]) ) - { - nnmax = j; - } - if( !mlpissoftmax(&network, _state)&&ae_fp_greater(y1.ptr.p_double[j],y1.ptr.p_double[dsmax]) ) - { - dsmax = j; - } - } - if( nnmax!=dsmax ) - { - refclserror = refclserror+1; - } - } - sparseconverttocrs(&sparsexy, _state); - if( ssize>0 ) - { - refrmserror = ae_sqrt(refrmserror/(ssize*nout), _state); - refavgerror = refavgerror/(ssize*nout); - refrelclserror = refclserror/ssize; - refavgce = refavgce/(ssize*ae_log((double)(2), _state)); - } - else - { - refrelclserror = 0.0; - } - if( avgrelcnt>0 ) - { - refavgrelerror = refavgrelerror/avgrelcnt; - } - - /* - * Test "continuous" errors on full dataset - */ - seterrorflagdiff(err, mlprmserror(&network, &xy, ssize, _state), refrmserror, etol, escale, _state); - seterrorflagdiff(err, mlpavgce(&network, &xy, ssize, _state), refavgce, etol, escale, _state); - seterrorflagdiff(err, mlpavgerror(&network, &xy, ssize, _state), refavgerror, etol, escale, _state); - seterrorflagdiff(err, mlpavgrelerror(&network, &xy, ssize, _state), refavgrelerror, etol, escale, _state); - seterrorflagdiff(err, mlprmserrorsparse(&network, &sparsexy, ssize, _state), refrmserror, etol, escale, _state); - seterrorflagdiff(err, mlpavgcesparse(&network, &sparsexy, ssize, _state), refavgce, etol, escale, _state); - seterrorflagdiff(err, mlpavgerrorsparse(&network, &sparsexy, ssize, _state), refavgerror, etol, escale, _state); - seterrorflagdiff(err, mlpavgrelerrorsparse(&network, &sparsexy, ssize, _state), refavgrelerror, etol, escale, _state); - mlpallerrorssubset(&network, &xy, ssize, &dummy, -1, &allerrors, _state); - seterrorflagdiff(err, allerrors.avgce, refavgce, etol, escale, _state); - seterrorflagdiff(err, allerrors.rmserror, refrmserror, etol, escale, _state); - seterrorflagdiff(err, allerrors.avgerror, refavgerror, etol, escale, _state); - seterrorflagdiff(err, allerrors.avgrelerror, refavgrelerror, etol, escale, _state); - mlpallerrorssparsesubset(&network, &sparsexy, ssize, &dummy, -1, &allerrors, _state); - seterrorflagdiff(err, allerrors.avgce, refavgce, etol, escale, _state); - seterrorflagdiff(err, allerrors.rmserror, refrmserror, etol, escale, _state); - seterrorflagdiff(err, allerrors.avgerror, refavgerror, etol, escale, _state); - seterrorflagdiff(err, allerrors.avgrelerror, refavgrelerror, etol, escale, _state); - - /* - * Test errors on dataset given by subset. - * We perform only limited test for RMS error, assuming that either all errors - * are calculated correctly (subject to subset given by Idx) - or none of them. - */ - if( ssize>0 ) - { - subsetsize = ae_randominteger(10, _state); - } - else - { - subsetsize = 0; - } - ae_vector_set_length(&idx, subsetsize, _state); - refrmserror = 0.0; - for(i=0; i<=subsetsize-1; i++) - { - k = ae_randominteger(ssize, _state); - idx.ptr.p_int[i] = k; - ae_v_move(&x1.ptr.p_double[0], 1, &xy.ptr.pp_double[k][0], 1, ae_v_len(0,nin-1)); - if( mlpissoftmax(&network, _state) ) - { - for(j=0; j<=nout-1; j++) - { - y1.ptr.p_double[j] = (double)(0); - } - y1.ptr.p_double[ae_round(xy.ptr.pp_double[k][nin], _state)] = (double)(1); - } - else - { - for(j=0; j<=nout-1; j++) - { - y1.ptr.p_double[j] = xy.ptr.pp_double[k][nin+j]; - } - } - mlpprocess(&network, &x1, &y, _state); - for(j=0; j<=nout-1; j++) - { - refrmserror = refrmserror+ae_sqr(y.ptr.p_double[j]-y1.ptr.p_double[j], _state); - } - } - if( subsetsize>0 ) - { - refrmserror = ae_sqrt(refrmserror/(subsetsize*nout), _state); - } - mlpallerrorssubset(&network, &xy, ssize, &idx, subsetsize, &allerrors, _state); - seterrorflagdiff(err, allerrors.rmserror, refrmserror, etol, escale, _state); - mlpallerrorssparsesubset(&network, &sparsexy, ssize, &idx, subsetsize, &allerrors, _state); - seterrorflagdiff(err, allerrors.rmserror, refrmserror, etol, escale, _state); - - /* - * Test "discontinuous" error function. - * Even slight changes in the network output may force these functions - * to change by 1. So, we test them with relaxed criteria, corresponding to - * difference in classification of two samples. - */ - if( ssize>0 ) - { - relclstolerance = 2.5/ssize; - ae_set_error_flag(err, ae_fp_greater(ae_fabs(mlpclserror(&network, &xy, ssize, _state)-refclserror, _state),ssize*relclstolerance), __FILE__, __LINE__, "testmlpbaseunit.ap:1728"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(mlprelclserror(&network, &xy, ssize, _state)-refrelclserror, _state),relclstolerance), __FILE__, __LINE__, "testmlpbaseunit.ap:1729"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(mlprelclserrorsparse(&network, &sparsexy, ssize, _state)-refrelclserror, _state),relclstolerance), __FILE__, __LINE__, "testmlpbaseunit.ap:1730"); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Special tests -*************************************************************************/ -static void testmlpbaseunit_spectests(ae_bool* inferrors, - ae_bool* procerrors, - ae_bool* graderrors, - ae_bool* hesserrors, - ae_bool* errerrors, - ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron net; - ae_matrix xy; - double f; - ae_vector g; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&net, 0, sizeof(net)); - memset(&xy, 0, sizeof(xy)); - memset(&g, 0, sizeof(g)); - _multilayerperceptron_init(&net, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&g, 0, DT_REAL, _state, ae_true); - - - /* - * Special test for overflow in TanH: - * * create 1x1x1 linear network - * * create dataset with 1 item: [x, y] = [0, 1] - * * set network weights to [10000000, 10000000, 10000000, 10000000] - * * check that error function is finite - * * check that gradient is finite - */ - mlpcreate1(1, 1, 1, &net, _state); - ae_matrix_set_length(&xy, 1, 2, _state); - xy.ptr.pp_double[0][0] = (double)(0); - xy.ptr.pp_double[0][1] = 1.0; - for(i=0; i<=mlpgetweightscount(&net, _state)-1; i++) - { - net.weights.ptr.p_double[i] = 10000000.0; - } - mlpgradbatch(&net, &xy, 1, &f, &g, _state); - ae_set_error_flag(graderrors, !ae_isfinite(f, _state), __FILE__, __LINE__, "testmlpbaseunit.ap:1903"); - ae_set_error_flag(graderrors, !ae_isfinite(mlperror(&net, &xy, 1, _state), _state), __FILE__, __LINE__, "testmlpbaseunit.ap:1904"); - for(i=0; i<=mlpgetweightscount(&net, _state)-1; i++) - { - ae_set_error_flag(graderrors, !ae_isfinite(g.ptr.p_double[i], _state), __FILE__, __LINE__, "testmlpbaseunit.ap:1906"); - } - - /* - * Special test for overflow in SOFTMAX layer: - * * create 1x1x2 classifier network - * * create dataset with 1 item: [x, y] = [0, 1] - * * set network weights to [10000000, 10000000, 10000000, 10000000] - * * check that error function is finite - * * check that gradient is finite - */ - mlpcreatec1(1, 1, 2, &net, _state); - ae_matrix_set_length(&xy, 1, 2, _state); - xy.ptr.pp_double[0][0] = (double)(0); - xy.ptr.pp_double[0][1] = (double)(1); - for(i=0; i<=mlpgetweightscount(&net, _state)-1; i++) - { - net.weights.ptr.p_double[i] = 10000000.0; - } - mlpgradbatch(&net, &xy, 1, &f, &g, _state); - ae_set_error_flag(graderrors, !ae_isfinite(f, _state), __FILE__, __LINE__, "testmlpbaseunit.ap:1924"); - ae_set_error_flag(graderrors, !ae_isfinite(mlperror(&net, &xy, 1, _state), _state), __FILE__, __LINE__, "testmlpbaseunit.ap:1925"); - for(i=0; i<=mlpgetweightscount(&net, _state)-1; i++) - { - ae_set_error_flag(graderrors, !ae_isfinite(g.ptr.p_double[i], _state), __FILE__, __LINE__, "testmlpbaseunit.ap:1927"); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -The function test functions MLPGradBatchMasked and MLPGradBatchSparseMasked. -*************************************************************************/ -static ae_bool testmlpbaseunit_testmlpgbsubset(ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron net; - ae_matrix a; - ae_matrix parta; - sparsematrix sa; - sparsematrix partsa; - ae_vector idx; - double e1; - double e2; - ae_vector grad1; - ae_vector grad2; - ae_int_t nin; - ae_int_t nout; - ae_int_t w; - ae_int_t wcount; - ae_int_t nhid1; - ae_int_t nhid2; - ae_int_t nkind; - double a1; - double a2; - ae_int_t n1; - ae_int_t n2; - ae_int_t ssize; - ae_int_t maxssize; - ae_int_t sbsize; - ae_int_t nvar; - ae_int_t variant; - ae_int_t i; - ae_int_t j; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&net, 0, sizeof(net)); - memset(&a, 0, sizeof(a)); - memset(&parta, 0, sizeof(parta)); - memset(&sa, 0, sizeof(sa)); - memset(&partsa, 0, sizeof(partsa)); - memset(&idx, 0, sizeof(idx)); - memset(&grad1, 0, sizeof(grad1)); - memset(&grad2, 0, sizeof(grad2)); - _multilayerperceptron_init(&net, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&parta, 0, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&sa, _state, ae_true); - _sparsematrix_init(&partsa, _state, ae_true); - ae_vector_init(&idx, 0, DT_INT, _state, ae_true); - ae_vector_init(&grad1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&grad2, 0, DT_REAL, _state, ae_true); - - - /* - * Variant: - * * 1 - there are all rows; - * * 2 - there are no one rows; - * * 3 - there are some random rows. - */ - nvar = 3; - maxssize = 96; - for(ssize=0; ssize<=maxssize; ssize++) - { - ae_vector_set_length(&idx, ssize, _state); - nkind = ae_randominteger(4, _state); - a1 = (double)(0); - a2 = (double)(0); - if( nkind==2 ) - { - a1 = 1000*ae_randomreal(_state)-500; - a2 = 2*ae_randomreal(_state)-1; - } - if( nkind==3 ) - { - a1 = 1000*ae_randomreal(_state)-500; - a2 = a1+(2*ae_randominteger(2, _state)-1)*(0.1+0.9*ae_randomreal(_state)); - } - nin = ae_randominteger(20, _state)+1; - nhid1 = ae_randominteger(5, _state); - if( nhid1==0 ) - { - nhid2 = 0; - } - else - { - nhid2 = ae_randominteger(5, _state); - } - nout = ae_randominteger(20, _state)+2; - testmlpbaseunit_createnetwork(&net, nkind, a1, a2, nin, nhid1, nhid2, nout, _state); - mlpproperties(&net, &n1, &n2, &wcount, _state); - if( mlpissoftmax(&net, _state) ) - { - w = nin+1; - if( ssize>0 ) - { - ae_matrix_set_length(&a, ssize, w, _state); - sparsecreate(ssize, w, ssize*w, &sa, _state); - } - else - { - ae_matrix_set_length(&a, 0, 0, _state); - sparsecreate(1, 1, 0, &sa, _state); - } - for(i=0; i<=ssize-1; i++) - { - for(j=0; j<=w-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state); - } - } - for(i=0; i<=ssize-1; i++) - { - a.ptr.pp_double[i][nin] = (double)(ae_randominteger(nout, _state)); - sparseset(&sa, i, nin, a.ptr.pp_double[i][nin], _state); - } - } - else - { - w = nin+nout; - if( ssize>0 ) - { - ae_matrix_set_length(&a, ssize, w, _state); - sparsecreate(ssize, w, ssize*w, &sa, _state); - } - else - { - ae_matrix_set_length(&a, 0, 0, _state); - sparsecreate(1, 1, 0, &sa, _state); - } - for(i=0; i<=ssize-1; i++) - { - for(j=0; j<=w-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state); - } - } - } - sparseconverttocrs(&sa, _state); - for(variant=1; variant<=nvar; variant++) - { - sbsize = -1; - if( variant==1 ) - { - sbsize = ssize; - for(i=0; i<=sbsize-1; i++) - { - idx.ptr.p_int[i] = i; - } - } - if( variant==2 ) - { - sbsize = 0; - } - if( variant==3 ) - { - if( ssize==0 ) - { - sbsize = 0; - } - else - { - sbsize = ae_randominteger(ssize, _state); - } - for(i=0; i<=sbsize-1; i++) - { - idx.ptr.p_int[i] = ae_randominteger(ssize, _state); - } - } - ae_assert(sbsize>=0, "mlpbase test: integrity check failed", _state); - if( sbsize!=0 ) - { - ae_matrix_set_length(&parta, sbsize, w, _state); - sparsecreate(sbsize, w, sbsize*w, &partsa, _state); - } - else - { - ae_matrix_set_length(&parta, 0, 0, _state); - sparsecreate(1, 1, 0, &partsa, _state); - } - for(i=0; i<=sbsize-1; i++) - { - ae_v_move(&parta.ptr.pp_double[i][0], 1, &a.ptr.pp_double[idx.ptr.p_int[i]][0], 1, ae_v_len(0,w-1)); - for(j=0; j<=w-1; j++) - { - sparseset(&partsa, i, j, parta.ptr.pp_double[i][j], _state); - } - } - sparseconverttocrs(&partsa, _state); - mlpgradbatch(&net, &parta, sbsize, &e1, &grad1, _state); - mlpgradbatchsubset(&net, &a, ssize, &idx, sbsize, &e2, &grad2, _state); - - /* - * Test for dense matrix - */ - if( ae_fp_greater(ae_fabs(e1-e2, _state),1.0E-6) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=wcount-1; i++) - { - if( ae_fp_greater(ae_fabs(grad1.ptr.p_double[i]-grad2.ptr.p_double[i], _state),1.0E-6) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - - /* - * Test for sparse matrix - */ - mlpgradbatchsparse(&net, &partsa, sbsize, &e1, &grad1, _state); - mlpgradbatchsparsesubset(&net, &sa, ssize, &idx, sbsize, &e2, &grad2, _state); - if( ae_fp_greater(ae_fabs(e1-e2, _state),1.0E-6) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=wcount-1; i++) - { - if( ae_fp_greater(ae_fabs(grad1.ptr.p_double[i]-grad2.ptr.p_double[i], _state),1.0E-6) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - - -static void testldaunit_gensimpleset(ae_int_t nfeatures, - ae_int_t nclasses, - ae_int_t nsamples, - ae_int_t axis, - /* Real */ ae_matrix* xy, - ae_state *_state); -static void testldaunit_gendeg1set(ae_int_t nfeatures, - ae_int_t nclasses, - ae_int_t nsamples, - ae_int_t axis, - /* Real */ ae_matrix* xy, - ae_state *_state); -static double testldaunit_generatenormal(double mean, - double sigma, - ae_state *_state); -static ae_bool testldaunit_testwn(/* Real */ ae_matrix* xy, - /* Real */ ae_matrix* wn, - ae_int_t ns, - ae_int_t nf, - ae_int_t nc, - ae_int_t ndeg, - ae_state *_state); -static double testldaunit_calcj(ae_int_t nf, - /* Real */ ae_matrix* st, - /* Real */ ae_matrix* sw, - /* Real */ ae_vector* w, - double* p, - double* q, - ae_state *_state); -static void testldaunit_fishers(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nfeatures, - ae_int_t nclasses, - /* Real */ ae_matrix* st, - /* Real */ ae_matrix* sw, - ae_state *_state); - - - - - -ae_bool testlda(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t maxnf; - ae_int_t maxns; - ae_int_t maxnc; - ae_int_t passcount; - ae_bool ldanerrors; - ae_bool lda1errors; - ae_bool waserrors; - ae_int_t nf; - ae_int_t nc; - ae_int_t ns; - ae_int_t i; - ae_int_t info; - ae_int_t pass; - ae_int_t axis; - ae_matrix xy; - ae_matrix wn; - ae_vector w1; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&wn, 0, sizeof(wn)); - memset(&w1, 0, sizeof(w1)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&wn, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w1, 0, DT_REAL, _state, ae_true); - - - /* - * Primary settings - */ - maxnf = 10; - maxns = 1000; - maxnc = 5; - passcount = 1; - waserrors = ae_false; - ldanerrors = ae_false; - lda1errors = ae_false; - - /* - * General tests - */ - for(nf=1; nf<=maxnf; nf++) - { - for(nc=2; nc<=maxnc; nc++) - { - for(pass=1; pass<=passcount; pass++) - { - - /* - * Simple test for LDA-N/LDA-1 - */ - axis = ae_randominteger(nf, _state); - ns = maxns/2+ae_randominteger(maxns/2, _state); - testldaunit_gensimpleset(nf, nc, ns, axis, &xy, _state); - fisherldan(&xy, ns, nf, nc, &info, &wn, _state); - if( info!=1 ) - { - ldanerrors = ae_true; - continue; - } - ldanerrors = ldanerrors||!testldaunit_testwn(&xy, &wn, ns, nf, nc, 0, _state); - ldanerrors = ldanerrors||ae_fp_less_eq(ae_fabs(wn.ptr.pp_double[axis][0], _state),0.75); - fisherlda(&xy, ns, nf, nc, &info, &w1, _state); - for(i=0; i<=nf-1; i++) - { - lda1errors = lda1errors||ae_fp_neq(w1.ptr.p_double[i],wn.ptr.pp_double[i][0]); - } - - /* - * Degenerate test for LDA-N - */ - if( nf>=3 ) - { - ns = maxns/2+ae_randominteger(maxns/2, _state); - - /* - * there are two duplicate features, - * axis is oriented along non-duplicate feature - */ - axis = ae_randominteger(nf-2, _state); - testldaunit_gendeg1set(nf, nc, ns, axis, &xy, _state); - fisherldan(&xy, ns, nf, nc, &info, &wn, _state); - if( info!=2 ) - { - ldanerrors = ae_true; - continue; - } - ldanerrors = ldanerrors||ae_fp_less_eq(wn.ptr.pp_double[axis][0],0.75); - fisherlda(&xy, ns, nf, nc, &info, &w1, _state); - for(i=0; i<=nf-1; i++) - { - lda1errors = lda1errors||ae_fp_neq(w1.ptr.p_double[i],wn.ptr.pp_double[i][0]); - } - } - } - } - } - - /* - * Final report - */ - waserrors = ldanerrors||lda1errors; - if( !silent ) - { - printf("LDA TEST\n"); - printf("FISHER LDA-N: "); - if( !ldanerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("FISHER LDA-1: "); - if( !lda1errors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST SUMMARY: FAILED\n"); - } - else - { - printf("TEST SUMMARY: PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Generates 'simple' set - a sequence of unit 'balls' at (0,0), (1,0), (2,0) -and so on. -*************************************************************************/ -static void testldaunit_gensimpleset(ae_int_t nfeatures, - ae_int_t nclasses, - ae_int_t nsamples, - ae_int_t axis, - /* Real */ ae_matrix* xy, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t c; - - ae_matrix_clear(xy); - - ae_assert(axis>=0&&axisptr.pp_double[i][j] = testldaunit_generatenormal(0.0, 1.0, _state); - } - c = i%nclasses; - xy->ptr.pp_double[i][axis] = xy->ptr.pp_double[i][axis]+c; - xy->ptr.pp_double[i][nfeatures] = (double)(c); - } -} - - -/************************************************************************* -Generates 'degenerate' set #1. -NFeatures>=3. -*************************************************************************/ -static void testldaunit_gendeg1set(ae_int_t nfeatures, - ae_int_t nclasses, - ae_int_t nsamples, - ae_int_t axis, - /* Real */ ae_matrix* xy, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_int_t c; - - ae_matrix_clear(xy); - - ae_assert(axis>=0&&axis=3, "GenDeg1Set: wrong NFeatures!", _state); - ae_matrix_set_length(xy, nsamples-1+1, nfeatures+1, _state); - if( axis>=nfeatures-2 ) - { - axis = nfeatures-3; - } - for(i=0; i<=nsamples-1; i++) - { - for(j=0; j<=nfeatures-2; j++) - { - xy->ptr.pp_double[i][j] = testldaunit_generatenormal(0.0, 1.0, _state); - } - xy->ptr.pp_double[i][nfeatures-1] = xy->ptr.pp_double[i][nfeatures-2]; - c = i%nclasses; - xy->ptr.pp_double[i][axis] = xy->ptr.pp_double[i][axis]+c; - xy->ptr.pp_double[i][nfeatures] = (double)(c); - } -} - - -/************************************************************************* -Normal random number -*************************************************************************/ -static double testldaunit_generatenormal(double mean, - double sigma, - ae_state *_state) -{ - double u; - double v; - double sum; - double result; - - - result = mean; - for(;;) - { - u = (2*ae_randominteger(2, _state)-1)*ae_randomreal(_state); - v = (2*ae_randominteger(2, _state)-1)*ae_randomreal(_state); - sum = u*u+v*v; - if( ae_fp_less(sum,(double)(1))&&ae_fp_greater(sum,(double)(0)) ) - { - sum = ae_sqrt(-2*ae_log(sum, _state)/sum, _state); - result = sigma*u*sum+mean; - break; - } - } - return result; -} - - -/************************************************************************* -Tests WN for correctness -*************************************************************************/ -static ae_bool testldaunit_testwn(/* Real */ ae_matrix* xy, - /* Real */ ae_matrix* wn, - ae_int_t ns, - ae_int_t nf, - ae_int_t nc, - ae_int_t ndeg, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix st; - ae_matrix sw; - ae_matrix a; - ae_matrix z; - ae_vector tx; - ae_vector jp; - ae_vector jq; - ae_vector work; - ae_int_t i; - ae_int_t j; - double v; - double wprev; - double tol; - double p; - double q; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&st, 0, sizeof(st)); - memset(&sw, 0, sizeof(sw)); - memset(&a, 0, sizeof(a)); - memset(&z, 0, sizeof(z)); - memset(&tx, 0, sizeof(tx)); - memset(&jp, 0, sizeof(jp)); - memset(&jq, 0, sizeof(jq)); - memset(&work, 0, sizeof(work)); - ae_matrix_init(&st, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&sw, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&jp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&jq, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - - tol = (double)(10000); - result = ae_true; - testldaunit_fishers(xy, ns, nf, nc, &st, &sw, _state); - - /* - * Test for decreasing of J - */ - ae_vector_set_length(&tx, nf-1+1, _state); - ae_vector_set_length(&jp, nf-1+1, _state); - ae_vector_set_length(&jq, nf-1+1, _state); - for(j=0; j<=nf-1; j++) - { - ae_v_move(&tx.ptr.p_double[0], 1, &wn->ptr.pp_double[0][j], wn->stride, ae_v_len(0,nf-1)); - v = testldaunit_calcj(nf, &st, &sw, &tx, &p, &q, _state); - jp.ptr.p_double[j] = p; - jq.ptr.p_double[j] = q; - } - for(i=1; i<=nf-1-ndeg; i++) - { - result = result&&ae_fp_greater_eq(jp.ptr.p_double[i-1]/jq.ptr.p_double[i-1],(1-tol*ae_machineepsilon)*jp.ptr.p_double[i]/jq.ptr.p_double[i]); - } - for(i=nf-1-ndeg+1; i<=nf-1; i++) - { - result = result&&ae_fp_less_eq(jp.ptr.p_double[i],tol*ae_machineepsilon*jp.ptr.p_double[0]); - } - - /* - * Test for J optimality - */ - ae_v_move(&tx.ptr.p_double[0], 1, &wn->ptr.pp_double[0][0], wn->stride, ae_v_len(0,nf-1)); - v = testldaunit_calcj(nf, &st, &sw, &tx, &p, &q, _state); - for(i=0; i<=nf-1; i++) - { - wprev = tx.ptr.p_double[i]; - tx.ptr.p_double[i] = wprev+0.01; - result = result&&ae_fp_greater_eq(v,(1-tol*ae_machineepsilon)*testldaunit_calcj(nf, &st, &sw, &tx, &p, &q, _state)); - tx.ptr.p_double[i] = wprev-0.01; - result = result&&ae_fp_greater_eq(v,(1-tol*ae_machineepsilon)*testldaunit_calcj(nf, &st, &sw, &tx, &p, &q, _state)); - tx.ptr.p_double[i] = wprev; - } - - /* - * Test for linear independence of W - */ - ae_vector_set_length(&work, nf+1, _state); - ae_matrix_set_length(&a, nf-1+1, nf-1+1, _state); - matrixmatrixmultiply(wn, 0, nf-1, 0, nf-1, ae_false, wn, 0, nf-1, 0, nf-1, ae_true, 1.0, &a, 0, nf-1, 0, nf-1, 0.0, &work, _state); - if( smatrixevd(&a, nf, 1, ae_true, &tx, &z, _state) ) - { - result = result&&ae_fp_greater(tx.ptr.p_double[0],tx.ptr.p_double[nf-1]*1000*ae_machineepsilon); - } - - /* - * Test for other properties - */ - for(j=0; j<=nf-1; j++) - { - v = ae_v_dotproduct(&wn->ptr.pp_double[0][j], wn->stride, &wn->ptr.pp_double[0][j], wn->stride, ae_v_len(0,nf-1)); - v = ae_sqrt(v, _state); - result = result&&ae_fp_less_eq(ae_fabs(v-1, _state),1000*ae_machineepsilon); - v = (double)(0); - for(i=0; i<=nf-1; i++) - { - v = v+wn->ptr.pp_double[i][j]; - } - result = result&&ae_fp_greater_eq(v,(double)(0)); - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Calculates J -*************************************************************************/ -static double testldaunit_calcj(ae_int_t nf, - /* Real */ ae_matrix* st, - /* Real */ ae_matrix* sw, - /* Real */ ae_vector* w, - double* p, - double* q, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector tx; - ae_int_t i; - double v; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&tx, 0, sizeof(tx)); - *p = 0; - *q = 0; - ae_vector_init(&tx, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&tx, nf-1+1, _state); - for(i=0; i<=nf-1; i++) - { - v = ae_v_dotproduct(&st->ptr.pp_double[i][0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,nf-1)); - tx.ptr.p_double[i] = v; - } - v = ae_v_dotproduct(&w->ptr.p_double[0], 1, &tx.ptr.p_double[0], 1, ae_v_len(0,nf-1)); - *p = v; - for(i=0; i<=nf-1; i++) - { - v = ae_v_dotproduct(&sw->ptr.pp_double[i][0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,nf-1)); - tx.ptr.p_double[i] = v; - } - v = ae_v_dotproduct(&w->ptr.p_double[0], 1, &tx.ptr.p_double[0], 1, ae_v_len(0,nf-1)); - *q = v; - result = *p/(*q); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Calculates ST/SW -*************************************************************************/ -static void testldaunit_fishers(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nfeatures, - ae_int_t nclasses, - /* Real */ ae_matrix* st, - /* Real */ ae_matrix* sw, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - ae_vector c; - ae_vector mu; - ae_matrix muc; - ae_vector nc; - ae_vector tf; - ae_vector work; - - ae_frame_make(_state, &_frame_block); - memset(&c, 0, sizeof(c)); - memset(&mu, 0, sizeof(mu)); - memset(&muc, 0, sizeof(muc)); - memset(&nc, 0, sizeof(nc)); - memset(&tf, 0, sizeof(tf)); - memset(&work, 0, sizeof(work)); - ae_matrix_clear(st); - ae_matrix_clear(sw); - ae_vector_init(&c, 0, DT_INT, _state, ae_true); - ae_vector_init(&mu, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&muc, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&nc, 0, DT_INT, _state, ae_true); - ae_vector_init(&tf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - - - /* - * Prepare temporaries - */ - ae_vector_set_length(&tf, nfeatures-1+1, _state); - ae_vector_set_length(&work, nfeatures+1, _state); - - /* - * Convert class labels from reals to integers (just for convenience) - */ - ae_vector_set_length(&c, npoints-1+1, _state); - for(i=0; i<=npoints-1; i++) - { - c.ptr.p_int[i] = ae_round(xy->ptr.pp_double[i][nfeatures], _state); - } - - /* - * Calculate class sizes and means - */ - ae_vector_set_length(&mu, nfeatures-1+1, _state); - ae_matrix_set_length(&muc, nclasses-1+1, nfeatures-1+1, _state); - ae_vector_set_length(&nc, nclasses-1+1, _state); - for(j=0; j<=nfeatures-1; j++) - { - mu.ptr.p_double[j] = (double)(0); - } - for(i=0; i<=nclasses-1; i++) - { - nc.ptr.p_int[i] = 0; - for(j=0; j<=nfeatures-1; j++) - { - muc.ptr.pp_double[i][j] = (double)(0); - } - } - for(i=0; i<=npoints-1; i++) - { - ae_v_add(&mu.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nfeatures-1)); - ae_v_add(&muc.ptr.pp_double[c.ptr.p_int[i]][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nfeatures-1)); - nc.ptr.p_int[c.ptr.p_int[i]] = nc.ptr.p_int[c.ptr.p_int[i]]+1; - } - for(i=0; i<=nclasses-1; i++) - { - v = (double)1/(double)nc.ptr.p_int[i]; - ae_v_muld(&muc.ptr.pp_double[i][0], 1, ae_v_len(0,nfeatures-1), v); - } - v = (double)1/(double)npoints; - ae_v_muld(&mu.ptr.p_double[0], 1, ae_v_len(0,nfeatures-1), v); - - /* - * Create ST matrix - */ - ae_matrix_set_length(st, nfeatures-1+1, nfeatures-1+1, _state); - for(i=0; i<=nfeatures-1; i++) - { - for(j=0; j<=nfeatures-1; j++) - { - st->ptr.pp_double[i][j] = (double)(0); - } - } - for(k=0; k<=npoints-1; k++) - { - ae_v_move(&tf.ptr.p_double[0], 1, &xy->ptr.pp_double[k][0], 1, ae_v_len(0,nfeatures-1)); - ae_v_sub(&tf.ptr.p_double[0], 1, &mu.ptr.p_double[0], 1, ae_v_len(0,nfeatures-1)); - for(i=0; i<=nfeatures-1; i++) - { - v = tf.ptr.p_double[i]; - ae_v_addd(&st->ptr.pp_double[i][0], 1, &tf.ptr.p_double[0], 1, ae_v_len(0,nfeatures-1), v); - } - } - - /* - * Create SW matrix - */ - ae_matrix_set_length(sw, nfeatures-1+1, nfeatures-1+1, _state); - for(i=0; i<=nfeatures-1; i++) - { - for(j=0; j<=nfeatures-1; j++) - { - sw->ptr.pp_double[i][j] = (double)(0); - } - } - for(k=0; k<=npoints-1; k++) - { - ae_v_move(&tf.ptr.p_double[0], 1, &xy->ptr.pp_double[k][0], 1, ae_v_len(0,nfeatures-1)); - ae_v_sub(&tf.ptr.p_double[0], 1, &muc.ptr.pp_double[c.ptr.p_int[k]][0], 1, ae_v_len(0,nfeatures-1)); - for(i=0; i<=nfeatures-1; i++) - { - v = tf.ptr.p_double[i]; - ae_v_addd(&sw->ptr.pp_double[i][0], 1, &tf.ptr.p_double[0], 1, ae_v_len(0,nfeatures-1), v); - } - } - ae_frame_leave(_state); -} - - - -static void testssaunit_testgeneral(ae_bool* errorflag, ae_state *_state); -static void testssaunit_testspecial(ae_bool* errorflag, ae_state *_state); - - - - - -ae_bool testssa(ae_bool silent, ae_state *_state) -{ - ae_bool specerrors; - ae_bool generrors; - ae_bool wereerrors; - ae_bool result; - - - specerrors = ae_false; - generrors = ae_false; - testssaunit_testspecial(&specerrors, _state); - testssaunit_testgeneral(&generrors, _state); - - /* - * Final report - */ - wereerrors = specerrors||generrors; - if( !silent ) - { - printf("SSA TEST\n"); - printf("* GENERAL TEST SUITE "); - if( !generrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* SPECIAL CASES "); - if( !specerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( wereerrors ) - { - printf("TEST SUMMARY: FAILED\n"); - } - else - { - printf("TEST SUMMARY: PASSED\n"); - } - printf("\n\n"); - } - result = !wereerrors; - return result; -} - - -/************************************************************************* -This function tests SSA on several general purpose analysis/prediction -problems. - -On failure sets ErrorFlag, on success it is untouched. -*************************************************************************/ -static void testssaunit_testgeneral(ae_bool* errorflag, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double vv; - ae_int_t pass; - ssamodel state; - ssamodel state2; - ae_int_t ntracks; - ae_int_t windowwidth; - ae_int_t nlasttracklen; - ae_int_t nzeros; - ae_int_t nlinear; - double sinefreq; - double sineoffs; - double sineamp; - ae_int_t windowwidth2; - ae_int_t nbasis; - ae_int_t nbasis2; - ae_int_t ninitial; - ae_vector x; - ae_vector x2; - ae_vector trend; - ae_vector noise; - ae_vector sv; - ae_vector sv2; - ae_vector tmp0; - ae_vector trend2; - ae_vector noise2; - ae_int_t algotype; - ae_int_t nticks; - ae_int_t nnoise; - ae_int_t navg; - ae_matrix a; - ae_matrix a2; - ae_matrix b; - double tol; - ae_int_t datalen; - ae_int_t forecastlen; - ae_int_t mlimit; - hqrndstate rs; - ae_int_t passcount; - double skipprob; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&state2, 0, sizeof(state2)); - memset(&x, 0, sizeof(x)); - memset(&x2, 0, sizeof(x2)); - memset(&trend, 0, sizeof(trend)); - memset(&noise, 0, sizeof(noise)); - memset(&sv, 0, sizeof(sv)); - memset(&sv2, 0, sizeof(sv2)); - memset(&tmp0, 0, sizeof(tmp0)); - memset(&trend2, 0, sizeof(trend2)); - memset(&noise2, 0, sizeof(noise2)); - memset(&a, 0, sizeof(a)); - memset(&a2, 0, sizeof(a2)); - memset(&b, 0, sizeof(b)); - memset(&rs, 0, sizeof(rs)); - _ssamodel_init(&state, _state, ae_true); - _ssamodel_init(&state2, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&trend, 0, DT_REAL, _state, ae_true); - ae_vector_init(&noise, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sv, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sv2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&trend2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&noise2, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - - /* - * Initialize RNG, test pass count and skip probability. - * - * When we perform several sequential tests on the same model, we may - * skip some of them with probability SkipProb in order to make sure - * that no carry-over effect is observed between tests. - */ - hqrndrandomize(&rs, _state); - passcount = 500; - skipprob = 0.50; - - /* - * Iterate over several algorithm types. - * Algorithms unsupported by tests are skipped within tests. - */ - for(algotype=1; algotype<=3; algotype++) - { - - /* - * Test that on perfectly constant dataset SSA correctly predicts - * perfectly constant trend. Additionally test that analysis phase - * correctly returns nearly-zero noise and nearly-constant trend. - * - * Dataset is a one/few sequences with different constants; top-1 - * algorithm is used (or precomputed unit-normalized vector of 1's). - */ - for(pass=1; pass<=passcount; pass++) - { - nlasttracklen = -9999999; - ntracks = 1+hqrnduniformi(&rs, 3, _state); - windowwidth = 2+hqrnduniformi(&rs, 3, _state); - ssacreate(&state, _state); - ssasetwindow(&state, windowwidth, _state); - for(k=0; k<=ntracks-1; k++) - { - nlasttracklen = windowwidth+hqrnduniformi(&rs, windowwidth, _state); - v = hqrndnormal(&rs, _state); - ae_vector_set_length(&x, nlasttracklen, _state); - for(i=0; i<=nlasttracklen-1; i++) - { - x.ptr.p_double[i] = v; - } - ssaaddsequence(&state, &x, nlasttracklen, _state); - } - if( algotype==1 ) - { - ae_matrix_set_length(&b, windowwidth, 1, _state); - for(i=0; i<=windowwidth-1; i++) - { - b.ptr.pp_double[i][0] = 1/ae_sqrt((double)(windowwidth), _state); - } - ssasetalgoprecomputed(&state, &b, windowwidth, 1, _state); - } - else - { - if( algotype==2 ) - { - ssasetalgotopkdirect(&state, 1, _state); - } - else - { - if( algotype==3 ) - { - ssasetalgotopkrealtime(&state, 1, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - tol = 1.0E-6; - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - ssaanalyzelastwindow(&state, &trend, &noise, &nticks, _state); - ae_set_error_flag(errorflag, nticks!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:143"); - ae_set_error_flag(errorflag, noise.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:144"); - ae_set_error_flag(errorflag, trend.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:145"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=windowwidth-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[nlasttracklen+i-windowwidth], _state),tol), __FILE__, __LINE__, "testssaunit.ap:150"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:151"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - ssaanalyzelast(&state, nlasttracklen, &trend, &noise, _state); - ae_set_error_flag(errorflag, noise.cnt!=nlasttracklen, __FILE__, __LINE__, "testssaunit.ap:157"); - ae_set_error_flag(errorflag, trend.cnt!=nlasttracklen, __FILE__, __LINE__, "testssaunit.ap:158"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=nlasttracklen-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:163"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:164"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nticks = 1+hqrnduniformi(&rs, 2*windowwidth, _state); - ae_vector_set_length(&trend, 0, _state); - ssaforecastlast(&state, nticks, &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:172"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=trend.cnt-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[nlasttracklen-1], _state),tol), __FILE__, __LINE__, "testssaunit.ap:176"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nticks = 1+hqrnduniformi(&rs, 2*windowwidth, _state); - navg = 1+hqrnduniformi(&rs, windowwidth+3, _state); - ae_vector_set_length(&trend, 0, _state); - ssaforecastavglast(&state, navg, nticks, &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:184"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=trend.cnt-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[nlasttracklen-1], _state),tol), __FILE__, __LINE__, "testssaunit.ap:188"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - datalen = windowwidth+hqrnduniformi(&rs, 10, _state); - forecastlen = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&x, datalen, _state); - x.ptr.p_double[0] = hqrndnormal(&rs, _state); - for(i=1; i<=datalen-1; i++) - { - x.ptr.p_double[i] = x.ptr.p_double[i-1]; - } - ae_vector_set_length(&trend, 0, _state); - ssaforecastsequence(&state, &x, datalen, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=forecastlen, __FILE__, __LINE__, "testssaunit.ap:200"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=forecastlen-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[datalen-1], _state),tol), __FILE__, __LINE__, "testssaunit.ap:204"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - datalen = windowwidth+hqrnduniformi(&rs, 10, _state); - navg = 1+hqrnduniformi(&rs, windowwidth+3, _state); - forecastlen = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&x, datalen, _state); - x.ptr.p_double[0] = hqrndnormal(&rs, _state); - for(i=1; i<=datalen-1; i++) - { - x.ptr.p_double[i] = x.ptr.p_double[i-1]; - } - ae_vector_set_length(&trend, 0, _state); - ssaforecastavgsequence(&state, &x, datalen, navg, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=forecastlen, __FILE__, __LINE__, "testssaunit.ap:217"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=forecastlen-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[datalen-1], _state),tol), __FILE__, __LINE__, "testssaunit.ap:221"); - } - } - } - - /* - * Test that on specially designed linear dataset SSA correctly - * predicts perfectly linear trend. Additionally test that analysis - * phase correctly returns nearly-zero noise and nearly-linear trend. - * Also test that correct basis vectors are returned. - * - * Dataset consists of many WindowWidth-sized (exactly) sequences with - * linear trend. Trend coefficients vary accross sequences. Top-2 - * algorithm is used (or precomputed unit-normalized linear trend basis). - * - * NOTE: this test requires NTracks>=2, WindowWidth>=3 and TopK=2 to work; - * however, in order to improve numerical properties (diversity among - * samples, different slopes and offsets) we set NTracks to be - * at least 5. - * - * NOTE: one more version of this test verifies scaling properties - * by solving larger task (WindowWidth=100, NTracks=5, - * TrackLen=2*WindowWidth). This version makes just 5 checks because - * of higher cost. - */ - for(pass=1; pass<=passcount; pass++) - { - ntracks = 5+hqrnduniformi(&rs, 10, _state); - windowwidth = 3+hqrnduniformi(&rs, 3, _state); - ssacreate(&state, _state); - ssasetwindow(&state, windowwidth, _state); - ae_vector_set_length(&x, windowwidth, _state); - for(k=0; k<=ntracks-1; k++) - { - v = hqrndnormal(&rs, _state); - x.ptr.p_double[0] = hqrndnormal(&rs, _state); - for(i=1; i<=windowwidth-1; i++) - { - x.ptr.p_double[i] = x.ptr.p_double[i-1]+v; - } - ssaaddsequence(&state, &x, windowwidth, _state); - } - if( algotype==1 ) - { - ae_matrix_set_length(&b, windowwidth, 2, _state); - v = 0.0; - for(i=0; i<=windowwidth-1; i++) - { - b.ptr.pp_double[i][0] = 1/ae_sqrt((double)(windowwidth), _state); - b.ptr.pp_double[i][1] = (double)(i); - v = v+(double)i/(double)windowwidth; - } - vv = 0.0; - for(i=0; i<=windowwidth-1; i++) - { - b.ptr.pp_double[i][1] = b.ptr.pp_double[i][1]-v; - vv = vv+ae_sqr(b.ptr.pp_double[i][1], _state); - } - for(i=0; i<=windowwidth-1; i++) - { - b.ptr.pp_double[i][1] = b.ptr.pp_double[i][1]/ae_sqrt(vv, _state); - } - ssasetalgoprecomputed(&state, &b, windowwidth, 2, _state); - } - else - { - if( algotype==2 ) - { - ssasetalgotopkdirect(&state, 2, _state); - } - else - { - if( algotype==3 ) - { - ssasetalgotopkrealtime(&state, 2, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - tol = 1.0E-6; - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - - /* - * Basis vectors must be linear/constant functions - */ - ssagetbasis(&state, &a, &sv, &windowwidth2, &nbasis, _state); - ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:293"); - ae_set_error_flag(errorflag, nbasis!=2, __FILE__, __LINE__, "testssaunit.ap:294"); - ae_set_error_flag(errorflag, a.cols!=nbasis, __FILE__, __LINE__, "testssaunit.ap:295"); - ae_set_error_flag(errorflag, a.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:296"); - ae_set_error_flag(errorflag, sv.cnt!=nbasis, __FILE__, __LINE__, "testssaunit.ap:297"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(j=0; j<=nbasis-1; j++) - { - v = a.ptr.pp_double[1][j]-a.ptr.pp_double[0][j]; - for(i=2; i<=windowwidth-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-a.ptr.pp_double[i-1][j]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:304"); - } - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - ssaanalyzelastwindow(&state, &trend, &noise, &nticks, _state); - ae_set_error_flag(errorflag, nticks!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:310"); - ae_set_error_flag(errorflag, noise.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:311"); - ae_set_error_flag(errorflag, trend.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:312"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=windowwidth-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:317"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:318"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - ssaanalyzelast(&state, windowwidth, &trend, &noise, _state); - ae_set_error_flag(errorflag, noise.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:324"); - ae_set_error_flag(errorflag, trend.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:325"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=windowwidth-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:330"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:331"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nticks = 1+hqrnduniformi(&rs, 2*windowwidth, _state); - ssaforecastlast(&state, nticks, &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:338"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - v = x.ptr.p_double[windowwidth-1]-x.ptr.p_double[windowwidth-2]; - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[0]-x.ptr.p_double[windowwidth-1]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:342"); - for(i=1; i<=nticks-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-trend.ptr.p_double[i-1]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:344"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nticks = 1+hqrnduniformi(&rs, 2*windowwidth, _state); - navg = 1+hqrnduniformi(&rs, windowwidth+5, _state); - ae_vector_set_length(&trend, 0, _state); - ssaforecastavglast(&state, navg, nticks, &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:352"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - v = x.ptr.p_double[windowwidth-1]-x.ptr.p_double[windowwidth-2]; - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[0]-x.ptr.p_double[windowwidth-1]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:356"); - for(i=1; i<=nticks-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-trend.ptr.p_double[i-1]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:358"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - datalen = windowwidth+hqrnduniformi(&rs, 10, _state); - forecastlen = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&x, datalen, _state); - v = hqrndnormal(&rs, _state); - x.ptr.p_double[0] = hqrndnormal(&rs, _state); - for(i=1; i<=datalen-1; i++) - { - x.ptr.p_double[i] = x.ptr.p_double[i-1]+v; - } - ae_vector_set_length(&trend, 0, _state); - ssaforecastsequence(&state, &x, datalen, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=forecastlen, __FILE__, __LINE__, "testssaunit.ap:371"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[0]-x.ptr.p_double[datalen-1]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:374"); - for(i=1; i<=forecastlen-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-trend.ptr.p_double[i-1]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:376"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - datalen = windowwidth+hqrnduniformi(&rs, 10, _state); - navg = 1+hqrnduniformi(&rs, windowwidth+5, _state); - forecastlen = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&x, datalen, _state); - v = hqrndnormal(&rs, _state); - x.ptr.p_double[0] = hqrndnormal(&rs, _state); - for(i=1; i<=datalen-1; i++) - { - x.ptr.p_double[i] = x.ptr.p_double[i-1]+v; - } - ae_vector_set_length(&trend, 0, _state); - ssaforecastavgsequence(&state, &x, datalen, navg, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=forecastlen, __FILE__, __LINE__, "testssaunit.ap:390"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[0]-x.ptr.p_double[datalen-1]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:393"); - for(i=1; i<=forecastlen-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-trend.ptr.p_double[i-1]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:395"); - } - } - } - for(pass=1; pass<=5; pass++) - { - ntracks = 5+hqrnduniformi(&rs, 10, _state); - windowwidth = 100; - nlasttracklen = 2*windowwidth; - ssacreate(&state, _state); - ssasetwindow(&state, windowwidth, _state); - ae_vector_set_length(&x, nlasttracklen, _state); - for(k=0; k<=ntracks-1; k++) - { - v = hqrndnormal(&rs, _state); - x.ptr.p_double[0] = hqrndnormal(&rs, _state); - for(i=1; i<=nlasttracklen-1; i++) - { - x.ptr.p_double[i] = x.ptr.p_double[i-1]+v; - } - ssaaddsequence(&state, &x, nlasttracklen, _state); - } - if( algotype==1 ) - { - ae_matrix_set_length(&b, windowwidth, 2, _state); - v = 0.0; - for(i=0; i<=windowwidth-1; i++) - { - b.ptr.pp_double[i][0] = 1/ae_sqrt((double)(windowwidth), _state); - b.ptr.pp_double[i][1] = (double)(i); - v = v+(double)i/(double)windowwidth; - } - vv = 0.0; - for(i=0; i<=windowwidth-1; i++) - { - b.ptr.pp_double[i][1] = b.ptr.pp_double[i][1]-v; - vv = vv+ae_sqr(b.ptr.pp_double[i][1], _state); - } - for(i=0; i<=windowwidth-1; i++) - { - b.ptr.pp_double[i][1] = b.ptr.pp_double[i][1]/ae_sqrt(vv, _state); - } - ssasetalgoprecomputed(&state, &b, windowwidth, 2, _state); - } - else - { - if( algotype==2 ) - { - ssasetalgotopkdirect(&state, 2, _state); - } - else - { - if( algotype==3 ) - { - ssasetalgotopkrealtime(&state, 2, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - tol = 1.0E-6; - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - ssaanalyzelastwindow(&state, &trend, &noise, &nticks, _state); - ae_set_error_flag(errorflag, nticks!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:444"); - ae_set_error_flag(errorflag, noise.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:445"); - ae_set_error_flag(errorflag, trend.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:446"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=windowwidth-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[nlasttracklen+i-windowwidth], _state),tol), __FILE__, __LINE__, "testssaunit.ap:451"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:452"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - ssaanalyzelast(&state, nlasttracklen, &trend, &noise, _state); - ae_set_error_flag(errorflag, noise.cnt!=nlasttracklen, __FILE__, __LINE__, "testssaunit.ap:458"); - ae_set_error_flag(errorflag, trend.cnt!=nlasttracklen, __FILE__, __LINE__, "testssaunit.ap:459"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=nlasttracklen-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:464"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:465"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nticks = 1+hqrnduniformi(&rs, 10, _state); - ssaforecastlast(&state, nticks, &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:472"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - v = x.ptr.p_double[nlasttracklen-1]-x.ptr.p_double[nlasttracklen-2]; - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[0]-x.ptr.p_double[nlasttracklen-1]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:476"); - for(i=1; i<=nticks-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-trend.ptr.p_double[i-1]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:478"); - } - } - } - - /* - * Test that on specially designed dataset with two sinusoidal components - * with significantly different amplitudes, whose periods are integer - * divisors of window width, SSA correctly separates leading sine from - * its smaller counterpart. Also test that we can correctly predict future - * values of the sequence. - * - * Dataset consists of many sequences, each of them featuring either - * sine with period=WindowWidth or sine with period=WindowWidth/2. Such - * dataset is necessary because sum of two sines is not well separated by - * SVD (it performs only approximate, asymptotic separation). But when - * every sequence is either one of the sines, but not two together, we - * can easily separate them. - * - * Sine coefficients are changed from sequence to sequence. - * - * NOTE: this test requires large WindowWidth and TopK=2 to work. - * - * NOTE: this test uses reduced number of passes because of higher computational complexity - */ - for(pass=1; pass<=10; pass++) - { - - /* - * Skip "precomputed basis" algorithm - */ - if( algotype==1 ) - { - continue; - } - - /* - * Generate dataset - */ - ntracks = 100+hqrnduniformi(&rs, 2, _state); - windowwidth = 64; - nlasttracklen = windowwidth+hqrnduniformi(&rs, 10, _state); - ssacreate(&state, _state); - ae_vector_set_length(&x, nlasttracklen, _state); - for(k=0; k<=ntracks-1; k++) - { - sineoffs = (double)(hqrnduniformi(&rs, windowwidth, _state)); - if( k%2==0 ) - { - sineamp = 1+hqrnduniformr(&rs, _state); - sinefreq = (double)(1); - } - else - { - sineamp = 0.1*(1+hqrnduniformr(&rs, _state)); - sinefreq = (double)(2); - } - for(i=0; i<=nlasttracklen-1; i++) - { - x.ptr.p_double[i] = sineamp*ae_sin((i+sineoffs)/windowwidth*2*ae_pi*sinefreq, _state); - } - ssaaddsequence(&state, &x, nlasttracklen, _state); - } - if( algotype==2 ) - { - ssasetalgotopkdirect(&state, 2, _state); - } - else - { - if( algotype==3 ) - { - ssasetalgotopkrealtime(&state, 2, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - tol = 1.0E-6; - - /* - * Test analysis with WindowWidth=SinePeriod: - * * analyze sine with frequency=1, it must be recognized as trend - * * analyze sine with frequency=2, with smoothing enabled - * it must be discarded as noise; - */ - ssasetwindow(&state, windowwidth, _state); - nticks = windowwidth+1+hqrnduniformi(&rs, windowwidth, _state); - sineoffs = (double)(hqrnduniformi(&rs, windowwidth, _state)); - sineamp = 1+hqrnduniformr(&rs, _state); - sinefreq = (double)(1); - ae_vector_set_length(&x, nticks, _state); - for(i=0; i<=nticks-1; i++) - { - x.ptr.p_double[i] = sineamp*ae_sin((i+sineoffs)/windowwidth*2*ae_pi*sinefreq, _state); - } - ssaanalyzesequence(&state, &x, nticks, &trend, &noise, _state); - ae_set_error_flag(errorflag, noise.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:558"); - ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:559"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=nticks-1; i++) - { - v = sineamp*ae_sin((i+sineoffs)/windowwidth*2*ae_pi*sinefreq, _state); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:565"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:566"); - } - forecastlen = 1+hqrnduniformi(&rs, nticks-windowwidth, _state); - datalen = nticks-forecastlen; - ae_vector_set_length(&x2, datalen, _state); - for(i=0; i<=datalen-1; i++) - { - x2.ptr.p_double[i] = x.ptr.p_double[i]; - } - ssaforecastsequence(&state, &x2, datalen, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state); - for(i=0; i<=forecastlen-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[datalen+i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:575"); - } - ae_vector_set_length(&tmp0, 0, _state); - windowwidth2 = -1; - ssagetlrr(&state, &tmp0, &windowwidth2, _state); - ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:579"); - ae_set_error_flag(errorflag, tmp0.cnt!=windowwidth-1, __FILE__, __LINE__, "testssaunit.ap:580"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=windowwidth-1; i<=nticks-1; i++) - { - v = ae_v_dotproduct(&x.ptr.p_double[i-(windowwidth-1)], 1, &tmp0.ptr.p_double[0], 1, ae_v_len(i-(windowwidth-1),i-1)); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v-x.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:586"); - } - nticks = windowwidth+1+hqrnduniformi(&rs, windowwidth, _state); - sineoffs = (double)(hqrnduniformi(&rs, windowwidth, _state)); - sineamp = 1+hqrnduniformr(&rs, _state); - sinefreq = (double)(2); - ae_vector_set_length(&x, nticks, _state); - for(i=0; i<=nticks-1; i++) - { - x.ptr.p_double[i] = sineamp*ae_sin((i+sineoffs)/windowwidth*2*ae_pi*sinefreq, _state); - } - ssaanalyzesequence(&state, &x, nticks, &trend, &noise, _state); - ae_set_error_flag(errorflag, noise.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:597"); - ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:598"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=nticks-1; i++) - { - v = sineamp*ae_sin((i+sineoffs)/windowwidth*2*ae_pi*sinefreq, _state); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:604"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:605"); - } - forecastlen = 1+hqrnduniformi(&rs, nticks-windowwidth, _state); - datalen = nticks-forecastlen; - ae_vector_set_length(&x2, datalen, _state); - for(i=0; i<=datalen-1; i++) - { - x2.ptr.p_double[i] = x.ptr.p_double[i]; - } - ssaforecastsequence(&state, &x2, datalen, forecastlen, ae_true, &trend, _state); - for(i=0; i<=forecastlen-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:614"); - } - } - - /* - * Test appendPoint() functionality. - * - * We have specially designed dataset: - * * NZeros ticks of exactly zero values - * * NLinear ticks of series which linearly grow from 0 to 1 - * * NLinear ticks of series which linearly decrease from 1 to 0 - * * NZeros ticks of exactly zero values - * * NZeros=100 - * * NLinear=20 - * - * SSA settings have following values: - * * WindowWidth=4 or 25 (large widths are more problematic for - * iterative solvers, so they help to debug incremental updates) - * * NBasis=2 - * - * We choose number of initial values to start with NInitial - * in [1..2*WindowWidth], then add points one - * by one with SSAAppendPointAndUpdate(). In the end we compare - * results returned by SSAGetBasis() with that returned by model - * which was created from full dataset. - * - * NOTE: we perform limited amount of passes because this test - * has high cost. - */ - for(pass=1; pass<=25; pass++) - { - - /* - * Generate dataset - */ - tol = 1.0E-6; - nzeros = 100; - nlinear = 50; - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - windowwidth = 25; - } - else - { - windowwidth = 4; - } - nbasis = 2; - ninitial = 1+hqrnduniformi(&rs, 2*windowwidth, _state); - ae_vector_set_length(&x, 2*nzeros+2*nlinear, _state); - for(i=0; i<=x.cnt-1; i++) - { - x.ptr.p_double[i] = 0.0; - } - for(i=0; i<=nlinear-1; i++) - { - x.ptr.p_double[nzeros+i] = (double)i/(double)nlinear; - x.ptr.p_double[nzeros+nlinear+i] = 1-(double)i/(double)nlinear; - } - rmatrixrndorthogonal(windowwidth, &b, _state); - - /* - * Build model using many sequential appends - * - * NOTE: for NInitial>=WindowWidth with probability 50% - * we enforce basis calculation before first - * append() call. It helps to debug different - * branches of algorithms. - * - * NOTE: we may also request delayed power-up of the - * algorithm. It also checks various branches of - * the algo, although with such settings delayed - * power-up is hard to check (initial dataset is - * just zeros, zeros, zeros..). - */ - ae_vector_set_length(&x2, ninitial, _state); - for(i=0; i<=x2.cnt-1; i++) - { - x2.ptr.p_double[i] = x.ptr.p_double[i]; - } - ssacreate(&state, _state); - ssasetwindow(&state, windowwidth, _state); - ssaaddsequence(&state, &x2, x2.cnt, _state); - if( algotype==1 ) - { - ssasetalgoprecomputed(&state, &b, windowwidth, nbasis, _state); - } - else - { - if( algotype==2 ) - { - ssasetalgotopkdirect(&state, nbasis, _state); - } - else - { - if( algotype==3 ) - { - ssasetalgotopkrealtime(&state, nbasis, _state); - if( ae_fp_greater(hqrnduniformr(&rs, _state),0.5) ) - { - ssasetpoweruplength(&state, 10, _state); - } - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - if( ninitial>=windowwidth&&ae_fp_greater(hqrnduniformr(&rs, _state),0.5) ) - { - ae_matrix_set_length(&a, 0, 0, _state); - ae_vector_set_length(&sv, 0, _state); - windowwidth2 = -1; - nbasis2 = -1; - ssagetbasis(&state, &a, &sv, &windowwidth2, &nbasis2, _state); - ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:705"); - ae_set_error_flag(errorflag, nbasis2!=nbasis, __FILE__, __LINE__, "testssaunit.ap:706"); - ae_set_error_flag(errorflag, a.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:707"); - ae_set_error_flag(errorflag, a.cols!=nbasis, __FILE__, __LINE__, "testssaunit.ap:708"); - ae_set_error_flag(errorflag, sv.cnt!=nbasis, __FILE__, __LINE__, "testssaunit.ap:709"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - } - for(i=x2.cnt; i<=x.cnt-1; i++) - { - ssaappendpointandupdate(&state, x.ptr.p_double[i], 1.0, _state); - } - ae_matrix_set_length(&a, 0, 0, _state); - ae_vector_set_length(&sv, 0, _state); - windowwidth2 = -1; - nbasis2 = -1; - ssagetbasis(&state, &a, &sv, &windowwidth2, &nbasis2, _state); - ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:720"); - ae_set_error_flag(errorflag, nbasis2!=nbasis, __FILE__, __LINE__, "testssaunit.ap:721"); - ae_set_error_flag(errorflag, a.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:722"); - ae_set_error_flag(errorflag, a.cols!=nbasis, __FILE__, __LINE__, "testssaunit.ap:723"); - ae_set_error_flag(errorflag, sv.cnt!=nbasis, __FILE__, __LINE__, "testssaunit.ap:724"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - - /* - * Build model using one big sequence - */ - ssacreate(&state2, _state); - ssasetwindow(&state2, windowwidth, _state); - ssaaddsequence(&state2, &x, x.cnt, _state); - if( algotype==1 ) - { - ssasetalgoprecomputed(&state2, &b, windowwidth, nbasis, _state); - } - else - { - if( algotype==2 ) - { - ssasetalgotopkdirect(&state2, nbasis, _state); - } - else - { - if( algotype==3 ) - { - ssasetalgotopkrealtime(&state2, nbasis, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - ae_matrix_set_length(&a2, 0, 0, _state); - ae_vector_set_length(&sv2, 0, _state); - windowwidth2 = -1; - nbasis2 = -1; - ssagetbasis(&state2, &a2, &sv2, &windowwidth2, &nbasis2, _state); - ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:747"); - ae_set_error_flag(errorflag, nbasis2!=nbasis, __FILE__, __LINE__, "testssaunit.ap:748"); - ae_set_error_flag(errorflag, a2.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:749"); - ae_set_error_flag(errorflag, a2.cols!=nbasis, __FILE__, __LINE__, "testssaunit.ap:750"); - ae_set_error_flag(errorflag, sv2.cnt!=nbasis, __FILE__, __LINE__, "testssaunit.ap:751"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - - /* - * Compare results - */ - for(i=0; i<=nbasis-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(sv.ptr.p_double[i]-sv2.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:759"); - } - for(j=0; j<=nbasis-1; j++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[0][j], a.stride, &a2.ptr.pp_double[0][j], a2.stride, ae_v_len(0,windowwidth-1)); - for(i=0; i<=windowwidth-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-ae_sign(v, _state)*a2.ptr.pp_double[i][j], _state),tol), __FILE__, __LINE__, "testssaunit.ap:764"); - } - } - } - - /* - * Test appendSequence() functionality. - * - * We have specially designed dataset: - * * NNoise sequences of Gaussian noise - * * NLinear linear sequences partially corrupted by noise - * * NZeros exactly zero sequences (used to let incremental algo converge) - * * all sequences have random size in [WindowWidth-2,WindowWidth+2] - * * NNoise=20 - * * NLinear=20 - * - * SSA settings have following values: - * * WindowWidth=4 or 25 (large widths are more problematic for - * iterative solvers, so they help to debug incremental updates) - * * NBasis=2 - * - * We have two solvers: - * * one is trained on complete dataset - * * another one starts from NNoise noisy sequences, linear/zero sequenes - * are incrementally appended with AppendSequence - * - * NOTE: we perform limited amount of passes because this test - * has high cost. - */ - for(pass=1; pass<=25; pass++) - { - - /* - * Problem metrics - */ - tol = 1.0E-5; - nnoise = 20; - nlinear = 20; - nzeros = 50; - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - windowwidth = 25; - } - else - { - windowwidth = 4; - } - nbasis = 2; - - /* - * Initialize solvers - * - * NOTE: we set State.DefaultSubspaceIts to large value in order - * to ensure convergence to same basis. - */ - rmatrixrndorthogonal(windowwidth, &b, _state); - ssacreate(&state, _state); - ssacreate(&state2, _state); - state.defaultsubspaceits = 50; - ssasetwindow(&state, windowwidth, _state); - ssasetwindow(&state2, windowwidth, _state); - if( algotype==1 ) - { - ssasetalgoprecomputed(&state, &b, windowwidth, nbasis, _state); - ssasetalgoprecomputed(&state2, &b, windowwidth, nbasis, _state); - } - else - { - if( algotype==2 ) - { - ssasetalgotopkdirect(&state, nbasis, _state); - ssasetalgotopkdirect(&state2, nbasis, _state); - } - else - { - if( algotype==3 ) - { - ssasetalgotopkrealtime(&state, nbasis, _state); - ssasetalgotopkrealtime(&state2, nbasis, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - - /* - * Feed noisy sequences - */ - for(i=0; i<=nnoise-1; i++) - { - k = windowwidth+(hqrnduniformi(&rs, 5, _state)-2); - ae_vector_set_length(&x, k, _state); - for(j=0; j<=k-1; j++) - { - x.ptr.p_double[j] = hqrndnormal(&rs, _state); - } - ssaaddsequence(&state, &x, x.cnt, _state); - ssaaddsequence(&state2, &x, x.cnt, _state); - } - - /* - * Feed linear and zero sequences. - * - * NOTE: with probability 50% we call SSAGetBasis(State2). - * Ideally, SSA should be able to handle appends correctly - * with or without preceeding call which requires basis - * to be evaluated. - */ - if( ae_fp_greater(hqrnduniformr(&rs, _state),0.5) ) - { - ae_matrix_set_length(&a2, 0, 0, _state); - ae_vector_set_length(&sv2, 0, _state); - windowwidth2 = -1; - nbasis2 = -1; - ssagetbasis(&state2, &a2, &sv2, &windowwidth2, &nbasis2, _state); - ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:865"); - ae_set_error_flag(errorflag, nbasis2!=nbasis, __FILE__, __LINE__, "testssaunit.ap:866"); - ae_set_error_flag(errorflag, a2.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:867"); - ae_set_error_flag(errorflag, a2.cols!=nbasis, __FILE__, __LINE__, "testssaunit.ap:868"); - ae_set_error_flag(errorflag, sv2.cnt!=nbasis, __FILE__, __LINE__, "testssaunit.ap:869"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - } - for(i=0; i<=nlinear-1; i++) - { - k = windowwidth+(hqrnduniformi(&rs, 5, _state)-2); - v = hqrndnormal(&rs, _state); - vv = hqrndnormal(&rs, _state); - ae_vector_set_length(&x, k, _state); - x.ptr.p_double[0] = v; - for(j=1; j<=k-1; j++) - { - x.ptr.p_double[j] = x.ptr.p_double[j-1]+vv+0.1*hqrndnormal(&rs, _state); - } - ssaaddsequence(&state, &x, x.cnt, _state); - ssaappendsequenceandupdate(&state2, &x, x.cnt, 1.0, _state); - } - for(i=0; i<=nzeros-1; i++) - { - k = windowwidth+(hqrnduniformi(&rs, 5, _state)-2); - ae_vector_set_length(&x, k, _state); - for(j=0; j<=k-1; j++) - { - x.ptr.p_double[j] = (double)(0); - } - ssaaddsequence(&state, &x, x.cnt, _state); - ssaappendsequenceandupdate(&state2, &x, x.cnt, 1.0, _state); - } - - /* - * Compare results - */ - ae_matrix_set_length(&a, 0, 0, _state); - ae_vector_set_length(&sv, 0, _state); - windowwidth2 = -1; - nbasis2 = -1; - ssagetbasis(&state, &a, &sv, &windowwidth2, &nbasis2, _state); - ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:903"); - ae_set_error_flag(errorflag, nbasis2!=nbasis, __FILE__, __LINE__, "testssaunit.ap:904"); - ae_set_error_flag(errorflag, a.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:905"); - ae_set_error_flag(errorflag, a.cols!=nbasis, __FILE__, __LINE__, "testssaunit.ap:906"); - ae_set_error_flag(errorflag, sv.cnt!=nbasis, __FILE__, __LINE__, "testssaunit.ap:907"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - ae_matrix_set_length(&a2, 0, 0, _state); - ae_vector_set_length(&sv2, 0, _state); - windowwidth2 = -1; - nbasis2 = -1; - ssagetbasis(&state2, &a2, &sv2, &windowwidth2, &nbasis2, _state); - ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:915"); - ae_set_error_flag(errorflag, nbasis2!=nbasis, __FILE__, __LINE__, "testssaunit.ap:916"); - ae_set_error_flag(errorflag, a2.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:917"); - ae_set_error_flag(errorflag, a2.cols!=nbasis, __FILE__, __LINE__, "testssaunit.ap:918"); - ae_set_error_flag(errorflag, sv2.cnt!=nbasis, __FILE__, __LINE__, "testssaunit.ap:919"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=nbasis-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(sv.ptr.p_double[i]-sv2.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:923"); - } - for(j=0; j<=nbasis-1; j++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[0][j], a.stride, &a2.ptr.pp_double[0][j], a2.stride, ae_v_len(0,windowwidth-1)); - for(i=0; i<=windowwidth-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-ae_sign(v, _state)*a2.ptr.pp_double[i][j], _state),tol), __FILE__, __LINE__, "testssaunit.ap:928"); - } - } - } - - /* - * Test memory limit functionality. - * - * Compare results obtained with HUGE limit vs ones obtained with small limit. - */ - for(windowwidth=1; windowwidth<=20; windowwidth++) - { - for(mlimit=-1; mlimit<=16; mlimit++) - { - - /* - * Not tested - */ - if( algotype==1 ) - { - continue; - } - - /* - * Problem metrics - */ - tol = 1.0E-5; - nticks = 1000+hqrnduniformi(&rs, 1000, _state); - if( windowwidth>5 ) - { - nbasis = 1+hqrnduniformi(&rs, 5, _state); - } - else - { - nbasis = 1; - } - - /* - * Create solvers, dataset, set limits - */ - ssacreate(&state, _state); - ssacreate(&state2, _state); - if( mlimit>=0 ) - { - ssasetmemorylimit(&state, ae_round(ae_pow((double)(2), (double)(mlimit), _state), _state), _state); - } - else - { - ssasetmemorylimit(&state, 0, _state); - } - ssasetmemorylimit(&state2, 999999999, _state); - ssasetwindow(&state, windowwidth, _state); - ssasetwindow(&state2, windowwidth, _state); - if( algotype==2 ) - { - ssasetalgotopkdirect(&state, nbasis, _state); - ssasetalgotopkdirect(&state2, nbasis, _state); - } - else - { - if( algotype==3 ) - { - ssasetalgotopkrealtime(&state, nbasis, _state); - ssasetalgotopkrealtime(&state2, nbasis, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - ae_vector_set_length(&x, nticks, _state); - for(i=0; i<=nticks-1; i++) - { - x.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ssaaddsequence(&state, &x, x.cnt, _state); - ssaaddsequence(&state2, &x, x.cnt, _state); - - /* - * Reset internal temporaries for this test. - * Implementation-dependent, may fail due to future changes in the core. - */ - ae_matrix_set_length(&state.uxbatch, 0, 0, _state); - ae_matrix_set_length(&state.aseqtrajectory, 0, 0, _state); - ae_matrix_set_length(&state.aseqtbproduct, 0, 0, _state); - - /* - * Test - */ - ssaanalyzelast(&state, nticks, &trend, &noise, _state); - ssaanalyzelast(&state2, nticks, &trend2, &noise2, _state); - for(i=0; i<=nticks-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-trend2.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:1001"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i]-noise2.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:1002"); - } - - /* - * Additional tests for sizes of internal arrays. - * Implementation-dependent, may fail due to future changes in the core. - */ - if( mlimit>=0 ) - { - k = ae_maxint(4*windowwidth*windowwidth, ae_round(ae_pow((double)(2), (double)(mlimit), _state), _state), _state); - ae_set_error_flag(errorflag, state.uxbatch.cols*state.uxbatch.rows>k, __FILE__, __LINE__, "testssaunit.ap:1012"); - ae_set_error_flag(errorflag, state.aseqtrajectory.cols*state.aseqtrajectory.rows>k, __FILE__, __LINE__, "testssaunit.ap:1013"); - ae_set_error_flag(errorflag, state.aseqtbproduct.cols*state.aseqtbproduct.rows>k, __FILE__, __LINE__, "testssaunit.ap:1014"); - } - else - { - ae_set_error_flag(errorflag, state.uxbatch.rows!=nticks-windowwidth+1, __FILE__, __LINE__, "testssaunit.ap:1018"); - ae_set_error_flag(errorflag, state.aseqtrajectory.rows!=nticks-windowwidth+1, __FILE__, __LINE__, "testssaunit.ap:1019"); - ae_set_error_flag(errorflag, state.aseqtbproduct.rows!=nticks-windowwidth+1, __FILE__, __LINE__, "testssaunit.ap:1020"); - } - } - } - } - - /* - * Test power-up ability of the real-time algorithm. - * - * We have specially designed dataset: - * * NTicks ticks of linearly descending from 1 to 0 linear trend, - * corrupted by random Gaussian noise - * * NZeros ticks of exactly zero values - * * NTicks=100 - * * NZeros=100 - * - * SSA settings have following values: - * * WindowWidth=4 or 25 (large widths are more problematic for - * iterative solvers, so they help to debug incremental updates) - * * NBasis=1..2 (only top vectors converge stable enough for unit testing) - * * powerup length is 10 - * - * We perform two SSAs: - * * one with full dataset and no powerup - * * one with powerup, NTicks+WindowWidth first elements, followed by appending of NZeros zeros - * - * We check that: - * * basis found by second model (right after initialization) is different - * from basis of the first one - * * basis found by second model after last append is same as the first one - * - * NOTE: we perform limited amount of passes because this test - * has high cost. - */ - for(pass=1; pass<=25; pass++) - { - - /* - * Generate dataset - */ - tol = 1.0E-3; - nticks = 100; - nzeros = 50; - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - windowwidth = 25; - } - else - { - windowwidth = 4; - } - nbasis = 1+hqrnduniformi(&rs, 2, _state); - ae_vector_set_length(&x, nticks+nzeros, _state); - for(i=0; i<=x.cnt-1; i++) - { - x.ptr.p_double[i] = 0.0; - } - for(i=0; i<=nticks-1; i++) - { - x.ptr.p_double[i] = 1-(double)i/(double)nticks+0.05*hqrndnormal(&rs, _state); - } - - /* - * Build complete model - * - * NOTE: we tweak S.DefaultSubspaceIts in order to enforce convergence to - * same basis; for this test we need extra-precise convergence. - */ - ssacreate(&state2, _state); - ssasetwindow(&state2, windowwidth, _state); - ssaaddsequence(&state2, &x, x.cnt, _state); - ssasetalgotopkrealtime(&state2, nbasis, _state); - ae_matrix_set_length(&a2, 0, 0, _state); - ae_vector_set_length(&sv2, 0, _state); - windowwidth2 = -1; - nbasis2 = -1; - ssagetbasis(&state2, &a2, &sv2, &windowwidth2, &nbasis2, _state); - ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1088"); - ae_set_error_flag(errorflag, nbasis2!=nbasis, __FILE__, __LINE__, "testssaunit.ap:1089"); - ae_set_error_flag(errorflag, a2.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1090"); - ae_set_error_flag(errorflag, a2.cols!=nbasis, __FILE__, __LINE__, "testssaunit.ap:1091"); - ae_set_error_flag(errorflag, sv2.cnt!=nbasis, __FILE__, __LINE__, "testssaunit.ap:1092"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - - /* - * Build model with power-up cycle - * - * NOTE: with probability 50% we enforce basis calculation - * before first append() call and compare basis with - * one returned by full analysis. We do it only in 50% - * of the cases because randomness helps to debug different - * branches of algorithms. - */ - ae_vector_set_length(&x2, nticks+windowwidth, _state); - for(i=0; i<=x2.cnt-1; i++) - { - x2.ptr.p_double[i] = x.ptr.p_double[i]; - } - ssacreate(&state, _state); - ssasetwindow(&state, windowwidth, _state); - ssaaddsequence(&state, &x2, x2.cnt, _state); - ssasetalgotopkrealtime(&state, nbasis, _state); - ssasetpoweruplength(&state, 10, _state); - if( ae_fp_greater(hqrnduniformr(&rs, _state),0.5) ) - { - ae_matrix_set_length(&a, 0, 0, _state); - ae_vector_set_length(&sv, 0, _state); - windowwidth2 = -1; - nbasis2 = -1; - ssagetbasis(&state, &a, &sv, &windowwidth2, &nbasis2, _state); - ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1120"); - ae_set_error_flag(errorflag, nbasis2!=nbasis, __FILE__, __LINE__, "testssaunit.ap:1121"); - ae_set_error_flag(errorflag, a.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1122"); - ae_set_error_flag(errorflag, a.cols!=nbasis, __FILE__, __LINE__, "testssaunit.ap:1123"); - ae_set_error_flag(errorflag, sv.cnt!=nbasis, __FILE__, __LINE__, "testssaunit.ap:1124"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - vv = 0.0; - for(i=0; i<=nbasis-1; i++) - { - vv = ae_maxreal(vv, ae_fabs(sv.ptr.p_double[i]-sv2.ptr.p_double[i], _state), _state); - } - for(j=0; j<=nbasis-1; j++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[0][j], a.stride, &a2.ptr.pp_double[0][j], a2.stride, ae_v_len(0,windowwidth-1)); - for(i=0; i<=windowwidth-1; i++) - { - vv = ae_maxreal(vv, ae_fabs(a.ptr.pp_double[i][j]-ae_sign(v, _state)*a2.ptr.pp_double[i][j], _state), _state); - } - } - ae_set_error_flag(errorflag, ae_fp_less(ae_fabs(vv, _state),tol), __FILE__, __LINE__, "testssaunit.ap:1136"); - } - for(i=x2.cnt; i<=x.cnt-1; i++) - { - ssaappendpointandupdate(&state, x.ptr.p_double[i], 1.0, _state); - } - ae_matrix_set_length(&a, 0, 0, _state); - ae_vector_set_length(&sv, 0, _state); - windowwidth2 = -1; - nbasis2 = -1; - ssagetbasis(&state, &a, &sv, &windowwidth2, &nbasis2, _state); - ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1145"); - ae_set_error_flag(errorflag, nbasis2!=nbasis, __FILE__, __LINE__, "testssaunit.ap:1146"); - ae_set_error_flag(errorflag, a.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1147"); - ae_set_error_flag(errorflag, a.cols!=nbasis, __FILE__, __LINE__, "testssaunit.ap:1148"); - ae_set_error_flag(errorflag, sv.cnt!=nbasis, __FILE__, __LINE__, "testssaunit.ap:1149"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - vv = 0.0; - for(i=0; i<=nbasis-1; i++) - { - vv = ae_maxreal(vv, ae_fabs(sv.ptr.p_double[i]-sv2.ptr.p_double[i], _state), _state); - } - for(j=0; j<=nbasis-1; j++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[0][j], a.stride, &a2.ptr.pp_double[0][j], a2.stride, ae_v_len(0,windowwidth-1)); - for(i=0; i<=windowwidth-1; i++) - { - vv = ae_maxreal(vv, ae_fabs(a.ptr.pp_double[i][j]-ae_sign(v, _state)*a2.ptr.pp_double[i][j], _state), _state); - } - } - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(vv, _state),tol), __FILE__, __LINE__, "testssaunit.ap:1161"); - } - - /* - * Test that SSAForecastAvgLast/Sequence() actually performs averaging. - * We test it by comparing its results vs manually averaged predictions. - * - * Dataset is a small linear trend + Gaussian noise. We are not interested - * in getting meaningful components, we just want to check correctness of math. - */ - for(pass=1; pass<=100; pass++) - { - nticks = 75+hqrnduniformi(&rs, 75, _state); - windowwidth = 5+hqrnduniformi(&rs, 5, _state); - navg = 1+hqrnduniformi(&rs, 2*windowwidth, _state); - forecastlen = 1+hqrnduniformi(&rs, 2*windowwidth, _state); - ssacreate(&state, _state); - ssasetwindow(&state, windowwidth, _state); - ae_vector_set_length(&x, nticks, _state); - for(i=0; i<=nticks-1; i++) - { - x.ptr.p_double[i] = 0.1*i+hqrndnormal(&rs, _state); - } - ssaaddsequence(&state, &x, nticks, _state); - ssasetalgotopkdirect(&state, 1+hqrnduniformi(&rs, 3, _state), _state); - tol = 1.0E-9; - ssaforecastavglast(&state, navg, forecastlen, &trend, _state); - ae_vector_set_length(&trend2, forecastlen, _state); - for(i=0; i<=forecastlen-1; i++) - { - trend2.ptr.p_double[i] = 0.0; - } - for(i=0; i<=navg-1; i++) - { - ssaforecastsequence(&state, &x, nticks-i, forecastlen+i, ae_true, &tmp0, _state); - for(j=0; j<=forecastlen-1; j++) - { - trend2.ptr.p_double[j] = trend2.ptr.p_double[j]+tmp0.ptr.p_double[i+j]/navg; - } - } - for(i=0; i<=forecastlen-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-trend2.ptr.p_double[i], _state),tol*maxreal3(ae_fabs(trend.ptr.p_double[i], _state), ae_fabs(trend2.ptr.p_double[i], _state), 1.0, _state)), __FILE__, __LINE__, "testssaunit.ap:1198"); - } - nticks = 75+hqrnduniformi(&rs, 75, _state); - j = hqrnduniformi(&rs, 150, _state)-75; - ae_vector_set_length(&x2, nticks, _state); - for(i=0; i<=nticks-1; i++) - { - x2.ptr.p_double[i] = 0.1*(i+j)+hqrndnormal(&rs, _state); - } - ssaforecastavgsequence(&state, &x2, nticks, navg, forecastlen, ae_true, &trend, _state); - ae_vector_set_length(&trend2, forecastlen, _state); - for(i=0; i<=forecastlen-1; i++) - { - trend2.ptr.p_double[i] = 0.0; - } - for(i=0; i<=navg-1; i++) - { - ssaforecastsequence(&state, &x2, nticks-i, forecastlen+i, ae_true, &tmp0, _state); - for(j=0; j<=forecastlen-1; j++) - { - trend2.ptr.p_double[j] = trend2.ptr.p_double[j]+tmp0.ptr.p_double[i+j]/navg; - } - } - for(i=0; i<=forecastlen-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-trend2.ptr.p_double[i], _state),tol*maxreal3(ae_fabs(trend.ptr.p_double[i], _state), ae_fabs(trend2.ptr.p_double[i], _state), 1.0, _state)), __FILE__, __LINE__, "testssaunit.ap:1217"); - } - nticks = 75+hqrnduniformi(&rs, 75, _state); - j = hqrnduniformi(&rs, 150, _state)-75; - ae_vector_set_length(&x2, nticks, _state); - for(i=0; i<=nticks-1; i++) - { - x2.ptr.p_double[i] = 0.1*(i+j)+hqrndnormal(&rs, _state); - } - ssaforecastavgsequence(&state, &x2, nticks, navg, forecastlen, ae_false, &trend, _state); - ae_vector_set_length(&trend2, forecastlen, _state); - for(i=0; i<=forecastlen-1; i++) - { - trend2.ptr.p_double[i] = 0.0; - } - for(i=0; i<=navg-1; i++) - { - ssaforecastsequence(&state, &x2, nticks-i, forecastlen+i, ae_false, &tmp0, _state); - for(j=0; j<=forecastlen-1; j++) - { - trend2.ptr.p_double[j] = trend2.ptr.p_double[j]+tmp0.ptr.p_double[i+j]/navg; - } - } - for(i=0; i<=forecastlen-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-trend2.ptr.p_double[i], _state),tol*maxreal3(ae_fabs(trend.ptr.p_double[i], _state), ae_fabs(trend2.ptr.p_double[i], _state), 1.0, _state)), __FILE__, __LINE__, "testssaunit.ap:1236"); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests different special cases (mostly - degenerate ones). - -On failure sets ErrorFlag, on success it is untouched. -*************************************************************************/ -static void testssaunit_testspecial(ae_bool* errorflag, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - ae_int_t pass; - ssamodel state; - ssamodel state2; - ae_matrix a; - ae_matrix b; - ae_vector x; - ae_vector x2; - ae_vector sv; - ae_vector trend; - ae_vector noise; - ae_vector trend2; - ae_vector noise2; - ae_int_t algotype; - ae_int_t nticks; - ae_int_t nanalyzed; - ae_int_t nlasttracklen; - ae_int_t ntracks; - ae_int_t maxtracklen; - ae_int_t mintracklen; - ae_int_t datalen; - ae_int_t forecastlen; - ae_int_t windowwidth; - ae_int_t nbasis; - ae_int_t windowwidth2; - ae_matrix tracksmatrix; - ae_vector trackssizes; - hqrndstate rs; - ae_int_t passcount; - double skipprob; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&state2, 0, sizeof(state2)); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - memset(&x, 0, sizeof(x)); - memset(&x2, 0, sizeof(x2)); - memset(&sv, 0, sizeof(sv)); - memset(&trend, 0, sizeof(trend)); - memset(&noise, 0, sizeof(noise)); - memset(&trend2, 0, sizeof(trend2)); - memset(&noise2, 0, sizeof(noise2)); - memset(&tracksmatrix, 0, sizeof(tracksmatrix)); - memset(&trackssizes, 0, sizeof(trackssizes)); - memset(&rs, 0, sizeof(rs)); - _ssamodel_init(&state, _state, ae_true); - _ssamodel_init(&state2, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sv, 0, DT_REAL, _state, ae_true); - ae_vector_init(&trend, 0, DT_REAL, _state, ae_true); - ae_vector_init(&noise, 0, DT_REAL, _state, ae_true); - ae_vector_init(&trend2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&noise2, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&tracksmatrix, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&trackssizes, 0, DT_INT, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - - /* - * Initialize RNG, test pass count and skip probability. - * - * When we perform several sequential tests on the same model, we may - * skip some of them with probability SkipProb in order to make sure - * that no carry-over effect is observed between tests. - */ - hqrndrandomize(&rs, _state); - passcount = 500; - skipprob = 0.50; - - /* - * Test that for empty model in default state: - * * SSAGetBasis() returns zero 1x1 basis - * * SSAAnalyzeLastWindow() returns zeros as trend/noise - * * SSAAnalyzeLast() returns zeros as trend/noise - * * SSAAnalyzeSequence() returns zeros as trend, sequence as noise - * * SSAForecastLast() returns zero trend - * * SSAForecastSequence() returns zero trend - */ - for(pass=1; pass<=passcount; pass++) - { - ssacreate(&state, _state); - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - ssagetbasis(&state, &a, &sv, &windowwidth, &nbasis, _state); - ae_set_error_flag(errorflag, windowwidth!=1, __FILE__, __LINE__, "testssaunit.ap:1299"); - ae_set_error_flag(errorflag, nbasis!=1, __FILE__, __LINE__, "testssaunit.ap:1300"); - ae_set_error_flag(errorflag, a.rows!=1, __FILE__, __LINE__, "testssaunit.ap:1301"); - ae_set_error_flag(errorflag, a.cols!=1, __FILE__, __LINE__, "testssaunit.ap:1302"); - ae_set_error_flag(errorflag, sv.cnt!=1, __FILE__, __LINE__, "testssaunit.ap:1303"); - for(i=0; i<=a.rows-1; i++) - { - for(j=0; j<=a.cols-1; j++) - { - ae_set_error_flag(errorflag, ae_fp_neq(a.ptr.pp_double[i][j],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1306"); - } - } - for(i=0; i<=sv.cnt-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(sv.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1308"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - windowwidth = -1; - ae_vector_set_length(&trend, 0, _state); - ae_vector_set_length(&noise, 0, _state); - ssaanalyzelastwindow(&state, &trend, &noise, &windowwidth, _state); - ae_set_error_flag(errorflag, windowwidth!=1, __FILE__, __LINE__, "testssaunit.ap:1316"); - ae_set_error_flag(errorflag, trend.cnt!=1||ae_fp_neq(trend.ptr.p_double[0],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1317"); - ae_set_error_flag(errorflag, noise.cnt!=1||ae_fp_neq(noise.ptr.p_double[0],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1318"); - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nticks = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&trend, 0, _state); - ae_vector_set_length(&noise, 0, _state); - ssaanalyzelast(&state, nticks, &trend, &noise, _state); - ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1326"); - ae_set_error_flag(errorflag, noise.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1327"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=nticks-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1332"); - ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1333"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nticks = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&x, nticks, _state); - for(i=0; i<=nticks-1; i++) - { - x.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&trend, 0, _state); - ae_vector_set_length(&noise, 0, _state); - ssaanalyzesequence(&state, &x, nticks, &trend, &noise, _state); - ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1345"); - ae_set_error_flag(errorflag, noise.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1346"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=nticks-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1351"); - ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],x.ptr.p_double[i]), __FILE__, __LINE__, "testssaunit.ap:1352"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nticks = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&trend, 0, _state); - ssaforecastlast(&state, nticks, &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1360"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=nticks-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1364"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - datalen = 1+hqrnduniformi(&rs, 10, _state); - forecastlen = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&x, datalen, _state); - for(i=0; i<=datalen-1; i++) - { - x.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&trend, 0, _state); - ssaforecastsequence(&state, &x, datalen, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=forecastlen, __FILE__, __LINE__, "testssaunit.ap:1375"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=forecastlen-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1379"); - } - } - } - - /* - * Test that for empty model with non-default window, but default - * algorithm and no data: - * * SSAGetBasis() returns zero WINDOWx1 basis - * * SSAAnalyzeLastWindow() returns zeros as trend/noise - * * SSAAnalyzeLast() returns zeros as trend/noise - * * SSAAnalyzeSequence() returns zeros as trend, sequence as noise - * * SSAForecastLast() returns zero trend - * * SSAForecastSequence() returns zero trend - */ - for(pass=1; pass<=passcount; pass++) - { - windowwidth2 = 1+hqrnduniformi(&rs, 10, _state); - ssacreate(&state, _state); - ssasetwindow(&state, windowwidth2, _state); - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - ssagetbasis(&state, &a, &sv, &windowwidth, &nbasis, _state); - ae_set_error_flag(errorflag, windowwidth!=windowwidth2, __FILE__, __LINE__, "testssaunit.ap:1401"); - ae_set_error_flag(errorflag, nbasis!=1, __FILE__, __LINE__, "testssaunit.ap:1402"); - ae_set_error_flag(errorflag, a.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1403"); - ae_set_error_flag(errorflag, a.cols!=1, __FILE__, __LINE__, "testssaunit.ap:1404"); - ae_set_error_flag(errorflag, sv.cnt!=1, __FILE__, __LINE__, "testssaunit.ap:1405"); - for(i=0; i<=a.rows-1; i++) - { - for(j=0; j<=a.cols-1; j++) - { - ae_set_error_flag(errorflag, ae_fp_neq(a.ptr.pp_double[i][j],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1408"); - } - } - for(i=0; i<=sv.cnt-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(sv.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1410"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - windowwidth = -1; - ae_vector_set_length(&trend, 0, _state); - ae_vector_set_length(&noise, 0, _state); - ssaanalyzelastwindow(&state, &trend, &noise, &windowwidth, _state); - ae_set_error_flag(errorflag, windowwidth!=windowwidth2, __FILE__, __LINE__, "testssaunit.ap:1418"); - ae_set_error_flag(errorflag, trend.cnt!=windowwidth2, __FILE__, __LINE__, "testssaunit.ap:1419"); - ae_set_error_flag(errorflag, noise.cnt!=windowwidth2, __FILE__, __LINE__, "testssaunit.ap:1420"); - for(i=0; i<=trend.cnt-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1422"); - } - for(i=0; i<=noise.cnt-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1424"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nticks = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&trend, 0, _state); - ae_vector_set_length(&noise, 0, _state); - ssaanalyzelast(&state, nticks, &trend, &noise, _state); - ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1432"); - ae_set_error_flag(errorflag, noise.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1433"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=nticks-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1438"); - ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1439"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nticks = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&x, nticks, _state); - for(i=0; i<=nticks-1; i++) - { - x.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&trend, 0, _state); - ae_vector_set_length(&noise, 0, _state); - ssaanalyzesequence(&state, &x, nticks, &trend, &noise, _state); - ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1451"); - ae_set_error_flag(errorflag, noise.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1452"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=nticks-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1457"); - ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],x.ptr.p_double[i]), __FILE__, __LINE__, "testssaunit.ap:1458"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nticks = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&trend, 0, _state); - ssaforecastlast(&state, nticks, &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1466"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=nticks-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1470"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - datalen = 1+hqrnduniformi(&rs, 10, _state); - forecastlen = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&x, datalen, _state); - for(i=0; i<=datalen-1; i++) - { - x.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&trend, 0, _state); - ssaforecastsequence(&state, &x, datalen, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=forecastlen, __FILE__, __LINE__, "testssaunit.ap:1481"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=forecastlen-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1485"); - } - } - } - - /* - * Test that for empty model with default algorithm and one/few tracks - * (which are sometimes shorter than window, sometimes longer than window) - * * SSAGetBasis() returns zero WINDOWx1 basis - * * SSAAnalyzeLastWindow() returns zeros as trend and correctly aligned - * cropped/padded copy of X in the noise - * * SSAAnalyzeLast() returns zeros as trend and correctly aligned - * cropped/padded copy of X in the noise - * * SSAAnalyzeSequence() returns zeros as trend, sequence as noise - * * SSAForecastLast() returns zero trend - * * SSAForecastSequence() returns zero trend - */ - for(pass=1; pass<=passcount; pass++) - { - - /* - * Generate task; last track is stored in X, its length in NLastTrackLen - */ - nlasttracklen = -999999; - windowwidth2 = 1+hqrnduniformi(&rs, 10, _state); - ntracks = 1+hqrnduniformi(&rs, 3, _state); - ssacreate(&state, _state); - ssasetwindow(&state, windowwidth2, _state); - ae_matrix_set_length(&tracksmatrix, ntracks, 2*windowwidth2, _state); - ae_vector_set_length(&trackssizes, ntracks, _state); - for(k=0; k<=ntracks-1; k++) - { - nlasttracklen = hqrnduniformi(&rs, 2*windowwidth2, _state); - ae_vector_set_length(&x, nlasttracklen, _state); - for(i=0; i<=nlasttracklen-1; i++) - { - x.ptr.p_double[i] = hqrndnormal(&rs, _state); - tracksmatrix.ptr.pp_double[k][i] = x.ptr.p_double[i]; - } - trackssizes.ptr.p_int[k] = nlasttracklen; - ssaaddsequence(&state, &x, nlasttracklen, _state); - } - - /* - * Test - */ - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - ssagetbasis(&state, &a, &sv, &windowwidth, &nbasis, _state); - ae_set_error_flag(errorflag, windowwidth!=windowwidth2, __FILE__, __LINE__, "testssaunit.ap:1532"); - ae_set_error_flag(errorflag, nbasis!=1, __FILE__, __LINE__, "testssaunit.ap:1533"); - ae_set_error_flag(errorflag, a.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1534"); - ae_set_error_flag(errorflag, a.cols!=1, __FILE__, __LINE__, "testssaunit.ap:1535"); - ae_set_error_flag(errorflag, sv.cnt!=1, __FILE__, __LINE__, "testssaunit.ap:1536"); - for(i=0; i<=a.rows-1; i++) - { - for(j=0; j<=a.cols-1; j++) - { - ae_set_error_flag(errorflag, ae_fp_neq(a.ptr.pp_double[i][j],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1539"); - } - } - for(i=0; i<=sv.cnt-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(sv.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1541"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - windowwidth = -1; - ae_vector_set_length(&trend, 0, _state); - ae_vector_set_length(&noise, 0, _state); - ssaanalyzelastwindow(&state, &trend, &noise, &windowwidth, _state); - ae_set_error_flag(errorflag, windowwidth!=windowwidth2, __FILE__, __LINE__, "testssaunit.ap:1549"); - ae_set_error_flag(errorflag, trend.cnt!=windowwidth2, __FILE__, __LINE__, "testssaunit.ap:1550"); - ae_set_error_flag(errorflag, noise.cnt!=windowwidth2, __FILE__, __LINE__, "testssaunit.ap:1551"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=windowwidth-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1555"); - } - for(i=0; i<=ae_maxint(windowwidth-nlasttracklen, 0, _state)-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1557"); - } - for(i=ae_maxint(windowwidth-nlasttracklen, 0, _state); i<=windowwidth-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],x.ptr.p_double[nlasttracklen+(i-windowwidth)]), __FILE__, __LINE__, "testssaunit.ap:1559"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nanalyzed = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&trend, 0, _state); - ae_vector_set_length(&noise, 0, _state); - ssaanalyzelast(&state, nanalyzed, &trend, &noise, _state); - ae_set_error_flag(errorflag, trend.cnt!=nanalyzed, __FILE__, __LINE__, "testssaunit.ap:1567"); - ae_set_error_flag(errorflag, noise.cnt!=nanalyzed, __FILE__, __LINE__, "testssaunit.ap:1568"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=nanalyzed-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1572"); - } - for(i=0; i<=ae_maxint(nanalyzed-nlasttracklen, 0, _state)-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1574"); - } - for(i=ae_maxint(nanalyzed-nlasttracklen, 0, _state); i<=nanalyzed-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],x.ptr.p_double[nlasttracklen+(i-nanalyzed)]), __FILE__, __LINE__, "testssaunit.ap:1576"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nticks = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&x, nticks, _state); - for(i=0; i<=nticks-1; i++) - { - x.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&trend, 0, _state); - ae_vector_set_length(&noise, 0, _state); - ssaanalyzesequence(&state, &x, nticks, &trend, &noise, _state); - ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1587"); - ae_set_error_flag(errorflag, noise.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1588"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=nticks-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1593"); - ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],x.ptr.p_double[i]), __FILE__, __LINE__, "testssaunit.ap:1594"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nticks = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&trend, 0, _state); - ssaforecastlast(&state, nticks, &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1602"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=nticks-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1606"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - datalen = 1+hqrnduniformi(&rs, 10, _state); - forecastlen = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&x, datalen, _state); - for(i=0; i<=datalen-1; i++) - { - x.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&trend, 0, _state); - ssaforecastsequence(&state, &x, datalen, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=forecastlen, __FILE__, __LINE__, "testssaunit.ap:1617"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=forecastlen-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1621"); - } - } - } - - /* - * Tests below are performed for all algorithms supported. - */ - for(algotype=1; algotype<=3; algotype++) - { - - /* - * Test that SSAClearData() actually clears data - */ - for(pass=1; pass<=passcount; pass++) - { - if( algotype==1 ) - { - continue; - } - - /* - * Create two models, one is created after cleardata() call - * which should erase all traces of the previous dataset. - */ - ssacreate(&state, _state); - ssacreate(&state2, _state); - ssasetwindow(&state, 5, _state); - ssasetwindow(&state2, 5, _state); - if( algotype==2 ) - { - ssasetalgotopkdirect(&state, 2, _state); - ssasetalgotopkdirect(&state2, 2, _state); - } - else - { - if( algotype==3 ) - { - ssasetalgotopkrealtime(&state, 2, _state); - ssasetalgotopkrealtime(&state2, 2, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - ae_vector_set_length(&x, 10, _state); - for(i=0; i<=x.cnt-1; i++) - { - x.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ssaaddsequence(&state, &x, x.cnt, _state); - ssacleardata(&state, _state); - for(i=0; i<=x.cnt-1; i++) - { - x.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ssaaddsequence(&state, &x, x.cnt, _state); - ssaaddsequence(&state2, &x, x.cnt, _state); - - /* - * Test - */ - ssaanalyzelast(&state, x.cnt, &trend, &noise, _state); - ssaanalyzelast(&state2, x.cnt, &trend2, &noise2, _state); - for(i=0; i<=x.cnt-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-trend2.ptr.p_double[i], _state),1.0E-5), __FILE__, __LINE__, "testssaunit.ap:1675"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i]-noise2.ptr.p_double[i], _state),1.0E-5), __FILE__, __LINE__, "testssaunit.ap:1676"); - } - } - - /* - * Test that for model with some algo being set, one/few tracks and unit window length: - * * SSAGetBasis() returns 1x1 basis (unit matrix) - * * SSAAnalyzeLastWindow() returns last element of track as trend and zeros - * as noise (with minor rounding error) - * * SSAAnalyzeLast() returns tracks as trend and zeros as noise (with - * minor rounding error possible). For NTicks>TrackLength result is correctly - * prepended with zeros. - * * SSAAnalyzeSequence() returns sequence as trend, zeros as noise (up to - * machine precision) - * * SSAForecastLast() returns just copies of the last element - * * SSAForecastSequence() returns just copies of the last element - */ - for(pass=1; pass<=passcount; pass++) - { - - /* - * Generate task; last track is stored in X, its length in NLastTrackLen - */ - nlasttracklen = -999999; - maxtracklen = 10; - ntracks = 1+hqrnduniformi(&rs, 3, _state); - ssacreate(&state, _state); - ssasetwindow(&state, 1, _state); - ae_matrix_set_length(&tracksmatrix, ntracks, maxtracklen, _state); - ae_vector_set_length(&trackssizes, ntracks, _state); - for(k=0; k<=ntracks-1; k++) - { - nlasttracklen = 1+hqrnduniformi(&rs, maxtracklen, _state); - ae_vector_set_length(&x, nlasttracklen, _state); - for(i=0; i<=nlasttracklen-1; i++) - { - x.ptr.p_double[i] = hqrndnormal(&rs, _state); - tracksmatrix.ptr.pp_double[k][i] = x.ptr.p_double[i]; - } - trackssizes.ptr.p_int[k] = nlasttracklen; - ssaaddsequence(&state, &x, nlasttracklen, _state); - } - if( algotype==1 ) - { - ae_matrix_set_length(&b, 1, 1, _state); - b.ptr.pp_double[0][0] = (double)(2*hqrnduniformi(&rs, 2, _state)-1); - ssasetalgoprecomputed(&state, &b, 1, 1, _state); - } - else - { - if( algotype==2 ) - { - ssasetalgotopkdirect(&state, 1, _state); - } - else - { - if( algotype==3 ) - { - ssasetalgotopkrealtime(&state, 1, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - - /* - * Test - */ - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - ssagetbasis(&state, &a, &sv, &windowwidth, &nbasis, _state); - ae_set_error_flag(errorflag, windowwidth!=1, __FILE__, __LINE__, "testssaunit.ap:1736"); - ae_set_error_flag(errorflag, nbasis!=1, __FILE__, __LINE__, "testssaunit.ap:1737"); - ae_set_error_flag(errorflag, a.rows!=1, __FILE__, __LINE__, "testssaunit.ap:1738"); - ae_set_error_flag(errorflag, a.cols!=1, __FILE__, __LINE__, "testssaunit.ap:1739"); - ae_set_error_flag(errorflag, sv.cnt!=1, __FILE__, __LINE__, "testssaunit.ap:1740"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(ae_fabs(a.ptr.pp_double[0][0], _state)-1, _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1741"); - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - windowwidth = -1; - ae_vector_set_length(&trend, 0, _state); - ae_vector_set_length(&noise, 0, _state); - ssaanalyzelastwindow(&state, &trend, &noise, &windowwidth, _state); - ae_set_error_flag(errorflag, windowwidth!=1, __FILE__, __LINE__, "testssaunit.ap:1749"); - ae_set_error_flag(errorflag, trend.cnt!=1, __FILE__, __LINE__, "testssaunit.ap:1750"); - ae_set_error_flag(errorflag, noise.cnt!=1, __FILE__, __LINE__, "testssaunit.ap:1751"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[0]-x.ptr.p_double[nlasttracklen-1], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1754"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[0], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1755"); - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nanalyzed = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&trend, 0, _state); - ae_vector_set_length(&noise, 0, _state); - ssaanalyzelast(&state, nanalyzed, &trend, &noise, _state); - ae_set_error_flag(errorflag, trend.cnt!=nanalyzed, __FILE__, __LINE__, "testssaunit.ap:1763"); - ae_set_error_flag(errorflag, noise.cnt!=nanalyzed, __FILE__, __LINE__, "testssaunit.ap:1764"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=ae_maxint(nanalyzed-nlasttracklen, 0, _state)-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1769"); - ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1770"); - } - for(i=ae_maxint(nanalyzed-nlasttracklen, 0, _state); i<=nanalyzed-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[i-nanalyzed+nlasttracklen], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1774"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1775"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nticks = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&x2, nticks, _state); - for(i=0; i<=nticks-1; i++) - { - x2.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&trend, 0, _state); - ae_vector_set_length(&noise, 0, _state); - ssaanalyzesequence(&state, &x2, nticks, &trend, &noise, _state); - ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1787"); - ae_set_error_flag(errorflag, noise.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1788"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=nticks-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x2.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1793"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1794"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nticks = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&trend, 0, _state); - ssaforecastlast(&state, nticks, &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1802"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=nticks-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],x.ptr.p_double[nlasttracklen-1]), __FILE__, __LINE__, "testssaunit.ap:1806"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - datalen = 1+hqrnduniformi(&rs, 10, _state); - forecastlen = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&x, datalen, _state); - for(i=0; i<=datalen-1; i++) - { - x.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&trend, 0, _state); - ssaforecastsequence(&state, &x, datalen, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=forecastlen, __FILE__, __LINE__, "testssaunit.ap:1817"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=forecastlen-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],x.ptr.p_double[datalen-1]), __FILE__, __LINE__, "testssaunit.ap:1821"); - } - } - } - - /* - * Test that for model with non-unit window, some algo being set to calculate ALL - * components, and one/few tracks which have at least window length ticks: - * * SSAGetBasis() returns full orthonormal basis - * * SSAAnalyzeLastWindow() returns last elements of track as trend and zeros - * as noise (with minor rounding error) - * * SSAAnalyzeLast() returns track as trend and zeros as noise (with - * minor rounding error possible). For NTicks>TrackLength result is correctly - * prepended with zeros. - * * SSAAnalyzeSequence() returns: - * * for sequences with length at least window width - sequence as trend, - * zeros as noise (up to machine precision) - * * for sequences shorter than window width - zeros as trend, - * sequence as noise (exactly) - * * SSAForecastLast() returns just copies of the last element - * * SSAForecastSequence() returns just copies of the last element for long enough - * sequences, zeros for shorter sequences - */ - for(pass=1; pass<=passcount; pass++) - { - - /* - * Generate task; last track is stored in X, its length in NLastTrackLen - */ - windowwidth = 1+hqrnduniformi(&rs, 5, _state); - ntracks = 1+hqrnduniformi(&rs, 3, _state); - mintracklen = windowwidth; - maxtracklen = mintracklen+2*windowwidth; - ssacreate(&state, _state); - ssasetwindow(&state, windowwidth, _state); - ae_matrix_set_length(&tracksmatrix, ntracks, maxtracklen, _state); - ae_vector_set_length(&trackssizes, ntracks, _state); - nlasttracklen = 0; - for(k=0; k<=ntracks-1; k++) - { - nlasttracklen = mintracklen+hqrnduniformi(&rs, maxtracklen-mintracklen+1, _state); - ae_vector_set_length(&x, nlasttracklen, _state); - for(i=0; i<=nlasttracklen-1; i++) - { - x.ptr.p_double[i] = hqrndnormal(&rs, _state); - tracksmatrix.ptr.pp_double[k][i] = x.ptr.p_double[i]; - } - trackssizes.ptr.p_int[k] = nlasttracklen; - ssaaddsequence(&state, &x, nlasttracklen, _state); - } - if( algotype==1 ) - { - rmatrixrndorthogonal(windowwidth, &b, _state); - ssasetalgoprecomputed(&state, &b, windowwidth, windowwidth, _state); - } - else - { - if( algotype==2 ) - { - ssasetalgotopkdirect(&state, windowwidth, _state); - } - else - { - if( algotype==3 ) - { - ssasetalgotopkrealtime(&state, windowwidth, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - - /* - * Test - */ - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - ssagetbasis(&state, &a, &sv, &windowwidth2, &nbasis, _state); - ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1888"); - ae_set_error_flag(errorflag, nbasis!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1889"); - ae_set_error_flag(errorflag, a.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1890"); - ae_set_error_flag(errorflag, a.cols!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1891"); - ae_set_error_flag(errorflag, sv.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1892"); - for(i=0; i<=windowwidth-1; i++) - { - for(j=0; j<=windowwidth-1; j++) - { - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &a.ptr.pp_double[j][0], 1, ae_v_len(0,windowwidth-1)); - if( i==j ) - { - v = v-1; - } - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v, _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1899"); - } - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - windowwidth2 = -1; - ae_vector_set_length(&trend, 0, _state); - ae_vector_set_length(&noise, 0, _state); - ssaanalyzelastwindow(&state, &trend, &noise, &windowwidth2, _state); - ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1908"); - ae_set_error_flag(errorflag, trend.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1909"); - ae_set_error_flag(errorflag, noise.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1910"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=windowwidth-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[i-windowwidth+nlasttracklen], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1915"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1916"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nanalyzed = 1+hqrnduniformi(&rs, 2*maxtracklen, _state); - ae_vector_set_length(&trend, 0, _state); - ae_vector_set_length(&noise, 0, _state); - ssaanalyzelast(&state, nanalyzed, &trend, &noise, _state); - ae_set_error_flag(errorflag, trend.cnt!=nanalyzed, __FILE__, __LINE__, "testssaunit.ap:1925"); - ae_set_error_flag(errorflag, noise.cnt!=nanalyzed, __FILE__, __LINE__, "testssaunit.ap:1926"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=ae_maxint(nanalyzed-nlasttracklen, 0, _state)-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1931"); - ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1932"); - } - for(i=ae_maxint(nanalyzed-nlasttracklen, 0, _state); i<=nanalyzed-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[i-nanalyzed+nlasttracklen], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1936"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1937"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nticks = 1+hqrnduniformi(&rs, 2*windowwidth, _state); - ae_vector_set_length(&x2, nticks, _state); - for(i=0; i<=nticks-1; i++) - { - x2.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&trend, 0, _state); - ae_vector_set_length(&noise, 0, _state); - ssaanalyzesequence(&state, &x2, nticks, &trend, &noise, _state); - ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1949"); - ae_set_error_flag(errorflag, noise.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1950"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=nticks-1; i++) - { - if( nticks>=windowwidth ) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x2.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1957"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1958"); - } - else - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1962"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i]-x2.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1963"); - } - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nticks = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&trend, 0, _state); - ssaforecastlast(&state, nticks, &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1972"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=nticks-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],x.ptr.p_double[nlasttracklen-1]), __FILE__, __LINE__, "testssaunit.ap:1976"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - if( windowwidth>2 ) - { - datalen = 1+hqrnduniformi(&rs, windowwidth-1, _state); - forecastlen = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&x, datalen, _state); - for(i=0; i<=datalen-1; i++) - { - x.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&trend, 0, _state); - ssaforecastsequence(&state, &x, datalen, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=forecastlen, __FILE__, __LINE__, "testssaunit.ap:1990"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=forecastlen-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],0.0), __FILE__, __LINE__, "testssaunit.ap:1994"); - } - } - datalen = windowwidth+hqrnduniformi(&rs, windowwidth, _state); - forecastlen = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&x, datalen, _state); - for(i=0; i<=datalen-1; i++) - { - x.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&trend, 0, _state); - ssaforecastsequence(&state, &x, datalen, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=forecastlen, __FILE__, __LINE__, "testssaunit.ap:2005"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=forecastlen-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],x.ptr.p_double[datalen-1]), __FILE__, __LINE__, "testssaunit.ap:2009"); - } - } - } - - /* - * Test that for model with - * - * * strictly non-unit window - * * some algo being set to calculate one leading component - * * a few tracks which have at least window length ticks - * * and last track which has LESS than window length minus 1 ticks - * - * we have: - * - * * SSAAnalyzeLastWindow() returns zero trend and sequence as noise, - * correctly padded by zeros - * * SSAAnalyzeLast() returns zero trend and sequence as noise, - * correctly padded by zeros - * * SSAForecastLast() returns zero trend - * - * This test checks correct handling of the situatuon when last sequence - * stored in the dataset is too short. - */ - for(pass=1; pass<=passcount; pass++) - { - - /* - * Generate task; last track is stored in X, its length in NLastTrackLen - */ - windowwidth = 3+hqrnduniformi(&rs, 5, _state); - ntracks = 1+hqrnduniformi(&rs, 3, _state); - mintracklen = windowwidth; - maxtracklen = mintracklen+2*windowwidth; - ssacreate(&state, _state); - ssasetwindow(&state, windowwidth, _state); - for(k=0; k<=ntracks-1; k++) - { - nlasttracklen = mintracklen+hqrnduniformi(&rs, maxtracklen-mintracklen+1, _state); - ae_vector_set_length(&x, nlasttracklen, _state); - for(i=0; i<=nlasttracklen-1; i++) - { - x.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ssaaddsequence(&state, &x, nlasttracklen, _state); - } - nlasttracklen = windowwidth-2; - ae_vector_set_length(&x, nlasttracklen, _state); - for(i=0; i<=nlasttracklen-1; i++) - { - x.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ssaaddsequence(&state, &x, nlasttracklen, _state); - if( algotype==1 ) - { - rmatrixrndorthogonal(windowwidth, &b, _state); - ssasetalgoprecomputed(&state, &b, windowwidth, 1, _state); - } - else - { - if( algotype==2 ) - { - ssasetalgotopkdirect(&state, 1, _state); - } - else - { - if( algotype==3 ) - { - ssasetalgotopkrealtime(&state, 1, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - - /* - * Test - */ - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - windowwidth2 = -1; - ae_vector_set_length(&trend, 0, _state); - ae_vector_set_length(&noise, 0, _state); - ssaanalyzelastwindow(&state, &trend, &noise, &windowwidth2, _state); - ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:2078"); - ae_set_error_flag(errorflag, trend.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:2079"); - ae_set_error_flag(errorflag, noise.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:2080"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=windowwidth-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],0.0), __FILE__, __LINE__, "testssaunit.ap:2085"); - j = nlasttracklen+(i-windowwidth); - if( j>=0 ) - { - ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],x.ptr.p_double[j]), __FILE__, __LINE__, "testssaunit.ap:2088"); - } - else - { - ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],0.0), __FILE__, __LINE__, "testssaunit.ap:2090"); - } - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nanalyzed = 1+hqrnduniformi(&rs, 2*windowwidth, _state); - ae_vector_set_length(&trend, 0, _state); - ae_vector_set_length(&noise, 0, _state); - ssaanalyzelast(&state, nanalyzed, &trend, &noise, _state); - ae_set_error_flag(errorflag, trend.cnt!=nanalyzed, __FILE__, __LINE__, "testssaunit.ap:2099"); - ae_set_error_flag(errorflag, noise.cnt!=nanalyzed, __FILE__, __LINE__, "testssaunit.ap:2100"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=ae_maxint(nanalyzed-nlasttracklen, 0, _state)-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:2105"); - ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:2106"); - } - for(i=ae_maxint(nanalyzed-nlasttracklen, 0, _state); i<=nanalyzed-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:2110"); - ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],x.ptr.p_double[nlasttracklen+(i-nanalyzed)]), __FILE__, __LINE__, "testssaunit.ap:2111"); - } - } - if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) ) - { - nticks = 1+hqrnduniformi(&rs, 10, _state); - ae_vector_set_length(&trend, 0, _state); - ssaforecastlast(&state, nticks, &trend, _state); - ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:2119"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=nticks-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],0.0), __FILE__, __LINE__, "testssaunit.ap:2123"); - } - } - } - } - ae_frame_leave(_state); -} - - - - - - - - -ae_bool testgammafunc(ae_bool silent, ae_state *_state) -{ - double threshold; - double v; - double s; - ae_bool waserrors; - ae_bool gammaerrors; - ae_bool lngammaerrors; - ae_bool result; - - - gammaerrors = ae_false; - lngammaerrors = ae_false; - waserrors = ae_false; - threshold = 100*ae_machineepsilon; - - /* - * - */ - gammaerrors = gammaerrors||ae_fp_greater(ae_fabs(gammafunction(0.5, _state)-ae_sqrt(ae_pi, _state), _state),threshold); - gammaerrors = gammaerrors||ae_fp_greater(ae_fabs(gammafunction(1.5, _state)-0.5*ae_sqrt(ae_pi, _state), _state),threshold); - v = lngamma(0.5, &s, _state); - lngammaerrors = (lngammaerrors||ae_fp_greater(ae_fabs(v-ae_log(ae_sqrt(ae_pi, _state), _state), _state),threshold))||ae_fp_neq(s,(double)(1)); - v = lngamma(1.5, &s, _state); - lngammaerrors = (lngammaerrors||ae_fp_greater(ae_fabs(v-ae_log(0.5*ae_sqrt(ae_pi, _state), _state), _state),threshold))||ae_fp_neq(s,(double)(1)); - - /* - * report - */ - waserrors = gammaerrors||lngammaerrors; - if( !silent ) - { - printf("TESTING GAMMA FUNCTION\n"); - printf("GAMMA: "); - if( gammaerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("LN GAMMA: "); - if( lngammaerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - - /* - * end - */ - result = !waserrors; - return result; -} - - - -static void testnormaldistrunit_testnormal(ae_bool* errorflag, - ae_state *_state); -static void testnormaldistrunit_testbvn(ae_bool* errorflag, - ae_state *_state); - - - - - -ae_bool testnormaldistr(ae_bool silent, ae_state *_state) -{ - ae_bool nrmerr; - ae_bool bvnerr; - ae_bool wereerrors; - ae_bool result; - - - nrmerr = ae_false; - bvnerr = ae_false; - testnormaldistrunit_testnormal(&nrmerr, _state); - testnormaldistrunit_testbvn(&bvnerr, _state); - - /* - * report - */ - wereerrors = bvnerr||nrmerr; - if( !silent ) - { - printf("TESTING NORMAL DISTRIBUTION\n"); - printf("NORMAL DISTRIBUTION: "); - if( nrmerr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("BIVARIATE NORMALS: "); - if( bvnerr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( wereerrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - - /* - * end - */ - result = !wereerrors; - return result; -} - - -/************************************************************************* -Normal test - - -- ALGLIB -- - Copyright 15.11.2019 by Bochkanov Sergey -*************************************************************************/ -static void testnormaldistrunit_testnormal(ae_bool* errorflag, - ae_state *_state) -{ - ae_frame _frame_block; - double v0; - double v1; - double x; - double h; - hqrndstate rs; - ae_int_t k; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Test that PDF is roughly equal to derivative of CDF - */ - for(k=0; k<=999; k++) - { - x = hqrndnormal(&rs, _state); - h = 1.0E-5; - v0 = normalpdf(x, _state); - v1 = (normalcdf(x+h, _state)-normalcdf(x-h, _state))/(2*h); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v0-v1, _state),1.0E-4), __FILE__, __LINE__, "testnormaldistrunit.ap:75"); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Bivariate normal test - - -- ALGLIB -- - Copyright 15.11.2019 by Bochkanov Sergey -*************************************************************************/ -static void testnormaldistrunit_testbvn(ae_bool* errorflag, - ae_state *_state) -{ - ae_frame _frame_block; - double v0; - double v1; - double err; - double x; - double y; - double rho; - double h; - hqrndstate rs; - ae_int_t k; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Test bivariate normal CDF values (small Rho and hard Rho) - */ - err = (double)(0); - err = ae_maxreal(err, ae_fabs(0.142221121370770000-bivariatenormalcdf(-1.060937077356340000, 1.523763953950230000, 0.344134938671007000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.001090824383322160-bivariatenormalcdf(-3.034280037001620000, 0.633583566571867000, 0.196737644948391000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000063428666799461-bivariatenormalcdf(-3.577198111015300000, -2.584892928002350000, 0.603284544092224000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000019144648137-bivariatenormalcdf(-1.053171728048290000, -2.987017621703680000, -0.659498170394145000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.972551066792029000-bivariatenormalcdf(4.785178416287600000, 1.919693671247900000, 0.261346800934746000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000608605272790-bivariatenormalcdf(-4.852815283224590000, 2.398320119295830000, 0.662485812586403000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.576135824931800000-bivariatenormalcdf(0.192020298597275000, 4.695461487450740000, -0.110028699320946000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.876357061322732000-bivariatenormalcdf(2.095780141251770000, 1.211768206209080000, 0.397007061864995000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.002969212104812400-bivariatenormalcdf(-2.654007687508430000, 1.340051767837440000, -0.233916559318503000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000377048151161364-bivariatenormalcdf(1.128363097510700000, -2.781006578069910000, -0.642877478801918000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.995657061734790000-bivariatenormalcdf(3.966506850977000000, 2.626841258388710000, 0.291409185863929000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.003282876365551870-bivariatenormalcdf(-2.717530641700190000, 3.217920162027340000, -0.101773464540366000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.002099371685469470-bivariatenormalcdf(-1.811681729272450000, -2.262911120125770000, 0.361735313431128000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.648944114852307000-bivariatenormalcdf(1.861468373436860000, 0.432740073549983000, 0.092845182466246300, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000094851728-bivariatenormalcdf(-4.898527851968480000, -3.491204153631050000, -0.010492822687090300, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000416778593465223-bivariatenormalcdf(-3.341356669094100000, 1.862802982022170000, 0.398642687655347000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.741640376816388000-bivariatenormalcdf(4.687494092358740000, 0.648415139929991000, -0.692925257444683000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.868844042717264000-bivariatenormalcdf(2.369093655782270000, 1.148153167494120000, 0.297877516862745000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.999356215351682000-bivariatenormalcdf(4.352384277131720000, 3.221749932900420000, -0.257163446680127000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.998760969813713000-bivariatenormalcdf(3.422289814750960000, 3.111433954663520000, 0.198012195099628000, _state), _state), _state); - ae_set_error_flag(errorflag, ae_fp_greater(err,1.0E-12), __FILE__, __LINE__, "testnormaldistrunit.ap:121"); - err = (double)(0); - err = ae_maxreal(err, ae_fabs(0.080575405379940000-bivariatenormalcdf(-1.060937077356340000, 1.523763953950230000, -0.999999999999000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000000000007-bivariatenormalcdf(-1.060937077356340000, -1.060937077356340000, -0.999999999999000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000000000007-bivariatenormalcdf(-1.060937077356340000, -1.060937077354570000, -0.999999999999000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000000000016-bivariatenormalcdf(-3.034280037001620000, 0.633583566571867000, -0.999999999990000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-3.034280037001620000, -3.034280037001620000, -0.999999999990000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-3.034280037001620000, -3.034280036974940000, -0.999999999990000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-3.577198111015300000, -2.584892928002350000, -0.999999999900000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-3.577198111015300000, -3.577198111015300000, -0.999999999900000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-3.577198111015300000, -3.577198111015280000, -0.999999999900000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-1.053171728048290000, -2.987017621703680000, -0.999999999000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000000000021-bivariatenormalcdf(-1.053171728048290000, -1.053171728048290000, -0.999999999000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000000000014-bivariatenormalcdf(-1.053171728048290000, -1.052982935276290000, -0.999999999000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.972550843757766000-bivariatenormalcdf(4.785178416287600000, 1.919693671247900000, -0.999999990000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.999998291644901000-bivariatenormalcdf(4.785178416287600000, 4.785178416287600000, -0.999999990000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.999998291644901000-bivariatenormalcdf(4.785178416287600000, 4.785178416295720000, -0.999999990000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-4.852815283224590000, 2.398320119295830000, -0.999999900000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-4.852815283224590000, -4.852815283224590000, -0.999999900000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-4.852815283224590000, -4.852815283224590000, -0.999999900000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.576135517318684000-bivariatenormalcdf(0.192020298597275000, 4.695461487450740000, -0.999999000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.152273694692214000-bivariatenormalcdf(0.192020298597275000, 0.192020298597275000, -0.999999000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.152273697664791000-bivariatenormalcdf(0.192020298597275000, 0.192020306187062000, -0.999999000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.869148589647661000-bivariatenormalcdf(2.095780141251770000, 1.211768206209080000, -0.999990000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.963898301217005000-bivariatenormalcdf(2.095780141251770000, 2.095780141251770000, -0.999990000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.963898301217035000-bivariatenormalcdf(2.095780141251770000, 2.095780141252440000, -0.999990000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-2.654007687508430000, 1.340051767837440000, -0.999900000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-2.654007687508430000, -2.654007687508430000, -0.999900000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-2.654007687508430000, -2.654007613149620000, -0.999900000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000000000019-bivariatenormalcdf(1.128363097510700000, -2.781006578069910000, -0.999000000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.740833394117601000-bivariatenormalcdf(1.128363097510700000, 1.128363097510700000, -0.999000000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.740862731628071000-bivariatenormalcdf(1.128363097510700000, 1.128502099120660000, -0.999000000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.995654456762395000-bivariatenormalcdf(3.966506850977000000, 2.626841258388710000, -0.990000000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.999927066319845000-bivariatenormalcdf(3.966506850977000000, 3.966506850977000000, -0.990000000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.999927066319846000-bivariatenormalcdf(3.966506850977000000, 3.966506850981670000, -0.990000000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.002769246133985220-bivariatenormalcdf(-2.717530641700190000, 3.217920162027340000, -0.900000000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-2.717530641700190000, -2.717530641700190000, -0.900000000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-2.717530641700190000, -2.717530635181090000, -0.900000000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.010079636581695100-bivariatenormalcdf(-1.811681729272450000, -2.262911120125770000, 0.900000000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.021493462833838000-bivariatenormalcdf(-1.811681729272450000, -1.811681729272450000, 0.900000000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.021493462833871500-bivariatenormalcdf(-1.811681729272450000, -1.811681729271170000, 0.900000000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.667398193291227000-bivariatenormalcdf(1.861468373436860000, 0.432740073549983000, 0.990000000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.964688949692122000-bivariatenormalcdf(1.861468373436860000, 1.861468373436860000, 0.990000000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.964688949699170000-bivariatenormalcdf(1.861468373436860000, 1.861468373617680000, 0.990000000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000482786767864-bivariatenormalcdf(-4.898527851968480000, -3.491204153631050000, 0.999000000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000439041574222-bivariatenormalcdf(-4.898527851968480000, -4.898527851968480000, 0.999000000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000000439041575582-bivariatenormalcdf(-4.898527851968480000, -4.898527850755250000, 0.999000000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000416850246666766-bivariatenormalcdf(-3.341356669094100000, 1.862802982022170000, 0.999900000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000408379488679640-bivariatenormalcdf(-3.341356669094100000, -3.341356669094100000, 0.999900000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000408379488680111-bivariatenormalcdf(-3.341356669094100000, -3.341356669093450000, 0.999900000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.741641759669778000-bivariatenormalcdf(4.687494092358740000, 0.648415139929991000, 0.999990000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.999998605095178000-bivariatenormalcdf(4.687494092358740000, 4.687494092358740000, 0.999990000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.999998606247630000-bivariatenormalcdf(4.687494092358740000, 4.687843556049730000, 0.999990000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.874547330614982000-bivariatenormalcdf(2.369093655782270000, 1.148153167494120000, 0.999999000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.991070530231016000-bivariatenormalcdf(2.369093655782270000, 2.369093655782270000, 0.999999000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.991070530231065000-bivariatenormalcdf(2.369093655782270000, 2.369093655786410000, 0.999999000000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.999362948580782000-bivariatenormalcdf(4.352384277131720000, 3.221749932900420000, 0.999999900000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.999993261271150000-bivariatenormalcdf(4.352384277131720000, 4.352384277131720000, 0.999999900000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.999993261272904000-bivariatenormalcdf(4.352384277131720000, 4.352384391237480000, 0.999999900000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.999069094420465000-bivariatenormalcdf(3.422289814750960000, 3.111433954663520000, 0.999999990000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.999689455134645000-bivariatenormalcdf(3.422289814750960000, 3.422289814750960000, 0.999999990000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.999689455134658000-bivariatenormalcdf(3.422289814750960000, 3.422289814777010000, 0.999999990000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.294719708527162000-bivariatenormalcdf(-0.539648565868907000, 2.177679562057720000, 0.999999999000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.294713555379044000-bivariatenormalcdf(-0.539648565868907000, -0.539648565868907000, 0.999999999000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.294718518285085000-bivariatenormalcdf(-0.539648565868907000, -0.539602058260055000, 0.999999999000000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000002811467986141-bivariatenormalcdf(-4.540093229575050000, 2.436946780486250000, 0.999999999900000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000002811392754616-bivariatenormalcdf(-4.540093229575050000, -4.540093229575050000, 0.999999999900000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000002811467986126-bivariatenormalcdf(-4.540093229575050000, -4.540001786779430000, 0.999999999900000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.565106870340374000-bivariatenormalcdf(0.163929988133744000, 3.995097146641120000, 0.999999999990000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.565106168077456000-bivariatenormalcdf(0.163929988133744000, 0.163929988133744000, 0.999999999990000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.565106168096292000-bivariatenormalcdf(0.163929988133744000, 0.163929988229317000, 0.999999999990000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.000064751025417698-bivariatenormalcdf(3.421155338081630000, -3.827403648909790000, 0.999999999999000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.999688220825439000-bivariatenormalcdf(3.421155338081630000, 3.421155338081630000, 0.999999999999000000, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(0.999688221472430000-bivariatenormalcdf(3.421155338081630000, 3.421174755498880000, 0.999999999999000000, _state), _state), _state); - ae_set_error_flag(errorflag, ae_fp_greater(err,1.0E-12), __FILE__, __LINE__, "testnormaldistrunit.ap:195"); - - /* - * Test that BVN PDF is roughly equal to derivative of BVN CDF - */ - for(k=0; k<=999; k++) - { - - /* - * Generate trial point - */ - x = hqrndnormal(&rs, _state); - y = hqrndnormal(&rs, _state); - rho = (double)(0); - - /* - * Compare two values: normal PDF and differentiation of normal CDF with step H - */ - h = 1.0E-5; - v0 = bivariatenormalpdf(x, y, rho, _state); - v1 = (bivariatenormalcdf(x+h, y+h, rho, _state)+bivariatenormalcdf(x-h, y-h, rho, _state)-bivariatenormalcdf(x+h, y-h, rho, _state)-bivariatenormalcdf(x-h, y+h, rho, _state))/ae_sqr(2*h, _state); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v0-v1, _state),1.0E-4), __FILE__, __LINE__, "testnormaldistrunit.ap:215"); - } - ae_frame_leave(_state); -} - - - -static void testlinregunit_generaterandomtask(double xl, - double xr, - ae_bool randomx, - double ymin, - double ymax, - double smin, - double smax, - ae_int_t n, - /* Real */ ae_matrix* xy, - /* Real */ ae_vector* s, - ae_state *_state); -static void testlinregunit_generatetask(double a, - double b, - double xl, - double xr, - ae_bool randomx, - double smin, - double smax, - ae_int_t n, - /* Real */ ae_matrix* xy, - /* Real */ ae_vector* s, - ae_state *_state); -static void testlinregunit_filltaskwithy(double a, - double b, - ae_int_t n, - /* Real */ ae_matrix* xy, - /* Real */ ae_vector* s, - ae_state *_state); -static double testlinregunit_generatenormal(double mean, - double sigma, - ae_state *_state); -static void testlinregunit_calculatemv(/* Real */ ae_vector* x, - ae_int_t n, - double* mean, - double* means, - double* stddev, - double* stddevs, - ae_state *_state); -static void testlinregunit_unsetlr(linearmodel* lr, ae_state *_state); - - - - - -ae_bool testlinreg(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - double sigmathreshold; - ae_int_t maxn; - ae_int_t passcount; - ae_int_t estpasscount; - double threshold; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t tmpi; - ae_int_t pass; - ae_int_t epass; - ae_int_t m; - ae_int_t tasktype; - ae_int_t modeltype; - ae_int_t m1; - ae_int_t m2; - ae_int_t n1; - ae_int_t n2; - ae_int_t info; - ae_int_t info2; - ae_matrix xy; - ae_matrix xy2; - ae_vector s; - ae_vector s2; - ae_vector w2; - ae_vector x; - ae_vector ta; - ae_vector tb; - ae_vector tc; - ae_vector xy0; - ae_vector tmpweights; - linearmodel w; - linearmodel wt; - linearmodel wt2; - ae_vector x1; - ae_vector x2; - double y1; - double y2; - ae_bool allsame; - double ea; - double eb; - double varatested; - double varbtested; - double a; - double b; - double vara; - double varb; - double a2; - double b2; - double covab; - double corrab; - double p; - ae_int_t qcnt; - ae_vector qtbl; - ae_vector qvals; - ae_vector qsigma; - lrreport ar; - lrreport ar2; - double f; - double fp; - double fm; - double v; - double vv; - double cvrmserror; - double cvavgerror; - double cvavgrelerror; - double rmserror; - double avgerror; - double avgrelerror; - ae_bool nondefect; - double sinshift; - double tasklevel; - double noiselevel; - double hstep; - double sigma; - double mean; - double means; - double stddev; - double stddevs; - ae_bool slcerrors; - ae_bool slerrors; - ae_bool grcoverrors; - ae_bool gropterrors; - ae_bool gresterrors; - ae_bool grothererrors; - ae_bool grconverrors; - ae_bool waserrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&xy2, 0, sizeof(xy2)); - memset(&s, 0, sizeof(s)); - memset(&s2, 0, sizeof(s2)); - memset(&w2, 0, sizeof(w2)); - memset(&x, 0, sizeof(x)); - memset(&ta, 0, sizeof(ta)); - memset(&tb, 0, sizeof(tb)); - memset(&tc, 0, sizeof(tc)); - memset(&xy0, 0, sizeof(xy0)); - memset(&tmpweights, 0, sizeof(tmpweights)); - memset(&w, 0, sizeof(w)); - memset(&wt, 0, sizeof(wt)); - memset(&wt2, 0, sizeof(wt2)); - memset(&x1, 0, sizeof(x1)); - memset(&x2, 0, sizeof(x2)); - memset(&qtbl, 0, sizeof(qtbl)); - memset(&qvals, 0, sizeof(qvals)); - memset(&qsigma, 0, sizeof(qsigma)); - memset(&ar, 0, sizeof(ar)); - memset(&ar2, 0, sizeof(ar2)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ta, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tb, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xy0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpweights, 0, DT_REAL, _state, ae_true); - _linearmodel_init(&w, _state, ae_true); - _linearmodel_init(&wt, _state, ae_true); - _linearmodel_init(&wt2, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&qtbl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&qvals, 0, DT_REAL, _state, ae_true); - ae_vector_init(&qsigma, 0, DT_REAL, _state, ae_true); - _lrreport_init(&ar, _state, ae_true); - _lrreport_init(&ar2, _state, ae_true); - - - /* - * Primary settings - */ - maxn = 40; - passcount = 3; - estpasscount = 1000; - sigmathreshold = (double)(7); - threshold = 1000000*ae_machineepsilon; - slerrors = ae_false; - slcerrors = ae_false; - grcoverrors = ae_false; - gropterrors = ae_false; - gresterrors = ae_false; - grothererrors = ae_false; - grconverrors = ae_false; - waserrors = ae_false; - - /* - * Quantiles table setup - */ - qcnt = 5; - ae_vector_set_length(&qtbl, qcnt-1+1, _state); - ae_vector_set_length(&qvals, qcnt-1+1, _state); - ae_vector_set_length(&qsigma, qcnt-1+1, _state); - qtbl.ptr.p_double[0] = 0.5; - qtbl.ptr.p_double[1] = 0.25; - qtbl.ptr.p_double[2] = 0.10; - qtbl.ptr.p_double[3] = 0.05; - qtbl.ptr.p_double[4] = 0.025; - for(i=0; i<=qcnt-1; i++) - { - qsigma.ptr.p_double[i] = ae_sqrt(qtbl.ptr.p_double[i]*(1-qtbl.ptr.p_double[i])/estpasscount, _state); - } - - /* - * Other setup - */ - ae_vector_set_length(&ta, estpasscount-1+1, _state); - ae_vector_set_length(&tb, estpasscount-1+1, _state); - - /* - * Test straight line regression - */ - for(n=2; n<=maxn; n++) - { - - /* - * Fail/pass test - */ - testlinregunit_generaterandomtask((double)(-1), (double)(1), ae_false, (double)(-1), (double)(1), (double)(1), (double)(2), n, &xy, &s, _state); - lrlines(&xy, &s, n, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state); - slcerrors = slcerrors||info!=1; - testlinregunit_generaterandomtask((double)(1), (double)(1), ae_false, (double)(-1), (double)(1), (double)(1), (double)(2), n, &xy, &s, _state); - lrlines(&xy, &s, n, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state); - slcerrors = slcerrors||info!=-3; - testlinregunit_generaterandomtask((double)(-1), (double)(1), ae_false, (double)(-1), (double)(1), (double)(-1), (double)(-1), n, &xy, &s, _state); - lrlines(&xy, &s, n, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state); - slcerrors = slcerrors||info!=-2; - testlinregunit_generaterandomtask((double)(-1), (double)(1), ae_false, (double)(-1), (double)(1), (double)(2), (double)(1), 2, &xy, &s, _state); - lrlines(&xy, &s, 1, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state); - slcerrors = slcerrors||info!=-1; - - /* - * Multipass tests - */ - for(pass=1; pass<=passcount; pass++) - { - - /* - * Test S variant against non-S variant - */ - ea = 2*ae_randomreal(_state)-1; - eb = 2*ae_randomreal(_state)-1; - testlinregunit_generatetask(ea, eb, -5*ae_randomreal(_state), 5*ae_randomreal(_state), ae_fp_greater(ae_randomreal(_state),0.5), (double)(1), (double)(1), n, &xy, &s, _state); - lrlines(&xy, &s, n, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state); - lrline(&xy, n, &info2, &a2, &b2, _state); - if( info!=1||info2!=1 ) - { - slcerrors = ae_true; - } - else - { - slerrors = (slerrors||ae_fp_greater(ae_fabs(a-a2, _state),threshold))||ae_fp_greater(ae_fabs(b-b2, _state),threshold); - } - - /* - * Test for A/B - * - * Generate task with exact, non-perturbed y[i], - * then make non-zero s[i] - */ - ea = 2*ae_randomreal(_state)-1; - eb = 2*ae_randomreal(_state)-1; - testlinregunit_generatetask(ea, eb, -5*ae_randomreal(_state), 5*ae_randomreal(_state), n>4, 0.0, 0.0, n, &xy, &s, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = 1+ae_randomreal(_state); - } - lrlines(&xy, &s, n, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state); - if( info!=1 ) - { - slcerrors = ae_true; - } - else - { - slerrors = (slerrors||ae_fp_greater(ae_fabs(a-ea, _state),0.001))||ae_fp_greater(ae_fabs(b-eb, _state),0.001); - } - - /* - * Test for VarA, VarB, P (P is being tested only for N>2) - */ - for(i=0; i<=qcnt-1; i++) - { - qvals.ptr.p_double[i] = (double)(0); - } - ea = 2*ae_randomreal(_state)-1; - eb = 2*ae_randomreal(_state)-1; - testlinregunit_generatetask(ea, eb, -5*ae_randomreal(_state), 5*ae_randomreal(_state), n>4, 1.0, 2.0, n, &xy, &s, _state); - lrlines(&xy, &s, n, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state); - if( info!=1 ) - { - slcerrors = ae_true; - continue; - } - varatested = vara; - varbtested = varb; - for(epass=0; epass<=estpasscount-1; epass++) - { - - /* - * Generate - */ - testlinregunit_filltaskwithy(ea, eb, n, &xy, &s, _state); - lrlines(&xy, &s, n, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state); - if( info!=1 ) - { - slcerrors = ae_true; - continue; - } - - /* - * A, B, P - * (P is being tested for uniformity, additional p-tests are below) - */ - ta.ptr.p_double[epass] = a; - tb.ptr.p_double[epass] = b; - for(i=0; i<=qcnt-1; i++) - { - if( ae_fp_less_eq(p,qtbl.ptr.p_double[i]) ) - { - qvals.ptr.p_double[i] = qvals.ptr.p_double[i]+(double)1/(double)estpasscount; - } - } - } - testlinregunit_calculatemv(&ta, estpasscount, &mean, &means, &stddev, &stddevs, _state); - slerrors = slerrors||ae_fp_greater_eq(ae_fabs(mean-ea, _state)/means,sigmathreshold); - slerrors = slerrors||ae_fp_greater_eq(ae_fabs(stddev-ae_sqrt(varatested, _state), _state)/stddevs,sigmathreshold); - testlinregunit_calculatemv(&tb, estpasscount, &mean, &means, &stddev, &stddevs, _state); - slerrors = slerrors||ae_fp_greater_eq(ae_fabs(mean-eb, _state)/means,sigmathreshold); - slerrors = slerrors||ae_fp_greater_eq(ae_fabs(stddev-ae_sqrt(varbtested, _state), _state)/stddevs,sigmathreshold); - if( n>2 ) - { - for(i=0; i<=qcnt-1; i++) - { - if( ae_fp_greater(ae_fabs(qtbl.ptr.p_double[i]-qvals.ptr.p_double[i], _state)/qsigma.ptr.p_double[i],sigmathreshold) ) - { - slerrors = ae_true; - } - } - } - - /* - * Additional tests for P: correlation with fit quality - */ - if( n>2 ) - { - testlinregunit_generatetask(ea, eb, -5*ae_randomreal(_state), 5*ae_randomreal(_state), ae_false, 0.0, 0.0, n, &xy, &s, _state); - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = 1+ae_randomreal(_state); - } - lrlines(&xy, &s, n, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state); - if( info!=1 ) - { - slcerrors = ae_true; - continue; - } - slerrors = slerrors||ae_fp_less(p,0.999); - testlinregunit_generatetask((double)(0), (double)(0), -5*ae_randomreal(_state), 5*ae_randomreal(_state), ae_false, 1.0, 1.0, n, &xy, &s, _state); - for(i=0; i<=n-1; i++) - { - if( i%2==0 ) - { - xy.ptr.pp_double[i][1] = 5.0; - } - else - { - xy.ptr.pp_double[i][1] = -5.0; - } - } - if( n%2!=0 ) - { - xy.ptr.pp_double[n-1][1] = (double)(0); - } - lrlines(&xy, &s, n, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state); - if( info!=1 ) - { - slcerrors = ae_true; - continue; - } - slerrors = slerrors||ae_fp_greater(p,0.001); - } - } - } - - /* - * General regression tests: - */ - - /* - * Simple linear tests (small sample, optimum point, covariance) - */ - for(n=3; n<=maxn; n++) - { - ae_vector_set_length(&s, n-1+1, _state); - - /* - * Linear tests: - * a. random points, sigmas - * b. no sigmas - */ - ae_matrix_set_length(&xy, n-1+1, 1+1, _state); - for(i=0; i<=n-1; i++) - { - xy.ptr.pp_double[i][0] = 2*ae_randomreal(_state)-1; - xy.ptr.pp_double[i][1] = 2*ae_randomreal(_state)-1; - s.ptr.p_double[i] = 1+ae_randomreal(_state); - } - lrbuilds(&xy, &s, n, 1, &info, &wt, &ar, _state); - if( info!=1 ) - { - grconverrors = ae_true; - continue; - } - lrunpack(&wt, &tmpweights, &tmpi, _state); - lrlines(&xy, &s, n, &info2, &a, &b, &vara, &varb, &covab, &corrab, &p, _state); - gropterrors = gropterrors||ae_fp_greater(ae_fabs(a-tmpweights.ptr.p_double[1], _state),threshold); - gropterrors = gropterrors||ae_fp_greater(ae_fabs(b-tmpweights.ptr.p_double[0], _state),threshold); - grcoverrors = grcoverrors||ae_fp_greater(ae_fabs(vara-ar.c.ptr.pp_double[1][1], _state),threshold); - grcoverrors = grcoverrors||ae_fp_greater(ae_fabs(varb-ar.c.ptr.pp_double[0][0], _state),threshold); - grcoverrors = grcoverrors||ae_fp_greater(ae_fabs(covab-ar.c.ptr.pp_double[1][0], _state),threshold); - grcoverrors = grcoverrors||ae_fp_greater(ae_fabs(covab-ar.c.ptr.pp_double[0][1], _state),threshold); - lrbuild(&xy, n, 1, &info, &wt, &ar, _state); - if( info!=1 ) - { - grconverrors = ae_true; - continue; - } - lrunpack(&wt, &tmpweights, &tmpi, _state); - lrline(&xy, n, &info2, &a, &b, _state); - gropterrors = gropterrors||ae_fp_greater(ae_fabs(a-tmpweights.ptr.p_double[1], _state),threshold); - gropterrors = gropterrors||ae_fp_greater(ae_fabs(b-tmpweights.ptr.p_double[0], _state),threshold); - } - - /* - * S covariance versus S-less covariance. - * Slightly skewed task, large sample size. - * Will S-less subroutine estimate covariance matrix good enough? - */ - n = 1000+ae_randominteger(3000, _state); - sigma = 0.1+ae_randomreal(_state)*1.9; - ae_matrix_set_length(&xy, n-1+1, 1+1, _state); - ae_vector_set_length(&s, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - xy.ptr.pp_double[i][0] = 1.5*ae_randomreal(_state)-0.5; - xy.ptr.pp_double[i][1] = 1.2*xy.ptr.pp_double[i][0]-0.3+testlinregunit_generatenormal((double)(0), sigma, _state); - s.ptr.p_double[i] = sigma; - } - lrbuild(&xy, n, 1, &info, &wt, &ar, _state); - lrlines(&xy, &s, n, &info2, &a, &b, &vara, &varb, &covab, &corrab, &p, _state); - if( info!=1||info2!=1 ) - { - grconverrors = ae_true; - } - else - { - grcoverrors = grcoverrors||ae_fp_greater(ae_fabs(ae_log(ar.c.ptr.pp_double[0][0]/varb, _state), _state),ae_log(1.2, _state)); - grcoverrors = grcoverrors||ae_fp_greater(ae_fabs(ae_log(ar.c.ptr.pp_double[1][1]/vara, _state), _state),ae_log(1.2, _state)); - grcoverrors = grcoverrors||ae_fp_greater(ae_fabs(ae_log(ar.c.ptr.pp_double[0][1]/covab, _state), _state),ae_log(1.2, _state)); - grcoverrors = grcoverrors||ae_fp_greater(ae_fabs(ae_log(ar.c.ptr.pp_double[1][0]/covab, _state), _state),ae_log(1.2, _state)); - } - - /* - * General tests: - * * basis functions - up to cubic - * * task types: - * * data set is noisy sine half-period with random shift - * * tests: - * unpacking/packing - * optimality - * error estimates - * * tasks: - * 0 = noised sine - * 1 = degenerate task with 1-of-n encoded categorical variables - * 2 = random task with large variation (for 1-type models) - * 3 = random task with small variation (for 1-type models) - * - * Additional tasks TODO - * specially designed task with defective vectors which leads to - * the failure of the fast CV formula. - * - */ - m1 = 0; - m2 = -1; - n1 = 0; - n2 = -1; - for(modeltype=0; modeltype<=1; modeltype++) - { - for(tasktype=0; tasktype<=3; tasktype++) - { - if( tasktype==0 ) - { - m1 = 1; - m2 = 3; - } - if( tasktype==1 ) - { - m1 = 9; - m2 = 9; - } - if( tasktype==2||tasktype==3 ) - { - m1 = 9; - m2 = 9; - } - for(m=m1; m<=m2; m++) - { - if( tasktype==0 ) - { - n1 = m+3; - n2 = m+20; - } - if( tasktype==1 ) - { - n1 = 70+ae_randominteger(70, _state); - n2 = n1; - } - if( tasktype==2||tasktype==3 ) - { - n1 = 100; - n2 = n1; - } - for(n=n1; n<=n2; n++) - { - ae_matrix_set_length(&xy, n-1+1, m+1, _state); - ae_vector_set_length(&xy0, n-1+1, _state); - ae_vector_set_length(&s, n-1+1, _state); - hstep = 0.001; - noiselevel = 0.2; - - /* - * Prepare task - */ - if( tasktype==0 ) - { - for(i=0; i<=n-1; i++) - { - xy.ptr.pp_double[i][0] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=n-1; i++) - { - for(j=1; j<=m-1; j++) - { - xy.ptr.pp_double[i][j] = xy.ptr.pp_double[i][0]*xy.ptr.pp_double[i][j-1]; - } - } - sinshift = ae_randomreal(_state)*ae_pi; - for(i=0; i<=n-1; i++) - { - xy0.ptr.p_double[i] = ae_sin(sinshift+ae_pi*0.5*(xy.ptr.pp_double[i][0]+1), _state); - xy.ptr.pp_double[i][m] = xy0.ptr.p_double[i]+noiselevel*testlinregunit_generatenormal((double)(0), (double)(1), _state); - } - } - if( tasktype==1 ) - { - ae_assert(m==9, "Assertion failed", _state); - ae_vector_set_length(&ta, 8+1, _state); - ta.ptr.p_double[0] = (double)(1); - ta.ptr.p_double[1] = (double)(2); - ta.ptr.p_double[2] = (double)(3); - ta.ptr.p_double[3] = 0.25; - ta.ptr.p_double[4] = 0.5; - ta.ptr.p_double[5] = 0.75; - ta.ptr.p_double[6] = 0.06; - ta.ptr.p_double[7] = 0.12; - ta.ptr.p_double[8] = 0.18; - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - xy.ptr.pp_double[i][j] = (double)(0); - } - xy.ptr.pp_double[i][0+i%3] = (double)(1); - xy.ptr.pp_double[i][3+i/3%3] = (double)(1); - xy.ptr.pp_double[i][6+i/9%3] = (double)(1); - v = ae_v_dotproduct(&xy.ptr.pp_double[i][0], 1, &ta.ptr.p_double[0], 1, ae_v_len(0,8)); - xy0.ptr.p_double[i] = v; - xy.ptr.pp_double[i][m] = v+noiselevel*testlinregunit_generatenormal((double)(0), (double)(1), _state); - } - } - if( tasktype==2||tasktype==3 ) - { - ae_assert(m==9, "Assertion failed", _state); - ae_vector_set_length(&ta, 8+1, _state); - ta.ptr.p_double[0] = (double)(1); - ta.ptr.p_double[1] = (double)(-2); - ta.ptr.p_double[2] = (double)(3); - ta.ptr.p_double[3] = 0.25; - ta.ptr.p_double[4] = -0.5; - ta.ptr.p_double[5] = 0.75; - ta.ptr.p_double[6] = -0.06; - ta.ptr.p_double[7] = 0.12; - ta.ptr.p_double[8] = -0.18; - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - if( tasktype==2 ) - { - xy.ptr.pp_double[i][j] = 1+testlinregunit_generatenormal((double)(0), (double)(3), _state); - } - else - { - xy.ptr.pp_double[i][j] = 1+testlinregunit_generatenormal((double)(0), 0.05, _state); - } - } - v = ae_v_dotproduct(&xy.ptr.pp_double[i][0], 1, &ta.ptr.p_double[0], 1, ae_v_len(0,8)); - xy0.ptr.p_double[i] = v; - xy.ptr.pp_double[i][m] = v+noiselevel*testlinregunit_generatenormal((double)(0), (double)(1), _state); - } - } - for(i=0; i<=n-1; i++) - { - s.ptr.p_double[i] = 1+ae_randomreal(_state); - } - - /* - * Solve (using S-variant, non-S-variant is not tested) - */ - if( modeltype==0 ) - { - lrbuilds(&xy, &s, n, m, &info, &wt, &ar, _state); - } - else - { - lrbuildzs(&xy, &s, n, m, &info, &wt, &ar, _state); - } - if( info!=1 ) - { - grconverrors = ae_true; - continue; - } - lrunpack(&wt, &tmpweights, &tmpi, _state); - - /* - * LRProcess test - */ - ae_vector_set_length(&x, m-1+1, _state); - v = tmpweights.ptr.p_double[m]; - for(i=0; i<=m-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - v = v+tmpweights.ptr.p_double[i]*x.ptr.p_double[i]; - } - grothererrors = grothererrors||ae_fp_greater(ae_fabs(v-lrprocess(&wt, &x, _state), _state)/ae_maxreal(ae_fabs(v, _state), (double)(1), _state),threshold); - - /* - * LRPack test - */ - lrpack(&tmpweights, m, &wt2, _state); - ae_vector_set_length(&x, m-1+1, _state); - for(i=0; i<=m-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - v = lrprocess(&wt, &x, _state); - grothererrors = grothererrors||ae_fp_greater(ae_fabs(v-lrprocess(&wt2, &x, _state), _state)/ae_fabs(v, _state),threshold); - - /* - * Optimality test - */ - for(k=0; k<=m; k++) - { - if( modeltype==1&&k==m ) - { - - /* - * 0-type models (with non-zero constant term) - * are tested for optimality of all coefficients. - * - * 1-type models (with zero constant term) - * are tested for optimality of non-constant terms only. - */ - continue; - } - f = (double)(0); - fp = (double)(0); - fm = (double)(0); - for(i=0; i<=n-1; i++) - { - v = tmpweights.ptr.p_double[m]; - for(j=0; j<=m-1; j++) - { - v = v+xy.ptr.pp_double[i][j]*tmpweights.ptr.p_double[j]; - } - f = f+ae_sqr((v-xy.ptr.pp_double[i][m])/s.ptr.p_double[i], _state); - if( kptr.pp_double[i][0] = xl+(xr-xl)*ae_randomreal(_state); - } - else - { - xy->ptr.pp_double[i][0] = xl+(xr-xl)*i/(n-1); - } - xy->ptr.pp_double[i][1] = ymin+(ymax-ymin)*ae_randomreal(_state); - s->ptr.p_double[i] = smin+(smax-smin)*ae_randomreal(_state); - } -} - - -/************************************************************************* -Task generation. -*************************************************************************/ -static void testlinregunit_generatetask(double a, - double b, - double xl, - double xr, - ae_bool randomx, - double smin, - double smax, - ae_int_t n, - /* Real */ ae_matrix* xy, - /* Real */ ae_vector* s, - ae_state *_state) -{ - ae_int_t i; - - - ae_matrix_set_length(xy, n-1+1, 1+1, _state); - ae_vector_set_length(s, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - if( randomx ) - { - xy->ptr.pp_double[i][0] = xl+(xr-xl)*ae_randomreal(_state); - } - else - { - xy->ptr.pp_double[i][0] = xl+(xr-xl)*i/(n-1); - } - s->ptr.p_double[i] = smin+(smax-smin)*ae_randomreal(_state); - xy->ptr.pp_double[i][1] = a+b*xy->ptr.pp_double[i][0]+testlinregunit_generatenormal((double)(0), s->ptr.p_double[i], _state); - } -} - - -/************************************************************************* -Task generation. -y[i] are filled based on A, B, X[I], S[I] -*************************************************************************/ -static void testlinregunit_filltaskwithy(double a, - double b, - ae_int_t n, - /* Real */ ae_matrix* xy, - /* Real */ ae_vector* s, - ae_state *_state) -{ - ae_int_t i; - - - for(i=0; i<=n-1; i++) - { - xy->ptr.pp_double[i][1] = a+b*xy->ptr.pp_double[i][0]+testlinregunit_generatenormal((double)(0), s->ptr.p_double[i], _state); - } -} - - -/************************************************************************* -Normal random numbers -*************************************************************************/ -static double testlinregunit_generatenormal(double mean, - double sigma, - ae_state *_state) -{ - double u; - double v; - double sum; - double result; - - - result = mean; - for(;;) - { - u = (2*ae_randominteger(2, _state)-1)*ae_randomreal(_state); - v = (2*ae_randominteger(2, _state)-1)*ae_randomreal(_state); - sum = u*u+v*v; - if( ae_fp_less(sum,(double)(1))&&ae_fp_greater(sum,(double)(0)) ) - { - sum = ae_sqrt(-2*ae_log(sum, _state)/sum, _state); - result = sigma*u*sum+mean; - break; - } - } - return result; -} - - -/************************************************************************* -Moments estimates and their errors -*************************************************************************/ -static void testlinregunit_calculatemv(/* Real */ ae_vector* x, - ae_int_t n, - double* mean, - double* means, - double* stddev, - double* stddevs, - ae_state *_state) -{ - ae_int_t i; - double v1; - double v2; - double variance; - - *mean = 0; - *means = 0; - *stddev = 0; - *stddevs = 0; - - *mean = (double)(0); - *means = (double)(1); - *stddev = (double)(0); - *stddevs = (double)(1); - variance = (double)(0); - if( n<=1 ) - { - return; - } - - /* - * Mean - */ - for(i=0; i<=n-1; i++) - { - *mean = *mean+x->ptr.p_double[i]; - } - *mean = *mean/n; - - /* - * Variance (using corrected two-pass algorithm) - */ - if( n!=1 ) - { - v1 = (double)(0); - for(i=0; i<=n-1; i++) - { - v1 = v1+ae_sqr(x->ptr.p_double[i]-(*mean), _state); - } - v2 = (double)(0); - for(i=0; i<=n-1; i++) - { - v2 = v2+(x->ptr.p_double[i]-(*mean)); - } - v2 = ae_sqr(v2, _state)/n; - variance = (v1-v2)/(n-1); - if( ae_fp_less(variance,(double)(0)) ) - { - variance = (double)(0); - } - *stddev = ae_sqrt(variance, _state); - } - - /* - * Errors - */ - *means = *stddev/ae_sqrt((double)(n), _state); - *stddevs = *stddev*ae_sqrt((double)(2), _state)/ae_sqrt((double)(n-1), _state); -} - - -/************************************************************************* -Unsets LR -*************************************************************************/ -static void testlinregunit_unsetlr(linearmodel* lr, ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix xy; - ae_int_t info; - lrreport rep; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _lrreport_init(&rep, _state, ae_true); - - ae_matrix_set_length(&xy, 5+1, 1+1, _state); - for(i=0; i<=5; i++) - { - xy.ptr.pp_double[i][0] = (double)(0); - xy.ptr.pp_double[i][1] = (double)(0); - } - lrbuild(&xy, 6, 1, &info, lr, &rep, _state); - ae_assert(info>0, "Assertion failed", _state); - ae_frame_leave(_state); -} - - - - - - - - -ae_bool testfilters(ae_bool silent, ae_state *_state) -{ - ae_bool waserrors; - ae_bool smaerrors; - ae_bool emaerrors; - ae_bool lrmaerrors; - ae_bool result; - - - smaerrors = testsma(ae_true, _state); - emaerrors = testema(ae_true, _state); - lrmaerrors = testlrma(ae_true, _state); - - /* - * Final report - */ - waserrors = (smaerrors||emaerrors)||lrmaerrors; - if( !silent ) - { - printf("FILTERS TEST\n"); - printf("* SMA: "); - if( !smaerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* EMA: "); - if( !emaerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* LRMA: "); - if( !lrmaerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST SUMMARY: FAILED\n"); - } - else - { - printf("TEST SUMMARY: PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - return result; -} - - -/************************************************************************* -This function tests SMA(k) filter. It returns True on error. - -Additional IsSilent parameter controls detailed error reporting. -*************************************************************************/ -ae_bool testsma(ae_bool issilent, ae_state *_state) -{ - ae_frame _frame_block; - ae_vector x; - ae_bool precomputederrors; - ae_bool zerohandlingerrors; - double threshold; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - - threshold = 1000*ae_machineepsilon; - if( !issilent ) - { - printf("SMA(K) TEST\n"); - } - - /* - * Test several pre-computed problems. - * - * NOTE: tests below rely on the fact that floating point - * additions and subtractions are exact when dealing - * with integer values. - */ - precomputederrors = ae_false; - ae_vector_set_length(&x, 1, _state); - x.ptr.p_double[0] = (double)(7); - filtersma(&x, 1, 1, _state); - precomputederrors = precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7)); - ae_vector_set_length(&x, 3, _state); - x.ptr.p_double[0] = (double)(7); - x.ptr.p_double[1] = (double)(8); - x.ptr.p_double[2] = (double)(9); - filtersma(&x, 3, 1, _state); - precomputederrors = ((precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7)))||ae_fp_neq(x.ptr.p_double[1],(double)(8)))||ae_fp_neq(x.ptr.p_double[2],(double)(9)); - filtersma(&x, 3, 2, _state); - precomputederrors = ((precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7)))||ae_fp_neq(x.ptr.p_double[1],7.5))||ae_fp_neq(x.ptr.p_double[2],8.5); - ae_vector_set_length(&x, 3, _state); - x.ptr.p_double[0] = (double)(7); - x.ptr.p_double[1] = (double)(8); - x.ptr.p_double[2] = (double)(9); - filtersma(&x, 3, 4, _state); - precomputederrors = ((precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7)))||ae_fp_neq(x.ptr.p_double[1],7.5))||ae_fp_neq(x.ptr.p_double[2],(double)(8)); - - /* - * Test zero-handling: - * a) when we have non-zero sequence (N1 elements) followed by zero sequence - * (N2 elements), then first N1+K-1 elements of the processed sequence are - * non-zero, but elements since (N1+K)th must be exactly zero. - * b) similar property holds for zero sequence followed by non-zero one - * - * Naive implementation of SMA does not have such property. - * - * NOTE: it is important to initialize X with non-integer elements with long - * binary mantissas, because this test tries to test behaviour in the presence - * of roundoff errors, and it will be useless when used with integer inputs. - */ - zerohandlingerrors = ae_false; - ae_vector_set_length(&x, 10, _state); - x.ptr.p_double[0] = ae_sqrt((double)(2), _state); - x.ptr.p_double[1] = ae_sqrt((double)(3), _state); - x.ptr.p_double[2] = ae_sqrt((double)(5), _state); - x.ptr.p_double[3] = ae_sqrt((double)(6), _state); - x.ptr.p_double[4] = ae_sqrt((double)(7), _state); - x.ptr.p_double[5] = (double)(0); - x.ptr.p_double[6] = (double)(0); - x.ptr.p_double[7] = (double)(0); - x.ptr.p_double[8] = (double)(0); - x.ptr.p_double[9] = (double)(0); - filtersma(&x, 10, 3, _state); - zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[0]-ae_sqrt((double)(2), _state), _state),threshold); - zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[1]-(ae_sqrt((double)(2), _state)+ae_sqrt((double)(3), _state))/2, _state),threshold); - zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[2]-(ae_sqrt((double)(2), _state)+ae_sqrt((double)(3), _state)+ae_sqrt((double)(5), _state))/3, _state),threshold); - zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[3]-(ae_sqrt((double)(3), _state)+ae_sqrt((double)(5), _state)+ae_sqrt((double)(6), _state))/3, _state),threshold); - zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[4]-(ae_sqrt((double)(5), _state)+ae_sqrt((double)(6), _state)+ae_sqrt((double)(7), _state))/3, _state),threshold); - zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[5]-(ae_sqrt((double)(6), _state)+ae_sqrt((double)(7), _state))/3, _state),threshold); - zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[6]-ae_sqrt((double)(7), _state)/3, _state),threshold); - zerohandlingerrors = zerohandlingerrors||ae_fp_neq(x.ptr.p_double[7],(double)(0)); - zerohandlingerrors = zerohandlingerrors||ae_fp_neq(x.ptr.p_double[8],(double)(0)); - zerohandlingerrors = zerohandlingerrors||ae_fp_neq(x.ptr.p_double[9],(double)(0)); - x.ptr.p_double[0] = (double)(0); - x.ptr.p_double[1] = (double)(0); - x.ptr.p_double[2] = (double)(0); - x.ptr.p_double[3] = (double)(0); - x.ptr.p_double[4] = (double)(0); - x.ptr.p_double[5] = ae_sqrt((double)(2), _state); - x.ptr.p_double[6] = ae_sqrt((double)(3), _state); - x.ptr.p_double[7] = ae_sqrt((double)(5), _state); - x.ptr.p_double[8] = ae_sqrt((double)(6), _state); - x.ptr.p_double[9] = ae_sqrt((double)(7), _state); - filtersma(&x, 10, 3, _state); - zerohandlingerrors = zerohandlingerrors||ae_fp_neq(x.ptr.p_double[0],(double)(0)); - zerohandlingerrors = zerohandlingerrors||ae_fp_neq(x.ptr.p_double[1],(double)(0)); - zerohandlingerrors = zerohandlingerrors||ae_fp_neq(x.ptr.p_double[2],(double)(0)); - zerohandlingerrors = zerohandlingerrors||ae_fp_neq(x.ptr.p_double[3],(double)(0)); - zerohandlingerrors = zerohandlingerrors||ae_fp_neq(x.ptr.p_double[4],(double)(0)); - zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[5]-ae_sqrt((double)(2), _state)/3, _state),threshold); - zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[6]-(ae_sqrt((double)(2), _state)+ae_sqrt((double)(3), _state))/3, _state),threshold); - zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[7]-(ae_sqrt((double)(2), _state)+ae_sqrt((double)(3), _state)+ae_sqrt((double)(5), _state))/3, _state),threshold); - zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[8]-(ae_sqrt((double)(3), _state)+ae_sqrt((double)(5), _state)+ae_sqrt((double)(6), _state))/3, _state),threshold); - zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[9]-(ae_sqrt((double)(5), _state)+ae_sqrt((double)(6), _state)+ae_sqrt((double)(7), _state))/3, _state),threshold); - - /* - * Final result - */ - result = precomputederrors||zerohandlingerrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function tests EMA(alpha) filter. It returns True on error. - -Additional IsSilent parameter controls detailed error reporting. -*************************************************************************/ -ae_bool testema(ae_bool issilent, ae_state *_state) -{ - ae_frame _frame_block; - ae_vector x; - ae_bool precomputederrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - - if( !issilent ) - { - printf("EMA(alpha) TEST\n"); - } - - /* - * Test several pre-computed problems. - * - * NOTE: tests below rely on the fact that floating point - * additions and subtractions are exact when dealing - * with integer values. - */ - precomputederrors = ae_false; - ae_vector_set_length(&x, 1, _state); - x.ptr.p_double[0] = (double)(7); - filterema(&x, 1, 1.0, _state); - precomputederrors = precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7)); - filterema(&x, 1, 0.5, _state); - precomputederrors = precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7)); - ae_vector_set_length(&x, 3, _state); - x.ptr.p_double[0] = (double)(7); - x.ptr.p_double[1] = (double)(8); - x.ptr.p_double[2] = (double)(9); - filterema(&x, 3, 1.0, _state); - precomputederrors = ((precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7)))||ae_fp_neq(x.ptr.p_double[1],(double)(8)))||ae_fp_neq(x.ptr.p_double[2],(double)(9)); - filterema(&x, 3, 0.5, _state); - precomputederrors = ((precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7)))||ae_fp_neq(x.ptr.p_double[1],7.5))||ae_fp_neq(x.ptr.p_double[2],8.25); - - /* - * Final result - */ - result = precomputederrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function tests LRMA(k) filter. It returns True on error. - -Additional IsSilent parameter controls detailed error reporting. -*************************************************************************/ -ae_bool testlrma(ae_bool issilent, ae_state *_state) -{ - ae_frame _frame_block; - ae_vector x; - ae_bool precomputederrors; - double threshold; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - - threshold = 1000*ae_machineepsilon; - if( !issilent ) - { - printf("LRMA(K) TEST\n"); - } - precomputederrors = ae_false; - - /* - * First, check that filter does not changes points for K=1 or K=2 - */ - ae_vector_set_length(&x, 1, _state); - x.ptr.p_double[0] = (double)(7); - filterlrma(&x, 1, 1, _state); - precomputederrors = precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7)); - ae_vector_set_length(&x, 6, _state); - x.ptr.p_double[0] = (double)(7); - x.ptr.p_double[1] = (double)(8); - x.ptr.p_double[2] = (double)(9); - x.ptr.p_double[3] = (double)(10); - x.ptr.p_double[4] = (double)(11); - x.ptr.p_double[5] = (double)(12); - filterlrma(&x, 6, 1, _state); - precomputederrors = (((((precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7)))||ae_fp_neq(x.ptr.p_double[1],(double)(8)))||ae_fp_neq(x.ptr.p_double[2],(double)(9)))||ae_fp_neq(x.ptr.p_double[3],(double)(10)))||ae_fp_neq(x.ptr.p_double[4],(double)(11)))||ae_fp_neq(x.ptr.p_double[5],(double)(12)); - filterlrma(&x, 6, 2, _state); - precomputederrors = (((((precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7)))||ae_fp_neq(x.ptr.p_double[1],(double)(8)))||ae_fp_neq(x.ptr.p_double[2],(double)(9)))||ae_fp_neq(x.ptr.p_double[3],(double)(10)))||ae_fp_neq(x.ptr.p_double[4],(double)(11)))||ae_fp_neq(x.ptr.p_double[5],(double)(12)); - - /* - * Check several precomputed problems - */ - ae_vector_set_length(&x, 6, _state); - x.ptr.p_double[0] = (double)(7); - x.ptr.p_double[1] = (double)(8); - x.ptr.p_double[2] = (double)(9); - x.ptr.p_double[3] = (double)(10); - x.ptr.p_double[4] = (double)(11); - x.ptr.p_double[5] = (double)(12); - filterlrma(&x, 6, 3, _state); - precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[0]-7, _state),threshold); - precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[1]-8, _state),threshold); - precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[2]-9, _state),threshold); - precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[3]-10, _state),threshold); - precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[4]-11, _state),threshold); - precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[5]-12, _state),threshold); - ae_vector_set_length(&x, 6, _state); - x.ptr.p_double[0] = (double)(7); - x.ptr.p_double[1] = (double)(8); - x.ptr.p_double[2] = (double)(8); - x.ptr.p_double[3] = (double)(9); - x.ptr.p_double[4] = (double)(12); - x.ptr.p_double[5] = (double)(12); - filterlrma(&x, 6, 3, _state); - precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[0]-7.0000000000, _state),1.0E-5); - precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[1]-8.0000000000, _state),1.0E-5); - precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[2]-8.1666666667, _state),1.0E-5); - precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[3]-8.8333333333, _state),1.0E-5); - precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[4]-11.6666666667, _state),1.0E-5); - precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[5]-12.5000000000, _state),1.0E-5); - - /* - * Final result - */ - result = precomputederrors; - ae_frame_leave(_state); - return result; -} - - - -static void testmcpdunit_testsimple(ae_bool* err, ae_state *_state); -static void testmcpdunit_testentryexit(ae_bool* err, ae_state *_state); -static void testmcpdunit_testec(ae_bool* err, ae_state *_state); -static void testmcpdunit_testbc(ae_bool* err, ae_state *_state); -static void testmcpdunit_testlc(ae_bool* err, ae_state *_state); -static void testmcpdunit_createee(ae_int_t n, - ae_int_t entrystate, - ae_int_t exitstate, - mcpdstate* s, - ae_state *_state); - - - - - -ae_bool testmcpd(ae_bool silent, ae_state *_state) -{ - ae_bool waserrors; - ae_bool simpleerrors; - ae_bool entryexiterrors; - ae_bool ecerrors; - ae_bool bcerrors; - ae_bool lcerrors; - ae_bool othererrors; - ae_bool result; - - - - /* - * Init - */ - waserrors = ae_false; - othererrors = ae_false; - simpleerrors = ae_false; - entryexiterrors = ae_false; - ecerrors = ae_false; - bcerrors = ae_false; - lcerrors = ae_false; - - /* - * Test - */ - testmcpdunit_testsimple(&simpleerrors, _state); - testmcpdunit_testentryexit(&entryexiterrors, _state); - testmcpdunit_testec(&ecerrors, _state); - testmcpdunit_testbc(&bcerrors, _state); - testmcpdunit_testlc(&lcerrors, _state); - - /* - * Final report - */ - waserrors = ((((othererrors||simpleerrors)||entryexiterrors)||ecerrors)||bcerrors)||lcerrors; - if( !silent ) - { - printf("MCPD TEST\n"); - printf("TOTAL RESULTS: "); - if( !waserrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* SIMPLE: "); - if( !simpleerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* ENTRY/EXIT: "); - if( !entryexiterrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* EQUALITY CONSTRAINTS: "); - if( !ecerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* BOUND CONSTRAINTS: "); - if( !bcerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* LINEAR CONSTRAINTS: "); - if( !lcerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* OTHER PROPERTIES: "); - if( !othererrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST SUMMARY: FAILED\n"); - } - else - { - printf("TEST SUMMARY: PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - return result; -} - - -/************************************************************************* -Simple test with no "entry"/"exit" states - -On failure sets Err to True (leaves it unchanged otherwise) -*************************************************************************/ -static void testmcpdunit_testsimple(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_matrix pexact; - ae_matrix xy; - double threshold; - ae_int_t i; - ae_int_t j; - double v; - double v0; - ae_matrix p; - mcpdstate s; - mcpdreport rep; - double offdiagonal; - - ae_frame_make(_state, &_frame_block); - memset(&pexact, 0, sizeof(pexact)); - memset(&xy, 0, sizeof(xy)); - memset(&p, 0, sizeof(p)); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_init(&pexact, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&p, 0, 0, DT_REAL, _state, ae_true); - _mcpdstate_init(&s, _state, ae_true); - _mcpdreport_init(&rep, _state, ae_true); - - threshold = 1.0E-2; - - /* - * First test: - * * N-dimensional problem - * * proportional data - * * no "entry"/"exit" states - * * N tracks, each includes only two states - * * first record in I-th track is [0 ... 1 ... 0] with 1 is in I-th position - * * all tracks are modelled using randomly generated transition matrix P - */ - for(n=1; n<=5; n++) - { - - /* - * Initialize "exact" P: - * * fill by random values - * * make sure that each column sums to non-zero value - * * normalize - */ - ae_matrix_set_length(&pexact, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - pexact.ptr.pp_double[i][j] = ae_randomreal(_state); - } - } - for(j=0; j<=n-1; j++) - { - i = ae_randominteger(n, _state); - pexact.ptr.pp_double[i][j] = pexact.ptr.pp_double[i][j]+0.1; - } - for(j=0; j<=n-1; j++) - { - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+pexact.ptr.pp_double[i][j]; - } - for(i=0; i<=n-1; i++) - { - pexact.ptr.pp_double[i][j] = pexact.ptr.pp_double[i][j]/v; - } - } - - /* - * Initialize solver: - * * create object - * * add tracks - */ - mcpdcreate(n, &s, _state); - for(i=0; i<=n-1; i++) - { - ae_matrix_set_length(&xy, 2, n, _state); - for(j=0; j<=n-1; j++) - { - xy.ptr.pp_double[0][j] = (double)(0); - } - xy.ptr.pp_double[0][i] = (double)(1); - for(j=0; j<=n-1; j++) - { - xy.ptr.pp_double[1][j] = pexact.ptr.pp_double[j][i]; - } - mcpdaddtrack(&s, &xy, 2, _state); - } - - /* - * Solve and test - */ - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - if( rep.terminationtype>0 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - *err = *err||ae_fp_greater(ae_fabs(p.ptr.pp_double[i][j]-pexact.ptr.pp_double[i][j], _state),threshold); - } - } - } - else - { - *err = ae_true; - } - } - - /* - * Second test: - * * N-dimensional problem - * * proportional data - * * no "entry"/"exit" states - * * N tracks, each includes only two states - * * first record in I-th track is [0 ...0.1 0.8 0.1 ... 0] with 0.8 is in I-th position - * * all tracks are modelled using randomly generated transition matrix P - */ - offdiagonal = 0.1; - for(n=1; n<=5; n++) - { - - /* - * Initialize "exact" P: - * * fill by random values - * * make sure that each column sums to non-zero value - * * normalize - */ - ae_matrix_set_length(&pexact, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - pexact.ptr.pp_double[i][j] = ae_randomreal(_state); - } - } - for(j=0; j<=n-1; j++) - { - i = ae_randominteger(n, _state); - pexact.ptr.pp_double[i][j] = pexact.ptr.pp_double[i][j]+0.1; - } - for(j=0; j<=n-1; j++) - { - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+pexact.ptr.pp_double[i][j]; - } - for(i=0; i<=n-1; i++) - { - pexact.ptr.pp_double[i][j] = pexact.ptr.pp_double[i][j]/v; - } - } - - /* - * Initialize solver: - * * create object - * * add tracks - */ - mcpdcreate(n, &s, _state); - for(i=0; i<=n-1; i++) - { - ae_matrix_set_length(&xy, 2, n, _state); - for(j=0; j<=n-1; j++) - { - xy.ptr.pp_double[0][j] = (double)(0); - } - - /* - * "main" element - */ - xy.ptr.pp_double[0][i] = 1.0-2*offdiagonal; - for(j=0; j<=n-1; j++) - { - xy.ptr.pp_double[1][j] = (1.0-2*offdiagonal)*pexact.ptr.pp_double[j][i]; - } - - /* - * off-diagonal ones - */ - if( i>0 ) - { - xy.ptr.pp_double[0][i-1] = offdiagonal; - for(j=0; j<=n-1; j++) - { - xy.ptr.pp_double[1][j] = xy.ptr.pp_double[1][j]+offdiagonal*pexact.ptr.pp_double[j][i-1]; - } - } - if( i0 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - *err = *err||ae_fp_greater(ae_fabs(p.ptr.pp_double[i][j]-pexact.ptr.pp_double[i][j], _state),threshold); - } - } - } - else - { - *err = ae_true; - } - } - - /* - * Third test: - * * N-dimensional problem - * * population data - * * no "entry"/"exit" states - * * N tracks, each includes only two states - * * first record in I-th track is V*[0 ...0.1 0.8 0.1 ... 0] with 0.8 is in I-th position, V in [1,10] - * * all tracks are modelled using randomly generated transition matrix P - */ - offdiagonal = 0.1; - for(n=1; n<=5; n++) - { - - /* - * Initialize "exact" P: - * * fill by random values - * * make sure that each column sums to non-zero value - * * normalize - */ - ae_matrix_set_length(&pexact, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - pexact.ptr.pp_double[i][j] = ae_randomreal(_state); - } - } - for(j=0; j<=n-1; j++) - { - i = ae_randominteger(n, _state); - pexact.ptr.pp_double[i][j] = pexact.ptr.pp_double[i][j]+0.1; - } - for(j=0; j<=n-1; j++) - { - v = (double)(0); - for(i=0; i<=n-1; i++) - { - v = v+pexact.ptr.pp_double[i][j]; - } - for(i=0; i<=n-1; i++) - { - pexact.ptr.pp_double[i][j] = pexact.ptr.pp_double[i][j]/v; - } - } - - /* - * Initialize solver: - * * create object - * * add tracks - */ - mcpdcreate(n, &s, _state); - for(i=0; i<=n-1; i++) - { - ae_matrix_set_length(&xy, 2, n, _state); - for(j=0; j<=n-1; j++) - { - xy.ptr.pp_double[0][j] = (double)(0); - } - - /* - * "main" element - */ - v0 = 9*ae_randomreal(_state)+1; - xy.ptr.pp_double[0][i] = v0*(1.0-2*offdiagonal); - for(j=0; j<=n-1; j++) - { - xy.ptr.pp_double[1][j] = v0*(1.0-2*offdiagonal)*pexact.ptr.pp_double[j][i]; - } - - /* - * off-diagonal ones - */ - if( i>0 ) - { - xy.ptr.pp_double[0][i-1] = v0*offdiagonal; - for(j=0; j<=n-1; j++) - { - xy.ptr.pp_double[1][j] = xy.ptr.pp_double[1][j]+v0*offdiagonal*pexact.ptr.pp_double[j][i-1]; - } - } - if( i0 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - *err = *err||ae_fp_greater(ae_fabs(p.ptr.pp_double[i][j]-pexact.ptr.pp_double[i][j], _state),threshold); - } - } - } - else - { - *err = ae_true; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Test for different combinations of "entry"/"exit" models - -On failure sets Err to True (leaves it unchanged otherwise) -*************************************************************************/ -static void testmcpdunit_testentryexit(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_matrix p; - ae_matrix pexact; - ae_matrix xy; - double threshold; - ae_int_t entrystate; - ae_int_t exitstate; - ae_int_t entrykind; - ae_int_t exitkind; - ae_int_t popkind; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - mcpdstate s; - mcpdreport rep; - - ae_frame_make(_state, &_frame_block); - memset(&p, 0, sizeof(p)); - memset(&pexact, 0, sizeof(pexact)); - memset(&xy, 0, sizeof(xy)); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_init(&p, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&pexact, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _mcpdstate_init(&s, _state, ae_true); - _mcpdreport_init(&rep, _state, ae_true); - - threshold = 1.0E-3; - - /* - * - */ - for(n=2; n<=5; n++) - { - for(entrykind=0; entrykind<=1; entrykind++) - { - for(exitkind=0; exitkind<=1; exitkind++) - { - for(popkind=0; popkind<=1; popkind++) - { - - /* - * Generate EntryState/ExitState such that one of the following is True: - * * EntryState<>ExitState - * * EntryState=-1 or ExitState=-1 - */ - do - { - if( entrykind==0 ) - { - entrystate = -1; - } - else - { - entrystate = ae_randominteger(n, _state); - } - if( exitkind==0 ) - { - exitstate = -1; - } - else - { - exitstate = ae_randominteger(n, _state); - } - } - while(!((entrystate==-1||exitstate==-1)||entrystate!=exitstate)); - - /* - * Generate transition matrix P such that: - * * columns corresponding to non-exit states sums to 1.0 - * * columns corresponding to exit states sums to 0.0 - * * rows corresponding to entry states are zero - */ - ae_matrix_set_length(&pexact, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - pexact.ptr.pp_double[i][j] = (double)(1+ae_randominteger(5, _state)); - if( i==entrystate ) - { - pexact.ptr.pp_double[i][j] = 0.0; - } - if( j==exitstate ) - { - pexact.ptr.pp_double[i][j] = 0.0; - } - } - } - for(j=0; j<=n-1; j++) - { - v = 0.0; - for(i=0; i<=n-1; i++) - { - v = v+pexact.ptr.pp_double[i][j]; - } - if( ae_fp_neq(v,(double)(0)) ) - { - for(i=0; i<=n-1; i++) - { - pexact.ptr.pp_double[i][j] = pexact.ptr.pp_double[i][j]/v; - } - } - } - - /* - * Create MCPD solver - */ - if( entrystate<0&&exitstate<0 ) - { - mcpdcreate(n, &s, _state); - } - if( entrystate>=0&&exitstate<0 ) - { - mcpdcreateentry(n, entrystate, &s, _state); - } - if( entrystate<0&&exitstate>=0 ) - { - mcpdcreateexit(n, exitstate, &s, _state); - } - if( entrystate>=0&&exitstate>=0 ) - { - mcpdcreateentryexit(n, entrystate, exitstate, &s, _state); - } - - /* - * Add N tracks. - * - * K-th track starts from vector with large value of - * K-th component and small random noise in other components. - * - * Track contains from 2 to 4 elements. - * - * Tracks contain proportional (normalized) or - * population data, depending on PopKind variable. - */ - for(k=0; k<=n-1; k++) - { - - /* - * Generate track whose length is in 2..4 - */ - ae_matrix_set_length(&xy, 2+ae_randominteger(3, _state), n, _state); - for(j=0; j<=n-1; j++) - { - xy.ptr.pp_double[0][j] = 0.05*ae_randomreal(_state); - } - xy.ptr.pp_double[0][k] = 1+ae_randomreal(_state); - for(i=1; i<=xy.rows-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( j!=entrystate ) - { - v = ae_v_dotproduct(&pexact.ptr.pp_double[j][0], 1, &xy.ptr.pp_double[i-1][0], 1, ae_v_len(0,n-1)); - xy.ptr.pp_double[i][j] = v; - } - else - { - xy.ptr.pp_double[i][j] = ae_randomreal(_state); - } - } - } - - /* - * Normalize, if needed - */ - if( popkind==1 ) - { - for(i=0; i<=xy.rows-1; i++) - { - v = 0.0; - for(j=0; j<=n-1; j++) - { - v = v+xy.ptr.pp_double[i][j]; - } - if( ae_fp_greater(v,(double)(0)) ) - { - for(j=0; j<=n-1; j++) - { - xy.ptr.pp_double[i][j] = xy.ptr.pp_double[i][j]/v; - } - } - } - } - - /* - * Add track - */ - mcpdaddtrack(&s, &xy, xy.rows, _state); - } - - /* - * Solve and test - */ - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - if( rep.terminationtype>0 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - *err = *err||ae_fp_greater(ae_fabs(p.ptr.pp_double[i][j]-pexact.ptr.pp_double[i][j], _state),threshold); - } - } - } - else - { - *err = ae_true; - } - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Test equality constraints. - -On failure sets Err to True (leaves it unchanged otherwise) -*************************************************************************/ -static void testmcpdunit_testec(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_matrix p; - ae_matrix ec; - ae_matrix xy; - ae_int_t entrystate; - ae_int_t exitstate; - ae_int_t entrykind; - ae_int_t exitkind; - ae_int_t i; - ae_int_t j; - ae_int_t ic; - ae_int_t jc; - double vc; - mcpdstate s; - mcpdreport rep; - - ae_frame_make(_state, &_frame_block); - memset(&p, 0, sizeof(p)); - memset(&ec, 0, sizeof(ec)); - memset(&xy, 0, sizeof(xy)); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_init(&p, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ec, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _mcpdstate_init(&s, _state, ae_true); - _mcpdreport_init(&rep, _state, ae_true); - - - /* - * We try different problems with following properties: - * * N is large enough - we won't have problems with inconsistent constraints - * * first state is either "entry" or "normal" - * * last state is either "exit" or "normal" - * * we have one long random track - * - * We test several properties which are described in comments below - */ - for(n=4; n<=6; n++) - { - for(entrykind=0; entrykind<=1; entrykind++) - { - for(exitkind=0; exitkind<=1; exitkind++) - { - - /* - * Prepare problem - */ - if( entrykind==0 ) - { - entrystate = -1; - } - else - { - entrystate = 0; - } - if( exitkind==0 ) - { - exitstate = -1; - } - else - { - exitstate = n-1; - } - ae_matrix_set_length(&xy, 2*n, n, _state); - for(i=0; i<=xy.rows-1; i++) - { - for(j=0; j<=xy.cols-1; j++) - { - xy.ptr.pp_double[i][j] = ae_randomreal(_state); - } - } - - /* - * Test that single equality constraint on non-entry - * non-exit elements of P is satisfied. - * - * NOTE: this test needs N>=4 because smaller values - * can give us inconsistent constraints - */ - ae_assert(n>=4, "TestEC: expectation failed", _state); - ic = 1+ae_randominteger(n-2, _state); - jc = 1+ae_randominteger(n-2, _state); - vc = ae_randomreal(_state); - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - mcpdaddec(&s, ic, jc, vc, _state); - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - if( rep.terminationtype>0 ) - { - *err = *err||ae_fp_neq(p.ptr.pp_double[ic][jc],vc); - } - else - { - *err = ae_true; - } - - /* - * Test interaction with default "sum-to-one" constraint - * on columns of P. - * - * We set N-1 equality constraints on random non-exit column - * of P, which are inconsistent with this default constraint - * (sum will be greater that 1.0). - * - * Algorithm must detect inconsistency. - * - * NOTE: - * 1. we do not set constraints for the first element of - * the column, because this element may be constrained by - * "exit state" constraint. - * 2. this test needs N>=3 - */ - ae_assert(n>=3, "TestEC: expectation failed", _state); - jc = ae_randominteger(n-1, _state); - vc = 0.95; - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - for(i=1; i<=n-1; i++) - { - mcpdaddec(&s, i, jc, vc, _state); - } - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - *err = *err||rep.terminationtype!=-3; - - /* - * Test interaction with constrains on entry states. - * - * When model has entry state, corresponding row of P - * must be zero. We try to set two kinds of constraints - * on random element of this row: - * * zero equality constraint, which must be consistent - * * non-zero equality constraint, which must be inconsistent - */ - if( entrystate>=0 ) - { - jc = ae_randominteger(n, _state); - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - mcpdaddec(&s, entrystate, jc, 0.0, _state); - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - *err = *err||rep.terminationtype<=0; - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - mcpdaddec(&s, entrystate, jc, 0.5, _state); - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - *err = *err||rep.terminationtype!=-3; - } - - /* - * Test interaction with constrains on exit states. - * - * When model has exit state, corresponding column of P - * must be zero. We try to set two kinds of constraints - * on random element of this column: - * * zero equality constraint, which must be consistent - * * non-zero equality constraint, which must be inconsistent - */ - if( exitstate>=0 ) - { - ic = ae_randominteger(n, _state); - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - mcpdaddec(&s, ic, exitstate, 0.0, _state); - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - *err = *err||rep.terminationtype<=0; - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - mcpdaddec(&s, ic, exitstate, 0.5, _state); - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - *err = *err||rep.terminationtype!=-3; - } - - /* - * Test SetEC() call - we constrain subset of non-entry - * non-exit elements and test it. - */ - ae_assert(n>=4, "TestEC: expectation failed", _state); - ae_matrix_set_length(&ec, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - ec.ptr.pp_double[i][j] = _state->v_nan; - } - } - for(j=1; j<=n-2; j++) - { - ec.ptr.pp_double[1+ae_randominteger(n-2, _state)][j] = 0.1+0.1*ae_randomreal(_state); - } - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - mcpdsetec(&s, &ec, _state); - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - if( rep.terminationtype>0 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_isfinite(ec.ptr.pp_double[i][j], _state) ) - { - *err = *err||ae_fp_neq(p.ptr.pp_double[i][j],ec.ptr.pp_double[i][j]); - } - } - } - } - else - { - *err = ae_true; - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Test bound constraints. - -On failure sets Err to True (leaves it unchanged otherwise) -*************************************************************************/ -static void testmcpdunit_testbc(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_matrix p; - ae_matrix bndl; - ae_matrix bndu; - ae_matrix xy; - ae_int_t entrystate; - ae_int_t exitstate; - ae_int_t entrykind; - ae_int_t exitkind; - ae_int_t i; - ae_int_t j; - ae_int_t ic; - ae_int_t jc; - double vl; - double vu; - mcpdstate s; - mcpdreport rep; - - ae_frame_make(_state, &_frame_block); - memset(&p, 0, sizeof(p)); - memset(&bndl, 0, sizeof(bndl)); - memset(&bndu, 0, sizeof(bndu)); - memset(&xy, 0, sizeof(xy)); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_init(&p, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&bndl, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&bndu, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _mcpdstate_init(&s, _state, ae_true); - _mcpdreport_init(&rep, _state, ae_true); - - - /* - * We try different problems with following properties: - * * N is large enough - we won't have problems with inconsistent constraints - * * first state is either "entry" or "normal" - * * last state is either "exit" or "normal" - * * we have one long random track - * - * We test several properties which are described in comments below - */ - for(n=4; n<=6; n++) - { - for(entrykind=0; entrykind<=1; entrykind++) - { - for(exitkind=0; exitkind<=1; exitkind++) - { - - /* - * Prepare problem - */ - if( entrykind==0 ) - { - entrystate = -1; - } - else - { - entrystate = 0; - } - if( exitkind==0 ) - { - exitstate = -1; - } - else - { - exitstate = n-1; - } - ae_matrix_set_length(&xy, 2*n, n, _state); - for(i=0; i<=xy.rows-1; i++) - { - for(j=0; j<=xy.cols-1; j++) - { - xy.ptr.pp_double[i][j] = ae_randomreal(_state); - } - } - - /* - * Test that single bound constraint on non-entry - * non-exit elements of P is satisfied. - * - * NOTE 1: this test needs N>=4 because smaller values - * can give us inconsistent constraints - */ - ae_assert(n>=4, "TestBC: expectation failed", _state); - ic = 1+ae_randominteger(n-2, _state); - jc = 1+ae_randominteger(n-2, _state); - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - vl = 0.3*ae_randomreal(_state); - } - else - { - vl = _state->v_neginf; - } - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - vu = 0.5+0.3*ae_randomreal(_state); - } - else - { - vu = _state->v_posinf; - } - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - mcpdaddbc(&s, ic, jc, vl, vu, _state); - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - if( rep.terminationtype>0 ) - { - *err = *err||ae_fp_less(p.ptr.pp_double[ic][jc],vl); - *err = *err||ae_fp_greater(p.ptr.pp_double[ic][jc],vu); - } - else - { - *err = ae_true; - } - - /* - * Test interaction with default "sum-to-one" constraint - * on columns of P. - * - * We set N-1 bound constraints on random non-exit column - * of P, which are inconsistent with this default constraint - * (sum will be greater that 1.0). - * - * Algorithm must detect inconsistency. - * - * NOTE: - * 1. we do not set constraints for the first element of - * the column, because this element may be constrained by - * "exit state" constraint. - * 2. this test needs N>=3 - */ - ae_assert(n>=3, "TestEC: expectation failed", _state); - jc = ae_randominteger(n-1, _state); - vl = 0.85; - vu = 0.95; - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - for(i=1; i<=n-1; i++) - { - mcpdaddbc(&s, i, jc, vl, vu, _state); - } - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - *err = *err||rep.terminationtype!=-3; - - /* - * Test interaction with constrains on entry states. - * - * When model has entry state, corresponding row of P - * must be zero. We try to set two kinds of constraints - * on random element of this row: - * * bound constraint with zero lower bound, which must be consistent - * * bound constraint with non-zero lower bound, which must be inconsistent - */ - if( entrystate>=0 ) - { - jc = ae_randominteger(n, _state); - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - mcpdaddbc(&s, entrystate, jc, 0.0, 1.0, _state); - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - *err = *err||rep.terminationtype<=0; - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - mcpdaddbc(&s, entrystate, jc, 0.5, 1.0, _state); - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - *err = *err||rep.terminationtype!=-3; - } - - /* - * Test interaction with constrains on exit states. - * - * When model has exit state, corresponding column of P - * must be zero. We try to set two kinds of constraints - * on random element of this column: - * * bound constraint with zero lower bound, which must be consistent - * * bound constraint with non-zero lower bound, which must be inconsistent - */ - if( exitstate>=0 ) - { - ic = ae_randominteger(n, _state); - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - mcpdaddbc(&s, ic, exitstate, 0.0, 1.0, _state); - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - *err = *err||rep.terminationtype<=0; - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - mcpdaddbc(&s, ic, exitstate, 0.5, 1.0, _state); - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - *err = *err||rep.terminationtype!=-3; - } - - /* - * Test SetBC() call - we constrain subset of non-entry - * non-exit elements and test it. - */ - ae_assert(n>=4, "TestBC: expectation failed", _state); - ae_matrix_set_length(&bndl, n, n, _state); - ae_matrix_set_length(&bndu, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - bndl.ptr.pp_double[i][j] = _state->v_neginf; - bndu.ptr.pp_double[i][j] = _state->v_posinf; - } - } - for(j=1; j<=n-2; j++) - { - i = 1+ae_randominteger(n-2, _state); - bndl.ptr.pp_double[i][j] = 0.5-0.1*ae_randomreal(_state); - bndu.ptr.pp_double[i][j] = 0.5+0.1*ae_randomreal(_state); - } - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - mcpdsetbc(&s, &bndl, &bndu, _state); - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - if( rep.terminationtype>0 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - *err = *err||ae_fp_less(p.ptr.pp_double[i][j],bndl.ptr.pp_double[i][j]); - *err = *err||ae_fp_greater(p.ptr.pp_double[i][j],bndu.ptr.pp_double[i][j]); - } - } - } - else - { - *err = ae_true; - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Test bound constraints. - -On failure sets Err to True (leaves it unchanged otherwise) -*************************************************************************/ -static void testmcpdunit_testlc(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_matrix p; - ae_matrix c; - ae_matrix xy; - ae_vector ct; - ae_int_t entrystate; - ae_int_t exitstate; - ae_int_t entrykind; - ae_int_t exitkind; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t t; - ae_int_t jc; - double v; - double threshold; - mcpdstate s; - mcpdreport rep; - - ae_frame_make(_state, &_frame_block); - memset(&p, 0, sizeof(p)); - memset(&c, 0, sizeof(c)); - memset(&xy, 0, sizeof(xy)); - memset(&ct, 0, sizeof(ct)); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_init(&p, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ct, 0, DT_INT, _state, ae_true); - _mcpdstate_init(&s, _state, ae_true); - _mcpdreport_init(&rep, _state, ae_true); - - threshold = 1.0E5*ae_machineepsilon; - - /* - * We try different problems with following properties: - * * N is large enough - we won't have problems with inconsistent constraints - * * first state is either "entry" or "normal" - * * last state is either "exit" or "normal" - * * we have one long random track - * - * We test several properties which are described in comments below - */ - for(n=4; n<=6; n++) - { - for(entrykind=0; entrykind<=1; entrykind++) - { - for(exitkind=0; exitkind<=1; exitkind++) - { - - /* - * Prepare problem - */ - if( entrykind==0 ) - { - entrystate = -1; - } - else - { - entrystate = 0; - } - if( exitkind==0 ) - { - exitstate = -1; - } - else - { - exitstate = n-1; - } - ae_matrix_set_length(&xy, 2*n, n, _state); - for(i=0; i<=xy.rows-1; i++) - { - for(j=0; j<=xy.cols-1; j++) - { - xy.ptr.pp_double[i][j] = ae_randomreal(_state); - } - } - - /* - * Test that single linear equality/inequality constraint - * on non-entry non-exit elements of P is satisfied. - * - * NOTE 1: this test needs N>=4 because smaller values - * can give us inconsistent constraints - * NOTE 2: Constraints are generated is such a way that P=(1/N ... 1/N) - * is always feasible. It guarantees that there always exists - * at least one feasible point - * NOTE 3: If we have inequality constraint, we "shift" right part - * in order to make feasible some neighborhood of P=(1/N ... 1/N). - */ - ae_assert(n>=4, "TestLC: expectation failed", _state); - ae_matrix_set_length(&c, 1, n*n+1, _state); - ae_vector_set_length(&ct, 1, _state); - v = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ((i==0||i==n-1)||j==0)||j==n-1 ) - { - c.ptr.pp_double[0][i*n+j] = (double)(0); - } - else - { - c.ptr.pp_double[0][i*n+j] = ae_randomreal(_state); - v = v+c.ptr.pp_double[0][i*n+j]*((double)1/(double)n); - } - } - } - c.ptr.pp_double[0][n*n] = v; - ct.ptr.p_int[0] = ae_randominteger(3, _state)-1; - if( ct.ptr.p_int[0]<0 ) - { - c.ptr.pp_double[0][n*n] = c.ptr.pp_double[0][n*n]+0.1; - } - if( ct.ptr.p_int[0]>0 ) - { - c.ptr.pp_double[0][n*n] = c.ptr.pp_double[0][n*n]-0.1; - } - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - mcpdsetlc(&s, &c, &ct, 1, _state); - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - if( rep.terminationtype>0 ) - { - v = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = v+p.ptr.pp_double[i][j]*c.ptr.pp_double[0][i*n+j]; - } - } - if( ct.ptr.p_int[0]<0 ) - { - *err = *err||ae_fp_greater_eq(v,c.ptr.pp_double[0][n*n]+threshold); - } - if( ct.ptr.p_int[0]==0 ) - { - *err = *err||ae_fp_greater_eq(ae_fabs(v-c.ptr.pp_double[0][n*n], _state),threshold); - } - if( ct.ptr.p_int[0]>0 ) - { - *err = *err||ae_fp_less_eq(v,c.ptr.pp_double[0][n*n]-threshold); - } - } - else - { - *err = ae_true; - } - - /* - * Test interaction with default "sum-to-one" constraint - * on columns of P. - * - * We set linear constraint which has for "sum-to-X" on - * on random non-exit column of P. This constraint can be - * either consistent (X=1.0) or inconsistent (X<>1.0) with - * this default constraint. - * - * Algorithm must detect inconsistency. - * - * NOTE: - * 1. this test needs N>=2 - */ - ae_assert(n>=2, "TestLC: expectation failed", _state); - jc = ae_randominteger(n-1, _state); - ae_matrix_set_length(&c, 1, n*n+1, _state); - ae_vector_set_length(&ct, 1, _state); - for(i=0; i<=n*n-1; i++) - { - c.ptr.pp_double[0][i] = 0.0; - } - for(i=0; i<=n-1; i++) - { - c.ptr.pp_double[0][n*i+jc] = 1.0; - } - c.ptr.pp_double[0][n*n] = 1.0; - ct.ptr.p_int[0] = 0; - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - mcpdsetlc(&s, &c, &ct, 1, _state); - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - *err = *err||rep.terminationtype<=0; - c.ptr.pp_double[0][n*n] = 2.0; - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - mcpdsetlc(&s, &c, &ct, 1, _state); - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - *err = *err||rep.terminationtype!=-3; - - /* - * Test interaction with constrains on entry states. - * - * When model has entry state, corresponding row of P - * must be zero. We try to set two kinds of constraints - * on elements of this row: - * * sums-to-zero constraint, which must be consistent - * * sums-to-one constraint, which must be inconsistent - */ - if( entrystate>=0 ) - { - ae_matrix_set_length(&c, 1, n*n+1, _state); - ae_vector_set_length(&ct, 1, _state); - for(i=0; i<=n*n-1; i++) - { - c.ptr.pp_double[0][i] = 0.0; - } - for(j=0; j<=n-1; j++) - { - c.ptr.pp_double[0][n*entrystate+j] = 1.0; - } - ct.ptr.p_int[0] = 0; - c.ptr.pp_double[0][n*n] = 0.0; - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - mcpdsetlc(&s, &c, &ct, 1, _state); - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - *err = *err||rep.terminationtype<=0; - c.ptr.pp_double[0][n*n] = 1.0; - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - mcpdsetlc(&s, &c, &ct, 1, _state); - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - *err = *err||rep.terminationtype!=-3; - } - - /* - * Test interaction with constrains on exit states. - * - * When model has exit state, corresponding column of P - * must be zero. We try to set two kinds of constraints - * on elements of this column: - * * sums-to-zero constraint, which must be consistent - * * sums-to-one constraint, which must be inconsistent - */ - if( exitstate>=0 ) - { - ae_matrix_set_length(&c, 1, n*n+1, _state); - ae_vector_set_length(&ct, 1, _state); - for(i=0; i<=n*n-1; i++) - { - c.ptr.pp_double[0][i] = 0.0; - } - for(i=0; i<=n-1; i++) - { - c.ptr.pp_double[0][n*i+exitstate] = 1.0; - } - ct.ptr.p_int[0] = 0; - c.ptr.pp_double[0][n*n] = 0.0; - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - mcpdsetlc(&s, &c, &ct, 1, _state); - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - *err = *err||rep.terminationtype<=0; - c.ptr.pp_double[0][n*n] = 1.0; - testmcpdunit_createee(n, entrystate, exitstate, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - mcpdsetlc(&s, &c, &ct, 1, _state); - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - *err = *err||rep.terminationtype!=-3; - } - } - } - } - - /* - * Final test - we generate several random constraints and - * test SetLC() function. - * - * NOTES: - * - * 1. Constraints are generated is such a way that P=(1/N ... 1/N) - * is always feasible. It guarantees that there always exists - * at least one feasible point - * 2. For simplicity of the test we do not use entry/exit states - * in our model - */ - for(n=1; n<=4; n++) - { - for(k=1; k<=2*n; k++) - { - - /* - * Generate track - */ - ae_matrix_set_length(&xy, 2*n, n, _state); - for(i=0; i<=xy.rows-1; i++) - { - for(j=0; j<=xy.cols-1; j++) - { - xy.ptr.pp_double[i][j] = ae_randomreal(_state); - } - } - - /* - * Generate random constraints - */ - ae_matrix_set_length(&c, k, n*n+1, _state); - ae_vector_set_length(&ct, k, _state); - for(i=0; i<=k-1; i++) - { - - /* - * Generate constraint and its right part - */ - c.ptr.pp_double[i][n*n] = (double)(0); - for(j=0; j<=n*n-1; j++) - { - c.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - c.ptr.pp_double[i][n*n] = c.ptr.pp_double[i][n*n]+c.ptr.pp_double[i][j]*((double)1/(double)n); - } - ct.ptr.p_int[i] = ae_randominteger(3, _state)-1; - - /* - * If we have inequality constraint, we "shift" right part - * in order to make feasible some neighborhood of P=(1/N ... 1/N). - */ - if( ct.ptr.p_int[i]<0 ) - { - c.ptr.pp_double[i][n*n] = c.ptr.pp_double[i][n*n]+0.1; - } - if( ct.ptr.p_int[i]>0 ) - { - c.ptr.pp_double[i][n*n] = c.ptr.pp_double[i][n*n]-0.1; - } - } - - /* - * Test - */ - testmcpdunit_createee(n, -1, -1, &s, _state); - mcpdaddtrack(&s, &xy, xy.rows, _state); - mcpdsetlc(&s, &c, &ct, k, _state); - mcpdsolve(&s, _state); - mcpdresults(&s, &p, &rep, _state); - if( rep.terminationtype>0 ) - { - for(t=0; t<=k-1; t++) - { - v = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = v+p.ptr.pp_double[i][j]*c.ptr.pp_double[t][i*n+j]; - } - } - if( ct.ptr.p_int[t]<0 ) - { - *err = *err||ae_fp_greater_eq(v,c.ptr.pp_double[t][n*n]+threshold); - } - if( ct.ptr.p_int[t]==0 ) - { - *err = *err||ae_fp_greater_eq(ae_fabs(v-c.ptr.pp_double[t][n*n], _state),threshold); - } - if( ct.ptr.p_int[t]>0 ) - { - *err = *err||ae_fp_less_eq(v,c.ptr.pp_double[t][n*n]-threshold); - } - } - } - else - { - *err = ae_true; - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function is used to create MCPD object with arbitrary combination of -entry and exit states -*************************************************************************/ -static void testmcpdunit_createee(ae_int_t n, - ae_int_t entrystate, - ae_int_t exitstate, - mcpdstate* s, - ae_state *_state) -{ - - _mcpdstate_clear(s); - - if( entrystate<0&&exitstate<0 ) - { - mcpdcreate(n, s, _state); - } - if( entrystate>=0&&exitstate<0 ) - { - mcpdcreateentry(n, entrystate, s, _state); - } - if( entrystate<0&&exitstate>=0 ) - { - mcpdcreateexit(n, exitstate, s, _state); - } - if( entrystate>=0&&exitstate>=0 ) - { - mcpdcreateentryexit(n, entrystate, exitstate, s, _state); - } -} - - - -static void testmlpeunit_createensemble(mlpensemble* ensemble, - ae_int_t nkind, - double a1, - double a2, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t ec, - ae_state *_state); -static void testmlpeunit_unsetensemble(mlpensemble* ensemble, - ae_state *_state); -static void testmlpeunit_testinformational(ae_int_t nkind, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t ec, - ae_int_t passcount, - ae_bool* err, - ae_state *_state); -static void testmlpeunit_testprocessing(ae_int_t nkind, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t ec, - ae_int_t passcount, - ae_bool* err, - ae_state *_state); -static void testmlpeunit_testerr(ae_int_t nkind, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t ec, - ae_int_t passcount, - ae_int_t sizemin, - ae_int_t sizemax, - ae_bool* err, - ae_state *_state); - - - - - -ae_bool testmlpe(ae_bool silent, ae_state *_state) -{ - ae_bool waserrors; - ae_bool inferrors; - ae_bool procerrors; - ae_bool errerrors; - ae_int_t passcount; - ae_int_t maxn; - ae_int_t maxhid; - ae_int_t nf; - ae_int_t nl; - ae_int_t nhid1; - ae_int_t nhid2; - ae_int_t ec; - ae_int_t nkind; - ae_int_t sizemin; - ae_int_t sizemax; - ae_bool result; - - - waserrors = ae_false; - inferrors = ae_false; - procerrors = ae_false; - errerrors = ae_false; - passcount = 5; - maxn = 3; - maxhid = 3; - - /* - * General MLP ensembles tests - * These tests are performed with small dataset, whose size is in [0,10]. - * We test correctness of functions on small sets, but do not test code - * which splits large dataset into smaller chunks. - */ - sizemin = 0; - sizemax = 10; - for(nf=1; nf<=maxn; nf++) - { - for(nl=1; nl<=maxn; nl++) - { - for(nhid1=0; nhid1<=maxhid; nhid1++) - { - for(nhid2=0; nhid2<=maxhid; nhid2++) - { - for(nkind=0; nkind<=3; nkind++) - { - for(ec=1; ec<=3; ec++) - { - - /* - * Skip meaningless parameters combinations - */ - if( nkind==1&&nl<2 ) - { - continue; - } - if( nhid1==0&&nhid2!=0 ) - { - continue; - } - - /* - * Tests - */ - testmlpeunit_testinformational(nkind, nf, nhid1, nhid2, nl, ec, passcount, &inferrors, _state); - testmlpeunit_testprocessing(nkind, nf, nhid1, nhid2, nl, ec, passcount, &procerrors, _state); - testmlpeunit_testerr(nkind, nf, nhid1, nhid2, nl, ec, passcount, sizemin, sizemax, &errerrors, _state); - } - } - } - } - } - } - - /* - * Special tests on large datasets: test ability to correctly split - * work into smaller chunks. - */ - nf = 2; - nhid1 = 10; - nhid2 = 10; - nl = 2; - ec = 10; - sizemin = 1000; - sizemax = 1000; - testmlpeunit_testerr(0, nf, nhid1, nhid2, nl, ec, 1, sizemin, sizemax, &errerrors, _state); - - /* - * Final report - */ - waserrors = (inferrors||procerrors)||errerrors; - if( !silent ) - { - printf("MLP ENSEMBLE TEST\n"); - printf("INFORMATIONAL FUNCTIONS: "); - if( !inferrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("BASIC PROCESSING: "); - if( !procerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("ERROR FUNCTIONS: "); - if( !errerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST SUMMARY: FAILED\n"); - } - else - { - printf("TEST SUMMARY: PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - return result; -} - - -/************************************************************************* -Network creation -*************************************************************************/ -static void testmlpeunit_createensemble(mlpensemble* ensemble, - ae_int_t nkind, - double a1, - double a2, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t ec, - ae_state *_state) -{ - - - ae_assert(((nin>0&&nhid1>=0)&&nhid2>=0)&&nout>0, "CreateNetwork error", _state); - ae_assert(nhid1!=0||nhid2==0, "CreateNetwork error", _state); - ae_assert(nkind!=1||nout>=2, "CreateNetwork error", _state); - if( nhid1==0 ) - { - - /* - * No hidden layers - */ - if( nkind==0 ) - { - mlpecreate0(nin, nout, ec, ensemble, _state); - } - else - { - if( nkind==1 ) - { - mlpecreatec0(nin, nout, ec, ensemble, _state); - } - else - { - if( nkind==2 ) - { - mlpecreateb0(nin, nout, a1, a2, ec, ensemble, _state); - } - else - { - if( nkind==3 ) - { - mlpecreater0(nin, nout, a1, a2, ec, ensemble, _state); - } - } - } - } - return; - } - if( nhid2==0 ) - { - - /* - * One hidden layer - */ - if( nkind==0 ) - { - mlpecreate1(nin, nhid1, nout, ec, ensemble, _state); - } - else - { - if( nkind==1 ) - { - mlpecreatec1(nin, nhid1, nout, ec, ensemble, _state); - } - else - { - if( nkind==2 ) - { - mlpecreateb1(nin, nhid1, nout, a1, a2, ec, ensemble, _state); - } - else - { - if( nkind==3 ) - { - mlpecreater1(nin, nhid1, nout, a1, a2, ec, ensemble, _state); - } - } - } - } - return; - } - - /* - * Two hidden layers - */ - if( nkind==0 ) - { - mlpecreate2(nin, nhid1, nhid2, nout, ec, ensemble, _state); - } - else - { - if( nkind==1 ) - { - mlpecreatec2(nin, nhid1, nhid2, nout, ec, ensemble, _state); - } - else - { - if( nkind==2 ) - { - mlpecreateb2(nin, nhid1, nhid2, nout, a1, a2, ec, ensemble, _state); - } - else - { - if( nkind==3 ) - { - mlpecreater2(nin, nhid1, nhid2, nout, a1, a2, ec, ensemble, _state); - } - } - } - } -} - - -/************************************************************************* -Unsets network (initialize it to smallest network possible -*************************************************************************/ -static void testmlpeunit_unsetensemble(mlpensemble* ensemble, - ae_state *_state) -{ - - - mlpecreate0(1, 1, 1, ensemble, _state); -} - - -/************************************************************************* -Iformational functions test -*************************************************************************/ -static void testmlpeunit_testinformational(ae_int_t nkind, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t ec, - ae_int_t passcount, - ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - mlpensemble ensemble; - ae_int_t n1; - ae_int_t n2; - - ae_frame_make(_state, &_frame_block); - memset(&ensemble, 0, sizeof(ensemble)); - _mlpensemble_init(&ensemble, _state, ae_true); - - testmlpeunit_createensemble(&ensemble, nkind, -1.0, 1.0, nin, nhid1, nhid2, nout, ec, _state); - mlpeproperties(&ensemble, &n1, &n2, _state); - *err = (*err||n1!=nin)||n2!=nout; - ae_frame_leave(_state); -} - - -/************************************************************************* -Processing functions test -*************************************************************************/ -static void testmlpeunit_testprocessing(ae_int_t nkind, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t ec, - ae_int_t passcount, - ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - mlpensemble ensemble; - mlpensemble ensemble2; - double a1; - double a2; - ae_int_t pass; - ae_int_t rkind; - ae_int_t i; - ae_bool allsame; - ae_vector x1; - ae_vector x2; - ae_vector y1; - ae_vector y2; - ae_vector ra; - ae_vector ra2; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&ensemble, 0, sizeof(ensemble)); - memset(&ensemble2, 0, sizeof(ensemble2)); - memset(&x1, 0, sizeof(x1)); - memset(&x2, 0, sizeof(x2)); - memset(&y1, 0, sizeof(y1)); - memset(&y2, 0, sizeof(y2)); - memset(&ra, 0, sizeof(ra)); - memset(&ra2, 0, sizeof(ra2)); - _mlpensemble_init(&ensemble, _state, ae_true); - _mlpensemble_init(&ensemble2, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ra, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ra2, 0, DT_REAL, _state, ae_true); - - - /* - * Prepare network - */ - a1 = (double)(0); - a2 = (double)(0); - if( nkind==2 ) - { - a1 = 1000*ae_randomreal(_state)-500; - a2 = 2*ae_randomreal(_state)-1; - } - if( nkind==3 ) - { - a1 = 1000*ae_randomreal(_state)-500; - a2 = a1+(2*ae_randominteger(2, _state)-1)*(0.1+0.9*ae_randomreal(_state)); - } - - /* - * Initialize arrays - */ - ae_vector_set_length(&x1, nin-1+1, _state); - ae_vector_set_length(&x2, nin-1+1, _state); - ae_vector_set_length(&y1, nout-1+1, _state); - ae_vector_set_length(&y2, nout-1+1, _state); - - /* - * Main cycle: - * * Pass is a number of repeated test - * * RKind is a "replication kind": - * * RKind=0 means that we work with original ensemble - * * RKind=1 means that we work with replica created with MLPECopy() - * * RKind=2 means that we work with replica created with serialization/unserialization - */ - for(pass=1; pass<=passcount; pass++) - { - for(rkind=0; rkind<=2; rkind++) - { - - /* - * Create network, pass through replication in order to test that replicated network works correctly. - */ - testmlpeunit_createensemble(&ensemble, nkind, a1, a2, nin, nhid1, nhid2, nout, ec, _state); - if( rkind==1 ) - { - mlpecopy(&ensemble, &ensemble2, _state); - testmlpeunit_unsetensemble(&ensemble, _state); - mlpecopy(&ensemble2, &ensemble, _state); - testmlpeunit_unsetensemble(&ensemble2, _state); - } - if( rkind==2 ) - { - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - mlpealloc(&_local_serializer, &ensemble, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpeserialize(&_local_serializer, &ensemble, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpeunserialize(&_local_serializer, &ensemble2, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - testmlpeunit_unsetensemble(&ensemble, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - mlpealloc(&_local_serializer, &ensemble2, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpeserialize(&_local_serializer, &ensemble2, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpeunserialize(&_local_serializer, &ensemble, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - testmlpeunit_unsetensemble(&ensemble2, _state); - } - - /* - * Same inputs leads to same outputs - */ - for(i=0; i<=nin-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - for(i=0; i<=nout-1; i++) - { - y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - mlpeprocess(&ensemble, &x1, &y1, _state); - mlpeprocess(&ensemble, &x2, &y2, _state); - allsame = ae_true; - for(i=0; i<=nout-1; i++) - { - allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]); - } - *err = *err||!allsame; - - /* - * Same inputs on original network leads to same outputs - * on copy created using MLPCopy - */ - testmlpeunit_unsetensemble(&ensemble2, _state); - mlpecopy(&ensemble, &ensemble2, _state); - for(i=0; i<=nin-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - for(i=0; i<=nout-1; i++) - { - y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - mlpeprocess(&ensemble, &x1, &y1, _state); - mlpeprocess(&ensemble2, &x2, &y2, _state); - allsame = ae_true; - for(i=0; i<=nout-1; i++) - { - allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]); - } - *err = *err||!allsame; - - /* - * Same inputs on original network leads to same outputs - * on copy created using MLPSerialize - */ - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - mlpealloc(&_local_serializer, &ensemble, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpeserialize(&_local_serializer, &ensemble, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - mlpeunserialize(&_local_serializer, &ensemble2, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - for(i=0; i<=nin-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - for(i=0; i<=nout-1; i++) - { - y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - mlpeprocess(&ensemble, &x1, &y1, _state); - mlpeprocess(&ensemble2, &x2, &y2, _state); - allsame = ae_true; - for(i=0; i<=nout-1; i++) - { - allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]); - } - *err = *err||!allsame; - - /* - * Different inputs leads to different outputs (non-zero network) - */ - for(i=0; i<=nin-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=nout-1; i++) - { - y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - y2.ptr.p_double[i] = y1.ptr.p_double[i]; - } - mlpeprocess(&ensemble, &x1, &y1, _state); - mlpeprocess(&ensemble, &x2, &y2, _state); - allsame = ae_true; - for(i=0; i<=nout-1; i++) - { - allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]); - } - *err = *err||allsame; - - /* - * Randomization changes outputs (when inputs are unchanged, non-zero network) - */ - for(i=0; i<=nin-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=nout-1; i++) - { - y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - y2.ptr.p_double[i] = y1.ptr.p_double[i]; - } - mlpecopy(&ensemble, &ensemble2, _state); - mlperandomize(&ensemble2, _state); - mlpeprocess(&ensemble, &x1, &y1, _state); - mlpeprocess(&ensemble2, &x1, &y2, _state); - allsame = ae_true; - for(i=0; i<=nout-1; i++) - { - allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]); - } - *err = *err||allsame; - - /* - * Normalization properties - */ - if( nkind==1 ) - { - - /* - * Classifier network outputs are normalized - */ - for(i=0; i<=nin-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - mlpeprocess(&ensemble, &x1, &y1, _state); - v = (double)(0); - for(i=0; i<=nout-1; i++) - { - v = v+y1.ptr.p_double[i]; - *err = *err||ae_fp_less(y1.ptr.p_double[i],(double)(0)); - } - *err = *err||ae_fp_greater(ae_fabs(v-1, _state),1000*ae_machineepsilon); - } - if( nkind==2 ) - { - - /* - * B-type network outputs are bounded from above/below - */ - for(i=0; i<=nin-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - mlpeprocess(&ensemble, &x1, &y1, _state); - for(i=0; i<=nout-1; i++) - { - if( ae_fp_greater_eq(a2,(double)(0)) ) - { - *err = *err||ae_fp_less(y1.ptr.p_double[i],a1); - } - else - { - *err = *err||ae_fp_greater(y1.ptr.p_double[i],a1); - } - } - } - if( nkind==3 ) - { - - /* - * R-type network outputs are within [A1,A2] (or [A2,A1]) - */ - for(i=0; i<=nin-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - mlpeprocess(&ensemble, &x1, &y1, _state); - for(i=0; i<=nout-1; i++) - { - *err = (*err||ae_fp_less(y1.ptr.p_double[i],ae_minreal(a1, a2, _state)))||ae_fp_greater(y1.ptr.p_double[i],ae_maxreal(a1, a2, _state)); - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Error functions - -Ensemble of type NKind is created, with NIn inputs, NHid1*NHid2 hidden -layers (one layer if NHid2=0), NOut outputs. PassCount random passes is -performed. Dataset has random size in [SizeMin,SizeMax]. -*************************************************************************/ -static void testmlpeunit_testerr(ae_int_t nkind, - ae_int_t nin, - ae_int_t nhid1, - ae_int_t nhid2, - ae_int_t nout, - ae_int_t ec, - ae_int_t passcount, - ae_int_t sizemin, - ae_int_t sizemax, - ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - mlpensemble ensemble; - sparsematrix sparsexy; - sparsematrix sparsexy2; - ae_int_t n1; - ae_int_t n2; - ae_int_t wcount; - double etol; - double escale; - double a1; - double a2; - ae_int_t pass; - ae_int_t i; - ae_int_t j; - ae_int_t ssize; - ae_matrix xy; - ae_matrix xy2; - ae_vector y; - ae_vector x1; - ae_vector y1; - ae_vector idx; - ae_vector dummy; - double refrmserror; - double refclserror; - double refavgce; - double refavgerror; - double refavgrelerror; - ae_int_t avgrelcnt; - modelerrors allerrors; - ae_int_t nnmax; - ae_int_t dsmax; - - ae_frame_make(_state, &_frame_block); - memset(&ensemble, 0, sizeof(ensemble)); - memset(&sparsexy, 0, sizeof(sparsexy)); - memset(&sparsexy2, 0, sizeof(sparsexy2)); - memset(&xy, 0, sizeof(xy)); - memset(&xy2, 0, sizeof(xy2)); - memset(&y, 0, sizeof(y)); - memset(&x1, 0, sizeof(x1)); - memset(&y1, 0, sizeof(y1)); - memset(&idx, 0, sizeof(idx)); - memset(&dummy, 0, sizeof(dummy)); - memset(&allerrors, 0, sizeof(allerrors)); - _mlpensemble_init(&ensemble, _state, ae_true); - _sparsematrix_init(&sparsexy, _state, ae_true); - _sparsematrix_init(&sparsexy2, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&idx, 0, DT_INT, _state, ae_true); - ae_vector_init(&dummy, 0, DT_INT, _state, ae_true); - _modelerrors_init(&allerrors, _state, ae_true); - - a1 = (double)(0); - a2 = (double)(0); - if( nkind==2 ) - { - a1 = 1000*ae_randomreal(_state)-500; - a2 = 2*ae_randomreal(_state)-1; - } - if( nkind==3 ) - { - a1 = 1000*ae_randomreal(_state)-500; - a2 = a1+(2*ae_randominteger(2, _state)-1)*(0.1+0.9*ae_randomreal(_state)); - } - testmlpeunit_createensemble(&ensemble, nkind, a1, a2, nin, nhid1, nhid2, nout, ec, _state); - mlpproperties(&ensemble.network, &n1, &n2, &wcount, _state); - etol = 1.0E-4; - escale = 1.0E-2; - - /* - * Initialize - */ - ae_vector_set_length(&x1, nin, _state); - ae_vector_set_length(&y, nout, _state); - ae_vector_set_length(&y1, nout, _state); - - /* - * Process - */ - for(pass=1; pass<=passcount; pass++) - { - - /* - * Randomize Ensemble, then re-randomaze weights manually. - * - * NOTE: weights magnitude is chosen to be small, about 0.1, - * which allows us to avoid oversaturated Ensemble. - * In 10% of cases we use zero weights. - */ - mlperandomize(&ensemble, _state); - if( ae_fp_less_eq(ae_randomreal(_state),0.1) ) - { - for(i=0; i<=wcount*ec-1; i++) - { - ensemble.weights.ptr.p_double[i] = 0.0; - } - } - else - { - for(i=0; i<=wcount*ec-1; i++) - { - ensemble.weights.ptr.p_double[i] = 0.2*ae_randomreal(_state)-0.1; - } - } - - /* - * Generate random dataset. - * Calculate reference errors. - * - * NOTE: about 10% of tests are performed with zero SSize - */ - ssize = sizemin+ae_randominteger(sizemax-sizemin+1, _state); - if( mlpeissoftmax(&ensemble, _state) ) - { - ae_matrix_set_length(&xy, ae_maxint(ssize, 1, _state), nin+1, _state); - sparsecreate(ae_maxint(ssize, 1, _state), nin+1, 0, &sparsexy, _state); - } - else - { - ae_matrix_set_length(&xy, ae_maxint(ssize, 1, _state), nin+nout, _state); - sparsecreate(ae_maxint(ssize, 1, _state), nin+nout, 0, &sparsexy, _state); - } - refrmserror = 0.0; - refclserror = 0.0; - refavgce = 0.0; - refavgerror = 0.0; - refavgrelerror = 0.0; - avgrelcnt = 0; - for(i=0; i<=ssize-1; i++) - { - - /* - * Fill I-th row - */ - for(j=0; j<=nin-1; j++) - { - x1.ptr.p_double[j] = 4*ae_randomreal(_state)-2; - sparseset(&sparsexy, i, j, x1.ptr.p_double[j], _state); - } - ae_v_move(&xy.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,nin-1)); - if( mlpeissoftmax(&ensemble, _state) ) - { - for(j=0; j<=nout-1; j++) - { - y1.ptr.p_double[j] = (double)(0); - } - xy.ptr.pp_double[i][nin] = (double)(ae_randominteger(nout, _state)); - sparseset(&sparsexy, i, nin, xy.ptr.pp_double[i][nin], _state); - y1.ptr.p_double[ae_round(xy.ptr.pp_double[i][nin], _state)] = (double)(1); - } - else - { - for(j=0; j<=nout-1; j++) - { - y1.ptr.p_double[j] = 4*ae_randomreal(_state)-2; - sparseset(&sparsexy, i, nin+j, y1.ptr.p_double[j], _state); - } - ae_v_move(&xy.ptr.pp_double[i][nin], 1, &y1.ptr.p_double[0], 1, ae_v_len(nin,nin+nout-1)); - } - - /* - * Process - */ - mlpeprocess(&ensemble, &x1, &y, _state); - - /* - * Update reference errors - */ - nnmax = 0; - if( mlpeissoftmax(&ensemble, _state) ) - { - if( ae_fp_greater(y.ptr.p_double[ae_round(xy.ptr.pp_double[i][nin], _state)],(double)(0)) ) - { - refavgce = refavgce+ae_log(1/y.ptr.p_double[ae_round(xy.ptr.pp_double[i][nin], _state)], _state); - } - else - { - refavgce = refavgce+ae_log(ae_maxrealnumber, _state); - } - } - if( mlpeissoftmax(&ensemble, _state) ) - { - dsmax = ae_round(xy.ptr.pp_double[i][nin], _state); - } - else - { - dsmax = 0; - } - for(j=0; j<=nout-1; j++) - { - refrmserror = refrmserror+ae_sqr(y.ptr.p_double[j]-y1.ptr.p_double[j], _state); - refavgerror = refavgerror+ae_fabs(y.ptr.p_double[j]-y1.ptr.p_double[j], _state); - if( ae_fp_neq(y1.ptr.p_double[j],(double)(0)) ) - { - refavgrelerror = refavgrelerror+ae_fabs(y.ptr.p_double[j]-y1.ptr.p_double[j], _state)/ae_fabs(y1.ptr.p_double[j], _state); - avgrelcnt = avgrelcnt+1; - } - if( ae_fp_greater(y.ptr.p_double[j],y.ptr.p_double[nnmax]) ) - { - nnmax = j; - } - if( !mlpeissoftmax(&ensemble, _state)&&ae_fp_greater(y1.ptr.p_double[j],y1.ptr.p_double[dsmax]) ) - { - dsmax = j; - } - } - if( nnmax!=dsmax ) - { - refclserror = refclserror+1; - } - } - sparseconverttocrs(&sparsexy, _state); - if( ssize>0 ) - { - refrmserror = ae_sqrt(refrmserror/(ssize*nout), _state); - refavgerror = refavgerror/(ssize*nout); - refavgce = refavgce/(ssize*ae_log((double)(2), _state)); - } - if( avgrelcnt>0 ) - { - refavgrelerror = refavgrelerror/avgrelcnt; - } - - /* - * Test "continuous" errors on full dataset - */ - seterrorflagdiff(err, mlpermserror(&ensemble, &xy, ssize, _state), refrmserror, etol, escale, _state); - seterrorflagdiff(err, mlpeavgce(&ensemble, &xy, ssize, _state), refavgce, etol, escale, _state); - seterrorflagdiff(err, mlpeavgerror(&ensemble, &xy, ssize, _state), refavgerror, etol, escale, _state); - seterrorflagdiff(err, mlpeavgrelerror(&ensemble, &xy, ssize, _state), refavgrelerror, etol, escale, _state); - } - ae_frame_leave(_state); -} - - - -static ae_bool testmlptrainunit_testmlptraines(ae_state *_state); -static ae_bool testmlptrainunit_testmlptrainregr(ae_state *_state); -static ae_bool testmlptrainunit_testmlpxorregr(ae_state *_state); -static ae_bool testmlptrainunit_testmlptrainclass(ae_state *_state); -static ae_bool testmlptrainunit_testmlpxorcls(ae_state *_state); -static ae_bool testmlptrainunit_testmlpzeroweights(ae_state *_state); -static ae_bool testmlptrainunit_testmlprestarts(ae_state *_state); -static ae_bool testmlptrainunit_testmlpcverror(ae_state *_state); -static ae_bool testmlptrainunit_testmlptrainens(ae_state *_state); -static ae_bool testmlptrainunit_testmlptrainensregr(ae_state *_state); -static ae_bool testmlptrainunit_testmlptrainenscls(ae_state *_state); - - - - - -ae_bool testmlptrain(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_bool waserrors; - ae_int_t info; - multilayerperceptron network; - multilayerperceptron network2; - mlpreport rep; - mlpcvreport cvrep; - ae_matrix xy; - ae_matrix valxy; - ae_bool trnerrors; - ae_bool mlpcverrorerr; - ae_bool mlptrainregrerr; - ae_bool mlptrainclasserr; - ae_bool mlprestartserr; - ae_bool mlpxorregrerr; - ae_bool mlpxorclserr; - ae_bool mlptrainenserrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&network, 0, sizeof(network)); - memset(&network2, 0, sizeof(network2)); - memset(&rep, 0, sizeof(rep)); - memset(&cvrep, 0, sizeof(cvrep)); - memset(&xy, 0, sizeof(xy)); - memset(&valxy, 0, sizeof(valxy)); - _multilayerperceptron_init(&network, _state, ae_true); - _multilayerperceptron_init(&network2, _state, ae_true); - _mlpreport_init(&rep, _state, ae_true); - _mlpcvreport_init(&cvrep, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&valxy, 0, 0, DT_REAL, _state, ae_true); - - waserrors = ae_false; - trnerrors = ae_false; - mlpcverrorerr = ae_false; - mlptrainregrerr = ae_false; - mlptrainclasserr = ae_false; - mlprestartserr = ae_false; - mlpxorregrerr = ae_false; - mlpxorclserr = ae_false; - mlptrainenserrors = ae_false; - - /* - * Test network training on simple XOR problem - */ - ae_matrix_set_length(&xy, 3+1, 2+1, _state); - xy.ptr.pp_double[0][0] = (double)(-1); - xy.ptr.pp_double[0][1] = (double)(-1); - xy.ptr.pp_double[0][2] = (double)(-1); - xy.ptr.pp_double[1][0] = (double)(1); - xy.ptr.pp_double[1][1] = (double)(-1); - xy.ptr.pp_double[1][2] = (double)(1); - xy.ptr.pp_double[2][0] = (double)(-1); - xy.ptr.pp_double[2][1] = (double)(1); - xy.ptr.pp_double[2][2] = (double)(1); - xy.ptr.pp_double[3][0] = (double)(1); - xy.ptr.pp_double[3][1] = (double)(1); - xy.ptr.pp_double[3][2] = (double)(-1); - mlpcreate1(2, 2, 1, &network, _state); - mlptrainlm(&network, &xy, 4, 0.001, 10, &info, &rep, _state); - trnerrors = trnerrors||ae_fp_greater(mlprmserror(&network, &xy, 4, _state),0.1); - - /* - * Test early stopping - */ - trnerrors = trnerrors||testmlptrainunit_testmlptraines(_state); - - /* - * Test for function MLPFoldCV() - */ - mlpcverrorerr = testmlptrainunit_testmlpcverror(_state); - - /* - * Test for training functions - */ - mlptrainregrerr = testmlptrainunit_testmlptrainregr(_state)||testmlptrainunit_testmlpzeroweights(_state); - mlptrainclasserr = testmlptrainunit_testmlptrainclass(_state); - mlprestartserr = testmlptrainunit_testmlprestarts(_state); - mlpxorregrerr = testmlptrainunit_testmlpxorregr(_state); - mlpxorclserr = testmlptrainunit_testmlpxorcls(_state); - - /* - * Training for ensembles - */ - mlptrainenserrors = (testmlptrainunit_testmlptrainens(_state)||testmlptrainunit_testmlptrainensregr(_state))||testmlptrainunit_testmlptrainenscls(_state); - - /* - * Final report - */ - waserrors = ((((((trnerrors||mlptrainregrerr)||mlptrainclasserr)||mlprestartserr)||mlpxorregrerr)||mlpxorclserr)||mlpcverrorerr)||mlptrainenserrors; - if( !silent ) - { - printf("MLP TEST\n"); - printf("CROSS-VALIDATION ERRORS: "); - if( !mlpcverrorerr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("TRAINING: "); - if( !trnerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("TRAIN -LM -LBFGS FOR REGRESSION: "); - if( mlptrainregrerr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("TRAIN -LM -LBFGS FOR CLASSIFIER: "); - if( mlptrainclasserr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("PARAMETER RESTARTS IN TRAIN -LBFGS: "); - if( mlprestartserr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("TRAINIG WITH TRAINER FOR REGRESSION: "); - if( mlpxorregrerr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("TRAINIG WITH TRAINER FOR CLASSIFIER: "); - if( mlpxorclserr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("TRAINING ENSEMBLES: "); - if( mlptrainenserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST SUMMARY: FAILED\n"); - } - else - { - printf("TEST SUMMARY: PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function tests MLPTrainES(). - -It returns True in case of errors, False when no errors were detected -*************************************************************************/ -static ae_bool testmlptrainunit_testmlptraines(ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t pass; - ae_int_t passcount; - multilayerperceptron network; - ae_matrix trnxy; - ae_matrix valxy; - ae_vector x; - ae_vector y; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_int_t nrestarts; - ae_int_t info; - mlpreport rep; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&network, 0, sizeof(network)); - memset(&trnxy, 0, sizeof(trnxy)); - memset(&valxy, 0, sizeof(valxy)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&rep, 0, sizeof(rep)); - _multilayerperceptron_init(&network, _state, ae_true); - ae_matrix_init(&trnxy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&valxy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - _mlpreport_init(&rep, _state, ae_true); - - result = ae_false; - - /* - * First test checks that MLPTrainES() - when training set is equal to the validation - * set, MLPTrainES() behaves just like a "normal" training algorithm. - * - * Test sequence: - * * generate training set - 100 random points from 2D square [-1,+1]*[-1,+1] - * * generate network with 2 inputs, no hidden layers, nonlinear output layer, - * use its outputs as target values for the test set - * * randomize network - * * train with MLPTrainES(), using original set as both training and validation set - * * trained network must reproduce training set with good precision - * - * NOTE: it is important to test algorithm on nonlinear network because linear - * problems converge too fast. Slow convergence is important to detect - * some kinds of bugs. - * - * NOTE: it is important to have NRestarts at least equal to 5, because with just - * one restart algorithm fails test about once in several thousands of passes. - */ - passcount = 10; - nrestarts = 5; - for(pass=1; pass<=passcount; pass++) - { - - /* - * Create network, generate training/validation sets - */ - mlpcreater0(2, 1, -2.0, 2.0, &network, _state); - mlprandomize(&network, _state); - n = 100; - ae_matrix_set_length(&trnxy, n, 3, _state); - ae_matrix_set_length(&valxy, n, 3, _state); - ae_vector_set_length(&x, 2, _state); - ae_vector_set_length(&y, 1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=1; j++) - { - trnxy.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - valxy.ptr.pp_double[i][j] = trnxy.ptr.pp_double[i][j]; - x.ptr.p_double[j] = trnxy.ptr.pp_double[i][j]; - } - mlpprocess(&network, &x, &y, _state); - trnxy.ptr.pp_double[i][2] = y.ptr.p_double[0]; - valxy.ptr.pp_double[i][2] = y.ptr.p_double[0]; - } - mlprandomize(&network, _state); - mlptraines(&network, &trnxy, n, &valxy, n, 0.0001, nrestarts, &info, &rep, _state); - if( info<=0 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - if( ae_fp_greater(ae_sqrt(mlperror(&network, &valxy, n, _state)/n, _state),0.01) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function tests MLPTrainLM, MLPTrainLBFGS and MLPTrainNetwork -functions for regression. It check that train functions work correctly. -Test use Create1 with 10 neurons. -Test function is f(x,y)=X^2+cos(3*Pi*y). -*************************************************************************/ -static ae_bool testmlptrainunit_testmlptrainregr(ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron net; - mlptrainer trainer; - mlpreport rep; - ae_int_t info; - ae_matrix xy; - sparsematrix sm; - ae_vector x; - ae_vector y; - ae_int_t n; - ae_int_t sn; - ae_int_t nneurons; - double vdecay; - double averr; - double st; - double eps; - double traineps; - ae_int_t nneedrest; - ae_int_t trainits; - ae_int_t shift; - ae_int_t i; - ae_int_t j; - ae_int_t vtrain; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&net, 0, sizeof(net)); - memset(&trainer, 0, sizeof(trainer)); - memset(&rep, 0, sizeof(rep)); - memset(&xy, 0, sizeof(xy)); - memset(&sm, 0, sizeof(sm)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - _multilayerperceptron_init(&net, _state, ae_true); - _mlptrainer_init(&trainer, _state, ae_true); - _mlpreport_init(&rep, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&sm, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - - eps = 0.01; - vdecay = 0.001; - nneurons = 10; - nneedrest = 5; - traineps = 1.0E-3; - trainits = 0; - sn = 5; - n = sn*sn; - st = (double)2/(double)(sn-1); - sparsecreate(n, 3, n*3, &sm, _state); - ae_matrix_set_length(&xy, n, 3, _state); - ae_vector_set_length(&x, 2, _state); - for(vtrain=0; vtrain<=3; vtrain++) - { - averr = (double)(0); - - /* - * Create a train set(uniformly distributed set of points). - */ - for(i=0; i<=sn-1; i++) - { - for(j=0; j<=sn-1; j++) - { - shift = i*sn+j; - xy.ptr.pp_double[shift][0] = i*st-1.0; - xy.ptr.pp_double[shift][1] = j*st-1.0; - xy.ptr.pp_double[shift][2] = xy.ptr.pp_double[shift][0]*xy.ptr.pp_double[shift][0]+ae_cos(3*ae_pi*xy.ptr.pp_double[shift][1], _state); - } - } - - /* - * Create and train a neural network - */ - mlpcreate1(2, nneurons, 1, &net, _state); - if( vtrain==0 ) - { - mlptrainlm(&net, &xy, n, vdecay, nneedrest, &info, &rep, _state); - } - if( vtrain==1 ) - { - mlptrainlbfgs(&net, &xy, n, vdecay, nneedrest, traineps, trainits, &info, &rep, _state); - } - - /* - * Train with trainer, using: - * * dense matrix; - */ - if( vtrain==2 ) - { - mlpcreatetrainer(2, 1, &trainer, _state); - mlpsetdataset(&trainer, &xy, n, _state); - mlpsetdecay(&trainer, vdecay, _state); - mlpsetcond(&trainer, traineps, trainits, _state); - mlptrainnetwork(&trainer, &net, nneedrest, &rep, _state); - } - - /* - * * sparse matrix. - */ - if( vtrain==3 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=2; j++) - { - sparseset(&sm, i, j, xy.ptr.pp_double[i][j], _state); - } - } - mlpcreatetrainer(2, 1, &trainer, _state); - mlpsetsparsedataset(&trainer, &sm, n, _state); - mlpsetdecay(&trainer, vdecay, _state); - mlpsetcond(&trainer, traineps, trainits, _state); - mlptrainnetwork(&trainer, &net, nneedrest, &rep, _state); - } - - /* - * Check that network is trained correctly - */ - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[0] = xy.ptr.pp_double[i][0]; - x.ptr.p_double[1] = xy.ptr.pp_double[i][1]; - mlpprocess(&net, &x, &y, _state); - - /* - * Calculate average error - */ - averr = averr+ae_fabs(y.ptr.p_double[0]-xy.ptr.pp_double[i][2], _state); - } - if( ae_fp_greater(averr/n,eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function tests MLPTrainNetwork/MLPStartTraining/MLPContinueTraining -functions for regression. It check that train functions work correctly. -Test use Create1 with 2 neurons. -Test function is XOR(x,y). -*************************************************************************/ -static ae_bool testmlptrainunit_testmlpxorregr(ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron net; - mlptrainer trainer; - mlpreport rep; - ae_matrix xy; - sparsematrix sm; - ae_vector x; - ae_vector y; - ae_int_t n; - ae_int_t sn; - ae_int_t nneurons; - double vdecay; - double averr; - double eps; - ae_int_t numxp; - double traineps; - ae_int_t nneedrest; - ae_int_t trainits; - ae_int_t shift; - ae_int_t i; - ae_int_t j; - ae_int_t vtrain; - ae_int_t xp; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&net, 0, sizeof(net)); - memset(&trainer, 0, sizeof(trainer)); - memset(&rep, 0, sizeof(rep)); - memset(&xy, 0, sizeof(xy)); - memset(&sm, 0, sizeof(sm)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - _multilayerperceptron_init(&net, _state, ae_true); - _mlptrainer_init(&trainer, _state, ae_true); - _mlpreport_init(&rep, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&sm, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - - eps = 0.01; - numxp = 15; - vdecay = 0.001; - nneurons = 3; - nneedrest = 1; - traineps = 1.0E-4; - trainits = 0; - sn = 2; - n = sn*sn; - sparsecreate(n, 3, n*3, &sm, _state); - ae_matrix_set_length(&xy, n, 3, _state); - ae_vector_set_length(&x, 2, _state); - for(xp=1; xp<=numxp; xp++) - { - for(vtrain=0; vtrain<=3; vtrain++) - { - averr = (double)(0); - - /* - * Create a train set(uniformly distributed set of points). - */ - for(i=0; i<=sn-1; i++) - { - for(j=0; j<=sn-1; j++) - { - shift = i*sn+j; - xy.ptr.pp_double[shift][0] = (double)(i); - xy.ptr.pp_double[shift][1] = (double)(j); - if( ae_fp_eq(xy.ptr.pp_double[shift][0],xy.ptr.pp_double[shift][1]) ) - { - xy.ptr.pp_double[shift][2] = (double)(0); - } - else - { - xy.ptr.pp_double[shift][2] = (double)(1); - } - } - } - - /* - * Create and train a neural network - */ - mlpcreate1(2, nneurons, 1, &net, _state); - - /* - * Train with trainer, using: - * * dense matrix; - */ - if( vtrain==0 ) - { - mlpcreatetrainer(2, 1, &trainer, _state); - mlpsetdataset(&trainer, &xy, n, _state); - mlpsetdecay(&trainer, vdecay, _state); - mlpsetcond(&trainer, traineps, trainits, _state); - mlptrainnetwork(&trainer, &net, nneedrest, &rep, _state); - } - if( vtrain==1 ) - { - mlpcreatetrainer(2, 1, &trainer, _state); - mlpsetdataset(&trainer, &xy, n, _state); - mlpsetdecay(&trainer, vdecay, _state); - mlpsetcond(&trainer, traineps, trainits, _state); - mlpstarttraining(&trainer, &net, ae_true, _state); - while(mlpcontinuetraining(&trainer, &net, _state)) - { - } - } - - /* - * * sparse matrix. - */ - if( vtrain==2 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=2; j++) - { - sparseset(&sm, i, j, xy.ptr.pp_double[i][j], _state); - } - } - mlpcreatetrainer(2, 1, &trainer, _state); - mlpsetsparsedataset(&trainer, &sm, n, _state); - mlpsetdecay(&trainer, vdecay, _state); - mlpsetcond(&trainer, traineps, trainits, _state); - mlptrainnetwork(&trainer, &net, nneedrest, &rep, _state); - } - if( vtrain==3 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=2; j++) - { - sparseset(&sm, i, j, xy.ptr.pp_double[i][j], _state); - } - } - mlpcreatetrainer(2, 1, &trainer, _state); - mlpsetsparsedataset(&trainer, &sm, n, _state); - mlpsetdecay(&trainer, vdecay, _state); - mlpsetcond(&trainer, traineps, trainits, _state); - mlpstarttraining(&trainer, &net, ae_true, _state); - while(mlpcontinuetraining(&trainer, &net, _state)) - { - } - } - - /* - * Check that network is trained correctly - */ - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[0] = xy.ptr.pp_double[i][0]; - x.ptr.p_double[1] = xy.ptr.pp_double[i][1]; - mlpprocess(&net, &x, &y, _state); - - /* - * Calculate average error - */ - averr = averr+ae_fabs(y.ptr.p_double[0]-xy.ptr.pp_double[i][2], _state); - } - if( ae_fp_greater(averr/n,eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function tests MLPTrainLM, MLPTrainLBFGS and MLPTrainNetwork -functions for classification problems. It check that train functions work -correctly when is used CreateC1 function. Here the network tries to -distinguish positive from negative numbers. -*************************************************************************/ -static ae_bool testmlptrainunit_testmlptrainclass(ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron net; - mlptrainer trainer; - mlpreport rep; - ae_int_t info; - ae_matrix xy; - sparsematrix sm; - ae_vector x; - ae_vector y; - ae_int_t n; - double vdecay; - double traineps; - ae_int_t nneedrest; - ae_int_t trainits; - double tmp; - double mnc; - double mxc; - ae_int_t nxp; - ae_int_t i; - ae_int_t rndind; - ae_int_t vtrain; - ae_int_t xp; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&net, 0, sizeof(net)); - memset(&trainer, 0, sizeof(trainer)); - memset(&rep, 0, sizeof(rep)); - memset(&xy, 0, sizeof(xy)); - memset(&sm, 0, sizeof(sm)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - _multilayerperceptron_init(&net, _state, ae_true); - _mlptrainer_init(&trainer, _state, ae_true); - _mlpreport_init(&rep, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&sm, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - - mnc = (double)(10); - mxc = (double)(11); - nxp = 15; - vdecay = 0.001; - nneedrest = 10; - traineps = 1.0E-4; - trainits = 0; - n = 100; - sparsecreate(n, 2, n*2, &sm, _state); - ae_vector_set_length(&x, 1, _state); - ae_matrix_set_length(&xy, n, 2, _state); - for(xp=1; xp<=nxp; xp++) - { - for(vtrain=0; vtrain<=3; vtrain++) - { - - /* - * Initialization: - * * create negative part of the set; - */ - for(i=0; i<=n/2-1; i++) - { - xy.ptr.pp_double[i][0] = -1*((mxc-mnc)*ae_randomreal(_state)+mnc); - xy.ptr.pp_double[i][1] = (double)(0); - } - - /* - * * create positive part of the set; - */ - for(i=n/2; i<=n-1; i++) - { - xy.ptr.pp_double[i][0] = (mxc-mnc)*ae_randomreal(_state)+mnc; - xy.ptr.pp_double[i][1] = (double)(1); - } - - /* - * * mix two parts. - */ - for(i=0; i<=n-1; i++) - { - do - { - rndind = ae_randominteger(n, _state); - } - while(rndind==i); - tmp = xy.ptr.pp_double[i][0]; - xy.ptr.pp_double[i][0] = xy.ptr.pp_double[rndind][0]; - xy.ptr.pp_double[rndind][0] = tmp; - tmp = xy.ptr.pp_double[i][1]; - xy.ptr.pp_double[i][1] = xy.ptr.pp_double[rndind][1]; - xy.ptr.pp_double[rndind][1] = tmp; - } - - /* - * Create and train a neural network - */ - mlpcreatec0(1, 2, &net, _state); - if( vtrain==0 ) - { - mlptrainlm(&net, &xy, n, vdecay, nneedrest, &info, &rep, _state); - } - if( vtrain==1 ) - { - mlptrainlbfgs(&net, &xy, n, vdecay, nneedrest, traineps, trainits, &info, &rep, _state); - } - - /* - * Train with trainer, using: - * * dense matrix; - */ - if( vtrain==2 ) - { - mlpcreatetrainercls(1, 2, &trainer, _state); - mlpsetdataset(&trainer, &xy, n, _state); - mlpsetdecay(&trainer, vdecay, _state); - mlpsetcond(&trainer, traineps, trainits, _state); - mlptrainnetwork(&trainer, &net, nneedrest, &rep, _state); - } - - /* - * * sparse matrix. - */ - if( vtrain==3 ) - { - for(i=0; i<=n-1; i++) - { - sparseset(&sm, i, 0, xy.ptr.pp_double[i][0], _state); - sparseset(&sm, i, 1, xy.ptr.pp_double[i][1], _state); - } - mlpcreatetrainercls(1, 2, &trainer, _state); - mlpsetsparsedataset(&trainer, &sm, n, _state); - mlpsetdecay(&trainer, vdecay, _state); - mlpsetcond(&trainer, traineps, trainits, _state); - mlptrainnetwork(&trainer, &net, nneedrest, &rep, _state); - } - - /* - * Test on training set - */ - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[0] = xy.ptr.pp_double[i][0]; - mlpprocess(&net, &x, &y, _state); - - /* - * Negative number has to be negative and - * positive number has to be positive. - */ - if( ((ae_fp_less(x.ptr.p_double[0],(double)(0))&&ae_fp_less(y.ptr.p_double[0],0.95))&&ae_fp_greater(y.ptr.p_double[1],0.05))||((ae_fp_greater_eq(x.ptr.p_double[0],(double)(0))&&ae_fp_greater(y.ptr.p_double[0],0.05))&&ae_fp_less(y.ptr.p_double[1],0.95)) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - - /* - * Test on random set - */ - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[0] = ae_pow((double)(-1), (double)(ae_randominteger(2, _state)), _state)*((mxc-mnc)*ae_randomreal(_state)+mnc); - mlpprocess(&net, &x, &y, _state); - if( ((ae_fp_less(x.ptr.p_double[0],(double)(0))&&ae_fp_less(y.ptr.p_double[0],0.95))&&ae_fp_greater(y.ptr.p_double[1],0.05))||((ae_fp_greater_eq(x.ptr.p_double[0],(double)(0))&&ae_fp_greater(y.ptr.p_double[0],0.05))&&ae_fp_less(y.ptr.p_double[1],0.95)) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function tests MLPTrainNetwork/MLPStartTraining/MLPContinueTraining -functions for classification problems. It check that train functions work -correctly when is used CreateC1 function. Here the network tries to -distinguish positive from negative numbers. -*************************************************************************/ -static ae_bool testmlptrainunit_testmlpxorcls(ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron net; - mlptrainer trainer; - mlpreport rep; - ae_matrix xy; - sparsematrix sm; - ae_vector x; - ae_vector y; - ae_int_t n; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - double e; - double ebest; - double v; - ae_vector wbest; - double vdecay; - double traineps; - ae_int_t nneurons; - ae_int_t nneedrest; - ae_int_t trainits; - ae_int_t nxp; - ae_int_t i; - ae_int_t vtrain; - ae_int_t xp; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&net, 0, sizeof(net)); - memset(&trainer, 0, sizeof(trainer)); - memset(&rep, 0, sizeof(rep)); - memset(&xy, 0, sizeof(xy)); - memset(&sm, 0, sizeof(sm)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&wbest, 0, sizeof(wbest)); - _multilayerperceptron_init(&net, _state, ae_true); - _mlptrainer_init(&trainer, _state, ae_true); - _mlpreport_init(&rep, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&sm, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wbest, 0, DT_REAL, _state, ae_true); - - nxp = 15; - nneurons = 3; - vdecay = 0.001; - nneedrest = 3; - traineps = 1.0E-4; - trainits = 0; - n = 4; - sparsecreate(n, 3, n*3, &sm, _state); - ae_vector_set_length(&x, 2, _state); - ae_matrix_set_length(&xy, n, 3, _state); - - /* - * Initialization: - */ - xy.ptr.pp_double[0][0] = (double)(0); - xy.ptr.pp_double[0][1] = (double)(0); - xy.ptr.pp_double[0][2] = (double)(0); - xy.ptr.pp_double[1][0] = (double)(0); - xy.ptr.pp_double[1][1] = (double)(1); - xy.ptr.pp_double[1][2] = (double)(1); - xy.ptr.pp_double[2][0] = (double)(1); - xy.ptr.pp_double[2][1] = (double)(0); - xy.ptr.pp_double[2][2] = (double)(1); - xy.ptr.pp_double[3][0] = (double)(1); - xy.ptr.pp_double[3][1] = (double)(1); - xy.ptr.pp_double[3][2] = (double)(0); - - /* - * Create a neural network - */ - mlpcreatec1(2, nneurons, 2, &net, _state); - mlpproperties(&net, &nin, &nout, &wcount, _state); - ae_vector_set_length(&wbest, wcount, _state); - - /* - * Test - */ - for(xp=1; xp<=nxp; xp++) - { - for(vtrain=0; vtrain<=3; vtrain++) - { - - /* - * Train with trainer, using: - * * dense matrix; - */ - if( vtrain==0 ) - { - mlpcreatetrainercls(2, 2, &trainer, _state); - mlpsetdataset(&trainer, &xy, n, _state); - mlpsetdecay(&trainer, vdecay, _state); - mlpsetcond(&trainer, traineps, trainits, _state); - mlptrainnetwork(&trainer, &net, nneedrest, &rep, _state); - } - if( vtrain==1 ) - { - mlpcreatetrainercls(2, 2, &trainer, _state); - mlpsetdataset(&trainer, &xy, n, _state); - mlpsetdecay(&trainer, vdecay, _state); - mlpsetcond(&trainer, traineps, trainits, _state); - ebest = ae_maxrealnumber; - for(i=1; i<=nneedrest; i++) - { - mlpstarttraining(&trainer, &net, ae_true, _state); - while(mlpcontinuetraining(&trainer, &net, _state)) - { - } - v = ae_v_dotproduct(&net.weights.ptr.p_double[0], 1, &net.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - e = mlperror(&net, &xy, n, _state)+0.5*vdecay*v; - - /* - * Compare with the best answer. - */ - if( ae_fp_less(e,ebest) ) - { - ae_v_move(&wbest.ptr.p_double[0], 1, &net.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - ebest = e; - } - } - - /* - * The best result - */ - ae_v_move(&net.weights.ptr.p_double[0], 1, &wbest.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - } - - /* - * * sparse matrix. - */ - if( vtrain==2 ) - { - for(i=0; i<=n-1; i++) - { - sparseset(&sm, i, 0, xy.ptr.pp_double[i][0], _state); - sparseset(&sm, i, 1, xy.ptr.pp_double[i][1], _state); - sparseset(&sm, i, 2, xy.ptr.pp_double[i][2], _state); - } - mlpcreatetrainercls(2, 2, &trainer, _state); - mlpsetsparsedataset(&trainer, &sm, n, _state); - mlpsetdecay(&trainer, vdecay, _state); - mlpsetcond(&trainer, traineps, trainits, _state); - mlptrainnetwork(&trainer, &net, nneedrest, &rep, _state); - } - if( vtrain==3 ) - { - for(i=0; i<=n-1; i++) - { - sparseset(&sm, i, 0, xy.ptr.pp_double[i][0], _state); - sparseset(&sm, i, 1, xy.ptr.pp_double[i][1], _state); - sparseset(&sm, i, 2, xy.ptr.pp_double[i][2], _state); - } - mlpcreatetrainercls(2, 2, &trainer, _state); - mlpsetsparsedataset(&trainer, &sm, n, _state); - mlpsetdecay(&trainer, vdecay, _state); - mlpsetcond(&trainer, traineps, trainits, _state); - ebest = ae_maxrealnumber; - for(i=1; i<=nneedrest; i++) - { - mlpstarttraining(&trainer, &net, ae_true, _state); - while(mlpcontinuetraining(&trainer, &net, _state)) - { - } - v = ae_v_dotproduct(&net.weights.ptr.p_double[0], 1, &net.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - e = mlperror(&net, &xy, n, _state)+0.5*vdecay*v; - - /* - * Compare with the best answer. - */ - if( ae_fp_less(e,ebest) ) - { - ae_v_move(&wbest.ptr.p_double[0], 1, &net.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - ebest = e; - } - } - - /* - * The best result - */ - ae_v_move(&net.weights.ptr.p_double[0], 1, &wbest.ptr.p_double[0], 1, ae_v_len(0,wcount-1)); - } - - /* - * Test on training set - */ - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[0] = xy.ptr.pp_double[i][0]; - x.ptr.p_double[1] = xy.ptr.pp_double[i][1]; - mlpprocess(&net, &x, &y, _state); - if( ((ae_fp_eq(x.ptr.p_double[0],x.ptr.p_double[1])&&ae_fp_less(y.ptr.p_double[0],0.95))&&ae_fp_greater(y.ptr.p_double[1],0.05))||((ae_fp_neq(x.ptr.p_double[0],x.ptr.p_double[1])&&ae_fp_greater(y.ptr.p_double[0],0.05))&&ae_fp_less(y.ptr.p_double[1],0.95)) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -The test check, that all weights are zero after training with trainer -using empty dataset(either zero size or is't used MLPSetDataSet function). -Test on regression and classification problems given by dense or sparse -matrix. - -NOTE: Result of the function is written in MLPTrainRegrErr variable in - unit test. -*************************************************************************/ -static ae_bool testmlptrainunit_testmlpzeroweights(ae_state *_state) -{ - ae_frame _frame_block; - mlptrainer trainer; - multilayerperceptron net; - mlpreport rep; - ae_int_t nin; - ae_int_t nout; - ae_int_t wcount; - ae_int_t mxnin; - ae_int_t mxnout; - double vdecay; - double traineps; - ae_int_t trainits; - ae_int_t nneedrest; - ae_matrix dds; - sparsematrix sds; - ae_bool iscls; - ae_bool issparse; - ae_int_t c; - ae_int_t n; - ae_int_t xp; - ae_int_t nxp; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&trainer, 0, sizeof(trainer)); - memset(&net, 0, sizeof(net)); - memset(&rep, 0, sizeof(rep)); - memset(&dds, 0, sizeof(dds)); - memset(&sds, 0, sizeof(sds)); - _mlptrainer_init(&trainer, _state, ae_true); - _multilayerperceptron_init(&net, _state, ae_true); - _mlpreport_init(&rep, _state, ae_true); - ae_matrix_init(&dds, 0, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&sds, _state, ae_true); - - mxnin = 10; - mxnout = 10; - vdecay = 1.0E-3; - nneedrest = 1; - traineps = 1.0E-3; - trainits = 0; - sparsecreate(1, 1, 0, &sds, _state); - sparseconverttocrs(&sds, _state); - nxp = 10; - for(xp=1; xp<=nxp; xp++) - { - c = ae_randominteger(2, _state); - iscls = c==1; - c = ae_randominteger(2, _state); - issparse = c==1; - - /* - * Create trainer and network - */ - if( !iscls ) - { - - /* - * Regression - */ - nin = ae_randominteger(mxnin, _state)+1; - nout = ae_randominteger(mxnout, _state)+1; - mlpcreatetrainer(nin, nout, &trainer, _state); - mlpcreate0(nin, nout, &net, _state); - } - else - { - - /* - * Classification - */ - nin = ae_randominteger(mxnin, _state)+1; - nout = ae_randominteger(mxnout, _state)+2; - mlpcreatetrainercls(nin, nout, &trainer, _state); - mlpcreatec0(nin, nout, &net, _state); - } - n = ae_randominteger(2, _state)-1; - if( n==0 ) - { - if( !issparse ) - { - mlpsetdataset(&trainer, &dds, n, _state); - } - else - { - mlpsetsparsedataset(&trainer, &sds, n, _state); - } - } - mlpsetdecay(&trainer, vdecay, _state); - mlpsetcond(&trainer, traineps, trainits, _state); - c = ae_randominteger(2, _state); - if( c==0 ) - { - mlpstarttraining(&trainer, &net, ae_true, _state); - while(mlpcontinuetraining(&trainer, &net, _state)) - { - } - } - if( c==1 ) - { - mlptrainnetwork(&trainer, &net, nneedrest, &rep, _state); - } - - /* - * Check weights - */ - mlpproperties(&net, &nin, &nout, &wcount, _state); - for(c=0; c<=wcount-1; c++) - { - if( ae_fp_neq(net.weights.ptr.p_double[c],(double)(0)) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function tests that increasing numbers of restarts lead to statistical -improvement quality of solution. -Neural network created by Create1(10 neurons) and trained by MLPTrainLBFGS. - -TEST's DISCRIPTION: - -Net0 - network trained with one restart (denoted as R1) -Net1 - network trained with more than one restart (denoted as Rn) - -We must refuse hypothesis that R1 equivalent to Rn. -Here Mean = N/2, Sigma = Sqrt(N)/2. - _ - | 0 - R1 worse than Rn; - ri = | - |_1 - Rn same or worse then R1. - -If Sum(ri)1 restarts. - */ - mlpproperties(&net1, &nin, &nout, &wcount1, _state); - e1 = ae_v_dotproduct(&net1.weights.ptr.p_double[0], 1, &net1.weights.ptr.p_double[0], 1, ae_v_len(0,wcount1-1)); - e1 = mlperrorn(&net1, &xy, n, _state)+0.5*vdecay*e1; - if( ae_fp_less_eq(e0,e1) ) - { - avval = avval+1; - } - } - if( ae_fp_less(mean-numsigma,avval) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -The function test function MLPKFoldCV. -*************************************************************************/ -static ae_bool testmlptrainunit_testmlpcverror(ae_state *_state) -{ - ae_frame _frame_block; - multilayerperceptron net; - mlptrainer trainer; - mlpreport rep; - mlpreport cvrep; - ae_int_t nin; - ae_int_t nout; - ae_int_t nneurons; - ae_int_t rowsz; - double decay; - double wstep; - ae_int_t maxits; - ae_int_t foldscount; - ae_int_t nneedrest; - sparsematrix sptrainingset; - ae_matrix trainingset; - ae_matrix testset; - ae_int_t npoints; - ae_int_t ntstpoints; - double mean; - double numsigma; - double diffms; - double tstrelclserror; - double tstavgce; - double tstrmserror; - double tstavgerror; - double tstavgrelerror; - ae_int_t r0; - ae_int_t r1; - ae_int_t r2; - ae_int_t r3; - ae_int_t r4; - ae_int_t ntest; - ae_int_t xp; - ae_int_t nxp; - ae_bool isregr; - ae_int_t issparse; - ae_int_t i; - ae_int_t j; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&net, 0, sizeof(net)); - memset(&trainer, 0, sizeof(trainer)); - memset(&rep, 0, sizeof(rep)); - memset(&cvrep, 0, sizeof(cvrep)); - memset(&sptrainingset, 0, sizeof(sptrainingset)); - memset(&trainingset, 0, sizeof(trainingset)); - memset(&testset, 0, sizeof(testset)); - _multilayerperceptron_init(&net, _state, ae_true); - _mlptrainer_init(&trainer, _state, ae_true); - _mlpreport_init(&rep, _state, ae_true); - _mlpreport_init(&cvrep, _state, ae_true); - _sparsematrix_init(&sptrainingset, _state, ae_true); - ae_matrix_init(&trainingset, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&testset, 0, 0, DT_REAL, _state, ae_true); - - decay = 1.0E-6; - wstep = 0.0; - foldscount = 5; - nneedrest = 1; - ntest = ae_randominteger(4, _state); - nxp = 1000; - maxits = 50; - nin = 1; - nout = 1; - npoints = 5; - ntstpoints = 100; - isregr = ae_true; - nneurons = 3; - if( ntest==1 ) - { - nxp = 1000; - maxits = 50; - nin = 1; - nout = 10; - npoints = 5; - ntstpoints = 100; - isregr = ae_true; - } - if( ntest==2 ) - { - nxp = 1000; - maxits = 50; - nin = 10; - nout = 1; - npoints = 20; - ntstpoints = 100; - isregr = ae_true; - } - if( ntest==3 ) - { - nxp = 2000; - maxits = 10; - nin = 1; - nneurons = 3; - nout = 3; - npoints = 10; - ntstpoints = 100; - isregr = ae_false; - } - mean = nxp/2.0; - numsigma = 5.0*ae_sqrt((double)(nxp), _state)/2.0; - diffms = mean-numsigma; - issparse = ae_randominteger(2, _state); - if( isregr ) - { - mlpcreate0(nin, nout, &net, _state); - mlpcreatetrainer(nin, nout, &trainer, _state); - } - else - { - mlpcreatec1(nin, nneurons, nout, &net, _state); - mlpcreatetrainercls(nin, nout, &trainer, _state); - } - mlpsetcond(&trainer, wstep, maxits, _state); - mlpsetdecay(&trainer, decay, _state); - if( isregr ) - { - rowsz = nin+nout; - } - else - { - rowsz = nin+1; - } - r0 = 0; - r1 = 0; - r2 = 0; - r3 = 0; - r4 = 0; - for(xp=1; xp<=nxp; xp++) - { - - /* - * Dense matrix - */ - if( issparse==0 ) - { - rmatrixsetlengthatleast(&trainingset, npoints, rowsz, _state); - - /* - * Create training set - */ - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nin-1; j++) - { - trainingset.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - if( isregr ) - { - for(i=0; i<=npoints-1; i++) - { - for(j=nin; j<=rowsz-1; j++) - { - trainingset.ptr.pp_double[i][j] = 2*ae_randomreal(_state)+1; - } - } - } - else - { - for(i=0; i<=npoints-1; i++) - { - for(j=nin; j<=rowsz-1; j++) - { - trainingset.ptr.pp_double[i][j] = (double)(ae_randominteger(nout, _state)); - } - } - } - mlpsetdataset(&trainer, &trainingset, npoints, _state); - } - - /* - * Sparse matrix - */ - if( issparse==1 ) - { - sparsecreate(npoints, rowsz, npoints*rowsz, &sptrainingset, _state); - - /* - * Create training set - */ - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nin-1; j++) - { - sparseset(&sptrainingset, i, j, 2*ae_randomreal(_state)-1, _state); - } - } - if( isregr ) - { - for(i=0; i<=npoints-1; i++) - { - for(j=nin; j<=rowsz-1; j++) - { - sparseset(&sptrainingset, i, j, 2*ae_randomreal(_state)+1, _state); - } - } - } - else - { - for(i=0; i<=npoints-1; i++) - { - for(j=nin; j<=rowsz-1; j++) - { - sparseset(&sptrainingset, i, j, (double)(ae_randominteger(nout, _state)), _state); - } - } - } - sparseconverttocrs(&sptrainingset, _state); - mlpsetsparsedataset(&trainer, &sptrainingset, npoints, _state); - } - rmatrixsetlengthatleast(&testset, ntstpoints, rowsz, _state); - - /* - * Create test set - */ - for(i=0; i<=ntstpoints-1; i++) - { - for(j=0; j<=nin-1; j++) - { - testset.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - if( isregr ) - { - for(i=0; i<=ntstpoints-1; i++) - { - for(j=nin; j<=rowsz-1; j++) - { - testset.ptr.pp_double[i][j] = 2*ae_randomreal(_state)+1; - } - } - } - else - { - for(i=0; i<=ntstpoints-1; i++) - { - for(j=nin; j<=rowsz-1; j++) - { - testset.ptr.pp_double[i][j] = (double)(ae_randominteger(nout, _state)); - } - } - } - mlptrainnetwork(&trainer, &net, nneedrest, &rep, _state); - tstrelclserror = (double)(0); - tstavgce = (double)(0); - tstrmserror = (double)(0); - tstavgerror = (double)(0); - tstavgrelerror = (double)(0); - if( !isregr ) - { - tstrelclserror = mlprelclserror(&net, &testset, ntstpoints, _state); - tstavgce = mlpavgce(&net, &testset, ntstpoints, _state); - } - tstrmserror = mlprmserror(&net, &testset, ntstpoints, _state); - tstavgerror = mlpavgerror(&net, &testset, ntstpoints, _state); - tstavgrelerror = mlpavgrelerror(&net, &testset, ntstpoints, _state); - - /* - * Cross-validation - */ - mlpkfoldcv(&trainer, &net, nneedrest, foldscount, &cvrep, _state); - if( !isregr ) - { - if( ae_fp_less(ae_fabs(tstrelclserror-rep.relclserror, _state),ae_fabs(tstrelclserror-cvrep.relclserror, _state)) ) - { - r0 = r0+1; - } - if( ae_fp_less(ae_fabs(tstavgce-rep.avgce, _state),ae_fabs(tstavgce-cvrep.avgce, _state)) ) - { - r1 = r1+1; - } - } - if( ae_fp_less(ae_fabs(tstrmserror-rep.rmserror, _state),ae_fabs(tstrmserror-cvrep.rmserror, _state)) ) - { - r2 = r2+1; - } - if( ae_fp_less(ae_fabs(tstavgerror-rep.avgerror, _state),ae_fabs(tstavgerror-cvrep.avgerror, _state)) ) - { - r3 = r3+1; - } - if( ae_fp_less(ae_fabs(tstavgrelerror-rep.avgrelerror, _state),ae_fabs(tstavgrelerror-cvrep.avgrelerror, _state)) ) - { - r4 = r4+1; - } - } - if( !isregr ) - { - if( ae_fp_less_eq(diffms,(double)(r0))||ae_fp_less_eq(diffms,(double)(r1)) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - if( (ae_fp_less_eq(diffms,(double)(r2))||ae_fp_less_eq(diffms,(double)(r3)))||ae_fp_less_eq(diffms,(double)(r4)) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Test FoldCV when no dataset was specified with - * MLPSetDataset/SetSparseDataset(), or subset with - * only one point was given. - * - * NPoints values: - * * -1 - don't set dataset with using MLPSetDataset..; - * * 0 - zero dataset; - * * 1 - dataset with one point. - */ - for(npoints=-1; npoints<=1; npoints++) - { - if( isregr ) - { - mlpcreatetrainer(nin, nout, &trainer, _state); - } - else - { - mlpcreatetrainercls(nin, nout, &trainer, _state); - } - if( npoints>-1 ) - { - if( issparse==0 ) - { - mlpsetdataset(&trainer, &trainingset, npoints, _state); - } - if( issparse==1 ) - { - mlpsetsparsedataset(&trainer, &sptrainingset, npoints, _state); - } - } - mlpkfoldcv(&trainer, &net, nneedrest, foldscount, &cvrep, _state); - if( ((((((ae_fp_neq(cvrep.relclserror,(double)(0))||ae_fp_neq(cvrep.avgce,(double)(0)))||ae_fp_neq(cvrep.rmserror,(double)(0)))||ae_fp_neq(cvrep.avgerror,(double)(0)))||ae_fp_neq(cvrep.avgrelerror,(double)(0)))||cvrep.ngrad!=0)||cvrep.nhess!=0)||cvrep.ncholesky!=0 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -The function tests functions for training ensembles: MLPEBaggingLM, -MLPEBaggingLBFGS. -*************************************************************************/ -static ae_bool testmlptrainunit_testmlptrainens(ae_state *_state) -{ - ae_frame _frame_block; - mlpensemble ensemble; - mlpreport rep; - mlpcvreport oobrep; - ae_int_t info; - ae_matrix xy; - ae_int_t nin; - ae_int_t nout; - ae_int_t npoints; - ae_int_t nhid; - ae_int_t algtype; - ae_int_t tasktype; - ae_int_t pass; - double e; - ae_int_t nless; - ae_int_t nall; - ae_int_t nclasses; - ae_int_t i; - ae_int_t j; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&ensemble, 0, sizeof(ensemble)); - memset(&rep, 0, sizeof(rep)); - memset(&oobrep, 0, sizeof(oobrep)); - memset(&xy, 0, sizeof(xy)); - _mlpensemble_init(&ensemble, _state, ae_true); - _mlpreport_init(&rep, _state, ae_true); - _mlpcvreport_init(&oobrep, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - - result = ae_false; - - /* - * network training must reduce error - * test on random regression task - */ - nin = 3; - nout = 2; - nhid = 5; - npoints = 100; - nless = 0; - nall = 0; - for(pass=1; pass<=10; pass++) - { - for(algtype=0; algtype<=1; algtype++) - { - for(tasktype=0; tasktype<=1; tasktype++) - { - if( tasktype==0 ) - { - ae_matrix_set_length(&xy, npoints, nin+nout, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nin+nout-1; j++) - { - xy.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - mlpecreate1(nin, nhid, nout, 1+ae_randominteger(3, _state), &ensemble, _state); - } - else - { - ae_matrix_set_length(&xy, npoints, nin+1, _state); - nclasses = 2+ae_randominteger(2, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nin-1; j++) - { - xy.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - xy.ptr.pp_double[i][nin] = (double)(ae_randominteger(nclasses, _state)); - } - mlpecreatec1(nin, nhid, nclasses, 1+ae_randominteger(3, _state), &ensemble, _state); - } - e = mlpermserror(&ensemble, &xy, npoints, _state); - if( algtype==0 ) - { - mlpebagginglm(&ensemble, &xy, npoints, 0.001, 1, &info, &rep, &oobrep, _state); - } - else - { - mlpebagginglbfgs(&ensemble, &xy, npoints, 0.001, 1, 0.01, 0, &info, &rep, &oobrep, _state); - } - if( info<0 ) - { - result = ae_true; - } - else - { - if( ae_fp_less(mlpermserror(&ensemble, &xy, npoints, _state),e) ) - { - nless = nless+1; - } - } - nall = nall+1; - } - } - } - result = result||ae_fp_greater((double)(nall-nless),0.3*nall); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Testing for functions MLPETrainES and MLPTrainEnsembleES on regression -problems. Returns TRUE for errors, FALSE for success. -*************************************************************************/ -static ae_bool testmlptrainunit_testmlptrainensregr(ae_state *_state) -{ - ae_frame _frame_block; - mlptrainer trainer; - mlpensemble netens; - mlpreport rep; - modelerrors repx; - ae_int_t info; - sparsematrix xytrainsp; - ae_matrix xytrain; - ae_matrix xytest; - ae_int_t nin; - ae_int_t nout; - ae_int_t nneurons; - ae_vector x; - ae_vector y; - double decay; - double wstep; - ae_int_t maxits; - ae_int_t nneedrest; - ae_int_t enssize; - double mnval; - double mxval; - ae_int_t ntrain; - ae_int_t ntest; - double avgerr; - ae_int_t issparse; - ae_int_t withtrainer; - double eps; - ae_int_t xp; - ae_int_t i; - ae_int_t j; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&trainer, 0, sizeof(trainer)); - memset(&netens, 0, sizeof(netens)); - memset(&rep, 0, sizeof(rep)); - memset(&repx, 0, sizeof(repx)); - memset(&xytrainsp, 0, sizeof(xytrainsp)); - memset(&xytrain, 0, sizeof(xytrain)); - memset(&xytest, 0, sizeof(xytest)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - _mlptrainer_init(&trainer, _state, ae_true); - _mlpensemble_init(&netens, _state, ae_true); - _mlpreport_init(&rep, _state, ae_true); - _modelerrors_init(&repx, _state, ae_true); - _sparsematrix_init(&xytrainsp, _state, ae_true); - ae_matrix_init(&xytrain, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xytest, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - - result = ae_false; - - /* - * This test checks ability to train ensemble on simple regression - * problem "f(x0,x1,x2,...) = x0 + x1 + x2 + ...". - */ - eps = 5.0E-2; - mnval = (double)(-1); - mxval = (double)(1); - ntrain = 40; - ntest = 20; - decay = 1.0E-3; - wstep = 1.0E-3; - maxits = 20; - nneedrest = 1; - nneurons = 20; - nout = 1; - enssize = 100; - for(xp=1; xp<=2; xp++) - { - nin = ae_randominteger(3, _state)+1; - rvectorsetlengthatleast(&x, nin, _state); - mlpcreatetrainer(nin, nout, &trainer, _state); - mlpsetdecay(&trainer, decay, _state); - mlpsetcond(&trainer, wstep, maxits, _state); - rmatrixsetlengthatleast(&xytrain, ntrain, nin+nout, _state); - rmatrixsetlengthatleast(&xytest, ntest, nin+nout, _state); - withtrainer = ae_randominteger(2, _state); - issparse = 0; - if( withtrainer==0 ) - { - issparse = 0; - } - if( withtrainer==1 ) - { - issparse = ae_randominteger(2, _state); - } - - /* - * Training set - */ - for(i=0; i<=ntrain-1; i++) - { - for(j=0; j<=nin-1; j++) - { - xytrain.ptr.pp_double[i][j] = (mxval-mnval)*ae_randomreal(_state)+mnval; - } - xytrain.ptr.pp_double[i][nin] = (double)(0); - for(j=0; j<=nin-1; j++) - { - xytrain.ptr.pp_double[i][nin] = xytrain.ptr.pp_double[i][nin]+xytrain.ptr.pp_double[i][j]; - } - } - if( withtrainer==1 ) - { - - /* - * Dense matrix - */ - if( issparse==0 ) - { - mlpsetdataset(&trainer, &xytrain, ntrain, _state); - } - - /* - * Sparse matrix - */ - if( issparse==1 ) - { - sparsecreate(ntrain, nin+nout, ntrain*(nin+nout), &xytrainsp, _state); - - /* - * Just copy dense matrix to sparse matrix(using SparseGet() is too expensive). - */ - for(i=0; i<=ntrain-1; i++) - { - for(j=0; j<=nin+nout-1; j++) - { - sparseset(&xytrainsp, i, j, xytrain.ptr.pp_double[i][j], _state); - } - } - sparseconverttocrs(&xytrainsp, _state); - mlpsetsparsedataset(&trainer, &xytrainsp, ntrain, _state); - } - } - - /* - * Test set - */ - for(i=0; i<=ntest-1; i++) - { - for(j=0; j<=nin-1; j++) - { - xytest.ptr.pp_double[i][j] = (mxval-mnval)*ae_randomreal(_state)+mnval; - } - xytest.ptr.pp_double[i][nin] = (double)(0); - for(j=0; j<=nin-1; j++) - { - xytest.ptr.pp_double[i][nin] = xytest.ptr.pp_double[i][nin]+xytest.ptr.pp_double[i][j]; - } - } - - /* - * Create ensemble - */ - mlpecreate1(nin, nneurons, nout, enssize, &netens, _state); - - /* - * Train ensembles: - * * without trainer; - */ - if( withtrainer==0 ) - { - mlpetraines(&netens, &xytrain, ntrain, decay, nneedrest, &info, &rep, _state); - } - - /* - * * with trainer. - */ - if( withtrainer==1 ) - { - mlptrainensemblees(&trainer, &netens, nneedrest, &rep, _state); - } - - /* - * Test that Rep contains correct error values - */ - mlpeallerrorsx(&netens, &xytrain, &xytrainsp, ntrain, 0, &netens.network.dummyidx, 0, ntrain, 0, &netens.network.buf, &repx, _state); - seterrorflagdiff(&result, rep.relclserror, repx.relclserror, 1.0E-4, 1.0E-2, _state); - seterrorflagdiff(&result, rep.avgce, repx.avgce, 1.0E-4, 1.0E-2, _state); - seterrorflagdiff(&result, rep.rmserror, repx.rmserror, 1.0E-4, 1.0E-2, _state); - seterrorflagdiff(&result, rep.avgerror, repx.avgerror, 1.0E-4, 1.0E-2, _state); - seterrorflagdiff(&result, rep.avgrelerror, repx.avgrelerror, 1.0E-4, 1.0E-2, _state); - - /* - * Test that network fits data well. Calculate average error: - * * on training dataset; - * * on test dataset. (here we reduce the accuracy - * requirements - average error is compared with 2*Eps). - */ - avgerr = (double)(0); - for(i=0; i<=ntrain-1; i++) - { - if( issparse==0 ) - { - ae_v_move(&x.ptr.p_double[0], 1, &xytrain.ptr.pp_double[i][0], 1, ae_v_len(0,nin-1)); - } - if( issparse==1 ) - { - sparsegetrow(&xytrainsp, i, &x, _state); - } - mlpeprocess(&netens, &x, &y, _state); - avgerr = avgerr+ae_fabs(y.ptr.p_double[0]-xytrain.ptr.pp_double[i][nin], _state); - } - avgerr = avgerr/ntrain; - ae_set_error_flag(&result, ae_fp_greater(avgerr,eps), __FILE__, __LINE__, "testmlptrainunit.ap:1799"); - avgerr = (double)(0); - for(i=0; i<=ntest-1; i++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xytest.ptr.pp_double[i][0], 1, ae_v_len(0,nin-1)); - mlpeprocess(&netens, &x, &y, _state); - avgerr = avgerr+ae_fabs(y.ptr.p_double[0]-xytest.ptr.pp_double[i][nin], _state); - } - avgerr = avgerr/ntest; - ae_set_error_flag(&result, ae_fp_greater(avgerr,2*eps), __FILE__, __LINE__, "testmlptrainunit.ap:1808"); - } - - /* - * Catch bug in implementation of MLPTrainEnsembleX: - * test ensemble training on empty dataset. - * - * Unfixed version should crash with violation of array - * bounds (at least in C#). - */ - nin = 2; - nout = 2; - nneurons = 3; - enssize = 3; - nneedrest = 2; - wstep = 0.001; - maxits = 2; - mlpcreatetrainer(nin, nout, &trainer, _state); - mlpsetcond(&trainer, wstep, maxits, _state); - mlpecreate1(nin, nneurons, nout, enssize, &netens, _state); - mlptrainensemblees(&trainer, &netens, nneedrest, &rep, _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Testing for functions MLPETrainES and MLPTrainEnsembleES on classification -problems. -*************************************************************************/ -static ae_bool testmlptrainunit_testmlptrainenscls(ae_state *_state) -{ - ae_frame _frame_block; - mlptrainer trainer; - mlpensemble netens; - mlpreport rep; - ae_int_t info; - sparsematrix xytrainsp; - ae_matrix xytrain; - ae_matrix xytest; - ae_int_t nin; - ae_int_t nout; - ae_vector x; - ae_vector y; - double decay; - double wstep; - ae_int_t maxits; - ae_int_t nneedrest; - ae_int_t enssize; - ae_int_t val; - ae_int_t ntrain; - ae_int_t ntest; - double avgerr; - double eps; - double delta; - ae_int_t issparse; - ae_int_t withtrainer; - ae_int_t xp; - ae_int_t nxp; - ae_int_t i; - ae_int_t j; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&trainer, 0, sizeof(trainer)); - memset(&netens, 0, sizeof(netens)); - memset(&rep, 0, sizeof(rep)); - memset(&xytrainsp, 0, sizeof(xytrainsp)); - memset(&xytrain, 0, sizeof(xytrain)); - memset(&xytest, 0, sizeof(xytest)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - _mlptrainer_init(&trainer, _state, ae_true); - _mlpensemble_init(&netens, _state, ae_true); - _mlpreport_init(&rep, _state, ae_true); - _sparsematrix_init(&xytrainsp, _state, ae_true); - ae_matrix_init(&xytrain, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xytest, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - - eps = 5.0E-2; - delta = 0.1; - ntrain = 90; - ntest = 90; - nin = 3; - nout = 3; - rvectorsetlengthatleast(&x, nin, _state); - rmatrixsetlengthatleast(&xytrain, ntrain, nin+1, _state); - rmatrixsetlengthatleast(&xytest, ntest, nin+1, _state); - decay = 1.0E-3; - wstep = 1.0E-3; - maxits = 100; - nneedrest = 1; - mlpcreatetrainercls(nin, nout, &trainer, _state); - mlpsetdecay(&trainer, decay, _state); - mlpsetcond(&trainer, wstep, maxits, _state); - nxp = 5; - for(xp=1; xp<=nxp; xp++) - { - enssize = ae_round(ae_pow((double)(10), (double)(ae_randominteger(2, _state)+1), _state), _state); - withtrainer = ae_randominteger(2, _state); - issparse = 0; - if( withtrainer==0 ) - { - issparse = 0; - } - if( withtrainer==1 ) - { - issparse = ae_randominteger(2, _state); - } - for(i=0; i<=ntrain-1; i++) - { - val = i%nin; - for(j=0; j<=nin-1; j++) - { - xytrain.ptr.pp_double[i][j] = delta*(ae_randomreal(_state)-1); - } - xytrain.ptr.pp_double[i][val] = xytrain.ptr.pp_double[i][val]+1; - xytrain.ptr.pp_double[i][nin] = (double)(val); - } - - /* - * Set dense dataset in trainer - */ - if( issparse==0 ) - { - mlpsetdataset(&trainer, &xytrain, ntrain, _state); - } - - /* - * * Sparse dataset(create it with using dense dataset). - */ - if( issparse==1 ) - { - sparsecreate(ntrain, nin+1, ntrain*(nin+1), &xytrainsp, _state); - for(i=0; i<=ntrain-1; i++) - { - for(j=0; j<=nin-1; j++) - { - sparseset(&xytrainsp, i, j, xytrain.ptr.pp_double[i][j], _state); - } - sparseset(&xytrainsp, i, nin, xytrain.ptr.pp_double[i][nin], _state); - } - sparseconverttocrs(&xytrainsp, _state); - - /* - * Set sparse dataset in trainer - */ - mlpsetsparsedataset(&trainer, &xytrainsp, ntrain, _state); - } - - /* - * Create test set - */ - for(i=0; i<=ntest-1; i++) - { - val = ae_randominteger(nin, _state); - for(j=0; j<=nin-1; j++) - { - xytest.ptr.pp_double[i][j] = delta*(ae_randomreal(_state)-1); - } - xytest.ptr.pp_double[i][val] = xytest.ptr.pp_double[i][val]+1; - xytest.ptr.pp_double[i][nin] = (double)(val); - } - - /* - * Create ensemble - */ - mlpecreatec0(nin, nout, enssize, &netens, _state); - - /* - * Train ensembles: - * * without trainer; - */ - if( withtrainer==0 ) - { - mlpetraines(&netens, &xytrain, ntrain, decay, nneedrest, &info, &rep, _state); - } - - /* - * * with trainer. - */ - if( withtrainer==1 ) - { - mlptrainensemblees(&trainer, &netens, nneedrest, &rep, _state); - } - - /* - * Calculate average error: - * * on training dataset; - */ - avgerr = (double)(0); - for(i=0; i<=ntrain-1; i++) - { - if( issparse==0 ) - { - ae_v_move(&x.ptr.p_double[0], 1, &xytrain.ptr.pp_double[i][0], 1, ae_v_len(0,nin-1)); - } - if( issparse==1 ) - { - sparsegetrow(&xytrainsp, i, &x, _state); - } - mlpeprocess(&netens, &x, &y, _state); - for(j=0; j<=nout-1; j++) - { - if( ae_fp_neq((double)(j),xytrain.ptr.pp_double[i][nin]) ) - { - avgerr = avgerr+y.ptr.p_double[j]; - } - else - { - avgerr = avgerr+(1-y.ptr.p_double[j]); - } - } - } - avgerr = avgerr/(ntrain*nout); - if( ae_fp_greater(avgerr,eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * * on test dataset. - */ - avgerr = (double)(0); - for(i=0; i<=ntest-1; i++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xytest.ptr.pp_double[i][0], 1, ae_v_len(0,nin-1)); - mlpeprocess(&netens, &x, &y, _state); - for(j=0; j<=nout-1; j++) - { - if( ae_fp_neq((double)(j),xytest.ptr.pp_double[i][nin]) ) - { - avgerr = avgerr+y.ptr.p_double[j]; - } - else - { - avgerr = avgerr+(1-y.ptr.p_double[j]); - } - } - } - avgerr = avgerr/(ntest*nout); - if( ae_fp_greater(avgerr,eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - - -static ae_bool testclusteringunit_basicahctests(ae_state *_state); -static ae_bool testclusteringunit_advancedahctests(ae_state *_state); -static void testclusteringunit_kmeanssimpletest1(ae_int_t nvars, - ae_int_t nc, - ae_int_t passcount, - ae_bool* converrors, - ae_bool* othererrors, - ae_bool* simpleerrors, - ae_state *_state); -static void testclusteringunit_kmeansspecialtests(ae_bool* othererrors, - ae_state *_state); -static void testclusteringunit_kmeansinfinitelooptest(ae_bool* othererrors, - ae_state *_state); -static void testclusteringunit_kmeansrestartstest(ae_bool* converrors, - ae_bool* restartserrors, - ae_state *_state); -static double testclusteringunit_rnormal(ae_state *_state); -static void testclusteringunit_rsphere(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t i, - ae_state *_state); -static double testclusteringunit_distfunc(/* Real */ ae_vector* x0, - /* Real */ ae_vector* x1, - ae_int_t d, - ae_int_t disttype, - ae_state *_state); -static ae_bool testclusteringunit_errorsinmerges(/* Real */ ae_matrix* d, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nf, - ahcreport* rep, - ae_int_t ahcalgo, - ae_state *_state); -static void testclusteringunit_kmeansreferenceupdatedistances(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - /* Real */ ae_matrix* ct, - ae_int_t k, - /* Integer */ ae_vector* xyc, - /* Real */ ae_vector* xydist2, - ae_state *_state); - - - - - -/************************************************************************* -Testing clustering -*************************************************************************/ -ae_bool testclustering(ae_bool silent, ae_state *_state) -{ - ae_bool waserrors; - ae_bool basicahcerrors; - ae_bool ahcerrors; - ae_bool kmeansconverrors; - ae_bool kmeanssimpleerrors; - ae_bool kmeansothererrors; - ae_bool kmeansrestartserrors; - ae_int_t passcount; - ae_int_t nf; - ae_int_t nc; - ae_bool result; - - - - /* - * AHC tests - */ - basicahcerrors = testclusteringunit_basicahctests(_state); - ahcerrors = testclusteringunit_advancedahctests(_state); - - /* - * k-means tests - */ - passcount = 10; - kmeansconverrors = ae_false; - kmeansothererrors = ae_false; - kmeanssimpleerrors = ae_false; - kmeansrestartserrors = ae_false; - testclusteringunit_kmeansspecialtests(&kmeansothererrors, _state); - testclusteringunit_kmeansinfinitelooptest(&kmeansothererrors, _state); - testclusteringunit_kmeansrestartstest(&kmeansconverrors, &kmeansrestartserrors, _state); - for(nf=1; nf<=5; nf++) - { - for(nc=1; nc<=5; nc++) - { - testclusteringunit_kmeanssimpletest1(nf, nc, passcount, &kmeansconverrors, &kmeansothererrors, &kmeanssimpleerrors, _state); - } - } - - /* - * Results - */ - waserrors = ae_false; - waserrors = waserrors||(basicahcerrors||ahcerrors); - waserrors = waserrors||(((kmeansconverrors||kmeansothererrors)||kmeanssimpleerrors)||kmeansrestartserrors); - if( !silent ) - { - printf("TESTING CLUSTERING\n"); - printf("AHC: \n"); - printf("* BASIC TESTS "); - if( !basicahcerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* GENERAL TESTS "); - if( !ahcerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("K-MEANS: \n"); - printf("* CONVERGENCE "); - if( !kmeansconverrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* SIMPLE TASKS "); - if( !kmeanssimpleerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* OTHER PROPERTIES "); - if( !kmeansothererrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* RESTARTS PROPERTIES "); - if( !kmeansrestartserrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - return result; -} - - -/************************************************************************* -Basic agglomerative hierarchical clustering tests: -returns True on failure, False on success. - -Basic tests study algorithm behavior on simple, hand-made datasets with -small number of points (1..10). -*************************************************************************/ -static ae_bool testclusteringunit_basicahctests(ae_state *_state) -{ - ae_frame _frame_block; - clusterizerstate s; - ahcreport rep; - ae_matrix xy; - ae_matrix d; - ae_matrix c; - ae_bool berr; - ae_int_t ahcalgo; - ae_int_t i; - ae_int_t j; - ae_int_t npoints; - ae_int_t k; - ae_vector cidx; - ae_vector cz; - ae_vector cidx2; - ae_vector cz2; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&xy, 0, sizeof(xy)); - memset(&d, 0, sizeof(d)); - memset(&c, 0, sizeof(c)); - memset(&cidx, 0, sizeof(cidx)); - memset(&cz, 0, sizeof(cz)); - memset(&cidx2, 0, sizeof(cidx2)); - memset(&cz2, 0, sizeof(cz2)); - _clusterizerstate_init(&s, _state, ae_true); - _ahcreport_init(&rep, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&d, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cidx, 0, DT_INT, _state, ae_true); - ae_vector_init(&cz, 0, DT_INT, _state, ae_true); - ae_vector_init(&cidx2, 0, DT_INT, _state, ae_true); - ae_vector_init(&cz2, 0, DT_INT, _state, ae_true); - - result = ae_true; - - /* - * Test on empty problem - */ - clusterizercreate(&s, _state); - clusterizerrunahc(&s, &rep, _state); - if( rep.npoints!=0 ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test on problem with one point - */ - ae_matrix_set_length(&xy, 1, 2, _state); - xy.ptr.pp_double[0][0] = ae_randomreal(_state); - xy.ptr.pp_double[0][1] = ae_randomreal(_state); - clusterizercreate(&s, _state); - clusterizersetpoints(&s, &xy, 1, 2, 0, _state); - clusterizerrunahc(&s, &rep, _state); - if( rep.npoints!=1 ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test on problem with two points - */ - ae_matrix_set_length(&xy, 2, 2, _state); - xy.ptr.pp_double[0][0] = ae_randomreal(_state); - xy.ptr.pp_double[0][1] = ae_randomreal(_state); - xy.ptr.pp_double[1][0] = ae_randomreal(_state); - xy.ptr.pp_double[1][1] = ae_randomreal(_state); - clusterizercreate(&s, _state); - clusterizersetpoints(&s, &xy, 2, 2, 0, _state); - clusterizerrunahc(&s, &rep, _state); - if( (rep.npoints!=2||rep.z.rows!=1)||rep.z.cols!=2 ) - { - ae_frame_leave(_state); - return result; - } - if( rep.z.ptr.pp_int[0][0]!=0||rep.z.ptr.pp_int[0][1]!=1 ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test on specially designed problem which should have - * following dendrogram: - * - * ------ - * | | - * ---- ---- - * | | | | - * 0 1 2 3 - * - * ...with first merge performed on 0 and 1, second merge - * performed on 2 and 3. Complete linkage is used. - * - * Additionally we test ClusterizerSeparatedByDist() on this - * problem for different distances. Test is performed by - * comparing function result with ClusterizerGetKClusters() - * for known K. - */ - ae_matrix_set_length(&xy, 4, 1, _state); - xy.ptr.pp_double[0][0] = 0.0; - xy.ptr.pp_double[1][0] = 1.0; - xy.ptr.pp_double[2][0] = 3.0; - xy.ptr.pp_double[3][0] = 4.1; - clusterizercreate(&s, _state); - clusterizersetpoints(&s, &xy, 4, 1, 0, _state); - clusterizersetahcalgo(&s, 0, _state); - clusterizerrunahc(&s, &rep, _state); - if( (((rep.npoints!=4||rep.z.rows!=3)||rep.z.cols!=2)||rep.pz.rows!=3)||rep.pz.cols!=2 ) - { - ae_frame_leave(_state); - return result; - } - berr = ae_false; - berr = (berr||rep.z.ptr.pp_int[0][0]!=0)||rep.z.ptr.pp_int[0][1]!=1; - berr = (berr||rep.z.ptr.pp_int[1][0]!=2)||rep.z.ptr.pp_int[1][1]!=3; - berr = (berr||rep.z.ptr.pp_int[2][0]!=4)||rep.z.ptr.pp_int[2][1]!=5; - berr = (((berr||rep.p.ptr.p_int[0]!=0)||rep.p.ptr.p_int[1]!=1)||rep.p.ptr.p_int[2]!=2)||rep.p.ptr.p_int[3]!=3; - berr = (berr||rep.pz.ptr.pp_int[0][0]!=0)||rep.pz.ptr.pp_int[0][1]!=1; - berr = (berr||rep.pz.ptr.pp_int[1][0]!=2)||rep.pz.ptr.pp_int[1][1]!=3; - berr = (berr||rep.pz.ptr.pp_int[2][0]!=4)||rep.pz.ptr.pp_int[2][1]!=5; - berr = (((berr||rep.pm.ptr.pp_int[0][0]!=0)||rep.pm.ptr.pp_int[0][1]!=0)||rep.pm.ptr.pp_int[0][2]!=1)||rep.pm.ptr.pp_int[0][3]!=1; - berr = (((berr||rep.pm.ptr.pp_int[1][0]!=2)||rep.pm.ptr.pp_int[1][1]!=2)||rep.pm.ptr.pp_int[1][2]!=3)||rep.pm.ptr.pp_int[1][3]!=3; - berr = (((berr||rep.pm.ptr.pp_int[2][0]!=0)||rep.pm.ptr.pp_int[2][1]!=1)||rep.pm.ptr.pp_int[2][2]!=2)||rep.pm.ptr.pp_int[2][3]!=3; - if( berr ) - { - ae_frame_leave(_state); - return result; - } - clusterizerseparatedbydist(&rep, 0.5, &k, &cidx, &cz, _state); - clusterizergetkclusters(&rep, 4, &cidx2, &cz2, _state); - if( k!=4 ) - { - ae_frame_leave(_state); - return result; - } - if( ((cidx.ptr.p_int[0]!=cidx2.ptr.p_int[0]||cidx.ptr.p_int[1]!=cidx2.ptr.p_int[1])||cidx.ptr.p_int[2]!=cidx2.ptr.p_int[2])||cidx.ptr.p_int[3]!=cidx2.ptr.p_int[3] ) - { - ae_frame_leave(_state); - return result; - } - if( ((cz.ptr.p_int[0]!=cz2.ptr.p_int[0]||cz.ptr.p_int[1]!=cz2.ptr.p_int[1])||cz.ptr.p_int[2]!=cz2.ptr.p_int[2])||cz.ptr.p_int[3]!=cz2.ptr.p_int[3] ) - { - ae_frame_leave(_state); - return result; - } - clusterizerseparatedbydist(&rep, 1.05, &k, &cidx, &cz, _state); - clusterizergetkclusters(&rep, 3, &cidx2, &cz2, _state); - if( k!=3 ) - { - ae_frame_leave(_state); - return result; - } - if( ((cidx.ptr.p_int[0]!=cidx2.ptr.p_int[0]||cidx.ptr.p_int[1]!=cidx2.ptr.p_int[1])||cidx.ptr.p_int[2]!=cidx2.ptr.p_int[2])||cidx.ptr.p_int[3]!=cidx2.ptr.p_int[3] ) - { - ae_frame_leave(_state); - return result; - } - if( (cz.ptr.p_int[0]!=cz2.ptr.p_int[0]||cz.ptr.p_int[1]!=cz2.ptr.p_int[1])||cz.ptr.p_int[2]!=cz2.ptr.p_int[2] ) - { - ae_frame_leave(_state); - return result; - } - clusterizerseparatedbydist(&rep, 1.15, &k, &cidx, &cz, _state); - clusterizergetkclusters(&rep, 2, &cidx2, &cz2, _state); - if( k!=2 ) - { - ae_frame_leave(_state); - return result; - } - if( ((cidx.ptr.p_int[0]!=cidx2.ptr.p_int[0]||cidx.ptr.p_int[1]!=cidx2.ptr.p_int[1])||cidx.ptr.p_int[2]!=cidx2.ptr.p_int[2])||cidx.ptr.p_int[3]!=cidx2.ptr.p_int[3] ) - { - ae_frame_leave(_state); - return result; - } - if( cz.ptr.p_int[0]!=cz2.ptr.p_int[0]||cz.ptr.p_int[1]!=cz2.ptr.p_int[1] ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test on specially designed problem with Pearson distance - * which should have following dendrogram: - * - * ------ - * | | - * ---- ---- - * | | | | - * 0 1 2 3 - * - * This problem is used to test ClusterizerSeparatedByDist(). - * The test is performed by comparing function result with - * ClusterizerGetKClusters() for known K. - * - * NOTE: - * * corr(a0,a1) = 0.866 - * * corr(a2,a3) = 0.990 - * * corr(a0/a1, a2/a3)<=0.5 - */ - ae_matrix_set_length(&xy, 4, 3, _state); - xy.ptr.pp_double[0][0] = 0.3; - xy.ptr.pp_double[0][1] = 0.5; - xy.ptr.pp_double[0][2] = 0.3; - xy.ptr.pp_double[1][0] = 0.3; - xy.ptr.pp_double[1][1] = 0.5; - xy.ptr.pp_double[1][2] = 0.4; - xy.ptr.pp_double[2][0] = 0.1; - xy.ptr.pp_double[2][1] = 0.5; - xy.ptr.pp_double[2][2] = 0.9; - xy.ptr.pp_double[3][0] = 0.1; - xy.ptr.pp_double[3][1] = 0.4; - xy.ptr.pp_double[3][2] = 0.9; - clusterizercreate(&s, _state); - clusterizersetpoints(&s, &xy, 4, 3, 10, _state); - clusterizersetahcalgo(&s, 1, _state); - clusterizerrunahc(&s, &rep, _state); - clusterizerseparatedbycorr(&rep, 0.999, &k, &cidx, &cz, _state); - clusterizergetkclusters(&rep, 4, &cidx2, &cz2, _state); - if( k!=4 ) - { - ae_frame_leave(_state); - return result; - } - if( ((cidx.ptr.p_int[0]!=cidx2.ptr.p_int[0]||cidx.ptr.p_int[1]!=cidx2.ptr.p_int[1])||cidx.ptr.p_int[2]!=cidx2.ptr.p_int[2])||cidx.ptr.p_int[3]!=cidx2.ptr.p_int[3] ) - { - ae_frame_leave(_state); - return result; - } - if( ((cz.ptr.p_int[0]!=cz2.ptr.p_int[0]||cz.ptr.p_int[1]!=cz2.ptr.p_int[1])||cz.ptr.p_int[2]!=cz2.ptr.p_int[2])||cz.ptr.p_int[3]!=cz2.ptr.p_int[3] ) - { - ae_frame_leave(_state); - return result; - } - clusterizerseparatedbycorr(&rep, 0.900, &k, &cidx, &cz, _state); - clusterizergetkclusters(&rep, 3, &cidx2, &cz2, _state); - if( k!=3 ) - { - ae_frame_leave(_state); - return result; - } - if( ((cidx.ptr.p_int[0]!=cidx2.ptr.p_int[0]||cidx.ptr.p_int[1]!=cidx2.ptr.p_int[1])||cidx.ptr.p_int[2]!=cidx2.ptr.p_int[2])||cidx.ptr.p_int[3]!=cidx2.ptr.p_int[3] ) - { - ae_frame_leave(_state); - return result; - } - if( (cz.ptr.p_int[0]!=cz2.ptr.p_int[0]||cz.ptr.p_int[1]!=cz2.ptr.p_int[1])||cz.ptr.p_int[2]!=cz2.ptr.p_int[2] ) - { - ae_frame_leave(_state); - return result; - } - clusterizerseparatedbycorr(&rep, 0.600, &k, &cidx, &cz, _state); - clusterizergetkclusters(&rep, 2, &cidx2, &cz2, _state); - if( k!=2 ) - { - ae_frame_leave(_state); - return result; - } - if( ((cidx.ptr.p_int[0]!=cidx2.ptr.p_int[0]||cidx.ptr.p_int[1]!=cidx2.ptr.p_int[1])||cidx.ptr.p_int[2]!=cidx2.ptr.p_int[2])||cidx.ptr.p_int[3]!=cidx2.ptr.p_int[3] ) - { - ae_frame_leave(_state); - return result; - } - if( cz.ptr.p_int[0]!=cz2.ptr.p_int[0]||cz.ptr.p_int[1]!=cz2.ptr.p_int[1] ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Single linkage vs. complete linkage - */ - ae_matrix_set_length(&xy, 6, 1, _state); - xy.ptr.pp_double[0][0] = 0.0; - xy.ptr.pp_double[1][0] = 1.0; - xy.ptr.pp_double[2][0] = 2.1; - xy.ptr.pp_double[3][0] = 3.3; - xy.ptr.pp_double[4][0] = 6.0; - xy.ptr.pp_double[5][0] = 4.6; - clusterizercreate(&s, _state); - clusterizersetpoints(&s, &xy, 6, 1, 0, _state); - clusterizersetahcalgo(&s, 0, _state); - clusterizerrunahc(&s, &rep, _state); - if( rep.npoints!=6||rep.p.cnt!=6 ) - { - ae_frame_leave(_state); - return result; - } - if( ((rep.z.rows!=5||rep.z.cols!=2)||rep.pz.rows!=5)||rep.pz.cols!=2 ) - { - ae_frame_leave(_state); - return result; - } - berr = ae_false; - berr = berr||rep.p.ptr.p_int[0]!=2; - berr = berr||rep.p.ptr.p_int[1]!=3; - berr = berr||rep.p.ptr.p_int[2]!=4; - berr = berr||rep.p.ptr.p_int[3]!=5; - berr = berr||rep.p.ptr.p_int[4]!=0; - berr = berr||rep.p.ptr.p_int[5]!=1; - berr = (berr||rep.z.ptr.pp_int[0][0]!=0)||rep.z.ptr.pp_int[0][1]!=1; - berr = (berr||rep.z.ptr.pp_int[1][0]!=2)||rep.z.ptr.pp_int[1][1]!=3; - berr = (berr||rep.z.ptr.pp_int[2][0]!=4)||rep.z.ptr.pp_int[2][1]!=5; - berr = (berr||rep.z.ptr.pp_int[3][0]!=6)||rep.z.ptr.pp_int[3][1]!=7; - berr = (berr||rep.z.ptr.pp_int[4][0]!=8)||rep.z.ptr.pp_int[4][1]!=9; - berr = (berr||rep.pz.ptr.pp_int[0][0]!=2)||rep.pz.ptr.pp_int[0][1]!=3; - berr = (berr||rep.pz.ptr.pp_int[1][0]!=4)||rep.pz.ptr.pp_int[1][1]!=5; - berr = (berr||rep.pz.ptr.pp_int[2][0]!=0)||rep.pz.ptr.pp_int[2][1]!=1; - berr = (berr||rep.pz.ptr.pp_int[3][0]!=6)||rep.pz.ptr.pp_int[3][1]!=7; - berr = (berr||rep.pz.ptr.pp_int[4][0]!=8)||rep.pz.ptr.pp_int[4][1]!=9; - if( berr ) - { - ae_frame_leave(_state); - return result; - } - clusterizersetahcalgo(&s, 1, _state); - clusterizerrunahc(&s, &rep, _state); - if( (rep.npoints!=6||rep.z.rows!=5)||rep.z.cols!=2 ) - { - ae_frame_leave(_state); - return result; - } - berr = ae_false; - berr = (berr||rep.z.ptr.pp_int[0][0]!=0)||rep.z.ptr.pp_int[0][1]!=1; - berr = (berr||rep.z.ptr.pp_int[1][0]!=2)||rep.z.ptr.pp_int[1][1]!=6; - berr = (berr||rep.z.ptr.pp_int[2][0]!=3)||rep.z.ptr.pp_int[2][1]!=7; - berr = (berr||rep.z.ptr.pp_int[3][0]!=5)||rep.z.ptr.pp_int[3][1]!=8; - berr = (berr||rep.z.ptr.pp_int[4][0]!=4)||rep.z.ptr.pp_int[4][1]!=9; - if( berr ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test which differentiates complete linkage and average linkage from - * single linkage: - * * we have cluster C0={(-0.5), (0)}, - * cluster C1={(19.0), (20.0), (21.0), (22.0), (23.0)}, - * and point P between them - (10.0) - * * we try three different strategies - single linkage, complete - * linkage, average linkage. - * * any strategy will merge C0 first, then merge points of C1, - * and then merge P with C0 or C1 (depending on linkage type) - * * we test that: - * a) C0 is merged first - * b) after 5 merges (including merge of C0), P is merged with C0 or C1 - * c) P is merged with C1 when we have single linkage, with C0 otherwise - */ - ae_matrix_set_length(&xy, 8, 1, _state); - xy.ptr.pp_double[0][0] = -0.5; - xy.ptr.pp_double[1][0] = 0.0; - xy.ptr.pp_double[2][0] = 10.0; - xy.ptr.pp_double[3][0] = 19.0; - xy.ptr.pp_double[4][0] = 20.0; - xy.ptr.pp_double[5][0] = 21.0; - xy.ptr.pp_double[6][0] = 22.0; - xy.ptr.pp_double[7][0] = 23.0; - clusterizercreate(&s, _state); - clusterizersetpoints(&s, &xy, 8, 1, 0, _state); - for(ahcalgo=0; ahcalgo<=2; ahcalgo++) - { - clusterizersetahcalgo(&s, ahcalgo, _state); - clusterizerrunahc(&s, &rep, _state); - if( (rep.npoints!=8||rep.z.rows!=7)||rep.z.cols!=2 ) - { - ae_frame_leave(_state); - return result; - } - if( rep.z.ptr.pp_int[0][0]!=0||rep.z.ptr.pp_int[0][1]!=1 ) - { - ae_frame_leave(_state); - return result; - } - if( rep.z.ptr.pp_int[5][0]!=2&&rep.z.ptr.pp_int[5][1]!=2 ) - { - ae_frame_leave(_state); - return result; - } - if( rep.z.ptr.pp_int[5][0]!=2&&rep.z.ptr.pp_int[5][1]!=2 ) - { - ae_frame_leave(_state); - return result; - } - if( (ahcalgo==0||ahcalgo==2)&&(rep.z.ptr.pp_int[5][0]!=8&&rep.z.ptr.pp_int[5][1]!=8) ) - { - ae_frame_leave(_state); - return result; - } - if( ahcalgo==1&&(rep.z.ptr.pp_int[5][0]==8||rep.z.ptr.pp_int[5][1]==8) ) - { - ae_frame_leave(_state); - return result; - } - } - - /* - * Test which differentiates single linkage and average linkage from - * complete linkage: - * * we have cluster C0={(-2.5), (-2.0)}, - * cluster C1={(19.0), (20.0), (21.0), (22.0), (23.0)}, - * and point P between them - (10.0) - * * we try three different strategies - single linkage, complete - * linkage, average linkage. - * * any strategy will merge C0 first, then merge points of C1, - * and then merge P with C0 or C1 (depending on linkage type) - * * we test that: - * a) C0 is merged first - * b) after 5 merges (including merge of C0), P is merged with C0 or C1 - * c) P is merged with C0 when we have complete linkage, with C1 otherwise - */ - ae_matrix_set_length(&xy, 8, 1, _state); - xy.ptr.pp_double[0][0] = -2.5; - xy.ptr.pp_double[1][0] = -2.0; - xy.ptr.pp_double[2][0] = 10.0; - xy.ptr.pp_double[3][0] = 19.0; - xy.ptr.pp_double[4][0] = 20.0; - xy.ptr.pp_double[5][0] = 21.0; - xy.ptr.pp_double[6][0] = 22.0; - xy.ptr.pp_double[7][0] = 23.0; - clusterizercreate(&s, _state); - clusterizersetpoints(&s, &xy, 8, 1, 0, _state); - for(ahcalgo=0; ahcalgo<=2; ahcalgo++) - { - clusterizersetahcalgo(&s, ahcalgo, _state); - clusterizerrunahc(&s, &rep, _state); - if( (rep.npoints!=8||rep.z.rows!=7)||rep.z.cols!=2 ) - { - ae_frame_leave(_state); - return result; - } - if( rep.z.ptr.pp_int[0][0]!=0||rep.z.ptr.pp_int[0][1]!=1 ) - { - ae_frame_leave(_state); - return result; - } - if( rep.z.ptr.pp_int[5][0]!=2&&rep.z.ptr.pp_int[5][1]!=2 ) - { - ae_frame_leave(_state); - return result; - } - if( rep.z.ptr.pp_int[5][0]!=2&&rep.z.ptr.pp_int[5][1]!=2 ) - { - ae_frame_leave(_state); - return result; - } - if( ahcalgo==0&&(rep.z.ptr.pp_int[5][0]!=8&&rep.z.ptr.pp_int[5][1]!=8) ) - { - ae_frame_leave(_state); - return result; - } - if( (ahcalgo==1||ahcalgo==2)&&(rep.z.ptr.pp_int[5][0]==8||rep.z.ptr.pp_int[5][1]==8) ) - { - ae_frame_leave(_state); - return result; - } - } - - /* - * Test which differentiates weighred average linkage from unweighted average linkage: - * * we have cluster C0={(0.0), (1.5), (2.5)}, - * cluster C1={(7.5), (7.99)}, - * and point P between them - (4.5) - * * we try two different strategies - weighted average linkage and unweighted average linkage - * * any strategy will merge C1 first, then merge points of C0, - * and then merge P with C0 or C1 (depending on linkage type) - * * we test that: - * a) C1 is merged first, C0 is merged after that - * b) after first 3 merges P is merged with C0 or C1 - * c) P is merged with C1 when we have weighted average linkage, with C0 otherwise - */ - ae_matrix_set_length(&xy, 6, 1, _state); - xy.ptr.pp_double[0][0] = 0.0; - xy.ptr.pp_double[1][0] = 1.5; - xy.ptr.pp_double[2][0] = 2.5; - xy.ptr.pp_double[3][0] = 4.5; - xy.ptr.pp_double[4][0] = 7.5; - xy.ptr.pp_double[5][0] = 7.99; - clusterizercreate(&s, _state); - clusterizersetpoints(&s, &xy, 6, 1, 0, _state); - for(ahcalgo=2; ahcalgo<=3; ahcalgo++) - { - clusterizersetahcalgo(&s, ahcalgo, _state); - clusterizerrunahc(&s, &rep, _state); - if( (rep.npoints!=6||rep.z.rows!=5)||rep.z.cols!=2 ) - { - ae_frame_leave(_state); - return result; - } - if( rep.z.ptr.pp_int[0][0]!=4||rep.z.ptr.pp_int[0][1]!=5 ) - { - ae_frame_leave(_state); - return result; - } - if( rep.z.ptr.pp_int[1][0]!=1||rep.z.ptr.pp_int[1][1]!=2 ) - { - ae_frame_leave(_state); - return result; - } - if( rep.z.ptr.pp_int[2][0]!=0||rep.z.ptr.pp_int[2][1]!=7 ) - { - ae_frame_leave(_state); - return result; - } - if( rep.z.ptr.pp_int[3][0]!=3 ) - { - ae_frame_leave(_state); - return result; - } - if( ahcalgo==2&&rep.z.ptr.pp_int[3][1]!=8 ) - { - ae_frame_leave(_state); - return result; - } - if( ahcalgo==3&&rep.z.ptr.pp_int[3][1]!=6 ) - { - ae_frame_leave(_state); - return result; - } - } - - /* - * Test which checks correctness of Ward's method on very basic problem - */ - ae_matrix_set_length(&xy, 4, 1, _state); - xy.ptr.pp_double[0][0] = 0.0; - xy.ptr.pp_double[1][0] = 1.0; - xy.ptr.pp_double[2][0] = 3.1; - xy.ptr.pp_double[3][0] = 4.0; - clusterizercreate(&s, _state); - clusterizersetpoints(&s, &xy, xy.rows, xy.cols, 2, _state); - clusterizergetdistances(&xy, xy.rows, xy.cols, 2, &d, _state); - clusterizersetahcalgo(&s, 4, _state); - clusterizerrunahc(&s, &rep, _state); - if( testclusteringunit_errorsinmerges(&d, &xy, xy.rows, xy.cols, &rep, 4, _state) ) - { - ae_frame_leave(_state); - return result; - } - - /* - * One more Ward's test - */ - ae_matrix_set_length(&xy, 8, 2, _state); - xy.ptr.pp_double[0][0] = 0.4700566262; - xy.ptr.pp_double[0][1] = 0.4565938448; - xy.ptr.pp_double[1][0] = 0.2394499506; - xy.ptr.pp_double[1][1] = 0.1750209592; - xy.ptr.pp_double[2][0] = 0.6518417019; - xy.ptr.pp_double[2][1] = 0.6151370746; - xy.ptr.pp_double[3][0] = 0.9863942841; - xy.ptr.pp_double[3][1] = 0.7855012189; - xy.ptr.pp_double[4][0] = 0.1517812919; - xy.ptr.pp_double[4][1] = 0.2600174758; - xy.ptr.pp_double[5][0] = 0.7840203638; - xy.ptr.pp_double[5][1] = 0.9023597604; - xy.ptr.pp_double[6][0] = 0.2604194835; - xy.ptr.pp_double[6][1] = 0.9792704661; - xy.ptr.pp_double[7][0] = 0.6353096042; - xy.ptr.pp_double[7][1] = 0.8252606906; - clusterizercreate(&s, _state); - clusterizersetpoints(&s, &xy, xy.rows, xy.cols, 2, _state); - clusterizergetdistances(&xy, xy.rows, xy.cols, 2, &d, _state); - clusterizersetahcalgo(&s, 4, _state); - clusterizerrunahc(&s, &rep, _state); - if( rep.z.ptr.pp_int[0][0]!=1||rep.z.ptr.pp_int[0][1]!=4 ) - { - ae_frame_leave(_state); - return result; - } - if( rep.z.ptr.pp_int[1][0]!=5||rep.z.ptr.pp_int[1][1]!=7 ) - { - ae_frame_leave(_state); - return result; - } - if( rep.z.ptr.pp_int[2][0]!=0||rep.z.ptr.pp_int[2][1]!=2 ) - { - ae_frame_leave(_state); - return result; - } - if( rep.z.ptr.pp_int[3][0]!=3||rep.z.ptr.pp_int[3][1]!=9 ) - { - ae_frame_leave(_state); - return result; - } - if( rep.z.ptr.pp_int[4][0]!=10||rep.z.ptr.pp_int[4][1]!=11 ) - { - ae_frame_leave(_state); - return result; - } - if( rep.z.ptr.pp_int[5][0]!=6||rep.z.ptr.pp_int[5][1]!=12 ) - { - ae_frame_leave(_state); - return result; - } - if( rep.z.ptr.pp_int[6][0]!=8||rep.z.ptr.pp_int[6][1]!=13 ) - { - ae_frame_leave(_state); - return result; - } - if( testclusteringunit_errorsinmerges(&d, &xy, xy.rows, xy.cols, &rep, 4, _state) ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Ability to solve problems with zero distance matrix - */ - npoints = 20; - ae_matrix_set_length(&d, npoints, npoints, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=npoints-1; j++) - { - d.ptr.pp_double[i][j] = 0.0; - } - } - for(ahcalgo=0; ahcalgo<=4; ahcalgo++) - { - clusterizercreate(&s, _state); - clusterizersetdistances(&s, &d, npoints, ae_true, _state); - clusterizersetahcalgo(&s, ahcalgo, _state); - clusterizerrunahc(&s, &rep, _state); - if( (rep.npoints!=npoints||rep.z.rows!=npoints-1)||rep.z.cols!=2 ) - { - ae_frame_leave(_state); - return result; - } - } - - /* - * Test GetKClusters() - */ - ae_matrix_set_length(&xy, 8, 1, _state); - xy.ptr.pp_double[0][0] = -2.5; - xy.ptr.pp_double[1][0] = -2.0; - xy.ptr.pp_double[2][0] = 10.0; - xy.ptr.pp_double[3][0] = 19.0; - xy.ptr.pp_double[4][0] = 20.0; - xy.ptr.pp_double[5][0] = 21.0; - xy.ptr.pp_double[6][0] = 22.0; - xy.ptr.pp_double[7][0] = 23.0; - clusterizercreate(&s, _state); - clusterizersetpoints(&s, &xy, 8, 1, 0, _state); - clusterizersetahcalgo(&s, 0, _state); - clusterizerrunahc(&s, &rep, _state); - clusterizergetkclusters(&rep, 3, &cidx, &cz, _state); - if( ((((((cidx.ptr.p_int[0]!=1||cidx.ptr.p_int[1]!=1)||cidx.ptr.p_int[2]!=0)||cidx.ptr.p_int[3]!=2)||cidx.ptr.p_int[4]!=2)||cidx.ptr.p_int[5]!=2)||cidx.ptr.p_int[6]!=2)||cidx.ptr.p_int[7]!=2 ) - { - ae_frame_leave(_state); - return result; - } - if( (cz.ptr.p_int[0]!=2||cz.ptr.p_int[1]!=8)||cz.ptr.p_int[2]!=12 ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test is done - */ - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Advanced agglomerative hierarchical clustering tests : returns True on -failure, False on success. - -Advanced testing subroutine perform several automatically generated tests. -*************************************************************************/ -static ae_bool testclusteringunit_advancedahctests(ae_state *_state) -{ - ae_frame _frame_block; - clusterizerstate s; - ahcreport rep; - ae_matrix xy; - ae_matrix dm; - ae_matrix dm2; - ae_vector idx; - ae_vector disttypes; - ae_vector x0; - ae_vector x1; - ae_int_t d; - ae_int_t n; - ae_int_t npoints; - ae_int_t ahcalgo; - ae_int_t disttype; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - ae_int_t t; - ae_int_t euclidean; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&xy, 0, sizeof(xy)); - memset(&dm, 0, sizeof(dm)); - memset(&dm2, 0, sizeof(dm2)); - memset(&idx, 0, sizeof(idx)); - memset(&disttypes, 0, sizeof(disttypes)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - _clusterizerstate_init(&s, _state, ae_true); - _ahcreport_init(&rep, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&dm, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&dm2, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&idx, 0, DT_INT, _state, ae_true); - ae_vector_init(&disttypes, 0, DT_INT, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - - result = ae_false; - euclidean = 2; - - /* - * Test on D-dimensional problem: - * * D = 2...5 - * * D clusters, each has N points; - * centers are located at x=(0 ... 1 ... 0); - * cluster radii are approximately 0.1 - * * single/complete/unweighted_average/weighted_average linkage/Ward's method are tested - * * Euclidean distance is used, either: - * a) one given by distance matrix (ClusterizerSetDistances) - * b) one calculated from dataset (ClusterizerSetPoints) - * * we have N*D points, and N*D-1 merges in total - * * points are randomly rearranged after generation - * - * For all kinds of linkage we perform following test: - * * for each point we remember index of its cluster - * (one which is determined during dataset generation) - * * we clusterize points with ALGLIB capabilities - * * we scan Rep.Z and perform first D*(N-1) merges - * * for each merge we check that it merges points - * from same cluster; - * - * Additonally, we call ErrorsInMerges(). See function comments - * for more information about specific tests performed. This function - * allows us to check that clusters are built exactly as specified by - * definition of the clustering algorithm. - */ - for(d=2; d<=5; d++) - { - for(ahcalgo=0; ahcalgo<=4; ahcalgo++) - { - n = ae_round(ae_pow((double)(3), (double)(ae_randominteger(3, _state)), _state), _state); - npoints = d*n; - - /* - * 1. generate dataset. - * 2. fill Idx (array of cluster indexes): - * * first N*D elements store cluster indexes - * * next D*(N-1) elements are filled during merges - * 3. build distance matrix DM - */ - ae_matrix_set_length(&xy, n*d, d, _state); - ae_vector_set_length(&idx, n*d+d*(n-1), _state); - for(i=0; i<=n*d-1; i++) - { - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][j] = 0.2*ae_randomreal(_state)-0.1; - } - xy.ptr.pp_double[i][i%d] = xy.ptr.pp_double[i][i%d]+1.0; - idx.ptr.p_int[i] = i%d; - } - for(i=0; i<=n*d-1; i++) - { - k = ae_randominteger(n*d, _state); - if( k!=i ) - { - for(j=0; j<=d-1; j++) - { - v = xy.ptr.pp_double[i][j]; - xy.ptr.pp_double[i][j] = xy.ptr.pp_double[k][j]; - xy.ptr.pp_double[k][j] = v; - } - t = idx.ptr.p_int[k]; - idx.ptr.p_int[k] = idx.ptr.p_int[i]; - idx.ptr.p_int[i] = t; - } - } - ae_matrix_set_length(&dm, npoints, npoints, _state); - ae_vector_set_length(&x0, d, _state); - ae_vector_set_length(&x1, d, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=npoints-1; j++) - { - ae_v_move(&x0.ptr.p_double[0], 1, &xy.ptr.pp_double[i][0], 1, ae_v_len(0,d-1)); - ae_v_move(&x1.ptr.p_double[0], 1, &xy.ptr.pp_double[j][0], 1, ae_v_len(0,d-1)); - dm.ptr.pp_double[i][j] = testclusteringunit_distfunc(&x0, &x1, d, euclidean, _state); - } - } - - /* - * Clusterize with SetPoints() - */ - clusterizercreate(&s, _state); - clusterizersetpoints(&s, &xy, n*d, d, euclidean, _state); - clusterizersetahcalgo(&s, ahcalgo, _state); - clusterizerrunahc(&s, &rep, _state); - - /* - * Tests: - * * replay first D*(N-1) merges; these merges should take place - * within clusters, intercluster merges will be performed at the - * last stages of the processing. - * * test with ErrorsInMerges() - */ - if( rep.npoints!=npoints ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=d*(n-1)-1; i++) - { - - /* - * Check correctness of I-th row of Z - */ - if( (rep.z.ptr.pp_int[i][0]<0||rep.z.ptr.pp_int[i][0]>=rep.z.ptr.pp_int[i][1])||rep.z.ptr.pp_int[i][1]>=d*n+i ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Check that merge is performed within cluster - */ - if( idx.ptr.p_int[rep.z.ptr.pp_int[i][0]]!=idx.ptr.p_int[rep.z.ptr.pp_int[i][1]] ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Write new entry of Idx. - * Both points from the same cluster, so result of the merge - * belongs to the same cluster - */ - idx.ptr.p_int[n*d+i] = idx.ptr.p_int[rep.z.ptr.pp_int[i][1]]; - } - if( ((ahcalgo==0||ahcalgo==1)||ahcalgo==2)||ahcalgo==4 ) - { - if( testclusteringunit_errorsinmerges(&dm, &xy, d*n, d, &rep, ahcalgo, _state) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - - /* - * Clusterize one more time, now with distance matrix - */ - clusterizercreate(&s, _state); - clusterizersetdistances(&s, &dm, n*d, ae_fp_greater(ae_randomreal(_state),0.5), _state); - clusterizersetahcalgo(&s, ahcalgo, _state); - clusterizerrunahc(&s, &rep, _state); - - /* - * Tests: - * * replay first D*(N-1) merges; these merges should take place - * within clusters, intercluster merges will be performed at the - * last stages of the processing. - * * test with ErrorsInMerges() - */ - if( rep.npoints!=npoints ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=d*(n-1)-1; i++) - { - - /* - * Check correctness of I-th row of Z - */ - if( (rep.z.ptr.pp_int[i][0]<0||rep.z.ptr.pp_int[i][0]>=rep.z.ptr.pp_int[i][1])||rep.z.ptr.pp_int[i][1]>=d*n+i ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Check that merge is performed within cluster - */ - if( idx.ptr.p_int[rep.z.ptr.pp_int[i][0]]!=idx.ptr.p_int[rep.z.ptr.pp_int[i][1]] ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Write new entry of Idx. - * Both points from the same cluster, so result of the merge - * belongs to the same cluster - */ - idx.ptr.p_int[n*d+i] = idx.ptr.p_int[rep.z.ptr.pp_int[i][1]]; - } - if( ((ahcalgo==0||ahcalgo==1)||ahcalgo==2)||ahcalgo==4 ) - { - if( testclusteringunit_errorsinmerges(&dm, &xy, d*n, d, &rep, ahcalgo, _state) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - - /* - * Test on random D-dimensional problem: - * * D = 2...5 - * * N=1..16 random points from unit hypercube - * * single/complete/unweighted_average linkage/Ward's method are tested - * * different distance functions are tested - * * we call ErrorsInMerges() and we check distance matrix - * calculated by unit test against one returned by GetDistances() - */ - ae_vector_set_length(&disttypes, 9, _state); - disttypes.ptr.p_int[0] = 0; - disttypes.ptr.p_int[1] = 1; - disttypes.ptr.p_int[2] = 2; - disttypes.ptr.p_int[3] = 10; - disttypes.ptr.p_int[4] = 11; - disttypes.ptr.p_int[5] = 12; - disttypes.ptr.p_int[6] = 13; - disttypes.ptr.p_int[7] = 20; - disttypes.ptr.p_int[8] = 21; - for(disttype=0; disttype<=disttypes.cnt-1; disttype++) - { - for(ahcalgo=0; ahcalgo<=4; ahcalgo++) - { - if( ahcalgo==3 ) - { - continue; - } - if( ahcalgo==4&&disttype!=2 ) - { - continue; - } - npoints = ae_round(ae_pow((double)(2), (double)(ae_randominteger(5, _state)), _state), _state); - d = 2+ae_randominteger(4, _state); - - /* - * Generate dataset and distance matrix - */ - ae_matrix_set_length(&xy, npoints, d, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][j] = ae_randomreal(_state); - } - } - ae_matrix_set_length(&dm, npoints, npoints, _state); - ae_vector_set_length(&x0, d, _state); - ae_vector_set_length(&x1, d, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=npoints-1; j++) - { - ae_v_move(&x0.ptr.p_double[0], 1, &xy.ptr.pp_double[i][0], 1, ae_v_len(0,d-1)); - ae_v_move(&x1.ptr.p_double[0], 1, &xy.ptr.pp_double[j][0], 1, ae_v_len(0,d-1)); - dm.ptr.pp_double[i][j] = testclusteringunit_distfunc(&x0, &x1, d, disttypes.ptr.p_int[disttype], _state); - } - } - - /* - * Clusterize - */ - clusterizercreate(&s, _state); - clusterizersetpoints(&s, &xy, npoints, d, disttypes.ptr.p_int[disttype], _state); - clusterizersetahcalgo(&s, ahcalgo, _state); - clusterizerrunahc(&s, &rep, _state); - - /* - * Test with ErrorsInMerges() - */ - if( testclusteringunit_errorsinmerges(&dm, &xy, npoints, d, &rep, ahcalgo, _state) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Test distance matrix - */ - clusterizergetdistances(&xy, npoints, d, disttypes.ptr.p_int[disttype], &dm2, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=npoints-1; j++) - { - if( !ae_isfinite(dm2.ptr.pp_double[i][j], _state)||ae_fp_greater(ae_fabs(dm.ptr.pp_double[i][j]-dm2.ptr.pp_double[i][j], _state),1.0E5*ae_machineepsilon) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Simple test 1: ellipsoid in NF-dimensional space. -compare k-means centers with random centers -*************************************************************************/ -static void testclusteringunit_kmeanssimpletest1(ae_int_t nvars, - ae_int_t nc, - ae_int_t passcount, - ae_bool* converrors, - ae_bool* othererrors, - ae_bool* simpleerrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t npoints; - ae_int_t majoraxis; - ae_matrix xy; - ae_vector tmp; - double v; - ae_int_t i; - ae_int_t j; - ae_int_t pass; - ae_int_t restarts; - double ekmeans; - double erandom; - double dclosest; - ae_int_t cclosest; - clusterizerstate s; - kmeansreport rep; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&tmp, 0, sizeof(tmp)); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - _clusterizerstate_init(&s, _state, ae_true); - _kmeansreport_init(&rep, _state, ae_true); - - npoints = nc*100; - restarts = 5; - passcount = 10; - ae_vector_set_length(&tmp, nvars-1+1, _state); - for(pass=1; pass<=passcount; pass++) - { - - /* - * Fill - */ - ae_matrix_set_length(&xy, npoints-1+1, nvars-1+1, _state); - majoraxis = ae_randominteger(nvars, _state); - for(i=0; i<=npoints-1; i++) - { - testclusteringunit_rsphere(&xy, nvars, i, _state); - xy.ptr.pp_double[i][majoraxis] = nc*xy.ptr.pp_double[i][majoraxis]; - } - - /* - * Test - */ - clusterizercreate(&s, _state); - clusterizersetpoints(&s, &xy, npoints, nvars, 2, _state); - clusterizersetkmeanslimits(&s, restarts, 0, _state); - clusterizerrunkmeans(&s, nc, &rep, _state); - if( rep.terminationtype<=0 ) - { - *converrors = ae_true; - ae_frame_leave(_state); - return; - } - - /* - * Test that XYC is correct mapping to cluster centers - */ - for(i=0; i<=npoints-1; i++) - { - cclosest = -1; - dclosest = ae_maxrealnumber; - for(j=0; j<=nc-1; j++) - { - ae_v_move(&tmp.ptr.p_double[0], 1, &xy.ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - ae_v_sub(&tmp.ptr.p_double[0], 1, &rep.c.ptr.pp_double[j][0], 1, ae_v_len(0,nvars-1)); - v = ae_v_dotproduct(&tmp.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,nvars-1)); - if( ae_fp_less(v,dclosest) ) - { - cclosest = j; - dclosest = v; - } - } - if( cclosest!=rep.cidx.ptr.p_int[i] ) - { - *othererrors = ae_true; - ae_frame_leave(_state); - return; - } - } - - /* - * Use first NC rows of XY as random centers - * (XY is totally random, so it is as good as any other choice). - * - * Compare potential functions. - */ - ekmeans = (double)(0); - for(i=0; i<=npoints-1; i++) - { - ae_v_move(&tmp.ptr.p_double[0], 1, &xy.ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - ae_v_sub(&tmp.ptr.p_double[0], 1, &rep.c.ptr.pp_double[rep.cidx.ptr.p_int[i]][0], 1, ae_v_len(0,nvars-1)); - v = ae_v_dotproduct(&tmp.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,nvars-1)); - ekmeans = ekmeans+v; - } - erandom = (double)(0); - for(i=0; i<=npoints-1; i++) - { - dclosest = ae_maxrealnumber; - v = (double)(0); - for(j=0; j<=nc-1; j++) - { - ae_v_move(&tmp.ptr.p_double[0], 1, &xy.ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - ae_v_sub(&tmp.ptr.p_double[0], 1, &xy.ptr.pp_double[j][0], 1, ae_v_len(0,nvars-1)); - v = ae_v_dotproduct(&tmp.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,nvars-1)); - if( ae_fp_less(v,dclosest) ) - { - dclosest = v; - } - } - erandom = erandom+v; - } - if( ae_fp_less(erandom,ekmeans) ) - { - *simpleerrors = ae_true; - ae_frame_leave(_state); - return; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This test perform several checks for special properties - -On failure sets error flag, on success leaves it unchanged. -*************************************************************************/ -static void testclusteringunit_kmeansspecialtests(ae_bool* othererrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t npoints; - ae_int_t nfeatures; - ae_int_t nclusters; - ae_int_t initalgo; - ae_matrix xy; - ae_matrix c; - ae_int_t idx0; - ae_int_t idx1; - ae_int_t idx2; - ae_int_t i; - ae_int_t j; - ae_int_t pass; - ae_int_t passcount; - ae_int_t separation; - ae_vector xyc; - ae_vector xycref; - ae_vector xydist2; - ae_vector xydist2ref; - ae_vector energies; - hqrndstate rs; - clusterizerstate s; - kmeansreport rep; - ae_shared_pool bufferpool; - apbuffers bufferseed; - ae_vector pointslist; - ae_vector featureslist; - ae_vector clusterslist; - ae_bool allsame; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&c, 0, sizeof(c)); - memset(&xyc, 0, sizeof(xyc)); - memset(&xycref, 0, sizeof(xycref)); - memset(&xydist2, 0, sizeof(xydist2)); - memset(&xydist2ref, 0, sizeof(xydist2ref)); - memset(&energies, 0, sizeof(energies)); - memset(&rs, 0, sizeof(rs)); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&bufferpool, 0, sizeof(bufferpool)); - memset(&bufferseed, 0, sizeof(bufferseed)); - memset(&pointslist, 0, sizeof(pointslist)); - memset(&featureslist, 0, sizeof(featureslist)); - memset(&clusterslist, 0, sizeof(clusterslist)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xyc, 0, DT_INT, _state, ae_true); - ae_vector_init(&xycref, 0, DT_INT, _state, ae_true); - ae_vector_init(&xydist2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xydist2ref, 0, DT_REAL, _state, ae_true); - ae_vector_init(&energies, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - _clusterizerstate_init(&s, _state, ae_true); - _kmeansreport_init(&rep, _state, ae_true); - ae_shared_pool_init(&bufferpool, _state, ae_true); - _apbuffers_init(&bufferseed, _state, ae_true); - ae_vector_init(&pointslist, 0, DT_INT, _state, ae_true); - ae_vector_init(&featureslist, 0, DT_INT, _state, ae_true); - ae_vector_init(&clusterslist, 0, DT_INT, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Compare different initialization algorithms: - * * dataset is K balls, chosen at random gaussian points, with - * radius equal to 2^(-Separation). - * * we generate random sample, run k-means initialization algorithm - * and calculate mean energy for each initialization algorithm. - * In order to suppress Lloyd's iteration we use KmeansDbgNoIts - * debug flag. - * * then, we compare mean energies; kmeans++ must be best one, - * random initialization must be worst one. - */ - ae_vector_set_length(&energies, 4, _state); - passcount = 1000; - npoints = 100; - nfeatures = 3; - nclusters = 6; - ae_matrix_set_length(&xy, npoints, nfeatures, _state); - ae_matrix_set_length(&c, nclusters, nfeatures, _state); - clusterizercreate(&s, _state); - s.kmeansdbgnoits = ae_true; - for(separation=2; separation<=5; separation++) - { - - /* - * Try different init algorithms - */ - for(initalgo=1; initalgo<=3; initalgo++) - { - energies.ptr.p_double[initalgo] = 0.0; - clusterizersetkmeansinit(&s, initalgo, _state); - for(pass=1; pass<=passcount; pass++) - { - - /* - * Generate centers of balls - */ - for(i=0; i<=nclusters-1; i++) - { - for(j=0; j<=nfeatures-1; j++) - { - c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - - /* - * Generate points - */ - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nfeatures-1; j++) - { - xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state)*ae_pow((double)(2), (double)(-separation), _state)+c.ptr.pp_double[i%nclusters][j]; - } - } - - /* - * Run clusterization - */ - clusterizersetpoints(&s, &xy, npoints, nfeatures, 2, _state); - clusterizerrunkmeans(&s, nclusters, &rep, _state); - ae_set_error_flag(othererrors, rep.terminationtype<=0, __FILE__, __LINE__, "testclusteringunit.ap:1069"); - energies.ptr.p_double[initalgo] = energies.ptr.p_double[initalgo]+rep.energy/passcount; - } - } - - /* - * Compare - */ - ae_set_error_flag(othererrors, !ae_fp_less(energies.ptr.p_double[2],energies.ptr.p_double[1]), __FILE__, __LINE__, "testclusteringunit.ap:1077"); - ae_set_error_flag(othererrors, !ae_fp_less(energies.ptr.p_double[3],energies.ptr.p_double[1]), __FILE__, __LINE__, "testclusteringunit.ap:1078"); - } - - /* - * Test distance calculation algorithm - */ - ae_vector_set_length(&pointslist, 6, _state); - pointslist.ptr.p_int[0] = 1; - pointslist.ptr.p_int[1] = 10; - pointslist.ptr.p_int[2] = 32; - pointslist.ptr.p_int[3] = 100; - pointslist.ptr.p_int[4] = 512; - pointslist.ptr.p_int[5] = 8000; - ae_vector_set_length(&featureslist, 5, _state); - featureslist.ptr.p_int[0] = 1; - featureslist.ptr.p_int[1] = 5; - featureslist.ptr.p_int[2] = 32; - featureslist.ptr.p_int[3] = 50; - featureslist.ptr.p_int[4] = 96; - ae_vector_set_length(&clusterslist, 5, _state); - clusterslist.ptr.p_int[0] = 1; - clusterslist.ptr.p_int[1] = 5; - clusterslist.ptr.p_int[2] = 32; - clusterslist.ptr.p_int[3] = 50; - clusterslist.ptr.p_int[4] = 96; - ae_shared_pool_set_seed(&bufferpool, &bufferseed, sizeof(bufferseed), _apbuffers_init, _apbuffers_init_copy, _apbuffers_destroy, _state); - for(idx0=0; idx0<=pointslist.cnt-1; idx0++) - { - for(idx1=0; idx1<=featureslist.cnt-1; idx1++) - { - for(idx2=0; idx2<=clusterslist.cnt-1; idx2++) - { - npoints = pointslist.ptr.p_int[idx0]; - nfeatures = featureslist.ptr.p_int[idx1]; - nclusters = clusterslist.ptr.p_int[idx2]; - ae_matrix_set_length(&xy, npoints, nfeatures, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nfeatures-1; j++) - { - xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - ae_matrix_set_length(&c, nclusters, nfeatures, _state); - for(i=0; i<=nclusters-1; i++) - { - for(j=0; j<=nfeatures-1; j++) - { - c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - ae_vector_set_length(&xyc, npoints, _state); - ae_vector_set_length(&xycref, npoints, _state); - ae_vector_set_length(&xydist2, npoints, _state); - ae_vector_set_length(&xydist2ref, npoints, _state); - - /* - * Test - */ - kmeansupdatedistances(&xy, 0, npoints, nfeatures, &c, 0, nclusters, &xyc, &xydist2, &bufferpool, _state); - testclusteringunit_kmeansreferenceupdatedistances(&xy, npoints, nfeatures, &c, nclusters, &xycref, &xydist2ref, _state); - for(i=0; i<=npoints-1; i++) - { - ae_set_error_flag(othererrors, xyc.ptr.p_int[i]!=xycref.ptr.p_int[i], __FILE__, __LINE__, "testclusteringunit.ap:1137"); - ae_set_error_flag(othererrors, ae_fp_greater(ae_fabs(xydist2.ptr.p_double[i]-xydist2ref.ptr.p_double[i], _state),1.0E-6), __FILE__, __LINE__, "testclusteringunit.ap:1138"); - } - } - } - } - - /* - * Test degenerate dataset (less than NClusters distinct points) - */ - for(nclusters=2; nclusters<=10; nclusters++) - { - for(initalgo=0; initalgo<=3; initalgo++) - { - for(pass=1; pass<=10; pass++) - { - - /* - * Initialize points. Two algorithms are used: - * * initialization by small integers (no rounding problems) - * * initialization by "long" fraction - */ - npoints = 100; - nfeatures = 10; - ae_matrix_set_length(&xy, npoints, nfeatures, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - for(i=0; i<=nclusters-2; i++) - { - for(j=0; j<=nfeatures-1; j++) - { - xy.ptr.pp_double[i][j] = ae_sin(hqrndnormal(&rs, _state), _state); - } - } - } - else - { - for(i=0; i<=nclusters-2; i++) - { - for(j=0; j<=nfeatures-1; j++) - { - xy.ptr.pp_double[i][j] = (double)(hqrnduniformi(&rs, 50, _state)); - } - } - } - for(i=nclusters-1; i<=npoints-1; i++) - { - idx0 = hqrnduniformi(&rs, nclusters-1, _state); - for(j=0; j<=nfeatures-1; j++) - { - xy.ptr.pp_double[i][j] = xy.ptr.pp_double[idx0][j]; - } - } - - /* - * Clusterize with unlimited number of iterations. - * Correct error code must be returned. - */ - clusterizercreate(&s, _state); - clusterizersetpoints(&s, &xy, npoints, nfeatures, 2, _state); - clusterizersetkmeanslimits(&s, 1, 0, _state); - clusterizersetkmeansinit(&s, initalgo, _state); - clusterizerrunkmeans(&s, nclusters, &rep, _state); - ae_set_error_flag(othererrors, rep.terminationtype!=-3, __FILE__, __LINE__, "testclusteringunit.ap:1185"); - } - } - } - - /* - * Test deterministic seed: - * * specyfying zero seed, or not specyfind seed at all = nondeterministic algo - * * nonzero zeed = deterministic algo - */ - for(initalgo=0; initalgo<=3; initalgo++) - { - - /* - * Initialize points. - */ - npoints = 100; - nfeatures = 3; - ae_matrix_set_length(&xy, npoints, nfeatures, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nfeatures-1; j++) - { - xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - - /* - * Clusterize with negative seed. - * - * Perform multiple runs, compare results with - * first one returned - at least one result must - * be different. - */ - clusterizercreate(&s, _state); - clusterizersetpoints(&s, &xy, npoints, nfeatures, 2, _state); - clusterizersetkmeanslimits(&s, 1, 1, _state); - clusterizersetkmeansinit(&s, initalgo, _state); - clusterizersetseed(&s, -ae_randominteger(3, _state), _state); - allsame = ae_true; - for(pass=0; pass<=10; pass++) - { - clusterizerrunkmeans(&s, nclusters, &rep, _state); - ae_set_error_flag(othererrors, rep.terminationtype<=0, __FILE__, __LINE__, "testclusteringunit.ap:1221"); - if( *othererrors ) - { - ae_frame_leave(_state); - return; - } - if( pass==0 ) - { - - /* - * Save clusters - */ - ae_matrix_set_length(&c, rep.c.rows, rep.c.cols, _state); - for(i=0; i<=rep.c.rows-1; i++) - { - for(j=0; j<=rep.c.cols-1; j++) - { - c.ptr.pp_double[i][j] = rep.c.ptr.pp_double[i][j]; - } - } - } - else - { - - /* - * Compare clusters with ones returned from first run. - */ - for(i=0; i<=rep.c.rows-1; i++) - { - for(j=0; j<=rep.c.cols-1; j++) - { - allsame = allsame&&ae_fp_eq(c.ptr.pp_double[i][j],rep.c.ptr.pp_double[i][j]); - } - } - } - } - ae_set_error_flag(othererrors, allsame, __FILE__, __LINE__, "testclusteringunit.ap:1244"); - - /* - * Clusterize with positive seed. - * - * Perform multiple runs, compare results with - * first one returned - all results must be same. - */ - clusterizercreate(&s, _state); - clusterizersetpoints(&s, &xy, npoints, nfeatures, 2, _state); - clusterizersetkmeanslimits(&s, 1, 1, _state); - clusterizersetkmeansinit(&s, initalgo, _state); - clusterizersetseed(&s, 1+ae_randominteger(3, _state), _state); - allsame = ae_true; - for(pass=0; pass<=10; pass++) - { - clusterizerrunkmeans(&s, nclusters, &rep, _state); - ae_set_error_flag(othererrors, rep.terminationtype<=0, __FILE__, __LINE__, "testclusteringunit.ap:1261"); - if( *othererrors ) - { - ae_frame_leave(_state); - return; - } - if( pass==0 ) - { - - /* - * Save clusters - */ - ae_matrix_set_length(&c, rep.c.rows, rep.c.cols, _state); - for(i=0; i<=rep.c.rows-1; i++) - { - for(j=0; j<=rep.c.cols-1; j++) - { - c.ptr.pp_double[i][j] = rep.c.ptr.pp_double[i][j]; - } - } - } - else - { - - /* - * Compare clusters with ones returned from first run. - */ - for(i=0; i<=rep.c.rows-1; i++) - { - for(j=0; j<=rep.c.cols-1; j++) - { - allsame = allsame&&ae_fp_eq(c.ptr.pp_double[i][j],rep.c.ptr.pp_double[i][j]); - } - } - } - } - ae_set_error_flag(othererrors, !allsame, __FILE__, __LINE__, "testclusteringunit.ap:1284"); - - /* - * Clusterize with default seed. - * - * Perform multiple runs, compare results with - * first one returned - all results must be same. - */ - clusterizercreate(&s, _state); - clusterizersetpoints(&s, &xy, npoints, nfeatures, 2, _state); - clusterizersetkmeanslimits(&s, 1, 1, _state); - clusterizersetkmeansinit(&s, initalgo, _state); - allsame = ae_true; - for(pass=0; pass<=10; pass++) - { - clusterizerrunkmeans(&s, nclusters, &rep, _state); - ae_set_error_flag(othererrors, rep.terminationtype<=0, __FILE__, __LINE__, "testclusteringunit.ap:1301"); - if( *othererrors ) - { - ae_frame_leave(_state); - return; - } - if( pass==0 ) - { - - /* - * Save clusters - */ - ae_matrix_set_length(&c, rep.c.rows, rep.c.cols, _state); - for(i=0; i<=rep.c.rows-1; i++) - { - for(j=0; j<=rep.c.cols-1; j++) - { - c.ptr.pp_double[i][j] = rep.c.ptr.pp_double[i][j]; - } - } - } - else - { - - /* - * Compare clusters with ones returned from first run. - */ - for(i=0; i<=rep.c.rows-1; i++) - { - for(j=0; j<=rep.c.cols-1; j++) - { - allsame = allsame&&ae_fp_eq(c.ptr.pp_double[i][j],rep.c.ptr.pp_double[i][j]); - } - } - } - } - ae_set_error_flag(othererrors, !allsame, __FILE__, __LINE__, "testclusteringunit.ap:1324"); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This test checks algorithm ability to handle degenerate problems without -causing infinite loop. -*************************************************************************/ -static void testclusteringunit_kmeansinfinitelooptest(ae_bool* othererrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t npoints; - ae_int_t nfeatures; - ae_int_t nclusters; - ae_int_t restarts; - ae_matrix xy; - ae_int_t i; - ae_int_t j; - clusterizerstate s; - kmeansreport rep; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _clusterizerstate_init(&s, _state, ae_true); - _kmeansreport_init(&rep, _state, ae_true); - - - /* - * Problem 1: all points are same. - * - * For NClusters=1 we must get correct solution, for NClusters>1 we must get failure. - */ - npoints = 100; - nfeatures = 1; - restarts = 5; - ae_matrix_set_length(&xy, npoints, nfeatures, _state); - for(j=0; j<=nfeatures-1; j++) - { - xy.ptr.pp_double[0][j] = ae_randomreal(_state); - } - for(i=1; i<=npoints-1; i++) - { - for(j=0; j<=nfeatures-1; j++) - { - xy.ptr.pp_double[i][j] = xy.ptr.pp_double[0][j]; - } - } - nclusters = 1; - clusterizercreate(&s, _state); - clusterizersetpoints(&s, &xy, npoints, nfeatures, 2, _state); - clusterizersetkmeanslimits(&s, restarts, 0, _state); - clusterizerrunkmeans(&s, nclusters, &rep, _state); - *othererrors = *othererrors||rep.terminationtype<=0; - for(i=0; i<=nfeatures-1; i++) - { - *othererrors = *othererrors||ae_fp_greater(ae_fabs(rep.c.ptr.pp_double[0][i]-xy.ptr.pp_double[0][i], _state),1000*ae_machineepsilon); - } - for(i=0; i<=npoints-1; i++) - { - *othererrors = *othererrors||rep.cidx.ptr.p_int[i]!=0; - } - nclusters = 5; - clusterizerrunkmeans(&s, nclusters, &rep, _state); - *othererrors = *othererrors||rep.terminationtype>0; - - /* - * Problem 2: degenerate dataset (report by Andreas). - */ - npoints = 57; - nfeatures = 1; - restarts = 1; - nclusters = 4; - ae_matrix_set_length(&xy, npoints, nfeatures, _state); - xy.ptr.pp_double[0][0] = 12.244689632138986; - xy.ptr.pp_double[1][0] = 12.244689632138982; - xy.ptr.pp_double[2][0] = 12.244689632138986; - xy.ptr.pp_double[3][0] = 12.244689632138982; - xy.ptr.pp_double[4][0] = 12.244689632138986; - xy.ptr.pp_double[5][0] = 12.244689632138986; - xy.ptr.pp_double[6][0] = 12.244689632138986; - xy.ptr.pp_double[7][0] = 12.244689632138986; - xy.ptr.pp_double[8][0] = 12.244689632138986; - xy.ptr.pp_double[9][0] = 12.244689632138986; - xy.ptr.pp_double[10][0] = 12.244689632138989; - xy.ptr.pp_double[11][0] = 12.244689632138984; - xy.ptr.pp_double[12][0] = 12.244689632138986; - xy.ptr.pp_double[13][0] = 12.244689632138986; - xy.ptr.pp_double[14][0] = 12.244689632138989; - xy.ptr.pp_double[15][0] = 12.244689632138986; - xy.ptr.pp_double[16][0] = 12.244689632138986; - xy.ptr.pp_double[17][0] = 12.244689632138986; - xy.ptr.pp_double[18][0] = 12.244689632138986; - xy.ptr.pp_double[19][0] = 12.244689632138989; - xy.ptr.pp_double[20][0] = 12.244689632138972; - xy.ptr.pp_double[21][0] = 12.244689632138986; - xy.ptr.pp_double[22][0] = 12.244689632138986; - xy.ptr.pp_double[23][0] = 12.244689632138986; - xy.ptr.pp_double[24][0] = 12.244689632138984; - xy.ptr.pp_double[25][0] = 12.244689632138982; - xy.ptr.pp_double[26][0] = 12.244689632138986; - xy.ptr.pp_double[27][0] = 12.244689632138986; - xy.ptr.pp_double[28][0] = 12.244689632138986; - xy.ptr.pp_double[29][0] = 12.244689632138986; - xy.ptr.pp_double[30][0] = 12.244689632138986; - xy.ptr.pp_double[31][0] = 12.244689632138986; - xy.ptr.pp_double[32][0] = 12.244689632138986; - xy.ptr.pp_double[33][0] = 12.244689632138986; - xy.ptr.pp_double[34][0] = 12.244689632138986; - xy.ptr.pp_double[35][0] = 12.244689632138982; - xy.ptr.pp_double[36][0] = 12.244689632138989; - xy.ptr.pp_double[37][0] = 12.244689632138986; - xy.ptr.pp_double[38][0] = 12.244689632138986; - xy.ptr.pp_double[39][0] = 12.244689632138986; - xy.ptr.pp_double[40][0] = 12.244689632138986; - xy.ptr.pp_double[41][0] = 12.244689632138986; - xy.ptr.pp_double[42][0] = 12.244689632138986; - xy.ptr.pp_double[43][0] = 12.244689632138986; - xy.ptr.pp_double[44][0] = 12.244689632138986; - xy.ptr.pp_double[45][0] = 12.244689632138986; - xy.ptr.pp_double[46][0] = 12.244689632138986; - xy.ptr.pp_double[47][0] = 12.244689632138986; - xy.ptr.pp_double[48][0] = 12.244689632138986; - xy.ptr.pp_double[49][0] = 12.244689632138986; - xy.ptr.pp_double[50][0] = 12.244689632138984; - xy.ptr.pp_double[51][0] = 12.244689632138986; - xy.ptr.pp_double[52][0] = 12.244689632138986; - xy.ptr.pp_double[53][0] = 12.244689632138986; - xy.ptr.pp_double[54][0] = 12.244689632138986; - xy.ptr.pp_double[55][0] = 12.244689632138986; - xy.ptr.pp_double[56][0] = 12.244689632138986; - clusterizercreate(&s, _state); - clusterizersetpoints(&s, &xy, npoints, nfeatures, 2, _state); - clusterizersetkmeanslimits(&s, restarts, 0, _state); - clusterizerrunkmeans(&s, nclusters, &rep, _state); - *othererrors = *othererrors||rep.terminationtype<=0; - ae_frame_leave(_state); -} - - -/************************************************************************* -This non-deterministic test checks that Restarts>1 significantly improves -quality of results. - -Subroutine generates random task 3 unit balls in 2D, each with 20 points, -separated by 5 units wide gaps, and solves it with Restarts=1 and with -Restarts=5. Potential functions are compared, outcome of the trial is -either 0 or 1 (depending on what is better). - -Sequence of 1000 such tasks is solved. If Restarts>1 actually improve -quality of solution, sum of outcome will be non-binomial. If it doesn't -matter, it will be binomially distributed. - -P.S. This test was added after report from Gianluca Borello who noticed -error in the handling of multiple restarts. -*************************************************************************/ -static void testclusteringunit_kmeansrestartstest(ae_bool* converrors, - ae_bool* restartserrors, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t npoints; - ae_int_t nvars; - ae_int_t nclusters; - ae_int_t clustersize; - ae_int_t restarts; - ae_int_t passcount; - double sigmathreshold; - double p; - double s; - ae_matrix xy; - ae_vector tmp; - ae_int_t i; - ae_int_t j; - ae_int_t pass; - double ea; - double eb; - double v; - clusterizerstate state; - kmeansreport rep1; - kmeansreport rep2; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&tmp, 0, sizeof(tmp)); - memset(&state, 0, sizeof(state)); - memset(&rep1, 0, sizeof(rep1)); - memset(&rep2, 0, sizeof(rep2)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - _clusterizerstate_init(&state, _state, ae_true); - _kmeansreport_init(&rep1, _state, ae_true); - _kmeansreport_init(&rep2, _state, ae_true); - - restarts = 5; - passcount = 1000; - clustersize = 20; - nclusters = 3; - nvars = 2; - npoints = nclusters*clustersize; - sigmathreshold = (double)(5); - ae_matrix_set_length(&xy, npoints, nvars, _state); - ae_vector_set_length(&tmp, nvars, _state); - p = (double)(0); - for(pass=1; pass<=passcount; pass++) - { - - /* - * Fill - */ - for(i=0; i<=npoints-1; i++) - { - testclusteringunit_rsphere(&xy, nvars, i, _state); - for(j=0; j<=nvars-1; j++) - { - xy.ptr.pp_double[i][j] = xy.ptr.pp_double[i][j]+(double)i/(double)clustersize*5; - } - } - clusterizercreate(&state, _state); - clusterizersetpoints(&state, &xy, npoints, nvars, 2, _state); - - /* - * Test: Restarts=1 - */ - clusterizersetkmeanslimits(&state, 1, 0, _state); - clusterizerrunkmeans(&state, nclusters, &rep1, _state); - if( rep1.terminationtype<=0 ) - { - *converrors = ae_true; - ae_frame_leave(_state); - return; - } - ea = (double)(0); - for(i=0; i<=npoints-1; i++) - { - ae_v_move(&tmp.ptr.p_double[0], 1, &xy.ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - ae_v_sub(&tmp.ptr.p_double[0], 1, &rep1.c.ptr.pp_double[rep1.cidx.ptr.p_int[i]][0], 1, ae_v_len(0,nvars-1)); - v = ae_v_dotproduct(&tmp.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,nvars-1)); - ea = ea+v; - } - - /* - * Test: Restarts>1 - */ - clusterizersetkmeanslimits(&state, restarts, 0, _state); - clusterizerrunkmeans(&state, nclusters, &rep2, _state); - if( rep2.terminationtype<=0 ) - { - *converrors = ae_true; - ae_frame_leave(_state); - return; - } - eb = (double)(0); - for(i=0; i<=npoints-1; i++) - { - ae_v_move(&tmp.ptr.p_double[0], 1, &xy.ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - ae_v_sub(&tmp.ptr.p_double[0], 1, &rep2.c.ptr.pp_double[rep2.cidx.ptr.p_int[i]][0], 1, ae_v_len(0,nvars-1)); - v = ae_v_dotproduct(&tmp.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,nvars-1)); - eb = eb+v; - } - - /* - * Calculate statistic. - */ - if( ae_fp_less(ea,eb) ) - { - p = p+1; - } - if( ae_fp_eq(ea,eb) ) - { - p = p+0.5; - } - } - - /* - * If Restarts doesn't influence quality of centers found, P must be - * binomially distributed random value with mean 0.5*PassCount and - * standard deviation Sqrt(PassCount/4). - * - * If Restarts do influence quality of solution, P must be significantly - * lower than 0.5*PassCount. - */ - s = (p-0.5*passcount)/ae_sqrt((double)passcount/(double)4, _state); - *restartserrors = *restartserrors||ae_fp_greater(s,-sigmathreshold); - ae_frame_leave(_state); -} - - -/************************************************************************* -Random normal number -*************************************************************************/ -static double testclusteringunit_rnormal(ae_state *_state) -{ - double u; - double v; - double s; - double x1; - double result; - - - for(;;) - { - u = 2*ae_randomreal(_state)-1; - v = 2*ae_randomreal(_state)-1; - s = ae_sqr(u, _state)+ae_sqr(v, _state); - if( ae_fp_greater(s,(double)(0))&&ae_fp_less(s,(double)(1)) ) - { - s = ae_sqrt(-2*ae_log(s, _state)/s, _state); - x1 = u*s; - break; - } - } - result = x1; - return result; -} - - -/************************************************************************* -Random point from sphere -*************************************************************************/ -static void testclusteringunit_rsphere(/* Real */ ae_matrix* xy, - ae_int_t n, - ae_int_t i, - ae_state *_state) -{ - ae_int_t j; - double v; - - - for(j=0; j<=n-1; j++) - { - xy->ptr.pp_double[i][j] = testclusteringunit_rnormal(_state); - } - v = ae_v_dotproduct(&xy->ptr.pp_double[i][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - v = ae_randomreal(_state)/ae_sqrt(v, _state); - ae_v_muld(&xy->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v); -} - - -/************************************************************************* -Distance function: distance between X0 and X1 - -X0, X1 - array[D], points -DistType - distance type -*************************************************************************/ -static double testclusteringunit_distfunc(/* Real */ ae_vector* x0, - /* Real */ ae_vector* x1, - ae_int_t d, - ae_int_t disttype, - ae_state *_state) -{ - ae_int_t i; - double s0; - double s1; - double result; - - - ae_assert((((((((disttype==0||disttype==1)||disttype==2)||disttype==10)||disttype==11)||disttype==12)||disttype==13)||disttype==20)||disttype==21, "Assertion failed", _state); - if( disttype==0 ) - { - result = 0.0; - for(i=0; i<=d-1; i++) - { - result = ae_maxreal(result, ae_fabs(x0->ptr.p_double[i]-x1->ptr.p_double[i], _state), _state); - } - return result; - } - if( disttype==1 ) - { - result = 0.0; - for(i=0; i<=d-1; i++) - { - result = result+ae_fabs(x0->ptr.p_double[i]-x1->ptr.p_double[i], _state); - } - return result; - } - if( disttype==2 ) - { - result = 0.0; - for(i=0; i<=d-1; i++) - { - result = result+ae_sqr(x0->ptr.p_double[i]-x1->ptr.p_double[i], _state); - } - result = ae_sqrt(result, _state); - return result; - } - if( disttype==10 ) - { - result = ae_maxreal(1-pearsoncorr2(x0, x1, d, _state), 0.0, _state); - return result; - } - if( disttype==11 ) - { - result = ae_maxreal(1-ae_fabs(pearsoncorr2(x0, x1, d, _state), _state), 0.0, _state); - return result; - } - if( disttype==12||disttype==13 ) - { - s0 = 0.0; - s1 = 0.0; - for(i=0; i<=d-1; i++) - { - s0 = s0+ae_sqr(x0->ptr.p_double[i], _state)/d; - s1 = s1+ae_sqr(x1->ptr.p_double[i], _state)/d; - } - s0 = ae_sqrt(s0, _state); - s1 = ae_sqrt(s1, _state); - result = (double)(0); - for(i=0; i<=d-1; i++) - { - result = result+x0->ptr.p_double[i]/s0*(x1->ptr.p_double[i]/s1)/d; - } - if( disttype==12 ) - { - result = ae_maxreal(1-result, 0.0, _state); - } - else - { - result = ae_maxreal(1-ae_fabs(result, _state), 0.0, _state); - } - return result; - } - if( disttype==20 ) - { - result = ae_maxreal(1-spearmancorr2(x0, x1, d, _state), 0.0, _state); - return result; - } - if( disttype==21 ) - { - result = ae_maxreal(1-ae_fabs(spearmancorr2(x0, x1, d, _state), _state), 0.0, _state); - return result; - } - result = (double)(0); - return result; -} - - -/************************************************************************* -This function replays merges and checks that: -* Rep.NPoints, Rep.Z, Rep.PZ and Rep.PM are consistent and correct -* Rep.MergeDist is consistent with distance between clusters being merged -* clusters with minimal distance are merged at each step -* GetKClusters() correctly unpacks clusters for each K - -NOTE: this algorithm correctly handle ties, i.e. situations where several - pairs of clusters have same intercluster distance, and we can't - unambiguously choose clusters to merge. - -INPUT PARAMETERS - D - distance matrix, array[NPoints,NPoints], full matrix - is given (including both triangles and zeros on the - main diagonal) - XY - dataset matrix, array[NPoints,NF] - NPoints - dataset size - NF - number of features - Rep - clusterizer report - AHCAlgo - AHC algorithm: - * 0 - complete linkage - * 1 - single linkage - * 2 - unweighted average linkage - -This function returns True on failure, False on success. -*************************************************************************/ -static ae_bool testclusteringunit_errorsinmerges(/* Real */ ae_matrix* d, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nf, - ahcreport* rep, - ae_int_t ahcalgo, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix dm; - ae_matrix cm; - ae_vector clustersizes; - ae_vector clusterheights; - ae_vector b; - ae_vector x0; - ae_vector x1; - ae_bool bflag; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t i0; - ae_int_t i1; - ae_int_t c0; - ae_int_t c1; - ae_int_t s0; - ae_int_t s1; - double v; - ae_int_t t; - ae_int_t mergeidx; - ae_vector kidx; - ae_vector kidxz; - ae_int_t currentelement; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&dm, 0, sizeof(dm)); - memset(&cm, 0, sizeof(cm)); - memset(&clustersizes, 0, sizeof(clustersizes)); - memset(&clusterheights, 0, sizeof(clusterheights)); - memset(&b, 0, sizeof(b)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&kidx, 0, sizeof(kidx)); - memset(&kidxz, 0, sizeof(kidxz)); - ae_matrix_init(&dm, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&cm, 0, 0, DT_INT, _state, ae_true); - ae_vector_init(&clustersizes, 0, DT_INT, _state, ae_true); - ae_vector_init(&clusterheights, 0, DT_INT, _state, ae_true); - ae_vector_init(&b, 0, DT_BOOL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&kidx, 0, DT_INT, _state, ae_true); - ae_vector_init(&kidxz, 0, DT_INT, _state, ae_true); - - ae_assert(ahcalgo!=3, "integrity error", _state); - result = ae_false; - ae_vector_set_length(&x0, nf, _state); - ae_vector_set_length(&x1, nf, _state); - - /* - * Basic checks: - * * positive completion code - * * sizes of arrays - * * Rep.P is correct permutation - * * Rep.Z contains correct cluster indexes - * * Rep.PZ is consistent with Rep.P/Rep.Z - * * Rep.PM contains consistent indexes - * * GetKClusters() for K=NPoints - */ - bflag = ae_false; - bflag = bflag||rep->terminationtype<=0; - if( bflag ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - bflag = bflag||rep->npoints!=npoints; - bflag = (bflag||rep->z.rows!=npoints-1)||(npoints>1&&rep->z.cols!=2); - bflag = (bflag||rep->pz.rows!=npoints-1)||(npoints>1&&rep->pz.cols!=2); - bflag = (bflag||rep->pm.rows!=npoints-1)||(npoints>1&&rep->pm.cols!=6); - bflag = bflag||rep->mergedist.cnt!=npoints-1; - bflag = bflag||rep->p.cnt!=npoints; - if( bflag ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - ae_vector_set_length(&b, npoints, _state); - for(i=0; i<=npoints-1; i++) - { - b.ptr.p_bool[i] = ae_false; - } - for(i=0; i<=npoints-1; i++) - { - if( (rep->p.ptr.p_int[i]<0||rep->p.ptr.p_int[i]>=npoints)||b.ptr.p_bool[rep->p.ptr.p_int[i]] ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - b.ptr.p_bool[rep->p.ptr.p_int[i]] = ae_true; - } - for(i=0; i<=npoints-2; i++) - { - if( (rep->z.ptr.pp_int[i][0]<0||rep->z.ptr.pp_int[i][0]>=rep->z.ptr.pp_int[i][1])||rep->z.ptr.pp_int[i][1]>=npoints+i ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - if( (rep->pz.ptr.pp_int[i][0]<0||rep->pz.ptr.pp_int[i][0]>=rep->pz.ptr.pp_int[i][1])||rep->pz.ptr.pp_int[i][1]>=npoints+i ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - for(i=0; i<=npoints-2; i++) - { - c0 = rep->z.ptr.pp_int[i][0]; - c1 = rep->z.ptr.pp_int[i][1]; - s0 = rep->pz.ptr.pp_int[i][0]; - s1 = rep->pz.ptr.pp_int[i][1]; - if( c0p.ptr.p_int[c0]; - } - if( c1p.ptr.p_int[c1]; - } - if( c0!=s0||c1!=s1 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - clusterizergetkclusters(rep, npoints, &kidx, &kidxz, _state); - if( kidx.cnt!=npoints||kidxz.cnt!=npoints ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=npoints-1; i++) - { - if( kidxz.ptr.p_int[i]!=i||kidx.ptr.p_int[i]!=i ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - - /* - * Test description: - * * we generate (2*NPoints-1)x(2*NPoints-1) matrix of distances DM and - * (2*NPoints-1)xNPoints matrix of clusters CM (I-th row contains indexes - * of elements which belong to I-th cluster, negative indexes denote - * empty cells). Leading N*N square of DM is just a distance matrix, - * other elements are filled by some large number M (used to mark empty - * elements). - * * we replay all merges - * * every time we merge clusters I and J into K, we: - * * check that distance between I and J is equal to the smallest - * element of DM (note: we account for rounding errors when we - * decide on that) - * * check that distance is consistent with Rep.MergeDist - * * then, we enumerate all elements in clusters being merged, - * and check that after permutation their indexes fall into range - * prescribed by Rep.PM - * * fill K-th column/row of D by distances to cluster K - * * merge I-th and J-th rows of CM and store result into K-th row - * * clear DM and CM: fill I-th and J-th column/row of DM by large - * number M, fill I-th and J-th row of CM by -1. - * - * NOTE: DM is initialized by distance metric specific to AHC algorithm - * being used. CLINK, SLINK and average linkage use user-provided - * distance measure, say Euclidean one, without any modifications. - * Ward's method uses (and reports) squared and scaled Euclidean - * distances. - */ - ae_matrix_set_length(&dm, 2*npoints-1, 2*npoints-1, _state); - ae_matrix_set_length(&cm, 2*npoints-1, npoints, _state); - ae_vector_set_length(&clustersizes, 2*npoints-1, _state); - for(i=0; i<=2*npoints-2; i++) - { - for(j=0; j<=2*npoints-2; j++) - { - if( iptr.pp_double[i][j]; - if( ahcalgo==4 ) - { - dm.ptr.pp_double[i][j] = 0.5*ae_sqr(dm.ptr.pp_double[i][j], _state); - } - } - else - { - dm.ptr.pp_double[i][j] = ae_maxrealnumber; - } - } - } - for(i=0; i<=2*npoints-2; i++) - { - for(j=0; j<=npoints-1; j++) - { - cm.ptr.pp_int[i][j] = -1; - } - } - for(i=0; i<=npoints-1; i++) - { - cm.ptr.pp_int[i][0] = i; - clustersizes.ptr.p_int[i] = 1; - } - for(i=npoints; i<=2*npoints-2; i++) - { - clustersizes.ptr.p_int[i] = 0; - } - ae_vector_set_length(&clusterheights, 2*npoints-1, _state); - for(i=0; i<=npoints-1; i++) - { - clusterheights.ptr.p_int[i] = 0; - } - for(mergeidx=0; mergeidx<=npoints-2; mergeidx++) - { - - /* - * Check that clusters with minimum distance are merged, - * and that MergeDist is consistent with results. - * - * NOTE: we do not check for specific cluster indexes, - * because it is possible to have a tie. We just - * check that distance between clusters is a true - * minimum over all possible clusters. - */ - v = ae_maxrealnumber; - for(i=0; i<=2*npoints-2; i++) - { - for(j=0; j<=2*npoints-2; j++) - { - if( i!=j ) - { - v = ae_minreal(v, dm.ptr.pp_double[i][j], _state); - } - } - } - c0 = rep->z.ptr.pp_int[mergeidx][0]; - c1 = rep->z.ptr.pp_int[mergeidx][1]; - if( ae_fp_greater(dm.ptr.pp_double[c0][c1],v+10000*ae_machineepsilon) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - if( ae_fp_greater(rep->mergedist.ptr.p_double[mergeidx],v+10000*ae_machineepsilon) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Check that indexes of elements fall into range prescribed by Rep.PM, - * and Rep.PM correctly described merge operation - */ - s0 = clustersizes.ptr.p_int[c0]; - s1 = clustersizes.ptr.p_int[c1]; - for(j=0; j<=clustersizes.ptr.p_int[c0]-1; j++) - { - if( rep->p.ptr.p_int[cm.ptr.pp_int[c0][j]]pm.ptr.pp_int[mergeidx][0]||rep->p.ptr.p_int[cm.ptr.pp_int[c0][j]]>rep->pm.ptr.pp_int[mergeidx][1] ) - { - - /* - * Element falls outside of range described by PM - */ - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - for(j=0; j<=clustersizes.ptr.p_int[c1]-1; j++) - { - if( rep->p.ptr.p_int[cm.ptr.pp_int[c1][j]]pm.ptr.pp_int[mergeidx][2]||rep->p.ptr.p_int[cm.ptr.pp_int[c1][j]]>rep->pm.ptr.pp_int[mergeidx][3] ) - { - - /* - * Element falls outside of range described by PM - */ - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - if( (rep->pm.ptr.pp_int[mergeidx][1]-rep->pm.ptr.pp_int[mergeidx][0]!=s0-1||rep->pm.ptr.pp_int[mergeidx][3]-rep->pm.ptr.pp_int[mergeidx][2]!=s1-1)||rep->pm.ptr.pp_int[mergeidx][2]!=rep->pm.ptr.pp_int[mergeidx][1]+1 ) - { - - /* - * Cluster size (as given by PM) is inconsistent with its actual size. - */ - result = ae_true; - ae_frame_leave(_state); - return result; - } - if( rep->pm.ptr.pp_int[mergeidx][4]!=clusterheights.ptr.p_int[rep->z.ptr.pp_int[mergeidx][0]]||rep->pm.ptr.pp_int[mergeidx][5]!=clusterheights.ptr.p_int[rep->z.ptr.pp_int[mergeidx][1]] ) - { - - /* - * Heights of subdendrograms as returned by PM are inconsistent with heights - * calculated by us. - */ - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Update cluster heights - */ - clusterheights.ptr.p_int[mergeidx+npoints] = ae_maxint(clusterheights.ptr.p_int[rep->z.ptr.pp_int[mergeidx][0]], clusterheights.ptr.p_int[rep->z.ptr.pp_int[mergeidx][1]], _state)+1; - - /* - * Update CM - */ - t = 0; - for(j=0; j<=clustersizes.ptr.p_int[rep->z.ptr.pp_int[mergeidx][0]]-1; j++) - { - cm.ptr.pp_int[npoints+mergeidx][t] = cm.ptr.pp_int[rep->z.ptr.pp_int[mergeidx][0]][j]; - t = t+1; - } - for(j=0; j<=clustersizes.ptr.p_int[rep->z.ptr.pp_int[mergeidx][1]]-1; j++) - { - cm.ptr.pp_int[npoints+mergeidx][t] = cm.ptr.pp_int[rep->z.ptr.pp_int[mergeidx][1]][j]; - t = t+1; - } - clustersizes.ptr.p_int[npoints+mergeidx] = t; - clustersizes.ptr.p_int[rep->z.ptr.pp_int[mergeidx][0]] = 0; - clustersizes.ptr.p_int[rep->z.ptr.pp_int[mergeidx][1]] = 0; - - /* - * Update distance matrix D - */ - for(i=0; i<=2*npoints-2; i++) - { - - /* - * "Remove" columns/rows corresponding to clusters being merged - */ - dm.ptr.pp_double[i][rep->z.ptr.pp_int[mergeidx][0]] = ae_maxrealnumber; - dm.ptr.pp_double[i][rep->z.ptr.pp_int[mergeidx][1]] = ae_maxrealnumber; - dm.ptr.pp_double[rep->z.ptr.pp_int[mergeidx][0]][i] = ae_maxrealnumber; - dm.ptr.pp_double[rep->z.ptr.pp_int[mergeidx][1]][i] = ae_maxrealnumber; - } - for(i=0; i<=npoints+mergeidx-1; i++) - { - if( clustersizes.ptr.p_int[i]>0 ) - { - - /* - * Calculate column/row corresponding to new cluster - */ - if( ahcalgo==0 ) - { - - /* - * Calculate distance between clusters I and NPoints+MergeIdx for CLINK - */ - v = 0.0; - for(i0=0; i0<=clustersizes.ptr.p_int[i]-1; i0++) - { - for(i1=0; i1<=clustersizes.ptr.p_int[npoints+mergeidx]-1; i1++) - { - v = ae_maxreal(v, d->ptr.pp_double[cm.ptr.pp_int[i][i0]][cm.ptr.pp_int[npoints+mergeidx][i1]], _state); - } - } - } - if( ahcalgo==1 ) - { - - /* - * Calculate distance between clusters I and NPoints+MergeIdx for SLINK - */ - v = ae_maxrealnumber; - for(i0=0; i0<=clustersizes.ptr.p_int[i]-1; i0++) - { - for(i1=0; i1<=clustersizes.ptr.p_int[npoints+mergeidx]-1; i1++) - { - v = ae_minreal(v, d->ptr.pp_double[cm.ptr.pp_int[i][i0]][cm.ptr.pp_int[npoints+mergeidx][i1]], _state); - } - } - } - if( ahcalgo==2 ) - { - - /* - * Calculate distance between clusters I and NPoints+MergeIdx for unweighted average - */ - v = 0.0; - t = 0; - for(i0=0; i0<=clustersizes.ptr.p_int[i]-1; i0++) - { - for(i1=0; i1<=clustersizes.ptr.p_int[npoints+mergeidx]-1; i1++) - { - v = v+d->ptr.pp_double[cm.ptr.pp_int[i][i0]][cm.ptr.pp_int[npoints+mergeidx][i1]]; - t = t+1; - } - } - v = v/t; - } - if( ahcalgo==3 ) - { - ae_assert(ae_false, "Assertion failed", _state); - } - if( ahcalgo==4 ) - { - - /* - * Calculate distance between clusters I and NPoints+MergeIdx for Ward's method: - * * X0 = center of mass for cluster I - * * X1 = center of mass for cluster NPoints+MergeIdx - * * S0 = size of cluster I - * * S1 = size of cluster NPoints+MergeIdx - * * distance between clusters is S0*S1/(S0+S1)*|X0-X1|^2 - * - */ - for(j=0; j<=nf-1; j++) - { - x0.ptr.p_double[j] = 0.0; - x1.ptr.p_double[j] = 0.0; - } - for(i0=0; i0<=clustersizes.ptr.p_int[i]-1; i0++) - { - for(j=0; j<=nf-1; j++) - { - x0.ptr.p_double[j] = x0.ptr.p_double[j]+xy->ptr.pp_double[cm.ptr.pp_int[i][i0]][j]/clustersizes.ptr.p_int[i]; - } - } - for(i1=0; i1<=clustersizes.ptr.p_int[npoints+mergeidx]-1; i1++) - { - for(j=0; j<=nf-1; j++) - { - x1.ptr.p_double[j] = x1.ptr.p_double[j]+xy->ptr.pp_double[cm.ptr.pp_int[npoints+mergeidx][i1]][j]/clustersizes.ptr.p_int[npoints+mergeidx]; - } - } - v = 0.0; - for(j=0; j<=nf-1; j++) - { - v = v+ae_sqr(x0.ptr.p_double[j]-x1.ptr.p_double[j], _state); - } - v = v*clustersizes.ptr.p_int[i]*clustersizes.ptr.p_int[npoints+mergeidx]/(clustersizes.ptr.p_int[i]+clustersizes.ptr.p_int[npoints+mergeidx]); - } - dm.ptr.pp_double[i][npoints+mergeidx] = v; - dm.ptr.pp_double[npoints+mergeidx][i] = v; - } - } - - /* - * Check that GetKClusters() correctly unpacks clusters for K=NPoints-(MergeIdx+1): - * * check lengths of arays - * * check consistency of CIdx/CZ parameters - * * scan clusters (CZ parameter), for each cluster scan CM matrix which stores - * cluster elements (according to our replay of merges), for each element of - * the current cluster check that CIdx array correctly reflects its status. - */ - k = npoints-(mergeidx+1); - clusterizergetkclusters(rep, k, &kidx, &kidxz, _state); - if( kidx.cnt!=npoints||kidxz.cnt!=k ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=k-2; i++) - { - if( (kidxz.ptr.p_int[i]<0||kidxz.ptr.p_int[i]>=kidxz.ptr.p_int[i+1])||kidxz.ptr.p_int[i+1]>2*npoints-2 ) - { - - /* - * CZ is inconsistent - */ - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - for(i=0; i<=npoints-1; i++) - { - if( kidx.ptr.p_int[i]<0||kidx.ptr.p_int[i]>=k ) - { - - /* - * CIdx is inconsistent - */ - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - for(i=0; i<=k-1; i++) - { - for(j=0; j<=clustersizes.ptr.p_int[kidxz.ptr.p_int[i]]-1; j++) - { - currentelement = cm.ptr.pp_int[kidxz.ptr.p_int[i]][j]; - if( kidx.ptr.p_int[currentelement]!=i ) - { - - /* - * We've found element which belongs to I-th cluster (according to CM - * matrix, which reflects current status of agglomerative clustering), - * but this element does not belongs to I-th cluster according to - * results of ClusterizerGetKClusters() - */ - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This procedure is a reference version of KMeansUpdateDistances(). - -INPUT PARAMETERS: - XY - dataset, array [0..NPoints-1,0..NVars-1]. - NPoints - dataset size, NPoints>=K - NVars - number of variables, NVars>=1 - CT - matrix of centers, centers are stored in rows - K - number of centers, K>=1 - XYC - preallocated output buffer - XYDist2 - preallocated output buffer - -OUTPUT PARAMETERS: - XYC - new assignment of points to centers - XYDist2 - squared distances - - -- ALGLIB -- - Copyright 21.01.2015 by Bochkanov Sergey -*************************************************************************/ -static void testclusteringunit_kmeansreferenceupdatedistances(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - /* Real */ ae_matrix* ct, - ae_int_t k, - /* Integer */ ae_vector* xyc, - /* Real */ ae_vector* xydist2, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t cclosest; - double dclosest; - double v; - ae_vector tmp; - - ae_frame_make(_state, &_frame_block); - memset(&tmp, 0, sizeof(tmp)); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&tmp, nvars, _state); - for(i=0; i<=npoints-1; i++) - { - cclosest = -1; - dclosest = ae_maxrealnumber; - for(j=0; j<=k-1; j++) - { - ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - ae_v_sub(&tmp.ptr.p_double[0], 1, &ct->ptr.pp_double[j][0], 1, ae_v_len(0,nvars-1)); - v = ae_v_dotproduct(&tmp.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,nvars-1)); - if( ae_fp_less(v,dclosest) ) - { - cclosest = j; - dclosest = v; - } - } - ae_assert(cclosest>=0, "KMeansUpdateDistances: internal error", _state); - xyc->ptr.p_int[i] = cclosest; - xydist2->ptr.p_double[i] = dclosest; - } - ae_frame_leave(_state); -} - - - -static ae_int_t testdforestunit_algomax = 0; -static ae_int_t testdforestunit_splitmax = 2; -static void testdforestunit_testprocessing(ae_bool* err, ae_state *_state); -static void testdforestunit_basictest1(ae_bool* err, ae_state *_state); -static void testdforestunit_basictest2(ae_bool* err, ae_state *_state); -static void testdforestunit_basictest3(ae_bool* err, ae_state *_state); -static void testdforestunit_basictest4(ae_bool* err, ae_state *_state); -static void testdforestunit_basictest5(ae_bool* err, ae_state *_state); -static void testdforestunit_basictestrandom(ae_bool* err, - ae_state *_state); -static void testdforestunit_basictestallsame(ae_bool* err, - ae_state *_state); -static void testdforestunit_testcompression(ae_bool* err, - ae_state *_state); -static void testdforestunit_testimportance(ae_bool* err, ae_state *_state); -static void testdforestunit_unsetdf(decisionforest* df, ae_state *_state); -static void testdforestunit_randomlyrearrange(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nvars, - hqrndstate* rs, - ae_state *_state); - - - - - -ae_bool testdforest(ae_bool silent, ae_state *_state) -{ - ae_bool waserrors; - ae_bool basicerrors; - ae_bool procerrors; - ae_bool compressionerrors; - ae_bool importanceerrors; - ae_bool result; - - - - /* - * Primary settings - */ - basicerrors = ae_false; - procerrors = ae_false; - compressionerrors = ae_false; - importanceerrors = ae_false; - waserrors = ae_false; - - /* - * Tests - */ - testdforestunit_testprocessing(&procerrors, _state); - testdforestunit_basictest1(&basicerrors, _state); - testdforestunit_basictest2(&basicerrors, _state); - testdforestunit_basictest3(&basicerrors, _state); - testdforestunit_basictest4(&basicerrors, _state); - testdforestunit_basictest5(&basicerrors, _state); - testdforestunit_basictestrandom(&basicerrors, _state); - testdforestunit_basictestallsame(&basicerrors, _state); - testdforestunit_testcompression(&compressionerrors, _state); - testdforestunit_testimportance(&importanceerrors, _state); - - /* - * Final report - */ - waserrors = ((basicerrors||procerrors)||compressionerrors)||importanceerrors; - if( !silent ) - { - printf("RANDOM FOREST TEST\n"); - printf("TOTAL RESULTS: "); - if( !waserrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* PROCESSING FUNCTIONS: "); - if( !procerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* BASIC TESTS: "); - if( !basicerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* COMPRESSION TESTS: "); - if( !compressionerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* VARIABLE IMPORTANCE TESTS: "); - if( !importanceerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST SUMMARY: FAILED\n"); - } - else - { - printf("TEST SUMMARY: PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - return result; -} - - -/************************************************************************* -Processing functions test -*************************************************************************/ -static void testdforestunit_testprocessing(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nvars; - ae_int_t nclasses; - ae_int_t ntrees; - ae_int_t foresttype; - decisionforest df1; - decisionforest df2; - decisionforestbuilder builder; - dfreport rep; - decisionforestbuffer buf; - ae_int_t npoints; - ae_matrix xy; - ae_int_t pass; - ae_int_t passcount; - ae_int_t i; - ae_int_t j; - ae_bool allsame; - ae_vector x1; - ae_vector x2; - ae_vector y1; - ae_vector y2; - double v; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&df1, 0, sizeof(df1)); - memset(&df2, 0, sizeof(df2)); - memset(&builder, 0, sizeof(builder)); - memset(&rep, 0, sizeof(rep)); - memset(&buf, 0, sizeof(buf)); - memset(&xy, 0, sizeof(xy)); - memset(&x1, 0, sizeof(x1)); - memset(&x2, 0, sizeof(x2)); - memset(&y1, 0, sizeof(y1)); - memset(&y2, 0, sizeof(y2)); - memset(&rs, 0, sizeof(rs)); - _decisionforest_init(&df1, _state, ae_true); - _decisionforest_init(&df2, _state, ae_true); - _decisionforestbuilder_init(&builder, _state, ae_true); - _dfreport_init(&rep, _state, ae_true); - _decisionforestbuffer_init(&buf, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y2, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - passcount = 100; - hqrndrandomize(&rs, _state); - - /* - * Main cycle - */ - for(pass=1; pass<=passcount; pass++) - { - - /* - * initialize parameters - */ - nvars = 1+hqrnduniformi(&rs, 5, _state); - nclasses = 1+hqrnduniformi(&rs, 3, _state); - ntrees = 1+hqrnduniformi(&rs, 4, _state); - foresttype = hqrnduniformi(&rs, 3, _state); - - /* - * Initialize arrays and data - */ - npoints = 10+ae_randominteger(50, _state); - ae_vector_set_length(&x1, nvars, _state); - ae_vector_set_length(&x2, nvars, _state); - ae_vector_set_length(&y1, nclasses, _state); - ae_vector_set_length(&y2, nclasses, _state); - ae_matrix_set_length(&xy, npoints, nvars+1, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - if( j%2==0 ) - { - xy.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - else - { - xy.ptr.pp_double[i][j] = (double)(ae_randominteger(2, _state)); - } - } - if( nclasses==1 ) - { - xy.ptr.pp_double[i][nvars] = 2*ae_randomreal(_state)-1; - } - else - { - xy.ptr.pp_double[i][nvars] = (double)(ae_randominteger(nclasses, _state)); - } - } - - /* - * create forest - */ - dfbuildercreate(&builder, _state); - dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state); - dfbuildersetrdfalgo(&builder, ae_randominteger(testdforestunit_algomax+1, _state), _state); - dfbuildersetrdfsplitstrength(&builder, ae_randominteger(testdforestunit_splitmax+1, _state), _state); - if( foresttype==0 ) - { - - /* - * Build uncompressed random forest - */ - dfbuilderbuildrandomforest(&builder, ntrees, &df1, &rep, _state); - } - if( foresttype==1 ) - { - - /* - * Build uncompressed random forest, then perform 16-bit compression - */ - dfbuilderbuildrandomforest(&builder, ntrees, &df1, &rep, _state); - dfbinarycompression(&df1, _state); - } - if( foresttype==2 ) - { - - /* - * Build uncompressed random forest, then perform 8-bit compression - */ - dfbuilderbuildrandomforest(&builder, ntrees, &df1, &rep, _state); - dfbinarycompression8(&df1, _state); - } - dfcreatebuffer(&df1, &buf, _state); - - /* - * Same inputs leads to same outputs - */ - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - for(i=0; i<=nclasses-1; i++) - { - y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - dfprocess(&df1, &x1, &y1, _state); - dfprocess(&df1, &x2, &y2, _state); - allsame = ae_true; - for(i=0; i<=nclasses-1; i++) - { - allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]); - } - *err = *err||!allsame; - - /* - * DFProcess0 works as expected - */ - ae_vector_set_length(&x1, nvars, _state); - ae_vector_set_length(&x2, nvars, _state); - ae_vector_set_length(&y1, nclasses, _state); - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = hqrndnormal(&rs, _state); - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - for(i=0; i<=nclasses-1; i++) - { - y1.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - dfprocess(&df1, &x1, &y1, _state); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y1.ptr.p_double[0]-dfprocess0(&df1, &x2, _state), _state),100*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:225"); - - /* - * DFClassify works as expected - */ - ae_vector_set_length(&x1, nvars, _state); - ae_vector_set_length(&x2, nvars, _state); - ae_vector_set_length(&y1, nclasses, _state); - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = hqrndnormal(&rs, _state); - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - if( nclasses>1 ) - { - for(i=0; i<=nclasses-1; i++) - { - y1.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - dfprocess(&df1, &x1, &y1, _state); - j = dfclassify(&df1, &x2, _state); - for(i=0; i<=nclasses-1; i++) - { - ae_set_error_flag(err, ae_fp_greater(y1.ptr.p_double[i],y1.ptr.p_double[j]), __FILE__, __LINE__, "testdforestunit.ap:248"); - } - } - else - { - ae_set_error_flag(err, dfclassify(&df1, &x2, _state)!=-1, __FILE__, __LINE__, "testdforestunit.ap:251"); - } - - /* - * DFTsProcess() works as expected - */ - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - for(i=0; i<=nclasses-1; i++) - { - y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - dfprocess(&df1, &x1, &y1, _state); - dftsprocess(&df1, &buf, &x2, &y2, _state); - allsame = ae_true; - for(i=0; i<=nclasses-1; i++) - { - allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]); - } - ae_set_error_flag(err, !allsame, __FILE__, __LINE__, "testdforestunit.ap:272"); - - /* - * Same inputs on original forest leads to same outputs - * on copy created using DFCopy - */ - testdforestunit_unsetdf(&df2, _state); - dfcopy(&df1, &df2, _state); - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - for(i=0; i<=nclasses-1; i++) - { - y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - dfprocess(&df1, &x1, &y1, _state); - dfprocess(&df2, &x2, &y2, _state); - allsame = ae_true; - for(i=0; i<=nclasses-1; i++) - { - allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]); - } - *err = *err||!allsame; - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(dfprocess0(&df1, &x1, _state)-dfprocess0(&df2, &x2, _state), _state),100*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:303"); - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - ae_set_error_flag(err, dfclassify(&df1, &x1, _state)!=dfclassify(&df2, &x2, _state), __FILE__, __LINE__, "testdforestunit.ap:309"); - - /* - * Same inputs on original forest leads to same outputs - * on copy created using DFSerialize - */ - testdforestunit_unsetdf(&df2, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - dfalloc(&_local_serializer, &df1, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - dfserialize(&_local_serializer, &df1, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - dfunserialize(&_local_serializer, &df2, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - for(i=0; i<=nclasses-1; i++) - { - y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - dfprocess(&df1, &x1, &y1, _state); - dfprocess(&df2, &x2, &y2, _state); - allsame = ae_true; - for(i=0; i<=nclasses-1; i++) - { - allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]); - } - *err = *err||!allsame; - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(dfprocess0(&df1, &x1, _state)-dfprocess0(&df2, &x2, _state), _state),100*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:339"); - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - ae_set_error_flag(err, dfclassify(&df1, &x1, _state)!=dfclassify(&df2, &x2, _state), __FILE__, __LINE__, "testdforestunit.ap:345"); - - /* - * Normalization properties - */ - if( nclasses>1 ) - { - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - dfprocess(&df1, &x1, &y1, _state); - v = (double)(0); - for(i=0; i<=nclasses-1; i++) - { - v = v+y1.ptr.p_double[i]; - *err = *err||ae_fp_less(y1.ptr.p_double[i],(double)(0)); - } - *err = *err||ae_fp_greater(ae_fabs(v-1, _state),1000*ae_machineepsilon); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Basic test: one-tree uncompressed forest built using full sample must -remember all training cases. - -Special relaxed testing is performed for compressed forests. -*************************************************************************/ -static void testdforestunit_basictest1(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t pass; - ae_matrix xy; - ae_int_t npoints; - ae_int_t ntrees; - ae_int_t i; - ae_int_t j; - double s; - ae_int_t info; - decisionforestbuilder builder; - decisionforest df; - decisionforest df1; - ae_vector x; - ae_vector y; - dfreport rep; - ae_int_t nvars; - ae_int_t nclasses; - ae_int_t passcount; - hqrndstate rs; - double tol16; - double tol8; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&builder, 0, sizeof(builder)); - memset(&df, 0, sizeof(df)); - memset(&df1, 0, sizeof(df1)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&rep, 0, sizeof(rep)); - memset(&rs, 0, sizeof(rs)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _decisionforestbuilder_init(&builder, _state, ae_true); - _decisionforest_init(&df, _state, ae_true); - _decisionforest_init(&df1, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - _dfreport_init(&rep, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - tol16 = 0.0001; - tol8 = 0.01; - - /* - * Test uncompressed forest - */ - passcount = 10; - for(nvars=1; nvars<=4; nvars++) - { - for(nclasses=1; nclasses<=3; nclasses++) - { - for(pass=0; pass<=passcount-1; pass++) - { - - /* - * select number of points - */ - if( pass<3&&passcount>3 ) - { - npoints = 1+pass; - } - else - { - npoints = 100+hqrnduniformi(&rs, 100, _state); - } - - /* - * Prepare task - */ - ae_matrix_set_length(&xy, npoints, nvars+1, _state); - ae_vector_set_length(&x, nvars, _state); - ae_vector_set_length(&y, nclasses, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = (double)(i); - for(j=1; j<=nvars-1; j++) - { - xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - if( nclasses>1 ) - { - xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nclasses, _state)); - } - else - { - xy.ptr.pp_double[i][nvars] = hqrndnormal(&rs, _state); - } - } - - /* - * Train - * - * NOTE: we also test obsolete forest construction functions - */ - ae_assert(passcount>=2, "RDF: test integrity failed", _state); - ntrees = 1; - if( pass>0 ) - { - - /* - * Test new interface - */ - dfbuildercreate(&builder, _state); - dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state); - dfbuildersetsubsampleratio(&builder, 1.0, _state); - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - dfbuildersetrndvars(&builder, nvars, _state); - } - else - { - dfbuildersetrndvarsratio(&builder, 1.0, _state); - } - dfbuildersetrdfalgo(&builder, ae_randominteger(testdforestunit_algomax+1, _state), _state); - dfbuildersetrdfsplitstrength(&builder, ae_randominteger(testdforestunit_splitmax+1, _state), _state); - dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state); - } - else - { - - /* - * Test old interface - */ - if( hqrnduniformi(&rs, 2, _state)==0 ) - { - dfbuildrandomdecisionforest(&xy, npoints, nvars, nclasses, ntrees, 1.0, &info, &df, &rep, _state); - } - else - { - dfbuildrandomdecisionforestx1(&xy, npoints, nvars, nclasses, ntrees, 1, 1.0, &info, &df, &rep, _state); - } - if( info<=0 ) - { - ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testdforestunit.ap:467"); - ae_frame_leave(_state); - return; - } - } - - /* - * Test - */ - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.rmserror, _state),1.0E-9), __FILE__, __LINE__, "testdforestunit.ap:475"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgerror, _state),1.0E-9), __FILE__, __LINE__, "testdforestunit.ap:476"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgrelerror, _state),1.0E-9), __FILE__, __LINE__, "testdforestunit.ap:477"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.relclserror, _state),(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:478"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgce, _state),(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:479"); - for(i=0; i<=npoints-1; i++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xy.ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - dfprocess(&df, &x, &y, _state); - if( nclasses>1 ) - { - - /* - * Checks for classification tasks - */ - s = (double)(0); - for(j=0; j<=nclasses-1; j++) - { - ae_set_error_flag(err, ae_fp_less(y.ptr.p_double[j],(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:492"); - s = s+y.ptr.p_double[j]; - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(s-1, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:495"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[ae_round(xy.ptr.pp_double[i][nvars], _state)]-1, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:496"); - } - else - { - - /* - * Regression problem - */ - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[0]-xy.ptr.pp_double[i][nvars], _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:503"); - } - } - } - } - } - - /* - * Test compressed forest - */ - nvars = 1; - npoints = 100; - for(nclasses=1; nclasses<=3; nclasses++) - { - for(pass=0; pass<=passcount-1; pass++) - { - - /* - * Dataset - */ - ae_matrix_set_length(&xy, npoints, nvars+1, _state); - ae_vector_set_length(&x, nvars, _state); - ae_vector_set_length(&y, nclasses, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = (double)(i); - if( nclasses>1 ) - { - xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nclasses, _state)); - } - else - { - xy.ptr.pp_double[i][nvars] = hqrnduniformr(&rs, _state)-0.5; - } - } - - /* - * Train - */ - ntrees = 1; - dfbuildercreate(&builder, _state); - dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state); - dfbuildersetsubsampleratio(&builder, 1.0, _state); - dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.rmserror, _state),1.0E-9), __FILE__, __LINE__, "testdforestunit.ap:541"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgerror, _state),1.0E-9), __FILE__, __LINE__, "testdforestunit.ap:542"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgrelerror, _state),1.0E-9), __FILE__, __LINE__, "testdforestunit.ap:543"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.relclserror, _state),(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:544"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgce, _state),(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:545"); - - /* - * Test 16-bit compression - */ - dfcopy(&df, &df1, _state); - dfbinarycompression(&df1, _state); - for(i=0; i<=npoints-1; i++) - { - x.ptr.p_double[0] = xy.ptr.pp_double[i][0]; - dfprocess(&df1, &x, &y, _state); - if( nclasses>1 ) - { - - /* - * Checks for classification tasks - */ - s = (double)(0); - for(j=0; j<=nclasses-1; j++) - { - ae_set_error_flag(err, ae_fp_less(y.ptr.p_double[j],(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:564"); - s = s+y.ptr.p_double[j]; - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(s-1, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:567"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[ae_round(xy.ptr.pp_double[i][nvars], _state)]-1, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:568"); - } - else - { - - /* - * Regression problem - */ - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[0]-xy.ptr.pp_double[i][nvars], _state),tol16), __FILE__, __LINE__, "testdforestunit.ap:575"); - } - } - - /* - * Test 8-bit compression - */ - dfcopy(&df, &df1, _state); - dfbinarycompression8(&df1, _state); - for(i=0; i<=npoints-1; i++) - { - x.ptr.p_double[0] = xy.ptr.pp_double[i][0]; - dfprocess(&df1, &x, &y, _state); - if( nclasses>1 ) - { - - /* - * Checks for classification tasks - */ - s = (double)(0); - for(j=0; j<=nclasses-1; j++) - { - ae_set_error_flag(err, ae_fp_less(y.ptr.p_double[j],(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:596"); - s = s+y.ptr.p_double[j]; - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(s-1, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:599"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[ae_round(xy.ptr.pp_double[i][nvars], _state)]-1, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:600"); - } - else - { - - /* - * Regression problem - */ - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[0]-xy.ptr.pp_double[i][nvars], _state),tol8), __FILE__, __LINE__, "testdforestunit.ap:607"); - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Basic test: tests generalization ability on a simple noisy classification -task: -* 00.25 - P(class=0)=0 -*************************************************************************/ -static void testdforestunit_basictest3(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t pass; - ae_int_t passcount; - ae_matrix xy; - ae_int_t npoints; - ae_int_t ntrees; - ae_int_t i; - ae_int_t j; - ae_int_t info; - decisionforestbuilder builder; - decisionforest df; - ae_vector x; - ae_vector y; - dfreport rep; - ae_int_t testgridsize; - double r; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&builder, 0, sizeof(builder)); - memset(&df, 0, sizeof(df)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&rep, 0, sizeof(rep)); - memset(&rs, 0, sizeof(rs)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _decisionforestbuilder_init(&builder, _state, ae_true); - _decisionforest_init(&df, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - _dfreport_init(&rep, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - passcount = 2; - testgridsize = 50; - for(pass=0; pass<=passcount-1; pass++) - { - - /* - * select npoints and ntrees - */ - npoints = 2000; - ntrees = 100; - - /* - * Prepare task - */ - ae_matrix_set_length(&xy, npoints, 3, _state); - ae_vector_set_length(&x, 2, _state); - ae_vector_set_length(&y, 2, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = 2*hqrnduniformr(&rs, _state)-1; - xy.ptr.pp_double[i][1] = 2*hqrnduniformr(&rs, _state)-1; - if( ae_fp_less_eq(ae_sqr(xy.ptr.pp_double[i][0], _state)+ae_sqr(xy.ptr.pp_double[i][1], _state),0.25) ) - { - xy.ptr.pp_double[i][2] = (double)(0); - } - else - { - xy.ptr.pp_double[i][2] = (double)(1); - } - } - - /* - * Build forest - * - * NOTE: we also test obsolete forest construction functions - */ - ae_assert(passcount>=2, "RDF: test integrity failed", _state); - if( pass>0 ) - { - - /* - * Test new interface - */ - dfbuildercreate(&builder, _state); - dfbuildersetdataset(&builder, &xy, npoints, 2, 2, _state); - dfbuildersetsubsampleratio(&builder, 0.10, _state); - dfbuildersetrdfalgo(&builder, ae_randominteger(testdforestunit_algomax+1, _state), _state); - dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state); - } - else - { - - /* - * Test old interface - */ - if( hqrnduniformi(&rs, 2, _state)==0 ) - { - dfbuildrandomdecisionforest(&xy, npoints, 2, 2, ntrees, 0.10, &info, &df, &rep, _state); - } - else - { - dfbuildrandomdecisionforestx1(&xy, npoints, 2, 2, ntrees, 1, 0.10, &info, &df, &rep, _state); - } - if( info<=0 ) - { - ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testdforestunit.ap:806"); - ae_frame_leave(_state); - return; - } - } - - /* - * Test - */ - for(i=-testgridsize/2; i<=testgridsize/2; i++) - { - for(j=-testgridsize/2; j<=testgridsize/2; j++) - { - x.ptr.p_double[0] = (double)i/(double)(testgridsize/2); - x.ptr.p_double[1] = (double)j/(double)(testgridsize/2); - dfprocess(&df, &x, &y, _state); - - /* - * Test for basic properties - */ - ae_set_error_flag(err, ae_fp_less(y.ptr.p_double[0],(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:824"); - ae_set_error_flag(err, ae_fp_less(y.ptr.p_double[1],(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:825"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[0]+y.ptr.p_double[1]-1, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:826"); - - /* - * test for good correlation with results - */ - r = ae_sqrt(ae_sqr(x.ptr.p_double[0], _state)+ae_sqr(x.ptr.p_double[1], _state), _state); - if( ae_fp_less(r,0.66*0.5) ) - { - ae_set_error_flag(err, ae_fp_less(y.ptr.p_double[0],0.66), __FILE__, __LINE__, "testdforestunit.ap:833"); - } - if( ae_fp_greater(r,1.33*0.5) ) - { - ae_set_error_flag(err, ae_fp_less(y.ptr.p_double[1],0.66), __FILE__, __LINE__, "testdforestunit.ap:835"); - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Basic test: simple regression task without noise: -* |x|<1, |y|<1 -* F(x,y) = x^2+y -*************************************************************************/ -static void testdforestunit_basictest4(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t pass; - ae_int_t passcount; - ae_matrix xy; - ae_int_t npoints; - ae_int_t ntrees; - ae_int_t i; - ae_int_t j; - ae_int_t info; - decisionforest df; - ae_vector x; - ae_vector y; - dfreport rep; - ae_int_t testgridsize; - decisionforestbuilder builder; - double maxerr; - double avgerr; - ae_int_t cnt; - double ey; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&df, 0, sizeof(df)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&rep, 0, sizeof(rep)); - memset(&builder, 0, sizeof(builder)); - memset(&rs, 0, sizeof(rs)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _decisionforest_init(&df, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - _dfreport_init(&rep, _state, ae_true); - _decisionforestbuilder_init(&builder, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - passcount = 2; - testgridsize = 50; - for(pass=0; pass<=passcount-1; pass++) - { - - /* - * select npoints and ntrees - */ - npoints = 5000; - ntrees = 100; - - /* - * Prepare task - */ - ae_matrix_set_length(&xy, npoints, 3, _state); - ae_vector_set_length(&x, 2, _state); - ae_vector_set_length(&y, 1, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = 2*hqrnduniformr(&rs, _state)-1; - xy.ptr.pp_double[i][1] = 2*hqrnduniformr(&rs, _state)-1; - xy.ptr.pp_double[i][2] = ae_sqr(xy.ptr.pp_double[i][0], _state)+xy.ptr.pp_double[i][1]; - } - - /* - * Build forest - * - * NOTE: we also test obsolete forest construction functions - */ - ae_assert(passcount>=2, "RDF: test integrity failed", _state); - if( pass>0 ) - { - - /* - * Test new interface - */ - dfbuildercreate(&builder, _state); - dfbuildersetdataset(&builder, &xy, npoints, 2, 1, _state); - dfbuildersetsubsampleratio(&builder, 0.10, _state); - dfbuildersetrdfalgo(&builder, ae_randominteger(testdforestunit_algomax+1, _state), _state); - dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state); - } - else - { - - /* - * Test old interface - */ - if( hqrnduniformi(&rs, 2, _state)==0 ) - { - dfbuildrandomdecisionforest(&xy, npoints, 2, 1, ntrees, 0.10, &info, &df, &rep, _state); - } - else - { - dfbuildrandomdecisionforestx1(&xy, npoints, 2, 1, ntrees, 1, 0.10, &info, &df, &rep, _state); - } - if( info<=0 ) - { - ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testdforestunit.ap:924"); - ae_frame_leave(_state); - return; - } - } - - /* - * Check report fields - */ - ae_set_error_flag(err, ae_fp_neq(rep.relclserror,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:932"); - ae_set_error_flag(err, ae_fp_neq(rep.avgce,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:933"); - ae_set_error_flag(err, ae_fp_neq(rep.oobrelclserror,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:934"); - ae_set_error_flag(err, ae_fp_neq(rep.oobavgce,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:935"); - ae_set_error_flag(err, ae_fp_greater_eq(rep.rmserror,rep.oobrmserror), __FILE__, __LINE__, "testdforestunit.ap:936"); - ae_set_error_flag(err, ae_fp_greater_eq(rep.avgerror,rep.oobavgerror), __FILE__, __LINE__, "testdforestunit.ap:937"); - ae_set_error_flag(err, ae_fp_greater_eq(rep.avgrelerror,rep.oobavgrelerror), __FILE__, __LINE__, "testdforestunit.ap:938"); - ae_set_error_flag(err, ae_fp_greater(rep.oobrmserror,0.05), __FILE__, __LINE__, "testdforestunit.ap:939"); - ae_set_error_flag(err, ae_fp_greater(rep.oobavgerror,0.05), __FILE__, __LINE__, "testdforestunit.ap:940"); - ae_set_error_flag(err, ae_fp_less(rep.oobrmserror,0.001), __FILE__, __LINE__, "testdforestunit.ap:941"); - ae_set_error_flag(err, ae_fp_less(rep.oobavgerror,0.001), __FILE__, __LINE__, "testdforestunit.ap:942"); - - /* - * Test - */ - maxerr = (double)(0); - avgerr = (double)(0); - cnt = 0; - for(i=ae_round(-0.7*testgridsize/2, _state); i<=ae_round(0.7*testgridsize/2, _state); i++) - { - for(j=ae_round(-0.7*testgridsize/2, _state); j<=ae_round(0.7*testgridsize/2, _state); j++) - { - x.ptr.p_double[0] = (double)i/(double)(testgridsize/2); - x.ptr.p_double[1] = (double)j/(double)(testgridsize/2); - ey = ae_sqr(x.ptr.p_double[0], _state)+x.ptr.p_double[1]; - dfprocess(&df, &x, &y, _state); - maxerr = ae_maxreal(maxerr, ae_fabs(y.ptr.p_double[0]-ey, _state), _state); - avgerr = avgerr+ae_fabs(y.ptr.p_double[0]-ey, _state); - cnt = cnt+1; - } - } - avgerr = avgerr/cnt; - ae_set_error_flag(err, ae_fp_greater(maxerr,0.15), __FILE__, __LINE__, "testdforestunit.ap:962"); - ae_set_error_flag(err, ae_fp_greater(avgerr,0.05), __FILE__, __LINE__, "testdforestunit.ap:963"); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Basic test: extended variable selection leads to better results. - -Next task CAN be solved without EVS but it is very unlikely. With EVS -it can be easily and exactly solved. - -Task matrix: - 1 0 0 0 ... 0 0 - 0 1 0 0 ... 0 1 - 0 0 1 0 ... 0 2 - 0 0 0 1 ... 0 3 - 0 0 0 0 ... 1 N-1 -*************************************************************************/ -static void testdforestunit_basictest5(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix xy; - ae_int_t nvars; - ae_int_t npoints; - ae_int_t ntrees; - ae_int_t i; - ae_int_t j; - decisionforestbuilder builder; - decisionforest df; - ae_vector x; - ae_vector y; - dfreport rep; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&builder, 0, sizeof(builder)); - memset(&df, 0, sizeof(df)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _decisionforestbuilder_init(&builder, _state, ae_true); - _decisionforest_init(&df, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - _dfreport_init(&rep, _state, ae_true); - - - /* - * select npoints and ntrees - */ - npoints = 50; - nvars = npoints; - ntrees = 1; - - /* - * Prepare task - */ - ae_matrix_set_length(&xy, npoints, nvars+1, _state); - ae_vector_set_length(&x, nvars, _state); - ae_vector_set_length(&y, 1, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - xy.ptr.pp_double[i][j] = (double)(0); - } - xy.ptr.pp_double[i][i] = (double)(1); - xy.ptr.pp_double[i][nvars] = (double)(i); - } - - /* - * Build forest - */ - dfbuildercreate(&builder, _state); - dfbuildersetdataset(&builder, &xy, npoints, nvars, 1, _state); - dfbuildersetsubsampleratio(&builder, 1.00, _state); - dfbuildersetrdfalgo(&builder, ae_randominteger(testdforestunit_algomax+1, _state), _state); - dfbuildersetrdfsplitstrength(&builder, ae_randominteger(testdforestunit_splitmax+1, _state), _state); - dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state); - - /* - * Test - */ - ae_set_error_flag(err, ae_fp_greater_eq(rep.rmserror,rep.oobrmserror), __FILE__, __LINE__, "testdforestunit.ap:1032"); - ae_set_error_flag(err, ae_fp_greater_eq(rep.avgerror,rep.oobavgerror), __FILE__, __LINE__, "testdforestunit.ap:1033"); - ae_set_error_flag(err, ae_fp_greater_eq(rep.avgrelerror,rep.oobavgrelerror), __FILE__, __LINE__, "testdforestunit.ap:1034"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.rmserror, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:1035"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgerror, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:1036"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgrelerror, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:1037"); - for(i=0; i<=npoints-1; i++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xy.ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1)); - dfprocess(&df, &x, &y, _state); - if( ae_fp_greater(ae_fabs(y.ptr.p_double[0]-xy.ptr.pp_double[i][nvars], _state),1000*ae_machineepsilon) ) - { - ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testdforestunit.ap:1043"); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Basic test: test correctness of error reports on completely random problem; -test that OOB errors are roughly unbiased. -*************************************************************************/ -static void testdforestunit_basictestrandom(ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix xy; - ae_int_t nvars; - ae_int_t npoints; - ae_int_t ntrees; - ae_int_t nclasses; - ae_int_t i; - ae_int_t j; - ae_int_t factor; - decisionforestbuilder builder; - decisionforest df; - ae_vector x; - ae_vector y; - dfreport rep; - hqrndstate rs; - double meanlevel; - double sigma; - double v; - double refavgce; - double refrms; - double refavg; - double refavgrel; - ae_int_t relcnt; - double oobtol; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&builder, 0, sizeof(builder)); - memset(&df, 0, sizeof(df)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&rep, 0, sizeof(rep)); - memset(&rs, 0, sizeof(rs)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _decisionforestbuilder_init(&builder, _state, ae_true); - _decisionforest_init(&df, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - _dfreport_init(&rep, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - npoints = 200; - nvars = 10; - ntrees = 1000; - oobtol = 0.20; - for(nclasses=1; nclasses<=3; nclasses++) - { - - /* - * Prepare task - */ - ae_matrix_set_length(&xy, npoints, nvars+1, _state); - meanlevel = 10*hqrndnormal(&rs, _state); - sigma = ae_pow((double)(10), hqrndnormal(&rs, _state), _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - xy.ptr.pp_double[i][j] = (double)(0); - if( j%3==0 ) - { - xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - if( j%3==1&&ae_fp_less(hqrnduniformr(&rs, _state),0.05) ) - { - xy.ptr.pp_double[i][j] = (double)(1); - } - if( j%3==2&&ae_fp_less(hqrnduniformr(&rs, _state),0.05) ) - { - xy.ptr.pp_double[i][j] = (double)(1+hqrnduniformi(&rs, 3, _state)); - } - } - if( nclasses==1 ) - { - xy.ptr.pp_double[i][nvars] = meanlevel+sigma*hqrndnormal(&rs, _state); - if( ae_fp_less(hqrnduniformr(&rs, _state),0.05) ) - { - xy.ptr.pp_double[i][nvars] = (double)(0); - } - } - else - { - xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nclasses, _state)); - } - } - ae_vector_set_length(&x, nvars, _state); - ae_vector_set_length(&y, nclasses, _state); - - /* - * Build forest using 50% and 66% of the samples. - * Check TRN and OOB errors (OOB should be 2x and 3x larger in these cases) - */ - for(factor=2; factor<=3; factor++) - { - j = hqrnduniformi(&rs, 3, _state); - dfbuildercreate(&builder, _state); - dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state); - dfbuildersetsubsampleratio(&builder, 1-(double)1/(double)factor, _state); - if( j>0 ) - { - dfbuildersetrndvars(&builder, 1+hqrnduniformi(&rs, 5, _state), _state); - } - if( j==0 ) - { - dfbuildersetrndvarsauto(&builder, _state); - } - if( j<0 ) - { - dfbuildersetrndvarsratio(&builder, hqrnduniformr(&rs, _state), _state); - } - dfbuildersetrdfalgo(&builder, ae_randominteger(testdforestunit_algomax+1, _state), _state); - dfbuildersetrdfsplitstrength(&builder, ae_randominteger(testdforestunit_splitmax+1, _state), _state); - ae_set_error_flag(err, ae_fp_neq(dfbuildergetprogress(&builder, _state),0.0), __FILE__, __LINE__, "testdforestunit.ap:1132"); - ae_set_error_flag(err, ae_fp_neq(dfbuilderpeekprogress(&builder, _state),0.0), __FILE__, __LINE__, "testdforestunit.ap:1133"); - dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state); - ae_set_error_flag(err, ae_fp_neq(dfbuildergetprogress(&builder, _state),1.0), __FILE__, __LINE__, "testdforestunit.ap:1135"); - ae_set_error_flag(err, ae_fp_neq(dfbuilderpeekprogress(&builder, _state),1.0), __FILE__, __LINE__, "testdforestunit.ap:1136"); - refavgce = (double)(0); - refrms = (double)(0); - refavg = (double)(0); - refavgrel = (double)(0); - relcnt = 0; - if( nclasses==1 ) - { - - /* - * Check training set errors - */ - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - x.ptr.p_double[j] = xy.ptr.pp_double[i][j]; - } - dfprocess(&df, &x, &y, _state); - v = y.ptr.p_double[0]-xy.ptr.pp_double[i][nvars]; - refrms = refrms+ae_sqr(v, _state); - refavg = refavg+ae_fabs(v, _state); - if( ae_fp_neq(xy.ptr.pp_double[i][nvars],(double)(0)) ) - { - refavgrel = refavgrel+ae_fabs(v/xy.ptr.pp_double[i][nvars], _state); - relcnt = relcnt+1; - } - } - refrms = ae_sqrt(refrms/npoints, _state); - refavg = refavg/npoints; - refavgrel = refavgrel/coalesce((double)(relcnt), (double)(1), _state); - ae_set_error_flag(err, ae_fp_neq(rep.relclserror,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1164"); - ae_set_error_flag(err, ae_fp_neq(rep.avgce,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1165"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state)/refrms,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1166"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state)/refavg,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1167"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state)/refavgrel,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1168"); - ae_set_error_flag(err, ae_fp_neq(dfrelclserror(&df, &xy, npoints, _state),(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1169"); - ae_set_error_flag(err, ae_fp_neq(dfavgce(&df, &xy, npoints, _state),(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1170"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(dfrmserror(&df, &xy, npoints, _state)-refrms, _state)/refrms,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1171"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(dfavgerror(&df, &xy, npoints, _state)-refavg, _state)/refavg,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1172"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(dfavgrelerror(&df, &xy, npoints, _state)-refavgrel, _state)/refavgrel,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1173"); - - /* - * Check OOB errors against training set errors: - * * RelCLS and AvgCE are not calculated for regression problems - * * RMS and AVG should be roughly FACTOR times larger - * * AVG-REL should be just larger (it is more prone to sampling noise than previous two) - */ - ae_set_error_flag(err, ae_fp_neq(rep.oobrelclserror,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1181"); - ae_set_error_flag(err, ae_fp_neq(rep.oobavgce,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1182"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.oobrmserror/rep.rmserror-factor, _state),oobtol), __FILE__, __LINE__, "testdforestunit.ap:1183"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.oobavgerror/rep.avgerror-factor, _state),oobtol), __FILE__, __LINE__, "testdforestunit.ap:1184"); - ae_set_error_flag(err, ae_fp_less(rep.oobavgrelerror,rep.avgrelerror), __FILE__, __LINE__, "testdforestunit.ap:1185"); - } - else - { - - /* - * Check training set errors - */ - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - x.ptr.p_double[j] = xy.ptr.pp_double[i][j]; - } - dfprocess(&df, &x, &y, _state); - for(j=0; j<=nclasses-1; j++) - { - v = y.ptr.p_double[j]; - if( ae_fp_eq((double)(j),xy.ptr.pp_double[i][nvars]) ) - { - v = v-1; - } - refrms = refrms+ae_sqr(v, _state); - refavg = refavg+ae_fabs(v, _state); - if( ae_fp_eq((double)(j),xy.ptr.pp_double[i][nvars]) ) - { - refavgrel = refavgrel+ae_fabs(v, _state); - refavgce = refavgce-ae_log(v, _state); - } - } - } - refrms = ae_sqrt(refrms/(npoints*nclasses), _state); - refavg = refavg/(npoints*nclasses); - refavgrel = refavgrel/npoints; - refavgce = refavgce/npoints; - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgce-refavgce, _state)/refavgce,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1215"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state)/refrms,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1216"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state)/refavg,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1217"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state)/refavgrel,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1218"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(dfrelclserror(&df, &xy, npoints, _state)-rep.relclserror, _state)*npoints,(double)(5)), __FILE__, __LINE__, "testdforestunit.ap:1220"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(dfavgce(&df, &xy, npoints, _state)-refavgce, _state)/refavgce,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1221"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(dfrmserror(&df, &xy, npoints, _state)-refrms, _state)/refrms,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1222"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(dfavgerror(&df, &xy, npoints, _state)-refavg, _state)/refavg,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1223"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(dfavgrelerror(&df, &xy, npoints, _state)-refavgrel, _state)/refavgrel,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1224"); - - /* - * Check OOB errors against training set errors - * * RelCLS, AvgCE and AvgRel should be just larger (too prone to sampling noise to perform more sensitive tests) - * * RMS and AVG should be roughly FACTOR times larger - * - */ - ae_set_error_flag(err, ae_fp_less(rep.oobrelclserror,rep.relclserror), __FILE__, __LINE__, "testdforestunit.ap:1232"); - ae_set_error_flag(err, ae_fp_less(rep.oobavgce,rep.avgce), __FILE__, __LINE__, "testdforestunit.ap:1233"); - ae_set_error_flag(err, ae_fp_less(rep.oobavgrelerror,rep.avgrelerror), __FILE__, __LINE__, "testdforestunit.ap:1234"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.oobrmserror/rep.rmserror-factor, _state),oobtol), __FILE__, __LINE__, "testdforestunit.ap:1235"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.oobavgerror/rep.avgerror-factor, _state),oobtol), __FILE__, __LINE__, "testdforestunit.ap:1236"); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Test behavior of the RDF algorithm on problem where all values of variables -are same -*************************************************************************/ -static void testdforestunit_basictestallsame(ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix xy; - ae_int_t nvars; - ae_int_t npoints; - ae_int_t ntrees; - ae_int_t nclasses; - ae_int_t i; - ae_int_t j; - ae_int_t k; - decisionforestbuilder builder; - decisionforest df; - ae_vector x; - ae_vector y; - dfreport rep; - hqrndstate rs; - double v; - double refavgce; - double refrms; - double refavg; - double refavgrel; - ae_int_t relcnt; - double oobtol; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&builder, 0, sizeof(builder)); - memset(&df, 0, sizeof(df)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&rep, 0, sizeof(rep)); - memset(&rs, 0, sizeof(rs)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _decisionforestbuilder_init(&builder, _state, ae_true); - _decisionforest_init(&df, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - _dfreport_init(&rep, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - npoints = 100; - nvars = 10; - ntrees = 100; - oobtol = 0.25; - for(nclasses=1; nclasses<=3; nclasses++) - { - - /* - * Prepare task - */ - ae_matrix_set_length(&xy, npoints, nvars+1, _state); - k = hqrnduniformi(&rs, 11, _state)-5; - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - xy.ptr.pp_double[i][j] = (double)(k); - } - if( nclasses==1 ) - { - xy.ptr.pp_double[i][nvars] = hqrndnormal(&rs, _state); - } - else - { - xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nclasses, _state)); - } - } - ae_vector_set_length(&x, nvars, _state); - ae_vector_set_length(&y, nclasses, _state); - - /* - * Build forest. - * Check TRN and OOB errors. - */ - j = hqrnduniformi(&rs, 3, _state); - dfbuildercreate(&builder, _state); - dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state); - dfbuildersetsubsampleratio(&builder, 0.5, _state); - if( j>0 ) - { - dfbuildersetrndvars(&builder, 1+hqrnduniformi(&rs, 5, _state), _state); - } - if( j==0 ) - { - dfbuildersetrndvarsauto(&builder, _state); - } - if( j<0 ) - { - dfbuildersetrndvarsratio(&builder, hqrnduniformr(&rs, _state), _state); - } - dfbuildersetrdfalgo(&builder, ae_randominteger(testdforestunit_algomax+1, _state), _state); - dfbuildersetrdfsplitstrength(&builder, ae_randominteger(testdforestunit_splitmax+1, _state), _state); - dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state); - refavgce = (double)(0); - refrms = (double)(0); - refavg = (double)(0); - refavgrel = (double)(0); - relcnt = 0; - if( nclasses==1 ) - { - - /* - * Check training set errors - */ - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - x.ptr.p_double[j] = xy.ptr.pp_double[i][j]; - } - dfprocess(&df, &x, &y, _state); - v = y.ptr.p_double[0]-xy.ptr.pp_double[i][nvars]; - refrms = refrms+ae_sqr(v, _state); - refavg = refavg+ae_fabs(v, _state); - if( ae_fp_neq(xy.ptr.pp_double[i][nvars],(double)(0)) ) - { - refavgrel = refavgrel+ae_fabs(v/xy.ptr.pp_double[i][nvars], _state); - relcnt = relcnt+1; - } - } - refrms = ae_sqrt(refrms/npoints, _state); - refavg = refavg/npoints; - refavgrel = refavgrel/coalesce((double)(relcnt), (double)(1), _state); - ae_set_error_flag(err, ae_fp_neq(rep.relclserror,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1339"); - ae_set_error_flag(err, ae_fp_neq(rep.avgce,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1340"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state)/refrms,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1341"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state)/refavg,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1342"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state)/refavgrel,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1343"); - - /* - * Check OOB errors against training set errors: - * * RelCLS and AvgCE are not calculated for regression problems - * * RMS and AVG should be roughly same - */ - ae_set_error_flag(err, ae_fp_neq(rep.oobrelclserror,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1350"); - ae_set_error_flag(err, ae_fp_neq(rep.oobavgce,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1351"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.oobrmserror/rep.rmserror-1, _state),oobtol), __FILE__, __LINE__, "testdforestunit.ap:1352"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.oobavgerror/rep.avgerror-1, _state),oobtol), __FILE__, __LINE__, "testdforestunit.ap:1353"); - } - else - { - - /* - * Check training set errors - */ - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - x.ptr.p_double[j] = xy.ptr.pp_double[i][j]; - } - dfprocess(&df, &x, &y, _state); - for(j=0; j<=nclasses-1; j++) - { - v = y.ptr.p_double[j]; - if( ae_fp_eq((double)(j),xy.ptr.pp_double[i][nvars]) ) - { - v = v-1; - } - refrms = refrms+ae_sqr(v, _state); - refavg = refavg+ae_fabs(v, _state); - if( ae_fp_eq((double)(j),xy.ptr.pp_double[i][nvars]) ) - { - refavgrel = refavgrel+ae_fabs(v, _state); - refavgce = refavgce-ae_log(v, _state); - } - } - } - refrms = ae_sqrt(refrms/(npoints*nclasses), _state); - refavg = refavg/(npoints*nclasses); - refavgrel = refavgrel/npoints; - refavgce = refavgce/npoints; - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgce-refavgce, _state)/refavgce,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1383"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state)/refrms,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1384"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state)/refavg,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1385"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state)/refavgrel,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1386"); - - /* - * Check OOB errors against training set errors - * * RMS and AVG should be roughly same - * - */ - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.oobrmserror/rep.rmserror-1, _state),oobtol), __FILE__, __LINE__, "testdforestunit.ap:1393"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.oobavgerror/rep.avgerror-1, _state),oobtol), __FILE__, __LINE__, "testdforestunit.ap:1394"); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Test model compression - that it works and generates forests which correctly -reproduce original one -*************************************************************************/ -static void testdforestunit_testcompression(ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t pass; - ae_matrix xy; - ae_int_t npoints; - ae_int_t ntrees; - ae_int_t i; - ae_int_t j; - ae_int_t k; - decisionforestbuilder builder; - decisionforest dfraw; - decisionforest df16; - decisionforest df8; - ae_vector x; - ae_vector y0; - ae_vector y1; - dfreport rep; - ae_int_t nvars; - ae_int_t nclasses; - hqrndstate rs; - double tol16; - double tol8; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&builder, 0, sizeof(builder)); - memset(&dfraw, 0, sizeof(dfraw)); - memset(&df16, 0, sizeof(df16)); - memset(&df8, 0, sizeof(df8)); - memset(&x, 0, sizeof(x)); - memset(&y0, 0, sizeof(y0)); - memset(&y1, 0, sizeof(y1)); - memset(&rep, 0, sizeof(rep)); - memset(&rs, 0, sizeof(rs)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _decisionforestbuilder_init(&builder, _state, ae_true); - _decisionforest_init(&dfraw, _state, ae_true); - _decisionforest_init(&df16, _state, ae_true); - _decisionforest_init(&df8, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y1, 0, DT_REAL, _state, ae_true); - _dfreport_init(&rep, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - tol16 = 0.0001; - tol8 = 0.01; - - /* - * Test compression on small-scale problems: - * * a K-dimensional input, with 3^K distinct points located at integer grid - * * we test that compressed model produces roughly same results as uncompressed - * one (predicts same class / predicts same scalar output subject to small - * truncation error) - */ - for(nvars=1; nvars<=5; nvars++) - { - for(nclasses=1; nclasses<=3; nclasses++) - { - ae_vector_set_length(&x, nvars, _state); - ae_vector_set_length(&y0, nclasses, _state); - ae_vector_set_length(&y1, nclasses, _state); - - /* - * Generate dataset - */ - npoints = ae_round(ae_pow((double)(3), (double)(nvars), _state), _state); - ae_matrix_set_length(&xy, npoints, nvars+1, _state); - for(i=0; i<=npoints-1; i++) - { - k = i; - for(j=0; j<=nvars-1; j++) - { - xy.ptr.pp_double[i][j] = (double)(k%3-1); - k = k/3; - } - if( nclasses==1 ) - { - xy.ptr.pp_double[i][nvars] = hqrnduniformr(&rs, _state)-0.5; - } - else - { - xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nclasses, _state)); - } - } - - /* - * Train uncompressed - */ - ntrees = 1+hqrnduniformi(&rs, 10, _state); - dfbuildercreate(&builder, _state); - dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state); - dfbuildersetsubsampleratio(&builder, 0.66, _state); - dfbuilderbuildrandomforest(&builder, ntrees, &dfraw, &rep, _state); - - /* - * Test 16-bit compression - */ - dfcopy(&dfraw, &df16, _state); - dfbinarycompression(&df16, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - x.ptr.p_double[j] = xy.ptr.pp_double[i][j]; - } - dfprocess(&dfraw, &x, &y0, _state); - dfprocess(&df16, &x, &y1, _state); - if( nclasses>1 ) - { - - /* - * Compare output probabilities for classification problem - */ - for(j=0; j<=nclasses-1; j++) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y0.ptr.p_double[j]-y1.ptr.p_double[j], _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:1488"); - } - } - else - { - - /* - * Compare output values for regression problem - */ - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y0.ptr.p_double[0]-y1.ptr.p_double[0], _state),tol16), __FILE__, __LINE__, "testdforestunit.ap:1495"); - } - } - - /* - * Test 8-bit compression - */ - dfcopy(&dfraw, &df8, _state); - dfbinarycompression8(&df8, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - x.ptr.p_double[j] = xy.ptr.pp_double[i][j]; - } - dfprocess(&dfraw, &x, &y0, _state); - dfprocess(&df8, &x, &y1, _state); - if( nclasses>1 ) - { - - /* - * Compare output probabilities for classification problem - */ - for(j=0; j<=nclasses-1; j++) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y0.ptr.p_double[j]-y1.ptr.p_double[j], _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:1516"); - } - } - else - { - - /* - * Compare output values for regression problem - */ - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y0.ptr.p_double[0]-y1.ptr.p_double[0], _state),tol8), __FILE__, __LINE__, "testdforestunit.ap:1523"); - } - } - } - } - - /* - * Test compression on large-scale problems: - * * NVars=500, NPoints=500, I-th point is zero except for I-th position - * * NClasses=1 (random output) or NClasses=400 - * * NTrees is in 1...5 - */ - for(pass=0; pass<=1; pass++) - { - - /* - * Set up problem - */ - ae_assert(pass==0||pass==1, "DF: integrity check failed", _state); - nvars = 500; - npoints = 500; - nclasses = 1; - if( pass==1 ) - { - nclasses = 400; - } - ae_matrix_set_length(&xy, npoints, nvars+1, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - xy.ptr.pp_double[i][j] = (double)(0); - } - xy.ptr.pp_double[i][i] = (double)(1); - if( nclasses==1 ) - { - xy.ptr.pp_double[i][nvars] = hqrnduniformr(&rs, _state)-0.5; - } - else - { - xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nclasses, _state)); - } - } - ae_vector_set_length(&x, nvars, _state); - ae_vector_set_length(&y0, nclasses, _state); - ae_vector_set_length(&y1, nclasses, _state); - - /* - * Train uncompressed - */ - ntrees = 1+hqrnduniformi(&rs, 5, _state); - dfbuildercreate(&builder, _state); - dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state); - dfbuildersetsubsampleratio(&builder, 0.66, _state); - dfbuilderbuildrandomforest(&builder, ntrees, &dfraw, &rep, _state); - - /* - * Test 16-bit compression - */ - dfcopy(&dfraw, &df16, _state); - dfbinarycompression(&df16, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - x.ptr.p_double[j] = xy.ptr.pp_double[i][j]; - } - dfprocess(&dfraw, &x, &y0, _state); - dfprocess(&df16, &x, &y1, _state); - if( nclasses>1 ) - { - - /* - * Compare output probabilities for classification problem - */ - for(j=0; j<=nclasses-1; j++) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y0.ptr.p_double[j]-y1.ptr.p_double[j], _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:1586"); - } - } - else - { - - /* - * Compare output values for regression problem - */ - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y0.ptr.p_double[0]-y1.ptr.p_double[0], _state),tol16), __FILE__, __LINE__, "testdforestunit.ap:1593"); - } - } - - /* - * Test 8-bit compression - */ - dfcopy(&dfraw, &df8, _state); - dfbinarycompression8(&df8, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - x.ptr.p_double[j] = xy.ptr.pp_double[i][j]; - } - dfprocess(&dfraw, &x, &y0, _state); - dfprocess(&df8, &x, &y1, _state); - if( nclasses>1 ) - { - - /* - * Compare output probabilities for classification problem - */ - for(j=0; j<=nclasses-1; j++) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y0.ptr.p_double[j]-y1.ptr.p_double[j], _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:1614"); - } - } - else - { - - /* - * Compare output values for regression problem - */ - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y0.ptr.p_double[0]-y1.ptr.p_double[0], _state),tol8), __FILE__, __LINE__, "testdforestunit.ap:1621"); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Test variable importance -*************************************************************************/ -static void testdforestunit_testimportance(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t i1; - ae_matrix xy; - ae_matrix xy2; - ae_matrix xyp; - ae_vector c; - ae_vector vloss; - ae_vector tmp; - ae_int_t npoints; - ae_int_t npoints2; - ae_int_t nvars; - ae_int_t nclasses; - ae_int_t ntrees; - decisionforestbuilder builder; - decisionforest df; - dfreport rep; - double v; - double unimportantlo; - double unimportanthi; - double importantlo; - double importanthi; - hqrndstate rs; - ae_int_t ntype; - ae_int_t ntypes; - ae_int_t stype; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&xy2, 0, sizeof(xy2)); - memset(&xyp, 0, sizeof(xyp)); - memset(&c, 0, sizeof(c)); - memset(&vloss, 0, sizeof(vloss)); - memset(&tmp, 0, sizeof(tmp)); - memset(&builder, 0, sizeof(builder)); - memset(&df, 0, sizeof(df)); - memset(&rep, 0, sizeof(rep)); - memset(&rs, 0, sizeof(rs)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xyp, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vloss, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - _decisionforestbuilder_init(&builder, _state, ae_true); - _decisionforest_init(&df, _state, ae_true); - _dfreport_init(&rep, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - ntypes = 3; - hqrndrandomize(&rs, _state); - - /* - * Test that default state of importance estimation is off - */ - npoints = 50; - ntrees = 50; - for(nclasses=1; nclasses<=3; nclasses++) - { - - /* - * Generate dataset - */ - nvars = 1+hqrnduniformi(&rs, 3, _state); - ae_matrix_set_length(&xy, npoints, nvars+1, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - if( nclasses==1 ) - { - xy.ptr.pp_double[i][nvars] = hqrnduniformr(&rs, _state)-0.5; - } - else - { - xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nclasses, _state)); - } - } - - /* - * Train with default settings, check that variable importances reported are zero - */ - dfbuildercreate(&builder, _state); - dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state); - dfbuildersetsubsampleratio(&builder, 0.66, _state); - dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state); - ae_set_error_flag(err, rep.varimportances.cnt!=nvars, __FILE__, __LINE__, "testdforestunit.ap:1687"); - ae_set_error_flag(err, rep.topvars.cnt!=nvars, __FILE__, __LINE__, "testdforestunit.ap:1688"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - for(j=0; j<=nvars-1; j++) - { - ae_set_error_flag(err, ae_fp_neq(rep.varimportances.ptr.p_double[j],(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1693"); - ae_set_error_flag(err, rep.topvars.ptr.p_int[j]!=j, __FILE__, __LINE__, "testdforestunit.ap:1694"); - } - } - - /* - * Test that degenerate cases are handled correctly - */ - npoints = 50; - ntrees = 50; - for(nclasses=1; nclasses<=3; nclasses++) - { - for(npoints=1; npoints<=2; npoints++) - { - for(stype=0; stype<=1; stype++) - { - for(ntype=0; ntype<=ntypes-1; ntype++) - { - - /* - * Generate dataset - */ - nvars = 1+hqrnduniformi(&rs, 3, _state); - ae_matrix_set_length(&xy, npoints, nvars+1, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - if( nclasses==1 ) - { - xy.ptr.pp_double[i][nvars] = hqrnduniformr(&rs, _state)-0.5; - } - else - { - xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nclasses, _state)); - } - } - - /* - * Train - */ - dfbuildercreate(&builder, _state); - dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state); - dfbuildersetsubsampleratio(&builder, 1.0-stype*0.5, _state); - ae_assert(ntype<=2, "integrity check in the test", _state); - if( ntype==0 ) - { - dfbuildersetimportanceoobgini(&builder, _state); - } - if( ntype==1 ) - { - dfbuildersetimportancepermutation(&builder, _state); - } - if( ntype==2 ) - { - dfbuildersetimportancetrngini(&builder, _state); - } - dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state); - ae_set_error_flag(err, rep.varimportances.cnt!=nvars, __FILE__, __LINE__, "testdforestunit.ap:1737"); - ae_set_error_flag(err, rep.topvars.cnt!=nvars, __FILE__, __LINE__, "testdforestunit.ap:1738"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - if( npoints==1||stype==1 ) - { - for(j=0; j<=nvars-1; j++) - { - ae_set_error_flag(err, ae_fp_neq(rep.varimportances.ptr.p_double[j],(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1745"); - ae_set_error_flag(err, rep.topvars.ptr.p_int[j]!=j, __FILE__, __LINE__, "testdforestunit.ap:1746"); - } - } - } - } - } - } - - /* - * Test various importance types - */ - for(ntype=0; ntype<=ntypes-1; ntype++) - { - - /* - * Select variables count - */ - nvars = 1+hqrnduniformi(&rs, 3, _state); - - /* - * Select preferred problem metrics for this importance type - */ - npoints = -1; - ntrees = -1; - unimportantlo = (double)(-1); - unimportanthi = (double)(-1); - importantlo = (double)(-1); - importanthi = (double)(-1); - if( ntype==0 ) - { - - /* - * OOB Gini importance averages individual importances between multiple trees, - * so its variance is inversely proportional to the tree count. Tasks with large number - * of trees are preferred. - */ - npoints = 250; - ntrees = 1000; - unimportantlo = 0.00; - unimportanthi = 0.25; - importantlo = 0.75*((double)1/(double)nvars); - importanthi = ae_minreal(1.25*((double)1/(double)nvars), 1.00, _state); - } - if( ntype==1 ) - { - - /* - * Variance of permutation importance estimate is inversely proportional to the - * dataset size. Tasks with large number of points are preferred, trees count - * does not matter much here. - */ - npoints = 5000; - ntrees = 10; - unimportantlo = 0.00; - unimportanthi = 0.15; - importantlo = 0.85; - importanthi = 1.00; - } - if( ntype==2 ) - { - - /* - * TRN Gini importance averages individual importances between multiple trees, - * so its variance is inversely proportional to the tree count. Tasks with large number - * of trees are preferred. - */ - npoints = 250; - ntrees = 1000; - unimportantlo = 0.75*((double)1/(double)nvars); - unimportanthi = ae_minreal(1.25*((double)1/(double)nvars), 1.00, _state); - importantlo = 0.75*((double)1/(double)nvars); - importanthi = ae_minreal(1.25*((double)1/(double)nvars), 1.00, _state); - } - - /* - * Test on a problem with completely random outputs - */ - for(nclasses=1; nclasses<=3; nclasses++) - { - - /* - * Generate dataset - */ - ae_matrix_set_length(&xy, npoints, nvars+1, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - if( nclasses==1 ) - { - xy.ptr.pp_double[i][nvars] = hqrnduniformr(&rs, _state)-0.5; - } - else - { - xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nclasses, _state)); - } - } - testdforestunit_randomlyrearrange(&xy, npoints, nvars, &rs, _state); - - /* - * Train - */ - dfbuildercreate(&builder, _state); - dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state); - dfbuildersetsubsampleratio(&builder, 0.66, _state); - dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state); - ae_assert(ntype<=2, "integrity check in the test", _state); - if( ntype==0 ) - { - dfbuildersetimportanceoobgini(&builder, _state); - } - if( ntype==1 ) - { - dfbuildersetimportancepermutation(&builder, _state); - } - if( ntype==2 ) - { - dfbuildersetimportancetrngini(&builder, _state); - } - dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state); - ae_set_error_flag(err, rep.varimportances.cnt!=nvars, __FILE__, __LINE__, "testdforestunit.ap:1848"); - ae_set_error_flag(err, rep.topvars.cnt!=nvars, __FILE__, __LINE__, "testdforestunit.ap:1849"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - for(j=0; j<=nvars-1; j++) - { - ae_set_error_flag(err, ae_fp_less(rep.varimportances.ptr.p_double[j],unimportantlo), __FILE__, __LINE__, "testdforestunit.ap:1856"); - ae_set_error_flag(err, ae_fp_greater(rep.varimportances.ptr.p_double[j],unimportanthi), __FILE__, __LINE__, "testdforestunit.ap:1857"); - } - setlengthzero(&tmp, nvars, _state); - for(j=0; j<=nvars-1; j++) - { - ae_set_error_flag(err, rep.topvars.ptr.p_int[j]<0, __FILE__, __LINE__, "testdforestunit.ap:1862"); - ae_set_error_flag(err, rep.topvars.ptr.p_int[j]>=nvars, __FILE__, __LINE__, "testdforestunit.ap:1863"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(err, ae_fp_neq(tmp.ptr.p_double[rep.topvars.ptr.p_int[j]],(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1866"); - tmp.ptr.p_double[rep.topvars.ptr.p_int[j]] = tmp.ptr.p_double[rep.topvars.ptr.p_int[j]]+1; - } - for(j=0; j<=nvars-2; j++) - { - ae_set_error_flag(err, ae_fp_less(rep.varimportances.ptr.p_double[rep.topvars.ptr.p_int[j]],rep.varimportances.ptr.p_double[rep.topvars.ptr.p_int[j+1]]), __FILE__, __LINE__, "testdforestunit.ap:1870"); - } - if( ntype==2 ) - { - - /* - * TRN-Gini importances sum to 1.0 - */ - v = (double)(0); - for(j=0; j<=nvars-1; j++) - { - v = v+rep.varimportances.ptr.p_double[j]; - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-1, _state),1.0e-6), __FILE__, __LINE__, "testdforestunit.ap:1879"); - } - } - - /* - * Test that on a problem where: - * * every variable matters - * * every variable is critical - * * result is completely predictable. - */ - for(nclasses=1; nclasses<=3; nclasses++) - { - - /* - * Generate dataset - */ - ae_matrix_set_length(&xy, npoints, nvars+1, _state); - for(i=0; i<=npoints-1; i++) - { - if( nclasses==1 ) - { - xy.ptr.pp_double[i][nvars] = (double)(0); - k = i; - for(j=0; j<=nvars-1; j++) - { - xy.ptr.pp_double[i][j] = (double)(k%3); - xy.ptr.pp_double[i][nvars] = xy.ptr.pp_double[i][nvars]+ae_round(xy.ptr.pp_double[i][j], _state); - k = k/3; - } - xy.ptr.pp_double[i][nvars] = (double)(ae_round(xy.ptr.pp_double[i][nvars], _state)%3-1); - } - else - { - xy.ptr.pp_double[i][nvars] = (double)(0); - k = i; - for(j=0; j<=nvars-1; j++) - { - xy.ptr.pp_double[i][j] = (double)(k%nclasses); - xy.ptr.pp_double[i][nvars] = xy.ptr.pp_double[i][nvars]+ae_round(xy.ptr.pp_double[i][j], _state); - k = k/nclasses; - } - xy.ptr.pp_double[i][nvars] = (double)(ae_round(xy.ptr.pp_double[i][nvars], _state)%nclasses); - } - } - testdforestunit_randomlyrearrange(&xy, npoints, nvars, &rs, _state); - - /* - * Train - */ - dfbuildercreate(&builder, _state); - dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state); - dfbuildersetsubsampleratio(&builder, 0.5, _state); - dfbuildersetrndvars(&builder, nvars, _state); - ae_assert(ntype<=2, "integrity check in the test", _state); - if( ntype==0 ) - { - dfbuildersetimportanceoobgini(&builder, _state); - } - if( ntype==1 ) - { - dfbuildersetimportancepermutation(&builder, _state); - } - if( ntype==2 ) - { - dfbuildersetimportancetrngini(&builder, _state); - } - dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state); - ae_set_error_flag(err, rep.varimportances.cnt!=nvars, __FILE__, __LINE__, "testdforestunit.ap:1939"); - ae_set_error_flag(err, rep.topvars.cnt!=nvars, __FILE__, __LINE__, "testdforestunit.ap:1940"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - for(j=0; j<=nvars-1; j++) - { - ae_set_error_flag(err, ae_fp_less(rep.varimportances.ptr.p_double[j],importantlo), __FILE__, __LINE__, "testdforestunit.ap:1947"); - ae_set_error_flag(err, ae_fp_greater(rep.varimportances.ptr.p_double[j],importanthi), __FILE__, __LINE__, "testdforestunit.ap:1948"); - } - setlengthzero(&tmp, nvars, _state); - for(j=0; j<=nvars-1; j++) - { - ae_set_error_flag(err, rep.topvars.ptr.p_int[j]<0, __FILE__, __LINE__, "testdforestunit.ap:1953"); - ae_set_error_flag(err, rep.topvars.ptr.p_int[j]>=nvars, __FILE__, __LINE__, "testdforestunit.ap:1954"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(err, ae_fp_neq(tmp.ptr.p_double[rep.topvars.ptr.p_int[j]],(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1957"); - tmp.ptr.p_double[rep.topvars.ptr.p_int[j]] = tmp.ptr.p_double[rep.topvars.ptr.p_int[j]]+1; - } - for(j=0; j<=nvars-2; j++) - { - ae_set_error_flag(err, ae_fp_less(rep.varimportances.ptr.p_double[rep.topvars.ptr.p_int[j]],rep.varimportances.ptr.p_double[rep.topvars.ptr.p_int[j+1]]), __FILE__, __LINE__, "testdforestunit.ap:1961"); - } - if( ntype==2 ) - { - - /* - * TRN-Gini importances sum to 1.0 - */ - v = (double)(0); - for(j=0; j<=nvars-1; j++) - { - v = v+rep.varimportances.ptr.p_double[j]; - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-1, _state),1.0e-6), __FILE__, __LINE__, "testdforestunit.ap:1970"); - } - } - } - - /* - * Test values computed by the fast MDA (permutation) algorithm against - * ones computed by definition (by simply running model on permuted dataset). - * - * We solve regression and 2-class classification problems. - * - * Large "reference" dataset is used to compute reference importances in order - * to reduce variance of at least one component in the difference |I_reference-I_computed| - */ - npoints = 5000; - ntrees = 10; - npoints2 = npoints; - for(nclasses=1; nclasses<=2; nclasses++) - { - - /* - * Generate dataset - */ - nvars = 3; - ae_vector_set_length(&c, nvars, _state); - for(j=0; j<=nvars-1; j++) - { - c.ptr.p_double[j] = ae_pow((double)(2), (double)(-j), _state); - } - ae_matrix_set_length(&xy2, npoints+npoints2, nvars+1, _state); - for(i=0; i<=npoints+npoints2-1; i++) - { - xy2.ptr.pp_double[i][nvars] = 0.01*hqrndnormal(&rs, _state); - for(j=0; j<=nvars-1; j++) - { - xy2.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5; - xy2.ptr.pp_double[i][nvars] = xy2.ptr.pp_double[i][nvars]+xy2.ptr.pp_double[i][j]*c.ptr.p_double[j]; - } - if( nclasses==2 ) - { - if( ae_fp_greater(xy2.ptr.pp_double[i][nvars],(double)(0)) ) - { - xy2.ptr.pp_double[i][nvars] = (double)(0); - } - else - { - xy2.ptr.pp_double[i][nvars] = (double)(1); - } - } - } - ae_matrix_set_length(&xy, npoints, nvars+1, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars; j++) - { - xy.ptr.pp_double[i][j] = xy2.ptr.pp_double[npoints2+i][j]; - } - } - rmatrixresize(&xy2, npoints2, nvars+1, _state); - testdforestunit_randomlyrearrange(&xy, npoints, nvars, &rs, _state); - - /* - * Train model - */ - dfbuildercreate(&builder, _state); - dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state); - dfbuildersetsubsampleratio(&builder, 0.5, _state); - dfbuildersetimportancepermutation(&builder, _state); - dfbuildersetrndvars(&builder, nvars, _state); - dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state); - ae_set_error_flag(err, rep.varimportances.cnt!=nvars, __FILE__, __LINE__, "testdforestunit.ap:2029"); - ae_set_error_flag(err, rep.topvars.cnt!=nvars, __FILE__, __LINE__, "testdforestunit.ap:2030"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - - /* - * Compute importances by definition - */ - ae_matrix_set_length(&xyp, npoints2, nvars+1, _state); - ae_vector_set_length(&vloss, nvars+2, _state); - for(k=0; k<=nvars+1; k++) - { - for(i=0; i<=npoints2-1; i++) - { - for(j=0; j<=nvars; j++) - { - xyp.ptr.pp_double[i][j] = xy2.ptr.pp_double[i][j]; - } - } - if( kptr.pp_double[i][kind]; - } - tagsort(&y, npoints, &p1, &p2, _state); - for(i=0; i<=npoints-1; i++) - { - swaprows(xy, i, p2.ptr.p_int[i], nvars+1, _state); - } - ae_frame_leave(_state); -} - - - -static void testknnunit_testknnalgo(ae_bool* err, ae_state *_state); -static void testknnunit_unsetknn(knnmodel* model, ae_state *_state); -static void testknnunit_testseterrors(knnmodel* model, - ae_int_t nvars, - ae_int_t nout, - ae_bool iscls, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double* avgce, - double* relcls0, - double* relcls1, - double* rms, - double* avg, - double* avgrel, - ae_state *_state); - - - - - -ae_bool testknn(ae_bool silent, ae_state *_state) -{ - ae_bool waserrors; - ae_bool knnerrors; - ae_bool result; - - - - /* - * Primary settings - */ - knnerrors = ae_false; - waserrors = ae_false; - - /* - * Tests - */ - testknnunit_testknnalgo(&knnerrors, _state); - - /* - * Final report - */ - waserrors = knnerrors; - if( !silent ) - { - printf("KNN CLASSIFIER/REGRESSION TEST\n"); - printf("TOTAL RESULTS: "); - if( !waserrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* KNN (AKNN) ALGORITHM "); - if( !knnerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST SUMMARY: FAILED\n"); - } - else - { - printf("TEST SUMMARY: PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - return result; -} - - -/************************************************************************* -Processing functions test -*************************************************************************/ -static void testknnunit_testknnalgo(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t nvars; - ae_int_t nout; - ae_bool iscls; - ae_int_t ny; - ae_int_t k; - double eps; - knnmodel model1; - knnmodel model2; - knnmodel modelus; - knnbuilder builder; - knnreport rep; - knnreport rep2; - knnreport tstrep; - knnbuffer buf; - ae_matrix xy; - ae_int_t npoints; - ae_matrix testxy; - ae_int_t testnpoints; - ae_int_t pass; - ae_int_t i; - ae_int_t j; - ae_bool allsame; - ae_vector x1; - ae_vector x2; - ae_vector y1; - ae_vector y2; - ae_vector y3; - double v; - double refavgce; - double refcls0; - double refcls1; - double refrms; - double refavg; - double refavgrel; - double maxerr; - double avgerr; - ae_int_t cnt; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&model1, 0, sizeof(model1)); - memset(&model2, 0, sizeof(model2)); - memset(&modelus, 0, sizeof(modelus)); - memset(&builder, 0, sizeof(builder)); - memset(&rep, 0, sizeof(rep)); - memset(&rep2, 0, sizeof(rep2)); - memset(&tstrep, 0, sizeof(tstrep)); - memset(&buf, 0, sizeof(buf)); - memset(&xy, 0, sizeof(xy)); - memset(&testxy, 0, sizeof(testxy)); - memset(&x1, 0, sizeof(x1)); - memset(&x2, 0, sizeof(x2)); - memset(&y1, 0, sizeof(y1)); - memset(&y2, 0, sizeof(y2)); - memset(&y3, 0, sizeof(y3)); - memset(&rs, 0, sizeof(rs)); - _knnmodel_init(&model1, _state, ae_true); - _knnmodel_init(&model2, _state, ae_true); - _knnmodel_init(&modelus, _state, ae_true); - _knnbuilder_init(&builder, _state, ae_true); - _knnreport_init(&rep, _state, ae_true); - _knnreport_init(&rep2, _state, ae_true); - _knnreport_init(&tstrep, _state, ae_true); - _knnbuffer_init(&buf, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&testxy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y3, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Test on randomly generated sets with randomly generated algo settings - * - * We test: - * * process - * * processi - * * process0 - * * classify - * * serialization/unserialization - * * reports and test set error evaluation - * * knnrewritekeps() - */ - for(pass=1; pass<=100; pass++) - { - - /* - * initialize parameters - */ - nvars = 1+hqrnduniformi(&rs, 5, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - iscls = ae_true; - nout = 2+hqrnduniformi(&rs, 3, _state); - ny = 1; - } - else - { - iscls = ae_false; - nout = 1+hqrnduniformi(&rs, 3, _state); - ny = nout; - } - k = 1+hqrnduniformi(&rs, 3, _state); - eps = hqrnduniformi(&rs, 2, _state)*0.1*hqrnduniformr(&rs, _state); - - /* - * Initialize arrays and data: training and test sets - */ - npoints = 10+hqrnduniformi(&rs, 100, _state); - ae_matrix_set_length(&xy, npoints, nvars+ny, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - if( j%2==0 ) - { - xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - else - { - xy.ptr.pp_double[i][j] = (double)(hqrnduniformi(&rs, 2, _state)); - } - } - if( iscls ) - { - xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nout, _state)); - } - else - { - for(j=0; j<=nout-1; j++) - { - xy.ptr.pp_double[i][nvars+j] = hqrndnormal(&rs, _state); - } - } - } - testnpoints = 10+hqrnduniformi(&rs, 100, _state); - ae_matrix_set_length(&testxy, testnpoints, nvars+ny, _state); - for(i=0; i<=testnpoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - if( j%2==0 ) - { - testxy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - else - { - testxy.ptr.pp_double[i][j] = (double)(hqrnduniformi(&rs, 2, _state)); - } - } - if( iscls ) - { - testxy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nout, _state)); - } - else - { - for(j=0; j<=nout-1; j++) - { - testxy.ptr.pp_double[i][nvars+j] = hqrndnormal(&rs, _state); - } - } - } - - /* - * create model - */ - testknnunit_unsetknn(&model1, _state); - knnbuildercreate(&builder, _state); - if( iscls ) - { - knnbuildersetdatasetcls(&builder, &xy, npoints, nvars, nout, _state); - } - else - { - knnbuildersetdatasetreg(&builder, &xy, npoints, nvars, nout, _state); - } - knnbuildersetnorm(&builder, hqrnduniformi(&rs, 3, _state), _state); - knnbuilderbuildknnmodel(&builder, k, eps, &model1, &rep, _state); - knncreatebuffer(&model1, &buf, _state); - - /* - * Check that: - * * knnprocess() does not shrink output array, only increases - * * knntsprocess() does not shrink output array, only increases - * * knnprocessi() fits length exactly to NOut - */ - ae_vector_set_length(&x1, nvars, _state); - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&y1, nout+1, _state); - knnprocess(&model1, &x1, &y1, _state); - ae_set_error_flag(err, y1.cnt!=nout+1, __FILE__, __LINE__, "testknnunit.ap:200"); - ae_vector_set_length(&y1, nout-1, _state); - knnprocess(&model1, &x1, &y1, _state); - ae_set_error_flag(err, y1.cnt!=nout, __FILE__, __LINE__, "testknnunit.ap:203"); - ae_vector_set_length(&y1, nout+1, _state); - knntsprocess(&model1, &buf, &x1, &y1, _state); - ae_set_error_flag(err, y1.cnt!=nout+1, __FILE__, __LINE__, "testknnunit.ap:207"); - ae_vector_set_length(&y1, nout-1, _state); - knntsprocess(&model1, &buf, &x1, &y1, _state); - ae_set_error_flag(err, y1.cnt!=nout, __FILE__, __LINE__, "testknnunit.ap:210"); - ae_vector_set_length(&y1, nout+1, _state); - knnprocessi(&model1, &x1, &y1, _state); - ae_set_error_flag(err, y1.cnt!=nout, __FILE__, __LINE__, "testknnunit.ap:214"); - ae_vector_set_length(&y1, nout-1, _state); - knnprocessi(&model1, &x1, &y1, _state); - ae_set_error_flag(err, y1.cnt!=nout, __FILE__, __LINE__, "testknnunit.ap:217"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - - /* - * knnprocess(), knnprocessi() and knntsprocess() return same results - */ - ae_vector_set_length(&x1, nvars, _state); - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - knnprocess(&model1, &x1, &y1, _state); - knnprocessi(&model1, &x1, &y2, _state); - knntsprocess(&model1, &buf, &x1, &y3, _state); - for(i=0; i<=nout-1; i++) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y2.ptr.p_double[i]-y1.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testknnunit.ap:232"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y3.ptr.p_double[i]-y1.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testknnunit.ap:233"); - } - - /* - * Same inputs leads to same outputs - */ - ae_vector_set_length(&x1, nvars, _state); - ae_vector_set_length(&x2, nvars, _state); - ae_vector_set_length(&y1, nout, _state); - ae_vector_set_length(&y2, nout, _state); - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = hqrndnormal(&rs, _state); - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - for(i=0; i<=nout-1; i++) - { - y1.ptr.p_double[i] = hqrndnormal(&rs, _state); - y2.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - knnprocess(&model1, &x1, &y1, _state); - knnprocess(&model1, &x2, &y2, _state); - allsame = ae_true; - for(i=0; i<=nout-1; i++) - { - allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]); - } - ae_set_error_flag(err, !allsame, __FILE__, __LINE__, "testknnunit.ap:259"); - - /* - * Same inputs on original forest leads to same outputs - * on copy created using KNNSerialize - */ - ae_vector_set_length(&x1, nvars, _state); - ae_vector_set_length(&x2, nvars, _state); - ae_vector_set_length(&y1, nout, _state); - ae_vector_set_length(&y2, nout, _state); - testknnunit_unsetknn(&modelus, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - knnalloc(&_local_serializer, &model1, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - knnserialize(&_local_serializer, &model1, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - knnunserialize(&_local_serializer, &modelus, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = hqrndnormal(&rs, _state); - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - for(i=0; i<=nout-1; i++) - { - y1.ptr.p_double[i] = hqrndnormal(&rs, _state); - y2.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - knnprocess(&model1, &x1, &y1, _state); - knnprocess(&modelus, &x2, &y2, _state); - allsame = ae_true; - for(i=0; i<=nout-1; i++) - { - allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]); - } - ae_set_error_flag(err, !allsame, __FILE__, __LINE__, "testknnunit.ap:287"); - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = hqrndnormal(&rs, _state); - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(knnprocess0(&model1, &x1, _state)-knnprocess0(&modelus, &x2, _state), _state),100*ae_machineepsilon), __FILE__, __LINE__, "testknnunit.ap:293"); - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = hqrndnormal(&rs, _state); - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - ae_set_error_flag(err, knnclassify(&model1, &x1, _state)!=knnclassify(&modelus, &x2, _state), __FILE__, __LINE__, "testknnunit.ap:299"); - - /* - * KNNProcess0 works as expected - */ - ae_vector_set_length(&x1, nvars, _state); - ae_vector_set_length(&x2, nvars, _state); - ae_vector_set_length(&y1, nout, _state); - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = hqrndnormal(&rs, _state); - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - for(i=0; i<=nout-1; i++) - { - y1.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - knnprocess(&model1, &x1, &y1, _state); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y1.ptr.p_double[0]-knnprocess0(&model1, &x2, _state), _state),100*ae_machineepsilon), __FILE__, __LINE__, "testknnunit.ap:318"); - - /* - * KNNClassify works as expected - */ - ae_vector_set_length(&x1, nvars, _state); - ae_vector_set_length(&x2, nvars, _state); - ae_vector_set_length(&y1, nout, _state); - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = hqrndnormal(&rs, _state); - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - if( iscls ) - { - for(i=0; i<=nout-1; i++) - { - y1.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - knnprocess(&model1, &x1, &y1, _state); - j = knnclassify(&model1, &x2, _state); - for(i=0; i<=nout-1; i++) - { - ae_set_error_flag(err, ae_fp_greater(y1.ptr.p_double[i],y1.ptr.p_double[j]), __FILE__, __LINE__, "testknnunit.ap:341"); - } - } - else - { - ae_set_error_flag(err, knnclassify(&model1, &x2, _state)!=-1, __FILE__, __LINE__, "testknnunit.ap:344"); - } - - /* - * Normalization properties - */ - if( iscls ) - { - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&y1, 0, _state); - knnprocess(&model1, &x1, &y1, _state); - v = (double)(0); - for(i=0; i<=nout-1; i++) - { - v = v+y1.ptr.p_double[i]; - ae_set_error_flag(err, ae_fp_less(y1.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testknnunit.ap:359"); - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-1, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testknnunit.ap:361"); - } - - /* - * Test various error metrics reported by algorithm: - * * training set errors included in the report - * * errors on the test set - * - * NOTE: cross-entropy metric is tested only for training set. - * because model can produce exactly zero probabilities - * for completely unknown values - */ - testknnunit_testseterrors(&model1, nvars, nout, iscls, &xy, npoints, &refavgce, &refcls0, &refcls1, &refrms, &refavg, &refavgrel, _state); - if( iscls ) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgce-refavgce, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:377"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(knnavgce(&model1, &xy, npoints, _state)-refavgce, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:378"); - ae_set_error_flag(err, ae_fp_less(rep.relclserror,refcls0-1.0E-6), __FILE__, __LINE__, "testknnunit.ap:381"); - ae_set_error_flag(err, ae_fp_greater(rep.relclserror,refcls1+1.0E-6), __FILE__, __LINE__, "testknnunit.ap:382"); - ae_set_error_flag(err, ae_fp_less(knnrelclserror(&model1, &xy, npoints, _state),refcls0-1.0E-6), __FILE__, __LINE__, "testknnunit.ap:383"); - ae_set_error_flag(err, ae_fp_greater(knnrelclserror(&model1, &xy, npoints, _state),refcls1+1.0E-6), __FILE__, __LINE__, "testknnunit.ap:384"); - } - else - { - ae_set_error_flag(err, ae_fp_neq(rep.avgce,(double)(0)), __FILE__, __LINE__, "testknnunit.ap:389"); - ae_set_error_flag(err, ae_fp_neq(knnavgce(&model1, &xy, npoints, _state),(double)(0)), __FILE__, __LINE__, "testknnunit.ap:390"); - ae_set_error_flag(err, ae_fp_neq(rep.relclserror,(double)(0)), __FILE__, __LINE__, "testknnunit.ap:393"); - ae_set_error_flag(err, ae_fp_neq(knnrelclserror(&model1, &xy, npoints, _state),(double)(0)), __FILE__, __LINE__, "testknnunit.ap:394"); - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:396"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:397"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:398"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(knnrmserror(&model1, &xy, npoints, _state)-refrms, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:399"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(knnavgerror(&model1, &xy, npoints, _state)-refavg, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:400"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(knnavgrelerror(&model1, &xy, npoints, _state)-refavgrel, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:401"); - testknnunit_testseterrors(&model1, nvars, nout, iscls, &testxy, testnpoints, &refavgce, &refcls0, &refcls1, &refrms, &refavg, &refavgrel, _state); - knnallerrors(&model1, &testxy, testnpoints, &tstrep, _state); - if( iscls ) - { - ae_set_error_flag(err, ae_fp_less(tstrep.relclserror,refcls0-1.0E-6), __FILE__, __LINE__, "testknnunit.ap:406"); - ae_set_error_flag(err, ae_fp_greater(tstrep.relclserror,refcls1+1.0E-6), __FILE__, __LINE__, "testknnunit.ap:407"); - } - else - { - ae_set_error_flag(err, ae_fp_neq(tstrep.avgce,(double)(0)), __FILE__, __LINE__, "testknnunit.ap:411"); - ae_set_error_flag(err, ae_fp_neq(tstrep.relclserror,(double)(0)), __FILE__, __LINE__, "testknnunit.ap:412"); - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(tstrep.rmserror-refrms, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:414"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(tstrep.avgerror-refavg, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:415"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(tstrep.avgrelerror-refavgrel, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:416"); - } - - /* - * Test that model built with K=1 and Eps=0 remembers all training cases - */ - for(nvars=1; nvars<=4; nvars++) - { - for(pass=0; pass<=10; pass++) - { - - /* - * Prepare task - */ - npoints = 1+hqrnduniformi(&rs, 20, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - iscls = ae_true; - nout = 2+hqrnduniformi(&rs, 3, _state); - ny = 1; - } - else - { - iscls = ae_false; - nout = 1+hqrnduniformi(&rs, 3, _state); - ny = nout; - } - ae_matrix_set_length(&xy, npoints, nvars+ny, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = i*0.000001; - for(j=1; j<=nvars-1; j++) - { - xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - if( iscls ) - { - xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nout, _state)); - } - else - { - for(j=0; j<=nout-1; j++) - { - xy.ptr.pp_double[i][nvars+j] = hqrndnormal(&rs, _state); - } - } - } - - /* - * Create model - */ - testknnunit_unsetknn(&model1, _state); - knnbuildercreate(&builder, _state); - if( iscls ) - { - knnbuildersetdatasetcls(&builder, &xy, npoints, nvars, nout, _state); - } - else - { - knnbuildersetdatasetreg(&builder, &xy, npoints, nvars, nout, _state); - } - knnbuildersetnorm(&builder, hqrnduniformi(&rs, 3, _state), _state); - knnbuilderbuildknnmodel(&builder, 1, 0.0, &model1, &rep, _state); - ae_set_error_flag(err, ae_fp_greater(rep.avgce,(double)(0)), __FILE__, __LINE__, "testknnunit.ap:467"); - ae_set_error_flag(err, ae_fp_greater(rep.relclserror,(double)(0)), __FILE__, __LINE__, "testknnunit.ap:468"); - ae_set_error_flag(err, ae_fp_greater(rep.rmserror,1.0E-6), __FILE__, __LINE__, "testknnunit.ap:469"); - ae_set_error_flag(err, ae_fp_greater(rep.avgerror,1.0E-6), __FILE__, __LINE__, "testknnunit.ap:470"); - ae_set_error_flag(err, ae_fp_greater(rep.avgrelerror,1.0E-6), __FILE__, __LINE__, "testknnunit.ap:471"); - ae_vector_set_length(&x1, nvars, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - x1.ptr.p_double[j] = xy.ptr.pp_double[i][j]; - } - knnprocess(&model1, &x1, &y1, _state); - if( iscls ) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y1.ptr.p_double[ae_round(xy.ptr.pp_double[i][nvars], _state)]-1, _state),10*ae_machineepsilon), __FILE__, __LINE__, "testknnunit.ap:479"); - } - else - { - for(j=0; j<=nout-1; j++) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y1.ptr.p_double[j]-xy.ptr.pp_double[i][nvars+j], _state),10*ae_machineepsilon), __FILE__, __LINE__, "testknnunit.ap:483"); - } - } - } - } - } - - /* - * Test that model rewrite works as expected - */ - for(nvars=1; nvars<=20; nvars++) - { - - /* - * Prepare task - */ - npoints = 50+5*nvars; - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - iscls = ae_true; - nout = 2+hqrnduniformi(&rs, 3, _state); - ny = 1; - } - else - { - iscls = ae_false; - nout = 1+hqrnduniformi(&rs, 3, _state); - ny = nout; - } - ae_matrix_set_length(&xy, npoints, nvars+ny, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - if( iscls ) - { - xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nout, _state)); - } - else - { - for(j=0; j<=nout-1; j++) - { - xy.ptr.pp_double[i][nvars+j] = hqrndnormal(&rs, _state); - } - } - } - - /* - * Select K, Eps - */ - k = 1+hqrnduniformi(&rs, 10, _state); - eps = hqrnduniformi(&rs, 2, _state)*(1+3*hqrnduniformr(&rs, _state)); - - /* - * Create model 1 using K, EPS. - * Create model 2 using other (K,Eps), then rewrite search settings - */ - knnbuildercreate(&builder, _state); - if( iscls ) - { - knnbuildersetdatasetcls(&builder, &xy, npoints, nvars, nout, _state); - } - else - { - knnbuildersetdatasetreg(&builder, &xy, npoints, nvars, nout, _state); - } - testknnunit_unsetknn(&model1, _state); - knnbuilderbuildknnmodel(&builder, k, eps, &model1, &rep, _state); - testknnunit_unsetknn(&model2, _state); - knnbuilderbuildknnmodel(&builder, 1+hqrnduniformi(&rs, 10, _state), hqrnduniformi(&rs, 2, _state)*(1+3*hqrnduniformr(&rs, _state)), &model2, &rep2, _state); - knnrewritekeps(&model2, k, eps, _state); - ae_vector_set_length(&x1, nvars, _state); - ae_vector_set_length(&x2, nvars, _state); - for(i=0; i<=nvars-1; i++) - { - x1.ptr.p_double[i] = hqrndnormal(&rs, _state); - x2.ptr.p_double[i] = x1.ptr.p_double[i]; - } - knnprocess(&model1, &x1, &y1, _state); - knnprocess(&model2, &x2, &y2, _state); - for(i=0; i<=nout-1; i++) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y1.ptr.p_double[i]-y2.ptr.p_double[i], _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testknnunit.ap:553"); - } - } - - /* - * Test generalization ability on a simple noisy classification task: - * * 00 results in worse error metrics, but not too bad - */ - - /* - * Prepare task - */ - npoints = 5000; - ae_matrix_set_length(&xy, npoints, 3, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = 2*hqrnduniformr(&rs, _state)-1; - xy.ptr.pp_double[i][1] = 2*hqrnduniformr(&rs, _state)-1; - xy.ptr.pp_double[i][2] = ae_sqr(xy.ptr.pp_double[i][0], _state)+xy.ptr.pp_double[i][1]; - } - - /* - * Build model with Eps=0, check model quality - */ - k = 50; - testknnunit_unsetknn(&model1, _state); - knnbuildercreate(&builder, _state); - knnbuildersetdatasetreg(&builder, &xy, npoints, 2, 1, _state); - knnbuildersetnorm(&builder, hqrnduniformi(&rs, 3, _state), _state); - knnbuilderbuildknnmodel(&builder, k, 0.0, &model1, &rep, _state); - ae_vector_set_length(&x1, 2, _state); - maxerr = (double)(0); - avgerr = (double)(0); - cnt = 0; - for(i=0; i<=1000; i++) - { - - /* - * NOTE: we test model in the inner points, it deteriorates near the bounds - */ - x1.ptr.p_double[0] = 0.8*(2*hqrnduniformr(&rs, _state)-1); - x1.ptr.p_double[1] = 0.8*(2*hqrnduniformr(&rs, _state)-1); - v = ae_sqr(x1.ptr.p_double[0], _state)+x1.ptr.p_double[1]; - knnprocess(&model1, &x1, &y1, _state); - v = ae_fabs(y1.ptr.p_double[0]-v, _state); - maxerr = ae_maxreal(maxerr, v, _state); - avgerr = avgerr+v; - cnt = cnt+1; - } - avgerr = avgerr/cnt; - ae_set_error_flag(err, ae_fp_greater(maxerr,0.15), __FILE__, __LINE__, "testknnunit.ap:669"); - ae_set_error_flag(err, ae_fp_greater(avgerr,0.05), __FILE__, __LINE__, "testknnunit.ap:670"); - - /* - * Build model with Eps=1.0, compare error metrics with Eps=0 - */ - knnbuilderbuildknnmodel(&builder, k, 1.0, &model2, &rep2, _state); - ae_set_error_flag(err, ae_fp_less_eq(rep2.rmserror,rep.rmserror), __FILE__, __LINE__, "testknnunit.ap:676"); - ae_set_error_flag(err, ae_fp_less_eq(rep2.rmserror,rep.rmserror+0.001), __FILE__, __LINE__, "testknnunit.ap:677"); - ae_set_error_flag(err, ae_fp_greater_eq(rep2.rmserror,rep.rmserror+0.020), __FILE__, __LINE__, "testknnunit.ap:678"); - ae_frame_leave(_state); -} - - -/************************************************************************* -Unsets model -*************************************************************************/ -static void testknnunit_unsetknn(knnmodel* model, ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix xy; - knnbuilder builder; - knnreport rep; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&builder, 0, sizeof(builder)); - memset(&rep, 0, sizeof(rep)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _knnbuilder_init(&builder, _state, ae_true); - _knnreport_init(&rep, _state, ae_true); - - ae_matrix_set_length(&xy, 1, 2, _state); - xy.ptr.pp_double[0][0] = (double)(0); - xy.ptr.pp_double[0][1] = ae_randomreal(_state)-0.5; - knnbuildercreate(&builder, _state); - knnbuildersetdatasetreg(&builder, &xy, 1, 1, 1, _state); - knnbuilderbuildknnmodel(&builder, 1, (double)(0), model, &rep, _state); - model->nvars = -1; - model->nout = -1; - model->k = -1; - model->eps = (double)(0); - model->isdummy = ae_true; - ae_frame_leave(_state); -} - - -/************************************************************************* -Test set errors. - -Computes test set errors: -* average cross-entropy -* relative classification error (a range [RelCls0,RelCls1] is returned - because classification error can be computed differently in the presence - of the ties). All possible values of the classification error, no matter - how ties are resolved, are guaranteed to be within [RelCls0,RelCls1]. -*************************************************************************/ -static void testknnunit_testseterrors(knnmodel* model, - ae_int_t nvars, - ae_int_t nout, - ae_bool iscls, - /* Real */ ae_matrix* xy, - ae_int_t npoints, - double* avgce, - double* relcls0, - double* relcls1, - double* rms, - double* avg, - double* avgrel, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector x; - ae_vector y; - ae_vector ey; - ae_int_t relcnt; - ae_int_t i; - ae_int_t j; - double v; - double mxy; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&ey, 0, sizeof(ey)); - *avgce = 0; - *relcls0 = 0; - *relcls1 = 0; - *rms = 0; - *avg = 0; - *avgrel = 0; - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ey, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&x, nvars, _state); - ae_vector_set_length(&y, nout, _state); - ae_vector_set_length(&ey, nout, _state); - *avgce = (double)(0); - *relcls0 = (double)(0); - *relcls1 = (double)(0); - *rms = (double)(0); - *avg = (double)(0); - *avgrel = (double)(0); - relcnt = 0; - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nvars-1; j++) - { - x.ptr.p_double[j] = xy->ptr.pp_double[i][j]; - } - knnprocess(model, &x, &y, _state); - if( iscls ) - { - for(j=0; j<=nout-1; j++) - { - ey.ptr.p_double[j] = (double)(0); - } - ey.ptr.p_double[ae_round(xy->ptr.pp_double[i][nvars], _state)] = (double)(1); - } - else - { - for(j=0; j<=nout-1; j++) - { - ey.ptr.p_double[j] = xy->ptr.pp_double[i][nvars+j]; - } - } - for(j=0; j<=nout-1; j++) - { - v = y.ptr.p_double[j]-ey.ptr.p_double[j]; - if( iscls ) - { - *avgce = *avgce-ey.ptr.p_double[j]*ae_log(y.ptr.p_double[j]+ae_minrealnumber, _state); - } - *rms = *rms+ae_sqr(v, _state); - *avg = *avg+ae_fabs(v, _state); - if( ae_fp_neq(ey.ptr.p_double[j],(double)(0)) ) - { - *avgrel = *avgrel+ae_fabs(v/ey.ptr.p_double[j], _state); - relcnt = relcnt+1; - } - } - if( iscls ) - { - mxy = (double)(0); - for(j=0; j<=nout-1; j++) - { - mxy = ae_maxreal(mxy, y.ptr.p_double[j], _state); - } - if( ae_fp_eq(y.ptr.p_double[ae_round(xy->ptr.pp_double[i][nvars], _state)],mxy) ) - { - - /* - * RelCls0 is NOT increased because correct value achieves maximum. - * However, if ties are present, we have to increase RelCls1, upper bound - * of the uncertainty interval for the classification error. - */ - for(j=0; j<=nout-1; j++) - { - if( j!=ae_round(xy->ptr.pp_double[i][nvars], _state)&&ae_fp_eq(y.ptr.p_double[j],mxy) ) - { - *relcls1 = *relcls1+1; - break; - } - } - } - else - { - - /* - * Both bounds of the error range are increased by 1 - */ - *relcls0 = *relcls0+1; - *relcls1 = *relcls1+1; - } - } - } - *relcls0 = *relcls0/npoints; - *relcls1 = *relcls1/npoints; - *avgce = *avgce/npoints; - *rms = ae_sqrt(*rms/(npoints*nout), _state); - *avg = *avg/(npoints*nout); - *avgrel = *avgrel/coalesce((double)(relcnt), (double)(1), _state); - ae_frame_leave(_state); -} - - - -static double testgqunit_mapkind(ae_int_t k, ae_state *_state); -static void testgqunit_buildgausslegendrequadrature(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state); -static void testgqunit_buildgaussjacobiquadrature(ae_int_t n, - double alpha, - double beta, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state); -static void testgqunit_buildgausslaguerrequadrature(ae_int_t n, - double alpha, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state); -static void testgqunit_buildgausshermitequadrature(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state); - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testgq(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_vector alpha; - ae_vector beta; - ae_vector x; - ae_vector w; - ae_vector x2; - ae_vector w2; - double err; - ae_int_t n; - ae_int_t i; - ae_int_t info; - ae_int_t akind; - ae_int_t bkind; - double alphac; - double betac; - double errtol; - double nonstricterrtol; - double stricterrtol; - ae_bool recerrors; - ae_bool specerrors; - ae_bool waserrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&alpha, 0, sizeof(alpha)); - memset(&beta, 0, sizeof(beta)); - memset(&x, 0, sizeof(x)); - memset(&w, 0, sizeof(w)); - memset(&x2, 0, sizeof(x2)); - memset(&w2, 0, sizeof(w2)); - ae_vector_init(&alpha, 0, DT_REAL, _state, ae_true); - ae_vector_init(&beta, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w2, 0, DT_REAL, _state, ae_true); - - recerrors = ae_false; - specerrors = ae_false; - waserrors = ae_false; - errtol = 1.0E-12; - nonstricterrtol = 1.0E-6; - stricterrtol = 1000*ae_machineepsilon; - - /* - * Three tests for rec-based Gauss quadratures with known weights/nodes: - * 1. Gauss-Legendre with N=2 - * 2. Gauss-Legendre with N=5 - * 3. Gauss-Chebyshev with N=1, 2, 4, 8, ..., 512 - */ - err = (double)(0); - ae_vector_set_length(&alpha, 2, _state); - ae_vector_set_length(&beta, 2, _state); - alpha.ptr.p_double[0] = (double)(0); - alpha.ptr.p_double[1] = (double)(0); - beta.ptr.p_double[1] = (double)1/(double)(4*1*1-1); - gqgeneraterec(&alpha, &beta, 2.0, 2, &info, &x, &w, _state); - if( info>0 ) - { - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[0]+ae_sqrt((double)(3), _state)/3, _state), _state); - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[1]-ae_sqrt((double)(3), _state)/3, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[0]-1, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[1]-1, _state), _state); - for(i=0; i<=0; i++) - { - recerrors = recerrors||ae_fp_greater_eq(x.ptr.p_double[i],x.ptr.p_double[i+1]); - } - } - else - { - recerrors = ae_true; - } - ae_vector_set_length(&alpha, 5, _state); - ae_vector_set_length(&beta, 5, _state); - alpha.ptr.p_double[0] = (double)(0); - for(i=1; i<=4; i++) - { - alpha.ptr.p_double[i] = (double)(0); - beta.ptr.p_double[i] = ae_sqr((double)(i), _state)/(4*ae_sqr((double)(i), _state)-1); - } - gqgeneraterec(&alpha, &beta, 2.0, 5, &info, &x, &w, _state); - if( info>0 ) - { - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[0]+ae_sqrt(245+14*ae_sqrt((double)(70), _state), _state)/21, _state), _state); - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[0]+x.ptr.p_double[4], _state), _state); - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[1]+ae_sqrt(245-14*ae_sqrt((double)(70), _state), _state)/21, _state), _state); - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[1]+x.ptr.p_double[3], _state), _state); - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[2], _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[0]-(322-13*ae_sqrt((double)(70), _state))/900, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[0]-w.ptr.p_double[4], _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[1]-(322+13*ae_sqrt((double)(70), _state))/900, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[1]-w.ptr.p_double[3], _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[2]-(double)128/(double)225, _state), _state); - for(i=0; i<=3; i++) - { - recerrors = recerrors||ae_fp_greater_eq(x.ptr.p_double[i],x.ptr.p_double[i+1]); - } - } - else - { - recerrors = ae_true; - } - n = 1; - while(n<=512) - { - ae_vector_set_length(&alpha, n, _state); - ae_vector_set_length(&beta, n, _state); - for(i=0; i<=n-1; i++) - { - alpha.ptr.p_double[i] = (double)(0); - if( i==0 ) - { - beta.ptr.p_double[i] = (double)(0); - } - if( i==1 ) - { - beta.ptr.p_double[i] = (double)1/(double)2; - } - if( i>1 ) - { - beta.ptr.p_double[i] = (double)1/(double)4; - } - } - gqgeneraterec(&alpha, &beta, ae_pi, n, &info, &x, &w, _state); - if( info>0 ) - { - for(i=0; i<=n-1; i++) - { - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[i]-ae_cos(ae_pi*(n-i-0.5)/n, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[i]-ae_pi/n, _state), _state); - } - for(i=0; i<=n-2; i++) - { - recerrors = recerrors||ae_fp_greater_eq(x.ptr.p_double[i],x.ptr.p_double[i+1]); - } - } - else - { - recerrors = ae_true; - } - n = n*2; - } - recerrors = recerrors||ae_fp_greater(err,errtol); - - /* - * Three tests for rec-based Gauss-Lobatto quadratures with known weights/nodes: - * 1. Gauss-Lobatto with N=3 - * 2. Gauss-Lobatto with N=4 - * 3. Gauss-Lobatto with N=6 - */ - err = (double)(0); - ae_vector_set_length(&alpha, 2, _state); - ae_vector_set_length(&beta, 2, _state); - alpha.ptr.p_double[0] = (double)(0); - alpha.ptr.p_double[1] = (double)(0); - beta.ptr.p_double[0] = (double)(0); - beta.ptr.p_double[1] = (double)(1*1)/(double)(4*1*1-1); - gqgenerategausslobattorec(&alpha, &beta, 2.0, (double)(-1), (double)(1), 3, &info, &x, &w, _state); - if( info>0 ) - { - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[0]+1, _state), _state); - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[1], _state), _state); - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[2]-1, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[0]-(double)1/(double)3, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[1]-(double)4/(double)3, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[2]-(double)1/(double)3, _state), _state); - for(i=0; i<=1; i++) - { - recerrors = recerrors||ae_fp_greater_eq(x.ptr.p_double[i],x.ptr.p_double[i+1]); - } - } - else - { - recerrors = ae_true; - } - ae_vector_set_length(&alpha, 3, _state); - ae_vector_set_length(&beta, 3, _state); - alpha.ptr.p_double[0] = (double)(0); - alpha.ptr.p_double[1] = (double)(0); - alpha.ptr.p_double[2] = (double)(0); - beta.ptr.p_double[0] = (double)(0); - beta.ptr.p_double[1] = (double)(1*1)/(double)(4*1*1-1); - beta.ptr.p_double[2] = (double)(2*2)/(double)(4*2*2-1); - gqgenerategausslobattorec(&alpha, &beta, 2.0, (double)(-1), (double)(1), 4, &info, &x, &w, _state); - if( info>0 ) - { - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[0]+1, _state), _state); - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[1]+ae_sqrt((double)(5), _state)/5, _state), _state); - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[2]-ae_sqrt((double)(5), _state)/5, _state), _state); - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[3]-1, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[0]-(double)1/(double)6, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[1]-(double)5/(double)6, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[2]-(double)5/(double)6, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[3]-(double)1/(double)6, _state), _state); - for(i=0; i<=2; i++) - { - recerrors = recerrors||ae_fp_greater_eq(x.ptr.p_double[i],x.ptr.p_double[i+1]); - } - } - else - { - recerrors = ae_true; - } - ae_vector_set_length(&alpha, 5, _state); - ae_vector_set_length(&beta, 5, _state); - alpha.ptr.p_double[0] = (double)(0); - alpha.ptr.p_double[1] = (double)(0); - alpha.ptr.p_double[2] = (double)(0); - alpha.ptr.p_double[3] = (double)(0); - alpha.ptr.p_double[4] = (double)(0); - beta.ptr.p_double[0] = (double)(0); - beta.ptr.p_double[1] = (double)(1*1)/(double)(4*1*1-1); - beta.ptr.p_double[2] = (double)(2*2)/(double)(4*2*2-1); - beta.ptr.p_double[3] = (double)(3*3)/(double)(4*3*3-1); - beta.ptr.p_double[4] = (double)(4*4)/(double)(4*4*4-1); - gqgenerategausslobattorec(&alpha, &beta, 2.0, (double)(-1), (double)(1), 6, &info, &x, &w, _state); - if( info>0 ) - { - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[0]+1, _state), _state); - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[1]+ae_sqrt((7+2*ae_sqrt((double)(7), _state))/21, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[2]+ae_sqrt((7-2*ae_sqrt((double)(7), _state))/21, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[3]-ae_sqrt((7-2*ae_sqrt((double)(7), _state))/21, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[4]-ae_sqrt((7+2*ae_sqrt((double)(7), _state))/21, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[5]-1, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[0]-(double)1/(double)15, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[1]-(14-ae_sqrt((double)(7), _state))/30, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[2]-(14+ae_sqrt((double)(7), _state))/30, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[3]-(14+ae_sqrt((double)(7), _state))/30, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[4]-(14-ae_sqrt((double)(7), _state))/30, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[5]-(double)1/(double)15, _state), _state); - for(i=0; i<=4; i++) - { - recerrors = recerrors||ae_fp_greater_eq(x.ptr.p_double[i],x.ptr.p_double[i+1]); - } - } - else - { - recerrors = ae_true; - } - recerrors = recerrors||ae_fp_greater(err,errtol); - - /* - * Three tests for rec-based Gauss-Radau quadratures with known weights/nodes: - * 1. Gauss-Radau with N=2 - * 2. Gauss-Radau with N=3 - * 3. Gauss-Radau with N=3 (another case) - */ - err = (double)(0); - ae_vector_set_length(&alpha, 1, _state); - ae_vector_set_length(&beta, 2, _state); - alpha.ptr.p_double[0] = (double)(0); - beta.ptr.p_double[0] = (double)(0); - beta.ptr.p_double[1] = (double)(1*1)/(double)(4*1*1-1); - gqgenerategaussradaurec(&alpha, &beta, 2.0, (double)(-1), 2, &info, &x, &w, _state); - if( info>0 ) - { - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[0]+1, _state), _state); - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[1]-(double)1/(double)3, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[0]-0.5, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[1]-1.5, _state), _state); - for(i=0; i<=0; i++) - { - recerrors = recerrors||ae_fp_greater_eq(x.ptr.p_double[i],x.ptr.p_double[i+1]); - } - } - else - { - recerrors = ae_true; - } - ae_vector_set_length(&alpha, 2, _state); - ae_vector_set_length(&beta, 3, _state); - alpha.ptr.p_double[0] = (double)(0); - alpha.ptr.p_double[1] = (double)(0); - for(i=0; i<=2; i++) - { - beta.ptr.p_double[i] = ae_sqr((double)(i), _state)/(4*ae_sqr((double)(i), _state)-1); - } - gqgenerategaussradaurec(&alpha, &beta, 2.0, (double)(-1), 3, &info, &x, &w, _state); - if( info>0 ) - { - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[0]+1, _state), _state); - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[1]-(1-ae_sqrt((double)(6), _state))/5, _state), _state); - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[2]-(1+ae_sqrt((double)(6), _state))/5, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[0]-(double)2/(double)9, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[1]-(16+ae_sqrt((double)(6), _state))/18, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[2]-(16-ae_sqrt((double)(6), _state))/18, _state), _state); - for(i=0; i<=1; i++) - { - recerrors = recerrors||ae_fp_greater_eq(x.ptr.p_double[i],x.ptr.p_double[i+1]); - } - } - else - { - recerrors = ae_true; - } - ae_vector_set_length(&alpha, 2, _state); - ae_vector_set_length(&beta, 3, _state); - alpha.ptr.p_double[0] = (double)(0); - alpha.ptr.p_double[1] = (double)(0); - for(i=0; i<=2; i++) - { - beta.ptr.p_double[i] = ae_sqr((double)(i), _state)/(4*ae_sqr((double)(i), _state)-1); - } - gqgenerategaussradaurec(&alpha, &beta, 2.0, (double)(1), 3, &info, &x, &w, _state); - if( info>0 ) - { - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[2]-1, _state), _state); - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[1]+(1-ae_sqrt((double)(6), _state))/5, _state), _state); - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[0]+(1+ae_sqrt((double)(6), _state))/5, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[2]-(double)2/(double)9, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[1]-(16+ae_sqrt((double)(6), _state))/18, _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[0]-(16-ae_sqrt((double)(6), _state))/18, _state), _state); - for(i=0; i<=1; i++) - { - recerrors = recerrors||ae_fp_greater_eq(x.ptr.p_double[i],x.ptr.p_double[i+1]); - } - } - else - { - recerrors = ae_true; - } - recerrors = recerrors||ae_fp_greater(err,errtol); - - /* - * test recurrence-based special cases (Legendre, Jacobi, Hermite, ...) - * against another implementation (polynomial root-finder) - */ - for(n=1; n<=20; n++) - { - - /* - * test gauss-legendre - */ - err = (double)(0); - gqgenerategausslegendre(n, &info, &x, &w, _state); - if( info>0 ) - { - testgqunit_buildgausslegendrequadrature(n, &x2, &w2, _state); - for(i=0; i<=n-1; i++) - { - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[i]-x2.ptr.p_double[i], _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[i]-w2.ptr.p_double[i], _state), _state); - } - } - else - { - specerrors = ae_true; - } - specerrors = specerrors||ae_fp_greater(err,errtol); - - /* - * Test Gauss-Jacobi. - * Since task is much more difficult we will use less strict - * threshold. - */ - err = (double)(0); - for(akind=0; akind<=9; akind++) - { - for(bkind=0; bkind<=9; bkind++) - { - alphac = testgqunit_mapkind(akind, _state); - betac = testgqunit_mapkind(bkind, _state); - gqgenerategaussjacobi(n, alphac, betac, &info, &x, &w, _state); - if( info>0 ) - { - testgqunit_buildgaussjacobiquadrature(n, alphac, betac, &x2, &w2, _state); - for(i=0; i<=n-1; i++) - { - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[i]-x2.ptr.p_double[i], _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[i]-w2.ptr.p_double[i], _state), _state); - } - } - else - { - specerrors = ae_true; - } - } - } - specerrors = specerrors||ae_fp_greater(err,nonstricterrtol); - - /* - * special test for Gauss-Jacobi (Chebyshev weight - * function with analytically known nodes/weights) - */ - err = (double)(0); - gqgenerategaussjacobi(n, -0.5, -0.5, &info, &x, &w, _state); - if( info>0 ) - { - for(i=0; i<=n-1; i++) - { - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[i]+ae_cos(ae_pi*(i+0.5)/n, _state), _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[i]-ae_pi/n, _state), _state); - } - } - else - { - specerrors = ae_true; - } - specerrors = specerrors||ae_fp_greater(err,stricterrtol); - - /* - * Test Gauss-Laguerre - */ - err = (double)(0); - for(akind=0; akind<=9; akind++) - { - alphac = testgqunit_mapkind(akind, _state); - gqgenerategausslaguerre(n, alphac, &info, &x, &w, _state); - if( info>0 ) - { - testgqunit_buildgausslaguerrequadrature(n, alphac, &x2, &w2, _state); - for(i=0; i<=n-1; i++) - { - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[i]-x2.ptr.p_double[i], _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[i]-w2.ptr.p_double[i], _state), _state); - } - } - else - { - specerrors = ae_true; - } - } - specerrors = specerrors||ae_fp_greater(err,nonstricterrtol); - - /* - * Test Gauss-Hermite - */ - err = (double)(0); - gqgenerategausshermite(n, &info, &x, &w, _state); - if( info>0 ) - { - testgqunit_buildgausshermitequadrature(n, &x2, &w2, _state); - for(i=0; i<=n-1; i++) - { - err = ae_maxreal(err, ae_fabs(x.ptr.p_double[i]-x2.ptr.p_double[i], _state), _state); - err = ae_maxreal(err, ae_fabs(w.ptr.p_double[i]-w2.ptr.p_double[i], _state), _state); - } - } - else - { - specerrors = ae_true; - } - specerrors = specerrors||ae_fp_greater(err,nonstricterrtol); - } - - /* - * end - */ - waserrors = recerrors||specerrors; - if( !silent ) - { - printf("TESTING GAUSS QUADRATURES\n"); - printf("FINAL RESULT: "); - if( waserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* SPECIAL CASES (LEGENDRE/JACOBI/..) "); - if( specerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* RECURRENCE-BASED: "); - if( recerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Maps: - 0 => -0.9 - 1 => -0.5 - 2 => -0.1 - 3 => 0.0 - 4 => +0.1 - 5 => +0.5 - 6 => +0.9 - 7 => +1.0 - 8 => +1.5 - 9 => +2.0 -*************************************************************************/ -static double testgqunit_mapkind(ae_int_t k, ae_state *_state) -{ - double result; - - - result = (double)(0); - if( k==0 ) - { - result = -0.9; - } - if( k==1 ) - { - result = -0.5; - } - if( k==2 ) - { - result = -0.1; - } - if( k==3 ) - { - result = 0.0; - } - if( k==4 ) - { - result = 0.1; - } - if( k==5 ) - { - result = 0.5; - } - if( k==6 ) - { - result = 0.9; - } - if( k==7 ) - { - result = 1.0; - } - if( k==8 ) - { - result = 1.5; - } - if( k==9 ) - { - result = 2.0; - } - return result; -} - - -/************************************************************************* -Gauss-Legendre, another variant -*************************************************************************/ -static void testgqunit_buildgausslegendrequadrature(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double r; - double r1; - double p1; - double p2; - double p3; - double dp3; - double tmp; - - ae_vector_clear(x); - ae_vector_clear(w); - - ae_vector_set_length(x, n-1+1, _state); - ae_vector_set_length(w, n-1+1, _state); - for(i=0; i<=(n+1)/2-1; i++) - { - r = ae_cos(ae_pi*(4*i+3)/(4*n+2), _state); - do - { - p2 = (double)(0); - p3 = (double)(1); - for(j=0; j<=n-1; j++) - { - p1 = p2; - p2 = p3; - p3 = ((2*j+1)*r*p2-j*p1)/(j+1); - } - dp3 = n*(r*p3-p2)/(r*r-1); - r1 = r; - r = r-p3/dp3; - } - while(ae_fp_greater_eq(ae_fabs(r-r1, _state),ae_machineepsilon*(1+ae_fabs(r, _state))*100)); - x->ptr.p_double[i] = r; - x->ptr.p_double[n-1-i] = -r; - w->ptr.p_double[i] = 2/((1-r*r)*dp3*dp3); - w->ptr.p_double[n-1-i] = 2/((1-r*r)*dp3*dp3); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-2-i; j++) - { - if( ae_fp_greater_eq(x->ptr.p_double[j],x->ptr.p_double[j+1]) ) - { - tmp = x->ptr.p_double[j]; - x->ptr.p_double[j] = x->ptr.p_double[j+1]; - x->ptr.p_double[j+1] = tmp; - tmp = w->ptr.p_double[j]; - w->ptr.p_double[j] = w->ptr.p_double[j+1]; - w->ptr.p_double[j+1] = tmp; - } - } - } -} - - -/************************************************************************* -Gauss-Jacobi, another variant -*************************************************************************/ -static void testgqunit_buildgaussjacobiquadrature(ae_int_t n, - double alpha, - double beta, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double r; - double r1; - double t1; - double t2; - double t3; - double p1; - double p2; - double p3; - double pp; - double an; - double bn; - double a; - double b; - double c; - double tmpsgn; - double tmp; - double alfbet; - double temp; - - ae_vector_clear(x); - ae_vector_clear(w); - - ae_vector_set_length(x, n-1+1, _state); - ae_vector_set_length(w, n-1+1, _state); - r = (double)(0); - for(i=0; i<=n-1; i++) - { - if( i==0 ) - { - an = alpha/n; - bn = beta/n; - t1 = (1+alpha)*(2.78/(4+n*n)+0.768*an/n); - t2 = 1+1.48*an+0.96*bn+0.452*an*an+0.83*an*bn; - r = (t2-t1)/t2; - } - else - { - if( i==1 ) - { - t1 = (4.1+alpha)/((1+alpha)*(1+0.156*alpha)); - t2 = 1+0.06*(n-8)*(1+0.12*alpha)/n; - t3 = 1+0.012*beta*(1+0.25*ae_fabs(alpha, _state))/n; - r = r-t1*t2*t3*(1-r); - } - else - { - if( i==2 ) - { - t1 = (1.67+0.28*alpha)/(1+0.37*alpha); - t2 = 1+0.22*(n-8)/n; - t3 = 1+8*beta/((6.28+beta)*n*n); - r = r-t1*t2*t3*(x->ptr.p_double[0]-r); - } - else - { - if( iptr.p_double[i-1]-3*x->ptr.p_double[i-2]+x->ptr.p_double[i-3]; - } - else - { - if( i==n-2 ) - { - t1 = (1+0.235*beta)/(0.766+0.119*beta); - t2 = 1/(1+0.639*(n-4)/(1+0.71*(n-4))); - t3 = 1/(1+20*alpha/((7.5+alpha)*n*n)); - r = r+t1*t2*t3*(r-x->ptr.p_double[i-2]); - } - else - { - if( i==n-1 ) - { - t1 = (1+0.37*beta)/(1.67+0.28*beta); - t2 = 1/(1+0.22*(n-8)/n); - t3 = 1/(1+8*alpha/((6.28+alpha)*n*n)); - r = r+t1*t2*t3*(r-x->ptr.p_double[i-2]); - } - } - } - } - } - } - alfbet = alpha+beta; - do - { - temp = 2+alfbet; - p1 = (alpha-beta+temp*r)*0.5; - p2 = (double)(1); - for(j=2; j<=n; j++) - { - p3 = p2; - p2 = p1; - temp = 2*j+alfbet; - a = 2*j*(j+alfbet)*(temp-2); - b = (temp-1)*(alpha*alpha-beta*beta+temp*(temp-2)*r); - c = 2*(j-1+alpha)*(j-1+beta)*temp; - p1 = (b*p2-c*p3)/a; - } - pp = (n*(alpha-beta-temp*r)*p1+2*(n+alpha)*(n+beta)*p2)/(temp*(1-r*r)); - r1 = r; - r = r1-p1/pp; - } - while(ae_fp_greater_eq(ae_fabs(r-r1, _state),ae_machineepsilon*(1+ae_fabs(r, _state))*100)); - x->ptr.p_double[i] = r; - w->ptr.p_double[i] = ae_exp(lngamma(alpha+n, &tmpsgn, _state)+lngamma(beta+n, &tmpsgn, _state)-lngamma((double)(n+1), &tmpsgn, _state)-lngamma(n+alfbet+1, &tmpsgn, _state), _state)*temp*ae_pow((double)(2), alfbet, _state)/(pp*p2); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-2-i; j++) - { - if( ae_fp_greater_eq(x->ptr.p_double[j],x->ptr.p_double[j+1]) ) - { - tmp = x->ptr.p_double[j]; - x->ptr.p_double[j] = x->ptr.p_double[j+1]; - x->ptr.p_double[j+1] = tmp; - tmp = w->ptr.p_double[j]; - w->ptr.p_double[j] = w->ptr.p_double[j+1]; - w->ptr.p_double[j+1] = tmp; - } - } - } -} - - -/************************************************************************* -Gauss-Laguerre, another variant -*************************************************************************/ -static void testgqunit_buildgausslaguerrequadrature(ae_int_t n, - double alpha, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double r; - double r1; - double p1; - double p2; - double p3; - double dp3; - double tsg; - double tmp; - - ae_vector_clear(x); - ae_vector_clear(w); - - ae_vector_set_length(x, n-1+1, _state); - ae_vector_set_length(w, n-1+1, _state); - r = (double)(0); - for(i=0; i<=n-1; i++) - { - if( i==0 ) - { - r = (1+alpha)*(3+0.92*alpha)/(1+2.4*n+1.8*alpha); - } - else - { - if( i==1 ) - { - r = r+(15+6.25*alpha)/(1+0.9*alpha+2.5*n); - } - else - { - r = r+((1+2.55*(i-1))/(1.9*(i-1))+1.26*(i-1)*alpha/(1+3.5*(i-1)))/(1+0.3*alpha)*(r-x->ptr.p_double[i-2]); - } - } - do - { - p2 = (double)(0); - p3 = (double)(1); - for(j=0; j<=n-1; j++) - { - p1 = p2; - p2 = p3; - p3 = ((-r+2*j+alpha+1)*p2-(j+alpha)*p1)/(j+1); - } - dp3 = (n*p3-(n+alpha)*p2)/r; - r1 = r; - r = r-p3/dp3; - } - while(ae_fp_greater_eq(ae_fabs(r-r1, _state),ae_machineepsilon*(1+ae_fabs(r, _state))*100)); - x->ptr.p_double[i] = r; - w->ptr.p_double[i] = -ae_exp(lngamma(alpha+n, &tsg, _state)-lngamma((double)(n), &tsg, _state), _state)/(dp3*n*p2); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-2-i; j++) - { - if( ae_fp_greater_eq(x->ptr.p_double[j],x->ptr.p_double[j+1]) ) - { - tmp = x->ptr.p_double[j]; - x->ptr.p_double[j] = x->ptr.p_double[j+1]; - x->ptr.p_double[j+1] = tmp; - tmp = w->ptr.p_double[j]; - w->ptr.p_double[j] = w->ptr.p_double[j+1]; - w->ptr.p_double[j+1] = tmp; - } - } - } -} - - -/************************************************************************* -Gauss-Hermite, another variant -*************************************************************************/ -static void testgqunit_buildgausshermitequadrature(ae_int_t n, - /* Real */ ae_vector* x, - /* Real */ ae_vector* w, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double r; - double r1; - double p1; - double p2; - double p3; - double dp3; - double pipm4; - double tmp; - - ae_vector_clear(x); - ae_vector_clear(w); - - ae_vector_set_length(x, n-1+1, _state); - ae_vector_set_length(w, n-1+1, _state); - pipm4 = ae_pow(ae_pi, -0.25, _state); - r = (double)(0); - for(i=0; i<=(n+1)/2-1; i++) - { - if( i==0 ) - { - r = ae_sqrt((double)(2*n+1), _state)-1.85575*ae_pow((double)(2*n+1), -(double)1/(double)6, _state); - } - else - { - if( i==1 ) - { - r = r-1.14*ae_pow((double)(n), 0.426, _state)/r; - } - else - { - if( i==2 ) - { - r = 1.86*r-0.86*x->ptr.p_double[0]; - } - else - { - if( i==3 ) - { - r = 1.91*r-0.91*x->ptr.p_double[1]; - } - else - { - r = 2*r-x->ptr.p_double[i-2]; - } - } - } - } - do - { - p2 = (double)(0); - p3 = pipm4; - for(j=0; j<=n-1; j++) - { - p1 = p2; - p2 = p3; - p3 = p2*r*ae_sqrt((double)2/(double)(j+1), _state)-p1*ae_sqrt((double)j/(double)(j+1), _state); - } - dp3 = ae_sqrt((double)(2*j), _state)*p2; - r1 = r; - r = r-p3/dp3; - } - while(ae_fp_greater_eq(ae_fabs(r-r1, _state),ae_machineepsilon*(1+ae_fabs(r, _state))*100)); - x->ptr.p_double[i] = r; - w->ptr.p_double[i] = 2/(dp3*dp3); - x->ptr.p_double[n-1-i] = -x->ptr.p_double[i]; - w->ptr.p_double[n-1-i] = w->ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-2-i; j++) - { - if( ae_fp_greater_eq(x->ptr.p_double[j],x->ptr.p_double[j+1]) ) - { - tmp = x->ptr.p_double[j]; - x->ptr.p_double[j] = x->ptr.p_double[j+1]; - x->ptr.p_double[j+1] = tmp; - tmp = w->ptr.p_double[j]; - w->ptr.p_double[j] = w->ptr.p_double[j+1]; - w->ptr.p_double[j+1] = tmp; - } - } - } -} - - - -static double testgkqunit_mapkind(ae_int_t k, ae_state *_state); - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testgkq(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t pkind; - double errtol; - double eps; - ae_int_t n; - ae_int_t i; - ae_int_t k; - ae_int_t info; - double err; - ae_int_t akind; - ae_int_t bkind; - double alphac; - double betac; - ae_vector x1; - ae_vector wg1; - ae_vector wk1; - ae_vector x2; - ae_vector wg2; - ae_vector wk2; - ae_int_t info1; - ae_int_t info2; - ae_bool successatleastonce; - ae_bool intblerrors; - ae_bool vstblerrors; - ae_bool generrors; - ae_bool waserrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&x1, 0, sizeof(x1)); - memset(&wg1, 0, sizeof(wg1)); - memset(&wk1, 0, sizeof(wk1)); - memset(&x2, 0, sizeof(x2)); - memset(&wg2, 0, sizeof(wg2)); - memset(&wk2, 0, sizeof(wk2)); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wg1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wk1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wg2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&wk2, 0, DT_REAL, _state, ae_true); - - intblerrors = ae_false; - vstblerrors = ae_false; - generrors = ae_false; - waserrors = ae_false; - errtol = 10000*ae_machineepsilon; - - /* - * test recurrence-based Legendre nodes against the precalculated table - */ - for(pkind=0; pkind<=5; pkind++) - { - n = 0; - if( pkind==0 ) - { - n = 15; - } - if( pkind==1 ) - { - n = 21; - } - if( pkind==2 ) - { - n = 31; - } - if( pkind==3 ) - { - n = 41; - } - if( pkind==4 ) - { - n = 51; - } - if( pkind==5 ) - { - n = 61; - } - gkqlegendrecalc(n, &info, &x1, &wk1, &wg1, _state); - gkqlegendretbl(n, &x2, &wk2, &wg2, &eps, _state); - if( info<=0 ) - { - generrors = ae_true; - break; - } - for(i=0; i<=n-1; i++) - { - vstblerrors = vstblerrors||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-x2.ptr.p_double[i], _state),errtol); - vstblerrors = vstblerrors||ae_fp_greater(ae_fabs(wk1.ptr.p_double[i]-wk2.ptr.p_double[i], _state),errtol); - vstblerrors = vstblerrors||ae_fp_greater(ae_fabs(wg1.ptr.p_double[i]-wg2.ptr.p_double[i], _state),errtol); - } - } - - /* - * Test recurrence-baced Gauss-Kronrod nodes against Gauss-only nodes - * calculated with subroutines from GQ unit. - */ - for(k=1; k<=30; k++) - { - n = 2*k+1; - - /* - * Gauss-Legendre - */ - err = (double)(0); - gkqgenerategausslegendre(n, &info1, &x1, &wk1, &wg1, _state); - gqgenerategausslegendre(k, &info2, &x2, &wg2, _state); - if( info1>0&&info2>0 ) - { - for(i=0; i<=k-1; i++) - { - err = ae_maxreal(err, ae_fabs(x1.ptr.p_double[2*i+1]-x2.ptr.p_double[i], _state), _state); - err = ae_maxreal(err, ae_fabs(wg1.ptr.p_double[2*i+1]-wg2.ptr.p_double[i], _state), _state); - } - } - else - { - generrors = ae_true; - } - generrors = generrors||ae_fp_greater(err,errtol); - } - for(k=1; k<=15; k++) - { - n = 2*k+1; - - /* - * Gauss-Jacobi - */ - successatleastonce = ae_false; - err = (double)(0); - for(akind=0; akind<=9; akind++) - { - for(bkind=0; bkind<=9; bkind++) - { - alphac = testgkqunit_mapkind(akind, _state); - betac = testgkqunit_mapkind(bkind, _state); - gkqgenerategaussjacobi(n, alphac, betac, &info1, &x1, &wk1, &wg1, _state); - gqgenerategaussjacobi(k, alphac, betac, &info2, &x2, &wg2, _state); - if( info1>0&&info2>0 ) - { - successatleastonce = ae_true; - for(i=0; i<=k-1; i++) - { - err = ae_maxreal(err, ae_fabs(x1.ptr.p_double[2*i+1]-x2.ptr.p_double[i], _state), _state); - err = ae_maxreal(err, ae_fabs(wg1.ptr.p_double[2*i+1]-wg2.ptr.p_double[i], _state), _state); - } - } - else - { - generrors = generrors||info1!=-5; - } - } - } - generrors = (generrors||ae_fp_greater(err,errtol))||!successatleastonce; - } - - /* - * end - */ - waserrors = (intblerrors||vstblerrors)||generrors; - if( !silent ) - { - printf("TESTING GAUSS-KRONROD QUADRATURES\n"); - printf("FINAL RESULT: "); - if( waserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* PRE-CALCULATED TABLE: "); - if( intblerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* CALCULATED AGAINST THE TABLE: "); - if( vstblerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* GENERAL PROPERTIES: "); - if( generrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Maps: - 0 => -0.9 - 1 => -0.5 - 2 => -0.1 - 3 => 0.0 - 4 => +0.1 - 5 => +0.5 - 6 => +0.9 - 7 => +1.0 - 8 => +1.5 - 9 => +2.0 -*************************************************************************/ -static double testgkqunit_mapkind(ae_int_t k, ae_state *_state) -{ - double result; - - - result = (double)(0); - if( k==0 ) - { - result = -0.9; - } - if( k==1 ) - { - result = -0.5; - } - if( k==2 ) - { - result = -0.1; - } - if( k==3 ) - { - result = 0.0; - } - if( k==4 ) - { - result = 0.1; - } - if( k==5 ) - { - result = 0.5; - } - if( k==6 ) - { - result = 0.9; - } - if( k==7 ) - { - result = 1.0; - } - if( k==8 ) - { - result = 1.5; - } - if( k==9 ) - { - result = 2.0; - } - return result; -} - - - - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testautogk(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - double a; - double b; - autogkstate state; - autogkreport rep; - double v; - double exact; - double eabs; - double alpha; - ae_int_t pkind; - double errtol; - ae_bool simpleerrors; - ae_bool sngenderrors; - ae_bool waserrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - _autogkstate_init(&state, _state, ae_true); - _autogkreport_init(&rep, _state, ae_true); - - simpleerrors = ae_false; - sngenderrors = ae_false; - waserrors = ae_false; - errtol = 10000*ae_machineepsilon; - - /* - * Simple test: integral(exp(x),+-1,+-2), no maximum width requirements - */ - a = (2*ae_randominteger(2, _state)-1)*1.0; - b = (2*ae_randominteger(2, _state)-1)*2.0; - autogksmooth(a, b, &state, _state); - while(autogkiteration(&state, _state)) - { - state.f = ae_exp(state.x, _state); - } - autogkresults(&state, &v, &rep, _state); - exact = ae_exp(b, _state)-ae_exp(a, _state); - eabs = ae_fabs(ae_exp(b, _state)-ae_exp(a, _state), _state); - if( rep.terminationtype<=0 ) - { - simpleerrors = ae_true; - } - else - { - simpleerrors = simpleerrors||ae_fp_greater(ae_fabs(exact-v, _state),errtol*eabs); - } - - /* - * Simple test: integral(exp(x),+-1,+-2), XWidth=0.1 - */ - a = (2*ae_randominteger(2, _state)-1)*1.0; - b = (2*ae_randominteger(2, _state)-1)*2.0; - autogksmoothw(a, b, 0.1, &state, _state); - while(autogkiteration(&state, _state)) - { - state.f = ae_exp(state.x, _state); - } - autogkresults(&state, &v, &rep, _state); - exact = ae_exp(b, _state)-ae_exp(a, _state); - eabs = ae_fabs(ae_exp(b, _state)-ae_exp(a, _state), _state); - if( rep.terminationtype<=0 ) - { - simpleerrors = ae_true; - } - else - { - simpleerrors = simpleerrors||ae_fp_greater(ae_fabs(exact-v, _state),errtol*eabs); - } - - /* - * Simple test: integral(cos(100*x),0,2*pi), no maximum width requirements - */ - a = (double)(0); - b = 2*ae_pi; - autogksmooth(a, b, &state, _state); - while(autogkiteration(&state, _state)) - { - state.f = ae_cos(100*state.x, _state); - } - autogkresults(&state, &v, &rep, _state); - exact = (double)(0); - eabs = (double)(4); - if( rep.terminationtype<=0 ) - { - simpleerrors = ae_true; - } - else - { - simpleerrors = simpleerrors||ae_fp_greater(ae_fabs(exact-v, _state),errtol*eabs); - } - - /* - * Simple test: integral(cos(100*x),0,2*pi), XWidth=0.3 - */ - a = (double)(0); - b = 2*ae_pi; - autogksmoothw(a, b, 0.3, &state, _state); - while(autogkiteration(&state, _state)) - { - state.f = ae_cos(100*state.x, _state); - } - autogkresults(&state, &v, &rep, _state); - exact = (double)(0); - eabs = (double)(4); - if( rep.terminationtype<=0 ) - { - simpleerrors = ae_true; - } - else - { - simpleerrors = simpleerrors||ae_fp_greater(ae_fabs(exact-v, _state),errtol*eabs); - } - - /* - * singular problem on [a,b] = [0.1, 0.5] - * f2(x) = (1+x)*(b-x)^alpha, -1 < alpha < 1 - */ - for(pkind=0; pkind<=6; pkind++) - { - a = 0.1; - b = 0.5; - alpha = 0.0; - if( pkind==0 ) - { - alpha = -0.9; - } - if( pkind==1 ) - { - alpha = -0.5; - } - if( pkind==2 ) - { - alpha = -0.1; - } - if( pkind==3 ) - { - alpha = 0.0; - } - if( pkind==4 ) - { - alpha = 0.1; - } - if( pkind==5 ) - { - alpha = 0.5; - } - if( pkind==6 ) - { - alpha = 0.9; - } - - /* - * f1(x) = (1+x)*(x-a)^alpha, -1 < alpha < 1 - * 1. use singular integrator for [a,b] - * 2. use singular integrator for [b,a] - */ - exact = ae_pow(b-a, alpha+2, _state)/(alpha+2)+(1+a)*ae_pow(b-a, alpha+1, _state)/(alpha+1); - eabs = ae_fabs(exact, _state); - autogksingular(a, b, alpha, 0.0, &state, _state); - while(autogkiteration(&state, _state)) - { - if( ae_fp_less(state.xminusa,0.01) ) - { - state.f = ae_pow(state.xminusa, alpha, _state)*(1+state.x); - } - else - { - state.f = ae_pow(state.x-a, alpha, _state)*(1+state.x); - } - } - autogkresults(&state, &v, &rep, _state); - if( rep.terminationtype<=0 ) - { - sngenderrors = ae_true; - } - else - { - sngenderrors = sngenderrors||ae_fp_greater(ae_fabs(v-exact, _state),errtol*eabs); - } - autogksingular(b, a, 0.0, alpha, &state, _state); - while(autogkiteration(&state, _state)) - { - if( ae_fp_greater(state.bminusx,-0.01) ) - { - state.f = ae_pow(-state.bminusx, alpha, _state)*(1+state.x); - } - else - { - state.f = ae_pow(state.x-a, alpha, _state)*(1+state.x); - } - } - autogkresults(&state, &v, &rep, _state); - if( rep.terminationtype<=0 ) - { - sngenderrors = ae_true; - } - else - { - sngenderrors = sngenderrors||ae_fp_greater(ae_fabs(-v-exact, _state),errtol*eabs); - } - - /* - * f1(x) = (1+x)*(b-x)^alpha, -1 < alpha < 1 - * 1. use singular integrator for [a,b] - * 2. use singular integrator for [b,a] - */ - exact = (1+b)*ae_pow(b-a, alpha+1, _state)/(alpha+1)-ae_pow(b-a, alpha+2, _state)/(alpha+2); - eabs = ae_fabs(exact, _state); - autogksingular(a, b, 0.0, alpha, &state, _state); - while(autogkiteration(&state, _state)) - { - if( ae_fp_less(state.bminusx,0.01) ) - { - state.f = ae_pow(state.bminusx, alpha, _state)*(1+state.x); - } - else - { - state.f = ae_pow(b-state.x, alpha, _state)*(1+state.x); - } - } - autogkresults(&state, &v, &rep, _state); - if( rep.terminationtype<=0 ) - { - sngenderrors = ae_true; - } - else - { - sngenderrors = sngenderrors||ae_fp_greater(ae_fabs(v-exact, _state),errtol*eabs); - } - autogksingular(b, a, alpha, 0.0, &state, _state); - while(autogkiteration(&state, _state)) - { - if( ae_fp_greater(state.xminusa,-0.01) ) - { - state.f = ae_pow(-state.xminusa, alpha, _state)*(1+state.x); - } - else - { - state.f = ae_pow(b-state.x, alpha, _state)*(1+state.x); - } - } - autogkresults(&state, &v, &rep, _state); - if( rep.terminationtype<=0 ) - { - sngenderrors = ae_true; - } - else - { - sngenderrors = sngenderrors||ae_fp_greater(ae_fabs(-v-exact, _state),errtol*eabs); - } - } - - /* - * end - */ - waserrors = simpleerrors||sngenderrors; - if( !silent ) - { - printf("TESTING AUTOGK\n"); - printf("INTEGRATION WITH GIVEN ACCURACY: "); - if( simpleerrors||sngenderrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* SIMPLE PROBLEMS: "); - if( simpleerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* SINGULAR PROBLEMS (ENDS OF INTERVAL): "); - if( sngenderrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - - -static void testfftunit_reffftc1d(/* Complex */ ae_vector* a, - ae_int_t n, - ae_state *_state); -static void testfftunit_reffftc1dinv(/* Complex */ ae_vector* a, - ae_int_t n, - ae_state *_state); -static void testfftunit_refinternalcfft(/* Real */ ae_vector* a, - ae_int_t nn, - ae_bool inversefft, - ae_state *_state); -static void testfftunit_refinternalrfft(/* Real */ ae_vector* a, - ae_int_t nn, - /* Complex */ ae_vector* f, - ae_state *_state); -static void testfftunit_quicktest(ae_int_t n, - double* referr, - double* refrerr, - ae_state *_state); - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testfft(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t i; - ae_int_t k; - ae_vector a1; - ae_vector a2; - ae_vector a3; - ae_vector r1; - ae_vector r2; - ae_vector buf; - fasttransformplan plan; - ae_int_t maxsmalln; - double bidierr; - double bidirerr; - double referr; - double refrerr; - double reinterr; - double errtol; - ae_bool referrors; - ae_bool bidierrors; - ae_bool refrerrors; - ae_bool bidirerrors; - ae_bool reinterrors; - ae_bool waserrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a1, 0, sizeof(a1)); - memset(&a2, 0, sizeof(a2)); - memset(&a3, 0, sizeof(a3)); - memset(&r1, 0, sizeof(r1)); - memset(&r2, 0, sizeof(r2)); - memset(&buf, 0, sizeof(buf)); - memset(&plan, 0, sizeof(plan)); - ae_vector_init(&a1, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&a2, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&a3, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&r1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&r2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&buf, 0, DT_REAL, _state, ae_true); - _fasttransformplan_init(&plan, _state, ae_true); - - maxsmalln = 128; - errtol = 100000*ae_pow((double)(maxsmalln), (double)3/(double)2, _state)*ae_machineepsilon; - bidierrors = ae_false; - referrors = ae_false; - bidirerrors = ae_false; - refrerrors = ae_false; - reinterrors = ae_false; - waserrors = ae_false; - - /* - * Test bi-directional error: norm(x-invFFT(FFT(x))) - */ - bidierr = (double)(0); - bidirerr = (double)(0); - for(n=1; n<=maxsmalln; n++) - { - - /* - * Complex FFT/invFFT - */ - ae_vector_set_length(&a1, n, _state); - ae_vector_set_length(&a2, n, _state); - ae_vector_set_length(&a3, n, _state); - for(i=0; i<=n-1; i++) - { - a1.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1; - a1.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1; - a2.ptr.p_complex[i] = a1.ptr.p_complex[i]; - a3.ptr.p_complex[i] = a1.ptr.p_complex[i]; - } - fftc1d(&a2, n, _state); - fftc1dinv(&a2, n, _state); - fftc1dinv(&a3, n, _state); - fftc1d(&a3, n, _state); - for(i=0; i<=n-1; i++) - { - bidierr = ae_maxreal(bidierr, ae_c_abs(ae_c_sub(a1.ptr.p_complex[i],a2.ptr.p_complex[i]), _state), _state); - bidierr = ae_maxreal(bidierr, ae_c_abs(ae_c_sub(a1.ptr.p_complex[i],a3.ptr.p_complex[i]), _state), _state); - } - - /* - * Real - */ - ae_vector_set_length(&r1, n, _state); - ae_vector_set_length(&r2, n, _state); - for(i=0; i<=n-1; i++) - { - r1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - r2.ptr.p_double[i] = r1.ptr.p_double[i]; - } - fftr1d(&r2, n, &a1, _state); - ae_v_muld(&r2.ptr.p_double[0], 1, ae_v_len(0,n-1), 0); - fftr1dinv(&a1, n, &r2, _state); - for(i=0; i<=n-1; i++) - { - bidirerr = ae_maxreal(bidirerr, ae_c_abs(ae_complex_from_d(r1.ptr.p_double[i]-r2.ptr.p_double[i]), _state), _state); - } - } - bidierrors = bidierrors||ae_fp_greater(bidierr,errtol); - bidirerrors = bidirerrors||ae_fp_greater(bidirerr,errtol); - - /* - * Test against reference O(N^2) implementation for small N's - * (we do not test large N's because reference implementation will be too slow). - */ - referr = (double)(0); - refrerr = (double)(0); - for(n=1; n<=maxsmalln; n++) - { - - /* - * Complex FFT - */ - ae_vector_set_length(&a1, n, _state); - ae_vector_set_length(&a2, n, _state); - for(i=0; i<=n-1; i++) - { - a1.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1; - a1.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1; - a2.ptr.p_complex[i] = a1.ptr.p_complex[i]; - } - fftc1d(&a1, n, _state); - testfftunit_reffftc1d(&a2, n, _state); - for(i=0; i<=n-1; i++) - { - referr = ae_maxreal(referr, ae_c_abs(ae_c_sub(a1.ptr.p_complex[i],a2.ptr.p_complex[i]), _state), _state); - } - - /* - * Complex inverse FFT - */ - ae_vector_set_length(&a1, n, _state); - ae_vector_set_length(&a2, n, _state); - for(i=0; i<=n-1; i++) - { - a1.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1; - a1.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1; - a2.ptr.p_complex[i] = a1.ptr.p_complex[i]; - } - fftc1dinv(&a1, n, _state); - testfftunit_reffftc1dinv(&a2, n, _state); - for(i=0; i<=n-1; i++) - { - referr = ae_maxreal(referr, ae_c_abs(ae_c_sub(a1.ptr.p_complex[i],a2.ptr.p_complex[i]), _state), _state); - } - - /* - * Real forward/inverse FFT: - * * calculate and check forward FFT - * * use precalculated FFT to check backward FFT - * fill unused parts of frequencies array with random numbers - * to ensure that they are not really used - */ - ae_vector_set_length(&r1, n, _state); - ae_vector_set_length(&r2, n, _state); - for(i=0; i<=n-1; i++) - { - r1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - r2.ptr.p_double[i] = r1.ptr.p_double[i]; - } - fftr1d(&r1, n, &a1, _state); - testfftunit_refinternalrfft(&r2, n, &a2, _state); - for(i=0; i<=n-1; i++) - { - refrerr = ae_maxreal(refrerr, ae_c_abs(ae_c_sub(a1.ptr.p_complex[i],a2.ptr.p_complex[i]), _state), _state); - } - ae_vector_set_length(&a3, ae_ifloor((double)n/(double)2, _state)+1, _state); - for(i=0; i<=ae_ifloor((double)n/(double)2, _state); i++) - { - a3.ptr.p_complex[i] = a2.ptr.p_complex[i]; - } - a3.ptr.p_complex[0].y = 2*ae_randomreal(_state)-1; - if( n%2==0 ) - { - a3.ptr.p_complex[ae_ifloor((double)n/(double)2, _state)].y = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=n-1; i++) - { - r1.ptr.p_double[i] = (double)(0); - } - fftr1dinv(&a3, n, &r1, _state); - for(i=0; i<=n-1; i++) - { - refrerr = ae_maxreal(refrerr, ae_fabs(r2.ptr.p_double[i]-r1.ptr.p_double[i], _state), _state); - } - } - referrors = referrors||ae_fp_greater(referr,errtol); - refrerrors = refrerrors||ae_fp_greater(refrerr,errtol); - - /* - * Test for large N's: - * * we perform FFT - * * we selectively calculate K (small number) of DFT components (using reference formula) - * and compare them with ones calculated by fast implementation - * * K components to test are chosen at random (random sampling with possible repetitions) - * * overall complexity of the test is O(N*logN+K*N) - * Several N's are tested, with different kinds of factorizations - */ - referr = (double)(0); - refrerr = (double)(0); - testfftunit_quicktest(1000, &referr, &refrerr, _state); - testfftunit_quicktest(1024, &referr, &refrerr, _state); - testfftunit_quicktest(1025, &referr, &refrerr, _state); - testfftunit_quicktest(2000, &referr, &refrerr, _state); - testfftunit_quicktest(2048, &referr, &refrerr, _state); - testfftunit_quicktest(6535, &referr, &refrerr, _state); - testfftunit_quicktest(65536, &referr, &refrerr, _state); - testfftunit_quicktest(104729, &referr, &refrerr, _state); - testfftunit_quicktest(139129, &referr, &refrerr, _state); - testfftunit_quicktest(141740, &referr, &refrerr, _state); - referrors = referrors||ae_fp_greater(referr,errtol); - refrerrors = refrerrors||ae_fp_greater(refrerr,errtol); - - /* - * test internal real even FFT - */ - reinterr = (double)(0); - for(k=1; k<=maxsmalln/2; k++) - { - n = 2*k; - - /* - * Real forward FFT - */ - ae_vector_set_length(&r1, n, _state); - ae_vector_set_length(&r2, n, _state); - for(i=0; i<=n-1; i++) - { - r1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - r2.ptr.p_double[i] = r1.ptr.p_double[i]; - } - ftcomplexfftplan(n/2, 1, &plan, _state); - ae_vector_set_length(&buf, n, _state); - fftr1dinternaleven(&r1, n, &buf, &plan, _state); - testfftunit_refinternalrfft(&r2, n, &a2, _state); - reinterr = ae_maxreal(reinterr, ae_fabs(r1.ptr.p_double[0]-a2.ptr.p_complex[0].x, _state), _state); - reinterr = ae_maxreal(reinterr, ae_fabs(r1.ptr.p_double[1]-a2.ptr.p_complex[n/2].x, _state), _state); - for(i=1; i<=n/2-1; i++) - { - reinterr = ae_maxreal(reinterr, ae_fabs(r1.ptr.p_double[2*i+0]-a2.ptr.p_complex[i].x, _state), _state); - reinterr = ae_maxreal(reinterr, ae_fabs(r1.ptr.p_double[2*i+1]-a2.ptr.p_complex[i].y, _state), _state); - } - - /* - * Real backward FFT - */ - ae_vector_set_length(&r1, n, _state); - for(i=0; i<=n-1; i++) - { - r1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - ae_vector_set_length(&a2, ae_ifloor((double)n/(double)2, _state)+1, _state); - a2.ptr.p_complex[0] = ae_complex_from_d(r1.ptr.p_double[0]); - for(i=1; i<=ae_ifloor((double)n/(double)2, _state)-1; i++) - { - a2.ptr.p_complex[i].x = r1.ptr.p_double[2*i+0]; - a2.ptr.p_complex[i].y = r1.ptr.p_double[2*i+1]; - } - a2.ptr.p_complex[ae_ifloor((double)n/(double)2, _state)] = ae_complex_from_d(r1.ptr.p_double[1]); - ftcomplexfftplan(n/2, 1, &plan, _state); - ae_vector_set_length(&buf, n, _state); - fftr1dinvinternaleven(&r1, n, &buf, &plan, _state); - fftr1dinv(&a2, n, &r2, _state); - for(i=0; i<=n-1; i++) - { - reinterr = ae_maxreal(reinterr, ae_fabs(r1.ptr.p_double[i]-r2.ptr.p_double[i], _state), _state); - } - } - reinterrors = reinterrors||ae_fp_greater(reinterr,errtol); - - /* - * end - */ - waserrors = (((bidierrors||bidirerrors)||referrors)||refrerrors)||reinterrors; - if( !silent ) - { - printf("TESTING FFT\n"); - printf("FINAL RESULT: "); - if( waserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* BI-DIRECTIONAL COMPLEX TEST: "); - if( bidierrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* AGAINST REFERENCE COMPLEX FFT: "); - if( referrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* BI-DIRECTIONAL REAL TEST: "); - if( bidirerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* AGAINST REFERENCE REAL FFT: "); - if( refrerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* INTERNAL EVEN FFT: "); - if( reinterrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Reference FFT -*************************************************************************/ -static void testfftunit_reffftc1d(/* Complex */ ae_vector* a, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector buf; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&buf, 0, sizeof(buf)); - ae_vector_init(&buf, 0, DT_REAL, _state, ae_true); - - ae_assert(n>0, "FFTC1D: incorrect N!", _state); - ae_vector_set_length(&buf, 2*n, _state); - for(i=0; i<=n-1; i++) - { - buf.ptr.p_double[2*i+0] = a->ptr.p_complex[i].x; - buf.ptr.p_double[2*i+1] = a->ptr.p_complex[i].y; - } - testfftunit_refinternalcfft(&buf, n, ae_false, _state); - for(i=0; i<=n-1; i++) - { - a->ptr.p_complex[i].x = buf.ptr.p_double[2*i+0]; - a->ptr.p_complex[i].y = buf.ptr.p_double[2*i+1]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Reference inverse FFT -*************************************************************************/ -static void testfftunit_reffftc1dinv(/* Complex */ ae_vector* a, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector buf; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&buf, 0, sizeof(buf)); - ae_vector_init(&buf, 0, DT_REAL, _state, ae_true); - - ae_assert(n>0, "FFTC1DInv: incorrect N!", _state); - ae_vector_set_length(&buf, 2*n, _state); - for(i=0; i<=n-1; i++) - { - buf.ptr.p_double[2*i+0] = a->ptr.p_complex[i].x; - buf.ptr.p_double[2*i+1] = a->ptr.p_complex[i].y; - } - testfftunit_refinternalcfft(&buf, n, ae_true, _state); - for(i=0; i<=n-1; i++) - { - a->ptr.p_complex[i].x = buf.ptr.p_double[2*i+0]; - a->ptr.p_complex[i].y = buf.ptr.p_double[2*i+1]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal complex FFT stub. -Uses straightforward formula with O(N^2) complexity. -*************************************************************************/ -static void testfftunit_refinternalcfft(/* Real */ ae_vector* a, - ae_int_t nn, - ae_bool inversefft, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector tmp; - ae_int_t i; - ae_int_t k; - double hre; - double him; - double c; - double s; - double re; - double im; - - ae_frame_make(_state, &_frame_block); - memset(&tmp, 0, sizeof(tmp)); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&tmp, 2*nn-1+1, _state); - if( !inversefft ) - { - for(i=0; i<=nn-1; i++) - { - hre = (double)(0); - him = (double)(0); - for(k=0; k<=nn-1; k++) - { - re = a->ptr.p_double[2*k]; - im = a->ptr.p_double[2*k+1]; - c = ae_cos(-2*ae_pi*k*i/nn, _state); - s = ae_sin(-2*ae_pi*k*i/nn, _state); - hre = hre+c*re-s*im; - him = him+c*im+s*re; - } - tmp.ptr.p_double[2*i] = hre; - tmp.ptr.p_double[2*i+1] = him; - } - for(i=0; i<=2*nn-1; i++) - { - a->ptr.p_double[i] = tmp.ptr.p_double[i]; - } - } - else - { - for(k=0; k<=nn-1; k++) - { - hre = (double)(0); - him = (double)(0); - for(i=0; i<=nn-1; i++) - { - re = a->ptr.p_double[2*i]; - im = a->ptr.p_double[2*i+1]; - c = ae_cos(2*ae_pi*k*i/nn, _state); - s = ae_sin(2*ae_pi*k*i/nn, _state); - hre = hre+c*re-s*im; - him = him+c*im+s*re; - } - tmp.ptr.p_double[2*k] = hre/nn; - tmp.ptr.p_double[2*k+1] = him/nn; - } - for(i=0; i<=2*nn-1; i++) - { - a->ptr.p_double[i] = tmp.ptr.p_double[i]; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Internal real FFT stub. -Uses straightforward formula with O(N^2) complexity. -*************************************************************************/ -static void testfftunit_refinternalrfft(/* Real */ ae_vector* a, - ae_int_t nn, - /* Complex */ ae_vector* f, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector tmp; - ae_int_t i; - - ae_frame_make(_state, &_frame_block); - memset(&tmp, 0, sizeof(tmp)); - ae_vector_clear(f); - ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&tmp, 2*nn-1+1, _state); - for(i=0; i<=nn-1; i++) - { - tmp.ptr.p_double[2*i] = a->ptr.p_double[i]; - tmp.ptr.p_double[2*i+1] = (double)(0); - } - testfftunit_refinternalcfft(&tmp, nn, ae_false, _state); - ae_vector_set_length(f, nn, _state); - for(i=0; i<=nn-1; i++) - { - f->ptr.p_complex[i].x = tmp.ptr.p_double[2*i+0]; - f->ptr.p_complex[i].y = tmp.ptr.p_double[2*i+1]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function performs real/complex FFT of given length on random data, -selects K random components and compares them with values calculated by -DFT definition. - -It updates RefErr and RefRErr as follows: - RefErr:= max(RefErr, error_of_complex_FFT) - RefRErr:= max(RefRErr,error_of_real_FFT) - -*************************************************************************/ -static void testfftunit_quicktest(ae_int_t n, - double* referr, - double* refrerr, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector a0; - ae_vector a1; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t idx; - ae_complex v; - double c; - double s; - double re; - double im; - - ae_frame_make(_state, &_frame_block); - memset(&a0, 0, sizeof(a0)); - memset(&a1, 0, sizeof(a1)); - ae_vector_init(&a0, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&a1, 0, DT_COMPLEX, _state, ae_true); - - k = 10; - - /* - * Complex FFT - forward and inverse - */ - ae_vector_set_length(&a0, n, _state); - ae_vector_set_length(&a1, n, _state); - for(i=0; i<=n-1; i++) - { - a0.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1; - a0.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1; - a1.ptr.p_complex[i] = a0.ptr.p_complex[i]; - } - fftc1d(&a0, n, _state); - for(i=0; i<=k-1; i++) - { - idx = ae_randominteger(n, _state); - v = ae_complex_from_i(0); - for(j=0; j<=n-1; j++) - { - re = a1.ptr.p_complex[j].x; - im = a1.ptr.p_complex[j].y; - c = ae_cos(-2*ae_pi*j*idx/n, _state); - s = ae_sin(-2*ae_pi*j*idx/n, _state); - v.x = v.x+c*re-s*im; - v.y = v.y+c*im+s*re; - } - *referr = ae_maxreal(*referr, ae_c_abs(ae_c_sub(v,a0.ptr.p_complex[idx]), _state), _state); - } - fftc1dinv(&a0, n, _state); - for(i=0; i<=n-1; i++) - { - *referr = ae_maxreal(*referr, ae_c_abs(ae_c_sub(a0.ptr.p_complex[i],a1.ptr.p_complex[i]), _state), _state); - } - ae_frame_leave(_state); -} - - - -static void testfhtunit_reffhtr1d(/* Real */ ae_vector* a, - ae_int_t n, - ae_state *_state); -static void testfhtunit_reffhtr1dinv(/* Real */ ae_vector* a, - ae_int_t n, - ae_state *_state); - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testfht(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t i; - ae_vector r1; - ae_vector r2; - ae_vector r3; - ae_int_t maxn; - double bidierr; - double referr; - double errtol; - ae_bool referrors; - ae_bool bidierrors; - ae_bool waserrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&r1, 0, sizeof(r1)); - memset(&r2, 0, sizeof(r2)); - memset(&r3, 0, sizeof(r3)); - ae_vector_init(&r1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&r2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&r3, 0, DT_REAL, _state, ae_true); - - maxn = 128; - errtol = 100000*ae_pow((double)(maxn), (double)3/(double)2, _state)*ae_machineepsilon; - bidierrors = ae_false; - referrors = ae_false; - waserrors = ae_false; - - /* - * Test bi-directional error: norm(x-invFHT(FHT(x))) - */ - bidierr = (double)(0); - for(n=1; n<=maxn; n++) - { - - /* - * FHT/invFHT - */ - ae_vector_set_length(&r1, n, _state); - ae_vector_set_length(&r2, n, _state); - ae_vector_set_length(&r3, n, _state); - for(i=0; i<=n-1; i++) - { - r1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - r2.ptr.p_double[i] = r1.ptr.p_double[i]; - r3.ptr.p_double[i] = r1.ptr.p_double[i]; - } - fhtr1d(&r2, n, _state); - fhtr1dinv(&r2, n, _state); - fhtr1dinv(&r3, n, _state); - fhtr1d(&r3, n, _state); - for(i=0; i<=n-1; i++) - { - bidierr = ae_maxreal(bidierr, ae_fabs(r1.ptr.p_double[i]-r2.ptr.p_double[i], _state), _state); - bidierr = ae_maxreal(bidierr, ae_fabs(r1.ptr.p_double[i]-r3.ptr.p_double[i], _state), _state); - } - } - bidierrors = bidierrors||ae_fp_greater(bidierr,errtol); - - /* - * Test against reference O(N^2) implementation - */ - referr = (double)(0); - for(n=1; n<=maxn; n++) - { - - /* - * FHT - */ - ae_vector_set_length(&r1, n, _state); - ae_vector_set_length(&r2, n, _state); - for(i=0; i<=n-1; i++) - { - r1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - r2.ptr.p_double[i] = r1.ptr.p_double[i]; - } - fhtr1d(&r1, n, _state); - testfhtunit_reffhtr1d(&r2, n, _state); - for(i=0; i<=n-1; i++) - { - referr = ae_maxreal(referr, ae_fabs(r1.ptr.p_double[i]-r2.ptr.p_double[i], _state), _state); - } - - /* - * inverse FHT - */ - ae_vector_set_length(&r1, n, _state); - ae_vector_set_length(&r2, n, _state); - for(i=0; i<=n-1; i++) - { - r1.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - r2.ptr.p_double[i] = r1.ptr.p_double[i]; - } - fhtr1dinv(&r1, n, _state); - testfhtunit_reffhtr1dinv(&r2, n, _state); - for(i=0; i<=n-1; i++) - { - referr = ae_maxreal(referr, ae_fabs(r1.ptr.p_double[i]-r2.ptr.p_double[i], _state), _state); - } - } - referrors = referrors||ae_fp_greater(referr,errtol); - - /* - * end - */ - waserrors = bidierrors||referrors; - if( !silent ) - { - printf("TESTING FHT\n"); - printf("FINAL RESULT: "); - if( waserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* BI-DIRECTIONAL TEST: "); - if( bidierrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* AGAINST REFERENCE FHT: "); - if( referrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Reference FHT -*************************************************************************/ -static void testfhtunit_reffhtr1d(/* Real */ ae_vector* a, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector buf; - ae_int_t i; - ae_int_t j; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&buf, 0, sizeof(buf)); - ae_vector_init(&buf, 0, DT_REAL, _state, ae_true); - - ae_assert(n>0, "RefFHTR1D: incorrect N!", _state); - ae_vector_set_length(&buf, n, _state); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+a->ptr.p_double[j]*(ae_cos(2*ae_pi*i*j/n, _state)+ae_sin(2*ae_pi*i*j/n, _state)); - } - buf.ptr.p_double[i] = v; - } - for(i=0; i<=n-1; i++) - { - a->ptr.p_double[i] = buf.ptr.p_double[i]; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Reference inverse FHT -*************************************************************************/ -static void testfhtunit_reffhtr1dinv(/* Real */ ae_vector* a, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - - - ae_assert(n>0, "RefFHTR1DInv: incorrect N!", _state); - testfhtunit_reffhtr1d(a, n, _state); - for(i=0; i<=n-1; i++) - { - a->ptr.p_double[i] = a->ptr.p_double[i]/n; - } -} - - - -static void testconvunit_refconvc1d(/* Complex */ ae_vector* a, - ae_int_t m, - /* Complex */ ae_vector* b, - ae_int_t n, - /* Complex */ ae_vector* r, - ae_state *_state); -static void testconvunit_refconvc1dcircular(/* Complex */ ae_vector* a, - ae_int_t m, - /* Complex */ ae_vector* b, - ae_int_t n, - /* Complex */ ae_vector* r, - ae_state *_state); -static void testconvunit_refconvr1d(/* Real */ ae_vector* a, - ae_int_t m, - /* Real */ ae_vector* b, - ae_int_t n, - /* Real */ ae_vector* r, - ae_state *_state); -static void testconvunit_refconvr1dcircular(/* Real */ ae_vector* a, - ae_int_t m, - /* Real */ ae_vector* b, - ae_int_t n, - /* Real */ ae_vector* r, - ae_state *_state); - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testconv(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t m; - ae_int_t n; - ae_int_t i; - ae_int_t rkind; - ae_int_t circkind; - ae_vector ra; - ae_vector rb; - ae_vector rr1; - ae_vector rr2; - ae_vector ca; - ae_vector cb; - ae_vector cr1; - ae_vector cr2; - ae_int_t maxn; - double referr; - double refrerr; - double inverr; - double invrerr; - double errtol; - ae_bool referrors; - ae_bool refrerrors; - ae_bool inverrors; - ae_bool invrerrors; - ae_bool waserrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&ra, 0, sizeof(ra)); - memset(&rb, 0, sizeof(rb)); - memset(&rr1, 0, sizeof(rr1)); - memset(&rr2, 0, sizeof(rr2)); - memset(&ca, 0, sizeof(ca)); - memset(&cb, 0, sizeof(cb)); - memset(&cr1, 0, sizeof(cr1)); - memset(&cr2, 0, sizeof(cr2)); - ae_vector_init(&ra, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rb, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rr1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rr2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ca, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&cb, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&cr1, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&cr2, 0, DT_COMPLEX, _state, ae_true); - - maxn = 32; - errtol = 100000*ae_pow((double)(maxn), (double)3/(double)2, _state)*ae_machineepsilon; - referrors = ae_false; - refrerrors = ae_false; - inverrors = ae_false; - invrerrors = ae_false; - waserrors = ae_false; - - /* - * Test against reference O(N^2) implementation. - * - * Automatic ConvC1D() and different algorithms of ConvC1DX() are tested. - */ - referr = (double)(0); - refrerr = (double)(0); - for(m=1; m<=maxn; m++) - { - for(n=1; n<=maxn; n++) - { - for(circkind=0; circkind<=1; circkind++) - { - for(rkind=-3; rkind<=1; rkind++) - { - - /* - * skip impossible combinations of parameters: - * * circular convolution, M-3 - internal subroutine does not support M=n ) - { - - /* - * test internal subroutine: - * * circular/non-circular mode - */ - convc1dx(&ca, m, &cb, n, circkind!=0, rkind, 0, &cr1, _state); - } - else - { - - /* - * test internal subroutine - circular mode only - */ - ae_assert(circkind==0, "Convolution test: internal error!", _state); - convc1dx(&cb, n, &ca, m, ae_false, rkind, 0, &cr1, _state); - } - } - if( circkind==0 ) - { - testconvunit_refconvc1d(&ca, m, &cb, n, &cr2, _state); - } - else - { - testconvunit_refconvc1dcircular(&ca, m, &cb, n, &cr2, _state); - } - if( circkind==0 ) - { - for(i=0; i<=m+n-2; i++) - { - referr = ae_maxreal(referr, ae_c_abs(ae_c_sub(cr1.ptr.p_complex[i],cr2.ptr.p_complex[i]), _state), _state); - } - } - else - { - for(i=0; i<=m-1; i++) - { - referr = ae_maxreal(referr, ae_c_abs(ae_c_sub(cr1.ptr.p_complex[i],cr2.ptr.p_complex[i]), _state), _state); - } - } - - /* - * Real convolution - */ - ae_vector_set_length(&ra, m, _state); - for(i=0; i<=m-1; i++) - { - ra.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - ae_vector_set_length(&rb, n, _state); - for(i=0; i<=n-1; i++) - { - rb.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - ae_vector_set_length(&rr1, 1, _state); - if( rkind==-3 ) - { - - /* - * test wrapper subroutine: - * * circular/non-circular - */ - if( circkind==0 ) - { - convr1d(&ra, m, &rb, n, &rr1, _state); - } - else - { - convr1dcircular(&ra, m, &rb, n, &rr1, _state); - } - } - else - { - if( m>=n ) - { - - /* - * test internal subroutine: - * * circular/non-circular mode - */ - convr1dx(&ra, m, &rb, n, circkind!=0, rkind, 0, &rr1, _state); - } - else - { - - /* - * test internal subroutine - non-circular mode only - */ - convr1dx(&rb, n, &ra, m, circkind!=0, rkind, 0, &rr1, _state); - } - } - if( circkind==0 ) - { - testconvunit_refconvr1d(&ra, m, &rb, n, &rr2, _state); - } - else - { - testconvunit_refconvr1dcircular(&ra, m, &rb, n, &rr2, _state); - } - if( circkind==0 ) - { - for(i=0; i<=m+n-2; i++) - { - refrerr = ae_maxreal(refrerr, ae_fabs(rr1.ptr.p_double[i]-rr2.ptr.p_double[i], _state), _state); - } - } - else - { - for(i=0; i<=m-1; i++) - { - refrerr = ae_maxreal(refrerr, ae_fabs(rr1.ptr.p_double[i]-rr2.ptr.p_double[i], _state), _state); - } - } - } - } - } - } - referrors = referrors||ae_fp_greater(referr,errtol); - refrerrors = refrerrors||ae_fp_greater(refrerr,errtol); - - /* - * Test inverse convolution - */ - inverr = (double)(0); - invrerr = (double)(0); - for(m=1; m<=maxn; m++) - { - for(n=1; n<=maxn; n++) - { - - /* - * Complex circilar and non-circular - */ - ae_vector_set_length(&ca, m, _state); - for(i=0; i<=m-1; i++) - { - ca.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1; - ca.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1; - } - ae_vector_set_length(&cb, n, _state); - for(i=0; i<=n-1; i++) - { - cb.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1; - cb.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1; - } - ae_vector_set_length(&cr1, 1, _state); - ae_vector_set_length(&cr2, 1, _state); - convc1d(&ca, m, &cb, n, &cr2, _state); - convc1dinv(&cr2, m+n-1, &cb, n, &cr1, _state); - for(i=0; i<=m-1; i++) - { - inverr = ae_maxreal(inverr, ae_c_abs(ae_c_sub(cr1.ptr.p_complex[i],ca.ptr.p_complex[i]), _state), _state); - } - ae_vector_set_length(&cr1, 1, _state); - ae_vector_set_length(&cr2, 1, _state); - convc1dcircular(&ca, m, &cb, n, &cr2, _state); - convc1dcircularinv(&cr2, m, &cb, n, &cr1, _state); - for(i=0; i<=m-1; i++) - { - inverr = ae_maxreal(inverr, ae_c_abs(ae_c_sub(cr1.ptr.p_complex[i],ca.ptr.p_complex[i]), _state), _state); - } - - /* - * Real circilar and non-circular - */ - ae_vector_set_length(&ra, m, _state); - for(i=0; i<=m-1; i++) - { - ra.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - ae_vector_set_length(&rb, n, _state); - for(i=0; i<=n-1; i++) - { - rb.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - ae_vector_set_length(&rr1, 1, _state); - ae_vector_set_length(&rr2, 1, _state); - convr1d(&ra, m, &rb, n, &rr2, _state); - convr1dinv(&rr2, m+n-1, &rb, n, &rr1, _state); - for(i=0; i<=m-1; i++) - { - invrerr = ae_maxreal(invrerr, ae_fabs(rr1.ptr.p_double[i]-ra.ptr.p_double[i], _state), _state); - } - ae_vector_set_length(&rr1, 1, _state); - ae_vector_set_length(&rr2, 1, _state); - convr1dcircular(&ra, m, &rb, n, &rr2, _state); - convr1dcircularinv(&rr2, m, &rb, n, &rr1, _state); - for(i=0; i<=m-1; i++) - { - invrerr = ae_maxreal(invrerr, ae_fabs(rr1.ptr.p_double[i]-ra.ptr.p_double[i], _state), _state); - } - } - } - inverrors = inverrors||ae_fp_greater(inverr,errtol); - invrerrors = invrerrors||ae_fp_greater(invrerr,errtol); - - /* - * end - */ - waserrors = ((referrors||refrerrors)||inverrors)||invrerrors; - if( !silent ) - { - printf("TESTING CONVOLUTION\n"); - printf("FINAL RESULT: "); - if( waserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* AGAINST REFERENCE COMPLEX CONV: "); - if( referrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* AGAINST REFERENCE REAL CONV: "); - if( refrerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* COMPLEX INVERSE: "); - if( inverrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* REAL INVERSE: "); - if( invrerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Reference implementation -*************************************************************************/ -static void testconvunit_refconvc1d(/* Complex */ ae_vector* a, - ae_int_t m, - /* Complex */ ae_vector* b, - ae_int_t n, - /* Complex */ ae_vector* r, - ae_state *_state) -{ - ae_int_t i; - ae_complex v; - - ae_vector_clear(r); - - ae_vector_set_length(r, m+n-1, _state); - for(i=0; i<=m+n-2; i++) - { - r->ptr.p_complex[i] = ae_complex_from_i(0); - } - for(i=0; i<=m-1; i++) - { - v = a->ptr.p_complex[i]; - ae_v_caddc(&r->ptr.p_complex[i], 1, &b->ptr.p_complex[0], 1, "N", ae_v_len(i,i+n-1), v); - } -} - - -/************************************************************************* -Reference implementation -*************************************************************************/ -static void testconvunit_refconvc1dcircular(/* Complex */ ae_vector* a, - ae_int_t m, - /* Complex */ ae_vector* b, - ae_int_t n, - /* Complex */ ae_vector* r, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i1; - ae_int_t i2; - ae_int_t j2; - ae_vector buf; - - ae_frame_make(_state, &_frame_block); - memset(&buf, 0, sizeof(buf)); - ae_vector_clear(r); - ae_vector_init(&buf, 0, DT_COMPLEX, _state, ae_true); - - testconvunit_refconvc1d(a, m, b, n, &buf, _state); - ae_vector_set_length(r, m, _state); - ae_v_cmove(&r->ptr.p_complex[0], 1, &buf.ptr.p_complex[0], 1, "N", ae_v_len(0,m-1)); - i1 = m; - while(i1<=m+n-2) - { - i2 = ae_minint(i1+m-1, m+n-2, _state); - j2 = i2-i1; - ae_v_cadd(&r->ptr.p_complex[0], 1, &buf.ptr.p_complex[i1], 1, "N", ae_v_len(0,j2)); - i1 = i1+m; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Reference FFT -*************************************************************************/ -static void testconvunit_refconvr1d(/* Real */ ae_vector* a, - ae_int_t m, - /* Real */ ae_vector* b, - ae_int_t n, - /* Real */ ae_vector* r, - ae_state *_state) -{ - ae_int_t i; - double v; - - ae_vector_clear(r); - - ae_vector_set_length(r, m+n-1, _state); - for(i=0; i<=m+n-2; i++) - { - r->ptr.p_double[i] = (double)(0); - } - for(i=0; i<=m-1; i++) - { - v = a->ptr.p_double[i]; - ae_v_addd(&r->ptr.p_double[i], 1, &b->ptr.p_double[0], 1, ae_v_len(i,i+n-1), v); - } -} - - -/************************************************************************* -Reference implementation -*************************************************************************/ -static void testconvunit_refconvr1dcircular(/* Real */ ae_vector* a, - ae_int_t m, - /* Real */ ae_vector* b, - ae_int_t n, - /* Real */ ae_vector* r, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i1; - ae_int_t i2; - ae_int_t j2; - ae_vector buf; - - ae_frame_make(_state, &_frame_block); - memset(&buf, 0, sizeof(buf)); - ae_vector_clear(r); - ae_vector_init(&buf, 0, DT_REAL, _state, ae_true); - - testconvunit_refconvr1d(a, m, b, n, &buf, _state); - ae_vector_set_length(r, m, _state); - ae_v_move(&r->ptr.p_double[0], 1, &buf.ptr.p_double[0], 1, ae_v_len(0,m-1)); - i1 = m; - while(i1<=m+n-2) - { - i2 = ae_minint(i1+m-1, m+n-2, _state); - j2 = i2-i1; - ae_v_add(&r->ptr.p_double[0], 1, &buf.ptr.p_double[i1], 1, ae_v_len(0,j2)); - i1 = i1+m; - } - ae_frame_leave(_state); -} - - - -static void testcorrunit_refcorrc1d(/* Complex */ ae_vector* signal, - ae_int_t n, - /* Complex */ ae_vector* pattern, - ae_int_t m, - /* Complex */ ae_vector* r, - ae_state *_state); -static void testcorrunit_refcorrc1dcircular(/* Complex */ ae_vector* signal, - ae_int_t n, - /* Complex */ ae_vector* pattern, - ae_int_t m, - /* Complex */ ae_vector* r, - ae_state *_state); -static void testcorrunit_refcorrr1d(/* Real */ ae_vector* signal, - ae_int_t n, - /* Real */ ae_vector* pattern, - ae_int_t m, - /* Real */ ae_vector* r, - ae_state *_state); -static void testcorrunit_refcorrr1dcircular(/* Real */ ae_vector* signal, - ae_int_t n, - /* Real */ ae_vector* pattern, - ae_int_t m, - /* Real */ ae_vector* r, - ae_state *_state); - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testcorr(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t m; - ae_int_t n; - ae_int_t i; - ae_vector ra; - ae_vector rb; - ae_vector rr1; - ae_vector rr2; - ae_vector ca; - ae_vector cb; - ae_vector cr1; - ae_vector cr2; - ae_int_t maxn; - double referr; - double refrerr; - double errtol; - ae_bool referrors; - ae_bool refrerrors; - ae_bool waserrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&ra, 0, sizeof(ra)); - memset(&rb, 0, sizeof(rb)); - memset(&rr1, 0, sizeof(rr1)); - memset(&rr2, 0, sizeof(rr2)); - memset(&ca, 0, sizeof(ca)); - memset(&cb, 0, sizeof(cb)); - memset(&cr1, 0, sizeof(cr1)); - memset(&cr2, 0, sizeof(cr2)); - ae_vector_init(&ra, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rb, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rr1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rr2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ca, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&cb, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&cr1, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&cr2, 0, DT_COMPLEX, _state, ae_true); - - maxn = 32; - errtol = 100000*ae_pow((double)(maxn), (double)3/(double)2, _state)*ae_machineepsilon; - referrors = ae_false; - refrerrors = ae_false; - waserrors = ae_false; - - /* - * Test against reference O(N^2) implementation. - */ - referr = (double)(0); - refrerr = (double)(0); - for(m=1; m<=maxn; m++) - { - for(n=1; n<=maxn; n++) - { - - /* - * Complex correlation - */ - ae_vector_set_length(&ca, m, _state); - for(i=0; i<=m-1; i++) - { - ca.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1; - ca.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1; - } - ae_vector_set_length(&cb, n, _state); - for(i=0; i<=n-1; i++) - { - cb.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1; - cb.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1; - } - ae_vector_set_length(&cr1, 1, _state); - corrc1d(&ca, m, &cb, n, &cr1, _state); - testcorrunit_refcorrc1d(&ca, m, &cb, n, &cr2, _state); - for(i=0; i<=m+n-2; i++) - { - referr = ae_maxreal(referr, ae_c_abs(ae_c_sub(cr1.ptr.p_complex[i],cr2.ptr.p_complex[i]), _state), _state); - } - ae_vector_set_length(&cr1, 1, _state); - corrc1dcircular(&ca, m, &cb, n, &cr1, _state); - testcorrunit_refcorrc1dcircular(&ca, m, &cb, n, &cr2, _state); - for(i=0; i<=m-1; i++) - { - referr = ae_maxreal(referr, ae_c_abs(ae_c_sub(cr1.ptr.p_complex[i],cr2.ptr.p_complex[i]), _state), _state); - } - - /* - * Real correlation - */ - ae_vector_set_length(&ra, m, _state); - for(i=0; i<=m-1; i++) - { - ra.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - ae_vector_set_length(&rb, n, _state); - for(i=0; i<=n-1; i++) - { - rb.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - ae_vector_set_length(&rr1, 1, _state); - corrr1d(&ra, m, &rb, n, &rr1, _state); - testcorrunit_refcorrr1d(&ra, m, &rb, n, &rr2, _state); - for(i=0; i<=m+n-2; i++) - { - refrerr = ae_maxreal(refrerr, ae_fabs(rr1.ptr.p_double[i]-rr2.ptr.p_double[i], _state), _state); - } - ae_vector_set_length(&rr1, 1, _state); - corrr1dcircular(&ra, m, &rb, n, &rr1, _state); - testcorrunit_refcorrr1dcircular(&ra, m, &rb, n, &rr2, _state); - for(i=0; i<=m-1; i++) - { - refrerr = ae_maxreal(refrerr, ae_fabs(rr1.ptr.p_double[i]-rr2.ptr.p_double[i], _state), _state); - } - } - } - referrors = referrors||ae_fp_greater(referr,errtol); - refrerrors = refrerrors||ae_fp_greater(refrerr,errtol); - - /* - * end - */ - waserrors = referrors||refrerrors; - if( !silent ) - { - printf("TESTING CORRELATION\n"); - printf("FINAL RESULT: "); - if( waserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* AGAINST REFERENCE COMPLEX CORR: "); - if( referrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* AGAINST REFERENCE REAL CORR: "); - if( refrerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Reference implementation -*************************************************************************/ -static void testcorrunit_refcorrc1d(/* Complex */ ae_vector* signal, - ae_int_t n, - /* Complex */ ae_vector* pattern, - ae_int_t m, - /* Complex */ ae_vector* r, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_complex v; - ae_vector s; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - ae_vector_clear(r); - ae_vector_init(&s, 0, DT_COMPLEX, _state, ae_true); - - ae_vector_set_length(&s, m+n-1, _state); - ae_v_cmove(&s.ptr.p_complex[0], 1, &signal->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1)); - for(i=n; i<=m+n-2; i++) - { - s.ptr.p_complex[i] = ae_complex_from_i(0); - } - ae_vector_set_length(r, m+n-1, _state); - for(i=0; i<=n-1; i++) - { - v = ae_complex_from_i(0); - for(j=0; j<=m-1; j++) - { - if( i+j>=n ) - { - break; - } - v = ae_c_add(v,ae_c_mul(ae_c_conj(pattern->ptr.p_complex[j], _state),s.ptr.p_complex[i+j])); - } - r->ptr.p_complex[i] = v; - } - for(i=1; i<=m-1; i++) - { - v = ae_complex_from_i(0); - for(j=i; j<=m-1; j++) - { - v = ae_c_add(v,ae_c_mul(ae_c_conj(pattern->ptr.p_complex[j], _state),s.ptr.p_complex[j-i])); - } - r->ptr.p_complex[m+n-1-i] = v; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Reference implementation -*************************************************************************/ -static void testcorrunit_refcorrc1dcircular(/* Complex */ ae_vector* signal, - ae_int_t n, - /* Complex */ ae_vector* pattern, - ae_int_t m, - /* Complex */ ae_vector* r, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - ae_complex v; - - ae_vector_clear(r); - - ae_vector_set_length(r, n, _state); - for(i=0; i<=n-1; i++) - { - v = ae_complex_from_i(0); - for(j=0; j<=m-1; j++) - { - v = ae_c_add(v,ae_c_mul(ae_c_conj(pattern->ptr.p_complex[j], _state),signal->ptr.p_complex[(i+j)%n])); - } - r->ptr.p_complex[i] = v; - } -} - - -/************************************************************************* -Reference implementation -*************************************************************************/ -static void testcorrunit_refcorrr1d(/* Real */ ae_vector* signal, - ae_int_t n, - /* Real */ ae_vector* pattern, - ae_int_t m, - /* Real */ ae_vector* r, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - double v; - ae_vector s; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - ae_vector_clear(r); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&s, m+n-1, _state); - ae_v_move(&s.ptr.p_double[0], 1, &signal->ptr.p_double[0], 1, ae_v_len(0,n-1)); - for(i=n; i<=m+n-2; i++) - { - s.ptr.p_double[i] = (double)(0); - } - ae_vector_set_length(r, m+n-1, _state); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=m-1; j++) - { - if( i+j>=n ) - { - break; - } - v = v+pattern->ptr.p_double[j]*s.ptr.p_double[i+j]; - } - r->ptr.p_double[i] = v; - } - for(i=1; i<=m-1; i++) - { - v = (double)(0); - for(j=i; j<=m-1; j++) - { - v = v+pattern->ptr.p_double[j]*s.ptr.p_double[-i+j]; - } - r->ptr.p_double[m+n-1-i] = v; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Reference implementation -*************************************************************************/ -static void testcorrunit_refcorrr1dcircular(/* Real */ ae_vector* signal, - ae_int_t n, - /* Real */ ae_vector* pattern, - ae_int_t m, - /* Real */ ae_vector* r, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - - ae_vector_clear(r); - - ae_vector_set_length(r, n, _state); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=m-1; j++) - { - v = v+pattern->ptr.p_double[j]*signal->ptr.p_double[(i+j)%n]; - } - r->ptr.p_double[i] = v; - } -} - - - -static void testidwunit_testcontinuity(idwmodel* model, - ae_int_t nx, - ae_int_t ny, - /* Real */ ae_vector* x0, - /* Real */ ae_vector* x1, - ae_int_t nsteps, - ae_int_t d, - ae_bool* err, - ae_state *_state); -static void testidwunit_testcommon(ae_bool* err, ae_state *_state); -static void testidwunit_testmstab(ae_bool* err, ae_state *_state); - - - - - -/************************************************************************* -Testing IDW interpolation -*************************************************************************/ -ae_bool testidw(ae_bool silent, ae_state *_state) -{ - ae_bool waserrors; - ae_bool commonerrors; - ae_bool mstaberrors; - ae_bool result; - - - commonerrors = ae_false; - mstaberrors = ae_false; - testidwunit_testcommon(&commonerrors, _state); - testidwunit_testmstab(&mstaberrors, _state); - waserrors = commonerrors||mstaberrors; - if( !silent ) - { - printf("TESTING INVERSE DISTANCE WEIGHTING\n"); - printf("* common properties "); - if( !commonerrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* MSTAB-specific tests "); - if( !mstaberrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - return result; -} - - -/************************************************************************* -Testing continuity properties: C0 (D=0) or C1 (D=1) continuity. - -Error flag is modified on failure, unchanged on success. -*************************************************************************/ -static void testidwunit_testcontinuity(idwmodel* model, - ae_int_t nx, - ae_int_t ny, - /* Real */ ae_vector* x0, - /* Real */ ae_vector* x1, - ae_int_t nsteps, - ae_int_t d, - ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t cidx; - double t; - ae_vector xc; - ae_vector yc; - ae_matrix yy; - double lc1; - double lc2; - - ae_frame_make(_state, &_frame_block); - memset(&xc, 0, sizeof(xc)); - memset(&yc, 0, sizeof(yc)); - memset(&yy, 0, sizeof(yy)); - ae_vector_init(&xc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yc, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&yy, 0, 0, DT_REAL, _state, ae_true); - - ae_assert(nsteps>=10, "TestContinuity: NSteps is too small", _state); - ae_assert(d==0||d==1, "TestContinuity: incorrect D", _state); - - /* - * Compute sequence of function values - */ - ae_vector_set_length(&xc, nx, _state); - ae_matrix_set_length(&yy, nsteps, ny, _state); - for(i=0; i<=nsteps-1; i++) - { - t = (double)i/(double)(nsteps-1); - for(j=0; j<=nx-1; j++) - { - xc.ptr.p_double[j] = x0->ptr.p_double[j]*t+x1->ptr.p_double[j]*(1-t); - } - idwcalcbuf(model, &xc, &yc, _state); - for(j=0; j<=ny-1; j++) - { - yy.ptr.pp_double[i][j] = yc.ptr.p_double[j]; - } - } - - /* - * Evaluate all differentiability levels (C0, C1) requested by user - */ - for(cidx=0; cidx<=d; cidx++) - { - - /* - * Compute Lipschitz constant for original and increased steps - */ - lc1 = (double)(0); - lc2 = (double)(0); - for(i=0; i<=nsteps-3; i++) - { - for(j=0; j<=ny-1; j++) - { - lc1 = ae_maxreal(lc1, ae_fabs(yy.ptr.pp_double[i][j]-yy.ptr.pp_double[i+1][j], _state), _state); - lc2 = ae_maxreal(lc2, ae_fabs(yy.ptr.pp_double[i][j]-yy.ptr.pp_double[i+2][j], _state)/2, _state); - } - } - ae_set_error_flag(err, ae_fp_greater(lc2,1.0E-4)&&ae_fp_greater(lc1,1.750*lc2), __FILE__, __LINE__, "testidwunit.ap:67"); - - /* - * Differentiate function, repeat one more time - */ - for(i=0; i<=nsteps-2; i++) - { - for(j=0; j<=ny-1; j++) - { - yy.ptr.pp_double[i][j] = yy.ptr.pp_double[i+1][j]-yy.ptr.pp_double[i][j]; - } - } - nsteps = nsteps-1; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Test MSTAB; Err is set to True on failure, unchanged otherwise. -*************************************************************************/ -static void testidwunit_testcommon(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t pass; - ae_int_t algotype; - ae_int_t i; - ae_int_t i0; - ae_int_t i1; - ae_int_t j; - ae_int_t k; - ae_int_t n; - ae_matrix xy; - double v; - double vv; - ae_bool initdone; - idwmodel model; - idwmodel model1; - idwbuilder builder; - idwreport rep; - idwcalcbuffer buffer; - double shepardp; - double rbase; - double tol; - double mindistinf; - double refrms; - double refavg; - double refmax; - double refr2; - double refrss; - double reftss; - ae_int_t nx; - ae_int_t ny; - hqrndstate rs; - double x0; - double x1; - double x2; - ae_int_t continuitytesting; - ae_vector x; - ae_vector xx; - ae_vector y; - ae_vector meany; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&model, 0, sizeof(model)); - memset(&model1, 0, sizeof(model1)); - memset(&builder, 0, sizeof(builder)); - memset(&rep, 0, sizeof(rep)); - memset(&buffer, 0, sizeof(buffer)); - memset(&rs, 0, sizeof(rs)); - memset(&x, 0, sizeof(x)); - memset(&xx, 0, sizeof(xx)); - memset(&y, 0, sizeof(y)); - memset(&meany, 0, sizeof(meany)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _idwmodel_init(&model, _state, ae_true); - _idwmodel_init(&model1, _state, ae_true); - _idwbuilder_init(&builder, _state, ae_true); - _idwreport_init(&rep, _state, ae_true); - _idwcalcbuffer_init(&buffer, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&meany, 0, DT_REAL, _state, ae_true); - - hqrndrandomize(&rs, _state); - tol = 1.0E-10; - mindistinf = 0.05; - - /* - * Try all algorithms - */ - for(algotype=0; algotype<=2; algotype++) - { - - /* - * Test empty dataset - */ - for(nx=1; nx<=5; nx++) - { - for(ny=1; ny<=5; ny++) - { - initdone = ae_false; - idwbuildercreate(nx, ny, &builder, _state); - if( algotype==0 ) - { - initdone = ae_true; - shepardp = 1+(nx+1)*hqrnduniformr(&rs, _state); - idwbuildersetalgotextbookshepard(&builder, shepardp, _state); - } - if( algotype==1 ) - { - initdone = ae_true; - rbase = ae_pow(2.0, 4*hqrnduniformr(&rs, _state)-2, _state); - idwbuildersetalgotextbookmodshepard(&builder, rbase, _state); - } - if( algotype==2 ) - { - initdone = ae_true; - rbase = ae_pow(2.0, 4*hqrnduniformr(&rs, _state)-2, _state); - idwbuildersetalgomstab(&builder, rbase, _state); - } - ae_assert(initdone, "TestCommon: unexpected AlgoType", _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - - /* - * Fit and store result directly into the variable - */ - idwfit(&builder, &model, &rep, _state); - } - else - { - - /* - * Fit, store result to temporary, pass through the serializer - */ - idwfit(&builder, &model1, &rep, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - idwalloc(&_local_serializer, &model1, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - idwserialize(&_local_serializer, &model1, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - idwunserialize(&_local_serializer, &model, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - } - idwcreatecalcbuffer(&model, &buffer, _state); - - /* - * Test report - */ - ae_set_error_flag(err, ae_fp_neq(rep.rmserror,(double)(0)), __FILE__, __LINE__, "testidwunit.ap:169"); - ae_set_error_flag(err, ae_fp_neq(rep.avgerror,(double)(0)), __FILE__, __LINE__, "testidwunit.ap:170"); - ae_set_error_flag(err, ae_fp_neq(rep.maxerror,(double)(0)), __FILE__, __LINE__, "testidwunit.ap:171"); - ae_set_error_flag(err, ae_fp_neq(rep.r2,(double)(1)), __FILE__, __LINE__, "testidwunit.ap:172"); - - /* - * Test simplified evaluation - */ - x0 = hqrndnormal(&rs, _state); - x1 = hqrndnormal(&rs, _state); - x2 = hqrndnormal(&rs, _state); - if( nx==1&&ny==1 ) - { - ae_set_error_flag(err, ae_fp_neq(idwcalc1(&model, x0, _state),(double)(0)), __FILE__, __LINE__, "testidwunit.ap:181"); - } - if( nx==2&&ny==1 ) - { - ae_set_error_flag(err, ae_fp_neq(idwcalc2(&model, x0, x1, _state),(double)(0)), __FILE__, __LINE__, "testidwunit.ap:183"); - } - if( nx==3&&ny==1 ) - { - ae_set_error_flag(err, ae_fp_neq(idwcalc3(&model, x0, x1, x2, _state),(double)(0)), __FILE__, __LINE__, "testidwunit.ap:185"); - } - - /* - * Test generic evaluation - */ - ae_vector_set_length(&x, nx, _state); - for(i=0; i<=nx-1; i++) - { - x.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&y, 0, _state); - idwcalc(&model, &x, &y, _state); - ae_set_error_flag(err, y.cnt!=ny, __FILE__, __LINE__, "testidwunit.ap:195"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=ny-1; i++) - { - ae_set_error_flag(err, ae_fp_neq(y.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testidwunit.ap:199"); - } - ae_vector_set_length(&y, 0, _state); - idwcalcbuf(&model, &x, &y, _state); - ae_set_error_flag(err, y.cnt!=ny, __FILE__, __LINE__, "testidwunit.ap:202"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=ny-1; i++) - { - ae_set_error_flag(err, ae_fp_neq(y.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testidwunit.ap:206"); - } - ae_vector_set_length(&y, 0, _state); - idwtscalcbuf(&model, &buffer, &x, &y, _state); - ae_set_error_flag(err, y.cnt!=ny, __FILE__, __LINE__, "testidwunit.ap:209"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=ny-1; i++) - { - ae_set_error_flag(err, ae_fp_neq(y.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testidwunit.ap:213"); - } - } - } - - /* - * Generate random dataset with distinct points, test interpolation - * properties (target function is reproduced almost exactly, the model - * is continuous) - */ - for(pass=1; pass<=20; pass++) - { - n = 1+hqrnduniformi(&rs, 25, _state); - nx = 1+hqrnduniformi(&rs, 4, _state); - ny = 1+hqrnduniformi(&rs, 4, _state); - ae_vector_set_length(&x, nx, _state); - ae_vector_set_length(&xx, nx, _state); - ae_vector_set_length(&y, ny, _state); - - /* - * Generate dataset with distinct points - */ - ae_matrix_set_length(&xy, n, nx+ny, _state); - ae_vector_set_length(&meany, ny, _state); - for(j=0; j<=ny-1; j++) - { - meany.ptr.p_double[j] = (double)(0); - } - i = 0; - while(i=0 ) - { - testidwunit_testcontinuity(&model, nx, ny, &x, &xx, 10000, continuitytesting, err, _state); - } - } - - /* - * Test evaluation at remote points - */ - ae_vector_set_length(&x, nx, _state); - for(j=0; j<=nx-1; j++) - { - x.ptr.p_double[j] = 1.0E20*(2*hqrnduniformi(&rs, 2, _state)-1); - } - idwcalc(&model, &x, &y, _state); - for(j=0; j<=ny-1; j++) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[j]-meany.ptr.p_double[j], _state),tol), __FILE__, __LINE__, "testidwunit.ap:424"); - } - } - - /* - * Generate random dataset with NONDISTINCT points, test approximation - * properties and error reports. - */ - for(pass=1; pass<=20; pass++) - { - n = 2*(1+hqrnduniformi(&rs, 10, _state)); - nx = 1+hqrnduniformi(&rs, 4, _state); - ny = 1+hqrnduniformi(&rs, 4, _state); - ae_vector_set_length(&x, nx, _state); - ae_vector_set_length(&xx, nx, _state); - ae_vector_set_length(&y, ny, _state); - ae_vector_set_length(&meany, ny, _state); - - /* - * Generate dataset with nondistinct points, each point is repeated; - * compute reference values of the error metrics - */ - ae_matrix_set_length(&xy, n, nx+ny, _state); - refrms = (double)(0); - refavg = (double)(0); - refmax = (double)(0); - refrss = (double)(0); - reftss = (double)(0); - for(j=0; j<=ny-1; j++) - { - meany.ptr.p_double[j] = (double)(0); - } - i = 0; - while(i<=n/2-1) - { - - /* - * Generate two copies of the same point - */ - for(j=0; j<=nx+ny-1; j++) - { - v = hqrndnormal(&rs, _state); - xy.ptr.pp_double[2*i+0][j] = v; - xy.ptr.pp_double[2*i+1][j] = v; - } - - /* - * Test distance between newly generated point and other ones. - * Repeat point generation if it is too close to some other point. - */ - v = ae_maxrealnumber; - for(i0=0; i0<=2*i-1; i0++) - { - vv = (double)(0); - for(j=0; j<=nx-1; j++) - { - vv = ae_maxreal(vv, ae_fabs(xy.ptr.pp_double[2*i+0][j]-xy.ptr.pp_double[i0][j], _state), _state); - } - v = ae_minreal(v, vv, _state); - } - if( ae_fp_less(v,mindistinf) ) - { - continue; - } - - /* - * Update meanY - */ - for(j=0; j<=ny-1; j++) - { - meany.ptr.p_double[j] = meany.ptr.p_double[j]+(xy.ptr.pp_double[2*i+0][nx+j]+xy.ptr.pp_double[2*i+1][nx+j])/n; - } - - /* - * Apply perturbation to the target value - */ - for(j=0; j<=ny-1; j++) - { - v = ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - xy.ptr.pp_double[2*i+0][nx+j] = xy.ptr.pp_double[2*i+0][nx+j]+v; - xy.ptr.pp_double[2*i+1][nx+j] = xy.ptr.pp_double[2*i+1][nx+j]-v; - v = ae_fabs(v, _state); - refrms = refrms+2*v*v; - refavg = refavg+2*v; - refmax = ae_maxreal(refmax, v, _state); - refrss = refrss+2*v*v; - } - - /* - * Next I - */ - i = i+1; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=ny-1; j++) - { - reftss = reftss+ae_sqr(xy.ptr.pp_double[i][nx+j]-meany.ptr.p_double[j], _state); - } - } - refrms = ae_sqrt(refrms/(n*ny), _state); - refavg = refavg/(n*ny); - refr2 = 1.0-refrss/coalesce(reftss, (double)(1), _state); - - /* - * Build IDW model - */ - initdone = ae_false; - idwbuildercreate(nx, ny, &builder, _state); - if( algotype==0 ) - { - initdone = ae_true; - shepardp = nx*(1+hqrnduniformr(&rs, _state)); - idwbuildersetalgotextbookshepard(&builder, shepardp, _state); - } - if( algotype==1 ) - { - initdone = ae_true; - rbase = ae_pow(2.0, 4*hqrnduniformr(&rs, _state)-2, _state); - idwbuildersetalgotextbookmodshepard(&builder, rbase, _state); - } - if( algotype==2 ) - { - initdone = ae_true; - rbase = ae_pow(2.0, 4*hqrnduniformr(&rs, _state)-2, _state); - idwbuildersetalgomstab(&builder, rbase, _state); - } - ae_assert(initdone, "TestCommon: unexpected AlgoType", _state); - idwbuildersetpoints(&builder, &xy, n, _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - - /* - * Fit and store result directly into the variable - */ - idwfit(&builder, &model, &rep, _state); - } - else - { - - /* - * Fit, store result to temporary, pass through the serializer - */ - idwfit(&builder, &model1, &rep, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - idwalloc(&_local_serializer, &model1, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - idwserialize(&_local_serializer, &model1, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - idwunserialize(&_local_serializer, &model, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - } - idwcreatecalcbuffer(&model, &buffer, _state); - - /* - * Test error metrics - */ - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state),tol), __FILE__, __LINE__, "testidwunit.ap:562"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state),tol), __FILE__, __LINE__, "testidwunit.ap:563"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.maxerror-refmax, _state),tol), __FILE__, __LINE__, "testidwunit.ap:564"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.r2-refr2, _state),tol), __FILE__, __LINE__, "testidwunit.ap:565"); - - /* - * Test ability to reproduce mean over non-distinct points - * - * NOTE: we do not test all evaluation functions, just IDWCalc() - */ - for(i=0; i<=n/2-1; i++) - { - for(j=0; j<=nx-1; j++) - { - x.ptr.p_double[j] = xy.ptr.pp_double[2*i+0][j]; - } - idwcalc(&model, &x, &y, _state); - for(j=0; j<=ny-1; j++) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[j]-0.5*(xy.ptr.pp_double[2*i+0][nx+j]+xy.ptr.pp_double[2*i+1][nx+j]), _state),tol), __FILE__, __LINE__, "testidwunit.ap:578"); - } - } - - /* - * Test continuity properties: - * * continuity is guaranteed for original Shepard's method, MSTAB and MSMOOTH - * * modified Shepard method does not guarantee continuity of the model, but - * we can be sure that model is continuous along line connecting two nearest - * points - */ - for(k=0; k<=1; k++) - { - i0 = hqrnduniformi(&rs, n, _state); - for(j=0; j<=nx-1; j++) - { - x.ptr.p_double[j] = xy.ptr.pp_double[i0][j]; - } - i1 = -1; - v = ae_maxrealnumber; - for(i=0; i<=n-1; i++) - { - vv = (double)(0); - for(j=0; j<=nx-1; j++) - { - vv = vv+ae_sqr(x.ptr.p_double[j]-xy.ptr.pp_double[i][j], _state); - } - if( ae_fp_less(vv,v)&&ae_fp_greater(vv,(double)(0)) ) - { - i1 = i; - for(j=0; j<=nx-1; j++) - { - xx.ptr.p_double[j] = xy.ptr.pp_double[i][j]; - } - v = vv; - } - } - if( i1<0 ) - { - i1 = hqrnduniformi(&rs, n, _state); - for(j=0; j<=nx-1; j++) - { - xx.ptr.p_double[j] = xy.ptr.pp_double[i1][j]; - } - } - continuitytesting = 1; - if( algotype==0 ) - { - continuitytesting = 0; - } - if( algotype==1 ) - { - continuitytesting = -1; - } - if( continuitytesting>=0 ) - { - testidwunit_testcontinuity(&model, nx, ny, &x, &xx, 10000, continuitytesting, err, _state); - } - } - } - - /* - * Test correct handling of the prior term - */ - n = 10; - for(pass=1; pass<=20; pass++) - { - nx = 1+hqrnduniformi(&rs, 4, _state); - ny = 1+hqrnduniformi(&rs, 4, _state); - ae_vector_set_length(&x, nx, _state); - ae_vector_set_length(&y, ny, _state); - ae_matrix_set_length(&xy, n, nx+ny, _state); - ae_vector_set_length(&meany, ny, _state); - for(j=0; j<=ny-1; j++) - { - meany.ptr.p_double[j] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - for(j=0; j<=ny-1; j++) - { - xy.ptr.pp_double[i][nx+j] = hqrndnormal(&rs, _state); - meany.ptr.p_double[j] = meany.ptr.p_double[j]+xy.ptr.pp_double[i][nx+j]/n; - } - } - initdone = ae_false; - idwbuildercreate(nx, ny, &builder, _state); - if( algotype==0 ) - { - initdone = ae_true; - shepardp = 1+(nx+1)*hqrnduniformr(&rs, _state); - idwbuildersetalgotextbookshepard(&builder, shepardp, _state); - } - if( algotype==1 ) - { - initdone = ae_true; - rbase = ae_pow(2.0, 4*hqrnduniformr(&rs, _state)-2, _state); - idwbuildersetalgotextbookmodshepard(&builder, rbase, _state); - } - if( algotype==2 ) - { - initdone = ae_true; - rbase = ae_pow(2.0, 4*hqrnduniformr(&rs, _state)-2, _state); - idwbuildersetalgomstab(&builder, rbase, _state); - } - ae_assert(initdone, "TestCommon: unexpected AlgoType (prior test)", _state); - idwbuildersetpoints(&builder, &xy, n, _state); - - /* - * Zero prior (not tested with textbook Shepard method) - */ - if( algotype!=0 ) - { - idwbuildersetzeroterm(&builder, _state); - idwfit(&builder, &model, &rep, _state); - for(j=0; j<=nx-1; j++) - { - x.ptr.p_double[j] = 1.0E20*(2*hqrnduniformi(&rs, 2, _state)-1); - } - idwcalc(&model, &x, &y, _state); - for(j=0; j<=ny-1; j++) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[j], _state),tol), __FILE__, __LINE__, "testidwunit.ap:684"); - } - } - - /* - * Mean prior - */ - idwbuildersetconstterm(&builder, _state); - idwfit(&builder, &model, &rep, _state); - for(j=0; j<=nx-1; j++) - { - x.ptr.p_double[j] = 1.0E20*(2*hqrnduniformi(&rs, 2, _state)-1); - } - idwcalc(&model, &x, &y, _state); - for(j=0; j<=ny-1; j++) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[j]-meany.ptr.p_double[j], _state),tol), __FILE__, __LINE__, "testidwunit.ap:696"); - } - - /* - * User-specified prior (not tested with textbook Shepard method) - */ - if( algotype!=0 ) - { - v = hqrndnormal(&rs, _state); - idwbuildersetuserterm(&builder, v, _state); - idwfit(&builder, &model, &rep, _state); - for(j=0; j<=nx-1; j++) - { - x.ptr.p_double[j] = 1.0E20*(2*hqrnduniformi(&rs, 2, _state)-1); - } - idwcalc(&model, &x, &y, _state); - for(j=0; j<=ny-1; j++) - { - ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[j]-v, _state),tol), __FILE__, __LINE__, "testidwunit.ap:710"); - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Test MSTAB; Err is set to True on failure, unchanged otherwise. -*************************************************************************/ -static void testidwunit_testmstab(ae_bool* err, ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix xy; - ae_int_t i; - ae_int_t n; - double v; - double vv; - double x0; - double x1; - double rbase; - idwmodel model; - idwbuilder builder; - idwreport rep; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&model, 0, sizeof(model)); - memset(&builder, 0, sizeof(builder)); - memset(&rep, 0, sizeof(rep)); - memset(&rs, 0, sizeof(rs)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _idwmodel_init(&model, _state, ae_true); - _idwbuilder_init(&builder, _state, ae_true); - _idwreport_init(&rep, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Basic test #1: nonzero derivative - * * XY = [[-1,-1],[0,0,],[1,1]] - * * RBase>=2 - * * derivative at x=0 must be positive and bigger than 0.1 - */ - ae_matrix_set_length(&xy, 3, 2, _state); - for(i=0; i<=2; i++) - { - xy.ptr.pp_double[i][0] = (double)(i-1); - xy.ptr.pp_double[i][1] = (double)(i-1); - } - idwbuildercreate(1, 1, &builder, _state); - rbase = ae_pow(2.0, 1.0+hqrnduniformr(&rs, _state), _state); - idwbuildersetalgomstab(&builder, rbase, _state); - idwbuildersetpoints(&builder, &xy, 3, _state); - idwfit(&builder, &model, &rep, _state); - v = 0.01; - ae_set_error_flag(err, ae_fp_less((idwcalc1(&model, v, _state)-idwcalc1(&model, -v, _state))/(2*v),0.1), __FILE__, __LINE__, "testidwunit.ap:758"); - - /* - * Basic test #2: good smoothness - * * 2D task, dataset is composed from 3 parallel lines - * along y=-0.1, y=0, y=+0.1, with outer lines having - * constant zero target value, inner line having constant - * target equal to 1 - * * RBase=1 is used - * * we test that function value does not change significantly - * along the line - */ - n = 100; - ae_matrix_set_length(&xy, 3*n, 3, _state); - for(i=0; i<=n-1; i++) - { - xy.ptr.pp_double[3*i+0][0] = (double)i/(double)(n-1); - xy.ptr.pp_double[3*i+0][1] = -0.1; - xy.ptr.pp_double[3*i+0][2] = (double)(0); - xy.ptr.pp_double[3*i+1][0] = (double)i/(double)(n-1); - xy.ptr.pp_double[3*i+1][1] = (double)(0); - xy.ptr.pp_double[3*i+1][2] = (double)(1); - xy.ptr.pp_double[3*i+2][0] = (double)i/(double)(n-1); - xy.ptr.pp_double[3*i+2][1] = 0.1; - xy.ptr.pp_double[3*i+2][2] = (double)(0); - } - rbase = 1.0; - idwbuildercreate(2, 1, &builder, _state); - idwbuildersetalgomstab(&builder, rbase, _state); - idwbuildersetpoints(&builder, &xy, 3*n, _state); - idwfit(&builder, &model, &rep, _state); - v = (double)(0); - for(i=0; i<=1000; i++) - { - v = ae_maxreal(v, ae_fabs(idwcalc2(&model, hqrnduniformr(&rs, _state), -0.1, _state), _state), _state); - v = ae_maxreal(v, ae_fabs(idwcalc2(&model, hqrnduniformr(&rs, _state), 0.1, _state), _state), _state); - v = ae_maxreal(v, ae_fabs(idwcalc2(&model, hqrnduniformr(&rs, _state), (double)(0), _state)-1, _state), _state); - } - ae_set_error_flag(err, ae_fp_greater(v,0.001), __FILE__, __LINE__, "testidwunit.ap:796"); - - /* - * Continuity when moving away from the dataset - */ - ae_matrix_set_length(&xy, 1, 2, _state); - xy.ptr.pp_double[0][0] = (double)(0); - xy.ptr.pp_double[0][1] = (double)(1); - rbase = 1.0; - idwbuildercreate(1, 1, &builder, _state); - idwbuildersetalgomstab(&builder, rbase, _state); - idwbuildersetpoints(&builder, &xy, 1, _state); - idwbuildersetzeroterm(&builder, _state); - idwfit(&builder, &model, &rep, _state); - ae_set_error_flag(err, ae_fp_neq(idwcalc1(&model, (double)(100000), _state),(double)(0)), __FILE__, __LINE__, "testidwunit.ap:810"); - v = (double)(0); - for(i=0; i<=500; i++) - { - x0 = 1.2*rbase*((double)i/(double)500); - x1 = 1.2*rbase*((double)(i+1)/(double)500); - v = ae_maxreal(v, ae_fabs((idwcalc1(&model, x1, _state)-idwcalc1(&model, x0, _state))/(x1-x0), _state), _state); - } - vv = (double)(0); - for(i=0; i<=1000; i++) - { - x0 = 1.2*rbase*((double)i/(double)1000); - x1 = 1.2*rbase*((double)(i+1)/(double)1000); - vv = ae_maxreal(vv, ae_fabs((idwcalc1(&model, x1, _state)-idwcalc1(&model, x0, _state))/(x1-x0), _state), _state); - } - ae_set_error_flag(err, ae_fp_greater(vv/v,1.333), __FILE__, __LINE__, "testidwunit.ap:825"); - ae_frame_leave(_state); -} - - - -static void testratintunit_poldiff2(/* Real */ ae_vector* x, - /* Real */ ae_vector* f, - ae_int_t n, - double t, - double* p, - double* dp, - double* d2p, - ae_state *_state); -static void testratintunit_brcunset(barycentricinterpolant* b, - ae_state *_state); - - - - - -ae_bool testratint(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_bool waserrors; - ae_bool bcerrors; - ae_bool nperrors; - double threshold; - double lipschitztol; - ae_int_t passcount; - barycentricinterpolant b1; - barycentricinterpolant b2; - ae_vector x; - ae_vector x2; - ae_vector y; - ae_vector y2; - ae_vector w; - ae_vector w2; - ae_vector xc; - ae_vector yc; - ae_vector dc; - double h; - double s1; - double s2; - ae_int_t n; - ae_int_t n2; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t d; - ae_int_t pass; - double maxerr; - double t; - double a; - double b; - double s; - double v0; - double v1; - double v2; - double v3; - double d0; - double d1; - double d2; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&b1, 0, sizeof(b1)); - memset(&b2, 0, sizeof(b2)); - memset(&x, 0, sizeof(x)); - memset(&x2, 0, sizeof(x2)); - memset(&y, 0, sizeof(y)); - memset(&y2, 0, sizeof(y2)); - memset(&w, 0, sizeof(w)); - memset(&w2, 0, sizeof(w2)); - memset(&xc, 0, sizeof(xc)); - memset(&yc, 0, sizeof(yc)); - memset(&dc, 0, sizeof(dc)); - _barycentricinterpolant_init(&b1, _state, ae_true); - _barycentricinterpolant_init(&b2, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dc, 0, DT_INT, _state, ae_true); - - nperrors = ae_false; - bcerrors = ae_false; - waserrors = ae_false; - - /* - * PassCount number of repeated passes - * Threshold error tolerance - * LipschitzTol Lipschitz constant increase allowed - * when calculating constant on a twice denser grid - */ - passcount = 5; - threshold = 1000000*ae_machineepsilon; - lipschitztol = 1.3; - - /* - * Basic barycentric functions - */ - for(n=1; n<=10; n++) - { - - /* - * randomized tests - */ - for(pass=1; pass<=passcount; pass++) - { - - /* - * generate weights from polynomial interpolation - */ - v0 = 1+0.4*ae_randomreal(_state)-0.2; - v1 = 2*ae_randomreal(_state)-1; - v2 = 2*ae_randomreal(_state)-1; - v3 = 2*ae_randomreal(_state)-1; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - ae_vector_set_length(&w, n, _state); - for(i=0; i<=n-1; i++) - { - if( n==1 ) - { - x.ptr.p_double[i] = (double)(0); - } - else - { - x.ptr.p_double[i] = v0*ae_cos(i*ae_pi/(n-1), _state); - } - y.ptr.p_double[i] = ae_sin(v1*x.ptr.p_double[i], _state)+ae_cos(v2*x.ptr.p_double[i], _state)+ae_exp(v3*x.ptr.p_double[i], _state); - } - for(j=0; j<=n-1; j++) - { - w.ptr.p_double[j] = (double)(1); - for(k=0; k<=n-1; k++) - { - if( k!=j ) - { - w.ptr.p_double[j] = w.ptr.p_double[j]/(x.ptr.p_double[j]-x.ptr.p_double[k]); - } - } - } - barycentricbuildxyw(&x, &y, &w, n, &b1, _state); - - /* - * unpack, then pack again and compare - */ - testratintunit_brcunset(&b2, _state); - barycentricunpack(&b1, &n2, &x2, &y2, &w2, _state); - bcerrors = bcerrors||n2!=n; - barycentricbuildxyw(&x2, &y2, &w2, n2, &b2, _state); - t = 2*ae_randomreal(_state)-1; - bcerrors = bcerrors||ae_fp_greater(ae_fabs(barycentriccalc(&b1, t, _state)-barycentriccalc(&b2, t, _state), _state),threshold); - - /* - * copy, compare - */ - testratintunit_brcunset(&b2, _state); - barycentriccopy(&b1, &b2, _state); - t = 2*ae_randomreal(_state)-1; - bcerrors = bcerrors||ae_fp_greater(ae_fabs(barycentriccalc(&b1, t, _state)-barycentriccalc(&b2, t, _state), _state),threshold); - - /* - * test interpolation properties - */ - for(i=0; i<=n-1; i++) - { - - /* - * test interpolation at nodes - */ - bcerrors = bcerrors||ae_fp_greater(ae_fabs(barycentriccalc(&b1, x.ptr.p_double[i], _state)-y.ptr.p_double[i], _state),threshold*ae_fabs(y.ptr.p_double[i], _state)); - - /* - * compare with polynomial interpolation - */ - t = 2*ae_randomreal(_state)-1; - testratintunit_poldiff2(&x, &y, n, t, &v0, &v1, &v2, _state); - bcerrors = bcerrors||ae_fp_greater(ae_fabs(barycentriccalc(&b1, t, _state)-v0, _state),threshold*ae_maxreal(ae_fabs(v0, _state), (double)(1), _state)); - - /* - * test continuity between nodes - * calculate Lipschitz constant on two grids - - * dense and even more dense. If Lipschitz constant - * on a denser grid is significantly increased, - * continuity test is failed - */ - t = 3.0; - k = 100; - s1 = (double)(0); - for(j=0; j<=k-1; j++) - { - v1 = x.ptr.p_double[i]+(t-x.ptr.p_double[i])*j/k; - v2 = x.ptr.p_double[i]+(t-x.ptr.p_double[i])*(j+1)/k; - s1 = ae_maxreal(s1, ae_fabs(barycentriccalc(&b1, v2, _state)-barycentriccalc(&b1, v1, _state), _state)/ae_fabs(v2-v1, _state), _state); - } - k = 2*k; - s2 = (double)(0); - for(j=0; j<=k-1; j++) - { - v1 = x.ptr.p_double[i]+(t-x.ptr.p_double[i])*j/k; - v2 = x.ptr.p_double[i]+(t-x.ptr.p_double[i])*(j+1)/k; - s2 = ae_maxreal(s2, ae_fabs(barycentriccalc(&b1, v2, _state)-barycentriccalc(&b1, v1, _state), _state)/ae_fabs(v2-v1, _state), _state); - } - bcerrors = bcerrors||(ae_fp_greater(s2,lipschitztol*s1)&&ae_fp_greater(s1,threshold*k)); - } - - /* - * test differentiation properties - */ - for(i=0; i<=n-1; i++) - { - t = 2*ae_randomreal(_state)-1; - testratintunit_poldiff2(&x, &y, n, t, &v0, &v1, &v2, _state); - d0 = (double)(0); - d1 = (double)(0); - d2 = (double)(0); - barycentricdiff1(&b1, t, &d0, &d1, _state); - bcerrors = bcerrors||ae_fp_greater(ae_fabs(v0-d0, _state),threshold*ae_maxreal(ae_fabs(v0, _state), (double)(1), _state)); - bcerrors = bcerrors||ae_fp_greater(ae_fabs(v1-d1, _state),threshold*ae_maxreal(ae_fabs(v1, _state), (double)(1), _state)); - d0 = (double)(0); - d1 = (double)(0); - d2 = (double)(0); - barycentricdiff2(&b1, t, &d0, &d1, &d2, _state); - bcerrors = bcerrors||ae_fp_greater(ae_fabs(v0-d0, _state),threshold*ae_maxreal(ae_fabs(v0, _state), (double)(1), _state)); - bcerrors = bcerrors||ae_fp_greater(ae_fabs(v1-d1, _state),threshold*ae_maxreal(ae_fabs(v1, _state), (double)(1), _state)); - bcerrors = bcerrors||ae_fp_greater(ae_fabs(v2-d2, _state),ae_sqrt(threshold, _state)*ae_maxreal(ae_fabs(v2, _state), (double)(1), _state)); - } - - /* - * test linear translation - */ - t = 2*ae_randomreal(_state)-1; - a = 2*ae_randomreal(_state)-1; - b = 2*ae_randomreal(_state)-1; - testratintunit_brcunset(&b2, _state); - barycentriccopy(&b1, &b2, _state); - barycentriclintransx(&b2, a, b, _state); - bcerrors = bcerrors||ae_fp_greater(ae_fabs(barycentriccalc(&b1, a*t+b, _state)-barycentriccalc(&b2, t, _state), _state),threshold); - a = (double)(0); - b = 2*ae_randomreal(_state)-1; - testratintunit_brcunset(&b2, _state); - barycentriccopy(&b1, &b2, _state); - barycentriclintransx(&b2, a, b, _state); - bcerrors = bcerrors||ae_fp_greater(ae_fabs(barycentriccalc(&b1, a*t+b, _state)-barycentriccalc(&b2, t, _state), _state),threshold); - a = 2*ae_randomreal(_state)-1; - b = 2*ae_randomreal(_state)-1; - testratintunit_brcunset(&b2, _state); - barycentriccopy(&b1, &b2, _state); - barycentriclintransy(&b2, a, b, _state); - bcerrors = bcerrors||ae_fp_greater(ae_fabs(a*barycentriccalc(&b1, t, _state)+b-barycentriccalc(&b2, t, _state), _state),threshold); - } - } - for(pass=0; pass<=3; pass++) - { - - /* - * Crash-test: small numbers, large numbers - */ - ae_vector_set_length(&x, 4, _state); - ae_vector_set_length(&y, 4, _state); - ae_vector_set_length(&w, 4, _state); - h = (double)(1); - if( pass%2==0 ) - { - h = 100*ae_minrealnumber; - } - if( pass%2==1 ) - { - h = 0.01*ae_maxrealnumber; - } - x.ptr.p_double[0] = 0*h; - x.ptr.p_double[1] = 1*h; - x.ptr.p_double[2] = 2*h; - x.ptr.p_double[3] = 3*h; - y.ptr.p_double[0] = 0*h; - y.ptr.p_double[1] = 1*h; - y.ptr.p_double[2] = 2*h; - y.ptr.p_double[3] = 3*h; - w.ptr.p_double[0] = -1/(x.ptr.p_double[1]-x.ptr.p_double[0]); - w.ptr.p_double[1] = 1*(1/(x.ptr.p_double[1]-x.ptr.p_double[0])+1/(x.ptr.p_double[2]-x.ptr.p_double[1])); - w.ptr.p_double[2] = -1*(1/(x.ptr.p_double[2]-x.ptr.p_double[1])+1/(x.ptr.p_double[3]-x.ptr.p_double[2])); - w.ptr.p_double[3] = 1/(x.ptr.p_double[3]-x.ptr.p_double[2]); - v0 = (double)(0); - if( pass/2==0 ) - { - v0 = (double)(0); - } - if( pass/2==1 ) - { - v0 = 0.6*h; - } - barycentricbuildxyw(&x, &y, &w, 4, &b1, _state); - t = barycentriccalc(&b1, v0, _state); - d0 = (double)(0); - d1 = (double)(0); - d2 = (double)(0); - barycentricdiff1(&b1, v0, &d0, &d1, _state); - bcerrors = bcerrors||ae_fp_greater(ae_fabs(t-v0, _state),threshold*v0); - bcerrors = bcerrors||ae_fp_greater(ae_fabs(d0-v0, _state),threshold*v0); - bcerrors = bcerrors||ae_fp_greater(ae_fabs(d1-1, _state),1000*threshold); - } - - /* - * crash test: large abscissas, small argument - * - * test for errors in D0 is not very strict - * because renormalization used in Diff1() - * destroys part of precision. - */ - ae_vector_set_length(&x, 4, _state); - ae_vector_set_length(&y, 4, _state); - ae_vector_set_length(&w, 4, _state); - h = 0.01*ae_maxrealnumber; - x.ptr.p_double[0] = 0*h; - x.ptr.p_double[1] = 1*h; - x.ptr.p_double[2] = 2*h; - x.ptr.p_double[3] = 3*h; - y.ptr.p_double[0] = 0*h; - y.ptr.p_double[1] = 1*h; - y.ptr.p_double[2] = 2*h; - y.ptr.p_double[3] = 3*h; - w.ptr.p_double[0] = -1/(x.ptr.p_double[1]-x.ptr.p_double[0]); - w.ptr.p_double[1] = 1*(1/(x.ptr.p_double[1]-x.ptr.p_double[0])+1/(x.ptr.p_double[2]-x.ptr.p_double[1])); - w.ptr.p_double[2] = -1*(1/(x.ptr.p_double[2]-x.ptr.p_double[1])+1/(x.ptr.p_double[3]-x.ptr.p_double[2])); - w.ptr.p_double[3] = 1/(x.ptr.p_double[3]-x.ptr.p_double[2]); - v0 = 100*ae_minrealnumber; - barycentricbuildxyw(&x, &y, &w, 4, &b1, _state); - t = barycentriccalc(&b1, v0, _state); - d0 = (double)(0); - d1 = (double)(0); - d2 = (double)(0); - barycentricdiff1(&b1, v0, &d0, &d1, _state); - bcerrors = bcerrors||ae_fp_greater(ae_fabs(t, _state),v0*(1+threshold)); - bcerrors = bcerrors||ae_fp_greater(ae_fabs(d0, _state),v0*(1+threshold)); - bcerrors = bcerrors||ae_fp_greater(ae_fabs(d1-1, _state),1000*threshold); - - /* - * crash test: test safe barycentric formula - */ - ae_vector_set_length(&x, 4, _state); - ae_vector_set_length(&y, 4, _state); - ae_vector_set_length(&w, 4, _state); - h = 2*ae_minrealnumber; - x.ptr.p_double[0] = 0*h; - x.ptr.p_double[1] = 1*h; - x.ptr.p_double[2] = 2*h; - x.ptr.p_double[3] = 3*h; - y.ptr.p_double[0] = 0*h; - y.ptr.p_double[1] = 1*h; - y.ptr.p_double[2] = 2*h; - y.ptr.p_double[3] = 3*h; - w.ptr.p_double[0] = -1/(x.ptr.p_double[1]-x.ptr.p_double[0]); - w.ptr.p_double[1] = 1*(1/(x.ptr.p_double[1]-x.ptr.p_double[0])+1/(x.ptr.p_double[2]-x.ptr.p_double[1])); - w.ptr.p_double[2] = -1*(1/(x.ptr.p_double[2]-x.ptr.p_double[1])+1/(x.ptr.p_double[3]-x.ptr.p_double[2])); - w.ptr.p_double[3] = 1/(x.ptr.p_double[3]-x.ptr.p_double[2]); - v0 = ae_minrealnumber; - barycentricbuildxyw(&x, &y, &w, 4, &b1, _state); - t = barycentriccalc(&b1, v0, _state); - bcerrors = bcerrors||ae_fp_greater(ae_fabs(t-v0, _state)/v0,threshold); - - /* - * Testing "No Poles" interpolation - */ - maxerr = (double)(0); - for(pass=1; pass<=passcount-1; pass++) - { - ae_vector_set_length(&x, 1, _state); - ae_vector_set_length(&y, 1, _state); - x.ptr.p_double[0] = 2*ae_randomreal(_state)-1; - y.ptr.p_double[0] = 2*ae_randomreal(_state)-1; - barycentricbuildfloaterhormann(&x, &y, 1, 1, &b1, _state); - maxerr = ae_maxreal(maxerr, ae_fabs(barycentriccalc(&b1, 2*ae_randomreal(_state)-1, _state)-y.ptr.p_double[0], _state), _state); - } - for(n=2; n<=10; n++) - { - - /* - * compare interpolant built by subroutine - * with interpolant built by hands - */ - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - ae_vector_set_length(&w, n, _state); - ae_vector_set_length(&w2, n, _state); - - /* - * D=1, non-equidistant nodes - */ - for(pass=1; pass<=passcount; pass++) - { - - /* - * Initialize X, Y, W - */ - a = -1-1*ae_randomreal(_state); - b = 1+1*ae_randomreal(_state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = ae_atan((b-a)*i/(n-1)+a, _state); - } - for(i=0; i<=n-1; i++) - { - y.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - w.ptr.p_double[0] = -1/(x.ptr.p_double[1]-x.ptr.p_double[0]); - s = (double)(1); - for(i=1; i<=n-2; i++) - { - w.ptr.p_double[i] = s*(1/(x.ptr.p_double[i]-x.ptr.p_double[i-1])+1/(x.ptr.p_double[i+1]-x.ptr.p_double[i])); - s = -s; - } - w.ptr.p_double[n-1] = s/(x.ptr.p_double[n-1]-x.ptr.p_double[n-2]); - for(i=0; i<=n-1; i++) - { - k = ae_randominteger(n, _state); - if( k!=i ) - { - t = x.ptr.p_double[i]; - x.ptr.p_double[i] = x.ptr.p_double[k]; - x.ptr.p_double[k] = t; - t = y.ptr.p_double[i]; - y.ptr.p_double[i] = y.ptr.p_double[k]; - y.ptr.p_double[k] = t; - t = w.ptr.p_double[i]; - w.ptr.p_double[i] = w.ptr.p_double[k]; - w.ptr.p_double[k] = t; - } - } - - /* - * Build and test - */ - barycentricbuildfloaterhormann(&x, &y, n, 1, &b1, _state); - barycentricbuildxyw(&x, &y, &w, n, &b2, _state); - for(i=1; i<=2*n; i++) - { - t = a+(b-a)*ae_randomreal(_state); - maxerr = ae_maxreal(maxerr, ae_fabs(barycentriccalc(&b1, t, _state)-barycentriccalc(&b2, t, _state), _state), _state); - } - } - - /* - * D = 0, 1, 2. Equidistant nodes. - */ - for(d=0; d<=2; d++) - { - for(pass=1; pass<=passcount; pass++) - { - - /* - * Skip incorrect (N,D) pairs - */ - if( n<2*d ) - { - continue; - } - - /* - * Initialize X, Y, W - */ - a = -1-1*ae_randomreal(_state); - b = 1+1*ae_randomreal(_state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = (b-a)*i/(n-1)+a; - } - for(i=0; i<=n-1; i++) - { - y.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - s = (double)(1); - if( d==0 ) - { - for(i=0; i<=n-1; i++) - { - w.ptr.p_double[i] = s; - s = -s; - } - } - if( d==1 ) - { - w.ptr.p_double[0] = -s; - for(i=1; i<=n-2; i++) - { - w.ptr.p_double[i] = 2*s; - s = -s; - } - w.ptr.p_double[n-1] = s; - } - if( d==2 ) - { - w.ptr.p_double[0] = s; - w.ptr.p_double[1] = -3*s; - for(i=2; i<=n-3; i++) - { - w.ptr.p_double[i] = 4*s; - s = -s; - } - w.ptr.p_double[n-2] = 3*s; - w.ptr.p_double[n-1] = -s; - } - - /* - * Mix - */ - for(i=0; i<=n-1; i++) - { - k = ae_randominteger(n, _state); - if( k!=i ) - { - t = x.ptr.p_double[i]; - x.ptr.p_double[i] = x.ptr.p_double[k]; - x.ptr.p_double[k] = t; - t = y.ptr.p_double[i]; - y.ptr.p_double[i] = y.ptr.p_double[k]; - y.ptr.p_double[k] = t; - t = w.ptr.p_double[i]; - w.ptr.p_double[i] = w.ptr.p_double[k]; - w.ptr.p_double[k] = t; - } - } - - /* - * Build and test - */ - barycentricbuildfloaterhormann(&x, &y, n, d, &b1, _state); - barycentricbuildxyw(&x, &y, &w, n, &b2, _state); - for(i=1; i<=2*n; i++) - { - t = a+(b-a)*ae_randomreal(_state); - maxerr = ae_maxreal(maxerr, ae_fabs(barycentriccalc(&b1, t, _state)-barycentriccalc(&b2, t, _state), _state), _state); - } - } - } - } - if( ae_fp_greater(maxerr,threshold) ) - { - nperrors = ae_true; - } - - /* - * report - */ - waserrors = bcerrors||nperrors; - if( !silent ) - { - printf("TESTING RATIONAL INTERPOLATION\n"); - printf("BASIC BARYCENTRIC FUNCTIONS: "); - if( bcerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("FLOATER-HORMANN: "); - if( nperrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - - /* - * end - */ - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -static void testratintunit_poldiff2(/* Real */ ae_vector* x, - /* Real */ ae_vector* f, - ae_int_t n, - double t, - double* p, - double* dp, - double* d2p, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _f; - ae_int_t m; - ae_int_t i; - ae_vector df; - ae_vector d2f; - - ae_frame_make(_state, &_frame_block); - memset(&_f, 0, sizeof(_f)); - memset(&df, 0, sizeof(df)); - memset(&d2f, 0, sizeof(d2f)); - ae_vector_init_copy(&_f, f, _state, ae_true); - f = &_f; - *p = 0; - *dp = 0; - *d2p = 0; - ae_vector_init(&df, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d2f, 0, DT_REAL, _state, ae_true); - - n = n-1; - ae_vector_set_length(&df, n+1, _state); - ae_vector_set_length(&d2f, n+1, _state); - for(i=0; i<=n; i++) - { - d2f.ptr.p_double[i] = (double)(0); - df.ptr.p_double[i] = (double)(0); - } - for(m=1; m<=n; m++) - { - for(i=0; i<=n-m; i++) - { - d2f.ptr.p_double[i] = ((t-x->ptr.p_double[i+m])*d2f.ptr.p_double[i]+(x->ptr.p_double[i]-t)*d2f.ptr.p_double[i+1]+2*df.ptr.p_double[i]-2*df.ptr.p_double[i+1])/(x->ptr.p_double[i]-x->ptr.p_double[i+m]); - df.ptr.p_double[i] = ((t-x->ptr.p_double[i+m])*df.ptr.p_double[i]+f->ptr.p_double[i]+(x->ptr.p_double[i]-t)*df.ptr.p_double[i+1]-f->ptr.p_double[i+1])/(x->ptr.p_double[i]-x->ptr.p_double[i+m]); - f->ptr.p_double[i] = ((t-x->ptr.p_double[i+m])*f->ptr.p_double[i]+(x->ptr.p_double[i]-t)*f->ptr.p_double[i+1])/(x->ptr.p_double[i]-x->ptr.p_double[i+m]); - } - } - *p = f->ptr.p_double[0]; - *dp = df.ptr.p_double[0]; - *d2p = d2f.ptr.p_double[0]; - ae_frame_leave(_state); -} - - -static void testratintunit_brcunset(barycentricinterpolant* b, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector x; - ae_vector y; - ae_vector w; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&w, 0, sizeof(w)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&x, 1, _state); - ae_vector_set_length(&y, 1, _state); - ae_vector_set_length(&w, 1, _state); - x.ptr.p_double[0] = (double)(0); - y.ptr.p_double[0] = (double)(0); - w.ptr.p_double[0] = (double)(1); - barycentricbuildxyw(&x, &y, &w, 1, b, _state); - ae_frame_leave(_state); -} - - - -static void testfitsphereunit_testspherefittingls(ae_bool* err, - ae_state *_state); -static void testfitsphereunit_testspherefittingns(ae_bool* err, - ae_state *_state); -static void testfitsphereunit_testspherefittingvosswinkel2(ae_bool* err, - ae_state *_state); -static void testfitsphereunit_calcradii(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - /* Real */ ae_vector* cx, - double* rlo, - double* rhi, - ae_state *_state); -static void testfitsphereunit_calclserror(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - /* Real */ ae_vector* cx, - double* err, - ae_state *_state); -static void testfitsphereunit_addvalue(/* Real */ ae_matrix* xy, - ae_int_t* cnt, - double v, - ae_state *_state); - - - - - -ae_bool testfitsphere(ae_bool silent, ae_state *_state) -{ - ae_bool nserrors; - ae_bool lserrors; - ae_bool wereerrors; - ae_bool result; - - - nserrors = ae_false; - lserrors = ae_false; - - /* - * Sphere fitting, several different test suites - */ - testfitsphereunit_testspherefittingls(&lserrors, _state); - testfitsphereunit_testspherefittingns(&nserrors, _state); - testfitsphereunit_testspherefittingvosswinkel2(&nserrors, _state); - - /* - * report - */ - wereerrors = nserrors||lserrors; - if( !silent ) - { - printf("TESTING FITSPHERE\n"); - printf("* LEAST SQUARES CIRCLE FITTING "); - if( lserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* NON-SMOOTH FITTING (MC, MI, MZ) "); - if( nserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( wereerrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !wereerrors; - return result; -} - - -/************************************************************************* -This function tests least squares (LS) sphere fitting using generic -synthetic datasets - -On failure sets Err to True (leaves it unchanged otherwise) -*************************************************************************/ -static void testfitsphereunit_testspherefittingls(ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - hqrndstate rs; - ae_matrix xy; - double xtol; - ae_int_t npoints; - ae_int_t nx; - ae_vector cx; - ae_vector cy; - double rlo; - double rhi; - double ftol; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double vv; - double v0; - double v1; - ae_int_t problemtype; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - memset(&xy, 0, sizeof(xy)); - memset(&cx, 0, sizeof(cx)); - memset(&cy, 0, sizeof(cy)); - _hqrndstate_init(&rs, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cy, 0, DT_REAL, _state, ae_true); - - hqrndrandomize(&rs, _state); - xtol = 1.0E-5; - - /* - * Generate random problem - */ - for(nx=1; nx<=4; nx++) - { - - /* - * Generate synthetic dataset, at least 5 points - */ - npoints = 5+2*nx+hqrnduniformi(&rs, 50+ae_round(ae_pow((double)(4), (double)(nx), _state), _state), _state); - ae_matrix_set_length(&xy, npoints, nx, _state); - for(i=0; i<=npoints-1; i++) - { - v = (double)(0); - for(j=0; j<=nx-1; j++) - { - vv = hqrndnormal(&rs, _state); - v = v+ae_sqr(vv, _state); - xy.ptr.pp_double[i][j] = vv; - } - ae_assert(ae_fp_greater(v,(double)(0)), "Assertion failed", _state); - v = (1+0.1*hqrnduniformr(&rs, _state))/ae_sqrt(v, _state); - for(j=0; j<=nx-1; j++) - { - xy.ptr.pp_double[i][j] = xy.ptr.pp_double[i][j]*v; - } - } - - /* - * Solve with generic solver, check - */ - unsetrealarray(&cx, _state); - rlo = (double)(0); - rhi = (double)(0); - problemtype = 0; - fitspherex(&xy, npoints, nx, problemtype, 0.0, 0, 0.0, &cx, &rlo, &rhi, _state); - ae_set_error_flag(err, ae_fp_neq(rlo,rhi), __FILE__, __LINE__, "testfitsphereunit.ap:109"); - vv = 0.0; - for(i=0; i<=npoints-1; i++) - { - v = (double)(0); - for(j=0; j<=nx-1; j++) - { - v = v+ae_sqr(cx.ptr.p_double[j]-xy.ptr.pp_double[i][j], _state); - } - vv = vv+ae_sqrt(v, _state)/npoints; - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(vv-rlo, _state),xtol), __FILE__, __LINE__, "testfitsphereunit.ap:118"); - testfitsphereunit_calclserror(&xy, npoints, nx, &cx, &v0, _state); - - /* - * Check that small perturbations to center position increase target function - * - * NOTE: in fact, we do allow small increase in target function - but no more - * than FTol=1E-6*XTol. It helps to avoid spurious error reports in - * degenerate cases. - */ - ftol = 1.0E-6*xtol; - ae_vector_set_length(&cy, nx, _state); - for(j=0; j<=nx-1; j++) - { - for(k=0; k<=nx-1; k++) - { - cy.ptr.p_double[k] = cx.ptr.p_double[k]; - } - cy.ptr.p_double[j] = cx.ptr.p_double[j]+xtol; - testfitsphereunit_calclserror(&xy, npoints, nx, &cy, &v1, _state); - ae_set_error_flag(err, ae_fp_less(v1,v0-ftol), __FILE__, __LINE__, "testfitsphereunit.ap:137"); - for(k=0; k<=nx-1; k++) - { - cy.ptr.p_double[k] = cx.ptr.p_double[k]; - } - cy.ptr.p_double[j] = cx.ptr.p_double[j]-xtol; - testfitsphereunit_calclserror(&xy, npoints, nx, &cy, &v1, _state); - ae_set_error_flag(err, ae_fp_less(v1,v0-ftol), __FILE__, __LINE__, "testfitsphereunit.ap:144"); - } - - /* - * Compare against results returned by specific solver - */ - fitspherels(&xy, npoints, nx, &cy, &v, _state); - ae_set_error_flag(err, ae_fp_neq(v,rlo), __FILE__, __LINE__, "testfitsphereunit.ap:151"); - for(j=0; j<=nx-1; j++) - { - ae_set_error_flag(err, ae_fp_neq(cy.ptr.p_double[j],cx.ptr.p_double[j]), __FILE__, __LINE__, "testfitsphereunit.ap:153"); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests sphere fitting using generic synthetic datasets and -non-smooth target functions (MC, MI, MZ fitting) - -On failure sets Err to True (leaves it unchanged otherwise) -*************************************************************************/ -static void testfitsphereunit_testspherefittingns(ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - hqrndstate rs; - ae_matrix xy; - ae_int_t npoints; - ae_int_t nx; - ae_vector cx; - ae_vector cy; - double rlo; - double rhi; - double rlo2; - double rhi2; - double xtol; - double ftol; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double vv; - ae_int_t problemtype; - double vlo; - double vhi; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - memset(&xy, 0, sizeof(xy)); - memset(&cx, 0, sizeof(cx)); - memset(&cy, 0, sizeof(cy)); - _hqrndstate_init(&rs, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cy, 0, DT_REAL, _state, ae_true); - - hqrndrandomize(&rs, _state); - xtol = 1.0E-5; - - /* - * Generate random problem - */ - for(nx=1; nx<=4; nx++) - { - - /* - * Generate synthetic dataset - */ - npoints = 50+ae_round(ae_pow((double)(4), (double)(nx), _state), _state); - ae_matrix_set_length(&xy, npoints, nx, _state); - for(i=0; i<=npoints-1; i++) - { - v = (double)(0); - for(j=0; j<=nx-1; j++) - { - vv = hqrndnormal(&rs, _state); - v = v+ae_sqr(vv, _state); - xy.ptr.pp_double[i][j] = vv; - } - ae_assert(ae_fp_greater(v,(double)(0)), "Assertion failed", _state); - v = (1+0.1*hqrnduniformr(&rs, _state))/ae_sqrt(v, _state); - for(j=0; j<=nx-1; j++) - { - xy.ptr.pp_double[i][j] = xy.ptr.pp_double[i][j]*v; - } - } - - /* - * Perform various kinds of fit, NLC solver is used - */ - for(problemtype=1; problemtype<=3; problemtype++) - { - - /* - * Solve with generic solver - */ - unsetrealarray(&cx, _state); - rlo = (double)(0); - rhi = (double)(0); - fitspherex(&xy, npoints, nx, problemtype, 0.0, 0, 0.0, &cx, &rlo, &rhi, _state); - - /* - * Check that small perturbations to center position increase target function - * - * NOTE: in fact, we do allow small increase in target function - but no more - * than FTol=1E-6*XTol. It helps to avoid spurious error reports in - * degenerate cases. - */ - ftol = 1.0E-6*xtol; - ae_vector_set_length(&cy, nx, _state); - if( problemtype==2||problemtype==3 ) - { - vlo = (double)(1); - } - else - { - vlo = (double)(0); - } - if( problemtype==1||problemtype==3 ) - { - vhi = (double)(1); - } - else - { - vhi = (double)(0); - } - for(j=0; j<=nx-1; j++) - { - for(k=0; k<=nx-1; k++) - { - cy.ptr.p_double[k] = cx.ptr.p_double[k]; - } - cy.ptr.p_double[j] = cx.ptr.p_double[j]+xtol; - testfitsphereunit_calcradii(&xy, npoints, nx, &cy, &rlo2, &rhi2, _state); - ae_set_error_flag(err, ae_fp_less(rhi2*vhi-rlo2*vlo,rhi*vhi-rlo*vlo-ftol), __FILE__, __LINE__, "testfitsphereunit.ap:245"); - for(k=0; k<=nx-1; k++) - { - cy.ptr.p_double[k] = cx.ptr.p_double[k]; - } - cy.ptr.p_double[j] = cx.ptr.p_double[j]-xtol; - testfitsphereunit_calcradii(&xy, npoints, nx, &cy, &rlo2, &rhi2, _state); - ae_set_error_flag(err, ae_fp_less(rhi2*vhi-rlo2*vlo,rhi*vhi-rlo*vlo-ftol), __FILE__, __LINE__, "testfitsphereunit.ap:252"); - } - - /* - * Compare against results returned by specific solver - */ - if( problemtype==1 ) - { - fitspheremc(&xy, npoints, nx, &cy, &rhi2, _state); - ae_set_error_flag(err, ae_fp_neq(rhi2,rhi), __FILE__, __LINE__, "testfitsphereunit.ap:261"); - for(j=0; j<=nx-1; j++) - { - ae_set_error_flag(err, ae_fp_neq(cy.ptr.p_double[j],cx.ptr.p_double[j]), __FILE__, __LINE__, "testfitsphereunit.ap:263"); - } - } - if( problemtype==2 ) - { - fitspheremi(&xy, npoints, nx, &cy, &rlo2, _state); - ae_set_error_flag(err, ae_fp_neq(rlo2,rlo), __FILE__, __LINE__, "testfitsphereunit.ap:268"); - for(j=0; j<=nx-1; j++) - { - ae_set_error_flag(err, ae_fp_neq(cy.ptr.p_double[j],cx.ptr.p_double[j]), __FILE__, __LINE__, "testfitsphereunit.ap:270"); - } - } - if( problemtype==3 ) - { - fitspheremz(&xy, npoints, nx, &cy, &rlo2, &rhi2, _state); - ae_set_error_flag(err, ae_fp_neq(rlo2,rlo), __FILE__, __LINE__, "testfitsphereunit.ap:275"); - ae_set_error_flag(err, ae_fp_neq(rhi2,rhi), __FILE__, __LINE__, "testfitsphereunit.ap:276"); - for(j=0; j<=nx-1; j++) - { - ae_set_error_flag(err, ae_fp_neq(cy.ptr.p_double[j],cx.ptr.p_double[j]), __FILE__, __LINE__, "testfitsphereunit.ap:278"); - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function tests sphere fitting - -On failure sets Err to True (leaves it unchanged otherwise) -*************************************************************************/ -static void testfitsphereunit_testspherefittingvosswinkel2(ae_bool* err, - ae_state *_state) -{ - ae_frame _frame_block; - hqrndstate rs; - ae_matrix xy; - ae_int_t cnt; - ae_vector cx; - double rlo; - double rhi; - double tol; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - memset(&xy, 0, sizeof(xy)); - memset(&cx, 0, sizeof(cx)); - _hqrndstate_init(&rs, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cx, 0, DT_REAL, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Test problem #2 by Vosswinkel GmbH - */ - ae_matrix_set_length(&xy, 40, 2, _state); - cnt = 0; - testfitsphereunit_addvalue(&xy, &cnt, 0.1026, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.000036, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.101119, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.016144, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.096754, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.031654, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.088981, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.045634, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.082056, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.06008, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.074966, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.075647, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.065, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.090471, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.052411, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.104381, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.036436, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.114859, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.019034, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.126577, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.001191, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.139295, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.024689, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.147143, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.049729, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.147861, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.076402, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.145907, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.103928, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.139553, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.133726, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.130429, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.159051, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.112298, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.179496, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.08821, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.194562, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.059989, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.204838, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.029135, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.206971, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.00349, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.206207, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.036427, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.197079, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.06806, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.180492, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.096353, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.158203, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.119891, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.132669, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.138375, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.105652, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.152229, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.078587, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.16316, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.049984, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.167084, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.022067, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.165233, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.004002, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.16075, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.028058, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.151829, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.050088, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.141178, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.067646, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.124169, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.081421, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.10567, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.087305, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.082618, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.094189, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.064399, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.099445, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.047018, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.09936, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.028981, _state); - testfitsphereunit_addvalue(&xy, &cnt, 0.101784, _state); - testfitsphereunit_addvalue(&xy, &cnt, -0.012918, _state); - tol = 1.0E-7; - - /* - * MZ problem, NLC solver - */ - unsetrealarray(&cx, _state); - rlo = (double)(0); - rhi = (double)(0); - fitspheremz(&xy, xy.rows, xy.cols, &cx, &rlo, &rhi, _state); - ae_set_error_flag(err, cx.cnt!=2, __FILE__, __LINE__, "testfitsphereunit.ap:395"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[0]+0.050884688, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:398"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[1]+0.011472328, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:399"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rlo-0.150973382, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:400"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rhi-0.164374709, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:401"); - unsetrealarray(&cx, _state); - rlo = (double)(0); - rhi = (double)(0); - fitspherex(&xy, xy.rows, xy.cols, 3, 0.0, 0, 0.0, &cx, &rlo, &rhi, _state); - ae_set_error_flag(err, cx.cnt!=2, __FILE__, __LINE__, "testfitsphereunit.ap:406"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[0]+0.050884688, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:409"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[1]+0.011472328, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:410"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rlo-0.150973382, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:411"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rhi-0.164374709, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:412"); - - /* - * MC problem, NLC solver - */ - unsetrealarray(&cx, _state); - rlo = (double)(0); - rhi = (double)(0); - fitspheremc(&xy, xy.rows, xy.cols, &cx, &rhi, _state); - ae_set_error_flag(err, cx.cnt!=2, __FILE__, __LINE__, "testfitsphereunit.ap:421"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[0]+0.051137580, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:424"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[1]+0.011680985, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:425"); - ae_set_error_flag(err, ae_fp_neq(rlo,(double)(0)), __FILE__, __LINE__, "testfitsphereunit.ap:426"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rhi-0.164365735, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:427"); - unsetrealarray(&cx, _state); - rlo = (double)(0); - rhi = (double)(0); - fitspherex(&xy, xy.rows, xy.cols, 1, 0.0, 0, 0.0, &cx, &rlo, &rhi, _state); - ae_set_error_flag(err, cx.cnt!=2, __FILE__, __LINE__, "testfitsphereunit.ap:432"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[0]+0.051137580, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:435"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[1]+0.011680985, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:436"); - ae_set_error_flag(err, ae_fp_neq(rlo,(double)(0)), __FILE__, __LINE__, "testfitsphereunit.ap:437"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rhi-0.164365735, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:438"); - - /* - * MI problem, NLC solver - */ - unsetrealarray(&cx, _state); - rlo = (double)(0); - rhi = (double)(0); - fitspheremi(&xy, xy.rows, xy.cols, &cx, &rlo, _state); - ae_set_error_flag(err, cx.cnt!=2, __FILE__, __LINE__, "testfitsphereunit.ap:447"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[0]+0.054593489, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:450"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[1]+0.007459466, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:451"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rlo-0.152429205, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:452"); - ae_set_error_flag(err, ae_fp_neq(rhi,(double)(0)), __FILE__, __LINE__, "testfitsphereunit.ap:453"); - unsetrealarray(&cx, _state); - rlo = (double)(0); - rhi = (double)(0); - fitspherex(&xy, xy.rows, xy.cols, 2, 0.0, 0, 0.0, &cx, &rlo, &rhi, _state); - ae_set_error_flag(err, cx.cnt!=2, __FILE__, __LINE__, "testfitsphereunit.ap:458"); - if( *err ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[0]+0.054593489, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:461"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[1]+0.007459466, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:462"); - ae_set_error_flag(err, ae_fp_greater(ae_fabs(rlo-0.152429205, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:463"); - ae_set_error_flag(err, ae_fp_neq(rhi,(double)(0)), __FILE__, __LINE__, "testfitsphereunit.ap:464"); - ae_frame_leave(_state); -} - - -/************************************************************************* -Used to calculate RLo/Rhi given XY and center position -*************************************************************************/ -static void testfitsphereunit_calcradii(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - /* Real */ ae_vector* cx, - double* rlo, - double* rhi, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - - *rlo = 0; - *rhi = 0; - - *rlo = ae_maxrealnumber; - *rhi = (double)(0); - for(i=0; i<=npoints-1; i++) - { - v = (double)(0); - for(j=0; j<=nx-1; j++) - { - v = v+ae_sqr(xy->ptr.pp_double[i][j]-cx->ptr.p_double[j], _state); - } - v = ae_sqrt(v, _state); - *rhi = ae_maxreal(*rhi, v, _state); - *rlo = ae_minreal(*rlo, v, _state); - } -} - - -/************************************************************************* -Used to calculate least squares error given XY and center position -*************************************************************************/ -static void testfitsphereunit_calclserror(/* Real */ ae_matrix* xy, - ae_int_t npoints, - ae_int_t nx, - /* Real */ ae_vector* cx, - double* err, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - double rad; - - *err = 0; - - rad = 0.0; - for(i=0; i<=npoints-1; i++) - { - v = (double)(0); - for(j=0; j<=nx-1; j++) - { - v = v+ae_sqr(cx->ptr.p_double[j]-xy->ptr.pp_double[i][j], _state); - } - rad = rad+ae_sqrt(v, _state)/npoints; - } - *err = 0.0; - for(i=0; i<=npoints-1; i++) - { - v = (double)(0); - for(j=0; j<=nx-1; j++) - { - v = v+ae_sqr(cx->ptr.p_double[j]-xy->ptr.pp_double[i][j], _state); - } - *err = *err+ae_sqr(rad-ae_sqrt(v, _state), _state); - } -} - - -/************************************************************************* -Used to initialize dynamic array with constant values -*************************************************************************/ -static void testfitsphereunit_addvalue(/* Real */ ae_matrix* xy, - ae_int_t* cnt, - double v, - ae_state *_state) -{ - - - xy->ptr.pp_double[*cnt/xy->cols][*cnt%xy->cols] = v; - *cnt = *cnt+1; -} - - - -static void testspline1dunit_lconst(double a, - double b, - spline1dinterpolant* c, - double lstep, - double* l0, - double* l1, - double* l2, - ae_state *_state); -static ae_bool testspline1dunit_enumerateallsplines(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t* splineindex, - spline1dinterpolant* s, - ae_state *_state); -static ae_bool testspline1dunit_testunpack(spline1dinterpolant* c, - /* Real */ ae_vector* x, - ae_state *_state); -static void testspline1dunit_unsetspline1d(spline1dinterpolant* c, - ae_state *_state); -static void testspline1dunit_unsetreport(spline1dfitreport* rep, - ae_state *_state); -static ae_bool testspline1dunit_testmonotonespline(ae_state *_state); -static void testspline1dunit_testsplinefitting(ae_bool* fiterrors, - ae_state *_state); - - - - - -ae_bool testspline1d(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_bool waserrors; - ae_bool crserrors; - ae_bool cserrors; - ae_bool hserrors; - ae_bool aserrors; - ae_bool lserrors; - ae_bool dserrors; - ae_bool uperrors; - ae_bool cperrors; - ae_bool lterrors; - ae_bool ierrors; - ae_bool monotoneerr; - ae_bool fiterr; - double threshold; - ae_int_t passcount; - double lstep; - double h; - ae_int_t maxn; - ae_int_t bltype; - ae_int_t brtype; - ae_bool periodiccond; - ae_int_t n; - ae_int_t i; - ae_int_t k; - ae_int_t pass; - ae_vector x; - ae_vector y; - ae_vector yp; - ae_vector w; - ae_vector w2; - ae_vector y2; - ae_vector d; - ae_vector xc; - ae_vector yc; - ae_vector xtest; - ae_int_t n2; - ae_vector tmp0; - ae_vector tmp1; - ae_vector tmp2; - ae_vector tmpx; - ae_vector dc; - spline1dinterpolant c; - spline1dinterpolant c2; - double a; - double b; - double bl; - double br; - double t; - double sa; - double sb; - double v; - double l10; - double l11; - double l12; - double l20; - double l21; - double l22; - double p0; - double p1; - double p2; - double s; - double ds; - double d2s; - double s2; - double ds2; - double d2s2; - double vl; - double vm; - double vr; - double err; - double tension; - double intab; - ae_int_t splineindex; - double lipschitzeps; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&yp, 0, sizeof(yp)); - memset(&w, 0, sizeof(w)); - memset(&w2, 0, sizeof(w2)); - memset(&y2, 0, sizeof(y2)); - memset(&d, 0, sizeof(d)); - memset(&xc, 0, sizeof(xc)); - memset(&yc, 0, sizeof(yc)); - memset(&xtest, 0, sizeof(xtest)); - memset(&tmp0, 0, sizeof(tmp0)); - memset(&tmp1, 0, sizeof(tmp1)); - memset(&tmp2, 0, sizeof(tmp2)); - memset(&tmpx, 0, sizeof(tmpx)); - memset(&dc, 0, sizeof(dc)); - memset(&c, 0, sizeof(c)); - memset(&c2, 0, sizeof(c2)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yp, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xtest, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmpx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dc, 0, DT_INT, _state, ae_true); - _spline1dinterpolant_init(&c, _state, ae_true); - _spline1dinterpolant_init(&c2, _state, ae_true); - - waserrors = ae_false; - passcount = 20; - lstep = 0.005; - h = 0.00001; - maxn = 10; - lipschitzeps = 1.0E-6; - threshold = 10000*ae_machineepsilon; - lserrors = ae_false; - cserrors = ae_false; - crserrors = ae_false; - hserrors = ae_false; - aserrors = ae_false; - dserrors = ae_false; - cperrors = ae_false; - uperrors = ae_false; - lterrors = ae_false; - ierrors = ae_false; - fiterr = ae_false; - - /* - * General test: linear, cubic, Hermite, Akima - */ - for(n=2; n<=maxn; n++) - { - ae_vector_set_length(&x, n-1+1, _state); - ae_vector_set_length(&y, n-1+1, _state); - ae_vector_set_length(&yp, n-1+1, _state); - ae_vector_set_length(&d, n-1+1, _state); - for(pass=1; pass<=passcount; pass++) - { - - /* - * Prepare task: - * * X contains abscissas from [A,B] - * * Y contains function values - * * YP contains periodic function values - */ - a = -1-ae_randomreal(_state); - b = 1+ae_randomreal(_state); - bl = 2*ae_randomreal(_state)-1; - br = 2*ae_randomreal(_state)-1; - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 0.5*(b+a)+0.5*(b-a)*ae_cos(ae_pi*(2*i+1)/(2*n), _state); - if( i==0 ) - { - x.ptr.p_double[i] = a; - } - if( i==n-1 ) - { - x.ptr.p_double[i] = b; - } - y.ptr.p_double[i] = ae_cos(1.3*ae_pi*x.ptr.p_double[i]+0.4, _state); - yp.ptr.p_double[i] = y.ptr.p_double[i]; - d.ptr.p_double[i] = -1.3*ae_pi*ae_sin(1.3*ae_pi*x.ptr.p_double[i]+0.4, _state); - } - yp.ptr.p_double[n-1] = yp.ptr.p_double[0]; - for(i=0; i<=n-1; i++) - { - k = ae_randominteger(n, _state); - if( k!=i ) - { - t = x.ptr.p_double[i]; - x.ptr.p_double[i] = x.ptr.p_double[k]; - x.ptr.p_double[k] = t; - t = y.ptr.p_double[i]; - y.ptr.p_double[i] = y.ptr.p_double[k]; - y.ptr.p_double[k] = t; - t = yp.ptr.p_double[i]; - yp.ptr.p_double[i] = yp.ptr.p_double[k]; - yp.ptr.p_double[k] = t; - t = d.ptr.p_double[i]; - d.ptr.p_double[i] = d.ptr.p_double[k]; - d.ptr.p_double[k] = t; - } - } - - /* - * Build linear spline - * Test for general interpolation scheme properties: - * * values at nodes - * * continuous function - * Test for specific properties is implemented below. - */ - spline1dbuildlinear(&x, &y, n, &c, _state); - err = (double)(0); - for(i=0; i<=n-1; i++) - { - err = ae_maxreal(err, ae_fabs(y.ptr.p_double[i]-spline1dcalc(&c, x.ptr.p_double[i], _state), _state), _state); - } - lserrors = lserrors||ae_fp_greater(err,threshold); - testspline1dunit_lconst(a, b, &c, lstep, &l10, &l11, &l12, _state); - testspline1dunit_lconst(a, b, &c, lstep/3, &l20, &l21, &l22, _state); - lserrors = lserrors||ae_fp_greater(l20/l10,1.2); - - /* - * Build cubic spline. - * Test for interpolation scheme properties: - * * values at nodes - * * boundary conditions - * * continuous function - * * continuous first derivative - * * continuous second derivative - * * periodicity properties - * * Spline1DGridDiff(), Spline1DGridDiff2() and Spline1DDiff() - * calls must return same results - */ - for(bltype=-1; bltype<=2; bltype++) - { - for(brtype=-1; brtype<=2; brtype++) - { - - /* - * skip meaningless combination of boundary conditions - * (one condition is periodic, another is not) - */ - periodiccond = bltype==-1||brtype==-1; - if( periodiccond&&bltype!=brtype ) - { - continue; - } - - /* - * build - */ - if( periodiccond ) - { - spline1dbuildcubic(&x, &yp, n, bltype, bl, brtype, br, &c, _state); - } - else - { - spline1dbuildcubic(&x, &y, n, bltype, bl, brtype, br, &c, _state); - } - - /* - * interpolation properties - */ - err = (double)(0); - if( periodiccond ) - { - - /* - * * check values at nodes; spline is periodic so - * we add random number of periods to nodes - * * we also test for periodicity of derivatives - */ - for(i=0; i<=n-1; i++) - { - v = x.ptr.p_double[i]; - vm = v+(b-a)*(ae_randominteger(5, _state)-2); - t = yp.ptr.p_double[i]-spline1dcalc(&c, vm, _state); - err = ae_maxreal(err, ae_fabs(t, _state), _state); - spline1ddiff(&c, v, &s, &ds, &d2s, _state); - spline1ddiff(&c, vm, &s2, &ds2, &d2s2, _state); - err = ae_maxreal(err, ae_fabs(s-s2, _state), _state); - err = ae_maxreal(err, ae_fabs(ds-ds2, _state), _state); - err = ae_maxreal(err, ae_fabs(d2s-d2s2, _state), _state); - } - - /* - * periodicity between nodes - */ - v = a+(b-a)*ae_randomreal(_state); - vm = v+(b-a)*(ae_randominteger(5, _state)-2); - err = ae_maxreal(err, ae_fabs(spline1dcalc(&c, v, _state)-spline1dcalc(&c, vm, _state), _state), _state); - spline1ddiff(&c, v, &s, &ds, &d2s, _state); - spline1ddiff(&c, vm, &s2, &ds2, &d2s2, _state); - err = ae_maxreal(err, ae_fabs(s-s2, _state), _state); - err = ae_maxreal(err, ae_fabs(ds-ds2, _state), _state); - err = ae_maxreal(err, ae_fabs(d2s-d2s2, _state), _state); - } - else - { - - /* - * * check values at nodes - */ - for(i=0; i<=n-1; i++) - { - err = ae_maxreal(err, ae_fabs(y.ptr.p_double[i]-spline1dcalc(&c, x.ptr.p_double[i], _state), _state), _state); - } - } - ae_set_error_flag(&cserrors, ae_fp_greater(err,threshold), __FILE__, __LINE__, "testspline1dunit.ap:221"); - - /* - * check boundary conditions - */ - err = (double)(0); - if( bltype==0 ) - { - spline1ddiff(&c, a-h, &s, &ds, &d2s, _state); - spline1ddiff(&c, a+h, &s2, &ds2, &d2s2, _state); - t = (d2s2-d2s)/(2*h); - err = ae_maxreal(err, ae_fabs(t, _state), _state); - } - if( bltype==1 ) - { - t = (spline1dcalc(&c, a+h, _state)-spline1dcalc(&c, a-h, _state))/(2*h); - err = ae_maxreal(err, ae_fabs(bl-t, _state), _state); - } - if( bltype==2 ) - { - t = (spline1dcalc(&c, a+h, _state)-2*spline1dcalc(&c, a, _state)+spline1dcalc(&c, a-h, _state))/ae_sqr(h, _state); - err = ae_maxreal(err, ae_fabs(bl-t, _state), _state); - } - if( brtype==0 ) - { - spline1ddiff(&c, b-h, &s, &ds, &d2s, _state); - spline1ddiff(&c, b+h, &s2, &ds2, &d2s2, _state); - t = (d2s2-d2s)/(2*h); - err = ae_maxreal(err, ae_fabs(t, _state), _state); - } - if( brtype==1 ) - { - t = (spline1dcalc(&c, b+h, _state)-spline1dcalc(&c, b-h, _state))/(2*h); - err = ae_maxreal(err, ae_fabs(br-t, _state), _state); - } - if( brtype==2 ) - { - t = (spline1dcalc(&c, b+h, _state)-2*spline1dcalc(&c, b, _state)+spline1dcalc(&c, b-h, _state))/ae_sqr(h, _state); - err = ae_maxreal(err, ae_fabs(br-t, _state), _state); - } - if( bltype==-1||brtype==-1 ) - { - spline1ddiff(&c, a+100*ae_machineepsilon, &s, &ds, &d2s, _state); - spline1ddiff(&c, b-100*ae_machineepsilon, &s2, &ds2, &d2s2, _state); - err = ae_maxreal(err, ae_fabs(s-s2, _state), _state); - err = ae_maxreal(err, ae_fabs(ds-ds2, _state), _state); - err = ae_maxreal(err, ae_fabs(d2s-d2s2, _state), _state); - } - ae_set_error_flag(&cserrors, ae_fp_greater(err,1.0E-3), __FILE__, __LINE__, "testspline1dunit.ap:269"); - - /* - * Check Lipschitz continuity - */ - testspline1dunit_lconst(a, b, &c, lstep, &l10, &l11, &l12, _state); - testspline1dunit_lconst(a, b, &c, lstep/3, &l20, &l21, &l22, _state); - if( ae_fp_greater(l10,lipschitzeps) ) - { - ae_set_error_flag(&cserrors, ae_fp_greater(l20/(l10+lipschitzeps),1.2), __FILE__, __LINE__, "testspline1dunit.ap:277"); - } - if( ae_fp_greater(l11,lipschitzeps) ) - { - ae_set_error_flag(&cserrors, ae_fp_greater(l21/(l11+lipschitzeps),1.2), __FILE__, __LINE__, "testspline1dunit.ap:279"); - } - if( ae_fp_greater(l12,lipschitzeps) ) - { - ae_set_error_flag(&cserrors, ae_fp_greater(l22/(l12+lipschitzeps),1.2), __FILE__, __LINE__, "testspline1dunit.ap:281"); - } - - /* - * compare spline1dgriddiff() and spline1ddiff() results - */ - err = (double)(0); - if( periodiccond ) - { - spline1dgriddiffcubic(&x, &yp, n, bltype, bl, brtype, br, &tmp1, _state); - } - else - { - spline1dgriddiffcubic(&x, &y, n, bltype, bl, brtype, br, &tmp1, _state); - } - ae_assert(tmp1.cnt>=n, "Assertion failed", _state); - for(i=0; i<=n-1; i++) - { - spline1ddiff(&c, x.ptr.p_double[i], &s, &ds, &d2s, _state); - err = ae_maxreal(err, ae_fabs(ds-tmp1.ptr.p_double[i], _state), _state); - } - if( periodiccond ) - { - spline1dgriddiff2cubic(&x, &yp, n, bltype, bl, brtype, br, &tmp1, &tmp2, _state); - } - else - { - spline1dgriddiff2cubic(&x, &y, n, bltype, bl, brtype, br, &tmp1, &tmp2, _state); - } - for(i=0; i<=n-1; i++) - { - spline1ddiff(&c, x.ptr.p_double[i], &s, &ds, &d2s, _state); - err = ae_maxreal(err, ae_fabs(ds-tmp1.ptr.p_double[i], _state), _state); - err = ae_maxreal(err, ae_fabs(d2s-tmp2.ptr.p_double[i], _state), _state); - } - ae_set_error_flag(&cserrors, ae_fp_greater(err,threshold), __FILE__, __LINE__, "testspline1dunit.ap:307"); - - /* - * compare spline1dconv()/convdiff()/convdiff2() and spline1ddiff() results - */ - n2 = 2+ae_randominteger(2*n, _state); - ae_vector_set_length(&tmpx, n2, _state); - for(i=0; i<=n2-1; i++) - { - tmpx.ptr.p_double[i] = 0.5*(a+b)+(a-b)*(2*ae_randomreal(_state)-1); - } - err = (double)(0); - if( periodiccond ) - { - spline1dconvcubic(&x, &yp, n, bltype, bl, brtype, br, &tmpx, n2, &tmp0, _state); - } - else - { - spline1dconvcubic(&x, &y, n, bltype, bl, brtype, br, &tmpx, n2, &tmp0, _state); - } - for(i=0; i<=n2-1; i++) - { - spline1ddiff(&c, tmpx.ptr.p_double[i], &s, &ds, &d2s, _state); - err = ae_maxreal(err, ae_fabs(s-tmp0.ptr.p_double[i], _state), _state); - } - if( periodiccond ) - { - spline1dconvdiffcubic(&x, &yp, n, bltype, bl, brtype, br, &tmpx, n2, &tmp0, &tmp1, _state); - } - else - { - spline1dconvdiffcubic(&x, &y, n, bltype, bl, brtype, br, &tmpx, n2, &tmp0, &tmp1, _state); - } - for(i=0; i<=n2-1; i++) - { - spline1ddiff(&c, tmpx.ptr.p_double[i], &s, &ds, &d2s, _state); - err = ae_maxreal(err, ae_fabs(s-tmp0.ptr.p_double[i], _state), _state); - err = ae_maxreal(err, ae_fabs(ds-tmp1.ptr.p_double[i], _state), _state); - } - if( periodiccond ) - { - spline1dconvdiff2cubic(&x, &yp, n, bltype, bl, brtype, br, &tmpx, n2, &tmp0, &tmp1, &tmp2, _state); - } - else - { - spline1dconvdiff2cubic(&x, &y, n, bltype, bl, brtype, br, &tmpx, n2, &tmp0, &tmp1, &tmp2, _state); - } - for(i=0; i<=n2-1; i++) - { - spline1ddiff(&c, tmpx.ptr.p_double[i], &s, &ds, &d2s, _state); - err = ae_maxreal(err, ae_fabs(s-tmp0.ptr.p_double[i], _state), _state); - err = ae_maxreal(err, ae_fabs(ds-tmp1.ptr.p_double[i], _state), _state); - err = ae_maxreal(err, ae_fabs(d2s-tmp2.ptr.p_double[i], _state), _state); - } - ae_set_error_flag(&cserrors, ae_fp_greater(err,threshold), __FILE__, __LINE__, "testspline1dunit.ap:351"); - } - } - - /* - * Build Catmull-Rom spline. - * Test for interpolation scheme properties: - * * values at nodes - * * boundary conditions - * * continuous function - * * continuous first derivative - * * periodicity properties - */ - for(bltype=-1; bltype<=0; bltype++) - { - periodiccond = bltype==-1; - - /* - * select random tension value, then build - */ - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - tension = (double)(0); - } - else - { - tension = (double)(1); - } - } - else - { - tension = ae_randomreal(_state); - } - if( periodiccond ) - { - spline1dbuildcatmullrom(&x, &yp, n, bltype, tension, &c, _state); - } - else - { - spline1dbuildcatmullrom(&x, &y, n, bltype, tension, &c, _state); - } - - /* - * interpolation properties - */ - err = (double)(0); - if( periodiccond ) - { - - /* - * * check values at nodes; spline is periodic so - * we add random number of periods to nodes - * * we also test for periodicity of first derivative - */ - for(i=0; i<=n-1; i++) - { - v = x.ptr.p_double[i]; - vm = v+(b-a)*(ae_randominteger(5, _state)-2); - t = yp.ptr.p_double[i]-spline1dcalc(&c, vm, _state); - err = ae_maxreal(err, ae_fabs(t, _state), _state); - spline1ddiff(&c, v, &s, &ds, &d2s, _state); - spline1ddiff(&c, vm, &s2, &ds2, &d2s2, _state); - err = ae_maxreal(err, ae_fabs(s-s2, _state), _state); - err = ae_maxreal(err, ae_fabs(ds-ds2, _state), _state); - } - - /* - * periodicity between nodes - */ - v = a+(b-a)*ae_randomreal(_state); - vm = v+(b-a)*(ae_randominteger(5, _state)-2); - err = ae_maxreal(err, ae_fabs(spline1dcalc(&c, v, _state)-spline1dcalc(&c, vm, _state), _state), _state); - spline1ddiff(&c, v, &s, &ds, &d2s, _state); - spline1ddiff(&c, vm, &s2, &ds2, &d2s2, _state); - err = ae_maxreal(err, ae_fabs(s-s2, _state), _state); - err = ae_maxreal(err, ae_fabs(ds-ds2, _state), _state); - } - else - { - - /* - * * check values at nodes - */ - for(i=0; i<=n-1; i++) - { - err = ae_maxreal(err, ae_fabs(y.ptr.p_double[i]-spline1dcalc(&c, x.ptr.p_double[i], _state), _state), _state); - } - } - crserrors = crserrors||ae_fp_greater(err,threshold); - - /* - * check boundary conditions - */ - err = (double)(0); - if( bltype==0 ) - { - spline1ddiff(&c, a-h, &s, &ds, &d2s, _state); - spline1ddiff(&c, a+h, &s2, &ds2, &d2s2, _state); - t = (d2s2-d2s)/(2*h); - err = ae_maxreal(err, ae_fabs(t, _state), _state); - spline1ddiff(&c, b-h, &s, &ds, &d2s, _state); - spline1ddiff(&c, b+h, &s2, &ds2, &d2s2, _state); - t = (d2s2-d2s)/(2*h); - err = ae_maxreal(err, ae_fabs(t, _state), _state); - } - if( bltype==-1 ) - { - spline1ddiff(&c, a+100*ae_machineepsilon, &s, &ds, &d2s, _state); - spline1ddiff(&c, b-100*ae_machineepsilon, &s2, &ds2, &d2s2, _state); - err = ae_maxreal(err, ae_fabs(s-s2, _state), _state); - err = ae_maxreal(err, ae_fabs(ds-ds2, _state), _state); - } - crserrors = crserrors||ae_fp_greater(err,1.0E-3); - - /* - * Check Lipschitz continuity - */ - testspline1dunit_lconst(a, b, &c, lstep, &l10, &l11, &l12, _state); - testspline1dunit_lconst(a, b, &c, lstep/3, &l20, &l21, &l22, _state); - if( ae_fp_greater(l10,1.0E-6) ) - { - crserrors = crserrors||ae_fp_greater(l20/l10,1.2); - } - if( ae_fp_greater(l11,1.0E-6) ) - { - crserrors = crserrors||ae_fp_greater(l21/l11,1.2); - } - } - - /* - * Build Hermite spline. - * Test for interpolation scheme properties: - * * values and derivatives at nodes - * * continuous function - * * continuous first derivative - */ - spline1dbuildhermite(&x, &y, &d, n, &c, _state); - err = (double)(0); - for(i=0; i<=n-1; i++) - { - err = ae_maxreal(err, ae_fabs(y.ptr.p_double[i]-spline1dcalc(&c, x.ptr.p_double[i], _state), _state), _state); - } - hserrors = hserrors||ae_fp_greater(err,threshold); - err = (double)(0); - for(i=0; i<=n-1; i++) - { - t = (spline1dcalc(&c, x.ptr.p_double[i]+h, _state)-spline1dcalc(&c, x.ptr.p_double[i]-h, _state))/(2*h); - err = ae_maxreal(err, ae_fabs(d.ptr.p_double[i]-t, _state), _state); - } - hserrors = hserrors||ae_fp_greater(err,1.0E-3); - testspline1dunit_lconst(a, b, &c, lstep, &l10, &l11, &l12, _state); - testspline1dunit_lconst(a, b, &c, lstep/3, &l20, &l21, &l22, _state); - hserrors = hserrors||ae_fp_greater(l20/l10,1.2); - hserrors = hserrors||ae_fp_greater(l21/l11,1.2); - - /* - * Build Akima spline - * Test for general interpolation scheme properties: - * * values at nodes - * * continuous function - * * continuous first derivative - * Test for Akima-specific properties is implemented below. - */ - spline1dbuildakima(&x, &y, n, &c, _state); - err = (double)(0); - for(i=0; i<=n-1; i++) - { - err = ae_maxreal(err, ae_fabs(y.ptr.p_double[i]-spline1dcalc(&c, x.ptr.p_double[i], _state), _state), _state); - } - aserrors = aserrors||ae_fp_greater(err,threshold); - testspline1dunit_lconst(a, b, &c, lstep, &l10, &l11, &l12, _state); - testspline1dunit_lconst(a, b, &c, lstep/3, &l20, &l21, &l22, _state); - hserrors = hserrors||(ae_fp_greater(l10,1.0E-10)&&ae_fp_greater(l20/l10,1.2)); - hserrors = hserrors||(ae_fp_greater(l11,1.0E-10)&&ae_fp_greater(l21/l11,1.2)); - } - } - - /* - * Special linear spline test: - * test for linearity between x[i] and x[i+1] - */ - for(n=2; n<=maxn; n++) - { - ae_vector_set_length(&x, n-1+1, _state); - ae_vector_set_length(&y, n-1+1, _state); - - /* - * Prepare task - */ - a = (double)(-1); - b = (double)(1); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = a+(b-a)*i/(n-1); - y.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - spline1dbuildlinear(&x, &y, n, &c, _state); - - /* - * Test - */ - err = (double)(0); - for(k=0; k<=n-2; k++) - { - a = x.ptr.p_double[k]; - b = x.ptr.p_double[k+1]; - for(pass=1; pass<=passcount; pass++) - { - t = a+(b-a)*ae_randomreal(_state); - v = y.ptr.p_double[k]+(t-a)/(b-a)*(y.ptr.p_double[k+1]-y.ptr.p_double[k]); - err = ae_maxreal(err, ae_fabs(spline1dcalc(&c, t, _state)-v, _state), _state); - } - } - lserrors = lserrors||ae_fp_greater(err,threshold); - } - - /* - * Special Akima test: test outlier sensitivity - * Spline value at (x[i], x[i+1]) should depend from - * f[i-2], f[i-1], f[i], f[i+1], f[i+2], f[i+3] only. - */ - for(n=5; n<=maxn; n++) - { - ae_vector_set_length(&x, n-1+1, _state); - ae_vector_set_length(&y, n-1+1, _state); - ae_vector_set_length(&y2, n-1+1, _state); - - /* - * Prepare unperturbed Akima spline - */ - a = (double)(-1); - b = (double)(1); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = a+(b-a)*i/(n-1); - y.ptr.p_double[i] = ae_cos(1.3*ae_pi*x.ptr.p_double[i]+0.4, _state); - } - spline1dbuildakima(&x, &y, n, &c, _state); - - /* - * Process perturbed tasks - */ - err = (double)(0); - for(k=0; k<=n-1; k++) - { - ae_v_move(&y2.ptr.p_double[0], 1, &y.ptr.p_double[0], 1, ae_v_len(0,n-1)); - y2.ptr.p_double[k] = (double)(5); - spline1dbuildakima(&x, &y2, n, &c2, _state); - - /* - * Test left part independence - */ - if( k-3>=1 ) - { - a = (double)(-1); - b = x.ptr.p_double[k-3]; - for(pass=1; pass<=passcount; pass++) - { - t = a+(b-a)*ae_randomreal(_state); - err = ae_maxreal(err, ae_fabs(spline1dcalc(&c, t, _state)-spline1dcalc(&c2, t, _state), _state), _state); - } - } - - /* - * Test right part independence - */ - if( k+3<=n-2 ) - { - a = x.ptr.p_double[k+3]; - b = (double)(1); - for(pass=1; pass<=passcount; pass++) - { - t = a+(b-a)*ae_randomreal(_state); - err = ae_maxreal(err, ae_fabs(spline1dcalc(&c, t, _state)-spline1dcalc(&c2, t, _state), _state), _state); - } - } - } - aserrors = aserrors||ae_fp_greater(err,threshold); - } - - /* - * Differentiation, copy/unpack test - */ - for(n=2; n<=maxn; n++) - { - ae_vector_set_length(&x, n-1+1, _state); - ae_vector_set_length(&y, n-1+1, _state); - - /* - * Prepare cubic spline - */ - a = -1-ae_randomreal(_state); - b = 1+ae_randomreal(_state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = a+(b-a)*i/(n-1); - y.ptr.p_double[i] = ae_cos(1.3*ae_pi*x.ptr.p_double[i]+0.4, _state); - } - spline1dbuildcubic(&x, &y, n, 2, 0.0, 2, 0.0, &c, _state); - - /* - * Test diff - */ - err = (double)(0); - for(pass=1; pass<=passcount; pass++) - { - t = a+(b-a)*ae_randomreal(_state); - spline1ddiff(&c, t, &s, &ds, &d2s, _state); - vl = spline1dcalc(&c, t-h, _state); - vm = spline1dcalc(&c, t, _state); - vr = spline1dcalc(&c, t+h, _state); - err = ae_maxreal(err, ae_fabs(s-vm, _state), _state); - err = ae_maxreal(err, ae_fabs(ds-(vr-vl)/(2*h), _state), _state); - err = ae_maxreal(err, ae_fabs(d2s-(vr-2*vm+vl)/ae_sqr(h, _state), _state), _state); - } - dserrors = dserrors||ae_fp_greater(err,0.001); - - /* - * Test copy - */ - testspline1dunit_unsetspline1d(&c2, _state); - spline1dcopy(&c, &c2, _state); - err = (double)(0); - for(pass=1; pass<=passcount; pass++) - { - t = a+(b-a)*ae_randomreal(_state); - err = ae_maxreal(err, ae_fabs(spline1dcalc(&c, t, _state)-spline1dcalc(&c2, t, _state), _state), _state); - } - cperrors = cperrors||ae_fp_greater(err,threshold); - - /* - * Test unpack - */ - uperrors = uperrors||!testspline1dunit_testunpack(&c, &x, _state); - } - - /* - * Linear translation errors - */ - for(n=2; n<=maxn; n++) - { - - /* - * Prepare: - * * X, Y - grid points - * * XTest - test points - */ - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - a = -1-ae_randomreal(_state); - b = 1+ae_randomreal(_state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = a+(b-a)*(i+0.2*ae_randomreal(_state)-0.1)/(n-1); - y.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - ae_vector_set_length(&xtest, 5*n+2, _state); - for(i=0; i<=xtest.cnt-1; i++) - { - xtest.ptr.p_double[i] = a+(b-a)*(i-1)/(xtest.cnt-3); - } - splineindex = 0; - while(testspline1dunit_enumerateallsplines(&x, &y, n, &splineindex, &c, _state)) - { - - /* - * LinTransX, general A - */ - sa = 4*ae_randomreal(_state)-2; - sb = 2*ae_randomreal(_state)-1; - spline1dcopy(&c, &c2, _state); - spline1dlintransx(&c2, sa, sb, _state); - for(i=0; i<=xtest.cnt-1; i++) - { - lterrors = lterrors||ae_fp_greater(ae_fabs(spline1dcalc(&c, xtest.ptr.p_double[i], _state)-spline1dcalc(&c2, (xtest.ptr.p_double[i]-sb)/sa, _state), _state),threshold); - } - - /* - * LinTransX, special case: A=0 - */ - sb = 2*ae_randomreal(_state)-1; - spline1dcopy(&c, &c2, _state); - spline1dlintransx(&c2, (double)(0), sb, _state); - for(i=0; i<=xtest.cnt-1; i++) - { - lterrors = lterrors||ae_fp_greater(ae_fabs(spline1dcalc(&c, sb, _state)-spline1dcalc(&c2, xtest.ptr.p_double[i], _state), _state),threshold); - } - - /* - * LinTransY - */ - sa = 2*ae_randomreal(_state)-1; - sb = 2*ae_randomreal(_state)-1; - spline1dcopy(&c, &c2, _state); - spline1dlintransy(&c2, sa, sb, _state); - for(i=0; i<=xtest.cnt-1; i++) - { - lterrors = lterrors||ae_fp_greater(ae_fabs(sa*spline1dcalc(&c, xtest.ptr.p_double[i], _state)+sb-spline1dcalc(&c2, xtest.ptr.p_double[i], _state), _state),threshold); - } - } - } - - /* - * Testing integration. - * Three tests are performed: - * - * * approximate test (well behaved smooth function, many points, - * integration inside [a,b]), non-periodic spline - * - * * exact test (integration of parabola, outside of [a,b], non-periodic spline - * - * * approximate test for periodic splines. F(x)=cos(2*pi*x)+1. - * Period length is equals to 1.0, so all operations with - * multiples of period are done exactly. For each value of PERIOD - * we calculate and test integral at four points: - * - 0 < t0 < PERIOD - * - t1 = PERIOD-eps - * - t2 = PERIOD - * - t3 = PERIOD+eps - */ - err = (double)(0); - for(n=20; n<=35; n++) - { - ae_vector_set_length(&x, n-1+1, _state); - ae_vector_set_length(&y, n-1+1, _state); - for(pass=1; pass<=passcount; pass++) - { - - /* - * Prepare cubic spline - */ - a = -1-0.2*ae_randomreal(_state); - b = 1+0.2*ae_randomreal(_state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = a+(b-a)*i/(n-1); - y.ptr.p_double[i] = ae_sin(ae_pi*x.ptr.p_double[i]+0.4, _state)+ae_exp(x.ptr.p_double[i], _state); - } - bl = ae_pi*ae_cos(ae_pi*a+0.4, _state)+ae_exp(a, _state); - br = ae_pi*ae_cos(ae_pi*b+0.4, _state)+ae_exp(b, _state); - spline1dbuildcubic(&x, &y, n, 1, bl, 1, br, &c, _state); - - /* - * Test - */ - t = a+(b-a)*ae_randomreal(_state); - v = -ae_cos(ae_pi*a+0.4, _state)/ae_pi+ae_exp(a, _state); - v = -ae_cos(ae_pi*t+0.4, _state)/ae_pi+ae_exp(t, _state)-v; - v = v-spline1dintegrate(&c, t, _state); - err = ae_maxreal(err, ae_fabs(v, _state), _state); - } - } - ierrors = ierrors||ae_fp_greater(err,0.001); - p0 = 2*ae_randomreal(_state)-1; - p1 = 2*ae_randomreal(_state)-1; - p2 = 2*ae_randomreal(_state)-1; - a = -ae_randomreal(_state)-0.5; - b = ae_randomreal(_state)+0.5; - n = 2; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - ae_vector_set_length(&d, n, _state); - x.ptr.p_double[0] = a; - y.ptr.p_double[0] = p0+p1*a+p2*ae_sqr(a, _state); - d.ptr.p_double[0] = p1+2*p2*a; - x.ptr.p_double[1] = b; - y.ptr.p_double[1] = p0+p1*b+p2*ae_sqr(b, _state); - d.ptr.p_double[1] = p1+2*p2*b; - spline1dbuildhermite(&x, &y, &d, n, &c, _state); - bl = ae_minreal(a, b, _state)-ae_fabs(b-a, _state); - br = ae_minreal(a, b, _state)+ae_fabs(b-a, _state); - err = (double)(0); - for(pass=1; pass<=100; pass++) - { - t = bl+(br-bl)*ae_randomreal(_state); - v = p0*t+p1*ae_sqr(t, _state)/2+p2*ae_sqr(t, _state)*t/3-(p0*a+p1*ae_sqr(a, _state)/2+p2*ae_sqr(a, _state)*a/3); - v = v-spline1dintegrate(&c, t, _state); - err = ae_maxreal(err, ae_fabs(v, _state), _state); - } - ierrors = ierrors||ae_fp_greater(err,threshold); - n = 100; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = (double)i/(double)(n-1); - y.ptr.p_double[i] = ae_cos(2*ae_pi*x.ptr.p_double[i], _state)+1; - } - y.ptr.p_double[0] = (double)(2); - y.ptr.p_double[n-1] = (double)(2); - spline1dbuildcubic(&x, &y, n, -1, 0.0, -1, 0.0, &c, _state); - intab = spline1dintegrate(&c, 1.0, _state); - v = ae_randomreal(_state); - vr = spline1dintegrate(&c, v, _state); - ierrors = ierrors||ae_fp_greater(ae_fabs(intab-1, _state),0.001); - for(i=-10; i<=10; i++) - { - ierrors = ierrors||ae_fp_greater(ae_fabs(spline1dintegrate(&c, i+v, _state)-(i*intab+vr), _state),0.001); - ierrors = ierrors||ae_fp_greater(ae_fabs(spline1dintegrate(&c, i-1000*ae_machineepsilon, _state)-i*intab, _state),0.001); - ierrors = ierrors||ae_fp_greater(ae_fabs(spline1dintegrate(&c, (double)(i), _state)-i*intab, _state),0.001); - ierrors = ierrors||ae_fp_greater(ae_fabs(spline1dintegrate(&c, i+1000*ae_machineepsilon, _state)-i*intab, _state),0.001); - } - - /* - * Test monotone cubic Hermit interpolation - */ - monotoneerr = testspline1dunit_testmonotonespline(_state); - - /* - * Test fitting errors - */ - testspline1dunit_testsplinefitting(&fiterr, _state); - - /* - * report - */ - waserrors = ((((((((((lserrors||cserrors)||crserrors)||hserrors)||aserrors)||dserrors)||cperrors)||uperrors)||lterrors)||ierrors)||monotoneerr)||fiterr; - if( !silent ) - { - printf("TESTING SPLINE INTERPOLATION\n"); - - /* - * Normal tests - */ - printf("INTERPOLATION:\n"); - printf("* LINEAR SPLINE "); - if( lserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* CUBIC SPLINE "); - if( cserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* CATMULL-ROM SPLINE "); - if( crserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* HERMITE SPLINE "); - if( hserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* AKIMA SPLINE "); - if( aserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* MONOTONE SPLINE "); - if( monotoneerr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("FITTING: "); - if( fiterr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("DIFFERENTIATION TEST: "); - if( dserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("COPY/SERIALIZATION TEST: "); - if( cperrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("UNPACK TEST: "); - if( uperrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("LIN.TRANS. TEST: "); - if( lterrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("INTEGRATION TEST: "); - if( ierrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - - /* - * end - */ - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Lipschitz constants for spline itself, first and second derivatives. -*************************************************************************/ -static void testspline1dunit_lconst(double a, - double b, - spline1dinterpolant* c, - double lstep, - double* l0, - double* l1, - double* l2, - ae_state *_state) -{ - double t; - double vl; - double vm; - double vr; - double prevf; - double prevd; - double prevd2; - double f; - double d; - double d2; - - *l0 = 0; - *l1 = 0; - *l2 = 0; - - *l0 = (double)(0); - *l1 = (double)(0); - *l2 = (double)(0); - t = a-0.1; - vl = spline1dcalc(c, t-2*lstep, _state); - vm = spline1dcalc(c, t-lstep, _state); - vr = spline1dcalc(c, t, _state); - f = vm; - d = (vr-vl)/(2*lstep); - d2 = (vr-2*vm+vl)/ae_sqr(lstep, _state); - while(ae_fp_less_eq(t,b+0.1)) - { - prevf = f; - prevd = d; - prevd2 = d2; - vl = vm; - vm = vr; - vr = spline1dcalc(c, t+lstep, _state); - f = vm; - d = (vr-vl)/(2*lstep); - d2 = (vr-2*vm+vl)/ae_sqr(lstep, _state); - *l0 = ae_maxreal(*l0, ae_fabs((f-prevf)/lstep, _state), _state); - *l1 = ae_maxreal(*l1, ae_fabs((d-prevd)/lstep, _state), _state); - *l2 = ae_maxreal(*l2, ae_fabs((d2-prevd2)/lstep, _state), _state); - t = t+lstep; - } -} - - -/************************************************************************* -This function is used to enumerate all spline types which can be built -from given dataset. It should be used as follows: - -> -> init X, Y, N -> SplineIndex:=0; -> while EnumerateAllSplines(X, Y, N, SplineIndex, S) do -> begin -> do something with S -> end; -> - -On initial call EnumerateAllSplines accepts: -* dataset X, Y, number of points N (N>=2) -* SplineIndex, equal to 0 - -It returns: -* True, in case there is a spline type which corresponds to SplineIndex. - In this case S contains spline which was built using X/Y and spline type, - as specified by input value of SplineIndex. SplineIndex is advanced to - the next value. -* False, in case SplineIndex contains past-the-end value, spline is not built. - -This function tries different variants of linear/cubic, periodic/nonperiodic -splines. -*************************************************************************/ -static ae_bool testspline1dunit_enumerateallsplines(/* Real */ ae_vector* x, - /* Real */ ae_vector* y, - ae_int_t n, - ae_int_t* splineindex, - spline1dinterpolant* s, - ae_state *_state) -{ - ae_int_t idxoffs; - ae_bool result; - - _spline1dinterpolant_clear(s); - - ae_assert(*splineindex>=0, "Assertion failed", _state); - result = ae_false; - if( *splineindex==0 ) - { - - /* - * Linear spline - */ - spline1dbuildlinear(x, y, n, s, _state); - *splineindex = *splineindex+1; - result = ae_true; - return result; - } - else - { - if( *splineindex>=1&&*splineindex<11 ) - { - - /* - * Cubic spline, either periodic or non-periodic - */ - idxoffs = *splineindex-1; - if( idxoffs==9 ) - { - - /* - * Periodic spline - */ - spline1dbuildcubic(x, y, n, -1, 0.0, -1, 0.0, s, _state); - } - else - { - - /* - * Non-periodic spline - */ - spline1dbuildcubic(x, y, n, idxoffs/3, 2*ae_randomreal(_state)-1, idxoffs%3, 2*ae_randomreal(_state)-1, s, _state); - } - *splineindex = *splineindex+1; - result = ae_true; - return result; - } - } - return result; -} - - -/************************************************************************* -Unpack testing -*************************************************************************/ -static ae_bool testspline1dunit_testunpack(spline1dinterpolant* c, - /* Real */ ae_vector* x, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t n; - double err; - double t; - double v1; - double v2; - ae_int_t pass; - ae_int_t passcount; - ae_matrix tbl; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&tbl, 0, sizeof(tbl)); - ae_matrix_init(&tbl, 0, 0, DT_REAL, _state, ae_true); - - passcount = 20; - err = (double)(0); - spline1dunpack(c, &n, &tbl, _state); - for(i=0; i<=n-2; i++) - { - for(pass=1; pass<=passcount; pass++) - { - t = ae_randomreal(_state)*(tbl.ptr.pp_double[i][1]-tbl.ptr.pp_double[i][0]); - v1 = tbl.ptr.pp_double[i][2]+t*tbl.ptr.pp_double[i][3]+ae_sqr(t, _state)*tbl.ptr.pp_double[i][4]+t*ae_sqr(t, _state)*tbl.ptr.pp_double[i][5]; - v2 = spline1dcalc(c, tbl.ptr.pp_double[i][0]+t, _state); - err = ae_maxreal(err, ae_fabs(v1-v2, _state), _state); - } - } - for(i=0; i<=n-2; i++) - { - err = ae_maxreal(err, ae_fabs(x->ptr.p_double[i]-tbl.ptr.pp_double[i][0], _state), _state); - } - for(i=0; i<=n-2; i++) - { - err = ae_maxreal(err, ae_fabs(x->ptr.p_double[i+1]-tbl.ptr.pp_double[i][1], _state), _state); - } - result = ae_fp_less(err,100*ae_machineepsilon); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Unset spline, i.e. initialize it with random garbage -*************************************************************************/ -static void testspline1dunit_unsetspline1d(spline1dinterpolant* c, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector x; - ae_vector y; - ae_vector d; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&d, 0, sizeof(d)); - _spline1dinterpolant_clear(c); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&x, 2, _state); - ae_vector_set_length(&y, 2, _state); - ae_vector_set_length(&d, 2, _state); - x.ptr.p_double[0] = (double)(-1); - y.ptr.p_double[0] = ae_randomreal(_state); - d.ptr.p_double[0] = ae_randomreal(_state); - x.ptr.p_double[1] = (double)(1); - y.ptr.p_double[1] = ae_randomreal(_state); - d.ptr.p_double[1] = ae_randomreal(_state); - spline1dbuildhermite(&x, &y, &d, 2, c, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Unset spline, i.e. initialize it with random garbage -*************************************************************************/ -static void testspline1dunit_unsetreport(spline1dfitreport* rep, - ae_state *_state) -{ - - _spline1dfitreport_clear(rep); - - rep->taskrcond = ae_randomreal(_state); - rep->rmserror = ae_randomreal(_state); - rep->avgerror = ae_randomreal(_state); - rep->avgrelerror = ae_randomreal(_state); - rep->maxerror = ae_randomreal(_state); -} - - -/************************************************************************* -Tests that built spline is monotone. -*************************************************************************/ -static ae_bool testspline1dunit_testmonotonespline(ae_state *_state) -{ - ae_frame _frame_block; - spline1dinterpolant c; - spline1dinterpolant s2; - double c0; - double c1; - ae_vector x; - ae_vector y; - ae_vector d; - ae_int_t m; - ae_vector n; - ae_int_t alln; - ae_int_t shift; - double sign0; - double sign1; - double r; - double st; - double eps; - double delta; - double v; - double dv; - double d2v; - ae_int_t nseg; - ae_int_t npoints; - ae_int_t tp; - ae_int_t pass; - ae_int_t passcount; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t kmax; - ae_int_t l; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&c, 0, sizeof(c)); - memset(&s2, 0, sizeof(s2)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&d, 0, sizeof(d)); - memset(&n, 0, sizeof(n)); - _spline1dinterpolant_init(&c, _state, ae_true); - _spline1dinterpolant_init(&s2, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&n, 0, DT_INT, _state, ae_true); - - eps = 100*ae_machineepsilon; - - /* - * Special test - N=2. - * - * Following properties are tested: - * * monotone spline must be equal to the Hermite spline with - * zero derivative at the ends - * * monotone spline is constant beyond left/right boundaries - */ - ae_vector_set_length(&x, 2, _state); - ae_vector_set_length(&y, 2, _state); - ae_vector_set_length(&d, 2, _state); - x.ptr.p_double[0] = -0.1-ae_randomreal(_state); - y.ptr.p_double[0] = 2*ae_randomreal(_state)-1; - d.ptr.p_double[0] = 0.0; - x.ptr.p_double[1] = 0.1+ae_randomreal(_state); - y.ptr.p_double[1] = y.ptr.p_double[0]; - d.ptr.p_double[1] = 0.0; - spline1dbuildmonotone(&x, &y, 2, &c, _state); - spline1dbuildhermite(&x, &y, &d, 2, &s2, _state); - v = 2*ae_randomreal(_state)-1; - if( ae_fp_greater(ae_fabs(spline1dcalc(&c, v, _state)-spline1dcalc(&s2, v, _state), _state),eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - if( ae_fp_neq(spline1dcalc(&c, (double)(-5), _state),y.ptr.p_double[0]) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - if( ae_fp_neq(spline1dcalc(&c, (double)(5), _state),y.ptr.p_double[0]) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Special test - N=3, x=[0,1,2], y=[0,1,0]. - * Monotone spline must be equal to the Hermite spline with - * zero derivative at all points. - */ - ae_vector_set_length(&x, 3, _state); - ae_vector_set_length(&y, 3, _state); - ae_vector_set_length(&d, 3, _state); - x.ptr.p_double[0] = 0.0; - y.ptr.p_double[0] = 0.0; - d.ptr.p_double[0] = 0.0; - x.ptr.p_double[1] = 1.0; - y.ptr.p_double[1] = 1.0; - d.ptr.p_double[1] = 0.0; - x.ptr.p_double[2] = 2.0; - y.ptr.p_double[2] = 0.0; - d.ptr.p_double[2] = 0.0; - spline1dbuildmonotone(&x, &y, 3, &c, _state); - spline1dbuildhermite(&x, &y, &d, 3, &s2, _state); - for(i=0; i<=10; i++) - { - v = x.ptr.p_double[0]+(double)i/(double)10*(x.ptr.p_double[2]-x.ptr.p_double[0]); - if( ae_fp_greater(ae_fabs(spline1dcalc(&c, v, _state)-spline1dcalc(&s2, v, _state), _state),eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - - /* - * Special test - N=5, x=[0,1,2,3,4], y=[0,1,1,2,3]. - * - * 1) spline passes through all prescribed points - * 2) spline derivative at all points except x=3 is exactly zero - * 3) spline derivative at x=3 is 1.0 (within machine epsilon) - */ - ae_vector_set_length(&x, 5, _state); - ae_vector_set_length(&y, 5, _state); - x.ptr.p_double[0] = 0.0; - y.ptr.p_double[0] = 0.0; - x.ptr.p_double[1] = 1.0; - y.ptr.p_double[1] = 1.0; - x.ptr.p_double[2] = 2.0; - y.ptr.p_double[2] = 1.0; - x.ptr.p_double[3] = 3.0; - y.ptr.p_double[3] = 2.0; - x.ptr.p_double[4] = 4.0; - y.ptr.p_double[4] = 3.0; - spline1dbuildmonotone(&x, &y, 5, &c, _state); - for(i=0; i<=4; i++) - { - spline1ddiff(&c, x.ptr.p_double[i], &v, &dv, &d2v, _state); - if( ae_fp_greater(ae_fabs(v-y.ptr.p_double[i], _state),eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - if( (ae_fp_eq(x.ptr.p_double[i],3.0)&&ae_fp_greater(ae_fabs(dv-1.0, _state),eps))||(ae_fp_neq(x.ptr.p_double[i],3.0)&&ae_fp_neq(dv,(double)(0))) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - - /* - * Special test: - * * N=4 - * * three fixed points - (0,0), (1,1), (2,0) - * * one special point (x,y) with x in [0.1,0.9], y in [0.1,0.9] - * * monotonicity of the interpolant at [0,1] is checked with very small step 1/KMax - */ - ae_vector_set_length(&x, 4, _state); - ae_vector_set_length(&y, 4, _state); - x.ptr.p_double[0] = 0.0; - y.ptr.p_double[0] = 0.0; - x.ptr.p_double[2] = 1.0; - y.ptr.p_double[2] = 1.0; - x.ptr.p_double[3] = 2.0; - y.ptr.p_double[3] = 0.0; - for(i=1; i<=9; i++) - { - for(j=1; j<=9; j++) - { - x.ptr.p_double[1] = (double)i/(double)10; - y.ptr.p_double[1] = (double)j/(double)10; - spline1dbuildmonotone(&x, &y, 4, &c, _state); - kmax = 1000; - for(k=0; k<=kmax-1; k++) - { - if( ae_fp_greater(spline1dcalc(&c, (double)k/(double)kmax, _state),spline1dcalc(&c, (double)(k+1)/(double)kmax, _state)) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - - /* - * General case - */ - delta = (double)(0); - nseg = 10; - npoints = 15; - passcount = 30; - for(pass=1; pass<=passcount; pass++) - { - tp = ae_randominteger(6, _state)+4; - r = (double)(ae_randominteger(76, _state)+25); - m = ae_randominteger(nseg, _state)+1; - ae_vector_set_length(&n, m, _state); - alln = 0; - for(i=0; i<=m-1; i++) - { - n.ptr.p_int[i] = ae_randominteger(npoints, _state)+2; - alln = alln+n.ptr.p_int[i]; - } - ae_vector_set_length(&x, alln, _state); - ae_vector_set_length(&y, alln, _state); - x.ptr.p_double[0] = r*(2*ae_randomreal(_state)-1); - y.ptr.p_double[0] = r*(2*ae_randomreal(_state)-1); - - /* - * Builds monotone function - */ - st = 0.1+0.7*ae_randomreal(_state); - shift = 0; - sign0 = ae_pow((double)(-1), (double)(0), _state); - for(i=0; i<=m-1; i++) - { - for(j=1; j<=n.ptr.p_int[i]-1; j++) - { - x.ptr.p_double[shift+j] = x.ptr.p_double[shift+j-1]+st+ae_randomreal(_state); - delta = ae_maxreal(delta, x.ptr.p_double[shift+j]-x.ptr.p_double[shift+j-1], _state); - y.ptr.p_double[shift+j] = y.ptr.p_double[shift+j-1]+sign0*(st+ae_randomreal(_state)); - } - shift = shift+n.ptr.p_int[i]; - if( i!=m-1 ) - { - sign0 = ae_pow((double)(-1), (double)(i+1), _state); - x.ptr.p_double[shift] = x.ptr.p_double[shift-1]+st+ae_randomreal(_state); - y.ptr.p_double[shift] = y.ptr.p_double[shift-1]+sign0*ae_randomreal(_state); - } - } - delta = 3*delta; - spline1dbuildmonotone(&x, &y, alln, &c, _state); - - /* - * Check that built function is monotone - */ - shift = 0; - for(i=0; i<=m-1; i++) - { - for(j=1; j<=n.ptr.p_int[i]-1; j++) - { - st = (x.ptr.p_double[shift+j]-x.ptr.p_double[shift+j-1])/tp; - sign0 = y.ptr.p_double[shift+j]-y.ptr.p_double[shift+j-1]; - if( ae_fp_neq(sign0,(double)(0)) ) - { - sign0 = sign0/ae_fabs(sign0, _state); - } - for(l=0; l<=tp-1; l++) - { - c0 = spline1dcalc(&c, x.ptr.p_double[shift+j-1]+l*st, _state); - c1 = spline1dcalc(&c, x.ptr.p_double[shift+j-1]+(l+1)*st, _state); - sign1 = c1-c0; - if( ae_fp_neq(sign1,(double)(0)) ) - { - sign1 = sign1/ae_fabs(sign1, _state); - } - if( ae_fp_less(sign0*sign1,(double)(0)) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - c0 = spline1dcalc(&c, x.ptr.p_double[0]-delta, _state); - c1 = spline1dcalc(&c, x.ptr.p_double[0], _state); - if( ae_fp_greater(ae_fabs(c0-c1, _state),eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - c0 = spline1dcalc(&c, x.ptr.p_double[alln-1], _state); - c1 = spline1dcalc(&c, x.ptr.p_double[alln-1]+delta, _state); - if( ae_fp_greater(ae_fabs(c0-c1, _state),eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Builds constant function - */ - y.ptr.p_double[0] = r*(2*ae_randomreal(_state)-1); - for(i=1; i<=alln-1; i++) - { - y.ptr.p_double[i] = y.ptr.p_double[0]; - } - spline1dbuildmonotone(&x, &y, alln, &c, _state); - shift = 0; - for(i=0; i<=m-1; i++) - { - for(j=1; j<=n.ptr.p_int[i]-1; j++) - { - st = (x.ptr.p_double[shift+j]-x.ptr.p_double[shift+j-1])/tp; - sign0 = y.ptr.p_double[shift+j]-y.ptr.p_double[shift+j-1]; - for(l=0; l<=tp-1; l++) - { - c0 = spline1dcalc(&c, x.ptr.p_double[shift+j-1]+l*st, _state); - c1 = spline1dcalc(&c, x.ptr.p_double[shift+j-1]+(l+1)*st, _state); - sign1 = c1-c0; - if( ae_fp_greater(sign0,eps)||ae_fp_greater(sign1,eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -static void testspline1dunit_testsplinefitting(ae_bool* fiterrors, - ae_state *_state) -{ - ae_frame _frame_block; - double threshold; - double nonstrictthreshold; - ae_int_t passcount; - ae_int_t n; - ae_int_t m; - ae_int_t i; - ae_int_t k; - ae_int_t pass; - ae_vector x; - ae_vector y; - ae_vector w; - ae_vector w2; - ae_vector xc; - ae_vector yc; - ae_vector d; - ae_vector dc; - spline1dinterpolant c; - spline1dinterpolant c2; - spline1dfitreport rep; - spline1dfitreport rep2; - double s; - double v; - double v1; - double v2; - double u; - double u1; - double u2; - double a; - double b; - double refrms; - double refavg; - double refavgrel; - double refmax; - double rho; - hqrndstate rs; - double prevresiduals; - double prevpenalty; - double residuals; - double penalty; - double mxd2; - ae_int_t testtype; - double lipschitzeps; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&w, 0, sizeof(w)); - memset(&w2, 0, sizeof(w2)); - memset(&xc, 0, sizeof(xc)); - memset(&yc, 0, sizeof(yc)); - memset(&d, 0, sizeof(d)); - memset(&dc, 0, sizeof(dc)); - memset(&c, 0, sizeof(c)); - memset(&c2, 0, sizeof(c2)); - memset(&rep, 0, sizeof(rep)); - memset(&rep2, 0, sizeof(rep2)); - memset(&rs, 0, sizeof(rs)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dc, 0, DT_INT, _state, ae_true); - _spline1dinterpolant_init(&c, _state, ae_true); - _spline1dinterpolant_init(&c2, _state, ae_true); - _spline1dfitreport_init(&rep, _state, ae_true); - _spline1dfitreport_init(&rep2, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Values: - * * pass count - * * threshold - for tests which must be satisfied exactly - * * nonstrictthreshold - for approximate tests - */ - passcount = 20; - threshold = 10000*ae_machineepsilon; - nonstrictthreshold = 1.0E-6; - lipschitzeps = 1.0E-6; - *fiterrors = ae_false; - - /* - * check basic properties of penalized splines which are - * preserved independently of Rho parameter. - */ - for(m=4; m<=10; m++) - { - for(k=-5; k<=5; k++) - { - rho = (double)(k); - - /* - * when we have two points (even with different weights), - * resulting spline must be equal to the straight line - */ - ae_vector_set_length(&x, 2, _state); - ae_vector_set_length(&y, 2, _state); - ae_vector_set_length(&w, 2, _state); - x.ptr.p_double[0] = -0.5-ae_randomreal(_state); - y.ptr.p_double[0] = 0.5+ae_randomreal(_state); - w.ptr.p_double[0] = 1+ae_randomreal(_state); - x.ptr.p_double[1] = 0.5+ae_randomreal(_state); - y.ptr.p_double[1] = 0.5+ae_randomreal(_state); - w.ptr.p_double[1] = 1+ae_randomreal(_state); - testspline1dunit_unsetspline1d(&c, _state); - testspline1dunit_unsetreport(&rep, _state); - spline1dfit(&x, &y, 2, m, ae_pow(10.0, rho, _state), &c, &rep, _state); - v = 2*ae_randomreal(_state)-1; - v1 = (v-x.ptr.p_double[0])/(x.ptr.p_double[1]-x.ptr.p_double[0])*y.ptr.p_double[1]+(v-x.ptr.p_double[1])/(x.ptr.p_double[0]-x.ptr.p_double[1])*y.ptr.p_double[0]; - ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(v1-spline1dcalc(&c, v, _state), _state),threshold), __FILE__, __LINE__, "testspline1dunit.ap:1507"); - ae_set_error_flag(fiterrors, ae_fp_greater(rep.rmserror,threshold), __FILE__, __LINE__, "testspline1dunit.ap:1508"); - ae_set_error_flag(fiterrors, ae_fp_greater(rep.avgerror,threshold), __FILE__, __LINE__, "testspline1dunit.ap:1509"); - ae_set_error_flag(fiterrors, ae_fp_greater(rep.maxerror,threshold), __FILE__, __LINE__, "testspline1dunit.ap:1510"); - } - } - - /* - * Test spline ability to reproduce target: - * * a penalized spline with M=N and nearly zero Rho must pass - * through all points on equidistant grid - * * a penalized spline with M about 5*N and sufficiently small - * Rho must pass through all points on equidistant grid - * In both cases spline must be C0, C1 and C2 continuous. - */ - for(n=2; n<=20; n++) - { - - /* - * Fit - */ - m = n; - rho = (double)(-15); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = (double)i/(double)(n-1); - y.ptr.p_double[i] = ae_randomreal(_state)-0.5; - } - testspline1dunit_unsetspline1d(&c, _state); - testspline1dunit_unsetreport(&rep, _state); - spline1dfit(&x, &y, n, m, ae_pow((double)(10), rho, _state), &c, &rep, _state); - - /* - * Test that spline passes through all the points - */ - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(y.ptr.p_double[i]-spline1dcalc(&c, x.ptr.p_double[i], _state), _state),nonstrictthreshold), __FILE__, __LINE__, "testspline1dunit.ap:1543"); - } - ae_set_error_flag(fiterrors, ae_fp_greater(rep.rmserror,nonstrictthreshold), __FILE__, __LINE__, "testspline1dunit.ap:1544"); - ae_set_error_flag(fiterrors, ae_fp_greater(rep.avgerror,nonstrictthreshold), __FILE__, __LINE__, "testspline1dunit.ap:1545"); - ae_set_error_flag(fiterrors, ae_fp_greater(rep.maxerror,nonstrictthreshold), __FILE__, __LINE__, "testspline1dunit.ap:1546"); - - /* - * Test continuity properties - */ - s = 0.01*((double)1/(double)m); - testspline1dunit_lconst((double)(0), (double)(1), &c, s, &u, &u1, &u2, _state); - testspline1dunit_lconst((double)(0), (double)(1), &c, s/2, &v, &v1, &v2, _state); - ae_set_error_flag(fiterrors, ae_fp_greater(v/(u+lipschitzeps),1.2), __FILE__, __LINE__, "testspline1dunit.ap:1555"); - ae_set_error_flag(fiterrors, ae_fp_greater(v1/(u1+lipschitzeps*m),1.2), __FILE__, __LINE__, "testspline1dunit.ap:1556"); - ae_set_error_flag(fiterrors, ae_fp_greater(v2/(u2+lipschitzeps*ae_sqr((double)(m), _state)),1.2), __FILE__, __LINE__, "testspline1dunit.ap:1557"); - } - for(n=2; n<=20; n++) - { - m = 5*n; - rho = (double)(-10); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - ae_vector_set_length(&w, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = (double)i/(double)(n-1); - y.ptr.p_double[i] = ae_randomreal(_state); - w.ptr.p_double[i] = 0.1+ae_randomreal(_state); - } - testspline1dunit_unsetspline1d(&c, _state); - testspline1dunit_unsetreport(&rep, _state); - spline1dfit(&x, &y, n, m, ae_pow((double)(10), rho, _state), &c, &rep, _state); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(y.ptr.p_double[i]-spline1dcalc(&c, x.ptr.p_double[i], _state), _state),nonstrictthreshold), __FILE__, __LINE__, "testspline1dunit.ap:1576"); - } - ae_set_error_flag(fiterrors, ae_fp_greater(rep.rmserror,nonstrictthreshold), __FILE__, __LINE__, "testspline1dunit.ap:1577"); - ae_set_error_flag(fiterrors, ae_fp_greater(rep.avgerror,nonstrictthreshold), __FILE__, __LINE__, "testspline1dunit.ap:1578"); - ae_set_error_flag(fiterrors, ae_fp_greater(rep.maxerror,nonstrictthreshold), __FILE__, __LINE__, "testspline1dunit.ap:1579"); - - /* - * Test continuity properties - */ - s = 0.01*((double)1/(double)m); - testspline1dunit_lconst((double)(0), (double)(1), &c, s, &u, &u1, &u2, _state); - testspline1dunit_lconst((double)(0), (double)(1), &c, s/2, &v, &v1, &v2, _state); - ae_set_error_flag(fiterrors, ae_fp_greater(v/(u+lipschitzeps),1.2), __FILE__, __LINE__, "testspline1dunit.ap:1588"); - ae_set_error_flag(fiterrors, ae_fp_greater(v1/(u1+lipschitzeps*m),1.2), __FILE__, __LINE__, "testspline1dunit.ap:1589"); - ae_set_error_flag(fiterrors, ae_fp_greater(v2/(u2+lipschitzeps*ae_sqr((double)(m), _state)),1.2), __FILE__, __LINE__, "testspline1dunit.ap:1590"); - } - - /* - * Test smoothing properties: a sequence of problems with increasing Rho - * results in residuals monotonically increasing and nonlinearity penalty - * monotonically decreasing. - * - * This test is performed twice: first time for M<>N - */ - for(testtype=0; testtype<=1; testtype++) - { - if( testtype==0 ) - { - n = 100; - m = 10; - } - else - { - n = 10; - m = 100; - } - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = hqrndnormal(&rs, _state); - y.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - a = x.ptr.p_double[0]; - b = x.ptr.p_double[0]; - for(i=1; i<=n-1; i++) - { - a = ae_minreal(a, x.ptr.p_double[i], _state); - b = ae_maxreal(b, x.ptr.p_double[i], _state); - } - prevresiduals = (double)(0); - prevpenalty = ae_maxrealnumber; - rho = (double)(-4); - while(ae_fp_less_eq(rho,(double)(4))) - { - - /* - * Fit spline - */ - testspline1dunit_unsetspline1d(&c, _state); - testspline1dunit_unsetreport(&rep, _state); - spline1dfit(&x, &y, n, m, ae_pow((double)(10), rho, _state), &c, &rep, _state); - - /* - * Test continuity properties - */ - s = 0.01*((b-a)/m); - testspline1dunit_lconst(a, b, &c, s, &u, &u1, &u2, _state); - testspline1dunit_lconst(a, b, &c, s/2, &v, &v1, &v2, _state); - ae_set_error_flag(fiterrors, ae_fp_greater(v/(u+lipschitzeps),1.2), __FILE__, __LINE__, "testspline1dunit.ap:1645"); - ae_set_error_flag(fiterrors, ae_fp_greater(v1/(u1+lipschitzeps*m),1.2), __FILE__, __LINE__, "testspline1dunit.ap:1646"); - ae_set_error_flag(fiterrors, ae_fp_greater(v2/(u2+lipschitzeps*ae_sqr((double)(m), _state)),1.2), __FILE__, __LINE__, "testspline1dunit.ap:1647"); - - /* - * Compute residuals and penalty - */ - residuals = (double)(0); - for(i=0; i<=n-1; i++) - { - residuals = residuals+ae_sqr(spline1dcalc(&c, x.ptr.p_double[i], _state)-y.ptr.p_double[i], _state); - } - residuals = residuals/n; - penalty = (double)(0); - mxd2 = (double)(0); - k = 100*m; - for(i=0; i<=k; i++) - { - spline1ddiff(&c, a+(b-a)*i/k, &v, &v1, &v2, _state); - penalty = penalty+ae_sqr(v2, _state); - mxd2 = ae_maxreal(mxd2, ae_fabs(v2, _state), _state); - } - penalty = penalty/(k+1); - - /* - * Compare with previous, update previous, update Rho - * - * Write('%.15e %.15e %.15e\n', Residuals, Penalty, MxD2); - */ - ae_set_error_flag(fiterrors, ae_fp_less_eq(residuals,prevresiduals), __FILE__, __LINE__, "testspline1dunit.ap:1673"); - ae_set_error_flag(fiterrors, ae_fp_greater_eq(penalty,prevpenalty), __FILE__, __LINE__, "testspline1dunit.ap:1674"); - prevresiduals = residuals; - prevpenalty = penalty; - rho = rho+1; - } - ae_set_error_flag(fiterrors, ae_fp_greater_eq(penalty,1.0E-6), __FILE__, __LINE__, "testspline1dunit.ap:1679"); - ae_set_error_flag(fiterrors, ae_fp_greater_eq(mxd2,1.0E-3), __FILE__, __LINE__, "testspline1dunit.ap:1680"); - } - - /* - * Special test which allows to distinguish "true smoothing" from - * basic regularization enforced upon spline coefficients. - */ - n = 4; - m = 100; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - x.ptr.p_double[0] = (double)(-2); - x.ptr.p_double[1] = (double)(-1); - x.ptr.p_double[2] = (double)(1); - x.ptr.p_double[3] = (double)(2); - y.ptr.p_double[0] = (double)(-1); - y.ptr.p_double[1] = (double)(1); - y.ptr.p_double[2] = (double)(1); - y.ptr.p_double[3] = (double)(-1); - rho = (double)(-5); - spline1dfit(&x, &y, n, m, ae_pow((double)(10), rho, _state), &c, &rep, _state); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(spline1dcalc(&c, x.ptr.p_double[i], _state)-y.ptr.p_double[i], _state),0.0001), __FILE__, __LINE__, "testspline1dunit.ap:1702"); - } - ae_set_error_flag(fiterrors, ae_fp_less(spline1dcalc(&c, (double)(0), _state),1.000), __FILE__, __LINE__, "testspline1dunit.ap:1703"); - - /* - * Check correctness of error reports - */ - for(pass=1; pass<=passcount; pass++) - { - ae_assert(passcount>=2, "PassCount should be 2 or greater!", _state); - - /* - * solve simple task (all X[] are the same, Y[] are specially - * calculated to ensure simple form of all types of errors) - * and check correctness of the errors calculated by subroutines - * - * First pass is done with zero Y[], other passes - with random Y[]. - * It should test both ability to correctly calculate errors and - * ability to not fail while working with zeros :) - */ - n = 4; - if( pass==1 ) - { - v1 = (double)(0); - v2 = (double)(0); - v = (double)(0); - } - else - { - v1 = ae_randomreal(_state); - v2 = ae_randomreal(_state); - v = 1+ae_randomreal(_state); - } - ae_vector_set_length(&x, 4, _state); - ae_vector_set_length(&y, 4, _state); - ae_vector_set_length(&w, 4, _state); - x.ptr.p_double[0] = (double)(0); - y.ptr.p_double[0] = v-v2; - w.ptr.p_double[0] = (double)(1); - x.ptr.p_double[1] = (double)(0); - y.ptr.p_double[1] = v-v1; - w.ptr.p_double[1] = (double)(1); - x.ptr.p_double[2] = (double)(0); - y.ptr.p_double[2] = v+v1; - w.ptr.p_double[2] = (double)(1); - x.ptr.p_double[3] = (double)(0); - y.ptr.p_double[3] = v+v2; - w.ptr.p_double[3] = (double)(1); - refrms = ae_sqrt((ae_sqr(v1, _state)+ae_sqr(v2, _state))/2, _state); - refavg = (ae_fabs(v1, _state)+ae_fabs(v2, _state))/2; - if( pass==1 ) - { - refavgrel = (double)(0); - } - else - { - refavgrel = 0.25*(ae_fabs(v2, _state)/ae_fabs(v-v2, _state)+ae_fabs(v1, _state)/ae_fabs(v-v1, _state)+ae_fabs(v1, _state)/ae_fabs(v+v1, _state)+ae_fabs(v2, _state)/ae_fabs(v+v2, _state)); - } - refmax = ae_maxreal(v1, v2, _state); - spline1dfit(&x, &y, 4, 4, 0.0, &c, &rep, _state); - s = spline1dcalc(&c, (double)(0), _state); - ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(s-v, _state),threshold), __FILE__, __LINE__, "testspline1dunit.ap:1758"); - ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state),threshold), __FILE__, __LINE__, "testspline1dunit.ap:1759"); - ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state),threshold), __FILE__, __LINE__, "testspline1dunit.ap:1760"); - ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state),threshold), __FILE__, __LINE__, "testspline1dunit.ap:1761"); - ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(rep.maxerror-refmax, _state),threshold), __FILE__, __LINE__, "testspline1dunit.ap:1762"); - } - ae_frame_leave(_state); -} - - - -static void testparametricunit_testrdp(ae_bool* errorflag, - ae_state *_state); -static void testparametricunit_unsetp2(pspline2interpolant* p, - ae_state *_state); -static void testparametricunit_unsetp3(pspline3interpolant* p, - ae_state *_state); - - - - - -ae_bool testparametric(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_bool waserrors; - ae_bool p2errors; - ae_bool p3errors; - ae_bool rdperrors; - double nonstrictthreshold; - double threshold; - ae_int_t maxn; - ae_int_t periodicity; - ae_int_t skind; - ae_int_t pkind; - ae_bool periodic; - double a; - double b; - ae_int_t n; - ae_int_t tmpn; - ae_int_t i; - double vx; - double vy; - double vz; - double vx2; - double vy2; - double vz2; - double vdx; - double vdy; - double vdz; - double vdx2; - double vdy2; - double vdz2; - double vd2x; - double vd2y; - double vd2z; - double vd2x2; - double vd2y2; - double vd2z2; - double v0; - double v1; - ae_vector x; - ae_vector y; - ae_vector z; - ae_vector t; - ae_vector t2; - ae_vector t3; - ae_matrix xy; - ae_matrix xyz; - pspline2interpolant p2; - pspline3interpolant p3; - spline1dinterpolant s; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&z, 0, sizeof(z)); - memset(&t, 0, sizeof(t)); - memset(&t2, 0, sizeof(t2)); - memset(&t3, 0, sizeof(t3)); - memset(&xy, 0, sizeof(xy)); - memset(&xyz, 0, sizeof(xyz)); - memset(&p2, 0, sizeof(p2)); - memset(&p3, 0, sizeof(p3)); - memset(&s, 0, sizeof(s)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&z, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t3, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xyz, 0, 0, DT_REAL, _state, ae_true); - _pspline2interpolant_init(&p2, _state, ae_true); - _pspline3interpolant_init(&p3, _state, ae_true); - _spline1dinterpolant_init(&s, _state, ae_true); - - waserrors = ae_false; - maxn = 10; - threshold = 10000*ae_machineepsilon; - nonstrictthreshold = 0.00001; - p2errors = ae_false; - p3errors = ae_false; - rdperrors = ae_false; - testparametricunit_testrdp(&rdperrors, _state); - - /* - * Test basic properties of 2- and 3-dimensional splines: - * * PSpline2ParameterValues() properties - * * values at nodes - * * for periodic splines - periodicity properties - * - * Variables used: - * * N points count - * * SKind spline - * * PKind parameterization - * * Periodicity whether we have periodic spline or not - */ - for(n=2; n<=maxn; n++) - { - for(skind=0; skind<=2; skind++) - { - for(pkind=0; pkind<=2; pkind++) - { - for(periodicity=0; periodicity<=1; periodicity++) - { - periodic = periodicity==1; - - /* - * skip unsupported combinations of parameters - */ - if( periodic&&n<3 ) - { - continue; - } - if( periodic&&skind==0 ) - { - continue; - } - if( n<5&&skind==0 ) - { - continue; - } - - /* - * init - */ - ae_matrix_set_length(&xy, n, 2, _state); - ae_matrix_set_length(&xyz, n, 3, _state); - taskgenint1dequidist((double)(-1), (double)(1), n, &t2, &x, _state); - ae_v_move(&xy.ptr.pp_double[0][0], xy.stride, &x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&xyz.ptr.pp_double[0][0], xyz.stride, &x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - taskgenint1dequidist((double)(-1), (double)(1), n, &t2, &y, _state); - ae_v_move(&xy.ptr.pp_double[0][1], xy.stride, &y.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&xyz.ptr.pp_double[0][1], xyz.stride, &y.ptr.p_double[0], 1, ae_v_len(0,n-1)); - taskgenint1dequidist((double)(-1), (double)(1), n, &t2, &z, _state); - ae_v_move(&xyz.ptr.pp_double[0][2], xyz.stride, &z.ptr.p_double[0], 1, ae_v_len(0,n-1)); - testparametricunit_unsetp2(&p2, _state); - testparametricunit_unsetp3(&p3, _state); - if( periodic ) - { - pspline2buildperiodic(&xy, n, skind, pkind, &p2, _state); - pspline3buildperiodic(&xyz, n, skind, pkind, &p3, _state); - } - else - { - pspline2build(&xy, n, skind, pkind, &p2, _state); - pspline3build(&xyz, n, skind, pkind, &p3, _state); - } - - /* - * PSpline2ParameterValues() properties - */ - pspline2parametervalues(&p2, &tmpn, &t2, _state); - if( tmpn!=n ) - { - p2errors = ae_true; - continue; - } - pspline3parametervalues(&p3, &tmpn, &t3, _state); - if( tmpn!=n ) - { - p3errors = ae_true; - continue; - } - p2errors = p2errors||ae_fp_neq(t2.ptr.p_double[0],(double)(0)); - p3errors = p3errors||ae_fp_neq(t3.ptr.p_double[0],(double)(0)); - for(i=1; i<=n-1; i++) - { - p2errors = p2errors||ae_fp_less_eq(t2.ptr.p_double[i],t2.ptr.p_double[i-1]); - p3errors = p3errors||ae_fp_less_eq(t3.ptr.p_double[i],t3.ptr.p_double[i-1]); - } - if( periodic ) - { - p2errors = p2errors||ae_fp_greater_eq(t2.ptr.p_double[n-1],(double)(1)); - p3errors = p3errors||ae_fp_greater_eq(t3.ptr.p_double[n-1],(double)(1)); - } - else - { - p2errors = p2errors||ae_fp_neq(t2.ptr.p_double[n-1],(double)(1)); - p3errors = p3errors||ae_fp_neq(t3.ptr.p_double[n-1],(double)(1)); - } - - /* - * Now we have parameter values stored at T, - * and want to test whether the actully correspond to - * points - */ - for(i=0; i<=n-1; i++) - { - - /* - * 2-dimensional test - */ - pspline2calc(&p2, t2.ptr.p_double[i], &vx, &vy, _state); - p2errors = p2errors||ae_fp_greater(ae_fabs(vx-x.ptr.p_double[i], _state),threshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vy-y.ptr.p_double[i], _state),threshold); - - /* - * 3-dimensional test - */ - pspline3calc(&p3, t3.ptr.p_double[i], &vx, &vy, &vz, _state); - p3errors = p3errors||ae_fp_greater(ae_fabs(vx-x.ptr.p_double[i], _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vy-y.ptr.p_double[i], _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vz-z.ptr.p_double[i], _state),threshold); - } - - /* - * Test periodicity (if needed) - */ - if( periodic ) - { - - /* - * periodicity at nodes - */ - for(i=0; i<=n-1; i++) - { - - /* - * 2-dimensional test - */ - pspline2calc(&p2, t2.ptr.p_double[i]+ae_randominteger(10, _state)-5, &vx, &vy, _state); - p2errors = p2errors||ae_fp_greater(ae_fabs(vx-x.ptr.p_double[i], _state),threshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vy-y.ptr.p_double[i], _state),threshold); - pspline2diff(&p2, t2.ptr.p_double[i]+ae_randominteger(10, _state)-5, &vx, &vdx, &vy, &vdy, _state); - p2errors = p2errors||ae_fp_greater(ae_fabs(vx-x.ptr.p_double[i], _state),threshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vy-y.ptr.p_double[i], _state),threshold); - pspline2diff2(&p2, t2.ptr.p_double[i]+ae_randominteger(10, _state)-5, &vx, &vdx, &vd2x, &vy, &vdy, &vd2y, _state); - p2errors = p2errors||ae_fp_greater(ae_fabs(vx-x.ptr.p_double[i], _state),threshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vy-y.ptr.p_double[i], _state),threshold); - - /* - * 3-dimensional test - */ - pspline3calc(&p3, t3.ptr.p_double[i]+ae_randominteger(10, _state)-5, &vx, &vy, &vz, _state); - p3errors = p3errors||ae_fp_greater(ae_fabs(vx-x.ptr.p_double[i], _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vy-y.ptr.p_double[i], _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vz-z.ptr.p_double[i], _state),threshold); - pspline3diff(&p3, t3.ptr.p_double[i]+ae_randominteger(10, _state)-5, &vx, &vdx, &vy, &vdy, &vz, &vdz, _state); - p3errors = p3errors||ae_fp_greater(ae_fabs(vx-x.ptr.p_double[i], _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vy-y.ptr.p_double[i], _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vz-z.ptr.p_double[i], _state),threshold); - pspline3diff2(&p3, t3.ptr.p_double[i]+ae_randominteger(10, _state)-5, &vx, &vdx, &vd2x, &vy, &vdy, &vd2y, &vz, &vdz, &vd2z, _state); - p3errors = p3errors||ae_fp_greater(ae_fabs(vx-x.ptr.p_double[i], _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vy-y.ptr.p_double[i], _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vz-z.ptr.p_double[i], _state),threshold); - } - - /* - * periodicity between nodes - */ - v0 = ae_randomreal(_state); - pspline2calc(&p2, v0, &vx, &vy, _state); - pspline2calc(&p2, v0+ae_randominteger(10, _state)-5, &vx2, &vy2, _state); - p2errors = p2errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold); - pspline3calc(&p3, v0, &vx, &vy, &vz, _state); - pspline3calc(&p3, v0+ae_randominteger(10, _state)-5, &vx2, &vy2, &vz2, _state); - p3errors = p3errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vz-vz2, _state),threshold); - - /* - * near-boundary test for continuity of function values and derivatives: - * 2-dimensional curve - */ - ae_assert(skind==1||skind==2, "TEST: unexpected spline type!", _state); - v0 = 100*ae_machineepsilon; - v1 = 1-v0; - pspline2calc(&p2, v0, &vx, &vy, _state); - pspline2calc(&p2, v1, &vx2, &vy2, _state); - p2errors = p2errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold); - pspline2diff(&p2, v0, &vx, &vdx, &vy, &vdy, _state); - pspline2diff(&p2, v1, &vx2, &vdx2, &vy2, &vdy2, _state); - p2errors = p2errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vdx-vdx2, _state),nonstrictthreshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vdy-vdy2, _state),nonstrictthreshold); - pspline2diff2(&p2, v0, &vx, &vdx, &vd2x, &vy, &vdy, &vd2y, _state); - pspline2diff2(&p2, v1, &vx2, &vdx2, &vd2x2, &vy2, &vdy2, &vd2y2, _state); - p2errors = p2errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vdx-vdx2, _state),nonstrictthreshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vdy-vdy2, _state),nonstrictthreshold); - if( skind==2 ) - { - - /* - * second derivative test only for cubic splines - */ - p2errors = p2errors||ae_fp_greater(ae_fabs(vd2x-vd2x2, _state),nonstrictthreshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vd2y-vd2y2, _state),nonstrictthreshold); - } - - /* - * near-boundary test for continuity of function values and derivatives: - * 3-dimensional curve - */ - ae_assert(skind==1||skind==2, "TEST: unexpected spline type!", _state); - v0 = 100*ae_machineepsilon; - v1 = 1-v0; - pspline3calc(&p3, v0, &vx, &vy, &vz, _state); - pspline3calc(&p3, v1, &vx2, &vy2, &vz2, _state); - p3errors = p3errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vz-vz2, _state),threshold); - pspline3diff(&p3, v0, &vx, &vdx, &vy, &vdy, &vz, &vdz, _state); - pspline3diff(&p3, v1, &vx2, &vdx2, &vy2, &vdy2, &vz2, &vdz2, _state); - p3errors = p3errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vz-vz2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vdx-vdx2, _state),nonstrictthreshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vdy-vdy2, _state),nonstrictthreshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vdz-vdz2, _state),nonstrictthreshold); - pspline3diff2(&p3, v0, &vx, &vdx, &vd2x, &vy, &vdy, &vd2y, &vz, &vdz, &vd2z, _state); - pspline3diff2(&p3, v1, &vx2, &vdx2, &vd2x2, &vy2, &vdy2, &vd2y2, &vz2, &vdz2, &vd2z2, _state); - p3errors = p3errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vz-vz2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vdx-vdx2, _state),nonstrictthreshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vdy-vdy2, _state),nonstrictthreshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vdz-vdz2, _state),nonstrictthreshold); - if( skind==2 ) - { - - /* - * second derivative test only for cubic splines - */ - p3errors = p3errors||ae_fp_greater(ae_fabs(vd2x-vd2x2, _state),nonstrictthreshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vd2y-vd2y2, _state),nonstrictthreshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vd2z-vd2z2, _state),nonstrictthreshold); - } - } - } - } - } - } - - /* - * Test differentiation, tangents, calculation between nodes. - * - * Because differentiation is done in parameterization/spline/periodicity - * oblivious manner, we don't have to test all possible combinations - * of spline types and parameterizations. - * - * Actually we test special combination with properties which allow us - * to easily solve this problem: - * * 2 (3) variables - * * first variable is sampled from equidistant grid on [0,1] - * * other variables are random - * * uniform parameterization is used - * * periodicity - none - * * spline type - any (we use cubic splines) - * Same problem allows us to test calculation BETWEEN nodes. - */ - for(n=2; n<=maxn; n++) - { - - /* - * init - */ - ae_matrix_set_length(&xy, n, 2, _state); - ae_matrix_set_length(&xyz, n, 3, _state); - taskgenint1dequidist((double)(0), (double)(1), n, &t, &x, _state); - ae_v_move(&xy.ptr.pp_double[0][0], xy.stride, &x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&xyz.ptr.pp_double[0][0], xyz.stride, &x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - taskgenint1dequidist((double)(0), (double)(1), n, &t, &y, _state); - ae_v_move(&xy.ptr.pp_double[0][1], xy.stride, &y.ptr.p_double[0], 1, ae_v_len(0,n-1)); - ae_v_move(&xyz.ptr.pp_double[0][1], xyz.stride, &y.ptr.p_double[0], 1, ae_v_len(0,n-1)); - taskgenint1dequidist((double)(0), (double)(1), n, &t, &z, _state); - ae_v_move(&xyz.ptr.pp_double[0][2], xyz.stride, &z.ptr.p_double[0], 1, ae_v_len(0,n-1)); - testparametricunit_unsetp2(&p2, _state); - testparametricunit_unsetp3(&p3, _state); - pspline2build(&xy, n, 2, 0, &p2, _state); - pspline3build(&xyz, n, 2, 0, &p3, _state); - - /* - * Test 2D/3D spline: - * * build non-parametric cubic spline from T and X/Y - * * calculate its value and derivatives at V0 - * * compare with Spline2Calc/Spline2Diff/Spline2Diff2 - * Because of task properties both variants should - * return same answer. - */ - v0 = ae_randomreal(_state); - spline1dbuildcubic(&t, &x, n, 0, 0.0, 0, 0.0, &s, _state); - spline1ddiff(&s, v0, &vx2, &vdx2, &vd2x2, _state); - spline1dbuildcubic(&t, &y, n, 0, 0.0, 0, 0.0, &s, _state); - spline1ddiff(&s, v0, &vy2, &vdy2, &vd2y2, _state); - spline1dbuildcubic(&t, &z, n, 0, 0.0, 0, 0.0, &s, _state); - spline1ddiff(&s, v0, &vz2, &vdz2, &vd2z2, _state); - - /* - * 2D test - */ - pspline2calc(&p2, v0, &vx, &vy, _state); - p2errors = p2errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold); - pspline2diff(&p2, v0, &vx, &vdx, &vy, &vdy, _state); - p2errors = p2errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vdx-vdx2, _state),threshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vdy-vdy2, _state),threshold); - pspline2diff2(&p2, v0, &vx, &vdx, &vd2x, &vy, &vdy, &vd2y, _state); - p2errors = p2errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vdx-vdx2, _state),threshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vdy-vdy2, _state),threshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vd2x-vd2x2, _state),threshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vd2y-vd2y2, _state),threshold); - - /* - * 3D test - */ - pspline3calc(&p3, v0, &vx, &vy, &vz, _state); - p3errors = p3errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vz-vz2, _state),threshold); - pspline3diff(&p3, v0, &vx, &vdx, &vy, &vdy, &vz, &vdz, _state); - p3errors = p3errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vz-vz2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vdx-vdx2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vdy-vdy2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vdz-vdz2, _state),threshold); - pspline3diff2(&p3, v0, &vx, &vdx, &vd2x, &vy, &vdy, &vd2y, &vz, &vdz, &vd2z, _state); - p3errors = p3errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vz-vz2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vdx-vdx2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vdy-vdy2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vdz-vdz2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vd2x-vd2x2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vd2y-vd2y2, _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vd2z-vd2z2, _state),threshold); - - /* - * Test tangents for 2D/3D - */ - pspline2tangent(&p2, v0, &vx, &vy, _state); - p2errors = p2errors||ae_fp_greater(ae_fabs(vx-vdx2/safepythag2(vdx2, vdy2, _state), _state),threshold); - p2errors = p2errors||ae_fp_greater(ae_fabs(vy-vdy2/safepythag2(vdx2, vdy2, _state), _state),threshold); - pspline3tangent(&p3, v0, &vx, &vy, &vz, _state); - p3errors = p3errors||ae_fp_greater(ae_fabs(vx-vdx2/safepythag3(vdx2, vdy2, vdz2, _state), _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vy-vdy2/safepythag3(vdx2, vdy2, vdz2, _state), _state),threshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(vz-vdz2/safepythag3(vdx2, vdy2, vdz2, _state), _state),threshold); - } - - /* - * Arc length test. - * - * Simple problem with easy solution (points on a straight line with - * uniform parameterization). - */ - for(n=2; n<=maxn; n++) - { - ae_matrix_set_length(&xy, n, 2, _state); - ae_matrix_set_length(&xyz, n, 3, _state); - for(i=0; i<=n-1; i++) - { - xy.ptr.pp_double[i][0] = (double)(i); - xy.ptr.pp_double[i][1] = (double)(i); - xyz.ptr.pp_double[i][0] = (double)(i); - xyz.ptr.pp_double[i][1] = (double)(i); - xyz.ptr.pp_double[i][2] = (double)(i); - } - pspline2build(&xy, n, 1, 0, &p2, _state); - pspline3build(&xyz, n, 1, 0, &p3, _state); - a = ae_randomreal(_state); - b = ae_randomreal(_state); - p2errors = p2errors||ae_fp_greater(ae_fabs(pspline2arclength(&p2, a, b, _state)-(b-a)*ae_sqrt((double)(2), _state)*(n-1), _state),nonstrictthreshold); - p3errors = p3errors||ae_fp_greater(ae_fabs(pspline3arclength(&p3, a, b, _state)-(b-a)*ae_sqrt((double)(3), _state)*(n-1), _state),nonstrictthreshold); - } - - /* - * report - */ - waserrors = (p2errors||p3errors)||rdperrors; - if( !silent ) - { - printf("TESTING PARAMETRIC INTERPOLATION\n"); - - /* - * Normal tests - */ - printf("2D SPLINES: "); - if( p2errors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("3D SPLINES: "); - if( p3errors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("RDP: "); - if( rdperrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - - /* - * end - */ - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function tests 4PL/5PL fitting. On error sets FitErrors flag variable; -on success - flag is not changed. -*************************************************************************/ -static void testparametricunit_testrdp(ae_bool* errorflag, - ae_state *_state) -{ - ae_frame _frame_block; - hqrndstate rs; - ae_vector x; - ae_vector y; - ae_vector e; - ae_vector x2; - ae_vector y2; - ae_vector x3; - ae_vector y3; - ae_matrix xy; - ae_matrix xy2; - ae_matrix xy3; - ae_vector idx2; - ae_vector idx3; - ae_int_t nsections; - ae_int_t nsections3; - double eps; - double v; - ae_int_t i; - ae_int_t j; - ae_int_t n; - ae_int_t d; - spline1dinterpolant s; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&e, 0, sizeof(e)); - memset(&x2, 0, sizeof(x2)); - memset(&y2, 0, sizeof(y2)); - memset(&x3, 0, sizeof(x3)); - memset(&y3, 0, sizeof(y3)); - memset(&xy, 0, sizeof(xy)); - memset(&xy2, 0, sizeof(xy2)); - memset(&xy3, 0, sizeof(xy3)); - memset(&idx2, 0, sizeof(idx2)); - memset(&idx3, 0, sizeof(idx3)); - memset(&s, 0, sizeof(s)); - _hqrndstate_init(&rs, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&e, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x3, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y3, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy3, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&idx2, 0, DT_INT, _state, ae_true); - ae_vector_init(&idx3, 0, DT_INT, _state, ae_true); - _spline1dinterpolant_init(&s, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Parametric test 1: non-closed curve - */ - ae_matrix_set_length(&xy, 4, 2, _state); - xy.ptr.pp_double[0][0] = (double)(0); - xy.ptr.pp_double[0][1] = (double)(0); - xy.ptr.pp_double[1][0] = (double)(1); - xy.ptr.pp_double[1][1] = (double)(2); - xy.ptr.pp_double[2][0] = (double)(3); - xy.ptr.pp_double[2][1] = (double)(1); - xy.ptr.pp_double[3][0] = (double)(3); - xy.ptr.pp_double[3][1] = (double)(3); - parametricrdpfixed(&xy, 4, 2, 0, ae_sqrt((double)(2), _state)+0.001, &xy2, &idx2, &nsections, _state); - ae_set_error_flag(errorflag, nsections!=1, __FILE__, __LINE__, "testparametricunit.ap:41"); - if( nsections==1 ) - { - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:44"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:45"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:46"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][0],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:47"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][1],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:48"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[1]!=3, __FILE__, __LINE__, "testparametricunit.ap:49"); - } - parametricrdpfixed(&xy, 4, 2, 0, ae_sqrt((double)(2), _state)-0.001, &xy2, &idx2, &nsections, _state); - ae_set_error_flag(errorflag, nsections!=3, __FILE__, __LINE__, "testparametricunit.ap:52"); - if( nsections==3 ) - { - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:55"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:56"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:57"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][0],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:58"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][1],(double)(2)), __FILE__, __LINE__, "testparametricunit.ap:59"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[1]!=1, __FILE__, __LINE__, "testparametricunit.ap:60"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][0],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:61"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][1],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:62"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[2]!=2, __FILE__, __LINE__, "testparametricunit.ap:63"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[3][0],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:64"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[3][1],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:65"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[3]!=3, __FILE__, __LINE__, "testparametricunit.ap:66"); - } - parametricrdpfixed(&xy, 4, 2, 1, 0.0, &xy2, &idx2, &nsections, _state); - ae_set_error_flag(errorflag, nsections!=1, __FILE__, __LINE__, "testparametricunit.ap:69"); - if( nsections==1 ) - { - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:72"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:73"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:74"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][0],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:75"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][1],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:76"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[1]!=3, __FILE__, __LINE__, "testparametricunit.ap:77"); - } - parametricrdpfixed(&xy, 4, 2, 2, 0.0, &xy2, &idx2, &nsections, _state); - ae_set_error_flag(errorflag, nsections!=2, __FILE__, __LINE__, "testparametricunit.ap:80"); - if( nsections==2 ) - { - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:83"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:84"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:85"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][0],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:86"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][1],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:87"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[1]!=2, __FILE__, __LINE__, "testparametricunit.ap:88"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][0],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:89"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][1],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:90"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[2]!=3, __FILE__, __LINE__, "testparametricunit.ap:91"); - } - parametricrdpfixed(&xy, 4, 2, 3, 0.0, &xy2, &idx2, &nsections, _state); - ae_set_error_flag(errorflag, nsections!=3, __FILE__, __LINE__, "testparametricunit.ap:94"); - if( nsections==3 ) - { - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:97"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:98"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:99"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][0],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:100"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][1],(double)(2)), __FILE__, __LINE__, "testparametricunit.ap:101"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[1]!=1, __FILE__, __LINE__, "testparametricunit.ap:102"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][0],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:103"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][1],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:104"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[2]!=2, __FILE__, __LINE__, "testparametricunit.ap:105"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[3][0],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:106"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[3][1],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:107"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[3]!=3, __FILE__, __LINE__, "testparametricunit.ap:108"); - } - parametricrdpfixed(&xy, 4, 2, 4, 0.0, &xy2, &idx2, &nsections, _state); - ae_set_error_flag(errorflag, nsections!=3, __FILE__, __LINE__, "testparametricunit.ap:111"); - if( nsections==3 ) - { - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:114"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:115"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:116"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][0],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:117"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][1],(double)(2)), __FILE__, __LINE__, "testparametricunit.ap:118"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[1]!=1, __FILE__, __LINE__, "testparametricunit.ap:119"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][0],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:120"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][1],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:121"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[2]!=2, __FILE__, __LINE__, "testparametricunit.ap:122"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[3][0],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:123"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[3][1],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:124"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[3]!=3, __FILE__, __LINE__, "testparametricunit.ap:125"); - } - - /* - * Parametric test 2: closed curve - */ - ae_matrix_set_length(&xy, 5, 2, _state); - xy.ptr.pp_double[0][0] = (double)(0); - xy.ptr.pp_double[0][1] = (double)(0); - xy.ptr.pp_double[1][0] = (double)(1); - xy.ptr.pp_double[1][1] = (double)(0); - xy.ptr.pp_double[2][0] = (double)(1); - xy.ptr.pp_double[2][1] = (double)(1); - xy.ptr.pp_double[3][0] = (double)(0); - xy.ptr.pp_double[3][1] = (double)(1); - xy.ptr.pp_double[4][0] = (double)(0); - xy.ptr.pp_double[4][1] = (double)(0); - parametricrdpfixed(&xy, 5, 2, 0, ae_sqrt((double)(2), _state)+0.001, &xy2, &idx2, &nsections, _state); - ae_set_error_flag(errorflag, nsections!=1, __FILE__, __LINE__, "testparametricunit.ap:144"); - if( nsections==1 ) - { - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:147"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:148"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:149"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:150"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:151"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[1]!=4, __FILE__, __LINE__, "testparametricunit.ap:152"); - } - parametricrdpfixed(&xy, 5, 2, 0, ae_sqrt((double)(2), _state)-0.001, &xy2, &idx2, &nsections, _state); - ae_set_error_flag(errorflag, nsections!=2, __FILE__, __LINE__, "testparametricunit.ap:155"); - if( nsections==2 ) - { - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:158"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:159"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:160"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][0],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:161"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][1],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:162"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[1]!=2, __FILE__, __LINE__, "testparametricunit.ap:163"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:164"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:165"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[2]!=4, __FILE__, __LINE__, "testparametricunit.ap:166"); - } - parametricrdpfixed(&xy, 5, 2, 0, ae_sqrt((double)(2), _state)/2+0.001, &xy2, &idx2, &nsections, _state); - ae_set_error_flag(errorflag, nsections!=2, __FILE__, __LINE__, "testparametricunit.ap:169"); - if( nsections==2 ) - { - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:172"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:173"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:174"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][0],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:175"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][1],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:176"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[1]!=2, __FILE__, __LINE__, "testparametricunit.ap:177"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:178"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:179"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[2]!=4, __FILE__, __LINE__, "testparametricunit.ap:180"); - } - parametricrdpfixed(&xy, 5, 2, 0, ae_sqrt((double)(2), _state)/2-0.001, &xy2, &idx2, &nsections, _state); - ae_set_error_flag(errorflag, nsections!=4, __FILE__, __LINE__, "testparametricunit.ap:183"); - if( nsections==4 ) - { - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:186"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:187"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:188"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][0],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:189"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:190"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[1]!=1, __FILE__, __LINE__, "testparametricunit.ap:191"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][0],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:192"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][1],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:193"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[2]!=2, __FILE__, __LINE__, "testparametricunit.ap:194"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[3][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:195"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[3][1],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:196"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[3]!=3, __FILE__, __LINE__, "testparametricunit.ap:197"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[4][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:198"); - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[4][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:199"); - ae_set_error_flag(errorflag, idx2.ptr.p_int[4]!=4, __FILE__, __LINE__, "testparametricunit.ap:200"); - } - - /* - * Parametric, variable precision test (non-fixed), results are compared against fixed-section test - */ - eps = 10.0; - n = 100; - while(ae_fp_greater_eq(eps,0.0001)) - { - - /* - * Try different dimension counts - */ - for(d=1; d<=5; d++) - { - - /* - * Generate dataset - */ - ae_matrix_set_length(&xy, n, d, _state); - for(i=0; i<=n-1; i++) - { - v = ae_pi*i/(n-1); - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][j] = ae_pow(ae_sin(v, _state), (double)(j+1), _state)+0.01*(hqrnduniformr(&rs, _state)-0.5); - } - } - - /* - * Perform run of eps-based RDP algorithm - */ - parametricrdpfixed(&xy, n, d, 0, eps, &xy2, &idx2, &nsections, _state); - ae_set_error_flag(errorflag, nsections==0, __FILE__, __LINE__, "testparametricunit.ap:231"); - if( nsections==0 ) - { - ae_frame_leave(_state); - return; - } - - /* - * Check properties - */ - ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:238"); - for(i=0; i<=nsections-1; i++) - { - ae_set_error_flag(errorflag, idx2.ptr.p_int[i]>=idx2.ptr.p_int[i+1], __FILE__, __LINE__, "testparametricunit.ap:240"); - } - ae_set_error_flag(errorflag, idx2.ptr.p_int[nsections]!=n-1, __FILE__, __LINE__, "testparametricunit.ap:241"); - for(i=0; i<=nsections; i++) - { - for(j=0; j<=d-1; j++) - { - ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[i][j],xy.ptr.pp_double[idx2.ptr.p_int[i]][j]), __FILE__, __LINE__, "testparametricunit.ap:244"); - } - } - ae_vector_set_length(&x, nsections+1, _state); - ae_vector_set_length(&y, nsections+1, _state); - ae_vector_set_length(&e, n, _state); - for(i=0; i<=n-1; i++) - { - e.ptr.p_double[i] = (double)(0); - } - for(j=0; j<=d-1; j++) - { - for(i=0; i<=nsections; i++) - { - x.ptr.p_double[i] = (double)(idx2.ptr.p_int[i]); - y.ptr.p_double[i] = xy2.ptr.pp_double[i][j]; - } - spline1dbuildlinear(&x, &y, nsections+1, &s, _state); - for(i=0; i<=n-1; i++) - { - e.ptr.p_double[i] = e.ptr.p_double[i]+ae_sqr(spline1dcalc(&s, (double)(i), _state)-xy.ptr.pp_double[i][j], _state); - } - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_sqrt(e.ptr.p_double[i], _state),eps), __FILE__, __LINE__, "testparametricunit.ap:262"); - } - - /* - * compare results with values returned by section-based algorithm - */ - parametricrdpfixed(&xy, n, d, nsections, 0.0, &xy3, &idx3, &nsections3, _state); - ae_set_error_flag(errorflag, nsections3!=nsections, __FILE__, __LINE__, "testparametricunit.ap:268"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=nsections; i++) - { - ae_set_error_flag(errorflag, idx2.ptr.p_int[i]!=idx3.ptr.p_int[i], __FILE__, __LINE__, "testparametricunit.ap:273"); - for(j=0; j<=d-1; j++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xy2.ptr.pp_double[i][j]-xy3.ptr.pp_double[i][j], _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testparametricunit.ap:275"); - } - } - } - - /* - * Next epsilon - */ - eps = eps*0.5; - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Unset spline, i.e. initialize it with random garbage -*************************************************************************/ -static void testparametricunit_unsetp2(pspline2interpolant* p, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix xy; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - _pspline2interpolant_clear(p); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - - ae_matrix_set_length(&xy, 2, 2, _state); - xy.ptr.pp_double[0][0] = (double)(-1); - xy.ptr.pp_double[0][1] = (double)(-1); - xy.ptr.pp_double[1][0] = (double)(1); - xy.ptr.pp_double[1][1] = (double)(1); - pspline2build(&xy, 2, 1, 0, p, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -Unset spline, i.e. initialize it with random garbage -*************************************************************************/ -static void testparametricunit_unsetp3(pspline3interpolant* p, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix xy; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - _pspline3interpolant_clear(p); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - - ae_matrix_set_length(&xy, 2, 3, _state); - xy.ptr.pp_double[0][0] = (double)(-1); - xy.ptr.pp_double[0][1] = (double)(-1); - xy.ptr.pp_double[0][2] = (double)(-1); - xy.ptr.pp_double[1][0] = (double)(1); - xy.ptr.pp_double[1][1] = (double)(1); - xy.ptr.pp_double[1][2] = (double)(1); - pspline3build(&xy, 2, 1, 0, p, _state); - ae_frame_leave(_state); -} - - - -static ae_bool testspline3dunit_basictest(ae_state *_state); -static ae_bool testspline3dunit_testunpack(ae_state *_state); -static ae_bool testspline3dunit_testlintrans(ae_state *_state); -static ae_bool testspline3dunit_testtrilinearresample(ae_state *_state); -static void testspline3dunit_buildrndgrid(ae_bool isvect, - ae_bool reorder, - ae_int_t* n, - ae_int_t* m, - ae_int_t* l, - ae_int_t* d, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* z, - /* Real */ ae_vector* f, - ae_state *_state); - - - - - -ae_bool testspline3d(ae_bool silence, ae_state *_state) -{ - ae_bool waserrors; - ae_bool basicerr; - ae_bool unpackerr; - ae_bool lintransferr; - ae_bool trilinreserr; - ae_bool result; - - - basicerr = testspline3dunit_basictest(_state); - unpackerr = testspline3dunit_testunpack(_state); - lintransferr = testspline3dunit_testlintrans(_state); - trilinreserr = testspline3dunit_testtrilinearresample(_state); - waserrors = ((basicerr||unpackerr)||lintransferr)||trilinreserr; - if( !silence ) - { - printf("TESTING 3D SPLINE\n"); - printf("BASIC TEST: "); - if( basicerr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("UNPACK TEST: "); - if( unpackerr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("LIN_TRANSF TEST: "); - if( lintransferr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("TRILINEAR RESAMPLING TEST: "); - if( trilinreserr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - - /* - * Summary - */ - if( waserrors ) - { - printf("TEST FAILED"); - } - else - { - printf("TEST PASSED"); - } - printf("\n\n"); - } - result = !waserrors; - return result; -} - - -/************************************************************************* -The function does test basic functionality. -*************************************************************************/ -static ae_bool testspline3dunit_basictest(ae_state *_state) -{ - ae_frame _frame_block; - spline3dinterpolant c; - spline3dinterpolant cc; - ae_vector vvf; - double vsf; - ae_int_t d; - ae_int_t m; - ae_int_t n; - ae_int_t l; - ae_vector x; - ae_vector y; - ae_vector z; - ae_vector sf; - ae_vector vf; - double eps; - ae_int_t pass; - ae_int_t passcount; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t offs; - ae_int_t di; - double ax; - double ay; - double az; - double axy; - double ayz; - double vx; - double vy; - double vz; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&c, 0, sizeof(c)); - memset(&cc, 0, sizeof(cc)); - memset(&vvf, 0, sizeof(vvf)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&z, 0, sizeof(z)); - memset(&sf, 0, sizeof(sf)); - memset(&vf, 0, sizeof(vf)); - _spline3dinterpolant_init(&c, _state, ae_true); - _spline3dinterpolant_init(&cc, _state, ae_true); - ae_vector_init(&vvf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&z, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vf, 0, DT_REAL, _state, ae_true); - - eps = 1000*ae_machineepsilon; - - /* - * Test spline ability to reproduce D-dimensional vector function - * f[idx](x,y,z) = idx+AX*x + AY*y + AZ*z + AXY*x*y + AYZ*y*z - * with random AX/AY/... - * - * We generate random test function, build spline, then evaluate - * it in the random test point. - */ - for(d=1; d<=3; d++) - { - n = 2+ae_randominteger(4, _state); - m = 2+ae_randominteger(4, _state); - l = 2+ae_randominteger(4, _state); - ae_vector_set_length(&x, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = (double)(i); - } - ae_vector_set_length(&y, m, _state); - for(i=0; i<=m-1; i++) - { - y.ptr.p_double[i] = (double)(i); - } - ae_vector_set_length(&z, l, _state); - for(i=0; i<=l-1; i++) - { - z.ptr.p_double[i] = (double)(i); - } - ae_vector_set_length(&vf, l*m*n*d, _state); - offs = 0; - ax = 2*ae_randomreal(_state)-1; - ay = 2*ae_randomreal(_state)-1; - az = 2*ae_randomreal(_state)-1; - axy = 2*ae_randomreal(_state)-1; - ayz = 2*ae_randomreal(_state)-1; - for(k=0; k<=l-1; k++) - { - for(j=0; j<=m-1; j++) - { - for(i=0; i<=n-1; i++) - { - for(di=0; di<=d-1; di++) - { - vf.ptr.p_double[offs] = di+ax*i+ay*j+az*k+axy*i*j+ayz*j*k; - offs = offs+1; - } - } - } - } - spline3dbuildtrilinearv(&x, n, &y, m, &z, l, &vf, d, &c, _state); - vx = ae_randomreal(_state)*n; - vy = ae_randomreal(_state)*m; - vz = ae_randomreal(_state)*l; - spline3dcalcv(&c, vx, vy, vz, &vf, _state); - for(di=0; di<=d-1; di++) - { - if( ae_fp_greater(ae_fabs(di+ax*vx+ay*vy+az*vz+axy*vx*vy+ayz*vy*vz-vf.ptr.p_double[di], _state),eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - if( d==1 ) - { - vsf = spline3dcalc(&c, vx, vy, vz, _state); - if( ae_fp_greater(ae_fabs(ax*vx+ay*vy+az*vz+axy*vx*vy+ayz*vy*vz-vsf, _state),eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - - /* - * Generate random grid and test function. - * Test spline ability to reproduce function values at grid nodes. - */ - passcount = 20; - for(pass=1; pass<=passcount; pass++) - { - - /* - * Prepare a model and check that functions (Spline3DBuildTrilinear, - * Spline3DCalc,Spline3DCalcV) work correctly and - */ - testspline3dunit_buildrndgrid(ae_true, ae_true, &n, &m, &l, &d, &x, &y, &z, &vf, _state); - rvectorsetlengthatleast(&sf, n*m*l, _state); - - /* - * Check that the model's values are equal to the function's values - * in grid points - */ - spline3dbuildtrilinearv(&x, n, &y, m, &z, l, &vf, d, &c, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - for(k=0; k<=l-1; k++) - { - spline3dcalcv(&c, x.ptr.p_double[i], y.ptr.p_double[j], z.ptr.p_double[k], &vvf, _state); - for(di=0; di<=d-1; di++) - { - if( ae_fp_greater(ae_fabs(vf.ptr.p_double[d*(n*(m*k+j)+i)+di]-vvf.ptr.p_double[di], _state),eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Unpack/UnpackV test -*************************************************************************/ -static ae_bool testspline3dunit_testunpack(ae_state *_state) -{ - ae_frame _frame_block; - spline3dinterpolant c; - ae_matrix tbl0; - ae_matrix tbl1; - ae_int_t n; - ae_int_t m; - ae_int_t l; - ae_int_t d; - ae_int_t sz; - ae_int_t un; - ae_int_t um; - ae_int_t ul; - ae_int_t ud; - ae_int_t ust; - ae_int_t uvn; - ae_int_t uvm; - ae_int_t uvl; - ae_int_t uvd; - ae_int_t uvst; - ae_int_t ci; - ae_int_t cj; - ae_int_t ck; - ae_vector x; - ae_vector y; - ae_vector z; - ae_vector sf; - ae_vector vf; - ae_int_t p0; - ae_int_t p1; - double tx; - double ty; - double tz; - double v1; - double v2; - double err; - ae_int_t pass; - ae_int_t passcount; - ae_bool bperr; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t di; - ae_int_t i0; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&c, 0, sizeof(c)); - memset(&tbl0, 0, sizeof(tbl0)); - memset(&tbl1, 0, sizeof(tbl1)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&z, 0, sizeof(z)); - memset(&sf, 0, sizeof(sf)); - memset(&vf, 0, sizeof(vf)); - _spline3dinterpolant_init(&c, _state, ae_true); - ae_matrix_init(&tbl0, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&tbl1, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&z, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sf, 0, DT_REAL, _state, ae_true); - ae_vector_init(&vf, 0, DT_REAL, _state, ae_true); - - passcount = 20; - err = (double)(0); - for(pass=1; pass<=passcount; pass++) - { - - /* - * generate random grid. - * NOTE: for this test we need ordered grid, i.e. grid - * with nodes in ascending order - */ - testspline3dunit_buildrndgrid(ae_true, ae_false, &n, &m, &l, &d, &x, &y, &z, &vf, _state); - sz = n*m*l; - rvectorsetlengthatleast(&sf, sz, _state); - spline3dbuildtrilinearv(&x, n, &y, m, &z, l, &vf, d, &c, _state); - spline3dunpackv(&c, &uvn, &uvm, &uvl, &uvd, &uvst, &tbl0, _state); - for(di=0; di<=d-1; di++) - { - - /* - * DI-th component copy of a vector-function to - * a scalar function - */ - for(i=0; i<=sz-1; i++) - { - sf.ptr.p_double[i] = vf.ptr.p_double[d*i+di]; - } - spline3dbuildtrilinearv(&x, n, &y, m, &z, l, &sf, 1, &c, _state); - spline3dunpackv(&c, &un, &um, &ul, &ud, &ust, &tbl1, _state); - for(i=0; i<=n-2; i++) - { - for(j=0; j<=m-2; j++) - { - for(k=0; k<=l-2; k++) - { - p1 = (n-1)*((m-1)*k+j)+i; - p0 = d*p1+di; - - /* - * Check that all components are correct: - * *first check, that unpacked componets are equal - * to packed components; - */ - bperr = (((((((((((((((((un!=n||um!=m)||ul!=l)||ae_fp_neq(tbl1.ptr.pp_double[p1][0],x.ptr.p_double[i]))||ae_fp_neq(tbl1.ptr.pp_double[p1][1],x.ptr.p_double[i+1]))||ae_fp_neq(tbl1.ptr.pp_double[p1][2],y.ptr.p_double[j]))||ae_fp_neq(tbl1.ptr.pp_double[p1][3],y.ptr.p_double[j+1]))||ae_fp_neq(tbl1.ptr.pp_double[p1][4],z.ptr.p_double[k]))||ae_fp_neq(tbl1.ptr.pp_double[p1][5],z.ptr.p_double[k+1]))||uvn!=n)||uvm!=m)||uvl!=l)||uvd!=d)||ae_fp_neq(tbl0.ptr.pp_double[p0][0],x.ptr.p_double[i]))||ae_fp_neq(tbl0.ptr.pp_double[p0][1],x.ptr.p_double[i+1]))||ae_fp_neq(tbl0.ptr.pp_double[p0][2],y.ptr.p_double[j]))||ae_fp_neq(tbl0.ptr.pp_double[p0][3],y.ptr.p_double[j+1]))||ae_fp_neq(tbl0.ptr.pp_double[p0][4],z.ptr.p_double[k]))||ae_fp_neq(tbl0.ptr.pp_double[p0][5],z.ptr.p_double[k+1]); - - /* - * *check, that all components unpacked by Unpack - * function are equal to all components unpacked - * by UnpackV function. - */ - for(i0=0; i0<=13; i0++) - { - bperr = bperr||ae_fp_neq(tbl0.ptr.pp_double[p0][i0],tbl1.ptr.pp_double[p1][i0]); - } - if( bperr ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - tx = (0.001+0.999*ae_randomreal(_state))*(tbl1.ptr.pp_double[p1][1]-tbl1.ptr.pp_double[p1][0]); - ty = (0.001+0.999*ae_randomreal(_state))*(tbl1.ptr.pp_double[p1][3]-tbl1.ptr.pp_double[p1][2]); - tz = (0.001+0.999*ae_randomreal(_state))*(tbl1.ptr.pp_double[p1][5]-tbl1.ptr.pp_double[p1][4]); - - /* - * Interpolation properties for: - * *scalar function; - */ - v1 = (double)(0); - for(ci=0; ci<=1; ci++) - { - for(cj=0; cj<=1; cj++) - { - for(ck=0; ck<=1; ck++) - { - v1 = v1+tbl1.ptr.pp_double[p1][6+2*(2*ck+cj)+ci]*ae_pow(tx, (double)(ci), _state)*ae_pow(ty, (double)(cj), _state)*ae_pow(tz, (double)(ck), _state); - } - } - } - v2 = spline3dcalc(&c, tbl1.ptr.pp_double[p1][0]+tx, tbl1.ptr.pp_double[p1][2]+ty, tbl1.ptr.pp_double[p1][4]+tz, _state); - err = ae_maxreal(err, ae_fabs(v1-v2, _state), _state); - - /* - * *component of vector function. - */ - v1 = (double)(0); - for(ci=0; ci<=1; ci++) - { - for(cj=0; cj<=1; cj++) - { - for(ck=0; ck<=1; ck++) - { - v1 = v1+tbl0.ptr.pp_double[p0][6+2*(2*ck+cj)+ci]*ae_pow(tx, (double)(ci), _state)*ae_pow(ty, (double)(cj), _state)*ae_pow(tz, (double)(ck), _state); - } - } - } - v2 = spline3dcalc(&c, tbl0.ptr.pp_double[p0][0]+tx, tbl0.ptr.pp_double[p0][2]+ty, tbl0.ptr.pp_double[p0][4]+tz, _state); - err = ae_maxreal(err, ae_fabs(v1-v2, _state), _state); - } - } - } - } - } - result = ae_fp_greater(err,1.0E+5*ae_machineepsilon); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -LinTrans test -*************************************************************************/ -static ae_bool testspline3dunit_testlintrans(ae_state *_state) -{ - ae_frame _frame_block; - spline3dinterpolant c; - spline3dinterpolant c2; - ae_int_t m; - ae_int_t n; - ae_int_t l; - ae_int_t d; - ae_vector x; - ae_vector y; - ae_vector z; - ae_vector f; - double a1; - double a2; - double a3; - double b1; - double b2; - double b3; - double tx; - double ty; - double tz; - double vx; - double vy; - double vz; - ae_vector v1; - ae_vector v2; - ae_int_t pass; - ae_int_t passcount; - ae_int_t xjob; - ae_int_t yjob; - ae_int_t zjob; - double err; - ae_int_t i; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&c, 0, sizeof(c)); - memset(&c2, 0, sizeof(c2)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&z, 0, sizeof(z)); - memset(&f, 0, sizeof(f)); - memset(&v1, 0, sizeof(v1)); - memset(&v2, 0, sizeof(v2)); - _spline3dinterpolant_init(&c, _state, ae_true); - _spline3dinterpolant_init(&c2, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&z, 0, DT_REAL, _state, ae_true); - ae_vector_init(&f, 0, DT_REAL, _state, ae_true); - ae_vector_init(&v1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&v2, 0, DT_REAL, _state, ae_true); - - err = (double)(0); - passcount = 15; - for(pass=1; pass<=passcount; pass++) - { - testspline3dunit_buildrndgrid(ae_true, ae_false, &n, &m, &l, &d, &x, &y, &z, &f, _state); - spline3dbuildtrilinearv(&x, n, &y, m, &z, l, &f, d, &c, _state); - for(xjob=0; xjob<=1; xjob++) - { - for(yjob=0; yjob<=1; yjob++) - { - for(zjob=0; zjob<=1; zjob++) - { - - /* - * Prepare - */ - do - { - a1 = 2.0*ae_randomreal(_state)-1.0; - } - while(ae_fp_eq(a1,(double)(0))); - a1 = a1*xjob; - b1 = x.ptr.p_double[0]+ae_randomreal(_state)*(x.ptr.p_double[n-1]-x.ptr.p_double[0]+2.0)-1.0; - do - { - a2 = 2.0*ae_randomreal(_state)-1.0; - } - while(ae_fp_eq(a2,(double)(0))); - a2 = a2*yjob; - b2 = y.ptr.p_double[0]+ae_randomreal(_state)*(y.ptr.p_double[m-1]-y.ptr.p_double[0]+2.0)-1.0; - do - { - a3 = 2.0*ae_randomreal(_state)-1.0; - } - while(ae_fp_eq(a3,(double)(0))); - a3 = a3*zjob; - b3 = z.ptr.p_double[0]+ae_randomreal(_state)*(z.ptr.p_double[l-1]-z.ptr.p_double[0]+2.0)-1.0; - - /* - * Test XYZ - */ - spline3dcopy(&c, &c2, _state); - spline3dlintransxyz(&c2, a1, b1, a2, b2, a3, b3, _state); - tx = x.ptr.p_double[0]+ae_randomreal(_state)*(x.ptr.p_double[n-1]-x.ptr.p_double[0]); - ty = y.ptr.p_double[0]+ae_randomreal(_state)*(y.ptr.p_double[m-1]-y.ptr.p_double[0]); - tz = z.ptr.p_double[0]+ae_randomreal(_state)*(z.ptr.p_double[l-1]-z.ptr.p_double[0]); - if( xjob==0 ) - { - tx = b1; - vx = x.ptr.p_double[0]+ae_randomreal(_state)*(x.ptr.p_double[n-1]-x.ptr.p_double[0]); - } - else - { - vx = (tx-b1)/a1; - } - if( yjob==0 ) - { - ty = b2; - vy = y.ptr.p_double[0]+ae_randomreal(_state)*(y.ptr.p_double[m-1]-y.ptr.p_double[0]); - } - else - { - vy = (ty-b2)/a2; - } - if( zjob==0 ) - { - tz = b3; - vz = z.ptr.p_double[0]+ae_randomreal(_state)*(z.ptr.p_double[l-1]-z.ptr.p_double[0]); - } - else - { - vz = (tz-b3)/a3; - } - spline3dcalcv(&c, tx, ty, tz, &v1, _state); - spline3dcalcv(&c2, vx, vy, vz, &v2, _state); - for(i=0; i<=d-1; i++) - { - err = ae_maxreal(err, ae_fabs(v1.ptr.p_double[i]-v2.ptr.p_double[i], _state), _state); - } - if( ae_fp_greater(err,1.0E+4*ae_machineepsilon) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Test F - */ - spline3dcopy(&c, &c2, _state); - spline3dlintransf(&c2, a1, b1, _state); - tx = x.ptr.p_double[0]+ae_randomreal(_state)*(x.ptr.p_double[n-1]-x.ptr.p_double[0]); - ty = y.ptr.p_double[0]+ae_randomreal(_state)*(y.ptr.p_double[m-1]-y.ptr.p_double[0]); - tz = z.ptr.p_double[0]+ae_randomreal(_state)*(z.ptr.p_double[l-1]-z.ptr.p_double[0]); - spline3dcalcv(&c, tx, ty, tz, &v1, _state); - spline3dcalcv(&c2, tx, ty, tz, &v2, _state); - for(i=0; i<=d-1; i++) - { - err = ae_maxreal(err, ae_fabs(a1*v1.ptr.p_double[i]+b1-v2.ptr.p_double[i], _state), _state); - } - } - } - } - } - result = ae_fp_greater(err,1.0E+4*ae_machineepsilon); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Resample test -*************************************************************************/ -static ae_bool testspline3dunit_testtrilinearresample(ae_state *_state) -{ - ae_frame _frame_block; - spline3dinterpolant c; - ae_int_t n; - ae_int_t m; - ae_int_t l; - ae_int_t n2; - ae_int_t m2; - ae_int_t l2; - ae_vector x; - ae_vector y; - ae_vector z; - ae_vector f; - ae_vector fr; - double v1; - double v2; - double err; - double mf; - ae_int_t pass; - ae_int_t passcount; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&c, 0, sizeof(c)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&z, 0, sizeof(z)); - memset(&f, 0, sizeof(f)); - memset(&fr, 0, sizeof(fr)); - _spline3dinterpolant_init(&c, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&z, 0, DT_REAL, _state, ae_true); - ae_vector_init(&f, 0, DT_REAL, _state, ae_true); - ae_vector_init(&fr, 0, DT_REAL, _state, ae_true); - - result = ae_false; - passcount = 20; - for(pass=1; pass<=passcount; pass++) - { - n = ae_randominteger(4, _state)+2; - m = ae_randominteger(4, _state)+2; - l = ae_randominteger(4, _state)+2; - n2 = ae_randominteger(4, _state)+2; - m2 = ae_randominteger(4, _state)+2; - l2 = ae_randominteger(4, _state)+2; - rvectorsetlengthatleast(&x, n, _state); - rvectorsetlengthatleast(&y, m, _state); - rvectorsetlengthatleast(&z, l, _state); - rvectorsetlengthatleast(&f, n*m*l, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = (double)i/(double)(n-1); - } - for(i=0; i<=m-1; i++) - { - y.ptr.p_double[i] = (double)i/(double)(m-1); - } - for(i=0; i<=l-1; i++) - { - z.ptr.p_double[i] = (double)i/(double)(l-1); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - for(k=0; k<=l-1; k++) - { - f.ptr.p_double[n*(m*k+j)+i] = 2*ae_randomreal(_state)-1; - } - } - } - spline3dresampletrilinear(&f, l, m, n, l2, m2, n2, &fr, _state); - spline3dbuildtrilinearv(&x, n, &y, m, &z, l, &f, 1, &c, _state); - err = (double)(0); - mf = (double)(0); - for(i=0; i<=n2-1; i++) - { - for(j=0; j<=m2-1; j++) - { - for(k=0; k<=l2-1; k++) - { - v1 = spline3dcalc(&c, (double)i/(double)(n2-1), (double)j/(double)(m2-1), (double)k/(double)(l2-1), _state); - v2 = fr.ptr.p_double[n2*(m2*k+j)+i]; - err = ae_maxreal(err, ae_fabs(v1-v2, _state), _state); - mf = ae_maxreal(mf, ae_fabs(v1, _state), _state); - } - } - } - result = result||ae_fp_greater(err/mf,1.0E+4*ae_machineepsilon); - if( result ) - { - ae_frame_leave(_state); - return result; - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -The function does build random function on random grid with random number -of points: -* N, M, K - random from 2 to 5 -* D - 1 in case IsVect=False, 1..3 in case IsVect=True -* X, Y, Z - each variable spans from MinV to MaxV, with MinV is random - number from [-1.5,0.5] and MaxV is random number from - [0.5,1.5]. All nodes are well separated. All nodes are - randomly reordered in case Reorder=False. When Reorder=True, - nodes are returned in ascending order. -* F - random values from [-1,+1] -*************************************************************************/ -static void testspline3dunit_buildrndgrid(ae_bool isvect, - ae_bool reorder, - ae_int_t* n, - ae_int_t* m, - ae_int_t* l, - ae_int_t* d, - /* Real */ ae_vector* x, - /* Real */ ae_vector* y, - /* Real */ ae_vector* z, - /* Real */ ae_vector* f, - ae_state *_state) -{ - double st; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t di; - double v; - double mx; - double maxv; - double minv; - - *n = 0; - *m = 0; - *l = 0; - *d = 0; - ae_vector_clear(x); - ae_vector_clear(y); - ae_vector_clear(z); - ae_vector_clear(f); - - st = 0.3; - *m = ae_randominteger(4, _state)+2; - *n = ae_randominteger(4, _state)+2; - *l = ae_randominteger(4, _state)+2; - if( isvect ) - { - *d = ae_randominteger(3, _state)+1; - } - else - { - *d = 1; - } - rvectorsetlengthatleast(x, *n, _state); - rvectorsetlengthatleast(y, *m, _state); - rvectorsetlengthatleast(z, *l, _state); - rvectorsetlengthatleast(f, *n*(*m)*(*l)*(*d), _state); - - /* - * Fill X - */ - x->ptr.p_double[0] = (double)(0); - for(i=1; i<=*n-1; i++) - { - x->ptr.p_double[i] = x->ptr.p_double[i-1]+st+ae_randomreal(_state); - } - minv = -0.5-ae_randomreal(_state); - maxv = 0.5+ae_randomreal(_state); - mx = x->ptr.p_double[*n-1]; - for(i=0; i<=*n-1; i++) - { - x->ptr.p_double[i] = x->ptr.p_double[i]/mx*(maxv-minv)+minv; - } - if( reorder ) - { - for(i=0; i<=*n-1; i++) - { - k = ae_randominteger(*n, _state); - v = x->ptr.p_double[i]; - x->ptr.p_double[i] = x->ptr.p_double[k]; - x->ptr.p_double[k] = v; - } - } - - /* - * Fill Y - */ - y->ptr.p_double[0] = (double)(0); - for(i=1; i<=*m-1; i++) - { - y->ptr.p_double[i] = y->ptr.p_double[i-1]+st+ae_randomreal(_state); - } - minv = -0.5-ae_randomreal(_state); - maxv = 0.5+ae_randomreal(_state); - mx = y->ptr.p_double[*m-1]; - for(i=0; i<=*m-1; i++) - { - y->ptr.p_double[i] = y->ptr.p_double[i]/mx*(maxv-minv)+minv; - } - if( reorder ) - { - for(i=0; i<=*m-1; i++) - { - k = ae_randominteger(*m, _state); - v = y->ptr.p_double[i]; - y->ptr.p_double[i] = y->ptr.p_double[k]; - y->ptr.p_double[k] = v; - } - } - - /* - * Fill Z - */ - z->ptr.p_double[0] = (double)(0); - for(i=1; i<=*l-1; i++) - { - z->ptr.p_double[i] = z->ptr.p_double[i-1]+st+ae_randomreal(_state); - } - minv = -0.5-ae_randomreal(_state); - maxv = 0.5+ae_randomreal(_state); - mx = z->ptr.p_double[*l-1]; - for(i=0; i<=*l-1; i++) - { - z->ptr.p_double[i] = z->ptr.p_double[i]/mx*(maxv-minv)+minv; - } - if( reorder ) - { - for(i=0; i<=*l-1; i++) - { - k = ae_randominteger(*l, _state); - v = z->ptr.p_double[i]; - z->ptr.p_double[i] = z->ptr.p_double[k]; - z->ptr.p_double[k] = v; - } - } - - /* - * Fill F - */ - for(i=0; i<=*n-1; i++) - { - for(j=0; j<=*m-1; j++) - { - for(k=0; k<=*l-1; k++) - { - for(di=0; di<=*d-1; di++) - { - f->ptr.p_double[*d*(*n*(*m*k+j)+i)+di] = 2*ae_randomreal(_state)-1; - } - } - } - } -} - - - -static double testpolintunit_internalpolint(/* Real */ ae_vector* x, - /* Real */ ae_vector* f, - ae_int_t n, - double t, - ae_state *_state); -static void testpolintunit_brcunset(barycentricinterpolant* b, - ae_state *_state); - - - - - -/************************************************************************* -Unit test -*************************************************************************/ -ae_bool testpolint(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_bool waserrors; - ae_bool interrors; - double threshold; - ae_vector x; - ae_vector y; - ae_vector w; - ae_vector c; - ae_vector c0; - ae_vector c1; - ae_vector c2; - ae_vector x2; - ae_vector y2; - ae_vector w2; - ae_vector xfull; - ae_vector yfull; - double a; - double b; - double t; - ae_int_t i; - ae_int_t k; - ae_vector xc; - ae_vector yc; - ae_vector dc; - double v; - double v0; - double v1; - double v2; - double v3; - double v4; - double pscale; - double poffset; - double eps; - barycentricinterpolant p; - barycentricinterpolant p1; - barycentricinterpolant p2; - ae_int_t n; - ae_int_t maxn; - ae_int_t pass; - ae_int_t passcount; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&w, 0, sizeof(w)); - memset(&c, 0, sizeof(c)); - memset(&c0, 0, sizeof(c0)); - memset(&c1, 0, sizeof(c1)); - memset(&c2, 0, sizeof(c2)); - memset(&x2, 0, sizeof(x2)); - memset(&y2, 0, sizeof(y2)); - memset(&w2, 0, sizeof(w2)); - memset(&xfull, 0, sizeof(xfull)); - memset(&yfull, 0, sizeof(yfull)); - memset(&xc, 0, sizeof(xc)); - memset(&yc, 0, sizeof(yc)); - memset(&dc, 0, sizeof(dc)); - memset(&p, 0, sizeof(p)); - memset(&p1, 0, sizeof(p1)); - memset(&p2, 0, sizeof(p2)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xfull, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yfull, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dc, 0, DT_INT, _state, ae_true); - _barycentricinterpolant_init(&p, _state, ae_true); - _barycentricinterpolant_init(&p1, _state, ae_true); - _barycentricinterpolant_init(&p2, _state, ae_true); - - waserrors = ae_false; - interrors = ae_false; - maxn = 5; - passcount = 20; - threshold = 1.0E8*ae_machineepsilon; - - /* - * Test equidistant interpolation - */ - for(pass=1; pass<=passcount; pass++) - { - for(n=1; n<=maxn; n++) - { - - /* - * prepare task: - * * equidistant points - * * random Y - * * T in [A,B] or near (within 10% of its width) - */ - do - { - a = 2*ae_randomreal(_state)-1; - b = 2*ae_randomreal(_state)-1; - } - while(ae_fp_less_eq(ae_fabs(a-b, _state),0.2)); - t = a+(1.2*ae_randomreal(_state)-0.1)*(b-a); - taskgenint1dequidist(a, b, n, &x, &y, _state); - - /* - * test "fast" equidistant interpolation (no barycentric model) - */ - interrors = interrors||ae_fp_greater(ae_fabs(polynomialcalceqdist(a, b, &y, n, t, _state)-testpolintunit_internalpolint(&x, &y, n, t, _state), _state),threshold); - - /* - * test "slow" equidistant interpolation (create barycentric model) - */ - testpolintunit_brcunset(&p, _state); - polynomialbuild(&x, &y, n, &p, _state); - interrors = interrors||ae_fp_greater(ae_fabs(barycentriccalc(&p, t, _state)-testpolintunit_internalpolint(&x, &y, n, t, _state), _state),threshold); - - /* - * test "fast" interpolation (create "fast" barycentric model) - */ - testpolintunit_brcunset(&p, _state); - polynomialbuildeqdist(a, b, &y, n, &p, _state); - interrors = interrors||ae_fp_greater(ae_fabs(barycentriccalc(&p, t, _state)-testpolintunit_internalpolint(&x, &y, n, t, _state), _state),threshold); - } - } - - /* - * Test Chebyshev-1 interpolation - */ - for(pass=1; pass<=passcount; pass++) - { - for(n=1; n<=maxn; n++) - { - - /* - * prepare task: - * * equidistant points - * * random Y - * * T in [A,B] or near (within 10% of its width) - */ - do - { - a = 2*ae_randomreal(_state)-1; - b = 2*ae_randomreal(_state)-1; - } - while(ae_fp_less_eq(ae_fabs(a-b, _state),0.2)); - t = a+(1.2*ae_randomreal(_state)-0.1)*(b-a); - taskgenint1dcheb1(a, b, n, &x, &y, _state); - - /* - * test "fast" interpolation (no barycentric model) - */ - interrors = interrors||ae_fp_greater(ae_fabs(polynomialcalccheb1(a, b, &y, n, t, _state)-testpolintunit_internalpolint(&x, &y, n, t, _state), _state),threshold); - - /* - * test "slow" interpolation (create barycentric model) - */ - testpolintunit_brcunset(&p, _state); - polynomialbuild(&x, &y, n, &p, _state); - interrors = interrors||ae_fp_greater(ae_fabs(barycentriccalc(&p, t, _state)-testpolintunit_internalpolint(&x, &y, n, t, _state), _state),threshold); - - /* - * test "fast" interpolation (create "fast" barycentric model) - */ - testpolintunit_brcunset(&p, _state); - polynomialbuildcheb1(a, b, &y, n, &p, _state); - interrors = interrors||ae_fp_greater(ae_fabs(barycentriccalc(&p, t, _state)-testpolintunit_internalpolint(&x, &y, n, t, _state), _state),threshold); - } - } - - /* - * Test Chebyshev-2 interpolation - */ - for(pass=1; pass<=passcount; pass++) - { - for(n=1; n<=maxn; n++) - { - - /* - * prepare task: - * * equidistant points - * * random Y - * * T in [A,B] or near (within 10% of its width) - */ - do - { - a = 2*ae_randomreal(_state)-1; - b = 2*ae_randomreal(_state)-1; - } - while(ae_fp_less_eq(ae_fabs(a-b, _state),0.2)); - t = a+(1.2*ae_randomreal(_state)-0.1)*(b-a); - taskgenint1dcheb2(a, b, n, &x, &y, _state); - - /* - * test "fast" interpolation (no barycentric model) - */ - interrors = interrors||ae_fp_greater(ae_fabs(polynomialcalccheb2(a, b, &y, n, t, _state)-testpolintunit_internalpolint(&x, &y, n, t, _state), _state),threshold); - - /* - * test "slow" interpolation (create barycentric model) - */ - testpolintunit_brcunset(&p, _state); - polynomialbuild(&x, &y, n, &p, _state); - interrors = interrors||ae_fp_greater(ae_fabs(barycentriccalc(&p, t, _state)-testpolintunit_internalpolint(&x, &y, n, t, _state), _state),threshold); - - /* - * test "fast" interpolation (create "fast" barycentric model) - */ - testpolintunit_brcunset(&p, _state); - polynomialbuildcheb2(a, b, &y, n, &p, _state); - interrors = interrors||ae_fp_greater(ae_fabs(barycentriccalc(&p, t, _state)-testpolintunit_internalpolint(&x, &y, n, t, _state), _state),threshold); - } - } - - /* - * Testing conversion Barycentric<->Chebyshev - */ - for(pass=1; pass<=passcount; pass++) - { - for(k=1; k<=3; k++) - { - - /* - * Allocate - */ - ae_vector_set_length(&x, k, _state); - ae_vector_set_length(&y, k, _state); - - /* - * Generate problem - */ - a = 2*ae_randomreal(_state)-1; - b = a+(0.1+ae_randomreal(_state))*(2*ae_randominteger(2, _state)-1); - v0 = 2*ae_randomreal(_state)-1; - v1 = 2*ae_randomreal(_state)-1; - v2 = 2*ae_randomreal(_state)-1; - if( k==1 ) - { - x.ptr.p_double[0] = 0.5*(a+b); - y.ptr.p_double[0] = v0; - } - if( k==2 ) - { - x.ptr.p_double[0] = a; - y.ptr.p_double[0] = v0-v1; - x.ptr.p_double[1] = b; - y.ptr.p_double[1] = v0+v1; - } - if( k==3 ) - { - x.ptr.p_double[0] = a; - y.ptr.p_double[0] = v0-v1+v2; - x.ptr.p_double[1] = 0.5*(a+b); - y.ptr.p_double[1] = v0-v2; - x.ptr.p_double[2] = b; - y.ptr.p_double[2] = v0+v1+v2; - } - - /* - * Test forward conversion - */ - polynomialbuild(&x, &y, k, &p, _state); - ae_vector_set_length(&c, 1, _state); - polynomialbar2cheb(&p, a, b, &c, _state); - interrors = interrors||c.cnt!=k; - if( k>=1 ) - { - interrors = interrors||ae_fp_greater(ae_fabs(c.ptr.p_double[0]-v0, _state),threshold); - } - if( k>=2 ) - { - interrors = interrors||ae_fp_greater(ae_fabs(c.ptr.p_double[1]-v1, _state),threshold); - } - if( k>=3 ) - { - interrors = interrors||ae_fp_greater(ae_fabs(c.ptr.p_double[2]-v2, _state),threshold); - } - - /* - * Test backward conversion - */ - polynomialcheb2bar(&c, k, a, b, &p2, _state); - v = a+ae_randomreal(_state)*(b-a); - interrors = interrors||ae_fp_greater(ae_fabs(barycentriccalc(&p, v, _state)-barycentriccalc(&p2, v, _state), _state),threshold); - } - } - - /* - * Testing conversion Barycentric<->Power - */ - for(pass=1; pass<=passcount; pass++) - { - for(k=1; k<=5; k++) - { - - /* - * Allocate - */ - ae_vector_set_length(&x, k, _state); - ae_vector_set_length(&y, k, _state); - - /* - * Generate problem - */ - poffset = 2*ae_randomreal(_state)-1; - pscale = (0.1+ae_randomreal(_state))*(2*ae_randominteger(2, _state)-1); - v0 = 2*ae_randomreal(_state)-1; - v1 = 2*ae_randomreal(_state)-1; - v2 = 2*ae_randomreal(_state)-1; - v3 = 2*ae_randomreal(_state)-1; - v4 = 2*ae_randomreal(_state)-1; - if( k==1 ) - { - x.ptr.p_double[0] = poffset; - y.ptr.p_double[0] = v0; - } - if( k==2 ) - { - x.ptr.p_double[0] = poffset-pscale; - y.ptr.p_double[0] = v0-v1; - x.ptr.p_double[1] = poffset+pscale; - y.ptr.p_double[1] = v0+v1; - } - if( k==3 ) - { - x.ptr.p_double[0] = poffset-pscale; - y.ptr.p_double[0] = v0-v1+v2; - x.ptr.p_double[1] = poffset; - y.ptr.p_double[1] = v0; - x.ptr.p_double[2] = poffset+pscale; - y.ptr.p_double[2] = v0+v1+v2; - } - if( k==4 ) - { - x.ptr.p_double[0] = poffset-pscale; - y.ptr.p_double[0] = v0-v1+v2-v3; - x.ptr.p_double[1] = poffset-0.5*pscale; - y.ptr.p_double[1] = v0-0.5*v1+0.25*v2-0.125*v3; - x.ptr.p_double[2] = poffset+0.5*pscale; - y.ptr.p_double[2] = v0+0.5*v1+0.25*v2+0.125*v3; - x.ptr.p_double[3] = poffset+pscale; - y.ptr.p_double[3] = v0+v1+v2+v3; - } - if( k==5 ) - { - x.ptr.p_double[0] = poffset-pscale; - y.ptr.p_double[0] = v0-v1+v2-v3+v4; - x.ptr.p_double[1] = poffset-0.5*pscale; - y.ptr.p_double[1] = v0-0.5*v1+0.25*v2-0.125*v3+0.0625*v4; - x.ptr.p_double[2] = poffset; - y.ptr.p_double[2] = v0; - x.ptr.p_double[3] = poffset+0.5*pscale; - y.ptr.p_double[3] = v0+0.5*v1+0.25*v2+0.125*v3+0.0625*v4; - x.ptr.p_double[4] = poffset+pscale; - y.ptr.p_double[4] = v0+v1+v2+v3+v4; - } - - /* - * Test forward conversion - */ - polynomialbuild(&x, &y, k, &p, _state); - ae_vector_set_length(&c, 1, _state); - polynomialbar2pow(&p, poffset, pscale, &c, _state); - interrors = interrors||c.cnt!=k; - if( k>=1 ) - { - interrors = interrors||ae_fp_greater(ae_fabs(c.ptr.p_double[0]-v0, _state),threshold); - } - if( k>=2 ) - { - interrors = interrors||ae_fp_greater(ae_fabs(c.ptr.p_double[1]-v1, _state),threshold); - } - if( k>=3 ) - { - interrors = interrors||ae_fp_greater(ae_fabs(c.ptr.p_double[2]-v2, _state),threshold); - } - if( k>=4 ) - { - interrors = interrors||ae_fp_greater(ae_fabs(c.ptr.p_double[3]-v3, _state),threshold); - } - if( k>=5 ) - { - interrors = interrors||ae_fp_greater(ae_fabs(c.ptr.p_double[4]-v4, _state),threshold); - } - - /* - * Test backward conversion - */ - polynomialpow2bar(&c, k, poffset, pscale, &p2, _state); - v = poffset+(2*ae_randomreal(_state)-1)*pscale; - interrors = interrors||ae_fp_greater(ae_fabs(barycentriccalc(&p, v, _state)-barycentriccalc(&p2, v, _state), _state),threshold); - } - } - - /* - * crash-test: ability to solve tasks which will overflow/underflow - * weights with straightforward implementation - */ - for(n=1; n<=20; n++) - { - a = -0.1*ae_maxrealnumber; - b = 0.1*ae_maxrealnumber; - taskgenint1dequidist(a, b, n, &x, &y, _state); - polynomialbuild(&x, &y, n, &p, _state); - for(i=0; i<=n-1; i++) - { - interrors = interrors||ae_fp_eq(p.w.ptr.p_double[i],(double)(0)); - } - } - - /* - * Test issue #634: instability in PolynomialBar2Pow(). - * - * Function returns incorrect coefficients when called with - * approximately-unit scale for data which have significantly - * non-unit scale. - */ - n = 7; - eps = 1.0E-8; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&x2, n, _state); - ae_vector_set_length(&y, n, _state); - x.ptr.p_double[0] = ae_randomreal(_state)-0.5; - y.ptr.p_double[0] = ae_randomreal(_state)-0.5; - for(i=1; i<=n-1; i++) - { - x.ptr.p_double[i] = x.ptr.p_double[i-1]+ae_randomreal(_state)+0.1; - y.ptr.p_double[i] = ae_randomreal(_state)-0.5; - } - polynomialbuild(&x, &y, n, &p, _state); - polynomialbar2pow(&p, 0.0, 1.0, &c0, _state); - pscale = 1.0E-10; - for(i=0; i<=n-1; i++) - { - x2.ptr.p_double[i] = x.ptr.p_double[i]*pscale; - } - polynomialbuild(&x2, &y, n, &p, _state); - polynomialbar2pow(&p, 0.0, 1.0, &c1, _state); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(&interrors, ae_fp_greater(ae_fabs(c0.ptr.p_double[i]-c1.ptr.p_double[i]*ae_pow(pscale, (double)(i), _state), _state),eps), __FILE__, __LINE__, "testpolintunit.ap:395"); - } - pscale = 1.0E10; - for(i=0; i<=n-1; i++) - { - x2.ptr.p_double[i] = x.ptr.p_double[i]*pscale; - } - polynomialbuild(&x2, &y, n, &p, _state); - polynomialbar2pow(&p, 0.0, 1.0, &c2, _state); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(&interrors, ae_fp_greater(ae_fabs(c0.ptr.p_double[i]-c2.ptr.p_double[i]*ae_pow(pscale, (double)(i), _state), _state),eps), __FILE__, __LINE__, "testpolintunit.ap:402"); - } - - /* - * report - */ - waserrors = interrors; - if( !silent ) - { - printf("TESTING POLYNOMIAL INTERPOLATION\n"); - - /* - * Normal tests - */ - printf("INTERPOLATION TEST: "); - if( interrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - - /* - * end - */ - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -static double testpolintunit_internalpolint(/* Real */ ae_vector* x, - /* Real */ ae_vector* f, - ae_int_t n, - double t, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _f; - ae_int_t i; - ae_int_t j; - double result; - - ae_frame_make(_state, &_frame_block); - memset(&_f, 0, sizeof(_f)); - ae_vector_init_copy(&_f, f, _state, ae_true); - f = &_f; - - n = n-1; - for(j=0; j<=n-1; j++) - { - for(i=j+1; i<=n; i++) - { - f->ptr.p_double[i] = ((t-x->ptr.p_double[j])*f->ptr.p_double[i]-(t-x->ptr.p_double[i])*f->ptr.p_double[j])/(x->ptr.p_double[i]-x->ptr.p_double[j]); - } - } - result = f->ptr.p_double[n]; - ae_frame_leave(_state); - return result; -} - - -static void testpolintunit_brcunset(barycentricinterpolant* b, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector x; - ae_vector y; - ae_vector w; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&w, 0, sizeof(w)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&x, 1, _state); - ae_vector_set_length(&y, 1, _state); - ae_vector_set_length(&w, 1, _state); - x.ptr.p_double[0] = (double)(0); - y.ptr.p_double[0] = (double)(0); - w.ptr.p_double[0] = (double)(1); - barycentricbuildxyw(&x, &y, &w, 1, b, _state); - ae_frame_leave(_state); -} - - - -static void testlsfitunit_testpolynomialfitting(ae_bool* fiterrors, - ae_state *_state); -static void testlsfitunit_testrationalfitting(ae_bool* fiterrors, - ae_state *_state); -static void testlsfitunit_testsplinefitting(ae_bool* fiterrors, - ae_state *_state); -static void testlsfitunit_testgeneralfitting(ae_bool* llserrors, - ae_bool* nlserrors, - ae_state *_state); -static void testlsfitunit_testrdp(ae_bool* errorflag, ae_state *_state); -static void testlsfitunit_testlogisticfitting(ae_bool* fiterrors, - ae_state *_state); -static void testlsfitunit_testbcnls(ae_bool* errorflag, ae_state *_state); -static void testlsfitunit_testlcnls(ae_bool* errorflag, ae_state *_state); -static ae_bool testlsfitunit_isglssolution(ae_int_t n, - ae_int_t m, - ae_int_t k, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* fmatrix, - /* Real */ ae_matrix* cmatrix, - /* Real */ ae_vector* c, - ae_state *_state); -static double testlsfitunit_getglserror(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* fmatrix, - /* Real */ ae_vector* c, - ae_state *_state); -static void testlsfitunit_fitlinearnonlinear(ae_int_t m, - ae_int_t deravailable, - /* Real */ ae_matrix* xy, - lsfitstate* state, - ae_bool* nlserrors, - ae_state *_state); -static void testlsfitunit_testgradientcheck(ae_bool* testg, - ae_state *_state); -static void testlsfitunit_funcderiv(/* Real */ ae_vector* c, - /* Real */ ae_vector* x, - /* Real */ ae_vector* x0, - ae_int_t k, - ae_int_t m, - ae_int_t functype, - double* f, - /* Real */ ae_vector* g, - ae_state *_state); -static void testlsfitunit_testfunc1(ae_int_t k, - /* Real */ ae_vector* x, - /* Real */ ae_vector* z, - double* f, - ae_bool needf, - /* Real */ ae_vector* g, - ae_bool needg, - ae_state *_state); -static void testlsfitunit_testfunc2(/* Real */ ae_vector* x, - ae_int_t nx, - /* Real */ ae_vector* c, - ae_int_t nc, - double* f, - ae_bool needf, - /* Real */ ae_vector* g, - ae_bool needg, - ae_state *_state); -static void testlsfitunit_testfunc3(/* Real */ ae_vector* x, - ae_int_t nx, - /* Real */ ae_vector* c, - ae_int_t nc, - double* f, - ae_bool needf, - /* Real */ ae_vector* g, - ae_bool needg, - ae_state *_state); -static void testlsfitunit_append10(/* Real */ ae_vector* x, - double v0, - double v1, - double v2, - double v3, - double v4, - double v5, - double v6, - double v7, - double v8, - double v9, - ae_state *_state); - - - - - -ae_bool testlsfit(ae_bool silent, ae_state *_state) -{ - ae_bool waserrors; - ae_bool llserrors; - ae_bool nlserrors; - ae_bool polfiterrors; - ae_bool ratfiterrors; - ae_bool splfiterrors; - ae_bool graderrors; - ae_bool logisticerrors; - ae_bool rdperrors; - ae_bool result; - - - waserrors = ae_false; - polfiterrors = ae_false; - ratfiterrors = ae_false; - splfiterrors = ae_false; - llserrors = ae_false; - nlserrors = ae_false; - graderrors = ae_false; - logisticerrors = ae_false; - rdperrors = ae_false; - testlsfitunit_testrdp(&rdperrors, _state); - testlsfitunit_testlogisticfitting(&logisticerrors, _state); - testlsfitunit_testpolynomialfitting(&polfiterrors, _state); - testlsfitunit_testrationalfitting(&ratfiterrors, _state); - testlsfitunit_testsplinefitting(&splfiterrors, _state); - testlsfitunit_testgeneralfitting(&llserrors, &nlserrors, _state); - testlsfitunit_testgradientcheck(&graderrors, _state); - - /* - * report - */ - waserrors = ((((((llserrors||nlserrors)||polfiterrors)||ratfiterrors)||splfiterrors)||graderrors)||logisticerrors)||rdperrors; - if( !silent ) - { - printf("TESTING LEAST SQUARES\n"); - printf("POLYNOMIAL LEAST SQUARES: "); - if( polfiterrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("RATIONAL LEAST SQUARES: "); - if( ratfiterrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("SPLINE LEAST SQUARES: "); - if( splfiterrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("LINEAR LEAST SQUARES: "); - if( llserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("NON-LINEAR LEAST SQUARES: "); - if( nlserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("TEST FOR VERIFICATION OF THE GRADIENT: "); - if( graderrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("LOGISTIC FITTING (4PL/5PL): "); - if( logisticerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("RDP ALGORITHM: "); - if( rdperrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - - /* - * end - */ - result = !waserrors; - return result; -} - - -/************************************************************************* -Unit test -*************************************************************************/ -static void testlsfitunit_testpolynomialfitting(ae_bool* fiterrors, - ae_state *_state) -{ - ae_frame _frame_block; - double threshold; - ae_vector x; - ae_vector y; - ae_vector w; - ae_vector x2; - ae_vector y2; - ae_vector w2; - ae_vector xfull; - ae_vector yfull; - double t; - ae_int_t i; - ae_int_t k; - ae_vector xc; - ae_vector yc; - ae_vector dc; - ae_int_t info; - ae_int_t info2; - double v; - double v0; - double v1; - double v2; - double s; - double xmin; - double xmax; - double refrms; - double refavg; - double refavgrel; - double refmax; - barycentricinterpolant p; - barycentricinterpolant p1; - barycentricinterpolant p2; - polynomialfitreport rep; - polynomialfitreport rep2; - ae_int_t n; - ae_int_t m; - ae_int_t maxn; - ae_int_t pass; - ae_int_t passcount; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&w, 0, sizeof(w)); - memset(&x2, 0, sizeof(x2)); - memset(&y2, 0, sizeof(y2)); - memset(&w2, 0, sizeof(w2)); - memset(&xfull, 0, sizeof(xfull)); - memset(&yfull, 0, sizeof(yfull)); - memset(&xc, 0, sizeof(xc)); - memset(&yc, 0, sizeof(yc)); - memset(&dc, 0, sizeof(dc)); - memset(&p, 0, sizeof(p)); - memset(&p1, 0, sizeof(p1)); - memset(&p2, 0, sizeof(p2)); - memset(&rep, 0, sizeof(rep)); - memset(&rep2, 0, sizeof(rep2)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xfull, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yfull, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dc, 0, DT_INT, _state, ae_true); - _barycentricinterpolant_init(&p, _state, ae_true); - _barycentricinterpolant_init(&p1, _state, ae_true); - _barycentricinterpolant_init(&p2, _state, ae_true); - _polynomialfitreport_init(&rep, _state, ae_true); - _polynomialfitreport_init(&rep2, _state, ae_true); - - *fiterrors = ae_false; - maxn = 5; - passcount = 20; - threshold = 1.0E8*ae_machineepsilon; - - /* - * Test polynomial fitting - */ - for(pass=1; pass<=passcount; pass++) - { - for(n=1; n<=maxn; n++) - { - - /* - * N=M+K fitting (i.e. interpolation) - */ - for(k=0; k<=n-1; k++) - { - taskgenint1d((double)(-1), (double)(1), n, &xfull, &yfull, _state); - ae_vector_set_length(&x, n-k, _state); - ae_vector_set_length(&y, n-k, _state); - ae_vector_set_length(&w, n-k, _state); - if( k>0 ) - { - ae_vector_set_length(&xc, k, _state); - ae_vector_set_length(&yc, k, _state); - ae_vector_set_length(&dc, k, _state); - } - for(i=0; i<=n-k-1; i++) - { - x.ptr.p_double[i] = xfull.ptr.p_double[i]; - y.ptr.p_double[i] = yfull.ptr.p_double[i]; - w.ptr.p_double[i] = 1+ae_randomreal(_state); - } - for(i=0; i<=k-1; i++) - { - xc.ptr.p_double[i] = xfull.ptr.p_double[n-k+i]; - yc.ptr.p_double[i] = yfull.ptr.p_double[n-k+i]; - dc.ptr.p_int[i] = 0; - } - polynomialfitwc(&x, &y, &w, n-k, &xc, &yc, &dc, k, n, &info, &p1, &rep, _state); - if( info<=0 ) - { - *fiterrors = ae_true; - } - else - { - for(i=0; i<=n-k-1; i++) - { - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(barycentriccalc(&p1, x.ptr.p_double[i], _state)-y.ptr.p_double[i], _state),threshold); - } - for(i=0; i<=k-1; i++) - { - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(barycentriccalc(&p1, xc.ptr.p_double[i], _state)-yc.ptr.p_double[i], _state),threshold); - } - } - } - - /* - * Testing constraints on derivatives. - * Special tasks which will always have solution: - * 1. P(0)=YC[0] - * 2. P(0)=YC[0], P'(0)=YC[1] - */ - if( n>1 ) - { - for(m=3; m<=5; m++) - { - for(k=1; k<=2; k++) - { - taskgenint1d((double)(-1), (double)(1), n, &x, &y, _state); - ae_vector_set_length(&w, n, _state); - ae_vector_set_length(&xc, 2, _state); - ae_vector_set_length(&yc, 2, _state); - ae_vector_set_length(&dc, 2, _state); - for(i=0; i<=n-1; i++) - { - w.ptr.p_double[i] = 1+ae_randomreal(_state); - } - xc.ptr.p_double[0] = (double)(0); - yc.ptr.p_double[0] = 2*ae_randomreal(_state)-1; - dc.ptr.p_int[0] = 0; - xc.ptr.p_double[1] = (double)(0); - yc.ptr.p_double[1] = 2*ae_randomreal(_state)-1; - dc.ptr.p_int[1] = 1; - polynomialfitwc(&x, &y, &w, n, &xc, &yc, &dc, k, m, &info, &p1, &rep, _state); - if( info<=0 ) - { - *fiterrors = ae_true; - } - else - { - barycentricdiff1(&p1, 0.0, &v0, &v1, _state); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(v0-yc.ptr.p_double[0], _state),threshold); - if( k==2 ) - { - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(v1-yc.ptr.p_double[1], _state),threshold); - } - } - } - } - } - } - } - for(m=2; m<=8; m++) - { - for(pass=1; pass<=passcount; pass++) - { - - /* - * General fitting - * - * interpolating function through M nodes should have - * greater RMS error than fitting it through the same M nodes - */ - n = 100; - ae_vector_set_length(&x2, n, _state); - ae_vector_set_length(&y2, n, _state); - ae_vector_set_length(&w2, n, _state); - xmin = (double)(0); - xmax = 2*ae_pi; - for(i=0; i<=n-1; i++) - { - x2.ptr.p_double[i] = 2*ae_pi*ae_randomreal(_state); - y2.ptr.p_double[i] = ae_sin(x2.ptr.p_double[i], _state); - w2.ptr.p_double[i] = (double)(1); - } - ae_vector_set_length(&x, m, _state); - ae_vector_set_length(&y, m, _state); - for(i=0; i<=m-1; i++) - { - x.ptr.p_double[i] = xmin+(xmax-xmin)*i/(m-1); - y.ptr.p_double[i] = ae_sin(x.ptr.p_double[i], _state); - } - polynomialbuild(&x, &y, m, &p1, _state); - polynomialfitwc(&x2, &y2, &w2, n, &xc, &yc, &dc, 0, m, &info, &p2, &rep, _state); - if( info<=0 ) - { - *fiterrors = ae_true; - } - else - { - - /* - * calculate P1 (interpolant) RMS error, compare with P2 error - */ - v1 = (double)(0); - v2 = (double)(0); - for(i=0; i<=n-1; i++) - { - v1 = v1+ae_sqr(barycentriccalc(&p1, x2.ptr.p_double[i], _state)-y2.ptr.p_double[i], _state); - v2 = v2+ae_sqr(barycentriccalc(&p2, x2.ptr.p_double[i], _state)-y2.ptr.p_double[i], _state); - } - v1 = ae_sqrt(v1/n, _state); - v2 = ae_sqrt(v2/n, _state); - *fiterrors = *fiterrors||ae_fp_greater(v2,v1); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(v2-rep.rmserror, _state),threshold); - } - - /* - * compare weighted and non-weighted - */ - n = 20; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - ae_vector_set_length(&w, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = i+(ae_randomreal(_state)-0.5); - y.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - w.ptr.p_double[i] = (double)(1); - } - polynomialfitwc(&x, &y, &w, n, &xc, &yc, &dc, 0, m, &info, &p1, &rep, _state); - polynomialfit(&x, &y, n, m, &info2, &p2, &rep2, _state); - if( info<=0||info2<=0 ) - { - *fiterrors = ae_true; - } - else - { - - /* - * calculate P1 (interpolant), compare with P2 error - * compare RMS errors - */ - t = 2*ae_randomreal(_state)-1; - v1 = barycentriccalc(&p1, t, _state); - v2 = barycentriccalc(&p2, t, _state); - *fiterrors = *fiterrors||!approxequal(v2, v1, 1.0E-12, _state); - *fiterrors = *fiterrors||!approxequal(rep.rmserror, rep2.rmserror, 1.0E-12*maxreal3((double)(1), rep.rmserror, rep2.rmserror, _state), _state); - *fiterrors = *fiterrors||!approxequal(rep.avgerror, rep2.avgerror, 1.0E-12*maxreal3((double)(1), rep.avgerror, rep2.avgerror, _state), _state); - *fiterrors = *fiterrors||!approxequal(rep.avgrelerror, rep2.avgrelerror, 1.0E-12*maxreal3((double)(1), rep.avgrelerror, rep2.avgrelerror, _state), _state); - *fiterrors = *fiterrors||!approxequal(rep.maxerror, rep2.maxerror, 1.0E-12*maxreal3((double)(1), rep.maxerror, rep2.maxerror, _state), _state); - } - } - } - for(m=1; m<=maxn; m++) - { - for(pass=1; pass<=passcount; pass++) - { - ae_assert(passcount>=2, "PassCount should be 2 or greater!", _state); - - /* - * solve simple task (all X[] are the same, Y[] are specially - * calculated to ensure simple form of all types of errors) - * and check correctness of the errors calculated by subroutines - * - * First pass is done with zero Y[], other passes - with random Y[]. - * It should test both ability to correctly calculate errors and - * ability to not fail while working with zeros :) - */ - n = 4*maxn; - if( pass==1 ) - { - v1 = (double)(0); - v2 = (double)(0); - v = (double)(0); - } - else - { - v1 = ae_randomreal(_state); - v2 = ae_randomreal(_state); - v = 1+ae_randomreal(_state); - } - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - ae_vector_set_length(&w, n, _state); - for(i=0; i<=maxn-1; i++) - { - x.ptr.p_double[4*i+0] = (double)(i); - y.ptr.p_double[4*i+0] = v-v2; - w.ptr.p_double[4*i+0] = (double)(1); - x.ptr.p_double[4*i+1] = (double)(i); - y.ptr.p_double[4*i+1] = v-v1; - w.ptr.p_double[4*i+1] = (double)(1); - x.ptr.p_double[4*i+2] = (double)(i); - y.ptr.p_double[4*i+2] = v+v1; - w.ptr.p_double[4*i+2] = (double)(1); - x.ptr.p_double[4*i+3] = (double)(i); - y.ptr.p_double[4*i+3] = v+v2; - w.ptr.p_double[4*i+3] = (double)(1); - } - refrms = ae_sqrt((ae_sqr(v1, _state)+ae_sqr(v2, _state))/2, _state); - refavg = (ae_fabs(v1, _state)+ae_fabs(v2, _state))/2; - if( pass==1 ) - { - refavgrel = (double)(0); - } - else - { - refavgrel = 0.25*(ae_fabs(v2, _state)/ae_fabs(v-v2, _state)+ae_fabs(v1, _state)/ae_fabs(v-v1, _state)+ae_fabs(v1, _state)/ae_fabs(v+v1, _state)+ae_fabs(v2, _state)/ae_fabs(v+v2, _state)); - } - refmax = ae_maxreal(v1, v2, _state); - - /* - * Test errors correctness - */ - polynomialfit(&x, &y, n, m, &info, &p, &rep, _state); - if( info<=0 ) - { - *fiterrors = ae_true; - } - else - { - s = barycentriccalc(&p, (double)(0), _state); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(s-v, _state),threshold); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state),threshold); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state),threshold); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state),threshold); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.maxerror-refmax, _state),threshold); - } - } - } - ae_frame_leave(_state); -} - - -static void testlsfitunit_testrationalfitting(ae_bool* fiterrors, - ae_state *_state) -{ - ae_frame _frame_block; - double threshold; - ae_int_t maxn; - ae_int_t passcount; - barycentricinterpolant b1; - barycentricinterpolant b2; - ae_vector x; - ae_vector x2; - ae_vector y; - ae_vector y2; - ae_vector w; - ae_vector w2; - ae_vector xc; - ae_vector yc; - ae_vector dc; - ae_int_t n; - ae_int_t m; - ae_int_t i; - ae_int_t k; - ae_int_t pass; - double t; - double s; - double v; - double v0; - double v1; - double v2; - ae_int_t info; - ae_int_t info2; - double xmin; - double xmax; - double refrms; - double refavg; - double refavgrel; - double refmax; - barycentricfitreport rep; - barycentricfitreport rep2; - - ae_frame_make(_state, &_frame_block); - memset(&b1, 0, sizeof(b1)); - memset(&b2, 0, sizeof(b2)); - memset(&x, 0, sizeof(x)); - memset(&x2, 0, sizeof(x2)); - memset(&y, 0, sizeof(y)); - memset(&y2, 0, sizeof(y2)); - memset(&w, 0, sizeof(w)); - memset(&w2, 0, sizeof(w2)); - memset(&xc, 0, sizeof(xc)); - memset(&yc, 0, sizeof(yc)); - memset(&dc, 0, sizeof(dc)); - memset(&rep, 0, sizeof(rep)); - memset(&rep2, 0, sizeof(rep2)); - _barycentricinterpolant_init(&b1, _state, ae_true); - _barycentricinterpolant_init(&b2, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dc, 0, DT_INT, _state, ae_true); - _barycentricfitreport_init(&rep, _state, ae_true); - _barycentricfitreport_init(&rep2, _state, ae_true); - - *fiterrors = ae_false; - - /* - * PassCount number of repeated passes - * Threshold error tolerance - * LipschitzTol Lipschitz constant increase allowed - * when calculating constant on a twice denser grid - */ - passcount = 5; - maxn = 15; - threshold = 1000000*ae_machineepsilon; - - /* - * Test rational fitting: - */ - for(pass=1; pass<=passcount; pass++) - { - for(n=2; n<=maxn; n++) - { - - /* - * N=M+K fitting (i.e. interpolation) - */ - for(k=0; k<=n-1; k++) - { - ae_vector_set_length(&x, n-k, _state); - ae_vector_set_length(&y, n-k, _state); - ae_vector_set_length(&w, n-k, _state); - if( k>0 ) - { - ae_vector_set_length(&xc, k, _state); - ae_vector_set_length(&yc, k, _state); - ae_vector_set_length(&dc, k, _state); - } - for(i=0; i<=n-k-1; i++) - { - x.ptr.p_double[i] = (double)i/(double)(n-1); - y.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - w.ptr.p_double[i] = 1+ae_randomreal(_state); - } - for(i=0; i<=k-1; i++) - { - xc.ptr.p_double[i] = (double)(n-k+i)/(double)(n-1); - yc.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - dc.ptr.p_int[i] = 0; - } - barycentricfitfloaterhormannwc(&x, &y, &w, n-k, &xc, &yc, &dc, k, n, &info, &b1, &rep, _state); - if( info<=0 ) - { - *fiterrors = ae_true; - } - else - { - for(i=0; i<=n-k-1; i++) - { - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(barycentriccalc(&b1, x.ptr.p_double[i], _state)-y.ptr.p_double[i], _state),threshold); - } - for(i=0; i<=k-1; i++) - { - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(barycentriccalc(&b1, xc.ptr.p_double[i], _state)-yc.ptr.p_double[i], _state),threshold); - } - } - } - - /* - * Testing constraints on derivatives: - * * several M's are tried - * * several K's are tried - 1, 2. - * * constraints at the ends of the interval - */ - for(m=3; m<=5; m++) - { - for(k=1; k<=2; k++) - { - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - ae_vector_set_length(&w, n, _state); - ae_vector_set_length(&xc, 2, _state); - ae_vector_set_length(&yc, 2, _state); - ae_vector_set_length(&dc, 2, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - y.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - w.ptr.p_double[i] = 1+ae_randomreal(_state); - } - xc.ptr.p_double[0] = (double)(-1); - yc.ptr.p_double[0] = 2*ae_randomreal(_state)-1; - dc.ptr.p_int[0] = 0; - xc.ptr.p_double[1] = (double)(1); - yc.ptr.p_double[1] = 2*ae_randomreal(_state)-1; - dc.ptr.p_int[1] = 0; - barycentricfitfloaterhormannwc(&x, &y, &w, n, &xc, &yc, &dc, k, m, &info, &b1, &rep, _state); - if( info<=0 ) - { - *fiterrors = ae_true; - } - else - { - for(i=0; i<=k-1; i++) - { - barycentricdiff1(&b1, xc.ptr.p_double[i], &v0, &v1, _state); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(v0-yc.ptr.p_double[i], _state),threshold); - } - } - } - } - } - } - for(m=2; m<=8; m++) - { - for(pass=1; pass<=passcount; pass++) - { - - /* - * General fitting - * - * interpolating function through M nodes should have - * greater RMS error than fitting it through the same M nodes - */ - n = 100; - ae_vector_set_length(&x2, n, _state); - ae_vector_set_length(&y2, n, _state); - ae_vector_set_length(&w2, n, _state); - xmin = ae_maxrealnumber; - xmax = -ae_maxrealnumber; - for(i=0; i<=n-1; i++) - { - x2.ptr.p_double[i] = 2*ae_pi*ae_randomreal(_state); - y2.ptr.p_double[i] = ae_sin(x2.ptr.p_double[i], _state); - w2.ptr.p_double[i] = (double)(1); - xmin = ae_minreal(xmin, x2.ptr.p_double[i], _state); - xmax = ae_maxreal(xmax, x2.ptr.p_double[i], _state); - } - ae_vector_set_length(&x, m, _state); - ae_vector_set_length(&y, m, _state); - for(i=0; i<=m-1; i++) - { - x.ptr.p_double[i] = xmin+(xmax-xmin)*i/(m-1); - y.ptr.p_double[i] = ae_sin(x.ptr.p_double[i], _state); - } - barycentricbuildfloaterhormann(&x, &y, m, 3, &b1, _state); - barycentricfitfloaterhormannwc(&x2, &y2, &w2, n, &xc, &yc, &dc, 0, m, &info, &b2, &rep, _state); - if( info<=0 ) - { - *fiterrors = ae_true; - } - else - { - - /* - * calculate B1 (interpolant) RMS error, compare with B2 error - */ - v1 = (double)(0); - v2 = (double)(0); - for(i=0; i<=n-1; i++) - { - v1 = v1+ae_sqr(barycentriccalc(&b1, x2.ptr.p_double[i], _state)-y2.ptr.p_double[i], _state); - v2 = v2+ae_sqr(barycentriccalc(&b2, x2.ptr.p_double[i], _state)-y2.ptr.p_double[i], _state); - } - v1 = ae_sqrt(v1/n, _state); - v2 = ae_sqrt(v2/n, _state); - *fiterrors = *fiterrors||ae_fp_greater(v2,v1); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(v2-rep.rmserror, _state),threshold); - } - - /* - * compare weighted and non-weighted - */ - n = 20; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - ae_vector_set_length(&w, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = i+(ae_randomreal(_state)-0.5); - y.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - w.ptr.p_double[i] = (double)(1); - } - barycentricfitfloaterhormannwc(&x, &y, &w, n, &xc, &yc, &dc, 0, m, &info, &b1, &rep, _state); - barycentricfitfloaterhormann(&x, &y, n, m, &info2, &b2, &rep2, _state); - if( info<=0||info2<=0 ) - { - *fiterrors = ae_true; - } - else - { - - /* - * calculate B1 (interpolant), compare with B2 - * compare RMS errors - */ - t = 2*ae_randomreal(_state)-1; - v1 = barycentriccalc(&b1, t, _state); - v2 = barycentriccalc(&b2, t, _state); - *fiterrors = *fiterrors||!approxequal(v2, v1, 1.0E-12, _state); - *fiterrors = *fiterrors||!approxequal(rep.rmserror, rep2.rmserror, 1.0E-12*maxreal3((double)(1), rep.rmserror, rep2.rmserror, _state), _state); - *fiterrors = *fiterrors||!approxequal(rep.avgerror, rep2.avgerror, 1.0E-12*maxreal3((double)(1), rep.avgerror, rep2.avgerror, _state), _state); - *fiterrors = *fiterrors||!approxequal(rep.avgrelerror, rep2.avgrelerror, 1.0E-12*maxreal3((double)(1), rep.avgrelerror, rep2.avgrelerror, _state), _state); - *fiterrors = *fiterrors||!approxequal(rep.maxerror, rep2.maxerror, 1.0E-12*maxreal3((double)(1), rep.maxerror, rep2.maxerror, _state), _state); - } - } - } - for(pass=1; pass<=passcount; pass++) - { - ae_assert(passcount>=2, "PassCount should be 2 or greater!", _state); - - /* - * solve simple task (all X[] are the same, Y[] are specially - * calculated to ensure simple form of all types of errors) - * and check correctness of the errors calculated by subroutines - * - * First pass is done with zero Y[], other passes - with random Y[]. - * It should test both ability to correctly calculate errors and - * ability to not fail while working with zeros :) - */ - n = 4; - if( pass==1 ) - { - v1 = (double)(0); - v2 = (double)(0); - v = (double)(0); - } - else - { - v1 = ae_randomreal(_state); - v2 = ae_randomreal(_state); - v = 1+ae_randomreal(_state); - } - ae_vector_set_length(&x, 4, _state); - ae_vector_set_length(&y, 4, _state); - ae_vector_set_length(&w, 4, _state); - x.ptr.p_double[0] = (double)(0); - y.ptr.p_double[0] = v-v2; - w.ptr.p_double[0] = (double)(1); - x.ptr.p_double[1] = (double)(0); - y.ptr.p_double[1] = v-v1; - w.ptr.p_double[1] = (double)(1); - x.ptr.p_double[2] = (double)(0); - y.ptr.p_double[2] = v+v1; - w.ptr.p_double[2] = (double)(1); - x.ptr.p_double[3] = (double)(0); - y.ptr.p_double[3] = v+v2; - w.ptr.p_double[3] = (double)(1); - refrms = ae_sqrt((ae_sqr(v1, _state)+ae_sqr(v2, _state))/2, _state); - refavg = (ae_fabs(v1, _state)+ae_fabs(v2, _state))/2; - if( pass==1 ) - { - refavgrel = (double)(0); - } - else - { - refavgrel = 0.25*(ae_fabs(v2, _state)/ae_fabs(v-v2, _state)+ae_fabs(v1, _state)/ae_fabs(v-v1, _state)+ae_fabs(v1, _state)/ae_fabs(v+v1, _state)+ae_fabs(v2, _state)/ae_fabs(v+v2, _state)); - } - refmax = ae_maxreal(v1, v2, _state); - - /* - * Test errors correctness - */ - barycentricfitfloaterhormann(&x, &y, 4, 2, &info, &b1, &rep, _state); - if( info<=0 ) - { - *fiterrors = ae_true; - } - else - { - s = barycentriccalc(&b1, (double)(0), _state); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(s-v, _state),threshold); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state),threshold); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state),threshold); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state),threshold); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.maxerror-refmax, _state),threshold); - } - } - ae_frame_leave(_state); -} - - -static void testlsfitunit_testsplinefitting(ae_bool* fiterrors, - ae_state *_state) -{ - ae_frame _frame_block; - double threshold; - ae_int_t passcount; - ae_int_t n; - ae_int_t m; - ae_int_t i; - ae_int_t k; - ae_int_t pass; - ae_vector x; - ae_vector y; - ae_vector w; - ae_vector w2; - ae_vector xc; - ae_vector yc; - ae_vector d; - ae_vector dc; - double sa; - double sb; - ae_int_t info; - ae_int_t info1; - ae_int_t info2; - spline1dinterpolant c; - spline1dinterpolant c2; - spline1dfitreport rep; - spline1dfitreport rep2; - double s; - double ds; - double d2s; - ae_int_t stype; - double t; - double v; - double v1; - double v2; - double refrms; - double refavg; - double refavgrel; - double refmax; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&w, 0, sizeof(w)); - memset(&w2, 0, sizeof(w2)); - memset(&xc, 0, sizeof(xc)); - memset(&yc, 0, sizeof(yc)); - memset(&d, 0, sizeof(d)); - memset(&dc, 0, sizeof(dc)); - memset(&c, 0, sizeof(c)); - memset(&c2, 0, sizeof(c2)); - memset(&rep, 0, sizeof(rep)); - memset(&rep2, 0, sizeof(rep2)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&dc, 0, DT_INT, _state, ae_true); - _spline1dinterpolant_init(&c, _state, ae_true); - _spline1dinterpolant_init(&c2, _state, ae_true); - _spline1dfitreport_init(&rep, _state, ae_true); - _spline1dfitreport_init(&rep2, _state, ae_true); - - - /* - * Valyes: - * * pass count - * * threshold - for tests which must be satisfied exactly - */ - passcount = 20; - threshold = 10000*ae_machineepsilon; - *fiterrors = ae_false; - - /* - * Test fitting by Cubic and Hermite splines (obsolete, but still supported) - */ - for(pass=1; pass<=passcount; pass++) - { - - /* - * Cubic splines - * Ability to handle boundary constraints (1-4 constraints on F, dF/dx). - */ - for(m=4; m<=8; m++) - { - for(k=1; k<=4; k++) - { - if( k>=m ) - { - continue; - } - n = 100; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - ae_vector_set_length(&w, n, _state); - ae_vector_set_length(&xc, 4, _state); - ae_vector_set_length(&yc, 4, _state); - ae_vector_set_length(&dc, 4, _state); - sa = 1+ae_randomreal(_state); - sb = 2*ae_randomreal(_state)-1; - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = sa*ae_randomreal(_state)+sb; - y.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - w.ptr.p_double[i] = 1+ae_randomreal(_state); - } - xc.ptr.p_double[0] = sb; - yc.ptr.p_double[0] = 2*ae_randomreal(_state)-1; - dc.ptr.p_int[0] = 0; - xc.ptr.p_double[1] = sb; - yc.ptr.p_double[1] = 2*ae_randomreal(_state)-1; - dc.ptr.p_int[1] = 1; - xc.ptr.p_double[2] = sa+sb; - yc.ptr.p_double[2] = 2*ae_randomreal(_state)-1; - dc.ptr.p_int[2] = 0; - xc.ptr.p_double[3] = sa+sb; - yc.ptr.p_double[3] = 2*ae_randomreal(_state)-1; - dc.ptr.p_int[3] = 1; - spline1dfitcubicwc(&x, &y, &w, n, &xc, &yc, &dc, k, m, &info, &c, &rep, _state); - if( info<=0 ) - { - *fiterrors = ae_true; - } - else - { - - /* - * Check that constraints are satisfied - */ - for(i=0; i<=k-1; i++) - { - spline1ddiff(&c, xc.ptr.p_double[i], &s, &ds, &d2s, _state); - if( dc.ptr.p_int[i]==0 ) - { - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(s-yc.ptr.p_double[i], _state),threshold); - } - if( dc.ptr.p_int[i]==1 ) - { - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(ds-yc.ptr.p_double[i], _state),threshold); - } - if( dc.ptr.p_int[i]==2 ) - { - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(d2s-yc.ptr.p_double[i], _state),threshold); - } - } - } - } - } - - /* - * Cubic splines - * Ability to handle one internal constraint - */ - for(m=4; m<=8; m++) - { - n = 100; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - ae_vector_set_length(&w, n, _state); - ae_vector_set_length(&xc, 1, _state); - ae_vector_set_length(&yc, 1, _state); - ae_vector_set_length(&dc, 1, _state); - sa = 1+ae_randomreal(_state); - sb = 2*ae_randomreal(_state)-1; - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = sa*ae_randomreal(_state)+sb; - y.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - w.ptr.p_double[i] = 1+ae_randomreal(_state); - } - xc.ptr.p_double[0] = sa*ae_randomreal(_state)+sb; - yc.ptr.p_double[0] = 2*ae_randomreal(_state)-1; - dc.ptr.p_int[0] = ae_randominteger(2, _state); - spline1dfitcubicwc(&x, &y, &w, n, &xc, &yc, &dc, 1, m, &info, &c, &rep, _state); - if( info<=0 ) - { - *fiterrors = ae_true; - } - else - { - - /* - * Check that constraints are satisfied - */ - spline1ddiff(&c, xc.ptr.p_double[0], &s, &ds, &d2s, _state); - if( dc.ptr.p_int[0]==0 ) - { - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(s-yc.ptr.p_double[0], _state),threshold); - } - if( dc.ptr.p_int[0]==1 ) - { - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(ds-yc.ptr.p_double[0], _state),threshold); - } - if( dc.ptr.p_int[0]==2 ) - { - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(d2s-yc.ptr.p_double[0], _state),threshold); - } - } - } - - /* - * Hermite splines - * Ability to handle boundary constraints (1-4 constraints on F, dF/dx). - */ - for(m=4; m<=8; m++) - { - for(k=1; k<=4; k++) - { - if( k>=m ) - { - continue; - } - if( m%2!=0 ) - { - continue; - } - n = 100; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - ae_vector_set_length(&w, n, _state); - ae_vector_set_length(&xc, 4, _state); - ae_vector_set_length(&yc, 4, _state); - ae_vector_set_length(&dc, 4, _state); - sa = 1+ae_randomreal(_state); - sb = 2*ae_randomreal(_state)-1; - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = sa*ae_randomreal(_state)+sb; - y.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - w.ptr.p_double[i] = 1+ae_randomreal(_state); - } - xc.ptr.p_double[0] = sb; - yc.ptr.p_double[0] = 2*ae_randomreal(_state)-1; - dc.ptr.p_int[0] = 0; - xc.ptr.p_double[1] = sb; - yc.ptr.p_double[1] = 2*ae_randomreal(_state)-1; - dc.ptr.p_int[1] = 1; - xc.ptr.p_double[2] = sa+sb; - yc.ptr.p_double[2] = 2*ae_randomreal(_state)-1; - dc.ptr.p_int[2] = 0; - xc.ptr.p_double[3] = sa+sb; - yc.ptr.p_double[3] = 2*ae_randomreal(_state)-1; - dc.ptr.p_int[3] = 1; - spline1dfithermitewc(&x, &y, &w, n, &xc, &yc, &dc, k, m, &info, &c, &rep, _state); - if( info<=0 ) - { - *fiterrors = ae_true; - } - else - { - - /* - * Check that constraints are satisfied - */ - for(i=0; i<=k-1; i++) - { - spline1ddiff(&c, xc.ptr.p_double[i], &s, &ds, &d2s, _state); - if( dc.ptr.p_int[i]==0 ) - { - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(s-yc.ptr.p_double[i], _state),threshold); - } - if( dc.ptr.p_int[i]==1 ) - { - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(ds-yc.ptr.p_double[i], _state),threshold); - } - if( dc.ptr.p_int[i]==2 ) - { - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(d2s-yc.ptr.p_double[i], _state),threshold); - } - } - } - } - } - - /* - * Hermite splines - * Ability to handle one internal constraint - */ - for(m=4; m<=8; m++) - { - if( m%2!=0 ) - { - continue; - } - n = 100; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - ae_vector_set_length(&w, n, _state); - ae_vector_set_length(&xc, 1, _state); - ae_vector_set_length(&yc, 1, _state); - ae_vector_set_length(&dc, 1, _state); - sa = 1+ae_randomreal(_state); - sb = 2*ae_randomreal(_state)-1; - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = sa*ae_randomreal(_state)+sb; - y.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - w.ptr.p_double[i] = 1+ae_randomreal(_state); - } - xc.ptr.p_double[0] = sa*ae_randomreal(_state)+sb; - yc.ptr.p_double[0] = 2*ae_randomreal(_state)-1; - dc.ptr.p_int[0] = ae_randominteger(2, _state); - spline1dfithermitewc(&x, &y, &w, n, &xc, &yc, &dc, 1, m, &info, &c, &rep, _state); - if( info<=0 ) - { - *fiterrors = ae_true; - } - else - { - - /* - * Check that constraints are satisfied - */ - spline1ddiff(&c, xc.ptr.p_double[0], &s, &ds, &d2s, _state); - if( dc.ptr.p_int[0]==0 ) - { - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(s-yc.ptr.p_double[0], _state),threshold); - } - if( dc.ptr.p_int[0]==1 ) - { - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(ds-yc.ptr.p_double[0], _state),threshold); - } - if( dc.ptr.p_int[0]==2 ) - { - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(d2s-yc.ptr.p_double[0], _state),threshold); - } - } - } - } - for(m=4; m<=8; m++) - { - for(stype=0; stype<=1; stype++) - { - for(pass=1; pass<=passcount; pass++) - { - if( stype==1&&m%2!=0 ) - { - continue; - } - - /* - * cubic/Hermite spline fitting: - * * generate "template spline" C2 - * * generate 2*N points from C2, such that result of - * ideal fit should be equal to C2 - * * fit, store in C - * * compare C and C2 - */ - sa = 1+ae_randomreal(_state); - sb = 2*ae_randomreal(_state)-1; - if( stype==0 ) - { - ae_vector_set_length(&x, m-2, _state); - ae_vector_set_length(&y, m-2, _state); - for(i=0; i<=m-2-1; i++) - { - x.ptr.p_double[i] = sa*i/(m-2-1)+sb; - y.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - spline1dbuildcubic(&x, &y, m-2, 1, 2*ae_randomreal(_state)-1, 1, 2*ae_randomreal(_state)-1, &c2, _state); - } - if( stype==1 ) - { - ae_vector_set_length(&x, m/2, _state); - ae_vector_set_length(&y, m/2, _state); - ae_vector_set_length(&d, m/2, _state); - for(i=0; i<=m/2-1; i++) - { - x.ptr.p_double[i] = sa*i/(m/2-1)+sb; - y.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - d.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - spline1dbuildhermite(&x, &y, &d, m/2, &c2, _state); - } - n = 50; - ae_vector_set_length(&x, 2*n, _state); - ae_vector_set_length(&y, 2*n, _state); - ae_vector_set_length(&w, 2*n, _state); - for(i=0; i<=n-1; i++) - { - - /* - * "if i=0" and "if i=1" are needed to - * synchronize interval size for C2 and - * spline being fitted (i.e. C). - */ - t = ae_randomreal(_state); - x.ptr.p_double[i] = sa*ae_randomreal(_state)+sb; - if( i==0 ) - { - x.ptr.p_double[i] = sb; - } - if( i==1 ) - { - x.ptr.p_double[i] = sa+sb; - } - v = spline1dcalc(&c2, x.ptr.p_double[i], _state); - y.ptr.p_double[i] = v+t; - w.ptr.p_double[i] = 1+ae_randomreal(_state); - x.ptr.p_double[n+i] = x.ptr.p_double[i]; - y.ptr.p_double[n+i] = v-t; - w.ptr.p_double[n+i] = w.ptr.p_double[i]; - } - info = -1; - if( stype==0 ) - { - spline1dfitcubicwc(&x, &y, &w, 2*n, &xc, &yc, &dc, 0, m, &info, &c, &rep, _state); - } - if( stype==1 ) - { - spline1dfithermitewc(&x, &y, &w, 2*n, &xc, &yc, &dc, 0, m, &info, &c, &rep, _state); - } - if( info<=0 ) - { - *fiterrors = ae_true; - } - else - { - for(i=0; i<=n-1; i++) - { - v = sa*ae_randomreal(_state)+sb; - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(spline1dcalc(&c, v, _state)-spline1dcalc(&c2, v, _state), _state),threshold); - } - } - } - } - } - for(m=4; m<=8; m++) - { - for(pass=1; pass<=passcount; pass++) - { - - /* - * prepare points/weights - */ - n = 10+ae_randominteger(10, _state); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - ae_vector_set_length(&w, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = i+(ae_randomreal(_state)-0.5); - y.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - w.ptr.p_double[i] = (double)(1); - } - - /* - * Fit cubic with unity weights, without weights, then compare - */ - if( m>=4 ) - { - spline1dfitcubicwc(&x, &y, &w, n, &xc, &yc, &dc, 0, m, &info1, &c, &rep, _state); - spline1dfitcubic(&x, &y, n, m, &info2, &c2, &rep2, _state); - if( info1<=0||info2<=0 ) - { - *fiterrors = ae_true; - } - else - { - for(i=0; i<=n-1; i++) - { - v = ae_randomreal(_state)*(n-1); - *fiterrors = *fiterrors||!approxequal(spline1dcalc(&c, v, _state), spline1dcalc(&c2, v, _state), 1.0E-12, _state); - *fiterrors = *fiterrors||!approxequal(rep.taskrcond, rep2.taskrcond, 1.0E-12*maxreal3((double)(1), rep.taskrcond, rep2.taskrcond, _state), _state); - *fiterrors = *fiterrors||!approxequal(rep.rmserror, rep2.rmserror, 1.0E-12*maxreal3((double)(1), rep.rmserror, rep2.rmserror, _state), _state); - *fiterrors = *fiterrors||!approxequal(rep.avgerror, rep2.avgerror, 1.0E-12*maxreal3((double)(1), rep.avgerror, rep2.avgerror, _state), _state); - *fiterrors = *fiterrors||!approxequal(rep.avgrelerror, rep2.avgrelerror, 1.0E-12*maxreal3((double)(1), rep.avgrelerror, rep2.avgrelerror, _state), _state); - *fiterrors = *fiterrors||!approxequal(rep.maxerror, rep2.maxerror, 1.0E-12*maxreal3((double)(1), rep.maxerror, rep2.maxerror, _state), _state); - } - } - } - - /* - * Fit Hermite with unity weights, without weights, then compare - */ - if( m>=4&&m%2==0 ) - { - spline1dfithermitewc(&x, &y, &w, n, &xc, &yc, &dc, 0, m, &info1, &c, &rep, _state); - spline1dfithermite(&x, &y, n, m, &info2, &c2, &rep2, _state); - if( info1<=0||info2<=0 ) - { - *fiterrors = ae_true; - } - else - { - for(i=0; i<=n-1; i++) - { - v = ae_randomreal(_state)*(n-1); - *fiterrors = *fiterrors||!approxequal(spline1dcalc(&c, v, _state), spline1dcalc(&c2, v, _state), 1.0E-12, _state); - *fiterrors = *fiterrors||!approxequal(rep.taskrcond, rep2.taskrcond, 1.0E-12*maxreal3((double)(1), rep.taskrcond, rep2.taskrcond, _state), _state); - *fiterrors = *fiterrors||!approxequal(rep.rmserror, rep2.rmserror, 1.0E-12*maxreal3((double)(1), rep.rmserror, rep2.rmserror, _state), _state); - *fiterrors = *fiterrors||!approxequal(rep.avgerror, rep2.avgerror, 1.0E-12*maxreal3((double)(1), rep.avgerror, rep2.avgerror, _state), _state); - *fiterrors = *fiterrors||!approxequal(rep.avgrelerror, rep2.avgrelerror, 1.0E-12*maxreal3((double)(1), rep.avgrelerror, rep2.avgrelerror, _state), _state); - *fiterrors = *fiterrors||!approxequal(rep.maxerror, rep2.maxerror, 1.0E-12*maxreal3((double)(1), rep.maxerror, rep2.maxerror, _state), _state); - } - } - } - } - } - - /* - * Check correctness of error reports - */ - for(pass=1; pass<=passcount; pass++) - { - ae_assert(passcount>=2, "PassCount should be 2 or greater!", _state); - - /* - * solve simple task (all X[] are the same, Y[] are specially - * calculated to ensure simple form of all types of errors) - * and check correctness of the errors calculated by subroutines - * - * First pass is done with zero Y[], other passes - with random Y[]. - * It should test both ability to correctly calculate errors and - * ability to not fail while working with zeros :) - */ - n = 4; - if( pass==1 ) - { - v1 = (double)(0); - v2 = (double)(0); - v = (double)(0); - } - else - { - v1 = ae_randomreal(_state); - v2 = ae_randomreal(_state); - v = 1+ae_randomreal(_state); - } - ae_vector_set_length(&x, 4, _state); - ae_vector_set_length(&y, 4, _state); - ae_vector_set_length(&w, 4, _state); - x.ptr.p_double[0] = (double)(0); - y.ptr.p_double[0] = v-v2; - w.ptr.p_double[0] = (double)(1); - x.ptr.p_double[1] = (double)(0); - y.ptr.p_double[1] = v-v1; - w.ptr.p_double[1] = (double)(1); - x.ptr.p_double[2] = (double)(0); - y.ptr.p_double[2] = v+v1; - w.ptr.p_double[2] = (double)(1); - x.ptr.p_double[3] = (double)(0); - y.ptr.p_double[3] = v+v2; - w.ptr.p_double[3] = (double)(1); - refrms = ae_sqrt((ae_sqr(v1, _state)+ae_sqr(v2, _state))/2, _state); - refavg = (ae_fabs(v1, _state)+ae_fabs(v2, _state))/2; - if( pass==1 ) - { - refavgrel = (double)(0); - } - else - { - refavgrel = 0.25*(ae_fabs(v2, _state)/ae_fabs(v-v2, _state)+ae_fabs(v1, _state)/ae_fabs(v-v1, _state)+ae_fabs(v1, _state)/ae_fabs(v+v1, _state)+ae_fabs(v2, _state)/ae_fabs(v+v2, _state)); - } - refmax = ae_maxreal(v1, v2, _state); - - /* - * Test cubic fitting - */ - spline1dfitcubic(&x, &y, 4, 4, &info, &c, &rep, _state); - if( info<=0 ) - { - *fiterrors = ae_true; - } - else - { - s = spline1dcalc(&c, (double)(0), _state); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(s-v, _state),threshold); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state),threshold); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state),threshold); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state),threshold); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.maxerror-refmax, _state),threshold); - } - - /* - * Test Hermite fitting - */ - spline1dfithermite(&x, &y, 4, 4, &info, &c, &rep, _state); - if( info<=0 ) - { - *fiterrors = ae_true; - } - else - { - s = spline1dcalc(&c, (double)(0), _state); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(s-v, _state),threshold); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state),threshold); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state),threshold); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state),threshold); - *fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.maxerror-refmax, _state),threshold); - } - } - ae_frame_leave(_state); -} - - -static void testlsfitunit_testgeneralfitting(ae_bool* llserrors, - ae_bool* nlserrors, - ae_state *_state) -{ - ae_frame _frame_block; - double threshold; - double nlthreshold; - ae_int_t maxn; - ae_int_t maxm; - ae_int_t skind; - ae_int_t pkind; - ae_int_t passcount; - ae_int_t n; - ae_int_t m; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t pass; - double xscale; - double cscale; - double wscale; - double noiselevel; - double tol; - double diffstep; - ae_vector x; - ae_vector y; - ae_vector y2; - ae_vector w; - ae_vector w2; - ae_vector s; - ae_vector c; - ae_vector cstart; - ae_vector cend; - ae_vector c2; - ae_matrix a; - ae_matrix a2; - ae_matrix cm; - double v; - double v1; - double v2; - lsfitreport rep; - lsfitreport rep2; - ae_int_t info; - ae_int_t info2; - double refrms; - double refavg; - double refavgrel; - double refmax; - double avgdeviationpar; - double avgdeviationcurve; - double avgdeviationnoise; - double adccnt; - double adpcnt; - double adncnt; - lsfitstate state; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&y2, 0, sizeof(y2)); - memset(&w, 0, sizeof(w)); - memset(&w2, 0, sizeof(w2)); - memset(&s, 0, sizeof(s)); - memset(&c, 0, sizeof(c)); - memset(&cstart, 0, sizeof(cstart)); - memset(&cend, 0, sizeof(cend)); - memset(&c2, 0, sizeof(c2)); - memset(&a, 0, sizeof(a)); - memset(&a2, 0, sizeof(a2)); - memset(&cm, 0, sizeof(cm)); - memset(&rep, 0, sizeof(rep)); - memset(&rep2, 0, sizeof(rep2)); - memset(&state, 0, sizeof(state)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&w2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&s, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cstart, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cend, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c2, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&cm, 0, 0, DT_REAL, _state, ae_true); - _lsfitreport_init(&rep, _state, ae_true); - _lsfitreport_init(&rep2, _state, ae_true); - _lsfitstate_init(&state, _state, ae_true); - - *llserrors = ae_false; - *nlserrors = ae_false; - threshold = 10000*ae_machineepsilon; - nlthreshold = 0.00001; - diffstep = 0.0001; - maxn = 6; - maxm = 6; - passcount = 4; - - /* - * Test constrained NLS problems - */ - testlsfitunit_testbcnls(nlserrors, _state); - testlsfitunit_testlcnls(nlserrors, _state); - - /* - * Testing unconstrained least squares (linear/nonlinear) - */ - for(n=1; n<=maxn; n++) - { - for(m=1; m<=maxm; m++) - { - for(pass=1; pass<=passcount; pass++) - { - - /* - * Solve non-degenerate linear least squares task - * Use Chebyshev basis. Its condition number is very good. - */ - ae_matrix_set_length(&a, n, m, _state); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - ae_vector_set_length(&w, n, _state); - xscale = 0.9+0.1*ae_randomreal(_state); - for(i=0; i<=n-1; i++) - { - if( n==1 ) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - else - { - x.ptr.p_double[i] = xscale*((double)(2*i)/(double)(n-1)-1); - } - y.ptr.p_double[i] = 3*x.ptr.p_double[i]+ae_exp(x.ptr.p_double[i], _state); - w.ptr.p_double[i] = 1+ae_randomreal(_state); - a.ptr.pp_double[i][0] = (double)(1); - if( m>1 ) - { - a.ptr.pp_double[i][1] = x.ptr.p_double[i]; - } - for(j=2; j<=m-1; j++) - { - a.ptr.pp_double[i][j] = 2*x.ptr.p_double[i]*a.ptr.pp_double[i][j-1]-a.ptr.pp_double[i][j-2]; - } - } - - /* - * 1. test weighted fitting (optimality) - * 2. Solve degenerate least squares task built on the basis - * of previous task - */ - lsfitlinearw(&y, &w, &a, n, m, &info, &c, &rep, _state); - if( info<=0 ) - { - *llserrors = ae_true; - } - else - { - *llserrors = *llserrors||!testlsfitunit_isglssolution(n, m, 0, &y, &w, &a, &cm, &c, _state); - } - ae_matrix_set_length(&a2, n, 2*m, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - a2.ptr.pp_double[i][2*j+0] = a.ptr.pp_double[i][j]; - a2.ptr.pp_double[i][2*j+1] = a.ptr.pp_double[i][j]; - } - } - lsfitlinearw(&y, &w, &a2, n, 2*m, &info, &c2, &rep, _state); - if( info<=0 ) - { - *llserrors = ae_true; - } - else - { - - /* - * test answer correctness using design matrix properties - * and previous task solution - */ - for(j=0; j<=m-1; j++) - { - *llserrors = *llserrors||ae_fp_greater(ae_fabs(c2.ptr.p_double[2*j+0]+c2.ptr.p_double[2*j+1]-c.ptr.p_double[j], _state),threshold); - } - } - - /* - * test non-weighted fitting - */ - ae_vector_set_length(&w2, n, _state); - for(i=0; i<=n-1; i++) - { - w2.ptr.p_double[i] = (double)(1); - } - lsfitlinearw(&y, &w2, &a, n, m, &info, &c, &rep, _state); - lsfitlinear(&y, &a, n, m, &info2, &c2, &rep2, _state); - if( info<=0||info2<=0 ) - { - *llserrors = ae_true; - } - else - { - - /* - * test answer correctness - */ - for(j=0; j<=m-1; j++) - { - *llserrors = *llserrors||ae_fp_greater(ae_fabs(c.ptr.p_double[j]-c2.ptr.p_double[j], _state),threshold); - } - *llserrors = *llserrors||ae_fp_greater(ae_fabs(rep.taskrcond-rep2.taskrcond, _state),threshold); - } - - /* - * test nonlinear fitting on the linear task - * (only non-degenerate tasks are tested) - * and compare with answer from linear fitting subroutine - */ - if( n>=m ) - { - ae_vector_set_length(&c2, m, _state); - - /* - * test function/gradient/Hessian-based weighted fitting - */ - lsfitlinearw(&y, &w, &a, n, m, &info, &c, &rep, _state); - for(i=0; i<=m-1; i++) - { - c2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - lsfitcreatewf(&a, &y, &w, &c2, n, m, m, diffstep, &state, _state); - lsfitsetcond(&state, nlthreshold, 0, _state); - testlsfitunit_fitlinearnonlinear(m, 0, &a, &state, nlserrors, _state); - lsfitresults(&state, &info, &c2, &rep2, _state); - if( info<=0 ) - { - *nlserrors = ae_true; - } - else - { - for(i=0; i<=m-1; i++) - { - *nlserrors = *nlserrors||ae_fp_greater(ae_fabs(c.ptr.p_double[i]-c2.ptr.p_double[i], _state),100*nlthreshold); - } - } - for(i=0; i<=m-1; i++) - { - c2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - lsfitcreatewfg(&a, &y, &w, &c2, n, m, m, ae_fp_greater(ae_randomreal(_state),0.5), &state, _state); - lsfitsetcond(&state, nlthreshold, 0, _state); - testlsfitunit_fitlinearnonlinear(m, 1, &a, &state, nlserrors, _state); - lsfitresults(&state, &info, &c2, &rep2, _state); - if( info<=0 ) - { - *nlserrors = ae_true; - } - else - { - for(i=0; i<=m-1; i++) - { - *nlserrors = *nlserrors||ae_fp_greater(ae_fabs(c.ptr.p_double[i]-c2.ptr.p_double[i], _state),100*nlthreshold); - } - } - for(i=0; i<=m-1; i++) - { - c2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - lsfitcreatewfgh(&a, &y, &w, &c2, n, m, m, &state, _state); - lsfitsetcond(&state, nlthreshold, 0, _state); - testlsfitunit_fitlinearnonlinear(m, 2, &a, &state, nlserrors, _state); - lsfitresults(&state, &info, &c2, &rep2, _state); - if( info<=0 ) - { - *nlserrors = ae_true; - } - else - { - for(i=0; i<=m-1; i++) - { - *nlserrors = *nlserrors||ae_fp_greater(ae_fabs(c.ptr.p_double[i]-c2.ptr.p_double[i], _state),100*nlthreshold); - } - } - - /* - * test gradient-only or Hessian-based fitting without weights - */ - lsfitlinear(&y, &a, n, m, &info, &c, &rep, _state); - for(i=0; i<=m-1; i++) - { - c2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - lsfitcreatef(&a, &y, &c2, n, m, m, diffstep, &state, _state); - lsfitsetcond(&state, nlthreshold, 0, _state); - testlsfitunit_fitlinearnonlinear(m, 0, &a, &state, nlserrors, _state); - lsfitresults(&state, &info, &c2, &rep2, _state); - if( info<=0 ) - { - *nlserrors = ae_true; - } - else - { - for(i=0; i<=m-1; i++) - { - *nlserrors = *nlserrors||ae_fp_greater(ae_fabs(c.ptr.p_double[i]-c2.ptr.p_double[i], _state),100*nlthreshold); - } - } - for(i=0; i<=m-1; i++) - { - c2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - lsfitcreatefg(&a, &y, &c2, n, m, m, ae_fp_greater(ae_randomreal(_state),0.5), &state, _state); - lsfitsetcond(&state, nlthreshold, 0, _state); - testlsfitunit_fitlinearnonlinear(m, 1, &a, &state, nlserrors, _state); - lsfitresults(&state, &info, &c2, &rep2, _state); - if( info<=0 ) - { - *nlserrors = ae_true; - } - else - { - for(i=0; i<=m-1; i++) - { - *nlserrors = *nlserrors||ae_fp_greater(ae_fabs(c.ptr.p_double[i]-c2.ptr.p_double[i], _state),100*nlthreshold); - } - } - for(i=0; i<=m-1; i++) - { - c2.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - lsfitcreatefgh(&a, &y, &c2, n, m, m, &state, _state); - lsfitsetcond(&state, nlthreshold, 0, _state); - testlsfitunit_fitlinearnonlinear(m, 2, &a, &state, nlserrors, _state); - lsfitresults(&state, &info, &c2, &rep2, _state); - if( info<=0 ) - { - *nlserrors = ae_true; - } - else - { - for(i=0; i<=m-1; i++) - { - *nlserrors = *nlserrors||ae_fp_greater(ae_fabs(c.ptr.p_double[i]-c2.ptr.p_double[i], _state),100*nlthreshold); - } - } - } - } - } - - /* - * test correctness of the RCond field - */ - ae_matrix_set_length(&a, n-1+1, n-1+1, _state); - ae_vector_set_length(&x, n-1+1, _state); - ae_vector_set_length(&y, n-1+1, _state); - ae_vector_set_length(&w, n-1+1, _state); - v1 = ae_maxrealnumber; - v2 = ae_minrealnumber; - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = 0.1+0.9*ae_randomreal(_state); - y.ptr.p_double[i] = 0.1+0.9*ae_randomreal(_state); - w.ptr.p_double[i] = (double)(1); - for(j=0; j<=n-1; j++) - { - if( i==j ) - { - a.ptr.pp_double[i][i] = 0.1+0.9*ae_randomreal(_state); - v1 = ae_minreal(v1, a.ptr.pp_double[i][i], _state); - v2 = ae_maxreal(v2, a.ptr.pp_double[i][i], _state); - } - else - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - } - lsfitlinearw(&y, &w, &a, n, n, &info, &c, &rep, _state); - if( info<=0 ) - { - *llserrors = ae_true; - } - else - { - *llserrors = *llserrors||ae_fp_greater(ae_fabs(rep.taskrcond-v1/v2, _state),threshold); - } - } - - /* - * Test constrained least squares - */ - for(pass=1; pass<=passcount; pass++) - { - for(n=1; n<=maxn; n++) - { - for(m=1; m<=maxm; m++) - { - - /* - * test for K<>0 - */ - for(k=1; k<=m-1; k++) - { - - /* - * Prepare Chebyshev basis. Its condition number is very good. - * Prepare constraints (random numbers) - */ - ae_matrix_set_length(&a, n, m, _state); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - ae_vector_set_length(&w, n, _state); - xscale = 0.9+0.1*ae_randomreal(_state); - for(i=0; i<=n-1; i++) - { - if( n==1 ) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - else - { - x.ptr.p_double[i] = xscale*((double)(2*i)/(double)(n-1)-1); - } - y.ptr.p_double[i] = 3*x.ptr.p_double[i]+ae_exp(x.ptr.p_double[i], _state); - w.ptr.p_double[i] = 1+ae_randomreal(_state); - a.ptr.pp_double[i][0] = (double)(1); - if( m>1 ) - { - a.ptr.pp_double[i][1] = x.ptr.p_double[i]; - } - for(j=2; j<=m-1; j++) - { - a.ptr.pp_double[i][j] = 2*x.ptr.p_double[i]*a.ptr.pp_double[i][j-1]-a.ptr.pp_double[i][j-2]; - } - } - ae_matrix_set_length(&cm, k, m+1, _state); - for(i=0; i<=k-1; i++) - { - for(j=0; j<=m; j++) - { - cm.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - - /* - * Solve constrained task - */ - lsfitlinearwc(&y, &w, &a, &cm, n, m, k, &info, &c, &rep, _state); - if( info<=0 ) - { - *llserrors = ae_true; - } - else - { - *llserrors = *llserrors||!testlsfitunit_isglssolution(n, m, k, &y, &w, &a, &cm, &c, _state); - } - - /* - * test non-weighted fitting - */ - ae_vector_set_length(&w2, n, _state); - for(i=0; i<=n-1; i++) - { - w2.ptr.p_double[i] = (double)(1); - } - lsfitlinearwc(&y, &w2, &a, &cm, n, m, k, &info, &c, &rep, _state); - lsfitlinearc(&y, &a, &cm, n, m, k, &info2, &c2, &rep2, _state); - if( info<=0||info2<=0 ) - { - *llserrors = ae_true; - } - else - { - - /* - * test answer correctness - */ - for(j=0; j<=m-1; j++) - { - *llserrors = *llserrors||ae_fp_greater(ae_fabs(c.ptr.p_double[j]-c2.ptr.p_double[j], _state),threshold); - } - *llserrors = *llserrors||ae_fp_greater(ae_fabs(rep.taskrcond-rep2.taskrcond, _state),threshold); - } - } - } - } - } - - /* - * nonlinear task for nonlinear fitting: - * - * f(X,C) = 1/(1+C*X^2), - * C(true) = 2. - */ - n = 100; - ae_vector_set_length(&c, 1, _state); - c.ptr.p_double[0] = 1+2*ae_randomreal(_state); - ae_matrix_set_length(&a, n, 1, _state); - ae_vector_set_length(&y, n, _state); - for(i=0; i<=n-1; i++) - { - a.ptr.pp_double[i][0] = 4*ae_randomreal(_state)-2; - y.ptr.p_double[i] = 1/(1+2*ae_sqr(a.ptr.pp_double[i][0], _state)); - } - lsfitcreatefg(&a, &y, &c, n, 1, 1, ae_true, &state, _state); - lsfitsetcond(&state, nlthreshold, 0, _state); - while(lsfititeration(&state, _state)) - { - if( state.needf ) - { - state.f = 1/(1+state.c.ptr.p_double[0]*ae_sqr(state.x.ptr.p_double[0], _state)); - } - if( state.needfg ) - { - state.f = 1/(1+state.c.ptr.p_double[0]*ae_sqr(state.x.ptr.p_double[0], _state)); - state.g.ptr.p_double[0] = -ae_sqr(state.x.ptr.p_double[0], _state)/ae_sqr(1+state.c.ptr.p_double[0]*ae_sqr(state.x.ptr.p_double[0], _state), _state); - } - } - lsfitresults(&state, &info, &c, &rep, _state); - if( info<=0 ) - { - ae_set_error_flag(nlserrors, ae_true, __FILE__, __LINE__, "testlsfitunit.ap:1389"); - } - else - { - ae_set_error_flag(nlserrors, ae_fp_greater(ae_fabs(c.ptr.p_double[0]-2, _state),100*nlthreshold), __FILE__, __LINE__, "testlsfitunit.ap:1391"); - } - - /* - * solve simple task (fitting by constant function) and check - * correctness of the errors calculated by subroutines - */ - for(pass=1; pass<=passcount; pass++) - { - - /* - * test on task with non-zero Yi - */ - n = 4; - v1 = ae_randomreal(_state); - v2 = ae_randomreal(_state); - v = 1+ae_randomreal(_state); - ae_vector_set_length(&c, 1, _state); - c.ptr.p_double[0] = 1+2*ae_randomreal(_state); - ae_matrix_set_length(&a, 4, 1, _state); - ae_vector_set_length(&y, 4, _state); - a.ptr.pp_double[0][0] = (double)(1); - y.ptr.p_double[0] = v-v2; - a.ptr.pp_double[1][0] = (double)(1); - y.ptr.p_double[1] = v-v1; - a.ptr.pp_double[2][0] = (double)(1); - y.ptr.p_double[2] = v+v1; - a.ptr.pp_double[3][0] = (double)(1); - y.ptr.p_double[3] = v+v2; - refrms = ae_sqrt((ae_sqr(v1, _state)+ae_sqr(v2, _state))/2, _state); - refavg = (ae_fabs(v1, _state)+ae_fabs(v2, _state))/2; - refavgrel = 0.25*(ae_fabs(v2, _state)/ae_fabs(v-v2, _state)+ae_fabs(v1, _state)/ae_fabs(v-v1, _state)+ae_fabs(v1, _state)/ae_fabs(v+v1, _state)+ae_fabs(v2, _state)/ae_fabs(v+v2, _state)); - refmax = ae_maxreal(v1, v2, _state); - - /* - * Test LLS - */ - lsfitlinear(&y, &a, 4, 1, &info, &c, &rep, _state); - if( info<=0 ) - { - *llserrors = ae_true; - } - else - { - *llserrors = *llserrors||ae_fp_greater(ae_fabs(c.ptr.p_double[0]-v, _state),threshold); - *llserrors = *llserrors||ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state),threshold); - *llserrors = *llserrors||ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state),threshold); - *llserrors = *llserrors||ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state),threshold); - *llserrors = *llserrors||ae_fp_greater(ae_fabs(rep.maxerror-refmax, _state),threshold); - } - - /* - * Test NLS - */ - lsfitcreatefg(&a, &y, &c, 4, 1, 1, ae_true, &state, _state); - lsfitsetcond(&state, nlthreshold, 0, _state); - while(lsfititeration(&state, _state)) - { - if( state.needf ) - { - state.f = state.c.ptr.p_double[0]; - } - if( state.needfg ) - { - state.f = state.c.ptr.p_double[0]; - state.g.ptr.p_double[0] = (double)(1); - } - } - lsfitresults(&state, &info, &c, &rep, _state); - if( info<=0 ) - { - ae_set_error_flag(nlserrors, ae_true, __FILE__, __LINE__, "testlsfitunit.ap:1456"); - } - else - { - ae_set_error_flag(nlserrors, ae_fp_greater(ae_fabs(c.ptr.p_double[0]-v, _state),threshold), __FILE__, __LINE__, "testlsfitunit.ap:1459"); - ae_set_error_flag(nlserrors, ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state),threshold), __FILE__, __LINE__, "testlsfitunit.ap:1460"); - ae_set_error_flag(nlserrors, ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state),threshold), __FILE__, __LINE__, "testlsfitunit.ap:1461"); - ae_set_error_flag(nlserrors, ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state),threshold), __FILE__, __LINE__, "testlsfitunit.ap:1462"); - ae_set_error_flag(nlserrors, ae_fp_greater(ae_fabs(rep.maxerror-refmax, _state),threshold), __FILE__, __LINE__, "testlsfitunit.ap:1463"); - } - } - - /* - * Check covariance matrix, errors-in-parameters. - * - * We test three different solvers: - * * nonlinear solver - * * unconstrained linear solver - * * constrained linear solver with empty set of constrains - * on two random problems: - * * problem with known prior, noise, unit weights - * * problem with known prior, noise, non-unit weights - * - * We test that: - * * rep.ErrPar=sqrt(diag(Rep.CovPar)) - * * Rep.ErrPar is not too optimistic - average value of ratio - * between |c_fit-c_prior| and ErrPar[] is less than TOL - * * Rep.ErrPar is not too pessimistic - average value of ratio - * is larger than 1/TOL - * * similarly, Rep.ErrCurve gives good estimate of |A*c_fit - A*c_prior| - * - not optimistic, not pessimistic. - * * similarly, per-point noise estimates are good enough (we use - * slightly different tolerances, though) - * In order to have these estimates we perform many different tests - * and calculate average deviation divided by ErrPar/ErrCurve. Then - * we perform test. - * - * Due to stochastic nature of the test it is not good idea to - * consider each case individually - it is better to average over - * many runs. - * - */ - tol = 10.0; - for(n=1; n<=10; n++) - { - for(skind=0; skind<=2; skind++) - { - for(pkind=0; pkind<=1; pkind++) - { - - /* - * Generate problem: - * * PKind=0 - unit weights - * * PKind=1 - non-unit weights, exact estimate of noise at I-th point - * - * We generate: - * * C - prior values of parameters - * * CStart - random initial point - * * A - function matrix - * * Y - noisy version of A*C - * * W - weights vector - * * S - vector of per-point estimates of noise - */ - cscale = ae_pow(10.0, 2*randomnormal(_state), _state); - xscale = ae_pow(10.0, 2*randomnormal(_state), _state); - noiselevel = 0.01*cscale*xscale; - ae_vector_set_length(&c, n, _state); - ae_vector_set_length(&cstart, n, _state); - for(i=0; i<=n-1; i++) - { - c.ptr.p_double[i] = cscale*randomnormal(_state); - cstart.ptr.p_double[i] = cscale*randomnormal(_state); - } - ae_matrix_set_length(&a, 1000, n, _state); - ae_vector_set_length(&y, a.rows, _state); - ae_vector_set_length(&w, a.rows, _state); - ae_vector_set_length(&s, a.rows, _state); - for(i=0; i<=a.rows-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = xscale*randomnormal(_state); - } - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &c.ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( pkind==0 ) - { - w.ptr.p_double[i] = (double)(1); - s.ptr.p_double[i] = noiselevel; - y.ptr.p_double[i] = v+s.ptr.p_double[i]*randomnormal(_state); - } - if( pkind==1 ) - { - w.ptr.p_double[i] = 1/noiselevel; - s.ptr.p_double[i] = noiselevel; - y.ptr.p_double[i] = v+s.ptr.p_double[i]*randomnormal(_state); - } - } - - /* - * Test different solvers: - * * SKind=0 - nonlinear solver - * * SKind=1 - linear unconstrained - * * SKind=2 - linear constrained with empty set of constraints - */ - info = -1; - if( skind==0 ) - { - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - lsfitcreatefg(&a, &y, &cstart, a.rows, n, n, ae_true, &state, _state); - } - else - { - lsfitcreatef(&a, &y, &cstart, a.rows, n, n, 0.001*cscale, &state, _state); - } - lsfitsetcond(&state, 0.0, 10, _state); - while(lsfititeration(&state, _state)) - { - if( state.needf ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+state.c.ptr.p_double[i]*state.x.ptr.p_double[i]; - } - } - if( state.needfg ) - { - state.f = (double)(0); - for(i=0; i<=n-1; i++) - { - state.f = state.f+state.c.ptr.p_double[i]*state.x.ptr.p_double[i]; - state.g.ptr.p_double[i] = state.x.ptr.p_double[i]; - } - } - } - lsfitresults(&state, &info, &cend, &rep, _state); - } - if( skind==1 ) - { - if( pkind==0 ) - { - lsfitlinear(&y, &a, a.rows, n, &info, &cend, &rep, _state); - } - else - { - lsfitlinearw(&y, &w, &a, a.rows, n, &info, &cend, &rep, _state); - } - } - if( skind==2 ) - { - if( pkind==0 ) - { - lsfitlinearc(&y, &a, &a2, a.rows, n, 0, &info, &cend, &rep, _state); - } - else - { - lsfitlinearwc(&y, &w, &a, &a2, a.rows, n, 0, &info, &cend, &rep, _state); - } - } - - /* - * Tests: - * * check relation between CovPar and ErrPar - * * accumulate average deviation in parameters - * * accumulate average deviation in curve fit - * * accumulate average deviation in noise estimate - */ - avgdeviationpar = (double)(0); - adpcnt = (double)(0); - avgdeviationcurve = (double)(0); - adccnt = (double)(0); - avgdeviationnoise = (double)(0); - adncnt = (double)(0); - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(llserrors, ae_fp_greater(ae_fabs(rep.covpar.ptr.pp_double[i][i]-ae_sqr(rep.errpar.ptr.p_double[i], _state), _state),100*ae_machineepsilon*ae_maxreal(ae_sqr(rep.errpar.ptr.p_double[i], _state), rep.covpar.ptr.pp_double[i][i], _state)), __FILE__, __LINE__, "testlsfitunit.ap:1612"); - } - for(i=0; i<=n-1; i++) - { - avgdeviationpar = (avgdeviationpar*adpcnt+ae_fabs(c.ptr.p_double[i]-cend.ptr.p_double[i], _state)/rep.errpar.ptr.p_double[i])/(adpcnt+1); - adpcnt = adpcnt+1; - } - for(i=0; i<=a.rows-1; i++) - { - v1 = ae_v_dotproduct(&c.ptr.p_double[0], 1, &a.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - v2 = ae_v_dotproduct(&cend.ptr.p_double[0], 1, &a.ptr.pp_double[i][0], 1, ae_v_len(0,n-1)); - avgdeviationcurve = (avgdeviationcurve*adccnt+ae_fabs(v1-v2, _state)/rep.errcurve.ptr.p_double[i])/(adccnt+1); - adccnt = adccnt+1; - avgdeviationnoise = (avgdeviationnoise*adncnt+rep.noise.ptr.p_double[i]/s.ptr.p_double[i])/(adncnt+1); - adncnt = adncnt+1; - } - - /* - * Check that estimates are not too optimistic. - * This test is performed always. - */ - ae_set_error_flag(llserrors, ae_fp_greater(avgdeviationpar,tol), __FILE__, __LINE__, "testlsfitunit.ap:1632"); - ae_set_error_flag(llserrors, ae_fp_greater(avgdeviationcurve,tol), __FILE__, __LINE__, "testlsfitunit.ap:1633"); - ae_set_error_flag(llserrors, ae_fp_greater(avgdeviationnoise,1.50), __FILE__, __LINE__, "testlsfitunit.ap:1634"); - ae_set_error_flag(llserrors, ae_fp_less(avgdeviationnoise,0.66), __FILE__, __LINE__, "testlsfitunit.ap:1635"); - - /* - * Test for estimates being too pessimistic is performed only - * when we have more than 4 parameters. - */ - ae_set_error_flag(llserrors, n>=5&&ae_fp_less(avgdeviationcurve,0.01), __FILE__, __LINE__, "testlsfitunit.ap:1641"); - ae_set_error_flag(llserrors, n>=5&&ae_fp_less(avgdeviationpar,0.01), __FILE__, __LINE__, "testlsfitunit.ap:1642"); - } - } - } - - /* - * Check special property of the LSFit solver: it does not include points with - * zero weight in the estimate of the noise level. Such property seems to be - * quite natural, but in fact it requires some additional code in order to - * ignore such points. - * - * In order to test it we solve two problems: one 300xN, with 150 non-zero - * weights and 150 zero weights - and another one with only 150 points with - * non-zero weights. Both problems should give us same covariance matrix. - */ - tol = (double)(10); - for(n=1; n<=10; n++) - { - - /* - * Generate N-dimensional linear problem with 300 points: - * * y = c'*x + noise - * * prior values of coefficients C has scale CScale - * * coordinates X has scale XScale - * * noise in I-th point has magnitude 0.1*CScale*XScale*WScale/W[i] - */ - cscale = ae_pow(10.0, 2*randomnormal(_state), _state); - xscale = ae_pow(10.0, 2*randomnormal(_state), _state); - wscale = ae_pow(10.0, 2*randomnormal(_state), _state); - noiselevel = 0.1*cscale*xscale; - ae_vector_set_length(&c, n, _state); - ae_vector_set_length(&cstart, n, _state); - for(i=0; i<=n-1; i++) - { - c.ptr.p_double[i] = cscale*randomnormal(_state); - cstart.ptr.p_double[i] = cscale*randomnormal(_state); - } - ae_matrix_set_length(&a, 300, n, _state); - ae_vector_set_length(&y, a.rows, _state); - ae_vector_set_length(&w, a.rows, _state); - for(i=0; i<=a.rows-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = xscale*randomnormal(_state); - } - v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &c.ptr.p_double[0], 1, ae_v_len(0,n-1)); - if( i0 and NZ<>0, but in - * some cases either N or NZ (but not both) is zero. - * - * X-values have scale equal to ScaleX - */ - scalex = ae_pow((double)(10), 30*hqrnduniformr(&rs, _state)-15, _state); - n = 40+hqrnduniformi(&rs, 40, _state); - nz = 4+hqrnduniformi(&rs, 4, _state); - if( ae_fp_less(hqrnduniformr(&rs, _state),0.1) ) - { - if( ae_fp_less(hqrnduniformr(&rs, _state),0.5) ) - { - n = 0; - } - else - { - nz = 0; - } - } - ntotal = 2*(n+nz); - ae_vector_set_length(&x, ntotal, _state); - for(i=0; i<=n-1; i++) - { - v = scalex*ae_exp(ae_log((double)(5), _state)*(2*hqrnduniformr(&rs, _state)-1), _state); - x.ptr.p_double[2*i+0] = v; - x.ptr.p_double[2*i+1] = v; - } - for(i=0; i<=nz-1; i++) - { - x.ptr.p_double[2*n+2*i+0] = (double)(0); - x.ptr.p_double[2*n+2*i+1] = (double)(0); - } - - /* - * Fenerate A/B/C/D: - * * A/D are random with scale equal to ScaleY - * * B is in +-[0.25,4.0] - * * for C we choose one of X[], if N>0; - * if N=0, we set C=1. - */ - scaley = ae_pow((double)(10), 30*hqrnduniformr(&rs, _state)-15, _state); - ae = scaley*(hqrnduniformr(&rs, _state)-0.5); - be = (2*hqrnduniformi(&rs, 2, _state)-1)*ae_exp(ae_log((double)(4), _state)*(2*hqrnduniformr(&rs, _state)-1), _state); - ce = scalex*ae_exp(ae_log((double)(2), _state)*(2*hqrnduniformr(&rs, _state)-1), _state); - de = ae+scaley*(2*hqrnduniformi(&rs, 2, _state)-1)*(hqrnduniformr(&rs, _state)+0.5); - - /* - * Choose noise level and generate Y[]. - */ - noise = 0.05*scaley; - ae_vector_set_length(&y, ntotal, _state); - for(i=0; i<=ntotal/2-1; i++) - { - if( ae_fp_neq(x.ptr.p_double[2*i+0],(double)(0)) ) - { - v = de+(ae-de)/(1.0+ae_pow(x.ptr.p_double[2*i+0]/ce, be, _state)); - } - else - { - if( ae_fp_greater_eq(be,(double)(0)) ) - { - v = ae; - } - else - { - v = de; - } - } - y.ptr.p_double[2*i+0] = v+noise; - y.ptr.p_double[2*i+1] = v-noise; - } - - /* - * Unconstrained fit and test - * - * NOTE: we test that B>=0 is returned. If BE<0, we use - * symmetry property of 4PL model. - */ - logisticfit4(&x, &y, ntotal, &a, &b, &c, &d, &rep, _state); - ae_set_error_flag(fiterrors, !ae_isfinite(a, _state), __FILE__, __LINE__, "testlsfitunit.ap:2162"); - ae_set_error_flag(fiterrors, !ae_isfinite(b, _state), __FILE__, __LINE__, "testlsfitunit.ap:2163"); - ae_set_error_flag(fiterrors, !ae_isfinite(c, _state), __FILE__, __LINE__, "testlsfitunit.ap:2164"); - ae_set_error_flag(fiterrors, !ae_isfinite(d, _state), __FILE__, __LINE__, "testlsfitunit.ap:2165"); - ae_set_error_flag(fiterrors, ae_fp_less(b,(double)(0)), __FILE__, __LINE__, "testlsfitunit.ap:2166"); - v = 0.0; - for(i=0; i<=ntotal-1; i++) - { - if( ae_fp_neq(x.ptr.p_double[i],(double)(0)) ) - { - vv = d+(a-d)/(1.0+ae_pow(x.ptr.p_double[i]/c, b, _state)); - } - else - { - vv = a; - } - v = v+ae_sqr(y.ptr.p_double[i]-vv, _state); - } - v = ae_sqrt(v/ntotal, _state); - ae_set_error_flag(fiterrors, ae_fp_greater(v,(1+tol)*noise), __FILE__, __LINE__, "testlsfitunit.ap:2177"); - - /* - * Constrained fit and test - * - * NOTE: we test that B>=0 is returned. If BE<0, we use - * symmetry property of 4PL model. - */ - for(k0=0; k0<=1; k0++) - { - for(k1=0; k1<=1; k1++) - { - - /* - * Choose constraints. - */ - if( k0==0 ) - { - v0 = _state->v_nan; - } - else - { - if( ae_fp_greater_eq(be,(double)(0)) ) - { - v0 = ae; - } - else - { - v0 = de; - } - } - if( k1==0 ) - { - v1 = _state->v_nan; - } - else - { - if( ae_fp_greater_eq(be,(double)(0)) ) - { - v1 = de; - } - else - { - v1 = ae; - } - } - - /* - * Fit - */ - logisticfit4ec(&x, &y, ntotal, v0, v1, &a, &b, &c, &d, &rep, _state); - - /* - * Check - */ - ae_set_error_flag(fiterrors, !ae_isfinite(a, _state), __FILE__, __LINE__, "testlsfitunit.ap:2218"); - ae_set_error_flag(fiterrors, !ae_isfinite(b, _state), __FILE__, __LINE__, "testlsfitunit.ap:2219"); - ae_set_error_flag(fiterrors, !ae_isfinite(c, _state), __FILE__, __LINE__, "testlsfitunit.ap:2220"); - ae_set_error_flag(fiterrors, !ae_isfinite(d, _state), __FILE__, __LINE__, "testlsfitunit.ap:2221"); - ae_set_error_flag(fiterrors, ae_fp_less(b,(double)(0)), __FILE__, __LINE__, "testlsfitunit.ap:2222"); - ae_set_error_flag(fiterrors, k0!=0&&ae_fp_neq(a,v0), __FILE__, __LINE__, "testlsfitunit.ap:2223"); - ae_set_error_flag(fiterrors, k1!=0&&ae_fp_neq(d,v1), __FILE__, __LINE__, "testlsfitunit.ap:2224"); - v = 0.0; - for(i=0; i<=ntotal-1; i++) - { - if( ae_fp_neq(x.ptr.p_double[i],(double)(0)) ) - { - vv = d+(a-d)/(1.0+ae_pow(x.ptr.p_double[i]/c, b, _state)); - } - else - { - if( ae_fp_greater_eq(b,(double)(0)) ) - { - vv = a; - } - else - { - vv = d; - } - } - v = v+ae_sqr(y.ptr.p_double[i]-vv, _state); - } - v = ae_sqrt(v/ntotal, _state); - ae_set_error_flag(fiterrors, ae_fp_greater(v,(1+tol)*noise), __FILE__, __LINE__, "testlsfitunit.ap:2240"); - } - } - } - - /* - * 5PL fitting - * - * Generate random AE/BE/CE/DE/GE, generate random set of points and for - * each point generate two function values: F(x)+eps and F(x)-eps. - * Such problem has solution which is exactly AE/BE/CE/DE which were - * used to generate points. - * - * NOTE: because problem has higher condition number, we use lower - * tolerance for power parameters B and G. - * - * This test checks both unconstrained and constrained fitting. - */ - tol = 1.0E-6; - for(pass=1; pass<=10; pass++) - { - - /* - * Generate N points, N-1 of them with non-zero X and - * last one with zero X. - * X-values have scale equal to ScaleX - */ - scalex = ae_pow((double)(10), 30*hqrnduniformr(&rs, _state)-15, _state); - k = 50; - n = 2*k+1; - ae_vector_set_length(&x, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = scalex*ae_pow((double)(2), (double)(2*(i-k))/(double)k, _state); - } - x.ptr.p_double[n-1] = (double)(0); - - /* - * Generate A/B/C/D/G: - * * A/D are random with scale equal to ScaleY - * * B is in +-[0.25,4.0] - * * G is in [0.25,4.0] - * * C is in [0.25,4.0]*ScaleX - * if N=0, we set C=1. - * Generate Y[]. - */ - scaley = ae_pow((double)(10), 30*hqrnduniformr(&rs, _state)-15, _state); - ae = scaley*(hqrnduniformr(&rs, _state)-0.5); - be = (2*hqrnduniformi(&rs, 2, _state)-1)*ae_exp(ae_log((double)(2), _state)*(2*hqrnduniformr(&rs, _state)-1), _state); - ce = scalex*ae_exp(ae_log((double)(2), _state)*(2*hqrnduniformr(&rs, _state)-1), _state); - de = ae+scaley*(2*hqrnduniformi(&rs, 2, _state)-1)*(hqrnduniformr(&rs, _state)+0.5); - ge = ae_exp(ae_log((double)(2), _state)*(2*hqrnduniformr(&rs, _state)-1), _state); - ae_vector_set_length(&y, n, _state); - for(i=0; i<=n-1; i++) - { - if( ae_fp_neq(x.ptr.p_double[i],(double)(0)) ) - { - v = de+(ae-de)/ae_pow(1.0+ae_pow(x.ptr.p_double[i]/ce, be, _state), ge, _state); - } - else - { - if( ae_fp_greater_eq(be,(double)(0)) ) - { - v = ae; - } - else - { - v = de; - } - } - y.ptr.p_double[i] = v; - } - - /* - * Unconstrained fit and test - * - * NOTE: we test that B>=0 is returned. If BE<0, we use - * symmetry property of 4PL model. - */ - logisticfit5(&x, &y, n, &a, &b, &c, &d, &g, &rep, _state); - v = 0.0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_neq(x.ptr.p_double[i],(double)(0)) ) - { - vv = d+(a-d)/ae_pow(1.0+ae_pow(x.ptr.p_double[i]/c, b, _state), g, _state); - } - else - { - if( ae_fp_greater_eq(b,(double)(0)) ) - { - vv = a; - } - else - { - vv = d; - } - } - v = v+ae_sqr(y.ptr.p_double[i]-vv, _state); - } - v = ae_sqrt(v/n, _state); - ae_set_error_flag(fiterrors, ae_fp_greater(v,scaley*tol), __FILE__, __LINE__, "testlsfitunit.ap:2325"); - - /* - * Constrained fit and test - */ - for(k0=0; k0<=1; k0++) - { - for(k1=0; k1<=1; k1++) - { - - /* - * Choose constraints. - */ - if( k0==0 ) - { - v0 = _state->v_nan; - } - else - { - if( ae_fp_greater_eq(be,(double)(0)) ) - { - v0 = ae; - } - else - { - v0 = de; - } - } - if( k1==0 ) - { - v1 = _state->v_nan; - } - else - { - if( ae_fp_greater_eq(be,(double)(0)) ) - { - v1 = de; - } - else - { - v1 = ae; - } - } - - /* - * Fit - */ - logisticfit5ec(&x, &y, n, v0, v1, &a, &b, &c, &d, &g, &rep, _state); - ae_set_error_flag(fiterrors, !ae_isfinite(a, _state), __FILE__, __LINE__, "testlsfitunit.ap:2359"); - ae_set_error_flag(fiterrors, !ae_isfinite(b, _state), __FILE__, __LINE__, "testlsfitunit.ap:2360"); - ae_set_error_flag(fiterrors, !ae_isfinite(c, _state), __FILE__, __LINE__, "testlsfitunit.ap:2361"); - ae_set_error_flag(fiterrors, !ae_isfinite(d, _state), __FILE__, __LINE__, "testlsfitunit.ap:2362"); - if( ae_fp_greater(b,(double)(0)) ) - { - ae_set_error_flag(fiterrors, k0!=0&&ae_fp_neq(a,v0), __FILE__, __LINE__, "testlsfitunit.ap:2365"); - ae_set_error_flag(fiterrors, k1!=0&&ae_fp_neq(d,v1), __FILE__, __LINE__, "testlsfitunit.ap:2366"); - } - else - { - ae_set_error_flag(fiterrors, k0!=0&&ae_fp_neq(d,v0), __FILE__, __LINE__, "testlsfitunit.ap:2370"); - ae_set_error_flag(fiterrors, k1!=0&&ae_fp_neq(a,v1), __FILE__, __LINE__, "testlsfitunit.ap:2371"); - } - v = 0.0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_neq(x.ptr.p_double[i],(double)(0)) ) - { - vv = d+(a-d)/ae_pow(1.0+ae_pow(x.ptr.p_double[i]/c, b, _state), g, _state); - } - else - { - if( ae_fp_greater_eq(b,(double)(0)) ) - { - vv = a; - } - else - { - vv = d; - } - } - v = v+ae_sqr(y.ptr.p_double[i]-vv, _state); - } - v = ae_sqrt(v/n, _state); - ae_set_error_flag(fiterrors, ae_fp_greater(v,scaley*tol), __FILE__, __LINE__, "testlsfitunit.ap:2388"); - } - } - } - - /* - * Test correctness of errors - */ - tol = 1.0E-6; - for(pass=1; pass<=20; pass++) - { - n = 10; - meany = 0.0; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = (double)(i); - y.ptr.p_double[i] = hqrnduniformr(&rs, _state)-0.5; - meany = meany+y.ptr.p_double[i]; - } - meany = meany/n; - x.ptr.p_double[1] = (double)(0); - - /* - * Choose model fitting function to test - */ - k = hqrnduniformi(&rs, 4, _state); - a = (double)(0); - d = (double)(0); - c = (double)(1); - b = (double)(1); - g = (double)(1); - if( k==0 ) - { - logisticfit4(&x, &y, n, &a, &b, &c, &d, &rep, _state); - g = 1.0; - } - if( k==1 ) - { - logisticfit4ec(&x, &y, n, hqrnduniformr(&rs, _state)-0.5, hqrnduniformr(&rs, _state)-0.5, &a, &b, &c, &d, &rep, _state); - g = 1.0; - } - if( k==2 ) - { - logisticfit5(&x, &y, n, &a, &b, &c, &d, &g, &rep, _state); - } - if( k==3 ) - { - logisticfit5ec(&x, &y, n, hqrnduniformr(&rs, _state)-0.5, hqrnduniformr(&rs, _state)-0.5, &a, &b, &c, &d, &g, &rep, _state); - } - k = 0; - erms = (double)(0); - eavg = (double)(0); - eavgrel = (double)(0); - emax = (double)(0); - rss = 0.0; - tss = 0.0; - for(i=0; i<=n-1; i++) - { - if( ae_fp_neq(x.ptr.p_double[i],(double)(0)) ) - { - v = d+(a-d)/ae_pow(1.0+ae_pow(x.ptr.p_double[i]/c, b, _state), g, _state); - } - else - { - if( ae_fp_greater_eq(b,(double)(0)) ) - { - v = a; - } - else - { - v = d; - } - } - v = v-y.ptr.p_double[i]; - rss = rss+v*v; - tss = tss+ae_sqr(y.ptr.p_double[i]-meany, _state); - erms = erms+ae_sqr(v, _state); - eavg = eavg+ae_fabs(v, _state); - if( ae_fp_neq(y.ptr.p_double[i],(double)(0)) ) - { - eavgrel = eavgrel+ae_fabs(v/y.ptr.p_double[i], _state); - k = k+1; - } - emax = ae_maxreal(emax, ae_fabs(v, _state), _state); - } - er2 = 1.0-rss/tss; - erms = ae_sqrt(erms/n, _state); - eavg = eavg/n; - if( k>0 ) - { - eavgrel = eavgrel/k; - } - ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(erms-rep.rmserror, _state),tol), __FILE__, __LINE__, "testlsfitunit.ap:2477"); - ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(eavg-rep.avgerror, _state),tol), __FILE__, __LINE__, "testlsfitunit.ap:2478"); - ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(emax-rep.maxerror, _state),tol), __FILE__, __LINE__, "testlsfitunit.ap:2479"); - ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(eavgrel-rep.avgrelerror, _state),tol), __FILE__, __LINE__, "testlsfitunit.ap:2480"); - ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(er2-rep.r2, _state),tol), __FILE__, __LINE__, "testlsfitunit.ap:2481"); - } - - /* - * Test previously fixed bug #834 - */ - ae_vector_set_length(&x, 0, _state); - testlsfitunit_append10(&x, 0.019556, 0.093533, 0.13780, 0.25210, 0.46373, 0.23997, 0.52861, 0.50526, 0.43401, 0.82270, _state); - testlsfitunit_append10(&x, 0.65746, 0.76479, 0.81512, 0.89031, 1.1959, 1.2032, 1.0671, 1.2350, 1.2954, 1.5422, _state); - testlsfitunit_append10(&x, 1.4306, 1.5628, 1.6774, 1.8053, 1.9866, 2.1446, 2.1740, 2.2574, 2.2662, 2.4035, _state); - testlsfitunit_append10(&x, 2.7225, 2.6500, 2.7752, 2.9126, 2.8962, 3.0439, 3.1260, 3.2458, 3.3613, 3.3728, _state); - testlsfitunit_append10(&x, 3.5641, 3.5168, 3.6975, 3.7848, 3.8421, 3.9058, 4.0292, 4.1111, 4.0835, 4.3436, _state); - testlsfitunit_append10(&x, 4.3982, 4.6098, 4.3606, 4.5595, 4.7099, 4.8806, 4.9779, 4.9909, 5.0121, 5.2571, _state); - testlsfitunit_append10(&x, 5.3663, 5.4739, 5.5818, 5.5224, 5.7895, 5.9141, 6.0897, 6.1476, 6.2491, 6.3541, _state); - testlsfitunit_append10(&x, 6.4007, 6.5969, 6.6530, 6.7837, 6.8692, 6.9383, 7.0344, 7.1702, 7.3118, 7.3728, _state); - testlsfitunit_append10(&x, 7.4589, 7.6068, 7.6290, 7.8139, 7.9891, 8.0425, 8.1817, 8.3442, 8.3772, 8.4691, _state); - testlsfitunit_append10(&x, 8.5864, 8.7201, 8.9721, 8.9208, 9.0603, 9.1961, 9.3344, 9.3738, 9.4808, 9.6527, _state); - testlsfitunit_append10(&x, 9.7197, 9.8180, 10.034, 10.155, 10.205, 10.323, 10.421, 10.571, 10.723, 10.795, _state); - testlsfitunit_append10(&x, 11.000, 10.977, 11.145, 11.249, 11.425, 11.495, 11.598, 11.723, 11.787, 12.001, _state); - testlsfitunit_append10(&x, 12.005, 12.136, 12.312, 12.381, 12.417, 12.645, 12.766, 12.864, 12.889, 13.017, _state); - testlsfitunit_append10(&x, 13.171, 13.323, 13.406, 13.451, 13.551, 13.732, 13.735, 13.909, 14.075, 14.150, _state); - testlsfitunit_append10(&x, 14.265, 14.365, 14.524, 14.541, 14.679, 14.836, 14.998, 15.071, 15.170, 15.238, _state); - testlsfitunit_append10(&x, 15.327, 15.388, 15.614, 15.729, 15.671, 15.858, 15.984, 16.008, 16.219, 16.231, _state); - testlsfitunit_append10(&x, 16.424, 16.642, 16.784, 16.837, 16.959, 17.000, 17.088, 17.162, 17.210, 17.460, _state); - testlsfitunit_append10(&x, 17.597, 17.698, 17.679, 17.962, 17.974, 17.966, 18.240, 18.240, 18.521, 18.645, _state); - testlsfitunit_append10(&x, 18.739, 18.830, 18.749, 19.062, 19.062, 19.160, 19.224, 19.334, 19.395, 19.567, _state); - ae_vector_set_length(&y, 0, _state); - testlsfitunit_append10(&y, 0.096932, 0.099305, 0.098981, 0.098981, 0.099898, 0.096879, 0.098334, 0.097525, 0.097418, 0.098065, _state); - testlsfitunit_append10(&y, 0.098334, 0.096016, 0.098172, 0.096339, 0.098550, 0.098927, 0.099898, 0.098927, 0.097472, 0.097418, _state); - testlsfitunit_append10(&y, 0.098604, 0.097849, 0.096932, 0.098765, 0.097957, 0.099143, 0.097795, 0.098819, 0.098550, 0.098658, _state); - testlsfitunit_append10(&y, 0.099143, 0.096609, 0.099358, 0.099358, 0.100110, 0.098819, 0.097148, 0.098604, 0.095692, 0.097849, _state); - testlsfitunit_append10(&y, 0.098172, 0.097957, 0.099898, 0.097687, 0.097364, 0.098226, 0.098280, 0.099844, 0.099143, 0.098765, _state); - testlsfitunit_append10(&y, 0.099412, 0.098442, 0.100110, 0.098172, 0.098334, 0.096932, 0.097687, 0.098981, 0.098873, 0.096501, _state); - testlsfitunit_append10(&y, 0.098550, 0.099682, 0.100170, 0.098927, 0.099628, 0.099628, 0.099197, 0.099089, 0.098550, 0.098819, _state); - testlsfitunit_append10(&y, 0.099035, 0.097202, 0.099736, 0.099628, 0.099035, 0.099035, 0.099305, 0.097795, 0.099143, 0.100060, _state); - testlsfitunit_append10(&y, 0.098442, 0.099951, 0.098065, 0.099628, 0.098388, 0.099898, 0.098873, 0.099520, 0.097795, 0.097687, _state); - testlsfitunit_append10(&y, 0.098658, 0.098765, 0.099628, 0.099736, 0.098388, 0.099628, 0.099251, 0.098334, 0.097903, 0.099682, _state); - testlsfitunit_append10(&y, 0.097094, 0.098765, 0.098765, 0.098981, 0.099574, 0.099736, 0.098280, 0.099520, 0.099466, 0.099790, _state); - testlsfitunit_append10(&y, 0.099358, 0.098873, 0.097579, 0.099143, 0.099951, 0.099035, 0.097256, 0.098765, 0.099520, 0.099790, _state); - testlsfitunit_append10(&y, 0.097094, 0.099520, 0.099305, 0.098765, 0.098604, 0.099790, 0.098226, 0.099251, 0.098819, 0.099574, _state); - testlsfitunit_append10(&y, 0.099682, 0.099951, 0.098119, 0.100220, 0.099197, 0.098334, 0.099035, 0.098927, 0.099628, 0.10076, _state); - testlsfitunit_append10(&y, 0.10081, 0.10351, 0.10367, 0.10405, 0.10502, 0.10815, 0.11208, 0.11451, 0.11467, 0.11639, _state); - testlsfitunit_append10(&y, 0.11839, 0.12195, 0.12378, 0.12577, 0.12755, 0.12842, 0.13262, 0.13747, 0.14486, 0.15483, _state); - testlsfitunit_append10(&y, 0.17554, 0.20422, 0.23796, 0.27581, 0.31495, 0.35576, 0.39857, 0.44374, 0.48946, 0.53475, _state); - testlsfitunit_append10(&y, 0.57766, 0.61960, 0.65400, 0.68936, 0.72268, 0.75573, 0.78446, 0.81169, 0.83185, 0.86247, _state); - testlsfitunit_append10(&y, 0.88797, 0.91083, 0.93142, 0.94916, 0.96463, 0.97881, 0.98809, 0.99774, 0.99844, 1.00000, _state); - logisticfit4(&x, &y, 190, &a, &b, &c, &d, &rep, _state); - ae_set_error_flag(fiterrors, ae_fp_less(b,31.90)||ae_fp_greater(b,32.00), __FILE__, __LINE__, "testlsfitunit.ap:2528"); - ae_set_error_flag(fiterrors, ae_fp_greater(rep.rmserror,0.02), __FILE__, __LINE__, "testlsfitunit.ap:2529"); - logisticfit5(&x, &y, 190, &a, &b, &c, &d, &g, &rep2, _state); - ae_set_error_flag(fiterrors, ae_fp_greater(rep2.rmserror,0.95*rep.rmserror), __FILE__, __LINE__, "testlsfitunit.ap:2531"); - ae_frame_leave(_state); -} - - -/************************************************************************* -Test for box constrained problemsNLS. -On failure sets error flag, leaves it unchanged on success. -*************************************************************************/ -static void testlsfitunit_testbcnls(ae_bool* errorflag, ae_state *_state) -{ - ae_frame _frame_block; - lsfitstate state; - lsfitreport rep; - ae_vector bl; - ae_vector bu; - ae_int_t nx; - ae_int_t nc; - ae_int_t m; - ae_vector x; - ae_vector c0; - ae_vector c1; - ae_vector c2; - ae_matrix xx; - ae_vector y; - ae_int_t i; - ae_int_t j; - ae_int_t ii; - double v; - double h; - hqrndstate rs; - double epsx; - double f0; - double f1; - ae_int_t tmpkind; - ae_int_t terminationtype; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&bl, 0, sizeof(bl)); - memset(&bu, 0, sizeof(bu)); - memset(&x, 0, sizeof(x)); - memset(&c0, 0, sizeof(c0)); - memset(&c1, 0, sizeof(c1)); - memset(&c2, 0, sizeof(c2)); - memset(&xx, 0, sizeof(xx)); - memset(&y, 0, sizeof(y)); - memset(&rs, 0, sizeof(rs)); - _lsfitstate_init(&state, _state, ae_true); - _lsfitreport_init(&rep, _state, ae_true); - ae_vector_init(&bl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c2, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xx, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Fit - * - * [ ] - * f(X|C)= SUM_j[ (alpha*c_j+power(c_j,3))*x_j ] - * [ ] - * - * subject to non-negativity constraints on c_j - */ - epsx = 1.0E-9; - for(tmpkind=0; tmpkind<=1; tmpkind++) - { - for(nc=1; nc<=20; nc++) - { - nx = nc; - m = nc+hqrnduniformi(&rs, nc, _state); - ae_vector_set_length(&bl, nc, _state); - ae_vector_set_length(&bu, nc, _state); - ae_vector_set_length(&c0, nc, _state); - ae_vector_set_length(&x, nx, _state); - for(i=0; i<=nc-1; i++) - { - bl.ptr.p_double[i] = (double)(0); - bu.ptr.p_double[i] = _state->v_posinf; - c0.ptr.p_double[i] = 1+hqrnduniformr(&rs, _state); - } - ae_matrix_set_length(&xx, m, nx, _state); - ae_vector_set_length(&y, m, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=nx-1; j++) - { - xx.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - y.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - if( tmpkind==0 ) - { - lsfitcreatef(&xx, &y, &c0, m, nx, nc, 10*epsx, &state, _state); - } - if( tmpkind==1 ) - { - lsfitcreatefg(&xx, &y, &c0, m, nx, nc, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &state, _state); - } - lsfitsetcond(&state, epsx, 0, _state); - lsfitsetbc(&state, &bl, &bu, _state); - while(lsfititeration(&state, _state)) - { - for(i=0; i<=nc-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_less(state.c.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2603"); - ae_set_error_flag(errorflag, ae_fp_greater(state.c.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2604"); - } - if( state.needf ) - { - testlsfitunit_testfunc1(nx, &state.x, &state.c, &state.f, ae_true, &state.g, ae_false, _state); - continue; - } - if( state.needfg ) - { - testlsfitunit_testfunc1(nx, &state.x, &state.c, &state.f, ae_true, &state.g, ae_true, _state); - continue; - } - ae_assert(ae_false, "minlm test: integrity check failed", _state); - } - lsfitresults(&state, &terminationtype, &c1, &rep, _state); - ae_set_error_flag(errorflag, terminationtype<=0, __FILE__, __LINE__, "testlsfitunit.ap:2619"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - f0 = (double)(0); - for(ii=0; ii<=m-1; ii++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1)); - testlsfitunit_testfunc1(nx, &x, &c1, &v, ae_true, &state.g, ae_false, _state); - f0 = f0+ae_sqr(v-y.ptr.p_double[ii], _state); - } - h = 0.001; - ae_vector_set_length(&c2, nc, _state); - for(i=0; i<=nc-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_less(c1.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2636"); - ae_set_error_flag(errorflag, ae_fp_greater(c1.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2637"); - if( ae_fp_greater_eq(c1.ptr.p_double[i]+h,bl.ptr.p_double[i]) ) - { - for(j=0; j<=nc-1; j++) - { - c2.ptr.p_double[j] = c1.ptr.p_double[j]; - } - c2.ptr.p_double[i] = c2.ptr.p_double[i]+h; - f1 = (double)(0); - for(ii=0; ii<=m-1; ii++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1)); - testlsfitunit_testfunc1(nx, &x, &c2, &v, ae_true, &state.g, ae_false, _state); - f1 = f1+ae_sqr(v-y.ptr.p_double[ii], _state); - } - ae_set_error_flag(errorflag, ae_fp_less(f1,f0), __FILE__, __LINE__, "testlsfitunit.ap:2652"); - } - if( ae_fp_greater_eq(c1.ptr.p_double[i]-h,bl.ptr.p_double[i]) ) - { - for(j=0; j<=nc-1; j++) - { - c2.ptr.p_double[j] = c1.ptr.p_double[j]; - } - c2.ptr.p_double[i] = c2.ptr.p_double[i]-h; - f1 = (double)(0); - for(ii=0; ii<=m-1; ii++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1)); - testlsfitunit_testfunc1(nx, &x, &c2, &v, ae_true, &state.g, ae_false, _state); - f1 = f1+ae_sqr(v-y.ptr.p_double[ii], _state); - } - ae_set_error_flag(errorflag, ae_fp_less(f1,f0), __FILE__, __LINE__, "testlsfitunit.ap:2668"); - } - } - } - } - - /* - * Fit - * - * [ ] - * f(X|C)= SUM_j[ (alpha*c_j+power(c_j,3))*x_j ] - * [ ] - * - * subject to random box constraints on c_j - */ - epsx = 1.0E-9; - for(tmpkind=0; tmpkind<=1; tmpkind++) - { - for(nc=1; nc<=20; nc++) - { - nx = nc; - m = nc+hqrnduniformi(&rs, nc, _state); - ae_vector_set_length(&bl, nc, _state); - ae_vector_set_length(&bu, nc, _state); - ae_vector_set_length(&c0, nc, _state); - ae_vector_set_length(&x, nx, _state); - for(i=0; i<=nc-1; i++) - { - bl.ptr.p_double[i] = hqrndnormal(&rs, _state); - bu.ptr.p_double[i] = bl.ptr.p_double[i]+hqrnduniformr(&rs, _state); - c0.ptr.p_double[i] = 1+hqrnduniformr(&rs, _state); - } - ae_matrix_set_length(&xx, m, nx, _state); - ae_vector_set_length(&y, m, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=nx-1; j++) - { - xx.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - y.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - if( tmpkind==0 ) - { - lsfitcreatef(&xx, &y, &c0, m, nx, nc, 10*epsx, &state, _state); - } - if( tmpkind==1 ) - { - lsfitcreatefg(&xx, &y, &c0, m, nx, nc, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &state, _state); - } - lsfitsetcond(&state, epsx, 0, _state); - lsfitsetbc(&state, &bl, &bu, _state); - while(lsfititeration(&state, _state)) - { - for(i=0; i<=nc-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_less(state.c.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2717"); - ae_set_error_flag(errorflag, ae_fp_greater(state.c.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2718"); - } - if( state.needf ) - { - testlsfitunit_testfunc1(nx, &state.x, &state.c, &state.f, ae_true, &state.g, ae_false, _state); - continue; - } - if( state.needfg ) - { - testlsfitunit_testfunc1(nx, &state.x, &state.c, &state.f, ae_true, &state.g, ae_true, _state); - continue; - } - ae_assert(ae_false, "minlm test: integrity check failed", _state); - } - lsfitresults(&state, &terminationtype, &c1, &rep, _state); - ae_set_error_flag(errorflag, terminationtype<=0, __FILE__, __LINE__, "testlsfitunit.ap:2733"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - f0 = (double)(0); - for(ii=0; ii<=m-1; ii++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1)); - testlsfitunit_testfunc1(nx, &x, &c1, &v, ae_true, &state.g, ae_false, _state); - f0 = f0+ae_sqr(v-y.ptr.p_double[ii], _state); - } - h = 0.001; - ae_vector_set_length(&c2, nc, _state); - for(i=0; i<=nc-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_less(c1.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2750"); - ae_set_error_flag(errorflag, ae_fp_greater(c1.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2751"); - if( ae_fp_greater_eq(c1.ptr.p_double[i]+h,bl.ptr.p_double[i])&&ae_fp_less_eq(c1.ptr.p_double[i]+h,bu.ptr.p_double[i]) ) - { - for(j=0; j<=nc-1; j++) - { - c2.ptr.p_double[j] = c1.ptr.p_double[j]; - } - c2.ptr.p_double[i] = c2.ptr.p_double[i]+h; - f1 = (double)(0); - for(ii=0; ii<=m-1; ii++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1)); - testlsfitunit_testfunc1(nx, &x, &c2, &v, ae_true, &state.g, ae_false, _state); - f1 = f1+ae_sqr(v-y.ptr.p_double[ii], _state); - } - ae_set_error_flag(errorflag, ae_fp_less(f1,f0), __FILE__, __LINE__, "testlsfitunit.ap:2766"); - } - if( ae_fp_greater_eq(c1.ptr.p_double[i]-h,bl.ptr.p_double[i])&&ae_fp_less_eq(c1.ptr.p_double[i]-h,bu.ptr.p_double[i]) ) - { - for(j=0; j<=nc-1; j++) - { - c2.ptr.p_double[j] = c1.ptr.p_double[j]; - } - c2.ptr.p_double[i] = c2.ptr.p_double[i]-h; - f1 = (double)(0); - for(ii=0; ii<=m-1; ii++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1)); - testlsfitunit_testfunc1(nx, &x, &c2, &v, ae_true, &state.g, ae_false, _state); - f1 = f1+ae_sqr(v-y.ptr.p_double[ii], _state); - } - ae_set_error_flag(errorflag, ae_fp_less(f1,f0), __FILE__, __LINE__, "testlsfitunit.ap:2782"); - } - } - } - } - - /* - * Fit - * - * - * f(X|C)= c_0 - * - * - * subject to random box constraints on c_0, where X is N-dimensional vector - * (f does not depend on X, and it is not an error! we just test that sizes - * of X and C are correctly handled). - */ - epsx = 1.0E-9; - for(tmpkind=0; tmpkind<=1; tmpkind++) - { - for(nx=1; nx<=20; nx++) - { - nc = 1; - m = nx+hqrnduniformi(&rs, nx, _state); - ae_vector_set_length(&bl, nc, _state); - ae_vector_set_length(&bu, nc, _state); - ae_vector_set_length(&c0, nc, _state); - ae_vector_set_length(&x, nx, _state); - for(i=0; i<=nc-1; i++) - { - bl.ptr.p_double[i] = hqrndnormal(&rs, _state); - bu.ptr.p_double[i] = bl.ptr.p_double[i]+hqrnduniformr(&rs, _state); - c0.ptr.p_double[i] = 1+hqrnduniformr(&rs, _state); - } - ae_matrix_set_length(&xx, m, nx, _state); - ae_vector_set_length(&y, m, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=nx-1; j++) - { - xx.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - y.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - if( tmpkind==0 ) - { - lsfitcreatef(&xx, &y, &c0, m, nx, nc, 10*epsx, &state, _state); - } - if( tmpkind==1 ) - { - lsfitcreatefg(&xx, &y, &c0, m, nx, nc, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &state, _state); - } - lsfitsetcond(&state, epsx, 0, _state); - lsfitsetbc(&state, &bl, &bu, _state); - while(lsfititeration(&state, _state)) - { - for(i=0; i<=nc-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_less(state.c.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2833"); - ae_set_error_flag(errorflag, ae_fp_greater(state.c.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2834"); - } - if( state.needf ) - { - testlsfitunit_testfunc2(&state.x, nx, &state.c, nc, &state.f, ae_true, &state.g, ae_false, _state); - continue; - } - if( state.needfg ) - { - testlsfitunit_testfunc2(&state.x, nx, &state.c, nc, &state.f, ae_true, &state.g, ae_true, _state); - continue; - } - ae_assert(ae_false, "minlm test: integrity check failed", _state); - } - lsfitresults(&state, &terminationtype, &c1, &rep, _state); - ae_set_error_flag(errorflag, terminationtype<=0, __FILE__, __LINE__, "testlsfitunit.ap:2849"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - f0 = (double)(0); - for(ii=0; ii<=m-1; ii++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1)); - testlsfitunit_testfunc2(&x, nx, &c1, nc, &v, ae_true, &state.g, ae_false, _state); - f0 = f0+ae_sqr(v-y.ptr.p_double[ii], _state); - } - h = 0.001; - ae_vector_set_length(&c2, nc, _state); - for(i=0; i<=nc-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_less(c1.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2866"); - ae_set_error_flag(errorflag, ae_fp_greater(c1.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2867"); - if( ae_fp_greater_eq(c1.ptr.p_double[i]+h,bl.ptr.p_double[i])&&ae_fp_less_eq(c1.ptr.p_double[i]+h,bu.ptr.p_double[i]) ) - { - for(j=0; j<=nc-1; j++) - { - c2.ptr.p_double[j] = c1.ptr.p_double[j]; - } - c2.ptr.p_double[i] = c2.ptr.p_double[i]+h; - f1 = (double)(0); - for(ii=0; ii<=m-1; ii++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1)); - testlsfitunit_testfunc2(&x, nx, &c2, nc, &v, ae_true, &state.g, ae_false, _state); - f1 = f1+ae_sqr(v-y.ptr.p_double[ii], _state); - } - ae_set_error_flag(errorflag, ae_fp_less(f1,f0), __FILE__, __LINE__, "testlsfitunit.ap:2882"); - } - if( ae_fp_greater_eq(c1.ptr.p_double[i]-h,bl.ptr.p_double[i])&&ae_fp_less_eq(c1.ptr.p_double[i]-h,bu.ptr.p_double[i]) ) - { - for(j=0; j<=nc-1; j++) - { - c2.ptr.p_double[j] = c1.ptr.p_double[j]; - } - c2.ptr.p_double[i] = c2.ptr.p_double[i]-h; - f1 = (double)(0); - for(ii=0; ii<=m-1; ii++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1)); - testlsfitunit_testfunc2(&x, nx, &c2, nc, &v, ae_true, &state.g, ae_false, _state); - f1 = f1+ae_sqr(v-y.ptr.p_double[ii], _state); - } - ae_set_error_flag(errorflag, ae_fp_less(f1,f0), __FILE__, __LINE__, "testlsfitunit.ap:2898"); - } - } - } - } - - /* - * Fit - * - * - * f(X|C)= c_0 + c_1*x0 + c_2*x0^2 + ... - * - * - * subject to random box constraints on c. - */ - epsx = 1.0E-9; - for(tmpkind=0; tmpkind<=1; tmpkind++) - { - for(nc=1; nc<=5; nc++) - { - nx = 1; - m = 10+nc+hqrnduniformi(&rs, nc, _state); - ae_vector_set_length(&bl, nc, _state); - ae_vector_set_length(&bu, nc, _state); - ae_vector_set_length(&c0, nc, _state); - ae_vector_set_length(&x, nx, _state); - for(i=0; i<=nc-1; i++) - { - bl.ptr.p_double[i] = hqrndnormal(&rs, _state); - bu.ptr.p_double[i] = bl.ptr.p_double[i]+hqrnduniformr(&rs, _state); - c0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_matrix_set_length(&xx, m, nx, _state); - ae_vector_set_length(&y, m, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=nx-1; j++) - { - xx.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - y.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - if( tmpkind==0 ) - { - lsfitcreatef(&xx, &y, &c0, m, nx, nc, 10*epsx, &state, _state); - } - if( tmpkind==1 ) - { - lsfitcreatefg(&xx, &y, &c0, m, nx, nc, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &state, _state); - } - lsfitsetcond(&state, epsx, 0, _state); - lsfitsetbc(&state, &bl, &bu, _state); - while(lsfititeration(&state, _state)) - { - for(i=0; i<=nc-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_less(state.c.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2947"); - ae_set_error_flag(errorflag, ae_fp_greater(state.c.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2948"); - } - if( state.needf ) - { - testlsfitunit_testfunc3(&state.x, nx, &state.c, nc, &state.f, ae_true, &state.g, ae_false, _state); - continue; - } - if( state.needfg ) - { - testlsfitunit_testfunc3(&state.x, nx, &state.c, nc, &state.f, ae_true, &state.g, ae_true, _state); - continue; - } - ae_assert(ae_false, "minlm test: integrity check failed", _state); - } - lsfitresults(&state, &terminationtype, &c1, &rep, _state); - ae_set_error_flag(errorflag, terminationtype<=0, __FILE__, __LINE__, "testlsfitunit.ap:2963"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - f0 = (double)(0); - for(ii=0; ii<=m-1; ii++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1)); - testlsfitunit_testfunc3(&x, nx, &c1, nc, &v, ae_true, &state.g, ae_false, _state); - f0 = f0+ae_sqr(v-y.ptr.p_double[ii], _state); - } - h = 0.001; - ae_vector_set_length(&c2, nc, _state); - for(i=0; i<=nc-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_less(c1.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2980"); - ae_set_error_flag(errorflag, ae_fp_greater(c1.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2981"); - if( ae_fp_greater_eq(c1.ptr.p_double[i]+h,bl.ptr.p_double[i])&&ae_fp_less_eq(c1.ptr.p_double[i]+h,bu.ptr.p_double[i]) ) - { - for(j=0; j<=nc-1; j++) - { - c2.ptr.p_double[j] = c1.ptr.p_double[j]; - } - c2.ptr.p_double[i] = c2.ptr.p_double[i]+h; - f1 = (double)(0); - for(ii=0; ii<=m-1; ii++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1)); - testlsfitunit_testfunc3(&x, nx, &c2, nc, &v, ae_true, &state.g, ae_false, _state); - f1 = f1+ae_sqr(v-y.ptr.p_double[ii], _state); - } - ae_set_error_flag(errorflag, ae_fp_less(f1,f0), __FILE__, __LINE__, "testlsfitunit.ap:2996"); - } - if( ae_fp_greater_eq(c1.ptr.p_double[i]-h,bl.ptr.p_double[i])&&ae_fp_less_eq(c1.ptr.p_double[i]-h,bu.ptr.p_double[i]) ) - { - for(j=0; j<=nc-1; j++) - { - c2.ptr.p_double[j] = c1.ptr.p_double[j]; - } - c2.ptr.p_double[i] = c2.ptr.p_double[i]-h; - f1 = (double)(0); - for(ii=0; ii<=m-1; ii++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1)); - testlsfitunit_testfunc3(&x, nx, &c2, nc, &v, ae_true, &state.g, ae_false, _state); - f1 = f1+ae_sqr(v-y.ptr.p_double[ii], _state); - } - ae_set_error_flag(errorflag, ae_fp_less(f1,f0), __FILE__, __LINE__, "testlsfitunit.ap:3012"); - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Test for linearly constrained NLS problems. -On failure sets error flag, leaves it unchanged on success. -*************************************************************************/ -static void testlsfitunit_testlcnls(ae_bool* errorflag, ae_state *_state) -{ - ae_frame _frame_block; - lsfitstate state; - lsfitreport rep; - ae_vector bl; - ae_vector bu; - ae_int_t nx; - ae_int_t nc; - ae_int_t m; - ae_vector x; - ae_vector y; - ae_vector c0; - ae_vector c1; - ae_vector c2; - ae_matrix rawc; - ae_vector rawct; - ae_int_t rawccnt; - ae_matrix xx; - ae_matrix xx12; - ae_matrix z; - ae_int_t trialidx; - ae_int_t i; - ae_int_t j; - ae_int_t ii; - double v; - double h; - ae_int_t optkind; - hqrndstate rs; - double epsx; - double xtol; - double f0; - double f1; - ae_bool bflag; - ae_int_t terminationtype; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&bl, 0, sizeof(bl)); - memset(&bu, 0, sizeof(bu)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&c0, 0, sizeof(c0)); - memset(&c1, 0, sizeof(c1)); - memset(&c2, 0, sizeof(c2)); - memset(&rawc, 0, sizeof(rawc)); - memset(&rawct, 0, sizeof(rawct)); - memset(&xx, 0, sizeof(xx)); - memset(&xx12, 0, sizeof(xx12)); - memset(&z, 0, sizeof(z)); - memset(&rs, 0, sizeof(rs)); - _lsfitstate_init(&state, _state, ae_true); - _lsfitreport_init(&rep, _state, ae_true); - ae_vector_init(&bl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bu, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c2, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&rawc, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rawct, 0, DT_INT, _state, ae_true); - ae_matrix_init(&xx, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xx12, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Minimize - * - * [ [ ]2 ] - * SUM_i[ SUM_j[ (0.1*x_j+power(x_j,3))*c_ij ] ] - * [ [ ] ] - * - * subject to mix of box and linear inequality constraints on x_j - * - * We check correctness of solution by sampling a few random points - * around one returned by optimizer, and comparing function value - * with target. Sampling is performed with respect to inequality - * constraints. - */ - epsx = 1.0E-12; - xtol = 1.0E-8; - optkind = 1; - for(nc=5; nc<=20; nc++) - { - - /* - * Generate problem - */ - nx = nc; - m = nc+hqrnduniformi(&rs, nc, _state); - ae_vector_set_length(&bl, nc, _state); - ae_vector_set_length(&bu, nc, _state); - ae_vector_set_length(&c0, nc, _state); - ae_vector_set_length(&x, nx, _state); - for(i=0; i<=nc-1; i++) - { - bl.ptr.p_double[i] = hqrndnormal(&rs, _state); - bu.ptr.p_double[i] = bl.ptr.p_double[i]+0.01+hqrnduniformr(&rs, _state); - c0.ptr.p_double[i] = bl.ptr.p_double[i]+(bu.ptr.p_double[i]-bl.ptr.p_double[i])*hqrnduniformr(&rs, _state); - } - ae_matrix_set_length(&xx, m, nx, _state); - ae_vector_set_length(&y, m, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=nx-1; j++) - { - xx.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - y.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_assert(nc>=5, "Assertion failed", _state); - rawccnt = 3; - ae_matrix_set_length(&rawc, rawccnt, nc+1, _state); - ae_vector_set_length(&rawct, rawccnt, _state); - for(i=0; i<=rawccnt-1; i++) - { - v = (double)(0); - for(j=0; j<=nc-1; j++) - { - rawc.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - v = v+c0.ptr.p_double[j]*rawc.ptr.pp_double[i][j]; - } - rawc.ptr.pp_double[i][nc] = v; - rawct.ptr.p_int[i] = 2*hqrnduniformi(&rs, 2, _state)-1; - } - - /* - * Solve - */ - if( optkind==0 ) - { - lsfitcreatef(&xx, &y, &c0, m, nx, nc, 1.0E-6, &state, _state); - } - if( optkind==1 ) - { - lsfitcreatefg(&xx, &y, &c0, m, nx, nc, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &state, _state); - } - lsfitsetcond(&state, epsx, 0, _state); - lsfitsetbc(&state, &bl, &bu, _state); - lsfitsetlc(&state, &rawc, &rawct, rawccnt, _state); - while(lsfititeration(&state, _state)) - { - for(i=0; i<=nc-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_less(state.c.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:3121"); - ae_set_error_flag(errorflag, ae_fp_greater(state.c.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:3122"); - } - if( state.needf ) - { - testlsfitunit_testfunc1(nx, &state.x, &state.c, &state.f, ae_true, &state.g, ae_false, _state); - continue; - } - if( state.needfg ) - { - testlsfitunit_testfunc1(nx, &state.x, &state.c, &state.f, ae_true, &state.g, ae_true, _state); - continue; - } - ae_assert(ae_false, "lsfit test: integrity check failed", _state); - } - lsfitresults(&state, &terminationtype, &c1, &rep, _state); - ae_set_error_flag(errorflag, terminationtype<=0, __FILE__, __LINE__, "testlsfitunit.ap:3137"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - - /* - * Test feasibility w.r.t. box and linear inequality constraints - */ - for(i=0; i<=nc-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_less(c1.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:3146"); - ae_set_error_flag(errorflag, ae_fp_greater(c1.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:3147"); - } - for(i=0; i<=rawccnt-1; i++) - { - v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &c1.ptr.p_double[0], 1, ae_v_len(0,nc-1)); - v = v-rawc.ptr.pp_double[i][nc]; - if( rawct.ptr.p_int[i]>0 ) - { - ae_set_error_flag(errorflag, ae_fp_less(v,-xtol), __FILE__, __LINE__, "testlsfitunit.ap:3154"); - } - if( rawct.ptr.p_int[i]<0 ) - { - ae_set_error_flag(errorflag, ae_fp_greater(v,xtol), __FILE__, __LINE__, "testlsfitunit.ap:3156"); - } - } - - /* - * Make several random trial steps and: - * 0) generate small random trial step - * 1) if step is infeasible, skip to next trial - * 2) compare function value in the trial point against one in other points - */ - f0 = (double)(0); - for(ii=0; ii<=m-1; ii++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1)); - testlsfitunit_testfunc1(nx, &x, &c1, &v, ae_true, &state.g, ae_false, _state); - f0 = f0+ae_sqr(v-y.ptr.p_double[ii], _state); - } - ae_vector_set_length(&c2, nc, _state); - for(trialidx=0; trialidx<=10*nc; trialidx++) - { - h = 0.001; - for(i=0; i<=nc-1; i++) - { - do - { - c2.ptr.p_double[i] = c1.ptr.p_double[i]+(hqrnduniformr(&rs, _state)*2-1)*h; - } - while(!(ae_fp_greater_eq(c2.ptr.p_double[i],bl.ptr.p_double[i])&&ae_fp_less_eq(c2.ptr.p_double[i],bu.ptr.p_double[i]))); - } - bflag = ae_false; - for(i=0; i<=rawccnt-1; i++) - { - ae_assert(rawct.ptr.p_int[i]!=0, "Assertion failed", _state); - v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &c2.ptr.p_double[0], 1, ae_v_len(0,nc-1)); - v = v-rawc.ptr.pp_double[i][nc]; - bflag = bflag||(rawct.ptr.p_int[i]>0&&ae_fp_less(v,(double)(0))); - bflag = bflag||(rawct.ptr.p_int[i]<0&&ae_fp_greater(v,(double)(0))); - } - if( bflag ) - { - continue; - } - f1 = (double)(0); - for(ii=0; ii<=m-1; ii++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1)); - testlsfitunit_testfunc1(nx, &x, &c2, &v, ae_true, &state.g, ae_false, _state); - f1 = f1+ae_sqr(v-y.ptr.p_double[ii], _state); - } - ae_set_error_flag(errorflag, ae_fp_less(f1,f0), __FILE__, __LINE__, "testlsfitunit.ap:3205"); - } - } - - /* - * Minimize - * - * [ [ ]2 ] - * SUM_i[ SUM_j[ (0.1*x_j+power(x_j,3))*c_ij ] ] - * [ [ ] ] - * - * subject to linear EQUALITY constraints on x_j. - * - * We check correctness of solution by sampling a few random points - * around one returned by optimizer, and comparing function value - * with target. Sampling is performed with respect to equality - * constraints. In order to simplify algorithm we use orthogonal - * equality constraints. - * - * NOTE: we solve problem using VJ mode (analytic Jacobian) because - * roundoff errors from numerical differentiation sometimes - * prevent us from converging with good precision. - */ - epsx = 1.0E-12; - xtol = 1.0E-8; - optkind = 1; - for(nc=10; nc<=20; nc++) - { - - /* - * Generate problem - */ - nx = nc; - m = nc+hqrnduniformi(&rs, nc, _state); - ae_vector_set_length(&c0, nc, _state); - for(i=0; i<=nc-1; i++) - { - c0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_matrix_set_length(&xx, m, nx, _state); - ae_vector_set_length(&y, m, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=nx-1; j++) - { - xx.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - y.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_assert(nc>=10, "Assertion failed", _state); - rawccnt = 1+hqrnduniformi(&rs, 5, _state); - rmatrixrndorthogonal(nc, &z, _state); - ae_matrix_set_length(&rawc, rawccnt, nc+1, _state); - ae_vector_set_length(&rawct, rawccnt, _state); - for(i=0; i<=rawccnt-1; i++) - { - v = (double)(0); - for(j=0; j<=nc-1; j++) - { - rawc.ptr.pp_double[i][j] = z.ptr.pp_double[i][j]; - v = v+c0.ptr.p_double[j]*rawc.ptr.pp_double[i][j]; - } - rawc.ptr.pp_double[i][nc] = v; - rawct.ptr.p_int[i] = 0; - } - - /* - * Solve - */ - if( optkind==0 ) - { - lsfitcreatef(&xx, &y, &c0, m, nx, nc, 1.0E-6, &state, _state); - } - if( optkind==1 ) - { - lsfitcreatefg(&xx, &y, &c0, m, nx, nc, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &state, _state); - } - lsfitsetcond(&state, epsx, 0, _state); - lsfitsetlc(&state, &rawc, &rawct, rawccnt, _state); - while(lsfititeration(&state, _state)) - { - if( state.needf ) - { - testlsfitunit_testfunc1(nx, &state.x, &state.c, &state.f, ae_true, &state.g, ae_false, _state); - continue; - } - if( state.needfg ) - { - testlsfitunit_testfunc1(nx, &state.x, &state.c, &state.f, ae_true, &state.g, ae_true, _state); - continue; - } - ae_assert(ae_false, "lsfit test: integrity check failed", _state); - } - lsfitresults(&state, &terminationtype, &c1, &rep, _state); - ae_set_error_flag(errorflag, terminationtype<=0, __FILE__, __LINE__, "testlsfitunit.ap:3291"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - - /* - * Test feasibility w.r.t. linear equality constraints - */ - for(i=0; i<=rawccnt-1; i++) - { - v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &c1.ptr.p_double[0], 1, ae_v_len(0,nc-1)); - v = v-rawc.ptr.pp_double[i][nc]; - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v, _state),xtol), __FILE__, __LINE__, "testlsfitunit.ap:3302"); - } - - /* - * Make several random trial steps and: - * 0) generate small random trial step - * 1) project it onto equality constrained subspace - * 2) compare function value in the trial point against one in other points - */ - f0 = (double)(0); - for(ii=0; ii<=m-1; ii++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1)); - testlsfitunit_testfunc1(nx, &x, &c1, &v, ae_true, &state.g, ae_false, _state); - f0 = f0+ae_sqr(v-y.ptr.p_double[ii], _state); - } - ae_vector_set_length(&c2, nc, _state); - for(trialidx=0; trialidx<=nc; trialidx++) - { - h = 0.001; - for(i=0; i<=nc-1; i++) - { - c2.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - for(i=0; i<=rawccnt-1; i++) - { - v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &c2.ptr.p_double[0], 1, ae_v_len(0,nc-1)); - ae_v_subd(&c2.ptr.p_double[0], 1, &rawc.ptr.pp_double[i][0], 1, ae_v_len(0,nc-1), v); - } - v = ae_v_dotproduct(&c2.ptr.p_double[0], 1, &c2.ptr.p_double[0], 1, ae_v_len(0,nc-1)); - ae_assert(ae_fp_greater(v,(double)(0)), "Assertion failed", _state); - v = h/ae_sqrt(v, _state); - ae_v_muld(&c2.ptr.p_double[0], 1, ae_v_len(0,nc-1), v); - ae_v_add(&c2.ptr.p_double[0], 1, &c1.ptr.p_double[0], 1, ae_v_len(0,nc-1)); - f1 = (double)(0); - for(ii=0; ii<=m-1; ii++) - { - ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1)); - testlsfitunit_testfunc1(nx, &x, &c2, &v, ae_true, &state.g, ae_false, _state); - f1 = f1+ae_sqr(v-y.ptr.p_double[ii], _state); - } - ae_set_error_flag(errorflag, ae_fp_less(f1,f0), __FILE__, __LINE__, "testlsfitunit.ap:3344"); - } - } - - /* - * Fit - * - * - * f(X|C)= c_0 - * - * - * subject to single general linear equality constraint on c_0. - * - * Here X has dimensionality NX, and C has dimensionality 1. - * - * We do not test convergence to solution, only feasibility of constraint. - * The aim of this test is to assert that optimizer correctly handles - * situations when dimensions of X and C differ. - */ - epsx = 1.0E-9; - for(optkind=0; optkind<=1; optkind++) - { - for(nx=1; nx<=20; nx++) - { - nc = 1; - m = nx+hqrnduniformi(&rs, nx, _state); - ae_vector_set_length(&c0, nc, _state); - for(i=0; i<=nc-1; i++) - { - c0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_matrix_set_length(&xx, m, nx, _state); - ae_vector_set_length(&y, m, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=nx-1; j++) - { - xx.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - y.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_assert(nc==1, "Assertion failed", _state); - rawccnt = 1; - ae_matrix_set_length(&rawc, 1, 2, _state); - ae_vector_set_length(&rawct, 1, _state); - rawc.ptr.pp_double[0][0] = (double)(1); - rawc.ptr.pp_double[0][1] = hqrndnormal(&rs, _state); - rawct.ptr.p_int[0] = 0; - if( optkind==0 ) - { - lsfitcreatef(&xx, &y, &c0, m, nx, nc, 10*epsx, &state, _state); - } - if( optkind==1 ) - { - lsfitcreatefg(&xx, &y, &c0, m, nx, nc, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &state, _state); - } - lsfitsetcond(&state, epsx, 0, _state); - lsfitsetlc(&state, &rawc, &rawct, rawccnt, _state); - while(lsfititeration(&state, _state)) - { - if( state.needf ) - { - testlsfitunit_testfunc2(&state.x, nx, &state.c, nc, &state.f, ae_true, &state.g, ae_false, _state); - continue; - } - if( state.needfg ) - { - testlsfitunit_testfunc2(&state.x, nx, &state.c, nc, &state.f, ae_true, &state.g, ae_true, _state); - continue; - } - ae_assert(ae_false, "minlm test: integrity check failed", _state); - } - lsfitresults(&state, &terminationtype, &c1, &rep, _state); - ae_set_error_flag(errorflag, terminationtype<=0, __FILE__, __LINE__, "testlsfitunit.ap:3409"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(c1.ptr.p_double[0]-rawc.ptr.pp_double[0][1], _state),1.0E-6), __FILE__, __LINE__, "testlsfitunit.ap:3414"); - } - } - - /* - * Fit - * - * - * f(X|C)= c_0 + c_1*x0 + c_2*x0^2 + ... - * - * - * subject to single general linear equality constraint on c. - * - * Here X has dimensionality 1, and C has dimensionality NC. - * - * We do not test convergence to solution, only feasibility of constraint. - * The aim of this test is to assert that optimizer correctly handles - * situations when dimensions of X and C differ. - */ - epsx = 1.0E-9; - for(optkind=0; optkind<=1; optkind++) - { - for(nc=1; nc<=5; nc++) - { - nx = 1; - m = 10+nc+hqrnduniformi(&rs, nc, _state); - ae_vector_set_length(&c0, nc, _state); - for(i=0; i<=nc-1; i++) - { - c0.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_matrix_set_length(&xx, m, nx, _state); - ae_vector_set_length(&y, m, _state); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=nx-1; j++) - { - xx.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - y.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - rawccnt = 1; - ae_matrix_set_length(&rawc, 1, nc+1, _state); - ae_vector_set_length(&rawct, 1, _state); - for(j=0; j<=nc; j++) - { - rawc.ptr.pp_double[0][j] = (2*hqrnduniformi(&rs, 2, _state)-1)*(0.1+hqrnduniformr(&rs, _state)); - } - rawct.ptr.p_int[0] = 0; - if( optkind==0 ) - { - lsfitcreatef(&xx, &y, &c0, m, nx, nc, 10*epsx, &state, _state); - } - if( optkind==1 ) - { - lsfitcreatefg(&xx, &y, &c0, m, nx, nc, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &state, _state); - } - lsfitsetcond(&state, epsx, 0, _state); - lsfitsetlc(&state, &rawc, &rawct, rawccnt, _state); - while(lsfititeration(&state, _state)) - { - if( state.needf ) - { - testlsfitunit_testfunc3(&state.x, nx, &state.c, nc, &state.f, ae_true, &state.g, ae_false, _state); - continue; - } - if( state.needfg ) - { - testlsfitunit_testfunc3(&state.x, nx, &state.c, nc, &state.f, ae_true, &state.g, ae_true, _state); - continue; - } - ae_assert(ae_false, "minlm test: integrity check failed", _state); - } - lsfitresults(&state, &terminationtype, &c1, &rep, _state); - ae_set_error_flag(errorflag, terminationtype<=0, __FILE__, __LINE__, "testlsfitunit.ap:3477"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - v = -rawc.ptr.pp_double[0][nc]; - for(j=0; j<=nc-1; j++) - { - v = v+rawc.ptr.pp_double[0][j]*c1.ptr.p_double[j]; - } - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v, _state),1.0E-6), __FILE__, __LINE__, "testlsfitunit.ap:3485"); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Tests whether C is solution of (possibly) constrained LLS problem -*************************************************************************/ -static ae_bool testlsfitunit_isglssolution(ae_int_t n, - ae_int_t m, - ae_int_t k, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* fmatrix, - /* Real */ ae_matrix* cmatrix, - /* Real */ ae_vector* c, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector _c; - ae_int_t i; - ae_int_t j; - ae_vector c2; - ae_vector sv; - ae_vector deltac; - ae_vector deltaproj; - ae_matrix u; - ae_matrix vt; - double v; - double s1; - double s2; - double s3; - double delta; - double threshold; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_c, 0, sizeof(_c)); - memset(&c2, 0, sizeof(c2)); - memset(&sv, 0, sizeof(sv)); - memset(&deltac, 0, sizeof(deltac)); - memset(&deltaproj, 0, sizeof(deltaproj)); - memset(&u, 0, sizeof(u)); - memset(&vt, 0, sizeof(vt)); - ae_vector_init_copy(&_c, c, _state, ae_true); - c = &_c; - ae_vector_init(&c2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sv, 0, DT_REAL, _state, ae_true); - ae_vector_init(&deltac, 0, DT_REAL, _state, ae_true); - ae_vector_init(&deltaproj, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vt, 0, 0, DT_REAL, _state, ae_true); - - - /* - * Setup. - * Threshold is small because CMatrix may be ill-conditioned - */ - delta = 0.001; - threshold = ae_sqrt(ae_machineepsilon, _state); - ae_vector_set_length(&c2, m, _state); - ae_vector_set_length(&deltac, m, _state); - ae_vector_set_length(&deltaproj, m, _state); - - /* - * test whether C is feasible point or not (projC must be close to C) - */ - for(i=0; i<=k-1; i++) - { - v = ae_v_dotproduct(&cmatrix->ptr.pp_double[i][0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,m-1)); - if( ae_fp_greater(ae_fabs(v-cmatrix->ptr.pp_double[i][m], _state),threshold) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - } - - /* - * find orthogonal basis of Null(CMatrix) (stored in rows from K to M-1) - */ - if( k>0 ) - { - rmatrixsvd(cmatrix, k, m, 0, 2, 2, &sv, &u, &vt, _state); - } - - /* - * Test result - */ - result = ae_true; - s1 = testlsfitunit_getglserror(n, m, y, w, fmatrix, c, _state); - for(j=0; j<=m-1; j++) - { - - /* - * prepare modification of C which leave us in the feasible set. - * - * let deltaC be increment on Jth coordinate, then project - * deltaC in the Null(CMatrix) and store result in DeltaProj - */ - ae_v_move(&c2.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,m-1)); - for(i=0; i<=m-1; i++) - { - if( i==j ) - { - deltac.ptr.p_double[i] = delta; - } - else - { - deltac.ptr.p_double[i] = (double)(0); - } - } - if( k==0 ) - { - ae_v_move(&deltaproj.ptr.p_double[0], 1, &deltac.ptr.p_double[0], 1, ae_v_len(0,m-1)); - } - else - { - for(i=0; i<=m-1; i++) - { - deltaproj.ptr.p_double[i] = (double)(0); - } - for(i=k; i<=m-1; i++) - { - v = ae_v_dotproduct(&vt.ptr.pp_double[i][0], 1, &deltac.ptr.p_double[0], 1, ae_v_len(0,m-1)); - ae_v_addd(&deltaproj.ptr.p_double[0], 1, &vt.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v); - } - } - - /* - * now we have DeltaProj such that if C is feasible, - * then C+DeltaProj is feasible too - */ - ae_v_move(&c2.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,m-1)); - ae_v_add(&c2.ptr.p_double[0], 1, &deltaproj.ptr.p_double[0], 1, ae_v_len(0,m-1)); - s2 = testlsfitunit_getglserror(n, m, y, w, fmatrix, &c2, _state); - ae_v_move(&c2.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,m-1)); - ae_v_sub(&c2.ptr.p_double[0], 1, &deltaproj.ptr.p_double[0], 1, ae_v_len(0,m-1)); - s3 = testlsfitunit_getglserror(n, m, y, w, fmatrix, &c2, _state); - result = (result&&ae_fp_greater_eq(s2,s1/(1+threshold)))&&ae_fp_greater_eq(s3,s1/(1+threshold)); - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Tests whether C is solution of LLS problem -*************************************************************************/ -static double testlsfitunit_getglserror(ae_int_t n, - ae_int_t m, - /* Real */ ae_vector* y, - /* Real */ ae_vector* w, - /* Real */ ae_matrix* fmatrix, - /* Real */ ae_vector* c, - ae_state *_state) -{ - ae_int_t i; - double v; - double result; - - - result = (double)(0); - for(i=0; i<=n-1; i++) - { - v = ae_v_dotproduct(&fmatrix->ptr.pp_double[i][0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,m-1)); - result = result+ae_sqr(w->ptr.p_double[i]*(v-y->ptr.p_double[i]), _state); - } - return result; -} - - -/************************************************************************* -Subroutine for nonlinear fitting of linear problem - -DerAvailable: -* 0 when only function value should be used -* 1 when we can provide gradient/function -* 2 when we can provide Hessian/gradient/function - -When something which is not permitted by DerAvailable is requested, -this function sets NLSErrors to True. -*************************************************************************/ -static void testlsfitunit_fitlinearnonlinear(ae_int_t m, - ae_int_t deravailable, - /* Real */ ae_matrix* xy, - lsfitstate* state, - ae_bool* nlserrors, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double v; - - - while(lsfititeration(state, _state)) - { - - /* - * assume that one and only one of flags is set - * test that we didn't request hessian in hessian-free setting - */ - if( deravailable<1&&state->needfg ) - { - *nlserrors = ae_true; - } - if( deravailable<2&&state->needfgh ) - { - *nlserrors = ae_true; - } - i = 0; - if( state->needf ) - { - i = i+1; - } - if( state->needfg ) - { - i = i+1; - } - if( state->needfgh ) - { - i = i+1; - } - if( i!=1 ) - { - *nlserrors = ae_true; - } - - /* - * test that PointIndex is consistent with actual point passed - */ - for(i=0; i<=m-1; i++) - { - *nlserrors = *nlserrors||ae_fp_neq(xy->ptr.pp_double[state->pointindex][i],state->x.ptr.p_double[i]); - } - - /* - * calculate - */ - if( state->needf ) - { - v = ae_v_dotproduct(&state->x.ptr.p_double[0], 1, &state->c.ptr.p_double[0], 1, ae_v_len(0,m-1)); - state->f = v; - continue; - } - if( state->needfg ) - { - v = ae_v_dotproduct(&state->x.ptr.p_double[0], 1, &state->c.ptr.p_double[0], 1, ae_v_len(0,m-1)); - state->f = v; - ae_v_move(&state->g.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,m-1)); - continue; - } - if( state->needfgh ) - { - v = ae_v_dotproduct(&state->x.ptr.p_double[0], 1, &state->c.ptr.p_double[0], 1, ae_v_len(0,m-1)); - state->f = v; - ae_v_move(&state->g.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,m-1)); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=m-1; j++) - { - state->h.ptr.pp_double[i][j] = (double)(0); - } - } - continue; - } - } -} - - -/************************************************************************* -This function tests, that gradient verified correctly. -On failure sets error flag, on success does not modify it. -*************************************************************************/ -static void testlsfitunit_testgradientcheck(ae_bool* testg, - ae_state *_state) -{ - ae_frame _frame_block; - lsfitstate state; - lsfitreport rep; - ae_int_t n; - ae_int_t m; - ae_int_t k; - ae_vector c; - ae_vector cres; - ae_matrix x; - ae_vector y; - ae_vector x0; - ae_int_t info; - ae_vector bl; - ae_vector bu; - ae_int_t infcomp; - double teststep; - double noise; - ae_int_t nbrcomp; - double spp; - ae_int_t func; - ae_int_t pass; - ae_int_t passcount; - ae_int_t i; - ae_int_t j; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&c, 0, sizeof(c)); - memset(&cres, 0, sizeof(cres)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&x0, 0, sizeof(x0)); - memset(&bl, 0, sizeof(bl)); - memset(&bu, 0, sizeof(bu)); - _lsfitstate_init(&state, _state, ae_true); - _lsfitreport_init(&rep, _state, ae_true); - ae_vector_init(&c, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cres, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&x, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bl, 0, DT_REAL, _state, ae_true); - ae_vector_init(&bu, 0, DT_REAL, _state, ae_true); - - passcount = 35; - spp = 1.0; - teststep = 0.001; - for(pass=1; pass<=passcount; pass++) - { - m = ae_randominteger(5, _state)+1; - ae_vector_set_length(&x0, m, _state); - k = ae_randominteger(5, _state)+1; - ae_vector_set_length(&c, k, _state); - ae_vector_set_length(&bl, k, _state); - ae_vector_set_length(&bu, k, _state); - - /* - * Prepare test's parameters - */ - func = ae_randominteger(3, _state)+1; - n = ae_randominteger(8, _state)+3; - ae_matrix_set_length(&x, n, m, _state); - ae_vector_set_length(&y, n, _state); - nbrcomp = ae_randominteger(k, _state); - noise = (double)(2*ae_randominteger(2, _state)-1); - - /* - * Prepare function's parameters - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - x.ptr.pp_double[i][j] = spp*(2*ae_randomreal(_state)-1); - } - y.ptr.p_double[i] = spp*(2*ae_randomreal(_state)-1); - } - for(i=0; i<=k-1; i++) - { - c.ptr.p_double[i] = spp*(2*ae_randomreal(_state)-1); - } - for(i=0; i<=m-1; i++) - { - x0.ptr.p_double[i] = 10*(2*ae_randomreal(_state)-1); - } - - /* - * Prepare boundary parameters - */ - for(i=0; i<=k-1; i++) - { - bl.ptr.p_double[i] = -ae_randomreal(_state)-spp; - bu.ptr.p_double[i] = ae_randomreal(_state)+spp; - } - infcomp = ae_randominteger(k+1, _state); - if( infcompv_neginf; - } - infcomp = ae_randominteger(k+1, _state); - if( infcompv_posinf; - } - lsfitcreatefg(&x, &y, &c, n, m, k, ae_true, &state, _state); - lsfitsetgradientcheck(&state, teststep, _state); - lsfitsetcond(&state, 0.0, 100, _state); - lsfitsetbc(&state, &bl, &bu, _state); - - /* - * Check that the criterion passes a derivative if it is correct - */ - while(lsfititeration(&state, _state)) - { - if( state.needfg ) - { - testlsfitunit_funcderiv(&state.c, &state.x, &x0, k, m, func, &state.f, &state.g, _state); - } - } - lsfitresults(&state, &info, &cres, &rep, _state); - - /* - * Check that error code does not equal to -7 and parameter .VarIdx - * equal to -1. - */ - if( info==-7||rep.varidx!=-1 ) - { - ae_set_error_flag(testg, ae_true, __FILE__, __LINE__, "testlsfitunit.ap:3917"); - ae_frame_leave(_state); - return; - } - - /* - * Create again and... - */ - lsfitcreatefg(&x, &y, &c, n, m, k, ae_true, &state, _state); - lsfitsetgradientcheck(&state, teststep, _state); - lsfitsetcond(&state, 0.0, 100, _state); - lsfitsetbc(&state, &bl, &bu, _state); - - /* - * Check that the criterion does not miss a derivative if - * it is incorrect - */ - while(lsfititeration(&state, _state)) - { - if( state.needfg ) - { - testlsfitunit_funcderiv(&state.c, &state.x, &x0, k, m, func, &state.f, &state.g, _state); - state.g.ptr.p_double[nbrcomp] = state.g.ptr.p_double[nbrcomp]+noise; - } - } - lsfitresults(&state, &info, &cres, &rep, _state); - - /* - * Check that error code equal to -7 and parameter .VarIdx - * equal to number of incorrect component. - */ - if( info!=-7||rep.varidx!=nbrcomp ) - { - ae_set_error_flag(testg, ae_true, __FILE__, __LINE__, "testlsfitunit.ap:3949"); - ae_frame_leave(_state); - return; - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -This function return function's value(F=F(X,C)) and it derivatives(DF=dF/dC). -Function dimension is M. Length(C) is K. - Function's list: - * funcType=1: - K>M: - F(X)=C0^2*(X0-CX0)^2+C1^2*(X1-CX1)^2+...+CM^2*(XM-CXM)^2 - +C(M+1)^2+...+CK^2; - KM: - F(X)=C0*sin(X0-CX0)^2+C1*sin(X1-CX1)^2+...+CM*sin(XM-CXM)^2 - +C(M+1)^3+...+CK^3; - K=1&&functype<=3, "FuncDeriv: incorrect funcType(funcType<1 or funcType>3).", _state); - ae_assert(k>0, "FuncDeriv: K<=0", _state); - ae_assert(m>0, "FuncDeriv: M<=0", _state); - ae_assert(x->cnt>=m, "FuncDeriv: Length(X)cnt>=m, "FuncDeriv: Length(X0)cnt>=k, "FuncDeriv: Length(X)ptr.p_double[i]*(x->ptr.p_double[i]-x0->ptr.p_double[i]), _state); - g->ptr.p_double[i] = 2*c->ptr.p_double[i]*ae_sqr(x->ptr.p_double[i]-x0->ptr.p_double[i], _state); - } - if( k>m ) - { - for(i=m; i<=k-1; i++) - { - *f = *f+ae_sqr(c->ptr.p_double[i], _state); - g->ptr.p_double[i] = 2*c->ptr.p_double[i]; - } - } - if( kptr.p_double[i]-x0->ptr.p_double[i], _state); - } - } - return; - } - if( functype==2 ) - { - *f = (double)(0); - for(i=0; i<=ae_minint(m, k, _state)-1; i++) - { - *f = *f+c->ptr.p_double[i]*ae_sqr(ae_sin(x->ptr.p_double[i]-x0->ptr.p_double[i], _state), _state); - g->ptr.p_double[i] = ae_sqr(ae_sin(x->ptr.p_double[i]-x0->ptr.p_double[i], _state), _state); - } - if( k>m ) - { - for(i=m; i<=k-1; i++) - { - *f = *f+c->ptr.p_double[i]*c->ptr.p_double[i]*c->ptr.p_double[i]; - g->ptr.p_double[i] = 3*ae_sqr(c->ptr.p_double[i], _state); - } - } - if( kptr.p_double[i]-x0->ptr.p_double[i], _state), _state); - } - } - return; - } - if( functype==3 ) - { - *f = (double)(0); - for(i=0; i<=m-1; i++) - { - *f = *f+ae_sqr(x->ptr.p_double[i]-x0->ptr.p_double[i], _state); - } - for(i=0; i<=k-1; i++) - { - *f = *f+c->ptr.p_double[i]*c->ptr.p_double[i]; - } - for(i=0; i<=k-1; i++) - { - g->ptr.p_double[i] = 2*c->ptr.p_double[i]; - } - return; - } -} - - -/************************************************************************* -Test function 1: - - F(K, X, Z) = SUM( (power(z_j,3)+alpha*z_j)*x_ij ) - -here X is a space of points, Z is a space of parameters -*************************************************************************/ -static void testlsfitunit_testfunc1(ae_int_t k, - /* Real */ ae_vector* x, - /* Real */ ae_vector* z, - double* f, - ae_bool needf, - /* Real */ ae_vector* g, - ae_bool needg, - ae_state *_state) -{ - ae_int_t j; - double v; - double alpha; - - - alpha = 0.01; - v = (double)(0); - for(j=0; j<=k-1; j++) - { - v = v+(alpha*z->ptr.p_double[j]+ae_pow(z->ptr.p_double[j], (double)(3), _state))*x->ptr.p_double[j]; - if( needg ) - { - g->ptr.p_double[j] = (alpha+3*ae_pow(z->ptr.p_double[j], (double)(2), _state))*x->ptr.p_double[j]; - } - } - if( needf ) - { - *f = v; - } -} - - -/************************************************************************* -Test function 2: - - F(X|C) = c_0 - -here X is a space of points, C is a space of parameters -*************************************************************************/ -static void testlsfitunit_testfunc2(/* Real */ ae_vector* x, - ae_int_t nx, - /* Real */ ae_vector* c, - ae_int_t nc, - double* f, - ae_bool needf, - /* Real */ ae_vector* g, - ae_bool needg, - ae_state *_state) -{ - - - ae_assert(nc==1, "TestFunc2: integrity check failure", _state); - if( needf ) - { - *f = c->ptr.p_double[0]; - } - if( needg ) - { - g->ptr.p_double[0] = (double)(1); - } -} - - -/************************************************************************* -Test function 3: - - F(X|C) = c_0 + c_1*x0 + c_2*x0^2 + ... - -here X is a space of points, C is a space of parameters -*************************************************************************/ -static void testlsfitunit_testfunc3(/* Real */ ae_vector* x, - ae_int_t nx, - /* Real */ ae_vector* c, - ae_int_t nc, - double* f, - ae_bool needf, - /* Real */ ae_vector* g, - ae_bool needg, - ae_state *_state) -{ - double v; - ae_int_t i; - - - ae_assert(nx==1, "TestFunc3: integrity check failure", _state); - v = (double)(0); - for(i=0; i<=nc-1; i++) - { - v = v+c->ptr.p_double[i]*ae_pow(x->ptr.p_double[0], (double)(i), _state); - if( needg ) - { - g->ptr.p_double[i] = ae_pow(x->ptr.p_double[0], (double)(i), _state); - } - } - if( needf ) - { - *f = v; - } -} - - -/************************************************************************* -Appends 10 elements to the array -*************************************************************************/ -static void testlsfitunit_append10(/* Real */ ae_vector* x, - double v0, - double v1, - double v2, - double v3, - double v4, - double v5, - double v6, - double v7, - double v8, - double v9, - ae_state *_state) -{ - - - rvectorresize(x, x->cnt+10, _state); - x->ptr.p_double[x->cnt-10] = v0; - x->ptr.p_double[x->cnt-9] = v1; - x->ptr.p_double[x->cnt-8] = v2; - x->ptr.p_double[x->cnt-7] = v3; - x->ptr.p_double[x->cnt-6] = v4; - x->ptr.p_double[x->cnt-5] = v5; - x->ptr.p_double[x->cnt-4] = v6; - x->ptr.p_double[x->cnt-3] = v7; - x->ptr.p_double[x->cnt-2] = v8; - x->ptr.p_double[x->cnt-1] = v9; -} - - - -static void testspline2dunit_lconst(spline2dinterpolant* c, - /* Real */ ae_vector* lx, - /* Real */ ae_vector* ly, - ae_int_t m, - ae_int_t n, - double lstep, - double* lc, - double* lcx, - double* lcy, - double* lcxy, - ae_state *_state); -static void testspline2dunit_twodnumder(spline2dinterpolant* c, - double x, - double y, - double h, - double* f, - double* fx, - double* fy, - double* fxy, - ae_state *_state); -static ae_bool testspline2dunit_testunpack(spline2dinterpolant* c, - /* Real */ ae_vector* lx, - /* Real */ ae_vector* ly, - ae_state *_state); -static ae_bool testspline2dunit_testlintrans(spline2dinterpolant* c, - ae_int_t d, - double ax, - double bx, - double ay, - double by, - ae_state *_state); -static void testspline2dunit_unsetspline2d(spline2dinterpolant* c, - ae_state *_state); -static ae_bool testspline2dunit_testspline2dvf(ae_bool silent, - ae_state *_state); -static void testspline2dunit_testfittingprior(ae_bool* errorflag, - ae_state *_state); -static void testspline2dunit_testfittingpenalty(ae_bool* errorflag, - ae_state *_state); -static void testspline2dunit_testfittingblocksolver(ae_bool* errorflag, - ae_state *_state); -static void testspline2dunit_testfittingfastddmsolver(ae_bool* errorflag, - ae_state *_state); - - - - - -ae_bool testspline2d(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_bool waserrors; - ae_bool blerrors; - ae_bool bcerrors; - ae_bool dserrors; - ae_bool cperrors; - ae_bool sererrors; - ae_bool uperrors; - ae_bool lterrors; - ae_bool syerrors; - ae_bool rlerrors; - ae_bool rcerrors; - ae_bool vferrors; - ae_bool fiterrorsfastddmsolver; - ae_bool fiterrorsblocksolver; - ae_bool fiterrorspenalty; - ae_bool fiterrorsprior; - ae_int_t pass; - ae_int_t passcount; - ae_int_t jobtype; - double lstep; - double h; - ae_vector x; - ae_vector y; - spline2dinterpolant c; - spline2dinterpolant c2; - ae_vector lx; - ae_vector ly; - ae_vector fv1; - ae_vector fvd; - ae_matrix f; - ae_matrix fr; - ae_matrix ft; - double ax; - double ay; - double bx; - double by; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t n; - ae_int_t m; - ae_int_t d; - ae_int_t n2; - ae_int_t m2; - double err; - double t; - double t1; - double t2; - double l1; - double l1x; - double l1y; - double l1xy; - double l2; - double l2x; - double l2y; - double l2xy; - double fm; - double f1; - double f2; - double f3; - double f4; - double v1; - double v1x; - double v1y; - double v1xy; - double v2; - double v2x; - double v2y; - double v2xy; - double mf; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&c, 0, sizeof(c)); - memset(&c2, 0, sizeof(c2)); - memset(&lx, 0, sizeof(lx)); - memset(&ly, 0, sizeof(ly)); - memset(&fv1, 0, sizeof(fv1)); - memset(&fvd, 0, sizeof(fvd)); - memset(&f, 0, sizeof(f)); - memset(&fr, 0, sizeof(fr)); - memset(&ft, 0, sizeof(ft)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - _spline2dinterpolant_init(&c, _state, ae_true); - _spline2dinterpolant_init(&c2, _state, ae_true); - ae_vector_init(&lx, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ly, 0, DT_REAL, _state, ae_true); - ae_vector_init(&fv1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&fvd, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&f, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&fr, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ft, 0, 0, DT_REAL, _state, ae_true); - - waserrors = ae_false; - passcount = 10; - h = 0.00001; - lstep = 0.001; - blerrors = ae_false; - bcerrors = ae_false; - dserrors = ae_false; - cperrors = ae_false; - sererrors = ae_false; - uperrors = ae_false; - lterrors = ae_false; - syerrors = ae_false; - rlerrors = ae_false; - rcerrors = ae_false; - vferrors = ae_false; - fiterrorsfastddmsolver = ae_false; - fiterrorsblocksolver = ae_false; - fiterrorsprior = ae_false; - fiterrorspenalty = ae_false; - - /* - * Fitting functions - */ - testspline2dunit_testfittingfastddmsolver(&fiterrorsfastddmsolver, _state); - testspline2dunit_testfittingprior(&fiterrorsprior, _state); - testspline2dunit_testfittingblocksolver(&fiterrorsblocksolver, _state); - testspline2dunit_testfittingpenalty(&fiterrorspenalty, _state); - - /* - * Test: bilinear, bicubic - */ - for(n=2; n<=7; n++) - { - for(m=2; m<=7; m++) - { - d = ae_randominteger(2, _state)+2; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, m, _state); - ae_vector_set_length(&lx, 2*n-1, _state); - ae_vector_set_length(&ly, 2*m-1, _state); - ae_matrix_set_length(&f, m, n, _state); - ae_vector_set_length(&fv1, m*n, _state); - ae_vector_set_length(&fvd, m*n*d, _state); - ae_matrix_set_length(&ft, n, m, _state); - for(pass=1; pass<=passcount; pass++) - { - - /* - * Prepare task: - * * X and Y stores grid - * * F stores function values - * * LX and LY stores twice dense grid (for Lipschitz testing) - */ - ax = -1-ae_randomreal(_state); - bx = 1+ae_randomreal(_state); - ay = -1-ae_randomreal(_state); - by = 1+ae_randomreal(_state); - for(j=0; j<=n-1; j++) - { - x.ptr.p_double[j] = 0.5*(bx+ax)-0.5*(bx-ax)*ae_cos(ae_pi*(2*j+1)/(2*n), _state); - if( j==0 ) - { - x.ptr.p_double[j] = ax; - } - if( j==n-1 ) - { - x.ptr.p_double[j] = bx; - } - lx.ptr.p_double[2*j] = x.ptr.p_double[j]; - if( j>0 ) - { - lx.ptr.p_double[2*j-1] = 0.5*(x.ptr.p_double[j]+x.ptr.p_double[j-1]); - } - } - for(j=0; j<=n-1; j++) - { - k = ae_randominteger(n, _state); - if( k!=j ) - { - t = x.ptr.p_double[j]; - x.ptr.p_double[j] = x.ptr.p_double[k]; - x.ptr.p_double[k] = t; - } - } - for(i=0; i<=m-1; i++) - { - y.ptr.p_double[i] = 0.5*(by+ay)-0.5*(by-ay)*ae_cos(ae_pi*(2*i+1)/(2*m), _state); - if( i==0 ) - { - y.ptr.p_double[i] = ay; - } - if( i==m-1 ) - { - y.ptr.p_double[i] = by; - } - ly.ptr.p_double[2*i] = y.ptr.p_double[i]; - if( i>0 ) - { - ly.ptr.p_double[2*i-1] = 0.5*(y.ptr.p_double[i]+y.ptr.p_double[i-1]); - } - } - for(i=0; i<=m-1; i++) - { - k = ae_randominteger(m, _state); - if( k!=i ) - { - t = y.ptr.p_double[i]; - y.ptr.p_double[i] = y.ptr.p_double[k]; - y.ptr.p_double[k] = t; - } - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - f.ptr.pp_double[i][j] = ae_exp(0.6*x.ptr.p_double[j], _state)-ae_exp(-0.3*y.ptr.p_double[i]+0.08*x.ptr.p_double[j], _state)+2*ae_cos(ae_pi*(x.ptr.p_double[j]+1.2*y.ptr.p_double[i]), _state)+0.1*ae_cos(20*x.ptr.p_double[j]+15*y.ptr.p_double[i], _state); - fv1.ptr.p_double[i*n+j] = f.ptr.pp_double[i][j]; - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - for(k=0; k<=d-1; k++) - { - fvd.ptr.p_double[d*(n*j+i)+k] = ae_exp(0.6*x.ptr.p_double[i], _state)-ae_exp(-0.3*y.ptr.p_double[j]+0.08*x.ptr.p_double[i], _state)+2*ae_cos(ae_pi*(x.ptr.p_double[i]+1.2*y.ptr.p_double[j]+k), _state)+0.1*ae_cos(20*x.ptr.p_double[i]+15*y.ptr.p_double[j]+k, _state); - } - } - } - - /* - * Test scalar bilinear interpolation: - * * interpolation at the nodes - * * linearity - * * continuity - * * differentiation in the inner points - */ - spline2dbuildbilinearv(&x, n, &y, m, &fv1, 1, &c, _state); - err = (double)(0); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - err = ae_maxreal(err, ae_fabs(f.ptr.pp_double[i][j]-spline2dcalc(&c, x.ptr.p_double[j], y.ptr.p_double[i], _state), _state), _state); - } - } - blerrors = blerrors||ae_fp_greater(err,10000*ae_machineepsilon); - err = (double)(0); - for(i=0; i<=m-2; i++) - { - for(j=0; j<=n-2; j++) - { - - /* - * Test for linearity between grid points - * (test point - geometric center of the cell) - */ - fm = spline2dcalc(&c, lx.ptr.p_double[2*j+1], ly.ptr.p_double[2*i+1], _state); - f1 = spline2dcalc(&c, lx.ptr.p_double[2*j], ly.ptr.p_double[2*i], _state); - f2 = spline2dcalc(&c, lx.ptr.p_double[2*j+2], ly.ptr.p_double[2*i], _state); - f3 = spline2dcalc(&c, lx.ptr.p_double[2*j+2], ly.ptr.p_double[2*i+2], _state); - f4 = spline2dcalc(&c, lx.ptr.p_double[2*j], ly.ptr.p_double[2*i+2], _state); - err = ae_maxreal(err, ae_fabs(0.25*(f1+f2+f3+f4)-fm, _state), _state); - } - } - blerrors = blerrors||ae_fp_greater(err,10000*ae_machineepsilon); - testspline2dunit_lconst(&c, &lx, &ly, m, n, lstep, &l1, &l1x, &l1y, &l1xy, _state); - testspline2dunit_lconst(&c, &lx, &ly, m, n, lstep/3, &l2, &l2x, &l2y, &l2xy, _state); - blerrors = blerrors||ae_fp_greater(l2/l1,1.2); - err = (double)(0); - for(i=0; i<=m-2; i++) - { - for(j=0; j<=n-2; j++) - { - spline2ddiff(&c, lx.ptr.p_double[2*j+1], ly.ptr.p_double[2*i+1], &v1, &v1x, &v1y, &v1xy, _state); - testspline2dunit_twodnumder(&c, lx.ptr.p_double[2*j+1], ly.ptr.p_double[2*i+1], h, &v2, &v2x, &v2y, &v2xy, _state); - err = ae_maxreal(err, ae_fabs(v1-v2, _state), _state); - err = ae_maxreal(err, ae_fabs(v1x-v2x, _state), _state); - err = ae_maxreal(err, ae_fabs(v1y-v2y, _state), _state); - err = ae_maxreal(err, ae_fabs(v1xy-v2xy, _state), _state); - } - } - dserrors = dserrors||ae_fp_greater(err,1.0E-3); - uperrors = uperrors||!testspline2dunit_testunpack(&c, &lx, &ly, _state); - lterrors = lterrors||!testspline2dunit_testlintrans(&c, 1, ax, bx, ay, by, _state); - - /* - * Lin.Trans. test for multicomponent vector function - */ - spline2dbuildbilinearv(&x, n, &y, m, &fvd, d, &c, _state); - lterrors = lterrors||!testspline2dunit_testlintrans(&c, d, ax, bx, ay, by, _state); - - /* - * Test bicubic interpolation. - * * interpolation at the nodes - * * smoothness - * * differentiation - */ - spline2dbuildbicubicv(&x, n, &y, m, &fv1, 1, &c, _state); - err = (double)(0); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - err = ae_maxreal(err, ae_fabs(f.ptr.pp_double[i][j]-spline2dcalc(&c, x.ptr.p_double[j], y.ptr.p_double[i], _state), _state), _state); - } - } - bcerrors = bcerrors||ae_fp_greater(err,10000*ae_machineepsilon); - testspline2dunit_lconst(&c, &lx, &ly, m, n, lstep, &l1, &l1x, &l1y, &l1xy, _state); - testspline2dunit_lconst(&c, &lx, &ly, m, n, lstep/3, &l2, &l2x, &l2y, &l2xy, _state); - bcerrors = bcerrors||ae_fp_greater(l2/l1,1.2); - bcerrors = bcerrors||ae_fp_greater(l2x/l1x,1.2); - bcerrors = bcerrors||ae_fp_greater(l2y/l1y,1.2); - if( ae_fp_greater(l2xy,0.01)&&ae_fp_greater(l1xy,0.01) ) - { - - /* - * Cross-derivative continuity is tested only when - * bigger than 0.01. When the task size is too - * small, the d2F/dXdY is nearly zero and Lipschitz - * constant ratio is ill-conditioned. - */ - bcerrors = bcerrors||ae_fp_greater(l2xy/l1xy,1.2); - } - err = (double)(0); - for(i=0; i<=2*m-2; i++) - { - for(j=0; j<=2*n-2; j++) - { - spline2ddiff(&c, lx.ptr.p_double[j], ly.ptr.p_double[i], &v1, &v1x, &v1y, &v1xy, _state); - testspline2dunit_twodnumder(&c, lx.ptr.p_double[j], ly.ptr.p_double[i], h, &v2, &v2x, &v2y, &v2xy, _state); - err = ae_maxreal(err, ae_fabs(v1-v2, _state), _state); - err = ae_maxreal(err, ae_fabs(v1x-v2x, _state), _state); - err = ae_maxreal(err, ae_fabs(v1y-v2y, _state), _state); - err = ae_maxreal(err, ae_fabs(v1xy-v2xy, _state), _state); - } - } - dserrors = dserrors||ae_fp_greater(err,1.0E-3); - uperrors = uperrors||!testspline2dunit_testunpack(&c, &lx, &ly, _state); - lterrors = lterrors||!testspline2dunit_testlintrans(&c, 1, ax, bx, ay, by, _state); - - /* - * Lin.Trans. test for vector-function - */ - spline2dbuildbicubicv(&x, n, &y, m, &fvd, d, &c, _state); - lterrors = lterrors||!testspline2dunit_testlintrans(&c, d, ax, bx, ay, by, _state); - - /* - * Copy test - */ - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - spline2dbuildbicubic(&x, &y, &f, m, n, &c, _state); - } - else - { - spline2dbuildbilinear(&x, &y, &f, m, n, &c, _state); - } - testspline2dunit_unsetspline2d(&c2, _state); - spline2dcopy(&c, &c2, _state); - err = (double)(0); - for(i=1; i<=5; i++) - { - t1 = ax+(bx-ax)*ae_randomreal(_state); - t2 = ay+(by-ay)*ae_randomreal(_state); - err = ae_maxreal(err, ae_fabs(spline2dcalc(&c, t1, t2, _state)-spline2dcalc(&c2, t1, t2, _state), _state), _state); - } - cperrors = cperrors||ae_fp_greater(err,10000*ae_machineepsilon); - - /* - * Serialization test - */ - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - spline2dbuildbicubic(&x, &y, &f, m, n, &c, _state); - } - else - { - spline2dbuildbilinear(&x, &y, &f, m, n, &c, _state); - } - testspline2dunit_unsetspline2d(&c2, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - spline2dalloc(&_local_serializer, &c, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - spline2dserialize(&_local_serializer, &c, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - spline2dunserialize(&_local_serializer, &c2, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - err = (double)(0); - for(i=1; i<=5; i++) - { - t1 = ax+(bx-ax)*ae_randomreal(_state); - t2 = ay+(by-ay)*ae_randomreal(_state); - err = ae_maxreal(err, ae_fabs(spline2dcalc(&c, t1, t2, _state)-spline2dcalc(&c2, t1, t2, _state), _state), _state); - } - ae_set_error_flag(&sererrors, ae_fp_greater(err,10000*ae_machineepsilon), __FILE__, __LINE__, "testspline2dunit.ap:292"); - - /* - * Special symmetry test - */ - err = (double)(0); - for(jobtype=0; jobtype<=1; jobtype++) - { - - /* - * Prepare - */ - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - ft.ptr.pp_double[j][i] = f.ptr.pp_double[i][j]; - } - } - if( jobtype==0 ) - { - spline2dbuildbilinear(&x, &y, &f, m, n, &c, _state); - spline2dbuildbilinear(&y, &x, &ft, n, m, &c2, _state); - } - else - { - spline2dbuildbicubic(&x, &y, &f, m, n, &c, _state); - spline2dbuildbicubic(&y, &x, &ft, n, m, &c2, _state); - } - - /* - * Test - */ - for(i=1; i<=10; i++) - { - t1 = ax+(bx-ax)*ae_randomreal(_state); - t2 = ay+(by-ay)*ae_randomreal(_state); - err = ae_maxreal(err, ae_fabs(spline2dcalc(&c, t1, t2, _state)-spline2dcalc(&c2, t2, t1, _state), _state), _state); - } - } - syerrors = syerrors||ae_fp_greater(err,10000*ae_machineepsilon); - } - } - } - - /* - * Test resample - */ - for(m=2; m<=6; m++) - { - for(n=2; n<=6; n++) - { - ae_matrix_set_length(&f, m-1+1, n-1+1, _state); - ae_vector_set_length(&x, n-1+1, _state); - ae_vector_set_length(&y, m-1+1, _state); - for(j=0; j<=n-1; j++) - { - x.ptr.p_double[j] = (double)j/(double)(n-1); - } - for(i=0; i<=m-1; i++) - { - y.ptr.p_double[i] = (double)i/(double)(m-1); - } - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - f.ptr.pp_double[i][j] = ae_exp(0.6*x.ptr.p_double[j], _state)-ae_exp(-0.3*y.ptr.p_double[i]+0.08*x.ptr.p_double[j], _state)+2*ae_cos(ae_pi*(x.ptr.p_double[j]+1.2*y.ptr.p_double[i]), _state)+0.1*ae_cos(20*x.ptr.p_double[j]+15*y.ptr.p_double[i], _state); - } - } - for(m2=2; m2<=6; m2++) - { - for(n2=2; n2<=6; n2++) - { - for(pass=1; pass<=passcount; pass++) - { - for(jobtype=0; jobtype<=1; jobtype++) - { - if( jobtype==0 ) - { - spline2dresamplebilinear(&f, m, n, &fr, m2, n2, _state); - spline2dbuildbilinear(&x, &y, &f, m, n, &c, _state); - } - if( jobtype==1 ) - { - spline2dresamplebicubic(&f, m, n, &fr, m2, n2, _state); - spline2dbuildbicubic(&x, &y, &f, m, n, &c, _state); - } - err = (double)(0); - mf = (double)(0); - for(i=0; i<=m2-1; i++) - { - for(j=0; j<=n2-1; j++) - { - v1 = spline2dcalc(&c, (double)j/(double)(n2-1), (double)i/(double)(m2-1), _state); - v2 = fr.ptr.pp_double[i][j]; - err = ae_maxreal(err, ae_fabs(v1-v2, _state), _state); - mf = ae_maxreal(mf, ae_fabs(v1, _state), _state); - } - } - if( jobtype==0 ) - { - rlerrors = rlerrors||ae_fp_greater(err/mf,10000*ae_machineepsilon); - } - if( jobtype==1 ) - { - rcerrors = rcerrors||ae_fp_greater(err/mf,10000*ae_machineepsilon); - } - } - } - } - } - } - } - - /* - * Test for vector-function - */ - vferrors = testspline2dunit_testspline2dvf(ae_true, _state); - - /* - * Report - */ - waserrors = (((((((((((((blerrors||bcerrors)||dserrors)||cperrors)||sererrors)||uperrors)||lterrors)||syerrors)||rlerrors)||rcerrors)||vferrors)||fiterrorsprior)||fiterrorspenalty)||fiterrorsblocksolver)||fiterrorsfastddmsolver; - if( !silent ) - { - printf("TESTING 2D SPLINE\n"); - - /* - * Normal tests - */ - printf("INTERPOLATION:\n"); - printf("* bilinear "); - if( blerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* bicubic "); - if( bcerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* differentiation "); - if( dserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* copying "); - if( cperrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* serialization "); - if( sererrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* unpacking "); - if( uperrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* lin.trans. "); - if( lterrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* special symmetry props "); - if( syerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* vector spline "); - if( vferrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("FITTING:\n"); - printf("* linear prior term "); - if( fiterrorsprior ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* nonlinearity penalty term "); - if( fiterrorspenalty ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* block solver "); - if( fiterrorsblocksolver ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* fast DDM solver "); - if( fiterrorsfastddmsolver ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("RESAMPLING:\n"); - printf("* bilinear "); - if( rlerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* bicubic "); - if( rcerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - - /* - * Summary - */ - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - - /* - * end - */ - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Lipschitz constants for spline inself, first and second derivatives. -*************************************************************************/ -static void testspline2dunit_lconst(spline2dinterpolant* c, - /* Real */ ae_vector* lx, - /* Real */ ae_vector* ly, - ae_int_t m, - ae_int_t n, - double lstep, - double* lc, - double* lcx, - double* lcy, - double* lcxy, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double f1; - double f2; - double f3; - double f4; - double fx1; - double fx2; - double fx3; - double fx4; - double fy1; - double fy2; - double fy3; - double fy4; - double fxy1; - double fxy2; - double fxy3; - double fxy4; - double s2lstep; - - *lc = 0; - *lcx = 0; - *lcy = 0; - *lcxy = 0; - - *lc = (double)(0); - *lcx = (double)(0); - *lcy = (double)(0); - *lcxy = (double)(0); - s2lstep = ae_sqrt((double)(2), _state)*lstep; - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - - /* - * Calculate - */ - testspline2dunit_twodnumder(c, lx->ptr.p_double[j]-lstep/2, ly->ptr.p_double[i]-lstep/2, lstep/4, &f1, &fx1, &fy1, &fxy1, _state); - testspline2dunit_twodnumder(c, lx->ptr.p_double[j]+lstep/2, ly->ptr.p_double[i]-lstep/2, lstep/4, &f2, &fx2, &fy2, &fxy2, _state); - testspline2dunit_twodnumder(c, lx->ptr.p_double[j]+lstep/2, ly->ptr.p_double[i]+lstep/2, lstep/4, &f3, &fx3, &fy3, &fxy3, _state); - testspline2dunit_twodnumder(c, lx->ptr.p_double[j]-lstep/2, ly->ptr.p_double[i]+lstep/2, lstep/4, &f4, &fx4, &fy4, &fxy4, _state); - - /* - * Lipschitz constant for the function itself - */ - *lc = ae_maxreal(*lc, ae_fabs((f1-f2)/lstep, _state), _state); - *lc = ae_maxreal(*lc, ae_fabs((f2-f3)/lstep, _state), _state); - *lc = ae_maxreal(*lc, ae_fabs((f3-f4)/lstep, _state), _state); - *lc = ae_maxreal(*lc, ae_fabs((f4-f1)/lstep, _state), _state); - *lc = ae_maxreal(*lc, ae_fabs((f1-f3)/s2lstep, _state), _state); - *lc = ae_maxreal(*lc, ae_fabs((f2-f4)/s2lstep, _state), _state); - - /* - * Lipschitz constant for the first derivative - */ - *lcx = ae_maxreal(*lcx, ae_fabs((fx1-fx2)/lstep, _state), _state); - *lcx = ae_maxreal(*lcx, ae_fabs((fx2-fx3)/lstep, _state), _state); - *lcx = ae_maxreal(*lcx, ae_fabs((fx3-fx4)/lstep, _state), _state); - *lcx = ae_maxreal(*lcx, ae_fabs((fx4-fx1)/lstep, _state), _state); - *lcx = ae_maxreal(*lcx, ae_fabs((fx1-fx3)/s2lstep, _state), _state); - *lcx = ae_maxreal(*lcx, ae_fabs((fx2-fx4)/s2lstep, _state), _state); - - /* - * Lipschitz constant for the first derivative - */ - *lcy = ae_maxreal(*lcy, ae_fabs((fy1-fy2)/lstep, _state), _state); - *lcy = ae_maxreal(*lcy, ae_fabs((fy2-fy3)/lstep, _state), _state); - *lcy = ae_maxreal(*lcy, ae_fabs((fy3-fy4)/lstep, _state), _state); - *lcy = ae_maxreal(*lcy, ae_fabs((fy4-fy1)/lstep, _state), _state); - *lcy = ae_maxreal(*lcy, ae_fabs((fy1-fy3)/s2lstep, _state), _state); - *lcy = ae_maxreal(*lcy, ae_fabs((fy2-fy4)/s2lstep, _state), _state); - - /* - * Lipschitz constant for the cross-derivative - */ - *lcxy = ae_maxreal(*lcxy, ae_fabs((fxy1-fxy2)/lstep, _state), _state); - *lcxy = ae_maxreal(*lcxy, ae_fabs((fxy2-fxy3)/lstep, _state), _state); - *lcxy = ae_maxreal(*lcxy, ae_fabs((fxy3-fxy4)/lstep, _state), _state); - *lcxy = ae_maxreal(*lcxy, ae_fabs((fxy4-fxy1)/lstep, _state), _state); - *lcxy = ae_maxreal(*lcxy, ae_fabs((fxy1-fxy3)/s2lstep, _state), _state); - *lcxy = ae_maxreal(*lcxy, ae_fabs((fxy2-fxy4)/s2lstep, _state), _state); - } - } -} - - -/************************************************************************* -Numerical differentiation. -*************************************************************************/ -static void testspline2dunit_twodnumder(spline2dinterpolant* c, - double x, - double y, - double h, - double* f, - double* fx, - double* fy, - double* fxy, - ae_state *_state) -{ - - *f = 0; - *fx = 0; - *fy = 0; - *fxy = 0; - - *f = spline2dcalc(c, x, y, _state); - *fx = (spline2dcalc(c, x+h, y, _state)-spline2dcalc(c, x-h, y, _state))/(2*h); - *fy = (spline2dcalc(c, x, y+h, _state)-spline2dcalc(c, x, y-h, _state))/(2*h); - *fxy = (spline2dcalc(c, x+h, y+h, _state)-spline2dcalc(c, x-h, y+h, _state)-spline2dcalc(c, x+h, y-h, _state)+spline2dcalc(c, x-h, y-h, _state))/ae_sqr(2*h, _state); -} - - -/************************************************************************* -Unpack test -*************************************************************************/ -static ae_bool testspline2dunit_testunpack(spline2dinterpolant* c, - /* Real */ ae_vector* lx, - /* Real */ ae_vector* ly, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t n; - ae_int_t m; - ae_int_t ci; - ae_int_t cj; - ae_int_t p; - double err; - double tx; - double ty; - double v1; - double v2; - ae_int_t pass; - ae_int_t passcount; - ae_matrix tbl; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&tbl, 0, sizeof(tbl)); - ae_matrix_init(&tbl, 0, 0, DT_REAL, _state, ae_true); - - passcount = 20; - err = (double)(0); - spline2dunpack(c, &m, &n, &tbl, _state); - for(i=0; i<=m-2; i++) - { - for(j=0; j<=n-2; j++) - { - for(pass=1; pass<=passcount; pass++) - { - p = (n-1)*i+j; - tx = (0.001+0.999*ae_randomreal(_state))*(tbl.ptr.pp_double[p][1]-tbl.ptr.pp_double[p][0]); - ty = (0.001+0.999*ae_randomreal(_state))*(tbl.ptr.pp_double[p][3]-tbl.ptr.pp_double[p][2]); - - /* - * Interpolation properties - */ - v1 = (double)(0); - for(ci=0; ci<=3; ci++) - { - for(cj=0; cj<=3; cj++) - { - v1 = v1+tbl.ptr.pp_double[p][4+ci*4+cj]*ae_pow(tx, (double)(ci), _state)*ae_pow(ty, (double)(cj), _state); - } - } - v2 = spline2dcalc(c, tbl.ptr.pp_double[p][0]+tx, tbl.ptr.pp_double[p][2]+ty, _state); - err = ae_maxreal(err, ae_fabs(v1-v2, _state), _state); - - /* - * Grid correctness - */ - err = ae_maxreal(err, ae_fabs(lx->ptr.p_double[2*j]-tbl.ptr.pp_double[p][0], _state), _state); - err = ae_maxreal(err, ae_fabs(lx->ptr.p_double[2*(j+1)]-tbl.ptr.pp_double[p][1], _state), _state); - err = ae_maxreal(err, ae_fabs(ly->ptr.p_double[2*i]-tbl.ptr.pp_double[p][2], _state), _state); - err = ae_maxreal(err, ae_fabs(ly->ptr.p_double[2*(i+1)]-tbl.ptr.pp_double[p][3], _state), _state); - } - } - } - result = ae_fp_less(err,10000*ae_machineepsilon); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -LinTrans test for scalar -*************************************************************************/ -static ae_bool testspline2dunit_testlintrans(spline2dinterpolant* c, - ae_int_t d, - double ax, - double bx, - double ay, - double by, - ae_state *_state) -{ - ae_frame _frame_block; - double err; - double a1; - double a2; - double b1; - double b2; - double tx; - double ty; - double vx; - double vy; - ae_vector v1; - ae_vector v2; - ae_int_t pass; - ae_int_t passcount; - ae_int_t xjob; - ae_int_t yjob; - spline2dinterpolant c2; - ae_int_t di; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&v1, 0, sizeof(v1)); - memset(&v2, 0, sizeof(v2)); - memset(&c2, 0, sizeof(c2)); - ae_vector_init(&v1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&v2, 0, DT_REAL, _state, ae_true); - _spline2dinterpolant_init(&c2, _state, ae_true); - - passcount = 5; - err = (double)(0); - for(xjob=0; xjob<=1; xjob++) - { - for(yjob=0; yjob<=1; yjob++) - { - for(pass=1; pass<=passcount; pass++) - { - - /* - * Prepare - */ - do - { - a1 = 2*ae_randomreal(_state)-1; - } - while(ae_fp_eq(a1,(double)(0))); - a1 = a1*xjob; - b1 = 2*ae_randomreal(_state)-1; - do - { - a2 = 2*ae_randomreal(_state)-1; - } - while(ae_fp_eq(a2,(double)(0))); - a2 = a2*yjob; - b2 = 2*ae_randomreal(_state)-1; - - /* - * Test XY - */ - spline2dcopy(c, &c2, _state); - spline2dlintransxy(&c2, a1, b1, a2, b2, _state); - tx = ax+ae_randomreal(_state)*(bx-ax); - ty = ay+ae_randomreal(_state)*(by-ay); - if( xjob==0 ) - { - tx = b1; - vx = ax+ae_randomreal(_state)*(bx-ax); - } - else - { - vx = (tx-b1)/a1; - } - if( yjob==0 ) - { - ty = b2; - vy = ay+ae_randomreal(_state)*(by-ay); - } - else - { - vy = (ty-b2)/a2; - } - spline2dcalcv(c, tx, ty, &v1, _state); - spline2dcalcv(&c2, vx, vy, &v2, _state); - for(di=0; di<=d-1; di++) - { - err = ae_maxreal(err, ae_fabs(v1.ptr.p_double[di]-v2.ptr.p_double[di], _state), _state); - } - - /* - * Test F - */ - spline2dcopy(c, &c2, _state); - spline2dlintransf(&c2, a1, b1, _state); - tx = ax+ae_randomreal(_state)*(bx-ax); - ty = ay+ae_randomreal(_state)*(by-ay); - spline2dcalcv(c, tx, ty, &v1, _state); - spline2dcalcv(&c2, tx, ty, &v2, _state); - for(di=0; di<=d-1; di++) - { - err = ae_maxreal(err, ae_fabs(a1*v1.ptr.p_double[di]+b1-v2.ptr.p_double[di], _state), _state); - } - } - } - } - result = ae_fp_less(err,10000*ae_machineepsilon); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Unset spline, i.e. initialize it with random garbage -*************************************************************************/ -static void testspline2dunit_unsetspline2d(spline2dinterpolant* c, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector x; - ae_vector y; - ae_matrix f; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&f, 0, sizeof(f)); - _spline2dinterpolant_clear(c); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&f, 0, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&x, 2, _state); - ae_vector_set_length(&y, 2, _state); - ae_matrix_set_length(&f, 2, 2, _state); - x.ptr.p_double[0] = (double)(-1); - x.ptr.p_double[1] = (double)(1); - y.ptr.p_double[0] = (double)(-1); - y.ptr.p_double[1] = (double)(1); - f.ptr.pp_double[0][0] = (double)(0); - f.ptr.pp_double[0][1] = (double)(0); - f.ptr.pp_double[1][0] = (double)(0); - f.ptr.pp_double[1][1] = (double)(0); - spline2dbuildbilinear(&x, &y, &f, 2, 2, c, _state); - ae_frame_leave(_state); -} - - -/************************************************************************* -The function check, that follow functions works correctly: - Spline2DBilinearV, Spline2DBicubicV, Spline2DCalcV, Spline2DCalcVI, - Spline2DDiffVI and Spline2DUnpackV. -*************************************************************************/ -static ae_bool testspline2dunit_testspline2dvf(ae_bool silent, - ae_state *_state) -{ - ae_frame _frame_block; - spline2dinterpolant vc; - spline2dinterpolant sc; - double range; - ae_vector x; - ae_vector y; - ae_vector f; - double rndx; - double rndy; - ae_vector resf; - ae_matrix ef; - double resef; - ae_int_t m; - ae_int_t n; - ae_int_t d; - ae_int_t tstn; - ae_int_t tstm; - ae_int_t tstd; - ae_matrix tsttbl0; - ae_matrix tsttbl1; - double eps; - double st; - ae_int_t p0; - ae_int_t p1; - ae_int_t variant; - ae_int_t pass; - ae_int_t passcount; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t i0; - ae_int_t j0; - double xmin; - double xmax; - double ymin; - double ymax; - double vi; - double vxi; - double vyi; - double vxyi; - double si; - double sxi; - double syi; - double sxyi; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&vc, 0, sizeof(vc)); - memset(&sc, 0, sizeof(sc)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&f, 0, sizeof(f)); - memset(&resf, 0, sizeof(resf)); - memset(&ef, 0, sizeof(ef)); - memset(&tsttbl0, 0, sizeof(tsttbl0)); - memset(&tsttbl1, 0, sizeof(tsttbl1)); - _spline2dinterpolant_init(&vc, _state, ae_true); - _spline2dinterpolant_init(&sc, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&f, 0, DT_REAL, _state, ae_true); - ae_vector_init(&resf, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ef, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&tsttbl0, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&tsttbl1, 0, 0, DT_REAL, _state, ae_true); - - eps = 10000.0*ae_machineepsilon; - st = 0.1; - passcount = 5; - result = ae_false; - for(pass=1; pass<=passcount; pass++) - { - for(variant=1; variant<=2; variant++) - { - range = (double)(ae_randominteger(71, _state)+30); - m = ae_randominteger(4, _state)+2; - n = ae_randominteger(4, _state)+2; - d = ae_randominteger(3, _state)+1; - rvectorsetlengthatleast(&x, n, _state); - rvectorsetlengthatleast(&y, m, _state); - rvectorsetlengthatleast(&f, n*m*d, _state); - rmatrixsetlengthatleast(&ef, m, n, _state); - - /* - * Build a grid for spline - */ - x.ptr.p_double[0] = range*(2*ae_randomreal(_state)-1); - y.ptr.p_double[0] = range*(2*ae_randomreal(_state)-1); - for(i=1; i<=n-1; i++) - { - x.ptr.p_double[i] = x.ptr.p_double[i-1]+st+ae_randomreal(_state); - } - for(i=1; i<=m-1; i++) - { - y.ptr.p_double[i] = y.ptr.p_double[i-1]+st+ae_randomreal(_state); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - for(k=0; k<=d-1; k++) - { - f.ptr.p_double[d*(n*j+i)+k] = range*(2*ae_randomreal(_state)-1); - } - } - } - xmin = x.ptr.p_double[0]; - xmax = x.ptr.p_double[n-1]; - ymin = y.ptr.p_double[0]; - ymax = y.ptr.p_double[m-1]; - - /* - * Build a spline - */ - if( variant==1 ) - { - spline2dbuildbilinearv(&x, n, &y, m, &f, d, &vc, _state); - } - if( variant==2 ) - { - spline2dbuildbicubicv(&x, n, &y, m, &f, d, &vc, _state); - } - - /* - * Part of test, which shows that Spline2DBuildBilinearV function - * works correctly. - * And there is test for Spline2DUnpackV. - */ - spline2dunpackv(&vc, &tstm, &tstn, &tstd, &tsttbl1, _state); - if( (tstm!=m||tstn!=n)||tstd!=d ) - { - if( !silent ) - { - printf("TestSpline2DVF fail Spline2DUnpack:\n"); - printf(" TstM=%0d; M=%0d;\n TstN=%0d; N=%0d;\n TstD=%0d; D=%0d.\n", - (int)(tstm), - (int)(m), - (int)(tstn), - (int)(n), - (int)(tstd), - (int)(d)); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(k=0; k<=d-1; k++) - { - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - ef.ptr.pp_double[i][j] = f.ptr.p_double[d*(i*n+j)+k]; - } - } - if( variant==1 ) - { - spline2dbuildbilinear(&x, &y, &ef, m, n, &sc, _state); - } - if( variant==2 ) - { - spline2dbuildbicubic(&x, &y, &ef, m, n, &sc, _state); - } - spline2dunpack(&sc, &tstm, &tstn, &tsttbl0, _state); - if( tstm!=m||tstn!=n ) - { - if( !silent ) - { - printf("TestSpline2DVF fail Spline2DUnpack:\n"); - printf(" TstM=%0d; M=%0d;\n TstN=%0d; N=%0d.\n", - (int)(tstm), - (int)(m), - (int)(tstn), - (int)(n)); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=m-2; i++) - { - for(j=0; j<=n-2; j++) - { - p0 = i*(n-1)+j; - p1 = d*p0; - for(i0=0; i0<=19; i0++) - { - if( ae_fp_neq(tsttbl1.ptr.pp_double[p1+k][i0],tsttbl0.ptr.pp_double[p0][i0]) ) - { - if( !silent ) - { - printf("TestSpline2DVF: Tbl error\n"); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - } - - /* - * Part of test, which shows that functions Spline2DCalcVBuf, Spline2DDiffVI, - * Spline2DCalcVI and Spline2DCalcV work correctly - */ - for(k=0; k<=d-1; k++) - { - - /* - * Build 1D spline corresponding to selected dimension (already tested) - */ - for(i0=0; i0<=m-1; i0++) - { - for(j0=0; j0<=n-1; j0++) - { - ef.ptr.pp_double[i0][j0] = f.ptr.p_double[d*(i0*n+j0)+k]; - } - } - if( variant==1 ) - { - spline2dbuildbilinear(&x, &y, &ef, m, n, &sc, _state); - } - if( variant==2 ) - { - spline2dbuildbicubic(&x, &y, &ef, m, n, &sc, _state); - } - - /* - * test at grid points - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=m-1; j++) - { - - /* - * Test calculation at grid points - */ - spline2dcalcv(&vc, x.ptr.p_double[i], y.ptr.p_double[j], &resf, _state); - resef = spline2dcalc(&sc, x.ptr.p_double[i], y.ptr.p_double[j], _state); - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(resf.ptr.p_double[k]-resef, _state),eps), __FILE__, __LINE__, "testspline2dunit.ap:914"); - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(spline2dcalcvi(&vc, x.ptr.p_double[i], y.ptr.p_double[j], k, _state)-resef, _state),eps), __FILE__, __LINE__, "testspline2dunit.ap:915"); - - /* - * Test differentiation at grid points - */ - spline2ddiffvi(&vc, x.ptr.p_double[i], y.ptr.p_double[j], k, &vi, &vxi, &vyi, &vxyi, _state); - spline2ddiff(&sc, x.ptr.p_double[i], y.ptr.p_double[j], &si, &sxi, &syi, &sxyi, _state); - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vi-si, _state),eps*(ae_fabs(si, _state)+1)), __FILE__, __LINE__, "testspline2dunit.ap:922"); - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vxi-sxi, _state),eps*(ae_fabs(sxi, _state)+1)), __FILE__, __LINE__, "testspline2dunit.ap:923"); - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vyi-syi, _state),eps*(ae_fabs(syi, _state)+1)), __FILE__, __LINE__, "testspline2dunit.ap:924"); - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vxyi-sxyi, _state),eps*(ae_fabs(sxyi, _state)+1)), __FILE__, __LINE__, "testspline2dunit.ap:925"); - } - } - - /* - * Test at random points - */ - for(i=0; i<=n*m-1; i++) - { - rndx = xmin+(xmax-xmin)*ae_randomreal(_state); - rndy = ymin+(ymax-ymin)*ae_randomreal(_state); - - /* - * Test calculation at random points - */ - spline2dcalcv(&vc, rndx, rndy, &resf, _state); - resef = spline2dcalc(&sc, rndx, rndy, _state); - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(resf.ptr.p_double[k]-resef, _state),eps), __FILE__, __LINE__, "testspline2dunit.ap:941"); - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(spline2dcalcvi(&vc, rndx, rndy, k, _state)-resef, _state),eps), __FILE__, __LINE__, "testspline2dunit.ap:942"); - - /* - * Test differentiation at random points - */ - spline2ddiffvi(&vc, rndx, rndy, k, &vi, &vxi, &vyi, &vxyi, _state); - spline2ddiff(&sc, rndx, rndy, &si, &sxi, &syi, &sxyi, _state); - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vi-si, _state),eps*(ae_fabs(si, _state)+1)), __FILE__, __LINE__, "testspline2dunit.ap:949"); - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vxi-sxi, _state),eps*(ae_fabs(sxi, _state)+1)), __FILE__, __LINE__, "testspline2dunit.ap:950"); - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vyi-syi, _state),eps*(ae_fabs(syi, _state)+1)), __FILE__, __LINE__, "testspline2dunit.ap:951"); - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vxyi-sxyi, _state),eps*(ae_fabs(sxyi, _state)+1)), __FILE__, __LINE__, "testspline2dunit.ap:952"); - } - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Fitting, properties of linear prior term -*************************************************************************/ -static void testspline2dunit_testfittingprior(ae_bool* errorflag, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector kv; - ae_int_t d; - ae_int_t kidx; - ae_int_t areatype; - ae_int_t solvertype; - ae_int_t i; - ae_int_t j; - ae_int_t k; - hqrndstate rs; - double tol; - spline2dbuilder state; - spline2dinterpolant s; - spline2dinterpolant s2; - spline2dinterpolant s3; - spline2dfitreport rep; - spline2dfitreport rep2; - spline2dfitreport rep3; - ae_int_t kx; - ae_int_t ky; - ae_int_t npoints; - ae_matrix xy; - ae_matrix xy2; - ae_matrix xy3; - ae_matrix vterm; - double vprior; - double v; - ae_bool bad; - ae_vector meany; - ae_vector tmp0; - ae_vector tmp1; - - ae_frame_make(_state, &_frame_block); - memset(&kv, 0, sizeof(kv)); - memset(&rs, 0, sizeof(rs)); - memset(&state, 0, sizeof(state)); - memset(&s, 0, sizeof(s)); - memset(&s2, 0, sizeof(s2)); - memset(&s3, 0, sizeof(s3)); - memset(&rep, 0, sizeof(rep)); - memset(&rep2, 0, sizeof(rep2)); - memset(&rep3, 0, sizeof(rep3)); - memset(&xy, 0, sizeof(xy)); - memset(&xy2, 0, sizeof(xy2)); - memset(&xy3, 0, sizeof(xy3)); - memset(&vterm, 0, sizeof(vterm)); - memset(&meany, 0, sizeof(meany)); - memset(&tmp0, 0, sizeof(tmp0)); - memset(&tmp1, 0, sizeof(tmp1)); - ae_vector_init(&kv, 0, DT_INT, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - _spline2dbuilder_init(&state, _state, ae_true); - _spline2dinterpolant_init(&s, _state, ae_true); - _spline2dinterpolant_init(&s2, _state, ae_true); - _spline2dinterpolant_init(&s3, _state, ae_true); - _spline2dfitreport_init(&rep, _state, ae_true); - _spline2dfitreport_init(&rep2, _state, ae_true); - _spline2dfitreport_init(&rep3, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy3, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vterm, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&meany, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true); - - hqrndrandomize(&rs, _state); - tol = 1.0E-5; - - /* - * Check properties of underlying linear prior. - */ - ae_vector_set_length(&kv, 3, _state); - kv.ptr.p_int[0] = 5; - kv.ptr.p_int[1] = 10; - kv.ptr.p_int[2] = 16; - for(kidx=0; kidx<=kv.cnt-1; kidx++) - { - for(d=1; d<=3; d++) - { - for(areatype=0; areatype<=0; areatype++) - { - for(solvertype=1; solvertype<=2; solvertype++) - { - - /* - * Select grid size and create builder - */ - kx = 1+hqrnduniformi(&rs, kv.ptr.p_int[kidx], _state); - ky = 1+hqrnduniformi(&rs, kv.ptr.p_int[kidx], _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - kx = kv.ptr.p_int[kidx]; - } - else - { - ky = kv.ptr.p_int[kidx]; - } - spline2dbuildercreate(d, &state, _state); - spline2dbuildersetgrid(&state, kx, ky, _state); - if( solvertype==1 ) - { - spline2dbuildersetalgoblocklls(&state, 0.0, _state); - } - else - { - if( solvertype==2 ) - { - spline2dbuildersetalgonaivells(&state, 0.0, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - - /* - * Generate perfectly linear dataset, check against linear prior. - * At least 8 points is required to get stable results. - * - * NOTE: we also check that constant term does NOT work. - */ - ae_matrix_set_length(&vterm, d, 3, _state); - for(i=0; i<=d-1; i++) - { - for(j=0; j<=2; j++) - { - vterm.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - npoints = 8+ae_round(10*hqrnduniformr(&rs, _state), _state); - ae_vector_set_length(&meany, d, _state); - for(j=0; j<=d-1; j++) - { - meany.ptr.p_double[j] = (double)(0); - } - ae_matrix_set_length(&xy, npoints, 2+d, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state); - xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state); - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][2+j] = vterm.ptr.pp_double[j][0]*xy.ptr.pp_double[i][0]+vterm.ptr.pp_double[j][1]*xy.ptr.pp_double[i][1]+vterm.ptr.pp_double[j][2]; - meany.ptr.p_double[j] = meany.ptr.p_double[j]+xy.ptr.pp_double[i][2+j]/npoints; - } - } - spline2dbuildersetpoints(&state, &xy, npoints, _state); - spline2dbuildersetlinterm(&state, _state); - spline2dfit(&state, &s, &rep, _state); - ae_vector_set_length(&tmp0, 3, _state); - for(k=0; k<=10; k++) - { - tmp0.ptr.p_double[0] = 3*hqrnduniformr(&rs, _state)-1; - tmp0.ptr.p_double[1] = 3*hqrnduniformr(&rs, _state)-1; - tmp0.ptr.p_double[2] = 1.0; - spline2dcalcv(&s, tmp0.ptr.p_double[0], tmp0.ptr.p_double[1], &tmp1, _state); - for(j=0; j<=d-1; j++) - { - v = vterm.ptr.pp_double[j][0]*tmp0.ptr.p_double[0]+vterm.ptr.pp_double[j][1]*tmp0.ptr.p_double[1]+vterm.ptr.pp_double[j][2]; - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(tmp1.ptr.p_double[j]-v, _state)/ae_maxreal(ae_fabs(v, _state), (double)(1), _state),tol), __FILE__, __LINE__, "testspline2dunit.ap:1094"); - } - } - ae_set_error_flag(errorflag, ae_fp_greater(rep.rmserror,tol), __FILE__, __LINE__, "testspline2dunit.ap:1097"); - ae_set_error_flag(errorflag, ae_fp_greater(rep.avgerror,tol), __FILE__, __LINE__, "testspline2dunit.ap:1098"); - ae_set_error_flag(errorflag, ae_fp_greater(rep.maxerror,tol), __FILE__, __LINE__, "testspline2dunit.ap:1099"); - spline2dbuildersetconstterm(&state, _state); - spline2dfit(&state, &s, &rep, _state); - ae_vector_set_length(&tmp0, 3, _state); - bad = ae_false; - for(k=0; k<=10; k++) - { - tmp0.ptr.p_double[0] = 2+hqrnduniformr(&rs, _state); - tmp0.ptr.p_double[1] = 2+hqrnduniformr(&rs, _state); - tmp0.ptr.p_double[2] = 1.0; - spline2dcalcv(&s, tmp0.ptr.p_double[0], tmp0.ptr.p_double[1], &tmp1, _state); - for(j=0; j<=d-1; j++) - { - v = vterm.ptr.pp_double[j][0]*tmp0.ptr.p_double[0]+vterm.ptr.pp_double[j][1]*tmp0.ptr.p_double[1]+vterm.ptr.pp_double[j][2]; - bad = bad||ae_fp_greater(ae_fabs(tmp1.ptr.p_double[j]-v, _state),tol); - } - } - ae_set_error_flag(errorflag, !bad, __FILE__, __LINE__, "testspline2dunit.ap:1118"); - - /* - * Generate perfectly constant dataset, check against constant prior. - * At least 8 points is required to get stable results. - */ - ae_matrix_set_length(&vterm, d, 3, _state); - for(i=0; i<=d-1; i++) - { - for(j=0; j<=1; j++) - { - vterm.ptr.pp_double[i][j] = (double)(0); - } - vterm.ptr.pp_double[i][2] = hqrndnormal(&rs, _state); - } - npoints = 8+ae_round(10*hqrnduniformr(&rs, _state), _state); - ae_vector_set_length(&meany, d, _state); - for(j=0; j<=d-1; j++) - { - meany.ptr.p_double[j] = (double)(0); - } - ae_matrix_set_length(&xy, npoints, 2+d, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state); - xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state); - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][2+j] = vterm.ptr.pp_double[j][0]*xy.ptr.pp_double[i][0]+vterm.ptr.pp_double[j][1]*xy.ptr.pp_double[i][1]+vterm.ptr.pp_double[j][2]; - meany.ptr.p_double[j] = meany.ptr.p_double[j]+xy.ptr.pp_double[i][2+j]/npoints; - } - } - spline2dbuildersetpoints(&state, &xy, npoints, _state); - spline2dbuildersetconstterm(&state, _state); - spline2dfit(&state, &s, &rep, _state); - ae_vector_set_length(&tmp0, 3, _state); - for(k=0; k<=10; k++) - { - tmp0.ptr.p_double[0] = 3*hqrnduniformr(&rs, _state)-1; - tmp0.ptr.p_double[1] = 3*hqrnduniformr(&rs, _state)-1; - tmp0.ptr.p_double[2] = 1.0; - spline2dcalcv(&s, tmp0.ptr.p_double[0], tmp0.ptr.p_double[1], &tmp1, _state); - for(j=0; j<=d-1; j++) - { - v = vterm.ptr.pp_double[j][0]*tmp0.ptr.p_double[0]+vterm.ptr.pp_double[j][1]*tmp0.ptr.p_double[1]+vterm.ptr.pp_double[j][2]; - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(tmp1.ptr.p_double[j]-v, _state)/ae_maxreal(ae_fabs(v, _state), (double)(1), _state),tol), __FILE__, __LINE__, "testspline2dunit.ap:1159"); - } - } - ae_set_error_flag(errorflag, ae_fp_greater(rep.rmserror,tol), __FILE__, __LINE__, "testspline2dunit.ap:1162"); - ae_set_error_flag(errorflag, ae_fp_greater(rep.avgerror,tol), __FILE__, __LINE__, "testspline2dunit.ap:1163"); - ae_set_error_flag(errorflag, ae_fp_greater(rep.maxerror,tol), __FILE__, __LINE__, "testspline2dunit.ap:1164"); - - /* - * Generate perfectly constant dataset, check against user-defined constant prior. - * At least 8 points is required to get stable results. - */ - vprior = hqrndnormal(&rs, _state); - npoints = 8+ae_round(10*hqrnduniformr(&rs, _state), _state); - ae_vector_set_length(&meany, d, _state); - for(j=0; j<=d-1; j++) - { - meany.ptr.p_double[j] = (double)(0); - } - ae_matrix_set_length(&xy, npoints, 2+d, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state); - xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state); - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][2+j] = vprior; - meany.ptr.p_double[j] = meany.ptr.p_double[j]+xy.ptr.pp_double[i][2+j]/npoints; - } - } - spline2dbuildersetpoints(&state, &xy, npoints, _state); - spline2dbuildersetuserterm(&state, vprior, _state); - spline2dfit(&state, &s, &rep, _state); - ae_vector_set_length(&tmp0, 3, _state); - for(k=0; k<=10; k++) - { - tmp0.ptr.p_double[0] = 3*hqrnduniformr(&rs, _state)-1; - tmp0.ptr.p_double[1] = 3*hqrnduniformr(&rs, _state)-1; - tmp0.ptr.p_double[2] = 1.0; - spline2dcalcv(&s, tmp0.ptr.p_double[0], tmp0.ptr.p_double[1], &tmp1, _state); - for(j=0; j<=d-1; j++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(tmp1.ptr.p_double[j]-vprior, _state),tol), __FILE__, __LINE__, "testspline2dunit.ap:1199"); - } - } - ae_set_error_flag(errorflag, ae_fp_greater(rep.rmserror,tol), __FILE__, __LINE__, "testspline2dunit.ap:1201"); - ae_set_error_flag(errorflag, ae_fp_greater(rep.avgerror,tol), __FILE__, __LINE__, "testspline2dunit.ap:1202"); - ae_set_error_flag(errorflag, ae_fp_greater(rep.maxerror,tol), __FILE__, __LINE__, "testspline2dunit.ap:1203"); - spline2dbuildersetuserterm(&state, vprior+(2*hqrnduniformi(&rs, 2, _state)-1), _state); - spline2dfit(&state, &s, &rep, _state); - ae_vector_set_length(&tmp0, 3, _state); - for(k=0; k<=10; k++) - { - tmp0.ptr.p_double[0] = 2+hqrnduniformr(&rs, _state); - tmp0.ptr.p_double[1] = 2+hqrnduniformr(&rs, _state); - tmp0.ptr.p_double[2] = 1.0; - spline2dcalcv(&s, tmp0.ptr.p_double[0], tmp0.ptr.p_double[1], &tmp1, _state); - for(j=0; j<=d-1; j++) - { - ae_set_error_flag(errorflag, ae_fp_less_eq(ae_fabs(tmp1.ptr.p_double[j]-vprior, _state),tol), __FILE__, __LINE__, "testspline2dunit.ap:1216"); - } - } - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Nonlinearity penalty test -*************************************************************************/ -static void testspline2dunit_testfittingpenalty(ae_bool* errorflag, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t kidx; - ae_int_t pidx; - ae_int_t solvertype; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t d; - ae_int_t kx; - ae_int_t ky; - ae_int_t npoints; - ae_matrix xy; - spline2dinterpolant s; - spline2dinterpolant s2; - spline2dfitreport rep; - spline2dfitreport rep2; - hqrndstate rs; - spline2dbuilder state; - double rmserror; - ae_vector penalty; - ae_vector penalty2; - double v; - double v0; - double v1; - double f0; - double f1; - double f2; - double f3; - - ae_frame_make(_state, &_frame_block); - memset(&xy, 0, sizeof(xy)); - memset(&s, 0, sizeof(s)); - memset(&s2, 0, sizeof(s2)); - memset(&rep, 0, sizeof(rep)); - memset(&rep2, 0, sizeof(rep2)); - memset(&rs, 0, sizeof(rs)); - memset(&state, 0, sizeof(state)); - memset(&penalty, 0, sizeof(penalty)); - memset(&penalty2, 0, sizeof(penalty2)); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _spline2dinterpolant_init(&s, _state, ae_true); - _spline2dinterpolant_init(&s2, _state, ae_true); - _spline2dfitreport_init(&rep, _state, ae_true); - _spline2dfitreport_init(&rep2, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - _spline2dbuilder_init(&state, _state, ae_true); - ae_vector_init(&penalty, 0, DT_REAL, _state, ae_true); - ae_vector_init(&penalty2, 0, DT_REAL, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Penalized fitting problem: - * * square KxK grid, K>=8 (points do not "touch" each other by their far fields) - * * four points in the corners, perfectly linear value - * * zero prior term - * - * Check that: - * * with significant nonlinearity penalty we have nearly-linear fit, - * central value is an average of corner values - * * without nonlinearity penalty, central value is zero - */ - for(kidx=3; kidx<=4; kidx++) - { - for(solvertype=1; solvertype<=2; solvertype++) - { - - /* - * Generate dataset - */ - kx = ae_round(ae_pow((double)(2), (double)(kidx), _state), _state); - ky = kx; - npoints = 4; - ae_matrix_set_length(&xy, npoints, 3, _state); - xy.ptr.pp_double[0][0] = (double)(-1); - xy.ptr.pp_double[0][1] = (double)(-1); - xy.ptr.pp_double[0][2] = hqrndnormal(&rs, _state); - xy.ptr.pp_double[1][0] = (double)(1); - xy.ptr.pp_double[1][1] = (double)(-1); - xy.ptr.pp_double[1][2] = hqrndnormal(&rs, _state); - xy.ptr.pp_double[2][0] = (double)(-1); - xy.ptr.pp_double[2][1] = (double)(1); - xy.ptr.pp_double[2][2] = hqrndnormal(&rs, _state); - xy.ptr.pp_double[3][0] = (double)(1); - xy.ptr.pp_double[3][1] = (double)(1); - xy.ptr.pp_double[3][2] = xy.ptr.pp_double[0][2]+(xy.ptr.pp_double[1][2]-xy.ptr.pp_double[0][2])+(xy.ptr.pp_double[2][2]-xy.ptr.pp_double[0][2]); - - /* - * Create solver, set grid, area and other properties - * according to chosen test mode. - */ - spline2dbuildercreate(1, &state, _state); - spline2dbuildersetgrid(&state, kx, ky, _state); - spline2dbuildersetarea(&state, (double)(-1), (double)(1), (double)(-1), (double)(1), _state); - spline2dbuildersetpoints(&state, &xy, npoints, _state); - spline2dbuildersetzeroterm(&state, _state); - - /* - * Check fitting with penalty - */ - if( solvertype==1 ) - { - spline2dbuildersetalgoblocklls(&state, 1.0, _state); - } - else - { - if( solvertype==2 ) - { - spline2dbuildersetalgonaivells(&state, 1.0, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - spline2dfit(&state, &s, &rep, _state); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(spline2dcalc(&s, 0.0, 0.0, _state)-0.25*(xy.ptr.pp_double[0][2]+xy.ptr.pp_double[1][2]+xy.ptr.pp_double[2][2]+xy.ptr.pp_double[3][2]), _state),1.0E-4), __FILE__, __LINE__, "testspline2dunit.ap:1305"); - - /* - * Check fitting without penalty - */ - if( solvertype==1 ) - { - spline2dbuildersetalgoblocklls(&state, 0.0, _state); - } - else - { - if( solvertype==2 ) - { - spline2dbuildersetalgonaivells(&state, 0.0, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - spline2dfit(&state, &s2, &rep2, _state); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(spline2dcalc(&s2, 0.0, 0.0, _state), _state),1.0E-4), __FILE__, __LINE__, "testspline2dunit.ap:1318"); - } - } - - /* - * Solve a sequence of problems with increasing value of penalty coefficient; - * test that increasing penalty coefficient results in: - * * increased residuals - * * decreased value of penalty function - */ - for(solvertype=1; solvertype<=2; solvertype++) - { - for(d=1; d<=3; d++) - { - - /* - * Prepare solver and dataset - */ - kx = 6+hqrnduniformi(&rs, 5, _state); - ky = 6+hqrnduniformi(&rs, 5, _state); - npoints = 3*(kx+2)*(ky+2)+30; - ae_matrix_set_length(&xy, npoints, 2+d, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state); - xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state); - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state); - } - } - spline2dbuildercreate(d, &state, _state); - spline2dbuildersetgrid(&state, kx, ky, _state); - if( solvertype==1 ) - { - spline2dbuildersetalgoblocklls(&state, 0.0, _state); - } - else - { - if( solvertype==2 ) - { - spline2dbuildersetalgonaivells(&state, 0.0, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - spline2dbuildersetarea(&state, (double)(0), (double)(1), (double)(0), (double)(1), _state); - spline2dbuildersetpoints(&state, &xy, npoints, _state); - spline2dbuildersetzeroterm(&state, _state); - - /* - * Solve with zero penalty - */ - spline2dfit(&state, &s, &rep, _state); - rmserror = rep.rmserror; - ae_vector_set_length(&penalty, d, _state); - for(k=0; k<=d-1; k++) - { - penalty.ptr.p_double[k] = 0.0; - } - v = 1.0E-3; - for(i=0; i<=kx-1; i++) - { - for(j=0; j<=ky-1; j++) - { - v0 = (double)i/(double)(kx-1); - v1 = (double)j/(double)(ky-1); - for(k=0; k<=d-1; k++) - { - f0 = spline2dcalcvi(&s, v0-v, v1, k, _state); - f1 = spline2dcalcvi(&s, v0, v1, k, _state); - f2 = spline2dcalcvi(&s, v0+v, v1, k, _state); - penalty.ptr.p_double[k] = penalty.ptr.p_double[k]+ae_sqr((f0+f2-2*f1)/ae_sqr(v, _state), _state); - } - for(k=0; k<=d-1; k++) - { - f0 = spline2dcalcvi(&s, v0, v1-v, k, _state); - f1 = spline2dcalcvi(&s, v0, v1, k, _state); - f2 = spline2dcalcvi(&s, v0, v1+v, k, _state); - penalty.ptr.p_double[k] = penalty.ptr.p_double[k]+ae_sqr((f0+f2-2*f1)/ae_sqr(v, _state), _state); - } - for(k=0; k<=d-1; k++) - { - f0 = spline2dcalcvi(&s, v0-v, v1-v, k, _state); - f1 = spline2dcalcvi(&s, v0+v, v1-v, k, _state); - f2 = spline2dcalcvi(&s, v0-v, v1+v, k, _state); - f3 = spline2dcalcvi(&s, v0+v, v1+v, k, _state); - penalty.ptr.p_double[k] = penalty.ptr.p_double[k]+2*ae_sqr((f3-f2-f1+f0)/ae_sqr(v, _state), _state); - } - } - } - - /* - * Solve with non-zero penalty - */ - for(pidx=-6; pidx<=3; pidx++) - { - if( solvertype==1 ) - { - spline2dbuildersetalgoblocklls(&state, ae_pow((double)(10), (double)pidx/(double)2, _state), _state); - } - else - { - if( solvertype==2 ) - { - spline2dbuildersetalgonaivells(&state, ae_pow((double)(10), (double)pidx/(double)2, _state), _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - spline2dfit(&state, &s, &rep, _state); - ae_vector_set_length(&penalty2, d, _state); - for(k=0; k<=d-1; k++) - { - penalty2.ptr.p_double[k] = 0.0; - } - v = 1.0E-3; - for(i=0; i<=kx-1; i++) - { - for(j=0; j<=ky-1; j++) - { - v0 = (double)i/(double)(kx-1); - v1 = (double)j/(double)(ky-1); - for(k=0; k<=d-1; k++) - { - f0 = spline2dcalcvi(&s, v0-v, v1, k, _state); - f1 = spline2dcalcvi(&s, v0, v1, k, _state); - f2 = spline2dcalcvi(&s, v0+v, v1, k, _state); - penalty2.ptr.p_double[k] = penalty2.ptr.p_double[k]+ae_sqr((f0+f2-2*f1)/ae_sqr(v, _state), _state); - } - for(k=0; k<=d-1; k++) - { - f0 = spline2dcalcvi(&s, v0, v1-v, k, _state); - f1 = spline2dcalcvi(&s, v0, v1, k, _state); - f2 = spline2dcalcvi(&s, v0, v1+v, k, _state); - penalty2.ptr.p_double[k] = penalty2.ptr.p_double[k]+ae_sqr((f0+f2-2*f1)/ae_sqr(v, _state), _state); - } - for(k=0; k<=d-1; k++) - { - f0 = spline2dcalcvi(&s, v0-v, v1-v, k, _state); - f1 = spline2dcalcvi(&s, v0+v, v1-v, k, _state); - f2 = spline2dcalcvi(&s, v0-v, v1+v, k, _state); - f3 = spline2dcalcvi(&s, v0+v, v1+v, k, _state); - penalty2.ptr.p_double[k] = penalty2.ptr.p_double[k]+2*ae_sqr((f3-f2-f1+f0)/ae_sqr(v, _state), _state); - } - } - } - ae_set_error_flag(errorflag, ae_fp_less_eq(rep.rmserror,rmserror), __FILE__, __LINE__, "testspline2dunit.ap:1448"); - for(k=0; k<=d-1; k++) - { - ae_set_error_flag(errorflag, ae_fp_greater_eq(penalty2.ptr.p_double[k],penalty.ptr.p_double[k]), __FILE__, __LINE__, "testspline2dunit.ap:1450"); - } - rmserror = rep.rmserror; - for(k=0; k<=d-1; k++) - { - penalty.ptr.p_double[k] = penalty2.ptr.p_double[k]; - } - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Block solver test for fitting functionality -*************************************************************************/ -static void testspline2dunit_testfittingblocksolver(ae_bool* errorflag, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector kv; - ae_int_t d; - ae_int_t kidx; - ae_int_t areatype; - ae_int_t gridtype; - ae_int_t solvertype; - ae_int_t i; - ae_int_t j; - ae_int_t k; - hqrndstate rs; - double errtol; - spline2dbuilder state; - spline2dinterpolant s; - spline2dinterpolant s2; - spline2dinterpolant s3; - spline2dfitreport rep; - spline2dfitreport rep2; - spline2dfitreport rep3; - ae_int_t kx; - ae_int_t ky; - double w1; - double xc; - double yc; - ae_int_t npoints; - ae_matrix xy; - ae_matrix xy2; - ae_matrix xy3; - ae_matrix vterm; - ae_int_t priortype; - double mx; - double rmserror; - double avgerror; - double maxerror; - double rss; - double tss; - double r2; - double v; - double v0; - double v1; - ae_vector meany; - ae_vector tmp0; - ae_vector tmp1; - - ae_frame_make(_state, &_frame_block); - memset(&kv, 0, sizeof(kv)); - memset(&rs, 0, sizeof(rs)); - memset(&state, 0, sizeof(state)); - memset(&s, 0, sizeof(s)); - memset(&s2, 0, sizeof(s2)); - memset(&s3, 0, sizeof(s3)); - memset(&rep, 0, sizeof(rep)); - memset(&rep2, 0, sizeof(rep2)); - memset(&rep3, 0, sizeof(rep3)); - memset(&xy, 0, sizeof(xy)); - memset(&xy2, 0, sizeof(xy2)); - memset(&xy3, 0, sizeof(xy3)); - memset(&vterm, 0, sizeof(vterm)); - memset(&meany, 0, sizeof(meany)); - memset(&tmp0, 0, sizeof(tmp0)); - memset(&tmp1, 0, sizeof(tmp1)); - ae_vector_init(&kv, 0, DT_INT, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - _spline2dbuilder_init(&state, _state, ae_true); - _spline2dinterpolant_init(&s, _state, ae_true); - _spline2dinterpolant_init(&s2, _state, ae_true); - _spline2dinterpolant_init(&s3, _state, ae_true); - _spline2dfitreport_init(&rep, _state, ae_true); - _spline2dfitreport_init(&rep2, _state, ae_true); - _spline2dfitreport_init(&rep3, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy3, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vterm, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&meany, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true); - - hqrndrandomize(&rs, _state); - errtol = 1.0E-6; - - /* - * Check that default state (no dataset) results in zero model being returned. - */ - for(priortype=0; priortype<=2; priortype++) - { - for(d=1; d<=3; d++) - { - for(areatype=0; areatype<=1; areatype++) - { - for(gridtype=0; gridtype<=1; gridtype++) - { - for(solvertype=1; solvertype<=2; solvertype++) - { - - /* - * Create solver, set grid, area and other properties - * according to chosen test mode. - */ - kx = ae_maxint(4, 1+hqrnduniformi(&rs, 10, _state), _state); - ky = ae_maxint(4, 1+hqrnduniformi(&rs, 10, _state), _state); - spline2dbuildercreate(d, &state, _state); - if( gridtype==1 ) - { - spline2dbuildersetgrid(&state, kx, ky, _state); - } - if( solvertype==1 ) - { - spline2dbuildersetalgoblocklls(&state, 0.0, _state); - } - else - { - if( solvertype==2 ) - { - spline2dbuildersetalgonaivells(&state, 0.0, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - if( areatype==0 ) - { - spline2dbuildersetareaauto(&state, _state); - } - else - { - if( areatype==1 ) - { - spline2dbuildersetarea(&state, (double)(0), (double)(1), (double)(0), (double)(1), _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - if( priortype==0 ) - { - spline2dbuildersetlinterm(&state, _state); - } - else - { - if( priortype==1 ) - { - spline2dbuildersetconstterm(&state, _state); - } - else - { - if( priortype==2 ) - { - spline2dbuildersetzeroterm(&state, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - spline2dfit(&state, &s, &rep, _state); - - /* - * Test - */ - for(j=0; j<=d-1; j++) - { - ae_set_error_flag(errorflag, ae_fp_neq(spline2dcalcvi(&s, hqrndnormal(&rs, _state), hqrndnormal(&rs, _state), j, _state),(double)(0)), __FILE__, __LINE__, "testspline2dunit.ap:1550"); - } - ae_set_error_flag(errorflag, ae_fp_neq(rep.rmserror,(double)(0)), __FILE__, __LINE__, "testspline2dunit.ap:1551"); - ae_set_error_flag(errorflag, ae_fp_neq(rep.avgerror,(double)(0)), __FILE__, __LINE__, "testspline2dunit.ap:1552"); - ae_set_error_flag(errorflag, ae_fp_neq(rep.maxerror,(double)(0)), __FILE__, __LINE__, "testspline2dunit.ap:1553"); - ae_set_error_flag(errorflag, ae_fp_neq(rep.r2,(double)(1)), __FILE__, __LINE__, "testspline2dunit.ap:1554"); - } - } - } - } - } - - /* - * Check properties of regression spline fitting WITHOUT nonlinearity - * penalty. Absence of penalty term allows us to perform several indirect - * tests which are impossible when working under penalty. - * - * Section below performs following tests on completely random dataset: - * * correctness of report fields - * * indirect tests for fitting solver (fitting on residuals from previous fit) - */ - ae_vector_set_length(&kv, 5, _state); - kv.ptr.p_int[0] = 4; - kv.ptr.p_int[1] = 5; - kv.ptr.p_int[2] = 10; - kv.ptr.p_int[3] = 12; - kv.ptr.p_int[4] = 15; - for(kidx=0; kidx<=kv.cnt-1; kidx++) - { - for(d=1; d<=3; d++) - { - for(areatype=0; areatype<=1; areatype++) - { - for(gridtype=1; gridtype<=1; gridtype++) - { - for(solvertype=1; solvertype<=2; solvertype++) - { - - /* - * Generate dataset - */ - kx = ae_maxint(4, 1+hqrnduniformi(&rs, kv.ptr.p_int[kidx], _state), _state); - ky = ae_maxint(4, 1+hqrnduniformi(&rs, kv.ptr.p_int[kidx], _state), _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - kx = kv.ptr.p_int[kidx]; - } - else - { - ky = kv.ptr.p_int[kidx]; - } - w1 = ae_pow((double)(10), hqrndnormal(&rs, _state), _state); - xc = w1*(2*hqrnduniformr(&rs, _state)-1); - yc = w1*(2*hqrnduniformr(&rs, _state)-1); - ae_vector_set_length(&meany, d, _state); - for(j=0; j<=d-1; j++) - { - meany.ptr.p_double[j] = (double)(0); - } - npoints = ae_round((kx+2)*(ky+2)*(3+hqrnduniformr(&rs, _state)), _state); - ae_matrix_set_length(&xy, npoints, 2+d, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = xc+w1*(2*hqrnduniformr(&rs, _state)-1)*kx; - xy.ptr.pp_double[i][1] = yc+w1*(2*hqrnduniformr(&rs, _state)-1)*ky; - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state); - meany.ptr.p_double[j] = meany.ptr.p_double[j]+xy.ptr.pp_double[i][2+j]/npoints; - } - } - - /* - * Create solver, set grid, area and other properties - * according to chosen test mode. - */ - spline2dbuildercreate(d, &state, _state); - if( gridtype==1 ) - { - spline2dbuildersetgrid(&state, kx, ky, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - if( solvertype==1 ) - { - spline2dbuildersetalgoblocklls(&state, 0.0, _state); - } - else - { - if( solvertype==2 ) - { - spline2dbuildersetalgonaivells(&state, 0.0, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - if( areatype==0 ) - { - spline2dbuildersetareaauto(&state, _state); - } - else - { - if( areatype==1 ) - { - spline2dbuildersetarea(&state, xc-w1*kx, xc+w1*kx, yc-w1*ky, yc+w1*ky, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - spline2dbuildersetpoints(&state, &xy, npoints, _state); - spline2dfit(&state, &s, &rep, _state); - - /* - * Test report fields - */ - rmserror = (double)(0); - avgerror = (double)(0); - maxerror = (double)(0); - rss = 0.0; - tss = 0.0; - for(i=0; i<=npoints-1; i++) - { - spline2dcalcv(&s, xy.ptr.pp_double[i][0], xy.ptr.pp_double[i][1], &tmp0, _state); - for(j=0; j<=d-1; j++) - { - v = xy.ptr.pp_double[i][2+j]-tmp0.ptr.p_double[j]; - rss = rss+v*v; - tss = tss+ae_sqr(xy.ptr.pp_double[i][2+j]-meany.ptr.p_double[j], _state); - rmserror = rmserror+ae_sqr(v, _state); - avgerror = avgerror+ae_fabs(v, _state)/(npoints*d); - maxerror = ae_maxreal(maxerror, ae_fabs(v, _state), _state); - } - } - rmserror = ae_sqrt(rmserror/(npoints*d), _state); - r2 = 1.0-rss/coalesce(tss, (double)(1), _state); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(rmserror-rep.rmserror, _state),errtol), __FILE__, __LINE__, "testspline2dunit.ap:1654"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(avgerror-rep.avgerror, _state),errtol), __FILE__, __LINE__, "testspline2dunit.ap:1655"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(maxerror-rep.maxerror, _state),errtol), __FILE__, __LINE__, "testspline2dunit.ap:1656"); - if( ae_fp_greater(tss,1.0E-3) ) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(r2-rep.r2, _state),errtol), __FILE__, __LINE__, "testspline2dunit.ap:1658"); - } - - /* - * Minimalistic test for fitting quality: R2 is better than zero - * (zero value = fitting by median value). - */ - ae_set_error_flag(errorflag, ae_fp_less(rep.r2,0.0), __FILE__, __LINE__, "testspline2dunit.ap:1664"); - - /* - * Indirect test for solver: test that fitting on residuals from - * previous fitting does not significantly decrease residuals. - * - * In our test we require that residuals from residuals are - * greater than 0.8 times original residuals. - * - * In the ideal world, fitting on residuals will return same - * residuals, but during spline construction we made several - * compromises (regularization, pre-model phase). So, we just - * check that residuals are weakly decreased. - * - * NOTE: this test is performed only for significantly non-zero residuals - */ - if( ae_fp_greater(rep.rmserror,0.05) ) - { - ae_matrix_set_length(&xy2, npoints, 2+d, _state); - for(i=0; i<=npoints-1; i++) - { - xy2.ptr.pp_double[i][0] = xy.ptr.pp_double[i][0]; - xy2.ptr.pp_double[i][1] = xy.ptr.pp_double[i][1]; - spline2dcalcv(&s, xy.ptr.pp_double[i][0], xy.ptr.pp_double[i][1], &tmp1, _state); - for(j=0; j<=d-1; j++) - { - xy2.ptr.pp_double[i][2+j] = xy.ptr.pp_double[i][2+j]-tmp1.ptr.p_double[j]; - } - } - spline2dbuildersetpoints(&state, &xy2, npoints, _state); - spline2dfit(&state, &s2, &rep2, _state); - ae_set_error_flag(errorflag, ae_fp_less(rep2.rmserror,0.8*rep.rmserror), __FILE__, __LINE__, "testspline2dunit.ap:1693"); - } - } - } - } - } - } - - /* - * Direct test: - * * points on regular grid which is exactly the same as one used - * for regression, but with some noise added to point locations - * * we test that without penalty we get nearly-zero RMS error - */ - ae_vector_set_length(&kv, 5, _state); - kv.ptr.p_int[0] = 4; - kv.ptr.p_int[1] = 5; - kv.ptr.p_int[2] = 6; - kv.ptr.p_int[3] = 8; - kv.ptr.p_int[4] = 12; - for(kidx=0; kidx<=kv.cnt-1; kidx++) - { - for(d=1; d<=2; d++) - { - for(solvertype=1; solvertype<=2; solvertype++) - { - - /* - * Generate dataset - */ - kx = ae_maxint(4, 1+hqrnduniformi(&rs, kv.ptr.p_int[kidx], _state), _state); - ky = ae_maxint(4, 1+hqrnduniformi(&rs, kv.ptr.p_int[kidx], _state), _state); - if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) ) - { - kx = kv.ptr.p_int[kidx]; - } - else - { - ky = kv.ptr.p_int[kidx]; - } - npoints = kx*ky; - ae_matrix_set_length(&xy, npoints, 2+d, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = boundval(i%kx+0.05*hqrndnormal(&rs, _state), (double)(0), (double)(kx-1), _state); - xy.ptr.pp_double[i][1] = boundval(i/kx+0.05*hqrndnormal(&rs, _state), (double)(0), (double)(ky-1), _state); - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state); - } - } - - /* - * Create solver, set grid, area and other properties - * according to chosen test mode. - */ - spline2dbuildercreate(d, &state, _state); - spline2dbuildersetgrid(&state, kx, ky, _state); - if( solvertype==1 ) - { - spline2dbuildersetalgoblocklls(&state, 0.0, _state); - } - else - { - if( solvertype==2 ) - { - spline2dbuildersetalgonaivells(&state, 0.0, _state); - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - spline2dbuildersetareaauto(&state, _state); - spline2dbuildersetpoints(&state, &xy, npoints, _state); - spline2dfit(&state, &s, &rep, _state); - - /* - * Test - */ - for(i=0; i<=npoints-1; i++) - { - for(k=0; k<=d-1; k++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(spline2dcalcvi(&s, xy.ptr.pp_double[i][0], xy.ptr.pp_double[i][1], k, _state)-xy.ptr.pp_double[i][2+k], _state),1.0E-6), __FILE__, __LINE__, "testspline2dunit.ap:1754"); - } - } - } - } - } - - /* - * Compare results obtained with block solver vs naive one - */ - mx = (double)(0); - for(kx=4; kx<=8; kx++) - { - for(ky=4; ky<=8; ky++) - { - for(d=1; d<=2; d++) - { - - /* - * Generate dataset - */ - npoints = 300; - ae_matrix_set_length(&xy, npoints, 2+d, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = (kx-1)*hqrnduniformr(&rs, _state); - xy.ptr.pp_double[i][1] = (ky-1)*hqrnduniformr(&rs, _state); - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state); - } - } - - /* - * Create solver, set grid, area and other properties - * according to chosen test mode. - * - * NOTE: we perform just one iteration of LSQR in order - * to test subtle differences of two implementations - - * reference one (NaiveLLS) and high-performance one. - */ - spline2dbuildercreate(d, &state, _state); - spline2dbuildersetgrid(&state, kx, ky, _state); - spline2dbuildersetarea(&state, (double)(0), (double)(kx-1), (double)(0), (double)(ky-1), _state); - spline2dbuildersetpoints(&state, &xy, npoints, _state); - state.lsqrcnt = 1; - spline2dbuildersetalgonaivells(&state, 0.0, _state); - spline2dfit(&state, &s, &rep, _state); - spline2dbuildersetalgoblocklls(&state, 0.0, _state); - spline2dfit(&state, &s2, &rep2, _state); - for(i=0; i<=npoints-1; i++) - { - spline2dcalcv(&s, xy.ptr.pp_double[i][0], xy.ptr.pp_double[i][1], &tmp0, _state); - spline2dcalcv(&s2, xy.ptr.pp_double[i][0], xy.ptr.pp_double[i][1], &tmp1, _state); - for(j=0; j<=d-1; j++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(tmp0.ptr.p_double[j]-tmp1.ptr.p_double[j], _state),1.0E-6), __FILE__, __LINE__, "testspline2dunit.ap:1801"); - mx = ae_maxreal(mx, ae_fabs(tmp0.ptr.p_double[j]-tmp1.ptr.p_double[j], _state), _state); - } - } - } - } - } - - /* - * Investigate stability against minor perturbations - */ - d = 1; - kx = 20; - ky = 20; - npoints = 5*kx*ky; - ae_matrix_set_length(&xy, npoints, 2+d, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = (kx-1)*hqrnduniformr(&rs, _state); - xy.ptr.pp_double[i][1] = (ky-1)*hqrnduniformr(&rs, _state); - xy.ptr.pp_double[i][2] = hqrndnormal(&rs, _state); - } - spline2dbuildercreate(d, &state, _state); - spline2dbuildersetgrid(&state, kx, ky, _state); - spline2dbuildersetarea(&state, (double)(0), (double)(kx-1), (double)(0), (double)(ky-1), _state); - spline2dbuildersetalgoblocklls(&state, 0.001, _state); - spline2dbuildersetpoints(&state, &xy, npoints, _state); - spline2dfit(&state, &s, &rep, _state); - for(i=0; i<=npoints-1; i++) - { - j = i+hqrnduniformi(&rs, npoints-i, _state); - swaprows(&xy, i, j, -1, _state); - xy.ptr.pp_double[i][2] = xy.ptr.pp_double[i][2]+ae_machineepsilon*hqrndnormal(&rs, _state); - } - spline2dbuildersetpoints(&state, &xy, npoints, _state); - spline2dfit(&state, &s2, &rep2, _state); - mx = (double)(0); - maxerror = (double)(0); - for(i=0; i<=npoints-1; i++) - { - v0 = (kx-1)*hqrnduniformr(&rs, _state); - v1 = (ky-1)*hqrnduniformr(&rs, _state); - maxerror = ae_maxreal(maxerror, ae_fabs(spline2dcalc(&s, v0, v1, _state)-spline2dcalc(&s2, v0, v1, _state), _state), _state); - mx = ae_maxreal(mx, ae_fabs(spline2dcalc(&s, v0, v1, _state), _state), _state); - } - ae_set_error_flag(errorflag, ae_fp_greater(maxerror/mx,1.0E-12), __FILE__, __LINE__, "testspline2dunit.ap:1846"); - ae_frame_leave(_state); -} - - -/************************************************************************* -Block solver test for fitting functionality -*************************************************************************/ -static void testspline2dunit_testfittingfastddmsolver(ae_bool* errorflag, - ae_state *_state) -{ - ae_frame _frame_block; - hqrndstate rs; - ae_int_t pass; - ae_int_t tilesize; - ae_int_t interfacesize; - ae_int_t npoints; - ae_int_t d; - ae_int_t kx; - ae_int_t ky; - ae_int_t kxcur; - ae_int_t kycur; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v0; - double v1; - double vx; - double vy; - double f0; - double f1; - double f2; - double f3; - double h; - double smax; - double ernd; - double ept; - double emax; - double eavg; - double vmax; - ae_int_t padding; - ae_int_t nlayers; - ae_matrix xy; - ae_matrix xy1; - spline2dbuilder state; - spline2dinterpolant sa0; - spline2dinterpolant sa1; - spline2dinterpolant s1; - spline2dinterpolant s2; - spline2dfitreport rep0; - spline2dfitreport rep1; - spline2dfitreport rep2; - ae_vector meany; - ae_vector lambdaa; - ae_vector penaltya; - ae_vector rmsa; - double rmserror; - double avgerror; - double maxerror; - double rss; - double tss; - double r2; - double v; - - ae_frame_make(_state, &_frame_block); - memset(&rs, 0, sizeof(rs)); - memset(&xy, 0, sizeof(xy)); - memset(&xy1, 0, sizeof(xy1)); - memset(&state, 0, sizeof(state)); - memset(&sa0, 0, sizeof(sa0)); - memset(&sa1, 0, sizeof(sa1)); - memset(&s1, 0, sizeof(s1)); - memset(&s2, 0, sizeof(s2)); - memset(&rep0, 0, sizeof(rep0)); - memset(&rep1, 0, sizeof(rep1)); - memset(&rep2, 0, sizeof(rep2)); - memset(&meany, 0, sizeof(meany)); - memset(&lambdaa, 0, sizeof(lambdaa)); - memset(&penaltya, 0, sizeof(penaltya)); - memset(&rmsa, 0, sizeof(rmsa)); - _hqrndstate_init(&rs, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy1, 0, 0, DT_REAL, _state, ae_true); - _spline2dbuilder_init(&state, _state, ae_true); - _spline2dinterpolant_init(&sa0, _state, ae_true); - _spline2dinterpolant_init(&sa1, _state, ae_true); - _spline2dinterpolant_init(&s1, _state, ae_true); - _spline2dinterpolant_init(&s2, _state, ae_true); - _spline2dfitreport_init(&rep0, _state, ae_true); - _spline2dfitreport_init(&rep1, _state, ae_true); - _spline2dfitreport_init(&rep2, _state, ae_true); - ae_vector_init(&meany, 0, DT_REAL, _state, ae_true); - ae_vector_init(&lambdaa, 0, DT_REAL, _state, ae_true); - ae_vector_init(&penaltya, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rmsa, 0, DT_REAL, _state, ae_true); - - hqrndrandomize(&rs, _state); - - /* - * Basic test: - * * small grid whose size is TileSize+1 or less - * * random dataset - * * compared with single run of naiveLLS - * * we also test correctness of report fields - */ - for(pass=1; pass<=3; pass++) - { - for(d=1; d<=3; d++) - { - tilesize = 8+hqrnduniformi(&rs, 8, _state); - kx = ae_maxint(1+hqrnduniformi(&rs, tilesize+1, _state), 4, _state); - ky = ae_maxint(1+hqrnduniformi(&rs, tilesize+1, _state), 4, _state); - npoints = 10*kx*ky; - ae_matrix_set_length(&xy, npoints, 2+d, _state); - ae_vector_set_length(&meany, d, _state); - for(j=0; j<=d-1; j++) - { - meany.ptr.p_double[j] = (double)(0); - } - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state); - xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state); - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state); - meany.ptr.p_double[j] = meany.ptr.p_double[j]+xy.ptr.pp_double[i][2+j]/npoints; - } - } - - /* - * Create solver, set grid, area and other properties. - * Fit with NaiveLLS first. - */ - spline2dbuildercreate(d, &state, _state); - spline2dbuildersetarea(&state, 0.0, 1.0, 0.0, 1.0, _state); - state.maxcoresize = tilesize; - state.adddegreeoffreedom = ae_false; - spline2dbuildersetalgonaivells(&state, 0.0, _state); - spline2dbuildersetpoints(&state, &xy, npoints, _state); - spline2dbuildersetgrid(&state, kx, ky, _state); - spline2dfit(&state, &sa0, &rep0, _state); - - /* - * Fit with FastDDM solver with NLayers in [-2,+2] - */ - spline2dbuildersetpoints(&state, &xy, npoints, _state); - spline2dbuildersetgrid(&state, kx, ky, _state); - spline2dbuildersetalgofastddm(&state, hqrnduniformi(&rs, 5, _state)-2, 0.0, _state); - spline2dfit(&state, &s1, &rep1, _state); - - /* - * Compare at random locations - */ - smax = 0.0; - ernd = 0.0; - for(k=0; k<=20*kx*ky-1; k++) - { - vx = hqrnduniformr(&rs, _state); - vy = hqrnduniformr(&rs, _state); - for(j=0; j<=d-1; j++) - { - v0 = spline2dcalcvi(&sa0, vx, vy, j, _state); - v1 = spline2dcalcvi(&s1, vx, vy, j, _state); - smax = ae_maxreal(smax, ae_fabs(v0, _state), _state); - ernd = ae_maxreal(ernd, ae_fabs(v0-v1, _state), _state); - } - } - ae_set_error_flag(errorflag, ae_fp_greater(ernd/smax,0.001), __FILE__, __LINE__, "testspline2dunit.ap:1964"); - - /* - * Test report fields - */ - rmserror = (double)(0); - avgerror = (double)(0); - maxerror = (double)(0); - rss = 0.0; - tss = 0.0; - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=d-1; j++) - { - v = xy.ptr.pp_double[i][2+j]-spline2dcalcvi(&s1, xy.ptr.pp_double[i][0], xy.ptr.pp_double[i][1], j, _state); - rss = rss+v*v; - tss = tss+ae_sqr(xy.ptr.pp_double[i][2+j]-meany.ptr.p_double[j], _state); - rmserror = rmserror+ae_sqr(v, _state); - avgerror = avgerror+ae_fabs(v, _state)/(npoints*d); - maxerror = ae_maxreal(maxerror, ae_fabs(v, _state), _state); - } - } - rmserror = ae_sqrt(rmserror/(npoints*d), _state); - r2 = 1.0-rss/coalesce(tss, (double)(1), _state); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(rmserror-rep1.rmserror, _state),1.0E-6), __FILE__, __LINE__, "testspline2dunit.ap:1988"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(avgerror-rep1.avgerror, _state),1.0E-6), __FILE__, __LINE__, "testspline2dunit.ap:1989"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(maxerror-rep1.maxerror, _state),1.0E-6), __FILE__, __LINE__, "testspline2dunit.ap:1990"); - if( ae_fp_greater(tss,1.0E-3) ) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(r2-rep1.r2, _state),1.0E-6), __FILE__, __LINE__, "testspline2dunit.ap:1992"); - } - } - } - - /* - * Basic test: two-layer task; "reference" model is built by - * subsequent fitting of two "traditional" splines; test model - * is built by FastDDM algorithm. - */ - tilesize = 15; - for(d=1; d<=2; d++) - { - - /* - * Generate dataset - */ - kx = 2*tilesize+1; - ky = 2*tilesize+1; - npoints = kx*ky; - ae_matrix_set_length(&xy, npoints, 2+d, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = boundval(i%kx+0.05*hqrndnormal(&rs, _state), (double)(0), (double)(kx-1), _state); - xy.ptr.pp_double[i][1] = boundval(i/kx+0.05*hqrndnormal(&rs, _state), (double)(0), (double)(ky-1), _state); - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state); - } - } - - /* - * Create solver, set grid, area and other properties - */ - spline2dbuildercreate(d, &state, _state); - spline2dbuildersetarea(&state, (double)(0), (double)(kx-1), (double)(0), (double)(ky-1), _state); - state.maxcoresize = tilesize; - - /* - * Fit with BlockLLS solver - */ - state.adddegreeoffreedom = ae_false; - spline2dbuildersetalgoblocklls(&state, 0.0, _state); - spline2dbuildersetpoints(&state, &xy, npoints, _state); - spline2dbuildersetgrid(&state, (kx-1)/2+1, (ky-1)/2+1, _state); - spline2dfit(&state, &sa0, &rep0, _state); - ae_matrix_set_length(&xy1, npoints, 2+d, _state); - for(i=0; i<=npoints-1; i++) - { - xy1.ptr.pp_double[i][0] = xy.ptr.pp_double[i][0]; - xy1.ptr.pp_double[i][1] = xy.ptr.pp_double[i][1]; - for(j=0; j<=d-1; j++) - { - xy1.ptr.pp_double[i][2+j] = xy.ptr.pp_double[i][2+j]-spline2dcalcvi(&sa0, xy.ptr.pp_double[i][0], xy.ptr.pp_double[i][1], j, _state); - } - } - spline2dbuildersetpoints(&state, &xy1, npoints, _state); - spline2dbuildersetgrid(&state, kx, ky, _state); - spline2dfit(&state, &sa1, &rep0, _state); - - /* - * Fit with another solver - */ - spline2dbuildersetpoints(&state, &xy, npoints, _state); - spline2dbuildersetgrid(&state, kx, ky, _state); - spline2dbuildersetalgofastddm(&state, 0, 0.0, _state); - spline2dfit(&state, &s1, &rep1, _state); - - /* - * Compare - */ - padding = 0; - smax = 0.0; - ernd = 0.0; - for(k=0; k<=20*kx*ky-1; k++) - { - vx = (kx-1-2*padding)*hqrnduniformr(&rs, _state)+padding; - vy = (ky-1-2*padding)*hqrnduniformr(&rs, _state)+padding; - for(j=0; j<=d-1; j++) - { - v0 = spline2dcalcvi(&sa0, vx, vy, j, _state)+spline2dcalcvi(&sa1, vx, vy, j, _state); - v1 = spline2dcalcvi(&s1, vx, vy, j, _state); - smax = ae_maxreal(smax, ae_fabs(v0, _state), _state); - ernd = ae_maxreal(ernd, ae_fabs(v0-v1, _state), _state); - } - } - ae_set_error_flag(errorflag, ae_fp_greater(ernd/smax,0.010), __FILE__, __LINE__, "testspline2dunit.ap:2071"); - ept = 0.0; - for(i=0; i<=npoints-1; i++) - { - vx = xy.ptr.pp_double[i][0]; - vy = xy.ptr.pp_double[i][1]; - for(j=0; j<=d-1; j++) - { - v0 = spline2dcalcvi(&sa0, vx, vy, j, _state)+spline2dcalcvi(&sa1, vx, vy, j, _state); - v1 = spline2dcalcvi(&s1, vx, vy, j, _state); - smax = ae_maxreal(smax, ae_fabs(v0, _state), _state); - ept = ae_maxreal(ept, ae_fabs(v0-v1, _state), _state); - } - } - ae_set_error_flag(errorflag, ae_fp_greater(ept/smax,0.001), __FILE__, __LINE__, "testspline2dunit.ap:2085"); - } - - /* - * Test correctness of error reporting in multilevel setting: - * * grid whose size is larger than TileSize+1 - * * random dataset - * * we just test correctness of report fields - */ - for(pass=1; pass<=2; pass++) - { - for(d=1; d<=2; d++) - { - tilesize = 5+hqrnduniformi(&rs, 3, _state); - kx = ae_maxint(1+hqrnduniformi(&rs, 5*tilesize+1, _state), 4, _state); - ky = ae_maxint(1+hqrnduniformi(&rs, 5*tilesize+1, _state), 4, _state); - npoints = 10*kx*ky; - ae_matrix_set_length(&xy, npoints, 2+d, _state); - ae_vector_set_length(&meany, d, _state); - for(j=0; j<=d-1; j++) - { - meany.ptr.p_double[j] = (double)(0); - } - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state); - xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state); - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state); - meany.ptr.p_double[j] = meany.ptr.p_double[j]+xy.ptr.pp_double[i][2+j]/npoints; - } - } - - /* - * Create solver, set grid, area and other properties. - * Fit with FastDDM solver - */ - spline2dbuildercreate(d, &state, _state); - spline2dbuildersetarea(&state, 0.0, 1.0, 0.0, 1.0, _state); - state.maxcoresize = tilesize; - spline2dbuildersetpoints(&state, &xy, npoints, _state); - spline2dbuildersetgrid(&state, kx, ky, _state); - spline2dbuildersetalgofastddm(&state, hqrnduniformi(&rs, 5, _state)-2, 0.0, _state); - spline2dfit(&state, &s1, &rep1, _state); - - /* - * Test report fields - */ - rmserror = (double)(0); - avgerror = (double)(0); - maxerror = (double)(0); - rss = 0.0; - tss = 0.0; - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=d-1; j++) - { - v = xy.ptr.pp_double[i][2+j]-spline2dcalcvi(&s1, xy.ptr.pp_double[i][0], xy.ptr.pp_double[i][1], j, _state); - rss = rss+v*v; - tss = tss+ae_sqr(xy.ptr.pp_double[i][2+j]-meany.ptr.p_double[j], _state); - rmserror = rmserror+ae_sqr(v, _state); - avgerror = avgerror+ae_fabs(v, _state)/(npoints*d); - maxerror = ae_maxreal(maxerror, ae_fabs(v, _state), _state); - } - } - rmserror = ae_sqrt(rmserror/(npoints*d), _state); - r2 = 1.0-rss/coalesce(tss, (double)(1), _state); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(rmserror-rep1.rmserror, _state),1.0E-6), __FILE__, __LINE__, "testspline2dunit.ap:2152"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(avgerror-rep1.avgerror, _state),1.0E-6), __FILE__, __LINE__, "testspline2dunit.ap:2153"); - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(maxerror-rep1.maxerror, _state),1.0E-6), __FILE__, __LINE__, "testspline2dunit.ap:2154"); - if( ae_fp_greater(tss,1.0E-3) ) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(r2-rep1.r2, _state),1.0E-6), __FILE__, __LINE__, "testspline2dunit.ap:2156"); - } - } - } - - /* - * Test correctness of handling NLayers>0, NLayers=0 and NLayers<0. - * - * NOTE: we use reduced tile size and interface size, because we do - * not test model quality, just identity with NLayers<=0 - */ - d = 1; - tilesize = 5; - interfacesize = 2; - kx = 1+4*(tilesize-hqrnduniformi(&rs, 2, _state)); - ky = 1+4*(tilesize-hqrnduniformi(&rs, 2, _state)); - nlayers = 3; - npoints = kx*ky; - ae_matrix_set_length(&xy, npoints, 2+d, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state); - xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state); - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state); - } - } - - /* - * Create solver, set grid, area and other properties. - */ - spline2dbuildercreate(d, &state, _state); - spline2dbuildersetarea(&state, 0.0, 1.0, 0.0, 1.0, _state); - state.maxcoresize = tilesize; - state.interfacesize = interfacesize; - spline2dbuildersetpoints(&state, &xy, npoints, _state); - spline2dbuildersetgrid(&state, kx, ky, _state); - - /* - * Try different NLayers>0, compare with corresponding non-positive values - */ - for(k=1; k<=nlayers+1; k++) - { - spline2dbuildersetalgofastddm(&state, k, 0.0, _state); - spline2dfit(&state, &s1, &rep1, _state); - spline2dbuildersetalgofastddm(&state, imin2(k-nlayers, 0, _state), 0.0, _state); - spline2dfit(&state, &s2, &rep2, _state); - - /* - * Test report fields - */ - vmax = (double)(0); - for(i=0; i<=10; i++) - { - vx = hqrnduniformr(&rs, _state); - vy = hqrnduniformr(&rs, _state); - vmax = ae_maxreal(vmax, ae_fabs(spline2dcalc(&s1, vx, vy, _state)-spline2dcalc(&s2, vx, vy, _state), _state), _state); - } - ae_set_error_flag(errorflag, ae_fp_greater(vmax,1.0E-12), __FILE__, __LINE__, "testspline2dunit.ap:2212"); - } - - /* - * Ability to reproduce target function in multilayer setup: - * * small tile size - * * nearly regular KX*KY dataset, for random KX>TileSize, KY>TileSize - * * (2*KX)x(2*KY) grid, flexible enough - * - * We check that maximum and average errors at nodes are small - */ - vmax = 0.0; - for(pass=1; pass<=10; pass++) - { - d = 1; - tilesize = 5+hqrnduniformi(&rs, 4, _state); - kx = 4+hqrnduniformi(&rs, 4*tilesize+1, _state); - ky = 4+hqrnduniformi(&rs, 4*tilesize+1, _state); - npoints = kx*ky; - ae_matrix_set_length(&xy, npoints, 2+d, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = boundval(i%kx+0.05*hqrndnormal(&rs, _state), (double)(0), (double)(kx-1), _state); - xy.ptr.pp_double[i][1] = boundval(i/kx+0.05*hqrndnormal(&rs, _state), (double)(0), (double)(ky-1), _state); - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state); - } - } - - /* - * Create solver, set grid, area and other properties. - */ - spline2dbuildercreate(d, &state, _state); - state.maxcoresize = tilesize; - spline2dbuildersetpoints(&state, &xy, npoints, _state); - spline2dbuildersetgrid(&state, ae_round(2.0*kx, _state), ae_round(2.0*ky, _state), _state); - spline2dbuildersetarea(&state, 0.0, (double)(kx-1), 0.0, (double)(ky-1), _state); - spline2dbuildersetalgofastddm(&state, 0, 0.0, _state); - spline2dfit(&state, &s1, &rep1, _state); - - /* - * Compare - */ - emax = 0.0; - eavg = 0.0; - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=d-1; j++) - { - v = ae_fabs(spline2dcalcvi(&s1, xy.ptr.pp_double[i][0], xy.ptr.pp_double[i][1], j, _state)-xy.ptr.pp_double[i][2+j], _state); - emax = ae_maxreal(emax, v, _state); - eavg = eavg+v/(npoints*d); - } - } - ae_set_error_flag(errorflag, ae_fp_greater(emax,0.00100), __FILE__, __LINE__, "testspline2dunit.ap:2265"); - ae_set_error_flag(errorflag, ae_fp_greater(eavg,0.00010), __FILE__, __LINE__, "testspline2dunit.ap:2266"); - vmax = ae_maxreal(vmax, ae_fabs(emax, _state), _state); - } - - /* - * Test that increasing LambdaV results in decrease of S'' integral; - * although (unlike BlockLLS) FastDDM does NOT minimize S'' explicitly, - * it shows similar behavior with respect to regularization, so we can - * expect that penalty decreases. - * - * NOTE: we use ultra-small values of tile size and interface size because - * precision is not important here. - */ - for(pass=0; pass<=2; pass++) - { - d = 1; - tilesize = 5; - kx = 1+4*(tilesize-hqrnduniformi(&rs, 2, _state)); - ky = 1+4*(tilesize-hqrnduniformi(&rs, 2, _state)); - npoints = -1; - vx = (double)(0); - vy = (double)(0); - if( pass==0 ) - { - npoints = 1+ae_round(0.5*kx*ky, _state); - ae_matrix_set_length(&xy, npoints, 2+d, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state); - xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state); - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state); - } - } - vx = (double)1/(double)(kx-1); - vy = (double)1/(double)(ky-1); - } - if( pass==1 ) - { - npoints = kx*ky; - ae_matrix_set_length(&xy, npoints, 2+d, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = boundval(i%kx+0.05*hqrndnormal(&rs, _state), (double)(0), (double)(kx-1), _state); - xy.ptr.pp_double[i][1] = boundval(i/kx+0.05*hqrndnormal(&rs, _state), (double)(0), (double)(ky-1), _state); - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state); - } - } - vx = (double)(1); - vy = (double)(1); - } - if( pass==2 ) - { - npoints = 1+ae_round(3.0*kx*ky, _state); - ae_matrix_set_length(&xy, npoints, 2+d, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state); - xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state); - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state); - } - } - vx = (double)1/(double)(kx-1); - vy = (double)1/(double)(ky-1); - } - ae_assert(ae_fp_greater(vx,(double)(0)), "Spline2D: unit test failed integrity check", _state); - ae_assert(ae_fp_greater(vy,(double)(0)), "Spline2D: unit test failed integrity check", _state); - - /* - * Create solver, set grid, area and other properties. - */ - spline2dbuildercreate(d, &state, _state); - spline2dbuildersetarea(&state, (double)(0), (double)(kx-1), (double)(0), (double)(ky-1), _state); - state.maxcoresize = tilesize; - spline2dbuildersetpoints(&state, &xy, npoints, _state); - spline2dbuildersetgrid(&state, kx, ky, _state); - - /* - * Try different values of LambdaV, calculate penalty - */ - ae_vector_set_length(&lambdaa, 4, _state); - lambdaa.ptr.p_double[0] = 0.0; - lambdaa.ptr.p_double[1] = 1.0E-1; - lambdaa.ptr.p_double[2] = 1.0E+1; - lambdaa.ptr.p_double[3] = 1.0E+2; - ae_vector_set_length(&penaltya, lambdaa.cnt, _state); - ae_vector_set_length(&rmsa, lambdaa.cnt, _state); - for(k=0; k<=lambdaa.cnt-1; k++) - { - spline2dbuildersetalgofastddm(&state, 0, lambdaa.ptr.p_double[k], _state); - spline2dfit(&state, &s1, &rep1, _state); - h = 1.0E-4; - v = 0.0; - for(i=0; i<=kx-1; i++) - { - for(j=0; j<=ky-1; j++) - { - v0 = i*vx; - v1 = j*vy; - f0 = spline2dcalc(&s1, v0-h, v1, _state); - f1 = spline2dcalc(&s1, v0, v1, _state); - f2 = spline2dcalc(&s1, v0+h, v1, _state); - v = v+ae_sqr((f0+f2-2*f1)/ae_sqr(h, _state), _state); - f0 = spline2dcalc(&s1, v0, v1-h, _state); - f1 = spline2dcalc(&s1, v0, v1, _state); - f2 = spline2dcalc(&s1, v0, v1+h, _state); - v = v+ae_sqr((f0+f2-2*f1)/ae_sqr(h, _state), _state); - f0 = spline2dcalc(&s1, v0-h, v1-h, _state); - f1 = spline2dcalc(&s1, v0+h, v1-h, _state); - f2 = spline2dcalc(&s1, v0-h, v1+h, _state); - f3 = spline2dcalc(&s1, v0+h, v1+h, _state); - v = v+2*ae_sqr((f3-f2-f1+f0)/ae_sqr(h, _state), _state); - } - } - penaltya.ptr.p_double[k] = v; - rmsa.ptr.p_double[k] = rep1.rmserror; - } - for(k=0; k<=lambdaa.cnt-2; k++) - { - ae_set_error_flag(errorflag, ae_fp_less(penaltya.ptr.p_double[k],penaltya.ptr.p_double[k+1]), __FILE__, __LINE__, "testspline2dunit.ap:2387"); - } - } - - /* - * Test that refining grid in "K:=2*K-1" fashion results in - * decrease of RMS error; although it seems quite silly test, - * in fact it checks various failures in the algorithm. - * - * NOTE: we set high penalty coefficient in order to avoid nearly - * precise fits (such fits are hard to test reliably) - * - * NOTE: we use ultra-small values of tile size and interface size because - * precision is not important here. - */ - for(pass=0; pass<=2; pass++) - { - d = 1; - tilesize = 5; - kx = 1+4*tilesize; - ky = 1+4*tilesize; - nlayers = 3; - npoints = -1; - if( pass==0 ) - { - npoints = 1+ae_round(0.1*kx*ky, _state); - ae_matrix_set_length(&xy, npoints, 2+d, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state); - xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state); - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state); - } - } - vx = (double)1/(double)(kx-1); - vy = (double)1/(double)(ky-1); - } - if( pass==1 ) - { - npoints = kx*ky; - ae_matrix_set_length(&xy, npoints, 2+d, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = boundval(i%kx+0.05*hqrndnormal(&rs, _state), (double)(0), (double)(kx-1), _state); - xy.ptr.pp_double[i][1] = boundval(i/kx+0.05*hqrndnormal(&rs, _state), (double)(0), (double)(ky-1), _state); - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state); - } - } - vx = (double)(1); - vy = (double)(1); - } - if( pass==2 ) - { - npoints = 1+ae_round(2.0*kx*ky, _state); - ae_matrix_set_length(&xy, npoints, 2+d, _state); - for(i=0; i<=npoints-1; i++) - { - xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state); - xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state); - for(j=0; j<=d-1; j++) - { - xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state); - } - } - vx = (double)1/(double)(kx-1); - vy = (double)1/(double)(ky-1); - } - - /* - * Create solver, set grid, area and other properties. - */ - spline2dbuildercreate(d, &state, _state); - spline2dbuildersetarea(&state, (double)(0), (double)(kx-1), (double)(0), (double)(ky-1), _state); - state.maxcoresize = tilesize; - spline2dbuildersetpoints(&state, &xy, npoints, _state); - - /* - * Try different values of LambdaV, calculate penalty - */ - ae_vector_set_length(&rmsa, nlayers, _state); - kxcur = tilesize+1; - kycur = tilesize+1; - for(k=0; k<=rmsa.cnt-1; k++) - { - spline2dbuildersetgrid(&state, kxcur, kycur, _state); - spline2dbuildersetalgofastddm(&state, 0, 0.0, _state); - spline2dfit(&state, &s1, &rep1, _state); - rmsa.ptr.p_double[k] = rep1.rmserror; - kxcur = 2*kxcur-1; - kycur = 2*kycur-1; - } - for(k=0; k<=rmsa.cnt-2; k++) - { - ae_set_error_flag(errorflag, ae_fp_less_eq(rmsa.ptr.p_double[k],rmsa.ptr.p_double[k+1]), __FILE__, __LINE__, "testspline2dunit.ap:2479"); - } - } - ae_frame_leave(_state); -} - - - -static double testrbfunit_tol = 1.0E-10; -static ae_int_t testrbfunit_mxits = 0; -static double testrbfunit_heps = 1.0E-12; -static ae_bool testrbfunit_specialtest(ae_state *_state); -static ae_bool testrbfunit_basicrbftest(ae_state *_state); -static ae_bool testrbfunit_irregularrbftest(ae_state *_state); -static ae_bool testrbfunit_linearitymodelrbftest(ae_state *_state); -static ae_bool testrbfunit_serializationtest(ae_state *_state); -static ae_bool testrbfunit_searcherr(/* Real */ ae_matrix* y0, - /* Real */ ae_matrix* y1, - ae_int_t n, - ae_int_t ny, - ae_int_t errtype, - /* Real */ ae_vector* b1, - /* Real */ ae_vector* delta, - ae_state *_state); -static ae_bool testrbfunit_basicmultilayerrbftest(ae_state *_state); -static void testrbfunit_gridcalc23test(ae_bool* errorflag, - ae_state *_state); -static ae_bool testrbfunit_basichrbftest(ae_state *_state); -static ae_bool testrbfunit_scaledhrbftest(ae_state *_state); -static ae_bool testrbfunit_spechrbftest(ae_state *_state); -static ae_bool testrbfunit_gridhrbftest(ae_state *_state); - - - - - -ae_bool testrbf(ae_bool silent, ae_state *_state) -{ - ae_bool specialerrors; - ae_bool basicrbferrors; - ae_bool irregularrbferrors; - ae_bool linearitymodelrbferr; - ae_bool sqrdegmatrixrbferr; - ae_bool sererrors; - ae_bool multilayerrbf1derrors; - ae_bool multilayerrbferrors; - ae_bool gridcalc23errors; - ae_bool hrbfbasicerrors; - ae_bool hrbfscaleerrors; - ae_bool hrbfspecerrors; - ae_bool hrbfgriderrors; - ae_bool hrbferrors; - ae_bool waserrors; - ae_bool result; - - - - /* - * HRBF tests - */ - hrbfbasicerrors = testrbfunit_basichrbftest(_state); - hrbfspecerrors = testrbfunit_spechrbftest(_state); - hrbfscaleerrors = testrbfunit_scaledhrbftest(_state); - hrbfgriderrors = testrbfunit_gridhrbftest(_state); - hrbferrors = ((hrbfbasicerrors||hrbfspecerrors)||hrbfscaleerrors)||hrbfgriderrors; - - /* - * Other tests - */ - specialerrors = testrbfunit_specialtest(_state); - basicrbferrors = testrbfunit_basicrbftest(_state); - irregularrbferrors = testrbfunit_irregularrbftest(_state); - linearitymodelrbferr = testrbfunit_linearitymodelrbftest(_state); - sqrdegmatrixrbferr = sqrdegmatrixrbftest(ae_true, _state); - multilayerrbf1derrors = ae_false; - multilayerrbferrors = testrbfunit_basicmultilayerrbftest(_state); - sererrors = testrbfunit_serializationtest(_state); - gridcalc23errors = ae_false; - testrbfunit_gridcalc23test(&gridcalc23errors, _state); - - /* - * report - */ - waserrors = ((((((((specialerrors||basicrbferrors)||irregularrbferrors)||linearitymodelrbferr)||sqrdegmatrixrbferr)||sererrors)||multilayerrbf1derrors)||multilayerrbferrors)||gridcalc23errors)||hrbferrors; - if( !silent ) - { - printf("TESTING RBF\n"); - printf("GENERAL TESTS:\n"); - printf("* serialization test: "); - if( sererrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* special properties: "); - if( specialerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("RBF-V2:\n"); - printf("* basic HRBF test: "); - if( hrbfbasicerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* scale-related tests: "); - if( hrbfscaleerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* grid calculation tests: "); - if( hrbfgriderrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* special properties: "); - if( hrbfspecerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("RBF-V1:\n"); - printf("* basicRBFTest: "); - if( basicrbferrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* irregularRBFTest: "); - if( irregularrbferrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* linearity test: "); - if( linearitymodelrbferr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* SqrDegMatrixRBFTest: "); - if( sqrdegmatrixrbferr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* MultiLayerRBFErrors in 1D test: "); - if( multilayerrbf1derrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* MultiLayerRBFErrors in 2-3D test: "); - if( multilayerrbferrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* GridCalc2/3V: "); - if( gridcalc23errors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - - /* - * was errors? - */ - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - return result; -} - - -/************************************************************************* -The test has to check, that algorithm can solve problems of matrix are -degenerate. - * used model with linear term; - * points locate in a subspace of dimension less than an original space. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -ae_bool sqrdegmatrixrbftest(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - rbfmodel s; - rbfreport rep; - ae_int_t nx; - ae_int_t ny; - ae_int_t k0; - ae_int_t k1; - ae_int_t np; - double sx; - double sy; - double zx; - double px; - double zy; - double py; - double q; - double z; - ae_vector point; - ae_matrix a; - ae_vector d0; - ae_vector d1; - ae_int_t gen; - ae_vector pvd0; - ae_vector pvd1; - double pvdnorm; - double vnorm; - double dd0; - double dd1; - ae_matrix gp; - ae_vector x; - ae_vector y; - ae_int_t unx; - ae_int_t uny; - ae_matrix xwr; - ae_matrix v; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double eps; - ae_int_t modelversion; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&point, 0, sizeof(point)); - memset(&a, 0, sizeof(a)); - memset(&d0, 0, sizeof(d0)); - memset(&d1, 0, sizeof(d1)); - memset(&pvd0, 0, sizeof(pvd0)); - memset(&pvd1, 0, sizeof(pvd1)); - memset(&gp, 0, sizeof(gp)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&xwr, 0, sizeof(xwr)); - memset(&v, 0, sizeof(v)); - _rbfmodel_init(&s, _state, ae_true); - _rbfreport_init(&rep, _state, ae_true); - ae_vector_init(&point, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&pvd0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&pvd1, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&gp, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xwr, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true); - - zx = (double)(10); - px = (double)(15); - zy = (double)(10); - py = (double)(15); - eps = 1.0E-6; - ny = 1; - for(nx=2; nx<=3; nx++) - { - - /* - * prepare test problem - */ - sx = ae_pow(zx, px*(ae_randominteger(3, _state)-1), _state); - sy = ae_pow(zy, py*(ae_randominteger(3, _state)-1), _state); - ae_vector_set_length(&x, nx, _state); - ae_vector_set_length(&y, ny, _state); - ae_vector_set_length(&point, nx, _state); - rbfcreate(nx, ny, &s, _state); - rbfsetcond(&s, testrbfunit_heps, testrbfunit_heps, testrbfunit_mxits, _state); - q = 0.25+ae_randomreal(_state); - z = 4.5+ae_randomreal(_state); - rbfsetalgoqnn(&s, q, z, _state); - - /* - * start points for grid - */ - for(i=0; i<=nx-1; i++) - { - point.ptr.p_double[i] = sx*(2*ae_randomreal(_state)-1); - } - if( nx==2 ) - { - for(k0=2; k0<=4; k0++) - { - rmatrixrndorthogonal(nx, &a, _state); - ae_vector_set_length(&d0, nx, _state); - ae_v_move(&d0.ptr.p_double[0], 1, &a.ptr.pp_double[0][0], a.stride, ae_v_len(0,nx-1)); - np = k0; - ae_matrix_set_length(&gp, np, nx+ny, _state); - - /* - * create grid - */ - for(i=0; i<=k0-1; i++) - { - gp.ptr.pp_double[i][0] = point.ptr.p_double[0]+sx*i*d0.ptr.p_double[0]; - gp.ptr.pp_double[i][1] = point.ptr.p_double[1]+sx*i*d0.ptr.p_double[1]; - for(k=0; k<=ny-1; k++) - { - gp.ptr.pp_double[i][nx+k] = sy*(2*ae_randomreal(_state)-1); - } - } - rbfsetpoints(&s, &gp, np, _state); - rbfbuildmodel(&s, &rep, _state); - for(i=0; i<=np-1; i++) - { - x.ptr.p_double[0] = gp.ptr.pp_double[i][0]; - x.ptr.p_double[1] = gp.ptr.pp_double[i][1]; - rbfcalc(&s, &x, &y, _state); - for(j=0; j<=ny-1; j++) - { - if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - } - if( nx==3 ) - { - for(k0=2; k0<=4; k0++) - { - for(k1=2; k1<=4; k1++) - { - for(gen=1; gen<=2; gen++) - { - rmatrixrndorthogonal(nx, &a, _state); - ae_vector_set_length(&d0, nx, _state); - ae_v_move(&d0.ptr.p_double[0], 1, &a.ptr.pp_double[0][0], a.stride, ae_v_len(0,nx-1)); - - /* - * create grid - */ - np = -1; - if( gen==1 ) - { - np = k0; - ae_matrix_set_length(&gp, np, nx+ny, _state); - for(i=0; i<=k0-1; i++) - { - gp.ptr.pp_double[i][0] = point.ptr.p_double[0]+sx*i*d0.ptr.p_double[0]; - gp.ptr.pp_double[i][1] = point.ptr.p_double[1]+sx*i*d0.ptr.p_double[1]; - gp.ptr.pp_double[i][2] = point.ptr.p_double[2]+sx*i*d0.ptr.p_double[2]; - for(k=0; k<=ny-1; k++) - { - gp.ptr.pp_double[i][nx+k] = sy*(2*ae_randomreal(_state)-1); - } - } - } - if( gen==2 ) - { - ae_vector_set_length(&d1, nx, _state); - ae_v_move(&d1.ptr.p_double[0], 1, &a.ptr.pp_double[0][1], a.stride, ae_v_len(0,nx-1)); - np = k0*k1; - ae_matrix_set_length(&gp, np, nx+ny, _state); - for(i=0; i<=k0-1; i++) - { - for(j=0; j<=k1-1; j++) - { - gp.ptr.pp_double[i*k1+j][0] = sx*i*d0.ptr.p_double[0]+sx*j*d1.ptr.p_double[0]; - gp.ptr.pp_double[i*k1+j][1] = sx*i*d0.ptr.p_double[1]+sx*j*d1.ptr.p_double[1]; - gp.ptr.pp_double[i*k1+j][2] = sx*i*d0.ptr.p_double[2]+sx*j*d1.ptr.p_double[2]; - for(k=0; k<=ny-1; k++) - { - gp.ptr.pp_double[i*k1+j][nx+k] = sy*(2*ae_randomreal(_state)-1); - } - } - } - } - ae_assert(np>=0, "rbf test: integrity error", _state); - rbfsetpoints(&s, &gp, np, _state); - rbfbuildmodel(&s, &rep, _state); - for(i=0; i<=np-1; i++) - { - x.ptr.p_double[0] = gp.ptr.pp_double[i][0]; - x.ptr.p_double[1] = gp.ptr.pp_double[i][1]; - x.ptr.p_double[2] = gp.ptr.pp_double[i][2]; - rbfcalc(&s, &x, &y, _state); - for(j=0; j<=ny-1; j++) - { - if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - if( gen==2 ) - { - rbfunpack(&s, &unx, &uny, &xwr, &np, &v, &modelversion, _state); - dd0 = (d0.ptr.p_double[0]*v.ptr.pp_double[0][0]+d0.ptr.p_double[1]*v.ptr.pp_double[0][1]+d0.ptr.p_double[2]*v.ptr.pp_double[0][2])/(d0.ptr.p_double[0]*d0.ptr.p_double[0]+d0.ptr.p_double[1]*d0.ptr.p_double[1]+d0.ptr.p_double[2]*d0.ptr.p_double[2]); - dd1 = (d1.ptr.p_double[0]*v.ptr.pp_double[0][0]+d1.ptr.p_double[1]*v.ptr.pp_double[0][1]+d1.ptr.p_double[2]*v.ptr.pp_double[0][2])/(d1.ptr.p_double[0]*d1.ptr.p_double[0]+d1.ptr.p_double[1]*d1.ptr.p_double[1]+d1.ptr.p_double[2]*d1.ptr.p_double[2]); - ae_vector_set_length(&pvd0, nx, _state); - ae_vector_set_length(&pvd1, nx, _state); - for(i=0; i<=nx-1; i++) - { - pvd0.ptr.p_double[i] = dd0*d0.ptr.p_double[i]; - pvd1.ptr.p_double[i] = dd1*d1.ptr.p_double[i]; - } - pvdnorm = ae_sqrt(ae_sqr(v.ptr.pp_double[0][0]-pvd0.ptr.p_double[0]-pvd1.ptr.p_double[0], _state)+ae_sqr(v.ptr.pp_double[0][1]-pvd0.ptr.p_double[1]-pvd1.ptr.p_double[1], _state)+ae_sqr(v.ptr.pp_double[0][2]-pvd0.ptr.p_double[2]-pvd1.ptr.p_double[2], _state), _state); - vnorm = ae_sqrt(ae_sqr(v.ptr.pp_double[0][0], _state)+ae_sqr(v.ptr.pp_double[0][1], _state)+ae_sqr(v.ptr.pp_double[0][2], _state), _state); - if( ae_fp_greater(pvdnorm,vnorm*testrbfunit_tol) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Function for testing basic functionality of RBF module on regular grids with -multi-layer algorithm in 1D. - - -- ALGLIB -- - Copyright 2.03.2012 by Bochkanov Sergey -*************************************************************************/ -ae_bool basicmultilayerrbf1dtest(ae_state *_state) -{ - ae_frame _frame_block; - rbfmodel s; - rbfreport rep; - ae_int_t nx; - ae_int_t ny; - ae_int_t linterm; - ae_int_t n; - double q; - double r; - ae_int_t errtype; - ae_vector delta; - ae_int_t nlayers; - double a; - double b; - double f1; - double f2; - ae_vector a1; - ae_vector b1; - ae_matrix gp; - ae_vector x; - ae_vector y; - ae_matrix mody0; - ae_matrix mody1; - ae_matrix gy; - ae_vector gpgx0; - ae_vector gpgx1; - ae_int_t pass; - ae_int_t passcount; - ae_int_t i; - ae_int_t j; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&delta, 0, sizeof(delta)); - memset(&a1, 0, sizeof(a1)); - memset(&b1, 0, sizeof(b1)); - memset(&gp, 0, sizeof(gp)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&mody0, 0, sizeof(mody0)); - memset(&mody1, 0, sizeof(mody1)); - memset(&gy, 0, sizeof(gy)); - memset(&gpgx0, 0, sizeof(gpgx0)); - memset(&gpgx1, 0, sizeof(gpgx1)); - _rbfmodel_init(&s, _state, ae_true); - _rbfreport_init(&rep, _state, ae_true); - ae_vector_init(&delta, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b1, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&gp, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&mody0, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&mody1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&gy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&gpgx0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&gpgx1, 0, DT_REAL, _state, ae_true); - - a = 1.0; - b = (double)1/(double)9; - f1 = 1.0; - f2 = 10.0; - passcount = 5; - n = 100; - ae_vector_set_length(&gpgx0, n, _state); - ae_vector_set_length(&gpgx1, n, _state); - for(i=0; i<=n-1; i++) - { - gpgx0.ptr.p_double[i] = (double)i/(double)n; - gpgx1.ptr.p_double[i] = (double)(0); - } - r = (double)(1); - for(pass=0; pass<=passcount-1; pass++) - { - nx = ae_randominteger(2, _state)+2; - ny = ae_randominteger(3, _state)+1; - linterm = ae_randominteger(3, _state)+1; - ae_vector_set_length(&x, nx, _state); - ae_vector_set_length(&y, ny, _state); - ae_vector_set_length(&a1, ny, _state); - ae_vector_set_length(&b1, ny, _state); - ae_vector_set_length(&delta, ny, _state); - ae_matrix_set_length(&mody0, n, ny, _state); - ae_matrix_set_length(&mody1, n, ny, _state); - for(i=0; i<=ny-1; i++) - { - a1.ptr.p_double[i] = a+0.01*a*(2*ae_randomreal(_state)-1); - b1.ptr.p_double[i] = b+0.01*b*(2*ae_randomreal(_state)-1); - delta.ptr.p_double[i] = 0.35*b1.ptr.p_double[i]; - } - ae_matrix_set_length(&gp, n, nx+ny, _state); - - /* - * create grid - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - gp.ptr.pp_double[i][j] = (double)(0); - } - gp.ptr.pp_double[i][0] = (double)i/(double)n; - for(j=0; j<=ny-1; j++) - { - gp.ptr.pp_double[i][nx+j] = a1.ptr.p_double[j]*ae_cos(f1*2*ae_pi*gp.ptr.pp_double[i][0], _state)+b1.ptr.p_double[j]*ae_cos(f2*2*ae_pi*gp.ptr.pp_double[i][0], _state); - mody0.ptr.pp_double[i][j] = gp.ptr.pp_double[i][nx+j]; - } - } - q = (double)(1); - nlayers = 1; - errtype = 1; - - /* - * test multilayer algorithm with different parameters - */ - while(ae_fp_greater_eq(q,1/(2*f2))) - { - rbfcreate(nx, ny, &s, _state); - rbfsetalgomultilayer(&s, r, nlayers, 0.0, _state); - if( linterm==1 ) - { - rbfsetlinterm(&s, _state); - } - if( linterm==2 ) - { - rbfsetconstterm(&s, _state); - } - if( linterm==3 ) - { - rbfsetzeroterm(&s, _state); - } - rbfsetpoints(&s, &gp, n, _state); - rbfbuildmodel(&s, &rep, _state); - if( ny==1 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - x.ptr.p_double[j] = gp.ptr.pp_double[i][j]; - } - if( nx==2 ) - { - mody1.ptr.pp_double[i][0] = rbfcalc2(&s, x.ptr.p_double[0], x.ptr.p_double[1], _state); - } - else - { - if( nx==3 ) - { - mody1.ptr.pp_double[i][0] = rbfcalc3(&s, x.ptr.p_double[0], x.ptr.p_double[1], x.ptr.p_double[2], _state); - } - else - { - ae_assert(ae_false, "BasicMultiLayerRBFTest1D: Invalid variable NX(NX neither 2 nor 3)", _state); - } - } - } - if( testrbfunit_searcherr(&mody0, &mody1, n, ny, errtype, &b1, &delta, _state) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - if( nx==2 ) - { - rbfgridcalc2(&s, &gpgx0, n, &gpgx1, n, &gy, _state); - for(i=0; i<=n-1; i++) - { - mody1.ptr.pp_double[i][0] = gy.ptr.pp_double[i][0]; - } - } - if( testrbfunit_searcherr(&mody0, &mody1, n, ny, errtype, &b1, &delta, _state) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - x.ptr.p_double[j] = gp.ptr.pp_double[i][j]; - } - rbfcalc(&s, &x, &y, _state); - for(j=0; j<=ny-1; j++) - { - mody1.ptr.pp_double[i][j] = y.ptr.p_double[j]; - } - } - if( testrbfunit_searcherr(&mody0, &mody1, n, ny, errtype, &b1, &delta, _state) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - x.ptr.p_double[j] = gp.ptr.pp_double[i][j]; - } - rbfcalcbuf(&s, &x, &y, _state); - for(j=0; j<=ny-1; j++) - { - mody1.ptr.pp_double[i][j] = y.ptr.p_double[j]; - } - } - if( testrbfunit_searcherr(&mody0, &mody1, n, ny, errtype, &b1, &delta, _state) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - q = q/2; - nlayers = nlayers+1; - if( errtype==1&&ae_fp_less_eq(q,1/f2) ) - { - errtype = 2; - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function tests special cases: -* uninitialized RBF model will correctly return zero values -* RBF correctly handles 1 or 2 distinct points -* when we have many uniformly spaced points and one outlier, filter which - is applied to radii, makes all radii equal (RBF-QNN). -* RBF-ML with NLayers=0 gives linear model -* Hierarchical RBF with NLayers=0 gives linear model - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testrbfunit_specialtest(ae_state *_state) -{ - ae_frame _frame_block; - rbfmodel s; - rbfreport rep; - ae_int_t n; - ae_int_t nx; - ae_int_t ny; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t t; - ae_matrix xy; - ae_matrix vf; - ae_vector x; - ae_vector y; - ae_int_t termtype; - double errtol; - ae_int_t tmpnx; - ae_int_t tmpny; - ae_int_t tmpnc; - ae_matrix xwr; - ae_matrix v; - double sx; - double z; - double va; - double vb; - double vc; - double vd; - ae_int_t modelversion; - double vv; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&xy, 0, sizeof(xy)); - memset(&vf, 0, sizeof(vf)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&xwr, 0, sizeof(xwr)); - memset(&v, 0, sizeof(v)); - _rbfmodel_init(&s, _state, ae_true); - _rbfreport_init(&rep, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&vf, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xwr, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true); - - errtol = 1.0E-9; - result = ae_false; - - /* - * Create model in the default state (no parameters/points specified). - * With probability 0.5 we do one of the following: - * * test that default state of the model is a zero model (all Calc() - * functions return zero) - * * call RBFBuildModel() (without specifying anything) and test that - * all Calc() functions return zero. - * - * NOTE: because NX varies between 1 and 4, both V1 (old) and V2 RBFs - * are tested. - */ - for(nx=1; nx<=4; nx++) - { - for(ny=1; ny<=3; ny++) - { - rbfcreate(nx, ny, &s, _state); - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - rbfbuildmodel(&s, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:202"); - ae_frame_leave(_state); - return result; - } - } - ae_vector_set_length(&x, nx, _state); - ae_vector_set_length(&y, 1, _state); - for(i=0; i<=nx-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - rbfcalc(&s, &x, &y, _state); - if( y.cnt!=ny ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:213"); - ae_frame_leave(_state); - return result; - } - for(i=0; i<=ny-1; i++) - { - if( ae_fp_neq(y.ptr.p_double[i],(double)(0)) ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:219"); - ae_frame_leave(_state); - return result; - } - } - } - } - - /* - * Create default model with 1 point and different types of linear term. - * Test algorithm on such dataset. - * - * NOTE: because NX varies between 1 and 4, both V1 (old) and V2 RBFs - * are tested. - */ - for(nx=1; nx<=4; nx++) - { - for(ny=1; ny<=3; ny++) - { - rbfcreate(nx, ny, &s, _state); - for(termtype=0; termtype<=1; termtype++) - { - if( termtype==0 ) - { - rbfsetlinterm(&s, _state); - } - if( termtype==1 ) - { - rbfsetconstterm(&s, _state); - } - ae_matrix_set_length(&xy, 1, nx+ny, _state); - for(i=0; i<=nx+ny-1; i++) - { - xy.ptr.pp_double[0][i] = 2*ae_randomreal(_state)-1; - } - rbfsetpoints(&s, &xy, 1, _state); - rbfbuildmodel(&s, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:248"); - ae_frame_leave(_state); - return result; - } - - /* - * First, test that model exactly reproduces our dataset in the specified point - */ - ae_vector_set_length(&x, nx, _state); - for(i=0; i<=nx-1; i++) - { - x.ptr.p_double[i] = xy.ptr.pp_double[0][i]; - } - rbfcalc(&s, &x, &y, _state); - if( y.cnt!=ny ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:261"); - ae_frame_leave(_state); - return result; - } - for(i=0; i<=ny-1; i++) - { - if( ae_fp_greater(ae_fabs(y.ptr.p_double[i]-xy.ptr.pp_double[0][nx+i], _state),errtol) ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:267"); - ae_frame_leave(_state); - return result; - } - } - - /* - * Second, test that model is constant - */ - for(i=0; i<=nx-1; i++) - { - x.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - rbfcalc(&s, &x, &y, _state); - if( y.cnt!=ny ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:279"); - ae_frame_leave(_state); - return result; - } - for(i=0; i<=ny-1; i++) - { - if( ae_fp_greater(ae_fabs(y.ptr.p_double[i]-xy.ptr.pp_double[0][nx+i], _state),errtol) ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:285"); - ae_frame_leave(_state); - return result; - } - } - } - } - } - - /* - * Create model with 2 points and different types of linear term. - * Test algorithm on such dataset. - */ - for(nx=2; nx<=3; nx++) - { - for(ny=1; ny<=3; ny++) - { - rbfcreate(nx, ny, &s, _state); - for(termtype=0; termtype<=1; termtype++) - { - if( termtype==0 ) - { - rbfsetlinterm(&s, _state); - } - if( termtype==1 ) - { - rbfsetconstterm(&s, _state); - } - if( termtype==2 ) - { - rbfsetzeroterm(&s, _state); - } - ae_matrix_set_length(&xy, 2, nx+ny, _state); - for(i=0; i<=nx+ny-1; i++) - { - xy.ptr.pp_double[0][i] = 2*ae_randomreal(_state)-1; - } - for(i=0; i<=nx+ny-1; i++) - { - xy.ptr.pp_double[1][i] = xy.ptr.pp_double[0][i]+1.0; - } - rbfsetpoints(&s, &xy, 2, _state); - rbfbuildmodel(&s, &rep, _state); - if( rep.terminationtype<=0 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(j=0; j<=1; j++) - { - ae_vector_set_length(&x, nx, _state); - for(i=0; i<=nx-1; i++) - { - x.ptr.p_double[i] = xy.ptr.pp_double[j][i]; - } - rbfcalc(&s, &x, &y, _state); - if( y.cnt!=ny ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=ny-1; i++) - { - if( ae_fp_greater(ae_fabs(y.ptr.p_double[i]-xy.ptr.pp_double[j][nx+i], _state),errtol) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - } - } - - /* - * Generate a set of points (xi,yi) = (SX*i,0), and one - * outlier (x_far,y_far)=(-1000*SX,0). - * - * Radii filtering should place a bound on the radius of outlier. - */ - for(nx=2; nx<=3; nx++) - { - for(ny=1; ny<=3; ny++) - { - sx = ae_exp(-5+10*ae_randomreal(_state), _state); - rbfcreate(nx, ny, &s, _state); - ae_matrix_set_length(&xy, 20, nx+ny, _state); - for(i=0; i<=xy.rows-1; i++) - { - xy.ptr.pp_double[i][0] = sx*i; - for(j=1; j<=nx-1; j++) - { - xy.ptr.pp_double[i][j] = (double)(0); - } - for(j=0; j<=ny-1; j++) - { - xy.ptr.pp_double[i][nx+j] = ae_randomreal(_state); - } - } - xy.ptr.pp_double[xy.rows-1][0] = -1000*sx; - rbfsetpoints(&s, &xy, xy.rows, _state); - - /* - * Try random Z from [1,5] - */ - z = 1+ae_randomreal(_state)*4; - rbfsetalgoqnn(&s, 1.0, z, _state); - rbfbuildmodel(&s, &rep, _state); - if( rep.terminationtype<=0 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - rbfunpack(&s, &tmpnx, &tmpny, &xwr, &tmpnc, &v, &modelversion, _state); - if( ((((tmpnx!=nx||tmpny!=ny)||tmpnc!=xy.rows)||xwr.cols!=nx+ny+1)||xwr.rows!=tmpnc)||modelversion!=1 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=tmpnc-2; i++) - { - if( ae_fp_greater(ae_fabs(xwr.ptr.pp_double[i][nx+ny]-sx, _state),errtol) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - if( ae_fp_greater(ae_fabs(xwr.ptr.pp_double[tmpnc-1][nx+ny]-z*sx, _state),errtol) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - - /* - * RBF-ML with NLayers=0 gives us linear model. - * - * In order to perform this test, we use test function which - * is perfectly linear and see whether RBF model is able to - * reproduce such function. - */ - n = 5; - for(ny=1; ny<=3; ny++) - { - va = 2*ae_randomreal(_state)-1; - vb = 2*ae_randomreal(_state)-1; - vc = 2*ae_randomreal(_state)-1; - vd = 2*ae_randomreal(_state)-1; - - /* - * Test NX=2. - * Generate linear function using random coefficients VA/VB/VC. - * Function is K-dimensional vector-valued, each component has slightly - * different coefficients. - */ - ae_matrix_set_length(&xy, n*n, 2+ny, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - xy.ptr.pp_double[n*i+j][0] = (double)(i); - xy.ptr.pp_double[n*i+j][1] = (double)(j); - for(k=0; k<=ny-1; k++) - { - xy.ptr.pp_double[n*i+j][2+k] = (va+0.1*k)*i+(vb+0.2*k)*j+(vc+0.3*k); - } - } - } - rbfcreate(2, ny, &s, _state); - rbfsetpoints(&s, &xy, n*n, _state); - rbfsetalgomultilayer(&s, 1.0, 0, 0.01, _state); - rbfbuildmodel(&s, &rep, _state); - if( rep.terminationtype<=0 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - ae_vector_set_length(&x, 2, _state); - x.ptr.p_double[0] = (n-1)*ae_randomreal(_state); - x.ptr.p_double[1] = (n-1)*ae_randomreal(_state); - if( ny==1&&ae_fp_greater(ae_fabs(rbfcalc2(&s, x.ptr.p_double[0], x.ptr.p_double[1], _state)-(va*x.ptr.p_double[0]+vb*x.ptr.p_double[1]+vc), _state),errtol) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - rbfcalc(&s, &x, &y, _state); - for(k=0; k<=ny-1; k++) - { - if( ae_fp_greater(ae_fabs(y.ptr.p_double[k]-((va+0.1*k)*x.ptr.p_double[0]+(vb+0.2*k)*x.ptr.p_double[1]+(vc+0.3*k)), _state),errtol) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - - /* - * Test NX=3. - * Generate linear function using random coefficients VA/VB/VC/VC. - * Function is K-dimensional vector-valued, each component has slightly - * different coefficients. - */ - ae_matrix_set_length(&xy, n*n*n, 3+ny, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - for(t=0; t<=n-1; t++) - { - xy.ptr.pp_double[n*n*i+n*j+t][0] = (double)(i); - xy.ptr.pp_double[n*n*i+n*j+t][1] = (double)(j); - xy.ptr.pp_double[n*n*i+n*j+t][2] = (double)(t); - for(k=0; k<=ny-1; k++) - { - xy.ptr.pp_double[n*n*i+n*j+t][3+k] = (va+0.1*k)*i+(vb+0.2*k)*j+(vc+0.3*k)*t+(vd+0.4*k); - } - } - } - } - rbfcreate(3, ny, &s, _state); - rbfsetpoints(&s, &xy, n*n*n, _state); - rbfsetalgomultilayer(&s, 1.0, 0, 0.01, _state); - rbfbuildmodel(&s, &rep, _state); - if( rep.terminationtype<=0 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - ae_vector_set_length(&x, 3, _state); - x.ptr.p_double[0] = (n-1)*ae_randomreal(_state); - x.ptr.p_double[1] = (n-1)*ae_randomreal(_state); - x.ptr.p_double[2] = (n-1)*ae_randomreal(_state); - if( ny==1&&ae_fp_greater(ae_fabs(rbfcalc3(&s, x.ptr.p_double[0], x.ptr.p_double[1], x.ptr.p_double[2], _state)-(va*x.ptr.p_double[0]+vb*x.ptr.p_double[1]+vc*x.ptr.p_double[2]+vd), _state),errtol) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - rbfcalc(&s, &x, &y, _state); - for(k=0; k<=ny-1; k++) - { - if( ae_fp_greater(ae_fabs(y.ptr.p_double[k]-((va+0.1*k)*x.ptr.p_double[0]+(vb+0.2*k)*x.ptr.p_double[1]+(vc+0.3*k)*x.ptr.p_double[2]+(vd+0.4*k)), _state),errtol) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - - /* - * HierarchicalRBF with NLayers=0 gives us linear model. - * - * In order to perform this test, we use test function which - * is perfectly linear and see whether RBF model is able to - * reproduce such function. - */ - n = 15; - for(nx=1; nx<=5; nx++) - { - for(ny=1; ny<=3; ny++) - { - ae_matrix_set_length(&vf, ny, nx+1, _state); - for(i=0; i<=ny-1; i++) - { - for(j=0; j<=nx; j++) - { - vf.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - ae_matrix_set_length(&xy, n, nx+ny, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - xy.ptr.pp_double[i][j] = ae_randomreal(_state); - } - for(j=0; j<=ny-1; j++) - { - xy.ptr.pp_double[i][nx+j] = vf.ptr.pp_double[j][nx]; - for(k=0; k<=nx-1; k++) - { - xy.ptr.pp_double[i][nx+j] = xy.ptr.pp_double[i][nx+j]+vf.ptr.pp_double[j][k]*xy.ptr.pp_double[i][k]; - } - } - } - rbfcreate(nx, ny, &s, _state); - rbfsetpoints(&s, &xy, n, _state); - rbfsetalgohierarchical(&s, 1.0, 0, 0.0, _state); - rbfbuildmodel(&s, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:525"); - ae_frame_leave(_state); - return result; - } - ae_vector_set_length(&x, nx, _state); - for(i=0; i<=nx-1; i++) - { - x.ptr.p_double[i] = ae_randomreal(_state); - } - rbfcalc(&s, &x, &y, _state); - for(k=0; k<=ny-1; k++) - { - vv = vf.ptr.pp_double[k][nx]; - for(j=0; j<=nx-1; j++) - { - vv = vv+vf.ptr.pp_double[k][j]*x.ptr.p_double[j]; - } - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vv-y.ptr.p_double[k], _state),errtol), __FILE__, __LINE__, "testrbfunit.ap:537"); - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Function for testing basic functionality of RBF module on regular grids. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testrbfunit_basicrbftest(ae_state *_state) -{ - ae_frame _frame_block; - rbfmodel s; - rbfreport rep; - rbfcalcbuffer calcbuf; - ae_int_t nx; - ae_int_t ny; - ae_int_t k0; - ae_int_t k1; - ae_int_t k2; - ae_int_t linterm; - ae_int_t np; - double sx; - double sy; - double zx; - double px; - double zy; - double py; - double q; - double z; - ae_vector point; - ae_matrix gp; - ae_vector x; - ae_vector y; - ae_matrix gy; - ae_int_t unx; - ae_int_t uny; - ae_matrix xwr; - ae_matrix v; - ae_vector gpgx0; - ae_vector gpgx1; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t l; - ae_int_t fidx; - double eps; - ae_int_t modelversion; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&calcbuf, 0, sizeof(calcbuf)); - memset(&point, 0, sizeof(point)); - memset(&gp, 0, sizeof(gp)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&gy, 0, sizeof(gy)); - memset(&xwr, 0, sizeof(xwr)); - memset(&v, 0, sizeof(v)); - memset(&gpgx0, 0, sizeof(gpgx0)); - memset(&gpgx1, 0, sizeof(gpgx1)); - _rbfmodel_init(&s, _state, ae_true); - _rbfreport_init(&rep, _state, ae_true); - _rbfcalcbuffer_init(&calcbuf, _state, ae_true); - ae_vector_init(&point, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&gp, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&gy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xwr, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&gpgx0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&gpgx1, 0, DT_REAL, _state, ae_true); - - zx = (double)(10); - px = (double)(15); - zy = (double)(10); - py = (double)(15); - eps = 1.0E-6; - - /* - * Problem types: - * * 2 and 3-dimensional problems - * * problems with zero, constant, linear terms - * * different scalings of X and Y values (1.0, 1E-15, 1E+15) - * * regular grids different grid sizes (from 2 to 4 points for each dimension) - * - * We check that: - * * RBF model correctly reproduces function value (testes with different Calc() functions) - * * unpacked model containt correct radii - * * linear term has correct form - */ - for(nx=2; nx<=3; nx++) - { - for(ny=1; ny<=3; ny++) - { - for(linterm=1; linterm<=3; linterm++) - { - - /* - * prepare test problem - */ - sx = ae_pow(zx, px*(ae_randominteger(3, _state)-1), _state); - sy = ae_pow(zy, py*(ae_randominteger(3, _state)-1), _state); - ae_vector_set_length(&x, nx, _state); - ae_vector_set_length(&y, ny, _state); - ae_vector_set_length(&point, nx, _state); - rbfcreate(nx, ny, &s, _state); - rbfsetcond(&s, testrbfunit_heps, testrbfunit_heps, testrbfunit_mxits, _state); - q = 0.25+ae_randomreal(_state); - z = 4.5+ae_randomreal(_state); - rbfsetalgoqnn(&s, q, z, _state); - if( linterm==1 ) - { - rbfsetlinterm(&s, _state); - } - if( linterm==2 ) - { - rbfsetconstterm(&s, _state); - } - if( linterm==3 ) - { - rbfsetzeroterm(&s, _state); - } - - /* - * start points for grid - */ - for(i=0; i<=nx-1; i++) - { - point.ptr.p_double[i] = sx*(2*ae_randomreal(_state)-1); - } - - /* - * 2-dimensional test problem - */ - if( nx==2 ) - { - for(k0=2; k0<=4; k0++) - { - for(k1=2; k1<=4; k1++) - { - np = k0*k1; - ae_matrix_set_length(&gp, np, nx+ny, _state); - - /* - * create grid - */ - for(i=0; i<=k0-1; i++) - { - for(j=0; j<=k1-1; j++) - { - gp.ptr.pp_double[i*k1+j][0] = point.ptr.p_double[0]+sx*i; - gp.ptr.pp_double[i*k1+j][1] = point.ptr.p_double[1]+sx*j; - for(k=0; k<=ny-1; k++) - { - gp.ptr.pp_double[i*k1+j][nx+k] = sy*(2*ae_randomreal(_state)-1); - } - } - } - rbfsetpoints(&s, &gp, np, _state); - rbfbuildmodel(&s, &rep, _state); - rbfcreatecalcbuffer(&s, &calcbuf, _state); - if( ny==1 ) - { - ae_vector_set_length(&gpgx0, k0, _state); - ae_vector_set_length(&gpgx1, k1, _state); - for(i=0; i<=k0-1; i++) - { - gpgx0.ptr.p_double[i] = point.ptr.p_double[0]+sx*i; - } - for(i=0; i<=k1-1; i++) - { - gpgx1.ptr.p_double[i] = point.ptr.p_double[1]+sx*i; - } - rbfgridcalc2(&s, &gpgx0, k0, &gpgx1, k1, &gy, _state); - for(i=0; i<=k0-1; i++) - { - for(j=0; j<=k1-1; j++) - { - if( ae_fp_greater(ae_fabs(gy.ptr.pp_double[i][j]-gp.ptr.pp_double[i*k1+j][nx], _state),sy*eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - for(i=0; i<=np-1; i++) - { - - /* - * For each row we randomly choose a function to test - * and call it. We do not call multiple functions per - * row because carry-over effects may mask errors in - * some function (say, it is possible that function - * simply returns results from previous call of some - * other function which were stored in the RBF model; - * in this case, previous call with same parameters - * may hide deficiencies in the function). - */ - x.ptr.p_double[0] = gp.ptr.pp_double[i][0]; - x.ptr.p_double[1] = gp.ptr.pp_double[i][1]; - fidx = ae_randominteger(4, _state); - if( fidx==0&&ny==1 ) - { - y.ptr.p_double[0] = rbfcalc2(&s, x.ptr.p_double[0], x.ptr.p_double[1], _state); - if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx]-y.ptr.p_double[0], _state),sy*eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - if( fidx==1 ) - { - rbfcalc(&s, &x, &y, _state); - for(j=0; j<=ny-1; j++) - { - if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - if( fidx==2 ) - { - rbfcalcbuf(&s, &x, &y, _state); - for(j=0; j<=ny-1; j++) - { - if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - if( fidx==3 ) - { - rbftscalcbuf(&s, &calcbuf, &x, &y, _state); - for(j=0; j<=ny-1; j++) - { - if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - - /* - * test for RBFUnpack - */ - rbfunpack(&s, &unx, &uny, &xwr, &np, &v, &modelversion, _state); - if( (((((nx!=unx||ny!=uny)||xwr.rows!=np)||xwr.cols!=nx+ny+1)||v.rows!=ny)||v.cols!=nx+1)||modelversion!=1 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:735"); - ae_frame_leave(_state); - return result; - } - for(i=0; i<=np-1; i++) - { - if( ae_fp_greater(ae_fabs(xwr.ptr.pp_double[i][unx+uny]-q*sx, _state),sx*eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - if( linterm==2 ) - { - for(i=0; i<=unx-1; i++) - { - for(j=0; j<=uny-1; j++) - { - if( ae_fp_neq(v.ptr.pp_double[j][i],(double)(0)) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - if( linterm==3 ) - { - for(i=0; i<=unx; i++) - { - for(j=0; j<=uny-1; j++) - { - if( ae_fp_neq(v.ptr.pp_double[j][i],(double)(0)) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - } - } - } - - /* - * 3-dimensional test problems - */ - if( nx==3 ) - { - for(k0=2; k0<=4; k0++) - { - for(k1=2; k1<=4; k1++) - { - for(k2=2; k2<=4; k2++) - { - np = k0*k1*k2; - ae_matrix_set_length(&gp, np, nx+ny, _state); - - /* - * create grid - */ - for(i=0; i<=k0-1; i++) - { - for(j=0; j<=k1-1; j++) - { - for(k=0; k<=k2-1; k++) - { - gp.ptr.pp_double[(i*k1+j)*k2+k][0] = point.ptr.p_double[0]+sx*i; - gp.ptr.pp_double[(i*k1+j)*k2+k][1] = point.ptr.p_double[1]+sx*j; - gp.ptr.pp_double[(i*k1+j)*k2+k][2] = point.ptr.p_double[2]+sx*k; - for(l=0; l<=ny-1; l++) - { - gp.ptr.pp_double[(i*k1+j)*k2+k][nx+l] = sy*(2*ae_randomreal(_state)-1); - } - } - } - } - rbfsetpoints(&s, &gp, np, _state); - rbfbuildmodel(&s, &rep, _state); - rbfcreatecalcbuffer(&s, &calcbuf, _state); - for(i=0; i<=np-1; i++) - { - - /* - * For each row we randomly choose a function to test - * and call it. We do not call multiple functions per - * row because carry-over effects may mask errors in - * some function (say, it is possible that function - * simply returns results from previous call of some - * other function which were stored in the RBF model; - * in this case, previous call with same parameters - * may hide deficiencies in the function). - */ - x.ptr.p_double[0] = gp.ptr.pp_double[i][0]; - x.ptr.p_double[1] = gp.ptr.pp_double[i][1]; - x.ptr.p_double[2] = gp.ptr.pp_double[i][2]; - fidx = ae_randominteger(4, _state); - if( fidx==0&&ny==1 ) - { - y.ptr.p_double[0] = rbfcalc3(&s, x.ptr.p_double[0], x.ptr.p_double[1], x.ptr.p_double[2], _state); - if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx]-y.ptr.p_double[0], _state),sy*eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - if( fidx==1 ) - { - rbfcalc(&s, &x, &y, _state); - for(j=0; j<=ny-1; j++) - { - if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - if( fidx==2 ) - { - rbfcalcbuf(&s, &x, &y, _state); - for(j=0; j<=ny-1; j++) - { - if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - if( fidx==3 ) - { - rbftscalcbuf(&s, &calcbuf, &x, &y, _state); - for(j=0; j<=ny-1; j++) - { - if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - - /* - * test for RBFUnpack - */ - rbfunpack(&s, &unx, &uny, &xwr, &np, &v, &modelversion, _state); - if( (((((nx!=unx||ny!=uny)||xwr.rows!=np)||xwr.cols!=nx+ny+1)||v.rows!=ny)||v.cols!=nx+1)||modelversion!=1 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:852"); - ae_frame_leave(_state); - return result; - } - for(i=0; i<=np-1; i++) - { - if( ae_fp_greater(ae_fabs(xwr.ptr.pp_double[i][unx+uny]-q*sx, _state),sx*eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - if( linterm==2 ) - { - for(i=0; i<=unx-1; i++) - { - for(j=0; j<=uny-1; j++) - { - if( ae_fp_neq(v.ptr.pp_double[j][i],(double)(0)) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - if( linterm==3 ) - { - for(i=0; i<=unx; i++) - { - for(j=0; j<=uny-1; j++) - { - if( ae_fp_neq(v.ptr.pp_double[j][i],(double)(0)) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - } - } - } - } - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Function for testing RBF module on irregular grids. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testrbfunit_irregularrbftest(ae_state *_state) -{ - ae_frame _frame_block; - rbfmodel s; - rbfreport rep; - ae_int_t nx; - ae_int_t ny; - ae_int_t k0; - ae_int_t k1; - ae_int_t k2; - ae_int_t linterm; - ae_int_t np; - double sx; - double sy; - double zx; - double px; - double zy; - double py; - double q; - double z; - ae_vector point; - ae_matrix gp; - ae_vector x; - ae_vector y; - ae_matrix gy; - double noiselevel; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t l; - double eps; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&point, 0, sizeof(point)); - memset(&gp, 0, sizeof(gp)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&gy, 0, sizeof(gy)); - _rbfmodel_init(&s, _state, ae_true); - _rbfreport_init(&rep, _state, ae_true); - ae_vector_init(&point, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&gp, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&gy, 0, 0, DT_REAL, _state, ae_true); - - zx = (double)(10); - px = (double)(15); - zy = (double)(10); - py = (double)(15); - noiselevel = 0.1; - eps = 1.0E-6; - - /* - * Problem types: - * * 2 and 3-dimensional problems - * * problems with zero, constant, linear terms - * * different scalings of X and Y values (1.0, 1E-15, 1E+15) - * * noisy grids, which are just regular grids with different grid sizes - * (from 2 to 4 points for each dimension) and moderate amount of random - * noise added to all node positions. - * - * We check that: - * * RBF model correctly reproduces function value (testes with different Calc() functions) - */ - for(nx=2; nx<=3; nx++) - { - for(ny=1; ny<=3; ny++) - { - for(linterm=1; linterm<=3; linterm++) - { - - /* - * prepare test problem - */ - sx = ae_pow(zx, px*(ae_randominteger(3, _state)-1), _state); - sy = ae_pow(zy, py*(ae_randominteger(3, _state)-1), _state); - ae_vector_set_length(&x, nx, _state); - ae_vector_set_length(&y, ny, _state); - ae_vector_set_length(&point, nx, _state); - rbfcreate(nx, ny, &s, _state); - rbfsetcond(&s, testrbfunit_heps, testrbfunit_heps, testrbfunit_mxits, _state); - q = 0.25+ae_randomreal(_state); - z = 4.5+ae_randomreal(_state); - rbfsetalgoqnn(&s, q, z, _state); - if( linterm==1 ) - { - rbfsetlinterm(&s, _state); - } - if( linterm==2 ) - { - rbfsetconstterm(&s, _state); - } - if( linterm==3 ) - { - rbfsetzeroterm(&s, _state); - } - - /* - * start points for grid - */ - for(i=0; i<=nx-1; i++) - { - point.ptr.p_double[i] = sx*(2*ae_randomreal(_state)-1); - } - - /* - * 2-dimensional test problems - */ - if( nx==2 ) - { - for(k0=2; k0<=4; k0++) - { - for(k1=2; k1<=4; k1++) - { - np = k0*k1; - ae_matrix_set_length(&gp, np, nx+ny, _state); - - /* - * create grid - */ - for(i=0; i<=k0-1; i++) - { - for(j=0; j<=k1-1; j++) - { - gp.ptr.pp_double[i*k1+j][0] = point.ptr.p_double[0]+sx*i+noiselevel*sx*(2*ae_randomreal(_state)-1); - gp.ptr.pp_double[i*k1+j][1] = point.ptr.p_double[1]+sx*j+noiselevel*sx*(2*ae_randomreal(_state)-1); - for(k=0; k<=ny-1; k++) - { - gp.ptr.pp_double[i*k1+j][nx+k] = sy*(2*ae_randomreal(_state)-1); - } - } - } - rbfsetpoints(&s, &gp, np, _state); - rbfbuildmodel(&s, &rep, _state); - for(i=0; i<=np-1; i++) - { - x.ptr.p_double[0] = gp.ptr.pp_double[i][0]; - x.ptr.p_double[1] = gp.ptr.pp_double[i][1]; - if( ny==1 ) - { - y.ptr.p_double[0] = rbfcalc2(&s, x.ptr.p_double[0], x.ptr.p_double[1], _state); - if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx]-y.ptr.p_double[0], _state),sy*eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - rbfcalc(&s, &x, &y, _state); - for(j=0; j<=ny-1; j++) - { - if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - rbfcalcbuf(&s, &x, &y, _state); - for(j=0; j<=ny-1; j++) - { - if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - } - } - - /* - * 2-dimensional test problems - */ - if( nx==3 ) - { - for(k0=2; k0<=4; k0++) - { - for(k1=2; k1<=4; k1++) - { - for(k2=2; k2<=4; k2++) - { - np = k0*k1*k2; - ae_matrix_set_length(&gp, np, nx+ny, _state); - - /* - * create grid - */ - for(i=0; i<=k0-1; i++) - { - for(j=0; j<=k1-1; j++) - { - for(k=0; k<=k2-1; k++) - { - gp.ptr.pp_double[(i*k1+j)*k2+k][0] = point.ptr.p_double[0]+sx*i+noiselevel*sx*(2*ae_randomreal(_state)-1); - gp.ptr.pp_double[(i*k1+j)*k2+k][1] = point.ptr.p_double[1]+sx*j+noiselevel*sx*(2*ae_randomreal(_state)-1); - gp.ptr.pp_double[(i*k1+j)*k2+k][2] = point.ptr.p_double[2]+sx*k+noiselevel*sx*(2*ae_randomreal(_state)-1); - for(l=0; l<=ny-1; l++) - { - gp.ptr.pp_double[(i*k1+j)*k2+k][nx+l] = sy*(2*ae_randomreal(_state)-1); - } - } - } - } - rbfsetpoints(&s, &gp, np, _state); - rbfbuildmodel(&s, &rep, _state); - for(i=0; i<=np-1; i++) - { - x.ptr.p_double[0] = gp.ptr.pp_double[i][0]; - x.ptr.p_double[1] = gp.ptr.pp_double[i][1]; - x.ptr.p_double[2] = gp.ptr.pp_double[i][2]; - if( ny==1 ) - { - y.ptr.p_double[0] = rbfcalc3(&s, x.ptr.p_double[0], x.ptr.p_double[1], x.ptr.p_double[2], _state); - if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx]-y.ptr.p_double[0], _state),sy*eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - rbfcalc(&s, &x, &y, _state); - for(j=0; j<=ny-1; j++) - { - if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - rbfcalcbuf(&s, &x, &y, _state); - for(j=0; j<=ny-1; j++) - { - if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - } - } - } - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -The test does check, that algorithm can build linear model for the data -sets, when Y depends on X linearly. - - -- ALGLIB -- - Copyright 13.12.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testrbfunit_linearitymodelrbftest(ae_state *_state) -{ - ae_frame _frame_block; - rbfmodel s; - rbfreport rep; - ae_int_t nx; - ae_int_t ny; - ae_int_t k0; - ae_int_t k1; - ae_int_t k2; - ae_int_t linterm; - ae_int_t np; - double sx; - double sy; - double zx; - double px; - double zy; - double py; - double q; - double z; - ae_vector point; - ae_vector a; - ae_matrix gp; - ae_vector x; - ae_vector y; - ae_int_t unx; - ae_int_t uny; - ae_matrix xwr; - ae_matrix v; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t l; - ae_int_t modelversion; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&point, 0, sizeof(point)); - memset(&a, 0, sizeof(a)); - memset(&gp, 0, sizeof(gp)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&xwr, 0, sizeof(xwr)); - memset(&v, 0, sizeof(v)); - _rbfmodel_init(&s, _state, ae_true); - _rbfreport_init(&rep, _state, ae_true); - ae_vector_init(&point, 0, DT_REAL, _state, ae_true); - ae_vector_init(&a, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&gp, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xwr, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true); - - zx = (double)(10); - px = (double)(15); - zy = (double)(10); - py = (double)(15); - ny = 1; - for(nx=2; nx<=3; nx++) - { - for(linterm=1; linterm<=3; linterm++) - { - - /* - * prepare test problem - */ - sx = ae_pow(zx, px*(ae_randominteger(3, _state)-1), _state); - sy = ae_pow(zy, py*(ae_randominteger(3, _state)-1), _state); - ae_vector_set_length(&x, nx, _state); - ae_vector_set_length(&y, ny, _state); - ae_vector_set_length(&point, nx, _state); - rbfcreate(nx, ny, &s, _state); - q = 0.25+ae_randomreal(_state); - z = 4.5+ae_randomreal(_state); - rbfsetalgoqnn(&s, q, z, _state); - ae_vector_set_length(&a, nx+1, _state); - if( linterm==1 ) - { - rbfsetlinterm(&s, _state); - for(i=0; i<=nx-1; i++) - { - a.ptr.p_double[i] = sy*(2*ae_randomreal(_state)-1)/sx; - } - a.ptr.p_double[nx] = sy*(2*ae_randomreal(_state)-1); - } - if( linterm==2 ) - { - rbfsetconstterm(&s, _state); - for(i=0; i<=nx-1; i++) - { - a.ptr.p_double[i] = (double)(0); - } - a.ptr.p_double[nx] = sy*(2*ae_randomreal(_state)-1); - } - if( linterm==3 ) - { - rbfsetzeroterm(&s, _state); - for(i=0; i<=nx; i++) - { - a.ptr.p_double[i] = (double)(0); - } - } - - /* - * start points for grid - */ - for(i=0; i<=nx-1; i++) - { - point.ptr.p_double[i] = sx*(2*ae_randomreal(_state)-1); - } - if( nx==2 ) - { - for(k0=2; k0<=4; k0++) - { - for(k1=2; k1<=4; k1++) - { - np = k0*k1; - ae_matrix_set_length(&gp, np, nx+ny, _state); - - /* - * create grid - */ - for(i=0; i<=k0-1; i++) - { - for(j=0; j<=k1-1; j++) - { - gp.ptr.pp_double[i*k1+j][0] = point.ptr.p_double[0]+sx*i; - gp.ptr.pp_double[i*k1+j][1] = point.ptr.p_double[1]+sx*j; - gp.ptr.pp_double[i*k1+j][nx] = a.ptr.p_double[nx]; - for(k=0; k<=nx-1; k++) - { - gp.ptr.pp_double[i*k1+j][nx] = gp.ptr.pp_double[i*k1+j][nx]+gp.ptr.pp_double[i*k1+j][k]*a.ptr.p_double[k]; - } - } - } - rbfsetpoints(&s, &gp, np, _state); - rbfbuildmodel(&s, &rep, _state); - - /* - * test for RBFUnpack - */ - rbfunpack(&s, &unx, &uny, &xwr, &np, &v, &modelversion, _state); - if( (((((nx!=unx||ny!=uny)||xwr.rows!=np)||xwr.cols!=nx+ny+1)||v.rows!=ny)||v.cols!=nx+1)||modelversion!=1 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=nx-1; i++) - { - if( ae_fp_greater(ae_fabs(v.ptr.pp_double[0][i]-a.ptr.p_double[i], _state),sy/sx*testrbfunit_tol) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - if( ae_fp_greater(ae_fabs(v.ptr.pp_double[0][nx]-a.ptr.p_double[nx], _state),sy*testrbfunit_tol) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=np-1; i++) - { - if( ae_fp_greater(ae_fabs(xwr.ptr.pp_double[i][unx], _state),sy*testrbfunit_tol) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - } - if( nx==3 ) - { - for(k0=2; k0<=4; k0++) - { - for(k1=2; k1<=4; k1++) - { - for(k2=2; k2<=4; k2++) - { - np = k0*k1*k2; - ae_matrix_set_length(&gp, np, nx+ny, _state); - - /* - * create grid - */ - for(i=0; i<=k0-1; i++) - { - for(j=0; j<=k1-1; j++) - { - for(k=0; k<=k2-1; k++) - { - gp.ptr.pp_double[(i*k1+j)*k2+k][0] = point.ptr.p_double[0]+sx*i; - gp.ptr.pp_double[(i*k1+j)*k2+k][1] = point.ptr.p_double[1]+sx*j; - gp.ptr.pp_double[(i*k1+j)*k2+k][2] = point.ptr.p_double[2]+sx*k; - gp.ptr.pp_double[(i*k1+j)*k2+k][nx] = a.ptr.p_double[nx]; - for(l=0; l<=nx-1; l++) - { - gp.ptr.pp_double[(i*k1+j)*k2+k][nx] = gp.ptr.pp_double[(i*k1+j)*k2+k][nx]+gp.ptr.pp_double[(i*k1+j)*k2+k][l]*a.ptr.p_double[l]; - } - } - } - } - rbfsetpoints(&s, &gp, np, _state); - rbfbuildmodel(&s, &rep, _state); - - /* - * test for RBFUnpack - */ - rbfunpack(&s, &unx, &uny, &xwr, &np, &v, &modelversion, _state); - if( (((((nx!=unx||ny!=uny)||xwr.rows!=np)||xwr.cols!=nx+ny+1)||v.rows!=ny)||v.cols!=nx+1)||modelversion!=1 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=nx-1; i++) - { - if( ae_fp_greater(ae_fabs(v.ptr.pp_double[0][i]-a.ptr.p_double[i], _state),sy/sx*testrbfunit_tol) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - if( ae_fp_greater(ae_fabs(v.ptr.pp_double[0][nx]-a.ptr.p_double[nx], _state),sy*testrbfunit_tol) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=np-1; i++) - { - if( ae_fp_greater(ae_fabs(xwr.ptr.pp_double[i][unx], _state),sy*testrbfunit_tol) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - } - } - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function tests serialization - - -- ALGLIB -- - Copyright 02.02.2012 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testrbfunit_serializationtest(ae_state *_state) -{ - ae_frame _frame_block; - rbfmodel s; - rbfmodel s2; - rbfreport rep; - ae_int_t n; - ae_int_t nx; - ae_int_t ny; - ae_int_t k0; - ae_int_t k1; - ae_int_t k2; - ae_int_t i; - ae_int_t i0; - ae_int_t i1; - ae_int_t i2; - ae_int_t j; - ae_int_t k; - double rbase; - ae_int_t nlayers; - ae_int_t bf; - ae_int_t gridsize; - ae_matrix xy; - ae_vector testpoint; - ae_vector y0; - ae_vector y1; - ae_vector scalevec; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&s2, 0, sizeof(s2)); - memset(&rep, 0, sizeof(rep)); - memset(&xy, 0, sizeof(xy)); - memset(&testpoint, 0, sizeof(testpoint)); - memset(&y0, 0, sizeof(y0)); - memset(&y1, 0, sizeof(y1)); - memset(&scalevec, 0, sizeof(scalevec)); - _rbfmodel_init(&s, _state, ae_true); - _rbfmodel_init(&s2, _state, ae_true); - _rbfreport_init(&rep, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&testpoint, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&scalevec, 0, DT_REAL, _state, ae_true); - - result = ae_false; - - /* - * This function generates random 2 or 3 dimensional problem, - * builds RBF model (QNN is used), serializes/unserializes it, then compares - * models by calculating model value at some random point. - * - * Additionally we test that new model (one which was restored - * after serialization) has lost all model construction settings, - * i.e. if we call RBFBuildModel() on a NEW model, we will get - * empty (zero) model. - */ - for(nx=2; nx<=3; nx++) - { - for(ny=1; ny<=2; ny++) - { - - /* - * prepare test problem - */ - rbfcreate(nx, ny, &s, _state); - rbfsetalgoqnn(&s, 1.0, 5.0, _state); - rbfsetlinterm(&s, _state); - if( nx==2 ) - { - - /* - * 2-dimensional problem - */ - k0 = 2+ae_randominteger(4, _state); - k1 = 2+ae_randominteger(4, _state); - ae_matrix_set_length(&xy, k0*k1, nx+ny, _state); - for(i0=0; i0<=k0-1; i0++) - { - for(i1=0; i1<=k1-1; i1++) - { - xy.ptr.pp_double[i0*k1+i1][0] = i0+0.1*(2*ae_randomreal(_state)-1); - xy.ptr.pp_double[i0*k1+i1][1] = i1+0.1*(2*ae_randomreal(_state)-1); - for(j=0; j<=ny-1; j++) - { - xy.ptr.pp_double[i0*k1+i1][nx+j] = 2*ae_randomreal(_state)-1; - } - } - } - ae_vector_set_length(&testpoint, nx, _state); - testpoint.ptr.p_double[0] = ae_randomreal(_state)*(k0-1); - testpoint.ptr.p_double[1] = ae_randomreal(_state)*(k1-1); - } - else - { - - /* - * 3-dimensional problem - */ - k0 = 2+ae_randominteger(4, _state); - k1 = 2+ae_randominteger(4, _state); - k2 = 2+ae_randominteger(4, _state); - ae_matrix_set_length(&xy, k0*k1*k2, nx+ny, _state); - for(i0=0; i0<=k0-1; i0++) - { - for(i1=0; i1<=k1-1; i1++) - { - for(i2=0; i2<=k2-1; i2++) - { - xy.ptr.pp_double[i0*k1*k2+i1*k2+i2][0] = i0+0.1*(2*ae_randomreal(_state)-1); - xy.ptr.pp_double[i0*k1*k2+i1*k2+i2][1] = i1+0.1*(2*ae_randomreal(_state)-1); - xy.ptr.pp_double[i0*k1*k2+i1*k2+i2][2] = i2+0.1*(2*ae_randomreal(_state)-1); - for(j=0; j<=ny-1; j++) - { - xy.ptr.pp_double[i0*k1*k2+i1*k2+i2][nx+j] = 2*ae_randomreal(_state)-1; - } - } - } - } - ae_vector_set_length(&testpoint, nx, _state); - testpoint.ptr.p_double[0] = ae_randomreal(_state)*(k0-1); - testpoint.ptr.p_double[1] = ae_randomreal(_state)*(k1-1); - testpoint.ptr.p_double[2] = ae_randomreal(_state)*(k2-1); - } - rbfsetpoints(&s, &xy, xy.rows, _state); - - /* - * Build model, serialize, compare - */ - rbfbuildmodel(&s, &rep, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - rbfalloc(&_local_serializer, &s, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - rbfserialize(&_local_serializer, &s, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - rbfunserialize(&_local_serializer, &s2, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - rbfcalc(&s, &testpoint, &y0, _state); - rbfcalc(&s2, &testpoint, &y1, _state); - if( y0.cnt!=ny||y1.cnt!=ny ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(j=0; j<=ny-1; j++) - { - if( ae_fp_neq(y0.ptr.p_double[j],y1.ptr.p_double[j]) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - - /* - * Check that calling RBFBuildModel() on S2 (new model) - * will result in construction of zero model, i.e. test - * that serialization restores model, but not dataset - * which was used to build model. - */ - rbfbuildmodel(&s2, &rep, _state); - rbfcalc(&s2, &testpoint, &y1, _state); - if( y1.cnt!=ny ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(j=0; j<=ny-1; j++) - { - if( ae_fp_neq(y1.ptr.p_double[j],(double)(0)) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - - /* - * This function generates random 2 or 3 dimensional problem, - * builds model using RBF-ML algo, serializes/unserializes it, - * then compares models by calculating model value at some - * random point. - * - * Additionally we test that new model (one which was restored - * after serialization) has lost all model construction settings, - * i.e. if we call RBFBuildModel() on a NEW model, we will get - * empty (zero) model. - */ - for(nx=2; nx<=3; nx++) - { - for(ny=1; ny<=2; ny++) - { - - /* - * prepare test problem - */ - rbfcreate(nx, ny, &s, _state); - rbfsetalgomultilayer(&s, 5.0, 5, 1.0E-3, _state); - rbfsetlinterm(&s, _state); - if( nx==2 ) - { - - /* - * 2-dimensional problem - */ - k0 = 2+ae_randominteger(4, _state); - k1 = 2+ae_randominteger(4, _state); - ae_matrix_set_length(&xy, k0*k1, nx+ny, _state); - for(i0=0; i0<=k0-1; i0++) - { - for(i1=0; i1<=k1-1; i1++) - { - xy.ptr.pp_double[i0*k1+i1][0] = i0+0.1*(2*ae_randomreal(_state)-1); - xy.ptr.pp_double[i0*k1+i1][1] = i1+0.1*(2*ae_randomreal(_state)-1); - for(j=0; j<=ny-1; j++) - { - xy.ptr.pp_double[i0*k1+i1][nx+j] = 2*ae_randomreal(_state)-1; - } - } - } - ae_vector_set_length(&testpoint, nx, _state); - testpoint.ptr.p_double[0] = ae_randomreal(_state)*(k0-1); - testpoint.ptr.p_double[1] = ae_randomreal(_state)*(k1-1); - } - else - { - - /* - * 3-dimensional problem - */ - k0 = 2+ae_randominteger(4, _state); - k1 = 2+ae_randominteger(4, _state); - k2 = 2+ae_randominteger(4, _state); - ae_matrix_set_length(&xy, k0*k1*k2, nx+ny, _state); - for(i0=0; i0<=k0-1; i0++) - { - for(i1=0; i1<=k1-1; i1++) - { - for(i2=0; i2<=k2-1; i2++) - { - xy.ptr.pp_double[i0*k1*k2+i1*k2+i2][0] = i0+0.1*(2*ae_randomreal(_state)-1); - xy.ptr.pp_double[i0*k1*k2+i1*k2+i2][1] = i1+0.1*(2*ae_randomreal(_state)-1); - xy.ptr.pp_double[i0*k1*k2+i1*k2+i2][2] = i2+0.1*(2*ae_randomreal(_state)-1); - for(j=0; j<=ny-1; j++) - { - xy.ptr.pp_double[i0*k1*k2+i1*k2+i2][nx+j] = 2*ae_randomreal(_state)-1; - } - } - } - } - ae_vector_set_length(&testpoint, nx, _state); - testpoint.ptr.p_double[0] = ae_randomreal(_state)*(k0-1); - testpoint.ptr.p_double[1] = ae_randomreal(_state)*(k1-1); - testpoint.ptr.p_double[2] = ae_randomreal(_state)*(k2-1); - } - rbfsetpoints(&s, &xy, xy.rows, _state); - - /* - * Build model, serialize, compare - */ - rbfbuildmodel(&s, &rep, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - rbfalloc(&_local_serializer, &s, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - rbfserialize(&_local_serializer, &s, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - rbfunserialize(&_local_serializer, &s2, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - rbfcalc(&s, &testpoint, &y0, _state); - rbfcalc(&s2, &testpoint, &y1, _state); - if( y0.cnt!=ny||y1.cnt!=ny ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(j=0; j<=ny-1; j++) - { - if( ae_fp_neq(y0.ptr.p_double[j],y1.ptr.p_double[j]) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - - /* - * Check that calling RBFBuildModel() on S2 (new model) - * will result in construction of zero model, i.e. test - * that serialization restores model, but not dataset - * which was used to build model. - */ - rbfbuildmodel(&s2, &rep, _state); - rbfcalc(&s2, &testpoint, &y1, _state); - if( y1.cnt!=ny ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(j=0; j<=ny-1; j++) - { - if( ae_fp_neq(y1.ptr.p_double[j],(double)(0)) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - - /* - * This function generates random 1...4-dimensional problem, - * builds model using RBF-H algo, serializes/unserializes it, - * then compares models by calculating model value at some - * random point. - * - * NOTE: we choose at random whether to use default scaling - - * or user-supplied one. - * - * Additionally we test that new model (one which was restored - * after serialization) has lost all model construction settings, - * i.e. if we call RBFBuildModel() on a NEW model, we will get - * empty (zero) model. - */ - for(nx=1; nx<=4; nx++) - { - for(ny=1; ny<=2; ny++) - { - - /* - * problem setup - */ - n = 150; - rbase = 0.33; - nlayers = 5; - gridsize = ae_round(ae_pow((double)(n), (double)1/(double)nx, _state), _state)+1; - bf = ae_randominteger(2, _state); - n = ae_round(ae_pow((double)(gridsize), (double)(nx), _state), _state); - ae_matrix_set_length(&xy, n, nx+ny, _state); - ae_assert(gridsize>1, "Assertion failed", _state); - ae_assert(ae_fp_eq((double)(n),ae_pow((double)(gridsize), (double)(nx), _state)), "Assertion failed", _state); - for(i=0; i<=n-1; i++) - { - k = i; - for(j=0; j<=nx-1; j++) - { - xy.ptr.pp_double[i][j] = (double)(k%gridsize)/(double)(gridsize-1); - k = k/gridsize; - } - for(j=0; j<=ny-1; j++) - { - xy.ptr.pp_double[i][nx+j] = ae_randomreal(_state)-0.5; - } - } - ae_vector_set_length(&testpoint, nx, _state); - for(j=0; j<=nx-1; j++) - { - testpoint.ptr.p_double[j] = ae_randomreal(_state); - } - ae_vector_set_length(&scalevec, nx, _state); - for(j=0; j<=nx-1; j++) - { - scalevec.ptr.p_double[j] = ae_pow((double)(2), 2*ae_randomreal(_state)-1, _state); - } - - /* - * prepare test problem - */ - rbfcreate(nx, ny, &s, _state); - rbfsetv2bf(&s, bf, _state); - rbfsetalgohierarchical(&s, rbase, nlayers, 0.0, _state); - rbfsetlinterm(&s, _state); - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - rbfsetpoints(&s, &xy, xy.rows, _state); - } - else - { - rbfsetpointsandscales(&s, &xy, xy.rows, &scalevec, _state); - } - - /* - * Build model, serialize, compare - */ - rbfbuildmodel(&s, &rep, _state); - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - rbfalloc(&_local_serializer, &s, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - rbfserialize(&_local_serializer, &s, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - rbfunserialize(&_local_serializer, &s2, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - rbfcalc(&s, &testpoint, &y0, _state); - rbfcalc(&s2, &testpoint, &y1, _state); - if( y0.cnt!=ny||y1.cnt!=ny ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(j=0; j<=ny-1; j++) - { - if( ae_fp_neq(y0.ptr.p_double[j],y1.ptr.p_double[j]) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - - /* - * Check that calling RBFBuildModel() on S2 (new model) - * will result in construction of zero model, i.e. test - * that serialization restores model, but not dataset - * which was used to build model. - */ - rbfbuildmodel(&s2, &rep, _state); - rbfcalc(&s2, &testpoint, &y1, _state); - if( y1.cnt!=ny ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(j=0; j<=ny-1; j++) - { - if( ae_fp_neq(y1.ptr.p_double[j],(double)(0)) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - ae_frame_leave(_state); - return result; -} - - -static ae_bool testrbfunit_searcherr(/* Real */ ae_matrix* y0, - /* Real */ ae_matrix* y1, - ae_int_t n, - ae_int_t ny, - ae_int_t errtype, - /* Real */ ae_vector* b1, - /* Real */ ae_vector* delta, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix _y0; - ae_matrix _y1; - ae_vector _b1; - ae_vector _delta; - double oralerr; - double iralerr; - ae_vector irerr; - ae_vector orerr; - ae_int_t lb; - ae_int_t rb; - ae_int_t i; - ae_int_t j; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&_y0, 0, sizeof(_y0)); - memset(&_y1, 0, sizeof(_y1)); - memset(&_b1, 0, sizeof(_b1)); - memset(&_delta, 0, sizeof(_delta)); - memset(&irerr, 0, sizeof(irerr)); - memset(&orerr, 0, sizeof(orerr)); - ae_matrix_init_copy(&_y0, y0, _state, ae_true); - y0 = &_y0; - ae_matrix_init_copy(&_y1, y1, _state, ae_true); - y1 = &_y1; - ae_vector_init_copy(&_b1, b1, _state, ae_true); - b1 = &_b1; - ae_vector_init_copy(&_delta, delta, _state, ae_true); - delta = &_delta; - ae_vector_init(&irerr, 0, DT_REAL, _state, ae_true); - ae_vector_init(&orerr, 0, DT_REAL, _state, ae_true); - - ae_assert(n>0, "SearchErr: invalid parameter N(N<=0).", _state); - ae_assert(ny>0, "SearchErr: invalid parameter NY(NY<=0).", _state); - oralerr = 1.0E-1; - iralerr = 1.0E-2; - lb = 25; - rb = 75; - ae_vector_set_length(&orerr, ny, _state); - ae_vector_set_length(&irerr, ny, _state); - for(j=0; j<=ny-1; j++) - { - orerr.ptr.p_double[j] = (double)(0); - irerr.ptr.p_double[j] = (double)(0); - } - if( errtype==1 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=ny-1; j++) - { - if( ae_fp_less(orerr.ptr.p_double[j],ae_fabs(y0->ptr.pp_double[i][j]-y1->ptr.pp_double[i][j], _state)) ) - { - orerr.ptr.p_double[j] = ae_fabs(y0->ptr.pp_double[i][j]-y1->ptr.pp_double[i][j], _state); - } - } - } - for(i=0; i<=ny-1; i++) - { - if( ae_fp_greater(orerr.ptr.p_double[i],b1->ptr.p_double[i]+delta->ptr.p_double[i])||ae_fp_less(orerr.ptr.p_double[i],b1->ptr.p_double[i]-delta->ptr.p_double[i]) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - else - { - if( errtype==2 ) - { - for(i=0; i<=n-1; i++) - { - for(j=0; j<=ny-1; j++) - { - if( i>lb&&iptr.pp_double[i][j]-y1->ptr.pp_double[i][j], _state)) ) - { - irerr.ptr.p_double[j] = ae_fabs(y0->ptr.pp_double[i][j]-y1->ptr.pp_double[i][j], _state); - } - } - else - { - if( ae_fp_less(orerr.ptr.p_double[j],ae_fabs(y0->ptr.pp_double[i][j]-y1->ptr.pp_double[i][j], _state)) ) - { - orerr.ptr.p_double[j] = ae_fabs(y0->ptr.pp_double[i][j]-y1->ptr.pp_double[i][j], _state); - } - } - } - } - for(i=0; i<=ny-1; i++) - { - if( ae_fp_greater(orerr.ptr.p_double[i],oralerr)||ae_fp_greater(irerr.ptr.p_double[i],iralerr) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - else - { - ae_assert(ae_false, "SearchErr: invalid argument ErrType(ErrType neither 1 nor 2)", _state); - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Function for testing basic functionality of RBF module on regular grids with -multi-layer algorithm in 2-3D. - - -- ALGLIB -- - Copyright 2.03.2012 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testrbfunit_basicmultilayerrbftest(ae_state *_state) -{ - ae_frame _frame_block; - rbfmodel s; - rbfreport rep; - rbfcalcbuffer calcbuf; - ae_int_t nx; - ae_int_t ny; - ae_int_t k0; - ae_int_t k1; - ae_int_t k2; - ae_int_t linterm; - ae_int_t np; - double q; - ae_int_t layers; - double eps; - ae_int_t range; - double s1; - double s2; - double gstep; - ae_vector point; - ae_matrix gp; - ae_vector x; - ae_vector y; - ae_matrix gy; - ae_vector gpgx0; - ae_vector gpgx1; - ae_vector gpgx2; - ae_vector gcy; - ae_int_t pass; - ae_int_t passcount; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t l; - ae_int_t fidx; - double r0; - ae_int_t margin; - ae_int_t gridsize; - double threshold; - double v; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&calcbuf, 0, sizeof(calcbuf)); - memset(&point, 0, sizeof(point)); - memset(&gp, 0, sizeof(gp)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&gy, 0, sizeof(gy)); - memset(&gpgx0, 0, sizeof(gpgx0)); - memset(&gpgx1, 0, sizeof(gpgx1)); - memset(&gpgx2, 0, sizeof(gpgx2)); - memset(&gcy, 0, sizeof(gcy)); - _rbfmodel_init(&s, _state, ae_true); - _rbfreport_init(&rep, _state, ae_true); - _rbfcalcbuffer_init(&calcbuf, _state, ae_true); - ae_vector_init(&point, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&gp, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&gy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&gpgx0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&gpgx1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&gpgx2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&gcy, 0, DT_REAL, _state, ae_true); - - result = ae_false; - range = 10; - passcount = 10; - eps = 1.0E-6; - - /* - * Test that RBF model with sufficient layers will exactly reproduce - * target function. - */ - for(pass=0; pass<=passcount-1; pass++) - { - - /* - * prepare test problem - */ - k0 = 6+ae_randominteger(3, _state); - k1 = 6+ae_randominteger(3, _state); - k2 = 6+ae_randominteger(3, _state); - s1 = ae_pow((double)(range), (double)(ae_randominteger(3, _state)-1), _state); - s2 = ae_pow((double)(range), (double)(ae_randominteger(3, _state)-1), _state); - nx = ae_randominteger(2, _state)+2; - ny = ae_randominteger(2, _state)+1; - linterm = ae_randominteger(3, _state)+1; - layers = 5; - gstep = s1/6; - q = s1; - - /* - * Create RBF structure and auxiliary structures - */ - ae_vector_set_length(&x, nx, _state); - ae_vector_set_length(&y, ny, _state); - ae_vector_set_length(&point, nx, _state); - rbfcreate(nx, ny, &s, _state); - rbfsetalgomultilayer(&s, q, layers, 0.0, _state); - if( linterm==1 ) - { - rbfsetlinterm(&s, _state); - } - if( linterm==2 ) - { - rbfsetconstterm(&s, _state); - } - if( linterm==3 ) - { - rbfsetzeroterm(&s, _state); - } - for(i=0; i<=nx-1; i++) - { - point.ptr.p_double[i] = s1*(2*ae_randomreal(_state)-1); - } - - /* - * 2-dimensional test problem - */ - if( nx==2 ) - { - np = k0*k1; - ae_matrix_set_length(&gp, np, nx+ny, _state); - - /* - * create grid - */ - for(i=0; i<=k0-1; i++) - { - for(j=0; j<=k1-1; j++) - { - gp.ptr.pp_double[i*k1+j][0] = point.ptr.p_double[0]+gstep*i; - gp.ptr.pp_double[i*k1+j][1] = point.ptr.p_double[1]+gstep*j; - for(k=0; k<=ny-1; k++) - { - gp.ptr.pp_double[i*k1+j][nx+k] = s2*(2*ae_randomreal(_state)-1); - } - } - } - rbfsetpoints(&s, &gp, np, _state); - rbfbuildmodel(&s, &rep, _state); - rbfcreatecalcbuffer(&s, &calcbuf, _state); - if( ny==1 ) - { - ae_vector_set_length(&gpgx0, k0, _state); - ae_vector_set_length(&gpgx1, k1, _state); - for(i=0; i<=k0-1; i++) - { - gpgx0.ptr.p_double[i] = point.ptr.p_double[0]+gstep*i; - } - for(i=0; i<=k1-1; i++) - { - gpgx1.ptr.p_double[i] = point.ptr.p_double[1]+gstep*i; - } - rbfgridcalc2(&s, &gpgx0, k0, &gpgx1, k1, &gy, _state); - for(i=0; i<=k0-1; i++) - { - for(j=0; j<=k1-1; j++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(gy.ptr.pp_double[i][j]-gp.ptr.pp_double[i*k1+j][nx], _state),s2*eps), __FILE__, __LINE__, "testrbfunit.ap:2216"); - } - } - } - for(i=0; i<=np-1; i++) - { - - /* - * For each row we randomly choose a function to test - * and call it. We do not call multiple functions per - * row because carry-over effects may mask errors in - * some function (say, it is possible that function - * simply returns results from previous call of some - * other function which were stored in the RBF model; - * in this case, previous call with same parameters - * may hide deficiencies in the function). - */ - x.ptr.p_double[0] = gp.ptr.pp_double[i][0]; - x.ptr.p_double[1] = gp.ptr.pp_double[i][1]; - fidx = ae_randominteger(4, _state); - if( fidx==0&&ny!=1 ) - { - continue; - } - if( fidx==0 ) - { - y.ptr.p_double[0] = rbfcalc2(&s, x.ptr.p_double[0], x.ptr.p_double[1], _state); - } - if( fidx==1 ) - { - rbfcalc(&s, &x, &y, _state); - } - if( fidx==2 ) - { - rbfcalcbuf(&s, &x, &y, _state); - } - if( fidx==3 ) - { - rbftscalcbuf(&s, &calcbuf, &x, &y, _state); - } - for(j=0; j<=ny-1; j++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),s2*eps), __FILE__, __LINE__, "testrbfunit.ap:2244"); - } - } - } - - /* - * 3-dimensional test problems - */ - if( nx==3 ) - { - np = k0*k1*k2; - ae_matrix_set_length(&gp, np, nx+ny, _state); - - /* - * create grid, build model - */ - ae_vector_set_length(&gpgx0, k0, _state); - ae_vector_set_length(&gpgx1, k1, _state); - ae_vector_set_length(&gpgx2, k2, _state); - for(i=0; i<=k0-1; i++) - { - gpgx0.ptr.p_double[i] = point.ptr.p_double[0]+gstep*i; - } - for(i=0; i<=k1-1; i++) - { - gpgx1.ptr.p_double[i] = point.ptr.p_double[1]+gstep*i; - } - for(i=0; i<=k2-1; i++) - { - gpgx2.ptr.p_double[i] = point.ptr.p_double[2]+gstep*i; - } - for(i=0; i<=k0-1; i++) - { - for(j=0; j<=k1-1; j++) - { - for(k=0; k<=k2-1; k++) - { - gp.ptr.pp_double[(i*k1+j)*k2+k][0] = gpgx0.ptr.p_double[i]; - gp.ptr.pp_double[(i*k1+j)*k2+k][1] = gpgx1.ptr.p_double[j]; - gp.ptr.pp_double[(i*k1+j)*k2+k][2] = gpgx2.ptr.p_double[k]; - for(l=0; l<=ny-1; l++) - { - gp.ptr.pp_double[(i*k1+j)*k2+k][nx+l] = s2*(2*ae_randomreal(_state)-1); - } - } - } - } - rbfsetpoints(&s, &gp, np, _state); - rbfbuildmodel(&s, &rep, _state); - rbfcreatecalcbuffer(&s, &calcbuf, _state); - - /* - * Test RBFCalc3(), RBFCalc() and RBFCalcBuf() vs expected values on the grid (we expect good fit). - */ - for(i=0; i<=np-1; i++) - { - - /* - * For each row we randomly choose a function to test - * and call it. We do not call multiple functions per - * row because carry-over effects may mask errors in - * some function (say, it is possible that function - * simply returns results from previous call of some - * other function which were stored in the RBF model; - * in this case, previous call with same parameters - * may hide deficiencies in the function). - */ - x.ptr.p_double[0] = gp.ptr.pp_double[i][0]; - x.ptr.p_double[1] = gp.ptr.pp_double[i][1]; - x.ptr.p_double[2] = gp.ptr.pp_double[i][2]; - fidx = ae_randominteger(4, _state); - if( fidx==0&&ny!=1 ) - { - continue; - } - if( fidx==0 ) - { - y.ptr.p_double[0] = rbfcalc3(&s, x.ptr.p_double[0], x.ptr.p_double[1], x.ptr.p_double[2], _state); - } - if( fidx==1 ) - { - rbfcalc(&s, &x, &y, _state); - } - if( fidx==2 ) - { - rbfcalcbuf(&s, &x, &y, _state); - } - if( fidx==3 ) - { - rbftscalcbuf(&s, &calcbuf, &x, &y, _state); - } - for(j=0; j<=ny-1; j++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),s2*eps), __FILE__, __LINE__, "testrbfunit.ap:2312"); - } - } - - /* - * Test RBFGridCalc3V vs RBFCalc() - */ - rbfgridcalc3v(&s, &gpgx0, k0, &gpgx1, k1, &gpgx2, k2, &gcy, _state); - for(i=0; i<=k0-1; i++) - { - for(j=0; j<=k1-1; j++) - { - for(k=0; k<=k2-1; k++) - { - x.ptr.p_double[0] = gpgx0.ptr.p_double[i]; - x.ptr.p_double[1] = gpgx1.ptr.p_double[j]; - x.ptr.p_double[2] = gpgx2.ptr.p_double[k]; - rbfcalcbuf(&s, &x, &y, _state); - for(l=0; l<=ny-1; l++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(y.ptr.p_double[l]-gcy.ptr.p_double[l+ny*(i+j*k0+k*k0*k1)], _state),1.0E-9*s2), __FILE__, __LINE__, "testrbfunit.ap:2329"); - } - } - } - } - } - } - - /* - * Test smoothing properties of RBF model: model with just one layer - * and large initial radius will produce "average" value of neighbors. - * - * In order to test it we create regular grid, fill it with regular - * +1/-1 pattern, and test model values in the inner points. Model - * values should be around zero (we use handcrafted threshold to test - * it). Radius is chosen to be several times larger than grid step. - * - * We perform test for 2D model, because same behavior is expected - * regardless of dimensionality. - */ - r0 = (double)(3); - margin = 5; - gridsize = 2*margin+20; - threshold = 0.1; - nx = 2; - ny = 1; - rbfcreate(nx, ny, &s, _state); - rbfsetalgomultilayer(&s, r0, 1, 0.0, _state); - rbfsetzeroterm(&s, _state); - ae_matrix_set_length(&gp, gridsize*gridsize, nx+ny, _state); - for(i=0; i<=gridsize-1; i++) - { - for(j=0; j<=gridsize-1; j++) - { - gp.ptr.pp_double[i*gridsize+j][0] = (double)(i); - gp.ptr.pp_double[i*gridsize+j][1] = (double)(j); - gp.ptr.pp_double[i*gridsize+j][2] = 0.10*ae_randomreal(_state)-0.05+(2*((i+j)%2)-1); - } - } - rbfsetpoints(&s, &gp, gridsize*gridsize, _state); - rbfbuildmodel(&s, &rep, _state); - v = 0.0; - for(i=margin; i<=gridsize-margin-1; i++) - { - for(j=margin; j<=gridsize-margin-1; j++) - { - v = ae_maxreal(v, ae_fabs(rbfcalc2(&s, (double)(i), (double)(j), _state), _state), _state); - } - } - ae_set_error_flag(&result, ae_fp_greater(v,threshold), __FILE__, __LINE__, "testrbfunit.ap:2376"); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Function for testing basic functionality of RBF module on regular grids with -multi-layer algorithm in 2-3D. - - -- ALGLIB -- - Copyright 2.03.2012 by Bochkanov Sergey -*************************************************************************/ -static void testrbfunit_gridcalc23test(ae_bool* errorflag, - ae_state *_state) -{ - ae_frame _frame_block; - rbfmodel s; - rbfreport rep; - hqrndstate rs; - ae_int_t pass; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t l; - double perturbation; - ae_vector kx; - double sx; - double sy; - ae_int_t nx; - ae_int_t ny; - ae_int_t linterm; - ae_int_t layers; - ae_int_t npoints; - ae_matrix xy; - ae_vector gf; - ae_vector rf; - ae_vector x0; - ae_vector x1; - ae_vector x2; - ae_vector gy; - ae_vector gy2; - ae_vector x; - ae_vector y; - double sparsity; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&rs, 0, sizeof(rs)); - memset(&kx, 0, sizeof(kx)); - memset(&xy, 0, sizeof(xy)); - memset(&gf, 0, sizeof(gf)); - memset(&rf, 0, sizeof(rf)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&x2, 0, sizeof(x2)); - memset(&gy, 0, sizeof(gy)); - memset(&gy2, 0, sizeof(gy2)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - _rbfmodel_init(&s, _state, ae_true); - _rbfreport_init(&rep, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - ae_vector_init(&kx, 0, DT_INT, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&gf, 0, DT_BOOL, _state, ae_true); - ae_vector_init(&rf, 0, DT_BOOL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&gy, 0, DT_REAL, _state, ae_true); - ae_vector_init(&gy2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - - hqrndrandomize(&rs, _state); - for(pass=0; pass<=24; pass++) - { - - /* - * prepare test problem - */ - ae_vector_set_length(&kx, 3, _state); - for(i=0; i<=2; i++) - { - - /* - * 66% of cases - large grid - */ - if( hqrnduniformi(&rs, 3, _state)==0 ) - { - kx.ptr.p_int[i] = ae_round(10*ae_pow((double)(10), hqrnduniformr(&rs, _state), _state), _state); - continue; - } - - /* - * 33% of cases - small grid - */ - k = hqrnduniformi(&rs, 3, _state); - if( k==0 ) - { - kx.ptr.p_int[i] = 1; - } - if( k==1 ) - { - kx.ptr.p_int[i] = 2; - } - if( k==2 ) - { - kx.ptr.p_int[i] = 10; - } - } - sx = ae_pow((double)(10), (double)(hqrnduniformi(&rs, 3, _state)-1), _state); - sy = ae_pow((double)(10), (double)(hqrnduniformi(&rs, 3, _state)-1), _state); - nx = 3; - ny = 1+hqrnduniformi(&rs, 5, _state); - linterm = hqrnduniformi(&rs, 3, _state)+1; - layers = hqrnduniformi(&rs, 3, _state)+1; - npoints = 100; - ae_matrix_set_length(&xy, npoints, nx+ny, _state); - for(i=0; i<=npoints-1; i++) - { - for(j=0; j<=nx-1; j++) - { - xy.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)*sx; - } - for(j=0; j<=ny-1; j++) - { - xy.ptr.pp_double[i][nx+j] = hqrnduniformr(&rs, _state)*sy; - } - } - - /* - * Create RBF model - */ - rbfcreate(nx, ny, &s, _state); - rbfsetalgomultilayer(&s, 0.1*sx, layers, 0.0, _state); - if( linterm==1 ) - { - rbfsetlinterm(&s, _state); - } - if( linterm==2 ) - { - rbfsetconstterm(&s, _state); - } - if( linterm==3 ) - { - rbfsetzeroterm(&s, _state); - } - rbfsetpoints(&s, &xy, npoints, _state); - rbfbuildmodel(&s, &rep, _state); - ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testrbfunit.ap:2473"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - - /* - * Prepare test grid - */ - ae_vector_set_length(&x0, kx.ptr.p_int[0], _state); - for(i=0; i<=kx.ptr.p_int[0]-1; i++) - { - perturbation = 0.5*(hqrnduniformr(&rs, _state)-0.5); - x0.ptr.p_double[i] = sx*(i+perturbation)/kx.ptr.p_int[0]; - } - ae_vector_set_length(&x1, kx.ptr.p_int[1], _state); - for(i=0; i<=kx.ptr.p_int[1]-1; i++) - { - perturbation = 0.5*(hqrnduniformr(&rs, _state)-0.5); - x1.ptr.p_double[i] = sx*(i+perturbation)/kx.ptr.p_int[1]; - } - ae_vector_set_length(&x2, kx.ptr.p_int[2], _state); - for(i=0; i<=kx.ptr.p_int[2]-1; i++) - { - perturbation = 0.5*(hqrnduniformr(&rs, _state)-0.5); - x2.ptr.p_double[i] = sx*(i+perturbation)/kx.ptr.p_int[2]; - } - - /* - * Test calculation on grid - */ - ae_vector_set_length(&x, nx, _state); - ae_vector_set_length(&y, ny, _state); - unsetrealarray(&gy, _state); - rbfgridcalc3v(&s, &x0, kx.ptr.p_int[0], &x1, kx.ptr.p_int[1], &x2, kx.ptr.p_int[2], &gy, _state); - for(i=0; i<=kx.ptr.p_int[0]-1; i++) - { - for(j=0; j<=kx.ptr.p_int[1]-1; j++) - { - for(k=0; k<=kx.ptr.p_int[2]-1; k++) - { - x.ptr.p_double[0] = x0.ptr.p_double[i]; - x.ptr.p_double[1] = x1.ptr.p_double[j]; - x.ptr.p_double[2] = x2.ptr.p_double[k]; - rbfcalcbuf(&s, &x, &y, _state); - for(l=0; l<=ny-1; l++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(y.ptr.p_double[l]-gy.ptr.p_double[l+ny*(i+j*kx.ptr.p_int[0]+k*kx.ptr.p_int[0]*kx.ptr.p_int[1])], _state),1.0E-9*sy), __FILE__, __LINE__, "testrbfunit.ap:2516"); - } - } - } - } - - /* - * Test calculation on subset of regular grid: - * * select sparsity coefficient (from 1.0 to 0.001) - * * fill bitmap array - * * Test 1: compare full and subset versions - * * Test 2: check sparsity. Subset function may perform additional - * evaluations because it processes data micro-row by micro-row. - * So, we can't check that all elements which were not flagged - * are zero - some of them may become non-zero. However, if entire - * row is empty, we can reasonably expect (informal guarantee) - * that it is not processed. So, we check empty (completely - * unflagged) rows - * - */ - sparsity = ae_pow((double)(10), (double)(-hqrnduniformi(&rs, 4, _state)), _state); - ae_vector_set_length(&gf, kx.ptr.p_int[0]*kx.ptr.p_int[1]*kx.ptr.p_int[2], _state); - ae_vector_set_length(&rf, kx.ptr.p_int[1]*kx.ptr.p_int[2], _state); - for(i=0; i<=kx.ptr.p_int[1]*kx.ptr.p_int[2]-1; i++) - { - rf.ptr.p_bool[i] = ae_false; - } - for(i=0; i<=kx.ptr.p_int[0]*kx.ptr.p_int[1]*kx.ptr.p_int[2]-1; i++) - { - gf.ptr.p_bool[i] = ae_fp_less(hqrnduniformr(&rs, _state),sparsity); - if( gf.ptr.p_bool[i] ) - { - rf.ptr.p_bool[i/kx.ptr.p_int[0]] = ae_true; - } - } - ae_vector_set_length(&x, nx, _state); - ae_vector_set_length(&y, ny, _state); - unsetrealarray(&gy, _state); - unsetrealarray(&gy2, _state); - rbfgridcalc3vsubset(&s, &x0, kx.ptr.p_int[0], &x1, kx.ptr.p_int[1], &x2, kx.ptr.p_int[2], &gf, &gy, _state); - rbfgridcalc3v(&s, &x0, kx.ptr.p_int[0], &x1, kx.ptr.p_int[1], &x2, kx.ptr.p_int[2], &gy2, _state); - for(i=0; i<=ny*kx.ptr.p_int[0]*kx.ptr.p_int[1]*kx.ptr.p_int[2]-1; i++) - { - ae_set_error_flag(errorflag, gf.ptr.p_bool[i/ny]&&ae_fp_greater(ae_fabs(gy.ptr.p_double[i]-gy2.ptr.p_double[i], _state),1.0E-9*sy), __FILE__, __LINE__, "testrbfunit.ap:2558"); - ae_set_error_flag(errorflag, !rf.ptr.p_bool[i/(ny*kx.ptr.p_int[0])]&&ae_fp_neq(gy.ptr.p_double[i],0.0), __FILE__, __LINE__, "testrbfunit.ap:2559"); - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Function for testing basic functionality of RBF module with hierarchical -algorithm. - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testrbfunit_basichrbftest(ae_state *_state) -{ - ae_frame _frame_block; - rbfmodel s; - rbfmodel s2; - rbfreport rep; - rbfcalcbuffer tsbuf; - ae_int_t nx; - ae_int_t ny; - ae_int_t linterm; - ae_int_t bf; - double rbase; - ae_int_t nlayers; - double errtol; - double scalefactor; - ae_matrix xy; - ae_matrix xytest; - ae_matrix uxwr; - ae_matrix uv; - ae_matrix xy2; - ae_vector x; - ae_vector y; - ae_vector y2; - ae_vector xzero; - ae_vector yref; - ae_vector scalevec; - ae_int_t n; - ae_int_t ntest; - ae_int_t gridsize; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double r0; - ae_int_t margin; - double threshold; - double v; - ae_int_t functype; - ae_int_t densitytype; - double width; - double lowprec; - double highprec; - ae_int_t modeltype; - ae_int_t shaketype; - double maxerr; - ae_bool fractionalerror; - ae_int_t unx; - ae_int_t uny; - ae_int_t unc; - ae_int_t modelversion; - ae_bool hasscale; - hqrndstate rs; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&s2, 0, sizeof(s2)); - memset(&rep, 0, sizeof(rep)); - memset(&tsbuf, 0, sizeof(tsbuf)); - memset(&xy, 0, sizeof(xy)); - memset(&xytest, 0, sizeof(xytest)); - memset(&uxwr, 0, sizeof(uxwr)); - memset(&uv, 0, sizeof(uv)); - memset(&xy2, 0, sizeof(xy2)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&y2, 0, sizeof(y2)); - memset(&xzero, 0, sizeof(xzero)); - memset(&yref, 0, sizeof(yref)); - memset(&scalevec, 0, sizeof(scalevec)); - memset(&rs, 0, sizeof(rs)); - _rbfmodel_init(&s, _state, ae_true); - _rbfmodel_init(&s2, _state, ae_true); - _rbfreport_init(&rep, _state, ae_true); - _rbfcalcbuffer_init(&tsbuf, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xytest, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&uxwr, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&uv, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xzero, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yref, 0, DT_REAL, _state, ae_true); - ae_vector_init(&scalevec, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - result = ae_false; - - /* - * First test - random problem, ability to build model - * which reproduces function value in all points with - * good precision. - * - * We also test properties of the linear term - that - * model value in far away points is either constant - * or exactly zero (for corresponding kinds of linear - * term). - * - * All dataset points are located in unit cube on - * regular grid. We do not use smoothing for this test. - * - * We use/test following functions: - * * RBFCalc() - * * RBFCalc2() - * * RBFCalc3() - * * RBFCalcBuf() - * * RBFTsCalcBuf() - */ - errtol = 1.0E-6; - for(nx=1; nx<=4; nx++) - { - for(ny=1; ny<=3; ny++) - { - - /* - * problem setup - */ - n = 150; - rbase = 0.33; - nlayers = 10; - gridsize = ae_round(ae_pow((double)(n), (double)1/(double)nx, _state), _state)+1; - linterm = 1+ae_randominteger(3, _state); - bf = ae_randominteger(2, _state); - n = ae_round(ae_pow((double)(gridsize), (double)(nx), _state), _state); - ae_matrix_set_length(&xy, n, nx+ny, _state); - ae_assert(gridsize>1, "Assertion failed", _state); - ae_assert(ae_fp_eq((double)(n),ae_pow((double)(gridsize), (double)(nx), _state)), "Assertion failed", _state); - for(i=0; i<=n-1; i++) - { - k = i; - for(j=0; j<=nx-1; j++) - { - xy.ptr.pp_double[i][j] = (double)(k%gridsize)/(double)(gridsize-1); - k = k/gridsize; - } - for(j=0; j<=ny-1; j++) - { - xy.ptr.pp_double[i][nx+j] = ae_randomreal(_state)-0.5; - } - } - - /* - * Build model - */ - rbfcreate(nx, ny, &s, _state); - rbfsetv2bf(&s, bf, _state); - rbfsetalgohierarchical(&s, rbase, nlayers, 0.0, _state); - if( linterm==1 ) - { - rbfsetlinterm(&s, _state); - } - if( linterm==2 ) - { - rbfsetconstterm(&s, _state); - } - if( linterm==3 ) - { - rbfsetzeroterm(&s, _state); - } - rbfsetpoints(&s, &xy, n, _state); - rbfbuildmodel(&s, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:2683"); - ae_frame_leave(_state); - return result; - } - rbfcreatecalcbuffer(&s, &tsbuf, _state); - - /* - * Test ability to reproduce function value - * - * NOTE: we use RBFCalc(XZero) to guarantee that internal state of - * RBF model is "reset" between subsequent calls of different - * functions. It allows us to make sure that we have no bug - * like function simply returning latest result - */ - ae_vector_set_length(&x, nx, _state); - ae_vector_set_length(&xzero, nx, _state); - ae_vector_set_length(&y, ny, _state); - for(j=0; j<=nx-1; j++) - { - xzero.ptr.p_double[j] = (double)(0); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - x.ptr.p_double[j] = xy.ptr.pp_double[i][j]; - } - rbfcalc(&s, &xzero, &y, _state); - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - ae_vector_set_length(&yref, ny+1, _state); - } - rbfcalc(&s, &x, &yref, _state); - for(j=0; j<=ny-1; j++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(yref.ptr.p_double[j]-xy.ptr.pp_double[i][nx+j], _state),errtol), __FILE__, __LINE__, "testrbfunit.ap:2712"); - } - ae_set_error_flag(&result, yref.cnt!=ny, __FILE__, __LINE__, "testrbfunit.ap:2713"); - if( nx==1&&ny==1 ) - { - rbfcalc(&s, &xzero, &y, _state); - ae_set_error_flag(&result, ae_fp_neq(rbfcalc1(&s, x.ptr.p_double[0], _state),yref.ptr.p_double[0]), __FILE__, __LINE__, "testrbfunit.ap:2719"); - } - if( nx==2&&ny==1 ) - { - rbfcalc(&s, &xzero, &y, _state); - ae_set_error_flag(&result, ae_fp_neq(rbfcalc2(&s, x.ptr.p_double[0], x.ptr.p_double[1], _state),yref.ptr.p_double[0]), __FILE__, __LINE__, "testrbfunit.ap:2726"); - } - if( nx==3&&ny==1 ) - { - rbfcalc(&s, &xzero, &y, _state); - ae_set_error_flag(&result, ae_fp_neq(rbfcalc3(&s, x.ptr.p_double[0], x.ptr.p_double[1], x.ptr.p_double[2], _state),yref.ptr.p_double[0]), __FILE__, __LINE__, "testrbfunit.ap:2733"); - } - rbfcalc(&s, &xzero, &y, _state); - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - ae_vector_set_length(&y, ny+1, _state); - rbfcalcbuf(&s, &x, &y, _state); - ae_set_error_flag(&result, y.cnt!=ny+1, __FILE__, __LINE__, "testrbfunit.ap:2742"); - } - else - { - ae_vector_set_length(&y, ny-1, _state); - rbfcalcbuf(&s, &x, &y, _state); - ae_set_error_flag(&result, y.cnt!=ny, __FILE__, __LINE__, "testrbfunit.ap:2748"); - } - for(j=0; j<=ny-1; j++) - { - ae_set_error_flag(&result, ae_fp_neq(y.ptr.p_double[j],yref.ptr.p_double[j]), __FILE__, __LINE__, "testrbfunit.ap:2751"); - } - rbfcalc(&s, &xzero, &y, _state); - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - ae_vector_set_length(&y, ny+1, _state); - rbftscalcbuf(&s, &tsbuf, &x, &y, _state); - ae_set_error_flag(&result, y.cnt!=ny+1, __FILE__, __LINE__, "testrbfunit.ap:2759"); - } - else - { - ae_vector_set_length(&y, ny-1, _state); - rbftscalcbuf(&s, &tsbuf, &x, &y, _state); - ae_set_error_flag(&result, y.cnt!=ny, __FILE__, __LINE__, "testrbfunit.ap:2765"); - } - for(j=0; j<=ny-1; j++) - { - ae_set_error_flag(&result, ae_fp_neq(y.ptr.p_double[j],yref.ptr.p_double[j]), __FILE__, __LINE__, "testrbfunit.ap:2768"); - } - } - - /* - * Test that: - * a) model with zero linear term is zero far away from dataset - * b) model with constant linear term is constant far away from dataset - */ - ae_vector_set_length(&x, nx, _state); - if( linterm==2 ) - { - for(j=0; j<=nx-1; j++) - { - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - x.ptr.p_double[j] = 1+1000*rbase; - } - else - { - x.ptr.p_double[j] = 0-1000*rbase; - } - } - rbfcalc(&s, &x, &y, _state); - for(j=0; j<=nx-1; j++) - { - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - x.ptr.p_double[j] = 1+1000*rbase; - } - else - { - x.ptr.p_double[j] = 0-1000*rbase; - } - } - rbfcalc(&s, &x, &y2, _state); - for(j=0; j<=ny-1; j++) - { - ae_set_error_flag(&result, ae_fp_neq(y.ptr.p_double[j],y2.ptr.p_double[j]), __FILE__, __LINE__, "testrbfunit.ap:2792"); - } - } - if( linterm==3 ) - { - for(j=0; j<=nx-1; j++) - { - if( ae_fp_greater(ae_randomreal(_state),0.5) ) - { - x.ptr.p_double[j] = 1+1000*rbase; - } - else - { - x.ptr.p_double[j] = 0-1000*rbase; - } - } - rbfcalc(&s, &x, &y, _state); - for(j=0; j<=ny-1; j++) - { - ae_set_error_flag(&result, ae_fp_neq(y.ptr.p_double[j],(double)(0)), __FILE__, __LINE__, "testrbfunit.ap:2803"); - } - } - } - } - - /* - * Test rbfunpack() - */ - for(nx=1; nx<=2; nx++) - { - for(ny=1; ny<=2; ny++) - { - - /* - * problem setup - */ - n = 150; - rbase = 0.33; - nlayers = 5; - gridsize = ae_round(ae_pow((double)(n), (double)1/(double)nx, _state), _state)+1; - linterm = 1+ae_randominteger(3, _state); - bf = ae_randominteger(2, _state); - n = ae_round(ae_pow((double)(gridsize), (double)(nx), _state), _state); - ae_matrix_set_length(&xy, n, nx+ny, _state); - ae_assert(gridsize>1, "Assertion failed", _state); - ae_assert(ae_fp_eq((double)(n),ae_pow((double)(gridsize), (double)(nx), _state)), "Assertion failed", _state); - for(i=0; i<=n-1; i++) - { - k = i; - for(j=0; j<=nx-1; j++) - { - xy.ptr.pp_double[i][j] = (double)(k%gridsize)/(double)(gridsize-1); - k = k/gridsize; - } - for(j=0; j<=ny-1; j++) - { - xy.ptr.pp_double[i][nx+j] = ae_randomreal(_state)-0.5; - } - } - hasscale = ae_randominteger(2, _state)==0; - ae_vector_set_length(&scalevec, nx, _state); - if( hasscale ) - { - for(j=0; j<=nx-1; j++) - { - scalevec.ptr.p_double[j] = ae_pow((double)(2), 2*ae_randomreal(_state)-1, _state); - } - } - - /* - * Build model - */ - rbfcreate(nx, ny, &s, _state); - rbfsetv2bf(&s, bf, _state); - rbfsetalgohierarchical(&s, rbase, nlayers, 0.0, _state); - if( linterm==1 ) - { - rbfsetlinterm(&s, _state); - } - if( linterm==2 ) - { - rbfsetconstterm(&s, _state); - } - if( linterm==3 ) - { - rbfsetzeroterm(&s, _state); - } - if( hasscale ) - { - rbfsetpointsandscales(&s, &xy, n, &scalevec, _state); - } - else - { - rbfsetpoints(&s, &xy, n, _state); - } - rbfbuildmodel(&s, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:2864"); - ae_frame_leave(_state); - return result; - } - - /* - * Test RBFUnpack() - */ - rbfunpack(&s, &unx, &uny, &uxwr, &unc, &uv, &modelversion, _state); - if( modelversion!=2 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:2874"); - ae_frame_leave(_state); - return result; - } - if( unx!=nx||uny!=ny ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:2879"); - ae_frame_leave(_state); - return result; - } - if( uv.cols!=nx+1||uv.rows!=ny ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:2884"); - ae_frame_leave(_state); - return result; - } - if( linterm==2 ) - { - for(i=0; i<=ny-1; i++) - { - for(j=0; j<=nx-1; j++) - { - ae_set_error_flag(&result, ae_fp_neq(uv.ptr.pp_double[i][j],(double)(0)), __FILE__, __LINE__, "testrbfunit.ap:2891"); - } - } - } - if( linterm==3 ) - { - for(i=0; i<=ny-1; i++) - { - for(j=0; j<=nx; j++) - { - ae_set_error_flag(&result, ae_fp_neq(uv.ptr.pp_double[i][j],(double)(0)), __FILE__, __LINE__, "testrbfunit.ap:2897"); - } - } - } - ae_vector_set_length(&x, nx, _state); - ae_vector_set_length(&y, ny, _state); - for(i=0; i<=9; i++) - { - for(j=0; j<=nx-1; j++) - { - x.ptr.p_double[j] = ae_randomreal(_state); - } - rbfcalc(&s, &x, &yref, _state); - for(j=0; j<=ny-1; j++) - { - y.ptr.p_double[j] = uv.ptr.pp_double[j][nx]; - for(k=0; k<=nx-1; k++) - { - y.ptr.p_double[j] = y.ptr.p_double[j]+x.ptr.p_double[k]*uv.ptr.pp_double[j][k]; - } - } - for(k=0; k<=unc-1; k++) - { - v = (double)(0); - for(j=0; j<=nx-1; j++) - { - v = v+ae_sqr(uxwr.ptr.pp_double[k][j]-x.ptr.p_double[j], _state)/ae_sqr(uxwr.ptr.pp_double[k][nx+ny+j], _state); - } - if( ae_fp_less(v,rbfv2farradius(bf, _state)*rbfv2farradius(bf, _state)) ) - { - v = rbfv2basisfunc(bf, v, _state); - } - else - { - v = (double)(0); - } - for(j=0; j<=ny-1; j++) - { - y.ptr.p_double[j] = y.ptr.p_double[j]+v*uxwr.ptr.pp_double[k][nx+j]; - } - } - for(j=0; j<=ny-1; j++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(y.ptr.p_double[j]-yref.ptr.p_double[j], _state),1.0E-9), __FILE__, __LINE__, "testrbfunit.ap:2932"); - } - } - } - } - - /* - * Test that smooth 1D function is reproduced (between nodes) - * with good precision. We test two model types: model with - * three layers and moderate initial radius, and model with - * large initial radius and large number of layers. - * - * This test: - * * generates test function on [-Width,+Width]. Two sets of - * nodes are generated - "model" ones and "test" ones. - * * builds RBF model using "model" dataset - * * test model using "test" dataset. Test points are more - * dense and are spread in [-0.9*Width, +0.9*Width] (reduced - * interval is used because RBF models are too bad near the - * boundaries). - * - * NOTE: we calculate maximum error for given function type - * and grid density over all modifications of the task, - * and only after that we perform comparison with tolerance - * level. It allows easier debugging. - */ - for(functype=0; functype<=2; functype++) - { - for(densitytype=0; densitytype<=1; densitytype++) - { - - /* - * Select tolerance - */ - lowprec = (double)(-999999); - highprec = (double)(-999999); - if( functype==0 ) - { - lowprec = 1.0E-2; - highprec = 1.0E-3; - } - else - { - if( functype==1 ) - { - lowprec = 1.0E-1; - highprec = 1.0E-2; - } - else - { - if( functype==2 ) - { - lowprec = 1.0E-3; - highprec = 1.0E-4; - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - if( densitytype==0 ) - { - errtol = lowprec; - } - else - { - errtol = highprec; - } - - /* - * Test - */ - maxerr = (double)(0); - for(modeltype=0; modeltype<=1; modeltype++) - { - for(shaketype=0; shaketype<=1; shaketype++) - { - - /* - * Generate grid - */ - width = (double)(1); - fractionalerror = ae_false; - if( functype==0 ) - { - - /* - * sin(x) on [-2*pi,+2*pi] - */ - n = 17*ae_round(ae_pow((double)(4), (double)(densitytype), _state), _state); - width = ae_pi; - fractionalerror = ae_false; - } - else - { - if( functype==1 ) - { - - /* - * exp(x) on [-3,+3] - */ - n = 50*ae_round(ae_pow((double)(4), (double)(densitytype), _state), _state); - width = (double)(3); - fractionalerror = ae_true; - } - else - { - if( functype==2 ) - { - - /* - * 1/(1+x^2) on [-3,+3] - */ - n = 20*ae_round(ae_pow((double)(4), (double)(densitytype), _state), _state); - width = (double)(3); - fractionalerror = ae_false; - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - ae_matrix_set_length(&xy, n, 2, _state); - for(i=0; i<=n-1; i++) - { - v = shaketype*0.25*(ae_randomreal(_state)-0.5); - v = (i+v)/(n-1); - v = 2*v-1; - xy.ptr.pp_double[i][0] = width*v; - } - ntest = n*10; - ae_matrix_set_length(&xytest, ntest, 2, _state); - for(i=0; i<=ntest-1; i++) - { - xytest.ptr.pp_double[i][0] = 0.9*width*((double)(2*i)/(double)(ntest-1)-1); - } - - /* - * Evaluate function - */ - if( functype==0 ) - { - - /* - * sin(x) - */ - for(i=0; i<=n-1; i++) - { - xy.ptr.pp_double[i][1] = ae_sin(xy.ptr.pp_double[i][0], _state); - } - for(i=0; i<=ntest-1; i++) - { - xytest.ptr.pp_double[i][1] = ae_sin(xytest.ptr.pp_double[i][0], _state); - } - } - else - { - if( functype==1 ) - { - - /* - * exp(x) - */ - for(i=0; i<=n-1; i++) - { - xy.ptr.pp_double[i][1] = ae_exp(xy.ptr.pp_double[i][0], _state); - } - for(i=0; i<=ntest-1; i++) - { - xytest.ptr.pp_double[i][1] = ae_exp(xytest.ptr.pp_double[i][0], _state); - } - } - else - { - if( functype==2 ) - { - - /* - * 1/(1+x^2) - */ - for(i=0; i<=n-1; i++) - { - xy.ptr.pp_double[i][1] = 1/(1+ae_sqr(xy.ptr.pp_double[i][0], _state)); - } - for(i=0; i<=ntest-1; i++) - { - xytest.ptr.pp_double[i][1] = 1/(1+ae_sqr(xytest.ptr.pp_double[i][0], _state)); - } - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - } - - /* - * Select model properties and precision - */ - if( modeltype==0 ) - { - rbase = 4.0*(2*width/n); - nlayers = 3; - } - else - { - if( modeltype==1 ) - { - rbase = 16.0*(2*width/n); - nlayers = 6; - } - else - { - ae_assert(ae_false, "Assertion failed", _state); - } - } - - /* - * Build model - */ - bf = ae_randominteger(2, _state); - rbfcreate(1, 1, &s, _state); - rbfsetv2bf(&s, bf, _state); - rbfsetalgohierarchical(&s, rbase, nlayers, 0.0, _state); - rbfsetpoints(&s, &xy, n, _state); - rbfbuildmodel(&s, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3106"); - ae_frame_leave(_state); - return result; - } - - /* - * Check - */ - ae_vector_set_length(&x, 1, _state); - for(i=0; i<=ntest-1; i++) - { - x.ptr.p_double[0] = xytest.ptr.pp_double[i][0]; - rbfcalc(&s, &x, &y, _state); - if( fractionalerror ) - { - maxerr = ae_maxreal(maxerr, ae_fabs(y.ptr.p_double[0]-xytest.ptr.pp_double[i][1], _state)/ae_fabs(xytest.ptr.pp_double[i][1], _state), _state); - } - else - { - maxerr = ae_maxreal(maxerr, ae_fabs(y.ptr.p_double[0]-xytest.ptr.pp_double[i][1], _state), _state); - } - } - } - } - - /* - * Check error - */ - ae_set_error_flag(&result, ae_fp_greater(maxerr,errtol), __FILE__, __LINE__, "testrbfunit.ap:3128"); - } - } - - /* - * Scaling test - random problem, we test that after - * scaling of all variables and radius by 2^K (for some K) - * we will get exactly same results (up to the last bit of - * mantissa). - * - * It is very strong requirement for algorithm stability, - * but it is satisfiable in most implementations of RBFs, - * because all operations involving spatial values are usually - * followed by division by radius, and using multiplier which - * is exactly power of 2 results in no changes in numbers - * being returned. - * - * It allows to test different scale-related bugs - * (say, situation when deep in kd-tree search code we compare - * against R instead of R^2). - * - * All dataset points are located in unit cube on - * regular grid. - * - * We do not use smoothing for this test. - */ - for(nx=1; nx<=4; nx++) - { - - /* - * problem setup - */ - n = 150; - rbase = 0.33; - nlayers = ae_randominteger(4, _state); - scalefactor = ae_pow((double)(1024), (double)(2*ae_randominteger(2, _state)-1), _state); - gridsize = ae_round(ae_pow((double)(n), (double)1/(double)nx, _state), _state)+1; - ny = 1+ae_randominteger(3, _state); - linterm = 1+ae_randominteger(3, _state); - bf = ae_randominteger(2, _state); - n = ae_round(ae_pow((double)(gridsize), (double)(nx), _state), _state); - ae_matrix_set_length(&xy, n, nx+ny, _state); - ae_matrix_set_length(&xy2, n, nx+ny, _state); - ae_assert(gridsize>1, "Assertion failed", _state); - ae_assert(ae_fp_eq((double)(n),ae_pow((double)(gridsize), (double)(nx), _state)), "Assertion failed", _state); - for(i=0; i<=n-1; i++) - { - k = i; - for(j=0; j<=nx-1; j++) - { - xy.ptr.pp_double[i][j] = (double)(k%gridsize)/(double)(gridsize-1); - xy2.ptr.pp_double[i][j] = xy.ptr.pp_double[i][j]*scalefactor; - k = k/gridsize; - } - for(j=0; j<=ny-1; j++) - { - xy.ptr.pp_double[i][nx+j] = ae_randomreal(_state)-0.5; - xy2.ptr.pp_double[i][nx+j] = xy.ptr.pp_double[i][nx+j]; - } - } - - /* - * Build model 1 - */ - rbfcreate(nx, ny, &s, _state); - rbfsetv2bf(&s, bf, _state); - rbfsetalgohierarchical(&s, rbase, nlayers, 0.0, _state); - if( linterm==1 ) - { - rbfsetlinterm(&s, _state); - } - if( linterm==2 ) - { - rbfsetconstterm(&s, _state); - } - if( linterm==3 ) - { - rbfsetzeroterm(&s, _state); - } - rbfsetpoints(&s, &xy, n, _state); - rbfbuildmodel(&s, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3204"); - ae_frame_leave(_state); - return result; - } - - /* - * Build model 2 - */ - rbfcreate(nx, ny, &s2, _state); - rbfsetv2bf(&s2, bf, _state); - rbfsetalgohierarchical(&s2, rbase*scalefactor, nlayers, 0.0, _state); - if( linterm==1 ) - { - rbfsetlinterm(&s2, _state); - } - if( linterm==2 ) - { - rbfsetconstterm(&s2, _state); - } - if( linterm==3 ) - { - rbfsetzeroterm(&s2, _state); - } - rbfsetpoints(&s2, &xy2, n, _state); - rbfbuildmodel(&s2, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3224"); - ae_frame_leave(_state); - return result; - } - - /* - * Compare models - */ - ae_vector_set_length(&x, nx, _state); - ae_vector_set_length(&y, ny, _state); - ae_vector_set_length(&y2, ny, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - x.ptr.p_double[j] = xy.ptr.pp_double[i][j]; - } - rbfcalc(&s, &x, &y, _state); - for(j=0; j<=nx-1; j++) - { - x.ptr.p_double[j] = xy2.ptr.pp_double[i][j]; - } - rbfcalc(&s2, &x, &y2, _state); - for(j=0; j<=ny-1; j++) - { - ae_set_error_flag(&result, ae_fp_neq(y.ptr.p_double[j],y2.ptr.p_double[j]), __FILE__, __LINE__, "testrbfunit.ap:3243"); - } - } - } - - /* - * Test that passing scaled dataset automatically results in V2 model - * being built (even when algorithm type is not set explicitly). - */ - for(nx=1; nx<=4; nx++) - { - for(ny=1; ny<=3; ny++) - { - - /* - * problem setup - */ - n = 10; - ae_matrix_set_length(&xy, n, nx+ny, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx+ny-1; j++) - { - xy.ptr.pp_double[i][j] = ae_randomreal(_state)-0.5; - } - } - ae_vector_set_length(&scalevec, nx, _state); - for(j=0; j<=nx-1; j++) - { - scalevec.ptr.p_double[j] = ae_pow((double)(2), 2*ae_randomreal(_state)-1, _state); - } - - /* - * prepare test problem - */ - rbfcreate(nx, ny, &s, _state); - rbfsetpointsandscales(&s, &xy, xy.rows, &scalevec, _state); - - /* - * Build model, check model version - */ - rbfbuildmodel(&s, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3279"); - ae_frame_leave(_state); - return result; - } - ae_set_error_flag(&result, rbfgetmodelversion(&s, _state)!=2, __FILE__, __LINE__, "testrbfunit.ap:3282"); - } - } - - /* - * Test smoothing properties of RBF model: model with just one layer - * and large initial radius will produce "average" value of neighbors. - * - * In order to test it we create regular grid, fill it with regular - * +1/-1 pattern, and test model values in the inner points. Model - * values should be around zero (we use handcrafted threshold to test - * it). Radius is chosen to be several times larger than grid step. - * - * We perform test for 2D model, because same behavior is expected - * regardless of dimensionality. - */ - r0 = (double)(6); - margin = 10; - threshold = 0.005; - gridsize = 2*margin+10; - nx = 2; - ny = 1; - for(bf=0; bf<=1; bf++) - { - rbfcreate(nx, ny, &s, _state); - rbfsetv2bf(&s, bf, _state); - rbfsetalgohierarchical(&s, r0, 1, 1.0E-1, _state); - rbfsetzeroterm(&s, _state); - ae_matrix_set_length(&xy, gridsize*gridsize, nx+ny, _state); - for(i=0; i<=gridsize-1; i++) - { - for(j=0; j<=gridsize-1; j++) - { - xy.ptr.pp_double[i*gridsize+j][0] = (double)(i); - xy.ptr.pp_double[i*gridsize+j][1] = (double)(j); - xy.ptr.pp_double[i*gridsize+j][2] = 0.01*(ae_randomreal(_state)-0.5)+(2*((i+j)%2)-1); - } - } - rbfsetpoints(&s, &xy, gridsize*gridsize, _state); - rbfbuildmodel(&s, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3322"); - ae_frame_leave(_state); - return result; - } - v = 0.0; - for(i=margin; i<=gridsize-margin-1; i++) - { - for(j=margin; j<=gridsize-margin-1; j++) - { - v = ae_maxreal(v, ae_fabs(rbfcalc2(&s, (double)(i), (double)(j), _state), _state), _state); - } - } - ae_set_error_flag(&result, ae_fp_greater(v,threshold), __FILE__, __LINE__, "testrbfunit.ap:3329"); - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Function for testing scaling-related functionality of RBF module with -hierarchical algorithm. - -Returns True on failure (error flag is set). - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testrbfunit_scaledhrbftest(ae_state *_state) -{ - ae_frame _frame_block; - rbfmodel s; - rbfmodel s2; - rbfreport rep; - rbfcalcbuffer tsbuf; - ae_int_t nx; - ae_int_t ny; - ae_int_t linterm; - ae_int_t bf; - double rbase; - ae_int_t nlayers; - double errtol; - ae_matrix xy; - ae_matrix xy2; - ae_vector x; - ae_vector y; - ae_vector y2; - ae_vector xzero; - ae_vector yref; - ae_vector scalex; - ae_vector scaley; - ae_vector c0; - ae_vector c1; - ae_int_t n; - ae_int_t gridsize; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t strictness; - double lambdav; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&s2, 0, sizeof(s2)); - memset(&rep, 0, sizeof(rep)); - memset(&tsbuf, 0, sizeof(tsbuf)); - memset(&xy, 0, sizeof(xy)); - memset(&xy2, 0, sizeof(xy2)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&y2, 0, sizeof(y2)); - memset(&xzero, 0, sizeof(xzero)); - memset(&yref, 0, sizeof(yref)); - memset(&scalex, 0, sizeof(scalex)); - memset(&scaley, 0, sizeof(scaley)); - memset(&c0, 0, sizeof(c0)); - memset(&c1, 0, sizeof(c1)); - _rbfmodel_init(&s, _state, ae_true); - _rbfmodel_init(&s2, _state, ae_true); - _rbfreport_init(&rep, _state, ae_true); - _rbfcalcbuffer_init(&tsbuf, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xzero, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yref, 0, DT_REAL, _state, ae_true); - ae_vector_init(&scalex, 0, DT_REAL, _state, ae_true); - ae_vector_init(&scaley, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c1, 0, DT_REAL, _state, ae_true); - - result = ae_false; - - /* - * First test - random problem, test that using scaling - * does not change model significantly (except for - * rounding-related errors). - * - * We test two kinds of scaling: - * * "strict", which is scaling by some power of 2, and - * which should result in bit-to-bit equivalence of results - * * "non-strict", which is scaling by random number, and - * which should result in approximate equivalence - * - * We also apply scaling to Y, in order to test that it - * is correctly handled too. - */ - for(strictness=0; strictness<=1; strictness++) - { - for(nx=1; nx<=2; nx++) - { - for(ny=1; ny<=2; ny++) - { - - /* - * problem setup - */ - if( strictness==1 ) - { - errtol = (double)(0); - ae_vector_set_length(&scalex, nx, _state); - for(i=0; i<=nx-1; i++) - { - scalex.ptr.p_double[i] = ae_pow((double)(16), (double)(ae_randominteger(3, _state)-1), _state); - } - ae_vector_set_length(&scaley, ny, _state); - for(i=0; i<=ny-1; i++) - { - scaley.ptr.p_double[i] = ae_pow((double)(16), (double)(ae_randominteger(3, _state)-1), _state); - } - } - else - { - errtol = 1.0E-3; - ae_vector_set_length(&scalex, nx, _state); - for(i=0; i<=nx-1; i++) - { - scalex.ptr.p_double[i] = ae_pow((double)(4), 2*ae_randomreal(_state)-1, _state); - } - ae_vector_set_length(&scaley, ny, _state); - for(i=0; i<=ny-1; i++) - { - scaley.ptr.p_double[i] = ae_pow((double)(4), 2*ae_randomreal(_state)-1, _state); - } - } - n = 150; - rbase = 0.33; - nlayers = 2; - gridsize = ae_round(ae_pow((double)(n), (double)1/(double)nx, _state), _state)+1; - linterm = 1+ae_randominteger(3, _state); - bf = ae_randominteger(2, _state); - lambdav = 1.0E-3*ae_randominteger(2, _state); - n = ae_round(ae_pow((double)(gridsize), (double)(nx), _state), _state); - ae_matrix_set_length(&xy, n, nx+ny, _state); - ae_assert(gridsize>1, "Assertion failed", _state); - ae_assert(ae_fp_eq((double)(n),ae_pow((double)(gridsize), (double)(nx), _state)), "Assertion failed", _state); - ae_vector_set_length(&c0, nx, _state); - for(j=0; j<=nx-1; j++) - { - c0.ptr.p_double[j] = ae_randomreal(_state)-0.5; - } - ae_vector_set_length(&c1, ny, _state); - for(j=0; j<=ny-1; j++) - { - c1.ptr.p_double[j] = ae_randomreal(_state)-0.5; - } - for(i=0; i<=n-1; i++) - { - k = i; - for(j=0; j<=nx-1; j++) - { - xy.ptr.pp_double[i][j] = (double)(k%gridsize)/(double)(gridsize-1); - k = k/gridsize; - } - for(j=0; j<=ny-1; j++) - { - xy.ptr.pp_double[i][nx+j] = (double)(0); - for(k=0; k<=nx-1; k++) - { - xy.ptr.pp_double[i][nx+j] = xy.ptr.pp_double[i][nx+j]+c0.ptr.p_double[k]*ae_cos(ae_pi*(1+k)*xy.ptr.pp_double[i][k], _state); - } - xy.ptr.pp_double[i][nx+j] = c1.ptr.p_double[j]*xy.ptr.pp_double[i][nx+j]; - } - } - ae_matrix_set_length(&xy2, n, nx+ny, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - xy2.ptr.pp_double[i][j] = xy.ptr.pp_double[i][j]*scalex.ptr.p_double[j]; - } - for(j=0; j<=ny-1; j++) - { - xy2.ptr.pp_double[i][nx+j] = xy.ptr.pp_double[i][nx+j]*scaley.ptr.p_double[j]; - } - } - - /* - * Build models - */ - rbfcreate(nx, ny, &s, _state); - rbfsetv2bf(&s, bf, _state); - rbfsetalgohierarchical(&s, rbase, nlayers, lambdav, _state); - if( linterm==1 ) - { - rbfsetlinterm(&s, _state); - } - if( linterm==2 ) - { - rbfsetconstterm(&s, _state); - } - if( linterm==3 ) - { - rbfsetzeroterm(&s, _state); - } - rbfsetpoints(&s, &xy, n, _state); - rbfbuildmodel(&s, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3472"); - ae_frame_leave(_state); - return result; - } - rbfcreate(nx, ny, &s2, _state); - rbfsetv2bf(&s2, bf, _state); - rbfsetalgohierarchical(&s2, rbase, nlayers, lambdav, _state); - if( linterm==1 ) - { - rbfsetlinterm(&s2, _state); - } - if( linterm==2 ) - { - rbfsetconstterm(&s2, _state); - } - if( linterm==3 ) - { - rbfsetzeroterm(&s2, _state); - } - rbfsetpointsandscales(&s2, &xy2, n, &scalex, _state); - rbfbuildmodel(&s2, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3488"); - ae_frame_leave(_state); - return result; - } - - /* - * Compare model values in grid points - */ - ae_vector_set_length(&x, nx, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - x.ptr.p_double[j] = xy.ptr.pp_double[i][j]; - } - rbfcalc(&s, &x, &y, _state); - for(j=0; j<=nx-1; j++) - { - x.ptr.p_double[j] = xy2.ptr.pp_double[i][j]; - } - rbfcalc(&s2, &x, &y2, _state); - for(j=0; j<=ny-1; j++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(y.ptr.p_double[j]-y2.ptr.p_double[j]/scaley.ptr.p_double[j], _state),errtol), __FILE__, __LINE__, "testrbfunit.ap:3505"); - } - } - - /* - * Compare model values in random points - */ - ae_vector_set_length(&x, nx, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - x.ptr.p_double[j] = ae_randomreal(_state); - } - rbfcalc(&s, &x, &y, _state); - for(j=0; j<=nx-1; j++) - { - x.ptr.p_double[j] = x.ptr.p_double[j]*scalex.ptr.p_double[j]; - } - rbfcalc(&s2, &x, &y2, _state); - for(j=0; j<=ny-1; j++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(y.ptr.p_double[j]-y2.ptr.p_double[j]/scaley.ptr.p_double[j], _state),errtol), __FILE__, __LINE__, "testrbfunit.ap:3521"); - } - } - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Test special properties of hierarchical RBFs. -Returns True on errors. - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testrbfunit_spechrbftest(ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t n; - ae_int_t nx; - ae_int_t ny; - double rbase; - rbfmodel s0; - rbfmodel s1; - rbfreport rep; - ae_int_t nlayers; - ae_matrix xy; - ae_int_t i; - ae_int_t j; - double vdiff; - double d2; - ae_int_t v2its; - hqrndstate rs; - double vref; - double vfunc; - double maxerr; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s0, 0, sizeof(s0)); - memset(&s1, 0, sizeof(s1)); - memset(&rep, 0, sizeof(rep)); - memset(&xy, 0, sizeof(xy)); - memset(&rs, 0, sizeof(rs)); - _rbfmodel_init(&s0, _state, ae_true); - _rbfmodel_init(&s1, _state, ae_true); - _rbfreport_init(&rep, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - hqrndrandomize(&rs, _state); - result = ae_false; - - /* - * Test properties of RBF basis functions - we compare values - * returned by RBFV2BasisFunc() against analytic expressions - * which are approximately modeled by RBFV2BasisFunc(). - */ - d2 = 0.0; - while(ae_fp_less(d2,100.0)) - { - vref = ae_exp(-d2, _state); - vfunc = rbfv2basisfunc(0, d2, _state); - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vref-vfunc, _state),1.0E-9*vref), __FILE__, __LINE__, "testrbfunit.ap:3563"); - d2 = d2+(double)1/(double)64; - } - d2 = 0.0; - maxerr = 0.0; - while(ae_fp_less(d2,16.0)) - { - vref = ae_maxreal(1-d2/9, (double)(0), _state)*ae_exp(-d2, _state); - vfunc = rbfv2basisfunc(1, d2, _state); - maxerr = ae_maxreal(maxerr, ae_fabs(vref-vfunc, _state), _state); - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vref-vfunc, _state),0.005), __FILE__, __LINE__, "testrbfunit.ap:3573"); - d2 = d2+(double)1/(double)64; - } - - /* - * Test that tiny changes in dataset points introduce tiny - * numerical noise. The noise magnitude depends on the - * properties of the linear solver being used. We compare - * noise magnitude against hard-coded values. - * - * Test sequence: - * * create model #1 - * * create model #2 using slightly modified dataset - */ - nx = 2; - ny = 1; - n = 20; - rbase = 2.0; - nlayers = 1; - v2its = 50; - ae_matrix_set_length(&xy, n*n, nx+ny, _state); - for(i=0; i<=n*n-1; i++) - { - xy.ptr.pp_double[i][0] = (double)(i%n); - xy.ptr.pp_double[i][1] = (double)(i/n); - xy.ptr.pp_double[i][2] = ae_sin((double)(i), _state); - } - rbfcreate(nx, ny, &s0, _state); - rbfsetalgohierarchical(&s0, rbase, nlayers, 0.0, _state); - rbfsetv2its(&s0, v2its, _state); - rbfsetpoints(&s0, &xy, n*n, _state); - rbfbuildmodel(&s0, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3608"); - ae_frame_leave(_state); - return result; - } - for(i=0; i<=n*n-1; i++) - { - xy.ptr.pp_double[i][0] = xy.ptr.pp_double[i][0]+1.0E-14*ae_sin((double)(3*i), _state); - xy.ptr.pp_double[i][1] = xy.ptr.pp_double[i][1]+1.0E-14*ae_sin((double)(7*i*i), _state); - } - rbfcreate(nx, ny, &s1, _state); - rbfsetalgohierarchical(&s1, rbase, nlayers, 0.0, _state); - rbfsetv2its(&s1, v2its, _state); - rbfsetpoints(&s1, &xy, n*n, _state); - rbfbuildmodel(&s1, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3623"); - ae_frame_leave(_state); - return result; - } - vdiff = (double)(0); - for(i=0; i<=n-2; i++) - { - for(j=0; j<=n-2; j++) - { - vdiff = vdiff+ae_fabs(rbfcalc2(&s0, 0.5+i, 0.5+j, _state)-rbfcalc2(&s1, 0.5+i, 0.5+j, _state), _state)/ae_sqr((double)(n-1), _state); - } - } - ae_set_error_flag(&result, ae_fp_greater(vdiff,0.00200)||ae_fp_less(vdiff,0.00001), __FILE__, __LINE__, "testrbfunit.ap:3630"); - - /* - * Test progress reports: progress before model construction is - * zero, progress after model is built is 1. More detailed tests - * are performed in the multithreaded TestHRBFProgress(). - */ - nx = 2; - ny = 1; - n = 20; - rbase = 1.0; - nlayers = 3; - ae_matrix_set_length(&xy, n, nx+ny, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx; j++) - { - xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state); - } - } - rbfcreate(nx, ny, &s0, _state); - rbfsetalgohierarchical(&s0, rbase, nlayers, 0.0, _state); - ae_set_error_flag(&result, ae_fp_neq(rbfpeekprogress(&s0, _state),(double)(0)), __FILE__, __LINE__, "testrbfunit.ap:3652"); - rbfbuildmodel(&s0, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testrbfunit.ap:3654"); - ae_set_error_flag(&result, ae_fp_neq(rbfpeekprogress(&s0, _state),(double)(1)), __FILE__, __LINE__, "testrbfunit.ap:3655"); - rbfcreate(nx, ny, &s0, _state); - rbfsetpoints(&s0, &xy, n, _state); - rbfsetalgohierarchical(&s0, rbase, 0, 0.0, _state); - ae_set_error_flag(&result, ae_fp_neq(rbfpeekprogress(&s0, _state),(double)(0)), __FILE__, __LINE__, "testrbfunit.ap:3661"); - rbfbuildmodel(&s0, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testrbfunit.ap:3663"); - ae_set_error_flag(&result, ae_fp_neq(rbfpeekprogress(&s0, _state),(double)(1)), __FILE__, __LINE__, "testrbfunit.ap:3664"); - rbfcreate(nx, ny, &s0, _state); - rbfsetpoints(&s0, &xy, n, _state); - rbfsetalgohierarchical(&s0, rbase, nlayers, 0.0, _state); - ae_set_error_flag(&result, ae_fp_neq(rbfpeekprogress(&s0, _state),(double)(0)), __FILE__, __LINE__, "testrbfunit.ap:3670"); - rbfbuildmodel(&s0, &rep, _state); - ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testrbfunit.ap:3672"); - ae_set_error_flag(&result, ae_fp_neq(rbfpeekprogress(&s0, _state),(double)(1)), __FILE__, __LINE__, "testrbfunit.ap:3673"); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Test gridded evaluation of hierarchical RBFs. -Returns True on errors. - - -- ALGLIB -- - Copyright 20.06.2016 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testrbfunit_gridhrbftest(ae_state *_state) -{ - ae_frame _frame_block; - rbfmodel s; - rbfreport rep; - ae_int_t linterm; - ae_int_t bf; - double rbase; - ae_int_t nlayers; - ae_int_t nx; - ae_int_t ny; - ae_bool hasscale; - double errtol; - ae_int_t n; - ae_matrix xy; - ae_matrix xy2; - ae_matrix y2; - ae_vector x0; - ae_vector x1; - ae_vector x2; - ae_vector x02; - ae_vector x12; - ae_vector x22; - ae_vector scalevec; - ae_vector scalevec2; - ae_vector needy; - ae_vector rowflags; - ae_int_t n0; - ae_int_t n1; - ae_int_t n2; - ae_int_t nkind; - double v; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t i0; - ae_int_t i1; - ae_int_t i2; - ae_vector x; - ae_vector y; - ae_vector yv; - ae_vector yv2; - double scalefactor; - double lambdav; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&xy, 0, sizeof(xy)); - memset(&xy2, 0, sizeof(xy2)); - memset(&y2, 0, sizeof(y2)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&x2, 0, sizeof(x2)); - memset(&x02, 0, sizeof(x02)); - memset(&x12, 0, sizeof(x12)); - memset(&x22, 0, sizeof(x22)); - memset(&scalevec, 0, sizeof(scalevec)); - memset(&scalevec2, 0, sizeof(scalevec2)); - memset(&needy, 0, sizeof(needy)); - memset(&rowflags, 0, sizeof(rowflags)); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&yv, 0, sizeof(yv)); - memset(&yv2, 0, sizeof(yv2)); - _rbfmodel_init(&s, _state, ae_true); - _rbfreport_init(&rep, _state, ae_true); - ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&y2, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x02, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x12, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x22, 0, DT_REAL, _state, ae_true); - ae_vector_init(&scalevec, 0, DT_REAL, _state, ae_true); - ae_vector_init(&scalevec2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&needy, 0, DT_BOOL, _state, ae_true); - ae_vector_init(&rowflags, 0, DT_BOOL, _state, ae_true); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yv, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yv2, 0, DT_REAL, _state, ae_true); - - result = ae_false; - - /* - * Test 2-dimensional grid calculation - */ - errtol = 1.0E-12; - nx = 2; - for(ny=1; ny<=4; ny++) - { - for(nkind=0; nkind<=2; nkind++) - { - - /* - * problem setup - */ - n = 150; - rbase = 0.10; - nlayers = ae_randominteger(3, _state); - linterm = 1+ae_randominteger(3, _state); - lambdav = 1.0E-3*ae_randominteger(2, _state); - bf = ae_randominteger(2, _state); - ae_matrix_set_length(&xy, n, nx+ny, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - xy.ptr.pp_double[i][j] = ae_randomreal(_state); - } - for(j=0; j<=ny-1; j++) - { - xy.ptr.pp_double[i][nx+j] = ae_randomreal(_state)-0.5; - } - } - hasscale = ae_randominteger(2, _state)==0; - if( hasscale ) - { - ae_vector_set_length(&scalevec, nx, _state); - for(j=0; j<=nx-1; j++) - { - scalevec.ptr.p_double[j] = ae_pow((double)(2), 2*ae_randomreal(_state)-1, _state); - } - } - - /* - * Build model - */ - rbfcreate(nx, ny, &s, _state); - rbfsetv2bf(&s, bf, _state); - rbfsetalgohierarchical(&s, rbase, nlayers, lambdav, _state); - if( linterm==1 ) - { - rbfsetlinterm(&s, _state); - } - if( linterm==2 ) - { - rbfsetconstterm(&s, _state); - } - if( linterm==3 ) - { - rbfsetzeroterm(&s, _state); - } - if( hasscale ) - { - rbfsetpointsandscales(&s, &xy, n, &scalevec, _state); - } - else - { - rbfsetpoints(&s, &xy, n, _state); - } - rbfbuildmodel(&s, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3765"); - ae_frame_leave(_state); - return result; - } - - /* - * Prepare grid to test - */ - n0 = 1+ae_randominteger(50, _state); - n1 = 1+ae_randominteger(50, _state); - if( nkind==1 ) - { - k = ae_randominteger(2, _state); - if( k==0 ) - { - n0 = 1; - } - if( k==1 ) - { - n1 = 1; - } - } - else - { - if( nkind==2 ) - { - n0 = 1; - n1 = 1; - } - else - { - ae_assert(nkind==0, "Assertion failed", _state); - } - } - ae_vector_set_length(&x0, n0, _state); - x0.ptr.p_double[0] = ae_randomreal(_state); - for(i=1; i<=n0-1; i++) - { - x0.ptr.p_double[i] = x0.ptr.p_double[i-1]+ae_randomreal(_state)/n0; - } - ae_vector_set_length(&x1, n1, _state); - x1.ptr.p_double[0] = ae_randomreal(_state); - for(i=1; i<=n1-1; i++) - { - x1.ptr.p_double[i] = x1.ptr.p_double[i-1]+ae_randomreal(_state)/n1; - } - ae_vector_set_length(&needy, n0*n1, _state); - v = ae_pow((double)(10), -3*ae_randomreal(_state), _state); - for(i=0; i<=n0*n1-1; i++) - { - needy.ptr.p_bool[i] = ae_fp_less(ae_randomreal(_state),v); - } - - /* - * Test at grid - */ - ae_vector_set_length(&x, nx, _state); - rbfgridcalc2v(&s, &x0, n0, &x1, n1, &yv, _state); - for(i0=0; i0<=n0-1; i0++) - { - for(i1=0; i1<=n1-1; i1++) - { - x.ptr.p_double[0] = x0.ptr.p_double[i0]; - x.ptr.p_double[1] = x1.ptr.p_double[i1]; - rbfcalc(&s, &x, &y, _state); - for(i=0; i<=ny-1; i++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(y.ptr.p_double[i]-yv.ptr.p_double[i+ny*(i0+i1*n0)], _state),errtol), __FILE__, __LINE__, "testrbfunit.ap:3814"); - } - } - } - - /* - * Test calculation on subset of regular grid: - * * Test 1: compare full and subset versions - * * Test 2: check sparsity. Subset function may perform additional - * evaluations because it processes data micro-row by micro-row. - * So, we can't check that all elements which were not flagged - * are zero - some of them may become non-zero. However, if entire - * row is empty, we can reasonably expect (informal guarantee) - * that it is not processed. So, we check empty (completely - * unflagged) rows - * - */ - unsetrealarray(&yv2, _state); - rbfgridcalc2vsubset(&s, &x0, n0, &x1, n1, &needy, &yv2, _state); - for(i=0; i<=ny*n0*n1-1; i++) - { - ae_set_error_flag(&result, needy.ptr.p_bool[i/ny]&&ae_fp_greater(ae_fabs(yv.ptr.p_double[i]-yv2.ptr.p_double[i], _state),errtol), __FILE__, __LINE__, "testrbfunit.ap:3833"); - } - - /* - * Test legacy function - */ - rbfgridcalc2(&s, &x0, n0, &x1, n1, &y2, _state); - for(i=0; i<=n0*n1-1; i++) - { - if( ny==1 ) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(yv.ptr.p_double[i]-y2.ptr.pp_double[i%n0][i/n0], _state),errtol), __FILE__, __LINE__, "testrbfunit.ap:3843"); - } - else - { - ae_set_error_flag(&result, ae_fp_neq(y2.ptr.pp_double[i%n0][i/n0],(double)(0)), __FILE__, __LINE__, "testrbfunit.ap:3845"); - } - } - - /* - * Test that scaling RBase, XY, X0, X1 by some power of 2 - * does not change values at grid (quite a strict requirement, but - * ALGLIB implementation of RBF may deal with it). - */ - scalefactor = ae_pow((double)(1024), (double)(2*ae_randominteger(2, _state)-1), _state); - ae_matrix_set_length(&xy2, n, nx+ny, _state); - ae_vector_set_length(&x02, n0, _state); - ae_vector_set_length(&x12, n1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - xy2.ptr.pp_double[i][j] = xy.ptr.pp_double[i][j]*scalefactor; - } - for(j=0; j<=ny-1; j++) - { - xy2.ptr.pp_double[i][nx+j] = xy.ptr.pp_double[i][nx+j]; - } - } - for(i=0; i<=n0-1; i++) - { - x02.ptr.p_double[i] = x0.ptr.p_double[i]*scalefactor; - } - for(i=0; i<=n1-1; i++) - { - x12.ptr.p_double[i] = x1.ptr.p_double[i]*scalefactor; - } - if( hasscale ) - { - rbfsetpointsandscales(&s, &xy2, n, &scalevec, _state); - } - else - { - rbfsetpoints(&s, &xy2, n, _state); - } - rbfsetv2bf(&s, bf, _state); - rbfsetalgohierarchical(&s, rbase*scalefactor, nlayers, lambdav, _state); - rbfbuildmodel(&s, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3877"); - ae_frame_leave(_state); - return result; - } - unsetrealarray(&yv2, _state); - rbfgridcalc2v(&s, &x02, n0, &x12, n1, &yv2, _state); - for(i=0; i<=ny*n0*n1-1; i++) - { - ae_set_error_flag(&result, ae_fp_neq(yv.ptr.p_double[i],yv2.ptr.p_double[i]), __FILE__, __LINE__, "testrbfunit.ap:3883"); - } - - /* - * Test that scaling RBase and scale vector by some power of 2 - * (increase RBase and decreasing scale, or vice versa) does not - * change values at grid (quite a strict requirement, but - * ALGLIB implementation of RBF may deal with it). - */ - scalefactor = ae_pow((double)(1024), (double)(2*ae_randominteger(2, _state)-1), _state); - ae_vector_set_length(&scalevec2, nx, _state); - for(i=0; i<=nx-1; i++) - { - if( hasscale ) - { - scalevec2.ptr.p_double[i] = scalevec.ptr.p_double[i]; - } - else - { - scalevec2.ptr.p_double[i] = 1.0; - } - scalevec2.ptr.p_double[i] = scalevec2.ptr.p_double[i]/scalefactor; - } - rbfsetpointsandscales(&s, &xy, n, &scalevec2, _state); - rbfsetv2bf(&s, bf, _state); - rbfsetalgohierarchical(&s, rbase*scalefactor, nlayers, lambdav, _state); - rbfbuildmodel(&s, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3907"); - ae_frame_leave(_state); - return result; - } - unsetrealarray(&yv2, _state); - rbfgridcalc2v(&s, &x0, n0, &x1, n1, &yv2, _state); - for(i=0; i<=ny*n0*n1-1; i++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(yv.ptr.p_double[i]-yv2.ptr.p_double[i], _state),100*ae_machineepsilon*rmax3(ae_fabs(yv.ptr.p_double[i], _state), ae_fabs(yv2.ptr.p_double[i], _state), 1.0, _state)), __FILE__, __LINE__, "testrbfunit.ap:3913"); - } - } - } - - /* - * Test 3-dimensional grid calculation - */ - errtol = 1.0E-12; - nx = 3; - for(ny=1; ny<=4; ny++) - { - for(nkind=0; nkind<=2; nkind++) - { - - /* - * problem setup - */ - n = 150; - rbase = 0.10; - lambdav = 1.0E-3*ae_randominteger(2, _state); - nlayers = ae_randominteger(3, _state); - linterm = 1+ae_randominteger(3, _state); - bf = ae_randominteger(2, _state); - ae_matrix_set_length(&xy, n, nx+ny, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - xy.ptr.pp_double[i][j] = ae_randomreal(_state); - } - for(j=0; j<=ny-1; j++) - { - xy.ptr.pp_double[i][nx+j] = ae_randomreal(_state)-0.5; - } - } - hasscale = ae_randominteger(2, _state)==0; - if( hasscale ) - { - ae_vector_set_length(&scalevec, nx, _state); - for(j=0; j<=nx-1; j++) - { - scalevec.ptr.p_double[j] = ae_pow((double)(2), 2*ae_randomreal(_state)-1, _state); - } - } - - /* - * Build model - */ - rbfcreate(nx, ny, &s, _state); - rbfsetv2bf(&s, bf, _state); - rbfsetalgohierarchical(&s, rbase, nlayers, lambdav, _state); - if( linterm==1 ) - { - rbfsetlinterm(&s, _state); - } - if( linterm==2 ) - { - rbfsetconstterm(&s, _state); - } - if( linterm==3 ) - { - rbfsetzeroterm(&s, _state); - } - if( hasscale ) - { - rbfsetpointsandscales(&s, &xy, n, &scalevec, _state); - } - else - { - rbfsetpoints(&s, &xy, n, _state); - } - rbfbuildmodel(&s, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3968"); - ae_frame_leave(_state); - return result; - } - - /* - * Prepare grid to test - */ - n0 = 1+ae_randominteger(50, _state); - n1 = 1+ae_randominteger(50, _state); - n2 = 1+ae_randominteger(50, _state); - if( nkind==1 ) - { - k = ae_randominteger(3, _state); - if( k==0 ) - { - n0 = 1; - } - if( k==1 ) - { - n1 = 1; - } - if( k==2 ) - { - n2 = 1; - } - } - else - { - if( nkind==2 ) - { - n0 = 1; - n1 = 1; - n2 = 1; - } - else - { - ae_assert(nkind==0, "Assertion failed", _state); - } - } - ae_vector_set_length(&x0, n0, _state); - x0.ptr.p_double[0] = ae_randomreal(_state); - for(i=1; i<=n0-1; i++) - { - x0.ptr.p_double[i] = x0.ptr.p_double[i-1]+ae_randomreal(_state)/n0; - } - ae_vector_set_length(&x1, n1, _state); - x1.ptr.p_double[0] = ae_randomreal(_state); - for(i=1; i<=n1-1; i++) - { - x1.ptr.p_double[i] = x1.ptr.p_double[i-1]+ae_randomreal(_state)/n1; - } - ae_vector_set_length(&x2, n2, _state); - x2.ptr.p_double[0] = ae_randomreal(_state); - for(i=1; i<=n2-1; i++) - { - x2.ptr.p_double[i] = x2.ptr.p_double[i-1]+ae_randomreal(_state)/n2; - } - ae_vector_set_length(&needy, n0*n1*n2, _state); - v = ae_pow((double)(10), -3*ae_randomreal(_state), _state); - for(i=0; i<=n0*n1*n2-1; i++) - { - needy.ptr.p_bool[i] = ae_fp_less(ae_randomreal(_state),v); - } - - /* - * Test at grid - */ - ae_vector_set_length(&x, nx, _state); - rbfgridcalc3v(&s, &x0, n0, &x1, n1, &x2, n2, &yv, _state); - for(i0=0; i0<=n0-1; i0++) - { - for(i1=0; i1<=n1-1; i1++) - { - for(i2=0; i2<=n2-1; i2++) - { - x.ptr.p_double[0] = x0.ptr.p_double[i0]; - x.ptr.p_double[1] = x1.ptr.p_double[i1]; - x.ptr.p_double[2] = x2.ptr.p_double[i2]; - rbfcalc(&s, &x, &y, _state); - for(i=0; i<=ny-1; i++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(y.ptr.p_double[i]-yv.ptr.p_double[i+ny*(i0+i1*n0+i2*n0*n1)], _state),errtol), __FILE__, __LINE__, "testrbfunit.ap:4027"); - } - } - } - } - - /* - * Test calculation on subset of regular grid: - * * Test 1: compare full and subset versions - * * Test 2: check sparsity. Subset function may perform additional - * evaluations because it processes data micro-row by micro-row. - * So, we can't check that all elements which were not flagged - * are zero - some of them may become non-zero. However, if entire - * row is empty, we can reasonably expect (informal guarantee) - * that it is not processed. So, we check empty (completely - * unflagged) rows - * - */ - ae_vector_set_length(&rowflags, n1*n2, _state); - for(i=0; i<=n1*n2-1; i++) - { - rowflags.ptr.p_bool[i] = ae_false; - } - for(i=0; i<=n0*n1*n2-1; i++) - { - if( needy.ptr.p_bool[i] ) - { - rowflags.ptr.p_bool[i/n0] = ae_true; - } - } - unsetrealarray(&yv2, _state); - rbfgridcalc3vsubset(&s, &x0, n0, &x1, n1, &x2, n2, &needy, &yv2, _state); - for(i=0; i<=ny*n0*n1*n2-1; i++) - { - ae_set_error_flag(&result, needy.ptr.p_bool[i/ny]&&ae_fp_greater(ae_fabs(yv.ptr.p_double[i]-yv2.ptr.p_double[i], _state),errtol), __FILE__, __LINE__, "testrbfunit.ap:4054"); - ae_set_error_flag(&result, !rowflags.ptr.p_bool[i/(ny*n0)]&&ae_fp_neq(yv2.ptr.p_double[i],0.0), __FILE__, __LINE__, "testrbfunit.ap:4055"); - } - - /* - * Test that scaling RBase, XY, X0, X1 and X2 by some power of 2 - * does not change values at grid (quite a strict requirement, but - * ALGLIB implementation of RBF may deal with it). - */ - scalefactor = ae_pow((double)(1024), (double)(2*ae_randominteger(2, _state)-1), _state); - ae_matrix_set_length(&xy2, n, nx+ny, _state); - ae_vector_set_length(&x02, n0, _state); - ae_vector_set_length(&x12, n1, _state); - ae_vector_set_length(&x22, n2, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=nx-1; j++) - { - xy2.ptr.pp_double[i][j] = xy.ptr.pp_double[i][j]*scalefactor; - } - for(j=0; j<=ny-1; j++) - { - xy2.ptr.pp_double[i][nx+j] = xy.ptr.pp_double[i][nx+j]; - } - } - for(i=0; i<=n0-1; i++) - { - x02.ptr.p_double[i] = x0.ptr.p_double[i]*scalefactor; - } - for(i=0; i<=n1-1; i++) - { - x12.ptr.p_double[i] = x1.ptr.p_double[i]*scalefactor; - } - for(i=0; i<=n2-1; i++) - { - x22.ptr.p_double[i] = x2.ptr.p_double[i]*scalefactor; - } - if( hasscale ) - { - rbfsetpointsandscales(&s, &xy2, n, &scalevec, _state); - } - else - { - rbfsetpoints(&s, &xy2, n, _state); - } - rbfsetv2bf(&s, bf, _state); - rbfsetalgohierarchical(&s, rbase*scalefactor, nlayers, lambdav, _state); - rbfbuildmodel(&s, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:4090"); - ae_frame_leave(_state); - return result; - } - unsetrealarray(&yv2, _state); - rbfgridcalc3v(&s, &x02, n0, &x12, n1, &x22, n2, &yv2, _state); - for(i=0; i<=ny*n0*n1*n2-1; i++) - { - ae_set_error_flag(&result, ae_fp_neq(yv.ptr.p_double[i],yv2.ptr.p_double[i]), __FILE__, __LINE__, "testrbfunit.ap:4096"); - } - - /* - * Test that scaling RBase and scale vector by some power of 2 - * (increase RBase and decreasing scale, or vice versa) does not - * change values at grid (quite a strict requirement, but - * ALGLIB implementation of RBF may deal with it). - */ - scalefactor = ae_pow((double)(1024), (double)(2*ae_randominteger(2, _state)-1), _state); - ae_vector_set_length(&scalevec2, nx, _state); - for(i=0; i<=nx-1; i++) - { - if( hasscale ) - { - scalevec2.ptr.p_double[i] = scalevec.ptr.p_double[i]; - } - else - { - scalevec2.ptr.p_double[i] = 1.0; - } - scalevec2.ptr.p_double[i] = scalevec2.ptr.p_double[i]/scalefactor; - } - rbfsetpointsandscales(&s, &xy, n, &scalevec2, _state); - rbfsetv2bf(&s, bf, _state); - rbfsetalgohierarchical(&s, rbase*scalefactor, nlayers, lambdav, _state); - rbfbuildmodel(&s, &rep, _state); - if( rep.terminationtype<=0 ) - { - ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:4120"); - ae_frame_leave(_state); - return result; - } - unsetrealarray(&yv2, _state); - rbfgridcalc3v(&s, &x0, n0, &x1, n1, &x2, n2, &yv2, _state); - for(i=0; i<=ny*n0*n1*n2-1; i++) - { - ae_set_error_flag(&result, ae_fp_greater(ae_fabs(yv.ptr.p_double[i]-yv2.ptr.p_double[i], _state),100*ae_machineepsilon*rmax3(ae_fabs(yv.ptr.p_double[i], _state), ae_fabs(yv2.ptr.p_double[i], _state), 1.0, _state)), __FILE__, __LINE__, "testrbfunit.ap:4126"); - } - } - } - ae_frame_leave(_state); - return result; -} - - - - - - - - -ae_bool testhermite(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - double err; - double sumerr; - double cerr; - double threshold; - ae_int_t n; - ae_int_t maxn; - ae_int_t pass; - ae_vector c; - double x; - double v; - ae_bool waserrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&c, 0, sizeof(c)); - ae_vector_init(&c, 0, DT_REAL, _state, ae_true); - - err = (double)(0); - sumerr = (double)(0); - cerr = (double)(0); - threshold = 1.0E-9; - waserrors = ae_false; - - /* - * Testing Hermite polynomials - */ - n = 0; - err = ae_maxreal(err, ae_fabs(hermitecalculate(n, (double)(1), _state)-1, _state), _state); - n = 1; - err = ae_maxreal(err, ae_fabs(hermitecalculate(n, (double)(1), _state)-2, _state), _state); - n = 2; - err = ae_maxreal(err, ae_fabs(hermitecalculate(n, (double)(1), _state)-2, _state), _state); - n = 3; - err = ae_maxreal(err, ae_fabs(hermitecalculate(n, (double)(1), _state)+4, _state), _state); - n = 4; - err = ae_maxreal(err, ae_fabs(hermitecalculate(n, (double)(1), _state)+20, _state), _state); - n = 5; - err = ae_maxreal(err, ae_fabs(hermitecalculate(n, (double)(1), _state)+8, _state), _state); - n = 6; - err = ae_maxreal(err, ae_fabs(hermitecalculate(n, (double)(1), _state)-184, _state), _state); - n = 7; - err = ae_maxreal(err, ae_fabs(hermitecalculate(n, (double)(1), _state)-464, _state), _state); - n = 11; - err = ae_maxreal(err, ae_fabs(hermitecalculate(n, (double)(1), _state)-230848, _state), _state); - n = 12; - err = ae_maxreal(err, ae_fabs(hermitecalculate(n, (double)(1), _state)-280768, _state), _state); - - /* - * Testing Clenshaw summation - */ - maxn = 10; - ae_vector_set_length(&c, maxn+1, _state); - for(pass=1; pass<=10; pass++) - { - x = 2*ae_randomreal(_state)-1; - v = (double)(0); - for(n=0; n<=maxn; n++) - { - c.ptr.p_double[n] = 2*ae_randomreal(_state)-1; - v = v+hermitecalculate(n, x, _state)*c.ptr.p_double[n]; - sumerr = ae_maxreal(sumerr, ae_fabs(v-hermitesum(&c, n, x, _state), _state), _state); - } - } - - /* - * Testing coefficients - */ - hermitecoefficients(0, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-1, _state), _state); - hermitecoefficients(1, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-2, _state), _state); - hermitecoefficients(2, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]+2, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-4, _state), _state); - hermitecoefficients(3, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]+12, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]-8, _state), _state); - hermitecoefficients(4, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-12, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]+48, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[4]-16, _state), _state); - hermitecoefficients(5, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-120, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]+160, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[4]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[5]-32, _state), _state); - hermitecoefficients(6, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]+120, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-720, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[4]+480, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[5]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[6]-64, _state), _state); - - /* - * Reporting - */ - waserrors = (ae_fp_greater(err,threshold)||ae_fp_greater(sumerr,threshold))||ae_fp_greater(cerr,threshold); - if( !silent ) - { - printf("TESTING CALCULATION OF THE HERMITE POLYNOMIALS\n"); - printf("Max error %5.2e\n", - (double)(err)); - printf("Summation error %5.2e\n", - (double)(sumerr)); - printf("Coefficients error %5.2e\n", - (double)(cerr)); - printf("Threshold %5.2e\n", - (double)(threshold)); - if( !waserrors ) - { - printf("TEST PASSED\n"); - } - else - { - printf("TEST FAILED\n"); - } - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - - - - - - - -ae_bool testlaguerre(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - double err; - double sumerr; - double cerr; - double threshold; - ae_int_t n; - ae_int_t maxn; - ae_int_t pass; - ae_vector c; - double x; - double v; - ae_bool waserrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&c, 0, sizeof(c)); - ae_vector_init(&c, 0, DT_REAL, _state, ae_true); - - err = (double)(0); - sumerr = (double)(0); - cerr = (double)(0); - threshold = 1.0E-9; - waserrors = ae_false; - - /* - * Testing Laguerre polynomials - */ - n = 0; - err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)-1.0000000000, _state), _state); - n = 1; - err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)-0.5000000000, _state), _state); - n = 2; - err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)-0.1250000000, _state), _state); - n = 3; - err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)+0.1458333333, _state), _state); - n = 4; - err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)+0.3307291667, _state), _state); - n = 5; - err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)+0.4455729167, _state), _state); - n = 6; - err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)+0.5041449653, _state), _state); - n = 7; - err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)+0.5183392237, _state), _state); - n = 8; - err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)+0.4983629984, _state), _state); - n = 9; - err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)+0.4529195204, _state), _state); - n = 10; - err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)+0.3893744141, _state), _state); - n = 11; - err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)+0.3139072988, _state), _state); - n = 12; - err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)+0.2316496389, _state), _state); - - /* - * Testing Clenshaw summation - */ - maxn = 20; - ae_vector_set_length(&c, maxn+1, _state); - for(pass=1; pass<=10; pass++) - { - x = 2*ae_randomreal(_state)-1; - v = (double)(0); - for(n=0; n<=maxn; n++) - { - c.ptr.p_double[n] = 2*ae_randomreal(_state)-1; - v = v+laguerrecalculate(n, x, _state)*c.ptr.p_double[n]; - sumerr = ae_maxreal(sumerr, ae_fabs(v-laguerresum(&c, n, x, _state), _state), _state); - } - } - - /* - * Testing coefficients - */ - laguerrecoefficients(0, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-1, _state), _state); - laguerrecoefficients(1, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-1, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]+1, _state), _state); - laguerrecoefficients(2, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-(double)2/(double)2, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]+(double)4/(double)2, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-(double)1/(double)2, _state), _state); - laguerrecoefficients(3, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-(double)6/(double)6, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]+(double)18/(double)6, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-(double)9/(double)6, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]+(double)1/(double)6, _state), _state); - laguerrecoefficients(4, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-(double)24/(double)24, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]+(double)96/(double)24, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-(double)72/(double)24, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]+(double)16/(double)24, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[4]-(double)1/(double)24, _state), _state); - laguerrecoefficients(5, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-(double)120/(double)120, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]+(double)600/(double)120, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-(double)600/(double)120, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]+(double)200/(double)120, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[4]-(double)25/(double)120, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[5]+(double)1/(double)120, _state), _state); - laguerrecoefficients(6, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-(double)720/(double)720, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]+(double)4320/(double)720, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-(double)5400/(double)720, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]+(double)2400/(double)720, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[4]-(double)450/(double)720, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[5]+(double)36/(double)720, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[6]-(double)1/(double)720, _state), _state); - - /* - * Reporting - */ - waserrors = (ae_fp_greater(err,threshold)||ae_fp_greater(sumerr,threshold))||ae_fp_greater(cerr,threshold); - if( !silent ) - { - printf("TESTING CALCULATION OF THE LAGUERRE POLYNOMIALS\n"); - printf("Max error %5.2e\n", - (double)(err)); - printf("Summation error %5.2e\n", - (double)(sumerr)); - printf("Coefficients error %5.2e\n", - (double)(cerr)); - printf("Threshold %5.2e\n", - (double)(threshold)); - if( !waserrors ) - { - printf("TEST PASSED\n"); - } - else - { - printf("TEST FAILED\n"); - } - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - - - - - - - -ae_bool testlegendre(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - double err; - double sumerr; - double cerr; - double threshold; - ae_int_t n; - ae_int_t maxn; - ae_int_t i; - ae_int_t pass; - ae_vector c; - double x; - double v; - double t; - ae_bool waserrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&c, 0, sizeof(c)); - ae_vector_init(&c, 0, DT_REAL, _state, ae_true); - - err = (double)(0); - sumerr = (double)(0); - cerr = (double)(0); - threshold = 1.0E-9; - waserrors = ae_false; - - /* - * Testing Legendre polynomials values - */ - for(n=0; n<=10; n++) - { - legendrecoefficients(n, &c, _state); - for(pass=1; pass<=10; pass++) - { - x = 2*ae_randomreal(_state)-1; - v = legendrecalculate(n, x, _state); - t = (double)(1); - for(i=0; i<=n; i++) - { - v = v-c.ptr.p_double[i]*t; - t = t*x; - } - err = ae_maxreal(err, ae_fabs(v, _state), _state); - } - } - - /* - * Testing Clenshaw summation - */ - maxn = 20; - ae_vector_set_length(&c, maxn+1, _state); - for(pass=1; pass<=10; pass++) - { - x = 2*ae_randomreal(_state)-1; - v = (double)(0); - for(n=0; n<=maxn; n++) - { - c.ptr.p_double[n] = 2*ae_randomreal(_state)-1; - v = v+legendrecalculate(n, x, _state)*c.ptr.p_double[n]; - sumerr = ae_maxreal(sumerr, ae_fabs(v-legendresum(&c, n, x, _state), _state), _state); - } - } - - /* - * Testing coefficients - */ - legendrecoefficients(0, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-1, _state), _state); - legendrecoefficients(1, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-1, _state), _state); - legendrecoefficients(2, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]+(double)1/(double)2, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-(double)3/(double)2, _state), _state); - legendrecoefficients(3, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]+(double)3/(double)2, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]-(double)5/(double)2, _state), _state); - legendrecoefficients(4, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-(double)3/(double)8, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]+(double)30/(double)8, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[4]-(double)35/(double)8, _state), _state); - legendrecoefficients(9, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-(double)315/(double)128, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]+(double)4620/(double)128, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[4]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[5]-(double)18018/(double)128, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[6]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[7]+(double)25740/(double)128, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[8]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[9]-(double)12155/(double)128, _state), _state); - - /* - * Reporting - */ - waserrors = (ae_fp_greater(err,threshold)||ae_fp_greater(sumerr,threshold))||ae_fp_greater(cerr,threshold); - if( !silent ) - { - printf("TESTING CALCULATION OF THE LEGENDRE POLYNOMIALS\n"); - printf("Max error %5.2e\n", - (double)(err)); - printf("Summation error %5.2e\n", - (double)(sumerr)); - printf("Coefficients error %5.2e\n", - (double)(cerr)); - printf("Threshold %5.2e\n", - (double)(threshold)); - if( !waserrors ) - { - printf("TEST PASSED\n"); - } - else - { - printf("TEST FAILED\n"); - } - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - - - - - - - -ae_bool testchebyshev(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - double err; - double sumerr; - double cerr; - double ferr; - double threshold; - double x; - double v; - ae_int_t pass; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t n; - ae_int_t maxn; - ae_vector c; - ae_vector p1; - ae_vector p2; - ae_matrix a; - ae_bool waserrors; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&c, 0, sizeof(c)); - memset(&p1, 0, sizeof(p1)); - memset(&p2, 0, sizeof(p2)); - memset(&a, 0, sizeof(a)); - ae_vector_init(&c, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p1, 0, DT_REAL, _state, ae_true); - ae_vector_init(&p2, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - - err = (double)(0); - sumerr = (double)(0); - cerr = (double)(0); - ferr = (double)(0); - threshold = 1.0E-9; - waserrors = ae_false; - - /* - * Testing Chebyshev polynomials of the first kind - */ - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 0, 0.00, _state)-1, _state), _state); - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 0, 0.33, _state)-1, _state), _state); - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 0, -0.42, _state)-1, _state), _state); - x = 0.2; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 1, x, _state)-0.2, _state), _state); - x = 0.4; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 1, x, _state)-0.4, _state), _state); - x = 0.6; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 1, x, _state)-0.6, _state), _state); - x = 0.8; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 1, x, _state)-0.8, _state), _state); - x = 1.0; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 1, x, _state)-1.0, _state), _state); - x = 0.2; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 2, x, _state)+0.92, _state), _state); - x = 0.4; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 2, x, _state)+0.68, _state), _state); - x = 0.6; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 2, x, _state)+0.28, _state), _state); - x = 0.8; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 2, x, _state)-0.28, _state), _state); - x = 1.0; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 2, x, _state)-1.00, _state), _state); - n = 10; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, n, 0.2, _state)-0.4284556288, _state), _state); - n = 11; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, n, 0.2, _state)+0.7996160205, _state), _state); - n = 12; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, n, 0.2, _state)+0.7483020370, _state), _state); - - /* - * Testing Chebyshev polynomials of the second kind - */ - n = 0; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(2, n, 0.2, _state)-1.0000000000, _state), _state); - n = 1; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(2, n, 0.2, _state)-0.4000000000, _state), _state); - n = 2; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(2, n, 0.2, _state)+0.8400000000, _state), _state); - n = 3; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(2, n, 0.2, _state)+0.7360000000, _state), _state); - n = 4; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(2, n, 0.2, _state)-0.5456000000, _state), _state); - n = 10; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(2, n, 0.2, _state)-0.6128946176, _state), _state); - n = 11; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(2, n, 0.2, _state)+0.6770370970, _state), _state); - n = 12; - err = ae_maxreal(err, ae_fabs(chebyshevcalculate(2, n, 0.2, _state)+0.8837094564, _state), _state); - - /* - * Testing Clenshaw summation - */ - maxn = 20; - ae_vector_set_length(&c, maxn+1, _state); - for(k=1; k<=2; k++) - { - for(pass=1; pass<=10; pass++) - { - x = 2*ae_randomreal(_state)-1; - v = (double)(0); - for(n=0; n<=maxn; n++) - { - c.ptr.p_double[n] = 2*ae_randomreal(_state)-1; - v = v+chebyshevcalculate(k, n, x, _state)*c.ptr.p_double[n]; - sumerr = ae_maxreal(sumerr, ae_fabs(v-chebyshevsum(&c, k, n, x, _state), _state), _state); - } - } - } - - /* - * Testing coefficients - */ - chebyshevcoefficients(0, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-1, _state), _state); - chebyshevcoefficients(1, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-1, _state), _state); - chebyshevcoefficients(2, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]+1, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-2, _state), _state); - chebyshevcoefficients(3, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]+3, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]-4, _state), _state); - chebyshevcoefficients(4, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-1, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]+8, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[4]-8, _state), _state); - chebyshevcoefficients(9, &c, _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-9, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]+120, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[4]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[5]-432, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[6]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[7]+576, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[8]-0, _state), _state); - cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[9]-256, _state), _state); - - /* - * Testing FromChebyshev - */ - maxn = 10; - ae_matrix_set_length(&a, maxn+1, maxn+1, _state); - for(i=0; i<=maxn; i++) - { - for(j=0; j<=maxn; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - chebyshevcoefficients(i, &c, _state); - ae_v_move(&a.ptr.pp_double[i][0], 1, &c.ptr.p_double[0], 1, ae_v_len(0,i)); - } - ae_vector_set_length(&c, maxn+1, _state); - ae_vector_set_length(&p1, maxn+1, _state); - for(n=0; n<=maxn; n++) - { - for(pass=1; pass<=10; pass++) - { - for(i=0; i<=n; i++) - { - p1.ptr.p_double[i] = (double)(0); - } - for(i=0; i<=n; i++) - { - c.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - v = c.ptr.p_double[i]; - ae_v_addd(&p1.ptr.p_double[0], 1, &a.ptr.pp_double[i][0], 1, ae_v_len(0,i), v); - } - fromchebyshev(&c, n, &p2, _state); - for(i=0; i<=n; i++) - { - ferr = ae_maxreal(ferr, ae_fabs(p1.ptr.p_double[i]-p2.ptr.p_double[i], _state), _state); - } - } - } - - /* - * Reporting - */ - waserrors = ((ae_fp_greater(err,threshold)||ae_fp_greater(sumerr,threshold))||ae_fp_greater(cerr,threshold))||ae_fp_greater(ferr,threshold); - if( !silent ) - { - printf("TESTING CALCULATION OF THE CHEBYSHEV POLYNOMIALS\n"); - printf("Max error against table %5.2e\n", - (double)(err)); - printf("Summation error %5.2e\n", - (double)(sumerr)); - printf("Coefficients error %5.2e\n", - (double)(cerr)); - printf("FrobChebyshev error %5.2e\n", - (double)(ferr)); - printf("Threshold %5.2e\n", - (double)(threshold)); - if( !waserrors ) - { - printf("TEST PASSED\n"); - } - else - { - printf("TEST FAILED\n"); - } - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - - - - - - - -ae_bool testwsr(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_bool waserrors; - ae_vector xa; - ae_int_t n; - ae_int_t i; - double taill; - double tailr; - double tailb; - double taillprev; - double tailrprev; - double ebase; - double eshift; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&xa, 0, sizeof(xa)); - ae_vector_init(&xa, 0, DT_REAL, _state, ae_true); - - waserrors = ae_false; - - /* - * Test monotonicity of tail values for moving value of E - */ - for(n=5; n<=50; n++) - { - - /* - * Generate uniform and sorted X spanning [0,1] - */ - ae_vector_set_length(&xa, n, _state); - for(i=0; i<=n-1; i++) - { - xa.ptr.p_double[i] = (double)i/(double)(n-1); - } - - /* - * Test N+1 values of E - */ - ebase = -0.5/(n-1); - eshift = (double)1/(double)(n-1); - tailrprev = (double)(0); - taillprev = (double)(1); - for(i=0; i<=n; i++) - { - wilcoxonsignedranktest(&xa, n, ebase+eshift*i, &tailb, &taill, &tailr, _state); - ae_set_error_flag(&waserrors, ae_fp_neq(tailb,2*ae_minreal(taill, tailr, _state)), __FILE__, __LINE__, "testwsrunit.ap:42"); - ae_set_error_flag(&waserrors, ae_fp_greater(tailrprev,tailr), __FILE__, __LINE__, "testwsrunit.ap:43"); - ae_set_error_flag(&waserrors, ae_fp_less(taillprev,taill), __FILE__, __LINE__, "testwsrunit.ap:44"); - tailrprev = tailr; - taillprev = taill; - } - } - - /* - * Test for integer overflow in the function: if one crucial - * calculation step is performed in 32-bit integer arithmetics, - * it will return incorrect results. - * - * We use special handcrafted N, such that in 32-bit integer - * arithmetics int32(N*N)<0. Such negative N leads to domain - * error in the sqrt() function. - */ - n = 50000; - ae_vector_set_length(&xa, n, _state); - for(i=0; i<=n-1; i++) - { - xa.ptr.p_double[i] = ae_sin((double)(10*i), _state); - } - wilcoxonsignedranktest(&xa, n, 0.0, &tailb, &taill, &tailr, _state); - ae_set_error_flag(&waserrors, !ae_isfinite(tailb, _state), __FILE__, __LINE__, "testwsrunit.ap:64"); - ae_set_error_flag(&waserrors, !ae_isfinite(taill, _state), __FILE__, __LINE__, "testwsrunit.ap:65"); - ae_set_error_flag(&waserrors, !ae_isfinite(tailr, _state), __FILE__, __LINE__, "testwsrunit.ap:66"); - - /* - * - */ - if( !silent ) - { - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - - - - - - - -ae_bool teststest(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_vector x; - double taill; - double tailr; - double tailb; - ae_bool waserrors; - double eps; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - - waserrors = ae_false; - eps = 1.0E-3; - - /* - * Test 1 - */ - ae_vector_set_length(&x, 6, _state); - x.ptr.p_double[0] = (double)(-3); - x.ptr.p_double[1] = (double)(-2); - x.ptr.p_double[2] = (double)(-1); - x.ptr.p_double[3] = (double)(1); - x.ptr.p_double[4] = (double)(2); - x.ptr.p_double[5] = (double)(3); - onesamplesigntest(&x, 6, 0.0, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_greater(ae_fabs(taill-0.65625, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.65625, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-1.00000, _state),eps); - onesamplesigntest(&x, 6, -1.0, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_greater(ae_fabs(taill-0.81250, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.50000, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-1.00000, _state),eps); - onesamplesigntest(&x, 6, -1.5, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_greater(ae_fabs(taill-0.89062, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.34375, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-0.68750, _state),eps); - onesamplesigntest(&x, 6, -3.0, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_greater(ae_fabs(taill-1.00000, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.03125, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-0.06250, _state),eps); - - /* - * Test 2 - */ - ae_vector_set_length(&x, 3, _state); - x.ptr.p_double[0] = (double)(2); - x.ptr.p_double[1] = (double)(2); - x.ptr.p_double[2] = (double)(2); - onesamplesigntest(&x, 3, 2.0, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(taill,(double)(1)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(1)); - waserrors = waserrors||ae_fp_neq(tailb,(double)(1)); - - /* - * Final report - */ - if( !silent ) - { - printf("SIGN TEST: "); - if( !waserrors ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - if( waserrors ) - { - printf("TEST SUMMARY: FAILED\n"); - } - else - { - printf("TEST SUMMARY: PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - - - - - - - -ae_bool teststudentttests(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_bool waserrors; - double eps; - ae_vector x; - ae_vector y; - ae_vector xa; - ae_vector ya; - ae_vector xb; - ae_vector yb; - ae_int_t n; - ae_int_t i; - double taill; - double tailr; - double tailb; - double taill1; - double tailr1; - double tailb1; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&xa, 0, sizeof(xa)); - memset(&ya, 0, sizeof(ya)); - memset(&xb, 0, sizeof(xb)); - memset(&yb, 0, sizeof(yb)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xa, 0, DT_REAL, _state, ae_true); - ae_vector_init(&ya, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xb, 0, DT_REAL, _state, ae_true); - ae_vector_init(&yb, 0, DT_REAL, _state, ae_true); - - waserrors = ae_false; - eps = 0.001; - - /* - * 1-sample test - */ - n = 8; - ae_vector_set_length(&x, 8, _state); - x.ptr.p_double[0] = -3.0; - x.ptr.p_double[1] = -1.5; - x.ptr.p_double[2] = -1.0; - x.ptr.p_double[3] = -0.5; - x.ptr.p_double[4] = 0.5; - x.ptr.p_double[5] = 1.0; - x.ptr.p_double[6] = 1.5; - x.ptr.p_double[7] = 3.0; - studentttest1(&x, n, 0.0, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-1.00000, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(taill-0.50000, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.50000, _state),eps); - studentttest1(&x, n, 1.0, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-0.17816, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(taill-0.08908, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.91092, _state),eps); - studentttest1(&x, n, -1.0, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-0.17816, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(taill-0.91092, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.08908, _state),eps); - x.ptr.p_double[0] = 1.1; - x.ptr.p_double[1] = 1.1; - x.ptr.p_double[2] = 1.1; - x.ptr.p_double[3] = 1.1; - x.ptr.p_double[4] = 1.1; - x.ptr.p_double[5] = 1.1; - x.ptr.p_double[6] = 1.1; - x.ptr.p_double[7] = 1.1; - studentttest1(&x, n, 1.1, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(tailb,(double)(1)); - waserrors = waserrors||ae_fp_neq(taill,(double)(1)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(1)); - studentttest1(&x, n, 0.0, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(tailb,(double)(0)); - waserrors = waserrors||ae_fp_neq(taill,(double)(1)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(0)); - x.ptr.p_double[7] = 1.1; - studentttest1(&x, 1, 1.1, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(tailb,(double)(1)); - waserrors = waserrors||ae_fp_neq(taill,(double)(1)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(1)); - studentttest1(&x, 1, 0.0, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(tailb,(double)(0)); - waserrors = waserrors||ae_fp_neq(taill,(double)(1)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(0)); - - /* - * 2-sample pooled (equal variance) test - */ - n = 8; - ae_vector_set_length(&x, 8, _state); - ae_vector_set_length(&y, 8, _state); - x.ptr.p_double[0] = -3.0; - x.ptr.p_double[1] = -1.5; - x.ptr.p_double[2] = -1.0; - x.ptr.p_double[3] = -0.5; - x.ptr.p_double[4] = 0.5; - x.ptr.p_double[5] = 1.0; - x.ptr.p_double[6] = 1.5; - x.ptr.p_double[7] = 3.0; - y.ptr.p_double[0] = -2.0; - y.ptr.p_double[1] = -0.5; - y.ptr.p_double[2] = 0.0; - y.ptr.p_double[3] = 0.5; - y.ptr.p_double[4] = 1.5; - y.ptr.p_double[5] = 2.0; - y.ptr.p_double[6] = 2.5; - y.ptr.p_double[7] = 4.0; - studentttest2(&x, n, &y, n, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-0.30780, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(taill-0.15390, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.84610, _state),eps); - studentttest2(&x, n, &y, n-1, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-0.53853, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(taill-0.26927, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.73074, _state),eps); - studentttest2(&x, n-1, &y, n, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-0.13829, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(taill-0.06915, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.93086, _state),eps); - x.ptr.p_double[0] = -1.0; - x.ptr.p_double[1] = -1.0; - x.ptr.p_double[2] = -1.0; - x.ptr.p_double[3] = -1.0; - x.ptr.p_double[4] = -1.0; - x.ptr.p_double[5] = -1.0; - x.ptr.p_double[6] = -1.0; - x.ptr.p_double[7] = -1.0; - y.ptr.p_double[0] = 1.0; - y.ptr.p_double[1] = 1.0; - y.ptr.p_double[2] = 1.0; - y.ptr.p_double[3] = 1.0; - y.ptr.p_double[4] = 1.0; - y.ptr.p_double[5] = 1.0; - y.ptr.p_double[6] = 1.0; - y.ptr.p_double[7] = 1.0; - studentttest2(&x, n, &y, n, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(tailb,(double)(0)); - waserrors = waserrors||ae_fp_neq(taill,(double)(0)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(1)); - studentttest2(&x, n, &y, n-1, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(tailb,(double)(0)); - waserrors = waserrors||ae_fp_neq(taill,(double)(0)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(1)); - studentttest2(&x, n, &y, 1, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(tailb,(double)(0)); - waserrors = waserrors||ae_fp_neq(taill,(double)(0)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(1)); - studentttest2(&x, n-1, &y, n, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(tailb,(double)(0)); - waserrors = waserrors||ae_fp_neq(taill,(double)(0)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(1)); - studentttest2(&x, 1, &y, n, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(tailb,(double)(0)); - waserrors = waserrors||ae_fp_neq(taill,(double)(0)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(1)); - studentttest2(&x, 1, &y, 1, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(tailb,(double)(0)); - waserrors = waserrors||ae_fp_neq(taill,(double)(0)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(1)); - studentttest2(&y, 1, &x, 1, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(tailb,(double)(0)); - waserrors = waserrors||ae_fp_neq(taill,(double)(1)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(0)); - x.ptr.p_double[0] = 1.1; - x.ptr.p_double[1] = 1.1; - x.ptr.p_double[2] = 1.1; - x.ptr.p_double[3] = 1.1; - x.ptr.p_double[4] = 1.1; - x.ptr.p_double[5] = 1.1; - x.ptr.p_double[6] = 1.1; - x.ptr.p_double[7] = 1.1; - y.ptr.p_double[0] = 1.1; - y.ptr.p_double[1] = 1.1; - y.ptr.p_double[2] = 1.1; - y.ptr.p_double[3] = 1.1; - y.ptr.p_double[4] = 1.1; - y.ptr.p_double[5] = 1.1; - y.ptr.p_double[6] = 1.1; - y.ptr.p_double[7] = 1.1; - studentttest2(&x, n, &y, n, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(tailb,(double)(1)); - waserrors = waserrors||ae_fp_neq(taill,(double)(1)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(1)); - studentttest2(&x, n, &y, n-1, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(tailb,(double)(1)); - waserrors = waserrors||ae_fp_neq(taill,(double)(1)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(1)); - studentttest2(&x, n, &y, 1, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(tailb,(double)(1)); - waserrors = waserrors||ae_fp_neq(taill,(double)(1)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(1)); - studentttest2(&x, n-1, &y, n, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(tailb,(double)(1)); - waserrors = waserrors||ae_fp_neq(taill,(double)(1)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(1)); - studentttest2(&x, 1, &y, n, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(tailb,(double)(1)); - waserrors = waserrors||ae_fp_neq(taill,(double)(1)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(1)); - studentttest2(&x, 1, &y, 1, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(tailb,(double)(1)); - waserrors = waserrors||ae_fp_neq(taill,(double)(1)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(1)); - - /* - * 2-sample unpooled (unequal variance) test: - * * test on two non-constant samples - * * tests on different combinations of non-constant and constant samples - */ - n = 8; - ae_vector_set_length(&xa, 8, _state); - ae_vector_set_length(&ya, 8, _state); - ae_vector_set_length(&xb, 8, _state); - ae_vector_set_length(&yb, 8, _state); - xa.ptr.p_double[0] = -3.0; - xa.ptr.p_double[1] = -1.5; - xa.ptr.p_double[2] = -1.0; - xa.ptr.p_double[3] = -0.5; - xa.ptr.p_double[4] = 0.5; - xa.ptr.p_double[5] = 1.0; - xa.ptr.p_double[6] = 1.5; - xa.ptr.p_double[7] = 3.0; - ya.ptr.p_double[0] = -1.0; - ya.ptr.p_double[1] = -0.5; - ya.ptr.p_double[2] = 0.0; - ya.ptr.p_double[3] = 0.5; - ya.ptr.p_double[4] = 1.5; - ya.ptr.p_double[5] = 2.0; - ya.ptr.p_double[6] = 2.5; - ya.ptr.p_double[7] = 3.0; - xb.ptr.p_double[0] = -1.1; - xb.ptr.p_double[1] = -1.1; - xb.ptr.p_double[2] = -1.1; - xb.ptr.p_double[3] = -1.1; - xb.ptr.p_double[4] = -1.1; - xb.ptr.p_double[5] = -1.1; - xb.ptr.p_double[6] = -1.1; - xb.ptr.p_double[7] = -1.1; - yb.ptr.p_double[0] = 1.1; - yb.ptr.p_double[1] = 1.1; - yb.ptr.p_double[2] = 1.1; - yb.ptr.p_double[3] = 1.1; - yb.ptr.p_double[4] = 1.1; - yb.ptr.p_double[5] = 1.1; - yb.ptr.p_double[6] = 1.1; - yb.ptr.p_double[7] = 1.1; - unequalvariancettest(&xa, n, &ya, n, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-0.25791, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(taill-0.12896, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.87105, _state),eps); - unequalvariancettest(&xa, n, &yb, n, &tailb, &taill, &tailr, _state); - studentttest1(&xa, n, 1.1, &tailb1, &taill1, &tailr1, _state); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-tailb1, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(taill-taill1, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-tailr1, _state),eps); - unequalvariancettest(&xa, n, &yb, 1, &tailb, &taill, &tailr, _state); - studentttest1(&xa, n, 1.1, &tailb1, &taill1, &tailr1, _state); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-tailb1, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(taill-taill1, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-tailr1, _state),eps); - unequalvariancettest(&xb, n, &ya, n, &tailb, &taill, &tailr, _state); - studentttest1(&ya, n, -1.1, &tailb1, &taill1, &tailr1, _state); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-tailb1, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(taill-tailr1, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-taill1, _state),eps); - unequalvariancettest(&xb, 1, &ya, n, &tailb, &taill, &tailr, _state); - studentttest1(&ya, n, -1.1, &tailb1, &taill1, &tailr1, _state); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-tailb1, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(taill-tailr1, _state),eps); - waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-taill1, _state),eps); - unequalvariancettest(&xb, 1, &yb, 1, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(tailb,(double)(0)); - waserrors = waserrors||ae_fp_neq(taill,(double)(0)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(1)); - unequalvariancettest(&yb, 1, &xb, 1, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(tailb,(double)(0)); - waserrors = waserrors||ae_fp_neq(taill,(double)(1)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(0)); - unequalvariancettest(&xb, 1, &xb, 1, &tailb, &taill, &tailr, _state); - waserrors = waserrors||ae_fp_neq(tailb,(double)(1)); - waserrors = waserrors||ae_fp_neq(taill,(double)(1)); - waserrors = waserrors||ae_fp_neq(tailr,(double)(1)); - - /* - * Test for integer overflow in the function: if one crucial - * calculation step is performed in 32-bit integer arithmetics, - * it will return incorrect results. - * - * We use special handcrafted N, such that in 32-bit integer - * arithmetics int32(N*N)<0. Such negative N leads to domain - * error in the incomplete beta function. - */ - n = 50000; - ae_vector_set_length(&xa, n, _state); - ae_vector_set_length(&ya, n, _state); - for(i=0; i<=n-1; i++) - { - xa.ptr.p_double[i] = ae_randomreal(_state); - ya.ptr.p_double[i] = ae_randomreal(_state); - } - unequalvariancettest(&xa, n, &ya, n, &tailb, &taill, &tailr, _state); - - /* - * - */ - if( !silent ) - { - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - - - - - - - -ae_bool testmannwhitneyu(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_bool waserrors; - ae_vector x; - ae_vector y; - ae_int_t testmin; - ae_int_t testmax; - ae_int_t testcnt; - ae_int_t pass; - ae_int_t n; - ae_int_t m; - ae_int_t i; - ae_int_t k; - double taill; - double tailr; - double tailb; - double taill1; - double tailr1; - double tailb1; - double taillprev; - double tailrprev; - double ebase; - double eshift; - ae_int_t ecnt; - double worsterr; - double v; - hqrndstate rs; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&y, 0, sizeof(y)); - memset(&rs, 0, sizeof(rs)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&y, 0, DT_REAL, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - waserrors = ae_false; - hqrndrandomize(&rs, _state); - - /* - * Test monotonicity of tail values for monotinically moving distributions. - */ - for(n=5; n<=20; n++) - { - for(m=5; m<=20; m++) - { - - /* - * Generate uniform and sorted X/Y spanning [0,1] - */ - ae_vector_set_length(&x, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = (double)i/(double)(n-1)+100*ae_machineepsilon*hqrndnormal(&rs, _state); - } - ae_vector_set_length(&y, m, _state); - for(i=0; i<=m-1; i++) - { - y.ptr.p_double[i] = (double)i/(double)(m-1)+100*ae_machineepsilon*hqrndnormal(&rs, _state); - } - - /* - * Test 100 values of E - */ - ecnt = 100; - ebase = -1.1; - eshift = -2*ebase/(ecnt-1); - tailrprev = (double)(0); - taillprev = (double)(1); - for(i=0; i<=m-1; i++) - { - y.ptr.p_double[i] = y.ptr.p_double[i]+ebase; - } - for(k=0; k<=ecnt-1; k++) - { - mannwhitneyutest(&x, n, &y, m, &tailb, &taill, &tailr, _state); - ae_set_error_flag(&waserrors, ae_fp_neq(tailb,2*ae_minreal(taill, tailr, _state)), __FILE__, __LINE__, "testmannwhitneyuunit.ap:57"); - ae_set_error_flag(&waserrors, ae_fp_greater(tailrprev,tailr), __FILE__, __LINE__, "testmannwhitneyuunit.ap:58"); - ae_set_error_flag(&waserrors, ae_fp_less(taillprev,taill), __FILE__, __LINE__, "testmannwhitneyuunit.ap:59"); - tailrprev = tailr; - taillprev = taill; - for(i=0; i<=m-1; i++) - { - y.ptr.p_double[i] = y.ptr.p_double[i]+eshift; - } - } - } - } - - /* - * Test frequency of p-value 0.05 - */ - testmin = 5; - testmax = 50; - testcnt = 10000; - worsterr = 0.0; - for(n=testmin; n<=testmax; n++) - { - m = n+hqrnduniformi(&rs, testmax-n+1, _state); - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, m, _state); - - /* - * Generate two uniformly distributed values, calculate p-value for both-tails, repeat - */ - k = 0; - for(pass=0; pass<=testcnt-1; pass++) - { - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = hqrnduniformr(&rs, _state); - } - for(i=0; i<=m-1; i++) - { - y.ptr.p_double[i] = hqrnduniformr(&rs, _state); - } - mannwhitneyutest(&x, n, &y, m, &tailb, &taill, &tailr, _state); - if( ae_fp_less(tailb,0.05) ) - { - k = k+1; - } - } - v = ae_fabs((double)k/(double)testcnt-0.05, _state); - worsterr = ae_maxreal(worsterr, v, _state); - - /* - * Test error in quantile; for different N's we have different tolerances - */ - if( n<10 ) - { - ae_set_error_flag(&waserrors, ae_fp_greater(v,0.030), __FILE__, __LINE__, "testmannwhitneyuunit.ap:101"); - } - else - { - if( n<15 ) - { - ae_set_error_flag(&waserrors, ae_fp_greater(v,0.020), __FILE__, __LINE__, "testmannwhitneyuunit.ap:103"); - } - else - { - if( n<30 ) - { - ae_set_error_flag(&waserrors, ae_fp_greater(v,0.015), __FILE__, __LINE__, "testmannwhitneyuunit.ap:105"); - } - else - { - ae_set_error_flag(&waserrors, ae_fp_greater(v,0.010), __FILE__, __LINE__, "testmannwhitneyuunit.ap:107"); - } - } - } - } - - /* - * Test symmetry properties - */ - for(n=5; n<=50; n++) - { - for(m=5; m<=50; m++) - { - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, m, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = hqrnduniformr(&rs, _state); - } - for(i=0; i<=m-1; i++) - { - y.ptr.p_double[i] = hqrnduniformr(&rs, _state); - } - mannwhitneyutest(&x, n, &y, m, &tailb, &taill, &tailr, _state); - mannwhitneyutest(&y, m, &x, n, &tailb1, &taill1, &tailr1, _state); - ae_set_error_flag(&waserrors, ae_fp_greater(ae_fabs(tailb-tailb1, _state),1.0E-12), __FILE__, __LINE__, "testmannwhitneyuunit.ap:126"); - ae_set_error_flag(&waserrors, ae_fp_greater(ae_fabs(taill-tailr1, _state),1.0E-12), __FILE__, __LINE__, "testmannwhitneyuunit.ap:127"); - ae_set_error_flag(&waserrors, ae_fp_greater(ae_fabs(tailr-taill1, _state),1.0E-12), __FILE__, __LINE__, "testmannwhitneyuunit.ap:128"); - } - } - - /* - * Test for integer overflow in the function: if one crucial - * calculation step is performed in 32-bit integer arithmetics, - * it will return incorrect results. - * - * We use special handcrafted N, such that in 32-bit integer - * arithmetics int32(N*N)<0. Such negative N leads to domain - * error in the sqrt() function. - */ - n = 50000; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&y, n, _state); - for(i=0; i<=n-1; i++) - { - x.ptr.p_double[i] = ae_sin((double)(10*i), _state); - y.ptr.p_double[i] = ae_sin((double)(13*i), _state); - } - mannwhitneyutest(&x, n, &y, n, &tailb, &taill, &tailr, _state); - ae_set_error_flag(&waserrors, !ae_isfinite(tailb, _state), __FILE__, __LINE__, "testmannwhitneyuunit.ap:149"); - ae_set_error_flag(&waserrors, !ae_isfinite(taill, _state), __FILE__, __LINE__, "testmannwhitneyuunit.ap:150"); - ae_set_error_flag(&waserrors, !ae_isfinite(tailr, _state), __FILE__, __LINE__, "testmannwhitneyuunit.ap:151"); - - /* - * - */ - if( !silent ) - { - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - - -static void testschurunit_testschurproblem(/* Real */ ae_matrix* a, - ae_int_t n, - double* materr, - double* orterr, - ae_bool* errstruct, - ae_bool* wfailed, - ae_state *_state); - - - - - -/************************************************************************* -Testing Schur decomposition subroutine -*************************************************************************/ -ae_bool testschur(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix a; - ae_int_t n; - ae_int_t maxn; - ae_int_t i; - ae_int_t j; - ae_int_t pass; - ae_int_t passcount; - ae_bool waserrors; - ae_bool errstruct; - ae_bool wfailed; - double materr; - double orterr; - double threshold; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - - materr = (double)(0); - orterr = (double)(0); - errstruct = ae_false; - wfailed = ae_false; - waserrors = ae_false; - maxn = 70; - passcount = 1; - threshold = 5*100*ae_machineepsilon; - ae_matrix_set_length(&a, maxn-1+1, maxn-1+1, _state); - - /* - * zero matrix, several cases - */ - for(i=0; i<=maxn-1; i++) - { - for(j=0; j<=maxn-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - for(n=1; n<=maxn; n++) - { - if( n>30&&n%2==0 ) - { - continue; - } - testschurunit_testschurproblem(&a, n, &materr, &orterr, &errstruct, &wfailed, _state); - } - - /* - * Dense matrix - */ - for(pass=1; pass<=passcount; pass++) - { - for(n=1; n<=maxn; n++) - { - if( n>30&&n%2==0 ) - { - continue; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - } - } - testschurunit_testschurproblem(&a, n, &materr, &orterr, &errstruct, &wfailed, _state); - } - } - - /* - * report - */ - waserrors = ((ae_fp_greater(materr,threshold)||ae_fp_greater(orterr,threshold))||errstruct)||wfailed; - if( !silent ) - { - printf("TESTING SCHUR DECOMPOSITION\n"); - printf("Schur decomposition error: %5.3e\n", - (double)(materr)); - printf("Schur orthogonality error: %5.3e\n", - (double)(orterr)); - printf("T matrix structure: "); - if( !errstruct ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("Always converged: "); - if( !wfailed ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("Threshold: %5.3e\n", - (double)(threshold)); - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -static void testschurunit_testschurproblem(/* Real */ ae_matrix* a, - ae_int_t n, - double* materr, - double* orterr, - ae_bool* errstruct, - ae_bool* wfailed, - ae_state *_state) -{ - ae_frame _frame_block; - ae_matrix s; - ae_matrix t; - ae_vector sr; - ae_vector astc; - ae_vector sastc; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double v; - double locerr; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&t, 0, sizeof(t)); - memset(&sr, 0, sizeof(sr)); - memset(&astc, 0, sizeof(astc)); - memset(&sastc, 0, sizeof(sastc)); - ae_matrix_init(&s, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&t, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sr, 0, DT_REAL, _state, ae_true); - ae_vector_init(&astc, 0, DT_REAL, _state, ae_true); - ae_vector_init(&sastc, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&sr, n-1+1, _state); - ae_vector_set_length(&astc, n-1+1, _state); - ae_vector_set_length(&sastc, n-1+1, _state); - - /* - * Schur decomposition, convergence test - */ - ae_matrix_set_length(&t, n-1+1, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - t.ptr.pp_double[i][j] = a->ptr.pp_double[i][j]; - } - } - if( !rmatrixschur(&t, n, &s, _state) ) - { - *wfailed = ae_true; - ae_frame_leave(_state); - return; - } - - /* - * decomposition error - */ - locerr = (double)(0); - for(j=0; j<=n-1; j++) - { - ae_v_move(&sr.ptr.p_double[0], 1, &s.ptr.pp_double[j][0], 1, ae_v_len(0,n-1)); - for(k=0; k<=n-1; k++) - { - v = ae_v_dotproduct(&t.ptr.pp_double[k][0], 1, &sr.ptr.p_double[0], 1, ae_v_len(0,n-1)); - astc.ptr.p_double[k] = v; - } - for(k=0; k<=n-1; k++) - { - v = ae_v_dotproduct(&s.ptr.pp_double[k][0], 1, &astc.ptr.p_double[0], 1, ae_v_len(0,n-1)); - sastc.ptr.p_double[k] = v; - } - for(k=0; k<=n-1; k++) - { - locerr = ae_maxreal(locerr, ae_fabs(sastc.ptr.p_double[k]-a->ptr.pp_double[k][j], _state), _state); - } - } - *materr = ae_maxreal(*materr, locerr, _state); - - /* - * orthogonality error - */ - locerr = (double)(0); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - v = ae_v_dotproduct(&s.ptr.pp_double[0][i], s.stride, &s.ptr.pp_double[0][j], s.stride, ae_v_len(0,n-1)); - if( i!=j ) - { - locerr = ae_maxreal(locerr, ae_fabs(v, _state), _state); - } - else - { - locerr = ae_maxreal(locerr, ae_fabs(v-1, _state), _state); - } - } - } - *orterr = ae_maxreal(*orterr, locerr, _state); - - /* - * T matrix structure - */ - for(j=0; j<=n-1; j++) - { - for(i=j+2; i<=n-1; i++) - { - if( ae_fp_neq(t.ptr.pp_double[i][j],(double)(0)) ) - { - *errstruct = ae_true; - } - } - } - ae_frame_leave(_state); -} - - - - - - - - -/************************************************************************* -Testing bidiagonal SVD decomposition subroutine -*************************************************************************/ -ae_bool testspdgevd(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t pass; - ae_int_t n; - ae_int_t passcount; - ae_int_t maxn; - ae_int_t atask; - ae_int_t btask; - ae_vector d; - ae_vector t1; - ae_matrix a; - ae_matrix b; - ae_matrix afull; - ae_matrix bfull; - ae_matrix l; - ae_matrix z; - ae_bool isuppera; - ae_bool isupperb; - ae_int_t i; - ae_int_t j; - ae_int_t minij; - double v; - double v1; - double v2; - double err; - double valerr; - double threshold; - ae_bool waserrors; - ae_bool wfailed; - ae_bool wnsorted; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&d, 0, sizeof(d)); - memset(&t1, 0, sizeof(t1)); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - memset(&afull, 0, sizeof(afull)); - memset(&bfull, 0, sizeof(bfull)); - memset(&l, 0, sizeof(l)); - memset(&z, 0, sizeof(z)); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&t1, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&afull, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&bfull, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&l, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true); - - threshold = 10000*ae_machineepsilon; - valerr = (double)(0); - wfailed = ae_false; - wnsorted = ae_false; - maxn = 20; - passcount = 5; - - /* - * Main cycle - */ - for(n=1; n<=maxn; n++) - { - for(pass=1; pass<=passcount; pass++) - { - for(atask=0; atask<=1; atask++) - { - for(btask=0; btask<=1; btask++) - { - isuppera = atask==0; - isupperb = btask==0; - - /* - * Initialize A, B, AFull, BFull - */ - ae_vector_set_length(&t1, n-1+1, _state); - ae_matrix_set_length(&a, n-1+1, n-1+1, _state); - ae_matrix_set_length(&b, n-1+1, n-1+1, _state); - ae_matrix_set_length(&afull, n-1+1, n-1+1, _state); - ae_matrix_set_length(&bfull, n-1+1, n-1+1, _state); - ae_matrix_set_length(&l, n-1+1, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1; - a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j]; - afull.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]; - afull.ptr.pp_double[j][i] = a.ptr.pp_double[i][j]; - } - } - for(i=0; i<=n-1; i++) - { - for(j=i+1; j<=n-1; j++) - { - l.ptr.pp_double[i][j] = ae_randomreal(_state); - l.ptr.pp_double[j][i] = l.ptr.pp_double[i][j]; - } - l.ptr.pp_double[i][i] = 1.5+ae_randomreal(_state); - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - minij = ae_minint(i, j, _state); - v = ae_v_dotproduct(&l.ptr.pp_double[i][0], 1, &l.ptr.pp_double[0][j], l.stride, ae_v_len(0,minij)); - b.ptr.pp_double[i][j] = v; - b.ptr.pp_double[j][i] = v; - bfull.ptr.pp_double[i][j] = v; - bfull.ptr.pp_double[j][i] = v; - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( isuppera ) - { - if( jptr.pp_double[i][j] = a->ptr.pp_double[i][j]; - } - } -} - - -/************************************************************************* -LU decomposition -*************************************************************************/ -static void testinverseupdateunit_matlu(/* Real */ ae_matrix* a, - ae_int_t m, - ae_int_t n, - /* Integer */ ae_vector* pivots, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - ae_int_t j; - ae_int_t jp; - ae_vector t1; - double s; - - ae_frame_make(_state, &_frame_block); - memset(&t1, 0, sizeof(t1)); - ae_vector_clear(pivots); - ae_vector_init(&t1, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(pivots, ae_minint(m-1, n-1, _state)+1, _state); - ae_vector_set_length(&t1, ae_maxint(m-1, n-1, _state)+1, _state); - ae_assert(m>=0&&n>=0, "Error in LUDecomposition: incorrect function arguments", _state); - - /* - * Quick return if possible - */ - if( m==0||n==0 ) - { - ae_frame_leave(_state); - return; - } - for(j=0; j<=ae_minint(m-1, n-1, _state); j++) - { - - /* - * Find pivot and test for singularity. - */ - jp = j; - for(i=j+1; i<=m-1; i++) - { - if( ae_fp_greater(ae_fabs(a->ptr.pp_double[i][j], _state),ae_fabs(a->ptr.pp_double[jp][j], _state)) ) - { - jp = i; - } - } - pivots->ptr.p_int[j] = jp; - if( ae_fp_neq(a->ptr.pp_double[jp][j],(double)(0)) ) - { - - /* - *Apply the interchange to rows - */ - if( jp!=j ) - { - ae_v_move(&t1.ptr.p_double[0], 1, &a->ptr.pp_double[j][0], 1, ae_v_len(0,n-1)); - ae_v_move(&a->ptr.pp_double[j][0], 1, &a->ptr.pp_double[jp][0], 1, ae_v_len(0,n-1)); - ae_v_move(&a->ptr.pp_double[jp][0], 1, &t1.ptr.p_double[0], 1, ae_v_len(0,n-1)); - } - - /* - *Compute elements J+1:M of J-th column. - */ - if( j+1ptr.pp_double[j][j]; - ae_v_muld(&a->ptr.pp_double[jp][j], a->stride, ae_v_len(jp,m-1), s); - } - } - if( jptr.pp_double[i][j]; - ae_v_subd(&a->ptr.pp_double[i][jp], 1, &a->ptr.pp_double[j][jp], 1, ae_v_len(jp,n-1), s); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Generate matrix with given condition number C (2-norm) -*************************************************************************/ -static void testinverseupdateunit_generaterandomorthogonalmatrix(/* Real */ ae_matrix* a0, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - double t; - double lambdav; - ae_int_t s; - ae_int_t i; - ae_int_t j; - double u1; - double u2; - ae_vector w; - ae_vector v; - ae_matrix a; - double sm; - - ae_frame_make(_state, &_frame_block); - memset(&w, 0, sizeof(w)); - memset(&v, 0, sizeof(v)); - memset(&a, 0, sizeof(a)); - ae_vector_init(&w, 0, DT_REAL, _state, ae_true); - ae_vector_init(&v, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - - if( n<=0 ) - { - ae_frame_leave(_state); - return; - } - ae_vector_set_length(&w, n+1, _state); - ae_vector_set_length(&v, n+1, _state); - ae_matrix_set_length(&a, n+1, n+1, _state); - ae_matrix_set_length(a0, n-1+1, n-1+1, _state); - - /* - * Prepare A - */ - for(i=1; i<=n; i++) - { - for(j=1; j<=n; j++) - { - if( i==j ) - { - a.ptr.pp_double[i][j] = (double)(1); - } - else - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - } - - /* - * Calculate A using Stewart algorithm - */ - for(s=2; s<=n; s++) - { - - /* - * Prepare v and Lambda = v'*v - */ - do - { - i = 1; - while(i<=s) - { - u1 = 2*ae_randomreal(_state)-1; - u2 = 2*ae_randomreal(_state)-1; - sm = u1*u1+u2*u2; - if( ae_fp_eq(sm,(double)(0))||ae_fp_greater(sm,(double)(1)) ) - { - continue; - } - sm = ae_sqrt(-2*ae_log(sm, _state)/sm, _state); - v.ptr.p_double[i] = u1*sm; - if( i+1<=s ) - { - v.ptr.p_double[i+1] = u2*sm; - } - i = i+2; - } - lambdav = ae_v_dotproduct(&v.ptr.p_double[1], 1, &v.ptr.p_double[1], 1, ae_v_len(1,s)); - } - while(ae_fp_eq(lambdav,(double)(0))); - lambdav = 2/lambdav; - - /* - * A * (I - 2 vv'/v'v ) = - * = A - (2/v'v) * A * v * v' = - * = A - (2/v'v) * w * v' - * where w = Av - */ - for(i=1; i<=s; i++) - { - t = ae_v_dotproduct(&a.ptr.pp_double[i][1], 1, &v.ptr.p_double[1], 1, ae_v_len(1,s)); - w.ptr.p_double[i] = t; - } - for(i=1; i<=s; i++) - { - t = w.ptr.p_double[i]*lambdav; - ae_v_subd(&a.ptr.pp_double[i][1], 1, &v.ptr.p_double[1], 1, ae_v_len(1,s), t); - } - } - - /* - * - */ - for(i=1; i<=n; i++) - { - for(j=1; j<=n; j++) - { - a0->ptr.pp_double[i-1][j-1] = a.ptr.pp_double[i][j]; - } - } - ae_frame_leave(_state); -} - - -static void testinverseupdateunit_generaterandommatrixcond(/* Real */ ae_matrix* a0, - ae_int_t n, - double c, - ae_state *_state) -{ - ae_frame _frame_block; - double l1; - double l2; - ae_matrix q1; - ae_matrix q2; - ae_vector cc; - ae_int_t i; - ae_int_t j; - ae_int_t k; - - ae_frame_make(_state, &_frame_block); - memset(&q1, 0, sizeof(q1)); - memset(&q2, 0, sizeof(q2)); - memset(&cc, 0, sizeof(cc)); - ae_matrix_init(&q1, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&q2, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&cc, 0, DT_REAL, _state, ae_true); - - testinverseupdateunit_generaterandomorthogonalmatrix(&q1, n, _state); - testinverseupdateunit_generaterandomorthogonalmatrix(&q2, n, _state); - ae_vector_set_length(&cc, n-1+1, _state); - l1 = (double)(0); - l2 = ae_log(1/c, _state); - cc.ptr.p_double[0] = ae_exp(l1, _state); - for(i=1; i<=n-2; i++) - { - cc.ptr.p_double[i] = ae_exp(ae_randomreal(_state)*(l2-l1)+l1, _state); - } - cc.ptr.p_double[n-1] = ae_exp(l2, _state); - ae_matrix_set_length(a0, n-1+1, n-1+1, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a0->ptr.pp_double[i][j] = (double)(0); - for(k=0; k<=n-1; k++) - { - a0->ptr.pp_double[i][j] = a0->ptr.pp_double[i][j]+q1.ptr.pp_double[i][k]*cc.ptr.p_double[k]*q2.ptr.pp_double[j][k]; - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -triangular inverse -*************************************************************************/ -static ae_bool testinverseupdateunit_invmattr(/* Real */ ae_matrix* a, - ae_int_t n, - ae_bool isupper, - ae_bool isunittriangular, - ae_state *_state) -{ - ae_frame _frame_block; - ae_bool nounit; - ae_int_t i; - ae_int_t j; - double v; - double ajj; - ae_vector t; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&t, 0, sizeof(t)); - ae_vector_init(&t, 0, DT_REAL, _state, ae_true); - - result = ae_true; - ae_vector_set_length(&t, n-1+1, _state); - - /* - * Test the input parameters. - */ - nounit = !isunittriangular; - if( isupper ) - { - - /* - * Compute inverse of upper triangular matrix. - */ - for(j=0; j<=n-1; j++) - { - if( nounit ) - { - if( ae_fp_eq(a->ptr.pp_double[j][j],(double)(0)) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - a->ptr.pp_double[j][j] = 1/a->ptr.pp_double[j][j]; - ajj = -a->ptr.pp_double[j][j]; - } - else - { - ajj = (double)(-1); - } - - /* - * Compute elements 1:j-1 of j-th column. - */ - if( j>0 ) - { - ae_v_move(&t.ptr.p_double[0], 1, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,j-1)); - for(i=0; i<=j-1; i++) - { - if( iptr.pp_double[i][i+1], 1, &t.ptr.p_double[i+1], 1, ae_v_len(i+1,j-1)); - } - else - { - v = (double)(0); - } - if( nounit ) - { - a->ptr.pp_double[i][j] = v+a->ptr.pp_double[i][i]*t.ptr.p_double[i]; - } - else - { - a->ptr.pp_double[i][j] = v+t.ptr.p_double[i]; - } - } - ae_v_muld(&a->ptr.pp_double[0][j], a->stride, ae_v_len(0,j-1), ajj); - } - } - } - else - { - - /* - * Compute inverse of lower triangular matrix. - */ - for(j=n-1; j>=0; j--) - { - if( nounit ) - { - if( ae_fp_eq(a->ptr.pp_double[j][j],(double)(0)) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - a->ptr.pp_double[j][j] = 1/a->ptr.pp_double[j][j]; - ajj = -a->ptr.pp_double[j][j]; - } - else - { - ajj = (double)(-1); - } - if( jptr.pp_double[j+1][j], a->stride, ae_v_len(j+1,n-1)); - for(i=j+1; i<=n-1; i++) - { - if( i>j+1 ) - { - v = ae_v_dotproduct(&a->ptr.pp_double[i][j+1], 1, &t.ptr.p_double[j+1], 1, ae_v_len(j+1,i-1)); - } - else - { - v = (double)(0); - } - if( nounit ) - { - a->ptr.pp_double[i][j] = v+a->ptr.pp_double[i][i]*t.ptr.p_double[i]; - } - else - { - a->ptr.pp_double[i][j] = v+t.ptr.p_double[i]; - } - } - ae_v_muld(&a->ptr.pp_double[j+1][j], a->stride, ae_v_len(j+1,n-1), ajj); - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -LU inverse -*************************************************************************/ -static ae_bool testinverseupdateunit_invmatlu(/* Real */ ae_matrix* a, - /* Integer */ ae_vector* pivots, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector work; - ae_int_t i; - ae_int_t j; - ae_int_t jp; - double v; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&work, 0, sizeof(work)); - ae_vector_init(&work, 0, DT_REAL, _state, ae_true); - - result = ae_true; - - /* - * Quick return if possible - */ - if( n==0 ) - { - ae_frame_leave(_state); - return result; - } - ae_vector_set_length(&work, n-1+1, _state); - - /* - * Form inv(U) - */ - if( !testinverseupdateunit_invmattr(a, n, ae_true, ae_false, _state) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - - /* - * Solve the equation inv(A)*L = inv(U) for inv(A). - */ - for(j=n-1; j>=0; j--) - { - - /* - * Copy current column of L to WORK and replace with zeros. - */ - for(i=j+1; i<=n-1; i++) - { - work.ptr.p_double[i] = a->ptr.pp_double[i][j]; - a->ptr.pp_double[i][j] = (double)(0); - } - - /* - * Compute current column of inv(A). - */ - if( jptr.pp_double[i][j+1], 1, &work.ptr.p_double[j+1], 1, ae_v_len(j+1,n-1)); - a->ptr.pp_double[i][j] = a->ptr.pp_double[i][j]-v; - } - } - } - - /* - * Apply column interchanges. - */ - for(j=n-2; j>=0; j--) - { - jp = pivots->ptr.p_int[j]; - if( jp!=j ) - { - ae_v_move(&work.ptr.p_double[0], 1, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,n-1)); - ae_v_move(&a->ptr.pp_double[0][j], a->stride, &a->ptr.pp_double[0][jp], a->stride, ae_v_len(0,n-1)); - ae_v_move(&a->ptr.pp_double[0][jp], a->stride, &work.ptr.p_double[0], 1, ae_v_len(0,n-1)); - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Matrix inverse -*************************************************************************/ -static ae_bool testinverseupdateunit_invmat(/* Real */ ae_matrix* a, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector pivots; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&pivots, 0, sizeof(pivots)); - ae_vector_init(&pivots, 0, DT_INT, _state, ae_true); - - testinverseupdateunit_matlu(a, n, n, &pivots, _state); - result = testinverseupdateunit_invmatlu(a, &pivots, n, _state); - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Diff -*************************************************************************/ -static double testinverseupdateunit_matrixdiff(/* Real */ ae_matrix* a, - /* Real */ ae_matrix* b, - ae_int_t m, - ae_int_t n, - ae_state *_state) -{ - ae_int_t i; - ae_int_t j; - double result; - - - result = (double)(0); - for(i=0; i<=m-1; i++) - { - for(j=0; j<=n-1; j++) - { - result = ae_maxreal(result, ae_fabs(b->ptr.pp_double[i][j]-a->ptr.pp_double[i][j], _state), _state); - } - } - return result; -} - - -/************************************************************************* -Update and inverse -*************************************************************************/ -static ae_bool testinverseupdateunit_updandinv(/* Real */ ae_matrix* a, - /* Real */ ae_vector* u, - /* Real */ ae_vector* v, - ae_int_t n, - ae_state *_state) -{ - ae_frame _frame_block; - ae_vector pivots; - ae_int_t i; - double r; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&pivots, 0, sizeof(pivots)); - ae_vector_init(&pivots, 0, DT_INT, _state, ae_true); - - for(i=0; i<=n-1; i++) - { - r = u->ptr.p_double[i]; - ae_v_addd(&a->ptr.pp_double[i][0], 1, &v->ptr.p_double[0], 1, ae_v_len(0,n-1), r); - } - testinverseupdateunit_matlu(a, n, n, &pivots, _state); - result = testinverseupdateunit_invmatlu(a, &pivots, n, _state); - ae_frame_leave(_state); - return result; -} - - - - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testpolynomialsolver(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_bool wereerrors; - ae_vector a; - ae_vector x; - double eps; - ae_int_t n; - polynomialsolverreport rep; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&x, 0, sizeof(x)); - memset(&rep, 0, sizeof(rep)); - ae_vector_init(&a, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x, 0, DT_COMPLEX, _state, ae_true); - _polynomialsolverreport_init(&rep, _state, ae_true); - - wereerrors = ae_false; - - /* - * Basic tests - */ - eps = 1.0E-6; - n = 1; - ae_vector_set_length(&a, n+1, _state); - a.ptr.p_double[0] = (double)(2); - a.ptr.p_double[1] = (double)(3); - polynomialsolve(&a, n, &x, &rep, _state); - ae_set_error_flag(&wereerrors, ae_fp_greater(ae_fabs(x.ptr.p_complex[0].x+(double)2/(double)3, _state),eps), __FILE__, __LINE__, "testpolynomialsolverunit.ap:33"); - ae_set_error_flag(&wereerrors, ae_fp_neq(x.ptr.p_complex[0].y,(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:34"); - ae_set_error_flag(&wereerrors, ae_fp_greater(rep.maxerr,100*ae_machineepsilon), __FILE__, __LINE__, "testpolynomialsolverunit.ap:35"); - n = 2; - ae_vector_set_length(&a, n+1, _state); - a.ptr.p_double[0] = (double)(1); - a.ptr.p_double[1] = (double)(-2); - a.ptr.p_double[2] = (double)(1); - polynomialsolve(&a, n, &x, &rep, _state); - ae_set_error_flag(&wereerrors, ae_fp_greater(ae_c_abs(ae_c_sub_d(x.ptr.p_complex[0],1), _state),eps), __FILE__, __LINE__, "testpolynomialsolverunit.ap:43"); - ae_set_error_flag(&wereerrors, ae_fp_greater(ae_c_abs(ae_c_sub_d(x.ptr.p_complex[1],1), _state),eps), __FILE__, __LINE__, "testpolynomialsolverunit.ap:44"); - ae_set_error_flag(&wereerrors, ae_fp_greater(rep.maxerr,100*ae_machineepsilon), __FILE__, __LINE__, "testpolynomialsolverunit.ap:45"); - n = 2; - ae_vector_set_length(&a, n+1, _state); - a.ptr.p_double[0] = (double)(2); - a.ptr.p_double[1] = (double)(-3); - a.ptr.p_double[2] = (double)(1); - polynomialsolve(&a, n, &x, &rep, _state); - if( ae_fp_less(x.ptr.p_complex[0].x,x.ptr.p_complex[1].x) ) - { - ae_set_error_flag(&wereerrors, ae_fp_greater(ae_fabs(x.ptr.p_complex[0].x-1, _state),eps), __FILE__, __LINE__, "testpolynomialsolverunit.ap:55"); - ae_set_error_flag(&wereerrors, ae_fp_greater(ae_fabs(x.ptr.p_complex[1].x-2, _state),eps), __FILE__, __LINE__, "testpolynomialsolverunit.ap:56"); - } - else - { - ae_set_error_flag(&wereerrors, ae_fp_greater(ae_fabs(x.ptr.p_complex[0].x-2, _state),eps), __FILE__, __LINE__, "testpolynomialsolverunit.ap:60"); - ae_set_error_flag(&wereerrors, ae_fp_greater(ae_fabs(x.ptr.p_complex[1].x-1, _state),eps), __FILE__, __LINE__, "testpolynomialsolverunit.ap:61"); - } - ae_set_error_flag(&wereerrors, ae_fp_neq(x.ptr.p_complex[0].y,(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:63"); - ae_set_error_flag(&wereerrors, ae_fp_neq(x.ptr.p_complex[1].y,(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:64"); - ae_set_error_flag(&wereerrors, ae_fp_greater(rep.maxerr,100*ae_machineepsilon), __FILE__, __LINE__, "testpolynomialsolverunit.ap:65"); - n = 2; - ae_vector_set_length(&a, n+1, _state); - a.ptr.p_double[0] = (double)(1); - a.ptr.p_double[1] = (double)(0); - a.ptr.p_double[2] = (double)(1); - polynomialsolve(&a, n, &x, &rep, _state); - ae_set_error_flag(&wereerrors, ae_fp_greater(ae_c_abs(ae_c_add_d(ae_c_mul(x.ptr.p_complex[0],x.ptr.p_complex[0]),(double)(1)), _state),eps), __FILE__, __LINE__, "testpolynomialsolverunit.ap:73"); - ae_set_error_flag(&wereerrors, ae_fp_greater(rep.maxerr,100*ae_machineepsilon), __FILE__, __LINE__, "testpolynomialsolverunit.ap:74"); - n = 4; - ae_vector_set_length(&a, n+1, _state); - a.ptr.p_double[0] = (double)(0); - a.ptr.p_double[1] = (double)(0); - a.ptr.p_double[2] = (double)(0); - a.ptr.p_double[3] = (double)(0); - a.ptr.p_double[4] = (double)(1); - polynomialsolve(&a, n, &x, &rep, _state); - ae_set_error_flag(&wereerrors, ae_c_neq_d(x.ptr.p_complex[0],(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:84"); - ae_set_error_flag(&wereerrors, ae_c_neq_d(x.ptr.p_complex[1],(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:85"); - ae_set_error_flag(&wereerrors, ae_c_neq_d(x.ptr.p_complex[2],(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:86"); - ae_set_error_flag(&wereerrors, ae_c_neq_d(x.ptr.p_complex[3],(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:87"); - ae_set_error_flag(&wereerrors, ae_fp_greater(rep.maxerr,100*ae_machineepsilon), __FILE__, __LINE__, "testpolynomialsolverunit.ap:88"); - n = 2; - ae_vector_set_length(&a, n+1, _state); - a.ptr.p_double[0] = (double)(0); - a.ptr.p_double[1] = (double)(3); - a.ptr.p_double[2] = (double)(2); - polynomialsolve(&a, n, &x, &rep, _state); - if( ae_fp_greater(x.ptr.p_complex[0].x,x.ptr.p_complex[1].x) ) - { - ae_set_error_flag(&wereerrors, ae_c_neq_d(x.ptr.p_complex[0],(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:98"); - ae_set_error_flag(&wereerrors, ae_fp_greater(ae_fabs(x.ptr.p_complex[1].x+(double)3/(double)2, _state),eps), __FILE__, __LINE__, "testpolynomialsolverunit.ap:99"); - ae_set_error_flag(&wereerrors, ae_fp_neq(x.ptr.p_complex[1].y,(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:100"); - } - else - { - ae_set_error_flag(&wereerrors, ae_c_neq_d(x.ptr.p_complex[1],(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:104"); - ae_set_error_flag(&wereerrors, ae_fp_greater(ae_fabs(x.ptr.p_complex[0].x+(double)3/(double)2, _state),eps), __FILE__, __LINE__, "testpolynomialsolverunit.ap:105"); - ae_set_error_flag(&wereerrors, ae_fp_neq(x.ptr.p_complex[0].y,(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:106"); - } - ae_set_error_flag(&wereerrors, ae_fp_greater(rep.maxerr,100*ae_machineepsilon), __FILE__, __LINE__, "testpolynomialsolverunit.ap:108"); - if( !silent ) - { - printf("TESTING POLYNOMIAL SOLVER\n"); - if( wereerrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - } - result = !wereerrors; - ae_frame_leave(_state); - return result; -} - - - -static void testnlequnit_testfunchbm(nleqstate* state, ae_state *_state); -static void testnlequnit_testfunchb1(nleqstate* state, ae_state *_state); -static void testnlequnit_testfuncshbm(nleqstate* state, ae_state *_state); - - - - - -ae_bool testnleq(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - ae_bool waserrors; - ae_bool basicserrors; - ae_bool converror; - ae_bool othererrors; - ae_int_t n; - ae_vector x; - ae_int_t i; - ae_int_t k; - double v; - double flast; - ae_vector xlast; - ae_bool firstrep; - ae_int_t nfunc; - ae_int_t njac; - ae_int_t itcnt; - nleqstate state; - nleqreport rep; - ae_int_t pass; - ae_int_t passcount; - double epsf; - double stpmax; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&x, 0, sizeof(x)); - memset(&xlast, 0, sizeof(xlast)); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - ae_vector_init(&x, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xlast, 0, DT_REAL, _state, ae_true); - _nleqstate_init(&state, _state, ae_true); - _nleqreport_init(&rep, _state, ae_true); - - waserrors = ae_false; - basicserrors = ae_false; - converror = ae_false; - othererrors = ae_false; - - /* - * Basic tests - * - * Test with Himmelblau's function (M): - * * ability to find correct result - * * ability to work after soft restart (restart after finish) - * * ability to work after hard restart (restart in the middle of optimization) - */ - passcount = 100; - for(pass=0; pass<=passcount-1; pass++) - { - - /* - * Ability to find correct result - */ - ae_vector_set_length(&x, 2, _state); - x.ptr.p_double[0] = 20*ae_randomreal(_state)-10; - x.ptr.p_double[1] = 20*ae_randomreal(_state)-10; - nleqcreatelm(2, 2, &x, &state, _state); - epsf = 1.0E-9; - nleqsetcond(&state, epsf, 0, _state); - while(nleqiteration(&state, _state)) - { - testnlequnit_testfunchbm(&state, _state); - } - nleqresults(&state, &x, &rep, _state); - if( rep.terminationtype>0 ) - { - basicserrors = basicserrors||ae_fp_greater(ae_sqr(x.ptr.p_double[0]*x.ptr.p_double[0]+x.ptr.p_double[1]-11, _state)+ae_sqr(x.ptr.p_double[0]+x.ptr.p_double[1]*x.ptr.p_double[1]-7, _state),ae_sqr(epsf, _state)); - } - else - { - basicserrors = ae_true; - } - - /* - * Ability to work after soft restart - */ - ae_vector_set_length(&x, 2, _state); - x.ptr.p_double[0] = 20*ae_randomreal(_state)-10; - x.ptr.p_double[1] = 20*ae_randomreal(_state)-10; - nleqcreatelm(2, 2, &x, &state, _state); - epsf = 1.0E-9; - nleqsetcond(&state, epsf, 0, _state); - while(nleqiteration(&state, _state)) - { - testnlequnit_testfunchbm(&state, _state); - } - nleqresults(&state, &x, &rep, _state); - ae_vector_set_length(&x, 2, _state); - x.ptr.p_double[0] = 20*ae_randomreal(_state)-10; - x.ptr.p_double[1] = 20*ae_randomreal(_state)-10; - nleqrestartfrom(&state, &x, _state); - while(nleqiteration(&state, _state)) - { - testnlequnit_testfunchbm(&state, _state); - } - nleqresults(&state, &x, &rep, _state); - if( rep.terminationtype>0 ) - { - basicserrors = basicserrors||ae_fp_greater(ae_sqr(x.ptr.p_double[0]*x.ptr.p_double[0]+x.ptr.p_double[1]-11, _state)+ae_sqr(x.ptr.p_double[0]+x.ptr.p_double[1]*x.ptr.p_double[1]-7, _state),ae_sqr(epsf, _state)); - } - else - { - basicserrors = ae_true; - } - - /* - * Ability to work after hard restart: - * * stopping condition: small F - * * StpMax is so small that we need about 10000 iterations to - * find solution (steps are small) - * * choose random K significantly less that 9999 - * * iterate for some time, then break, restart optimization - */ - ae_vector_set_length(&x, 2, _state); - x.ptr.p_double[0] = (double)(100); - x.ptr.p_double[1] = (double)(100); - nleqcreatelm(2, 2, &x, &state, _state); - epsf = 1.0E-9; - nleqsetcond(&state, epsf, 0, _state); - nleqsetstpmax(&state, 0.01, _state); - k = 1+ae_randominteger(100, _state); - for(i=0; i<=k-1; i++) - { - if( !nleqiteration(&state, _state) ) - { - break; - } - testnlequnit_testfunchbm(&state, _state); - } - ae_vector_set_length(&x, 2, _state); - x.ptr.p_double[0] = 20*ae_randomreal(_state)-10; - x.ptr.p_double[1] = 20*ae_randomreal(_state)-10; - nleqrestartfrom(&state, &x, _state); - while(nleqiteration(&state, _state)) - { - testnlequnit_testfunchbm(&state, _state); - } - nleqresults(&state, &x, &rep, _state); - if( rep.terminationtype>0 ) - { - basicserrors = basicserrors||ae_fp_greater(ae_sqr(x.ptr.p_double[0]*x.ptr.p_double[0]+x.ptr.p_double[1]-11, _state)+ae_sqr(x.ptr.p_double[0]+x.ptr.p_double[1]*x.ptr.p_double[1]-7, _state),ae_sqr(epsf, _state)); - } - else - { - basicserrors = ae_true; - } - } - - /* - * Basic tests - * - * Test with Himmelblau's function (1): - * * ability to find correct result - */ - passcount = 100; - for(pass=0; pass<=passcount-1; pass++) - { - - /* - * Ability to find correct result - */ - ae_vector_set_length(&x, 2, _state); - x.ptr.p_double[0] = 20*ae_randomreal(_state)-10; - x.ptr.p_double[1] = 20*ae_randomreal(_state)-10; - nleqcreatelm(2, 1, &x, &state, _state); - epsf = 1.0E-9; - nleqsetcond(&state, epsf, 0, _state); - while(nleqiteration(&state, _state)) - { - testnlequnit_testfunchb1(&state, _state); - } - nleqresults(&state, &x, &rep, _state); - if( rep.terminationtype>0 ) - { - basicserrors = basicserrors||ae_fp_greater(ae_sqr(x.ptr.p_double[0]*x.ptr.p_double[0]+x.ptr.p_double[1]-11, _state)+ae_sqr(x.ptr.p_double[0]+x.ptr.p_double[1]*x.ptr.p_double[1]-7, _state),epsf); - } - else - { - basicserrors = ae_true; - } - } - - /* - * Basic tests - * - * Ability to detect situation when we can't find minimum - */ - passcount = 100; - for(pass=0; pass<=passcount-1; pass++) - { - ae_vector_set_length(&x, 2, _state); - x.ptr.p_double[0] = 20*ae_randomreal(_state)-10; - x.ptr.p_double[1] = 20*ae_randomreal(_state)-10; - nleqcreatelm(2, 3, &x, &state, _state); - epsf = 1.0E-9; - nleqsetcond(&state, epsf, 0, _state); - while(nleqiteration(&state, _state)) - { - testnlequnit_testfuncshbm(&state, _state); - } - nleqresults(&state, &x, &rep, _state); - basicserrors = basicserrors||rep.terminationtype!=-4; - } - - /* - * Test correctness of intermediate reports and final report: - * * first report is starting point - * * function value decreases on subsequent reports - * * function value is correctly reported - * * last report is final point - * * NFunc and NJac are compared with values counted directly - * * IterationsCount is compared with value counter directly - */ - n = 2; - ae_vector_set_length(&x, n, _state); - ae_vector_set_length(&xlast, n, _state); - x.ptr.p_double[0] = 20*ae_randomreal(_state)-10; - x.ptr.p_double[1] = 20*ae_randomreal(_state)-10; - xlast.ptr.p_double[0] = ae_maxrealnumber; - xlast.ptr.p_double[1] = ae_maxrealnumber; - nleqcreatelm(n, 2, &x, &state, _state); - nleqsetcond(&state, 1.0E-6, 0, _state); - nleqsetxrep(&state, ae_true, _state); - firstrep = ae_true; - flast = ae_maxrealnumber; - nfunc = 0; - njac = 0; - itcnt = 0; - while(nleqiteration(&state, _state)) - { - if( state.xupdated ) - { - - /* - * first report must be starting point - */ - if( firstrep ) - { - for(i=0; i<=n-1; i++) - { - othererrors = othererrors||ae_fp_neq(state.x.ptr.p_double[i],x.ptr.p_double[i]); - } - firstrep = ae_false; - } - - /* - * function value must decrease - */ - othererrors = othererrors||ae_fp_greater(state.f,flast); - - /* - * check correctness of function value - */ - v = ae_sqr(state.x.ptr.p_double[0]*state.x.ptr.p_double[0]+state.x.ptr.p_double[1]-11, _state)+ae_sqr(state.x.ptr.p_double[0]+state.x.ptr.p_double[1]*state.x.ptr.p_double[1]-7, _state); - othererrors = othererrors||ae_fp_greater(ae_fabs(v-state.f, _state)/ae_maxreal(v, (double)(1), _state),100*ae_machineepsilon); - - /* - * update info and continue - */ - ae_v_move(&xlast.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1)); - flast = state.f; - itcnt = itcnt+1; - continue; - } - if( state.needf ) - { - nfunc = nfunc+1; - } - if( state.needfij ) - { - nfunc = nfunc+1; - njac = njac+1; - } - testnlequnit_testfunchbm(&state, _state); - } - nleqresults(&state, &x, &rep, _state); - if( rep.terminationtype>0 ) - { - othererrors = (othererrors||ae_fp_neq(xlast.ptr.p_double[0],x.ptr.p_double[0]))||ae_fp_neq(xlast.ptr.p_double[1],x.ptr.p_double[1]); - v = ae_sqr(x.ptr.p_double[0]*x.ptr.p_double[0]+x.ptr.p_double[1]-11, _state)+ae_sqr(x.ptr.p_double[0]+x.ptr.p_double[1]*x.ptr.p_double[1]-7, _state); - othererrors = othererrors||ae_fp_greater(ae_fabs(flast-v, _state)/ae_maxreal(v, (double)(1), _state),100*ae_machineepsilon); - } - else - { - converror = ae_true; - } - othererrors = othererrors||rep.nfunc!=nfunc; - othererrors = othererrors||rep.njac!=njac; - othererrors = othererrors||rep.iterationscount!=itcnt-1; - - /* - * Test ability to set limit on algorithm steps - */ - ae_vector_set_length(&x, 2, _state); - ae_vector_set_length(&xlast, 2, _state); - x.ptr.p_double[0] = 20*ae_randomreal(_state)+20; - x.ptr.p_double[1] = 20*ae_randomreal(_state)+20; - xlast.ptr.p_double[0] = x.ptr.p_double[0]; - xlast.ptr.p_double[1] = x.ptr.p_double[1]; - stpmax = 0.1+0.1*ae_randomreal(_state); - epsf = 1.0E-9; - nleqcreatelm(2, 2, &x, &state, _state); - nleqsetstpmax(&state, stpmax, _state); - nleqsetcond(&state, epsf, 0, _state); - nleqsetxrep(&state, ae_true, _state); - while(nleqiteration(&state, _state)) - { - if( state.needf||state.needfij ) - { - testnlequnit_testfunchbm(&state, _state); - } - if( (state.needf||state.needfij)||state.xupdated ) - { - othererrors = othererrors||ae_fp_greater(ae_sqrt(ae_sqr(state.x.ptr.p_double[0]-xlast.ptr.p_double[0], _state)+ae_sqr(state.x.ptr.p_double[1]-xlast.ptr.p_double[1], _state), _state),1.00001*stpmax); - } - if( state.xupdated ) - { - xlast.ptr.p_double[0] = state.x.ptr.p_double[0]; - xlast.ptr.p_double[1] = state.x.ptr.p_double[1]; - } - } - - /* - * end - */ - waserrors = (basicserrors||converror)||othererrors; - if( !silent ) - { - printf("TESTING NLEQ SOLVER\n"); - printf("BASIC FUNCTIONALITY: "); - if( basicserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("CONVERGENCE: "); - if( converror ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("OTHER PROPERTIES: "); - if( othererrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Himmelblau's function - - F = (x^2+y-11)^2 + (x+y^2-7)^2 - -posed as system of M functions: - - f0 = x^2+y-11 - f1 = x+y^2-7 - -*************************************************************************/ -static void testnlequnit_testfunchbm(nleqstate* state, ae_state *_state) -{ - double x; - double y; - - - ae_assert(state->needf||state->needfij, "TestNLEQUnit: internal error!", _state); - x = state->x.ptr.p_double[0]; - y = state->x.ptr.p_double[1]; - if( state->needf ) - { - state->f = ae_sqr(x*x+y-11, _state)+ae_sqr(x+y*y-7, _state); - return; - } - if( state->needfij ) - { - state->fi.ptr.p_double[0] = x*x+y-11; - state->fi.ptr.p_double[1] = x+y*y-7; - state->j.ptr.pp_double[0][0] = 2*x; - state->j.ptr.pp_double[0][1] = (double)(1); - state->j.ptr.pp_double[1][0] = (double)(1); - state->j.ptr.pp_double[1][1] = 2*y; - return; - } -} - - -/************************************************************************* -Himmelblau's function - - F = (x^2+y-11)^2 + (x+y^2-7)^2 - -posed as system of 1 function -*************************************************************************/ -static void testnlequnit_testfunchb1(nleqstate* state, ae_state *_state) -{ - double x; - double y; - - - ae_assert(state->needf||state->needfij, "TestNLEQUnit: internal error!", _state); - x = state->x.ptr.p_double[0]; - y = state->x.ptr.p_double[1]; - if( state->needf ) - { - state->f = ae_sqr(ae_sqr(x*x+y-11, _state)+ae_sqr(x+y*y-7, _state), _state); - return; - } - if( state->needfij ) - { - state->fi.ptr.p_double[0] = ae_sqr(x*x+y-11, _state)+ae_sqr(x+y*y-7, _state); - state->j.ptr.pp_double[0][0] = 2*(x*x+y-11)*2*x+2*(x+y*y-7); - state->j.ptr.pp_double[0][1] = 2*(x*x+y-11)+2*(x+y*y-7)*2*y; - return; - } -} - - -/************************************************************************* -Shifted Himmelblau's function - - F = (x^2+y-11)^2 + (x+y^2-7)^2 + 1 - -posed as system of M functions: - - f0 = x^2+y-11 - f1 = x+y^2-7 - f2 = 1 - -This function is used to test algorithm on problem which has no solution. -*************************************************************************/ -static void testnlequnit_testfuncshbm(nleqstate* state, ae_state *_state) -{ - double x; - double y; - - - ae_assert(state->needf||state->needfij, "TestNLEQUnit: internal error!", _state); - x = state->x.ptr.p_double[0]; - y = state->x.ptr.p_double[1]; - if( state->needf ) - { - state->f = ae_sqr(x*x+y-11, _state)+ae_sqr(x+y*y-7, _state)+1; - return; - } - if( state->needfij ) - { - state->fi.ptr.p_double[0] = x*x+y-11; - state->fi.ptr.p_double[1] = x+y*y-7; - state->fi.ptr.p_double[2] = (double)(1); - state->j.ptr.pp_double[0][0] = 2*x; - state->j.ptr.pp_double[0][1] = (double)(1); - state->j.ptr.pp_double[1][0] = (double)(1); - state->j.ptr.pp_double[1][1] = 2*y; - state->j.ptr.pp_double[2][0] = (double)(0); - state->j.ptr.pp_double[2][1] = (double)(0); - return; - } -} - - - -static void testdirectsparsesolversunit_testsks(ae_bool* errorflag, - ae_state *_state); -static void testdirectsparsesolversunit_testcholesky(ae_bool* errorflag, - ae_state *_state); -static void testdirectsparsesolversunit_testgen(ae_bool* errorflag, - ae_state *_state); - - - - - -/************************************************************************* -Test -*************************************************************************/ -ae_bool testdirectsparsesolvers(ae_bool silent, ae_state *_state) -{ - ae_bool rskserrors; - ae_bool rcholerrors; - ae_bool rgenerrors; - ae_bool wereerrors; - ae_bool result; - - - rskserrors = ae_false; - rcholerrors = ae_false; - rgenerrors = ae_false; - testdirectsparsesolversunit_testsks(&rskserrors, _state); - testdirectsparsesolversunit_testcholesky(&rcholerrors, _state); - testdirectsparsesolversunit_testgen(&rgenerrors, _state); - wereerrors = (rskserrors||rcholerrors)||rgenerrors; - if( !silent ) - { - printf("TESTING DIRECT SPARSE SOLVERS:\n"); - printf("* SPD-SKS (real) "); - if( rskserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* SPD-CRS (real) "); - if( rcholerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("* GENERAL (real) "); - if( rgenerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - if( wereerrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - } - result = !wereerrors; - return result; -} - - -/************************************************************************* -SPD SKS test -*************************************************************************/ -static void testdirectsparsesolversunit_testsks(ae_bool* errorflag, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t pass; - ae_int_t passcount; - ae_int_t maxn; - double threshold; - ae_int_t bw; - ae_bool isupper; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_matrix a; - ae_vector xe; - ae_vector b; - ae_vector xs; - sparsematrix sa; - sparsematrix sa2; - sparsesolverreport rep; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&xe, 0, sizeof(xe)); - memset(&b, 0, sizeof(b)); - memset(&xs, 0, sizeof(xs)); - memset(&sa, 0, sizeof(sa)); - memset(&sa2, 0, sizeof(sa2)); - memset(&rep, 0, sizeof(rep)); - memset(&rs, 0, sizeof(rs)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xe, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xs, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&sa, _state, ae_true); - _sparsematrix_init(&sa2, _state, ae_true); - _sparsesolverreport_init(&rep, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - passcount = 10; - maxn = 30; - threshold = 1.0E-6; - hqrndrandomize(&rs, _state); - - /* - * Well conditioned SPD problems solved with SKS solver - */ - for(n=1; n<=maxn; n++) - { - for(pass=1; pass<=passcount; pass++) - { - - /* - * 1. generate random well conditioned matrix A. - * 2. generate random solution vector xe - * 3. generate right part b=A*xe - */ - isupper = ae_fp_greater(hqrndnormal(&rs, _state),0.5); - bw = hqrnduniformi(&rs, n+1, _state); - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - sparsecreate(n, n, 0, &sa, _state); - for(i=0; i<=n-1; i++) - { - a.ptr.pp_double[i][i] = 1+hqrnduniformr(&rs, _state); - sparseset(&sa, i, i, a.ptr.pp_double[i][i], _state); - for(j=i+1; j<=ae_minint(i+bw, n-1, _state); j++) - { - a.ptr.pp_double[i][j] = (hqrnduniformr(&rs, _state)-0.5)/n; - a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j]; - if( isupper ) - { - sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state); - } - else - { - sparseset(&sa, j, i, a.ptr.pp_double[i][j], _state); - } - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (ji&&!isupper) ) - { - if( ae_fp_less(hqrnduniformr(&rs, _state),0.25) ) - { - sparseset(&sa, i, j, hqrndnormal(&rs, _state), _state); - } - } - } - } - sparseconvertto(&sa, hqrnduniformi(&rs, 3, _state), _state); - ae_vector_set_length(&xe, n, _state); - for(i=0; i<=n-1; i++) - { - xe.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&b, n, _state); - rmatrixgemv(n, n, 1.0, &a, 0, 0, 0, &xe, 0, 0.0, &b, 0, _state); - - /* - * Test SKS solver - */ - ae_vector_set_length(&xs, 0, _state); - sparsecopytosks(&sa, &sa2, _state); - sparsespdsolvesks(&sa2, isupper, &b, &xs, &rep, _state); - ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testdirectsparsesolversunit.ap:88"); - ae_set_error_flag(errorflag, xs.cnt!=n, __FILE__, __LINE__, "testdirectsparsesolversunit.ap:89"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-xs.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testdirectsparsesolversunit.ap:93"); - } - - /* - * Test solver #2 - */ - sparsecopytosks(&sa, &sa2, _state); - if( !sparsecholeskyskyline(&sa2, n, isupper, _state) ) - { - ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testdirectsparsesolversunit.ap:102"); - ae_frame_leave(_state); - return; - } - ae_vector_set_length(&xs, 0, _state); - sparsespdcholeskysolve(&sa2, isupper, &b, &xs, &rep, _state); - ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testdirectsparsesolversunit.ap:107"); - ae_set_error_flag(errorflag, xs.cnt!=n, __FILE__, __LINE__, "testdirectsparsesolversunit.ap:108"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-xs.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testdirectsparsesolversunit.ap:112"); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -SPD SKS test -*************************************************************************/ -static void testdirectsparsesolversunit_testcholesky(ae_bool* errorflag, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t pass; - ae_int_t passcount; - ae_int_t maxn; - double threshold; - ae_int_t bw; - ae_bool isupper; - ae_int_t n; - ae_int_t i; - ae_int_t j; - ae_matrix a; - ae_vector xe; - ae_vector b; - ae_vector xs; - sparsematrix sa; - sparsematrix sa2; - sparsesolverreport rep; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&xe, 0, sizeof(xe)); - memset(&b, 0, sizeof(b)); - memset(&xs, 0, sizeof(xs)); - memset(&sa, 0, sizeof(sa)); - memset(&sa2, 0, sizeof(sa2)); - memset(&rep, 0, sizeof(rep)); - memset(&rs, 0, sizeof(rs)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xe, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xs, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&sa, _state, ae_true); - _sparsematrix_init(&sa2, _state, ae_true); - _sparsesolverreport_init(&rep, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - passcount = 10; - maxn = 30; - threshold = 1.0E-6; - hqrndrandomize(&rs, _state); - - /* - * Well conditioned SPD problems solved with Cholesky solver - */ - for(n=1; n<=maxn; n++) - { - for(pass=1; pass<=passcount; pass++) - { - - /* - * 1. generate random well conditioned matrix A. - * 2. generate random solution vector xe - * 3. generate right part b=A*xe - */ - isupper = ae_fp_greater(hqrndnormal(&rs, _state),0.5); - bw = hqrnduniformi(&rs, n+1, _state); - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - sparsecreate(n, n, 0, &sa, _state); - for(i=0; i<=n-1; i++) - { - a.ptr.pp_double[i][i] = 1+hqrnduniformr(&rs, _state); - sparseset(&sa, i, i, a.ptr.pp_double[i][i], _state); - for(j=i+1; j<=ae_minint(i+bw, n-1, _state); j++) - { - a.ptr.pp_double[i][j] = (hqrnduniformr(&rs, _state)-0.5)/n; - a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j]; - if( isupper ) - { - sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state); - } - else - { - sparseset(&sa, j, i, a.ptr.pp_double[i][j], _state); - } - } - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( (ji&&!isupper) ) - { - if( ae_fp_less(hqrnduniformr(&rs, _state),0.25) ) - { - sparseset(&sa, i, j, hqrndnormal(&rs, _state), _state); - } - } - } - } - sparseconvertto(&sa, hqrnduniformi(&rs, 3, _state), _state); - ae_vector_set_length(&xe, n, _state); - for(i=0; i<=n-1; i++) - { - xe.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&b, n, _state); - rmatrixgemv(n, n, 1.0, &a, 0, 0, 0, &xe, 0, 0.0, &b, 0, _state); - - /* - * Test CRS/AMD solver - */ - ae_vector_set_length(&xs, 0, _state); - sparsecopy(&sa, &sa2, _state); - sparsespdsolve(&sa2, isupper, &b, &xs, &rep, _state); - ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testdirectsparsesolversunit.ap:196"); - ae_set_error_flag(errorflag, xs.cnt!=n, __FILE__, __LINE__, "testdirectsparsesolversunit.ap:197"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-xs.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testdirectsparsesolversunit.ap:201"); - } - } - } - ae_frame_leave(_state); -} - - -/************************************************************************* -General linear test -*************************************************************************/ -static void testdirectsparsesolversunit_testgen(ae_bool* errorflag, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t pass; - ae_int_t passcount; - ae_int_t maxn; - double threshold; - ae_int_t n; - ae_int_t noffdiag; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_matrix a; - ae_vector xe; - ae_vector b; - ae_vector xs; - ae_vector xs2; - ae_vector pivp; - ae_vector pivq; - sparsematrix sa; - sparsematrix sa2; - sparsesolverreport rep; - hqrndstate rs; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&xe, 0, sizeof(xe)); - memset(&b, 0, sizeof(b)); - memset(&xs, 0, sizeof(xs)); - memset(&xs2, 0, sizeof(xs2)); - memset(&pivp, 0, sizeof(pivp)); - memset(&pivq, 0, sizeof(pivq)); - memset(&sa, 0, sizeof(sa)); - memset(&sa2, 0, sizeof(sa2)); - memset(&rep, 0, sizeof(rep)); - memset(&rs, 0, sizeof(rs)); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xe, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xs, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xs2, 0, DT_REAL, _state, ae_true); - ae_vector_init(&pivp, 0, DT_INT, _state, ae_true); - ae_vector_init(&pivq, 0, DT_INT, _state, ae_true); - _sparsematrix_init(&sa, _state, ae_true); - _sparsematrix_init(&sa2, _state, ae_true); - _sparsesolverreport_init(&rep, _state, ae_true); - _hqrndstate_init(&rs, _state, ae_true); - - passcount = 10; - maxn = 30; - threshold = 1.0E-6; - hqrndrandomize(&rs, _state); - - /* - * Well conditioned general linear problems solved with LU solver - */ - for(n=1; n<=maxn; n++) - { - for(pass=1; pass<=passcount; pass++) - { - - /* - * Select number of off-diagonal entries, we want to try matrices - * from dense to sparse - */ - noffdiag = n*(n-1); - for(;;) - { - - /* - * 1. generate random well conditioned matrix A. - * 2. apply row/col permutation - * 3. generate random solution vector xe - * 4. generate right part b=A*xe - */ - ae_matrix_set_length(&a, n, n, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = (double)(0); - } - } - for(k=0; k<=noffdiag-1; k++) - { - i = hqrnduniformi(&rs, n, _state); - j = hqrnduniformi(&rs, n, _state); - a.ptr.pp_double[i][j] = 0.01*hqrndnormal(&rs, _state)/n; - } - for(i=0; i<=n-1; i++) - { - a.ptr.pp_double[i][i] = 1.0+ae_pow((double)(2), hqrndnormal(&rs, _state), _state); - } - for(i=0; i<=n-1; i++) - { - swaprows(&a, i, i+hqrnduniformi(&rs, n-i, _state), n, _state); - } - for(i=0; i<=n-1; i++) - { - swapcols(&a, i, i+hqrnduniformi(&rs, n-i, _state), n, _state); - } - sparsecreate(n, n, 0, &sa, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state); - } - } - sparseconvertto(&sa, hqrnduniformi(&rs, 3, _state), _state); - ae_vector_set_length(&xe, n, _state); - for(i=0; i<=n-1; i++) - { - xe.ptr.p_double[i] = hqrndnormal(&rs, _state); - } - ae_vector_set_length(&b, n, _state); - rmatrixgemv(n, n, 1.0, &a, 0, 0, 0, &xe, 0, 0.0, &b, 0, _state); - - /* - * Test solver #1 - */ - ae_vector_set_length(&xs, 0, _state); - sparsesolve(&sa, &b, &xs, &rep, _state); - ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testdirectsparsesolversunit.ap:285"); - ae_set_error_flag(errorflag, xs.cnt!=n, __FILE__, __LINE__, "testdirectsparsesolversunit.ap:286"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-xs.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testdirectsparsesolversunit.ap:290"); - } - - /* - * Test solver #2 - */ - ae_vector_set_length(&xs, 0, _state); - sparsecopytocrs(&sa, &sa2, _state); - sparselu(&sa2, 0, &pivp, &pivq, _state); - sparselusolve(&sa2, &pivp, &pivq, &b, &xs2, &rep, _state); - ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testdirectsparsesolversunit.ap:300"); - ae_set_error_flag(errorflag, xs2.cnt!=n, __FILE__, __LINE__, "testdirectsparsesolversunit.ap:301"); - if( *errorflag ) - { - ae_frame_leave(_state); - return; - } - for(i=0; i<=n-1; i++) - { - ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-xs2.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testdirectsparsesolversunit.ap:305"); - } - - /* - * Update fill factor - */ - if( noffdiag==0 ) - { - break; - } - noffdiag = noffdiag/2; - } - } - } - ae_frame_leave(_state); -} - - - -static double testlincgunit_e0 = 1.0E-6; -static double testlincgunit_maxcond = 30; -static ae_bool testlincgunit_complextest(ae_bool silent, ae_state *_state); -static ae_bool testlincgunit_complexres(ae_bool silent, ae_state *_state); -static ae_bool testlincgunit_basictestx(ae_bool silent, ae_state *_state); -static ae_bool testlincgunit_testrcorrectness(ae_bool silent, - ae_state *_state); -static ae_bool testlincgunit_basictestiters(ae_bool silent, - ae_state *_state); -static ae_bool testlincgunit_krylovsubspacetest(ae_bool silent, - ae_state *_state); -static ae_bool testlincgunit_sparsetest(ae_bool silent, ae_state *_state); -static ae_bool testlincgunit_precondtest(ae_bool silent, ae_state *_state); -static void testlincgunit_gramshmidtortnorm(/* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t k, - double eps, - /* Real */ ae_matrix* b, - ae_int_t* k2, - ae_state *_state); -static ae_bool testlincgunit_frombasis(/* Real */ ae_vector* x, - /* Real */ ae_matrix* basis, - ae_int_t n, - ae_int_t k, - double eps, - ae_state *_state); - - - - - -ae_bool testlincg(ae_bool silent, ae_state *_state) -{ - ae_bool basictestxerrors; - ae_bool basictestiterserr; - ae_bool complexreserrors; - ae_bool complexerrors; - ae_bool rcorrectness; - ae_bool krylovsubspaceerr; - ae_bool sparseerrors; - ae_bool preconderrors; - ae_bool waserrors; - ae_bool result; - - - basictestxerrors = testlincgunit_basictestx(ae_true, _state); - basictestiterserr = testlincgunit_basictestiters(ae_true, _state); - complexreserrors = testlincgunit_complexres(ae_true, _state); - complexerrors = testlincgunit_complextest(ae_true, _state); - rcorrectness = testlincgunit_testrcorrectness(ae_true, _state); - krylovsubspaceerr = testlincgunit_krylovsubspacetest(ae_true, _state); - sparseerrors = testlincgunit_sparsetest(ae_true, _state); - preconderrors = testlincgunit_precondtest(ae_true, _state); - - /* - * report - */ - waserrors = ((((((basictestxerrors||complexreserrors)||complexerrors)||rcorrectness)||basictestiterserr)||krylovsubspaceerr)||sparseerrors)||preconderrors; - if( !silent ) - { - printf("TESTING LinCG\n"); - printf("BasicTestX: "); - if( basictestxerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("BasicTestIters: "); - if( basictestiterserr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("ComplexResTest: "); - if( complexreserrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("ComplexTest: "); - if( complexerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("R2 correctness: "); - if( rcorrectness ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("KrylovSubSpaceTest: "); - if( krylovsubspaceerr ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("SparseTest: "); - if( sparseerrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - printf("PrecondTest: "); - if( preconderrors ) - { - printf("FAILED\n"); - } - else - { - printf("OK\n"); - } - - /* - *was errors? - */ - if( waserrors ) - { - printf("TEST FAILED\n"); - } - else - { - printf("TEST PASSED\n"); - } - printf("\n\n"); - } - result = !waserrors; - return result; -} - - -/************************************************************************* -Function for testing LinCGIteration function(custom option), which to solve -Ax=b(here A is random positive definite matrix NxN, b is random vector). It -uses the default stopping criterion(RNormk; - 2. (rk,rm)=0 for any m<>k; - 3. (rk,pm)=0 for any m<>k; - -INPUT: - Silent - if true then function output report - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testlincgunit_complextest(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - lincgstate state; - lincgreport rep; - ae_matrix a; - ae_vector b; - ae_int_t n; - double c; - ae_vector x0; - ae_vector residual; - double normofresidual; - double sclr; - double na; - double nv0; - double nv1; - ae_int_t sz; - double mx; - ae_int_t i; - ae_int_t j; - ae_int_t k; - ae_int_t l; - double tmp; - ae_matrix mtx; - ae_matrix mtp; - ae_matrix mtr; - double getrnorm; - ae_int_t numofit; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&state, 0, sizeof(state)); - memset(&rep, 0, sizeof(rep)); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - memset(&x0, 0, sizeof(x0)); - memset(&residual, 0, sizeof(residual)); - memset(&mtx, 0, sizeof(mtx)); - memset(&mtp, 0, sizeof(mtp)); - memset(&mtr, 0, sizeof(mtr)); - _lincgstate_init(&state, _state, ae_true); - _lincgreport_init(&rep, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&residual, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&mtx, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&mtp, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&mtr, 0, 0, DT_REAL, _state, ae_true); - - mx = (double)(100); - n = 5; - for(sz=1; sz<=n; sz++) - { - - /* - * Generate: - * * random A with norm NA (equal to 1.0), - * * random right part B whose elements are uniformly distributed in [-MX,+MX] - * * random starting point X0 whose elements are uniformly distributed in [-MX,+MX] - */ - c = 15+15*ae_randomreal(_state); - spdmatrixrndcond(sz, c, &a, _state); - na = (double)(1); - ae_vector_set_length(&b, sz, _state); - for(i=0; i<=sz-1; i++) - { - b.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1); - } - ae_vector_set_length(&x0, sz, _state); - for(i=0; i<=sz-1; i++) - { - x0.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1); - } - ae_matrix_set_length(&mtx, sz+1, sz, _state); - - /* - * Start optimization, record its progress for further analysis - * NOTE: we set update frequency of R to 2 in order to test that R is updated correctly - */ - lincgcreate(sz, &state, _state); - lincgsetxrep(&state, ae_true, _state); - lincgsetb(&state, &b, _state); - lincgsetstartingpoint(&state, &x0, _state); - lincgsetcond(&state, (double)(0), sz, _state); - lincgsetrupdatefreq(&state, 2, _state); - numofit = 0; - getrnorm = ae_maxrealnumber; - while(lincgiteration(&state, _state)) - { - if( state.needmv ) - { - for(i=0; i<=sz-1; i++) - { - state.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=sz-1; j++) - { - state.mv.ptr.p_double[i] = state.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - } - } - if( state.needvmv ) - { - state.vmv = (double)(0); - for(i=0; i<=sz-1; i++) - { - state.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=sz-1; j++) - { - state.mv.ptr.p_double[i] = state.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*state.x.ptr.p_double[j]; - } - state.vmv = state.vmv+state.mv.ptr.p_double[i]*state.x.ptr.p_double[i]; - } - } - if( state.needprec ) - { - for(i=0; i<=sz-1; i++) - { - state.pv.ptr.p_double[i] = state.x.ptr.p_double[i]; - } - } - if( state.xupdated ) - { - - /* - * Save current point to MtX, it will be used later for additional tests - */ - if( numofit>=mtx.rows ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=sz-1; i++) - { - mtx.ptr.pp_double[numofit][i] = state.x.ptr.p_double[i]; - } - getrnorm = state.r2; - numofit = numofit+1; - } - } - lincgresults(&state, &x0, &rep, _state); - if( ae_fp_neq(getrnorm,rep.r2) ) - { - if( !silent ) - { - printf("IterationsCount=%0d;\nNMV=%0d;\nTerminationType=%0d;\n", - (int)(rep.iterationscount), - (int)(rep.nmv), - (int)(rep.terminationtype)); - printf("Size=%0d;\nCond=%0.5f;\nComplexTest::Fail::GetRNorm<>Rep.R2!(%0.2e<>%0.2e)\n", - (int)(sz), - (double)(c), - (double)(getrnorm), - (double)(rep.r2)); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Calculate residual, check result - */ - ae_vector_set_length(&residual, sz, _state); - for(i=0; i<=sz-1; i++) - { - tmp = (double)(0); - for(j=0; j<=sz-1; j++) - { - tmp = tmp+a.ptr.pp_double[i][j]*x0.ptr.p_double[j]; - } - residual.ptr.p_double[i] = b.ptr.p_double[i]-tmp; - } - normofresidual = (double)(0); - for(i=0; i<=sz-1; i++) - { - if( ae_fp_greater(ae_fabs(residual.ptr.p_double[i], _state),testlincgunit_e0) ) - { - if( !silent ) - { - printf("IterationsCount=%0d;\nNMV=%0d;\nTerminationType=%0d;\n", - (int)(rep.iterationscount), - (int)(rep.nmv), - (int)(rep.terminationtype)); - printf("Size=%0d;\nCond=%0.5f;\nComplexTest::Fail::Discripancy[%0d]>E0!(%0.2e>%0.2e)\n", - (int)(sz), - (double)(c), - (int)(i), - (double)(residual.ptr.p_double[i]), - (double)(testlincgunit_e0)); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - normofresidual = normofresidual+residual.ptr.p_double[i]*residual.ptr.p_double[i]; - } - if( ae_fp_greater(ae_fabs(normofresidual-rep.r2, _state),testlincgunit_e0) ) - { - if( !silent ) - { - printf("IterationsCount=%0d;\nNMV=%0d;\nTerminationType=%0d;\n", - (int)(rep.iterationscount), - (int)(rep.nmv), - (int)(rep.terminationtype)); - printf("Size=%0d;\nCond=%0.5f;\nComplexTest::Fail::||NormOfResidual-Rep.R2||>E0!(%0.2e>%0.2e)\n", - (int)(sz), - (double)(c), - (double)(ae_fabs(normofresidual-rep.r2, _state)), - (double)(testlincgunit_e0)); - printf("NormOfResidual=%0.2e; Rep.R2=%0.2e\n", - (double)(normofresidual), - (double)(rep.r2)); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Check algorithm properties (conjugacy/orthogonality). - * Here we use MtX which was filled during algorithm progress towards solution. - * - * NOTE: this test is skipped when algorithm converged in less than SZ iterations. - */ - if( sz>1&&rep.iterationscount==sz ) - { - ae_matrix_set_length(&mtp, sz, sz, _state); - ae_matrix_set_length(&mtr, sz, sz, _state); - for(i=0; i<=sz-1; i++) - { - for(j=0; j<=sz-1; j++) - { - mtp.ptr.pp_double[i][j] = mtx.ptr.pp_double[i+1][j]-mtx.ptr.pp_double[i][j]; - tmp = (double)(0); - for(k=0; k<=sz-1; k++) - { - tmp = tmp+a.ptr.pp_double[j][k]*mtx.ptr.pp_double[i][k]; - } - mtr.ptr.pp_double[i][j] = b.ptr.p_double[j]-tmp; - } - } - - /* - *(Api,pj)=0? - */ - sclr = (double)(0); - nv0 = (double)(0); - nv1 = (double)(0); - for(i=0; i<=sz-1; i++) - { - for(j=0; j<=sz-1; j++) - { - if( i==j ) - { - continue; - } - for(k=0; k<=sz-1; k++) - { - tmp = (double)(0); - for(l=0; l<=sz-1; l++) - { - tmp = tmp+a.ptr.pp_double[k][l]*mtp.ptr.pp_double[i][l]; - } - sclr = sclr+tmp*mtp.ptr.pp_double[j][k]; - nv0 = nv0+mtp.ptr.pp_double[i][k]*mtp.ptr.pp_double[i][k]; - nv1 = nv1+mtp.ptr.pp_double[j][k]*mtp.ptr.pp_double[j][k]; - } - nv0 = ae_sqrt(nv0, _state); - nv1 = ae_sqrt(nv1, _state); - if( ae_fp_greater(ae_fabs(sclr, _state),testlincgunit_e0*na*nv0*nv1) ) - { - if( !silent ) - { - printf("IterationsCount=%0d;\nNMV=%0d;\nTerminationType=%0d;\n", - (int)(rep.iterationscount), - (int)(rep.nmv), - (int)(rep.terminationtype)); - printf("Size=%0d;\nCond=%0.5f;\nComplexTest::Fail::(Ap%0d,p%0d)!=0\n{Sclr=%0.15f; NA=%0.15f NV0=%0.15f NV1=%0.15f;}\n", - (int)(sz), - (double)(c), - (int)(i), - (int)(j), - (double)(sclr), - (double)(na), - (double)(nv0), - (double)(nv1)); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - - /* - *(ri,pj)=0? - */ - for(i=1; i<=sz-1; i++) - { - for(j=0; j<=i-1; j++) - { - sclr = (double)(0); - nv0 = (double)(0); - nv1 = (double)(0); - for(k=0; k<=sz-1; k++) - { - sclr = sclr+mtr.ptr.pp_double[i][k]*mtp.ptr.pp_double[j][k]; - nv0 = nv0+mtr.ptr.pp_double[i][k]*mtr.ptr.pp_double[i][k]; - nv1 = nv1+mtp.ptr.pp_double[j][k]*mtp.ptr.pp_double[j][k]; - } - nv0 = ae_sqrt(nv0, _state); - nv1 = ae_sqrt(nv1, _state); - if( ae_fp_greater(ae_fabs(sclr, _state),testlincgunit_e0*nv0*nv1) ) - { - if( !silent ) - { - printf("IterationsCount=%0d;\nNMV=%0d;\nTerminationType=%0d;\n", - (int)(rep.iterationscount), - (int)(rep.nmv), - (int)(rep.terminationtype)); - printf("Size=%0d;\nCond=%0.5f;\nComplexTest::Fail::(r%0d,p%0d)!=0\n{Sclr=%0.15f; NV0=%0.15f NV1=%0.15f;}\n", - (int)(sz), - (double)(c), - (int)(i), - (int)(j), - (double)(sclr), - (double)(nv0), - (double)(nv1)); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - - /* - *(ri,rj)=0? - */ - for(i=0; i<=sz-1; i++) - { - for(j=i+1; j<=sz-1; j++) - { - sclr = (double)(0); - nv0 = (double)(0); - nv1 = (double)(0); - for(k=0; k<=sz-1; k++) - { - sclr = sclr+mtr.ptr.pp_double[i][k]*mtr.ptr.pp_double[j][k]; - nv0 = nv0+mtr.ptr.pp_double[i][k]*mtr.ptr.pp_double[i][k]; - nv1 = nv1+mtr.ptr.pp_double[j][k]*mtr.ptr.pp_double[j][k]; - } - nv0 = ae_sqrt(nv0, _state); - nv1 = ae_sqrt(nv1, _state); - if( ae_fp_greater(ae_fabs(sclr, _state),testlincgunit_e0*nv0*nv1) ) - { - if( !silent ) - { - printf("IterationsCount=%0d;\nNMV=%0d;\nTerminationType=%0d;\n", - (int)(rep.iterationscount), - (int)(rep.nmv), - (int)(rep.terminationtype)); - printf("Size=%0d;\nCond=%0.5f;\nComplexTest::Fail::(rm,rk)!=0\n{Sclr=%0.15f; NV0=%0.15f NV1=%0.15f;}\n", - (int)(sz), - (double)(c), - (double)(sclr), - (double)(nv0), - (double)(nv1)); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - } - if( !silent ) - { - printf("ComplexTest::Ok\n"); - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function prepare problem with a known solution 'Xs'(A*Xs-b=0). There -b is A*Xs. After, function check algorithm result and 'Xs'. -There used two stopping criterions: - 1. achieved the required precision(StCrit=0); - 2. execution of the required number of iterations(StCrit=1). - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testlincgunit_complexres(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - lincgstate s; - lincgreport rep; - ae_matrix a; - ae_vector b; - ae_vector xs; - ae_vector x0; - double err; - ae_int_t n; - ae_int_t sz; - double c; - ae_int_t i; - ae_int_t j; - ae_int_t stcrit; - double mx; - double tmp; - double eps; - ae_int_t xp; - ae_int_t nxp; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - memset(&xs, 0, sizeof(xs)); - memset(&x0, 0, sizeof(x0)); - _lincgstate_init(&s, _state, ae_true); - _lincgreport_init(&rep, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xs, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - - sz = 5; - mx = (double)(100); - nxp = 100; - for(xp=0; xp<=nxp-1; xp++) - { - for(n=1; n<=sz; n++) - { - for(stcrit=0; stcrit<=1; stcrit++) - { - - /* - * Generate: - * * random A with norm NA (equal to 1.0), - * * random solution XS whose elements are uniformly distributed in [-MX,+MX] - * * random starting point X0 whose elements are uniformly distributed in [-MX,+MX] - * * B = A*Xs - */ - c = (testlincgunit_maxcond-1)*ae_randomreal(_state)+1; - spdmatrixrndcond(n, c, &a, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&xs, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1); - xs.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1); - } - eps = (double)(0); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - b.ptr.p_double[i] = b.ptr.p_double[i]+a.ptr.pp_double[i][j]*xs.ptr.p_double[j]; - } - eps = eps+b.ptr.p_double[i]*b.ptr.p_double[i]; - } - eps = 1.0E-6*ae_sqrt(eps, _state); - - /* - * Solve with different stopping criteria - */ - lincgcreate(n, &s, _state); - lincgsetb(&s, &b, _state); - lincgsetstartingpoint(&s, &x0, _state); - lincgsetxrep(&s, ae_true, _state); - if( stcrit==0 ) - { - lincgsetcond(&s, 1.0E-6, 0, _state); - } - else - { - lincgsetcond(&s, (double)(0), n, _state); - } - while(lincgiteration(&s, _state)) - { - if( s.needmv ) - { - for(i=0; i<=n-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - } - } - if( s.needvmv ) - { - s.vmv = (double)(0); - for(i=0; i<=n-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - s.vmv = s.vmv+s.mv.ptr.p_double[i]*s.x.ptr.p_double[i]; - } - } - if( s.needprec ) - { - for(i=0; i<=n-1; i++) - { - s.pv.ptr.p_double[i] = s.x.ptr.p_double[i]; - } - } - } - lincgresults(&s, &x0, &rep, _state); - - /* - * Check result - */ - err = 0.0; - for(i=0; i<=n-1; i++) - { - tmp = (double)(0); - for(j=0; j<=n-1; j++) - { - tmp = tmp+a.ptr.pp_double[i][j]*x0.ptr.p_double[j]; - } - err = err+ae_sqr(b.ptr.p_double[i]-tmp, _state); - } - err = ae_sqrt(err, _state); - if( ae_fp_greater(err,eps) ) - { - if( !silent ) - { - printf("ComplexRes::fail\n"); - printf("IterationsCount=%0d\n", - (int)(rep.iterationscount)); - printf("NMV=%0d\n", - (int)(rep.nmv)); - printf("TerminationType=%0d\n", - (int)(rep.terminationtype)); - printf("X and Xs...\n"); - for(j=0; j<=n-1; j++) - { - printf("x[%0d]=%0.10f; xs[%0d]=%0.10f\n", - (int)(j), - (double)(x0.ptr.p_double[j]), - (int)(j), - (double)(xs.ptr.p_double[j])); - } - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - - /* - *test has been passed - */ - if( !silent ) - { - printf("ComplexRes::Ok\n"); - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function check, that XUpdated return State.X=X0 at zero iteration and -State.X=X(algorithm result) at last. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testlincgunit_basictestx(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - lincgstate s; - lincgreport rep; - ae_matrix a; - ae_vector b; - ae_vector x0; - ae_vector x00; - ae_vector x01; - ae_int_t n; - ae_int_t sz; - double c; - ae_int_t i; - ae_int_t j; - double mx; - ae_int_t iters; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - memset(&x0, 0, sizeof(x0)); - memset(&x00, 0, sizeof(x00)); - memset(&x01, 0, sizeof(x01)); - _lincgstate_init(&s, _state, ae_true); - _lincgreport_init(&rep, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x00, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x01, 0, DT_REAL, _state, ae_true); - - sz = 5; - mx = (double)(100); - for(n=1; n<=sz; n++) - { - - /* - * Generate: - * * random A with norm NA (equal to 1.0), - * * random right part B whose elements are uniformly distributed in [-MX,+MX] - * * random starting point X0 whose elements are uniformly distributed in [-MX,+MX] - */ - c = (testlincgunit_maxcond-1)*ae_randomreal(_state)+1; - spdmatrixrndcond(n, c, &a, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&x00, n, _state); - ae_vector_set_length(&x01, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1); - b.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1); - } - - /* - * Solve, save first and last reported points to x00 and x01 - */ - lincgcreate(n, &s, _state); - lincgsetb(&s, &b, _state); - lincgsetstartingpoint(&s, &x0, _state); - lincgsetxrep(&s, ae_true, _state); - lincgsetcond(&s, (double)(0), n, _state); - iters = 0; - while(lincgiteration(&s, _state)) - { - if( s.needmv ) - { - for(i=0; i<=n-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - } - } - if( s.needvmv ) - { - s.vmv = (double)(0); - for(i=0; i<=n-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - s.vmv = s.vmv+s.mv.ptr.p_double[i]*s.x.ptr.p_double[i]; - } - } - if( s.needprec ) - { - for(i=0; i<=n-1; i++) - { - s.pv.ptr.p_double[i] = s.x.ptr.p_double[i]; - } - } - if( s.xupdated ) - { - if( iters==0 ) - { - for(i=0; i<=n-1; i++) - { - x00.ptr.p_double[i] = s.x.ptr.p_double[i]; - } - } - if( iters==n ) - { - for(i=0; i<=n-1; i++) - { - x01.ptr.p_double[i] = s.x.ptr.p_double[i]; - } - } - iters = iters+1; - } - } - - /* - * Check first and last points - */ - for(i=0; i<=n-1; i++) - { - if( ae_fp_neq(x00.ptr.p_double[i],x0.ptr.p_double[i]) ) - { - if( !silent ) - { - printf("BasicTestX::fail\n"); - printf("IterationsCount=%0d\n", - (int)(rep.iterationscount)); - printf("NMV=%0d\n", - (int)(rep.nmv)); - printf("TerminationType=%0d\n", - (int)(rep.terminationtype)); - for(j=0; j<=n-1; j++) - { - printf("x0=%0.5f; x00=%0.5f;\n", - (double)(x0.ptr.p_double[j]), - (double)(x00.ptr.p_double[j])); - } - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - lincgresults(&s, &x0, &rep, _state); - for(i=0; i<=n-1; i++) - { - if( ae_fp_neq(x01.ptr.p_double[i],x0.ptr.p_double[i]) ) - { - if( !silent ) - { - printf("BasicTestX::fail\n"); - printf("IterationsCount=%0d\n", - (int)(rep.iterationscount)); - printf("NMV=%0d\n", - (int)(rep.nmv)); - printf("TerminationType=%0d\n", - (int)(rep.terminationtype)); - for(j=0; j<=n-1; j++) - { - printf("x0=%0.5f; x01=%0.5f;\n", - (double)(x0.ptr.p_double[j]), - (double)(x01.ptr.p_double[j])); - } - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - - /* - *test has been passed - */ - if( !silent ) - { - printf("BasicTestIters::Ok\n"); - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function checks that XUpdated returns correct State.R2. It creates -large badly conditioned problem (N=50), which should be large enough and -ill-conditioned enough to cause periodic recalculation of R. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testlincgunit_testrcorrectness(ae_bool silent, - ae_state *_state) -{ - ae_frame _frame_block; - lincgstate s; - lincgreport rep; - ae_matrix a; - ae_vector b; - ae_int_t n; - double c; - ae_int_t i; - ae_int_t j; - double r2; - double v; - double rtol; - ae_int_t maxits; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - _lincgstate_init(&s, _state, ae_true); - _lincgreport_init(&rep, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - - rtol = 1.0E6*ae_machineepsilon; - n = 50; - maxits = n/2; - c = (double)(10000); - spdmatrixrndcond(n, c, &a, _state); - ae_vector_set_length(&b, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - lincgcreate(n, &s, _state); - lincgsetb(&s, &b, _state); - lincgsetxrep(&s, ae_true, _state); - lincgsetcond(&s, (double)(0), maxits, _state); - while(lincgiteration(&s, _state)) - { - if( s.needmv ) - { - for(i=0; i<=n-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - } - } - if( s.needvmv ) - { - s.vmv = (double)(0); - for(i=0; i<=n-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - s.vmv = s.vmv+s.mv.ptr.p_double[i]*s.x.ptr.p_double[i]; - } - } - if( s.needprec ) - { - for(i=0; i<=n-1; i++) - { - s.pv.ptr.p_double[i] = s.x.ptr.p_double[i]; - } - } - if( s.xupdated ) - { - - /* - * calculate R2, compare with value returned in state.R2 - */ - r2 = (double)(0); - for(i=0; i<=n-1; i++) - { - v = (double)(0); - for(j=0; j<=n-1; j++) - { - v = v+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - r2 = r2+ae_sqr(v-b.ptr.p_double[i], _state); - } - if( ae_fp_greater(ae_fabs(r2-s.r2, _state),rtol) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - lincgresults(&s, &b, &rep, _state); - if( rep.iterationscount!=maxits ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function check, that number of iterations are't more than MaxIts. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testlincgunit_basictestiters(ae_bool silent, - ae_state *_state) -{ - ae_frame _frame_block; - lincgstate s; - lincgreport rep; - ae_matrix a; - ae_vector b; - ae_vector x0; - ae_int_t n; - ae_int_t sz; - double c; - ae_int_t i; - ae_int_t j; - double mx; - ae_int_t iters; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - memset(&x0, 0, sizeof(x0)); - _lincgstate_init(&s, _state, ae_true); - _lincgreport_init(&rep, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - - sz = 5; - mx = (double)(100); - for(n=1; n<=sz; n++) - { - - /* - * Generate: - * * random A with norm NA (equal to 1.0), - * * random right part B whose elements are uniformly distributed in [-MX,+MX] - * * random starting point X0 whose elements are uniformly distributed in [-MX,+MX] - */ - c = (testlincgunit_maxcond-1)*ae_randomreal(_state)+1; - spdmatrixrndcond(n, c, &a, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x0, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1); - b.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1); - } - - /* - * Solve - */ - lincgcreate(n, &s, _state); - lincgsetb(&s, &b, _state); - lincgsetstartingpoint(&s, &x0, _state); - lincgsetxrep(&s, ae_true, _state); - lincgsetcond(&s, (double)(0), n, _state); - iters = 0; - while(lincgiteration(&s, _state)) - { - if( s.needmv ) - { - for(i=0; i<=n-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - } - } - if( s.needvmv ) - { - s.vmv = (double)(0); - for(i=0; i<=n-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - s.vmv = s.vmv+s.mv.ptr.p_double[i]*s.x.ptr.p_double[i]; - } - } - if( s.needprec ) - { - for(i=0; i<=n-1; i++) - { - s.pv.ptr.p_double[i] = s.x.ptr.p_double[i]; - } - } - if( s.xupdated ) - { - iters = iters+1; - } - } - lincgresults(&s, &x0, &rep, _state); - - /* - * Check - */ - if( iters!=rep.iterationscount+1||iters>n+1 ) - { - if( !silent ) - { - printf("BasicTestIters::fail\n"); - printf("IterationsCount=%0d\n", - (int)(rep.iterationscount)); - printf("NMV=%0d\n", - (int)(rep.nmv)); - printf("TerminationType=%0d\n", - (int)(rep.terminationtype)); - printf("Iters=%0d\n", - (int)(iters)); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Restart problem - */ - c = (testlincgunit_maxcond-1)*ae_randomreal(_state)+1; - spdmatrixrndcond(n, c, &a, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1); - b.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1); - } - lincgsetstartingpoint(&s, &x0, _state); - lincgrestart(&s, _state); - lincgsetb(&s, &b, _state); - iters = 0; - while(lincgiteration(&s, _state)) - { - if( s.needmv ) - { - for(i=0; i<=n-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - } - } - if( s.needvmv ) - { - s.vmv = (double)(0); - for(i=0; i<=n-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - s.vmv = s.vmv+s.mv.ptr.p_double[i]*s.x.ptr.p_double[i]; - } - } - if( s.needprec ) - { - for(i=0; i<=n-1; i++) - { - s.pv.ptr.p_double[i] = s.x.ptr.p_double[i]; - } - } - if( s.xupdated ) - { - iters = iters+1; - } - } - lincgresults(&s, &x0, &rep, _state); - - /* - *check - */ - if( iters!=rep.iterationscount+1||iters>n+1 ) - { - if( !silent ) - { - printf("BasicTestIters::fail\n"); - printf("IterationsCount=%0d\n", - (int)(rep.iterationscount)); - printf("NMV=%0d\n", - (int)(rep.nmv)); - printf("TerminationType=%0d\n", - (int)(rep.terminationtype)); - printf("Iters=%0d\n", - (int)(iters)); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - - /* - *test has been passed - */ - if( !silent ) - { - printf("BasicTestIters::Ok\n"); - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -This function check, that programmed method is Krylov subspace methed. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testlincgunit_krylovsubspacetest(ae_bool silent, - ae_state *_state) -{ - ae_frame _frame_block; - lincgstate s; - lincgreport rep; - ae_matrix a; - ae_vector b; - ae_vector x0; - ae_matrix ksr; - ae_vector r0; - ae_vector tarray; - ae_matrix mtx; - ae_int_t n; - ae_int_t sz; - double c; - ae_int_t i; - ae_int_t j; - ae_int_t l; - ae_int_t m; - double mx; - double tmp; - double normr0; - ae_int_t numofit; - ae_int_t maxits; - ae_int_t k2; - double eps; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - memset(&x0, 0, sizeof(x0)); - memset(&ksr, 0, sizeof(ksr)); - memset(&r0, 0, sizeof(r0)); - memset(&tarray, 0, sizeof(tarray)); - memset(&mtx, 0, sizeof(mtx)); - _lincgstate_init(&s, _state, ae_true); - _lincgreport_init(&rep, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ksr, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&r0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tarray, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&mtx, 0, 0, DT_REAL, _state, ae_true); - - eps = 1.0E-6; - maxits = 3; - sz = 5; - mx = (double)(100); - for(n=1; n<=sz; n++) - { - - /* - * Generate: - * * random A with unit norm - * * cond(A) in [0.5*MaxCond, 1.0*MaxCond] - * * random x0 and b such that |A*x0-b| is large enough for algorithm to make at least one iteration. - * - * IMPORTANT: it is very important to have cond(A) both (1) not very large and - * (2) not very small. Large cond(A) will make our problem ill-conditioned, - * thus analytic properties won't hold. Small cond(A), from the other side, - * will give us rapid convergence of the algorithm - in fact, too rapid. - * Krylov basis will be dominated by numerical noise and test may fail. - */ - c = testlincgunit_maxcond*(0.5*ae_randomreal(_state)+0.5); - spdmatrixrndcond(n, c, &a, _state); - ae_matrix_set_length(&mtx, n+1, n, _state); - ae_matrix_set_length(&ksr, n, n, _state); - ae_vector_set_length(&r0, n, _state); - ae_vector_set_length(&tarray, n, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&x0, n, _state); - do - { - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1); - b.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1); - } - normr0 = (double)(0); - for(i=0; i<=n-1; i++) - { - tmp = (double)(0); - for(j=0; j<=n-1; j++) - { - tmp = tmp+a.ptr.pp_double[i][j]*x0.ptr.p_double[j]; - } - r0.ptr.p_double[i] = b.ptr.p_double[i]-tmp; - normr0 = normr0+r0.ptr.p_double[i]*r0.ptr.p_double[i]; - } - } - while(ae_fp_less_eq(ae_sqrt(normr0, _state),eps)); - - /* - * Fill KSR by {r0, A*r0, A^2*r0, ... } - */ - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - ksr.ptr.pp_double[i][j] = r0.ptr.p_double[j]; - } - for(j=0; j<=i-1; j++) - { - for(l=0; l<=n-1; l++) - { - tarray.ptr.p_double[l] = (double)(0); - for(m=0; m<=n-1; m++) - { - tarray.ptr.p_double[l] = tarray.ptr.p_double[l]+a.ptr.pp_double[l][m]*ksr.ptr.pp_double[i][m]; - } - } - for(l=0; l<=n-1; l++) - { - ksr.ptr.pp_double[i][l] = tarray.ptr.p_double[l]; - } - } - } - - /* - * Solve system, record intermediate points for futher analysis. - * NOTE: we set update frequency of R to 2 in order to test that R is updated correctly - */ - lincgcreate(n, &s, _state); - lincgsetb(&s, &b, _state); - lincgsetstartingpoint(&s, &x0, _state); - lincgsetxrep(&s, ae_true, _state); - lincgsetcond(&s, (double)(0), n, _state); - lincgsetrupdatefreq(&s, 2, _state); - numofit = 0; - while(lincgiteration(&s, _state)) - { - if( s.needmv ) - { - for(i=0; i<=n-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - } - } - if( s.needvmv ) - { - s.vmv = (double)(0); - for(i=0; i<=n-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - s.vmv = s.vmv+s.mv.ptr.p_double[i]*s.x.ptr.p_double[i]; - } - } - if( s.needprec ) - { - for(i=0; i<=n-1; i++) - { - s.pv.ptr.p_double[i] = s.x.ptr.p_double[i]; - } - } - if( s.xupdated ) - { - for(i=0; i<=n-1; i++) - { - mtx.ptr.pp_double[numofit][i] = s.x.ptr.p_double[i]; - } - numofit = numofit+1; - } - } - - /* - * Check that I-th step S_i=X[I+1]-X[i] belongs to I-th Krylov subspace. - * Checks are done for first K2 steps, with K2 small enough to avoid - * numerical errors. - */ - if( n<=maxits ) - { - k2 = n; - } - else - { - k2 = maxits; - } - for(i=0; i<=k2-1; i++) - { - for(j=0; j<=n-1; j++) - { - tarray.ptr.p_double[j] = mtx.ptr.pp_double[i+1][j]-mtx.ptr.pp_double[i][j]; - } - if( !testlincgunit_frombasis(&tarray, &ksr, n, i+1, testlincgunit_e0, _state) ) - { - if( !silent ) - { - printf("KrylovSubspaceTest::FAIL\n"); - printf("Size=%0d; Iters=%0d;\n", - (int)(n), - (int)(i)); - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - if( !silent ) - { - printf("KrylovSubspaceTest::OK\n"); - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Function for testing LinCgSolveSparse. This function prepare problem with -a known solution 'Xs'(A*Xs-b=0). There b is A*Xs. After, function calculate -result by LinCGSolveSparse and compares it with 'Xs'. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testlincgunit_sparsetest(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - lincgstate s; - lincgreport rep; - ae_matrix a; - ae_vector b; - ae_vector xs; - ae_vector x0; - ae_vector x1; - sparsematrix uppera; - sparsematrix lowera; - double err; - ae_int_t n; - ae_int_t sz; - double c; - ae_int_t i; - ae_int_t j; - double mx; - double eps; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&a, 0, sizeof(a)); - memset(&b, 0, sizeof(b)); - memset(&xs, 0, sizeof(xs)); - memset(&x0, 0, sizeof(x0)); - memset(&x1, 0, sizeof(x1)); - memset(&uppera, 0, sizeof(uppera)); - memset(&lowera, 0, sizeof(lowera)); - _lincgstate_init(&s, _state, ae_true); - _lincgreport_init(&rep, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xs, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x1, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&uppera, _state, ae_true); - _sparsematrix_init(&lowera, _state, ae_true); - - sz = 5; - mx = (double)(100); - for(n=1; n<=sz; n++) - { - - /* - * Generate: - * * random A with unit norm - * * random X0 (starting point) and XS (known solution) - * Copy dense A to sparse SA - */ - c = (testlincgunit_maxcond-1)*ae_randomreal(_state)+1; - spdmatrixrndcond(n, c, &a, _state); - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&xs, n, _state); - for(i=0; i<=n-1; i++) - { - xs.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1); - } - eps = (double)(0); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - b.ptr.p_double[i] = b.ptr.p_double[i]+a.ptr.pp_double[i][j]*xs.ptr.p_double[j]; - } - eps = eps+b.ptr.p_double[i]*b.ptr.p_double[i]; - } - eps = 1.0E-6*ae_sqrt(eps, _state); - sparsecreate(n, n, 0, &uppera, _state); - sparsecreate(n, n, 0, &lowera, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( j>=i ) - { - sparseset(&uppera, i, j, a.ptr.pp_double[i][j], _state); - } - if( j<=i ) - { - sparseset(&lowera, i, j, a.ptr.pp_double[i][j], _state); - } - } - } - sparseconverttocrs(&uppera, _state); - sparseconverttocrs(&lowera, _state); - - /* - * Test upper triangle - */ - lincgcreate(n, &s, _state); - lincgsetcond(&s, (double)(0), n, _state); - lincgsolvesparse(&s, &uppera, ae_true, &b, _state); - lincgresults(&s, &x0, &rep, _state); - err = (double)(0); - for(i=0; i<=n-1; i++) - { - err = err+ae_sqr(x0.ptr.p_double[i]-xs.ptr.p_double[i], _state); - } - err = ae_sqrt(err, _state); - if( ae_fp_greater(err,eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - - /* - * Test lower triangle - */ - lincgcreate(n, &s, _state); - lincgsetcond(&s, (double)(0), n, _state); - lincgsolvesparse(&s, &lowera, ae_false, &b, _state); - lincgresults(&s, &x1, &rep, _state); - err = (double)(0); - for(i=0; i<=n-1; i++) - { - err = err+ae_sqr(x1.ptr.p_double[i]-xs.ptr.p_double[i], _state); - } - err = ae_sqrt(err, _state); - if( ae_fp_greater(err,eps) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Function for testing the preconditioned conjugate gradient method. - - -- ALGLIB -- - Copyright 14.11.2011 by Bochkanov Sergey -*************************************************************************/ -static ae_bool testlincgunit_precondtest(ae_bool silent, ae_state *_state) -{ - ae_frame _frame_block; - lincgstate s; - lincgreport rep; - ae_matrix a; - ae_matrix ta; - sparsematrix sa; - ae_vector m; - ae_matrix mtx; - ae_matrix mtprex; - ae_vector de; - ae_vector rde; - ae_vector b; - ae_vector tb; - ae_vector d; - ae_vector xe; - ae_vector x0; - ae_vector tx0; - ae_vector err; - ae_int_t n; - ae_int_t sz; - ae_int_t numofit; - double c; - ae_int_t i; - ae_int_t j; - ae_int_t k; - double eps; - ae_bool bflag; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&s, 0, sizeof(s)); - memset(&rep, 0, sizeof(rep)); - memset(&a, 0, sizeof(a)); - memset(&ta, 0, sizeof(ta)); - memset(&sa, 0, sizeof(sa)); - memset(&m, 0, sizeof(m)); - memset(&mtx, 0, sizeof(mtx)); - memset(&mtprex, 0, sizeof(mtprex)); - memset(&de, 0, sizeof(de)); - memset(&rde, 0, sizeof(rde)); - memset(&b, 0, sizeof(b)); - memset(&tb, 0, sizeof(tb)); - memset(&d, 0, sizeof(d)); - memset(&xe, 0, sizeof(xe)); - memset(&x0, 0, sizeof(x0)); - memset(&tx0, 0, sizeof(tx0)); - memset(&err, 0, sizeof(err)); - _lincgstate_init(&s, _state, ae_true); - _lincgreport_init(&rep, _state, ae_true); - ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&ta, 0, 0, DT_REAL, _state, ae_true); - _sparsematrix_init(&sa, _state, ae_true); - ae_vector_init(&m, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&mtx, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&mtprex, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&de, 0, DT_REAL, _state, ae_true); - ae_vector_init(&rde, 0, DT_REAL, _state, ae_true); - ae_vector_init(&b, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tb, 0, DT_REAL, _state, ae_true); - ae_vector_init(&d, 0, DT_REAL, _state, ae_true); - ae_vector_init(&xe, 0, DT_REAL, _state, ae_true); - ae_vector_init(&x0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&tx0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&err, 0, DT_REAL, _state, ae_true); - - - /* - * Test 1. - * - * Preconditioned CG for A*x=b with preconditioner M=E*E' is algebraically - * equivalent to non-preconditioned CG for (inv(E)*A*inv(E'))*z = inv(E)*b - * with z=E'*x. - * - * We test it by generating random preconditioner, running algorithm twice - - * one time for original problem with preconditioner , another one for - * modified problem without preconditioner. - */ - sz = 5; - for(n=1; n<=sz; n++) - { - - /* - * Generate: - * * random A with unit norm - * * random positive definite diagonal preconditioner M - * * dE=sqrt(M) - * * rdE=dE^(-1) - * * tA = rdE*A*rdE - * * random x0 and b - for original preconditioned problem - * * tx0 and tb - for modified problem - */ - c = (testlincgunit_maxcond-1)*ae_randomreal(_state)+1; - spdmatrixrndcond(n, c, &a, _state); - ae_matrix_set_length(&ta, n, n, _state); - ae_matrix_set_length(&mtx, n+1, n, _state); - ae_matrix_set_length(&mtprex, n+1, n, _state); - ae_vector_set_length(&m, n, _state); - ae_vector_set_length(&de, n, _state); - ae_vector_set_length(&rde, n, _state); - for(i=0; i<=n-1; i++) - { - m.ptr.p_double[i] = ae_randomreal(_state)+0.5; - de.ptr.p_double[i] = ae_sqrt(m.ptr.p_double[i], _state); - rde.ptr.p_double[i] = 1/de.ptr.p_double[i]; - } - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - ta.ptr.pp_double[i][j] = rde.ptr.p_double[i]*a.ptr.pp_double[i][j]*rde.ptr.p_double[j]; - } - } - ae_vector_set_length(&b, n, _state); - ae_vector_set_length(&tb, n, _state); - ae_vector_set_length(&x0, n, _state); - ae_vector_set_length(&tx0, n, _state); - ae_vector_set_length(&err, n, _state); - for(i=0; i<=n-1; i++) - { - x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - b.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - eps = 1.0E-5; - for(i=0; i<=n-1; i++) - { - tx0.ptr.p_double[i] = de.ptr.p_double[i]*x0.ptr.p_double[i]; - tb.ptr.p_double[i] = rde.ptr.p_double[i]*b.ptr.p_double[i]; - } - - /* - * Solve two problems, intermediate points are saved to MtX and MtPreX - */ - lincgcreate(n, &s, _state); - lincgsetb(&s, &b, _state); - lincgsetstartingpoint(&s, &x0, _state); - lincgsetxrep(&s, ae_true, _state); - lincgsetcond(&s, (double)(0), n, _state); - numofit = 0; - while(lincgiteration(&s, _state)) - { - if( s.needmv ) - { - for(i=0; i<=n-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - } - } - if( s.needvmv ) - { - s.vmv = (double)(0); - for(i=0; i<=n-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - s.vmv = s.vmv+s.mv.ptr.p_double[i]*s.x.ptr.p_double[i]; - } - } - if( s.needprec ) - { - for(i=0; i<=n-1; i++) - { - s.pv.ptr.p_double[i] = s.x.ptr.p_double[i]/m.ptr.p_double[i]; - } - } - if( s.xupdated ) - { - if( numofit>=mtx.rows ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=n-1; i++) - { - mtx.ptr.pp_double[numofit][i] = s.x.ptr.p_double[i]; - } - numofit = numofit+1; - } - } - lincgsetstartingpoint(&s, &tx0, _state); - lincgsetb(&s, &tb, _state); - lincgrestart(&s, _state); - numofit = 0; - while(lincgiteration(&s, _state)) - { - if( s.needmv ) - { - for(i=0; i<=n-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+ta.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - } - } - if( s.needvmv ) - { - s.vmv = (double)(0); - for(i=0; i<=n-1; i++) - { - s.mv.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+ta.ptr.pp_double[i][j]*s.x.ptr.p_double[j]; - } - s.vmv = s.vmv+s.mv.ptr.p_double[i]*s.x.ptr.p_double[i]; - } - } - if( s.needprec ) - { - for(i=0; i<=n-1; i++) - { - s.pv.ptr.p_double[i] = s.x.ptr.p_double[i]; - } - } - if( s.xupdated ) - { - if( numofit>=mtprex.rows ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=n-1; i++) - { - mtprex.ptr.pp_double[numofit][i] = s.x.ptr.p_double[i]; - } - numofit = numofit+1; - } - } - - /* - * Compare results - sequence of points generated when solving original problem with - * points generated by modified problem. - */ - for(i=0; i<=numofit-1; i++) - { - for(j=0; j<=n-1; j++) - { - if( ae_fp_greater(ae_fabs(mtx.ptr.pp_double[i][j]-rde.ptr.p_double[j]*mtprex.ptr.pp_double[i][j], _state),eps) ) - { - if( !silent ) - { - printf("PrecondTest::fail\n"); - printf("Size=%0d\n", - (int)(n)); - printf("IterationsCount=%0d\n", - (int)(rep.iterationscount)); - printf("NMV=%0d\n", - (int)(rep.nmv)); - printf("TerminationType=%0d\n", - (int)(rep.terminationtype)); - printf("X and X^...\n"); - for(k=0; k<=n-1; k++) - { - printf("I=%0d; mtx[%0d]=%0.10f; mtx^[%0d]=%0.10f\n", - (int)(i), - (int)(k), - (double)(mtx.ptr.pp_double[i][k]), - (int)(k), - (double)(mtprex.ptr.pp_double[i][k])); - } - } - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - } - } - - /* - * Test 2. - * - * We test automatic diagonal preconditioning used by SolveSparse. - * In order to do so we: - * 1. generate 20*20 matrix A0 with condition number equal to 1.0E1 - * 2. generate random "exact" solution xe and right part b=A0*xe - * 3. generate random ill-conditioned diagonal scaling matrix D with - * condition number equal to 1.0E50: - * 4. transform A*x=b into badly scaled problem: - * A0*x0=b0 - * A0*D*(inv(D)*x0)=b0 - * (D*A0*D)*(inv(D)*x0)=(D*b0) - * finally we got new problem A*x=b with A=D*A0*D, b=D*b0, x=inv(D)*x0 - * - * Then we solve A*x=b: - * 1. with default preconditioner - * 2. with explicitly activayed diagonal preconditioning - * 3. with unit preconditioner. - * 1st and 2nd solutions must be close to xe, 3rd solution must be very - * far from the true one. - */ - n = 20; - spdmatrixrndcond(n, 1.0E1, &ta, _state); - ae_vector_set_length(&xe, n, _state); - for(i=0; i<=n-1; i++) - { - xe.ptr.p_double[i] = randomnormal(_state); - } - ae_vector_set_length(&b, n, _state); - for(i=0; i<=n-1; i++) - { - b.ptr.p_double[i] = (double)(0); - for(j=0; j<=n-1; j++) - { - b.ptr.p_double[i] = b.ptr.p_double[i]+ta.ptr.pp_double[i][j]*xe.ptr.p_double[j]; - } - } - ae_vector_set_length(&d, n, _state); - for(i=0; i<=n-1; i++) - { - d.ptr.p_double[i] = ae_pow((double)(10), 100*ae_randomreal(_state)-50, _state); - } - ae_matrix_set_length(&a, n, n, _state); - sparsecreate(n, n, n*n, &sa, _state); - for(i=0; i<=n-1; i++) - { - for(j=0; j<=n-1; j++) - { - a.ptr.pp_double[i][j] = d.ptr.p_double[i]*ta.ptr.pp_double[i][j]*d.ptr.p_double[j]; - sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state); - } - b.ptr.p_double[i] = b.ptr.p_double[i]*d.ptr.p_double[i]; - xe.ptr.p_double[i] = xe.ptr.p_double[i]/d.ptr.p_double[i]; - } - sparseconverttocrs(&sa, _state); - lincgcreate(n, &s, _state); - lincgsetcond(&s, (double)(0), 2*n, _state); - lincgsolvesparse(&s, &sa, ae_true, &b, _state); - lincgresults(&s, &x0, &rep, _state); - if( rep.terminationtype<=0 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-x0.ptr.p_double[i], _state),5.0E-2/d.ptr.p_double[i]) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - lincgsetprecunit(&s, _state); - lincgsolvesparse(&s, &sa, ae_true, &b, _state); - lincgresults(&s, &x0, &rep, _state); - if( rep.terminationtype>0 ) - { - bflag = ae_false; - for(i=0; i<=n-1; i++) - { - bflag = bflag||ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-x0.ptr.p_double[i], _state),5.0E-2/d.ptr.p_double[i]); - } - if( !bflag ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - lincgsetprecdiag(&s, _state); - lincgsolvesparse(&s, &sa, ae_true, &b, _state); - lincgresults(&s, &x0, &rep, _state); - if( rep.terminationtype<=0 ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - for(i=0; i<=n-1; i++) - { - if( ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-x0.ptr.p_double[i], _state),5.0E-2/d.ptr.p_double[i]) ) - { - result = ae_true; - ae_frame_leave(_state); - return result; - } - } - - /* - *test has been passed - */ - if( !silent ) - { - printf("PrecondTest::Ok\n"); - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Orthogonalization by Gram-Shmidt method. -*************************************************************************/ -static void testlincgunit_gramshmidtortnorm(/* Real */ ae_matrix* a, - ae_int_t n, - ae_int_t k, - double eps, - /* Real */ ae_matrix* b, - ae_int_t* k2, - ae_state *_state) -{ - double scaling; - double tmp; - double e; - ae_int_t i; - ae_int_t j; - ae_int_t l; - ae_int_t m; - double sc; - - ae_matrix_clear(b); - *k2 = 0; - - *k2 = 0; - scaling = (double)(0); - ae_matrix_set_length(b, k, n, _state); - for(i=0; i<=k-1; i++) - { - tmp = (double)(0); - for(j=0; j<=n-1; j++) - { - tmp = tmp+a->ptr.pp_double[i][j]*a->ptr.pp_double[i][j]; - } - if( ae_fp_greater(tmp,scaling) ) - { - scaling = tmp; - } - } - scaling = ae_sqrt(scaling, _state); - e = eps*scaling; - for(i=0; i<=k-1; i++) - { - tmp = (double)(0); - for(j=0; j<=n-1; j++) - { - b->ptr.pp_double[*k2][j] = a->ptr.pp_double[i][j]; - tmp = tmp+a->ptr.pp_double[i][j]*a->ptr.pp_double[i][j]; - } - tmp = ae_sqrt(tmp, _state); - if( ae_fp_less_eq(tmp,e) ) - { - continue; - } - for(j=0; j<=*k2-1; j++) - { - sc = (double)(0); - for(m=0; m<=n-1; m++) - { - sc = sc+b->ptr.pp_double[*k2][m]*b->ptr.pp_double[j][m]; - } - for(l=0; l<=n-1; l++) - { - b->ptr.pp_double[*k2][l] = b->ptr.pp_double[*k2][l]-sc*b->ptr.pp_double[j][l]; - } - } - tmp = (double)(0); - for(j=0; j<=n-1; j++) - { - tmp = tmp+b->ptr.pp_double[*k2][j]*b->ptr.pp_double[*k2][j]; - } - tmp = ae_sqrt(tmp, _state); - if( ae_fp_less_eq(tmp,e) ) - { - continue; - } - else - { - for(j=0; j<=n-1; j++) - { - b->ptr.pp_double[*k2][j] = b->ptr.pp_double[*k2][j]/tmp; - } - } - *k2 = *k2+1; - } -} - - -/************************************************************************* -Checks that a vector belongs to the basis. -*************************************************************************/ -static ae_bool testlincgunit_frombasis(/* Real */ ae_vector* x, - /* Real */ ae_matrix* basis, - ae_int_t n, - ae_int_t k, - double eps, - ae_state *_state) -{ - ae_frame _frame_block; - double normx; - ae_matrix ortnormbasis; - ae_int_t k2; - ae_int_t i; - ae_int_t j; - double alpha; - ae_vector alphas; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&ortnormbasis, 0, sizeof(ortnormbasis)); - memset(&alphas, 0, sizeof(alphas)); - ae_matrix_init(&ortnormbasis, 0, 0, DT_REAL, _state, ae_true); - ae_vector_init(&alphas, 0, DT_REAL, _state, ae_true); - - ae_vector_set_length(&alphas, k, _state); - - /* - *calculating NORM for X - */ - normx = (double)(0); - for(i=0; i<=n-1; i++) - { - normx = normx+x->ptr.p_double[i]*x->ptr.p_double[i]; - } - normx = ae_sqrt(normx, _state); - - /* - *Gram-Shmidt method - */ - testlincgunit_gramshmidtortnorm(basis, n, k, eps, &ortnormbasis, &k2, _state); - for(i=0; i<=k2-1; i++) - { - alpha = (double)(0); - for(j=0; j<=n-1; j++) - { - alpha = alpha+x->ptr.p_double[j]*ortnormbasis.ptr.pp_double[i][j]; - } - alphas.ptr.p_double[i] = alpha; - } - - /* - *check - */ - for(i=0; i<=n-1; i++) - { - alpha = (double)(0); - for(j=0; j<=k2-1; j++) - { - alpha = alpha+alphas.ptr.p_double[j]*ortnormbasis.ptr.pp_double[j][i]; - } - if( ae_fp_greater(ae_fabs(x->ptr.p_double[i]-alpha, _state),normx*eps) ) - { - result = ae_false; - ae_frame_leave(_state); - return result; - } - } - result = ae_true; - ae_frame_leave(_state); - return result; -} - - - -static ae_bool testalglibbasicsunit_testcomplexarithmetics(ae_bool silent, - ae_state *_state); -static ae_bool testalglibbasicsunit_testieeespecial(ae_bool silent, - ae_state *_state); -static ae_bool testalglibbasicsunit_testswapfunctions(ae_bool silent, - ae_state *_state); -static ae_bool testalglibbasicsunit_teststandardfunctions(ae_bool silent, - ae_state *_state); -static ae_bool testalglibbasicsunit_testserializationfunctions(ae_bool silent, - ae_state *_state); -static void testalglibbasicsunit_createpoolandrecords(poolrec2* seedrec2, - poolrec2* seedrec2copy, - ae_shared_pool* pool, - ae_state *_state); -static ae_bool testalglibbasicsunit_sharedpoolerrors(ae_state *_state); -static ae_bool testalglibbasicsunit_testsharedpool(ae_bool silent, - ae_state *_state); -static void testalglibbasicsunit_testsort0func(/* Integer */ ae_vector* a, - /* Integer */ ae_vector* buf, - ae_int_t idx0, - ae_int_t idx2, - ae_state *_state); -ae_bool _trypexec_testalglibbasicsunit_testsort0func(/* Integer */ ae_vector* a, - /* Integer */ ae_vector* buf, - ae_int_t idx0, - ae_int_t idx2, ae_state *_state); -static ae_bool testalglibbasicsunit_performtestsort0(ae_state *_state); -static void testalglibbasicsunit_testsort1func(/* Integer */ ae_vector* a, - /* Integer */ ae_vector* buf, - ae_int_t idx0, - ae_int_t idx2, - ae_bool usesmp, - ae_state *_state); -ae_bool _trypexec_testalglibbasicsunit_testsort1func(/* Integer */ ae_vector* a, - /* Integer */ ae_vector* buf, - ae_int_t idx0, - ae_int_t idx2, - ae_bool usesmp, ae_state *_state); -static ae_bool testalglibbasicsunit_performtestsort1(ae_state *_state); -static void testalglibbasicsunit_testsort2func(/* Integer */ ae_vector* a, - /* Integer */ ae_vector* buf, - ae_int_t idx0, - ae_int_t idx2, - ae_state *_state); -ae_bool _trypexec_testalglibbasicsunit_testsort2func(/* Integer */ ae_vector* a, - /* Integer */ ae_vector* buf, - ae_int_t idx0, - ae_int_t idx2, ae_state *_state); -static ae_bool testalglibbasicsunit_performtestsort2(ae_state *_state); -static ae_bool testalglibbasicsunit_performtestpoolsum(ae_state *_state); -static void testalglibbasicsunit_parallelpoolsum(ae_shared_pool* sumpool, - ae_int_t ind0, - ae_int_t ind1, - ae_state *_state); -ae_bool _trypexec_testalglibbasicsunit_parallelpoolsum(ae_shared_pool* sumpool, - ae_int_t ind0, - ae_int_t ind1, ae_state *_state); -static void testalglibbasicsunit_mergesortedarrays(/* Integer */ ae_vector* a, - /* Integer */ ae_vector* buf, - ae_int_t idx0, - ae_int_t idx1, - ae_int_t idx2, - ae_state *_state); -ae_bool _trypexec_testalglibbasicsunit_mergesortedarrays(/* Integer */ ae_vector* a, - /* Integer */ ae_vector* buf, - ae_int_t idx0, - ae_int_t idx1, - ae_int_t idx2, ae_state *_state); -static ae_bool testalglibbasicsunit_testsmp(ae_bool silent, - ae_state *_state); - - - - - -void rec4serializationalloc(ae_serializer* s, - rec4serialization* v, - ae_state *_state) -{ - ae_int_t i; - - - - /* - * boolean fields - */ - ae_serializer_alloc_entry(s); - for(i=0; i<=v->b.cnt-1; i++) - { - ae_serializer_alloc_entry(s); - } - - /* - * integer fields - */ - ae_serializer_alloc_entry(s); - for(i=0; i<=v->i.cnt-1; i++) - { - ae_serializer_alloc_entry(s); - } - - /* - * real fields - */ - ae_serializer_alloc_entry(s); - for(i=0; i<=v->r.cnt-1; i++) - { - ae_serializer_alloc_entry(s); - } -} - - -void rec4serializationserialize(ae_serializer* s, - rec4serialization* v, - ae_state *_state) -{ - ae_int_t i; - - - - /* - * boolean fields - */ - ae_serializer_serialize_int(s, v->b.cnt, _state); - for(i=0; i<=v->b.cnt-1; i++) - { - ae_serializer_serialize_bool(s, v->b.ptr.p_bool[i], _state); - } - - /* - * integer fields - */ - ae_serializer_serialize_int(s, v->i.cnt, _state); - for(i=0; i<=v->i.cnt-1; i++) - { - ae_serializer_serialize_int(s, v->i.ptr.p_int[i], _state); - } - - /* - * real fields - */ - ae_serializer_serialize_int(s, v->r.cnt, _state); - for(i=0; i<=v->r.cnt-1; i++) - { - ae_serializer_serialize_double(s, v->r.ptr.p_double[i], _state); - } -} - - -void rec4serializationunserialize(ae_serializer* s, - rec4serialization* v, - ae_state *_state) -{ - ae_int_t i; - ae_int_t k; - ae_bool bv; - ae_int_t iv; - double rv; - - _rec4serialization_clear(v); - - - /* - * boolean fields - */ - ae_serializer_unserialize_int(s, &k, _state); - if( k>0 ) - { - ae_vector_set_length(&v->b, k, _state); - for(i=0; i<=k-1; i++) - { - ae_serializer_unserialize_bool(s, &bv, _state); - v->b.ptr.p_bool[i] = bv; - } - } - - /* - * integer fields - */ - ae_serializer_unserialize_int(s, &k, _state); - if( k>0 ) - { - ae_vector_set_length(&v->i, k, _state); - for(i=0; i<=k-1; i++) - { - ae_serializer_unserialize_int(s, &iv, _state); - v->i.ptr.p_int[i] = iv; - } - } - - /* - * real fields - */ - ae_serializer_unserialize_int(s, &k, _state); - if( k>0 ) - { - ae_vector_set_length(&v->r, k, _state); - for(i=0; i<=k-1; i++) - { - ae_serializer_unserialize_double(s, &rv, _state); - v->r.ptr.p_double[i] = rv; - } - } -} - - -ae_bool testalglibbasics(ae_bool silent, ae_state *_state) -{ - ae_bool result; - - - result = ae_true; - result = result&&testalglibbasicsunit_testcomplexarithmetics(silent, _state); - result = result&&testalglibbasicsunit_testieeespecial(silent, _state); - result = result&&testalglibbasicsunit_testswapfunctions(silent, _state); - result = result&&testalglibbasicsunit_teststandardfunctions(silent, _state); - result = result&&testalglibbasicsunit_testserializationfunctions(silent, _state); - result = result&&testalglibbasicsunit_testsharedpool(silent, _state); - result = result&&testalglibbasicsunit_testsmp(silent, _state); - if( !silent ) - { - printf("\n\n"); - } - return result; -} - - -/************************************************************************* -Complex arithmetics test -*************************************************************************/ -static ae_bool testalglibbasicsunit_testcomplexarithmetics(ae_bool silent, - ae_state *_state) -{ - ae_bool absc; - ae_bool addcc; - ae_bool addcr; - ae_bool addrc; - ae_bool subcc; - ae_bool subcr; - ae_bool subrc; - ae_bool mulcc; - ae_bool mulcr; - ae_bool mulrc; - ae_bool divcc; - ae_bool divcr; - ae_bool divrc; - ae_complex ca; - ae_complex cb; - ae_complex res; - double ra; - double rb; - double threshold; - ae_int_t pass; - ae_int_t passcount; - ae_bool result; - - - threshold = 100*ae_machineepsilon; - passcount = 1000; - result = ae_true; - absc = ae_true; - addcc = ae_true; - addcr = ae_true; - addrc = ae_true; - subcc = ae_true; - subcr = ae_true; - subrc = ae_true; - mulcc = ae_true; - mulcr = ae_true; - mulrc = ae_true; - divcc = ae_true; - divcr = ae_true; - divrc = ae_true; - for(pass=1; pass<=passcount; pass++) - { - - /* - * Test AbsC - */ - ca.x = 2*ae_randomreal(_state)-1; - ca.y = 2*ae_randomreal(_state)-1; - ra = ae_c_abs(ca, _state); - absc = absc&&ae_fp_less(ae_fabs(ra-ae_sqrt(ae_sqr(ca.x, _state)+ae_sqr(ca.y, _state), _state), _state),threshold); - - /* - * test Add - */ - ca.x = 2*ae_randomreal(_state)-1; - ca.y = 2*ae_randomreal(_state)-1; - cb.x = 2*ae_randomreal(_state)-1; - cb.y = 2*ae_randomreal(_state)-1; - ra = 2*ae_randomreal(_state)-1; - rb = 2*ae_randomreal(_state)-1; - res = ae_c_add(ca,cb); - addcc = (addcc&&ae_fp_less(ae_fabs(res.x-ca.x-cb.x, _state),threshold))&&ae_fp_less(ae_fabs(res.y-ca.y-cb.y, _state),threshold); - res = ae_c_add_d(ca,rb); - addcr = (addcr&&ae_fp_less(ae_fabs(res.x-ca.x-rb, _state),threshold))&&ae_fp_less(ae_fabs(res.y-ca.y, _state),threshold); - res = ae_c_add_d(cb,ra); - addrc = (addrc&&ae_fp_less(ae_fabs(res.x-ra-cb.x, _state),threshold))&&ae_fp_less(ae_fabs(res.y-cb.y, _state),threshold); - - /* - * test Sub - */ - ca.x = 2*ae_randomreal(_state)-1; - ca.y = 2*ae_randomreal(_state)-1; - cb.x = 2*ae_randomreal(_state)-1; - cb.y = 2*ae_randomreal(_state)-1; - ra = 2*ae_randomreal(_state)-1; - rb = 2*ae_randomreal(_state)-1; - res = ae_c_sub(ca,cb); - subcc = (subcc&&ae_fp_less(ae_fabs(res.x-(ca.x-cb.x), _state),threshold))&&ae_fp_less(ae_fabs(res.y-(ca.y-cb.y), _state),threshold); - res = ae_c_sub_d(ca,rb); - subcr = (subcr&&ae_fp_less(ae_fabs(res.x-(ca.x-rb), _state),threshold))&&ae_fp_less(ae_fabs(res.y-ca.y, _state),threshold); - res = ae_c_d_sub(ra,cb); - subrc = (subrc&&ae_fp_less(ae_fabs(res.x-(ra-cb.x), _state),threshold))&&ae_fp_less(ae_fabs(res.y+cb.y, _state),threshold); - - /* - * test Mul - */ - ca.x = 2*ae_randomreal(_state)-1; - ca.y = 2*ae_randomreal(_state)-1; - cb.x = 2*ae_randomreal(_state)-1; - cb.y = 2*ae_randomreal(_state)-1; - ra = 2*ae_randomreal(_state)-1; - rb = 2*ae_randomreal(_state)-1; - res = ae_c_mul(ca,cb); - mulcc = (mulcc&&ae_fp_less(ae_fabs(res.x-(ca.x*cb.x-ca.y*cb.y), _state),threshold))&&ae_fp_less(ae_fabs(res.y-(ca.x*cb.y+ca.y*cb.x), _state),threshold); - res = ae_c_mul_d(ca,rb); - mulcr = (mulcr&&ae_fp_less(ae_fabs(res.x-ca.x*rb, _state),threshold))&&ae_fp_less(ae_fabs(res.y-ca.y*rb, _state),threshold); - res = ae_c_mul_d(cb,ra); - mulrc = (mulrc&&ae_fp_less(ae_fabs(res.x-ra*cb.x, _state),threshold))&&ae_fp_less(ae_fabs(res.y-ra*cb.y, _state),threshold); - - /* - * test Div - */ - ca.x = 2*ae_randomreal(_state)-1; - ca.y = 2*ae_randomreal(_state)-1; - do - { - cb.x = 2*ae_randomreal(_state)-1; - cb.y = 2*ae_randomreal(_state)-1; - } - while(ae_fp_less_eq(ae_c_abs(cb, _state),0.5)); - ra = 2*ae_randomreal(_state)-1; - do - { - rb = 2*ae_randomreal(_state)-1; - } - while(ae_fp_less_eq(ae_fabs(rb, _state),0.5)); - res = ae_c_div(ca,cb); - divcc = (divcc&&ae_fp_less(ae_fabs(ae_c_mul(res,cb).x-ca.x, _state),threshold))&&ae_fp_less(ae_fabs(ae_c_mul(res,cb).y-ca.y, _state),threshold); - res = ae_c_div_d(ca,rb); - divcr = (divcr&&ae_fp_less(ae_fabs(res.x-ca.x/rb, _state),threshold))&&ae_fp_less(ae_fabs(res.y-ca.y/rb, _state),threshold); - res = ae_c_d_div(ra,cb); - divrc = (divrc&&ae_fp_less(ae_fabs(ae_c_mul(res,cb).x-ra, _state),threshold))&&ae_fp_less(ae_fabs(ae_c_mul(res,cb).y, _state),threshold); - } - - /* - * summary - */ - result = result&&absc; - result = result&&addcc; - result = result&&addcr; - result = result&&addrc; - result = result&&subcc; - result = result&&subcr; - result = result&&subrc; - result = result&&mulcc; - result = result&&mulcr; - result = result&&mulrc; - result = result&&divcc; - result = result&&divcr; - result = result&&divrc; - if( !silent ) - { - if( result ) - { - printf("COMPLEX ARITHMETICS: OK\n"); - } - else - { - printf("COMPLEX ARITHMETICS: FAILED\n"); - printf("* AddCC - - - - - - - - - - - - - - - - "); - if( addcc ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* AddCR - - - - - - - - - - - - - - - - "); - if( addcr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* AddRC - - - - - - - - - - - - - - - - "); - if( addrc ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* SubCC - - - - - - - - - - - - - - - - "); - if( subcc ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* SubCR - - - - - - - - - - - - - - - - "); - if( subcr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* SubRC - - - - - - - - - - - - - - - - "); - if( subrc ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* MulCC - - - - - - - - - - - - - - - - "); - if( mulcc ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* MulCR - - - - - - - - - - - - - - - - "); - if( mulcr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* MulRC - - - - - - - - - - - - - - - - "); - if( mulrc ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* DivCC - - - - - - - - - - - - - - - - "); - if( divcc ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* DivCR - - - - - - - - - - - - - - - - "); - if( divcr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* DivRC - - - - - - - - - - - - - - - - "); - if( divrc ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - } - } - return result; -} - - -/************************************************************************* -Tests for IEEE special quantities -*************************************************************************/ -static ae_bool testalglibbasicsunit_testieeespecial(ae_bool silent, - ae_state *_state) -{ - ae_bool oknan; - ae_bool okinf; - ae_bool okother; - double v1; - double v2; - ae_bool result; - - - result = ae_true; - oknan = ae_true; - okinf = ae_true; - okother = ae_true; - - /* - * Test classification functions - */ - okother = okother&&!ae_isinf(_state->v_nan, _state); - okother = okother&&ae_isinf(_state->v_posinf, _state); - okother = okother&&!ae_isinf(ae_maxrealnumber, _state); - okother = okother&&!ae_isinf(1.0, _state); - okother = okother&&!ae_isinf(ae_minrealnumber, _state); - okother = okother&&!ae_isinf(0.0, _state); - okother = okother&&!ae_isinf(-ae_minrealnumber, _state); - okother = okother&&!ae_isinf(-1.0, _state); - okother = okother&&!ae_isinf(-ae_maxrealnumber, _state); - okother = okother&&ae_isinf(_state->v_neginf, _state); - okother = okother&&!ae_isposinf(_state->v_nan, _state); - okother = okother&&ae_isposinf(_state->v_posinf, _state); - okother = okother&&!ae_isposinf(ae_maxrealnumber, _state); - okother = okother&&!ae_isposinf(1.0, _state); - okother = okother&&!ae_isposinf(ae_minrealnumber, _state); - okother = okother&&!ae_isposinf(0.0, _state); - okother = okother&&!ae_isposinf(-ae_minrealnumber, _state); - okother = okother&&!ae_isposinf(-1.0, _state); - okother = okother&&!ae_isposinf(-ae_maxrealnumber, _state); - okother = okother&&!ae_isposinf(_state->v_neginf, _state); - okother = okother&&!ae_isneginf(_state->v_nan, _state); - okother = okother&&!ae_isneginf(_state->v_posinf, _state); - okother = okother&&!ae_isneginf(ae_maxrealnumber, _state); - okother = okother&&!ae_isneginf(1.0, _state); - okother = okother&&!ae_isneginf(ae_minrealnumber, _state); - okother = okother&&!ae_isneginf(0.0, _state); - okother = okother&&!ae_isneginf(-ae_minrealnumber, _state); - okother = okother&&!ae_isneginf(-1.0, _state); - okother = okother&&!ae_isneginf(-ae_maxrealnumber, _state); - okother = okother&&ae_isneginf(_state->v_neginf, _state); - okother = okother&&ae_isnan(_state->v_nan, _state); - okother = okother&&!ae_isnan(_state->v_posinf, _state); - okother = okother&&!ae_isnan(ae_maxrealnumber, _state); - okother = okother&&!ae_isnan(1.0, _state); - okother = okother&&!ae_isnan(ae_minrealnumber, _state); - okother = okother&&!ae_isnan(0.0, _state); - okother = okother&&!ae_isnan(-ae_minrealnumber, _state); - okother = okother&&!ae_isnan(-1.0, _state); - okother = okother&&!ae_isnan(-ae_maxrealnumber, _state); - okother = okother&&!ae_isnan(_state->v_neginf, _state); - okother = okother&&!ae_isfinite(_state->v_nan, _state); - okother = okother&&!ae_isfinite(_state->v_posinf, _state); - okother = okother&&ae_isfinite(ae_maxrealnumber, _state); - okother = okother&&ae_isfinite(1.0, _state); - okother = okother&&ae_isfinite(ae_minrealnumber, _state); - okother = okother&&ae_isfinite(0.0, _state); - okother = okother&&ae_isfinite(-ae_minrealnumber, _state); - okother = okother&&ae_isfinite(-1.0, _state); - okother = okother&&ae_isfinite(-ae_maxrealnumber, _state); - okother = okother&&!ae_isfinite(_state->v_neginf, _state); - - /* - * Test NAN - */ - v1 = _state->v_nan; - v2 = _state->v_nan; - oknan = oknan&&ae_isnan(v1, _state); - oknan = oknan&&ae_fp_neq(v1,v2); - oknan = oknan&&!ae_fp_eq(v1,v2); - - /* - * Test INF: - * * basic properties - * * comparisons involving PosINF on one of the sides - * * comparisons involving NegINF on one of the sides - */ - v1 = _state->v_posinf; - v2 = _state->v_neginf; - okinf = okinf&&ae_isinf(_state->v_posinf, _state); - okinf = okinf&&ae_isinf(v1, _state); - okinf = okinf&&ae_isinf(_state->v_neginf, _state); - okinf = okinf&&ae_isinf(v2, _state); - okinf = okinf&&ae_isposinf(_state->v_posinf, _state); - okinf = okinf&&ae_isposinf(v1, _state); - okinf = okinf&&!ae_isposinf(_state->v_neginf, _state); - okinf = okinf&&!ae_isposinf(v2, _state); - okinf = okinf&&!ae_isneginf(_state->v_posinf, _state); - okinf = okinf&&!ae_isneginf(v1, _state); - okinf = okinf&&ae_isneginf(_state->v_neginf, _state); - okinf = okinf&&ae_isneginf(v2, _state); - okinf = okinf&&ae_fp_eq(_state->v_posinf,_state->v_posinf); - okinf = okinf&&ae_fp_eq(_state->v_posinf,v1); - okinf = okinf&&!ae_fp_eq(_state->v_posinf,_state->v_neginf); - okinf = okinf&&!ae_fp_eq(_state->v_posinf,v2); - okinf = okinf&&!ae_fp_eq(_state->v_posinf,(double)(0)); - okinf = okinf&&!ae_fp_eq(_state->v_posinf,1.2); - okinf = okinf&&!ae_fp_eq(_state->v_posinf,-1.2); - okinf = okinf&&ae_fp_eq(v1,_state->v_posinf); - okinf = okinf&&!ae_fp_eq(_state->v_neginf,_state->v_posinf); - okinf = okinf&&!ae_fp_eq(v2,_state->v_posinf); - okinf = okinf&&!ae_fp_eq((double)(0),_state->v_posinf); - okinf = okinf&&!ae_fp_eq(1.2,_state->v_posinf); - okinf = okinf&&!ae_fp_eq(-1.2,_state->v_posinf); - okinf = okinf&&!ae_fp_neq(_state->v_posinf,_state->v_posinf); - okinf = okinf&&!ae_fp_neq(_state->v_posinf,v1); - okinf = okinf&&ae_fp_neq(_state->v_posinf,_state->v_neginf); - okinf = okinf&&ae_fp_neq(_state->v_posinf,v2); - okinf = okinf&&ae_fp_neq(_state->v_posinf,(double)(0)); - okinf = okinf&&ae_fp_neq(_state->v_posinf,1.2); - okinf = okinf&&ae_fp_neq(_state->v_posinf,-1.2); - okinf = okinf&&!ae_fp_neq(v1,_state->v_posinf); - okinf = okinf&&ae_fp_neq(_state->v_neginf,_state->v_posinf); - okinf = okinf&&ae_fp_neq(v2,_state->v_posinf); - okinf = okinf&&ae_fp_neq((double)(0),_state->v_posinf); - okinf = okinf&&ae_fp_neq(1.2,_state->v_posinf); - okinf = okinf&&ae_fp_neq(-1.2,_state->v_posinf); - okinf = okinf&&!ae_fp_less(_state->v_posinf,_state->v_posinf); - okinf = okinf&&!ae_fp_less(_state->v_posinf,v1); - okinf = okinf&&!ae_fp_less(_state->v_posinf,_state->v_neginf); - okinf = okinf&&!ae_fp_less(_state->v_posinf,v2); - okinf = okinf&&!ae_fp_less(_state->v_posinf,(double)(0)); - okinf = okinf&&!ae_fp_less(_state->v_posinf,1.2); - okinf = okinf&&!ae_fp_less(_state->v_posinf,-1.2); - okinf = okinf&&!ae_fp_less(v1,_state->v_posinf); - okinf = okinf&&ae_fp_less(_state->v_neginf,_state->v_posinf); - okinf = okinf&&ae_fp_less(v2,_state->v_posinf); - okinf = okinf&&ae_fp_less((double)(0),_state->v_posinf); - okinf = okinf&&ae_fp_less(1.2,_state->v_posinf); - okinf = okinf&&ae_fp_less(-1.2,_state->v_posinf); - okinf = okinf&&ae_fp_less_eq(_state->v_posinf,_state->v_posinf); - okinf = okinf&&ae_fp_less_eq(_state->v_posinf,v1); - okinf = okinf&&!ae_fp_less_eq(_state->v_posinf,_state->v_neginf); - okinf = okinf&&!ae_fp_less_eq(_state->v_posinf,v2); - okinf = okinf&&!ae_fp_less_eq(_state->v_posinf,(double)(0)); - okinf = okinf&&!ae_fp_less_eq(_state->v_posinf,1.2); - okinf = okinf&&!ae_fp_less_eq(_state->v_posinf,-1.2); - okinf = okinf&&ae_fp_less_eq(v1,_state->v_posinf); - okinf = okinf&&ae_fp_less_eq(_state->v_neginf,_state->v_posinf); - okinf = okinf&&ae_fp_less_eq(v2,_state->v_posinf); - okinf = okinf&&ae_fp_less_eq((double)(0),_state->v_posinf); - okinf = okinf&&ae_fp_less_eq(1.2,_state->v_posinf); - okinf = okinf&&ae_fp_less_eq(-1.2,_state->v_posinf); - okinf = okinf&&!ae_fp_greater(_state->v_posinf,_state->v_posinf); - okinf = okinf&&!ae_fp_greater(_state->v_posinf,v1); - okinf = okinf&&ae_fp_greater(_state->v_posinf,_state->v_neginf); - okinf = okinf&&ae_fp_greater(_state->v_posinf,v2); - okinf = okinf&&ae_fp_greater(_state->v_posinf,(double)(0)); - okinf = okinf&&ae_fp_greater(_state->v_posinf,1.2); - okinf = okinf&&ae_fp_greater(_state->v_posinf,-1.2); - okinf = okinf&&!ae_fp_greater(v1,_state->v_posinf); - okinf = okinf&&!ae_fp_greater(_state->v_neginf,_state->v_posinf); - okinf = okinf&&!ae_fp_greater(v2,_state->v_posinf); - okinf = okinf&&!ae_fp_greater((double)(0),_state->v_posinf); - okinf = okinf&&!ae_fp_greater(1.2,_state->v_posinf); - okinf = okinf&&!ae_fp_greater(-1.2,_state->v_posinf); - okinf = okinf&&ae_fp_greater_eq(_state->v_posinf,_state->v_posinf); - okinf = okinf&&ae_fp_greater_eq(_state->v_posinf,v1); - okinf = okinf&&ae_fp_greater_eq(_state->v_posinf,_state->v_neginf); - okinf = okinf&&ae_fp_greater_eq(_state->v_posinf,v2); - okinf = okinf&&ae_fp_greater_eq(_state->v_posinf,(double)(0)); - okinf = okinf&&ae_fp_greater_eq(_state->v_posinf,1.2); - okinf = okinf&&ae_fp_greater_eq(_state->v_posinf,-1.2); - okinf = okinf&&ae_fp_greater_eq(v1,_state->v_posinf); - okinf = okinf&&!ae_fp_greater_eq(_state->v_neginf,_state->v_posinf); - okinf = okinf&&!ae_fp_greater_eq(v2,_state->v_posinf); - okinf = okinf&&!ae_fp_greater_eq((double)(0),_state->v_posinf); - okinf = okinf&&!ae_fp_greater_eq(1.2,_state->v_posinf); - okinf = okinf&&!ae_fp_greater_eq(-1.2,_state->v_posinf); - okinf = okinf&&!ae_fp_eq(_state->v_neginf,_state->v_posinf); - okinf = okinf&&!ae_fp_eq(_state->v_neginf,v1); - okinf = okinf&&ae_fp_eq(_state->v_neginf,_state->v_neginf); - okinf = okinf&&ae_fp_eq(_state->v_neginf,v2); - okinf = okinf&&!ae_fp_eq(_state->v_neginf,(double)(0)); - okinf = okinf&&!ae_fp_eq(_state->v_neginf,1.2); - okinf = okinf&&!ae_fp_eq(_state->v_neginf,-1.2); - okinf = okinf&&!ae_fp_eq(v1,_state->v_neginf); - okinf = okinf&&ae_fp_eq(_state->v_neginf,_state->v_neginf); - okinf = okinf&&ae_fp_eq(v2,_state->v_neginf); - okinf = okinf&&!ae_fp_eq((double)(0),_state->v_neginf); - okinf = okinf&&!ae_fp_eq(1.2,_state->v_neginf); - okinf = okinf&&!ae_fp_eq(-1.2,_state->v_neginf); - okinf = okinf&&ae_fp_neq(_state->v_neginf,_state->v_posinf); - okinf = okinf&&ae_fp_neq(_state->v_neginf,v1); - okinf = okinf&&!ae_fp_neq(_state->v_neginf,_state->v_neginf); - okinf = okinf&&!ae_fp_neq(_state->v_neginf,v2); - okinf = okinf&&ae_fp_neq(_state->v_neginf,(double)(0)); - okinf = okinf&&ae_fp_neq(_state->v_neginf,1.2); - okinf = okinf&&ae_fp_neq(_state->v_neginf,-1.2); - okinf = okinf&&ae_fp_neq(v1,_state->v_neginf); - okinf = okinf&&!ae_fp_neq(_state->v_neginf,_state->v_neginf); - okinf = okinf&&!ae_fp_neq(v2,_state->v_neginf); - okinf = okinf&&ae_fp_neq((double)(0),_state->v_neginf); - okinf = okinf&&ae_fp_neq(1.2,_state->v_neginf); - okinf = okinf&&ae_fp_neq(-1.2,_state->v_neginf); - okinf = okinf&&ae_fp_less(_state->v_neginf,_state->v_posinf); - okinf = okinf&&ae_fp_less(_state->v_neginf,v1); - okinf = okinf&&!ae_fp_less(_state->v_neginf,_state->v_neginf); - okinf = okinf&&!ae_fp_less(_state->v_neginf,v2); - okinf = okinf&&ae_fp_less(_state->v_neginf,(double)(0)); - okinf = okinf&&ae_fp_less(_state->v_neginf,1.2); - okinf = okinf&&ae_fp_less(_state->v_neginf,-1.2); - okinf = okinf&&!ae_fp_less(v1,_state->v_neginf); - okinf = okinf&&!ae_fp_less(_state->v_neginf,_state->v_neginf); - okinf = okinf&&!ae_fp_less(v2,_state->v_neginf); - okinf = okinf&&!ae_fp_less((double)(0),_state->v_neginf); - okinf = okinf&&!ae_fp_less(1.2,_state->v_neginf); - okinf = okinf&&!ae_fp_less(-1.2,_state->v_neginf); - okinf = okinf&&ae_fp_less_eq(_state->v_neginf,_state->v_posinf); - okinf = okinf&&ae_fp_less_eq(_state->v_neginf,v1); - okinf = okinf&&ae_fp_less_eq(_state->v_neginf,_state->v_neginf); - okinf = okinf&&ae_fp_less_eq(_state->v_neginf,v2); - okinf = okinf&&ae_fp_less_eq(_state->v_neginf,(double)(0)); - okinf = okinf&&ae_fp_less_eq(_state->v_neginf,1.2); - okinf = okinf&&ae_fp_less_eq(_state->v_neginf,-1.2); - okinf = okinf&&!ae_fp_less_eq(v1,_state->v_neginf); - okinf = okinf&&ae_fp_less_eq(_state->v_neginf,_state->v_neginf); - okinf = okinf&&ae_fp_less_eq(v2,_state->v_neginf); - okinf = okinf&&!ae_fp_less_eq((double)(0),_state->v_neginf); - okinf = okinf&&!ae_fp_less_eq(1.2,_state->v_neginf); - okinf = okinf&&!ae_fp_less_eq(-1.2,_state->v_neginf); - okinf = okinf&&!ae_fp_greater(_state->v_neginf,_state->v_posinf); - okinf = okinf&&!ae_fp_greater(_state->v_neginf,v1); - okinf = okinf&&!ae_fp_greater(_state->v_neginf,_state->v_neginf); - okinf = okinf&&!ae_fp_greater(_state->v_neginf,v2); - okinf = okinf&&!ae_fp_greater(_state->v_neginf,(double)(0)); - okinf = okinf&&!ae_fp_greater(_state->v_neginf,1.2); - okinf = okinf&&!ae_fp_greater(_state->v_neginf,-1.2); - okinf = okinf&&ae_fp_greater(v1,_state->v_neginf); - okinf = okinf&&!ae_fp_greater(_state->v_neginf,_state->v_neginf); - okinf = okinf&&!ae_fp_greater(v2,_state->v_neginf); - okinf = okinf&&ae_fp_greater((double)(0),_state->v_neginf); - okinf = okinf&&ae_fp_greater(1.2,_state->v_neginf); - okinf = okinf&&ae_fp_greater(-1.2,_state->v_neginf); - okinf = okinf&&!ae_fp_greater_eq(_state->v_neginf,_state->v_posinf); - okinf = okinf&&!ae_fp_greater_eq(_state->v_neginf,v1); - okinf = okinf&&ae_fp_greater_eq(_state->v_neginf,_state->v_neginf); - okinf = okinf&&ae_fp_greater_eq(_state->v_neginf,v2); - okinf = okinf&&!ae_fp_greater_eq(_state->v_neginf,(double)(0)); - okinf = okinf&&!ae_fp_greater_eq(_state->v_neginf,1.2); - okinf = okinf&&!ae_fp_greater_eq(_state->v_neginf,-1.2); - okinf = okinf&&ae_fp_greater_eq(v1,_state->v_neginf); - okinf = okinf&&ae_fp_greater_eq(_state->v_neginf,_state->v_neginf); - okinf = okinf&&ae_fp_greater_eq(v2,_state->v_neginf); - okinf = okinf&&ae_fp_greater_eq((double)(0),_state->v_neginf); - okinf = okinf&&ae_fp_greater_eq(1.2,_state->v_neginf); - okinf = okinf&&ae_fp_greater_eq(-1.2,_state->v_neginf); - - /* - * summary - */ - result = result&&oknan; - result = result&&okinf; - result = result&&okother; - if( !silent ) - { - if( result ) - { - printf("IEEE SPECIAL VALUES: OK\n"); - } - else - { - printf("IEEE SPECIAL VALUES: FAILED\n"); - printf("* NAN - - - - - - - - - - - - - - - - - "); - if( oknan ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* INF - - - - - - - - - - - - - - - - - "); - if( okinf ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* FUNCTIONS - - - - - - - - - - - - - - "); - if( okother ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - } - } - return result; -} - - -/************************************************************************* -Tests for swapping functions -*************************************************************************/ -static ae_bool testalglibbasicsunit_testswapfunctions(ae_bool silent, - ae_state *_state) -{ - ae_frame _frame_block; - ae_bool okb1; - ae_bool okb2; - ae_bool oki1; - ae_bool oki2; - ae_bool okr1; - ae_bool okr2; - ae_bool okc1; - ae_bool okc2; - ae_vector b11; - ae_vector b12; - ae_vector i11; - ae_vector i12; - ae_vector r11; - ae_vector r12; - ae_vector c11; - ae_vector c12; - ae_matrix b21; - ae_matrix b22; - ae_matrix i21; - ae_matrix i22; - ae_matrix r21; - ae_matrix r22; - ae_matrix c21; - ae_matrix c22; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&b11, 0, sizeof(b11)); - memset(&b12, 0, sizeof(b12)); - memset(&i11, 0, sizeof(i11)); - memset(&i12, 0, sizeof(i12)); - memset(&r11, 0, sizeof(r11)); - memset(&r12, 0, sizeof(r12)); - memset(&c11, 0, sizeof(c11)); - memset(&c12, 0, sizeof(c12)); - memset(&b21, 0, sizeof(b21)); - memset(&b22, 0, sizeof(b22)); - memset(&i21, 0, sizeof(i21)); - memset(&i22, 0, sizeof(i22)); - memset(&r21, 0, sizeof(r21)); - memset(&r22, 0, sizeof(r22)); - memset(&c21, 0, sizeof(c21)); - memset(&c22, 0, sizeof(c22)); - ae_vector_init(&b11, 0, DT_BOOL, _state, ae_true); - ae_vector_init(&b12, 0, DT_BOOL, _state, ae_true); - ae_vector_init(&i11, 0, DT_INT, _state, ae_true); - ae_vector_init(&i12, 0, DT_INT, _state, ae_true); - ae_vector_init(&r11, 0, DT_REAL, _state, ae_true); - ae_vector_init(&r12, 0, DT_REAL, _state, ae_true); - ae_vector_init(&c11, 0, DT_COMPLEX, _state, ae_true); - ae_vector_init(&c12, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&b21, 0, 0, DT_BOOL, _state, ae_true); - ae_matrix_init(&b22, 0, 0, DT_BOOL, _state, ae_true); - ae_matrix_init(&i21, 0, 0, DT_INT, _state, ae_true); - ae_matrix_init(&i22, 0, 0, DT_INT, _state, ae_true); - ae_matrix_init(&r21, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&r22, 0, 0, DT_REAL, _state, ae_true); - ae_matrix_init(&c21, 0, 0, DT_COMPLEX, _state, ae_true); - ae_matrix_init(&c22, 0, 0, DT_COMPLEX, _state, ae_true); - - result = ae_true; - okb1 = ae_true; - okb2 = ae_true; - oki1 = ae_true; - oki2 = ae_true; - okr1 = ae_true; - okr2 = ae_true; - okc1 = ae_true; - okc2 = ae_true; - - /* - * Test B1 swaps - */ - ae_vector_set_length(&b11, 1, _state); - ae_vector_set_length(&b12, 2, _state); - b11.ptr.p_bool[0] = ae_true; - b12.ptr.p_bool[0] = ae_false; - b12.ptr.p_bool[1] = ae_true; - ae_swap_vectors(&b11, &b12); - if( b11.cnt==2&&b12.cnt==1 ) - { - okb1 = okb1&&!b11.ptr.p_bool[0]; - okb1 = okb1&&b11.ptr.p_bool[1]; - okb1 = okb1&&b12.ptr.p_bool[0]; - } - else - { - okb1 = ae_false; - } - - /* - * Test I1 swaps - */ - ae_vector_set_length(&i11, 1, _state); - ae_vector_set_length(&i12, 2, _state); - i11.ptr.p_int[0] = 1; - i12.ptr.p_int[0] = 2; - i12.ptr.p_int[1] = 3; - ae_swap_vectors(&i11, &i12); - if( i11.cnt==2&&i12.cnt==1 ) - { - oki1 = oki1&&i11.ptr.p_int[0]==2; - oki1 = oki1&&i11.ptr.p_int[1]==3; - oki1 = oki1&&i12.ptr.p_int[0]==1; - } - else - { - oki1 = ae_false; - } - - /* - * Test R1 swaps - */ - ae_vector_set_length(&r11, 1, _state); - ae_vector_set_length(&r12, 2, _state); - r11.ptr.p_double[0] = 1.5; - r12.ptr.p_double[0] = 2.5; - r12.ptr.p_double[1] = 3.5; - ae_swap_vectors(&r11, &r12); - if( r11.cnt==2&&r12.cnt==1 ) - { - okr1 = okr1&&ae_fp_eq(r11.ptr.p_double[0],2.5); - okr1 = okr1&&ae_fp_eq(r11.ptr.p_double[1],3.5); - okr1 = okr1&&ae_fp_eq(r12.ptr.p_double[0],1.5); - } - else - { - okr1 = ae_false; - } - - /* - * Test C1 swaps - */ - ae_vector_set_length(&c11, 1, _state); - ae_vector_set_length(&c12, 2, _state); - c11.ptr.p_complex[0] = ae_complex_from_i(1); - c12.ptr.p_complex[0] = ae_complex_from_i(2); - c12.ptr.p_complex[1] = ae_complex_from_i(3); - ae_swap_vectors(&c11, &c12); - if( c11.cnt==2&&c12.cnt==1 ) - { - okc1 = okc1&&ae_c_eq_d(c11.ptr.p_complex[0],(double)(2)); - okc1 = okc1&&ae_c_eq_d(c11.ptr.p_complex[1],(double)(3)); - okc1 = okc1&&ae_c_eq_d(c12.ptr.p_complex[0],(double)(1)); - } - else - { - okc1 = ae_false; - } - - /* - * Test B2 swaps - */ - ae_matrix_set_length(&b21, 1, 2, _state); - ae_matrix_set_length(&b22, 2, 1, _state); - b21.ptr.pp_bool[0][0] = ae_true; - b21.ptr.pp_bool[0][1] = ae_false; - b22.ptr.pp_bool[0][0] = ae_false; - b22.ptr.pp_bool[1][0] = ae_true; - ae_swap_matrices(&b21, &b22); - if( ((b21.rows==2&&b21.cols==1)&&b22.rows==1)&&b22.cols==2 ) - { - okb2 = okb2&&!b21.ptr.pp_bool[0][0]; - okb2 = okb2&&b21.ptr.pp_bool[1][0]; - okb2 = okb2&&b22.ptr.pp_bool[0][0]; - okb2 = okb2&&!b22.ptr.pp_bool[0][1]; - } - else - { - okb2 = ae_false; - } - - /* - * Test I2 swaps - */ - ae_matrix_set_length(&i21, 1, 2, _state); - ae_matrix_set_length(&i22, 2, 1, _state); - i21.ptr.pp_int[0][0] = 1; - i21.ptr.pp_int[0][1] = 2; - i22.ptr.pp_int[0][0] = 3; - i22.ptr.pp_int[1][0] = 4; - ae_swap_matrices(&i21, &i22); - if( ((i21.rows==2&&i21.cols==1)&&i22.rows==1)&&i22.cols==2 ) - { - oki2 = oki2&&i21.ptr.pp_int[0][0]==3; - oki2 = oki2&&i21.ptr.pp_int[1][0]==4; - oki2 = oki2&&i22.ptr.pp_int[0][0]==1; - oki2 = oki2&&i22.ptr.pp_int[0][1]==2; - } - else - { - oki2 = ae_false; - } - - /* - * Test R2 swaps - */ - ae_matrix_set_length(&r21, 1, 2, _state); - ae_matrix_set_length(&r22, 2, 1, _state); - r21.ptr.pp_double[0][0] = (double)(1); - r21.ptr.pp_double[0][1] = (double)(2); - r22.ptr.pp_double[0][0] = (double)(3); - r22.ptr.pp_double[1][0] = (double)(4); - ae_swap_matrices(&r21, &r22); - if( ((r21.rows==2&&r21.cols==1)&&r22.rows==1)&&r22.cols==2 ) - { - okr2 = okr2&&ae_fp_eq(r21.ptr.pp_double[0][0],(double)(3)); - okr2 = okr2&&ae_fp_eq(r21.ptr.pp_double[1][0],(double)(4)); - okr2 = okr2&&ae_fp_eq(r22.ptr.pp_double[0][0],(double)(1)); - okr2 = okr2&&ae_fp_eq(r22.ptr.pp_double[0][1],(double)(2)); - } - else - { - okr2 = ae_false; - } - - /* - * Test C2 swaps - */ - ae_matrix_set_length(&c21, 1, 2, _state); - ae_matrix_set_length(&c22, 2, 1, _state); - c21.ptr.pp_complex[0][0] = ae_complex_from_i(1); - c21.ptr.pp_complex[0][1] = ae_complex_from_i(2); - c22.ptr.pp_complex[0][0] = ae_complex_from_i(3); - c22.ptr.pp_complex[1][0] = ae_complex_from_i(4); - ae_swap_matrices(&c21, &c22); - if( ((c21.rows==2&&c21.cols==1)&&c22.rows==1)&&c22.cols==2 ) - { - okc2 = okc2&&ae_c_eq_d(c21.ptr.pp_complex[0][0],(double)(3)); - okc2 = okc2&&ae_c_eq_d(c21.ptr.pp_complex[1][0],(double)(4)); - okc2 = okc2&&ae_c_eq_d(c22.ptr.pp_complex[0][0],(double)(1)); - okc2 = okc2&&ae_c_eq_d(c22.ptr.pp_complex[0][1],(double)(2)); - } - else - { - okc2 = ae_false; - } - - /* - * summary - */ - result = result&&okb1; - result = result&&okb2; - result = result&&oki1; - result = result&&oki2; - result = result&&okr1; - result = result&&okr2; - result = result&&okc1; - result = result&&okc2; - if( !silent ) - { - if( result ) - { - printf("SWAPPING FUNCTIONS: OK\n"); - } - else - { - printf("SWAPPING FUNCTIONS: FAILED\n"); - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Tests for standard functions -*************************************************************************/ -static ae_bool testalglibbasicsunit_teststandardfunctions(ae_bool silent, - ae_state *_state) -{ - ae_bool result; - - - result = ae_true; - - /* - * Test Sign() - */ - result = result&&ae_sign(1.2, _state)==1; - result = result&&ae_sign((double)(0), _state)==0; - result = result&&ae_sign(-1.2, _state)==-1; - - /* - * summary - */ - if( !silent ) - { - if( result ) - { - printf("STANDARD FUNCTIONS: OK\n"); - } - else - { - printf("STANDARD FUNCTIONS: FAILED\n"); - } - } - return result; -} - - -/************************************************************************* -Tests for serualization functions -*************************************************************************/ -static ae_bool testalglibbasicsunit_testserializationfunctions(ae_bool silent, - ae_state *_state) -{ - ae_frame _frame_block; - ae_bool okb; - ae_bool oki; - ae_bool okr; - ae_int_t nb; - ae_int_t ni; - ae_int_t nr; - ae_int_t i; - rec4serialization r0; - rec4serialization r1; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&r0, 0, sizeof(r0)); - memset(&r1, 0, sizeof(r1)); - _rec4serialization_init(&r0, _state, ae_true); - _rec4serialization_init(&r1, _state, ae_true); - - result = ae_true; - okb = ae_true; - oki = ae_true; - okr = ae_true; - for(nb=1; nb<=4; nb++) - { - for(ni=1; ni<=4; ni++) - { - for(nr=1; nr<=4; nr++) - { - ae_vector_set_length(&r0.b, nb, _state); - for(i=0; i<=nb-1; i++) - { - r0.b.ptr.p_bool[i] = ae_randominteger(2, _state)!=0; - } - ae_vector_set_length(&r0.i, ni, _state); - for(i=0; i<=ni-1; i++) - { - r0.i.ptr.p_int[i] = ae_randominteger(10, _state)-5; - } - ae_vector_set_length(&r0.r, nr, _state); - for(i=0; i<=nr-1; i++) - { - r0.r.ptr.p_double[i] = 2*ae_randomreal(_state)-1; - } - { - /* - * This code passes data structure through serializers - * (serializes it to string and loads back) - */ - ae_serializer _local_serializer; - ae_int_t _local_ssize; - ae_frame _local_frame_block; - ae_dyn_block _local_dynamic_block; - - ae_frame_make(_state, &_local_frame_block); - - ae_serializer_init(&_local_serializer); - ae_serializer_alloc_start(&_local_serializer); - rec4serializationalloc(&_local_serializer, &r0, _state); - _local_ssize = ae_serializer_get_alloc_size(&_local_serializer); - memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block)); - ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true); - ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - rec4serializationserialize(&_local_serializer, &r0, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_serializer_init(&_local_serializer); - ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr); - rec4serializationunserialize(&_local_serializer, &r1, _state); - ae_serializer_stop(&_local_serializer, _state); - ae_serializer_clear(&_local_serializer); - - ae_frame_leave(_state); - } - if( (r0.b.cnt==r1.b.cnt&&r0.i.cnt==r1.i.cnt)&&r0.r.cnt==r1.r.cnt ) - { - for(i=0; i<=nb-1; i++) - { - okb = okb&&((r0.b.ptr.p_bool[i]&&r1.b.ptr.p_bool[i])||(!r0.b.ptr.p_bool[i]&&!r1.b.ptr.p_bool[i])); - } - for(i=0; i<=ni-1; i++) - { - oki = oki&&r0.i.ptr.p_int[i]==r1.i.ptr.p_int[i]; - } - for(i=0; i<=nr-1; i++) - { - okr = okr&&ae_fp_eq(r0.r.ptr.p_double[i],r1.r.ptr.p_double[i]); - } - } - else - { - oki = ae_false; - } - } - } - } - - /* - * summary - */ - result = result&&okb; - result = result&&oki; - result = result&&okr; - if( !silent ) - { - if( result ) - { - printf("SERIALIZATION FUNCTIONS: OK\n"); - } - else - { - printf("SERIALIZATION FUNCTIONS: FAILED\n"); - printf("* BOOLEAN - - - - - - - - - - - - - - - "); - if( okb ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* INTEGER - - - - - - - - - - - - - - - "); - if( oki ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* REAL - - - - - - - - - - - - - - - - "); - if( okr ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - } - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Tests for pool functions -*************************************************************************/ -static void testalglibbasicsunit_createpoolandrecords(poolrec2* seedrec2, - poolrec2* seedrec2copy, - ae_shared_pool* pool, - ae_state *_state) -{ - - _poolrec2_clear(seedrec2); - _poolrec2_clear(seedrec2copy); - ae_shared_pool_clear(pool); - - seedrec2->bval = ae_fp_greater(ae_randomreal(_state),0.5); - seedrec2->recval.bval = ae_fp_greater(ae_randomreal(_state),0.5); - seedrec2->recval.ival = ae_randominteger(10, _state); - seedrec2->recval.rval = ae_randomreal(_state); - seedrec2->recval.cval.x = ae_randomreal(_state); - seedrec2->recval.cval.y = ae_randomreal(_state); - ae_vector_set_length(&seedrec2->recval.i1val, 3, _state); - seedrec2->recval.i1val.ptr.p_int[0] = ae_randominteger(10, _state); - seedrec2->recval.i1val.ptr.p_int[1] = ae_randominteger(10, _state); - seedrec2->recval.i1val.ptr.p_int[2] = ae_randominteger(10, _state); - seedrec2copy->bval = seedrec2->bval; - seedrec2copy->recval.bval = seedrec2->recval.bval; - seedrec2copy->recval.ival = seedrec2->recval.ival; - seedrec2copy->recval.rval = seedrec2->recval.rval; - seedrec2copy->recval.cval = seedrec2->recval.cval; - ae_vector_set_length(&seedrec2copy->recval.i1val, 3, _state); - seedrec2copy->recval.i1val.ptr.p_int[0] = seedrec2->recval.i1val.ptr.p_int[0]; - seedrec2copy->recval.i1val.ptr.p_int[1] = seedrec2->recval.i1val.ptr.p_int[1]; - seedrec2copy->recval.i1val.ptr.p_int[2] = seedrec2->recval.i1val.ptr.p_int[2]; - ae_shared_pool_set_seed(pool, seedrec2, sizeof(*seedrec2), _poolrec2_init, _poolrec2_init_copy, _poolrec2_destroy, _state); -} - - -static ae_bool testalglibbasicsunit_sharedpoolerrors(ae_state *_state) -{ - ae_frame _frame_block; - poolrec1 seedrec1; - poolrec2 seedrec2; - poolrec2 seedrec2copy; - ae_shared_pool pool; - ae_shared_pool pool2; - poolrec2 *prec2; - ae_smart_ptr _prec2; - poolrec2 *p0; - ae_smart_ptr _p0; - poolrec2 *p1; - ae_smart_ptr _p1; - poolrec2 *p2; - ae_smart_ptr _p2; - poolrec1 *q0; - ae_smart_ptr _q0; - poolrec1 *q1; - ae_smart_ptr _q1; - ae_shared_pool *ppool0; - ae_smart_ptr _ppool0; - ae_shared_pool *ppool1; - ae_smart_ptr _ppool1; - ae_int_t val100cnt; - ae_int_t val101cnt; - ae_int_t val102cnt; - ae_int_t tmpval; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&seedrec1, 0, sizeof(seedrec1)); - memset(&seedrec2, 0, sizeof(seedrec2)); - memset(&seedrec2copy, 0, sizeof(seedrec2copy)); - memset(&pool, 0, sizeof(pool)); - memset(&pool2, 0, sizeof(pool2)); - memset(&_prec2, 0, sizeof(_prec2)); - memset(&_p0, 0, sizeof(_p0)); - memset(&_p1, 0, sizeof(_p1)); - memset(&_p2, 0, sizeof(_p2)); - memset(&_q0, 0, sizeof(_q0)); - memset(&_q1, 0, sizeof(_q1)); - memset(&_ppool0, 0, sizeof(_ppool0)); - memset(&_ppool1, 0, sizeof(_ppool1)); - _poolrec1_init(&seedrec1, _state, ae_true); - _poolrec2_init(&seedrec2, _state, ae_true); - _poolrec2_init(&seedrec2copy, _state, ae_true); - ae_shared_pool_init(&pool, _state, ae_true); - ae_shared_pool_init(&pool2, _state, ae_true); - ae_smart_ptr_init(&_prec2, (void**)&prec2, _state, ae_true); - ae_smart_ptr_init(&_p0, (void**)&p0, _state, ae_true); - ae_smart_ptr_init(&_p1, (void**)&p1, _state, ae_true); - ae_smart_ptr_init(&_p2, (void**)&p2, _state, ae_true); - ae_smart_ptr_init(&_q0, (void**)&q0, _state, ae_true); - ae_smart_ptr_init(&_q1, (void**)&q1, _state, ae_true); - ae_smart_ptr_init(&_ppool0, (void**)&ppool0, _state, ae_true); - ae_smart_ptr_init(&_ppool1, (void**)&ppool1, _state, ae_true); - - result = ae_true; - - /* - * Test 1: test that: - * a) smart pointer is null by default - * b) "conventional local" is valid by default - * b) unitinitialized shared pool is "not initialized" - */ - if( prec2!=NULL ) - { - ae_frame_leave(_state); - return result; - } - if( !(&seedrec1!=NULL) ) - { - ae_frame_leave(_state); - return result; - } - if( ae_shared_pool_is_initialized(&pool) ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test 2: basic copying of complex structures - * * check that pool is recognized as "initialized" - * * change original seed record, - * * retrieve value from pool, - * * check that it is valid - * * and it is unchanged. - */ - testalglibbasicsunit_createpoolandrecords(&seedrec2, &seedrec2copy, &pool, _state); - if( !ae_shared_pool_is_initialized(&pool) ) - { - ae_frame_leave(_state); - return result; - } - seedrec2.bval = !seedrec2.bval; - seedrec2.recval.i1val.ptr.p_int[0] = seedrec2.recval.i1val.ptr.p_int[0]+1; - ae_shared_pool_retrieve(&pool, &_prec2, _state); - if( !(prec2!=NULL) ) - { - ae_frame_leave(_state); - return result; - } - if( (seedrec2copy.bval&&!prec2->bval)||(prec2->bval&&!seedrec2copy.bval) ) - { - ae_frame_leave(_state); - return result; - } - if( seedrec2copy.recval.i1val.ptr.p_int[0]!=prec2->recval.i1val.ptr.p_int[0] ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test 3: unrecycled values are lost - * * retrieve value from pool, - * * change it, - * * retrieve one more time, - * * check that it is unchanged. - */ - testalglibbasicsunit_createpoolandrecords(&seedrec2, &seedrec2copy, &pool, _state); - ae_shared_pool_retrieve(&pool, &_prec2, _state); - prec2->recval.ival = prec2->recval.ival+1; - ae_shared_pool_retrieve(&pool, &_prec2, _state); - if( prec2->recval.ival!=seedrec2copy.recval.ival ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test 4: recycled values are reused, PoolClearRecycled() removes recycled values - * * retrieve value from pool, - * * change it, - * * recycle, - * * check that recycled pointer is null - * * retrieve one more time, - * * check that modified value was returned, - * * recycle, - * * clear pool, - * * retrieve one more time, - * * check that unmodified value was returned, - */ - testalglibbasicsunit_createpoolandrecords(&seedrec2, &seedrec2copy, &pool, _state); - ae_shared_pool_retrieve(&pool, &_prec2, _state); - prec2->recval.ival = prec2->recval.ival+1; - ae_shared_pool_recycle(&pool, &_prec2, _state); - if( prec2!=NULL ) - { - ae_frame_leave(_state); - return result; - } - ae_shared_pool_retrieve(&pool, &_prec2, _state); - if( !(prec2!=NULL) ) - { - ae_frame_leave(_state); - return result; - } - if( prec2->recval.ival!=seedrec2copy.recval.ival+1 ) - { - ae_frame_leave(_state); - return result; - } - ae_shared_pool_recycle(&pool, &_prec2, _state); - ae_shared_pool_clear_recycled(&pool, _state); - ae_shared_pool_retrieve(&pool, &_prec2, _state); - if( !(prec2!=NULL) ) - { - ae_frame_leave(_state); - return result; - } - if( prec2->recval.ival!=seedrec2copy.recval.ival ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test 5: basic enumeration - * * retrieve 3 values from pool - * * fill RecVal.iVal by 100, 101, 102 - * * recycle values - * * enumerate, check that each iVal occurs only once during enumeration - * * repeat enumeration to make sure that it can be repeated - */ - testalglibbasicsunit_createpoolandrecords(&seedrec2, &seedrec2copy, &pool, _state); - ae_shared_pool_retrieve(&pool, &_p0, _state); - ae_shared_pool_retrieve(&pool, &_p1, _state); - ae_shared_pool_retrieve(&pool, &_p2, _state); - p0->recval.ival = 100; - p1->recval.ival = 101; - p2->recval.ival = 102; - ae_shared_pool_recycle(&pool, &_p1, _state); - ae_shared_pool_recycle(&pool, &_p2, _state); - ae_shared_pool_recycle(&pool, &_p0, _state); - val100cnt = 0; - val101cnt = 0; - val102cnt = 0; - ae_shared_pool_first_recycled(&pool, &_prec2, _state); - while(prec2!=NULL) - { - if( prec2->recval.ival==100 ) - { - val100cnt = val100cnt+1; - } - if( prec2->recval.ival==101 ) - { - val101cnt = val101cnt+1; - } - if( prec2->recval.ival==102 ) - { - val102cnt = val102cnt+1; - } - ae_shared_pool_next_recycled(&pool, &_prec2, _state); - } - if( (val100cnt!=1||val101cnt!=1)||val102cnt!=1 ) - { - ae_frame_leave(_state); - return result; - } - val100cnt = 0; - val101cnt = 0; - val102cnt = 0; - ae_shared_pool_first_recycled(&pool, &_prec2, _state); - while(prec2!=NULL) - { - if( prec2->recval.ival==100 ) - { - val100cnt = val100cnt+1; - } - if( prec2->recval.ival==101 ) - { - val101cnt = val101cnt+1; - } - if( prec2->recval.ival==102 ) - { - val102cnt = val102cnt+1; - } - ae_shared_pool_next_recycled(&pool, &_prec2, _state); - } - if( (val100cnt!=1||val101cnt!=1)||val102cnt!=1 ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test 6: pool itself can be pooled - * * pool can be seeded with another pool - * * smart pointers to pool are correctly handled - * * pool correctly returns different references on "retrieve": - * * we retrieve, modify and recycle back to PPool0 - * * we retrieve from PPool1 - unmodified value is returned - * * we retrievefrom PPool0 - modified value is returned - */ - testalglibbasicsunit_createpoolandrecords(&seedrec2, &seedrec2copy, &pool, _state); - ae_shared_pool_set_seed(&pool2, &pool, sizeof(pool), ae_shared_pool_init, ae_shared_pool_init_copy, ae_shared_pool_destroy, _state); - if( ppool0!=NULL||ppool1!=NULL ) - { - ae_frame_leave(_state); - return result; - } - ae_shared_pool_retrieve(&pool2, &_ppool0, _state); - ae_shared_pool_retrieve(&pool2, &_ppool1, _state); - if( !(ppool0!=NULL&&ppool1!=NULL) ) - { - ae_frame_leave(_state); - return result; - } - ae_shared_pool_retrieve(ppool0, &_p0, _state); - p0->recval.ival = p0->recval.ival+1; - tmpval = p0->recval.ival; - ae_shared_pool_recycle(ppool0, &_p0, _state); - ae_shared_pool_retrieve(ppool1, &_p1, _state); - if( p1->recval.ival==tmpval ) - { - ae_frame_leave(_state); - return result; - } - ae_shared_pool_recycle(ppool1, &_p1, _state); - ae_shared_pool_retrieve(ppool0, &_p0, _state); - if( p0->recval.ival!=tmpval ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test 7: pools which are fields of records are correctly handled - * * pool can be seeded with record which has initialized pool as its field - * * when record is retrieved from pool, its fields are correctly copied (including - * fields which are pools) - */ - testalglibbasicsunit_createpoolandrecords(&seedrec2, &seedrec2copy, &pool, _state); - tmpval = 99; - seedrec1.ival = tmpval; - ae_shared_pool_set_seed(&seedrec2.pool, &seedrec1, sizeof(seedrec1), _poolrec1_init, _poolrec1_init_copy, _poolrec1_destroy, _state); - ae_shared_pool_set_seed(&pool, &seedrec2, sizeof(seedrec2), _poolrec2_init, _poolrec2_init_copy, _poolrec2_destroy, _state); - ae_shared_pool_retrieve(&pool, &_p0, _state); - ae_shared_pool_retrieve(&p0->pool, &_q0, _state); - q0->ival = tmpval-1; - ae_shared_pool_recycle(&p0->pool, &_q0, _state); - ae_shared_pool_retrieve(&pool, &_p1, _state); - ae_shared_pool_retrieve(&p1->pool, &_q1, _state); - if( q1->ival!=tmpval ) - { - ae_frame_leave(_state); - return result; - } - ae_shared_pool_recycle(&p1->pool, &_q1, _state); - ae_shared_pool_retrieve(&p0->pool, &_q0, _state); - if( q0->ival!=tmpval-1 ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test 8: after call to PoolReset(), call to PoolFirstRecycled() returns null references - */ - testalglibbasicsunit_createpoolandrecords(&seedrec2, &seedrec2copy, &pool, _state); - ae_shared_pool_retrieve(&pool, &_p0, _state); - ae_shared_pool_retrieve(&pool, &_p1, _state); - ae_shared_pool_retrieve(&pool, &_p2, _state); - ae_shared_pool_recycle(&pool, &_p1, _state); - ae_shared_pool_recycle(&pool, &_p2, _state); - ae_shared_pool_recycle(&pool, &_p0, _state); - ae_shared_pool_first_recycled(&pool, &_p0, _state); - if( !(p0!=NULL) ) - { - ae_frame_leave(_state); - return result; - } - ae_shared_pool_next_recycled(&pool, &_p0, _state); - if( !(p0!=NULL) ) - { - ae_frame_leave(_state); - return result; - } - ae_shared_pool_next_recycled(&pool, &_p0, _state); - if( !(p0!=NULL) ) - { - ae_frame_leave(_state); - return result; - } - ae_shared_pool_next_recycled(&pool, &_p0, _state); - if( p0!=NULL ) - { - ae_frame_leave(_state); - return result; - } - ae_shared_pool_reset(&pool, _state); - ae_shared_pool_first_recycled(&pool, &_p0, _state); - if( p0!=NULL ) - { - ae_frame_leave(_state); - return result; - } - ae_shared_pool_next_recycled(&pool, &_p0, _state); - if( p0!=NULL ) - { - ae_frame_leave(_state); - return result; - } - ae_shared_pool_next_recycled(&pool, &_p0, _state); - if( p0!=NULL ) - { - ae_frame_leave(_state); - return result; - } - ae_shared_pool_next_recycled(&pool, &_p0, _state); - if( p0!=NULL ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test 9: invalid pointer is recognized as non-null (we do not reference it, just test) - */ - testalglibbasicsunit_createpoolandrecords(&seedrec2, &seedrec2copy, &pool, _state); - ae_shared_pool_retrieve(&pool, &_p0, _state); - ae_shared_pool_retrieve(&pool, &_p1, _state); - ae_shared_pool_retrieve(&pool, &_p2, _state); - ae_shared_pool_recycle(&pool, &_p1, _state); - ae_shared_pool_recycle(&pool, &_p2, _state); - ae_shared_pool_recycle(&pool, &_p0, _state); - ae_shared_pool_first_recycled(&pool, &_p0, _state); - if( !(p0!=NULL) ) - { - ae_frame_leave(_state); - return result; - } - ae_shared_pool_clear_recycled(&pool, _state); - if( !(p0!=NULL) ) - { - ae_frame_leave(_state); - return result; - } - - /* - * Test 9: non-null pointer is nulled by calling SetNull() - */ - testalglibbasicsunit_createpoolandrecords(&seedrec2, &seedrec2copy, &pool, _state); - ae_shared_pool_retrieve(&pool, &_p0, _state); - if( !(p0!=NULL) ) - { - ae_frame_leave(_state); - return result; - } - ae_smart_ptr_assign(&_p0, NULL, ae_false, ae_false, NULL); - if( p0!=NULL ) - { - ae_frame_leave(_state); - return result; - } - result = ae_false; - ae_frame_leave(_state); - return result; -} - - -static ae_bool testalglibbasicsunit_testsharedpool(ae_bool silent, - ae_state *_state) -{ - ae_bool result; - - - result = !testalglibbasicsunit_sharedpoolerrors(_state); - if( !silent ) - { - if( result ) - { - printf("SHARED POOL: OK\n"); - } - else - { - printf("SHARED POOL: FAILED\n"); - } - } - return result; -} - - -/************************************************************************* -Tests for SMP functions - -testSort0: sort function -*************************************************************************/ -static void testalglibbasicsunit_testsort0func(/* Integer */ ae_vector* a, - /* Integer */ ae_vector* buf, - ae_int_t idx0, - ae_int_t idx2, - ae_state *_state) -{ - ae_int_t idx1; - - - if( idx2<=idx0+1 ) - { - return; - } - idx1 = (idx0+idx2)/2; - testalglibbasicsunit_testsort0func(a, buf, idx0, idx1, _state); - testalglibbasicsunit_testsort0func(a, buf, idx1, idx2, _state); - testalglibbasicsunit_mergesortedarrays(a, buf, idx0, idx1, idx2, _state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_testalglibbasicsunit_testsort0func(/* Integer */ ae_vector* a, - /* Integer */ ae_vector* buf, - ae_int_t idx0, - ae_int_t idx2, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -testSort0: recursive sorting by splitting array into two subarrays. -Returns True on success, False on failure. -*************************************************************************/ -static ae_bool testalglibbasicsunit_performtestsort0(ae_state *_state) -{ - ae_frame _frame_block; - ae_vector a; - ae_vector buf; - ae_int_t i; - ae_int_t k; - ae_int_t t; - ae_int_t n; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&buf, 0, sizeof(buf)); - ae_vector_init(&a, 0, DT_INT, _state, ae_true); - ae_vector_init(&buf, 0, DT_INT, _state, ae_true); - - n = 100000; - ae_vector_set_length(&a, n, _state); - ae_vector_set_length(&buf, n, _state); - for(i=0; i<=n-1; i++) - { - a.ptr.p_int[i] = i; - } - for(i=0; i<=n-1; i++) - { - k = ae_randominteger(n, _state); - if( k!=i ) - { - t = a.ptr.p_int[i]; - a.ptr.p_int[i] = a.ptr.p_int[k]; - a.ptr.p_int[k] = t; - } - } - testalglibbasicsunit_testsort0func(&a, &buf, 0, n, _state); - result = ae_true; - for(i=0; i<=n-1; i++) - { - result = result&&a.ptr.p_int[i]==i; - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -TestSort0: sort function -*************************************************************************/ -static void testalglibbasicsunit_testsort1func(/* Integer */ ae_vector* a, - /* Integer */ ae_vector* buf, - ae_int_t idx0, - ae_int_t idx2, - ae_bool usesmp, - ae_state *_state) -{ - ae_int_t idxa; - ae_int_t idxb; - ae_int_t idxc; - ae_int_t cnt4; - - - if( idx2<=idx0+1 ) - { - return; - } - if( idx2==idx0+2 ) - { - testalglibbasicsunit_mergesortedarrays(a, buf, idx0, idx0+1, idx0+2, _state); - return; - } - if( idx2==idx0+3 ) - { - testalglibbasicsunit_mergesortedarrays(a, buf, idx0+0, idx0+1, idx0+2, _state); - testalglibbasicsunit_mergesortedarrays(a, buf, idx0+0, idx0+2, idx0+3, _state); - return; - } - if( idx2==idx0+4 ) - { - testalglibbasicsunit_mergesortedarrays(a, buf, idx0+0, idx0+1, idx0+2, _state); - testalglibbasicsunit_mergesortedarrays(a, buf, idx0+2, idx0+3, idx0+4, _state); - testalglibbasicsunit_mergesortedarrays(a, buf, idx0+0, idx0+2, idx0+4, _state); - return; - } - cnt4 = (idx2-idx0)/4; - idxa = idx0+cnt4; - idxb = idx0+2*cnt4; - idxc = idx0+3*cnt4; - testalglibbasicsunit_testsort1func(a, buf, idx0, idxa, usesmp, _state); - testalglibbasicsunit_testsort1func(a, buf, idxa, idxb, usesmp, _state); - testalglibbasicsunit_testsort1func(a, buf, idxb, idxc, usesmp, _state); - testalglibbasicsunit_testsort1func(a, buf, idxc, idx2, usesmp, _state); - testalglibbasicsunit_mergesortedarrays(a, buf, idx0, idxa, idxb, _state); - testalglibbasicsunit_mergesortedarrays(a, buf, idxb, idxc, idx2, _state); - testalglibbasicsunit_mergesortedarrays(a, buf, idx0, idxb, idx2, _state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_testalglibbasicsunit_testsort1func(/* Integer */ ae_vector* a, - /* Integer */ ae_vector* buf, - ae_int_t idx0, - ae_int_t idx2, - ae_bool usesmp, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -TestSort0: recursive sorting by splitting array into 4 subarrays. - -Sorting is performed in three rounds: -* parallel sorting of randomly permuted array -* result is randomly shuffled and sequentially sorted -* result is randomly shuffled (again) and sorted in parallel mode (again) - -The idea of such "multitry sort" is that we test ability of SMP core to -interleave highly parallel parts of code with long sequential parts. - -Returns True on success, False on failure. -*************************************************************************/ -static ae_bool testalglibbasicsunit_performtestsort1(ae_state *_state) -{ - ae_frame _frame_block; - ae_vector a; - ae_vector buf; - ae_int_t i; - ae_int_t k; - ae_int_t t; - ae_int_t n; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&buf, 0, sizeof(buf)); - ae_vector_init(&a, 0, DT_INT, _state, ae_true); - ae_vector_init(&buf, 0, DT_INT, _state, ae_true); - - - /* - * Generate array - */ - n = 100000; - ae_vector_set_length(&a, n, _state); - ae_vector_set_length(&buf, n, _state); - for(i=0; i<=n-1; i++) - { - a.ptr.p_int[i] = i; - } - - /* - * round 0: parallel sorting of randomly permuted array - */ - for(i=0; i<=n-1; i++) - { - k = ae_randominteger(n, _state); - if( k!=i ) - { - t = a.ptr.p_int[i]; - a.ptr.p_int[i] = a.ptr.p_int[k]; - a.ptr.p_int[k] = t; - } - } - testalglibbasicsunit_testsort1func(&a, &buf, 0, n, ae_true, _state); - - /* - * round 1: result is randomly shuffled and sequentially sorted - */ - for(i=0; i<=n-1; i++) - { - k = ae_randominteger(n, _state); - if( k!=i ) - { - t = a.ptr.p_int[i]; - a.ptr.p_int[i] = a.ptr.p_int[k]; - a.ptr.p_int[k] = t; - } - } - testalglibbasicsunit_testsort1func(&a, &buf, 0, n, ae_false, _state); - - /* - * round 2: result is randomly shuffled (again) and sorted in parallel mode (again) - */ - for(i=0; i<=n-1; i++) - { - k = ae_randominteger(n, _state); - if( k!=i ) - { - t = a.ptr.p_int[i]; - a.ptr.p_int[i] = a.ptr.p_int[k]; - a.ptr.p_int[k] = t; - } - } - testalglibbasicsunit_testsort1func(&a, &buf, 0, n, ae_true, _state); - - /* - * Test - */ - result = ae_true; - for(i=0; i<=n-1; i++) - { - result = result&&a.ptr.p_int[i]==i; - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Tests for SMP functions - -testSort2: sort function -*************************************************************************/ -static void testalglibbasicsunit_testsort2func(/* Integer */ ae_vector* a, - /* Integer */ ae_vector* buf, - ae_int_t idx0, - ae_int_t idx2, - ae_state *_state) -{ - ae_int_t idx1; - - - if( idx2<=idx0+1 ) - { - return; - } - idx1 = idx0+1+ae_randominteger(idx2-idx0-1, _state); - testalglibbasicsunit_testsort0func(a, buf, idx0, idx1, _state); - testalglibbasicsunit_testsort0func(a, buf, idx1, idx2, _state); - testalglibbasicsunit_mergesortedarrays(a, buf, idx0, idx1, idx2, _state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_testalglibbasicsunit_testsort2func(/* Integer */ ae_vector* a, - /* Integer */ ae_vector* buf, - ae_int_t idx0, - ae_int_t idx2, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -testSort2: recursive sorting by splitting array into two subarrays of -different length (main difference from testsort0). -Returns True on success, False on failure. -*************************************************************************/ -static ae_bool testalglibbasicsunit_performtestsort2(ae_state *_state) -{ - ae_frame _frame_block; - ae_vector a; - ae_vector buf; - ae_int_t i; - ae_int_t k; - ae_int_t t; - ae_int_t n; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&a, 0, sizeof(a)); - memset(&buf, 0, sizeof(buf)); - ae_vector_init(&a, 0, DT_INT, _state, ae_true); - ae_vector_init(&buf, 0, DT_INT, _state, ae_true); - - n = 100000; - ae_vector_set_length(&a, n, _state); - ae_vector_set_length(&buf, n, _state); - for(i=0; i<=n-1; i++) - { - a.ptr.p_int[i] = i; - } - for(i=0; i<=n-1; i++) - { - k = ae_randominteger(n, _state); - if( k!=i ) - { - t = a.ptr.p_int[i]; - a.ptr.p_int[i] = a.ptr.p_int[k]; - a.ptr.p_int[k] = t; - } - } - testalglibbasicsunit_testsort2func(&a, &buf, 0, n, _state); - result = ae_true; - for(i=0; i<=n-1; i++) - { - result = result&&a.ptr.p_int[i]==i; - } - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -TestPoolSum: summation with pool - -We perform summation of 500000 numbers (each of them is equal to 1) in the -recurrent manner, by accumulation of result in the pool. - -This test checks pool ability to handle continuous stream of operations. - -Returns True on success, False on failure. -*************************************************************************/ -static ae_bool testalglibbasicsunit_performtestpoolsum(ae_state *_state) -{ - ae_frame _frame_block; - ae_shared_pool pool; - poolsummand *ptr; - ae_smart_ptr _ptr; - poolsummand seed; - ae_int_t n; - ae_int_t sum; - ae_bool result; - - ae_frame_make(_state, &_frame_block); - memset(&pool, 0, sizeof(pool)); - memset(&_ptr, 0, sizeof(_ptr)); - memset(&seed, 0, sizeof(seed)); - ae_shared_pool_init(&pool, _state, ae_true); - ae_smart_ptr_init(&_ptr, (void**)&ptr, _state, ae_true); - _poolsummand_init(&seed, _state, ae_true); - - n = 500000; - seed.val = 0; - ae_shared_pool_set_seed(&pool, &seed, sizeof(seed), _poolsummand_init, _poolsummand_init_copy, _poolsummand_destroy, _state); - testalglibbasicsunit_parallelpoolsum(&pool, 0, n, _state); - sum = 0; - ae_shared_pool_first_recycled(&pool, &_ptr, _state); - while(ptr!=NULL) - { - sum = sum+ptr->val; - ae_shared_pool_next_recycled(&pool, &_ptr, _state); - } - result = sum==n; - ae_frame_leave(_state); - return result; -} - - -/************************************************************************* -Summation routune for parallel summation test. -*************************************************************************/ -static void testalglibbasicsunit_parallelpoolsum(ae_shared_pool* sumpool, - ae_int_t ind0, - ae_int_t ind1, - ae_state *_state) -{ - ae_frame _frame_block; - ae_int_t i; - poolsummand *ptr; - ae_smart_ptr _ptr; - - ae_frame_make(_state, &_frame_block); - memset(&_ptr, 0, sizeof(_ptr)); - ae_smart_ptr_init(&_ptr, (void**)&ptr, _state, ae_true); - - if( ind1-ind0<=2 ) - { - ae_shared_pool_retrieve(sumpool, &_ptr, _state); - ptr->val = ptr->val+ind1-ind0; - ae_shared_pool_recycle(sumpool, &_ptr, _state); - } - else - { - i = (ind0+ind1)/2; - testalglibbasicsunit_parallelpoolsum(sumpool, ind0, i, _state); - testalglibbasicsunit_parallelpoolsum(sumpool, i, ind1, _state); - } - ae_frame_leave(_state); -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_testalglibbasicsunit_parallelpoolsum(ae_shared_pool* sumpool, - ae_int_t ind0, - ae_int_t ind1, - ae_state *_state) -{ - return ae_false; -} - - -/************************************************************************* -This function merges sorted A[Idx0,Idx1) and A[Idx1,Idx2) into sorted array -A[Idx0,Idx2) using corresponding elements of Buf. -*************************************************************************/ -static void testalglibbasicsunit_mergesortedarrays(/* Integer */ ae_vector* a, - /* Integer */ ae_vector* buf, - ae_int_t idx0, - ae_int_t idx1, - ae_int_t idx2, - ae_state *_state) -{ - ae_int_t srcleft; - ae_int_t srcright; - ae_int_t dst; - - - srcleft = idx0; - srcright = idx1; - dst = idx0; - for(;;) - { - if( srcleft==idx1&&srcright==idx2 ) - { - break; - } - if( srcleft==idx1 ) - { - buf->ptr.p_int[dst] = a->ptr.p_int[srcright]; - srcright = srcright+1; - dst = dst+1; - continue; - } - if( srcright==idx2 ) - { - buf->ptr.p_int[dst] = a->ptr.p_int[srcleft]; - srcleft = srcleft+1; - dst = dst+1; - continue; - } - if( a->ptr.p_int[srcleft]ptr.p_int[srcright] ) - { - buf->ptr.p_int[dst] = a->ptr.p_int[srcleft]; - srcleft = srcleft+1; - dst = dst+1; - } - else - { - buf->ptr.p_int[dst] = a->ptr.p_int[srcright]; - srcright = srcright+1; - dst = dst+1; - } - } - for(dst=idx0; dst<=idx2-1; dst++) - { - a->ptr.p_int[dst] = buf->ptr.p_int[dst]; - } -} - - -/************************************************************************* -Serial stub for GPL edition. -*************************************************************************/ -ae_bool _trypexec_testalglibbasicsunit_mergesortedarrays(/* Integer */ ae_vector* a, - /* Integer */ ae_vector* buf, - ae_int_t idx0, - ae_int_t idx1, - ae_int_t idx2, - ae_state *_state) -{ - return ae_false; -} - - -static ae_bool testalglibbasicsunit_testsmp(ae_bool silent, - ae_state *_state) -{ - ae_bool t0; - ae_bool t1; - ae_bool t2; - ae_bool ts; - ae_bool result; - - - t0 = testalglibbasicsunit_performtestsort0(_state); - t1 = testalglibbasicsunit_performtestsort1(_state); - t2 = testalglibbasicsunit_performtestsort2(_state); - ts = testalglibbasicsunit_performtestpoolsum(_state); - result = ((t0&&t1)&&t2)&&ts; - if( !silent ) - { - if( result ) - { - printf("SMP FUNCTIONS: OK\n"); - } - else - { - printf("SMP FUNCTIONS: FAILED\n"); - printf("* TEST SORT0 (sorting, split-2) "); - if( t0 ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* TEST SORT1 (sorting, split-4) "); - if( t1 ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* TEST SORT2 (sorting, split-2, unequal) "); - if( t2 ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - printf("* TEST POOLSUM (accumulation with pool) "); - if( ts ) - { - printf("OK\n"); - } - else - { - printf("FAILED\n"); - } - } - } - return result; -} - - -void _rec1_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - rec1 *p = (rec1*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->b1field, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->r1field, 0, DT_REAL, _state, make_automatic); - ae_vector_init(&p->i1field, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->c1field, 0, DT_COMPLEX, _state, make_automatic); - ae_matrix_init(&p->b2field, 0, 0, DT_BOOL, _state, make_automatic); - ae_matrix_init(&p->r2field, 0, 0, DT_REAL, _state, make_automatic); - ae_matrix_init(&p->i2field, 0, 0, DT_INT, _state, make_automatic); - ae_matrix_init(&p->c2field, 0, 0, DT_COMPLEX, _state, make_automatic); -} - - -void _rec1_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - rec1 *dst = (rec1*)_dst; - rec1 *src = (rec1*)_src; - dst->bfield = src->bfield; - dst->rfield = src->rfield; - dst->ifield = src->ifield; - dst->cfield = src->cfield; - ae_vector_init_copy(&dst->b1field, &src->b1field, _state, make_automatic); - ae_vector_init_copy(&dst->r1field, &src->r1field, _state, make_automatic); - ae_vector_init_copy(&dst->i1field, &src->i1field, _state, make_automatic); - ae_vector_init_copy(&dst->c1field, &src->c1field, _state, make_automatic); - ae_matrix_init_copy(&dst->b2field, &src->b2field, _state, make_automatic); - ae_matrix_init_copy(&dst->r2field, &src->r2field, _state, make_automatic); - ae_matrix_init_copy(&dst->i2field, &src->i2field, _state, make_automatic); - ae_matrix_init_copy(&dst->c2field, &src->c2field, _state, make_automatic); -} - - -void _rec1_clear(void* _p) -{ - rec1 *p = (rec1*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->b1field); - ae_vector_clear(&p->r1field); - ae_vector_clear(&p->i1field); - ae_vector_clear(&p->c1field); - ae_matrix_clear(&p->b2field); - ae_matrix_clear(&p->r2field); - ae_matrix_clear(&p->i2field); - ae_matrix_clear(&p->c2field); -} - - -void _rec1_destroy(void* _p) -{ - rec1 *p = (rec1*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->b1field); - ae_vector_destroy(&p->r1field); - ae_vector_destroy(&p->i1field); - ae_vector_destroy(&p->c1field); - ae_matrix_destroy(&p->b2field); - ae_matrix_destroy(&p->r2field); - ae_matrix_destroy(&p->i2field); - ae_matrix_destroy(&p->c2field); -} - - -void _rec4serialization_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - rec4serialization *p = (rec4serialization*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->b, 0, DT_BOOL, _state, make_automatic); - ae_vector_init(&p->i, 0, DT_INT, _state, make_automatic); - ae_vector_init(&p->r, 0, DT_REAL, _state, make_automatic); -} - - -void _rec4serialization_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - rec4serialization *dst = (rec4serialization*)_dst; - rec4serialization *src = (rec4serialization*)_src; - ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic); - ae_vector_init_copy(&dst->i, &src->i, _state, make_automatic); - ae_vector_init_copy(&dst->r, &src->r, _state, make_automatic); -} - - -void _rec4serialization_clear(void* _p) -{ - rec4serialization *p = (rec4serialization*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->b); - ae_vector_clear(&p->i); - ae_vector_clear(&p->r); -} - - -void _rec4serialization_destroy(void* _p) -{ - rec4serialization *p = (rec4serialization*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->b); - ae_vector_destroy(&p->i); - ae_vector_destroy(&p->r); -} - - -void _poolrec1_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - poolrec1 *p = (poolrec1*)_p; - ae_touch_ptr((void*)p); - ae_vector_init(&p->i1val, 0, DT_INT, _state, make_automatic); -} - - -void _poolrec1_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - poolrec1 *dst = (poolrec1*)_dst; - poolrec1 *src = (poolrec1*)_src; - dst->cval = src->cval; - dst->rval = src->rval; - dst->ival = src->ival; - dst->bval = src->bval; - ae_vector_init_copy(&dst->i1val, &src->i1val, _state, make_automatic); -} - - -void _poolrec1_clear(void* _p) -{ - poolrec1 *p = (poolrec1*)_p; - ae_touch_ptr((void*)p); - ae_vector_clear(&p->i1val); -} - - -void _poolrec1_destroy(void* _p) -{ - poolrec1 *p = (poolrec1*)_p; - ae_touch_ptr((void*)p); - ae_vector_destroy(&p->i1val); -} - - -void _poolrec2_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - poolrec2 *p = (poolrec2*)_p; - ae_touch_ptr((void*)p); - _poolrec1_init(&p->recval, _state, make_automatic); - ae_shared_pool_init(&p->pool, _state, make_automatic); -} - - -void _poolrec2_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - poolrec2 *dst = (poolrec2*)_dst; - poolrec2 *src = (poolrec2*)_src; - dst->bval = src->bval; - _poolrec1_init_copy(&dst->recval, &src->recval, _state, make_automatic); - ae_shared_pool_init_copy(&dst->pool, &src->pool, _state, make_automatic); -} - - -void _poolrec2_clear(void* _p) -{ - poolrec2 *p = (poolrec2*)_p; - ae_touch_ptr((void*)p); - _poolrec1_clear(&p->recval); - ae_shared_pool_clear(&p->pool); -} - - -void _poolrec2_destroy(void* _p) -{ - poolrec2 *p = (poolrec2*)_p; - ae_touch_ptr((void*)p); - _poolrec1_destroy(&p->recval); - ae_shared_pool_destroy(&p->pool); -} - - -void _poolsummand_init(void* _p, ae_state *_state, ae_bool make_automatic) -{ - poolsummand *p = (poolsummand*)_p; - ae_touch_ptr((void*)p); -} - - -void _poolsummand_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic) -{ - poolsummand *dst = (poolsummand*)_dst; - poolsummand *src = (poolsummand*)_src; - dst->val = src->val; -} - - -void _poolsummand_clear(void* _p) -{ - poolsummand *p = (poolsummand*)_p; - ae_touch_ptr((void*)p); -} - - -void _poolsummand_destroy(void* _p) -{ - poolsummand *p = (poolsummand*)_p; - ae_touch_ptr((void*)p); -} - - - -#if (AE_OS==AE_WINDOWS) || defined(AE_DEBUG4WINDOWS) -#include -#endif -#if (AE_OS==AE_POSIX) || defined(AE_DEBUG4POSIX) -#include -#include -#endif -#define AE_SINGLECORE 1 -#define AE_SEQUENTIAL_MULTICORE 2 -#define AE_PARALLEL_SINGLECORE 3 -#define AE_PARALLEL_MULTICORE 4 -#define AE_SKIP_TEST 5 -unsigned seed; -int global_failure_flag = 0; -ae_bool use_smp = ae_false; -#if (AE_OS==AE_WINDOWS) || defined(AE_DEBUG4WINDOWS) -CRITICAL_SECTION tests_lock; -CRITICAL_SECTION print_lock; -#elif (AE_OS==AE_POSIX) || defined(AE_DEBUG4POSIX) -pthread_mutex_t tests_lock; -pthread_mutex_t print_lock; -#else -void *tests_lock = NULL; -void *print_lock = NULL; -#endif -typedef struct -{ - const char *name; - ae_bool (*testfunc)(ae_bool, ae_state*); - -} _s_testrecord; -int unittests_processed = 0; -_s_testrecord unittests[] = -{ - {"tsort",testtsort}, - {"nearestneighbor",testnearestneighbor}, - {"hqrnd",testhqrnd}, - {"odesolver",testodesolver}, - {"sparse",testsparse}, - {"ablas",testablas}, - {"creflections",testcreflections}, - {"matgen",testmatgen}, - {"trfac",testtrfac}, - {"trlinsolve",testtrlinsolve}, - {"safesolve",testsafesolve}, - {"rcond",testrcond}, - {"matinv",testmatinv}, - {"hblas",testhblas}, - {"sblas",testsblas}, - {"ortfac",testortfac}, - {"fbls",testfbls}, - {"cqmodels",testcqmodels}, - {"bdsvd",testbdsvd}, - {"blas",testblas}, - {"svd",testsvd}, - {"optserv",testoptserv}, - {"snnls",testsnnls}, - {"sactivesets",testsactivesets}, - {"xblas",testxblas}, - {"directdensesolvers",testdirectdensesolvers}, - {"linmin",testlinmin}, - {"minlbfgs",testminlbfgs}, - {"normestimator",testnormestimator}, - {"linlsqr",testlinlsqr}, - {"minbleic",testminbleic}, - {"minqp",testminqp}, - {"minlp",testminlp}, - {"minnlc",testminnlc}, - {"minbc",testminbc}, - {"minns",testminns}, - {"mincg",testmincg}, - {"minlm",testminlm}, - {"evd",testevd}, - {"basestat",testbasestat}, - {"pca",testpca}, - {"bdss",testbdss}, - {"mlpbase",testmlpbase}, - {"lda",testlda}, - {"ssa",testssa}, - {"gammafunc",testgammafunc}, - {"normaldistr",testnormaldistr}, - {"linreg",testlinreg}, - {"filters",testfilters}, - {"mcpd",testmcpd}, - {"mlpe",testmlpe}, - {"mlptrain",testmlptrain}, - {"clustering",testclustering}, - {"dforest",testdforest}, - {"knn",testknn}, - {"gq",testgq}, - {"gkq",testgkq}, - {"autogk",testautogk}, - {"fft",testfft}, - {"fht",testfht}, - {"conv",testconv}, - {"corr",testcorr}, - {"idw",testidw}, - {"ratint",testratint}, - {"fitsphere",testfitsphere}, - {"spline1d",testspline1d}, - {"parametric",testparametric}, - {"spline3d",testspline3d}, - {"polint",testpolint}, - {"lsfit",testlsfit}, - {"spline2d",testspline2d}, - {"rbf",testrbf}, - {"hermite",testhermite}, - {"laguerre",testlaguerre}, - {"legendre",testlegendre}, - {"chebyshev",testchebyshev}, - {"wsr",testwsr}, - {"stest",teststest}, - {"studentttests",teststudentttests}, - {"mannwhitneyu",testmannwhitneyu}, - {"schur",testschur}, - {"spdgevd",testspdgevd}, - {"inverseupdate",testinverseupdate}, - {"polynomialsolver",testpolynomialsolver}, - {"nleq",testnleq}, - {"directsparsesolvers",testdirectsparsesolvers}, - {"lincg",testlincg}, - {"alglibbasics",testalglibbasics}, - - {NULL, NULL} -}; - -#if (AE_OS==AE_WINDOWS) || defined(AE_DEBUG4WINDOWS) -void acquire_lock(CRITICAL_SECTION *p_lock) -{ - EnterCriticalSection(p_lock); -} -void release_lock(CRITICAL_SECTION *p_lock) -{ - LeaveCriticalSection(p_lock); -} -#elif (AE_OS==AE_POSIX) || defined(AE_DEBUG4POSIX) -void acquire_lock(pthread_mutex_t *p_lock) -{ - pthread_mutex_lock(p_lock); -} -void release_lock(pthread_mutex_t *p_lock) -{ - pthread_mutex_unlock(p_lock); -} -#else -void acquire_lock(void **p_lock) -{ -} -void release_lock(void **p_lock) -{ -} -#endif - -ae_bool call_unittest( - ae_bool(*testfunc)(ae_bool, ae_state*), - int *psticky) -{ -#ifndef AE_USE_CPP_ERROR_HANDLING - ae_state _alglib_env_state; - ae_frame _frame_block; - jmp_buf _break_jump; - ae_bool result; - - ae_state_init(&_alglib_env_state); - if( setjmp(_break_jump) ) - { - *psticky = 1; - return ae_false; - } - ae_state_set_break_jump(&_alglib_env_state, &_break_jump); - if( use_smp ) - ae_state_set_flags(&_alglib_env_state, _ALGLIB_FLG_THREADING_PARALLEL); - ae_frame_make(&_alglib_env_state, &_frame_block); - result = testfunc(ae_true, &_alglib_env_state); - ae_state_clear(&_alglib_env_state); - if( !result ) - *psticky = 1; - return result; -#else - try - { - ae_state _alglib_env_state; - ae_frame _frame_block; - ae_bool result; - - ae_state_init(&_alglib_env_state); - ae_frame_make(&_alglib_env_state, &_frame_block); - if( use_smp ) - ae_state_set_flags(&_alglib_env_state, _ALGLIB_FLG_THREADING_PARALLEL); - result = testfunc(ae_true, &_alglib_env_state); - ae_state_clear(&_alglib_env_state); - if( !result ) - *psticky = 1; - return result; - } - catch(...) - { - *psticky = 1; - return ae_false; - } -#endif -} - -#if (AE_OS==AE_WINDOWS) || defined(AE_DEBUG4WINDOWS) -DWORD WINAPI tester_function(LPVOID T) -#elif AE_OS==AE_POSIX || defined(AE_DEBUG4POSIX) -void* tester_function(void *T) -#else -void tester_function(void *T) -#endif -{ - int idx; - ae_bool status; - for(;;) - { - /* - * try to acquire test record - */ - acquire_lock(&tests_lock); - if( unittests[unittests_processed].name==NULL ) - { - release_lock(&tests_lock); - break; - - } - idx = unittests_processed; - unittests_processed++; - release_lock(&tests_lock); - - /* - * Call unit test - */ - status = call_unittest(unittests[idx].testfunc, &global_failure_flag); - acquire_lock(&print_lock); - if( status ) - printf("%-32s OK\n", unittests[idx].name); - else - printf("%-32s FAILED\n", unittests[idx].name); - fflush(stdout); - release_lock(&print_lock); - } -#if AE_OS==AE_WINDOWS || defined(AE_DEBUG4WINDOWS) - return 0; -#elif AE_OS==AE_POSIX || defined(AE_DEBUG4POSIX) - return NULL; -#else -#endif -} - -int main(int argc, char **argv) -{ - time_t time_0, time_1; - union - { - double a; - ae_int32_t p[2]; - } u; - if( argc==2 ) - seed = (unsigned)atoi(argv[1]); - else - { - time_t t; - seed = (unsigned)time(&t); - } -#if (AE_OS==AE_WINDOWS) || defined(AE_DEBUG4WINDOWS) - InitializeCriticalSection(&tests_lock); - InitializeCriticalSection(&print_lock); -#elif (AE_OS==AE_POSIX) || defined(AE_DEBUG4POSIX) - pthread_mutex_init(&tests_lock, NULL); - pthread_mutex_init(&print_lock, NULL); -#endif - - /* - * SMP settings - */ -#if AE_TEST==AE_PARALLEL_MULTICORE || AE_TEST==AE_SEQUENTIAL_MULTICORE - use_smp = ae_true; -#else - use_smp = ae_false; -#endif - - /* - * Seed - */ - printf("SEED: %u\n", (unsigned int)seed); - srand(seed); - - /* - * Compiler - */ -#if AE_COMPILER==AE_GNUC - printf("COMPILER: GCC\n"); -#elif AE_COMPILER==AE_SUNC - printf("COMPILER: SunStudio\n"); -#elif AE_COMPILER==AE_MSVC - printf("COMPILER: MSVC\n"); -#else - printf("COMPILER: unknown\n"); -#endif - - /* - * Architecture - */ - if( sizeof(void*)==4 ) - printf("HARDWARE: 32-bit\n"); - else if( sizeof(void*)==8 ) - printf("HARDWARE: 64-bit\n"); - else - printf("HARDWARE: strange (non-32, non-64)\n"); - - /* - * determine endianness of hardware. - * 1983 is a good number - non-periodic double representation allow us to - * easily distinguish between upper and lower halfs and to detect mixed endian hardware. - */ - u.a = 1.0/1983.0; - if( u.p[1]==0x3f408642 ) - printf("HARDWARE: little-endian\n"); - else if( u.p[0]==0x3f408642 ) - printf("HARDWARE: big-endian\n"); - else - printf("HARDWARE: mixed-endian\n"); - - /* - * CPU (as defined) - */ -#if AE_CPU==AE_INTEL - printf("CPU: Intel\n"); -#elif AE_CPU==AE_SPARC - printf("CPU: SPARC\n"); -#else - printf("CPU: unknown\n"); -#endif - - /* - * Cores count - */ -#ifdef _ALGLIB_HAS_WORKSTEALING - printf("CORES: %d\n", (int)ae_cores_count()); -#else - printf("CORES: 1 (serial version)\n"); -#endif - - /* - * Support for vendor libraries - */ -#ifdef AE_MKL - printf("LIBS: MKL (Intel)\n"); -#else - printf("LIBS: \n"); -#endif - - /* - * CPUID results - */ - printf("CPUID: %s\n", ae_cpuid()&CPU_SSE2 ? "sse2" : ""); - - /* - * OS - */ -#if AE_OS==AE_WINDOWS - printf("OS: Windows\n"); -#elif AE_OS==AE_POSIX - printf("OS: POSIX\n"); -#else - printf("OS: unknown\n"); -#endif - - /* - * Testing mode - */ -#if (AE_TEST==0) || (AE_TEST==AE_SINGLECORE) - printf("TESTING MODE: single core\n"); -#elif AE_TEST==AE_PARALLEL_SINGLECORE - printf("TESTING MODE: single core, parallel\n"); -#elif AE_TEST==AE_SEQUENTIAL_MULTICORE - printf("TESTING MODE: milti-core, sequential\n"); -#elif AE_TEST==AE_PARALLEL_MULTICORE - printf("TESTING MODE: milti-core, parallel\n"); -#elif AE_TEST==AE_SKIP_TEST - printf("TESTING MODE: just compiling\n"); - printf("Done in 0 seconds\n"); - return 0; -#else -#error Unknown AE_TEST being passed -#endif - - /* - * now we are ready to test! - */ - time(&time_0); -#ifdef _ALGLIB_HAS_WORKSTEALING - if( ae_smpselftests() ) - printf("%-32s OK\n", "SMP self tests"); - else - { - printf("%-32s FAILED\n", "SMP self tests"); - return 1; - } -#endif - fflush(stdout); -#if AE_TEST==0 || AE_TEST==AE_SINGLECORE || AE_TEST==AE_SEQUENTIAL_MULTICORE || AE_TEST==AE_SKIP_TEST - tester_function(NULL); -#elif AE_TEST==AE_PARALLEL_MULTICORE || AE_TEST==AE_PARALLEL_SINGLECORE -#ifdef _ALGLIB_HAS_WORKSTEALING - ae_set_cores_to_use(0); -#endif -#if AE_OS==AE_WINDOWS || defined(AE_DEBUG4WINDOWS) - { - SYSTEM_INFO sysInfo; - HANDLE *hThreads = NULL; - int idx; - GetSystemInfo(&sysInfo); - ae_assert(sysInfo.dwNumberOfProcessors>=1, "processors count is less than 1", NULL); - hThreads = (HANDLE*)malloc(sizeof(HANDLE)*sysInfo.dwNumberOfProcessors); - ae_assert(hThreads!=NULL, "malloc failure", NULL); - for(idx=0; idx=1, "processors count is less than 1", NULL); - threads = (pthread_t*)malloc(sizeof(pthread_t)*cpu_cnt); - ae_assert(threads!=NULL, "malloc failure", NULL); - for(idx=0; idx -#include "alglibinternal.h" -#include "alglibmisc.h" -#include "diffequations.h" -#include "linalg.h" -#include "optimization.h" -#include "solvers.h" -#include "statistics.h" -#include "dataanalysis.h" -#include "specialfunctions.h" -#include "integration.h" -#include "fasttransforms.h" -#include "interpolation.h" - -using namespace alglib; - -bool doc_test_bool(bool v, bool t) -{ return (v && t) || (!v && !t); } - -bool doc_test_int(ae_int_t v, ae_int_t t) -{ return v==t; } - -bool doc_test_real(double v, double t, double _threshold) -{ - double s = _threshold>=0 ? 1.0 : fabs(t); - double threshold = fabs(_threshold); - return fabs(v-t)/s<=threshold; -} - -bool doc_test_complex(alglib::complex v, alglib::complex t, double _threshold) -{ - double s = _threshold>=0 ? 1.0 : alglib::abscomplex(t); - double threshold = fabs(_threshold); - return abscomplex(v-t)/s<=threshold; -} - - -bool doc_test_bool_vector(const boolean_1d_array &v, const boolean_1d_array &t) -{ - ae_int_t i; - if( v.length()!=t.length() ) - return false; - for(i=0; i=0 ? 1.0 : fabs(t(i)); - double threshold = fabs(_threshold); - if( fabs(v(i)-t(i))/s>threshold ) - return false; - } - return true; -} - -bool doc_test_real_matrix(const real_2d_array &v, const real_2d_array &t, double _threshold) -{ - ae_int_t i, j; - if( v.rows()!=t.rows() ) - return false; - if( v.cols()!=t.cols() ) - return false; - for(i=0; i=0 ? 1.0 : fabs(t(i,j)); - double threshold = fabs(_threshold); - if( fabs(v(i,j)-t(i,j))/s>threshold ) - return false; - } - return true; -} - -bool doc_test_complex_vector(const complex_1d_array &v, const complex_1d_array &t, double _threshold) -{ - ae_int_t i; - if( v.length()!=t.length() ) - return false; - for(i=0; i=0 ? 1.0 : alglib::abscomplex(t(i)); - double threshold = fabs(_threshold); - if( abscomplex(v(i)-t(i))/s>threshold ) - return false; - } - return true; -} - -bool doc_test_complex_matrix(const complex_2d_array &v, const complex_2d_array &t, double _threshold) -{ - ae_int_t i, j; - if( v.rows()!=t.rows() ) - return false; - if( v.cols()!=t.cols() ) - return false; - for(i=0; i=0 ? 1.0 : alglib::abscomplex(t(i,j)); - double threshold = fabs(_threshold); - if( abscomplex(v(i,j)-t(i,j))/s>threshold ) - return false; - } - return true; -} - -template -void spoil_vector_by_adding_element(T &x) -{ - ae_int_t i; - T y = x; - x.setlength(y.length()+1); - for(i=0; i -void spoil_vector_by_deleting_element(T &x) -{ - ae_int_t i; - T y = x; - x.setlength(y.length()-1); - for(i=0; i -void spoil_matrix_by_adding_row(T &x) -{ - ae_int_t i, j; - T y = x; - x.setlength(y.rows()+1, y.cols()); - for(i=0; i -void spoil_matrix_by_deleting_row(T &x) -{ - ae_int_t i, j; - T y = x; - x.setlength(y.rows()-1, y.cols()); - for(i=0; i -void spoil_matrix_by_adding_col(T &x) -{ - ae_int_t i, j; - T y = x; - x.setlength(y.rows(), y.cols()+1); - for(i=0; i -void spoil_matrix_by_deleting_col(T &x) -{ - ae_int_t i, j; - T y = x; - x.setlength(y.rows(), y.cols()-1); - for(i=0; i -void spoil_vector_by_nan(T &x) -{ - if( x.length()!=0 ) - x(randominteger(x.length())) = fp_nan; -} - -template -void spoil_vector_by_posinf(T &x) -{ - if( x.length()!=0 ) - x(randominteger(x.length())) = fp_posinf; -} - -template -void spoil_vector_by_neginf(T &x) -{ - if( x.length()!=0 ) - x(randominteger(x.length())) = fp_neginf; -} - - - -template -void spoil_matrix_by_nan(T &x) -{ - if( x.rows()!=0 && x.cols()!=0 ) - x(randominteger(x.rows()),randominteger(x.cols())) = fp_nan; -} - -template -void spoil_matrix_by_posinf(T &x) -{ - if( x.rows()!=0 && x.cols()!=0 ) - x(randominteger(x.rows()),randominteger(x.cols())) = fp_posinf; -} - -template -void spoil_matrix_by_neginf(T &x) -{ - if( x.rows()!=0 && x.cols()!=0 ) - x(randominteger(x.rows()),randominteger(x.cols())) = fp_neginf; -} - -void function1_func(const real_1d_array &x, double &func, void *ptr) -{ - // - // this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4 - // - func = 100*pow(x[0]+3,4) + pow(x[1]-3,4); -} -void function1_grad(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr) -{ - // - // this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4 - // and its derivatives df/d0 and df/dx1 - // - func = 100*pow(x[0]+3,4) + pow(x[1]-3,4); - grad[0] = 400*pow(x[0]+3,3); - grad[1] = 4*pow(x[1]-3,3); -} -void function1_hess(const real_1d_array &x, double &func, real_1d_array &grad, real_2d_array &hess, void *ptr) -{ - // - // this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4 - // its derivatives df/d0 and df/dx1 - // and its Hessian. - // - func = 100*pow(x[0]+3,4) + pow(x[1]-3,4); - grad[0] = 400*pow(x[0]+3,3); - grad[1] = 4*pow(x[1]-3,3); - hess[0][0] = 1200*pow(x[0]+3,2); - hess[0][1] = 0; - hess[1][0] = 0; - hess[1][1] = 12*pow(x[1]-3,2); -} -void function1_fvec(const real_1d_array &x, real_1d_array &fi, void *ptr) -{ - // - // this callback calculates - // f0(x0,x1) = 100*(x0+3)^4, - // f1(x0,x1) = (x1-3)^4 - // - fi[0] = 10*pow(x[0]+3,2); - fi[1] = pow(x[1]-3,2); -} -void function1_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr) -{ - // - // this callback calculates - // f0(x0,x1) = 100*(x0+3)^4, - // f1(x0,x1) = (x1-3)^4 - // and Jacobian matrix J = [dfi/dxj] - // - fi[0] = 10*pow(x[0]+3,2); - fi[1] = pow(x[1]-3,2); - jac[0][0] = 20*(x[0]+3); - jac[0][1] = 0; - jac[1][0] = 0; - jac[1][1] = 2*(x[1]-3); -} -void function2_func(const real_1d_array &x, double &func, void *ptr) -{ - // - // this callback calculates f(x0,x1) = (x0^2+1)^2 + (x1-1)^2 - // - func = pow(x[0]*x[0]+1,2) + pow(x[1]-1,2); -} -void function2_grad(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr) -{ - // - // this callback calculates f(x0,x1) = (x0^2+1)^2 + (x1-1)^2 - // and its derivatives df/d0 and df/dx1 - // - func = pow(x[0]*x[0]+1,2) + pow(x[1]-1,2); - grad[0] = 4*(x[0]*x[0]+1)*x[0]; - grad[1] = 2*(x[1]-1); -} -void function2_hess(const real_1d_array &x, double &func, real_1d_array &grad, real_2d_array &hess, void *ptr) -{ - // - // this callback calculates f(x0,x1) = (x0^2+1)^2 + (x1-1)^2 - // its gradient and Hessian - // - func = pow(x[0]*x[0]+1,2) + pow(x[1]-1,2); - grad[0] = 4*(x[0]*x[0]+1)*x[0]; - grad[1] = 2*(x[1]-1); - hess[0][0] = 12*x[0]*x[0]+4; - hess[0][1] = 0; - hess[1][0] = 0; - hess[1][1] = 2; -} -void function2_fvec(const real_1d_array &x, real_1d_array &fi, void *ptr) -{ - // - // this callback calculates - // f0(x0,x1) = x0^2+1 - // f1(x0,x1) = x1-1 - // - fi[0] = x[0]*x[0]+1; - fi[1] = x[1]-1; -} -void function2_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr) -{ - // - // this callback calculates - // f0(x0,x1) = x0^2+1 - // f1(x0,x1) = x1-1 - // and Jacobian matrix J = [dfi/dxj] - // - fi[0] = x[0]*x[0]+1; - fi[1] = x[1]-1; - jac[0][0] = 2*x[0]; - jac[0][1] = 0; - jac[1][0] = 0; - jac[1][1] = 1; -} -void nlcfunc1_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr) -{ - // - // this callback calculates - // - // f0(x0,x1) = -x0+x1 - // f1(x0,x1) = x0^2+x1^2-1 - // - // and Jacobian matrix J = [dfi/dxj] - // - fi[0] = -x[0]+x[1]; - fi[1] = x[0]*x[0] + x[1]*x[1] - 1.0; - jac[0][0] = -1.0; - jac[0][1] = +1.0; - jac[1][0] = 2*x[0]; - jac[1][1] = 2*x[1]; -} -void nlcfunc2_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr) -{ - // - // this callback calculates - // - // f0(x0,x1,x2) = x0+x1 - // f1(x0,x1,x2) = x2-exp(x0) - // f2(x0,x1,x2) = x0^2+x1^2-1 - // - // and Jacobian matrix J = [dfi/dxj] - // - fi[0] = x[0]+x[1]; - fi[1] = x[2]-exp(x[0]); - fi[2] = x[0]*x[0] + x[1]*x[1] - 1.0; - jac[0][0] = 1.0; - jac[0][1] = 1.0; - jac[0][2] = 0.0; - jac[1][0] = -exp(x[0]); - jac[1][1] = 0.0; - jac[1][2] = 1.0; - jac[2][0] = 2*x[0]; - jac[2][1] = 2*x[1]; - jac[2][2] = 0.0; -} -void nsfunc1_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr) -{ - // - // this callback calculates - // - // f0(x0,x1) = 2*|x0|+x1 - // - // and Jacobian matrix J = [df0/dx0 df0/dx1] - // - fi[0] = 2*fabs(double(x[0]))+fabs(double(x[1])); - jac[0][0] = 2*alglib::sign(x[0]); - jac[0][1] = alglib::sign(x[1]); -} -void nsfunc1_fvec(const real_1d_array &x, real_1d_array &fi, void *ptr) -{ - // - // this callback calculates - // - // f0(x0,x1) = 2*|x0|+x1 - // - fi[0] = 2*fabs(double(x[0]))+fabs(double(x[1])); -} -void nsfunc2_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr) -{ - // - // this callback calculates function vector - // - // f0(x0,x1) = 2*|x0|+x1 - // f1(x0,x1) = x0-1 - // f2(x0,x1) = -x1-1 - // - // and Jacobian matrix J - // - // [ df0/dx0 df0/dx1 ] - // J = [ df1/dx0 df1/dx1 ] - // [ df2/dx0 df2/dx1 ] - // - fi[0] = 2*fabs(double(x[0]))+fabs(double(x[1])); - jac[0][0] = 2*alglib::sign(x[0]); - jac[0][1] = alglib::sign(x[1]); - fi[1] = x[0]-1; - jac[1][0] = 1; - jac[1][1] = 0; - fi[2] = -x[1]-1; - jac[2][0] = 0; - jac[2][1] = -1; -} -void bad_func(const real_1d_array &x, double &func, void *ptr) -{ - // - // this callback calculates 'bad' function, - // i.e. function with incorrectly calculated derivatives - // - func = 100*pow(x[0]+3,4) + pow(x[1]-3,4); -} -void bad_grad(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr) -{ - // - // this callback calculates 'bad' function, - // i.e. function with incorrectly calculated derivatives - // - func = 100*pow(x[0]+3,4) + pow(x[1]-3,4); - grad[0] = 40*pow(x[0]+3,3); - grad[1] = 40*pow(x[1]-3,3); -} -void bad_hess(const real_1d_array &x, double &func, real_1d_array &grad, real_2d_array &hess, void *ptr) -{ - // - // this callback calculates 'bad' function, - // i.e. function with incorrectly calculated derivatives - // - func = 100*pow(x[0]+3,4) + pow(x[1]-3,4); - grad[0] = 40*pow(x[0]+3,3); - grad[1] = 40*pow(x[1]-3,3); - hess[0][0] = 120*pow(x[0]+3,2); - hess[0][1] = 0; - hess[1][0] = 0; - hess[1][1] = 120*pow(x[1]-3,2); -} -void bad_fvec(const real_1d_array &x, real_1d_array &fi, void *ptr) -{ - // - // this callback calculates 'bad' function, - // i.e. function with incorrectly calculated derivatives - // - fi[0] = 10*pow(x[0]+3,2); - fi[1] = pow(x[1]-3,2); -} -void bad_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr) -{ - // - // this callback calculates 'bad' function, - // i.e. function with incorrectly calculated derivatives - // - fi[0] = 10*pow(x[0]+3,2); - fi[1] = pow(x[1]-3,2); - jac[0][0] = 2*(x[0]+3); - jac[0][1] = 1; - jac[1][0] = 0; - jac[1][1] = 20*(x[1]-3); -} -void function_cx_1_func(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr) -{ - // this callback calculates f(c,x)=exp(-c0*sqr(x0)) - // where x is a position on X-axis and c is adjustable parameter - func = exp(-c[0]*pow(x[0],2)); -} -void function_cx_1_grad(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, void *ptr) -{ - // this callback calculates f(c,x)=exp(-c0*sqr(x0)) and gradient G={df/dc[i]} - // where x is a position on X-axis and c is adjustable parameter. - // IMPORTANT: gradient is calculated with respect to C, not to X - func = exp(-c[0]*pow(x[0],2)); - grad[0] = -pow(x[0],2)*func; -} -void function_cx_1_hess(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, real_2d_array &hess, void *ptr) -{ - // this callback calculates f(c,x)=exp(-c0*sqr(x0)), gradient G={df/dc[i]} and Hessian H={d2f/(dc[i]*dc[j])} - // where x is a position on X-axis and c is adjustable parameter. - // IMPORTANT: gradient/Hessian are calculated with respect to C, not to X - func = exp(-c[0]*pow(x[0],2)); - grad[0] = -pow(x[0],2)*func; - hess[0][0] = pow(x[0],4)*func; -} -void ode_function_1_diff(const real_1d_array &y, double x, real_1d_array &dy, void *ptr) -{ - // this callback calculates f(y[],x)=-y[0] - dy[0] = -y[0]; -} -void int_function_1_func(double x, double xminusa, double bminusx, double &y, void *ptr) -{ - // this callback calculates f(x)=exp(x) - y = exp(x); -} -void function_debt_func(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr) -{ - // - // this callback calculates f(c,x)=c[0]*(1+c[1]*(pow(x[0]-1999,c[2])-1)) - // - func = c[0]*(1+c[1]*(pow(x[0]-1999,c[2])-1)); -} -void s1_grad(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr) -{ - // - // this callback calculates f(x) = (1+x)^(-0.2) + (1-x)^(-0.3) + 1000*x and its gradient. - // - // function is trimmed when we calculate it near the singular points or outside of the [-1,+1]. - // Note that we do NOT calculate gradient in this case. - // - if( (x[0]<=-0.999999999999) || (x[0]>=+0.999999999999) ) - { - func = 1.0E+300; - return; - } - func = pow(1+x[0],-0.2) + pow(1-x[0],-0.3) + 1000*x[0]; - grad[0] = -0.2*pow(1+x[0],-1.2) +0.3*pow(1-x[0],-1.3) + 1000; -} - -int main() -{ - bool _TotalResult = true; - bool _TestResult; - int _spoil_scenario; - printf("C++ tests. Please wait...\n"); -#if AE_MALLOC==AE_BASIC_STATIC_MALLOC - const ae_int_t _static_pool_size = 1000000; - ae_int_t _static_pool_used = 0, _static_pool_free = 0; - void *_static_pool = malloc(_static_pool_size); - alglib_impl::set_memory_pool(_static_pool, _static_pool_size); - alglib_impl::memory_pool_stats(&_static_pool_used, &_static_pool_free); - if( _static_pool_used!=0 || _static_pool_free<0.95*_static_pool_size || _static_pool_free>_static_pool_size ) - { - _TotalResult = false; - printf("FAILURE: memory pool usage stats are inconsistent!\n"); - return 1; - } - { - alglib::real_2d_array a("[[1,2],[3,4]]"); - ae_int_t _static_pool_used2 = 0, _static_pool_free2 = 0; - alglib_impl::memory_pool_stats(&_static_pool_used2, &_static_pool_free2); - if( _static_pool_used2<=_static_pool_used || - _static_pool_free2>=_static_pool_free || - _static_pool_used+_static_pool_free!=_static_pool_used2+_static_pool_free2 ) - { - _TotalResult = false; - printf("FAILURE: memory pool usage stats are inconsistent!\n"); - return 1; - } - a.setlength(1,1); // make sure that destructor of /a/ is never called prior to this point - } -#endif -#ifdef AE_USE_ALLOC_COUNTER - printf("Allocation counter activated...\n"); - alglib_impl::_use_alloc_counter = ae_true; - if( alglib_impl::_alloc_counter!=0 ) - { - _TotalResult = false; - printf("FAILURE: alloc_counter is non-zero on start!\n"); - } - { - { - alglib::real_1d_array x; - x.setlength(1); - if( alglib_impl::_alloc_counter==0 ) - printf(":::: WARNING: ALLOC_COUNTER IS INACTIVE!!! :::::\n"); - } - if( alglib_impl::_alloc_counter!=0 ) - { - printf("FAILURE: alloc_counter does not decrease!\n"); - return 1; - } - } -#endif - try - { - // - // TEST nneighbor_d_1 - // Nearest neighbor search, KNN queries - // - printf("0/151\n"); - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++) - { - try - { - real_2d_array a = "[[0,0],[0,1],[1,0],[1,1]]"; - if( _spoil_scenario==0 ) - spoil_matrix_by_nan(a); - if( _spoil_scenario==1 ) - spoil_matrix_by_posinf(a); - if( _spoil_scenario==2 ) - spoil_matrix_by_neginf(a); - ae_int_t nx = 2; - ae_int_t ny = 0; - ae_int_t normtype = 2; - kdtree kdt; - real_1d_array x; - real_2d_array r = "[[]]"; - ae_int_t k; - kdtreebuild(a, nx, ny, normtype, kdt); - x = "[-1,0]"; - k = kdtreequeryknn(kdt, x, 1); - _TestResult = _TestResult && doc_test_int(k, 1); - kdtreequeryresultsx(kdt, r); - _TestResult = _TestResult && doc_test_real_matrix(r, "[[0,0]]", 0.05); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "nneighbor_d_1"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST nneighbor_t_2 - // Subsequent queries; buffered functions must use previously allocated storage (if large enough), so buffer may contain some info from previous call - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++) - { - try - { - real_2d_array a = "[[0,0],[0,1],[1,0],[1,1]]"; - if( _spoil_scenario==0 ) - spoil_matrix_by_nan(a); - if( _spoil_scenario==1 ) - spoil_matrix_by_posinf(a); - if( _spoil_scenario==2 ) - spoil_matrix_by_neginf(a); - ae_int_t nx = 2; - ae_int_t ny = 0; - ae_int_t normtype = 2; - kdtree kdt; - real_1d_array x; - real_2d_array rx = "[[]]"; - ae_int_t k; - kdtreebuild(a, nx, ny, normtype, kdt); - x = "[+2,0]"; - k = kdtreequeryknn(kdt, x, 2, true); - _TestResult = _TestResult && doc_test_int(k, 2); - kdtreequeryresultsx(kdt, rx); - _TestResult = _TestResult && doc_test_real_matrix(rx, "[[1,0],[1,1]]", 0.05); - x = "[-2,0]"; - k = kdtreequeryknn(kdt, x, 1, true); - _TestResult = _TestResult && doc_test_int(k, 1); - kdtreequeryresultsx(kdt, rx); - _TestResult = _TestResult && doc_test_real_matrix(rx, "[[0,0],[1,1]]", 0.05); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "nneighbor_t_2"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST nneighbor_d_2 - // Serialization of KD-trees - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++) - { - try - { - real_2d_array a = "[[0,0],[0,1],[1,0],[1,1]]"; - if( _spoil_scenario==0 ) - spoil_matrix_by_nan(a); - if( _spoil_scenario==1 ) - spoil_matrix_by_posinf(a); - if( _spoil_scenario==2 ) - spoil_matrix_by_neginf(a); - ae_int_t nx = 2; - ae_int_t ny = 0; - ae_int_t normtype = 2; - kdtree kdt0; - kdtree kdt1; - std::string s; - real_1d_array x; - real_2d_array r0 = "[[]]"; - real_2d_array r1 = "[[]]"; - - // - // Build tree and serialize it - // - kdtreebuild(a, nx, ny, normtype, kdt0); - alglib::kdtreeserialize(kdt0, s); - alglib::kdtreeunserialize(s, kdt1); - - // - // Compare results from KNN queries - // - x = "[-1,0]"; - kdtreequeryknn(kdt0, x, 1); - kdtreequeryresultsx(kdt0, r0); - kdtreequeryknn(kdt1, x, 1); - kdtreequeryresultsx(kdt1, r1); - _TestResult = _TestResult && doc_test_real_matrix(r0, "[[0,0]]", 0.05); - _TestResult = _TestResult && doc_test_real_matrix(r1, "[[0,0]]", 0.05); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "nneighbor_d_2"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST odesolver_d1 - // Solving y'=-y with ODE solver - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<13; _spoil_scenario++) - { - try - { - real_1d_array y = "[1]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(y); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(y); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(y); - if( _spoil_scenario==3 ) - spoil_vector_by_deleting_element(y); - real_1d_array x = "[0, 1, 2, 3]"; - if( _spoil_scenario==4 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==5 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==6 ) - spoil_vector_by_neginf(x); - double eps = 0.00001; - if( _spoil_scenario==7 ) - eps = fp_nan; - if( _spoil_scenario==8 ) - eps = fp_posinf; - if( _spoil_scenario==9 ) - eps = fp_neginf; - double h = 0; - if( _spoil_scenario==10 ) - h = fp_nan; - if( _spoil_scenario==11 ) - h = fp_posinf; - if( _spoil_scenario==12 ) - h = fp_neginf; - odesolverstate s; - ae_int_t m; - real_1d_array xtbl; - real_2d_array ytbl; - odesolverreport rep; - odesolverrkck(y, x, eps, h, s); - alglib::odesolversolve(s, ode_function_1_diff); - odesolverresults(s, m, xtbl, ytbl, rep); - _TestResult = _TestResult && doc_test_int(m, 4); - _TestResult = _TestResult && doc_test_real_vector(xtbl, "[0, 1, 2, 3]", 0.005); - _TestResult = _TestResult && doc_test_real_matrix(ytbl, "[[1], [0.367], [0.135], [0.050]]", 0.005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "odesolver_d1"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST sparse_d_1 - // Basic operations with sparse matrices - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<1; _spoil_scenario++) - { - try - { - // - // This example demonstrates creation/initialization of the sparse matrix - // and matrix-vector multiplication. - // - // First, we have to create matrix and initialize it. Matrix is initially created - // in the Hash-Table format, which allows convenient initialization. We can modify - // Hash-Table matrix with sparseset() and sparseadd() functions. - // - // NOTE: Unlike CRS format, Hash-Table representation allows you to initialize - // elements in the arbitrary order. You may see that we initialize a[0][0] first, - // then move to the second row, and then move back to the first row. - // - sparsematrix s; - sparsecreate(2, 2, s); - sparseset(s, 0, 0, 2.0); - sparseset(s, 1, 1, 1.0); - sparseset(s, 0, 1, 1.0); - - sparseadd(s, 1, 1, 4.0); - - // - // Now S is equal to - // [ 2 1 ] - // [ 5 ] - // Lets check it by reading matrix contents with sparseget(). - // You may see that with sparseget() you may read both non-zero - // and zero elements. - // - double v; - v = sparseget(s, 0, 0); - _TestResult = _TestResult && doc_test_real(v, 2.0000, 0.005); - v = sparseget(s, 0, 1); - _TestResult = _TestResult && doc_test_real(v, 1.0000, 0.005); - v = sparseget(s, 1, 0); - _TestResult = _TestResult && doc_test_real(v, 0.0000, 0.005); - v = sparseget(s, 1, 1); - _TestResult = _TestResult && doc_test_real(v, 5.0000, 0.005); - - // - // After successful creation we can use our matrix for linear operations. - // - // However, there is one more thing we MUST do before using S in linear - // operations: we have to convert it from HashTable representation (used for - // initialization and dynamic operations) to CRS format with sparseconverttocrs() - // call. If you omit this call, ALGLIB will generate exception on the first - // attempt to use S in linear operations. - // - sparseconverttocrs(s); - - // - // Now S is in the CRS format and we are ready to do linear operations. - // Lets calculate A*x for some x. - // - real_1d_array x = "[1,-1]"; - if( _spoil_scenario==0 ) - spoil_vector_by_deleting_element(x); - real_1d_array y = "[]"; - sparsemv(s, x, y); - _TestResult = _TestResult && doc_test_real_vector(y, "[1.000,-5.000]", 0.005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "sparse_d_1"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST sparse_d_crs - // Advanced topic: creation in the CRS format. - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<2; _spoil_scenario++) - { - try - { - // - // This example demonstrates creation/initialization of the sparse matrix in the - // CRS format. - // - // Hash-Table format used by default is very convenient (it allows easy - // insertion of elements, automatic memory reallocation), but has - // significant memory and performance overhead. Insertion of one element - // costs hundreds of CPU cycles, and memory consumption is several times - // higher than that of CRS. - // - // When you work with really large matrices and when you can tell in - // advance how many elements EXACTLY you need, it can be beneficial to - // create matrix in the CRS format from the very beginning. - // - // If you want to create matrix in the CRS format, you should: - // * use sparsecreatecrs() function - // * know row sizes in advance (number of non-zero entries in the each row) - // * initialize matrix with sparseset() - another function, sparseadd(), is not allowed - // * initialize elements from left to right, from top to bottom, each - // element is initialized only once. - // - sparsematrix s; - integer_1d_array row_sizes = "[2,2,2,1]"; - if( _spoil_scenario==0 ) - spoil_vector_by_deleting_element(row_sizes); - sparsecreatecrs(4, 4, row_sizes, s); - sparseset(s, 0, 0, 2.0); - sparseset(s, 0, 1, 1.0); - sparseset(s, 1, 1, 4.0); - sparseset(s, 1, 2, 2.0); - sparseset(s, 2, 2, 3.0); - sparseset(s, 2, 3, 1.0); - sparseset(s, 3, 3, 9.0); - - // - // Now S is equal to - // [ 2 1 ] - // [ 4 2 ] - // [ 3 1 ] - // [ 9 ] - // - // We should point that we have initialized S elements from left to right, - // from top to bottom. CRS representation does NOT allow you to do so in - // the different order. Try to change order of the sparseset() calls above, - // and you will see that your program generates exception. - // - // We can check it by reading matrix contents with sparseget(). - // However, you should remember that sparseget() is inefficient on - // CRS matrices (it may have to pass through all elements of the row - // until it finds element you need). - // - double v; - v = sparseget(s, 0, 0); - _TestResult = _TestResult && doc_test_real(v, 2.0000, 0.005); - v = sparseget(s, 2, 3); - _TestResult = _TestResult && doc_test_real(v, 1.0000, 0.005); - - // you may see that you can read zero elements (which are not stored) with sparseget() - v = sparseget(s, 3, 2); - _TestResult = _TestResult && doc_test_real(v, 0.0000, 0.005); - - // - // After successful creation we can use our matrix for linear operations. - // Lets calculate A*x for some x. - // - real_1d_array x = "[1,-1,1,-1]"; - if( _spoil_scenario==1 ) - spoil_vector_by_deleting_element(x); - real_1d_array y = "[]"; - sparsemv(s, x, y); - _TestResult = _TestResult && doc_test_real_vector(y, "[1.000,-2.000,2.000,-9]", 0.005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "sparse_d_crs"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST ablas_d_gemm - // Matrix multiplication (single-threaded) - // - _TestResult = true; - try - { - real_2d_array a = "[[2,1],[1,3]]"; - real_2d_array b = "[[2,1],[0,1]]"; - real_2d_array c = "[[0,0],[0,0]]"; - - // - // rmatrixgemm() function allows us to calculate matrix product C:=A*B or - // to perform more general operation, C:=alpha*op1(A)*op2(B)+beta*C, - // where A, B, C are rectangular matrices, op(X) can be X or X^T, - // alpha and beta are scalars. - // - // This function: - // * can apply transposition and/or multiplication by scalar to operands - // * can use arbitrary part of matrices A/B (given by submatrix offset) - // * can store result into arbitrary part of C - // * for performance reasons requires C to be preallocated - // - // Parameters of this function are: - // * M, N, K - sizes of op1(A) (which is MxK), op2(B) (which - // is KxN) and C (which is MxN) - // * Alpha - coefficient before A*B - // * A, IA, JA - matrix A and offset of the submatrix - // * OpTypeA - transformation type: - // 0 - no transformation - // 1 - transposition - // * B, IB, JB - matrix B and offset of the submatrix - // * OpTypeB - transformation type: - // 0 - no transformation - // 1 - transposition - // * Beta - coefficient before C - // * C, IC, JC - preallocated matrix C and offset of the submatrix - // - // Below we perform simple product C:=A*B (alpha=1, beta=0) - // - // IMPORTANT: this function works with preallocated C, which must be large - // enough to store multiplication result. - // - ae_int_t m = 2; - ae_int_t n = 2; - ae_int_t k = 2; - double alpha = 1.0; - ae_int_t ia = 0; - ae_int_t ja = 0; - ae_int_t optypea = 0; - ae_int_t ib = 0; - ae_int_t jb = 0; - ae_int_t optypeb = 0; - double beta = 0.0; - ae_int_t ic = 0; - ae_int_t jc = 0; - rmatrixgemm(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc); - _TestResult = _TestResult && doc_test_real_matrix(c, "[[4,3],[2,4]]", 0.0001); - - // - // Now we try to apply some simple transformation to operands: C:=A*B^T - // - optypeb = 1; - rmatrixgemm(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc); - _TestResult = _TestResult && doc_test_real_matrix(c, "[[5,1],[5,3]]", 0.0001); - } - catch(ap_error) - { _TestResult = false; } - if( !_TestResult) - { - printf("%-32s FAILED\n", "ablas_d_gemm"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST ablas_d_syrk - // Symmetric rank-K update (single-threaded) - // - _TestResult = true; - try - { - // - // rmatrixsyrk() function allows us to calculate symmetric rank-K update - // C := beta*C + alpha*A'*A, where C is square N*N matrix, A is square K*N - // matrix, alpha and beta are scalars. It is also possible to update by - // adding A*A' instead of A'*A. - // - // Parameters of this function are: - // * N, K - matrix size - // * Alpha - coefficient before A - // * A, IA, JA - matrix and submatrix offsets - // * OpTypeA - multiplication type: - // * 0 - A*A^T is calculated - // * 2 - A^T*A is calculated - // * Beta - coefficient before C - // * C, IC, JC - preallocated input/output matrix and submatrix offsets - // * IsUpper - whether upper or lower triangle of C is updated; - // this function updates only one half of C, leaving - // other half unchanged (not referenced at all). - // - // Below we will show how to calculate simple product C:=A'*A - // - // NOTE: beta=0 and we do not use previous value of C, but still it - // MUST be preallocated. - // - ae_int_t n = 2; - ae_int_t k = 1; - double alpha = 1.0; - ae_int_t ia = 0; - ae_int_t ja = 0; - ae_int_t optypea = 2; - double beta = 0.0; - ae_int_t ic = 0; - ae_int_t jc = 0; - bool isupper = true; - real_2d_array a = "[[1,2]]"; - - // preallocate space to store result - real_2d_array c = "[[0,0],[0,0]]"; - - // calculate product, store result into upper part of c - rmatrixsyrk(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper); - - // output result. - // IMPORTANT: lower triangle of C was NOT updated! - _TestResult = _TestResult && doc_test_real_matrix(c, "[[1,2],[0,4]]", 0.0001); - } - catch(ap_error) - { _TestResult = false; } - if( !_TestResult) - { - printf("%-32s FAILED\n", "ablas_d_syrk"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST ablas_t_complex - // Basis test for complex matrix functions (correctness and presence of SMP support) - // - _TestResult = true; - try - { - complex_2d_array a; - complex_2d_array b; - complex_2d_array c; - - // test cmatrixgemm() - a = "[[2i,1i],[1,3]]"; - b = "[[2,1],[0,1]]"; - c = "[[0,0],[0,0]]"; - cmatrixgemm(2, 2, 2, 1.0, a, 0, 0, 0, b, 0, 0, 0, 0.0, c, 0, 0); - _TestResult = _TestResult && doc_test_complex_matrix(c, "[[4i,3i],[2,4]]", 0.0001); - } - catch(ap_error) - { _TestResult = false; } - if( !_TestResult) - { - printf("%-32s FAILED\n", "ablas_t_complex"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST matinv_d_r1 - // Real matrix inverse - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<7; _spoil_scenario++) - { - try - { - real_2d_array a = "[[1,-1],[1,1]]"; - if( _spoil_scenario==0 ) - spoil_matrix_by_nan(a); - if( _spoil_scenario==1 ) - spoil_matrix_by_posinf(a); - if( _spoil_scenario==2 ) - spoil_matrix_by_neginf(a); - if( _spoil_scenario==3 ) - spoil_matrix_by_adding_row(a); - if( _spoil_scenario==4 ) - spoil_matrix_by_adding_col(a); - if( _spoil_scenario==5 ) - spoil_matrix_by_deleting_row(a); - if( _spoil_scenario==6 ) - spoil_matrix_by_deleting_col(a); - ae_int_t info; - matinvreport rep; - rmatrixinverse(a, info, rep); - _TestResult = _TestResult && doc_test_int(info, 1); - _TestResult = _TestResult && doc_test_real_matrix(a, "[[0.5,0.5],[-0.5,0.5]]", 0.00005); - _TestResult = _TestResult && doc_test_real(rep.r1, 0.5, 0.00005); - _TestResult = _TestResult && doc_test_real(rep.rinf, 0.5, 0.00005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "matinv_d_r1"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST matinv_d_c1 - // Complex matrix inverse - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<7; _spoil_scenario++) - { - try - { - complex_2d_array a = "[[1i,-1],[1i,1]]"; - if( _spoil_scenario==0 ) - spoil_matrix_by_nan(a); - if( _spoil_scenario==1 ) - spoil_matrix_by_posinf(a); - if( _spoil_scenario==2 ) - spoil_matrix_by_neginf(a); - if( _spoil_scenario==3 ) - spoil_matrix_by_adding_row(a); - if( _spoil_scenario==4 ) - spoil_matrix_by_adding_col(a); - if( _spoil_scenario==5 ) - spoil_matrix_by_deleting_row(a); - if( _spoil_scenario==6 ) - spoil_matrix_by_deleting_col(a); - ae_int_t info; - matinvreport rep; - cmatrixinverse(a, info, rep); - _TestResult = _TestResult && doc_test_int(info, 1); - _TestResult = _TestResult && doc_test_complex_matrix(a, "[[-0.5i,-0.5i],[-0.5,0.5]]", 0.00005); - _TestResult = _TestResult && doc_test_real(rep.r1, 0.5, 0.00005); - _TestResult = _TestResult && doc_test_real(rep.rinf, 0.5, 0.00005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "matinv_d_c1"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST matinv_d_spd1 - // SPD matrix inverse - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<7; _spoil_scenario++) - { - try - { - real_2d_array a = "[[2,1],[1,2]]"; - if( _spoil_scenario==0 ) - spoil_matrix_by_nan(a); - if( _spoil_scenario==1 ) - spoil_matrix_by_posinf(a); - if( _spoil_scenario==2 ) - spoil_matrix_by_neginf(a); - if( _spoil_scenario==3 ) - spoil_matrix_by_adding_row(a); - if( _spoil_scenario==4 ) - spoil_matrix_by_adding_col(a); - if( _spoil_scenario==5 ) - spoil_matrix_by_deleting_row(a); - if( _spoil_scenario==6 ) - spoil_matrix_by_deleting_col(a); - ae_int_t info; - matinvreport rep; - spdmatrixinverse(a, info, rep); - _TestResult = _TestResult && doc_test_int(info, 1); - _TestResult = _TestResult && doc_test_real_matrix(a, "[[0.666666,-0.333333],[-0.333333,0.666666]]", 0.00005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "matinv_d_spd1"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST matinv_d_hpd1 - // HPD matrix inverse - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<7; _spoil_scenario++) - { - try - { - complex_2d_array a = "[[2,1],[1,2]]"; - if( _spoil_scenario==0 ) - spoil_matrix_by_nan(a); - if( _spoil_scenario==1 ) - spoil_matrix_by_posinf(a); - if( _spoil_scenario==2 ) - spoil_matrix_by_neginf(a); - if( _spoil_scenario==3 ) - spoil_matrix_by_adding_row(a); - if( _spoil_scenario==4 ) - spoil_matrix_by_adding_col(a); - if( _spoil_scenario==5 ) - spoil_matrix_by_deleting_row(a); - if( _spoil_scenario==6 ) - spoil_matrix_by_deleting_col(a); - ae_int_t info; - matinvreport rep; - hpdmatrixinverse(a, info, rep); - _TestResult = _TestResult && doc_test_int(info, 1); - _TestResult = _TestResult && doc_test_complex_matrix(a, "[[0.666666,-0.333333],[-0.333333,0.666666]]", 0.00005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "matinv_d_hpd1"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST matinv_t_r1 - // Real matrix inverse: singular matrix - // - _TestResult = true; - try - { - real_2d_array a = "[[1,-1],[-2,2]]"; - ae_int_t info; - matinvreport rep; - rmatrixinverse(a, info, rep); - _TestResult = _TestResult && doc_test_int(info, -3); - _TestResult = _TestResult && doc_test_real(rep.r1, 0.0, 0.00005); - _TestResult = _TestResult && doc_test_real(rep.rinf, 0.0, 0.00005); - } - catch(ap_error) - { _TestResult = false; } - if( !_TestResult) - { - printf("%-32s FAILED\n", "matinv_t_r1"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST matinv_t_c1 - // Complex matrix inverse: singular matrix - // - _TestResult = true; - try - { - complex_2d_array a = "[[1i,-1i],[-2,2]]"; - ae_int_t info; - matinvreport rep; - cmatrixinverse(a, info, rep); - _TestResult = _TestResult && doc_test_int(info, -3); - _TestResult = _TestResult && doc_test_real(rep.r1, 0.0, 0.00005); - _TestResult = _TestResult && doc_test_real(rep.rinf, 0.0, 0.00005); - } - catch(ap_error) - { _TestResult = false; } - if( !_TestResult) - { - printf("%-32s FAILED\n", "matinv_t_c1"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST matinv_e_spd1 - // Attempt to use SPD function on nonsymmetrix matrix - // - _TestResult = true; - try - { - real_2d_array a = "[[1,0],[1,1]]"; - ae_int_t info; - matinvreport rep; - spdmatrixinverse(a, info, rep); - _TestResult = false; - } - catch(ap_error) - {} - if( !_TestResult) - { - printf("%-32s FAILED\n", "matinv_e_spd1"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST matinv_e_hpd1 - // Attempt to use SPD function on nonsymmetrix matrix - // - _TestResult = true; - try - { - complex_2d_array a = "[[1,0],[1,1]]"; - ae_int_t info; - matinvreport rep; - hpdmatrixinverse(a, info, rep); - _TestResult = false; - } - catch(ap_error) - {} - if( !_TestResult) - { - printf("%-32s FAILED\n", "matinv_e_hpd1"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minlbfgs_d_1 - // Nonlinear optimization by L-BFGS - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<15; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of - // - // f(x,y) = 100*(x+3)^4+(y-3)^4 - // - // using LBFGS method, with: - // * initial point x=[0,0] - // * unit scale being set for all variables (see minlbfgssetscale for more info) - // * stopping criteria set to "terminate after short enough step" - // * OptGuard integrity check being used to check problem statement - // for some common errors like nonsmoothness or bad analytic gradient - // - // First, we create optimizer object and tune its properties - // - real_1d_array x = "[0,0]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(s); - double epsg = 0; - if( _spoil_scenario==6 ) - epsg = fp_nan; - if( _spoil_scenario==7 ) - epsg = fp_posinf; - if( _spoil_scenario==8 ) - epsg = fp_neginf; - double epsf = 0; - if( _spoil_scenario==9 ) - epsf = fp_nan; - if( _spoil_scenario==10 ) - epsf = fp_posinf; - if( _spoil_scenario==11 ) - epsf = fp_neginf; - double epsx = 0.0000000001; - if( _spoil_scenario==12 ) - epsx = fp_nan; - if( _spoil_scenario==13 ) - epsx = fp_posinf; - if( _spoil_scenario==14 ) - epsx = fp_neginf; - ae_int_t maxits = 0; - minlbfgsstate state; - minlbfgscreate(1, x, state); - minlbfgssetcond(state, epsg, epsf, epsx, maxits); - minlbfgssetscale(state, s); - - // - // Activate OptGuard integrity checking. - // - // OptGuard monitor helps to catch common coding and problem statement - // issues, like: - // * discontinuity of the target function (C0 continuity violation) - // * nonsmoothness of the target function (C1 continuity violation) - // * erroneous analytic gradient, i.e. one inconsistent with actual - // change in the target/constraints - // - // OptGuard is essential for early prototyping stages because such - // problems often result in premature termination of the optimizer - // which is really hard to distinguish from the correct termination. - // - // IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL - // DIFFERENTIATION. DO NOT USE IT IN PRODUCTION CODE!!!!!!! - // - // Other OptGuard checks add moderate overhead, but anyway - // it is better to turn them off when they are not needed. - // - minlbfgsoptguardsmoothness(state); - minlbfgsoptguardgradient(state, 0.001); - - // - // Optimize and examine results. - // - minlbfgsreport rep; - alglib::minlbfgsoptimize(state, function1_grad); - minlbfgsresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[-3,3]", 0.005); - - // - // Check that OptGuard did not report errors - // - // NOTE: want to test OptGuard? Try breaking the gradient - say, add - // 1.0 to some of its components. - // - optguardreport ogrep; - minlbfgsoptguardresults(state, ogrep); - _TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minlbfgs_d_1"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minlbfgs_d_2 - // Nonlinear optimization with additional settings and restarts - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<21; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of f(x,y) = 100*(x+3)^4+(y-3)^4 - // using LBFGS method. - // - // Several advanced techniques are demonstrated: - // * upper limit on step size - // * restart from new point - // - real_1d_array x = "[0,0]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(s); - double epsg = 0; - if( _spoil_scenario==6 ) - epsg = fp_nan; - if( _spoil_scenario==7 ) - epsg = fp_posinf; - if( _spoil_scenario==8 ) - epsg = fp_neginf; - double epsf = 0; - if( _spoil_scenario==9 ) - epsf = fp_nan; - if( _spoil_scenario==10 ) - epsf = fp_posinf; - if( _spoil_scenario==11 ) - epsf = fp_neginf; - double epsx = 0.0000000001; - if( _spoil_scenario==12 ) - epsx = fp_nan; - if( _spoil_scenario==13 ) - epsx = fp_posinf; - if( _spoil_scenario==14 ) - epsx = fp_neginf; - double stpmax = 0.1; - if( _spoil_scenario==15 ) - stpmax = fp_nan; - if( _spoil_scenario==16 ) - stpmax = fp_posinf; - if( _spoil_scenario==17 ) - stpmax = fp_neginf; - ae_int_t maxits = 0; - minlbfgsstate state; - minlbfgsreport rep; - - // create and tune optimizer - minlbfgscreate(1, x, state); - minlbfgssetcond(state, epsg, epsf, epsx, maxits); - minlbfgssetstpmax(state, stpmax); - minlbfgssetscale(state, s); - - // Set up OptGuard integrity checker which catches errors - // like nonsmooth targets or errors in the analytic gradient. - // - // OptGuard is essential at the early prototyping stages. - // - // NOTE: gradient verification needs 3*N additional function - // evaluations; DO NOT USE IT IN THE PRODUCTION CODE - // because it leads to unnecessary slowdown of your app. - minlbfgsoptguardsmoothness(state); - minlbfgsoptguardgradient(state, 0.001); - - // first run - alglib::minlbfgsoptimize(state, function1_grad); - minlbfgsresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[-3,3]", 0.005); - - // second run - algorithm is restarted - x = "[10,10]"; - if( _spoil_scenario==18 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==19 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==20 ) - spoil_vector_by_neginf(x); - minlbfgsrestartfrom(state, x); - alglib::minlbfgsoptimize(state, function1_grad); - minlbfgsresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[-3,3]", 0.005); - - // check OptGuard integrity report. Why do we need it at all? - // Well, try breaking the gradient by adding 1.0 to some - // of its components - OptGuard should report it as error. - // And it may also catch unintended errors too :) - optguardreport ogrep; - minlbfgsoptguardresults(state, ogrep); - _TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minlbfgs_d_2"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minlbfgs_numdiff - // Nonlinear optimization by L-BFGS with numerical differentiation - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<15; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of f(x,y) = 100*(x+3)^4+(y-3)^4 - // using numerical differentiation to calculate gradient. - // - real_1d_array x = "[0,0]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - double epsg = 0.0000000001; - if( _spoil_scenario==3 ) - epsg = fp_nan; - if( _spoil_scenario==4 ) - epsg = fp_posinf; - if( _spoil_scenario==5 ) - epsg = fp_neginf; - double epsf = 0; - if( _spoil_scenario==6 ) - epsf = fp_nan; - if( _spoil_scenario==7 ) - epsf = fp_posinf; - if( _spoil_scenario==8 ) - epsf = fp_neginf; - double epsx = 0; - if( _spoil_scenario==9 ) - epsx = fp_nan; - if( _spoil_scenario==10 ) - epsx = fp_posinf; - if( _spoil_scenario==11 ) - epsx = fp_neginf; - double diffstep = 1.0e-6; - if( _spoil_scenario==12 ) - diffstep = fp_nan; - if( _spoil_scenario==13 ) - diffstep = fp_posinf; - if( _spoil_scenario==14 ) - diffstep = fp_neginf; - ae_int_t maxits = 0; - minlbfgsstate state; - minlbfgsreport rep; - - minlbfgscreatef(1, x, diffstep, state); - minlbfgssetcond(state, epsg, epsf, epsx, maxits); - alglib::minlbfgsoptimize(state, function1_func); - minlbfgsresults(state, x, rep); - - _TestResult = _TestResult && doc_test_int(rep.terminationtype, 4); - _TestResult = _TestResult && doc_test_real_vector(x, "[-3,3]", 0.005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minlbfgs_numdiff"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST linlsqr_d_1 - // Solution of sparse linear systems with CG - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<4; _spoil_scenario++) - { - try - { - // - // This example illustrates solution of sparse linear least squares problem - // with LSQR algorithm. - // - // Suppose that we have least squares problem min|A*x-b| with sparse A - // represented by sparsematrix object - // [ 1 1 ] - // [ 1 1 ] - // A = [ 2 1 ] - // [ 1 ] - // [ 1 ] - // and right part b - // [ 4 ] - // [ 2 ] - // b = [ 4 ] - // [ 1 ] - // [ 2 ] - // and we want to solve this system in the least squares sense using - // LSQR algorithm. In order to do so, we have to create left part - // (sparsematrix object) and right part (dense array). - // - // Initially, sparse matrix is created in the Hash-Table format, - // which allows easy initialization, but do not allow matrix to be - // used in the linear solvers. So after construction you should convert - // sparse matrix to CRS format (one suited for linear operations). - // - sparsematrix a; - sparsecreate(5, 2, a); - sparseset(a, 0, 0, 1.0); - sparseset(a, 0, 1, 1.0); - sparseset(a, 1, 0, 1.0); - sparseset(a, 1, 1, 1.0); - sparseset(a, 2, 0, 2.0); - sparseset(a, 2, 1, 1.0); - sparseset(a, 3, 0, 1.0); - sparseset(a, 4, 1, 1.0); - - // - // Now our matrix is fully initialized, but we have to do one more - // step - convert it from Hash-Table format to CRS format (see - // documentation on sparse matrices for more information about these - // formats). - // - // If you omit this call, ALGLIB will generate exception on the first - // attempt to use A in linear operations. - // - sparseconverttocrs(a); - - // - // Initialization of the right part - // - real_1d_array b = "[4,2,4,1,2]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(b); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(b); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(b); - if( _spoil_scenario==3 ) - spoil_vector_by_deleting_element(b); - - // - // Now we have to create linear solver object and to use it for the - // solution of the linear system. - // - linlsqrstate s; - linlsqrreport rep; - real_1d_array x; - linlsqrcreate(5, 2, s); - linlsqrsolvesparse(s, a, b); - linlsqrresults(s, x, rep); - - _TestResult = _TestResult && doc_test_int(rep.terminationtype, 4); - _TestResult = _TestResult && doc_test_real_vector(x, "[1.000,2.000]", 0.005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "linlsqr_d_1"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minbleic_d_1 - // Nonlinear optimization with bound constraints - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<20; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of - // - // f(x,y) = 100*(x+3)^4+(y-3)^4 - // - // subject to box constraints - // - // -1<=x<=+1, -1<=y<=+1 - // - // using BLEIC optimizer with: - // * initial point x=[0,0] - // * unit scale being set for all variables (see minbleicsetscale for more info) - // * stopping criteria set to "terminate after short enough step" - // * OptGuard integrity check being used to check problem statement - // for some common errors like nonsmoothness or bad analytic gradient - // - // First, we create optimizer object and tune its properties: - // * set box constraints - // * set variable scales - // * set stopping criteria - // - real_1d_array x = "[0,0]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(s); - if( _spoil_scenario==6 ) - spoil_vector_by_deleting_element(s); - real_1d_array bndl = "[-1,-1]"; - if( _spoil_scenario==7 ) - spoil_vector_by_nan(bndl); - if( _spoil_scenario==8 ) - spoil_vector_by_deleting_element(bndl); - real_1d_array bndu = "[+1,+1]"; - if( _spoil_scenario==9 ) - spoil_vector_by_nan(bndu); - if( _spoil_scenario==10 ) - spoil_vector_by_deleting_element(bndu); - double epsg = 0; - if( _spoil_scenario==11 ) - epsg = fp_nan; - if( _spoil_scenario==12 ) - epsg = fp_posinf; - if( _spoil_scenario==13 ) - epsg = fp_neginf; - double epsf = 0; - if( _spoil_scenario==14 ) - epsf = fp_nan; - if( _spoil_scenario==15 ) - epsf = fp_posinf; - if( _spoil_scenario==16 ) - epsf = fp_neginf; - double epsx = 0.000001; - if( _spoil_scenario==17 ) - epsx = fp_nan; - if( _spoil_scenario==18 ) - epsx = fp_posinf; - if( _spoil_scenario==19 ) - epsx = fp_neginf; - ae_int_t maxits = 0; - minbleicstate state; - minbleiccreate(x, state); - minbleicsetbc(state, bndl, bndu); - minbleicsetscale(state, s); - minbleicsetcond(state, epsg, epsf, epsx, maxits); - - // - // Then we activate OptGuard integrity checking. - // - // OptGuard monitor helps to catch common coding and problem statement - // issues, like: - // * discontinuity of the target function (C0 continuity violation) - // * nonsmoothness of the target function (C1 continuity violation) - // * erroneous analytic gradient, i.e. one inconsistent with actual - // change in the target/constraints - // - // OptGuard is essential for early prototyping stages because such - // problems often result in premature termination of the optimizer - // which is really hard to distinguish from the correct termination. - // - // IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL - // DIFFERENTIATION. DO NOT USE IT IN PRODUCTION CODE!!!!!!! - // - // Other OptGuard checks add moderate overhead, but anyway - // it is better to turn them off when they are not needed. - // - minbleicoptguardsmoothness(state); - minbleicoptguardgradient(state, 0.001); - - // - // Optimize and evaluate results - // - minbleicreport rep; - alglib::minbleicoptimize(state, function1_grad); - minbleicresults(state, x, rep); - _TestResult = _TestResult && doc_test_int(rep.terminationtype, 4); - _TestResult = _TestResult && doc_test_real_vector(x, "[-1,1]", 0.005); - - // - // Check that OptGuard did not report errors - // - // NOTE: want to test OptGuard? Try breaking the gradient - say, add - // 1.0 to some of its components. - // - optguardreport ogrep; - minbleicoptguardresults(state, ogrep); - _TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minbleic_d_1"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minbleic_d_2 - // Nonlinear optimization with linear inequality constraints - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<22; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of - // - // f(x,y) = 100*(x+3)^4+(y-3)^4 - // - // subject to inequality constraints - // - // * x>=2 (posed as general linear constraint), - // * x+y>=6 - // - // using BLEIC optimizer with - // * initial point x=[0,0] - // * unit scale being set for all variables (see minbleicsetscale for more info) - // * stopping criteria set to "terminate after short enough step" - // * OptGuard integrity check being used to check problem statement - // for some common errors like nonsmoothness or bad analytic gradient - // - // First, we create optimizer object and tune its properties: - // * set linear constraints - // * set variable scales - // * set stopping criteria - // - real_1d_array x = "[5,5]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(s); - if( _spoil_scenario==6 ) - spoil_vector_by_deleting_element(s); - real_2d_array c = "[[1,0,2],[1,1,6]]"; - if( _spoil_scenario==7 ) - spoil_matrix_by_nan(c); - if( _spoil_scenario==8 ) - spoil_matrix_by_posinf(c); - if( _spoil_scenario==9 ) - spoil_matrix_by_neginf(c); - if( _spoil_scenario==10 ) - spoil_matrix_by_deleting_row(c); - if( _spoil_scenario==11 ) - spoil_matrix_by_deleting_col(c); - integer_1d_array ct = "[1,1]"; - if( _spoil_scenario==12 ) - spoil_vector_by_deleting_element(ct); - minbleicstate state; - double epsg = 0; - if( _spoil_scenario==13 ) - epsg = fp_nan; - if( _spoil_scenario==14 ) - epsg = fp_posinf; - if( _spoil_scenario==15 ) - epsg = fp_neginf; - double epsf = 0; - if( _spoil_scenario==16 ) - epsf = fp_nan; - if( _spoil_scenario==17 ) - epsf = fp_posinf; - if( _spoil_scenario==18 ) - epsf = fp_neginf; - double epsx = 0.000001; - if( _spoil_scenario==19 ) - epsx = fp_nan; - if( _spoil_scenario==20 ) - epsx = fp_posinf; - if( _spoil_scenario==21 ) - epsx = fp_neginf; - ae_int_t maxits = 0; - - minbleiccreate(x, state); - minbleicsetlc(state, c, ct); - minbleicsetscale(state, s); - minbleicsetcond(state, epsg, epsf, epsx, maxits); - - // - // Then we activate OptGuard integrity checking. - // - // OptGuard monitor helps to catch common coding and problem statement - // issues, like: - // * discontinuity of the target function (C0 continuity violation) - // * nonsmoothness of the target function (C1 continuity violation) - // * erroneous analytic gradient, i.e. one inconsistent with actual - // change in the target/constraints - // - // OptGuard is essential for early prototyping stages because such - // problems often result in premature termination of the optimizer - // which is really hard to distinguish from the correct termination. - // - // IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL - // DIFFERENTIATION. DO NOT USE IT IN PRODUCTION CODE!!!!!!! - // - // Other OptGuard checks add moderate overhead, but anyway - // it is better to turn them off when they are not needed. - // - minbleicoptguardsmoothness(state); - minbleicoptguardgradient(state, 0.001); - - // - // Optimize and evaluate results - // - minbleicreport rep; - alglib::minbleicoptimize(state, function1_grad); - minbleicresults(state, x, rep); - _TestResult = _TestResult && doc_test_int(rep.terminationtype, 4); - _TestResult = _TestResult && doc_test_real_vector(x, "[2,4]", 0.005); - - // - // Check that OptGuard did not report errors - // - // NOTE: want to test OptGuard? Try breaking the gradient - say, add - // 1.0 to some of its components. - // - optguardreport ogrep; - minbleicoptguardresults(state, ogrep); - _TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minbleic_d_2"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minbleic_numdiff - // Nonlinear optimization with bound constraints and numerical differentiation - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<23; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of - // - // f(x,y) = 100*(x+3)^4+(y-3)^4 - // - // subject to box constraints - // - // -1<=x<=+1, -1<=y<=+1 - // - // using BLEIC optimizer with: - // * numerical differentiation being used - // * initial point x=[0,0] - // * unit scale being set for all variables (see minbleicsetscale for more info) - // * stopping criteria set to "terminate after short enough step" - // * OptGuard integrity check being used to check problem statement - // for some common errors like nonsmoothness or bad analytic gradient - // - // First, we create optimizer object and tune its properties: - // * set box constraints - // * set variable scales - // * set stopping criteria - // - real_1d_array x = "[0,0]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(s); - if( _spoil_scenario==6 ) - spoil_vector_by_deleting_element(s); - real_1d_array bndl = "[-1,-1]"; - if( _spoil_scenario==7 ) - spoil_vector_by_nan(bndl); - if( _spoil_scenario==8 ) - spoil_vector_by_deleting_element(bndl); - real_1d_array bndu = "[+1,+1]"; - if( _spoil_scenario==9 ) - spoil_vector_by_nan(bndu); - if( _spoil_scenario==10 ) - spoil_vector_by_deleting_element(bndu); - minbleicstate state; - double epsg = 0; - if( _spoil_scenario==11 ) - epsg = fp_nan; - if( _spoil_scenario==12 ) - epsg = fp_posinf; - if( _spoil_scenario==13 ) - epsg = fp_neginf; - double epsf = 0; - if( _spoil_scenario==14 ) - epsf = fp_nan; - if( _spoil_scenario==15 ) - epsf = fp_posinf; - if( _spoil_scenario==16 ) - epsf = fp_neginf; - double epsx = 0.000001; - if( _spoil_scenario==17 ) - epsx = fp_nan; - if( _spoil_scenario==18 ) - epsx = fp_posinf; - if( _spoil_scenario==19 ) - epsx = fp_neginf; - ae_int_t maxits = 0; - double diffstep = 1.0e-6; - if( _spoil_scenario==20 ) - diffstep = fp_nan; - if( _spoil_scenario==21 ) - diffstep = fp_posinf; - if( _spoil_scenario==22 ) - diffstep = fp_neginf; - - minbleiccreatef(x, diffstep, state); - minbleicsetbc(state, bndl, bndu); - minbleicsetscale(state, s); - minbleicsetcond(state, epsg, epsf, epsx, maxits); - - // - // Then we activate OptGuard integrity checking. - // - // Numerical differentiation always produces "correct" gradient - // (with some truncation error, but unbiased). Thus, we just have - // to check smoothness properties of the target: C0 and C1 continuity. - // - // Sometimes user accidentally tries to solve nonsmooth problems - // with smooth optimizer. OptGuard helps to detect such situations - // early, at the prototyping stage. - // - minbleicoptguardsmoothness(state); - - // - // Optimize and evaluate results - // - minbleicreport rep; - alglib::minbleicoptimize(state, function1_func); - minbleicresults(state, x, rep); - _TestResult = _TestResult && doc_test_int(rep.terminationtype, 4); - _TestResult = _TestResult && doc_test_real_vector(x, "[-1,1]", 0.005); - - // - // Check that OptGuard did not report errors - // - // Want to challenge OptGuard? Try to make your problem - // nonsmooth by replacing 100*(x+3)^4 by 100*|x+3| and - // re-run optimizer. - // - optguardreport ogrep; - minbleicoptguardresults(state, ogrep); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minbleic_numdiff"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minqp_d_u1 - // Unconstrained dense quadratic programming - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<17; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of F(x0,x1) = x0^2 + x1^2 -6*x0 - 4*x1 - // - // Exact solution is [x0,x1] = [3,2] - // - // We provide algorithm with starting point, although in this case - // (dense matrix, no constraints) it can work without such information. - // - // Several QP solvers are tried: QuickQP, BLEIC, DENSE-AUL. - // - // IMPORTANT: this solver minimizes following function: - // f(x) = 0.5*x'*A*x + b'*x. - // Note that quadratic term has 0.5 before it. So if you want to minimize - // quadratic function, you should rewrite it in such way that quadratic term - // is multiplied by 0.5 too. - // - // For example, our function is f(x)=x0^2+x1^2+..., but we rewrite it as - // f(x) = 0.5*(2*x0^2+2*x1^2) + .... - // and pass diag(2,2) as quadratic term - NOT diag(1,1)! - // - real_2d_array a = "[[2,0],[0,2]]"; - if( _spoil_scenario==0 ) - spoil_matrix_by_nan(a); - if( _spoil_scenario==1 ) - spoil_matrix_by_posinf(a); - if( _spoil_scenario==2 ) - spoil_matrix_by_neginf(a); - if( _spoil_scenario==3 ) - spoil_matrix_by_deleting_row(a); - if( _spoil_scenario==4 ) - spoil_matrix_by_deleting_col(a); - real_1d_array b = "[-6,-4]"; - if( _spoil_scenario==5 ) - spoil_vector_by_nan(b); - if( _spoil_scenario==6 ) - spoil_vector_by_posinf(b); - if( _spoil_scenario==7 ) - spoil_vector_by_neginf(b); - if( _spoil_scenario==8 ) - spoil_vector_by_deleting_element(b); - real_1d_array x0 = "[0,1]"; - if( _spoil_scenario==9 ) - spoil_vector_by_nan(x0); - if( _spoil_scenario==10 ) - spoil_vector_by_posinf(x0); - if( _spoil_scenario==11 ) - spoil_vector_by_neginf(x0); - if( _spoil_scenario==12 ) - spoil_vector_by_deleting_element(x0); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==13 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==14 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==15 ) - spoil_vector_by_neginf(s); - if( _spoil_scenario==16 ) - spoil_vector_by_deleting_element(s); - real_1d_array x; - minqpstate state; - minqpreport rep; - - // create solver, set quadratic/linear terms - minqpcreate(2, state); - minqpsetquadraticterm(state, a); - minqpsetlinearterm(state, b); - minqpsetstartingpoint(state, x0); - - // Set scale of the parameters. - // It is strongly recommended that you set scale of your variables. - // Knowing their scales is essential for evaluation of stopping criteria - // and for preconditioning of the algorithm steps. - // You can find more information on scaling at http://www.alglib.net/optimization/scaling.php - // - // NOTE: for convex problems you may try using minqpsetscaleautodiag() - // which automatically determines variable scales. - minqpsetscale(state, s); - - // - // Solve problem with QuickQP solver. - // - // This solver is intended for medium and large-scale problems with box - // constraints (general linear constraints are not supported), but it can - // also be efficiently used on unconstrained problems. - // - // Default stopping criteria are used, Newton phase is active. - // - minqpsetalgoquickqp(state, 0.0, 0.0, 0.0, 0, true); - minqpoptimize(state); - minqpresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[3,2]", 0.005); - - // - // Solve problem with BLEIC-based QP solver. - // - // This solver is intended for problems with moderate (up to 50) number - // of general linear constraints and unlimited number of box constraints. - // Of course, unconstrained problems can be solved too. - // - // Default stopping criteria are used. - // - minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0); - minqpoptimize(state); - minqpresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[3,2]", 0.005); - - // - // Solve problem with DENSE-AUL solver. - // - // This solver is optimized for problems with up to several thousands of - // variables and large amount of general linear constraints. Problems with - // less than 50 general linear constraints can be efficiently solved with - // BLEIC, problems with box-only constraints can be solved with QuickQP. - // However, DENSE-AUL will work in any (including unconstrained) case. - // - // Default stopping criteria are used. - // - minqpsetalgodenseaul(state, 1.0e-9, 1.0e+4, 5); - minqpoptimize(state); - minqpresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[3,2]", 0.005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minqp_d_u1"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minqp_d_bc1 - // Bound constrained dense quadratic programming - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<21; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of F(x0,x1) = x0^2 + x1^2 -6*x0 - 4*x1 - // subject to bound constraints 0<=x0<=2.5, 0<=x1<=2.5 - // - // Exact solution is [x0,x1] = [2.5,2] - // - // We provide algorithm with starting point. With such small problem good starting - // point is not really necessary, but with high-dimensional problem it can save us - // a lot of time. - // - // Several QP solvers are tried: QuickQP, BLEIC, DENSE-AUL. - // - // IMPORTANT: this solver minimizes following function: - // f(x) = 0.5*x'*A*x + b'*x. - // Note that quadratic term has 0.5 before it. So if you want to minimize - // quadratic function, you should rewrite it in such way that quadratic term - // is multiplied by 0.5 too. - // For example, our function is f(x)=x0^2+x1^2+..., but we rewrite it as - // f(x) = 0.5*(2*x0^2+2*x1^2) + .... - // and pass diag(2,2) as quadratic term - NOT diag(1,1)! - // - real_2d_array a = "[[2,0],[0,2]]"; - if( _spoil_scenario==0 ) - spoil_matrix_by_nan(a); - if( _spoil_scenario==1 ) - spoil_matrix_by_posinf(a); - if( _spoil_scenario==2 ) - spoil_matrix_by_neginf(a); - if( _spoil_scenario==3 ) - spoil_matrix_by_deleting_row(a); - if( _spoil_scenario==4 ) - spoil_matrix_by_deleting_col(a); - real_1d_array b = "[-6,-4]"; - if( _spoil_scenario==5 ) - spoil_vector_by_nan(b); - if( _spoil_scenario==6 ) - spoil_vector_by_posinf(b); - if( _spoil_scenario==7 ) - spoil_vector_by_neginf(b); - if( _spoil_scenario==8 ) - spoil_vector_by_deleting_element(b); - real_1d_array x0 = "[0,1]"; - if( _spoil_scenario==9 ) - spoil_vector_by_nan(x0); - if( _spoil_scenario==10 ) - spoil_vector_by_posinf(x0); - if( _spoil_scenario==11 ) - spoil_vector_by_neginf(x0); - if( _spoil_scenario==12 ) - spoil_vector_by_deleting_element(x0); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==13 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==14 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==15 ) - spoil_vector_by_neginf(s); - if( _spoil_scenario==16 ) - spoil_vector_by_deleting_element(s); - real_1d_array bndl = "[0.0,0.0]"; - if( _spoil_scenario==17 ) - spoil_vector_by_nan(bndl); - if( _spoil_scenario==18 ) - spoil_vector_by_deleting_element(bndl); - real_1d_array bndu = "[2.5,2.5]"; - if( _spoil_scenario==19 ) - spoil_vector_by_nan(bndu); - if( _spoil_scenario==20 ) - spoil_vector_by_deleting_element(bndu); - real_1d_array x; - minqpstate state; - minqpreport rep; - - // create solver, set quadratic/linear terms - minqpcreate(2, state); - minqpsetquadraticterm(state, a); - minqpsetlinearterm(state, b); - minqpsetstartingpoint(state, x0); - minqpsetbc(state, bndl, bndu); - - // Set scale of the parameters. - // It is strongly recommended that you set scale of your variables. - // Knowing their scales is essential for evaluation of stopping criteria - // and for preconditioning of the algorithm steps. - // You can find more information on scaling at http://www.alglib.net/optimization/scaling.php - // - // NOTE: for convex problems you may try using minqpsetscaleautodiag() - // which automatically determines variable scales. - minqpsetscale(state, s); - - // - // Solve problem with QuickQP solver. - // - // This solver is intended for medium and large-scale problems with box - // constraints (general linear constraints are not supported). - // - // Default stopping criteria are used, Newton phase is active. - // - minqpsetalgoquickqp(state, 0.0, 0.0, 0.0, 0, true); - minqpoptimize(state); - minqpresults(state, x, rep); - _TestResult = _TestResult && doc_test_int(rep.terminationtype, 4); - _TestResult = _TestResult && doc_test_real_vector(x, "[2.5,2]", 0.005); - - // - // Solve problem with BLEIC-based QP solver. - // - // This solver is intended for problems with moderate (up to 50) number - // of general linear constraints and unlimited number of box constraints. - // - // Default stopping criteria are used. - // - minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0); - minqpoptimize(state); - minqpresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[2.5,2]", 0.005); - - // - // Solve problem with DENSE-AUL solver. - // - // This solver is optimized for problems with up to several thousands of - // variables and large amount of general linear constraints. Problems with - // less than 50 general linear constraints can be efficiently solved with - // BLEIC, problems with box-only constraints can be solved with QuickQP. - // However, DENSE-AUL will work in any (including unconstrained) case. - // - // Default stopping criteria are used. - // - minqpsetalgodenseaul(state, 1.0e-9, 1.0e+4, 5); - minqpoptimize(state); - minqpresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[2.5,2]", 0.005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minqp_d_bc1"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minqp_d_lc1 - // Linearly constrained dense quadratic programming - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<16; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of F(x0,x1) = x0^2 + x1^2 -6*x0 - 4*x1 - // subject to linear constraint x0+x1<=2 - // - // Exact solution is [x0,x1] = [1.5,0.5] - // - // IMPORTANT: this solver minimizes following function: - // f(x) = 0.5*x'*A*x + b'*x. - // Note that quadratic term has 0.5 before it. So if you want to minimize - // quadratic function, you should rewrite it in such way that quadratic term - // is multiplied by 0.5 too. - // For example, our function is f(x)=x0^2+x1^2+..., but we rewrite it as - // f(x) = 0.5*(2*x0^2+2*x1^2) + .... - // and pass diag(2,2) as quadratic term - NOT diag(1,1)! - // - real_2d_array a = "[[2,0],[0,2]]"; - if( _spoil_scenario==0 ) - spoil_matrix_by_nan(a); - if( _spoil_scenario==1 ) - spoil_matrix_by_posinf(a); - if( _spoil_scenario==2 ) - spoil_matrix_by_neginf(a); - if( _spoil_scenario==3 ) - spoil_matrix_by_deleting_row(a); - if( _spoil_scenario==4 ) - spoil_matrix_by_deleting_col(a); - real_1d_array b = "[-6,-4]"; - if( _spoil_scenario==5 ) - spoil_vector_by_nan(b); - if( _spoil_scenario==6 ) - spoil_vector_by_posinf(b); - if( _spoil_scenario==7 ) - spoil_vector_by_neginf(b); - if( _spoil_scenario==8 ) - spoil_vector_by_deleting_element(b); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==9 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==10 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==11 ) - spoil_vector_by_neginf(s); - if( _spoil_scenario==12 ) - spoil_vector_by_deleting_element(s); - real_2d_array c = "[[1.0,1.0,2.0]]"; - if( _spoil_scenario==13 ) - spoil_matrix_by_nan(c); - if( _spoil_scenario==14 ) - spoil_matrix_by_posinf(c); - if( _spoil_scenario==15 ) - spoil_matrix_by_neginf(c); - integer_1d_array ct = "[-1]"; - real_1d_array x; - minqpstate state; - minqpreport rep; - - // create solver, set quadratic/linear terms - minqpcreate(2, state); - minqpsetquadraticterm(state, a); - minqpsetlinearterm(state, b); - minqpsetlc(state, c, ct); - - // Set scale of the parameters. - // It is strongly recommended that you set scale of your variables. - // Knowing their scales is essential for evaluation of stopping criteria - // and for preconditioning of the algorithm steps. - // You can find more information on scaling at http://www.alglib.net/optimization/scaling.php - // - // NOTE: for convex problems you may try using minqpsetscaleautodiag() - // which automatically determines variable scales. - minqpsetscale(state, s); - - // - // Solve problem with BLEIC-based QP solver. - // - // This solver is intended for problems with moderate (up to 50) number - // of general linear constraints and unlimited number of box constraints. - // - // Default stopping criteria are used. - // - minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0); - minqpoptimize(state); - minqpresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[1.500,0.500]", 0.05); - - // - // Solve problem with DENSE-AUL solver. - // - // This solver is optimized for problems with up to several thousands of - // variables and large amount of general linear constraints. Problems with - // less than 50 general linear constraints can be efficiently solved with - // BLEIC, problems with box-only constraints can be solved with QuickQP. - // However, DENSE-AUL will work in any (including unconstrained) case. - // - // Default stopping criteria are used. - // - minqpsetalgodenseaul(state, 1.0e-9, 1.0e+4, 5); - minqpoptimize(state); - minqpresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[1.500,0.500]", 0.05); - - // - // Solve problem with QuickQP solver. - // - // This solver is intended for medium and large-scale problems with box - // constraints, and... - // - // ...Oops! It does not support general linear constraints, -5 returned as completion code! - // - minqpsetalgoquickqp(state, 0.0, 0.0, 0.0, 0, true); - minqpoptimize(state); - minqpresults(state, x, rep); - _TestResult = _TestResult && doc_test_int(rep.terminationtype, -5); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minqp_d_lc1"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minqp_d_u2 - // Unconstrained sparse quadratic programming - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<12; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of F(x0,x1) = x0^2 + x1^2 -6*x0 - 4*x1, - // with quadratic term given by sparse matrix structure. - // - // Exact solution is [x0,x1] = [3,2] - // - // We provide algorithm with starting point, although in this case - // (dense matrix, no constraints) it can work without such information. - // - // IMPORTANT: this solver minimizes following function: - // f(x) = 0.5*x'*A*x + b'*x. - // Note that quadratic term has 0.5 before it. So if you want to minimize - // quadratic function, you should rewrite it in such way that quadratic term - // is multiplied by 0.5 too. - // - // For example, our function is f(x)=x0^2+x1^2+..., but we rewrite it as - // f(x) = 0.5*(2*x0^2+2*x1^2) + .... - // and pass diag(2,2) as quadratic term - NOT diag(1,1)! - // - sparsematrix a; - real_1d_array b = "[-6,-4]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(b); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(b); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(b); - if( _spoil_scenario==3 ) - spoil_vector_by_deleting_element(b); - real_1d_array x0 = "[0,1]"; - if( _spoil_scenario==4 ) - spoil_vector_by_nan(x0); - if( _spoil_scenario==5 ) - spoil_vector_by_posinf(x0); - if( _spoil_scenario==6 ) - spoil_vector_by_neginf(x0); - if( _spoil_scenario==7 ) - spoil_vector_by_deleting_element(x0); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==8 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==9 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==10 ) - spoil_vector_by_neginf(s); - if( _spoil_scenario==11 ) - spoil_vector_by_deleting_element(s); - real_1d_array x; - minqpstate state; - minqpreport rep; - - // initialize sparsematrix structure - sparsecreate(2, 2, 0, a); - sparseset(a, 0, 0, 2.0); - sparseset(a, 1, 1, 2.0); - - // create solver, set quadratic/linear terms - minqpcreate(2, state); - minqpsetquadratictermsparse(state, a, true); - minqpsetlinearterm(state, b); - minqpsetstartingpoint(state, x0); - - // Set scale of the parameters. - // It is strongly recommended that you set scale of your variables. - // Knowing their scales is essential for evaluation of stopping criteria - // and for preconditioning of the algorithm steps. - // You can find more information on scaling at http://www.alglib.net/optimization/scaling.php - // - // NOTE: for convex problems you may try using minqpsetscaleautodiag() - // which automatically determines variable scales. - minqpsetscale(state, s); - - // - // Solve problem with BLEIC-based QP solver. - // - // This solver is intended for problems with moderate (up to 50) number - // of general linear constraints and unlimited number of box constraints. - // It also supports sparse problems. - // - // Default stopping criteria are used. - // - minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0); - minqpoptimize(state); - minqpresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[3,2]", 0.005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minqp_d_u2"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minqp_d_nonconvex - // Nonconvex quadratic programming - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<21; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of nonconvex function - // F(x0,x1) = -(x0^2+x1^2) - // subject to constraints x0,x1 in [1.0,2.0] - // Exact solution is [x0,x1] = [2,2]. - // - // Non-convex problems are harded to solve than convex ones, and they - // may have more than one local minimum. However, ALGLIB solves may deal - // with such problems (altough they do not guarantee convergence to - // global minimum). - // - // IMPORTANT: this solver minimizes following function: - // f(x) = 0.5*x'*A*x + b'*x. - // Note that quadratic term has 0.5 before it. So if you want to minimize - // quadratic function, you should rewrite it in such way that quadratic term - // is multiplied by 0.5 too. - // - // For example, our function is f(x)=-(x0^2+x1^2), but we rewrite it as - // f(x) = 0.5*(-2*x0^2-2*x1^2) - // and pass diag(-2,-2) as quadratic term - NOT diag(-1,-1)! - // - real_2d_array a = "[[-2,0],[0,-2]]"; - if( _spoil_scenario==0 ) - spoil_matrix_by_nan(a); - if( _spoil_scenario==1 ) - spoil_matrix_by_posinf(a); - if( _spoil_scenario==2 ) - spoil_matrix_by_neginf(a); - if( _spoil_scenario==3 ) - spoil_matrix_by_deleting_row(a); - if( _spoil_scenario==4 ) - spoil_matrix_by_deleting_col(a); - real_1d_array x0 = "[1,1]"; - if( _spoil_scenario==5 ) - spoil_vector_by_nan(x0); - if( _spoil_scenario==6 ) - spoil_vector_by_posinf(x0); - if( _spoil_scenario==7 ) - spoil_vector_by_neginf(x0); - if( _spoil_scenario==8 ) - spoil_vector_by_deleting_element(x0); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==9 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==10 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==11 ) - spoil_vector_by_neginf(s); - if( _spoil_scenario==12 ) - spoil_vector_by_deleting_element(s); - real_1d_array bndl = "[1.0,1.0]"; - if( _spoil_scenario==13 ) - spoil_vector_by_nan(bndl); - if( _spoil_scenario==14 ) - spoil_vector_by_deleting_element(bndl); - real_1d_array bndu = "[2.0,2.0]"; - if( _spoil_scenario==15 ) - spoil_vector_by_nan(bndu); - if( _spoil_scenario==16 ) - spoil_vector_by_deleting_element(bndu); - real_1d_array x; - minqpstate state; - minqpreport rep; - - // create solver, set quadratic/linear terms, constraints - minqpcreate(2, state); - minqpsetquadraticterm(state, a); - minqpsetstartingpoint(state, x0); - minqpsetbc(state, bndl, bndu); - - // Set scale of the parameters. - // It is strongly recommended that you set scale of your variables. - // Knowing their scales is essential for evaluation of stopping criteria - // and for preconditioning of the algorithm steps. - // You can find more information on scaling at http://www.alglib.net/optimization/scaling.php - // - // NOTE: there also exists minqpsetscaleautodiag() function - // which automatically determines variable scales; however, - // it does NOT work for non-convex problems. - minqpsetscale(state, s); - - // - // Solve problem with BLEIC-based QP solver. - // - // This solver is intended for problems with moderate (up to 50) number - // of general linear constraints and unlimited number of box constraints. - // - // It may solve non-convex problems as long as they are bounded from - // below under constraints. - // - // Default stopping criteria are used. - // - minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0); - minqpoptimize(state); - minqpresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[2,2]", 0.005); - - // - // Solve problem with DENSE-AUL solver. - // - // This solver is optimized for problems with up to several thousands of - // variables and large amount of general linear constraints. Problems with - // less than 50 general linear constraints can be efficiently solved with - // BLEIC, problems with box-only constraints can be solved with QuickQP. - // However, DENSE-AUL will work in any (including unconstrained) case. - // - // Algorithm convergence is guaranteed only for convex case, but you may - // expect that it will work for non-convex problems too (because near the - // solution they are locally convex). - // - // Default stopping criteria are used. - // - minqpsetalgodenseaul(state, 1.0e-9, 1.0e+4, 5); - minqpoptimize(state); - minqpresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[2,2]", 0.005); - - // Hmm... this problem is bounded from below (has solution) only under constraints. - // What it we remove them? - // - // You may see that BLEIC algorithm detects unboundedness of the problem, - // -4 is returned as completion code. However, DENSE-AUL is unable to detect - // such situation and it will cycle forever (we do not test it here). - real_1d_array nobndl = "[-inf,-inf]"; - if( _spoil_scenario==17 ) - spoil_vector_by_nan(nobndl); - if( _spoil_scenario==18 ) - spoil_vector_by_deleting_element(nobndl); - real_1d_array nobndu = "[+inf,+inf]"; - if( _spoil_scenario==19 ) - spoil_vector_by_nan(nobndu); - if( _spoil_scenario==20 ) - spoil_vector_by_deleting_element(nobndu); - minqpsetbc(state, nobndl, nobndu); - minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0); - minqpoptimize(state); - minqpresults(state, x, rep); - _TestResult = _TestResult && doc_test_int(rep.terminationtype, -4); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minqp_d_nonconvex"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minlp_basic - // Basic linear programming example - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<15; _spoil_scenario++) - { - try - { - // - // This example demonstrates how to minimize - // - // F(x0,x1) = -0.1*x0 - x1 - // - // subject to box constraints - // - // -1 <= x0,x1 <= +1 - // - // and general linear constraints - // - // x0 - x1 >= -1 - // x0 + x1 <= 1 - // - // We use dual simplex solver provided by ALGLIB for this task. Box - // constraints are specified by means of constraint vectors bndl and - // bndu (we have bndl<=x<=bndu). General linear constraints are - // specified as AL<=A*x<=AU, with AL/AU being 2x1 vectors and A being - // 2x2 matrix. - // - // NOTE: some/all components of AL/AU can be +-INF, same applies to - // bndl/bndu. You can also have AL[I]=AU[i] (as well as - // BndL[i]=BndU[i]). - // - real_2d_array a = "[[1,-1],[1,+1]]"; - if( _spoil_scenario==0 ) - spoil_matrix_by_nan(a); - if( _spoil_scenario==1 ) - spoil_matrix_by_deleting_row(a); - if( _spoil_scenario==2 ) - spoil_matrix_by_deleting_col(a); - real_1d_array al = "[-1,-inf]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(al); - if( _spoil_scenario==4 ) - spoil_vector_by_deleting_element(al); - real_1d_array au = "[+inf,+1]"; - if( _spoil_scenario==5 ) - spoil_vector_by_nan(au); - if( _spoil_scenario==6 ) - spoil_vector_by_deleting_element(au); - real_1d_array c = "[-0.1,-1]"; - if( _spoil_scenario==7 ) - spoil_vector_by_nan(c); - if( _spoil_scenario==8 ) - spoil_vector_by_deleting_element(c); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==9 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==10 ) - spoil_vector_by_deleting_element(s); - real_1d_array bndl = "[-1,-1]"; - if( _spoil_scenario==11 ) - spoil_vector_by_nan(bndl); - if( _spoil_scenario==12 ) - spoil_vector_by_deleting_element(bndl); - real_1d_array bndu = "[+1,+1]"; - if( _spoil_scenario==13 ) - spoil_vector_by_nan(bndu); - if( _spoil_scenario==14 ) - spoil_vector_by_deleting_element(bndu); - real_1d_array x; - minlpstate state; - minlpreport rep; - - minlpcreate(2, state); - - // - // Set cost vector, box constraints, general linear constraints. - // - // Box constraints can be set in one call to minlpsetbc() or minlpsetbcall() - // (latter sets same constraints for all variables and accepts two scalars - // instead of two vectors). - // - // General linear constraints can be specified in several ways: - // * minlpsetlc2dense() - accepts dense 2D array as input; sometimes this - // approach is more convenient, although less memory-efficient. - // * minlpsetlc2() - accepts sparse matrix as input - // * minlpaddlc2dense() - appends one row to the current set of constraints; - // row being appended is specified as dense vector - // * minlpaddlc2() - appends one row to the current set of constraints; - // row being appended is specified as sparse set of elements - // Independently from specific function being used, LP solver uses sparse - // storage format for internal representation of constraints. - // - minlpsetcost(state, c); - minlpsetbc(state, bndl, bndu); - minlpsetlc2dense(state, a, al, au, 2); - - // - // Set scale of the parameters. - // - // It is strongly recommended that you set scale of your variables. - // Knowing their scales is essential for evaluation of stopping criteria - // and for preconditioning of the algorithm steps. - // You can find more information on scaling at http://www.alglib.net/optimization/scaling.php - // - minlpsetscale(state, s); - - // Solve - minlpoptimize(state); - minlpresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[0,1]", 0.0005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minlp_basic"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minnlc_d_inequality - // Nonlinearly constrained optimization (inequality constraints) - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<9; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of - // - // f(x0,x1) = -x0+x1 - // - // subject to box constraints - // - // x0>=0, x1>=0 - // - // and nonlinear inequality constraint - // - // x0^2 + x1^2 - 1 <= 0 - // - real_1d_array x0 = "[0,0]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x0); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x0); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x0); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(s); - double epsx = 0.000001; - if( _spoil_scenario==6 ) - epsx = fp_nan; - if( _spoil_scenario==7 ) - epsx = fp_posinf; - if( _spoil_scenario==8 ) - epsx = fp_neginf; - ae_int_t maxits = 0; - real_1d_array bndl = "[0,0]"; - real_1d_array bndu = "[+inf,+inf]"; - minnlcstate state; - - // - // Create optimizer object and tune its settings: - // * epsx=0.000001 stopping condition for inner iterations - // * s=[1,1] all variables have unit scale; it is important to - // tell optimizer about scales of your variables - it - // greatly accelerates convergence and helps to perform - // some important integrity checks. - // - minnlccreate(2, x0, state); - minnlcsetcond(state, epsx, maxits); - minnlcsetscale(state, s); - - // - // Choose one of the nonlinear programming solvers supported by minnlc - // optimizer: - // * SQP - sequential quadratic programming NLP solver - // * AUL - augmented Lagrangian NLP solver - // * SLP - successive linear programming NLP solver - // - // Different solvers have different properties: - // * SQP needs less function evaluations than any other solver, but it - // has much higher iteration cost than other solvers (a QP subproblem - // has to be solved during each step) - // * AUL solver has cheaper iterations, but needs more target function - // evaluations - // * SLP is the most robust solver provided by ALGLIB, but it performs - // order of magnitude more iterations than SQP. - // - // In the code below we set solver to be AUL but then override it with SLP, - // and then with SQP, so the effective choice is to use SLP. We recommend - // you to use SQP at least for early prototyping stages, and then switch - // to AUL if possible. - // - double rho = 1000.0; - ae_int_t outerits = 5; - minnlcsetalgoaul(state, rho, outerits); - minnlcsetalgoslp(state); - minnlcsetalgosqp(state); - - // - // Set constraints: - // - // 1. boundary constraints are passed with minnlcsetbc() call - // - // 2. nonlinear constraints are more tricky - you can not "pack" general - // nonlinear function into double precision array. That's why - // minnlcsetnlc() does not accept constraints itself - only constraint - // counts are passed: first parameter is number of equality constraints, - // second one is number of inequality constraints. - // - // As for constraining functions - these functions are passed as part - // of problem Jacobian (see below). - // - // NOTE: MinNLC optimizer supports arbitrary combination of boundary, general - // linear and general nonlinear constraints. This example does not - // show how to work with general linear constraints, but you can - // easily find it in documentation on minnlcsetlc() function. - // - minnlcsetbc(state, bndl, bndu); - minnlcsetnlc(state, 0, 1); - - // - // Activate OptGuard integrity checking. - // - // OptGuard monitor helps to catch common coding and problem statement - // issues, like: - // * discontinuity of the target/constraints (C0 continuity violation) - // * nonsmoothness of the target/constraints (C1 continuity violation) - // * erroneous analytic Jacobian, i.e. one inconsistent with actual - // change in the target/constraints - // - // OptGuard is essential for early prototyping stages because such - // problems often result in premature termination of the optimizer - // which is really hard to distinguish from the correct termination. - // - // IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL - // DIFFERENTIATION, THUS DO NOT USE IT IN PRODUCTION CODE! - // - // Other OptGuard checks add moderate overhead, but anyway - // it is better to turn them off when they are not needed. - // - minnlcoptguardsmoothness(state); - minnlcoptguardgradient(state, 0.001); - - // - // Optimize and test results. - // - // Optimizer object accepts vector function and its Jacobian, with first - // component (Jacobian row) being target function, and next components - // (Jacobian rows) being nonlinear equality and inequality constraints. - // - // So, our vector function has form - // - // {f0,f1} = { -x0+x1 , x0^2+x1^2-1 } - // - // with Jacobian - // - // [ -1 +1 ] - // J = [ ] - // [ 2*x0 2*x1 ] - // - // with f0 being target function, f1 being constraining function. Number - // of equality/inequality constraints is specified by minnlcsetnlc(), - // with equality ones always being first, inequality ones being last. - // - minnlcreport rep; - real_1d_array x1; - alglib::minnlcoptimize(state, nlcfunc1_jac); - minnlcresults(state, x1, rep); - _TestResult = _TestResult && doc_test_real_vector(x1, "[1.0000,0.0000]", 0.005); - - // - // Check that OptGuard did not report errors - // - // NOTE: want to test OptGuard? Try breaking the Jacobian - say, add - // 1.0 to some of its components. - // - optguardreport ogrep; - minnlcoptguardresults(state, ogrep); - _TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minnlc_d_inequality"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minnlc_d_equality - // Nonlinearly constrained optimization (equality constraints) - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<9; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of - // - // f(x0,x1) = -x0+x1 - // - // subject to nonlinear equality constraint - // - // x0^2 + x1^2 - 1 = 0 - // - real_1d_array x0 = "[0,0]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x0); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x0); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x0); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(s); - double epsx = 0.000001; - if( _spoil_scenario==6 ) - epsx = fp_nan; - if( _spoil_scenario==7 ) - epsx = fp_posinf; - if( _spoil_scenario==8 ) - epsx = fp_neginf; - ae_int_t maxits = 0; - minnlcstate state; - - // - // Create optimizer object and tune its settings: - // * epsx=0.000001 stopping condition for inner iterations - // * s=[1,1] all variables have unit scale - // - minnlccreate(2, x0, state); - minnlcsetcond(state, epsx, maxits); - minnlcsetscale(state, s); - - // - // Choose one of the nonlinear programming solvers supported by minnlc - // optimizer: - // * SLP - successive linear programming NLP solver - // * AUL - augmented Lagrangian NLP solver - // - // Different solvers have different properties: - // * SLP is the most robust solver provided by ALGLIB: it can solve both - // convex and nonconvex optimization problems, it respects box and - // linear constraints (after you find feasible point it won't move away - // from the feasible area) and tries to respect nonlinear constraints - // as much as possible. It also usually needs less function evaluations - // to converge than AUL. - // However, it solves LP subproblems at each iterations which adds - // significant overhead to its running time. Sometimes it can be as much - // as 7x times slower than AUL. - // * AUL solver is less robust than SLP - it can violate box and linear - // constraints at any moment, and it is intended for convex optimization - // problems (although in many cases it can deal with nonconvex ones too). - // Also, unlike SLP it needs some tuning (penalty factor and number of - // outer iterations). - // However, it is often much faster than the current version of SLP. - // - // In the code below we set solver to be AUL but then override it with SLP, - // so the effective choice is to use SLP. We recommend you to use SLP at - // least for early prototyping stages. - // - // You can comment out line with SLP if you want to solve your problem with - // AUL solver. - // - double rho = 1000.0; - ae_int_t outerits = 5; - minnlcsetalgoaul(state, rho, outerits); - minnlcsetalgoslp(state); - - // - // Set constraints: - // - // Nonlinear constraints are tricky - you can not "pack" general - // nonlinear function into double precision array. That's why - // minnlcsetnlc() does not accept constraints itself - only constraint - // counts are passed: first parameter is number of equality constraints, - // second one is number of inequality constraints. - // - // As for constraining functions - these functions are passed as part - // of problem Jacobian (see below). - // - // NOTE: MinNLC optimizer supports arbitrary combination of boundary, general - // linear and general nonlinear constraints. This example does not - // show how to work with general linear constraints, but you can - // easily find it in documentation on minnlcsetbc() and - // minnlcsetlc() functions. - // - minnlcsetnlc(state, 1, 0); - - // - // Activate OptGuard integrity checking. - // - // OptGuard monitor helps to catch common coding and problem statement - // issues, like: - // * discontinuity of the target/constraints (C0 continuity violation) - // * nonsmoothness of the target/constraints (C1 continuity violation) - // * erroneous analytic Jacobian, i.e. one inconsistent with actual - // change in the target/constraints - // - // OptGuard is essential for early prototyping stages because such - // problems often result in premature termination of the optimizer - // which is really hard to distinguish from the correct termination. - // - // IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL - // DIFFERENTIATION, THUS DO NOT USE IT IN PRODUCTION CODE! - // - // Other OptGuard checks add moderate overhead, but anyway - // it is better to turn them off when they are not needed. - // - minnlcoptguardsmoothness(state); - minnlcoptguardgradient(state, 0.001); - - // - // Optimize and test results. - // - // Optimizer object accepts vector function and its Jacobian, with first - // component (Jacobian row) being target function, and next components - // (Jacobian rows) being nonlinear equality and inequality constraints. - // - // So, our vector function has form - // - // {f0,f1} = { -x0+x1 , x0^2+x1^2-1 } - // - // with Jacobian - // - // [ -1 +1 ] - // J = [ ] - // [ 2*x0 2*x1 ] - // - // with f0 being target function, f1 being constraining function. Number - // of equality/inequality constraints is specified by minnlcsetnlc(), - // with equality ones always being first, inequality ones being last. - // - minnlcreport rep; - real_1d_array x1; - alglib::minnlcoptimize(state, nlcfunc1_jac); - minnlcresults(state, x1, rep); - _TestResult = _TestResult && doc_test_real_vector(x1, "[0.70710,-0.70710]", 0.005); - - // - // Check that OptGuard did not report errors - // - // NOTE: want to test OptGuard? Try breaking the Jacobian - say, add - // 1.0 to some of its components. - // - optguardreport ogrep; - minnlcoptguardresults(state, ogrep); - _TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minnlc_d_equality"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minnlc_d_mixed - // Nonlinearly constrained optimization with mixed equality/inequality constraints - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<9; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of - // - // f(x0,x1) = x0+x1 - // - // subject to nonlinear inequality constraint - // - // x0^2 + x1^2 - 1 <= 0 - // - // and nonlinear equality constraint - // - // x2-exp(x0) = 0 - // - real_1d_array x0 = "[0,0,0]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x0); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x0); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x0); - real_1d_array s = "[1,1,1]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(s); - double epsx = 0.000001; - if( _spoil_scenario==6 ) - epsx = fp_nan; - if( _spoil_scenario==7 ) - epsx = fp_posinf; - if( _spoil_scenario==8 ) - epsx = fp_neginf; - ae_int_t maxits = 0; - minnlcstate state; - minnlcreport rep; - real_1d_array x1; - - // - // Create optimizer object and tune its settings: - // * epsx=0.000001 stopping condition for inner iterations - // * s=[1,1] all variables have unit scale - // * upper limit on step length is specified (to avoid probing locations where exp() is large) - // - minnlccreate(3, x0, state); - minnlcsetcond(state, epsx, maxits); - minnlcsetscale(state, s); - minnlcsetstpmax(state, 10.0); - - // - // Choose one of the nonlinear programming solvers supported by minnlc - // optimizer: - // * SLP - successive linear programming NLP solver - // * AUL - augmented Lagrangian NLP solver - // - // Different solvers have different properties: - // * SLP is the most robust solver provided by ALGLIB: it can solve both - // convex and nonconvex optimization problems, it respects box and - // linear constraints (after you find feasible point it won't move away - // from the feasible area) and tries to respect nonlinear constraints - // as much as possible. It also usually needs less function evaluations - // to converge than AUL. - // However, it solves LP subproblems at each iterations which adds - // significant overhead to its running time. Sometimes it can be as much - // as 7x times slower than AUL. - // * AUL solver is less robust than SLP - it can violate box and linear - // constraints at any moment, and it is intended for convex optimization - // problems (although in many cases it can deal with nonconvex ones too). - // Also, unlike SLP it needs some tuning (penalty factor and number of - // outer iterations). - // However, it is often much faster than the current version of SLP. - // - // In the code below we set solver to be AUL but then override it with SLP, - // so the effective choice is to use SLP. We recommend you to use SLP at - // least for early prototyping stages. - // - // You can comment out line with SLP if you want to solve your problem with - // AUL solver. - // - double rho = 1000.0; - ae_int_t outerits = 5; - minnlcsetalgoaul(state, rho, outerits); - minnlcsetalgoslp(state); - - // - // Set constraints: - // - // Nonlinear constraints are tricky - you can not "pack" general - // nonlinear function into double precision array. That's why - // minnlcsetnlc() does not accept constraints itself - only constraint - // counts are passed: first parameter is number of equality constraints, - // second one is number of inequality constraints. - // - // As for constraining functions - these functions are passed as part - // of problem Jacobian (see below). - // - // NOTE: MinNLC optimizer supports arbitrary combination of boundary, general - // linear and general nonlinear constraints. This example does not - // show how to work with boundary or general linear constraints, but you - // can easily find it in documentation on minnlcsetbc() and - // minnlcsetlc() functions. - // - minnlcsetnlc(state, 1, 1); - - // - // Activate OptGuard integrity checking. - // - // OptGuard monitor helps to catch common coding and problem statement - // issues, like: - // * discontinuity of the target/constraints (C0 continuity violation) - // * nonsmoothness of the target/constraints (C1 continuity violation) - // * erroneous analytic Jacobian, i.e. one inconsistent with actual - // change in the target/constraints - // - // OptGuard is essential for early prototyping stages because such - // problems often result in premature termination of the optimizer - // which is really hard to distinguish from the correct termination. - // - // IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL - // DIFFERENTIATION, THUS DO NOT USE IT IN PRODUCTION CODE! - // - // Other OptGuard checks add moderate overhead, but anyway - // it is better to turn them off when they are not needed. - // - minnlcoptguardsmoothness(state); - minnlcoptguardgradient(state, 0.001); - - // - // Optimize and test results. - // - // Optimizer object accepts vector function and its Jacobian, with first - // component (Jacobian row) being target function, and next components - // (Jacobian rows) being nonlinear equality and inequality constraints. - // - // So, our vector function has form - // - // {f0,f1,f2} = { x0+x1 , x2-exp(x0) , x0^2+x1^2-1 } - // - // with Jacobian - // - // [ +1 +1 0 ] - // J = [-exp(x0) 0 1 ] - // [ 2*x0 2*x1 0 ] - // - // with f0 being target function, f1 being equality constraint "f1=0", - // f2 being inequality constraint "f2<=0". Number of equality/inequality - // constraints is specified by minnlcsetnlc(), with equality ones always - // being first, inequality ones being last. - // - alglib::minnlcoptimize(state, nlcfunc2_jac); - minnlcresults(state, x1, rep); - _TestResult = _TestResult && doc_test_real_vector(x1, "[-0.70710,-0.70710,0.49306]", 0.005); - - // - // Check that OptGuard did not report errors - // - // NOTE: want to test OptGuard? Try breaking the Jacobian - say, add - // 1.0 to some of its components. - // - optguardreport ogrep; - minnlcoptguardresults(state, ogrep); - _TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minnlc_d_mixed"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minbc_d_1 - // Nonlinear optimization with box constraints - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<20; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of - // - // f(x,y) = 100*(x+3)^4+(y-3)^4 - // - // subject to box constraints - // - // -1<=x<=+1, -1<=y<=+1 - // - // using MinBC optimizer with: - // * initial point x=[0,0] - // * unit scale being set for all variables (see minbcsetscale for more info) - // * stopping criteria set to "terminate after short enough step" - // * OptGuard integrity check being used to check problem statement - // for some common errors like nonsmoothness or bad analytic gradient - // - // First, we create optimizer object and tune its properties: - // * set box constraints - // * set variable scales - // * set stopping criteria - // - real_1d_array x = "[0,0]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(s); - if( _spoil_scenario==6 ) - spoil_vector_by_deleting_element(s); - real_1d_array bndl = "[-1,-1]"; - if( _spoil_scenario==7 ) - spoil_vector_by_nan(bndl); - if( _spoil_scenario==8 ) - spoil_vector_by_deleting_element(bndl); - real_1d_array bndu = "[+1,+1]"; - if( _spoil_scenario==9 ) - spoil_vector_by_nan(bndu); - if( _spoil_scenario==10 ) - spoil_vector_by_deleting_element(bndu); - minbcstate state; - double epsg = 0; - if( _spoil_scenario==11 ) - epsg = fp_nan; - if( _spoil_scenario==12 ) - epsg = fp_posinf; - if( _spoil_scenario==13 ) - epsg = fp_neginf; - double epsf = 0; - if( _spoil_scenario==14 ) - epsf = fp_nan; - if( _spoil_scenario==15 ) - epsf = fp_posinf; - if( _spoil_scenario==16 ) - epsf = fp_neginf; - double epsx = 0.000001; - if( _spoil_scenario==17 ) - epsx = fp_nan; - if( _spoil_scenario==18 ) - epsx = fp_posinf; - if( _spoil_scenario==19 ) - epsx = fp_neginf; - ae_int_t maxits = 0; - minbccreate(x, state); - minbcsetbc(state, bndl, bndu); - minbcsetscale(state, s); - minbcsetcond(state, epsg, epsf, epsx, maxits); - - // - // Then we activate OptGuard integrity checking. - // - // OptGuard monitor helps to catch common coding and problem statement - // issues, like: - // * discontinuity of the target function (C0 continuity violation) - // * nonsmoothness of the target function (C1 continuity violation) - // * erroneous analytic gradient, i.e. one inconsistent with actual - // change in the target/constraints - // - // OptGuard is essential for early prototyping stages because such - // problems often result in premature termination of the optimizer - // which is really hard to distinguish from the correct termination. - // - // IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL - // DIFFERENTIATION. DO NOT USE IT IN PRODUCTION CODE!!!!!!! - // - // Other OptGuard checks add moderate overhead, but anyway - // it is better to turn them off when they are not needed. - // - minbcoptguardsmoothness(state); - minbcoptguardgradient(state, 0.001); - - // - // Optimize and evaluate results - // - minbcreport rep; - alglib::minbcoptimize(state, function1_grad); - minbcresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[-1,1]", 0.005); - - // - // Check that OptGuard did not report errors - // - // NOTE: want to test OptGuard? Try breaking the gradient - say, add - // 1.0 to some of its components. - // - optguardreport ogrep; - minbcoptguardresults(state, ogrep); - _TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minbc_d_1"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minbc_numdiff - // Nonlinear optimization with bound constraints and numerical differentiation - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<23; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of - // - // f(x,y) = 100*(x+3)^4+(y-3)^4 - // - // subject to box constraints - // - // -1<=x<=+1, -1<=y<=+1 - // - // using MinBC optimizer with: - // * numerical differentiation being used - // * initial point x=[0,0] - // * unit scale being set for all variables (see minbcsetscale for more info) - // * stopping criteria set to "terminate after short enough step" - // * OptGuard integrity check being used to check problem statement - // for some common errors like nonsmoothness or bad analytic gradient - // - real_1d_array x = "[0,0]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(s); - if( _spoil_scenario==6 ) - spoil_vector_by_deleting_element(s); - real_1d_array bndl = "[-1,-1]"; - if( _spoil_scenario==7 ) - spoil_vector_by_nan(bndl); - if( _spoil_scenario==8 ) - spoil_vector_by_deleting_element(bndl); - real_1d_array bndu = "[+1,+1]"; - if( _spoil_scenario==9 ) - spoil_vector_by_nan(bndu); - if( _spoil_scenario==10 ) - spoil_vector_by_deleting_element(bndu); - minbcstate state; - double epsg = 0; - if( _spoil_scenario==11 ) - epsg = fp_nan; - if( _spoil_scenario==12 ) - epsg = fp_posinf; - if( _spoil_scenario==13 ) - epsg = fp_neginf; - double epsf = 0; - if( _spoil_scenario==14 ) - epsf = fp_nan; - if( _spoil_scenario==15 ) - epsf = fp_posinf; - if( _spoil_scenario==16 ) - epsf = fp_neginf; - double epsx = 0.000001; - if( _spoil_scenario==17 ) - epsx = fp_nan; - if( _spoil_scenario==18 ) - epsx = fp_posinf; - if( _spoil_scenario==19 ) - epsx = fp_neginf; - ae_int_t maxits = 0; - double diffstep = 1.0e-6; - if( _spoil_scenario==20 ) - diffstep = fp_nan; - if( _spoil_scenario==21 ) - diffstep = fp_posinf; - if( _spoil_scenario==22 ) - diffstep = fp_neginf; - - // - // Now we are ready to actually optimize something: - // * first we create optimizer - // * we add boundary constraints - // * we tune stopping conditions - // * and, finally, optimize and obtain results... - // - minbccreatef(x, diffstep, state); - minbcsetbc(state, bndl, bndu); - minbcsetscale(state, s); - minbcsetcond(state, epsg, epsf, epsx, maxits); - - // - // Then we activate OptGuard integrity checking. - // - // Numerical differentiation always produces "correct" gradient - // (with some truncation error, but unbiased). Thus, we just have - // to check smoothness properties of the target: C0 and C1 continuity. - // - // Sometimes user accidentally tries to solve nonsmooth problems - // with smooth optimizer. OptGuard helps to detect such situations - // early, at the prototyping stage. - // - minbcoptguardsmoothness(state); - - // - // Optimize and evaluate results - // - minbcreport rep; - alglib::minbcoptimize(state, function1_func); - minbcresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[-1,1]", 0.005); - - // - // Check that OptGuard did not report errors - // - // Want to challenge OptGuard? Try to make your problem - // nonsmooth by replacing 100*(x+3)^4 by 100*|x+3| and - // re-run optimizer. - // - optguardreport ogrep; - minbcoptguardresults(state, ogrep); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minbc_numdiff"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minns_d_unconstrained - // Nonsmooth unconstrained optimization - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<15; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of - // - // f(x0,x1) = 2*|x0|+|x1| - // - // using nonsmooth nonlinear optimizer. - // - real_1d_array x0 = "[1,1]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x0); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x0); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x0); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(s); - double epsx = 0.00001; - if( _spoil_scenario==6 ) - epsx = fp_nan; - if( _spoil_scenario==7 ) - epsx = fp_posinf; - if( _spoil_scenario==8 ) - epsx = fp_neginf; - double radius = 0.1; - if( _spoil_scenario==9 ) - radius = fp_nan; - if( _spoil_scenario==10 ) - radius = fp_posinf; - if( _spoil_scenario==11 ) - radius = fp_neginf; - double rho = 0.0; - if( _spoil_scenario==12 ) - rho = fp_nan; - if( _spoil_scenario==13 ) - rho = fp_posinf; - if( _spoil_scenario==14 ) - rho = fp_neginf; - ae_int_t maxits = 0; - minnsstate state; - minnsreport rep; - real_1d_array x1; - - // - // Create optimizer object, choose AGS algorithm and tune its settings: - // * radius=0.1 good initial value; will be automatically decreased later. - // * rho=0.0 penalty coefficient for nonlinear constraints; can be zero - // because we do not have such constraints - // * epsx=0.000001 stopping conditions - // * s=[1,1] all variables have unit scale - // - minnscreate(2, x0, state); - minnssetalgoags(state, radius, rho); - minnssetcond(state, epsx, maxits); - minnssetscale(state, s); - - // - // Optimize and test results. - // - // Optimizer object accepts vector function and its Jacobian, with first - // component (Jacobian row) being target function, and next components - // (Jacobian rows) being nonlinear equality and inequality constraints - // (box/linear ones are passed separately by means of minnssetbc() and - // minnssetlc() calls). - // - // If you do not have nonlinear constraints (exactly our situation), then - // you will have one-component function vector and 1xN Jacobian matrix. - // - // So, our vector function has form - // - // {f0} = { 2*|x0|+|x1| } - // - // with Jacobian - // - // [ ] - // J = [ 2*sign(x0) sign(x1) ] - // [ ] - // - // NOTE: nonsmooth optimizer requires considerably more function - // evaluations than smooth solver - about 2N times more. Using - // numerical differentiation introduces additional (multiplicative) - // 2N speedup. - // - // It means that if smooth optimizer WITH user-supplied gradient - // needs 100 function evaluations to solve 50-dimensional problem, - // then AGS solver with user-supplied gradient will need about 10.000 - // function evaluations, and with numerical gradient about 1.000.000 - // function evaluations will be performed. - // - // NOTE: AGS solver used by us can handle nonsmooth and nonconvex - // optimization problems. It has convergence guarantees, i.e. it will - // converge to stationary point of the function after running for some - // time. - // - // However, it is important to remember that "stationary point" is not - // equal to "solution". If your problem is convex, everything is OK. - // But nonconvex optimization problems may have "flat spots" - large - // areas where gradient is exactly zero, but function value is far away - // from optimal. Such areas are stationary points too, and optimizer - // may be trapped here. - // - // "Flat spots" are nonsmooth equivalent of the saddle points, but with - // orders of magnitude worse properties - they may be quite large and - // hard to avoid. All nonsmooth optimizers are prone to this kind of the - // problem, because it is impossible to automatically distinguish "flat - // spot" from true solution. - // - // This note is here to warn you that you should be very careful when - // you solve nonsmooth optimization problems. Visual inspection of - // results is essential. - // - alglib::minnsoptimize(state, nsfunc1_jac); - minnsresults(state, x1, rep); - _TestResult = _TestResult && doc_test_real_vector(x1, "[0.0000,0.0000]", 0.005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minns_d_unconstrained"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minns_d_diff - // Nonsmooth unconstrained optimization with numerical differentiation - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<18; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of - // - // f(x0,x1) = 2*|x0|+|x1| - // - // using nonsmooth nonlinear optimizer with numerical - // differentiation provided by ALGLIB. - // - // NOTE: nonsmooth optimizer requires considerably more function - // evaluations than smooth solver - about 2N times more. Using - // numerical differentiation introduces additional (multiplicative) - // 2N speedup. - // - // It means that if smooth optimizer WITH user-supplied gradient - // needs 100 function evaluations to solve 50-dimensional problem, - // then AGS solver with user-supplied gradient will need about 10.000 - // function evaluations, and with numerical gradient about 1.000.000 - // function evaluations will be performed. - // - real_1d_array x0 = "[1,1]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x0); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x0); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x0); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(s); - double epsx = 0.00001; - if( _spoil_scenario==6 ) - epsx = fp_nan; - if( _spoil_scenario==7 ) - epsx = fp_posinf; - if( _spoil_scenario==8 ) - epsx = fp_neginf; - double diffstep = 0.000001; - if( _spoil_scenario==9 ) - diffstep = fp_nan; - if( _spoil_scenario==10 ) - diffstep = fp_posinf; - if( _spoil_scenario==11 ) - diffstep = fp_neginf; - double radius = 0.1; - if( _spoil_scenario==12 ) - radius = fp_nan; - if( _spoil_scenario==13 ) - radius = fp_posinf; - if( _spoil_scenario==14 ) - radius = fp_neginf; - double rho = 0.0; - if( _spoil_scenario==15 ) - rho = fp_nan; - if( _spoil_scenario==16 ) - rho = fp_posinf; - if( _spoil_scenario==17 ) - rho = fp_neginf; - ae_int_t maxits = 0; - minnsstate state; - minnsreport rep; - real_1d_array x1; - - // - // Create optimizer object, choose AGS algorithm and tune its settings: - // * radius=0.1 good initial value; will be automatically decreased later. - // * rho=0.0 penalty coefficient for nonlinear constraints; can be zero - // because we do not have such constraints - // * epsx=0.000001 stopping conditions - // * s=[1,1] all variables have unit scale - // - minnscreatef(2, x0, diffstep, state); - minnssetalgoags(state, radius, rho); - minnssetcond(state, epsx, maxits); - minnssetscale(state, s); - - // - // Optimize and test results. - // - // Optimizer object accepts vector function, with first component - // being target function, and next components being nonlinear equality - // and inequality constraints (box/linear ones are passed separately - // by means of minnssetbc() and minnssetlc() calls). - // - // If you do not have nonlinear constraints (exactly our situation), then - // you will have one-component function vector. - // - // So, our vector function has form - // - // {f0} = { 2*|x0|+|x1| } - // - alglib::minnsoptimize(state, nsfunc1_fvec); - minnsresults(state, x1, rep); - _TestResult = _TestResult && doc_test_real_vector(x1, "[0.0000,0.0000]", 0.005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minns_d_diff"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minns_d_bc - // Nonsmooth box constrained optimization - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<17; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of - // - // f(x0,x1) = 2*|x0|+|x1| - // - // subject to box constraints - // - // 1 <= x0 < +INF - // -INF <= x1 < +INF - // - // using nonsmooth nonlinear optimizer. - // - real_1d_array x0 = "[1,1]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x0); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x0); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x0); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(s); - real_1d_array bndl = "[1,-inf]"; - if( _spoil_scenario==6 ) - spoil_vector_by_nan(bndl); - real_1d_array bndu = "[+inf,+inf]"; - if( _spoil_scenario==7 ) - spoil_vector_by_nan(bndu); - double epsx = 0.00001; - if( _spoil_scenario==8 ) - epsx = fp_nan; - if( _spoil_scenario==9 ) - epsx = fp_posinf; - if( _spoil_scenario==10 ) - epsx = fp_neginf; - double radius = 0.1; - if( _spoil_scenario==11 ) - radius = fp_nan; - if( _spoil_scenario==12 ) - radius = fp_posinf; - if( _spoil_scenario==13 ) - radius = fp_neginf; - double rho = 0.0; - if( _spoil_scenario==14 ) - rho = fp_nan; - if( _spoil_scenario==15 ) - rho = fp_posinf; - if( _spoil_scenario==16 ) - rho = fp_neginf; - ae_int_t maxits = 0; - minnsstate state; - minnsreport rep; - real_1d_array x1; - - // - // Create optimizer object, choose AGS algorithm and tune its settings: - // * radius=0.1 good initial value; will be automatically decreased later. - // * rho=0.0 penalty coefficient for nonlinear constraints; can be zero - // because we do not have such constraints - // * epsx=0.000001 stopping conditions - // * s=[1,1] all variables have unit scale - // - minnscreate(2, x0, state); - minnssetalgoags(state, radius, rho); - minnssetcond(state, epsx, maxits); - minnssetscale(state, s); - - // - // Set box constraints. - // - // General linear constraints are set in similar way (see comments on - // minnssetlc() function for more information). - // - // You may combine box, linear and nonlinear constraints in one optimization - // problem. - // - minnssetbc(state, bndl, bndu); - - // - // Optimize and test results. - // - // Optimizer object accepts vector function and its Jacobian, with first - // component (Jacobian row) being target function, and next components - // (Jacobian rows) being nonlinear equality and inequality constraints - // (box/linear ones are passed separately by means of minnssetbc() and - // minnssetlc() calls). - // - // If you do not have nonlinear constraints (exactly our situation), then - // you will have one-component function vector and 1xN Jacobian matrix. - // - // So, our vector function has form - // - // {f0} = { 2*|x0|+|x1| } - // - // with Jacobian - // - // [ ] - // J = [ 2*sign(x0) sign(x1) ] - // [ ] - // - // NOTE: nonsmooth optimizer requires considerably more function - // evaluations than smooth solver - about 2N times more. Using - // numerical differentiation introduces additional (multiplicative) - // 2N speedup. - // - // It means that if smooth optimizer WITH user-supplied gradient - // needs 100 function evaluations to solve 50-dimensional problem, - // then AGS solver with user-supplied gradient will need about 10.000 - // function evaluations, and with numerical gradient about 1.000.000 - // function evaluations will be performed. - // - // NOTE: AGS solver used by us can handle nonsmooth and nonconvex - // optimization problems. It has convergence guarantees, i.e. it will - // converge to stationary point of the function after running for some - // time. - // - // However, it is important to remember that "stationary point" is not - // equal to "solution". If your problem is convex, everything is OK. - // But nonconvex optimization problems may have "flat spots" - large - // areas where gradient is exactly zero, but function value is far away - // from optimal. Such areas are stationary points too, and optimizer - // may be trapped here. - // - // "Flat spots" are nonsmooth equivalent of the saddle points, but with - // orders of magnitude worse properties - they may be quite large and - // hard to avoid. All nonsmooth optimizers are prone to this kind of the - // problem, because it is impossible to automatically distinguish "flat - // spot" from true solution. - // - // This note is here to warn you that you should be very careful when - // you solve nonsmooth optimization problems. Visual inspection of - // results is essential. - // - // - alglib::minnsoptimize(state, nsfunc1_jac); - minnsresults(state, x1, rep); - _TestResult = _TestResult && doc_test_real_vector(x1, "[1.0000,0.0000]", 0.005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minns_d_bc"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minns_d_nlc - // Nonsmooth nonlinearly constrained optimization - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<15; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of - // - // f(x0,x1) = 2*|x0|+|x1| - // - // subject to combination of equality and inequality constraints - // - // x0 = 1 - // x1 >= -1 - // - // using nonsmooth nonlinear optimizer. Although these constraints - // are linear, we treat them as general nonlinear ones in order to - // demonstrate nonlinearly constrained optimization setup. - // - real_1d_array x0 = "[1,1]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x0); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x0); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x0); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(s); - double epsx = 0.00001; - if( _spoil_scenario==6 ) - epsx = fp_nan; - if( _spoil_scenario==7 ) - epsx = fp_posinf; - if( _spoil_scenario==8 ) - epsx = fp_neginf; - double radius = 0.1; - if( _spoil_scenario==9 ) - radius = fp_nan; - if( _spoil_scenario==10 ) - radius = fp_posinf; - if( _spoil_scenario==11 ) - radius = fp_neginf; - double rho = 50.0; - if( _spoil_scenario==12 ) - rho = fp_nan; - if( _spoil_scenario==13 ) - rho = fp_posinf; - if( _spoil_scenario==14 ) - rho = fp_neginf; - ae_int_t maxits = 0; - minnsstate state; - minnsreport rep; - real_1d_array x1; - - // - // Create optimizer object, choose AGS algorithm and tune its settings: - // * radius=0.1 good initial value; will be automatically decreased later. - // * rho=50.0 penalty coefficient for nonlinear constraints. It is your - // responsibility to choose good one - large enough that it - // enforces constraints, but small enough in order to avoid - // extreme slowdown due to ill-conditioning. - // * epsx=0.000001 stopping conditions - // * s=[1,1] all variables have unit scale - // - minnscreate(2, x0, state); - minnssetalgoags(state, radius, rho); - minnssetcond(state, epsx, maxits); - minnssetscale(state, s); - - // - // Set general nonlinear constraints. - // - // This part is more tricky than working with box/linear constraints - you - // can not "pack" general nonlinear function into double precision array. - // That's why minnssetnlc() does not accept constraints itself - only - // constraint COUNTS are passed: first parameter is number of equality - // constraints, second one is number of inequality constraints. - // - // As for constraining functions - these functions are passed as part - // of problem Jacobian (see below). - // - // NOTE: MinNS optimizer supports arbitrary combination of boundary, general - // linear and general nonlinear constraints. This example does not - // show how to work with general linear constraints, but you can - // easily find it in documentation on minnlcsetlc() function. - // - minnssetnlc(state, 1, 1); - - // - // Optimize and test results. - // - // Optimizer object accepts vector function and its Jacobian, with first - // component (Jacobian row) being target function, and next components - // (Jacobian rows) being nonlinear equality and inequality constraints - // (box/linear ones are passed separately by means of minnssetbc() and - // minnssetlc() calls). - // - // Nonlinear equality constraints have form Gi(x)=0, inequality ones - // have form Hi(x)<=0, so we may have to "normalize" constraints prior - // to passing them to optimizer (right side is zero, constraints are - // sorted, multiplied by -1 when needed). - // - // So, our vector function has form - // - // {f0,f1,f2} = { 2*|x0|+|x1|, x0-1, -x1-1 } - // - // with Jacobian - // - // [ 2*sign(x0) sign(x1) ] - // J = [ 1 0 ] - // [ 0 -1 ] - // - // which means that we have optimization problem - // - // min{f0} subject to f1=0, f2<=0 - // - // which is essentially same as - // - // min { 2*|x0|+|x1| } subject to x0=1, x1>=-1 - // - // NOTE: AGS solver used by us can handle nonsmooth and nonconvex - // optimization problems. It has convergence guarantees, i.e. it will - // converge to stationary point of the function after running for some - // time. - // - // However, it is important to remember that "stationary point" is not - // equal to "solution". If your problem is convex, everything is OK. - // But nonconvex optimization problems may have "flat spots" - large - // areas where gradient is exactly zero, but function value is far away - // from optimal. Such areas are stationary points too, and optimizer - // may be trapped here. - // - // "Flat spots" are nonsmooth equivalent of the saddle points, but with - // orders of magnitude worse properties - they may be quite large and - // hard to avoid. All nonsmooth optimizers are prone to this kind of the - // problem, because it is impossible to automatically distinguish "flat - // spot" from true solution. - // - // This note is here to warn you that you should be very careful when - // you solve nonsmooth optimization problems. Visual inspection of - // results is essential. - // - alglib::minnsoptimize(state, nsfunc2_jac); - minnsresults(state, x1, rep); - _TestResult = _TestResult && doc_test_real_vector(x1, "[1.0000,0.0000]", 0.005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minns_d_nlc"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST mincg_d_1 - // Nonlinear optimization by CG - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<15; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of - // - // f(x,y) = 100*(x+3)^4+(y-3)^4 - // - // using nonlinear conjugate gradient method with: - // * initial point x=[0,0] - // * unit scale being set for all variables (see mincgsetscale for more info) - // * stopping criteria set to "terminate after short enough step" - // * OptGuard integrity check being used to check problem statement - // for some common errors like nonsmoothness or bad analytic gradient - // - // First, we create optimizer object and tune its properties - // - real_1d_array x = "[0,0]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(s); - double epsg = 0; - if( _spoil_scenario==6 ) - epsg = fp_nan; - if( _spoil_scenario==7 ) - epsg = fp_posinf; - if( _spoil_scenario==8 ) - epsg = fp_neginf; - double epsf = 0; - if( _spoil_scenario==9 ) - epsf = fp_nan; - if( _spoil_scenario==10 ) - epsf = fp_posinf; - if( _spoil_scenario==11 ) - epsf = fp_neginf; - double epsx = 0.0000000001; - if( _spoil_scenario==12 ) - epsx = fp_nan; - if( _spoil_scenario==13 ) - epsx = fp_posinf; - if( _spoil_scenario==14 ) - epsx = fp_neginf; - ae_int_t maxits = 0; - mincgstate state; - mincgcreate(x, state); - mincgsetcond(state, epsg, epsf, epsx, maxits); - mincgsetscale(state, s); - - // - // Activate OptGuard integrity checking. - // - // OptGuard monitor helps to catch common coding and problem statement - // issues, like: - // * discontinuity of the target function (C0 continuity violation) - // * nonsmoothness of the target function (C1 continuity violation) - // * erroneous analytic gradient, i.e. one inconsistent with actual - // change in the target/constraints - // - // OptGuard is essential for early prototyping stages because such - // problems often result in premature termination of the optimizer - // which is really hard to distinguish from the correct termination. - // - // IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL - // DIFFERENTIATION. DO NOT USE IT IN PRODUCTION CODE!!!!!!! - // - // Other OptGuard checks add moderate overhead, but anyway - // it is better to turn them off when they are not needed. - // - mincgoptguardsmoothness(state); - mincgoptguardgradient(state, 0.001); - - // - // Optimize and evaluate results - // - mincgreport rep; - alglib::mincgoptimize(state, function1_grad); - mincgresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[-3,3]", 0.005); - - // - // Check that OptGuard did not report errors - // - // NOTE: want to test OptGuard? Try breaking the gradient - say, add - // 1.0 to some of its components. - // - optguardreport ogrep; - mincgoptguardresults(state, ogrep); - _TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "mincg_d_1"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST mincg_d_2 - // Nonlinear optimization with additional settings and restarts - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<21; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of f(x,y) = 100*(x+3)^4+(y-3)^4 - // with nonlinear conjugate gradient method. - // - // Several advanced techniques are demonstrated: - // * upper limit on step size - // * restart from new point - // - real_1d_array x = "[0,0]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(s); - double epsg = 0; - if( _spoil_scenario==6 ) - epsg = fp_nan; - if( _spoil_scenario==7 ) - epsg = fp_posinf; - if( _spoil_scenario==8 ) - epsg = fp_neginf; - double epsf = 0; - if( _spoil_scenario==9 ) - epsf = fp_nan; - if( _spoil_scenario==10 ) - epsf = fp_posinf; - if( _spoil_scenario==11 ) - epsf = fp_neginf; - double epsx = 0.0000000001; - if( _spoil_scenario==12 ) - epsx = fp_nan; - if( _spoil_scenario==13 ) - epsx = fp_posinf; - if( _spoil_scenario==14 ) - epsx = fp_neginf; - double stpmax = 0.1; - if( _spoil_scenario==15 ) - stpmax = fp_nan; - if( _spoil_scenario==16 ) - stpmax = fp_posinf; - if( _spoil_scenario==17 ) - stpmax = fp_neginf; - ae_int_t maxits = 0; - mincgstate state; - mincgreport rep; - - // create and tune optimizer - mincgcreate(x, state); - mincgsetscale(state, s); - mincgsetcond(state, epsg, epsf, epsx, maxits); - mincgsetstpmax(state, stpmax); - - // Set up OptGuard integrity checker which catches errors - // like nonsmooth targets or errors in the analytic gradient. - // - // OptGuard is essential at the early prototyping stages. - // - // NOTE: gradient verification needs 3*N additional function - // evaluations; DO NOT USE IT IN THE PRODUCTION CODE - // because it leads to unnecessary slowdown of your app. - mincgoptguardsmoothness(state); - mincgoptguardgradient(state, 0.001); - - // first run - alglib::mincgoptimize(state, function1_grad); - mincgresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[-3,3]", 0.005); - - // second run - algorithm is restarted with mincgrestartfrom() - x = "[10,10]"; - if( _spoil_scenario==18 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==19 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==20 ) - spoil_vector_by_neginf(x); - mincgrestartfrom(state, x); - alglib::mincgoptimize(state, function1_grad); - mincgresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[-3,3]", 0.005); - - // check OptGuard integrity report. Why do we need it at all? - // Well, try breaking the gradient by adding 1.0 to some - // of its components - OptGuard should report it as error. - // And it may also catch unintended errors too :) - optguardreport ogrep; - mincgoptguardresults(state, ogrep); - _TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "mincg_d_2"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST mincg_numdiff - // Nonlinear optimization by CG with numerical differentiation - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<18; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of - // - // f(x,y) = 100*(x+3)^4+(y-3)^4 - // - // using numerical differentiation to calculate gradient. - // - // We also show how to use OptGuard integrity checker to catch common - // problem statement errors like accidentally specifying nonsmooth target - // function. - // - // First, we set up optimizer... - // - real_1d_array x = "[0,0]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(s); - double epsg = 0; - if( _spoil_scenario==6 ) - epsg = fp_nan; - if( _spoil_scenario==7 ) - epsg = fp_posinf; - if( _spoil_scenario==8 ) - epsg = fp_neginf; - double epsf = 0; - if( _spoil_scenario==9 ) - epsf = fp_nan; - if( _spoil_scenario==10 ) - epsf = fp_posinf; - if( _spoil_scenario==11 ) - epsf = fp_neginf; - double epsx = 0.0000000001; - if( _spoil_scenario==12 ) - epsx = fp_nan; - if( _spoil_scenario==13 ) - epsx = fp_posinf; - if( _spoil_scenario==14 ) - epsx = fp_neginf; - double diffstep = 1.0e-6; - if( _spoil_scenario==15 ) - diffstep = fp_nan; - if( _spoil_scenario==16 ) - diffstep = fp_posinf; - if( _spoil_scenario==17 ) - diffstep = fp_neginf; - ae_int_t maxits = 0; - mincgstate state; - mincgcreatef(x, diffstep, state); - mincgsetcond(state, epsg, epsf, epsx, maxits); - mincgsetscale(state, s); - - // - // Then, we activate OptGuard integrity checking. - // - // Numerical differentiation always produces "correct" gradient - // (with some truncation error, but unbiased). Thus, we just have - // to check smoothness properties of the target: C0 and C1 continuity. - // - // Sometimes user accidentally tried to solve nonsmooth problems - // with smooth optimizer. OptGuard helps to detect such situations - // early, at the prototyping stage. - // - mincgoptguardsmoothness(state); - - // - // Now we are ready to run the optimization - // - mincgreport rep; - alglib::mincgoptimize(state, function1_func); - mincgresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[-3,3]", 0.005); - - // - // ...and to check OptGuard integrity report. - // - // Want to challenge OptGuard? Try to make your problem - // nonsmooth by replacing 100*(x+3)^4 by 100*|x+3| and - // re-run optimizer. - // - optguardreport ogrep; - mincgoptguardresults(state, ogrep); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false); - _TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "mincg_numdiff"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minlm_d_v - // Nonlinear least squares optimization using function vector only - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<9; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of F(x0,x1) = f0^2+f1^2, where - // - // f0(x0,x1) = 10*(x0+3)^2 - // f1(x0,x1) = (x1-3)^2 - // - // using "V" mode of the Levenberg-Marquardt optimizer. - // - // Optimization algorithm uses: - // * function vector f[] = {f1,f2} - // - // No other information (Jacobian, gradient, etc.) is needed. - // - real_1d_array x = "[0,0]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(s); - double epsx = 0.0000000001; - if( _spoil_scenario==6 ) - epsx = fp_nan; - if( _spoil_scenario==7 ) - epsx = fp_posinf; - if( _spoil_scenario==8 ) - epsx = fp_neginf; - ae_int_t maxits = 0; - minlmstate state; - minlmreport rep; - - // - // Create optimizer, tell it to: - // * use numerical differentiation with step equal to 0.0001 - // * use unit scale for all variables (s is a unit vector) - // * stop after short enough step (less than epsx) - // - minlmcreatev(2, x, 0.0001, state); - minlmsetcond(state, epsx, maxits); - minlmsetscale(state, s); - - // - // Optimize - // - alglib::minlmoptimize(state, function1_fvec); - - // - // Test optimization results - // - // NOTE: because we use numerical differentiation, we do not - // verify Jacobian correctness - it is always "correct". - // However, if you switch to analytic gradient, consider - // checking it with OptGuard (see other examples). - // - minlmresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[-3,+3]", 0.005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minlm_d_v"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minlm_d_vj - // Nonlinear least squares optimization using function vector and Jacobian - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<9; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of F(x0,x1) = f0^2+f1^2, where - // - // f0(x0,x1) = 10*(x0+3)^2 - // f1(x0,x1) = (x1-3)^2 - // - // using "VJ" mode of the Levenberg-Marquardt optimizer. - // - // Optimization algorithm uses: - // * function vector f[] = {f1,f2} - // * Jacobian matrix J = {dfi/dxj}. - // - real_1d_array x = "[0,0]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(s); - double epsx = 0.0000000001; - if( _spoil_scenario==6 ) - epsx = fp_nan; - if( _spoil_scenario==7 ) - epsx = fp_posinf; - if( _spoil_scenario==8 ) - epsx = fp_neginf; - ae_int_t maxits = 0; - minlmstate state; - - // - // Create optimizer, tell it to: - // * use analytic gradient provided by user - // * use unit scale for all variables (s is a unit vector) - // * stop after short enough step (less than epsx) - // - minlmcreatevj(2, x, state); - minlmsetcond(state, epsx, maxits); - minlmsetscale(state, s); - - // - // Activate OptGuard integrity checking. - // - // OptGuard monitor helps to detect erroneous analytic Jacobian, - // i.e. one inconsistent with actual change in the target function. - // - // OptGuard is essential for early prototyping stages because such - // problems often result in premature termination of the optimizer - // which is really hard to distinguish from the correct termination. - // - // IMPORTANT: JACOBIAN VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL - // DIFFERENTIATION, THUS DO NOT USE IT IN PRODUCTION CODE! - // - minlmoptguardgradient(state, 0.001); - - // - // Optimize - // - alglib::minlmoptimize(state, function1_fvec, function1_jac); - - // - // Test optimization results - // - minlmreport rep; - minlmresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[-3,+3]", 0.005); - - // - // Check that OptGuard did not report errors - // - // NOTE: want to test OptGuard? Try breaking the Jacobian - say, add - // 1.0 to some of its components. - // - // NOTE: unfortunately, specifics of LM optimization do not allow us - // to detect errors like nonsmoothness (like we do with other - // optimizers). So, only Jacobian correctness is verified. - // - optguardreport ogrep; - minlmoptguardresults(state, ogrep); - _TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minlm_d_vj"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minlm_d_fgh - // Nonlinear Hessian-based optimization for general functions - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<6; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of F(x0,x1) = 100*(x0+3)^4+(x1-3)^4 - // using "FGH" mode of the Levenberg-Marquardt optimizer. - // - // F is treated like a monolitic function without internal structure, - // i.e. we do NOT represent it as a sum of squares. - // - // Optimization algorithm uses: - // * function value F(x0,x1) - // * gradient G={dF/dxi} - // * Hessian H={d2F/(dxi*dxj)} - // - real_1d_array x = "[0,0]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - double epsx = 0.0000000001; - if( _spoil_scenario==3 ) - epsx = fp_nan; - if( _spoil_scenario==4 ) - epsx = fp_posinf; - if( _spoil_scenario==5 ) - epsx = fp_neginf; - ae_int_t maxits = 0; - minlmstate state; - minlmreport rep; - - minlmcreatefgh(x, state); - minlmsetcond(state, epsx, maxits); - alglib::minlmoptimize(state, function1_func, function1_grad, function1_hess); - minlmresults(state, x, rep); - - _TestResult = _TestResult && doc_test_real_vector(x, "[-3,+3]", 0.005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minlm_d_fgh"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minlm_d_vb - // Bound constrained nonlinear least squares optimization - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<13; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of F(x0,x1) = f0^2+f1^2, where - // - // f0(x0,x1) = 10*(x0+3)^2 - // f1(x0,x1) = (x1-3)^2 - // - // with boundary constraints - // - // -1 <= x0 <= +1 - // -1 <= x1 <= +1 - // - // using "V" mode of the Levenberg-Marquardt optimizer. - // - // Optimization algorithm uses: - // * function vector f[] = {f1,f2} - // - // No other information (Jacobian, gradient, etc.) is needed. - // - real_1d_array x = "[0,0]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - real_1d_array s = "[1,1]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(s); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(s); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(s); - real_1d_array bndl = "[-1,-1]"; - if( _spoil_scenario==6 ) - spoil_vector_by_nan(bndl); - if( _spoil_scenario==7 ) - spoil_vector_by_deleting_element(bndl); - real_1d_array bndu = "[+1,+1]"; - if( _spoil_scenario==8 ) - spoil_vector_by_nan(bndu); - if( _spoil_scenario==9 ) - spoil_vector_by_deleting_element(bndu); - double epsx = 0.0000000001; - if( _spoil_scenario==10 ) - epsx = fp_nan; - if( _spoil_scenario==11 ) - epsx = fp_posinf; - if( _spoil_scenario==12 ) - epsx = fp_neginf; - ae_int_t maxits = 0; - minlmstate state; - - // - // Create optimizer, tell it to: - // * use numerical differentiation with step equal to 1.0 - // * use unit scale for all variables (s is a unit vector) - // * stop after short enough step (less than epsx) - // * set box constraints - // - minlmcreatev(2, x, 0.0001, state); - minlmsetbc(state, bndl, bndu); - minlmsetcond(state, epsx, maxits); - minlmsetscale(state, s); - - // - // Optimize - // - alglib::minlmoptimize(state, function1_fvec); - - // - // Test optimization results - // - // NOTE: because we use numerical differentiation, we do not - // verify Jacobian correctness - it is always "correct". - // However, if you switch to analytic gradient, consider - // checking it with OptGuard (see other examples). - // - minlmreport rep; - minlmresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[-1,+1]", 0.005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minlm_d_vb"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minlm_d_restarts - // Efficient restarts of LM optimizer - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<9; _spoil_scenario++) - { - try - { - // - // This example demonstrates minimization of F(x0,x1) = f0^2+f1^2, where - // - // f0(x0,x1) = 10*(x0+3)^2 - // f1(x0,x1) = (x1-3)^2 - // - // using several starting points and efficient restarts. - // - real_1d_array x; - double epsx = 0.0000000001; - if( _spoil_scenario==0 ) - epsx = fp_nan; - if( _spoil_scenario==1 ) - epsx = fp_posinf; - if( _spoil_scenario==2 ) - epsx = fp_neginf; - ae_int_t maxits = 0; - minlmstate state; - minlmreport rep; - - // - // create optimizer using minlmcreatev() - // - x = "[10,10]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(x); - minlmcreatev(2, x, 0.0001, state); - minlmsetcond(state, epsx, maxits); - alglib::minlmoptimize(state, function1_fvec); - minlmresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[-3,+3]", 0.005); - - // - // restart optimizer using minlmrestartfrom() - // - // we can use different starting point, different function, - // different stopping conditions, but problem size - // must remain unchanged. - // - x = "[4,4]"; - if( _spoil_scenario==6 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==7 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==8 ) - spoil_vector_by_neginf(x); - minlmrestartfrom(state, x); - alglib::minlmoptimize(state, function2_fvec); - minlmresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[0,1]", 0.005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minlm_d_restarts"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minlm_t_1 - // Nonlinear least squares optimization, FJ scheme (obsolete, but supported) - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<6; _spoil_scenario++) - { - try - { - real_1d_array x = "[0,0]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - double epsx = 0.0000000001; - if( _spoil_scenario==3 ) - epsx = fp_nan; - if( _spoil_scenario==4 ) - epsx = fp_posinf; - if( _spoil_scenario==5 ) - epsx = fp_neginf; - ae_int_t maxits = 0; - minlmstate state; - minlmreport rep; - minlmcreatefj(2, x, state); - minlmsetcond(state, epsx, maxits); - alglib::minlmoptimize(state, function1_func, function1_jac); - minlmresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[-3,+3]", 0.005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minlm_t_1"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST minlm_t_2 - // Nonlinear least squares optimization, FGJ scheme (obsolete, but supported) - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<6; _spoil_scenario++) - { - try - { - real_1d_array x = "[0,0]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - double epsx = 0.0000000001; - if( _spoil_scenario==3 ) - epsx = fp_nan; - if( _spoil_scenario==4 ) - epsx = fp_posinf; - if( _spoil_scenario==5 ) - epsx = fp_neginf; - ae_int_t maxits = 0; - minlmstate state; - minlmreport rep; - minlmcreatefgj(2, x, state); - minlmsetcond(state, epsx, maxits); - alglib::minlmoptimize(state, function1_func, function1_grad, function1_jac); - minlmresults(state, x, rep); - _TestResult = _TestResult && doc_test_real_vector(x, "[-3,+3]", 0.005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "minlm_t_2"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST basestat_d_base - // Basic functionality (moments, adev, median, percentile) - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<6; _spoil_scenario++) - { - try - { - real_1d_array x = "[0,1,4,9,16,25,36,49,64,81]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - double mean; - double variance; - double skewness; - double kurtosis; - double adev; - double p; - double v; - - // - // Here we demonstrate calculation of sample moments - // (mean, variance, skewness, kurtosis) - // - samplemoments(x, mean, variance, skewness, kurtosis); - _TestResult = _TestResult && doc_test_real(mean, 28.5, 0.01); - _TestResult = _TestResult && doc_test_real(variance, 801.1667, 0.01); - _TestResult = _TestResult && doc_test_real(skewness, 0.5751, 0.01); - _TestResult = _TestResult && doc_test_real(kurtosis, -1.2666, 0.01); - - // - // Average deviation - // - sampleadev(x, adev); - _TestResult = _TestResult && doc_test_real(adev, 23.2, 0.01); - - // - // Median and percentile - // - samplemedian(x, v); - _TestResult = _TestResult && doc_test_real(v, 20.5, 0.01); - p = 0.5; - if( _spoil_scenario==3 ) - p = fp_nan; - if( _spoil_scenario==4 ) - p = fp_posinf; - if( _spoil_scenario==5 ) - p = fp_neginf; - samplepercentile(x, p, v); - _TestResult = _TestResult && doc_test_real(v, 20.5, 0.01); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "basestat_d_base"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST basestat_d_c2 - // Correlation (covariance) between two random variables - // - printf("50/151\n"); - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<10; _spoil_scenario++) - { - try - { - // - // We have two samples - x and y, and want to measure dependency between them - // - real_1d_array x = "[0,1,4,9,16,25,36,49,64,81]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - if( _spoil_scenario==3 ) - spoil_vector_by_adding_element(x); - if( _spoil_scenario==4 ) - spoil_vector_by_deleting_element(x); - real_1d_array y = "[0,1,2,3,4,5,6,7,8,9]"; - if( _spoil_scenario==5 ) - spoil_vector_by_nan(y); - if( _spoil_scenario==6 ) - spoil_vector_by_posinf(y); - if( _spoil_scenario==7 ) - spoil_vector_by_neginf(y); - if( _spoil_scenario==8 ) - spoil_vector_by_adding_element(y); - if( _spoil_scenario==9 ) - spoil_vector_by_deleting_element(y); - double v; - - // - // Three dependency measures are calculated: - // * covariation - // * Pearson correlation - // * Spearman rank correlation - // - v = cov2(x, y); - _TestResult = _TestResult && doc_test_real(v, 82.5, 0.001); - v = pearsoncorr2(x, y); - _TestResult = _TestResult && doc_test_real(v, 0.9627, 0.001); - v = spearmancorr2(x, y); - _TestResult = _TestResult && doc_test_real(v, 1.000, 0.001); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "basestat_d_c2"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST basestat_d_cm - // Correlation (covariance) between components of random vector - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++) - { - try - { - // - // X is a sample matrix: - // * I-th row corresponds to I-th observation - // * J-th column corresponds to J-th variable - // - real_2d_array x = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]"; - if( _spoil_scenario==0 ) - spoil_matrix_by_nan(x); - if( _spoil_scenario==1 ) - spoil_matrix_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_matrix_by_neginf(x); - real_2d_array c; - - // - // Three dependency measures are calculated: - // * covariation - // * Pearson correlation - // * Spearman rank correlation - // - // Result is stored into C, with C[i,j] equal to correlation - // (covariance) between I-th and J-th variables of X. - // - covm(x, c); - _TestResult = _TestResult && doc_test_real_matrix(c, "[[1.80,0.60,-1.40],[0.60,0.70,-0.80],[-1.40,-0.80,14.70]]", 0.01); - pearsoncorrm(x, c); - _TestResult = _TestResult && doc_test_real_matrix(c, "[[1.000,0.535,-0.272],[0.535,1.000,-0.249],[-0.272,-0.249,1.000]]", 0.01); - spearmancorrm(x, c); - _TestResult = _TestResult && doc_test_real_matrix(c, "[[1.000,0.556,-0.306],[0.556,1.000,-0.750],[-0.306,-0.750,1.000]]", 0.01); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "basestat_d_cm"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST basestat_d_cm2 - // Correlation (covariance) between two random vectors - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<6; _spoil_scenario++) - { - try - { - // - // X and Y are sample matrices: - // * I-th row corresponds to I-th observation - // * J-th column corresponds to J-th variable - // - real_2d_array x = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]"; - if( _spoil_scenario==0 ) - spoil_matrix_by_nan(x); - if( _spoil_scenario==1 ) - spoil_matrix_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_matrix_by_neginf(x); - real_2d_array y = "[[2,3],[2,1],[-1,6],[-9,9],[7,1]]"; - if( _spoil_scenario==3 ) - spoil_matrix_by_nan(y); - if( _spoil_scenario==4 ) - spoil_matrix_by_posinf(y); - if( _spoil_scenario==5 ) - spoil_matrix_by_neginf(y); - real_2d_array c; - - // - // Three dependency measures are calculated: - // * covariation - // * Pearson correlation - // * Spearman rank correlation - // - // Result is stored into C, with C[i,j] equal to correlation - // (covariance) between I-th variable of X and J-th variable of Y. - // - covm2(x, y, c); - _TestResult = _TestResult && doc_test_real_matrix(c, "[[4.100,-3.250],[2.450,-1.500],[13.450,-5.750]]", 0.01); - pearsoncorrm2(x, y, c); - _TestResult = _TestResult && doc_test_real_matrix(c, "[[0.519,-0.699],[0.497,-0.518],[0.596,-0.433]]", 0.01); - spearmancorrm2(x, y, c); - _TestResult = _TestResult && doc_test_real_matrix(c, "[[0.541,-0.649],[0.216,-0.433],[0.433,-0.135]]", 0.01); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "basestat_d_cm2"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST basestat_t_base - // Tests ability to detect errors in inputs - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<34; _spoil_scenario++) - { - try - { - double mean; - double variance; - double skewness; - double kurtosis; - double adev; - double p; - double v; - - // - // first, we test short form of functions - // - real_1d_array x1 = "[0,1,4,9,16,25,36,49,64,81]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x1); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x1); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x1); - samplemoments(x1, mean, variance, skewness, kurtosis); - real_1d_array x2 = "[0,1,4,9,16,25,36,49,64,81]"; - if( _spoil_scenario==3 ) - spoil_vector_by_nan(x2); - if( _spoil_scenario==4 ) - spoil_vector_by_posinf(x2); - if( _spoil_scenario==5 ) - spoil_vector_by_neginf(x2); - sampleadev(x2, adev); - real_1d_array x3 = "[0,1,4,9,16,25,36,49,64,81]"; - if( _spoil_scenario==6 ) - spoil_vector_by_nan(x3); - if( _spoil_scenario==7 ) - spoil_vector_by_posinf(x3); - if( _spoil_scenario==8 ) - spoil_vector_by_neginf(x3); - samplemedian(x3, v); - real_1d_array x4 = "[0,1,4,9,16,25,36,49,64,81]"; - if( _spoil_scenario==9 ) - spoil_vector_by_nan(x4); - if( _spoil_scenario==10 ) - spoil_vector_by_posinf(x4); - if( _spoil_scenario==11 ) - spoil_vector_by_neginf(x4); - p = 0.5; - if( _spoil_scenario==12 ) - p = fp_nan; - if( _spoil_scenario==13 ) - p = fp_posinf; - if( _spoil_scenario==14 ) - p = fp_neginf; - samplepercentile(x4, p, v); - - // - // and then we test full form - // - real_1d_array x5 = "[0,1,4,9,16,25,36,49,64,81]"; - if( _spoil_scenario==15 ) - spoil_vector_by_nan(x5); - if( _spoil_scenario==16 ) - spoil_vector_by_posinf(x5); - if( _spoil_scenario==17 ) - spoil_vector_by_neginf(x5); - if( _spoil_scenario==18 ) - spoil_vector_by_deleting_element(x5); - samplemoments(x5, 10, mean, variance, skewness, kurtosis); - real_1d_array x6 = "[0,1,4,9,16,25,36,49,64,81]"; - if( _spoil_scenario==19 ) - spoil_vector_by_nan(x6); - if( _spoil_scenario==20 ) - spoil_vector_by_posinf(x6); - if( _spoil_scenario==21 ) - spoil_vector_by_neginf(x6); - if( _spoil_scenario==22 ) - spoil_vector_by_deleting_element(x6); - sampleadev(x6, 10, adev); - real_1d_array x7 = "[0,1,4,9,16,25,36,49,64,81]"; - if( _spoil_scenario==23 ) - spoil_vector_by_nan(x7); - if( _spoil_scenario==24 ) - spoil_vector_by_posinf(x7); - if( _spoil_scenario==25 ) - spoil_vector_by_neginf(x7); - if( _spoil_scenario==26 ) - spoil_vector_by_deleting_element(x7); - samplemedian(x7, 10, v); - real_1d_array x8 = "[0,1,4,9,16,25,36,49,64,81]"; - if( _spoil_scenario==27 ) - spoil_vector_by_nan(x8); - if( _spoil_scenario==28 ) - spoil_vector_by_posinf(x8); - if( _spoil_scenario==29 ) - spoil_vector_by_neginf(x8); - if( _spoil_scenario==30 ) - spoil_vector_by_deleting_element(x8); - p = 0.5; - if( _spoil_scenario==31 ) - p = fp_nan; - if( _spoil_scenario==32 ) - p = fp_posinf; - if( _spoil_scenario==33 ) - p = fp_neginf; - samplepercentile(x8, 10, p, v); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "basestat_t_base"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST basestat_t_covcorr - // Tests ability to detect errors in inputs - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<126; _spoil_scenario++) - { - try - { - double v; - real_2d_array c; - - // - // 2-sample short-form cov/corr are tested - // - real_1d_array x1 = "[0,1,4,9,16,25,36,49,64,81]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x1); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x1); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x1); - if( _spoil_scenario==3 ) - spoil_vector_by_adding_element(x1); - if( _spoil_scenario==4 ) - spoil_vector_by_deleting_element(x1); - real_1d_array y1 = "[0,1,2,3,4,5,6,7,8,9]"; - if( _spoil_scenario==5 ) - spoil_vector_by_nan(y1); - if( _spoil_scenario==6 ) - spoil_vector_by_posinf(y1); - if( _spoil_scenario==7 ) - spoil_vector_by_neginf(y1); - if( _spoil_scenario==8 ) - spoil_vector_by_adding_element(y1); - if( _spoil_scenario==9 ) - spoil_vector_by_deleting_element(y1); - v = cov2(x1, y1); - real_1d_array x2 = "[0,1,4,9,16,25,36,49,64,81]"; - if( _spoil_scenario==10 ) - spoil_vector_by_nan(x2); - if( _spoil_scenario==11 ) - spoil_vector_by_posinf(x2); - if( _spoil_scenario==12 ) - spoil_vector_by_neginf(x2); - if( _spoil_scenario==13 ) - spoil_vector_by_adding_element(x2); - if( _spoil_scenario==14 ) - spoil_vector_by_deleting_element(x2); - real_1d_array y2 = "[0,1,2,3,4,5,6,7,8,9]"; - if( _spoil_scenario==15 ) - spoil_vector_by_nan(y2); - if( _spoil_scenario==16 ) - spoil_vector_by_posinf(y2); - if( _spoil_scenario==17 ) - spoil_vector_by_neginf(y2); - if( _spoil_scenario==18 ) - spoil_vector_by_adding_element(y2); - if( _spoil_scenario==19 ) - spoil_vector_by_deleting_element(y2); - v = pearsoncorr2(x2, y2); - real_1d_array x3 = "[0,1,4,9,16,25,36,49,64,81]"; - if( _spoil_scenario==20 ) - spoil_vector_by_nan(x3); - if( _spoil_scenario==21 ) - spoil_vector_by_posinf(x3); - if( _spoil_scenario==22 ) - spoil_vector_by_neginf(x3); - if( _spoil_scenario==23 ) - spoil_vector_by_adding_element(x3); - if( _spoil_scenario==24 ) - spoil_vector_by_deleting_element(x3); - real_1d_array y3 = "[0,1,2,3,4,5,6,7,8,9]"; - if( _spoil_scenario==25 ) - spoil_vector_by_nan(y3); - if( _spoil_scenario==26 ) - spoil_vector_by_posinf(y3); - if( _spoil_scenario==27 ) - spoil_vector_by_neginf(y3); - if( _spoil_scenario==28 ) - spoil_vector_by_adding_element(y3); - if( _spoil_scenario==29 ) - spoil_vector_by_deleting_element(y3); - v = spearmancorr2(x3, y3); - - // - // 2-sample full-form cov/corr are tested - // - real_1d_array x1a = "[0,1,4,9,16,25,36,49,64,81]"; - if( _spoil_scenario==30 ) - spoil_vector_by_nan(x1a); - if( _spoil_scenario==31 ) - spoil_vector_by_posinf(x1a); - if( _spoil_scenario==32 ) - spoil_vector_by_neginf(x1a); - if( _spoil_scenario==33 ) - spoil_vector_by_deleting_element(x1a); - real_1d_array y1a = "[0,1,2,3,4,5,6,7,8,9]"; - if( _spoil_scenario==34 ) - spoil_vector_by_nan(y1a); - if( _spoil_scenario==35 ) - spoil_vector_by_posinf(y1a); - if( _spoil_scenario==36 ) - spoil_vector_by_neginf(y1a); - if( _spoil_scenario==37 ) - spoil_vector_by_deleting_element(y1a); - v = cov2(x1a, y1a, 10); - real_1d_array x2a = "[0,1,4,9,16,25,36,49,64,81]"; - if( _spoil_scenario==38 ) - spoil_vector_by_nan(x2a); - if( _spoil_scenario==39 ) - spoil_vector_by_posinf(x2a); - if( _spoil_scenario==40 ) - spoil_vector_by_neginf(x2a); - if( _spoil_scenario==41 ) - spoil_vector_by_deleting_element(x2a); - real_1d_array y2a = "[0,1,2,3,4,5,6,7,8,9]"; - if( _spoil_scenario==42 ) - spoil_vector_by_nan(y2a); - if( _spoil_scenario==43 ) - spoil_vector_by_posinf(y2a); - if( _spoil_scenario==44 ) - spoil_vector_by_neginf(y2a); - if( _spoil_scenario==45 ) - spoil_vector_by_deleting_element(y2a); - v = pearsoncorr2(x2a, y2a, 10); - real_1d_array x3a = "[0,1,4,9,16,25,36,49,64,81]"; - if( _spoil_scenario==46 ) - spoil_vector_by_nan(x3a); - if( _spoil_scenario==47 ) - spoil_vector_by_posinf(x3a); - if( _spoil_scenario==48 ) - spoil_vector_by_neginf(x3a); - if( _spoil_scenario==49 ) - spoil_vector_by_deleting_element(x3a); - real_1d_array y3a = "[0,1,2,3,4,5,6,7,8,9]"; - if( _spoil_scenario==50 ) - spoil_vector_by_nan(y3a); - if( _spoil_scenario==51 ) - spoil_vector_by_posinf(y3a); - if( _spoil_scenario==52 ) - spoil_vector_by_neginf(y3a); - if( _spoil_scenario==53 ) - spoil_vector_by_deleting_element(y3a); - v = spearmancorr2(x3a, y3a, 10); - - // - // vector short-form cov/corr are tested. - // - real_2d_array x4 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]"; - if( _spoil_scenario==54 ) - spoil_matrix_by_nan(x4); - if( _spoil_scenario==55 ) - spoil_matrix_by_posinf(x4); - if( _spoil_scenario==56 ) - spoil_matrix_by_neginf(x4); - covm(x4, c); - real_2d_array x5 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]"; - if( _spoil_scenario==57 ) - spoil_matrix_by_nan(x5); - if( _spoil_scenario==58 ) - spoil_matrix_by_posinf(x5); - if( _spoil_scenario==59 ) - spoil_matrix_by_neginf(x5); - pearsoncorrm(x5, c); - real_2d_array x6 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]"; - if( _spoil_scenario==60 ) - spoil_matrix_by_nan(x6); - if( _spoil_scenario==61 ) - spoil_matrix_by_posinf(x6); - if( _spoil_scenario==62 ) - spoil_matrix_by_neginf(x6); - spearmancorrm(x6, c); - - // - // vector full-form cov/corr are tested. - // - real_2d_array x7 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]"; - if( _spoil_scenario==63 ) - spoil_matrix_by_nan(x7); - if( _spoil_scenario==64 ) - spoil_matrix_by_posinf(x7); - if( _spoil_scenario==65 ) - spoil_matrix_by_neginf(x7); - if( _spoil_scenario==66 ) - spoil_matrix_by_deleting_row(x7); - if( _spoil_scenario==67 ) - spoil_matrix_by_deleting_col(x7); - covm(x7, 5, 3, c); - real_2d_array x8 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]"; - if( _spoil_scenario==68 ) - spoil_matrix_by_nan(x8); - if( _spoil_scenario==69 ) - spoil_matrix_by_posinf(x8); - if( _spoil_scenario==70 ) - spoil_matrix_by_neginf(x8); - if( _spoil_scenario==71 ) - spoil_matrix_by_deleting_row(x8); - if( _spoil_scenario==72 ) - spoil_matrix_by_deleting_col(x8); - pearsoncorrm(x8, 5, 3, c); - real_2d_array x9 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]"; - if( _spoil_scenario==73 ) - spoil_matrix_by_nan(x9); - if( _spoil_scenario==74 ) - spoil_matrix_by_posinf(x9); - if( _spoil_scenario==75 ) - spoil_matrix_by_neginf(x9); - if( _spoil_scenario==76 ) - spoil_matrix_by_deleting_row(x9); - if( _spoil_scenario==77 ) - spoil_matrix_by_deleting_col(x9); - spearmancorrm(x9, 5, 3, c); - - // - // cross-vector short-form cov/corr are tested. - // - real_2d_array x10 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]"; - if( _spoil_scenario==78 ) - spoil_matrix_by_nan(x10); - if( _spoil_scenario==79 ) - spoil_matrix_by_posinf(x10); - if( _spoil_scenario==80 ) - spoil_matrix_by_neginf(x10); - real_2d_array y10 = "[[2,3],[2,1],[-1,6],[-9,9],[7,1]]"; - if( _spoil_scenario==81 ) - spoil_matrix_by_nan(y10); - if( _spoil_scenario==82 ) - spoil_matrix_by_posinf(y10); - if( _spoil_scenario==83 ) - spoil_matrix_by_neginf(y10); - covm2(x10, y10, c); - real_2d_array x11 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]"; - if( _spoil_scenario==84 ) - spoil_matrix_by_nan(x11); - if( _spoil_scenario==85 ) - spoil_matrix_by_posinf(x11); - if( _spoil_scenario==86 ) - spoil_matrix_by_neginf(x11); - real_2d_array y11 = "[[2,3],[2,1],[-1,6],[-9,9],[7,1]]"; - if( _spoil_scenario==87 ) - spoil_matrix_by_nan(y11); - if( _spoil_scenario==88 ) - spoil_matrix_by_posinf(y11); - if( _spoil_scenario==89 ) - spoil_matrix_by_neginf(y11); - pearsoncorrm2(x11, y11, c); - real_2d_array x12 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]"; - if( _spoil_scenario==90 ) - spoil_matrix_by_nan(x12); - if( _spoil_scenario==91 ) - spoil_matrix_by_posinf(x12); - if( _spoil_scenario==92 ) - spoil_matrix_by_neginf(x12); - real_2d_array y12 = "[[2,3],[2,1],[-1,6],[-9,9],[7,1]]"; - if( _spoil_scenario==93 ) - spoil_matrix_by_nan(y12); - if( _spoil_scenario==94 ) - spoil_matrix_by_posinf(y12); - if( _spoil_scenario==95 ) - spoil_matrix_by_neginf(y12); - spearmancorrm2(x12, y12, c); - - // - // cross-vector full-form cov/corr are tested. - // - real_2d_array x13 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]"; - if( _spoil_scenario==96 ) - spoil_matrix_by_nan(x13); - if( _spoil_scenario==97 ) - spoil_matrix_by_posinf(x13); - if( _spoil_scenario==98 ) - spoil_matrix_by_neginf(x13); - if( _spoil_scenario==99 ) - spoil_matrix_by_deleting_row(x13); - if( _spoil_scenario==100 ) - spoil_matrix_by_deleting_col(x13); - real_2d_array y13 = "[[2,3],[2,1],[-1,6],[-9,9],[7,1]]"; - if( _spoil_scenario==101 ) - spoil_matrix_by_nan(y13); - if( _spoil_scenario==102 ) - spoil_matrix_by_posinf(y13); - if( _spoil_scenario==103 ) - spoil_matrix_by_neginf(y13); - if( _spoil_scenario==104 ) - spoil_matrix_by_deleting_row(y13); - if( _spoil_scenario==105 ) - spoil_matrix_by_deleting_col(y13); - covm2(x13, y13, 5, 3, 2, c); - real_2d_array x14 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]"; - if( _spoil_scenario==106 ) - spoil_matrix_by_nan(x14); - if( _spoil_scenario==107 ) - spoil_matrix_by_posinf(x14); - if( _spoil_scenario==108 ) - spoil_matrix_by_neginf(x14); - if( _spoil_scenario==109 ) - spoil_matrix_by_deleting_row(x14); - if( _spoil_scenario==110 ) - spoil_matrix_by_deleting_col(x14); - real_2d_array y14 = "[[2,3],[2,1],[-1,6],[-9,9],[7,1]]"; - if( _spoil_scenario==111 ) - spoil_matrix_by_nan(y14); - if( _spoil_scenario==112 ) - spoil_matrix_by_posinf(y14); - if( _spoil_scenario==113 ) - spoil_matrix_by_neginf(y14); - if( _spoil_scenario==114 ) - spoil_matrix_by_deleting_row(y14); - if( _spoil_scenario==115 ) - spoil_matrix_by_deleting_col(y14); - pearsoncorrm2(x14, y14, 5, 3, 2, c); - real_2d_array x15 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]"; - if( _spoil_scenario==116 ) - spoil_matrix_by_nan(x15); - if( _spoil_scenario==117 ) - spoil_matrix_by_posinf(x15); - if( _spoil_scenario==118 ) - spoil_matrix_by_neginf(x15); - if( _spoil_scenario==119 ) - spoil_matrix_by_deleting_row(x15); - if( _spoil_scenario==120 ) - spoil_matrix_by_deleting_col(x15); - real_2d_array y15 = "[[2,3],[2,1],[-1,6],[-9,9],[7,1]]"; - if( _spoil_scenario==121 ) - spoil_matrix_by_nan(y15); - if( _spoil_scenario==122 ) - spoil_matrix_by_posinf(y15); - if( _spoil_scenario==123 ) - spoil_matrix_by_neginf(y15); - if( _spoil_scenario==124 ) - spoil_matrix_by_deleting_row(y15); - if( _spoil_scenario==125 ) - spoil_matrix_by_deleting_col(y15); - spearmancorrm2(x15, y15, 5, 3, 2, c); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "basestat_t_covcorr"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST ssa_d_basic - // Simple SSA analysis demo - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++) - { - try - { - // - // Here we demonstrate SSA trend/noise separation for some toy problem: - // small monotonically growing series X are analyzed with 3-tick window - // and "top-K" version of SSA, which selects K largest singular vectors - // for analysis, with K=1. - // - ssamodel s; - real_1d_array x = "[0,0.5,1,1,1.5,2]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - - // - // First, we create SSA model, set its properties and add dataset. - // - // We use window with width=3 and configure model to use direct SSA - // algorithm - one which runs exact O(N*W^2) analysis - to extract - // one top singular vector. Well, it is toy problem :) - // - // NOTE: SSA model may store and analyze more than one sequence - // (say, different sequences may correspond to data collected - // from different devices) - // - ssacreate(s); - ssasetwindow(s, 3); - ssaaddsequence(s, x); - ssasetalgotopkdirect(s, 1); - - // - // Now we begin analysis. Internally SSA model stores everything it needs: - // data, settings, solvers and so on. Right after first call to analysis- - // related function it will analyze dataset, build basis and perform analysis. - // - // Subsequent calls to analysis functions will reuse previously computed - // basis, unless you invalidate it by changing model settings (or dataset). - // - real_1d_array trend; - real_1d_array noise; - ssaanalyzesequence(s, x, trend, noise); - _TestResult = _TestResult && doc_test_real_vector(trend, "[0.3815,0.5582,0.7810,1.0794,1.5041,2.0105]", 0.005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "ssa_d_basic"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST ssa_d_forecast - // Simple SSA forecasting demo - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++) - { - try - { - // - // Here we demonstrate SSA forecasting on some toy problem with clearly - // visible linear trend and small amount of noise. - // - ssamodel s; - real_1d_array x = "[0.05,0.96,2.04,3.11,3.97,5.03,5.98,7.02,8.02]"; - if( _spoil_scenario==0 ) - spoil_vector_by_nan(x); - if( _spoil_scenario==1 ) - spoil_vector_by_posinf(x); - if( _spoil_scenario==2 ) - spoil_vector_by_neginf(x); - - // - // First, we create SSA model, set its properties and add dataset. - // - // We use window with width=3 and configure model to use direct SSA - // algorithm - one which runs exact O(N*W^2) analysis - to extract - // two top singular vectors. Well, it is toy problem :) - // - // NOTE: SSA model may store and analyze more than one sequence - // (say, different sequences may correspond to data collected - // from different devices) - // - ssacreate(s); - ssasetwindow(s, 3); - ssaaddsequence(s, x); - ssasetalgotopkdirect(s, 2); - - // - // Now we begin analysis. Internally SSA model stores everything it needs: - // data, settings, solvers and so on. Right after first call to analysis- - // related function it will analyze dataset, build basis and perform analysis. - // - // Subsequent calls to analysis functions will reuse previously computed - // basis, unless you invalidate it by changing model settings (or dataset). - // - // In this example we show how to use ssaforecastlast() function, which - // predicts changed in the last sequence of the dataset. If you want to - // perform prediction for some other sequence, use ssaforecastsequence(). - // - real_1d_array trend; - ssaforecastlast(s, 3, trend); - - // - // Well, we expected it to be [9,10,11]. There exists some difference, - // which can be explained by the artificial noise in the dataset. - // - _TestResult = _TestResult && doc_test_real_vector(trend, "[9.0005,9.9322,10.8051]", 0.005); - _TestResult = _TestResult && (_spoil_scenario==-1); - } - catch(ap_error) - { _TestResult = _TestResult && (_spoil_scenario!=-1); } - } - if( !_TestResult) - { - printf("%-32s FAILED\n", "ssa_d_forecast"); - fflush(stdout); - } - _TotalResult = _TotalResult && _TestResult; - - - // - // TEST ssa_d_realtime - // Real-time SSA algorithm with fast incremental updates - // - _TestResult = true; - for(_spoil_scenario=-1; _spoil_scenario<9; _spoil_scenario++) - { - try - { - // - // Suppose that you have a constant stream of incoming data, and you want - // to regularly perform singular spectral analysis of this stream. - // - // One full run of direct algorithm costs O(N*Width^2) operations, so - // the more points you have, the more it costs to rebuild basis from - // scratch. - // - // Luckily we have incremental SSA algorithm which can perform quick - // updates of already computed basis in O(K*Width^2) ops, where K - // is a number of singular vectors extracted. Usually it is orders of - // magnitude faster than full update of the basis. - // - // In this example we start from some initial dataset x0. Then we - // start appending elements one by one to the end of the last sequence. - // - // NOTE: direct algorithm also supports incremental updates, but - // with O(Width^3) cost. Typically K<